HDLRuby 2.4.15 → 2.4.21
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 +4 -4
- data/lib/HDLRuby/hdr_samples/WithMultiChannelExpVerilog/with_multi_channels_hs_32.v +1277 -0
- data/lib/HDLRuby/hdr_samples/WithMultiChannelExpVerilog/with_multi_channels_qu_213.v +1345 -0
- data/lib/HDLRuby/hdr_samples/WithMultiChannelExpVerilog/with_multi_channels_qu_222.v +1339 -0
- data/lib/HDLRuby/hdr_samples/WithMultiChannelExpVerilog/with_multi_channels_rg_23.v +1248 -0
- data/lib/HDLRuby/hdr_samples/make_multi_channels_v.rb +24 -0
- data/lib/HDLRuby/hdr_samples/with_connector.rb +47 -7
- data/lib/HDLRuby/hdr_samples/with_connector_memory.rb +102 -0
- data/lib/HDLRuby/hdr_samples/with_multi_channels.rb +0 -12
- data/lib/HDLRuby/hruby_tools.rb +7 -1
- data/lib/HDLRuby/std/connector.rb +67 -5
- data/lib/HDLRuby/std/memory.rb +126 -3
- data/lib/HDLRuby/version.rb +1 -1
- metadata +8 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
# Script for generating the vcd files.
|
|
3
|
+
|
|
4
|
+
# The configuration scenarii
|
|
5
|
+
$scenarii = [
|
|
6
|
+
[:_clk2_clk2, :register], # 0
|
|
7
|
+
[:_clk2_nclk2, :register], # 1
|
|
8
|
+
[:_clk2_clk3, :register], # 2
|
|
9
|
+
[:_clk3_clk2, :register], # 3
|
|
10
|
+
[:_clk2_clk2, :handshake], # 4
|
|
11
|
+
[:_clk2_nclk2, :handshake], # 5
|
|
12
|
+
[:_clk2_clk3, :handshake], # 6
|
|
13
|
+
[:_clk3_clk2, :handshake], # 7
|
|
14
|
+
[:clk2_clk2_clk2, :queue], # 8
|
|
15
|
+
[:clk2_clk2_nclk2, :queue], # 9
|
|
16
|
+
[:clk1_clk2_clk3, :queue], # 10
|
|
17
|
+
[:clk3_clk2_clk1, :queue], # 11
|
|
18
|
+
[:clk2_clk3_clk1, :queue], # 12
|
|
19
|
+
[:clk2_clk1_clk3, :queue], # 13
|
|
20
|
+
]
|
|
21
|
+
$scenarii.each_with_index do |scenarii,i|
|
|
22
|
+
puts "scenario: [#{i}] #{scenarii}"
|
|
23
|
+
`bundle exec ../hdrcc.rb --verilog with_multi_channels.rb WithMultiChannelPaper.V#{i} #{i}`
|
|
24
|
+
end
|
|
@@ -125,9 +125,12 @@ end
|
|
|
125
125
|
# Module for testing the connector.
|
|
126
126
|
system :with_connectors do
|
|
127
127
|
inner :clk, :rst
|
|
128
|
-
|
|
128
|
+
|
|
129
|
+
# First tester.
|
|
130
|
+
[4].inner :counter
|
|
129
131
|
[4*4].inner :res
|
|
130
132
|
inner :ack_in, :ack_out
|
|
133
|
+
inner :dup_req, :dup_ack
|
|
131
134
|
|
|
132
135
|
# The input queue.
|
|
133
136
|
queue(bit[4],4,clk,rst).(:in_qu)
|
|
@@ -141,11 +144,27 @@ system :with_connectors do
|
|
|
141
144
|
queue(bit[4*4],4,clk,rst).(:out_qu)
|
|
142
145
|
|
|
143
146
|
# Connect the input queue to the middle queues.
|
|
144
|
-
duplicator(bit[4],clk.negedge,in_qu,mid_qus)
|
|
147
|
+
duplicator(bit[4],clk.negedge,in_qu,mid_qus,dup_req,dup_ack)
|
|
145
148
|
|
|
146
149
|
# Connect the middle queues to the output queue.
|
|
147
150
|
merger([bit[4]]*4,clk.negedge,mid_qus,out_qu)
|
|
148
151
|
|
|
152
|
+
|
|
153
|
+
# Second tester.
|
|
154
|
+
[4].inner :counterb
|
|
155
|
+
[4].inner :resb
|
|
156
|
+
inner :ack_inb0, :ack_inb1, :ack_outb
|
|
157
|
+
|
|
158
|
+
# The input queues.
|
|
159
|
+
queue(bit[4],4,clk,rst).(:in_qub0)
|
|
160
|
+
queue(bit[4],4,clk,rst).(:in_qub1)
|
|
161
|
+
|
|
162
|
+
# The output queue.
|
|
163
|
+
queue(bit[4],4,clk,rst).(:out_qub)
|
|
164
|
+
|
|
165
|
+
# Connect then with a serializer.
|
|
166
|
+
serializer(bit[4],clk.negedge,[in_qub0,in_qub1],out_qub)
|
|
167
|
+
|
|
149
168
|
# # Slow version, always work
|
|
150
169
|
# par(clk.posedge) do
|
|
151
170
|
# ack_in <= 0
|
|
@@ -171,25 +190,39 @@ system :with_connectors do
|
|
|
171
190
|
# Fast version but assumes connected channels are blocking
|
|
172
191
|
par(clk.posedge) do
|
|
173
192
|
ack_in <= 0
|
|
174
|
-
|
|
193
|
+
ack_inb0 <= 0
|
|
194
|
+
ack_inb1 <= 0
|
|
195
|
+
hif(rst) { counter <= 0; counterb <= 0 }
|
|
175
196
|
helse do
|
|
176
197
|
in_qu.write(counter) do
|
|
177
198
|
ack_in <= 1
|
|
178
199
|
counter <= counter + 1
|
|
179
200
|
end
|
|
180
201
|
hif(ack_in) do
|
|
181
|
-
# mid_qu0.read(res_0)
|
|
182
|
-
# mid_qu1.read(res_1)
|
|
183
|
-
# mid_qu2.read(res_2)
|
|
184
|
-
# mid_qu3.read(res_3)
|
|
185
202
|
out_qu.read(res)
|
|
186
203
|
end
|
|
204
|
+
hif(~ack_inb0) do
|
|
205
|
+
in_qub0.write(counterb) do
|
|
206
|
+
ack_inb0 <= 1
|
|
207
|
+
counterb <= counterb + 1
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
helse do
|
|
211
|
+
in_qub1.write(counterb) do
|
|
212
|
+
ack_inb1 <= 1
|
|
213
|
+
counterb <= counterb + 1
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
hif(ack_inb0 | ack_inb1) do
|
|
217
|
+
out_qub.read(resb)
|
|
218
|
+
end
|
|
187
219
|
end
|
|
188
220
|
end
|
|
189
221
|
|
|
190
222
|
timed do
|
|
191
223
|
clk <= 0
|
|
192
224
|
rst <= 0
|
|
225
|
+
dup_req <= 0
|
|
193
226
|
!10.ns
|
|
194
227
|
clk <= 1
|
|
195
228
|
!10.ns
|
|
@@ -204,6 +237,13 @@ system :with_connectors do
|
|
|
204
237
|
!10.ns
|
|
205
238
|
clk <= 0
|
|
206
239
|
rst <= 0
|
|
240
|
+
4.times do
|
|
241
|
+
!10.ns
|
|
242
|
+
clk <= 1
|
|
243
|
+
!10.ns
|
|
244
|
+
clk <= 0
|
|
245
|
+
end
|
|
246
|
+
dup_req <= 1
|
|
207
247
|
16.times do
|
|
208
248
|
!10.ns
|
|
209
249
|
clk <= 1
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'std/memory.rb'
|
|
2
|
+
require "std/fixpoint.rb"
|
|
3
|
+
require 'std/channel.rb'
|
|
4
|
+
require 'std/connector.rb'
|
|
5
|
+
|
|
6
|
+
include HDLRuby::High::Std
|
|
7
|
+
|
|
8
|
+
system :channel_connector do
|
|
9
|
+
# データ型の宣言
|
|
10
|
+
integer_width = 4 # 整数部のビット幅
|
|
11
|
+
decimal_width = 4 # 実数部のビット幅
|
|
12
|
+
address_width = 4 # lutのアドレスのビット幅
|
|
13
|
+
typ = signed[integer_width + decimal_width] # データ型
|
|
14
|
+
|
|
15
|
+
inputs_x = _00010011
|
|
16
|
+
inputs_h = _10100001
|
|
17
|
+
columns = [2, 2, 1]
|
|
18
|
+
|
|
19
|
+
inner :clk, # clock
|
|
20
|
+
:rst, # reset
|
|
21
|
+
:req, # request
|
|
22
|
+
:fill # 入力値のメモリへの書き込み
|
|
23
|
+
|
|
24
|
+
# inputs_x = quantize(inputs_x, typ, decimal_width)
|
|
25
|
+
# inputs_h = quantize(inputs_h, typ, decimal_width)
|
|
26
|
+
|
|
27
|
+
mem_rom(typ, columns[0], clk, rst, inputs_x, rinc: :rst, winc: :rst).(:rom_inputs_x) # 入力値を格納するrom(x)
|
|
28
|
+
|
|
29
|
+
mem_rom(typ, columns[0], clk, rst, inputs_h, rinc: :rst, winc: :rst).(:rom_inputs_h) # 入力値を格納するrom(h)
|
|
30
|
+
|
|
31
|
+
mem_dual(typ, columns[0], clk, rst, rinc: :rst, winc: :rst).(:ram_inputs_serializer) #
|
|
32
|
+
|
|
33
|
+
mem_dual(typ, columns[0]*2, clk, rst, rinc: :rst, winc: :rst).(:ram_inputs_merger) #
|
|
34
|
+
|
|
35
|
+
reader_inputs_x = rom_inputs_x.branch(:rinc) #入力値xの読みだし用branch
|
|
36
|
+
reader_inputs_h = rom_inputs_h.branch(:rinc) #入力値hの読みだし用branch
|
|
37
|
+
writer_inputs_serializer = ram_inputs_serializer.branch(:winc) #入力値を合成した値の書き込み用branch
|
|
38
|
+
writer_inputs_meger = ram_inputs_merger.branch(:winc) #入力値を合成した値の書き込み用branch
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
serializer(typ,clk.negedge,[reader_inputs_x,reader_inputs_h],writer_inputs_serializer)
|
|
42
|
+
|
|
43
|
+
mem_rom(typ, columns[0], clk, rst, inputs_x, rinc: :rst, winc: :rst).(:rom_inputs_r) # 入力値を格納するrom(x)
|
|
44
|
+
mem_dual(typ, columns[0], clk, rst, rinc: :rst, winc: :rst).(:ram_duplicator0) #
|
|
45
|
+
mem_dual(typ, columns[0], clk, rst, rinc: :rst, winc: :rst).(:ram_duplicator1) #
|
|
46
|
+
reader_inputs_r = rom_inputs_r.branch(:rinc)
|
|
47
|
+
writer_duplicator0 = ram_duplicator0.branch(:winc)
|
|
48
|
+
writer_duplicator1 = ram_duplicator1.branch(:winc)
|
|
49
|
+
|
|
50
|
+
duplicator(typ,clk.posedge,reader_inputs_r,[writer_duplicator0, writer_duplicator1])
|
|
51
|
+
|
|
52
|
+
timed do
|
|
53
|
+
# リセット
|
|
54
|
+
clk <= 0
|
|
55
|
+
rst <= 0
|
|
56
|
+
req <= 0
|
|
57
|
+
fill <= 0
|
|
58
|
+
!10.ps
|
|
59
|
+
|
|
60
|
+
# メモリ読み出し位置の初期化
|
|
61
|
+
rst <= 1
|
|
62
|
+
!10.ps
|
|
63
|
+
clk <= 1
|
|
64
|
+
!10.ps
|
|
65
|
+
clk <= 0
|
|
66
|
+
!10.ps
|
|
67
|
+
clk <= 1
|
|
68
|
+
!10.ps
|
|
69
|
+
|
|
70
|
+
# パラメータのメモリへの書き込み
|
|
71
|
+
clk <= 0
|
|
72
|
+
rst <= 0
|
|
73
|
+
fill <= 1
|
|
74
|
+
|
|
75
|
+
!10.ps
|
|
76
|
+
10.times do |i|
|
|
77
|
+
clk <= 1
|
|
78
|
+
!10.ps
|
|
79
|
+
clk <= 0
|
|
80
|
+
!10.ps
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
fill <= 0
|
|
84
|
+
clk <= 1
|
|
85
|
+
!10.ps
|
|
86
|
+
|
|
87
|
+
# 計算の実行
|
|
88
|
+
clk <= 0
|
|
89
|
+
req <= 1
|
|
90
|
+
!10.ps
|
|
91
|
+
clk <= 1
|
|
92
|
+
!10.ps
|
|
93
|
+
clk <= 0
|
|
94
|
+
!10.ps
|
|
95
|
+
30.times do
|
|
96
|
+
clk <= 1
|
|
97
|
+
!10.ps
|
|
98
|
+
clk <= 0
|
|
99
|
+
!10.ps
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -23,12 +23,6 @@ channel(:queue) do |typ,depth,clk,rst|
|
|
|
23
23
|
par(clk.posedge) do
|
|
24
24
|
hif(rst) { rptr <= 0; wptr <= 0 }
|
|
25
25
|
helse do
|
|
26
|
-
# hif(rsync) do
|
|
27
|
-
# hif(rptr != wptr) do
|
|
28
|
-
# rdata <= buffer[rptr]
|
|
29
|
-
# end
|
|
30
|
-
# end
|
|
31
|
-
# helse do
|
|
32
26
|
hif(~rsync) do
|
|
33
27
|
hif (~rreq) { rack <= 0 }
|
|
34
28
|
hif(rreq & (~rack) & (rptr != wptr)) do
|
|
@@ -38,10 +32,6 @@ channel(:queue) do |typ,depth,clk,rst|
|
|
|
38
32
|
end
|
|
39
33
|
end
|
|
40
34
|
|
|
41
|
-
# hif(wsync) do
|
|
42
|
-
# buffer[wptr] <= wdata
|
|
43
|
-
# end
|
|
44
|
-
# helse do
|
|
45
35
|
hif(~wsync) do
|
|
46
36
|
hif (~wreq) { wack <= 0 }
|
|
47
37
|
hif(wreq & (~wack) & (((wptr+1) % depth) != rptr)) do
|
|
@@ -67,7 +57,6 @@ channel(:queue) do |typ,depth,clk,rst|
|
|
|
67
57
|
end
|
|
68
58
|
seq do
|
|
69
59
|
hif(rptr != wptr) do
|
|
70
|
-
# target <= rdata
|
|
71
60
|
target <= buffer[rptr]
|
|
72
61
|
rptr <= (rptr + 1) % depth
|
|
73
62
|
blk.call if blk
|
|
@@ -102,7 +91,6 @@ channel(:queue) do |typ,depth,clk,rst|
|
|
|
102
91
|
wreq <= 0
|
|
103
92
|
end
|
|
104
93
|
hif(((wptr+1) % depth) != rptr) do
|
|
105
|
-
# wdata <= target
|
|
106
94
|
buffer[wptr] <= target
|
|
107
95
|
wptr <= (wptr + 1) % depth
|
|
108
96
|
blk.call if blk
|
data/lib/HDLRuby/hruby_tools.rb
CHANGED
|
@@ -29,8 +29,14 @@ module HDLRuby
|
|
|
29
29
|
class ::Integer
|
|
30
30
|
|
|
31
31
|
# Gets the bit width
|
|
32
|
+
# NOTE: returns infinity if the number is negative.
|
|
32
33
|
def width
|
|
33
|
-
return Math.log2(self+1).ceil
|
|
34
|
+
return self >= 0 ? Math.log2(self+1).ceil : 1.0/0.0
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Tells if the value is a power of 2.
|
|
38
|
+
def pow2?
|
|
39
|
+
return self > 0 && (self & (self - 1) == 0)
|
|
34
40
|
end
|
|
35
41
|
end
|
|
36
42
|
|
|
@@ -9,13 +9,28 @@ module HDLRuby::High::Std
|
|
|
9
9
|
# channel +in_ch+ and connect it to channels +out_chs+ with data of
|
|
10
10
|
# +typ+.
|
|
11
11
|
# The duplication is done according to event +ev+.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
# The optional req and ack arguments are the signals for controlling the
|
|
13
|
+
# duplicator using a handshake protocol. If set to nil, the duplicator
|
|
14
|
+
# runs automatically.
|
|
15
|
+
function :duplicator do |typ, ev, in_ch, out_chs, req = nil, ack = nil|
|
|
16
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
|
17
|
+
inner :in_ack
|
|
18
|
+
inner :in_req
|
|
15
19
|
out_acks = out_chs.size.times.map { |i| inner(:"out_ack#{i}") }
|
|
16
20
|
typ.inner :data
|
|
17
21
|
par(ev) do
|
|
18
|
-
|
|
22
|
+
if (ack) then
|
|
23
|
+
# Output ack mode.
|
|
24
|
+
ack <= 0
|
|
25
|
+
end
|
|
26
|
+
if (req) then
|
|
27
|
+
# Input request mode.
|
|
28
|
+
in_req <= 0
|
|
29
|
+
hif(req) { in_req <= 1 }
|
|
30
|
+
else
|
|
31
|
+
# Automatic mode.
|
|
32
|
+
in_req <= 1
|
|
33
|
+
end
|
|
19
34
|
out_acks.each { |ack| ack <= 0 }
|
|
20
35
|
out_acks.each do |ack|
|
|
21
36
|
hif(ack == 1) { in_req <= 0 }
|
|
@@ -30,6 +45,10 @@ module HDLRuby::High::Std
|
|
|
30
45
|
end
|
|
31
46
|
hif (out_acks.reduce(_1) { |sum,ack| ack & sum }) do
|
|
32
47
|
out_acks.each { |ack| ack <= 0 }
|
|
48
|
+
if (ack) then
|
|
49
|
+
# Output ack mode.
|
|
50
|
+
ack <= 1
|
|
51
|
+
end
|
|
33
52
|
end
|
|
34
53
|
end
|
|
35
54
|
end
|
|
@@ -37,7 +56,7 @@ module HDLRuby::High::Std
|
|
|
37
56
|
|
|
38
57
|
# Function for generating a connector that merges the output of
|
|
39
58
|
# channels +in_chs+ and connects the result to channel +out_ch+ with
|
|
40
|
-
# data of +
|
|
59
|
+
# data of types from +typs+.
|
|
41
60
|
# The merge is done according to event +ev+.
|
|
42
61
|
function :merger do |typs, ev, in_chs, out_ch|
|
|
43
62
|
ev = ev.posedge unless ev.is_a?(Event)
|
|
@@ -63,5 +82,48 @@ module HDLRuby::High::Std
|
|
|
63
82
|
end
|
|
64
83
|
|
|
65
84
|
|
|
85
|
+
# Function for generating a connector that serialize to the output of
|
|
86
|
+
# channels +in_chs+ and connects the result to channel +out_ch+ with
|
|
87
|
+
# data of +typ+.
|
|
88
|
+
# The merge is done according to event +ev+.
|
|
89
|
+
function :serializer do |typ, ev, in_chs, out_ch|
|
|
90
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
|
91
|
+
size = in_chs.size
|
|
92
|
+
inner :out_ack
|
|
93
|
+
# in_reqs = size.times.map { |i| inner(:"in_req#{i}") }
|
|
94
|
+
in_acks = size.times.map { |i| inner(:"in_ack#{i}") }
|
|
95
|
+
datas = size.times.map { |i| typ.inner(:"data#{i}") }
|
|
96
|
+
# The inpt channel selector
|
|
97
|
+
[size.width].inner :idx
|
|
98
|
+
inner :reading
|
|
99
|
+
par(ev) do
|
|
100
|
+
# in_reqs.each { |req| req <= 1 }
|
|
101
|
+
idx <= 0
|
|
102
|
+
reading <= 0
|
|
103
|
+
out_ack <= 0
|
|
104
|
+
hif(idx == size-1) { in_acks.each { |ack| ack <= 0 } }
|
|
105
|
+
# hif((idx == 0) & (in_reqs.reduce(_1) { |sum,req| req & sum })) do
|
|
106
|
+
hif(idx == 0) do
|
|
107
|
+
hif(~reading) do
|
|
108
|
+
size.times { |i| in_acks[i] <= 0 }
|
|
109
|
+
end
|
|
110
|
+
reading <= 1
|
|
111
|
+
in_chs.each_with_index do |ch,i|
|
|
112
|
+
hif(~in_acks[i]) do
|
|
113
|
+
ch.read(datas[i]) { in_acks[i] <= 1 }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
hif(in_acks.reduce(_1) { |sum,req| req & sum }) do
|
|
118
|
+
hcase(idx)
|
|
119
|
+
datas.each_with_index do |data,i|
|
|
120
|
+
hwhen(i) do
|
|
121
|
+
out_ch.write(data) { idx <= idx + 1; out_ack <= 1 }
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
66
128
|
|
|
67
129
|
end
|
data/lib/HDLRuby/std/memory.rb
CHANGED
|
@@ -289,9 +289,10 @@ HDLRuby::High::Std.channel(:mem_rom) do |typ,size,clk,rst,content,
|
|
|
289
289
|
rst = send(rst_name)
|
|
290
290
|
top_block.unshift do
|
|
291
291
|
# Initialize the address so that the next access is at address 0.
|
|
292
|
-
hif(rst==1) { abus_r <= -1 }
|
|
293
|
-
# Reset so switch of the access trigger.
|
|
294
|
-
trig_r <= 0
|
|
292
|
+
# hif(rst==1) { abus_r <= -1 }
|
|
293
|
+
# # Reset so switch of the access trigger.
|
|
294
|
+
# trig_r <= 0
|
|
295
|
+
hif(rst==1) { abus_r <= -1; trig_r <= 0 }
|
|
295
296
|
end
|
|
296
297
|
# The read procedure.
|
|
297
298
|
# par do
|
|
@@ -317,6 +318,7 @@ HDLRuby::High::Std.channel(:mem_rom) do |typ,size,clk,rst,content,
|
|
|
317
318
|
# blk.call if blk
|
|
318
319
|
seq do
|
|
319
320
|
# abus_r <= abus_r + 1
|
|
321
|
+
trig_r <= 0
|
|
320
322
|
target <= dbus_r
|
|
321
323
|
blk.call if blk
|
|
322
324
|
end
|
|
@@ -1704,6 +1706,127 @@ HDLRuby::High::Std.channel(:mem_bank) do |typ,nbanks,size,clk,rst,br_rsts = {}|
|
|
|
1704
1706
|
|
|
1705
1707
|
end
|
|
1706
1708
|
|
|
1709
|
+
|
|
1710
|
+
# Queue memory of +size+ elements of +typ+ typ, syncrhonized on +clk+
|
|
1711
|
+
# (positive and negative edges) and reset on +rst+.
|
|
1712
|
+
# At each rising edge of +clk+ a read and a write is guaranteed to be
|
|
1713
|
+
# completed provided they are triggered.
|
|
1714
|
+
#
|
|
1715
|
+
# NOTE: this channel does not have any branch.
|
|
1716
|
+
HDLRuby::High::Std.channel(:mem_queue) do |typ,size,clk,rst|
|
|
1717
|
+
# The inner buffer of the queue.
|
|
1718
|
+
typ[-size].inner :buffer
|
|
1719
|
+
# The read and write pointers.
|
|
1720
|
+
[size.width].inner :rptr, :wptr
|
|
1721
|
+
# The read and write command signals.
|
|
1722
|
+
inner :rreq, :wreq
|
|
1723
|
+
# The read and write ack signals.
|
|
1724
|
+
inner :rack, :wack
|
|
1725
|
+
# The read/write data registers.
|
|
1726
|
+
typ.inner :rdata, :wdata
|
|
1727
|
+
|
|
1728
|
+
# The flags telling of the channel is synchronized
|
|
1729
|
+
inner :rsync, :wsync
|
|
1730
|
+
|
|
1731
|
+
# The process handling the decoupled access to the buffer.
|
|
1732
|
+
par(clk.posedge) do
|
|
1733
|
+
hif(rst) { rptr <= 0; wptr <= 0 }
|
|
1734
|
+
helse do
|
|
1735
|
+
hif(~rsync) do
|
|
1736
|
+
hif (~rreq) { rack <= 0 }
|
|
1737
|
+
hif(rreq & (~rack) & (rptr != wptr)) do
|
|
1738
|
+
rdata <= buffer[rptr]
|
|
1739
|
+
rptr <= (rptr + 1) % depth
|
|
1740
|
+
rack <= 1
|
|
1741
|
+
end
|
|
1742
|
+
end
|
|
1743
|
+
|
|
1744
|
+
hif(~wsync) do
|
|
1745
|
+
hif (~wreq) { wack <= 0 }
|
|
1746
|
+
hif(wreq & (~wack) & (((wptr+1) % size) != rptr)) do
|
|
1747
|
+
buffer[wptr] <= wdata
|
|
1748
|
+
wptr <= (wptr + 1) % size
|
|
1749
|
+
wack <= 1
|
|
1750
|
+
end
|
|
1751
|
+
end
|
|
1752
|
+
end
|
|
1753
|
+
end
|
|
1754
|
+
|
|
1755
|
+
reader_output :rreq, :rptr, :rsync
|
|
1756
|
+
reader_input :rdata, :rack, :wptr, :buffer
|
|
1757
|
+
|
|
1758
|
+
# The read primitive.
|
|
1759
|
+
reader do |blk,target|
|
|
1760
|
+
if (cur_behavior.on_event?(clk.posedge,clk.negedge)) then
|
|
1761
|
+
# Same clk event, synchrone case: perform a direct access.
|
|
1762
|
+
# Now perform the access.
|
|
1763
|
+
top_block.unshift do
|
|
1764
|
+
rsync <= 1
|
|
1765
|
+
rreq <= 0
|
|
1766
|
+
end
|
|
1767
|
+
seq do
|
|
1768
|
+
hif(rptr != wptr) do
|
|
1769
|
+
# target <= rdata
|
|
1770
|
+
target <= buffer[rptr]
|
|
1771
|
+
rptr <= (rptr + 1) % size
|
|
1772
|
+
blk.call if blk
|
|
1773
|
+
end
|
|
1774
|
+
end
|
|
1775
|
+
else
|
|
1776
|
+
# Different clk event, perform a decoupled access.
|
|
1777
|
+
top_block.unshift do
|
|
1778
|
+
rsync <= 0
|
|
1779
|
+
rreq <= 0
|
|
1780
|
+
end
|
|
1781
|
+
par do
|
|
1782
|
+
hif (~rack) { rreq <= 1 }
|
|
1783
|
+
helsif(rreq) do
|
|
1784
|
+
rreq <= 0
|
|
1785
|
+
target <= rdata
|
|
1786
|
+
blk.call if blk
|
|
1787
|
+
end
|
|
1788
|
+
end
|
|
1789
|
+
end
|
|
1790
|
+
end
|
|
1791
|
+
|
|
1792
|
+
writer_output :wreq, :wdata, :wptr, :wsync, :buffer
|
|
1793
|
+
writer_input :wack, :rptr
|
|
1794
|
+
|
|
1795
|
+
# The write primitive.
|
|
1796
|
+
writer do |blk,target|
|
|
1797
|
+
if (cur_behavior.on_event?(clk.negedge,clk.posedge)) then
|
|
1798
|
+
# Same clk event, synchrone case: perform a direct access.
|
|
1799
|
+
top_block.unshift do
|
|
1800
|
+
wsync <= 1
|
|
1801
|
+
wreq <= 0
|
|
1802
|
+
end
|
|
1803
|
+
hif(((wptr+1) % size) != rptr) do
|
|
1804
|
+
buffer[wptr] <= target
|
|
1805
|
+
wptr <= (wptr + 1) % size
|
|
1806
|
+
blk.call if blk
|
|
1807
|
+
end
|
|
1808
|
+
else
|
|
1809
|
+
# Different clk event, asynchrone case: perform a decoupled access.
|
|
1810
|
+
top_block.unshift do
|
|
1811
|
+
wsync <= 0
|
|
1812
|
+
wreq <= 0
|
|
1813
|
+
end
|
|
1814
|
+
seq do
|
|
1815
|
+
hif (~wack) do
|
|
1816
|
+
wreq <= 1
|
|
1817
|
+
wdata <= target
|
|
1818
|
+
end
|
|
1819
|
+
helsif(wreq) do
|
|
1820
|
+
wreq <= 0
|
|
1821
|
+
blk.call if blk
|
|
1822
|
+
end
|
|
1823
|
+
end
|
|
1824
|
+
end
|
|
1825
|
+
end
|
|
1826
|
+
end
|
|
1827
|
+
|
|
1828
|
+
|
|
1829
|
+
|
|
1707
1830
|
# HDLRuby::High::Std.channel(:mem_bank) do |typ,nbanks,size,clk,rst,br_rsts = {}|
|
|
1708
1831
|
# # Ensure typ is a type.
|
|
1709
1832
|
# typ = typ.to_type
|