Revision 1359
Added by markw over 2 years ago
| atari_chips/pokeyv2/pokey/pokey.vhdl | ||
|---|---|---|
| 
     	signal enable_64 : std_logic;
 
   | 
||
| 
     	signal enable_15 : std_logic;
 
   | 
||
| 
     | 
||
| 
     	signal audf0_delayed_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal audf1_delayed_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal audf2_delayed_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal audf3_delayed_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     | 
||
| 
     	signal audctl_delayed_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     | 
||
| 
     	signal audf0_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal audc0_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal audf1_reg : std_logic_vector(7 downto 0);
 
   | 
||
| ... | ... | |
| 
     	signal serial_ip_overrun_next : std_logic;
 
   | 
||
| 
     	signal serial_ip_overrun_reg : std_logic;
 
   | 
||
| 
     	signal serial_op_needed_interrupt : std_logic;
 
   | 
||
| 
     	signal serial_op_needed_interrupt_delayed_next : std_logic_vector(1 downto 0);
 
   | 
||
| 
     	signal serial_op_needed_interrupt_delayed_reg : std_logic_vector(1 downto 0);
 
   | 
||
| 
     | 
||
| 
     	signal skctl_next : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal skctl_reg : std_logic_vector(7 downto 0);
 
   | 
||
| ... | ... | |
| 
     			noise_4_reg <= (others=>'0');
 
   | 
||
| 
     			noise_5_reg <= (others=>'0');
 
   | 
||
| 
     			noise_large_reg <= (others=>'0');
 
   | 
||
| 
     | 
||
| 
     			serial_op_needed_interrupt_delayed_reg <= (others=>'0');
 
   | 
||
| 
     | 
||
| 
     		elsif (clk'event and clk='1') then			
 
   | 
||
| 
     			audf0_reg <= audf0_next;
 
   | 
||
| ... | ... | |
| 
     			noise_4_reg <= noise_4_next;
 
   | 
||
| 
     			noise_5_reg <= noise_5_next;
 
   | 
||
| 
     			noise_large_reg <= noise_large_next;
 
   | 
||
| 
     | 
||
| 
     			serial_op_needed_interrupt_delayed_reg <= serial_op_needed_interrupt_delayed_next;
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     	end process;
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     		port map (addr_in=>addr, addr_decoded=>addr_decoded);
 
   | 
||
| 
     | 
||
| 
     	-- clock selection
 
   | 
||
| 
     	process(enable_64,enable_15,enable_179,audctl_reg,audf0_pulse,audf2_pulse)
 
   | 
||
| 
     	process(enable_64,enable_15,enable_179,audctl_delayed_reg,audf0_pulse,audf2_pulse)
 
   | 
||
| 
     	begin
 
   | 
||
| 
     		audf0_enable <= enable_64;
 
   | 
||
| 
     		audf1_enable <= enable_64;
 
   | 
||
| 
     		audf2_enable <= enable_64;
 
   | 
||
| 
     		audf3_enable <= enable_64;		
 
   | 
||
| 
     | 
||
| 
     		if (audctl_reg(0) = '1') then
 
   | 
||
| 
     		if (audctl_delayed_reg(0) = '1') then
 
   | 
||
| 
     			audf0_enable <= enable_15;
 
   | 
||
| 
     			audf1_enable <= enable_15;
 
   | 
||
| 
     			audf2_enable <= enable_15;
 
   | 
||
| 
     			audf3_enable <= enable_15;
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| 
     		if (audctl_reg(6) = '1') then
 
   | 
||
| 
     		if (audctl_delayed_reg(6) = '1') then
 
   | 
||
| 
     			audf0_enable <= enable_179;
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| 
     		if (audctl_reg(5) = '1') then
 
   | 
||
| 
     		if (audctl_delayed_reg(5) = '1') then
 
   | 
||
| 
     			audf2_enable <= enable_179;
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| 
     		if(audctl_reg(4) = '1') then
 
   | 
||
| 
     		if(audctl_delayed_reg(4) = '1') then
 
   | 
||
| 
     			audf1_enable <= audf0_pulse;
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| 
     		if(audctl_reg(3) = '1') then
 
   | 
||
| 
     		if(audctl_delayed_reg(3) = '1') then
 
   | 
||
| 
     			audf3_enable <= audf2_pulse;
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     	end process;
 
   | 
||
| 
     | 
||
| 
     	audf0_delay : entity work.wide_delay_line
 
   | 
||
| 
     		generic map (COUNT=>1, WIDTH=>8)
 
   | 
||
| 
     		port map(clk=>clk,sync_reset=>'0',data_in=>audf0_reg(7 downto 0),enable=>enable_179,reset_n=>reset_n,data_out=>audf0_delayed_reg(7 downto 0));	
 
   | 
||
| 
     	audf1_delay : entity work.wide_delay_line
 
   | 
||
| 
     		generic map (COUNT=>1, WIDTH=>8)
 
   | 
||
| 
     		port map(clk=>clk,sync_reset=>'0',data_in=>audf1_reg(7 downto 0),enable=>enable_179,reset_n=>reset_n,data_out=>audf1_delayed_reg(7 downto 0));	
 
   | 
||
| 
     	audf2_delay : entity work.wide_delay_line
 
   | 
||
| 
     		generic map (COUNT=>1, WIDTH=>8)
 
   | 
||
| 
     		port map(clk=>clk,sync_reset=>'0',data_in=>audf2_reg(7 downto 0),enable=>enable_179,reset_n=>reset_n,data_out=>audf2_delayed_reg(7 downto 0));	
 
   | 
||
| 
     	audf3_delay : entity work.wide_delay_line
 
   | 
||
| 
     		generic map (COUNT=>1, WIDTH=>8)
 
   | 
||
| 
     		port map(clk=>clk,sync_reset=>'0',data_in=>audf3_reg(7 downto 0),enable=>enable_179,reset_n=>reset_n,data_out=>audf3_delayed_reg(7 downto 0));	
 
   | 
||
| 
     	audctl_delay : entity work.wide_delay_line
 
   | 
||
| 
     		generic map (COUNT=>1, WIDTH=>8)
 
   | 
||
| 
     		port map(clk=>clk,sync_reset=>'0',data_in=>audctl_reg(7 downto 0),enable=>enable_179,reset_n=>reset_n,data_out=>audctl_delayed_reg(7 downto 0));	
 
   | 
||
| 
     | 
||
| 
     	-- Instantiate timers
 
   | 
||
| 
     	timer0 : pokey_countdown_timer
 
   | 
||
| 
     		generic map (UNDERFLOW_DELAY=>3)
 
   | 
||
| 
     		port map(clk=>clk,enable=>audf0_enable,enable_underflow=>enable_179,reset_n=>reset_n,wr_en=>audf0_reload,data_in=>audf0_next,DATA_OUT=>audf0_pulse_raw);
 
   | 
||
| 
     		port map(clk=>clk,enable=>audf0_enable,enable_underflow=>enable_179,reset_n=>reset_n,wr_en=>audf0_reload,data_in=>audf0_delayed_reg,DATA_OUT=>audf0_pulse_raw);
 
   | 
||
| 
     	timer1 : pokey_countdown_timer
 
   | 
||
| 
     		generic map (UNDERFLOW_DELAY=>3)
 
   | 
||
| 
     		port map(clk=>clk,enable=>audf1_enable,enable_underflow=>enable_179,reset_n=>reset_n,wr_en=>audf1_reload,data_in=>audf1_next,DATA_OUT=>audf1_pulse_raw);
 
   | 
||
| 
     		port map(clk=>clk,enable=>audf1_enable,enable_underflow=>enable_179,reset_n=>reset_n,wr_en=>audf1_reload,data_in=>audf1_delayed_reg,DATA_OUT=>audf1_pulse_raw);
 
   | 
||
| 
     	timer2 : pokey_countdown_timer
 
   | 
||
| 
     		generic map (UNDERFLOW_DELAY=>3)
 
   | 
||
| 
     		port map(clk=>clk,enable=>audf2_enable,enable_underflow=>enable_179,reset_n=>reset_n,wr_en=>audf2_reload,data_in=>audf2_next,DATA_OUT=>audf2_pulse_raw);
 
   | 
||
| 
     		port map(clk=>clk,enable=>audf2_enable,enable_underflow=>enable_179,reset_n=>reset_n,wr_en=>audf2_reload,data_in=>audf2_delayed_reg,DATA_OUT=>audf2_pulse_raw);
 
   | 
||
| 
     	timer3 : pokey_countdown_timer
 
   | 
||
| 
     		generic map (UNDERFLOW_DELAY=>3)
 
   | 
||
| 
     		port map(clk=>clk,enable=>audf3_enable,enable_underflow=>enable_179,reset_n=>reset_n,wr_en=>audf3_reload,data_in=>audf3_next,DATA_OUT=>audf3_pulse_raw);		
 
   | 
||
| 
     		port map(clk=>clk,enable=>audf3_enable,enable_underflow=>enable_179,reset_n=>reset_n,wr_en=>audf3_reload,data_in=>audf3_delayed_reg,DATA_OUT=>audf3_pulse_raw);		
 
   | 
||
| 
     | 
||
| 
     	-- Timer reloading
 
   | 
||
| 
     	process (audctl_reg, audf0_pulse_raw, audf1_pulse_raw, audf2_pulse_raw, audf3_pulse_raw, stimer_write_delayed, async_serial_reset, twotone_reset_delayed)
 
   | 
||
| 
     	process (audctl_delayed_reg, audf0_pulse_raw, audf1_pulse_raw, audf2_pulse_raw, audf3_pulse_raw, stimer_write_delayed, async_serial_reset, twotone_reset_delayed)
 
   | 
||
| 
     	begin
 
   | 
||
| 
     		audf0_reload <= ((not(audctl_reg(4)) and audf0_pulse_raw)) or (audctl_reg(4) and audf1_pulse_raw) or stimer_write_delayed or twotone_reset_delayed;
 
   | 
||
| 
     		audf0_reload <= ((not(audctl_delayed_reg(4)) and audf0_pulse_raw)) or (audctl_delayed_reg(4) and audf1_pulse_raw) or stimer_write_delayed or twotone_reset_delayed;
 
   | 
||
| 
     		audf1_reload <= audf1_pulse_raw or stimer_write_delayed or twotone_reset_delayed;
 
   | 
||
| 
     		audf2_reload <= ((not(audctl_reg(3)) and audf2_pulse_raw)) or (audctl_reg(3) and audf3_pulse_raw) or stimer_write_delayed or async_serial_reset;
 
   | 
||
| 
     		audf2_reload <= ((not(audctl_delayed_reg(3)) and audf2_pulse_raw)) or (audctl_delayed_reg(3) and audf3_pulse_raw) or stimer_write_delayed or async_serial_reset;
 
   | 
||
| 
     		audf3_reload <= audf3_pulse_raw or stimer_write_delayed or async_serial_reset;
 
   | 
||
| 
     	end process;
 
   | 
||
| 
     | 
||
| 
     	audf0_pulse <= audf0_pulse_raw and not(twotone_reset_delayed);
 
   | 
||
| 
     	audf1_pulse <= audf1_pulse_raw and not(twotone_reset_delayed);
 
   | 
||
| 
     	audf2_pulse <= audf2_pulse_raw and not(async_serial_reset);
 
   | 
||
| 
     	audf3_pulse <= audf3_pulse_raw and not(async_serial_reset);
 
   | 
||
| 
     	audf0_pulse <= audf0_pulse_raw and not(twotone_reset_delayed) and not(stimer_write_delayed);
 
   | 
||
| 
     	audf1_pulse <= audf1_pulse_raw and not(twotone_reset_delayed) and not(stimer_write_delayed);
 
   | 
||
| 
     	audf2_pulse <= audf2_pulse_raw and not(async_serial_reset) and not(stimer_write_delayed);
 
   | 
||
| 
     	audf3_pulse <= audf3_pulse_raw and not(async_serial_reset) and not(stimer_write_delayed);
 
   | 
||
| 
     | 
||
| 
     	twotone_del : latch_delay_line
 
   | 
||
| 
     		generic map (count=>2)
 
   | 
||
| ... | ... | |
| 
     	end process;
 
   | 
||
| 
     | 
||
| 
     	-- Fire interrupts
 
   | 
||
| 
     	process (irqen_reg, irqst_reg, audf0_pulse, audf1_pulse, audf3_pulse, other_key_irq, serial_ip_ready_interrupt, serout_active_reg, serial_op_needed_interrupt, break_irq)
 
   | 
||
| 
     	process (irqen_reg, irqst_reg, audf0_pulse, audf1_pulse, audf3_pulse, other_key_irq, serial_ip_ready_interrupt, serout_active_reg, serial_op_needed_interrupt, serial_op_needed_interrupt_delayed_reg, break_irq, enable_179)
 
   | 
||
| 
     	begin
 
   | 
||
| 
     		serial_op_needed_interrupt_delayed_next <= serial_op_needed_interrupt_delayed_reg;
 
   | 
||
| 
     		if (enable_179='1') then
 
   | 
||
| 
     			serial_op_needed_interrupt_delayed_next(1)<=serial_op_needed_interrupt_delayed_reg(0);
 
   | 
||
| 
     			serial_op_needed_interrupt_delayed_next(0)<='0';
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     		if (serial_op_needed_interrupt ='1') then
 
   | 
||
| 
     			serial_op_needed_interrupt_delayed_next(0)<='1';
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| 
     		-- clear interrupts
 
   | 
||
| 
     		irqst_next <= irqst_reg or not(irqen_reg);
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     | 
||
| 
     		irqst_next(3) <= serout_active_reg;
 
   | 
||
| 
     | 
||
| 
     		if (serial_op_needed_interrupt = '1') then
 
   | 
||
| 
     		if (serial_op_needed_interrupt_delayed_reg(1) = '1') then
 
   | 
||
| 
     			irqst_next(4) <= not(irqen_reg(4));
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     	chan3_output_next <= audf3_pulse_noise;
 
   | 
||
| 
     | 
||
| 
     	-- High pass filters
 
   | 
||
| 
     	process(audctl_reg,audf2_pulse,audf3_pulse,chan0_output_reg, chan1_output_reg, chan2_output_reg, chan3_output_reg, highpass0_reg, highpass1_reg)
 
   | 
||
| 
     	process(audctl_delayed_reg,audf2_pulse,audf3_pulse,chan0_output_reg, chan1_output_reg, chan2_output_reg, chan3_output_reg, highpass0_reg, highpass1_reg)
 
   | 
||
| 
     	begin
 
   | 
||
| 
     		highpass0_next <= highpass0_reg;
 
   | 
||
| 
     		highpass1_next <= highpass1_reg;
 
   | 
||
| 
     | 
||
| 
     		if (audctl_reg(2) = '1') then
 
   | 
||
| 
     		if (audctl_delayed_reg(2) = '1') then
 
   | 
||
| 
     			if (audf2_pulse = '1') then
 
   | 
||
| 
     				highpass0_next <= chan0_output_reg;
 
   | 
||
| 
     			end if;
 
   | 
||
| ... | ... | |
| 
     			highpass0_next <= '1';
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| 
     		if (audctl_reg(1) = '1') then
 
   | 
||
| 
     		if (audctl_delayed_reg(1) = '1') then
 
   | 
||
| 
     			if (audf3_pulse = '1') then
 
   | 
||
| 
     				highpass1_next <= chan1_output_reg;
 
   | 
||
| 
     			end if;
 
   | 
||
| ... | ... | |
| 
     | 
||
| 
     	-- resetcount 6/33
 
   | 
||
| 
     	enable_64_div : syncreset_enable_divider
 
   | 
||
| 
     		generic map (COUNT=>28,RESETCOUNT=>6) -- 28-22
 
   | 
||
| 
     		generic map (COUNT=>28,RESETCOUNT=>7) -- 28-22
 
   | 
||
| 
     		port map(clk=>clk,syncreset=>initmode,reset_n=>reset_n,enable_in=>enable_179,enable_out=>enable_64);
 
   | 
||
| 
     | 
||
| 
     	enable_15_div : syncreset_enable_divider
 
   | 
||
| 
     		generic map (COUNT=>114,RESETCOUNT=>33) -- 114-81
 
   | 
||
| 
     		generic map (COUNT=>114,RESETCOUNT=>34) -- 114-81
 
   | 
||
| 
     		port map(clk=>clk,syncreset=>initmode,reset_n=>reset_n,enable_in=>enable_179,enable_out=>enable_15);
 
   | 
||
| 
     | 
||
| 
     	-- Instantiate pokey noise circuits (lfsr)
 
   | 
||
| 
     	initmode <= skctl_next(1) nor skctl_next(0);
 
   | 
||
| 
     	poly_17_19_lfsr : pokey_poly_17_9
 
   | 
||
| 
     		port map(clk=>clk,reset_n=>reset_n,init=>initmode,enable=>enable_179,select_9_17=>audctl_reg(7),bit_out=>noise_large,rand_out=>rand_out);
 
   | 
||
| 
     		port map(clk=>clk,reset_n=>reset_n,init=>initmode,enable=>enable_179,select_9_17=>audctl_delayed_reg(7),bit_out=>noise_large,rand_out=>rand_out);
 
   | 
||
| 
     | 
||
| 
     	poly_5_lfsr : pokey_poly_5
 
   | 
||
| 
     		port map(clk=>clk,reset_n=>reset_n,init=>initmode,enable=>enable_179,bit_out=>noise_5);
 
   | 
||
| ... | ... | |
| 
     | 
||
| 
     	-- serial clocks
 
   | 
||
| 
     	process(sio_clockin_in1_reg,skctl_reg,clock_reg,clock_sync_reg,audf1_pulse,audf2_pulse,audf3_pulse,enable_179)
 
   | 
||
| 
     		variable clk_edge : std_logic;
 
   | 
||
| 
     	begin
 
   | 
||
| 
     		clock_next <= clock_reg;
 
   | 
||
| 
     		clock_sync_next <= clock_reg;
 
   | 
||
| 
     		clock_sync_next <= clock_sync_reg;
 
   | 
||
| 
     | 
||
| 
     		clk_edge := (not(clock_sync_reg) and clock_reg) or (clock_sync_reg and not(clock_reg));
 
   | 
||
| 
     | 
||
| 
     		if (enable_179='1') then
 
   | 
||
| 
     			clock_next <= sio_clockin_in1_reg;
 
   | 
||
| 
     			clock_sync_next <= clock_reg;
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| 
     		serout_enable <= '0';
 
   | 
||
| ... | ... | |
| 
     | 
||
| 
     		case skctl_reg(6 downto 4) is
 
   | 
||
| 
     			when "000" =>
 
   | 
||
| 
     				serin_enable <= not(clock_sync_reg) and clock_reg;
 
   | 
||
| 
     				serout_enable <= not(clock_sync_reg) and clock_reg;
 
   | 
||
| 
     				serin_enable <= clk_edge;
 
   | 
||
| 
     				serout_enable <= clk_edge;
 
   | 
||
| 
     			when "001" =>
 
   | 
||
| 
     				serin_enable <= audf3_pulse;
 
   | 
||
| 
     				serout_enable <= not(clock_sync_reg) and clock_reg;
 
   | 
||
| 
     				serout_enable <= clk_edge;
 
   | 
||
| 
     			when "010" =>
 
   | 
||
| 
     				serin_enable <= audf3_pulse;
 
   | 
||
| 
     				serout_enable <= audf3_pulse;
 
   | 
||
| ... | ... | |
| 
     				serin_enable <= audf3_pulse;
 
   | 
||
| 
     				serout_enable <= audf3_pulse;
 
   | 
||
| 
     			when "100" =>
 
   | 
||
| 
     				serin_enable <= not(clock_sync_reg) and clock_reg;
 
   | 
||
| 
     				serin_enable <= clk_edge;
 
   | 
||
| 
     				serout_enable <= audf3_pulse;
 
   | 
||
| 
     			when "101" =>
 
   | 
||
| 
     				serin_enable <= audf3_pulse;
 
   | 
||
| ... | ... | |
| 
     		end if;
 
   | 
||
| 
     | 
||
| 
     		if (potgo_write = '1') then
 
   | 
||
| 
     			pot_counter_next <= (others=>'0');
 
   | 
||
| 
     			pot_counter_next <= x"01";
 
   | 
||
| 
     			pot_reset_next <= '0'; -- turn off pot dump transistors, so they start to get charged
 
   | 
||
| 
     			allpot_next <= (others=>'1');
 
   | 
||
| 
     		end if;		
 
   | 
||
External clock triggers pulse on both edges. pot resets to 01 instead of 00. cycle exact corrections to audctl.