verilog为什么不在寄存器文件中产生正确的结果?

时间:2013-11-25 11:32:12

标签: verilog

我正在制作下面的8x32b寄存器文件是我的verilog代码

module register_file(clk, reset, dstW, valW, write, srcA, srcB, valA, valB   );
    input clk;
    input reset;
    input[2:0] dstW;
    input[31:0] valW;
    input write;
    input[2:0] srcA;
    input[2:0] srcB;
    output[31:0] valA;
    output[31:0] valB;

     reg[31:0] r0eax, r1ecx, r2edx, r3ebx, r4esi, r5edi, r6esp, r7edi;

     wire[31:0] reg_input_0, reg_input_1, reg_input_2, reg_input3, reg_input4,
        reg_input5, reg_input6, reg_input7;

     wire[7:0] decoder_out, select;

     assign valA = 
        (srcA == 3'b000) ? r0eax:
        (srcA == 3'b001) ? r1ecx:
        (srcA == 3'b010) ? r2edx:
        (srcA == 3'b011) ? r3ebx:
        (srcA == 3'b100) ? r4esi:
        (srcA == 3'b101) ? r5edi:
        (srcA == 3'b110) ? r6esp:
        (srcA == 3'b111) ? r7edi: 32'bx;

    assign valB =
        (srcB == 3'b000) ? r0eax:
        (srcB == 3'b001) ? r1ecx:
        (srcB == 3'b010) ? r2edx:
        (srcB == 3'b011) ? r3ebx:
        (srcB == 3'b100) ? r4esi:
        (srcB == 3'b101) ? r5edi:
        (srcB == 3'b110) ? r6esp:
        (srcB == 3'b111) ? r7edi: 32'bx;

        assign decoder_out[0] = (dstW == 3'b000)? 1'b1 : 1'b0;
        assign decoder_out[1] = (dstW == 3'b001)? 1'b1 : 1'b0;
        assign decoder_out[2] = (dstW == 3'b010)? 1'b1 : 1'b0;
        assign decoder_out[3] = (dstW == 3'b011)? 1'b1 : 1'b0;
        assign decoder_out[4] = (dstW == 3'b100)? 1'b1 : 1'b0;
        assign decoder_out[5] = (dstW == 3'b101)? 1'b1 : 1'b0;
        assign decoder_out[6] = (dstW == 3'b110)? 1'b1 : 1'b0;
        assign decoder_out[7] = (dstW == 3'b111)? 1'b1 : 1'b0;


        and(select[0], write, decoder_out[0]);
        and(select[1], write, decoder_out[1]);
        and(select[2], write, decoder_out[2]);
        and(select[3], write, decoder_out[3]);
        and(select[4], write, decoder_out[4]);
        and(select[5], write, decoder_out[5]);
        and(select[6], write, decoder_out[6]);
        and(select[7], write, decoder_out[7]);

        assign reg_input_0 = select[0] ? valW : r0eax;
        assign reg_input_1 = select[1] ? valW : r1ecx;
        assign reg_input_2 = select[2] ? valW : r2edx;
        assign reg_input_3 = select[3] ? valW : r3ebx;
        assign reg_input_4 = select[4] ? valW : r4esi;
        assign reg_input_5 = select[5] ? valW : r5edi;
        assign reg_input_6 = select[6] ? valW : r6esp;
        assign reg_input_7 = select[7] ? valW : r7edi;

        always @(posedge clk or negedge reset)
        begin
            if(!reset) begin
                r0eax <= 32'b0;
                r1ecx <= 32'b0;
                r2edx <= 32'b0;
                r3ebx <= 32'b0;
                r4esi <= 32'b0;
                r5edi <= 32'b0;
                r6esp <= 32'b0;
                r7edi <= 32'b0;
            end
            else begin
                r0eax <= reg_input_0;
                r1ecx <=    reg_input_1;
                r2edx <= reg_input_2;
                r3ebx <= reg_input_3;
                r4esi <= reg_input_4;
                r5edi <= reg_input_5;
                r6esp <= reg_input_6;
                r7edi <= reg_input_7;
            end
        end

    endmodule

和testbench如下

module tttt;

    // Inputs
    reg clk;
    reg reset;
    reg [2:0] dstW;
    reg [31:0] valW;
    reg write;
    reg [2:0] srcA;
    reg [2:0] srcB;

    // Outputs
    wire [31:0] valA;
    wire [31:0] valB;

    integer i;
    // Instantiate the Unit Under Test (UUT)
    register_file uut (
        .clk(clk), 
        .reset(reset), 
        .dstW(dstW), 
        .valW(valW), 
        .write(write), 
        .srcA(srcA), 
        .srcB(srcB), 
        .valA(valA), 
        .valB(valB)
    );

    initial begin
        // Initialize Inputs
            clk = 0;
        reset = 1;
        dstW = 0;
        valW = 0;
        write = 0;
        srcA = 0;
        srcB = 0;
        i =0;
        #10
        reset = 0;
        #10
        reset = 1;
        // Wait 100 ns for global reset to finish
        #100;
      clk=1;
        valW = 100;
        write = 1;
        for(i=0; i<8; i = i+1) begin
        clk =0;
        #10;
        dstW = i;
        clk = 1;
        #10;
        clk =0;
        #10;
        valW = valW + 10;
        clk =1;
        #10;
        end

        #100;
        write =0;
        for(i=0; i<8; i=i+1 ) begin
        clk = 0;
        #10;
        srcA = i;
        srcB = i;
        #10;
        clk=1;
        #10;
        end
        clk =0; 
        #10;
        clk = 1;


        // Add stimulus here

    end

endmodule

和结果

enter image description here

它只是在第三个i值之后得到0值。

我使用红色矩形检查。你能给我一个建议吗?提前谢谢

1 个答案:

答案 0 :(得分:5)

合成设计时,会出现以下警告:

WARNING:Xst:1780 - Signal <reg_input7> is never used or assigned. This unconnected signal will be trimmed during the optimization process.
WARNING:Xst:1780 - Signal <reg_input6> is never used or assigned. This unconnected signal will be trimmed during the optimization process.
WARNING:Xst:1780 - Signal <reg_input5> is never used or assigned. This unconnected signal will be trimmed during the optimization process.
WARNING:Xst:1780 - Signal <reg_input4> is never used or assigned. This unconnected signal will be trimmed during the optimization process.
WARNING:Xst:1780 - Signal <reg_input3> is never used or assigned. This unconnected signal will be trimmed during the optimization process.

如果合成器检测到这些信号未被使用,则会丢弃它们。请注意,这些信号会影响寄存器3到7的选择,因此,在读取时无法看到加载的值。

但是......你的代码分配并使用这些信号,不是吗?

    assign reg_input_0 = select[0] ? valW : r0eax;
    assign reg_input_1 = select[1] ? valW : r1ecx;
    assign reg_input_2 = select[2] ? valW : r2edx;
    assign reg_input_3 = select[3] ? valW : r3ebx;
    assign reg_input_4 = select[4] ? valW : r4esi;
    assign reg_input_5 = select[5] ? valW : r5edi;
    assign reg_input_6 = select[6] ? valW : r6esp;
    assign reg_input_7 = select[7] ? valW : r7edi;

是什么让reg_input_0,1和2与reg_input_3,4,5,6和7不同?这样:

wire[31:0] reg_input_0, reg_input_1, reg_input_2, reg_input3, reg_input4,
        reg_input5, reg_input6, reg_input7;

查看:reg_input_0reg_input_1reg_input_2。然后,reg_input3(其中是下划线?)

由于reg_input_3reg_input_7没有定义,它们默认为1位信号,而不是32位。当您使用多路复用器时,例如在reg_input_3定义其值...

 assign reg_input_3 = select[3] ? valW : r3ebx;

你实际上在合成这个:

 assign reg_input_3 = select[3] ? valW[0] : r3ebx[0];

在你的时钟总是,实际的寄存器分配不是这样的:

r3ebx <= reg_input_3;

但是就这样:

r3ebx[0] <= reg_input_3;

您对此的描述会通过上述多路复用器通过输入引起寄存器输出的反馈。虽然当时钟触发寄存器时这是可以的,但如果合成​​器没有检测到它,那么最终会产生许多不必要的多路复用器。从合成过程的结果(合成器是XST)看这个生成的原理图

Original design

右边的八个方块是你的八个寄存器。在左边,有大量的多路复用器。我无法向您展示所有这些,因为生成的原理图对于屏幕捕获来说太大了。

我建议不要使用多路复用器的显式环回路径来决定何时向寄存器写入新值。而不是那样,只有在选择了用于写入的寄存器时,修改同步始终将新值加载到寄存器中:

    always @(posedge clk or negedge reset)
    begin
        if(!reset) begin
            r0eax <= 32'b0;
            r1ecx <= 32'b0;
            r2edx <= 32'b0;
            r3ebx <= 32'b0;
            r4esi <= 32'b0;
            r5edi <= 32'b0;
            r6esp <= 32'b0;
            r7edi <= 32'b0;
        end
        else begin
            if (select[0])
              r0eax <= valW;
            if (select[1])
              r1ecx <= valW;
            if (select[2])
              r2edx <= valW;
            if (select[3])
              r3ebx <= valW;
            if (select[4])
              r4esi <= valW;
            if (select[5])
              r5edi <= valW;
            if (select[6])
              r6esp <= valW;
            if (select[7])
              r7edi <= valW;
        end
    end

此描述允许合成器推断具有CLK和CE输入的寄存器:如果CE被使能,寄存器将从其D输入接受新值。如果不是,则值不会改变。无论是否需要,您的描述都会使寄存器在每个时钟周期更改其值。

现在推断的电路是这样的(它实际上适合屏幕!): Optimized design

通过这个提出的解决方案,可以消除分配了不同reg_input_X信号的第一个块。

使用ISIM与ISE Webpack 12.4进行测试并且有效:)

chronogram of proposed solution