Reputation: 11
I have problem with running modelsim. i create 16 bit calculator that can operate add, substract, multiple, division calculation. input and outbut is 20bit bcd-code. For calculation first i convert input bcd-code to binary. After binary calculation i convert binary code to bcd code. i shouldn't use *’, ‘/’, ‘%’, ‘<<’, ‘>>’, ‘<<<’, and ‘>>>’ in verilog code. this is my calculator code:
module calculator_p(
input wire [3:0] a,
input wire clk,
input wire rst, //key0
input wire result, //sw9
input wire in_set , //sw4
input wire [1:0] selectmode, //sw6-5
input wire mode, //sw7 1(-) 0(+)
output reg ov, //ledr9
output reg [19:0] in_1, //first_input
output reg [19:0] in_2, //second_input
output reg [19:0] out, //final output
output reg [19:0] m1, //add_sub result
output reg [19:0] m2, //multiple result
output reg [11:0] m3,
output reg [15:0] remain, //divide calculation remain //division result
output wire [6:0] digit4,
output wire [6:0] digit3,
output wire [6:0] digit2,
output wire [6:0] digit1,
output wire [6:0] digit0
);
reg [15:0] cal1; //for calculation first binary variable
reg [15:0] cal2; //for calculation second binary variable
reg [7:0] cal2_1; //for divide calculation binary second variable
reg [15:0] cal3; //add, sub, multiple calculation binary result
reg [7:0] cal3_1; //divide calculation binary result
always @ (posedge clk, negedge rst, negedge result)
begin
if (rst==1'b0)
begin
in_1<=20'b0;
in_2<=20'b0;
out<=20'b0;
end
else if (result==1)
begin
if (in_set==1'b0)
begin
in_1[3:0]<=a;
in_1[7:4]<=in_1[3:0];
in_1[11:8]<=in_1[7:4];
in_1[15:12]<=in_1[11:8];
in_1[19:16]<=in_1[15:12];
end
else if (in_set==1'b1)
begin
in_2[3:0]<=a;
in_2[7:4]<=in_2[3:0];
in_2[11:8]<=in_2[7:4];
in_2[15:12]<=in_2[11:8];
in_2[19:16]<=in_2[15:12];
end
end
else
begin
in_1<=in_1;
in_2<=in_2;
end
end
bcd2bin conver1(.bcd(in_1),.bin(cal1));
bcd2bin conver2(.bcd(in_2),.bin(cal2));
bcd2bin conver3(.bcd(in_2),.bin(cal2_1));
add_sub adsb
(.cal1(cal1),.calc2(cal2),.mode({selectmode,in_set}),.cal3(cal3));
mp multi(.cal1(cal1),.cal2(cal2),.cal3(cal3));
divider db(.cal1(cal1),.cal2_1(cal2_1),.cal3_1(cal3_1),.remain(remain));
bin2bcd_16 m1_1(.bin(cal3),.bcd_tt(m1[19:16]),
.bcd_th(m1[15:12]),.bcd_h(m1[11:8]),
.bcd_t(m1[7:4]),.bcd_o(m1[3:0]));
bin2bcd_16 m2_2(.bin(cal3),.bcd_tt(m1[19:16]),
.bcd_th(m2[15:12]),.bcd_h(m2[11:8]),
.bcd_t(m2[7:4]),.bcd_o(m2[3:0]));
bin2bcd_8
m3_3(.bin(cal3_1),.bcd_h(m3[11:8]),.bcd_t(m3[7:4]),.bcd_o(m3[3:0]));
always @ *
begin
if (cal3 > 16'd32768)
ov<=1'b1;
else
ov<=1'b0;
end
always @ (posedge clk, posedge result)
begin
if (result==1)
begin
case ({selectmode,in_set})
3'b000 : out<=in_1; //first input
3'b001 : out<=in_2; //second input
3'b010 : out<=m1; //add
3'b011 : out<=m1; //sub
3'b100 : out<=m2; //multiple
3'b101 : out<=m3; //divide
3'b110 : out<=20'b0; //null
3'b111 : out<=20'b0; //null
endcase
end
end
segdec b_0 (.i(out[3:0]),.o(digit0));
segdec b_1 (.i(out[7:4]),.o(digit1));
segdec b_2 (.i(out[11:8]),.o(digit2));
segdec b_3 (.i(out[15:12]),.o(digit3));
segdec b_4 (.i(out[19:16]),.o(digit4));
endmodule
module add_sub(
input wire [15:0] cal1,
input wire [15:0] cal2,
input wire [2:0] mode,
output reg [15:0] cal3
);
always @ *
begin
cal3<=16'b0;
if (mode==3'b010)
cal3<=cal1+cal2;
else if (mode==3'b011)
cal3<=cal1-cal2;
end
endmodule
module mp(
input wire [15:0] cal1,
input wire [15:0] cal2,
output reg [15:0] cal3
);
reg [15:0] i;
always @ *
begin
if (cal2==0)
begin
cal3<=0;
end
else begin
for (i=0;i<cal2;i=i+1)
begin
cal3<=cal3+cal1;
end
end
end
endmodule
module divider(
input wire [15:0] cal1,
input wire [7:0] cal2_1,
output reg [7:0] cal3_1,
output reg [15:0] remain
);
reg [15:0] i;
always @ *
begin
cal3_1<=8'b0;
remain<=cal1;
for (i=0;i<2000;i=i+1)
begin
if (cal1>cal2_1)
begin
remain<=remain-cal2_1;
cal3_1=cal3_1+1'b1;
end
else
begin
cal3_1<=8'b0;
remain<=cal1;
end
end
end
endmodule
module SegDec(
input wire [3:0]i,
output reg [6:0]o
);
always @ *
case (i)
4'b0000 : o = 7'b1000000;//0
4'b0001 : o = 7'b1111001;//1
4'b0010 : o = 7'b0100100;//2
4'b0011 : o = 7'b0110000;//3
4'b0100 : o = 7'b0011001;//4
4'b0101 : o = 7'b0010010;//5
4'b0110 : o = 7'b0000010;//6
4'b0111 : o = 7'b1011000;//7
4'b1000 : o = 7'b0000000;//8
4'b1001 : o = 7'b0010000;//9
endcase
endmodule
module bcd2bin(
input wire [19:0] bcd,
output reg [15:0] bin
);
reg [3:0] i;
reg [3:0] i1;
reg [3:0] i2;
reg [3:0] i3;
reg [15:0] io;
reg [15:0] i1o;
reg [15:0] i2o;
reg [15:0] i3o;
always @ *
begin
io=0;
i1o=0;
i2o=0;
i3o=0;
if (bcd[3:0]<4'b1010)
begin
if (bcd[19:4]==16'b0)
bin<=bcd[3:0];
else if (bcd[19:8]==12'b0)
begin
for (i=0;i<bcd[7:4];i=i+1)
begin
io=io+16'd10;
end
bin<=io+bcd[3:0];
end
else if (bcd[19:12]==8'b0)
begin
for (i=0;i<bcd[7:4];i=i+1)
begin
io=io+4'd10;
end
for (i1=0;i1<bcd[11:8];i1=i1+1)
begin
i1o=i1o+16'd100;
end
bin<=i1o+io+bcd[3:0];
end
else if (bcd[19:16]==4'b0)
begin
for (i=0;i<bcd[7:4];i=i+1)
begin
io=io+16'd10;
end
for (i1=0;i1<bcd[11:8];i1=i1+1)
begin
i1o=i1o+16'd100;
end
for (i2=0;i2<bcd[15:12];i2=i2+1)
begin
i2o=i2o+16'd1000;
end
bin<=i2o+i1o+io+bcd[3:0];
end
else
begin
for (i=0;i<bcd[7:4];i=i+1)
begin
io=io+16'd10;
end
for (i1=0;i1<bcd[11:8];i1=i1+1)
begin
i1o=i1o+16'd100;
end
for (i2=0;i2<bcd[15:12];i2=i2+1)
begin
i2o=i2o+16'd1000;
end
for (i3=0;i3<bcd[19:16];i3=i3+1)
begin
i3o=i3o+16'd10000;
end
bin<=i3o+i2o+i1o+io+bcd[3:0];
end
end
else
bin={15{1'bx}};
end
endmodule
module bin2bcd_8(
input wire [7:0] bin,
output reg [3:0] bcd_h,
output reg [3:0] bcd_t,
output reg [3:0] bcd_o
);
reg [3:0] i;
always @ *
begin
{bcd_h,bcd_t,bcd_o} = 0;
for (i = 0; i < 8; i = i+1)
begin
{bcd_h,bcd_t,bcd_o} = {bcd_h[2:0],bcd_t,bcd_o ,bin[7-i]};
if(i < 7 && bcd_o > 4)
bcd_o = bcd_o + 3;
if(i < 7 && bcd_t > 4)
bcd_t = bcd_t + 3;
if(i < 7 && bcd_h > 4)
bcd_h = bcd_h + 3;
end
end
endmodule
module bin2bcd_16(
input wire [19:0] bin,
output reg [3:0] bcd_tt,
output reg [3:0] bcd_th,
output reg [3:0] bcd_h,
output reg [3:0] bcd_t,
output reg [3:0] bcd_o
);
reg [5:0] i;
always @ *
begin
{bcd_tt,bcd_th,bcd_h,bcd_t,bcd_o} = 0;
for (i = 0; i < 16; i = i+1)
begin
{bcd_tt,bcd_th,bcd_h,bcd_t,bcd_o} =
{bcd_tt[2:0],bcd_th,bcd_h,bcd_t,bcd_o,bin[15-i]};
if(i < 7 && bcd_o > 4)
bcd_o = bcd_o + 3;
if(i < 7 && bcd_t > 4)
bcd_t = bcd_t + 3;
if(i < 7 && bcd_h > 4)
bcd_h = bcd_h + 3;
if(i < 7 && bcd_th > 4)
bcd_th = bcd_th + 3;
if(i < 7 && bcd_tt > 4)
bcd_tt = bcd_tt + 3;
end
end
endmodule
and below is test bench code:
`timescale 1ns/1ps
module calculator_tb;
reg [3:0] a;
reg clk;
reg rst; //sw9
reg result; //key0
reg in_set; //sw4
reg [1:0] selectmode; //sw6-5
reg mode; //sw7 1(-) 0(+)
wire ov; //ledr9
reg [19:0] in_1; //first_input
reg [19:0] in_2; //second_input
wire [19:0] out; //final output
wire [15:0] remain; //divide calculation remain
wire [19:0] m1; //add_sub result
wire [19:0] m2; //multiple result
wire [11:0] m3; //division result
wire [6:0] digit4;
wire [6:0] digit3;
wire [6:0] digit2;
wire [6:0] digit1;
wire [6:0] digit0;
calculator_p utt(
.a(a),
.clk(clk),
.rst(rst),
.result(result),
.in_set(in_set),
.selectmode(selectmode),
.mode(mode),
.ov(ov),
.in_1(in_1),
.in_2(in_2),
.out(out),
.remain(remain),
.m1(m1),
.m2(m2),
.m3(m3),
.digit4(digit4),
.digit3(digit3),
.digit2(digit2),
.digit1(digit1),
.digit0(digit0)
);
initial begin
clk<=1'b0;
#1 clk=~clk;
end
initial begin
rst<=1'b0;
#5 rst=~rst;
end
initial begin
{selectmode,in_set}<=3'b000;
#30 {selectmode,in_set}<=3'b001;
#60 {selectmode,in_set}<=3'b010;
#100 {selectmode,in_set}<=3'b011;
end
initial begin
result<=1'b1;
#27 result<=1'b0;
#29 result<=1'b1;
#56 result=1'b0;
#105 result=1'b1;
end
initial begin
a<=4'b0;
#15 a<=4'b0010;
#21 a<=4'b0001;
#34 a<=4'b0111;
end
endmodule
Compiling doesn't have problem, and another test bench doesn't have a problem too.
Upvotes: 1
Views: 325
Reputation: 19112
I didn't fully debug your code, but here are some issues I notice:
In calculator_p
remove negedge result
and posedge result
from the sensitivity lists. Having them in the sensitivity list and referencing them in the block tells the synthesizer that they are asynchronous signals.
You might need to remove the rst
from the sensitivity list as well. FGPAs typically have limited support for asynchronous reset. Your might support it, it might not, or there might only be a handful of flip-flops with asynchronous reset. Removing it from the sensitivity list.
The mp
module has improper use on non-blocking assignment and the for-loop cannot static unroll. The intended equivalent code would be like bellow (64k loops is big and and slow; maybe a rethink is needed). Similar problem exists in bcd2bin
.
always @* begin
cal3 = 0;
for (i=1;i<(2<<16);i=i+1) begin
if (i<cal2) begin
cal3 = cal3+cal1;
end
end
end
In general combinational blocks should use blocking assignments, synchronous blocks should use non-blocking assignments.
Upvotes: 1