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.
@@ -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
@@ -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
- # It is a list, convert it to a hash with the following order:
218
- # raddr, waddr, rinc, winc, rdec, wdec, rque, wque
219
- # If there is only two entries they will be duplicated and mapped
220
- # as follows:
221
- # [raddr,waddr], [rinc,winc], [rdec,wdec], [rque,wque]
222
- # If there is only one entry it will be duplicated and mapped as
223
- # follows:
224
- # raddr, rinc, rdec, rque
225
- if br_rsts.size == 2 then
226
- br_rsts = br_rsts * 4
227
- elsif br_rsts.size == 1 then
228
- br_rsts = br_rsts * 8
229
- end
230
- br_rsts = { raddr: br_rsts[0], waddr: br_rsts[1],
231
- rinc: br_rsts[2], winc: br_rsts[3],
232
- rdec: br_rsts[4], wdec: br_rsts[5],
233
- rque: br_rsts[6], wque: br_rsts[6] }
234
- end
235
- unless br_rsts.respond_to?(:[])
236
- raise "Invalid reset mapping description: #{br_rsts}"
237
- end
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
- # # Processes handling the memory access.
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
- # hif(trig_w) { mem[abus_w] <= dbus_w }
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
- # By default the read trigger is 0.
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
- # By default the read trigger is 0.
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
- hif(trig_w == 1) do
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
- # - rnum: read by register number, the number must be a defined value.
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
- # By default the read trigger is 0.
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
- # By default the read trigger is 0.
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