uart串口环回(加FIFO)

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

一.uart简介

  • UART(universal asynchronous receiver-transmitter)是一种采用异步串行通信方式的通用异步收发传输器。
  • 定义如上,那么出现问题了,什么叫异步串行通信?请关注下文原理。

二.原理

1.同步通信&&异步通信

1.1同步通信

  • 发送方发送出数据后,等接收方响应后才发送下一个数据

1.2异步通信

  • 发送方发出数据后,不等接收方发回相应,接着发送下一个数据

2.并行通信&&串行通信

2.1并行通信

  • 并行通信是指数据各个位用多条数据线同时进行传输
    串口fifo,FPGA学习,fpga

2.2串行通信

  • 串行通信是将数据分成一位一位的形式在一条线上逐个传输
    串口fifo,FPGA学习,fpga

3.全双工&&半双工

3.1全双工

  • 双方都可以发送接收数据,并可以同时进行
    串口fifo,FPGA学习,fpga

3.2半双工

  • 双方都可以发送接收数据,但是同一时刻只能一方发送,一方接收
    串口fifo,FPGA学习,fpga

4.协议层

4.1数据格式

串口fifo,FPGA学习,fpga

  • 解析上图可以看出:空闲位处于高电平,起始位为0(拉低);数据位可以是6-8bit,注意是低位先发;暂时不考虑校验位,停止位为1(拉高)。

4.2传输速率

  • 串口通信的速率用波特率表示,它表示每秒传输二进制数据的位数,单位是bit/s(位/秒),简称bps。常用的波特率有9600、19200、38400、57600、115200等。本文中设计用的115200的波特率==>传输1bit需要计数50_000_000/115200 = 434次

二.初步设计

1.模块图

串口fifo,FPGA学习,fpga

2.tx设计

串口fifo,FPGA学习,fpga

  • tx将8bit的数据转换为1bit数据输出

3.rx设计

串口fifo,FPGA学习,fpga

  • rx将1bit的数据转换为8bit数据输出
  • 这里由于加入stop状态后面会导致状态跳崩了,于是我不要stop状态了

4.加入FIFO

  • FIFO配置上,数据宽度选8bit,数据深度选32bit,其他配置可参考前文https://blog.csdn.net/weixin_67803687/article/details/132248964?spm=1001.2014.3001.5501中的单时钟前显模式

三.代码

1.uart_tx

/**************************************功能介绍***********************************
Date	: 2023年8月16日17:07:11
Author	: Alegg xy.
Version	: 2.0
Description: FPGA向上位机发送数据【8bit变1bit(波形)】
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module uart_tx( 
    input				clk		,
    input				rst_n	,
    input       [7:0]   tx_data ,
    input               tx_data_vld,
    output              ready   ,
    output  reg         tx              
);								 
//---------<参数定义>--------------------------------------------------------- 
    parameter   MAX_1bit = 9'd434;//1bit要计434次
    //状态机参数定义
    localparam  IDLE   = 'b0001,//空闲状态
                START  = 'b0010,//起始位
                DATA   = 'b0100,//数据位
                STOP   = 'b1000;//停止位
//---------<内部信号定义>-----------------------------------------------------    
    reg 	[3:0]	cstate     ;//现态
    reg	    [3:0]	nstate     ;//次态
    
    wire    IDLE_START;
    wire    START_DATA;
    wire    DATA_CHECK;
    wire    CHECK_STOP;
    wire    STOP_IDLE;

    reg			[8:0]	cnt_baud	   	;//波特计数器,波特率115200
    wire				add_cnt_baud	;
    wire				end_cnt_baud	;

    reg			[2:0]	cnt_bit	   	;//bit计数器,起始位1bit,数据位8bit,结束位1bit
    wire				add_cnt_bit	;
    wire				end_cnt_bit	;
    
    reg         [3:0]   bit_max;//bit最大值,复用需要考察每个状态的bit值
    reg         [7:0]   tx_data_r;
    
    //计434次
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_baud <= 'd0;
        end 
        else if(add_cnt_baud)begin 
            if(end_cnt_baud)begin 
                cnt_baud <= 'd0;
            end
            else begin 
                cnt_baud <= cnt_baud + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_baud = cstate != IDLE;
    assign end_cnt_baud = add_cnt_baud && cnt_baud == MAX_1bit - 1'd1;
    
    //bit计数器
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_bit <= 'd0;
        end 
        else if(add_cnt_bit)begin 
            if(end_cnt_bit)begin 
                cnt_bit <= 'd0;
            end
            else begin 
                cnt_bit <= cnt_bit + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_bit = end_cnt_baud;
    assign end_cnt_bit = add_cnt_bit && cnt_bit == bit_max -1'd1;
    
    //计数器复用
    always @(*)begin 
        case (cstate)
            IDLE :bit_max = 'd0;
            START:bit_max = 'd1;//起始位1bit
            DATA :bit_max = 'd8;//数据位8bit
            STOP :bit_max = 'd1;//结束位1bit
            default: bit_max = 'd0;
        endcase
    end

    assign IDLE_START = (cstate == IDLE) && tx_data_vld;//考察到开始传输信号
    assign START_DATA = (cstate == START) && end_cnt_bit;//计1bit数据
    assign DATA_STOP = (cstate == DATA) && end_cnt_bit;
    assign STOP_IDLE = (cstate == STOP) && end_cnt_bit;//计1bit数据

    //第一段:时序逻辑描述状态转移
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cstate <= IDLE;
        end 
        else begin 
            cstate <= nstate;
        end 
    end
    
    //第二段:组合逻辑描述状态转移规律和状态转移条件
    always @(*) begin
        case(cstate)
            IDLE  :begin
                if (IDLE_START) begin
                    nstate = START;
                end
                else begin
                    nstate = cstate;
                end
            end
            START :begin
                if (START_DATA) begin
                    nstate = DATA;
                end
                else begin
                    nstate = cstate;
                end
            end
            DATA  :begin
                if (DATA_STOP) begin
                    nstate = STOP;
                end
                else begin
                    nstate = cstate;
                end
            end
            STOP  :begin
                if (STOP_IDLE) begin
                    nstate = IDLE;
                end
                else begin
                    nstate = cstate;
                end
            end
            default : nstate = cstate;
        endcase
    end

    //寄存一拍
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            tx_data_r <= 'd0;
        end
        else if (tx_data_vld) begin
            tx_data_r <= tx_data;
        end
        else begin
            tx_data_r <= tx_data_r;
        end
    end
    

    //第三段:描述输出,时序逻辑或组合逻辑皆可
    always @(*)begin 
        case (cstate)
            IDLE : tx = 1'b1;
            START: tx = 1'b0;//起始位为0
            DATA : tx = tx_data_r[cnt_bit];
            STOP : tx = 1'b1;//结束位为1
            default: tx = 1'b1;
        endcase
    end            
                
    assign ready = cstate == IDLE;//当状态为IDLE时,表示tx端可以接收数据
    
    
    
endmodule

2.uart_rx

/**************************************功能介绍***********************************
Date	: 2023年8月16日18:25:03 
Author	: Alegg xy.
Version	: 1.0
Description: FPGA收上位机发来的数据【1bit(波形)变8bit】
*********************************************************************************/

//---------<模块及端口声名>------------------------------------------------------
module uart_rx( 
    input				clk		,
    input				rst_n	,
    input               rx      ,
    output              rx_data_vld,
    output  reg [7:0]   rx_data            
);								 
//---------<参数定义>--------------------------------------------------------- 
    parameter   MAX_1bit = 9'd434;//1bit要计434次
    //状态机参数定义
    localparam  IDLE   = 'b001,//空闲状态
                START  = 'b010,//起始位
                DATA   = 'b100;//数据位

//---------<内部信号定义>-----------------------------------------------------    
    reg 	[2:0]	cstate     ;//现态
    reg	    [2:0]	nstate     ;//次态
    
    wire    IDLE_START;
    wire    START_DATA;
    wire    DATA_IDLE;

    reg			[8:0]	cnt_baud	   	;//波特计数器,波特率115200
    wire				add_cnt_baud	;
    wire				end_cnt_baud	;

    reg			[2:0]	cnt_bit	   	;//bit计数器,起始位1bit,数据位8bit,结束位1bit
    wire				add_cnt_bit	;
    wire				end_cnt_bit	;
    
    reg         [3:0]   bit_max;//bit最大值,复用需要考察每个状态的bit值

    //计434次
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_baud <= 'd0;
        end 
        else if(add_cnt_baud)begin 
            if(end_cnt_baud)begin 
                cnt_baud <= 'd0;
            end
            else begin 
                cnt_baud <= cnt_baud + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_baud = cstate != IDLE;
    assign end_cnt_baud = add_cnt_baud && cnt_baud == MAX_1bit - 1'd1;
    
    //bit计数器
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_bit <= 'd0;
        end 
        else if(add_cnt_bit)begin 
            if(end_cnt_bit)begin 
                cnt_bit <= 'd0;
            end
            else begin 
                cnt_bit <= cnt_bit + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_bit = end_cnt_baud;
    assign end_cnt_bit = add_cnt_bit && cnt_bit == bit_max -1'd1;
    
    //计数器复用
    always @(*)begin 
        case (cstate)
            IDLE :bit_max = 'd0;
            START:bit_max = 'd1;//起始位1bit
            DATA :bit_max = 'd8;//数据位8bit
            default: bit_max = 'd0;
        endcase
    end

    assign IDLE_START = (cstate == IDLE) && rx == 0;//识别到起始位0
    assign START_DATA = (cstate == START) && end_cnt_bit;//计1bit数据
    assign DATA_IDLE = (cstate == DATA) && end_cnt_bit;//计8bit数据

    //第一段:时序逻辑描述状态转移
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cstate <= IDLE;
        end 
        else begin 
            cstate <= nstate;
        end 
    end
    
    //第二段:组合逻辑描述状态转移规律和状态转移条件
    always @(*) begin
        case(cstate)
            IDLE  :begin
                if (IDLE_START) begin
                    nstate = START;
                end
                else begin
                    nstate = cstate;
                end
            end
            START :begin
                if (START_DATA) begin
                    nstate = DATA;
                end
                else begin
                    nstate = cstate;
                end
            end
            DATA  :begin
                if (DATA_IDLE) begin
                    nstate = IDLE;
                end
                else begin
                    nstate = cstate;
                end
            end
            default : nstate = IDLE;
        endcase
    end

    //第三段:描述输出,时序逻辑或组合逻辑皆可
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            rx_data <= 0;
        end
        else if (cstate == DATA && cnt_baud == MAX_1bit >> 1) begin//电平中间值采样,边沿采样容易出错
            rx_data[cnt_bit] <= rx;
        end
        else begin
            rx_data <= rx_data;
        end
    end

    assign rx_data_vld = DATA_IDLE;//开始传输数据信号为计满数据位
    
    
endmodule

3.ctrl(FIFO)

/**************************************功能介绍***********************************
Date	: 2023年8月16日18:43:33
Author	: Alegg xy.
Version	: 1.0
Description: 调用FIFO
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module ctrl( 
    input				clk		,
    input				rst_n	,
    input       [7:0]   rx_data ,
    input               rx_data_vld,
    input               ready   ,
    output              tx_data_vld,
    output      [7:0]   tx_data
);								 
//---------<参数定义>--------------------------------------------------------- 
    wire    fifo_rdempty;//FIFO读空信号
    wire    fifo_wrfull;//FIFO写满信号
//---------<内部信号定义>-----------------------------------------------------
    fifo	fifo_inst (
	    .aclr ( ~rst_n ),
	    .data ( rx_data ),
	    .rdclk ( clk ),
	    .rdreq ( ready && ~fifo_rdempty ),
	    .wrclk ( clk ),
	    .wrreq ( rx_data_vld && ~fifo_wrfull ),
	    .q ( tx_data ),
	    .rdempty ( fifo_rdempty ),
	    .wrfull ( fifo_wrfulll )
	);
    
    assign tx_data_vld = ready && ~fifo_rdempty;
    
    
endmodule

4.top

/**************************************功能介绍***********************************
Date	: 2023年8月16日18:51:42 
Author	: Alegg xy.
Version	: 1.0
Description: 顶层模块
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module top( 
    input				clk		,
    input				rst_n	,
    input				rx		,
    output              tx
);								 
//---------<参数定义>--------------------------------------------------------- 
    wire    [7:0]   tx_data;
    wire            tx_data_vld;

    wire    [7:0]   rx_data;
    wire            rx_data_vld;

    wire            ready;
//---------<内部信号定义>-----------------------------------------------------
    uart_tx u_uart_tx( 
        .clk		(clk),
        .rst_n	    (rst_n),
        .tx_data    (tx_data),
        .tx_data_vld(tx_data_vld),
        .ready      (ready),
        .tx         (tx)        
    );
    
    uart_rx u_uart_rx( 
        .clk		(clk),
        .rst_n	    (rst_n),
        .rx         (rx),
        .rx_data_vld(rx_data_vld),
        .rx_data    (rx_data)        
    );

    ctrl u_ctrl( 
        .clk		(clk),
        .rst_n	    (rst_n),
        .rx_data    (rx_data),
        .rx_data_vld(rx_data_vld),
        .ready      (ready),
        .tx_data_vld(tx_data_vld),
        .tx_data    (tx_data)
    );
    
    
endmodule

四.效果

串口fifo,FPGA学习,fpga文章来源地址https://www.toymoban.com/news/detail-820228.html

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

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

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

相关文章

  • FPGA学习笔记——FIFO读写

    【实验任务】向FIFO中以50MHz的频率按顺序写入0~254,再从FIFO中以5Hz的频率按顺序读出0~254,输出到LED中点亮。 FIFO全称为“First-In-First-Out”,是FPGA内部的存储数据的缓冲器,读写数据具有先入先出的特点,与数据结构中的“队列”有异曲同工之妙。 本博客例化紫光同创官方提

    2024年02月15日
    浏览(35)
  • FPGA学习笔记(3):FIFO

    FIFO是First Input First Output的英文简写 代表先进的数据先出 ,后进的数据后出。 FIFO存储器是系统的缓冲环节,如果没有FIFO存储器,整个系统就不可能正常工作。 FIFO的功能可以概括为 (1)对连续的数据流进行缓存,防止在进机和存储操作时丢失数据; (2)数据集中起来进行

    2024年01月19日
    浏览(40)
  • FPGA 学习分享-- 04 FIFO核的使用(2)

    写在前面: 博主耗费了四天!!!完成了FIFO核的第二部分。 在这个部分,博主遇到了很多问题,对着代码不停修改,询问学长和老师,好在终于没有报错,可以向大家交作业了!当然,我会在本文详细的帮助大家学习FIFO核的代码编写,带着大家剖析每个部分,尽可能地通俗

    2024年02月03日
    浏览(41)
  • FPGA原理与结构——FIFO IP核原理学习

    系列文章目录:FPGA原理与结构(0)——目录与传送门         FIFO是英文First-In-First-Out的缩写,是一种先入先出的数据缓冲器,与一般的存储器的区别在于没有地址线, 使用起来简单,缺点是只能顺序读写数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器

    2024年02月11日
    浏览(48)
  • FPGA原理与结构(12)——FIFO IP核原理学习

    系列文章目录:FPGA原理与结构(0)——目录与传送门         FIFO是英文First-In-First-Out的缩写,是一种先入先出的数据缓冲器,与一般的存储器的区别在于没有地址线, 使用起来简单,缺点是只能顺序读写数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器

    2024年02月08日
    浏览(44)
  • FPGA之FIFO详解,初识FIFO

           在篇博客里引入FIFO IP核的概念,FIFO是FPGA中最常用的IP核,经常用在接口模块、串并转换、协议处理、数据缓存等很多场合,所以活学活用这个IP核对于后期项目开发很重要,并且灵活掌握FIFO,也是一名合格的FPGA工程师的一项基本功。        FIFO顾名思义就是First

    2024年01月20日
    浏览(46)
  • FPGA中FIFO的应用(二)——异步FIFO设计

    ⭐️作者简介: 小瑞同学 ,一个努力精进的 FPGA 和通信学习者。 🍎个人主页:小瑞同学的博客主页 🌻个人信条:越努力,越幸运! ⏰日期:2023.12.3 🔍来源:自学经历 📖文章内容概述:介绍了 异步FIFO 的基本工作原理和深度计算,通过仿真观察了其读写过程。 连载系列

    2024年02月03日
    浏览(44)
  • FPGA FIFO基本介绍(FIFO Geneerator(13.2))

    软件:vivado 2020.2  参考文献: 文档xilinx官网pg057-fifo-generator文档下载链接官网https://docs.xilinx.com/v/u/en-US/pg057-fifo-generatorhttps://docs.xilinx.com/v/u/en-US/pg057-fifo-generator https://docs.xilinx.com/v/u/en-US/pg057-fifo-generator 原官网免费文档已被上传为付费文档,笔者上传的免费文档未过审核。

    2024年01月25日
    浏览(46)
  • FPGA——FIFO

    FIFO FIFO(First In First Out,即先入先出),是一种数据缓冲器,用来实现数据先入先出的读写方式。FIFO 根据读写时钟是否相同,分为 SCFIFO(single-clock FIFO)和 DCFIFO(duabl-clock FIFO),SCFIFO 的读写为同一时钟,应用在同步时钟系统中;DCFIFO 的读写时钟不同,应用在异步时钟系统

    2024年02月05日
    浏览(41)
  • 【LabVIEW FPGA入门】FIFO

            要在 FPGA VI 的不同部分之间或 FPGA 目标中的 VI 之间传输缓冲数据,可使用 FIFO。FIFO 是一种先进先出的缓冲器,第一个写入内存的数据项就是第一个从内存中读取和删除的数据项,类似于队列。         FPGA FIFO 的功能类似于一个固定长度的队列,可将多个数据

    2024年03月27日
    浏览(49)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包