Skip to content

Commit c19f14b

Browse files
committed
In FSM and Seq, Else is realized as a property, and actual Else operation is synthesized when add() is called. So FSM.goto() and related methods can use Else condition, as well as value assignment.
1 parent 2a0a612 commit c19f14b

File tree

3 files changed

+256
-0
lines changed

3 files changed

+256
-0
lines changed

tests/extension/fsm_/state/Makefile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
TARGET=$(shell ls *.py | grep -v test | grep -v parsetab.py)
2+
ARGS=
3+
4+
PYTHON=python3
5+
#PYTHON=python
6+
#OPT=-m pdb
7+
#OPT=-m cProfile -s time
8+
#OPT=-m cProfile -o profile.rslt
9+
10+
.PHONY: all
11+
all: test
12+
13+
.PHONY: run
14+
run:
15+
$(PYTHON) $(OPT) $(TARGET) $(ARGS)
16+
17+
.PHONY: test
18+
test:
19+
$(PYTHON) -m pytest -vv
20+
21+
.PHONY: check
22+
check:
23+
$(PYTHON) $(OPT) $(TARGET) $(ARGS) > tmp.v
24+
iverilog -tnull -Wall tmp.v
25+
rm -f tmp.v
26+
27+
.PHONY: clean
28+
clean:
29+
rm -rf *.pyc __pycache__ parsetab.py .cache *.out *.png *.dot tmp.v uut.vcd
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
from __future__ import absolute_import
2+
from __future__ import print_function
3+
import sys
4+
import os
5+
6+
# the next line can be removed after installation
7+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(
8+
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
9+
10+
from veriloggen import *
11+
12+
13+
def mkLed():
14+
m = Module('blinkled')
15+
clk = m.Input('CLK')
16+
rst = m.Input('RST')
17+
valid = m.OutputReg('valid', initval=0)
18+
counter = m.Reg('counter', 8, initval=0)
19+
20+
fsm = FSM(m, 'fsm', clk, rst)
21+
22+
s0 = fsm.init # -> State(fsm, 0)
23+
s1 = s0.If(valid).goto_next() # -> State(fsm, 1)
24+
s2 = s1.If(valid).goto_next() # -> State(fsm, 2)
25+
s3 = s2.If(counter[0] == 0).goto(s2.next) # -> State(fsm, 3)
26+
s1_ = s2.Elif(counter[1] == 1).goto(s1) # -> State(fsm, 1)
27+
s2_ = s2.Else.goto(s2) # -> State(fsm, 2)
28+
s0_ = s3.goto(s0) # -> State(fsm, 0)
29+
30+
fsm.Always.If(counter <= 2 ** 8 - 1)(
31+
counter.inc()
32+
).Else(
33+
counter(0)
34+
)
35+
36+
s0.If(counter == 10)(
37+
valid(0)
38+
)
39+
s0.Else(
40+
valid(1)
41+
)
42+
43+
s1.If(counter == 20)(
44+
valid(0)
45+
)
46+
s1.Else(
47+
valid(1)
48+
)
49+
50+
s2.If(counter == 30)(
51+
valid(0)
52+
)
53+
s2.Else(
54+
valid(1)
55+
)
56+
57+
s0_.If(counter == 40)(
58+
valid(0)
59+
)
60+
s0_.Else(
61+
valid(1)
62+
)
63+
64+
return m
65+
66+
67+
def mkTest():
68+
m = Module('test')
69+
clk = m.Reg('CLK')
70+
rst = m.Reg('RST')
71+
valid = m.Wire('valid')
72+
73+
uut = m.Instance(mkLed(), 'uut',
74+
ports=(('CLK', clk), ('RST', rst), ('valid', valid)))
75+
76+
# simulation.setup_waveform(m, uut)
77+
simulation.setup_clock(m, clk, hperiod=5)
78+
init = simulation.setup_reset(m, rst, period=100)
79+
80+
init.add(
81+
Delay(1000),
82+
Systask('finish'),
83+
)
84+
85+
return m
86+
87+
88+
if __name__ == '__main__':
89+
test = mkTest()
90+
verilog = test.to_verilog('tmp.v')
91+
print(verilog)
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
from __future__ import absolute_import
2+
from __future__ import print_function
3+
import veriloggen
4+
import fsm_state
5+
6+
expected_verilog = """
7+
module test;
8+
9+
reg CLK;
10+
reg RST;
11+
wire valid;
12+
13+
blinkled
14+
uut
15+
(
16+
.CLK(CLK),
17+
.RST(RST),
18+
.valid(valid)
19+
);
20+
21+
22+
initial begin
23+
CLK = 0;
24+
forever begin
25+
#5 CLK = !CLK;
26+
end
27+
end
28+
29+
30+
initial begin
31+
RST = 0;
32+
#100;
33+
RST = 1;
34+
#100;
35+
RST = 0;
36+
#1000;
37+
$finish;
38+
end
39+
40+
41+
endmodule
42+
43+
44+
45+
module blinkled
46+
(
47+
input CLK,
48+
input RST,
49+
output reg valid
50+
);
51+
52+
reg [8-1:0] counter;
53+
reg [32-1:0] fsm;
54+
localparam fsm_init = 0;
55+
localparam fsm_1 = 1;
56+
localparam fsm_2 = 2;
57+
localparam fsm_3 = 3;
58+
59+
always @(posedge CLK) begin
60+
if(RST) begin
61+
fsm <= fsm_init;
62+
valid <= 0;
63+
counter <= 0;
64+
end else begin
65+
if(counter <= 255) begin
66+
counter <= counter + 1;
67+
end else begin
68+
counter <= 0;
69+
end
70+
case(fsm)
71+
fsm_init: begin
72+
if(counter == 10) begin
73+
valid <= 0;
74+
end else begin
75+
valid <= 1;
76+
end
77+
if(counter == 40) begin
78+
valid <= 0;
79+
end else begin
80+
valid <= 1;
81+
end
82+
if(valid) begin
83+
fsm <= fsm_1;
84+
end
85+
end
86+
fsm_1: begin
87+
if(counter == 20) begin
88+
valid <= 0;
89+
end else begin
90+
valid <= 1;
91+
end
92+
if(valid) begin
93+
fsm <= fsm_2;
94+
end
95+
end
96+
fsm_2: begin
97+
if(counter == 30) begin
98+
valid <= 0;
99+
end else begin
100+
valid <= 1;
101+
end
102+
if(counter[0] == 0) begin
103+
fsm <= fsm_3;
104+
end
105+
if(!(counter[0] == 0) && (counter[1] == 1)) begin
106+
fsm <= fsm_1;
107+
end
108+
if(!(counter[0] == 0) && !(counter[1] == 1)) begin
109+
fsm <= fsm_2;
110+
end
111+
end
112+
fsm_3: begin
113+
fsm <= fsm_init;
114+
end
115+
endcase
116+
end
117+
end
118+
119+
120+
endmodule
121+
"""
122+
123+
124+
def test():
125+
veriloggen.reset()
126+
test_module = fsm_state.mkTest()
127+
code = test_module.to_verilog()
128+
129+
from pyverilog.vparser.parser import VerilogParser
130+
from pyverilog.ast_code_generator.codegen import ASTCodeGenerator
131+
parser = VerilogParser()
132+
expected_ast = parser.parse(expected_verilog)
133+
codegen = ASTCodeGenerator()
134+
expected_code = codegen.visit(expected_ast)
135+
136+
assert(expected_code == code)

0 commit comments

Comments
 (0)