HDLRuby 2.2.14 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a6a6e334b6e55bdc8f7947f92f4dd8a9de83fc0f90725bad5bfafedc27a8ca2e
4
- data.tar.gz: a6f43c383176d02af9e8491c6b2425b5e1e8ca3c339464842dbf288fbe91dc26
3
+ metadata.gz: bb0edfa902fbbc4e330f9a7fd8c26dcfc745f8ce5eb8cd73e4c2047cfef7dc68
4
+ data.tar.gz: 5ddc2948c53b905fb25c0683fc31be5300a2aabff31384c9187dc784c9e66a76
5
5
  SHA512:
6
- metadata.gz: 50a46ad334407428425912ec7b1fbd745d1de686e8792548524f23d4ca10f6252368b589f5fc77b201b07f1becf86aa7c234c77443b1014caad341c1fa0fa966
7
- data.tar.gz: c8defb6937e32d43ddd0c56f49a2a608a8444a8ca0eef10f387fb1fc89597dc13871ce086223e8d1892799d1518d9a5cf915142e500cf4c74937bdfbfff68514
6
+ metadata.gz: 93f86b91bf94ad22b4558ac912f950e79ec9373fafcdcaf2d33e8f1c34f3b77d30beec308f591d95f7ddafdcfda5bd283586216a98c882e12983fbe7301f43df
7
+ data.tar.gz: 60503ed5b5d45406827329bd6f42b961b9b6c74f47c630f7f0f21bd4d51bcbabffb380608c2287ee7dd8b60b5bb2039eaddd82357920eff3f6b437b40d59d34a
data/README.md CHANGED
@@ -1301,14 +1301,7 @@ __The vector operator__ `[]` is used for building types representing vectors of
1301
1301
  <type>[<range>]
1302
1302
  ```
1303
1303
 
1304
- The `<range>` of a vector type indicates the position of the starting and ending bits relatively to the radix point. If the position of the starting bit
1305
- is on the left side of the range, the vector is big endian, otherwise it is little endian. Negative values in a range are also possible and indicate positions bellow the radix point. For example, the following code describes a big-endian fixed-point type with 8 bits above the radix point and 4 bits
1306
- bellow:
1307
-
1308
- ```ruby
1309
- bit[7..-4]
1310
- ```
1311
-
1304
+ The `<range>` of a vector type indicates the position of the starting and ending bits.
1312
1305
  A `n..0` range can also be abbreviated to `n+1`. For instance, the two following types are identical:
1313
1306
 
1314
1307
  ```ruby
@@ -2801,6 +2794,19 @@ bit[4,4].inner :sig
2801
2794
 
2802
2795
  When performing computation with fixed point types, HDLRuby ensures that the result's decimal point position is correct.
2803
2796
 
2797
+ In addition to the fixed point data type, a method is added to the literal objects (Numeric) to convert them to fixed point representation:
2798
+
2799
+ ```ruby
2800
+ <litteral>.to_fix(<number of bits after the decimal point>)
2801
+ ```
2802
+
2803
+ For example the following code converts a floating point value to a fixed point value with 16 bits after the decimal point:
2804
+
2805
+ ```
2806
+ 3.178.to_fix(16)
2807
+ ```
2808
+
2809
+
2804
2810
  ## Channel
2805
2811
  <a name="channel"></a>
2806
2812
 
@@ -0,0 +1,235 @@
1
+ require 'std/memory.rb'
2
+ require 'std/linear.rb'
3
+
4
+ include HDLRuby::High::Std
5
+
6
+ # Tries for matrix-vector product.
7
+
8
+
9
+
10
+
11
+
12
+ # Sample code for testing the linear library.
13
+
14
+ system :linear_test do
15
+
16
+ # Clock and reset.
17
+ inner :clk,:rst
18
+
19
+ # Request and acknoledge signals.
20
+ inner :req
21
+ [8].inner :ack
22
+
23
+
24
+ # Circuit for testing the scaling.
25
+
26
+ # Input memory
27
+ mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_scale_in)
28
+ # Output memory
29
+ mem_file([8],8,clk,rst, winc: :rst).(:mem_scale_out)
30
+ # Access ports.
31
+ mem_scale_in.branch(:anum).inner :mem_scale_inP
32
+ mem_scale_inPs = 8.times.map { |i| mem_scale_inP.wrap(i) }
33
+ mem_scale_out.branch(:anum).inner :mem_scale_outP
34
+ mem_scale_outPs = 8.times.map { |i| mem_scale_outP.wrap(i) }
35
+
36
+ # Build the scaler.
37
+ scale([8],clk.posedge,req,ack[0],channel_port(3),
38
+ mem_scale_inPs,mem_scale_outPs)
39
+
40
+
41
+ # Circuit for testing the parallel addition.
42
+
43
+ # Input memories
44
+ mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_addn_left_in)
45
+ mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_addn_right_in)
46
+ # Output memory
47
+ mem_file([8],8,clk,rst, winc: :rst).(:mem_addn_out)
48
+ # Access ports.
49
+ mem_addn_left_in.branch(:anum).inner :mem_addn_left_inP
50
+ mem_addn_left_inPs = 8.times.map { |i| mem_addn_left_inP.wrap(i) }
51
+ mem_addn_right_in.branch(:anum).inner :mem_addn_right_inP
52
+ mem_addn_right_inPs = 8.times.map { |i| mem_addn_right_inP.wrap(i) }
53
+ mem_addn_out.branch(:anum).inner :mem_addn_outP
54
+ mem_addn_outPs = 8.times.map { |i| mem_addn_outP.wrap(i) }
55
+
56
+ # Build the adder.
57
+ add_n([8],clk.posedge,ack[0],ack[1],mem_addn_left_inPs,
58
+ mem_addn_right_inPs,mem_addn_outPs)
59
+
60
+
61
+ # Circuit for testing the parallel multiplication.
62
+
63
+ # Input memories
64
+ mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_muln_left_in)
65
+ mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_muln_right_in)
66
+ # Output memory
67
+ mem_file([8],8,clk,rst, winc: :rst).(:mem_muln_out)
68
+ # Access ports.
69
+ mem_muln_left_in.branch(:anum).inner :mem_muln_left_inP
70
+ mem_muln_left_inPs = 8.times.map { |i| mem_muln_left_inP.wrap(i) }
71
+ mem_muln_right_in.branch(:anum).inner :mem_muln_right_inP
72
+ mem_muln_right_inPs = 8.times.map { |i| mem_muln_right_inP.wrap(i) }
73
+ mem_muln_out.branch(:anum).inner :mem_muln_outP
74
+ mem_muln_outPs = 8.times.map { |i| mem_muln_outP.wrap(i) }
75
+
76
+ # Build the multer.
77
+ mul_n([8],clk.posedge,ack[1],ack[2],mem_muln_left_inPs,
78
+ mem_muln_right_inPs,mem_muln_outPs)
79
+
80
+
81
+ # Circuit for testing the mac
82
+ # Output signal.
83
+ [8].inner :acc
84
+
85
+ # Build the mac.
86
+ mac([8],clk.posedge,ack[2],ack[3],channel_port(5), channel_port(6),
87
+ channel_port(acc))
88
+
89
+
90
+ # Circuit for testing the parallel mac.
91
+ # Input memory
92
+ mem_file([8],8,clk,rst, winc: :rst).(:mem_macn1_left_in)
93
+ # Output memory
94
+ mem_file([8],8,clk,rst, winc: :rst).(:mem_macn1_out)
95
+ # Access ports.
96
+ mem_macn1_left_in.branch(:anum).inner :mem_macn1_left_inP
97
+ mem_macn1_left_inPs = 8.times.map { |i| mem_macn1_left_inP.wrap(i) }
98
+ mem_macn1_out.branch(:anum).inner :mem_macn1_outP
99
+ mem_macn1_outPs = 8.times.map { |i| mem_macn1_outP.wrap(i) }
100
+
101
+ # Build the mac.
102
+ mac_n1([8],clk.posedge,ack[3],ack[4], mem_macn1_left_inPs,
103
+ channel_port(5), mem_macn1_outPs)
104
+
105
+ # Circuit for testing the linearun with mac.
106
+ # Input memories
107
+ mem_dual([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_macrn_left_in)
108
+ mem_dual([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_macrn_right_in)
109
+ # Access ports.
110
+ mem_macrn_left_in.branch(:rinc).inner :mem_macrn_left_in_readP
111
+ mem_macrn_right_in.branch(:rinc).inner :mem_macrn_right_in_readP
112
+ # Output signal.
113
+ [8].inner :accr
114
+
115
+ # Build the linearun mac.
116
+ linearun(8,clk.posedge,ack[4],ack[5]) do |ev,req,ack|
117
+ mac([8],ev,req,ack,mem_macrn_left_in_readP,mem_macrn_right_in_readP,
118
+ channel_port(accr))
119
+ end
120
+
121
+
122
+ # The memory initializer.
123
+ # Writing ports
124
+ mem_scale_in.branch(:winc).inner :mem_scale_in_writeP
125
+ mem_addn_left_in.branch(:winc).inner :mem_addn_left_in_writeP
126
+ mem_addn_right_in.branch(:winc).inner :mem_addn_right_in_writeP
127
+ mem_muln_left_in.branch(:winc).inner :mem_muln_left_in_writeP
128
+ mem_muln_right_in.branch(:winc).inner :mem_muln_right_in_writeP
129
+ mem_macn1_left_in.branch(:winc).inner :mem_macn1_left_in_writeP
130
+ mem_macrn_left_in.branch(:winc).inner :mem_macrn_left_in_writeP
131
+ mem_macrn_right_in.branch(:winc).inner :mem_macrn_right_in_writeP
132
+ # Filling index
133
+ [8].inner :idx
134
+ # Filling counter
135
+ [3].inner :cnt
136
+ # Filling value
137
+ [8].inner :val
138
+
139
+ # Start flag
140
+ inner :start
141
+
142
+ # The execution process
143
+ par(clk.posedge) do
144
+ hif(rst) { cnt <= 0; val <= 0 }
145
+ helse do
146
+ # Step index processing.
147
+ hif(cnt == 7) do
148
+ hif(idx < 8) { idx <= idx + 1 }
149
+ end
150
+ # Memory filling steps.
151
+ hcase(idx)
152
+ hwhen(0) do
153
+ mem_scale_in_writeP.write(val) do
154
+ cnt <= cnt + 1; val <= val + 1
155
+ end
156
+ end
157
+ hwhen(1) do
158
+ mem_addn_left_in_writeP.write(val) do
159
+ cnt <= cnt + 1; val <= val + 1
160
+ end
161
+ end
162
+ hwhen(2) do
163
+ mem_addn_right_in_writeP.write(val) do
164
+ cnt <= cnt + 1; val <= val + 1
165
+ end
166
+ end
167
+ hwhen(3) do
168
+ mem_muln_left_in_writeP.write(val-24) do
169
+ cnt <= cnt + 1; val <= val + 1
170
+ end
171
+ end
172
+ hwhen(4) do
173
+ mem_muln_right_in_writeP.write(val-24) do
174
+ cnt <= cnt + 1; val <= val + 1
175
+ end
176
+ end
177
+ hwhen(5) do
178
+ mem_macn1_left_in_writeP.write(val-32) do
179
+ cnt <= cnt + 1; val <= val + 1
180
+ end
181
+ end
182
+ hwhen(6) do
183
+ mem_macrn_left_in_writeP.write(val-48) do
184
+ cnt <= cnt + 1; val <= val + 1
185
+ end
186
+ end
187
+ hwhen(7) do
188
+ mem_macrn_right_in_writeP.write(val-48) do
189
+ cnt <= cnt + 1; val <= val + 1
190
+ end
191
+ end
192
+ # Computation steps.
193
+ helse do
194
+ hif(start) do
195
+ req <= 1
196
+ start <= 0
197
+ end
198
+ helse { req <= 0 }
199
+ end
200
+ end
201
+ end
202
+
203
+
204
+ # The test bench.
205
+ timed do
206
+ req <= 0
207
+ ack <= 0
208
+ clk <= 0
209
+ rst <= 0
210
+ cnt <= 0
211
+ idx <= 0
212
+ val <= 0
213
+ start <= 0
214
+ !10.ns
215
+ clk <= 1
216
+ !10.ns
217
+ # Reset
218
+ clk <= 0
219
+ rst <= 1
220
+ !10.ns
221
+ clk <= 1
222
+ !10.ns
223
+ clk <= 0
224
+ rst <= 0
225
+ start <= 1
226
+ !10.ns
227
+ # Run
228
+ 128.times do
229
+ clk <= 1
230
+ !10.ns
231
+ clk <= 0
232
+ !10.ns
233
+ end
234
+ end
235
+ end
@@ -4,8 +4,8 @@ system :rom4_8 do
4
4
  [2..0].input :addr
5
5
  [7..0].output :data0,:data1,:data2
6
6
 
7
- bit[7..0][0..7].constant content0: [1,2,3,4,5,6,7]
8
- bit[7..0][-8].constant content1: [1,2,3,4,5,6,7]
7
+ bit[7..0][0..7].constant content0: [0,1,2,3,4,5,6,7]
8
+ bit[7..0][-8].constant content1: [0,1,2,3,4,5,6,7]
9
9
  bit[7..0][-8].constant content2: (8).times.to_a
10
10
 
11
11
  data0 <= content0[addr]
@@ -0,0 +1,96 @@
1
+ require 'std/memory.rb'
2
+ require 'std/linear.rb'
3
+ # require 'std/timing.rb'
4
+
5
+ include HDLRuby::High::Std
6
+
7
+
8
+ system :fir do |typ,iChannel,oChannel,coefs|
9
+ input :clk, :rst, :req
10
+ output :ack
11
+ # Declare the input port.
12
+ iChannel.input :iPort
13
+ # Declare the output port.
14
+ oChannel.output :oPort
15
+
16
+ # Declares the data registers.
17
+ datas = coefs.map.with_index do |coef,id|
18
+ coef.type.inner :"data_#{id}"
19
+ end
20
+
21
+ inner :req2
22
+
23
+
24
+ # Generate the mac pipeline.
25
+ mac_np(typ,clk.posedge,req2,ack,
26
+ datas.map{|data| channel_port(data) },
27
+ coefs.map{|coef| channel_port(coef) }, oPort)
28
+
29
+ # Generate the data transfer through the pipeline.
30
+ par(clk.posedge) do
31
+ req2 <= 0
32
+ hif(rst) { datas.each { |d| d <= 0 } }
33
+ hif(req) do
34
+ iPort.read(datas[0]) do
35
+ # datas.each_cons(2) { |d0,d1| d1 <= d0 }
36
+ datas[1..-1] <= datas[0..-2]
37
+ end
38
+ req2 <= 1
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+
45
+
46
+
47
+ system :work do
48
+
49
+ inner :clk,:rst,:req,:ack
50
+
51
+ # The input memory.
52
+ mem_rom([8],8,clk,rst,
53
+ [_00000001,_00000010,_00000011,_00000100,
54
+ _00000101,_00000110,_00000111,_00001000]).(:iMem)
55
+ # The output memory.
56
+ mem_dual([8],8,clk,rst).(:oMem)
57
+ # The coefficients.
58
+ coefs = [_11001100,_00110011,_10101010,_01010101,
59
+ _11110000,_00001111,_11100011,_00011100]
60
+
61
+ # The filter
62
+ fir([8],iMem.branch(:rinc),oMem.branch(:winc),coefs).(:my_fir).(clk,rst,req,ack)
63
+
64
+ # iMem.branch(:rinc).inner :port
65
+ # [8].inner :a
66
+ # par(clk.posedge) do
67
+ # hif(req) { port.read(a) }
68
+ # end
69
+
70
+ timed do
71
+ req <= 0
72
+ clk <= 0
73
+ rst <= 0
74
+ !10.ns
75
+ clk <= 1
76
+ !10.ns
77
+ clk <= 0
78
+ rst <= 1
79
+ !10.ns
80
+ clk <= 1
81
+ !10.ns
82
+ clk <= 0
83
+ rst <= 0
84
+ !10.ns
85
+ clk <= 1
86
+ !10.ns
87
+ req <= 1
88
+ clk <= 0
89
+ 64.times do
90
+ !10.ns
91
+ clk <= 1
92
+ !10.ns
93
+ clk <= 0
94
+ end
95
+ end
96
+ end
@@ -12,8 +12,9 @@ system :fix_test do
12
12
 
13
13
  # Performs calculation between then
14
14
  timed do
15
- x <= _00110011
16
- y <= _01000000
15
+ # x <= _00110011 # 3.1875
16
+ x <= 3.1875.to_fix(4)
17
+ y <= _01000000 # 4
17
18
  !10.ns
18
19
  z <= x + y
19
20
  !10.ns
@@ -0,0 +1,166 @@
1
+ require 'std/memory.rb'
2
+ require 'std/linear.rb'
3
+
4
+ include HDLRuby::High::Std
5
+
6
+ # Tries for matrix-vector product.
7
+
8
+
9
+
10
+
11
+
12
+ # Testing.
13
+ system :testmat do
14
+
15
+ inner :clk,:rst, :req
16
+
17
+ # Input memories
18
+ # mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memL0)
19
+ # The first memory is 4-bank for testing purpose.
20
+ mem_bank([8],4,256/4,clk,rst, rinc: :rst,winc: :rst).(:memL0)
21
+ # The others are standard dual-edge memories.
22
+ mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memL1)
23
+ mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memR)
24
+ # Access ports.
25
+ memL0.branch(:rinc).inner :readL0
26
+ memL1.branch(:rinc).inner :readL1
27
+ memR.branch(:rinc).inner :readR
28
+
29
+ # Prepares the left and acc arrays.
30
+ lefts = [readL0, readL1]
31
+
32
+ # Accumulators memory.
33
+ mem_file([8],2,clk,rst,rinc: :rst).(:memAcc)
34
+ memAcc.branch(:anum).inner :accs
35
+ accs_out = [accs.wrap(0), accs.wrap(1)]
36
+
37
+ # Layer 0 ack.
38
+ inner :ack0
39
+
40
+ # Instantiate the matrix product.
41
+ mac_n1([8],clk,req,ack0,lefts,readR,accs_out)
42
+
43
+ # Translation.
44
+ # Translation memory.
45
+ mem_file([8],2,clk,rst,winc: :rst).(:memT)
46
+ # Tarnslation result
47
+ mem_file([8],2,clk,rst,rinc: :rst).(:memF)
48
+ # Access ports.
49
+ memT.branch(:anum).inner :readT
50
+ memF.branch(:anum).inner :writeF
51
+ regRs = [ readT.wrap(0), readT.wrap(1) ]
52
+ regLs = [ accs.wrap(0), accs.wrap(1) ]
53
+ regs = [ writeF.wrap(0), writeF.wrap(1) ]
54
+
55
+ # Translater ack.
56
+ inner :ackT
57
+
58
+ # Instantiate the translater.
59
+ add_n([8],clk,ack0,ackT,regLs,regRs,regs)
60
+
61
+
62
+
63
+ # Second layer.
64
+ # Input memories.
65
+ mem_dual([8],2,clk,rst, rinc: :rst,winc: :rst).(:mem2L0)
66
+ # Access ports.
67
+ mem2L0.branch(:rinc).inner :read2L0
68
+ # memAcc.branch(:rinc).inner :accsR
69
+ memF.branch(:rinc).inner :readF
70
+
71
+ # Second layer ack.
72
+ inner :ack1
73
+
74
+ # Result.
75
+ [8].inner :res
76
+
77
+ sub do
78
+ # Instantiate the second matrix product.
79
+ # mac([8],clk,req,read2L0,accsR,res)
80
+ mac([8],clk,ackT,ack1,read2L0,readF,channel_port(res))
81
+ end
82
+
83
+
84
+
85
+ # The memory initializer.
86
+ memL0.branch(:winc).inner :writeL0
87
+ memL1.branch(:winc).inner :writeL1
88
+ memR.branch(:winc).inner :writeR
89
+ memT.branch(:winc).inner :writeT
90
+ mem2L0.branch(:winc).inner :write2L0
91
+ inner :fill, :fill2
92
+ [8].inner :val
93
+ par(clk.posedge) do
94
+ hif(fill) do
95
+ writeL0.write(val)
96
+ writeL1.write(val+1)
97
+ writeR.write(val+1)
98
+ end
99
+ hif(fill2) do
100
+ write2L0.write(val+2)
101
+ writeT.write(val+2)
102
+ end
103
+ end
104
+
105
+ timed do
106
+ req <= 0
107
+ clk <= 0
108
+ rst <= 0
109
+ fill <= 0
110
+ fill2 <= 0
111
+ val <= 0
112
+ !10.ns
113
+ # Reset the memories.
114
+ rst <= 1
115
+ !10.ns
116
+ clk <= 1
117
+ !10.ns
118
+ # Fill the memories.
119
+ # First layer
120
+ clk <= 0
121
+ rst <= 0
122
+ fill <= 1
123
+ !10.ns
124
+ 256.times do |i|
125
+ clk <= 1
126
+ !10.ns
127
+ clk <= 0
128
+ val <= val + 1
129
+ !10.ns
130
+ end
131
+ fill <= 0
132
+ clk <= 1
133
+ !10.ns
134
+ # Second layer
135
+ clk <= 0
136
+ rst <= 0
137
+ fill2 <= 1
138
+ !10.ns
139
+ 2.times do |i|
140
+ clk <= 1
141
+ !10.ns
142
+ clk <= 0
143
+ val <= val + 1
144
+ !10.ns
145
+ end
146
+ fill2 <= 0
147
+ clk <= 1
148
+ !10.ns
149
+ clk <= 0
150
+ !10.ns
151
+ clk <= 1
152
+ !10.ns
153
+ clk <= 0
154
+ !10.ns
155
+ # Launch the computation
156
+ clk <= 0
157
+ req <= 1
158
+ !10.ns
159
+ 300.times do
160
+ clk <= 1
161
+ !10.ns
162
+ clk <= 0
163
+ !10.ns
164
+ end
165
+ end
166
+ end