FPGA学习笔记:Verilog利用计数器发生信号

一、实验内容

1.等占空比信号发生:计数器计时1ms,使LED灯每隔1ms状态翻转一次,实现LED灯闪烁,产生周期为2ms、占空比50%的方波信号;
2.非等占空比信号发生:计时器计时1.8ms,LED灯亮1ms,灭0.8ms,产生周期为1.8ms、非等占空比的方波信号;
3.序列型脉冲信号产生:生成1011010011的序列脉冲信号,每个脉冲信号时间为1us;

二、计数器最大值计算

当Rst_n复位信号被拉低时,计数值清零;复位信号被拉高时,计数器从0开始计数,在每个Clk时钟上升沿到来时自增1。
以50Mhz的系统时钟为例,时钟周期为20ns,即两个Clk时钟上升沿间隔为20ns,因此计数器每20ns计数一次。要实现1ms计时,则需要计数1ms/20ns=50000次,由于计数器从0开始计数,故1ms计时的计数器最大值为50000-1=49999。得出计数器最大值的计算公式:
计数器最大值 = 计数时间 / 系统时钟周期 − 1 计数器最大值=计数时间/系统时钟周期-1 计数器最大值=计数时间/系统时钟周期1

三、等占空比信号发生

1.单一信号发生

使LED灯每隔1ms状态翻转一次,产生周期为2ms的方波信号,代码如下:

module cntled(
	input Clk,			//系统时钟
	input Rst_n,		//系统复位
	output reg led		//LED端口
);
	reg [15:0] cnt;
	always@(posedge Clk or negedge Rst_n)
		if(!Rst_n)
			cnt <= 0;
		else if(cnt == 49999)//(49999+1)*20=1000000ns=1ms
			cnt <= 0;
		else
			cnt <= cnt + 1'b1;
	always@(posedge Clk or negedge Rst_n)
		if(!Rst_n)
			led <= 0;
		else if(cnt == 49999)
			led <= ~led;
endmodule

仿真文件:

`timescale 1ns/1ns
module cntled_tb();
	reg Clk,Rst_n;
	wire led;
	cntled cntled(
		.Clk(Clk),
		.Rst_n(Rst_n),
		.led(led)
	);
	initial Clk = 1;
	always #10 Clk = ~Clk;
	initial begin
		Rst_n = 0;
		#200;
		Rst_n = 1;
		#10000000;
		$stop;
	end
endmodule

仿真结果:
2ms方波

2.多个信号发生

三个LED灯,使其分别按1ms、500us、250us的速率翻转。
根据上述内容,计算出三个计数器的最大值分别为49999、24999、12499,为了实现多次调用模块,在代码中添加cnt_max,通过更改cnt_max改变计数器的计数时间,cnt_max可以设置为模块端口,也可以设置为全局常量,在此提供三种方法。

//cnt_max设置为模块端口
input [15:0] cnt_max;
//cnt_max设置为全局常量
parameter cnt_max = 49999;

在对计数器模块例化时,对cnt_max赋值,以改变计数器的计数时间,模块cntled1将cnt_max设置为端口,模块cntled2将cnt_max设置为全局常量,例化代码如下:

//方法1: 直接添加为模块端口
	cntled1 test0(
		.Clk(Clk),
		.Rst_n(Rst_n),
		.cnt_max(49_999),
		.led(led1)
	);
//方法2: 添加常量,在例化时对常量赋值	
	cntled2
		#(
		.cnt_max(24_999)
		)
	test1(
		.Clk(Clk),
		.Rst_n(Rst_n),
		.led(led2)
	);			
//方法3: 添加常量,在例化后对常量赋值
	cntled2 test2(
		.Clk(Clk),
		.Rst_n(Rst_n),
		.led(led3)
	);	
	defparam test2.cnt_max = 12_499;

仿真结果:
在这里插入图片描述

四、非等占空比信号发生

LED灯亮1ms,灭0.8ms,产生周期为1.8ms、非等占空比的方波信号,代码如下:

module cntled3(Clk,Rst_n,led);
	input Clk,Rst_n;
	output reg led;
	reg [16:0] cnt;
	always@(posedge Clk or negedge Rst_n)
		if(!Rst_n)
			cnt <= 0;
		else if(cnt == 89_999)	//1.8ms
			cnt <= 0;
		else
			cnt <= cnt + 1'b1;
	always@(posedge Clk or negedge Rst_n)
		if(!Rst_n)
			led <= 0;
		else if(cnt < 50_000)	//1ms
			led <= 0;
		else					//0.8ms
			led <= 1;		
endmodule

仿真结果:
在这里插入图片描述

五、序列型脉冲信号产生

生成1011010011的序列脉冲信号,每个脉冲信号时间为1us。
共10个脉冲信号,故设置计数时间为10us,用序列机判断cnt的计数值,每计50个数时更改信号的输出值,即在cnt为0、49、99、149、199、249、299、349、399、449时更改信号的输出值;cnt为其它数值时,输出信号保持不变。代码如下:

module cntled4(Clk,Rst_n,led);
	input Clk,Rst_n;
	output reg led;
	reg [16:0] cnt;
	always@(posedge Clk or negedge Rst_n)
		if(!Rst_n)
			cnt <= 0;
		else if(cnt == 499)//10us
			cnt <= 0;
		else
			cnt <= cnt + 1'b1;
	always@(posedge Clk or negedge Rst_n)
		if(!Rst_n)
			led <= 0;
		else
			case(cnt)
				0:led <= 1;
				49:led <= 0;
				99:led <= 1;
				199:led <= 0;
				249:led <= 1;			
				299:led <= 0;
				399:led <= 1;
				default:led <= led;
			endcase
endmodule

仿真结果:
在这里插入图片描述

FPGA 中实现脉冲信号边缘检测可以利用 FPGA 内部的计数器和触发器等硬件模块,以及 VHDL 或 Verilog 等硬件描述语言进行设计和实现。 以下是一个简单的 FPGA 脉冲信号边缘检测的实现示例,以检测一个外部输入信号上升沿为例: ```vhdl -- 定义输入、输出端口 entity edge_detection is Port ( clk : in STD_LOGIC; input : in STD_LOGIC; output : out STD_LOGIC); end edge_detection; -- 实现边缘检测 architecture Behavioral of edge_detection is -- 定义计数器和触发器 signal counter : integer range 0 to 9999 := 0; signal trigger : STD_LOGIC := '0'; begin -- 计数器递增 process(clk) begin if rising_edge(clk) then if counter < 9999 then counter <= counter + 1; else counter <= 0; end if; end if; end process; -- 检测上升沿 process(input, counter) begin if input = '1' and counter = 0 then trigger <= '1'; else trigger <= '0'; end if; end process; -- 输出触发信号 process(trigger) begin if trigger = '1' then output <= '1'; else output <= '0'; end if; end process; end Behavioral; ``` 在上面的示例中,我们首先定义了输入端口 clk 和 input,以及输出端口 output。然后在 architecture 中,我们定义了一个计数器 signal counter 和一个触发器 signal trigger,用于实现上升沿的检测。 具体地,我们使用一个 process 对计数器进行递增操作,同时使用另一个 process 对输入信号计数器进行判断,如果检测到输入信号为高电平且计数器为 0,则表示发生上升沿,此时触发器的值为 '1';否则触发器的值为 '0'。最后,我们通过一个 process 将触发器的值输出到 output 端口。 这就是一个简单的 FPGA 脉冲信号边缘检测的实现示例。在实际应用中,可能需要更复杂的算法和硬件模块来实现不同的边缘检测需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值