对于偶次项n分频还是比较容易的如果。如果n是2的整数次幂,即n=2^m,可定义一个[m-1:0]的寄存器counter,对clk计数,分频输出取最高位assign div=counter[m-1]即可。如果不是2的整数次幂,2^(m-1)<n<2^m,也是定义一个[m-1:0]的寄存器counter,计数到n/2-1时,div反转即可。
对于奇数的分频可用以下的方法:
声明两个寄存器cnta和cntb,cnta在clk上升沿div时进行计数,cntb在clk下降沿是进行计数,div_a和div_b在cnta和cntb小于4时为高电平,然后两者或即可得到占空比为50%的七分频电路。
下面是verilog代码:
1 module fenping(clk,rst_n,div_a,div_b,div_out); 2 input clk; 3 input rst_n;4 output div_out; 5 output div_a,div_b; 6 reg[2:0] cnta; 7 always@(posedge clk or negedge rst_n) 8 if(!rst_n) 9 cnta<=0;10 else if (cnta==3'b110)11 cnta<=0;12 else13 cnta=cnta+1'b1;14 15 16 reg div_a;17 always@(posedge clk or negedge rst_n)18 if(!rst_n)19 div_a<=0;20 else if(cnta<3'b100)21 div_a<=1;22 else div_a<=0;23 24 reg[2:0] cntb;25 always@(negedge clk or negedge rst_n)26 if(!rst_n)27 cntb<=0;28 else if (cntb==3'b110)29 cntb<=0;30 else cntb=cntb+1'b1;31 32 reg div_b;33 always @(negedge clk or negedge rst_n)34 if(!rst_n)35 div_b<=0;36 else if(cntb<3'b100)37 div_b=1;38 else div_b=0;39 assign div_out=div_a|div_b;40 endmodule
用Altera-modelsim进行仿真,下面是testbench:
View Code
1 `timescale 1 ps/ 1 ps 2 module fenping_vlg_tst(); 3 reg eachvec; 4 reg clk; 5 reg rst_n; 6 wire div_a; 7 wire div_b; 8 wire div_out; 9 fenping i1 (10 .clk(clk),11 .div_a(div_a),12 .div_b(div_b),13 .div_out(div_out),14 .rst_n(rst_n)15 );16 initial 17 begin 18 clk=0;19 rst_n=0;20 #50 rst_n=1;21 forever22 #20 clk=~clk; 23 end 24 endmodule
仿真波形如下:
不知道大家有没有注意到我程序里13行和30行用了阻塞赋值:
13 cnta=cnta+1'b1;
30 cntb=cntb+1'b1;
这是不正确的,虽然仿真是结果是对的,但是不符合一般的规律,一般认为时序逻辑里用非阻塞赋值,组合逻辑里用阻塞赋值,一个always里是不能同时出现非阻塞赋值和阻塞赋值的。下面给出正确的v文件:
View Code
新手上路,如果有什么地方写的不对,请指出,谢谢! 1 module fenping(clk,rst_n,div_a,div_b,div_out); 2 input clk; 3 input rst_n; 4 output div_out; 5 output div_a,div_b; 6 reg[2:0] cnta; 7 always@(posedge clk or negedge rst_n) 8 if(!rst_n) 9 cnta<=0;10 else if (cnta==3'b110)11 cnta<=0;12 else13 cnta<=cnta+1'b1;14 15 16 reg div_a;17 always@(posedge clk or negedge rst_n)18 if(!rst_n)19 div_a<=0;20 else if(cnta<3'b011)21 div_a<=1;22 else div_a<=0;23 24 reg[2:0] cntb;25 always@(negedge clk or negedge rst_n)26 if(!rst_n)27 cntb<=0;28 else if (cntb==3'b110)29 cntb<=0;30 else cntb<=cntb+1'b1;31 32 reg div_b;33 always @(negedge clk or negedge rst_n)34 if(!rst_n)35 div_b<=0;36 else if(cntb<3'b011)37 div_b<=1;38 else div_b<=0;39 assign div_out=div_a|div_b;40 endmodule