If the UART module has a single clock input (call it axi_aclk), and the baudrate clock is generated from axi_aclk according to divisor registers (DLL and DLM).
Let's take the clocks for xmit fifo as an example below (the write port of the fifo is driven by axi_clk, and the read port is driven by baudclk:
+------------>---------------------+
| |
| v
--> axi_aclk ---> [baudrate generator] +-->[xmt fifo] <--
| ^
| |
+----------------------------------+
baudclk
My question is, in such case, does the xmt fifo implementation require clock-domain-crossing logic (and gray code for read/write pointers), and why?
PS: my baud clock generating module is below (the i_clk into brg module is axi_aclk):
/*
* baud-rate generate (brg) is a clock divisor which takes an input clock
* and generate an output clock (baud16), with the following freq relationship:
*
* baud16 = clk / divisor
*
*
* limitations:
* - The minimum divisor for this module is 1. For this case, baud16 ties to i_clk.
* - For divisor=0, the output is undefined.
* - For odd divisors greater than 1, the duty cycle of the output will be slightly less than 50%.
*/
`default_nettype none
module uart_brg #(
parameter DIVISOR_WIDTH = 16 // 16-bit integer, per 16550 standard
) (
input wire i_rst_n,
input wire i_clk,
input wire [DIVISOR_WIDTH - 1 : 0] i_divisor, // >0
output reg o_clk // baud16
);
reg [DIVISOR_WIDTH - 1 : 0] count = 0;
reg out;
// update count
always @(posedge i_clk, negedge i_rst_n) begin
if (~i_rst_n)
count <= {DIVISOR_WIDTH{1'b0}};
else begin
if (count == i_divisor - 1)
count <= 0;
else
count <= count + 1;
end
end
// update out
always @(posedge i_clk, negedge i_rst_n) begin
if (~i_rst_n)
out <= 1'b0;
else begin
if (count == 0 || count == i_divisor >> 1)
out <= ~out;
end
end
//assign o_clk = ~i_rst_n? 1'b0 : ((i_divisor == 1)? i_clk : out);
always @(*) begin
if (~i_rst_n) o_clk = 1'b0;
else if (i_divisor == 1) o_clk = i_clk;
else o_clk = out;
end
endmodule
`default_nettype wire
This design is targeting a Xilinx FPGA.
It uses the beh_fifo (w/o gray code) found at: Sunburst FIFO
If CDC is not necessary, can CDC logic and/or the FIFO be removed?
I am implementing a simplified version of Xilinx axi_uart16550.
These two clocks may be synchronous. baudclk may be implemented by gated clock. For example, mask 3 out of 4 axi_aclk clock pulses to generate a divide-by-4 baudclk.
Create a clock tree on axi_aclk, the DFFs of axi_aclk and baudclk domains will be balanced.