- 论坛徽章:
- 0
|
在verilog中,实现边缘触发清零计数器时。综合的时候会有很多限制: 1、在多个always语句中,不能对同一个变量进行赋值。 2、如果在一个always条件加上两个边缘触发条件时,写法又似乎有一定的要求。 必须使用异步复位的方法清零,否则使用同步复位会因为赋值的延时带来一个时钟周期的延时。 反复试验得到一个勉强可以使用的代码如下:
- module counter(clk,rst,cnt_out,reset);
-
input clk,rst;
-
output cnt_out;
-
output reset;
-
reg rst_last/*synthesis noprune*/;
-
reg [7:0] cnt;
-
reg cnt_out;
-
reg reset;
-
wire mclk;
-
-
pll p0(clk,mclk);
-
-
initial
-
begin
-
cnt=255;
-
cnt_out=1;
-
end
-
-
always@(posedge mclk)
-
begin
-
rst_last=rst;
-
end
-
-
always@(posedge mclk or negedge rst)
-
begin
-
if(!rst)
-
begin
-
if(rst_last)
-
reset=0;
-
else
-
reset=1;
-
end
-
end
-
-
always@(posedge mclk or negedge reset)
-
begin
-
if(!reset)
-
cnt=0;
-
else if(cnt!=255)
-
cnt=cnt+1;
-
end
-
-
always@(cnt)
-
begin
-
if(cnt==255)
-
cnt_out=1;
-
else
-
cnt_out=0;
-
end
-
-
endmodule
在上述代码中rst为输入信号,下降沿时计数器清零。 此外设置了reset变量,reset在rst下降沿时置0,并保持一个周期。 计数器变量则捕捉reset的下降沿,并且在reset为0时清零。 最终达到rst下降沿时计数器立即清零的效果,signaltap得到的图如下:
 从图中可以看到,rst下降时,cnt立即置0。但cnt的计数周期会增加一个时钟周期。 因为reset=1的赋值有一定的延时,而同时cnt取reset的值进行判断此时reset仍为0。硬件中的这种延时感觉真让人蛋疼...
|
|