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:
@@ -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
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
@@ -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
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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;
|
||||
@@ -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
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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
|
||||
--
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
219
common/PIO.vhd
219
common/PIO.vhd
@@ -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;
|
||||
174
common/RIOT.sv
174
common/RIOT.sv
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
477
common/TIA.sv
477
common/TIA.sv
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user