verilog合成中从外部源接收输入时出现多个驱动器问题

verilog合成中从外部源接收输入时出现多个驱动器问题,verilog,synthesis,greatest-common-divisor,elaboration,Verilog,Synthesis,Greatest Common Divisor,Elaboration,我试图在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_r

我试图在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
模块GCD\R(A、B、out、nrst、act、clk、fla\g);
输入[31:0]A,B;
输入时钟、act、nrst;
输出调节阀;
输出寄存器[31:0]输出;
reg[3:0]状态,下一个_状态;
reg[31:0]A_reg,B_reg,AIT_reg,Bint_reg,out_reg//2个寄存器将保留中间数字+和下一个数字
参数IDLE=3'b001;
参数ABIG=3'b010;
参数BBIG=3'b100;
reg next_标志;
始终@(*)
案件(州)
空闲:开始
$display(“开始”);
如果(act==0)开始
A_reg=A//A、 B是包含来自外部源的数字的导线
B_reg=B//首先分配给A_reg和B_reg
out_reg=31'bx;
下一个_标志=1'b0;
下一个_状态=空闲;
结束
如果(act==1)
如果(A_reg==0)开始
out_reg=B_reg;
下一个_标志=1'b1//测试台会知道我们什么时候停下来
未注册=未注册//注意不要推断锁闩
Bint_reg=B_reg;
下一个_状态=空闲;
结束
否则,如果(B_reg==0)开始
out_reg=A_reg;
下一个_标志=1'b1;
未注册=未注册//注意不要推断锁闩
Bint_reg=B_reg;
下一个_状态=空闲;
结束
否则,如果(A_reg>=B_reg)开始
out_reg=31'bx;
下一个_标志=1'b0;
未注册=未注册;
Bint_reg=B_reg;
下一个状态=ABIG;
结束
否则开始
out_reg=4'bxxx;
下一个_标志=1'b0;
未注册=未注册;
Bint_reg=B_reg;
下一个_状态=BBIG;
结束
其他的
开始
未注册=未注册;
Bint_reg=B_reg;
out_reg=4'bxxx;
下一个_标志=1'b0;
下一个_状态=4'bx;
结束
结束
阿比格:开始
如果(A_reg==0 | B_reg==0)开始
out_reg=31'bx;
下一个_标志=1'b0;
下一个_状态=空闲;
未注册=未注册;
Bint_reg=B_reg;
结束
否则如果(B_reg>A_reg)开始
out_reg=31'bx;
下一个_标志=1'b0;
下一个_状态=BBIG;
未注册=未注册;
Bint_reg=B_reg;
结束
否则开始
out_reg=31'bx;
下一个_标志=1'b0;
下一个状态=ABIG;
Aint_reg=A_reg-B_reg;
Bint_reg=B_reg;
结束
结束
开始
如果(A_reg==0 | B_reg==0)开始
out_reg=31'bx;
下一个_标志=1'b0;
下一个_状态=空闲;
未注册=未注册;
Bint_reg=B_reg;
结束
否则,如果(A_reg>B_reg)开始
out_reg=31'bx;
下一个_标志=1'b0;
下一个状态=ABIG;
未注册=未注册;
Bint_reg=B_reg;
结束
否则开始
out_reg=31'bx;
下一个_标志=1'b0;
下一个_状态=BBIG;
未注册=未注册;
Bint_reg=B_reg-A_reg;
结束
结束
默认值:开始
out_reg=31'bx;
下一个_标志=1'b0;
下一个_状态=4'bx;
未注册=未注册;
Bint_reg=B_reg;
$display(“%t:状态机未初始化/n”,$time);
结束
尾声
始终@(posedge clk或negedge nrst)
如果(~nrst)开始

state您正确地识别了代码中的主要问题是没有正确地处理寄存器和组合逻辑。每当你有一个寄存器(寄存器,而不是
reg
类型,它们是不同的,对于那些刚接触Verilog的人来说是混乱的),你都需要用一种特殊的方式来定义它,以便合成和模拟工具能够处理它。最安全的做法是在组合逻辑和顺序存储(即实际寄存器)之间创建一个干净的分离。您开始使用
Aint\u reg
Bint\u reg
out\u reg
等进行此操作;但您需要对其值来自组合块的所有注册值执行此操作。因此,所有这些想法一起产生了这样的代码结构(不完全是您的代码,而是类似的代码):

输入[31:0]A、B;
输出寄存器[31:0]输出;
reg[31:0]regA,regB;
注册[3:0]状态,下一状态;
始终@(posedge clk或negedge rst)开始
如果(~rst)开始

regA我将尝试提出一个像样的问题-不幸的是,我没有看到一个:(对不起,我似乎陷入了沉思。我想知道如何避免出现多个驱动器的问题,因为我在组合块和顺序块中都为A、B赋值。首先,你的语法是对的,我编写代码时没有使用制表符,因为我应该这样做(我在linux环境下工作,一位朋友向我推荐了一段代码,使它们像在其他windows平台上一样自动运行).关于您在case语句之前编写的代码段,有一件事我不太了解-正如我所说,A和B是用来保存外部源的值的导线,A_reg可能是“A”(B_reg也是一样)在这个段中,Aint_reg代表nextA。你的意思是我应该在开头写一个_reg=A来输入初始值吗?……这确实意味着我不需要在本例中指定一个_reg,因为它是外部的,但再次强调,因为它总是(*)条件,即使我处于计算输出的中间,它也不会总是把一个线值放进AYRG吗?@我所共享的代码段“RoalReaveVikBiiukOV”只是一个模板,并没有直接解决你的代码需要采取的形式。我已经更新了,以使它更清晰;再加上一些评论,看看所有的东西都是合乎希望的。这澄清了像这样的代码应该是什么样子的一般结构,然后您可以
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