我的反应测试代码完美无缺,在仿真中也应如此。但是当我将它移动到我的FPGA设备时,只要按下开始按钮就会停止,我无法弄清楚出现了什么问题,因为它在模拟中完美运行。
概念是,当按下重置时,屏幕上会显示Hi
,当按下start
时,从LFSR
中选择一个随机值并计算到最大值,从而使其成为最大值随机延迟。当达到此注册表的最大计数时,打开指示灯,启动计时器并等待按下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
答案 0 :(得分:4)
您是否已清除合成日志中的警告或错误等内容?我要做的第一件事就是弄清楚sel
信号发生了什么。如果综合认为它没有被使用那么它就会出现问题,你不应该用任何特殊的KEEP指令覆盖它。
有一件事我注意到你在sel
上推断了一个锁存器,因为你没有在每个状态下分配它。推断锁存器对于仿真没有问题,但您的FPGA可能不喜欢它。
可能需要阅读:Why are Inferred Latches Bad?
您还有很多其他推断锁存器:outled
,regd0-3
,random_done
,go_start
以及其他人。在尝试调试FPGA上的任何内容之前,您应该尝试清理这些内容。
答案 1 :(得分:2)
当模拟良好且合成代码不起作用时,现实生活与模拟之间存在差异。我总是希望发现差异在我的模拟中,因为它比现实生活更容易解决:)
一些例子:
模拟假设逻辑延迟是无关紧要的。如果你有良好的时序约束是真的。如果关键路径未被时序约束所覆盖,则不再适用。至少你需要一个时钟上的最大频率约束。
其他时序问题可能来自外部设备 - 您需要告诉FPGA工具它们的设置和保持和输出延迟,以便可以根据FPGA逻辑的能力检查它们
< / LI>如果你已经从数据表中创建了自己的外部零件模型,那么它们很可能在至少一些小细节上是不正确的
启动行为可能不同 - 如果您已初始化(不使用重置)任何信号,请检查综合日志以确保它们已传输到FPGA比特流,否则你可能会失去一些东西。
数字信号实际上是模拟信号,特别是一旦它们是片外信号。默认情况下,FPGA输出通常设置为快速设置,因此数字看起来不会很糟糕。如果你在没有良好返回路径的情况下将它们向下驱动一些随机线路,信号将变为“非常类似”!
答案 2 :(得分:0)