mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-04-14 07:29:37 +00:00
Ladybug HW: use common T80 and SN67489
This commit is contained in:
@@ -45,22 +45,24 @@
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
entity sn76489_attenuator is
|
||||
|
||||
port (
|
||||
attenuation_i : in std_logic_vector(0 to 3);
|
||||
factor_i : in signed(0 to 1);
|
||||
product_o : out signed(0 to 7)
|
||||
factor_i : in std_logic;
|
||||
product_o : out std_logic_vector(0 to 7)
|
||||
);
|
||||
|
||||
end sn76489_attenuator;
|
||||
|
||||
|
||||
architecture rtl of sn76489_attenuator is
|
||||
|
||||
type volume_t is array (natural range 0 to 15) of natural;
|
||||
constant volume_c : volume_t := (31, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3, 2, 2, 2, 1, 0);
|
||||
begin
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
@@ -78,37 +80,8 @@ begin
|
||||
-- v(0) = 31
|
||||
-- v(n+1) = v(n) * 0.79432823
|
||||
--
|
||||
attenuate: process (attenuation_i,
|
||||
factor_i)
|
||||
|
||||
type volume_t is array (natural range 0 to 15) of natural;
|
||||
constant volume_c : volume_t :=
|
||||
(31, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3, 2, 2, 2, 1, 0);
|
||||
|
||||
variable attenuation_v : unsigned(attenuation_i'range);
|
||||
variable volume_v : signed(product_o'range);
|
||||
|
||||
begin
|
||||
|
||||
attenuation_v := unsigned(attenuation_i);
|
||||
|
||||
-- volume look-up table
|
||||
volume_v := to_signed(volume_c(to_integer(attenuation_v)),
|
||||
product_o'length);
|
||||
|
||||
-- this replaces a multiplier and consumes a bit fewer
|
||||
-- resources
|
||||
case to_integer(factor_i) is
|
||||
when +1 =>
|
||||
product_o <= volume_v;
|
||||
when -1 =>
|
||||
product_o <= -volume_v;
|
||||
when others =>
|
||||
product_o <= (others => '0');
|
||||
end case;
|
||||
|
||||
end process attenuate;
|
||||
--
|
||||
-----------------------------------------------------------------------------
|
||||
product_o <= conv_std_logic_vector(volume_c(conv_integer(attenuation_i)), product_o'length) when factor_i = '1'
|
||||
else (others => '0');
|
||||
|
||||
end rtl;
|
||||
|
||||
@@ -45,7 +45,9 @@
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
entity sn76489_clock_div is
|
||||
|
||||
@@ -68,7 +70,7 @@ use ieee.numeric_std.all;
|
||||
architecture rtl of sn76489_clock_div is
|
||||
|
||||
signal cnt_s,
|
||||
cnt_q : unsigned(3 downto 0);
|
||||
cnt_q : std_logic_vector(3 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
@@ -109,9 +111,9 @@ begin
|
||||
clk_en_o <= true;
|
||||
|
||||
if clock_div_16_g = 1 then
|
||||
cnt_s <= to_unsigned(15, cnt_q'length);
|
||||
cnt_s <= conv_std_logic_vector(15, cnt_q'length);
|
||||
elsif clock_div_16_g = 0 then
|
||||
cnt_s <= to_unsigned( 1, cnt_q'length);
|
||||
cnt_s <= conv_std_logic_vector( 1, cnt_q'length);
|
||||
else
|
||||
-- pragma translate_off
|
||||
assert false
|
||||
|
||||
@@ -75,6 +75,7 @@ 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;
|
||||
signal we_n_d : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
@@ -92,6 +93,12 @@ begin
|
||||
ready_q <= '0';
|
||||
|
||||
elsif clock_i'event and clock_i = '1' then
|
||||
if clk_en_i then
|
||||
we_n_d <= we_n_i;
|
||||
elsif we_n_i = '1' then
|
||||
we_n_d <= '1';
|
||||
end if;
|
||||
|
||||
-- READY Flag Output ----------------------------------------------------
|
||||
if ready_q = '0' and we_q then
|
||||
if clk_en_i then
|
||||
@@ -104,15 +111,15 @@ begin
|
||||
end if;
|
||||
|
||||
-- Register Selection ---------------------------------------------------
|
||||
if ce_n_i = '0' and we_n_i = '0' then
|
||||
if clk_en_i then
|
||||
if clk_en_i then
|
||||
if ce_n_i = '0' and we_n_d = '1' and we_n_i = '0' then
|
||||
if d_i(0) = '1' then
|
||||
reg_q <= d_i(1 to 3);
|
||||
end if;
|
||||
we_q <= true;
|
||||
else
|
||||
we_q <= false;
|
||||
end if;
|
||||
else
|
||||
we_q <= false;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
@@ -45,8 +45,9 @@
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
entity sn76489_noise is
|
||||
|
||||
@@ -58,26 +59,25 @@ entity sn76489_noise is
|
||||
d_i : in std_logic_vector(0 to 7);
|
||||
r2_i : in std_logic;
|
||||
tone3_ff_i : in std_logic;
|
||||
noise_o : out signed(0 to 7)
|
||||
noise_o : out std_logic_vector(0 to 7)
|
||||
);
|
||||
|
||||
end sn76489_noise;
|
||||
|
||||
|
||||
architecture rtl of sn76489_noise is
|
||||
|
||||
signal nf_q : std_logic_vector(0 to 1);
|
||||
signal fb_q : std_logic;
|
||||
signal a_q : std_logic_vector(0 to 3);
|
||||
signal freq_cnt_q : unsigned(0 to 6);
|
||||
signal freq_cnt_q : std_logic_vector(0 to 6);
|
||||
signal freq_ff_q : std_logic;
|
||||
|
||||
signal shift_source_s,
|
||||
shift_source_q : std_logic;
|
||||
signal shift_rise_edge_s : boolean;
|
||||
|
||||
signal lfsr_q : std_logic_vector(0 to 15);
|
||||
|
||||
signal freq_s : signed(0 to 1);
|
||||
signal lfsr_q : std_logic_vector(0 to 14);
|
||||
|
||||
begin
|
||||
|
||||
@@ -133,11 +133,11 @@ begin
|
||||
-- reload frequency counter according to NF setting
|
||||
case nf_q is
|
||||
when "00" =>
|
||||
freq_cnt_q <= to_unsigned(16 * 2 - 1, freq_cnt_q'length);
|
||||
freq_cnt_q <= conv_std_logic_vector(16 * 2 - 1, freq_cnt_q'length);
|
||||
when "01" =>
|
||||
freq_cnt_q <= to_unsigned(16 * 4 - 1, freq_cnt_q'length);
|
||||
freq_cnt_q <= conv_std_logic_vector(16 * 4 - 1, freq_cnt_q'length);
|
||||
when "10" =>
|
||||
freq_cnt_q <= to_unsigned(16 * 8 - 1, freq_cnt_q'length);
|
||||
freq_cnt_q <= conv_std_logic_vector(16 * 8 - 1, freq_cnt_q'length);
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
@@ -202,9 +202,9 @@ begin
|
||||
lfsr: process (clock_i, res_n_i)
|
||||
|
||||
function lfsr_tapped_f(lfsr : in std_logic_vector) return std_logic is
|
||||
constant tapped_bits_c : std_logic_vector(0 to 15)
|
||||
constant tapped_bits_c : std_logic_vector(0 to 14)
|
||||
-- tapped bits are 0, 2, 15
|
||||
:= "1010000000000001";
|
||||
:= "110000000000000";
|
||||
variable parity_v : std_logic;
|
||||
begin
|
||||
parity_v := '0';
|
||||
@@ -253,17 +253,6 @@ begin
|
||||
end if;
|
||||
end if;
|
||||
end process lfsr;
|
||||
--
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Map output of LFSR to signed value for attenuator.
|
||||
-----------------------------------------------------------------------------
|
||||
freq_s <= to_signed(+1, 2)
|
||||
when lfsr_q(0) = '1' else
|
||||
to_signed( 0, 2);
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- The attenuator itself
|
||||
@@ -271,7 +260,7 @@ begin
|
||||
attenuator_b : entity work.sn76489_attenuator
|
||||
port map (
|
||||
attenuation_i => a_q,
|
||||
factor_i => freq_s,
|
||||
factor_i => lfsr_q(0),
|
||||
product_o => noise_o
|
||||
);
|
||||
|
||||
|
||||
@@ -45,8 +45,9 @@
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
entity sn76489_tone is
|
||||
|
||||
@@ -58,7 +59,7 @@ entity sn76489_tone is
|
||||
d_i : in std_logic_vector(0 to 7);
|
||||
r2_i : in std_logic;
|
||||
ff_o : out std_logic;
|
||||
tone_o : out signed(0 to 7)
|
||||
tone_o : out std_logic_vector(0 to 7)
|
||||
);
|
||||
|
||||
end sn76489_tone;
|
||||
@@ -67,10 +68,9 @@ architecture rtl of sn76489_tone is
|
||||
|
||||
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);
|
||||
signal freq_cnt_q : std_logic_vector(0 to 9);
|
||||
signal freq_ff_q : std_logic;
|
||||
|
||||
signal freq_s : signed(0 to 1);
|
||||
signal output_ff : std_logic;
|
||||
|
||||
function all_zero(a : in std_logic_vector) return boolean is
|
||||
variable result_v : boolean;
|
||||
@@ -134,21 +134,25 @@ begin
|
||||
if res_n_i = '0' then
|
||||
freq_cnt_q <= (others => '0');
|
||||
freq_ff_q <= '0';
|
||||
output_ff <= '0';
|
||||
|
||||
elsif clock_i'event and clock_i = '1' then
|
||||
if clk_en_i then
|
||||
if freq_cnt_q = 0 then
|
||||
if freq_cnt_q = 1 then
|
||||
-- update counter from frequency register
|
||||
freq_cnt_q <= unsigned(f_q);
|
||||
freq_cnt_q <= f_q;
|
||||
|
||||
-- and toggle the frequency flip-flop if enabled
|
||||
if not all_zero(f_q) then
|
||||
if (f_q > 5) then
|
||||
freq_ff_q <= not freq_ff_q;
|
||||
else
|
||||
-- if frequency setting is 0, then keep flip-flop at +1
|
||||
freq_ff_q <= '1';
|
||||
end if;
|
||||
|
||||
-- either way toggle the output_ff - this is used to clock noise
|
||||
output_ff <= not output_ff;
|
||||
|
||||
else
|
||||
-- decrement frequency counter
|
||||
freq_cnt_q <= freq_cnt_q - 1;
|
||||
@@ -157,16 +161,6 @@ begin
|
||||
end if;
|
||||
end if;
|
||||
end process freq_gen;
|
||||
--
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Map frequency flip-flop to signed value for attenuator.
|
||||
-----------------------------------------------------------------------------
|
||||
freq_s <= to_signed(+1, 2)
|
||||
when freq_ff_q = '1' else
|
||||
to_signed(-1, 2);
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
@@ -175,7 +169,7 @@ begin
|
||||
attenuator_b : entity work.sn76489_attenuator
|
||||
port map (
|
||||
attenuation_i => a_q,
|
||||
factor_i => freq_s,
|
||||
factor_i => freq_ff_q,
|
||||
product_o => tone_o
|
||||
);
|
||||
|
||||
@@ -183,6 +177,6 @@ begin
|
||||
-----------------------------------------------------------------------------
|
||||
-- Output mapping
|
||||
-----------------------------------------------------------------------------
|
||||
ff_o <= freq_ff_q;
|
||||
ff_o <= output_ff;
|
||||
|
||||
end rtl;
|
||||
|
||||
@@ -56,11 +56,9 @@
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library ieee;
|
||||
use ieee.numeric_std.all;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
entity sn76489_top is
|
||||
|
||||
@@ -75,11 +73,15 @@ entity sn76489_top is
|
||||
we_n_i : in std_logic;
|
||||
ready_o : out std_logic;
|
||||
d_i : in std_logic_vector(0 to 7);
|
||||
aout_o : out signed(0 to 7)
|
||||
aout_o : out std_logic_vector(0 to 7)
|
||||
);
|
||||
|
||||
end sn76489_top;
|
||||
|
||||
|
||||
library ieee;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
architecture struct of sn76489_top is
|
||||
|
||||
signal clk_en_s : boolean;
|
||||
@@ -93,7 +95,7 @@ architecture struct of sn76489_top is
|
||||
signal tone1_s,
|
||||
tone2_s,
|
||||
tone3_s,
|
||||
noise_s : signed(0 to 7);
|
||||
noise_s : std_logic_vector(0 to 7);
|
||||
|
||||
signal tone3_ff_s : std_logic;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user