~ruther/vhdl-i2c

e29d030c7ccc11c4c880908901d7a6c63a11ce34 — Rutherther 1 year, 5 months ago 906e750
feat: add utility entities

Delay, metastability filter, open drain buffer, synchronous edge detector
A src/utils/delay.vhd => src/utils/delay.vhd +36 -0
@@ 0,0 1,36 @@
library ieee;
use ieee.std_logic_1164.all;

entity delay is
  generic (
    DELAY : natural);

  port (
    clk_i   : in std_logic;
    rst_in  : in std_logic;
    signal_i : in std_logic;
    signal_o : out std_logic);

end entity delay;

architecture a1 of delay is
  signal DELAYED_PULSE_POS : natural := DELAY - 1;
  signal curr_pulses : std_logic_vector(DELAYED_PULSE_POS downto 0);
  signal next_pulses : std_logic_vector(DELAYED_PULSE_POS downto 0);
begin  -- architecture a1

  signal_o <= curr_pulses(DELAYED_PULSE_POS);
  next_pulses <= curr_pulses(DELAYED_PULSE_POS - 1 downto 1) & signal_i;

  set_regs: process (clk_i) is
  begin  -- process set_regs
    if rising_edge(clk_i) then          -- rising clock edge
      if rst_in = '0' then              -- synchronous reset (active low)
        curr_pulses <= (others => '0');
      else
        curr_pulses <= next_pulses;
      end if;
    end if;
  end process set_regs;

end architecture a1;

A src/utils/metastability_filter.vhd => src/utils/metastability_filter.vhd +26 -0
@@ 0,0 1,26 @@
library ieee;
use ieee.std_logic_1164.all;

entity metastability_filter is

  port (
    clk_i    : in  std_logic;
    signal_i : in  std_logic;
    signal_o : out std_logic);

end entity metastability_filter;

architecture a1 of metastability_filter is

begin  -- architecture a1

  entity work.delay
    generic map (
      DELAY => 2)
    port map (
      clk_i   => clk_i,
      rst_in  => '1',
      signal_i => signal_i,
      signal_o => signal_o);

end architecture a1;

A src/utils/open_drain_buffer.vhd => src/utils/open_drain_buffer.vhd +25 -0
@@ 0,0 1,25 @@
library ieee;
use ieee.std_logic_1164.all;

entity open_drain_buffer is

  port (
    pad_io   : inout std_logic;         -- The pad itself, will be set to 'Z'
                                        -- when enable_i = '0'
    enable_i : in    std_logic;         -- Whether to enable output, ie. set
                                        -- pad to '0' for enable_i = '1'
    state_o  : out   std_logic);        -- The state of the pad, relevant if
                                        -- enable_i = '0'

end entity open_drain_buffer;

architecture a1 of open_drain_buffer is

begin  -- architecture a1

  pad_io <= '0' when enable_i = '0' else
            'Z';

  state_o <= pad_io;

end architecture a1;

A src/utils/pulse_delay.vhd => src/utils/pulse_delay.vhd +0 -0
A src/utils/sync_edge_detector.vhd => src/utils/sync_edge_detector.vhd +54 -0
@@ 0,0 1,54 @@
-------------------------------------------------------------------------------
-- Title      : Synchronous edge detector
-- Project    :
-------------------------------------------------------------------------------
-- File       : sync_edge_detector.vhd
-- Author     : Frantisek Bohacek  <rutherther@protonmail.com>
-- Created    : 2023-11-26
-- Last update: 2023-11-26
-- Platform   :
-- Standard   : VHDL'93/02
-------------------------------------------------------------------------------
-- Description: Detects edges in signal_i, synchronously to clk_i
-------------------------------------------------------------------------------
-- Copyright (c) 2023
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 2023-11-26  1.0      ruther	Created
-------------------------------------------------------------------------------


library ieee;
use ieee.std_logic_1164.all;

entity sync_edge_detector is

  port (
    clk_i          : in  std_logic;
    signal_i       : in  std_logic;
    rising_edge_o  : out std_logic;
    falling_edge_o : out std_logic);

end entity sync_edge_detector;

architecture a1 of sync_edge_detector is
  signal reg_prev_signal : std_logic;
  signal next_prev_signal : std_logic;
begin  -- architecture a1
  next_prev_signal <= signal_i;

  rising_edge_o <= '1' when reg_prev_signal = '0' and signal_i = '1' else
                   '0';

  falling_edge_o <= '1' when reg_prev_signal = '1' and signal_i = '0' else
                    '0';

  set_next: process (clk_i) is
  begin  -- process set_next
    if rising_edge(clk_i) then          -- rising clock edge
      reg_prev_signal <= next_prev_signal;
    end if;
  end process set_next;

end architecture a1;

Do not follow this link