Kan lägga upp det jag gjort hittills, har inte haft tid att testa det än men förhoppningsvis hinner jag göra det senare ikväll. Simuleringen ser iaf ut som jag har förväntat mig, Tanken är att den ska ta emot en bokstav flippa case på den och skicka tillbaka den, i simuleringen nedan skickar jag ett l och ett L ska komma tillbaka.
Simulering
Lägger med koden till uart rx/tx samt koden som kopplar ihop allt, där jag inkluderat buffringen av rx. Ni får gärna påpeka misstag, best practise och sånt som jag missat. Är som jag sa tidigare nybörjare vad gäller VHDL. Har läst lite sporadiskt i några böcker, men de verkar vara mest iriktade mot simulering, och inte syntes.
Vad gäller chipscope så jag inte säker på att man kan använda det eftersom kortet programmeras via USB.
uart_rx:
Kod: Markera allt
entity uart_rx is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
rx : in STD_LOGIC;
done : out STD_LOGIC;
data : out STD_LOGIC_VECTOR (7 downto 0);
busy : out STD_LOGIC);
end uart_rx;
architecture Behavioral of uart_rx is
signal counter : STD_LOGIC_VECTOR(7 downto 0) := "00000000";
signal c_enable : STD_LOGIC := '0';
signal rx_done : STD_LOGIC := '0';
signal rx_data : STD_LOGIC_VECTOR(9 downto 0) := "0000000000";
signal rx_busy : STD_LOGIC := '1';
signal bit_counter : integer range 0 to 10;
type state_type is (idle, start, sample, delay, ready);
signal state, next_state : state_type;
begin
-- Clock used for delays
DELAY_CLOCK: process (clk)
begin
if clk='1' and clk'event then
if c_enable='1' then
counter <= counter + 1;
else
counter <= (others => '0');
end if;
end if;
end process;
SYNC_PROC: process (clk)
begin
if (clk'event and clk = '1') then
if (reset = '1') then
state <= idle;
data <= "00000000";
done <= '0';
busy <= '1';
else
state <= next_state;
data <= rx_data(8 downto 1);
done <= rx_done;
busy <= rx_busy;
end if;
end if;
end process;
OUTPUT_DECODE: process (state)
begin
-- Enable counter for waiting states
if state = start OR state = delay then
c_enable <= '1';
else
c_enable <= '0';
end if;
-- Always busy if state is not idle
if state = idle then
rx_busy <= '0';
else
rx_busy <= '1';
end if;
-- Set done output if start & stop are OK and reset bit counter on done state
if state = ready then
rx_done <= rx_data(9) and not rx_data(0);
bit_counter <= 0;
else
rx_done <= '0';
end if;
-- Shift in the sampled bit and increase bit counter
if state = sample then
rx_data <= rx & rx_data(9 downto 1);
bit_counter <= bit_counter + 1;
end if;
end process;
NEXT_STATE_DECODE: process (state, rx, counter, bit_counter)
begin
next_state <= state; --default is to stay in current state
case (state) is
when idle =>
if rx = '0' then
next_state <= start;
end if;
when start =>
if counter = 69 then -- = 69 which is half a bit for 115200 baud and 16 MHz
next_state <= sample;
end if;
when sample =>
if bit_counter < 10 then -- one start bit, eight data bits and one stop bit
next_state <= delay;
else
next_state <= ready;
end if;
when delay =>
if counter = 139 then -- = 139 which is one bit time for 115200 baud and 16 MHz
next_state <= sample;
end if;
when ready =>
next_state <= idle;
end case;
end process;
end Behavioral;
uart_tx
Kod: Markera allt
entity uart_tx is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
send : in STD_LOGIC;
data : in STD_LOGIC_VECTOR (7 downto 0);
tx : out STD_LOGIC;
done : out STD_LOGIC;
busy : out STD_LOGIC);
end uart_tx;
architecture Behavioral of uart_tx is
signal counter : STD_LOGIC_VECTOR(7 downto 0) := "00000000";
signal c_enable : STD_LOGIC := '0';
signal tx_done : STD_LOGIC := '0';
signal tx_out : STD_LOGIC := '1';
signal tx_data : STD_LOGIC_VECTOR(9 downto 0) := "0000000000";
signal tx_busy : STD_LOGIC := '0';
signal bit_counter : integer range 0 to 10;
type state_type is (idle, start, delay, shift, ready);
signal state, next_state : state_type;
begin
-- Clock used for delays
DELAY_CLOCK: process (clk)
begin
if clk='1' and clk'event then
if c_enable='1' then
counter <= counter + 1;
else
counter <= (others => '0');
end if;
end if;
end process;
SYNC_PROC: process (clk)
begin
if (clk'event and clk = '1') then
if (reset = '1') then
state <= idle;
tx <= '1';
done <= '0';
busy <= '1';
else
state <= next_state;
tx <= tx_out;
done <= tx_done;
busy <= tx_busy;
end if;
end if;
end process;
OUTPUT_DECODE: process (state)
begin
-- When idle, put 1 on tx-line, otherwise the next byte to be sent.
if state = idle then
tx_out <= '1';
tx_busy <= '0';
else
tx_out <= tx_data(0);
tx_busy <= '1';
end if;
-- Latch data in start state
if state = start then
tx_data <= "1" & data & "0";
end if;
-- Enable counter while waiting
if state = delay then
c_enable <= '1';
else
c_enable <= '0';
end if;
-- shift the bits in tx_data right one step and increase bit counter
if state = shift then
tx_data <= "0" & tx_data(9 downto 1);
bit_counter <= bit_counter + 1;
end if;
-- Set done output and reset bit counter on done state
if state = ready then
tx_done <= '1';
bit_counter <= 0;
else
tx_done <= '0';
end if;
end process;
NEXT_STATE_DECODE: process (state, send, counter, bit_counter)
begin
next_state <= state; --default is to stay in current state
case (state) is
when idle =>
if send = '1' then
next_state <= start;
end if;
when start =>
next_state <= delay;
when delay =>
if counter = 138 then -- = 139 which is one bit time for 115200 baud
if bit_counter < 9 then
next_state <= shift;
else
next_state <= ready;
end if;
end if;
when shift =>
next_state <= delay;
when ready =>
next_state <= idle;
when others =>
next_state <= idle;
end case;
end process;
end Behavioral;
uart_test
Kod: Markera allt
entity uart_test2 is
Port ( clk : in STD_LOGIC;
rx : in STD_LOGIC;
tx : out STD_LOGIC;
rx_busy : out STD_LOGIC;
tx_busy : out STD_LOGIC;
tx_done : out STD_LOGIC);
end uart_test2;
architecture Behavioral of uart_test2 is
signal rx_buf : STD_LOGIC := '1';
signal reset : STD_LOGIC := '0';
signal rx_data : STD_LOGIC_VECTOR (7 downto 0);
signal tx_data : STD_LOGIC_VECTOR (7 downto 0);
signal send : STD_LOGIC := '0';
component caps_change
port ( char_in : in STD_LOGIC_VECTOR (7 downto 0);
char_out : out STD_LOGIC_VECTOR (7 downto 0));
end component;
component uart_rx
port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
rx : in STD_LOGIC;
done : out STD_LOGIC;
data : out STD_LOGIC_VECTOR (7 downto 0);
busy : out STD_LOGIC);
end component;
component uart_tx
port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
send : in STD_LOGIC;
data : in STD_LOGIC_VECTOR (7 downto 0);
tx : out STD_LOGIC;
done : out STD_LOGIC;
busy : out STD_LOGIC);
end component;
begin
-- Buffer the rx pin
BUFFER_RX: process(clk)
begin
if clk='1' and clk'event then
rx_buf <= rx;
end if;
end process;
caps_change1 : caps_change port map (char_in(7 downto 0) => rx_data(7 downto 0), char_out(7 downto 0) => tx_data(7 downto 0));
uart_rx1 : uart_rx port map (clk=>clk, reset=>reset, rx=>rx_buf, data(7 downto 0)=>rx_data(7 downto 0), done=>send, busy=>rx_busy);
uart_tx1 : uart_tx port map (clk=>clk, data(7 downto 0)=>tx_data(7 downto 0), reset=>reset, send=>send, done=>tx_done, tx=>tx, busy=>tx_busy);
end Behavioral;