~ruther/vhdl-spi

e8d0cfa4c8f015cb4375bf6a9081ab2b2663ed36 — František Boháček 1 year, 7 months ago 6d638ba main
feat: add spi_slave connecting spi_recv and spi_transmit
2 files changed, 129 insertions(+), 0 deletions(-)

A src/spi_slave.vhd
A testbench/tb_spi_slave.vhd
A src/spi_slave.vhd => src/spi_slave.vhd +54 -0
@@ 0,0 1,54 @@
library ieee;
use ieee.std_logic_1164.all;

entity spi_slave is

  generic (
    WIDTH : integer := 8);

  port (
    rst_in     : in  std_logic;
    tx_valid_i : in  std_logic;
    tx_ready_o : out std_logic;
    tx_data_i  : in  std_logic_vector(WIDTH - 1 downto 0);
    rx_valid_o : out std_logic;
    rx_data_o  : out std_logic_vector(WIDTH - 1 downto 0);

    tx_transmitting_o : out std_logic;

    so   : out std_logic;
    si   : in  std_logic;
    sck  : in  std_logic;
    cs_n : in  std_logic);

end entity spi_slave;

architecture a1 of spi_slave is
  signal gated_sck : std_logic;
begin  -- architecture a1
  gated_sck <= '1' when sck = '1' and cs_n = '0' else '0';

  tx: entity work.spi_transmit
    generic map (
      WIDTH       => WIDTH,
      ALIGN_START => '1')
    port map (
      clk_i           => gated_sck,
      rst_in          => rst_in,
      transmit_data_i => tx_data_i,
      valid_i         => tx_valid_i,
      ready_o         => tx_ready_o,
      transmitting_o  => tx_transmitting_o,
      transmit_bit_o  => so);

  rx: entity work.spi_recv
    generic map (
      WIDTH => WIDTH)
    port map (
      clk_i       => gated_sck,
      rst_in      => rst_in,
      data_i      => si,
      recv_o      => rx_valid_o,
      recv_data_o => rx_data_o);

end architecture a1;

A testbench/tb_spi_slave.vhd => testbench/tb_spi_slave.vhd +75 -0
@@ 0,0 1,75 @@
library ieee;
use ieee.std_logic_1164.all;

library spi;

library vunit_lib;
context vunit_lib.vunit_context;

entity tb_spi_slave is

  generic (
    runner_cfg : string);

end entity tb_spi_slave;

architecture tb of tb_spi_slave is
  signal clk : std_logic := '0';
  signal rst : std_logic := '0';

  signal tx_valid, tx_ready, rx_valid, tx_transmitting : std_logic;
  signal tx_data, rx_data : std_logic_vector(7 downto 0);

  signal gated_si : std_logic;
  signal so : std_logic;
  signal cs_n : std_logic := '1';

  signal loopback : std_logic := '0';
  signal si : std_logic := '0';
begin  -- architecture tb
  uut: entity spi.spi_slave
    generic map (
      WIDTH => 8)
    port map (
      rst_in => rst,
      tx_valid_i => tx_valid,
      tx_ready_o => tx_ready,
      tx_data_i => tx_data,
      rx_valid_o => rx_valid,
      rx_data_o => rx_data,
      tx_transmitting_o => tx_transmitting,
      so  => so,
      si  => gated_si,
      sck => clk,
      cs_n => cs_n);

  clk <= not clk after 1 ns;
  rst <= '1' after 6 ns;

  gated_si <= so when loopback = '1' else si;

  main: process is
  begin  -- process main
    wait until rst = '1';
    test_runner_setup(runner, runner_cfg);

    while test_suite loop
      if run("one_byte_loopback") then
        loopback <= '1';
        cs_n <= '0';
        tx_data <= "11100010";
        tx_valid <= '1';
        wait until falling_edge(clk);
        tx_valid <= '0';

        wait until falling_edge(clk);
        wait until rx_valid = '1';
        wait until falling_edge(clk);
        check_equal(rx_data, std_logic_vector'("11100010"));
      end if;
    end loop;

    test_runner_cleanup(runner);
  end process main;

end architecture tb;

Do not follow this link