在migen中,如果一个模块将一个值赋给有限状态机中的一个信号,这个有限状态机被实现为migen.genlib.fsm.FSM
,那么生成的Verilog将向always块附加一个额外的赋值,以重置生成的寄存器。你知道吗
手动实现状态机而不是作为migen.genlib.fsm.FSM
生成Verilog,其中重置赋值被放在if (sys_reset)
块中。你知道吗
我的问题是,为什么这个赋值不在reset块中,并且在仍然使用FSM类的情况下可以阻止它。这是一个bug,还是暗示我的HDL设计不好?你知道吗
示例:
考虑一个具有两个按钮输入和一个LED输出的模块。一个按钮可以打开LED,一个按钮可以关闭LED。如果我要用FSM实现这一点,我可能会尝试:
from migen import *
from migen.fhdl import *
class FSMExample(Module):
def __init__(self):
# declare signals
self.led = Signal()
self.btn1 = Signal()
self.btn2 = Signal()
# define I/O
self.ios = {self.led, self.btn1, self.btn2}
self.fsm = FSM(reset_state="OFF")
self.fsm.act("OFF",
If(self.btn1, self.led.eq(1), NextState("ON"))
)
self.fsm.act("ON",
If(self.btn2, self.led.eq(0), NextState("OFF"))
)
self.submodules += self.fsm
然而,这会生成(使用verilog.convert(FSMExample(),FSMExample().ios
)以下verilog:
module top(
input led,
input btn1,
input btn2,
input sys_clk,
input sys_rst
);
reg fsmexample0_led;
reg fsmexample0_btn1 = 1'd0;
reg fsmexample0_btn2 = 1'd0;
reg state = 1'd0;
reg next_state;
// synthesis translate_off
reg dummy_s;
initial dummy_s <= 1'd0;
// synthesis translate_on
// synthesis translate_off
reg dummy_d;
// synthesis translate_on
always @(*) begin
fsmexample0_led <= 1'd0;
next_state <= 1'd0;
next_state <= state;
case (state)
1'd1: begin
if (fsmexample0_btn2) begin
fsmexample0_led <= 1'd0;
next_state <= 1'd0;
end
end
default: begin
if (fsmexample0_btn1) begin
fsmexample0_led <= 1'd1;
next_state <= 1'd1;
end
end
endcase
// synthesis translate_off
dummy_d <= dummy_s;
// synthesis translate_on
end
always @(posedge sys_clk) begin
state <= next_state;
if (sys_rst) begin
state <= 1'd0;
end
end
endmodule
注意always块中的fsmexample0_led <= 1'd0;
,即使在按下btn2之后也会重置LED。你知道吗
即使手动实现FSM也可以修复这种行为:
class FakeFSMExample(Module):
def __init__(self):
# declare signals
self.led = Signal()
self.btn1 = Signal()
self.btn2 = Signal()
self.state = Signal()
self.next_state = Signal()
# define I/O
self.ios = {self.led, self.btn1, self.btn2}
self.sync += self.state.eq(self.next_state)
self.sync += If(~self.state,
If(self.btn1, self.led.eq(1), self.next_state.eq(1))
).Elif(self.state,
If(self.btn2, self.led.eq(0), self.next_state.eq(0))
)
生成
module top(
input led,
input btn1,
input btn2,
input sys_clk,
input sys_rst
);
reg fakefsmexample0_led = 1'd0;
reg fakefsmexample0_btn1 = 1'd0;
reg fakefsmexample0_btn2 = 1'd0;
reg fakefsmexample0_state = 1'd0;
reg fakefsmexample0_next_state = 1'd0;
always @(posedge sys_clk) begin
fakefsmexample0_state <= fakefsmexample0_next_state;
if ((~fakefsmexample0_state)) begin
if (fakefsmexample0_btn1) begin
fakefsmexample0_led <= 1'd1;
fakefsmexample0_next_state <= 1'd1;
end
end else begin
if (fakefsmexample0_state) begin
if (fakefsmexample0_btn2) begin
fakefsmexample0_led <= 1'd0;
fakefsmexample0_next_state <= 1'd0;
end
end
end
if (sys_rst) begin
fakefsmexample0_led <= 1'd0;
fakefsmexample0_state <= 1'd0;
fakefsmexample0_next_state <= 1'd0;
end
end
endmodule
其中fakefsmexample0_led <= 1'd0
根据需要住在if (sys_rst)
内。你知道吗
(编辑:稍微修改示例,在If
语句中分配LED,使输出的Verilog实际产生不需要的行为)
目前没有回答
相关问题 更多 >
编程相关推荐