diff --git a/soc/peripheral/scrolling_buffer.vhd b/soc/peripheral/scrolling_buffer.vhd new file mode 100644 index 0000000..eb58192 --- /dev/null +++ b/soc/peripheral/scrolling_buffer.vhd @@ -0,0 +1,83 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity scrolling_buffer is + port( + clk : in std_logic; + rst : in std_logic; + buffer_clear : in std_logic; + buffer_write : in std_logic; + buffer_data : in std_logic_vector(4 downto 0); + next_char : in std_logic; + hex_char : out std_logic_vector(4 downto 0) + ); +end entity scrolling_buffer; + +architecture Behavioral of scrolling_buffer is + + constant BUFFER_SIZE : integer := 16; + + type ring_buffer_type is array (0 to BUFFER_SIZE - 1) of std_logic_vector(4 downto 0); + signal ptr_write : integer range 0 to BUFFER_SIZE - 1; + signal ptr_read : integer range 0 to BUFFER_SIZE - 1; + signal ptr_last : integer range -1 to BUFFER_SIZE - 1; + + signal ring_buffer : ring_buffer_type; + +begin + + process(clk) + begin + if clk'event and clk='1' then + if rst = '1' then + ptr_last <= -1; + ptr_write <= 0; + ring_buffer <= (others => (others => '0')); + else + if buffer_write = '1' then + ring_buffer(ptr_write) <= buffer_data; + + if ptr_last /= BUFFER_SIZE - 1 then + ptr_last <= ptr_write; + end if; + + if ptr_write = BUFFER_SIZE - 1 then + ptr_write <= 0; + else + ptr_write <= ptr_write + 1; + end if; + elsif buffer_clear = '1' then + ptr_last <= -1; + end if; + end if; + end if; + end process; + + process(clk) + begin + if clk'event and clk='1' then + if rst = '1' then + ptr_read <= 0; + hex_char <= (others => '0'); + else + hex_char <= (others => '0'); + + if next_char = '1' then + if ptr_last = -1 then -- Special case + hex_char <= (others => '0'); + else + hex_char <= ring_buffer(ptr_read); + + if ptr_read = ptr_last then + ptr_read <= 0; + else + ptr_read <= ptr_read + 1; + end if; + end if; + end if; + end if; + end if; + end process; + +end Behavioral; diff --git a/soc/testbench/scrolling_buffer_tb.vhd b/soc/testbench/scrolling_buffer_tb.vhd new file mode 100644 index 0000000..7adfb9a --- /dev/null +++ b/soc/testbench/scrolling_buffer_tb.vhd @@ -0,0 +1,121 @@ +-- See the file "LICENSE" for the full license governing this code. -- +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +LIBRARY work; +USE work.lt16soc_peripherals.ALL; + +ENTITY scrolling_buffer_tb IS +END ENTITY; + +ARCHITECTURE sim OF scrolling_buffer_tb IS + + constant CLK_PERIOD : time := 10 ns; + + signal rst : std_logic; + signal clk : std_logic := '0'; + + signal buffer_clear : std_logic := '0'; + signal buffer_write : std_logic := '0'; + signal buffer_data : std_logic_vector(4 downto 0) := (others => '0'); + signal next_char : std_logic := '0'; + signal hex_char : std_logic_vector(4 downto 0); + + component scrolling_buffer + port( + clk : in std_logic; + rst : in std_logic; + buffer_clear : in std_logic; + buffer_write : in std_logic; + buffer_data : in std_logic_vector(4 downto 0); + next_char : in std_logic; + hex_char : out std_logic_vector(4 downto 0) + ); + end component; + +BEGIN + + buf: scrolling_buffer + port map( + clk => clk, + rst => rst, + buffer_clear => buffer_clear, + buffer_write => buffer_write, + buffer_data => buffer_data, + next_char => next_char, + hex_char => hex_char + ); + + clk_gen: process + begin + clk <= not clk; + wait for CLK_PERIOD/2; + end process clk_gen; + + stimuli: process + begin + rst <= '1'; + wait for CLK_PERIOD; + + rst <= '0'; + wait for CLK_PERIOD; + + buffer_data <= "00001"; + buffer_write <= '1'; + + wait for CLK_PERIOD; + buffer_data <= "01011"; + + wait for CLK_PERIOD; + buffer_write <= '0'; + + wait for CLK_PERIOD; + buffer_data <= "01001"; + buffer_write <= '1'; + + wait for CLK_PERIOD; + buffer_data <= "00000"; + buffer_write <= '0'; + + wait for CLK_PERIOD; + next_char <= '1'; + + wait for CLK_PERIOD; + assert hex_char = "00001" severity failure; + + wait for CLK_PERIOD; + assert hex_char = "01011" severity failure; + + wait for CLK_PERIOD; + assert hex_char = "01001" severity failure; + + wait for CLK_PERIOD; + next_char <= '0'; + assert hex_char = "00001" severity failure; -- special case + + wait for CLK_PERIOD * 3; + + -- Write buffer full + buffer_data <= "11111"; + buffer_write <= '1'; + + wait for CLK_PERIOD * 16; + buffer_data <= "00000"; + buffer_write <= '0'; + + wait for CLK_PERIOD; + next_char <= '1'; + + wait for CLK_PERIOD * 8; + buffer_clear <= '1'; + + wait for CLK_PERIOD; + buffer_clear <= '0'; + + wait for CLK_PERIOD * 8; + + assert false report "Simulation terminated!" severity failure; + end process stimuli; + +END ARCHITECTURE;