反応テスターの私のコードは、シミュレーションで正常に機能します。しかし、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