一、实验分析与设计原理
设计一个可控分频器,clk_in 为分频器时钟输入(50MHz)。
sel 为选择开关,clk_out[1:0]为分频器信号输出。sn[3:0]为四位数字。
当 sel=0 时,clk_out[0]=sn[3:0]Hz,clk_out[1]=sn[3:0]/2Hz;
当 sel=1 时,clk_out[0]=sn[3:0]Hz,clk_out[1]=sn[3:0]/5Hz。
可知,有输入clk_in、sel;输出clk_out[1:0]。
本实验需要通过给定的时钟信号clk_in,分频出频率小于输入时钟信号的输出信号clk_out。
通过输出信号的频率sn,可以计算出一个输出信号的周期需要多少个输入信号的周期。
例:当sn=1234Hz时,通过50MHz / 1234Hz = 40518可得,当输入信号经过40518个周期,输出信号经过一个周期。当占空比为50%时,输出信号每经过40518 / 2个周期,输出信号翻转一次。
实验有两个输出和三种输出频率,所以需要两个计数器分别记录两个输出,以及三个常数确定输出频率需要的输入信号的周期。
对于clk_out[0],sel的取值不影响其频率,所以可以将其从sel的选择语句中独立出来。
对于clk_out[1],通过if选择语句,可以输出对应的频率。
二、代码编写
程序代码
L0、L1、L2分别表示三种输出频率需要的输入信号的周期数;i0、i1为两个计数器值。
每当i0(i1)计数到L0(L1、L2)时,将输出信号clk_out[0](clk_out[1])翻转一次。
module Test(clk_in,clk_out,sel);
input clk_in; //50MHz输入
input sel; //选择信号
output reg[1:0]clk_out = 2'b00; //分频器输出信号
parameter sn = 1234; //分频后频率
parameter L0 = 50000000/sn/2; //snHz需要的信号翻转的计数次数
parameter L1 = L0*2; //sn/2Hz需要的信号翻转的计数次数
parameter L2 = L0*5; //sn/5Hz需要的信号翻转的计数次数
integer i0 = 1, i1 = 1; //clk_out[0]、clk_out[1]计数
always@(posedge clk_in)
begin
//由于clk_out[0]频率不变,所以将其单独独立出来
if(i0 >= L0) //达到snHz需要的计数次数
begin
i0 <= 1; //计数器重置
clk_out[0] <= ~clk_out[0]; //输出信号翻转
end
else i0 <= i0 + 1; //计数器加一
if(sel==0)
begin
if(i1 >= L1) //达到sn/2Hz需要的计数次数
begin
i1 <= 1; //计数器重置
clk_out[1] <= ~clk_out[1]; //输出信号翻转
end
else i1 <= i1 + 1; //计数器加一
end
else
begin
if(i1 >= L2) //达到sn/5Hz需要的计数次数
begin
i1 <= 1;
clk_out[1] <= ~clk_out[1];
end
else i1 <= i1 + 1; //计数器加一
end
end
endmodule
三、ModelSim仿真
1、Test Bench文件
时间单位为1ns,输入信号clk每隔10个时间单位翻转一次,使输入信号的频率为50MHz。
初始sel为0,输出一种频率;延时5ms后,sel为1,输出另一种频率。
`timescale 1 ns/ 1 ns
module Test_vlg_tst();
reg clk_in;
reg sel;
wire [1:0] clk_out;
Test i1 (
.clk_in(clk_in),
.clk_out(clk_out),
.sel(sel)
);
initial
begin
clk_in = 0;
sel = 0;
#5000000
sel = 1;
$display("Running testbench");
end
always#10 clk_in = ~clk_in;
endmodule
2、波形图
温馨提示:基础操作可以查看本专栏中的其他博客。