我会直言不讳。我有一个简单的计数器正在尝试 模仿时钟如何工作。我有一个名为counter60sec的模块和另一个名为counter12hr的模块
counter12hr
module counter12hr(reset, hourInc, overflowOut, hrCounter);
input reset;
input hourInc;
output overflowOut;
output [3:0] hrCounter;
reg overflowOut;
reg [3:0] hrCounter; //0'b1101 == 13 hours
//Initialize counter
initial begin
overflowOut = 1'b0;
hrCounter = 4'b0; //once hour reaches 12:59:59, it is supposed to go back to zero
end
//Everytime hrInc is one, increment hrCounter
always@(negedge reset or posedge hourInc) begin
overflowOut = 1'b0;
if(reset == 1'b0) begin
overflowOut = 1'b0;
hrCounter = 4'b0;
end
else begin
if (hourInc == 1'b1) begin
hrCounter = hrCounter + 1'b1;
end
end
end
always@(negedge hrCounter) begin
if (hrCounter == 4'b1100) begin
overflowOut = 1'b1;
hrCounter = 4'b0;
end
end
endmodule
counter60sec
module counter60sec(reset, secInc, minOut, secCounter);
input reset;
input secInc;
output minOut;
output [5:0] secCounter;
reg [5:0] secCounter; //0'b111100 == 60 seconds.
reg minOut;
//Initialize counter
initial begin
minOut = 1'b0;
secCounter = 6'b0;
end
//Everytime secInc is one, increment secCounter
always@(posedge secInc or negedge reset) begin
minOut = 1'b0;
if(reset == 1'b0) begin
minOut = 1'b0;
secCounter = 6'b0;
end
else begin
if (secInc == 1'b1) begin
secCounter = secCounter + 1'b1;
end
end
end
//output minOut to 1 to signal minute increase when secCounter hits 111100 in binary
always@(negedge secCounter) begin
if(secCounter == 6'b111100) begin
minOut = 1'b1;
secCounter = 6'b0;
end
end
endmodule
我为两者设置了测试平台。 counter60sec一个正常工作(当secCounter值为60时,minOut变为1)。 counter12hr遵循相同的概念,但overflowOut的值永远不会变为1.
对于我在counter12hr.v中的hrCounter条件语句,我尝试了4'b1101和4'b1100,但两者都没有奏效。 (当hrCounter命中13时,试图让overflowOut成为一个)
我已经花了好几个小时,休息放松我的眼睛等等。我仍然看不到我错在哪里。任何帮助将不胜感激
答案 0 :(得分:1)
always@(negedge reset or posedge hourInc) begin
overflowOut = 1'b0;
...
always@(negedge hrCounter) begin
if (hrCounter == 4'b1100) begin
overflowOut = 1'b1;
overflowOut由2个不同的alsways块驱动。与第二个计数器中的minOut
相同。这些语句的执行顺序是未定义的,结果值将取决于顺序。
您需要重新构建程序,使寄存器仅在单个always块中分配。
其次,我认为,你有一个逻辑错误,在第一个块的第一个语句中将溢出分配给'0'(与第二个块中的相同)。
第三,你应该在寄存器的finlal赋值中使用非阻塞配对'< ='。
以下内容应该有效。
always@(negedge reset or posedge hourInc) begin
if(reset == 1'b0) begin
hrCounter <= 4'b0;
overflowOut <= 1'b0;
end
else begin
if (hrCounter == 4'b1100) begin
overflowOut <= 1'b1;
hrCounter <= 4'b0;
end
else
hrCounter <= hrCounter + 1'b1;
overflowOut <= 1'b0;
end
end
end
答案 1 :(得分:0)
你的代码在很多方面都是错误的...
很可能因为:
@(negedge hrCounter)
您使用的是矢量,但@ ...适用于位。所以它只会查看LS位。
至于你的代码:首先和大多数人开始使用时钟。不要使用信号的posedge和negedge来驱动其他信号。
你使用:
always@(posedge secInc ...
...
if (secInc == 1'b1)
删除'if'。你的永远陈述中已经有了这个条件。 (但信号不应该是'总是',它应该是你的时钟)
删除“初始”部分您有一个定义开始条件的重置。
如果您有一个活动的低重置反映在名称中。将它称为reset_n或n_reset除了'reset'之外的任何东西,按照惯例,它是一个正复位信号。
如果您的驱动器从边缘开始,无论是来自时钟还是来自其他信号,请使用非阻塞分配“&lt; =”
请勿使用生成的信号边沿生成其他信号。如上所述,为时钟部分中的所有内容使用时钟使用if。也不要从不同的'always'驱动信号。你永远不知道他们执行的顺序,然后你就有竞争条件。因此,清除和增量都在一个总是块中:
if (secCounter == 6'b111100) begin
minOut <= 1'b1;
secCounter <= 6'b0;
end
else
secCounter <= secCounter + 6'b000001;
由于时序方面,你现在必须转到59而不是60.这是你应该期待的,因为数字时钟和手表从00到59,而不是00到60.你可以使用十进制数,这将是,再次,使代码更具可读性:6'd59,4'd11