0

我正在尝试进行的合成是在 GCD 算法有限状态机上进行的,该算法使用“如果更大则减去”方法工作。我将附上代码并尝试制定一个体面的问题。

module GCD_R (A,B,out,nrst,act,clk,fla_g);
  input [31:0] A, B;
  input clk, act, nrst;
  output reg fla_g;     
  output reg [31:0] out;
  reg [3:0] state, next_state;
  reg [31:0] A_reg, B_reg, Aint_reg, Bint_reg, out_reg;//2 registers will keep intermediate numbers+out, and next numbers
  parameter IDLE = 3'b001;
  parameter ABIG = 3'b010;
  parameter BBIG = 3'b100;
  reg next_flag;


  always @(*)   
    case (state)
      IDLE: begin
        $display("start");
        if(act == 0) begin
          A_reg = A; //A,B are wires that contain numbers from an external source
          B_reg = B; //first assign to A_reg and B_reg
          out_reg = 31'bx;
          next_flag = 1'b0;
          next_state = IDLE;
        end
        if(act == 1)
          if(A_reg==0) begin
            out_reg = B_reg;
            next_flag = 1'b1; //testbench will know when we stopped 
            Aint_reg = A_reg; //taking care not to infer latches
            Bint_reg = B_reg; 
            next_state = IDLE;
          end
          else if (B_reg==0) begin  
            out_reg = A_reg;
            next_flag = 1'b1;
            Aint_reg = A_reg; //taking care not to infer latches
            Bint_reg = B_reg;
            next_state = IDLE;
          end                       
          else if (A_reg >= B_reg) begin
            out_reg = 31'bx;
            next_flag = 1'b0;
            Aint_reg = A_reg;
            Bint_reg = B_reg;
            next_state = ABIG;
          end
          else begin
            out_reg = 4'bxxx;
            next_flag = 1'b0;
            Aint_reg = A_reg;
            Bint_reg = B_reg;
            next_state = BBIG;
         end
       else
        begin
         Aint_reg = A_reg;
         Bint_reg = B_reg;
         out_reg = 4'bxxx;
         next_flag = 1'b0;  
         next_state = 4'bx;
        end
     end

     ABIG: begin
       if (A_reg==0 | B_reg==0) begin
         out_reg = 31'bx;
         next_flag = 1'b0;
         next_state = IDLE;
         Aint_reg = A_reg;
         Bint_reg = B_reg;
       end
       else if (B_reg > A_reg) begin
         out_reg = 31'bx;
         next_flag = 1'b0;
         next_state = BBIG;
         Aint_reg = A_reg;
         Bint_reg = B_reg;
       end
       else begin
         out_reg = 31'bx;
         next_flag = 1'b0;
         next_state = ABIG; 
         Aint_reg = A_reg - B_reg;
         Bint_reg = B_reg;
       end
     end

     BBIG: begin 
       if (A_reg==0 | B_reg==0) begin
         out_reg = 31'bx;
         next_flag = 1'b0;
         next_state = IDLE;
         Aint_reg = A_reg;
         Bint_reg = B_reg;
       end 
       else if (A_reg > B_reg) begin 
         out_reg = 31'bx;
         next_flag = 1'b0;
         next_state = ABIG;
         Aint_reg = A_reg;
         Bint_reg = B_reg;
       end
       else begin 
         out_reg = 31'bx;
         next_flag = 1'b0;
         next_state = BBIG; 
         Aint_reg = A_reg;
         Bint_reg = B_reg - A_reg;
       end  
     end

     default: begin
       out_reg = 31'bx;
       next_flag = 1'b0;
       next_state = 4'bx;
       Aint_reg = A_reg;
       Bint_reg = B_reg;
       $display("%t: State machine not initialized/n",$time);
     end
   endcase

 always @(posedge clk or negedge nrst)
   if (~nrst) begin
     state <=  IDLE;//we get the new values by resetting first
     out <= 4'bx;//we don't want anything there at the reset
     fla_g <= 1'b0;
   end
   else begin
     state <=  next_state;//otherwise, get the next state and the next registers to the intermediate ones
     A_reg <=  Aint_reg;// 2nd assign to A_reg and B_reg- that's the problem
     B_reg <=  Bint_reg;
     out <=  out_reg;
     fla_g <= next_flag;
   end

endmodule

首先,A 和 B 是电线,它们将通过外部源(测试台中的一些文本文件)接收要比较的数字列表。

A_reg 和 B_reg 是中间寄存器,用于保存我们正在检查“if”语句的数字,

Aint_reg 和 Bint_reg 是寄存器,在操作后保留寄存器的中间值,仅在时钟上升时将它们发送回 A_reg 和 B_reg,

act 决定机器是否处于“开启”模式并可以执行算法

nrst 是负复位切换

问题是如何形成的:

你可以看到,一开始,有一个if(act == 0)条件。它被放在那里是为了确保 A、B 线上的值(从外部接收)将进入那里的寄存器,而不是在我们处于这种if(~nrst)情况时将它们输入到顺序块中,因为在重置。

这将我们带到了当前的问题——我知道在顺序块和组合块中为 A 和 B 赋值是造成问题的原因,但我找不到替代方案。

ps 我正在使用的事实A_reg = A创建了闩锁,因为我没有分配给A_reg其他任何地方,这是另一个问题,因为写
Aint_reg = A_reg; A_reg = Aint_reg;
来满足闩锁并不适合我。

ps2。我尝试在网站上查看类似的问题,但由于我对该主题缺乏足够的知识,我无法将我的问题与那里的问题联系起来

我很乐意得到任何帮助,谢谢

编辑:我删除了 if(~nrst) 顺序块中的非阻塞分配,以免在A_reg <= 0那里和A_reg = A组合块中进行多重分配,但是多重分配问题仍然以某种方式对其进行了错误处理

EDIT2:似乎我忘记了一个基本的事情 - 不要在两个不同的“总是”块中分配给同一个变量,但我只是想不出一个足够好的解决方案来将电线 A,B 分配给寄存器而不是在顺序块中再次分配给它

4

1 回答 1

1

您正确地确定了代码中的主要问题是您没有正确处理寄存器和组合逻辑。每当您有一个寄存器(寄存器,而不是reg类型,它们是不一样的,并且对于那些刚接触 Verilog 的人来说会感到困惑)时,您需要以特定的方式定义它,以便综合和仿真工具可以处理它。最安全的做法是在组合逻辑和顺序存储(即实际寄存器)之间建立清晰的分离。您开始使用Aint_reg, Bint_reg,out_reg等来执行此操作;但是您需要对所有值来自组合块的注册值执行此操作。所以,所有这些想法一起产生了一个这样的代码结构(不完全是你的代码,而是类似的东西):

input [31:0] A, B;
output reg [31:0] out;

reg [31:0] regA, regB;
reg [3:0] state, nextState;

always @(posedge clk or negedge rst) begin
  if (~rst) begin
    regA <= '0;
    regB <= '0;
    state <= IDLE;
  end
  else begin
    regA <= nextA;
    regB <= nextB;
    state <= nextState;
  end
end

always @(*) begin
  // Default; I always do this here to ensure there are no cases in which I dont assign a combinational value for this block
  // it always helps me keep track of which variables are assigned in which block
  nextA = regA;
  nextB = regB;
  nextState = state;

  out = '0;

  case (state)
    // In here is your case body, where you can reassign nextA, nextB, nextState and out
    // where the assignments are only dependent on A, B, regA, regB and state (ie, the values NOT assigned in this block)  
  endcase
end

考虑到这一点,您只需要在组合块中包含Aint_reg,Bint_reg等;所以你不需要在组合块中分配A_reg,Breg等。另请注意,如果这意味着输出的时间将被延迟,因此如果您需要立即从组合块中推出一个值,您可以随时绕过寄存器。据我了解,您可能会在重置期间遇到加载问题,这是可以理解的,只要nrst断言 reset ( )(即 0),就不会加载任何内容。这是重置的全部要点,将系统保持在已知状态直到它被解除。所以在nrst被取消断言之前,你的模块不应该做任何事情。其他几点:

  • 正确格式化你的代码非常重要,确保你的代码总是干净的,因为它有助于发现错误。我重新格式化了它,状态begin..end的最后一个区块似乎丢失了IDLE
  • 总是begin..end你的块,它会避免这么多的错误
  • 注意事物的大小,我看到您将变量声明为 32 位reg [31:0],但仅使用31'd31 位来分配它们。使用'0语法对任何大小进行零填充。
  • 将寄存器设置'x为并不理想,您应该让寄存器保持其状态(就像您对寄存器值和下一个寄存器值所做的那样)。

希望这可以为您澄清事情。

于 2017-12-08T00:09:45.290 回答