Reputation: 1
I wrote a behavioral program for booth multiplier (radix 2) using state machine concept. 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.
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
Upvotes: 0
Views: 1880
Reputation: 7755
You've got various problems here.
Your sensitivity list for the first always block is incomplete. You're only looking at state
, but there's numerous other signals which need to be in there. If your tools support it, use always @*
, which automatically generates the sensitivity list. Change this and your code will start to simulate like it's running on the 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.
You've fallen into the trap that the Verilog keyword reg
creates registers. 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. wire
s can't be assigned to inside a procedural block.
A register is created when you assign something within a clocked procedural block (see footnote), like your state
variable. R_A
, R_B
, prev
and count
all appear to be holding values across cycles, so need to be registers. I'd change the code like this:
First I'd create a set of next_*
variables. 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:
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_
values are never read, except for the clocked processnext_
values are never written, except in the clocked process.I also suspect you want Mul_Result
to be a wire
and have it 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.Upvotes: 0
Reputation: 2991
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)
Upvotes: 0
Reputation: 62037
You have an incomplete sensitivity list in your combinational always
block. Change:
always @(state)
to:
always @*
This may be synthesizing latches.
Use blocking assignments in your combinational always
block. Change <=
to =
.
Good synthesis and linting tools should warn you about these constructs.
Upvotes: 3