系统 Verilog 循环

System Verilog Loops

我目前正在研究 System Verilog 中的 Shift-Add 算法(32x32 位乘法)。 System Verilog 找不到任何错误,根据 GTKwave,我的代码工作正常。当我用 yosys 综合我的电路时,会添加锁存器。这就是问题所在。我不想在我的电路中使用闩锁。这是我的代码:

module multiplier(
  input logic         clk_i,
  input logic         rst_i,
  input logic         start_i,
  input logic [31:0]  a_i,
  input logic [31:0]  b_i,
  output logic        finished_o,
  output logic [63:0] result_o
);

typedef enum logic [1:0] { STATE_A, STATE_B} state_t;
  state_t state_p, state_n;
logic [63:0] fin_res;
logic [63:0] tmp;
logic rst_flag;
integer i;


always @(posedge clk_i or posedge rst_i) begin
  if (rst_i == 1'b1) begin
    state_p <= STATE_B;
  end
  else begin
    state_p <= state_n;
  end
end


always @(*)begin
  state_n = state_p;
  case (state_p)
    STATE_A: if (start_i == 0) state_n = STATE_B;
    STATE_B: if (start_i == 1) state_n = STATE_A;
    default: state_n = state_p;
  endcase
end


always @(*) begin
  case (state_p)
    STATE_A: begin
      rst_flag = 1;
      fin_res = 0;
      finished_o = 0;
      tmp = 0;
      for (i = 0; i < 32; i = i + 1) begin
        if (a_i[i] == 1'b1) begin
          tmp = b_i;
          tmp = tmp << i;
          fin_res = fin_res + tmp;
        end
      end
    end
    STATE_B: begin 
      result_o = fin_res;
      if (rst_flag == 1) finished_o = 1;
      if (start_i == 1) finished_o = 0;
    end
    default: begin
        finished_o = 0;
        result_o = 0;
    end
  endcase
end
endmodule

在调试了 2 天之后,没有发现任何错误,我想问一下你是否可以帮助我。我正在分配每个输出(至少我是这么认为的)。那么我的错误在哪里?是for循环吗?但是这样做有什么问题呢?预先感谢您的帮助:)

代码片段的一些有用信息:start_i 是起始信号。如果将其设置为 1,则应开始乘法。 finished_o 是完成标志。如果将其设置为 1,CPU 将知道计算已完成。 a_i 和 b_i 是应该相乘的输入。 result_o是乘法的结果,当finished_o设置为1时可以读取。

根据 yosys,我得到以下锁存器:

64 DLATCH_N

64 DLATCH_P

我认为 for 循环中的 fin_res 可能有问题,因为逻辑变量和锁存器

一样长正好是 64 位

根据评论,您有一堆变量未在第二个 case 语句中分配,导致综合生成锁存器。为避免这种情况,您需要递归地分配 case 语句和条件语句的所有分支中的所有变量。

但是,如果有一个默认值可以分配给它们,您可以使用类似于第二个 always 块中的模式,只需在 'case' 语句之前分配默认值。这样你甚至不需要 default 子句,你也可以在第二个 always 块中去掉它。

always @(*) begin
  // set default values
  rst_flag = 0;
  fin_res = 0;
  finished_o = 0;
  tmp = 0;
  result_o = 0;

  case (state_p)
    STATE_A: begin
       rst_flag = 1;

      for (i = 0; i < 32; i = i + 1) begin
        if (a_i[i] == 1'b1) begin
          tmp = b_i;
          tmp = tmp << i;
          fin_res = fin_res + tmp;
        end
      end
    end
    STATE_B: begin 
      result_o = fin_res;

      // are you sure that you do not need a latch here?
      if (rst_flag == 1) finished_o = 1;
      if (start_i == 1) finished_o = 0;
    end
    // you do not need 'default' here.
  endcase
end

我的修复会导致组合行为,并且应该在综合中消除闩锁,但看起来它们的行为并不像您预期​​的那样。看起来你真的需要一个闩锁

  1. rst_flag 必须是闩锁。您在 STATE_A 中设置它并在 STATE_B 中使用它。它必须保持状态之间的价值。这是闩锁行为。

  2. 在 STATE_B 中,仅当满足某些条件时才更改 finished_o。如果 rst_flagstart_i 都为 0,会发生什么情况。您希望 finished_o 为 0还是以前的价值?在后一种情况下,您需要一个闩锁。

  3. fin_res怎么样?你想在其他州用它做什么?保留先前的值(锁存器)或具有默认值(无锁存器)。

...