Reputation: 45
I'm trying to make a 4-bit by 4-bit multiplier in Verilog that uses the add and shift method. However, when I run the simulation, I keep getting 00 for the result
value.
This is the code that I used:
`timescale 1ns / 1ps
module multi_8bit(
input clk,
input rstn,
input start,
input [3:0] a,
input [3:0] b,
output reg [7:0] result,
output reg done
);
localparam IDLE = 3'b000,
START = 3'b001,
LSB = 3'b010,
ADD = 3'b011,
SHIFT = 3'b100,
DONE = 3'b101;
reg [2:0] state, next_state;
reg [7:0] r_multiplicant;
reg [7:0] r_product;
reg [3:0] r_multiplier;
reg [2:0] r_count;
always @(posedge clk, negedge rstn)
begin
if(!rstn)
begin
state <= IDLE;
end
else
begin
state <= START;
end
end
always@(*)
begin
case(state)
IDLE:
begin
if(start)
next_state = START;
else
next_state = IDLE;
end
START:
begin
if(r_count != 0)
next_state = LSB;
else
next_state = DONE;
end
LSB:
begin
if(b[0])
next_state = ADD;
else
next_state = SHIFT;
end
ADD:
begin
next_state = SHIFT;
end
SHIFT:
begin
next_state = START;
end
DONE:
begin
next_state <= IDLE;
end
endcase
end
always@(posedge clk, negedge rstn)
begin
if(!rstn)
begin
r_multiplicant <= 0;
r_multiplier <= 0;
r_product <= 0;
r_count <= 4;
result <= 0;
done <= 0;
end
else
begin
begin
case(state)
IDLE:
begin
end
START:
begin
r_multiplicant = a;
r_multiplier = b;
end
LSB:
begin
r_count <= r_count - 1;
end
ADD:
begin
r_product <= r_product + r_multiplicant;
end
SHIFT:
begin
r_multiplicant <= r_multiplicant << 1;
r_multiplier <= r_multiplier >> 1;
end
DONE:
begin
assign result = r_product;
end
endcase
end
end
end
endmodule
And this is the testbench code that I used:
`timescale 1ns / 1ps
module tb_multi_8bit();
reg clk;
reg rstn;
reg start;
reg [3:0] a;
reg [3:0] b;
wire [7:0] result;
always #10 clk = ~clk;
multi_8bit test(
.clk(clk),
.rstn(rstn),
.start(start),
.a(a),
.b(b),
.result(result)
);
initial
begin
clk = 0; rstn = 1; start = 0;
#15 rstn = 0;
#25 rstn = 1;
#20 start = 1;
#10 a[0] = 0; a[1] = 1; a[2] = 1; a[3] = 0;
b[0] = 0; b[1] = 0; b[2] = 0; b[3] = 1;
#20 a[0] = 0; a[1] = 1; a[2] = 1; a[3] = 0;
b[0] = 0; b[1] = 0; b[2] = 1; b[3] = 0;
#20 a[0] = 0; a[1] = 1; a[2] = 1; a[3] = 0;
b[0] = 0; b[1] = 0; b[2] = 0; b[3] = 1;
#20 $finish;
end
endmodule
I just started learning Verilog, and this is my first time using the shift function, so I have no idea where I made a mistake in the code.
Upvotes: 2
Views: 252
Reputation: 62019
There is a bug in the sequential logic of your state machine. After reset, you force the state to always be START
, but you should set it to next_state
. This was obvious when I looked at waveforms of your internal signals.
This allows the state machine to progress through other states:
always @(posedge clk, negedge rstn)
begin
if(!rstn)
begin
state <= IDLE;
end
else
begin
state <= next_state;
end
end
Also, I added more delay before you end the simulation to see more states:
#50 $finish;
The result
remains at 0 because the state machine never reaches the DONE
state where you update the result. You need to look at waveforms to understand why you never reach that state.
Upvotes: 1