Verilog 时序逻辑

信号发生器

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

仿真图如下:
在这里插入图片描述

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值