FPGA实现串口功能

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    15:18:50 01/01/2022 
// Design Name: 
// Module Name:    uart 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module uart(
        clk,
        Reset_n,
        Data,
        Send_en,
        Bund_set,
        uart_tx,
        Tx_Done
    );
    input clk;
    input Reset_n;
    input [7:0]Data;
    input Send_en;
    input [2:0]Bund_set;
    output reg uart_tx;
    output reg Tx_Done;
    
    reg[17:0] div_cnt;//分频得到基本时钟
    reg[17:0] bps_DR;
    
    
    
    
    //译码,将波特率选择翻译成为计数器bps_DR的值    
    //前提:时钟周期为50Mhz,所以时钟周期为20ns
    //波特率:指的是一秒中能发送多少数据,以115200为例。
    //所以每个数据的发送需要占多少个时钟周期 div_cnt负责计数:1000000000/115200/20 = 434,而bps_DR则是其计数的门限
    //所以bpd_DR的多少是取决于Bund_set
    
    always@(posedge clk or negedge Reset_n)
    if(!Reset_n)
        div_cnt <= 0;
    else if(Send_en)begin
        if(div_cnt == bps_DR - 1)
            div_cnt <= 0;
        else
            div_cnt <= div_cnt + 1'b1;
        end
    else
        div_cnt <= 0;
    always@(*)
        case(Bund_set)
            4 : bps_DR <= 434;  //115200
            3 : bps_DR <= 868;  //57600
            2 : bps_DR <= 1302; //38400
            1 : bps_DR <= 2604; //19200
            0 : bps_DR <= 5208; //9600
            default:bps_DR <= 5208;
        endcase
    
    reg [3:0]bps_counter;
   always@(posedge clk or negedge Reset_n)
    if(!Reset_n)
        bps_counter <= 0;
    else if(Send_en)begin
        if(div_cnt == 1)begin
            if(bps_counter == 11)
                bps_counter <= 0;
            else
                bps_counter <= bps_counter + 1'b1;
        end
    end
    else
        bps_counter <= 0;
    always@(posedge clk or negedge Reset_n)
    if(!Reset_n)
        uart_tx <= 1'b0;
    else begin
        case(bps_counter) 
            1:uart_tx <= 1'b0;
            2:uart_tx <= Data[0];
            3:uart_tx <= Data[1];
            4:uart_tx <= Data[2];
            5:uart_tx <= Data[3];
            6:uart_tx <= Data[4];
            7:uart_tx <= Data[5];
            8:uart_tx <= Data[6];
            9:uart_tx <= Data[7];
            10:uart_tx <= 1;
            11:uart_tx <= 1; 
            default: uart_tx <= 1;
        endcase
    end
    always@(posedge clk or negedge Reset_n)
    if(!Reset_n)
        Tx_Done <= 1'b0;
    else if((div_cnt == 1) && (bps_counter == 10))
        Tx_Done <= 1'b1;
    else
        Tx_Done <= 1'b0;
        
endmodule
`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:
//
// Create Date:   21:37:13 01/01/2022
// Design Name:   uart
// Module Name:   E:/FPGA_WORKSPACE/uart/uart_test.v
// Project Name:  uart
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: uart
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module uart_test;

    // Inputs
    reg clk;
    reg Reset_n;
    reg [7:0] Data;
    reg Send_en;
    reg [2:0] Bund_set;

    // Outputs
    wire uart_tx;
    wire Tx_Done;

    // Instantiate the Unit Under Test (UUT)
    uart uut (
        .clk(clk), 
        .Reset_n(Reset_n), 
        .Data(Data), 
        .Send_en(Send_en), 
        .Bund_set(Bund_set), 
        .uart_tx(uart_tx), 
        .Tx_Done(Tx_Done)
    );
    initial clk = 1;
    always #10 clk = !clk;
    initial begin
        // Initialize Inputs
        Reset_n = 0;
        Data = 0;
        Send_en = 0;
        Bund_set = 0;

        // Wait 100 ns for global reset to finish
        #201;
      Reset_n = 1;
        #200;
        Data = 8'h57;
        Send_en = 1;
        Bund_set = 3;
        // Add stimulus here

    end
      
endmodule

 

上一篇:Linux服务器硬件信息查看的几个命令


下一篇:RISCV Bare Metal