我目前正在编写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
答案 0 :(得分:1)
在您的设计中enable
是一个锁存器,如果L
或R
在最短的时间内处于高位(或可能是浮动的),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;”时在线上设置断点。