Project

General

Profile

714 markw
---------------------------------------------------------------------------
999 markw
-- (c) 2020 mark watson
714 markw
-- I am happy for anyone to use this for non-commercial use.
-- If my vhdl files are used commercially or otherwise sold,
-- please contact me for explicit permission at scrameta (gmail).
-- This applies for source and binary form and derived works.
---------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_MISC.all;

ENTITY pokey_mixer_mux IS
PORT
(
CLK : IN STD_LOGIC;
1219 markw
RESET_N : IN STD_LOGIC;
714 markw
1012 markw
CHANNEL_0 : IN unsigned(5 downto 0);
CHANNEL_1 : IN unsigned(5 downto 0);
CHANNEL_2 : IN unsigned(5 downto 0);
CHANNEL_3 : IN unsigned(5 downto 0);
714 markw
1149 markw
VOLUME_OUT_0 : OUT unsigned(15 downto 0);
VOLUME_OUT_1 : OUT unsigned(15 downto 0);
VOLUME_OUT_2 : OUT unsigned(15 downto 0);
VOLUME_OUT_3 : OUT unsigned(15 downto 0);
999 markw
1203 markw
PROFILE_ADDR : OUT std_logic_vector(5 downto 0);
PROFILE_REQUEST : OUT std_logic;
PROFILE_READY : IN std_logic;
PROFILE_DATA : IN std_logic_vector(15 downto 0)
714 markw
);
END pokey_mixer_mux;

ARCHITECTURE vhdl OF pokey_mixer_mux IS
1283 markw
signal CHANNEL_STATE_NEXT : STD_LOGIC_VECTOR(2 downto 0);
signal CHANNEL_STATE_REG : STD_LOGIC_VECTOR(2 downto 0);
constant CHANNEL_STATE_WAIT0 : STD_LOGIC_VECTOR(2 downto 0) := "000";
constant CHANNEL_STATE_WAIT1 : STD_LOGIC_VECTOR(2 downto 0) := "001";
constant CHANNEL_STATE_WAIT2 : STD_LOGIC_VECTOR(2 downto 0) := "010";
constant CHANNEL_STATE_WAIT3 : STD_LOGIC_VECTOR(2 downto 0) := "011";
constant CHANNEL_STATE_REQUEST0 : STD_LOGIC_VECTOR(2 downto 0) := "100";
constant CHANNEL_STATE_REQUEST1 : STD_LOGIC_VECTOR(2 downto 0) := "101";
constant CHANNEL_STATE_REQUEST2 : STD_LOGIC_VECTOR(2 downto 0) := "110";
constant CHANNEL_STATE_REQUEST3 : STD_LOGIC_VECTOR(2 downto 0) := "111";
714 markw
1219 markw
signal CHANNEL_DIRTY_NEXT : STD_LOGIC_VECTOR(3 downto 0);
signal CHANNEL_DIRTY_REG : STD_LOGIC_VECTOR(3 downto 0);
signal CHANNEL_CHANGED : STD_LOGIC_VECTOR(3 downto 0);
714 markw
1219 markw
signal CHANNEL_IN_0_NEXT : unsigned(5 downto 0);
signal CHANNEL_IN_0_REG : unsigned(5 downto 0);
signal CHANNEL_IN_1_NEXT : unsigned(5 downto 0);
signal CHANNEL_IN_1_REG : unsigned(5 downto 0);
signal CHANNEL_IN_2_NEXT : unsigned(5 downto 0);
signal CHANNEL_IN_2_REG : unsigned(5 downto 0);
signal CHANNEL_IN_3_NEXT : unsigned(5 downto 0);
signal CHANNEL_IN_3_REG : unsigned(5 downto 0);

1149 markw
signal VOLUME_OUT_0_NEXT : unsigned(15 downto 0);
signal VOLUME_OUT_0_REG : unsigned(15 downto 0);
signal VOLUME_OUT_1_NEXT : unsigned(15 downto 0);
signal VOLUME_OUT_1_REG : unsigned(15 downto 0);
signal VOLUME_OUT_2_NEXT : unsigned(15 downto 0);
signal VOLUME_OUT_2_REG : unsigned(15 downto 0);
signal VOLUME_OUT_3_NEXT : unsigned(15 downto 0);
signal VOLUME_OUT_3_REG : unsigned(15 downto 0);
1219 markw
signal CHANNEL_MUX : STD_LOGIC_VECTOR(1 downto 0);
signal CHANNEL_SUM_OUT : unsigned(5 downto 0);
714 markw
BEGIN

1219 markw
process(clk,reset_n)
714 markw
begin
1219 markw
if (reset_n='0') then
CHANNEL_STATE_REG <= CHANNEL_STATE_WAIT0;
CHANNEL_DIRTY_REG <= (others=>'1');
714 markw
1219 markw
CHANNEL_IN_0_REG <= (others=>'0');
CHANNEL_IN_1_REG <= (others=>'0');
CHANNEL_IN_2_REG <= (others=>'0');
CHANNEL_IN_3_REG <= (others=>'0');

VOLUME_OUT_0_REG <= (others=>'0');
VOLUME_OUT_1_REG <= (others=>'0');
VOLUME_OUT_2_REG <= (others=>'0');
VOLUME_OUT_3_REG <= (others=>'0');
elsif (clk'event and clk='1') then
CHANNEL_STATE_REG <= CHANNEL_STATE_NEXT;
CHANNEL_DIRTY_REG <= CHANNEL_DIRTY_NEXT;

CHANNEL_IN_0_REG <= CHANNEL_IN_0_NEXT;
CHANNEL_IN_1_REG <= CHANNEL_IN_1_NEXT;
CHANNEL_IN_2_REG <= CHANNEL_IN_2_NEXT;
CHANNEL_IN_3_REG <= CHANNEL_IN_3_NEXT;

999 markw
VOLUME_OUT_0_REG <= VOLUME_OUT_0_NEXT;
VOLUME_OUT_1_REG <= VOLUME_OUT_1_NEXT;
VOLUME_OUT_2_REG <= VOLUME_OUT_2_NEXT;
VOLUME_OUT_3_REG <= VOLUME_OUT_3_NEXT;
714 markw
END IF;
END PROCESS;

734 markw
-- takes a few cycles for each channel
1219 markw
process(
CHANNEL_IN_0_REG,CHANNEL_IN_1_REG,CHANNEL_IN_2_REG,CHANNEL_IN_3_REG,
CHANNEL_0,CHANNEL_1,CHANNEL_2,CHANNEL_3
)
1203 markw
begin
1219 markw
CHANNEL_IN_0_NEXT <= CHANNEL_0;
CHANNEL_IN_1_NEXT <= CHANNEL_1;
CHANNEL_IN_2_NEXT <= CHANNEL_2;
CHANNEL_IN_3_NEXT <= CHANNEL_3;

CHANNEL_CHANGED(0) <= '0';
if (CHANNEL_0 /= CHANNEL_IN_0_REG) then
CHANNEL_CHANGED(0) <= '1';
1203 markw
end if;
1219 markw
CHANNEL_CHANGED(1) <= '0';
if (CHANNEL_1 /= CHANNEL_IN_1_REG) then
CHANNEL_CHANGED(1) <= '1';
end if;
CHANNEL_CHANGED(2) <= '0';
if (CHANNEL_2 /= CHANNEL_IN_2_REG) then
CHANNEL_CHANGED(2) <= '1';
end if;
CHANNEL_CHANGED(3) <= '0';
if (CHANNEL_3 /= CHANNEL_IN_3_REG) then
CHANNEL_CHANGED(3) <= '1';
end if;
1203 markw
end process;
714 markw
1219 markw
process(channel_state_reg,profile_ready,CHANNEL_DIRTY_REG,CHANNEL_CHANGED)
begin
CHANNEL_STATE_NEXT <= CHANNEL_STATE_REG;
CHANNEL_DIRTY_NEXT <= CHANNEL_DIRTY_REG or channel_changed;

CHANNEL_MUX <= (others=>'0');
1221 markw
PROFILE_REQUEST <= '0';
1219 markw
case CHANNEL_STATE_REG is
when CHANNEL_STATE_WAIT0 =>
if (CHANNEL_DIRTY_REG(0)='1') then
CHANNEL_STATE_NEXT <= CHANNEL_STATE_REQUEST0;
else
CHANNEL_STATE_NEXT <= CHANNEL_STATE_WAIT1;
end if;
when CHANNEL_STATE_WAIT1 =>
if (CHANNEL_DIRTY_REG(1)='1') then
CHANNEL_STATE_NEXT <= CHANNEL_STATE_REQUEST1;
else
CHANNEL_STATE_NEXT <= CHANNEL_STATE_WAIT2;
end if;
when CHANNEL_STATE_WAIT2 =>
if (CHANNEL_DIRTY_REG(2)='1') then
CHANNEL_STATE_NEXT <= CHANNEL_STATE_REQUEST2;
else
CHANNEL_STATE_NEXT <= CHANNEL_STATE_WAIT3;
end if;
when CHANNEL_STATE_WAIT3 =>
if (CHANNEL_DIRTY_REG(3)='1') then
CHANNEL_STATE_NEXT <= CHANNEL_STATE_REQUEST3;
else
CHANNEL_STATE_NEXT <= CHANNEL_STATE_WAIT0;
end if;
when CHANNEL_STATE_REQUEST0 =>
CHANNEL_MUX <= "00";
1221 markw
PROFILE_REQUEST <= '1';
CHANNEL_DIRTY_NEXT(0) <= not(profile_ready);
1219 markw
if (profile_ready='1') then
CHANNEL_STATE_NEXT <= CHANNEL_STATE_WAIT1;
end if;
when CHANNEL_STATE_REQUEST1 =>
CHANNEL_MUX <= "01";
1221 markw
PROFILE_REQUEST <= '1';
CHANNEL_DIRTY_NEXT(1) <= not(profile_ready);
1219 markw
if (profile_ready='1') then
CHANNEL_STATE_NEXT <= CHANNEL_STATE_WAIT2;
end if;
when CHANNEL_STATE_REQUEST2 =>
CHANNEL_MUX <= "10";
1221 markw
PROFILE_REQUEST <= '1';
CHANNEL_DIRTY_NEXT(2) <= not(profile_ready);
1219 markw
if (profile_ready='1') then
CHANNEL_STATE_NEXT <= CHANNEL_STATE_WAIT3;
end if;
when CHANNEL_STATE_REQUEST3 =>
CHANNEL_MUX <= "11";
1221 markw
PROFILE_REQUEST <= '1';
CHANNEL_DIRTY_NEXT(3) <= not(profile_ready);
1219 markw
if (profile_ready='1') then
CHANNEL_STATE_NEXT <= CHANNEL_STATE_WAIT0;
end if;
when OTHERS =>
CHANNEL_STATE_NEXT <= CHANNEL_STATE_WAIT0;
end case;
end process;

714 markw
-- mux input
PROCESS(
999 markw
CHANNEL_0,CHANNEL_1,CHANNEL_2,CHANNEL_3,
1219 markw
CHANNEL_MUX
999 markw
)
1012 markw
variable channel_sum : unsigned(5 downto 0);
714 markw
BEGIN
999 markw
channel_sum := (OTHERS=>'0');
714 markw
1219 markw
case channel_mux is
when "00" => -- 0
1203 markw
channel_sum := CHANNEL_0;
1219 markw
when "01" => -- 1
1203 markw
channel_sum := CHANNEL_1;
1219 markw
when "10" => -- 2
999 markw
channel_sum := CHANNEL_2;
--when "0000001" => -- 3
when others =>
channel_sum := CHANNEL_3;
734 markw
end case;
999 markw
channel_sum_out <= channel_sum;
714 markw
END PROCESS;

-- shared mixer
1203 markw
--shared_pokey_mixer : entity work.pokey_mixer
-- port map
-- (
-- sum => channel_sum_out,
--
-- saturate => saturate,
--
-- VOLUME_OUT_NEXT => VOLUME_OUT_NEXT
-- );
714 markw
-- mux output
PROCESS(
1203 markw
PROFILE_DATA,
PROFILE_READY,
999 markw
VOLUME_OUT_0_REG,
VOLUME_OUT_1_REG,
VOLUME_OUT_2_REG,
VOLUME_OUT_3_REG,
1219 markw
CHANNEL_MUX
)
714 markw
BEGIN
999 markw
VOLUME_OUT_0_NEXT <= VOLUME_OUT_0_REG;
VOLUME_OUT_1_NEXT <= VOLUME_OUT_1_REG;
VOLUME_OUT_2_NEXT <= VOLUME_OUT_2_REG;
VOLUME_OUT_3_NEXT <= VOLUME_OUT_3_REG;
714 markw
1203 markw
if (profile_ready='1') then
1219 markw
case channel_mux is
when "00" => -- 0
1203 markw
VOLUME_OUT_0_NEXT <= unsigned(PROFILE_DATA);
1219 markw
when "01" => -- 1
1203 markw
VOLUME_OUT_1_NEXT <= unsigned(PROFILE_DATA);
1219 markw
when "10" => -- 2
1203 markw
VOLUME_OUT_2_NEXT <= unsigned(PROFILE_DATA);
when others=> -- 3
VOLUME_OUT_3_NEXT <= unsigned(PROFILE_DATA);
end case;
end if;
714 markw
END PROCESS;

-- output
1149 markw
VOLUME_OUT_0 <= VOLUME_OUT_0_REG;
VOLUME_OUT_1 <= VOLUME_OUT_1_REG;
VOLUME_OUT_2 <= VOLUME_OUT_2_REG;
VOLUME_OUT_3 <= VOLUME_OUT_3_REG;
714 markw
1203 markw
PROFILE_ADDR <= std_logic_vector(CHANNEL_SUM_OUT);
714 markw
END vhdl;