HDLRuby 2.0.8
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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/HDLRuby.gemspec +36 -0
- data/LICENSE.txt +21 -0
- data/README.md +2774 -0
- data/README.pdf +0 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/hdrcc +3 -0
- data/lib/HDLRuby/alcc.rb +137 -0
- data/lib/HDLRuby/backend/hruby_allocator.rb +69 -0
- data/lib/HDLRuby/backend/hruby_c_allocator.rb +76 -0
- data/lib/HDLRuby/hdr_samples/adder.rb +7 -0
- data/lib/HDLRuby/hdr_samples/adder_assign_error.rb +11 -0
- data/lib/HDLRuby/hdr_samples/adder_bench.rb +27 -0
- data/lib/HDLRuby/hdr_samples/adder_gen.rb +7 -0
- data/lib/HDLRuby/hdr_samples/adder_nodef_error.rb +7 -0
- data/lib/HDLRuby/hdr_samples/addsub.rb +19 -0
- data/lib/HDLRuby/hdr_samples/addsubz.rb +22 -0
- data/lib/HDLRuby/hdr_samples/alu.rb +47 -0
- data/lib/HDLRuby/hdr_samples/calculator.rb +48 -0
- data/lib/HDLRuby/hdr_samples/counter_bench.rb +83 -0
- data/lib/HDLRuby/hdr_samples/dff.rb +9 -0
- data/lib/HDLRuby/hdr_samples/dff_bench.rb +66 -0
- data/lib/HDLRuby/hdr_samples/dff_counter.rb +20 -0
- data/lib/HDLRuby/hdr_samples/include.rb +14 -0
- data/lib/HDLRuby/hdr_samples/instance_open.rb +23 -0
- data/lib/HDLRuby/hdr_samples/mei8.rb +256 -0
- data/lib/HDLRuby/hdr_samples/mei8_bench.rb +309 -0
- data/lib/HDLRuby/hdr_samples/multer_gen.rb +8 -0
- data/lib/HDLRuby/hdr_samples/multer_seq.rb +29 -0
- data/lib/HDLRuby/hdr_samples/neural/a.rb +9 -0
- data/lib/HDLRuby/hdr_samples/neural/a_sub.rb +5 -0
- data/lib/HDLRuby/hdr_samples/neural/bw.rb +23 -0
- data/lib/HDLRuby/hdr_samples/neural/counter.rb +16 -0
- data/lib/HDLRuby/hdr_samples/neural/dadz.rb +9 -0
- data/lib/HDLRuby/hdr_samples/neural/dadz_sub.rb +4 -0
- data/lib/HDLRuby/hdr_samples/neural/forward.rb +153 -0
- data/lib/HDLRuby/hdr_samples/neural/forward_sub.rb +62 -0
- data/lib/HDLRuby/hdr_samples/neural/forward_sub_rand.rb +41 -0
- data/lib/HDLRuby/hdr_samples/neural/forward_sub_rand_typedef.rb +47 -0
- data/lib/HDLRuby/hdr_samples/neural/mem.rb +30 -0
- data/lib/HDLRuby/hdr_samples/neural/random.rb +23 -0
- data/lib/HDLRuby/hdr_samples/neural/selector.rb +29 -0
- data/lib/HDLRuby/hdr_samples/neural/sigmoid.rb +20 -0
- data/lib/HDLRuby/hdr_samples/neural/z.rb +33 -0
- data/lib/HDLRuby/hdr_samples/prog.obj +256 -0
- data/lib/HDLRuby/hdr_samples/ram.rb +18 -0
- data/lib/HDLRuby/hdr_samples/register_with_code_bench.rb +98 -0
- data/lib/HDLRuby/hdr_samples/rom.rb +10 -0
- data/lib/HDLRuby/hdr_samples/struct.rb +14 -0
- data/lib/HDLRuby/hdr_samples/sumprod.rb +29 -0
- data/lib/HDLRuby/hdr_samples/sw_encrypt_bench.rb +103 -0
- data/lib/HDLRuby/hdr_samples/sw_encrypt_cpu_bench.rb +261 -0
- data/lib/HDLRuby/hdr_samples/sw_encrypt_cpusim_bench.rb +302 -0
- data/lib/HDLRuby/hdr_samples/system_open.rb +11 -0
- data/lib/HDLRuby/hdr_samples/tuple.rb +16 -0
- data/lib/HDLRuby/hdr_samples/with_channel.rb +118 -0
- data/lib/HDLRuby/hdr_samples/with_class.rb +199 -0
- data/lib/HDLRuby/hdr_samples/with_decoder.rb +17 -0
- data/lib/HDLRuby/hdr_samples/with_fsm.rb +34 -0
- data/lib/HDLRuby/hdr_samples/with_reconf.rb +103 -0
- data/lib/HDLRuby/hdrcc.rb +623 -0
- data/lib/HDLRuby/high_samples/_adder_fault.rb +23 -0
- data/lib/HDLRuby/high_samples/_generic_transmission2.rb +146 -0
- data/lib/HDLRuby/high_samples/adder.rb +21 -0
- data/lib/HDLRuby/high_samples/adder_common_errors.rb +25 -0
- data/lib/HDLRuby/high_samples/addsub.rb +33 -0
- data/lib/HDLRuby/high_samples/addsubz.rb +37 -0
- data/lib/HDLRuby/high_samples/after.rb +28 -0
- data/lib/HDLRuby/high_samples/all_signals.rb +29 -0
- data/lib/HDLRuby/high_samples/alu.rb +61 -0
- data/lib/HDLRuby/high_samples/anonymous.rb +41 -0
- data/lib/HDLRuby/high_samples/before.rb +28 -0
- data/lib/HDLRuby/high_samples/blockblock.rb +26 -0
- data/lib/HDLRuby/high_samples/bugs/dadz.rb +22 -0
- data/lib/HDLRuby/high_samples/bugs/misample_instan.rb +20 -0
- data/lib/HDLRuby/high_samples/bugs/misample_updown.rb +22 -0
- data/lib/HDLRuby/high_samples/bugs/sample_add.rb +16 -0
- data/lib/HDLRuby/high_samples/bugs/sample_barrel.rb +13 -0
- data/lib/HDLRuby/high_samples/bugs/sample_daice.rb +57 -0
- data/lib/HDLRuby/high_samples/bugs/sample_kumiawase.rb +52 -0
- data/lib/HDLRuby/high_samples/bugs/sample_multi.rb +18 -0
- data/lib/HDLRuby/high_samples/bugs/sample_sub.rb +14 -0
- data/lib/HDLRuby/high_samples/bugs/z2.rb +32 -0
- data/lib/HDLRuby/high_samples/case.rb +32 -0
- data/lib/HDLRuby/high_samples/case2.rb +30 -0
- data/lib/HDLRuby/high_samples/change.rb +23 -0
- data/lib/HDLRuby/high_samples/clocks.rb +35 -0
- data/lib/HDLRuby/high_samples/comparer.rb +21 -0
- data/lib/HDLRuby/high_samples/conditionals.rb +29 -0
- data/lib/HDLRuby/high_samples/dff.rb +23 -0
- data/lib/HDLRuby/high_samples/each.rb +28 -0
- data/lib/HDLRuby/high_samples/exporter.rb +42 -0
- data/lib/HDLRuby/high_samples/functions.rb +60 -0
- data/lib/HDLRuby/high_samples/if_seq.rb +26 -0
- data/lib/HDLRuby/high_samples/inherit_as_dff.rb +32 -0
- data/lib/HDLRuby/high_samples/inherit_dff.rb +36 -0
- data/lib/HDLRuby/high_samples/instance.rb +37 -0
- data/lib/HDLRuby/high_samples/memory.rb +64 -0
- data/lib/HDLRuby/high_samples/multi_file.rb +27 -0
- data/lib/HDLRuby/high_samples/overload.rb +32 -0
- data/lib/HDLRuby/high_samples/paper_after.rb +49 -0
- data/lib/HDLRuby/high_samples/ram.rb +27 -0
- data/lib/HDLRuby/high_samples/registers.rb +139 -0
- data/lib/HDLRuby/high_samples/rom.rb +23 -0
- data/lib/HDLRuby/high_samples/scopeblockname.rb +37 -0
- data/lib/HDLRuby/high_samples/scopescope.rb +26 -0
- data/lib/HDLRuby/high_samples/shift.rb +31 -0
- data/lib/HDLRuby/high_samples/shift2.rb +40 -0
- data/lib/HDLRuby/high_samples/simple_instance.rb +31 -0
- data/lib/HDLRuby/high_samples/test_all.sh +10 -0
- data/lib/HDLRuby/high_samples/typedef.rb +24 -0
- data/lib/HDLRuby/high_samples/values.rb +70 -0
- data/lib/HDLRuby/high_samples/vector.rb +22 -0
- data/lib/HDLRuby/high_samples/with_decoder.rb +30 -0
- data/lib/HDLRuby/high_samples/with_fsm.rb +46 -0
- data/lib/HDLRuby/high_samples/with_pipe.rb +43 -0
- data/lib/HDLRuby/high_samples/with_seq.rb +25 -0
- data/lib/HDLRuby/hruby_bstr.rb +1085 -0
- data/lib/HDLRuby/hruby_check.rb +317 -0
- data/lib/HDLRuby/hruby_db.rb +432 -0
- data/lib/HDLRuby/hruby_error.rb +44 -0
- data/lib/HDLRuby/hruby_high.rb +4103 -0
- data/lib/HDLRuby/hruby_low.rb +4735 -0
- data/lib/HDLRuby/hruby_low2c.rb +1986 -0
- data/lib/HDLRuby/hruby_low2high.rb +738 -0
- data/lib/HDLRuby/hruby_low2seq.rb +248 -0
- data/lib/HDLRuby/hruby_low2sym.rb +126 -0
- data/lib/HDLRuby/hruby_low2vhd.rb +1437 -0
- data/lib/HDLRuby/hruby_low_bool2select.rb +295 -0
- data/lib/HDLRuby/hruby_low_cleanup.rb +193 -0
- data/lib/HDLRuby/hruby_low_fix_types.rb +437 -0
- data/lib/HDLRuby/hruby_low_mutable.rb +1803 -0
- data/lib/HDLRuby/hruby_low_resolve.rb +165 -0
- data/lib/HDLRuby/hruby_low_skeleton.rb +129 -0
- data/lib/HDLRuby/hruby_low_with_bool.rb +141 -0
- data/lib/HDLRuby/hruby_low_with_port.rb +167 -0
- data/lib/HDLRuby/hruby_low_with_var.rb +302 -0
- data/lib/HDLRuby/hruby_low_without_bit2vector.rb +88 -0
- data/lib/HDLRuby/hruby_low_without_concat.rb +162 -0
- data/lib/HDLRuby/hruby_low_without_connection.rb +113 -0
- data/lib/HDLRuby/hruby_low_without_namespace.rb +718 -0
- data/lib/HDLRuby/hruby_low_without_outread.rb +107 -0
- data/lib/HDLRuby/hruby_low_without_select.rb +206 -0
- data/lib/HDLRuby/hruby_serializer.rb +398 -0
- data/lib/HDLRuby/hruby_tools.rb +37 -0
- data/lib/HDLRuby/hruby_types.rb +239 -0
- data/lib/HDLRuby/hruby_values.rb +64 -0
- data/lib/HDLRuby/hruby_verilog.rb +1888 -0
- data/lib/HDLRuby/hruby_verilog_name.rb +52 -0
- data/lib/HDLRuby/low_samples/adder.yaml +97 -0
- data/lib/HDLRuby/low_samples/after.yaml +228 -0
- data/lib/HDLRuby/low_samples/before.yaml +223 -0
- data/lib/HDLRuby/low_samples/blockblock.yaml +48 -0
- data/lib/HDLRuby/low_samples/bugs/sample_add.yaml +97 -0
- data/lib/HDLRuby/low_samples/bugs/sample_daice.yaml +444 -0
- data/lib/HDLRuby/low_samples/bugs/sample_kumiawase.yaml +332 -0
- data/lib/HDLRuby/low_samples/bugs/sample_sub.yaml +97 -0
- data/lib/HDLRuby/low_samples/bugs/seqpar.yaml +184 -0
- data/lib/HDLRuby/low_samples/case.yaml +327 -0
- data/lib/HDLRuby/low_samples/change.yaml +135 -0
- data/lib/HDLRuby/low_samples/clocks.yaml +674 -0
- data/lib/HDLRuby/low_samples/cloner.rb +22 -0
- data/lib/HDLRuby/low_samples/comparer.yaml +85 -0
- data/lib/HDLRuby/low_samples/conditionals.yaml +133 -0
- data/lib/HDLRuby/low_samples/dff.yaml +107 -0
- data/lib/HDLRuby/low_samples/each.yaml +1328 -0
- data/lib/HDLRuby/low_samples/exporter.yaml +226 -0
- data/lib/HDLRuby/low_samples/functions.yaml +298 -0
- data/lib/HDLRuby/low_samples/generic_transmission.yaml +597 -0
- data/lib/HDLRuby/low_samples/inherit_as_dff.yaml +125 -0
- data/lib/HDLRuby/low_samples/inherit_dff.yaml +107 -0
- data/lib/HDLRuby/low_samples/load_yaml.rb +11 -0
- data/lib/HDLRuby/low_samples/memory.yaml +678 -0
- data/lib/HDLRuby/low_samples/namespace_extractor.rb +23 -0
- data/lib/HDLRuby/low_samples/overload.yaml +226 -0
- data/lib/HDLRuby/low_samples/paper_after.yaml +431 -0
- data/lib/HDLRuby/low_samples/port_maker.rb +14 -0
- data/lib/HDLRuby/low_samples/ram.yaml +207 -0
- data/lib/HDLRuby/low_samples/registers.yaml +228 -0
- data/lib/HDLRuby/low_samples/rom.yaml +2950 -0
- data/lib/HDLRuby/low_samples/shift.yaml +230 -0
- data/lib/HDLRuby/low_samples/shift2.yaml +2095 -0
- data/lib/HDLRuby/low_samples/simple_instance.yaml +102 -0
- data/lib/HDLRuby/low_samples/test_all.sh +43 -0
- data/lib/HDLRuby/low_samples/typedef.yaml +115 -0
- data/lib/HDLRuby/low_samples/values.yaml +577 -0
- data/lib/HDLRuby/low_samples/variable_maker.rb +14 -0
- data/lib/HDLRuby/low_samples/vector.yaml +56 -0
- data/lib/HDLRuby/low_samples/with_seq.yaml +188 -0
- data/lib/HDLRuby/low_samples/yaml2hdr.rb +10 -0
- data/lib/HDLRuby/low_samples/yaml2vhd.rb +19 -0
- data/lib/HDLRuby/sim/Makefile +19 -0
- data/lib/HDLRuby/sim/hruby_sim.h +590 -0
- data/lib/HDLRuby/sim/hruby_sim_calc.c +2362 -0
- data/lib/HDLRuby/sim/hruby_sim_core.c +589 -0
- data/lib/HDLRuby/sim/hruby_sim_list.c +93 -0
- data/lib/HDLRuby/sim/hruby_sim_vizualize.c +91 -0
- data/lib/HDLRuby/sim/hruby_value_pool.c +64 -0
- data/lib/HDLRuby/std/channel.rb +354 -0
- data/lib/HDLRuby/std/clocks.rb +165 -0
- data/lib/HDLRuby/std/counters.rb +82 -0
- data/lib/HDLRuby/std/decoder.rb +214 -0
- data/lib/HDLRuby/std/fsm.rb +516 -0
- data/lib/HDLRuby/std/pipeline.rb +220 -0
- data/lib/HDLRuby/std/reconf.rb +309 -0
- data/lib/HDLRuby/test_hruby_bstr.rb +2259 -0
- data/lib/HDLRuby/test_hruby_high.rb +594 -0
- data/lib/HDLRuby/test_hruby_high_low.rb +99 -0
- data/lib/HDLRuby/test_hruby_low.rb +934 -0
- data/lib/HDLRuby/v_samples/adder.v +10 -0
- data/lib/HDLRuby/v_samples/dff.v +12 -0
- data/lib/HDLRuby/v_samples/ram.v +20 -0
- data/lib/HDLRuby/v_samples/rom.v +270 -0
- data/lib/HDLRuby/version.rb +3 -0
- data/lib/HDLRuby.rb +11 -0
- data/makedoc +1 -0
- data/metadata.yaml +4 -0
- metadata +299 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Describes a simple D-FF
|
|
2
|
+
system :dff do
|
|
3
|
+
input :clk,:rst
|
|
4
|
+
input :d
|
|
5
|
+
output :q
|
|
6
|
+
|
|
7
|
+
(q <= d & ~rst ).at(clk.posedge)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Describes a 2-bit counter using dff
|
|
12
|
+
system :counter2 do
|
|
13
|
+
input :clk,:rst
|
|
14
|
+
output :q
|
|
15
|
+
|
|
16
|
+
dff [:dff0, :dff1]
|
|
17
|
+
|
|
18
|
+
dff0.(clk,rst,~dff0.q)
|
|
19
|
+
dff1.(dff0.q,rst,~dff1.q,q)
|
|
20
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
system :dff do
|
|
2
|
+
input :clk, :rst, :d
|
|
3
|
+
output :q
|
|
4
|
+
|
|
5
|
+
(q <= d & ~rst).at(clk.posedge)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
system :in_dff do
|
|
9
|
+
input :clk, :rst, :d
|
|
10
|
+
output :q, :qb
|
|
11
|
+
|
|
12
|
+
dff :dff0
|
|
13
|
+
dff0.open do
|
|
14
|
+
output :qb
|
|
15
|
+
qb <= ~q
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
dff0.clk <= clk
|
|
19
|
+
dff0.rst <= rst
|
|
20
|
+
dff0.d <= d
|
|
21
|
+
q <= dff0.q
|
|
22
|
+
qb <= dff0.qb
|
|
23
|
+
end
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
require '../std/fsm.rb'
|
|
2
|
+
require '../std/decoder.rb'
|
|
3
|
+
include HDLRuby::High::Std
|
|
4
|
+
|
|
5
|
+
# A simple implementation of the MEI8 processor.
|
|
6
|
+
#
|
|
7
|
+
# In this implementation, the program is hard-coded in an internal ROM
|
|
8
|
+
system :mei8 do |prog_file = "./prog.obj"|
|
|
9
|
+
# Clock and reset.
|
|
10
|
+
input :clk, :rst
|
|
11
|
+
# Bus.
|
|
12
|
+
output :req, :rwb
|
|
13
|
+
[8].output :addr
|
|
14
|
+
[8].inout :dbus
|
|
15
|
+
input :ack
|
|
16
|
+
# Interrupts.
|
|
17
|
+
input :iq0, :iq1
|
|
18
|
+
# The signals for controlling the io unit.
|
|
19
|
+
inner :io_req, :io_rwb, :io_done # Request, read/not write, done.
|
|
20
|
+
inner :io_r_done # Read done.
|
|
21
|
+
[8].inner :io_out,:io_in # The write and read inner buses.
|
|
22
|
+
[8].inner :data # The read buffer.
|
|
23
|
+
|
|
24
|
+
# The rom containing the program.
|
|
25
|
+
instance :prog do
|
|
26
|
+
[7..0].input :addr # The address bus
|
|
27
|
+
[7..0].output :instr # The instruction bus
|
|
28
|
+
bit[7..0][-256].constant content: # The content of the memory
|
|
29
|
+
File.readlines(prog_file).map {|l| l.split[0].to_i(2)}
|
|
30
|
+
instr <= content[addr] # The access procedure
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# The registers.
|
|
34
|
+
[8].inner :a, :b, :c, :d, :e, :f, :g, :h # General purpose registers
|
|
35
|
+
inner :zf, :cf, :sf, :vf # Flags
|
|
36
|
+
[8].inner :ir # Instruction register
|
|
37
|
+
[8].inner :pc # Program counter
|
|
38
|
+
[8].inner :s # Status register
|
|
39
|
+
|
|
40
|
+
# The ALU
|
|
41
|
+
instance :alu do
|
|
42
|
+
[4].input :opr # The operator bus
|
|
43
|
+
[8].input :x,:y # The input buses
|
|
44
|
+
[8].output :z # The output bus
|
|
45
|
+
output :zf, :cf, :sf, :vf # The flag signals
|
|
46
|
+
|
|
47
|
+
# The only adder instance.
|
|
48
|
+
instance :add do
|
|
49
|
+
[8].input :x,:y # The input buses
|
|
50
|
+
input :cin # The input carry
|
|
51
|
+
[9].output :z # The output bus (including
|
|
52
|
+
# the output carry)
|
|
53
|
+
z <= x.as([9])+y+cin
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# The control part for choosing between 0, add, sub and neg.
|
|
57
|
+
par do
|
|
58
|
+
# Default computations
|
|
59
|
+
cf <= 0; vf <= 0; zf <= (z == 0); sf <= z[7]
|
|
60
|
+
add.(0,0,0)
|
|
61
|
+
# Depending on the operator
|
|
62
|
+
hcase(opr)
|
|
63
|
+
hwhen(0) { add.(x ,y ,0,[cf,z]) # add
|
|
64
|
+
vf <= (~x[7] & ~y[7] & z[7]) | (x[7] & y[7] & ~z[7]) }
|
|
65
|
+
hwhen(1) { add.(x ,~y,1,[cf,z]) # sub
|
|
66
|
+
vf <= (~x[7] & y[7] & z[7]) | (x[7] & ~y[7] & ~z[7]) }
|
|
67
|
+
hwhen(2) { add.(x ,0 ,1,[cf,z]) # inc
|
|
68
|
+
vf <= (~x[7] & ~y[7] & z[7]) | (x[7] & y[7] & ~z[7]) }
|
|
69
|
+
hwhen(3) { add.(x ,0xFF ,0,[cf,z]) # dec
|
|
70
|
+
vf <= (~x[7] & ~y[7] & z[7]) | (x[7] & y[7] & ~z[7]) }
|
|
71
|
+
hwhen(4) { z <= x & y } # and
|
|
72
|
+
hwhen(5) { z <= x | y } # or
|
|
73
|
+
hwhen(6) { z <= x ^ y } # xor
|
|
74
|
+
hwhen(7) { z <= x } # mov
|
|
75
|
+
hwhen(8) { add.(~x,0 ,1,[cf,z]) # neg
|
|
76
|
+
vf <= (x[7] & ~z[7]) }
|
|
77
|
+
hwhen(9) { z <= ~x } # not
|
|
78
|
+
hwhen(10) { z <= x << 1 ; cf <= x[7] } # shl
|
|
79
|
+
hwhen(11) { z <= x >> 1 ; cf <= x[0] } # shr
|
|
80
|
+
hwhen(12) { z <= [x[7], x[7..1] ] ; cf <= x[0] } # sar
|
|
81
|
+
helse { z <= 0 } # zero
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Signals relative to the decoder
|
|
86
|
+
[3].inner :dst # Index of the destination register.
|
|
87
|
+
[8].inner :src0, :src1 # Values of the source registers.
|
|
88
|
+
inner :branch # Tells if the instruction is a branch.
|
|
89
|
+
inner :cc # Tells if a branch condition is met.
|
|
90
|
+
inner :wr, :wf # Tells the computation result is to write to a gpr/flag.
|
|
91
|
+
inner :ld, :st # Tells if the instruction is a load/store.
|
|
92
|
+
inner :iq_calc # Tells if the interrupt unit is preempting calculation.
|
|
93
|
+
|
|
94
|
+
# The decoder.
|
|
95
|
+
par do
|
|
96
|
+
# By default, no branch, no load, no store, write to gpr but not to
|
|
97
|
+
# flags and destination is a and output value is a
|
|
98
|
+
branch <= 0; ld <= 0; st <= 0; wr <= 1; wf <= 0; dst <= 0; io_out <= a
|
|
99
|
+
# And transfer 0.
|
|
100
|
+
alu.(15,0,0)
|
|
101
|
+
# Compute the possible sources
|
|
102
|
+
src0 <= mux(ir[5..3],a,b,c,d,e,f,g,h)
|
|
103
|
+
src1 <= mux(ir[2..0],a,b,c,d,e,f,g,h)
|
|
104
|
+
# Compute the branch condition.
|
|
105
|
+
cc <= mux(ir[5..3],1,zf,cf,sf,vf,~zf,0)
|
|
106
|
+
# Is it an interrupt?
|
|
107
|
+
hif (iq_calc) { alu.(2,h,0) }
|
|
108
|
+
# No, do a normal decoding of the instruction in ir.
|
|
109
|
+
helse do
|
|
110
|
+
decoder(ir) do
|
|
111
|
+
# Format 0
|
|
112
|
+
entry("00000000") { wr <= 0 } # nop
|
|
113
|
+
entry("00xxxyyy") {
|
|
114
|
+
hif (x == y) { alu.(15,0,0) } # mov 0,y
|
|
115
|
+
helse { alu.(7,src0) } # mov x,y
|
|
116
|
+
dst <= y }
|
|
117
|
+
# Format 1
|
|
118
|
+
entry("01oooyyy") { wf <= 1
|
|
119
|
+
# Destination is also y in case of inc/dec
|
|
120
|
+
hif (ir[6..4] == _101) { dst <= y }
|
|
121
|
+
alu.(o,a,src1) } # binary alu
|
|
122
|
+
# Format 1 extended.
|
|
123
|
+
entry("10000yyy") { wr <= 0; wf <= 1
|
|
124
|
+
alu.(1,a,src1) } # cp y
|
|
125
|
+
entry("10001yyy") { ld <= 1; dst <= y } # ld y
|
|
126
|
+
entry("10010yyy") { st <= 1; wr <= 0 # st y
|
|
127
|
+
[a,b,c,d,e,f,g,h].hcase(y) {|r| io_out <= r } }
|
|
128
|
+
entry("10011yyy") { branch <= 1 # jr y, must inc y
|
|
129
|
+
alu.(2,src1) } # since pc-1 is used
|
|
130
|
+
# Format 2
|
|
131
|
+
entry("1010iiii") { alu.(7,[_0000,i]) } # movl i
|
|
132
|
+
entry("1011iiii") { alu.(7,[i,a[3..0]]) } # movh i
|
|
133
|
+
# Format 4
|
|
134
|
+
entry("11110110") { branch <= 1 # trap
|
|
135
|
+
alu.(7,0xFC) }
|
|
136
|
+
entry("11110ooo") { wf <= 1; alu.([_1,o],a) } # unary alu
|
|
137
|
+
entry("111110os") { st <= s; ld <= ~s # ++--ld / ++--st
|
|
138
|
+
alu.([_001,o],g); dst <= 6 }
|
|
139
|
+
entry("1111110i") { branch <= i
|
|
140
|
+
st <= ~i; ld <= i
|
|
141
|
+
alu.([_001,~i],h)
|
|
142
|
+
dst <= 7; io_out <= pc } # push / pop pc
|
|
143
|
+
# Format 3
|
|
144
|
+
entry("11cccsii") { branch <= cc; wr <= 0
|
|
145
|
+
alu.(0,pc,[s]*6+[i]) }# br c i
|
|
146
|
+
# xs / halt / reset: treated without decoding
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# The io unit.
|
|
152
|
+
fsm(clk.posedge,rst,:async) do
|
|
153
|
+
default { io_done <= 0; req <= 0; rwb <= 0; addr <= 0
|
|
154
|
+
io_r_done <= 0
|
|
155
|
+
# Default handling of the 3-state data bus
|
|
156
|
+
hif(io_rwb) { dbus <= _zzzzzzzz }
|
|
157
|
+
helse { dbus <= io_out }
|
|
158
|
+
io_in <= dbus }
|
|
159
|
+
reset(:sync) { data <= 0; }
|
|
160
|
+
state(:wait) { goto(io_req,:start,:wait) } # Waiting for an IO
|
|
161
|
+
state(:start) { req <= 1; rwb <= io_rwb; addr <= g # Start an IO
|
|
162
|
+
goto(ack,:end,:start) } # Wait exteral ack to end IO
|
|
163
|
+
sync(:start) { data <= io_in }
|
|
164
|
+
state(:end) { io_done <= 1; io_r_done <= io_rwb # End IO
|
|
165
|
+
goto(:wait) }
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
inner :calc # Tell if calculation is to be writen back to a register.
|
|
169
|
+
inner :init # Tell CPU is in initialization mode (soft reset).
|
|
170
|
+
|
|
171
|
+
[8].inner :npc # Next pc
|
|
172
|
+
inner :nbr # Tell if must branch next.
|
|
173
|
+
|
|
174
|
+
# Write back unit: handles the writing to registers.
|
|
175
|
+
par(clk.posedge) do
|
|
176
|
+
nbr <= 0; npc <= 0 # By default no branch to schedule.
|
|
177
|
+
hif(rst) do
|
|
178
|
+
# In case of hard reset all the registers of the operative part
|
|
179
|
+
# are to put to 0.
|
|
180
|
+
[a,b,c,d,e,f,g,h,zf,cf,sf,vf,nbr,npc,s].each { |r| r <= 0 }
|
|
181
|
+
end
|
|
182
|
+
# Ensures a is 0 and enable interrupts when starting.
|
|
183
|
+
helsif(init) { a<= 0; s <= _00000011; }
|
|
184
|
+
helsif(iq_calc) do
|
|
185
|
+
s[7] <= 1
|
|
186
|
+
hif(iq1) { s[1] <= 0 }
|
|
187
|
+
helse { s[0] <= 0 }
|
|
188
|
+
h <= alu.z
|
|
189
|
+
end
|
|
190
|
+
helsif(calc) do
|
|
191
|
+
hif wr do # Write to the destination gpr.
|
|
192
|
+
[a,b,c,d,e,f,g,h].hcase(dst) { |r| r <= alu.z }
|
|
193
|
+
end
|
|
194
|
+
hif wf do # Write the the flags.
|
|
195
|
+
zf <= alu.zf; cf <= alu.cf; sf <= alu.sf; vf <= alu.vf
|
|
196
|
+
end
|
|
197
|
+
# Specific cases
|
|
198
|
+
hif(ir == _11110111) { s <= a; a <= s } # xs
|
|
199
|
+
hif(ir == _11110110) { s[7] <= 1 } # trap
|
|
200
|
+
hif(branch) { npc <= alu.z; nbr <= 1 } # Branch
|
|
201
|
+
end
|
|
202
|
+
# Write memory read result to a register if any.
|
|
203
|
+
helsif (io_r_done) do
|
|
204
|
+
hif(branch) { npc <= data; nbr <= 1 } # pop case
|
|
205
|
+
helsif(ir[7..3] == _10001) do # ld case
|
|
206
|
+
[a,b,c,d,e,f,g,h].hcase(dst) {|r| r <= data }
|
|
207
|
+
end
|
|
208
|
+
helse { a <= data } # ld++-- case
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
prog.addr <= pc # Buses permanent connections.
|
|
213
|
+
|
|
214
|
+
inner :iq_chk # Interrupt check buffer.
|
|
215
|
+
|
|
216
|
+
# The main FSM
|
|
217
|
+
fsm(clk.posedge,rst,:async) do
|
|
218
|
+
default { init <= 0; calc <= 0; io_req <= 0; io_rwb <= 1
|
|
219
|
+
iq_calc <= 0 }
|
|
220
|
+
reset(:sync) { pc <= 0; ir <= 0; iq_chk <= 0 } # Hard reset
|
|
221
|
+
# Soft reset state.
|
|
222
|
+
state(:re) { init <= 1 }
|
|
223
|
+
sync(:re) { pc <= 0; ir <= 0; iq_chk <= 0 }
|
|
224
|
+
# Standard execution states.
|
|
225
|
+
state(:fe) { }
|
|
226
|
+
sync(:fe) { ir <= prog.instr; pc <= pc + 1 # Standard fetch
|
|
227
|
+
iq_chk <= (iq0 & s[0]) | (iq1 & s[1]) } # Check interrupt
|
|
228
|
+
state(:ex) { calc <= 1 # Activate the write back unit
|
|
229
|
+
hif(ld|st) { io_req <= 1; io_rwb <= ld } # Prepare IO unit if ld or st
|
|
230
|
+
goto(:fe) # By default execution is over
|
|
231
|
+
goto(iq_chk,:iq_s) # Interrupt / No interrupt
|
|
232
|
+
goto(branch,:br) # Branch instruction
|
|
233
|
+
goto((ld|st) & ~io_done,:ld_st) # ld/st instruction
|
|
234
|
+
goto(ir == _11111110,:ht) # Halt instruction
|
|
235
|
+
goto(ir == _11111111,:re) } # Reset instruction
|
|
236
|
+
# Branch state.
|
|
237
|
+
state(:br) { goto(iq_chk,:iq_s,:fe) } # Interrupt / No interrupt
|
|
238
|
+
sync(:br) { hif(nbr) { pc <= npc-1 } } # Next pc is the branch target
|
|
239
|
+
# State waiting the end of a load/store.
|
|
240
|
+
state(:ld_st){ io_rwb <= ld # Tell IO unit if read or write
|
|
241
|
+
goto(branch,:br,:fe) # In case of pop, branch after ld
|
|
242
|
+
goto(~io_done,:ld_st) # ld/et not finished yet
|
|
243
|
+
goto(io_done & iq_chk,:iq_s)}# Interrupt / No interrupt
|
|
244
|
+
# States handling the interrupts.
|
|
245
|
+
# Push PC
|
|
246
|
+
state(:iq_s) { iq_calc <= 1;
|
|
247
|
+
io_req <= 1; io_rwb <= 0; # io_out <= pc
|
|
248
|
+
goto(io_done, :iq_d, :iq_s) }
|
|
249
|
+
# Jump to interrupt handler.
|
|
250
|
+
state(:iq_d) { goto(:fe) }
|
|
251
|
+
sync(:iq_d) { pc <= 0xF8 }
|
|
252
|
+
# State handling the halt (until a reset or an interrupt).
|
|
253
|
+
state(:ht) { goto(iq_chk,:iq_s,:ht) } # Interrupt / No interrupt
|
|
254
|
+
sync(:ht) { iq_chk <= (iq0 & s[0]) | (iq1 & s[1]) }
|
|
255
|
+
end
|
|
256
|
+
end
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
require '../std/fsm.rb'
|
|
2
|
+
require '../std/decoder.rb'
|
|
3
|
+
include HDLRuby::High::Std
|
|
4
|
+
|
|
5
|
+
# A simple implementation of the MEI8 processor.
|
|
6
|
+
#
|
|
7
|
+
# In this implementation, the program is hard-coded in an internal ROM
|
|
8
|
+
system :mei8 do |prog_file = "./prog_encrypt.obj"|
|
|
9
|
+
# Clock and reset.
|
|
10
|
+
input :clk, :rst
|
|
11
|
+
# Bus.
|
|
12
|
+
output :req, :rwb
|
|
13
|
+
[8].output :addr
|
|
14
|
+
[8].inout :dbus
|
|
15
|
+
input :ack
|
|
16
|
+
# Interrupts.
|
|
17
|
+
input :iq0, :iq1
|
|
18
|
+
# The signals for controlling the io unit.
|
|
19
|
+
inner :io_req, :io_rwb, :io_done # Request, read/not write, done.
|
|
20
|
+
inner :io_r_done # Read done.
|
|
21
|
+
[8].inner :io_out,:io_in # The write and read inner buses.
|
|
22
|
+
[8].inner :data # The read buffer.
|
|
23
|
+
|
|
24
|
+
# The rom containing the program.
|
|
25
|
+
instance :prog do
|
|
26
|
+
[7..0].input :addr # The address bus
|
|
27
|
+
[7..0].output :instr # The instruction bus
|
|
28
|
+
bit[7..0][-256].constant content: # The content of the memory
|
|
29
|
+
( File.readlines(prog_file).map {|l| l.split[0] }.select do |l|
|
|
30
|
+
["0","1"].include?(l[2])
|
|
31
|
+
end.map {|l| l[2..9] } )
|
|
32
|
+
instr <= content[addr] # The access procedure
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# The registers.
|
|
36
|
+
[8].inner :a, :b, :c, :d, :e, :f, :g, :h # General purpose registers
|
|
37
|
+
inner :zf, :cf, :sf, :vf # Flags
|
|
38
|
+
[8].inner :ir # Instruction register
|
|
39
|
+
[8].inner :pc # Program counter
|
|
40
|
+
[8].inner :s # Status register
|
|
41
|
+
|
|
42
|
+
# The ALU
|
|
43
|
+
instance :alu do
|
|
44
|
+
[4].input :opr # The operator bus
|
|
45
|
+
[8].input :x,:y # The input buses
|
|
46
|
+
[8].output :z # The output bus
|
|
47
|
+
output :zf, :cf, :sf, :vf # The flag signals
|
|
48
|
+
|
|
49
|
+
# The only adder instance.
|
|
50
|
+
instance :add do
|
|
51
|
+
[8].input :x,:y # The input buses
|
|
52
|
+
input :cin # The input carry
|
|
53
|
+
[9].output :z # The output bus (including
|
|
54
|
+
# the output carry)
|
|
55
|
+
z <= x.as([9])+y+cin
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# The control part for choosing between 0, add, sub and neg.
|
|
59
|
+
par do
|
|
60
|
+
# Default computations
|
|
61
|
+
cf <= 0; vf <= 0; zf <= (z == 0); sf <= z[7]
|
|
62
|
+
add.(0,0,0)
|
|
63
|
+
# Depending on the operator
|
|
64
|
+
hcase(opr)
|
|
65
|
+
hwhen(0) { add.(x ,y ,0,[cf,z]) # add
|
|
66
|
+
vf <= (~x[7] & ~y[7] & z[7]) | (x[7] & y[7] & ~z[7]) }
|
|
67
|
+
hwhen(1) { add.(x ,~y,1,[cf,z]) # sub
|
|
68
|
+
vf <= (~x[7] & y[7] & z[7]) | (x[7] & ~y[7] & ~z[7]) }
|
|
69
|
+
hwhen(2) { add.(x ,0 ,1,[cf,z]) # inc
|
|
70
|
+
vf <= (~x[7] & ~y[7] & z[7]) | (x[7] & y[7] & ~z[7]) }
|
|
71
|
+
hwhen(3) { add.(x ,0xFF ,0,[cf,z]) # dec
|
|
72
|
+
vf <= (~x[7] & ~y[7] & z[7]) | (x[7] & y[7] & ~z[7]) }
|
|
73
|
+
hwhen(4) { z <= x & y } # and
|
|
74
|
+
hwhen(5) { z <= x | y } # or
|
|
75
|
+
hwhen(6) { z <= x ^ y } # xor
|
|
76
|
+
hwhen(7) { z <= x } # mov
|
|
77
|
+
hwhen(8) { add.(~x,0 ,1,[cf,z]) # neg
|
|
78
|
+
vf <= (x[7] & ~z[7]) }
|
|
79
|
+
hwhen(9) { z <= ~x } # not
|
|
80
|
+
hwhen(10) { z <= x << 1 ; cf <= x[7] } # shl
|
|
81
|
+
hwhen(11) { z <= x >> 1 ; cf <= x[0] } # shr
|
|
82
|
+
hwhen(12) { z <= [x[7], x[7..1] ] ; cf <= x[0] } # sar
|
|
83
|
+
helse { z <= 0 } # zero
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Signals relative to the decoder
|
|
88
|
+
[3].inner :dst # Index of the destination register.
|
|
89
|
+
[8].inner :src0, :src1 # Values of the source registers.
|
|
90
|
+
inner :branch # Tells if the instruction is a branch.
|
|
91
|
+
inner :cc # Tells if a branch condition is met.
|
|
92
|
+
inner :wr, :wf # Tells the computation result is to write to a gpr/flag.
|
|
93
|
+
inner :ld, :st # Tells if the instruction is a load/store.
|
|
94
|
+
inner :iq_calc # Tells if the interrupt unit is preempting calculation.
|
|
95
|
+
|
|
96
|
+
# The decoder.
|
|
97
|
+
par do
|
|
98
|
+
# By default, no branch, no load, no store, write to gpr but not to
|
|
99
|
+
# flags and destination is a and output value is a
|
|
100
|
+
branch <= 0; ld <= 0; st <= 0; wr <= 1; wf <= 0; dst <= 0; io_out <= a
|
|
101
|
+
# And transfer 0.
|
|
102
|
+
alu.(15,0,0)
|
|
103
|
+
# Compute the possible sources
|
|
104
|
+
src0 <= mux(ir[5..3],a,b,c,d,e,f,g,h)
|
|
105
|
+
src1 <= mux(ir[2..0],a,b,c,d,e,f,g,h)
|
|
106
|
+
# Compute the branch condition.
|
|
107
|
+
cc <= mux(ir[5..3],1,zf,cf,sf,vf,~zf,0)
|
|
108
|
+
# Is it an interrupt?
|
|
109
|
+
hif (iq_calc) { alu.(2,h,0) }
|
|
110
|
+
# No, do a normal decoding of the instruction in ir.
|
|
111
|
+
helse do
|
|
112
|
+
decoder(ir) do
|
|
113
|
+
# Format 0
|
|
114
|
+
entry("00000000") { wr <= 0 } # nop
|
|
115
|
+
entry("00xxxyyy") {
|
|
116
|
+
hif (x == y) { alu.(15,0,0) } # mov 0,y
|
|
117
|
+
helse { alu.(7,src0) } # mov x,y
|
|
118
|
+
dst <= y }
|
|
119
|
+
# Format 1
|
|
120
|
+
entry("01oooyyy") { wf <= 1
|
|
121
|
+
# Destination is also y in case of inc/dec
|
|
122
|
+
hif (ir[6..4] == _101) { dst <= y }
|
|
123
|
+
alu.(o,a,src1) } # binary alu
|
|
124
|
+
# Format 1 extended.
|
|
125
|
+
entry("10000yyy") { wr <= 0; wf <= 1
|
|
126
|
+
alu.(1,a,src1) } # cp y
|
|
127
|
+
entry("10001yyy") { ld <= 1; dst <= y } # ld y
|
|
128
|
+
entry("10010yyy") { st <= 1; wr <= 0 # st y
|
|
129
|
+
[a,b,c,d,e,f,g,h].hcase(y) {|r| io_out <= r } }
|
|
130
|
+
entry("10011yyy") { branch <= 1 # jr y, must inc y
|
|
131
|
+
alu.(2,src1) } # since pc-1 is used
|
|
132
|
+
# Format 2
|
|
133
|
+
entry("1010iiii") { alu.(7,[_0000,i]) } # movl i
|
|
134
|
+
entry("1011iiii") { alu.(7,[i,a[3..0]]) } # movh i
|
|
135
|
+
# Format 4
|
|
136
|
+
entry("11110110") { branch <= 1 # trap
|
|
137
|
+
alu.(7,0xFC) }
|
|
138
|
+
entry("11110ooo") { wf <= 1; alu.([_1,o],a) } # unary alu
|
|
139
|
+
entry("111110os") { st <= s; ld <= ~s # ++--ld / ++--st
|
|
140
|
+
alu.([_001,o],g); dst <= 6 }
|
|
141
|
+
entry("1111110i") { branch <= i
|
|
142
|
+
st <= ~i; ld <= i
|
|
143
|
+
alu.([_001,~i],h)
|
|
144
|
+
dst <= 7; io_out <= pc } # push / pop pc
|
|
145
|
+
# Format 3
|
|
146
|
+
entry("11cccsii") { branch <= cc; wr <= 0
|
|
147
|
+
alu.(0,pc,[s]*6+[i]) }# br c i
|
|
148
|
+
# xs / halt / reset: treated without decoding
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# The io unit.
|
|
154
|
+
fsm(clk.posedge,rst,:async) do
|
|
155
|
+
default { io_done <= 0; req <= 0; rwb <= 0; addr <= 0
|
|
156
|
+
io_r_done <= 0
|
|
157
|
+
# Default handling of the 3-state data bus
|
|
158
|
+
hif(io_rwb) { dbus <= _zzzzzzzz }
|
|
159
|
+
helse { dbus <= io_out }
|
|
160
|
+
io_in <= dbus }
|
|
161
|
+
reset(:sync) { data <= 0; }
|
|
162
|
+
state(:wait) { goto(io_req,:start,:wait) } # Waiting for an IO
|
|
163
|
+
state(:start) { req <= 1; rwb <= io_rwb; addr <= g # Start an IO
|
|
164
|
+
goto(ack,:end,:start) } # Wait exteral ack to end IO
|
|
165
|
+
sync(:start) { data <= io_in }
|
|
166
|
+
state(:end) { io_done <= 1; io_r_done <= io_rwb # End IO
|
|
167
|
+
goto(:wait) }
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
inner :calc # Tell if calculation is to be writen back to a register.
|
|
171
|
+
inner :init # Tell CPU is in initialization mode (soft reset).
|
|
172
|
+
|
|
173
|
+
[8].inner :npc # Next pc
|
|
174
|
+
inner :nbr # Tell if must branch next.
|
|
175
|
+
|
|
176
|
+
# Write back unit: handles the writing to registers.
|
|
177
|
+
par(clk.posedge) do
|
|
178
|
+
nbr <= 0; npc <= 0 # By default no branch to schedule.
|
|
179
|
+
hif(rst) do
|
|
180
|
+
# In case of hard reset all the registers of the operative part
|
|
181
|
+
# are to put to 0.
|
|
182
|
+
[a,b,c,d,e,f,g,h,zf,cf,sf,vf,nbr,npc,s].each { |r| r <= 0 }
|
|
183
|
+
end
|
|
184
|
+
# Ensures a is 0 and enable interrupts when starting.
|
|
185
|
+
helsif(init) { a<= 0; s <= _00000011; }
|
|
186
|
+
helsif(iq_calc) do
|
|
187
|
+
s[7] <= 1
|
|
188
|
+
hif(iq1) { s[1] <= 0 }
|
|
189
|
+
helse { s[0] <= 0 }
|
|
190
|
+
h <= alu.z
|
|
191
|
+
end
|
|
192
|
+
helsif(calc) do
|
|
193
|
+
hif wr do # Write to the destination gpr.
|
|
194
|
+
[a,b,c,d,e,f,g,h].hcase(dst) { |r| r <= alu.z }
|
|
195
|
+
end
|
|
196
|
+
hif wf do # Write the the flags.
|
|
197
|
+
zf <= alu.zf; cf <= alu.cf; sf <= alu.sf; vf <= alu.vf
|
|
198
|
+
end
|
|
199
|
+
# Specific cases
|
|
200
|
+
hif(ir == _11110111) { s <= a; a <= s } # xs
|
|
201
|
+
hif(ir == _11110110) { s[7] <= 1 } # trap
|
|
202
|
+
hif(branch) { npc <= alu.z; nbr <= 1 } # Branch
|
|
203
|
+
end
|
|
204
|
+
# Write memory read result to a register if any.
|
|
205
|
+
helsif (io_r_done) do
|
|
206
|
+
hif(branch) { npc <= data; nbr <= 1 } # pop case
|
|
207
|
+
helsif(ir[7..3] == _10001) do # ld case
|
|
208
|
+
[a,b,c,d,e,f,g,h].hcase(dst) {|r| r <= data }
|
|
209
|
+
end
|
|
210
|
+
helse { a <= data } # ld++-- case
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
prog.addr <= pc # Buses permanent connections.
|
|
215
|
+
|
|
216
|
+
inner :iq_chk # Interrupt check buffer.
|
|
217
|
+
|
|
218
|
+
# The main FSM
|
|
219
|
+
fsm(clk.posedge,rst,:async) do
|
|
220
|
+
default { init <= 0; calc <= 0; io_req <= 0; io_rwb <= 1
|
|
221
|
+
iq_calc <= 0 }
|
|
222
|
+
reset(:sync) { pc <= 0; ir <= 0; iq_chk <= 0 } # Hard reset
|
|
223
|
+
# Soft reset state.
|
|
224
|
+
state(:re) { init <= 1 }
|
|
225
|
+
sync(:re) { pc <= 0; ir <= 0; iq_chk <= 0 }
|
|
226
|
+
# Standard execution states.
|
|
227
|
+
state(:fe) { }
|
|
228
|
+
sync(:fe) { ir <= prog.instr; pc <= pc + 1 # Standard fetch
|
|
229
|
+
iq_chk <= (iq0 & s[0]) | (iq1 & s[1]) } # Check interrupt
|
|
230
|
+
state(:ex) { calc <= 1 # Activate the write back unit
|
|
231
|
+
hif(ld|st) { io_req <= 1; io_rwb <= ld } # Prepare IO unit if ld or st
|
|
232
|
+
goto(:fe) # By default execution is over
|
|
233
|
+
goto(iq_chk,:iq_s) # Interrupt / No interrupt
|
|
234
|
+
goto(branch,:br) # Branch instruction
|
|
235
|
+
goto((ld|st) & ~io_done,:ld_st) # ld/st instruction
|
|
236
|
+
goto(ir == _11111110,:ht) # Halt instruction
|
|
237
|
+
goto(ir == _11111111,:re) } # Reset instruction
|
|
238
|
+
# Branch state.
|
|
239
|
+
state(:br) { goto(iq_chk,:iq_s,:fe) } # Interrupt / No interrupt
|
|
240
|
+
sync(:br) { hif(nbr) { pc <= npc-1 } } # Next pc is the branch target
|
|
241
|
+
# State waiting the end of a load/store.
|
|
242
|
+
state(:ld_st){ io_rwb <= ld # Tell IO unit if read or write
|
|
243
|
+
goto(branch,:br,:fe) # In case of pop, branch after ld
|
|
244
|
+
goto(~io_done,:ld_st) # ld/et not finished yet
|
|
245
|
+
goto(io_done & iq_chk,:iq_s)}# Interrupt / No interrupt
|
|
246
|
+
# States handling the interrupts.
|
|
247
|
+
# Push PC
|
|
248
|
+
state(:iq_s) { iq_calc <= 1;
|
|
249
|
+
io_req <= 1; io_rwb <= 0; # io_out <= pc
|
|
250
|
+
goto(io_done, :iq_d, :iq_s) }
|
|
251
|
+
# Jump to interrupt handler.
|
|
252
|
+
state(:iq_d) { goto(:fe) }
|
|
253
|
+
sync(:iq_d) { pc <= 0xF8 }
|
|
254
|
+
# State handling the halt (until a reset or an interrupt).
|
|
255
|
+
state(:ht) { goto(iq_chk,:iq_s,:ht) } # Interrupt / No interrupt
|
|
256
|
+
sync(:ht) { iq_chk <= (iq0 & s[0]) | (iq1 & s[1]) }
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
system :mei8_bench do
|
|
263
|
+
# Clock and reset.
|
|
264
|
+
inner :clk, :rst
|
|
265
|
+
# Bus.
|
|
266
|
+
inner :req, :rwb
|
|
267
|
+
[8].inner :addr
|
|
268
|
+
[8].inner :dbus
|
|
269
|
+
inner :ack
|
|
270
|
+
# Interrupts.
|
|
271
|
+
inner :iq0, :iq1
|
|
272
|
+
|
|
273
|
+
mei8(:my_mei8).(clk,rst,req,rwb,addr,dbus,ack,iq0,iq1)
|
|
274
|
+
|
|
275
|
+
timed do
|
|
276
|
+
# Initialize the processor
|
|
277
|
+
clk <= 0
|
|
278
|
+
rst <= 0
|
|
279
|
+
dbus <= 0
|
|
280
|
+
ack <= 0
|
|
281
|
+
iq0 <= 0
|
|
282
|
+
iq1 <= 0
|
|
283
|
+
!10.ns
|
|
284
|
+
clk <= 1
|
|
285
|
+
rst <= 0
|
|
286
|
+
!10.ns
|
|
287
|
+
clk <= 0
|
|
288
|
+
rst <= 1
|
|
289
|
+
!10.ns
|
|
290
|
+
clk <= 1
|
|
291
|
+
rst <= 1
|
|
292
|
+
!10.ns
|
|
293
|
+
clk <= 0
|
|
294
|
+
rst <= 0
|
|
295
|
+
!10.ns
|
|
296
|
+
clk <= 1
|
|
297
|
+
rst <= 0
|
|
298
|
+
!10.ns
|
|
299
|
+
# Now loop a few cycles.
|
|
300
|
+
100.times do |i|
|
|
301
|
+
clk <= 0
|
|
302
|
+
ack <= 1
|
|
303
|
+
dbus <= i
|
|
304
|
+
!10.ns
|
|
305
|
+
clk <= 1
|
|
306
|
+
!10.ns
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require '../std/fsm.rb'
|
|
2
|
+
include HDLRuby::High::Std
|
|
3
|
+
|
|
4
|
+
# A sequential 16x16 -> 32 multer
|
|
5
|
+
system :multer do
|
|
6
|
+
input :clk, :rst
|
|
7
|
+
input :start
|
|
8
|
+
[16].input :x,:y
|
|
9
|
+
[32].output :s
|
|
10
|
+
output :done
|
|
11
|
+
|
|
12
|
+
[32].inner :wx
|
|
13
|
+
[16].inner :wy
|
|
14
|
+
|
|
15
|
+
fsm(clk.posedge,rst) do
|
|
16
|
+
state(:init) { s <= 0 ; wx <= x ; wy <= y ; done <= 0
|
|
17
|
+
goto(start,:test,:init) }
|
|
18
|
+
|
|
19
|
+
state(:test) { goto(wy[0],:add,:next) }
|
|
20
|
+
|
|
21
|
+
state(:add) { s <= s + wx }
|
|
22
|
+
|
|
23
|
+
state(:next) { wx <= wx << 1 ; wy <= wy >> 1
|
|
24
|
+
goto(wy == 0,:end,:test) }
|
|
25
|
+
|
|
26
|
+
state(:end) { done <= 1
|
|
27
|
+
goto(:end) }
|
|
28
|
+
end
|
|
29
|
+
end
|