mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-05 23:54:41 +00:00
[C16] Add SID card support
This commit is contained in:
@@ -68,6 +68,9 @@ module C16 #(parameter MODE_PAL = 1)(
|
||||
input CASS_SENSE,
|
||||
output CASS_MOTOR,
|
||||
|
||||
input [1:0] SID_TYPE,
|
||||
output [17:0] SID_AUDIO,
|
||||
|
||||
output AUDIO_L,
|
||||
output AUDIO_R,
|
||||
|
||||
@@ -244,7 +247,7 @@ always @(posedge CLK28) // reset tries to emulate the length of a real reset
|
||||
// assign VSYNC=1'b1; // set scart mode to RGB for TV
|
||||
|
||||
assign c16_addr=(~mux)?c16_addrlatch:cpu_addr&ted_addr; // C16 address bus
|
||||
assign c16_data=(mux)?c16_datalatch:cpu_data&ted_data&ram_data&kernal_data&basic_data&keyport_data&cass_data; // C16 data bus
|
||||
assign c16_data=(mux)?c16_datalatch:cpu_data&ted_data&ram_data&kernal_data&basic_data&keyport_data&cass_data&sid_data; // C16 data bus
|
||||
|
||||
always @(posedge CLK28) // addres and data bus latching emulates dynamic memory behaviour of these buses
|
||||
begin
|
||||
@@ -275,4 +278,59 @@ wire cass_sel = cpu_addr[15:4] == 12'hFD1;
|
||||
wire [7:0] cass_data = { 5'b11111, cass_sel ? CASS_SENSE : 1'b1, 2'b11 };
|
||||
assign CASS_WRITE = port_out[6];
|
||||
|
||||
// SID extension
|
||||
reg sid_clk_en;
|
||||
always @(posedge CLK28) begin
|
||||
reg muxD, sid_clk;
|
||||
|
||||
sid_clk_en <= 0;
|
||||
muxD <= mux;
|
||||
if (~muxD & mux) begin
|
||||
sid_clk <= ~sid_clk;
|
||||
sid_clk_en <= sid_clk;
|
||||
end
|
||||
end
|
||||
|
||||
// valid adresses for SID: FD40-FD5F and FE80-FE9F
|
||||
wire cs_sid = SID_TYPE && ((c16_addr[15:5] == 'b1111_1101_010) || (c16_addr[15:5] == 'b1111_1110_100));
|
||||
|
||||
wire [7:0] sid8580_data;
|
||||
wire [15:0] sid8580_audio;
|
||||
|
||||
sid8580 sid8580
|
||||
(
|
||||
.reset(sreset),
|
||||
.clk32(CLK28),
|
||||
.clk_1MHz(sid_clk_en),
|
||||
|
||||
.cs(cs_sid),
|
||||
.we(~RW),
|
||||
.addr(c16_addr[4:0]),
|
||||
.data_in(c16_data),
|
||||
.data_out(sid8580_data),
|
||||
|
||||
.extfilter_en(1),
|
||||
.audio_data(sid8580_audio)
|
||||
);
|
||||
|
||||
wire [7:0] sid6581_data;
|
||||
wire [17:0] sid6581_audio;
|
||||
sid_top #(.g_num_voices(3)) sid6581
|
||||
(
|
||||
.reset(sreset),
|
||||
.clock(CLK28),
|
||||
.start_iter(sid_clk_en),
|
||||
|
||||
.wren(~RW & cs_sid),
|
||||
.addr({ 3'd0, c16_addr[4:0] }),
|
||||
.wdata(c16_data),
|
||||
.rdata(sid6581_data),
|
||||
|
||||
.extfilter_en(0), // disabled due to out of BRAM
|
||||
.sample_left(sid6581_audio)
|
||||
);
|
||||
|
||||
assign SID_AUDIO = SID_TYPE[0] ? sid6581_audio : (SID_TYPE[1] ? { sid8580_audio, 2'd0 } : 18'd0);
|
||||
wire [7:0] sid_data = (cs_sid & RW) ? (SID_TYPE[0] ? sid6581_data : sid8580_data) : 8'hFF;
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -167,7 +167,7 @@ set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
|
||||
# SignalTap II Assignments
|
||||
# ========================
|
||||
set_global_assignment -name ENABLE_SIGNALTAP OFF
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/ioctl.stp
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/sid.stp
|
||||
|
||||
# Power Estimation Assignments
|
||||
# ============================
|
||||
@@ -341,9 +341,11 @@ set_global_assignment -name VERILOG_INPUT_VERSION VERILOG_2001
|
||||
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
|
||||
set_global_assignment -name ENABLE_DRC_SETTINGS OFF
|
||||
set_location_assignment PLL_1 -to pll_c16|altpll_component|auto_generated|pll1
|
||||
set_global_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION OFF
|
||||
set_global_assignment -name VHDL_FILE tap_fifo.vhd
|
||||
set_global_assignment -name VHDL_FILE c1530.vhd
|
||||
set_global_assignment -name VHDL_FILE gen_ram.vhd
|
||||
set_global_assignment -name VERILOG_FILE sigma_delta_dac.v
|
||||
set_global_assignment -name VERILOG_FILE data_io.v
|
||||
set_global_assignment -name VERILOG_FILE sdram.v
|
||||
set_global_assignment -name VERILOG_FILE osd.v
|
||||
@@ -378,4 +380,21 @@ set_global_assignment -name QIP_FILE rom_reconfig_pal.qip
|
||||
set_global_assignment -name QIP_FILE rom_reconfig_ntsc.qip
|
||||
set_global_assignment -name QIP_FILE pll_reconfig.qip
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/ioctl.stp
|
||||
set_global_assignment -name VERILOG_FILE sid8580/sid_voice.v
|
||||
set_global_assignment -name VERILOG_FILE sid8580/sid_filters.v
|
||||
set_global_assignment -name VERILOG_FILE sid8580/sid_envelope.v
|
||||
set_global_assignment -name VERILOG_FILE sid8580/sid8580.v
|
||||
set_global_assignment -name VHDL_FILE sid/wave_map.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/sid_top.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/sid_regs.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/sid_mixer.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/sid_filter.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/sid_debug_pkg.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/sid_ctrl.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/Q_table.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/oscillator.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/my_math_pkg.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/mult_acc.vhd
|
||||
set_global_assignment -name VHDL_FILE sid/adsr_multi.vhd
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/sid.stp
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
@@ -79,10 +79,11 @@ parameter CONF_STR = {
|
||||
"O2,Scanlines,Off,On;",
|
||||
"O3,Joysticks,Normal,Swapped;",
|
||||
"O4,Memory,64k,16k;",
|
||||
"O89,SID,Off,6581,8580;",
|
||||
"T5,Reset;"
|
||||
};
|
||||
|
||||
parameter CONF_STR_LEN = 11+17+18+18+21+20+28+18+9;
|
||||
parameter CONF_STR_LEN = 11+17+18+18+21+20+28+18+22+9;
|
||||
|
||||
localparam TAP_MEM_START = 22'h20000;
|
||||
|
||||
@@ -96,7 +97,7 @@ always @(posedge clk28) begin
|
||||
end
|
||||
|
||||
// the status register is controlled by the on screen display (OSD)
|
||||
wire [7:0] status;
|
||||
wire [31:0] status;
|
||||
wire tv15khz;
|
||||
wire ypbpr;
|
||||
wire scanlines = status[2];
|
||||
@@ -105,6 +106,7 @@ wire memory_16k = status[4];
|
||||
wire osd_reset = status[5];
|
||||
wire tap_play = status[6];
|
||||
wire tap_sound = status[7];
|
||||
wire [1:0] sid_type = status[9:8];
|
||||
wire [1:0] buttons;
|
||||
|
||||
wire [7:0] js0, js1;
|
||||
@@ -606,8 +608,17 @@ always @(negedge clk28) begin
|
||||
end
|
||||
|
||||
wire audio_l_out, audio_r_out;
|
||||
assign AUDIO_L = audio_l_out | (tap_sound & ~cass_read);
|
||||
assign AUDIO_R = audio_r_out | (tap_sound & ~cass_read);
|
||||
wire [17:0] sid_audio;
|
||||
wire [17:0] audio_data_l = sid_audio + { audio_l_out, tap_sound & ~cass_read, 13'd0 };
|
||||
wire [17:0] audio_data_r = sid_audio + { audio_r_out, tap_sound & ~cass_read, 13'd0 };
|
||||
|
||||
sigma_delta_dac dac (
|
||||
.clk ( clk28),
|
||||
.ldatasum ( audio_data_l[17:3] ),
|
||||
.rdatasum ( audio_data_r[17:3] ),
|
||||
.aleft ( AUDIO_L ),
|
||||
.aright ( AUDIO_R )
|
||||
);
|
||||
|
||||
// include the c16 itself
|
||||
C16 c16 (
|
||||
@@ -651,6 +662,8 @@ C16 c16 (
|
||||
.CASS_MOTOR ( cass_motor ),
|
||||
.CASS_SENSE ( cass_sense ),
|
||||
|
||||
.SID_TYPE ( sid_type ),
|
||||
.SID_AUDIO ( sid_audio ),
|
||||
.AUDIO_L ( audio_l_out ),
|
||||
.AUDIO_R ( audio_r_out ),
|
||||
|
||||
|
||||
45
cores/c16/sid/Q_table.vhd
Normal file
45
cores/c16/sid/Q_table.vhd
Normal file
@@ -0,0 +1,45 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity Q_table is
|
||||
port (
|
||||
Q_reg : in unsigned(3 downto 0);
|
||||
filter_q : out signed(17 downto 0) );
|
||||
end Q_table;
|
||||
|
||||
architecture Gideon of Q_table is
|
||||
|
||||
type t_18_bit_array is array(natural range <>) of signed(17 downto 0);
|
||||
function create_factors(max_Q: real) return t_18_bit_array is
|
||||
constant critical : real := 0.70710678; -- no resonance at 0.5*sqrt(2)
|
||||
variable q_step : real;
|
||||
variable q : real;
|
||||
variable scaled : real;
|
||||
variable ret : t_18_bit_array(0 to 15);
|
||||
begin
|
||||
q_step := (max_Q - critical) / 15.0; -- linear
|
||||
for i in 0 to 15 loop
|
||||
q := critical + (real(i) * q_step);
|
||||
scaled := 65536.0 / q;
|
||||
ret(i) := to_signed(integer(scaled), 18);
|
||||
end loop;
|
||||
return ret;
|
||||
end function;
|
||||
|
||||
constant c_table : t_18_bit_array(0 to 15) := create_factors(1.8);
|
||||
begin
|
||||
filter_q <= c_table(to_integer(Q_reg));
|
||||
end Gideon;
|
||||
220
cores/c16/sid/adsr_multi.vhd
Normal file
220
cores/c16/sid/adsr_multi.vhd
Normal file
@@ -0,0 +1,220 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use work.sid_debug_pkg.all;
|
||||
|
||||
-- LUT: 195, FF:68
|
||||
|
||||
entity adsr_multi is
|
||||
generic (
|
||||
g_num_voices : integer := 8 );
|
||||
port (
|
||||
clock : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
voice_i : in unsigned(3 downto 0);
|
||||
enable_i : in std_logic;
|
||||
voice_o : out unsigned(3 downto 0);
|
||||
enable_o : out std_logic;
|
||||
|
||||
gate : in std_logic;
|
||||
attack : in std_logic_vector(3 downto 0);
|
||||
decay : in std_logic_vector(3 downto 0);
|
||||
sustain : in std_logic_vector(3 downto 0);
|
||||
release : in std_logic_vector(3 downto 0);
|
||||
|
||||
env_state: out std_logic_vector(1 downto 0); -- for testing only
|
||||
env_out : out unsigned(7 downto 0) );
|
||||
|
||||
end adsr_multi;
|
||||
|
||||
-- 158 1 62 .. FF
|
||||
-- 45 2 35 .. 61
|
||||
-- 26 4 1C .. 34
|
||||
-- 13 8 0D .. 1B
|
||||
-- 6 16 07 .. 0C
|
||||
-- 7 30 00 .. 06
|
||||
|
||||
architecture gideon of adsr_multi is
|
||||
|
||||
type presc_array_t is array(natural range <>) of unsigned(15 downto 0);
|
||||
constant prescalers : presc_array_t(0 to 15) := (
|
||||
X"0008", X"001F", X"003E", X"005E",
|
||||
X"0094", X"00DB", X"010A", X"0138",
|
||||
X"0187", X"03D0", X"07A1", X"0C35",
|
||||
X"0F42", X"2DC7", X"4C4B", X"7A12" );
|
||||
|
||||
|
||||
signal enveloppe : unsigned(7 downto 0) := (others => '0');
|
||||
signal state : unsigned(1 downto 0) := (others => '0');
|
||||
|
||||
constant st_release : unsigned(1 downto 0) := "00";
|
||||
constant st_attack : unsigned(1 downto 0) := "01";
|
||||
constant st_decay : unsigned(1 downto 0) := "11";
|
||||
|
||||
type state_array_t is array(natural range <>) of unsigned(29 downto 0);
|
||||
signal state_array : state_array_t(0 to g_num_voices-1) := (others => (others => '0'));
|
||||
begin
|
||||
env_out <= enveloppe;
|
||||
env_state <= std_logic_vector(state);
|
||||
|
||||
-- FF-5E 01
|
||||
-- 5D-37 02
|
||||
-- 36-1B 04
|
||||
-- 1A-0F 08
|
||||
-- 0E-07 10
|
||||
-- 06-01 1E
|
||||
process(clock)
|
||||
function logarithmic(lev: unsigned(7 downto 0)) return unsigned is
|
||||
variable res : unsigned(4 downto 0);
|
||||
begin
|
||||
if lev = X"00" then
|
||||
res := "00000"; -- prescaler off
|
||||
elsif lev < X"07" then
|
||||
res := "11101"; -- 1E-1
|
||||
elsif lev < X"0F" then
|
||||
res := "01111"; -- 10-1
|
||||
elsif lev < X"1B" then
|
||||
res := "00111"; -- 08-1
|
||||
elsif lev < X"37" then
|
||||
res := "00011"; -- 04-1
|
||||
elsif lev < X"5E" then
|
||||
res := "00001"; -- 02-1
|
||||
else
|
||||
res := "00000"; -- 01-1
|
||||
end if;
|
||||
return res;
|
||||
end function logarithmic;
|
||||
|
||||
variable presc_select : integer range 0 to 15;
|
||||
variable cur_state : unsigned(1 downto 0);
|
||||
variable cur_env : unsigned(7 downto 0);
|
||||
variable cur_pre15 : unsigned(14 downto 0);
|
||||
variable cur_pre5 : unsigned(4 downto 0);
|
||||
variable next_state : unsigned(1 downto 0);
|
||||
variable next_env : unsigned(7 downto 0);
|
||||
variable next_pre15 : unsigned(14 downto 0);
|
||||
variable next_pre5 : unsigned(4 downto 0);
|
||||
variable presc_val : unsigned(14 downto 0);
|
||||
variable log_div : unsigned(4 downto 0);
|
||||
variable do_count_15 : std_logic;
|
||||
variable do_count_5 : std_logic;
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
cur_state := state_array(0)(1 downto 0);
|
||||
cur_env := state_array(0)(9 downto 2);
|
||||
cur_pre15 := state_array(0)(24 downto 10);
|
||||
cur_pre5 := state_array(0)(29 downto 25);
|
||||
|
||||
voice_o <= voice_i;
|
||||
enable_o <= enable_i;
|
||||
|
||||
next_state := cur_state;
|
||||
next_env := cur_env;
|
||||
next_pre15 := cur_pre15;
|
||||
next_pre5 := cur_pre5;
|
||||
|
||||
|
||||
-- PRESCALER LOGIC, output: do_count --
|
||||
-- 15 bit prescaler select --
|
||||
case cur_state is
|
||||
when st_attack =>
|
||||
presc_select := to_integer(unsigned(attack));
|
||||
when st_decay =>
|
||||
presc_select := to_integer(unsigned(decay));
|
||||
when others => -- includes release and idle
|
||||
presc_select := to_integer(unsigned(release));
|
||||
end case;
|
||||
presc_val := prescalers(presc_select)(14 downto 0);
|
||||
|
||||
-- 15 bit prescaler counter --
|
||||
do_count_15 := '0';
|
||||
if cur_pre15 = presc_val then
|
||||
next_pre15 := (others => '0');
|
||||
do_count_15 := '1';
|
||||
else
|
||||
next_pre15 := cur_pre15 + 1;
|
||||
end if;
|
||||
|
||||
-- 5 bit prescaler --
|
||||
log_div := logarithmic(cur_env);
|
||||
do_count_5 := '0';
|
||||
if do_count_15='1' then
|
||||
if (cur_state = st_attack) or cur_pre5 = log_div then
|
||||
next_pre5 := "00000";
|
||||
do_count_5 := '1';
|
||||
else
|
||||
next_pre5 := cur_pre5 + 1;
|
||||
end if;
|
||||
end if;
|
||||
-- END PRESCALER LOGIC --
|
||||
|
||||
case cur_state is
|
||||
|
||||
when st_attack =>
|
||||
if gate = '0' then
|
||||
next_state := st_release;
|
||||
elsif cur_env = X"FF" then
|
||||
next_state := st_decay;
|
||||
end if;
|
||||
|
||||
if do_count_15='1' then
|
||||
next_env := cur_env + 1;
|
||||
-- if cur_env = X"FE" or cur_env = X"FF" then -- result could be FF, but also 00!!
|
||||
-- next_state := st_decay;
|
||||
-- end if;
|
||||
end if;
|
||||
|
||||
when st_decay =>
|
||||
if gate = '0' then
|
||||
next_state := st_release;
|
||||
end if;
|
||||
|
||||
if do_count_15='1' and do_count_5='1' and
|
||||
std_logic_vector(cur_env) /= (sustain & sustain) and
|
||||
cur_env /= X"00" then
|
||||
next_env := cur_env - 1;
|
||||
end if;
|
||||
|
||||
when st_release =>
|
||||
if gate = '1' then
|
||||
next_state := st_attack;
|
||||
end if;
|
||||
|
||||
if do_count_15='1' and do_count_5='1' and
|
||||
cur_env /= X"00" then
|
||||
next_env := cur_env - 1;
|
||||
end if;
|
||||
|
||||
when others =>
|
||||
next_state := st_release;
|
||||
|
||||
end case;
|
||||
|
||||
if enable_i='1' then
|
||||
state_array(0 to g_num_voices-2) <= state_array(1 to g_num_voices-1);
|
||||
state_array(g_num_voices-1) <= next_pre5 & next_pre15 & next_env & next_state;
|
||||
enveloppe <= next_env;
|
||||
state <= next_state;
|
||||
end if;
|
||||
|
||||
if reset='1' then
|
||||
state <= "00";
|
||||
enveloppe <= (others => '0');
|
||||
enable_o <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end gideon;
|
||||
209
cores/c16/sid/mult_acc.vhd
Normal file
209
cores/c16/sid/mult_acc.vhd
Normal file
@@ -0,0 +1,209 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.my_math_pkg.all;
|
||||
|
||||
entity mult_acc is
|
||||
port (
|
||||
clock : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
voice_i : in unsigned(3 downto 0);
|
||||
enable_i : in std_logic;
|
||||
voice3_off_l : in std_logic;
|
||||
voice3_off_r : in std_logic;
|
||||
|
||||
filter_en : in std_logic := '0';
|
||||
|
||||
enveloppe : in unsigned(7 downto 0);
|
||||
waveform : in unsigned(11 downto 0);
|
||||
|
||||
--
|
||||
osc3 : out std_logic_vector(7 downto 0);
|
||||
env3 : out std_logic_vector(7 downto 0);
|
||||
|
||||
--
|
||||
valid_out : out std_logic;
|
||||
|
||||
direct_out_L : out signed(17 downto 0);
|
||||
direct_out_R : out signed(17 downto 0);
|
||||
|
||||
filter_out_L : out signed(17 downto 0);
|
||||
filter_out_R : out signed(17 downto 0) );
|
||||
end mult_acc;
|
||||
|
||||
-- architecture unsigned_wave of mult_acc is
|
||||
-- signal filter_m : std_logic;
|
||||
-- signal voice_m : unsigned(3 downto 0);
|
||||
-- signal mult_m : unsigned(19 downto 0);
|
||||
-- signal accu_f : unsigned(17 downto 0);
|
||||
-- signal accu_u : unsigned(17 downto 0);
|
||||
-- signal enable_d : std_logic;
|
||||
-- signal direct_i : unsigned(17 downto 0);
|
||||
-- signal filter_i : unsigned(17 downto 0);
|
||||
-- begin
|
||||
-- process(clock)
|
||||
-- variable mult_ext : unsigned(21 downto 0);
|
||||
-- variable mult_trunc : unsigned(21 downto 4);
|
||||
-- begin
|
||||
-- if rising_edge(clock) then
|
||||
-- -- latch outputs
|
||||
-- if reset='1' then
|
||||
-- osc3 <= (others => '0');
|
||||
-- env3 <= (others => '0');
|
||||
-- elsif voice_i = X"2" then
|
||||
-- osc3 <= std_logic_vector(waveform(11 downto 4));
|
||||
-- env3 <= std_logic_vector(enveloppe);
|
||||
-- end if;
|
||||
--
|
||||
-- mult_ext := extend(mult_m, mult_ext'length);
|
||||
-- mult_trunc := mult_ext(mult_trunc'range);
|
||||
-- filter_m <= filter_en;
|
||||
-- voice_m <= voice_i;
|
||||
-- mult_m <= enveloppe * waveform;
|
||||
-- valid_out <= '0';
|
||||
-- enable_d <= enable_i;
|
||||
--
|
||||
-- if enable_d='1' then
|
||||
-- if voice_m = 0 then
|
||||
-- valid_out <= '1';
|
||||
-- direct_i <= accu_u;
|
||||
-- filter_i <= accu_f;
|
||||
-- if filter_m='1' then
|
||||
-- accu_f <= mult_trunc;
|
||||
-- accu_u <= (others => '0');
|
||||
-- else
|
||||
-- accu_f <= (others => '0');
|
||||
-- accu_u <= mult_trunc;
|
||||
-- end if;
|
||||
-- else
|
||||
-- valid_out <= '0';
|
||||
-- if filter_m='1' then
|
||||
-- accu_f <= sum_limit(accu_f, mult_trunc);
|
||||
-- else
|
||||
-- if (voice_m /= 2) or (voice3_off = '0') then
|
||||
-- accu_u <= sum_limit(accu_u, mult_trunc);
|
||||
-- end if;
|
||||
-- end if;
|
||||
-- end if;
|
||||
-- end if;
|
||||
--
|
||||
-- if reset = '1' then
|
||||
-- valid_out <= '0';
|
||||
-- accu_u <= (others => '0');
|
||||
-- accu_f <= (others => '0');
|
||||
-- direct_i <= (others => '0');
|
||||
-- filter_i <= (others => '0');
|
||||
-- end if;
|
||||
-- end if;
|
||||
-- end process;
|
||||
--
|
||||
-- direct_out <= '0' & signed(direct_i(17 downto 1));
|
||||
-- filter_out <= '0' & signed(filter_i(17 downto 1));
|
||||
-- end unsigned_wave;
|
||||
--
|
||||
|
||||
architecture signed_wave of mult_acc is
|
||||
signal filter_m : std_logic;
|
||||
signal voice_m : unsigned(3 downto 0);
|
||||
signal mult_m : signed(20 downto 0);
|
||||
signal accu_fl : signed(17 downto 0);
|
||||
signal accu_fr : signed(17 downto 0);
|
||||
signal accu_ul : signed(17 downto 0);
|
||||
signal accu_ur : signed(17 downto 0);
|
||||
signal enable_d : std_logic;
|
||||
begin
|
||||
process(clock)
|
||||
variable mult_ext : signed(21 downto 0);
|
||||
variable mult_trunc : signed(21 downto 4);
|
||||
variable env_signed : signed(8 downto 0);
|
||||
variable wave_signed: signed(11 downto 0);
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
-- latch outputs
|
||||
if reset='1' then
|
||||
osc3 <= (others => '0');
|
||||
env3 <= (others => '0');
|
||||
elsif voice_i = X"2" then
|
||||
osc3 <= std_logic_vector(waveform(11 downto 4));
|
||||
env3 <= std_logic_vector(enveloppe);
|
||||
end if;
|
||||
|
||||
env_signed := '0' & signed(enveloppe);
|
||||
wave_signed := not waveform(11) & signed(waveform(10 downto 0));
|
||||
|
||||
mult_ext := extend(mult_m, mult_ext'length);
|
||||
mult_trunc := mult_ext(mult_trunc'range);
|
||||
filter_m <= filter_en;
|
||||
voice_m <= voice_i;
|
||||
mult_m <= env_signed * wave_signed;
|
||||
valid_out <= '0';
|
||||
enable_d <= enable_i;
|
||||
if enable_d='1' then
|
||||
if voice_m = 0 then
|
||||
valid_out <= '1';
|
||||
direct_out_l <= accu_ul;
|
||||
direct_out_r <= accu_ur;
|
||||
filter_out_l <= accu_fl;
|
||||
filter_out_r <= accu_fr;
|
||||
accu_fr <= (others => '0');
|
||||
accu_ur <= (others => '0');
|
||||
if filter_m='1' then
|
||||
accu_fl <= mult_trunc;
|
||||
accu_ul <= (others => '0');
|
||||
else
|
||||
accu_fl <= (others => '0');
|
||||
accu_ul <= mult_trunc;
|
||||
end if;
|
||||
elsif voice_m(3)='0' then
|
||||
valid_out <= '0';
|
||||
if filter_m='1' then
|
||||
accu_fl <= sum_limit(accu_fl, mult_trunc);
|
||||
else
|
||||
if (voice_m /= 2) or (voice3_off_l = '0') then
|
||||
accu_ul <= sum_limit(accu_ul, mult_trunc);
|
||||
end if;
|
||||
end if;
|
||||
else -- upper 8 voices go to right
|
||||
valid_out <= '0';
|
||||
if filter_m='1' then
|
||||
accu_fr <= sum_limit(accu_fr, mult_trunc);
|
||||
else
|
||||
if (voice_m /= 10) or (voice3_off_r = '0') then
|
||||
accu_ur <= sum_limit(accu_ur, mult_trunc);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
if reset = '1' then
|
||||
valid_out <= '0';
|
||||
accu_ul <= (others => '0');
|
||||
accu_fl <= (others => '0');
|
||||
accu_ur <= (others => '0');
|
||||
accu_fr <= (others => '0');
|
||||
direct_out_l <= (others => '0');
|
||||
direct_out_r <= (others => '0');
|
||||
filter_out_l <= (others => '0');
|
||||
filter_out_r <= (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
end signed_wave;
|
||||
120
cores/c16/sid/my_math_pkg.vhd
Normal file
120
cores/c16/sid/my_math_pkg.vhd
Normal file
@@ -0,0 +1,120 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
package my_math_pkg is
|
||||
|
||||
function sum_limit(i1, i2 : signed) return signed;
|
||||
function sub_limit(i1, i2 : signed) return signed;
|
||||
function sum_limit(i1, i2 : unsigned) return unsigned;
|
||||
function extend(x : signed; len : natural) return signed;
|
||||
function extend(x : unsigned; len : natural) return unsigned;
|
||||
function left_align(x : signed; len : natural) return signed;
|
||||
function left_scale(x : signed; sh : natural) return signed;
|
||||
|
||||
-- function shift_right(x : signed; positions: natural) return signed;
|
||||
end;
|
||||
|
||||
package body my_math_pkg is
|
||||
|
||||
function sum_limit(i1, i2 : signed) return signed is
|
||||
variable o : signed(i1'range);
|
||||
begin
|
||||
assert i1'length = i2'length
|
||||
report "i1 and i2 should have the same length!"
|
||||
severity failure;
|
||||
o := i1 + i2;
|
||||
if (i1(i1'left) = i2(i2'left)) and (o(o'left) /= i1(i1'left)) then
|
||||
if i1(i1'left)='1' then
|
||||
o := to_signed(-(2**(o'length-1)), o'length);
|
||||
else
|
||||
o := to_signed(2**(o'length-1) - 1, o'length);
|
||||
end if;
|
||||
end if;
|
||||
return o;
|
||||
end function;
|
||||
|
||||
function sub_limit(i1, i2 : signed) return signed is
|
||||
variable o : signed(i1'range);
|
||||
begin
|
||||
assert i1'length = i2'length
|
||||
report "i1 and i2 should have the same length!"
|
||||
severity failure;
|
||||
o := i1 - i2;
|
||||
if (i1(i1'left) /= i2(i2'left)) and (o(o'left) /= i1(i1'left)) then
|
||||
if i1(i1'left)='1' then
|
||||
o := to_signed(-(2**(o'length-1)), o'length);
|
||||
else
|
||||
o := to_signed(2**(o'length-1) - 1, o'length);
|
||||
end if;
|
||||
end if;
|
||||
return o;
|
||||
end function;
|
||||
|
||||
function sum_limit(i1, i2 : unsigned) return unsigned is
|
||||
variable o : unsigned(i1'length downto 0);
|
||||
begin
|
||||
o := ('0' & i1) + i2;
|
||||
if o(o'left)='1' then
|
||||
o := (others => '1');
|
||||
end if;
|
||||
return o(i1'length-1 downto 0);
|
||||
end function;
|
||||
|
||||
function extend(x : signed; len : natural) return signed is
|
||||
variable ret : signed(len-1 downto 0);
|
||||
alias a : signed(x'length-1 downto 0) is x;
|
||||
begin
|
||||
ret := (others => x(x'left));
|
||||
ret(a'range) := a;
|
||||
return ret;
|
||||
end function extend;
|
||||
|
||||
function extend(x : unsigned; len : natural) return unsigned is
|
||||
variable ret : unsigned(len-1 downto 0);
|
||||
alias a : unsigned(x'length-1 downto 0) is x;
|
||||
begin
|
||||
ret := (others => '0');
|
||||
ret(a'range) := a;
|
||||
return ret;
|
||||
end function extend;
|
||||
|
||||
function left_align(x : signed; len : natural) return signed is
|
||||
variable ret : signed(len-1 downto 0);
|
||||
begin
|
||||
ret := (others => '0');
|
||||
ret(len-1 downto len-x'length) := x;
|
||||
return ret;
|
||||
end function left_align;
|
||||
|
||||
function left_scale(x : signed; sh : natural) return signed is
|
||||
alias a : signed(x'length-1 downto 0) is x;
|
||||
variable ret : signed(x'length-(1+sh) downto 0);
|
||||
variable top : signed(sh downto 0);
|
||||
begin
|
||||
if sh=0 then
|
||||
return x;
|
||||
end if;
|
||||
|
||||
top := a(a'high downto a'high-sh);
|
||||
if (top = -1) or (top = 0) then -- can shift without getting punished!
|
||||
ret := a(ret'range);
|
||||
elsif a(a'high)='1' then -- negative and can't shift, so max neg:
|
||||
ret := (others => '0');
|
||||
ret(ret'high) := '1';
|
||||
else -- positive and can't shift, so max pos
|
||||
ret := (others => '1');
|
||||
ret(ret'high) := '0';
|
||||
end if;
|
||||
return ret;
|
||||
end function left_scale;
|
||||
|
||||
-- function shift_right(x : signed; positions: natural) return signed is
|
||||
-- alias a : signed(x'length-1 downto 0) is x;
|
||||
-- variable ret : signed(x'length-1 downto 0);
|
||||
-- begin
|
||||
-- ret := (others => x(x'left));
|
||||
-- ret(a'left-positions downto 0) := a(a'left downto positions);
|
||||
-- return ret;
|
||||
-- end function shift_right;
|
||||
end;
|
||||
92
cores/c16/sid/oscillator.vhd
Normal file
92
cores/c16/sid/oscillator.vhd
Normal file
@@ -0,0 +1,92 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity oscillator is
|
||||
generic (
|
||||
g_num_voices : integer := 8);
|
||||
port (
|
||||
clock : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
enable_i : in std_logic;
|
||||
voice_i : in unsigned(3 downto 0);
|
||||
freq : in unsigned(15 downto 0);
|
||||
test : in std_logic := '0';
|
||||
sync : in std_logic := '0';
|
||||
|
||||
voice_o : out unsigned(3 downto 0);
|
||||
enable_o : out std_logic;
|
||||
test_o : out std_logic;
|
||||
osc_val : out unsigned(23 downto 0);
|
||||
carry_20 : out std_logic;
|
||||
msb_other: out std_logic );
|
||||
|
||||
end oscillator;
|
||||
|
||||
|
||||
architecture Gideon of oscillator is
|
||||
type accu_array_t is array (natural range <>) of unsigned(23 downto 0);
|
||||
signal accu_reg : accu_array_t(0 to g_num_voices-1) := (others => (others => '0'));
|
||||
|
||||
type int4_array is array (natural range <>) of integer range 0 to 15;
|
||||
|
||||
constant voice_linkage : int4_array(0 to 15) := ( 2, 0, 1, 7, 3, 4, 5, 6,
|
||||
10, 8, 9, 15, 11, 12, 13, 14 );
|
||||
|
||||
signal ring_index : integer range 0 to 15;
|
||||
signal sync_index : integer range 0 to 15;
|
||||
signal msb_register : std_logic_vector(0 to 15) := (others => '0');
|
||||
signal car_register : std_logic_vector(0 to 15) := (others => '0');
|
||||
signal do_sync : std_logic;
|
||||
begin
|
||||
sync_index <= voice_linkage(to_integer(voice_i));
|
||||
do_sync <= sync and car_register(sync_index);
|
||||
ring_index <= voice_linkage(to_integer(voice_i));
|
||||
|
||||
process(clock)
|
||||
variable cur_accu : unsigned(23 downto 0);
|
||||
variable new_accu : unsigned(24 downto 0);
|
||||
variable cur_20 : std_logic;
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
cur_accu := accu_reg(0);
|
||||
cur_20 := cur_accu(20);
|
||||
|
||||
if reset='1' or test='1' or do_sync='1' then
|
||||
new_accu := (others => '0');
|
||||
else
|
||||
new_accu := ('0' & cur_accu) + freq;
|
||||
end if;
|
||||
|
||||
osc_val <= new_accu(23 downto 0);
|
||||
-- carry <= new_accu(24);
|
||||
carry_20 <= new_accu(20) xor cur_20;
|
||||
msb_other <= msb_register(ring_index);
|
||||
voice_o <= voice_i;
|
||||
enable_o <= enable_i;
|
||||
test_o <= test;
|
||||
|
||||
if enable_i='1' then
|
||||
accu_reg(0 to g_num_voices-2) <= accu_reg(1 to g_num_voices-1);
|
||||
accu_reg(g_num_voices-1) <= new_accu(23 downto 0);
|
||||
|
||||
car_register(to_integer(voice_i)) <= new_accu(24);
|
||||
msb_register(to_integer(voice_i)) <= cur_accu(23);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end Gideon;
|
||||
58
cores/c16/sid/sid_ctrl.vhd
Normal file
58
cores/c16/sid/sid_ctrl.vhd
Normal file
@@ -0,0 +1,58 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity sid_ctrl is
|
||||
generic (
|
||||
g_num_voices : natural := 8 );
|
||||
port (
|
||||
clock : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
start_iter : in std_logic;
|
||||
|
||||
voice_osc : out unsigned(3 downto 0);
|
||||
enable_osc : out std_logic );
|
||||
|
||||
end sid_ctrl;
|
||||
|
||||
architecture gideon of sid_ctrl is
|
||||
|
||||
signal voice_cnt : unsigned(3 downto 0);
|
||||
signal enable : std_logic;
|
||||
|
||||
begin
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
if reset='1' then
|
||||
voice_cnt <= X"0";
|
||||
enable <= '0';
|
||||
elsif start_iter='1' then
|
||||
voice_cnt <= X"0";
|
||||
enable <= '1';
|
||||
elsif voice_cnt = g_num_voices-1 then
|
||||
voice_cnt <= X"0";
|
||||
enable <= '0';
|
||||
elsif enable='1' then
|
||||
voice_cnt <= voice_cnt + 1;
|
||||
enable <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
voice_osc <= voice_cnt;
|
||||
enable_osc <= enable;
|
||||
end gideon;
|
||||
35
cores/c16/sid/sid_debug_pkg.vhd
Normal file
35
cores/c16/sid/sid_debug_pkg.vhd
Normal file
@@ -0,0 +1,35 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
package sid_debug_pkg is
|
||||
|
||||
type t_voice_debug is record
|
||||
state : unsigned(1 downto 0);
|
||||
enveloppe : unsigned(7 downto 0);
|
||||
pre15 : unsigned(14 downto 0);
|
||||
pre5 : unsigned(4 downto 0);
|
||||
presc : unsigned(14 downto 0);
|
||||
gate : std_logic;
|
||||
attack : std_logic_vector(3 downto 0);
|
||||
decay : std_logic_vector(3 downto 0);
|
||||
sustain : std_logic_vector(3 downto 0);
|
||||
release : std_logic_vector(3 downto 0);
|
||||
end record;
|
||||
|
||||
type t_voice_debug_array is array(natural range <>) of t_voice_debug;
|
||||
|
||||
end;
|
||||
309
cores/c16/sid/sid_filter.vhd
Normal file
309
cores/c16/sid/sid_filter.vhd
Normal file
@@ -0,0 +1,309 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.my_math_pkg.all;
|
||||
|
||||
entity sid_filter is
|
||||
generic (
|
||||
g_divider : natural := 221 );
|
||||
port (
|
||||
clock : in std_logic;
|
||||
reset : in std_logic;
|
||||
enable : in std_logic;
|
||||
|
||||
filt_co : in unsigned(10 downto 0);
|
||||
filt_res : in unsigned(3 downto 0);
|
||||
|
||||
valid_in : in std_logic := '0';
|
||||
error_out : out std_logic;
|
||||
input : in signed(17 downto 0);
|
||||
high_pass : out signed(17 downto 0);
|
||||
band_pass : out signed(17 downto 0);
|
||||
low_pass : out signed(17 downto 0);
|
||||
|
||||
valid_out : out std_logic );
|
||||
end sid_filter;
|
||||
|
||||
architecture dsvf of sid_filter is
|
||||
signal filter_q : signed(17 downto 0);
|
||||
signal filter_f : signed(17 downto 0);
|
||||
signal input_sc : signed(17 downto 0);
|
||||
signal filt_ram : std_logic_vector(15 downto 0);
|
||||
signal xa : signed(17 downto 0);
|
||||
signal xb : signed(17 downto 0);
|
||||
signal sum_b : signed(17 downto 0);
|
||||
signal sub_a : signed(17 downto 0);
|
||||
signal sub_b : signed(17 downto 0);
|
||||
signal x_reg : signed(17 downto 0) := (others => '0');
|
||||
signal bp_reg : signed(17 downto 0);
|
||||
signal hp_reg : signed(17 downto 0);
|
||||
signal lp_reg : signed(17 downto 0);
|
||||
signal temp_reg : signed(17 downto 0);
|
||||
signal error : std_logic := '0';
|
||||
signal divider : integer range 0 to g_divider-1;
|
||||
|
||||
signal instruction : std_logic_vector(7 downto 0);
|
||||
type t_byte_array is array(natural range <>) of std_logic_vector(7 downto 0);
|
||||
constant c_program : t_byte_array := (X"80", X"12", X"81", X"4C", X"82", X"20");
|
||||
|
||||
type t_word_array is array(1023 downto 0) of signed(15 downto 0);
|
||||
constant coef : t_word_array :=
|
||||
(
|
||||
X"fff6", X"ffe5", X"ffd4", X"ffc3", X"ffb2", X"ffa0", X"ff8f", X"ff7e",
|
||||
X"ff6d", X"ff5c", X"ff4a", X"ff39", X"ff28", X"ff17", X"ff06", X"fef4",
|
||||
X"fee3", X"fed2", X"fec1", X"feb0", X"fe9e", X"fe8d", X"fe7c", X"fe6b",
|
||||
X"fe5a", X"fe48", X"fe37", X"fe26", X"fe15", X"fe04", X"fdf2", X"fde1",
|
||||
X"fdd0", X"fdbf", X"fdae", X"fd9c", X"fd8b", X"fd7a", X"fd69", X"fd58",
|
||||
X"fd46", X"fd35", X"fd24", X"fd13", X"fd02", X"fcf0", X"fcdf", X"fcce",
|
||||
X"fcbd", X"fcac", X"fc9a", X"fc89", X"fc78", X"fc67", X"fc56", X"fc44",
|
||||
X"fc33", X"fc22", X"fc11", X"fc00", X"fbee", X"fbdd", X"fbcc", X"fbbb",
|
||||
X"fb99", X"fb76", X"fb54", X"fb32", X"fb10", X"faee", X"facc", X"faaa",
|
||||
X"fa88", X"fa65", X"fa43", X"fa21", X"f9ff", X"f9dd", X"f9bb", X"f999",
|
||||
X"f976", X"f954", X"f932", X"f910", X"f8ee", X"f8cc", X"f8aa", X"f888",
|
||||
X"f865", X"f843", X"f821", X"f7ff", X"f7dd", X"f7bb", X"f799", X"f776",
|
||||
X"f754", X"f732", X"f710", X"f6ee", X"f6cc", X"f6aa", X"f688", X"f665",
|
||||
X"f643", X"f621", X"f5ff", X"f5dd", X"f5bb", X"f599", X"f576", X"f554",
|
||||
X"f532", X"f510", X"f4ee", X"f4cc", X"f4aa", X"f488", X"f465", X"f443",
|
||||
X"f421", X"f3ff", X"f3dd", X"f3bb", X"f399", X"f376", X"f354", X"f332",
|
||||
X"f2f4", X"f2b5", X"f276", X"f238", X"f1f9", X"f1bb", X"f17c", X"f13e",
|
||||
X"f0ff", X"f0c0", X"f082", X"f043", X"f005", X"efc6", X"ef88", X"ef49",
|
||||
X"ef0a", X"eecc", X"ee8d", X"ee4f", X"ee10", X"edd2", X"ed93", X"ed54",
|
||||
X"ed16", X"ecd7", X"ec99", X"ec5a", X"ec1b", X"ebdd", X"eb9e", X"eb60",
|
||||
X"eb21", X"eae3", X"eaa4", X"ea65", X"ea27", X"e9e8", X"e9aa", X"e96b",
|
||||
X"e92d", X"e8ee", X"e8af", X"e871", X"e832", X"e7f4", X"e7b5", X"e777",
|
||||
X"e738", X"e6f9", X"e6bb", X"e67c", X"e63e", X"e5ff", X"e5c0", X"e582",
|
||||
X"e543", X"e505", X"e4c6", X"e488", X"e449", X"e40a", X"e3cc", X"e38d",
|
||||
X"e338", X"e2e3", X"e28d", X"e238", X"e1e3", X"e18d", X"e138", X"e0e3",
|
||||
X"e08d", X"e038", X"dfe3", X"df8d", X"df38", X"dee3", X"de8d", X"de38",
|
||||
X"dde3", X"dd8d", X"dd38", X"dce3", X"dc8d", X"dc38", X"dbe3", X"db8d",
|
||||
X"db38", X"dae3", X"da8d", X"da38", X"d9e3", X"d98d", X"d938", X"d8e3",
|
||||
X"d88d", X"d838", X"d7e3", X"d78d", X"d738", X"d6e3", X"d68d", X"d638",
|
||||
X"d5e3", X"d58d", X"d538", X"d4e3", X"d48d", X"d438", X"d3e3", X"d38d",
|
||||
X"d338", X"d2e3", X"d28d", X"d238", X"d1e3", X"d18d", X"d138", X"d0e3",
|
||||
X"d08d", X"d038", X"cfe3", X"cf8d", X"cf38", X"cee3", X"ce8d", X"ce38",
|
||||
X"cdaa", X"cd1c", X"cc8d", X"cbff", X"cb71", X"cae3", X"ca54", X"c9c6",
|
||||
X"c938", X"c8aa", X"c81c", X"c78d", X"c6ff", X"c671", X"c5e3", X"c554",
|
||||
X"c4c6", X"c438", X"c3aa", X"c31c", X"c28d", X"c1ff", X"c171", X"c0e3",
|
||||
X"c054", X"bfc6", X"bf38", X"beaa", X"be1c", X"bd8d", X"bcff", X"bc71",
|
||||
X"bbe3", X"bb54", X"bac6", X"ba38", X"b9aa", X"b91c", X"b88d", X"b7ff",
|
||||
X"b771", X"b6e3", X"b654", X"b5c6", X"b538", X"b4aa", X"b41c", X"b38d",
|
||||
X"b2ff", X"b271", X"b1e3", X"b154", X"b0c6", X"b038", X"afaa", X"af1c",
|
||||
X"ae8d", X"adff", X"ad71", X"ace3", X"ac54", X"abc6", X"ab38", X"aaaa",
|
||||
X"aa1c", X"a98d", X"a8ff", X"a871", X"a7e3", X"a755", X"a6c6", X"a638",
|
||||
X"a5aa", X"a51c", X"a48d", X"a3ff", X"a371", X"a2e3", X"a255", X"a1c6",
|
||||
X"a138", X"a0aa", X"a01c", X"9f8d", X"9eff", X"9e71", X"9de3", X"9d55",
|
||||
X"9cc6", X"9c38", X"9baa", X"9b1c", X"9a8d", X"99ff", X"9971", X"98e3",
|
||||
X"9855", X"97c6", X"9738", X"96aa", X"961c", X"958d", X"94ff", X"9471",
|
||||
X"93e3", X"9355", X"92c6", X"9238", X"91aa", X"911c", X"908d", X"8fff",
|
||||
X"8f71", X"8ee3", X"8e55", X"8dc6", X"8d38", X"8caa", X"8c1c", X"8b8d",
|
||||
X"8aff", X"8a71", X"89e3", X"8955", X"88c6", X"8838", X"87aa", X"871c",
|
||||
X"8699", X"8616", X"8593", X"8510", X"848d", X"840b", X"8388", X"8305",
|
||||
X"8282", X"81ff", X"817c", X"80fa", X"8077", X"7ff4", X"7f71", X"7eee",
|
||||
X"7e6b", X"7de8", X"7d66", X"7ce3", X"7c60", X"7bdd", X"7b5a", X"7ad7",
|
||||
X"7a55", X"79d2", X"794f", X"78cc", X"7849", X"77c6", X"7744", X"76c1",
|
||||
X"763e", X"75bb", X"7538", X"74b5", X"7432", X"73b0", X"732d", X"72aa",
|
||||
X"7227", X"71a4", X"7121", X"709f", X"701c", X"6f99", X"6f16", X"6e93",
|
||||
X"6e10", X"6d8e", X"6d0b", X"6c88", X"6c05", X"6b82", X"6aff", X"6a7c",
|
||||
X"69fa", X"6977", X"68f4", X"6871", X"67ee", X"676b", X"66e9", X"6666",
|
||||
X"65dd", X"6555", X"64cc", X"6444", X"63bb", X"6333", X"62aa", X"6221",
|
||||
X"6199", X"6110", X"6088", X"5fff", X"5f77", X"5eee", X"5e66", X"5ddd",
|
||||
X"5d55", X"5ccc", X"5c44", X"5bbb", X"5b33", X"5aaa", X"5a21", X"5999",
|
||||
X"5910", X"5888", X"57ff", X"5777", X"56ee", X"5666", X"55dd", X"5555",
|
||||
X"54b5", X"5416", X"5377", X"52d8", X"5238", X"5199", X"50fa", X"505a",
|
||||
X"4fbb", X"4f1c", X"4e7d", X"4ddd", X"4d3e", X"4c9f", X"4bff", X"4b60",
|
||||
X"4ac8", X"4a31", X"4999", X"4901", X"486a", X"47d2", X"473a", X"46a2",
|
||||
X"460b", X"4573", X"44db", X"4444", X"438e", X"42d8", X"4222", X"416b",
|
||||
X"54b9", X"5381", X"5248", X"5110", X"4fff", X"4eee", X"4ddd", X"4ccc",
|
||||
X"4c16", X"4b60", X"4aaa", X"49f4", X"493e", X"4888", X"47d2", X"471c",
|
||||
X"467d", X"45dd", X"453e", X"449f", X"43ff", X"4360", X"42c1", X"4222",
|
||||
X"4182", X"40e3", X"4044", X"3fa4", X"3f05", X"3e66", X"3dc6", X"3d27",
|
||||
X"3caa", X"3c2d", X"3bb0", X"3b33", X"3ab5", X"3a38", X"39bb", X"393e",
|
||||
X"38c1", X"3844", X"37c7", X"3749", X"36cc", X"364f", X"35d2", X"3555",
|
||||
X"34d8", X"345a", X"33dd", X"3360", X"32e3", X"3266", X"31e9", X"316b",
|
||||
X"30ee", X"3071", X"2ff4", X"2f77", X"2efa", X"2e7d", X"2dff", X"2d82",
|
||||
X"2d1c", X"2cb5", X"2c4f", X"2be9", X"2b82", X"2b1c", X"2ab5", X"2a4f",
|
||||
X"29e9", X"2982", X"291c", X"28b5", X"284f", X"27e9", X"2782", X"271c",
|
||||
X"26b5", X"264f", X"25e9", X"2582", X"251c", X"24b5", X"244f", X"23e9",
|
||||
X"2382", X"231c", X"22b5", X"224f", X"21e9", X"2182", X"211c", X"20b5",
|
||||
X"2066", X"2016", X"1fc7", X"1f77", X"1f27", X"1ed8", X"1e88", X"1e38",
|
||||
X"1de9", X"1d99", X"1d49", X"1cfa", X"1caa", X"1c5a", X"1c0b", X"1bbb",
|
||||
X"1b6c", X"1b1c", X"1acc", X"1a7d", X"1a2d", X"19dd", X"198e", X"193e",
|
||||
X"18ee", X"189f", X"184f", X"17ff", X"17b0", X"1760", X"1711", X"16c1",
|
||||
X"1692", X"1664", X"1635", X"1606", X"15d8", X"15a9", X"157a", X"154c",
|
||||
X"151d", X"14ee", X"14c0", X"1491", X"1462", X"1434", X"1405", X"13d7",
|
||||
X"13a8", X"1379", X"134b", X"131c", X"12ed", X"12bf", X"1290", X"1261",
|
||||
X"1233", X"1204", X"11d5", X"11a7", X"1178", X"1149", X"111b", X"10ec",
|
||||
X"10bd", X"108f", X"1060", X"1032", X"1003", X"0fd4", X"0fa6", X"0f77",
|
||||
X"0f48", X"0f1a", X"0eeb", X"0ebc", X"0e8e", X"0e5f", X"0e30", X"0e02",
|
||||
X"0dd3", X"0da4", X"0d76", X"0d47", X"0d19", X"0cea", X"0cbb", X"0c8d",
|
||||
X"0c5e", X"0c2f", X"0c01", X"0bd2", X"0ba3", X"0b75", X"0b46", X"0b17",
|
||||
X"0b03", X"0aee", X"0ada", X"0ac5", X"0ab1", X"0a9c", X"0a88", X"0a74",
|
||||
X"0a5f", X"0a4b", X"0a36", X"0a22", X"0a0d", X"09f9", X"09e4", X"09d0",
|
||||
X"09bb", X"09a7", X"0992", X"097e", X"0969", X"0955", X"0940", X"092c",
|
||||
X"0917", X"0903", X"08ee", X"08da", X"08c5", X"08b1", X"089c", X"0888",
|
||||
X"0874", X"085f", X"084b", X"0836", X"0822", X"080d", X"07f9", X"07e4",
|
||||
X"07d0", X"07bb", X"07a7", X"0792", X"077e", X"0769", X"0755", X"0740",
|
||||
X"072c", X"0717", X"0703", X"06ee", X"06da", X"06c5", X"06b1", X"069d",
|
||||
X"0688", X"0674", X"065f", X"064b", X"0636", X"0622", X"060d", X"05f9",
|
||||
X"05f2", X"05eb", X"05e4", X"05dd", X"05d7", X"05d0", X"05c9", X"05c2",
|
||||
X"05bb", X"05b4", X"05ae", X"05a7", X"05a0", X"0599", X"0592", X"058b",
|
||||
X"0585", X"057e", X"0577", X"0570", X"0569", X"0562", X"055c", X"0555",
|
||||
X"054e", X"0547", X"0540", X"053a", X"0533", X"052c", X"0525", X"051e",
|
||||
X"0517", X"0511", X"050a", X"0503", X"04fc", X"04f5", X"04ee", X"04e8",
|
||||
X"04e1", X"04da", X"04d3", X"04cc", X"04c5", X"04bf", X"04b8", X"04b1",
|
||||
X"04aa", X"04a3", X"049d", X"0496", X"048f", X"0488", X"0481", X"047a",
|
||||
X"0474", X"046d", X"0466", X"045f", X"0458", X"0451", X"044b", X"0444",
|
||||
X"0441", X"043e", X"043b", X"0438", X"0436", X"0433", X"0430", X"042d",
|
||||
X"042a", X"0427", X"0424", X"0422", X"041f", X"041c", X"0419", X"0416",
|
||||
X"0413", X"0411", X"040e", X"040b", X"0408", X"0405", X"0402", X"03ff",
|
||||
X"03fd", X"03fa", X"03f7", X"03f4", X"03f1", X"03ee", X"03ec", X"03e9",
|
||||
X"03e6", X"03e3", X"03e0", X"03dd", X"03db", X"03d8", X"03d5", X"03d2",
|
||||
X"03cf", X"03cc", X"03c9", X"03c7", X"03c4", X"03c1", X"03be", X"03bb",
|
||||
X"03b8", X"03b6", X"03b3", X"03b0", X"03ad", X"03aa", X"03a7", X"03a4",
|
||||
X"03a2", X"039f", X"039c", X"0399", X"0396", X"0393", X"0391", X"038e",
|
||||
X"038d", X"038b", X"038a", X"0389", X"0388", X"0387", X"0386", X"0385",
|
||||
X"0383", X"0382", X"0381", X"0380", X"037f", X"037e", X"037d", X"037c",
|
||||
X"037a", X"0379", X"0378", X"0377", X"0376", X"0375", X"0374", X"0372",
|
||||
X"0371", X"0370", X"036f", X"036e", X"036d", X"036c", X"036a", X"0369",
|
||||
X"0368", X"0367", X"0366", X"0365", X"0364", X"0362", X"0361", X"0360",
|
||||
X"035f", X"035e", X"035d", X"035c", X"035b", X"0359", X"0358", X"0357",
|
||||
X"0356", X"0355", X"0354", X"0353", X"0351", X"0350", X"034f", X"034e",
|
||||
X"034d", X"034c", X"034b", X"0349", X"0348", X"0347", X"0346", X"0345",
|
||||
X"0344", X"0344", X"0343", X"0343", X"0342", X"0341", X"0341", X"0340",
|
||||
X"0340", X"033f", X"033f", X"033e", X"033e", X"033d", X"033c", X"033c",
|
||||
X"033b", X"033b", X"033a", X"033a", X"0339", X"0338", X"0338", X"0337",
|
||||
X"0337", X"0336", X"0336", X"0335", X"0334", X"0334", X"0333", X"0333",
|
||||
X"0332", X"0332", X"0331", X"0330", X"0330", X"032f", X"032f", X"032e",
|
||||
X"032e", X"032d", X"032c", X"032c", X"032b", X"032b", X"032a", X"032a",
|
||||
X"0329", X"0328", X"0328", X"0327", X"0327", X"0326", X"0326", X"0325",
|
||||
X"0324", X"0324", X"0323", X"0323", X"0322", X"0322", X"0321", X"0320"
|
||||
);
|
||||
|
||||
alias xa_select : std_logic is instruction(0);
|
||||
alias xb_select : std_logic is instruction(1);
|
||||
alias sub_a_sel : std_logic is instruction(2);
|
||||
alias sub_b_sel : std_logic is instruction(3);
|
||||
alias sum_to_lp : std_logic is instruction(4);
|
||||
alias sum_to_bp : std_logic is instruction(5);
|
||||
alias sub_to_hp : std_logic is instruction(6);
|
||||
alias mult_enable : std_logic is instruction(7);
|
||||
|
||||
begin
|
||||
-- Derive the actual 'f' and 'q' parameters
|
||||
i_q_table: entity work.Q_table
|
||||
port map (
|
||||
Q_reg => filt_res,
|
||||
filter_q => filter_q ); -- 2.16 format
|
||||
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
if(enable = '1') then
|
||||
filter_f <= "00" & coef(to_integer(filt_co(10 downto 1)));
|
||||
else
|
||||
filter_f <= "001111111111111111";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--input_sc <= input;
|
||||
input_sc <= shift_right(input, 1);
|
||||
|
||||
-- operations to execute the filter:
|
||||
-- bp_f = f * bp_reg
|
||||
-- q_contrib = q * bp_reg
|
||||
-- lp = bp_f + lp_reg
|
||||
-- temp = input - lp
|
||||
-- hp = temp - q_contrib
|
||||
-- hp_f = f * hp
|
||||
-- bp = hp_f + bp_reg
|
||||
-- bp_reg = bp
|
||||
-- lp_reg = lp
|
||||
|
||||
-- x_reg = f * bp_reg -- 10000000 -- 80
|
||||
-- lp_reg = x_reg + lp_reg -- 00010010 -- 12
|
||||
-- q_contrib = q * bp_reg -- 10000001 -- 81
|
||||
-- temp = input - lp -- 00000000 -- 00 (can be merged with previous!)
|
||||
-- hp_reg = temp - q_contrib -- 01001100 -- 4C
|
||||
-- x_reg = f * hp_reg -- 10000010 -- 82
|
||||
-- bp_reg = x_reg + bp_reg -- 00100000 -- 20
|
||||
|
||||
|
||||
-- now perform the arithmetic
|
||||
xa <= filter_f when xa_select='0' else filter_q;
|
||||
xb <= bp_reg when xb_select='0' else hp_reg;
|
||||
sum_b <= bp_reg when xb_select='0' else lp_reg;
|
||||
sub_a <= input_sc when sub_a_sel='0' else temp_reg;
|
||||
sub_b <= lp_reg when sub_b_sel='0' else x_reg;
|
||||
|
||||
process(clock)
|
||||
variable x_result : signed(35 downto 0);
|
||||
variable sum_result : signed(17 downto 0);
|
||||
variable sub_result : signed(17 downto 0);
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
x_result := xa * xb;
|
||||
if mult_enable='1' then
|
||||
x_reg <= x_result(33 downto 16);
|
||||
if (x_result(35 downto 33) /= "000") and (x_result(35 downto 33) /= "111") then
|
||||
error <= not error;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
sum_result := sum_limit(x_reg, sum_b);
|
||||
temp_reg <= sum_result;
|
||||
if sum_to_lp='1' then
|
||||
lp_reg <= sum_result;
|
||||
end if;
|
||||
if sum_to_bp='1' then
|
||||
bp_reg <= sum_result;
|
||||
end if;
|
||||
|
||||
sub_result := sub_limit(sub_a, sub_b);
|
||||
temp_reg <= sub_result;
|
||||
if sub_to_hp='1' then
|
||||
hp_reg <= sub_result;
|
||||
end if;
|
||||
|
||||
-- control part
|
||||
instruction <= (others => '0');
|
||||
if reset='1' then
|
||||
hp_reg <= (others => '0');
|
||||
lp_reg <= (others => '0');
|
||||
bp_reg <= (others => '0');
|
||||
divider <= 0;
|
||||
elsif divider = g_divider-1 then
|
||||
divider <= 0;
|
||||
else
|
||||
divider <= divider + 1;
|
||||
if divider < c_program'length then
|
||||
instruction <= c_program(divider);
|
||||
end if;
|
||||
end if;
|
||||
if divider = c_program'length then
|
||||
valid_out <= '1';
|
||||
else
|
||||
valid_out <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
high_pass <= hp_reg;
|
||||
band_pass <= bp_reg;
|
||||
low_pass <= lp_reg;
|
||||
error_out <= error;
|
||||
end dsvf;
|
||||
115
cores/c16/sid/sid_mixer.vhd
Normal file
115
cores/c16/sid/sid_mixer.vhd
Normal file
@@ -0,0 +1,115 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.my_math_pkg.all;
|
||||
|
||||
entity sid_mixer is
|
||||
port (
|
||||
clock : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
valid_in : in std_logic := '0';
|
||||
|
||||
direct_out : in signed(17 downto 0);
|
||||
high_pass : in signed(17 downto 0);
|
||||
band_pass : in signed(17 downto 0);
|
||||
low_pass : in signed(17 downto 0);
|
||||
|
||||
filter_hp : in std_logic;
|
||||
filter_bp : in std_logic;
|
||||
filter_lp : in std_logic;
|
||||
|
||||
volume : in unsigned(3 downto 0);
|
||||
|
||||
mixed_out : out signed(17 downto 0);
|
||||
valid_out : out std_logic );
|
||||
end sid_mixer;
|
||||
|
||||
architecture arith of sid_mixer is
|
||||
signal mix_i : signed(17 downto 0);
|
||||
signal mix_uns : unsigned(16 downto 0);
|
||||
signal vol_uns : unsigned(16 downto 0);
|
||||
signal vol_s : signed(16 downto 0);
|
||||
signal state : integer range 0 to 7;
|
||||
signal p_mul : unsigned(33 downto 0);
|
||||
signal p_mul_s : signed(34 downto 0);
|
||||
|
||||
type t_volume_lut is array(natural range <>) of unsigned(15 downto 0);
|
||||
constant c_volume_lut : t_volume_lut(0 to 15) := (
|
||||
X"0000", X"0EEF", X"1DDE", X"2CCD", X"3BBC", X"4AAA", X"5999", X"6888",
|
||||
X"7777", X"8666", X"9555", X"A444", X"B333", X"C221", X"D110", X"DFFF" );
|
||||
|
||||
|
||||
begin
|
||||
process(clock)
|
||||
variable mix_total : signed(17 downto 0);
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
valid_out <= '0';
|
||||
|
||||
state <= state + 1;
|
||||
case state is
|
||||
when 0 =>
|
||||
if valid_in = '1' then
|
||||
mix_i <= sum_limit(direct_out, to_signed(16384, 18));
|
||||
else
|
||||
state <= 0;
|
||||
end if;
|
||||
|
||||
when 1 =>
|
||||
if filter_hp='1' then
|
||||
mix_i <= sum_limit(mix_i, high_pass);
|
||||
end if;
|
||||
|
||||
when 2 =>
|
||||
if filter_bp='1' then
|
||||
mix_i <= sum_limit(mix_i, band_pass);
|
||||
end if;
|
||||
|
||||
when 3 =>
|
||||
if filter_lp='1' then
|
||||
mix_i <= sum_limit(mix_i, low_pass);
|
||||
end if;
|
||||
|
||||
when 4 =>
|
||||
-- p_mul <= mix_uns * vol_uns;
|
||||
p_mul_s <= mix_i * vol_s;
|
||||
valid_out <= '1';
|
||||
state <= 0;
|
||||
|
||||
when others =>
|
||||
state <= 0;
|
||||
|
||||
end case;
|
||||
|
||||
-- mix_total := not(p_mul(32)) & signed(p_mul(31 downto 15));
|
||||
-- mixed_out <= mix_total; -- + to_signed(16384, 18);
|
||||
mixed_out <= p_mul_s(33 downto 16);
|
||||
|
||||
if reset='1' then
|
||||
mix_i <= (others => '0');
|
||||
state <= 0;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- vol_uns <= "0" & volume & volume & volume & volume;
|
||||
-- vol_uns <= '0' & c_volume_lut(to_integer(volume));
|
||||
-- mix_uns <= not mix_i(17) & unsigned(mix_i(16 downto 1));
|
||||
|
||||
vol_s <= '0' & signed(c_volume_lut(to_integer(volume)));
|
||||
end arith;
|
||||
253
cores/c16/sid/sid_regs.mister
Normal file
253
cores/c16/sid/sid_regs.mister
Normal file
@@ -0,0 +1,253 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity sid_regs is
|
||||
port (
|
||||
clock : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
addr : in unsigned(7 downto 0);
|
||||
wren : in std_logic;
|
||||
wdata : in std_logic_vector(7 downto 0);
|
||||
rdata : out std_logic_vector(7 downto 0);
|
||||
|
||||
potx : in std_logic_vector(7 downto 0);
|
||||
poty : in std_logic_vector(7 downto 0);
|
||||
|
||||
---
|
||||
comb_wave_l : in std_logic;
|
||||
comb_wave_r : in std_logic;
|
||||
---
|
||||
voice_osc : in unsigned(3 downto 0);
|
||||
voice_wave : in unsigned(3 downto 0);
|
||||
voice_adsr : in unsigned(3 downto 0);
|
||||
voice_mul : in unsigned(3 downto 0);
|
||||
|
||||
-- Oscillator parameters
|
||||
freq : out unsigned(15 downto 0);
|
||||
test : out std_logic;
|
||||
sync : out std_logic;
|
||||
|
||||
-- Wave map parameters
|
||||
comb_mode : out std_logic;
|
||||
ring_mod : out std_logic;
|
||||
wave_sel : out std_logic_vector(3 downto 0);
|
||||
sq_width : out unsigned(11 downto 0);
|
||||
|
||||
-- ADSR parameters
|
||||
gate : out std_logic;
|
||||
attack : out std_logic_vector(3 downto 0);
|
||||
decay : out std_logic_vector(3 downto 0);
|
||||
sustain : out std_logic_vector(3 downto 0);
|
||||
release : out std_logic_vector(3 downto 0);
|
||||
|
||||
-- mixer 1 parameters
|
||||
filter_en : out std_logic;
|
||||
|
||||
-- globals
|
||||
volume_l : out unsigned(3 downto 0) := (others => '0');
|
||||
filter_co_l : out unsigned(10 downto 0) := (others => '0');
|
||||
filter_res_l : out unsigned(3 downto 0) := (others => '0');
|
||||
filter_ex_l : out std_logic := '0';
|
||||
filter_hp_l : out std_logic := '0';
|
||||
filter_bp_l : out std_logic := '0';
|
||||
filter_lp_l : out std_logic := '0';
|
||||
voice3_off_l : out std_logic := '0';
|
||||
|
||||
volume_r : out unsigned(3 downto 0) := (others => '0');
|
||||
filter_co_r : out unsigned(10 downto 0) := (others => '0');
|
||||
filter_res_r : out unsigned(3 downto 0) := (others => '0');
|
||||
filter_ex_r : out std_logic := '0';
|
||||
filter_hp_r : out std_logic := '0';
|
||||
filter_bp_r : out std_logic := '0';
|
||||
filter_lp_r : out std_logic := '0';
|
||||
voice3_off_r : out std_logic := '0';
|
||||
|
||||
-- readback
|
||||
osc3 : in std_logic_vector(7 downto 0);
|
||||
env3 : in std_logic_vector(7 downto 0) );
|
||||
|
||||
attribute ramstyle : string;
|
||||
|
||||
end sid_regs;
|
||||
|
||||
architecture gideon of sid_regs is
|
||||
attribute ramstyle of gideon : architecture is "logic";
|
||||
|
||||
type byte_array_t is array(natural range <>) of std_logic_vector(7 downto 0);
|
||||
type nibble_array_t is array(natural range <>) of std_logic_vector(3 downto 0);
|
||||
signal freq_lo : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal freq_hi : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal phase_lo : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal phase_hi : nibble_array_t(0 to 15):= (others => (others => '0'));
|
||||
signal control : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal att_dec : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal sust_rel : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal do_write : std_logic;
|
||||
signal filt_en_i: std_logic_vector(15 downto 0) := (others => '0');
|
||||
|
||||
constant address_remap : byte_array_t(0 to 255) := (
|
||||
X"00", X"01", X"02", X"03", X"04", X"05", X"06", -- 00 Voice 1
|
||||
X"10", X"11", X"12", X"13", X"14", X"15", X"16", -- 07 Voice 2
|
||||
X"20", X"21", X"22", X"23", X"24", X"25", X"26", -- 0E Voice 3
|
||||
|
||||
X"08", X"09", X"0A", X"0B", -- 15
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 19
|
||||
|
||||
X"30", X"31", X"32", X"33", X"34", X"35", X"36", -- 20 Voice 4
|
||||
X"40", X"41", X"42", X"43", X"44", X"45", X"46", -- 27 Voice 5
|
||||
X"50", X"51", X"52", X"53", X"54", X"55", X"56", -- 2E Voice 6
|
||||
X"60", X"61", X"62", X"63", X"64", X"65", X"66", -- 35 Voice 7
|
||||
X"70", X"71", X"72", X"73", X"74", X"75", X"76", -- 3C Voice 8
|
||||
X"0C", X"0D", X"0E", -- 43
|
||||
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 46
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 4D
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 54
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 5B
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 62
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 69
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 70
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 77
|
||||
X"FF", X"FF", -- 7E
|
||||
|
||||
X"80", X"81", X"82", X"83", X"84", X"85", X"86", -- 80 Voice 9
|
||||
X"90", X"91", X"92", X"93", X"94", X"95", X"96", -- 87 Voice 10
|
||||
X"A0", X"A1", X"A2", X"A3", X"A4", X"A5", X"A6", -- 8E Voice 11
|
||||
|
||||
X"88", X"89", X"8A", X"8B", -- 95
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 99
|
||||
|
||||
X"B0", X"B1", X"B2", X"B3", X"B4", X"B5", X"B6", -- A0 Voice 12
|
||||
X"C0", X"C1", X"C2", X"C3", X"C4", X"C5", X"C6", -- A7 Voice 13
|
||||
X"D0", X"D1", X"D2", X"D3", X"D4", X"D5", X"D6", -- AE Voice 14
|
||||
X"E0", X"E1", X"E2", X"E3", X"E4", X"E5", X"E6", -- B5 Voice 15
|
||||
X"F0", X"F1", X"F2", X"F3", X"F4", X"F5", X"F6", -- BC Voice 16
|
||||
X"8C", X"8D", X"8E", -- C3
|
||||
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- C6
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- CD
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- D4
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- DB
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- E2
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- E9
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- F0
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- F7
|
||||
X"FF", X"FF" ); -- FE
|
||||
|
||||
signal address : unsigned(7 downto 0);
|
||||
signal last_wr : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
address <= unsigned(address_remap(to_integer(addr)));
|
||||
do_write <= wren;
|
||||
|
||||
if do_write='0' and wren='1' then
|
||||
last_wr <= wdata;
|
||||
if address(3)='0' then -- Voice register
|
||||
case address(2 downto 0) is
|
||||
when "000" => freq_lo(to_integer(address(7 downto 4))) <= wdata;
|
||||
when "001" => freq_hi(to_integer(address(7 downto 4))) <= wdata;
|
||||
when "010" => phase_lo(to_integer(address(7 downto 4))) <= wdata;
|
||||
when "011" => phase_hi(to_integer(address(7 downto 4))) <= wdata(3 downto 0);
|
||||
when "100" => control(to_integer(address(7 downto 4))) <= wdata;
|
||||
when "101" => att_dec(to_integer(address(7 downto 4))) <= wdata;
|
||||
when "110" => sust_rel(to_integer(address(7 downto 4))) <= wdata;
|
||||
when others => null;
|
||||
end case;
|
||||
elsif address(7)='0' then -- Global register for left
|
||||
case address(2 downto 0) is
|
||||
when "000" => filter_co_l(2 downto 0) <= unsigned(wdata(2 downto 0));
|
||||
when "001" => filter_co_l(10 downto 3) <= unsigned(wdata);
|
||||
when "010" => filter_res_l <= unsigned(wdata(7 downto 4));
|
||||
filter_ex_l <= wdata(3);
|
||||
filt_en_i(2 downto 0) <= wdata(2 downto 0);
|
||||
when "011" => voice3_off_l <= wdata(7);
|
||||
filter_hp_l <= wdata(6);
|
||||
filter_bp_l <= wdata(5);
|
||||
filter_lp_l <= wdata(4);
|
||||
volume_l <= unsigned(wdata(3 downto 0));
|
||||
when "100" => filt_en_i(7 downto 0) <= wdata;
|
||||
when others => null;
|
||||
end case;
|
||||
else -- Global register for right
|
||||
case address(2 downto 0) is
|
||||
when "000" => filter_co_r(2 downto 0) <= unsigned(wdata(2 downto 0));
|
||||
when "001" => filter_co_r(10 downto 3) <= unsigned(wdata);
|
||||
when "010" => filter_res_r <= unsigned(wdata(7 downto 4));
|
||||
filter_ex_r <= wdata(3);
|
||||
filt_en_i(10 downto 8) <= wdata(2 downto 0);
|
||||
when "011" => voice3_off_r <= wdata(7);
|
||||
filter_hp_r <= wdata(6);
|
||||
filter_bp_r <= wdata(5);
|
||||
filter_lp_r <= wdata(4);
|
||||
volume_r <= unsigned(wdata(3 downto 0));
|
||||
when "100" => filt_en_i(15 downto 8) <= wdata;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Readback (unmapped address)
|
||||
case addr is
|
||||
when "00011001" => rdata <= potx;
|
||||
when "00011010" => rdata <= poty;
|
||||
when "00011011" => rdata <= osc3;
|
||||
when "00011100" => rdata <= env3;
|
||||
when others => rdata <= last_wr;
|
||||
end case;
|
||||
|
||||
if reset='1' then
|
||||
freq_lo <= (others => (others => '0'));
|
||||
freq_hi <= (others => (others => '0'));
|
||||
phase_lo <= (others => (others => '0'));
|
||||
phase_hi <= (others => (others => '0'));
|
||||
control <= (others => (others => '0'));
|
||||
att_dec <= (others => (others => '0'));
|
||||
sust_rel <= (others => (others => '0'));
|
||||
|
||||
filt_en_i <= (others => '0');
|
||||
voice3_off_l <= '0';
|
||||
voice3_off_r <= '0';
|
||||
volume_l <= X"0";
|
||||
volume_r <= X"0";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
freq <= unsigned(freq_hi(to_integer(voice_osc))) & unsigned(freq_lo(to_integer(voice_osc)));
|
||||
test <= control(to_integer(voice_osc))(3);
|
||||
sync <= control(to_integer(voice_osc))(1);
|
||||
|
||||
-- Wave map parameters
|
||||
ring_mod <= control(to_integer(voice_wave))(2);
|
||||
wave_sel <= control(to_integer(voice_wave))(7 downto 4);
|
||||
sq_width <= unsigned(phase_hi(to_integer(voice_wave))) & unsigned(phase_lo(to_integer(voice_wave)));
|
||||
comb_mode <= (voice_wave(3) and comb_wave_r) or (not voice_wave(3) and comb_wave_l);
|
||||
|
||||
-- ADSR parameters
|
||||
gate <= control(to_integer(voice_adsr))(0);
|
||||
attack <= att_dec(to_integer(voice_adsr))(7 downto 4);
|
||||
decay <= att_dec(to_integer(voice_adsr))(3 downto 0);
|
||||
sustain <= sust_rel(to_integer(voice_adsr))(7 downto 4);
|
||||
release <= sust_rel(to_integer(voice_adsr))(3 downto 0);
|
||||
|
||||
-- Mixer 1 parameters
|
||||
filter_en <= filt_en_i(to_integer(voice_mul));
|
||||
|
||||
end gideon;
|
||||
253
cores/c16/sid/sid_regs.vhd
Normal file
253
cores/c16/sid/sid_regs.vhd
Normal file
@@ -0,0 +1,253 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity sid_regs is
|
||||
port (
|
||||
clock : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
addr : in unsigned(7 downto 0);
|
||||
wren : in std_logic;
|
||||
wdata : in std_logic_vector(7 downto 0);
|
||||
rdata : out std_logic_vector(7 downto 0);
|
||||
|
||||
potx : in std_logic_vector(7 downto 0);
|
||||
poty : in std_logic_vector(7 downto 0);
|
||||
|
||||
---
|
||||
comb_wave_l : in std_logic;
|
||||
comb_wave_r : in std_logic;
|
||||
---
|
||||
voice_osc : in unsigned(3 downto 0);
|
||||
voice_wave : in unsigned(3 downto 0);
|
||||
voice_adsr : in unsigned(3 downto 0);
|
||||
voice_mul : in unsigned(3 downto 0);
|
||||
|
||||
-- Oscillator parameters
|
||||
freq : out unsigned(15 downto 0);
|
||||
test : out std_logic;
|
||||
sync : out std_logic;
|
||||
|
||||
-- Wave map parameters
|
||||
comb_mode : out std_logic;
|
||||
ring_mod : out std_logic;
|
||||
wave_sel : out std_logic_vector(3 downto 0);
|
||||
sq_width : out unsigned(11 downto 0);
|
||||
|
||||
-- ADSR parameters
|
||||
gate : out std_logic;
|
||||
attack : out std_logic_vector(3 downto 0);
|
||||
decay : out std_logic_vector(3 downto 0);
|
||||
sustain : out std_logic_vector(3 downto 0);
|
||||
release : out std_logic_vector(3 downto 0);
|
||||
|
||||
-- mixer 1 parameters
|
||||
filter_en : out std_logic;
|
||||
|
||||
-- globals
|
||||
volume_l : out unsigned(3 downto 0) := (others => '0');
|
||||
filter_co_l : out unsigned(10 downto 0) := (others => '0');
|
||||
filter_res_l : out unsigned(3 downto 0) := (others => '0');
|
||||
filter_ex_l : out std_logic := '0';
|
||||
filter_hp_l : out std_logic := '0';
|
||||
filter_bp_l : out std_logic := '0';
|
||||
filter_lp_l : out std_logic := '0';
|
||||
voice3_off_l : out std_logic := '0';
|
||||
|
||||
volume_r : out unsigned(3 downto 0) := (others => '0');
|
||||
filter_co_r : out unsigned(10 downto 0) := (others => '0');
|
||||
filter_res_r : out unsigned(3 downto 0) := (others => '0');
|
||||
filter_ex_r : out std_logic := '0';
|
||||
filter_hp_r : out std_logic := '0';
|
||||
filter_bp_r : out std_logic := '0';
|
||||
filter_lp_r : out std_logic := '0';
|
||||
voice3_off_r : out std_logic := '0';
|
||||
|
||||
-- readback
|
||||
osc3 : in std_logic_vector(7 downto 0);
|
||||
env3 : in std_logic_vector(7 downto 0) );
|
||||
|
||||
attribute ramstyle : string;
|
||||
|
||||
end sid_regs;
|
||||
|
||||
architecture gideon of sid_regs is
|
||||
attribute ramstyle of gideon : architecture is "logic";
|
||||
|
||||
type byte_array_t is array(natural range <>) of std_logic_vector(7 downto 0);
|
||||
type nibble_array_t is array(natural range <>) of std_logic_vector(3 downto 0);
|
||||
signal freq_lo : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal freq_hi : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal phase_lo : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal phase_hi : nibble_array_t(0 to 15):= (others => (others => '0'));
|
||||
signal control : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal att_dec : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal sust_rel : byte_array_t(0 to 15) := (others => (others => '0'));
|
||||
signal do_write : std_logic;
|
||||
signal bus_value: std_logic_vector(7 downto 0);
|
||||
signal filt_en_i: std_logic_vector(15 downto 0) := (others => '0');
|
||||
|
||||
constant address_remap : byte_array_t(0 to 255) := (
|
||||
X"00", X"01", X"02", X"03", X"04", X"05", X"06", -- 00 Voice 1
|
||||
X"10", X"11", X"12", X"13", X"14", X"15", X"16", -- 07 Voice 2
|
||||
X"20", X"21", X"22", X"23", X"24", X"25", X"26", -- 0E Voice 3
|
||||
|
||||
X"08", X"09", X"0A", X"0B", -- 15
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 19
|
||||
|
||||
X"30", X"31", X"32", X"33", X"34", X"35", X"36", -- 20 Voice 4
|
||||
X"40", X"41", X"42", X"43", X"44", X"45", X"46", -- 27 Voice 5
|
||||
X"50", X"51", X"52", X"53", X"54", X"55", X"56", -- 2E Voice 6
|
||||
X"60", X"61", X"62", X"63", X"64", X"65", X"66", -- 35 Voice 7
|
||||
X"70", X"71", X"72", X"73", X"74", X"75", X"76", -- 3C Voice 8
|
||||
X"0C", X"0D", X"0E", -- 43
|
||||
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 46
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 4D
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 54
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 5B
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 62
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 69
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 70
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 77
|
||||
X"FF", X"FF", -- 7E
|
||||
|
||||
X"80", X"81", X"82", X"83", X"84", X"85", X"86", -- 80 Voice 9
|
||||
X"90", X"91", X"92", X"93", X"94", X"95", X"96", -- 87 Voice 10
|
||||
X"A0", X"A1", X"A2", X"A3", X"A4", X"A5", X"A6", -- 8E Voice 11
|
||||
|
||||
X"88", X"89", X"8A", X"8B", -- 95
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- 99
|
||||
|
||||
X"B0", X"B1", X"B2", X"B3", X"B4", X"B5", X"B6", -- A0 Voice 12
|
||||
X"C0", X"C1", X"C2", X"C3", X"C4", X"C5", X"C6", -- A7 Voice 13
|
||||
X"D0", X"D1", X"D2", X"D3", X"D4", X"D5", X"D6", -- AE Voice 14
|
||||
X"E0", X"E1", X"E2", X"E3", X"E4", X"E5", X"E6", -- B5 Voice 15
|
||||
X"F0", X"F1", X"F2", X"F3", X"F4", X"F5", X"F6", -- BC Voice 16
|
||||
X"8C", X"8D", X"8E", -- C3
|
||||
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- C6
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- CD
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- D4
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- DB
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- E2
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- E9
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- F0
|
||||
X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", -- F7
|
||||
X"FF", X"FF" ); -- FE
|
||||
|
||||
begin
|
||||
process(clock)
|
||||
variable address: unsigned(7 downto 0);
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
address := unsigned(address_remap(to_integer(addr)));
|
||||
-- do_write <= wren;
|
||||
-- if do_write='0' and wren='1' then
|
||||
if wren='1' then
|
||||
bus_value <= wdata;
|
||||
if address(3)='0' then -- Voice register
|
||||
case address(2 downto 0) is
|
||||
when "000" => freq_lo(to_integer(address(7 downto 4))) <= wdata;
|
||||
when "001" => freq_hi(to_integer(address(7 downto 4))) <= wdata;
|
||||
when "010" => phase_lo(to_integer(address(7 downto 4))) <= wdata;
|
||||
when "011" => phase_hi(to_integer(address(7 downto 4))) <= wdata(3 downto 0);
|
||||
when "100" => control(to_integer(address(7 downto 4))) <= wdata;
|
||||
when "101" => att_dec(to_integer(address(7 downto 4))) <= wdata;
|
||||
when "110" => sust_rel(to_integer(address(7 downto 4))) <= wdata;
|
||||
when others => null;
|
||||
end case;
|
||||
elsif address(7)='0' then -- Global register for left
|
||||
case address(2 downto 0) is
|
||||
when "000" => filter_co_l(2 downto 0) <= unsigned(wdata(2 downto 0));
|
||||
when "001" => filter_co_l(10 downto 3) <= unsigned(wdata);
|
||||
when "010" => filter_res_l <= unsigned(wdata(7 downto 4));
|
||||
filter_ex_l <= wdata(3);
|
||||
filt_en_i(2 downto 0) <= wdata(2 downto 0);
|
||||
when "011" => voice3_off_l <= wdata(7);
|
||||
filter_hp_l <= wdata(6);
|
||||
filter_bp_l <= wdata(5);
|
||||
filter_lp_l <= wdata(4);
|
||||
volume_l <= unsigned(wdata(3 downto 0));
|
||||
when "100" => filt_en_i(7 downto 0) <= wdata;
|
||||
when others => null;
|
||||
end case;
|
||||
else -- Global register for right
|
||||
case address(2 downto 0) is
|
||||
when "000" => filter_co_r(2 downto 0) <= unsigned(wdata(2 downto 0));
|
||||
when "001" => filter_co_r(10 downto 3) <= unsigned(wdata);
|
||||
when "010" => filter_res_r <= unsigned(wdata(7 downto 4));
|
||||
filter_ex_r <= wdata(3);
|
||||
filt_en_i(10 downto 8) <= wdata(2 downto 0);
|
||||
when "011" => voice3_off_r <= wdata(7);
|
||||
filter_hp_r <= wdata(6);
|
||||
filter_bp_r <= wdata(5);
|
||||
filter_lp_r <= wdata(4);
|
||||
volume_r <= unsigned(wdata(3 downto 0));
|
||||
when "100" => filt_en_i(15 downto 8) <= wdata;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Readback (unmapped address)
|
||||
case addr is
|
||||
when "00011001" => rdata <= potx; bus_value <= potx;
|
||||
when "00011010" => rdata <= poty; bus_value <= poty;
|
||||
when "00011011" => rdata <= osc3; bus_value <= osc3;
|
||||
when "00011100" => rdata <= env3; bus_value <= env3;
|
||||
when others => rdata <= bus_value;
|
||||
end case;
|
||||
|
||||
if reset='1' then
|
||||
freq_lo <= (others => (others => '0'));
|
||||
freq_hi <= (others => (others => '0'));
|
||||
phase_lo <= (others => (others => '0'));
|
||||
phase_hi <= (others => (others => '0'));
|
||||
control <= (others => (others => '0'));
|
||||
att_dec <= (others => (others => '0'));
|
||||
sust_rel <= (others => (others => '0'));
|
||||
|
||||
filt_en_i <= (others => '0');
|
||||
voice3_off_l <= '0';
|
||||
voice3_off_r <= '0';
|
||||
volume_l <= X"0";
|
||||
volume_r <= X"0";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
freq <= unsigned(freq_hi(to_integer(voice_osc))) & unsigned(freq_lo(to_integer(voice_osc)));
|
||||
test <= control(to_integer(voice_osc))(3);
|
||||
sync <= control(to_integer(voice_osc))(1);
|
||||
|
||||
-- Wave map parameters
|
||||
ring_mod <= control(to_integer(voice_wave))(2);
|
||||
wave_sel <= control(to_integer(voice_wave))(7 downto 4);
|
||||
sq_width <= unsigned(phase_hi(to_integer(voice_wave))) & unsigned(phase_lo(to_integer(voice_wave)));
|
||||
comb_mode <= (voice_wave(3) and comb_wave_r) or (not voice_wave(3) and comb_wave_l);
|
||||
|
||||
-- ADSR parameters
|
||||
gate <= control(to_integer(voice_adsr))(0);
|
||||
attack <= att_dec(to_integer(voice_adsr))(7 downto 4);
|
||||
decay <= att_dec(to_integer(voice_adsr))(3 downto 0);
|
||||
sustain <= sust_rel(to_integer(voice_adsr))(7 downto 4);
|
||||
release <= sust_rel(to_integer(voice_adsr))(3 downto 0);
|
||||
|
||||
-- Mixer 1 parameters
|
||||
filter_en <= filt_en_i(to_integer(voice_mul));
|
||||
|
||||
end gideon;
|
||||
411
cores/c16/sid/sid_top.vhd
Normal file
411
cores/c16/sid/sid_top.vhd
Normal file
@@ -0,0 +1,411 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
|
||||
entity sid_top is
|
||||
generic (
|
||||
g_filter_div : natural := 141; --for 32 MHz (221; -- for 50 MHz)
|
||||
g_num_voices : natural := 3 );
|
||||
port (
|
||||
clock : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
addr : in unsigned(7 downto 0);
|
||||
wren : in std_logic;
|
||||
wdata : in std_logic_vector(7 downto 0);
|
||||
rdata : out std_logic_vector(7 downto 0);
|
||||
|
||||
potx : in std_logic_vector(7 downto 0);
|
||||
poty : in std_logic_vector(7 downto 0);
|
||||
|
||||
comb_wave_l : in std_logic := '0';
|
||||
comb_wave_r : in std_logic := '0';
|
||||
|
||||
start_iter : in std_logic;
|
||||
sample_left : out signed(17 downto 0);
|
||||
sample_right : out signed(17 downto 0);
|
||||
|
||||
extfilter_en : in std_logic
|
||||
);
|
||||
end sid_top;
|
||||
|
||||
|
||||
architecture structural of sid_top is
|
||||
|
||||
-- Voice index in pipe
|
||||
signal voice_osc : unsigned(3 downto 0);
|
||||
signal voice_wave : unsigned(3 downto 0);
|
||||
signal voice_mul : unsigned(3 downto 0);
|
||||
signal enable_osc : std_logic;
|
||||
signal enable_wave : std_logic;
|
||||
signal enable_mul : std_logic;
|
||||
|
||||
-- Oscillator parameters
|
||||
signal freq : unsigned(15 downto 0);
|
||||
signal test : std_logic;
|
||||
signal sync : std_logic;
|
||||
|
||||
-- Wave map parameters
|
||||
signal msb_other : std_logic;
|
||||
signal comb_mode : std_logic;
|
||||
signal ring_mod : std_logic;
|
||||
signal wave_sel : std_logic_vector(3 downto 0);
|
||||
signal sq_width : unsigned(11 downto 0);
|
||||
|
||||
-- ADSR parameters
|
||||
signal gate : std_logic;
|
||||
signal attack : std_logic_vector(3 downto 0);
|
||||
signal decay : std_logic_vector(3 downto 0);
|
||||
signal sustain : std_logic_vector(3 downto 0);
|
||||
signal release : std_logic_vector(3 downto 0);
|
||||
|
||||
-- Filter enable
|
||||
signal filter_en : std_logic;
|
||||
|
||||
-- globals
|
||||
signal volume_l : unsigned(3 downto 0);
|
||||
signal filter_co_l : unsigned(10 downto 0);
|
||||
signal filter_res_l : unsigned(3 downto 0);
|
||||
signal filter_hp_l : std_logic;
|
||||
signal filter_bp_l : std_logic;
|
||||
signal filter_lp_l : std_logic;
|
||||
signal voice3_off_l : std_logic;
|
||||
|
||||
signal volume_r : unsigned(3 downto 0);
|
||||
signal filter_co_r : unsigned(10 downto 0);
|
||||
signal filter_res_r : unsigned(3 downto 0);
|
||||
signal filter_hp_r : std_logic;
|
||||
signal filter_bp_r : std_logic;
|
||||
signal filter_lp_r : std_logic;
|
||||
signal voice3_off_r : std_logic;
|
||||
|
||||
-- readback
|
||||
signal osc3 : std_logic_vector(7 downto 0);
|
||||
signal env3 : std_logic_vector(7 downto 0);
|
||||
|
||||
-- intermediate flags and signals
|
||||
signal test_wave : std_logic;
|
||||
signal osc_val : unsigned(23 downto 0);
|
||||
signal carry_20 : std_logic;
|
||||
signal enveloppe : unsigned(7 downto 0);
|
||||
signal waveform : unsigned(11 downto 0);
|
||||
|
||||
signal valid_sum : std_logic;
|
||||
signal valid_filt : std_logic;
|
||||
signal valid_mix : std_logic;
|
||||
|
||||
signal filter_out_l: signed(17 downto 0) := (others => '0');
|
||||
signal direct_out_l: signed(17 downto 0) := (others => '0');
|
||||
signal high_pass_l : signed(17 downto 0) := (others => '0');
|
||||
signal band_pass_l : signed(17 downto 0) := (others => '0');
|
||||
signal low_pass_l : signed(17 downto 0) := (others => '0');
|
||||
signal mixed_out_l : signed(17 downto 0) := (others => '0');
|
||||
|
||||
signal filter_out_r: signed(17 downto 0) := (others => '0');
|
||||
signal direct_out_r: signed(17 downto 0) := (others => '0');
|
||||
signal high_pass_r : signed(17 downto 0) := (others => '0');
|
||||
signal band_pass_r : signed(17 downto 0) := (others => '0');
|
||||
signal low_pass_r : signed(17 downto 0) := (others => '0');
|
||||
signal mixed_out_r : signed(17 downto 0) := (others => '0');
|
||||
begin
|
||||
|
||||
i_regs: entity work.sid_regs
|
||||
port map
|
||||
(
|
||||
clock => clock,
|
||||
reset => reset,
|
||||
|
||||
addr => addr,
|
||||
wren => wren,
|
||||
wdata => wdata,
|
||||
rdata => rdata,
|
||||
|
||||
potx => potx,
|
||||
poty => poty,
|
||||
|
||||
comb_wave_l => comb_wave_l,
|
||||
comb_wave_r => comb_wave_r,
|
||||
|
||||
voice_osc => voice_osc,
|
||||
voice_wave => voice_wave,
|
||||
voice_adsr => voice_wave,
|
||||
voice_mul => voice_mul,
|
||||
|
||||
-- Oscillator parameters
|
||||
freq => freq,
|
||||
test => test,
|
||||
sync => sync,
|
||||
|
||||
-- Wave map parameters
|
||||
comb_mode => comb_mode,
|
||||
ring_mod => ring_mod,
|
||||
wave_sel => wave_sel,
|
||||
sq_width => sq_width,
|
||||
|
||||
-- ADSR parameters
|
||||
gate => gate,
|
||||
attack => attack,
|
||||
decay => decay,
|
||||
sustain => sustain,
|
||||
release => release,
|
||||
|
||||
-- mixer parameters
|
||||
filter_en => filter_en,
|
||||
|
||||
-- globals
|
||||
volume_l => volume_l,
|
||||
filter_co_l => filter_co_l,
|
||||
filter_res_l=> filter_res_l,
|
||||
filter_ex_l => open,
|
||||
filter_hp_l => filter_hp_l,
|
||||
filter_bp_l => filter_bp_l,
|
||||
filter_lp_l => filter_lp_l,
|
||||
voice3_off_l=> voice3_off_l,
|
||||
|
||||
volume_r => volume_r,
|
||||
filter_co_r => filter_co_r,
|
||||
filter_res_r=> filter_res_r,
|
||||
filter_ex_r => open,
|
||||
filter_hp_r => filter_hp_r,
|
||||
filter_bp_r => filter_bp_r,
|
||||
filter_lp_r => filter_lp_r,
|
||||
voice3_off_r=> voice3_off_r,
|
||||
|
||||
-- readback
|
||||
osc3 => osc3,
|
||||
env3 => env3
|
||||
);
|
||||
|
||||
i_ctrl: entity work.sid_ctrl
|
||||
generic map
|
||||
(
|
||||
g_num_voices => g_num_voices
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock => clock,
|
||||
reset => reset,
|
||||
start_iter => start_iter,
|
||||
voice_osc => voice_osc,
|
||||
enable_osc => enable_osc
|
||||
);
|
||||
|
||||
|
||||
osc: entity work.oscillator
|
||||
generic map
|
||||
(
|
||||
g_num_voices
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock => clock,
|
||||
reset => reset,
|
||||
|
||||
voice_i => voice_osc,
|
||||
voice_o => voice_wave,
|
||||
|
||||
enable_i => enable_osc,
|
||||
enable_o => enable_wave,
|
||||
|
||||
freq => freq,
|
||||
test => test,
|
||||
sync => sync,
|
||||
|
||||
osc_val => osc_val,
|
||||
test_o => test_wave,
|
||||
carry_20 => carry_20,
|
||||
msb_other => msb_other
|
||||
);
|
||||
|
||||
wmap: entity work.wave_map
|
||||
generic map
|
||||
(
|
||||
g_num_voices => g_num_voices,
|
||||
g_sample_bits => 12
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock => clock,
|
||||
reset => reset,
|
||||
test => test_wave,
|
||||
|
||||
osc_val => osc_val,
|
||||
carry_20 => carry_20,
|
||||
msb_other => msb_other,
|
||||
|
||||
voice_i => voice_wave,
|
||||
enable_i => enable_wave,
|
||||
comb_mode => comb_mode,
|
||||
wave_sel => wave_sel,
|
||||
ring_mod => ring_mod,
|
||||
sq_width => sq_width,
|
||||
|
||||
voice_o => voice_mul,
|
||||
enable_o => enable_mul,
|
||||
wave_out => waveform
|
||||
);
|
||||
|
||||
adsr: entity work.adsr_multi
|
||||
generic map
|
||||
(
|
||||
g_num_voices => g_num_voices
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock => clock,
|
||||
reset => reset,
|
||||
|
||||
voice_i => voice_wave,
|
||||
enable_i => enable_wave,
|
||||
voice_o => open,
|
||||
enable_o => open,
|
||||
|
||||
gate => gate,
|
||||
attack => attack,
|
||||
decay => decay,
|
||||
sustain => sustain,
|
||||
release => release,
|
||||
|
||||
env_state=> open, -- for testing only
|
||||
env_out => enveloppe
|
||||
);
|
||||
|
||||
sum: entity work.mult_acc(signed_wave)
|
||||
port map
|
||||
(
|
||||
clock => clock,
|
||||
reset => reset,
|
||||
|
||||
voice_i => voice_mul,
|
||||
enable_i => enable_mul,
|
||||
voice3_off_l=> voice3_off_l,
|
||||
voice3_off_r=> voice3_off_r,
|
||||
|
||||
enveloppe => enveloppe,
|
||||
waveform => waveform,
|
||||
filter_en => filter_en,
|
||||
|
||||
osc3 => osc3,
|
||||
env3 => env3,
|
||||
|
||||
valid_out => valid_sum,
|
||||
filter_out_L => filter_out_L,
|
||||
filter_out_R => filter_out_R,
|
||||
direct_out_L => direct_out_L,
|
||||
direct_out_R => direct_out_R
|
||||
);
|
||||
|
||||
i_filt_left: entity work.sid_filter
|
||||
generic map
|
||||
(
|
||||
g_divider => g_filter_div
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock => clock,
|
||||
reset => reset,
|
||||
enable => extfilter_en,
|
||||
|
||||
filt_co => filter_co_l,
|
||||
filt_res => filter_res_l,
|
||||
|
||||
valid_in => valid_sum,
|
||||
|
||||
input => filter_out_L,
|
||||
high_pass => high_pass_L,
|
||||
band_pass => band_pass_L,
|
||||
low_pass => low_pass_L,
|
||||
|
||||
error_out => open,
|
||||
valid_out => valid_filt
|
||||
);
|
||||
|
||||
mix: entity work.sid_mixer
|
||||
port map
|
||||
(
|
||||
clock => clock,
|
||||
reset => reset,
|
||||
|
||||
valid_in => valid_filt,
|
||||
|
||||
direct_out => direct_out_L,
|
||||
high_pass => high_pass_L,
|
||||
band_pass => band_pass_L,
|
||||
low_pass => low_pass_L,
|
||||
|
||||
filter_hp => filter_hp_l,
|
||||
filter_bp => filter_bp_l,
|
||||
filter_lp => filter_lp_l,
|
||||
|
||||
volume => volume_l,
|
||||
|
||||
mixed_out => mixed_out_L,
|
||||
valid_out => open
|
||||
);
|
||||
|
||||
i_filt_right: entity work.sid_filter
|
||||
generic map
|
||||
(
|
||||
g_divider => g_filter_div
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock => clock,
|
||||
reset => reset,
|
||||
enable => extfilter_en,
|
||||
|
||||
filt_co => filter_co_r,
|
||||
filt_res => filter_res_r,
|
||||
|
||||
valid_in => valid_sum,
|
||||
|
||||
input => filter_out_R,
|
||||
high_pass => high_pass_R,
|
||||
band_pass => band_pass_R,
|
||||
low_pass => low_pass_R,
|
||||
|
||||
error_out => open,
|
||||
valid_out => open
|
||||
);
|
||||
|
||||
mix_right: entity work.sid_mixer
|
||||
port map
|
||||
(
|
||||
clock => clock,
|
||||
reset => reset,
|
||||
|
||||
valid_in => valid_filt,
|
||||
|
||||
direct_out => direct_out_R,
|
||||
high_pass => high_pass_R,
|
||||
band_pass => band_pass_R,
|
||||
low_pass => low_pass_R,
|
||||
|
||||
filter_hp => filter_hp_r,
|
||||
filter_bp => filter_bp_r,
|
||||
filter_lp => filter_lp_r,
|
||||
|
||||
volume => volume_r,
|
||||
|
||||
mixed_out => mixed_out_R,
|
||||
valid_out => open
|
||||
);
|
||||
|
||||
sample_left <= mixed_out_L;
|
||||
sample_right <= mixed_out_R;
|
||||
|
||||
end structural;
|
||||
178
cores/c16/sid/wave_map.vhd
Normal file
178
cores/c16/sid/wave_map.vhd
Normal file
@@ -0,0 +1,178 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2010 Gideon's Logic Architectures'
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Gideon Zweijtzer (gideon.zweijtzer (at) gmail.com)
|
||||
--
|
||||
-- Note that this file is copyrighted, and is not supposed to be used in other
|
||||
-- projects without written permission from the author.
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity wave_map is
|
||||
generic (
|
||||
g_num_voices : integer := 8; -- 8 or 16, clock should then be 8 or 16 MHz, too!
|
||||
g_sample_bits : integer := 8 );
|
||||
port (
|
||||
clock : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
osc_val : in unsigned(23 downto 0);
|
||||
carry_20 : in std_logic;
|
||||
|
||||
msb_other: in std_logic := '0';
|
||||
ring_mod : in std_logic := '0';
|
||||
test : in std_logic := '0';
|
||||
|
||||
voice_i : in unsigned(3 downto 0);
|
||||
comb_mode: in std_logic;
|
||||
enable_i : in std_logic;
|
||||
wave_sel : in std_logic_vector(3 downto 0);
|
||||
sq_width : in unsigned(11 downto 0);
|
||||
|
||||
voice_o : out unsigned(3 downto 0);
|
||||
enable_o : out std_logic;
|
||||
wave_out : out unsigned(g_sample_bits-1 downto 0) );
|
||||
|
||||
end wave_map;
|
||||
|
||||
|
||||
architecture Gideon of wave_map is
|
||||
type noise_array_t is array (natural range <>) of unsigned(22 downto 0);
|
||||
signal noise_reg : noise_array_t(0 to g_num_voices-1) := (others => (0 => '1', others => '0'));
|
||||
type voice_array_t is array (natural range <>) of unsigned(g_sample_bits-1 downto 0);
|
||||
signal voice_reg : voice_array_t(0 to g_num_voices-1) := (others => (others => '0'));
|
||||
|
||||
type t_byte_array is array(natural range <>) of unsigned(7 downto 0);
|
||||
constant c_wave_TP : t_byte_array(0 to 255) := (
|
||||
16#FF# => X"FF", 16#F7# => X"F7", 16#EF# => X"EF", 16#E7# => X"E0",
|
||||
16#FE# => X"FE", 16#F6# => X"F0", 16#EE# => X"E0", 16#E6# => X"00",
|
||||
16#FD# => X"FD", 16#F5# => X"FD", 16#ED# => X"E0", 16#E5# => X"00",
|
||||
16#FC# => X"F8", 16#F4# => X"80", 16#EC# => X"00", 16#E4# => X"00",
|
||||
16#FB# => X"FB", 16#F3# => X"F0", 16#EB# => X"E0", 16#E3# => X"00",
|
||||
16#FA# => X"F8", 16#F2# => X"08", 16#EA# => X"00", 16#E2# => X"00",
|
||||
16#F9# => X"F0", 16#F1# => X"00", 16#E9# => X"00", 16#E1# => X"00",
|
||||
16#F8# => X"80", 16#F0# => X"00", 16#E8# => X"00", 16#E0# => X"00",
|
||||
|
||||
16#DF# => X"DF", 16#DE# => X"D0", 16#DD# => X"C0", 16#DB# => X"C0",
|
||||
16#D7# => X"C0", 16#CF# => X"C0", 16#BF# => X"BF", 16#BE# => X"B0",
|
||||
16#BD# => X"A0", 16#B9# => X"80", 16#B7# => X"80", 16#AF# => X"80",
|
||||
|
||||
16#7F# => X"7F", 16#7E# => X"70", 16#7D# => X"70", 16#7B# => X"60",
|
||||
16#77# => X"40", others => X"00" );
|
||||
|
||||
constant c_wave_TS : t_byte_array(0 to 255) := (
|
||||
16#7F# => X"1E", 16#FE# => X"18", 16#FF# => X"3E", others => X"00" );
|
||||
|
||||
begin
|
||||
process(clock)
|
||||
variable noise_tmp : unsigned(22 downto 0);
|
||||
variable voice_tmp : unsigned(g_sample_bits-1 downto 0);
|
||||
variable triangle : unsigned(g_sample_bits-1 downto 0);
|
||||
variable square : unsigned(g_sample_bits-1 downto 0);
|
||||
variable sawtooth : unsigned(g_sample_bits-1 downto 0);
|
||||
variable out_tmp : unsigned(g_sample_bits-1 downto 0);
|
||||
variable new_bit : std_logic;
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
-- take top of list
|
||||
voice_tmp := voice_reg(0);
|
||||
noise_tmp := noise_reg(0);
|
||||
|
||||
if reset='1' or test='1' then
|
||||
noise_tmp := (others => '1'); -- seed not equal to zero
|
||||
elsif carry_20='1' then
|
||||
new_bit := noise_tmp(22) xor noise_tmp(21) xor noise_tmp(20) xor noise_tmp(15);
|
||||
noise_tmp := noise_tmp(21 downto 0) & new_bit;
|
||||
end if;
|
||||
|
||||
if osc_val(23)='1' then
|
||||
triangle := not osc_val(22 downto 23-g_sample_bits);
|
||||
else
|
||||
triangle := osc_val(22 downto 23-g_sample_bits);
|
||||
end if;
|
||||
if ring_mod='1' and msb_other='0' then
|
||||
triangle := not triangle;
|
||||
end if;
|
||||
|
||||
sawtooth := osc_val(23 downto 24-g_sample_bits);
|
||||
if osc_val(23 downto 12) < sq_width then
|
||||
square := (others => '0');
|
||||
else
|
||||
square := (others => '1');
|
||||
end if;
|
||||
|
||||
out_tmp := (others => '0');
|
||||
case wave_sel is
|
||||
when X"0" =>
|
||||
out_tmp := voice_tmp;
|
||||
when X"1" =>
|
||||
out_tmp := triangle;
|
||||
when X"2" =>
|
||||
out_tmp := sawtooth;
|
||||
when X"3" =>
|
||||
if comb_mode='0' then
|
||||
out_tmp(g_sample_bits-1 downto g_sample_bits-8) :=
|
||||
c_wave_TS(to_integer(osc_val(23 downto 23-g_sample_bits)));
|
||||
else -- 8580
|
||||
out_tmp := triangle and sawtooth;
|
||||
end if;
|
||||
when X"4" =>
|
||||
out_tmp := square;
|
||||
when X"5" => -- combined triangle and square
|
||||
if comb_mode='0' then
|
||||
if square(0)='1' then
|
||||
out_tmp(g_sample_bits-1 downto g_sample_bits-8) :=
|
||||
c_wave_TP(to_integer(triangle(g_sample_bits-1 downto g_sample_bits-8)));
|
||||
end if;
|
||||
else -- 8580
|
||||
out_tmp := triangle and square;
|
||||
end if;
|
||||
when X"6" => -- combined saw and pulse
|
||||
if comb_mode='1' then
|
||||
out_tmp := sawtooth and square;
|
||||
end if;
|
||||
|
||||
when X"7" => -- combined triangle, saw and pulse
|
||||
if comb_mode='1' then
|
||||
out_tmp := triangle and sawtooth and square;
|
||||
end if;
|
||||
|
||||
when X"8" =>
|
||||
out_tmp(g_sample_bits-1) := noise_tmp(22); -- unsure.. 21?
|
||||
out_tmp(g_sample_bits-2) := noise_tmp(20);
|
||||
out_tmp(g_sample_bits-3) := noise_tmp(16);
|
||||
out_tmp(g_sample_bits-4) := noise_tmp(13);
|
||||
out_tmp(g_sample_bits-5) := noise_tmp(11);
|
||||
out_tmp(g_sample_bits-6) := noise_tmp(7);
|
||||
out_tmp(g_sample_bits-7) := noise_tmp(4);
|
||||
out_tmp(g_sample_bits-8) := noise_tmp(2);
|
||||
|
||||
-- when X"9"|X"A"|X"B"|X"C"|X"D"|X"E"|X"F" =>
|
||||
-- out_tmp := noise_tmp(20 downto 21-g_sample_bits);
|
||||
-- noise_tmp := (others => '0');
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
|
||||
if enable_i='1' then
|
||||
noise_reg(g_num_voices-1) <= noise_tmp;
|
||||
noise_reg(0 to g_num_voices-2) <= noise_reg(1 to g_num_voices-1);
|
||||
voice_reg(g_num_voices-1) <= out_tmp;
|
||||
voice_reg(0 to g_num_voices-2) <= voice_reg(1 to g_num_voices-1);
|
||||
end if;
|
||||
|
||||
--out_tmp(out_tmp'high) := not out_tmp(out_tmp'high);
|
||||
wave_out <= unsigned(out_tmp);
|
||||
|
||||
voice_o <= voice_i;
|
||||
enable_o <= enable_i;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end Gideon;
|
||||
253
cores/c16/sid8580/sid8580.v
Normal file
253
cores/c16/sid8580/sid8580.v
Normal file
@@ -0,0 +1,253 @@
|
||||
module sid8580 (clk_1MHz, clk32, reset, cs, we, addr, data_in, data_out,
|
||||
pot_x, pot_y, audio_data, extfilter_en);
|
||||
|
||||
// Input Ports
|
||||
input wire [0:0] clk_1MHz;
|
||||
input wire [0:0] clk32;
|
||||
input wire [0:0] reset;
|
||||
input wire [0:0] cs;
|
||||
input wire [0:0] we;
|
||||
input wire [4:0] addr;
|
||||
input wire [7:0] data_in;
|
||||
input wire [7:0] pot_x;
|
||||
input wire [7:0] pot_y;
|
||||
input wire [0:0] extfilter_en;
|
||||
|
||||
// Output Ports
|
||||
output wire [ 7:0] data_out;
|
||||
output wire [15:0] audio_data;
|
||||
|
||||
// Internal Signals
|
||||
reg [7:0] Voice_1_Freq_lo;
|
||||
reg [7:0] Voice_1_Freq_hi;
|
||||
reg [7:0] Voice_1_Pw_lo;
|
||||
reg [3:0] Voice_1_Pw_hi;
|
||||
reg [7:0] Voice_1_Control;
|
||||
reg [7:0] Voice_1_Att_dec;
|
||||
reg [7:0] Voice_1_Sus_Rel;
|
||||
|
||||
reg [7:0] Voice_2_Freq_lo;
|
||||
reg [7:0] Voice_2_Freq_hi;
|
||||
reg [7:0] Voice_2_Pw_lo;
|
||||
reg [3:0] Voice_2_Pw_hi;
|
||||
reg [7:0] Voice_2_Control;
|
||||
reg [7:0] Voice_2_Att_dec;
|
||||
reg [7:0] Voice_2_Sus_Rel;
|
||||
|
||||
reg [7:0] Voice_3_Freq_lo;
|
||||
reg [7:0] Voice_3_Freq_hi;
|
||||
reg [7:0] Voice_3_Pw_lo;
|
||||
reg [3:0] Voice_3_Pw_hi;
|
||||
reg [7:0] Voice_3_Control;
|
||||
reg [7:0] Voice_3_Att_dec;
|
||||
reg [7:0] Voice_3_Sus_Rel;
|
||||
|
||||
reg [7:0] Filter_Fc_lo;
|
||||
reg [7:0] Filter_Fc_hi;
|
||||
reg [7:0] Filter_Res_Filt;
|
||||
reg [7:0] Filter_Mode_Vol;
|
||||
|
||||
wire [7:0] Misc_Osc3_Random;
|
||||
wire [7:0] Misc_Env3;
|
||||
|
||||
reg [7:0] Ext_hi;
|
||||
reg [3:0] Ext_lo;
|
||||
|
||||
reg [7:0] do_buf;
|
||||
reg [7:0] sidrandom;
|
||||
|
||||
wire [11:0] voice_1;
|
||||
wire [11:0] voice_2;
|
||||
wire [11:0] voice_3;
|
||||
wire [17:0] voice_mixed;
|
||||
reg [17:0] voice_volume;
|
||||
|
||||
wire [ 0:0] voice_1_PA_MSB;
|
||||
wire [ 0:0] voice_2_PA_MSB;
|
||||
wire [ 0:0] voice_3_PA_MSB;
|
||||
|
||||
wire [18:0] filtered_audio;
|
||||
reg [ 0:0] tick_q1;
|
||||
reg [ 0:0] tick_q2;
|
||||
reg [ 0:0] input_valid;
|
||||
wire [17:0] unsigned_audio;
|
||||
wire [18:0] unsigned_filt;
|
||||
reg [ 0:0] ff1;
|
||||
|
||||
localparam DC_offset = 14'b00111111111111;
|
||||
|
||||
// Voice 1 Instantiation
|
||||
sid_voice v1 (.clock(clk_1MHz), .reset(reset),
|
||||
.freq_lo(Voice_1_Freq_lo), .freq_hi(Voice_1_Freq_hi),
|
||||
.pw_lo(Voice_1_Pw_lo), .pw_hi(Voice_1_Pw_hi),
|
||||
.control(Voice_1_Control),
|
||||
.att_dec(Voice_1_Att_dec), .sus_rel(Voice_1_Sus_Rel),
|
||||
.osc_msb_in(voice_3_PA_MSB), .osc_msb_out(voice_1_PA_MSB),
|
||||
.signal_out(voice_1));
|
||||
|
||||
// Voice 2 Instantiation
|
||||
sid_voice v2 (.clock(clk_1MHz), .reset(reset),
|
||||
.freq_lo(Voice_2_Freq_lo), .freq_hi(Voice_2_Freq_hi),
|
||||
.pw_lo(Voice_2_Pw_lo), .pw_hi(Voice_2_Pw_hi),
|
||||
.control(Voice_2_Control),
|
||||
.att_dec(Voice_2_Att_dec), .sus_rel(Voice_2_Sus_Rel),
|
||||
.osc_msb_in(voice_1_PA_MSB), .osc_msb_out(voice_2_PA_MSB),
|
||||
.signal_out(voice_2));
|
||||
|
||||
// Voice 3 Instantiation
|
||||
sid_voice v3 (.clock(clk_1MHz), .reset(reset),
|
||||
.freq_lo(Voice_3_Freq_lo), .freq_hi(Voice_3_Freq_hi),
|
||||
.pw_lo(Voice_3_Pw_lo), .pw_hi(Voice_3_Pw_hi),
|
||||
.control(Voice_3_Control),
|
||||
.att_dec(Voice_3_Att_dec), .sus_rel(Voice_3_Sus_Rel),
|
||||
.osc_msb_in(voice_2_PA_MSB), .osc_msb_out(voice_3_PA_MSB),
|
||||
.signal_out(voice_3), .osc_out(Misc_Osc3_Random),
|
||||
.env_out(Misc_Env3));
|
||||
|
||||
// Filter Instantiation
|
||||
sid_filters filters (.clk(clk32), .rst(reset),
|
||||
.Fc_lo(Filter_Fc_lo), .Fc_hi(Filter_Fc_hi),
|
||||
.Res_Filt(Filter_Res_Filt), .Mode_Vol(Filter_Mode_Vol),
|
||||
.voice1(voice_1), .voice2(voice_2),
|
||||
.voice3(voice_3), .input_valid(input_valid),
|
||||
.ext_in(12'hfff), .sound(audio_data),
|
||||
.extfilter_en(extfilter_en));
|
||||
|
||||
assign data_out = do_buf;
|
||||
//assign audio_data = {1'b0, (filtered_audio[18:5] + 14'b1000000000000000)};
|
||||
//assign unsigned_filt = filtered_audio + 19'b1000000000000000000;
|
||||
//assign unsigned_audio = unsigned_filt[18:1];
|
||||
//assign audio_data = filtered_audio[18:3];// + 15'h4000;//{1'b0, unsigned_audio[17:1]};
|
||||
|
||||
// Toggle Flip Flop
|
||||
always @(posedge clk_1MHz)
|
||||
begin
|
||||
if (reset)
|
||||
ff1 <= 1'b0;
|
||||
else
|
||||
ff1 <= ~ff1;
|
||||
end
|
||||
|
||||
always @(posedge clk32)
|
||||
begin
|
||||
input_valid <= (tick_q1 != tick_q2) ? 1'b1 : 1'b0;
|
||||
tick_q1 <= ff1;
|
||||
tick_q2 <= tick_q1;
|
||||
end
|
||||
|
||||
reg [7:0] last_wr;
|
||||
|
||||
// Register Decoding
|
||||
always @(posedge clk32)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
Voice_1_Freq_lo <= 8'h00;
|
||||
Voice_1_Freq_hi <= 8'h00;
|
||||
Voice_1_Pw_lo <= 8'h00;
|
||||
Voice_1_Pw_hi <= 4'h0;
|
||||
Voice_1_Control <= 8'h00;
|
||||
Voice_1_Att_dec <= 8'h00;
|
||||
Voice_1_Sus_Rel <= 8'h00;
|
||||
Voice_2_Freq_lo <= 8'h00;
|
||||
Voice_2_Freq_hi <= 8'h00;
|
||||
Voice_2_Pw_lo <= 8'h00;
|
||||
Voice_2_Pw_hi <= 4'h0;
|
||||
Voice_2_Control <= 8'h00;
|
||||
Voice_2_Att_dec <= 8'h00;
|
||||
Voice_2_Sus_Rel <= 8'h00;
|
||||
Voice_3_Freq_lo <= 8'h00;
|
||||
Voice_3_Freq_hi <= 8'h00;
|
||||
Voice_3_Pw_lo <= 8'h00;
|
||||
Voice_3_Pw_hi <= 4'h0;
|
||||
Voice_3_Control <= 8'h00;
|
||||
Voice_3_Att_dec <= 8'h00;
|
||||
Voice_3_Sus_Rel <= 8'h00;
|
||||
Filter_Fc_lo <= 8'h00;
|
||||
Filter_Fc_hi <= 8'h00;
|
||||
Filter_Res_Filt <= 8'h00;
|
||||
Filter_Mode_Vol <= 8'h00;
|
||||
Ext_hi <= 8'h00;
|
||||
Ext_lo <= 4'h0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Voice_1_Freq_lo <= Voice_1_Freq_lo;
|
||||
Voice_1_Freq_hi <= Voice_1_Freq_hi;
|
||||
Voice_1_Pw_lo <= Voice_1_Pw_lo;
|
||||
Voice_1_Pw_hi <= Voice_1_Pw_hi;
|
||||
Voice_1_Control <= Voice_1_Control;
|
||||
Voice_1_Att_dec <= Voice_1_Att_dec;
|
||||
Voice_1_Sus_Rel <= Voice_1_Sus_Rel;
|
||||
Voice_2_Freq_lo <= Voice_2_Freq_lo;
|
||||
Voice_2_Freq_hi <= Voice_2_Freq_hi;
|
||||
Voice_2_Pw_lo <= Voice_2_Pw_lo;
|
||||
Voice_2_Pw_hi <= Voice_2_Pw_hi;
|
||||
Voice_2_Control <= Voice_2_Control;
|
||||
Voice_2_Att_dec <= Voice_2_Att_dec;
|
||||
Voice_2_Sus_Rel <= Voice_2_Sus_Rel;
|
||||
Voice_3_Freq_lo <= Voice_3_Freq_lo;
|
||||
Voice_3_Freq_hi <= Voice_3_Freq_hi;
|
||||
Voice_3_Pw_lo <= Voice_3_Pw_lo;
|
||||
Voice_3_Pw_hi <= Voice_3_Pw_hi;
|
||||
Voice_3_Control <= Voice_3_Control;
|
||||
Voice_3_Att_dec <= Voice_3_Att_dec;
|
||||
Voice_3_Sus_Rel <= Voice_3_Sus_Rel;
|
||||
Filter_Fc_lo <= Filter_Fc_lo;
|
||||
Filter_Fc_hi <= Filter_Fc_hi;
|
||||
Filter_Res_Filt <= Filter_Res_Filt;
|
||||
Filter_Mode_Vol <= Filter_Mode_Vol;
|
||||
Ext_hi <= Ext_hi;
|
||||
Ext_lo <= Ext_lo;
|
||||
do_buf <= 8'h00;
|
||||
end
|
||||
if (cs)
|
||||
begin
|
||||
if (we)
|
||||
begin
|
||||
last_wr <= data_in;
|
||||
case (addr)
|
||||
5'h00: Voice_1_Freq_lo <= data_in;
|
||||
5'h01: Voice_1_Freq_hi <= data_in;
|
||||
5'h02: Voice_1_Pw_lo <= data_in;
|
||||
5'h03: Voice_1_Pw_hi <= data_in[3:0];
|
||||
5'h04: Voice_1_Control <= data_in;
|
||||
5'h05: Voice_1_Att_dec <= data_in;
|
||||
5'h06: Voice_1_Sus_Rel <= data_in;
|
||||
5'h07: Voice_2_Freq_lo <= data_in;
|
||||
5'h08: Voice_2_Freq_hi <= data_in;
|
||||
5'h09: Voice_2_Pw_lo <= data_in;
|
||||
5'h0a: Voice_2_Pw_hi <= data_in[3:0];
|
||||
5'h0b: Voice_2_Control <= data_in;
|
||||
5'h0c: Voice_2_Att_dec <= data_in;
|
||||
5'h0d: Voice_2_Sus_Rel <= data_in;
|
||||
5'h0e: Voice_3_Freq_lo <= data_in;
|
||||
5'h0f: Voice_3_Freq_hi <= data_in;
|
||||
5'h10: Voice_3_Pw_lo <= data_in;
|
||||
5'h11: Voice_3_Pw_hi <= data_in[3:0];
|
||||
5'h12: Voice_3_Control <= data_in;
|
||||
5'h13: Voice_3_Att_dec <= data_in;
|
||||
5'h14: Voice_3_Sus_Rel <= data_in;
|
||||
5'h15: Filter_Fc_lo <= data_in;
|
||||
5'h16: Filter_Fc_hi <= data_in;
|
||||
5'h17: Filter_Res_Filt <= data_in;
|
||||
5'h18: Filter_Mode_Vol <= data_in;
|
||||
5'h19: Ext_lo <= data_in[3:0];
|
||||
5'h1a: Ext_hi <= data_in;
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
else
|
||||
begin
|
||||
case (addr)
|
||||
5'h19: do_buf <= pot_x;
|
||||
5'h1a: do_buf <= pot_y;
|
||||
5'h1b: do_buf <= Misc_Osc3_Random;
|
||||
5'h1c: do_buf <= Misc_Env3;
|
||||
default: do_buf <= last_wr;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
232
cores/c16/sid8580/sid_envelope.v
Normal file
232
cores/c16/sid8580/sid_envelope.v
Normal file
@@ -0,0 +1,232 @@
|
||||
module sid_envelope (clock, reset, gate, att_dec, sus_rel, envelope);
|
||||
|
||||
// Input Signals
|
||||
input wire [ 0:0] clock;
|
||||
input wire [ 0:0] reset;
|
||||
input wire [ 0:0] gate;
|
||||
input wire [ 7:0] att_dec;
|
||||
input wire [ 7:0] sus_rel;
|
||||
|
||||
// Output Signals
|
||||
output reg [7:0] envelope;
|
||||
|
||||
// Internal Signals
|
||||
reg [ 1:0] state;
|
||||
reg [ 0:0] gate_edge;
|
||||
reg [14:0] rate_counter;
|
||||
reg [14:0] rate_period;
|
||||
wire [14:0] adsrtable [0:15];
|
||||
reg [ 7:0] exponential_counter;
|
||||
reg [ 7:0] exponential_counter_period;
|
||||
reg [ 0:0] hold_zero;
|
||||
reg [ 0:0] envelope_pipeline;
|
||||
|
||||
`define ST_ATTACK 2'b00
|
||||
`define ST_DEC_SUS 2'b01
|
||||
`define ST_RELEASE 2'b10
|
||||
|
||||
assign adsrtable[4'h0] = 15'h007f;
|
||||
assign adsrtable[4'h1] = 15'h3000;
|
||||
assign adsrtable[4'h2] = 15'h1e00;
|
||||
assign adsrtable[4'h3] = 15'h0660;
|
||||
assign adsrtable[4'h4] = 15'h0182;
|
||||
assign adsrtable[4'h5] = 15'h5573;
|
||||
assign adsrtable[4'h6] = 15'h000e;
|
||||
assign adsrtable[4'h7] = 15'h3805;
|
||||
assign adsrtable[4'h8] = 15'h2424;
|
||||
assign adsrtable[4'h9] = 15'h2220;
|
||||
assign adsrtable[4'ha] = 15'h090c;
|
||||
assign adsrtable[4'hb] = 15'h0ecd;
|
||||
assign adsrtable[4'hc] = 15'h010e;
|
||||
assign adsrtable[4'hd] = 15'h23f7;
|
||||
assign adsrtable[4'he] = 15'h5237;
|
||||
assign adsrtable[4'hf] = 15'h64a8;
|
||||
|
||||
// State Logic
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
state <= `ST_RELEASE;
|
||||
else
|
||||
begin
|
||||
if (gate_edge != gate)
|
||||
if (gate)
|
||||
state <= `ST_ATTACK;
|
||||
else
|
||||
state <= `ST_RELEASE;
|
||||
if (((rate_counter == rate_period) &&
|
||||
(state == `ST_ATTACK ||
|
||||
(exponential_counter + 1'b1) == exponential_counter_period) &&
|
||||
(!hold_zero)))
|
||||
case (state)
|
||||
`ST_ATTACK:
|
||||
if (envelope + 1'b1 == 8'hff)
|
||||
state <= `ST_DEC_SUS;
|
||||
default:
|
||||
;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// Gate Switch Detection
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
gate_edge <= 1'b0;
|
||||
else
|
||||
if (gate_edge != gate)
|
||||
gate_edge <= gate;
|
||||
end
|
||||
|
||||
// Envelope
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
envelope <= 8'h00;
|
||||
else
|
||||
begin
|
||||
if (envelope_pipeline)
|
||||
envelope <= envelope - 1'b1;
|
||||
if (((rate_counter == rate_period) &&
|
||||
(state == `ST_ATTACK ||
|
||||
(exponential_counter + 1'b1) == exponential_counter_period) &&
|
||||
(!hold_zero)))
|
||||
case (state)
|
||||
`ST_ATTACK:
|
||||
envelope <= envelope + 1'b1;
|
||||
`ST_DEC_SUS:
|
||||
if (envelope != {2{sus_rel[7:4]}} &&
|
||||
exponential_counter_period == 1)
|
||||
envelope <= envelope - 1'b1;
|
||||
`ST_RELEASE:
|
||||
if (exponential_counter_period == 1)
|
||||
envelope <= envelope - 1'b1;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// Envelope Pipeline
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
envelope_pipeline <= 1'b0;
|
||||
else
|
||||
begin
|
||||
if (gate_edge != gate)
|
||||
if (gate)
|
||||
envelope_pipeline <= 1'b0;
|
||||
if (envelope_pipeline)
|
||||
envelope_pipeline <= 1'b0;
|
||||
if (((rate_counter == rate_period) &&
|
||||
(state == `ST_ATTACK ||
|
||||
(exponential_counter + 1'b1) == exponential_counter_period) &&
|
||||
(!hold_zero)))
|
||||
case (state)
|
||||
`ST_DEC_SUS:
|
||||
if (envelope != {2{sus_rel[7:4]}} &&
|
||||
exponential_counter_period != 1)
|
||||
envelope_pipeline <= 1'b1;
|
||||
`ST_RELEASE:
|
||||
if(exponential_counter_period != 1)
|
||||
envelope_pipeline <= 1'b1;
|
||||
default:
|
||||
;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// Exponential Counter
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
exponential_counter <= 8'h00;
|
||||
else
|
||||
begin
|
||||
if (rate_counter == rate_period)
|
||||
begin
|
||||
exponential_counter <= exponential_counter + 1'b1;
|
||||
if (state == `ST_ATTACK ||
|
||||
(exponential_counter + 1'b1) == exponential_counter_period)
|
||||
exponential_counter <= 8'h00;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Exponential Counter Period
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
hold_zero <= 1'b1;
|
||||
exponential_counter_period <= 8'h00;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (gate_edge != gate)
|
||||
if (gate)
|
||||
hold_zero <= 1'b0;
|
||||
if ((envelope_pipeline) || ((rate_counter == rate_period) &&
|
||||
(state == `ST_ATTACK ||
|
||||
(exponential_counter + 1'b1) == exponential_counter_period) &&
|
||||
(!hold_zero)))
|
||||
begin
|
||||
case (state == `ST_ATTACK ? envelope + 1'b1 : envelope - 1'b1)
|
||||
8'hff:
|
||||
exponential_counter_period <= 8'd1;
|
||||
8'h5d:
|
||||
exponential_counter_period <= 8'd2;
|
||||
8'h36:
|
||||
exponential_counter_period <= 8'd4;
|
||||
8'h1a:
|
||||
exponential_counter_period <= 8'd8;
|
||||
8'h0e:
|
||||
exponential_counter_period <= 8'd16;
|
||||
8'h06:
|
||||
exponential_counter_period <= 8'd30;
|
||||
8'h00:
|
||||
begin
|
||||
exponential_counter_period <= 8'd1;
|
||||
hold_zero <= 1'b1;
|
||||
end
|
||||
default:
|
||||
;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Rate Counter
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset || rate_counter == rate_period)
|
||||
rate_counter <= 15'h7fff;
|
||||
else
|
||||
rate_counter <= {rate_counter[1] ^ rate_counter[0], rate_counter[14:1]};
|
||||
end
|
||||
|
||||
// Rate Period
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
rate_period <= adsrtable[sus_rel[3:0]];
|
||||
else
|
||||
begin
|
||||
if (gate_edge != gate)
|
||||
begin
|
||||
if (gate)
|
||||
rate_period <= adsrtable[att_dec[7:4]];
|
||||
else
|
||||
rate_period <= adsrtable[sus_rel[3:0]];
|
||||
end
|
||||
case (state)
|
||||
`ST_ATTACK:
|
||||
rate_period <= adsrtable[att_dec[7:4]];
|
||||
`ST_DEC_SUS:
|
||||
rate_period <= adsrtable[att_dec[3:0]];
|
||||
default:
|
||||
rate_period <= adsrtable[sus_rel[3:0]];
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
184
cores/c16/sid8580/sid_filters.v
Normal file
184
cores/c16/sid8580/sid_filters.v
Normal file
@@ -0,0 +1,184 @@
|
||||
module sid_filters (clk, rst, Fc_lo, Fc_hi, Res_Filt, Mode_Vol,
|
||||
voice1, voice2, voice3, input_valid, ext_in, sound, extfilter_en);
|
||||
|
||||
// Input Signals
|
||||
input wire [ 0:0] clk;
|
||||
input wire [ 0:0] rst;
|
||||
input wire [ 7:0] Fc_lo;
|
||||
input wire [ 7:0] Fc_hi;
|
||||
input wire [ 7:0] Res_Filt;
|
||||
input wire [ 7:0] Mode_Vol;
|
||||
input wire [11:0] voice1;
|
||||
input wire [11:0] voice2;
|
||||
input wire [11:0] voice3;
|
||||
input wire [ 0:0] input_valid;
|
||||
input wire [11:0] ext_in;
|
||||
input wire [ 0:0] extfilter_en;
|
||||
|
||||
// Output Signals
|
||||
output reg [15:0] sound;
|
||||
|
||||
// Internal Signals
|
||||
reg signed [17:0] mula;
|
||||
reg signed [17:0] mulb;
|
||||
reg [35:0] mulr;
|
||||
reg [ 0:0] mulen;
|
||||
|
||||
wire [35:0] mul1;
|
||||
wire [35:0] mul2;
|
||||
wire [35:0] mul3;
|
||||
wire [35:0] mul4;
|
||||
|
||||
wire [10:0] divmul [0:15];
|
||||
|
||||
reg signed [17:0] Vhp;
|
||||
reg signed [17:0] Vbp;
|
||||
reg [17:0] dVbp;
|
||||
reg [17:0] Vlp;
|
||||
reg [17:0] dVlp;
|
||||
reg [17:0] Vi;
|
||||
reg [17:0] Vnf;
|
||||
reg [17:0] Vf;
|
||||
reg signed [17:0] w0;
|
||||
reg signed [17:0] q;
|
||||
reg [ 3:0] state;
|
||||
|
||||
assign divmul[4'h0] = 11'd1448;
|
||||
assign divmul[4'h1] = 11'd1328;
|
||||
assign divmul[4'h2] = 11'd1218;
|
||||
assign divmul[4'h3] = 11'd1117;
|
||||
assign divmul[4'h4] = 11'd1024;
|
||||
assign divmul[4'h5] = 11'd939;
|
||||
assign divmul[4'h6] = 11'd861;
|
||||
assign divmul[4'h7] = 11'd790;
|
||||
assign divmul[4'h8] = 11'd724;
|
||||
assign divmul[4'h9] = 11'd664;
|
||||
assign divmul[4'ha] = 11'd609;
|
||||
assign divmul[4'hb] = 11'd558;
|
||||
assign divmul[4'hc] = 11'd512;
|
||||
assign divmul[4'hd] = 11'd470;
|
||||
assign divmul[4'he] = 11'd431;
|
||||
assign divmul[4'hf] = 11'd395;
|
||||
|
||||
// Multiplier
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (mulen)
|
||||
mulr <= mula * mulb;
|
||||
end
|
||||
|
||||
assign mul1 = w0 * Vhp;
|
||||
assign mul2 = w0 * Vbp;
|
||||
assign mul3 = q * Vbp;
|
||||
assign mul4 = 18'd82355 * ({Fc_hi, Fc_lo[2:0]} + 1'b1);
|
||||
|
||||
// Filter
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (rst)
|
||||
begin
|
||||
state <= 4'h0;
|
||||
Vlp <= 18'h00000;
|
||||
Vbp <= 18'h00000;
|
||||
Vhp <= 18'h00000;
|
||||
end
|
||||
else
|
||||
begin
|
||||
mula <= 18'h00000;
|
||||
mulb <= 18'h00000;
|
||||
mulen <= 1'b0;
|
||||
case (state)
|
||||
4'h0:
|
||||
begin
|
||||
if (input_valid)
|
||||
begin
|
||||
state <= 4'h1;
|
||||
Vi <= 18'h00000;
|
||||
Vnf <= 18'h00000;
|
||||
end
|
||||
end
|
||||
4'h1:
|
||||
begin
|
||||
state <= 4'h2;
|
||||
w0 <= {mul4[35], mul4[28:12]};
|
||||
if (Res_Filt[0])
|
||||
Vi <= Vi + (voice1 << 2);
|
||||
else
|
||||
Vnf <= Vnf + (voice1 << 2);
|
||||
end
|
||||
4'h2:
|
||||
begin
|
||||
state <= 4'h3;
|
||||
if (Res_Filt[1])
|
||||
Vi <= Vi + (voice2 << 2);
|
||||
else
|
||||
Vnf <= Vnf + (voice2 << 2);
|
||||
end
|
||||
4'h3:
|
||||
begin
|
||||
state <= 4'h4;
|
||||
if (Res_Filt[2])
|
||||
Vi <= Vi + (voice3 << 2);
|
||||
else
|
||||
if (!Mode_Vol[7])
|
||||
Vnf <= Vnf + (voice3 << 2);
|
||||
dVbp <= {mul1[35], mul1[35:19]};
|
||||
end
|
||||
4'h4:
|
||||
begin
|
||||
state <= 4'h5;
|
||||
if (Res_Filt[3])
|
||||
Vi <= Vi + (ext_in << 2);
|
||||
else
|
||||
Vnf <= Vnf + (ext_in << 2);
|
||||
dVlp <= {mul2[35], mul2[35:19]};
|
||||
Vbp <= Vbp - dVbp;
|
||||
q <= divmul[Res_Filt[7:4]];
|
||||
end
|
||||
4'h5:
|
||||
begin
|
||||
state <= 4'h6;
|
||||
Vlp <= Vlp - dVlp;
|
||||
Vf <= (Mode_Vol[5]) ? Vbp : 18'h00000;
|
||||
end
|
||||
4'h6:
|
||||
begin
|
||||
state <= 4'h7;
|
||||
Vhp <= {mul3[35], mul3[26:10]} - Vlp;
|
||||
Vf <= (Mode_Vol[4]) ? Vf + Vlp : Vf;
|
||||
end
|
||||
4'h7:
|
||||
begin
|
||||
state <= 4'h8;
|
||||
Vhp <= Vhp - Vi;
|
||||
end
|
||||
4'h8:
|
||||
begin
|
||||
state <= 4'h9;
|
||||
Vf <= (Mode_Vol[6]) ? Vf + Vhp : Vf;
|
||||
end
|
||||
4'h9:
|
||||
begin
|
||||
state <= 4'ha;
|
||||
//Vf <= {~Vf + 1'b1} + Vnf;
|
||||
Vf <= (extfilter_en) ? {~Vf + 1'b1} + Vnf : Vi + Vnf;
|
||||
end
|
||||
4'ha:
|
||||
begin
|
||||
state <= 4'hb;
|
||||
mulen <= 1'b1;
|
||||
mula <= Vf;
|
||||
mulb <= Mode_Vol[3:0];
|
||||
end
|
||||
4'hb:
|
||||
begin
|
||||
state <= 4'h0;
|
||||
sound <= (mulr[21] != mulr[20]) ? sound : mulr[20:5];
|
||||
end
|
||||
default:
|
||||
;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
345
cores/c16/sid8580/sid_voice.v
Normal file
345
cores/c16/sid8580/sid_voice.v
Normal file
@@ -0,0 +1,345 @@
|
||||
module sid_voice (clock, reset, freq_lo, freq_hi, pw_lo, pw_hi,
|
||||
control, att_dec, sus_rel, osc_msb_in, osc_msb_out,
|
||||
signal_out, osc_out, env_out);
|
||||
|
||||
// Input Signals
|
||||
input wire [0:0] clock;
|
||||
input wire [0:0] reset;
|
||||
input wire [7:0] freq_lo;
|
||||
input wire [7:0] freq_hi;
|
||||
input wire [7:0] pw_lo;
|
||||
input wire [3:0] pw_hi;
|
||||
input wire [7:0] control;
|
||||
input wire [7:0] att_dec;
|
||||
input wire [7:0] sus_rel;
|
||||
input wire [0:0] osc_msb_in;
|
||||
|
||||
// Output Signals
|
||||
output wire [ 0:0] osc_msb_out;
|
||||
output wire [11:0] signal_out;
|
||||
output wire [ 7:0] osc_out;
|
||||
output wire [ 7:0] env_out;
|
||||
|
||||
// Internal Signals
|
||||
reg [23:0] oscillator;
|
||||
reg [ 0:0] osc_edge;
|
||||
reg [ 0:0] osc_msb_in_prv;
|
||||
reg [11:0] triangle;
|
||||
reg [11:0] sawtooth;
|
||||
reg [11:0] pulse;
|
||||
reg [11:0] noise;
|
||||
reg [22:0] lfsr_noise;
|
||||
wire [ 7:0] envelope;
|
||||
reg [11:0] wave_out;
|
||||
reg [19:0] dca_out;
|
||||
|
||||
`define noise_ctrl control[7]
|
||||
`define pulse_ctrl control[6]
|
||||
`define saw_ctrl control[5]
|
||||
`define tri_ctrl control[4]
|
||||
`define test_ctrl control[3]
|
||||
`define ringmod_ctrl control[2]
|
||||
`define sync_ctrl control[1]
|
||||
|
||||
// Signal Assignments
|
||||
assign osc_msb_out = oscillator[23];
|
||||
assign signal_out = dca_out[19:8];
|
||||
assign osc_out = wave_out[11:4];
|
||||
assign env_out = envelope;
|
||||
|
||||
// Digital Controlled Amplifier
|
||||
always @(posedge clock)
|
||||
begin
|
||||
dca_out <= wave_out * envelope;
|
||||
end
|
||||
|
||||
// Envelope Instantiation
|
||||
sid_envelope adsr (.clock(clock), .reset(reset), .gate(control[0]),
|
||||
.att_dec(att_dec), .sus_rel(sus_rel), .envelope(envelope));
|
||||
|
||||
// Phase Accumulating Oscillator
|
||||
always @(posedge clock)
|
||||
begin
|
||||
osc_msb_in_prv <= osc_msb_in;
|
||||
if (reset || `test_ctrl ||
|
||||
((`sync_ctrl) && (!osc_msb_in) && (osc_msb_in != osc_msb_in_prv)))
|
||||
oscillator <= 24'h000000;
|
||||
else
|
||||
oscillator <= oscillator + {freq_hi, freq_lo};
|
||||
end
|
||||
|
||||
// Waveform Generator
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
triangle <= 12'h000;
|
||||
sawtooth <= 12'h000;
|
||||
pulse <= 12'h000;
|
||||
noise <= 12'h000;
|
||||
osc_edge <= 1'b0;
|
||||
lfsr_noise <= 23'h7fffff;
|
||||
end
|
||||
else
|
||||
begin
|
||||
triangle <= (`ringmod_ctrl) ?
|
||||
{({11{osc_msb_in}} ^
|
||||
{{11{oscillator[23]}}}) ^ oscillator[22:12], 1'b0} :
|
||||
{{11{oscillator[23]}} ^ oscillator[22:12], 1'b0};
|
||||
sawtooth <= oscillator[23:12];
|
||||
pulse <= (`test_ctrl) ? 12'hfff :
|
||||
(oscillator[23:12] >= {pw_hi, pw_lo}) ? {12{1'b1}} : {12{1'b0}};
|
||||
noise <= {lfsr_noise[21], lfsr_noise[19], lfsr_noise[15],
|
||||
lfsr_noise[12], lfsr_noise[10], lfsr_noise[6],
|
||||
lfsr_noise[3], lfsr_noise[1], 4'b0000};
|
||||
osc_edge <= (oscillator[19] && !osc_edge) ? 1'b1 :
|
||||
(!oscillator[19] && osc_edge) ? 1'b0 : osc_edge;
|
||||
lfsr_noise <= (oscillator[19] && !osc_edge) ?
|
||||
{lfsr_noise[21:0], (lfsr_noise[22] | `test_ctrl) ^
|
||||
lfsr_noise[17]} : lfsr_noise;
|
||||
end
|
||||
end
|
||||
|
||||
// Waveform Output Selector
|
||||
always @(*) begin
|
||||
case (control[7:4])
|
||||
4'b0001: wave_out = triangle;
|
||||
4'b0010: wave_out = sawtooth;
|
||||
4'b0011: wave_out = {wave__st[sawtooth], 4'b0000};
|
||||
4'b0100: wave_out = pulse;
|
||||
4'b0101: wave_out = {wave_p_t[triangle[11:1]], 4'b0000} & pulse;
|
||||
4'b0110: wave_out = {wave_ps_[sawtooth], 4'b0000} & pulse;
|
||||
4'b0111: wave_out = {wave_pst[sawtooth], 4'b0000} & pulse;
|
||||
4'b1000: wave_out = noise;
|
||||
default: wave_out = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
//
|
||||
// more efficient wave table (uses half LCs than the original) (Sorgelig)
|
||||
//
|
||||
|
||||
reg [7:0] wave__st[4096];
|
||||
reg [7:0] wave_p_t[2048];
|
||||
reg [7:0] wave_ps_[4096];
|
||||
reg [7:0] wave_pst[4096];
|
||||
|
||||
initial begin
|
||||
integer i;
|
||||
for(i = 0; i<4096; i=i+1) wave__st[i] =
|
||||
(i < 'h07e) ? 8'h00 : (i < 'h080) ? 8'h03 : (i < 'h0fc) ? 8'h00 : (i < 'h100) ? 8'h07 :
|
||||
(i < 'h17e) ? 8'h00 : (i < 'h180) ? 8'h03 : (i < 'h1f8) ? 8'h00 : (i < 'h1fc) ? 8'h0e :
|
||||
(i < 'h200) ? 8'h0f : (i < 'h27e) ? 8'h00 : (i < 'h280) ? 8'h03 : (i < 'h2fc) ? 8'h00 :
|
||||
(i < 'h300) ? 8'h07 : (i < 'h37e) ? 8'h00 : (i < 'h380) ? 8'h03 : (i < 'h3bf) ? 8'h00 :
|
||||
(i < 'h3c0) ? 8'h01 : (i < 'h3f0) ? 8'h00 : (i < 'h3f8) ? 8'h1c : (i < 'h3fa) ? 8'h1e :
|
||||
(i < 'h400) ? 8'h1f : (i < 'h47e) ? 8'h00 : (i < 'h480) ? 8'h03 : (i < 'h4fc) ? 8'h00 :
|
||||
(i < 'h500) ? 8'h07 : (i < 'h57e) ? 8'h00 : (i < 'h580) ? 8'h03 : (i < 'h5f8) ? 8'h00 :
|
||||
(i < 'h5fc) ? 8'h0e : (i < 'h5ff) ? 8'h0f : (i < 'h600) ? 8'h1f : (i < 'h67e) ? 8'h00 :
|
||||
(i < 'h680) ? 8'h03 : (i < 'h6fc) ? 8'h00 : (i < 'h700) ? 8'h07 : (i < 'h77e) ? 8'h00 :
|
||||
(i < 'h780) ? 8'h03 : (i < 'h7bf) ? 8'h00 : (i < 'h7c0) ? 8'h01 : (i < 'h7e0) ? 8'h00 :
|
||||
(i < 'h7f0) ? 8'h38 : (i < 'h7f7) ? 8'h3c : (i < 'h7f8) ? 8'h3e : (i < 'h800) ? 8'h7f :
|
||||
(i < 'h87e) ? 8'h00 : (i < 'h880) ? 8'h03 : (i < 'h8fc) ? 8'h00 : (i < 'h900) ? 8'h07 :
|
||||
(i < 'h97e) ? 8'h00 : (i < 'h980) ? 8'h03 : (i < 'h9f8) ? 8'h00 : (i < 'h9fc) ? 8'h0e :
|
||||
(i < 'ha00) ? 8'h0f : (i < 'ha7e) ? 8'h00 : (i < 'ha80) ? 8'h03 : (i < 'hafc) ? 8'h00 :
|
||||
(i < 'hb00) ? 8'h07 : (i < 'hb7e) ? 8'h00 : (i < 'hb80) ? 8'h03 : (i < 'hbbf) ? 8'h00 :
|
||||
(i < 'hbc0) ? 8'h01 : (i < 'hbf0) ? 8'h00 : (i < 'hbf8) ? 8'h1c : (i < 'hbfa) ? 8'h1e :
|
||||
(i < 'hbfe) ? 8'h1f : (i < 'hc00) ? 8'h3f : (i < 'hc7e) ? 8'h00 : (i < 'hc80) ? 8'h03 :
|
||||
(i < 'hcfc) ? 8'h00 : (i < 'hd00) ? 8'h07 : (i < 'hd7e) ? 8'h00 : (i < 'hd80) ? 8'h03 :
|
||||
(i < 'hdbf) ? 8'h00 : (i < 'hdc0) ? 8'h01 : (i < 'hdf8) ? 8'h00 : (i < 'hdfc) ? 8'h0e :
|
||||
(i < 'hdfe) ? 8'h0f : (i < 'he00) ? 8'h1f : (i < 'he7c) ? 8'h00 : (i < 'he7d) ? 8'h80 :
|
||||
(i < 'he7e) ? 8'h00 : (i < 'he80) ? 8'h83 : (i < 'hefc) ? 8'h80 : (i < 'heff) ? 8'h87 :
|
||||
(i < 'hf00) ? 8'h8f : (i < 'hf01) ? 8'hc0 : (i < 'hf03) ? 8'he0 : (i < 'hf05) ? 8'hc0 :
|
||||
(i < 'hf09) ? 8'he0 : (i < 'hf11) ? 8'hc0 : (i < 'hf13) ? 8'he0 : (i < 'hf18) ? 8'hc0 :
|
||||
(i < 'hf19) ? 8'he0 : (i < 'hf21) ? 8'hc0 : (i < 'hf23) ? 8'he0 : (i < 'hf25) ? 8'hc0 :
|
||||
(i < 'hf2b) ? 8'he0 : (i < 'hf2c) ? 8'hc0 : (i < 'hf2d) ? 8'he0 : (i < 'hf2e) ? 8'hc0 :
|
||||
(i < 'hf7e) ? 8'he0 : (i < 'hf80) ? 8'he3 : (i < 'hfbf) ? 8'hf0 : (i < 'hfc0) ? 8'hf1 :
|
||||
(i < 'hfe0) ? 8'hf8 : (i < 'hff0) ? 8'hfc : (i < 'hff8) ? 8'hfe : 8'hff;
|
||||
|
||||
for(i = 0; i<2048; i=i+1) wave_p_t[i] =
|
||||
(i < 'h0ff) ? 8'h00 : (i < 'h100) ? 8'h07 : (i < 'h1fb) ? 8'h00 : (i < 'h1fc) ? 8'h1c :
|
||||
(i < 'h1fd) ? 8'h00 : (i < 'h1fe) ? 8'h3c : (i < 'h200) ? 8'h3f : (i < 'h2fd) ? 8'h00 :
|
||||
(i < 'h2fe) ? 8'h0c : (i < 'h2ff) ? 8'h5e : (i < 'h300) ? 8'h5f : (i < 'h377) ? 8'h00 :
|
||||
(i < 'h378) ? 8'h40 : (i < 'h37b) ? 8'h00 : (i < 'h37d) ? 8'h40 : (i < 'h37f) ? 8'h60 :
|
||||
(i < 'h380) ? 8'h6f : (i < 'h39f) ? 8'h00 : (i < 'h3a0) ? 8'h40 : (i < 'h3ae) ? 8'h00 :
|
||||
(i < 'h3b0) ? 8'h40 : (i < 'h3b3) ? 8'h00 : (i < 'h3b7) ? 8'h40 : (i < 'h3b8) ? 8'h60 :
|
||||
(i < 'h3ba) ? 8'h40 : (i < 'h3be) ? 8'h60 : (i < 'h3bf) ? 8'h70 : (i < 'h3c0) ? 8'h77 :
|
||||
(i < 'h3c5) ? 8'h00 : (i < 'h3cd) ? 8'h40 : (i < 'h3d0) ? 8'h60 : (i < 'h3d3) ? 8'h40 :
|
||||
(i < 'h3d7) ? 8'h60 : (i < 'h3d8) ? 8'h70 : (i < 'h3db) ? 8'h60 : (i < 'h3de) ? 8'h70 :
|
||||
(i < 'h3df) ? 8'h78 : (i < 'h3e0) ? 8'h7b : (i < 'h3e3) ? 8'h60 : (i < 'h3e4) ? 8'h70 :
|
||||
(i < 'h3e5) ? 8'h60 : (i < 'h3eb) ? 8'h70 : (i < 'h3ef) ? 8'h78 : (i < 'h3f0) ? 8'h7c :
|
||||
(i < 'h3f3) ? 8'h78 : (i < 'h3f4) ? 8'h7c : (i < 'h3f5) ? 8'h78 : (i < 'h3f7) ? 8'h7c :
|
||||
(i < 'h3f8) ? 8'h7e : (i < 'h3f9) ? 8'h7c : (i < 'h3fb) ? 8'h7e : (i < 'h400) ? 8'h7f :
|
||||
(i < 'h47f) ? 8'h00 : (i < 'h480) ? 8'h80 : (i < 'h4bd) ? 8'h00 : (i < 'h4c0) ? 8'h80 :
|
||||
(i < 'h4cf) ? 8'h00 : (i < 'h4d0) ? 8'h80 : (i < 'h4d7) ? 8'h00 : (i < 'h4d8) ? 8'h80 :
|
||||
(i < 'h4da) ? 8'h00 : (i < 'h4e0) ? 8'h80 : (i < 'h4e3) ? 8'h00 : (i < 'h4fe) ? 8'h80 :
|
||||
(i < 'h4ff) ? 8'h8e : (i < 'h500) ? 8'h9f : (i < 'h51f) ? 8'h00 : (i < 'h520) ? 8'h80 :
|
||||
(i < 'h52b) ? 8'h00 : (i < 'h52c) ? 8'h80 : (i < 'h52d) ? 8'h00 : (i < 'h530) ? 8'h80 :
|
||||
(i < 'h532) ? 8'h00 : (i < 'h540) ? 8'h80 : (i < 'h543) ? 8'h00 : (i < 'h544) ? 8'h80 :
|
||||
(i < 'h545) ? 8'h00 : (i < 'h57f) ? 8'h80 : (i < 'h580) ? 8'haf : (i < 'h5bb) ? 8'h80 :
|
||||
(i < 'h5bf) ? 8'ha0 : (i < 'h5c0) ? 8'hb7 : (i < 'h5cf) ? 8'h80 : (i < 'h5d0) ? 8'ha0 :
|
||||
(i < 'h5d6) ? 8'h80 : (i < 'h5db) ? 8'ha0 : (i < 'h5dc) ? 8'hb0 : (i < 'h5dd) ? 8'ha0 :
|
||||
(i < 'h5df) ? 8'hb0 : (i < 'h5e0) ? 8'hbb : (i < 'h5e6) ? 8'ha0 : (i < 'h5e8) ? 8'hb0 :
|
||||
(i < 'h5e9) ? 8'ha0 : (i < 'h5eb) ? 8'hb0 : (i < 'h5ec) ? 8'hb8 : (i < 'h5ed) ? 8'hb0 :
|
||||
(i < 'h5ef) ? 8'hb8 : (i < 'h5f0) ? 8'hbc : (i < 'h5f1) ? 8'hb0 : (i < 'h5f5) ? 8'hb8 :
|
||||
(i < 'h5f7) ? 8'hbc : (i < 'h5f8) ? 8'hbe : (i < 'h5fa) ? 8'hbc : (i < 'h5fb) ? 8'hbe :
|
||||
(i < 'h5fc) ? 8'hbf : (i < 'h5fd) ? 8'hbe : (i < 'h600) ? 8'hbf : (i < 'h63e) ? 8'h80 :
|
||||
(i < 'h640) ? 8'hc0 : (i < 'h657) ? 8'h80 : (i < 'h658) ? 8'hc0 : (i < 'h65a) ? 8'h80 :
|
||||
(i < 'h660) ? 8'hc0 : (i < 'h663) ? 8'h80 : (i < 'h664) ? 8'hc0 : (i < 'h665) ? 8'h80 :
|
||||
(i < 'h67f) ? 8'hc0 : (i < 'h680) ? 8'hcf : (i < 'h686) ? 8'h80 : (i < 'h689) ? 8'hc0 :
|
||||
(i < 'h68a) ? 8'h80 : (i < 'h6bf) ? 8'hc0 : (i < 'h6c0) ? 8'hd7 : (i < 'h6dd) ? 8'hc0 :
|
||||
(i < 'h6df) ? 8'hd0 : (i < 'h6e0) ? 8'hd9 : (i < 'h6e7) ? 8'hc0 : (i < 'h6e8) ? 8'hd0 :
|
||||
(i < 'h6e9) ? 8'hc0 : (i < 'h6ed) ? 8'hd0 : (i < 'h6ef) ? 8'hd8 : (i < 'h6f0) ? 8'hdc :
|
||||
(i < 'h6f2) ? 8'hd0 : (i < 'h6f5) ? 8'hd8 : (i < 'h6f7) ? 8'hdc : (i < 'h6f8) ? 8'hde :
|
||||
(i < 'h6fa) ? 8'hdc : (i < 'h6fb) ? 8'hde : (i < 'h6fc) ? 8'hdf : (i < 'h6fd) ? 8'hde :
|
||||
(i < 'h700) ? 8'hdf : (i < 'h71b) ? 8'hc0 : (i < 'h71c) ? 8'he0 : (i < 'h71d) ? 8'hc0 :
|
||||
(i < 'h720) ? 8'he0 : (i < 'h727) ? 8'hc0 : (i < 'h728) ? 8'he0 : (i < 'h72a) ? 8'hc0 :
|
||||
(i < 'h73f) ? 8'he0 : (i < 'h740) ? 8'he7 : (i < 'h75f) ? 8'he0 : (i < 'h760) ? 8'he8 :
|
||||
(i < 'h76e) ? 8'he0 : (i < 'h76f) ? 8'he8 : (i < 'h770) ? 8'hec : (i < 'h773) ? 8'he0 :
|
||||
(i < 'h776) ? 8'he8 : (i < 'h777) ? 8'hec : (i < 'h778) ? 8'hee : (i < 'h77b) ? 8'hec :
|
||||
(i < 'h77d) ? 8'hee : (i < 'h780) ? 8'hef : (i < 'h78d) ? 8'he0 : (i < 'h790) ? 8'hf0 :
|
||||
(i < 'h792) ? 8'he0 : (i < 'h7af) ? 8'hf0 : (i < 'h7b0) ? 8'hf4 : (i < 'h7b7) ? 8'hf0 :
|
||||
(i < 'h7b8) ? 8'hf4 : (i < 'h7b9) ? 8'hf0 : (i < 'h7bb) ? 8'hf4 : (i < 'h7bd) ? 8'hf6 :
|
||||
(i < 'h7c0) ? 8'hf7 : (i < 'h7c3) ? 8'hf0 : (i < 'h7c4) ? 8'hf8 : (i < 'h7c5) ? 8'hf0 :
|
||||
(i < 'h7db) ? 8'hf8 : (i < 'h7dd) ? 8'hfa : (i < 'h7e0) ? 8'hfb : (i < 'h7e1) ? 8'hf8 :
|
||||
(i < 'h7ed) ? 8'hfc : (i < 'h7f0) ? 8'hfd : (i < 'h7f8) ? 8'hfe : 8'hff;
|
||||
|
||||
for(i = 0; i<4096; i=i+1) wave_ps_[i] =
|
||||
(i < 'h07f) ? 8'h00 : (i < 'h080) ? 8'h03 : (i < 'h0bf) ? 8'h00 : (i < 'h0c0) ? 8'h01 :
|
||||
(i < 'h0ff) ? 8'h00 : (i < 'h100) ? 8'h0f : (i < 'h17f) ? 8'h00 : (i < 'h180) ? 8'h07 :
|
||||
(i < 'h1bf) ? 8'h00 : (i < 'h1c0) ? 8'h03 : (i < 'h1df) ? 8'h00 : (i < 'h1e0) ? 8'h01 :
|
||||
(i < 'h1fd) ? 8'h00 : (i < 'h1ff) ? 8'h07 : (i < 'h200) ? 8'h1f : (i < 'h27f) ? 8'h00 :
|
||||
(i < 'h280) ? 8'h03 : (i < 'h2bf) ? 8'h00 : (i < 'h2c0) ? 8'h03 : (i < 'h2df) ? 8'h00 :
|
||||
(i < 'h2e0) ? 8'h01 : (i < 'h2fe) ? 8'h00 : (i < 'h2ff) ? 8'h01 : (i < 'h300) ? 8'h0f :
|
||||
(i < 'h33f) ? 8'h00 : (i < 'h340) ? 8'h01 : (i < 'h37f) ? 8'h00 : (i < 'h380) ? 8'h17 :
|
||||
(i < 'h3bf) ? 8'h00 : (i < 'h3c0) ? 8'h3b : (i < 'h3df) ? 8'h00 : (i < 'h3e0) ? 8'h3d :
|
||||
(i < 'h3ef) ? 8'h00 : (i < 'h3f0) ? 8'h3e : (i < 'h3f7) ? 8'h00 : (i < 'h3f8) ? 8'h3f :
|
||||
(i < 'h3f9) ? 8'h00 : (i < 'h3fa) ? 8'h0c : (i < 'h3fb) ? 8'h1c : (i < 'h3fc) ? 8'h3f :
|
||||
(i < 'h3fd) ? 8'h1e : (i < 'h400) ? 8'h3f : (i < 'h47f) ? 8'h00 : (i < 'h480) ? 8'h03 :
|
||||
(i < 'h4bf) ? 8'h00 : (i < 'h4c0) ? 8'h01 : (i < 'h4ff) ? 8'h00 : (i < 'h500) ? 8'h0f :
|
||||
(i < 'h53f) ? 8'h00 : (i < 'h540) ? 8'h01 : (i < 'h57f) ? 8'h00 : (i < 'h580) ? 8'h07 :
|
||||
(i < 'h5bf) ? 8'h00 : (i < 'h5c0) ? 8'h0b : (i < 'h5df) ? 8'h00 : (i < 'h5e0) ? 8'h0a :
|
||||
(i < 'h5ef) ? 8'h00 : (i < 'h5f0) ? 8'h5e : (i < 'h5f7) ? 8'h00 : (i < 'h5f8) ? 8'h5f :
|
||||
(i < 'h5fb) ? 8'h00 : (i < 'h5fc) ? 8'h5f : (i < 'h5fd) ? 8'h0c : (i < 'h600) ? 8'h5f :
|
||||
(i < 'h63f) ? 8'h00 : (i < 'h640) ? 8'h01 : (i < 'h67f) ? 8'h00 : (i < 'h680) ? 8'h47 :
|
||||
(i < 'h6bf) ? 8'h00 : (i < 'h6c0) ? 8'h43 : (i < 'h6df) ? 8'h00 : (i < 'h6e0) ? 8'h65 :
|
||||
(i < 'h6ef) ? 8'h00 : (i < 'h6f0) ? 8'h6e : (i < 'h6f7) ? 8'h00 : (i < 'h6f8) ? 8'h6f :
|
||||
(i < 'h6f9) ? 8'h00 : (i < 'h6fb) ? 8'h40 : (i < 'h6fc) ? 8'h6f : (i < 'h6fd) ? 8'h40 :
|
||||
(i < 'h700) ? 8'h6f : (i < 'h73f) ? 8'h00 : (i < 'h740) ? 8'h63 : (i < 'h75e) ? 8'h00 :
|
||||
(i < 'h75f) ? 8'h40 : (i < 'h760) ? 8'h61 : (i < 'h767) ? 8'h00 : (i < 'h768) ? 8'h40 :
|
||||
(i < 'h76b) ? 8'h00 : (i < 'h76c) ? 8'h40 : (i < 'h76d) ? 8'h00 : (i < 'h76f) ? 8'h40 :
|
||||
(i < 'h770) ? 8'h70 : (i < 'h772) ? 8'h00 : (i < 'h777) ? 8'h40 : (i < 'h778) ? 8'h70 :
|
||||
(i < 'h779) ? 8'h40 : (i < 'h77b) ? 8'h60 : (i < 'h77c) ? 8'h77 : (i < 'h77d) ? 8'h60 :
|
||||
(i < 'h780) ? 8'h77 : (i < 'h78f) ? 8'h00 : (i < 'h790) ? 8'h40 : (i < 'h796) ? 8'h00 :
|
||||
(i < 'h797) ? 8'h40 : (i < 'h798) ? 8'h60 : (i < 'h799) ? 8'h00 : (i < 'h79b) ? 8'h40 :
|
||||
(i < 'h79c) ? 8'h60 : (i < 'h79d) ? 8'h40 : (i < 'h79f) ? 8'h60 : (i < 'h7a0) ? 8'h79 :
|
||||
(i < 'h7a1) ? 8'h00 : (i < 'h7a7) ? 8'h40 : (i < 'h7a8) ? 8'h60 : (i < 'h7ab) ? 8'h40 :
|
||||
(i < 'h7af) ? 8'h60 : (i < 'h7b0) ? 8'h78 : (i < 'h7b1) ? 8'h40 : (i < 'h7b7) ? 8'h60 :
|
||||
(i < 'h7b8) ? 8'h78 : (i < 'h7b9) ? 8'h60 : (i < 'h7bb) ? 8'h70 : (i < 'h7bc) ? 8'h78 :
|
||||
(i < 'h7bd) ? 8'h70 : (i < 'h7be) ? 8'h79 : (i < 'h7c0) ? 8'h7b : (i < 'h7c7) ? 8'h60 :
|
||||
(i < 'h7c8) ? 8'h70 : (i < 'h7cb) ? 8'h60 : (i < 'h7cc) ? 8'h70 : (i < 'h7cd) ? 8'h60 :
|
||||
(i < 'h7cf) ? 8'h70 : (i < 'h7d0) ? 8'h7c : (i < 'h7d1) ? 8'h60 : (i < 'h7d7) ? 8'h70 :
|
||||
(i < 'h7d8) ? 8'h7c : (i < 'h7d9) ? 8'h70 : (i < 'h7db) ? 8'h78 : (i < 'h7dc) ? 8'h7c :
|
||||
(i < 'h7dd) ? 8'h78 : (i < 'h7df) ? 8'h7c : (i < 'h7e0) ? 8'h7d : (i < 'h7e1) ? 8'h70 :
|
||||
(i < 'h7e7) ? 8'h78 : (i < 'h7e8) ? 8'h7c : (i < 'h7e9) ? 8'h78 : (i < 'h7eb) ? 8'h7c :
|
||||
(i < 'h7ec) ? 8'h7e : (i < 'h7ed) ? 8'h7c : (i < 'h7f0) ? 8'h7e : (i < 'h7f3) ? 8'h7c :
|
||||
(i < 'h7f5) ? 8'h7e : (i < 'h7f8) ? 8'h7f : (i < 'h7f9) ? 8'h7e : (i < 'h7ff) ? 8'h7f :
|
||||
(i < 'h800) ? 8'hff : (i < 'h87f) ? 8'h00 : (i < 'h880) ? 8'h03 : (i < 'h8bf) ? 8'h00 :
|
||||
(i < 'h8c0) ? 8'h01 : (i < 'h8ff) ? 8'h00 : (i < 'h900) ? 8'h8f : (i < 'h93f) ? 8'h00 :
|
||||
(i < 'h940) ? 8'h01 : (i < 'h97f) ? 8'h00 : (i < 'h980) ? 8'h87 : (i < 'h9bf) ? 8'h00 :
|
||||
(i < 'h9c0) ? 8'h83 : (i < 'h9de) ? 8'h00 : (i < 'h9df) ? 8'h80 : (i < 'h9e0) ? 8'h8d :
|
||||
(i < 'h9e7) ? 8'h00 : (i < 'h9e8) ? 8'h80 : (i < 'h9eb) ? 8'h00 : (i < 'h9ec) ? 8'h80 :
|
||||
(i < 'h9ed) ? 8'h00 : (i < 'h9ef) ? 8'h80 : (i < 'h9f0) ? 8'h8e : (i < 'h9f3) ? 8'h00 :
|
||||
(i < 'h9f7) ? 8'h80 : (i < 'h9f8) ? 8'h8f : (i < 'h9fb) ? 8'h80 : (i < 'h9fc) ? 8'h9f :
|
||||
(i < 'h9fd) ? 8'h80 : (i < 'ha00) ? 8'h9f : (i < 'ha3f) ? 8'h00 : (i < 'ha40) ? 8'h01 :
|
||||
(i < 'ha6f) ? 8'h00 : (i < 'ha70) ? 8'h80 : (i < 'ha77) ? 8'h00 : (i < 'ha78) ? 8'h80 :
|
||||
(i < 'ha7b) ? 8'h00 : (i < 'ha7c) ? 8'h80 : (i < 'ha7d) ? 8'h00 : (i < 'ha7f) ? 8'h80 :
|
||||
(i < 'ha80) ? 8'h87 : (i < 'ha9f) ? 8'h00 : (i < 'haa0) ? 8'h80 : (i < 'haaf) ? 8'h00 :
|
||||
(i < 'hab0) ? 8'h80 : (i < 'hab7) ? 8'h00 : (i < 'hab8) ? 8'h80 : (i < 'habb) ? 8'h00 :
|
||||
(i < 'habf) ? 8'h80 : (i < 'hac0) ? 8'h83 : (i < 'hacf) ? 8'h00 : (i < 'had0) ? 8'h80 :
|
||||
(i < 'had5) ? 8'h00 : (i < 'had8) ? 8'h80 : (i < 'had9) ? 8'h00 : (i < 'hadf) ? 8'h80 :
|
||||
(i < 'hae0) ? 8'h81 : (i < 'haef) ? 8'h80 : (i < 'haf0) ? 8'h84 : (i < 'haf7) ? 8'h80 :
|
||||
(i < 'haf8) ? 8'h87 : (i < 'hafb) ? 8'h80 : (i < 'hafc) ? 8'h87 : (i < 'hafd) ? 8'h80 :
|
||||
(i < 'hafe) ? 8'h8f : (i < 'hb00) ? 8'haf : (i < 'hb0f) ? 8'h00 : (i < 'hb10) ? 8'h80 :
|
||||
(i < 'hb17) ? 8'h00 : (i < 'hb18) ? 8'h80 : (i < 'hb1b) ? 8'h00 : (i < 'hb20) ? 8'h80 :
|
||||
(i < 'hb23) ? 8'h00 : (i < 'hb24) ? 8'h80 : (i < 'hb26) ? 8'h00 : (i < 'hb28) ? 8'h80 :
|
||||
(i < 'hb29) ? 8'h00 : (i < 'hb3f) ? 8'h80 : (i < 'hb40) ? 8'h83 : (i < 'hb5f) ? 8'h80 :
|
||||
(i < 'hb60) ? 8'h81 : (i < 'hb6f) ? 8'h80 : (i < 'hb70) ? 8'ha0 : (i < 'hb77) ? 8'h80 :
|
||||
(i < 'hb78) ? 8'ha0 : (i < 'hb7b) ? 8'h80 : (i < 'hb7c) ? 8'ha0 : (i < 'hb7d) ? 8'h80 :
|
||||
(i < 'hb7e) ? 8'ha3 : (i < 'hb80) ? 8'hb7 : (i < 'hb9f) ? 8'h80 : (i < 'hba0) ? 8'hb1 :
|
||||
(i < 'hbaf) ? 8'h80 : (i < 'hbb0) ? 8'hb0 : (i < 'hbb7) ? 8'h80 : (i < 'hbb8) ? 8'hb0 :
|
||||
(i < 'hbb9) ? 8'h80 : (i < 'hbbb) ? 8'ha0 : (i < 'hbbc) ? 8'hb0 : (i < 'hbbd) ? 8'ha0 :
|
||||
(i < 'hbbe) ? 8'hb8 : (i < 'hbbf) ? 8'hb9 : (i < 'hbc0) ? 8'hbb : (i < 'hbc7) ? 8'h80 :
|
||||
(i < 'hbc8) ? 8'ha0 : (i < 'hbcb) ? 8'h80 : (i < 'hbcc) ? 8'ha0 : (i < 'hbcd) ? 8'h80 :
|
||||
(i < 'hbcf) ? 8'ha0 : (i < 'hbd0) ? 8'hb8 : (i < 'hbd1) ? 8'h80 : (i < 'hbd7) ? 8'ha0 :
|
||||
(i < 'hbd8) ? 8'hb8 : (i < 'hbd9) ? 8'ha0 : (i < 'hbdb) ? 8'hb0 : (i < 'hbdc) ? 8'hb8 :
|
||||
(i < 'hbdd) ? 8'hb0 : (i < 'hbdf) ? 8'hbc : (i < 'hbe0) ? 8'hbd : (i < 'hbe1) ? 8'ha0 :
|
||||
(i < 'hbe5) ? 8'hb0 : (i < 'hbe7) ? 8'hb8 : (i < 'hbe8) ? 8'hbc : (i < 'hbe9) ? 8'hb0 :
|
||||
(i < 'hbeb) ? 8'hb8 : (i < 'hbec) ? 8'hbc : (i < 'hbed) ? 8'hb8 : (i < 'hbee) ? 8'hbc :
|
||||
(i < 'hbf0) ? 8'hbe : (i < 'hbf1) ? 8'hb8 : (i < 'hbf3) ? 8'hbc : (i < 'hbf4) ? 8'hbe :
|
||||
(i < 'hbf5) ? 8'hbc : (i < 'hbf7) ? 8'hbe : (i < 'hbf8) ? 8'hbf : (i < 'hbf9) ? 8'hbe :
|
||||
(i < 'hc00) ? 8'hbf : (i < 'hc03) ? 8'h00 : (i < 'hc04) ? 8'h80 : (i < 'hc07) ? 8'h00 :
|
||||
(i < 'hc08) ? 8'h80 : (i < 'hc0b) ? 8'h00 : (i < 'hc0c) ? 8'h80 : (i < 'hc0f) ? 8'h00 :
|
||||
(i < 'hc10) ? 8'h80 : (i < 'hc11) ? 8'h00 : (i < 'hc18) ? 8'h80 : (i < 'hc19) ? 8'h00 :
|
||||
(i < 'hc3f) ? 8'h80 : (i < 'hc40) ? 8'h81 : (i < 'hc7f) ? 8'h80 : (i < 'hc80) ? 8'hc7 :
|
||||
(i < 'hcbe) ? 8'h80 : (i < 'hcbf) ? 8'hc0 : (i < 'hcc0) ? 8'hc3 : (i < 'hccf) ? 8'h80 :
|
||||
(i < 'hcd0) ? 8'hc0 : (i < 'hcd7) ? 8'h80 : (i < 'hcd8) ? 8'hc0 : (i < 'hcdb) ? 8'h80 :
|
||||
(i < 'hcdc) ? 8'hc0 : (i < 'hcdd) ? 8'h80 : (i < 'hcdf) ? 8'hc0 : (i < 'hce0) ? 8'hc1 :
|
||||
(i < 'hce7) ? 8'h80 : (i < 'hce8) ? 8'hc0 : (i < 'hceb) ? 8'h80 : (i < 'hcf7) ? 8'hc0 :
|
||||
(i < 'hcf8) ? 8'hc7 : (i < 'hcfb) ? 8'hc0 : (i < 'hcfc) ? 8'hc7 : (i < 'hcfd) ? 8'hc0 :
|
||||
(i < 'hd00) ? 8'hcf : (i < 'hd1f) ? 8'h80 : (i < 'hd20) ? 8'hc0 : (i < 'hd2f) ? 8'h80 :
|
||||
(i < 'hd30) ? 8'hc0 : (i < 'hd36) ? 8'h80 : (i < 'hd38) ? 8'hc0 : (i < 'hd39) ? 8'h80 :
|
||||
(i < 'hd3f) ? 8'hc0 : (i < 'hd40) ? 8'hc3 : (i < 'hd47) ? 8'h80 : (i < 'hd48) ? 8'hc0 :
|
||||
(i < 'hd4b) ? 8'h80 : (i < 'hd4c) ? 8'hc0 : (i < 'hd4d) ? 8'h80 : (i < 'hd50) ? 8'hc0 :
|
||||
(i < 'hd51) ? 8'h80 : (i < 'hd5f) ? 8'hc0 : (i < 'hd60) ? 8'hc1 : (i < 'hd7d) ? 8'hc0 :
|
||||
(i < 'hd7e) ? 8'hc1 : (i < 'hd7f) ? 8'hc7 : (i < 'hd80) ? 8'hd7 : (i < 'hdaf) ? 8'hc0 :
|
||||
(i < 'hdb0) ? 8'hd0 : (i < 'hdb7) ? 8'hc0 : (i < 'hdb8) ? 8'hd0 : (i < 'hdbb) ? 8'hc0 :
|
||||
(i < 'hdbc) ? 8'hd0 : (i < 'hdbd) ? 8'hc0 : (i < 'hdbe) ? 8'hd0 : (i < 'hdbf) ? 8'hd8 :
|
||||
(i < 'hdc0) ? 8'hdb : (i < 'hdcf) ? 8'hc0 : (i < 'hdd0) ? 8'hd8 : (i < 'hdd7) ? 8'hc0 :
|
||||
(i < 'hdd8) ? 8'hd8 : (i < 'hddb) ? 8'hc0 : (i < 'hddc) ? 8'hd8 : (i < 'hddd) ? 8'hd0 :
|
||||
(i < 'hddf) ? 8'hd8 : (i < 'hde0) ? 8'hdd : (i < 'hde3) ? 8'hc0 : (i < 'hde4) ? 8'hd0 :
|
||||
(i < 'hde5) ? 8'hc0 : (i < 'hde7) ? 8'hd0 : (i < 'hde8) ? 8'hdc : (i < 'hde9) ? 8'hd0 :
|
||||
(i < 'hdeb) ? 8'hd8 : (i < 'hdec) ? 8'hdc : (i < 'hded) ? 8'hd8 : (i < 'hdef) ? 8'hdc :
|
||||
(i < 'hdf0) ? 8'hde : (i < 'hdf1) ? 8'hd8 : (i < 'hdf3) ? 8'hdc : (i < 'hdf4) ? 8'hde :
|
||||
(i < 'hdf5) ? 8'hdc : (i < 'hdf7) ? 8'hde : (i < 'hdf8) ? 8'hdf : (i < 'hdf9) ? 8'hde :
|
||||
(i < 'he00) ? 8'hdf : (i < 'he3f) ? 8'hc0 : (i < 'he40) ? 8'he3 : (i < 'he57) ? 8'hc0 :
|
||||
(i < 'he58) ? 8'he0 : (i < 'he5b) ? 8'hc0 : (i < 'he5c) ? 8'he0 : (i < 'he5d) ? 8'hc0 :
|
||||
(i < 'he5f) ? 8'he0 : (i < 'he60) ? 8'he1 : (i < 'he67) ? 8'hc0 : (i < 'he68) ? 8'he0 :
|
||||
(i < 'he6b) ? 8'hc0 : (i < 'he70) ? 8'he0 : (i < 'he71) ? 8'hc0 : (i < 'he7d) ? 8'he0 :
|
||||
(i < 'he7e) ? 8'he1 : (i < 'he7f) ? 8'he3 : (i < 'he80) ? 8'he7 : (i < 'he87) ? 8'hc0 :
|
||||
(i < 'he88) ? 8'he0 : (i < 'he8b) ? 8'hc0 : (i < 'he8c) ? 8'he0 : (i < 'he8d) ? 8'hc0 :
|
||||
(i < 'he90) ? 8'he0 : (i < 'he93) ? 8'hc0 : (i < 'he94) ? 8'he0 : (i < 'he95) ? 8'hc0 :
|
||||
(i < 'hebf) ? 8'he0 : (i < 'hec0) ? 8'heb : (i < 'hedb) ? 8'he0 : (i < 'hedc) ? 8'he8 :
|
||||
(i < 'hedd) ? 8'he0 : (i < 'hedf) ? 8'he8 : (i < 'hee0) ? 8'hed : (i < 'hee7) ? 8'he0 :
|
||||
(i < 'hee8) ? 8'hec : (i < 'heeb) ? 8'he0 : (i < 'heec) ? 8'hec : (i < 'heed) ? 8'he8 :
|
||||
(i < 'heef) ? 8'hec : (i < 'hef0) ? 8'hee : (i < 'hef3) ? 8'he8 : (i < 'hef5) ? 8'hec :
|
||||
(i < 'hef7) ? 8'hee : (i < 'hef8) ? 8'hef : (i < 'hef9) ? 8'hec : (i < 'hf00) ? 8'hef :
|
||||
(i < 'hf1f) ? 8'he0 : (i < 'hf20) ? 8'hf0 : (i < 'hf27) ? 8'he0 : (i < 'hf28) ? 8'hf0 :
|
||||
(i < 'hf2b) ? 8'he0 : (i < 'hf2c) ? 8'hf0 : (i < 'hf2d) ? 8'he0 : (i < 'hf30) ? 8'hf0 :
|
||||
(i < 'hf33) ? 8'he0 : (i < 'hf3f) ? 8'hf0 : (i < 'hf40) ? 8'hf3 : (i < 'hf43) ? 8'he0 :
|
||||
(i < 'hf5f) ? 8'hf0 : (i < 'hf60) ? 8'hf5 : (i < 'hf6d) ? 8'hf0 : (i < 'hf6f) ? 8'hf4 :
|
||||
(i < 'hf70) ? 8'hf6 : (i < 'hf73) ? 8'hf0 : (i < 'hf74) ? 8'hf4 : (i < 'hf75) ? 8'hf0 :
|
||||
(i < 'hf76) ? 8'hf4 : (i < 'hf77) ? 8'hf6 : (i < 'hf78) ? 8'hf7 : (i < 'hf79) ? 8'hf4 :
|
||||
(i < 'hf7b) ? 8'hf6 : (i < 'hf80) ? 8'hf7 : (i < 'hf87) ? 8'hf0 : (i < 'hf88) ? 8'hf8 :
|
||||
(i < 'hf8d) ? 8'hf0 : (i < 'hf90) ? 8'hf8 : (i < 'hf93) ? 8'hf0 : (i < 'hf94) ? 8'hf8 :
|
||||
(i < 'hf95) ? 8'hf0 : (i < 'hf9f) ? 8'hf8 : (i < 'hfa0) ? 8'hf9 : (i < 'hfaf) ? 8'hf8 :
|
||||
(i < 'hfb0) ? 8'hfa : (i < 'hfb7) ? 8'hf8 : (i < 'hfb8) ? 8'hfb : (i < 'hfb9) ? 8'hf8 :
|
||||
(i < 'hfbb) ? 8'hfa : (i < 'hfc0) ? 8'hfb : (i < 'hfc3) ? 8'hf8 : (i < 'hfc4) ? 8'hfc :
|
||||
(i < 'hfc5) ? 8'hf8 : (i < 'hfd7) ? 8'hfc : (i < 'hfd8) ? 8'hfd : (i < 'hfdb) ? 8'hfc :
|
||||
(i < 'hfe0) ? 8'hfd : (i < 'hfe2) ? 8'hfc : (i < 'hff0) ? 8'hfe : 8'hff;
|
||||
|
||||
for(i = 0; i<4096; i=i+1) wave_pst[i] =
|
||||
(i < 'h3ff) ? 8'h00 : (i < 'h400) ? 8'h1f : (i < 'h7ee) ? 8'h00 : (i < 'h7ef) ? 8'h20 :
|
||||
(i < 'h7f0) ? 8'h70 : (i < 'h7f1) ? 8'h60 : (i < 'h7f2) ? 8'h20 : (i < 'h7f7) ? 8'h70 :
|
||||
(i < 'h7fa) ? 8'h78 : (i < 'h7fc) ? 8'h7c : (i < 'h7fe) ? 8'h7e : (i < 'h800) ? 8'h7f :
|
||||
(i < 'hbfd) ? 8'h00 : (i < 'hbfe) ? 8'h08 : (i < 'hbff) ? 8'h1e : (i < 'hc00) ? 8'h3f :
|
||||
(i < 'hdf7) ? 8'h00 : (i < 'hdfe) ? 8'h80 : (i < 'hdff) ? 8'h8c : (i < 'he00) ? 8'h9f :
|
||||
(i < 'he3e) ? 8'h00 : (i < 'he40) ? 8'h80 : (i < 'he5e) ? 8'h00 : (i < 'he60) ? 8'h80 :
|
||||
(i < 'he66) ? 8'h00 : (i < 'he67) ? 8'h80 : (i < 'he6a) ? 8'h00 : (i < 'he80) ? 8'h80 :
|
||||
(i < 'he82) ? 8'h00 : (i < 'he83) ? 8'h80 : (i < 'he85) ? 8'h00 : (i < 'he89) ? 8'h80 :
|
||||
(i < 'he8a) ? 8'h00 : (i < 'heee) ? 8'h80 : (i < 'heff) ? 8'hc0 : (i < 'hf00) ? 8'hcf :
|
||||
(i < 'hf6f) ? 8'hc0 : (i < 'hf70) ? 8'he0 : (i < 'hf74) ? 8'hc0 : (i < 'hf7f) ? 8'he0 :
|
||||
(i < 'hf80) ? 8'he3 : (i < 'hfb6) ? 8'he0 : (i < 'hfda) ? 8'hf0 : (i < 'hfeb) ? 8'hf8 :
|
||||
(i < 'hff5) ? 8'hfc : (i < 'hff9) ? 8'hfe : 8'hff;
|
||||
end
|
||||
|
||||
endmodule
|
||||
130
cores/c16/sigma_delta_dac.v
Normal file
130
cores/c16/sigma_delta_dac.v
Normal file
@@ -0,0 +1,130 @@
|
||||
|
||||
// sigmadelta.v
|
||||
// two channel second order sigma delta dac
|
||||
// taken from Minimig
|
||||
|
||||
// audio data processing
|
||||
// stereo sigma/delta bitstream modulator
|
||||
module sigma_delta_dac (
|
||||
input clk, // bus clock
|
||||
input [14:0] ldatasum, // left channel data
|
||||
input [14:0] rdatasum, // right channel data
|
||||
output reg aleft=0, // left bitstream output
|
||||
output reg aright=0 // right bitsteam output
|
||||
);
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// local signals
|
||||
localparam DW = 15;
|
||||
localparam CW = 2;
|
||||
localparam RW = 4;
|
||||
localparam A1W = 2;
|
||||
localparam A2W = 5;
|
||||
|
||||
wire [DW+2+0 -1:0] sd_l_er0, sd_r_er0;
|
||||
reg [DW+2+0 -1:0] sd_l_er0_prev=0, sd_r_er0_prev=0;
|
||||
wire [DW+A1W+2-1:0] sd_l_aca1, sd_r_aca1;
|
||||
wire [DW+A2W+2-1:0] sd_l_aca2, sd_r_aca2;
|
||||
reg [DW+A1W+2-1:0] sd_l_ac1=0, sd_r_ac1=0;
|
||||
reg [DW+A2W+2-1:0] sd_l_ac2=0, sd_r_ac2=0;
|
||||
wire [DW+A2W+3-1:0] sd_l_quant, sd_r_quant;
|
||||
|
||||
// LPF noise LFSR
|
||||
reg [24-1:0] seed1 = 24'h654321;
|
||||
reg [19-1:0] seed2 = 19'h12345;
|
||||
reg [24-1:0] seed_sum=0, seed_prev=0, seed_out=0;
|
||||
always @ (posedge clk) begin
|
||||
if (&seed1)
|
||||
seed1 <= #1 24'h654321;
|
||||
else
|
||||
seed1 <= #1 {seed1[22:0], ~(seed1[23] ^ seed1[22] ^ seed1[21] ^ seed1[16])};
|
||||
end
|
||||
always @ (posedge clk) begin
|
||||
if (&seed2)
|
||||
seed2 <= #1 19'h12345;
|
||||
else
|
||||
seed2 <= #1 {seed2[17:0], ~(seed2[18] ^ seed2[17] ^ seed2[16] ^ seed2[13] ^ seed2[0])};
|
||||
end
|
||||
always @ (posedge clk) begin
|
||||
seed_sum <= #1 seed1 + {5'b0, seed2};
|
||||
seed_prev <= #1 seed_sum;
|
||||
seed_out <= #1 seed_sum - seed_prev;
|
||||
end
|
||||
|
||||
// linear interpolate
|
||||
localparam ID=4; // counter size, also 2^ID = interpolation rate
|
||||
reg [ID+0-1:0] int_cnt = 0;
|
||||
always @ (posedge clk) int_cnt <= #1 int_cnt + 'd1;
|
||||
|
||||
reg [DW+0-1:0] ldata_cur=0, ldata_prev=0;
|
||||
reg [DW+0-1:0] rdata_cur=0, rdata_prev=0;
|
||||
wire [DW+1-1:0] ldata_step, rdata_step;
|
||||
reg [DW+ID-1:0] ldata_int=0, rdata_int=0;
|
||||
wire [DW+0-1:0] ldata_int_out, rdata_int_out;
|
||||
assign ldata_step = {ldata_cur[DW-1], ldata_cur} - {ldata_prev[DW-1], ldata_prev}; // signed subtract
|
||||
assign rdata_step = {rdata_cur[DW-1], rdata_cur} - {rdata_prev[DW-1], rdata_prev}; // signed subtract
|
||||
always @ (posedge clk) begin
|
||||
if (~|int_cnt) begin
|
||||
ldata_prev <= #1 ldata_cur;
|
||||
ldata_cur <= #1 ldatasum; //{~ldatasum[DW-1], ldatasum[DW-2:0]}; // convert to offset binary, samples no longer signed!
|
||||
rdata_prev <= #1 rdata_cur;
|
||||
rdata_cur <= #1 rdatasum; //{~rdatasum[DW-1], rdatasum[DW-2:0]}; // convert to offset binary, samples no longer signed!
|
||||
ldata_int <= #1 {ldata_cur[DW-1], ldata_cur, {ID{1'b0}}};
|
||||
rdata_int <= #1 {rdata_cur[DW-1], rdata_cur, {ID{1'b0}}};
|
||||
end else begin
|
||||
ldata_int <= #1 ldata_int + {{ID{ldata_step[DW+1-1]}}, ldata_step};
|
||||
rdata_int <= #1 rdata_int + {{ID{rdata_step[DW+1-1]}}, rdata_step};
|
||||
end
|
||||
end
|
||||
assign ldata_int_out = ldata_int[DW+ID-1:ID];
|
||||
assign rdata_int_out = rdata_int[DW+ID-1:ID];
|
||||
|
||||
// input gain x3
|
||||
wire [DW+2-1:0] ldata_gain, rdata_gain;
|
||||
assign ldata_gain = {ldata_int_out[DW-1], ldata_int_out, 1'b0} + {{(2){ldata_int_out[DW-1]}}, ldata_int_out};
|
||||
assign rdata_gain = {rdata_int_out[DW-1], rdata_int_out, 1'b0} + {{(2){rdata_int_out[DW-1]}}, rdata_int_out};
|
||||
|
||||
/*
|
||||
// random dither to 15 bits
|
||||
reg [DW-1:0] ldata=0, rdata=0;
|
||||
always @ (posedge clk) begin
|
||||
ldata <= #1 ldata_gain[DW+2-1:2] + ( (~(&ldata_gain[DW+2-1-1:2]) && (ldata_gain[1:0] > seed_out[1:0])) ? 15'd1 : 15'd0 );
|
||||
rdata <= #1 rdata_gain[DW+2-1:2] + ( (~(&ldata_gain[DW+2-1-1:2]) && (ldata_gain[1:0] > seed_out[1:0])) ? 15'd1 : 15'd0 );
|
||||
end
|
||||
*/
|
||||
|
||||
// accumulator adders
|
||||
assign sd_l_aca1 = {{(A1W){ldata_gain[DW+2-1]}}, ldata_gain} - {{(A1W){sd_l_er0[DW+2-1]}}, sd_l_er0} + sd_l_ac1;
|
||||
assign sd_r_aca1 = {{(A1W){rdata_gain[DW+2-1]}}, rdata_gain} - {{(A1W){sd_r_er0[DW+2-1]}}, sd_r_er0} + sd_r_ac1;
|
||||
|
||||
assign sd_l_aca2 = {{(A2W-A1W){sd_l_aca1[DW+A1W+2-1]}}, sd_l_aca1} - {{(A2W){sd_l_er0[DW+2-1]}}, sd_l_er0} - {{(A2W+1){sd_l_er0_prev[DW+2-1]}}, sd_l_er0_prev[DW+2-1:1]} + sd_l_ac2;
|
||||
assign sd_r_aca2 = {{(A2W-A1W){sd_r_aca1[DW+A1W+2-1]}}, sd_r_aca1} - {{(A2W){sd_r_er0[DW+2-1]}}, sd_r_er0} - {{(A2W+1){sd_r_er0_prev[DW+2-1]}}, sd_r_er0_prev[DW+2-1:1]} + sd_r_ac2;
|
||||
|
||||
// accumulators
|
||||
always @ (posedge clk) begin
|
||||
sd_l_ac1 <= #1 sd_l_aca1;
|
||||
sd_r_ac1 <= #1 sd_r_aca1;
|
||||
sd_l_ac2 <= #1 sd_l_aca2;
|
||||
sd_r_ac2 <= #1 sd_r_aca2;
|
||||
end
|
||||
|
||||
// value for quantizaton
|
||||
assign sd_l_quant = {sd_l_ac2[DW+A2W+2-1], sd_l_ac2} + {{(DW+A2W+3-RW){seed_out[RW-1]}}, seed_out[RW-1:0]};
|
||||
assign sd_r_quant = {sd_r_ac2[DW+A2W+2-1], sd_r_ac2} + {{(DW+A2W+3-RW){seed_out[RW-1]}}, seed_out[RW-1:0]};
|
||||
|
||||
// error feedback
|
||||
assign sd_l_er0 = sd_l_quant[DW+A2W+3-1] ? {1'b1, {(DW+2-1){1'b0}}} : {1'b0, {(DW+2-1){1'b1}}};
|
||||
assign sd_r_er0 = sd_r_quant[DW+A2W+3-1] ? {1'b1, {(DW+2-1){1'b0}}} : {1'b0, {(DW+2-1){1'b1}}};
|
||||
always @ (posedge clk) begin
|
||||
sd_l_er0_prev <= #1 (&sd_l_er0) ? sd_l_er0 : sd_l_er0+1;
|
||||
sd_r_er0_prev <= #1 (&sd_r_er0) ? sd_r_er0 : sd_r_er0+1;
|
||||
end
|
||||
|
||||
// output
|
||||
always @ (posedge clk) begin
|
||||
aleft <= #1 (~|ldata_gain) ? ~aleft : ~sd_l_er0[DW+2-1];
|
||||
aright <= #1 (~|rdata_gain) ? ~aright : ~sd_r_er0[DW+2-1];
|
||||
end
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user