IC面试:解决UART

打三排降低亚稳态概率并下降沿检测;保证在波特率的循环周期正中央采样;

module uart_tx#(
    parameter CLK_FRE = 50,
    parameter BAUD_RATE = 115200
)
(
    clk,
    rst_n,

    tx_data,
    tx_vld,

    tx_pin,
    tx_rdy
    
);    
    //==================modport
    input clk;
    input rst_n;

    input [7 : 0] tx_data;
    input tx_vld;

    output tx_pin;
    output tx_rdy;

    //===================parameter 
    parameter CYCLE = CLK_FRE * 1000000 / BAUD_RATE;
    parameter BITS = 11;


    //===================defination
    reg tx_rdy; 
    reg [10 : 0] data_r;
    reg tx_pin;

    reg [15 : 0] cnt_cycle;
    wire add_cnt_cycle;
    wire end_cnt_cycle;

    reg [15 : 0] cnt_bit;
    wire add_cnt_bit;
    wire end_cnt_bit;



    //===================defination
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) tx_rdy <= 1'b1;
        else if(tx_vld && tx_rdy) tx_rdy <= 1'b0;
        else if(end_cnt_bit) tx_rdy <= 1'b1;
    end
    
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) data_r <= 'd0;
        else if(tx_vld) data_r <= {1'b0, tx_data, 2'b0};
        else if(end_cnt_bit) data_r <= 'd0;
    end

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) tx_pin <= 1'b1;
        else if(~tx_rdy) tx_pin <= data_r[10 - cnt_bit];
        else tx_pin <= 1'b1;
    end

    assign add_cnt_cycle = ~tx_rdy;
    assign end_cnt_cycle = add_cnt_cycle && (cnt_cycle == CYCLE - 1);
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) cnt_cycle <= 'd0;
        else if(end_cnt_cycle) cnt_cycle <= 'd0;
        else if(add_cnt_cycle) cnt_cycle <= cnt_cycle + 1'b1;
    end

    assign add_cnt_bit = end_cnt_cycle;
    assign end_cnt_bit = add_cnt_bit && (cnt_bit == BITS - 1);
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) cnt_bit <= 'd0;
        else if(end_cnt_bit) cnt_bit <= 'd0;
        else if(add_cnt_bit) cnt_bit <= cnt_bit + 1'b1;
    end


endmodule
module uart_rx#(
    parameter CLK_FRE = 50,
    parameter BAUD_RATE = 115200
)
(
    clk,
    rst_n,

    rx_pin,
    rx_rdy,
    
    rx_data,
    rx_vld
);    
    //==================modport
    input clk;
    input rst_n;
    input rx_pin;
    input rx_rdy;

    output [7 : 0] rx_data;
    output rx_vld;

    //===================parameter 
    parameter CYCLE = CLK_FRE * 1000000 / BAUD_RATE;
    parameter BITS = 11;


    //===================defination
    reg rx_pin_r, rx_pin_rr, rx_pin_rrr;
    wire rx_pin_neg;

    reg trans;
    reg [7 : 0] rx_data;
    reg rx_vld;

    reg [15 : 0] cnt_cycle;
    wire add_cnt_cycle;
    wire end_cnt_cycle;

    reg [15 : 0] cnt_bit;
    wire add_cnt_bit;
    wire end_cnt_bit;



    //===================defination
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) {rx_pin_rrr, rx_pin_rr, rx_pin_r} <= 'd0;
        else {rx_pin_rrr, rx_pin_rr, rx_pin_r} <= {rx_pin_rr, rx_pin_r, rx_pin};
    end
    assign rx_pin_neg = rx_pin_rrr && ~rx_pin_rr;


    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) trans <= 1'b0;
        else if(rx_pin_neg) trans <= 1'b1;
        else if(end_cnt_bit) trans <= 1'b0;
    end

    assign add_cnt_cycle = trans;
    assign end_cnt_cycle = add_cnt_cycle && (cnt_cycle == CYCLE - 1);
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) cnt_cycle <= 'd0;
        else if(end_cnt_cycle) cnt_cycle <= 'd0;
        else if(add_cnt_cycle) cnt_cycle <= cnt_cycle + 1'b1;
    end

    assign add_cnt_bit = end_cnt_cycle;
    assign end_cnt_bit = add_cnt_bit && (cnt_bit == BITS - 1);
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) cnt_bit <= 'd0;
        else if(end_cnt_bit) cnt_bit <= 'd0;
        else if(add_cnt_bit) cnt_bit <= cnt_bit + 1'b1;
    end

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) rx_data <= 'd0;
        else if(cnt_bit > 1 && cnt_bit < 9) begin
            if(add_cnt_cycle && cnt_cycle == CYCLE / 2)
                rx_data <= {rx_data[6 : 0], rx_pin};
        end
        else rx_data <= 'd0;
    end

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) rx_vld <= 1'b0;
        else if(cnt_bit == 8 && add_cnt_cycle & cnt_cycle == CYCLE / 2) rx_vld <= 1'b1;
        else rx_vld <= 1'b0;
    end

endmodule
module top(
    clk,
    rst_n,
    tx_data,
    tx_vld,
    tx_rdy
);
    //================modport
    input clk;
    input rst_n;
    input [7 : 0] tx_data;
    input tx_vld;
    output tx_rdy;
    
    //================parameter
    parameter BAUD_RATE = 115200;
    parameter CLK_FRE = 50;

    //================defination
    wire tx_pin;
    wire [7 : 0] rx_data;
    wire rx_vld;
    wire rx_rdy;

    //================output
    assign rx_rdy = 1;

    //================instance
    uart_tx#(
        .CLK_FRE    (CLK_FRE),
        .BAUD_RATE  (BAUD_RATE)
    )
    u_tx
    (
        .clk        (clk),
        .rst_n      (rst_n),
        .tx_data    (tx_data),
        .tx_vld     (tx_vld),
        .tx_pin     (tx_pin),
        .tx_rdy     (tx_rdy)
    );

    uart_rx#(
        .CLK_FRE    (CLK_FRE),
        .BAUD_RATE  (BAUD_RATE)
    )
    u_rx
    (
        .clk        (clk),
        .rst_n      (rst_n),
        .rx_data    (rx_data),
        .rx_vld     (rx_vld),
        .rx_pin     (tx_pin),
        .rx_rdy     (rx_rdy)
    );

endmodule

module tb_top();
    //===================parameter
    parameter PERIOD = 20 / 2;


    //===================defination
    reg clk, rst_n;
    reg [7 : 0] tx_data;
    reg tx_vld;
    wire tx_rdy;
    //===================output
    initial begin
        clk = 0;
        forever 
        #PERIOD clk = ~clk;
    end

    initial begin
        rst_n = 0;
        #20 
        rst_n = 1;
    end
    
    initial begin
        wait(rst_n);
        wait(tx_rdy);
        tx(8'd5);
        wait(tx_rdy);
        tx(8'd9);
        wait(tx_rdy);

	#1000 $finish; 
    end

    task tx(input [7 : 0] data);
	begin
        @(posedge clk);
        #1;
        tx_data = data;
        tx_vld = 1'b1;
        @(posedge clk);
        #1;
        tx_vld = 1'b0;
	end
    endtask




    top u_top(
    .clk    (clk),
    .rst_n  (rst_n),
    .tx_data(tx_data),
    .tx_vld (tx_vld),
    .tx_rdy (tx_rdy)
    );


   
`ifdef FSDB
initial begin
	$fsdbDumpfile("tb_top.fsdb");
	$fsdbDumpvars;
    $fsdbDumpMDA();
end
`endif

endmodule 

在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值