HDLRuby 2.2.14 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
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