I am working on compiling Pulpino in vcs and run the simple "Helloworld" test, the UART is receving garbage. After long time of debugging, I found out the reason is actually coming from the System Verilog code of apb_uart_sv.
There are two UART modules in the /ips directory: apb_uart and apb_uart_sv.
The default compilation seems choose VHDL code, and works fine, but the in the System Verilog code, the UART is sending data 16x faster than the baud rate can read, which causing the reading become garbage.
As the pulpino/sw/libs/sys_lib/src/uart.c says,
/**
* Setup UART. The UART defaults to 8 bit character mode with 1 stop bit.
*
* parity Enable/disable parity mode
* clk_counter Clock counter value that is used to derive the UART clock.
* It has to be in the range of 1..2^16.
* There is a prescaler in place that already divides the SoC
* clock by 16. Since this is a counter, a value of 1 means that
* the SoC clock divided by 16*2 = 32 is used. A value of 31 would mean
* that we use the SoC clock divided by 16*32 = 512.
*/
There is a prescaler in place that already divides the SoC clock by 16.
which doesn't seem to work in the System Verilog code. In the sv code, the uart_tx is sending at the 1/2 s_clk frequency, which is at 12.5MHz.
This is only one clk_i passing in, which is the SoC clock, without dividing.
In the VHDL code, there is a slib_clock_divider, which generate the TXCLK 8x slower (2x baudrate), combined with iTx2 in the logic, the SoC clock is divided by 16. Thus the UART baudrate is matched.
entity uart_transmitter is
port (
CLK : in std_logic; -- Clock
RST : in std_logic; -- Reset
TXCLK : in std_logic; -- Transmitter clock (2x baudrate)
TXSTART : in std_logic; -- Start transmitter
CLEAR : in std_logic; -- Clear transmitter state
WLS : in std_logic_vector(1 downto 0); -- Word length select
STB : in std_logic; -- Number of stop bits
PEN : in std_logic; -- Parity enable
EPS : in std_logic; -- Even parity select
SP : in std_logic; -- Stick parity
BC : in std_logic; -- Break control
DIN : in std_logic_vector(7 downto 0); -- Input data
TXFINISHED : out std_logic; -- Transmitter operation finished
SOUT : out std_logic -- Transmitter output
);
component slib_clock_div is
generic (
RATIO : integer := 8 -- Clock divider ratio
);
port (
CLK : in std_logic; -- Clock
RST : in std_logic; -- Reset
CE : in std_logic; -- Clock enable input
Q : out std_logic -- New clock enable output
);
end component;
Did I missed something, or it's just a bug in the UART sv code?
I am working on compiling Pulpino in vcs and run the simple "Helloworld" test, the UART is receving garbage. After long time of debugging, I found out the reason is actually coming from the System Verilog code of apb_uart_sv.
There are two UART modules in the /ips directory: apb_uart and apb_uart_sv. The default compilation seems choose VHDL code, and works fine, but the in the System Verilog code, the UART is sending data 16x faster than the baud rate can read, which causing the reading become garbage.
As the pulpino/sw/libs/sys_lib/src/uart.c says,
which doesn't seem to work in the System Verilog code. In the sv code, the uart_tx is sending at the 1/2 s_clk frequency, which is at 12.5MHz.
This is only one clk_i passing in, which is the SoC clock, without dividing.
In the VHDL code, there is a slib_clock_divider, which generate the TXCLK 8x slower (2x baudrate), combined with iTx2 in the logic, the SoC clock is divided by 16. Thus the UART baudrate is matched.
Did I missed something, or it's just a bug in the UART sv code?
Thanks