0

まず、私がやろうとしていることを説明させてください。私は、7 セグメント ディスプレイが 4 つある DE0 を使用しています。私の目標は、ディスプレイ全体をスクロールするテキストの文字列を生成することです。テキスト文字列はユーザ​​ー入力に基づいています。ユーザーには、A、B、および C に対応する 3 つのボタンがあります。

7 セグメント ディスプレイにテキストを表示する「ループ」を作成できましたが、ユーザー入力を取得するのに苦労しています。私の考えは、いわばユーザー入力を受け取り、過去の入力をチェーンの下にシフトする9ビットシフトレジスタを使用することです。

私は Verilog にまったく慣れていないので、コードを書くときにそれについてどう考えるのが最善かをまだ考えているところです。これまでのところ、物理ハードウェアの観点から視覚化するのが最善であることがわかりました。

とは言っても、これは私が視覚化しているものです:

新しい入力 => フリップフロップ 1 => FF2 => FF3 => FF4 => FF5 => FF6 => FF7 => FF8 => 古い入力を破棄

このアイデアを使用して、次のコードを書きました。

wire[1:0] oneFF, twoFF, threeFF, fourFF, fiveFF, sixFF, sevenFF, eightFF;
reg[1:0] change;
wire bA, bB, bC; //Detects change in user input - either 1 or 0
parameter A = 2'b00; parameter B = 2'b01; parameter C = 2'b10;


//They are declared as wires since they really only interconnect portions of
  the hardware

FF One(clk, change, oneFF);
FF Two(clk, oneFF, twoFF);
FF Three(clk, twoFF, threeFF);
FF Four(clk, threeFF, fourFF);
FF Five(clk, fourFF, fiveFF);
FF Six(clk, fiveFF, sixFF);
FF Seven(clk, sixFF, sevenFF);
FF Eight(clk, sevenFF, eightFF);

module FF(clk, in, out);
  input clk;
  input [1:0] in;
  output reg [1:0] out;
  reg [31:0] count;

  always @(posedge clk)
    begin
        count <= count + 1;
        if(count == 50000000) begin
        out <= in;
        count <= 0;
        end
    end
endmodule

change次に、レジスタの入力を検出するモジュールを作成しました。

always @(*)
    begin

        if(bA) begin
            change = A;

        end

        if(bB) begin
            change = B;

        end

        if(bC) begin
            change = C;

        end
    end

ここで問題が発生します。ボタンを押すことはできますが、最初のレジスタの変更はチェーン全体に伝播します。明らかに、これは 8 つのレジスタすべてが同じクロックに接続されているために発生します。このクロックは 50mHz で動作しているため、瞬時に発生するように見えます。module FFこれが、疑惑を確認できるようにカウンターを通過する理由です。

これに対処するために、alwaysブロックに単一ビットの「更新」を挿入して、各入力で正のエッジを作成しようとしましたが、うまくいきませんでした。

例えば:

  reg update;
  always @(*)
    begin
        update = 0;
        if(bA) begin
            change = A;
            update = ~update;
        end

        if(bB) begin
            update = ~update;
            change = B; 
        end

        if(bC) begin
            change = C;
            update = ~update;
        end
            update = 0;
    end

それに応じて、モジュールのインスタンス化も変更します。これは、このブロックをノンブロッキング割り当てに変更した場合にも当てはまります。

この問題には本当に簡単な解決策があると思います。基本的に、私が望むのはこの効果を持つことだけです

文字列の初期化: _ _ _ _ _ ...

入力: _ _ _ _ ...

次の入力: BA _ _ _ ...

それ以外の

入力: AAAAA ...

次の入力: BBBBB ...

建設的な意見を歓迎します。

4

1 に答える 1

3

組み合わせロジックからエッジまたはパルスを生成しようとしないでください。クロックのみを使用して必要なことを行うことができるため、純粋にクロックされたロジックに固執する必要があります。

ユーザー入力の変更に基づいて更新ストローブ信号を生成する場合は、ボタンの以前の値を保存し、ボタンが変更されるたびに更新を生成します。

wire bA;
reg  bA_q;
reg  update;

always @(posedge clk) begin
   bA_q <= bA;
end

always @* begin
   if(bA && !bA_q) begin
        change = A;
        update = 1'b1;
   end else begin
        update = 1'b0;
        change = 0; //this can be anything, just set it so you don't infer a latch
   end
end

これにより、bA が 0 から 1 に遷移する任意のクロック サイクルで更新ストローブが生成されます。

ただし、FPGA によっては、ボタンをデバウンスする必要がある場合があります (一部の fpga は自動的に行います)。

ボタンがデバウンスされていない場合、ボタンを押すとすばやく上下にちらつき、この回路にはボタンを数回繰り返し押したように見えます。したがって、1 回のプレスで複数の更新プログラムを取得できます。これは非常に一般的なトピックであり、必要に応じてボタンをデバウンスする方法に関する追加のリソースを見つけることができると確信しています。

于 2014-03-29T20:21:46.570 に答える