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。に変更<==ます。

優れた合成およびリンティング ツールは、これらの構造について警告するはずです。

于 2013-04-05T12:50:29.093 に答える
0

シミュレーションでは機能するが実際には機能しない場合は、次のチェックリストに従ってください。

  • すべてのレジスタを初期化しましたか? (はい)
  • 各クロックの後に転送する 1 つの作業変数に 2 つのレジスタを使用しますか (いいえ) (ステート 2 信号/ワイヤに使用します。たとえば、state と state_next を使用し、各クロックの後に state_next を state に転送します)。

2 番目のポイントの例はこちらです。次のステージ ロジック、現在の状態ロジック、および出力ロジックが必要です。

FPGA 用に FSM を適切にコーディングする方法の詳細については、こちらを参照してください([HDL コーディング テクニック] -> [基本的な HDL コーディング テクニック] に移動します) 。

于 2013-04-05T12:38:52.583 に答える
0

ここにはさまざまな問題があります。

  1. 最初の always ブロックの秘密度リストは不完全です。あなたが見ているのは だけですがstate、他にも必要な信号がたくさんあります。ツールでサポートされている場合はalways @*、機密リストを自動的に生成する を使用してください。これを変更すると、コードが FPGA で実行されているかのようにシミュレーションを開始します。

    これにより、信号が間違ったタイミングで更新されるため、コードの他の問題が隠されています。コードをシミュレーターで動作させることができましたが、それは嘘に基づいています。嘘はR_AR_Bprevcount&Mul_Resultが状態の変化にのみ依存しているということですが、そのロジックへの入力であるより多くの信号があります。

  2. regVerilog キーワードがレジスタを作成するという罠に陥っています。そうではありません。ばかげていることはわかっていますが、それがその方法です。regつまり、手続き型ブロックから代入できる変数です。wire手続き型ブロック内で を割り当てることはできません。

    レジスターは、変数のようにクロック処理された手続き型ブロック (脚注を参照) 内で何かを割り当てると作成されますstateR_AR_Bprevおよびcountすべてがサイクル間で値を保持しているように見えるため、レジスターである必要があります。次のようにコードを変更します。

まず、一連の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ではないかと思いますが、そこで何をしようとしているのかわかりません。wireassign Mul_Result = R_B[7:0];


  • レジスタは通常 aregですが、 aはレジスタであるreg必要はありません。
于 2013-04-08T14:35:29.320 に答える