HDLRuby 2.11.12 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.html +3274 -0
- data/README.md +556 -84
- data/ext/hruby_sim/hruby_sim_calc.c +2 -0
- data/lib/HDLRuby/backend/hruby_allocator.rb +2 -2
- data/lib/HDLRuby/backend/hruby_c_allocator.rb +7 -7
- data/lib/HDLRuby/hdr_samples/mei8_bench.rb +1 -1
- data/lib/HDLRuby/hdr_samples/with_bram.rb +3 -3
- data/lib/HDLRuby/hdr_samples/with_bram_frame_stack.rb +105 -0
- data/lib/HDLRuby/hdr_samples/with_bram_stack.rb +69 -0
- data/lib/HDLRuby/hdr_samples/with_register_stack.rb +150 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer.rb +190 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer_deep.rb +91 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer_enumerable.rb +405 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer_enumerator.rb +89 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer_sync.rb +120 -0
- data/lib/HDLRuby/hdrcc.rb +15 -2
- data/lib/HDLRuby/hdrlib.rb +1 -1
- data/lib/HDLRuby/hruby_db.rb +2 -2
- data/lib/HDLRuby/hruby_high.rb +38 -20
- data/lib/HDLRuby/hruby_high_fullname.rb +3 -1
- data/lib/HDLRuby/hruby_low.rb +2 -2
- data/lib/HDLRuby/hruby_low2c.rb +58 -43
- data/lib/HDLRuby/hruby_low2hdr.rb +66 -40
- data/lib/HDLRuby/hruby_low2high.rb +86 -44
- data/lib/HDLRuby/hruby_low2seq.rb +26 -18
- data/lib/HDLRuby/hruby_low2sym.rb +14 -13
- data/lib/HDLRuby/hruby_low2vhd.rb +78 -43
- data/lib/HDLRuby/hruby_low_bool2select.rb +61 -46
- data/lib/HDLRuby/hruby_low_casts_without_expression.rb +56 -44
- data/lib/HDLRuby/hruby_low_cleanup.rb +18 -16
- data/lib/HDLRuby/hruby_low_fix_types.rb +64 -32
- data/lib/HDLRuby/hruby_low_mutable.rb +53 -118
- data/lib/HDLRuby/hruby_low_resolve.rb +26 -31
- data/lib/HDLRuby/hruby_low_with_bool.rb +33 -16
- data/lib/HDLRuby/hruby_low_with_port.rb +3 -3
- data/lib/HDLRuby/hruby_low_with_var.rb +23 -9
- data/lib/HDLRuby/hruby_low_without_concat.rb +19 -13
- data/lib/HDLRuby/hruby_low_without_namespace.rb +47 -32
- data/lib/HDLRuby/hruby_low_without_parinseq.rb +18 -12
- data/lib/HDLRuby/hruby_low_without_select.rb +36 -23
- data/lib/HDLRuby/hruby_low_without_subsignals.rb +29 -28
- data/lib/HDLRuby/hruby_rcsim.rb +79 -64
- data/lib/HDLRuby/hruby_rsim.rb +64 -15
- data/lib/HDLRuby/hruby_rsim_mute.rb +2 -3
- data/lib/HDLRuby/hruby_rsim_vcd.rb +28 -25
- data/lib/HDLRuby/hruby_values.rb +13 -2
- data/lib/HDLRuby/hruby_verilog.rb +90 -48
- data/lib/HDLRuby/soft/stacks.rb +219 -0
- data/lib/HDLRuby/std/bram.rb +9 -5
- data/lib/HDLRuby/std/clocks.rb +1 -1
- data/lib/HDLRuby/std/fsm.rb +29 -9
- data/lib/HDLRuby/std/sequencer.rb +1857 -0
- data/lib/HDLRuby/std/sequencer_sync.rb +400 -0
- data/lib/HDLRuby/std/std.rb +12 -0
- data/lib/HDLRuby/version.rb +1 -1
- data/tuto/adder_sat_flags_vcd.png +0 -0
- data/tuto/addsub_vcd.png +0 -0
- data/tuto/alu_vcd.png +0 -0
- data/tuto/bit_pong_vcd.png +0 -0
- data/tuto/checksum_vcd.png +0 -0
- data/tuto/circuit_hdr.odg +0 -0
- data/tuto/circuit_hdr.png +0 -0
- data/tuto/circuit_hie.odg +0 -0
- data/tuto/circuit_hie.png +0 -0
- data/tuto/circuit_view.odg +0 -0
- data/tuto/circuit_view.png +0 -0
- data/tuto/clock_counter_vcd.png +0 -0
- data/tuto/counter_ext_vcd.png +0 -0
- data/tuto/fact_vcd.png +0 -0
- data/tuto/hw_flow.odg +0 -0
- data/tuto/hw_flow.png +0 -0
- data/tuto/maxxer_vcd.png +0 -0
- data/tuto/pingpong0_vcd.png +0 -0
- data/tuto/pingpong1_vcd.png +0 -0
- data/tuto/pingpong2_vcd.png +0 -0
- data/tuto/ram_vcd.png +0 -0
- data/tuto/serializer_vcd.png +0 -0
- data/tuto/sw_flow.odg +0 -0
- data/tuto/sw_flow.png +0 -0
- data/tuto/the_counter_vcd.png +0 -0
- data/tuto/tutorial_sw.html +2359 -0
- data/tuto/tutorial_sw.md +2684 -0
- data/tuto/tutorial_sw.pdf +0 -0
- data/tuto/tutorial_sw_jp.md +417 -0
- metadata +44 -2
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
require 'std/bram'
|
|
2
|
+
|
|
3
|
+
module HDLRuby::High::Soft
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# Declare the possible commands for the stack.
|
|
7
|
+
PUSH = 0 # Pushes the value of input din into the stack.
|
|
8
|
+
POP = 1 # Pops din values for the stack. If din is negative, allocates din elements on the stack.
|
|
9
|
+
READ = 2 # Read the value address din and output it on dout.
|
|
10
|
+
WRITE = 3 # Write the value at the top of the stack at address din.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Describe a stack based on a BRAM (compatible with FPGA's)
|
|
17
|
+
# - 'widthD': data bit width
|
|
18
|
+
# - 'size' : the size of the stack
|
|
19
|
+
system :bram_stack do |widthD, size|
|
|
20
|
+
# Compute the address width.
|
|
21
|
+
widthA = (size-1).width
|
|
22
|
+
|
|
23
|
+
# Compute the bit width of the stack pointer register.
|
|
24
|
+
widthS = (size+1).width
|
|
25
|
+
|
|
26
|
+
# Declare the inputs and outputs.
|
|
27
|
+
input :clk, :rst, :ce
|
|
28
|
+
input :cmd
|
|
29
|
+
[widthD].input :din
|
|
30
|
+
[widthD].output :dout
|
|
31
|
+
output :empty, :full
|
|
32
|
+
|
|
33
|
+
# Declare the BRAM containing the stack data.
|
|
34
|
+
inner rwb: 1
|
|
35
|
+
[widthA].inner :addr
|
|
36
|
+
[widthD].inner :brin, :brout
|
|
37
|
+
bram(widthA,widthD).(:bramI).(clk,rwb,addr,brin,brout)
|
|
38
|
+
|
|
39
|
+
# Declare the stack pointer register and the top of stack value.
|
|
40
|
+
[widthS].inner sp: size
|
|
41
|
+
[widthD].inner :top
|
|
42
|
+
|
|
43
|
+
# Tells if the stack is empty or full.
|
|
44
|
+
empty <= (sp == size)
|
|
45
|
+
full <= (sp == 0)
|
|
46
|
+
|
|
47
|
+
# The output bus is the top of the stack.
|
|
48
|
+
dout <= top
|
|
49
|
+
|
|
50
|
+
# The clock process handling the access.
|
|
51
|
+
seq(clk.posedge) do
|
|
52
|
+
# By default, read before the top of the memory.
|
|
53
|
+
rwb <= 1
|
|
54
|
+
hif(rst) do
|
|
55
|
+
# sp is set to size (stack empty).
|
|
56
|
+
sp <= size
|
|
57
|
+
top <= 0
|
|
58
|
+
end
|
|
59
|
+
helsif(ce) do
|
|
60
|
+
# Now depending on the command.
|
|
61
|
+
hcase(cmd)
|
|
62
|
+
hwhen(PUSH) do
|
|
63
|
+
# Is the stack full?
|
|
64
|
+
hif(~full) do
|
|
65
|
+
# No, can push onto the stack.
|
|
66
|
+
# Update the top register.
|
|
67
|
+
top <= din
|
|
68
|
+
# Update the bram.
|
|
69
|
+
brin <= din
|
|
70
|
+
rwb <= 0
|
|
71
|
+
# Finally, decrease sp.
|
|
72
|
+
sp <= sp - 1
|
|
73
|
+
# The address is the top of the stack
|
|
74
|
+
addr <= sp
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
hwhen(POP) do
|
|
78
|
+
# Is the stack empty?
|
|
79
|
+
hif(~empty) do
|
|
80
|
+
# No, can pop from the stack.
|
|
81
|
+
# Update the top register.
|
|
82
|
+
top <= brout
|
|
83
|
+
# Finally, increase sp.
|
|
84
|
+
sp <= sp + 1
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
hif(~ce | cmd != PUSH) do
|
|
89
|
+
# By default the address is the top of the stack + 1
|
|
90
|
+
addr <= sp + 1
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# Describe a frame stack based on a BRAM (compatible with FPGA's)
|
|
98
|
+
# - 'widthD': data bit width
|
|
99
|
+
# - 'size' : the size of the stack
|
|
100
|
+
# - 'depth' : the maximum number of frames.
|
|
101
|
+
system :bram_frame_stack do |widthD, size, depth|
|
|
102
|
+
# Compute the address width.
|
|
103
|
+
widthA = (size-1).width
|
|
104
|
+
|
|
105
|
+
# Compute the bit width of the frame pointers.
|
|
106
|
+
widthF = (size+1).width
|
|
107
|
+
|
|
108
|
+
# compute the bit width of the frame stack pointer.
|
|
109
|
+
widthS = (depth+1).width
|
|
110
|
+
|
|
111
|
+
# Create the type used for accessing the frame stack.
|
|
112
|
+
typedef(:locT) { { frame: bit[widthS], offset: bit[widthF] } }
|
|
113
|
+
|
|
114
|
+
# Declare the inputs and outputs.
|
|
115
|
+
input :clk, :rst, :ce
|
|
116
|
+
[2].input :cmd
|
|
117
|
+
locT.input :loc
|
|
118
|
+
[widthD].input :din
|
|
119
|
+
[widthD].output :dout
|
|
120
|
+
output :empty, :full
|
|
121
|
+
|
|
122
|
+
# Declare the frame index stac pointer.
|
|
123
|
+
[widthS].inner :sp
|
|
124
|
+
|
|
125
|
+
# Declare the frame index table.
|
|
126
|
+
bit[widthF][-depth].inner :indexes
|
|
127
|
+
|
|
128
|
+
# Declare the BRAM containing the frames data.
|
|
129
|
+
inner rwb: 1
|
|
130
|
+
[widthA].inner :addr
|
|
131
|
+
[widthD].inner :brin, :brout
|
|
132
|
+
bram(widthA,widthD).(:bramI).(clk,rwb,addr,brin,brout)
|
|
133
|
+
|
|
134
|
+
# Tells if the stack is empty or full.
|
|
135
|
+
empty <= (sp == depth)
|
|
136
|
+
full <= (sp == 0)
|
|
137
|
+
|
|
138
|
+
# The input data is always the input of the bram.
|
|
139
|
+
brin <= din
|
|
140
|
+
|
|
141
|
+
# The output is always the output of the bram.
|
|
142
|
+
dout <= brout
|
|
143
|
+
|
|
144
|
+
# The clock process handling the access.
|
|
145
|
+
seq(clk.posedge) do
|
|
146
|
+
# By default, read before the top of the memory.
|
|
147
|
+
rwb <= 1
|
|
148
|
+
hif(rst) do
|
|
149
|
+
# sp is set to depth (stack empty).
|
|
150
|
+
sp <= depth
|
|
151
|
+
end
|
|
152
|
+
helsif(ce) do
|
|
153
|
+
# Now depending on the command.
|
|
154
|
+
hcase(cmd)
|
|
155
|
+
hwhen(PUSH) do
|
|
156
|
+
# Is the stack full or is the frame to push empty?
|
|
157
|
+
hif(~(full | loc.offset == 0)) do
|
|
158
|
+
# No, we can proceed.
|
|
159
|
+
# Decrease sp.
|
|
160
|
+
sp <= sp - 1
|
|
161
|
+
# Adds the frame.
|
|
162
|
+
hif(~empty) do
|
|
163
|
+
indexes[sp] <= loc.offset + indexes[sp+1]
|
|
164
|
+
end
|
|
165
|
+
helse do
|
|
166
|
+
indexes[sp] <= loc.offset
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
hwhen(POP) do
|
|
171
|
+
# Is the stack empty?
|
|
172
|
+
hif(~empty) do
|
|
173
|
+
# No, can pop a frame from the stack.
|
|
174
|
+
# Increase sp.
|
|
175
|
+
sp <= sp + 1
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
hwhen(READ) do
|
|
179
|
+
# Read access, is the frame valid?
|
|
180
|
+
cur_frame = sp+loc.frame
|
|
181
|
+
hif (~(empty | cur_frame >= depth)) do
|
|
182
|
+
# The frame is valid. Is the offset valid?
|
|
183
|
+
addr_calc = indexes[cur_frame] - loc.offset - 1
|
|
184
|
+
hif ((cur_frame < depth-1) &
|
|
185
|
+
(addr_calc > indexes[cur_frame+1])) do
|
|
186
|
+
# Not the first frame and the address is valid.
|
|
187
|
+
addr <= addr_calc
|
|
188
|
+
end
|
|
189
|
+
helsif ((cur_frame == depth-1) &
|
|
190
|
+
(addr_calc + 1 > 0)) do
|
|
191
|
+
# The first frame and the address is valid.
|
|
192
|
+
addr <= addr_calc
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
hwhen(WRITE) do
|
|
197
|
+
# Write access, is the frame valid?
|
|
198
|
+
cur_frame = sp+loc.frame
|
|
199
|
+
hif (~(empty | cur_frame >= depth)) do
|
|
200
|
+
# The frame is valid. Is the offset valid?
|
|
201
|
+
addr_calc = indexes[cur_frame] - loc.offset - 1
|
|
202
|
+
hif ((cur_frame < depth-1) &
|
|
203
|
+
(addr_calc > indexes[cur_frame+1])) do
|
|
204
|
+
# Not the first frame and the address is valid.
|
|
205
|
+
addr <= addr_calc
|
|
206
|
+
rwb <= 0
|
|
207
|
+
end
|
|
208
|
+
helsif ((cur_frame == depth-1) &
|
|
209
|
+
(addr_calc + 1 > 0)) do
|
|
210
|
+
# The first frame and the address is valid.
|
|
211
|
+
addr <= addr_calc
|
|
212
|
+
rwb <= 0
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
data/lib/HDLRuby/std/bram.rb
CHANGED
|
@@ -3,18 +3,22 @@ module HDLRuby::High::Std
|
|
|
3
3
|
# Describe a RAM compatibile with BRAM of FPGAs.
|
|
4
4
|
# - 'widthA': address bit width
|
|
5
5
|
# - 'widthD': data bit width
|
|
6
|
-
|
|
6
|
+
# - 'size': the size of the memory.
|
|
7
|
+
system :bram do |widthA, widthD, size = nil|
|
|
8
|
+
# Process size if required.
|
|
9
|
+
size = 2**widthA unless size
|
|
10
|
+
# puts "widthA=#{widthA} widthD=#{widthD} size=#{size}"
|
|
11
|
+
|
|
12
|
+
# Declares the io of the ram.
|
|
7
13
|
input :clk, :rwb
|
|
8
14
|
[widthA].input :addr
|
|
9
15
|
[widthD].input :din
|
|
10
16
|
[widthD].output :dout
|
|
11
17
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
bit[widthD][-2**widthA].inner mem: [ :"_b#{"0"*widthD}".to_value ] * 2**widthA
|
|
18
|
+
bit[widthD][-size].inner mem: [ :"_b#{"0"*widthD}".to_value ] * size
|
|
15
19
|
|
|
16
20
|
par(clk.negedge) do
|
|
17
|
-
hif(rwb ==
|
|
21
|
+
hif(rwb == 0) { mem[addr] <= din }
|
|
18
22
|
dout <= mem[addr]
|
|
19
23
|
end
|
|
20
24
|
end
|
data/lib/HDLRuby/std/clocks.rb
CHANGED
|
@@ -135,8 +135,8 @@ module HDLRuby::High::Std
|
|
|
135
135
|
end
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
# Enhnace the events with multiply operator.
|
|
139
138
|
class HDLRuby::High::Event
|
|
139
|
+
# Enhance the events with multiply operator.
|
|
140
140
|
|
|
141
141
|
# Creates a new event activated every +times+ occurences of the
|
|
142
142
|
# current event.
|
data/lib/HDLRuby/std/fsm.rb
CHANGED
|
@@ -31,8 +31,10 @@ module HDLRuby::High::Std
|
|
|
31
31
|
|
|
32
32
|
# Creates a new fsm type with +name+.
|
|
33
33
|
# +options+ allows to specify the type of fsm:
|
|
34
|
-
# synchronous (default)
|
|
35
|
-
#
|
|
34
|
+
# - :sync, :synchronous : synchronous (default)
|
|
35
|
+
# - :async, :asynchronous : asynchronous
|
|
36
|
+
# - :dual : dual front
|
|
37
|
+
# - :seq, :blocking : use blocking assignments
|
|
36
38
|
def initialize(name,*options)
|
|
37
39
|
# Check and set the name
|
|
38
40
|
@name = name.to_sym
|
|
@@ -40,6 +42,7 @@ module HDLRuby::High::Std
|
|
|
40
42
|
@dual = false
|
|
41
43
|
@type = :sync # By default, the FSM is synchronous.
|
|
42
44
|
@sequential = true # By default, the default next state is the next one in the list.
|
|
45
|
+
@blocking = false # By default, use non-blocking assignments (par)
|
|
43
46
|
options.each do |opt|
|
|
44
47
|
case opt
|
|
45
48
|
when :sync,:synchronous then
|
|
@@ -50,10 +53,23 @@ module HDLRuby::High::Std
|
|
|
50
53
|
@dual = true
|
|
51
54
|
when :static then
|
|
52
55
|
@sequential = false
|
|
56
|
+
when :seq then
|
|
57
|
+
@blocking = true
|
|
58
|
+
when :blocking then
|
|
59
|
+
@blocking = true
|
|
53
60
|
else
|
|
54
61
|
raise AnyError, "Invalid option for a fsm: :#{type}"
|
|
55
62
|
end
|
|
56
63
|
end
|
|
64
|
+
if @blocking then
|
|
65
|
+
define_singleton_method(:fsm_block) do |*args,&ruby_block|
|
|
66
|
+
send(:seq,*args,&ruby_block)
|
|
67
|
+
end
|
|
68
|
+
else
|
|
69
|
+
define_singleton_method(:fsm_block) do |*args,&ruby_block|
|
|
70
|
+
send(:par,*args,&ruby_block)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
57
73
|
|
|
58
74
|
# Initialize the internals of the FSM.
|
|
59
75
|
|
|
@@ -127,7 +143,8 @@ module HDLRuby::High::Std
|
|
|
127
143
|
# sub do
|
|
128
144
|
HDLRuby::High.space_push(namespace)
|
|
129
145
|
# Execute the instantiation block
|
|
130
|
-
return_value = HDLRuby::High.top_user.instance_exec(&ruby_block)
|
|
146
|
+
# return_value = HDLRuby::High.top_user.instance_exec(&ruby_block)
|
|
147
|
+
return_value = HDLRuby::High.top_user.instance_exec(&ruby_block) if ruby_block
|
|
131
148
|
|
|
132
149
|
# Expands the extra state processing so that al all the
|
|
133
150
|
# parts of the state machine are in par (clear synthesis).
|
|
@@ -171,7 +188,8 @@ module HDLRuby::High::Std
|
|
|
171
188
|
# Create the fsm code
|
|
172
189
|
|
|
173
190
|
# Control part: update of the state.
|
|
174
|
-
par(mk_ev.call) do
|
|
191
|
+
# par(mk_ev.call) do
|
|
192
|
+
fsm_block(mk_ev.call) do
|
|
175
193
|
hif(mk_rst.call) do
|
|
176
194
|
# Reset: current state is to put to 0.
|
|
177
195
|
this.cur_state_sig <= 0
|
|
@@ -194,7 +212,8 @@ module HDLRuby::High::Std
|
|
|
194
212
|
event = []
|
|
195
213
|
end
|
|
196
214
|
# The process
|
|
197
|
-
par(*event) do
|
|
215
|
+
# par(*event) do
|
|
216
|
+
fsm_block(*event) do
|
|
198
217
|
# The operative code.
|
|
199
218
|
oper_code = proc do
|
|
200
219
|
# The default code.
|
|
@@ -241,8 +260,6 @@ module HDLRuby::High::Std
|
|
|
241
260
|
st.gotos.each(&:call)
|
|
242
261
|
else
|
|
243
262
|
# No gotos, by default the next step is
|
|
244
|
-
# current + 1
|
|
245
|
-
# this.next_state_sig <= this.cur_state_sig + 1
|
|
246
263
|
if sequential then
|
|
247
264
|
this.next_state_sig <= this.cur_state_sig + 1
|
|
248
265
|
end
|
|
@@ -251,6 +268,7 @@ module HDLRuby::High::Std
|
|
|
251
268
|
end
|
|
252
269
|
# By default set the next state to 0.
|
|
253
270
|
helse do
|
|
271
|
+
# hprint("Unknow state case: ",this.cur_state_sig,"\n")
|
|
254
272
|
this.next_state_sig <= 0
|
|
255
273
|
end
|
|
256
274
|
|
|
@@ -260,7 +278,8 @@ module HDLRuby::High::Std
|
|
|
260
278
|
event = mk_ev.call
|
|
261
279
|
event = event.invert if @dual
|
|
262
280
|
# The extra code.
|
|
263
|
-
par(*event) do
|
|
281
|
+
# par(*event) do
|
|
282
|
+
fsm_block(*event) do
|
|
264
283
|
# Build the extra synchronous part.
|
|
265
284
|
sync_code = proc do
|
|
266
285
|
hcase(this.cur_state_sig)
|
|
@@ -289,7 +308,8 @@ module HDLRuby::High::Std
|
|
|
289
308
|
|
|
290
309
|
# Extra asynchronous operative part.
|
|
291
310
|
if extra_asyncs.any? then
|
|
292
|
-
par do
|
|
311
|
+
# par do
|
|
312
|
+
fsm_block do
|
|
293
313
|
# Build the extra synchronous part.
|
|
294
314
|
async_code = proc do
|
|
295
315
|
hcase(this.cur_state_sig)
|