FPGA——IO操作
IO作为输出——流水灯
目标 :1s时间间隔实现流水灯
需要的信号:时钟信号,复位信号
说明:要实现流水灯,我们需要计时器、移位寄存器。
首先根据外部50MHz晶振得出每一个振荡周期时间间隔为20ns,要实现1s计时我们需要一个可以计数到
1
s
/
20
n
s
=
50
,
000
,
000
1s/20ns=50,000,000
1s/20ns=50,000,000
的计数器
换算得二进制10 1111 1010 1111 0000 1000 0000。所以需要定义一个26位的cnt计数器。
同样实现流水效果时需要一个移位寄存器进行移位,例如:
led[3:0] <= {led[2:0],led[3]};
每当计数器计满时,led移位寄存器进行移位,达到流水效果
直接上代码
module IOoperating(
input sys_clk,
input rst_n, //定义输入信号
output reg [3:0]led //定义移位寄存器,作为输出
);
reg [25:0] cnt; //定义26为计数器,计时1s
/*****************************************************
计时1s
每当时钟上升沿或复位按下时,进行判断
*****************************************************/
always @(posedge sys_clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 26'b0; //如果复位被按下,计数器清零
else if(cnt < 26'd5000_0000)
cnt <= cnt + 1'b1; //如果没到1s,计数器+1
else
cnt <= 26'd0; //达到1s,计数器清零
end
/*****************************************************
led移位输出
*****************************************************/
always @(posedge sys_clk or negedge rst_n)
begin
if(!rst_n)
led <= 4'b1110; //复位被按下,恢复到初始状态
else if(cnt == 26'd5000_0000)
led[3:0] <= {led[2:0],led[3]}; //计数器满,达到一秒,led寄存器移位
else
led <= led;
end
endmodule
IO作为输入——按键控制led
目标:按下K0,led流水显示。按下K1,led闪烁。时间间隔均为1s。
主要方法:设置一个按键标志位,按下不同按键,给标志位不同值,从而控制效果
module key_led(
input sys_clk,
input rst_p, //定义输入信号
input [2:0] key,
output reg [3:0] led //定义移位寄存器,作为输出
);
//reg define
reg [25:0] cnt; //计数
reg [1:0] led_ctrl; //状态控制
reg [1:0] led_flag; //按键标志位
/*****************************************************
计时1s
每当时钟上升沿或复位按下时,进行判断
*****************************************************/
always @(posedge sys_clk or posedge rst_p)
begin
if(rst_p)
cnt <= 26'd0;
else
if(cnt < 25'd50_000_000)
cnt <= cnt + 1'b1;
else
cnt <= 26'd0;
end
/*****************************************************
状态计数器
led_ctrl为2位寄存器,共4个状态,累加到5时自动清零
从而实现不同显示效果
*****************************************************/
always @(posedge sys_clk or posedge rst_p)
begin
if(rst_p)
led_ctrl <= 2'd0;
else
if(cnt == 25'd50_000_000)
led_ctrl <= led_ctrl + 2'b1; //时间到达1s后led_ctrl+1,显示下一个状态
else
led_ctrl <= led_ctrl;
end
/*****************************************************
状态变化标志
当key[0]按下时,led_flag 为01
当key[1]按下时,led_flag 为10
*****************************************************/
always @(posedge sys_clk or posedge rst_p)
begin
if(rst_p)
led_flag <= 2'b0;
else
if(key[0] == 1'b0)
led_flag <= 2'b01;
else if(key[1] == 1'b0)
led_flag <= 2'b10;
else
led_flag <= led_flag;
end
/*****************************************************
根据按键改变led灯
判断led_flag 值,,通过led_ctrl的变化显示led
*****************************************************/
always @(posedge sys_clk or posedge rst_p)
begin
if(rst_p)
led <= 4'b1111;
else
if(led_flag[0] == 1'b1)
case(led_ctrl)
2'd0: led <= 4'b0111;
2'd1: led <= 4'b1011;
2'd2: led <= 4'b1101;
2'd3: led <= 4'b1110;
endcase
else if(led_flag[1] == 1'b1)
case(led_ctrl)
2'd0: led <= 4'b1111;
2'd1: led <= 4'b0000;
2'd2: led <= 4'b1111;
2'd3: led <= 4'b0000;
endcase
else
led <= 4'b1111;
end
endmodule