在Verilog中使用重复加法进行乘法

时间:2018-06-23 10:34:04

标签: verilog hdl

代码已正确合成,但是当我尝试对其进行仿真时,只有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

1 个答案:

答案 0 :(得分: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