【问题标题】:verilog modelsim (calculator) error loading designverilog modelsim(计算器)错误加载设计
【发布时间】:2022-01-10 22:55:55
【问题描述】:

您好,我在运行 modelsim 时遇到问题。我创建了可以进行加、减、乘、除计算的 16 位计算器。输入和输出是 20 位 bcd 码。首先,我将输入 bcd 代码转换为二进制。二进制计算后,我将二进制代码转换为 bcd 代码。我不应该在verilog代码中使用*'、'/'、'%'、'>'、'>>'。这是我的计算器代码

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

以下是测试台代码 `时间刻度 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

编译没有问题......另一个测试台也没有问题......两周我什么都做不了,请帮助我聪明的家伙......

【问题讨论】:

    标签: verilog calculator modelsim test-bench


    【解决方案1】:

    我没有完全调试您的代码,但我注意到了以下一些问题:

    calculator_p 中,从敏感度列表中删除negedge resultposedge result。将它们放在灵敏度列表中并在块中引用它们会告诉合成器它们是异步信号。

    您可能还需要从敏感度列表中删除rst。 FGPA 通常对异步复位的支持有限。您可能支持它,也可能不支持,或者可能只有少数几个具有异步复位功能的触发器。将其从敏感度列表中删除。

    mp 模块在非阻塞赋值中使用不当,for 循环无法静态展开。预期的等效代码如下所示(64k 循环又大又慢;也许需要重新考虑)。 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
    

    一般来说组合块应该使用阻塞赋值,同步块应该使用非阻塞赋值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多