HDLRuby 2.2.15 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.
@@ -714,7 +899,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
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