FPGA project : usrt_rs232

 

 

module uart_rx
#(
    parameter UART_BPS = 'd9600       ,
              CLK_FREQ = 'd50_000_000 
)(
    input       wire            sys_clk   ,
    input       wire            sys_rst_n ,
    input       wire            rx        ,

    output      reg     [7:0]   po_data   ,
    output      reg             po_flag 
);

    parameter BAUD_CNT_MAX = CLK_FREQ / UART_BPS ;
    // reg define signal
    reg                 rx_reg1     ;
    reg                 rx_reg2     ;
    reg                 rx_reg3     ;
    reg                 start       ;
    reg                 work_en     ;
    reg     [12:00]     baud_cnt    ;
    reg                 bit_flag    ;
    reg     [ 3: 0]     bit_cnt     ;
    reg     [ 7: 0]     rx_data     ;
    reg                 rx_flag     ;

    // rx_reg1     ;rx_reg2     ;rx_reg3     ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            rx_reg1 <= 1'b1 ;
            rx_reg2 <= 1'b1 ;
            rx_reg3 <= 1'b1 ;
        end else begin
            rx_reg1 <= rx      ;
            rx_reg2 <= rx_reg1 ;
            rx_reg3 <= rx_reg2 ;
        end
    end
    // start       ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            start <= 1'b0 ;
        end else begin
            if(rx_reg3 == 1'b1 && rx_reg2 == 1'b0 && bit_cnt == 4'd0) begin // 或者bit_cnt换成 work_en == 0 
                start <= 1'b1 ;
            end else begin
                start <= 1'b0 ;
            end
        end
    end
    // work_en     ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            work_en <= 1'b0 ;
        end else begin
            if(start == 1'b1) begin
                work_en <= 1'b1 ;
            end else begin
                if((bit_cnt == 4'd8) && (bit_flag == 1'b1)) begin
                    work_en <= 1'b0 ;
                end else begin
                    work_en <= work_en ;
                end
            end
        end
    end
    // [12:00]     baud_cnt    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            baud_cnt <= 13'd0 ;
        end else begin
            if(work_en == 1'b1 && baud_cnt == BAUD_CNT_MAX - 1'b1) begin
                baud_cnt <= 13'd0 ;
            end else begin
                if(work_en == 1'b1) begin
                    baud_cnt <= baud_cnt + 1'b1 ;
                end else begin
                    baud_cnt <= 13'd0 ;
                end
            end
        end
    end
    // always @(posedge sys_clk or negedge sys_rst_n) begin
    //     if(~sys_rst_n) begin
    //         baud_cnt <= 13'd0 ;
    //     end else begin
    //         if(work_en == 1'b1 && baud_cnt == BAUD_CNT_MAX - 1'b1 || work_en == 1'b0) begin
    //             baud_cnt <= 13'd0 ;
    //         end else begin
    //             baud_cnt <= baud_cnt + 1'b1 ; 
    //         end
    //     end
    // end
    // bit_flag    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            bit_flag <= 1'b0 ;
        end else begin
            if(baud_cnt == BAUD_CNT_MAX - 1'b1) begin // 也可以写成baud_cnt == BAUD_CNT_MAX / 2 - 1'b1
                bit_flag <= 1'b1 ;                    // 这样后面赋值时,就可以直接用bit_flag .
            end else begin
                bit_flag <= 1'b0 ;
            end
        end
    end
    // [ 2: 0]     bit_cnt     ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            bit_cnt <= 4'd0 ;
        end else begin
            if(bit_flag == 1'b1 && work_en == 1'b1 && bit_cnt == 4'd8) begin
                bit_cnt <= 4'd0 ;
            end else begin
                if(bit_flag == 1'b1 && work_en == 1'b1) begin
                    bit_cnt <= bit_cnt + 1'b1 ;
                end else begin
                    if(work_en == 1'b1) begin
                        bit_cnt <= bit_cnt ;
                    end else begin
                        bit_cnt <= 3'd0 ;
                    end
                end
            end
        end
    end
    // [7:0]   rx_data   ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            rx_data <= 8'd0 ;
        end else begin
            if(bit_cnt >= 4'd1 && bit_cnt <= 4'd8 && baud_cnt == 13'd3000) begin
                rx_data <= {rx_reg3, rx_data[7:1]} ;
            end else begin
                rx_data <= rx_data ;
            end
        end
    end
    // rx_flag 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            rx_flag <= 1'b0 ;
        end else begin
            if(bit_cnt == 4'd8 && bit_flag == 1'b1) begin
                rx_flag <= 1'b1 ;
            end else begin
                rx_flag <= 1'b0 ;
            end
        end
    end
    // output signal
    // po_flag 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            po_flag <= 1'b0 ;
        end else begin
            if(rx_flag == 1'b1) begin
                po_flag <= 1'b1 ;
            end else begin
                po_flag <= 1'b0 ;
            end
        end
    end
    // po_data
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            po_data <= 8'd0 ;
        end else begin
            if(rx_flag == 1'b1) begin
                po_data <= rx_data ;
            end else begin
                po_data <= 8'd0 ;
            end
        end
    end
endmodule
module uart_tx (
    input       wire            sys_clk   ,
    input       wire            sys_rst_n ,
    input       wire   [7:0]    pi_data   ,
    input       wire            pi_flag   ,

    output      reg             tx   
);

    // reg signal define
    reg             pi_flag_r   ;
    reg     [7:0]   pi_data_r   ;
    reg             work_en     ;
    reg     [12:00] baud_cnt    ;
    reg             bit_flag    ;
    reg     [ 3: 0] bit_cnt     ;
    // pi_flag_r     ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            pi_flag_r <= 1'b0 ;
        end else begin
            if(pi_flag == 1'b1) begin
                pi_flag_r <= 1'b1 ;
            end else begin
                pi_flag_r <= 1'b0 ;
            end
        end
    end
    // [7:0] pi_data_r   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            pi_data_r <= 1'b0 ;
        end else begin
            if(pi_flag == 1'b1) begin
                pi_data_r <= pi_data ;
            end else begin
                pi_data_r <= pi_data_r ;
            end
        end
    end
    //        work_en      ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            work_en <= 1'b0 ;
        end else begin
            if(baud_cnt == 13'd5027 && bit_cnt == 4'd9) begin
                work_en <= 1'b0 ;
            end else begin
                if(pi_flag_r == 1'b1) begin
                    work_en <= 1'b1 ;
                end else begin
                    work_en <= work_en ;
                end
            end
        end
    end
    // [12:00] baud_cnt    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            baud_cnt <= 13'd0 ;
        end else begin
            if(work_en == 1'b1 && baud_cnt == 13'd5027 || work_en == 1'b0) begin
                baud_cnt <= 13'd0 ;
            end else begin
                if(work_en == 1'b1) begin
                    baud_cnt <= baud_cnt + 1'b1 ;
                end else begin
                    baud_cnt <= 13'd0 ;
                end
            end
        end
    end
    //         bit_flag    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            bit_flag <= 1'b0 ;
        end else begin
            if(baud_cnt == 13'd5026) begin // 野火上是等于 1 .
                bit_flag <= 1'b1 ;
            end else begin
                bit_flag <= 1'b0 ;
            end
        end
    end
    // [ 3: 0] bit_cnt     ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            bit_cnt <= 4'd0 ;
        end else begin
            if(bit_flag == 1'b1 && bit_cnt == 4'd9 || work_en == 1'b0) begin
                bit_cnt <= 4'd0 ;
            end else begin
                if(bit_flag == 1'b1) begin
                    bit_cnt <= bit_cnt + 1'b1 ;
                end else begin
                    bit_cnt <= bit_cnt ;
                end
            end
        end
    end

    // output signal
    // tx
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            tx <= 1'b1 ;
        end else begin
            if(work_en == 1'b1 && bit_cnt == 4'd0) begin
                tx <= 1'b0 ;
            end else begin
                if(work_en == 1'b1 && bit_cnt == 4'd9 || work_en == 1'b0) begin
                    tx <= 1'b1 ;
                end else begin
                    tx <= pi_data_r[bit_cnt - 1'b1] ;
                end
            end
        end
    end
endmodule
module top_uart(
    input       wire            sys_clk   ,
    input       wire            sys_rst_n ,
    input       wire            rx        ,

    output      wire            tx 
);

    // 模块间连线
    wire    [7:0]   po_data   ;
    wire            po_flag   ;

uart_rx uart_rx_insert_top(
    .sys_clk                    ( sys_clk   ) ,
    .sys_rst_n                  ( sys_rst_n ) ,
    .rx                         ( rx        ) ,

    .po_data                    ( po_data   ) ,
    .po_flag                    ( po_flag   ) 
);

uart_tx uart_tx_insert_top(
    .sys_clk                    ( sys_clk   ) ,
    .sys_rst_n                  ( sys_rst_n ) ,
    .pi_data                    ( po_data   ) ,
    .pi_flag                    ( po_flag   ) ,

    .tx                         ( tx        )   
);

endmodule

 

`timescale 1ns/1ns
module test_top();
    reg             sys_clk   ;
    reg             sys_rst_n ;
    reg             rx        ;

    wire            tx ;


// Instantiation
top_uart top_uart_insert(
    .sys_clk                ( sys_clk   ) ,
    .sys_rst_n              ( sys_rst_n ) ,
    .rx                     ( rx        ) ,

    .tx                     ( tx        ) 
);
    parameter CYCLE = 20 ;

    task rx_bit ;

    input   [7:0]   data ;

    integer i ;
    for (i = 0;i <= 9 ;i = i  + 1 ) begin
        case (i)
            0: rx <= 1'b0 ;
            1: rx <= data[i - 1];
            2: rx <= data[i - 1];
            3: rx <= data[i - 1];
            4: rx <= data[i - 1];
            5: rx <= data[i - 1];
            6: rx <= data[i - 1];
            7: rx <= data[i - 1];
            8: rx <= data[i - 1];
            9: rx <= 1'b1 ;
            default: rx <= 1'b1 ;
        endcase
        #(CYCLE * 5207) ;
    end
    endtask

    initial begin
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        rx        <= 1'b1 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( 210 )          ;
        sys_rst_n <= 1'b0 ;
        #( 10 )           ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( CYCLE * 100  ) ;
        rx_bit(8'd1) ;
        rx_bit(8'd2) ;
        rx_bit(8'd3) ;
        rx_bit(8'd4) ;
        rx_bit(8'd5) ;
        rx_bit(8'd6) ;
        rx_bit(8'd7) ;
        rx_bit(8'd8) ;
        rx_bit(8'd9) ;
        rx_bit(8'd9) ;
        $stop        ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;



    // initial begin
    //     $timeformat(-9,0,"ns",6) ;
    //     /* (第一个位置)
    //         -9 是10 的负9次方 表示纳秒
    //         -3               表示毫秒
    //     */
    //     /* (第二个位置)
    //         0 表示,小数点后显示的位数
    //     */
    //     /* (第三个位置)
    //         “打印字符” 与单位相对应
    //     */
    //     /* (第四个位置)
    //         6 表示 打印的最小数字字符 是6个
    //     */
    //     $monitor("@time %t:sel=%b,seg=%b,cnt_16=%b,sum_tb=%b",$time,sel,seg,cnt_16) ; // 监测函数
    // end

endmodule

 

`timescale 1ns/1ns
module test_uart();
    reg             sys_clk   ;
    reg             sys_rst_n ;
    reg             rx        ;

    wire    [7:0]   po_data   ;
    wire            po_flag   ;

    wire            tx ;


// Instantiation
uart_rx uart_rx_insert(
    .sys_clk                ( sys_clk   ) ,
    .sys_rst_n              ( sys_rst_n ) ,
    .rx                     ( rx        ) ,

    .po_data                ( po_data   ) ,
    .po_flag                ( po_flag   ) 
);
    parameter CYCLE = 20 ;

    initial begin
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        rx        <= 1'b1 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( 210 )          ;
        sys_rst_n <= 1'b0 ;
        #( 10 )           ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( CYCLE * 100  ) ;

        rx         <= 1'b0; // 起始位
        #( CYCLE * 5207 ) ;
        rx         <= 1'b1; // 1
        #( CYCLE * 5207 ) ;
        rx         <= 1'b0; // 2
        #( CYCLE * 5207 ) ;
        rx         <= 1'b1; // 3
        #( CYCLE * 5207 ) ;
        rx         <= 1'b0; // 4
        #( CYCLE * 5207 ) ;
        rx         <= 1'b1; // 5
        #( CYCLE * 5207 ) ;
        rx         <= 1'b0; // 6
        #( CYCLE * 5207 ) ;
        rx         <= 1'b1; // 7
        #( CYCLE * 5207 ) ;
        rx         <= 1'b0; // 8
        #( CYCLE * 5207 ) ;
        rx         <= 1'b1; // 终止位
        #( CYCLE * 5207 ) ;
        $stop             ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;

uart_tx uart_tx_insert(
    .sys_clk                ( sys_clk    ) ,
    .sys_rst_n              ( sys_rst_n  ) ,
    .pi_data                ( po_data    ) ,
    .pi_flag                ( po_flag    ) ,

    .tx                     ( tx )   
);

    // initial begin
    //     $timeformat(-9,0,"ns",6) ;
    //     /* (第一个位置)
    //         -9 是10 的负9次方 表示纳秒
    //         -3               表示毫秒
    //     */
    //     /* (第二个位置)
    //         0 表示,小数点后显示的位数
    //     */
    //     /* (第三个位置)
    //         “打印字符” 与单位相对应
    //     */
    //     /* (第四个位置)
    //         6 表示 打印的最小数字字符 是6个
    //     */
    //     $monitor("@time %t:sel=%b,seg=%b,cnt_16=%b,sum_tb=%b",$time,sel,seg,cnt_16) ; // 监测函数
    // end

endmodule

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值