繁体   English   中英

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

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

以下代码实现(或应该实现)一个7段驱动程序,该驱动程序从某些开关读取一个值,并在4 7段显示中显示该值。 模拟工作正常,但是当它在FPGA中运行时,7段显示器在短时间内显示出一些东西,然后没有段亮起。 我不知道为什么它不起作用。 另外,我实现了一个简单的计数器。 当我在Always块中使用“ <=”时,它起作用了,当我使用“ =”时,它没有起作用,但是在仿真中,这两种方法都起作用了。 “ <=”和“ =”之间的区别仅仅是“ <=”并行运行,而“ =”依次运行?

我还应该说,如果我发送一个恒定值而不是将值从开关发送到显示模块,那么它将起作用。

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:

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:

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

谢谢

我还应该说,如果我发送一个恒定值而不是将值从开关发送到显示模块,那么它将起作用。

听起来好像您未达到计时窗口。 如果count是一个常数向量,则disp分配都应在合成中预先计算。 否则,需要即时计算它们,并推断出必要的逻辑(这相当慢)。

((count - disp[2]*100 - disp[1]*10 - disp[0])/1000) % 10的乘法器馈入一个除法器,再馈入另一个除法器。 有人希望可以将其推断为级联DSP,但是您应该检查资源报告以确保这一点,此外,还要进行完整性检查,以确保恒定信号与交换信号的资源计数之间存在差异。

如果您无法想到更理想的逻辑,则可能需要对这些操作进行流水线处理。

“ <=”和“ =”之间的区别仅仅是“ <=”并行运行,而“ =”依次运行?

是的,在某种意义上。 <==表示非阻塞阻塞分配。

模拟器将在每个时间步计算逻辑分配。

对于非阻塞 ,如果右侧在逻辑上依赖于其他信令,则将计算右手侧,并可以在该时间步的稍后进行更新,然后在下一个时间步开始之前,所有非阻塞分配的左手侧分配给更新的右侧。

阻塞分配中,模拟器将评估右侧,并立即将其分配给左侧,以这种方式阻止其他逻辑更改分配。

您可以考虑此顺序,但请记住,顺序仅功能块才是正确的。 如果您有两个始终在同一时间步执行相互依赖的评估的块,则不能保证模拟器将首先评估哪个块,并且根据模拟器的调度方式,您可能会看到一些奇怪的行为。

最佳实践是对要组合的行为(即always@(*) )使用阻塞分配,对要进行顺序的行为(即always@(posedge Clock) )使用非阻塞分配。

暂无
暂无

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

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