FPGA module – serial port module
- Send code
- receive code
- Pin constraints
Send code
1. Use the sending module
Using this module requires outputting a sending port output uart_txd, //UART send port /*-------------------------------------------------*/ wire uart_rx_done = 1'b1; //UART receives completion signal wire[7:0] rx_data; assign rx_data = 8'b11111111; //Data to be sent //parameter define parameter CLK_FREQ = 50000000; //Define the system clock frequency parameter UART_BPS = 115200; //Define the serial port baud rate //wire define //Serial port sending module uart_tx #( .CLK_FREQ (CLK_FREQ), .UART_BPS (UART_BPS) ) u_uart_tx( .clk (sys_clk), .rst_n (sys_rst_n), .uart_tx_en (uart_rx_done), .uart_tx_data (rx_data ), .uart_txd (uart_txd ), .uart_tx_busy ( ) );
2. The bottom layer of serial port sending
Add a uart_tx.v file
module uart_tx( input clk, //system clock input rst_n, //System reset, low effective input uart_tx_en, //UART transmission enable input [7:0] uart_tx_data, //Data to be sent by UART output reg uart_txd , //UART sending port output reg uart_tx_busy //Send busy status signal ); //parameter define parameter CLK_FREQ = 50000000; //system clock frequency parameter UART_BPS = 115200; //Serial port baud rate localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //To obtain the specified baud rate, count the system clock BPS_CNT times //reg define reg [7:0] tx_data_t; //Send data register reg [3:0] tx_cnt; //Send data counter reg [15:0] baud_cnt; //Baud rate counter //************************************************ ***** //** main code //************************************************ ***** //When uart_tx_en is high, register the input parallel data and pull the BUSY signal high always @(posedge clk or negedge rst_n) begin if(!rst_n) begin tx_data_t <= 8'b0; uart_tx_busy <= 1'b0; end //When sending is enabled, register the data to be sent and pull the BUSY signal high else if(uart_tx_en) begin tx_data_t <= uart_tx_data; uart_tx_busy <= 1'b1; end //When counting reaches the end of the stop bit, stop the sending process else if(tx_cnt == 4'd9 & amp; & amp; baud_cnt == BAUD_CNT_MAX - BAUD_CNT_MAX/16) begin tx_data_t <= 8'b0; //Clear the send data register uart_tx_busy <= 1'b0; //and pull down the BUSY signal end else begin tx_data_t <= tx_data_t; uart_tx_busy <= uart_tx_busy; end end //Counter assignment of baud rate always @(posedge clk or negedge rst_n) begin if(!rst_n) baud_cnt <= 16'd0; //When in the sending process, the baud rate counter (baud_cnt) performs loop counting else if(uart_tx_busy) begin if(baud_cnt < BAUD_CNT_MAX - 1'b1) baud_cnt <= baud_cnt + 16'b1; else baud_cnt <= 16'd0; //The count is cleared after reaching one baud rate cycle end else baud_cnt <= 16'd0; //The counter is cleared at the end of the sending process end //tx_cnt assigns value always @(posedge clk or negedge rst_n) begin if(!rst_n) tx_cnt <= 4'd0; else if(uart_tx_busy) begin //tx_cnt is counted only when it is in the sending process if(baud_cnt == BAUD_CNT_MAX - 1'b1) //When the baud rate counter counts to one baud rate cycle tx_cnt <= tx_cnt + 1'b1; //Send data counter plus 1 else tx_cnt <= tx_cnt; end else tx_cnt <= 4'd0; //The counter is cleared at the end of the sending process end //Assign a value to the uart sending port based on tx_cnt always @(posedge clk or negedge rst_n) begin if(!rst_n) uart_txd <= 1'b1; else if(uart_tx_busy) begin case(tx_cnt) 4'd0: uart_txd <= 1'b0; //Start bit 4'd1: uart_txd <= tx_data_t[0]; //The lowest bit of data bits 4'd2 : uart_txd <= tx_data_t[1]; 4'd3: uart_txd <= tx_data_t[2]; 4'd4 : uart_txd <= tx_data_t[3]; 4'd5 : uart_txd <= tx_data_t[4]; 4'd6: uart_txd <= tx_data_t[5]; 4'd7 : uart_txd <= tx_data_t[6]; 4'd8: uart_txd <= tx_data_t[7]; //Highest data bit 4'd9: uart_txd <= 1'b1; //Stop bit default : uart_txd <= 1'b1; endcase end else uart_txd <= 1'b1; //The sending port is high level when idle end endmodule
Receive code
1. Use the receiving module
To use this module, you need to enter a receiving port input uart_rxd //UART receiving port /*------------------------------------------------ ----*/ //parameter define parameter CLK_FREQ = 50000000; //Define the system clock frequency parameter UART_BPS = 115200; //Define the serial port baud rate //wire define wire uart_rx_done; //UART receives completion signal wire [7:0] uart_rx_data; reg [7:0] rx_data; initial flag <= 1'b0; //Check the received data always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) begin flag <= 1'b1; end else begin rx_data<=uart_rx_data; if(rx_data==8'b1111_1110)begin flag <= ~flag ; end end end //Serial port receiving module uart_rx #( .CLK_FREQ (CLK_FREQ), .UART_BPS (UART_BPS) ) u_uart_rx( .clk (sys_clk), .rst_n (sys_rst_n), .uart_rxd (uart_rxd ), .uart_rx_done (uart_rx_done), .uart_rx_data (uart_rx_data) );
2. The bottom layer of the receiving module
Add a uart_rx.v file
module uart_rx( input clk, //system clock input rst_n, //System reset, low effective input uart_rxd, //UART receiving port output reg uart_rx_done, //UART reception completion signal output reg [7:0] uart_rx_data //Data received by UART ); //parameter define parameter CLK_FREQ = 50000000; //system clock frequency parameter UART_BPS = 115200; //Serial port baud rate localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //To obtain the specified baud rate, count the system clock BPS_CNT times //reg define reg uart_rxd_d0; reg uart_rxd_d1; reg uart_rxd_d2; reg rx_flag; //Receive process flag signal reg [3:0] rx_cnt; //Receive data counter reg [15:0] baud_cnt; //Baud rate counter reg [7:0 ] rx_data_t; //Receive data register //wire define wire start_en; //************************************************ ***** //** main code //************************************************ ***** //Capture the falling edge (start bit) of the receiving port and get a pulse signal of one clock cycle assign start_en = uart_rxd_d2 & amp; (~uart_rxd_d1) & amp; (~rx_flag); //Synchronous processing of asynchronous signals always @(posedge clk or negedge rst_n) begin if(!rst_n) begin uart_rxd_d0 <= 1'b0; uart_rxd_d1 <= 1'b0; uart_rxd_d2 <= 1'b0; end else begin uart_rxd_d0 <= uart_rxd; uart_rxd_d1 <= uart_rxd_d0; uart_rxd_d2 <= uart_rxd_d1; end end //Assign a value to the receiving flag always @(posedge clk or negedge rst_n) begin if(!rst_n) rx_flag <= 1'b0; else if(start_en) //Start bit detected rx_flag <= 1'b1; //During the reception process, the flag signal rx_flag is pulled high //When the stop bit is halfway, that is, the receiving process ends, the flag signal rx_flag is pulled low else if((rx_cnt == 4'd9) & amp; & amp; (baud_cnt == BAUD_CNT_MAX/2 - 1'b1)) rx_flag <= 1'b0; else rx_flag <= rx_flag; end //Counter assignment of baud rate always @(posedge clk or negedge rst_n) begin if(!rst_n) baud_cnt <= 16'd0; else if(rx_flag) begin //When in the receiving process, the baud rate counter (baud_cnt) performs loop counting if(baud_cnt < BAUD_CNT_MAX - 1'b1) baud_cnt <= baud_cnt + 16'b1; else baud_cnt <= 16'd0; //The count is cleared after reaching one baud rate cycle end else baud_cnt <= 16'd0; //The counter is cleared at the end of the receiving process end //Assign value to the received data counter (rx_cnt) always @(posedge clk or negedge rst_n) begin if(!rst_n) rx_cnt <= 4'd0; else if(rx_flag) begin //rx_cnt counts only when it is in the receiving process if(baud_cnt == BAUD_CNT_MAX - 1'b1) //When the baud rate counter counts to one baud rate cycle rx_cnt <= rx_cnt + 1'b1; //Receive data counter plus 1 else rx_cnt <= rx_cnt; end else rx_cnt <= 4'd0; //The counter is cleared at the end of the receiving process end //Register the data of the rxd port according to rx_cnt always @(posedge clk or negedge rst_n) begin if(!rst_n) rx_data_t <= 8'b0; else if(rx_flag) begin //When the system is in the receiving process if(baud_cnt == BAUD_CNT_MAX/2 - 1'b1) begin //Determine whether baud_cnt counts to the middle of the data bits case(rx_cnt) 4'd1: rx_data_t[0] <= uart_rxd_d2; //Register the lowest bit of data 4'd2 : rx_data_t[1] <= uart_rxd_d2; 4'd3 : rx_data_t[2] <= uart_rxd_d2; 4'd4 : rx_data_t[3] <= uart_rxd_d2; 4'd5 : rx_data_t[4] <= uart_rxd_d2; 4'd6 : rx_data_t[5] <= uart_rxd_d2; 4'd7 : rx_data_t[6] <= uart_rxd_d2; 4'd8: rx_data_t[7] <= uart_rxd_d2; //Register the high and low bits of data default : ; endcase end else rx_data_t <= rx_data_t; end else rx_data_t <= 8'b0; end //Assign values to the reception completion signal and received data always @(posedge clk or negedge rst_n) begin if(!rst_n) begin uart_rx_done <= 1'b0; uart_rx_data <= 8'b0; end //When the received data counter counts to the stop bit and baud_cnt counts to the middle of the stop bit else if(rx_cnt == 4'd9 & amp; & amp; baud_cnt == BAUD_CNT_MAX/2 - 1'b1) begin uart_rx_done <= 1'b1; //Pull high the reception completion signal uart_rx_data <= rx_data_t; //Assign the data received by UART end else begin uart_rx_done <= 1'b0; uart_rx_data <= uart_rx_data; end end endmodule
Pin constraints
#Timing constraints create_clock -period 20.000 -name sys_clk [get_ports sys_clk] #IO pin constraints #----------------------System Clock------------------------- -- set_property -dict {<!-- -->PACKAGE_PIN R4 IOSTANDARD LVCMOS33} [get_ports sys_clk] #----------------------System Reset------------------------- -- set_property -dict {<!-- -->PACKAGE_PIN U2 IOSTANDARD LVCMOS33} [get_ports sys_rst_n] #---------------------USB UART------------------------- -- set_property -dict {<!-- -->PACKAGE_PIN U5 IOSTANDARD LVCMOS33} [get_ports uart_rxd] set_property -dict {<!-- -->PACKAGE_PIN T6 IOSTANDARD LVCMOS33} [get_ports uart_txd]