FPGA 按键控制串口发送

这篇具有很好参考价值的文章主要介绍了FPGA 按键控制串口发送。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

按键消抖

消抖时间一般为10ms,我使用的板子是ACX720,晶振为50MHZ,20ns为一周期。

FPGA 按键控制串口发送,fpga开发

状态机

FPGA 按键控制串口发送,fpga开发

模块设计

FPGA 按键控制串口发送,fpga开发

设计文件

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/01/11 12:18:36
// Design Name: 
// Module Name: key_filter
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module key_filter(
	 Clk,
     Rst_n,
     Key_in,
     Key_flag, //按键按下标志位
     Key_State //高电平,按键按下
);
    input Clk;
    input Rst_n;
    input Key_in;
    
    output reg Key_flag;
    output reg Key_State;
    
    parameter Filter_Time=500_000; //10ms
    localparam 
    		S1=4'b0001,//按键松开
    		S2=4'b0010,//消抖计数
    		S3=4'b0100,//按键松开
    		S4=4'b1000;//消抖计数

    //捕捉按键上升沿和下降沿
    reg [2:0] Pos_Neg_r;
    wire pos_edge;
    wire neg_edge;
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            Pos_Neg_r<=0;
        else begin
            Pos_Neg_r={Pos_Neg_r[1:0],Key_in};
        end
    end
    assign pos_edge=Pos_Neg_r[2:1]==2'b01;//上升沿  //按键松开
    assign neg_edge=Pos_Neg_r[2:1]==2'b10;//下降沿  //按键按下
    
    //消抖延迟计数器
    reg [18:0] counter_cnt;
    reg En_counter_cnt;//按键消抖计数的条件
    wire end_counter_cnt;
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            counter_cnt<=19'd0;
        else if(En_counter_cnt)begin
            if(end_counter_cnt)
                counter_cnt<=19'd0;
            else
                counter_cnt<=counter_cnt+1'd1;
        end
        else
            counter_cnt<=19'd0;
    end
    assign end_counter_cnt=counter_cnt>=(Filter_Time-1);
    
    reg	[3:0]	cur_state;					//定义现态寄存器
    reg	[3:0]	next_state;					//定义次态寄存器
 
    /*
    -----------------------------------------------------------------------
    状态机第一段:同步时序描述状态转移
    -----------------------------------------------------------------------
    */
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            cur_state <= S1;				//复位初始状态
        else
            cur_state <= next_state;		//次态转移到现态
    end
     
    /*
    -----------------------------------------------------------------------
    状态机第二段:组合逻辑判断状态转移条件,描述状态转移规律以及输出
    -----------------------------------------------------------------------
    */
    always@(*)begin
            case(cur_state)
                S1:begin                    //按键松开状态
                    if(neg_edge)            //按键按下--检测到下降沿
                        next_state=S2;
                    else
                        next_state=cur_state;
                end
                S2:begin
                    if(pos_edge)
                        next_state=S1;
                    else if(end_counter_cnt)
                        next_state=S3;
                    else
                        next_state=cur_state;
                end
                S3:begin                    //按键按下状态
                    if(pos_edge)            //按键松开--检测到上升沿
                        next_state=S4;
                    else
                        next_state=cur_state;
                end
                S4:begin    
                    if(neg_edge)
                        next_state=S3;
                    else if(end_counter_cnt)
                        next_state=S1;
                    else
                        next_state=cur_state;
                end
                default:next_state=cur_state;
            endcase
    end
    
    /*
    -----------------------------------------------------------------------
    状态机第三段:时序逻辑描述输出
    -----------------------------------------------------------------------
    */
    //消抖计数使能
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            En_counter_cnt <= 1'b0;			      //复位、初始状态 
        else
            case(cur_state)					      //根据当前状态进行输出
                S1:	En_counter_cnt <= 1'b0;		  //不计数			
                S2:	En_counter_cnt <= 1'b1;		  //计数
                S3:	En_counter_cnt <= 1'b0;		  //不计数
                S4:	En_counter_cnt <= 1'b1;		  //计数
                default:En_counter_cnt <= 1'b0;   //默认不计数
            endcase
    end
    //按键按下标志位
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            Key_flag <= 1'b0;                    //复位、初始状态 
        //Key_State存在一拍
        else if(cur_state==S2 && end_counter_cnt) 
            Key_flag<=1'd1;
        else 
            Key_flag<=1'd0;
    end
    //输出按键状态
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            Key_State <= 1'b0;                    //复位、初始状态 
        else if(cur_state==S3) 
            Key_State<=1'd1;
        else if(cur_state==S4 && end_counter_cnt)
            Key_State<=1'd0;
        else
            Key_State<=Key_State;
    end

endmodule

仿真验证

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/01/06 16:24:27
// Design Name: 
// Module Name: key_filter_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module key_filter_tb();

    reg Clk;
    reg Rst_n;
    reg Key_in;
    wire Key_flag;
    wire Key_State;

    key_filter
    #(
        .Filter_Time(5000)//100us
    )
    key_filter(
        Clk,
        Rst_n,
        Key_in,
        Key_flag, //按键按下标志位
        Key_State //高电平,按键按下
    );
    
    initial Clk=1;
    always #10 Clk=~Clk;
    
    initial begin
        Rst_n=0;
        Key_in=1;
        #201;
        Rst_n=1;
        Key_in=1;#20000;
        Key_in=0;#20000;
        Key_in=1;#10000;
        Key_in=0;#20000;
        Key_in=1;#20000;
        Key_in=0;#600000;
        Key_in=1;#20000;
        Key_in=0;#20000;
        Key_in=1;#10000;
        Key_in=0;#20000;
        Key_in=1;#20000;
        Key_in=0;#20000;
        Key_in=1;#10000;
        Key_in=0;#20000;
        Key_in=1;#20000;
        Key_in=0;#20000;
        Key_in=1;#10000;
        Key_in=1;#600000;
        $stop;
        
    end

endmodule

FPGA 按键控制串口发送,fpga开发

串口发送

**注意:**电平信号的传输线中有一个参考电平线(一般是GND),然后信号线上的信号值是由信号线电平和参考电平线的电压差决定。所以我们一定要养成模块之间共地的好习惯。

串口帧

FPGA 按键控制串口发送,fpga开发

模块设计

FPGA 按键控制串口发送,fpga开发

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/01/06 11:30:58
// Design Name: 
// Module Name: UART_Byte_Tx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module UART_Byte_Tx
    #(
        parameter BaudRate = 115200,//波特率
        parameter ClockRate = 50_000_000//系统时钟
    )
(
	Clk,
    Rst_n,
    Send_En,
    data_byte,
    Tx_Data,
    Tx_Done,
    uart_state
);
    input Clk;
    input Rst_n;
    input Send_En;
    input [7:0] data_byte;
    
    output reg Tx_Data;
    output reg Tx_Done;
    output reg uart_state;
    
    //设置使能
    reg tx_en;
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            tx_en<=0;
        else if(Send_En)
            tx_en<=1'd1;
        else if(Tx_Done)
            tx_en<=1'd0;
        else
            tx_en<=tx_en;
    end
    
    //设置波特率
    localparam Buad_Num = ClockRate/BaudRate;

    //设置计数器
    reg [12:0] buad_cnt;
    wire add_buad_cnt;
    wire end_buad_cnt;
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            buad_cnt<=0;
        else if(add_buad_cnt)begin
            if(end_buad_cnt)
                buad_cnt<=0;
            else 
                buad_cnt<=buad_cnt+1'b1;
        end
        else
            buad_cnt<=0;
    end
    assign add_buad_cnt=tx_en;
    assign end_buad_cnt=buad_cnt>=(Buad_Num-1'd1);
    
    //设置发送bit计数
    reg [3:0] bit_cnt;
    wire add_bit_cnt;
    wire end_bit_cnt;
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            bit_cnt<=0;
        else if(add_bit_cnt)
            bit_cnt<=bit_cnt+1'd1;
        else if(end_bit_cnt)
            bit_cnt<=0;
        else
            bit_cnt<=bit_cnt;
    end
    assign add_bit_cnt=buad_cnt==1;
    assign end_bit_cnt=(bit_cnt==4'd10 && add_bit_cnt) || !tx_en;
    
    //发送数据
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            Tx_Data<=1;
        else begin
            case(bit_cnt)
                4'd1:Tx_Data<=0;
                4'd2:Tx_Data<=data_byte[0];
                4'd3:Tx_Data<=data_byte[1];
                4'd4:Tx_Data<=data_byte[2];
                4'd5:Tx_Data<=data_byte[3];
                4'd6:Tx_Data<=data_byte[4];
                4'd7:Tx_Data<=data_byte[5];
                4'd8:Tx_Data<=data_byte[6];
                4'd9:Tx_Data<=data_byte[7];
                4'd10:Tx_Data<=1;
                default:Tx_Data<=1;
            endcase
        end
    end
    
    //发送结束
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            Tx_Done<=0;
        else if(bit_cnt==4'd10 && add_bit_cnt)
            Tx_Done<=1;
        else
            Tx_Done<=0;
    end
    
    //发送状态(有效数据)
    wire En_uart_state;
    wire Nen_uart_state;
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)
            uart_state<=0;
        else if(En_uart_state)
            uart_state<=1;
        else if(Nen_uart_state)
            uart_state<=0;
    end
    assign En_uart_state=bit_cnt==4'd1 && add_bit_cnt;
    assign Nen_uart_state=bit_cnt==4'd9 && add_bit_cnt;
    
endmodule

仿真验证

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/01/06 11:31:09
// Design Name: 
// Module Name: UART_Byte_Tx_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module UART_Byte_Tx_tb();


    reg Clk;
    reg Rst_n;
    reg Send_En;
    reg [7:0]data_byte;
    
    wire Tx_Data;
    wire Tx_Done;
    wire uart_state;
    
    initial Clk=1;
    always #10 Clk=~Clk;
    
    initial begin
        Rst_n=0;
        Send_En=0;
        data_byte=0;
        #201;
        Rst_n=1;
        data_byte=8'b1001_0110;
        Send_En=1;
        #20;
        Send_En=0;
        #100000;
        data_byte=8'b0111_0110;
        Send_En=1;
        #20;
        Send_En=0;
        #100000;
        $stop;
    end
    
    
    UART_Byte_Tx UART_Byte_Tx(
        .Clk(Clk),
        .Rst_n(Rst_n),
        .Send_En(Send_En),
        .data_byte(data_byte),
        .Tx_Data(Tx_Data),
        .Tx_Done(Tx_Done),
        .uart_state(uart_state)
    );
    
endmodule

FPGA 按键控制串口发送,fpga开发

按键控制串口发送

RTL视图

FPGA 按键控制串口发送,fpga开发

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/01/07 13:43:42
// Design Name: 
// Module Name: Uart_Key_Send_cmd
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module Uart_Key_Send_cmd(
	 Clk,
    Rst_n,
    Key_in,
    uart_tx
);
    input Clk;
    input Rst_n;
    input Key_in;
    output uart_tx;
    
    //按键模块
    wire Key_flag;
    wire Key_State;
    key_filter key_filter(
         Clk,
         Rst_n,
         Key_in,
         Key_flag, //按键按下标志位
         Key_State //高电平,按键按下
    );
    
    //串口发送
    reg [7:0] data_byte;
    wire Tx_Done;
    wire uart_state;
    //assign data_byte=8'b0100_0001; //发送A
    always@(posedge Clk or negedge Rst_n)begin
        if(!Rst_n)  
            data_byte<=8'b0100_0001; //发送A
        else if(Tx_Done)
            data_byte<=data_byte+1'b1;//数据加一
    end
    
    UART_Byte_Tx UART_Byte_Tx(
        .Clk(Clk),
        .Rst_n(Rst_n),
        .Send_En(Key_flag),
        .data_byte(data_byte),
        .Tx_Data(uart_tx),
        .Tx_Done(Tx_Done),
        .uart_state(uart_state)
    );

endmodule

板级验证

FPGA 按键控制串口发送,fpga开发文章来源地址https://www.toymoban.com/news/detail-847859.html

到了这里,关于FPGA 按键控制串口发送的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FPGA之按键控制LED

    一、按键开关        1、按键开关(轻触开关):主要是指轻触式按键开关,属于电子元器件类,使用时以满足操作力的条件向开关操作方向施压开关功能闭合接通,当撤销压力时开关即断开,其内部结构是靠金属弹片受力变化来实现通断的。        2、自锁按键:在开关

    2024年02月08日
    浏览(52)
  • 按键控制流水灯方向——FPGA

    环境: 1、Quartus18.0 2、vscode 3、板子型号:EP4CE6F17C8 要求: 按键1按下,流水灯从右开始向左开始流动,按键2按下,流水灯从左开始向右开始流动,按键3按下LED每隔1s进行亮灭,按键4按下LED常亮。 “自锁”是指开关能通过锁定机构保持某种状态(通或断),“轻触”是说明操

    2024年02月07日
    浏览(36)
  • FPGA初步学习之串口发送模块【单字节和字符串的发送】

    UART 在发送或接收过程中的一帧数据由4部分组成,起始位、数据位、奇偶校验位和停止位,如图所示。其中,起始位标志着一帧数据的开始,停止位标志着一帧数据的结束,数据位是一帧数据中的有效数据。 通常用的串口数据帧格式是:8位数据位,无校验位,1位停止位。

    2024年02月14日
    浏览(37)
  • 【FPGA零基础学习之旅#14】串口发送字符串

    🎉欢迎来到FPGA专栏~串口发送字符串 ☆* o(≧▽≦)o *☆ 嗨 ~我是 小夏与酒 🍹 ✨ 博客主页: 小夏与酒的博客 🎈该系列 文章专栏: FPGA学习之旅 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 📜 欢迎大家关注! ❤️ 🥝 发送Hello: 🥝 发送数字字符并自

    2024年02月08日
    浏览(31)
  • FPGA学习笔记(三)——串口通信之发送数据(调试过程)

    本学习笔记主要参考小梅哥B站教学视频,网址如下: https://www.bilibili.com/video/BV1va411c7Dz?p=1 使用的编译器为Vivado,HDL语言为verilog 一、串口通信之发送数据 原理 设计代码 测试代码 仿真结果 发现Send_en拉高之前,uart_tx就置为0了,不符合常理。 转到第二个发送信号处,发现Send

    2023年04月09日
    浏览(36)
  • FPGA串口接收解帧、并逐帧发送有效数据-2

    工程实现的功能:FPGA串口接收到串口调试助手发来的数据,将其数据解帧。判断到正确的帧头和帧尾之后,将有效数据存入rx_data中;另一方面发送端将有效数据逐帧发送出去。 参考:正点原子官方FPGA串口通信实验 模块构成: 在原子哥的基础上改的代码。 添加了接收状态机

    2024年02月05日
    浏览(27)
  • FPGA串口接收解帧、并逐帧发送有效数据——1

    工程实现的功能:FPGA串口接收到串口调试助手发来的数据,将其数据解帧。判断到正确的帧头和帧尾之后,将有效数据存入rx_data中;另一方面发送端将有效数据逐帧发送出去。 参考:正点原子官方FPGA串口通信实验 模块构成: 在原子哥的基础上改的代码。 添加了接收状态机

    2024年02月05日
    浏览(30)
  • 【FPGA零基础学习之旅#13】串口发送模块设计与验证

    🎉欢迎来到FPGA专栏~串口发送模块 ☆* o(≧▽≦)o *☆ 嗨 ~我是 小夏与酒 🍹 ✨ 博客主页: 小夏与酒的博客 🎈该系列 文章专栏: FPGA学习之旅 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 📜 欢迎大家关注! ❤️ 🥝 发送测试: 🥝 issp调试测试: 数据

    2024年02月09日
    浏览(46)
  • FPGA自学笔记--串口通信发送多字节数据(verilog版)

            关于uart协议实现这部分大家可以参考我上一篇的博客。《FPGA自学笔记--串口通信实现(vivadoverilog版)》。在上一篇博客中,主要实现了将单字节的数据,我们其实就是用上一篇博客的模块来实现多字节数据的发送。         在真实的数据传输过程中,我们不

    2023年04月17日
    浏览(30)
  • FPGA拾忆_(10):按键控制蜂鸣器_边沿检测_按键消抖

    1.硬件特征: 轻触式(回弹式)按键         略 蜂鸣器: 分为蜂鸣器按照结构原理不同可分为压电式蜂鸣器和电磁式蜂鸣器。 压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、 阻抗匹配器及共鸣箱、外壳等组成; 电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组

    2024年04月10日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包