前言
FPGA verilog项目学习
一、FPGA开发板使用
1.D1闪烁 间隔1s
代码如下:
module D1
#(
parameter CNT_MAX = 26'd49_999_999
)
(
input wire sys_clk ,
input wire sys_rst_n ,
output reg led1_out
);
reg [25:0] cnt ;
reg cnt_flag;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt <= 26'b0;
else if(cnt == CNT_MAX)
cnt <= 26'b0;
else
cnt <= cnt + 1'b1;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_flag <= 1'b0;
else if(cnt == CNT_MAX)
cnt_flag <= 1'b1;
else
cnt_flag <= 1'b0;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
led1_out <= 1'b0;
else if(cnt_flag == 1'b1)
led1_out <= ~led1_out;
endmodule
2.D2闪烁,间隔1s,按下key1,key2,实现D2的闪烁时间加长/减少
代码如下(示例):
module D2
(
output reg led1_out,
output reg led2_out,
input wire sys_clk ,
input wire sys_rst_n ,
input key1_flag,
input key2_flag
);
reg [26:0] cnt;
reg [25:0] cnt1;
reg [26:0] CNT_MAX ;
reg [26:0] CNT1_MAX ;
initial
begin
CNT_MAX <= 27'd50_000_000;
CNT1_MAX <= 27'd50_000_000;
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
cnt <= 27'd0;
else if(cnt == CNT_MAX)
cnt <= 27'd0;
else
cnt <= cnt + 27'd1;
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
cnt1 <= 0;
else if(cnt1 == CNT1_MAX)
cnt1 <= 0;
else
cnt1 <= cnt1 + 26'd1;
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
led1_out <= 1'b1;
else if(cnt1 == CNT1_MAX )
led1_out <= ~led1_out;
end
always@(posedge sys_clk )
begin
if(key1_flag==1 )
begin
CNT_MAX <= CNT_MAX + 27'd25_000_000;
end
else if(CNT_MAX >= 27'd49_000_001)
begin
if(key2_flag==1)
begin
CNT_MAX <= CNT_MAX - 27'd25_000_000;
end
end
end
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
led2_out <= 1'b1;
else if(cnt == CNT_MAX )
led2_out <= ~led2_out;
end
endmodule
二、串口通信
key3作为串口驱动信号,向mcu发送数据,反复发送,key4按下,mcu发送信号给FPGA,FPGA发送反馈数据给mcu
发送代码如下(示例):
module uart(
input sys_clk,
input sys_rst_n,
output reg uart_txd,
input key3_flag,
input key4_flag,
input [7:0] uart_data,
input [7:0] uart_data1,
input uart_done,
output reg led3_out
);
parameter BPS = 5208;
reg [7:0] data_buf;
reg tx_start;
reg tx1_start;
reg[3:0] tx_cnt;
reg[12:0] clk_cnt;
reg tx_flag;
reg tx1_flag;
always @ (posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
begin
tx_start <= 1'b0;
tx1_start <= 1'b0;
end
else begin
if(key3_flag==1)
begin tx_start <= ~tx_start;end
if(key4_flag==1)
begin tx1_start <= ~tx1_start;end
end
always @ (posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
tx_flag <=0;
else if(tx_start)
tx_flag <=1'b1;
else if((tx_cnt == 4'd9)&&(clk_cnt ==BPS/2))
tx_flag <= 1'b0;
always @ (posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
tx1_flag <=0;
else if(tx1_start)
tx1_flag <=1'b1;
else if((tx_cnt == 4'd9)&&(clk_cnt ==BPS/2))
tx1_flag <= 1'b0;
always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
clk_cnt<=13'd0;tx_cnt <= 4'd0;
end
else if(tx_flag||tx1_flag)
begin
if(clk_cnt == BPS-1)
begin
clk_cnt <= 13'd0;
tx_cnt <= tx_cnt +1'b1;
if(tx_cnt == 4'd9)tx_cnt <=0;
end
else
begin
clk_cnt <= clk_cnt +1'b1;tx_cnt<=tx_cnt;
end
end
end
reg [26:0] cnt_2s;
always @ (posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
cnt_2s<=0;
else if(cnt_2s==27'd100_000_000)
cnt_2s<=0;
else
cnt_2s<=cnt_2s+27'd1;
reg [27:0] cnt_15s;
always @ (posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
cnt_15s<=0;
else if(cnt_15s==28'd75_000_000-1)
cnt_15s<=0;
else
cnt_15s<=cnt_15s+28'd1;
reg [3:0] cnt_8;
always @ (posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
cnt_8<=4'd0;
else if(cnt_2s==27'd100_000_000)
cnt_8<=cnt_8+4'd1;
else if(cnt_8 == 4'd8)
cnt_8<=4'd0;
reg [3:0] cnt1_2;
always @ (posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
cnt1_2<=4'd0;
else if(cnt_15s==27'd75_000_000-1)
cnt1_2<=cnt1_2+4'd1;
else if(cnt1_2 == 4'd2)
cnt1_2<=4'd0;
reg [3:0] cnt1_8;
always @ (posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
cnt1_8<=4'd0;
else if(cnt_15s==27'd75_000_000-1)
cnt1_8<=cnt1_8+4'd1;
else if(cnt1_8 == 4'd8)
cnt1_8<=4'd0;
always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
data_buf<=8'h00;
else if(tx1_flag ==1)begin
if(uart_data == 8'h11)
data_buf <= uart_data;
if(uart_data == uart_data )
case(cnt1_2)
4'd0:data_buf <= uart_data;
4'd1:data_buf <= uart_data1;
default:;
endcase
end
else if(tx_flag ==1)
case(cnt_8)
4'd0:data_buf <= 8'h55;
4'd1:data_buf <= 8'hAA;
4'd2:data_buf <= 8'h66;
4'd3:data_buf <= 8'h99;
4'd4:data_buf <= 8'h01;
4'd5:data_buf <= 8'h23;
4'd6:data_buf <= 8'h45;
4'd7:data_buf <= 8'h67;
default:data_buf <= 8'h00;
endcase
end
always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
uart_txd <= 8'b1;
else
case(tx_cnt)
4'd0:uart_txd <= 8'b0;
4'd1:uart_txd <= data_buf[0];
4'd2:uart_txd <= data_buf[1];
4'd3:uart_txd <= data_buf[2];
4'd4:uart_txd <= data_buf[3];
4'd5:uart_txd <= data_buf[4];
4'd6:uart_txd <= data_buf[5];
4'd7:uart_txd <= data_buf[6];
4'd8:uart_txd <= data_buf[7];
4'd9:uart_txd <= 8'b1;
default:uart_txd <= 8'b1;
endcase
end
reg [7:0] array [0:3];
reg [3:0] i;
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
begin
led3_out<=1;
end
else if(uart_done == 1'b1)
begin i<=0;array[i]<=uart_data;i<=i+1;end
else if(uart_data1 == 8'h32)
begin led3_out <= 0 ; end
else if(uart_data1 == 8'h10)
begin led3_out <= 1 ; end
else if(uart_data1 == 8'h76)
begin led3_out <= 0 ; end
else if(uart_data1 == 8'h54)
begin led3_out <= 1 ; end
endmodule
接收代码如下(示例):
module rx(
input sys_clk,
input sys_rst_n,
input key4_flag,
input uart_rxd,
output reg[7:0] uart_data,
output reg[7:0] uart_data1,
output reg uart_done
);
parameter BPS = 5208;
reg rx_start;
reg rx_flag;
reg [3:0] rx_cnt;
reg [12:0] clk_cnt;
reg [7:0] rxdata;
reg uart_rxd_reg0;
reg uart_rxd_reg1;
wire start_flag;
initial uart_data <= 8'h11;
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
uart_rxd_reg0 <= 1'b1;
uart_rxd_reg1 <= 1'b1;
end
else begin
uart_rxd_reg0 <= uart_rxd;
uart_rxd_reg1 <= uart_rxd_reg0;
end
end
assign start_flag = (uart_rxd_reg1)&(~uart_rxd_reg0);
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
rx_flag <= 0;
else
begin
if(start_flag)
rx_flag <= 1'b1;
else if(rx_cnt == 4'd9 && clk_cnt == BPS/2)
rx_flag <= 1'b0;
else
rx_flag <= rx_flag;
end
end
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
clk_cnt <= 0;
else begin
if(rx_flag)begin
if(clk_cnt < BPS - 1)
clk_cnt <= clk_cnt + 1'b1;
else
clk_cnt <= 0;
end
else
clk_cnt <= 0;
end
end
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
rx_cnt <= 0;
else begin
if(rx_flag)begin
if(clk_cnt == BPS - 1)
rx_cnt <= rx_cnt + 1'b1;
else
rx_cnt <= rx_cnt;
end
else
rx_cnt <= 0;
end
end
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
rxdata <= 0;
else begin
if(rx_flag)begin
if(clk_cnt == BPS/2)begin
case(rx_cnt)
4'd1: rxdata[0] <= uart_rxd;
4'd2: rxdata[1] <= uart_rxd;
4'd3: rxdata[2] <= uart_rxd;
4'd4: rxdata[3] <= uart_rxd;
4'd5: rxdata[4] <= uart_rxd;
4'd6: rxdata[5] <= uart_rxd;
4'd7: rxdata[6] <= uart_rxd;
4'd8: rxdata[7] <= uart_rxd;
default:;
endcase
end
else
rxdata <= rxdata;
end
else
rxdata <= 0;
end
end
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
uart_data <= uart_data;
uart_data1 <= 0;
uart_done <= 0;
end
else begin
if(rx_cnt == 4'd9)begin
uart_data <= rxdata;
uart_data1 <= ~rxdata;
uart_done <= 1'b1;
end
else begin
uart_done <= 0;
end
end
end
endmodule
按键检测模块
module key1_filter
#(
parameter CNT_MAX = 20'd999_999 //计数器计数最大值
)
(
input wire sys_clk , //系统时钟 50MHz
input wire sys_rst_n , //全局复位
input wire key1_in , //按键输入信号
output reg key1_flag //key1_flag 为 1 时表示消抖后检测到按键被按下
//key1_flag 为 0 时表示没有检测到按键被按下
);
//按键消抖
reg [19:0] cnt_20ms ; //计数器
//cnt_20ms:如果时钟的上升沿检测到外部按键输入的值为低电平时,计数器开始计数
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_20ms <= 20'b0;
else if(key1_in == 1'b1)
cnt_20ms <= 20'b0;
else if(cnt_20ms == CNT_MAX && key1_in == 1'b0)
cnt_20ms <= cnt_20ms;
else
cnt_20ms <= cnt_20ms + 1'b1;
//key1_flag:当计数满 20ms 后产生按键有效标志位
//且 key1_flag 在 999_999 时拉高,维持一个时钟的高电平
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
key1_flag <= 1'b0;
else if(cnt_20ms == CNT_MAX - 1'b1)
key1_flag <= 1'b1;
else
key1_flag <= 1'b0;
按键按的次数
//always@(posedge sys_clk or negedge sys_rst_n)
//if(sys_rst_n == 1'b0)
// key1_value <= 4'd0;
//else if(key1_flag == 1'b1)
// key1_value <= key1_value + 4'd1;
//else
// key1_value <= 4'd0;
endmodule
总结
串口通信收发数据。
|