-
Notifications
You must be signed in to change notification settings - Fork 0
/
sound_machine.vhd
153 lines (131 loc) · 4.51 KB
/
sound_machine.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
---------------------------------------------------------------------------------
-- Galaga sound machine by Dar (darfpga@aol.fr)
-- http://darfpga.blogspot.fr
---------------------------------------------------------------------------------
-- 3 voices frequency/waveform synthetizer
--
-- Original hardware done with only one 4 bits sequential adder to realise
-- one 20 bits adder and two 16 bits adder.
--
-- Too nice and clever to be done another way, just doing it the same way!
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity sound_machine is
port(
clock_18 : in std_logic;
hcnt : in std_logic_vector(5 downto 0);
ena : in std_logic;
cpu_addr : in std_logic_vector(3 downto 0);
cpu_do : in std_logic_vector(3 downto 0);
ram_0_we : in std_logic;
ram_1_we : in std_logic;
audio : out std_logic_vector(9 downto 0)
);
end sound_machine;
architecture struct of sound_machine is
signal clock_18n : std_logic;
signal snd_ram_addr : std_logic_vector(3 downto 0);
signal snd_ram_di : std_logic_vector(3 downto 0);
signal snd_ram_0_we : std_logic;
signal snd_ram_1_we : std_logic;
signal snd_ram_0_do : std_logic_vector(3 downto 0);
signal snd_ram_1_do : std_logic_vector(3 downto 0);
signal snd_seq_do : std_logic_vector(3 downto 0);
signal snd_samples_addr : std_logic_vector(7 downto 0);
signal snd_samples_do : std_logic_vector(3 downto 0);
signal sum : std_logic_vector(4 downto 0) := (others => '0');
signal sum_r : std_logic_vector(4 downto 0) := (others => '0');
signal sum_3_rr : std_logic := '0';
signal samples_ch0 : std_logic_vector(3 downto 0);
signal samples_ch1 : std_logic_vector(3 downto 0);
signal samples_ch2 : std_logic_vector(3 downto 0);
signal volume_ch0 : std_logic_vector(3 downto 0);
signal volume_ch1 : std_logic_vector(3 downto 0);
signal volume_ch2 : std_logic_vector(3 downto 0);
begin
clock_18n <= not clock_18;
snd_ram_addr <= cpu_addr when (ram_0_we = '1' or ram_1_we = '1') else hcnt(5 downto 2);
snd_ram_di <= cpu_do when (ram_0_we = '1' or ram_1_we = '1') else sum_r(3 downto 0);
snd_ram_0_we <= (not snd_seq_do(1) and ena) or ram_0_we ;
snd_ram_1_we <= ram_1_we;
sum <= ('0' & snd_ram_0_do) + ('0' & snd_ram_1_do) + ("0000" & sum_r(4));
process (clock_18)
function mul4x4(arg1, arg2: std_logic_vector(3 downto 0)) return std_logic_vector is
variable rval: std_logic_vector(9 downto 0);
begin
rval := "0000000000";
if arg2(3) = '1' then rval := rval + (arg1 & "000"); end if;
if arg2(2) = '1' then rval := rval + (arg1 & "00"); end if;
if arg2(1) = '1' then rval := rval + (arg1 & "0"); end if;
if arg2(0) = '1' then rval := rval + arg1; end if;
return rval;
end mul4x4;
begin
if rising_edge(clock_18) then
if ena = '1' then
if snd_seq_do(3) = '0' then
sum_r <= (others => '0');
sum_3_rr <= '0';
elsif snd_seq_do(0) = '0' then
sum_r <= sum;
sum_3_rr <= sum_r(3);
end if ;
snd_samples_addr <= snd_ram_0_do(2 downto 0) & sum_r(3 downto 0) & sum_3_rr;
if snd_seq_do(2) = '0' then
if hcnt(5 downto 2) = X"5" then
samples_ch0 <= snd_samples_do(3 downto 0);
volume_ch0 <= snd_ram_1_do;
end if;
if hcnt(5 downto 2) = X"A" then
samples_ch1 <= snd_samples_do(3 downto 0);
volume_ch1 <= snd_ram_1_do;
end if;
if hcnt(5 downto 2) = X"F" then
samples_ch2 <= snd_samples_do(3 downto 0);
volume_ch2 <= snd_ram_1_do;
end if;
end if;
audio <= mul4x4(samples_ch0, volume_ch0) +
mul4x4(samples_ch1, volume_ch1) +
mul4x4(samples_ch2, volume_ch2);
end if;
end if;
end process;
-- sound register RAM0
sound_ram_0 : entity work.gen_ram
generic map( dWidth => 4, aWidth => 4)
port map(
clk => clock_18n,
we => snd_ram_0_we,
addr => snd_ram_addr,
d => snd_ram_di,
q => snd_ram_0_do
);
-- sound register RAM1
sound_ram_1 : entity work.gen_ram
generic map( dWidth => 4, aWidth => 4)
port map(
clk => clock_18n,
we => snd_ram_1_we,
addr => snd_ram_addr,
d => snd_ram_di,
q => snd_ram_1_do
);
-- sound samples ROM
sound_samples : entity work.sound_samples
port map(
clk => clock_18n,
addr => snd_samples_addr,
data => snd_samples_do
);
-- sound compute sequencer ROM
sound_seq : entity work.sound_seq
port map(
clk => clock_18n,
addr => not ram_0_we & hcnt(5 downto 0),
data => snd_seq_do
);
end struct;