HDLRuby 2.2.17 → 2.3.4

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.
@@ -15,50 +15,53 @@ module HDLRuby::High::Std
15
15
  def self.included(base)
16
16
  # Performs the previous included
17
17
  res = self.send(:_included_fixpoint,base)
18
- # Now modify the Type class
19
- ::HDLRuby::High::Type.class_eval do
20
- # Saves the former type generation method.
21
- alias_method :"_[]_fixpoint", :[]
18
+ # Now modify the Type class if not already modified.
19
+ unless ::HDLRuby::High::Type.instance_methods.include?(:"_[]_fixpoint") then
20
+ ::HDLRuby::High::Type.class_eval do
21
+ # Saves the former type generation method.
22
+ alias_method :"_[]_fixpoint", :[]
22
23
 
23
- # Redefine the type generation method for supporting fixed point
24
- # type generation.
25
- def [](*args)
26
- if args.size == 1 then
27
- return self.send(:"_[]_fixpoint",*args)
28
- else
29
- # Handle the arguments.
30
- arg0,arg1 = *args
31
- if arg0.respond_to?(:to_i) then
32
- arg0 = (arg0.to_i.abs-1)..0
33
- end
34
- if arg1.respond_to?(:to_i) then
35
- arg1 = (arg1.to_i.abs-1)..0
36
- end
37
- # Compute the fix point sizes.
38
- isize = (arg0.first-arg0.last).abs+1
39
- fsize = (arg1.first-arg1.last).abs+1
40
- # Build the type.
41
- case(self.name)
42
- when :bit
43
- typ = bit[isize+fsize].typedef(::HDLRuby.uniq_name)
44
- when :unsigned
45
- typ = unsigned[isize+fsize].typedef(::HDLRuby.uniq_name)
46
- when :signed
47
- typ = signed[isize+fsize].typedef(::HDLRuby.uniq_name)
24
+ # Redefine the type generation method for supporting fixed point
25
+ # type generation.
26
+ def [](*args)
27
+ if args.size == 1 then
28
+ return self.send(:"_[]_fixpoint",*args)
48
29
  else
49
- raise "Invalid type for generating a fixed point type: #{self.name}"
50
- end
51
- # Redefine the multiplication and division for fixed point.
52
- typ.define_operator(:*) do |left,right|
53
- (left.as([isize+fsize*2])*right) >> fsize
54
- end
55
- typ.define_operator(:/) do |left,right|
56
- (left.as([isize+fsize*2]) << fsize) / right
30
+ # Handle the arguments and compute the fix point sizes.
31
+ arg0,arg1 = *args
32
+ if arg0.respond_to?(:to_i) then
33
+ isize = arg0
34
+ else
35
+ isize = (arg0.first-arg0.last).abs+1
36
+ end
37
+ if arg1.respond_to?(:to_i) then
38
+ fsize = arg1
39
+ else
40
+ fsize = (arg1.first-arg1.last).abs+1
41
+ end
42
+ # Build the type.
43
+ case(self.name)
44
+ when :bit
45
+ typ = bit[isize+fsize].typedef(::HDLRuby.uniq_name)
46
+ when :unsigned
47
+ typ = unsigned[isize+fsize].typedef(::HDLRuby.uniq_name)
48
+ when :signed
49
+ typ = signed[isize+fsize].typedef(::HDLRuby.uniq_name)
50
+ else
51
+ raise "Invalid type for generating a fixed point type: #{self.name}"
52
+ end
53
+ # Redefine the multiplication and division for fixed point.
54
+ typ.define_operator(:*) do |left,right|
55
+ (left.as([isize+fsize*2])*right) >> fsize
56
+ end
57
+ typ.define_operator(:/) do |left,right|
58
+ (left.as([isize+fsize*2]) << fsize) / right
59
+ end
60
+ typ
57
61
  end
58
- typ
59
62
  end
63
+ return res
60
64
  end
61
- return res
62
65
  end
63
66
  end
64
67
 
@@ -244,6 +244,74 @@ module HDLRuby::High::Std
244
244
  end
245
245
 
246
246
 
247
+ # Declares a simple pipelined multiple mac with single right data.
248
+ #
249
+ # Can be used for the product of a martix-vector product.
250
+ function :mac_np do |typ,ev,req,ack,lefts, rights, last,
251
+ mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
252
+ # Ensure ev is really an event.
253
+ ev = ev.posedge unless ev.is_a?(Event)
254
+ # Ensures lefts is an array.
255
+ lefts = lefts.to_a
256
+ # Ensures rights is an array.
257
+ rights = rights.to_a
258
+ # Get the size of the pipeline and ensure lefts and rights have the
259
+ # same.
260
+ size = lefts.size
261
+ if (rights.size != size) then
262
+ raise "Incompatible lefts and rights sizes: lefts size is #{size} and rights size is #{rights.size}"
263
+ end
264
+ # Declares the accumulators.
265
+ accs = size.times.map { |i| typ.inner :"acc#{i}" }
266
+ # Left value and right value.
267
+ lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
268
+ rvs = rights.each_with_index.map { |right,i| typ.inner :"rv#{i}" }
269
+ # typ.inner :rv
270
+ # lv and rv are valid.
271
+ lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
272
+ # inner :rvok
273
+ rvoks = rights.each_with_index.map { |right,i| inner :"rvok#{i}" }
274
+ # Run flag
275
+ inner :run
276
+ par(ev) do
277
+ ack <= 0
278
+ run <= 0
279
+ hif(req | run) do
280
+ run <= 1
281
+ # Computation request.
282
+ lefts.zip(rights).each_with_index do |(left,right),i|
283
+ left.read(lvs[i]) { lvoks[i] <= 1 }
284
+ right.read(rvs[i]) { rvoks[i] <= 1 }
285
+ hif(lvoks[i] & rvoks[i]) do
286
+ ack <= 1
287
+ run <= 0
288
+ if (i < lefts.size-1) then
289
+ if (i>0) then
290
+ accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i])) +
291
+ accs[i-1]
292
+ else
293
+ accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i]))
294
+ end
295
+ else
296
+ # The last is reached
297
+ seq do
298
+ accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i]))
299
+ last.write(accs[i])
300
+ end
301
+ end
302
+ end
303
+ end
304
+ end
305
+ helse do
306
+ lefts.each_with_index do |left,i|
307
+ lvoks[i] <= 0
308
+ rvoks[i] <= 0
309
+ accs[i] <= 0
310
+ end
311
+ end
312
+ end
313
+ end
314
+
247
315
 
248
316
 
249
317
  end
@@ -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.
@@ -342,7 +527,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
342
527
  # Defines the read procedure at address +addr+
343
528
  # using +target+ as target of access result.
344
529
  reader do |blk,target|
345
- # By default the read trigger is 0.
530
+ # On reset the read trigger is 0.
346
531
  rst = send(rst_name)
347
532
  top_block.unshift do
348
533
  # Initialize the address so that the next access is at address 0.
@@ -382,7 +567,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
382
567
  # Defines the read procedure at address +addr+
383
568
  # using +target+ as target of access result.
384
569
  writer do |blk,target|
385
- # By default the read trigger is 0.
570
+ # On reset the read trigger is 0.
386
571
  rst = send(rst_name)
387
572
  top_block.unshift do
388
573
  # Initialize the address so that the next access is at address 0.
@@ -420,7 +605,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
420
605
  # Defines the read procedure at address +addr+
421
606
  # using +target+ as target of access result.
422
607
  reader do |blk,target|
423
- # By default the read trigger is 0.
608
+ # On reset the read trigger is 0.
424
609
  rst = send(rst_name)
425
610
  top_block.unshift do
426
611
  # Initialize the address so that the next access is at address 0.
@@ -460,7 +645,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
460
645
  # Defines the read procedure at address +addr+
461
646
  # using +target+ as target of access result.
462
647
  writer do |blk,target|
463
- # By default the read trigger is 0.
648
+ # On reset the read trigger is 0.
464
649
  rst = send(rst_name)
465
650
  top_block.unshift do
466
651
  # Initialize the address so that the next access is at address 0.
@@ -675,7 +860,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
675
860
  # using +target+ as target of access result.
676
861
  reader do |blk,target|
677
862
  regs = size.times.map {|i| send(:"reg_#{i}") }
678
- # By default the read trigger is 0.
863
+ # On reset the read trigger is 0.
679
864
  rst = send(rst_name)
680
865
  top_block.unshift do
681
866
  # Initialize the address so that the next access is at address 0.
@@ -704,17 +889,17 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
704
889
  rst_name = br_rsts[:winc].to_sym
705
890
  else
706
891
  rst_name = rst.name
707
- reader_input rst_name
892
+ writer_input rst_name
708
893
  end
709
894
  # Declares the address counter.
710
895
  [size.width-1].inner :abus_w
711
- reader_inout :abus_w
896
+ writer_inout :abus_w
712
897
 
713
898
  # Defines the write procedure at address +addr+
714
899
  # using +target+ as target of access result.
715
900
  writer do |blk,target|
716
901
  regs = size.times.map {|i| send(:"reg_#{i}") }
717
- # By default the read trigger is 0.
902
+ # On reset the read trigger is 0.
718
903
  rst = send(rst_name)
719
904
  top_block.unshift do
720
905
  # Initialize the address so that the next access is at address 0.
@@ -755,7 +940,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
755
940
  # using +target+ as target of access result.
756
941
  reader do |blk,target|
757
942
  regs = size.times.map {|i| send(:"reg_#{i}") }
758
- # By default the read trigger is 0.
943
+ # On reset the read trigger is 0.
759
944
  rst = send(rst_name)
760
945
  top_block.unshift do
761
946
  # Initialize the address so that the next access is at address 0.
@@ -794,7 +979,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
794
979
  # using +target+ as target of access result.
795
980
  writer do |blk,target|
796
981
  regs = size.times.map {|i| send(:"reg_#{i}") }
797
- # By default the read trigger is 0.
982
+ # On reset the read trigger is 0.
798
983
  rst = send(rst_name)
799
984
  top_block.unshift do
800
985
  # Initialize the address so that the next access is at address 0.
@@ -817,3 +1002,788 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
817
1002
  end
818
1003
 
819
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
+
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