原创 关于分频的概念

2009-8-12 00:33 2902 6 6 分类: FPGA/CPLD

今天写教程,写到一半做仿真的时候卡了壳,结果翻了很多的书,感觉总是哪里有点问题。


夏老师《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条评论)

登录后参与讨论
我要评论
0
6
关闭 站长推荐上一条 /3 下一条