* Implement serial port interface in test design.

This commit is contained in:
Joris van Rantwijk 2016-04-18 21:14:31 +02:00
parent 5b72e7f3f3
commit 5e02c373de
1 changed files with 136 additions and 3 deletions

View File

@ -17,7 +17,7 @@ entity test_sincos_serial is
generic ( generic (
-- Clock frequency divider from system clock to serial bitrate. -- Clock frequency divider from system clock to serial bitrate.
-- bitrate = system_clock_frequency / serial_bitrate_divider -- bitrate = system_clock_frequency / serial_bitrate_divider
serial_bitrate_divider: integer range 10 to 8191; serial_bitrate_divider: integer range 10 to 8192;
-- Select core. -- Select core.
-- 1 = 18-bit sin/cos generator; -- 1 = 18-bit sin/cos generator;
@ -65,10 +65,21 @@ architecture rtl of test_sincos_serial is
signal r_ser_rx_strobe: std_logic; signal r_ser_rx_strobe: std_logic;
signal r_ser_rx_byte: std_logic_vector(7 downto 0); signal r_ser_rx_byte: std_logic_vector(7 downto 0);
signal r_ser_rx_glitch: std_logic_vector(7 downto 0);
signal r_ser_rx_bit: std_logic;
signal r_ser_rx_timer: unsigned(12 downto 0);
signal r_ser_rx_timeout: std_logic;
signal r_ser_rx_state; std_logic_vector(1 downto 0);
signal r_ser_rx_shift: std_logic_vector(8 downto 0);
signal r_ser_tx_strobe: std_logic; signal r_ser_tx_strobe: std_logic;
signal r_ser_tx_busy: std_logic; signal r_ser_tx_busy: std_logic;
signal r_ser_tx_byte: std_logic_vector(7 downto 0); signal r_ser_tx_byte: std_logic_vector(7 downto 0);
signal r_ser_tx_bit: std_logic;
signal r_ser_tx_timer: unsigned(12 downto 0);
signal r_ser_tx_timeout: std_logic;
signal r_ser_tx_bitcnt: unsigned(3 downto 0);
signal r_ser_tx_shift: std_logic_vector(7 downto 0);
begin begin
@ -169,7 +180,129 @@ begin
-- TODO : byte-level protocol -- TODO : byte-level protocol
-- TODO : serial port RX machine -- Synchronous process.
-- TODO : serial port TX machine -- Serial port RX machine.
process (clk) is
begin
if rising_edge(clk) then
-- Default.
r_ser_rx_strobe <= '0';
-- Deglitch filter.
r_ser_rx_glitch <= r_ser_rx_glitch(6 downto 0) & ser_rx;
if r_ser_rx_glitch(7 downto 1) = "0000000" then
r_ser_rxbit <= '0';
elsif r_ser_rx_glitch(7 downto 1) = "1111111" then
r_ser_rxbit <= '1';
end if;
-- Bit timer.
r_ser_rx_timer <= r_ser_rx_timer - 1;
if r_ser_rx_timer = 0 then
r_ser_rx_timeout <= '1';
else
r_ser_rx_timeout <= '0';
end if;
-- RX state machine.
if r_ser_rx_state = "00" then
-- Wait for idle level.
if r_ser_rx_bit = '1' then
r_ser_rx_state <= "01";
end if;
elsif r_ser_rx_state = "01" then
-- Wait for start of byte.
r_ser_rx_shift(7 downto 0) <= (others => '0');
r_ser_rx_shift(8) <= '1';
r_ser_rx_timer <= to_unsigned(serial_bitrate_divider / 2 - 2, 13);
r_ser_rx_timeout <= '0';
if r_ser_rx_bit = '0' then
r_ser_rx_state <= "10";
end if;
elsif r_ser_rx_state = "10" then
-- Wait for data bit.
if r_ser_rx_timeout = '1' then
r_ser_rx_shift <= r_ser_rx_bit & r_ser_rx_shift(8 downto 1);
if r_ser_rx_shift(0) = '1' then
-- Reached end of byte.
if r_ser_rx_bit = '1' then
-- Got valid stop bit.
r_ser_rx_strobe <= '1';
r_ser_rx_state <= "01";
else
-- Got invalid stop bit.
r_ser_rx_state <= "00";
end if;
r_ser_rx_state <= "11";
end if;
r_ser_rx_timer <= to_unsigned(serial_bitrate_divider - 2);
end if;
else
-- Invalid state.
r_ser_rx_state <= "00";
end if;
-- Synchronous reset.
if rst = '1' then
r_ser_rx_state <= "00";
r_ser_rx_strobe <= '0';
end if;
end if;
end process;
-- Synchronous process.
-- Serial port TX machine.
process (clk) is
begin
if rising_edge(clk) then
-- Drive output register.
ser_tx <= r_ser_tx_bit;
-- Bit timer.
r_ser_tx_timer <= r_ser_tx_timer - 1;
if r_ser_tx_timer = 0 then
r_ser_tx_timeout <= '1';
else
r_ser_tx_timeout <= '0';
end if;
if r_ser_tx_busy = '0' then
-- Wait for start of byte.
r_ser_tx_timer <= to_unsigned(serial_bitrate_divider - 2, 13);
r_ser_tx_timeout <= '0';
r_ser_tx_shift <= r_ser_tx_byte;
r_ser_tx_bitcnt <= to_unsigned(9, 4);
if r_ser_tx_strobe = '1' then
-- Start new byte.
r_ser_tx_bit <= '0';
r_ser_tx_busy <= '1';
end if;
elsif r_ser_tx_busy = '1' and r_ser_tx_timout = '1' then
-- Send next bit.
r_ser_tx_bit <= r_ser_tx_shift(0);
r_ser_tx_shift <= "1" & r_ser_tx_shift(7 downto 1);
r_ser_tx_bitcnt <= r_ser_tx_bitcnt - 1;
r_ser_tx_timer <= to_unsigned(serial_bitrate_divider - 2, 13);
if r_ser_tx_bitcnt = 0 then
-- Just completed stop bit.
r_ser_tx_busy <= '0';
end if;
end if;
-- Synchronous reset.
if rst = '1' then
r_ser_tx_busy <= '0';
r_ser_tx_bit <= '1';
end if;
end if;
end process;
end architecture; end architecture;