当前位置:   article > 正文

FPAG—UART串口实现与解析-黑金fpga资料解析_黑金fpga开发板串口例程

黑金fpga开发板串口例程

UART实现-黑金fpga开发板案例解析

uart 异步串口通讯 无需时钟线,俩根线一跟复制发数据一根负责收数据。

具体的时序如下图1:
请添加图片描述

图1:UART时序图

可以看到 当数据线由高位变为地位时,即遇到一个下降沿时刻,表示开始这一次数据开始发送/接受,然后的高低电平表示数据位,一般是7-8个数据位,一般为8个,即一个字节,并可以添加校验位与停止位。

波特率介绍,由于uart通讯,使用单线单独进行数据传输,所有需要保证发送端与接收端能正常通讯,需要对信号进行约束,简单来说,就是对信号的采样频率进行设定。

当设置波特率为 115200 的时候,如果时钟信号时 50Mhz,这里,数据的一个位的高低电平持续时间应该时 50_000_000 / 115200 这么多个时钟,这样就可以约定发送与接收端,相隔一定的时间对信号线进行采样,得到的每位的高低电平表示这位的数据。

程序设计

包括收和发的设计,使用状态机的思想进行程序设计

接收模块设计

请添加图片描述

图2:状态机设计
### 程序设计

整体的设计思路保持在一个always语句块里,只对一个reg变量进行赋值。

  • 构造状态机的状态常量

    localparam                       S_IDLE      = 1;
    localparam                       S_START     = 2; //start bit
    localparam                       S_REC_BYTE  = 3; //data bits
    localparam                       S_STOP      = 4; //stop bit
    localparam                       S_DATA      = 5;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 构造状态机的状态变量进行状态切换

    reg[2:0]                         state;
    reg[2:0]                         next_state;
    always@(posedge clk or negedge rst_n)
    begin
    	if(rst_n == 1'b0)
    		state <= S_IDLE;
    	else
    		state <= next_state;
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这里,state是当前时钟的变量,next_state是下一时钟的变量

  • 对输入信号获得俩个节拍

    reg                              rx_d0;            //delay 1 clock for rx_pin
    reg                              rx_d1;            //delay 1 clock for rx_d0
    always@(posedge clk or negedge rst_n)
    begin
    	if(rst_n == 1'b0)
    	begin
    		rx_d0 <= 1'b0;
    		rx_d1 <= 1'b0;	
    	end
    	else
    	begin
    		rx_d0 <= rx_pin;
    		rx_d1 <= rx_d0;
    	end
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这样 可以通过比较d0和d1去判断输入信号的上升沿还是下降沿

    assign rx_negedge = rx_d1 && ~rx_d0;
    
    • 1
  • 状态机的具体实现

    S_IDLE 在这里检测下降沿 如果检测到下降沿 则切换到 S_START状态

    S_START 检测波特率计数器是否计数满 如果计数满了 则跳转到S_REC_BYTE数据接受状态,如果没满,则保持这个状态,等待计数满,其实也就是一个下降沿之后要保持一个bit的低电平时间之后才开始发送数据

    S_REC_BYTE 接受数据状态,在这个状态逐个接受数据,并检测是否接受完毕,完毕则跳转下一个S_STOP状态,没有则保持这个状态

    S_STOP 等待半个bit时间,跳转到下一个S_DATA状态

    S_DATA

    always@(*)
    begin
    	case(state)
    		S_IDLE:
    			if(rx_negedge)
    				next_state <= S_START;
    			else
    				next_state <= S_IDLE;
    		S_START:
    			if(cycle_cnt == CYCLE - 1)//one data cycle 
    				next_state <= S_REC_BYTE;
    			else
    				next_state <= S_START;
    		S_REC_BYTE:
    			if(cycle_cnt == CYCLE - 1  && bit_cnt == 3'd7)  //receive 8bit data
    				next_state <= S_STOP;
    			else
    				next_state <= S_REC_BYTE;
    		S_STOP:
    			if(cycle_cnt == CYCLE/2 - 1)//half bit cycle,to avoid missing the next byte receiver
    				next_state <= S_DATA;
    			else
    				next_state <= S_STOP;
    		S_DATA:
    			if(rx_data_ready)    //data receive complete
    				next_state <= S_IDLE;
    			else
    				next_state <= S_DATA;
    		default:
    			next_state <= S_IDLE;
    	endcase
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
  • 接受数据状态时进行接受数据

当在结束收据状态,且bit计数器到一半的时候,进行一次采样,也就是在中点进行采样,获取数据的高低电平,共采集八次,将八次的数据保存到rx_bits

reg[7:0]               
    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/724744
    推荐阅读
    相关标签
      

    闽ICP备14008679号