我的反应测试仪代码运行良好,在模拟中也应该如此。但是当我将它移到我的 FPGA 设备上时,它会在我按下开始按钮后立即停止,我无法弄清楚出了什么问题,因为它在模拟中完美运行。
这个概念是,当按下重置时Hi
屏幕上显示,当start
按下时,从中选择一个随机值LFSR
并计数到最大值,从而使其成为随机延迟。当达到此 reg 的最大计数时,打开 LED,启动计时器并等待stop
按下按钮。
这是在模拟中工作的代码的屏幕截图:
这0000
是正常的,因为ticker开始递增,当它达到所需的值时,它会递增计时器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