这是真正的FSM吗?
我有一个关于FSM的概念问题,以及以下代码是否为真正的FSM。这是为了我自己的好奇心和对这个主题的理解。当我编写此代码时,我的印象是这是FSM,但现在我不确定。根据我完成的大量阅读,真正的FSM应仅由顺序状态过渡块组成,然后是一个或两个组合块来计算下一个状态和输出逻辑。
我当前的代码合成并在我的Basys3板上工作,所以我知道可能有一个论点“如果它不破产,请不要修复它”,但是现在我已经有一段时间了,因为我可能有不正确的理解关于如何在HDL中编写FSM。
我尝试使用上述格式至少尝试4或5种不同的方法来重写我的代码,但是我似乎在不推断闩锁的情况下无法获得它,这主要是由于使用计数器的使用,而PCKD_BCD需要记住这一事实。它的先前值。
有人可以向我解释为什么这种算法不适合真正的FSM,为什么它适合真正的FSM以及我的误解在哪里,或者如何将其重写为上述格式。
module double_dabble #
(
parameter NUM_BITS = 8
)
(
input wire i_clk,
input wire i_rst,
input wire [NUM_BITS-1:0] i_binary,
output wire [15:0] o_pckd_bcd
);
localparam s_IDLE = 3'b000;
localparam s_SHIFT = 3'b001;
localparam s_CHECK = 3'b010;
localparam s_ADD = 3'b011;
localparam s_DONE = 3'b100;
reg [2:0] state;
reg [NUM_BITS-1:0] bin;
reg [3:0] count;
reg [15:0] pckd_bcd;
reg [NUM_BITS-1:0] input_reg;
reg [15:0] output_reg;
assign o_pckd_bcd = output_reg;
always @(posedge i_clk)
begin
if(i_rst)
begin
state <= s_IDLE;
bin <= 0;
count <= 0;
pckd_bcd <= 0;
output_reg <= 0;
input_reg <= 0;
end
else
begin
input_reg <= i_binary;
state <= s_IDLE;
// FSM
case(state)
s_IDLE :
begin
state <= s_IDLE;
bin <= 0;
count <= 0;
pckd_bcd <= 0;
if (input_reg!=i_binary)
begin
bin <= i_binary;
state <= s_SHIFT;
end
end
s_SHIFT :
begin
state <= s_CHECK;
bin <= bin<<1;
count <= count+1;
pckd_bcd <= pckd_bcd<<1;
pckd_bcd[0] <= bin[NUM_BITS-1];
end
s_CHECK :
begin
state <= s_ADD;
if(count>=NUM_BITS)
state <= s_DONE;
end
s_ADD :
begin
state <= s_SHIFT;
pckd_bcd[15:12] <= add_three(pckd_bcd[15:12]);
pckd_bcd[11:8] <= add_three(pckd_bcd[11:8]);
pckd_bcd[7:4] <= add_three(pckd_bcd[7:4]);
pckd_bcd[3:0] <= add_three(pckd_bcd[3:0]);
end
s_DONE :
begin
state <= s_IDLE;
output_reg <= pckd_bcd;
end
endcase
end
end
function [3:0] add_three;
input [3:0] bcd;
if (bcd > 4)
add_three = bcd +3;
else
add_three = bcd;
endfunction
endmodule
I have a conceptual question about FSM's and whether or not the following code is a true FSM. This is for my own curiosity and understanding about the subject. When I wrote this code, I was under the impression that this was an FSM, but now I am not so sure. According to a lot of reading I have done, a TRUE FSM should only consist of a sequential state transition block, followed by either one or two combination blocks to calculate the next state and the output logic.
My current code synthesizes and works on my Basys3 board, so I understand there may be an argument for "if it ain't broke, don't fix it" but it's been bugging me for a while now that I may have an incorrect understanding about how to write an FSM in HDL.
I have tried at least 4 or 5 different ways to rewrite my code using the format mentioned above, but I can't seem to get it without inferring latches, mainly due to the use of a counter, and the fact that pckd_bcd needs to remember its previous value.
Could somebody please explain to me either why this algorithm isn't fit for a true FSM, why it is fit for a true FSM and where my misunderstanding is, or how to rewrite this into the format mentioned above.
module double_dabble #
(
parameter NUM_BITS = 8
)
(
input wire i_clk,
input wire i_rst,
input wire [NUM_BITS-1:0] i_binary,
output wire [15:0] o_pckd_bcd
);
localparam s_IDLE = 3'b000;
localparam s_SHIFT = 3'b001;
localparam s_CHECK = 3'b010;
localparam s_ADD = 3'b011;
localparam s_DONE = 3'b100;
reg [2:0] state;
reg [NUM_BITS-1:0] bin;
reg [3:0] count;
reg [15:0] pckd_bcd;
reg [NUM_BITS-1:0] input_reg;
reg [15:0] output_reg;
assign o_pckd_bcd = output_reg;
always @(posedge i_clk)
begin
if(i_rst)
begin
state <= s_IDLE;
bin <= 0;
count <= 0;
pckd_bcd <= 0;
output_reg <= 0;
input_reg <= 0;
end
else
begin
input_reg <= i_binary;
state <= s_IDLE;
// FSM
case(state)
s_IDLE :
begin
state <= s_IDLE;
bin <= 0;
count <= 0;
pckd_bcd <= 0;
if (input_reg!=i_binary)
begin
bin <= i_binary;
state <= s_SHIFT;
end
end
s_SHIFT :
begin
state <= s_CHECK;
bin <= bin<<1;
count <= count+1;
pckd_bcd <= pckd_bcd<<1;
pckd_bcd[0] <= bin[NUM_BITS-1];
end
s_CHECK :
begin
state <= s_ADD;
if(count>=NUM_BITS)
state <= s_DONE;
end
s_ADD :
begin
state <= s_SHIFT;
pckd_bcd[15:12] <= add_three(pckd_bcd[15:12]);
pckd_bcd[11:8] <= add_three(pckd_bcd[11:8]);
pckd_bcd[7:4] <= add_three(pckd_bcd[7:4]);
pckd_bcd[3:0] <= add_three(pckd_bcd[3:0]);
end
s_DONE :
begin
state <= s_IDLE;
output_reg <= pckd_bcd;
end
endcase
end
end
function [3:0] add_three;
input [3:0] bcd;
if (bcd > 4)
add_three = bcd +3;
else
add_three = bcd;
endfunction
endmodule
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
通常,您的代码看起来像实现FSM。您有证据表明该设计正在按照董事会的需求工作。
您选择的编码样式(一个
始终
块)是有效的Verilog方法。另一种常见的FSM编码样式涉及两个始终
块:一个顺序和一个组合。 here there FSM不得使用两个始终块中的块。我在代码中确实注意到的一件事是,您正在同时对
state
信号进行多个非阻止分配。那是不寻常的。例如,就在
case
语句之前,您有:然后,在
indle
case-item中,您具有相同的代码:我建议尝试通过添加来清理该码
默认
<代码>案例语句。默认
在您的FSM中(如FSM)(如您的FSM)时,也是一个很好的编码练习。您仅定义了8个可能的状态中的5个(state
是3位寄存器)。多个非阻止分配的另一个示例是:
将其编码更好地编码为:
遵循建议的编码实践会产生更可预测的仿真和综合结果。
In general, your code looks like it implements an FSM. You have evidence that the design is working as desired on your board.
The coding style you have chosen (one
always
block) is a valid Verilog approach. Another common FSM coding style involves twoalways
blocks: one sequential and one combinational. See here for an example. It is not mandatory for an FSM to use twoalways
blocks in Verilog.One thing that I do notice in your code is that you are making multiple nonblocking assignments to the
state
signal at the same time. That is unusual.For example, right before the
case
statement, you have:Then, in the
IDLE
case-item, you have the same code:I recommend trying to clean that up by adding a
default
to thecase
statement. Adefault
is also a good coding practice when you have some undefined states, as in your FSM. You have only defined 5 of the 8 possible states (state
is a 3-bit register).Another example of multiple nonblocking assignments is:
That would be better coded as:
Following recommended coding practices yields more predictable simulation and synthesis results.