Welcome to leave a message, each message will be selected, and I will reply on the same day. Any errors in the article will also be updated in the reply.
#FPGA #UART Transmission #Volatility Generation #Timing Logic
The Verilog code is at the bottom of the article.
1. Design File <span>uart_byte_tx</span> Function Analysis
This module is a UART transmission module that converts byte data into serial signals (start bit, data bits, stop bit). The key logic is as follows:
-
Parameter Definition:
<span>MCNT_baudset</span>Baud rate (9600bps) corresponding to the frequency divider counter threshold (assuming system clock is 50MHz,<span>50_000_000 / 9600 ≈ 5208</span>).<span>MCNT_bitset</span>Maximum value of bit counter (1 byte + 1 start bit + 1 stop bit = 10 bits, counting from 0 to 9).<span>MCNT_dalaycnt</span>Delay counter threshold (originally designed for 1s, redefined in Testbench as 10ms).
Core Logic:
<span>delay_cnt</span>Delay counter, used to control the sending interval.<span>send_en</span>Send enable signal, activated after the delay counter is full.<span>baud_div_cnt</span>Baud rate division counter, generates bit period signal.<span>bit_cnt</span>Bit counter, tracks the current sending bit (start bit, data bits, stop bit).<span>data_byte_reg</span>Data register, temporarily stores the byte to be sent.<span>uart_tx</span>UART transmission logic, outputs the corresponding bit based on<span>bit_cnt</span>(start bit<span>0</span>, data bits, stop bit<span>1</span>).<span>led</span>Flips once after sending a byte, indicating transmission completion.
2. Testbench File <span>uart_byte_tx_tb</span> Analysis
-
Instantiation and Parameter Redefinition:
- Instantiate the
<span>uart_byte_tx</span>module. - Redefine
<span>MCNT_dalaycnt = 50_000_0 - 1</span>to shorten the sending interval from 1s to 10ms.
Stimulus Generation:
- Generate a 50MHz clock (period 20ns).
- After reset, first send
<span>8'b01010101</span>(0x55), then after a delay of 30ms send<span>8'b10101010</span>(0xAA).
3. Simulation Waveform Analysis

<span>clk</span>50MHz clock, green square wave.<span>reset_n</span>Initially low reset, then pulled high.<span>data_byte</span>First<span>01010101</span>(0x55), then<span>10101010</span>(0xAA).<span>uart_tx</span>- When sending
<span>0x55</span>: start bit<span>0</span>→ sequentially send<span>01010101</span>(LSB first) → stop bit<span>1</span>. - When sending
<span>0xAA</span>: start bit<span>0</span>→ sequentially send<span>10101010</span>(LSB first) → stop bit<span>1</span>. <span>led</span>Flips once after sending a byte, consistent with the design condition<span>(bit_cnt == MCNT_bitset) && (baud_div_cnt == MCNT_baudset)</span><span>.</span>
4. Summary
This design implements the UART byte transmission function. The Testbench shortened the sending interval by redefining parameters, and the simulation waveform verified the logical correctness:
-
The order of start bit, data bits, and stop bit is correct.
-
The LED accurately indicates the completion of byte transmission.
-
The baud rate division and bit counting logic meet expectations (at 9600bps, each bit period is approximately 104μs, corresponding to the division counter 5208).
<span>5. Verilog Code</span><span>1. Design file uart_byte_tx.v code</span>
module uart_byte_tx # ( parameter MCNT_baudset = 5208 -1,//Baud rate 9600 corresponding frequency divider counter threshold parameter MCNT_bitset = 10-1, parameter MCNT_dalaycnt = 50_000_000 - 1//Delay counter to 1s)( input clk,//Global clock signal input reset_n,//Reset signal input [7:0]data_byte,//Input byte-level data output reg uart_tx,//Data to be sent (bit-level) output reg led//Flips once after one byte transmission completed); reg [12:0] baud_div_cnt;//Baud rate division counter reg [3:0]bit_cnt;//Bit counter reg [7:0]data_byte_reg;//Input data register reg send_en;//Bit send enable signal reg [25:0]delay_cnt;//Delay counter, sending 1 byte requires 1s/9600*10=1.04ms, far less than 1s, the time from 1ms to 1s does not require sending data, so a delay counter is needed//Delay counter logic, delay_cntalways@(posedge clk or negedge reset_n)begin if(!reset_n) delay_cnt <= 0; else if(delay_cnt == MCNT_dalaycnt) //Count full reset to 0 delay_cnt <= 0; else delay_cnt <= delay_cnt + 1'b1;end//Bit send enable signal logic, send_enalways@(posedge clk or negedge reset_n)begin if(!reset_n) send_en <= 1'b0; else if(delay_cnt == MCNT_dalaycnt) //Count full set to 1 send_en <= 1'b1; else if((bit_cnt == MCNT_bitset)&&(baud_div_cnt == MCNT_baudset))//One byte transmission completed send_en <= 1'b0;end//Baud rate division counter logicbaud_div_cntalways@(posedge clk or negedge reset_n)begin if(!reset_n) baud_div_cnt <= 0; else if(send_en) begin//Enable signal triggered if(baud_div_cnt == MCNT_baudset) baud_div_cnt <= 0; else baud_div_cnt <= baud_div_cnt + 1'b1; end else//No enable signal, no reset signal baud_div_cnt <= 0;end//Bit counter logicbit_cntalways@(posedge clk or negedge reset_n)begin if(!reset_n) bit_cnt <= 0; else if(baud_div_cnt == MCNT_baudset)begin//Division counter full reset to 0 if(bit_cnt == MCNT_bitset) bit_cnt <= 0; else bit_cnt <= bit_cnt +1; endend//Data register logicdata_byte_regalways@(posedge clk or negedge reset_n)begin if(!reset_n) data_byte_reg <= 0; else if(delay_cnt == MCNT_dalaycnt)//1s delay reached, enable signal to send the next byte data_byte_reg <= data_byte; else data_byte_reg <= data_byte_reg;end//Bit send logicuart_txalways @ (posedge clk or negedge reset_n) begin if(!reset_n) uart_tx <= 1'b1; else if(send_en == 1) begin case(bit_cnt) 0:uart_tx <= 1'b0; 1:uart_tx <= data_byte_reg[0]; 2:uart_tx <= data_byte_reg[1]; 3:uart_tx <= data_byte_reg[2]; 4:uart_tx <= data_byte_reg[3]; 5:uart_tx <= data_byte_reg[4]; 6:uart_tx <= data_byte_reg[5]; 7:uart_tx <= data_byte_reg[6]; 8:uart_tx <= data_byte_reg[7]; 9:uart_tx <= 1'b1; default:uart_tx <= uart_tx; endcase end else uart_tx <= 1'b1;end//LED flip logicalways@(posedge clk or negedge reset_n)begin if(!reset_n) led <= 0; else if((bit_cnt == MCNT_bitset) &&(baud_div_cnt == MCNT_baudset))//One byte data transmission completed led <= !led; else led <= led;endendmodule
2. Simulation file uart_byte_tx_tb.v code:
`timescale 1ns / 1psmodule uart_byte_tx_tb();//Declare reg type signals as stimulus sources, wire type signals connect to the output of the module under test reg clk;//Global clock signal reg reset_n;//Reset signal reg [7:0]data_byte;//Input byte-level data wire uart_tx;//Data to be sent (bit-level) wire led;//Flips once after one byte transmission completed//Instantiate uart_byte_tx uart_byte_tx( .clk(clk), .reset_n(reset_n), .data_byte(data_byte), .uart_tx(uart_tx), .led(led) );//Redefine parameter MCNT_dalaycnt, shorten time from 1s to 10ms, that is, send data (byte level) every 10ms defparam uart_byte_tx.MCNT_dalaycnt = 50_000_0 -1;//Generate clock initial clk = 1; always #10 clk=~clk;//Generate test data initial begin reset_n = 0; #201; reset_n = 1; data_byte = 8'b01010101; # 30_000_000;//Send data three times, 30_000_000ns = 30_000 μs = 30 ms data_byte = 8'b10101010; # 30_000_000;//Send data three times, 30_000_000ns = 30_000 μs = 30 ms $stop; endendmodule