实验任务与需求分析
本次设计目标是在FPGA平台上实现一个可控分频器模块,其功能定义如下:
- 核心功能:模块输入一个频率固定的50MHz时钟信号 (
clk_in),通过分频产生一个可变的输出时钟信号 (clk_out)。
- 控制逻辑:通过一个选择开关 (
sel) 控制输出频率。
- 当
sel = 0 时,clk_out 输出频率为 sn[3:0] Hz。
- 当
sel = 1 时,clk_out 输出频率为 sn[4:1] Hz。
- (说明:
sn 为学号,sn[3:0] 表示学号的最后四位十进制数)。
- 占空比要求:输出时钟
clk_out 的占空比 (Duty Cycle) 需固定为 60%,即高电平时间占整个周期的60%。
设计原理与实现步骤
分频与计数原理
分频的本质是通过对高频时钟周期进行计数,达到设定计数值后产生一个完整的输出周期。这涉及到基础的计数算法。核心计算公式如下:
- 分频计数值 (N):
N = f_in / f_out - 1
f_in 为输入时钟频率 (50MHz = 50,000,000 Hz)。
f_out 为期望输出频率 (例如 5407 Hz)。
- 高电平计数值 (TH):
TH = N * Duty_Cycle
Duty_Cycle 为占空比 (60% = 0.6)。
以 f_out = 5407 Hz 为例计算:
- 分频计数值
N = 50,000,000 / 5407 ≈ 9247
- 高电平计数值
TH = 9247 * 0.6 ≈ 5548
以 f_out = 1540 Hz 为例计算:
- 分频计数值
N = 50,000,000 / 1540 ≈ 32468
- 高电平计数值
TH = 32468 * 0.6 ≈ 19481
核心模块代码实现
基于以上原理,设计一个包含计数器和输出逻辑的Verilog模块。关键点在于使用参数 (parameter) 定义两个分频模式下的 N 和 TH 值,并通过 sel 信号进行选择。
// 可控分频器模块
module yqh_5407_5_1(
input clk_in, // 50MHz 输入时钟
input sel, // 频率选择 (0: sn[3:0], 1: sn[4:1])
input clr, // 异步清零,低电平有效
output reg [14:0] cnt, // 内部计数器,用于观察
output reg clk_out // 分频后输出
);
// 参数定义:根据计算得到的计数值
parameter N0 = 15'd9247; // sel=0 时的分频系数 (5407Hz)
parameter TH0 = 15'd5548; // sel=0 时的高电平计数 (60%占空比)
parameter N1 = 15'd32468; // sel=1 时的分频系数 (1540Hz)
parameter TH1 = 15'd19481; // sel=1 时的高电平计数 (60%占空比)
always @(posedge clk_in or negedge clr) begin
if(!clr) begin // 异步复位
cnt <= 15'd0;
clk_out <= 1'b1; // 复位后输出高电平
end else begin
if(!sel) begin // sel=0 模式
if(cnt < N0) begin
cnt <= cnt + 15'b1;
// 实现60%占空比:计数值小于TH0时输出高,否则输出低
clk_out <= (cnt < TH0) ? 1'b1 : 1'b0;
end else begin
cnt <= 15'd0; // 计数满,归零开始新周期
end
end else begin // sel=1 模式
if(cnt < N1) begin
cnt <= cnt + 15'b1;
clk_out <= (cnt < TH1) ? 1'b1 : 1'b0;
end else begin
cnt <= 15'd0;
end
end
end
end
endmodule
测试验证
为了验证模块功能,编写一个简单的测试平台(Testbench),对 sel 和 clr 信号进行时序控制,并观察输出波形。
`timescale 1ns/1ns // 时间单位/精度
module test_yqh_5407_5_1;
reg clk_in;
reg sel;
reg clr;
wire [14:0] cnt;
wire clk_out;
// 实例化被测模块
yqh_5407_5_1 uut (
.clk_in(clk_in),
.sel(sel),
.clr(clr),
.cnt(cnt),
.clk_out(clk_out)
);
// 生成50MHz时钟 (周期20ns)
always begin
#10 clk_in = ~clk_in;
end
initial begin
// 初始化信号
clk_in = 1'b0;
sel = 1'b0; // 初始选择模式0
clr = 1'b0; // 初始处于复位状态
#200; // 等待一段时间
end
always begin
// 测试模式0 (输出5407Hz)
clr = 1'b1; // 释放复位
sel = 1'b0;
#400000000; // 仿真约0.4秒进行观察
// 测试模式1 (输出1540Hz)
sel = 1'b1;
#400000000;
// 测试复位功能
clr = 1'b0; // 触发复位
#400000;
clr = 1'b1; // 释放复位
#400000000;
$finish; // 结束仿真
end
endmodule
总结
本设计通过一个可配置的计数器,成功实现了基于FPGA的可控分频器。设计要点在于根据输入/输出频率关系准确计算分频系数,并通过比较器逻辑精确控制输出信号的占空比。这种参数化的设计方法使得模块具有良好的可重用性,只需修改 parameter 值即可适配不同的分频需求。理解此类时序逻辑的设计,对于掌握网络与系统中的时钟管理与信号同步至关重要。
|