systemverilog 中波浪中的危害

问题描述

在使用 FSM 和 32x32 乘法器执行指数运算 (a^b) 的模块上运行测试平台时 我在 FSM 输出(update_counter、busy、update_prod)的波中遇到了一个奇怪的危险。

为什么会发生危险?

乘法器的模块经过测试,工作正常,危害与FSM密切相关 危害:

enter image description here

代码

// Power Module
module power (
    input logic clk,// Clock
    input logic reset,// Reset
    input logic start,// Start signal
    input logic[3:0] a,// Input 
    input logic[2:0] b,// Input 
    output logic busy,// Power busy indication
    output logic[63:0] result     // Result
 );

// This module is calculating Result = a^b. 

// Local Variables. 
// Counter for Number of mult operations left. 
logic[4:0] counter;   
// Signals for mult.
logic mul_start,mul_busy,counter_clear,update_prod,clr_prod,counter_done,update_counter; 
// States for the FSM.
logic [1:0] cur_state,next_state;
// Inputs for the mult.
logic[31:0] b_input,a_input,product;
// Registers for the mult output.
logic[63:0]   mul_prod; 

// We want to assign the leg b of the mult 
// the input a as constant via b_input.
// Put your code here.
// ------------------
always_comb begin
    product=result;
    b_input=b;
    a_input=a;
end

// End of your code.

//Next,Declare the mult module we are going to use. 
// Put your code here.
// ------------------


mult32x32_fast mult(
    .busy(mul_busy),.product(mul_prod),.clk(clk),.reset(reset),.start(mul_start),.a(a_input),.b(product)
    );
    // End of your code.
    
    
    
// Initiating FFs Complete: 
always_ff @(posedge clk,posedge reset) begin
    if ( reset == 1'b1 ) begin
        cur_state<=2'b00;
    end
    else begin 
        cur_state<=next_state;
    end
    if (reset == 1'b1) begin
        counter <= 4'b00;
    end
    else begin 
        if (counter_clear == 1'b1) begin
            counter <= 4'b00;
        end
        else if ((counter < b_input - 1)&&update_counter==1'b1) begin
            counter <= counter + 1;
        end
    end
    if(reset==1'b1) begin
    result<=a_input;
    end
    else begin
        if(clr_prod==1'b1)begin
            result<=a;
        end
        else if(update_prod==1'b1)begin
            result<=mul_prod;
        end
        else begin
            result<=result;
        end
    end
end 
always_comb begin
    if (counter == b_input - 1) begin
        counter_done = 1'b1;
    end
    else begin
        counter_done = 1'b0;
    end

end

// Manage FSM Logic.
// We are going to use an FSM in order to manage 
// the multiplications. 
always_comb begin
    next_state=cur_state;
    mul_start=1'b0;
    counter_clear=1'b0;
    update_prod=1'b0;
    clr_prod=1'b0;
    busy=1'b0;
    update_counter=1'b0;
    case (cur_state) 
        2'b00: begin
            // Idle state - Waiting on 'start' signal.
            // Put your code here.
            // ------------------
            if(start==1'b0) begin
                next_state=2'b00;

            end
            else begin
                next_state=2'b01;
                clr_prod=1'b1;
                counter_clear=1'b1;
            end

            // End of your code.
        end
    
        2'b01: begin
            // Initiating state - Updating input for the mult 
            // and starting its operation.
            // Put your code here.
            // ------------------
            if(counter_done==1'b1)begin
                next_state=2'b00;
            end
            else begin
                next_state=2'b10;
                mul_start=1'b1;
                busy=1'b1;
            end
        
            // End of your code.
        end
        
        2'b10: begin
            // Waiting state - Waiting for the mult to finish 
            // How can you indicate?
            // Put your code here.
            // ------------------
            if(mul_busy==1'b1)begin
                next_state=2'b10;
                busy=1'b1;
            end
            else begin
                next_state=2'b01;
                update_prod=1'b1;
                update_counter=1'b1;
                busy=1'b1;
            end
        
            // End of your code.
        end            
    endcase
end
endmodule

测试平台:

// testbench for the power module
module power_tb;

logic clk;            // Clock
logic reset;          // Reset
logic start;          // Start signal
logic [3:0] a;        // Input a
logic [2:0] b;        // Input b
logic busy;           // Multiplier busy indication
logic [63:0] result;  // Miltiplication product


/* Check the hardware you wrote with the two cases you chose.*/
// Put your code here
// ------------------
power uut(
.busy(busy),.result(result),.start(start),.a(a),.b(b)
);

initial begin
    clk=1'b1;
end
always begin
    #1 clk=~clk;
end

initial begin
    reset=1'b0;
    @(posedge clk);
    reset=1'b1;
    start=1'b0;
    a=0;
    b=0;
    repeat (4) begin
        @(posedge clk);
    end
    reset=1'b0;
    @(posedge clk);
    start=1'b1;
    a={1'b0,1'b0,1'b1,1'b0};
    b={1'b1,1'b0};
    @(posedge clk);
    start=1'b0;
    @(negedge busy);
    @(posedge clk);
    start=1'b1;
    a={1'b1,1'b0};
    b={1'b0,1'b1};
    @(posedge clk);
    start=1'b0;
    @(negedge busy);
end
// End of your code

endmodule

解决方法

您需要在测试平台中使用非阻塞赋值,或者将您的输入从 posedge clk 中移除。这将消除您的故障。

initial begin
    reset=1'b0;
    @(negedge clk); //move away from posedge
    reset=1'b1;
    start=1'b0;
    a=0;
    b=0;
    repeat (4) @(posedge clk);
    reset <=1'b0; // no longer a race
    @(posedge clk);
    start<=1'b1; 
    a<={1'b0,1'b0,1'b1,1'b0};
    b<={1'b1,1'b0};
    ...