问题描述
在使用 FSM 和 32x32 乘法器执行指数运算 (a^b) 的模块上运行测试平台时 我在 FSM 输出(update_counter、busy、update_prod)的波中遇到了一个奇怪的危险。
为什么会发生危险?
乘法器的模块经过测试,工作正常,危害与FSM密切相关 危害:
代码:
// 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};
...