~ruther/vhdl-spi

be420a443e64cc222882d795f7535e34626cd1de — František Boháček 1 year, 10 months ago b5e7d3a
feat: add shift registers
A src/piso_shift_register.vhd => src/piso_shift_register.vhd +32 -0
@@ 0,0 1,32 @@
library ieee;
use ieee.std_logic_1164.all;

entity piso_shift_register is

  generic (
    WIDTH : integer := 8);

  port (
    clk_i : in std_logic;
    data_i : in std_logic_vector(WIDTH - 1 downto 0);
    store_i : in std_logic;
    q_o : out std_logic);

end entity piso_shift_register;

architecture a1 of piso_shift_register is
  signal q_reg : std_logic_vector(WIDTH - 1 downto 0);
  signal q_next : std_logic_vector(WIDTH - 1 downto 0);
begin  -- architecture a1
  q_next <= data_i when store_i = '1' else
            q_reg(WIDTH - 2 downto 0) & '0';
  q_o <= q_reg(WIDTH - 1);

  set_q_reg: process (clk_i) is
  begin  -- process set_q_reg
    if rising_edge(clk_i) then        -- rising clock edge
      q_reg <= q_next;
    end if;
  end process set_q_reg;

end architecture a1;

A src/sipo_shift_register.vhd => src/sipo_shift_register.vhd +34 -0
@@ 0,0 1,34 @@
library ieee;
use ieee.std_logic_1164.all;

entity sipo_shift_register is

  generic (
    WIDTH : integer := 8);              -- The width of the register,  in bits

  port (
    clk_i : in std_logic;
    data_i : in std_logic;
    q_o : out std_logic_vector(WIDTH - 1 downto 0));

end entity sipo_shift_register;

architecture a1 of sipo_shift_register is
    signal q_reg : std_logic_vector(WIDTH - 1 downto 0);
    signal q_next : std_logic_vector(WIDTH - 1 downto 0);
begin  -- architecture a1
  q_next <= q_reg(WIDTH - 2 downto 0) & data_i;
  q_o <= q_reg;

  -- purpose: Set the q_reg
  -- type   : sequential
  -- inputs : clock_i, reset_in
  -- outputs: q_reg
  set_q_reg: process (clk_i) is
  begin  -- process set_q_reg
    if rising_edge(clk_i) then        -- rising clock edge
      q_reg <= q_next;
    end if;
  end process set_q_reg;

end architecture a1;

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

library spi;

library vunit_lib;
context vunit_lib.vunit_context;

entity tb_spi_recv is

  generic (
    runner_cfg : string);

end entity tb_spi_recv;

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

  signal pass_clk : std_logic := '0';

  signal in_data_bit : std_logic := '0';
  signal recv_flag : std_logic;
  signal recv_data : std_logic_vector(7 downto 0);
  signal uut_clk : std_logic;
begin  -- architecture tb

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

  uut_clk <= clk and pass_clk;

  uut: entity spi.spi_recv
    generic map (
      WIDTH => 8)
    port map (
      clk_i  => uut_clk,
      rst_in => rst,
      data_i => in_data_bit,
      recv_o => recv_flag,
      recv_data_o => recv_data);

  main: process is
  begin  -- process main
    wait until rst = '1';

    test_runner_setup(runner, runner_cfg);
    show(get_logger(default_checker), display_handler, pass);

    while test_suite loop
      if run("one_byte") then
        wait until falling_edge(clk);
        pass_clk <= '1';

        for i in 0 to 3 loop
          in_data_bit <= '1';
          check_equal(recv_flag, '0');
          wait until falling_edge(clk);
        end loop;  -- i

        for i in 0 to 3 loop
          in_data_bit <= '0';
          check_equal(recv_flag, '0');
          wait until falling_edge(clk);
        end loop;  -- i

        check_equal(recv_flag, '1');
        check_equal(recv_data, std_logic_vector'("11110000"));
        wait until falling_edge(clk);
        check_equal(recv_flag, '0');
      elsif run("more_bytes") then
        wait until falling_edge(clk);
        pass_clk <= '1';

        for j in 0 to 3 loop
          for i in 0 to 3 loop
            in_data_bit <= '1';
            if i /= 0 or j = 0 then
              check_equal(recv_flag, '0');
            end if;
            wait until falling_edge(clk);
          end loop;  -- i

          for i in 0 to 3 loop
            in_data_bit <= '0';
            check_equal(recv_flag, '0');
            wait until falling_edge(clk);
          end loop;  -- i

          in_data_bit <= '1';
          check_equal(recv_flag, '1');
          check_equal(recv_data, std_logic_vector'("11110000"));
        end loop;  -- j
      end if;
    end loop;

    test_runner_cleanup(runner);
  end process main;

end architecture tb;

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

library spi;

library vunit_lib;
context vunit_lib.vunit_context;

entity tb_spi_transmit is

  generic (
    runner_cfg : string);

end entity tb_spi_transmit;

architecture a1 of tb_spi_transmit is
  signal clk : std_logic := '0';
  signal rst : std_logic := '0';

  signal transmit_data : std_logic_vector(7 downto 0);
  signal transmit_pulse : std_logic;

  signal ready : std_logic;
  signal transmitting : std_logic;
  signal mosi : std_logic;
begin  -- architecture a1
  uut: entity spi.spi_transmit
    generic map (
      WIDTH => 8)
    port map (
      clk_i  => clk,
      rst_in => rst,
      transmit_data_i => transmit_data,
      transmit_i => transmit_pulse,
      ready_o => ready,
      transmitting_o => transmitting,
      transmit_bit_o => mosi);

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

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

    while test_suite loop
      if run("transmit_one_byte") then
        wait until falling_edge(clk);
        check_equal(ready, '1');
        transmit_pulse <= '1';
        transmit_data <= "11100010";
        wait until falling_edge(clk);
        transmit_pulse <= '0';

        for i in 0 to 2 loop
          check_equal(ready, '1');
          check_equal(transmitting, '1');
          check_equal(mosi, '1');
          wait until falling_edge(clk);
        end loop;  -- i

        for i in 0 to 2 loop
          check_equal(ready, '1');
          check_equal(transmitting, '1');
          check_equal(mosi, '0');
          wait until falling_edge(clk);
        end loop;  -- i

        check_equal(ready, '1');
        check_equal(transmitting, '1');
        check_equal(mosi, '1');
        wait until falling_edge(clk);
        check_equal(ready, '1');
        check_equal(transmitting, '1');
        check_equal(mosi, '0');
        wait until falling_edge(clk);
        check_equal(ready, '1');
        check_equal(transmitting, '0');
      elsif run("transmit_more_bytes") then
        wait until falling_edge(clk);
        check_equal(ready, '1');
        transmit_pulse <= '1';
        transmit_data <= "11100010";
        wait until falling_edge(clk);
        check_equal(ready, '1');
        transmit_pulse <= '1';
        transmit_data <= "00011101";

        check_equal(ready, '1');
        check_equal(transmitting, '1');
        check_equal(mosi, '1');
        wait until falling_edge(clk);
        check_equal(ready, '0');
        transmit_pulse <= '0';

        for i in 0 to 1 loop
          check_equal(ready, '0');
          check_equal(transmitting, '1');
          check_equal(mosi, '1');
          wait until falling_edge(clk);
        end loop;  -- i

        for i in 0 to 2 loop
          check_equal(ready, '0');
          check_equal(transmitting, '1');
          check_equal(mosi, '0');
          wait until falling_edge(clk);
        end loop;  -- i

        check_equal(ready, '0');
        check_equal(transmitting, '1');
        check_equal(mosi, '1');
        wait until falling_edge(clk);

        check_equal(ready, '0');
        check_equal(transmitting, '1');
        check_equal(mosi, '0');
        wait until falling_edge(clk);

        -- starting to send second byte
        for i in 0 to 2 loop
          check_equal(ready, '1');
          check_equal(transmitting, '1');
          check_equal(mosi, '0');
          wait until falling_edge(clk);
        end loop;  -- i

        for i in 0 to 2 loop
          check_equal(ready, '1');
          check_equal(transmitting, '1');
          check_equal(mosi, '1');
          wait until falling_edge(clk);
        end loop;  -- i

        check_equal(ready, '1');
        check_equal(transmitting, '1');
        check_equal(mosi, '0');
        wait until falling_edge(clk);

        check_equal(ready, '1');
        check_equal(transmitting, '1');
        check_equal(mosi, '1');

        wait until falling_edge(clk);
        check_equal(ready, '1');
        check_equal(transmitting, '0');
        wait until falling_edge(clk);
        check_equal(ready, '1');
        check_equal(transmitting, '0');
      end if;
    end loop;

    test_runner_cleanup(runner);
  end process;

end architecture a1;

Do not follow this link