Various projects using Raspberry Pi
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

215 lines
6.2 KiB

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FiRoCtrlE is
generic (
EXTRACT : boolean := true
);
port (
--+ system if
Clk_i : in std_logic;
Reset_i : in std_logic;
--+ ctrl/status
Start_i : in std_logic;
Wait_i : in std_logic_vector(7 downto 0);
Run_i : in std_logic_vector(7 downto 0);
--+ rnd data
DataValid_o : out std_logic;
Data_o : out std_logic_vector(7 downto 0);
-- firo
Run_o : out std_logic;
Data_i : in std_logic
);
end entity FiRoCtrlE;
architecture rtl of FiRoCtrlE is
signal s_firo_run : std_logic;
signal s_firo_valid : std_logic;
type t_neumann_state is (BIT1, BIT2, BIT3, BIT4);
signal s_neumann_state : t_neumann_state;
signal s_neumann_buffer : std_logic_vector(2 downto 0);
type t_register_state is (SLEEP, COLLECT);
signal s_register_state : t_register_state;
signal s_register_enable : std_logic;
signal s_register_din : std_logic_vector(1 downto 0);
signal s_register_data : std_logic_vector(8 downto 0);
signal s_register_counter : unsigned(2 downto 0);
signal s_register_length : natural range 1 to 2;
signal s_data : std_logic_vector(3 downto 0);
begin
Run_o <= s_run when s_register_state = COLLECT else '0';
s_data <= s_neumann_buffer & Data_i;
ControllerP : process (Clk_i) is
variable v_wait_cnt : unsigned(7 downto 0);
variable v_run_cnt : unsigned(7 downto 0);
begin
if (rising_edge(Clk_i)) then
if (s_register_state = SLEEP) then
v_wait_cnt := unsigned(Wait_i);
v_run_cnt := unsigned(Run_i);
s_firo_run <= '0';
s_firo_valid <= '0';
else
s_firo_valid <= '0';
if (v_wait_cnt = 0) then
s_firo_run <= '1';
else
v_wait_cnt := v_wait_cnt - 1;
end if;
if (v_run_cnt = 0) then
s_firo_run <= '0';
elsif (v_run_cnt = 1) then
s_firo_valid <= '1';
else
if (v_wait_cnt = 0) then
v_run_cnt := v_run_cnt - 1;
end if;
end if;
end if;
end if;
end process ControllerP;
extractor : if EXTRACT generate
VonNeumannP : process (Clk_i) is
begin
if (rising_edge(Clk_i)) then
if (Reset_i = '0') then
s_neumann_state <= BIT1;
else
case s_neumann_state is
when BIT1 =>
s_register_enable <= '0';
if (s_firo_valid = '1') then
s_neumann_buffer(2) <= Data_i;
s_neumann_state <= BIT2;
end if;
when BIT2 =>
if (s_firo_valid = '1') then
s_neumann_buffer(1) <= Data_i;
s_neumann_state <= BIT3;
end if;
when BIT3 =>
if (s_firo_valid = '1') then
s_neumann_buffer(0) <= Data_i;
s_neumann_state <= BIT4;
end if;
when BIT4 =>
if (s_firo_valid = '1') then
s_register_enable <= '1';
s_register_length <= 1;
s_register_din <= "00";
s_neumann_state <= BIT1;
case (s_data) is
when x"5" =>
s_register_din <= "01";
when x"1" | x"6" | x"7" =>
s_register_length <= 2;
when x"2" | x"9" | x"b" =>
s_register_din <= "01";
s_register_length <= 2;
when x"4" | x"a" | x"d" =>
s_register_din <= "10";
s_register_length <= 2;
when x"8" | x"c" | x"e" =>
s_register_din <= "11";
s_register_length <= 2;
when x"0" | x"f" =>
s_register_enable <= '0';
when others => -- incl. x"3"
null;
end case;
end if;
when others =>
null;
end case;
end if;
end if;
end process VonNeumannP;
end generate;
no_extractor : if not(EXTRACT) generate
s_register_enable <= s_firo_valid;
s_register_din(0) <= Data_i;
s_register_length <= 1;
end generate;
Data_o <= s_register_data(7 downto 0);
ShiftRegisterP : process (Clk_i) is
begin
if (rising_edge(Clk_i)) then
if (Reset_i = '0') then
s_register_counter <= (others => '1');
s_register_state <= SLEEP;
DataValid_o <= '0';
else
case s_register_state is
when SLEEP =>
DataValid_o <= '0';
if (Start_i = '1' and Run_i /= x"00") then
s_register_state <= COLLECT;
s_register_data(0) <= s_register_data(8);
end if;
when COLLECT =>
if (s_register_enable = '1') then
if (s_register_counter = 0) then
s_register_data <= s_register_din(1) & s_register_data(6 downto 0) & s_register_din(0);
DataValid_o <= '1';
s_register_state <= SLEEP;
elsif (s_register_counter = 1) then
if (s_register_length = 1) then
s_register_data(7 downto 0) <= s_register_data(6 downto 0) & s_register_din(0);
end if;
if (s_register_length = 2) then
s_register_data(7 downto 0) <= s_register_data(5 downto 0) & s_register_din;
DataValid_o <= '1';
s_register_state <= SLEEP;
end if;
else
if (s_register_length = 1) then
s_register_data(7 downto 0) <= s_register_data(6 downto 0) & s_register_din(0);
else
s_register_data(7 downto 0) <= s_register_data(5 downto 0) & s_register_din;
end if;
end if;
s_register_counter <= s_register_counter - s_register_length;
end if;
when others =>
null;
end case;
end if;
end if;
end process ShiftRegisterP;
end architecture rtl;