0

我使用状态机概念为展位乘数(基数 2)编写了一个行为程序。在使用 modelsim 进行程序模拟期间,我得到了正确的结果,但是当我将它移植到 fpga(spartan 3)时,结果并不如预期。

我哪里出错了?

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
4

3 回答 3

3

您的组合always块中有一个不完整的敏感度列表。改变:

always @(state)

至:

always @*

这可能是合成锁存器。

always在组合块中使用阻塞分配。更改<==

良好的综合和 linting 工具应该警告您这些构造。

于 2013-04-05T12:50:29.093 回答
0

如果某些东西在模拟中起作用但在现实中不起作用,请遵循以下清单:

  • 您是否已初始化每个寄存器?(是的)
  • 您是否对每个时钟后传输的一个工作变量使用 2 个寄存器(否)(用于状态 2 信号/线路,例如 state 和 state_next 并在每个时钟 state_next 后传输到 state)

第二点的一个例子在这里,你需要下一个阶段逻辑,当前状态逻辑和输出逻辑。

有关如何为 FPGA 正确编码 FSM 的更多信息,请参见此处(转到 HDL 编码技术 -> 基本 HDL 编码技术)

于 2013-04-05T12:38:52.583 回答
0

你在这里遇到了各种各样的问题。

  1. 您对第一个 always 块的敏感度列表不完整。您只是在看state,但还有许多其他信号需要在那里。如果您的工具支持它,请使用always @*,它会自动生成敏感度列表。更改此设置,您的代码将开始模拟,就像它在 FPGA 上运行一样。

    这隐藏了代码的其他问题,因为它导致信号在错误的时间更新。你已经设法让你的代码在模拟器中工作,但它是基于一个谎言。谎言是 , R_A, R_B, prev&countMul_Result依赖状态的变化,但是还有更多的信号是该逻辑的输入。

  2. 您陷入了 Verilog 关键字reg创建寄存器的陷阱。它没有。我知道这很愚蠢,但事实就是这样。这reg意味着它是一个可以从程序块分配给的变量。wires 不能分配给程序块内。

    当您在时钟程序块(见脚注)中分配某些内容时,会创建一个寄存器,例如您的state变量。R_A, R_B,prevcount所有似乎都跨周期保存值,因此需要是寄存器。我会像这样更改代码:

首先,我会创建一组next_*变量。这些将包含我们在下一个时钟每个寄存器中想要的值。

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

然后我会改变时钟进程来使用这些:

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)
   .....

然后最后更改第一个过程以分配给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
        
    .....

笔记:

  • 所有寄存器现在都有一个重置
  • 任何寄存器的next_值都默认为其先前的值。
  • next_值永远不会被读取,除了时钟进程
  • next_值永远不会被写入,除非在时钟进程中。

我还怀疑您想Mul_Result成为一个wire并拥有它,assign Mul_Result = R_B[7:0];而不是成为另一个仅在启动状态下更新的寄存器,但是我不确定您要在那里做什么。


  • 寄存器通常是 a reg,但 areg不一定是寄存器。
于 2013-04-08T14:35:29.320 回答