简体   繁体   English

我的 Verilog 行为代码得到正确模拟,但在 FPGA 上没有按预期工作

[英]My Verilog behavioral code getting simulated properly but not working as expected on FPGA

I wrote a behavioral program for booth multiplier(radix 2) using state machine concept.我使用状态机概念为展位乘数(基数 2)编写了一个行为程序。 I am getting the the results properly during the program simulation using modelsim, but when I port it to fpga (spartan 3) the results are not as expected.我在使用modelsim的程序模拟过程中得到了正确的结果,但是当我将它移植到fpga(spartan 3)时,结果并不如预期。

Where have I gone wrong?我哪里错了?

module booth_using_statemachine(Mul_A,Mul_B,Mul_Result,clk,reset);

input Mul_A,Mul_B,clk,reset;
output Mul_Result;
wire [7:0] Mul_A,Mul_B;
reg [7:0] Mul_Result;


reg [15:0] R_B;
reg [7:0] R_A;
reg prev;
reg [1:0] state;
reg [3:0] count;

parameter start=1 ,add=2 ,shift=3;
always @(state)
begin

case(state)
 
  start:
   begin
      R_A   <= Mul_A;
      R_B   <= {8'b00000000,Mul_B};
      prev  <= 1'b0;
      count <= 3'b000;
      Mul_Result <= R_B[7:0];
     end
     
   add:
   begin
    
     case({R_B[0],prev})
            
         2'b00:
           begin
             prev <= 1'b0;
            end
         
         2'b01:
           begin
             R_B[15:8] <= R_B[15:8] + R_A;
         prev      <= 1'b0;
            end
         
         2'b10:
         begin
              R_B[15:8] <= R_B[15:8] - R_A;
              prev      <= 1'b1;
             end
         
         2'b11:
            begin
              prev <=1'b1;
             end
        
        endcase
        
    end
  
  shift:
   begin
     R_B  <= {R_B[15],R_B[15:1]};
     count <= count + 1;
    end
    
endcase
    
     
end  
     

  always @(posedge clk or posedge reset)
  begin
 
   if(reset==1)
      state <= start;
    
    else
      begin
       
        case(state)
           
            start:
              state <= add;
            
            add:
              state <= shift;
              
            
            shift:
              begin
                
                 if(count>7)
                  state <= start;
            
            else
              state <=add;
           
                end
                            
    
        
     endcase
  end
  end   
 endmodule

You have an incomplete sensitivity list in your combinational always block.您的组合always阻止中的敏感度列表不完整。 Change:改变:

always @(state)

to:到:

always @*

This may be synthesizing latches.这可能是合成锁存器。

Use blocking assignments in your combinational always block.在你的组合always阻塞中使用阻塞赋值。 Change <= to = .<=更改为=

Good synthesis and linting tools should warn you about these constructs.好的综合和 linting 工具应该会警告您这些构造。

Follow the following checklist if something does work in the simulation but not in reality:如果某些内容在模拟中有效但在现实中无效,请遵循以下清单:

  • Did you have initialized every register?您是否已初始化每个寄存器? (yes) (是的)
  • Do you use 2 registers for one working variable that you transfer after each clock (no) (use for state 2 signals/wires, for example state and state_next and transfer after each clock state_next to state)您是否将 2 个寄存器用于每个时钟后传输的一个工作变量(否)(用于状态 2 信号/线,例如 state 和 state_next 并在每个时钟 state_next 后传输到 state)

A Example for the second point is here , you need the next stage logic, the current state logic and the output logic.第二点的一个例子在这里,你需要下一级逻辑,当前状态逻辑和输出逻辑。

For more informations about how to proper code a FSM for an FPGA see here (go to HDL Coding Techniques -> Basic HDL Coding Techniques)有关如何为 FPGA 正确编码 FSM 的更多信息,请参见此处(转到 HDL 编码技术 -> 基本 HDL 编码技术)

You've got various problems here.你在这里有各种各样的问题。

  1. Your sensitivity list for the first always block is incomplete.您的第一个 always 块的敏感度列表不完整。 You're only looking at state , but there's numerous other signals which need to be in there.您只查看state ,但还有许多其他信号需要在那里。 If your tools support it, use always @* , which automatically generates the sensitivity list.如果您的工具支持它,请always @*使用always @* ,它会自动生成敏感度列表。 Change this and your code will start to simulate like it's running on the FPGA.更改此设置,您的代码将开始模拟,就像在 FPGA 上运行一样。

    This is hiding the other problems with the code because it's causing signals to update at the wrong time.这隐藏了代码的其他问题,因为它会导致信号在错误的时间更新。 You've managed to get your code to work in the simulator, but it's based on a lie.您已经设法让您的代码在模拟器中运行,但这是基于谎言。 The lie is that R_A , R_B , prev , count & Mul_Result are only dependent on changes in state, but there's more signals which are inputs to that logic.谎言是R_AR_BprevcountMul_Result依赖于状态的变化,但有更多的信号是该逻辑的输入。

  2. You've fallen into the trap that the Verilog keyword reg creates registers.您已经陷入了 Verilog 关键字reg创建寄存器的陷阱。 It doesn't.它没有。 I know it's silly, but that's the way it is.我知道这很愚蠢,但事情就是这样。 What reg means is that it's a variable that can be assigned to from a procedural block. reg意思是它是一个可以从程序块分配的变量。 wire s can't be assigned to inside a procedural block.不能将wire s 分配给程序块内部。

    A register is created when you assign something within a clocked procedural block (see footnote), like your state variable.当您在时钟程序块(参见脚注)中分配某些内容时,会创建一个寄存器,例如您的state变量。 R_A , R_B , prev and count all appear to be holding values across cycles, so need to be registers. R_AR_Bprevcount似乎都跨周期保存值,因此需要是寄存器。 I'd change the code like this:我会像这样更改代码:

First I'd create a set of next_* variables.首先,我会创建一组next_*变量。 These will contain the value we want in each register next clock.这些将包含我们在每个寄存器下一个时钟中想要的值。

reg [15:0] next_R_B;
reg [7:0]  next_R_A;
reg        next_prev;
reg [3:0]  next_count;

Then I'd change the clocked process to use these:然后我会更改时钟过程以使用这些:

always @(posedge clk or posedge reset) begin

 if(reset==1) begin
   state <= start;
   R_A   <= '0;
   R_B   <= '0;
   prev  <= '0;
   count <= '0;
 
 end else begin
   R_A   <= next_R_A;
   R_B   <= next_R_B;
   prev  <= next_prev;
   count <= next_count;

   case (state)
   .....

Then finally change the first process to assign to the next_* variables:然后最后将第一个进程更改为分配给next_*变量:

always @* begin
  next_R_A   <= R_A;
  next_R_B   <= R_B;
  next_prev  <= prev;
  next_count <= count;

  case(state)
    
    start: begin
      next_R_A   <= Mul_A;
      next_R_B   <= {8'b00000000,Mul_B};
      next_prev  <= 1'b0;
      next_count <= 3'b000;
      Mul_Result <= R_B[7:0];
    end

    add: begin

      case({R_B[0],prev})
        2'b00: begin
          next_prev <= 1'b0;
        end
        
    .....

Note:笔记:

  • All registers now have a reset所有寄存器现在都有一个复位
  • The next_ value for any register defaults to it's previous value.任何寄存器的next_值默认为其前一个值。
  • next_ values are never read, except for the clocked process next_值永远不会被读取,除了时钟进程
  • non- next_ values are never written, except in the clocked process.next_值永远不会被写入,除非在时钟过程中。

I also suspect you want Mul_Result to be a wire and have it assign Mul_Result = R_B[7:0];我还怀疑您希望Mul_Result成为一条wire并让它assign Mul_Result = R_B[7:0]; rather than it being another register that's only updated in the start state, but I'm not sure what you're going for there.而不是仅在开始状态更新的另一个寄存器,但我不确定您要在那里做什么。


  • A register is normally a reg , but a reg doesn't have to be a register.寄存器通常是reg ,但reg不一定是寄存器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM