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