diff --git a/sn76489-1.0/sn76489_comp_pack-p.vhd b/sn76489-1.0/sn76489_comp_pack-p.vhd index 06b12c8..c5fcc90 100644 --- a/sn76489-1.0/sn76489_comp_pack-p.vhd +++ b/sn76489-1.0/sn76489_comp_pack-p.vhd @@ -27,9 +27,11 @@ package sn76489_comp_pack is clock_i : in std_logic; clk_en_i : in boolean; res_n_i : in std_logic; - we_i : in boolean; + we_i : in std_logic; d_i : in std_logic_vector(0 to 7); - r2_i : in std_logic; + addr_i : in std_logic_vector(0 to 1); + rst_a_i : in std_logic_vector(0 to 3); + rst_cnt_i: in std_logic_vector(0 to 9); ff_o : out std_logic; tone_o : out signed(0 to 7) ); @@ -40,31 +42,14 @@ package sn76489_comp_pack is clock_i : in std_logic; clk_en_i : in boolean; res_n_i : in std_logic; - we_i : in boolean; + we_i : in std_logic; d_i : in std_logic_vector(0 to 7); - r2_i : in std_logic; + addr_i : in std_logic_vector(0 to 1); tone3_ff_i : in std_logic; noise_o : out signed(0 to 7) ); end component; - component sn76489_latch_ctrl - port ( - clock_i : in std_logic; - clk_en_i : in boolean; - res_n_i : in std_logic; - ce_n_i : in std_logic; - we_n_i : in std_logic; - d_i : in std_logic_vector(0 to 7); - ready_o : out std_logic; - tone1_we_o : out boolean; - tone2_we_o : out boolean; - tone3_we_o : out boolean; - noise_we_o : out boolean; - r2_o : out std_logic - ); - end component; - component sn76489_clock_div generic ( clock_div_16_g : integer := 1 diff --git a/sn76489-1.0/sn76489_latch_ctrl-c.vhd b/sn76489-1.0/sn76489_latch_ctrl-c.vhd deleted file mode 100644 index abc09e0..0000000 --- a/sn76489-1.0/sn76489_latch_ctrl-c.vhd +++ /dev/null @@ -1,14 +0,0 @@ -------------------------------------------------------------------------------- --- --- Synthesizable model of TI's SN76489AN. --- --- $Id: sn76489_latch_ctrl-c.vhd,v 1.2 2005/10/10 22:12:38 arnim Exp $ --- -------------------------------------------------------------------------------- - -configuration sn76489_latch_ctrl_rtl_c0 of sn76489_latch_ctrl is - - for rtl - end for; - -end sn76489_latch_ctrl_rtl_c0; diff --git a/sn76489-1.0/sn76489_latch_ctrl.vhd b/sn76489-1.0/sn76489_latch_ctrl.vhd deleted file mode 100644 index 789720c..0000000 --- a/sn76489-1.0/sn76489_latch_ctrl.vhd +++ /dev/null @@ -1,138 +0,0 @@ -------------------------------------------------------------------------------- --- --- Synthesizable model of TI's SN76489AN. --- --- $Id: sn76489_latch_ctrl.vhd,v 1.6 2006/02/27 20:30:10 arnim Exp $ --- --- Latch Control Unit --- -------------------------------------------------------------------------------- --- --- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net) --- --- All rights reserved --- --- Redistribution and use in source and synthezised forms, with or without --- modification, are permitted provided that the following conditions are met: --- --- Redistributions of source code must retain the above copyright notice, --- this list of conditions and the following disclaimer. --- --- Redistributions in synthesized form must reproduce the above copyright --- notice, this list of conditions and the following disclaimer in the --- documentation and/or other materials provided with the distribution. --- --- Neither the name of the author nor the names of other contributors may --- be used to endorse or promote products derived from this software without --- specific prior written permission. --- --- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" --- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, --- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR --- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE --- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR --- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF --- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS --- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN --- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) --- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE --- POSSIBILITY OF SUCH DAMAGE. --- --- Please report bugs to the author, but before you do so, please --- make sure that this is not a derivative work and that --- you have the latest version of this file. --- -------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; - -entity sn76489_latch_ctrl is - - port ( - clock_i : in std_logic; - clk_en_i : in boolean; - res_n_i : in std_logic; - ce_n_i : in std_logic; - we_n_i : in std_logic; - d_i : in std_logic_vector(0 to 7); - ready_o : out std_logic; - tone1_we_o : out boolean; - tone2_we_o : out boolean; - tone3_we_o : out boolean; - noise_we_o : out boolean; - r2_o : out std_logic - ); - -end sn76489_latch_ctrl; - - -library ieee; -use ieee.numeric_std.all; - -architecture rtl of sn76489_latch_ctrl is - - signal reg_q : std_logic_vector(0 to 2); - signal we_q : boolean; - signal ready_q : std_logic; - -begin - - ----------------------------------------------------------------------------- - -- Process seq - -- - -- Purpose: - -- Implements the sequential elements. - -- - seq: process (clock_i, res_n_i) - begin - if res_n_i = '0' then - reg_q <= (others => '0'); - we_q <= false; - ready_q <= '0'; - - elsif clock_i'event and clock_i = '1' then - -- READY Flag Output ---------------------------------------------------- - if ready_q = '0' and we_q then - if clk_en_i then - -- assert READY when write access happened - ready_q <= '1'; - end if; - elsif ce_n_i = '1' then - -- deassert READY when access has finished - ready_q <= '0'; - end if; - - -- Register Selection --------------------------------------------------- - if ce_n_i = '0' and we_n_i = '0' then - if clk_en_i then - if d_i(0) = '1' then - reg_q <= d_i(1 to 3); - end if; - we_q <= true; - end if; - else - we_q <= false; - end if; - - end if; - end process seq; - -- - ----------------------------------------------------------------------------- - - - ----------------------------------------------------------------------------- - -- Output mapping - ----------------------------------------------------------------------------- - tone1_we_o <= reg_q(0 to 1) = "00" and we_q; - tone2_we_o <= reg_q(0 to 1) = "01" and we_q; - tone3_we_o <= reg_q(0 to 1) = "10" and we_q; - noise_we_o <= reg_q(0 to 1) = "11" and we_q; - - r2_o <= reg_q(2); - - ready_o <= ready_q - when ce_n_i = '0' else - '1'; - -end rtl; diff --git a/sn76489-1.0/sn76489_noise.vhd b/sn76489-1.0/sn76489_noise.vhd index 8b2ee0e..035adab 100644 --- a/sn76489-1.0/sn76489_noise.vhd +++ b/sn76489-1.0/sn76489_noise.vhd @@ -54,9 +54,9 @@ entity sn76489_noise is clock_i : in std_logic; clk_en_i : in boolean; res_n_i : in std_logic; - we_i : in boolean; + we_i : in std_logic; d_i : in std_logic_vector(0 to 7); - r2_i : in std_logic; + addr_i : in std_logic_vector(0 to 1); tone3_ff_i : in std_logic; noise_o : out signed(0 to 7) ); @@ -68,6 +68,9 @@ use work.sn76489_comp_pack.sn76489_attenuator; architecture rtl of sn76489_noise is + signal selected : std_logic; + signal write_cr : std_logic; + signal nf_q : std_logic_vector(0 to 1); signal fb_q : std_logic; signal a_q : std_logic_vector(0 to 3); @@ -78,12 +81,13 @@ architecture rtl of sn76489_noise is shift_source_q : std_logic; signal shift_rise_edge_s : boolean; - signal lfsr_q : std_logic_vector(0 to 15); + signal lfsr_q : std_logic_vector(0 to 7); signal freq_s : signed(0 to 1); begin + ----------------------------------------------------------------------------- -- Process cpu_regs -- @@ -96,22 +100,25 @@ begin nf_q <= (others => '0'); fb_q <= '0'; a_q <= (others => '1'); - - elsif clock_i'event and clock_i = '1' then - if clk_en_i and we_i then - if r2_i = '0' then - -- access to control register - -- both access types can write to the control register! - nf_q <= d_i(6 to 7); - fb_q <= d_i(5); - - else - -- access to attenuator register - -- both access types can write to the attenuator register! - a_q <= d_i(4 to 7); - + elsif rising_edge(clock_i) and we_i = '1' then + if d_i(0) = '1' then + if d_i(1 to 2) = addr_i then + if d_i(3) = '0' then + selected<='1'; + nf_q <= d_i(6 to 7); + fb_q <= d_i(5); + else + selected <='0'; + a_q <= d_i(4 to 7); + end if; + else + selected <='0'; + end if; + elsif selected = '1' then + selected<='0'; + nf_q <= d_i(6 to 7); + fb_q <= d_i(5); end if; - end if; end if; end process cpu_regs; -- @@ -130,8 +137,7 @@ begin freq_cnt_q <= (others => '0'); freq_ff_q <= '0'; - elsif clock_i'event and clock_i = '1' then - if clk_en_i then + elsif rising_edge(clock_i) and clk_en_i then if freq_cnt_q = 0 then -- reload frequency counter according to NF setting case nf_q is @@ -152,8 +158,6 @@ begin freq_cnt_q <= freq_cnt_q - 1; end if; - - end if; end if; end process freq_gen; -- @@ -191,6 +195,8 @@ begin shift_rise_edge_s <= shift_source_q = '0' and shift_source_s = '1'; + write_cr <= '1' when ((we_i='1') and (((d_i(0) = '1') and (d_i(1 to 2) = addr_i) and (d_i(3) = '0')) or (selected='1'))) else '0'; + ----------------------------------------------------------------------------- -- Process lfsr -- @@ -219,15 +225,15 @@ begin return parity_v; end; + begin if res_n_i = '0' then -- reset LFSR to "0000000000000001" lfsr_q <= (others => '0'); lfsr_q(lfsr_q'right) <= '1'; - elsif clock_i'event and clock_i = '1' then - if clk_en_i then - if we_i and r2_i = '0' then + elsif rising_edge(clock_i) and clk_en_i then + if write_cr='1' then -- write to noise register -- -> reset LFSR lfsr_q <= (others => '0'); @@ -253,7 +259,6 @@ begin end if; - end if; end if; end process lfsr; -- diff --git a/sn76489-1.0/sn76489_tone.vhd b/sn76489-1.0/sn76489_tone.vhd index b71af8b..f1b6885 100644 --- a/sn76489-1.0/sn76489_tone.vhd +++ b/sn76489-1.0/sn76489_tone.vhd @@ -54,9 +54,11 @@ entity sn76489_tone is clock_i : in std_logic; clk_en_i : in boolean; res_n_i : in std_logic; - we_i : in boolean; + we_i : in std_logic; d_i : in std_logic_vector(0 to 7); - r2_i : in std_logic; + addr_i : in std_logic_vector(0 to 1); + rst_a_i : in std_logic_vector(0 to 3); + rst_cnt_i: in std_logic_vector(0 to 9); ff_o : out std_logic; tone_o : out signed(0 to 7) ); @@ -68,6 +70,7 @@ use work.sn76489_comp_pack.sn76489_attenuator; architecture rtl of sn76489_tone is + signal selected : std_logic; signal f_q : std_logic_vector(0 to 9); signal a_q : std_logic_vector(0 to 3); signal freq_cnt_q : unsigned(0 to 9); @@ -75,6 +78,7 @@ architecture rtl of sn76489_tone is signal freq_s : signed(0 to 1); + function all_zero(a : in std_logic_vector) return boolean is variable result_v : boolean; begin @@ -91,6 +95,8 @@ architecture rtl of sn76489_tone is begin + + ----------------------------------------------------------------------------- -- Process cpu_regs -- @@ -99,27 +105,28 @@ begin -- cpu_regs: process (clock_i, res_n_i) begin - if res_n_i = '0' then - f_q <= (others => '0'); - a_q <= (others => '1'); - - elsif clock_i'event and clock_i = '1' then - if clk_en_i and we_i then - if r2_i = '0' then - -- access to frequency register - if d_i(0) = '0' then - f_q(0 to 5) <= d_i(2 to 7); - else - f_q(6 to 9) <= d_i(4 to 7); - end if; - - else - -- access to attenuator register - -- both access types can write to the attenuator register! - a_q <= d_i(4 to 7); + if res_n_i = '0' then + f_q <= (others => '1'); + a_q <= rst_a_i; + selected <='0'; + elsif rising_edge(clock_i) and we_i = '1' then + if d_i(0) = '1' then + if d_i(1 to 2) = addr_i then + if d_i(3) = '0' then + selected<='1'; + f_q(6 to 9) <= d_i(4 to 7); + else + selected <='0'; + a_q <= d_i(4 to 7); + end if; + else + selected <='0'; + end if; + elsif selected = '1' then + selected<='0'; + f_q(0 to 5) <= d_i(2 to 7); end if; - end if; end if; end process cpu_regs; -- @@ -135,17 +142,19 @@ begin freq_gen: process (clock_i, res_n_i) begin if res_n_i = '0' then - freq_cnt_q <= (others => '0'); + freq_cnt_q <= unsigned(rst_cnt_i); freq_ff_q <= '0'; - elsif clock_i'event and clock_i = '1' then - if clk_en_i then - if freq_cnt_q = 0 then + elsif rising_edge(clock_i) and clk_en_i then + if we_i='1' and selected = '1' then + freq_cnt_q <= (others => '0'); + freq_ff_q <= '1'; + elsif freq_cnt_q = 0 then -- update counter from frequency register - freq_cnt_q <= unsigned(f_q); + freq_cnt_q <= unsigned(f_q)-to_unsigned(1,10); -- and toggle the frequency flip-flop if enabled - if not all_zero(f_q) then + if unsigned(f_q) > to_unsigned(1,10) then freq_ff_q <= not freq_ff_q; else -- if frequency setting is 0, then keep flip-flop at +1 @@ -157,7 +166,6 @@ begin freq_cnt_q <= freq_cnt_q - 1; end if; - end if; end if; end process freq_gen; -- diff --git a/sn76489-1.0/sn76489_top-c.vhd b/sn76489-1.0/sn76489_top-c.vhd index 8f709b9..55f3dfb 100644 --- a/sn76489-1.0/sn76489_top-c.vhd +++ b/sn76489-1.0/sn76489_top-c.vhd @@ -14,10 +14,6 @@ configuration sn76489_top_struct_c0 of sn76489_top is use configuration work.sn76489_clock_div_rtl_c0; end for; - for latch_ctrl_b : sn76489_latch_ctrl - use configuration work.sn76489_latch_ctrl_rtl_c0; - end for; - for all : sn76489_tone use configuration work.sn76489_tone_rtl_c0; end for; diff --git a/sn76489-1.0/sn76489_top.vhd b/sn76489-1.0/sn76489_top.vhd index deb8170..2f6a01c 100644 --- a/sn76489-1.0/sn76489_top.vhd +++ b/sn76489-1.0/sn76489_top.vhd @@ -86,19 +86,17 @@ architecture struct of sn76489_top is signal clk_en_s : boolean; - signal tone1_we_s, - tone2_we_s, - tone3_we_s, - noise_we_s : boolean; - signal r2_s : std_logic; - signal tone1_s, tone2_s, tone3_s, - noise_s : signed(0 to 7); + noise_s : signed(0 to 15); signal tone3_ff_s : std_logic; + signal dl : std_logic_vector(0 to 9); + + signal we : std_logic; + begin ----------------------------------------------------------------------------- @@ -116,26 +114,6 @@ begin ); - ----------------------------------------------------------------------------- - -- Latch Control = CPU Interface - ----------------------------------------------------------------------------- - latch_ctrl_b : sn76489_latch_ctrl - port map ( - clock_i => clock_i, - clk_en_i => clk_en_s, - res_n_i => res_n_i, - ce_n_i => ce_n_i, - we_n_i => we_n_i, - d_i => d_i, - ready_o => ready_o, - tone1_we_o => tone1_we_s, - tone2_we_o => tone2_we_s, - tone3_we_o => tone3_we_s, - noise_we_o => noise_we_s, - r2_o => r2_s - ); - - ----------------------------------------------------------------------------- -- Tone Channel 1 ----------------------------------------------------------------------------- @@ -144,9 +122,11 @@ begin clock_i => clock_i, clk_en_i => clk_en_s, res_n_i => res_n_i, - we_i => tone1_we_s, + we_i => we, d_i => d_i, - r2_i => r2_s, + addr_i => "00", + rst_a_i => "0000", + rst_cnt_i=> "0000000000", ff_o => open, tone_o => tone1_s ); @@ -159,9 +139,11 @@ begin clock_i => clock_i, clk_en_i => clk_en_s, res_n_i => res_n_i, - we_i => tone2_we_s, + we_i => we, d_i => d_i, - r2_i => r2_s, + addr_i => "01", + rst_a_i => "1000", + rst_cnt_i=> "0000110100", ff_o => open, tone_o => tone2_s ); @@ -174,9 +156,11 @@ begin clock_i => clock_i, clk_en_i => clk_en_s, res_n_i => res_n_i, - we_i => tone3_we_s, + we_i => we, d_i => d_i, - r2_i => r2_s, + addr_i => "10", + rst_a_i => "1000", + rst_cnt_i=> "1100110100", ff_o => tone3_ff_s, tone_o => tone3_s ); @@ -189,14 +173,16 @@ begin clock_i => clock_i, clk_en_i => clk_en_s, res_n_i => res_n_i, - we_i => noise_we_s, + we_i => we, d_i => d_i, - r2_i => r2_s, + addr_i => "11", tone3_ff_i => tone3_ff_s, noise_o => noise_s ); + we<= not(ce_n_i or we_n_i) when clk_en_s else '0'; + -- Register output process(clock_i) begin @@ -207,4 +193,23 @@ begin end if; end process; + process(clock_i) + begin + if res_n_i = '0' then + dl<=(others => '0'); + elsif rising_edge(clock_i) then + if ce_n_i = '0' and we_n_i = '0' then + if d_i(0)='1' then + if d_i(3)='0' then + dl(6 to 9) <= d_i(4 to 7); + end if; + else + dl(0 to 5) <= d_i(2 to 7); + end if; + end if; + end if; + end process; + + + ready_o <= '1'; end struct;