I'm trying to write a module which performs convolution on 24 by 24 bitmap image.
And here is the DUT and testbench.
Maybe there are some problems and I spend couple of hours to find what is problem but I can't figure it out.
Additionally, RTL Anaylsis works well without any error which makes me think that there is no problem on DUT.
Is there anyone who can help me?
module top_conv(clk,resetn,start,load_image_0,load_image_1,load_image_2,done,result);
input clk,resetn,load_image_0,load_image_1,load_image_2,start;
output done,result;
reg [1:0] st;
reg [1:0] nst;
reg [7:0] input_buffer_0 [0:2];
reg [7:0] input_buffer_1 [0:2];
reg [7:0] input_buffer_2 [0:2];
wire [7:0] load_image_0;
wire [7:0] load_image_1;
wire [7:0] load_image_2;
reg [7:0] result;
reg done;
integer load_cnt, row_cnt, col_cnt , result_cnt ;
parameter IDLE = 2'b00, LOAD = 2'b01, MAC = 2'b10, DONE = 2'b11;
always#(posedge clk or negedge resetn)begin
case(st)
LOAD:begin
input_buffer_0[load_cnt] <= load_image_0;
input_buffer_1[load_cnt] <= load_image_1;
input_buffer_2[load_cnt] <= load_image_2;
end
MAC:begin
input_buffer_0[0] <= input_buffer_0[1];
input_buffer_1[0] <= input_buffer_1[1];
input_buffer_2[0] <= input_buffer_2[1];
input_buffer_0[1] <= input_buffer_0[2];
input_buffer_1[1] <= input_buffer_0[2];
input_buffer_2[1] <= input_buffer_0[2];
input_buffer_0[2] <= load_image_0;
input_buffer_1[2] <= load_image_1;
input_buffer_2[2] <= load_image_2;
end
endcase
end
always#(posedge clk or negedge resetn)begin
if(!resetn) load_cnt <= 0;
else if(st == LOAD) load_cnt <= load_cnt + 1;
else load_cnt <= 0;
end
always#(posedge clk or negedge resetn)begin
if(!resetn) begin
col_cnt <= 0;
row_cnt <= 0;
end
else if(st == MAC) begin
if(col_cnt == 21) begin
col_cnt <= 0;
row_cnt <= row_cnt +1;
end
end
else begin
col_cnt <= 0;
row_cnt <= 0;
end
end
always#(posedge clk or negedge resetn)begin
if( st == MAC ) begin
result <= (input_buffer_0[0] + 2*input_buffer_0[1] + input_buffer_0[2])/16 + (input_buffer_1[0] + 2*input_buffer_1[1] + input_buffer_1[2])/8 + (input_buffer_2[0] + 2*input_buffer_2[1] + input_buffer_2[2])/16;
done <= 1'b1;
end
else done <=1'b0;
end
always#(posedge clk or negedge resetn)begin
if(!resetn) st <= 0;
else st <= nst;
end
always#(*)begin
case(st)
IDLE:begin
if(start) nst = LOAD;
else nst = IDLE;
end
LOAD:begin
if(load_cnt == 2)nst = MAC;
else nst = LOAD;
end
MAC:begin
if((row_cnt == 21)&&(col_cnt == 21)) nst = DONE;
else if(col_cnt == 21) nst = LOAD;
else nst = MAC;
end
DONE:begin
nst = IDLE;
end
endcase
end
endmodule
module testbench;
reg clk,resetn,start;
reg[7:0] val;
reg [7:0] b_load_image_0,g_load_image_0,r_load_image_0;
reg [7:0] b_load_image_1,g_load_image_1,r_load_image_1;
reg [7:0] b_load_image_2,g_load_image_2,r_load_image_2;
wire [2:0] done;
wire [7:0] b_result,g_result,r_result;
integer index;
top_conv blue_result (clk,resetn,start,b_load_image_0,b_load_image_1,b_load_image_2,done[0],b_result);
top_conv green_result (clk,resetn,start,g_load_image_0,g_load_image_1,g_load_image_2,done[1],g_result);
top_conv red_result (clk,resetn,start,r_load_image_0,r_load_image_1,r_load_image_2,done[2],r_result);
parameter read_fileName1 = "D:/blur_filter_unit/test.bmp" ;
localparam ARRAY_LEN = 24*24*3 + 54;
reg [7:0] data1 [0:ARRAY_LEN-1];
integer size,start_pos,width,height,bitcount;
task readBMP;
integer fileID1;
begin
fileID1 = $fopen(read_fileName1, "rb");
$display("%d" ,fileID1);
if(fileID1 == 0) begin
$display("Error: please check file path");
$finish;
end
else begin
$fread(data1, fileID1);
$fclose(fileID1);
size = {data1[5],data1[4],data1[3],data1[2]};
$display("size - %d", size);
start_pos = {data1[13],data1[12],data1[11],data1[10]};
$display("startpos : %d", start_pos);
width = {data1[21],data1[20],data1[19],data1[18]};
height = {data1[25],data1[24],data1[23],data1[22]};
$display("width - %d; height - %d",width,height);
bitcount = {data1[29],data1[28]};
if(bitcount != 24) begin
$display("Error: Please check the image file. It may be corrupted");
end
if(width%4)begin
$display("width is not suitable");
$finish;
end
end
end
endtask
integer i,j;
localparam RESULT_ARRAY_LEN = 24*24*3;
reg[7:0] result[0:RESULT_ARRAY_LEN - 1];
always #(posedge clk or negedge resetn)begin
if(!resetn)begin
j <= 8'b0;
end
else begin
if(&done[2:0]) begin
result[j] <= b_result;
result[j+1] <= g_result;
result[j+2] <= r_result;
j <= j+3;
end
end
end
parameter write_fileName1 = "D:/blur_filter_unit/result.bmp";
task writeBMP;
integer fileID, k;
begin
fileID = $fopen(write_fileName1,"wb");
for(k = 0; k < start_pos; k=k+1)begin
$fwrite(fileID, "%c",data1[k]);
end
for(k = start_pos; k<size; k=k+1)begin
$fwrite(fileID,"%c",result[k-start_pos]);
end
$fclose(fileID);
$display("Result.bmp is generated \n");
end
endtask
always begin
#1 clk = ~clk;
end
initial begin
clk = 1;
resetn = 0;
start = 0;
index = 1;
b_load_image_0 = 0;
g_load_image_0 = 0;
r_load_image_0 = 0;
b_load_image_1 = 0;
g_load_image_1 = 0;
r_load_image_1 = 0;
b_load_image_2 = 0;
g_load_image_2 = 0;
r_load_image_2 = 0;
readBMP;
#10;
resetn = 1;
start = 1;
for(i = start_pos; i<size; i=i+3)begin
{r_load_image_0, r_load_image_1, r_load_image_2} ={data1[i+2],data1[i+2+width*3],data1[i+2+width*6]};
{g_load_image_0, g_load_image_1, g_load_image_2} = {data1[i+1],data1[i+1+width*3],data1[i+1+width*6]};
{b_load_image_0, b_load_image_1, b_load_image_2} = {data1[i],data1[i+width*3],data1[i+width*6]};
#1;
end
#10;
#writeBMP;
#10
$stop;
end
endmodule
Even though this is not a complete answer, for figuring out the error you can use the below code which is revised version of your code for ease of debugging.
i think when synthesizing your design you might have faced this issue
Due to line numbers 25 & 71 in your code.You are declaring edge sensitive signal in sensitivity list and u are not using it in the always block. so tool cannot understand how to map it and throwing an error.
module top_conv(
input clk,resetn,start,
input [7:0] load_image_0,load_image_1,load_image_2,
output reg done,
output reg [7:0] result
);
reg [7:0] input_buffer_0 [0:2];
reg [7:0] input_buffer_1 [0:2];
reg [7:0] input_buffer_2 [0:2];
reg [4:0] row_cnt, col_cnt;
reg [1:0] load_cnt;
parameter IDLE = 2'b00,
LOAD = 2'b01,
MAC = 2'b10,
DONE = 2'b11;
reg [1:0] state,next;
always#(posedge clk or negedge resetn)begin
if(!resetn) state <= #10 IDLE ;
else state <= #10 next ;
end
always#(*)begin
next = 'bx; // default undefined state
case(state)
IDLE: next = start ? LOAD : IDLE ;
LOAD: next = (load_cnt == 2) ? MAC : LOAD ;
MAC : next = ((row_cnt == 21)&&(col_cnt == 21)) ? DONE :
(col_cnt == 21) ? LOAD : MAC ;
DONE: next = IDLE ;
endcase
end
always#(posedge clk or negedge resetn)begin
if(!resetn) begin
col_cnt <= #10 0;
row_cnt <= #10 0;
load_cnt <= #10 0;
done <= #10 1'b0;
result <= #10 0;
end else begin
col_cnt <= #10 0;
row_cnt <= #10 0;
load_cnt <= #10 0;
done <= #10 1'b0;
result <= #10 0;
case(next)
LOAD:load_cnt <= #10 load_cnt + 1'b1 ;
MAC :begin
col_cnt <= #10 (col_cnt == 21) ? 0 : col_cnt + 1'b1 ;
row_cnt <= #10 (col_cnt == 21) ? row_cnt : row_cnt + 1'b1 ;
end
DONE:begin
result <= #10 (input_buffer_0[0] + 2*input_buffer_0[1] + input_buffer_0[2])/16 +
(input_buffer_1[0] + 2*input_buffer_1[1] + input_buffer_1[2])/8 +
(input_buffer_2[0] + 2*input_buffer_2[1] + input_buffer_2[2])/16 ;
done <= #10 1'b1;
end
endcase
end
end
always#(posedge clk)begin
case(next)
LOAD:begin
input_buffer_0[load_cnt] <= #10 load_image_0;
input_buffer_1[load_cnt] <= #10 load_image_1;
input_buffer_2[load_cnt] <= #10 load_image_2;
end
MAC:begin
input_buffer_0[0] <= #10 input_buffer_0[1];
input_buffer_1[0] <= #10 input_buffer_1[1];
input_buffer_2[0] <= #10 input_buffer_2[1];
input_buffer_0[1] <= #10 input_buffer_0[2];
input_buffer_1[1] <= #10 input_buffer_0[2];
input_buffer_2[1] <= #10 input_buffer_0[2];
input_buffer_0[2] <= #10 load_image_0;
input_buffer_1[2] <= #10 load_image_1;
input_buffer_2[2] <= #10 load_image_2;
end
endcase
end
endmodule
Related
For a lab I must create the logic to use on a Digilent PMOD ALS. In the lab requirenment I cannot use the sclk signal on the sensitivity list and therefore use a state machine to create the 2.5 MHz clk signal to send to the PMOD ALS. See the code below:
module sens_interface(
input clk, //clk 10Mhz
input reset_n,
input [15:0] delay,
input datain,
output reg sclk,
output reg cs_n,
output reg [3:0] Cout,
output reg [3:0] Dout,
output reg [5:0] cnt
);
//params
//state machine 1
parameter SA0 = 3'b000;
parameter SA1 = 3'b001;
parameter SA2 = 3'b010;
parameter SA3 = 3'b011;
parameter SD0 = 3'b100;
parameter SD1 = 3'b101;
//state machine 2
parameter SR0 = 2'b00;
parameter SR1 = 2'b01;
parameter SR2 = 2'b10;
parameter SR3 = 2'b11;
//pmod als registers
//reg sclk; //2.5Mhz clk
//reg cs_n; //
reg [14:0] data_reg;
//count registers
//reg [5:0] cnt;
reg [15:0] cnt_d;
reg [5:0] cnt_r;
//state registers
reg [2:0] state_sclk;
reg [1:0] state_data;
//State Machine 1
always # (posedge clk)begin
if(reset_n == 1'b0)begin
cs_n <= 1'b1;
sclk <= 0;
cnt <= 6'd0;
cnt_d <= 16'd0;
end
else
case(state_sclk)
SA0:begin
sclk <= 1'b1;
state_sclk <= SA1;
if (cnt <= 6'd17)
cs_n <= 1'b0;
else
cs_n <= 1'b1;
end
SA1:begin
state_sclk <= SA2;
end
SA2:begin
sclk <= 1'b0;
cnt <= cnt + 1;
state_sclk <= SA3;
end
SA3:begin
if(cnt == 6'd21)begin
cnt <= 0;
state_sclk <= SD0;
end
else
state_sclk <= SA0;
end
SD0:begin
cnt_d <= delay;
state_sclk <= SD1;
end
SD1:begin
if (cnt_d == 0)
state_sclk <= SA0;
else
cnt_d <= cnt_d - 1;
end
default:begin
state_sclk <= SA0;
end
endcase
end
always # (posedge clk)begin
if (reset_n == 1'b0)begin
cnt_r <= 0;
data_reg <= 0;
end
else begin
case (state_data)
SR0:begin
if (cs_n == 1'b1 && sclk == 1'b1)
state_data <= SR1;
end
SR1: begin
if (cs_n == 1'b1)begin
state_data <= SR0;
cnt_r <= 0;
end
else if (sclk == 1'b0)
state_data <= SR2;
end
SR2:begin
if (cs_n == 1'b1)begin
state_data <= SR0;
cnt_r <= 0;
end
else if (cnt_r == 15)
state_data <= SR3;
else if (sclk == 1'b1)begin
data_reg [14-cnt_r] <= datain;
cnt_r <= cnt_r + 1;
state_data <= SR1;
end
end
SR3:begin
if (cs_n == 1) begin
Cout <= data_reg [11:8];
Dout <= data_reg [7:4];
state_data <= SR0;
end
end
default:begin
state_data <= SR0;
end
endcase
end
end
endmodule
I tried to make a simulation of it and the simulation indicates that after my cnt register reaches 15 it just cuts out and goes to 0.
simulation
That behavior is caused by your SA3 state.
SA3:begin
if(cnt == 6'd21)begin
cnt <= 0;
state_sclk <= SD0;
end
else
state_sclk <= SA0;
end
end
When your cnt == 6'd21 (which is 6'h15) the cnt is set to zero.
The generic variable names and lack of comments makes it difficult to see why this is not the expected behavior.
I am trying to simulate the following code for an synchronous ram in Verilog.
When I am trying to write in a specific address, dataOut is not coming the way I was expecting. It is skipping 1 address while reading data in the specified address.
Can anyone tell me the problem?
Here is GtkWave simulation result:
module ram
# (parameter ADDR_WIDTH = 4,
parameter DATA_WIDTH = 10,
parameter DEPTH = 1 << ADDR_WIDTH
)
( input clk,
input [ADDR_WIDTH-1:0] addr,
input [DATA_WIDTH-1:0] dataIn,
input enable,
input write,
input read,
input resetRam,
output[DATA_WIDTH-1:0] dataOut
);
reg [DATA_WIDTH-1:0] tmp_data;
reg [DATA_WIDTH-1:0] mem [DEPTH-1:0];
//reset
always #(posedge clk) begin
if(enable & resetRam) begin
for (integer i = 0; i < 2**ADDR_WIDTH; i = i + 1)
begin
mem[i] = {DATA_WIDTH{1'b0}};
end
end
end
//write
always # (posedge clk) begin
if (enable & write & !read)
mem[addr] <= dataIn;
end
//read
always # (posedge clk) begin
if (enable & !write & read)
tmp_data <= mem[addr];
end
assign dataOut = enable & read & !write ? tmp_data : 'hz || enable & resetRam ? 10'b0 : 'hz;
endmodule
module ram_tb;
parameter ADDR_WIDTH = 4;
parameter DATA_WIDTH = 10;
parameter DEPTH = 1 << ADDR_WIDTH;
reg clk;
reg enable;
reg write;
reg read;
reg resetRam;
reg [ADDR_WIDTH-1:0] addr;
wire [DATA_WIDTH-1:0] dataIn;
wire [DATA_WIDTH-1:0] dataOut;
reg [DATA_WIDTH-1:0] tb_data;
ram #(.DATA_WIDTH(DATA_WIDTH)) iram(
.clk(clk),
.addr(addr),
.dataIn(dataIn),
.enable(enable),
.write(write),
.read(read),
.resetRam(resetRam),
.dataOut(dataOut)
);
always #10 clk = ~clk;
assign dataIn = !read ? tb_data : 'hz ;
initial begin
$monitor("addrs = %b resetRam=%b Write = %b read=%b dataIn = %b dataOut = %b", addr,resetRam,write,read,dataIn,dataOut);
$dumpfile("ram_tb.vcd");
$dumpvars(0,ram_tb);
{clk, enable, write, addr, tb_data, read,resetRam} <= 0;
// //writing all the adrress with random value
// for (integer i = 0; i < DEPTH; i= i+1) begin
// #(posedge clk) addr <= i; write = 1; enable =1; read = 0; tb_data <= $random;
// end
// //reading them
// for (integer i = 0; i < DEPTH; i= i+1) begin
// #(posedge clk) addr = i; write = 0; enable = 1; read = 1;
// end
//Writing at specific address
#(posedge clk) addr = 4'b1000; write = 1; enable =1; read = 0; tb_data <= $random;
#(posedge clk) addr = 4'b1111; write = 1; enable =1; read = 0; tb_data <= $random;
#(posedge clk) addr = 4'b1001; write = 1; enable =1; read = 0; tb_data <= $random;
#(posedge clk) addr = 4'b0001; write = 1; enable =1; read = 0; tb_data <= $random;
//reading them
#(posedge clk) addr = 4'b1000;write = 0; enable =1; read = 1;
#(posedge clk) addr = 4'b1111;write = 0; enable =1; read = 1;
#(posedge clk) addr = 4'b1001;write = 0; enable =1; read = 1;
#(posedge clk) addr = 4'b0001;write = 0; enable =1; read = 1;
// //reset memory
// for (integer i = 0; i < DEPTH; i= i+1) begin
// repeat (1) #(posedge clk) addr <= i; enable <= 1; resetRam <=1;
// end
#200 $finish;
end
endmodule
//iverilog -o ram_tb.vpp ram.v
//vvp ram_tb.vpp
You have a race condition. You should use nonblocking assignments (<=) in your design and testbench for all synchronous signals.
In the design, change:
mem[i] = {DATA_WIDTH{1'b0}};
to:
mem[i] <= {DATA_WIDTH{1'b0}};
In the testbench, use:
//Writing at specific address
#(posedge clk) addr <= 4'b1000; write <= 1; enable <=1; read <= 0; tb_data <= $random;
#(posedge clk) addr <= 4'b1111; write <= 1; enable <=1; read <= 0; tb_data <= $random;
#(posedge clk) addr <= 4'b1001; write <= 1; enable <=1; read <= 0; tb_data <= $random;
#(posedge clk) addr <= 4'b0001; write <= 1; enable <=1; read <= 0; tb_data <= $random;
//reading them
#(posedge clk) addr <= 4'b1000;write <= 0; enable <=1; read <= 1;
#(posedge clk) addr <= 4'b1111;write <= 0; enable <=1; read <= 1;
#(posedge clk) addr <= 4'b1001;write <= 0; enable <=1; read <= 1;
#(posedge clk) addr <= 4'b0001;write <= 0; enable <=1; read <= 1;
With the above changes, I get your expected output with iverilog on edaplayground.
I'm trying to write a simple 4-bit stack of depth 8 with push/pop signals but it's behaving in a very odd manner. One of my if statements works fine and the other one does not run at all. Here's my code:
module Stack_8x4(
input wire clk,
input wire reset,
input wire push,
input wire pop,
input wire [3:0] data_in,
output reg [3:0] data_out,
output reg empty,
output reg full
);
reg [3:0] index;
reg [3:0] stack [7:0];
always #(posedge reset) begin
index <= -1;
data_out = 4'd0;
empty = 1;
full = 0;
end
always #(posedge clk) begin
if (push & !pop) begin
empty = 0;
if(!full) begin
index = index + 1;
stack[index] = data_in;
if(index > 6) full = 1;
end
end
if (pop & !push) begin
full = 0;
if(!empty) begin
data_out = stack[index];
index = index - 1;
if(index < 0) empty= 1;
end else data_out = 0;
end
end
endmodule
As you can see, the logic for push and pop is almost the same. My question is why does the line if(index < 0) empty= 1; does not work while if(index > 6) full = 1; works just fine?
Here's a test bench and simulation for more details:
module sim();
reg clk;
reg reset;
reg push;
reg pop;
reg [3:0] data_in;
wire [3:0] data_out;
wire full;
wire empty;
//wire [3:0]i;
always begin
clk = 0;
#5
clk = 1;
#5
clk = 0;
end
initial begin
// setup
reset = 1;
push = 0;
pop = 0;
data_in = 0;
#10
reset = 0;
// idle
#20
// push 1, 2, 3, 4, 5, 6, 7, 8, 9 to fill the module and test for idling at full
push = 1;
data_in = 1;
#10
data_in = 2;
#10
data_in = 3;
#10
data_in = 4;
#10
data_in = 5;
#10
data_in = 6;
#10
data_in = 7;
#10
data_in = 8;
#10
data_in = 9;
#10
data_in = 10;
#10
data_in = 11;
#10
pop = 1;
#10
push = 0;
#30
pop = 0;
push = 1;
#30
push = 0;
#20
pop = 1;
// pop
//pop = 1;
end
Stack_8x4 S (
.clk(clk),
.push(push),
.pop(pop),
.reset(reset),
.data_in(data_in),
.data_out(data_out),
.full(full),
.empty(empty)
);
endmodule
Your main issue is in the attempt to use signed data with unsigned variables. So, index <= -1;, index < 0 just do not work as you expect. My suggestion is to forget about signed arithmetic and do unsigned only.
Other issues:
you should use only a single always block to do reset and non-reset work.
you should use non-blocking assignments everywhere in your always #posedge blocks
for some reason you do not use 2 elements in your stack (6, 7) due to 'index < 6'.
So, here is my re-write of your code:
always #(posedge clk) begin
if (reset) begin
index <= 0;
data_out <= 4'd0;
empty <= 1;
full <= 0;
end
else if (push & !pop) begin
if(index < 8) begin
full<= 0;
stack[index] <= data_in;
index <= index + 1;
end
else
full <= 1;
end
else if (pop & !push) begin
if(index == 0) begin
empty <= 1;
data_out <= 0;
end
else begin
empty <= 0;
index <= index - 1;
data_out <= stack[index];
end
end // if (pop & !push)
end // always # (posedge clk)
I make a design for an adder but the result is wrong.
module FMUL(CLK, St, F1, E1, F2, E2, F, V, done);
input CLK;
input St;
input [3:0] F1;
input [3:0] E1;
input [3:0] F2;
input [3:0] E2;
output[6:0] F;
output V;
output done;
reg[6:0] F;
reg done;
reg V;
reg[3:0] A;
reg[3:0] B;
reg[3:0] C;
reg[4:0] X;
reg[4:0] Y;
reg Load;
reg Adx;
reg SM8;
reg RSF;
reg LSF;
reg AdSh;
reg Sh;
reg Cm;
reg Mdone;
reg[1:0] PS1;
reg[1:0] NS1;
reg[2:0] State;
reg[2:0] Nextstate;
initial
begin
State = 0;
PS1 = 0;
NS1 = 0;
Nextstate=0;
end
always #(PS1 or St or Mdone or X or A or B)
begin : main_control
Load = 1'b0;
Adx = 1'b0;
NS1 = 0;
SM8 = 1'b0;
RSF = 1'b0;
LSF = 1'b0;
V = 1'b0;
F = 7'b0000000;
done = 1'b0;
case (PS1)
0 :
begin
F = 7'b0000000;
done = 1'b0;
V = 1'b0;
if(St == 1'b1)
begin
Load = 1'b1;
NS1 = 1;
end
end
1 :
begin
Adx = 1'b1;
NS1 = 2;
end
2 :
begin
if(Mdone == 1'b1)
begin
if(A==0)
begin
SM8 = 1'b1;
end
else if(A == 4 & B == 0)
begin
RSF = 1'b1;
end
else if (A[2] == A[1])
begin
LSF = 1'b1;
end
NS1 = 3;
end
else
begin
NS1 = 2;
end
end
3 : begin
if(X[4] != X[3])
begin
V = 1'b1;
end
else
begin
V = 1'b0;
end
done = 1'b1;
F = {A[2:0],B};
if(St==1'b0)
begin
NS1 = 0;
end
end
endcase
end
always #(State or Adx or B)
begin : mul2c
AdSh = 1'b0;
Sh = 1'b0;
Cm = 1'b0;
Mdone = 1'b0;
Nextstate = 0;
case(State)
0 :
begin
if(Adx==1'b1)
begin
if((B[0]) == 1'b1)
begin
AdSh = 1'b1;
end
else
begin
Sh = 1'b1;
end
Nextstate = 1;
end
end
1,2 :
begin
if((B[0])==1'b1)
begin
AdSh = 1'b1;
end
else
begin
Sh = 1'b1;
end
Nextstate = State + 1;
end
3:
begin
if((B[0])==1'b1)
begin
Cm = 1'b1;
AdSh = 1'b1;
end
else
begin
Sh = 1'b1;
end
Nextstate = 4;
end
4:
begin
Mdone = 1'b1;
Nextstate = 0;
end
endcase
end
wire [3:0] addout;
assign addout = (Cm == 1'b0)? (A+C) : (A-C);
always #(posedge CLK)
begin : update
PS1 <= NS1;
State <= Nextstate;
if(Load == 1'b1)
begin
X <= {E1[3], E1};
Y <= {E2[3], E2};
A <= 4'b0000;
B <= F1;
C <= F2;
end
if(Adx == 1'b1)
begin
X <= X+Y;
end
if(SM8 == 1'b1)
begin
X <= 5'b11000;
end
if(RSF == 1'b1)
begin
A <= {1'b0, A[3:1]};
B <= {A[0], B[3:1]};
X <= X+1;
end
if(LSF == 1'b1)
begin
A <= {A[2:0], B[3]};
B <= {B[2:0], 1'b0};
X <= X+31;
end
if(AdSh == 1'b1)
begin
A <= {(C[3]^Cm), addout[3:1]};
B <= {addout[0], B[3:1]};
end
if(Sh == 1'b1)
begin
A <= {A[3], A[3:1]};
B <= {A[0], B[3:1]};
end
end
endmodule
test bench.
module tb_FMUL();
wire[6:0] F;
wire done;
wire V;
reg[3:0] A;
reg[3:0] B;
reg[3:0] C;
reg[4:0] X;
reg[4:0] Y;
reg Load;
reg Adx;
reg SM8;
reg RSF;
reg LSF;
reg AdSh;
reg Sh;
reg Cm;
reg Mdone;
reg[1:0] PS1;
reg[1:0] NS1;
reg[2:0] State;
reg[2:0] Nextstate;
reg CLK;
reg St;
reg [3:0] F1;
reg [3:0] E1;
reg [3:0] F2;
reg [3:0] E2;
FMUL u0(CLK, St, F1, E1, F2, E2, F, V, done);
always
begin
#10 CLK <= ~CLK;
end
initial
begin
#100 F1 = 2.125;
E1 = 5; F2 = 5.1; E2 = 1; St=0;
#100 F1 = 1.125;
E1 = 5; F2 = 2.1; E2 = 2; St=0;
#100 F1 = 5.125;
E1 = 5; F2 = 3.1; E2 = 3; St=0;
end
endmodule
The simulation results waveform.
enter image description here
I refer to the book.There is no code test bench.
So I made. But did't operate.
also CLK not is not changed.
please review the testbench code.
You have (at least) two problems:
Your clock needs to be initialised (eg to 1'b0):
initial CLK = 1'b0;
The initial value of any wire or reg in Verilog is 1'bx; ~1'bx is 1'bx; so CLK remains at 1'bx.
Your simulation doesn't stop. I added a call to $finish in the main initial block.
https://www.edaplayground.com/x/r4U
Good day guys, I'm created a Shift - And - Add multiplier. I'm confused on why my output is wrong and always at 85. Is it something with the Test bench ? It's working by the way.
new1.v
`define M ACC[0]
module mult4X4 (Clk, St, Mplier, Mcand, Done, Result);
input Clk,St;
input [3:0] Mplier, Mcand;
output Done;
output [7:0] Result;
reg [3:0] State;
reg [8:0] ACC;
initial
begin
State = 0;
ACC = 0;
end
always #(posedge Clk)
begin
case (State)
0:
begin
if(St == 1'b1)
begin
ACC[8:4] <= 5'b00000 ;
ACC[3:0] <= Mplier ;
State <= 1;
end
end
1,3,5,7 :
begin
if(`M==1'b1)
begin
ACC[8:4] <= {1'b0, ACC[7:4]} + Mcand ;
State <= State +1;
end
else
begin
ACC <= {1'b0, ACC[8:1]};
State <= State + 2;
end
end
2,4,6,8 :
begin
ACC <= {1'b0, ACC[8:1]};
State <= State +1;
end
9:
begin
State <= 0;
end
endcase
end
assign Done = (State == 9) ? 1'b1 : 1'b0 ;
assign Result = (State == 9) ? ACC[7:0] : 8'b01010101;
endmodule
tb_new1.v
module tb_mult4X4;
reg Clk,St,nReset;
reg [3:0] Mplier;
reg [3:0] Mcand;
wire Done;
wire [7:0] Result;
mult4X4 UUT (Clk,St,Mplier,Mcand,Done,Result);
initial begin
$dumpfile ("mult4X4.vpd");
$dumpvars;
end
initial
Clk = 0;
always
#5 Clk =~Clk;
initial begin
nReset = 0;
St = 0;
Mcand = 4'b1101;
Mplier = 4'b1011;
#10
nReset = 1;
St = 1;
Mcand = 4'b1111;
Mplier = 4'b1001;
#10
Mcand = 4'b0101;
Mplier = 4'b1010;
#10
Mcand = 4'b1111;
Mplier = 4'b1111;
#10
Mcand = 4'b1101;
Mplier = 4'b1010;
$finish;
end
endmodule
I ran though the code so many times and everything seems to be following my FSM. Can anyone please point out where went wrong. Really confused on this one
#10 is way to short. Your RTL requires 10 clocks to complete but you change the input every clock (half clk is #5).
Use #100 or better yet #(posedge Done); (which makes the test-bench to wait for done regardless the number of clocks that is required).