Verilog始终在时间= 0时阻止

时间:2012-05-15 00:06:25

标签: verilog

我目前正在编写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

3 个答案:

答案 0 :(得分:1)

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

最好让整个设计顺序完成,然后使用重置来确保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

我希望有所帮助。

答案 1 :(得分:1)

可能是由于编译器开关。

你的默认设置enabled实际上是一个初始块,因为初始块不可合成(Altera的Quartus可以被指示读取它们以设置上电条件,但正式根据Doulos它们不支持合成)然后应该不会影响FPGA逻辑的结果。

虽然这应该模拟为RTL。但我知道对于Altera器件,例如所有逻辑在启动时上电为零,除非“Powerup不关心”开关设置为on,在这种情况下,它将查看逻辑并将寄存器设置为最小化逻辑的值

在这种情况下,它会将enabled设置为逻辑0,因为它会产生最小的逻辑,因此不再需要(因为除了初始构造之外,你的代码永远不会设置为1,技术上应该忽略它,即使它正在读取初始构造然后用那个开关它可能是)。

我确实尝试添加一个重置来启用,通过添加一个始终并将所有赋值设置为启用(将其保留为锁存器)

总是@(重置)   如果(重置)     启用&lt; = 1'b1;   否则如果(L | R)     启用&lt; = 1'b0;

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

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

同样建议Verilog与整个代码中的大小写保持一致,因为最终你会遇到麻烦(经典错误是连接模块,如果语句`default_nettype none没有使用,编译器会推断连线(我是看一下像Sunburst技术的Clifford Cummin这样的代码,或者Doulos的灵感来源。

我希望这有帮助!

答案 2 :(得分:0)

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

模拟器(例如Modelsim)允许您在“enabled = 0;”时在线上设置断点。