#verilog #calculator #modelsim #test-bench
#verilog #калькулятор #modelsim #испытательный стенд
Вопрос:
здравствуйте, у меня проблема с запуском modelsim. я создаю 16-разрядный калькулятор, который может работать с вычислением сложения, вычитания, кратности, деления. вход и выход-это 20-битный bcd-код. Для расчета сначала я преобразую входной bcd-код в двоичный. После двоичного вычисления я преобразую двоичный код в код bcd. я не должен использовать *’, ‘/’, ‘%’, ‘lt;lt;’, ‘gt;lt;’, ‘gt;gt;’, ‘lt;’, ‘gt;gt;lt;lt;lt;’, и ‘gt;lt;’, и ‘gt;gt;lt;’, и ‘gt;gt;gt;’ в коде 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_1lt;=20'b0; in_2lt;=20'b0; outlt;=20'b0; end else if (result==1) begin if (in_set==1'b0) begin in_1[3:0]lt;=a; in_1[7:4]lt;=in_1[3:0]; in_1[11:8]lt;=in_1[7:4]; in_1[15:12]lt;=in_1[11:8]; in_1[19:16]lt;=in_1[15:12]; end else if (in_set==1'b1) begin in_2[3:0]lt;=a; in_2[7:4]lt;=in_2[3:0]; in_2[11:8]lt;=in_2[7:4]; in_2[15:12]lt;=in_2[11:8]; in_2[19:16]lt;=in_2[15:12]; end end else begin in_1lt;=in_1; in_2lt;=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 gt; 16'd32768) ovlt;=1'b1; else ovlt;=1'b0; end always @ (posedge clk, posedge result) begin if (result==1) begin case ({selectmode,in_set}) 3'b000 : outlt;=in_1; //first input 3'b001 : outlt;=in_2; //second input 3'b010 : outlt;=m1; //add 3'b011 : outlt;=m1; //sub 3'b100 : outlt;=m2; //multiple 3'b101 : outlt;=m3; //divide 3'b110 : outlt;=20'b0; //null 3'b111 : outlt;=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 cal3lt;=16'b0; if (mode==3'b010) cal3lt;=cal1 cal2; else if (mode==3'b011) cal3lt;=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 cal3lt;=0; end else begin for (i=0;ilt;cal2;i=i 1) begin cal3lt;=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_1lt;=8'b0; remainlt;=cal1; for (i=0;ilt;2000;i=i 1) begin if (cal1gt;cal2_1) begin remainlt;=remain-cal2_1; cal3_1=cal3_1 1'b1; end else begin cal3_1lt;=8'b0; remainlt;=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]lt;4'b1010) begin if (bcd[19:4]==16'b0) binlt;=bcd[3:0]; else if (bcd[19:8]==12'b0) begin for (i=0;ilt;bcd[7:4];i=i 1) begin io=io 16'd10; end binlt;=io bcd[3:0]; end else if (bcd[19:12]==8'b0) begin for (i=0;ilt;bcd[7:4];i=i 1) begin io=io 4'd10; end for (i1=0;i1lt;bcd[11:8];i1=i1 1) begin i1o=i1o 16'd100; end binlt;=i1o io bcd[3:0]; end else if (bcd[19:16]==4'b0) begin for (i=0;ilt;bcd[7:4];i=i 1) begin io=io 16'd10; end for (i1=0;i1lt;bcd[11:8];i1=i1 1) begin i1o=i1o 16'd100; end for (i2=0;i2lt;bcd[15:12];i2=i2 1) begin i2o=i2o 16'd1000; end binlt;=i2o i1o io bcd[3:0]; end else begin for (i=0;ilt;bcd[7:4];i=i 1) begin io=io 16'd10; end for (i1=0;i1lt;bcd[11:8];i1=i1 1) begin i1o=i1o 16'd100; end for (i2=0;i2lt;bcd[15:12];i2=i2 1) begin i2o=i2o 16'd1000; end for (i3=0;i3lt;bcd[19:16];i3=i3 1) begin i3o=i3o 16'd10000; end binlt;=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 lt; 8; i = i 1) begin {bcd_h,bcd_t,bcd_o} = {bcd_h[2:0],bcd_t,bcd_o ,bin[7-i]}; if(i lt; 7 amp;amp; bcd_o gt; 4) bcd_o = bcd_o 3; if(i lt; 7 amp;amp; bcd_t gt; 4) bcd_t = bcd_t 3; if(i lt; 7 amp;amp; bcd_h gt; 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 lt; 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 lt; 7 amp;amp; bcd_o gt; 4) bcd_o = bcd_o 3; if(i lt; 7 amp;amp; bcd_t gt; 4) bcd_t = bcd_t 3; if(i lt; 7 amp;amp; bcd_h gt; 4) bcd_h = bcd_h 3; if(i lt; 7 amp;amp; bcd_th gt; 4) bcd_th = bcd_th 3; if(i lt; 7 amp;amp; bcd_tt gt; 4) bcd_tt = bcd_tt 3; end end endmodule
а ниже приведен код испытательного стенда » шкала времени 1нс/1пс
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 clklt;=1'b0; #1 clk=~clk; end initial begin rstlt;=1'b0; #5 rst=~rst; end initial begin {selectmode,in_set}lt;=3'b000; #30 {selectmode,in_set}lt;=3'b001; #60 {selectmode,in_set}lt;=3'b010; #100 {selectmode,in_set}lt;=3'b011; end initial begin resultlt;=1'b1; #27 resultlt;=1'b0; #29 resultlt;=1'b1; #56 result=1'b0; #105 result=1'b1; end initial begin alt;=4'b0; #15 alt;=4'b0010; #21 alt;=4'b0001; #34 alt;=4'b0111; end endmodule
у компиляции нет проблем…и у другого тестового стенда тоже нет проблем…в течение 2 недель я ничего не могу сделать, пожалуйста, помогите мне, умные ребята……
Ответ №1:
Я не полностью отладил ваш код, но вот некоторые проблемы, которые я заметил:
В calculator_p
списке удалить negedge result
и posedge result
из списков чувствительности. Наличие их в списке чувствительности и ссылка на них в блоке сообщают синтезатору, что они являются асинхронными сигналами.
Возможно, вам также потребуется удалить его rst
из списка чувствительности. FGPA обычно имеют ограниченную поддержку асинхронного сброса. Вы можете поддерживать его, а можете и не поддерживать, или может быть только несколько триггеров с асинхронным сбросом. Удаление его из списка чувствительности.
mp
Модуль неправильно используется при неблокирующем назначении, и цикл for не может статически развернуться. Предполагаемый эквивалентный код был бы таким, как показано ниже (64-килобайтные циклы большие и медленные; возможно, потребуется переосмысление). Аналогичная проблема существует и в bcd2bin
.
always @* begin cal3 = 0; for (i=1;ilt;(2lt;lt;16);i=i 1) begin if (ilt;cal2) begin cal3 = cal3 cal1; end end end
В общем случае комбинационные блоки должны использовать блокирующие назначения, синхронные блоки должны использовать неблокирующие назначения.