eddie
eddie

Reputation: 11

modelsim (calculator) error loading design

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

Answers (1)

Greg
Greg

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

Related Questions