今天写教程,写到一半做仿真的时候卡了壳,结果翻了很多的书,感觉总是哪里有点问题。
夏老师《Verilog数字系统设计教程》书后练习题中有这么一个练习(练习三):实现1/20分频。我的书是第一版的,上面的写法是很经典的,也是我一向喜欢写的代码形式。
但是仿真出来的结果好像不太对,每个时钟的上升沿触发一次计数,记数到19的时候翻转输出信号。这个时候的输出信号的周期应该是20+20=40次,实际的结果应该是40才对。
不知道我今天是不是有点累晕了,这个概念反反复复不知道对不对。按照我的理解,20分频就应该是输出的信号频率是输入信号频率的1/20,周期是其20倍才对。所以在一个沿触发,计数值应该是“分频系数/2 - 1”(初值为0的情况)才对。
下面是一个6分频的波形图:
从图中可以看出,应该是计数三次之后输出信号翻转一次。所以我感觉夏老师的书好像有点问题,不知道第二版是不是不一样了。当然,这个写法和概念也让我用了多年,但是好像也没出什么大问题……
教程前面的代码好像也就是LED闪烁,间隔的时间倒是不用除2减1,因为那个间隔周期正好是计数值所需要的时间。
关于技术分频,当然需要在上升沿和下降沿同时触发,但是clk的上升沿和下降沿不能用一个always块,与此同时用于计数的reg型变量只能在一个always块中赋值,所以需要用一些过渡的手段来处理输出信号,而不能简单的计数后输出。
所以才会有针对奇数分频的一些代码和技巧,我找了下以前上学时候写的一个三分频,好像还可以用,没有仔细看里面代码是怎么样写的了,太古老了
module div3(clkin,clkout,rstn);
input clkin,rstn;
output clkout;
reg clkout1,clkout2;
wire clkout;
reg [1:0] counter,counter2;
always @(posedge clkin or negedge rstn)
begin
if (!rstn)
begin
counter<=2'b0;
clkout1<=0;
end
else
case(counter)
1: counter<=counter+1;
0: begin
clkout1<=~clkout1;
counter<=counter+1;
end
2: begin
clkout1<=~clkout1;
counter<=0;
end
endcase
end
always @(negedge clkin or negedge rstn)
begin
if (!rstn)
begin
counter2<=2'b0;
clkout2<=0;
end
else
case(counter2)
1: counter2<=counter2+1;
0: begin
clkout2<=~clkout2;
counter2<=counter2+1;
end
2: begin
clkout2<=~clkout2;
counter2<=0;
end
endcase
end
assign clkout="clkout1"&&clkout2;
endmodule
文章评论(0条评论)
登录后参与讨论