The three commonly used low-speed serial communication are UART, SPI, and IIC. Here FPGA is used to realize UART communication. UART communication has only two wires, one is to send data tx, and the other is to receive data rx. PC and PFGA realize data communication through two wires.
Complete the transceiver design of the FPGA part to realize the serial communication.
RS232
1. RS232 is a kind of UART, there is no clock line, only two data lines, namely rx and tx, both of which are 1bit wide. Where rx is the line for receiving data and tx is the line for sending data.
2. The rx bit width is 1 bit. When the PC sends 8-bit data to the FPGA through the serial port debugging assistant, the FPGA receives the data one by one through the rx serial port line, from the lowest bit to the highest bit, and finally the bits are spliced into 8 bits in the FPGA. bit data.
3. The tx bit width is 1 bit. When the FPGA sends 8-bit data to the PC through the serial port, the FPGA transmits the 8-bit data to the PC bit by bit through the tx line, and sends them sequentially from the lowest bit to the highest bit, and finally the host computer passes the serial port. According to the RS232 protocol, the assistant splices the data bit by bit into 8bit data.
4. The sending and receiving of serial port data is based on the frame structure, that is, sending and receiving data frame by frame. In addition to the 8-bit valid data in the middle of each frame, there must be a start bit at the beginning of each frame, which is fixed to 0; at the end of each frame, there must also be a stop bit, which is fixed to 1. That is, the most basic frame structure (excluding checksum etc.) has 10 bits. In the case of not sending or receiving data, rx and tx are in an idle state. At this time, both rx and tx lines remain high. If there is a data frame transmission, there will be a start bit first, and then 8bit data Bit, followed by a 1-bit stop bit, then rx and tx continue to enter the idle state, and then wait for the next data transmission. Figure 28-7 shows the most basic RS232 frame structure.
1bit represents one bit of 1or0 in binary. A binary symbol (1or0) can carry 1bit of information (1or0). An octal code unit can carry 3 bits of information.
The baud rate of the s232 serial port is also the symbol transmission rate. 9600Baud/s. means that 9600 symbols are transmitted per second. bit (bps) bit rate = (Bps) baud number The binary corresponding to a single modulation state, the above picture is 9600/1. Ps: The serial port sends or receives a data time in baud. The serial port baud rate is 9600Bps, so one baud time is 1/9600s. If the system clock is 50Mhz, then at 9600 baud, one baud is equivalent to 1/9600s and then divided by 20ns=5208 system cycles. That is, every time the serial port transmits a bit of information, the system clock must maintain 5208 cycles.
FPGA Accept Module
module uart_rx #( parameter UART_BAUD = 'd9600, //baud rate parameter CLK_FRE = 'd50_000_000 //system clock ) ( input wire sys_clk, input wire sys_rst_n, input wire rx ,//serial data sent by the assistant \t \t \t output reg [7:0] po_data ,//Outgoing parallel data output reg po_flag //flag signal for data transmission ); parameter BAUD_MAX = CLK_FRE/UART_BAUD;//Transmission time required for each bit data transmission reg rx_reg1;//Three beats to reduce the influence of metastable state reg rx_reg2;//Because the signal reaches the register, the setup time and hold time do not meet the requirements reg rx_reg3;//so a metastable state is generated reg start_nedge; reg work_on; reg [12:0] baud_cnt; reg bit_flag; reg [3:0] bit_cnt; reg [7:0] rx_data; reg rx_flag; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) rx_reg1 <= 1'b1; else rx_reg1 <= rx; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) rx_reg2 <= 1'b1; else rx_reg2 <= rx_reg1; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) rx_reg3 <= 1'b1; else rx_reg3 <= rx_reg2; //When the falling edge of rx_reg is detected, a high level of a clock is generated. When detecting the falling edge, the signal can be delayed //A clock, and then extract a flag signal as follows. always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) start_nedge <= 1'b0; else if((rx_reg2 == 1'b0) & amp; & amp; (rx_reg3 == 1'b1) & amp; & amp; (work_on == 1'b0)) start_nedge <= 1'b1; else start_nedge <= 1'b0; // An enable signal can be determined by the extracted flag signal. Use the enable signal to determine the sampling range of the data always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) work_on <= 1'b0; else if(start_nedge == 1'b1) work_on <= 1'b1; else if(bit_flag == 1'b1 & amp; & amp; bit_cnt == 4'd8) work_on <= 1'b0; else work_on <= work_on; //The baud rate counter counts, the time required for one bit information. 50_000_000/9600=5208 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) baud_cnt <= 13'd0; else if(baud_cnt == BAUD_MAX - 1 || work_on == 1'b0) baud_cnt <= 13'd0; else if(work_on == 1'b1) baud_cnt <= baud_cnt + 1'b1; //When the counter counts to the middle, the sampled data is the most stable //At this time, a flag message is pulled high to indicate that the data can be taken away always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) bit_flag <= 1'b0; else if(baud_cnt == BAUD_MAX/2 - 1) bit_flag <= 1'b1; else bit_flag <= 1'b0; //The counter of the number of valid data, 8 valid data (excluding start bit 0 and stop bit 1) always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) bit_cnt <= 4'd0; else if(bit_cnt == 4'd8 & amp; & amp; bit_flag == 1'b1) bit_cnt <= 4'd0; else if(bit_flag == 1'b1) bit_cnt <= bit_cnt + 1'b1; //Input data to shift always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) rx_data <= 8'h00; else if(bit_cnt >= 4'd1 & amp; & amp; bit_cnt <= 4'd8 & amp; & amp; bit_flag == 1'b1) rx_data <= {<!-- -->rx_reg3,rx_data[7:1]}; //When the input data is completed, pull up the level of a clock always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) rx_flag <= 1'b0; else if(bit_cnt == 4'd8 & amp; & amp; bit_flag == 1'b1) rx_flag <= 1'b1; else rx_flag <= 1'b0; //Complete the output of 8-bit valid data always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) po_data <= 8'h00; else if(rx_flag == 1'b1) po_data <= rx_data; //Output data valid flag bit always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) po_flag <= 1'b0; else po_flag <= rx_flag; endmodule
FPGA sending module
module uart_tx #( parameter UART_BPS = 'd9600,//serial port baud rate parameter CLK_FRE = 'd50_000_000//clock frequency ) ( input wire sys_clk, input wire sys_rst_n, input wire [7:0] pi_data ,//8bit data input by the module input wire pi_flag ,//Valid flag signal for parallel data \t \t output reg tx //Serial to parallel 1bit data ); parameter BAUD_CNT = CLK_FRE/UART_BPS;// reg work_on; reg [12:0] baud_cnt; reg bit_flag; reg [3:0] bit_cnt; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) work_on <= 1'b0; else if(pi_flag == 1'b1) work_on <= 1'b1; else if(bit_flag == 1'b1 & amp; & amp; bit_cnt == 4'd9) work_on <= 1'b0; else work_on <= work_on; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) baud_cnt <= 0; else if(baud_cnt == BAUD_CNT - 1 || work_on == 1'b0) baud_cnt <= 0; else if(work_on == 1'b1) baud_cnt <= baud_cnt + 1'b1; \t\t \t\t always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) bit_flag <= 1'b0; else if(baud_cnt == 0 & amp; & amp; work_on == 1'b1) bit_flag <= 1'b1; else bit_flag <= 1'b0; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) bit_cnt <= 0; else if(bit_cnt == 4'd9 & amp; & amp; bit_flag == 1'b1) bit_cnt <= 4'd0; else if(bit_flag == 1'b1 & amp; & amp; work_on == 1'b1) bit_cnt <= bit_cnt + 1'b1; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) tx <= 1'b1; else if(bit_flag == 1'b1) begin case(bit_cnt) 0: tx <= 1'b0; 1: tx <= pi_data[0]; 2: tx <= pi_data[1]; 3: tx <= pi_data[2]; 4: tx <= pi_data[3]; 5: tx <= pi_data[4]; 6: tx <= pi_data[5]; 7: tx <= pi_data[6]; 8: tx <= pi_data[7]; 9: tx <= 1'b1; default: tx <= 1'b1; end case end endmodule
Top level module
module rs232 ( input wire sys_clk, input wire sys_rst_n, input wire rx , \t output wire tx ); wire [7:0] po_data; wire po_flag; uart_rx #( .UART_BAUD(9600), //baud rate .CLK_FRE(50_000_000) //system clock ) uart_rx_inst ( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .rx (rx),//serial data sent by the assistant .po_data (po_data), //Outgoing parallel data .po_flag (po_flag) //Flag signal for data transmission ); uart_tx #( .UART_BPS(9600), .CLK_FRE(50_000_000) ) uart_tx_inst ( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .pi_data (po_data), .pi_flag (po_flag), .tx (tx) ); endmodule
Simulation results
Serial port assistant debugging results