FPGA以状态机实现串口通信

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

串口通信协议的简单介绍

1.协议介绍

UART通信只有两根信号线,一-根是发送数据端口线叫tx ,一 根是接收数据端口线叫rx ,对于上位机来说它的tx要和对于FPGA来说的rx连接,同样上位机的rx要和FPGA的tx连接,如果是两个tx或者两个rx连接那数据就不能正常被发送出去和接收到。UART可以实现全双工,即可以同时进行发送数据和接收数据。

2.协议的数据格式

FPGA以状态机实现串口通信,FPGA,fpga开发串口的一帧数据包括:起始位,数据位,奇偶校验位和停止位。如上图所示,起始位表示数据开始传输,数据位表示传输的数据,校验位分为奇校验和偶校验,用于检测数据在传输过程中是否出错。停止位,表示数据传输完成。在设置好上面的一系列参数之后,设备就可以通过串口协议通信了,而协议的主要作用就是完成数据的并串转换。

3.串口通信链接示意图

FPGA以状态机实现串口通信,FPGA,fpga开发注意:这里的信号链接细节,上位机的tx应该链接到fpga的rx,上位机的rx应该链接到fpga的tx,如果链接反了,就会出现数据通信不成功的情况。

4.状态的实现

状态机的介绍在fpga专栏第一个博客已经介绍完毕,如果还有不懂的,请参考野火或者正点原子的状态机的教程,哪里会十分详细的介绍,我写这些博客的目的更在意的是和大家分享怎么用,以及交流。
由状态机的数据格式我们可以知道,数据的传输是有明显的先后顺序的,所以我们就应该仔细想一下,用状态机是否可以将其实现出来。答案是显然的。

4.1接受状态机的实现

状态转移图:
FPGA以状态机实现串口通信,FPGA,fpga开发由状态转移图可知:最开始是”IDLE“状态,当数据线出现下降沿时,跳转到"START"状态,"START"状态的持续时间应该是协议中的一bit的数据持续时间,这里的时间计算单位应该是用输入的时间频率除以你的波特率,这里我输入的时钟频率为50MHZ,波特率为115200,所以一bit的数据应该计数最大值为,50_000_000/115200=434。这里的知识建议大家直接百度或者学一下通信的知识,不做过多的介绍。当计数器记到一个周期的计数值时,跳到"RX_DATA"状态,数据位是八位的,所以应该经过八个计数周期,计数完成之后跳转到"STOP"状态,单独靠文字来说,可能有点迷糊,下面将状态跳转的波形图也贴上,方便大家理解。
FPGA以状态机实现串口通信,FPGA,fpga开发这些变量的赋值我相信大家应该都可以轻易做到,这里不做过多的介绍,下面上状态的代码:

/*************************************************
说明:时序逻辑表示状态寄存

************************************************/
always @(posedge sys_clk or negedge sys_rst) begin
    if(!sys_rst)
        current_state <= IDLE;
    else 
        current_state <= next_state;
end
/********************************************
说明:组合逻辑表示状态转移

*********************************************/
always @(*) begin
	next_state = IDLE;
    case(current_state)
        IDLE:
            if(work_en == 1'b1)
                next_state = START;
            else 
                next_state = IDLE;
        START:
            if(boud_cnt == BAUD_CNT_MAX - 1'b1)
                next_state = RD_DATA;
            else 
                next_state = START;
        RD_DATA:
            if((bit_cnt == 4'd7)&&(boud_cnt == BAUD_CNT_MAX - 1'b1))
                next_state = STOP;
            else    
                next_state = RD_DATA;
        STOP:
            if(boud_cnt == BAUD_CNT_MAX/2- 1'b1)
                next_state = IDLE;
            else    
                next_state = STOP;
        default:next_state = IDLE;
    endcase
end

由于接受模块没有输出,所以输出这里可以不写。同时接受模块中,由于是输入输出的时钟不同,所以应该对输入信号进行跨时钟域的处理,以消除亚稳态,这一部分详细见野火的教程。跨时钟域代码:

/***********************************************
对异步信号的同步处理
**********************************************/
always @(posedge sys_clk or negedge sys_rst) begin
    if(!sys_rst)
        rx_reg1 <= 1'b1;
    else 
        rx_reg1 <= Rx_data;
end
always @(posedge sys_clk or negedge sys_rst) begin
    if(!sys_rst)
        begin
            rx_reg2 <= 1'b1;
            rx_reg3 <= 1'b1;
        end
    else
        begin
            rx_reg2 <= rx_reg1;
            rx_reg3 <= rx_reg2;
        end
end

打拍后的结果:
FPGA以状态机实现串口通信,FPGA,fpga开发
同时状态机最重要的是,要知道每一个状态下的输入和输出。那么由"IDLE"状态跳转到"START"状态就应该有一个下降沿的出现,这里还有检测数据跳转的下降沿。

assign  start_flag = ~rx_reg1 && (rx_reg2)&&(~work_en) ;    //下降沿检测 注意检测的是reg2的下降沿

最后在数据的采集也有相应的细节需要注意:一般来说要在时钟信号的中间进行数据的采样,这里的话不多说直接上代码:

//输出数据拼接
always @(posedge sys_clk or negedge sys_rst) begin
    if(!sys_rst)
        rx_data_r <= 8'b0;
    else if((current_state == RD_DATA )&&(boud_cnt == BAUD_CNT_MAX/2 - 1'd1))
        rx_data_r[bit_cnt] <= Rx_data;
    else 
        rx_data_r <= rx_data_r;
end

代码的思路是在计数器记到一半的时候进行的数据的采样。
在完成所有的准备之后,也就是状态在"STOP"结束时将数据输出:

//接受数据完成信号和数据输出标志位
always @(posedge sys_clk or negedge sys_rst) begin
    if(!sys_rst)
        begin
            po_flag <= 1'b0;
            po_data <= 8'b0;
        end
    else if((boud_cnt == BAUD_CNT_MAX/2 - 1'd1)&&(current_state == STOP )) begin 
            po_flag <= 1'b1;
            po_data <= rx_data_r;
        end 
    else 
        begin
            po_flag <= 1'b0;
            po_data <= 8'b0; 
        end
end

完整的波形图:
FPGA以状态机实现串口通信,FPGA,fpga开发

4.2发送状态机的实现

发送的状态机原理和接受的状态机大同小异:
FPGA以状态机实现串口通信,FPGA,fpga开发状态的转移也是比较类似的,其状态的转移波形图也是类似的。
FPGA以状态机实现串口通信,FPGA,fpga开发变量的赋值以及代码的编写不做介绍,看图说话。
这里直接上代码:

/********************
说明:时序逻辑表示状态寄存

******************/
always @(posedge sys_clk or negedge sys_rst) begin
    if(!sys_rst)
        current_state <= IDLE;
    else 
        current_state <= next_state;
end


/********************************************
说明:组合逻辑表示状态转移

*********************************************/
always @(*) begin
    case(current_state)
        IDLE:
            if(work_en == 1'b1)
                next_state = START;
            else 
                next_state = IDLE;
        START:
            if(Baud_cnt == BAUD_CNT_MAX - 1'b1)
                next_state = TX_DATA;
            else 
                next_state = START;
        TX_DATA:
            if((Bit_cnt == 4'd7)&&(Baud_cnt == BAUD_CNT_MAX - 1'b1))
                next_state = STOP;
            else    
                next_state = TX_DATA;
        STOP:
            if((Baud_cnt == BAUD_CNT_MAX/2- 1'd1))
                next_state = IDLE;
            else    
                next_state = STOP;
        default:;
    endcase
end
/********************************************
说明:数据寄存

*********************************************/


always@(posedge sys_clk or negedge sys_rst)
begin
	if(!sys_rst)
		begin
			tx_data_latch <= 8'd0;
		end
	else if(current_state == TX_DATA)
			tx_data_latch <= Pi_data;
		
end

/********************************************
说明:时序逻辑表示状态输出

*********************************************/

always @(posedge sys_clk or negedge sys_rst) begin
    if(!sys_rst)
        tx_data_r <= 1'b1;
    else 
        case(current_state)
            IDLE:
                tx_data_r <= 1'b1;
            START:
                tx_data_r <= 1'b0;
            TX_DATA:
                tx_data_r <= tx_data_latch[Bit_cnt];
            STOP:
                tx_data_r <= 1'b1;
            default: tx_data_r <= 1'b1;
        endcase

end

完整的波形图:
FPGA以状态机实现串口通信,FPGA,fpga开发

状态输出的一些说明:
不应该在时钟的上升沿经行输出,这里延迟了一拍进行输出。
以上是用状态机来实现串口通信,亲测有效,由于本人太懒,测试的时候忘记截图,下次一定截图。
详细的工程如果大伙需要,可以私信我,我发给你们,拜拜。下一节更新IIC通信的状态机。文章来源地址https://www.toymoban.com/news/detail-775979.html

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

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

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

相关文章

  • FPGA与stm32实现串口通信(stm32发,FPGA收)

    FPGA与stm32实现串口通信(stm32发,FPGA收)

    要使用FPGA与STM32实现串口通信,以下是一般的步骤: 配置STM32的串口模块:使用STM32的库函数或者寄存器配置,选择一个可用的串口模块(例如USART1、USART2等)并设置相应的波特率、数据位、停止位等参数。确保STM32串口的引脚与FPGA连接正确。 配置FPGA与STM32之间的通信接口:

    2024年02月14日
    浏览(11)
  • FPGA实现串口通信(RS232)含代码

    带有CH340的FPAG开发板 该模块的功能是接收通过 PC 机上的串口调试助手发送的固定波特率的数据,串口接收模块按照串口的协议准确接收串行数据,解析提取有用数据后需将其转化为并行数据;简单的说,接收模块的功能就是 解析+串转并 ; 具体实现步骤如下: 1、算出波特

    2024年02月02日
    浏览(11)
  • 【FPGA学习】状态机实现UART通信

    【FPGA学习】状态机实现UART通信

      在之前的文章中【FPGA学习】实例一、Cyclone IV串口通信(RS232)我们已经能够采用波形图的方法,实现9600bps的Uart通信。近期笔者在整理了状态机和计数器组合的设计方法以后,对状态机的设计又有了新的感悟和体会,所以又把经典的RS232协议拉出来当状态机的例子练手了哈哈

    2023年04月11日
    浏览(7)
  • FPGA入门 —— FPGA UART 串口通信

    FPGA入门 —— FPGA UART 串口通信

    UART 通用异步收发传输器( Universal Asynchronous Receiver/Transmitter) ,通常称作 UART。 UART 是一种通用的数据通信协议,也是异步串行通信口(串口)的总称,它在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。 它包括了ch340、 RS232、

    2024年02月09日
    浏览(11)
  • 【FPGA开发】HDMI通信协议解析及FPGA实现

    【FPGA开发】HDMI通信协议解析及FPGA实现

      笔者在这里使用的开发板是正点原子的达芬奇开发板,FPGA型号为XC7A35TFGG484-2。参考的课程是正点原子的课程手把手教你学达芬奇达芬奇Pro之FPGA开发篇。   HDMI,全称为High Definition Multimedia Interface,即高清多媒体接口。它不仅可以传输视频信号,还可以传输音频信号。上

    2024年02月21日
    浏览(10)
  • FPGA-串口通信

    FPGA-串口通信

    UART (universal asynchronous receiver-transmitter)是一种采用异步串行通信方式的通用异步收发传输器; 它在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。 UART串口通信需要两根信号线来实现,一根用于发送,另外一根接收(表明是异

    2024年02月16日
    浏览(15)
  • FPGA 串口通信

    FPGA 串口通信

    基础原理 并行通信 数据的各个位使用多条数据线同时进行传输 传输速度快,但是占用引脚资源多 串行通信 将数据分成一位一位的形式在一条传输线上逐个传输 通信线路简单,占用引脚资源少,但是传输速度较慢 串行通信分类 同步通信 带时钟同步信号的数据传输,发送发

    2023年04月09日
    浏览(10)
  • 【FPGA】UART串口通信---基于FIFO

    【FPGA】UART串口通信---基于FIFO

    我们在上一章完成了UART串口通信的收发模块,这一章我们将FIFO引入进来,使用FIFO进行缓存数据,来连接串口通信的收发模块 FIFO即First In First Out,是一种先进先出数据存储、缓冲器,我们知道一般的存储器是用外部的读写地址来进行读写,而FIFO这种存储器的结构并不需要外

    2023年04月14日
    浏览(17)
  • FPGA串口(RS422)调试笔记:理解串口通信与调试记录

    探索FPGA串口(RS422)通信的调试过程与记录,包括串口通信概念解析、调试步骤、代码示例以及数据拼接方法。记录调试中遇到的问题与解决方案,展示对串口通信功能的实现与乐趣体验。

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

    FPGA学习笔记(三)——串口通信之发送数据(调试过程)

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

    2023年04月09日
    浏览(14)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包