1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-02-14 19:56:02 +00:00

Remove garbage

This commit is contained in:
Gyorgy Szombathelyi
2021-03-31 12:23:31 +02:00
parent b304707536
commit d55d98ed1e
57 changed files with 0 additions and 13801 deletions

View File

@@ -1,446 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Arithmetic Logic Unit (ALU).
-- It contains the ALU core plus the Accumulator and the Temp Reg.
--
-- $Id: alu.vhd,v 1.8 2004/04/24 23:43:56 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_t;
use work.alu_pack.alu_op_t;
entity alu is
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
write_accu_i : in boolean;
write_shadow_i : in boolean;
write_temp_reg_i : in boolean;
read_alu_i : in boolean;
-- Decoder Interface ------------------------------------------------------
carry_i : in std_logic;
carry_o : out std_logic;
aux_carry_o : out std_logic;
alu_op_i : in alu_op_t;
use_carry_i : in boolean;
da_high_i : in boolean;
da_overflow_o : out boolean;
accu_low_i : in boolean;
p06_temp_reg_i : in boolean;
p60_temp_reg_i : in boolean
);
end alu;
library ieee;
use ieee.numeric_std.all;
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.nibble_t;
use work.alu_pack.all;
-- pragma translate_off
use work.t48_tb_pack.tb_accu_s;
-- pragma translate_on
architecture rtl of alu is
-- the Accumulator and Temp Reg
signal accumulator_q,
accu_shadow_q,
temp_req_q : word_t;
-- inputs to the ALU core
signal in_a_s,
in_b_s : word_t;
-- output of the ALU core
signal data_s : word_t;
signal add_result_s : alu_operand_t;
begin
-----------------------------------------------------------------------------
-- Process working_regs
--
-- Purpose:
-- Implements the working registers:
-- + Accumulator
-- + Temp Reg
--
working_regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
accumulator_q <= (others => '0');
accu_shadow_q <= (others => '0');
temp_req_q <= (others => '0');
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
if write_accu_i then
if accu_low_i then
accumulator_q(nibble_t'range) <= data_i(nibble_t'range);
else
accumulator_q <= data_i;
end if;
end if;
if write_shadow_i then
-- write shadow directly from t48 data bus
accu_shadow_q <= data_i;
else
-- default: update shadow Accumulator from real Accumulator
accu_shadow_q <= accumulator_q;
end if;
if p06_temp_reg_i then
-- low nibble of DA sequence
temp_req_q <= "00000110";
elsif p60_temp_reg_i then
-- high nibble of DA sequence
temp_req_q <= "01100000";
elsif write_temp_reg_i then
-- normal load from T48 bus
temp_req_q <= data_i;
end if;
end if;
end if;
end process working_regs;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Build the inputs to the ALU core.
-- Input A:
-- Unary operators use only Input A.
-- Is always fed from the shadow Accumulator.
-- Assumption: It never happens that the Accumulator is written and then
-- read for an ALU operation in the next cycle.
-- Its contents can thus be staged through the shadow Accu.
-- Input B:
-- Is always fed from the Temp Reg.
-----------------------------------------------------------------------------
in_a_s <= accu_shadow_q;
in_b_s <= temp_req_q;
-----------------------------------------------------------------------------
-- Process alu_core
--
-- Purpose:
-- Implements the ALU core.
-- All operations defined in alu_op_t are handled here.
--
alu_core: process (in_a_s,
in_b_s,
alu_op_i,
carry_i,
use_carry_i,
add_result_s)
begin
-- default assigments
data_s <= (others => '0');
carry_o <= '0';
case alu_op_i is
-- Operation: AND -------------------------------------------------------
when ALU_AND =>
data_s <= in_a_s and in_b_s;
-- Operation: OR --------------------------------------------------------
when ALU_OR =>
data_s <= in_a_s or in_b_s;
-- Operation: XOR -------------------------------------------------------
when ALU_XOR =>
data_s <= in_a_s xor in_b_s;
-- Operation: Add -------------------------------------------------------
when ALU_ADD =>
data_s <= add_result_s(data_s'range);
carry_o <= add_result_s(add_result_s'high);
-- Operation: CPL -------------------------------------------------------
when ALU_CPL =>
data_s <= not in_a_s;
-- Operation: CLR -------------------------------------------------------
when ALU_CLR =>
data_s <= (others => '0');
-- Operation: RL --------------------------------------------------------
when ALU_RL =>
data_s(7 downto 1) <= in_a_s(6 downto 0);
carry_o <= in_a_s(7);
if use_carry_i then
data_s(0) <= carry_i;
else
data_s(0) <= in_a_s(7);
end if;
-- Operation: RR --------------------------------------------------------
when ALU_RR =>
data_s(6 downto 0) <= in_a_s(7 downto 1);
carry_o <= in_a_s(0);
if use_carry_i then
data_s(7) <= carry_i;
else
data_s(7) <= in_a_s(0);
end if;
-- Operation: Swap ------------------------------------------------------
when ALU_SWAP =>
data_s(3 downto 0) <= in_a_s(7 downto 4);
data_s(7 downto 4) <= in_a_s(3 downto 0);
-- Operation: DEC -------------------------------------------------------
when ALU_DEC =>
data_s <= add_result_s(data_s'range);
-- Operation: INC -------------------------------------------------------
when ALU_INC =>
data_s <= add_result_s(data_s'range);
-- Operation CONCAT -----------------------------------------------------
when ALU_CONCAT =>
data_s <= in_b_s(7 downto 4) & in_a_s(3 downto 0);
-- Operation: NOP -------------------------------------------------------
when ALU_NOP =>
data_s <= in_a_s;
when others =>
-- pragma translate_off
assert false
report "Unknown ALU operation selected!"
severity error;
-- pragma translate_on
end case;
end process alu_core;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process adder
--
-- Purpose:
-- Implements the adder used by several instructions.
-- This way of modelling the adder forces resource sharing of:
-- * ADD
-- * INC
-- * DEC
--
adder: process (in_a_s,
in_b_s,
alu_op_i,
carry_i,
use_carry_i)
variable add_a_v, add_b_v : alu_operand_t;
variable c_v : alu_operand_t;
variable result_v : UNSIGNED(alu_operand_t'range);
variable aux_c_v : std_logic_vector(1 downto 0);
begin
-- Carry Selection --------------------------------------------------------
c_v := (others => '0');
if use_carry_i and carry_i = '1' then
c_v(0) := '1';
end if;
-- Operand Selection ------------------------------------------------------
-- defaults for ADD
add_a_v := '0' & in_a_s;
add_b_v := '0' & in_b_s;
case alu_op_i is
when ALU_INC =>
add_b_v := (others => '0');
add_b_v(0) := '1';
when ALU_DEC =>
add_b_v := (others => '1');
when others =>
null;
end case;
-- The Adder --------------------------------------------------------------
result_v := UNSIGNED(add_a_v) +
UNSIGNED(add_b_v) +
UNSIGNED(c_v);
add_result_s <= std_logic_vector(result_v);
-- Auxiliary Carry --------------------------------------------------------
aux_c_v := in_a_s(4) & in_b_s(4);
aux_carry_o <= '0';
case aux_c_v is
when "00" | "11" =>
if result_v(4) = '1' then
aux_carry_o <= '1';
end if;
when "01" | "10" =>
if result_v(4) = '0' then
aux_carry_o <= '1';
end if;
when others =>
null;
end case;
end process adder;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process da_overflow
--
-- Purpose:
-- Detect overflow situation during DA sequence.
--
da_overflow: process (accu_shadow_q,
da_high_i)
variable da_nibble_v : nibble_t;
function da_overflow_f(data : in nibble_t) return boolean is
variable overflow_v : boolean;
begin
case data is
when "1010" |
"1011" |
"1100" |
"1101" |
"1110" |
"1111" =>
overflow_v := true;
when others =>
overflow_v := false;
end case;
return(overflow_v);
end;
begin
if da_high_i then
da_nibble_v := accu_shadow_q(7 downto 4);
else
da_nibble_v := accu_shadow_q(3 downto 0);
end if;
da_overflow_o <= da_overflow_f(da_nibble_v);
end process da_overflow;
--
-----------------------------------------------------------------------------
-- pragma translate_off
-----------------------------------------------------------------------------
-- Testbench support.
-----------------------------------------------------------------------------
tb_accu_s <= accumulator_q;
-- pragma translate_on
-----------------------------------------------------------------------------
-- Output Multiplexer.
-----------------------------------------------------------------------------
data_o <= data_s
when read_alu_i else
(others => bus_idle_level_c);
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: alu.vhd,v $
-- Revision 1.8 2004/04/24 23:43:56 arniml
-- move from std_logic_arith to numeric_std
--
-- Revision 1.7 2004/04/07 22:09:03 arniml
-- remove unused signals
--
-- Revision 1.6 2004/04/07 20:56:23 arniml
-- default assignment for aux_carry_o
--
-- Revision 1.5 2004/04/06 20:21:53 arniml
-- fix sensitivity list
--
-- Revision 1.4 2004/04/06 18:10:41 arniml
-- rework adder and force resource sharing between ADD, INC and DEC
--
-- Revision 1.3 2004/04/04 14:18:52 arniml
-- add measures to implement XCHD
--
-- Revision 1.2 2004/03/28 21:08:51 arniml
-- support for DA instruction
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
-------------------------------------------------------------------------------

View File

@@ -1,49 +0,0 @@
-------------------------------------------------------------------------------
--
-- $Id: alu_pack-p.vhd,v 1.2 2004/04/04 14:18:53 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_width_c;
package alu_pack is
-----------------------------------------------------------------------------
-- The ALU operations
-----------------------------------------------------------------------------
type alu_op_t is (ALU_AND, ALU_OR, ALU_XOR,
ALU_CPL, ALU_CLR,
ALU_RL, ALU_RR,
ALU_SWAP,
ALU_DEC, ALU_INC,
ALU_ADD,
ALU_CONCAT,
ALU_NOP);
-----------------------------------------------------------------------------
-- The dedicated ALU arithmetic types.
-----------------------------------------------------------------------------
subtype alu_operand_t is std_logic_vector(word_width_c downto 0);
end alu_pack;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: alu_pack-p.vhd,v $
-- Revision 1.2 2004/04/04 14:18:53 arniml
-- add measures to implement XCHD
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,111 +0,0 @@
-------------------------------------------------------------------------------
--
-- The T48 Bus Connector.
-- Multiplexes all drivers of the T48 bus.
--
-- $Id: bus_mux.vhd,v 1.1 2004/03/23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_t;
entity bus_mux is
port (
alu_data_i : in word_t;
bus_data_i : in word_t;
dec_data_i : in word_t;
dm_data_i : in word_t;
pm_data_i : in word_t;
p1_data_i : in word_t;
p2_data_i : in word_t;
psw_data_i : in word_t;
tim_data_i : in word_t;
data_o : out word_t
);
end bus_mux;
use work.t48_pack.bus_idle_level_c;
architecture rtl of bus_mux is
begin
or_tree: if bus_idle_level_c = '0' generate
data_o <= alu_data_i or
bus_data_i or
dec_data_i or
dm_data_i or
pm_data_i or
p1_data_i or
p2_data_i or
psw_data_i or
tim_data_i;
end generate;
and_tree: if bus_idle_level_c = '1' generate
data_o <= alu_data_i and
bus_data_i and
dec_data_i and
dm_data_i and
pm_data_i and
p1_data_i and
p2_data_i and
psw_data_i and
tim_data_i;
end generate;
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: bus_mux.vhd,v $
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,397 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Clock Control unit.
-- Clock States and Machine Cycles are generated here.
--
-- $Id: clock_ctrl.vhd,v 1.4 2004/04/24 23:44:25 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.all;
entity clock_ctrl is
generic (
-- divide XTAL1 by 3 to derive Clock States
xtal_div_3_g : integer := 1
);
port (
clk_i : in std_logic;
xtal_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
xtal3_o : out boolean;
multi_cycle_i : in boolean;
assert_psen_i : in boolean;
assert_prog_i : in boolean;
assert_rd_i : in boolean;
assert_wr_i : in boolean;
mstate_o : out mstate_t;
second_cycle_o : out boolean;
ale_o : out boolean;
psen_o : out boolean;
prog_o : out boolean;
rd_o : out boolean;
wr_o : out boolean
);
end clock_ctrl;
library ieee;
use ieee.numeric_std.all;
architecture rtl of clock_ctrl is
-- The three XTAL1 cycles.
signal xtal_q : unsigned(1 downto 0);
signal xtal1_s,
xtal2_s,
xtal3_s : boolean;
signal x1_s,
x2_s,
x3_s : std_logic;
-- The five clock states.
signal mstate_q : mstate_t;
signal ale_q : boolean;
signal psen_q : boolean;
signal prog_q : boolean;
signal rd_q : boolean;
signal wr_q : boolean;
-- The Machine Cycle marker.
signal second_cycle_q : boolean;
signal multi_cycle_q : boolean;
begin
-----------------------------------------------------------------------------
-- Verify the generics
-----------------------------------------------------------------------------
-- pragma translate_off
-- XTAL1 divide by 3 --------------------------------------------------------
assert (xtal_div_3_g = 1) or (xtal_div_3_g = 0)
report "xtal_div_3_g must be either 1 or 0!"
severity failure;
-- pragma translate_on
-----------------------------------------------------------------------------
-- Divide XTAL1 by 3 to derive Clock States.
-----------------------------------------------------------------------------
use_xtal_div: if xtal_div_3_g = 1 generate
xtal: process (res_i, xtal_i)
begin
if res_i = res_active_c then
xtal_q <= TO_UNSIGNED(0, 2);
elsif xtal_i'event and xtal_i = clk_active_c then
if xtal_q < 2 then
xtal_q <= xtal_q + 1;
else
xtal_q <= TO_UNSIGNED(0, 2);
end if;
end if;
end process xtal;
x1_s <= '1'
when xtal_q = 0 else
'0';
x2_s <= '1'
when xtal_q = 1 else
'0';
x3_s <= '1'
when xtal_q = 2 else
'0';
end generate;
-----------------------------------------------------------------------------
-- XTAL1 is used directly for Clock States.
-----------------------------------------------------------------------------
no_xtal_div: if xtal_div_3_g = 0 generate
xtal_q <= TO_UNSIGNED(0, 2);
x1_s <= '1';
x2_s <= '1';
x3_s <= '1';
end generate;
-- And finally the boolean flags --------------------------------------------
xtal1_s <= to_boolean(x1_s);
xtal2_s <= to_boolean(x2_s);
xtal3_s <= to_boolean(x3_s);
-----------------------------------------------------------------------------
-- Process external_signal
--
-- Purpose:
-- Control signals ALE, PSEN, PROG and RD/WR are generated here.
--
external_signals: process (res_i, xtal_i)
begin
if res_i = res_active_c then
ale_q <= false;
psen_q <= false;
prog_q <= false;
rd_q <= false;
wr_q <= false;
elsif xtal_i'event and xtal_i = clk_active_c then
case mstate_q is
when MSTATE5 =>
-- RD, WR are set at the end of XTAL2 of first machine cycle
if xtal2_s and not second_cycle_q then
if assert_rd_i then
rd_q <= true;
end if;
if assert_wr_i then
wr_q <= true;
end if;
end if;
when MSTATE1 =>
if xtal3_s then
psen_q <= false;
end if;
when MSTATE2 =>
if xtal2_s then
-- RD, WR are removed at the end of XTAL3 of second machine cycle
rd_q <= false;
wr_q <= false;
-- PROG is removed at the and of XTAL3 of second machine cycle
prog_q <= false;
end if;
when MSTATE3 =>
-- ALE is set at the end of XTAL2 of every machine cycle
if xtal2_s then
ale_q <= true;
end if;
when MSTATE4 =>
if xtal3_s then
-- PSEN is set at the end of XTAL3
if assert_psen_i then
psen_q <= true;
end if;
end if;
-- PROG is set at the and of XTAL2
if xtal2_s and multi_cycle_q and not second_cycle_q and
assert_prog_i then
prog_q <= true;
end if;
-- ALE is removed at the end of XTAL2 of every machine cycle
if xtal2_s then
ale_q <= false;
end if;
when others =>
-- recover when states are out of sync
ale_q <= false;
psen_q <= false;
prog_q <= false;
rd_q <= false;
wr_q <= false;
end case;
end if;
end process external_signals;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process states
--
-- Purpose:
-- The Clock State controller.
--
states: process (res_i, clk_i)
begin
if res_i = res_active_c then
-- Reset machine state to MSTATE3
-- This allows a proper instruction fetch for the first real instruction
-- after reset.
-- The MSTATE3 is part of a virtual NOP that has no MSTATE1 and MSTATE2.
mstate_q <= MSTATE3;
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
case mstate_q is
when MSTATE5 =>
mstate_q <= MSTATE1;
when MSTATE1 =>
mstate_q <= MSTATE2;
when MSTATE2 =>
mstate_q <= MSTATE3;
when MSTATE3 =>
mstate_q <= MSTATE4;
when MSTATE4 =>
mstate_q <= MSTATE5;
when others =>
-- recover when states are out of sync
mstate_q <= MSTATE1;
-- pragma translate_off
assert false
report "Encoding of Clock States failed!"
severity error;
-- pragma translate_on
end case;
end if;
end if;
end process states;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process machine_cycle
--
-- Purpose:
-- Keep track of machine cycles.
-- Basically, this means to differ between first and second cycle.
--
machine_cycle: process (res_i, clk_i)
variable state2_v, state5_v : boolean;
begin
if res_i = res_active_c then
multi_cycle_q <= false;
second_cycle_q <= false;
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
state2_v := mstate_q = MSTATE2;
state5_v := mstate_q = MSTATE5;
-- multi cycle information is delivered in State 2 from the decoder
if state2_v and multi_cycle_i then
multi_cycle_q <= true;
end if;
-- mark second machine cycle
if multi_cycle_q and state5_v then
second_cycle_q <= true;
end if;
-- reset at end of second machine cycle
if state5_v and
(multi_cycle_q and second_cycle_q) then
multi_cycle_q <= false;
second_cycle_q <= false;
end if;
end if;
end if;
end process machine_cycle;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output assignments
-----------------------------------------------------------------------------
xtal3_o <= xtal3_s;
mstate_o <= mstate_q;
second_cycle_o <= second_cycle_q;
ale_o <= ale_q;
psen_o <= psen_q;
prog_o <= prog_q;
rd_o <= rd_q;
wr_o <= wr_q;
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: clock_ctrl.vhd,v $
-- Revision 1.4 2004/04/24 23:44:25 arniml
-- move from std_logic_arith to numeric_std
--
-- Revision 1.3 2004/04/18 18:56:23 arniml
-- reset machine state to MSTATE3 to allow proper instruction fetch
-- after reset
--
-- Revision 1.2 2004/03/28 12:55:06 arniml
-- move code for PROG out of if-branch for xtal3_s
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,215 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Conditional Branch Logic unit.
-- Decisions whether to take a jump or not are made here.
--
-- $Id: cond_branch.vhd,v 1.2 2004/04/24 23:44:25 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_t;
use work.cond_branch_pack.all;
entity cond_branch is
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- Decoder Interface ------------------------------------------------------
compute_take_i : in boolean;
branch_cond_i : in branch_conditions_t;
take_branch_o : out boolean;
accu_i : in word_t;
t0_i : in std_logic;
t1_i : in std_logic;
int_n_i : in std_logic;
f0_i : in std_logic;
f1_i : in std_logic;
tf_i : in std_logic;
carry_i : in std_logic;
comp_value_i : in comp_value_t
);
end cond_branch;
library ieee;
use ieee.numeric_std.all;
use work.t48_pack.res_active_c;
use work.t48_pack.clk_active_c;
architecture rtl of cond_branch is
-- marker for branch taken
signal take_branch_s,
take_branch_q : boolean;
begin
-----------------------------------------------------------------------------
-- Process decide_take
--
-- Purpose:
-- Decides whether a branch has to be taken or not.
--
decide_take: process (accu_i,
branch_cond_i,
t0_i, t1_i,
int_n_i,
f0_i, f1_i,
tf_i,
carry_i,
comp_value_i)
variable or_v : std_logic;
begin
-- default assignment
take_branch_s <= false;
or_v := '0';
case branch_cond_i is
-- Branch On: Accumulator Bit -------------------------------------------
when COND_ON_BIT =>
if accu_i(TO_INTEGER(UNSIGNED(comp_value_i))) = '1' then
take_branch_s <= true;
end if;
-- Branch On: Accumulator Zero ------------------------------------------
when COND_Z =>
for i in accu_i'range loop
or_v := or_v or accu_i(i);
end loop;
take_branch_s <= or_v = not comp_value_i(0);
-- Branch On: Carry -----------------------------------------------------
when COND_C =>
take_branch_s <= carry_i = comp_value_i(0);
-- Branch On: Flag 0 ----------------------------------------------------
when COND_F0 =>
take_branch_s <= f0_i = '1';
-- Branch On: Flag 1 ----------------------------------------------------
when COND_F1 =>
take_branch_s <= f1_i = '1';
-- Branch On: Interrupt -------------------------------------------------
when COND_INT =>
take_branch_s <= int_n_i = '0';
-- Branch On: Test 0 ----------------------------------------------------
when COND_T0 =>
take_branch_s <= t0_i = comp_value_i(0);
-- Branch On: Test 1 ----------------------------------------------------
when COND_T1 =>
take_branch_s <= t1_i = comp_value_i(0);
-- Branch On: Timer Flag ------------------------------------------------
when COND_TF =>
take_branch_s <= tf_i = '1';
when others =>
-- pragma translate_off
assert false
report "Unknown branch condition specified!"
severity error;
-- pragma translate_on
end case;
end process decide_take;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process reg
--
-- Purpose:
-- Implement the marker register.
--
reg: process (res_i, clk_i)
begin
if res_i = res_active_c then
take_branch_q <= false;
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
if compute_take_i then
take_branch_q <= take_branch_s;
end if;
end if;
end if;
end process reg;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
take_branch_o <= take_branch_q;
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: cond_branch.vhd,v $
-- Revision 1.2 2004/04/24 23:44:25 arniml
-- move from std_logic_arith to numeric_std
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,39 +0,0 @@
-------------------------------------------------------------------------------
--
-- $Id: cond_branch_pack-p.vhd,v 1.1 2004/03/23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
package cond_branch_pack is
-----------------------------------------------------------------------------
-- The branch conditions.
-----------------------------------------------------------------------------
type branch_conditions_t is (COND_ON_BIT, COND_Z,
COND_C,
COND_F0, COND_F1,
COND_INT,
COND_T0, COND_T1,
COND_TF);
subtype comp_value_t is std_logic_vector(2 downto 0);
end cond_branch_pack;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: cond_branch_pack-p.vhd,v $
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,151 +0,0 @@
-------------------------------------------------------------------------------
--
-- The BUS unit.
-- Implements the BUS port logic.
--
-- $Id: db_bus.vhd,v 1.2 2004/04/04 14:15:45 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_t;
entity db_bus is
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
ea_i : in std_logic;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
write_bus_i : in boolean;
read_bus_i : in boolean;
-- BUS Interface ----------------------------------------------------------
output_pcl_i : in boolean;
bidir_bus_i : in boolean;
pcl_i : in word_t;
db_i : in word_t;
db_o : out word_t;
db_dir_o : out std_logic
);
end db_bus;
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.to_stdLogic;
architecture rtl of db_bus is
-- the BUS output register
signal bus_q : word_t;
-- BUS direction marker
signal db_dir_q : std_logic;
begin
-----------------------------------------------------------------------------
-- Process bus_regs
--
-- Purpose:
-- Implements the BUS output register.
--
bus_regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
bus_q <= (others => '0');
db_dir_q <= '0';
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
if write_bus_i then
bus_q <= data_i;
db_dir_q <= '1';
elsif ea_i = '1' or bidir_bus_i then
db_dir_q <= '0';
end if;
end if;
end if;
end process bus_regs;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
db_o <= pcl_i
when output_pcl_i else
bus_q;
db_dir_o <= db_dir_q or to_stdLogic(output_pcl_i);
data_o <= (others => bus_idle_level_c)
when not read_bus_i else
db_i;
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: db_bus.vhd,v $
-- Revision 1.2 2004/04/04 14:15:45 arniml
-- add dump_compare support
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -1,87 +0,0 @@
-------------------------------------------------------------------------------
--
-- $Id: decoder_pack-p.vhd,v 1.2 2004/03/28 13:09:53 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
package decoder_pack is
-----------------------------------------------------------------------------
-- The Mnemonics.
-----------------------------------------------------------------------------
type mnemonic_t is (MN_ADD,
MN_ADD_A_DATA,
MN_ANL,
MN_ANL_A_DATA,
MN_ANL_EXT,
MN_CALL,
MN_CLR_A,
MN_CLR_C,
MN_CLR_F,
MN_CPL_A,
MN_CPL_C,
MN_CPL_F,
MN_DA,
MN_DEC,
MN_DIS_EN_I,
MN_DIS_EN_TCNTI,
MN_DJNZ,
MN_ENT0_CLK,
MN_IN,
MN_INC,
MN_INS,
MN_JBB,
MN_JC,
MN_JF,
MN_JMP,
MN_JMPP,
MN_JNI,
MN_JT,
MN_JTF,
MN_JZ,
MN_MOV_A_DATA,
MN_MOV_A_PSW,
MN_MOV_A_RR,
MN_MOV_PSW_A,
MN_MOV_RR,
MN_MOV_RR_DATA,
MN_MOV_T,
MN_MOVD_A_PP,
MN_MOVP,
MN_MOVX,
MN_NOP,
MN_ORL,
MN_ORL_A_DATA,
MN_ORL_EXT,
MN_OUTD_PP_A,
MN_OUTL_EXT,
MN_RET,
MN_RL,
MN_RR,
MN_SEL_MB,
MN_SEL_RB,
MN_STOP_TCNT,
MN_STRT,
MN_SWAP,
MN_XCH,
MN_XRL,
MN_XRL_A_DATA);
end decoder_pack;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: decoder_pack-p.vhd,v $
-- Revision 1.2 2004/03/28 13:09:53 arniml
-- merge MN_ANLD, MN_MOVD_PP_A and MN_ORLD_PP_A to OUTLD_PP_A
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
-------------------------------------------------------------------------------

View File

@@ -1,217 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Data Memory control unit.
-- All accesses to the Data Memory are managed here.
--
-- $Id: dmem_ctrl.vhd,v 1.3 2004/04/24 23:44:25 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.dmem_addr_t;
use work.t48_pack.word_t;
use work.dmem_ctrl_pack.dmem_addr_ident_t;
entity dmem_ctrl is
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- Control Interface ------------------------------------------------------
data_i : in word_t;
write_dmem_addr_i : in boolean;
write_dmem_i : in boolean;
read_dmem_i : in boolean;
addr_type_i : in dmem_addr_ident_t;
bank_select_i : in std_logic;
data_o : out word_t;
-- Data Memory Interface --------------------------------------------------
dmem_data_i : in word_t;
dmem_addr_o : out dmem_addr_t;
dmem_we_o : out std_logic;
dmem_data_o : out word_t
);
end dmem_ctrl;
library ieee;
use ieee.numeric_std.all;
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.to_stdLogic;
use work.dmem_ctrl_pack.all;
architecture rtl of dmem_ctrl is
signal dmem_addr_s,
dmem_addr_q : dmem_addr_t;
begin
-----------------------------------------------------------------------------
-- Process addr_decode
--
-- Purpose:
-- Decode/multiplex the address information for the Data Memory.
--
addr_decode: process (data_i,
addr_type_i,
bank_select_i,
dmem_addr_q)
variable stack_addr_v : unsigned(5 downto 0);
begin
-- default assignment
dmem_addr_s <= dmem_addr_q;
stack_addr_v := (others => '0');
case addr_type_i is
when DM_PLAIN =>
dmem_addr_s <= data_i;
when DM_REG =>
dmem_addr_s <= (others => '0');
dmem_addr_s(2 downto 0) <= data_i(2 downto 0);
-- implement bank switching
if bank_select_i = '1' then
-- dmem address 24 - 31: access proper set
dmem_addr_s(4 downto 3) <= "11";
end if;
when DM_STACK =>
-- build address from stack pointer
stack_addr_v(3 downto 1) := unsigned(data_i(2 downto 0));
-- dmem address 8 - 23
stack_addr_v := stack_addr_v + 8;
dmem_addr_s <= (others => '0');
dmem_addr_s(5 downto 0) <= std_logic_vector(stack_addr_v);
when DM_STACK_HIGH =>
dmem_addr_s(0) <= '1';
when others =>
-- do nothing
-- pragma translate_off
assert false
report "Unknown address type identification for Data Memory controller!"
severity error;
-- pragma translate_on
end case;
end process addr_decode;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process dmem_addr_reg
--
-- Purpose:
-- Implements the Data Memory Address Register.
-- This register is necessary to hold the address during a write operation
-- as we cannot hold the address in the input register of the
-- synchronous RAM (no clock suppression/gating).
--
dmem_addr_reg: process (res_i, clk_i)
begin
if res_i = res_active_c then
dmem_addr_q <= (others => '0');
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
if write_dmem_addr_i then
dmem_addr_q <= dmem_addr_s;
end if;
end if;
end if;
end process dmem_addr_reg;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output mapping.
-----------------------------------------------------------------------------
dmem_addr_o <= dmem_addr_s
when write_dmem_addr_i and en_clk_i else
dmem_addr_q;
-- data from bus is fed through
dmem_data_o <= data_i;
-- data to bus is enabled upon read request
data_o <= dmem_data_i
when read_dmem_i else
(others => bus_idle_level_c);
-- write enable to Data Memory is fed through
dmem_we_o <= to_stdLogic(write_dmem_i);
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: dmem_ctrl.vhd,v $
-- Revision 1.3 2004/04/24 23:44:25 arniml
-- move from std_logic_arith to numeric_std
--
-- Revision 1.2 2004/04/18 18:58:29 arniml
-- clean up sensitivity list
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,32 +0,0 @@
-------------------------------------------------------------------------------
--
-- $Id: dmem_ctrl_pack-p.vhd,v 1.1 2004/03/23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
package dmem_ctrl_pack is
-----------------------------------------------------------------------------
-- Address Type Identifier
-----------------------------------------------------------------------------
type dmem_addr_ident_t is (DM_PLAIN,
DM_REG,
DM_STACK,
DM_STACK_HIGH);
end dmem_ctrl_pack;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: dmem_ctrl_pack-p.vhd,v $
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,252 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Interrupt Controller.
-- It collects the interrupt sources and notifies the decoder.
--
-- $Id: int.vhd,v 1.3 2004/07/11 16:51:33 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.mstate_t;
entity int is
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
clk_mstate_i : in mstate_t;
jtf_executed_i : in boolean;
tim_overflow_i : in boolean;
tf_o : out std_logic;
en_tcnti_i : in boolean;
dis_tcnti_i : in boolean;
int_n_i : in std_logic;
ale_i : in boolean;
last_cycle_i : in boolean;
en_i_i : in boolean;
dis_i_i : in boolean;
ext_int_o : out boolean;
tim_int_o : out boolean;
retr_executed_i : in boolean;
int_executed_i : in boolean;
int_pending_o : out boolean;
int_in_progress_o : out boolean
);
end int;
use work.t48_pack.all;
architecture rtl of int is
constant tim_int_c : std_logic := '0';
constant ext_int_c : std_logic := '1';
type int_state_t is (IDLE, PENDING, INT);
signal int_state_s,
int_state_q : int_state_t;
signal timer_flag_q : boolean;
signal timer_overflow_q : boolean;
signal timer_int_enable_q : boolean;
signal int_q : boolean;
signal int_enable_q : boolean;
signal ale_q : boolean;
signal int_type_q : std_logic;
signal int_in_progress_q : boolean;
begin
-----------------------------------------------------------------------------
-- Process nstate
--
-- Purpose:
-- Determines the next state of the Interrupt controller FSM.
--
nstate: process (int_state_q,
int_type_q,
int_in_progress_q,
int_executed_i,
retr_executed_i,
clk_mstate_i,
last_cycle_i)
begin
int_state_s <= int_state_q;
case int_state_q is
when IDLE =>
if int_in_progress_q and
last_cycle_i and clk_mstate_i = MSTATE5 then
int_state_s <= PENDING;
end if;
when PENDING =>
if int_executed_i then
int_state_s <= INT;
end if;
when INT =>
if retr_executed_i then
int_state_s <= IDLE;
end if;
when others =>
int_state_s <= IDLE;
end case;
end process nstate;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process regs
--
-- Purpose:
-- Implement the various registers.
-- They are designed according Figure "Interrupt Logic" of
-- "The Single Component MCS-48 System".
--
regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
timer_flag_q <= false;
timer_overflow_q <= false;
timer_int_enable_q <= false;
int_q <= false;
int_enable_q <= false;
ale_q <= false;
int_type_q <= '0';
int_state_q <= IDLE;
int_in_progress_q <= false;
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
ale_q <= ale_i;
int_state_q <= int_state_s;
if jtf_executed_i then
timer_flag_q <= false;
elsif tim_overflow_i then
timer_flag_q <= true;
end if;
if (int_type_q = tim_int_c and int_executed_i) or
not timer_int_enable_q then
timer_overflow_q <= false;
elsif tim_overflow_i then
timer_overflow_q <= true;
end if;
if dis_tcnti_i then
timer_int_enable_q <= false;
elsif en_tcnti_i then
timer_int_enable_q <= true;
end if;
if last_cycle_i and
ale_q and not ale_i then
int_q <= not to_boolean(int_n_i);
end if;
if dis_i_i then
int_enable_q <= false;
elsif en_i_i then
int_enable_q <= true;
end if;
if retr_executed_i then
int_in_progress_q <= false;
elsif (int_q and int_enable_q) or
timer_overflow_q then
int_in_progress_q <= true;
if not int_in_progress_q then
int_type_q <= to_stdLogic(int_q and int_enable_q);
end if;
end if;
end if;
end if;
end process regs;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
tf_o <= to_stdLogic(timer_flag_q);
ext_int_o <= int_type_q = ext_int_c;
tim_int_o <= int_type_q = tim_int_c;
int_pending_o <= int_state_q = PENDING;
int_in_progress_o <= int_in_progress_q;
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: int.vhd,v $
-- Revision 1.3 2004/07/11 16:51:33 arniml
-- cleanup copyright notice
--
-- Revision 1.2 2004/06/30 21:18:28 arniml
-- Fix bug report:
-- "Program Memory bank can be switched during interrupt"
-- int module emits int_in_progress signal that is used inside the decoder
-- to hold mb low for JMP and CALL during interrupts
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,180 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Opcode Decoder.
-- Derives instruction mnemonics and multicycle information
-- using the OPC table unit.
--
-- $Id: opc_decoder.vhd,v 1.2 2004/07/11 16:51:33 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_t;
use work.decoder_pack.mnemonic_t;
entity opc_decoder is
generic (
-- store mnemonic in flip-flops (registered-out)
register_mnemonic_g : integer := 1
);
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
read_bus_i : in boolean;
-- Decoder Interface ------------------------------------------------------
inj_int_i : in boolean;
opcode_o : out word_t;
mnemonic_o : out mnemonic_t;
multi_cycle_o : out boolean
);
end opc_decoder;
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.to_boolean;
--use work.decoder_pack.MN_NOP;
use work.decoder_pack.all;
use work.t48_comp_pack.opc_table;
architecture rtl of opc_decoder is
-- the opcode register
signal opcode_q : word_t;
-- the mnemonic
signal mnemonic_s,
mnemonic_q : mnemonic_t;
signal multi_cycle_s : std_logic;
begin
-----------------------------------------------------------------------------
-- Verify the generics
-----------------------------------------------------------------------------
-- pragma translate_off
-- Register Mnemonic --------------------------------------------------------
assert (register_mnemonic_g = 1) or (register_mnemonic_g = 0)
report "register_mnemonic_g must be either 1 or 0!"
severity failure;
-- pragma translate_on
-----------------------------------------------------------------------------
-- Opcode Decoder Table
-----------------------------------------------------------------------------
opc_table_b : opc_table
port map (
opcode_i => opcode_q,
multi_cycle_o => multi_cycle_s,
mnemonic_o => mnemonic_s
);
-----------------------------------------------------------------------------
-- Process regs
--
-- Purpose:
-- Implements the opcode and mnemonic registers.
--
regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
opcode_q <= (others => '0'); -- NOP
mnemonic_q <= MN_NOP;
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
if read_bus_i then
opcode_q <= data_i;
elsif inj_int_i then
opcode_q <= "00010100";
else
mnemonic_q <= mnemonic_s;
end if;
end if;
end if;
end process regs;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
opcode_o <= opcode_q;
multi_cycle_o <= to_boolean(multi_cycle_s);
mnemonic_o <= mnemonic_q
when register_mnemonic_g = 1 else
mnemonic_s;
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: opc_decoder.vhd,v $
-- Revision 1.2 2004/07/11 16:51:33 arniml
-- cleanup copyright notice
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,422 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Opcode Decoder Table.
-- Decodes the given opcode to instruction mnemonics.
-- Also derives the multicycle information.
--
-- $Id: opc_table.vhd,v 1.3 2004/07/11 16:51:33 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_t;
use work.decoder_pack.mnemonic_t;
entity opc_table is
port (
opcode_i : in word_t;
multi_cycle_o : out std_logic;
mnemonic_o : out mnemonic_t
);
end opc_table;
use work.decoder_pack.all;
architecture rtl of opc_table is
begin
-----------------------------------------------------------------------------
-- Process opc_decode
--
-- Purpose:
-- Decode the opcode to the set of mnemonics.
--
opc_decode: process (opcode_i)
begin
-- default assignment
mnemonic_o <= MN_NOP;
multi_cycle_o <= '0';
case opcode_i is
-- Mnemonic ADD ---------------------------------------------------------
when "01101000" | "01101001" | "01101010" | "01101011" | -- ADD A, Rr
"01101100" | "01101101" | "01101110" | "01101111" | --
"01100000" | "01100001" | -- ADD A, @ Rr
"01111000" | "01111001" | "01111010" | "01111011" | -- ADDC A, Rr
"01111100" | "01111101" | "01111110" | "01111111" | --
"01110000" | "01110001" => -- ADDC A, @ Rr
mnemonic_o <= MN_ADD;
-- Mnemonic ADD_A_DATA --------------------------------------------------
when "00000011" | -- ADD A, data
"00010011" => -- ADDC A, data
mnemonic_o <= MN_ADD_A_DATA;
multi_cycle_o <= '1';
-- Mnemonic ANL ---------------------------------------------------------
when "01011000" | "01011001" | "01011010" | "01011011" | -- ANL A, Rr
"01011100" | "01011101" | "01011110" | "01011111" | --
"01010000" | "01010001" => -- ANL A, @ Rr
mnemonic_o <= MN_ANL;
-- Mnemonic ANL_A_DATA --------------------------------------------------
when "01010011" => -- ANL A, data
mnemonic_o <= MN_ANL_A_DATA;
multi_cycle_o <= '1';
-- Mnemonic ANL_EXT -----------------------------------------------------
when "10011000" | -- ANL BUS, data
"10011001" | "10011010" => -- ANL PP, data
mnemonic_o <= MN_ANL_EXT;
multi_cycle_o <= '1';
-- Mnemonic CALL --------------------------------------------------------
when "00010100" | "00110100" | "01010100" | "01110100" | -- CALL addr
"10010100" | "10110100" | "11010100" | "11110100" => --
mnemonic_o <= MN_CALL;
multi_cycle_o <= '1';
-- Mnemonic CLR_A -------------------------------------------------------
when "00100111" => -- CLR A
mnemonic_o <= MN_CLR_A;
-- Mnemonic CLR_C -------------------------------------------------------
when "10010111" => -- CLR C
mnemonic_o <= MN_CLR_C;
-- Mnemonic CLR_F -------------------------------------------------------
when "10000101" | -- CLR F0
"10100101" =>
mnemonic_o <= MN_CLR_F;
-- Mnemonic CPL_A -------------------------------------------------------
when "00110111" => -- CPL A
mnemonic_o <= MN_CPL_A;
-- Mnemonic CPL_C -------------------------------------------------------
when "10100111" => -- CPL C
mnemonic_o <= MN_CPL_C;
-- Mnemonic CPL_F -------------------------------------------------------
when "10010101" | -- CPL F0
"10110101" => -- CPL F1
mnemonic_o <= MN_CPL_F;
-- Mnemonic DA ----------------------------------------------------------
when "01010111" => -- DA D
mnemonic_o <= MN_DA;
-- Mnemonic DEC ---------------------------------------------------------
when "11001000" | "11001001" | "11001010" | "11001011" | -- DEC Rr
"11001100" | "11001101" | "11001110" | "11001111" | --
"00000111" => -- DEC A
mnemonic_o <= MN_DEC;
-- Mnemonic DIS_EN_I ----------------------------------------------------
when "00010101" | -- DIS I
"00000101" => -- EN I
mnemonic_o <= MN_DIS_EN_I;
-- Mnemonic DIS_EN_TCNTI ------------------------------------------------
when "00110101" | -- DIS TCNTI
"00100101" => -- EN TCNTI
mnemonic_o <= MN_DIS_EN_TCNTI;
-- Mnemonic DJNZ --------------------------------------------------------
when "11101000" | "11101001" | "11101010" | "11101011" | -- DJNZ Rr, addr
"11101100" | "11101101" | "11101110" | "11101111" => --
mnemonic_o <= MN_DJNZ;
multi_cycle_o <= '1';
-- Mnemonic ENT0_CLK ----------------------------------------------------
when "01110101" => -- ENT0 CLK
mnemonic_o <= MN_ENT0_CLK;
-- Mnemonic IN ----------------------------------------------------------
when "00001001" | "00001010" => -- IN A, Pp
mnemonic_o <= MN_IN;
multi_cycle_o <= '1';
-- Mnemonic INC ---------------------------------------------------------
when "00010111" | -- INC A
"00011000" | "00011001" | "00011010" | "00011011" | -- INC Rr
"00011100" | "00011101" | "00011110" | "00011111" | --
"00010000" | "00010001" => -- INC @ Rr
mnemonic_o <= MN_INC;
-- Mnemonic INS ---------------------------------------------------------
when "00001000" => -- INS A, BUS
mnemonic_o <= MN_INS;
multi_cycle_o <= '1';
-- Mnemonic JBB ---------------------------------------------------------
when "00010010" | "00110010" | "01010010" | "01110010" | -- JBb addr
"10010010" | "10110010" | "11010010" | "11110010" => --
mnemonic_o <= MN_JBB;
multi_cycle_o <= '1';
-- Mnemonic JC ----------------------------------------------------------
when "11110110" | -- JC addr
"11100110" => -- JNC addr
mnemonic_o <= MN_JC;
multi_cycle_o <= '1';
-- Mnemonic JF ----------------------------------------------------------
when "10110110" | -- JF0 addr
"01110110" => -- JF1 addr
mnemonic_o <= MN_JF;
multi_cycle_o <= '1';
-- Mnemonic JMP ---------------------------------------------------------
when "00000100" | "00100100" | "01000100" | "01100100" | -- JMP addr
"10000100" | "10100100" | "11000100" | "11100100" => --
mnemonic_o <= MN_JMP;
multi_cycle_o <= '1';
-- Mnemonic JMPP --------------------------------------------------------
when "10110011" => -- JMPP @ A
mnemonic_o <= MN_JMPP;
multi_cycle_o <= '1';
-- Mnemonic JNI ---------------------------------------------------------
when "10000110" => -- JNI addr
mnemonic_o <= MN_JNI;
multi_cycle_o <= '1';
-- Mnemonic JT ----------------------------------------------------------
when "00100110" | -- JNT0 addr
"01000110" | -- JNT1 addr
"00110110" | -- JT0 addr
"01010110" => -- JT1 addr
mnemonic_o <= MN_JT;
multi_cycle_o <= '1';
-- Mnemonic JTF ---------------------------------------------------------
when "00010110" => -- JTF addr
mnemonic_o <= MN_JTF;
multi_cycle_o <= '1';
-- Mnemonic JZ ----------------------------------------------------------
when "10010110" | -- JNZ addr
"11000110" => -- JZ addr
mnemonic_o <= MN_JZ;
multi_cycle_o <= '1';
-- Mnemonic MOV_A_DATA --------------------------------------------------
when "00100011" => -- MOV A, data
mnemonic_o <= MN_MOV_A_DATA;
multi_cycle_o <= '1';
-- Mnemonic MOV_A_PSW ---------------------------------------------------
when "11000111" => -- MOV A, PSW
mnemonic_o <= MN_MOV_A_PSW;
-- Mnemonic MOV_A_RR ----------------------------------------------------
when "11111000" | "11111001" | "11111010" | "11111011" | -- MOV A, Rr
"11111100" | "11111101" | "11111110" | "11111111" | --
"11110000" | "11110001" => -- MOV A, @ Rr
mnemonic_o <= MN_MOV_A_RR;
-- Mnemonic MOV_PSW_A ---------------------------------------------------
when "11010111" => -- MOV PSW, A
mnemonic_o <= MN_MOV_PSW_A;
-- Mnemonic MOV_RR ------------------------------------------------------
when "10101000" | "10101001" | "10101010" | "10101011" | -- MOV Rr, A
"10101100" | "10101101" | "10101110" | "10101111" | --
"10100000" | "10100001" => -- MOV @ Rr, A
mnemonic_o <= MN_MOV_RR;
-- Mnemonic MOV_RR_DATA -------------------------------------------------
when "10111000" | "10111001" | "10111010" | "10111011" | -- MOV Rr, data
"10111100" | "10111101" | "10111110" | "10111111" | --
"10110000" | "10110001" => -- MOV @ Rr, data
mnemonic_o <= MN_MOV_RR_DATA;
multi_cycle_o <= '1';
-- Mnemonic MOV_T -------------------------------------------------------
when "01100010" | -- MOV T, A
"01000010" => -- MOV A, T
mnemonic_o <= MN_MOV_T;
-- Mnemonic MOVD_A_PP ---------------------------------------------------
when "00001100" | "00001101" | "00001110" | "00001111" => -- MOVD A, Pp
mnemonic_o <= MN_MOVD_A_PP;
multi_cycle_o <= '1';
-- Mnemonic MOVP --------------------------------------------------------
when "10100011" | -- MOVP A, @ A
"11100011" => -- MOVP3 A, @ A
mnemonic_o <= MN_MOVP;
multi_cycle_o <= '1';
-- Mnemonic MOVX --------------------------------------------------------
when "10000000" | "10000001" | -- MOVX A, @ Rr
"10010000" | "10010001" => -- MOVX @ Rr, A
mnemonic_o <= MN_MOVX;
multi_cycle_o <= '1';
-- Mnemonic NOP ---------------------------------------------------------
when "00000000" => -- NOP
mnemonic_o <= MN_NOP;
-- Mnemonic ORL ---------------------------------------------------------
when "01001000" | "01001001" | "01001010" | "01001011" | -- ORL A, Rr
"01001100" | "01001101" | "01001110" | "01001111" | --
"01000000" | "01000001" => -- ORL A, @ Rr
mnemonic_o <= MN_ORL;
-- Mnemonic ORL_A_DATA --------------------------------------------------
when "01000011" => -- ORL A, data
mnemonic_o <= MN_ORL_A_DATA;
multi_cycle_o <= '1';
-- Mnemonic ORL_EXT -----------------------------------------------------
when "10001000" | -- ORL BUS, data
"10001001" | "10001010" => -- ORL Pp, data
mnemonic_o <= MN_ORL_EXT;
multi_cycle_o <= '1';
-- Mnemonic OUTD_PP_A ---------------------------------------------------
when "00111100" | "00111101" | "00111110" | "00111111" | -- MOVD Pp, A
"10011100" | "10011101" | "10011110" | "10011111" | -- ANLD PP, A
"10001100" | "10001101" | "10001110" | "10001111" => -- ORLD Pp, A
mnemonic_o <= MN_OUTD_PP_A;
multi_cycle_o <= '1';
-- Mnemonic OUTL_EXT ----------------------------------------------------
when "00111001" | "00111010" | -- OUTL Pp, A
"00000010" => -- OUTL BUS, A
mnemonic_o <= MN_OUTL_EXT;
multi_cycle_o <= '1';
-- Mnemonic RET ---------------------------------------------------------
when "10000011" | -- RET
"10010011" => -- RETR
mnemonic_o <= MN_RET;
multi_cycle_o <= '1';
-- Mnemonic RL ----------------------------------------------------------
when "11100111" | -- RL A
"11110111" => -- RLC A
mnemonic_o <= MN_RL;
-- Mnemonic RR ----------------------------------------------------------
when "01110111" | -- RR A
"01100111" => -- RRC A
mnemonic_o <= MN_RR;
-- Mnemonic SEL_MB ------------------------------------------------------
when "11100101" | -- SEL MB0
"11110101" => -- SEL MB1
mnemonic_o <= MN_SEL_MB;
-- Mnemonic SEL_RB ------------------------------------------------------
when "11000101" | -- SEL RB0
"11010101" => -- SEL RB1
mnemonic_o <= MN_SEL_RB;
-- Mnemonic STOP_TCNT ---------------------------------------------------
when "01100101" => -- STOP TCNT
mnemonic_o <= MN_STOP_TCNT;
-- Mnemonic START -------------------------------------------------------
when "01000101" | -- STRT CNT
"01010101" => -- STRT T
mnemonic_o <= MN_STRT;
-- Mnemonic SWAP --------------------------------------------------------
when "01000111" => -- SWAP A
mnemonic_o <= MN_SWAP;
-- Mnemonic XCH ---------------------------------------------------------
when "00101000" | "00101001" | "00101010" | "00101011" | -- XCH A, Rr
"00101100" | "00101101" | "00101110" | "00101111" | --
"00100000" | "00100001" | -- XCH A, @ Rr
"00110000" | "00110001" => -- XCHD A, @ Rr
mnemonic_o <= MN_XCH;
-- Mnemonic XRL ---------------------------------------------------------
when "11011000" | "11011001" | "11011010" | "11011011" | -- XRL A, Rr
"11011100" | "11011101" | "11011110" | "11011111" | --
"11010000" | "11010001" => -- XRL A, @ Rr
mnemonic_o <= MN_XRL;
-- Mnemonic XRL_A_DATA --------------------------------------------------
when "11010011" => -- XRL A, data
mnemonic_o <= MN_XRL_A_DATA;
multi_cycle_o <= '1';
when others =>
-- pragma translate_off
assert now = 0 ns
report "Unknown opcode."
severity warning;
-- pragma translate_on
end case;
end process opc_decode;
--
-----------------------------------------------------------------------------
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: opc_table.vhd,v $
-- Revision 1.3 2004/07/11 16:51:33 arniml
-- cleanup copyright notice
--
-- Revision 1.2 2004/03/28 13:10:48 arniml
-- merge MN_ANLD, MN_MOVD_PP_A and MN_ORLD_PP_A to OUTLD_PP_A
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
-------------------------------------------------------------------------------

View File

@@ -1,170 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Port 1 unit.
-- Implements the Port 1 logic.
--
-- $Id: p1.vhd,v 1.4 2004/07/11 16:51:33 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_t;
entity p1 is
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
write_p1_i : in boolean;
read_p1_i : in boolean;
read_reg_i : in boolean;
-- Port 1 Interface -------------------------------------------------------
p1_i : in word_t;
p1_o : out word_t;
p1_low_imp_o : out std_logic
);
end p1;
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
architecture rtl of p1 is
-- the port output register
signal p1_q : word_t;
-- the low impedance marker
signal low_imp_q : std_logic;
begin
-----------------------------------------------------------------------------
-- Process p1_reg
--
-- Purpose:
-- Implements the port output register.
--
p1_reg: process (res_i, clk_i)
begin
if res_i = res_active_c then
p1_q <= (others => '1');
low_imp_q <= '0';
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
if write_p1_i then
p1_q <= data_i;
low_imp_q <= '1';
else
low_imp_q <= '0';
end if;
end if;
end if;
end process p1_reg;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process p1_data
--
-- Purpose:
-- Generates the T48 bus data.
--
p1_data: process (read_p1_i,
p1_i,
read_reg_i,
p1_q)
begin
data_o <= (others => bus_idle_level_c);
if read_p1_i then
if read_reg_i then
data_o <= p1_q;
else
data_o <= p1_i;
end if;
end if;
end process p1_data;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
p1_o <= p1_q;
p1_low_imp_o <= low_imp_q;
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: p1.vhd,v $
-- Revision 1.4 2004/07/11 16:51:33 arniml
-- cleanup copyright notice
--
-- Revision 1.3 2004/05/17 14:37:53 arniml
-- reorder data_o generation
--
-- Revision 1.2 2004/03/29 19:39:58 arniml
-- rename pX_limp to pX_low_imp
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
-------------------------------------------------------------------------------

View File

@@ -1,219 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Port 2 unit.
-- Implements the Port 2 logic.
--
-- $Id: p2.vhd,v 1.6 2004/07/11 16:51:33 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_t;
use work.t48_pack.nibble_t;
entity p2 is
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
write_p2_i : in boolean;
write_exp_i : in boolean;
read_p2_i : in boolean;
read_reg_i : in boolean;
read_exp_i : in boolean;
-- Port 2 Interface -------------------------------------------------------
output_pch_i : in boolean;
output_exp_i : in boolean;
pch_i : in nibble_t;
p2_i : in word_t;
p2_o : out word_t;
p2_low_imp_o : out std_logic
);
end p2;
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
architecture rtl of p2 is
-- the port output register
signal p2_q : word_t;
-- the low impedance marker
signal low_imp_q : std_logic;
-- the expander register
signal exp_q : nibble_t;
begin
-----------------------------------------------------------------------------
-- Process p2_regs
--
-- Purpose:
-- Implements the port output and expander registers.
--
p2_regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
p2_q <= (others => '1');
low_imp_q <= '0';
exp_q <= (others => '0');
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
if write_p2_i then
p2_q <= data_i;
low_imp_q <= '1';
else
low_imp_q <= '0';
end if;
if write_exp_i then
exp_q <= data_i(exp_q'range);
end if;
end if;
end if;
end process p2_regs;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process p2_port
--
-- Purpose:
-- Generates the output byte vector for Port 2.
--
p2_port: process (p2_q,
exp_q,
output_exp_i,
pch_i,
output_pch_i)
begin
p2_o <= p2_q;
if output_exp_i then
p2_o(nibble_t'range) <= exp_q;
end if;
if output_pch_i then
p2_o(nibble_t'range) <= pch_i;
end if;
end process p2_port;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process p2_data
--
-- Purpose:
-- Generates the T48 bus data.
--
p2_data: process (read_p2_i,
p2_i,
read_reg_i,
p2_q,
read_exp_i)
begin
data_o <= (others => bus_idle_level_c);
if read_p2_i then
if read_reg_i then
data_o <= p2_q;
elsif read_exp_i then
data_o <= "0000" & p2_i(nibble_t'range);
else
data_o <= p2_i;
end if;
end if;
end process p2_data;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
p2_low_imp_o <= low_imp_q;
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: p2.vhd,v $
-- Revision 1.6 2004/07/11 16:51:33 arniml
-- cleanup copyright notice
--
-- Revision 1.5 2004/05/17 13:52:46 arniml
-- Fix bug "ANL and ORL to P1/P2 read port status instead of port output register"
--
-- Revision 1.4 2004/04/24 23:44:25 arniml
-- move from std_logic_arith to numeric_std
--
-- Revision 1.3 2004/03/29 19:39:58 arniml
-- rename pX_limp to pX_low_imp
--
-- Revision 1.2 2004/03/28 13:11:43 arniml
-- rework Port 2 expander handling
--
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
-------------------------------------------------------------------------------

View File

@@ -1,231 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Program Memory control unit.
-- All operations related to the Program Memory are managed here.
--
-- $Id: pmem_ctrl.vhd,v 1.3 2004/07/11 16:51:33 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.pmem_addr_t;
use work.t48_pack.word_t;
use work.pmem_ctrl_pack.pmem_addr_ident_t;
entity pmem_ctrl is
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
write_pcl_i : in boolean;
read_pcl_i : in boolean;
write_pch_i : in boolean;
read_pch_i : in boolean;
inc_pc_i : in boolean;
write_pmem_addr_i : in boolean;
addr_type_i : in pmem_addr_ident_t;
read_pmem_i : in boolean;
-- Porgram Memroy Interface -----------------------------------------------
pmem_addr_o : out pmem_addr_t;
pmem_data_i : in word_t
);
end pmem_ctrl;
library ieee;
use ieee.numeric_std.all;
use work.pmem_ctrl_pack.all;
use work.t48_pack.res_active_c;
use work.t48_pack.clk_active_c;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.pmem_addr_width_c;
use work.t48_pack.dmem_addr_width_c;
use work.t48_pack.page_t;
architecture rtl of pmem_ctrl is
-- the Program Counter
signal program_counter_q : unsigned(pmem_addr_t'range);
-- the Program Memory address
signal pmem_addr_s,
pmem_addr_q : std_logic_vector(pmem_addr_t'range);
begin
-----------------------------------------------------------------------------
-- Process program_counter
--
-- Purpose:
-- Implements the Program Counter.
--
program_counter: process (res_i, clk_i)
begin
if res_i = res_active_c then
program_counter_q <= (others => '0');
pmem_addr_q <= (others => '0');
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
-- parallel load mode
if write_pcl_i then
program_counter_q(data_i'range) <= UNSIGNED(data_i);
elsif write_pch_i then
program_counter_q(pmem_addr_width_c-1 downto data_i'high+1) <=
UNSIGNED(data_i(pmem_addr_width_c - dmem_addr_width_c - 1 downto 0));
elsif inc_pc_i then
-- increment mode
program_counter_q <= program_counter_q + 1;
end if;
-- set pmem address
if write_pmem_addr_i then
pmem_addr_q <= pmem_addr_s;
end if;
end if;
end if;
end process program_counter;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process pmem_addr
--
-- Purpose:
-- Multiplex the Program Memory address.
--
pmem_addr: process (program_counter_q,
addr_type_i,
pmem_addr_q,
data_i)
begin
-- default assignment
pmem_addr_s <= STD_LOGIC_VECTOR(program_counter_q);
case addr_type_i is
when PM_PC =>
-- default is ok
null;
when PM_PAGE =>
pmem_addr_s(word_t'range) <= data_i;
-- take page address from program counter
-- => important for JMPP, MOVP!
-- they must wrap to next page when at FF!
when PM_PAGE3 =>
pmem_addr_s(word_t'range) <= data_i;
-- page address is explicitely specified
pmem_addr_s(page_t'range) <= "0011";
when others =>
null;
end case;
end process pmem_addr;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process data_output
--
-- Purpose:
-- Multiplex the data bus output.
--
data_output: process (read_pmem_i,
read_pcl_i,
read_pch_i,
pmem_data_i,
program_counter_q)
begin
data_o <= (others => bus_idle_level_c);
if read_pmem_i then
data_o <= pmem_data_i;
elsif read_pcl_i then
data_o <= STD_LOGIC_VECTOR(program_counter_q(data_o'range));
elsif read_pch_i then
data_o(3 downto 0) <= STD_LOGIC_VECTOR(program_counter_q(pmem_addr_width_c-1 downto data_o'high+1));
end if;
end process data_output;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
pmem_addr_o <= pmem_addr_q;
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: pmem_ctrl.vhd,v $
-- Revision 1.3 2004/07/11 16:51:33 arniml
-- cleanup copyright notice
--
-- Revision 1.2 2004/04/24 23:44:25 arniml
-- move from std_logic_arith to numeric_std
--
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,31 +0,0 @@
-------------------------------------------------------------------------------
--
-- $Id: pmem_ctrl_pack-p.vhd,v 1.1 2004/03/23 21:31:53 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
package pmem_ctrl_pack is
-----------------------------------------------------------------------------
-- Address Type Identifier
-----------------------------------------------------------------------------
type pmem_addr_ident_t is (PM_PC,
PM_PAGE,
PM_PAGE3);
end pmem_ctrl_pack;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: pmem_ctrl_pack-p.vhd,v $
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,240 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Program Status Word (PSW).
-- Implements the PSW with its special bits.
--
-- $Id: psw.vhd,v 1.7 2004/07/11 16:51:33 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_t;
entity psw is
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
read_psw_i : in boolean;
read_sp_i : in boolean;
write_psw_i : in boolean;
write_sp_i : in boolean;
-- Decoder Interface ------------------------------------------------------
special_data_i : in std_logic;
inc_stackp_i : in boolean;
dec_stackp_i : in boolean;
write_carry_i : in boolean;
write_aux_carry_i : in boolean;
write_f0_i : in boolean;
write_bs_i : in boolean;
carry_o : out std_logic;
aux_carry_i : in std_logic;
aux_carry_o : out std_logic;
f0_o : out std_logic;
bs_o : out std_logic
);
end psw;
library ieee;
use ieee.numeric_std.all;
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.nibble_t;
architecture rtl of psw is
-- special bit positions in PSW
constant carry_c : natural := 3;
constant aux_carry_c : natural := 2;
constant f0_c : natural := 1;
constant bs_c : natural := 0;
-- the PSW register
signal psw_q : nibble_t;
-- the Stack Pointer
signal sp_q : unsigned(2 downto 0);
-- pragma translate_off
signal psw_s : word_t;
-- pragma translate_on
begin
-----------------------------------------------------------------------------
-- Process psw_reg
--
-- Purpose:
-- Implements the PSW register.
--
psw_reg: process (res_i, clk_i)
begin
if res_i = res_active_c then
psw_q <= (others => '0');
sp_q <= (others => '0');
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
-- T48 bus access
if write_psw_i then
psw_q <= data_i(7 downto 4);
end if;
if write_sp_i then
sp_q <= unsigned(data_i(2 downto 0));
end if;
-- increment Stack Pointer
if inc_stackp_i then
sp_q <= sp_q + 1;
end if;
-- decrement Stack Pointer
if dec_stackp_i then
sp_q <= sp_q - 1;
end if;
-- access to special bits
if write_carry_i then
psw_q(carry_c) <= special_data_i;
end if;
--
if write_aux_carry_i then
psw_q(aux_carry_c) <= aux_carry_i;
end if;
--
if write_f0_i then
psw_q(f0_c) <= special_data_i;
end if;
--
if write_bs_i then
psw_q(bs_c) <= special_data_i;
end if;
end if;
end if;
end process psw_reg;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process data_out
--
-- Purpose:
-- Output multiplexer for T48 Data Bus.
--
data_out: process (read_psw_i,
read_sp_i,
psw_q,
sp_q)
begin
data_o <= (others => bus_idle_level_c);
if read_psw_i then
data_o(7 downto 4) <= psw_q;
end if;
if read_sp_i then
data_o(3 downto 0) <= '1' & std_logic_vector(sp_q);
end if;
end process data_out;
--
-----------------------------------------------------------------------------
-- pragma translate_off
tb: process (psw_q, sp_q)
begin
psw_s(7 downto 4) <= psw_q;
psw_s(3) <= '1';
psw_s(2 downto 0) <= std_logic_vector(sp_q);
end process tb;
-- pragma translate_on
-----------------------------------------------------------------------------
-- Output mapping.
-----------------------------------------------------------------------------
carry_o <= psw_q(carry_c);
aux_carry_o <= psw_q(aux_carry_c);
f0_o <= psw_q(f0_c);
bs_o <= psw_q(bs_c);
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: psw.vhd,v $
-- Revision 1.7 2004/07/11 16:51:33 arniml
-- cleanup copyright notice
--
-- Revision 1.6 2004/04/24 23:44:25 arniml
-- move from std_logic_arith to numeric_std
--
-- Revision 1.5 2004/04/24 11:25:39 arniml
-- removed dummy_s - workaround not longer needed for GHDL 0.11.1
--
-- Revision 1.4 2004/04/18 18:59:01 arniml
-- add temporary workaround for GHDL 0.11
--
-- Revision 1.3 2004/04/04 14:15:45 arniml
-- add dump_compare support
--
-- Revision 1.2 2004/03/28 21:28:13 arniml
-- take auxiliary carry from direct ALU connection
--
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
-------------------------------------------------------------------------------

View File

@@ -1,73 +0,0 @@
-------------------------------------------------------------------------------
--
-- A synchronous parametrizable RAM.
--
-- $Id: syn_ram-e.vhd,v 1.1 2004/03/24 21:32:27 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity syn_ram is
generic (
address_width_g : positive := 8
);
port (
clk_i : in std_logic;
res_i : in std_logic;
ram_addr_i : in std_logic_vector(address_width_g-1 downto 0);
ram_data_i : in std_logic_vector(7 downto 0);
ram_we_i : in std_logic;
ram_data_o : out std_logic_vector(7 downto 0)
);
end syn_ram;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: syn_ram-e.vhd,v $
-- Revision 1.1 2004/03/24 21:32:27 arniml
-- initial check-in
--
-------------------------------------------------------------------------------

View File

@@ -1,392 +0,0 @@
-------------------------------------------------------------------------------
--
-- $Id: t48_comp_pack-p.vhd,v 1.7 2004/06/30 21:16:21 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.alu_pack.alu_op_t;
use work.cond_branch_pack.branch_conditions_t;
use work.cond_branch_pack.comp_value_t;
use work.decoder_pack.mnemonic_t;
use work.dmem_ctrl_pack.dmem_addr_ident_t;
use work.pmem_ctrl_pack.pmem_addr_ident_t;
use work.t48_pack.dmem_addr_t;
use work.t48_pack.pmem_addr_t;
use work.t48_pack.mstate_t;
use work.t48_pack.word_t;
use work.t48_pack.nibble_t;
package t48_comp_pack is
component alu
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
data_o : out word_t;
write_accu_i : in boolean;
write_shadow_i : in boolean;
write_temp_reg_i : in boolean;
read_alu_i : in boolean;
carry_i : in std_logic;
carry_o : out std_logic;
aux_carry_o : out std_logic;
alu_op_i : in alu_op_t;
use_carry_i : in boolean;
da_high_i : in boolean;
da_overflow_o : out boolean;
accu_low_i : in boolean;
p06_temp_reg_i : in boolean;
p60_temp_reg_i : in boolean
);
end component;
component bus_mux
port (
alu_data_i : in word_t;
bus_data_i : in word_t;
dec_data_i : in word_t;
dm_data_i : in word_t;
pm_data_i : in word_t;
p1_data_i : in word_t;
p2_data_i : in word_t;
psw_data_i : in word_t;
tim_data_i : in word_t;
data_o : out word_t
);
end component;
component clock_ctrl
generic (
xtal_div_3_g : integer := 1
);
port (
clk_i : in std_logic;
xtal_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
xtal3_o : out boolean;
multi_cycle_i : in boolean;
assert_psen_i : in boolean;
assert_prog_i : in boolean;
assert_rd_i : in boolean;
assert_wr_i : in boolean;
mstate_o : out mstate_t;
second_cycle_o : out boolean;
ale_o : out boolean;
psen_o : out boolean;
prog_o : out boolean;
rd_o : out boolean;
wr_o : out boolean
);
end component;
component cond_branch
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
compute_take_i : in boolean;
branch_cond_i : in branch_conditions_t;
take_branch_o : out boolean;
accu_i : in word_t;
t0_i : in std_logic;
t1_i : in std_logic;
int_n_i : in std_logic;
f0_i : in std_logic;
f1_i : in std_logic;
tf_i : in std_logic;
carry_i : in std_logic;
comp_value_i : in comp_value_t
);
end component;
component db_bus
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
ea_i : in std_logic;
data_i : in word_t;
data_o : out word_t;
write_bus_i : in boolean;
read_bus_i : in boolean;
output_pcl_i : in boolean;
bidir_bus_i : in boolean;
pcl_i : in word_t;
db_i : in word_t;
db_o : out word_t;
db_dir_o : out std_logic
);
end component;
component decoder
generic (
register_mnemonic_g : integer := 1
);
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
ea_i : in std_logic;
ale_i : in boolean;
int_n_i : in std_logic;
t0_dir_o : out std_logic;
data_i : in word_t;
data_o : out word_t;
alu_write_accu_o : out boolean;
alu_write_shadow_o : out boolean;
alu_write_temp_reg_o : out boolean;
alu_read_alu_o : out boolean;
bus_write_bus_o : out boolean;
bus_read_bus_o : out boolean;
dm_write_dmem_addr_o : out boolean;
dm_write_dmem_o : out boolean;
dm_read_dmem_o : out boolean;
p1_write_p1_o : out boolean;
p1_read_p1_o : out boolean;
p2_write_p2_o : out boolean;
p2_write_exp_o : out boolean;
p2_read_p2_o : out boolean;
pm_write_pcl_o : out boolean;
pm_read_pcl_o : out boolean;
pm_write_pch_o : out boolean;
pm_read_pch_o : out boolean;
pm_read_pmem_o : out boolean;
psw_read_psw_o : out boolean;
psw_read_sp_o : out boolean;
psw_write_psw_o : out boolean;
psw_write_sp_o : out boolean;
alu_carry_i : in std_logic;
alu_op_o : out alu_op_t;
alu_da_high_o : out boolean;
alu_accu_low_o : out boolean;
alu_da_overflow_i : in boolean;
alu_p06_temp_reg_o : out boolean;
alu_p60_temp_reg_o : out boolean;
alu_use_carry_o : out boolean;
bus_output_pcl_o : out boolean;
bus_bidir_bus_o : out boolean;
clk_multi_cycle_o : out boolean;
clk_assert_psen_o : out boolean;
clk_assert_prog_o : out boolean;
clk_assert_rd_o : out boolean;
clk_assert_wr_o : out boolean;
clk_mstate_i : in mstate_t;
clk_second_cycle_i : in boolean;
cnd_compute_take_o : out boolean;
cnd_branch_cond_o : out branch_conditions_t;
cnd_take_branch_i : in boolean;
cnd_comp_value_o : out comp_value_t;
cnd_f1_o : out std_logic;
cnd_tf_o : out std_logic;
dm_addr_type_o : out dmem_addr_ident_t;
tim_read_timer_o : out boolean;
tim_write_timer_o : out boolean;
tim_start_t_o : out boolean;
tim_start_cnt_o : out boolean;
tim_stop_tcnt_o : out boolean;
p1_read_reg_o : out boolean;
p2_read_reg_o : out boolean;
p2_read_exp_o : out boolean;
p2_output_pch_o : out boolean;
p2_output_exp_o : out boolean;
pm_inc_pc_o : out boolean;
pm_write_pmem_addr_o : out boolean;
pm_addr_type_o : out pmem_addr_ident_t;
psw_special_data_o : out std_logic;
psw_carry_i : in std_logic;
psw_aux_carry_i : in std_logic;
psw_f0_i : in std_logic;
psw_inc_stackp_o : out boolean;
psw_dec_stackp_o : out boolean;
psw_write_carry_o : out boolean;
psw_write_aux_carry_o : out boolean;
psw_write_f0_o : out boolean;
psw_write_bs_o : out boolean;
tim_overflow_i : in boolean
);
end component;
component dmem_ctrl
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
write_dmem_addr_i : in boolean;
write_dmem_i : in boolean;
read_dmem_i : in boolean;
addr_type_i : in dmem_addr_ident_t;
bank_select_i : in std_logic;
data_o : out word_t;
dmem_data_i : in word_t;
dmem_addr_o : out dmem_addr_t;
dmem_we_o : out std_logic;
dmem_data_o : out word_t
);
end component;
component int
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
clk_mstate_i : in mstate_t;
jtf_executed_i : in boolean;
tim_overflow_i : in boolean;
tf_o : out std_logic;
en_tcnti_i : in boolean;
dis_tcnti_i : in boolean;
int_n_i : in std_logic;
ale_i : in boolean;
last_cycle_i : in boolean;
en_i_i : in boolean;
dis_i_i : in boolean;
ext_int_o : out boolean;
tim_int_o : out boolean;
retr_executed_i : in boolean;
int_executed_i : in boolean;
int_pending_o : out boolean;
int_in_progress_o : out boolean
);
end component;
component opc_table
port (
opcode_i : in word_t;
multi_cycle_o : out std_logic;
mnemonic_o : out mnemonic_t
);
end component;
component opc_decoder
generic (
register_mnemonic_g : integer := 1
);
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
read_bus_i : in boolean;
inj_int_i : in boolean;
opcode_o : out word_t;
mnemonic_o : out mnemonic_t;
multi_cycle_o : out boolean
);
end component;
component timer
generic (
sample_t1_state_g : integer := 4
);
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
t1_i : in std_logic;
clk_mstate_i : in mstate_t;
data_i : in word_t;
data_o : out word_t;
read_timer_i : in boolean;
write_timer_i : in boolean;
start_t_i : in boolean;
start_cnt_i : in boolean;
stop_tcnt_i : in boolean;
overflow_o : out std_logic
);
end component;
component p1
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
data_o : out word_t;
write_p1_i : in boolean;
read_p1_i : in boolean;
read_reg_i : in boolean;
p1_i : in word_t;
p1_o : out word_t;
p1_low_imp_o : out std_logic
);
end component;
component p2
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
data_o : out word_t;
write_p2_i : in boolean;
write_exp_i : in boolean;
read_p2_i : in boolean;
read_reg_i : in boolean;
read_exp_i : in boolean;
output_pch_i : in boolean;
output_exp_i : in boolean;
pch_i : in nibble_t;
p2_i : in word_t;
p2_o : out word_t;
p2_low_imp_o : out std_logic
);
end component;
component pmem_ctrl
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
data_o : out word_t;
write_pcl_i : in boolean;
read_pcl_i : in boolean;
write_pch_i : in boolean;
read_pch_i : in boolean;
inc_pc_i : in boolean;
write_pmem_addr_i : in boolean;
addr_type_i : in pmem_addr_ident_t;
read_pmem_i : in boolean;
pmem_addr_o : out pmem_addr_t;
pmem_data_i : in word_t
);
end component;
component psw
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
data_o : out word_t;
read_psw_i : in boolean;
read_sp_i : in boolean;
write_psw_i : in boolean;
write_sp_i : in boolean;
special_data_i : in std_logic;
inc_stackp_i : in boolean;
dec_stackp_i : in boolean;
write_carry_i : in boolean;
write_aux_carry_i : in boolean;
write_f0_i : in boolean;
write_bs_i : in boolean;
carry_o : out std_logic;
aux_carry_i : in std_logic;
aux_carry_o : out std_logic;
f0_o : out std_logic;
bs_o : out std_logic
);
end component;
end t48_comp_pack;

View File

@@ -1,655 +0,0 @@
-------------------------------------------------------------------------------
--
-- T48 Microcontroller Core
--
-- $Id: t48_core.vhd,v 1.7 2004/05/01 11:58:04 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-- Limitations :
-- =============
--
-- Compared to the original MCS-48 architecture, the following limitations
-- apply:
--
-- * Nibble-wide instructions addressing expander port implemented but
-- not verified in detail.
--
-- * Single-step mode not implemented.
-- Not selected for future implementation.
--
-- * Reading of internal Program Memory not implemented.
-- Not selected for future implementation.
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity t48_core is
generic (
-- divide XTAL1 by 3 to derive Clock States
xtal_div_3_g : integer := 1;
-- store mnemonic in flip-flops (registered-out)
register_mnemonic_g : integer := 1;
-- include the port 1 module
include_port1_g : integer := 1;
-- include the port 2 module
include_port2_g : integer := 1;
-- include the BUS module
include_bus_g : integer := 1;
-- include the timer module
include_timer_g : integer := 1;
-- state in which T1 is sampled (3 or 4)
sample_t1_state_g : integer := 4
);
port (
-- T48 Interface ----------------------------------------------------------
xtal_i : in std_logic;
reset_i : in std_logic;
t0_i : in std_logic;
t0_o : out std_logic;
t0_dir_o : out std_logic;
int_n_i : in std_logic;
ea_i : in std_logic;
rd_n_o : out std_logic;
psen_n_o : out std_logic;
wr_n_o : out std_logic;
ale_o : out std_logic;
db_i : in std_logic_vector( 7 downto 0);
db_o : out std_logic_vector( 7 downto 0);
db_dir_o : out std_logic;
t1_i : in std_logic;
p2_i : in std_logic_vector( 7 downto 0);
p2_o : out std_logic_vector( 7 downto 0);
p2_low_imp_o : out std_logic;
p1_i : in std_logic_vector( 7 downto 0);
p1_o : out std_logic_vector( 7 downto 0);
p1_low_imp_o : out std_logic;
prog_n_o : out std_logic;
-- Core Interface ---------------------------------------------------------
clk_i : in std_logic;
en_clk_i : in std_logic;
xtal3_o : out std_logic;
dmem_addr_o : out std_logic_vector( 7 downto 0);
dmem_we_o : out std_logic;
dmem_data_i : in std_logic_vector( 7 downto 0);
dmem_data_o : out std_logic_vector( 7 downto 0);
pmem_addr_o : out std_logic_vector(11 downto 0);
pmem_data_i : in std_logic_vector( 7 downto 0)
);
end t48_core;
use work.alu_pack.alu_op_t;
use work.cond_branch_pack.branch_conditions_t;
use work.cond_branch_pack.comp_value_t;
use work.dmem_ctrl_pack.dmem_addr_ident_t;
use work.pmem_ctrl_pack.pmem_addr_ident_t;
use work.t48_comp_pack.all;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.word_t;
use work.t48_pack.pmem_addr_t;
use work.t48_pack.mstate_t;
use work.t48_pack.to_stdLogic;
use work.t48_pack.to_boolean;
architecture struct of t48_core is
signal t48_data_s : word_t;
signal en_clk_s : boolean;
-- ALU signals
signal alu_data_s : word_t;
signal alu_write_accu_s : boolean;
signal alu_write_shadow_s : boolean;
signal alu_write_temp_reg_s : boolean;
signal alu_read_alu_s : boolean;
signal alu_carry_s : std_logic;
signal alu_aux_carry_s : std_logic;
signal alu_op_s : alu_op_t;
signal alu_use_carry_s : boolean;
signal alu_da_high_s : boolean;
signal alu_da_overflow_s : boolean;
signal alu_accu_low_s : boolean;
signal alu_p06_temp_reg_s : boolean;
signal alu_p60_temp_reg_s : boolean;
-- BUS signals
signal bus_write_bus_s : boolean;
signal bus_read_bus_s : boolean;
signal bus_output_pcl_s : boolean;
signal bus_bidir_bus_s : boolean;
signal bus_data_s : word_t;
-- Clock Controller signals
signal clk_multi_cycle_s : boolean;
signal clk_assert_psen_s : boolean;
signal clk_assert_prog_s : boolean;
signal clk_assert_rd_s : boolean;
signal clk_assert_wr_s : boolean;
signal clk_mstate_s : mstate_t;
signal clk_second_cycle_s : boolean;
signal psen_s : boolean;
signal prog_s : boolean;
signal rd_s : boolean;
signal wr_s : boolean;
signal ale_s : boolean;
signal xtal3_s : boolean;
-- Conditional Branch Logic signals
signal cnd_compute_take_s : boolean;
signal cnd_branch_cond_s : branch_conditions_t;
signal cnd_take_branch_s : boolean;
signal cnd_comp_value_s : comp_value_t;
signal cnd_f1_s : std_logic;
signal cnd_tf_s : std_logic;
-- Data Memory Controller signals
signal dm_write_dmem_addr_s : boolean;
signal dm_write_dmem_s : boolean;
signal dm_read_dmem_s : boolean;
signal dm_addr_type_s : dmem_addr_ident_t;
signal dm_data_s : word_t;
-- Decoder signals
signal dec_data_s : word_t;
-- Port 1 signals
signal p1_write_p1_s : boolean;
signal p1_read_p1_s : boolean;
signal p1_read_reg_s : boolean;
signal p1_data_s : word_t;
-- Port 2 signals
signal p2_write_p2_s : boolean;
signal p2_write_exp_s : boolean;
signal p2_read_p2_s : boolean;
signal p2_read_reg_s : boolean;
signal p2_read_exp_s : boolean;
signal p2_output_pch_s : boolean;
signal p2_output_exp_s : boolean;
signal p2_data_s : word_t;
-- Program Memory Controller signals
signal pm_write_pcl_s : boolean;
signal pm_read_pcl_s : boolean;
signal pm_write_pch_s : boolean;
signal pm_read_pch_s : boolean;
signal pm_read_pmem_s : boolean;
signal pm_inc_pc_s : boolean;
signal pm_write_pmem_addr_s : boolean;
signal pm_data_s : word_t;
signal pm_addr_type_s : pmem_addr_ident_t;
signal pmem_addr_s : pmem_addr_t;
-- PSW signals
signal psw_read_psw_s : boolean;
signal psw_read_sp_s : boolean;
signal psw_write_psw_s : boolean;
signal psw_write_sp_s : boolean;
signal psw_carry_s : std_logic;
signal psw_aux_carry_s : std_logic;
signal psw_f0_s : std_logic;
signal psw_bs_s : std_logic;
signal psw_special_data_s : std_logic;
signal psw_inc_stackp_s : boolean;
signal psw_dec_stackp_s : boolean;
signal psw_write_carry_s : boolean;
signal psw_write_aux_carry_s : boolean;
signal psw_write_f0_s : boolean;
signal psw_write_bs_s : boolean;
signal psw_data_s : word_t;
-- Timer signals
signal tim_overflow_s : boolean;
signal tim_of_s : std_logic;
signal tim_read_timer_s : boolean;
signal tim_write_timer_s : boolean;
signal tim_start_t_s : boolean;
signal tim_start_cnt_s : boolean;
signal tim_stop_tcnt_s : boolean;
signal tim_data_s : word_t;
begin
-----------------------------------------------------------------------------
-- Check generics for valid values.
-----------------------------------------------------------------------------
-- pragma translate_off
assert include_timer_g = 0 or include_timer_g = 1
report "include_timer_g must be either 1 or 0!"
severity failure;
assert include_port1_g = 0 or include_port1_g = 1
report "include_port1_g must be either 1 or 0!"
severity failure;
assert include_port2_g = 0 or include_port2_g = 1
report "include_port2_g must be either 1 or 0!"
severity failure;
assert include_bus_g = 0 or include_bus_g = 1
report "include_bus_g must be either 1 or 0!"
severity failure;
-- pragma translate_on
en_clk_s <= to_boolean(en_clk_i);
alu_b : alu
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
data_o => alu_data_s,
write_accu_i => alu_write_accu_s,
write_shadow_i => alu_write_shadow_s,
write_temp_reg_i => alu_write_temp_reg_s,
read_alu_i => alu_read_alu_s,
carry_i => psw_carry_s,
carry_o => alu_carry_s,
aux_carry_o => alu_aux_carry_s,
alu_op_i => alu_op_s,
use_carry_i => alu_use_carry_s,
da_high_i => alu_da_high_s,
da_overflow_o => alu_da_overflow_s,
accu_low_i => alu_accu_low_s,
p06_temp_reg_i => alu_p06_temp_reg_s,
p60_temp_reg_i => alu_p60_temp_reg_s
);
bus_mux_b : bus_mux
port map (
alu_data_i => alu_data_s,
bus_data_i => bus_data_s,
dec_data_i => dec_data_s,
dm_data_i => dm_data_s,
pm_data_i => pm_data_s,
p1_data_i => p1_data_s,
p2_data_i => p2_data_s,
psw_data_i => psw_data_s,
tim_data_i => tim_data_s,
data_o => t48_data_s
);
clock_ctrl_b : clock_ctrl
generic map (
xtal_div_3_g => xtal_div_3_g
)
port map (
clk_i => clk_i,
xtal_i => xtal_i,
res_i => reset_i,
en_clk_i => en_clk_s,
xtal3_o => xtal3_s,
multi_cycle_i => clk_multi_cycle_s,
assert_psen_i => clk_assert_psen_s,
assert_prog_i => clk_assert_prog_s,
assert_rd_i => clk_assert_rd_s,
assert_wr_i => clk_assert_wr_s,
mstate_o => clk_mstate_s,
second_cycle_o => clk_second_cycle_s,
ale_o => ale_s,
psen_o => psen_s,
prog_o => prog_s,
rd_o => rd_s,
wr_o => wr_s
);
cond_branch_b : cond_branch
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
compute_take_i => cnd_compute_take_s,
branch_cond_i => cnd_branch_cond_s,
take_branch_o => cnd_take_branch_s,
accu_i => alu_data_s,
t0_i => To_X01Z(t0_i),
t1_i => To_X01Z(t1_i),
int_n_i => int_n_i,
f0_i => psw_f0_s,
f1_i => cnd_f1_s,
tf_i => cnd_tf_s,
carry_i => psw_carry_s,
comp_value_i => cnd_comp_value_s
);
use_db_bus: if include_bus_g = 1 generate
db_bus_b : db_bus
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
ea_i => ea_i,
data_i => t48_data_s,
data_o => bus_data_s,
write_bus_i => bus_write_bus_s,
read_bus_i => bus_read_bus_s,
output_pcl_i => bus_output_pcl_s,
bidir_bus_i => bus_bidir_bus_s,
pcl_i => pmem_addr_s(word_t'range),
db_i => db_i,
db_o => db_o,
db_dir_o => db_dir_o
);
end generate;
skip_db_bus: if include_bus_g = 0 generate
bus_data_s <= (others => bus_idle_level_c);
db_o <= (others => '0');
db_dir_o <= '0';
end generate;
decoder_b : decoder
generic map (
register_mnemonic_g => register_mnemonic_g
)
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
ea_i => ea_i,
ale_i => ale_s,
int_n_i => int_n_i,
t0_dir_o => t0_dir_o,
data_i => t48_data_s,
data_o => dec_data_s,
alu_write_accu_o => alu_write_accu_s,
alu_write_shadow_o => alu_write_shadow_s,
alu_write_temp_reg_o => alu_write_temp_reg_s,
alu_read_alu_o => alu_read_alu_s,
bus_write_bus_o => bus_write_bus_s,
bus_read_bus_o => bus_read_bus_s,
dm_write_dmem_addr_o => dm_write_dmem_addr_s,
dm_write_dmem_o => dm_write_dmem_s,
dm_read_dmem_o => dm_read_dmem_s,
p1_write_p1_o => p1_write_p1_s,
p1_read_p1_o => p1_read_p1_s,
pm_write_pcl_o => pm_write_pcl_s,
p2_write_p2_o => p2_write_p2_s,
p2_write_exp_o => p2_write_exp_s,
p2_read_p2_o => p2_read_p2_s,
pm_read_pcl_o => pm_read_pcl_s,
pm_write_pch_o => pm_write_pch_s,
pm_read_pch_o => pm_read_pch_s,
pm_read_pmem_o => pm_read_pmem_s,
psw_read_psw_o => psw_read_psw_s,
psw_read_sp_o => psw_read_sp_s,
psw_write_psw_o => psw_write_psw_s,
psw_write_sp_o => psw_write_sp_s,
alu_carry_i => alu_carry_s,
alu_op_o => alu_op_s,
alu_use_carry_o => alu_use_carry_s,
alu_da_high_o => alu_da_high_s,
alu_da_overflow_i => alu_da_overflow_s,
alu_accu_low_o => alu_accu_low_s,
alu_p06_temp_reg_o => alu_p06_temp_reg_s,
alu_p60_temp_reg_o => alu_p60_temp_reg_s,
bus_output_pcl_o => bus_output_pcl_s,
bus_bidir_bus_o => bus_bidir_bus_s,
clk_multi_cycle_o => clk_multi_cycle_s,
clk_assert_psen_o => clk_assert_psen_s,
clk_assert_prog_o => clk_assert_prog_s,
clk_assert_rd_o => clk_assert_rd_s,
clk_assert_wr_o => clk_assert_wr_s,
clk_mstate_i => clk_mstate_s,
clk_second_cycle_i => clk_second_cycle_s,
cnd_compute_take_o => cnd_compute_take_s,
cnd_branch_cond_o => cnd_branch_cond_s,
cnd_take_branch_i => cnd_take_branch_s,
cnd_comp_value_o => cnd_comp_value_s,
cnd_f1_o => cnd_f1_s,
cnd_tf_o => cnd_tf_s,
dm_addr_type_o => dm_addr_type_s,
tim_read_timer_o => tim_read_timer_s,
tim_write_timer_o => tim_write_timer_s,
tim_start_t_o => tim_start_t_s,
tim_start_cnt_o => tim_start_cnt_s,
tim_stop_tcnt_o => tim_stop_tcnt_s,
p1_read_reg_o => p1_read_reg_s,
p2_read_reg_o => p2_read_reg_s,
p2_read_exp_o => p2_read_exp_s,
p2_output_pch_o => p2_output_pch_s,
p2_output_exp_o => p2_output_exp_s,
pm_inc_pc_o => pm_inc_pc_s,
pm_write_pmem_addr_o => pm_write_pmem_addr_s,
pm_addr_type_o => pm_addr_type_s,
psw_special_data_o => psw_special_data_s,
psw_carry_i => psw_carry_s,
psw_aux_carry_i => psw_aux_carry_s,
psw_f0_i => psw_f0_s,
psw_inc_stackp_o => psw_inc_stackp_s,
psw_dec_stackp_o => psw_dec_stackp_s,
psw_write_carry_o => psw_write_carry_s,
psw_write_aux_carry_o => psw_write_aux_carry_s,
psw_write_f0_o => psw_write_f0_s,
psw_write_bs_o => psw_write_bs_s,
tim_overflow_i => tim_overflow_s
);
dmem_ctrl_b : dmem_ctrl
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
write_dmem_addr_i => dm_write_dmem_addr_s,
write_dmem_i => dm_write_dmem_s,
read_dmem_i => dm_read_dmem_s,
addr_type_i => dm_addr_type_s,
bank_select_i => psw_bs_s,
data_o => dm_data_s,
dmem_data_i => dmem_data_i,
dmem_addr_o => dmem_addr_o,
dmem_we_o => dmem_we_o,
dmem_data_o => dmem_data_o
);
use_timer: if include_timer_g = 1 generate
timer_b : timer
generic map (
sample_t1_state_g => sample_t1_state_g
)
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
t1_i => To_X01Z(t1_i),
clk_mstate_i => clk_mstate_s,
data_i => t48_data_s,
data_o => tim_data_s,
read_timer_i => tim_read_timer_s,
write_timer_i => tim_write_timer_s,
start_t_i => tim_start_t_s,
start_cnt_i => tim_start_cnt_s,
stop_tcnt_i => tim_stop_tcnt_s,
overflow_o => tim_of_s
);
end generate;
skip_timer: if include_timer_g = 0 generate
tim_data_s <= (others => bus_idle_level_c);
tim_of_s <= '0';
end generate;
tim_overflow_s <= to_boolean(tim_of_s);
use_p1: if include_port1_g = 1 generate
p1_b : p1
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
data_o => p1_data_s,
write_p1_i => p1_write_p1_s,
read_p1_i => p1_read_p1_s,
read_reg_i => p1_read_reg_s,
p1_i => p1_i,
p1_o => p1_o,
p1_low_imp_o => p1_low_imp_o
);
end generate;
skip_p1: if include_port1_g = 0 generate
p1_data_s <= (others => bus_idle_level_c);
p1_o <= (others => '0');
p1_low_imp_o <= '0';
end generate;
use_p2: if include_port2_g = 1 generate
p2_b : p2
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
data_o => p2_data_s,
write_p2_i => p2_write_p2_s,
write_exp_i => p2_write_exp_s,
read_p2_i => p2_read_p2_s,
read_reg_i => p2_read_reg_s,
read_exp_i => p2_read_exp_s,
output_pch_i => p2_output_pch_s,
output_exp_i => p2_output_exp_s,
pch_i => pmem_addr_s(11 downto 8),
p2_i => p2_i,
p2_o => p2_o,
p2_low_imp_o => p2_low_imp_o
);
end generate;
skip_p2: if include_port2_g = 0 generate
p2_data_s <= (others => bus_idle_level_c);
p2_o <= (others => '0');
p2_low_imp_o <= '0';
end generate;
pmem_ctrl_b : pmem_ctrl
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
data_o => pm_data_s,
write_pcl_i => pm_write_pcl_s,
read_pcl_i => pm_read_pcl_s,
write_pch_i => pm_write_pch_s,
read_pch_i => pm_read_pch_s,
inc_pc_i => pm_inc_pc_s,
write_pmem_addr_i => pm_write_pmem_addr_s,
addr_type_i => pm_addr_type_s,
read_pmem_i => pm_read_pmem_s,
pmem_addr_o => pmem_addr_s,
pmem_data_i => pmem_data_i
);
psw_b : psw
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
data_o => psw_data_s,
read_psw_i => psw_read_psw_s,
read_sp_i => psw_read_sp_s,
write_psw_i => psw_write_psw_s,
write_sp_i => psw_write_sp_s,
special_data_i => psw_special_data_s,
inc_stackp_i => psw_inc_stackp_s,
dec_stackp_i => psw_dec_stackp_s,
write_carry_i => psw_write_carry_s,
write_aux_carry_i => psw_write_aux_carry_s,
write_f0_i => psw_write_f0_s,
write_bs_i => psw_write_bs_s,
carry_o => psw_carry_s,
aux_carry_i => alu_aux_carry_s,
aux_carry_o => psw_aux_carry_s,
f0_o => psw_f0_s,
bs_o => psw_bs_s
);
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
ale_o <= to_stdLogic(ale_s);
t0_o <= clk_i;
psen_n_o <= to_stdLogic(not psen_s);
prog_n_o <= to_stdLogic(not prog_s);
rd_n_o <= to_stdLogic(not rd_s);
wr_n_o <= to_stdLogic(not wr_s);
xtal3_o <= to_stdLogic(xtal3_s);
pmem_addr_o <= pmem_addr_s;
end struct;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: t48_core.vhd,v $
-- Revision 1.7 2004/05/01 11:58:04 arniml
-- update notice about expander port instructions
--
-- Revision 1.6 2004/04/07 22:09:03 arniml
-- remove unused signals
--
-- Revision 1.5 2004/04/04 14:18:53 arniml
-- add measures to implement XCHD
--
-- Revision 1.4 2004/03/29 19:39:58 arniml
-- rename pX_limp to pX_low_imp
--
-- Revision 1.3 2004/03/28 21:27:50 arniml
-- update wiring for DA support
--
-- Revision 1.2 2004/03/28 13:13:20 arniml
-- connect control signal for Port 2 expander
--
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
-------------------------------------------------------------------------------

View File

@@ -1,87 +0,0 @@
-------------------------------------------------------------------------------
--
-- $Id: t48_core_comp_pack-p.vhd,v 1.2 2004/03/29 19:39:58 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
package t48_core_comp_pack is
component t48_core
generic (
xtal_div_3_g : integer := 1;
register_mnemonic_g : integer := 1;
include_port1_g : integer := 1;
include_port2_g : integer := 1;
include_bus_g : integer := 1;
include_timer_g : integer := 1;
sample_t1_state_g : integer := 4
);
port (
xtal_i : in std_logic;
reset_i : in std_logic;
t0_i : in std_logic;
t0_o : out std_logic;
t0_dir_o : out std_logic;
int_n_i : in std_logic;
ea_i : in std_logic;
rd_n_o : out std_logic;
psen_n_o : out std_logic;
wr_n_o : out std_logic;
ale_o : out std_logic;
db_i : in std_logic_vector( 7 downto 0);
db_o : out std_logic_vector( 7 downto 0);
db_dir_o : out std_logic;
t1_i : in std_logic;
p2_i : in std_logic_vector( 7 downto 0);
p2_o : out std_logic_vector( 7 downto 0);
p2_low_imp_o : out std_logic;
p1_i : in std_logic_vector( 7 downto 0);
p1_o : out std_logic_vector( 7 downto 0);
p1_low_imp_o : out std_logic;
prog_n_o : out std_logic;
clk_i : in std_logic;
en_clk_i : in std_logic;
xtal3_o : out std_logic;
dmem_addr_o : out std_logic_vector( 7 downto 0);
dmem_we_o : out std_logic;
dmem_data_i : in std_logic_vector( 7 downto 0);
dmem_data_o : out std_logic_vector( 7 downto 0);
pmem_addr_o : out std_logic_vector(11 downto 0);
pmem_data_i : in std_logic_vector( 7 downto 0)
);
end component;
component syn_rom
generic (
address_width_g : positive := 10
);
port (
clk_i : in std_logic;
rom_addr_i : in std_logic_vector(address_width_g-1 downto 0);
rom_data_o : out std_logic_vector(7 downto 0)
);
end component;
component syn_ram
generic (
address_width_g : positive := 8
);
port (
clk_i : in std_logic;
res_i : in std_logic;
ram_addr_i : in std_logic_vector(address_width_g-1 downto 0);
ram_data_i : in std_logic_vector(7 downto 0);
ram_we_i : in std_logic;
ram_data_o : out std_logic_vector(7 downto 0)
);
end component;
end t48_core_comp_pack;

View File

@@ -1,82 +0,0 @@
-------------------------------------------------------------------------------
--
-- $Id: t48_pack-p.vhd,v 1.1 2004/03/23 21:31:53 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
package t48_pack is
-----------------------------------------------------------------------------
-- Global constants
-----------------------------------------------------------------------------
-- clock active level
constant clk_active_c : std_logic := '1';
-- reset active level
constant res_active_c : std_logic := '0';
-- idle level on internal data bus
constant bus_idle_level_c : std_logic := '1';
-- global data word width
constant word_width_c : natural := 8;
-- data memory address width
constant dmem_addr_width_c : natural := 8;
-- program memory address width
constant pmem_addr_width_c : natural := 12;
-----------------------------------------------------------------------------
-- Global data types
-----------------------------------------------------------------------------
-- the global data word width type
subtype word_t is std_logic_vector(word_width_c-1 downto 0);
subtype nibble_t is std_logic_vector(word_width_c/2-1 downto 0);
-- the global data memory address type
subtype dmem_addr_t is std_logic_vector(dmem_addr_width_c-1 downto 0);
-- the global program memory address type
subtype pmem_addr_t is std_logic_vector(pmem_addr_width_c-1 downto 0);
subtype page_t is std_logic_vector(pmem_addr_width_c-1 downto word_width_c);
-- the machine states
type mstate_t is (MSTATE1, MSTATE2, MSTATE3, MSTATE4, MSTATE5);
-----------------------------------------------------------------------------
-- Global functions
-----------------------------------------------------------------------------
function to_stdLogic(input: boolean) return std_logic;
function to_boolean(input: std_logic) return boolean;
end t48_pack;
package body t48_pack is
function to_stdLogic(input: boolean) return std_logic is
begin
if input then
return '1';
else
return '0';
end if;
end to_stdLogic;
function to_boolean(input: std_logic) return boolean is
begin
if input = '1' then
return true;
else
return false;
end if;
end to_boolean;
end t48_pack;

View File

@@ -1,278 +0,0 @@
-------------------------------------------------------------------------------
--
-- The Timer/Counter unit.
--
-- $Id: timer.vhd,v 1.5 2004/07/11 16:51:33 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.t48_pack.word_t;
use work.t48_pack.mstate_t;
entity timer is
generic (
-- state in which T1 is sampled (3 or 4)
sample_t1_state_g : integer := 4
);
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
t1_i : in std_logic;
clk_mstate_i : in mstate_t;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
read_timer_i : in boolean;
write_timer_i : in boolean;
-- Decoder Interface ------------------------------------------------------
start_t_i : in boolean;
start_cnt_i : in boolean;
stop_tcnt_i : in boolean;
overflow_o : out std_logic
);
end timer;
library ieee;
use ieee.numeric_std.all;
use work.t48_pack.all;
architecture rtl of timer is
-- the 8 bit counter core
signal counter_q : unsigned(word_t'range);
signal overflow_q : boolean;
-- increment signal for the counter core
type inc_type_t is (NONE, TIMER, COUNTER);
signal increment_s : boolean;
signal inc_sel_q : inc_type_t;
-- T1 edge detector
signal t1_q : std_logic;
signal t1_inc_s : boolean;
-- timer prescaler
signal prescaler_q : unsigned(4 downto 0);
signal pre_inc_s : boolean;
begin
-----------------------------------------------------------------------------
-- Verify the generics
-----------------------------------------------------------------------------
-- pragma translate_off
assert (sample_t1_state_g = 3) or (sample_t1_state_g = 4)
report "sample_t1_state_g must be either 3 or 4!"
severity failure;
-- pragma translate_on
-----------------------------------------------------------------------------
-- Process t1_edge
--
-- Purpose:
-- Implements the edge detector for T1.
--
t1_edge: process (t1_i,
t1_q,
clk_mstate_i)
begin
t1_inc_s <= false;
-- sample in state according to generic
-- Old devices: sample at the beginning of state 3
-- New devices: sample in state 4
if (sample_t1_state_g = 3 and clk_mstate_i = MSTATE3) or
(sample_t1_state_g = 4 and clk_mstate_i = MSTATE4) then
-- detect falling edge
if t1_q = '1' and t1_i = '0' then
t1_inc_s <= true;
end if;
end if;
end process t1_edge;
--
-----------------------------------------------------------------------------
pre_inc_s <= clk_mstate_i = MSTATE4 and prescaler_q = 31;
-----------------------------------------------------------------------------
-- Process inc_sel
--
-- Purpose:
-- Select increment source (timer, counter or none).
--
inc_sel: process (inc_sel_q,
pre_inc_s,
t1_inc_s)
begin
-- default assignment
increment_s <= false;
case inc_sel_q is
when NONE =>
increment_s <= false;
when TIMER =>
increment_s <= pre_inc_s;
when COUNTER =>
increment_s <= t1_inc_s;
when others =>
null;
end case;
end process inc_sel;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process regs
--
-- Purpose:
-- Implements the counter, the prescaler and other registers.
--
regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
overflow_q <= false;
t1_q <= '0';
prescaler_q <= (others => '0');
inc_sel_q <= NONE;
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
-- Counter Core and overflow ------------------------------------------
overflow_q <= false;
if write_timer_i then
counter_q <= unsigned(data_i);
elsif increment_s then
counter_q <= counter_q + 1;
if counter_q = 255 then
overflow_q <= true;
end if;
end if;
-- T1 edge detector ---------------------------------------------------
if (sample_t1_state_g = 3 and clk_mstate_i = MSTATE3) or
(sample_t1_state_g = 4 and clk_mstate_i = MSTATE4) then
t1_q <= t1_i;
end if;
-- Prescaler ----------------------------------------------------------
if start_t_i then
prescaler_q <= (others => '0');
elsif clk_mstate_i = MSTATE3 then
prescaler_q <= prescaler_q + 1;
end if;
-- Increment Selector -------------------------------------------------
if start_t_i then
inc_sel_q <= TIMER;
elsif start_cnt_i then
inc_sel_q <= COUNTER;
elsif stop_tcnt_i then
inc_sel_q <= NONE;
end if;
end if;
end if;
end process regs;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
data_o <= std_logic_vector(counter_q)
when read_timer_i else
(others => bus_idle_level_c);
overflow_o <= to_stdLogic(overflow_q);
end rtl;
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: timer.vhd,v $
-- Revision 1.5 2004/07/11 16:51:33 arniml
-- cleanup copyright notice
--
-- Revision 1.4 2004/07/04 13:06:45 arniml
-- counter_q is not cleared during reset
-- this would match all different descriptions of the Counter as
-- a) if the software assumes that the Counter is modified during reset, it
-- will initialize the Counter anyhow
-- b) the special case 'Counter not modified during reset' is covered
--
-- Revision 1.3 2004/05/16 15:32:57 arniml
-- fix edge detector bug for counter
--
-- Revision 1.2 2004/04/15 22:05:13 arniml
-- increment prescaler with MSTATE4
--
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------

View File

@@ -1,371 +0,0 @@
-------------------------------------------------------------------------------
--
-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-------------------------------------------------------------------------------
--
-- Emulacao memoria dual-port para SDRAMs
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity dpSDRAM16Mb is
generic (
freq_g : integer := 100
);
port (
clock_i : in std_logic;
reset_i : in std_logic;
refresh_i : in std_logic := '1';
-- Porta 0
port0_cs_i : in std_logic;
port0_oe_i : in std_logic;
port0_we_i : in std_logic;
port0_addr_i : in std_logic_vector(20 downto 0);
port0_data_i : in std_logic_vector( 7 downto 0);
port0_data_o : out std_logic_vector( 7 downto 0);
-- Porta 1
port1_cs_i : in std_logic;
port1_oe_i : in std_logic;
port1_we_i : in std_logic;
port1_addr_i : in std_logic_vector(20 downto 0);
port1_data_i : in std_logic_vector( 7 downto 0);
port1_data_o : out std_logic_vector( 7 downto 0);
-- SD-RAM ports
mem_cke_o : out std_logic;
mem_cs_n_o : out std_logic;
mem_ras_n_o : out std_logic;
mem_cas_n_o : out std_logic;
mem_we_n_o : out std_logic;
mem_udq_o : out std_logic;
mem_ldq_o : out std_logic;
mem_ba_o : out std_logic;
mem_addr_o : out std_logic_vector(10 downto 0);
mem_data_io : inout std_logic_vector(15 downto 0)
);
end entity;
architecture Behavior of dpSDRAM16Mb is
constant SdrCmd_de_c : std_logic_vector(3 downto 0) := "1111"; -- deselect
constant SdrCmd_xx_c : std_logic_vector(3 downto 0) := "0111"; -- no operation
constant SdrCmd_rd_c : std_logic_vector(3 downto 0) := "0101"; -- read
constant SdrCmd_wr_c : std_logic_vector(3 downto 0) := "0100"; -- write
constant SdrCmd_ac_c : std_logic_vector(3 downto 0) := "0011"; -- activate
constant SdrCmd_pr_c : std_logic_vector(3 downto 0) := "0010"; -- precharge all
constant SdrCmd_re_c : std_logic_vector(3 downto 0) := "0001"; -- refresh
constant SdrCmd_ms_c : std_logic_vector(3 downto 0) := "0000"; -- mode regiser set
-- SD-RAM control signals
signal SdrCmd_s : std_logic_vector(3 downto 0);
signal SdrBa_s : std_logic;
signal SdrUdq_s : std_logic;
signal SdrLdq_s : std_logic;
signal SdrAdr_s : std_logic_vector(10 downto 0);
signal SdrDat_s : std_logic_vector(15 downto 0);
signal ram0_req_s : std_logic;
signal ram0_ack_s : std_logic;
signal ram0_addr_s : std_logic_vector(20 downto 0);
signal ram0_din_s : std_logic_vector( 7 downto 0);
signal ram0_dout_s : std_logic_vector( 7 downto 0);
signal ram0_we_s : std_logic;
signal ram1_req_s : std_logic;
signal ram1_ack_s : std_logic;
signal ram1_addr_s : std_logic_vector(20 downto 0);
signal ram1_din_s : std_logic_vector( 7 downto 0);
signal ram1_dout_s : std_logic_vector( 7 downto 0);
signal ram1_we_s : std_logic;
begin
-- Detectar pedido na porta 0
process (reset_i, clock_i)
variable pcs_v : std_logic_vector(1 downto 0);
variable acesso_v : std_logic;
begin
if reset_i = '1' then
port0_data_o <= (others => '1');
ram0_we_s <= '0';
ram0_req_s <= '0';
pcs_v := "00";
elsif rising_edge(clock_i) then
if ram0_req_s = '1' and ram0_ack_s = '1' then
if ram0_we_s = '0' then
port0_data_o <= ram0_dout_s;
end if;
ram0_req_s <= '0';
end if;
if pcs_v = "01" then
ram0_addr_s <= port0_addr_i;
ram0_req_s <= '1';
if port0_we_i = '1' then
ram0_din_s <= port0_data_i;
ram0_we_s <= '1';
else
ram0_we_s <= '0';
end if;
end if;
acesso_v := port0_cs_i and (port0_oe_i or port0_we_i);
pcs_v := pcs_v(0) & acesso_v;
end if;
end process;
-- Detectar pedido na porta 1
process (reset_i, clock_i)
variable pcs_v : std_logic_vector(1 downto 0);
variable acesso_v : std_logic;
begin
if reset_i = '1' then
port1_data_o <= (others => '1');
ram1_we_s <= '0';
ram1_req_s <= '0';
pcs_v := "00";
elsif rising_edge(clock_i) then
if ram1_req_s = '1' and ram1_ack_s = '1' then
if ram1_we_s = '0' then
port1_data_o <= ram1_dout_s;
end if;
ram1_req_s <= '0';
end if;
if pcs_v = "01" then
ram1_addr_s <= port1_addr_i;
ram1_req_s <= '1';
if port1_we_i = '1' then
ram1_din_s <= port1_data_i;
ram1_we_s <= '1';
else
ram1_we_s <= '0';
end if;
end if;
acesso_v := port1_cs_i and (port1_oe_i or port1_we_i);
pcs_v := pcs_v(0) & acesso_v;
end if;
end process;
----------------------------
process (clock_i)
type typSdrRoutine_t is ( SdrRoutine_Null, SdrRoutine_Init, SdrRoutine_Idle, SdrRoutine_RefreshAll, SdrRoutine_ReadOne, SdrRoutine_WriteOne );
variable SdrRoutine_v : typSdrRoutine_t := SdrRoutine_Null;
variable SdrRoutineSeq_v : unsigned( 7 downto 0) := X"00";
variable refreshDelayCounter_v : unsigned(23 downto 0) := x"000000";
variable SdrRefreshCounter_v : unsigned(15 downto 0) := X"0000";
variable SdrPort_v : std_logic := '0';
variable SdrAddress_v : std_logic_vector(20 downto 0);
begin
if rising_edge(clock_i) then
ram0_ack_s <= '0';
ram1_ack_s <= '0';
case SdrRoutine_v is
when SdrRoutine_Null =>
SdrCmd_s <= SdrCmd_xx_c;
SdrDat_s <= (others => 'Z');
if refreshDelayCounter_v = 0 then
SdrRoutine_v := SdrRoutine_Init;
end if;
when SdrRoutine_Init =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_pr_c;
SdrAdr_s <= (others => '1');
SdrBa_s <= '0';
SdrUdq_s <= '1';
SdrLdq_s <= '1';
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"04" or SdrRoutineSeq_v = X"0C" then
SdrCmd_s <= SdrCmd_re_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"14" then
SdrCmd_s <= SdrCmd_ms_c;
SdrAdr_s <= "0000" & "010" & "0" & "000"; -- CAS Latency=2, WT=0(seq), BL=1
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"17" then
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
when SdrRoutine_Idle =>
SdrCmd_s <= SdrCmd_xx_c;
SdrDat_s <= (others => 'Z');
if ram0_req_s = '1' and ram0_ack_s = '0' then
SdrPort_v := '0';
SdrAddress_v := ram0_addr_s;
if ram0_we_s = '1' then
SdrRoutine_v := SdrRoutine_WriteOne;
else
SdrRoutine_v := SdrRoutine_ReadOne;
end if;
elsif ram1_req_s = '1' and ram1_ack_s = '0' then
SdrPort_v := '1';
SdrAddress_v := ram1_addr_s;
if ram1_we_s = '1' then
SdrRoutine_v := SdrRoutine_WriteOne;
else
SdrRoutine_v := SdrRoutine_ReadOne;
end if;
elsif SdrRefreshCounter_v < 2048 and refresh_i = '1' then
SdrRoutine_v := SdrRoutine_RefreshAll;
SdrRefreshCounter_v := SdrRefreshCounter_v + 1;
end if;
when SdrRoutine_RefreshAll =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_re_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"06" then
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
when SdrRoutine_ReadOne =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_ac_c;
SdrBa_s <= SdrAddress_v(20);
SdrAdr_s <= SdrAddress_v(19 downto 9); -- Row (11 bits)
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"02" then
SdrCmd_s <= SdrCmd_rd_c;
SdrAdr_s(10 downto 8) <= "100"; -- A10 = '1' => Auto Pre-charge
SdrAdr_s(7 downto 0) <= SdrAddress_v(8 downto 1); -- Col (8 bits)
SdrUdq_s <= '0';
SdrLdq_s <= '0';
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"05" then
if SdrPort_v = '0' then
if SdrAddress_v(0) = '0' then
ram0_dout_s <= mem_data_io(7 downto 0);
else
ram0_dout_s <= mem_data_io(15 downto 8);
end if;
ram0_ack_s <= '1';
else
if SdrAddress_v(0) = '0' then
ram1_dout_s <= mem_data_io(7 downto 0);
else
ram1_dout_s <= mem_data_io(15 downto 8);
end if;
ram1_ack_s <= '1';
end if;
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"06" then
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
when SdrRoutine_WriteOne =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_ac_c;
SdrBa_s <= SdrAddress_v(20);
SdrAdr_s <= SdrAddress_v(19 downto 9);
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"02" then
SdrCmd_s <= SdrCmd_wr_c;
SdrAdr_s(10 downto 8) <= "100"; -- A10 = '1' => Auto Pre-charge
SdrAdr_s(7 downto 0) <= SdrAddress_v(8 downto 1);
SdrUdq_s <= not SdrAddress_v(0);
SdrLdq_s <= SdrAddress_v(0);
if SdrPort_v = '0' then
SdrDat_s <= ram0_din_s & ram0_din_s;
else
SdrDat_s <= ram1_din_s & ram1_din_s;
end if;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"03" then
if SdrPort_v = '0' then
ram0_ack_s <= '1';
else
ram1_ack_s <= '1';
end if;
SdrCmd_s <= SdrCmd_xx_c;
SdrDat_s <= (others => 'Z');
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"05" then
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
end case;
refreshDelayCounter_v := refreshDelayCounter_v + 1;
if refreshDelayCounter_v >= ( freq_g * 1000 * 32 ) then
refreshDelayCounter_v := x"000000";
SdrRefreshCounter_v := x"0000";
end if;
end if;
end process;
mem_cke_o <= '1';
mem_cs_n_o <= SdrCmd_s(3);
mem_ras_n_o <= SdrCmd_s(2);
mem_cas_n_o <= SdrCmd_s(1);
mem_we_n_o <= SdrCmd_s(0);
mem_udq_o <= SdrUdq_s;
mem_ldq_o <= SdrLdq_s;
mem_ba_o <= SdrBa_s;
mem_addr_o <= SdrAdr_s;
mem_data_io <= SdrDat_s;
end architecture;

View File

@@ -1,373 +0,0 @@
-------------------------------------------------------------------------------
--
-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-------------------------------------------------------------------------------
--
-- Emulacao memoria dual-port para SDRAMs
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity dpSDRAM256Mb is
generic (
freq_g : integer := 100
);
port (
clock_i : in std_logic;
reset_i : in std_logic;
refresh_i : in std_logic := '1';
-- Port 0
port0_cs_i : in std_logic;
port0_oe_i : in std_logic;
port0_we_i : in std_logic;
port0_addr_i : in std_logic_vector(24 downto 0);
port0_data_i : in std_logic_vector( 7 downto 0);
port0_data_o : out std_logic_vector( 7 downto 0);
-- Port 1
port1_cs_i : in std_logic;
port1_oe_i : in std_logic;
port1_we_i : in std_logic;
port1_addr_i : in std_logic_vector(24 downto 0);
port1_data_i : in std_logic_vector( 7 downto 0);
port1_data_o : out std_logic_vector( 7 downto 0);
-- SDRAM in board
mem_cke_o : out std_logic;
mem_cs_n_o : out std_logic;
mem_ras_n_o : out std_logic;
mem_cas_n_o : out std_logic;
mem_we_n_o : out std_logic;
mem_udq_o : out std_logic;
mem_ldq_o : out std_logic;
mem_ba_o : out std_logic_vector( 1 downto 0);
mem_addr_o : out std_logic_vector(12 downto 0);
mem_data_io : inout std_logic_vector(15 downto 0)
);
end entity;
architecture Behavior of dpSDRAM256Mb is
constant SdrCmd_de_c : std_logic_vector(3 downto 0) := "1111"; -- deselect
constant SdrCmd_xx_c : std_logic_vector(3 downto 0) := "0111"; -- no operation
constant SdrCmd_rd_c : std_logic_vector(3 downto 0) := "0101"; -- read
constant SdrCmd_wr_c : std_logic_vector(3 downto 0) := "0100"; -- write
constant SdrCmd_ac_c : std_logic_vector(3 downto 0) := "0011"; -- activate
constant SdrCmd_pr_c : std_logic_vector(3 downto 0) := "0010"; -- precharge all
constant SdrCmd_re_c : std_logic_vector(3 downto 0) := "0001"; -- refresh
constant SdrCmd_ms_c : std_logic_vector(3 downto 0) := "0000"; -- mode regiser set
-- SD-RAM control signals
signal SdrCmd_s : std_logic_vector(3 downto 0);
signal SdrBa_s : std_logic_vector(1 downto 0);
signal SdrUdq_s : std_logic;
signal SdrLdq_s : std_logic;
signal SdrAdr_s : std_logic_vector(12 downto 0);
signal SdrDat_s : std_logic_vector(15 downto 0);
signal ram0_req_s : std_logic;
signal ram0_ack_s : std_logic;
signal ram0_addr_s : std_logic_vector(24 downto 0);
signal ram0_din_s : std_logic_vector( 7 downto 0);
signal ram0_dout_s : std_logic_vector( 7 downto 0);
signal ram0_we_s : std_logic;
signal ram1_req_s : std_logic;
signal ram1_ack_s : std_logic;
signal ram1_addr_s : std_logic_vector(24 downto 0);
signal ram1_din_s : std_logic_vector( 7 downto 0);
signal ram1_dout_s : std_logic_vector( 7 downto 0);
signal ram1_we_s : std_logic;
begin
-- Detectar pedido na porta 0
process (reset_i, clock_i)
variable pcs_v : std_logic_vector(1 downto 0);
variable acesso_v : std_logic;
begin
if reset_i = '1' then
port0_data_o <= (others => '1');
ram0_we_s <= '0';
ram0_req_s <= '0';
pcs_v := "00";
elsif rising_edge(clock_i) then
if ram0_req_s = '1' and ram0_ack_s = '1' then
if ram0_we_s = '0' then
port0_data_o <= ram0_dout_s;
end if;
ram0_req_s <= '0';
end if;
if pcs_v = "01" then
ram0_addr_s <= port0_addr_i;
ram0_req_s <= '1';
if port0_we_i = '1' then
ram0_din_s <= port0_data_i;
ram0_we_s <= '1';
else
ram0_we_s <= '0';
end if;
end if;
acesso_v := port0_cs_i and (port0_oe_i or port0_we_i);
pcs_v := pcs_v(0) & acesso_v;
end if;
end process;
-- Detectar pedido na porta 1
process (reset_i, clock_i)
variable pcs_v : std_logic_vector(1 downto 0);
variable acesso_v : std_logic;
begin
if reset_i = '1' then
port1_data_o <= (others => '1');
ram1_we_s <= '0';
ram1_req_s <= '0';
pcs_v := "00";
elsif rising_edge(clock_i) then
if ram1_req_s = '1' and ram1_ack_s = '1' then
if ram1_we_s = '0' then
port1_data_o <= ram1_dout_s;
end if;
ram1_req_s <= '0';
end if;
if pcs_v = "01" then
ram1_addr_s <= port1_addr_i;
ram1_req_s <= '1';
if port1_we_i = '1' then
ram1_din_s <= port1_data_i;
ram1_we_s <= '1';
else
ram1_we_s <= '0';
end if;
end if;
acesso_v := port1_cs_i and (port1_oe_i or port1_we_i);
pcs_v := pcs_v(0) & acesso_v;
end if;
end process;
----------------------------
process (clock_i)
type typSdrRoutine_t is ( SdrRoutine_Null, SdrRoutine_Init, SdrRoutine_Idle, SdrRoutine_RefreshAll, SdrRoutine_ReadOne, SdrRoutine_WriteOne );
variable SdrRoutine_v : typSdrRoutine_t := SdrRoutine_Null;
variable SdrRoutineSeq_v : unsigned(7 downto 0) := X"00";
variable refreshDelayCounter_v : unsigned(23 downto 0) := x"000000";
variable SdrRefreshCounter_v : unsigned(15 downto 0) := X"0000";
variable SdrPort_v : std_logic := '0';
variable SdrAddress_v : std_logic_vector(24 downto 0);
begin
if rising_edge(clock_i) then
ram0_ack_s <= '0';
ram1_ack_s <= '0';
case SdrRoutine_v is
when SdrRoutine_Null =>
SdrCmd_s <= SdrCmd_xx_c;
SdrDat_s <= (others => 'Z');
if refreshDelayCounter_v = 0 then
SdrRoutine_v := SdrRoutine_Init;
end if;
when SdrRoutine_Init =>
if SdrRoutineSeq_v = X"0" then
SdrCmd_s <= SdrCmd_pr_c;
SdrAdr_s <= (others => '1');
SdrBa_s <= "00";
SdrUdq_s <= '1';
SdrLdq_s <= '1';
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"04" or SdrRoutineSeq_v = X"0C" then
SdrCmd_s <= SdrCmd_re_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"14" then
SdrCmd_s <= SdrCmd_ms_c;
SdrAdr_s <= "000" & "1" & "00" & "010" & "0" & "000"; -- Single, Standard, CAS Latency=2, WT=0(seq), BL=1
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"17" then
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
when SdrRoutine_Idle =>
SdrCmd_s <= SdrCmd_xx_c;
SdrDat_s <= (others => 'Z');
if ram0_req_s = '1' and ram0_ack_s = '0' then
SdrPort_v := '0';
SdrAddress_v := ram0_addr_s;
if ram0_we_s = '1' then
SdrRoutine_v := SdrRoutine_WriteOne;
else
SdrRoutine_v := SdrRoutine_ReadOne;
end if;
elsif ram1_req_s = '1' and ram1_ack_s = '0' then
SdrPort_v := '1';
SdrAddress_v := ram1_addr_s;
if ram1_we_s = '1' then
SdrRoutine_v := SdrRoutine_WriteOne;
else
SdrRoutine_v := SdrRoutine_ReadOne;
end if;
elsif SdrRefreshCounter_v < 8192 and refresh_i = '1' then
SdrRoutine_v := SdrRoutine_RefreshAll;
SdrRefreshCounter_v := SdrRefreshCounter_v + 1;
end if;
when SdrRoutine_RefreshAll =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_re_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"06" then
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
when SdrRoutine_ReadOne =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_ac_c;
SdrBa_s <= SdrAddress_v(24 downto 23);
SdrAdr_s <= SdrAddress_v(22 downto 10); -- Row (13 bits)
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"02" then
SdrCmd_s <= SdrCmd_rd_c;
SdrAdr_s(12 downto 9) <= "0010"; -- A10 = '1' => Auto Pre-charge
SdrAdr_s(8 downto 0) <= SdrAddress_v(9 downto 1);
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
SdrUdq_s <= '0';
SdrLdq_s <= '0';
elsif SdrRoutineSeq_v = X"05" then
if SdrPort_v = '0' then
if SdrAddress_v(0) = '0' then
ram0_dout_s <= mem_data_io(7 downto 0);
else
ram0_dout_s <= mem_data_io(15 downto 8);
end if;
ram0_ack_s <= '1';
else
if SdrAddress_v(0) = '0' then
ram1_dout_s <= mem_data_io(7 downto 0);
else
ram1_dout_s <= mem_data_io(15 downto 8);
end if;
ram1_ack_s <= '1';
end if;
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"06" then
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
when SdrRoutine_WriteOne =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_ac_c;
SdrBa_s <= SdrAddress_v(24 downto 23);
SdrAdr_s <= SdrAddress_v(22 downto 10);
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"02" then
SdrCmd_s <= SdrCmd_wr_c;
SdrAdr_s(12 downto 9) <= "0010"; -- A10 = '1' => Auto Pre-charge
SdrAdr_s(8 downto 0) <= SdrAddress_v(9 downto 1);
SdrUdq_s <= not SdrAddress_v(0);
SdrLdq_s <= SdrAddress_v(0);
if SdrPort_v = '0' then
SdrDat_s <= ram0_din_s & ram0_din_s;
else
SdrDat_s <= ram1_din_s & ram1_din_s;
end if;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"03" then
if SdrPort_v = '0' then
ram0_ack_s <= '1';
else
ram1_ack_s <= '1';
end if;
SdrCmd_s <= SdrCmd_xx_c;
SdrDat_s <= (others => 'Z');
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"05" then
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
end case;
refreshDelayCounter_v := refreshDelayCounter_v + 1;
if refreshDelayCounter_v >= ( freq_g * 1000 * 64 ) then
refreshDelayCounter_v := x"000000";
SdrRefreshCounter_v := x"0000";
end if;
end if;
end process;
mem_cke_o <= '1';
mem_cs_n_o <= SdrCmd_s(3);
mem_ras_n_o <= SdrCmd_s(2);
mem_cas_n_o <= SdrCmd_s(1);
mem_we_n_o <= SdrCmd_s(0);
mem_udq_o <= SdrUdq_s;
mem_ldq_o <= SdrLdq_s;
mem_ba_o <= SdrBa_s;
mem_addr_o <= SdrAdr_s;
mem_data_io <= SdrDat_s;
end architecture;

View File

@@ -1,371 +0,0 @@
-------------------------------------------------------------------------------
--
-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-------------------------------------------------------------------------------
--
-- SDRAM dual-port emulation
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity dpSDRAM64Mb is
generic (
freq_g : integer := 100
);
port (
clock_i : in std_logic;
reset_i : in std_logic;
refresh_i : in std_logic := '1';
-- Port 0
port0_cs_i : in std_logic;
port0_oe_i : in std_logic;
port0_we_i : in std_logic;
port0_addr_i : in std_logic_vector(22 downto 0);
port0_data_i : in std_logic_vector( 7 downto 0);
port0_data_o : out std_logic_vector( 7 downto 0);
-- Port 1
port1_cs_i : in std_logic;
port1_oe_i : in std_logic;
port1_we_i : in std_logic;
port1_addr_i : in std_logic_vector(22 downto 0);
port1_data_i : in std_logic_vector( 7 downto 0);
port1_data_o : out std_logic_vector( 7 downto 0);
-- SDRAM in board
mem_cke_o : out std_logic;
mem_cs_n_o : out std_logic;
mem_ras_n_o : out std_logic;
mem_cas_n_o : out std_logic;
mem_we_n_o : out std_logic;
mem_udq_o : out std_logic;
mem_ldq_o : out std_logic;
mem_ba_o : out std_logic_vector( 1 downto 0);
mem_addr_o : out std_logic_vector(11 downto 0);
mem_data_io : inout std_logic_vector(15 downto 0)
);
end entity;
architecture Behavior of dpSDRAM64Mb is
constant SdrCmd_de_c : std_logic_vector(3 downto 0) := "1111"; -- deselect
constant SdrCmd_xx_c : std_logic_vector(3 downto 0) := "0111"; -- no operation
constant SdrCmd_rd_c : std_logic_vector(3 downto 0) := "0101"; -- read
constant SdrCmd_wr_c : std_logic_vector(3 downto 0) := "0100"; -- write
constant SdrCmd_ac_c : std_logic_vector(3 downto 0) := "0011"; -- activate
constant SdrCmd_pr_c : std_logic_vector(3 downto 0) := "0010"; -- precharge all
constant SdrCmd_re_c : std_logic_vector(3 downto 0) := "0001"; -- refresh
constant SdrCmd_ms_c : std_logic_vector(3 downto 0) := "0000"; -- mode regiser set
-- SD-RAM control signals
signal SdrCmd_s : std_logic_vector(3 downto 0);
signal SdrBa_s : std_logic_vector(1 downto 0);
signal SdrUdq_s : std_logic;
signal SdrLdq_s : std_logic;
signal SdrAdr_s : std_logic_vector(11 downto 0);
signal SdrDat_s : std_logic_vector(15 downto 0);
signal ram0_req_s : std_logic;
signal ram0_ack_s : std_logic;
signal ram0_addr_s : std_logic_vector(22 downto 0);
signal ram0_din_s : std_logic_vector( 7 downto 0);
signal ram0_dout_s : std_logic_vector( 7 downto 0);
signal ram0_we_s : std_logic;
signal ram1_req_s : std_logic;
signal ram1_ack_s : std_logic;
signal ram1_addr_s : std_logic_vector(22 downto 0);
signal ram1_din_s : std_logic_vector( 7 downto 0);
signal ram1_dout_s : std_logic_vector( 7 downto 0);
signal ram1_we_s : std_logic;
begin
-- Detectar pedido na porta 0
process (reset_i, clock_i)
variable pcs_v : std_logic_vector(1 downto 0);
variable acesso_v : std_logic;
begin
if reset_i = '1' then
port0_data_o <= (others => '1');
ram0_we_s <= '0';
ram0_req_s <= '0';
pcs_v := "00";
elsif rising_edge(clock_i) then
if ram0_req_s = '1' and ram0_ack_s = '1' then
if ram0_we_s = '0' then
port0_data_o <= ram0_dout_s;
end if;
ram0_req_s <= '0';
end if;
if pcs_v = "01" then
ram0_addr_s <= port0_addr_i;
ram0_req_s <= '1';
if port0_we_i = '1' then
ram0_din_s <= port0_data_i;
ram0_we_s <= '1';
else
ram0_we_s <= '0';
end if;
end if;
acesso_v := port0_cs_i and (port0_oe_i or port0_we_i);
pcs_v := pcs_v(0) & acesso_v;
end if;
end process;
-- Detectar pedido na porta 1
process (reset_i, clock_i)
variable pcs_v : std_logic_vector(1 downto 0);
variable acesso_v : std_logic;
begin
if reset_i = '1' then
port1_data_o <= (others => '1');
ram1_we_s <= '0';
ram1_req_s <= '0';
pcs_v := "00";
elsif rising_edge(clock_i) then
if ram1_req_s = '1' and ram1_ack_s = '1' then
if ram1_we_s = '0' then
port1_data_o <= ram1_dout_s;
end if;
ram1_req_s <= '0';
end if;
if pcs_v = "01" then
ram1_addr_s <= port1_addr_i;
ram1_req_s <= '1';
if port1_we_i = '1' then
ram1_din_s <= port1_data_i;
ram1_we_s <= '1';
else
ram1_we_s <= '0';
end if;
end if;
acesso_v := port1_cs_i and (port1_oe_i or port1_we_i);
pcs_v := pcs_v(0) & acesso_v;
end if;
end process;
----------------------------
process (clock_i)
type typSdrRoutine_t is ( SdrRoutine_Null, SdrRoutine_Init, SdrRoutine_Idle, SdrRoutine_RefreshAll, SdrRoutine_ReadOne, SdrRoutine_WriteOne );
variable SdrRoutine_v : typSdrRoutine_t := SdrRoutine_Null;
variable SdrRoutineSeq_v : unsigned( 7 downto 0) := X"00";
variable refreshDelayCounter_v : unsigned(23 downto 0) := x"000000";
variable SdrRefreshCounter_v : unsigned(15 downto 0) := X"0000";
variable SdrPort_v : std_logic := '0';
variable SdrAddress_v : std_logic_vector(22 downto 0);
begin
if rising_edge(clock_i) then
ram0_ack_s <= '0';
ram1_ack_s <= '0';
case SdrRoutine_v is
when SdrRoutine_Null =>
SdrCmd_s <= SdrCmd_xx_c;
SdrDat_s <= (others => 'Z');
if refreshDelayCounter_v = 0 then
SdrRoutine_v := SdrRoutine_Init;
end if;
when SdrRoutine_Init =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_pr_c;
SdrAdr_s <= (others => '1');
SdrBa_s <= "00";
SdrUdq_s <= '1';
SdrLdq_s <= '1';
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"04" or SdrRoutineSeq_v = X"0C" then
SdrCmd_s <= SdrCmd_re_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"14" then
SdrCmd_s <= SdrCmd_ms_c;
SdrAdr_s <= "00" & "1" & "00" & "010" & "0" & "000"; -- Single, Standard, CAS Latency=2, WT=0(seq), BL=1
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"17" then
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
when SdrRoutine_Idle =>
SdrCmd_s <= SdrCmd_xx_c;
SdrDat_s <= (others => 'Z');
if ram0_req_s = '1' and ram0_ack_s = '0' then
SdrPort_v := '0';
SdrAddress_v := ram0_addr_s;
if ram0_we_s = '1' then
SdrRoutine_v := SdrRoutine_WriteOne;
else
SdrRoutine_v := SdrRoutine_ReadOne;
end if;
elsif ram1_req_s = '1' and ram1_ack_s = '0' then
SdrPort_v := '1';
SdrAddress_v := ram1_addr_s;
if ram1_we_s = '1' then
SdrRoutine_v := SdrRoutine_WriteOne;
else
SdrRoutine_v := SdrRoutine_ReadOne;
end if;
elsif SdrRefreshCounter_v < 4096 and refresh_i = '1' then
SdrRoutine_v := SdrRoutine_RefreshAll;
SdrRefreshCounter_v := SdrRefreshCounter_v + 1;
end if;
when SdrRoutine_RefreshAll =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_re_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"06" then
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
when SdrRoutine_ReadOne =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_ac_c;
SdrBa_s <= SdrAddress_v(22 downto 21);
SdrAdr_s <= SdrAddress_v(20 downto 9); -- Row (12 bits)
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"02" then
SdrCmd_s <= SdrCmd_rd_c;
SdrAdr_s(11 downto 8) <= "0100"; -- A10 = '1' => Auto Pre-charge
SdrAdr_s(7 downto 0) <= SdrAddress_v(8 downto 1); -- Col (8 bits)
SdrUdq_s <= '0';
SdrLdq_s <= '0';
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"05" then
if SdrPort_v = '0' then
if SdrAddress_v(0) = '0' then
ram0_dout_s <= mem_data_io(7 downto 0);
else
ram0_dout_s <= mem_data_io(15 downto 8);
end if;
ram0_ack_s <= '1';
else
if SdrAddress_v(0) = '0' then
ram1_dout_s <= mem_data_io(7 downto 0);
else
ram1_dout_s <= mem_data_io(15 downto 8);
end if;
ram1_ack_s <= '1';
end if;
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"06" then
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
when SdrRoutine_WriteOne =>
if SdrRoutineSeq_v = X"00" then
SdrCmd_s <= SdrCmd_ac_c;
SdrBa_s <= SdrAddress_v(22 downto 21);
SdrAdr_s <= SdrAddress_v(20 downto 9);
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"02" then
SdrCmd_s <= SdrCmd_wr_c;
SdrAdr_s(11 downto 8) <= "0100"; -- A10 = '1' => Auto Pre-charge
SdrAdr_s(7 downto 0) <= SdrAddress_v(8 downto 1);
SdrUdq_s <= not SdrAddress_v(0);
SdrLdq_s <= SdrAddress_v(0);
if SdrPort_v = '0' then
SdrDat_s <= ram0_din_s & ram0_din_s;
else
SdrDat_s <= ram1_din_s & ram1_din_s;
end if;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"03" then
if SdrPort_v = '0' then
ram0_ack_s <= '1';
else
ram1_ack_s <= '1';
end if;
SdrCmd_s <= SdrCmd_xx_c;
SdrDat_s <= (others => 'Z');
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
elsif SdrRoutineSeq_v = X"05" then
SdrRoutineSeq_v := X"00";
SdrRoutine_v := SdrRoutine_Idle;
else
SdrCmd_s <= SdrCmd_xx_c;
SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
end if;
end case;
refreshDelayCounter_v := refreshDelayCounter_v + 1;
if refreshDelayCounter_v >= ( freq_g * 1000 * 64 ) then
refreshDelayCounter_v := x"000000";
SdrRefreshCounter_v := x"0000";
end if;
end if;
end process;
mem_cke_o <= '1';
mem_cs_n_o <= SdrCmd_s(3);
mem_ras_n_o <= SdrCmd_s(2);
mem_cas_n_o <= SdrCmd_s(1);
mem_we_n_o <= SdrCmd_s(0);
mem_udq_o <= SdrUdq_s;
mem_ldq_o <= SdrLdq_s;
mem_ba_o <= SdrBa_s;
mem_addr_o <= SdrAdr_s;
mem_data_io <= SdrDat_s;
end architecture;

View File

@@ -1,136 +0,0 @@
library ieee;
use ieee.std_logic_1164.all;
entity dpSRAM_1288 is
port (
clk_i : in std_logic;
-- Porta 0
porta0_addr_i : in std_logic_vector(16 downto 0);
porta0_ce_i : in std_logic;
porta0_oe_i : in std_logic;
porta0_we_i : in std_logic;
porta0_data_i : in std_logic_vector(7 downto 0);
porta0_data_o : out std_logic_vector(7 downto 0);
-- Porta 1
porta1_addr_i : in std_logic_vector(16 downto 0);
porta1_ce_i : in std_logic;
porta1_oe_i : in std_logic;
porta1_we_i : in std_logic;
porta1_data_i : in std_logic_vector(7 downto 0);
porta1_data_o : out std_logic_vector(7 downto 0);
-- Output to SRAM in board
sram_addr_o : out std_logic_vector(16 downto 0);
sram_data_io : inout std_logic_vector(7 downto 0);
sram_ce_n_o : out std_logic := '1';
sram_oe_n_o : out std_logic := '1';
sram_we_n_o : out std_logic := '1'
);
end entity;
architecture Behavior of dpSRAM_1288 is
signal sram_we_n_s : std_logic;
signal sram_oe_n_s : std_logic;
begin
sram_ce_n_o <= '0'; -- sempre ativa
sram_we_n_o <= sram_we_n_s;
sram_oe_n_o <= sram_oe_n_s;
process (clk_i)
variable state_v : std_logic := '0';
variable p0_ce_v : std_logic_vector(1 downto 0);
variable p1_ce_v : std_logic_vector(1 downto 0);
variable acesso0_v : std_logic;
variable acesso1_v : std_logic;
variable p0_req_v : std_logic := '0';
variable p1_req_v : std_logic := '0';
variable p0_we_v : std_logic := '0';
variable p1_we_v : std_logic := '0';
variable p0_addr_v : std_logic_vector(16 downto 0);
variable p1_addr_v : std_logic_vector(16 downto 0);
variable p0_data_v : std_logic_vector(7 downto 0);
variable p1_data_v : std_logic_vector(7 downto 0);
begin
if rising_edge(clk_i) then
acesso0_v := porta0_ce_i and (porta0_oe_i or porta0_we_i);
acesso1_v := porta1_ce_i and (porta1_oe_i or porta1_we_i);
p0_ce_v := p0_ce_v(0) & acesso0_v;
p1_ce_v := p1_ce_v(0) & acesso1_v;
if p0_ce_v = "01" then -- detecta rising edge do pedido da porta0
p0_req_v := '1'; -- marca que porta0 pediu acesso
p0_we_v := '0'; -- por enquanto eh leitura
p0_addr_v := porta0_addr_i; -- pegamos endereco
if porta0_we_i = '1' then -- se foi gravacao que a porta0 pediu
p0_we_v := '1'; -- marcamos que eh gravacao
p0_data_v := porta0_data_i; -- pegamos dado
end if;
end if;
if p1_ce_v = "01" then -- detecta rising edge do pedido da porta1
p1_req_v := '1'; -- marca que porta1 pediu acesso
p1_we_v := '0'; -- por enquanto eh leitura
p1_addr_v := porta1_addr_i; -- pegamos endereco
if porta1_we_i = '1' then -- se foi gravacao que a porta1 pediu
p1_we_v := '1'; -- marcamos que eh gravacao
p1_data_v := porta1_data_i; -- pegamos dado
end if;
end if;
if state_v = '0' then -- Estado 0
sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
if p0_req_v = '1' then -- pedido da porta0 pendente
sram_addr_o <= p0_addr_v; -- colocamos o endereco pedido na SRAM
sram_we_n_s <= '1';
-- sram_ce_n <= '0';
sram_oe_n_s <= '0';
if p0_we_v = '1' then -- se for gravacao
sram_data_io <= p0_data_v; -- damos o dado para a SRAM
sram_we_n_s <= '0'; -- e dizemos para ela gravar
sram_oe_n_s <= '1';
end if;
state_v := '1';
elsif p1_req_v = '1' then -- pedido da porta1 pendente
sram_addr_o <= p1_addr_v; -- colocamos o endereco pedido na SRAM
sram_we_n_s <= '1';
-- sram_ce_n <= '0';
sram_oe_n_s <= '0';
if p1_we_v = '1' then -- se for gravacao
sram_data_io <= p1_data_v; -- damos o dado para a SRAM
sram_we_n_s <= '0'; -- e dizemos para ela gravar
sram_oe_n_s <= '1';
end if;
state_v := '1'; -- proximo rising do clock vamos para segundo estado
end if;
elsif state_v = '1' then -- Estado 1
if p0_req_v = '1' then -- pedido da porta0 pendente
sram_we_n_s <= '1';
sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
if p0_we_v = '0' then -- se for leitura
porta0_data_o <= sram_data_io; -- pegamos o dado que a SRAM devolveu
end if;
p0_req_v := '0'; -- limpamos a flag de requisicao da porta0
state_v := '0'; -- voltar para estado 0
sram_oe_n_s <= '1';
-- sram_ce_n <= '1';
elsif p1_req_v = '1' then -- pedido da porta1 pendente
sram_we_n_s <= '1';
sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
if p1_we_v = '0' then -- se for leitura
porta1_data_o <= sram_data_io; -- pegamos o dado que a SRAM devolveu
end if;
p1_req_v := '0'; -- limpamos a flag de requisicao da porta1
state_v := '0'; -- voltar para estado 0
sram_oe_n_s <= '1';
-- sram_ce_n <= '1';
end if;
end if;
end if;
end process;
end;

View File

@@ -1,186 +0,0 @@
-------------------------------------------------------------------------------
--
-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity dpSRAM_25616 is
port (
clk_i : in std_logic;
-- Port 0
porta0_addr_i : in std_logic_vector(18 downto 0);
porta0_ce_i : in std_logic;
porta0_oe_i : in std_logic;
porta0_we_i : in std_logic;
porta0_d_i : in std_logic_vector(7 downto 0);
porta0_d_o : out std_logic_vector(7 downto 0);
-- Port 1
porta1_addr_i : in std_logic_vector(18 downto 0);
porta1_ce_i : in std_logic;
porta1_oe_i : in std_logic;
porta1_we_i : in std_logic;
porta1_d_i : in std_logic_vector(7 downto 0);
porta1_d_o : out std_logic_vector(7 downto 0);
-- SRAM in board
sram_addr_o : out std_logic_vector(17 downto 0);
sram_data_io : inout std_logic_vector(15 downto 0);
sram_ub_o : out std_logic;
sram_lb_o : out std_logic;
sram_ce_n_o : out std_logic := '1';
sram_oe_n_o : out std_logic := '1';
sram_we_n_o : out std_logic := '1'
);
end entity;
architecture Behavior of dpSRAM_25616 is
signal sram_a_s : std_logic_vector(18 downto 0);
signal sram_d_s : std_logic_vector(7 downto 0);
signal sram_we_s : std_logic;
signal sram_oe_s : std_logic;
begin
sram_ce_n_o <= '0'; -- sempre ativa
sram_oe_n_o <= sram_oe_s;
sram_we_n_o <= sram_we_s;
sram_ub_o <= not sram_a_s(0); -- UB = 0 ativa bits 15..8
sram_lb_o <= sram_a_s(0); -- LB = 0 ativa bits 7..0
sram_addr_o <= sram_a_s(18 downto 1);
sram_data_io <= "ZZZZZZZZ" & sram_d_s when sram_a_s(0) = '0' else
sram_d_s & "ZZZZZZZZ";
process (clk_i)
variable state_v : std_logic := '0';
variable p0_ce_v : std_logic_vector(1 downto 0);
variable p1_ce_v : std_logic_vector(1 downto 0);
variable acesso0_v : std_logic;
variable acesso1_v : std_logic;
variable p0_req_v : std_logic := '0';
variable p1_req_v : std_logic := '0';
variable p0_we_v : std_logic := '0';
variable p1_we_v : std_logic := '0';
variable p0_addr_v : std_logic_vector(18 downto 0);
variable p1_addr_v : std_logic_vector(18 downto 0);
variable p0_data_v : std_logic_vector(7 downto 0);
variable p1_data_v : std_logic_vector(7 downto 0);
begin
if rising_edge(clk_i) then
acesso0_v := porta0_ce_i and (porta0_oe_i or porta0_we_i);
acesso1_v := porta1_ce_i and (porta1_oe_i or porta1_we_i);
p0_ce_v := p0_ce_v(0) & acesso0_v;
p1_ce_v := p1_ce_v(0) & acesso1_v;
if p0_ce_v = "01" then -- detecta rising edge do pedido da porta0
p0_req_v := '1'; -- marca que porta0 pediu acesso
p0_we_v := '0'; -- por enquanto eh leitura
p0_addr_v := porta0_addr_i; -- pegamos endereco
if porta0_we_i = '1' then -- se foi gravacao que a porta0 pediu
p0_we_v := '1'; -- marcamos que eh gravacao
p0_data_v := porta0_d_i; -- pegamos dado
end if;
end if;
if p1_ce_v = "01" then -- detecta rising edge do pedido da porta1
p1_req_v := '1'; -- marca que porta1 pediu acesso
p1_we_v := '0'; -- por enquanto eh leitura
p1_addr_v := porta1_addr_i; -- pegamos endereco
if porta1_we_i = '1' then -- se foi gravacao que a porta1 pediu
p1_we_v := '1'; -- marcamos que eh gravacao
p1_data_v := porta1_d_i; -- pegamos dado
end if;
end if;
if state_v = '0' then -- Estado 0
sram_d_s <= (others => 'Z'); -- desconectar bus da SRAM
if p0_req_v = '1' then -- pedido da porta0 pendente
sram_a_s <= p0_addr_v; -- colocamos o endereco pedido na SRAM
sram_we_s <= '1';
sram_oe_s <= '0';
if p0_we_v = '1' then -- se for gravacao
sram_d_s <= p0_data_v; -- damos o dado para a SRAM
sram_we_s <= '0'; -- e dizemos para ela gravar
sram_oe_s <= '1';
end if;
state_v := '1';
elsif p1_req_v = '1' then -- pedido da porta1 pendente
sram_a_s <= p1_addr_v; -- colocamos o endereco pedido na SRAM
sram_we_s <= '1';
sram_oe_s <= '0';
if p1_we_v = '1' then -- se for gravacao
sram_d_s <= p1_data_v; -- damos o dado para a SRAM
sram_we_s <= '0'; -- e dizemos para ela gravar
sram_oe_s <= '1';
end if;
state_v := '1'; -- proximo rising do clock vamos para segundo estado
end if;
elsif state_v = '1' then -- Estado 1
if p0_req_v = '1' then -- pedido da porta0 pendente
sram_we_s <= '1';
sram_d_s <= (others => 'Z'); -- desconectar bus da SRAM
if p0_we_v = '0' then -- se for leitura
if sram_a_s(0) = '0' then -- pegamos o dado que a SRAM devolveu
porta0_d_o <= sram_data_io(7 downto 0);
else
porta0_d_o <= sram_data_io(15 downto 8);
end if;
end if;
p0_req_v := '0'; -- limpamos a flag de requisicao da porta0
state_v := '0'; -- voltar para estado 0
sram_oe_s <= '1';
elsif p1_req_v = '1' then -- pedido da porta1 pendente
sram_we_s <= '1';
sram_d_s <= (others => 'Z'); -- desconectar bus da SRAM
if p1_we_v = '0' then -- se for leitura
if sram_a_s(0) = '0' then -- pegamos o dado que a SRAM devolveu
porta1_d_o <= sram_data_io(7 downto 0);
else
porta1_d_o <= sram_data_io(15 downto 8);
end if;
end if;
p1_req_v := '0'; -- limpamos a flag de requisicao da porta1
state_v := '0'; -- voltar para estado 0
sram_oe_s <= '1';
end if;
end if;
end if;
end process;
end;

View File

@@ -1,173 +0,0 @@
-------------------------------------------------------------------------------
--
-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity dpSRAM_5128 is
port (
clk_i : in std_logic;
-- Port 0
porta0_addr_i : in std_logic_vector(18 downto 0);
porta0_ce_i : in std_logic;
porta0_oe_i : in std_logic;
porta0_we_i : in std_logic;
porta0_data_i : in std_logic_vector(7 downto 0);
porta0_data_o : out std_logic_vector(7 downto 0);
-- Port 1
porta1_addr_i : in std_logic_vector(18 downto 0);
porta1_ce_i : in std_logic;
porta1_oe_i : in std_logic;
porta1_we_i : in std_logic;
porta1_data_i : in std_logic_vector(7 downto 0);
porta1_data_o : out std_logic_vector(7 downto 0);
-- SRAM in board
sram_addr_o : out std_logic_vector(18 downto 0);
sram_data_io : inout std_logic_vector(7 downto 0);
sram_ce_n_o : out std_logic := '1';
sram_oe_n_o : out std_logic := '1';
sram_we_n_o : out std_logic := '1'
);
end entity;
architecture Behavior of dpSRAM_5128 is
signal sram_we_s : std_logic;
signal sram_oe_s : std_logic;
begin
sram_ce_n_o <= '0'; -- sempre ativa
sram_we_n_o <= sram_we_s;
sram_oe_n_o <= sram_oe_s;
process (clk_i)
variable state_v : std_logic := '0';
variable p0_ce_v : std_logic_vector(1 downto 0);
variable p1_ce_v : std_logic_vector(1 downto 0);
variable acesso0_v : std_logic;
variable acesso1_v : std_logic;
variable p0_req_v : std_logic := '0';
variable p1_req_v : std_logic := '0';
variable p0_we_v : std_logic := '0';
variable p1_we_v : std_logic := '0';
variable p0_addr_v : std_logic_vector(18 downto 0);
variable p1_addr_v : std_logic_vector(18 downto 0);
variable p0_data_v : std_logic_vector(7 downto 0);
variable p1_data_v : std_logic_vector(7 downto 0);
begin
if rising_edge(clk_i) then
acesso0_v := porta0_ce_i and (porta0_oe_i or porta0_we_i);
acesso1_v := porta1_ce_i and (porta1_oe_i or porta1_we_i);
p0_ce_v := p0_ce_v(0) & acesso0_v;
p1_ce_v := p1_ce_v(0) & acesso1_v;
if p0_ce_v = "01" then -- detecta rising edge do pedido da porta0
p0_req_v := '1'; -- marca que porta0 pediu acesso
p0_we_v := '0'; -- por enquanto eh leitura
p0_addr_v := porta0_addr_i; -- pegamos endereco
if porta0_we_i = '1' then -- se foi gravacao que a porta0 pediu
p0_we_v := '1'; -- marcamos que eh gravacao
p0_data_v := porta0_data_i; -- pegamos dado
end if;
end if;
if p1_ce_v = "01" then -- detecta rising edge do pedido da porta1
p1_req_v := '1'; -- marca que porta1 pediu acesso
p1_we_v := '0'; -- por enquanto eh leitura
p1_addr_v := porta1_addr_i; -- pegamos endereco
if porta1_we_i = '1' then -- se foi gravacao que a porta1 pediu
p1_we_v := '1'; -- marcamos que eh gravacao
p1_data_v := porta1_data_i; -- pegamos dado
end if;
end if;
if state_v = '0' then -- Estado 0
sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
if p0_req_v = '1' then -- pedido da porta0 pendente
sram_addr_o <= p0_addr_v; -- colocamos o endereco pedido na SRAM
sram_we_s <= '1';
-- sram_ce_n <= '0';
sram_oe_s <= '0';
if p0_we_v = '1' then -- se for gravacao
sram_data_io <= p0_data_v; -- damos o dado para a SRAM
sram_we_s <= '0'; -- e dizemos para ela gravar
sram_oe_s <= '1';
end if;
state_v := '1';
elsif p1_req_v = '1' then -- pedido da porta1 pendente
sram_addr_o <= p1_addr_v; -- colocamos o endereco pedido na SRAM
sram_we_s <= '1';
-- sram_ce_n <= '0';
sram_oe_s <= '0';
if p1_we_v = '1' then -- se for gravacao
sram_data_io <= p1_data_v; -- damos o dado para a SRAM
sram_we_s <= '0'; -- e dizemos para ela gravar
sram_oe_s <= '1';
end if;
state_v := '1'; -- proximo rising do clock vamos para segundo estado
end if;
elsif state_v = '1' then -- Estado 1
if p0_req_v = '1' then -- pedido da porta0 pendente
sram_we_s <= '1';
sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
if p0_we_v = '0' then -- se for leitura
porta0_data_o <= sram_data_io; -- pegamos o dado que a SRAM devolveu
end if;
p0_req_v := '0'; -- limpamos a flag de requisicao da porta0
state_v := '0'; -- voltar para estado 0
sram_oe_s <= '1';
-- sram_ce_n <= '1';
elsif p1_req_v = '1' then -- pedido da porta1 pendente
sram_we_s <= '1';
sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
if p1_we_v = '0' then -- se for leitura
porta1_data_o <= sram_data_io; -- pegamos o dado que a SRAM devolveu
end if;
p1_req_v := '0'; -- limpamos a flag de requisicao da porta1
state_v := '0'; -- voltar para estado 0
sram_oe_s <= '1';
-- sram_ce_n <= '1';
end if;
end if;
end if;
end process;
end;

View File

@@ -1,219 +0,0 @@
------------------------------------------------------------------------------
-- Project : Red Zombie
------------------------------------------------------------------------------
-- File : redzombie.vhd
-- Author : fpgakuechle
-- Company : hobbyist
-- Created : 2012-12
-- Last update: 2013-04-02
-- Lizenz : GNU General Public License (http://www.gnu.de/documents/gpl.de.html)
------------------------------------------------------------------------------
-- Description:
--parallel io unit
--Zilog Z80 PIO - U855
------------------------------------------------------------------------------
--Status: UNDER CONSTRUCTION: 2013-03-03
--missing: IRQ-control
--control register/data path under test now
--last change: fixed: mixed up mask and mode register; add single bit mode
-- fixed: outputs *_rdy at single bit mode
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity pio is
port(
clk : in std_logic;
ce_ni : in std_logic;
IOREQn_i : in std_logic;
data_o : out std_logic_vector(7 downto 0);
data_i : in std_logic_vector(7 downto 0);
RD_n : in std_logic;
M1_n : in std_logic;
sel_b_nA : in std_logic;
sel_c_nD : in std_logic;
--
IRQEna_i : in std_logic;
IRQEna_o : out std_logic;
INTn_o : out std_logic;
astb_n : in std_logic; --Data strobe in, is able to generate IREQ
ardy_n : out std_logic; --
porta_o : out std_logic_vector(7 downto 0);
porta_i : in std_logic_vector(7 downto 0);
bstb_n : in std_logic;
brdy_n : out std_logic;
portb_o : out std_logic_vector(7 downto 0);
portb_i : in std_logic_vector(7 downto 0));
end entity pio;
architecture behave of pio is
signal ctrl_selected : boolean;
signal data_selected : boolean;
type T_ALL_REGS_INDEX is (
IRQ_VEC, MODE, PORTDIR, IRQ_CTRL, MASK, ERR);
type T_PORT_INDEX is (PORT_A, PORT_B);
subtype T_REG is std_logic_vector(7 downto 0);
type T_ALL_REGS is array (T_ALL_REGS_INDEX) of T_REG;
signal reg_index : T_ALL_REGS_INDEX;
type T_2P_SL is array (T_PORT_INDEX'left to T_PORT_INDEX'right) of std_logic;
type T_2P_REG_7b is array (T_PORT_INDEX) of std_logic_vector(7 downto 1);
type T_2P_REG_8b is array (T_PORT_INDEX) of std_logic_vector(7 downto 0);
type T_2P_REG_2b is array (T_PORT_INDEX) of std_logic_vector(7 downto 6);
--default mode: Byte - Out
signal mode_reg : T_2P_REG_2b := (others => "01");
signal portdir_reg : T_2P_REG_8b := (others => x"00");
signal mask_reg : T_2P_REG_8b := (others => x"00");
signal irq_vec_reg : T_2P_REG_7b := (others => "0000000");
signal irq_ctrl_reg : std_logic_vector(7 downto 4) := (others => '0');
signal err_reg : std_logic_vector(7 downto 0) := (others => '0');
signal wr_dir_reg_q : boolean := false;
signal wr_mask_reg_q : boolean := false;
signal data_oq : std_logic_vector(7 downto 0);
signal port_sel : T_PORT_INDEX;
--ports as vectors
signal port_indata : T_2P_REG_8b;
signal port_outdata : T_2P_REG_8b;
--ports regs
signal port_indata_reg : T_2P_REG_8b;
signal port_outdata_reg : T_2P_REG_8b;
signal strb_in : T_2P_SL;
signal rdy_out : T_2P_SL;
begin
port_sel <= PORT_B when sel_b_nA = '1' else
PORT_A;
strb_in(PORT_A) <= astb_n;
strb_in(PORT_B) <= bstb_n;
ardy_n <= rdy_out(PORT_A);
brdy_n <= rdy_out(PORT_B);
port_indata(PORT_A) <= porta_i;
port_indata(PORT_B) <= portb_i;
porta_o <= port_outdata(PORT_A);
portb_o <= port_outdata(PORT_B);
--built enables for control register
process(data_i(3 downto 0), wr_dir_reg_q, wr_mask_reg_q) is
begin
if wr_dir_reg_q then
reg_index <= PORTDIR;
elsif wr_mask_reg_q then
reg_index <= MASK;
elsif data_i(0) = '0' then
reg_index <= IRQ_VEC;
elsif data_i(3 downto 0) = x"F" then
reg_index <= MODE;
elsif data_i(3 downto 0) = x"7" then
reg_index <= IRQ_CTRL;
else
reg_index <= ERR;
end if;
end process;
ctrl_selected <= ce_ni = '0' and IOREQn_i = '0' and sel_c_nD = '1'; --access controlregs
data_selected <= ce_ni = '0' and IOREQn_i = '0' and sel_c_nD = '0'; --access ports
--read/write control register
process(clk)
begin
if falling_edge(clk) then
if ctrl_selected then
if rd_n = '1' then
wr_dir_reg_q <= false;
wr_mask_reg_q <= false;
--write control reg
case reg_index is
when IRQ_VEC => irq_vec_reg(port_sel) <= data_i(7 downto 1);
when MODE => mode_reg(port_sel) <= data_i(7 downto 6);
if data_i(7 downto 6) = "11" then
wr_dir_reg_q <= true;
end if;
when PORTDIR => portdir_reg(port_sel) <= data_i(7 downto 0);
when IRQ_CTRL => irq_ctrl_reg <= data_i(7 downto 4);
if data_i(4) = '1' then
wr_mask_reg_q <= true;
end if;
when MASK => mask_reg(port_sel) <= data_i(7 downto 0);
when ERR => err_reg <= data_i(7 downto 0);
when others => err_reg <= data_i(7 downto 0);
end case;
else
--read control reg ?How to select control register while reading?
case reg_index is
when IRQ_VEC => data_oq <= irq_vec_reg(port_sel) & '0';
when MODE => data_oq <= mode_reg(port_sel) & "000000";
when PORTDIR => data_oq <= portdir_reg(port_sel);
when IRQ_CTRL => data_oq <= irq_ctrl_reg & x"0";
when MASK => data_oq <= mask_reg(port_sel);
when ERR => data_oq <= err_reg;
when others => data_oq <= x"00";
end case;
end if;
--port_regs <> CPU
elsif data_selected then
if rd_n = '0' then
data_oq <= port_indata_reg(port_sel);
else
port_outdata_reg(port_sel) <= data_i;
end if;
end if;
end if;
end process;
g_portCPU : for pchan in T_PORT_INDEX generate
--real port access
process(clk)
begin
if falling_edge(clk) then
if mode_reg(pchan) = "00" then --output mode
port_outdata(pchan) <= port_outdata_reg(pchan);
elsif mode_reg(pchan) = "01" then --input mode
port_indata_reg(pchan) <= port_indata(pchan);
elsif mode_reg(pchan) = "10" then --bidir
for i in 0 to 7 loop --strb contrl mot implemented yet
if portdir_reg(pchan)(i) = '0' then --output
port_outdata(pchan)(i) <= port_outdata_reg(pchan)(i);
else
port_indata_reg(pchan)(i) <= port_indata(pchan)(i);
end if;
end loop;
elsif mode_reg(pchan) = "11" then --bit mode
for i in 0 to 7 loop
if portdir_reg(pchan)(i) = '0' then --output port
port_outdata(pchan)(i) <= port_outdata_reg(pchan)(i);
else --input port
port_indata_reg(pchan)(i) <= port_indata(pchan)(i);
end if;
end loop;
end if;
end if;
end process;
end generate g_portCPU;
data_o <= data_oq;
--unused output yet
IRQEna_o <= '1';
INTn_o <= '1';
rdy_out(PORT_A) <= '0' when mode_reg(PORT_A) = "11" else '1'; --other modes
--not implemented
rdy_out(PORT_B) <= '0' when mode_reg(PORT_B) = "11" and mode_reg(PORT_A) /= "10" else '1';
end architecture;

View File

@@ -1,174 +0,0 @@
/* Atari on an FPGA
Masters of Engineering Project
Cornell University, 2007
Daniel Beer
RIOT.v
Redesign of the MOS 6532 chip. Provides RAM, I/O and timers to the Atari.
*/
`timescale 1ns / 1ps
`include "riot.vh"
module RIOT(A, // Address bus input
Din, // Data bus input
Dout, // Data bus output
CS, // Chip select input
CS_n, // Active low chip select input
R_W_n, // Active low read/write input
RS_n, // Active low rom select input
RES_n, // Active low reset input
IRQ_n, // Active low interrupt output
CLK, // Clock input
PAin, // 8 bit port A input
PAout, // 8 bit port A output
PBin, // 8 bit port B input
PBout);// 8 bit port B output
input [6:0] A;
input [7:0] Din;
output [7:0] Dout;
input CS, CS_n, R_W_n, RS_n, RES_n, CLK;
output IRQ_n;
input [7:0] PAin, PBin;
output [7:0] PAout, PBout; // Output register
reg [7:0] Dout; // RAM allocation
reg [7:0] RAM[127:0]; // I/O registers
reg [7:0] DRA, DRB; // Data registers
reg [7:0] DDRA, DDRB; // Data direction registers
wire PA7;
reg R_PA7;
assign PA7 = (PAin[7] & ~DDRA[7]) | (DRA[7] & DDRA[7]);
assign PAout = DRA & DDRA;
assign PBout = DRB & DDRB;
// Timer registers
reg [8:0] Timer;
reg [9:0] Prescaler;
reg [1:0] Timer_Mode;
reg Timer_Int_Flag, PA7_Int_Flag, Timer_Int_Enable, PA7_Int_Enable, PA7_Int_Mode; // Timer prescaler constants
wire [9:0] PRESCALER_VALS[3:0];
assign PRESCALER_VALS[0] = 10'd0;
assign PRESCALER_VALS[1] = 10'd7;
assign PRESCALER_VALS[2] = 10'd63;
assign PRESCALER_VALS[3] = 10'd1023;
// Interrupt
assign IRQ_n = ~(Timer_Int_Flag & Timer_Int_Enable | PA7_Int_Flag & PA7_Int_Enable);
// Operation decoding
wire [6:0] op;
reg [6:0] R_op;
assign op = {RS_n, R_W_n, A[4:0]};
// Registered data in
reg [7:0] R_Din;
integer cnt;
// Software operations
always @(posedge CLK)
begin
// Reset operation
if (~RES_n) begin
DRA <= 8'b0;
DDRA <= 8'b0;
DRB <= 8'b00010100;
DDRB <= 8'b00010100;
Timer_Int_Flag <= 1'b0;
PA7_Int_Flag <= 1'b0;
PA7_Int_Enable <= 1'b0;
PA7_Int_Mode <= 1'b0;
// Fill RAM with 0s
for (cnt = 0; cnt < 128; cnt = cnt + 1)
RAM[cnt] <= 8'b0;
R_PA7 <= 1'b0;
R_op <= `NOP;
R_Din <= 8'b0;
end
// If the chip is enabled, execute an operation
else if (CS & ~CS_n) begin
// Register inputs for use later
R_PA7 <= PA7;
R_op <= op;
R_Din <= Din;
// Update the timer interrupt flag
casex (op)
`WRITE_TIMER: Timer_Int_Flag <= 1'b0;
`READ_TIMER: Timer_Int_Flag <= 1'b0;
default: if (Timer == 9'b111111111) Timer_Int_Flag <= 1'b1;
endcase
// Update the port A interrupt flag
casex (op)
`READ_INT_FLAG: PA7_Int_Flag <= 1'b0;
default: PA7_Int_Flag <= PA7_Int_Flag | (PA7 != R_PA7 & PA7 == PA7_Int_Mode);
endcase
// Process the current operation
casex(op) // RAM access
`READ_RAM: Dout <= RAM[A];
`WRITE_RAM: RAM[A] <= Din;
// Port A data access
`READ_DRA : Dout <= (PAin & ~DDRA) | (DRA & DDRA);
`WRITE_DRA: DRA <= Din;
// Port A direction register access
`READ_DDRA: Dout <= DDRA;
`WRITE_DDRA: DDRA <= Din;
// Port B data access
`READ_DRB: Dout <= (PBin & ~DDRB) | (DRB & DDRB);
`WRITE_DRB: DRB <= Din;
// Port B direction register access
`READ_DDRB: Dout <= DDRB;
`WRITE_DDRB: DDRB <= Din;
// Timer access
`READ_TIMER: Dout <= Timer[7:0];
// Status register access
`READ_INT_FLAG: Dout <= {Timer_Int_Flag, PA7_Int_Flag, 6'b0};
// Enable the port A interrupt
`WRITE_EDGE_DETECT: begin
PA7_Int_Mode <= A[0]; PA7_Int_Enable <= A[1];
end
endcase
end
// Even if the chip is not enabled, update background functions
else begin
// Update the timer interrupt
if (Timer == 9'b111111111)
Timer_Int_Flag <= 1'b1;
// Update the port A interrupt
R_PA7 <= PA7;
PA7_Int_Flag <= PA7_Int_Flag | (PA7 != R_PA7 & PA7 == PA7_Int_Mode);
// Set the operation to a NOP
R_op <=`NOP;
end
end
// Update the timer at the negative edge of the clock
always @(negedge CLK)begin
// Reset operation
if (~RES_n) begin
Timer <= 9'b0;
Timer_Mode <= 2'b0;
Prescaler <= 10'b0;
Timer_Int_Enable <= 1'b0;
end
// Otherwise, process timer operations
else
casex
(R_op)
// Write value to the timer and update the prescaler based on the address
`WRITE_TIMER:begin
Timer <= {1'b0, R_Din};
Timer_Mode <= R_op[1:0];
Prescaler <= PRESCALER_VALS[R_op[1:0]];
Timer_Int_Enable <= R_op[3];
end
// Otherwise decrement the prescaler and if necessary the timer.
// The prescaler holds a variable number of counts that must be
// run before the timer is decremented
default:if (Timer != 9'b100000000) begin
if (Prescaler != 10'b0)
Prescaler <= Prescaler - 10'b1;
else begin
if (Timer == 9'b0)
begin
Prescaler <= 10'b0;
Timer_Mode <= 2'b0;
end
else
Prescaler <= PRESCALER_VALS[Timer_Mode];
Timer <= Timer - 9'b1;
end
end
endcase
end
endmodule

View File

@@ -1,278 +0,0 @@
module AY8912
(
input CLK, // Global clock
input CE, // PSG Clock enable
input RESET, // Chip RESET (set all Registers to '0', active hi)
input BDIR, // Bus Direction (0 - read , 1 - write)
input BC, // Bus control
input [7:0] DI, // Data In
output [7:0] DO, // Data Out
output [7:0] CHANNEL_A, // PSG Output channel A
output [7:0] CHANNEL_B, // PSG Output channel B
output [7:0] CHANNEL_C, // PSG Output channel C
input SEL,
input [7:0] IO_in,
output [7:0] IO_out
);
assign IO_out = ymreg[14];
reg ena_div;
reg ena_div_noise;
reg [3:0] addr;
reg [7:0] ymreg[16];
reg env_ena;
reg [4:0] env_vol;
wire [7:0] volTableAy[16] =
'{8'h00, 8'h03, 8'h04, 8'h06,
8'h0a, 8'h0f, 8'h15, 8'h22,
8'h28, 8'h41, 8'h5b, 8'h72,
8'h90, 8'hb5, 8'hd7, 8'hff
};
// Read from AY
assign DO = dout;
reg [7:0] dout;
always_comb begin
case(addr)
0: dout = ymreg[0];
1: dout = {4'b0000, ymreg[1][3:0]};
2: dout = ymreg[2];
3: dout = {4'b0000, ymreg[3][3:0]};
4: dout = ymreg[4];
5: dout = {4'b0000, ymreg[5][3:0]};
6: dout = {3'b000, ymreg[6][4:0]};
7: dout = ymreg[7];
8: dout = {3'b000, ymreg[8][4:0]};
9: dout = {3'b000, ymreg[9][4:0]};
10: dout = {3'b000, ymreg[10][4:0]};
11: dout = ymreg[11];
12: dout = ymreg[12];
13: dout = {4'b0000, ymreg[13][3:0]};
14: dout = (ymreg[7][6] ? ymreg[14] : IO_in);
15: dout = (ymreg[7][7] ? ymreg[15] : IO_in);
endcase
end
// p_divider
always @(posedge CLK) begin
reg [3:0] cnt_div;
reg noise_div;
if(CE) begin
ena_div <= 0;
ena_div_noise <= 0;
if(!cnt_div) begin
cnt_div <= {SEL, 3'b111};
ena_div <= 1;
noise_div <= (~noise_div);
if (noise_div) ena_div_noise <= 1;
end else begin
cnt_div <= cnt_div - 1'b1;
end
end
end
reg [16:0] poly17;
wire [4:0] noise_gen_comp = ymreg[6][4:0] ? ymreg[6][4:0] - 1'd1 : 5'd0;
// p_noise_gen
always @(posedge CLK) begin
reg [4:0] noise_gen_cnt;
if(CE) begin
if (ena_div_noise) begin
if (noise_gen_cnt >= noise_gen_comp) begin
noise_gen_cnt <= 0;
poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
end else begin
noise_gen_cnt <= noise_gen_cnt + 1'd1;
end
end
end
end
wire [11:0] tone_gen_freq[1:3];
assign tone_gen_freq[1] = {ymreg[1][3:0], ymreg[0]};
assign tone_gen_freq[2] = {ymreg[3][3:0], ymreg[2]};
assign tone_gen_freq[3] = {ymreg[5][3:0], ymreg[4]};
wire [11:0] tone_gen_comp[1:3];
assign tone_gen_comp[1] = tone_gen_freq[1] ? tone_gen_freq[1] - 1'd1 : 12'd0;
assign tone_gen_comp[2] = tone_gen_freq[2] ? tone_gen_freq[2] - 1'd1 : 12'd0;
assign tone_gen_comp[3] = tone_gen_freq[3] ? tone_gen_freq[3] - 1'd1 : 12'd0;
reg [3:1] tone_gen_op;
//p_tone_gens
always @(posedge CLK) begin
integer i;
reg [11:0] tone_gen_cnt[1:3];
if(CE) begin
// looks like real chips count up - we need to get the Exact behaviour ..
for (i = 1; i <= 3; i = i + 1) begin
if(ena_div) begin
if (tone_gen_cnt[i] >= tone_gen_comp[i]) begin
tone_gen_cnt[i] <= 0;
tone_gen_op[i] <= (~tone_gen_op[i]);
end else begin
tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
end
end
end
end
end
wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
//p_envelope_freq
always @(posedge CLK) begin
reg [15:0] env_gen_cnt;
if(CE) begin
env_ena <= 0;
if(ena_div) begin
if (env_gen_cnt >= env_gen_comp) begin
env_gen_cnt <= 0;
env_ena <= 1;
end else begin
env_gen_cnt <= (env_gen_cnt + 1'd1);
end
end
end
end
wire is_bot = (env_vol == 5'b00000);
wire is_bot_p1 = (env_vol == 5'b00001);
wire is_top_m1 = (env_vol == 5'b11110);
wire is_top = (env_vol == 5'b11111);
always @(posedge CLK) begin
reg old_BDIR;
reg env_reset;
reg env_hold;
reg env_inc;
// envelope shapes
// C AtAlH
// 0 0 x x \___
//
// 0 1 x x /___
//
// 1 0 0 0 \\\\
//
// 1 0 0 1 \___
//
// 1 0 1 0 \/\/
// ___
// 1 0 1 1 \
//
// 1 1 0 0 ////
// ___
// 1 1 0 1 /
//
// 1 1 1 0 /\/\
//
// 1 1 1 1 /___
if(RESET) begin
ymreg[0] <= 0;
ymreg[1] <= 0;
ymreg[2] <= 0;
ymreg[3] <= 0;
ymreg[4] <= 0;
ymreg[5] <= 0;
ymreg[6] <= 0;
ymreg[7] <= 255;
ymreg[8] <= 0;
ymreg[9] <= 0;
ymreg[10] <= 0;
ymreg[11] <= 0;
ymreg[12] <= 0;
ymreg[13] <= 0;
ymreg[14] <= 0;
ymreg[15] <= 0;
addr <= 0;
env_vol <= 0;
end else begin
old_BDIR <= BDIR;
if(~old_BDIR & BDIR) begin
if(BC) addr <= DI[3:0];
else begin
ymreg[addr] <= DI;
env_reset <= (addr == 13);
end
end
end
if(CE) begin
if(env_reset) begin
env_reset <= 0;
// load initial state
if(!ymreg[13][2]) begin // attack
env_vol <= 5'b11111;
env_inc <= 0; // -1
end else begin
env_vol <= 5'b00000;
env_inc <= 1; // +1
end
env_hold <= 0;
end else begin
if (env_ena) begin
if (!env_hold) begin
if (env_inc) env_vol <= (env_vol + 5'b00001);
else env_vol <= (env_vol + 5'b11111);
end
// envelope shape control.
if(!ymreg[13][3]) begin
if(!env_inc) begin // down
if(is_bot_p1) env_hold <= 1;
end else if (is_top) env_hold <= 1;
end else if(ymreg[13][0]) begin // hold = 1
if(!env_inc) begin // down
if(ymreg[13][1]) begin // alt
if(is_bot) env_hold <= 1;
end else if(is_bot_p1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alt
if(is_top) env_hold <= 1;
end else if(is_top_m1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alternate
if(env_inc == 1'b0) begin // down
if(is_bot_p1) env_hold <= 1;
if(is_bot) begin
env_hold <= 0;
env_inc <= 1;
end
end else begin
if(is_top_m1) env_hold <= 1;
if(is_top) begin
env_hold <= 0;
env_inc <= 0;
end
end
end
end
end
end
end
wire [4:0] A = ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | poly17[0])) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]};
wire [4:0] B = ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | poly17[0])) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]};
wire [4:0] C = ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | poly17[0])) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]};
assign CHANNEL_A = volTableAy[A[4:1]];
assign CHANNEL_B = volTableAy[B[4:1]];
assign CHANNEL_C = volTableAy[C[4:1]];
endmodule

View File

@@ -1,308 +0,0 @@
// ports are not identical to the actual AY chip - no need for that.
// Also the parallel ports are not very useful, so they are not connected
module ay8910(rst_n,clk,clk_en,asel,wr_n,cs_n,din,dout,A,B,C,audio);
input rst_n;
input clk; // 28 MHz clock from the system
input clk_en; // 1.7 (?) clock to run the sound timing
input asel;
input wr_n;
input cs_n;
input [7:0] din;
output [7:0] dout;
output [7:0] A;
output [7:0] B;
output [7:0] C;
output [7:0] audio;
/////////////////////////////////////////////////////////////////////////////
// Write Register
/////////////////////////////////////////////////////////////////////////////
reg [3:0] addr;
// registers
reg [11:0] period_a,period_b,period_c;
reg [4:0] period_n;
reg [7:0] reg_en;
reg [4:0] vol_a,vol_b,vol_c;
reg [15:0] period_e;
reg [3:0] shape_e;
reg [7:0] pa_r,pb_r;
wire pb_od = reg_en[7];
wire pa_od = reg_en[6];
wire na = reg_en[5];
wire nb = reg_en[4];
wire nc = reg_en[3];
wire ena = reg_en[2];
wire enb = reg_en[1];
wire enc = reg_en[0];
always @(posedge clk)
if(~rst_n) begin
vol_a <= 0;
vol_b <= 0;
vol_c <= 0;
end else
if(~wr_n && ~cs_n) begin
if(asel)
begin
// address write
addr <= din[3:0];
end else begin
// register write
case(addr)
0:period_a[ 7:0] <= din;
1:period_a[11:8] <= din[3:0];
2:period_b[ 7:0] <= din;
3:period_b[11:8] <= din[3:0];
4:period_c[ 7:0] <= din;
5:period_c[11:8] <= din[3:0];
6:period_n[ 4:0] <= din[4:0];
7:reg_en <= din;
8:vol_a <= din[4:0];
9:vol_b <= din[4:0];
10:vol_c <= din[4:0];
11:period_e[7:0] <= din;
12:period_e[15:8] <= din;
13:shape_e <= din[3:0];
14:pa_r <= din;
15:pb_r <= din;
endcase
end
end
/////////////////////////////////////////////////////////////////////////////
// Read Register
/////////////////////////////////////////////////////////////////////////////
assign dout = addr==4'h0 ? period_a[7:0] :
addr==4'h1 ? {4'h0,period_a[11:0]} :
addr==4'h2 ? period_b[7:0] :
addr==4'h3 ? {4'h0,period_b[11:0]} :
addr==4'h4 ? period_c[7:0] :
addr==4'h5 ? {4'h0,period_c[11:0]} :
addr==4'h6 ? {3'h0,period_n} :
addr==4'h7 ? reg_en :
addr==4'h8 ? {3'h0,vol_a} :
addr==4'h9 ? {3'h0,vol_b} :
addr==4'ha ? {3'h0,vol_c} :
addr==4'hb ? period_e[7:0] :
addr==4'hc ? period_e[15:8] :
addr==4'hd ? {4'h0,shape_e} : 8'hff;
/////////////////////////////////////////////////////////////////////////////
// PSG
/////////////////////////////////////////////////////////////////////////////
//
// toneA 12bit | 12bit
// toneB 12bit | 12bit
// toneC 12bit | 12bit
// env 15bit | 15bit
//
reg [2:0] pris;
reg [11:0] cnt_a,cnt_b,cnt_c;
reg out_a,out_b,out_c;
always @(posedge clk)
if(clk_en) begin
pris <= pris + 1;
if(pris==0)
begin
// tone generator
cnt_a <= cnt_a + 1;
if(cnt_a==period_a)
begin
out_a <= ~out_a;
cnt_a <= 0;
end
cnt_b <= cnt_b + 1;
if(cnt_b==period_b)
begin
out_b <= ~out_b;
cnt_b <= 0;
end
cnt_c <= cnt_c + 1;
if(cnt_c==period_c)
begin
out_c <= ~out_c;
cnt_c <= 0;
end
end
end
/////////////////////////////////////////////////////////////////////////////
// envelope generator
/////////////////////////////////////////////////////////////////////////////
reg [15:0] env_cnt;
reg [3:0] env_phase;
reg env_start;
reg env_en;
reg env_inv;
// write eshape
wire env_clr = (addr==13) & ~cs_n & ~wr_n;
// bit3 = turn reset , 0=on , 1=off
// bit2 = start , 0=up , 1=down(inv)
// bit1 = turn invert, 0=tggle , 1=fix
// bit0 = turn repeat, 0=off, 1=on
wire next_no_reset = shape_e[3];
wire start_no_inv = shape_e[2];
wire next_toggle = shape_e[1];
wire next_repeat = shape_e[0];
// envelope volume output
wire [3:0] vol_e = env_phase ^ {4{env_inv}};
//
always @(posedge clk or posedge env_clr)
begin
if(env_clr) env_start <= 1'b1;
else if(clk_en) env_start <= 1'b0;
end
always @(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
env_en <= 1'b0;
end else
if(clk_en)begin
// start trigger
if(env_start)
begin
env_cnt <= 0;
env_phase <= 0;
env_inv <= ~start_no_inv;
env_en <= 1'b1;
end
// count
if(pris==0 && env_en)
begin
// phase up
env_cnt <= env_cnt + 1;
if(env_cnt==period_e)
begin
env_cnt <= 0;
env_phase <= env_phase+1;
// turn over
if(env_phase==15)
begin
if(~next_no_reset)
begin
env_inv <= (env_inv ^ next_toggle) & next_no_reset;
env_en <= next_repeat & next_no_reset;
end
end
end
end
end
end
/////////////////////////////////////////////////////////////////////////////
// noise generator
/////////////////////////////////////////////////////////////////////////////
reg [16:0] shift_n;
reg [4:0] cnt_n;
always @(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
shift_n <= 17'b00000000000000001;
end else if((pris==0) &&(clk_en))
begin
cnt_n <= cnt_n +1;
if(cnt_n == period_n)
begin
cnt_n <= 0;
shift_n <= {shift_n[0]^shift_n[3],shift_n[16:1]};
end
end
end
wire out_n = shift_n[0];
/////////////////////////////////////////////////////////////////////////////
// volume table 3db / step
/////////////////////////////////////////////////////////////////////////////
function [7:0] vol_tbl;
input [4:0] vol;
input [3:0] vole;
input out;
begin
if(~out)
vol_tbl = 0;
else case(vol[4]?vole:vol[3:0])
15:vol_tbl = 255;
14:vol_tbl = 180;
13:vol_tbl = 127;
12:vol_tbl = 90;
11:vol_tbl = 64;
10:vol_tbl = 45;
9:vol_tbl = 32;
8:vol_tbl = 22;
7:vol_tbl = 16;
6:vol_tbl = 11;
5:vol_tbl = 8;
4:vol_tbl = 5;
3:vol_tbl = 4;
2:vol_tbl = 3;
1:vol_tbl = 2;
0:vol_tbl = 0; //1;
endcase
end
endfunction
/////////////////////////////////////////////////////////////////////////////
// output
/////////////////////////////////////////////////////////////////////////////
assign A = vol_tbl(vol_a,vol_e,(out_a | ena) & (out_n | na) );
assign B = vol_tbl(vol_b,vol_e,(out_b | enb) & (out_n | nb) );
assign C = vol_tbl(vol_c,vol_e,(out_c | enc) & (out_n | nc) );
assign audio = {"00",A} + {"00",B} + {"00",C};//todo gehstock
endmodule

View File

@@ -1,380 +0,0 @@
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- --
-- Copyright (c) 2005-2009 Tobias Gubener --
-- Subdesign CPC T-REX by TobiFlex --
-- --
-- This source file 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 source file 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. --
-- --
-- You should have received a copy of the GNU General Public License --
-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
-- --
------------------------------------------------------------------------------
------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ay8912 is
port (
cpuclk : in STD_LOGIC; --48MHz
reset : in STD_LOGIC;
cs : in STD_LOGIC; --H-aktiv
bc0 : in STD_LOGIC; --
bdir : in STD_LOGIC;
Data_in : in STD_LOGIC_VECTOR (7 downto 0);
Data_out : out STD_LOGIC_VECTOR (7 downto 0);
IO_A : in STD_LOGIC_VECTOR (7 downto 0);
chanA : buffer STD_LOGIC_VECTOR (10 downto 0);
chanB : buffer STD_LOGIC_VECTOR (10 downto 0);
chanC : buffer STD_LOGIC_VECTOR (10 downto 0);
Arechts : out STD_LOGIC_VECTOR (15 downto 0);
Alinks : out STD_LOGIC_VECTOR (15 downto 0);
Amono : out STD_LOGIC_VECTOR (15 downto 0)
);
end ay8912;
architecture logic of ay8912 is
signal t_Data : STD_LOGIC_VECTOR (7 downto 0);
signal PSGReg : STD_LOGIC_VECTOR (3 downto 0);
signal APeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 0,1
signal BPeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 2,3
signal CPeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 4,5
signal Noise : STD_LOGIC_VECTOR (4 downto 0); --Reg 6
signal enable : STD_LOGIC_VECTOR (7 downto 0); --Reg 7
signal AVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 8
signal BVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 9
signal CVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 10
signal HPeriode : STD_LOGIC_VECTOR (15 downto 0); --Reg 11,12
signal HKurve : STD_LOGIC_VECTOR (3 downto 0); --Reg 13
signal PortA : STD_LOGIC_VECTOR (7 downto 0); --Reg 14
signal PortB : STD_LOGIC_VECTOR (7 downto 0); --Reg 15
signal AVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 8log
signal BVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 9log
signal CVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 10log
signal Alog : STD_LOGIC_VECTOR (9 downto 0);
signal Blog : STD_LOGIC_VECTOR (9 downto 0);
signal Clog : STD_LOGIC_VECTOR (9 downto 0);
signal HVollog : STD_LOGIC_VECTOR (11 downto 0);
signal ACount : STD_LOGIC_VECTOR (11 downto 0);
signal BCount : STD_LOGIC_VECTOR (11 downto 0);
signal CCount : STD_LOGIC_VECTOR (11 downto 0);
signal NCount : STD_LOGIC_VECTOR (4 downto 0);
signal HCount : STD_LOGIC_VECTOR (15 downto 0);
signal HVol : STD_LOGIC_VECTOR (4 downto 0);
signal nHVol : STD_LOGIC_VECTOR (3 downto 0);
signal HStart : STD_LOGIC;
signal Noisebit : STD_LOGIC;
signal RNG : STD_LOGIC_VECTOR (16 downto 0);
signal Anot, Bnot, Cnot : STD_LOGIC;
signal n_setreg : STD_LOGIC;
signal n_Pegel : STD_LOGIC_VECTOR (11 downto 0);
signal clockgen : STD_LOGIC_VECTOR (9 downto 0);
signal S_Tick : STD_LOGIC;
signal H_Tick : STD_LOGIC;
begin
-------------------------------------------------------------------------
--Clock gen
-------------------------------------------------------------------------
process (cpuclk, clockgen)
begin
S_Tick <= '0'; --sound
H_Tick <= '0'; --Hüllkurve
IF clockgen(9 downto 1)=0 THEN
S_Tick <= '1';
IF clockgen(0)='0' THEN
H_Tick <= '1';
END IF;
END IF;
IF rising_edge(cpuclk) THEN
Arechts <= (chanA&"00000")+('0'&chanB&"0000");
Alinks <= (chanC&"00000")+('0'&chanB&"0000");
Amono <= (chanC&"00000")+('0'&chanB&"0000")+(chanA&"00000");
IF H_Tick='1' THEN
-- clockgen <= ((48*16)-1); --48MHz
clockgen <= "1011111111"; --48MHz
ELSE
clockgen <= clockgen-1;
END IF;
END IF;
END process;
-------------------------------------------------------------------------
--IO Regs
-------------------------------------------------------------------------
process (cpuclk, reset, IO_A, PortA, PortB, Aperiode, Bperiode, Cperiode, Hperiode, AVol, BVol, CVol, Noise, HKurve, enable, Data_in, t_Data, PSGReg, bdir, bc0)
begin
IF reset='0' THEN
enable <= (others => '0');
PortA <= "11111111";
PortB <= "11111111";
ELSIF rising_edge(cpuclk) THEN
HStart <= '0';
IF bdir='1' AND bc0='1' THEN
IF Data_in(7 downto 4)="0000" THEN
PSGReg <= Data_in(3 downto 0);
END IF;
ELSE
IF bdir='1' AND bc0='0' THEN
CASE PSGReg IS
WHEN "0000" =>
APeriode(7 downto 0) <= Data_in;
WHEN "0001" =>
APeriode(11 downto 8) <= Data_in(3 downto 0);
WHEN "0010" =>
BPeriode(7 downto 0) <= Data_in;
WHEN "0011" =>
BPeriode(11 downto 8) <= Data_in(3 downto 0);
WHEN "0100" =>
CPeriode(7 downto 0) <= Data_in;
WHEN "0101" =>
CPeriode(11 downto 8) <= Data_in(3 downto 0);
WHEN "0110" =>
Noise(4 downto 0) <= Data_in(4 downto 0);
WHEN "0111" =>
enable <= Data_in XOR B"00111111";
WHEN "1000" =>
AVollog <= n_Pegel(9 downto 0);
AVol(4 downto 0) <= Data_in(4 downto 0);
WHEN "1001" =>
BVollog <= n_Pegel(9 downto 0);
BVol(4 downto 0) <= Data_in(4 downto 0);
WHEN "1010" =>
CVollog <= n_Pegel(9 downto 0);
CVol(4 downto 0) <= Data_in(4 downto 0);
WHEN "1011" =>
HPeriode(7 downto 0) <= Data_in;
WHEN "1100" =>
HPeriode(15 downto 8) <= Data_in;
WHEN "1101" =>
HStart <= '1';
HKurve(3 downto 0) <= Data_in(3 downto 0);
WHEN "1110" =>
PortA <= Data_in;
WHEN "1111" =>
PortB <= Data_in;
WHEN OTHERS => null;
END CASE;
END IF;
END IF;
END IF;
CASE Data_in(3 downto 0) IS
WHEN "1111" => n_Pegel <= X"2AA"; -- Umsetzung in logarithmische Werte in ca. 3dB Schritten
WHEN "1110" => n_Pegel <= X"1E2"; -- für Kanäle
WHEN "1101" => n_Pegel <= X"155";
WHEN "1100" => n_Pegel <= X"0F1";
WHEN "1011" => n_Pegel <= X"0AA";
WHEN "1010" => n_Pegel <= X"078";
WHEN "1001" => n_Pegel <= X"055";
WHEN "1000" => n_Pegel <= X"03C";
WHEN "0111" => n_Pegel <= X"02A";
WHEN "0110" => n_Pegel <= X"01E";
WHEN "0101" => n_Pegel <= X"015";
WHEN "0100" => n_Pegel <= X"00F";
WHEN "0011" => n_Pegel <= X"00A";
WHEN "0010" => n_Pegel <= X"007";
WHEN "0001" => n_Pegel <= X"005";
WHEN "0000" => n_Pegel <= X"000";
WHEN OTHERS => null;
END CASE;
-- read reg
IF bc0='1' AND bdir='0' THEN
Data_out <= t_Data;
ELSE
Data_out <= "11111111";
END IF;
t_Data <= "00000000";
CASE PSGReg IS
WHEN "0000" =>
t_Data <= Aperiode(7 downto 0);
WHEN "0001" =>
t_Data(3 downto 0) <= Aperiode(11 downto 8);
WHEN "0010" =>
t_Data <= Bperiode(7 downto 0);
WHEN "0011" =>
t_Data(3 downto 0) <= Bperiode(11 downto 8);
WHEN "0100" =>
t_Data <= Cperiode(7 downto 0);
WHEN "0101" =>
t_Data(3 downto 0) <= Cperiode(11 downto 8);
WHEN "0110" =>
t_Data(4 downto 0) <= Noise;
WHEN "0111" =>
t_Data <= enable XOR "00111111";
WHEN "1000" =>
t_Data(4 downto 0) <= AVol;
WHEN "1001" =>
t_Data(4 downto 0) <= BVol;
WHEN "1010" =>
t_Data(4 downto 0) <= CVol;
WHEN "1011" =>
t_Data <= Hperiode(7 downto 0);
WHEN "1100" =>
t_Data <= Hperiode(15 downto 8);
WHEN "1101" =>
t_Data(3 downto 0) <= HKurve;
WHEN "1110" =>
IF enable(6)='0' THEN
t_Data <= PortA AND IO_A;
ELSE
t_Data <= PortA;
END IF;
WHEN "1111" =>
t_Data <= PortB;
END CASE;
END process;
-------------------------------------------------------------------------
--Soundgen
-------------------------------------------------------------------------
process (cpuclk, reset, AVol, BVol, CVol, HVol, nHVol, AVollog, BVollog, CVollog, HVollog, HKurve)
begin
-- channel A
IF AVol(4)='1' THEN
Alog <= HVollog(9 downto 0);
ELSE
Alog <= AVollog;
END IF;
IF rising_edge(cpuclk) THEN
IF ((enable(3) AND Noisebit) XOR Anot)='1' THEN
chanA <= ('0'&Alog);
ELSE
chanA <= (others => '0');
END IF;
IF enable(0)='0' OR APeriode="000000000000" THEN
Anot <= '1';
ACount <= "000000000000";
ELSIF S_Tick='1' THEN
IF ACount(11 downto 0)>=APeriode THEN
ACount <= "000000000001";
Anot <= NOT Anot;
ELSE
ACount <= ACount+1;
END IF;
END IF;
END IF;
-- channel B
IF BVol(4)='1' THEN
Blog <= HVollog(9 downto 0);
ELSE
Blog <= BVollog;
END IF;
IF rising_edge(cpuclk) THEN
IF ((enable(4) AND Noisebit) XOR Bnot)='1' THEN
chanB <= ('0'&Blog);
ELSE
chanB <= (others => '0');
END IF;
IF enable(1)='0' OR BPeriode="000000000000" THEN
Bnot <= '1';
BCount <= "000000000000";
ELSIF S_Tick='1' THEN
IF BCount(11 downto 0)>=BPeriode THEN
BCount <= "000000000001";
Bnot <= NOT Bnot;
ELSE
BCount <= BCount+1;
END IF;
END IF;
END IF;
-- channel C
IF CVol(4)='1' THEN
Clog <= HVollog(9 downto 0);
ELSE
Clog <= CVollog;
END IF;
IF rising_edge(cpuclk) THEN
IF ((enable(5) AND Noisebit) XOR Cnot)='1' THEN
chanC <= ('0'&Clog);
ELSE
chanC <= (others => '0');
END IF;
IF enable(2)='0' OR CPeriode="000000000000" THEN
Cnot <= '1';
CCount <= "000000000000";
ELSIF S_Tick='1' THEN
IF CCount(11 downto 0)>=CPeriode THEN
CCount <= "000000000001";
Cnot <= NOT Cnot;
ELSE
CCount <= CCount+1;
END IF;
END IF;
END IF;
--noise
--Noise="00000" and Noise="00001" is the same
IF rising_edge(cpuclk) THEN
IF S_Tick='1' THEN
IF NCount(4 downto 1)="0000" THEN
NCount <= Noise ;
RNG <= (NOT (RNG(0) XOR RNG(2))& RNG(16 downto 1));
Noisebit <= RNG(0);
ELSE
NCount <= NCount-1;
END IF;
END IF;
END IF;
-- Huellkurve
nHVol <= HVol(3 downto 0);
IF ((HKurve(3) OR NOT HVol(4)) AND ( NOT HKurve(2) XOR ((HKurve(1) XOR HKurve(0)) AND HVol(4))))='1' THEN
nHVol <= HVol(3 downto 0) XOR "1111";
END IF;
IF rising_edge(cpuclk) THEN
IF HStart='1' THEN
HCount <= "0000000000000001";
HVol <= "00000";
ELSIF H_Tick='1' THEN
IF HCount>=HPeriode THEN
HCount <= "0000000000000001";
IF (NOT HVol(4) OR (NOT HKurve(0) AND HKurve(3)))='1' AND (HPeriode /= 0) THEN --HOLD
-- IF (NOT HVol(4) OR (NOT HKurve(0) AND HKurve(3)))='1' THEN --HOLD
HVol <= HVol+1;
END IF;
ELSE
HCount <= HCount+1;
END IF;
END IF;
END IF;
CASE nHVol(3 downto 0) IS
WHEN "1111" => HVollog <= X"2AA"; -- Umsetzung in logarithmische Werte in ca. 3dB Schritten
WHEN "1110" => HVollog <= X"1E2"; -- für Hüllkurve
WHEN "1101" => HVollog <= X"155";
WHEN "1100" => HVollog <= X"0F1";
WHEN "1011" => HVollog <= X"0AA";
WHEN "1010" => HVollog <= X"078";
WHEN "1001" => HVollog <= X"055";
WHEN "1000" => HVollog <= X"03C";
WHEN "0111" => HVollog <= X"02A";
WHEN "0110" => HVollog <= X"01E";
WHEN "0101" => HVollog <= X"015";
WHEN "0100" => HVollog <= X"00F";
WHEN "0011" => HVollog <= X"00A";
WHEN "0010" => HVollog <= X"007";
WHEN "0001" => HVollog <= X"005";
WHEN "0000" => HVollog <= X"000";
WHEN OTHERS => null;
END CASE;
END process;
end logic;

View File

@@ -1,375 +0,0 @@
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- --
-- Copyright (c) 2005-2009 Tobias Gubener --
-- Subdesign CPC T-REX by TobiFlex --
-- --
-- This source file 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 source file 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. --
-- --
-- You should have received a copy of the GNU General Public License --
-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
-- --
------------------------------------------------------------------------------
------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ay8913 is
port (
cpuclk : in STD_LOGIC; --48MHz
reset : in STD_LOGIC;
cs : in STD_LOGIC; --H-aktiv
bc0 : in STD_LOGIC; --
bdir : in STD_LOGIC;
Data_in : in STD_LOGIC_VECTOR (7 downto 0);
Data_out : out STD_LOGIC_VECTOR (7 downto 0);
chanA : buffer STD_LOGIC_VECTOR (10 downto 0);
chanB : buffer STD_LOGIC_VECTOR (10 downto 0);
chanC : buffer STD_LOGIC_VECTOR (10 downto 0);
Arechts : out STD_LOGIC_VECTOR (15 downto 0);
Alinks : out STD_LOGIC_VECTOR (15 downto 0);
Amono : out STD_LOGIC_VECTOR (15 downto 0)
);
end ay8913;
architecture logic of ay8913 is
signal t_Data : STD_LOGIC_VECTOR (7 downto 0);
signal PSGReg : STD_LOGIC_VECTOR (3 downto 0);
signal APeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 0,1
signal BPeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 2,3
signal CPeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 4,5
signal Noise : STD_LOGIC_VECTOR (4 downto 0); --Reg 6
signal enable : STD_LOGIC_VECTOR (7 downto 0); --Reg 7
signal AVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 8
signal BVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 9
signal CVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 10
signal HPeriode : STD_LOGIC_VECTOR (15 downto 0); --Reg 11,12
signal HKurve : STD_LOGIC_VECTOR (3 downto 0); --Reg 13
signal PortA : STD_LOGIC_VECTOR (7 downto 0); --Reg 14
signal PortB : STD_LOGIC_VECTOR (7 downto 0); --Reg 15
signal AVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 8log
signal BVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 9log
signal CVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 10log
signal Alog : STD_LOGIC_VECTOR (9 downto 0);
signal Blog : STD_LOGIC_VECTOR (9 downto 0);
signal Clog : STD_LOGIC_VECTOR (9 downto 0);
signal HVollog : STD_LOGIC_VECTOR (11 downto 0);
signal ACount : STD_LOGIC_VECTOR (11 downto 0);
signal BCount : STD_LOGIC_VECTOR (11 downto 0);
signal CCount : STD_LOGIC_VECTOR (11 downto 0);
signal NCount : STD_LOGIC_VECTOR (4 downto 0);
signal HCount : STD_LOGIC_VECTOR (15 downto 0);
signal HVol : STD_LOGIC_VECTOR (4 downto 0);
signal nHVol : STD_LOGIC_VECTOR (3 downto 0);
signal HStart : STD_LOGIC;
signal Noisebit : STD_LOGIC;
signal RNG : STD_LOGIC_VECTOR (16 downto 0);
signal Anot, Bnot, Cnot : STD_LOGIC;
signal n_setreg : STD_LOGIC;
signal n_Pegel : STD_LOGIC_VECTOR (11 downto 0);
signal clockgen : STD_LOGIC_VECTOR (9 downto 0);
signal S_Tick : STD_LOGIC;
signal H_Tick : STD_LOGIC;
begin
-------------------------------------------------------------------------
--Clock gen
-------------------------------------------------------------------------
process (cpuclk, clockgen)
begin
S_Tick <= '0'; --sound
H_Tick <= '0'; --Hüllkurve
IF clockgen(9 downto 1)=0 THEN
S_Tick <= '1';
IF clockgen(0)='0' THEN
H_Tick <= '1';
END IF;
END IF;
IF rising_edge(cpuclk) THEN
Arechts <= (chanA&"00000")+('0'&chanB&"0000");
Alinks <= (chanC&"00000")+('0'&chanB&"0000");
Amono <= (chanC&"00000")+('0'&chanB&"0000")+(chanA&"00000");
IF H_Tick='1' THEN
-- clockgen <= ((48*16)-1); --48MHz
clockgen <= "1011111111"; --48MHz
ELSE
clockgen <= clockgen-1;
END IF;
END IF;
END process;
-------------------------------------------------------------------------
--IO Regs
-------------------------------------------------------------------------
process (cpuclk, reset, IO_A, PortA, PortB, Aperiode, Bperiode, Cperiode, Hperiode, AVol, BVol, CVol, Noise, HKurve, enable, Data_in, t_Data, PSGReg, bdir, bc0)
begin
IF reset='0' THEN
enable <= (others => '0');
PortA <= "11111111";
PortB <= "11111111";
ELSIF rising_edge(cpuclk) THEN
HStart <= '0';
IF bdir='1' AND bc0='1' THEN
IF Data_in(7 downto 4)="0000" THEN
PSGReg <= Data_in(3 downto 0);
END IF;
ELSE
IF bdir='1' AND bc0='0' THEN
CASE PSGReg IS
WHEN "0000" =>
APeriode(7 downto 0) <= Data_in;
WHEN "0001" =>
APeriode(11 downto 8) <= Data_in(3 downto 0);
WHEN "0010" =>
BPeriode(7 downto 0) <= Data_in;
WHEN "0011" =>
BPeriode(11 downto 8) <= Data_in(3 downto 0);
WHEN "0100" =>
CPeriode(7 downto 0) <= Data_in;
WHEN "0101" =>
CPeriode(11 downto 8) <= Data_in(3 downto 0);
WHEN "0110" =>
Noise(4 downto 0) <= Data_in(4 downto 0);
WHEN "0111" =>
enable <= Data_in XOR B"00111111";
WHEN "1000" =>
AVollog <= n_Pegel(9 downto 0);
AVol(4 downto 0) <= Data_in(4 downto 0);
WHEN "1001" =>
BVollog <= n_Pegel(9 downto 0);
BVol(4 downto 0) <= Data_in(4 downto 0);
WHEN "1010" =>
CVollog <= n_Pegel(9 downto 0);
CVol(4 downto 0) <= Data_in(4 downto 0);
WHEN "1011" =>
HPeriode(7 downto 0) <= Data_in;
WHEN "1100" =>
HPeriode(15 downto 8) <= Data_in;
WHEN "1101" =>
HStart <= '1';
HKurve(3 downto 0) <= Data_in(3 downto 0);
WHEN "1110" =>
PortA <= Data_in;
WHEN "1111" =>
PortB <= Data_in;
WHEN OTHERS => null;
END CASE;
END IF;
END IF;
END IF;
CASE Data_in(3 downto 0) IS
WHEN "1111" => n_Pegel <= X"2AA"; -- Umsetzung in logarithmische Werte in ca. 3dB Schritten
WHEN "1110" => n_Pegel <= X"1E2"; -- für Kanäle
WHEN "1101" => n_Pegel <= X"155";
WHEN "1100" => n_Pegel <= X"0F1";
WHEN "1011" => n_Pegel <= X"0AA";
WHEN "1010" => n_Pegel <= X"078";
WHEN "1001" => n_Pegel <= X"055";
WHEN "1000" => n_Pegel <= X"03C";
WHEN "0111" => n_Pegel <= X"02A";
WHEN "0110" => n_Pegel <= X"01E";
WHEN "0101" => n_Pegel <= X"015";
WHEN "0100" => n_Pegel <= X"00F";
WHEN "0011" => n_Pegel <= X"00A";
WHEN "0010" => n_Pegel <= X"007";
WHEN "0001" => n_Pegel <= X"005";
WHEN "0000" => n_Pegel <= X"000";
WHEN OTHERS => null;
END CASE;
-- read reg
IF bc0='1' AND bdir='0' THEN
Data_out <= t_Data;
ELSE
Data_out <= "11111111";
END IF;
t_Data <= "00000000";
CASE PSGReg IS
WHEN "0000" =>
t_Data <= Aperiode(7 downto 0);
WHEN "0001" =>
t_Data(3 downto 0) <= Aperiode(11 downto 8);
WHEN "0010" =>
t_Data <= Bperiode(7 downto 0);
WHEN "0011" =>
t_Data(3 downto 0) <= Bperiode(11 downto 8);
WHEN "0100" =>
t_Data <= Cperiode(7 downto 0);
WHEN "0101" =>
t_Data(3 downto 0) <= Cperiode(11 downto 8);
WHEN "0110" =>
t_Data(4 downto 0) <= Noise;
WHEN "0111" =>
t_Data <= enable XOR "00111111";
WHEN "1000" =>
t_Data(4 downto 0) <= AVol;
WHEN "1001" =>
t_Data(4 downto 0) <= BVol;
WHEN "1010" =>
t_Data(4 downto 0) <= CVol;
WHEN "1011" =>
t_Data <= Hperiode(7 downto 0);
WHEN "1100" =>
t_Data <= Hperiode(15 downto 8);
WHEN "1101" =>
t_Data(3 downto 0) <= HKurve;
WHEN "1110" =>
t_Data <= PortA;
WHEN "1111" =>
t_Data <= PortB;
END CASE;
END process;
-------------------------------------------------------------------------
--Soundgen
-------------------------------------------------------------------------
process (cpuclk, reset, AVol, BVol, CVol, HVol, nHVol, AVollog, BVollog, CVollog, HVollog, HKurve)
begin
-- channel A
IF AVol(4)='1' THEN
Alog <= HVollog(9 downto 0);
ELSE
Alog <= AVollog;
END IF;
IF rising_edge(cpuclk) THEN
IF ((enable(3) AND Noisebit) XOR Anot)='1' THEN
chanA <= ('0'&Alog);
ELSE
chanA <= (others => '0');
END IF;
IF enable(0)='0' OR APeriode="000000000000" THEN
Anot <= '1';
ACount <= "000000000000";
ELSIF S_Tick='1' THEN
IF ACount(11 downto 0)>=APeriode THEN
ACount <= "000000000001";
Anot <= NOT Anot;
ELSE
ACount <= ACount+1;
END IF;
END IF;
END IF;
-- channel B
IF BVol(4)='1' THEN
Blog <= HVollog(9 downto 0);
ELSE
Blog <= BVollog;
END IF;
IF rising_edge(cpuclk) THEN
IF ((enable(4) AND Noisebit) XOR Bnot)='1' THEN
chanB <= ('0'&Blog);
ELSE
chanB <= (others => '0');
END IF;
IF enable(1)='0' OR BPeriode="000000000000" THEN
Bnot <= '1';
BCount <= "000000000000";
ELSIF S_Tick='1' THEN
IF BCount(11 downto 0)>=BPeriode THEN
BCount <= "000000000001";
Bnot <= NOT Bnot;
ELSE
BCount <= BCount+1;
END IF;
END IF;
END IF;
-- channel C
IF CVol(4)='1' THEN
Clog <= HVollog(9 downto 0);
ELSE
Clog <= CVollog;
END IF;
IF rising_edge(cpuclk) THEN
IF ((enable(5) AND Noisebit) XOR Cnot)='1' THEN
chanC <= ('0'&Clog);
ELSE
chanC <= (others => '0');
END IF;
IF enable(2)='0' OR CPeriode="000000000000" THEN
Cnot <= '1';
CCount <= "000000000000";
ELSIF S_Tick='1' THEN
IF CCount(11 downto 0)>=CPeriode THEN
CCount <= "000000000001";
Cnot <= NOT Cnot;
ELSE
CCount <= CCount+1;
END IF;
END IF;
END IF;
--noise
--Noise="00000" and Noise="00001" is the same
IF rising_edge(cpuclk) THEN
IF S_Tick='1' THEN
IF NCount(4 downto 1)="0000" THEN
NCount <= Noise ;
RNG <= (NOT (RNG(0) XOR RNG(2))& RNG(16 downto 1));
Noisebit <= RNG(0);
ELSE
NCount <= NCount-1;
END IF;
END IF;
END IF;
-- Huellkurve
nHVol <= HVol(3 downto 0);
IF ((HKurve(3) OR NOT HVol(4)) AND ( NOT HKurve(2) XOR ((HKurve(1) XOR HKurve(0)) AND HVol(4))))='1' THEN
nHVol <= HVol(3 downto 0) XOR "1111";
END IF;
IF rising_edge(cpuclk) THEN
IF HStart='1' THEN
HCount <= "0000000000000001";
HVol <= "00000";
ELSIF H_Tick='1' THEN
IF HCount>=HPeriode THEN
HCount <= "0000000000000001";
IF (NOT HVol(4) OR (NOT HKurve(0) AND HKurve(3)))='1' AND (HPeriode /= 0) THEN --HOLD
-- IF (NOT HVol(4) OR (NOT HKurve(0) AND HKurve(3)))='1' THEN --HOLD
HVol <= HVol+1;
END IF;
ELSE
HCount <= HCount+1;
END IF;
END IF;
END IF;
CASE nHVol(3 downto 0) IS
WHEN "1111" => HVollog <= X"2AA"; -- Umsetzung in logarithmische Werte in ca. 3dB Schritten
WHEN "1110" => HVollog <= X"1E2"; -- für Hüllkurve
WHEN "1101" => HVollog <= X"155";
WHEN "1100" => HVollog <= X"0F1";
WHEN "1011" => HVollog <= X"0AA";
WHEN "1010" => HVollog <= X"078";
WHEN "1001" => HVollog <= X"055";
WHEN "1000" => HVollog <= X"03C";
WHEN "0111" => HVollog <= X"02A";
WHEN "0110" => HVollog <= X"01E";
WHEN "0101" => HVollog <= X"015";
WHEN "0100" => HVollog <= X"00F";
WHEN "0011" => HVollog <= X"00A";
WHEN "0010" => HVollog <= X"007";
WHEN "0001" => HVollog <= X"005";
WHEN "0000" => HVollog <= X"000";
WHEN OTHERS => null;
END CASE;
END process;
end logic;

View File

@@ -1,477 +0,0 @@
/* Atari on an FPGA
Masters of Engineering Project
Cornell University, 2007
Daniel Beer
TIA.v
Redesign of the Atari TIA chip. Provides the Atari with video generation,
sound generation and I/O.
*/
`timescale 1ns / 1ps
`include "tia.vh"
module TIA(A, // Address bus input
Din, // Data bus input
Dout, // Data bus output
CS_n, // Active low chip select input
CS, // Chip select input
R_W_n, // Active low read/write input
RDY, // CPU ready output
MASTERCLK, // 3.58 Mhz pixel clock input
CLK2, // 1.19 Mhz bus clock input
idump_in, // Dumped I/O
Ilatch, // Latched I/O
HSYNC, // Video horizontal sync output
HBLANK, // Video horizontal blank output
VSYNC, // Video vertical sync output
VBLANK, // Video vertical sync output
COLOROUT, // Indexed color output
RES_n, // Active low reset input
AUD0, //audio pin 0
AUD1, //audio pin 1
audv0, //audio volume for use with external xformer module
audv1); //audio volume for use with external xformer module
input [5:0] A;
input [7:0] Din;
output [7:0] Dout;
input [2:0] CS_n;
input CS;
input R_W_n;
output RDY;
input MASTERCLK;
input CLK2;
input [1:0] Ilatch;
input [3:0] idump_in;
output HSYNC, HBLANK;
output VSYNC, VBLANK;
output [7:0] COLOROUT;
input RES_n;
output AUD0, AUD1;
output reg [3:0] audv0, audv1;
// Data output register
reg [7:0] Dout;
// Video control signal registers
wire HSYNC;
reg VSYNC, VBLANK;
// Horizontal pixel counter
reg [7:0] hCount;
reg [3:0] hCountReset;
reg clk_30;
reg [7:0] clk_30_count;
wire [3:0] Idump;
// Pixel counter update
always @(posedge MASTERCLK)
begin
// Reset operation
if (~RES_n) begin
hCount <= 8'd0;
hCountReset[3:1] <= 3'd0;
clk_30 <= 0;
clk_30_count <= 0;
latchedInputs <= 2'b11;
end
else begin
if (inputLatchReset)
latchedInputs <= 2'b11;
else
latchedInputs <= latchedInputs & Ilatch;
if (clk_30_count == 57) begin
clk_30 <= ~clk_30;
clk_30_count <= 0;
end else begin
clk_30_count <= clk_30_count + 1;
end
// Increment the count and reset if necessary
if ((hCountReset[3]) ||(hCount == 8'd227))
hCount <= 8'd0;
else
hCount <= hCount + 8'd1;
// Software resets are delayed by three cycles
hCountReset[3:1] <= hCountReset[2:0];
end
end
assign HSYNC = (hCount >= 8'd20) && (hCount < 8'd36);
assign HBLANK = (hCount < 8'd68);
// Screen object registers
// These registers are set by the software and used to generate pixels
reg [7:0] player0Pos, player1Pos, missile0Pos, missile1Pos, ballPos;
reg [4:0] player0Size, player1Size;
reg [7:0] player0Color, player1Color, ballColor, pfColor, bgColor;
reg [3:0] player0Motion, player1Motion, missile0Motion, missile1Motion,
ballMotion;
reg missile0Enable, missile1Enable, ballEnable, R_ballEnable;
reg [1:0] ballSize;
reg [19:0] pfGraphic;
reg [7:0] player0Graphic, player1Graphic;
reg [7:0] R_player0Graphic, R_player1Graphic;
reg pfReflect, player0Reflect, player1Reflect;
reg prioCtrl;
reg pfColorCtrl;
reg [14:0] collisionLatch;
reg missile0Lock, missile1Lock;
reg player0VertDelay, player1VertDelay, ballVertDelay;
reg [3:0] audc0, audc1;
reg [4:0] audf0, audf1;
// Pixel number calculation
wire [7:0] pixelNum;
//audio control
audio audio_ctrl(.AUDC0(audc0),
.AUDC1(audc1),
.AUDF0(audf0),
.AUDF1(audf1),
.CLK_30(clk_30), //30khz clock
.AUD0(AUD0),
.AUD1(AUD1));
assign pixelNum = (hCount >= 8'd68) ? (hCount - 8'd68) : 8'd227;
// Pixel tests. For each pixel and screen object, a test is done based on the
// screen objects register to determine if the screen object should show on that
// pixel. The results of all the tests are fed into logic to pick which displayed
// object has priority and color the pixel the color of that object.
// Playfield pixel test
wire [5:0] pfPixelNum;
wire pfPixelOn, pfLeftPixelVal, pfRightPixelVal;
assign pfPixelNum = pixelNum[7:2];
assign pfLeftPixelVal = pfGraphic[pfPixelNum];
assign pfRightPixelVal = (pfReflect == 1'b0)? pfGraphic[pfPixelNum - 6'd20]:
pfGraphic[6'd39 - pfPixelNum];
assign pfPixelOn = (pfPixelNum < 6'd20)? pfLeftPixelVal : pfRightPixelVal;
// Player 0 sprite pixel test
wire pl0PixelOn;
wire [7:0] pl0Mask, pl0MaskDel;
assign pl0MaskDel = (player0VertDelay)? R_player0Graphic : player0Graphic;
assign pl0Mask = (!player0Reflect)? pl0MaskDel : {pl0MaskDel[0], pl0MaskDel[1],
pl0MaskDel[2], pl0MaskDel[3],
pl0MaskDel[4], pl0MaskDel[5],
pl0MaskDel[6], pl0MaskDel[7]};
objPixelOn player0_test(pixelNum, player0Pos, player0Size[2:0], pl0Mask, pl0PixelOn);
// Player 1 sprite pixel test
wire pl1PixelOn;
wire [7:0] pl1Mask, pl1MaskDel;
assign pl1MaskDel = (player1VertDelay)? R_player1Graphic : player1Graphic;
assign pl1Mask = (!player1Reflect)? pl1MaskDel : {pl1MaskDel[0], pl1MaskDel[1],
pl1MaskDel[2], pl1MaskDel[3],
pl1MaskDel[4], pl1MaskDel[5],
pl1MaskDel[6], pl1MaskDel[7]};
objPixelOn player1_test(pixelNum, player1Pos, player1Size[2:0], pl1Mask, pl1PixelOn);
// Missile 0 pixel test
wire mis0PixelOn, mis0PixelOut;
wire [7:0] mis0ActualPos;
reg [7:0] mis0Mask;
always @(player0Size)
begin
case(player0Size[4:3])
2'd0: mis0Mask <= 8'h01;
2'd1: mis0Mask <= 8'h03;
2'd2: mis0Mask <= 8'h0F;
2'd3: mis0Mask <= 8'hFF;
endcase
end
assign mis0ActualPos = (missile0Lock)? player0Pos : missile0Pos;
objPixelOn missile0_test(pixelNum, mis0ActualPos, player0Size[2:0], mis0Mask, mis0PixelOut);
assign mis0PixelOn = mis0PixelOut && missile0Enable;
// Missile 1 pixel test
wire mis1PixelOn, mis1PixelOut;
wire [7:0] mis1ActualPos;
reg [7:0] mis1Mask;
always @(player1Size)
begin
case(player1Size[4:3])
2'd0: mis1Mask <= 8'h01;
2'd1: mis1Mask <= 8'h03;
2'd2: mis1Mask <= 8'h0F;
2'd3: mis1Mask <= 8'hFF;
endcase
end
assign mis1ActualPos = (missile1Lock)? player1Pos : missile1Pos;
objPixelOn missile1_test(pixelNum, mis1ActualPos, player1Size[2:0], mis1Mask, mis1PixelOut);
assign mis1PixelOn = mis1PixelOut && missile1Enable;
// Ball pixel test
wire ballPixelOut, ballPixelOn, ballEnableDel;
reg [7:0] ballMask;
always @(ballSize)
begin
case(ballSize)
2'd0: ballMask <= 8'h01;
2'd1: ballMask <= 8'h03;
2'd2: ballMask <= 8'h0F;
2'd3: ballMask <= 8'hFF;
endcase
end
objPixelOn ball_test(pixelNum, ballPos, 3'd0, ballMask, ballPixelOut);
assign ballEnableDel = ((ballVertDelay)? R_ballEnable : ballEnable);
assign ballPixelOn = ballPixelOut && ballEnableDel;
// Playfield color selection
// The programmer can select a unique color for the playfield or have it match
// the player's sprites colors
reg [7:0] pfActualColor;
always @(pfColorCtrl, pfColor, player0Color, player1Color, pfPixelNum)
begin
if (pfColorCtrl)
begin
if (pfPixelNum < 6'd20)
pfActualColor <= player0Color;
else
pfActualColor <= player1Color;
end
else
pfActualColor <= pfColor;
end
// Final pixel color selection
reg [7:0] pixelColor;
assign COLOROUT = (HBLANK)? 8'b0 : pixelColor;
// This combinational logic uses a priority encoder like structure to select
// the highest priority screen object and color the pixel.
always @(prioCtrl, pfPixelOn, pl0PixelOn, pl1PixelOn, mis0PixelOn, mis1PixelOn,
ballPixelOn, pfActualColor, player0Color, player1Color, bgColor)
begin
// Show the playfield behind the players
if (!prioCtrl)
begin
if (pl0PixelOn || mis0PixelOn)
pixelColor <= player0Color;
else if (pl1PixelOn || mis1PixelOn)
pixelColor <= player1Color;
else if (pfPixelOn)
pixelColor <= pfActualColor;
else
pixelColor <= bgColor;
end
// Otherwise, show the playfield in front of the players
else begin
if (pfPixelOn)
pixelColor <= pfActualColor;
else if (pl0PixelOn || mis0PixelOn)
pixelColor <= player0Color;
else if (pl1PixelOn || mis1PixelOn)
pixelColor <= player1Color;
else
pixelColor <= bgColor;
end
end
// Collision register and latching update
wire [14:0] collisions;
reg collisionLatchReset;
assign collisions = {pl0PixelOn && pl1PixelOn, mis0PixelOn && mis1PixelOn,
ballPixelOn && pfPixelOn,
mis1PixelOn && pfPixelOn, mis1PixelOn && ballPixelOn,
mis0PixelOn && pfPixelOn, mis0PixelOn && ballPixelOn,
pl1PixelOn && pfPixelOn, pl1PixelOn && ballPixelOn,
pl0PixelOn && pfPixelOn, pl0PixelOn && ballPixelOn,
mis1PixelOn && pl0PixelOn, mis1PixelOn && pl1PixelOn,
mis0PixelOn && pl1PixelOn, mis0PixelOn && pl0PixelOn};
always @(posedge MASTERCLK, posedge collisionLatchReset)
begin
if (collisionLatchReset)
collisionLatch <= 15'b000000000000000;
else
collisionLatch <= collisionLatch | collisions;
end
// WSYNC logic
// When a WSYNC is signalled by the programmer, the CPU ready line is lowered
// until the end of a scanline
reg wSync, wSyncReset;
always @(hCount, wSyncReset)
begin
if (hCount == 8'd0)
wSync <= 1'b0;
else if (wSyncReset && hCount > 8'd2)
wSync <= 1'b1;
end
assign RDY = ~wSync;
// Latched input registers and update
wire [1:0] latchedInputsValue;
reg inputLatchEnabled;
reg inputLatchReset;
reg [1:0] latchedInputs;
/*always_ff @(Ilatch, inputLatchReset)
begin
if (inputLatchReset)
latchedInputs <= 2'b11;
else
latchedInputs <= latchedInputs & Ilatch;
end*/
assign latchedInputsValue = (inputLatchEnabled)? latchedInputs : Ilatch;
// Dumped input registers update
reg inputDumpEnabled;
assign Idump = (inputDumpEnabled)? 4'b0000 : idump_in;
// Software operations
always @(posedge CLK2)
begin
// Reset operation
if (~RES_n) begin
inputLatchReset <= 1'b0;
collisionLatchReset <= 1'b0;
hCountReset[0] <= 1'b0;
wSyncReset <= 1'b0;
Dout <= 8'b00000000;
end
// If the chip is enabled, execute an operation
else if (CS) begin
// Software reset signals
inputLatchReset <= ({R_W_n, A[5:0]} == `VBLANK && Din[6] && !inputLatchEnabled);
collisionLatchReset <= ({R_W_n, A[5:0]} == `CXCLR);
hCountReset[0] <= ({R_W_n, A[5:0]} == `RSYNC);
wSyncReset <= ({R_W_n, A[5:0]} == `WSYNC) && !wSync;
case({R_W_n, A[5:0]})
// Collision latch reads
`CXM0P, `CXM0P_7800: Dout <= {collisionLatch[1:0],6'b000000};
`CXM1P, `CXM1P_7800: Dout <= {collisionLatch[3:2],6'b000000};
`CXP0FB, `CXP0FB_7800: Dout <= {collisionLatch[5:4],6'b000000};
`CXP1FB, `CXP1FB_7800: Dout <= {collisionLatch[7:6],6'b000000};
`CXM0FB, `CXM0FB_7800: Dout <= {collisionLatch[9:8],6'b000000};
`CXM1FB, `CXM1FB_7800: Dout <= {collisionLatch[11:10],6'b000000};
`CXBLPF, `CXBLPF_7800: Dout <= {collisionLatch[12],7'b0000000};
`CXPPMM, `CXPPMM_7800: Dout <= {collisionLatch[14:13],6'b000000};
// I/O reads
`INPT0, `INPT0_7800: Dout <= {Idump[0], 7'b0000000};
`INPT1, `INPT1_7800: Dout <= {Idump[1], 7'b0000000};
`INPT2, `INPT2_7800: Dout <= {Idump[2], 7'b0000000};
`INPT3, `INPT3_7800: Dout <= {Idump[3], 7'b0000000};
`INPT4, `INPT4_7800: Dout <= {latchedInputsValue[0], 7'b0000000};
`INPT5, `INPT5_7800: Dout <= {latchedInputsValue[1], 7'b0000000};
// Video signals
`VSYNC: VSYNC <= Din[1];
`VBLANK: begin
inputLatchEnabled <= Din[6];
inputDumpEnabled <= Din[7];
VBLANK <= Din[1];
end
`WSYNC:;
`RSYNC:;
// Screen object register access
`NUSIZ0: player0Size <= {Din[5:4],Din[2:0]};
`NUSIZ1: player1Size <= {Din[5:4],Din[2:0]};
`COLUP0: player0Color <= Din;
`COLUP1: player1Color <= Din;
`COLUPF: pfColor <= Din;
`COLUBK: bgColor <= Din;
`CTRLPF: begin
pfReflect <= Din[0];
pfColorCtrl <= Din[1];
prioCtrl <= Din[2];
ballSize <= Din[5:4];
end
`REFP0: player0Reflect <= Din[3];
`REFP1: player1Reflect <= Din[3];
`PF0: pfGraphic[3:0] <= Din[7:4];
`PF1: pfGraphic[11:4] <= {Din[0], Din[1], Din[2], Din[3],
Din[4], Din[5], Din[6], Din[7]};
`PF2: pfGraphic[19:12] <= Din[7:0];
`RESP0: player0Pos <= pixelNum;
`RESP1: player1Pos <= pixelNum;
`RESM0: missile0Pos <= pixelNum;
`RESM1: missile1Pos <= pixelNum;
`RESBL: ballPos <= pixelNum;
// Audio controls
`AUDC0: audc0 <= Din[3:0];
`AUDC1: audc1 <= Din[3:0];
`AUDF0: audf0 <= Din[4:0];
`AUDF1: audf1 <= Din[4:0];
`AUDV0: audv0 <= Din[3:0];
`AUDV1: audv1 <= Din[3:0];
// Screen object register access
`GRP0: begin
player0Graphic <= {Din[0], Din[1], Din[2], Din[3],
Din[4], Din[5], Din[6], Din[7]};
R_player1Graphic <= player1Graphic;
end
`GRP1: begin
player1Graphic <= {Din[0], Din[1], Din[2], Din[3],
Din[4], Din[5], Din[6], Din[7]};
R_player0Graphic <= player0Graphic;
R_ballEnable <= ballEnable;
end
`ENAM0: missile0Enable <= Din[1];
`ENAM1: missile1Enable <= Din[1];
`ENABL: ballEnable <= Din[1];
`HMP0: player0Motion <= Din[7:4];
`HMP1: player1Motion <= Din[7:4];
`HMM0: missile0Motion <= Din[7:4];
`HMM1: missile1Motion <= Din[7:4];
`HMBL: ballMotion <= Din[7:4];
`VDELP0: player0VertDelay <= Din[0];
`VDELP1: player1VertDelay <= Din[0];
`VDELBL: ballVertDelay <= Din[0];
`RESMP0: missile0Lock <= Din[1];
`RESMP1: missile1Lock <= Din[1];
// Strobed line that initiates an object move
`HMOVE: begin
player0Pos <= player0Pos - {{4{player0Motion[3]}},
player0Motion[3:0]};
player1Pos <= player1Pos - {{4{player1Motion[3]}},
player1Motion[3:0]};
missile0Pos <= missile0Pos - {{4{missile0Motion[3]}},
missile0Motion[3:0]};
missile1Pos <= missile1Pos - {{4{missile1Motion[3]}},
missile1Motion[3:0]};
ballPos <= ballPos - {{4{ballMotion[3]}},ballMotion[3:0]};
end
// Motion register clear
`HMCLR: begin
player0Motion <= Din[7:4];
player1Motion <= Din[7:4];
missile0Motion <= Din[7:4];
missile1Motion <= Din[7:4];
ballMotion <= Din[7:4];
end
`CXCLR:;
default: Dout <= 8'b00000000;
endcase
end
// If the chip is not enabled, do nothing
else begin
inputLatchReset <= 1'b0;
collisionLatchReset <= 1'b0;
hCountReset[0] <= 1'b0;
wSyncReset <= 1'b0;
Dout <= 8'b00000000;
end
end
endmodule
// objPixelOn module
// Checks the pixel number against a stretched and possibly duplicated version of the
// object.
module objPixelOn(pixelNum, objPos, objSize, objMask, pixelOn);
input [7:0] pixelNum, objPos, objMask;
input [2:0] objSize;
output pixelOn;
wire [7:0] objIndex;
wire [8:0] objByteIndex;
wire objMaskOn, objPosOn;
reg objSizeOn;
reg [2:0] objMaskSel;
assign objIndex = pixelNum - objPos - 8'd1;
assign objByteIndex = 9'b1 << (objIndex[7:3]);
always @(objSize, objByteIndex)
begin
case (objSize)
3'd0: objSizeOn <= (objByteIndex & 9'b00000001) != 0;
3'd1: objSizeOn <= (objByteIndex & 9'b00000101) != 0;
3'd2: objSizeOn <= (objByteIndex & 9'b00010001) != 0;
3'd3: objSizeOn <= (objByteIndex & 9'b00010101) != 0;
3'd4: objSizeOn <= (objByteIndex & 9'b10000001) != 0;
3'd5: objSizeOn <= (objByteIndex & 9'b00000011) != 0;
3'd6: objSizeOn <= (objByteIndex & 9'b10010001) != 0;
3'd7: objSizeOn <= (objByteIndex & 9'b00001111) != 0;
endcase
end
always @(objSize, objIndex)
begin
case (objSize)
3'd5: objMaskSel <= objIndex[3:1];
3'd7: objMaskSel <= objIndex[4:2];
default: objMaskSel <= objIndex[2:0];
endcase
end
assign objMaskOn = objMask[objMaskSel];
assign objPosOn = (pixelNum > objPos) && ({1'b0, pixelNum} <= {1'b0, objPos} + 9'd72);
assign pixelOn = objSizeOn && objMaskOn && objPosOn;
endmodule

View File

@@ -1,137 +0,0 @@
-- Copyright (c) 2015, $ME
-- All rights reserved.
--
-- Redistribution and use in source and synthezised forms, with or without modification, are permitted
-- provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions
-- and the following disclaimer.
--
-- 2. Redistributions in synthezised form must reproduce the above copyright notice, this list of conditions
-- and the following disclaimer in the documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
-- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
--
-- implementation of a z80 ctc
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity ctc is
generic (
sysclk : integer := 500000; -- 50MHz
ctcclk : integer := 24576 -- 2.4576MHz
);
port (
clk : in std_logic;
res_n : in std_logic; -- negative
en : in std_logic; -- negative
dIn : in std_logic_vector(7 downto 0);
dOut : out std_logic_vector(7 downto 0);
cs : in std_logic_vector(1 downto 0);
m1_n : in std_logic; -- negative
iorq_n : in std_logic; -- negative
rd_n : in std_logic; -- negative
int : out std_logic_vector(3 downto 0);
intAck : in std_logic_vector(3 downto 0);
clk_trg : in std_logic_vector(3 downto 0);
zc_to : out std_logic_vector(3 downto 0);
kcSysClk : out std_logic
);
end ctc;
architecture rtl of ctc is
type byteArray is array (natural range <>) of std_logic_vector(7 downto 0);
signal clkCounter : integer range 0 to sysclk+ctcclk-1 := 0;
signal ctcClkEn : std_logic := '0';
signal cEn : std_logic_vector(3 downto 0);
signal cDOut : byteArray(3 downto 0);
signal cSetTC : std_logic_vector(3 downto 0);
signal setTC : std_logic;
signal irqVect : std_logic_vector(7 downto 3) := (others => '0');
signal intAckChannel : std_logic_vector(1 downto 0);
begin
kcSysClk <= ctcClkEn;
intAckChannel <=
"00" when intAck(0)='1' else
"01" when intAck(1)='1' else
"10" when intAck(2)='1' else
"11";
dOut <=
irqVect & intAckChannel & "0" when intAck/="0000" else -- int acknowledge
cDOut(0) when cEn(0)='1' else
cDOut(1) when cEn(1)='1' else
cDOut(2) when cEn(2)='1' else
cDOut(3);
setTC <=
cSetTC(0) when cs="00" else
cSetTC(1) when cs="01" else
cSetTC(2) when cs="10" else
cSetTC(3);
-- generate clock for ctc timer
clkGen : process
begin
wait until rising_edge(clk);
if (clkCounter>=sysclk-ctcclk) then
clkCounter <= clkCounter - sysclk + ctcclk;
ctcClkEn <= '1';
else
clkCounter <= clkCounter + ctcclk;
ctcClkEn <= '0';
end if;
end process;
cpuInt : process
begin
wait until rising_edge(clk);
if (en='0' and rd_n='1' and iorq_n='0' and m1_n='1' and dIn(0)='0' and setTC='0') then -- set irq vector
irqVect <= dIn(7 downto 3);
end if;
end process;
channels: for i in 0 to 3 generate
channel : entity work.ctc_channel
port map (
clk => clk,
res_n => res_n,
en => cEn(i),
dIn => dIn,
dOut => cDOut(i),
rd_n => rd_n,
int => int(i),
setTC => cSetTC(i),
ctcClkEn => ctcClkEn,
clk_trg => clk_trg(i),
zc_to => zc_to(i)
);
cEn(i) <= '1' when (en='0' and iorq_n='0' and m1_n='1' and to_integer(unsigned(cs))=i) else '0';
end generate;
end;

View File

@@ -1,172 +0,0 @@
-- Copyright (c) 2015, $ME
-- All rights reserved.
--
-- Redistribution and use in source and synthezised forms, with or without modification, are permitted
-- provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions
-- and the following disclaimer.
--
-- 2. Redistributions in synthezised form must reproduce the above copyright notice, this list of conditions
-- and the following disclaimer in the documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
-- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
--
-- single ctc channel
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity ctc_channel is
port (
clk : in std_logic;
res_n : in std_logic;
en : in std_logic;
dIn : in std_logic_vector(7 downto 0);
dOut : out std_logic_vector(7 downto 0);
rd_n : in std_logic;
int : out std_logic;
setTC : out std_logic;
ctcClkEn : in std_logic;
clk_trg : in std_logic;
zc_to : out std_logic
);
end ctc_channel;
architecture rtl of ctc_channel is
type states is (default, setTimeConstant);
signal state : states := default;
signal nextState : states := default;
signal control : std_logic_vector(7 downto 3) := (others => '0');
signal preDivider : integer range 0 to 255 := 0;
signal preDivVect : std_logic_vector(7 downto 0);
signal edgeDet : std_logic_vector(1 downto 0);
signal dCounter : integer range 0 to 256 := 0;
signal timeConstant : integer range 1 to 256 := 256;
signal triggerIrq : boolean := false;
signal running : boolean := false;
signal startUp : boolean := true;
begin
setTC <= '1' when state=setTimeConstant else '0';
dOut <= std_logic_vector(to_unsigned(dCounter, dOut'length)); -- CTC Read
int <= '1' when triggerIrq and control(7)='1' else '0';
-- zc_to <= '1' when control(7)='1' else '0';
-- zc_to <= edgeDet(1);
preDivVect <= std_logic_vector(to_unsigned(preDivider, preDivVect'length));
-- ctc counter
counter : process
variable cntrEvent : boolean;
begin
wait until rising_edge(clk);
if (ctcClkEn='1') then
if (preDivider=255) then
preDivider <= 0;
else
preDivider <= preDivider + 1;
end if;
end if;
-- edgeDetector
if (control(6 downto 5)="00") then -- Timer mode + Prescaler 16
edgeDet(0) <= preDivVect(3);
elsif (control(6 downto 5)="01") then -- Timer mode + Prescaler 256
edgeDet(0) <= preDivVect(7);
else -- Counter mode
edgeDet(0) <= clk_trg;
end if;
edgeDet(1) <= edgeDet(0);
triggerIrq <= false;
cntrEvent := false;
if (running) then
if (edgeDet="01") then
cntrEvent := true;
end if;
if (startUp) then
startUp <= false;
dCounter <= timeConstant;
elsif (cntrEvent) then
if (dCounter = 1) then -- next count 0 => reload
dCounter <= timeConstant;
triggerIrq <= true;
zc_to <= '1';
else
dCounter <= dCounter - 1;
zc_to <= '0';
end if;
end if;
else
edgeDet <= (others => '0');
startUp <= true;
dCounter <= 0;
preDivider <= 0;
triggerIrq <= false;
zc_to <= '0';
end if;
end process;
-- cpu-interface
cpu : process
variable tcData : integer range 0 to 255;
begin
wait until rising_edge(clk);
if (res_n='0') then
nextState <= default;
running <= false;
timeConstant <= 256;
elsif (en='1') then
if (rd_n='1') then -- CTC Write
if (state=setTimeConstant) then -- set Time Constant
nextState <= default;
running <= true;
tcData := to_integer(unsigned(dIn));
if (tcData=0) then
timeConstant <= 256;
else
timeConstant <= to_integer(unsigned(dIn));
end if;
elsif (dIn(0)='1') then
control <= dIn(7 downto 3);
if (dIn(2)='1') then -- Time Constant Follows
nextState <= setTimeConstant;
end if;
if (dIn(1)='1') then -- reset
running <= false;
end if;
end if;
end if;
else
state <= nextState;
end if;
end process;
end;

View File

@@ -1,11 +0,0 @@
The files available in this directory were created by me and I claim ownership
and copyright. I grant to anyone and everyone the right to download, use, modify
and redistribute them freely so long as this notice is included with any
redistribution, in whole or in part, whether modified or not.
All files in this directory are provided as-is for no charge. There is no
warranty, guarantee, or claim of suitability for any purpose. No offer of
support or service has been or will be made.
Peter J. Bartlett
2012

View File

@@ -1,48 +0,0 @@
This is a preliminary Verilog implemenation of a replacement for the TMS9918A
VDP. It outputs 800x600 VGA @ 60Hz, with each of the colors (R/G/B) having 4-bit
resolution. It is (insofar as I know how to make it) compatible with the
original VDP. It has a software selectable mode that allows all 32 sprites on
one line, however.
The only FPGA-specific module at this time is "vdp_clkgen" that uses an embedded
PLL to convert the 50MHz clock on my development board to 40MHz. Either replace
it with your FPGA's equivalent or simply use an external 40MHz oscillator.
At the current resolution and clock frequency, I'm using this with an external
Alliance 512KB SRAM with 55ns access time. The design has been pre-planned to
work with 25ns SRAMs at 65 MHz or more for 1024x768 SVGA resolution.
There are a number of major changes planned. For example the non-working copy of
all the sprite data, some 960 flip-flops, will be replaced by an embedded RAM.
The pattern shift registers will be greatly simplified as well.
This Verilog was written from scratch in a 2-week period, so it's not well
commented. On the bright side, it's free.
Externally, I went with a "poor man's DAC" to convert the 4-bit R/G/B signals
into 1.4V for VGA. I used an AD813 triple video op-amp in an inverting
configuration with resistors (20K, 10K, 5K, 2.5K, a clever young lad can
imagine how to do that with few parts) on the minus input, a 1K
potentiometer on the feedback path, and a 75 ohm series resistor on the
output. Works perfectly.
---
Update: all planned TMS9918 emulation changes are in. The internal RAM is 256
x 8-bit words, synchronous inputs and outputs. Making this change reduced
utilization of the (rather small) Cyclone II FPGA I'm using from 76% to 46%.
In order to enable "unlimited sprites per line" mode, set bit 0 of register 31.
I'll probably be going forward with adding features of the V9938 VDP to the
design such as 512 pixel width and 80-column text modes (using 1024x768 XVGA),
but I won't be posting any of that here since it goes beyond the scope of
recreating a historical TRS-80 peripheral device--the Mikrokolor.
Pete.
---
By the way, I don't like the way the tabs in the Verilog files got converted; they were originally 3 spaces each.
p.

View File

@@ -1,30 +0,0 @@
set_time_format -unit ns -decimal_places 3
create_clock -name {clk50m_17} -period 20.000 -waveform { 0.000 10.000 } [get_ports {clk50m_17}]
create_generated_clock -name {clkgen|altpll_component|pll|clk[0]} -source [get_pins {clkgen|altpll_component|pll|inclk[0]}] -duty_cycle 50.000 -multiply_by 4 -divide_by 5 -master_clock {clk50m_17} [get_pins {clkgen|altpll_component|pll|clk[0]}]
set_false_path -from [get_ports {cpu_a[*] cpu_d[*] cpu_in_n cpu_out_n cpu_rst_n por_73_n push_144_n}] \
-to [get_clocks {clkgen|altpll_component|pll|clk[0]}]
set_false_path -from [get_ports {cpu_a[*]}] -to [get_ports {cpu_d[*]}]
set_false_path -from [get_registers {vdp_cpu:cpu|spr_mag vdp_cpu:cpu|spr_size}] \
-to [get_registers {vdp_fsm:fsm|spr_color[*] vdp_fsm:fsm|spr_pattern vdp_fsm:fsm|spr_collide \
vdp_fsm:fsm|spr_pat[*][*] vdp_fsm:fsm|spr_xvld[*] vdp_fsm:fsm|spr_odd[*]}]
set_false_path -to [get_ports {led1_3_n led2_7_n led3_9_n}]
set_false_path -from [get_ports {push_144_n por_73_n cpu_rst_n}]
set_multicycle_path -setup -end -from [get_registers {vdp_fsm:fsm|spr_hcount[*] vdp_fsm:fsm|spr_col[*][*]}] \
-to [get_registers {vdp_fsm:fsm|spr_color[*] vdp_fsm:fsm|spr_pattern vdp_fsm:fsm|spr_collide vdp_fsm:fsm|spr_pat[*][*]}] 3
set_multicycle_path -hold -end -from [get_registers {vdp_fsm:fsm|spr_hcount[*] vdp_fsm:fsm|spr_col[*][*]}] \
-to [get_registers {vdp_fsm:fsm|spr_color[*] vdp_fsm:fsm|spr_pattern vdp_fsm:fsm|spr_collide vdp_fsm:fsm|spr_pat[*][*]}] 3
set_multicycle_path -setup -end -from [get_registers {vdp_fsm:fsm|spr_dly[*][*] vdp_fsm:fsm|spr_pat[*][*] vdp_fsm:fsm|spr_vld[*]}] \
-to [get_registers {vdp_fsm:fsm|spr_color[*] vdp_fsm:fsm|spr_pattern vdp_fsm:fsm|spr_collide vdp_fsm:fsm|spr_pat[*][*]}] 3
set_multicycle_path -hold -end -from [get_registers {vdp_fsm:fsm|spr_dly[*][*] vdp_fsm:fsm|spr_pat[*][*] vdp_fsm:fsm|spr_vld[*]}] \
-to [get_registers {vdp_fsm:fsm|spr_color[*] vdp_fsm:fsm|spr_pattern vdp_fsm:fsm|spr_collide vdp_fsm:fsm|spr_pat[*][*]}] 3
set_max_delay -from [get_clocks {clkgen|altpll_component|pll|clk[0]}] -to [get_ports {b[*] g[*] r[*] hsync vsync}] 5.000
set_max_delay -from [get_clocks {clkgen|altpll_component|pll|clk[0]}] -to [get_ports {sram_a[*] sram_d[*] sram_oe_n sram_we_n}] 5.000
set_max_delay -from [get_clocks {clkgen|altpll_component|pll|clk[0]}] -to [get_ports {cpu_int_n}] 8.000
set_max_delay -from [get_ports {sram_d[*]}] -to [get_clocks {clkgen|altpll_component|pll|clk[0]}] 3.000

View File

@@ -1,241 +0,0 @@
module vdp(
clk40m,
clk40m_n,
cpu_rst_n,
cpu_a,
cpu_din,
cpu_dout,
cpu_doe,
cpu_in_n,
cpu_out_n,
cpu_int_n,
sram_a,
sram_din,
sram_dout,
sram_doe,
sram_oe_n,
sram_we_n,
hsync,
vsync,
r,
g,
b
);
// Clocks
input clk40m;
input clk40m_n;
// CPU interface
input cpu_rst_n;
input [ 7 : 0 ] cpu_a;
input [ 7 : 0 ] cpu_din;
output [ 7 : 0 ] cpu_dout;
output cpu_doe;
input cpu_in_n;
input cpu_out_n;
output cpu_int_n;
// SRAM interface
output [ 18 : 0 ] sram_a;
input [ 7 : 0 ] sram_din;
output [ 7 : 0 ] sram_dout;
output sram_doe;
output sram_oe_n;
output sram_we_n;
// VGA interface
output hsync; // Horizontal sync
output vsync; // Vertical sync
output [ 3 : 0 ] r;
output [ 3 : 0 ] g;
output [ 3 : 0 ] b;
// VDP I/O ports.
parameter [ 7 : 0 ] cpu_vram_port = 8'h01;
parameter [ 7 : 0 ] cpu_vdp_port = 8'h02;
wire rst_n;
wire vram_cpu_req;
wire vram_cpu_ack;
wire vram_cpu_wr;
wire vram_ack;
wire [ 13 : 0 ] vram_cpu_a;
wire [ 7 : 0 ] vram_cpu_rdata;
wire [ 7 : 0 ] vram_rdata;
wire g1_mode;
wire g2_mode;
wire multi_mode;
wire text_mode;
wire gmode;
wire blank_n;
wire spr_size;
wire spr_mag;
wire [ 3 : 0 ] ntb;
wire [ 7 : 0 ] colb;
wire [ 2 : 0 ] pgb;
wire [ 6 : 0 ] sab;
wire [ 2 : 0 ] spgb;
wire [ 3 : 0 ] color1;
wire [ 3 : 0 ] color0;
wire visible;
wire border;
wire start_vblank;
wire set_mode;
wire vram_req;
wire vram_wr;
wire [ 13 : 0 ] vram_addr;
wire [ 7 : 0 ] pattern;
wire [ 7 : 0 ] color;
wire load;
wire [ 3 : 0 ] color_1;
wire [ 3 : 0 ] color_0;
wire pixel;
wire spr_pattern;
wire [ 3 : 0 ] spr_color;
wire spr_collide;
wire spr_5;
wire [ 4 : 0 ] spr_5num;
wire spr_nolimit;
assign rst_n = cpu_rst_n;
assign sram_a[ 18 : 14 ] = 5'b00000;
vdp_colormap colormap(
clk40m,
rst_n,
visible,
border,
pixel,
color_1,
color_0,
color0,
spr_pattern,
spr_color,
r,
g,
b
);
vdp_shift shift(
clk40m,
rst_n,
pattern,
color,
color1,
color0,
load,
text_mode,
color_1,
color_0,
pixel
);
vdp_fsm fsm(
clk40m,
rst_n,
g1_mode,
g2_mode,
multi_mode,
gmode,
text_mode,
spr_size,
spr_mag,
blank_n,
ntb,
colb,
pgb,
sab,
spgb,
hsync,
vsync,
start_vblank,
set_mode,
visible,
border,
vram_req,
vram_wr,
vram_ack,
vram_addr,
vram_rdata,
vram_cpu_req,
vram_cpu_wr,
vram_cpu_ack,
vram_cpu_a,
pattern,
color,
load,
spr_pattern,
spr_color,
spr_collide,
spr_5,
spr_5num,
spr_nolimit
);
// SRAM interface.
vdp_sram sram(
clk40m,
clk40m_n,
rst_n,
vram_req,
vram_wr,
vram_ack,
vram_addr,
vram_rdata,
sram_a[ 13 : 0 ],
sram_din,
sram_doe,
sram_oe_n,
sram_we_n
);
// CPU interface.
vdp_cpu cpu(
clk40m,
rst_n,
cpu_vram_port,
cpu_vdp_port,
cpu_a,
cpu_din,
cpu_dout,
cpu_doe,
cpu_in_n,
cpu_out_n,
cpu_int_n,
vram_cpu_req,
vram_cpu_ack,
vram_cpu_wr,
vram_cpu_a,
sram_dout,
vram_rdata,
g1_mode,
g2_mode,
multi_mode,
text_mode,
gmode,
blank_n,
spr_size,
spr_mag,
ntb,
colb,
pgb,
sab,
spgb,
color1,
color0,
spr_nolimit,
spr_collide,
spr_5,spr_5num,
start_vblank,
set_mode
);
endmodule

View File

@@ -1,168 +0,0 @@
module vdp_colormap(
clk,
rst_n,
visible,
border,
pattern,
color1,
color0,
bgcolor,
spr_pat,
spr_color,
r,
g,
b
);
input clk;
input rst_n;
input visible;
input border;
input pattern;
input [ 3 : 0 ] color1;
input [ 3 : 0 ] color0;
input [ 3 : 0 ] bgcolor;
input spr_pat;
input [ 3 : 0 ] spr_color;
output [ 3 : 0 ] r;
output [ 3 : 0 ] g;
output [ 3 : 0 ] b;
`define TRANSPARENT 0
`define BLACK 1
`define MEDIUM_GREEN 2
`define LIGHT_GREEN 3
`define DARK_BLUE 4
`define LIGHT_BLUE 5
`define DARK_RED 6
`define CYAN 7
`define MEDIUM_RED 8
`define LIGHT_RED 9
`define DARK_YELLOW 10
`define LIGHT_YELLOW 11
`define DARK_GREEN 12
`define MAGENTA 13
`define GRAY 14
`define WHITE 15
reg [ 3 : 0 ] colorsel;
always @( visible or border or bgcolor
or spr_pat or spr_color
or pattern or color1 or color0 ) begin
colorsel = `TRANSPARENT;
if( !visible ) begin
colorsel = `BLACK;
end else if( border ) begin
colorsel = bgcolor;
end else if( spr_pat && spr_color != `TRANSPARENT ) begin
colorsel = spr_color;
end else if( pattern ) begin
colorsel = color1;
end else begin
colorsel = color0;
end
if( colorsel == `TRANSPARENT ) begin
colorsel = bgcolor;
end
end
reg [ 3 : 0 ] red;
reg [ 3 : 0 ] green;
reg [ 3 : 0 ] blue;
always @( colorsel ) begin
case( colorsel )
`TRANSPARENT, `BLACK: begin
red <= 0;
green <= 0;
blue <= 0;
end
`MEDIUM_GREEN: begin
red <= 3;
green <= 13;
blue <= 3;
end
`LIGHT_GREEN: begin
red <= 7;
green <= 15;
blue <= 7;
end
`DARK_BLUE: begin
red <= 3;
green <= 3;
blue <= 15;
end
`LIGHT_BLUE: begin
red <= 5;
green <= 7;
blue <= 15;
end
`DARK_RED: begin
red <= 11;
green <= 3;
blue <= 3;
end
`CYAN: begin
red <= 5;
green <= 13;
blue <= 15;
end
`MEDIUM_RED: begin
red <= 15;
green <= 3;
blue <= 3;
end
`LIGHT_RED: begin
red <= 15;
green <= 7;
blue <= 7;
end
`DARK_YELLOW: begin
red <= 13;
green <= 13;
blue <= 3;
end
`LIGHT_YELLOW: begin
red <= 13;
green <= 13;
blue <= 9;
end
`DARK_GREEN: begin
red <= 3;
green <= 9;
blue <= 3;
end
`MAGENTA: begin
red <= 13;
green <= 5;
blue <= 11;
end
`GRAY: begin
red <= 11;
green <= 11;
blue <= 11;
end
`WHITE: begin
red <= 15;
green <= 15;
blue <= 15;
end
endcase
end
reg [ 3 : 0 ] r;
reg [ 3 : 0 ] g;
reg [ 3 : 0 ] b;
always @( negedge rst_n or posedge clk ) begin
if( !rst_n ) begin
r <= 4'hF;
g <= 4'hF;
b <= 4'hF;
end else begin
// For inverting DAC.
r <= ~red;
g <= ~green;
b <= ~blue;
end
end
endmodule

View File

@@ -1,333 +0,0 @@
module vdp_cpu(
clk40m,
rst_n,
cpu_vram_port,
cpu_vdp_port,
cpu_a,
cpu_din,
cpu_dout,
cpu_doe,
cpu_in_n,
cpu_out_n,
cpu_int_n,
vram_cpu_req,
vram_cpu_ack,
vram_cpu_wr,
vram_cpu_a,
vram_cpu_wdata,
vram_cpu_rdata,
g1_mode,
g2_mode,
multi_mode,
text_mode,
gmode,
blank_n,
spr_size,
spr_mag,
ntb,
colb,
pgb,
sab,
spgb,
color1,
color0,
spr_nolimit,
spr_collide,
spr_5,
spr_5num,
start_vblank,
set_mode
);
input clk40m;
input rst_n;
input [ 7 : 0 ] cpu_vram_port;
input [ 7 : 0 ] cpu_vdp_port;
input [ 7 : 0 ] cpu_a;
input [ 7 : 0 ] cpu_din;
output [ 7 : 0 ] cpu_dout;
output cpu_doe;
input cpu_in_n;
input cpu_out_n;
output cpu_int_n;
output vram_cpu_req;
input vram_cpu_ack;
output vram_cpu_wr;
output [ 13 : 0 ] vram_cpu_a;
output [ 7 : 0 ] vram_cpu_wdata;
input [ 7 : 0 ] vram_cpu_rdata;
output g1_mode;
output g2_mode;
output multi_mode;
output text_mode;
output gmode;
output blank_n;
output spr_size;
output spr_mag;
output [ 3 : 0 ] ntb;
output [ 7 : 0 ] colb;
output [ 2 : 0 ] pgb;
output [ 6 : 0 ] sab;
output [ 2 : 0 ] spgb;
output [ 3 : 0 ] color1;
output [ 3 : 0 ] color0;
output spr_nolimit;
input spr_collide;
input spr_5;
input [ 4 : 0 ] spr_5num;
input start_vblank;
input set_mode;
wire in_sel = !cpu_in_n && ( cpu_a == cpu_vram_port || cpu_a == cpu_vdp_port );
wire out_sel = !cpu_out_n && ( cpu_a == cpu_vram_port || cpu_a == cpu_vdp_port );
wire mode = ( cpu_a == cpu_vdp_port );
// Synchronize CPU interface.
reg in_1, in_2, in_3;
reg out_1, out_2, out_3;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
in_1 <= 0;
in_2 <= 0;
in_3 <= 0;
out_1 <= 0;
out_2 <= 0;
out_3 <= 0;
end else begin
in_1 <= in_sel;
in_2 <= in_1;
in_3 <= in_2;
out_1 <= out_sel;
out_2 <= out_1;
out_3 <= out_2;
end
end
wire cpu_wr = out_2 && !out_3;
wire cpu_rd = !in_2 && in_3; // After CPU has read data.
// Freeze status register at beginning of read.
// Must be sure what value of flags the CPU sees for auto-clearing.
// spr_5 must always correspond to spr_5num.
reg stat_f, stat_c, stat_5;
reg [ 4 : 0 ] stat_5num;
reg [ 7 : 0 ] stat;
always @( posedge clk40m ) begin
if( in_2 && !in_3 ) begin
stat <= { stat_f, stat_c, stat_5, stat_5num };
end
end
// Interrupt status.
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
stat_f <= 0;
stat_c <= 0;
stat_5 <= 0;
end else if( start_vblank ) begin
stat_f <= 1;
stat_c <= spr_collide;
stat_5 <= spr_5;
stat_5num <= spr_5num;
end else if( cpu_rd && mode ) begin
stat_f <= 0;
stat_c <= 0;
stat_5 <= 0;
end
end
// Register fields.
reg xm3, xm2, xm1;
reg xblank_n;
reg ien;
reg xspr_size;
reg xspr_mag;
reg [ 3 : 0 ] ntb;
reg [ 7 : 0 ] colb;
reg [ 2 : 0 ] pgb;
reg [ 6 : 0 ] sab;
reg [ 2 : 0 ] spgb;
reg [ 3 : 0 ] color1;
reg [ 3 : 0 ] color0;
// Added (nonstandard) functions.
reg xspr_nolimit;
// Capture CPU write data.
reg cpu_byte2;
reg [ 7 : 0 ] vram_cpu_wdata;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
cpu_byte2 <= 0;
xm3 <= 0;
xm2 <= 0;
xm1 <= 0;
xblank_n <= 0;
ien <= 0;
xspr_size <= 0;
xspr_mag <= 0;
xspr_nolimit <= 0;
ntb <= 0;
colb <= 0;
pgb <= 0;
sab <= 0;
spgb <= 0;
color1 <= 0;
color0 <= 0;
end else begin
if( cpu_wr ) begin
if( mode ) begin
if( cpu_byte2 ) begin
if( cpu_din[ 7 ] ) begin
if( cpu_din[ 6 ] == 1'b0 ) begin
// Register write.
case( cpu_din[ 5 : 0 ] )
0: begin
xm3 <= vram_cpu_a[ 1 ];
end
1: begin
xspr_mag <= vram_cpu_a[ 0 ];
xspr_size <= vram_cpu_a[ 1 ];
xm2 <= vram_cpu_a[ 3 ];
xm1 <= vram_cpu_a[ 4 ];
ien <= vram_cpu_a[ 5 ];
xblank_n <= vram_cpu_a[ 6 ];
end
2: begin
ntb <= vram_cpu_a[ 3 : 0 ];
end
3: begin
colb <= vram_cpu_a[ 7 : 0 ];
end
4: begin
pgb <= vram_cpu_a[ 2 : 0 ];
end
5: begin
sab <= vram_cpu_a[ 6 : 0 ];
end
6: begin
spgb <= vram_cpu_a[ 2 : 0 ];
end
7: begin
color1 <= vram_cpu_a[ 7 : 4 ];
color0 <= vram_cpu_a[ 3 : 0 ];
end
31: begin
xspr_nolimit <= vram_cpu_a[ 0 ];
end
default: begin
end
endcase
end
end
end
cpu_byte2 <= !cpu_byte2;
end else begin
// VRAM write (malformed if cpu_byte2, but do it anyway).
vram_cpu_wdata <= cpu_din;
cpu_byte2 <= 0;
end
end else if( cpu_rd ) begin
cpu_byte2 <= 0;
end
end
end
// Certain register bits mustn't change mid-screen.
reg g1_mode;
reg g2_mode;
reg multi_mode;
reg text_mode;
reg gmode; // Any valid graphics mode.
reg spr_size;
reg spr_mag;
reg spr_nolimit;
reg blank_n;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
g1_mode <= 1;
g2_mode <= 0;
multi_mode <= 0;
text_mode <= 0;
gmode <= 1;
spr_size <= 0;
spr_mag <= 0;
spr_nolimit <= 0;
blank_n <= 0;
end else if( set_mode ) begin
g1_mode <= ( { xm1, xm2, xm3 } == 3'b000 );
g2_mode <= ( { xm1, xm2, xm3 } == 3'b001 );
multi_mode <= ( { xm1, xm2, xm3 } == 3'b010 );
text_mode <= ( { xm1, xm2, xm3 } == 3'b100 );
gmode <= !xm1;
spr_size <= xspr_size;
spr_mag <= xspr_mag;
spr_nolimit <= xspr_nolimit;
blank_n <= xblank_n;
end
end
wire set_addr_lsb = cpu_wr && mode && !cpu_byte2;
wire set_addr_msb = cpu_wr && mode && cpu_byte2 && !cpu_din[ 7 ];
// VRAM CPU access state machine.
reg [ 13 : 0 ] vram_cpu_a;
reg [ 7 : 0 ] vram_rdata;
reg vram_cpu_req;
reg vram_cpu_wr;
reg addr_mod;
wire start_req = ( ( cpu_wr || cpu_rd ) && !mode && ( !vram_cpu_req || vram_cpu_ack ) )
|| ( set_addr_msb && !cpu_din[ 6 ] && ( !vram_cpu_req || vram_cpu_ack ) );
wire start_wr = !mode && cpu_wr;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
vram_cpu_a <= 0;
vram_rdata <= 0;
vram_cpu_req <= 0;
vram_cpu_wr <= 0;
addr_mod <= 0;
end else begin
if( vram_cpu_req && vram_cpu_ack ) begin
if( !start_req ) begin
vram_cpu_req <= 0;
end
if( !addr_mod && !set_addr_lsb && !set_addr_msb ) begin
// Auto-increment CPU VRAM address.
vram_cpu_a <= vram_cpu_a + 1'b1;
end
addr_mod <= 0;
if( !vram_cpu_wr ) begin
vram_rdata <= vram_cpu_rdata;
end
end
if( start_req ) begin
vram_cpu_req <= 1;
vram_cpu_wr <= start_wr;
end
if( set_addr_lsb ) begin
if( vram_cpu_req && !vram_cpu_ack ) begin
addr_mod <= 1;
end
vram_cpu_a[ 7 : 0 ] <= cpu_din;
end
if( set_addr_msb ) begin
if( vram_cpu_req && !vram_cpu_ack ) begin
addr_mod <= 1;
end
vram_cpu_a[ 13 : 8 ] <= cpu_din[ 5 : 0 ];
end
end
end
// CPU read data.
assign cpu_dout = ( mode ? stat : vram_rdata );
assign cpu_doe = in_sel;
// CPU interrupt.
assign cpu_int_n = ( stat_f && ien ) ? 1'b0 : 1'bZ;
endmodule

View File

@@ -1,633 +0,0 @@
module vdp_fsm(
clk40m,
rst_n,
g1_mode,
g2_mode,
multi_mode,
gmode,
text_mode,
spr_size,
spr_mag,
blank_n,
ntb,
colb,
pgb,
sab,
spgb,
hsync,
vsync,
start_vblank,
set_mode,
visible,
border,
vram_req,
vram_wr,
vram_ack,
vram_addr,
vram_rdata,
vram_cpu_req,
vram_cpu_wr,
vram_cpu_ack,
vram_cpu_a,
pattern,
color,
load,
spr_pattern,
spr_color,
spr_collide,
spr_5,
spr_5num,
spr_nolimit
);
input clk40m;
input rst_n;
input g1_mode;
input g2_mode;
input multi_mode;
input gmode;
input text_mode;
input spr_size;
input spr_mag;
input blank_n;
input [ 3 : 0 ] ntb;
input [ 7 : 0 ] colb;
input [ 2 : 0 ] pgb;
input [ 6 : 0 ] sab;
input [ 2 : 0 ] spgb;
output hsync;
output vsync;
output start_vblank;
output set_mode;
output visible;
output border;
output vram_req;
output vram_wr;
input vram_ack;
output [ 13 : 0 ] vram_addr;
input [ 7 : 0 ] vram_rdata;
input vram_cpu_req;
input vram_cpu_wr;
output vram_cpu_ack;
input [ 13 : 0 ] vram_cpu_a;
output [ 7 : 0 ] pattern;
output [ 7 : 0 ] color;
output load;
output spr_pattern;
output [ 3 : 0 ] spr_color;
output spr_collide;
output spr_5;
output [ 4 : 0 ] spr_5num;
input spr_nolimit;
// 800x600 @ 60 Hz SVGA, pixel frequency = 40 MHz, +HSYNC, +VSYNC.
// H: 800 active, 40 front porch, 128 sync, 88 back porch = 1056 pixel clocks per line.
// V: 600 active, 1 front porch, 4 sync, 23 back porch = 628 lines.
// TMS9918A pixels are 3x3 SVGA pixels each (768x576 visible non-border).
`define H_ACT 800
`define H_FP 40
`define H_SYNC 128
`define H_BP 88
`define H_WIDTH `H_ACT+`H_FP+`H_SYNC+`H_BP
`define V_ACT 600
`define V_FP 1
`define V_SYNC 4
`define V_BP 23
`define V_HEIGHT `V_ACT+`V_FP+`V_SYNC+`V_BP
reg [ 10 : 0 ] h;
reg [ 9 : 0 ] v;
reg hsync;
reg vsync;
reg start_vblank;
reg line_end;
reg set_mode;
reg visible;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
h <= 0;
v <= 0;
hsync <= 0;
vsync <= 0;
start_vblank <= 0;
line_end <= 0;
set_mode <= 0;
visible <= 1;
end else begin
hsync <= ( h >= `H_ACT+`H_FP-1 && h < `H_ACT+`H_FP+`H_SYNC-1 );
line_end <= ( h == `H_WIDTH-2 );
set_mode <= ( h == `H_WIDTH-3 ) && ( v == `V_HEIGHT-1 );
start_vblank <= ( h == `H_WIDTH-2 ) && ( v == `V_ACT-1 );
visible <= ( h >= `H_WIDTH-2 && ( v == `V_HEIGHT-1 || v < `V_ACT-1 ) )
|| ( h < `H_ACT-2 && v <= `V_ACT-1 );
if( line_end ) begin
h <= 0;
if( v >= `V_ACT+`V_FP-1 && v < `V_ACT+`V_FP+`V_SYNC-1 ) begin
vsync <= 1;
end else begin
vsync <= 0;
end
if( v == `V_HEIGHT-1 ) begin
v <= 0;
end else begin
v <= v + 1'b1;
end
end else begin
h <= h + 1'b1;
end
end
end
`define BORD_TOP 12
`define BORD_BOT 12
reg [ 1 : 0 ] vrep; // Vertical line repeat x3.
reg [ 7 : 0 ] scan_line; // Active scan line, 0-191+.
reg [ 7 : 0 ] scan_next; // Scan line + 1.
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
vrep <= 0;
scan_line <= 192;
scan_next <= 193;
end else if( line_end ) begin
if( v == `BORD_TOP-4 ) begin
// For sprite setup vrep must be valid for 3 scan lines before active region.
vrep <= 0;
scan_line <= 8'hFF; // Bit 3 must be odd for sprites.
scan_next <= 0;
end else if( vrep == 2 ) begin
vrep <= 0;
scan_line <= scan_next;
scan_next <= scan_next + 1'b1;
end else begin
vrep <= vrep + 1'b1;
end
end
end
wire [ 2 : 0 ] line = scan_line[ 2 : 0 ]; // Scan line within pattern, 0-7.
wire [ 5 : 0 ] multi_row = scan_line[ 7 : 2 ]; // Multicolor block row, 0-47.
wire [ 4 : 0 ] row = scan_line[ 7 : 3 ]; // Pattern row, 0-23.
// Border delineation.
// Top and bottom borders are 12 SVGA lines each.
// In text mode, left and right borders are 40 SVGA pixels each.
// In graphics modes, left and right borders are 16 SVGA pixels each.
`define BORD_GRAPH 16
`define BORD_TEXT 40
reg border;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
border <= 1;
end else if( v < `BORD_TOP || v >= `V_ACT-`BORD_BOT ) begin
border <= 1;
end else if( blank_n && text_mode ) begin
border <= !( h >= `BORD_TEXT-2 && h < `H_ACT-`BORD_TEXT-2 );
end else if( blank_n && gmode ) begin
border <= !( h >= `BORD_GRAPH-2 && h < `H_ACT-`BORD_GRAPH-2 );
end else begin
border <= 1;
end
end
// Horizontal pattern counter, all modes.
wire ghnext, thnext;
reg [ 5 : 0 ] col;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
col <= 0;
end else if( line_end ) begin
col <= 0;
end else if( ghnext || thnext ) begin
col <= col + 1'b1;
end
end
// Graphics modes horizontal counter.
reg [ 4 : 0 ] ghcount;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
ghcount <= 0;
end else if( line_end || ghnext || !gmode ) begin
ghcount <= 0;
end else begin
ghcount <= ghcount + 1'b1;
end
end
assign ghnext = ( ghcount == 23 );
wire ghload = ( ghcount == 14 );
// Text mode horizontal counter.
reg [ 4 : 0 ] thcount;
reg [ 9 : 0 ] text_pos; // 40*pattern row + column.
reg [ 9 : 0 ] save_pos;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
thcount <= 0;
text_pos <= 0;
save_pos <= 0;
end else if( !text_mode ) begin
thcount <= 0;
end else if( line_end ) begin
thcount <= 0;
if( v == `BORD_TOP-1 ) begin
text_pos <= 0;
save_pos <= 0;
end else if( vrep != 2 || line != 7 ) begin
// For 23 additional lines in text row, restore text position.
text_pos <= save_pos;
end else begin
save_pos <= text_pos;
end
end else if( thnext ) begin
thcount <= 0;
text_pos <= text_pos + 1'b1;
end else if( thcount == 3 && ( h < 24 || h >= 744 || v < `BORD_TOP || v >= `V_ACT-`BORD_BOT ) ) begin
// Allow more CPU accesses during non-active time.
thcount <= 0;
end else begin
thcount <= thcount + 1'b1;
end
end
assign thnext = ( thcount == 17 );
wire thload = ( thcount == 14 );
// Load pattern into pixel shifter.
assign load = ( ghload || thload );
reg [ 4 : 0 ] spr_num;
always @( vrep or col ) begin
spr_num = 5'hXX;
if( vrep == 0 ) begin
spr_num = { 1'b0, col[ 4 : 1 ] };
end else if( vrep == 1 ) begin
spr_num = { 1'b1, col[ 4 : 1 ] };
end else if( vrep == 2 ) begin
spr_num = col[ 4 : 0 ];
end
end
reg [ 31 : 0 ] spr_xvld;
reg spr_load;
// VRAM requests. Must be mutually exclusive and at least 4 clocks apart.
wire pre_gnreq = ( ghcount == 0 ) && ( col < 32 ) && gmode;
wire pre_gpreq = ( ghcount == 4 ) && ( col < 32 ) && gmode;
wire pre_gcreq = ( ghcount == 8 ) && ( col < 32 ) && ( g1_mode || g2_mode );
wire pre_gxreq = ( ghcount == 20 ) && gmode;
// Sprite data is read from VRAM during the three SVGA lines prior to the corresponding three VDP lines.
// Sprite 0 is read on v = 9,10,11 for the first active VDP line at v = 12,13,14.
// Sprite 31 is read on v = 582,583,584 for the last active VDP line at v = 585,586,587.
wire pre_svreq = ( ghcount == 12 ) && !col[ 0 ] && ( col < 32 )
&& ( v > 8 ) && ( v < 585 ) && ( vrep == 0 || vrep == 1 )
&& spr_load && blank_n && gmode;
wire pre_snreq = ( ghcount == 16 ) && !col[ 0 ] && ( col < 32 )
&& ( v > 8 ) && ( v < 585 ) && ( vrep == 0 || vrep == 1 )
&& spr_load && blank_n && gmode;
wire pre_sp0req = ( ghcount == 12 ) && col[ 0 ] && ( col < 32 )
&& ( v > 8 ) && ( v < 585 ) && ( vrep == 0 || vrep == 1 )
&& spr_xvld[ spr_num ] && blank_n && gmode;
wire pre_sp1req = ( ghcount == 16 ) && col[ 0 ] && ( col < 32 )
&& ( v > 8 ) && ( v < 585 ) && ( vrep == 0 || vrep == 1 )
&& spr_xvld[ spr_num ] && blank_n && gmode && spr_size;
wire pre_sareq = ( ghcount == 12 ) && ( col < 32 )
&& ( v > 8 ) && ( v < 585 ) && vrep == 2
&& spr_xvld[ spr_num ] && blank_n && gmode;
wire pre_shreq = ( ghcount == 16 ) && ( col < 32 )
&& ( v > 8 ) && ( v < 585 ) && vrep == 2
&& spr_xvld[ spr_num ] && blank_n && gmode;
wire pre_tnreq = ( thcount == 4 ) && text_mode;
wire pre_tpreq = ( thcount == 8 ) && text_mode;
wire pre_txreq = ( thcount == 0 || thcount == 12 ) && text_mode;
reg nreq, preq, creq, ureq, xureq;
reg svreq, shreq, snreq, sareq, sp0req, sp1req;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
nreq <= 0;
preq <= 0;
creq <= 0;
ureq <= 0;
svreq <= 0;
shreq <= 0;
snreq <= 0;
sareq <= 0;
sp0req <= 0;
end else begin
nreq <= blank_n && ( scan_line < 192 ) && ( pre_gnreq || pre_tnreq );
preq <= blank_n && ( scan_line < 192 ) && ( pre_gpreq || pre_tpreq );
creq <= blank_n && ( scan_line < 192 ) && pre_gcreq;
ureq <= ( v >= `BORD_TOP-4 && v < `V_ACT-`BORD_BOT ) && blank_n && ( pre_gxreq || pre_txreq );
xureq <= ( h[ 1 : 0 ] == 2'b00 ) && ( !blank_n
|| ( !gmode && !text_mode )
|| ( v < `BORD_TOP-4 || v >= `V_ACT-`BORD_BOT ) );
svreq <= pre_svreq;
shreq <= pre_shreq;
snreq <= pre_snreq;
sareq <= pre_sareq;
sp0req <= pre_sp0req;
sp1req <= pre_sp1req;
end
end
wire xreq = vram_cpu_req && ( ureq || xureq ) && !vram_cpu_ack;
wire vram_req = ( nreq || preq || creq || svreq || shreq || snreq || sareq || sp0req || sp1req || xreq );
wire vram_wr = ( xreq && vram_cpu_wr );
// With the 3-state SRAM controller, ACK is asserted one clock before valid read data.
reg vram_ack2;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
vram_ack2 <= 0;
end else begin
vram_ack2 <= vram_ack;
end
end
reg [ 9 : 0 ] reqs;
always @( posedge clk40m ) begin
if( vram_req ) begin
// Store each req so we know what to do with the ack.
reqs <= { svreq, shreq, snreq, sareq, sp0req, sp1req, nreq, preq, creq, xreq };
end else if( vram_ack2 ) begin
reqs <= 0;
end
end
assign vram_cpu_ack = reqs[ 0 ] && vram_ack2;
// Sprite data RAM, 256 x 8-bit words.
// Synchronous inputs and outputs.
reg [ 7 : 0 ] spr_addr;
wire spr_wren;
wire [ 7 : 0 ] spr_rdata;
vdp_sprdata sprdata(
spr_addr,
clk40m,
vram_rdata,
spr_wren,
spr_rdata
);
// Sprite data RAM address.
always @( col or scan_line or reqs or vrep or ghcount or spr_num ) begin
if( col < 32 ) begin
// Write data address.
spr_addr[ 7 : 2 ] = { !scan_line[ 0 ], spr_num };
spr_addr[ 1 : 0 ] = 2'bXX;
if( reqs[ 5 ] ) begin
spr_addr[ 1 : 0 ] = 2'b00; // Pattern 0.
end else if( reqs[ 4 ] ) begin
spr_addr[ 1 : 0 ] = 2'b01; // Pattern 1.
end else if( reqs[ 6 ] ) begin
spr_addr[ 1 : 0 ] = 2'b10; // Early clock/color.
end else if( reqs[ 8 ] ) begin
spr_addr[ 1 : 0 ] = 2'b11; // Horizontal position.
end
end else begin
// Read data address.
spr_addr = { ( vrep[ 1 ] ^ scan_line[ 0 ] ), col[ 2 : 0 ], ghcount[ 3 : 0 ] };
end
end
// Sprite RAM data write enable.
assign spr_wren = vram_ack2 && ( reqs[ 4 ] || reqs[ 5 ] || reqs[ 6 ] || reqs[ 8 ] );
// Sprite arithmetic.
wire [ 5 : 0 ] spr_side = spr_size ? ( spr_mag ? 6'd32 : 6'd16 ) : ( spr_mag ? 6'd16 : 6'd8 );
wire [ 7 : 0 ] spr_min = vram_rdata;
wire [ 7 : 0 ] spr_max = vram_rdata + spr_side;
wire spr_start = ( h == `H_WIDTH-1+`BORD_GRAPH-32*3-4 );
wire spr_setup = ( spr_start && vrep == 2 );
// Store VRAM read data.
reg [ 7 : 0 ] name;
reg [ 7 : 0 ] pattern;
reg [ 7 : 0 ] color;
reg [ 4 : 0 ] spr_line;
reg [ 7 : 0 ] spr_name;
reg spr_5;
reg [ 4 : 0 ] spr_5num;
reg [ 2 : 0 ] spr_count;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
spr_5 <= 0;
end else if( start_vblank ) begin
spr_5 <= 0;
end else if( spr_setup ) begin
spr_load <= 1;
spr_xvld <= 0;
spr_count <= 0;
end else if( vram_ack2 ) begin
if( reqs[ 3 ] ) begin
name <= vram_rdata;
end
if( reqs[ 2 ] ) begin
if( !multi_mode ) begin
pattern <= vram_rdata;
end else begin
pattern <= 8'hF0;
color <= vram_rdata;
end
end
if( reqs[ 1 ] ) begin
color <= vram_rdata;
end
if( reqs[ 9 ] ) begin
if( vram_rdata == 208 ) begin
spr_load <= 0;
end else if( !spr_nolimit && spr_count == 4 ) begin
if( !spr_5 ) begin
spr_5num <= spr_num;
end
spr_5 <= 1;
spr_load <= 0;
end else if( scan_next+8'd32 > spr_min+8'd32 && scan_next+8'd32 <= spr_max+8'd32 ) begin
spr_xvld[ spr_num ] <= 1;
spr_line <= scan_next[ 4 : 0 ]-vram_rdata[ 4 : 0 ]-5'h1;
spr_count <= spr_count + 1'b1;
end
end
if( reqs[ 7 ] ) begin
spr_name <= vram_rdata;
end
end
end
// VRAM address MUX. Big MUX.
reg [ 13 : 0 ] vram_addr;
always @( xreq or vram_cpu_a
or nreq or ntb or text_mode or row or col
or preq or g1_mode or g2_mode or multi_mode or pgb or name or line or multi_row or text_pos
or creq or colb or vram_rdata
or svreq or shreq or snreq or sareq or sp0req or sp1req
or spr_num or spr_size or spr_mag or spr_name or spr_line or spgb or sab ) begin
vram_addr = 14'hXXXX;
if( xreq ) begin
vram_addr = vram_cpu_a;
end
if( nreq ) begin
vram_addr[ 13 : 10 ] = ntb;
if( text_mode ) begin
vram_addr[ 9 : 0 ] = text_pos;
end else begin
vram_addr[ 9 : 0 ] = { row, col[ 4 : 0 ] };
end
end
if( preq ) begin
// Name is not set until next clock, use vram_rdata instead.
if( g1_mode || text_mode ) begin
vram_addr = { pgb, vram_rdata, line };
end else if( g2_mode ) begin
vram_addr = { pgb[ 2 ], row[ 4 : 3 ], vram_rdata, line };
end else if( multi_mode ) begin
vram_addr = { pgb, vram_rdata, multi_row[ 2 : 0 ] };
end
end
if( creq ) begin
if( g1_mode ) begin
vram_addr = { colb, 1'b0, name[ 7 : 3 ] };
end else if( g2_mode ) begin
vram_addr = { colb[ 2 ], row[ 4 : 3 ], name, line };
end
end
if( svreq ) begin
vram_addr = { sab, spr_num, 2'b00 };
end
if( shreq ) begin
vram_addr = { sab, spr_num, 2'b01 };
end
if( snreq ) begin
vram_addr = { sab, spr_num, 2'b10 };
end
if( sareq ) begin
vram_addr = { sab, spr_num, 2'b11 };
end
if( sp0req ) begin
if( !spr_size ) begin
if( !spr_mag ) begin
vram_addr = { spgb, spr_name, spr_line[ 2 : 0 ] };
end else begin
vram_addr = { spgb, spr_name, spr_line[ 3 : 1 ] };
end
end else begin
if( !spr_mag ) begin
vram_addr = { spgb, spr_name[ 7 : 2 ], 1'b0, spr_line[ 3 : 0 ] };
end else begin
vram_addr = { spgb, spr_name[ 7 : 2 ], 1'b0, spr_line[ 4 : 1 ] };
end
end
end
if( sp1req ) begin
if( !spr_mag ) begin
vram_addr = { spgb, spr_name[ 7 : 2 ], 1'b1, spr_line[ 3 : 0 ] };
end else begin
vram_addr = { spgb, spr_name[ 7 : 2 ], 1'b1, spr_line[ 4 : 1 ] };
end
end
end
// Sprite state machine.
integer i;
reg spr_found;
reg spr_active;
reg [ 1 : 0 ] spr_hrep;
reg spr_pattern;
reg [ 3 : 0 ] spr_color;
reg spr_collide;
reg [ 8 : 0 ] spr_hcount;
reg [ 31 : 0 ] spr_odd;
reg [ 4 : 0 ] snum;
reg early;
reg [ 31 : 0 ] spr_vld;
reg [ 3 : 0 ] spr_col [ 0 : 31 ];
reg [ 8 : 0 ] spr_dly [ 0 : 31 ];
reg [ 15 : 0 ] spr_pat [ 0 : 31 ];
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
spr_collide <= 0;
spr_active <= 0;
end else if( start_vblank ) begin
spr_collide <= 0;
spr_vld <= 0;
end else if( col >= 32 && col < 40 && ghcount >= 2 && ghcount < 18 ) begin
spr_active <= 0;
// Unload sprite data from RAM.
snum = ( ( ghcount - 2'd2 ) & 4'b1100 ) >> 2;
snum[ 4 : 2 ] = col[ 2 : 0 ];
case( ghcount[ 1 : 0 ] )
0: begin
spr_col[ snum ] <= spr_rdata[ 3 : 0 ];
early <= spr_rdata[ 7 ];
end
1: begin
if( early ) begin
spr_dly[ snum ] <= { 1'b0, spr_rdata };
end else begin
spr_dly[ snum ] <= 9'd32 + spr_rdata;
end
end
2: begin
spr_pat[ snum ][ 15 : 8 ] <= spr_rdata;
end
3: begin
if( spr_size ) begin
spr_pat[ snum ][ 7 : 0 ] <= spr_rdata;
end else begin
spr_pat[ snum ][ 7 : 0 ] <= 8'h00;
end
end
endcase
end else if( spr_start ) begin
spr_hrep <= 2;
spr_pattern <= 0;
spr_odd <= 0;
spr_hcount <= 0;
spr_active <= 1;
if( spr_setup ) begin
spr_vld <= spr_xvld;
end
end else if( spr_active && spr_hrep == 1 ) begin
// Multicycle path:
// Count, pattern, color, collide clocked in when hrep 1->2 only.
spr_found = 0;
for( i = 0; i <= 31; i = i + 1 ) begin
if( spr_hcount >= spr_dly[ i ] ) begin
if( spr_vld[ i ] ) begin
if( spr_pat[ i ][ 15 ] ) begin
if( spr_found ) begin
// Sprite collision.
spr_collide <= 1;
end else begin
spr_color <= spr_col[ i ];
end
spr_found = 1;
end
if( !spr_mag || spr_odd[ i ] ) begin
// Shift pattern, zero backfill.
spr_pat[ i ] <= { spr_pat[ i ][ 14 : 0 ], 1'b0 };
end
end
spr_odd[ i ] <= ~spr_odd[ i ];
end
end
spr_pattern <= spr_found;
spr_hrep <= 2;
spr_hcount <= spr_hcount + 1'b1;
end else if( spr_hrep == 2 ) begin
spr_hrep <= 0;
end else begin
spr_hrep <= 1;
end
end
endmodule

View File

@@ -1,58 +0,0 @@
module vdp_shift(
clk40m,
rst_n,
pattern,
color,
color1,
color0,
load,
text_mode,
color_1,
color_0,
pixel
);
input clk40m;
input rst_n;
input [ 7 : 0 ] pattern;
input [ 7 : 0 ] color;
input [ 3 : 0 ] color1;
input [ 3 : 0 ] color0;
input load;
input text_mode;
output [ 3 : 0 ] color_1;
output [ 3 : 0 ] color_0;
output pixel;
reg [ 3 : 0 ] color_1;
reg [ 3 : 0 ] color_0;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
color_1 <= 0;
color_0 <= 0;
end else if( load ) begin
color_1 <= text_mode ? color1 : color[ 7 : 4 ];
color_0 <= text_mode ? color0 : color[ 3 : 0 ];
end
end
reg pixel;
reg [ 6 : 0 ] shift;
reg [ 1 : 0 ] hrep;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
pixel <= 0;
shift <= 0;
hrep <= 0;
end else if( load ) begin
hrep <= 0;
{ pixel, shift } <= pattern;
end else if( hrep == 2 ) begin
hrep <= 0;
{ pixel, shift } <= { shift[ 6 : 0 ], 1'b0 };
end else begin
hrep <= hrep + 1'b1;
end
end
endmodule

View File

@@ -1,104 +0,0 @@
module vdp_sram(
clk40m,
clk40m_n,
rst_n,
vram_req,
vram_wr,
vram_ack,
vram_addr,
vram_rdata,
sram_a,
sram_din,
sram_doe,
sram_oe_n,
sram_we_n
);
input clk40m;
input clk40m_n;
input rst_n;
input vram_req;
input vram_wr;
output vram_ack;
input [ 13 : 0 ] vram_addr;
output [ 7 : 0 ] vram_rdata;
output [ 13 : 0 ] sram_a;
input [ 7 : 0 ] sram_din;
output sram_doe;
output sram_oe_n;
output sram_we_n;
// SRAM controller, 3 cycles per access.
reg [ 7 : 0 ] vram_rdata;
reg vram_active;
reg [ 13 : 0 ] sram_a;
reg sram_doe;
reg sram_oe_n;
reg sram_pwe_n;
reg [ 1 : 0 ] vram_state;
reg vram_ack;
always @( negedge rst_n or posedge clk40m ) begin
if( !rst_n ) begin
vram_active <= 0;
sram_doe <= 0;
sram_oe_n <= 1;
sram_pwe_n <= 1;
vram_state <= 0;
vram_ack <= 0;
end else begin
case( vram_state )
0: begin
if( vram_req ) begin
vram_active <= 1;
sram_a <= vram_addr;
sram_pwe_n <= !vram_wr;
vram_state <= 1;
end else begin
vram_active <= 0;
sram_pwe_n <= 1;
vram_state <= 0;
end
sram_doe <= 0;
sram_oe_n <= 1;
if( vram_active && !sram_oe_n ) begin
vram_rdata <= sram_din;
end
vram_ack <= 0;
end
1: begin
sram_oe_n <= !( vram_active && sram_pwe_n );
sram_doe <= !sram_pwe_n;
vram_state <= 2;
vram_ack <= 0;
end
2: begin
sram_pwe_n <= 1;
vram_state <= 0;
vram_ack <= 1;
end
3: begin
// Illegal state.
vram_active <= 0;
sram_doe <= 0;
sram_oe_n <= 1;
sram_pwe_n <= 1;
vram_ack <= 0;
vram_state <= 0;
end
endcase
end
end
// WE* on half clock for pulse width, addr setup/hold.
reg sram_we_n;
always @( negedge rst_n or posedge clk40m_n ) begin
if( !rst_n ) begin
sram_we_n <= 1;
end else begin
sram_we_n <= sram_pwe_n;
end
end
endmodule

View File

@@ -1,105 +0,0 @@
module vdp_wrap(
por_73_n,
clk50m_17,
push_144_n,
led1_3_n,
led2_7_n,
led3_9_n,
cpu_rst_n,
cpu_a,
cpu_d,
cpu_in_n,
cpu_out_n,
cpu_int_n,
sram_a,
sram_d,
sram_oe_n,
sram_we_n,
hsync,
vsync,
r,
g,
b
);
// Development board hardwired pins
input por_73_n; // 100 ms time constant RC POR on pin 73
input clk50m_17; // 50 MHz oscillator on pin 17
input push_144_n; // Pushbutton on pin 144
output led1_3_n; // LED on pin 3
output led2_7_n; // LED on pin 7
output led3_9_n; // LED on pin 9
// CPU interface
input cpu_rst_n;
input [ 7 : 0 ] cpu_a;
inout [ 7 : 0 ] cpu_d;
input cpu_in_n;
input cpu_out_n;
output cpu_int_n;
// SRAM interface
output [ 18 : 0 ] sram_a;
inout [ 7 : 0 ] sram_d;
output sram_oe_n;
output sram_we_n;
// VGA interface
output hsync; // Horizontal sync
output vsync; // Vertical sync
output [ 3 : 0 ] r;
output [ 3 : 0 ] g;
output [ 3 : 0 ] b;
wire [ 7 : 0 ] cpu_din;
wire [ 7 : 0 ] cpu_dout;
wire cpu_doe;
assign cpu_din = cpu_d;
assign cpu_d = cpu_doe ? cpu_dout : 8'hZZ;
wire [ 7 : 0 ] sram_din;
wire [ 7 : 0 ] sram_dout;
wire sram_doe;
assign sram_din = sram_d;
assign sram_d = sram_doe ? sram_dout : 8'hZZ;
// Give the LEDs something useless to do, to reduce synthesis warnings.
assign led1_3_n = !( !por_73_n || !push_144_n );
assign led2_7_n = !( !por_73_n || !push_144_n );
assign led3_9_n = !( !por_73_n || !push_144_n );
// PLL to convert 50 MHz to 40 MHz.
wire clk40m, clk40m_n;
vdp_clkgen clkgen(
clk50m_17,
clk40m,
clk40m_n
);
vdp vdp1(
clk40m,
clk40m_n,
cpu_rst_n,
cpu_a,
cpu_din,
cpu_dout,
cpu_doe,
cpu_in_n,
cpu_out_n,
cpu_int_n,
sram_a,
sram_din,
sram_dout,
sram_doe,
sram_oe_n,
sram_we_n,
hsync,
vsync,
r,
g,
b
);
endmodule

View File

@@ -1,151 +0,0 @@
// ====================================================================
// Bashkiria-2M FPGA REPLICA
//
// Copyright (C) 2010 Dmitry Tselikov
//
// This core is distributed under modified BSD license.
// For complete licensing information see LICENSE.TXT.
// --------------------------------------------------------------------
//
// An open implementation of Bashkiria-2M home computer
//
// Author: Dmitry Tselikov http://bashkiria-2m.narod.ru/
//
// Design File: k580wi53.v
//
// Interval timer k580wi53 design file of Bashkiria-2M replica.
module k580wi53(input clk,
input c0, input c1, input c2,
input g0, input g1, input g2,
output out0, output out1, output out2,
input[1:0] addr, input rd, input we_n, input[7:0] idata, output reg[7:0] odata);
wire[7:0] odata0;
wire[7:0] odata1;
wire[7:0] odata2;
always @(*)
case (addr)
2'b00: odata = odata0;
2'b01: odata = odata1;
2'b10: odata = odata2;
2'b11: odata = 0;
endcase
k580wi53channel ch0(.clk(clk), .c(c0), .gate(g0), .cout(out0), .addr(&addr), .rd(rd && addr==2'b00), .we_n(we_n || (addr!=2'b00 && (addr!=2'b11 || idata[7:6]!=2'b00))), .idata(idata), .odata(odata0));
k580wi53channel ch1(.clk(clk), .c(c1), .gate(g1), .cout(out1), .addr(&addr), .rd(rd && addr==2'b01), .we_n(we_n || (addr!=2'b01 && (addr!=2'b11 || idata[7:6]!=2'b01))), .idata(idata), .odata(odata1));
k580wi53channel ch2(.clk(clk), .c(c2), .gate(g2), .cout(out2), .addr(&addr), .rd(rd && addr==2'b10), .we_n(we_n || (addr!=2'b10 && (addr!=2'b11 || idata[7:6]!=2'b10))), .idata(idata), .odata(odata2));
endmodule
module k580wi53channel(input clk, input c, input gate, output reg cout,
input addr, input rd, input we_n, input[7:0] idata, output reg[7:0] odata);
reg[5:0] mode;
reg[15:0] init;
reg[15:0] cntlatch;
reg[15:0] counter;
reg[15:0] sub1;
reg[15:0] sub2;
reg enabled;
reg latched;
reg loaded;
reg ff;
reg first;
reg done;
reg exc;
reg exgate;
reg exrd;
reg exwe_n;
always @(*)
case ({latched,ff})
2'b00: odata = counter[7:0];
2'b01: odata = counter[15:8];
2'b10: odata = cntlatch[7:0];
2'b11: odata = cntlatch[15:8];
endcase
always @(*)
casex ({mode[0],|counter[15:12],|counter[11:8],|counter[7:4],|counter[3:0]})
5'b10000: sub1 = 16'h9999;
5'b11000: sub1 = 16'hF999;
5'b1x100: sub1 = 16'hFF99;
5'b1xx10: sub1 = 16'hFFF9;
default: sub1 = 16'hFFFF;
endcase
always @(*)
casex ({mode[0],|counter[15:12],|counter[11:8],|counter[7:4],|counter[3:1]})
5'b10000: sub2 = 16'h9998;
5'b11000: sub2 = 16'hF998;
5'b1x100: sub2 = 16'hFF98;
5'b1xx10: sub2 = 16'hFFF8;
default: sub2 = 16'hFFFE;
endcase
wire[15:0] new1 = counter + (first|~&mode[2:1]?sub1:sub2);
wire[15:0] newvalue = {new1[15:1],new1[0]&~&mode[2:1]};
always @(posedge clk)
begin
exc <= c; exgate <= gate; exrd <= rd; exwe_n <= we_n;
if (enabled & c & ~exc) begin
if (loaded) begin
if (mode[2]==1'b1 && newvalue==0) begin
counter <= init;
first <= init[0]&~cout;
end else begin
counter <= newvalue;
first <= 0;
end
if (newvalue[15:1]==0 && ~done) begin
casex ({mode[3:1],newvalue[0]})
4'b0000: {cout,done} <= 2'b11;
4'b0010: {cout,done} <= 2'b11;
4'bx100: cout <= 1'b1;
4'bx101: cout <= 0;
4'bx11x: cout <= ~cout;
4'b1000: {cout,done} <= 2'b11;
4'b1001: cout <= 0;
4'b1010: {cout,done} <= 2'b11;
4'b1011: cout <= 0;
endcase
end
end else begin
counter <= init; loaded <= 1'b1; first <= 1'b1; done <= 0;
if (mode[3:2]==0) cout <= 0;
end
end
if (exgate ^ gate) begin
if (mode[2:1]!=2'b01) enabled <= gate;
else if (gate) begin loaded <= 0; enabled <= 1; end
end
if (exrd & ~rd) begin
if (mode[5:4]==2'b11) ff <= ~ff;
if (mode[5:4]!=2'b11 || ff) latched <= 0;
end else
if (exwe_n & ~we_n) begin
if (addr) begin
if (idata[5:4]==0) begin
cntlatch <= counter; latched <= 1;
end else begin
mode <= idata[5:0]; enabled <= 0; loaded <= 0; done <= 1'b1;
latched <= 0; cout <= idata[3:1]!=0;
end
ff <= idata[5:4]==2'b10;
end else begin
casex ({mode[5:4],ff})
3'b01x: begin init <= {8'h00,idata}; enabled <= gate; ff <= 0; end
3'b10x: begin init <= {idata,8'h00}; enabled <= gate; ff <= 1; end
3'b110: begin init[7:0] <= idata; enabled <= 0; ff <= 1; end
3'b111: begin init[15:8] <= idata; enabled <= gate; ff <= 0; end
endcase
loaded <= mode[2:1]!=0 & ~done;
cout <= mode[3:1]!=0||(mode[5:4]==2'b01&&idata==8'b1);
end
end
end
endmodule

View File

@@ -1,473 +0,0 @@
// ====================================================================
// Bashkiria-2M FPGA REPLICA
//
// Copyright (C) 2010 Dmitry Tselikov
//
// This core is distributed under modified BSD license.
// For complete licensing information see LICENSE.TXT.
// --------------------------------------------------------------------
//
// An open implementation of Bashkiria-2M home computer
//
// Author: Dmitry Tselikov http://bashkiria-2m.narod.ru/
//
// Design File: k580wm80a.v
//
// Processor k580wm80a core design file of Bashkiria-2M replica.
module k580wm80a(
input clk,
input ce,
input reset,
input intr,
input [7:0] idata,
output reg [15:0] addr,
output reg sync,
output rd,
output reg wr_n,
output inta_n,
output reg [7:0] odata,
output inte_o);
reg M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16,M17,T5;
reg[2:0] state;
wire M1n = M2|M3|M4|M5|M6|M7|M8|M9|M10|M11|M12|M13|M14|M15|M16|M17;
reg[15:0] PC;
reg[15:0] SP;
reg[7:0] B,C,D,E,H,L,A;
reg[7:0] W,Z,IR;
reg[9:0] ALU;
reg FS,FZ,FA,FP,FC,_FA;
reg rd_,intproc;
assign rd = rd_&~intproc;
assign inta_n = ~(rd_&intproc);
assign inte_o = inte[1];
reg[1:0] inte;
reg jmp,call,halt;
reg save_alu,save_a,save_r,save_rp,read_r,read_rp;
reg incdec,xthl,xchg,sphl,daa;
reg ccc;
always @(*) begin
casex (IR[5:3])
3'b00x: ALU = {1'b0,A,1'b1}+{1'b0,Z,FC&IR[3]};
3'b01x: ALU = {1'b0,A,1'b0}-{1'b0,Z,FC&IR[3]};
3'b100: ALU = {1'b0,A & Z,1'b0};
3'b101: ALU = {1'b0,A ^ Z,1'b0};
3'b110: ALU = {1'b0,A | Z,1'b0};
3'b111: ALU = {1'b0,A,1'b0}-{1'b0,Z,1'b0};
endcase
end
always @(*) begin
casex (IR[5:3])
3'b00x: _FA = A[4]^Z[4]^ALU[5];
3'b100: _FA = A[3]|Z[3];
3'b101: _FA = 1'b0;
3'b110: _FA = 1'b0;
default: _FA = ~(A[4]^Z[4]^ALU[5]);
endcase
end
always @(*) begin
// SZ.A.P.C
case(idata[5:3])
3'h0: ccc = ~FZ;
3'h1: ccc = FZ;
3'h2: ccc = ~FC;
3'h3: ccc = FC;
3'h4: ccc = ~FP;
3'h5: ccc = FP;
3'h6: ccc = ~FS;
3'h7: ccc = FS;
endcase
end
wire[7:0] F = {FS,FZ,1'b0,FA,1'b0,FP,1'b1,FC};
wire[7:0] Z1 = incdec ? Z+{{7{IR[0]}},1'b1} : Z;
wire[15:0] WZ1 = incdec ? {W,Z}+{{15{IR[3]}},1'b1} : {W,Z};
wire[3:0] daaZL = FA!=0 || A[3:0] > 4'h9 ? 4'h6 : 4'h0;
wire[3:0] daaZH = FC!=0 || A[7:4] > {3'b100, A[3:0]>4'h9 ? 1'b0 : 1'b1} ? 4'h6 : 4'h0;
always @(posedge clk or posedge reset)
begin
if (reset) begin
{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16,M17} <= 0;
state <= 0; PC <= 0; {FS,FZ,FA,FP,FC} <= 0; {addr,odata} <= 0;
{sync,rd_,jmp,halt,inte,save_alu,save_a,save_r,save_rp,incdec,intproc} <= 0;
wr_n <= 1'b1;
end else if (ce) begin
sync <= 0; rd_ <= 0; wr_n <= 1'b1;
if (halt&~(M1|(intr&inte[1]))) begin
sync <= 1'b1; // state: rd in m1 out hlt stk ~wr int
odata <= 8'b10001010; // rd? hlt ~wr
end else
if (M1|~M1n) begin
case (state)
3'b000: begin
halt <= 0; intproc <= intr&inte[1]; inte[1] <= inte[0];
M1 <= 1'b1;
sync <= 1'b1;
odata <= {7'b1010001,intr&inte[1]}; // rd m1 ~wr
addr <= jmp ? {W,Z} : PC;
state <= 3'b001;
if (intr&inte[1]) inte <= 2'b0;
if (save_alu) begin
FS <= ALU[8];
FZ <= ~|ALU[8:1];
FA <= _FA;
FP <= ~^ALU[8:1];
FC <= ALU[9]|(FC&daa);
if (IR[5:3]!=3'b111) A <= ALU[8:1];
end else
if (save_a) begin
A <= Z1;
end else
if (save_r) begin
case (IR[5:3])
3'b000: B <= Z1;
3'b001: C <= Z1;
3'b010: D <= Z1;
3'b011: E <= Z1;
3'b100: H <= Z1;
3'b101: L <= Z1;
3'b111: A <= Z1;
endcase
if (incdec) begin
FS <= Z1[7];
FZ <= ~|Z1;
FA <= IR[0] ? Z1[3:0]!=4'b1111 : Z1[3:0]==0;
FP <= ~^Z1;
end
end else
if (save_rp) begin
case (IR[5:4])
2'b00: {B,C} <= WZ1;
2'b01: {D,E} <= WZ1;
2'b10: {H,L} <= WZ1;
2'b11:
if (sphl || !IR[7]) begin
SP <= WZ1;
end else begin
{A,FS,FZ,FA,FP,FC} <= {WZ1[15:8],WZ1[7],WZ1[6],WZ1[4],WZ1[2],WZ1[0]};
end
endcase
end
end
3'b001: begin
rd_ <= 1'b1;
PC <= addr+{15'b0,~intproc};
state <= 3'b010;
end
3'b010: begin
IR <= idata;
{jmp,call,save_alu,save_a,save_r,save_rp,read_r,read_rp,incdec,xthl,xchg,sphl,T5,daa} <= 0;
casex (idata)
8'b00xx0001: {save_rp,M2,M3} <= 3'b111;
8'b00xx1001: {read_rp,M16,M17} <= 3'b111;
8'b000x0010: {read_rp,M14} <= 2'b11;
8'b00100010: {M2,M3,M14,M15} <= 4'b1111;
8'b00110010: {M2,M3,M14} <= 3'b111;
8'b000x1010: {read_rp,save_a,M12} <= 3'b111;
8'b00101010: {save_rp,M2,M3,M12,M13} <= 5'b11111;
8'b00111010: {save_a,M2,M3,M12} <= 4'b1111;
8'b00xxx011: {read_rp,save_rp,incdec,T5} <= 4'b1111;
8'b00xxx10x: {read_r,save_r,incdec,T5} <= {3'b111,idata[5:3]!=3'b110};
8'b00xxx110: {save_r,M2} <= 2'b11;
8'b00000111: {FC,A} <= {A,A[7]};
8'b00001111: {A,FC} <= {A[0],A};
8'b00010111: {FC,A} <= {A,FC};
8'b00011111: {A,FC} <= {FC,A};
8'b00100111: {daa,save_alu,IR[5:3],Z} <= {5'b11000,daaZH,daaZL};
8'b00101111: A <= ~A;
8'b00110111: FC <= 1'b1;
8'b00111111: FC <= ~FC;
8'b01xxxxxx: if (idata[5:0]==6'b110110) halt <= 1'b1; else {read_r,save_r,T5} <= {2'b11,~(idata[5:3]==3'b110||idata[2:0]==3'b110)};
8'b10xxxxxx: {read_r,save_alu} <= 2'b11;
8'b11xxx000: {jmp,M8,M9} <= {3{ccc}};
8'b11xx0001: {save_rp,M8,M9} <= 3'b111;
8'b110x1001: {jmp,M8,M9} <= 3'b111;
8'b11101001: {read_rp,jmp,T5} <= 3'b111;
8'b11111001: {read_rp,save_rp,T5,sphl} <= 4'b1111;
8'b11xxx010: {jmp,M2,M3} <= {ccc,2'b11};
8'b1100x011: {jmp,M2,M3} <= 3'b111;
8'b11010011: {M2,M7} <= 2'b11;
8'b11011011: {M2,M6} <= 2'b11;
8'b11100011: {save_rp,M8,M9,M10,M11,xthl} <= 6'b111111;
8'b11101011: {read_rp,save_rp,xchg} <= 3'b111;
8'b1111x011: inte <= idata[3] ? 2'b1 : 2'b0;
8'b11xxx100: {jmp,M2,M3,T5,M10,M11,call} <= {ccc,3'b111,{3{ccc}}};
8'b11xx0101: {read_rp,T5,M10,M11} <= 4'b1111;
8'b11xx1101: {jmp,M2,M3,T5,M10,M11,call} <= 7'b1111111;
8'b11xxx110: {save_alu,M2} <= 2'b11;
8'b11xxx111: {jmp,T5,M10,M11,call,W,Z} <= {5'b11111,10'b0,idata[5:3],3'b0};
endcase
state <= 3'b011;
end
3'b011: begin
if (read_rp) begin
case (IR[5:4])
2'b00: {W,Z} <= {B,C};
2'b01: {W,Z} <= {D,E};
2'b10: {W,Z} <= xchg ? {D,E} : {H,L};
2'b11: {W,Z} <= sphl ? {H,L} : IR[7] ? {A,F} : SP;
endcase
if (xchg) {D,E} <= {H,L};
end else
if (~(jmp|daa)) begin
case (incdec?IR[5:3]:IR[2:0])
3'b000: Z <= B;
3'b001: Z <= C;
3'b010: Z <= D;
3'b011: Z <= E;
3'b100: Z <= H;
3'b101: Z <= L;
3'b110: M4 <= read_r;
3'b111: Z <= A;
endcase
M5 <= save_r && IR[5:3]==3'b110;
end
state <= T5 ? 3'b100 : 0;
M1 <= T5;
end
3'b100: begin
if (M10) SP <= SP-16'b1;
state <= 0;
M1 <= 0;
end
endcase
end else
if (M2 || M3) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b1000001,intproc}; // rd ~wr
addr <= PC;
state <= 3'b001;
end
3'b001: begin
rd_ <= 1'b1;
PC <= addr+{15'b0,~intproc};
state <= 3'b010;
end
3'b010: begin
if (M2) begin
Z <= idata;
M2 <= 0;
end else begin
W <= idata;
M3 <= 0;
end
state <= 3'b000;
end
endcase
end else
if (M4) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b1000001,intproc}; // rd ~wr
addr <= {H,L};
state <= 3'b001;
end
3'b001: begin
rd_ <= 1'b1;
state <= 3'b010;
end
3'b010: begin
Z <= idata;
M4 <= 0;
state <= 3'b000;
end
endcase
end else
if (M5) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0000000,intproc}; // ~wr=0
addr <= {H,L};
state <= 3'b001;
end
3'b001: begin
odata <= Z1;
wr_n <= 1'b0;
state <= 3'b010;
end
3'b010: begin
M5 <= 0;
state <= 3'b000;
end
endcase
end else
if (M6) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0100001,intproc}; // in ~wr
addr <= {Z,Z};
state <= 3'b001;
end
3'b001: begin
rd_ <= 1'b1;
state <= 3'b010;
end
3'b010: begin
A <= idata;
M6 <= 0;
state <= 3'b000;
end
endcase
end else
if (M7) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0001000,intproc}; // out
addr <= {Z,Z};
state <= 3'b001;
end
3'b001: begin
odata <= A;
wr_n <= 1'b0;
state <= 3'b010;
end
3'b010: begin
M7 <= 0;
state <= 3'b000;
end
endcase
end else
if (M8 || M9) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b1000011,intproc}; // rd stk ~wr
addr <= SP;
state <= 3'b001;
end
3'b001: begin
rd_ <= 1'b1;
if (M8 || !xthl) SP <= SP+16'b1;
state <= 3'b010;
end
3'b010: begin
if (M8) begin
Z <= idata;
M8 <= 0;
end else begin
W <= idata;
M9 <= 0;
end
state <= 3'b000;
end
endcase
end else
if (M10 || M11) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0000010,intproc}; // stk
addr <= SP;
state <= 3'b001;
end
3'b001: begin
if (M10) begin
SP <= SP-16'b1;
odata <= xthl ? H : call ? PC[15:8] : W;
end else begin
odata <= xthl ? L : call ? PC[7:0] : Z;
end
wr_n <= 1'b0;
state <= 3'b010;
end
3'b010: begin
if (M10) begin
M10 <= 0;
end else begin
M11 <= 0;
end
state <= 3'b000;
end
endcase
end else
if (M12 || M13) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b1000001,intproc}; // rd ~wr
addr <= M12 ? {W,Z} : addr+16'b1;
state <= 3'b001;
end
3'b001: begin
rd_ <= 1'b1;
state <= 3'b010;
end
3'b010: begin
if (M12) begin
Z <= idata;
M12 <= 0;
end else begin
W <= idata;
M13 <= 0;
end
state <= 3'b000;
end
endcase
end else
if (M14 || M15) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0000000,intproc}; // ~wr=0
addr <= M14 ? {W,Z} : addr+16'b1;
state <= 3'b001;
end
3'b001: begin
if (M14) begin
odata <= M15 ? L : A;
end else begin
odata <= H;
end
wr_n <= 1'b0;
state <= 3'b010;
end
3'b010: begin
if (M14) begin
M14 <= 0;
end else begin
M15 <= 0;
end
state <= 3'b000;
end
endcase
end else
if (M16 || M17) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0000001,intproc}; // ~wr
state <= 3'b001;
end
3'b001: begin
state <= 3'b010;
end
3'b010: begin
if (M16) begin
M16 <= 0;
end else begin
{FC,H,L} <= {1'b0,H,L}+{1'b0,W,Z};
M17 <= 0;
end
state <= 3'b000;
end
endcase
end
end
end
endmodule

View File

@@ -1,95 +0,0 @@
// ====================================================================
// Bashkiria-2M FPGA REPLICA
//
// Copyright (C) 2010 Dmitry Tselikov
//
// This core is distributed under modified BSD license.
// For complete licensing information see LICENSE.TXT.
// --------------------------------------------------------------------
//
// An open implementation of Bashkiria-2M home computer
//
// Author: Dmitry Tselikov http://bashkiria-2m.narod.ru/
//
// Design File: k580wn59.v
//
// Programmable interrupt controller k580wn59 design file of Bashkiria-2M replica.
//
// Warning: Interrupt level shift not supported.
module k580wn59(
input clk, input reset, input addr, input we_n,
input[7:0] idata, output reg[7:0] odata,
output intr, input inta_n, input[7:0] irq);
reg[1:0] state;
reg[7:0] irqmask;
reg[7:0] smask;
reg[7:0] serviced;
reg[2:0] addr0;
reg[7:0] addr1;
reg init;
reg addrfmt;
reg exinta_n;
wire[7:0] r = irq & ~(irqmask | smask);
assign intr = |r;
reg[2:0] x;
always @(*)
casex (r)
8'bxxxxxxx1: x = 3'b000;
8'bxxxxxx10: x = 3'b001;
8'bxxxxx100: x = 3'b010;
8'bxxxx1000: x = 3'b011;
8'bxxx10000: x = 3'b100;
8'bxx100000: x = 3'b101;
8'bx1000000: x = 3'b110;
default: x = 3'b111;
endcase
always @(*)
casex ({inta_n,state})
3'b000: odata = 8'hCD;
3'bx01: odata = addrfmt ? {addr0,x,2'b00} : {addr0[2:1],x,3'b000};
3'bx1x: odata = addr1;
3'b100: odata = addr ? irqmask : irq;
endcase
always @(posedge clk or posedge reset) begin
if (reset) begin
state <= 0; init <= 0; irqmask <= 8'hFF; smask <= 8'hFF; serviced <= 0; exinta_n <= 1'b1;
end else begin
exinta_n <= inta_n;
smask <= smask & (irq|serviced);
case (state)
2'b00: begin
if (~we_n) begin
init <= 0;
casex ({addr,idata[4:3]})
3'b000:
case (idata[7:5])
3'b001: serviced <= 0;
3'b011: serviced[idata[2:0]] <= 0;
endcase
3'b01x: begin init <= 1'b1; addr0 <= idata[7:5]; addrfmt <= idata[2]; end
3'b1xx: if (init) addr1 <= idata; else irqmask <= idata;
endcase
end
if (inta_n&~exinta_n) state <= 2'b01;
end
2'b01: begin
if (inta_n&~exinta_n) state <= 2'b10;
end
2'b10: begin
if (inta_n&~exinta_n) begin
state <= 2'b00;
smask[x] <= 1'b1;
serviced[x] <= 1'b1;
end
end
endcase
end
end
endmodule

View File

@@ -1,52 +0,0 @@
// ====================================================================
// Bashkiria-2M FPGA REPLICA
//
// Copyright (C) 2010 Dmitry Tselikov
//
// This core is distributed under modified BSD license.
// For complete licensing information see LICENSE.TXT.
// --------------------------------------------------------------------
//
// An open implementation of Bashkiria-2M home computer
//
// Author: Dmitry Tselikov http://bashkiria-2m.narod.ru/
//
// Design File: k580ww55.v
//
// Parallel interface k580ww55 design file of Bashkiria-2M replica.
//
// Warning: This realization is not fully operational.
module k580ww55(
input clk, input reset, input[1:0] addr, input we_n,
input[7:0] idata, output reg[7:0] odata,
input[7:0] ipa, output reg[7:0] opa,
input[7:0] ipb, output reg[7:0] opb,
input[7:0] ipc, output reg[7:0] opc);
//reg[6:0] mode;
always begin
case (addr)
2'b00: odata = ipa;
2'b01: odata = ipb;
2'b10: odata = ipc;
2'b11: odata = 8'h00;
endcase
end
always @(posedge clk or posedge reset) begin
if (reset) begin
//mode <= 7'b0011011;
{opa,opb,opc} <= {8'hFF,8'hFF,8'hFF};
end else
if (~we_n) begin
if (addr==2'b00) opa <= idata;
if (addr==2'b01) opb <= idata;
if (addr==2'b10) opc <= idata;
//if (addr==2'b11 && idata[7]) mode <= idata[6:0];
if (addr==2'b11 && ~idata[7]) opc[idata[3:1]] <= idata[0];
end
end
endmodule

View File

@@ -1,26 +0,0 @@
/* Atari on an FPGA
Masters of Engineering Project
Cornell University, 2007
Daniel Beer
RIOT.h
Header file that contains useful definitions for the RIOT module.
*/
`define READ_RAM 7'b01xxxxx
`define WRITE_RAM 7'b00xxxxx
`define READ_DRA 7'b11xx000
`define WRITE_DRA 7'b10xx000
`define READ_DDRA 7'b11xx001
`define WRITE_DDRA 7'b10xx001
`define READ_DRB 7'b11xx010
`define WRITE_DRB 7'b10xx010
`define READ_DDRB 7'b11xx011
`define WRITE_DDRB 7'b10xx011
`define WRITE_TIMER 7'b101x1xx
`define READ_TIMER 7'b11xx1x0
`define READ_INT_FLAG 7'b11xx1x1
`define WRITE_EDGE_DETECT 7'b100x1x0
`define NOP 7'b0100000
`define TM_1 2'b00
`define TM_8 2'b01
`define TM_64 2'b10
`define TM_1024 2'b11

View File

@@ -1,81 +0,0 @@
/* Atari on an FPGA
Masters of Engineering Project
Cornell University, 2007
Daniel Beer
TIA.h
Header file that contains useful definitions for the TIA module.
*/
`define CXM0P 7'h70
`define CXM1P 7'h71
`define CXP0FB 7'h72
`define CXP1FB 7'h73
`define CXM0FB 7'h74
`define CXM1FB 7'h75
`define CXBLPF 7'h76
`define CXPPMM 7'h77
`define INPT0 7'h78
`define INPT1 7'h79
`define INPT2 7'h7A
`define INPT3 7'h7B
`define INPT4 7'h7C
`define INPT5 7'h7D
`define VSYNC 7'h00
`define VBLANK 7'h01
`define WSYNC 7'h02
`define RSYNC 7'h03
`define NUSIZ0 7'h04
`define NUSIZ1 7'h05
`define COLUP0 7'h06
`define COLUP1 7'h07
`define COLUPF 7'h08
`define COLUBK 7'h09
`define CTRLPF 7'h0A
`define REFP0 7'h0B
`define REFP1 7'h0C
`define PF0 7'h0D
`define PF1 7'h0E
`define PF2 7'h0F
`define RESP0 7'h10
`define RESP1 7'h11
`define RESM0 7'h12
`define RESM1 7'h13
`define RESBL 7'h14
`define AUDC0 7'h15
`define AUDC1 7'h16
`define AUDF0 7'h17
`define AUDF1 7'h18
`define AUDV0 7'h19
`define AUDV1 7'h1A
`define GRP0 7'h1B
`define GRP1 7'h1C
`define ENAM0 7'h1D
`define ENAM1 7'h1E
`define ENABL 7'h1F
`define HMP0 7'h20
`define HMP1 7'h21
`define HMM0 7'h22
`define HMM1 7'h23
`define HMBL 7'h24
`define VDELP0 7'h25
`define VDELP1 7'h26
`define VDELBL 7'h27
`define RESMP0 7'h28
`define RESMP1 7'h29
`define HMOVE 7'h2A
`define HMCLR 7'h2B
`define CXCLR 7'h2C
`define CXM0P_7800 7'h40
`define CXM1P_7800 7'h41
`define CXP0FB_7800 7'h42
`define CXP1FB_7800 7'h43
`define CXM0FB_7800 7'h44
`define CXM1FB_7800 7'h45
`define CXBLPF_7800 7'h46
`define CXPPMM_7800 7'h47
`define INPT0_7800 7'h48
`define INPT1_7800 7'h49
`define INPT2_7800 7'h4A
`define INPT3_7800 7'h4B
`define INPT4_7800 7'h4C
`define INPT5_7800 7'h4D