Files
es-praktikum/Milestone2/axis_audio_bitcrusher.vhd
2024-12-09 17:09:55 +01:00

147 lines
4.9 KiB
VHDL

library IEEE;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity axis_audio_bitcrusher is
generic(
BIT_REDUCTION : integer := 14;
HAS_LAST : boolean := false
);
port
(
AXIS_ACLK : in std_logic;
AXIS_ARESETN : in std_logic;
-- AXI Streaming Target Port
S_AXIS_TVALID : in std_logic := '0';
S_AXIS_TDATA : in std_logic_vector(15 downto 0) := (others => '0');
S_AXIS_TLAST : in std_logic := '0';
S_AXIS_TREADY : out std_logic;
-- AXI Streaming Initiator Port
M_AXIS_TVALID : out std_logic;
M_AXIS_TDATA : out std_logic_vector(15 downto 0);
M_AXIS_TLAST : out std_logic;
M_AXIS_TREADY : in std_logic := '1'
);
end;
architecture rtl of axis_audio_bitcrusher is
-- Steuersignale zwischen Steuerwerk und Rechenwerk
signal RegInputEn : std_logic := '0';
signal RegOutputEn : std_logic := '0';
-- Signale innerhalb des Rechenwerks
signal caculatorInput : std_logic_vector(15 downto 0);
signal caculatorOutput : std_logic_vector(15 downto 0);
signal safeTLast : std_logic := '0';
-- Finite state machine
type state_t is (S_INPUT, S_CALCULATE, S_OUTPUT, S_ERROR);
signal state : state_t := S_INPUT;
signal state_next : state_t;
begin
-- Register fuer die Inputdaten
RegInput: process
begin
wait until rising_edge(AXIS_ACLK);
if RegInputEn = '1' then
caculatorInput <= S_AXIS_TDATA;
end if;
end process;
-- Kombinatorik fuer Bitcrusherberechnung
Bitcrusher: process (caculatorInput)
begin
caculatorOutput <= caculatorInput(15 downto BIT_REDUCTION + 1) & (BIT_REDUCTION downto 0 => '0');
end process;
-- Register fuer die Outputdaten
RegOutput: process
begin
wait until rising_edge(AXIS_ACLK);
if RegOutputEn = '1' then
M_AXIS_TDATA <= caculatorOutput;
end if;
end process;
-- Prozesse fuer endlichen Automaten
Transition: process(state, AXIS_ARESETN, M_AXIS_TREADY, S_AXIS_TVALID, S_AXIS_TLAST)
begin
-- Default-Werte fuer Folgezustand und Mealy-Ausgaenge
state_next <= S_ERROR;
-- Berechnung des Folgezustandes und der Mealy-Ausgaenge
case state is
when S_INPUT =>
if HAS_LAST = true then
if S_AXIS_TLAST = '1' then
safeTLast <= '1';
elsif S_AXIS_TLAST = '0' then
safeTLast <= '0';
end if;
end if;
if S_AXIS_TVALID = '1' then
state_next <= S_CALCULATE;
elsif S_AXIS_TVALID = '0' then
state_next <= S_INPUT;
end if;
when S_CALCULATE =>
state_next <= S_OUTPUT;
when S_OUTPUT =>
if HAS_LAST = true then
if safeTLast = '1' then
M_AXIS_TLAST <= '1';
elsif safeTLast = '0' then
M_AXIS_TLAST <= '0';
end if;
end if;
if M_AXIS_TREADY = '1' then
state_next <= S_INPUT;
elsif M_AXIS_TREADY = '0' then
state_next <= S_OUTPUT;
end if;
when S_ERROR =>
if AXIS_ARESETN = '1' then
state_next <= S_OUTPUT;
else
state_next <= S_ERROR;
end if;
end case;
end process;
-- Register fuer Zustand und Ausgaenge
Reg: process
begin
wait until rising_edge(AXIS_ACLK);
-- Zustandswechsel
state <= state_next;
-- Berechnung der Moore-Ausgaenge, die nur vom Zustand abhaengen
-- Default-Werte
S_AXIS_TREADY <= 'X';
RegOutputEn <= 'X';
RegInputEn <= 'X';
M_AXIS_TVALID <= 'X';
case state_next is
when S_INPUT =>
S_AXIS_TREADY <= '1';
RegOutputEn <= '0';
RegInputEn <= '1';
M_AXIS_TVALID <= '0';
when S_CALCULATE =>
S_AXIS_TREADY <= '0';
RegOutputEn <= '1';
RegInputEn <= '0';
M_AXIS_TVALID <= '0';
when S_OUTPUT =>
S_AXIS_TREADY <= '0';
RegOutputEn <= '0';
RegInputEn <= '0';
M_AXIS_TVALID <= '1';
when S_ERROR =>
S_AXIS_TREADY <= 'X';
RegOutputEn <= 'X';
RegInputEn <= 'X';
M_AXIS_TVALID <= 'X';
end case;
end process;
end rtl;