36.UART(通用异步收发传输器)-RS232(3)

(1)串口发送模块visio视图:

(2)串口发送模块Verilog代码:

/*
常见波特率: 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_tx
(
    input   [16:0]  baud_set        ,
    input           clk             ,
    input           reset_n         ,
    input   [7:0]   tx_data         ,
    input           tx_start        ,
    
    output   reg    tx              ,
    output   reg    tx_done            
    
);
    
    reg [15:0]      BAUD_MCNT       ;
    reg [7:0]       r_tx_data       ;
    reg             en_baud_cnt     ;
    reg [15:0]      baud_cnt        ;
    reg [3:0]       bit_cnt         ;
    
    
//波特最大计数设计
    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)
        if(tx_start)
            r_tx_data <= tx_data;
        else
            r_tx_data <= r_tx_data;
        
//波特率计数器使能信号设计
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            en_baud_cnt <= 1'd0;
        else if(tx_start)
            en_baud_cnt <= 1'd1;
        else if((bit_cnt == 4'd9)&&(baud_cnt == BAUD_MCNT))
            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)
            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) && (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;
            
//tx输出序列机设计
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            tx <= 1'd1;
        else if(!en_baud_cnt)
            tx <= 1'd1;
        else if(baud_cnt == 16'd1)begin
            case(bit_cnt)
                4'd0:   tx <= 1'd0;
                4'd1:   tx <= r_tx_data[0];
                4'd2:   tx <= r_tx_data[1];
                4'd3:   tx <= r_tx_data[2];
                4'd4:   tx <= r_tx_data[3];
                4'd5:   tx <= r_tx_data[4];
                4'd6:   tx <= r_tx_data[5];
                4'd7:   tx <= r_tx_data[6];
                4'd8:   tx <= r_tx_data[7];
                4'd9:   tx <= 1'd1;
                default:tx <= 1'd1;
            endcase
        end
        else 
            tx <= tx;
            
//tx_done信号设计
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            tx_done <= 1'd0;
        else if((baud_cnt == BAUD_MCNT) && (bit_cnt == 4'd9))
            tx_done <= 1'd1;
        else 
            tx_done <= 1'd0;
       
endmodule

(3)串口发送模块仿真代码:

`timescale 1ns / 1ps

module rs232_tx_tb;

reg     [16:0]      baud_set    ; 
reg                 clk         ;     
reg                 reset_n     ;
reg     [7:0]       tx_data     ;  
reg                 tx_start    ;

wire                tx          ;
wire                tx_done     ;

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

initial begin
    baud_set <= 17'd9600;
    reset_n <= 1'd0;
    tx_data <= 1'd0;
    tx_start <= 1'd0;
    #21;
    reset_n <= 1'd1;
    #40;
    @(posedge clk);
    //输入数据0
    tx_data <= 8'd0;
    tx_start <= 1'd1;
    #20;
    tx_start <= 1'd0;
    #(5208 * 20 * 10);
    //输入数据1
    tx_data <= 8'd1;
    tx_start <= 1'd1;
    #20;
    tx_start <= 1'd0;
    #(5208 * 20 * 10);
    //输入数据2
    tx_data <= 8'd2;
    tx_start <= 1'd1;
    #20;
    tx_start <= 1'd0;
    #(5208 * 20 * 10);
    //输入数据3
    tx_data <= 8'd3;
    tx_start <= 1'd1;
    #20;
    tx_start <= 1'd0;
    #(5208 * 20 * 10);
    //输入数据4
    tx_data <= 8'd4;
    tx_start <= 1'd1;
    #20;
    tx_start <= 1'd0;
    #(5208 * 20 * 10);
    //输入数据5
    tx_data <= 8'd5;
    tx_start <= 1'd1;
    #20;
    tx_start <= 1'd0;
    #(5208 * 20 * 10);
    //输入数据6
    tx_data <= 8'd6;
    tx_start <= 1'd1;
    #20;
    tx_start <= 1'd0;
    #(5208 * 20 * 10);
    //输入数据7
    tx_data <= 8'd7;
    tx_start <= 1'd1;
    #20;
    tx_start <= 1'd0;
    #(5208 * 20 * 10);
    $stop;
end

rs232_tx rs232_tx_inst
(
    .baud_set       ( baud_set)        ,
    .clk            ( clk     )        ,
    .reset_n        ( reset_n )        ,
    .tx_data        ( tx_data )        ,
    .tx_start       ( tx_start)        ,
    
    .tx             ( tx      )        ,
    .tx_done        ( tx_done )           
    
);

endmodule

(4)仿真波形:

同时,可以看见,tx一开始被赋予了高电平,在波特计数器计数为1,起始位时被拉低。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值