1

私は現在、学校から入手したFPGAを使用してVerilog HDLでプロジェクトに取り組んでいます(Quartus IIバージョン10.1および11.0を実行しています(両方を試しました))。非常に奇妙なバグが発生しているので、一生理解できません。

ドットとダッシュを検出し、この入力に基づいて適切な文字をHEXディスプレイに出力するモールス信号プログラムを開発しています。HEXディスプレイは美しく機能しますが、私のUserInputモジュールはまったく何もしていないようです。

module UserInput(Clock, reset, in, out);
input Clock, reset, in;
output reg [1:0] out;

wire [2:0] PS;
reg [2:0] NS;

parameter NONE = 2'b00, DOT = 2'b01, DASH = 2'b11; //For Output
parameter UP = 3'b000, SHORT0 = 3'b001, SHORT1 = 3'b010, UP_DOT = 3'b011, LONG = 3'b100, UP_DASH = 3'b101;

//Active High
always@(PS or in)
    case (PS)
        UP: if (in)         NS = SHORT0;
             else               NS = UP;

        SHORT0: if (in) NS = SHORT1;
                 else           NS = UP_DOT;

        SHORT1: if (in) NS = LONG;
                 else           NS = UP_DOT;

        UP_DOT:                 NS = UP;

        LONG:   if (in)     NS = LONG;
                else            NS = UP_DASH;

        UP_DASH:            NS = UP;
    default: NS = 3'bxxx;
    endcase

always@(PS)
    case (PS)
        UP:     out = NONE;
        SHORT0: out = NONE;
        SHORT1: out = NONE;
        UP_DOT: out = DOT;
        LONG:   out = NONE;
        UP_DASH: out = DASH;
        default: out = 2'bxx;
    endcase

D_FF dff0 (PS[0], NS[0], reset, Clock);
D_FF dff1 (PS[1], NS[1], reset, Clock);
D_FF dff2 (PS[2], NS[2], reset, Clock);

endmodule

module D_FF (q, d, reset, clk);
    input d, reset, clk;
    output reg q;

    always@(posedge clk or posedge reset)
    begin
        if (reset) q = 0;
        else       q = d;
    end
endmodule

モジュールの入力はFPGAのKEYです。UserInputモジュールによって表されるFSMのキーは、t=0で「UP」状態になっています。次に、入力がある場合は、SHORT0またはSHORT1を通過し、最後にLONGに移動します。これらの状態のいずれかでキーが解放されると、適切な中間UP状態になり、「DOT」または「DASH」の出力を提供します。

ただし、これをFPGAに接続しても、何も得られません。私のテストから、それは「UP」状態から決して離れないようです。私のシミュレーションでさえ私には何も与えません。次に、別のプロジェクト(私が知っているプロジェクト)から別のUserInputモジュールを接続しようとしましたが、それでも何も起こりません。私が見逃しているVerilogのバックグラウンドで何かが起こっていますか?

シミュレーション波形の画像は次のとおりです。シミュレーション波形

DFf 0、1、および2は、PSのビット0、1、および2です。私のシミュレーションでは、NSを表示できません。

4

1 に答える 1

2

あなたのコードは私には悪いように見えます (コードが機能しないので、聞きたいと思います)。タイミングの問題と設計上の欠陥の組み合わせのようです。

波形ビューを見て、何が起こっているのか理解できないか見てみましょう。

信号入力が高くなり、常にブロックがトリガーされます。PS は 0 なので、NS を 1 に設定します。これは立ち上がりクロック エッジに間に合わないため、DFF でトリガーされません (ご想像のとおり)。

入力信号がローになると、常にブロックがトリガーされます。PS は 0 なので、NS を 0 に設定します。これはクロックの立ち上がりエッジに間に合うように発生し、DFF でキャプチャされます (NS 信号が必要に応じて 1 になるのを見逃してしまいました)。 .

また、リセットがアサートされている間にフリップフロップがアサートされるとエラーが発生すると誰かが言いました。これは問題ではありません。リセットは同期的です。したがって、次の立ち上がりクロック エッジで、DFF は 0 にリセットされます。

それで、解決策は何ですか(私には宿題のように見えるので、うまくいけば、これはすでに修正されています!):

次のようになります (シミュレートしていないため、保証はありません)。

Module UserInput (clk, reset, in, out);
input clk, reset, in;
output [1:0] out;

// output parameters
parameter IDLE = 2'b00;
parameter DOT = 2'b01;
parameter DASH = 2'b10;

// FSM states
parameter LOW = 3'b000;
parameter SHORT1 = 3'b001;
parameter SHORT2 = 3'b010;
parameter LONG = 3'b100;

reg [2:0] state;
wire [1:0] next_out;
wire [2:0] next_state;

always @(posedge clk)
begin
    if (reset)
    begin
        out <= IDLE;
        state <= LOW;
    end;
    else
    begin
        out <= next_out;
        state <= next_state;
    end
    end if;
end

always @(*)
begin
    case (state)
    LOW:
        next_out = IDLE;
        next_state = (in? SHORT1 : LOW);
    SHORT1:
    begin
        next_state = (in? SHORT2: LOW);
        next_out = (in? IDLE : DOT);
    end;
    SHORT2:
        next_state = (in? LONG: LOW);
        next_out = (in? IDLE : DOT);
   LONG:
        next_state = (in? LONG : LOW);
        next_out = (in? IDLE : DASH);
   default:
        // we shouldn't get here!!
        next_state = LOW;
        next_out = IDLE;
   end;
   end module;

ここで何が起こっているのか: これはかなり明白なはずです。in 信号がハイからローに変化すると、現在の状態 (LONG は DASH、SHORT1 と SHORT2 は DOT) を出力し、それ以外の場合は IDLE を出力します。in シグナルが高い場合、どのくらい高い状態であるかに応じて状態を移動します。

このコードには、シミュレーションには影響しないが、ほぼ確実に FPGA に影響するエラーがあります。準安定性の問題を防ぐためのフロップ。これは、一連の D フリップフロップを追加して in 信号をキャプチャし、この「クリーンな」buffered_in を UserInput に渡すことで修正できます。

すなわち:

module in_buffer (clk, reset, in, out);
input clk, reset, in;
output out;

reg buf1, buf2;

always @ (posedge clk)
begin
    if (reset)
    begin
        out <= 0;
        buf1 <= 0;
        buf2 <= 0;
    end
    else
        out <= buf2;
        buf2 <= buf1;
        buf1 <= in;
    end
end
于 2012-06-29T06:48:48.043 に答える