【笔记】精密计数
参考<<verilog那些事儿-时序篇>>
module counter_module ( input CLK, input RSTn, output _1US, output _3US, output _is1US, output _is3US, output [4:0]C1, output [5:0]C2 ); /*******************************/ parameter T1US = 5'd20; /*******************************/ reg [4:0]Count_1US; reg is1US; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin Count_1US <= 5'd0; is1US <= 1'b0; end else if( Count_1US == T1US ) begin Count_1US <= 5'd0; is1US <= 1'b1; end else begin Count_1US <= Count_1US + 1'b1; is1US = 1'b0; end /*******************************/ parameter T3US = 6'd60; /*******************************/ reg [5:0]Count_3US; reg is3US; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin Count_3US <= 6'd0; is3US <= 1'b0; end else if( Count_3US == T3US ) begin Count_3US <= 6'd0; is3US <= 1'b1; end else begin Count_3US <= Count_3US + 1'b1; is3US <= 1'b0; end /*******************************/ assign _1US = ( Count_1US == T1US ) ? 1'b1 : 1'b0; assign _3US = ( Count_3US == T3US ) ? 1'b1 : 1'b0; assign _is1US = is1US; assign _is3US = is3US; assign C1 = Count_1US; assign C2 = Count_3US; /*******************************/ endmodule
仿真源代码
`timescale 1 ns/ 1 ps module counter_module_simulation(); reg CLK; reg RSTn; wire _1US; wire _3US; wire _is1US; wire _is3US; wire [4:0]C1; wire [5:0]C2; /************************/ counter_module i1 ( .CLK(CLK), .RSTn(RSTn), ._1US(_1US), ._3US(_3US), ._is1US( _is1US ), ._is3US( _is3US ), .C1( C1 ), .C2( C2 ) ); /************************/ initial begin RSTn = 0; #1000; RSTn = 1; CLK = 0; forever #25 CLK = ~CLK; end /************************/ endmodule
在quartusII里面setting -- simulation
在Test Benches里面添加所写的仿真代码,设置完成后点击ok
仿真结果
可以发现_1US用了0.95us,is_1US用了1us
这里强调的是
1:assign _1US = ( Count_1US == T1US ) ? 1'b1 : 1'b0;
2: else if( Count_1US == T1US ) //T1US定义的常量是20哦,why?1us / 50ns = 20 (这里50位一个时钟周期)
begin Count_1US <= 5'd0; is1US <= 1'b1; end
assign _is1US = is1US; //上面的is1US一变化这里的_is1US就马上就变化了,实际上就是起到连线的作用而已
不一样的,两者相差一个时钟,切记切记。
下面的例子理解到模块的沟通要用到一个时钟的
modulecounter
(
......
output_1US, // 由组合逻辑驱动
output_is1US // 有寄存器驱动
);
parameterT1US=5'd20; // 时钟频率20Mhz
......
assign_1US=(Count_US==T1US) ?1'b1:1'b0;
assign_is1US=is1US;
endmodule
moduleled
(
......
input_1US,
input_is1US
);
case(i)
0,1,2,3,4,5,6,7:
if(_1US)beginLED_A<=(4'h01<<i);i<=i+1'b1;end
......
case(j)
0,1,2,3,4,5,6,7:
if(_is1US)beginLED_B<=(4'h01<<j );j<=j+1'b1;end
......
endmodule
如果根据“模块之间沟通”的规则,由寄存器驱动的1us定时信号_is1US,是满1us
之后就产生定时信号,然而模块的沟通需要至少一个时钟,所以LED_B的流水灯效果,
实际上是1.00us+0.05us。反之,由组合逻辑驱动的1us定时信号_1US,在满1us前
一个时钟就产生定时信号了,然而模块的沟通至少需要一个时钟,所以LED_A的流水
灯效果是0.95us+0.05us,亦即准1us。