--------------------------------------------------------------------------- -- (c) 2020 mark watson -- 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_UNSIGNED.ALL; use IEEE.STD_LOGIC_MISC.all; LIBRARY work; ENTITY SID_top IS GENERIC ( wave_base: std_logic_vector(16 downto 0) ); PORT ( CLK : in std_logic; -- >1MHz, ideally higher for more accurate filter (as long as timing met) RESET_N : in std_logic; ENABLE : in std_logic; -- Typically ~1MHz ADDR : in std_logic_vector(4 downto 0); READ_ENABLE : in std_logic; WRITE_ENABLE : in std_logic; POT_X : in std_logic; POT_Y : in std_logic; POT_RESET : out std_logic; DI : in std_logic_vector(7 downto 0); DO : out std_logic_vector(7 downto 0); DRIVE_DO : out std_logic; AUDIO : out std_logic_vector(15 downto 0); DEBUG_WV1 : out unsigned(11 downto 0); DEBUG_EV1 : out unsigned(7 downto 0); DEBUG_AM1 : out signed(15 downto 0); sidtype : in std_logic; -- 0=8580 filter, 1=6581 filter EXT : in std_logic_vector(1 downto 0); -- 00=GND,01=digifix,10=ADC EXT_ADC : in unsigned(15 downto 0); rom_addr : out std_logic_vector(16 downto 0); rom_data : in std_logic_vector(31 downto 0); rom_request : out std_logic; rom_ready : in std_logic; FILTER_BP_OUT : out signed(17 downto 8); FILTER_HP_OUT : out signed(17 downto 8); FILTER_F_OUT : out std_logic_vector(12 downto 0); FILTER_F_BP : in std_logic_vector(12 downto 0); FILTER_F_HP : in std_logic_vector(12 downto 0) ); END SID_top; ARCHITECTURE vhdl OF SID_top IS -- frequency (added to 24 bit osc on each tick) signal freq_adj_channel_a_reg : std_logic_vector(15 downto 0); signal freq_adj_channel_a_next : std_logic_vector(15 downto 0); signal freq_adj_channel_b_reg : std_logic_vector(15 downto 0); signal freq_adj_channel_b_next : std_logic_vector(15 downto 0); signal freq_adj_channel_c_reg : std_logic_vector(15 downto 0); signal freq_adj_channel_c_next : std_logic_vector(15 downto 0); -- pulse waveform duty cycle signal pulse_width_channel_a_reg : std_logic_vector(11 downto 0); signal pulse_width_channel_a_next : std_logic_vector(11 downto 0); signal pulse_width_channel_b_reg : std_logic_vector(11 downto 0); signal pulse_width_channel_b_next : std_logic_vector(11 downto 0); signal pulse_width_channel_c_reg : std_logic_vector(11 downto 0); signal pulse_width_channel_c_next : std_logic_vector(11 downto 0); -- waveform signal waveselect_a_reg : std_logic_vector(3 downto 0); signal waveselect_a_next : std_logic_vector(3 downto 0); signal waveselect_b_reg : std_logic_vector(3 downto 0); signal waveselect_b_next : std_logic_vector(3 downto 0); signal waveselect_c_reg : std_logic_vector(3 downto 0); signal waveselect_c_next : std_logic_vector(3 downto 0); --ring mod, sync, gate signal control_a_reg : std_logic_vector(3 downto 0); signal control_a_next : std_logic_vector(3 downto 0); signal control_b_reg : std_logic_vector(3 downto 0); signal control_b_next : std_logic_vector(3 downto 0); signal control_c_reg : std_logic_vector(3 downto 0); signal control_c_next : std_logic_vector(3 downto 0); -- ADSR envelope - attack/decay/sustain/release signal envelope_attack_a_reg : std_logic_vector(3 downto 0); signal envelope_attack_a_next : std_logic_vector(3 downto 0); signal envelope_attack_b_reg : std_logic_vector(3 downto 0); signal envelope_attack_b_next : std_logic_vector(3 downto 0); signal envelope_attack_c_reg : std_logic_vector(3 downto 0); signal envelope_attack_c_next : std_logic_vector(3 downto 0); signal envelope_decay_a_reg : std_logic_vector(3 downto 0); signal envelope_decay_a_next : std_logic_vector(3 downto 0); signal envelope_decay_b_reg : std_logic_vector(3 downto 0); signal envelope_decay_b_next : std_logic_vector(3 downto 0); signal envelope_decay_c_reg : std_logic_vector(3 downto 0); signal envelope_decay_c_next : std_logic_vector(3 downto 0); signal envelope_sustain_a_reg : std_logic_vector(3 downto 0); signal envelope_sustain_a_next : std_logic_vector(3 downto 0); signal envelope_sustain_b_reg : std_logic_vector(3 downto 0); signal envelope_sustain_b_next : std_logic_vector(3 downto 0); signal envelope_sustain_c_reg : std_logic_vector(3 downto 0); signal envelope_sustain_c_next : std_logic_vector(3 downto 0); signal envelope_release_a_reg : std_logic_vector(3 downto 0); signal envelope_release_a_next : std_logic_vector(3 downto 0); signal envelope_release_b_reg : std_logic_vector(3 downto 0); signal envelope_release_b_next : std_logic_vector(3 downto 0); signal envelope_release_c_reg : std_logic_vector(3 downto 0); signal envelope_release_c_next : std_logic_vector(3 downto 0); -- state variable filter params signal statevariable_fcutoff_reg : std_logic_vector(10 downto 0); --30Hz to 12KHz, linear (or rather not, read from rom...) signal statevariable_fcutoff_next : std_logic_vector(10 downto 0); signal statevariable_F_reg : std_logic_vector(12 downto 0); -- F computed from fcutoff -> or read from ram : 0.21 fixed point signal statevariable_F_next : std_logic_vector(12 downto 0); -- see example computation at start of filter.vhdl signal statevariable_f_changed : std_logic; signal statevariable_f_dirty_next : std_logic; signal statevariable_f_dirty_reg : std_logic; signal rom_state_reg : std_logic_vector(2 downto 0); signal rom_state_next : std_logic_vector(2 downto 0); constant rom_state_init : std_logic_vector(2 downto 0) := "000"; constant rom_state_romrequest_statevariable_f : std_logic_vector(2 downto 0) := "001"; constant rom_state_romrequest_wave_a : std_logic_vector(2 downto 0) := "010"; constant rom_state_romrequest_wave_b : std_logic_vector(2 downto 0) := "011"; constant rom_state_romrequest_wave_c : std_logic_vector(2 downto 0) := "100"; constant rom_state_romrequest_statevariable_q : std_logic_vector(2 downto 0) := "101"; signal statevariable_q_changed : std_logic; signal statevariable_q_dirty_next : std_logic; signal statevariable_q_dirty_reg : std_logic; signal statevariable_Q_reg : std_logic_vector(3 downto 0); --resonance signal statevariable_Q_next : std_logic_vector(3 downto 0); signal statevariable_1q_reg : signed(17 downto 0); --resonance signal statevariable_1q_next : signed(17 downto 0); signal rom_addr_mux : std_logic_vector(2 downto 0); signal rom_data_word : std_logic_vector(15 downto 0); signal rom_osc : std_logic_vector(10 downto 0); signal rom_high_word : std_logic; signal rom_wave_3bit : std_logic_vector(2 downto 0); signal rom_wave_2bit : std_logic_vector(1 downto 0); signal wavegen_data_needed : std_logic_vector(2 downto 0); signal wavegen_data_ready : std_logic_vector(2 downto 0); -- which channels are filtered? signal filter_en_reg : std_logic_vector(3 downto 0); signal filter_en_next : std_logic_vector(3 downto 0); -- which filters are we using? signal filter_sel_reg : std_logic_vector(2 downto 0); --hp/bp/lp signal filter_sel_next : std_logic_vector(2 downto 0); -- allow ch3 to be silent (direct audio path), if using it for modulation signal ch3silent_reg : std_logic; signal ch3silent_next : std_logic; -- overall volume signal vol_reg : std_logic_vector(3 downto 0); signal vol_next : std_logic_vector(3 downto 0); -- op regs signal addr_decoded : std_logic_vector(31 downto 0); signal audio_reg: std_logic_vector(15 downto 0); -- osc regs signal osc_a_reg : std_logic_vector(11 downto 0); signal osc_b_reg : std_logic_vector(11 downto 0); signal osc_c_reg : std_logic_vector(11 downto 0); signal osc_a_lfsr_enable : std_logic; signal osc_b_lfsr_enable : std_logic; signal osc_c_lfsr_enable : std_logic; signal sync_a : std_logic; signal sync_b : std_logic; signal sync_c : std_logic; signal osc_a_sync_out : std_logic; signal osc_b_sync_out : std_logic; signal osc_c_sync_out : std_logic; signal osc_a_changing : std_logic; signal osc_b_changing : std_logic; signal osc_c_changing : std_logic; -- wavegen regs signal wave_a_reg : std_logic_vector(11 downto 0); signal wave_b_reg : std_logic_vector(11 downto 0); signal wave_c_reg : std_logic_vector(11 downto 0); -- envelope regs signal envelope_a_reg : std_logic_vector(7 downto 0); signal envelope_b_reg : std_logic_vector(7 downto 0); signal envelope_c_reg : std_logic_vector(7 downto 0); signal delay_lfsr_a : std_logic_vector(14 downto 0); signal delay_lfsr_b : std_logic_vector(14 downto 0); signal delay_lfsr_c : std_logic_vector(14 downto 0); signal tapkey_a : std_logic_vector(3 downto 0); signal tapkey_b : std_logic_vector(3 downto 0); signal tapkey_c : std_logic_vector(3 downto 0); signal tapmatches : std_logic_vector(2 downto 0); -- amplitude modulator signal channel_a_modulated : signed(15 downto 0); signal channel_b_modulated : signed(15 downto 0); signal channel_c_modulated : signed(15 downto 0); signal channel_d : signed(15 downto 0); -- prefilter signal channel_prefilter : signed(15 downto 0); signal channel_directsum : signed(15 downto 0); -- filter signal filter_lp : signed(17 downto 0); -- extra bit due to Jammer causing filter to clip signal filter_bp : signed(17 downto 0); signal filter_hp : signed(17 downto 0); -- paddles signal potx_reg : std_logic_vector(7 downto 0); signal potx_next : std_logic_vector(7 downto 0); signal poty_reg : std_logic_vector(7 downto 0); signal poty_next : std_logic_vector(7 downto 0); signal potcount_reg : std_logic_vector(8 downto 0); signal potcount_next : std_logic_vector(8 downto 0); signal potread_x_reg : std_logic; signal potread_y_reg : std_logic; signal potread_x_next : std_logic; signal potread_y_next : std_logic; -- do internal bus signal do_out_next : std_logic_vector(7 downto 0); signal do_out_reg : std_logic_vector(7 downto 0); signal reset_readcount : std_logic; signal readcount_reg : unsigned(15 downto 0); signal readcount_next : unsigned(15 downto 0); BEGIN process(clk,reset_n) begin if (reset_n='0') then freq_adj_channel_a_reg <= (others=>'0'); freq_adj_channel_b_reg <= (others=>'0'); freq_adj_channel_c_reg <= (others=>'0'); pulse_width_channel_a_reg <= (others=>'0'); pulse_width_channel_b_reg <= (others=>'0'); pulse_width_channel_c_reg <= (others=>'0'); waveselect_a_reg <= (others=>'0'); waveselect_b_reg <= (others=>'0'); waveselect_c_reg <= (others=>'0'); control_a_reg <= (others=>'0'); control_b_reg <= (others=>'0'); control_c_reg <= (others=>'0'); envelope_attack_a_reg <= (others=>'0'); envelope_attack_b_reg <= (others=>'0'); envelope_attack_c_reg <= (others=>'0'); envelope_decay_a_reg <= (others=>'0'); envelope_decay_b_reg <= (others=>'0'); envelope_decay_c_reg <= (others=>'0'); envelope_sustain_a_reg <= (others=>'0'); envelope_sustain_b_reg <= (others=>'0'); envelope_sustain_c_reg <= (others=>'0'); envelope_release_a_reg <= (others=>'0'); envelope_release_b_reg <= (others=>'0'); envelope_release_c_reg <= (others=>'0'); statevariable_fcutoff_reg <= (others=>'0'); statevariable_F_reg <= (others=>'0'); statevariable_Q_reg <= (others=>'0'); statevariable_1q_reg <= (others=>'0'); rom_state_reg <= rom_state_init; filter_en_reg <= (others=>'0'); filter_sel_reg <= (others=>'0'); ch3silent_reg <= '0'; vol_reg <= (others=>'0'); statevariable_f_dirty_reg <= '1'; statevariable_q_dirty_reg <= '1'; potx_reg <= (others=>'0'); poty_reg <= (others=>'0'); potread_x_reg <= '0'; potread_y_reg <= '0'; potcount_reg <= (others=>'0'); do_out_reg <= (others=>'0'); readcount_reg <= (others=>'0'); elsif (clk'event and clk='1') then freq_adj_channel_a_reg <= freq_adj_channel_a_next; freq_adj_channel_b_reg <= freq_adj_channel_b_next; freq_adj_channel_c_reg <= freq_adj_channel_c_next; pulse_width_channel_a_reg <= pulse_width_channel_a_next; pulse_width_channel_b_reg <= pulse_width_channel_b_next; pulse_width_channel_c_reg <= pulse_width_channel_c_next; waveselect_a_reg <= waveselect_a_next; waveselect_b_reg <= waveselect_b_next; waveselect_c_reg <= waveselect_c_next; control_a_reg <= control_a_next; control_b_reg <= control_b_next; control_c_reg <= control_c_next; envelope_attack_a_reg <= envelope_attack_a_next; envelope_attack_b_reg <= envelope_attack_b_next; envelope_attack_c_reg <= envelope_attack_c_next; envelope_decay_a_reg <= envelope_decay_a_next; envelope_decay_b_reg <= envelope_decay_b_next; envelope_decay_c_reg <= envelope_decay_c_next; envelope_sustain_a_reg <= envelope_sustain_a_next; envelope_sustain_b_reg <= envelope_sustain_b_next; envelope_sustain_c_reg <= envelope_sustain_c_next; envelope_release_a_reg <= envelope_release_a_next; envelope_release_b_reg <= envelope_release_b_next; envelope_release_c_reg <= envelope_release_c_next; statevariable_fcutoff_reg <= statevariable_fcutoff_next; statevariable_F_reg <= statevariable_F_next; statevariable_Q_Reg <= statevariable_Q_next; statevariable_1q_reg <= statevariable_1q_next; rom_state_reg <= rom_state_next; filter_en_reg <= filter_en_next; filter_sel_reg <= filter_sel_next; ch3silent_reg <= ch3silent_next; vol_reg <= vol_next; statevariable_f_dirty_reg <= statevariable_f_dirty_next; statevariable_q_dirty_reg <= statevariable_q_dirty_next; potx_reg <= potx_next; poty_reg <= poty_next; potread_x_reg <= potread_x_next; potread_y_reg <= potread_y_next; potcount_reg <= potcount_next; do_out_reg <= do_out_next; readcount_reg <= readcount_next; end if; end process; decode_addr1 : entity work.complete_address_decoder generic map(width=>5) port map (addr_in=>ADDR(4 downto 0), addr_decoded=>addr_decoded); process(addr_decoded,write_enable,di, freq_adj_channel_a_reg, freq_adj_channel_b_reg, freq_adj_channel_c_reg, pulse_width_channel_a_reg, pulse_width_channel_b_reg, pulse_width_channel_c_reg, waveselect_a_reg, waveselect_b_reg, waveselect_c_reg, control_a_reg, control_b_reg, control_c_reg, envelope_attack_a_reg, envelope_attack_b_reg, envelope_attack_c_reg, envelope_decay_a_reg, envelope_decay_b_reg, envelope_decay_c_reg, envelope_sustain_a_reg, envelope_sustain_b_reg, envelope_sustain_c_reg, envelope_release_a_reg, envelope_release_b_reg, envelope_release_c_reg, statevariable_fcutoff_reg, statevariable_Q_Reg, filter_en_reg, filter_sel_reg, ch3silent_reg, vol_reg ) begin freq_adj_channel_a_next <= freq_adj_channel_a_reg; freq_adj_channel_b_next <= freq_adj_channel_b_reg; freq_adj_channel_c_next <= freq_adj_channel_c_reg; pulse_width_channel_a_next <= pulse_width_channel_a_reg; pulse_width_channel_b_next <= pulse_width_channel_b_reg; pulse_width_channel_c_next <= pulse_width_channel_c_reg; waveselect_a_next <= waveselect_a_reg; waveselect_b_next <= waveselect_b_reg; waveselect_c_next <= waveselect_c_reg; control_a_next <= control_a_reg; control_b_next <= control_b_reg; control_c_next <= control_c_reg; envelope_attack_a_next <= envelope_attack_a_reg; envelope_attack_b_next <= envelope_attack_b_reg; envelope_attack_c_next <= envelope_attack_c_reg; envelope_decay_a_next <= envelope_decay_a_reg; envelope_decay_b_next <= envelope_decay_b_reg; envelope_decay_c_next <= envelope_decay_c_reg; envelope_sustain_a_next <= envelope_sustain_a_reg; envelope_sustain_b_next <= envelope_sustain_b_reg; envelope_sustain_c_next <= envelope_sustain_c_reg; envelope_release_a_next <= envelope_release_a_reg; envelope_release_b_next <= envelope_release_b_reg; envelope_release_c_next <= envelope_release_c_reg; statevariable_fcutoff_next <= statevariable_fcutoff_reg; statevariable_Q_next <= statevariable_Q_reg; filter_en_next <= filter_en_reg; filter_sel_next <= filter_sel_reg; ch3silent_next <= ch3silent_reg; vol_next <= vol_reg; statevariable_f_changed <= '0'; statevariable_q_changed <= '0'; if (write_enable='1') then --ch a if (addr_decoded(0)='1') then freq_adj_channel_a_next(7 downto 0) <= di; end if; if (addr_decoded(1)='1') then freq_adj_channel_a_next(15 downto 8) <= di; end if; if (addr_decoded(2)='1') then pulse_width_channel_a_next(7 downto 0) <= di; end if; if (addr_decoded(3)='1') then pulse_width_channel_a_next(11 downto 8) <= di(3 downto 0); end if; if (addr_decoded(4)='1') then control_a_next <= di(3 downto 0); waveselect_a_next <= di(7 downto 4); end if; if (addr_decoded(5)='1') then envelope_attack_a_next <= di(7 downto 4); envelope_decay_a_next <= di(3 downto 0); end if; if (addr_decoded(6)='1') then envelope_sustain_a_next <= di(7 downto 4); envelope_release_a_next <= di(3 downto 0); end if; --ch b if (addr_decoded(7)='1') then freq_adj_channel_b_next(7 downto 0) <= di; end if; if (addr_decoded(8)='1') then freq_adj_channel_b_next(15 downto 8) <= di; end if; if (addr_decoded(9)='1') then pulse_width_channel_b_next(7 downto 0) <= di; end if; if (addr_decoded(10)='1') then pulse_width_channel_b_next(11 downto 8) <= di(3 downto 0); end if; if (addr_decoded(11)='1') then control_b_next <= di(3 downto 0); waveselect_b_next <= di(7 downto 4); end if; if (addr_decoded(12)='1') then envelope_attack_b_next <= di(7 downto 4); envelope_decay_b_next <= di(3 downto 0); end if; if (addr_decoded(13)='1') then envelope_sustain_b_next <= di(7 downto 4); envelope_release_b_next <= di(3 downto 0); end if; --ch c if (addr_decoded(14)='1') then freq_adj_channel_c_next(7 downto 0) <= di; end if; if (addr_decoded(15)='1') then freq_adj_channel_c_next(15 downto 8) <= di; end if; if (addr_decoded(16)='1') then pulse_width_channel_c_next(7 downto 0) <= di; end if; if (addr_decoded(17)='1') then pulse_width_channel_c_next(11 downto 8) <= di(3 downto 0); end if; if (addr_decoded(18)='1') then control_c_next <= di(3 downto 0); waveselect_c_next <= di(7 downto 4); end if; if (addr_decoded(19)='1') then envelope_attack_c_next <= di(7 downto 4); envelope_decay_c_next <= di(3 downto 0); end if; if (addr_decoded(20)='1') then envelope_sustain_c_next <= di(7 downto 4); envelope_release_c_next <= di(3 downto 0); end if; --filter if (addr_decoded(21)='1') then statevariable_fcutoff_next(2 downto 0) <= di(2 downto 0); statevariable_f_changed <= '1'; end if; if (addr_decoded(22)='1') then statevariable_fcutoff_next(10 downto 3) <= di; statevariable_f_changed <= '1'; end if; if (addr_decoded(23)='1') then statevariable_Q_next <= di(7 downto 4); statevariable_q_changed <= '1'; filter_en_next <= di(3 downto 0); end if; if (addr_decoded(24)='1') then ch3silent_next <= di(7); filter_sel_next <= di(6 downto 4); vol_next <= di(3 downto 0); end if; end if; end process; process(addr,addr_decoded, do_out_reg,do_out_next, read_enable, wave_c_reg, envelope_c_reg, potx_reg, poty_reg, readcount_reg ) begin drive_do <= '1'; --ADDR(4) and ADDR(3) and or_reduce(ADDR(2 downto 0)); do_out_next <= do_out_reg; reset_readcount <= '0'; if (read_enable='1') then if (addr_decoded(25)='1') then do_out_next <= potx_reg; reset_readcount <= '1'; end if; if (addr_decoded(26)='1') then do_out_next <= poty_reg; reset_readcount <= '1'; end if; if (addr_decoded(27)='1') then do_out_next <= wave_c_reg(11 downto 4); reset_readcount <= '1'; end if; if (addr_decoded(28)='1') then do_out_next <= envelope_c_reg; reset_readcount <= '1'; end if; else if (or_reduce(std_logic_vector(readcount_reg))='0') then do_out_next <= (others=>'0'); end if; end if; do <= do_out_next; end process; process(readcount_reg,enable,reset_readcount,sidtype) begin readcount_next <= readcount_reg; if (reset_readcount='1') then if (sidtype ='1') then --6581 readcount_next <=to_unsigned(8000,16); else readcount_next <=to_unsigned(65535,16); end if; else if (enable='1') then readcount_next <=readcount_reg-1; end if; end if; end process; -- osc a osc_a : entity work.SID_oscillator PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, TEST => control_a_reg(3), LFSR_ENABLE => osc_a_lfsr_enable, CHANGING => osc_a_changing, BITS_OUT => osc_a_reg, SYNC_IN => sync_a, SYNC_OUT => osc_a_sync_out, ADJ => freq_adj_channel_a_reg ); sync_a <= control_a_reg(1) and osc_c_sync_out; -- osc b osc_b : entity work.SID_oscillator PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, TEST => control_b_reg(3), LFSR_ENABLE => osc_b_lfsr_enable, CHANGING => osc_b_changing, BITS_OUT => osc_b_reg, SYNC_IN => sync_b, SYNC_OUT => osc_b_sync_out, ADJ => freq_adj_channel_b_reg ); sync_b <= control_b_reg(1) and osc_a_sync_out; -- osc c osc_c : entity work.SID_oscillator PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, TEST => control_c_reg(3), LFSR_ENABLE => osc_c_lfsr_enable, CHANGING => osc_c_changing, BITS_OUT => osc_c_reg, SYNC_IN => sync_c, SYNC_OUT => osc_c_sync_out, ADJ => freq_adj_channel_c_reg ); sync_c <= control_c_reg(1) and osc_b_sync_out; --wave generator wavegen_a : entity work.SID_wavegen PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, CHANGING => osc_a_changing, DELAYSAWTOOTH => not(sidtype), RINGMOD => control_a_reg(2), RINGMOD_OSC_MSB => osc_c_reg(11), TEST => control_a_next(3), LFSR_ENABLE => (osc_a_lfsr_enable or (control_a_reg(3) xor control_a_next(3)) or (control_a_reg(3) and enable)), OSC_IN => osc_a_reg, PULSE_WIDTH_IN => pulse_width_channel_a_reg, WAVESELECT_IN => waveselect_a_reg, WAVE_DATA_NEEDED => wavegen_data_needed(0), WAVE_DATA_READY => wavegen_data_ready(0), WAVE_DATA => rom_data_word(11 downto 0), WAVE_OUT => wave_a_reg ); wavegen_b : entity work.SID_wavegen PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, CHANGING => osc_b_changing, DELAYSAWTOOTH => not(sidtype), RINGMOD => control_b_reg(2), RINGMOD_OSC_MSB => osc_a_reg(11), TEST => control_b_next(3), LFSR_ENABLE => (osc_b_lfsr_enable or (control_b_reg(3) xor control_b_next(3)) or (control_b_reg(3) and enable)), OSC_IN => osc_b_reg, PULSE_WIDTH_IN => pulse_width_channel_b_reg, WAVESELECT_IN => waveselect_b_reg, WAVE_DATA_NEEDED => wavegen_data_needed(1), WAVE_DATA_READY => wavegen_data_ready(1), WAVE_DATA => rom_data_word(11 downto 0), WAVE_OUT => wave_b_reg ); wavegen_c : entity work.SID_wavegen PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, CHANGING => osc_c_changing, DELAYSAWTOOTH => not(sidtype), RINGMOD => control_c_reg(2), RINGMOD_OSC_MSB => osc_b_reg(11), TEST => control_c_next(3), LFSR_ENABLE => (osc_c_lfsr_enable or (control_c_reg(3) xor control_c_next(3)) or (control_c_reg(3) and enable)), OSC_IN => osc_c_reg, PULSE_WIDTH_IN => pulse_width_channel_c_reg, WAVESELECT_IN => waveselect_c_reg, WAVE_DATA_NEEDED => wavegen_data_needed(2), WAVE_DATA_READY => wavegen_data_ready(2), WAVE_DATA => rom_data_word(11 downto 0), WAVE_OUT => wave_c_reg ); -- envelope envelope_a : entity work.SID_envelope PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, TAPMATCH => tapmatches(0), ATTACK => envelope_attack_a_reg, SUSTAIN => envelope_sustain_a_reg, DECAY => envelope_decay_a_reg, RELEASE_IN => envelope_release_a_reg, GATE => control_a_reg(0), ENVELOPE => envelope_a_reg, DELAY_LFSR => delay_lfsr_a, TAPKEY => tapkey_a ); envelope_b : entity work.SID_envelope PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, TAPMATCH => tapmatches(1), ATTACK => envelope_attack_b_reg, SUSTAIN => envelope_sustain_b_reg, DECAY => envelope_decay_b_reg, RELEASE_IN => envelope_release_b_reg, GATE => control_b_reg(0), ENVELOPE => envelope_b_reg, DELAY_LFSR => delay_lfsr_b, TAPKEY => tapkey_b ); envelope_c : entity work.SID_envelope PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, TAPMATCH => tapmatches(2), ATTACK => envelope_attack_c_reg, SUSTAIN => envelope_sustain_c_reg, DECAY => envelope_decay_c_reg, RELEASE_IN => envelope_release_c_reg, GATE => control_c_reg(0), ENVELOPE => envelope_c_reg, DELAY_LFSR => delay_lfsr_c, TAPKEY => tapkey_c ); envelope_tapmatcher : entity work.SID_envelope_tapmatch PORT MAP ( CLK => clk, RESET_N => reset_n, DELAY_LFSR1 => delay_lfsr_a, DELAY_LFSR2 => delay_lfsr_b, DELAY_LFSR3 => delay_lfsr_c, TAPKEY1 => tapkey_a, TAPKEY2 => tapkey_b, TAPKEY3 => tapkey_c, TAPMATCHES => tapmatches ); -- volume vol_a : entity work.SID_amplitudeModulator PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, WAVE => wave_a_reg, ENVELOPE => envelope_a_reg, MODULATED => channel_a_modulated ); vol_b : entity work.SID_amplitudeModulator PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, WAVE => wave_b_reg, ENVELOPE => envelope_b_reg, MODULATED => channel_b_modulated ); vol_c : entity work.SID_amplitudeModulator PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, WAVE => wave_c_reg, ENVELOPE => envelope_c_reg, MODULATED => channel_c_modulated ); prefilter: entity work.SID_preFilterSum PORT MAP ( CLK => clk, RESET_N => reset_n, ENABLE => enable, BIAS_CHANNEL => sidtype, CHANNEL_A => channel_a_modulated, CHANNEL_B => channel_b_modulated, CHANNEL_C => channel_c_modulated, CHANNEL_C_CUTDIRECT => ch3silent_reg, CHANNEL_D => channel_d, FILTER_EN => filter_en_reg, PREFILTER_OUT => channel_prefilter, DIRECT_OUT => channel_directsum ); process(statevariable_F_reg, statevariable_1q_reg, rom_state_reg, statevariable_f_changed, statevariable_f_dirty_reg, statevariable_q_changed, statevariable_q_dirty_reg, rom_data, rom_data_word, rom_high_word, rom_ready, wavegen_data_needed) begin statevariable_f_dirty_next <= statevariable_f_dirty_reg or statevariable_f_changed; statevariable_F_next <= statevariable_F_reg; statevariable_q_dirty_next <= statevariable_q_dirty_reg or statevariable_q_changed; statevariable_1q_next <= statevariable_1q_reg; rom_state_next <= rom_state_reg; rom_request <= '0'; rom_addr_mux <= "000"; wavegen_data_ready <= (others=>'0'); if (rom_high_word='0') then rom_data_word <= rom_data(15 downto 0); else rom_data_word <= rom_data(31 downto 16); end if; case rom_state_reg is when rom_state_init => if (statevariable_f_dirty_reg='1') then rom_state_next <= rom_state_romrequest_statevariable_f; end if; if (statevariable_q_dirty_reg='1') then rom_state_next <= rom_state_romrequest_statevariable_q; end if; if (wavegen_data_needed(0)='1') then rom_state_next <= rom_state_romrequest_wave_a; end if; if (wavegen_data_needed(1)='1') then rom_state_next <= rom_state_romrequest_wave_b; end if; if (wavegen_data_needed(2)='1') then rom_state_next <= rom_state_romrequest_wave_c; end if; when rom_state_romrequest_statevariable_f => rom_request <= '1'; rom_addr_mux <= "000"; if (rom_ready = '1') then statevariable_f_dirty_next <= '0'; statevariable_F_next <= rom_data_word(12 downto 0); rom_state_next <= rom_state_init; end if; when rom_state_romrequest_wave_a => rom_request <= '1'; rom_addr_mux <= "001"; wavegen_data_ready(0) <= rom_ready; if (rom_ready = '1') then rom_state_next <= rom_state_init; end if; when rom_state_romrequest_wave_b => rom_request <= '1'; rom_addr_mux <= "010"; wavegen_data_ready(1) <= rom_ready; if (rom_ready = '1') then rom_state_next <= rom_state_init; end if; when rom_state_romrequest_wave_c => rom_request <= '1'; rom_addr_mux <= "011"; wavegen_data_ready(2) <= rom_ready; if (rom_ready = '1') then rom_state_next <= rom_state_init; end if; when rom_state_romrequest_statevariable_q => rom_request <= '1'; rom_addr_mux <= "100"; if (rom_ready = '1') then statevariable_q_dirty_next <= '0'; statevariable_1q_next <= signed(rom_data(17 downto 0)); rom_state_next <= rom_state_init; end if; when others => rom_state_next <= rom_state_init; end case; end process; process(rom_addr_mux, sidtype, statevariable_fcutoff_reg, statevariable_q_reg, osc_a_reg,osc_b_reg,osc_c_reg, waveselect_a_reg,waveselect_b_reg,waveselect_c_reg, rom_wave_2bit,rom_wave_3bit, rom_osc,rom_high_word) variable rom_wave_addr: std_logic_vector(16 downto 0); variable sidtype2: std_logic_vector(0 downto 0); begin rom_addr <= (others=>'0'); rom_high_word <= '0'; rom_wave_2bit <= (others=>'0'); rom_wave_3bit <= (others=>'0'); rom_osc <= (others=>'0'); sidtype2(0) := sidtype; case rom_wave_3bit is when "011" => -- ST rom_wave_2bit <= "00"; when "101" => --P T rom_wave_2bit <= "01"; when "110" => --PS rom_wave_2bit <= "10"; when "111" => --PST rom_wave_2bit <= "11"; when others => end case; rom_wave_addr := std_logic_vector(unsigned(wave_base)+resize(unsigned(sidtype2(0 downto 0)&rom_wave_2bit&rom_osc),17)); --1:2:11 case rom_addr_mux is when "000" => rom_addr <= "00000"&std_logic_vector(unsigned('0'&sidtype2(0 downto 0))+1)&statevariable_fcutoff_reg(10 downto 1); rom_high_word <= statevariable_fcutoff_reg(0); when "001" => rom_osc <= osc_a_reg(11 downto 1); rom_wave_3bit <= waveselect_a_reg(2 downto 0); rom_addr <= rom_wave_addr; rom_high_word <= osc_a_reg(0); when "010" => rom_osc <= osc_b_reg(11 downto 1); rom_wave_3bit <= waveselect_b_reg(2 downto 0); rom_addr <= rom_wave_addr; rom_high_word <= osc_b_reg(0); when "011" => rom_osc <= osc_c_reg(11 downto 1); rom_wave_3bit <= waveselect_c_reg(2 downto 0); rom_addr <= rom_wave_addr; rom_high_word <= osc_c_reg(0); when "100" => rom_addr <= "000000010000"&sidtype2(0 downto 0)&statevariable_q_reg; when others => end case; end process; variable_state_filter : entity work.SID_filter PORT MAP ( CLK => clk, RESET_N => reset_n, INPUT => channel_prefilter, SIDTYPE => sidtype, LOWPASS => filter_lp, BANDPASS => filter_bp, HIGHPASS => filter_hp, --CUTOFF_FREQUENCY => statevariable_fcutoff_reg, F_BP => unsigned(filter_f_bp), F_HP => unsigned(filter_f_hp), Q => statevariable_1q_reg ); postfilter: entity work.SID_postFilterSum PORT MAP ( CLK => clk, RESET_N => reset_n, DIRECT => channel_directsum, FILTER_LP => filter_lp, FILTER_BP => filter_bp, FILTER_HP => filter_hp, FILTER_SEL => filter_sel_reg, VOLUME => vol_reg, CHANNEL_OUT => audio_reg ); -- paddles process (potx_reg,poty_reg,pot_x,pot_y,potcount_reg,enable,potread_x_reg,potread_y_reg) begin potx_next <= potx_reg; poty_next <= poty_reg; potread_x_next <= potread_x_reg and not(potcount_reg(8)); potread_y_next <= potread_y_reg and not(potcount_reg(8)); potcount_next <= potcount_reg; pot_reset <= potcount_reg(8); if (enable='1') then potcount_next <= std_logic_vector(unsigned(potcount_reg)+1); if ((pot_x='1' or potcount_reg="011111111") and potread_x_reg='0') then potx_next <= potcount_reg(7 downto 0); potread_x_next <= '1'; end if; if ((pot_y='1' or potcount_reg="011111111") and potread_y_reg='0') then poty_next <= potcount_reg(7 downto 0); potread_y_next <= '1'; end if; end if; end process; -- ext audio process(ext_adc,ext) begin --EXT : in std_logic_vector(1 downto 0); -- 00=GND,01=digifix,10=ADC --EXT_ADC : in unsigned(7 downto 0); channel_d <= to_signed(0,16); case EXT is when "01" => channel_d <= signed("000"&ext&"00000000000"); when "10" => channel_d <= signed(not(ext_adc(15))&ext_adc(14 downto 0)); when others=> end case; end process; -------------------------------- -- TODO -- 1) DONE:check above works! -- 2) DONE: wave combinations need to read flash -- 3) DONE:envelope/gate -- 4) DONE:amplitude modulation -- 5) DONE:filter on/off -- 5) DONE:filter (state variable as per info found) -- 6) DONE:volume -- 7) DONE: read registers: pot, osc3 etc -- 8) 6581! buggy_variable_state_filter : entity work.SID_filter -- ref: https://bel.fi/alankila/c64-sw/index-cpp.html -- see distortion section -------------------------------- --outputs AUDIO <= audio_reg; DEBUG_EV1 <= unsigned(envelope_a_reg); DEBUG_WV1 <= unsigned(wave_a_reg); DEBUG_AM1 <= channel_a_modulated; FILTER_BP_OUT <= filter_bp(17 downto 8); FILTER_HP_OUT <= filter_hp(17 downto 8); FILTER_F_OUT <= statevariable_F_reg; end vhdl;