1

我目前正在编写 Verilog 代码来构建“拔河”游戏。下面的模块代表代表比赛场地的 15 个 LED 的中央 LED。中央灯必须一直亮着,直到游戏开始,例如当它接收到某种输入时(输入由 L 和 R 给出,其中 L 是向左移动,而 R 是向右移动)。

但是,我遇到了一个奇怪的错误。虽然我enabled在构造时给出了 1 的值,并且 L 和 R 在构造时为 0(或应该是),但当我运行代码时enabled立即变为 0。

我的问题是,为什么会发生这种情况?在看到输入之前,我将如何使变量保持值 1?

module centerLight(Clock, reset, L, R, NL, NR, lightOn);
    input Clock, reset, L, R, NL, NR;
    output reg lightOn;

    reg gameStart = 0;
    reg enabled = 1;

    always@(L or R)
    if (L | R) begin
        gameStart = 1;
        enabled = 0;
    end
    else if (enabled)
        gameStart = 0;
    wire PS;
    reg NS;

    always@(PS or L or R or NL or NR)
    if((NL && R) || (NR && L)) NS = ~PS;
    else               NS = PS;

    always@(PS or gameStart)
    case(PS || !gameStart)
        0: lightOn = 0;
        1: lightOn = 1;
    endcase

    D_FF cl (PS, NS, reset, Clock);

endmodule

module D_FF (q, d, reset, clk);
    input d, reset, clk;
    output reg q;

    always@(posedge clk or posedge reset)
    if (reset)
        q = 0;
    else
        q = d;

endmodule
4

3 回答 3

1

在您的设计enable中是一个锁存器,如果在最短的时间内处于高电平(或可能浮动),L则将打开。Renable

最好使整个设计顺序化,然后使用复位来确保gameStart低电平。

这就是我的做法:

module centerLight(Clock, reset, L, R, NL, NR, lightOn);
    input Clock, reset, L, R, NL, NR;
    output reg lightOn;

    reg lightOn_d;
    reg gameStart, gameStart_d;
    reg PN, NS;

    always @ (posedge Clock or posedge reset)
        if(reset)
            begin
                gameStart <= 1'b0;
                PS        <= 1'b0;
                lightOn   <= 1'b0;
            end
        else
            begin
                gameStart <= gameStart_d;
                PS        <= NS;
                lightOn   <= lightOn_d;
            end

    always @ *
        begin
            if(L || R)
                gameStart_d = 1'b1;
            else
                gameStart_d = gameStart;

            if((NL && R) || (NR && L))
                NS = ~PS;
            else
                NS = PS;

            if(PS || !gameStart)
                lightOn_d = 1'b1;
            else
                lightOn_d = 1'b0;
        end

endmodule

我希望这会有所帮助。

于 2012-05-17T10:59:49.467 回答
1

这可能是由于编译器开关造成的。

您的默认启用设置实际上是一个初始块,因为初始块是不可综合的(可以指示 Altera 的 Quartus 读取它们以设置上电条件,但根据 Doulos 的官方说法,它们不支持综合)那么它不应该影响FPGA逻辑的结果。

不过,这应该可以模拟为 RTL。但是我知道对于 Altera 设备,例如,所有逻辑在启动时上电为零,除非“Powerup don't care”开关设置为打开,在这种情况下,它将查看逻辑并将寄存器设置为可以最小化逻辑的值.

在这种情况下,它会将 enabled 设置为逻辑 0,因为这会产生最小的逻辑,因此不需要(因为您的代码在任何地方都不会设置 enabled 为 1,除非在技术上应该被忽略的初始构造中,即使它正在读取初始构造然后用那个开关它可能是)。

我确实尝试通过添加一个总是添加一个重置启用并将所有分配放在那里启用(保持它作为一个锁存器)

always@(reset) if (reset) enabled <= 1'b1; 否则如果 (L | R) 启用 <= 1'b0;

通过这样做,我可以看到启用的功能保留在逻辑上。

另一方面,我建议采用同步注册方法而不是闩锁。

还建议 Verilog 在整个代码中与大小写保持一致,因为最终您会遇到麻烦(经典错误是将模块连接起来,如果不使用语句 `default_nettype none ,编译器会推断出连线(我会查看代码)像 Sunburst 技术公司的 Clifford Cummin 或 Doulos 的灵感)。

我希望这有帮助!

于 2012-07-04T10:32:12.303 回答
0

当 L|R=1 时,代码中的启用值被分配为 0。如果您的测试台中 L 和 R 的初始值或 FPGS 上这些引脚的值最初为 1,则启用将切换为 0。悬空的 L 和 R 引脚也可能被评估为 1。

Modelsim 等模拟器允许您在“enabled = 0;”时在该行设置断点。

于 2012-05-16T13:38:26.190 回答