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.