简体   繁体   English

FPGA(Verilog)-在仿真中工作,但在FPGA上不工作

[英]FPGA (Verilog) - Working in simulation but not working on FPGA

The following code implements (or should implement) a 7 segment driver that reads a value from some switches and shows that value in the 4 7 segment displays. 以下代码实现(或应该实现)一个7段驱动程序,该驱动程序从某些开关读取一个值,并在4 7段显示中显示该值。 The simulation works fine, but when it runs in the FPGA the 7 segment displays show something for a fraction of time and then no segment lights up. 模拟工作正常,但是当它在FPGA中运行时,7段显示器在短时间内显示出一些东西,然后没有段亮起。 I have no idea why it doesn't work. 我不知道为什么它不起作用。 Also, I implemented a simple counter. 另外,我实现了一个简单的计数器。 When I had "<=" inside of the always blocks it worked and when I had "=" it didn't, but in simulation it worked with both. 当我在Always块中使用“ <=”时,它起作用了,当我使用“ =”时,它没有起作用,但是在仿真中,这两种方法都起作用了。 The difference between "<=" and "=" is just that "<=" runs in parallel and "=" in sequence? “ <=”和“ =”之间的区别仅仅是“ <=”并行运行,而“ =”依次运行?

I should also say that it works if instead of sending the value from the switches to the display module I send a constant value. 我还应该说,如果我发送一个恒定值而不是将值从开关发送到显示模块,那么它将起作用。

display.v: display.v:

module display(
    input [15:0] count,
    output reg [6:0] seg,
    output dp,
    output [3:0] an,
    input clk
    );

reg [3:0] an_temp;
reg [6:0] rom [9:0];

initial
begin
    an_temp <= 1;
    rom[0] <= 'b1000000;
    rom[1] <= 'b1111001;
    rom[2] <= 'b0100100;
    rom[3] <= 'b0110000;
    rom[4] <= 'b0011001;
    rom[5] <= 'b0010010;
    rom[6] <= 'b0000010;
    rom[7] <= 'b1111000;
    rom[8] <= 'b0000000;
    rom[9] <= 'b0110000;
end

assign dp = 1;
assign an = ~an_temp;

wire [3:0] disp [3:0];

assign disp[0] = count % 10;
assign disp[1] = ((count - disp[0])/10) % 10;
assign disp[2] = ((count - disp[1]*10 - disp[0])/100) % 10;
assign disp[3] = ((count - disp[2]*100 - disp[1]*10 - disp[0])/1000) % 10;

always @ (posedge clk)
begin
    if (an_temp == 'b1000) an_temp = 1;
    else an_temp = an_temp = 1;
    case (an_temp)
        'b0001: seg <= rom[disp[0]];
        'b0010: seg <= rom[disp[1]];
        'b0100: seg <= rom[disp[2]];
        'b1000: seg <= rom[disp[3]];
        default: seg <= 'b1111111;
    endcase
end

endmodule

disp_clk.v: disp_clk.v:

module disp_clk(
    input clk,
    output disp_clk
    );

reg [31:0] count;

initial count = 0;

always @ (posedge clk)
begin
    count = count + 1;
    if (count == 400000) count = 0;
end

assign disp_clk = (count > 200000) ? 1 : 0;

endmodule

top.v: top.v:

module top(
    input clk,
    input [15:0] sw,
    output [6:0] seg,
    output dp,
    output [3:0] an
    );

wire disp_clk;

disp_clk disp_clk0(
    .clk(clk),
    .disp_clk(disp_clk)
    );

display disp0(
    .count(sw),
    .seg(seg),
    .dp(dp),
    .an(an),
    .clk(disp_clk)
    );

endmodule

Thank you 谢谢

I should also say that it works if instead of sending the value from the switches to the display module I send a constant value. 我还应该说,如果我发送一个恒定值而不是将值从开关发送到显示模块,那么它将起作用。

Sounds like you are not meeting your timing window. 听起来好像您未达到计时窗口。 If count is a constant vector, then the disp assignments should all be precomputed in synthesis. 如果count是一个常数向量,则disp分配都应在合成中预先计算。 Otherwise, they need to be computed on the fly, and the requisite logic is inferred (which is rather slow). 否则,需要即时计算它们,并推断出必要的逻辑(这相当慢)。

((count - disp[2]*100 - disp[1]*10 - disp[0])/1000) % 10 has a multiplier feeding into a division feeding into another division. ((count - disp[2]*100 - disp[1]*10 - disp[0])/1000) % 10的乘法器馈入一个除法器,再馈入另一个除法器。 One would hope that this is being inferred as cascading DSPs, but you should check your resource report to make sure, and as an added sanity check make sure the resource count for constant vs switched signaling shows a difference. 有人希望可以将其推断为级联DSP,但是您应该检查资源报告以确保这一点,此外,还要进行完整性检查,以确保恒定信号与交换信号的资源计数之间存在差异。

You may need to pipeline these operations if you cannot think of more optimal logic. 如果您无法想到更理想的逻辑,则可能需要对这些操作进行流水线处理。

The difference between "<=" and "=" is just that "<=" runs in parallel and "=" in sequence? “ <=”和“ =”之间的区别仅仅是“ <=”并行运行,而“ =”依次运行?

Yes, in a sense. 是的,在某种意义上。 <= and = refer to non-blocking and blocking assignments respectively. <==表示非阻塞阻塞分配。

The simulator will compute logic assignment on every time step. 模拟器将在每个时间步计算逻辑分配。

For non-blocking , the right hand side is computed and may be updated later in the time step if it is logically dependent on other signaling, then just before the next time step begins, the left hand side of all the non-blocking assignments are assigned to the updated right hand side. 对于非阻塞 ,如果右侧在逻辑上依赖于其他信令,则将计算右手侧,并可以在该时间步的稍后进行更新,然后在下一个时间步开始之前,所有非阻塞分配的左手侧分配给更新的右侧。

In a blocking assignment, the simulator will evaluate the right hand side and immediately assign it to the left hand side, in this way other logic is blocked from altering the assignment. 阻塞分配中,模拟器将评估右侧,并立即将其分配给左侧,以这种方式阻止其他逻辑更改分配。

You can consider this sequential, but keep in mind that the sequentiality is only true within a functional block. 您可以考虑此顺序,但请记住,顺序仅功能块才是正确的。 If you have two always blocks that perform co-dependent evaluations on the same time step, you are not guaranteed which block the simulator will evaluate first and you might see some bizarre behavior based on how the simulator does it's scheduling. 如果您有两个始终在同一时间步执行相互依赖的评估的块,则不能保证模拟器将首先评估哪个块,并且根据模拟器的调度方式,您可能会看到一些奇怪的行为。

Best practice is to use blocking assignments for behaviors that are intended to be combinatorial (ie always@(*) ), and non-blocking assignments for those that are intended to be sequential (ie always@(posedge Clock) ). 最佳实践是对要组合的行为(即always@(*) )使用阻塞分配,对要进行顺序的行为(即always@(posedge Clock) )使用非阻塞分配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM