串口收发模块设计及仿真验证


异步串行通信(UART)接口之RS232接口协议,现主要应用于模块间通信;

这里完成一次串口回传功能仿真及验证,完成后的模块可嵌入其他应用系统;

RS232接口使用双线通信,波特率9600;

a. rx 表示PC 端的串口发送端(对于FPGA 端,为串口的接收端),在串口空闲状态时,rx 一直处于高电平。若PC 端需要通过串口发送数据,则需要将rx 从高拉低,表示串口发送的起始位,接着依次发送8bit 的数据(最低位优先),发送完最后1bit 数据后,rx 保持高电平(无校验位);

b. 由于PC 端与FPGA 端处于两个时钟域,所以在FPGA 端需要进行跨时钟域处理,即对rx 进行打两拍处理(rx_t,rx_tt),rx_ttt 是rx 的3 级寄存器;

c. rx_flag 是串口处于接收状态的标志信号,rx_flag 拉高的条件是rx 从空闲状态发送起始位的下降沿,拉低条件是接收完一帧串口数据(8bit);

d. baud_cnt 为波特率计数器,FPGA 使用时钟为50MHz,所以串口发送1bit的数据占用的时钟周期为:(1/9600)x109÷20≈5208,该计数器自加的条件为rx_flag 为高,当计数满5207 时,自动清零;

e. bit_flag 为检测rx 上串口数据的标志信号,只有当baud_cnt 计数到2603时,bit_flag 才会拉高。选在baud_cnt 计数器的中间值来检测串口数据,是为提高检测数据的可靠性;

f. bit_cnt 为已接收一帧串口数据的bit 数,其自加条件为bit_flag,当计数到8,即表示接收完一帧数据后清零;

g. rx_data 是接收串口数据的寄存器,位宽为8,该寄存器使用了位拼接操作,其目的是对接收到的串口数据进行移位,将接收到的1bit 数据构造成8bit 的数据,也可以理解成串转并的一个操作;

h. po_flag 为接收完一帧串口数据的标志信号,用于提供给外部模块检测接收到的串口数据,即rx_data 寄存器的值。


 

发送模块设计:

module  rs232_t(
        //system signals
        input                   sclk                    ,
        input                   s_rst_n                 ,
        //input signals
        input           [ 7:0]  tx_data                 ,
        input                   pi_flag                 ,
        //output signals
        output  reg             tx
);
//===================================================================\
// ========= Define Parameter and Internal Signals ==========
//===================================================================/
parameter               BOUND   =       5208                    ;

reg                             flag_tx                         ;
reg     [12:0]                  bound_cnt                       ;
reg                             bit_flag                        ;
reg     [ 8:0]                  bit_cnt                         ;

reg     [ 7:0]                  data                            ;
//===========================================================================
// **************     Main     Code    **************
//===========================================================================
//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                flag_tx <=      1'b0;
        else if(pi_flag == 1'b1 && flag_tx == 1'b0)
                flag_tx <=      1'b1;
        else if(bit_cnt >= 'd8 && bound_cnt >= BOUND)
                flag_tx <=      1'b0;
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                bound_cnt       <=      'd0;
        else if(bound_cnt >= BOUND)
                bound_cnt       <=      'd0;
        else if(flag_tx ==1'b1)
                bound_cnt       <=      bound_cnt + 1'b1;
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                bit_flag        <=      1'b0;
        else if(bound_cnt == BOUND)
                bit_flag        <=      1'b1;
        else
                bit_flag        <=      1'b0;
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                bit_cnt <=      'd0;
        else if(bit_cnt >= 'd8 && bit_flag == 1'b1)
                bit_cnt <=      'd0;
        else if(bit_flag ==1'b1)
                bit_cnt <=      bit_cnt + 1'b1;
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                data    <=      'd0;
        else if(pi_flag == 1'b1)
                data    <=      tx_data;
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                tx      <=      1'b1;
        else if(pi_flag == 1'b1)
                tx      <=      1'b0;
        else if(bit_flag == 1'b1 && flag_tx == 1'b1)
                tx      <=      data[bit_cnt];
        else if(flag_tx == 1'b0)
                tx      <=      1'b1;
end



endmodule

 


 

接收模块设计:

module  rs232_r(
        //system signals
        input                   sclk                    ,
        input                   s_rst_n                 ,
        //input signals
        input                   rx                      ,
        //output signals
        output  reg     [ 7:0]  rx_data                 ,
        output  reg             po_flag                 
);
//===================================================================\
// ========= Define Parameter and Internal Signals ==========
//===================================================================/
parameter               BOUND   =       5208            ;

reg                     rx_r1                           ;
reg                     rx_r2                           ;
reg                     rx_r3                           ;
reg                     flag_rx                         ;
reg             [12:0]  bound_cnt                       ;
reg                     bit_flag                        ;
reg             [ 8:0]  bit_cnt                         ;

//===========================================================================
// **************     Main     Code    **************
//===========================================================================
//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0) begin
                rx_r1   <=      1'b1;
                rx_r2   <=      1'b1;
                rx_r3   <=      1'b1;
        end
        else begin
                rx_r1   <=      rx;
                rx_r2   <=      rx_r1;
                rx_r3   <=      rx_r2;
        end
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                flag_rx <=      1'b0;
        else if(rx_r2 == 1'b0 && rx_r3 == 1'b1)
                flag_rx <=      1'b1;
        else if(bit_cnt == 'd0 && bound_cnt >= BOUND)
                flag_rx <=      1'b0;
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                bound_cnt       <=      'd0;
        else if(bound_cnt >= BOUND)
                bound_cnt       <=      'd0;
        else if(flag_rx ==1'b1)
                bound_cnt       <=      bound_cnt + 1'b1;
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                bit_flag        <=      1'b0;
        else if(bound_cnt == BOUND/2)
                bit_flag        <=      1'b1;
        else
                bit_flag        <=      1'b0;
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                bit_cnt <=      'd0;
        else if(bit_cnt >= 'd8 && bit_flag == 1'b1)
                bit_cnt <=      'd0;
        else if(bit_flag ==1'b1)
                bit_cnt <=      bit_cnt + 1'b1;
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                rx_data         <=      'b0;
        else if(bit_flag == 1'b1)
                rx_data         <=      {rx_r3,rx_data[7:1]};
end

//
always  @(posedge sclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
                po_flag <=      1'b0;
        else if(bit_flag == 1'b1 && bit_cnt >= 'd8)
                po_flag <=      1'b1;
        else
                po_flag <=      1'b0;
end



endmodule

 

 


 

 为方便仿真和验证,设计顶层模块将发送接收模块封装:

module  test(
        //system signals
        input                   sclk                    ,
        input                   s_rst_n                 ,
        input                   rx                      ,
        output  wire            tx
);
//===================================================================\
// ========= Define Parameter and Internal Signals ==========
//===================================================================/

wire   [ 7:0]           rx_data                         ;
wire                    pi_flag                         ;

//===========================================================================
// **************     Main     Code    **************
//===========================================================================

rs232_t rs232_t_inst(
        .sclk                    (sclk                  ),
        .s_rst_n                 (s_rst_n               ),
        .tx_data                 (rx_data               ),
        .pi_flag                 (pi_flag               ),
        .tx                      (tx                    )
);

rs232_r rs232_r_inst(
        .sclk                    (sclk                  ),
        .s_rst_n                 (s_rst_n               ),
        .rx                      (rx                    ),
        .rx_data                 (rx_data               ),
        .po_flag                 (pi_flag               )
);


endmodule

 


 

 发送模块的仿真模块设计:

`timescale      1ns/1ns

module  tb_rs232_t;

reg                     sclk;
reg                     s_rst_n;
wire            [ 7:0]  tx_data;
reg                     pi_flag;
wire                    tx;

assign  tx_data =       8'b00101010;

initial begin
        sclk    =       1'b1;
        s_rst_n<=       1'b0;
        pi_flag<=       1'b0;
        #100
        s_rst_n<=       1'b1;
        pi_flag<=       1'b1;
        #20
        pi_flag<=       1'b0;
end

always  #10     sclk    =       ~sclk;

defparam        rs232_t_inst.BOUND      =       6;

rs232_t rs232_t_inst(
        .sclk                    (sclk                  ),
        .s_rst_n                 (s_rst_n               ),
        .tx_data                 (tx_data               ),
        .pi_flag                 (pi_flag               ),
        .tx                      (tx                    )
);

endmodule

 


顶层模块的仿真模块设计:

`timescale      1ns/1ns

module  tb_test;

reg                     sclk;
reg                     s_rst_n;
reg                     pi_flag;                   
reg                     rx;
wire                    tx;


initial begin
        sclk    =       1'b1;
        s_rst_n <=      1'b0;
        rx      <=      1'b1;
        #100
        s_rst_n <=      1'b1;
        #20
        rx      <=      1'b0;
        #140
        rx      <=      1'b0;
        #140
        rx      <=      1'b0;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b0;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b0;
        #140
        rx      <=      1'b0;
        #140
        rx      <=      1'b0;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b1;
        #140
        rx      <=      1'b0;
end

always  #10     sclk    =       ~sclk;

defparam        test_inst.rs232_t_inst.BOUND      =       6;
defparam        test_inst.rs232_r_inst.BOUND      =       6;

test    test_inst(
        .sclk                   (sclk                   ),
        .s_rst_n                (s_rst_n                ),
        .rx                     (rx                     ),
        .tx                     (tx                     )
);

endmodule

 


下载到芯片完成功能验证时,可使用COM接口或转USB接口与上位机进行通信验证;

 

。。。。。。。。。。。。。。。待续。。。

 

posted @ 2017-05-13 15:36  __大娱乐家  阅读(802)  评论(0编辑  收藏  举报