问题
My code for a reaction tester works perfectly and as it should in simulation. But when I move it to my FPGA device it just stalls as soon as I press the start button and I cannot figure out what goes wrong as it is working perfectly in simulation.
The concept is, when reset is pressed display Hi
on the screen, when start
is pressed, pick a random value from LFSR
and count up to max value, thus making it a random delay. When max count for this reg is reached turn on the led, start the timer and wait for the stop
button to be pressed.
Here is a screenshot of the code working in simulation:
Here 0000
is normal as notice that ticker starts incrementing and when it reaches its desired value it increments the timer making it 0001
, so if I scroll forward enough it shows proper operation.
Here is the commented code, I added the (* KEEP = "TRUE" *)reg [1:0] sel;
because during optimization the sel
signal was removed as it was declared but never called, but obviously I needed it as it is.
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
And here is the display circuit that will take the regd0-regd3
values.
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
When I move it on to my FPGA device at reset "Hi" is displayed as it should but when I press start
the display just shows 0000
and stays at that. The led wont turn on either so that means the times was never initialized after the start
button was pressed. I have been trying to sort this out for days now and cant seem to figure out why this is happening. What does one do when something works in simulation but does not work as its supposed to in hardware?
Update code with the latches fixed:
//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
回答1:
Have you scrubbed your synthesis logs for anything like warnings or errors? The first thing I would do would figure out what's going on with that sel
signal. If synthesis thinks it is not used then something is very wrong with it, you shouldn't have to override it with any special KEEP directive.
For one thing I notice that you have inferred a latch on sel
as you don't assign it in every state. Inferring latches is no problem for simulation, but your FPGA may not like it.
May want to read: Why are Inferred Latches Bad?
You have quite a few other inferred latches as well: outled
, regd0-3
, random_done
, go_start
, and maybe others. You should try to clean these all up before trying to debug anything on the FPGA.
回答2:
When the simulation is good and the synthesised code doesn't work there is a discrepancy between real-life and the simulations. I always hope to find that the discrepancy is in my simulations as it's easier to fix than real-life is :)
Some examples:
Simulation assumes that logic delays are inconsequential. If you have good timing constraints that is true. If a critical path is not covered by the timing constraints, it is no longer true. At the very least you need an maximum frequency constraint on the clock.
Other timing problems can come from the devices externally - you need to tell the FPGA tools about their setup and hold and output delays so that they can be checked against what the FPGA logic is capable of
If you've created your own models of the outside parts from the datasheet, they are very likely to be incorrect in at least some small detail
The startup behaviour might be different - if you have initialised (not using a reset) any signals, check the synthesis logs to make sure they got carried through to the FPGA bitstream, otherwise you might be losing something.
Digital signals are really analogue, especially once they are offchip. FPGA outputs are usually set to a fast setting by default, so that the numbers don't look bad. If you then drive them down a bit of random wire without a good return path, the signals will turn "very-analogue"!
回答3:
Something else you can try in order to debug issues when running on the FPGA is to use a logic analyzer to see what your hardware is doing and how that compares to you simulations.
Xilinx provides a tool called Chipscope
and Altera provides Signaltap
These are good tools to use after you resolved all simulator/router warnings and are still having issues.
来源:https://stackoverflow.com/questions/15180808/how-to-debug-after-implementation-my-code-that-works-perfectly-in-simulation-sh