串口RS232:

1、串口简介:

        通用异步收发传输器,英文全称Universal Asynchronous Receiver/Transmitter , 简称UART。

        UART是一种通用的数据通信协议,也是异步串行通信(串口)的总称,它在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据

        包括RS232,RS499,RS423,RS422和RS485等接口标准规范和总线标准规范。

2、串口通信方式:(全双工通信)

缺点:传输距离近,传输速度慢;

优点:应用广泛,适配传感器

3、串口RS232接口:

补充:波特率:每秒中通过的码元个数,称为码元的传输速率,也称作波特率;

           符号:Band   单位:Bps

           比特率:每秒传输的比特数; 单位: bps

           比特率 = 波特率 * 每个调制状态对应的二进制数

           串口接收和发送1bit数据的时间,称之为一个波特,比如波特率为9600.那么其波特率为:

(1 / 9600) s,如果系统时钟是50Mhz, 那么其系统时钟是20ns,那么在9600的波特率下,一个波特等于 5208个系统时钟周期;

4、实践:在FPGA内部实现一个数据收发模块,在pc端用串口助手做一个串口收发回环检测;

4.1 模块设计

顶层:

接收子模块:(将接收的串行数据转为并行数据发给发送子模块)

发送子模块:(将接收的并行数据转为串行数据输出)

整体系统框图:

4.2 波形设计

4.2.1 补充知识:亚稳态

亚稳态形成原因:由于信号输入到寄存器的时候,建立时间保持时间不满足我们的条件,会导致亚稳态的产生;

建立时间:Tsu :时钟信号上升沿到来之前,信号维持一定时间的稳定状态,这个信号稳定不变的最小时间称为建立时间;

保持时间:Th:触发器时钟上升沿到达以后,信号维持一定时间的稳定状态,这个信号稳定不变的最小时间称为保持时间;

寄存器延迟时间:Tco: 信号在寄存器内部传输的时间;

决断时间:Tmet:当信号震荡需要做出0/1判决的时间

亚稳态的消除:使用寄存器,因为每经过一个寄存器,决断时间就会缩短,多打几拍(经历多级寄存器),单bit信号一般为了减少亚稳态打两拍即可;

 4.2.2 接收模块

4.2.3 发送模块 

4.3 程序设计

 4.3.1 接收模块

module  uart_rx
#(
    parameter   UART_BAUD = '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_BAUD; //baud-rate:9600; sys_clk:50MHz;(1/9600)/(1/50MHz)

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

//Tapping the input signal:rx
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        rx_reg1 <= 1'b1;
    else
        rx_reg1 <= rx;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        rx_reg2 <= 1'b1;
    else
        rx_reg2 <= rx_reg1;

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

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

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        work_en <= 1'b0;
    else if(start_flag == 1'b1)
        work_en <= 1'b1;
    else if((bit_cnt == 4'd8) && (bit_flag == 1'b1))
        work_en <= 1'b0;
    else
        work_en <= work_en;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        baud_cnt <= 16'd0;
    else if(baud_cnt == BAUD_CNT_MAX - 1 || work_en == 1'b0)
        baud_cnt <= 16'd0;
    else
        baud_cnt <= baud_cnt + 1'b1;
        
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;
        
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;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        rx_data <= 8'b0;
    else if((bit_cnt >= 4'd1)&&(bit_cnt <= 4'd8)&&(bit_flag == 1'b1))
        rx_data <= {rx_reg3,rx_data[7:1]};

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;
        
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;

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

仿真部分:tb_uart_rx:

`timescale 1ns/1ns
module  tb_uart_rx();

reg         sys_clk     ;
reg         sys_rst_n   ;
reg         rx          ;

wire    [7:0]   po_data ;
wire            po_flag ;

initial
    begin
        sys_clk = 1'b1;
        sys_rst_n <= 1'b0;
        rx        <= 1'b1;
        #20
        sys_rst_n <= 1'b1;
    end
//Analog sends data 8 times, respectively 0~7
 initial begin
    #200
    rx_bit(8'd0);
    rx_bit(8'd1);
    rx_bit(8'd2);
    rx_bit(8'd3);
    rx_bit(8'd4);
    rx_bit(8'd5);
    rx_bit(8'd6);
    rx_bit(8'd7);
 end

always #10 sys_clk = ~sys_clk;

//use the task function to assign values to rx
task    rx_bit
(
    input   [7:0]   data
);

    integer i;

for(i = 0; i < 10; i = i + 1)
    begin
        case(i)
            0:rx <= 1'b0;
            1:rx <= data[0];
            2:rx <= data[1];
            3:rx <= data[2];
            4:rx <= data[3];
            5:rx <= data[4];
            6:rx <= data[5];
            7:rx <= data[6];
            8:rx <= data[7];
            9:rx <= 1'b1;
        endcase
        #(5208*20);
    end
endtask

uart_rx
#(
    .UART_BAUD   (9600      ),
    .CLK_FREQ    (50_000_000)
)  
uart_rx_inst
(
    .sys_clk    (sys_clk    ),
    .sys_rst_n  (sys_rst_n  ),
    .rx         (rx         ),

    .po_data    (po_data    ),
    .po_flag    (po_flag    )
);

endmodule

4.3.2 发送模块

module uart_tx
#(
    parameter   UART_BAUD = '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_BAUD; //baud-rate:9600; 

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

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;
    else
        work_en <= work_en;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        baud_cnt <= 16'd0;
    else if(work_en == 1'b0 || baud_cnt == BAUD_CNT_MAX - 1)
        baud_cnt <= 16'd0;
    else if(work_en == 1'b1)
        baud_cnt <= baud_cnt + 1'b1;
 
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        bit_flag <= 1'b0;
    else if(baud_cnt == 16'd1)
        bit_flag <= 1'b1;
    else
        bit_flag <= 1'b0;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)    
        bit_cnt <= 4'd0;
    else if(bit_cnt == 4'd9 && bit_flag == 1'b1)
        bit_cnt <= 4'd0;
    else if(bit_flag == 1'b1)
        bit_cnt <= bit_cnt + 1'b1;

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

仿真部分:tb_uart_tx:

`timescale  1ns/1ns
module  tb_uart_tx();

reg         sys_clk     ;
reg         sys_rst_n   ;
reg [7:0]   pi_data     ;
reg         pi_flag     ;
wire        tx          ;

initial
    begin
        sys_clk = 1'b1;
        sys_rst_n <= 1'b0;
        #20
        sys_rst_n <= 1'b1;
    end

always #10 sys_clk = ~ sys_clk;

initial
    begin
        pi_data <= 8'd0;
        pi_flag <= 1'b0;
        #200
        //data 0
        pi_data <= 8'd0;
        pi_flag <= 1'b1;
        #20
        pi_flag <= 1'b0;
        #(5208 * 10 * 20)
        //data 1
        pi_data <= 8'd1;
        pi_flag <= 1'b1;
        #20
        pi_flag <= 1'b0;
        #(5208 * 10 * 20)
        //data 2
        pi_data <= 8'd2;
        pi_flag <= 1'b1;
        #20
        pi_flag <= 1'b0;
        #(5208 * 10 * 20)
        //data 3
        pi_data <= 8'd3;
        pi_flag <= 1'b1;
        #20
        pi_flag <= 1'b0;
        #(5208 * 10 * 20)
        //data 4
        pi_data <= 8'd4;
        pi_flag <= 1'b1;
        #20
        pi_flag <= 1'b0;
        #(5208 * 10 * 20)
        //data 5
        pi_data <= 8'd5;
        pi_flag <= 1'b1;
        #20
        pi_flag <= 1'b0;
        #(5208 * 10 * 20)
        //data 6
        pi_data <= 8'd6;
        pi_flag <= 1'b1;
        #20
        pi_flag <= 1'b0;
        #(5208 * 10 * 20)
        //data 7
        pi_data <= 8'd7;
        pi_flag <= 1'b1;
        #20
        pi_flag <= 1'b0;      
    end

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     (pi_data   ),
    .pi_flag     (pi_flag   ),

    .tx          (tx        )
);

endmodule

4.3.3 顶层模块

module rs232
(
    input   wire        sys_clk     ,
    input   wire        sys_rst_n   ,
    input   wire        rx          ,
    
    output  wire        tx          
); 

 parameter UART_BPS = 14'd9600; //比特率
 parameter CLK_FREQ = 26'd50_000_000; //时钟频率

wire     [7:0]       rx_data;
wire                 rx_flag;


uart_tx
#(
    .UART_BPS   (UART_BPS),
    .CLK_FREQ   (CLK_FREQ) 
)
uart_tx_inst
(
    .sys_clk     (sys_clk),
    .sys_rst_n   (sys_rst_n),
    .pi_data     (rx_data),
    .pi_flag     (rx_flag),
 
    .tx          (tx)
);
uart_rx
#(
    .UART_BAUD  (UART_BPS),
    .CLK_FREQ   (CLK_FREQ)
)
uart_rx_inst
(
    .sys_clk     (sys_clk),
    .sys_rst_n   (sys_rst_n),
    .rx          (rx),
    .po_data     (rx_data),
    .po_flag     (rx_flag)
);

endmodule

总体仿真

`timescale  1ns/1ns
module tb_rs232();

reg         sys_clk     ;
reg         sys_rst_n   ;
reg         rx          ;

wire        tx          ;

initial
    begin
        sys_clk = 1'b1;
        sys_rst_n <= 1'b0;
        rx        <= 1'b1;
        #20
        sys_rst_n <= 1'b1;
    end
    
always #10 sys_clk = ~sys_clk;

initial
    begin
        #200    //idle time
        rx_byte();
    end
        

task   rx_byte(); 
    integer j;
        for(j = 0; j < 8; j = j + 1)
        rx_bit(j);
endtask        

//use the task function to assign values to rx
task    rx_bit
(
    input   [7:0]   data
);

    integer i;

for(i = 0; i < 10; i = i + 1)
    begin
        case(i)
            0:rx <= 1'b0;
            1:rx <= data[0];
            2:rx <= data[1];
            3:rx <= data[2];
            4:rx <= data[3];
            5:rx <= data[4];
            6:rx <= data[5];
            7:rx <= data[6];
            8:rx <= data[7];
            9:rx <= 1'b1;
        endcase
        #(5208*20);
    end
endtask     

rs232   rs232_inst
(
    .sys_clk     (sys_clk),
    .sys_rst_n   (sys_rst_n),
    .rx          (rx),
  
    .tx          (tx)
); 
endmodule

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super_WY_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值