信号发生器
Verilog 代码
`timescale 1ns/1ns
module signal_generator(
input clk,
input rst_n,
input [1:0] wave_choise, output reg [4:0]wave
);
reg [4:0] cnt;
reg k;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt <= 5'd0;
wave <= 5'd0;
end
else begin
case(wave_choise)
2'd0:begin
if(cnt == 5'd19) begin
cnt <= 5'd0;
wave <= 5'd0;
end
else if(cnt>=5'd9 && cnt<5'd19)begin
cnt <= cnt + 1'b1;
wave <= 5'd20;
end
else begin
cnt <= cnt + 1'b1;
wave <= 5'd00;
end
end
2'd1:begin
if(wave >= 5'd20)
wave <= 5'd0;
else
wave <= wave + 1'b1;
end
2'd2:begin
if(wave == 5'd0) begin
k <= 1'b0;
wave <= wave + 1'b1;
end
else if(wave == 5'd20) begin
k <= 1'b1;
wave <= wave - 1'b1;
end
else if(k == 1'b0 && wave < 5'd20)
wave <= wave + 1'b1;
else if(k == 1'b1 && wave > 5'd0)
wave <= wave - 1'b1;
else
wave <= wave - 1'b1;
end
default:begin wave <= wave;end
endcase
end
end
endmodule
仿真波形:
wave_choise :
00 输出方波
01 输出锯齿波
10 输出三角波
Format /Radix相应设置如下,可得到波形
clock_section
利用寄存器计数,取寄存器各个位下 0 / 1 转换,产生不同频率的 CLK enable 脉冲。
CLK_EN_5M_Hz
Verilog 代码:
`timescale 1ns/1ns
module clock_5M (
input main_clk, // 20.46MHz
input cpld_reset_, output clk_en_10m
);
reg [3:0] div_1m_count;
always @(posedge main_clk or negedge cpld_reset_)
begin
if(!cpld_reset_)
begin
div_1m_count <= 4'b0;
end
else if(div_1m_count[1] & div_1m_count[0])
begin
div_1m_count <= 4'b0;
end
else begin
div_1m_count <= div_1m_count + 1'b1;
end
end
assign clk_en_10m = div_1m_count[1];
endmodule
仿真波形如下:
取了一个 4 位寄存器做计数器,div_1m_count:00,01,10,11 之间循环。
clk_en_10m 电位高低跟随 div_1m_count 的第一位变化;
div_1m_count[0]频率 = main_clk 频率 / 2 = 20.46 MHz / 2 = 10.23MHz
div_1m_count[1]频率 = main_clk 频率 / 4 = 20.46 MHz / 4 = 5.115MHz
clk_en_10m 频率 = div_1m_count[1]频率 = 5.115MHz
div_count_1m
reg [8:0] div_count_1m;
always @(posedge main_clk or negedge cpld_reset_)
begin
if(!cpld_reset_)
begin
div_count_1m <= 9'b0;
end
else if(clk_en_10m)
begin
div_count_1m <= div_count_1m + 1'b1;
end
else if(div_count_1m[6] & div_count_1m[0])
begin
div_count_1m <= 9'b0;
end
else begin
div_count_1m <= div_count_1m;
end
在 clk_en_10m = 1 的时候,div_count_1m 计数;
clk_en_10m = 0 的时候,div_count_1m 保持,main_clk 频率 = 20.46M Hz, clk_en_10m 频率 = 5.115M Hz;
clk_en_10m = 1, div_count_1m 计数;
两个 main_clk,clk_en_10m = 0 的时候,div_count_1m 保持两个 main_clk,一直计数到 65d 循环。
clk_en_2_5M
clk_en_80k_dly <= {clk_en_80k_dly[0], div_count_1m[1]};
clk_en_80k_init <= clk_en_80k_dly[0] & ~clk_en_80k_dly[1];
assign clk_en_2_5M = clk_en_80k_init;
clk_en_10m = 1, div_count_1m 从 00 开始计数;
两个 main_clk,clk_en_10m = 0 的时候,div_count_1m 保持两个 main_clk,div_count_1m[1:0]循环如下:
div_count_1m[1:0]= 00/01 / 10 / 10 / 10 /11 / 00 / 00 / 00 /01 ….一个循环耗时 8 个 main_clk。
clk_en_80k_dly = 01 的时候,clk_en_80k_init 为 1;clk_en_80k_init 的频率为:20.46 / 8 = 2.5M Hz
clk_en_1m
clk_en_1m_dly <= {clk_en_1m_dly[0], div_count_1m[2]};
clk_en_1m_init <= clk_en_1m_dly[0] & ~clk_en_1m_dly[1];
assign clk_en_1m = clk_en_1m_init;
与 clk_en_2_5M 产生自同一个寄存器 div_count_1m,利用 div_count_1m 第 2 位的变化产生一个 clk_en_1m enable 脉冲;
clk_en_1m 周期为 16 个 main_clk;clk_en_1m 频率为 20.46 MHz/ 16 = 1.27 MHz
其他频率的 clk enable 产生与上述方法相同,就不在赘述。
源时钟分频
200KHz 源时钟的 2 分频,4 分频,8 分频
利用加法器的二进制之间不通位次的跳变实现。
源码如下:
`timescale 1ns/1ns
module clock_2_4_8 (
input clk_200k,
input rst_n, output clk_2_out, output clk_4_out, output clk_8_out
);
reg [2:0] cnt;
always @(posedge clk_200k or negedge rst_n)
if(! rst_n)
cnt <=2'b000;
else
cnt <= cnt + 1 ;
assign clk_2_out = cnt[0];
assign clk_4_out = cnt[1];
assign clk_8_out = cnt[2];
endmodule
仿真图如下:
分频就是用同一个时钟信号通过一定的电路结构转变成不同频率的时钟信号。
二分频是在时钟每触发 2 个周期时,电路输出 1 个周期信号;
四分频是在时钟每触发 4 个周期时,电路输出 1 个周期信号;
八分频是在时钟每触发 8 个周期时,电路输出 1 个周期信号。
源时钟的 3 分频
源码如下:
`timescale 1ns/1ns
module clock_3(
input clk,
input rst_n, output clk_out
);
reg [1:0] state;
reg clk1;
always @(posedge clk or negedge rst_n)
if(! rst_n)
state <= 2'b00;
else
case(state)
2'b00: state <= 2'b01;
2'b01: state <= 2'b11;
2'b11: state <= 2'b00;
default:state <= 2'b00;
endcase
always @(negedge clk or negedge rst_n)
if(! rst_n)
clk1 <= 1'b0;
else
clk1 <= state[0];
assign clk_out = state[0] & clk1;
endmodule
仿真图如下:
三分频是在时钟每触发 3 个周期时,电路输出 1 个周期信号。
分析:
与偶数倍分频不同,奇数分频用 case 语句实现。
case 语句中的执行条件是 posedge clk,clk1 的执行条件是 negedge clk,两个 always 同时执行且相差半个 clk,由此输出周期可以按 clk 的半个周期计算。
那么三分频需要3 个clk 周期,6 个 clk 半周期,且三个 clk 半周期高,三个 clk 半周期低。
最后由 case 编写三种状态的循环语句,三种状态就有 3 个 clk 周期,6 个 clk 半周期,其中 state[0] 4 个 clk 半周期高,2 个 clk
半周期低,clk1 中延迟的一个 clk 半个周期和 state[0] 与门计算,得到三个 clk 半周期高和三个 clk 半周期低。
奇数数倍分频都可以用这种方法实现,例如下面的五分频。
源时钟的 5 分频
源码如下:
`timescale 1ns/1ns
module clock_5 (
input clk,
input rst_n, output clk_out
);
reg [2:0] state;
reg clk1;
always @(posedge clk or negedge rst_n)
if(! rst_n)
state<=2'b000;
else
case(state)
3'b000: state <= 3'b001;
3'b001: state <= 3'b011;
3'b011: state <= 3'b111;
3'b111: state <= 3'b010;
3'b010: state <= 3'b000;
default:state <= 3'b000;
endcase
always @(negedge clk or negedge rst_n)
if(! rst_n)
clk1 <= 1'b0;
else
clk1 <= state[0];
assign clk_out = state[0] & clk1;
endmodule
仿真图如下: