UART

10021 ワード

タンデム実験
注意:連続送信の精度を確保するために、システムクロックを50 Hz 1)トップレベルの実験モジュールに倍周波数することができる.
module uart_top(
    input           sys_clk,          //  50M  
    input           sys_rst_n,        //      ,   
    //uart  
    input           uart_rxd,         //UART    
    output          uart_txd          //UART    
    );
    
//parameter define
parameter  CLK_FREQ = 50000000;       //        
parameter  UART_BPS = 115200;         //       
    
//wire define   
wire       uart_en_w;                 //UART    
wire [7:0] uart_data_w;               //UART    

//*****************************************************
//**                    main code
//*****************************************************     
uart_recv #(                          //      
    .CLK_FREQ       (CLK_FREQ),       //        
    .UART_BPS       (UART_BPS))       //         
u_uart_recv(                 
    .sys_clk        (sys_clk), 
    .sys_rst_n      (sys_rst_n),
    
    .uart_rxd       (uart_rxd),
    .uart_done      (uart_en_w),
    .uart_data      (uart_data_w)
    );
    
uart_send #(                          //      
    .CLK_FREQ       (CLK_FREQ),       //        
    .UART_BPS       (UART_BPS))       //         
u_uart_send(                 
    .sys_clk        (sys_clk),
    .sys_rst_n      (sys_rst_n),
     
    .uart_en        (uart_en_w),
    .uart_din       (uart_data_w),
    .uart_txd       (uart_txd)
    );

endmodule 

2)受入モジュール
module uart_recv(
    input			  sys_clk,                  //    
    input             sys_rst_n,                //    ,     
    
    input             uart_rxd,                 //UART    
    output  reg       uart_done,                //            
    output  reg [7:0] uart_data                 //     
    );
    
//parameter define
parameter  CLK_FREQ = 50000000;                 //      
parameter  UART_BPS = 9600;                     //     
localparam BPS_CNT  = CLK_FREQ/UART_BPS;        //        ,
                                                //         BPS_CNT 
//reg define
reg        uart_rxd_d0;
reg        uart_rxd_d1;
reg [15:0] clk_cnt;                             //       
reg [ 3:0] rx_cnt;                              //       
reg        rx_flag;                             //        
reg [ 7:0] rxdata;                              //       

//wire define
wire       start_flag;

//*****************************************************
//**                    main code
//*****************************************************
//         (   ),             
assign  start_flag = uart_rxd_d1 & (~uart_rxd_d0);    

// UART               
always @(posedge sys_clk or negedge sys_rst_n) begin 
    if (!sys_rst_n) begin 
        uart_rxd_d0 <= 1'b0;
        uart_rxd_d1 <= 1'b0;          
    end
    else begin
        uart_rxd_d0  <= uart_rxd;                   
        uart_rxd_d1  <= uart_rxd_d0;
    end   
end

//     start_flag   ,                 
always @(posedge sys_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n)                                  
        rx_flag <= 1'b0;
    else begin
        if(start_flag)                          //      
            rx_flag <= 1'b1;                    //      ,   rx_flag  
        else if((rx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2))
            rx_flag <= 1'b0;                    //         ,      
        else
            rx_flag <= rx_flag;
    end
end

//       ,                 
always @(posedge sys_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n) begin                             
        clk_cnt <= 16'd0;                                  
        rx_cnt  <= 4'd0;
    end                                                      
    else if ( rx_flag ) begin                   //      
            if (clk_cnt < BPS_CNT - 1) begin
                clk_cnt <= clk_cnt + 1'b1;
                rx_cnt  <= rx_cnt;
            end
            else begin
                clk_cnt <= 16'd0;               //                  
                rx_cnt  <= rx_cnt + 1'b1;       //          1
            end
        end
        else begin                              //      ,     
            clk_cnt <= 16'd0;
            rx_cnt  <= 4'd0;
        end
end

//            uart      
always @(posedge sys_clk or negedge sys_rst_n) begin 
    if ( !sys_rst_n)  
        rxdata <= 8'd0;                                     
    else if(rx_flag)                            //        
        if (clk_cnt == BPS_CNT/2) begin         //                 
            case ( rx_cnt )
             4'd1 : rxdata[0] <= uart_rxd_d1;   //        
             4'd2 : rxdata[1] <= uart_rxd_d1;
             4'd3 : rxdata[2] <= uart_rxd_d1;
             4'd4 : rxdata[3] <= uart_rxd_d1;
             4'd5 : rxdata[4] <= uart_rxd_d1;
             4'd6 : rxdata[5] <= uart_rxd_d1;
             4'd7 : rxdata[6] <= uart_rxd_d1;
             4'd8 : rxdata[7] <= uart_rxd_d1;   //        
             default:;                                    
            endcase
        end
        else 
            rxdata <= rxdata;
    else
        rxdata <= 8'd0;
end

//                        
always @(posedge sys_clk or negedge sys_rst_n) begin        
    if (!sys_rst_n) begin
        uart_data <= 8'd0;                               
        uart_done <= 1'b0;
    end
    else if(rx_cnt == 4'd9) begin               //                         
        uart_data <= rxdata;                    //          
        uart_done <= 1'b1;                      //           
    end
    else begin
        uart_data <= 8'd0;                                   
        uart_done <= 1'b0; 
    end    
end

endmodule	

送信モジュール
module uart_send(
    input	      sys_clk,                  //    
    input         sys_rst_n,                //    ,     
    
    input         uart_en,                  //      
    input  [7:0]  uart_din,                 //     
    output  reg   uart_txd                  //UART    
    );
    
//parameter define
parameter  CLK_FREQ = 50000000;             //      
parameter  UART_BPS = 9600;                 //     
localparam BPS_CNT  = CLK_FREQ/UART_BPS;    //        ,       BPS_CNT 

//reg define
reg        uart_en_d0; 
reg        uart_en_d1;  
reg [15:0] clk_cnt;                         //       
reg [ 3:0] tx_cnt;                          //       
reg        tx_flag;                         //        
reg [ 7:0] tx_data;                         //      

//wire define
wire       en_flag;

//*****************************************************
//**                    main code
//*****************************************************
//  uart_en   ,             
assign en_flag = (~uart_en_d1) & uart_en_d0;
                                                 
//       uart_en        
always @(posedge sys_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n) begin
        uart_en_d0 <= 1'b0;                                  
        uart_en_d1 <= 1'b0;
    end                                                      
    else begin                                               
        uart_en_d0 <= uart_en;                               
        uart_en_d1 <= uart_en_d0;                            
    end
end

//     en_flag   ,        ,                 
always @(posedge sys_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n) begin                                  
        tx_flag <= 1'b0;
        tx_data <= 8'd0;
    end 
    else if (en_flag) begin                 //                                
            tx_flag <= 1'b1;                //      ,   tx_flag  
            tx_data <= uart_din;            //        
        end
        else 
        if ((tx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2))
        begin                               //         ,      
            tx_flag <= 1'b0;                //      ,   tx_flag  
            tx_data <= 8'd0;
        end
        else begin
            tx_flag <= tx_flag;
            tx_data <= tx_data;
        end 
end

//       ,                 
always @(posedge sys_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n) begin                             
        clk_cnt <= 16'd0;                                  
        tx_cnt  <= 4'd0;
    end                                                      
    else if (tx_flag) begin                 //      
        if (clk_cnt < BPS_CNT - 1) begin
            clk_cnt <= clk_cnt + 1'b1;
            tx_cnt  <= tx_cnt;
        end
        else begin
            clk_cnt <= 16'd0;               //                  
            tx_cnt  <= tx_cnt + 1'b1;       //          1
        end
    end
    else begin                              //      
        clk_cnt <= 16'd0;
        tx_cnt  <= 4'd0;
    end
end

//           uart      
always @(posedge sys_clk or negedge sys_rst_n) begin        
    if (!sys_rst_n)  
        uart_txd <= 1'b1;        
    else if (tx_flag)
        case(tx_cnt)
            4'd0: uart_txd <= 1'b0;         //    
            4'd1: uart_txd <= tx_data[0];   //      
            4'd2: uart_txd <= tx_data[1];
            4'd3: uart_txd <= tx_data[2];
            4'd4: uart_txd <= tx_data[3];
            4'd5: uart_txd <= tx_data[4];
            4'd6: uart_txd <= tx_data[5];
            4'd7: uart_txd <= tx_data[6];
            4'd8: uart_txd <= tx_data[7];   //      
            4'd9: uart_txd <= 1'b1;         //   
            default: ;
        endcase
    else 
        uart_txd <= 1'b1;                   //           
end

endmodule