系统Verilog循环

问题描述

我目前正在研究系统Verilog中的Shift-Add算法(32x32位乘法)。根据GTKwave,系统Verilog无法找到任何错误,我的代码正在正常工作。当我用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,则应开始乘法。 finish_o是完成标志。如果将其设置为1,CPU将知道计算已完成。 a_i和b_i是应该相乘的输入。 result_o是乘法的结果,当finish_o设置为1时可以读取。

根据yosys,我得到以下闩锁:

64 DLATCH_N

64 DLATCH_P

我认为for循环中的fin_res可能出了一些问题,原因是逻辑变量与锁存器一样正好是64位长

解决方法

从注释中可以看到一堆未在第二个case语句中分配的变量,这些变量导致综合生成锁存器。为了避免这种情况,您需要递归地分配case语句和条件语句的所有分支中的所有var。

但是,如果可以为它们分配默认值,则可以使用类似于第二个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_flag start_i 都为0,会发生什么。您是否要将finish_o设为0或先前的值?在后一种情况下,您需要一个闩锁。

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

...

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...