1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-01-20 01:34:38 +00:00

Robotron HW: add speech chip for Sinistar

This commit is contained in:
Gyorgy Szombathelyi 2020-03-11 18:59:25 +01:00
parent b47e88d9f5
commit 877750e448
7 changed files with 167 additions and 29 deletions

View File

@ -6,8 +6,6 @@ Supported games: Robotron 2048, Joust, Sinistar, Bubbles, Splat, Stargate, Alien
After loading the RBF (Core), a CMOS clearing happens. When the message
"Factory Settings Restored" appears, press the MiST soft RESET button (right).
Sinistar has some graphics issues, and the speech chip is not implemented.
Usage:
------
- Make sure you use firmware 200215 or later.
@ -18,7 +16,7 @@ Usage:
- MRA utilty: https://github.com/sebdel/mra-tools-c
Note: the MRA files contains a dump of the CMOS RAM. It will be included in the genearted ROM file.
Note: the MRA files contains a dump of the CMOS RAM. It will be included in the generated ROM file.
Change it for permanent settings (search for the format online). It's possible to change these values
inside the core, with turning on "Auto-up" switch, and activate the "Advance" trigger in the OSD.
Refer to the arcade's user manual for further info.

View File

@ -212,11 +212,12 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO
set_global_assignment -name SYSTEMVERILOG_FILE rtl/RobotronFPGA_MiST.sv
set_global_assignment -name VHDL_FILE rtl/defender_sound_board.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
set_global_assignment -name VHDL_FILE rtl/defender_sound_board.vhd
set_global_assignment -name VHDL_FILE rtl/hc55564.vhd
set_global_assignment -name VHDL_FILE rtl/robotron_soc.vhd
set_global_assignment -name VHDL_FILE rtl/robotron_cpu/sc1.vhd
set_global_assignment -name VHDL_FILE rtl/robotron_cpu/robotron_cpu.vhd

View File

@ -4,7 +4,7 @@
<rbf>robotron</rbf>
<setname>sinistar</setname>
<rom index="1"><part>6</part></rom>
<rom index="0" zip="sinistar.zip" md5="60b465866ccf143727ff2ce9027e0886" type="merged">
<rom index="0" zip="sinistar.zip" md5="d1801e21859efdeabb8d713acbe5db99" type="merged">
<part name="sinistar.01"/>
<part name="sinistar.02"/>
<part name="sinistar.03"/>
@ -85,5 +85,12 @@
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
</part>
<part repeat="0xC00">FF</part>
<part crc="e1019568" name="speech.ic7"/>
<part crc="cf3b5ffd" name="speech.ic5"/>
<part crc="ff8d2645" name="speech.ic6"/>
<part crc="4b56a626" name="speech.ic4"/>
</rom>
</misterromdescription>

View File

@ -47,7 +47,7 @@ localparam CONF_STR = {
"O5,Blend,Off,On;",
"O6,Swap Joysticks,Off,On;",
"O7,Auto up,Off,On;",
"T8,Advance,Off,On;",
"T8,Advance;",
"T0,Reset;",
"V,v1.0.",`BUILD_DATE
};
@ -64,6 +64,7 @@ reg [7:0] JA;
reg [7:0] JB;
reg [3:0] BTN;
reg blitter_sc2, sinistar;
reg speech_en;
wire [6:0] core_mod;
reg [1:0] orientation; // [left/right, landscape/portrait]
@ -88,6 +89,7 @@ always @(*) begin
BTN = 4'hF;
blitter_sc2 = 0;
sinistar = 0;
speech_en = 0;
case (core_mod)
7'h0: // ROBOTRON
@ -132,6 +134,7 @@ always @(*) begin
7'h6: // SINISTAR
begin
sinistar = 1;
speech_en = 1;
orientation = 2'b01;
BTN = { m_two_players, m_one_player, m_coin1 | m_coin2, reset };
JA = { sin_x, 2'b00, m_right | m_left | m_right2 | m_left2, sin_y, 2'b00, m_up | m_down | m_up2 | m_down2 };
@ -164,11 +167,6 @@ wire [7:0] joystick_1;
wire scandoublerD;
wire no_csync;
wire ypbpr;
wire [7:0] audio;
wire hs, vs;
wire blankn;
wire [2:0] r,g;
wire [1:0] b;
wire key_pressed;
wire [7:0] key_code;
wire key_strobe;
@ -204,9 +202,11 @@ wire [7:0] ioctl_dout;
/*
ROM Structure:
0000-BFFF main cpu 48k
C000-CFFF snd cpu 4k
D000-D3FF CMOS RAM 1k
00000-0BFFF main cpu 48k
0C000-0CFFF snd cpu 4k
0D000-0D3FF CMOS RAM 1k
0D400-0DFFF ---
0E000-11FFF speech 16k
*/
data_io data_io (
@ -290,6 +290,13 @@ always @(posedge clk_sys) begin
reset <= status[0] | buttons[1] | ioctl_downl | ~rom_loaded;
end
wire [7:0] audio;
wire [15:0] speech;
wire hs, vs;
wire blankn;
wire [2:0] r,g;
wire [1:0] b;
robotron_soc robotron_soc (
.clock ( clk_sys ),
.clock_snd ( clk_aud ),
@ -299,6 +306,7 @@ robotron_soc robotron_soc (
.Hsync ( hs ),
.Vsync ( vs ),
.audio_out ( audio ),
.speech_out ( speech ),
.blitter_sc2 ( blitter_sc2 ),
.sinistar ( sinistar ),
@ -320,7 +328,7 @@ robotron_soc robotron_soc (
.FlashCS ( romcs ),
.dl_clock ( clk_mem ),
.dl_addr ( ioctl_addr[15:0] ),
.dl_addr ( ioctl_addr[16:0] ),
.dl_data ( ioctl_dout ),
.dl_wr ( ioctl_wr )
);
@ -349,16 +357,17 @@ mist_video #(.COLOR_DEPTH(3), .SD_HCNT_WIDTH(11)) mist_video(
.ypbpr ( ypbpr )
);
wire [16:0] audio_mix = speech_en ? { 1'b0, audio, audio } + { 1'b0, speech } : { 1'b0, audio, audio };
wire dac_o;
assign AUDIO_L = dac_o;
assign AUDIO_R = dac_o;
dac #(
.C_bits(11))
.C_bits(17))
dac(
.clk_i(clk_aud),
.res_n_i(1),
.dac_i({3'd0, audio}), // silence by 9dB
.dac_i(audio_mix),
.dac_o(dac_o)
);

View File

@ -32,8 +32,10 @@ port(
hand : out std_logic;
select_sound : in std_logic_vector( 5 downto 0);
audio_out : out std_logic_vector( 7 downto 0);
rom_addr : out std_logic_vector(11 downto 0);
speech_out : out std_logic_vector(15 downto 0);
rom_addr : out std_logic_vector(13 downto 0);
rom_do : in std_logic_vector( 7 downto 0);
spch_do : in std_logic_vector( 7 downto 0);
rom_vma : out std_logic
);
end defender_sound_board;
@ -54,6 +56,8 @@ architecture struct of defender_sound_board is
signal wram_do : std_logic_vector( 7 downto 0);
signal rom_cs : std_logic;
signal spch_cs : std_logic;
-- signal rom_do : std_logic_vector( 7 downto 0);
-- pia port a
@ -70,6 +74,9 @@ architecture struct of defender_sound_board is
-- ca2 speech data N/C
-- cb2 speech clock N/C
signal speech_cen : std_logic;
signal speech_data: std_logic;
signal pia_rw_n : std_logic;
signal pia_cs : std_logic;
signal pia_irqa : std_logic;
@ -86,8 +93,9 @@ reset_n <= not reset;
-- pia cs
wram_cs <= '1' when cpu_addr(15 downto 8) = X"00" else '0'; -- 0000-007F
pia_cs <= '1' when cpu_addr(14 downto 12) = "000" and cpu_addr(10) = '1' else '0'; -- 8400-8403 ? => 0400-0403
spch_cs <= '1' when cpu_addr(15 downto 12) >= X"B" and cpu_addr(15 downto 12) <= X"E" else '0'; -- B000-EFFF
rom_cs <= '1' when cpu_addr(15 downto 12) = X"F" else '0'; -- F800-FFFF
-- write enables
wram_we <= '1' when cpu_rw = '0' and wram_cs = '1' else '0';
pia_rw_n <= '0' when cpu_rw = '0' and pia_cs = '1' else '1';
@ -96,7 +104,8 @@ pia_rw_n <= '0' when cpu_rw = '0' and pia_cs = '1' else '1';
cpu_di <=
wram_do when wram_cs = '1' else
pia_do when pia_cs = '1' else
rom_do when rom_cs = '1' else X"55";
rom_do when rom_cs = '1' else
spch_do when spch_cs = '1' else X"55";
-- pia I/O
audio_out <= pia_pa_o;
@ -139,7 +148,7 @@ port map(
-- data => rom_do
--);
rom_vma <= rom_cs and cpu_vma;
rom_addr <= cpu_addr(11 downto 0);
rom_addr <= (cpu_addr(13 downto 12) - "11") & cpu_addr(11 downto 0);
-- cpu wram
cpu_ram : entity work.gen_ram
@ -170,15 +179,25 @@ port map
pa_oe => open,
ca1 => '1',
ca2_i => '0',
ca2_o => open,
ca2_o => speech_data,
ca2_oe => open,
pb_i => pia_pb_i,
pb_o => open,
pb_oe => open,
cb1 => pia_cb1_i,
cb2_i => '0',
cb2_o => open,
cb2_o => speech_cen,
cb2_oe => open
);
end struct;
-- CVSD speech decoder
IC1: entity work.HC55564
port map(
clk => clk_0p89,
cen => speech_cen,
rst => '0', -- Reset is not currently implemented
bit_in => speech_data,
sample_out(15 downto 0) => speech_out
);
end struct;

View File

@ -0,0 +1,84 @@
-- HC55516/HC55564 Continuously Variable Slope Delta decoder
-- (c)2015 vlait
--
-- This is free software: you can redistribute
-- it and/or modify it under the terms of the GNU General
-- Public License as published by the Free Software
-- Foundation, either version 3 of the License, or (at your
-- option) any later version.
--
-- This is distributed in the hope that it will
-- be useful, but WITHOUT ANY WARRANTY; without even the
-- implied warranty of MERCHANTABILITY or FITNESS FOR A
-- PARTICULAR PURPOSE. See the GNU General Public License
-- for more details.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity hc55564 is
port
(
clk : in std_logic;
cen : in std_logic;
rst : in std_logic;
bit_in : in std_logic;
sample_out : out std_logic_vector(15 downto 0)
);
end hc55564;
architecture hdl of hc55564 is
constant h : integer := (1 - 1/8) *256; --integrator decay (1 - 1/8) * 256 = 224
constant b : integer := (1 - 1/256)*256; --syllabic decay (1 - 1/256) * 256 = 255
constant s_min : unsigned(15 downto 0) := to_unsigned(40, 16);
constant s_max : unsigned(15 downto 0) := to_unsigned(5120, 16);
signal runofn_new : std_logic_vector(2 downto 0);
signal runofn : std_logic_vector(2 downto 0);
signal res1 : unsigned(31 downto 0);
signal res2 : unsigned(31 downto 0);
signal x_new : unsigned(16 downto 0);
signal x : unsigned(15 downto 0); --integrator
signal s : unsigned(15 downto 0); --syllabic
signal old_cen : std_logic;
begin
res1 <= x * h;
res2 <= s * b;
runofn_new <= runofn(1 downto 0) & bit_in;
x_new <= ('0'&res1(23 downto 8)) + s when bit_in = '1' else ('0'&res1(23 downto 8)) - s;
process(clk, rst, bit_in)
begin
-- reset ??
if rising_edge(clk) then
old_cen <= cen;
if old_cen = '0' and cen = '1' then
runofn <= runofn_new;
if runofn_new = "000" or runofn_new = "111" then
s <= s + 40;
if (s + 40) > s_max then
s <= s_max;
end if;
else
s <= res2(23 downto 8);
if res2(23 downto 8) < s_min then
s <= s_min;
end if;
end if;
if x_new(16) = '1' then
x <= (others => bit_in);
else
x <= x_new(15 downto 0);
end if;
end if;
end if;
end process;
sample_out <= std_logic_vector(x);
end architecture hdl;

View File

@ -29,6 +29,7 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity robotron_soc is
port (
@ -75,13 +76,14 @@ port (
-- Audio
audio_out : out std_logic_vector(7 downto 0);
speech_out : out std_logic_vector(15 downto 0);
-- 12-pin connectors
JA : in std_logic_vector(7 downto 0);
JB : in std_logic_vector(7 downto 0);
dl_clock : in std_logic;
dl_addr : in std_logic_vector(15 downto 0);
dl_addr : in std_logic_vector(16 downto 0);
dl_data : in std_logic_vector(7 downto 0);
dl_wr : in std_logic
);
@ -131,9 +133,11 @@ signal cpu_q : std_logic;
signal hand : std_logic;
signal select_sound : std_logic_vector( 5 downto 0);
signal snd_addr : std_logic_vector(11 downto 0);
signal snd_addr : std_logic_vector(13 downto 0);
signal snd_do : std_logic_vector( 7 downto 0);
signal spch_do : std_logic_vector( 7 downto 0);
signal snd_rom_we : std_logic;
signal spch_rom_we : std_logic;
begin
@ -237,15 +241,29 @@ snd_rom : entity work.dpram
generic map( dWidth => 8, aWidth => 12)
port map(
clk_a => clock_snd,
addr_a => snd_addr,
addr_a => snd_addr(11 downto 0),
q_a => snd_do,
clk_b => dl_clock,
we_b => snd_rom_we,
addr_b => dl_addr(11 downto 0),
d_b => dl_data
);
spch_rom : entity work.dpram
snd_rom_we <= '1' when dl_wr = '1' and dl_addr(15 downto 12) = x"C" else '0'; -- C000-CFFF
generic map( dWidth => 8, aWidth => 14)
port map(
clk_a => clock_snd,
addr_a => snd_addr,
q_a => spch_do,
clk_b => dl_clock,
we_b => spch_rom_we,
addr_b => (dl_addr(13 downto 12) - "10") & dl_addr(11 downto 0),
d_b => dl_data
);
snd_rom_we <= '1' when dl_wr = '1' and dl_addr(16 downto 12) = x"C" else '0'; -- 0C000-0CFFF
spch_rom_we <= '1' when dl_wr = '1' and dl_addr(16 downto 12) >= x"E" else '0'; -- 0E000-11FFF
-- sound board
defender_sound_board : entity work.defender_sound_board
@ -255,8 +273,10 @@ port map(
hand => hand,
select_sound => select_sound,
audio_out => audio_out,
speech_out => speech_out,
rom_addr => snd_addr,
rom_do => snd_do
rom_do => snd_do,
spch_do => spch_do
);
end Behavioral;