HDLRuby 2.2.13 → 2.3.0
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/README.md +14 -8
- data/lib/HDLRuby/hdr_samples/linear_test.rb +235 -0
- data/lib/HDLRuby/hdr_samples/memory_test.rb +272 -0
- data/lib/HDLRuby/hdr_samples/rom.rb +2 -2
- data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +96 -0
- data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +3 -2
- data/lib/HDLRuby/hdr_samples/with_linear.rb +166 -0
- data/lib/HDLRuby/hdr_samples/with_loop.rb +69 -0
- data/lib/HDLRuby/hdr_samples/with_memory.rb +13 -3
- data/lib/HDLRuby/hdrcc.rb +1 -1
- data/lib/HDLRuby/hruby_high.rb +12 -4
- data/lib/HDLRuby/hruby_low.rb +25 -28
- data/lib/HDLRuby/hruby_low2c.rb +10 -5
- data/lib/HDLRuby/hruby_low2high.rb +1 -1
- data/lib/HDLRuby/hruby_low2vhd.rb +63 -48
- data/lib/HDLRuby/hruby_low_fix_types.rb +4 -2
- data/lib/HDLRuby/hruby_low_mutable.rb +2 -1
- data/lib/HDLRuby/hruby_low_resolve.rb +7 -4
- data/lib/HDLRuby/hruby_low_without_concat.rb +8 -4
- data/lib/HDLRuby/hruby_types.rb +82 -72
- data/lib/HDLRuby/hruby_verilog.rb +9 -1
- data/lib/HDLRuby/sim/hruby_sim.h +21 -0
- data/lib/HDLRuby/sim/hruby_sim_calc.c +254 -18
- data/lib/HDLRuby/std/channel.rb +140 -40
- data/lib/HDLRuby/std/fixpoint.rb +15 -6
- data/lib/HDLRuby/std/linear.rb +317 -0
- data/lib/HDLRuby/std/loop.rb +101 -0
- data/lib/HDLRuby/std/memory.rb +1159 -45
- data/lib/HDLRuby/std/task.rb +850 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +10 -2
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'std/task.rb'
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
##
|
6
|
+
# Standard HDLRuby::High library: loops encapsulated in tasks.
|
7
|
+
#
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
## While loop: loops until +condition+ is met execution +ruby_block+.
|
11
|
+
# The loop is synchronized on +clk_e+ and initialized by +init+.
|
12
|
+
# If +condition+ is nil, then +init+ is used as +condition+.
|
13
|
+
HDLRuby::High::Std.task(:while_task) do |clk_e, init, condition, ruby_block|
|
14
|
+
# Ensure clk_e is an event, if not set it to a positive edge.
|
15
|
+
clk_e = clk_e.posedge unless clk_e.is_a?(Event)
|
16
|
+
|
17
|
+
# Ensures there is a condition.
|
18
|
+
unless condition then
|
19
|
+
condition = init
|
20
|
+
init = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
# Transform condition into a proc if it is not the case.
|
24
|
+
unless condition.is_a?(Proc) then
|
25
|
+
condition_expr = condition
|
26
|
+
condition = proc { condition_expr }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Ensures init to be a proc if not nil
|
30
|
+
init = init.to_proc unless init == nil
|
31
|
+
|
32
|
+
# Declares the signals for controlling the loop.
|
33
|
+
inner :req # Signal to set to 1 for running the loop.
|
34
|
+
|
35
|
+
# Declares the runner signals.
|
36
|
+
runner_output :req
|
37
|
+
|
38
|
+
par(clk_e) do
|
39
|
+
# Performs the loop.
|
40
|
+
hif(req) do
|
41
|
+
# By default the loop is not finished.
|
42
|
+
# If the condition is still met go on looping.
|
43
|
+
hif(condition.call,&ruby_block)
|
44
|
+
end
|
45
|
+
# # if (init) then
|
46
|
+
# # # There is an initialization, do it when there is no req.
|
47
|
+
# # helse do
|
48
|
+
# # init.call
|
49
|
+
# # end
|
50
|
+
# # end
|
51
|
+
end
|
52
|
+
|
53
|
+
# The code for reseting the task.
|
54
|
+
if (init) then
|
55
|
+
# reseter(&init)
|
56
|
+
reseter do
|
57
|
+
req <= 0
|
58
|
+
init.call
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# The code for running the task.
|
63
|
+
runner do
|
64
|
+
# top_block.unshift { req <= 0 }
|
65
|
+
req <= 1
|
66
|
+
end
|
67
|
+
|
68
|
+
# The code for checking the end of execution.
|
69
|
+
finisher do |blk|
|
70
|
+
hif(~condition.call,&blk)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
## A simplified loop: loops until +condition+ is met execution +ruby_block+.
|
78
|
+
# The loop is synchronized on +clk_e+ and initialized by +init+.
|
79
|
+
# If +condition+ is nil, then +init+ is used as +condition+.
|
80
|
+
def while_loop(clk_e, init, condition = nil, &ruby_block)
|
81
|
+
# Create the loop task.
|
82
|
+
tsk = while_task(clk_e,init,condition,ruby_block).(HDLRuby.uniq_name)
|
83
|
+
# Create the inner access port.
|
84
|
+
prt = tsk.inner HDLRuby.uniq_name
|
85
|
+
# Return the access port.
|
86
|
+
return prt
|
87
|
+
end
|
88
|
+
|
89
|
+
## Loop +num+ times executing +ruby_block+.
|
90
|
+
# The loop is synchronized on +clk_e+.
|
91
|
+
def times_loop(clk_e, num, &ruby_block)
|
92
|
+
# Compute the width of the counter.
|
93
|
+
width = num.respond_to?(:width) ? num.width : num.type.width
|
94
|
+
# Declares the counter.
|
95
|
+
cnt = [width].inner(HDLRuby.uniq_name)
|
96
|
+
# Create the loop.
|
97
|
+
return while_loop(clk_e, proc{cnt<=0}, cnt<num) do
|
98
|
+
cnt <= cnt + 1
|
99
|
+
ruby_block.call
|
100
|
+
end
|
101
|
+
end
|
data/lib/HDLRuby/std/memory.rb
CHANGED
@@ -170,6 +170,187 @@ HDLRuby::High::Std.channel(:mem_sync) do |n,typ,size,clk_e,rst,br_rsts = []|
|
|
170
170
|
end
|
171
171
|
|
172
172
|
|
173
|
+
# Flexible ROM memory of +size+ elements of +typ+ typ, syncrhonized on +clk+
|
174
|
+
# (positive and negative edges) and reset on +rst+.
|
175
|
+
# At each rising edge of +clk+ a read and a write is guaranteed to be
|
176
|
+
# completed provided they are triggered.
|
177
|
+
# +br_rsts+ are reset names on the branches, if not given, a reset input
|
178
|
+
# is added and connected to rst.
|
179
|
+
# The content of the ROM is passed through +content+ argument.
|
180
|
+
#
|
181
|
+
# NOTE:
|
182
|
+
#
|
183
|
+
# * such memories uses the following ports:
|
184
|
+
# - trig_r: read access trigger (output)
|
185
|
+
# - trig_w: write access trigger (output)
|
186
|
+
# - dbus_r: read data bus (input)
|
187
|
+
# - dbus_w: write data bus (output)
|
188
|
+
#
|
189
|
+
# * The following branches are possible (only one read and one write can
|
190
|
+
# be used per channel)
|
191
|
+
# - raddr: read by address, this channel adds the following port:
|
192
|
+
# abus_r: read address bus (output)
|
193
|
+
# - waddr: read by address, this channel adds the following port:
|
194
|
+
# abus_w: write address bus (output)
|
195
|
+
# - rinc: read by automatically incremented address.
|
196
|
+
# - winc: write by automatically incremented address.
|
197
|
+
# - rdec: read by automatically decremented address.
|
198
|
+
# - wdec: write by automatically decremented address.
|
199
|
+
# - rque: read in queue mode: automatically incremented address ensuring
|
200
|
+
# the read address is always different from the write address.
|
201
|
+
# - wque: write in queue mode: automatically incremented address ensuring
|
202
|
+
# the write address is always differnet from the read address.
|
203
|
+
#
|
204
|
+
HDLRuby::High::Std.channel(:mem_rom) do |typ,size,clk,rst,content,
|
205
|
+
br_rsts = {}|
|
206
|
+
# Ensure typ is a type.
|
207
|
+
typ = typ.to_type
|
208
|
+
# Ensure size in an integer.
|
209
|
+
size = size.to_i
|
210
|
+
# Compute the address bus width from the size.
|
211
|
+
awidth = (size-1).width
|
212
|
+
# Process the table of reset mapping for the branches.
|
213
|
+
# Ensures br_srts is a hash.
|
214
|
+
br_rsts = br_rsts.to_hash
|
215
|
+
|
216
|
+
# Declare the control signals.
|
217
|
+
# Access trigger.
|
218
|
+
inner :trig_r
|
219
|
+
# Data bus
|
220
|
+
typ.inner :dbus_r
|
221
|
+
# Address bus (or simply register)
|
222
|
+
[awidth].inner :abus_r
|
223
|
+
|
224
|
+
# Declare the ROM with its inner content.
|
225
|
+
# typ[-size].constant mem: content.map { |val| val.to_expr }
|
226
|
+
typ[-size].constant mem: content
|
227
|
+
|
228
|
+
# Processes handling the memory access.
|
229
|
+
par(clk.negedge) do
|
230
|
+
dbus_r <= mem[abus_r]
|
231
|
+
end
|
232
|
+
|
233
|
+
# The address branches.
|
234
|
+
# Read with address
|
235
|
+
brancher(:raddr) do
|
236
|
+
reader_output :trig_r, :abus_r
|
237
|
+
reader_input :dbus_r
|
238
|
+
if br_rsts[:raddr] then
|
239
|
+
rst_name = br_rsts[:raddr].to_sym
|
240
|
+
else
|
241
|
+
rst_name = rst.name
|
242
|
+
reader_input rst_name
|
243
|
+
end
|
244
|
+
|
245
|
+
# Defines the read procedure at address +addr+
|
246
|
+
# using +target+ as target of access result.
|
247
|
+
reader do |blk,addr,target|
|
248
|
+
# By default the read trigger is 0.
|
249
|
+
top_block.unshift { trig_r <= 0 }
|
250
|
+
# The read procedure.
|
251
|
+
rst = send(rst_name)
|
252
|
+
par do
|
253
|
+
hif(rst == 0) do
|
254
|
+
# No reset, so can perform the read.
|
255
|
+
hif(trig_r == 1) do
|
256
|
+
# The trigger was previously set, read ok.
|
257
|
+
target <= dbus_r
|
258
|
+
trig_r <= 0
|
259
|
+
blk.call if blk
|
260
|
+
end
|
261
|
+
helse do
|
262
|
+
# Prepare the read.
|
263
|
+
abus_r <= addr
|
264
|
+
trig_r <= 1
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# The increment branches.
|
272
|
+
# Read with increment
|
273
|
+
brancher(:rinc) do
|
274
|
+
reader_output :trig_r, :abus_r
|
275
|
+
reader_input :dbus_r
|
276
|
+
if br_rsts[:rinc] then
|
277
|
+
rst_name = br_rsts[:rinc].to_sym
|
278
|
+
else
|
279
|
+
rst_name = rst.name
|
280
|
+
reader_input rst_name
|
281
|
+
end
|
282
|
+
|
283
|
+
# Defines the read procedure at address +addr+
|
284
|
+
# using +target+ as target of access result.
|
285
|
+
reader do |blk,target|
|
286
|
+
# On reset the read trigger is 0.
|
287
|
+
rst = send(rst_name)
|
288
|
+
top_block.unshift do
|
289
|
+
# Initialize the address so that the next access is at address 0.
|
290
|
+
hif(rst==1) { abus_r <= -1 }
|
291
|
+
# Reset so switch of the access trigger.
|
292
|
+
trig_r <= 0
|
293
|
+
end
|
294
|
+
# The read procedure.
|
295
|
+
par do
|
296
|
+
hif(rst == 0) do
|
297
|
+
# No reset, so can perform the read.
|
298
|
+
hif(trig_r == 1) do
|
299
|
+
# The trigger was previously set, read ok.
|
300
|
+
target <= dbus_r
|
301
|
+
blk.call if blk
|
302
|
+
end
|
303
|
+
# Prepare the read.
|
304
|
+
abus_r <= abus_r + 1
|
305
|
+
trig_r <= 1
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
# The decrement branches.
|
312
|
+
# Read with increment
|
313
|
+
brancher(:rdec) do
|
314
|
+
reader_output :trig_r, :abus_r
|
315
|
+
reader_input :dbus_r
|
316
|
+
if br_rsts[:rdec] then
|
317
|
+
rst_name = br_rsts[:rdec].to_sym
|
318
|
+
else
|
319
|
+
rst_name = rst.name
|
320
|
+
reader_input rst_name
|
321
|
+
end
|
322
|
+
|
323
|
+
# Defines the read procedure at address +addr+
|
324
|
+
# using +target+ as target of access result.
|
325
|
+
reader do |blk,target|
|
326
|
+
# On reset the read trigger is 0.
|
327
|
+
rst = send(rst_name)
|
328
|
+
top_block.unshift do
|
329
|
+
# Initialize the address so that the next access is at address 0.
|
330
|
+
hif(rst==1) { abus_r <= 0 }
|
331
|
+
# Reset so switch of the access trigger.
|
332
|
+
trig_r <= 0
|
333
|
+
end
|
334
|
+
# The read procedure.
|
335
|
+
par do
|
336
|
+
hif(rst == 0) do
|
337
|
+
# No reset, so can perform the read.
|
338
|
+
hif(trig_r == 1) do
|
339
|
+
# The trigger was previously set, read ok.
|
340
|
+
target <= dbus_r
|
341
|
+
blk.call if blk
|
342
|
+
end
|
343
|
+
# Prepare the read.
|
344
|
+
abus_r <= abus_r - 1
|
345
|
+
trig_r <= 1
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
end
|
352
|
+
|
353
|
+
|
173
354
|
|
174
355
|
|
175
356
|
|
@@ -213,28 +394,32 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
213
394
|
awidth = (size-1).width
|
214
395
|
# Process the table of reset mapping for the branches.
|
215
396
|
# puts "first br_rsts=#{br_rsts}"
|
216
|
-
if br_rsts.is_a?(Array) then
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
397
|
+
# if br_rsts.is_a?(Array) then
|
398
|
+
# # It is a list, convert it to a hash with the following order:
|
399
|
+
# # raddr, waddr, rinc, winc, rdec, wdec, rque, wque
|
400
|
+
# # When not specified the reset is +rst+ by default.
|
401
|
+
# # If there is only two entries they will be duplicated and mapped
|
402
|
+
# # as follows:
|
403
|
+
# # [raddr,waddr], [rinc,winc], [rdec,wdec], [rque,wque]
|
404
|
+
# # If there is only one entry it will be duplicated and mapped as
|
405
|
+
# # follows:
|
406
|
+
# # raddr, rinc, rdec, rque
|
407
|
+
# if br_rsts.size == 2 then
|
408
|
+
# br_rsts = br_rsts * 4
|
409
|
+
# elsif br_rsts.size == 1 then
|
410
|
+
# br_rsts = br_rsts * 8
|
411
|
+
# end
|
412
|
+
# br_rsts = { raddr: br_rsts[0], waddr: br_rsts[1],
|
413
|
+
# rinc: br_rsts[2], winc: br_rsts[3],
|
414
|
+
# rdec: br_rsts[4], wdec: br_rsts[5],
|
415
|
+
# rque: br_rsts[6], wque: br_rsts[6] }
|
416
|
+
# end
|
417
|
+
# unless br_rsts.respond_to?(:[])
|
418
|
+
# raise "Invalid reset mapping description: #{br_rsts}"
|
419
|
+
# end
|
420
|
+
#
|
421
|
+
# Ensures br_srts is a hash.
|
422
|
+
br_rsts = br_rsts.to_hash
|
238
423
|
|
239
424
|
# Declare the control signals.
|
240
425
|
# Access triggers.
|
@@ -243,23 +428,14 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
243
428
|
typ.inner :dbus_r, :dbus_w
|
244
429
|
# Address buses (or simply registers)
|
245
430
|
[awidth].inner :abus_r, :abus_w
|
246
|
-
# # Address buffers
|
247
|
-
# [awidth].inner :abus_r_reg
|
248
431
|
|
249
432
|
# Declare the memory content.
|
250
433
|
typ[-size].inner :mem
|
251
434
|
|
252
|
-
#
|
253
|
-
par(clk.posedge) do
|
254
|
-
# # # Output memory value for reading at each cycle.
|
255
|
-
# # dbus_r <= mem[abus_r_reg]
|
256
|
-
# Manage the write to the memory.
|
257
|
-
hif(trig_w) { mem[abus_w] <= dbus_w }
|
258
|
-
end
|
259
|
-
# par(clk.negedge) { abus_r_reg <= abus_r }
|
435
|
+
# Processes handling the memory access.
|
260
436
|
par(clk.negedge) do
|
261
437
|
dbus_r <= mem[abus_r]
|
262
|
-
|
438
|
+
hif(trig_w) { mem[abus_w] <= dbus_w }
|
263
439
|
end
|
264
440
|
|
265
441
|
# The address branches.
|
@@ -351,7 +527,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
351
527
|
# Defines the read procedure at address +addr+
|
352
528
|
# using +target+ as target of access result.
|
353
529
|
reader do |blk,target|
|
354
|
-
#
|
530
|
+
# On reset the read trigger is 0.
|
355
531
|
rst = send(rst_name)
|
356
532
|
top_block.unshift do
|
357
533
|
# Initialize the address so that the next access is at address 0.
|
@@ -391,7 +567,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
391
567
|
# Defines the read procedure at address +addr+
|
392
568
|
# using +target+ as target of access result.
|
393
569
|
writer do |blk,target|
|
394
|
-
#
|
570
|
+
# On reset the read trigger is 0.
|
395
571
|
rst = send(rst_name)
|
396
572
|
top_block.unshift do
|
397
573
|
# Initialize the address so that the next access is at address 0.
|
@@ -403,10 +579,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
403
579
|
par do
|
404
580
|
hif(rst == 0) do
|
405
581
|
# No reset, so can perform the write.
|
406
|
-
|
407
|
-
# The trigger was previously set, write ok.
|
408
|
-
blk.call
|
409
|
-
end if blk
|
582
|
+
blk.call if blk
|
410
583
|
# Prepare the write.
|
411
584
|
abus_w <= abus_w + 1
|
412
585
|
trig_w <= 1
|
@@ -416,6 +589,84 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
416
589
|
end
|
417
590
|
end
|
418
591
|
|
592
|
+
|
593
|
+
# The decrement branches.
|
594
|
+
# Read with increment
|
595
|
+
brancher(:rdec) do
|
596
|
+
reader_output :trig_r, :abus_r
|
597
|
+
reader_input :dbus_r
|
598
|
+
if br_rsts[:rdec] then
|
599
|
+
rst_name = br_rsts[:rdec].to_sym
|
600
|
+
else
|
601
|
+
rst_name = rst.name
|
602
|
+
reader_input rst_name
|
603
|
+
end
|
604
|
+
|
605
|
+
# Defines the read procedure at address +addr+
|
606
|
+
# using +target+ as target of access result.
|
607
|
+
reader do |blk,target|
|
608
|
+
# On reset the read trigger is 0.
|
609
|
+
rst = send(rst_name)
|
610
|
+
top_block.unshift do
|
611
|
+
# Initialize the address so that the next access is at address 0.
|
612
|
+
hif(rst==1) { abus_r <= 0 }
|
613
|
+
# Reset so switch of the access trigger.
|
614
|
+
trig_r <= 0
|
615
|
+
end
|
616
|
+
# The read procedure.
|
617
|
+
par do
|
618
|
+
hif(rst == 0) do
|
619
|
+
# No reset, so can perform the read.
|
620
|
+
hif(trig_r == 1) do
|
621
|
+
# The trigger was previously set, read ok.
|
622
|
+
target <= dbus_r
|
623
|
+
blk.call if blk
|
624
|
+
end
|
625
|
+
# Prepare the read.
|
626
|
+
abus_r <= abus_r - 1
|
627
|
+
trig_r <= 1
|
628
|
+
end
|
629
|
+
end
|
630
|
+
end
|
631
|
+
end
|
632
|
+
|
633
|
+
# Write with address
|
634
|
+
brancher(:wdec) do
|
635
|
+
writer_output :trig_w, :abus_w, :dbus_w
|
636
|
+
if br_rsts[:wdec] then
|
637
|
+
rst_name = br_rsts[:wdec].to_sym
|
638
|
+
else
|
639
|
+
rst_name = rst.name
|
640
|
+
writer_input rst_name
|
641
|
+
end
|
642
|
+
# puts "br_rsts=#{br_rsts}"
|
643
|
+
# puts "rst_name=#{rst_name}"
|
644
|
+
|
645
|
+
# Defines the read procedure at address +addr+
|
646
|
+
# using +target+ as target of access result.
|
647
|
+
writer do |blk,target|
|
648
|
+
# On reset the read trigger is 0.
|
649
|
+
rst = send(rst_name)
|
650
|
+
top_block.unshift do
|
651
|
+
# Initialize the address so that the next access is at address 0.
|
652
|
+
hif(rst == 1) { abus_w <= 0 }
|
653
|
+
# Reset so switch of the access trigger.
|
654
|
+
trig_w <= 0
|
655
|
+
end
|
656
|
+
# The write procedure.
|
657
|
+
par do
|
658
|
+
hif(rst == 0) do
|
659
|
+
# No reset, so can perform the write.
|
660
|
+
blk.call if blk
|
661
|
+
# Prepare the write.
|
662
|
+
abus_w <= abus_w - 1
|
663
|
+
trig_w <= 1
|
664
|
+
dbus_w <= target
|
665
|
+
end
|
666
|
+
end
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
419
670
|
end
|
420
671
|
|
421
672
|
|
@@ -436,8 +687,7 @@ end
|
|
436
687
|
#
|
437
688
|
# * The following branches are possible (only one read and one write can
|
438
689
|
# be used per channel)
|
439
|
-
# -
|
440
|
-
# - wnum: writer by register number, the number must be a defined value.
|
690
|
+
# - anum: access by register number, the number must be a defined value.
|
441
691
|
# - raddr: read by address
|
442
692
|
# - waddr: read by address
|
443
693
|
# - rinc: read by automatically incremented address.
|
@@ -536,7 +786,6 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
536
786
|
# Read with address
|
537
787
|
brancher(:raddr) do
|
538
788
|
size.times { |i| reader_input :"reg_#{i}" }
|
539
|
-
regs = size.times.map {|i| send(:"reg_#{i}") }
|
540
789
|
if br_rsts[:raddr] then
|
541
790
|
rst_name = br_rsts[:raddr].to_sym
|
542
791
|
else
|
@@ -547,6 +796,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
547
796
|
# Defines the read procedure at address +addr+
|
548
797
|
# using +target+ as target of access result.
|
549
798
|
reader do |blk,addr,target|
|
799
|
+
regs = size.times.map {|i| send(:"reg_#{i}") }
|
550
800
|
# The read procedure.
|
551
801
|
rst = send(rst_name)
|
552
802
|
par do
|
@@ -565,7 +815,6 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
565
815
|
# Write with address
|
566
816
|
brancher(:waddr) do
|
567
817
|
size.times { |i| writer_output :"reg_#{i}" }
|
568
|
-
regs = size.times.map {|i| send(:"reg_#{i}") }
|
569
818
|
if br_rsts[:waddr] then
|
570
819
|
rst_name = br_rsts[:waddr].to_sym
|
571
820
|
else
|
@@ -576,6 +825,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
576
825
|
# Defines the writer procedure at address +addr+
|
577
826
|
# using +target+ as target of access.
|
578
827
|
writer do |blk,addr,target|
|
828
|
+
regs = size.times.map {|i| send(:"reg_#{i}") }
|
579
829
|
# The writer procedure.
|
580
830
|
rst = send(rst_name)
|
581
831
|
par do
|
@@ -610,7 +860,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
610
860
|
# using +target+ as target of access result.
|
611
861
|
reader do |blk,target|
|
612
862
|
regs = size.times.map {|i| send(:"reg_#{i}") }
|
613
|
-
#
|
863
|
+
# On reset the read trigger is 0.
|
614
864
|
rst = send(rst_name)
|
615
865
|
top_block.unshift do
|
616
866
|
# Initialize the address so that the next access is at address 0.
|
@@ -649,7 +899,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
649
899
|
# using +target+ as target of access result.
|
650
900
|
writer do |blk,target|
|
651
901
|
regs = size.times.map {|i| send(:"reg_#{i}") }
|
652
|
-
#
|
902
|
+
# On reset the read trigger is 0.
|
653
903
|
rst = send(rst_name)
|
654
904
|
top_block.unshift do
|
655
905
|
# Initialize the address so that the next access is at address 0.
|
@@ -672,4 +922,868 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
672
922
|
end
|
673
923
|
|
674
924
|
|
925
|
+
# The decrement branches.
|
926
|
+
# Read with decrement
|
927
|
+
brancher(:rdec) do
|
928
|
+
size.times { |i| reader_input :"reg_#{i}" }
|
929
|
+
if br_rsts[:rdec] then
|
930
|
+
rst_name = br_rsts[:rdec].to_sym
|
931
|
+
else
|
932
|
+
rst_name = rst.name
|
933
|
+
reader_input rst_name
|
934
|
+
end
|
935
|
+
# Declares the address counter.
|
936
|
+
[size.width-1].inner :abus_r
|
937
|
+
reader_inout :abus_r
|
938
|
+
|
939
|
+
# Defines the read procedure at address +addr+
|
940
|
+
# using +target+ as target of access result.
|
941
|
+
reader do |blk,target|
|
942
|
+
regs = size.times.map {|i| send(:"reg_#{i}") }
|
943
|
+
# On reset the read trigger is 0.
|
944
|
+
rst = send(rst_name)
|
945
|
+
top_block.unshift do
|
946
|
+
# Initialize the address so that the next access is at address 0.
|
947
|
+
hif(rst==1) { abus_r <= -1 }
|
948
|
+
end
|
949
|
+
# The read procedure.
|
950
|
+
par do
|
951
|
+
hif(rst == 0) do
|
952
|
+
# No reset, so can perform the read.
|
953
|
+
hcase(abus_r)
|
954
|
+
size.times do |i|
|
955
|
+
hwhen(i) { target <= regs[i] }
|
956
|
+
end
|
957
|
+
blk.call if blk
|
958
|
+
# Prepare the next read.
|
959
|
+
abus_r <= abus_r - 1
|
960
|
+
end
|
961
|
+
end
|
962
|
+
end
|
963
|
+
end
|
964
|
+
|
965
|
+
# Write with decrement
|
966
|
+
brancher(:wdec) do
|
967
|
+
size.times { |i| writer_output :"reg_#{i}" }
|
968
|
+
if br_rsts[:wdec] then
|
969
|
+
rst_name = br_rsts[:wdec].to_sym
|
970
|
+
else
|
971
|
+
rst_name = rst.name
|
972
|
+
reader_input rst_name
|
973
|
+
end
|
974
|
+
# Declares the address counter.
|
975
|
+
[size.width-1].inner :abus_w
|
976
|
+
reader_inout :abus_w
|
977
|
+
|
978
|
+
# Defines the write procedure at address +addr+
|
979
|
+
# using +target+ as target of access result.
|
980
|
+
writer do |blk,target|
|
981
|
+
regs = size.times.map {|i| send(:"reg_#{i}") }
|
982
|
+
# On reset the read trigger is 0.
|
983
|
+
rst = send(rst_name)
|
984
|
+
top_block.unshift do
|
985
|
+
# Initialize the address so that the next access is at address 0.
|
986
|
+
hif(rst==1) { abus_w <= -1 }
|
987
|
+
end
|
988
|
+
# The read procedure.
|
989
|
+
par do
|
990
|
+
hif(rst == 0) do
|
991
|
+
# No reset, so can perform the read.
|
992
|
+
hcase(abus_w)
|
993
|
+
size.times do |i|
|
994
|
+
hwhen(i) { regs[i] <= target }
|
995
|
+
end
|
996
|
+
blk.call if blk
|
997
|
+
# Prepare the next write.
|
998
|
+
abus_w <= abus_w - 1
|
999
|
+
end
|
1000
|
+
end
|
1001
|
+
end
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
|
1007
|
+
|
1008
|
+
|
1009
|
+
# Multi-bank memory combining several dual-edge memories of +nbanks+ banks
|
1010
|
+
# of +size+ elements of +typ+ typ, syncrhonized on +clk+ (positive and
|
1011
|
+
# negative edges) and reset on +rst+.
|
1012
|
+
# at each rising edge of +clk+ a read and a write is guaranteed to be
|
1013
|
+
# completed provided they are triggered.
|
1014
|
+
# +br_rsts+ are reset names on the branches, if not given, a reset input
|
1015
|
+
# is added and connected to rst.
|
1016
|
+
#
|
1017
|
+
# NOTE:
|
1018
|
+
#
|
1019
|
+
# * such memories uses the following ports:
|
1020
|
+
# - trig_r: read access trigger (output)
|
1021
|
+
# - trig_w: write access trigger (output)
|
1022
|
+
# - dbus_r: read data bus (input)
|
1023
|
+
# - dbus_w: write data bus (output)
|
1024
|
+
#
|
1025
|
+
# * The following branches are possible (only one read and one write can
|
1026
|
+
# be used per channel)
|
1027
|
+
# - raddr: read by address, this channel adds the following port:
|
1028
|
+
# abus_r: read address bus (output)
|
1029
|
+
# - waddr: read by address, this channel adds the following port:
|
1030
|
+
# abus_w: write address bus (output)
|
1031
|
+
# - rinc: read by automatically incremented address.
|
1032
|
+
# - winc: write by automatically incremented address.
|
1033
|
+
# - rdec: read by automatically decremented address.
|
1034
|
+
# - wdec: write by automatically decremented address.
|
1035
|
+
# - rque: read in queue mode: automatically incremented address ensuring
|
1036
|
+
# the read address is always different from the write address.
|
1037
|
+
# - wque: write in queue mode: automatically incremented address ensuring
|
1038
|
+
# the write address is always differnet from the read address.
|
1039
|
+
HDLRuby::High::Std.channel(:mem_bank) do |typ,nbanks,size,clk,rst,br_rsts = {}|
|
1040
|
+
# Ensure typ is a type.
|
1041
|
+
typ = typ.to_type
|
1042
|
+
# Ensure size in an integer.
|
1043
|
+
size = size.to_i
|
1044
|
+
# Compute the address bus width from the size.
|
1045
|
+
awidth = (size*nbanks-1).width
|
1046
|
+
awidth_b = (size-1).width # Bank width
|
1047
|
+
# Ensures br_srts is a hash.
|
1048
|
+
br_rsts = br_rsts.to_hash
|
1049
|
+
|
1050
|
+
# The global buses and control signals.
|
1051
|
+
[awidth].inner :abus_r, :abus_w
|
1052
|
+
typ.inner :dbus_r, :dbus_w
|
1053
|
+
inner :trig_r, :trig_w
|
1054
|
+
|
1055
|
+
# For each bank.
|
1056
|
+
nbanks.times do |id|
|
1057
|
+
# Declare the control signals.
|
1058
|
+
# Access triggers.
|
1059
|
+
inner :"trig_r_#{id}", :"trig_w_#{id}"
|
1060
|
+
# Data buses
|
1061
|
+
typ.inner :"dbus_r_#{id}", :"dbus_w_#{id}"
|
1062
|
+
# Address buses (or simply registers)
|
1063
|
+
[awidth_b].inner :"abus_r_#{id}", :"abus_w_#{id}"
|
1064
|
+
|
1065
|
+
# Declare the memory content.
|
1066
|
+
typ[-size].inner :"mem_#{id}"
|
1067
|
+
|
1068
|
+
# Processes handling the memory access.
|
1069
|
+
par(clk.negedge) do
|
1070
|
+
send(:"dbus_r_#{id}") <= send(:"mem_#{id}")[send(:"abus_r_#{id}")]
|
1071
|
+
hif(trig_w & ((abus_w % nbanks) == id)) do
|
1072
|
+
send(:"mem_#{id}")[send(:"abus_w_#{id}")] <= dbus_w
|
1073
|
+
end
|
1074
|
+
helsif(send(:"trig_w_#{id}")) do
|
1075
|
+
send(:"mem_#{id}")[send(:"abus_w_#{id}")] <= send(:"dbus_w_#{id}")
|
1076
|
+
end
|
1077
|
+
end
|
1078
|
+
end
|
1079
|
+
# Interconnect the buses and triggers
|
1080
|
+
nbanks.times do |id|
|
1081
|
+
send(:"abus_r_#{id}") <= abus_r / nbanks
|
1082
|
+
send(:"abus_w_#{id}") <= abus_w / nbanks
|
1083
|
+
end
|
1084
|
+
par do
|
1085
|
+
# By default triggers are off.
|
1086
|
+
nbanks.times do |id|
|
1087
|
+
send(:"trig_w_#{id}") <= 0
|
1088
|
+
send(:"trig_r_#{id}") <= 0
|
1089
|
+
end
|
1090
|
+
# Set the read address bus and trigger if required.
|
1091
|
+
hcase(abus_r % nbanks)
|
1092
|
+
nbanks.times do |id|
|
1093
|
+
hwhen(id) do
|
1094
|
+
dbus_r <= send(:"dbus_r_#{id}")
|
1095
|
+
send(:"trig_r_#{id}") <= trig_r
|
1096
|
+
end
|
1097
|
+
end
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
|
1101
|
+
# The address branches.
|
1102
|
+
# Read with address
|
1103
|
+
brancher(:raddr) do
|
1104
|
+
reader_output :trig_r, :abus_r
|
1105
|
+
reader_input :dbus_r
|
1106
|
+
if br_rsts[:raddr] then
|
1107
|
+
rst_name = br_rsts[:raddr].to_sym
|
1108
|
+
else
|
1109
|
+
rst_name = rst.name
|
1110
|
+
reader_input rst_name
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
# Defines the read procedure at address +addr+
|
1114
|
+
# using +target+ as target of access result.
|
1115
|
+
reader do |blk,addr,target|
|
1116
|
+
# By default the read trigger is 0.
|
1117
|
+
top_block.unshift { trig_r <= 0 }
|
1118
|
+
# The read procedure.
|
1119
|
+
rst = send(rst_name)
|
1120
|
+
par do
|
1121
|
+
hif(rst == 0) do
|
1122
|
+
# No reset, so can perform the read.
|
1123
|
+
hif(trig_r == 1) do
|
1124
|
+
# The trigger was previously set, read ok.
|
1125
|
+
target <= dbus_r
|
1126
|
+
trig_r <= 0
|
1127
|
+
blk.call if blk
|
1128
|
+
end
|
1129
|
+
helse do
|
1130
|
+
# Prepare the read.
|
1131
|
+
abus_r <= addr
|
1132
|
+
trig_r <= 1
|
1133
|
+
end
|
1134
|
+
end
|
1135
|
+
end
|
1136
|
+
end
|
1137
|
+
end
|
1138
|
+
|
1139
|
+
# Write with address
|
1140
|
+
brancher(:waddr) do
|
1141
|
+
writer_output :trig_w, :abus_w, :dbus_w
|
1142
|
+
if br_rsts[:waddr] then
|
1143
|
+
rst_name = br_rsts[:waddr].to_sym
|
1144
|
+
else
|
1145
|
+
rst_name = rst.name
|
1146
|
+
writer_input rst_name
|
1147
|
+
end
|
1148
|
+
# puts "br_rsts=#{br_rsts}"
|
1149
|
+
# puts "rst_name=#{rst_name}"
|
1150
|
+
|
1151
|
+
# Defines the read procedure at address +addr+
|
1152
|
+
# using +target+ as target of access result.
|
1153
|
+
writer do |blk,addr,target|
|
1154
|
+
# By default the read trigger is 0.
|
1155
|
+
top_block.unshift { trig_w <= 0 }
|
1156
|
+
# The write procedure.
|
1157
|
+
rst = send(rst_name)
|
1158
|
+
par do
|
1159
|
+
hif(rst == 0) do
|
1160
|
+
# No reset, so can perform the write.
|
1161
|
+
hif(trig_w == 1) do
|
1162
|
+
# The trigger was previously set, write ok.
|
1163
|
+
blk.call if blk
|
1164
|
+
end
|
1165
|
+
# Prepare the write.
|
1166
|
+
abus_w <= addr
|
1167
|
+
trig_w <= 1
|
1168
|
+
dbus_w <= target
|
1169
|
+
end
|
1170
|
+
end
|
1171
|
+
end
|
1172
|
+
end
|
1173
|
+
|
1174
|
+
# The increment branches.
|
1175
|
+
# Read with increment
|
1176
|
+
brancher(:rinc) do
|
1177
|
+
reader_output :trig_r, :abus_r
|
1178
|
+
reader_input :dbus_r
|
1179
|
+
if br_rsts[:rinc] then
|
1180
|
+
rst_name = br_rsts[:rinc].to_sym
|
1181
|
+
else
|
1182
|
+
rst_name = rst.name
|
1183
|
+
reader_input rst_name
|
1184
|
+
end
|
1185
|
+
|
1186
|
+
# Defines the read procedure at address +addr+
|
1187
|
+
# using +target+ as target of access result.
|
1188
|
+
reader do |blk,target|
|
1189
|
+
# On reset the read trigger is 0.
|
1190
|
+
rst = send(rst_name)
|
1191
|
+
top_block.unshift do
|
1192
|
+
# Initialize the address so that the next access is at address 0.
|
1193
|
+
hif(rst==1) { abus_r <= -1 }
|
1194
|
+
# Reset so switch of the access trigger.
|
1195
|
+
trig_r <= 0
|
1196
|
+
end
|
1197
|
+
# The read procedure.
|
1198
|
+
par do
|
1199
|
+
hif(rst == 0) do
|
1200
|
+
# No reset, so can perform the read.
|
1201
|
+
hif(trig_r == 1) do
|
1202
|
+
# The trigger was previously set, read ok.
|
1203
|
+
target <= dbus_r
|
1204
|
+
blk.call if blk
|
1205
|
+
end
|
1206
|
+
# Prepare the read.
|
1207
|
+
abus_r <= abus_r + 1
|
1208
|
+
trig_r <= 1
|
1209
|
+
end
|
1210
|
+
end
|
1211
|
+
end
|
1212
|
+
end
|
1213
|
+
|
1214
|
+
# Write with address
|
1215
|
+
brancher(:winc) do
|
1216
|
+
writer_output :trig_w, :abus_w, :dbus_w
|
1217
|
+
if br_rsts[:winc] then
|
1218
|
+
rst_name = br_rsts[:winc].to_sym
|
1219
|
+
else
|
1220
|
+
rst_name = rst.name
|
1221
|
+
writer_input rst_name
|
1222
|
+
end
|
1223
|
+
# puts "br_rsts=#{br_rsts}"
|
1224
|
+
# puts "rst_name=#{rst_name}"
|
1225
|
+
|
1226
|
+
# Defines the read procedure at address +addr+
|
1227
|
+
# using +target+ as target of access result.
|
1228
|
+
writer do |blk,target|
|
1229
|
+
# On reset the read trigger is 0.
|
1230
|
+
rst = send(rst_name)
|
1231
|
+
top_block.unshift do
|
1232
|
+
# Initialize the address so that the next access is at address 0.
|
1233
|
+
hif(rst == 1) { abus_w <= -1 }
|
1234
|
+
# Reset so switch of the access trigger.
|
1235
|
+
trig_w <= 0
|
1236
|
+
end
|
1237
|
+
# The write procedure.
|
1238
|
+
par do
|
1239
|
+
hif(rst == 0) do
|
1240
|
+
# No reset, so can perform the write.
|
1241
|
+
blk.call if blk
|
1242
|
+
# Prepare the write.
|
1243
|
+
abus_w <= abus_w + 1
|
1244
|
+
trig_w <= 1
|
1245
|
+
dbus_w <= target
|
1246
|
+
end
|
1247
|
+
end
|
1248
|
+
end
|
1249
|
+
end
|
1250
|
+
|
1251
|
+
# The decrement branches.
|
1252
|
+
# Read with increment
|
1253
|
+
brancher(:rdec) do
|
1254
|
+
reader_output :trig_r, :abus_r
|
1255
|
+
reader_input :dbus_r
|
1256
|
+
if br_rsts[:rdec] then
|
1257
|
+
rst_name = br_rsts[:rdec].to_sym
|
1258
|
+
else
|
1259
|
+
rst_name = rst.name
|
1260
|
+
reader_input rst_name
|
1261
|
+
end
|
1262
|
+
|
1263
|
+
# Defines the read procedure at address +addr+
|
1264
|
+
# using +target+ as target of access result.
|
1265
|
+
reader do |blk,target|
|
1266
|
+
# On reset the read trigger is 0.
|
1267
|
+
rst = send(rst_name)
|
1268
|
+
top_block.unshift do
|
1269
|
+
# Initialize the address so that the next access is at address 0.
|
1270
|
+
hif(rst==1) { abus_r <= 0 }
|
1271
|
+
# Reset so switch of the access trigger.
|
1272
|
+
trig_r <= 0
|
1273
|
+
end
|
1274
|
+
# The read procedure.
|
1275
|
+
par do
|
1276
|
+
hif(rst == 0) do
|
1277
|
+
# No reset, so can perform the read.
|
1278
|
+
hif(trig_r == 1) do
|
1279
|
+
# The trigger was previously set, read ok.
|
1280
|
+
target <= dbus_r
|
1281
|
+
blk.call if blk
|
1282
|
+
end
|
1283
|
+
# Prepare the read.
|
1284
|
+
abus_r <= abus_r - 1
|
1285
|
+
trig_r <= 1
|
1286
|
+
end
|
1287
|
+
end
|
1288
|
+
end
|
1289
|
+
end
|
1290
|
+
|
1291
|
+
# Write with address
|
1292
|
+
brancher(:wdec) do
|
1293
|
+
writer_output :trig_w, :abus_w, :dbus_w
|
1294
|
+
if br_rsts[:wdec] then
|
1295
|
+
rst_name = br_rsts[:wdec].to_sym
|
1296
|
+
else
|
1297
|
+
rst_name = rst.name
|
1298
|
+
writer_input rst_name
|
1299
|
+
end
|
1300
|
+
# puts "br_rsts=#{br_rsts}"
|
1301
|
+
# puts "rst_name=#{rst_name}"
|
1302
|
+
|
1303
|
+
# Defines the read procedure at address +addr+
|
1304
|
+
# using +target+ as target of access result.
|
1305
|
+
writer do |blk,target|
|
1306
|
+
# On reset the read trigger is 0.
|
1307
|
+
rst = send(rst_name)
|
1308
|
+
top_block.unshift do
|
1309
|
+
# Initialize the address so that the next access is at address 0.
|
1310
|
+
hif(rst == 1) { abus_w <= 0 }
|
1311
|
+
# Reset so switch of the access trigger.
|
1312
|
+
trig_w <= 0
|
1313
|
+
end
|
1314
|
+
# The write procedure.
|
1315
|
+
par do
|
1316
|
+
hif(rst == 0) do
|
1317
|
+
# No reset, so can perform the write.
|
1318
|
+
blk.call if blk
|
1319
|
+
# Prepare the write.
|
1320
|
+
abus_w <= abus_w - 1
|
1321
|
+
trig_w <= 1
|
1322
|
+
dbus_w <= target
|
1323
|
+
end
|
1324
|
+
end
|
1325
|
+
end
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
|
1329
|
+
# Declare the branchers for accessing directly the banks.
|
1330
|
+
nbanks.times do |id|
|
1331
|
+
# Read with address.
|
1332
|
+
brancher(:"raddr_#{id}") do
|
1333
|
+
reader_output :"trig_r_#{id}", :"abus_r_#{id}"
|
1334
|
+
reader_input :"dbus_r_#{id}"
|
1335
|
+
if br_rsts[:"raddr_#{id}"] then
|
1336
|
+
rst_name = br_rsts[:"raddr_#{id}"].to_sym
|
1337
|
+
else
|
1338
|
+
rst_name = rst.name
|
1339
|
+
reader_input rst_name
|
1340
|
+
end
|
1341
|
+
|
1342
|
+
# Defines the read procedure at address +addr+
|
1343
|
+
# using +target+ as target of access result.
|
1344
|
+
reader do |blk,addr,target|
|
1345
|
+
# By default the read trigger is 0.
|
1346
|
+
top_block.unshift { send(:"trig_r_#{id}") <= 0 }
|
1347
|
+
# The read procedure.
|
1348
|
+
rst = send(rst_name)
|
1349
|
+
par do
|
1350
|
+
hif(rst == 0) do
|
1351
|
+
# No reset, so can perform the read.
|
1352
|
+
hif(send(:"trig_r_#{id}") == 1) do
|
1353
|
+
# The trigger was previously set, read ok.
|
1354
|
+
target <= send(:"dbus_r_#{id}")
|
1355
|
+
send(:"trig_r_#{id}") <= 0
|
1356
|
+
blk.call if blk
|
1357
|
+
end
|
1358
|
+
helse do
|
1359
|
+
# Prepare the read.
|
1360
|
+
send(:"abus_r_#{id}") <= addr
|
1361
|
+
send(:"trig_r_#{id}") <= 1
|
1362
|
+
end
|
1363
|
+
end
|
1364
|
+
end
|
1365
|
+
end
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
# Write with address
|
1369
|
+
brancher(:"waddr_#{id}") do
|
1370
|
+
writer_output :"trig_w_#{id}", :"abus_w_#{id}", :"dbus_w_#{id}"
|
1371
|
+
if br_rsts[:"waddr_#{id}"] then
|
1372
|
+
rst_name = br_rsts[:"waddr_#{id}"].to_sym
|
1373
|
+
else
|
1374
|
+
rst_name = rst.name
|
1375
|
+
writer_input rst_name
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
# Defines the read procedure at address +addr+
|
1379
|
+
# using +target+ as target of access result.
|
1380
|
+
writer do |blk,addr,target|
|
1381
|
+
# By default the read trigger is 0.
|
1382
|
+
top_block.unshift { send(:"trig_w_#{id}") <= 0 }
|
1383
|
+
# The write procedure.
|
1384
|
+
rst = send(rst_name)
|
1385
|
+
par do
|
1386
|
+
hif(rst == 0) do
|
1387
|
+
# No reset, so can perform the write.
|
1388
|
+
hif(send(:"trig_w_#{id}") == 1) do
|
1389
|
+
# The trigger was previously set, write ok.
|
1390
|
+
blk.call if blk
|
1391
|
+
end
|
1392
|
+
# Prepare the write.
|
1393
|
+
send(:"abus_w_#{id}") <= addr
|
1394
|
+
send(:"trig_w_#{id}") <= 1
|
1395
|
+
send(:"dbus_w_#{id}") <= target
|
1396
|
+
end
|
1397
|
+
end
|
1398
|
+
end
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
# The increment branches.
|
1402
|
+
# Read with increment
|
1403
|
+
brancher(:"rinc_#{id}") do
|
1404
|
+
reader_output :"trig_r_#{id}", :"abus_r_#{id}"
|
1405
|
+
reader_input :"dbus_r_#{id}"
|
1406
|
+
if br_rsts[:"rinc_#{id}"] then
|
1407
|
+
rst_name = br_rsts[:"rinc_#{id}"].to_sym
|
1408
|
+
else
|
1409
|
+
rst_name = rst.name
|
1410
|
+
reader_input rst_name
|
1411
|
+
end
|
1412
|
+
|
1413
|
+
# Defines the read procedure at address +addr+
|
1414
|
+
# using +target+ as target of access result.
|
1415
|
+
reader do |blk,target|
|
1416
|
+
# On reset the read trigger is 0.
|
1417
|
+
rst = send(rst_name)
|
1418
|
+
top_block.unshift do
|
1419
|
+
# Initialize the address so that the next access is at address 0.
|
1420
|
+
hif(rst==1) { send(:"abus_r_#{id}") <= -1 }
|
1421
|
+
# Reset so switch of the access trigger.
|
1422
|
+
send(:"trig_r_#{id}") <= 0
|
1423
|
+
end
|
1424
|
+
# The read procedure.
|
1425
|
+
par do
|
1426
|
+
hif(rst == 0) do
|
1427
|
+
# No reset, so can perform the read.
|
1428
|
+
hif(send(:"trig_r_#{id}") == 1) do
|
1429
|
+
# The trigger was previously set, read ok.
|
1430
|
+
target <= send(:"dbus_r_#{id}")
|
1431
|
+
blk.call if blk
|
1432
|
+
end
|
1433
|
+
# Prepare the read.
|
1434
|
+
send(:"abus_r_#{id}") <= send(:"abus_r_#{id}") + 1
|
1435
|
+
send(:"trig_r_#{id}") <= 1
|
1436
|
+
end
|
1437
|
+
end
|
1438
|
+
end
|
1439
|
+
end
|
1440
|
+
|
1441
|
+
# Write with address
|
1442
|
+
brancher(:"winc_#{id}") do
|
1443
|
+
writer_output :"trig_w_#{id}", :"abus_w_#{id}", :"dbus_w_#{id}"
|
1444
|
+
if br_rsts[:"winc_#{id}"] then
|
1445
|
+
rst_name = br_rsts[:"winc_#{id}"].to_sym
|
1446
|
+
else
|
1447
|
+
rst_name = rst.name
|
1448
|
+
writer_input rst_name
|
1449
|
+
end
|
1450
|
+
|
1451
|
+
# Defines the read procedure at address +addr+
|
1452
|
+
# using +target+ as target of access result.
|
1453
|
+
writer do |blk,target|
|
1454
|
+
# On reset the read trigger is 0.
|
1455
|
+
rst = send(rst_name)
|
1456
|
+
top_block.unshift do
|
1457
|
+
# Initialize the address so that the next access is at address 0.
|
1458
|
+
hif(rst == 1) { send(:"abus_w_#{id}") <= -1 }
|
1459
|
+
# Reset so switch of the access trigger.
|
1460
|
+
send(:"trig_w_#{id}") <= 0
|
1461
|
+
end
|
1462
|
+
# The write procedure.
|
1463
|
+
par do
|
1464
|
+
hif(rst == 0) do
|
1465
|
+
# No reset, so can perform the write.
|
1466
|
+
blk.call if blk
|
1467
|
+
# Prepare the write.
|
1468
|
+
send(:"abus_w_#{id}") <= send(:"abus_w_#{id}") + 1
|
1469
|
+
send(:"trig_w_#{id}") <= 1
|
1470
|
+
send(:"dbus_w_#{id}") <= target
|
1471
|
+
end
|
1472
|
+
end
|
1473
|
+
end
|
1474
|
+
end
|
1475
|
+
|
1476
|
+
# The decrement branches.
|
1477
|
+
# Read with increment
|
1478
|
+
brancher(:"rdec_#{id}") do
|
1479
|
+
reader_output :"trig_r_#{id}", :"abus_r_#{id}"
|
1480
|
+
reader_input :"dbus_r_#{id}"
|
1481
|
+
if br_rsts[:"rdec_#{id}"] then
|
1482
|
+
rst_name = br_rsts[:"rdec_#{id}"].to_sym
|
1483
|
+
else
|
1484
|
+
rst_name = rst.name
|
1485
|
+
reader_input rst_name
|
1486
|
+
end
|
1487
|
+
|
1488
|
+
# Defines the read procedure at address +addr+
|
1489
|
+
# using +target+ as target of access result.
|
1490
|
+
reader do |blk,target|
|
1491
|
+
# On reset the read trigger is 0.
|
1492
|
+
rst = send(rst_name)
|
1493
|
+
top_block.unshift do
|
1494
|
+
# Initialize the address so that the next access is at address 0.
|
1495
|
+
hif(rst==1) { send(:"abus_r_#{id}") <= 0 }
|
1496
|
+
# Reset so switch of the access trigger.
|
1497
|
+
send(:"trig_r_#{id}") <= 0
|
1498
|
+
end
|
1499
|
+
# The read procedure.
|
1500
|
+
par do
|
1501
|
+
hif(rst == 0) do
|
1502
|
+
# No reset, so can perform the read.
|
1503
|
+
hif(send(:"trig_r_#{id}") == 1) do
|
1504
|
+
# The trigger was previously set, read ok.
|
1505
|
+
target <= send(:"dbus_r_#{id}")
|
1506
|
+
blk.call if blk
|
1507
|
+
end
|
1508
|
+
# Prepare the read.
|
1509
|
+
send(:"abus_r_#{id}") <= send(:"abus_r_#{id}") - 1
|
1510
|
+
send(:"trig_r_#{id}") <= 1
|
1511
|
+
end
|
1512
|
+
end
|
1513
|
+
end
|
1514
|
+
end
|
1515
|
+
|
1516
|
+
# Write with address
|
1517
|
+
brancher(:"wdec_#{id}") do
|
1518
|
+
writer_output :"trig_w_#{id}", :"abus_w_#{id}", :"dbus_w_#{id}"
|
1519
|
+
if br_rsts[:"wdec_#{id}"] then
|
1520
|
+
rst_name = br_rsts[:"wdec_#{id}"].to_sym
|
1521
|
+
else
|
1522
|
+
rst_name = rst.name
|
1523
|
+
writer_input rst_name
|
1524
|
+
end
|
1525
|
+
|
1526
|
+
# Defines the read procedure at address +addr+
|
1527
|
+
# using +target+ as target of access result.
|
1528
|
+
writer do |blk,target|
|
1529
|
+
# On reset the read trigger is 0.
|
1530
|
+
rst = send(rst_name)
|
1531
|
+
top_block.unshift do
|
1532
|
+
# Initialize the address so that the next access is at address 0.
|
1533
|
+
hif(rst == 1) { send(:"abus_w_#{id}") <= 0 }
|
1534
|
+
# Reset so switch of the access trigger.
|
1535
|
+
trig_w <= 0
|
1536
|
+
end
|
1537
|
+
# The write procedure.
|
1538
|
+
par do
|
1539
|
+
hif(rst == 0) do
|
1540
|
+
# No reset, so can perform the write.
|
1541
|
+
blk.call if blk
|
1542
|
+
# Prepare the write.
|
1543
|
+
send(:"abus_w_#{id}") <= send(:"abus_w_#{id}") - 1
|
1544
|
+
send(:"trig_w_#{id}") <= 1
|
1545
|
+
send(:"dbus_w_#{id}") <= target
|
1546
|
+
end
|
1547
|
+
end
|
1548
|
+
end
|
1549
|
+
end
|
1550
|
+
end
|
1551
|
+
|
675
1552
|
end
|
1553
|
+
|
1554
|
+
# HDLRuby::High::Std.channel(:mem_bank) do |typ,nbanks,size,clk,rst,br_rsts = {}|
|
1555
|
+
# # Ensure typ is a type.
|
1556
|
+
# typ = typ.to_type
|
1557
|
+
# # Ensure nbank is an integer.
|
1558
|
+
# nbanks = nbanks.to_i
|
1559
|
+
# # Ensure size in an integer.
|
1560
|
+
# size = size.to_i
|
1561
|
+
# # Compute the address bus width from the size.
|
1562
|
+
# awidth = (size-1).width
|
1563
|
+
# # # Process the table of reset mapping for the branches.
|
1564
|
+
# # # puts "first br_rsts=#{br_rsts}"
|
1565
|
+
# # if br_rsts.is_a?(Array) then
|
1566
|
+
# # # It is a list, convert it to a hash with the following order:
|
1567
|
+
# # # raddr, waddr, rinc, winc, rdec, wdec, rque, wque
|
1568
|
+
# # # If there is only two entries they will be duplicated and mapped
|
1569
|
+
# # # as follows:
|
1570
|
+
# # # [raddr,waddr], [rinc,winc], [rdec,wdec], [rque,wque]
|
1571
|
+
# # # If there is only one entry it will be duplicated and mapped as
|
1572
|
+
# # # follows:
|
1573
|
+
# # # raddr, rinc, rdec, rque
|
1574
|
+
# # if br_rsts.size == 2 then
|
1575
|
+
# # br_rsts = br_rsts * 4
|
1576
|
+
# # elsif br_rsts.size == 1 then
|
1577
|
+
# # br_rsts = br_rsts * 8
|
1578
|
+
# # end
|
1579
|
+
# # br_rsts = { raddr: br_rsts[0], waddr: br_rsts[1],
|
1580
|
+
# # rinc: br_rsts[2], winc: br_rsts[3],
|
1581
|
+
# # rdec: br_rsts[4], wdec: br_rsts[5],
|
1582
|
+
# # rque: br_rsts[6], wque: br_rsts[6] }
|
1583
|
+
# # end
|
1584
|
+
# # unless br_rsts.respond_to?(:[])
|
1585
|
+
# # raise "Invalid reset mapping description: #{br_rsts}"
|
1586
|
+
# # end
|
1587
|
+
# # Ensures br_rsts is a hash.
|
1588
|
+
# br_rsts = br_rsts.to_hash
|
1589
|
+
#
|
1590
|
+
# # Declares the banks.
|
1591
|
+
# banks = nbanks.times.map do |id|
|
1592
|
+
# # Extract the resets corresponding to the bank.
|
1593
|
+
# cur_br_rsts = {}
|
1594
|
+
# br_rsts.each do |k,v|
|
1595
|
+
# num = k.to_s[/\d+$/]
|
1596
|
+
# if num && num.to_i == id then
|
1597
|
+
# cur_br_rsts[k.to_s.chomp[num]] = v
|
1598
|
+
# end
|
1599
|
+
# end
|
1600
|
+
# # Declare the bank.
|
1601
|
+
# mem_dual(typ,size,clk,rst, cur_br_rsts).(HDLRuby.uniq_name)
|
1602
|
+
# end
|
1603
|
+
#
|
1604
|
+
# # Declare the branchers for accessing directly the banks.
|
1605
|
+
# banks.each_with_index do |bank,id|
|
1606
|
+
# brancher(id,bank)
|
1607
|
+
# end
|
1608
|
+
#
|
1609
|
+
# # Generate the gobal access to the memory.
|
1610
|
+
#
|
1611
|
+
# # The address branches.
|
1612
|
+
# # Read with address
|
1613
|
+
# brancher(:raddr) do
|
1614
|
+
# # Create the read branch for each bank.
|
1615
|
+
# bank_brs = banks.map do |bank|
|
1616
|
+
# bank.branch(:raddr).inner HDLRuby.uniq_name
|
1617
|
+
# end
|
1618
|
+
# # Defines the read procedure at address +addr+
|
1619
|
+
# # using +target+ as target of access result.
|
1620
|
+
# reader do |blk,addr,target|
|
1621
|
+
# # Select the bank depending on the address.
|
1622
|
+
# hcase(addr / nbanks)
|
1623
|
+
# nbanks.times do |i|
|
1624
|
+
# hwhen(i) do
|
1625
|
+
# bank_brs[i].read(addr % nbanks,target,&blk)
|
1626
|
+
# end
|
1627
|
+
# end
|
1628
|
+
# end
|
1629
|
+
# end
|
1630
|
+
# # Write with address
|
1631
|
+
# brancher(:waddr) do
|
1632
|
+
# # Create the write branch for each bank.
|
1633
|
+
# bank_brs = banks.map do |bank|
|
1634
|
+
# bank.branch(:waddr).inner HDLRuby.uniq_name
|
1635
|
+
# end
|
1636
|
+
# # Defines the read procedure at address +addr+
|
1637
|
+
# # using +target+ as target of access result.
|
1638
|
+
# writer do |blk,addr,target|
|
1639
|
+
# # Select the bank depending on the address.
|
1640
|
+
# hcase(addr / nbanks)
|
1641
|
+
# nbanks.times do |i|
|
1642
|
+
# hwhen(i) do
|
1643
|
+
# bank_brs[i].write(addr % nbanks,target,&blk)
|
1644
|
+
# end
|
1645
|
+
# end
|
1646
|
+
# end
|
1647
|
+
# end
|
1648
|
+
#
|
1649
|
+
#
|
1650
|
+
# # Address buses (or simply registers) for increment/decrement accesses
|
1651
|
+
# [awidth].inner :abus_r, :abus_w
|
1652
|
+
#
|
1653
|
+
# # The increment branches.
|
1654
|
+
# # Read with increment
|
1655
|
+
# brancher(:rinc) do
|
1656
|
+
# reader_output :abus_r
|
1657
|
+
# if br_rsts[:rinc] then
|
1658
|
+
# rst_name = br_rsts[:rinc].to_sym
|
1659
|
+
# else
|
1660
|
+
# rst_name = rst.name
|
1661
|
+
# reader_input rst_name
|
1662
|
+
# end
|
1663
|
+
# # Create the write branch for each bank.
|
1664
|
+
# bank_brs = banks.map do |bank|
|
1665
|
+
# bank.branch(:raddr).inner HDLRuby.uniq_name
|
1666
|
+
# end
|
1667
|
+
#
|
1668
|
+
# # Defines the read procedure at address +addr+
|
1669
|
+
# # using +target+ as target of access result.
|
1670
|
+
# reader do |blk,target|
|
1671
|
+
# # On reset the read trigger is 0.
|
1672
|
+
# rst = send(rst_name)
|
1673
|
+
# top_block.unshift do
|
1674
|
+
# # Initialize the address so that the next access is at address 0.
|
1675
|
+
# hif(rst==1) { abus_r <= 0 }
|
1676
|
+
# end
|
1677
|
+
# # Select the bank depending on the address.
|
1678
|
+
# hcase(abus_r / nbanks)
|
1679
|
+
# nbanks.times do |i|
|
1680
|
+
# hwhen(i) do
|
1681
|
+
# bank_brs[i].read(abus_r % nbanks,target) do
|
1682
|
+
# abus_r <= abus_r + 1
|
1683
|
+
# blk.call
|
1684
|
+
# end
|
1685
|
+
# end
|
1686
|
+
# end
|
1687
|
+
# end
|
1688
|
+
# end
|
1689
|
+
# # Write with increment
|
1690
|
+
# brancher(:winc) do
|
1691
|
+
# reader_output :abus_w
|
1692
|
+
# if br_rsts[:winc] then
|
1693
|
+
# rst_name = br_rsts[:winc].to_sym
|
1694
|
+
# else
|
1695
|
+
# rst_name = rst.name
|
1696
|
+
# writer_input rst_name
|
1697
|
+
# end
|
1698
|
+
# # Create the write branch for each bank.
|
1699
|
+
# bank_brs = banks.map do |bank|
|
1700
|
+
# bank.branch(:waddr).inner HDLRuby.uniq_name
|
1701
|
+
# end
|
1702
|
+
#
|
1703
|
+
# # Defines the read procedure at address +addr+
|
1704
|
+
# # using +target+ as target of access result.
|
1705
|
+
# writer do |blk,target|
|
1706
|
+
# # On reset the read trigger is 0.
|
1707
|
+
# rst = send(rst_name)
|
1708
|
+
# top_block.unshift do
|
1709
|
+
# # Initialize the address so that the next access is at address 0.
|
1710
|
+
# hif(rst==1) { abus_w <= 0 }
|
1711
|
+
# end
|
1712
|
+
# # Select the bank depending on the address.
|
1713
|
+
# hcase(abus_w / nbanks)
|
1714
|
+
# nbanks.times do |i|
|
1715
|
+
# hwhen(i) do
|
1716
|
+
# bank_brs[i].read(abus_w % nbanks,target) do
|
1717
|
+
# abus_w <= abus_w + 1
|
1718
|
+
# blk.call
|
1719
|
+
# end
|
1720
|
+
# end
|
1721
|
+
# end
|
1722
|
+
# end
|
1723
|
+
# end
|
1724
|
+
#
|
1725
|
+
# # The decrement branches.
|
1726
|
+
# # Read with decrement
|
1727
|
+
# brancher(:rdec) do
|
1728
|
+
# reader_output :abus_r
|
1729
|
+
# if br_rsts[:rdec] then
|
1730
|
+
# rst_name = br_rsts[:rdec].to_sym
|
1731
|
+
# else
|
1732
|
+
# rst_name = rst.name
|
1733
|
+
# reader_input rst_name
|
1734
|
+
# end
|
1735
|
+
#
|
1736
|
+
# # Defines the read procedure at address +addr+
|
1737
|
+
# # using +target+ as target of access result.
|
1738
|
+
# reader do |blk,target|
|
1739
|
+
# # On reset the read trigger is 0.
|
1740
|
+
# rst = send(rst_name)
|
1741
|
+
# top_block.unshift do
|
1742
|
+
# # Initialize the address so that the next access is at address 0.
|
1743
|
+
# hif(rst==1) { abus_r <= 0 }
|
1744
|
+
# end
|
1745
|
+
# # Select the bank depending on the address.
|
1746
|
+
# hcase(abus_r / nbanks)
|
1747
|
+
# nbanks.times do |i|
|
1748
|
+
# hwhen(i) do
|
1749
|
+
# banks[i].read(abus_r % nbanks,target) do
|
1750
|
+
# abus_r <= abus_r + 1
|
1751
|
+
# blk.call
|
1752
|
+
# end
|
1753
|
+
# end
|
1754
|
+
# end
|
1755
|
+
# end
|
1756
|
+
# end
|
1757
|
+
# # Write with decrement
|
1758
|
+
# brancher(:wdec) do
|
1759
|
+
# reader_output :abus_w
|
1760
|
+
# if br_rsts[:wdec] then
|
1761
|
+
# rst_name = br_rsts[:wdec].to_sym
|
1762
|
+
# else
|
1763
|
+
# rst_name = rst.name
|
1764
|
+
# writer_input rst_name
|
1765
|
+
# end
|
1766
|
+
#
|
1767
|
+
# # Defines the read procedure at address +addr+
|
1768
|
+
# # using +target+ as target of access result.
|
1769
|
+
# writer do |blk,target|
|
1770
|
+
# # On reset the read trigger is 0.
|
1771
|
+
# rst = send(rst_name)
|
1772
|
+
# top_block.unshift do
|
1773
|
+
# # Initialize the address so that the next access is at address 0.
|
1774
|
+
# hif(rst==1) { abus_w <= 0 }
|
1775
|
+
# end
|
1776
|
+
# # Select the bank depending on the address.
|
1777
|
+
# hcase(abus_w / nbanks)
|
1778
|
+
# nbanks.times do |i|
|
1779
|
+
# hwhen(i) do
|
1780
|
+
# banks[i].read(abus_w % nbanks,target) do
|
1781
|
+
# abus_w <= abus_w + 1
|
1782
|
+
# blk.call
|
1783
|
+
# end
|
1784
|
+
# end
|
1785
|
+
# end
|
1786
|
+
# end
|
1787
|
+
# end
|
1788
|
+
#
|
1789
|
+
# end
|