MVP111

导航

Uart回环测试

一、Uart接受模块设计

## 1.串口模块的时序设计图

image
image
image

PS:1. 0-bit_cnt 接受了起始位;1-bit_cnt 接受了数据位第一位;以此类推,8_bit-cnt 接受了数据位第八位;(此时拉高po_flag,表示数据接收完成。
2. bit_cnt>=1时代表着传输数据的开始,结合bit_flag,进行数据的位移操作;
****
如下所示,为具体的verilog实现代码:

点击查看代码
`timescale 1ns / 1ps
`define sim
module uart_rx(
    //system signal
    input                sclk    ,
    input                rst_n   ,
    //uart interface
    input                uart_rx ,
    //others
    output  reg [7:0]    rx_data , 
    output  reg          rx_done
    );

reg               rx_r1     ;
reg               rx_r2     ; //打两拍跨时钟域
reg               rx_r3     ; //检测下降沿
reg               rx_flag   ; 
reg[12:0]         baud_cnt  ;
reg               bit_flag  ;
reg[3:0]          bit_cnt   ;

wire       rx_in_nedge; 
assign     rx_in_nedge = ~rx_r2 & rx_r3;

`ifndef sim
localparam     BAUD_END = 5208 - 1;            //根据波特率设置
`else
localparam     BAUD_END = 56;
`endif 

localparam     BAUD_M   = BAUD_END / 2 - 1;    //在每一位的中间采样
localparam     BIT_END  = 8    ;

always@(posedge sclk,negedge rst_n)begin
    if(!rst_n)begin
        rx_r1 <= 1'b0;
        rx_r2 <= 1'b0;
        rx_r3 <= 1'b0;
    end
    else begin
        rx_r1 <= uart_rx;
        rx_r2 <= rx_r1;
        rx_r3 <= rx_r2;
    end
end

always@(posedge sclk,negedge rst_n)begin
    if(!rst_n)
        rx_flag <= 1'b0;
    else if(rx_in_nedge)
        rx_flag <= 1'b1;
    else if(bit_cnt == 0 && baud_cnt == BAUD_END)
        rx_flag <= 1'b0;
    else
        rx_flag <= rx_flag;
end  
always@(posedge sclk,negedge rst_n)begin
    if(!rst_n)
        baud_cnt <= 13'b0;
    else if(baud_cnt == BAUD_END)
        baud_cnt <= 13'b0;
    else if(rx_flag)
        baud_cnt <= baud_cnt + 1;
    else 
        baud_cnt <= 13'b0;
end   
always@(posedge sclk,negedge rst_n)begin
    if(!rst_n)
        bit_flag <= 1'b0;
    else if(baud_cnt == BAUD_M)
        bit_flag <= 1'b1;
    else 
        bit_flag <= 1'b0;
end     
always@(posedge sclk,negedge rst_n)begin
    if(!rst_n)
        bit_cnt <= 4'b0;
    else if(bit_cnt == 8 && bit_flag)
        bit_cnt <= 4'b0;
    else if(bit_flag)
        bit_cnt <= bit_cnt + 1;
    else
        bit_cnt <= bit_cnt;
end   
always@(posedge sclk,negedge rst_n)begin
    if(!rst_n)
        rx_data <= 8'b0;
    else if(bit_cnt>=1 && bit_flag)    
        rx_data <= {rx_r2,rx_data[7:1]};
    else
        rx_data <= rx_data;
end   
always@(posedge sclk,negedge rst_n)begin
    if(!rst_n)
        rx_done <= 1'b0;
    else if(bit_cnt == 8 && bit_flag)
        rx_done <= 1'b1;
    else 
        rx_done <= 1'b0;
end    
endmodule
下面进行虚拟的仿真,tsetbench如下:
点击查看代码
`timescale 1ns / 1ps

module uart_rx_tb();
reg            sclk;
reg            rst_n; 
reg            uart_rx;

wire[7:0]      rx_data;
wire           rx_done;

reg[7:0]       mem_a[3:0]; //定义了一个深度为4.位宽为8的寄存器

initial sclk = 1;
always #5 sclk =~sclk;

initial $readmemb("tx_data.txt",mem_a);

initial begin
    rst_n   = 0;
    uart_rx = 1;
    #100
    rst_n   = 1;
    #200
    tx_byte();
end

task tx_byte();
    integer i;
    for(i=0;i<4;i=i+1)begin
        tx_bit(mem_a[i]);
    end
endtask

task tx_bit (
    input [7:0] data
);
integer  i;
for(i = 0;i<10;i=i+1)begin
    case(i)
        0: uart_rx <= 1'b0;
        1: uart_rx <= data[0];
        2: uart_rx <= data[1];
        3: uart_rx <= data[2];
        4: uart_rx <= data[3];
        5: uart_rx <= data[4];
        6: uart_rx <= data[5];
        7: uart_rx <= data[6];
        8: uart_rx <= data[7];
        9: uart_rx <= 1'b1;
    endcase
    #560;
end 
endtask

uart_rx  inst0(
    //system signal
    .sclk    (sclk    ),
    .rst_n   (rst_n   ),
    //uart interface 
    .uart_rx (uart_rx ),
    //others
    .rx_data (rx_data ), 
    .rx_done (rx_done ) 
    );

endmodule

posted on 2024-06-16 23:00  MVP-curry-萌神  阅读(147)  评论(0)    收藏  举报