In Verilog and VHDL, finite state machines are typically described using case statements. Python doesn't have a case statement, but the converter recognizes particular if-then-else structures and maps them to case statements. This optimization occurs when a variable whose type is an enumerated type is sequentially tested against enumeration items in an if-then-else structure. Also, the appropriate synthesis pragmas for efficient synthesis are generated in the Verilog code.
As a further optimization, function enum was enhanced to support alternative encoding schemes elegantly, using an additional parameter encoding. For example:
t_State = enum('SEARCH', 'CONFIRM', 'SYNC', encoding='one_hot')
The default encoding is 'binary'; the other possibilities are
'one_hot' and 'one_cold'. This parameter only affects
the conversion output, not the behavior of the type. The generated
Verilog code for case statements is optimized for an efficient
implementation according to the encoding. Note that in contrast, a
Verilog designer has to make nontrivial code changes to implement a
different encoding scheme.
As an example, consider the following finite state machine, whose state variable uses the enumeration type defined above:
ACTIVE_LOW = 0
FRAME_SIZE = 8
def FramerCtrl(SOF, state, syncFlag, clk, reset_n, t_State):
""" Framing control FSM.
SOF -- start-of-frame output bit
state -- FramerState output
syncFlag -- sync pattern found indication input
clk -- clock input
reset_n -- active low reset
"""
index = Signal(intbv(0)[8:]) # position in frame
@always(clk.posedge, reset_n.negedge)
def FSM():
if reset_n == ACTIVE_LOW:
SOF.next = 0
index.next = 0
state.next = t_State.SEARCH
else:
index.next = (index + 1) % FRAME_SIZE
SOF.next = 0
if state == t_State.SEARCH:
index.next = 1
if syncFlag:
state.next = t_State.CONFIRM
elif state == t_State.CONFIRM:
if index == 0:
if syncFlag:
state.next = t_State.SYNC
else:
state.next = t_State.SEARCH
elif state == t_State.SYNC:
if index == 0:
if not syncFlag:
state.next = t_State.SEARCH
SOF.next = (index == FRAME_SIZE-1)
else:
raise ValueError("Undefined state")
return FSM
The conversion is done as before:
SOF = Signal(bool(0)) syncFlag = Signal(bool(0)) clk = Signal(bool(0)) reset_n = Signal(bool(1)) state = Signal(t_State.SEARCH) framerctrl_inst = toVerilog(FramerCtrl, SOF, state, syncFlag, clk, reset_n)
The Verilog output looks as follows:
module FramerCtrl (
SOF,
state,
syncFlag,
clk,
reset_n
);
output SOF;
reg SOF;
output [2:0] state;
reg [2:0] state;
input syncFlag;
input clk;
input reset_n;
reg [7:0] index;
always @(posedge clk or negedge reset_n) begin: _FramerCtrl_FSM
if ((reset_n == 0)) begin
SOF <= 0;
index <= 0;
state <= 3'b001;
end
else begin
index <= ((index + 1) % 8);
SOF <= 0;
// synthesis parallel_case full_case
casez (state)
3'b??1: begin
index <= 1;
if (syncFlag) begin
state <= 3'b010;
end
end
3'b?1?: begin
if ((index == 0)) begin
if (syncFlag) begin
state <= 3'b100;
end
else begin
state <= 3'b001;
end
end
end
3'b1??: begin
if ((index == 0)) begin
if ((!syncFlag)) begin
state <= 3'b001;
end
end
SOF <= (index == (8 - 1));
end
default: begin
$display("ValueError(Undefined state)");
$finish;
end
endcase
end
end
endmodule
About this document