当然了,有经验的同学可能会发现上述代码中,out_clk_1、out_clk_2是从复位完成时开始同步的,长时间运行,可能会导致同步出错,两信号相或之后就会不是所要的结果。
那么,我们可以考虑改进上述代码。
本帖最后由 lcytms 于 2016-11-10 09:23 编辑
新建改进的任意分频模块divider2.v。
将改进的任意分频模块divider2.v设置为顶层模块。
将原有的显式建模方式改为隐式建模方式,原有生成out_clk_2时采用~clk作为时钟,现在改用negedge clk触发。
同步由原来的复位信号同步,改为cnt计数器同步。
这样避免了原有的长时间运行后同步出错可能性。
改进的任意分频模块divider2.v代码如下。
module divider2 (clk, rst_n, clk_out);
input clk, rst_n;
output clk_out;
parameter WIDTH = 3; // WIDTH = 3
wire HW, LW;
assign HW = WIDTH>>1;
assign LW = (WIDTH+1)>>1;
reg out_clk_1, out_clk_2;
reg state1, state2;
localparam s0 = 1'b0,
s1 = 1'b1;
reg cnt;
always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
cnt <= 0;
out_clk_1 <= 1;
state1 <= s0;
end
else
begin
case (state1)
s0 : begin // HW part
if (cnt < HW - 1)
begin
cnt <= cnt + 26'b1;
out_clk_1 <= 1;
state1 <= s0;
end
else
begin
cnt <= 0;
out_clk_1 <= 1;
state1 <= s1;
end
end
s1 : begin // LW part
if (cnt < LW - 1)
begin
cnt <= cnt + 26'b1;
out_clk_1 <= 0;
state1 <= s1;
end
else
begin
cnt <= 0;
out_clk_1 <= 0;
state1 <= s0;
end
end
default : state1 <= s0;
endcase
end
end
always @ (negedge clk or negedge rst_n)
begin
if (!rst_n)
begin
out_clk_2 <= 1;
state2 <= s0;
end
else
begin
case (state2)
s0 : begin // HW part
if (cnt < HW - 1)
begin
out_clk_2 <= 1;
state2 <= s0;
end
else
begin
out_clk_2 <= 1;
state2 <= s1;
end
end
s1 : begin // LW part
if (cnt < LW - 1)
begin
out_clk_2 <= 0;
state2 <= s1;
end
else
begin
out_clk_2 <= 0;
state2 <= s0;
end
end
default : state2 <= s0;
endcase
end
end
assign clk_out = (WIDTH & 1'b1) ? (out_clk_1 || out_clk_2) : out_clk_1;
endmodule
本帖最后由 lcytms 于 2016-11-9 21:14 编辑
新建Testbench。编写divider2_tb.v模块代码。
`timescale 1ns/1ps
module divider2_tb;
reg clk, rst_n;
wire clk_out;
divider2 #(.WIDTH(5)) dut (.clk(clk), .rst_n(rst_n), .clk_out(clk_out));
initial
begin
clk = 1;
rst_n = 0;
#200.1
rst_n = 1;
#2000 $stop;
end
always #10 clk = ~clk;
endmodule
本帖最后由 lcytms 于 2016-11-9 21:18 编辑
设置好仿真。
查看仿真波形。
WIDTH=5,此时分频次数为奇数次,仿真波形与设计要求相符。
通过修改参数WIDTH可以实现分频次数的调整。
修改WIDTH=6,此时分频次数为偶数次。
查看仿真波形,与设计要求相符。
好了,今天的课程就讲到这里。
通过今天的课程,我们学习了任意分频器的基本原理,并对任意分频器电路进行了建模和仿真检查。
希望大家建立对任意分频器的理解,并熟练运用Verilog语言编写驱动逻辑。
更复杂的知识和技巧我们将逐步通过后面的课程展现给大家。
课程到此结束,谢谢大家的关注!
FPGA初级课程第十讲 任意分频器
页:
1
[2]