首页 > 其他分享 >三大低速总线之UART

三大低速总线之UART

时间:2022-10-31 14:11:13浏览次数:54  
标签:wire UART 总线 rx sys flag rst reg 三大

1、串口又叫通用异步收发传输器,即UART;是一种通用的数据通信协议。

2、接受数据时:将接收到的串行数据转换成并行数据;(涉及到串转并

发送数据时:将并行数据转换成串行数据来传输;(涉及到并转串

3、串口常见总线包括:RS232、RS499、RS423、RS422、RS485;

​4、在信息传输通道中,携带数据信息的信号单元叫码元(因为串口是 1bit 进行传输的,所以其码元就是代表一个二进制数)

​5、波特率:每秒钟通过信号传输的码元数称为码元的传输速率,简称波特率;单位为Bps;

​6、比特率:每秒钟通信信道传输的信息量称为位传输速率,简称比特率;单位为bps;且可由波特率算出。公式为:比特率=波特率 * 单个调制状态对应的二进制位数。例如使用的是9600的波特率,则其串口的比特率为:9600Bps*1bit=9600bps;

​7、串口发送和接收数据的格式:1bit起始位(高电平)+8bit数据位+1bit停止位(高电平)

例子:串口回环(电脑通过串口发送数据到FPGA,FPGA接收串口的数据并将接收的数据通过串口回传给电脑)

整体模块划分:

点击查看代码
module  rs232
(
    input   wire    sys_clk,
    input   wire    sys_rst_n,
    input   wire    rx,
    
    output  wire    tx
);

wire    [7:0]   rx_data;
wire            rx_flag;

uart_rx
#(
    .UART_BPS(9600       ),
    .CLK_FREQ(50_000_000 )
)
uart_rx_inst
(
    .sys_clk  (sys_clk  ),
    .sys_rst_n(sys_rst_n),
    .rx       (rx       ),
               
    .po_data  (rx_data  ),
    .po_flag  (rx_flag  )  
);

uart_tx
#(
    .UART_BPS(9600      ),
    .CLK_FREQ(50_000_000)
)
uart_tx_inst
(
    .sys_clk  (sys_clk  ),
    .sys_rst_n(sys_rst_n),
    .pi_data  (rx_data  ),
    .pi_flag  (rx_flag  ),
               
    .tx       (tx       )
);

endmodule

其中,接收模块如下:

波形图如下:

点击查看代码
module  uart_rx
#(
    parameter       UART_BPS    = 'd9600,
    parameter       CLK_FREQ    = 'd50_000_000
)
(
    input   wire            sys_clk,
    input   wire            sys_rst_n,
    input   wire            rx,
                          
    output  reg    [7:0]    po_data,
    output  reg             po_flag    
);

parameter   BAUD_CNT_MAX=CLK_FREQ/UART_BPS;

reg             rx_reg1;
reg             rx_reg2;
reg             rx_reg3;
reg             start_flag; 
reg             work_en;
reg    [12:0]   baud_cnt;
reg             bit_flag;
reg    [3:0]    bit_cnt;
reg    [7:0]    rx_data;
reg             rx_flag;

//打一拍(rx_reg1)
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        rx_reg1<=1'b1;
    else 
        rx_reg1<=rx;
        
//打二拍(rx_reg2)
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        rx_reg2<=1'b1;
    else 
        rx_reg2<=rx_reg1;
        
//打三拍(rx_reg3)
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        rx_reg3<=1'b1;
    else 
        rx_reg3<=rx_reg2;

//start_flag
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        start_flag<=1'b0;
    else if((rx_reg2==1'b0)&&(rx_reg3==1'b1))
        start_flag<=1'b1;
    else 
        start_flag<=1'b0;

//work_en
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        work_en<=1'b0;
    else if((bit_cnt==4'd8)&&(bit_flag==1'b1))
        work_en<=1'b0;
    else if(start_flag==1'b1)
        work_en<=1'b1;
        
//baud_cnt
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        baud_cnt<=13'd0;
    else if((baud_cnt==BAUD_CNT_MAX-1)||(work_en==1'b0))
        baud_cnt<=13'd0;
    else
        baud_cnt<=baud_cnt+1'b1;
        
//bit_flag
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        bit_flag<=1'b0;
    else if(baud_cnt==BAUD_CNT_MAX/2-1)
        bit_flag<=1'b1;
    else 
        bit_flag<=1'b0;
        
//bit_cnt
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        bit_cnt<=4'd0;
    else if((bit_cnt==4'd8)&&(bit_flag==1'b1))
        bit_cnt<=4'd0;
    else if(bit_flag==1'b1)
        bit_cnt<=bit_cnt+1'b1;
    
//rx_data
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        rx_data<=8'd0;
    else if((bit_cnt>=4'd1)&&(bit_cnt<=4'd8)&&(bit_flag==1'b1))
        rx_data<={rx_reg3,rx_data[7:1]};
        
//rx_flag
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        rx_flag<=1'b0;
    else if((bit_cnt==4'd8)&&(bit_flag==1'b1))
        rx_flag<=1'b1;
    else 
        rx_flag<=1'b0;
        
//po_data
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        po_data<=8'd0;
    else if(rx_flag==1'b1)
        po_data<=rx_data;
        
//po_flag
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        po_flag<=1'b0;
    else 
        po_flag<=rx_flag;       

endmodule

发送模块如下:

波形图如下:

点击查看代码
module  uart_tx
#(
    parameter       UART_BPS    = 'd9600,
    parameter       CLK_FREQ    = 'd50_000_000
)
(
    input   wire         sys_clk,
    input   wire         sys_rst_n,
    input   wire  [7:0]  pi_data,
    input   wire         pi_flag,
    
    output  reg          tx
);

parameter   BAUD_CNT_MAX=CLK_FREQ/UART_BPS;

reg            work_en;
reg    [12:0]  baud_cnt;
reg            bit_flag;
reg    [3:0]   bit_cnt;

//work_en
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        work_en<=1'b0;
    else if((bit_cnt==4'd9)&&(bit_flag==1'b1))
        work_en<=1'b0;
    else if(pi_flag==1'b1)
        work_en<=1'b1;
        
//baud_cnt
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        baud_cnt<=13'd0;
    else if((baud_cnt==BAUD_CNT_MAX-1)||(work_en==1'b0))
        baud_cnt<=13'd0;
    else if(work_en==1'b1)
        baud_cnt<=baud_cnt+1'd1;
        
//bit_flag
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        bit_flag<=1'b0;
    else if(baud_cnt==13'd1)
        bit_flag<=1'b1;
    else 
        bit_flag<=1'b0;
        
//bit_cnt
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        bit_cnt<=4'd0;
    else if((bit_flag==1'b1)&&(work_en==1'b1))
        bit_cnt<=bit_cnt+1'b1;
    else if((bit_flag==1'b1)&&(bit_cnt==4'd9))
        bit_cnt<=4'd0;
        
//tx
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        tx<=1'b1;
    else if(bit_flag==1'b1)
        case(bit_cnt)
            0:  tx<=1'b0;
            1:  tx<=pi_data[0];
            2:  tx<=pi_data[1];
            3:  tx<=pi_data[2];
            4:  tx<=pi_data[3];
            5:  tx<=pi_data[4];
            6:  tx<=pi_data[5];
            7:  tx<=pi_data[6];
            8:  tx<=pi_data[7];
            9:  tx<=1'b1;
            default:tx<=1'b1;
        endcase

endmodule

关于接收模块中的打拍的问题:单比特信号从慢速时钟域同步到快速时钟域需要使用打两拍的方式消除亚稳态;超过两拍后效果就不明显了。

标签:wire,UART,总线,rx,sys,flag,rst,reg,三大
From: https://www.cnblogs.com/haogegedeboke/p/16844045.html

相关文章

  • 兄弟组件使用中央事件总线进行传值
    兄弟组件使用中央事件总线进行传值 对于非父子组件通讯:使用空实例/中央事件总线.VueX当项目业务复杂程度不高,可以选用中央事件总线解决当项目业务十分庞大时,一......
  • 十四,SpringBoot-整合Quartz
     Quartz是一个任务调度框架,在以前我们使用它的时候都是xml配置的方式,在spingboot中只需要几个注解就可以轻松搞定。主要用到以下几个注解:1.@Scheduled可以理解成触发器2.......
  • Quartz定时调度
    在SpringBoot中有Java自带的av.util.Timer类,SpringBoot自带的Scheduled来实现也有强大的调度器Quartz.Scheduled在Spring3.X引入,默认SpringBoot自带该功能使用起来也......
  • 三大框架的认知
    简单介绍下vue前段三大框架之一,渐进式框架使用的MVVM模式属于数据驱动方式,核心是通过属性访问器和es6代以及观察者模式实现的双向绑定和虚拟DOM技术简单介绍下React前......
  • 8086总线周期
    8086总线周期是由4个时钟周期组成(T1-T4,Tw不包括)分时复用理解:我们知道8086有20位地址总线和16位数据总线和一些控制总线,看图片,金色的就是引脚,CPU的功能就是从存储器内取出......
  • 总线接口部件BIU
    考试题:简答,填空,选择题,BIU主要是理解和记忆,记住BIU的功能和组成,以及各个组成部件的功能。功能:1.形成访问存储器的物理地址 2.访问存储器中取得指令并暂存到指令队列......
  • 【Vue2.0学习】—全局事件总线GlobalEventBus(六十一)
    【Vue2.0学习】—全局事件总线GlobalEventBus(六十一)知识回顾:全局事件总线(GlobalEventBus)一种组件间通信的方式,适用于任意组件间通信安装全局事件总线:使用事件总线:接收数据......
  • 独享HTTP代理必须知道的三大特性
    我们经常会听商家推荐独享代理池,说独享的如何如何好,对于没用过的朋友来说,根本没有概念,那么独享HTTP代理池究竟有哪些特性是我们必须要知道的呢?今天就给大家简单的科普一下......
  • Quartz Scheduler
    SchedulerFactory&Scheduler&QuartzScheduler&QuartzSchedulerThread&ThreadExecutor(DefaultThreadExecutor)&ThreadPool(SimpleThreadPoolandWorkThread)是Qu......
  • javaSE09基础-面向对象三大特征
    面向对象特征封装封装概念:封装,将类的某些信息隐藏在类内部,不允许外部访问,而且时通过该类提供的方法来实现对隐藏信息的操作和访问优点:隐藏类的实现细节类内部的结构可......