[英]My Verilog behavioral code getting simulated properly but not working as expected on FPGA
I wrote a behavioral program for booth multiplier(radix 2) using state machine concept.我使用状态机概念为展位乘数(基数 2)编写了一个行为程序。 I am getting the the results properly during the program simulation using modelsim, but when I port it to fpga (spartan 3) the results are not as expected.
我在使用modelsim的程序模拟过程中得到了正确的结果,但是当我将它移植到fpga(spartan 3)时,结果并不如预期。
Where have I gone wrong?我哪里错了?
module booth_using_statemachine(Mul_A,Mul_B,Mul_Result,clk,reset);
input Mul_A,Mul_B,clk,reset;
output Mul_Result;
wire [7:0] Mul_A,Mul_B;
reg [7:0] Mul_Result;
reg [15:0] R_B;
reg [7:0] R_A;
reg prev;
reg [1:0] state;
reg [3:0] count;
parameter start=1 ,add=2 ,shift=3;
always @(state)
begin
case(state)
start:
begin
R_A <= Mul_A;
R_B <= {8'b00000000,Mul_B};
prev <= 1'b0;
count <= 3'b000;
Mul_Result <= R_B[7:0];
end
add:
begin
case({R_B[0],prev})
2'b00:
begin
prev <= 1'b0;
end
2'b01:
begin
R_B[15:8] <= R_B[15:8] + R_A;
prev <= 1'b0;
end
2'b10:
begin
R_B[15:8] <= R_B[15:8] - R_A;
prev <= 1'b1;
end
2'b11:
begin
prev <=1'b1;
end
endcase
end
shift:
begin
R_B <= {R_B[15],R_B[15:1]};
count <= count + 1;
end
endcase
end
always @(posedge clk or posedge reset)
begin
if(reset==1)
state <= start;
else
begin
case(state)
start:
state <= add;
add:
state <= shift;
shift:
begin
if(count>7)
state <= start;
else
state <=add;
end
endcase
end
end
endmodule
You have an incomplete sensitivity list in your combinational always
block.您的组合
always
阻止中的敏感度列表不完整。 Change:改变:
always @(state)
to:到:
always @*
This may be synthesizing latches.这可能是合成锁存器。
Use blocking assignments in your combinational always
block.在你的组合
always
阻塞中使用阻塞赋值。 Change <=
to =
.将
<=
更改为=
。
Good synthesis and linting tools should warn you about these constructs.好的综合和 linting 工具应该会警告您这些构造。
Follow the following checklist if something does work in the simulation but not in reality:如果某些内容在模拟中有效但在现实中无效,请遵循以下清单:
A Example for the second point is here , you need the next stage logic, the current state logic and the output logic.第二点的一个例子在这里,你需要下一级逻辑,当前状态逻辑和输出逻辑。
For more informations about how to proper code a FSM for an FPGA see here (go to HDL Coding Techniques -> Basic HDL Coding Techniques)有关如何为 FPGA 正确编码 FSM 的更多信息,请参见此处(转到 HDL 编码技术 -> 基本 HDL 编码技术)
You've got various problems here.你在这里有各种各样的问题。
Your sensitivity list for the first always block is incomplete.您的第一个 always 块的敏感度列表不完整。 You're only looking at
state
, but there's numerous other signals which need to be in there.您只查看
state
,但还有许多其他信号需要在那里。 If your tools support it, use always @*
, which automatically generates the sensitivity list.如果您的工具支持它,请
always @*
使用always @*
,它会自动生成敏感度列表。 Change this and your code will start to simulate like it's running on the FPGA.更改此设置,您的代码将开始模拟,就像在 FPGA 上运行一样。
This is hiding the other problems with the code because it's causing signals to update at the wrong time.这隐藏了代码的其他问题,因为它会导致信号在错误的时间更新。 You've managed to get your code to work in the simulator, but it's based on a lie.
您已经设法让您的代码在模拟器中运行,但这是基于谎言。 The lie is that
R_A
, R_B
, prev
, count
& Mul_Result
are only dependent on changes in state, but there's more signals which are inputs to that logic.谎言是
R_A
、 R_B
、 prev
、 count
和Mul_Result
只依赖于状态的变化,但有更多的信号是该逻辑的输入。
You've fallen into the trap that the Verilog keyword reg
creates registers.您已经陷入了 Verilog 关键字
reg
创建寄存器的陷阱。 It doesn't.它没有。 I know it's silly, but that's the way it is.
我知道这很愚蠢,但事情就是这样。 What
reg
means is that it's a variable that can be assigned to from a procedural block. reg
意思是它是一个可以从程序块分配的变量。 wire
s can't be assigned to inside a procedural block.不能将
wire
s 分配给程序块内部。
A register is created when you assign something within a clocked procedural block (see footnote), like your state
variable.当您在时钟程序块(参见脚注)中分配某些内容时,会创建一个寄存器,例如您的
state
变量。 R_A
, R_B
, prev
and count
all appear to be holding values across cycles, so need to be registers. R_A
、 R_B
、 prev
和count
似乎都跨周期保存值,因此需要是寄存器。 I'd change the code like this:我会像这样更改代码:
First I'd create a set of next_*
variables.首先,我会创建一组
next_*
变量。 These will contain the value we want in each register next clock.这些将包含我们在每个寄存器下一个时钟中想要的值。
reg [15:0] next_R_B;
reg [7:0] next_R_A;
reg next_prev;
reg [3:0] next_count;
Then I'd change the clocked process to use these:然后我会更改时钟过程以使用这些:
always @(posedge clk or posedge reset) begin
if(reset==1) begin
state <= start;
R_A <= '0;
R_B <= '0;
prev <= '0;
count <= '0;
end else begin
R_A <= next_R_A;
R_B <= next_R_B;
prev <= next_prev;
count <= next_count;
case (state)
.....
Then finally change the first process to assign to the next_*
variables:然后最后将第一个进程更改为分配给
next_*
变量:
always @* begin
next_R_A <= R_A;
next_R_B <= R_B;
next_prev <= prev;
next_count <= count;
case(state)
start: begin
next_R_A <= Mul_A;
next_R_B <= {8'b00000000,Mul_B};
next_prev <= 1'b0;
next_count <= 3'b000;
Mul_Result <= R_B[7:0];
end
add: begin
case({R_B[0],prev})
2'b00: begin
next_prev <= 1'b0;
end
.....
Note:笔记:
next_
value for any register defaults to it's previous value.next_
值默认为其前一个值。next_
values are never read, except for the clocked process next_
值永远不会被读取,除了时钟进程next_
values are never written, except in the clocked process.next_
值永远不会被写入,除非在时钟过程中。 I also suspect you want Mul_Result
to be a wire
and have it assign Mul_Result = R_B[7:0];
我还怀疑您希望
Mul_Result
成为一条wire
并让它assign Mul_Result = R_B[7:0];
rather than it being another register that's only updated in the start state, but I'm not sure what you're going for there.而不是仅在开始状态更新的另一个寄存器,但我不确定您要在那里做什么。
reg
, but a reg
doesn't have to be a register.reg
,但reg
不一定是寄存器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.