首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >系统Verilog环

系统Verilog环
EN

Stack Overflow用户
提问于 2020-11-12 19:22:59
回答 1查看 308关注 0票数 1

我目前正在系统Verilog中研究Shift-Add算法(32x32位乘法)。System找不到任何错误,我的代码按照GTKwave正确工作。当我用yosys合成我的电路时,会增加锁存器。这就是问题所在。我不想把锁锁在我的电路里。这是我的密码:

代码语言:javascript
复制
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

经过两天的调试,没有发现任何错误,我想问你是否可以帮助我。我正在分配每个输出(至少我认为是这样)。那我的错误在哪里?是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位。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-13 00:35:49

在注释中,有许多变量没有在第二个case语句中赋值,从而导致合成生成闩锁。为了避免这种情况,您需要递归地分配case语句和条件语句的所有分支中的所有var。

但是,如果有一个默认值可以分配给所有这些值,则可以使用与第二个始终块中的模式类似的模式,只需在'case‘语句之前分配默认值。这样,您甚至不需要默认子句,并且可以在第二个始终块中消除它。

代码语言:javascript
复制
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中使用它,它必须保持状态之间的值。这是锁存行为。

  1. In STATE_B您只有在满足某些条件的情况下才会更改finished_o。如果rst_flag和start_i都是0,会发生什么。您希望finished_o是0还是以前的值?在后一种情况下,您需要一个锁存器.

  1. fin_res怎么样?你想在其他州用它做什么?保留以前的值(闩锁)或有默认值(没有锁存)。

..。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64810439

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档