做VGA方块碰撞实验时,发现一个计数器的问题。如果我们需要设计一个计数器,它先递增,递增到一定数后开始递减,递减到一定数后又递增,循环反复,应该怎么设计呢?这个思想在很多地方都能用到,如PWM呼吸灯、VGA方块回弹等。这里给出一个设计方法。
要求:
设计一个数x,它先递增10次,然后递减10次,又递增10次,循环反复。
代码:
1 module count 2 //---------------------<端口声明>------------------------------------------- 3 ( 4 input wire clk , //时钟,50Mhz 5 input wire rst_n , //复位,低电平有效 6 output reg [3:0] x , 7 output reg flag_x 8 ); 9 10 //-------------------------------------------------------------------------- 11 //-- 程序开始 12 //-------------------------------------------------------------------------- 13 always @(posedge clk or negedge rst_n) begin 14 if (!rst_n) 15 x <= 0; 16 else if(flag_x==0 && x<9) 17 x <= x + 1; 18 else if(flag_x==1 && x>0) 19 x <= x - 1; 20 end 21 22 always @(posedge clk or negedge rst_n) begin 23 if (!rst_n) 24 flag_x <= 0; 25 else if(flag_x==0 && x==9) 26 flag_x <= 1; 27 else if(flag_x==1 && x==0) 28 flag_x <= 0; 29 end 30 31 32 33 endmodule
仿真波形:
可以看到,波形显示flag_x为0时,x的数值为:0,1,2,3,4,5,6,7,8,9,接着flag_x拉高为1,x的数值变为:9,8,7,6,5,4,3,2,1,0,接着又是一轮循环。我们的设计成功了!
后记:
一开始设计时没有在x的触发条件那加上 x<9 和 x>0 ,结果导致x会多计一下,最终功能上有所欠缺,原因是x和flag_x两个always块并行跑,如果不加那个限制条件,那flag_x刚刚拉高时,x同步变化,实际上还是执行的上一轮限制条件,最终导致结果出错。而加了限制条件后,这个问题就解决了。