37.UART(通用异步收发传输器)-RS232(4)

(1)顶层模块设计Visio视图(没有加入baud_set端口):

(2)修改一部分串口接收模块代码:

/*
常见波特率: 4800、9600、14400、115200
在系统时钟为50MHz时,对应计数为:   
(1/4800)    * 10^9 /20 -1 = 10416     
(1/9600)    * 10^9 /20 -1 = 5207
(1/14400)   * 10^9 /20 -1 = 3471
(1/115200)  * 10^9 /20 -1 = 433 
*/

module rs232_rx
(
    input [16:0]    baud_set    ,
    input           clk         ,
    input           reset_n     ,
    input           rx          ,
    input           rx_start    ,
    
    output reg[7:0] rx_data     ,
    output reg      rx_done     
    
);
    
    reg [15:0]      BAUD_MCNT   ;
    reg             rx_reg0     ;
    reg             rx_reg1     ;
    reg             rx_reg2     ;
    reg             en_baud_cnt ;
    reg [15:0]      baud_cnt    ;
    reg [3:0]       bit_cnt     ;
    reg [7:0]       r_rx_data   ;
    
    wire            nedge       ;
    wire            w_rx_done   ;
    
//波特最大计数设计
    always@(posedge clk)
        begin
            case(baud_set)
                17'd4800    :BAUD_MCNT <= 16'd10416;
                17'd9600    :BAUD_MCNT <= 16'd5207;
                17'd14400   :BAUD_MCNT <= 16'd3471;
                17'd115200  :BAUD_MCNT <= 16'd433;
                default     :BAUD_MCNT <= 16'd5207;      //当输入baud_set为其他值时,一律当成9600处理。
            endcase
        end
    
//输入信号打拍处理
    always@(posedge clk)
        begin
            rx_reg0 <= rx;
            rx_reg1 <= rx_reg0;
        end

//下降沿设计
    always@(posedge clk)
        rx_reg2 <= rx_reg1;
        
    assign nedge = (rx_reg2) && (!rx_reg1);
    
//波特率计数使能信号设计 
   always@(posedge clk or negedge reset_n)
        if(!reset_n)
            en_baud_cnt <= 1'd0;
        else if(!rx_start)
            en_baud_cnt <= 1'd0;
        else if(nedge)
            en_baud_cnt <= 1'd1;
        else if((bit_cnt == 4'd0) && (baud_cnt == BAUD_MCNT/2)&&(rx_reg2))      //防止起始位只是一个抖动
            en_baud_cnt <= 1'd0;
        else if((bit_cnt == 4'd9) && (baud_cnt == BAUD_MCNT/2))
            en_baud_cnt <= 1'd0;
        else    
            en_baud_cnt <= en_baud_cnt;
            
//波特计数器模块设计
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            baud_cnt <= 16'd0;
        else if(!en_baud_cnt)
            baud_cnt <= 16'd0;
        else if((baud_cnt == BAUD_MCNT) || ((bit_cnt == 4'd9) && (baud_cnt == BAUD_MCNT/2)))
            baud_cnt <= 16'd0;
        else 
            baud_cnt <= baud_cnt + 16'd1;
            
//位计数器模块设计
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            bit_cnt <= 4'd0;
        else if((baud_cnt == BAUD_MCNT/2) &&(bit_cnt == 4'd9))
            bit_cnt <= 4'd0;
        else if(baud_cnt == BAUD_MCNT)
            bit_cnt <= bit_cnt + 4'd1;
        else 
            bit_cnt <= bit_cnt;
            
//rx_data设计
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            r_rx_data <= 8'd0;
        else if(baud_cnt == BAUD_MCNT/2)begin
            case(bit_cnt)
                4'd1: r_rx_data[0] <= rx_reg2;
                4'd2: r_rx_data[1] <= rx_reg2;
                4'd3: r_rx_data[2] <= rx_reg2;
                4'd4: r_rx_data[3] <= rx_reg2;
                4'd5: r_rx_data[4] <= rx_reg2;
                4'd6: r_rx_data[5] <= rx_reg2;
                4'd7: r_rx_data[6] <= rx_reg2;
                4'd8: r_rx_data[7] <= rx_reg2;
                default:r_rx_data <= r_rx_data;
            endcase
        end
        else 
            r_rx_data <= r_rx_data;
    
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            rx_data <= 8'd0;
        else if(w_rx_done)
            rx_data <= r_rx_data;
        else    
            rx_data <= rx_data;
    
//w_rx_done和rx_done信号设计
    assign w_rx_done = (bit_cnt == 4'd9) && (baud_cnt == BAUD_MCNT/2) ;
    
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            rx_done <= 1'd0;
        else 
            rx_done <= w_rx_done;
            
endmodule

(3)顶层模块代码:

module rx232
(
    input               clk     ,
    input               reset_n ,
    input               rx      ,
    
    output              tx      ,
    output     reg      led 
);

    wire            tx_done ;
    wire    [7:0]   rx_data ;
    wire            rx_done ;
    wire    [7:0]   tx_data ;
    wire            tx_start;

assign tx_data  = rx_data;
assign tx_start = rx_done;

rs232_rx    rs232_rx_inst0
(
    .baud_set    ( 17'd9600 )     ,
    .clk         ( clk      )     ,
    .reset_n     ( reset_n  )     ,
    .rx          ( rx       )     ,
    .rx_start    ( 1'd1     )     ,

    .rx_data     ( rx_data  )     ,
    .rx_done     ( rx_done  )     
    
);

rs232_tx rs232_tx_inst0
(
    .baud_set       ( 17'd9600 )        ,
    .clk            ( clk      )        ,
    .reset_n        ( reset_n  )        ,
    .tx_data        ( tx_data  )        ,
    .tx_start       ( tx_start )        ,

    .tx             ( tx       )        ,
    .tx_done        ( tx_done  )           
    
);

always@(posedge clk or negedge reset_n)
    if(!reset_n)
        led <= 1'd0;
    else if(tx_done)
        led <= ~led;
    else 
        led <= led;

endmodule

(4)仿真文件代码:

`timescale 1ns / 1ps

module rx232_tb;

reg    clk       ;
reg    reset_n   ;
reg    rx        ;

wire   tx        ;
wire   led       ;

initial clk = 1'd1;
always #10 clk = ~clk;

initial begin
   reset_n <= 1'd0;
   rx      <= 1'd1;
   #22;
   reset_n <= 1'd1;
   #2000;
   @(posedge clk);
   set_byte();
   #2000000;
   $stop;
end

task set_byte();

integer j;

for(j = 1;j < 20; j = j + 3)
        set_bit(j);
endtask

task set_bit(
    input [7:0]data
);

integer i;
for(i = 0; i < 10; i = i + 1)begin
    case(i)
       0:   rx <= 1'd0;
       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'd1;
    endcase
    #(5208 * 20);
end
endtask

rx232  rx232_inst
(
    .clk     (clk    ),
    .reset_n (reset_n),
    .rx      (rx     ),
    
    .tx      (tx     ),
    .led     (led    )
);

endmodule

(5)仿真波形:

        波特率均固定在9600,波特率计数器最大值固定在5207:

        rs232接收模块顺利将rx串行数据转换成了[7:0]rx_data并行数据,并输出了rx_done信号,将它们赋值给了rs232发送模块的[7:0]tx_data信号和tx_start信号:

        现以传输的数据13为例,比较rx与tx信号的细节,且可以观察到led随着tx发送完一次数据而翻转:

(6)引脚绑定:

(7)开发板连接图:

(8)串口调试:

led翻转

传输多个数据:

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值