Altera_Forum
Honored Contributor
9 years agoUART issue
Greetings everyone,
I'm working on an UART design (only the receiver), I followed an online pdf wich deals with the subject. I ended up with this following code :
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity uart_rx is
generic(
DBIT: integer:=8; --# data bits
SB_TICK: integer:=16; --# ticks for stop bits
N: integer := 7; -- size of q out corresponding to baud rate counter
M: integer := 100 -- divisor for baud rate generator oversampling x16 50MHz/16*31250=100
);
port(
clk, reset: in std_logic;
rx: in std_logic;
rx_done_tick: out std_logic;
q: out std_logic_vector(N-1 downto 0);
dout: out std_logic_vector(7 downto 0)
);
end uart_rx ;
architecture arch of uart_rx is
type state_type is (idle, start, data, stop);
signal state_reg, state_next: state_type;
signal s_reg, s_next: unsigned(3 downto 0);
signal n_reg, n_next: unsigned(2 downto 0);
signal b_reg, b_next: std_logic_vector(7 downto 0);
signal r_reg: unsigned(N-1 downto 0);
signal r_next: unsigned(N-1 downto 0);
signal max_tick : std_logic;
begin
-- baud generator
process(clk, reset)
begin
if(reset = '1')then
r_reg <= (others => '0');
elsif(rising_edge(clk))then
r_reg <= r_next;
end if;
end process;
-- next state logic
r_next <= (others => '0') when r_reg=(M-1) else r_reg + 1;
-- output logic
q <= std_logic_vector(r_reg);
max_tick <= '1' when r_reg=(M-1) else '0';
-- FSMD state & data registers
process(clk,reset)
begin
if reset='1' then
state_reg <= idle;
s_reg <= (others=>'0');
n_reg <= (others=>'0');
b_reg <= (others=>'0');
elsif (rising_edge(clk)) then
state_reg <= state_next;
s_reg <= s_next;
n_reg <= n_next;
b_reg <= b_next;
end if;
end process;
-- next-state logic & data path functional units/routing
process(state_reg,s_reg,n_reg,b_reg,max_tick,rx)
begin
state_next <= state_reg;
s_next <= s_reg;
n_next <= n_reg;
b_next <= b_reg;
rx_done_tick <='0';
case state_reg is
when idle =>
if rx='0' then
state_next <= start;
s_next <= (others=>'0');
end if;
when start =>
if (max_tick = '1') then
if s_reg=7 then
state_next <= data;
s_next <= (others=>'0');
n_next <= (others=>'0');
else
s_next <= s_reg + 1;
end if;
end if;
when data =>
if (max_tick = '1') then
if s_reg=15 then
s_next <= (others=>'0');
b_next <= rx & b_reg(7 downto 1) ;
if n_reg=(DBIT-1) then
state_next <= stop ;
else
n_next <= n_reg + 1;
end if;
else
s_next <= s_reg + 1;
end if;
end if;
when stop =>
if (max_tick = '1') then
if s_reg=(SB_TICK-1) then
state_next <= idle;
rx_done_tick <='1';
else
s_next <= s_reg + 1;
end if;
end if;
end case;
end process;
dout <= b_reg;
end arch;
I wrote a Test Bench for it and my simulation picking me up a strange anomaly : there is a unwanted spike produced on rx_done_tick just before the wanted one. http://www.alteraforum.com/forum/attachment.php?attachmentid=13060&stc=1 There is a spike on rx_done_tick but state_next doesnt change wich could be a lead. Hope someone can help me to figure this out.