使用verilog中的重复添加进行乘法运算

问题描述 投票:0回答:1

代码是正确合成的,但是当我尝试模拟它时,只有lda从0变为1.其余的控制信号保持不变。 eqz信号永远不会从x变化。其余信号保持在0状态。我已经尝试了一切。任何人都可以告诉我哪里出错了?

试验台

module multiplier(input clk, start, [15:0]datain , output done);
    wire eqz, lda, ldb, ldp, clrp, decb;
    mul_datapath D(eqz, clk, lda, ldb, ldp, clrp, decb, datain);
    mul_control C(done, lda, ldb, ldp, clrp, decb, clk, start, eqz, datain);
endmodule

数据路径

module mul_datapath(eqz, clk, lda, ldb, ldp, clrp, decb, datain);
    input clk, lda, ldb, ldp, clrp, decb;
    input [15:0] datain;
    wire [15:0]x, y, z, bout;
    output eqz;
    PIPO1 P1(x, clk, lda, datain);
    PIPO2 P2(y, clk, ldp, clrp, z);
    ADD A(z, x, y);
    COUNT CNT(bout, clk, ldb, decb, datain);
    COMP com(eqz, bout);
endmodule

PIPO登记册A.

module PIPO1(x, clk, lda, datain);
    input clk, lda;
    input [15:0] datain;
    output reg [15:0] x;
    always @(posedge clk)
        if(lda) x<= datain;
endmodule

PIPO注册B.

module PIPO2(y, clk, ldp, clrp, z);
    input clk, ldp, clrp; 
    input [15:0] z;
    output reg [15:0]y;
    always @(posedge clk)
        begin
            if(clrp) y<= 16'b0;
            else if(ldp) y<= z;
        end     
endmodule

加法器单元

module ADD(z, x, y);
    input [15:0]x, y;
    output reg [15:0]z;
    always @(*)
        z = x + y;
endmodule

反减B

module COUNT(bout, clk, ldb, decb, datain);
    input clk, ldb, decb;
    input [15:0] datain;
    output reg [15:0]bout;
    always @(posedge clk)
        begin
            if(ldb) bout <= datain;
            else if(decb)
                bout <= bout -1;
        end
endmodule

比较器将B与零进行比较

module COMP(eqz, bout);
    input [15:0] bout;
    output eqz;
    assign eqz = (bout==0);
endmodule

控制路径

module mul_control(done, lda, ldb, ldp, clrp, decb, clk, start, eqz, datain);
    input clk, start, eqz;
    input[15:0] datain;
    output reg lda, ldb, ldp, clrp, decb, done; 
    reg [2:0]state;
    parameter S0=000, S1=001, S2=010, S3=011, S4=100;
    always @(posedge clk)
        begin
            case(state)
                S0 : if(start) state<= S1;  
                S1 : state<=S2;
                S2 : state<= S3;
                S3 : begin if(eqz) state<=S4; else state<=S3; end 
                S4 : state<= S4;
                default : state<= S0; 
            endcase
        end 
    always @(state)
        begin
           case(state)
               S0: begin lda = 0; ldb = 0; ldp = 0; clrp = 0; decb = 0; done = 0; end
               S1: begin lda = 1; ldb = 0; ldp = 0; clrp = 0; decb = 0; done = 0; end
               S2: begin lda = 0; ldb = 1; ldp = 0; clrp = 0; decb = 0; done = 0; end
               S3: begin lda = 0; ldb = 0; ldp = 1; clrp =0; decb = 1; done = 0; end
               S4: begin lda = 0; ldb = 0; ldp = 0; clrp = 0; decb = 0; done = 1; end
               default : begin lda = 0; ldb = 0; ldp = 0; clrp = 0; decb = 0; done = 0; end 
           endcase
        end
endmodule
verilog hdl
1个回答
0
投票

你的基本错误是乘法器和mul_control模块。

对于乘数模块,您已经错误地声明了端口。

据我了解,您的意思是将其用作测试平台。然后不需要输入或输出端口。也不需要电线声明。只是机会前两行。这应该做

module multiplier;
    reg [15:0] datain;
    reg clk, start;
    wire done;

    mul_datapath D(eqz, clk, lda, ldb, ldp, clrp, decb, datain);
    mul_control C(done, lda, ldb, ldp, clrp, decb, clk, start, eqz, datain);
endmodule

但是我建议你添加一些代码来实际为测试平台添加意义,这样你就可以测试所有的模块。

此外,您在mul_control.v中不需要datain。删除数据也需要在测试平台中调用相同的更改。此外,在mul_control.v中,您还应该添加一个条件状态更改的延迟。此外,您忘记在mul_control.v中为状态2设置clrp

所有错误中最严重的是,您保存为000,001,0010的状态参数都默认为十进制。由于您需要从0到5的5个状态,因此将二进制表示法的状态值指定为3'b000,3'b001,3'b010等。

所以现在

mul_control.v

module mul_control(done, lda, ldb, ldp, clrp, decb, clk, start, eqz);
    input clk, start, eqz;
    output reg lda, ldb, ldp, clrp, decb, done; 
    reg [2:0]state;
    parameter S0=3'b000, S1=3'b001, S2=3'b010, S3=3'b011, S4=3'b100;
    always @(posedge clk)
        begin
            case(state)
                S0 : if(start) state<= S1;  
                S1 : state<=S2;
                S2 : state<= S3;
                S3 : #2 if(eqz) state<=S4; 
                S4 : state<= S4;
                default : state<= S0; 
            endcase
        end 
    always @(state)
        begin
           case(state)
               S0: begin lda = 0; ldb = 0; ldp = 0; clrp = 0; decb = 0; done = 0; end
               S1: begin lda = 1; ldb = 0; ldp = 0; clrp = 0; decb = 0; done = 0; end
               S2: begin lda = 0; ldb = 1; ldp = 0; clrp = 1; decb = 0; done = 0; end
               S3: begin lda = 0; ldb = 0; ldp = 1; clrp =0; decb = 1; done = 0; end
               S4: begin lda = 0; ldb = 0; ldp = 0; clrp = 0; decb = 0; done = 1; end
               default : begin lda = 0; ldb = 0; ldp = 0; clrp = 0; decb = 0; done = 0; end 
           endcase
        end
endmodule

multiplier.v

module multiplier;
    reg [15:0] datain;
    reg clk, start;
    wire done;

    mul_datapath D(eqz, clk, lda, ldb, ldp, clrp, decb, datain);
    mul_control C(done, lda, ldb, ldp, clrp, decb, clk, start, eqz);


    initial
        begin
            clk = 1'b0;
            #3 start = 1'b1;
            #500 $finish;
        end

    always #5 clk = ~clk;

    initial
        begin
            #17 datain = 5;
            #10 datain = 6;

        end 
    initial
        begin
            $monitor($time, " %d %b", D.y, done);
            $dumpfile("mul.vcd"); $dumpvars(0, multiplier);

        end 
endmodule

在运行它时,我得到以下输出:

$ iverilog add.v count.v PIPO2.v mul_datapath.v COMP.v PIPO1.v mul_control.v multiplier.v
$ vvp a.out
VCD info: dumpfile mul.vcd opened for output.
                   0     x x
                   5     x 0
                  35     0 0
                  45     5 0
                  55    10 0
                  65    15 0
                  75    20 0
                  85    25 0
                  95    30 0
                  97    30 1

答案(y的值)是30,因为我们给出5和6作为数据。

在测试平台中,我还保存了一个波形转储文件名mul.vcd,它可以使用gtkwave打开,如gtkwave mul.vcd &

注意:我使用iverilog和gtkwave进行编译,运行和模拟。有关它们的更多详细信息,请访问:http://axayjha.github.io/pages/iverilog.html

© www.soinside.com 2019 - 2024. All rights reserved.