0

反応テスターの私のコードは、シミュレーションで正常に機能します。しかし、FPGAデバイスに移動すると、スタートボタンを押すとすぐに停止し、シミュレーションで完全に機能しているため、何が問題になっているのか理解できません。

コンセプトは、リセットが押されHiたときに画面に表示され、が押されたときstartにランダムな値を選択し、LFSR最大値までカウントアップすることで、ランダムな遅延を実現します。このregの最大カウントに達したら、LEDをオンにし、タイマーを開始して、stopボタンが押されるのを待ちます。

シミュレーションで機能するコードのスクリーンショットは次のとおりです。

ここに画像の説明を入力してください

0000ティッカーがインクリメントを開始し、目的の値に達するとタイマーをインクリメントしてタイマーを作成するので0001、これは正常です。十分に前にスクロールすると、適切な動作が示されます。

コメントされたコードは次のとおりです。(* KEEP = "TRUE" *)reg [1:0] sel;最適化中にselシグナルが宣言されたときに削除されたが呼び出されなかったため、追加しましたが、明らかにそのまま必要でした。

  reg [12:0] random, random_next, random_done; //**13 bit for simulation purposes

reg [4:0] count_r, count_next_r; //to keep track of the shifts. 5 bit register to count up to 30


wire feedback = random[12] ^ random[3] ^ random[2] ^ random[0]; //**for simulation

always @ (posedge clock or posedge reset)
begin
    if (reset)
    begin
        random <= 13'hF; //**An LFSR cannot have an all 0 state, thus reset to FF
        count_r <= 0;
    end

    else
    begin
        random <= random_next;
        count_r <= count_next_r;
    end
end

always @ (*)
begin
    random_next = random; //default state stays the same
    count_next_r = count_r;

        random_next = {random[11:0], feedback}; //**shift left the xor'd every posedge clock
        count_next_r = count_r + 1;

    if (count_r == 13) //**for implementation its 30, simulation its 13
    begin
        count_next_r = 0;
        random_done = random; //assign the random number to output after 13 shifts
    end

end
//random number block ends

reg outled;

reg [3:0] reg_d0, reg_d1, reg_d2, reg_d3; //registers that will hold the individual counts
(* KEEP = "TRUE" *)reg [1:0] sel;
localparam [1:0]
                        idle = 2'b00,
                        starting = 2'b01,
                        time_it = 2'b10,
                        done = 2'b11;

reg [1:0] state_reg, state_next;
reg [12:0] count_reg, count_next; //**change for simulation, 30 bits for implementation, 13 bits for simulation

always @ (posedge clock or posedge reset)
begin
    if(reset)
        begin 
            state_reg <= idle;
            count_reg <= 0;
        end
    else
        begin
            state_reg <= state_next;
            count_reg <= count_next;
        end
end

reg go_start;
always @ (*)
begin
    state_next = state_reg; //default state stays the same
    count_next = count_reg;

    case(state_reg)
        idle:
            begin
                //DISPLAY HI HERE
                sel = 2'b00;
                if(start)
                begin
                    count_next = random_done; //get the random number from LFSR module
                    state_next = starting;
                end
            end
        starting:
            begin
                if(count_next == 8191) // **750M equals a delay of 15 seconds.
                begin                           //and starting from 'rand' ensures a random delay
                    outled = 1'b1; //turn on the led 
                    state_next = time_it; //go to next state
                end

                else
                    count_next = count_reg + 1; 
            end     
        time_it:
            begin
                    sel = 2'b01; //start the timer
                    state_next = done;                  
            end

        done:
            begin
                if(stop)
                    begin
                        sel = 2'b10; //stop the timer
                        outled = 1'b0;
                    end
            end

        endcase

    case(sel)
        2'b00: //hi
        begin
            go_start = 0; //make sure timer module is off
            regd0 = 4'd12; 
            regd1 = 4'd11;
            regd2 = 4'd10;
            regd3 = 4'd12;
        end

        2'b01: //timer
        begin

            go_start = 1'b1; //enable start signal to start timer
            regd0 = reg_d0;
            regd1 = reg_d1;
            regd2 = reg_d2;
            regd3 = reg_d3;
        end

        2'b10: //stop timer
        begin
            go_start = 1'b0;
        end

        default:
        begin
            regd0 = 4'bx;
            regd1 = 4'bx;
            regd2 = 4'bx;
            regd3 = 4'bx;
        end
    endcase         
end


//the stopwatch block


reg [15:0] ticker; //**16 bits needed to count up to 50K bits, 10 bit for simulation
wire click;

//the mod 50K clock to generate a tick ever 0.001 second

always @ (posedge clock or posedge reset)
begin
    if(reset)

        ticker <= 0;

    else if(ticker == 50000) //**if it reaches the desired max value of 50K reset it, 500 for simulation
        ticker <= 0;
    else if(go_start) //only start if the input is set high
        ticker <= ticker + 1;
end

assign click = ((ticker == 50000)?1'b1:1'b0); //**click to be assigned high every 0.001 second

always @ (posedge clock or posedge reset)
begin
    if (reset)
        begin
            reg_d0 <= 0;
            reg_d1 <= 0;
            reg_d2 <= 0;
            reg_d3 <= 0;
        end

    else if (click) //increment at every click
        begin
            if(reg_d0 == 9) //xxx9 - the 0.001 second digit
            begin  //if_1
                reg_d0 <= 0;

                if (reg_d1 == 9) //xx99 
                begin  // if_2
                    reg_d1 <= 0;
                    if (reg_d2 == 5) //x599 - the two digit seconds digits
                    begin //if_3
                        reg_d2 <= 0;
                        if(reg_d3 == 9) //9599 - The minute digit
                            reg_d3 <= 0;
                        else
                            reg_d3 <= reg_d3 + 1;
                    end
                    else //else_3
                        reg_d2 <= reg_d2 + 1;
                end

                else //else_2
                    reg_d1 <= reg_d1 + 1;
            end 

            else //else_1
                reg_d0 <= reg_d0 + 1;
        end
end

そして、これが値を取る表示回路regd0-regd3です。

    localparam N = 18; //18 for implementation, 8 for simulation

reg [N-1:0]count;

always @ (posedge clock or posedge reset)
    begin
        if (reset)
            count <= 0;
        else
            count <= count + 1;
    end

reg [3:0]sseg;
reg [3:0]an_temp;
reg reg_dp;
always @ (*)
    begin
        case(count[N-1:N-2]) //MSB and MSB-1 for multiplexing

            2'b00 : 
                begin
                    sseg = first;
                    an_temp = 4'b1110;
                    reg_dp = 1'b1;
                end

            2'b01:
                begin
                    sseg = second;
                    an_temp = 4'b1101;
                    reg_dp = 1'b0;
                end

            2'b10:
                begin
                    sseg = third;
                    an_temp = 4'b1011;
                    reg_dp = 1'b1;
                end

            2'b11:
                begin
                    sseg = fourth;
                    an_temp = 4'b0111;
                    reg_dp = 1'b0;
                end
        endcase
    end
assign an_m = an_temp;

reg [6:0] sseg_temp;    
always @ (*)
    begin
        case(sseg)
            4'd0 : sseg_temp = 7'b1000000; //display 0
            4'd1 : sseg_temp = 7'b1111001; //display 1
            4'd2 : sseg_temp = 7'b0100100;// display 2
            4'd3 : sseg_temp = 7'b0110000;
            4'd4 : sseg_temp = 7'b0011001;
            4'd5 : sseg_temp = 7'b0010010;
            4'd6 : sseg_temp = 7'b0000010;
            4'd7 : sseg_temp = 7'b1111000;
            4'd8 : sseg_temp = 7'b0000000;
            4'd9 : sseg_temp = 7'b0010000;
            4'd10 : sseg_temp = 7'b0001001; //to display H
            4'd11 : sseg_temp = 7'b1001111; //to display I
            default : sseg_temp = 7'b0111111; //dash
        endcase
    end
assign {g_m, f_m, e_m, d_m, c_m, b_m, a_m} = sseg_temp; 
assign dp_m = reg_dp;

endmodule

リセット時にFPGAデバイスに移動すると、「Hi」が表示されますが、押すstartと、表示さ0000れたままになります。LEDもオンにならないため、startボタンが押された後に時刻が初期化されることはありませんでした。私はこれを何日も整理しようとしてきましたが、なぜこれが起こっているのか理解できないようです。シミュレーションでは機能するが、ハードウェアでは想定どおりに機能しない場合はどうすればよいですか?

ラッチを修正してコードを更新します。

    //Block for LFSR random number generator        
reg [12:0] random, random_next, random_done; //**13 bit for simulation purposes
//reg [29:0] random, random_next, random_done; //30 bit register to keep track upto 15 seconds
reg [4:0] count_r, count_next_r; //to keep track of the shifts. 5 bit register to count up to 30

//wire feedback = random[29] ^ random[5] ^ random[3] ^ random[0]; 
wire feedback = random[12] ^ random[3] ^ random[2] ^ random[0]; //**for simulation

always @ (posedge clock or posedge reset)
begin
    if (reset)
    begin
        random <= 13'hF; //**An LFSR cannot have an all 0 state, thus reset to FF
        count_r <= 0;
    end

    else
    begin
        random <= random_next;
        count_r <= count_next_r;
    end
end

always @ (*)
begin
    random_next = random; //default state stays the same
    count_next_r = count_r;

        random_next = {random[11:0], feedback}; //**shift left the xor'd every posedge clock
        //count_next_r = count_r + 1;

    if (count_r == 13) //**for implementation its 30, simulation its 13
    begin
        count_next_r = 0;
        random_done = random; //assign the random number to output after 13 shifts
    end
    else
    begin
        count_next_r = count_r + 1;
        random_done = 13'b0;
    end

end
//random number block ends

reg outled;

reg [3:0] reg_d0, reg_d1, reg_d2, reg_d3; //registers that will hold the individual counts
/*(* KEEP = "TRUE" *)*/reg [1:0] sel, sel_next;
localparam [1:0]
                        idle = 2'b00,
                        starting = 2'b01,
                        time_it = 2'b10,
                        done = 2'b11;

reg [1:0] state_reg, state_next;
reg [12:0] count_reg, count_next; //**change for simulation, 30 bits for implementation, 13 bits for simulation

always @ (posedge clock or posedge reset)
begin
    if(reset)
        begin 
            state_reg <= idle;
            count_reg <= 0;
            sel <=0;
        end
    else
        begin
            state_reg <= state_next;
            count_reg <= count_next;
            sel <= sel_next;
        end
end

reg go_start;
always @ (*)
begin
    state_next = state_reg; //default state stays the same
    count_next = count_reg;
    sel_next = sel;
    case(state_reg)
        idle:
            begin
                //DISPLAY HI HERE
                //sel_next = 2'b00;
                if(start)
                begin
                    count_next = random_done; //get the random number from LFSR module
                    state_next = starting;
                end
            end
        starting:
            begin
                if(count_next == 8191) // **750M equals a delay of 15 seconds.
                begin                           //and starting from 'rand' ensures a random delay
                    outled = 1'b1; //turn on the led 
                    state_next = time_it; //go to next state
                end

                else
                begin
                    count_next = count_reg + 1; 
                    outled = 1'b0;
                end
            end     
        time_it:
            begin
                    sel_next = 2'b01; //start the timer
                    state_next = done;                  
            end

        done:
            begin
                if(stop)
                    begin
                        sel_next = 2'b10; //stop the timer
                        outled = 1'b0;
                    end
            end

        endcase

    case(sel_next)
        2'b00: //hi
        begin
            go_start = 0; //make sure timer module is off
            regd0 = 4'd12; 
            regd1 = 4'd11;
            regd2 = 4'd10;
            regd3 = 4'd12;
        end

        2'b01: //timer
        begin

            go_start = 1'b1; //enable start signal to start timer
            regd0 = reg_d0;
            regd1 = reg_d1;
            regd2 = reg_d2;
            regd3 = reg_d3;
        end

        2'b10: //stop timer
        begin
            go_start = 1'b0;
            regd0 = reg_d0;
            regd1 = reg_d1;
            regd2 = reg_d2;
            regd3 = reg_d3;
        end

        2'b11:
        begin
            regd0 = 4'd12;
            regd1 = 4'd12;
            regd2 = 4'd12;
            regd3 = 4'd12;
            go_start = 1'b0;
        end

        default:
        begin
            regd0 = 4'd12;
            regd1 = 4'd12;
            regd2 = 4'd12;
            regd3 = 4'd12;
            go_start = 1'b0;
        end
    endcase         
end


//the stopwatch block


reg [15:0] ticker; //**16 bits needed to count up to 50K bits, 10 bit for simulation
wire click;

//the mod 50K clock to generate a tick ever 0.001 second

always @ (posedge clock or posedge reset)
begin
    if(reset)

        ticker <= 0;

    else if(ticker == 50000) //**if it reaches the desired max value of 50K reset it, 500 for simulation
        ticker <= 0;
    else if(go_start) //only start if the input is set high
        ticker <= ticker + 1;
end

assign click = ((ticker == 50000)?1'b1:1'b0); //**click to be assigned high every 0.001 second

always @ (posedge clock or posedge reset)
begin
    if (reset)
        begin
            reg_d0 <= 0;
            reg_d1 <= 0;
            reg_d2 <= 0;
            reg_d3 <= 0;
        end

    else if (click) //increment at every click
        begin
            if(reg_d0 == 9) //xxx9 - the 0.001 second digit
            begin  //if_1
                reg_d0 <= 0;

                if (reg_d1 == 9) //xx99 
                begin  // if_2
                    reg_d1 <= 0;
                    if (reg_d2 == 5) //x599 - the two digit seconds digits
                    begin //if_3
                        reg_d2 <= 0;
                        if(reg_d3 == 9) //9599 - The minute digit
                            reg_d3 <= 0;
                        else
                            reg_d3 <= reg_d3 + 1;
                    end
                    else //else_3
                        reg_d2 <= reg_d2 + 1;
                end

                else //else_2
                    reg_d1 <= reg_d1 + 1;
            end 

            else //else_1
                reg_d0 <= reg_d0 + 1;
        end
end
assign led = outled;
endmodule 
4

3 に答える 3

4

警告やエラーなどの合成ログをスクラブしましたか?sel私が最初にすることは、その信号で何が起こっているのかを理解することです。合成が使用されていないと判断した場合は、何かが非常に間違っているため、特別なKEEPディレクティブでオーバーライドする必要はありません。

sel一つには、すべての状態でラッチを割り当てているわけではないので、ラッチがオンになっていると推測していることに気付きました。ラッチの推測はシミュレーションでは問題ありませんが、FPGAが気に入らない場合があります。

読みたいかもしれません:なぜ推定ラッチが悪いのですか?

他にもかなりの数の推定ラッチがあります:、、、、、そして多分他のものoutled。FPGAで何かをデバッグする前に、これらすべてをクリーンアップする必要があります。regd0-3random_donego_start

于 2013-03-03T03:11:34.643 に答える
2

シミュレーションが適切で、合成されたコードが機能しない場合、実際のシミュレーションとシミュレーションの間に不一致があります。実生活よりも修正が簡単なので、シミュレーションに不一致があることを常に知りたいと思っています:)

いくつかの例:

  • シミュレーションでは、ロジックの遅延は重要ではないと想定しています。タイミングの制約が適切な場合は、それが当てはまります。クリティカルパスがタイミング制約でカバーされていない場合、それはもはや真実ではありません。少なくとも、クロックに最大周波数の制約が必要です。

  • その他のタイミングの問題は、外部のデバイスから発生する可能性があります。FPGAロジックの機能と照合できるように、FPGAツールにセットアップとホールドおよび出力の遅延について通知する必要があります。

  • データシートから外側のパーツの独自のモデルを作成した場合、少なくともいくつかの細部が正しくない可能性が非常に高くなります。

  • 起動動作が異なる場合があります。信号を初期化した(リセットを使用していない)場合は、合成ログをチェックして、それらがFPGAビットストリームに引き継がれていることを確認してください。そうでない場合、何かが失われる可能性があります。

  • デジタル信号は、特にオフチップになると、本当にアナログです。FPGA出力は通常、デフォルトで高速設定に設定されているため、数値が悪く見えません。次に、適切なリターンパスなしでランダムなワイヤを少しドライブすると、信号は「非常にアナログ」になります。

于 2013-03-04T14:50:30.243 に答える
0

FPGAで実行しているときに問題をデバッグするために試すことができる他の方法は、ロジックアナライザーを使用して、ハードウェアの動作とシミュレーションとの比較を確認することです。

ザイリンクスはChipscopeと呼ばれるツールを提供しています

アルテラはSignaltapを提供しています

これらは、すべてのシミュレーター/ルーターの警告を解決した後も問題が解決しない場合に使用するのに適したツールです。

于 2014-04-12T12:51:59.500 に答える