* Implement serial port interface in test design.
This commit is contained in:
parent
5b72e7f3f3
commit
5e02c373de
|
@ -17,7 +17,7 @@ entity test_sincos_serial is
|
|||
generic (
|
||||
-- Clock frequency divider from system clock to serial bitrate.
|
||||
-- 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.
|
||||
-- 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_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_busy: std_logic;
|
||||
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
|
||||
|
||||
|
@ -169,7 +180,129 @@ begin
|
|||
|
||||
-- TODO : byte-level protocol
|
||||
|
||||
-- TODO : serial port RX machine
|
||||
-- TODO : serial port TX machine
|
||||
-- Synchronous process.
|
||||
-- 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;
|
||||
|
|
Loading…
Reference in New Issue