//偶数分频的两种方法
//1.寄存器法实现2^n分频,有clk上升沿则翻转
//2.计数器法可以实现任意偶数分频
1.首先按照自己的想法写,写出来是一个计数器二分频,实现了基本的波形。
module twofd (clk,rst,clk1);
//偶数分频的两种方法
//1.寄存器法实现2^n分频,有clk上升沿则翻转
//2.计数器法可以实现任意偶数分频
input clk,rst;
output clk1;
reg [1:0] clk1r;
reg [1:0] count;
assign clk1=clk1r;
//这里还是用寄存器给输出赋值
initial begin clk1r<=2'd0; count<=2'd0; end
always @(posedge clk or negedge rst)
if(!rst)
begin clk1r<=2'd0; count<=2'd0; end
else if(count==2'd0)
begin clk1r=!clk1r; count<=count+2'd1; end
else if(count==2'd1)
begin clk1r=!clk1r; count<=2'd0; end
endmodule
`timescale 1ps/1ps
module twofdtest;
reg clk,rst;
wire clk1;
twofd t1(.clk(clk), .rst(rst), .clk1(clk1));//这里也要分号。
always #5 clk=~clk;
always
begin
clk=0;rst=1;
#10 rst=0;
#15 rst=1;
#100 $stop;
end
endmodule
2.接下来按照寄存器的思想做一个二分频。测试模块的输出clk1不能被定义为reg型。
module twofd (clk,rst,clk1);
input clk,rst;
output reg [1:0] clk1;
initial clk1<=2'd0;
always @(posedge clk or negedge rst)
if(!rst)
clk1<=2'd0;
else clk1=!clk1;
endmodule
`timescale 1ps/1ps
module twofdtest;
reg clk,rst;
wire clk1;
twofd t1(.clk(clk), .rst(rst), .clk1(clk1));//这里也要分号。
always #5 clk=~clk;
always
begin
clk=0;rst=1;
#10 rst=0;
#15 rst=1;
#100 $stop;
end
endmodule
3.扩展到2^n分频的寄存器偶数分频,n每多1就要把前面的n-1次分频都做出来,然后取n-1分频的上升沿重复操作
module twofd (clk,rst,clkn);
//想要做一个2^n分频的怎么做呢?
//先做一个2^(n-1)分频的,然后对这个进行重复的操作
input clk,rst;
output reg [1:0] clkn;
reg [1:0] clk1;
parameter n=2'd2;
initial begin clk1<=2'd0; clkn<=2'd0; end
always @(posedge clk or negedge rst)
if(!rst)
clk1<=2'd0;
else clk1=!clk1;
always @(posedge clk1 or negedge rst)
if(!rst)
clkn<=2'd0;
else clkn=!clkn;
endmodule
`timescale 1ps/1ps
module twofdtest;
reg clk,rst;
wire clkn;
twofd t1(.clk(clk), .rst(rst), .clkn(clkn));//这里也要分号。
always #5 clk=~clk;
always
begin
clk=0;rst=1;
#10 rst=0;
#15 rst=1;
#100 $stop;
end
endmodule
4.最后是用计数器实现任意偶数分频的做法 ,不给定初始值的话则输出x
module twofd (clk,rst,clk1);
input clk,rst;
output [2:0] clk1;
reg [2:0] clk1r;
reg [2:0] count;
assign clk1=clk1r;
parameter N=6;
//不给初始值试试
always @(posedge clk or negedge rst)
if(!rst)//rst为0,全部清0
begin clk1r<=3'd0; count<=2'd0; end
else if(count==2'd0)
begin clk1r<=!clk1r; count<=count+2'd1; end
else if(count==N/2)
begin clk1r<=!clk1r; count<=count+2'd1; end
else if(count==N-2'd1)
count<=2'd0;
else count<=count+2'd1;
endmodule
//第一次做出来是一个3/4的四分频,检查后发现是count的位数只有2位,不够计数到5
5.看看大佬的代码反思,定义N的时候也要直接给出位数,可以试试用逻辑或把两个翻转点合在一起写else if(count==3'd0||count==N/2)。
6.最后是用状态机实现不考虑占空比为50%的任意偶数分频。奇怪的是不给输出一个初始值就没有输出,不是给状态,也不是给count。
module twofd (clk,rst,clk1);
input clk,rst;
output clk1;
reg clk1r;
reg [2:0] count;
reg [2:0] state;
assign clk1=clk1r;
parameter stop=3'b000,one=3'b001,two=3'b010,three=3'b011,four=3'b100,five=3'b101;
initial begin state<=stop; count<=3'd3; clk1r<=0; end
always @(posedge clk or negedge rst)
if(!rst)
begin
state<=stop;
count<=3'd0;
end
else
case(state)
stop: if(count==3'd0)
begin state<=one;count<=count+3'd1;clk1r<=!clk1r; end
else state<=stop;
one: if(count==3'd1)
begin state<=two;count<=count+3'd1;clk1r<=!clk1r; end
else state<=one;
two: if(count==3'd2)
begin state<=three;count<=count+3'd1; end
else state<=two;
three: if(count==3'd3)
begin state<=four;count<=count+3'd1; end
else state<=three;
four: if(count==3'd4)
begin state<=five;count<=count+3'd1; end
else state<=four;
five: if(count==3'd5)
begin state<=stop;count<=3'd0; end
else state<=five;
default state<=3'bxxx;
endcase
endmodule
`timescale 1ps/1ps
module twofdtest;
reg clk,rst;
wire clk1;
twofd t1(.clk(clk), .rst(rst), .clk1(clk1));
always #5 clk=~clk;
always
begin
clk=0;rst=1;
#10 rst=0;
#15 rst=1;
#90 rst=0;
#110 rst=1;
#200 $stop;
end
endmodule