This commit is contained in:
aschi54
2010-12-27 13:20:36 +00:00
commit 1b6b1201a2
427 changed files with 91737 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2009 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus II
# Version 9.1 Build 222 10/21/2009 SJ Web Edition
# Date created = 12:11:46 March 06, 2010
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# Coldari1_assignment_defaults.qdf
# If this file doesn't exist, see file:
# assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
# file is updated automatically by the Quartus II software
# and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #
set_global_assignment -name FAMILY "Stratix II"
set_global_assignment -name DEVICE AUTO
set_global_assignment -name TOP_LEVEL_ENTITY Coldari1
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 9.1
set_global_assignment -name PROJECT_CREATION_TIME_DATE "12:11:46 MARCH 06, 2010"
set_global_assignment -name LAST_QUARTUS_VERSION 9.1

View File

@@ -0,0 +1,79 @@
-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.
-- Copyright (C) 1991-2008 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- Generated by Quartus II Version 8.1 (Build Build 163 10/28/2008)
-- Created on Tue Sep 08 16:24:57 2009
LIBRARY ieee;
USE ieee.std_logic_1164.all;
-- Entity Declaration
ENTITY DSP IS
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
PORT
(
CLK33M : IN STD_LOGIC;
MAIN_CLK : IN STD_LOGIC;
nFB_OE : IN STD_LOGIC;
nFB_WR : IN STD_LOGIC;
nFB_CS1 : IN STD_LOGIC;
nFB_CS2 : IN STD_LOGIC;
FB_SIZE0 : IN STD_LOGIC;
FB_SIZE1 : IN STD_LOGIC;
nFB_BURST : IN STD_LOGIC;
FB_ADR : IN STD_LOGIC_VECTOR(31 downto 0);
nRSTO : IN STD_LOGIC;
nFB_CS3 : IN STD_LOGIC;
nSRCS : INOUT STD_LOGIC;
nSRBLE : OUT STD_LOGIC;
nSRBHE : OUT STD_LOGIC;
nSRWE : OUT STD_LOGIC;
nSROE : OUT STD_LOGIC;
DSP_INT : OUT STD_LOGIC;
DSP_TA : OUT STD_LOGIC;
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0);
IO : INOUT STD_LOGIC_VECTOR(17 downto 0);
SRD : INOUT STD_LOGIC_VECTOR(15 downto 0)
);
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
END DSP;
-- Architecture Body
ARCHITECTURE DSP_architecture OF DSP IS
BEGIN
nSRCS <= '0' when nFB_CS2 = '0' and FB_ADR(27 downto 24) = x"4" else '1'; --nFB_CS3;
nSRBHE <= '0' when FB_ADR(0 downto 0) = "0" else '1';
nSRBLE <= '1' when FB_ADR(0 downto 0) = "0" and FB_SIZE1 = '0' and FB_SIZE0 = '1' else '0';
nSRWE <= '0' when nFB_WR = '0' and nSRCS = '0' and MAIN_CLK = '0' else '1';
nSROE <= '0' when nFB_OE = '0' and nSRCS = '0' else '1';
DSP_INT <= '0';
DSP_TA <= '0';
IO(17 downto 0) <= FB_ADR(18 downto 1);
SRD(15 downto 0) <= FB_AD(31 downto 16) when nFB_WR = '0' and nSRCS = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= SRD(15 downto 0) when nFB_OE = '0' and nSRCS = '0' else "ZZZZZZZZZZZZZZZZ";
END DSP_architecture;

View File

@@ -0,0 +1,79 @@
-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.
-- Copyright (C) 1991-2008 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- Generated by Quartus II Version 8.1 (Build Build 163 10/28/2008)
-- Created on Tue Sep 08 16:24:57 2009
LIBRARY ieee;
USE ieee.std_logic_1164.all;
-- Entity Declaration
ENTITY DSP IS
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
PORT
(
CLK33M : IN STD_LOGIC;
MAIN_CLK : IN STD_LOGIC;
nFB_OE : IN STD_LOGIC;
nFB_WR : IN STD_LOGIC;
nFB_CS1 : IN STD_LOGIC;
nFB_CS2 : IN STD_LOGIC;
FB_SIZE0 : IN STD_LOGIC;
FB_SIZE1 : IN STD_LOGIC;
nFB_BURST : IN STD_LOGIC;
FB_ADR : IN STD_LOGIC_VECTOR(31 downto 0);
nRSTO : IN STD_LOGIC;
nFB_CS3 : IN STD_LOGIC;
nSRCS : OUT STD_LOGIC;
nSRBLE : OUT STD_LOGIC;
nSRBHE : OUT STD_LOGIC;
nSRWE : OUT STD_LOGIC;
nSROE : OUT STD_LOGIC;
DSP_INT : OUT STD_LOGIC;
DSP_TA : OUT STD_LOGIC;
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0);
IO : INOUT STD_LOGIC_VECTOR(17 downto 0);
SRD : INOUT STD_LOGIC_VECTOR(15 downto 0)
);
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
END DSP;
-- Architecture Body
ARCHITECTURE DSP_architecture OF DSP IS
BEGIN
nSRCS <= '0' when nFB_CS2 = '0' and FB_ADR(27 downto 24) = x"4" else '1'; --nFB_CS3;
nSRBHE <= '0' when FB_ADR(0 downto 0) = "0" else '1';
nSRBLE <= '1' when FB_ADR(0 downto 0) = "0" and FB_SIZE1 = '0' and FB_SIZE0 = '1' else '0';
nSRWE <= '0' when nFB_WR = '0' and nSRCS = '0' and MAIN_CLK = '0' else '1';
nSROE <= '0' when nFB_OE = '0' and nSRCS = '0' else '1';
DSP_INT <= '0';
DSP_TA <= '0';
IO(17 downto 0) <= FB_ADR(18 downto 1);
SRD(15 downto 0) <= FB_AD(31 downto 16) when nFB_WR = '0' and nSRCS = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= SRD(15 downto 0) when nFB_OE = '0' and nSRCS = '0' else "ZZZZZZZZZZZZZZZZ";
END DSP_architecture;

Binary file not shown.

View File

@@ -0,0 +1,216 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
use work.constants_pkg.all;
entity adgen_stage is port(
activate_adgen : in std_logic;
activate_x_mem : in std_logic;
activate_y_mem : in std_logic;
activate_l_mem : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
optional_ea_word : in std_logic_vector(23 downto 0);
register_file : in register_file_type;
adgen_mode_a : in adgen_mode_type;
adgen_mode_b : in adgen_mode_type;
address_out_x : out unsigned(BW_ADDRESS-1 downto 0);
address_out_y : out unsigned(BW_ADDRESS-1 downto 0);
wr_R_port_A_valid : out std_logic;
wr_R_port_A : out addr_wr_port_type;
wr_R_port_B_valid : out std_logic;
wr_R_port_B : out addr_wr_port_type
);
end entity;
architecture rtl of adgen_stage is
signal address_out_x_int : unsigned(BW_ADDRESS-1 downto 0);
begin
address_out_x <= address_out_x_int;
address_generator_X: process(activate_adgen, instr_word, register_file, adgen_mode_a) is
variable r_reg_local : unsigned(BW_ADDRESS-1 downto 0);
variable n_reg_local : unsigned(BW_ADDRESS-1 downto 0);
variable m_reg_local : unsigned(BW_ADDRESS-1 downto 0);
variable op1 : unsigned(BW_ADDRESS-1 downto 0);
variable op2 : unsigned(BW_ADDRESS-1 downto 0);
variable addr_mod : unsigned(BW_ADDRESS-1 downto 0);
variable new_r_reg : unsigned(BW_ADDRESS-1 downto 0);
variable new_r_reg_interm : unsigned(BW_ADDRESS-1 downto 0);
variable modulo_bitmask : std_logic_vector(BW_ADDRESS-1 downto 0);
variable bit_set : std_logic;
begin
r_reg_local := register_file.addr_r(to_integer(unsigned(instr_word(10 downto 8))));
n_reg_local := register_file.addr_n(to_integer(unsigned(instr_word(10 downto 8))));
m_reg_local := register_file.addr_m(to_integer(unsigned(instr_word(10 downto 8))));
-- select the operands for the calculation
case adgen_mode_a is
-- (Rn) - Nn
when POST_MIN_N => addr_mod := unsigned(- signed(n_reg_local));
-- (Rn) + Nn
when POST_PLUS_N => addr_mod := n_reg_local;
-- (Rn)-
when POST_MIN_1 => addr_mod := (others => '1'); -- -1
-- (Rn)+
when POST_PLUS_1 => addr_mod := to_unsigned(1, BW_ADDRESS);
-- (Rn)
when NOP => addr_mod := (others => '0');
-- (Rn + Nn)
when INDEXED_N => addr_mod := n_reg_local;
-- -(Rn)
when PRE_MIN_1 => addr_mod := (others => '1'); -- - 1
-- absolute address (appended to instruction word)
when ABSOLUTE => addr_mod := (others => '0');
when IMMEDIATE => addr_mod := (others => '0');
end case;
op1 := r_reg_local;
op2 := addr_mod;
-- linear addressing
if m_reg_local = 2**BW_ADDRESS-1 then
op1 := r_reg_local;
op2 := addr_mod;
-- bit reverse operation
elsif m_reg_local = 0 then
-- reverse the input to the adder bit wise
-- so we just need to use a single adder
for i in 0 to BW_ADDRESS-1 loop
op1(BW_ADDRESS - 1 - i) := r_reg_local(i);
op2(BW_ADDRESS - 1 - i) := addr_mod(i);
end loop;
-- modulo arithmetic
else
bit_set := '0';
for i in BW_ADDRESS-1 downto 0 loop
if m_reg_local(i) = '1' then
bit_set := '1';
end if;
if bit_set = '1' then
modulo_bitmask(i) := '0';
else
modulo_bitmask(i) := '1';
end if;
end loop;
end if;
new_r_reg_interm := op1 + op2;
new_r_reg := new_r_reg_interm;
-- linear addressing
if m_reg_local = 2**BW_ADDRESS-1 then
new_r_reg := new_r_reg_interm;
-- bit reverse operation
elsif m_reg_local = 0 then
for i in 0 to BW_ADDRESS-1 loop
new_r_reg(BW_ADDRESS - 1 - i) := new_r_reg_interm(i);
end loop;
else
end if;
-- store the updated register in the global register file
-- do not store when we do nothing or there is nothing to update
-- LUA instructions DO NOT UPDATE the source register!!
if (adgen_mode_a = NOP or adgen_mode_a = ABSOLUTE or adgen_mode_a = IMMEDIATE or instr_array = INSTR_LUA) then
wr_R_port_A_valid <= '0';
else
wr_R_port_A_valid <= '1';
end if;
wr_R_port_A.reg_number <= unsigned(instr_word(10 downto 8));
wr_R_port_A.reg_value <= new_r_reg;
-- select the output of the AGU
case adgen_mode_a is
-- (Rn) - Nn
when POST_MIN_N => address_out_x_int <= r_reg_local;
-- (Rn) + Nn
when POST_PLUS_N => address_out_x_int <= r_reg_local;
-- (Rn)-
when POST_MIN_1 => address_out_x_int <= r_reg_local;
-- (Rn)+
when POST_PLUS_1 => address_out_x_int <= r_reg_local;
-- (Rn)
when NOP => address_out_x_int <= r_reg_local;
-- (Rn + Nn)
when INDEXED_N => address_out_x_int <= new_r_reg;
-- -(Rn)
when PRE_MIN_1 => address_out_x_int <= new_r_reg;
-- absolute address (appended to instruction word)
when ABSOLUTE => address_out_x_int <= unsigned(optional_ea_word(BW_ADDRESS-1 downto 0));
when IMMEDIATE => address_out_x_int <= r_reg_local; -- Done externally, value never used
end case;
-- LUA instructions only use the updated address!
if instr_array = INSTR_LUA then
address_out_x_int <= new_r_reg;
end if;
end process address_generator_X;
address_generator_Y: process(activate_adgen, activate_x_mem, activate_y_mem, activate_l_mem, instr_word,
register_file, adgen_mode_b, address_out_x_int) is
variable r_reg_local : unsigned(BW_ADDRESS-1 downto 0);
variable n_reg_local : unsigned(BW_ADDRESS-1 downto 0);
variable m_reg_local : unsigned(BW_ADDRESS-1 downto 0);
variable op2 : unsigned(BW_ADDRESS-1 downto 0);
variable new_r_reg : unsigned(BW_ADDRESS-1 downto 0);
begin
r_reg_local := register_file.addr_r(to_integer(unsigned((not instr_word(10)) & instr_word(14 downto 13))));
n_reg_local := register_file.addr_n(to_integer(unsigned((not instr_word(10)) & instr_word(14 downto 13))));
m_reg_local := register_file.addr_m(to_integer(unsigned((not instr_word(10)) & instr_word(14 downto 13))));
-- select the operands for the calculation
case adgen_mode_b is
-- (Rn) + Nn
when POST_PLUS_N => op2 := n_reg_local;
-- (Rn)-
when POST_MIN_1 => op2 := (others => '1'); -- -1
-- (Rn)+
when POST_PLUS_1 => op2 := to_unsigned(1, BW_ADDRESS);
-- (Rn)
when others => op2 := (others => '0');
end case;
new_r_reg := r_reg_local + op2;
-- TODO: USE modifier register!
-- store the updated register in the global register file
-- do not store when we do nothing or there is nothing to update
if adgen_mode_b = NOP then
wr_R_port_B_valid <= '0';
else
wr_R_port_B_valid <= '1';
end if;
wr_R_port_B.reg_number <= unsigned((not instr_word(10)) & instr_word(14 downto 13));
wr_R_port_B.reg_value <= new_r_reg;
-- the address for the y memory is calculated in the first AGU if the x memory is not accessed!
-- so use the other output as address output for the y memory!
-- Furthermore, use the same address for L memory accesses (X and Y memory access the same address!)
if (activate_y_mem = '1' and activate_x_mem = '0') or activate_l_mem = '1' then
address_out_y <= address_out_x_int;
-- in any other case use the locally computed value
else
-- select the output of the AGU
case adgen_mode_b is
-- (Rn) + Nn
when POST_PLUS_N => address_out_y <= r_reg_local;
-- (Rn)-
when POST_MIN_1 => address_out_y <= r_reg_local;
-- (Rn)+
when POST_PLUS_1 => address_out_y <= r_reg_local;
-- (Rn)
when others => address_out_y <= r_reg_local;
end case;
end if;
end process address_generator_Y;
end architecture;

View File

@@ -0,0 +1,62 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
package constants_pkg is
-------------------------
-- Flags in CCR register
-------------------------
constant C_FLAG : natural := 0;
constant V_FLAG : natural := 1;
constant Z_FLAG : natural := 2;
constant N_FLAG : natural := 3;
constant U_FLAG : natural := 4;
constant E_FLAG : natural := 5;
constant L_FLAG : natural := 6;
constant S_FLAG : natural := 7;
-------------------
-- Pipeline stages
-------------------
constant ST_FETCH : natural := 0;
constant ST_FETCH2 : natural := 1;
constant ST_DECODE : natural := 2;
constant ST_ADGEN : natural := 3;
constant ST_EXEC : natural := 4;
----------------------
-- Activation signals
----------------------
constant ACT_ADGEN : natural := 0; -- Run the address generator
constant ACT_ALU : natural := 1; -- Activation of ALU results in modification of the status register
constant ACT_EXEC_BRA : natural := 2; -- Branch (in execute stage)
constant ACT_EXEC_CR_MOD : natural := 3; -- Control Register Modification (in execute stage)
constant ACT_EXEC_LOOP : natural := 4; -- Loop instruction (REP, DO)
constant ACT_X_MEM_RD : natural := 5; -- Init read from X memory
constant ACT_Y_MEM_RD : natural := 6; -- Init read from Y memory
constant ACT_P_MEM_RD : natural := 7; -- Init read from P memory
constant ACT_X_MEM_WR : natural := 8; -- Init write to X memory
constant ACT_Y_MEM_WR : natural := 9; -- Init write to Y memory
constant ACT_P_MEM_WR : natural := 10; -- Init write to P memory
constant ACT_REG_RD : natural := 11; -- Read from register (6 bit addressing)
constant ACT_REG_WR : natural := 12; -- Write to register (6 bit addressing)
constant ACT_IMM_8BIT : natural := 13; -- 8 bit immediate operand (in instruction word)
constant ACT_IMM_12BIT : natural := 14; -- 12 bit immediate operand (in instruction word)
constant ACT_IMM_LONG : natural := 15; -- 24 bit immediate operant (in optional instruction word)
constant ACT_X_BUS_RD : natural := 16; -- Read data via X-bus (from x0,x1,a,b)
constant ACT_X_BUS_WR : natural := 17; -- Write data via X-bus (to x0,x1,a,b)
constant ACT_Y_BUS_RD : natural := 18; -- Read data via Y-bus (from y0,y1,a,b)
constant ACT_Y_BUS_WR : natural := 19; -- Write data via Y-bus (to y0,y1,a,b)
constant ACT_L_BUS_RD : natural := 20; -- Read data via L-bus (from a10, b10,x,y,a,b,ab,ba)
constant ACT_L_BUS_WR : natural := 21; -- Write data via L-bus (to a10, b10,x,y,a,b,ab,ba)
constant ACT_BIT_MOD_WR : natural := 22; -- Bit modify write (to set for BSET, BCLR, BCHG)
constant ACT_REG_WR_CC : natural := 23; -- Write to register file conditionally (Tcc)
constant ACT_ALU_WR_CC : natural := 24; -- Write ALU result conditionally (Tcc)
constant ACT_NORM : natural := 25; -- NORM instruction needs special handling
end package constants_pkg;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,603 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
use work.constants_pkg.all;
entity exec_stage_alu is port(
alu_activate : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
alu_ctrl : in alu_ctrl_type;
register_file : in register_file_type;
addr_r_in : in unsigned(BW_ADDRESS-1 downto 0);
addr_r_out : out unsigned(BW_ADDRESS-1 downto 0);
modify_accu : out std_logic;
dst_accu : out std_logic;
modified_accu : out signed(55 downto 0);
modify_sr : out std_logic;
modified_sr : out std_logic_vector(15 downto 0)
);
end entity;
architecture rtl of exec_stage_alu is
signal alu_shifter_out : signed(55 downto 0);
signal alu_shifter_carry_out : std_logic;
signal alu_shifter_overflow_out : std_logic;
signal alu_logic_conj : signed(55 downto 0);
signal alu_multiplier_out : signed(55 downto 0);
signal alu_src_op : signed(55 downto 0);
signal alu_add_result : signed(56 downto 0);
signal alu_add_carry_out : std_logic;
signal alu_post_adder_result : signed(56 downto 0);
signal scaling_mode : std_logic_vector(1 downto 0);
signal modified_accu_int : signed(55 downto 0);
signal norm_instr_asl : std_logic;
signal norm_instr_asr : std_logic;
signal norm_instr_nop : std_logic;
signal norm_update_ccr : std_logic;
begin
-- store calculated value?
modify_accu <= alu_ctrl.store_result;
modified_accu <= modified_accu_int;
-- for the norm instruction we first need to determine whether we have to
-- update the CCR register or not
modify_sr <= alu_activate when alu_ctrl.norm_instr = '0' else
norm_update_ccr;
dst_accu <= alu_ctrl.dst_accu;
scaling_mode <= register_file.sr(11 downto 10);
calcule_ccr_flags: process(register_file, alu_ctrl, alu_shifter_carry_out,
alu_post_adder_result, modified_accu_int, alu_add_carry_out) is
begin
-- by default do not modify the flags in the status register
modified_sr <= register_file.sr;
-- Carry flag generation
-------------------------
case alu_ctrl.ccr_flags_ctrl(C_FLAG) is
when CLEAR => modified_sr(C_FLAG) <= '0';
when SET => modified_sr(C_FLAG) <= '1';
when MODIFY =>
-- the carry flag can stem from the shifter or from the post adder
-- in case we shift and add only a zero to the shift result (ASL, ASR, LSL, LSR, ROL, ROR)
-- take the carry flag from the shifter, else from the post adder
if (alu_ctrl.shift_mode = SHIFT_LEFT or alu_ctrl.shift_mode = SHIFT_RIGHT) and
alu_ctrl.add_src_stage_2 = "00" then -- add zero after shifting?
modified_sr(C_FLAG) <= alu_shifter_carry_out;
elsif alu_ctrl.div_instr = '1' then
modified_sr(C_FLAG) <= not std_logic(alu_post_adder_result(55));
else
-- modified_sr(C_FLAG) <= std_logic(alu_post_adder_result(57));
modified_sr(C_FLAG) <= alu_add_carry_out;
end if;
when others => -- Don't touch
end case;
-- Overflow flag generation
----------------------------
case alu_ctrl.ccr_flags_ctrl(V_FLAG) is
when CLEAR => modified_sr(V_FLAG) <= '0';
when SET => modified_sr(V_FLAG) <= '1';
when MODIFY =>
-- There are two sources for the overflow flag:
-- 1)
-- in case the result cannot be represented using 56 bits set
-- the overflow flag. this is the case when the two MSBs of
-- the 57 bit result are different
-- 2)
-- The shifter circuit performs a 56 bit left shift. In case the
-- two MSBs of the operand are different set the overflow flag as well
if (alu_ctrl.div_instr = '0' and alu_post_adder_result(56) /= alu_post_adder_result(55)) or
(alu_ctrl.shift_mode = SHIFT_LEFT and alu_ctrl.word_24_update = '0' and
alu_shifter_overflow_out = '1' ) then
modified_sr(V_FLAG) <= '1';
else
modified_sr(V_FLAG) <= '0';
end if;
when others => -- Don't touch
end case;
-- Zero flag generation
----------------------------
case alu_ctrl.ccr_flags_ctrl(Z_FLAG) is
when CLEAR => modified_sr(Z_FLAG) <= '0';
when SET => modified_sr(Z_FLAG) <= '1';
when MODIFY =>
-- in case the result is zero set this flag
-- distinguish between 24 bit and 56 bit ALU operations
-- 24 bit instructions are LSL, LSR, ROR, ROL, OR, EOR, NOT, AND
if (alu_ctrl.word_24_update = '1' and modified_accu_int(47 downto 24) = 0) or
(alu_ctrl.word_24_update = '0' and modified_accu_int(55 downto 0) = 0) then
modified_sr(Z_FLAG) <= '1';
else
modified_sr(Z_FLAG) <= '0';
end if;
when others => -- Don't touch
end case;
-- Negative flag generation
----------------------------
case alu_ctrl.ccr_flags_ctrl(N_FLAG) is
when CLEAR => modified_sr(N_FLAG) <= '0';
when SET => modified_sr(N_FLAG) <= '1';
when MODIFY =>
-- in case the result is negative set this flag
-- distinguish between 24 bit and 56 bit ALU operations
-- 24 bit instructions are LSL, LSR, ROR, ROL, OR, EOR, NOT, AND
if alu_ctrl.word_24_update = '1' then
modified_sr(N_FLAG) <= std_logic(modified_accu_int(47));
else
modified_sr(N_FLAG) <= std_logic(modified_accu_int(55));
end if;
when others => -- Don't touch
end case;
-- Unnormalized flag generation
----------------------------
case alu_ctrl.ccr_flags_ctrl(U_FLAG) is
when CLEAR => modified_sr(U_FLAG) <= '0';
when SET => modified_sr(U_FLAG) <= '1';
when MODIFY =>
-- Set unnormalized bit according to the scaling mode
if (scaling_mode = "00" and alu_post_adder_result(47) = alu_post_adder_result(46)) or
(scaling_mode = "01" and alu_post_adder_result(48) = alu_post_adder_result(47)) or
(scaling_mode = "10" and alu_post_adder_result(46) = alu_post_adder_result(45)) then
modified_sr(U_FLAG) <= '1';
else
modified_sr(U_FLAG) <= '0';
end if;
when others => -- Don't touch
end case;
-- Extension flag generation
----------------------------
case alu_ctrl.ccr_flags_ctrl(E_FLAG) is
when CLEAR => modified_sr(E_FLAG) <= '0';
when SET => modified_sr(E_FLAG) <= '1';
when MODIFY =>
-- Set extension flag by default
modified_sr(E_FLAG) <= '1';
-- Clear extension flag according to the scaling mode
case scaling_mode is
when "00" =>
if alu_post_adder_result(55 downto 47) = "111111111" or alu_post_adder_result(55 downto 47) = "000000000" then
modified_sr(E_FLAG) <= '0';
end if;
when "01" =>
if alu_post_adder_result(55 downto 48) = "11111111" or alu_post_adder_result(55 downto 48) = "00000000" then
modified_sr(E_FLAG) <= '0';
end if;
when "10" =>
if alu_post_adder_result(55 downto 46) = "1111111111" or alu_post_adder_result(55 downto 46) = "0000000000" then
modified_sr(E_FLAG) <= '0';
end if;
when others =>
modified_sr(E_FLAG) <= '0';
end case;
when others => -- Don't touch
end case;
-- Limit flag generation (equals overflow flag generaton!)
-- Clearing of the Limit flag has to be done by the user!
-----------------------------------------------------------
case alu_ctrl.ccr_flags_ctrl(L_FLAG) is
when CLEAR => modified_sr(L_FLAG) <= '0';
when SET => modified_sr(L_FLAG) <= '1';
when MODIFY =>
-- There are two sources for the overflow flag:
-- 1)
-- in case the result cannot be represented using 56 bits set
-- the overflow flag. this is the case when the two MSBs of
-- the 57 bit result are different
-- 2)
-- The shifter circuit performs a 56 bit left shift. In case the
-- two MSBs of the operand are different set the overflow flag as well
if (alu_ctrl.div_instr = '0' and alu_post_adder_result(56) /= alu_post_adder_result(55)) or
(alu_ctrl.shift_mode = SHIFT_LEFT and alu_ctrl.word_24_update = '0' and
alu_shifter_overflow_out = '1' ) then
modified_sr(L_FLAG) <= '1';
end if;
when others => -- Don't touch
end case;
-- Scaling flag generation (DSP56002 and up)
--------------------------------------------
-- Scaling flag is not generated in the ALU, but when A or B are read to the XDB or YDB
end process;
src_operand_select: process(register_file, alu_ctrl) is
begin
-- decoding according similar to JJJ representation
case alu_ctrl.add_src_stage_1 is
when "000" =>
-- select depending on destination accu
if alu_ctrl.dst_accu = '0' then
alu_src_op <= register_file.a;
else
alu_src_op <= register_file.b;
end if;
when "001" => -- A,B or B,A
-- select depending on destination accu
if alu_ctrl.dst_accu = '0' then
alu_src_op <= register_file.b;
else
alu_src_op <= register_file.a;
end if;
when "010" => -- X
alu_src_op(55 downto 48) <= (others => register_file.x1(23));
alu_src_op(47 downto 0) <= register_file.x1 & register_file.x0;
when "011" => -- Y
alu_src_op(55 downto 48) <= (others => register_file.y1(23));
alu_src_op(47 downto 0) <= register_file.y1 & register_file.y0;
when "100" => -- x0
alu_src_op(55 downto 48) <= (others => register_file.x0(23));
alu_src_op(47 downto 24) <= register_file.x0;
alu_src_op(23 downto 0) <= (others => '0');
when "101" => -- y0
alu_src_op(55 downto 48) <= (others => register_file.y0(23));
alu_src_op(47 downto 24) <= register_file.y0;
alu_src_op(23 downto 0) <= (others => '0');
when "110" => -- x1
alu_src_op(55 downto 48) <= (others => register_file.x1(23));
alu_src_op(47 downto 24) <= register_file.x1;
alu_src_op(23 downto 0) <= (others => '0');
when "111" => -- y1
alu_src_op(55 downto 48) <= (others => register_file.y1(23));
alu_src_op(47 downto 24) <= register_file.y1;
alu_src_op(23 downto 0) <= (others => '0');
when others =>
end case;
end process;
alu_logical_functions: process(alu_ctrl, alu_src_op, alu_shifter_out) is
begin
alu_logic_conj <= alu_shifter_out;
case alu_ctrl.logic_function is
when "110" =>
alu_logic_conj(47 downto 24) <= alu_shifter_out(47 downto 24) and alu_src_op(47 downto 24);
when "010" =>
alu_logic_conj(47 downto 24) <= alu_shifter_out(47 downto 24) or alu_src_op(47 downto 24);
when "011" =>
alu_logic_conj(47 downto 24) <= alu_shifter_out(47 downto 24) xor alu_src_op(47 downto 24);
when "111" =>
alu_logic_conj(47 downto 24) <= not alu_shifter_out(47 downto 24);
when others =>
end case;
end process;
alu_adder : process(alu_ctrl, alu_src_op, alu_multiplier_out, alu_shifter_out) is
variable add_src_op_1 : signed(56 downto 0);
variable add_src_op_2 : signed(56 downto 0);
variable carry_const : signed(56 downto 0);
variable alu_shifter_out_57 : signed(56 downto 0);
variable alu_add_result_58 : signed(57 downto 0);
variable alu_add_result_interm : signed(56 downto 0);
variable invert_carry_flag : std_logic;
begin
-- by default do not invert the carry
invert_carry_flag := '0';
-- determine whether to use multiplier output, the operand defined above, or zeros!
-- resizing is done here already. Like that we can see whether an overflow
-- occurs due to negating the source operand
case alu_ctrl.add_src_stage_2 is
when "00" => add_src_op_1 := (others => '0');
when "10" => add_src_op_1 := resize(alu_multiplier_out, 57);
when others => add_src_op_1 := resize(alu_src_op, 57);
end case;
-- determine the sign for the 1st operand!
case alu_ctrl.add_src_sign is
-- normal operation
when "00" => add_src_op_1 := add_src_op_1;
-- negative sign
when "01" => add_src_op_1 := - add_src_op_1;
invert_carry_flag := not invert_carry_flag;
-- change according to sign
-- performs - | accu | for the CMPM instruction
when "10" =>
-- we subtract in any case, so invert the carry!
invert_carry_flag := not invert_carry_flag;
if add_src_op_1(55) = '0' then
add_src_op_1 := - add_src_op_1;
else
add_src_op_1 := add_src_op_1;
end if;
-- div instruction!
-- sign dependant of D[55] XOR S[23], if 1 => positive , if 0 => negative
-- add_src_op_1 holds S[23] (sign extension!)
when others =>
if (alu_ctrl.shift_src = '0' and add_src_op_1(55) /= register_file.a(55)) or
(alu_ctrl.shift_src = '1' and add_src_op_1(55) /= register_file.b(55)) then
add_src_op_1 := add_src_op_1;
else
add_src_op_1 := - add_src_op_1;
-- invert_carry_flag := not invert_carry_flag;
end if;
end case;
alu_shifter_out_57 := resize(alu_shifter_out, 57);
-- determine the sign for the 2nd operand (coming from the shifter)!
case alu_ctrl.shift_src_sign is
-- negative sign
when "01" =>
add_src_op_2 := - alu_shifter_out_57;
-- change according to sign
-- this allows to build the magnitude (ABS, CMPM)
when "10" =>
if alu_shifter_out(55) = '1' then
add_src_op_2 := - alu_shifter_out_57;
else
add_src_op_2 := alu_shifter_out_57;
end if;
when others =>
add_src_op_2 := alu_shifter_out_57;
end case;
-- determine whether carry flag has to be added or subtracted
if alu_ctrl.rounding_used = "10" then
-- add carry flag
carry_const(0) := register_file.sr(C_FLAG);
elsif alu_ctrl.rounding_used = "11" then
-- subtract carry flag
carry_const := (others => register_file.sr(0)); -- carry flag
else
carry_const := (others => '0');
end if;
-- add the values and calculate the carry bit
alu_add_result_interm := ('0' & add_src_op_1(55 downto 0)) +
('0' & add_src_op_2(55 downto 0)) +
('0' & carry_const(55 downto 0));
-- here pops the new carry out of the adder
if invert_carry_flag = '0' then
alu_add_carry_out <= alu_add_result_interm(56);
else
alu_add_carry_out <= not alu_add_result_interm(56);
end if;
-- calculate the last bit (56), in order to test for overflow later on
alu_add_result(55 downto 0) <= alu_add_result_interm(55 downto 0);
-- alu_add_result(56) <= add_src_op_1(56) xor add_src_op_2(56) xor alu_add_result_interm(56);
alu_add_result(56) <= add_src_op_1(56) xor add_src_op_2(56)
xor carry_const(56) xor alu_add_result_interm(56);
end process alu_adder;
-- Adder after the normal arithmetic adder
-- This adder is responsible for
-- -- 1) carry addition
-- -- 2) carry subtration
-- 3) convergent rounding
alu_post_adder: process(alu_add_result, scaling_mode, alu_ctrl) is
variable post_adder_constant : signed(56 downto 0);
variable testing_constant : signed(24 downto 0);
begin
-- by default add nothing
post_adder_constant := (others => '0');
case alu_ctrl.rounding_used is
-- rounding dependant on scaling bits
when "01" =>
case scaling_mode is
-- no scaling
when "00" => testing_constant := alu_add_result(23 downto 0) & '0';
-- scale down
when "01" => testing_constant := alu_add_result(24 downto 0);
-- scale up
when "10" => testing_constant := alu_add_result(22 downto 0) & "00";
when others =>
testing_constant := alu_add_result(23 downto 0) & '0';
end case;
-- Special case!
if testing_constant(24) = '1' and testing_constant(23 downto 0) = X"000000" then
-- add depending on bit left to the rounding position
case scaling_mode is
-- no scaling
when "00" => post_adder_constant(23) := alu_add_result(24);
-- scale down
when "01" => post_adder_constant(24) := alu_add_result(25);
-- scale up
when "10" => post_adder_constant(22) := alu_add_result(23);
when others =>
end case;
else -- testing_constant /= X"1000000"
-- add rounding constant depending on scaling mode
-- results in round up if MSB of testing constant is set, else nothing happens
case scaling_mode is
-- no scaling
when "00" => post_adder_constant(23) := '1';
-- scale down
when "01" => post_adder_constant(24) := '1';
-- scale up
when "10" => post_adder_constant(22) := '1';
when others =>
end case;
end if;
-- no rounding
when others =>
post_adder_constant := (others => '0');
end case;
-- Add the result of the first adder to the constant (e.g., carry flag)
alu_post_adder_result <= alu_add_result + post_adder_constant;
-- When rounding is used set 24 LSBs to zero!
if alu_ctrl.rounding_used = "01" then
alu_post_adder_result(23 downto 0) <= (others => '0');
end if;
end process;
alu_select_new_accu: process(alu_post_adder_result, alu_logic_conj, alu_ctrl) is
begin
if alu_ctrl.logic_function /= "000" then
modified_accu_int <= alu_logic_conj;
else
modified_accu_int <= alu_post_adder_result(55 downto 0);
end if;
end process;
-- contains the 24*24 bit fractional multiplier
alu_multiplier : process(register_file, alu_ctrl) is
variable src_op1: signed(23 downto 0);
variable src_op2: signed(23 downto 0);
variable mul_result_interm : signed(47 downto 0);
begin
-- select source operands for multiplication
case alu_ctrl.mul_op1 is
when "00" => src_op1 := register_file.x0;
when "01" => src_op1 := register_file.x1;
when "10" => src_op1 := register_file.y0;
when others => src_op1 := register_file.y1;
end case;
case alu_ctrl.mul_op2 is
when "00" => src_op2 := register_file.x0;
when "01" => src_op2 := register_file.x1;
when "10" => src_op2 := register_file.y0;
when others => src_op2 := register_file.y1;
end case;
-- perform integer multiplication
mul_result_interm := src_op1 * src_op2;
-- sign extension of result
alu_multiplier_out(55 downto 48) <= (others => mul_result_interm(47));
-- convert from two's complement representation to fractional format
-- signed integer multiplication delivers twice the sign bit, but only one is needed for the
-- fractional multiplication, so remove one and append a zero to the result
alu_multiplier_out(47 downto 0) <= mul_result_interm(46 downto 0) & '0';
end process alu_multiplier;
-- contains the data shifter
alu_shifter: process(register_file, alu_ctrl, norm_instr_asl, norm_instr_asr) is
variable src_accu : signed(55 downto 0);
variable shift_to_perform : alu_shift_mode;
begin
-- read source accumulator
if alu_ctrl.shift_src = '0' then
src_accu := register_file.a;
else
src_accu := register_file.b;
end if;
alu_shifter_carry_out <= '0';
alu_shifter_overflow_out <= '0';
-- NORM instruction determines the shift value just
-- in time, so overwrite the flag from the alu_ctrl
-- for this instruction by the calculated value
if alu_ctrl.norm_instr = '0' then
shift_to_perform := alu_ctrl.shift_mode;
else
if norm_instr_asl = '1' then
shift_to_perform := SHIFT_LEFT;
elsif norm_instr_asr = '1' then
shift_to_perform := SHIFT_RIGHT;
else
shift_to_perform := NO_SHIFT;
end if;
end if;
case shift_to_perform is
when NO_SHIFT =>
alu_shifter_out <= src_accu;
when SHIFT_LEFT =>
-- ASL, ADDL, DIV?
if alu_ctrl.word_24_update = '0' then
-- special handling for div instruction required
if alu_ctrl.div_instr = '1' then
alu_shifter_out <= src_accu(54 downto 0) & register_file.sr(C_FLAG);
else
alu_shifter_out <= src_accu(54 downto 0) & '0';
end if;
alu_shifter_carry_out <= src_accu(55);
-- detect overflow that results from left shifting
-- Needed for ASL, ADDL, DIV instructions
if src_accu(55) /= src_accu(54) then
alu_shifter_overflow_out <= '1';
end if;
-- LSL/ROL?
elsif alu_ctrl.word_24_update = '1' then
alu_shifter_out(55 downto 48) <= src_accu(55 downto 48);
alu_shifter_out(23 downto 0) <= src_accu(23 downto 0);
alu_shifter_carry_out <= src_accu(47);
if alu_ctrl.rotate = '0' then -- LSL ?
alu_shifter_out(47 downto 24) <= src_accu(46 downto 24) & '0';
else -- ROL ?
alu_shifter_out(47 downto 24) <= src_accu(46 downto 24) & register_file.sr(C_FLAG);
end if;
end if;
when SHIFT_RIGHT =>
-- ASR?
if alu_ctrl.word_24_update = '0' then
alu_shifter_out <= src_accu(55) & src_accu(55 downto 1);
alu_shifter_carry_out <= src_accu(0);
-- LSR/ROR?
elsif alu_ctrl.word_24_update = '1' then
alu_shifter_out(55 downto 48) <= src_accu(55 downto 48);
alu_shifter_out(23 downto 0) <= src_accu(23 downto 0);
alu_shifter_carry_out <= src_accu(24);
if alu_ctrl.rotate = '0' then -- LSR
alu_shifter_out(47 downto 24) <= '0' & src_accu(47 downto 25);
else -- ROR
alu_shifter_out(47 downto 24) <= register_file.sr(C_FLAG) & src_accu(47 downto 25);
end if;
end if;
when ZEROS =>
alu_shifter_out <= (others => '0');
end case;
end process alu_shifter;
-- Special handling for NORM instruction
-- Determine which case occurs (see User's Manual for more information)
norm_instr_logic: process(register_file, addr_r_in) is
begin
norm_instr_asl <= '0';
norm_instr_asr <= '0';
-- Either left shift
if register_file.sr(E_FLAG) = '0' and
register_file.sr(U_FLAG) = '1' and
register_file.sr(Z_FLAG) = '0' then
norm_instr_asl <= '1';
norm_update_ccr <= '1';
addr_r_out <= addr_r_in - 1;
-- Or right shift
elsif register_file.sr(E_FLAG) = '1' then
norm_instr_asr <= '1';
norm_update_ccr <= '1';
addr_r_out <= addr_r_in + 1;
-- Or do nothing!
else
norm_update_ccr <= '0';
addr_r_out <= addr_r_in;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,79 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
use work.constants_pkg.all;
entity exec_stage_bit_modify is port(
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
src_operand : in std_logic_vector(23 downto 0);
register_file : in register_file_type;
dst_operand : out std_logic_vector(23 downto 0);
bit_cond_met : out std_logic;
modify_sr : out std_logic;
modified_sr : out std_logic_vector(15 downto 0)
);
end entity;
architecture rtl of exec_stage_bit_modify is
signal operand_bit : std_logic;
signal src_operand_32 : std_logic_vector(31 downto 0);
begin
-- this is just a helper signal to prevent the simulator
-- to stop when accessing a bit > 23.
src_operand_32 <= "00000000" & src_operand;
-- read the bit we want to test (and modify)
operand_bit <= src_operand_32(to_integer(unsigned(instr_word(4 downto 0))));
-- modify the Carry flag only for the bit modify instructions!
modify_sr <= '1' when instr_array = INSTR_BCLR or instr_array = INSTR_BSET or instr_array = INSTR_BCHG or instr_array = INSTR_BTST else '0';
modified_sr <= register_file.sr(15 downto 1) & operand_bit;
bit_operation: process(instr_word, instr_array, src_operand, operand_bit) is
variable new_bit : std_logic;
begin
-- do nothing by default!
dst_operand <= src_operand;
bit_cond_met <= '0';
-- determine which bit to write
if instr_array = INSTR_BCLR then
new_bit := '0';
elsif instr_array = INSTR_BSET then
new_bit := '1';
else -- BCHG
new_bit := not operand_bit;
end if;
if instr_array = INSTR_BCLR or instr_array = INSTR_BSET or instr_array = INSTR_BCHG then
dst_operand(to_integer(unsigned(instr_word(4 downto 0)))) <= new_bit;
end if;
-- check for the jump instructions whether condition is met or not!
if instr_array = INSTR_JCLR or instr_array = INSTR_JSCLR then
if operand_bit = '0' then
bit_cond_met <= '1';
else
bit_cond_met <= '0';
end if;
end if;
if instr_array = INSTR_JSET or instr_array = INSTR_JSSET then
if operand_bit = '0' then
bit_cond_met <= '0';
else
bit_cond_met <= '1';
end if;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,117 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
use work.constants_pkg.all;
entity exec_stage_branch is port(
activate_exec_bra : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
register_file : in register_file_type;
jump_address : in unsigned(BW_ADDRESS-1 downto 0);
bit_cond_met : in std_logic;
cc_flag_set : in std_logic;
push_stack : out push_stack_type;
pop_stack : out pop_stack_type;
modify_pc : out std_logic;
modified_pc : out unsigned(BW_ADDRESS-1 downto 0);
modify_sr : out std_logic;
modified_sr : out std_logic_vector(15 downto 0)
);
end entity;
architecture rtl of exec_stage_branch is
signal branch_condition_met : std_logic;
signal modify_pc_int : std_logic;
begin
modify_pc_int <= '1' when activate_exec_bra = '1' and branch_condition_met = '1' else '0';
modify_pc <= modify_pc_int;
calculate_branch_condition : process(instr_word, instr_array, register_file, bit_cond_met)
begin
branch_condition_met <= '0';
-- unconditional jumps
if instr_array = INSTR_JMP or
instr_array = INSTR_JSR or
instr_array = INSTR_RTI or
instr_array = INSTR_RTS then
-- jump always
branch_condition_met <= '1';
end if;
-- then see whether the branch condition is satisfied
if instr_array = INSTR_JCC or instr_array = INSTR_JSCC then
branch_condition_met <= cc_flag_set;
end if;
-- jmp that is executed according to a certain bit condition
if instr_array = INSTR_JCLR or instr_array = INSTR_JSCLR or
instr_array = INSTR_JSET or instr_array = INSTR_JSSET then
branch_condition_met <= bit_cond_met;
end if;
end process calculate_branch_condition;
calculate_branch_target : process(instr_array, instr_word, jump_address)
begin
modified_pc <= jump_address;
-- address calculation is the same for the following instructions
if instr_array = INSTR_JMP or
instr_array = INSTR_JCC or
instr_array = INSTR_JSCC or
instr_array = INSTR_JSR then
if instr_word(18) = '1' then
-- short jump address included in opcode (bits 11 downto 0)
modified_pc(11 downto 0) <= unsigned(instr_word(11 downto 0));
elsif instr_word(18) = '0' then
-- effective address defined by opcode and coming from address generator unit
modified_pc <= jump_address;
end if;
end if;
-- jump address contains the obligatory address of the second
-- instruction word
if instr_array = INSTR_JCLR or
instr_array = INSTR_JSET or
instr_array = INSTR_JSCLR or
instr_array = INSTR_JSSET then
modified_pc <= jump_address;
end if;
-- target address is stored on the stack
if instr_array = INSTR_RTS or
instr_array = INSTR_RTI then
modified_pc <= unsigned(register_file.current_ssh);
end if;
end process calculate_branch_target;
-- Subroutine functions need to store PC and SR on the stack
push_stack.valid <= '1' when modify_pc_int = '1' and (instr_array = INSTR_JSCC or instr_array = INSTR_JSR or
instr_array = INSTR_JSCLR or instr_array = INSTR_JSSET) else '0';
push_stack.content <= PC_AND_SR;
-- pc is set externally!
push_stack.pc <= (others => '0');
-- RTI/RTS instructions need to read from the stack
pop_stack.valid <= '1' when modify_pc_int = '1' and (instr_array = INSTR_RTI or instr_array = INSTR_RTS) else '0';
-- some instructions require to set the SR
calculate_status_register : process(instr_array)
begin
modify_sr <= '0';
modified_sr <= (others => '0');
if instr_array = INSTR_RTI then
modify_sr <= '1';
modified_sr <= register_file.current_ssl;
end if;
end process calculate_status_register;
end architecture rtl;

View File

@@ -0,0 +1,75 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
use work.constants_pkg.all;
entity exec_stage_cc_flag_calc is port(
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
register_file : in register_file_type;
cc_flag_set : out std_logic
);
end entity;
architecture rtl of exec_stage_cc_flag_calc is
begin
calculate_cc_flag : process(instr_word, instr_array, register_file)
variable cc_select : std_logic_vector(3 downto 0);
procedure calculate_cc_flag(cc: std_logic_vector(3 downto 0)) is
variable c_flag : std_logic := register_file.ccr(0);
variable v_flag : std_logic := register_file.ccr(1);
variable z_flag : std_logic := register_file.ccr(2);
variable n_flag : std_logic := register_file.ccr(3);
variable u_flag : std_logic := register_file.ccr(4);
variable e_flag : std_logic := register_file.ccr(5);
variable l_flag : std_logic := register_file.ccr(6);
begin
if (cc = "0000" and c_flag = '0') or -- CC: carry clear
(cc = "1000" and c_flag = '1') or -- CS: carry set
(cc = "0101" and e_flag = '0') or -- EC: extension clear
(cc = "1010" and z_flag = '1') or -- EQ: equal
(cc = "1101" and e_flag = '1') or -- ES: extension set
(cc = "0001" and (n_flag = v_flag)) or -- GE: greater than or equal
(cc = "0001" and ((n_flag xor v_flag) or z_flag) = '0') or -- GT: greater than
(cc = "0110" and l_flag = '0') or -- LC: limit clear
(cc = "1111" and ((n_flag xor v_flag) or z_flag ) = '1') or -- LE: less or equal
(cc = "1110" and l_flag = '1') or -- LS: limit set
(cc = "1001" and (n_flag /= v_flag)) or -- LT: less than
(cc = "1011" and n_flag = '1') or -- MI: minus
(cc = "0010" and z_flag = '0') or -- NE: not equal
(cc = "1100" and (( not u_flag and not e_flag) or z_flag) = '1') or -- NR: normalized
(cc = "0011" and n_flag = '0') or -- PL: plus
(cc = "0100" and (( not u_flag and not e_flag ) or z_flag) = '0') -- NN: not normalized
then
cc_flag_set <= '1';
end if;
end procedure;
begin
cc_flag_set <= '0';
-- Rip the flags we have to test for from the instruction word
if (instr_array = INSTR_JCC and instr_word(18) = '0') or
(instr_array = INSTR_JSCC) then
cc_select := instr_word(3 downto 0);
else
cc_select := instr_word(15 downto 12);
end if;
calculate_cc_flag(cc_select);
end process;
end architecture;

View File

@@ -0,0 +1,72 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
use work.constants_pkg.all;
entity exec_stage_cr_mod is port (
activate_exec_cr_mod : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
register_file : in register_file_type;
modify_sr : out std_logic;
modified_sr : out std_logic_vector(15 downto 0);
modify_omr : out std_logic;
modified_omr : out std_logic_vector(7 downto 0)
);
end exec_stage_cr_mod;
architecture rtl of exec_stage_cr_mod is
begin
process(activate_exec_cr_mod, instr_word, instr_array, register_file) is
variable imm8 : std_logic_vector(7 downto 0);
variable op8 : std_logic_vector(7 downto 0);
variable res8 : std_logic_vector(7 downto 0);
begin
modify_sr <= '0';
modify_omr <= '0';
modified_sr <= (others => '0');
modified_omr <= (others => '0');
imm8 := instr_word(15 downto 8);
if instr_word(1 downto 0) = "00" then
-- read MR
op8 := register_file.mr;
elsif instr_word(1 downto 0) = "01" then
-- read CCR
op8 := register_file.ccr;
else -- instr_word(1 downto 0) = "10"
-- read OMR
op8 := register_file.omr;
end if;
if instr_array = INSTR_ANDI then
res8 := imm8 and op8;
else -- instr_array = INSTR_ORI
res8 := imm8 or op8;
end if;
-- only write the result when activated
if activate_exec_cr_mod = '1' then
if instr_word(1 downto 0) = "00" then
-- update MR
modify_sr <= '1';
modified_sr <= res8 & register_file.ccr;
elsif instr_word(1 downto 0) = "01" then
-- update CCR
modify_sr <= '1';
modified_sr <= register_file.mr & res8;
elsif instr_word(1 downto 0) = "10" then
-- update OMR
modify_omr <= '1';
modified_omr <= res8;
end if;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,200 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
use work.constants_pkg.all;
entity exec_stage_loop is port(
clk, rst : in std_logic;
activate_exec_loop : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
loop_iterations : in unsigned(15 downto 0);
loop_address : in unsigned(BW_ADDRESS-1 downto 0);
loop_start_address: in unsigned(BW_ADDRESS-1 downto 0);
register_file : in register_file_type;
fetch_perform_enddo: in std_logic;
memory_stall : in std_logic;
push_stack : out push_stack_type;
pop_stack : out pop_stack_type;
stall_rep : out std_logic;
stall_do : out std_logic;
decrement_lc : out std_logic;
modify_lc : out std_logic;
modified_lc : out unsigned(15 downto 0);
modify_la : out std_logic;
modified_la : out unsigned(15 downto 0);
modify_pc : out std_logic;
modified_pc : out unsigned(BW_ADDRESS-1 downto 0);
modify_sr : out std_logic;
modified_sr : out std_logic_vector(15 downto 0)
);
end entity;
architecture rtl of exec_stage_loop is
signal rep_loop_polling : std_logic;
signal do_loop_polling : std_logic;
signal enddo_polling : std_logic;
signal lc_temp : unsigned(15 downto 0);
signal rf_lc_eq_1 : std_logic;
signal memory_stall_t : std_logic;
begin
modified_pc <= loop_start_address;
-- loop counter in register file equal to 1?
rf_lc_eq_1 <= '1' when register_file.lc = 1 else '0';
process(activate_exec_loop, instr_array, register_file, fetch_perform_enddo,
rep_loop_polling, loop_iterations, rf_lc_eq_1, loop_start_address) is
begin
stall_rep <= '0';
stall_do <= '0';
modify_la <= '0';
modify_lc <= '0';
modify_pc <= '0';
modify_sr <= '0';
modified_la <= loop_address;
modified_lc <= loop_iterations; -- default
-- set the loop flag LF (bit 15) of Status register
modified_sr(15) <= '1';
modified_sr(14 downto 0) <= register_file.sr(14 downto 0);
push_stack.valid <= '0'; -- push PC and SR on the stack
push_stack.pc <= loop_start_address;
push_stack.content <= LA_AND_LC;
pop_stack.valid <= '0';
decrement_lc <= '0';
------------------
-- DO instruction
------------------
if activate_exec_loop = '1' and instr_array = INSTR_DO then
-- first instruction of the do loop instruction?
if do_loop_polling = '0' then
stall_do <= '1';
modify_lc <= '1'; -- store the new loop counter
modify_la <= '1'; -- store the new loop address
push_stack.valid <= '1'; -- push LA and LC on the stack
push_stack.content <= LA_AND_LC;
else -- second clock cycle of the do loop instruction ?
push_stack.valid <= '1'; -- push PC and SR on the stack
push_stack.pc <= loop_start_address;
push_stack.content <= PC_AND_SR;
-- set the PC to the first instruction of the loop
-- the already fetched instruction are flushed from the pipeline
-- this prevents problems, when the loop consists of only one or two instructions
modify_pc <= '1';
-- set the loop flag
modify_sr <= '1';
end if;
end if;
-----------------------------------------------
-- ENDDO instruction / loop end in fetch stage
-----------------------------------------------
if (activate_exec_loop = '1' and instr_array = INSTR_ENDDO) or fetch_perform_enddo = '1' or enddo_polling = '1' then
pop_stack.valid <= '1';
if enddo_polling = '0' then
-- only restore the LF from the stack
modified_sr(15) <= register_file.current_ssl(15);
modify_sr <= '1';
stall_do <= '1'; -- stall one clock cycle
else
-- restore loop counter and loop address in second clock cycle
modified_lc <= unsigned(register_file.current_ssl);
modify_lc <= '1';
modified_la <= unsigned(register_file.current_ssh);
modify_la <= '1';
end if;
end if;
-------------------
-- REP instruction
-------------------
if activate_exec_loop = '1' and instr_array = INSTR_REP then
-- only do something when there are more than 1 iterations
-- the first execution is already on the way
if loop_iterations /= 1 then
stall_rep <= '1'; -- stall the fetch and decode stages
modify_lc <= '1'; -- store the loop counter
modified_lc <= loop_iterations - 1;
end if;
end if;
-- keep processing the single instruction
if rep_loop_polling = '1' then
stall_rep <= '1';
-- if the REP instruction cause a stall do not modify the lc!
if memory_stall_t = '0' then
if rf_lc_eq_1 = '0' then
decrement_lc <= '1';
-- when the instruction to repeat caused a memory stall
-- do not continue!
else
-- finish the REP instruction by restoring the LC
stall_rep <= '0';
modify_lc <= '1';
modified_lc <= lc_temp;
end if;
end if;
end if;
end process;
-- process that allows to remember that we are processing a REP/DO instruction
-- even though the REP instruction is not available in the pipeline anymore
-- also store the old loop counter
process(clk) is
begin
if rising_edge(clk) then
if rst = '1' then
rep_loop_polling <= '0';
do_loop_polling <= '0';
enddo_polling <= '0';
lc_temp <= (others => '0');
memory_stall_t <= '0';
else
memory_stall_t <= memory_stall;
if activate_exec_loop = '1' and instr_array = INSTR_REP then
-- only do something when there are more than 1 iterations
-- the first execution is already on the way
if loop_iterations /= 1 then
rep_loop_polling <= '1';
lc_temp <= register_file.lc;
end if;
end if;
-- test whether the REP instruction has been executed
if rep_loop_polling = '1' and rf_lc_eq_1 = '1' and memory_stall_t = '0' then
rep_loop_polling <= '0';
end if;
-- do loop execution takes two clock cycles
-- in the first clock cycle we store loop address and loop counter on the stack
-- in the second clock cycle we store programm counter and status register on the stack
if activate_exec_loop = '1' and instr_array = INSTR_DO then
do_loop_polling <= '1';
end if;
-- clear the flag immediately again (only two cycles execution time!)
if do_loop_polling = '1' then
do_loop_polling <= '0';
end if;
-- ENDDO instructions take two clock cycles as well!
if (activate_exec_loop = '1' and instr_array = INSTR_ENDDO) or fetch_perform_enddo = '1' then
enddo_polling <= '1';
end if;
if enddo_polling = '1' then
enddo_polling <= '0';
end if;
end if;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,60 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
entity fetch_stage is port(
pc_old : in unsigned(BW_ADDRESS-1 downto 0);
pc_new : out unsigned(BW_ADDRESS-1 downto 0);
modify_pc : in std_logic;
modified_pc : in unsigned(BW_ADDRESS-1 downto 0);
register_file : in register_file_type;
decrement_lc : out std_logic;
perform_enddo : out std_logic
);
end fetch_stage;
architecture rtl of fetch_stage is
begin
pc_calculation: process(pc_old, modify_pc, modified_pc, register_file) is
begin
decrement_lc <= '0';
perform_enddo <= '0';
-- by default increment pc by one
pc_new <= pc_old + 1;
if modify_pc = '1' then
pc_new <= modified_pc;
end if;
-- Loop Flag set?
if register_file.sr(15) = '1' then
if register_file.la = pc_old then
-- Loop not finished?
-- => start from the beginning if necessary
if register_file.lc /= 1 then
-- if the last address was LA and the loop is not finished yet, we have to
-- read now from the beginning of the loop again
pc_new <= unsigned(register_file.current_ssh(BW_ADDRESS-1 downto 0));
-- decrement loop counter
decrement_lc <= '1';
else
-- loop done!
-- => tell the loop controller in the exec stage to perform the enddo operation
-- (without flushing of the pipeline!)
perform_enddo <= '1';
end if;
end if;
end if;
end process pc_calculation;
end architecture rtl;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,206 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
use work.constants_pkg.all;
entity memory_management is port (
clk, rst : in std_logic;
stall_flags : in std_logic_vector(PIPELINE_DEPTH-1 downto 0);
memory_stall : out std_logic;
data_rom_enable: in std_logic;
pmem_ctrl_in : in mem_ctrl_type_in;
pmem_ctrl_out : out mem_ctrl_type_out;
xmem_ctrl_in : in mem_ctrl_type_in;
xmem_ctrl_out : out mem_ctrl_type_out;
ymem_ctrl_in : in mem_ctrl_type_in;
ymem_ctrl_out : out mem_ctrl_type_out
);
end memory_management;
architecture rtl of memory_management is
component mem_control is
generic(
mem_type : memory_type
);
port(
clk, rst : in std_logic;
rd_addr : in unsigned(BW_ADDRESS-1 downto 0);
rd_en : in std_logic;
data_out : out std_logic_vector(23 downto 0);
data_out_valid : out std_logic;
wr_addr : in unsigned(BW_ADDRESS-1 downto 0);
wr_en : in std_logic;
wr_accomplished : out std_logic;
data_in : in std_logic_vector(23 downto 0)
);
end component mem_control;
signal pmem_data_out : std_logic_vector(23 downto 0);
signal pmem_data_out_valid : std_logic;
signal pmem_rd_addr : unsigned(BW_ADDRESS-1 downto 0);
signal pmem_rd_en : std_logic;
signal xmem_rd_en : std_logic;
signal xmem_data_out : std_logic_vector(23 downto 0);
signal xmem_data_out_valid : std_logic;
signal xmem_rd_polling : std_logic;
signal ymem_rd_en : std_logic;
signal ymem_data_out : std_logic_vector(23 downto 0);
signal ymem_data_out_valid : std_logic;
signal ymem_rd_polling : std_logic;
signal pmem_stall_buffer : std_logic_vector(23 downto 0);
signal pmem_stall_buffer_valid : std_logic;
signal xmem_stall_buffer : std_logic_vector(23 downto 0);
signal ymem_stall_buffer : std_logic_vector(23 downto 0);
signal stall_flags_d : std_logic_vector(PIPELINE_DEPTH-1 downto 0);
begin
-- here it is necessary to store the output of the pmem/xmem/ymem when the pipeline enters a stall
-- when the pipeline wakes up, this temporal result is inserted into the pipeline
stall_buffer: process(clk) is
begin
if rising_edge(clk) then
if rst = '1' then
pmem_stall_buffer <= (others => '0');
pmem_stall_buffer_valid <= '0';
xmem_stall_buffer <= (others => '0');
ymem_stall_buffer <= (others => '0');
stall_flags_d <= (others => '0');
else
stall_flags_d <= stall_flags;
if stall_flags(ST_FETCH2) = '1' and stall_flags_d(ST_FETCH2) = '0' then
if pmem_data_out_valid = '1' then
pmem_stall_buffer <= pmem_data_out;
pmem_stall_buffer_valid <= '1';
end if;
end if;
if stall_flags(ST_FETCH2) = '0' and stall_flags_d(ST_FETCH2) = '1' then
pmem_stall_buffer_valid <= '0';
end if;
end if;
end if;
end process stall_buffer;
memory_stall <= '1' when ( xmem_rd_en = '1' or (xmem_rd_polling = '1' and xmem_data_out_valid = '0') ) or
( ymem_rd_en = '1' or (ymem_rd_polling = '1' and ymem_data_out_valid = '0') ) else
'0';
-------------------------------
-- PMEM CONTROLLER
-------------------------------
inst_pmem_ctrl : mem_control
generic map(
mem_type => P_MEM
)
port map(
clk => clk,
rst => rst,
rd_addr => pmem_ctrl_in.rd_addr,
rd_en => pmem_ctrl_in.rd_en,
data_out => pmem_data_out,
data_out_valid => pmem_data_out_valid,
wr_addr => pmem_ctrl_in.wr_addr,
wr_en => pmem_ctrl_in.wr_en,
data_in => pmem_ctrl_in.data_in
);
-- In case we wake up from a stall use the buffered value
pmem_ctrl_out.data_out <= pmem_stall_buffer when stall_flags(ST_FETCH2) = '0' and
stall_flags_d(ST_FETCH2) = '1' and
pmem_stall_buffer_valid = '1' else
pmem_data_out;
pmem_ctrl_out.data_out_valid <= pmem_stall_buffer_valid when stall_flags(ST_FETCH2) = '0' and
stall_flags_d(ST_FETCH2) = '1' else
'0' when stall_flags(ST_FETCH2) = '1' else
pmem_data_out_valid;
-------------------------------
-- XMEM CONTROLLER
-------------------------------
inst_xmem_ctrl : mem_control
generic map(
mem_type => X_MEM
)
port map(
clk => clk,
rst => rst,
rd_addr => xmem_ctrl_in.rd_addr,
rd_en => xmem_rd_en,
data_out => xmem_data_out,
data_out_valid => xmem_data_out_valid,
wr_addr => xmem_ctrl_in.wr_addr,
wr_en => xmem_ctrl_in.wr_en,
data_in => xmem_ctrl_in.data_in
);
xmem_rd_en <= '1' when xmem_rd_polling = '0' and xmem_ctrl_in.rd_en = '1' else '0';
xmem_ctrl_out.data_out <= xmem_data_out;
xmem_ctrl_out.data_out_valid <= xmem_data_out_valid;
-------------------------------
-- YMEM CONTROLLER
-------------------------------
inst_ymem_ctrl : mem_control
generic map(
mem_type => Y_MEM
)
port map(
clk => clk,
rst => rst,
rd_addr => ymem_ctrl_in.rd_addr,
rd_en => ymem_rd_en,
data_out => ymem_data_out,
data_out_valid => ymem_data_out_valid,
wr_addr => ymem_ctrl_in.wr_addr,
wr_en => ymem_ctrl_in.wr_en,
data_in => ymem_ctrl_in.data_in
);
ymem_rd_en <= '1' when ymem_rd_polling = '0' and ymem_ctrl_in.rd_en = '1' else '0';
ymem_ctrl_out.data_out <= ymem_data_out;
ymem_ctrl_out.data_out_valid <= ymem_data_out_valid;
mem_stall_control: process(clk) is
begin
if rising_edge(clk) then
if rst = '1' then
xmem_rd_polling <= '0';
ymem_rd_polling <= '0';
else
if xmem_rd_en = '1' then
xmem_rd_polling <= '1';
end if;
if xmem_data_out_valid = '1' then
xmem_rd_polling <= '0';
end if;
if ymem_rd_en = '1' then
ymem_rd_polling <= '1';
end if;
if ymem_data_out_valid = '1' then
ymem_rd_polling <= '0';
end if;
end if;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,10 @@
package parameter_pkg is
constant BW_ADDRESS : natural := 16;
constant PIPELINE_DEPTH : natural := 5;
constant NUM_ACT_SIGNALS : natural := 26;
end package;

View File

@@ -0,0 +1,968 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
use work.constants_pkg.all;
entity pipeline is port (
clk, rst : in std_logic;
register_file_out : out register_file_type
);
end pipeline;
-- TODOs:
-- External memory accesses
-- ROM tables
-- Reading from SSH flag has to modify stack pointer
-- Memory access (x,y,p) and talling accordingly
-- Address Generator: ring buffers are not yet supported
-- List of BUGS:
-- - Reading from address one clock cycle after writing to the same address might result in corrupted data!!
-- - SBC instruction has errorneous carry flag calculation
-- List of probable issues:
-- - Reading from XMEM/YMEM with stalls probably results in corrupted data
-- - ENDDO instruction probably has to flush the pipeline afterwards
-- - Writing to memory occurs twice, when stalls occur
-- Things to optimize:
-- - RTS/RTI could be executed in the ADGEN Stage already
-- - DO loops always flush the pipeline. This is necessary in case we have a very short loop.
-- The single instruction of the loop then has passed the fetch stage already without the branch
architecture rtl of pipeline is
signal pipeline_regs : pipeline_type;
signal stall_flags : std_logic_vector(PIPELINE_DEPTH-1 downto 0);
component fetch_stage is port(
pc_old : in unsigned(BW_ADDRESS-1 downto 0);
pc_new : out unsigned(BW_ADDRESS-1 downto 0);
modify_pc : in std_logic;
modified_pc : in unsigned(BW_ADDRESS-1 downto 0);
register_file : in register_file_type;
decrement_lc : out std_logic;
perform_enddo : out std_logic
);
end component fetch_stage;
signal pc_old, pc_new : unsigned(BW_ADDRESS-1 downto 0);
signal fetch_modify_pc : std_logic;
signal fetch_modified_pc : unsigned(BW_ADDRESS-1 downto 0);
signal fetch_perform_enddo: std_logic;
signal fetch_decrement_lc: std_logic;
component decode_stage is port(
activate_dec : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
dble_word_instr : out std_logic;
instr_array : out instructions_type;
act_array : out std_logic_vector(NUM_ACT_SIGNALS-1 downto 0);
reg_wr_addr : out std_logic_vector(5 downto 0);
reg_rd_addr : out std_logic_vector(5 downto 0);
x_bus_rd_addr : out std_logic_vector(1 downto 0);
x_bus_wr_addr : out std_logic_vector(1 downto 0);
y_bus_rd_addr : out std_logic_vector(1 downto 0);
y_bus_wr_addr : out std_logic_vector(1 downto 0);
l_bus_addr : out std_logic_vector(2 downto 0);
adgen_mode_a : out adgen_mode_type;
adgen_mode_b : out adgen_mode_type;
alu_ctrl : out alu_ctrl_type
);
end component decode_stage;
signal dec_activate : std_logic;
signal dec_instr_word : std_logic_vector(23 downto 0);
signal dec_dble_word_instr : std_logic;
signal dec_instr_array : instructions_type;
signal dec_act_array : std_logic_vector(NUM_ACT_SIGNALS-1 downto 0);
signal dec_reg_wr_addr : std_logic_vector(5 downto 0);
signal dec_reg_rd_addr : std_logic_vector(5 downto 0);
signal dec_x_bus_wr_addr : std_logic_vector(1 downto 0);
signal dec_x_bus_rd_addr : std_logic_vector(1 downto 0);
signal dec_y_bus_wr_addr : std_logic_vector(1 downto 0);
signal dec_y_bus_rd_addr : std_logic_vector(1 downto 0);
signal dec_l_bus_addr : std_logic_vector(2 downto 0);
signal dec_adgen_mode_a : adgen_mode_type;
signal dec_adgen_mode_b : adgen_mode_type;
signal dec_alu_ctrl : alu_ctrl_type;
component adgen_stage is port(
activate_adgen : in std_logic;
activate_x_mem : in std_logic;
activate_y_mem : in std_logic;
activate_l_mem : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
optional_ea_word : in std_logic_vector(23 downto 0);
register_file : in register_file_type;
adgen_mode_a : in adgen_mode_type;
adgen_mode_b : in adgen_mode_type;
address_out_x : out unsigned(BW_ADDRESS-1 downto 0);
address_out_y : out unsigned(BW_ADDRESS-1 downto 0);
wr_R_port_A_valid : out std_logic;
wr_R_port_A : out addr_wr_port_type;
wr_R_port_B_valid : out std_logic;
wr_R_port_B : out addr_wr_port_type
);
end component adgen_stage;
signal adgen_activate : std_logic;
signal adgen_activate_x_mem : std_logic;
signal adgen_activate_y_mem : std_logic;
signal adgen_activate_l_mem : std_logic;
signal adgen_instr_word : std_logic_vector(23 downto 0);
signal adgen_instr_array : instructions_type;
signal adgen_optional_ea_word : std_logic_vector(23 downto 0);
signal adgen_register_file : register_file_type;
signal adgen_mode_a : adgen_mode_type;
signal adgen_mode_b : adgen_mode_type;
signal adgen_address_out_x : unsigned(BW_ADDRESS-1 downto 0);
signal adgen_address_out_y : unsigned(BW_ADDRESS-1 downto 0);
signal adgen_wr_R_port_A_valid : std_logic;
signal adgen_wr_R_port_A : addr_wr_port_type;
signal adgen_wr_R_port_B_valid : std_logic;
signal adgen_wr_R_port_B : addr_wr_port_type;
component exec_stage_bit_modify is port(
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
src_operand : in std_logic_vector(23 downto 0);
register_file : in register_file_type;
dst_operand : out std_logic_vector(23 downto 0);
bit_cond_met : out std_logic;
modify_sr : out std_logic;
modified_sr : out std_logic_vector(15 downto 0)
);
end component exec_stage_bit_modify;
signal exec_bit_modify_instr_word : std_logic_vector(23 downto 0);
signal exec_bit_modify_instr_array : instructions_type;
signal exec_bit_modify_src_operand : std_logic_vector(23 downto 0);
signal exec_bit_modify_dst_operand : std_logic_vector(23 downto 0);
signal exec_bit_modify_bit_cond_met : std_logic;
signal exec_bit_modify_modify_sr : std_logic;
signal exec_bit_modify_modified_sr : std_logic_vector(15 downto 0);
component exec_stage_branch is port(
activate_exec_bra : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
register_file : in register_file_type;
jump_address : in unsigned(BW_ADDRESS-1 downto 0);
bit_cond_met : in std_logic;
cc_flag_set : in std_logic;
push_stack : out push_stack_type;
pop_stack : out pop_stack_type;
modify_pc : out std_logic;
modified_pc : out unsigned(BW_ADDRESS-1 downto 0);
modify_sr : out std_logic;
modified_sr : out std_logic_vector(15 downto 0)
);
end component exec_stage_branch;
signal exec_bra_activate : std_logic;
signal exec_bra_instr_word : std_logic_vector(23 downto 0);
signal exec_bra_instr_array : instructions_type;
signal exec_bra_jump_address : unsigned(BW_ADDRESS-1 downto 0);
signal exec_bra_bit_cond_met : std_logic;
signal exec_bra_push_stack : push_stack_type;
signal exec_bra_pop_stack : pop_stack_type;
signal exec_bra_modify_pc : std_logic;
signal exec_bra_modified_pc : unsigned(BW_ADDRESS-1 downto 0);
signal exec_bra_modify_sr : std_logic;
signal exec_bra_modified_sr : std_logic_vector(15 downto 0);
component exec_stage_cr_mod is port(
activate_exec_cr_mod : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
register_file : in register_file_type;
modify_sr : out std_logic;
modified_sr : out std_logic_vector(15 downto 0);
modify_omr : out std_logic;
modified_omr : out std_logic_vector(7 downto 0)
);
end component exec_stage_cr_mod;
signal exec_cr_mod_activate : std_logic;
signal exec_cr_mod_instr_word : std_logic_vector(23 downto 0);
signal exec_cr_mod_instr_array : instructions_type;
signal exec_cr_mod_modify_sr : std_logic;
signal exec_cr_mod_modified_sr : std_logic_vector(15 downto 0);
signal exec_cr_mod_modify_omr : std_logic;
signal exec_cr_mod_modified_omr : std_logic_vector(7 downto 0);
component exec_stage_loop is port(
clk, rst : in std_logic;
activate_exec_loop : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
loop_iterations : in unsigned(15 downto 0);
loop_address : in unsigned(BW_ADDRESS-1 downto 0);
loop_start_address: in unsigned(BW_ADDRESS-1 downto 0);
register_file : in register_file_type;
fetch_perform_enddo: in std_logic;
memory_stall : in std_logic;
push_stack : out push_stack_type;
pop_stack : out pop_stack_type;
stall_rep : out std_logic;
stall_do : out std_logic;
decrement_lc : out std_logic;
modify_lc : out std_logic;
modified_lc : out unsigned(15 downto 0);
modify_la : out std_logic;
modified_la : out unsigned(15 downto 0);
modify_pc : out std_logic;
modified_pc : out unsigned(BW_ADDRESS-1 downto 0);
modify_sr : out std_logic;
modified_sr : out std_logic_vector(15 downto 0)
);
end component exec_stage_loop;
signal exec_loop_activate : std_logic;
signal exec_loop_instr_word : std_logic_vector(23 downto 0);
signal exec_loop_instr_array : instructions_type;
signal exec_loop_iterations : unsigned(15 downto 0);
signal exec_loop_address : unsigned(BW_ADDRESS-1 downto 0);
signal exec_loop_start_address : unsigned(BW_ADDRESS-1 downto 0);
signal exec_loop_register_file : register_file_type;
signal exec_loop_push_stack : push_stack_type;
signal exec_loop_pop_stack : pop_stack_type;
signal exec_loop_stall_rep : std_logic;
signal exec_loop_stall_do : std_logic;
signal exec_loop_decrement_lc : std_logic;
signal exec_loop_modify_lc : std_logic;
signal exec_loop_modified_lc : unsigned(15 downto 0);
signal exec_loop_modify_la : std_logic;
signal exec_loop_modified_la : unsigned(BW_ADDRESS-1 downto 0);
signal exec_loop_modify_pc : std_logic;
signal exec_loop_modified_pc : unsigned(BW_ADDRESS-1 downto 0);
signal exec_loop_modify_sr : std_logic;
signal exec_loop_modified_sr : std_logic_vector(BW_ADDRESS-1 downto 0);
component exec_stage_alu is port(
alu_activate : in std_logic;
instr_word : in std_logic_vector(23 downto 0);
alu_ctrl : in alu_ctrl_type;
register_file : in register_file_type;
addr_r_in : in unsigned(BW_ADDRESS-1 downto 0);
addr_r_out : out unsigned(BW_ADDRESS-1 downto 0);
modify_accu : out std_logic;
dst_accu : out std_logic;
modified_accu : out signed(55 downto 0);
modify_sr : out std_logic;
modified_sr : out std_logic_vector(15 downto 0)
);
end component exec_stage_alu;
signal exec_alu_activate : std_logic;
signal exec_alu_instr_word : std_logic_vector(23 downto 0);
signal exec_alu_ctrl : alu_ctrl_type;
signal exec_alu_addr_r_in : unsigned(BW_ADDRESS-1 downto 0);
signal exec_alu_addr_r_out : unsigned(BW_ADDRESS-1 downto 0);
signal exec_alu_modify_accu : std_logic;
signal exec_alu_dst_accu : std_logic;
signal exec_alu_modified_accu : signed(55 downto 0);
signal exec_alu_modify_sr : std_logic;
signal exec_alu_modified_sr : std_logic_vector(15 downto 0);
signal exec_imm_8bit : std_logic_vector(23 downto 0);
signal exec_imm_12bit : std_logic_vector(23 downto 0);
signal exec_src_operand : std_logic_vector(23 downto 0);
signal exec_dst_operand : std_logic_vector(23 downto 0);
component exec_stage_cc_flag_calc is port(
instr_word : in std_logic_vector(23 downto 0);
instr_array : in instructions_type;
register_file : in register_file_type;
cc_flag_set : out std_logic
);
end component exec_stage_cc_flag_calc;
signal exec_cc_flag_calc_instr_word : std_logic_vector(23 downto 0);
signal exec_cc_flag_calc_instr_array : instructions_type;
signal exec_cc_flag_set : std_logic;
component reg_file is port(
clk, rst : in std_logic;
register_file : out register_file_type;
wr_R_port_A_valid : in std_logic;
wr_R_port_A : in addr_wr_port_type;
wr_R_port_B_valid : in std_logic;
wr_R_port_B : in addr_wr_port_type;
alu_wr_valid : in std_logic;
alu_wr_addr : in std_logic;
alu_wr_data : in signed(55 downto 0);
reg_wr_addr : in std_logic_vector(5 downto 0);
reg_wr_addr_valid : in std_logic;
reg_wr_data : in std_Logic_vector(23 downto 0);
reg_rd_addr : in std_logic_vector(5 downto 0);
reg_rd_data : out std_Logic_vector(23 downto 0);
X_bus_rd_addr : in std_logic_vector(1 downto 0);
X_bus_data_out : out std_logic_vector(23 downto 0);
X_bus_wr_addr : in std_logic_vector(1 downto 0);
X_bus_wr_valid : in std_logic;
X_bus_data_in : in std_logic_vector(23 downto 0);
Y_bus_rd_addr : in std_logic_vector(1 downto 0);
Y_bus_data_out : out std_logic_vector(23 downto 0);
Y_bus_wr_addr : in std_logic_vector(1 downto 0);
Y_bus_wr_valid : in std_logic;
Y_bus_data_in : in std_logic_vector(23 downto 0);
L_bus_rd_addr : in std_logic_vector(2 downto 0);
L_bus_rd_valid : in std_logic;
L_bus_wr_addr : in std_logic_vector(2 downto 0);
L_bus_wr_valid : in std_logic;
push_stack : in push_stack_type;
pop_stack : in pop_stack_type;
set_sr : in std_logic;
new_sr : in std_logic_vector(15 downto 0);
set_omr : in std_logic;
new_omr : in std_logic_vector(7 downto 0);
set_lc : in std_logic;
new_lc : in unsigned(15 downto 0);
dec_lc : in std_logic;
set_la : in std_logic;
new_la : in unsigned(BW_ADDRESS-1 downto 0)
);
end component reg_file;
signal register_file : register_file_type;
signal rf_wr_R_port_A_valid : std_logic;
signal rf_wr_R_port_B_valid : std_logic;
signal rf_reg_wr_addr : std_logic_vector(5 downto 0);
signal rf_reg_wr_addr_valid : std_logic;
signal rf_reg_wr_data : std_logic_vector(23 downto 0);
signal rf_reg_rd_addr : std_logic_vector(5 downto 0);
signal rf_reg_rd_data : std_logic_vector(23 downto 0);
signal rf_X_bus_rd_addr : std_logic_vector(1 downto 0);
signal rf_X_bus_data_out : std_logic_vector(23 downto 0);
signal rf_X_bus_wr_addr : std_logic_vector(1 downto 0);
signal rf_X_bus_wr_valid : std_logic;
signal rf_X_bus_data_in : std_logic_vector(23 downto 0);
signal rf_Y_bus_rd_addr : std_logic_vector(1 downto 0);
signal rf_Y_bus_data_out : std_logic_vector(23 downto 0);
signal rf_Y_bus_wr_addr : std_logic_vector(1 downto 0);
signal rf_Y_bus_wr_valid : std_logic;
signal rf_Y_bus_data_in : std_logic_vector(23 downto 0);
signal rf_L_bus_rd_addr : std_logic_vector(2 downto 0);
signal rf_L_bus_rd_valid : std_logic;
signal rf_L_bus_wr_addr : std_logic_vector(2 downto 0);
signal rf_L_bus_wr_valid : std_logic;
signal push_stack : push_stack_type;
signal pop_stack : pop_stack_type;
signal rf_set_sr : std_logic;
signal rf_new_sr : std_logic_vector(15 downto 0);
signal rf_set_omr : std_logic;
signal rf_new_omr : std_logic_vector(7 downto 0);
signal rf_dec_lc : std_logic;
signal rf_set_lc : std_logic;
signal rf_new_lc : unsigned(15 downto 0);
signal rf_set_la : std_logic;
signal rf_new_la : unsigned(BW_ADDRESS-1 downto 0);
signal rf_alu_wr_valid : std_logic;
component memory_management is port (
clk, rst : in std_logic;
stall_flags : in std_logic_vector(PIPELINE_DEPTH-1 downto 0);
memory_stall : out std_logic;
data_rom_enable: in std_logic;
pmem_ctrl_in : in mem_ctrl_type_in;
pmem_ctrl_out : out mem_ctrl_type_out;
xmem_ctrl_in : in mem_ctrl_type_in;
xmem_ctrl_out : out mem_ctrl_type_out;
ymem_ctrl_in : in mem_ctrl_type_in;
ymem_ctrl_out : out mem_ctrl_type_out
);
end component memory_management;
signal memory_stall : std_logic;
signal pmem_ctrl_in : mem_ctrl_type_in;
signal pmem_ctrl_out : mem_ctrl_type_out;
signal xmem_ctrl_in : mem_ctrl_type_in;
signal xmem_ctrl_out : mem_ctrl_type_out;
signal ymem_ctrl_in : mem_ctrl_type_in;
signal ymem_ctrl_out : mem_ctrl_type_out;
signal pmem_data_out : std_logic_vector(23 downto 0);
signal pmem_data_out_valid : std_logic;
signal xmem_data_out : std_logic_vector(23 downto 0);
signal xmem_data_out_valid : std_logic;
signal ymem_data_out : std_logic_vector(23 downto 0);
signal ymem_data_out_valid : std_logic;
begin
register_file_out <= register_file;
-- merge all stall sources
stall_flags(ST_FETCH) <= '1' when exec_loop_stall_rep = '1' or
memory_stall = '1' or
exec_loop_stall_do = '1' else '0';
stall_flags(ST_FETCH2) <= '1' when exec_loop_stall_rep = '1' or
memory_stall = '1' or
exec_loop_stall_do = '1' else '0';
stall_flags(ST_DECODE) <= '1' when exec_loop_stall_rep = '1' or
memory_stall = '1' or
exec_loop_stall_do = '1' else '0';
stall_flags(ST_ADGEN) <= exec_loop_stall_do;
-- stall_flags(ST_ADGEN) <= '1' when memory_stall = '1' or
-- exec_loop_stall_do = '1' else '0';
-- stall_flags(ST_EXEC) <= '0';
stall_flags(ST_EXEC) <= exec_loop_stall_do;
-- stall_flags(ST_EXEC) <= '1' when memory_stall = '1' or
-- exec_loop_stall_do = '1' else '0';
shift_pipeline: process(clk, rst) is
procedure flush_pipeline_stage(stage: natural) is
begin
pipeline_regs(stage).pc <= (others => '1');
pipeline_regs(stage).instr_word <= (others => '0');
pipeline_regs(stage).act_array <= (others => '0');
pipeline_regs(stage).instr_array <= INSTR_NOP;
pipeline_regs(stage).dble_word_instr <= '0';
pipeline_regs(stage).dec_activate <= '0';
pipeline_regs(stage).adgen_mode_a <= NOP;
pipeline_regs(stage).adgen_mode_b <= NOP;
pipeline_regs(stage).reg_wr_addr <= (others => '0');
pipeline_regs(stage).reg_rd_addr <= (others => '0');
pipeline_regs(stage).x_bus_rd_addr <= (others => '0');
pipeline_regs(stage).x_bus_wr_addr <= (others => '0');
pipeline_regs(stage).y_bus_rd_addr <= (others => '0');
pipeline_regs(stage).y_bus_wr_addr <= (others => '0');
pipeline_regs(stage).l_bus_addr <= (others => '0');
pipeline_regs(stage).adgen_address_x <= (others => '0');
pipeline_regs(stage).adgen_address_y <= (others => '0');
pipeline_regs(stage).RAM_out_x <= (others => '0');
pipeline_regs(stage).RAM_out_y <= (others => '0');
pipeline_regs(stage).alu_ctrl.store_result <= '0';
end procedure flush_pipeline_stage;
begin
if rising_edge(clk) then
if rst = '1' then
for i in 0 to PIPELINE_DEPTH-1 loop
flush_pipeline_stage(i);
end loop;
else
-- shift the pipeline registers when no stall applies
for i in 1 to PIPELINE_DEPTH-1 loop
if stall_flags(i) = '0' then
-- do not copy the pipeline registers from a stalled pipeline stage
-- for REP we do not flush
-- if stall_flags(i-1) = '1' then
if (stall_flags(i-1) = '1' and exec_loop_stall_rep = '0') or
(i = ST_ADGEN and memory_stall = '1' and exec_loop_stall_rep = '1') then
flush_pipeline_stage(i);
else
pipeline_regs(i) <= pipeline_regs(i-1);
end if;
end if;
end loop;
-- FETCH Pipeline Registers
if stall_flags(ST_FETCH) = '0' then
pipeline_regs(ST_FETCH).pc <= pc_new;
pipeline_regs(ST_FETCH).dec_activate <= '1';
end if;
-- FETCH2 Pipeline Registers
if stall_flags(ST_FETCH2) = '0' then
-- Normal pipeline operation?
-- Buffering of RAM output when stalling is performed in the memory management
if pmem_data_out_valid = '1' then
pipeline_regs(ST_FETCH2).instr_word <= pmem_data_out;
end if;
end if;
-- DECODE Pipeline registers
if stall_flags(ST_DECODE) = '0' then
pipeline_regs(ST_DECODE).act_array <= dec_act_array;
pipeline_regs(ST_DECODE).instr_array <= dec_instr_array;
pipeline_regs(ST_DECODE).dble_word_instr <= dec_dble_word_instr;
pipeline_regs(ST_DECODE).reg_wr_addr <= dec_reg_wr_addr;
pipeline_regs(ST_DECODE).reg_rd_addr <= dec_reg_rd_addr;
pipeline_regs(ST_DECODE).x_bus_wr_addr <= dec_x_bus_wr_addr;
pipeline_regs(ST_DECODE).x_bus_rd_addr <= dec_x_bus_rd_addr;
pipeline_regs(ST_DECODE).y_bus_wr_addr <= dec_y_bus_wr_addr;
pipeline_regs(ST_DECODE).y_bus_rd_addr <= dec_y_bus_rd_addr;
pipeline_regs(ST_DECODE).l_bus_addr <= dec_l_bus_addr;
pipeline_regs(ST_DECODE).adgen_mode_a <= dec_adgen_mode_a;
pipeline_regs(ST_DECODE).adgen_mode_b <= dec_adgen_mode_b;
pipeline_regs(ST_DECODE).alu_ctrl <= dec_alu_ctrl;
end if;
-- ADGEN Pipeline registers
if stall_flags(ST_ADGEN) = '0' then
pipeline_regs(ST_ADGEN).adgen_address_x <= adgen_address_out_x;
pipeline_regs(ST_ADGEN).adgen_address_y <= adgen_address_out_y;
end if;
if xmem_data_out_valid = '1' then
pipeline_regs(ST_ADGEN).RAM_out_x <= xmem_data_out;
end if;
if ymem_data_out_valid = '1' then
pipeline_regs(ST_ADGEN).RAM_out_y <= ymem_data_out;
end if;
-- EXEC Pipeline stuff
if exec_bra_modify_pc = '1' or exec_loop_modify_pc = '1' then
-- clear the following pipeline stages,
-- since we modified the pc.
-- Do not flush ST_FETCH - it will hold the correct pc.
flush_pipeline_stage(ST_FETCH2);
flush_pipeline_stage(ST_DECODE);
flush_pipeline_stage(ST_ADGEN);
end if;
end if;
end if;
end process shift_pipeline;
-------------------------------
-- FETCH STAGE INSTANTIATION
-------------------------------
inst_fetch_stage: fetch_stage port map(
pc_old => pc_old,
pc_new => pc_new,
modify_pc => fetch_modify_pc,
modified_pc => fetch_modified_pc,
register_file => register_file,
decrement_lc => fetch_decrement_lc,
perform_enddo => fetch_perform_enddo
);
pc_old <= pipeline_regs(ST_FETCH).pc;
fetch_modify_pc <= '1' when exec_bra_modify_pc = '1' or exec_loop_modify_pc = '1' else '0';
fetch_modified_pc <= exec_bra_modified_pc when exec_bra_modify_pc = '1' else
exec_loop_modified_pc;
-------------------------------
-- DECODE STAGE INSTANTIATION
-------------------------------
inst_decode_stage : decode_stage port map(
activate_dec => dec_activate,
instr_word => dec_instr_word,
dble_word_instr => dec_dble_word_instr,
instr_array => dec_instr_array,
act_array => dec_act_array,
reg_wr_addr => dec_reg_wr_addr,
reg_rd_addr => dec_reg_rd_addr,
x_bus_wr_addr => dec_x_bus_wr_addr,
x_bus_rd_addr => dec_x_bus_rd_addr,
y_bus_wr_addr => dec_y_bus_wr_addr,
y_bus_rd_addr => dec_y_bus_rd_addr,
l_bus_addr => dec_l_bus_addr,
adgen_mode_a => dec_adgen_mode_a,
adgen_mode_b => dec_adgen_mode_b,
alu_ctrl => dec_alu_ctrl
);
dec_instr_word <= pipeline_regs(ST_DECODE-1).instr_word;
-- do not decode, when we have no valid instruction. This can happen when
-- 1) the pipeline just started its operation
-- 2) the pipeline was flushed due to a jump
-- 3) we are processing a instruction that consists of two words
dec_activate <= '1' when pipeline_regs(ST_DECODE-1).dec_activate = '1' and pipeline_regs(ST_DECODE).dble_word_instr = '0' else '0';
-------------------------------
-- AGU STAGE INSTANTIATION
-------------------------------
inst_adgen_stage: adgen_stage port map(
activate_adgen => adgen_activate,
activate_x_mem => adgen_activate_x_mem,
activate_y_mem => adgen_activate_y_mem,
activate_l_mem => adgen_activate_l_mem,
instr_word => adgen_instr_word,
instr_array => adgen_instr_array,
optional_ea_word => adgen_optional_ea_word,
register_file => register_file,
adgen_mode_a => adgen_mode_a,
adgen_mode_b => adgen_mode_b,
address_out_x => adgen_address_out_x,
address_out_y => adgen_address_out_y,
wr_R_port_A_valid => adgen_wr_R_port_A_valid,
wr_R_port_A => adgen_wr_R_port_A,
wr_R_port_B_valid => adgen_wr_R_port_B_valid,
wr_R_port_B => adgen_wr_R_port_B
);
adgen_activate <= pipeline_regs(ST_ADGEN-1).act_array(ACT_ADGEN);
adgen_activate_x_mem <= '1' when pipeline_regs(ST_ADGEN-1).act_array(ACT_X_MEM_RD) = '1' or
pipeline_regs(ST_ADGEN-1).act_array(ACT_X_MEM_WR) = '1' else '0';
adgen_activate_y_mem <= '1' when pipeline_regs(ST_ADGEN-1).act_array(ACT_Y_MEM_RD) = '1' or
pipeline_regs(ST_ADGEN-1).act_array(ACT_Y_MEM_WR) = '1' else '0';
adgen_activate_l_mem <= '1' when pipeline_regs(ST_ADGEN-1).act_array(ACT_L_BUS_RD) = '1' or
pipeline_regs(ST_ADGEN-1).act_array(ACT_L_BUS_WR) = '1' else '0';
adgen_instr_word <= pipeline_regs(ST_ADGEN-1).instr_word;
adgen_instr_array <= pipeline_regs(ST_ADGEN-1).instr_array;
adgen_optional_ea_word <= pipeline_regs(ST_ADGEN-2).instr_word;
adgen_mode_a <= pipeline_regs(ST_ADGEN-1).adgen_mode_a;
adgen_mode_b <= pipeline_regs(ST_ADGEN-1).adgen_mode_b;
-------------------------------
-- EXECUTE STAGE INSTANTIATIONS
-------------------------------
inst_exec_stage_alu: exec_stage_alu port map(
alu_activate => exec_alu_activate,
instr_word => exec_alu_instr_word,
alu_ctrl => exec_alu_ctrl,
register_file => register_file,
addr_r_in => exec_alu_addr_r_in,
addr_r_out => exec_alu_addr_r_out,
modify_accu => exec_alu_modify_accu,
dst_accu => exec_alu_dst_accu,
modified_accu => exec_alu_modified_accu,
modify_sr => exec_alu_modify_sr,
modified_sr => exec_alu_modified_sr
);
exec_alu_activate <= pipeline_regs(ST_EXEC-1).act_array(ACT_ALU);
exec_alu_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
exec_alu_ctrl <= pipeline_regs(ST_EXEC-1).alu_ctrl;
exec_alu_addr_r_in <= unsigned(rf_reg_rd_data(BW_ADDRESS-1 downto 0));
inst_exec_stage_bit_modify: exec_stage_bit_modify port map(
instr_word => exec_bit_modify_instr_word,
instr_array => exec_bit_modify_instr_array,
src_operand => exec_bit_modify_src_operand,
register_file => register_file,
dst_operand => exec_bit_modify_dst_operand,
bit_cond_met => exec_bit_modify_bit_cond_met,
modify_sr => exec_bit_modify_modify_sr,
modified_sr => exec_bit_modify_modified_sr
);
exec_bit_modify_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
exec_bit_modify_instr_array <= pipeline_regs(ST_EXEC-1).instr_array;
exec_bit_modify_src_operand <= exec_src_operand;
-- Writing to the register file using the 6 bit addressing scheme
-- sources are:
-- 1) X-RAM output
-- 2) Y-RAM output
-- 3) register file itself
-- 4) short immediate value (8 bit stored in instruction word)
-- 5) long immediate value (from optional effective address extension)
-- 5) address generated by the address generation unit (LUA instr)
exec_src_operand <= pipeline_regs(ST_EXEC-1).RAM_out_x when pipeline_regs(ST_EXEC-1).act_array(ACT_X_MEM_RD) = '1' else
pipeline_regs(ST_EXEC-1).RAM_out_y when pipeline_regs(ST_EXEC-1).act_array(ACT_Y_MEM_RD) = '1' else
rf_reg_rd_data when pipeline_regs(ST_EXEC-1).act_array(ACT_REG_RD) = '1' else
exec_imm_8bit when pipeline_regs(ST_EXEC-1).act_array(ACT_IMM_8BIT) = '1' else
exec_imm_12bit when pipeline_regs(ST_EXEC-1).act_array(ACT_IMM_12BIT) = '1' else
pipeline_regs(ST_EXEC-2).instr_word when pipeline_regs(ST_EXEC-1).act_array(ACT_IMM_LONG) = '1' else
std_logic_vector(resize(pipeline_regs(ST_EXEC-1).adgen_address_x, 24)); -- for LUA instr.
-- Destination for the register file using the 6 bit addressing scheme.
-- Either read the bit modified version of the read value
-- or use the modified Rn in case of a NORM instruction
-- exec_dst_operand <= exec_bit_modify_dst_operand;
exec_dst_operand <= exec_bit_modify_dst_operand when pipeline_regs(ST_EXEC-1).act_array(ACT_NORM) = '0' else
std_logic_vector(resize(exec_alu_addr_r_out,24));
-- Unit to check whether cc (in Jcc, JScc, Tcc, ...) is true
inst_exec_stage_cc_flag_calc: exec_stage_cc_flag_calc port map(
instr_word => exec_cc_flag_calc_instr_word,
instr_array => exec_cc_flag_calc_instr_array,
register_file => register_file,
cc_flag_set => exec_cc_flag_set
);
exec_cc_flag_calc_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
exec_cc_flag_calc_instr_array <= pipeline_regs(ST_EXEC-1).instr_array;
inst_exec_stage_branch : exec_stage_branch port map(
activate_exec_bra => exec_bra_activate,
instr_word => exec_bra_instr_word,
instr_array => exec_bra_instr_array,
register_file => register_file,
jump_address => exec_bra_jump_address,
bit_cond_met => exec_bra_bit_cond_met,
cc_flag_set => exec_cc_flag_set,
push_stack => exec_bra_push_stack,
pop_stack => exec_bra_pop_stack,
modify_pc => exec_bra_modify_pc,
modified_pc => exec_bra_modified_pc,
modify_sr => exec_bra_modify_sr,
modified_sr => exec_bra_modified_sr
);
exec_bra_activate <= pipeline_regs(ST_EXEC-1).act_array(ACT_EXEC_BRA);
exec_bra_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
exec_bra_instr_array <= pipeline_regs(ST_EXEC-1).instr_array;
exec_bra_jump_address <= pipeline_regs(ST_EXEC-1).adgen_address_x when pipeline_regs(ST_EXEC-1).dble_word_instr = '0' else
unsigned(pipeline_regs(ST_EXEC-2).instr_word(BW_ADDRESS-1 downto 0));
exec_bra_bit_cond_met <= exec_bit_modify_bit_cond_met;
inst_exec_stage_cr_mod : exec_stage_cr_mod port map(
activate_exec_cr_mod => exec_cr_mod_activate,
instr_word => exec_cr_mod_instr_word,
instr_array => exec_cr_mod_instr_array,
register_file => register_file,
modify_sr => exec_cr_mod_modify_sr,
modified_sr => exec_cr_mod_modified_sr,
modify_omr => exec_cr_mod_modify_omr,
modified_omr => exec_cr_mod_modified_omr
);
exec_cr_mod_activate <= pipeline_regs(ST_EXEC-1).act_array(ACT_EXEC_CR_MOD);
exec_cr_mod_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
exec_cr_mod_instr_array <= pipeline_regs(ST_EXEC-1).instr_array;
inst_exec_stage_loop: exec_stage_loop port map(
clk => clk,
rst => rst,
activate_exec_loop => exec_loop_activate,
instr_word => exec_loop_instr_word,
instr_array => exec_loop_instr_array,
loop_iterations => exec_loop_iterations,
loop_address => exec_loop_address,
loop_start_address => exec_loop_start_address,
register_file => register_file,
fetch_perform_enddo=> fetch_perform_enddo,
memory_stall => memory_stall,
push_stack => exec_loop_push_stack,
pop_stack => exec_loop_pop_stack,
stall_rep => exec_loop_stall_rep,
stall_do => exec_loop_stall_do,
modify_lc => exec_loop_modify_lc,
decrement_lc => exec_loop_decrement_lc,
modified_lc => exec_loop_modified_lc,
modify_la => exec_loop_modify_la,
modified_la => exec_loop_modified_la,
modify_pc => exec_loop_modify_pc,
modified_pc => exec_loop_modified_pc,
modify_sr => exec_loop_modify_sr,
modified_sr => exec_loop_modified_sr
);
exec_loop_activate <= pipeline_regs(ST_EXEC-1).act_array(ACT_EXEC_LOOP);
exec_loop_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
exec_loop_instr_array <= pipeline_regs(ST_EXEC-1).instr_array;
exec_loop_iterations <= unsigned(exec_src_operand(15 downto 0));
-- from which source is our operand?
-- - XMEM
-- - YMEM
-- - Any register
-- - Immediate (from instruction word)
-- exec_src_operand <= unsigned(pipeline_regs(ST_EXEC-1).RAM_out_x(BW_ADDRESS-1 downto 0)) when
-- pipeline_regs(ST_EXEC-1).act_array(ACT_X_MEM_RD) = '1' else
-- unsigned(pipeline_regs(ST_EXEC-1).RAM_out_y(BW_ADDRESS-1 downto 0)) when
-- pipeline_regs(ST_EXEC-1).act_array(ACT_Y_MEM_RD) = '1' else
-- unsigned(rf_reg_rd_data(15 downto 0)) when
-- pipeline_regs(ST_EXEC-1).act_array(ACT_REG_RD) = '1' else
-- "00000000" & unsigned(pipeline_regs(ST_EXEC-1).instr_word(15 downto 8));
-- Loop address is given by the second instruction word of the DO instruction.
-- This address is available one previous stage within the pipeline
exec_loop_address <= unsigned(pipeline_regs(ST_EXEC-2).instr_word(BW_ADDRESS-1 downto 0)) - 1;
-- one more stage before we find the programm counter of the first instruction to be executed in a DO loop
exec_loop_start_address <= unsigned(pipeline_regs(ST_EXEC-3).pc);
-- For the 8 bit immediate is can be either a fractional (registers x0,x1,y0,y1,a,b) or an unsigned (the rest)
exec_imm_8bit(23 downto 16) <= (others => '0') when rf_reg_wr_addr(5 downto 2) /= "0001" and rf_reg_wr_addr(5 downto 1) /= "00111" else
pipeline_regs(ST_EXEC-1).instr_word(15 downto 8);
exec_imm_8bit(15 downto 8) <= (others => '0');
exec_imm_8bit( 7 downto 0) <= (others => '0') when rf_reg_wr_addr(5 downto 2) = "0001" or rf_reg_wr_addr(5 downto 1) = "00111" else
pipeline_regs(ST_EXEC-1).instr_word(15 downto 8);
-- The 12 bit immediate stems from the instruction word
exec_imm_12bit(23 downto 12) <= (others => '0');
exec_imm_12bit(11 downto 0) <= pipeline_regs(ST_EXEC-1).instr_word(3 downto 0) & pipeline_regs(ST_EXEC-1).instr_word(15 downto 8);
-----------------
-- REGISTER FILE
-----------------
inst_reg_file: reg_file port map(
clk => clk,
rst => rst,
register_file => register_file,
wr_R_port_A_valid => rf_wr_R_port_A_valid,
wr_R_port_A => adgen_wr_R_port_A,
wr_R_port_B_valid => rf_wr_R_port_B_valid,
wr_R_port_B => adgen_wr_R_port_B,
reg_wr_addr => rf_reg_wr_addr,
reg_wr_addr_valid => rf_reg_wr_addr_valid,
reg_wr_data => rf_reg_wr_data,
reg_rd_addr => rf_reg_rd_addr,
reg_rd_data => rf_reg_rd_data,
alu_wr_valid => rf_alu_wr_valid,
alu_wr_addr => exec_alu_dst_accu,
alu_wr_data => exec_alu_modified_accu,
X_bus_rd_addr => rf_X_bus_rd_addr,
X_bus_data_out => rf_X_bus_data_out,
X_bus_wr_addr => rf_X_bus_wr_addr ,
X_bus_wr_valid => rf_X_bus_wr_valid,
X_bus_data_in => rf_X_bus_data_in ,
Y_bus_rd_addr => rf_Y_bus_rd_addr ,
Y_bus_data_out => rf_Y_bus_data_out,
Y_bus_wr_addr => rf_Y_bus_wr_addr ,
Y_bus_wr_valid => rf_Y_bus_wr_valid,
Y_bus_data_in => rf_Y_bus_data_in ,
L_bus_rd_addr => rf_L_bus_rd_addr ,
L_bus_rd_valid => rf_L_bus_rd_valid,
L_bus_wr_addr => rf_L_bus_wr_addr ,
L_bus_wr_valid => rf_L_bus_wr_valid,
push_stack => push_stack,
pop_stack => pop_stack,
set_sr => rf_set_sr,
new_sr => rf_new_sr,
set_omr => rf_set_omr,
new_omr => rf_new_omr,
set_la => rf_set_la,
new_la => rf_new_la,
dec_lc => rf_dec_lc,
set_lc => rf_set_lc,
new_lc => rf_new_lc
);
-----------------
-- BUSES (X,Y,L)
-----------------
rf_X_bus_wr_valid <= pipeline_regs(ST_EXEC-1).act_array(ACT_X_BUS_WR);
rf_X_bus_wr_addr <= pipeline_regs(ST_EXEC-1).x_bus_wr_addr;
rf_X_bus_rd_addr <= pipeline_regs(ST_EXEC-1).x_bus_rd_addr;
rf_X_bus_data_in <= rf_X_bus_data_out when pipeline_regs(ST_EXEC-1).act_array(ACT_X_BUS_RD) = '1' else
pipeline_regs(ST_EXEC-1).RAM_out_x; -- when pipeline_regs(ST_EXEC-1).act_array(ACT_X_MEM_RD) = '1' else
rf_Y_bus_wr_valid <= pipeline_regs(ST_EXEC-1).act_array(ACT_Y_BUS_WR);
rf_Y_bus_wr_addr <= pipeline_regs(ST_EXEC-1).y_bus_wr_addr;
rf_Y_bus_rd_addr <= pipeline_regs(ST_EXEC-1).y_bus_rd_addr;
rf_Y_bus_data_in <= rf_Y_bus_data_out when pipeline_regs(ST_EXEC-1).act_array(ACT_Y_BUS_RD) = '1' else
pipeline_regs(ST_EXEC-1).RAM_out_y; -- when pipeline_regs(ST_EXEC-1).act_array(ACT_Y_MEM_RD) = '1' else
rf_L_bus_wr_valid <= pipeline_regs(ST_EXEC-1).act_array(ACT_L_BUS_WR);
rf_L_bus_rd_valid <= pipeline_regs(ST_EXEC-1).act_array(ACT_L_BUS_RD);
rf_L_bus_wr_addr <= pipeline_regs(ST_EXEC-1).l_bus_addr; -- equal to bits in instruction word
rf_L_bus_rd_addr <= pipeline_regs(ST_EXEC-1).l_bus_addr; -- could be simplified by taking these bits..
-- writing to the R registers within the ADGEN stage has to be prevented when
-- 1) a jump is currently being executed (which is detected in the exec stage)
-- 2) stall cycles occur. In this case the write will happen in the last cycle, when we stop stalling.
-- 3) a memory access results in a stall (e.g. caused by the instruction to REP)
rf_wr_R_port_A_valid <= '0' when stall_flags(ST_ADGEN) = '1' or
exec_bra_modify_pc = '1' or
memory_stall = '1' else
adgen_wr_R_port_A_valid;
rf_wr_R_port_B_valid <= '0' when stall_flags(ST_ADGEN) = '1' or
exec_bra_modify_pc = '1' or
memory_stall = '1' else
adgen_wr_R_port_B_valid;
rf_reg_wr_addr <= pipeline_regs(ST_EXEC-1).reg_wr_addr;
-- can be set due to
-- 1) normal write operation (e.g., move)
-- 2) conditional move (Tcc)
rf_reg_wr_addr_valid <= '1' when pipeline_regs(ST_EXEC-1).act_array(ACT_REG_WR) = '1' else
exec_cc_flag_set when pipeline_regs(ST_EXEC-1).act_array(ACT_REG_WR_CC) = '1' else '0';
rf_reg_wr_data <= exec_dst_operand;
rf_reg_rd_addr <= pipeline_regs(ST_EXEC-1).reg_rd_addr;
-- Writing from the ALU can depend on the condition code (Tcc) instruction
rf_alu_wr_valid <= exec_cc_flag_set when pipeline_regs(ST_EXEC-1).act_array(ACT_ALU_WR_CC) = '1' else
exec_alu_modify_accu;
push_stack.valid <= '1' when exec_bra_push_stack.valid = '1' or exec_loop_push_stack.valid = '1' else '0';
push_stack.content <= exec_bra_push_stack.content when exec_bra_push_stack.valid = '1' else
exec_loop_push_stack.content;
-- for jump to subroutine store the pc of the subsequent instruction
push_stack.pc <= pipeline_regs(ST_EXEC-2).pc when exec_bra_push_stack.valid = '1' and pipeline_regs(ST_EXEC-1).dble_word_instr = '0' else
pipeline_regs(ST_EXEC-3).pc when exec_bra_push_stack.valid = '1' and pipeline_regs(ST_EXEC-1).dble_word_instr = '1' else
exec_loop_push_stack.pc when exec_loop_push_stack.valid = '1' else
(others => '0');
pop_stack.valid <= '1' when exec_bra_pop_stack.valid = '1' or exec_loop_pop_stack.valid = '1' else '0';
rf_set_sr <= '1' when exec_bra_modify_sr = '1' or
exec_cr_mod_modify_sr = '1' or
exec_loop_modify_sr = '1' or
exec_alu_modify_sr = '1' or
exec_bit_modify_modify_sr = '1' else '0';
rf_new_sr <= exec_bra_modified_sr when exec_bra_modify_sr = '1' else
exec_cr_mod_modified_sr when exec_cr_mod_modify_sr = '1' else
exec_loop_modified_sr when exec_loop_modify_sr = '1' else
exec_alu_modified_sr when exec_alu_modify_sr = '1' else
exec_bit_modify_modified_sr; -- when exec_bit_modify_modify_sr = '1' else
rf_set_omr <= exec_cr_mod_modify_omr;
rf_new_omr <= exec_cr_mod_modified_omr;
rf_set_lc <= exec_loop_modify_lc;
rf_new_lc <= exec_loop_modified_lc;
rf_set_la <= exec_loop_modify_la;
rf_new_la <= exec_loop_modified_la;
rf_dec_lc <= '1' when exec_loop_decrement_lc = '1' or fetch_decrement_lc = '1' else '0';
---------------------
-- MEMORY MANAGEMENT
---------------------
MMU_inst: memory_management port map (
clk => clk,
rst => rst,
stall_flags => stall_flags,
memory_stall => memory_stall,
data_rom_enable => register_file.omr(2),
pmem_ctrl_in => pmem_ctrl_in,
pmem_ctrl_out => pmem_ctrl_out,
xmem_ctrl_in => xmem_ctrl_in,
xmem_ctrl_out => xmem_ctrl_out,
ymem_ctrl_in => ymem_ctrl_in,
ymem_ctrl_out => ymem_ctrl_out
);
------------------
-- Program Memory
------------------
pmem_ctrl_in.rd_addr <= pc_new;
pmem_ctrl_in.rd_en <= '1' when stall_flags(ST_FETCH) = '0' else '0';
-- TODO: Writing to PMEM!
pmem_ctrl_in.wr_addr <= (others => '0');
pmem_ctrl_in.wr_en <= '0';
pmem_ctrl_in.data_in <= (others => '0');
pmem_data_out <= pmem_ctrl_out.data_out;
pmem_data_out_valid <= pmem_ctrl_out.data_out_valid;
------------------
-- X Memory
------------------
-- Either take the result of the AGU or use the short absolute value stored in the instruction word
xmem_ctrl_in.rd_addr <= adgen_address_out_x when pipeline_regs(ST_ADGEN-1).act_array(ACT_ADGEN) = '1' else
"0000000000" & unsigned(pipeline_regs(ST_ADGEN-1).instr_word(13 downto 8));
xmem_ctrl_in.rd_en <= '1' when pipeline_regs(ST_ADGEN-1).act_array(ACT_X_MEM_RD) = '1' else '0';
-- Either take the result of the AGU or use the absolute value stored in the instruction word
xmem_ctrl_in.wr_addr <= pipeline_regs(ST_EXEC-1).adgen_address_x when pipeline_regs(ST_EXEC-1).act_array(ACT_ADGEN) = '1' else
"0000000000" & unsigned(pipeline_regs(ST_EXEC-1).instr_word(13 downto 8));
xmem_ctrl_in.wr_en <= '1' when pipeline_regs(ST_EXEC-1).act_array(ACT_X_MEM_WR) = '1' else '0';
xmem_ctrl_in.data_in <= rf_X_bus_data_out when pipeline_regs(ST_EXEC-1).act_array(ACT_X_BUS_RD) = '1' or
pipeline_regs(ST_EXEC-1).act_array(ACT_L_BUS_RD) = '1' else
exec_dst_operand;
xmem_data_out <= xmem_ctrl_out.data_out;
xmem_data_out_valid <= xmem_ctrl_out.data_out_valid;
------------------
-- Y Memory
------------------
-- Either take the result of the AGU or use the absolute value stored in the instruction word
ymem_ctrl_in.rd_addr <= adgen_address_out_y when pipeline_regs(ST_ADGEN-1).act_array(ACT_ADGEN) = '1' else
"0000000000" & unsigned(pipeline_regs(ST_ADGEN-1).instr_word(13 downto 8));
ymem_ctrl_in.rd_en <= '1' when pipeline_regs(ST_ADGEN-1).act_array(ACT_Y_MEM_RD) = '1' else '0';
-- Either take the result of the AGU or use the absolute value stored in the instruction word
ymem_ctrl_in.wr_addr <= pipeline_regs(ST_EXEC-1).adgen_address_y when pipeline_regs(ST_EXEC-1).act_array(ACT_ADGEN) = '1' else
"0000000000" & unsigned(pipeline_regs(ST_EXEC-1).instr_word(13 downto 8));
ymem_ctrl_in.wr_en <= '1' when pipeline_regs(ST_EXEC-1).act_array(ACT_Y_MEM_WR) = '1' else '0';
ymem_ctrl_in.data_in <= rf_Y_bus_data_out when pipeline_regs(ST_EXEC-1).act_array(ACT_Y_BUS_RD) = '1' or
pipeline_regs(ST_EXEC-1).act_array(ACT_L_BUS_RD) = '1' else
exec_dst_operand;
ymem_data_out <= ymem_ctrl_out.data_out;
ymem_data_out_valid <= ymem_ctrl_out.data_out_valid;
end architecture rtl;

View File

@@ -0,0 +1,679 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
use work.types_pkg.all;
use work.constants_pkg.all;
entity reg_file is port(
clk, rst : in std_logic;
register_file : out register_file_type;
wr_R_port_A_valid : in std_logic;
wr_R_port_A : in addr_wr_port_type;
wr_R_port_B_valid : in std_logic;
wr_R_port_B : in addr_wr_port_type;
alu_wr_valid : in std_logic;
alu_wr_addr : in std_logic;
alu_wr_data : in signed(55 downto 0);
reg_wr_addr : in std_logic_vector(5 downto 0);
reg_wr_addr_valid : in std_logic;
reg_wr_data : in std_Logic_vector(23 downto 0);
reg_rd_addr : in std_logic_vector(5 downto 0);
reg_rd_data : out std_Logic_vector(23 downto 0);
X_bus_rd_addr : in std_logic_vector(1 downto 0);
X_bus_data_out : out std_logic_vector(23 downto 0);
X_bus_wr_addr : in std_logic_vector(1 downto 0);
X_bus_wr_valid : in std_logic;
X_bus_data_in : in std_logic_vector(23 downto 0);
Y_bus_rd_addr : in std_logic_vector(1 downto 0);
Y_bus_data_out : out std_logic_vector(23 downto 0);
Y_bus_wr_addr : in std_logic_vector(1 downto 0);
Y_bus_wr_valid : in std_logic;
Y_bus_data_in : in std_logic_vector(23 downto 0);
L_bus_rd_addr : in std_logic_vector(2 downto 0);
L_bus_rd_valid : in std_logic;
L_bus_wr_addr : in std_logic_vector(2 downto 0);
L_bus_wr_valid : in std_logic;
push_stack : in push_stack_type;
pop_stack : in pop_stack_type;
set_sr : in std_logic;
new_sr : in std_logic_vector(15 downto 0);
set_omr : in std_logic;
new_omr : in std_logic_vector(7 downto 0);
dec_lc : in std_logic;
set_lc : in std_logic;
new_lc : in unsigned(15 downto 0);
set_la : in std_logic;
new_la : in unsigned(BW_ADDRESS-1 downto 0)
);
end entity;
architecture rtl of reg_file is
signal addr_r : addr_array;
signal addr_m : addr_array;
signal addr_n : addr_array;
signal loop_address : unsigned(BW_ADDRESS-1 downto 0);
signal loop_counter : unsigned(15 downto 0);
-- condition code register
signal ccr : std_logic_vector(7 downto 0);
-- mode register
signal mr : std_logic_vector(7 downto 0);
-- status register = mode register + condition code register
signal sr : std_logic_vector(15 downto 0);
-- operation mode register
signal omr : std_logic_vector(7 downto 0);
signal stack_pointer : unsigned(5 downto 0);
signal system_stack_ssh : stack_array_type;
signal system_stack_ssl : stack_array_type;
signal x0 : signed(23 downto 0);
signal x1 : signed(23 downto 0);
signal y0 : signed(23 downto 0);
signal y1 : signed(23 downto 0);
signal a0 : signed(23 downto 0);
signal a1 : signed(23 downto 0);
signal a2 : signed(7 downto 0);
signal b0 : signed(23 downto 0);
signal b1 : signed(23 downto 0);
signal b2 : signed(7 downto 0);
signal limited_a1 : signed(23 downto 0);
signal limited_b1 : signed(23 downto 0);
signal limited_a0 : signed(23 downto 0);
signal limited_b0 : signed(23 downto 0);
signal set_limiting_flag : std_logic;
signal X_bus_rd_limited_a : std_logic;
signal X_bus_rd_limited_b : std_logic;
signal Y_bus_rd_limited_a : std_logic;
signal Y_bus_rd_limited_b : std_logic;
signal reg_rd_limited_a : std_logic;
signal reg_rd_limited_b : std_logic;
signal rd_limited_a : std_logic;
signal rd_limited_b : std_logic;
begin
sr <= mr & ccr;
register_file.addr_r <= addr_r;
register_file.addr_n <= addr_n;
register_file.addr_m <= addr_m;
register_file.lc <= loop_counter;
register_file.la <= loop_address;
register_file.ccr <= ccr;
register_file.mr <= mr;
register_file.sr <= sr;
register_file.omr <= omr;
register_file.stack_pointer <= stack_pointer;
register_file.current_ssh <= system_stack_ssh(to_integer(stack_pointer(3 downto 0)));
register_file.current_ssl <= system_stack_ssl(to_integer(stack_pointer(3 downto 0)));
register_file.a <= a2 & a1 & a0;
register_file.b <= b2 & b1 & b0;
register_file.x0 <= x0;
register_file.x1 <= x1;
register_file.y0 <= y0;
register_file.y1 <= y1;
global_register_file: process(clk) is
variable stack_pointer_plus_1 : unsigned(3 downto 0);
variable reg_addr : integer range 0 to 7;
begin
if rising_edge(clk) then
if rst = '1' then
addr_r <= (others => (others => '0'));
addr_n <= (others => (others => '0'));
addr_m <= (others => (others => '1'));
ccr <= (others => '0');
mr <= (others => '0');
omr <= (others => '0');
system_stack_ssl <= (others => (others => '0'));
system_stack_ssh <= (others => (others => '0'));
stack_pointer <= (others => '0');
loop_counter <= (others => '0');
loop_address <= (others => '0');
x0 <= (others => '0');
x1 <= (others => '0');
y0 <= (others => '0');
y1 <= (others => '0');
a0 <= (others => '0');
a1 <= (others => '0');
a2 <= (others => '0');
b0 <= (others => '0');
b1 <= (others => '0');
b2 <= (others => '0');
else
reg_addr := to_integer(unsigned(reg_wr_addr(2 downto 0)));
-----------------------------------------------------------------------
-- General write port to register file using 6 bit addressing scheme
-----------------------------------------------------------------------
if reg_wr_addr_valid = '1' then
case reg_wr_addr(5 downto 3) is
-- X0, X1, Y0, Y1
when "000" =>
case reg_wr_addr(2 downto 0) is
when "100" =>
x0 <= signed(reg_wr_data);
when "101" =>
x1 <= signed(reg_wr_data);
when "110" =>
y0 <= signed(reg_wr_data);
when "111" =>
y1 <= signed(reg_wr_data);
when others =>
end case;
-- A0, B0, A2, B2, A1, B1, A, B
when "001" =>
case reg_wr_addr(2 downto 0) is
when "000" =>
a0 <= signed(reg_wr_data);
when "001" =>
b0 <= signed(reg_wr_data);
when "010" =>
a2 <= signed(reg_wr_data(7 downto 0));
when "011" =>
b2 <= signed(reg_wr_data(7 downto 0));
when "100" =>
a1 <= signed(reg_wr_data);
when "101" =>
b1 <= signed(reg_wr_data);
when "110" =>
a2 <= (others => reg_wr_data(23));
a1 <= signed(reg_wr_data);
a0 <= (others => '0');
when "111" =>
b2 <= (others => reg_wr_data(23));
b1 <= signed(reg_wr_data);
b0 <= (others => '0');
when others =>
end case;
-- R0-R7
when "010" =>
addr_r(reg_addr) <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
-- N0-N7
when "011" =>
addr_n(reg_addr) <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
-- M0-M7
when "100" =>
addr_m(reg_addr) <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
-- SR, OMR, SP, SSH, SSL, LA, LC
when "111" =>
case reg_wr_addr(2 downto 0) is
-- SR
when "001" =>
mr <= reg_wr_data(15 downto 8);
ccr <= reg_wr_data( 7 downto 0);
-- OMR
when "010" =>
omr <= reg_wr_data(7 downto 0);
-- SP
when "011" =>
stack_pointer <= unsigned(reg_wr_data(5 downto 0));
-- SSH
when "100" =>
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= reg_wr_data(BW_ADDRESS-1 downto 0);
-- increase stack after writing
stack_pointer(3 downto 0) <= stack_pointer_plus_1;
-- test whether stack is full, if so set the stack error flag (SE)
if stack_pointer(3 downto 0) = "1111" then
stack_pointer(4) <= '1';
end if;
-- SSL
when "101" =>
system_stack_ssl(to_integer(stack_pointer)) <= reg_wr_data(BW_ADDRESS-1 downto 0);
-- LA
when "110" =>
loop_address <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
-- LC
when "111" =>
loop_counter <= unsigned(reg_wr_data(15 downto 0));
when others =>
end case;
when others =>
end case;
end if;
----------------
-- X BUS Write
----------------
if X_bus_wr_valid = '1' then
case X_bus_wr_addr is
when "00" =>
x0 <= signed(X_bus_data_in);
when "01" =>
x1 <= signed(X_bus_data_in);
when "10" =>
a2 <= (others => X_bus_data_in(23));
a1 <= signed(X_bus_data_in);
a0 <= (others => '0');
when others =>
b2 <= (others => X_bus_data_in(23));
b1 <= signed(X_bus_data_in);
b0 <= (others => '0');
end case;
end if;
----------------
-- Y BUS Write
----------------
if Y_bus_wr_valid = '1' then
case Y_bus_wr_addr is
when "00" =>
y0 <= signed(Y_bus_data_in);
when "01" =>
y1 <= signed(Y_bus_data_in);
when "10" =>
a2 <= (others => Y_bus_data_in(23));
a1 <= signed(Y_bus_data_in);
a0 <= (others => '0');
when others =>
b2 <= (others => Y_bus_data_in(23));
b1 <= signed(Y_bus_data_in);
b0 <= (others => '0');
end case;
end if;
------------------
-- L BUS Write
------------------
if L_bus_wr_valid = '1' then
case L_bus_wr_addr is
-- A10
when "000" =>
a1 <= signed(X_bus_data_in);
a0 <= signed(Y_bus_data_in);
-- B10
when "001" =>
b1 <= signed(X_bus_data_in);
b0 <= signed(Y_bus_data_in);
-- X
when "010" =>
x1 <= signed(X_bus_data_in);
x0 <= signed(Y_bus_data_in);
-- Y
when "011" =>
y1 <= signed(X_bus_data_in);
y0 <= signed(Y_bus_data_in);
-- A
when "100" =>
a2 <= (others => X_bus_data_in(23));
a1 <= signed(X_bus_data_in);
a0 <= signed(Y_bus_data_in);
-- B
when "101" =>
b2 <= (others => X_bus_data_in(23));
b1 <= signed(X_bus_data_in);
b0 <= signed(Y_bus_data_in);
-- AB
when "110" =>
a2 <= (others => X_bus_data_in(23));
a1 <= signed(X_bus_data_in);
a0 <= (others => '0');
b2 <= (others => Y_bus_data_in(23));
b1 <= signed(Y_bus_data_in);
b0 <= (others => '0');
-- BA
when others =>
a2 <= (others => Y_bus_data_in(23));
a1 <= signed(Y_bus_data_in);
a0 <= (others => '0');
b2 <= (others => X_bus_data_in(23));
b1 <= signed(X_bus_data_in);
b0 <= (others => '0');
end case;
end if;
---------------------
-- STATUS REGISTERS
---------------------
if set_sr = '1' then
ccr <= new_sr( 7 downto 0);
mr <= new_sr(15 downto 8);
end if;
if set_omr = '1' then
omr <= new_omr;
end if;
-- data limiter active?
-- listing this statement after the set_sr test results
-- in the correct behaviour for ALU operations with parallel move
if set_limiting_flag = '1' then
ccr(6) <= '1';
end if;
--------------------
-- LOOP REGISTERS
--------------------
if set_la = '1' then
loop_address <= new_la;
end if;
if set_lc = '1' then
loop_counter <= new_lc;
end if;
if dec_lc = '1' then
loop_counter <= loop_counter - 1;
end if;
---------------------
-- ADDRESS REGISTER
---------------------
if wr_R_port_A_valid = '1' then
addr_r(to_integer(wr_R_port_A.reg_number)) <= wr_R_port_A.reg_value;
end if;
if wr_R_port_B_valid = '1' then
addr_r(to_integer(wr_R_port_B.reg_number)) <= wr_R_port_B.reg_value;
end if;
-------------------------
-- ALU ACCUMULATOR WRITE
-------------------------
if alu_wr_valid = '1' then
if alu_wr_addr = '0' then
a2 <= alu_wr_data(55 downto 48);
a1 <= alu_wr_data(47 downto 24);
a0 <= alu_wr_data(23 downto 0);
else
b2 <= alu_wr_data(55 downto 48);
b1 <= alu_wr_data(47 downto 24);
b0 <= alu_wr_data(23 downto 0);
end if;
end if;
---------------------
-- STACK CONTROLLER
---------------------
stack_pointer_plus_1 := stack_pointer(3 downto 0) + 1;
if push_stack.valid = '1' then
-- increase stack after writing
stack_pointer(3 downto 0) <= stack_pointer_plus_1;
-- test whether stack is full, if so set the stack error flag (SE)
if stack_pointer(3 downto 0) = "1111" then
stack_pointer(4) <= '1';
end if;
case push_stack.content is
when PC =>
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= std_logic_vector(push_stack.pc);
when PC_AND_SR =>
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= std_logic_vector(push_stack.pc);
system_stack_ssl(to_integer(stack_pointer_plus_1)) <= SR;
when LA_AND_LC =>
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= std_logic_vector(loop_address);
system_stack_ssl(to_integer(stack_pointer_plus_1)) <= std_logic_vector(loop_counter);
end case;
end if;
-- decrease stack pointer
if pop_stack.valid = '1' then
stack_pointer(3 downto 0) <= stack_pointer(3 downto 0) - 1;
-- if stack is empty set the underflow flag (bit 5, UF) and the stack error flag (bit 4, SE)
if stack_pointer(3 downto 0) = "0000" then
stack_pointer(5) <= '1';
stack_pointer(4) <= '1';
end if;
end if;
end if;
end if;
end process;
x_bus_rd_port: process(X_bus_rd_addr,x0,x1,a1,b1,limited_a1,limited_b1,
L_bus_rd_addr,L_bus_rd_valid,y1) is
begin
X_bus_rd_limited_a <= '0';
X_bus_rd_limited_b <= '0';
case X_bus_rd_addr is
when "00" => X_bus_data_out <= std_logic_vector(x0);
when "01" => X_bus_data_out <= std_logic_vector(x1);
when "10" => X_bus_data_out <= std_logic_vector(limited_a1); X_bus_rd_limited_a <= '1';
when others => X_bus_data_out <= std_logic_vector(limited_b1); X_bus_rd_limited_b <= '1';
end case;
if L_bus_rd_valid = '1' then
case L_bus_rd_addr is
when "000" => X_bus_data_out <= std_logic_vector(a1);
when "001" => X_bus_data_out <= std_logic_vector(b1);
when "010" => X_bus_data_out <= std_logic_vector(x1);
when "011" => X_bus_data_out <= std_logic_vector(y1);
when "100" => X_bus_data_out <= std_logic_vector(limited_a1); X_bus_rd_limited_a <= '1';
when "101" => X_bus_data_out <= std_logic_vector(limited_b1); X_bus_rd_limited_b <= '1';
when "110" => X_bus_data_out <= std_logic_vector(limited_a1); X_bus_rd_limited_a <= '1';
when others => X_bus_data_out <= std_logic_vector(limited_b1); X_bus_rd_limited_b <= '1';
end case;
end if;
end process x_bus_rd_port;
y_bus_rd_port: process(Y_bus_rd_addr,y0,y1,a1,b1,limited_a1,limited_b1,
L_bus_rd_addr,L_bus_rd_valid,a0,b0,x0,limited_a0,limited_b0) is
begin
Y_bus_rd_limited_a <= '0';
Y_bus_rd_limited_b <= '0';
case Y_bus_rd_addr is
when "00" => Y_bus_data_out <= std_logic_vector(y0);
when "01" => Y_bus_data_out <= std_logic_vector(y1);
when "10" => Y_bus_data_out <= std_logic_vector(limited_a1); Y_bus_rd_limited_a <= '1';
when others => Y_bus_data_out <= std_logic_vector(limited_b1); Y_bus_rd_limited_b <= '1';
end case;
if L_bus_rd_valid = '1' then
case L_bus_rd_addr is
when "000" => Y_bus_data_out <= std_logic_vector(a0);
when "001" => Y_bus_data_out <= std_logic_vector(b0);
when "010" => Y_bus_data_out <= std_logic_vector(x0);
when "011" => Y_bus_data_out <= std_logic_vector(y0);
when "100" => Y_bus_data_out <= std_logic_vector(limited_a0); Y_bus_rd_limited_a <= '1';
when "101" => Y_bus_data_out <= std_logic_vector(limited_b0); Y_bus_rd_limited_b <= '1';
when "110" => Y_bus_data_out <= std_logic_vector(limited_b1); Y_bus_rd_limited_b <= '1';
when others => Y_bus_data_out <= std_logic_vector(limited_a1); Y_bus_rd_limited_a <= '1';
end case;
end if;
end process y_bus_rd_port;
reg_rd_port: process(reg_rd_addr, x0,x1,y0,y1,a0,a1,a2,b0,b1,b2,
omr,ccr,mr,addr_r,addr_n,addr_m,stack_pointer,
loop_address,loop_counter,system_stack_ssl,system_stack_ssh) is
variable reg_addr : integer range 0 to 7;
begin
reg_addr := to_integer(unsigned(reg_rd_addr(2 downto 0)));
reg_rd_data <= (others => '0');
reg_rd_limited_a <= '0';
reg_rd_limited_b <= '0';
case reg_rd_addr(5 downto 3) is
-- X0, X1, Y0, Y1
when "000" =>
case reg_rd_addr(2 downto 0) is
when "100" =>
reg_rd_data <= std_logic_vector(x0);
when "101" =>
reg_rd_data <= std_logic_vector(x1);
when "110" =>
reg_rd_data <= std_logic_vector(y0);
when "111" =>
reg_rd_data <= std_logic_vector(y1);
when others =>
end case;
-- A0, B0, A2, B2, A1, B1, A, B
when "001" =>
case reg_rd_addr(2 downto 0) is
when "000" =>
reg_rd_data <= std_logic_vector(a0);
when "001" =>
reg_rd_data <= std_logic_vector(b0);
when "010" =>
-- MSBs are read as zero!
reg_rd_data(23 downto 8) <= (others => '0');
reg_rd_data(7 downto 0) <= std_logic_vector(a2);
when "011" =>
-- MSBs are read as zero!
reg_rd_data(23 downto 8) <= (others => '0');
reg_rd_data(7 downto 0) <= std_logic_vector(b2);
when "100" =>
reg_rd_data <= std_logic_vector(a1);
when "101" =>
reg_rd_data <= std_logic_vector(b1);
when "110" =>
reg_rd_data <= std_logic_vector(limited_a1);
reg_rd_limited_a <= '1';
when "111" =>
reg_rd_data <= std_logic_vector(limited_b1);
reg_rd_limited_b <= '1';
when others =>
end case;
-- R0-R7
when "010" =>
reg_rd_data <= std_logic_vector(resize(addr_r(reg_addr), 24));
-- N0-N7
when "011" =>
reg_rd_data <= std_logic_vector(resize(addr_n(reg_addr), 24));
-- M0-M7
when "100" =>
reg_rd_data <= std_logic_vector(resize(addr_m(reg_addr), 24));
-- SR, OMR, SP, SSH, SSL, LA, LC
when "111" =>
case reg_wr_addr(2 downto 0) is
-- SR
when "001" =>
reg_rd_data(23 downto 16) <= (others => '0');
reg_rd_data(15 downto 0) <= mr & ccr;
-- OMR
when "010" =>
reg_rd_data(23 downto 8) <= (others => '0');
reg_rd_data( 7 downto 0) <= omr;
-- SP
when "011" =>
reg_rd_data(23 downto 6) <= (others => '0');
reg_rd_data(5 downto 0) <= std_logic_vector(stack_pointer);
-- SSH
when "100" =>
-- TODO!
-- system_stack_ssh(to_integer(stack_pointer_plus_1)) <= reg_wr_data(BW_ADDRESS-1 downto 0);
-- -- increase stack after writing
-- stack_pointer(3 downto 0) <= stack_pointer_plus_1;
-- -- test whether stack is full, if so set the stack error flag (SE)
-- if stack_pointer(3 downto 0) = "1111" then
-- stack_pointer(4) <= '1';
-- end if;
-- SSL
when "101" =>
reg_rd_data <= (others => '0');
reg_rd_data(BW_ADDRESS-1 downto 0) <= std_logic_vector(system_stack_ssl(to_integer(stack_pointer)));
-- LA
when "110" =>
reg_rd_data <= (others => '0');
reg_rd_data(BW_ADDRESS-1 downto 0) <= std_logic_vector(loop_address);
-- LC
when "111" =>
reg_rd_data <= (others => '0');
reg_rd_data(15 downto 0) <= std_logic_vector(loop_counter);
when others =>
end case;
when others =>
end case;
end process;
rd_limited_a <= '1' when reg_rd_limited_a = '1' or X_bus_rd_limited_a = '1' or Y_bus_rd_limited_a = '1' else '0';
rd_limited_b <= '1' when reg_rd_limited_b = '1' or X_bus_rd_limited_b = '1' or Y_bus_rd_limited_b = '1' else '0';
data_shifter_limiter: process(a2,a1,a0,b2,b1,b0,sr,rd_limited_a,rd_limited_b) is
variable scaled_a : signed(55 downto 0);
variable scaled_b : signed(55 downto 0);
begin
set_limiting_flag <= '0';
-----------------
-- DATA SCALING
-----------------
-- test against scaling bits S1, S0
case sr(11 downto 10) is
-- scale down (right shift)
when "01" =>
scaled_a := a2(7) & a2 & a1 & a0(23 downto 1);
scaled_b := b2(7) & b2 & b1 & b0(23 downto 1);
-- scale up (arithmetic left shift)
when "10" =>
scaled_a := a2(6 downto 0) & a1 & a0 & '0';
scaled_b := b2(6 downto 0) & b1 & b0 & '0';
-- "00" do not scale!
when others =>
scaled_a := a2 & a1 & a0;
scaled_b := b2 & b1 & b0;
end case;
-- only sign extension stored in a2?
-- Yes: No limiting needed!
if scaled_a(55 downto 47) = "111111111" or scaled_a(55 downto 47) = "000000000" then
limited_a1 <= scaled_a(47 downto 24);
limited_a0 <= scaled_a(23 downto 0);
else
-- positive value in a?
if scaled_a(55) = '0' then
limited_a1 <= X"7FFFFF";
limited_a0 <= X"FFFFFF";
-- negative value in a?
else
limited_a1 <= X"800000";
limited_a0 <= X"000000";
end if;
-- set the limit flag in the status register
if rd_limited_a = '1' then
set_limiting_flag <= '1';
end if;
end if;
-- only sign extension stored in b2?
-- Yes: No limiting needed!
if scaled_b(55 downto 47) = "111111111" or scaled_b(55 downto 47) = "000000000" then
limited_b1 <= scaled_b(47 downto 24);
limited_b0 <= scaled_b(23 downto 0);
else
-- positive value in b?
if scaled_b(55) = '0' then
limited_b1 <= X"7FFFFF";
limited_b0 <= X"FFFFFF";
-- negative value in b?
else
limited_b1 <= X"800000";
limited_b0 <= X"000000";
end if;
-- set the limit flag in the status register
if rd_limited_b = '1' then
set_limiting_flag <= '1';
end if;
end if;
end process;
end architecture rtl;

View File

@@ -0,0 +1,167 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.parameter_pkg.all;
package types_pkg is
-- the different addressing modes
type adgen_mode_type is (NOP, POST_MIN_N, POST_PLUS_N, POST_MIN_1, POST_PLUS_1, INDEXED_N, PRE_MIN_1, ABSOLUTE, IMMEDIATE);
------------------------
-- Decoded instructions
------------------------
type instructions_type is (
INSTR_NOP ,
INSTR_RTI ,
INSTR_ILLEGAL ,
INSTR_SWI ,
INSTR_RTS ,
INSTR_RESET ,
INSTR_WAIT ,
INSTR_STOP ,
INSTR_ENDDO ,
INSTR_ANDI ,
INSTR_ORI ,
INSTR_DIV ,
INSTR_NORM ,
INSTR_LUA ,
INSTR_MOVEC ,
INSTR_REP ,
INSTR_DO ,
INSTR_MOVEM ,
INSTR_MOVEP ,
INSTR_PM_MOVEM,
INSTR_BCLR ,
INSTR_BSET ,
INSTR_JCLR ,
INSTR_JSET ,
INSTR_JMP ,
INSTR_JCC ,
INSTR_BCHG ,
INSTR_BTST ,
INSTR_JSCLR ,
INSTR_JSSET ,
INSTR_JSR ,
INSTR_JSCC );
type addr_array is array(0 to 7) of unsigned(BW_ADDRESS-1 downto 0);
type alu_shift_mode is (NO_SHIFT, SHIFT_LEFT, SHIFT_RIGHT, ZEROS);
type alu_ccr_flag is (DONT_TOUCH, CLEAR, MODIFY, SET);
type alu_ccr_flag_array is array(7 downto 0) of alu_ccr_flag;
type alu_ctrl_type is record
mul_op1 : std_logic_vector(1 downto 0); -- x0,x1,y0,y1
mul_op2 : std_logic_vector(1 downto 0); -- x0,x1,y0,y1
shift_src : std_logic; -- a,b
shift_src_sign : std_logic_vector(1 downto 0); -- 00: pos, 01: neg, 10: sign dependant, 11: reserved
shift_mode : alu_shift_mode;
rotate : std_logic; -- 0: logical shift, 1: rotate shift
add_src_stage_1 : std_logic_vector(2 downto 0); -- x0,x1,y0,y1,x,y,a,b
add_src_stage_2 : std_logic_vector(1 downto 0); -- 00: 0 , 01: add_src_1, 10: mul_result, 11: reserved
add_src_sign : std_logic_vector(1 downto 0); -- 00: pos, 01: neg, 10: sign dependant, 11: reserved
logic_function : std_logic_vector(2 downto 0); -- 000: none, 001: and, 010: or, 011: eor, 100: not
word_24_update : std_logic; -- only accumulator bits 47 downto 24 affected?
rounding_used : std_logic_vector(1 downto 0); -- 00: no rounding, 01: rounding, 10: add carry, 11: subtract carry
store_result : std_logic; -- 0: do not update accumulator, 1: update accumulator
dst_accu : std_logic; -- 0: a, 1: b
div_instr : std_logic; -- DIV instruction? Special ALU operations needed!
norm_instr : std_logic; -- NORM instruction? Special ALU operations needed!
ccr_flags_ctrl : alu_ccr_flag_array;
end record;
type pipeline_signals is record
instr_word: std_logic_vector(23 downto 0);
pc : unsigned(BW_ADDRESS-1 downto 0);
dble_word_instr : std_logic;
instr_array : instructions_type;
act_array : std_logic_vector(NUM_ACT_SIGNALS-1 downto 0);
dec_activate : std_logic;
adgen_mode_a : adgen_mode_type;
adgen_mode_b : adgen_mode_type;
reg_wr_addr : std_logic_vector(5 downto 0);
reg_rd_addr : std_logic_vector(5 downto 0);
x_bus_rd_addr : std_logic_vector(1 downto 0);
x_bus_wr_addr : std_logic_vector(1 downto 0);
y_bus_rd_addr : std_logic_vector(1 downto 0);
y_bus_wr_addr : std_logic_vector(1 downto 0);
l_bus_addr : std_logic_vector(2 downto 0);
adgen_address_x : unsigned(BW_ADDRESS-1 downto 0);
adgen_address_y : unsigned(BW_ADDRESS-1 downto 0);
RAM_out_x : std_logic_vector(23 downto 0);
RAM_out_y : std_logic_vector(23 downto 0);
alu_ctrl : alu_ctrl_type;
end record;
type pipeline_type is array(0 to PIPELINE_DEPTH-1) of pipeline_signals;
type register_file_type is record
a : signed(55 downto 0);
b : signed(55 downto 0);
x0 : signed(23 downto 0);
x1 : signed(23 downto 0);
y0 : signed(23 downto 0);
y1 : signed(23 downto 0);
la : unsigned(BW_ADDRESS-1 downto 0);
lc : unsigned(15 downto 0);
addr_r : addr_array;
addr_n : addr_array;
addr_m : addr_array;
ccr : std_logic_vector(7 downto 0);
mr : std_logic_vector(7 downto 0);
sr : std_logic_vector(15 downto 0);
omr : std_logic_vector(7 downto 0);
stack_pointer : unsigned(5 downto 0);
-- system_stack_ssh : stack_array_type;
-- system_stack_ssl : stack_array_type;
current_ssh : std_logic_vector(BW_ADDRESS-1 downto 0);
current_ssl : std_logic_vector(BW_ADDRESS-1 downto 0);
end record;
type addr_wr_port_type is record
-- write_valid : std_logic;
reg_number : unsigned(2 downto 0);
reg_value : unsigned(15 downto 0);
end record;
type mem_ctrl_type_in is record
rd_addr : unsigned(BW_ADDRESS-1 downto 0);
rd_en : std_logic;
wr_addr : unsigned(BW_ADDRESS-1 downto 0);
wr_en : std_logic;
data_in : std_logic_vector(23 downto 0);
end record;
type mem_ctrl_type_out is record
data_out : std_logic_vector(23 downto 0);
data_out_valid : std_logic;
end record;
type memory_type is (X_MEM, Y_MEM, P_MEM);
---------------
-- STACK TYPES
---------------
type stack_array_type is array(0 to 15) of std_logic_vector(BW_ADDRESS-1 downto 0);
type push_stack_content_type is (PC, PC_AND_SR, LA_AND_LC);
type push_stack_type is record
valid : std_logic;
pc : unsigned(BW_ADDRESS-1 downto 0);
content : push_stack_content_type;
end record;
-- type pop_stack_content_type is (PC, PC_AND_SR, SR, LA_AND_LC);
-- type pop_stack_type is std_logic;
type pop_stack_type is record
valid : std_logic;
-- content : pop_stack_content_type;
end record;
end package types_pkg;

View File

@@ -0,0 +1,971 @@
-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.
-- Copyright (C) 1991-2008 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- Generated by Quartus II Version 8.1 (Build Build 163 10/28/2008)
-- Created on Tue Sep 08 16:24:20 2009
library work;
use work.FalconIO_SDCard_IDE_CF_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
-- Entity Declaration
-- Entity Declaration
ENTITY FalconIO_SDCard_IDE_CF IS
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
PORT
(
CLK33M : IN STD_LOGIC;
MAIN_CLK : IN STD_LOGIC;
CLK2M : IN STD_LOGIC;
CLK500k : IN STD_LOGIC;
nFB_CS1 : IN STD_LOGIC;
FB_SIZE0 : IN STD_LOGIC;
FB_SIZE1 : IN STD_LOGIC;
nFB_BURST : IN STD_LOGIC;
FB_ADR : IN STD_LOGIC_VECTOR(31 downto 0);
LP_BUSY : IN STD_LOGIC;
nACSI_DRQ : IN STD_LOGIC;
nACSI_INT : IN STD_LOGIC;
nSCSI_DRQ : IN STD_LOGIC;
nSCSI_MSG : IN STD_LOGIC;
MIDI_IN : IN STD_LOGIC;
RxD : IN STD_LOGIC;
CTS : IN STD_LOGIC;
RI : IN STD_LOGIC;
DCD : IN STD_LOGIC;
AMKB_RX : IN STD_LOGIC;
PIC_AMKB_RX : IN STD_LOGIC;
IDE_RDY : IN STD_LOGIC;
IDE_INT : IN STD_LOGIC;
WP_CS_CARD : IN STD_LOGIC;
nINDEX : IN STD_LOGIC;
TRACK00 : IN STD_LOGIC;
nRD_DATA : IN STD_LOGIC;
nDCHG : IN STD_LOGIC;
SD_DATA0 : IN STD_LOGIC;
SD_DATA1 : IN STD_LOGIC;
SD_DATA2 : IN STD_LOGIC;
SD_CARD_DEDECT : IN STD_LOGIC;
SD_WP : IN STD_LOGIC;
nDACK0 : IN STD_LOGIC;
nFB_WR : INOUT STD_LOGIC;
WP_CF_CARD : IN STD_LOGIC;
nWP : IN STD_LOGIC;
nFB_CS2 : IN STD_LOGIC;
nRSTO : IN STD_LOGIC;
HD_DD : IN STD_LOGIC;
nSCSI_C_D : IN STD_LOGIC;
nSCSI_I_O : IN STD_LOGIC;
CLK2M4576 : IN STD_LOGIC;
nFB_OE : IN STD_LOGIC;
VSYNC : IN STD_LOGIC;
HSYNC : IN STD_LOGIC;
DSP_INT : IN STD_LOGIC;
nBLANK : IN STD_LOGIC;
FDC_CLK : IN STD_LOGIC;
FB_ALE : IN STD_LOGIC;
ACP_CONF : IN STD_LOGIC_VECTOR(31 downto 24);
nIDE_CS1 : OUT STD_LOGIC;
nIDE_CS0 : OUT STD_LOGIC;
LP_STR : OUT STD_LOGIC;
LP_DIR : OUT STD_LOGIC;
nACSI_ACK : OUT STD_LOGIC;
nACSI_RESET : OUT STD_LOGIC;
nACSI_CS : OUT STD_LOGIC;
ACSI_DIR : OUT STD_LOGIC;
ACSI_A1 : OUT STD_LOGIC;
nSCSI_ACK : OUT STD_LOGIC;
nSCSI_ATN : OUT STD_LOGIC;
SCSI_DIR : OUT STD_LOGIC;
SD_CLK : OUT STD_LOGIC;
YM_QA : OUT STD_LOGIC;
YM_QC : OUT STD_LOGIC;
YM_QB : OUT STD_LOGIC;
nSDSEL : OUT STD_LOGIC;
STEP : OUT STD_LOGIC;
MOT_ON : OUT STD_LOGIC;
nRP_LDS : OUT STD_LOGIC;
nRP_UDS : OUT STD_LOGIC;
nROM4 : OUT STD_LOGIC;
nROM3 : OUT STD_LOGIC;
nCF_CS1 : OUT STD_LOGIC;
nCF_CS0 : OUT STD_LOGIC;
nIDE_RD : INOUT STD_LOGIC;
nIDE_WR : INOUT STD_LOGIC;
AMKB_TX : OUT STD_LOGIC;
IDE_RES : OUT STD_LOGIC;
DTR : OUT STD_LOGIC;
RTS : OUT STD_LOGIC;
TxD : OUT STD_LOGIC;
MIDI_OLR : OUT STD_LOGIC;
MIDI_TLR : OUT STD_LOGIC;
nDREQ0 : OUT STD_LOGIC;
DSA_D : OUT STD_LOGIC;
nMFP_INT : OUT STD_LOGIC;
FALCON_IO_TA : OUT STD_LOGIC;
STEP_DIR : OUT STD_LOGIC;
WR_DATA : OUT STD_LOGIC;
WR_GATE : OUT STD_LOGIC;
DMA_DRQ : OUT STD_LOGIC;
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0);
LP_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
ACSI_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
SCSI_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
SCSI_PAR : INOUT STD_LOGIC;
nSCSI_SEL : INOUT STD_LOGIC;
nSCSI_BUSY : INOUT STD_LOGIC;
nSCSI_RST : INOUT STD_LOGIC;
SD_CD_DATA3 : INOUT STD_LOGIC;
SD_CDM_D1 : INOUT STD_LOGIC
);
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
END FalconIO_SDCard_IDE_CF;
-- Architecture Body
ARCHITECTURE FalconIO_SDCard_IDE_CF_architecture OF FalconIO_SDCard_IDE_CF IS
-- system
signal SYS_CLK : STD_LOGIC;
signal RESETn : STD_LOGIC;
signal FB_B0 : STD_LOGIC; -- UPPER BYT BEI 16BIT BUS
signal FB_B1 : STD_LOGIC; -- LOWER BYT BEI 16BIT BUS
signal BYT : STD_LOGIC; -- WENN BYT -> 1
signal LONG : STD_LOGIC; -- WENN -> 1
-- KEYBOARD MIDI
signal ACIA_CS_I : STD_LOGIC;
signal IRQ_KEYBDn : STD_LOGIC;
signal IRQ_MIDIn : STD_LOGIC;
signal KEYB_RxD : STD_LOGIC;
signal AMKB_REG : STD_LOGIC_VECTOR(4 downto 0);
signal MIDI_OUT : STD_LOGIC;
signal DATA_OUT_ACIA_I : STD_LOGIC_VECTOR(7 downto 0);
signal DATA_OUT_ACIA_II : STD_LOGIC_VECTOR(7 downto 0);
-- MFP
signal MFP_CS : STD_LOGIC;
signal MFP_INTACK : STD_LOGIC;
signal LDS : STD_LOGIC;
signal DTACK_OUT_MFPn : STD_LOGIC;
signal IRQ_ACIAn : STD_LOGIC;
signal DINTn : STD_LOGIC;
signal DATA_OUT_MFP : STD_LOGIC_VECTOR(7 downto 0);
signal TDO : STD_LOGIC;
-- SOUND
signal SNDCS : STD_LOGIC;
signal SNDCS_I : STD_LOGIC;
signal SNDIR_I : STD_LOGIC;
signal LP_DIR_X : STD_LOGIC;
signal DA_OUT_X : STD_LOGIC_VECTOR(7 downto 0);
signal LP_D_X : STD_LOGIC_VECTOR(7 downto 0);
-- DIV
signal SUB_BUS : STD_LOGIC; -- SUB BUS MIT ROM-PORT, CF UND IDE
signal ROM_CS : STD_LOGIC;
-- DMA UND FLOPPY
signal DMA_DATEN_CS : STD_LOGIC;
signal DMA_MODUS_CS : STD_LOGIC;
signal DMA_MODUS : STD_LOGIC_VECTOR(15 downto 0);
signal WDC_BSL_CS : STD_LOGIC;
signal WDC_BSL : STD_LOGIC_VECTOR(1 DOWNTO 0);
signal HD_DD_OUT : STD_LOGIC;
signal FDCS_In : STD_LOGIC;
signal CA0 : STD_LOGIC;
signal CA1 : STD_LOGIC;
signal CA2 : STD_LOGIC;
signal FDINT : STD_LOGIC;
signal FDRQ : STD_LOGIC;
signal CD_OUT_FDC : STD_LOGIC_VECTOR(7 downto 0);
signal CD_IN_FDC : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_TOP_CS : STD_LOGIC;
signal DMA_TOP : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_HIGH_CS : STD_LOGIC;
signal DMA_HIGH : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_MID_CS : STD_LOGIC;
signal DMA_MID : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_LOW_CS : STD_LOGIC;
signal DMA_LOW : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_DIRM_CS : STD_LOGIC;
signal DMA_ADR_CS : STD_LOGIC;
signal DMA_STATUS : STD_LOGIC_VECTOR(2 downto 0);
signal DMA_DIR_OLD : STD_LOGIC;
signal DMA_BYT_CNT_CS : STD_LOGIC;
signal DMA_BYT_CNT : STD_LOGIC_VECTOR(31 downto 0);
signal CLR_FIFO : STD_LOGIC;
signal DMA_DRQ_I : STD_LOGIC;
signal DMA_DRQ_REG : STD_LOGIC_VECTOR(1 downto 0);
signal DMA_DRQQ : STD_LOGIC;
signal DMA_DRQ_Q : STD_LOGIC;
signal RDF_DOUT : STD_LOGIC_VECTOR(31 downto 0);
signal RDF_AZ : STD_LOGIC_VECTOR(9 downto 0);
signal RDF_RDE : STD_LOGIC;
signal RDF_WRE : STD_LOGIC;
signal RDF_DIN : STD_LOGIC_VECTOR(7 downto 0);
signal WRF_DOUT : STD_LOGIC_VECTOR(7 downto 0);
signal WRF_AZ : STD_LOGIC_VECTOR(9 downto 0);
signal WRF_RDE : STD_LOGIC;
signal WRF_WRE : STD_LOGIC;
signal nFDC_WR : STD_LOGIC;
type FCF_STATES is( FCF_IDLE, FCF_T0, FCF_T1, FCF_T2, FCF_T3, FCF_T6, FCF_T7);
signal FCF_STATE : FCF_STATES;
signal NEXT_FCF_STATE : FCF_STATES;
signal DMA_REQ : STD_LOGIC;
signal FDC_CS : STD_LOGIC;
signal FCF_CS : STD_LOGIC;
signal FCF_APH : STD_LOGIC;
signal DMA_AZ_CS : STD_LOGIC;
signal DMA_ACTIV : STD_LOGIC;
signal DMA_ACTIV_NEW : STD_LOGIC;
signal FDC_OUT : STD_LOGIC_VECTOR(7 downto 0);
-- SCSI
signal SCSI_CS : STD_LOGIC;
signal SCSI_CSn : STD_LOGIC;
signal SCSI_DOUT : STD_LOGIC_VECTOR(7 downto 0);
signal nSCSI_DACK : STD_LOGIC;
signal SCSI_DRQ : STD_LOGIC;
signal SCSI_INT : STD_LOGIC;
signal DB_OUTn : STD_LOGIC_VECTOR(7 downto 0);
signal DB_EN : STD_LOGIC;
signal DBP_OUTn : STD_LOGIC;
signal DBP_EN : STD_LOGIC;
signal RST_OUTn : STD_LOGIC;
signal RST_EN : STD_LOGIC;
signal BSY_OUTn : STD_LOGIC;
signal BSY_EN : STD_LOGIC;
signal SEL_OUTn : STD_LOGIC;
signal SEL_EN : STD_LOGIC;
-- IDE
signal nnIDE_RES : STD_LOGIC;
signal IDE_CF_CS : STD_LOGIC;
signal IDE_CF_TA : STD_LOGIC;
signal NEXT_nIDE_RD : STD_LOGIC;
signal NEXT_nIDE_WR : STD_LOGIC;
type CMD_STATES is( IDLE, T1, T6, T7);
signal CMD_STATE : CMD_STATES;
signal NEXT_CMD_STATE : CMD_STATES;
BEGIN
LONG <= '1' when FB_SIZE1 = '0' and FB_SIZE0 = '0' else '0';
BYT <= '1' when FB_SIZE1 = '0' and FB_SIZE0 = '1' else '0';
FB_B0 <= '1' when FB_ADR(0) = '0' or BYT = '0' else '0';
FB_B1 <= '1' when FB_ADR(0) = '1' or BYT = '0' else '0';
FALCON_IO_TA <= '1' when SNDCS = '1' or DTACK_OUT_MFPn = '0' or ACIA_CS_I = '1' or DMA_MODUS_CS ='1'
or DMA_ADR_CS = '1' or DMA_DIRM_CS = '1' or DMA_BYT_CNT_CS = '1' or FCF_CS = '1' or IDE_CF_TA = '1' else '0';
SUB_BUS <= '1' when nFB_WR = '1' and ROM_CS = '1' ELSE
'1' when nFB_WR = '1' and IDE_CF_CS = '1' ELSE
'1' when nFB_WR = '0' and nIDE_WR = '0' ELSE '0';
nRP_UDS <= '0' when SUB_BUS = '1' and FB_B0 = '1' else '1';
nRP_LDS <= '0' when SUB_BUS = '1' and FB_B1 = '1' else '1';
nDREQ0 <= '0';
----------------------------------------------------------------------------
-- SD
----------------------------------------------------------------------------
SD_CLK <= 'Z';
SD_CD_DATA3 <= 'Z';
SD_CDM_D1 <= 'Z';
----------------------------------------------------------------------------
-- IDE
----------------------------------------------------------------------------
CMD_REG: process(nRSTO, MAIN_CLK, CMD_STATE, NEXT_CMD_STATE)
begin
if nRSTO = '0' then
CMD_STATE <= IDLE;
elsif rising_edge(MAIN_CLK) then
CMD_STATE <= NEXT_CMD_STATE; -- go to next
nIDE_RD <= NEXT_nIDE_RD; -- go to next
nIDE_WR <= NEXT_nIDE_WR; -- go to next
else
CMD_STATE <= CMD_STATE; -- halten
nIDE_RD <= nIDE_RD; -- halten
nIDE_WR <= nIDE_WR; -- halten
end if;
end process CMD_REG;
CMD_DECODER: process(CMD_STATE, NEXT_CMD_STATE, NEXT_nIDE_RD, NEXT_nIDE_WR, IDE_RDY, IDE_CF_TA)
begin
case CMD_STATE is
when IDLE =>
IDE_CF_TA <= '0';
if IDE_CF_CS = '1' then
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T1;
else
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= IDLE;
end if;
when T1 =>
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T6;
when T6 =>
IF IDE_RDY = '1' then
IDE_CF_TA <= '1';
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= T7;
else
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T6;
end if;
when T7 =>
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= IDLE;
end case;
end process CMD_DECODER;
IDE_RES <= not nnIDE_RES and nRSTO;
IDE_CF_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 7) = x"0" else '0'; -- FFF0'0000/80
nCF_CS0 <= '0' when ACP_CONF(31) = '0' and FB_ADR(19 downto 5) = x"0" else -- FFFO'0000-FFF0'001F
'0' when ACP_CONF(31) = '1' and FB_ADR(19 downto 5) = x"2" else '1'; -- FFFO'0040-FFF0'005F
nCF_CS1 <= '0' when ACP_CONF(31) = '0' and FB_ADR(19 downto 5) = x"1" else -- FFF0'0020-FFF0'003F
'0' when ACP_CONF(31) = '1' and FB_ADR(19 downto 5) = x"3" else '1'; -- FFFO'0060-FFF0'007F
nIDE_CS0 <= '0' when ACP_CONF(30) = '0' and FB_ADR(19 downto 5) = x"2" else -- FFF0'0040-FFF0'005F
'0' when ACP_CONF(30) = '1' and FB_ADR(19 downto 5) = x"0" else '1'; -- FFFO'0000-FFF0'001F
nIDE_CS1 <= '0' when ACP_CONF(30) = '0' and FB_ADR(19 downto 5) = x"3" else -- FFF0'0060-FFF0'007F
'0' when ACP_CONF(30) = '1' and FB_ADR(19 downto 5) = x"1" else '1'; -- FFFO'0020-FFF0'003F
-----------------------------------------------------------------------------------------------------------------------------------------
-- ACSI, SCSI UND FLOPPY WD1772
-------------------------------------------------------------------------------------------------------------------------------------------
-- daten read fifo
RDF: dcfifo0
port map(
aclr => CLR_FIFO,
data => RDF_DIN,
rdclk => MAIN_CLK,
rdreq => RDF_RDE,
wrclk => FDC_CLK,
wrreq => RDF_WRE,
q => RDF_DOUT,
wrusedw => RDF_AZ
);
FCF_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"0020110" and LONG = '1' else '0'; -- F002'0110 LONG ONLY
FCF_APH <= '1' when FB_ALE = '1' and FB_AD(31 downto 0) = x"F0020110" and LONG = '1' else '0'; -- ADRESSPHASE F0020110 LONG ONLY
RDF_RDE <= '1' when FCF_APH = '1' and nFB_WR = '1' else '0'; -- AKTIVIEREN IN ADRESSPHASE
FB_AD <= RDF_DOUT(7 downto 0) & RDF_DOUT(15 downto 8) & RDF_DOUT(23 downto 16) & RDF_DOUT(31 downto 24) when FCF_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
RDF_DIN <= CD_OUT_FDC when DMA_MODUS(7) = '1' else SCSI_DOUT;
-- daten write fifo
WRF: dcfifo1
port map(
aclr => CLR_FIFO,
data => FB_AD(7 downto 0) & FB_AD(15 downto 8) & FB_AD(23 downto 16) & FB_AD(31 downto 24),
rdclk => FDC_CLK,
rdreq => WRF_RDE,
wrclk => MAIN_CLK,
wrreq => WRF_WRE,
q => WRF_DOUT,
rdusedw => WRF_AZ
);
CD_IN_FDC <= WRF_DOUT when DMA_ACTIV = '1' and DMA_MODUS(8) = '1' else FB_AD(23 downto 16); -- BEI DMA WRITE <-FIFO SONST <-FB
DMA_AZ_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"002010C" else '0'; -- F002'010C LONG
FB_AD <= DMA_DRQ_Q & DMA_DRQ_REG & IDE_INT & FDINT & SCSI_INT & RDF_AZ & "0" & DMA_STATUS & "00" & WRF_AZ when DMA_AZ_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
DMA_DRQ_Q <= '1' when DMA_DRQ_REG = "11" and DMA_MODUS(6) = '0' else '0';
-- FIFO WRITE: GENAU 1 MAIN_CLK -------------------------------------------------------------------------
process(MAIN_CLK, nRSTO, WRF_WRE, nFB_WR, FCF_APH)
begin
if nRSTO = '0' THEN
WRF_WRE <= '0';
elsif rising_edge(MAIN_CLK) then
IF FCF_APH = '1' and nFB_WR = '0' then
WRF_WRE <= '1';
else
WRF_WRE <= '0';
end if;
else
WRF_WRE <= WRF_WRE;
end if;
END PROCESS;
FCF_REG: process(nRSTO, FDC_CLK, FCF_STATE, NEXT_FCF_STATE, DMA_ACTIV)
begin
if nRSTO = '0' then
FCF_STATE <= FCF_IDLE;
DMA_ACTIV <= '0';
elsif rising_edge(FDC_CLK) then
FCF_STATE <= NEXT_FCF_STATE; -- go to next
DMA_ACTIV <= DMA_ACTIV_NEW;
else
FCF_STATE <= FCF_STATE; -- halten
DMA_ACTIV <= DMA_ACTIV;
end if;
end process FCF_REG;
FDC_REG: process(nRSTO, FDC_CLK, FDC_OUT, FDCS_In, CD_OUT_FDC)
begin
if nRSTO = '0' then
FDC_OUT <= x"00";
elsif rising_edge(FDC_CLK) and FDCS_In = '0' then
FDC_OUT <= CD_OUT_FDC; -- set
else
FDC_OUT <= FDC_OUT; -- halten
end if;
end process FDC_REG;
DMA_REQ <= '1' when ((DMA_DRQ_I = '1' and DMA_MODUS(7) = '1') or (SCSI_DRQ = '1' and DMA_MODUS(7) = '0')) and DMA_STATUS(1) = '1' and DMA_MODUS(6) = '0' and CLR_FIFO = '0' else '0';
FDC_CS <= '1' when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "00" and FB_B1 = '1' else '0';
SCSI_CS <= '1' when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "01" and FB_B1 = '1' else '0';
FCF_DECODER: process(FCF_STATE, NEXT_FCF_STATE, DMA_REQ,FDC_CS, RDF_WRE, WRF_RDE, SCSI_DRQ, nSCSI_DACK, DMA_MODUS, DMA_ACTIV, FDCS_In,SCSI_CS, SCSI_CSn)
begin
case FCF_STATE is
when FCF_IDLE =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
WRF_RDE <= '0';
nSCSI_DACK <= '1';
if DMA_REQ = '1' or FDC_CS = '1' or SCSI_CS = '1' then
DMA_ACTIV_NEW <= DMA_REQ;
NEXT_FCF_STATE <= FCF_T0;
else
DMA_ACTIV_NEW <= '0';
NEXT_FCF_STATE <= FCF_IDLE;
end if;
when FCF_T0 =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
nSCSI_DACK <= '1';
DMA_ACTIV_NEW <= DMA_REQ;
WRF_RDE <= DMA_MODUS(8) and DMA_REQ; -- WRITE -> READ FROM FIFO
if DMA_REQ = '0' and DMA_ACTIV = '1' THEN -- spike?
NEXT_FCF_STATE <= FCF_IDLE; -- ja -> zum start
else
NEXT_FCF_STATE <= FCF_T1;
end if;
when FCF_T1 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T2;
when FCF_T2 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T3;
when FCF_T3 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T6;
when FCF_T6 =>
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
RDF_WRE <= not DMA_MODUS(8) and DMA_ACTIV; -- READ -> WRITE IN FIFO
NEXT_FCF_STATE <= FCF_T7;
when FCF_T7 =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
WRF_RDE <= '0';
nSCSI_DACK <= '1';
DMA_ACTIV_NEW <= '0';
if FDC_CS = '1' and DMA_REQ = '0' then
NEXT_FCF_STATE <= FCF_T7;
else
NEXT_FCF_STATE <= FCF_IDLE;
end if;
end case;
end process FCF_DECODER;
I_FDC: WF1772IP_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
CSn => FDCS_In,
RWn => nFDC_WR,
A1 => CA2,
A0 => CA1,
DATA_IN => CD_IN_FDC,
DATA_OUT => CD_OUT_FDC,
-- DATA_EN => CD_EN_FDC,
RDn => nRD_DATA,
TR00n => TRACK00,
IPn => nINDEX,
WPRTn => nWP,
DDEn => '0', -- Fixed to MFM.
HDTYPE => HD_DD_OUT,
MO => MOT_ON,
WG => WR_GATE,
WD => WR_DATA,
STEP => STEP,
DIRC => STEP_DIR,
DRQ => DMA_DRQ_I,
INTRQ => FDINT
);
DMA_DATEN_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C302" else '0'; -- F8604/2
DMA_MODUS_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C303" else '0'; -- F8606/2
WDC_BSL_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C307" else '0'; -- F860E/2
HD_DD_OUT <= HD_DD WHEN ACP_CONF(29) = '0' ELSE WDC_BSL(0);
nFDC_WR <= (not DMA_MODUS(8)) when DMA_ACTIV = '1' else nFB_WR;
CA0 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(0);
CA1 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(1);
CA2 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(2);
FB_AD(23 downto 16) <= "0000" & (not DMA_STATUS(1)) & "0" & WDC_BSL(1) & HD_DD when WDC_BSL_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(31 downto 24) <= "00000000" when DMA_DATEN_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= FDC_OUT when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "00" and nFB_OE = '0' else
SCSI_DOUT when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "01" and nFB_OE = '0' else
DMA_BYT_CNT(16 downto 9) when DMA_DATEN_CS = '1' and DMA_MODUS(4) = '1' and nFB_OE = '0' else "ZZZZZZZZ";
--- WDC BSL REGISTER -------------------------------------------------------
process(MAIN_CLK, nRSTO, WDC_BSL_CS, WDC_BSL, nFB_WR, FB_B0, FB_B1)
begin
if nRSTO = '0' THEN
WDC_BSL <= "00";
elsif rising_edge(MAIN_CLK) and WDC_BSL_CS = '1' and nFB_WR = '0' then
IF FB_B0 = '1' THEN
WDC_BSL(1 DOWNTO 0) <= FB_AD(25 DOWNTO 24);
else
WDC_BSL(1 DOWNTO 0) <= WDC_BSL(1 DOWNTO 0);
end if;
end if;
END PROCESS;
--- DMA MODUS REGISTER -------------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_MODUS_CS, DMA_MODUS, nFB_WR, FB_B0, FB_B1)
begin
if nRSTO = '0' THEN
DMA_MODUS <= x"0000";
elsif rising_edge(MAIN_CLK) and DMA_MODUS_CS = '1' and nFB_WR = '0' then
IF FB_B0 = '1' THEN
DMA_MODUS(15 downto 8) <= FB_AD(31 downto 24);
else
DMA_MODUS(15 downto 8) <= DMA_MODUS(15 downto 8);
end if;
IF FB_B1 = '1' THEN
DMA_MODUS(7 downto 0) <= FB_AD(23 downto 16);
else
DMA_MODUS(7 downto 0) <= DMA_MODUS(7 downto 0);
end if;
else
DMA_MODUS <= DMA_MODUS;
end if;
END PROCESS;
-- BYT COUNTER, SECTOR COUNTER ----------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_DATEN_CS, DMA_BYT_CNT_CS, DMA_BYT_CNT, nFB_WR, FB_B0, FB_B1, DMA_MODUS, CLR_FIFO)
begin
if nRSTO = '0' or CLR_FIFO = '1' THEN
DMA_BYT_CNT <= x"00000000";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and DMA_DATEN_CS = '1' and nFB_WR = '0' and DMA_MODUS(4) = '1' and FB_B1 = '1' then
DMA_BYT_CNT(31 downto 17) <= "000000000000000";
DMA_BYT_CNT(16 downto 9) <= FB_AD(23 downto 16);
DMA_BYT_CNT(8 downto 0) <= "000000000";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and DMA_BYT_CNT_CS = '1' then
DMA_BYT_CNT <= FB_AD;
else
DMA_BYT_CNT <= DMA_BYT_CNT;
end if;
END PROCESS;
--------------------------------------------------------------------
FB_AD(31 downto 16) <= "0000000000000" & DMA_STATUS when DMA_MODUS_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
DMA_STATUS(0) <= '1'; -- DMA OK
DMA_STATUS(1) <= '1' when DMA_BYT_CNT /= 0 and DMA_BYT_CNT(31) = '0' else '0'; -- WENN byts UND NICHT MINUS
DMA_STATUS(2) <= '0' when DMA_DRQ_I = '1' or SCSI_DRQ = '1' else '0';
DMA_DRQQ <= '1' when DMA_STATUS(1) = '1' and DMA_MODUS(8) = '0' and RDF_AZ > 15 and DMA_MODUS(6) = '0' else
'1' when DMA_STATUS(1) = '1' and DMA_MODUS(8) = '1' and WRF_AZ < 512 and DMA_MODUS(6) = '0' else '0';
DMA_DRQ <= '1' when DMA_DRQ_REG = "11" and DMA_MODUS(6) = '0' else '0';
-- DMA REQUEST: SPIKES AUSFILTERN ------------------------------------------
process(FDC_CLK, nRSTO, DMA_DRQ_REG)
begin
if nRSTO = '0' THEN
DMA_DRQ_REG <= "00";
elsif rising_edge(FDC_CLK) then
DMA_DRQ_REG(0) <= DMA_DRQQ;
DMA_DRQ_REG(1) <= DMA_DRQ_REG(0) and DMA_DRQQ;
else
DMA_DRQ_REG <= DMA_DRQ_REG;
end if;
END PROCESS;
-- DMA ADRESSE ------------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_TOP_CS, DMA_TOP, nFB_WR, DMA_ADR_CS)
begin
if nRSTO = '0' THEN
DMA_TOP <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and (DMA_TOP_CS = '1' or DMA_ADR_CS = '1') then
DMA_TOP <= FB_AD(31 downto 24);
else
DMA_TOP <= DMA_TOP;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_HIGH_CS, DMA_HIGH, nFB_WR, DMA_ADR_CS)
begin
if nRSTO = '0' THEN
DMA_HIGH <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and (DMA_HIGH_CS = '1' or DMA_ADR_CS = '1') then
DMA_HIGH <= FB_AD(23 downto 16);
else
DMA_HIGH <= DMA_HIGH;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_MID_CS, DMA_MID, nFB_WR)
begin
DMA_MID <= DMA_MID;
if nRSTO = '0' THEN
DMA_MID <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' then
if DMA_MID_CS = '1' then
DMA_MID <= FB_AD(23 downto 16);
elsif DMA_ADR_CS = '1' then
DMA_MID <= FB_AD(15 downto 8);
end if;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_LOW_CS, DMA_LOW, nFB_WR)
begin
DMA_LOW <= DMA_LOW;
if nRSTO = '0' THEN
DMA_LOW <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' then
if DMA_LOW_CS = '1'then
DMA_LOW <= FB_AD(23 downto 16);
elsif DMA_ADR_CS = '1' then
DMA_LOW <= FB_AD(7 downto 0);
end if;
end if;
END PROCESS;
--------------------------------------------------------------------------------------------
DMA_TOP_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C304" and FB_B0 = '1' else '0'; -- F8608/2
DMA_HIGH_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C304" and FB_B1 = '1' else '0'; -- F8609/2
DMA_MID_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C305" and FB_B1 = '1' else '0'; -- F860B/2
DMA_LOW_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C306" and FB_B1 = '1' else '0'; -- F860D/2
FB_AD(31 downto 24) <= DMA_TOP when DMA_TOP_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_HIGH when DMA_HIGH_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_MID when DMA_MID_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_LOW when DMA_LOW_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
-- DIRECTZUGRIFF
DMA_DIRM_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20100" else '0'; -- F002'0100 WORD
DMA_ADR_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20104" else '0'; -- F002'0104 LONG
DMA_BYT_CNT_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20108" else '0'; -- F002'0108 LONG
FB_AD <= DMA_TOP & DMA_HIGH & DMA_MID & DMA_LOW when DMA_ADR_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= DMA_MODUS when DMA_DIRM_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD <= DMA_BYT_CNT when DMA_BYT_CNT_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
-- DMA RW TOGGLE ------------------------------------------
process(MAIN_CLK, nRSTO, DMA_MODUS_CS, DMA_MODUS, DMA_DIR_OLD)
begin
if nRSTO = '0' THEN
DMA_DIR_OLD <= '0';
elsif rising_edge(MAIN_CLK) and DMA_MODUS_CS = '0' then
DMA_DIR_OLD <= DMA_MODUS(8);
else
DMA_DIR_OLD <= DMA_DIR_OLD;
end if;
END PROCESS;
CLR_FIFO <= DMA_MODUS(8) xor DMA_DIR_OLD;
-- SCSI ----------------------------------------------------------------------------------
I_SCSI: WF5380_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
ADR => CA2 & CA1 & CA0,
DATA_IN => CD_IN_FDC,
DATA_OUT => SCSI_DOUT,
--DATA_EN : out bit;
-- Bus and DMA controls:
CSn => '1', --SCSI_CSn, ABGESCHALTET
RDn => (not nFDC_WR) or (not SCSI_CS),
WRn => nFDC_WR or (not SCSI_CS),
EOPn => '1',
DACKn => nSCSI_DACK,
DRQ => SCSI_DRQ,
INT => SCSI_INT,
-- READY =>
-- SCSI bus:
DB_INn => SCSI_D,
DB_OUTn => DB_OUTn,
DB_EN => DB_EN,
DBP_INn => SCSI_PAR,
DBP_OUTn => DBP_OUTn,
DBP_EN => DBP_EN, -- wenn 1 dann output
RST_INn => nSCSI_RST,
RST_OUTn => RST_OUTn,
RST_EN => RST_EN,
BSY_INn => nSCSI_BUSY,
BSY_OUTn => BSY_OUTn,
BSY_EN => BSY_EN,
SEL_INn => nSCSI_SEL,
SEL_OUTn => SEL_OUTn,
SEL_EN => SEL_EN,
ACK_INn => '1',
ACK_OUTn => nSCSI_ACK,
-- ACK_EN => ACK_EN,
ATN_INn => '1',
ATN_OUTn => nSCSI_ATN,
-- ATN_EN => ATN_EN,
REQ_INn => nSCSI_DRQ,
-- REQ_OUTn => REQ_OUTn,
-- REQ_EN => REQ_EN,
IOn_IN => nSCSI_I_O,
-- IOn_OUT => IOn_OUT,
-- IO_EN => IO_EN,
CDn_IN => nSCSI_C_D,
-- CDn_OUT => CDn_OUT,
-- CD_EN => CD_EN,
MSG_INn => nSCSI_MSG
-- MSG_OUTn => MSG_OUTn,
-- MSG_EN => MSG_EN
);
-- SCSI ACSI ---------------------------------------------------------------
SCSI_D <= DB_OUTn when DB_EN = '1' else "ZZZZZZZZ";
SCSI_DIR <= '1'; --'0' when DB_EN = '1' else '1'; --ABGESCHALTET
SCSI_PAR <= DBP_OUTn when DBP_EN = '1' else 'Z';
nSCSI_RST <= RST_OUTn when RST_EN = '1' else 'Z';
nSCSI_BUSY <= BSY_OUTn when BSY_EN = '1' else 'Z';
nSCSI_SEL <= SEL_OUTn when SEL_EN = '1' else 'Z';
ACSI_DIR <= '0';
ACSI_D <= "ZZZZZZZZ";
nACSI_CS <= '1';
ACSI_A1 <= CA1;
nACSI_RESET <= nRSTO;
nACSI_ACK <= '1';
----------------------------------------------------------------------------
-- ROM-PORT TA KOMMT FROM DEFAULT TA = 16 BUSCYCLEN = 500ns
----------------------------------------------------------------------------
ROM_CS <= '1' when nFB_CS1 = '0' and nFB_WR = '1' and FB_ADR(19 downto 17) = x"5" else '0'; -- FFF A'0000/2'0000
nROM4 <= '0' when ROM_CS = '1' and FB_ADR(16) = '0' else '1';
nROM3 <= '0' when ROM_CS = '1' and FB_ADR(16) = '1' else '1';
----------------------------------------------------------------------------
-- ACIA KEYBOARD
----------------------------------------------------------------------------
I_ACIA_KEYBOARD: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
CS2n => FB_ADR(2),
CS1 => '1',
CS0 => ACIA_CS_I,
E => ACIA_CS_I,
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_OUT => DATA_OUT_ACIA_I,
-- DATA_EN => DATA_EN_ACIA_I,
TXCLK => CLK500k,
RXCLK => CLK500k,
RXDATA => KEYB_RxD,
CTSn => '0',
DCDn => '0',
IRQn => IRQ_KEYBDn,
TXDATA => AMKB_TX
--RTSn => -- Not used.
);
ACIA_CS_I <= '1' when nFB_CS1 = '0'and FB_ADR(19 downto 3) = x"1FF80" else '0'; -- FFC00-FFC07 FFC00/8
KEYB_RxD <= '1' when AMKB_REG(3) = '1' or PIC_AMKB_RX = '0' else '0'; -- TASTATUR DATEN VOM PIC(PS2) OR NORMAL
FB_AD(31 downto 24) <= DATA_OUT_ACIA_I when ACIA_CS_I = '1' and FB_ADR(2) = '0' and nFB_OE = '0' else "ZZZZZZZZ";
-- AMKB_TX: SPIKES AUSFILTERN ------------------------------------------
process(CLK2M, AMKB_RX, AMKB_REG)
begin
if rising_edge(CLK2M) then
IF AMKB_RX = '0' THEN
IF AMKB_REG < 16 THEN
AMKB_REG <= "00000";
ELSE
AMKB_REG <= AMKB_REG - 1;
END IF;
ELSE
IF AMKB_REG > 15 THEN
AMKB_REG <= "11111";
ELSE
AMKB_REG <= AMKB_REG + 1;
END IF;
END IF;
ELSE
AMKB_REG <= AMKB_REG;
end if;
END PROCESS;
----------------------------------------------------------------------------
-- ACIA MIDI
----------------------------------------------------------------------------
I_ACIA_MIDI: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
CS2n => '0',
CS1 => FB_ADR(2),
CS0 => ACIA_CS_I,
E => ACIA_CS_I,
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_OUT => DATA_OUT_ACIA_II,
-- DATA_EN => DATA_EN_ACIA_II,
TXCLK => CLK500k,
RXCLK => CLK500k,
RXDATA => MIDI_IN,
CTSn => '0',
DCDn => '0',
IRQn => IRQ_MIDIn,
TXDATA => MIDI_OUT
--RTSn => -- Not used.
);
MIDI_TLR <= MIDI_OUT;
MIDI_OLR <= MIDI_OUT;
FB_AD(31 downto 24) <= DATA_OUT_ACIA_II when ACIA_CS_I = '1' and FB_ADR(2) = '1' and nFB_OE = '0' else "ZZZZZZZZ";
----------------------------------------------------------------------------
-- MFP
----------------------------------------------------------------------------
I_MFP: WF68901IP_TOP_SOC
port map(
-- System control:
CLK => MAIN_CLK,
RESETn => nRSTO,
-- Asynchronous bus control:
DSn => not LDS,
CSn => not MFP_CS,
RWn => nFB_WR,
DTACKn => DTACK_OUT_MFPn,
-- Data and Adresses:
RS => FB_ADR(5 downto 1),
DATA_IN => FB_AD(23 downto 16),
DATA_OUT => DATA_OUT_MFP,
-- DATA_EN => DATA_EN_MFP,
GPIP_IN(7) => not DMA_DRQ_Q,
GPIP_IN(6) => not RI,
GPIP_IN(5) => DINTn,
GPIP_IN(4) => IRQ_ACIAn,
GPIP_IN(3) => DSP_INT,
GPIP_IN(2) => not CTS,
GPIP_IN(1) => not DCD,
GPIP_IN(0) => LP_BUSY,
-- GPIP_OUT =>, -- Not used; all GPIPs are direction input.
-- GPIP_EN =>, -- Not used; all GPIPs are direction input.
-- Interrupt control:
IACKn => not MFP_INTACK,
IEIn => '0',
-- IEOn =>, -- Not used.
IRQn => nMFP_INT,
-- Timers and timer control:
XTAL1 => CLK2M4576,
TAI => '0',
TBI => nBLANK,
-- TAO =>,
-- TBO =>,
-- TCO =>,
TDO => TDO,
-- Serial I/O control:
RC => TDO,
TC => TDO,
SI => RxD,
SO => TxD
-- SO_EN => MFP_SO_EN
-- DMA control:
-- RRn =>,
-- TRn =>
);
MFP_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 6) = x"3FE8" else '0'; -- FFA00/40
MFP_INTACK <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20000" else '0'; --F002'0000
LDS <= '1' when MFP_CS = '1' or MFP_INTACK = '1' else '0';
FB_AD(23 downto 16) <= DATA_OUT_MFP when MFP_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(31 downto 10) <= "0000000000000000000000" when MFP_INTACK = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZ";
FB_AD(9 downto 2) <= DATA_OUT_MFP when MFP_INTACK = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(1 downto 0) <= "00" when MFP_INTACK = '1' and nFB_OE = '0' else "ZZ";
DINTn <= '0' when IDE_INT = '1' AND ACP_CONF(28) = '1' else
'0' when FDINT = '1' else
'0' when SCSI_INT = '1' AND ACP_CONF(28) = '1' else '1';
-- TASTATUR UND KEYBOARD INTERRUPT: SPIKES AUSFILTERN ------------------------------------------
process(MAIN_CLK,nRSTO,IRQ_ACIAn,IRQ_KEYBDn,IRQ_MIDIn)
begin
if nRSTO = '0' THEN
IRQ_ACIAn <= '1';
elsif rising_edge(MAIN_CLK) then
IRQ_ACIAn <= IRQ_KEYBDn and IRQ_MIDIn;
else
IRQ_ACIAn <= IRQ_ACIAn;
end if;
END PROCESS;
----------------------------------------------------------------------------
-- Sound
----------------------------------------------------------------------------
I_SOUND: WF2149IP_TOP_SOC
port map(
SYS_CLK => MAIN_CLK,
RESETn => nRSTO,
WAV_CLK => CLK2M,
SELn => '1',
BDIR => SNDIR_I,
BC2 => '1',
BC1 => SNDCS_I,
A9n => '0',
A8 => '1',
DA_IN => FB_AD(31 downto 24),
DA_OUT => DA_OUT_X,
IO_A_IN => x"00", -- All port pins are dedicated outputs.
IO_A_OUT(7) => nnIDE_RES,
IO_A_OUT(6) => LP_DIR_X,
IO_A_OUT(5) => LP_STR,
IO_A_OUT(4) => DTR,
IO_A_OUT(3) => RTS,
-- IO_A_OUT(2) => FDD_D1SEL,
IO_A_OUT(1) => DSA_D,
IO_A_OUT(0) => nSDSEL,
-- IO_A_EN =>, -- Not required.
IO_B_IN => LP_D,
IO_B_OUT => LP_D_X,
-- IO_B_EN => IO_B_EN,
OUT_A => YM_QA,
OUT_B => YM_QB,
OUT_C => YM_QC
);
SNDCS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 2) = x"3E200" else '0'; -- 8800-8803 F8800/4
SNDCS_I <= '1' when SNDCS = '1' and FB_ADR (1 downto 1) = "0" else '0';
SNDIR_I <= '1' when SNDCS = '1' and nFB_WR = '0' else '0';
FB_AD(31 downto 24) <= DA_OUT_X when SNDCS_I = '1' and nFB_OE = '0' else "ZZZZZZZZ";
LP_D <= LP_D_X when LP_DIR_X = '0' else "ZZZZZZZZ";
LP_DIR <= LP_DIR_X;
END FalconIO_SDCard_IDE_CF_architecture;

View File

@@ -0,0 +1,971 @@
-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.
-- Copyright (C) 1991-2008 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- Generated by Quartus II Version 8.1 (Build Build 163 10/28/2008)
-- Created on Tue Sep 08 16:24:20 2009
library work;
use work.FalconIO_SDCard_IDE_CF_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
-- Entity Declaration
-- Entity Declaration
ENTITY FalconIO_SDCard_IDE_CF IS
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
PORT
(
CLK33M : IN STD_LOGIC;
MAIN_CLK : IN STD_LOGIC;
CLK2M : IN STD_LOGIC;
CLK500k : IN STD_LOGIC;
nFB_CS1 : IN STD_LOGIC;
FB_SIZE0 : IN STD_LOGIC;
FB_SIZE1 : IN STD_LOGIC;
nFB_BURST : IN STD_LOGIC;
FB_ADR : IN STD_LOGIC_VECTOR(31 downto 0);
LP_BUSY : IN STD_LOGIC;
nACSI_DRQ : IN STD_LOGIC;
nACSI_INT : IN STD_LOGIC;
nSCSI_DRQ : IN STD_LOGIC;
nSCSI_MSG : IN STD_LOGIC;
MIDI_IN : IN STD_LOGIC;
RxD : IN STD_LOGIC;
CTS : IN STD_LOGIC;
RI : IN STD_LOGIC;
DCD : IN STD_LOGIC;
AMKB_RX : IN STD_LOGIC;
PIC_AMKB_RX : IN STD_LOGIC;
IDE_RDY : IN STD_LOGIC;
IDE_INT : IN STD_LOGIC;
WP_CS_CARD : IN STD_LOGIC;
nINDEX : IN STD_LOGIC;
TRACK00 : IN STD_LOGIC;
nRD_DATA : IN STD_LOGIC;
nDCHG : IN STD_LOGIC;
SD_DATA0 : IN STD_LOGIC;
SD_DATA1 : IN STD_LOGIC;
SD_DATA2 : IN STD_LOGIC;
SD_CARD_DEDECT : IN STD_LOGIC;
SD_WP : IN STD_LOGIC;
nDACK0 : IN STD_LOGIC;
nFB_WR : INOUT STD_LOGIC;
WP_CF_CARD : IN STD_LOGIC;
nWP : IN STD_LOGIC;
nFB_CS2 : IN STD_LOGIC;
nRSTO : IN STD_LOGIC;
HD_DD : IN STD_LOGIC;
nSCSI_C_D : IN STD_LOGIC;
nSCSI_I_O : IN STD_LOGIC;
CLK2M4576 : IN STD_LOGIC;
nFB_OE : IN STD_LOGIC;
VSYNC : IN STD_LOGIC;
HSYNC : IN STD_LOGIC;
DSP_INT : IN STD_LOGIC;
nBLANK : IN STD_LOGIC;
FDC_CLK : IN STD_LOGIC;
FB_ALE : IN STD_LOGIC;
ACP_CONF : IN STD_LOGIC_VECTOR(31 downto 24);
nIDE_CS1 : OUT STD_LOGIC;
nIDE_CS0 : OUT STD_LOGIC;
LP_STR : OUT STD_LOGIC;
LP_DIR : OUT STD_LOGIC;
nACSI_ACK : OUT STD_LOGIC;
nACSI_RESET : OUT STD_LOGIC;
nACSI_CS : OUT STD_LOGIC;
ACSI_DIR : OUT STD_LOGIC;
ACSI_A1 : OUT STD_LOGIC;
nSCSI_ACK : OUT STD_LOGIC;
nSCSI_ATN : OUT STD_LOGIC;
SCSI_DIR : OUT STD_LOGIC;
SD_CLK : OUT STD_LOGIC;
YM_QA : OUT STD_LOGIC;
YM_QC : OUT STD_LOGIC;
YM_QB : OUT STD_LOGIC;
nSDSEL : OUT STD_LOGIC;
STEP : OUT STD_LOGIC;
MOT_ON : OUT STD_LOGIC;
nRP_LDS : OUT STD_LOGIC;
nRP_UDS : OUT STD_LOGIC;
nROM4 : OUT STD_LOGIC;
nROM3 : OUT STD_LOGIC;
nCF_CS1 : OUT STD_LOGIC;
nCF_CS0 : OUT STD_LOGIC;
nIDE_RD : INOUT STD_LOGIC;
nIDE_WR : INOUT STD_LOGIC;
AMKB_TX : OUT STD_LOGIC;
IDE_RES : OUT STD_LOGIC;
DTR : OUT STD_LOGIC;
RTS : OUT STD_LOGIC;
TxD : OUT STD_LOGIC;
MIDI_OLR : OUT STD_LOGIC;
MIDI_TLR : OUT STD_LOGIC;
nDREQ0 : OUT STD_LOGIC;
DSA_D : OUT STD_LOGIC;
nMFP_INT : OUT STD_LOGIC;
FALCON_IO_TA : OUT STD_LOGIC;
STEP_DIR : OUT STD_LOGIC;
WR_DATA : OUT STD_LOGIC;
WR_GATE : OUT STD_LOGIC;
DMA_DRQ : OUT STD_LOGIC;
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0);
LP_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
ACSI_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
SCSI_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
SCSI_PAR : INOUT STD_LOGIC;
nSCSI_SEL : INOUT STD_LOGIC;
nSCSI_BUSY : INOUT STD_LOGIC;
nSCSI_RST : INOUT STD_LOGIC;
SD_CD_DATA3 : INOUT STD_LOGIC;
SD_CDM_D1 : INOUT STD_LOGIC
);
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
END FalconIO_SDCard_IDE_CF;
-- Architecture Body
ARCHITECTURE FalconIO_SDCard_IDE_CF_architecture OF FalconIO_SDCard_IDE_CF IS
-- system
signal SYS_CLK : STD_LOGIC;
signal RESETn : STD_LOGIC;
signal FB_B0 : STD_LOGIC; -- UPPER BYT BEI 16BIT BUS
signal FB_B1 : STD_LOGIC; -- LOWER BYT BEI 16BIT BUS
signal BYT : STD_LOGIC; -- WENN BYT -> 1
signal LONG : STD_LOGIC; -- WENN -> 1
-- KEYBOARD MIDI
signal ACIA_CS_I : STD_LOGIC;
signal IRQ_KEYBDn : STD_LOGIC;
signal IRQ_MIDIn : STD_LOGIC;
signal KEYB_RxD : STD_LOGIC;
signal AMKB_REG : STD_LOGIC_VECTOR(4 downto 0);
signal MIDI_OUT : STD_LOGIC;
signal DATA_OUT_ACIA_I : STD_LOGIC_VECTOR(7 downto 0);
signal DATA_OUT_ACIA_II : STD_LOGIC_VECTOR(7 downto 0);
-- MFP
signal MFP_CS : STD_LOGIC;
signal MFP_INTACK : STD_LOGIC;
signal LDS : STD_LOGIC;
signal DTACK_OUT_MFPn : STD_LOGIC;
signal IRQ_ACIAn : STD_LOGIC;
signal DINTn : STD_LOGIC;
signal DATA_OUT_MFP : STD_LOGIC_VECTOR(7 downto 0);
signal TDO : STD_LOGIC;
-- SOUND
signal SNDCS : STD_LOGIC;
signal SNDCS_I : STD_LOGIC;
signal SNDIR_I : STD_LOGIC;
signal LP_DIR_X : STD_LOGIC;
signal DA_OUT_X : STD_LOGIC_VECTOR(7 downto 0);
signal LP_D_X : STD_LOGIC_VECTOR(7 downto 0);
-- DIV
signal SUB_BUS : STD_LOGIC; -- SUB BUS MIT ROM-PORT, CF UND IDE
signal ROM_CS : STD_LOGIC;
-- DMA UND FLOPPY
signal DMA_DATEN_CS : STD_LOGIC;
signal DMA_MODUS_CS : STD_LOGIC;
signal DMA_MODUS : STD_LOGIC_VECTOR(15 downto 0);
signal WDC_BSL_CS : STD_LOGIC;
signal WDC_BSL : STD_LOGIC_VECTOR(1 DOWNTO 0);
signal HD_DD_OUT : STD_LOGIC;
signal FDCS_In : STD_LOGIC;
signal CA0 : STD_LOGIC;
signal CA1 : STD_LOGIC;
signal CA2 : STD_LOGIC;
signal FDINT : STD_LOGIC;
signal FDRQ : STD_LOGIC;
signal CD_OUT_FDC : STD_LOGIC_VECTOR(7 downto 0);
signal CD_IN_FDC : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_TOP_CS : STD_LOGIC;
signal DMA_TOP : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_HIGH_CS : STD_LOGIC;
signal DMA_HIGH : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_MID_CS : STD_LOGIC;
signal DMA_MID : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_LOW_CS : STD_LOGIC;
signal DMA_LOW : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_DIRM_CS : STD_LOGIC;
signal DMA_ADR_CS : STD_LOGIC;
signal DMA_STATUS : STD_LOGIC_VECTOR(2 downto 0);
signal DMA_DIR_OLD : STD_LOGIC;
signal DMA_BYT_CNT_CS : STD_LOGIC;
signal DMA_BYT_CNT : STD_LOGIC_VECTOR(31 downto 0);
signal CLR_FIFO : STD_LOGIC;
signal DMA_DRQ_I : STD_LOGIC;
signal DMA_DRQ_REG : STD_LOGIC_VECTOR(1 downto 0);
signal DMA_DRQQ : STD_LOGIC;
signal DMA_DRQ_Q : STD_LOGIC;
signal RDF_DOUT : STD_LOGIC_VECTOR(31 downto 0);
signal RDF_AZ : STD_LOGIC_VECTOR(9 downto 0);
signal RDF_RDE : STD_LOGIC;
signal RDF_WRE : STD_LOGIC;
signal RDF_DIN : STD_LOGIC_VECTOR(7 downto 0);
signal WRF_DOUT : STD_LOGIC_VECTOR(7 downto 0);
signal WRF_AZ : STD_LOGIC_VECTOR(9 downto 0);
signal WRF_RDE : STD_LOGIC;
signal WRF_WRE : STD_LOGIC;
signal nFDC_WR : STD_LOGIC;
type FCF_STATES is( FCF_IDLE, FCF_T0, FCF_T1, FCF_T2, FCF_T3, FCF_T6, FCF_T7);
signal FCF_STATE : FCF_STATES;
signal NEXT_FCF_STATE : FCF_STATES;
signal DMA_REQ : STD_LOGIC;
signal FDC_CS : STD_LOGIC;
signal FCF_CS : STD_LOGIC;
signal FCF_APH : STD_LOGIC;
signal DMA_AZ_CS : STD_LOGIC;
signal DMA_ACTIV : STD_LOGIC;
signal DMA_ACTIV_NEW : STD_LOGIC;
signal FDC_OUT : STD_LOGIC_VECTOR(7 downto 0);
-- SCSI
signal SCSI_CS : STD_LOGIC;
signal SCSI_CSn : STD_LOGIC;
signal SCSI_DOUT : STD_LOGIC_VECTOR(7 downto 0);
signal nSCSI_DACK : STD_LOGIC;
signal SCSI_DRQ : STD_LOGIC;
signal SCSI_INT : STD_LOGIC;
signal DB_OUTn : STD_LOGIC_VECTOR(7 downto 0);
signal DB_EN : STD_LOGIC;
signal DBP_OUTn : STD_LOGIC;
signal DBP_EN : STD_LOGIC;
signal RST_OUTn : STD_LOGIC;
signal RST_EN : STD_LOGIC;
signal BSY_OUTn : STD_LOGIC;
signal BSY_EN : STD_LOGIC;
signal SEL_OUTn : STD_LOGIC;
signal SEL_EN : STD_LOGIC;
-- IDE
signal nnIDE_RES : STD_LOGIC;
signal IDE_CF_CS : STD_LOGIC;
signal IDE_CF_TA : STD_LOGIC;
signal NEXT_nIDE_RD : STD_LOGIC;
signal NEXT_nIDE_WR : STD_LOGIC;
type CMD_STATES is( IDLE, T1, T6, T7);
signal CMD_STATE : CMD_STATES;
signal NEXT_CMD_STATE : CMD_STATES;
BEGIN
LONG <= '1' when FB_SIZE1 = '0' and FB_SIZE0 = '0' else '0';
BYT <= '1' when FB_SIZE1 = '0' and FB_SIZE0 = '1' else '0';
FB_B0 <= '1' when FB_ADR(0) = '0' or BYT = '0' else '0';
FB_B1 <= '1' when FB_ADR(0) = '1' or BYT = '0' else '0';
FALCON_IO_TA <= '1' when SNDCS = '1' or DTACK_OUT_MFPn = '0' or ACIA_CS_I = '1' or DMA_MODUS_CS ='1'
or DMA_ADR_CS = '1' or DMA_DIRM_CS = '1' or DMA_BYT_CNT_CS = '1' or FCF_CS = '1' or IDE_CF_TA = '1' else '0';
SUB_BUS <= '1' when nFB_WR = '1' and ROM_CS = '1' ELSE
'1' when nFB_WR = '1' and IDE_CF_CS = '1' ELSE
'1' when nFB_WR = '0' and nIDE_WR = '0' ELSE '0';
nRP_UDS <= '0' when SUB_BUS = '1' and FB_B0 = '1' else '1';
nRP_LDS <= '0' when SUB_BUS = '1' and FB_B1 = '1' else '1';
nDREQ0 <= '0';
----------------------------------------------------------------------------
-- SD
----------------------------------------------------------------------------
SD_CLK <= 'Z';
SD_CD_DATA3 <= 'Z';
SD_CDM_D1 <= 'Z';
----------------------------------------------------------------------------
-- IDE
----------------------------------------------------------------------------
CMD_REG: process(nRSTO, MAIN_CLK, CMD_STATE, NEXT_CMD_STATE)
begin
if nRSTO = '0' then
CMD_STATE <= IDLE;
elsif rising_edge(MAIN_CLK) then
CMD_STATE <= NEXT_CMD_STATE; -- go to next
nIDE_RD <= NEXT_nIDE_RD; -- go to next
nIDE_WR <= NEXT_nIDE_WR; -- go to next
else
CMD_STATE <= CMD_STATE; -- halten
nIDE_RD <= nIDE_RD; -- halten
nIDE_WR <= nIDE_WR; -- halten
end if;
end process CMD_REG;
CMD_DECODER: process(CMD_STATE, NEXT_CMD_STATE, NEXT_nIDE_RD, NEXT_nIDE_WR, IDE_RDY, IDE_CF_TA)
begin
case CMD_STATE is
when IDLE =>
IDE_CF_TA <= '0';
if IDE_CF_CS = '1' then
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T1;
else
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= IDLE;
end if;
when T1 =>
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T6;
when T6 =>
IF IDE_RDY = '1' then
IDE_CF_TA <= '1';
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= T7;
else
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T6;
end if;
when T7 =>
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= IDLE;
end case;
end process CMD_DECODER;
IDE_RES <= not nnIDE_RES and nRSTO;
IDE_CF_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 7) = x"0" else '0'; -- FFF0'0000/80
nCF_CS0 <= '0' when ACP_CONF(31) = '0' and FB_ADR(19 downto 5) = x"0" else -- FFFO'0000-FFF0'001F
'0' when ACP_CONF(31) = '1' and FB_ADR(19 downto 5) = x"2" else '1'; -- FFFO'0040-FFF0'005F
nCF_CS1 <= '0' when ACP_CONF(31) = '0' and FB_ADR(19 downto 5) = x"1" else -- FFF0'0020-FFF0'003F
'0' when ACP_CONF(31) = '1' and FB_ADR(19 downto 5) = x"3" else '1'; -- FFFO'0060-FFF0'007F
nIDE_CS0 <= '0' when ACP_CONF(30) = '0' and FB_ADR(19 downto 5) = x"2" else -- FFF0'0040-FFF0'005F
'0' when ACP_CONF(30) = '1' and FB_ADR(19 downto 5) = x"0" else '1'; -- FFFO'0000-FFF0'001F
nIDE_CS1 <= '0' when ACP_CONF(30) = '0' and FB_ADR(19 downto 5) = x"3" else -- FFF0'0060-FFF0'007F
'0' when ACP_CONF(30) = '1' and FB_ADR(19 downto 5) = x"1" else '1'; -- FFFO'0020-FFF0'003F
-----------------------------------------------------------------------------------------------------------------------------------------
-- ACSI, SCSI UND FLOPPY WD1772
-------------------------------------------------------------------------------------------------------------------------------------------
-- daten read fifo
RDF: dcfifo0
port map(
aclr => CLR_FIFO,
data => RDF_DIN,
rdclk => MAIN_CLK,
rdreq => RDF_RDE,
wrclk => FDC_CLK,
wrreq => RDF_WRE,
q => RDF_DOUT,
wrusedw => RDF_AZ
);
FCF_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"0020110" and LONG = '1' else '0'; -- F002'0110 LONG ONLY
FCF_APH <= '1' when FB_ALE = '1' and FB_AD(31 downto 0) = x"F0020110" and LONG = '1' else '0'; -- ADRESSPHASE F0020110 LONG ONLY
RDF_RDE <= '1' when FCF_APH = '1' and nFB_WR = '1' else '0'; -- AKTIVIEREN IN ADRESSPHASE
FB_AD <= RDF_DOUT(7 downto 0) & RDF_DOUT(15 downto 8) & RDF_DOUT(23 downto 16) & RDF_DOUT(31 downto 24) when FCF_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
RDF_DIN <= CD_OUT_FDC when DMA_MODUS(7) = '1' else SCSI_DOUT;
-- daten write fifo
WRF: dcfifo1
port map(
aclr => CLR_FIFO,
data => FB_AD(7 downto 0) & FB_AD(15 downto 8) & FB_AD(23 downto 16) & FB_AD(31 downto 24),
rdclk => FDC_CLK,
rdreq => WRF_RDE,
wrclk => MAIN_CLK,
wrreq => WRF_WRE,
q => WRF_DOUT,
rdusedw => WRF_AZ
);
CD_IN_FDC <= WRF_DOUT when DMA_ACTIV = '1' and DMA_MODUS(8) = '1' else FB_AD(23 downto 16); -- BEI DMA WRITE <-FIFO SONST <-FB
DMA_AZ_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"002010C" else '0'; -- F002'010C LONG
FB_AD <= DMA_DRQ_Q & DMA_DRQ_REG & IDE_INT & FDINT & SCSI_INT & RDF_AZ & "0" & DMA_STATUS & "00" & WRF_AZ when DMA_AZ_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
DMA_DRQ_Q <= '1' when DMA_DRQ_REG = "11" and DMA_MODUS(6) = '0' else '0';
-- FIFO WRITE: GENAU 1 MAIN_CLK -------------------------------------------------------------------------
process(MAIN_CLK, nRSTO, WRF_WRE, nFB_WR, FCF_APH)
begin
if nRSTO = '0' THEN
WRF_WRE <= '0';
elsif rising_edge(MAIN_CLK) then
IF FCF_APH = '1' and nFB_WR = '0' then
WRF_WRE <= '1';
else
WRF_WRE <= '0';
end if;
else
WRF_WRE <= WRF_WRE;
end if;
END PROCESS;
FCF_REG: process(nRSTO, FDC_CLK, FCF_STATE, NEXT_FCF_STATE, DMA_ACTIV)
begin
if nRSTO = '0' then
FCF_STATE <= FCF_IDLE;
DMA_ACTIV <= '0';
elsif rising_edge(FDC_CLK) then
FCF_STATE <= NEXT_FCF_STATE; -- go to next
DMA_ACTIV <= DMA_ACTIV_NEW;
else
FCF_STATE <= FCF_STATE; -- halten
DMA_ACTIV <= DMA_ACTIV;
end if;
end process FCF_REG;
FDC_REG: process(nRSTO, FDC_CLK, FDC_OUT, FDCS_In, CD_OUT_FDC)
begin
if nRSTO = '0' then
FDC_OUT <= x"00";
elsif rising_edge(FDC_CLK) and FDCS_In = '0' then
FDC_OUT <= CD_OUT_FDC; -- set
else
FDC_OUT <= FDC_OUT; -- halten
end if;
end process FDC_REG;
DMA_REQ <= '1' when ((DMA_DRQ_I = '1' and DMA_MODUS(7) = '1') or (SCSI_DRQ = '1' and DMA_MODUS(7) = '0')) and DMA_STATUS(1) = '1' and DMA_MODUS(6) = '0' and CLR_FIFO = '0' else '0';
FDC_CS <= '1' when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "00" and FB_B1 = '1' else '0';
SCSI_CS <= '1' when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "01" and FB_B1 = '1' else '0';
FCF_DECODER: process(FCF_STATE, NEXT_FCF_STATE, DMA_REQ,FDC_CS, RDF_WRE, WRF_RDE, SCSI_DRQ, nSCSI_DACK, DMA_MODUS, DMA_ACTIV, FDCS_In,SCSI_CS, SCSI_CSn)
begin
case FCF_STATE is
when FCF_IDLE =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
WRF_RDE <= '0';
nSCSI_DACK <= '1';
if DMA_REQ = '1' or FDC_CS = '1' or SCSI_CS = '1' then
DMA_ACTIV_NEW <= DMA_REQ;
NEXT_FCF_STATE <= FCF_T0;
else
DMA_ACTIV_NEW <= '0';
NEXT_FCF_STATE <= FCF_IDLE;
end if;
when FCF_T0 =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
nSCSI_DACK <= '1';
DMA_ACTIV_NEW <= DMA_REQ;
WRF_RDE <= DMA_MODUS(8) and DMA_REQ; -- WRITE -> READ FROM FIFO
if DMA_REQ = '0' and DMA_ACTIV = '1' THEN -- spike?
NEXT_FCF_STATE <= FCF_IDLE; -- ja -> zum start
else
NEXT_FCF_STATE <= FCF_T1;
end if;
when FCF_T1 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T2;
when FCF_T2 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T3;
when FCF_T3 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T6;
when FCF_T6 =>
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
RDF_WRE <= not DMA_MODUS(8) and DMA_ACTIV; -- READ -> WRITE IN FIFO
NEXT_FCF_STATE <= FCF_T7;
when FCF_T7 =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
WRF_RDE <= '0';
nSCSI_DACK <= '1';
DMA_ACTIV_NEW <= '0';
if FDC_CS = '1' and DMA_REQ = '0' then
NEXT_FCF_STATE <= FCF_T7;
else
NEXT_FCF_STATE <= FCF_IDLE;
end if;
end case;
end process FCF_DECODER;
I_FDC: WF1772IP_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
CSn => FDCS_In,
RWn => nFDC_WR,
A1 => CA2,
A0 => CA1,
DATA_IN => CD_IN_FDC,
DATA_OUT => CD_OUT_FDC,
-- DATA_EN => CD_EN_FDC,
RDn => nRD_DATA,
TR00n => TRACK00,
IPn => nINDEX,
WPRTn => nWP,
DDEn => '0', -- Fixed to MFM.
HDTYPE => HD_DD_OUT,
MO => MOT_ON,
WG => WR_GATE,
WD => WR_DATA,
STEP => STEP,
DIRC => STEP_DIR,
DRQ => DMA_DRQ_I,
INTRQ => FDINT
);
DMA_DATEN_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C302" else '0'; -- F8604/2
DMA_MODUS_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C303" else '0'; -- F8606/2
WDC_BSL_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C307" else '0'; -- F860E/2
HD_DD_OUT <= HD_DD WHEN ACP_CONF(29) = '0' ELSE WDC_BSL(0);
nFDC_WR <= (not DMA_MODUS(8)) when DMA_ACTIV = '1' else nFB_WR;
CA0 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(0);
CA1 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(1);
CA2 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(2);
FB_AD(23 downto 16) <= "0000" & (not DMA_STATUS(1)) & "0" & WDC_BSL(1) & HD_DD when WDC_BSL_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(31 downto 24) <= "00000000" when DMA_DATEN_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= FDC_OUT when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "00" and nFB_OE = '0' else
SCSI_DOUT when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "01" and nFB_OE = '0' else
DMA_BYT_CNT(16 downto 9) when DMA_DATEN_CS = '1' and DMA_MODUS(4) = '1' and nFB_OE = '0' else "ZZZZZZZZ";
--- WDC BSL REGISTER -------------------------------------------------------
process(MAIN_CLK, nRSTO, WDC_BSL_CS, WDC_BSL, nFB_WR, FB_B0, FB_B1)
begin
if nRSTO = '0' THEN
WDC_BSL <= "00";
elsif rising_edge(MAIN_CLK) and WDC_BSL_CS = '1' and nFB_WR = '0' then
IF FB_B0 = '1' THEN
WDC_BSL(1 DOWNTO 0) <= FB_AD(25 DOWNTO 24);
else
WDC_BSL(1 DOWNTO 0) <= WDC_BSL(1 DOWNTO 0);
end if;
end if;
END PROCESS;
--- DMA MODUS REGISTER -------------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_MODUS_CS, DMA_MODUS, nFB_WR, FB_B0, FB_B1)
begin
if nRSTO = '0' THEN
DMA_MODUS <= x"0000";
elsif rising_edge(MAIN_CLK) and DMA_MODUS_CS = '1' and nFB_WR = '0' then
IF FB_B0 = '1' THEN
DMA_MODUS(15 downto 8) <= FB_AD(31 downto 24);
else
DMA_MODUS(15 downto 8) <= DMA_MODUS(15 downto 8);
end if;
IF FB_B1 = '1' THEN
DMA_MODUS(7 downto 0) <= FB_AD(23 downto 16);
else
DMA_MODUS(7 downto 0) <= DMA_MODUS(7 downto 0);
end if;
else
DMA_MODUS <= DMA_MODUS;
end if;
END PROCESS;
-- BYT COUNTER, SECTOR COUNTER ----------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_DATEN_CS, DMA_BYT_CNT_CS, DMA_BYT_CNT, nFB_WR, FB_B0, FB_B1, DMA_MODUS, CLR_FIFO)
begin
if nRSTO = '0' or CLR_FIFO = '1' THEN
DMA_BYT_CNT <= x"00000000";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and DMA_DATEN_CS = '1' and nFB_WR = '0' and DMA_MODUS(4) = '1' and FB_B1 = '1' then
DMA_BYT_CNT(31 downto 17) <= "000000000000000";
DMA_BYT_CNT(16 downto 9) <= FB_AD(23 downto 16);
DMA_BYT_CNT(8 downto 0) <= "000000000";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and DMA_BYT_CNT_CS = '1' then
DMA_BYT_CNT <= FB_AD;
else
DMA_BYT_CNT <= DMA_BYT_CNT;
end if;
END PROCESS;
--------------------------------------------------------------------
FB_AD(31 downto 16) <= "0000000000000" & DMA_STATUS when DMA_MODUS_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
DMA_STATUS(0) <= '1'; -- DMA OK
DMA_STATUS(1) <= '1' when DMA_BYT_CNT /= 0 and DMA_BYT_CNT(31) = '0' else '0'; -- WENN byts UND NICHT MINUS
DMA_STATUS(2) <= '0' when DMA_DRQ_I = '1' or SCSI_DRQ = '1' else '0';
DMA_DRQQ <= '1' when DMA_STATUS(1) = '1' and DMA_MODUS(8) = '0' and RDF_AZ > 15 and DMA_MODUS(6) = '0' else
'1' when DMA_STATUS(1) = '1' and DMA_MODUS(8) = '1' and WRF_AZ < 512 and DMA_MODUS(6) = '0' else '0';
DMA_DRQ <= '1' when DMA_DRQ_REG = "11" and DMA_MODUS(6) = '0' else '0';
-- DMA REQUEST: SPIKES AUSFILTERN ------------------------------------------
process(FDC_CLK, nRSTO, DMA_DRQ_REG)
begin
if nRSTO = '0' THEN
DMA_DRQ_REG <= "00";
elsif rising_edge(FDC_CLK) then
DMA_DRQ_REG(0) <= DMA_DRQQ;
DMA_DRQ_REG(1) <= DMA_DRQ_REG(0) and DMA_DRQQ;
else
DMA_DRQ_REG <= DMA_DRQ_REG;
end if;
END PROCESS;
-- DMA ADRESSE ------------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_TOP_CS, DMA_TOP, nFB_WR, DMA_ADR_CS)
begin
if nRSTO = '0' THEN
DMA_TOP <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and (DMA_TOP_CS = '1' or DMA_ADR_CS = '1') then
DMA_TOP <= FB_AD(31 downto 24);
else
DMA_TOP <= DMA_TOP;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_HIGH_CS, DMA_HIGH, nFB_WR, DMA_ADR_CS)
begin
if nRSTO = '0' THEN
DMA_HIGH <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and (DMA_HIGH_CS = '1' or DMA_ADR_CS = '1') then
DMA_HIGH <= FB_AD(23 downto 16);
else
DMA_HIGH <= DMA_HIGH;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_MID_CS, DMA_MID, nFB_WR)
begin
DMA_MID <= DMA_MID;
if nRSTO = '0' THEN
DMA_MID <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' then
if DMA_MID_CS = '1' then
DMA_MID <= FB_AD(23 downto 16);
elsif DMA_ADR_CS = '1' then
DMA_MID <= FB_AD(15 downto 8);
end if;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_LOW_CS, DMA_LOW, nFB_WR)
begin
DMA_LOW <= DMA_LOW;
if nRSTO = '0' THEN
DMA_LOW <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' then
if DMA_LOW_CS = '1'then
DMA_LOW <= FB_AD(23 downto 16);
elsif DMA_ADR_CS = '1' then
DMA_LOW <= FB_AD(7 downto 0);
end if;
end if;
END PROCESS;
--------------------------------------------------------------------------------------------
DMA_TOP_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C304" and FB_B0 = '1' else '0'; -- F8608/2
DMA_HIGH_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C304" and FB_B1 = '1' else '0'; -- F8609/2
DMA_MID_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C305" and FB_B1 = '1' else '0'; -- F860B/2
DMA_LOW_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C306" and FB_B1 = '1' else '0'; -- F860D/2
FB_AD(31 downto 24) <= DMA_TOP when DMA_TOP_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_HIGH when DMA_HIGH_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_MID when DMA_MID_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_LOW when DMA_LOW_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
-- DIRECTZUGRIFF
DMA_DIRM_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20100" else '0'; -- F002'0100 WORD
DMA_ADR_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20104" else '0'; -- F002'0104 LONG
DMA_BYT_CNT_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20108" else '0'; -- F002'0108 LONG
FB_AD <= DMA_TOP & DMA_HIGH & DMA_MID & DMA_LOW when DMA_ADR_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= DMA_MODUS when DMA_DIRM_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD <= DMA_BYT_CNT when DMA_BYT_CNT_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
-- DMA RW TOGGLE ------------------------------------------
process(MAIN_CLK, nRSTO, DMA_MODUS_CS, DMA_MODUS, DMA_DIR_OLD)
begin
if nRSTO = '0' THEN
DMA_DIR_OLD <= '0';
elsif rising_edge(MAIN_CLK) and DMA_MODUS_CS = '0' then
DMA_DIR_OLD <= DMA_MODUS(8);
else
DMA_DIR_OLD <= DMA_DIR_OLD;
end if;
END PROCESS;
CLR_FIFO <= DMA_MODUS(8) xor DMA_DIR_OLD;
-- SCSI ----------------------------------------------------------------------------------
I_SCSI: WF5380_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
ADR => CA2 & CA1 & CA0,
DATA_IN => CD_IN_FDC,
DATA_OUT => SCSI_DOUT,
--DATA_EN : out bit;
-- Bus and DMA controls:
CSn => '1', --SCSI_CSn, ABGESCHALTET
RDn => (not nFDC_WR) or (not SCSI_CS),
WRn => nFDC_WR or (not SCSI_CS),
EOPn => '1',
DACKn => nSCSI_DACK,
DRQ => SCSI_DRQ,
INT => SCSI_INT,
-- READY =>
-- SCSI bus:
DB_INn => SCSI_D,
DB_OUTn => DB_OUTn,
DB_EN => DB_EN,
DBP_INn => SCSI_PAR,
DBP_OUTn => DBP_OUTn,
DBP_EN => DBP_EN, -- wenn 1 dann output
RST_INn => nSCSI_RST,
RST_OUTn => RST_OUTn,
RST_EN => RST_EN,
BSY_INn => nSCSI_BUSY,
BSY_OUTn => BSY_OUTn,
BSY_EN => BSY_EN,
SEL_INn => nSCSI_SEL,
SEL_OUTn => SEL_OUTn,
SEL_EN => SEL_EN,
ACK_INn => '1',
ACK_OUTn => nSCSI_ACK,
-- ACK_EN => ACK_EN,
ATN_INn => '1',
ATN_OUTn => nSCSI_ATN,
-- ATN_EN => ATN_EN,
REQ_INn => nSCSI_DRQ,
-- REQ_OUTn => REQ_OUTn,
-- REQ_EN => REQ_EN,
IOn_IN => nSCSI_I_O,
-- IOn_OUT => IOn_OUT,
-- IO_EN => IO_EN,
CDn_IN => nSCSI_C_D,
-- CDn_OUT => CDn_OUT,
-- CD_EN => CD_EN,
MSG_INn => nSCSI_MSG
-- MSG_OUTn => MSG_OUTn,
-- MSG_EN => MSG_EN
);
-- SCSI ACSI ---------------------------------------------------------------
SCSI_D <= DB_OUTn when DB_EN = '1' else "ZZZZZZZZ";
SCSI_DIR <= '1'; --'0' when DB_EN = '1' else '1'; --ABGESCHALTET
SCSI_PAR <= DBP_OUTn when DBP_EN = '1' else 'Z';
nSCSI_RST <= RST_OUTn when RST_EN = '1' else 'Z';
nSCSI_BUSY <= BSY_OUTn when BSY_EN = '1' else 'Z';
nSCSI_SEL <= SEL_OUTn when SEL_EN = '1' else 'Z';
ACSI_DIR <= '0';
ACSI_D <= "ZZZZZZZZ";
nACSI_CS <= '1';
ACSI_A1 <= CA1;
nACSI_RESET <= nRSTO;
nACSI_ACK <= '1';
----------------------------------------------------------------------------
-- ROM-PORT TA KOMMT FROM DEFAULT TA = 16 BUSCYCLEN = 500ns
----------------------------------------------------------------------------
ROM_CS <= '1' when nFB_CS1 = '0' and nFB_WR = '1' and FB_ADR(19 downto 17) = x"5" else '0'; -- FFF A'0000/2'0000
nROM4 <= '0' when ROM_CS = '1' and FB_ADR(16) = '0' else '1';
nROM3 <= '0' when ROM_CS = '1' and FB_ADR(16) = '1' else '1';
----------------------------------------------------------------------------
-- ACIA KEYBOARD
----------------------------------------------------------------------------
I_ACIA_KEYBOARD: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
CS2n => FB_ADR(2),
CS1 => '1',
CS0 => ACIA_CS_I,
E => ACIA_CS_I,
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_OUT => DATA_OUT_ACIA_I,
-- DATA_EN => DATA_EN_ACIA_I,
TXCLK => CLK500k,
RXCLK => CLK500k,
RXDATA => KEYB_RxD,
CTSn => '0',
DCDn => '0',
IRQn => IRQ_KEYBDn,
TXDATA => AMKB_TX
--RTSn => -- Not used.
);
ACIA_CS_I <= '1' when nFB_CS1 = '0'and FB_ADR(19 downto 3) = x"1FF80" else '0'; -- FFC00-FFC07 FFC00/8
KEYB_RxD <= '1' when AMKB_REG(3) = '1' or PIC_AMKB_RX = '0' else '0'; -- TASTATUR DATEN VOM PIC(PS2) OR NORMAL
FB_AD(31 downto 24) <= DATA_OUT_ACIA_I when ACIA_CS_I = '1' and FB_ADR(2) = '0' and nFB_OE = '0' else "ZZZZZZZZ";
-- AMKB_TX: SPIKES AUSFILTERN ------------------------------------------
process(CLK2M, AMKB_RX, AMKB_REG)
begin
if rising_edge(CLK2M) then
IF AMKB_RX = '0' THEN
IF AMKB_REG < 16 THEN
AMKB_REG <= "00000";
ELSE
AMKB_REG <= AMKB_REG - 1;
END IF;
ELSE
IF AMKB_REG > 15 THEN
AMKB_REG <= "11111";
ELSE
AMKB_REG <= AMKB_REG + 1;
END IF;
END IF;
ELSE
AMKB_REG <= AMKB_REG;
end if;
END PROCESS;
----------------------------------------------------------------------------
-- ACIA MIDI
----------------------------------------------------------------------------
I_ACIA_MIDI: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
CS2n => '0',
CS1 => FB_ADR(2),
CS0 => ACIA_CS_I,
E => ACIA_CS_I,
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_OUT => DATA_OUT_ACIA_II,
-- DATA_EN => DATA_EN_ACIA_II,
TXCLK => CLK500k,
RXCLK => CLK500k,
RXDATA => MIDI_IN,
CTSn => '0',
DCDn => '0',
IRQn => IRQ_MIDIn,
TXDATA => MIDI_OUT
--RTSn => -- Not used.
);
MIDI_TLR <= MIDI_OUT;
MIDI_OLR <= MIDI_OUT;
FB_AD(31 downto 24) <= DATA_OUT_ACIA_II when ACIA_CS_I = '1' and FB_ADR(2) = '1' and nFB_OE = '0' else "ZZZZZZZZ";
----------------------------------------------------------------------------
-- MFP
----------------------------------------------------------------------------
I_MFP: WF68901IP_TOP_SOC
port map(
-- System control:
CLK => MAIN_CLK,
RESETn => nRSTO,
-- Asynchronous bus control:
DSn => not LDS,
CSn => not MFP_CS,
RWn => nFB_WR,
DTACKn => DTACK_OUT_MFPn,
-- Data and Adresses:
RS => FB_ADR(5 downto 1),
DATA_IN => FB_AD(23 downto 16),
DATA_OUT => DATA_OUT_MFP,
-- DATA_EN => DATA_EN_MFP,
GPIP_IN(7) => not DMA_DRQ_Q,
GPIP_IN(6) => not RI,
GPIP_IN(5) => DINTn,
GPIP_IN(4) => IRQ_ACIAn,
GPIP_IN(3) => DSP_INT,
GPIP_IN(2) => not CTS,
GPIP_IN(1) => not DCD,
GPIP_IN(0) => LP_BUSY,
-- GPIP_OUT =>, -- Not used; all GPIPs are direction input.
-- GPIP_EN =>, -- Not used; all GPIPs are direction input.
-- Interrupt control:
IACKn => not MFP_INTACK,
IEIn => '0',
-- IEOn =>, -- Not used.
IRQn => nMFP_INT,
-- Timers and timer control:
XTAL1 => CLK2M4576,
TAI => '0',
TBI => nBLANK,
-- TAO =>,
-- TBO =>,
-- TCO =>,
TDO => TDO,
-- Serial I/O control:
RC => TDO,
TC => TDO,
SI => RxD,
SO => TxD
-- SO_EN => MFP_SO_EN
-- DMA control:
-- RRn =>,
-- TRn =>
);
MFP_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 6) = x"3FE8" else '0'; -- FFA00/40
MFP_INTACK <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20000" else '0'; --F002'0000
LDS <= '1' when MFP_CS = '1' or MFP_INTACK = '1' else '0';
FB_AD(23 downto 16) <= DATA_OUT_MFP when MFP_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(31 downto 10) <= "0000000000000000000000" when MFP_INTACK = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZ";
FB_AD(9 downto 2) <= DATA_OUT_MFP when MFP_INTACK = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(1 downto 0) <= "00" when MFP_INTACK = '1' and nFB_OE = '0' else "ZZ";
DINTn <= '0' when IDE_INT = '1' AND ACP_CONFIG[28] = '1' else
'0' when FDINT = '1' else
'0' when SCSI_INT = '1' AND ACP_CONFIG[28] = '1' else '1';
-- TASTATUR UND KEYBOARD INTERRUPT: SPIKES AUSFILTERN ------------------------------------------
process(MAIN_CLK,nRSTO,IRQ_ACIAn,IRQ_KEYBDn,IRQ_MIDIn)
begin
if nRSTO = '0' THEN
IRQ_ACIAn <= '1';
elsif rising_edge(MAIN_CLK) then
IRQ_ACIAn <= IRQ_KEYBDn and IRQ_MIDIn;
else
IRQ_ACIAn <= IRQ_ACIAn;
end if;
END PROCESS;
----------------------------------------------------------------------------
-- Sound
----------------------------------------------------------------------------
I_SOUND: WF2149IP_TOP_SOC
port map(
SYS_CLK => MAIN_CLK,
RESETn => nRSTO,
WAV_CLK => CLK2M,
SELn => '1',
BDIR => SNDIR_I,
BC2 => '1',
BC1 => SNDCS_I,
A9n => '0',
A8 => '1',
DA_IN => FB_AD(31 downto 24),
DA_OUT => DA_OUT_X,
IO_A_IN => x"00", -- All port pins are dedicated outputs.
IO_A_OUT(7) => nnIDE_RES,
IO_A_OUT(6) => LP_DIR_X,
IO_A_OUT(5) => LP_STR,
IO_A_OUT(4) => DTR,
IO_A_OUT(3) => RTS,
-- IO_A_OUT(2) => FDD_D1SEL,
IO_A_OUT(1) => DSA_D,
IO_A_OUT(0) => nSDSEL,
-- IO_A_EN =>, -- Not required.
IO_B_IN => LP_D,
IO_B_OUT => LP_D_X,
-- IO_B_EN => IO_B_EN,
OUT_A => YM_QA,
OUT_B => YM_QB,
OUT_C => YM_QC
);
SNDCS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 2) = x"3E200" else '0'; -- 8800-8803 F8800/4
SNDCS_I <= '1' when SNDCS = '1' and FB_ADR (1 downto 1) = "0" else '0';
SNDIR_I <= '1' when SNDCS = '1' and nFB_WR = '0' else '0';
FB_AD(31 downto 24) <= DA_OUT_X when SNDCS_I = '1' and nFB_OE = '0' else "ZZZZZZZZ";
LP_D <= LP_D_X when LP_DIR_X = '0' else "ZZZZZZZZ";
LP_DIR <= LP_DIR_X;
END FalconIO_SDCard_IDE_CF_architecture;

View File

@@ -0,0 +1,406 @@
----------------------------------------------------------------------
---- ----
---- Atari Coldfire IP Core ----
---- ----
---- This file is part of the Atari Coldfire project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- ----
---- ----
---- ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
-- 1.0 Initial Release, 20090925.
--
library ieee;
use ieee.std_logic_1164.all;
package FalconIO_SDCard_IDE_CF_PKG is
component WF25915IP_TOP_V1_SOC -- GLUE.
port (
-- Clock system:
GL_CLK : in std_logic; -- Originally 8MHz.
GL_CLK_016 : in std_logic; -- One sixteenth of GL_CLK.
-- Core address select:
GL_ROMSEL_FC_E0n : in std_logic;
EN_RAM_14MB : in std_logic;
-- Adress decoder outputs:
GL_ROM_6n : out std_logic; -- STE.
GL_ROM_5n : out std_logic; -- STE.
GL_ROM_4n : out std_logic; -- ST.
GL_ROM_3n : out std_logic; -- ST.
GL_ROM_2n : out std_logic;
GL_ROM_1n : out std_logic;
GL_ROM_0n : out std_logic;
GL_ACIACS : out std_logic;
GL_MFPCSn : out std_logic;
GL_SNDCSn : out std_logic;
GL_FCSn : out std_logic;
GL_STE_SNDCS : out std_logic; -- STE: Sound chip select.
GL_STE_SNDIR : out std_logic; -- STE: Data flow direction control.
GL_STE_RTCCSn : out std_logic; --STE only.
GL_STE_RTC_WRn : out std_logic; --STE only.
GL_STE_RTC_RDn : out std_logic; --STE only.
-- 6800 peripheral control,
GL_VPAn : out std_logic;
GL_VMAn : in std_logic;
GL_DMA_SYNC : in std_logic;
GL_DEVn : out std_logic;
GL_RAMn : out std_logic;
GL_DMAn : out std_logic;
-- Interrupt system:
-- Comment out GL_AVECn for CPUs which do not provide the VMAn signal.
GL_AVECn : out std_logic;
GL_STE_FDINT : in std_logic; -- Floppy disk interrupt; STE only.
GL_STE_HDINTn : in std_logic; -- Hard disk interrupt; STE only.
GL_MFPINTn : in std_logic; -- ST.
GL_STE_EINT3n : in std_logic; --STE only.
GL_STE_EINT5n : in std_logic; --STE only.
GL_STE_EINT7n : in std_logic; --STE only.
GL_STE_DINTn : out std_logic; -- Disk interrupt (floppy or hard disk); STE only.
GL_IACKn : out std_logic; -- ST.
GL_STE_IPL2n : out std_logic; --STE only.
GL_STE_IPL1n : out std_logic; --STE only.
GL_STE_IPL0n : out std_logic; --STE only.
-- Video timing:
GL_BLANKn : out std_logic;
GL_DE : out std_logic;
GL_MULTISYNC : in std_logic_vector(3 downto 2);
GL_VIDEO_HIMODE : out std_logic;
GL_HSYNC_INn : in std_logic;
GL_HSYNC_OUTn : out std_logic;
GL_VSYNC_INn : in std_logic;
GL_VSYNC_OUTn : out std_logic;
GL_SYNC_OUT_EN : out std_logic;
-- Bus arstd_logicration control:
GL_RDY_INn : in std_logic;
GL_RDY_OUTn : out std_logic;
GL_BRn : out std_logic;
GL_BGIn : in std_logic;
GL_BGOn : out std_logic;
GL_BGACK_INn : in std_logic;
GL_BGACK_OUTn : out std_logic;
-- Adress and data bus:
GL_ADDRESS : in std_logic_vector(23 downto 1);
-- ST: put the data bus to 1 downto 0.
-- STE: put the data out bus to 15 downto 0.
GL_DATA_IN : in std_logic_vector(7 downto 0);
GL_DATA_OUT : out std_logic_vector(15 downto 0);
GL_DATA_EN : out std_logic;
-- Asynchronous bus control:
GL_RWn_IN : in std_logic;
GL_RWn_OUT : out std_logic;
GL_AS_INn : in std_logic;
GL_AS_OUTn : out std_logic;
GL_UDS_INn : in std_logic;
GL_UDS_OUTn : out std_logic;
GL_LDS_INn : in std_logic;
GL_LDS_OUTn : out std_logic;
GL_DTACK_INn : in std_logic;
GL_DTACK_OUTn : out std_logic;
GL_CTRL_EN : out std_logic;
-- System control:
GL_RESETn : in std_logic;
GL_BERRn : out std_logic;
-- Processor function codes:
GL_FC : in std_logic_vector(2 downto 0);
-- STE enhancements:
GL_STE_FDDS : out std_logic; -- Floppy type select (HD or DD).
GL_STE_FCCLK : out std_logic; -- Floppy controller clock select.
GL_STE_JOY_RHn : out std_logic; -- Read only FF9202 high byte.
GL_STE_JOY_RLn : out std_logic; -- Read only FF9202 low byte.
GL_STE_JOY_WL : out std_logic; -- Write only FF9202 low byte.
GL_STE_JOY_WEn : out std_logic; -- Write only FF9202 output enable.
GL_STE_BUTTONn : out std_logic; -- Read only FF9000 low byte.
GL_STE_PAD0Xn : in std_logic; -- Counter input for the Paddle 0X.
GL_STE_PAD0Yn : in std_logic; -- Counter input for the Paddle 0Y.
GL_STE_PAD1Xn : in std_logic; -- Counter input for the Paddle 1X.
GL_STE_PAD1Yn : in std_logic; -- Counter input for the Paddle 1Y.
GL_STE_PADRSTn : out std_logic; -- Paddle monoflops reset.
GL_STE_PENn : in std_logic; -- Input of the light pen.
GL_STE_SCCn : out std_logic; -- Select signal for the STE or TT SCC chip.
GL_STE_CPROGn : out std_logic -- Select signal for the STE's cache processor.
);
end component WF25915IP_TOP_V1_SOC;
component WF5380_TOP_SOC
port (
CLK : in std_logic;
RESETn : in std_logic;
ADR : in std_logic_vector(2 downto 0);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
CSn : in std_logic;
RDn : in std_logic;
WRn : in std_logic;
EOPn : in std_logic;
DACKn : in std_logic;
DRQ : out std_logic;
INT : out std_logic;
READY : out std_logic;
DB_INn : in std_logic_vector(7 downto 0);
DB_OUTn : out std_logic_vector(7 downto 0);
DB_EN : out std_logic;
DBP_INn : in std_logic;
DBP_OUTn : out std_logic;
DBP_EN : out std_logic;
RST_INn : in std_logic;
RST_OUTn : out std_logic;
RST_EN : out std_logic;
BSY_INn : in std_logic;
BSY_OUTn : out std_logic;
BSY_EN : out std_logic;
SEL_INn : in std_logic;
SEL_OUTn : out std_logic;
SEL_EN : out std_logic;
ACK_INn : in std_logic;
ACK_OUTn : out std_logic;
ACK_EN : out std_logic;
ATN_INn : in std_logic;
ATN_OUTn : out std_logic;
ATN_EN : out std_logic;
REQ_INn : in std_logic;
REQ_OUTn : out std_logic;
REQ_EN : out std_logic;
IOn_IN : in std_logic;
IOn_OUT : out std_logic;
IO_EN : out std_logic;
CDn_IN : in std_logic;
CDn_OUT : out std_logic;
CD_EN : out std_logic;
MSG_INn : in std_logic;
MSG_OUTn : out std_logic;
MSG_EN : out std_logic
);
end component WF5380_TOP_SOC;
component WF1772IP_TOP_SOC -- FDC.
port (
CLK : in std_logic; -- 16MHz clock!
RESETn : in std_logic;
CSn : in std_logic;
RWn : in std_logic;
A1, A0 : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
RDn : in std_logic;
TR00n : in std_logic;
IPn : in std_logic;
WPRTn : in std_logic;
DDEn : in std_logic;
HDTYPE : in std_logic; -- '0' = DD disks, '1' = HD disks.
MO : out std_logic;
WG : out std_logic;
WD : out std_logic;
STEP : out std_logic;
DIRC : out std_logic;
DRQ : out std_logic;
INTRQ : out std_logic
);
end component WF1772IP_TOP_SOC;
component WF68901IP_TOP_SOC -- MFP.
port ( -- System control:
CLK : in std_logic;
RESETn : in std_logic;
-- Asynchronous bus control:
DSn : in std_logic;
CSn : in std_logic;
RWn : in std_logic;
DTACKn : out std_logic;
-- Data and Adresses:
RS : in std_logic_vector(5 downto 1);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
GPIP_IN : in std_logic_vector(7 downto 0);
GPIP_OUT : out std_logic_vector(7 downto 0);
GPIP_EN : out std_logic_vector(7 downto 0);
-- Interrupt control:
IACKn : in std_logic;
IEIn : in std_logic;
IEOn : out std_logic;
IRQn : out std_logic;
-- Timers and timer control:
XTAL1 : in std_logic; -- Use an oszillator instead of a quartz.
TAI : in std_logic;
TBI : in std_logic;
TAO : out std_logic;
TBO : out std_logic;
TCO : out std_logic;
TDO : out std_logic;
-- Serial I/O control:
RC : in std_logic;
TC : in std_logic;
SI : in std_logic;
SO : out std_logic;
SO_EN : out std_logic;
-- DMA control:
RRn : out std_logic;
TRn : out std_logic
);
end component WF68901IP_TOP_SOC;
component WF2149IP_TOP_SOC -- Sound.
port(
SYS_CLK : in std_logic; -- Read the inforation in the header!
RESETn : in std_logic;
WAV_CLK : in std_logic; -- Read the inforation in the header!
SELn : in std_logic;
BDIR : in std_logic;
BC2, BC1 : in std_logic;
A9n, A8 : in std_logic;
DA_IN : in std_logic_vector(7 downto 0);
DA_OUT : out std_logic_vector(7 downto 0);
DA_EN : out std_logic;
IO_A_IN : in std_logic_vector(7 downto 0);
IO_A_OUT : out std_logic_vector(7 downto 0);
IO_A_EN : out std_logic;
IO_B_IN : in std_logic_vector(7 downto 0);
IO_B_OUT : out std_logic_vector(7 downto 0);
IO_B_EN : out std_logic;
OUT_A : out std_logic; -- Analog (PWM) outputs.
OUT_B : out std_logic;
OUT_C : out std_logic
);
end component WF2149IP_TOP_SOC;
component WF6850IP_TOP_SOC -- ACIA.
port (
CLK : in std_logic;
RESETn : in std_logic;
CS2n, CS1, CS0 : in std_logic;
E : in std_logic;
RWn : in std_logic;
RS : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
TXCLK : in std_logic;
RXCLK : in std_logic;
RXDATA : in std_logic;
CTSn : in std_logic;
DCDn : in std_logic;
IRQn : out std_logic;
TXDATA : out std_logic;
RTSn : out std_logic
);
end component WF6850IP_TOP_SOC;
component WF_SD_CARD
port (
RESETn : in std_logic;
CLK : in std_logic;
ACSI_A1 : in std_logic;
ACSI_CSn : in std_logic;
ACSI_ACKn : in std_logic;
ACSI_INTn : out std_logic;
ACSI_DRQn : out std_logic;
ACSI_D_IN : in std_logic_vector(7 downto 0);
ACSI_D_OUT : out std_logic_vector(7 downto 0);
ACSI_D_EN : out std_logic;
MC_DO : in std_logic;
MC_PIO_DMAn : in std_logic;
MC_RWn : in std_logic;
MC_CLR_CMD : in std_logic;
MC_DONE : out std_logic;
MC_GOT_CMD : out std_logic;
MC_D_IN : in std_logic_vector(7 downto 0);
MC_D_OUT : out std_logic_vector(7 downto 0);
MC_D_EN : out std_logic
);
end component WF_SD_CARD;
component dcfifo0
PORT (
aclr : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
end component dcfifo0;
component dcfifo1
PORT (
aclr : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
rdusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
end component;
end FalconIO_SDCard_IDE_CF_PKG;

View File

@@ -0,0 +1,406 @@
----------------------------------------------------------------------
---- ----
---- Atari Coldfire IP Core ----
---- ----
---- This file is part of the Atari Coldfire project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- ----
---- ----
---- ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
-- 1.0 Initial Release, 20090925.
--
library ieee;
use ieee.std_logic_1164.all;
package FalconIO_SDCard_IDE_CF_PKG is
component WF25915IP_TOP_V1_SOC -- GLUE.
port (
-- Clock system:
GL_CLK : in std_logic; -- Originally 8MHz.
GL_CLK_016 : in std_logic; -- One sixteenth of GL_CLK.
-- Core address select:
GL_ROMSEL_FC_E0n : in std_logic;
EN_RAM_14MB : in std_logic;
-- Adress decoder outputs:
GL_ROM_6n : out std_logic; -- STE.
GL_ROM_5n : out std_logic; -- STE.
GL_ROM_4n : out std_logic; -- ST.
GL_ROM_3n : out std_logic; -- ST.
GL_ROM_2n : out std_logic;
GL_ROM_1n : out std_logic;
GL_ROM_0n : out std_logic;
GL_ACIACS : out std_logic;
GL_MFPCSn : out std_logic;
GL_SNDCSn : out std_logic;
GL_FCSn : out std_logic;
GL_STE_SNDCS : out std_logic; -- STE: Sound chip select.
GL_STE_SNDIR : out std_logic; -- STE: Data flow direction control.
GL_STE_RTCCSn : out std_logic; --STE only.
GL_STE_RTC_WRn : out std_logic; --STE only.
GL_STE_RTC_RDn : out std_logic; --STE only.
-- 6800 peripheral control,
GL_VPAn : out std_logic;
GL_VMAn : in std_logic;
GL_DMA_SYNC : in std_logic;
GL_DEVn : out std_logic;
GL_RAMn : out std_logic;
GL_DMAn : out std_logic;
-- Interrupt system:
-- Comment out GL_AVECn for CPUs which do not provide the VMAn signal.
GL_AVECn : out std_logic;
GL_STE_FDINT : in std_logic; -- Floppy disk interrupt; STE only.
GL_STE_HDINTn : in std_logic; -- Hard disk interrupt; STE only.
GL_MFPINTn : in std_logic; -- ST.
GL_STE_EINT3n : in std_logic; --STE only.
GL_STE_EINT5n : in std_logic; --STE only.
GL_STE_EINT7n : in std_logic; --STE only.
GL_STE_DINTn : out std_logic; -- Disk interrupt (floppy or hard disk); STE only.
GL_IACKn : out std_logic; -- ST.
GL_STE_IPL2n : out std_logic; --STE only.
GL_STE_IPL1n : out std_logic; --STE only.
GL_STE_IPL0n : out std_logic; --STE only.
-- Video timing:
GL_BLANKn : out std_logic;
GL_DE : out std_logic;
GL_MULTISYNC : in std_logic_vector(3 downto 2);
GL_VIDEO_HIMODE : out std_logic;
GL_HSYNC_INn : in std_logic;
GL_HSYNC_OUTn : out std_logic;
GL_VSYNC_INn : in std_logic;
GL_VSYNC_OUTn : out std_logic;
GL_SYNC_OUT_EN : out std_logic;
-- Bus arstd_logicration control:
GL_RDY_INn : in std_logic;
GL_RDY_OUTn : out std_logic;
GL_BRn : out std_logic;
GL_BGIn : in std_logic;
GL_BGOn : out std_logic;
GL_BGACK_INn : in std_logic;
GL_BGACK_OUTn : out std_logic;
-- Adress and data bus:
GL_ADDRESS : in std_logic_vector(23 downto 1);
-- ST: put the data bus to 1 downto 0.
-- STE: put the data out bus to 15 downto 0.
GL_DATA_IN : in std_logic_vector(7 downto 0);
GL_DATA_OUT : out std_logic_vector(15 downto 0);
GL_DATA_EN : out std_logic;
-- Asynchronous bus control:
GL_RWn_IN : in std_logic;
GL_RWn_OUT : out std_logic;
GL_AS_INn : in std_logic;
GL_AS_OUTn : out std_logic;
GL_UDS_INn : in std_logic;
GL_UDS_OUTn : out std_logic;
GL_LDS_INn : in std_logic;
GL_LDS_OUTn : out std_logic;
GL_DTACK_INn : in std_logic;
GL_DTACK_OUTn : out std_logic;
GL_CTRL_EN : out std_logic;
-- System control:
GL_RESETn : in std_logic;
GL_BERRn : out std_logic;
-- Processor function codes:
GL_FC : in std_logic_vector(2 downto 0);
-- STE enhancements:
GL_STE_FDDS : out std_logic; -- Floppy type select (HD or DD).
GL_STE_FCCLK : out std_logic; -- Floppy controller clock select.
GL_STE_JOY_RHn : out std_logic; -- Read only FF9202 high byte.
GL_STE_JOY_RLn : out std_logic; -- Read only FF9202 low byte.
GL_STE_JOY_WL : out std_logic; -- Write only FF9202 low byte.
GL_STE_JOY_WEn : out std_logic; -- Write only FF9202 output enable.
GL_STE_BUTTONn : out std_logic; -- Read only FF9000 low byte.
GL_STE_PAD0Xn : in std_logic; -- Counter input for the Paddle 0X.
GL_STE_PAD0Yn : in std_logic; -- Counter input for the Paddle 0Y.
GL_STE_PAD1Xn : in std_logic; -- Counter input for the Paddle 1X.
GL_STE_PAD1Yn : in std_logic; -- Counter input for the Paddle 1Y.
GL_STE_PADRSTn : out std_logic; -- Paddle monoflops reset.
GL_STE_PENn : in std_logic; -- Input of the light pen.
GL_STE_SCCn : out std_logic; -- Select signal for the STE or TT SCC chip.
GL_STE_CPROGn : out std_logic -- Select signal for the STE's cache processor.
);
end component WF25915IP_TOP_V1_SOC;
component WF5380_TOP_SOC
port (
CLK : in std_logic;
RESETn : in std_logic;
ADR : in std_logic_vector(2 downto 0);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
CSn : in std_logic;
RDn : in std_logic;
WRn : in std_logic;
EOPn : in std_logic;
DACKn : in std_logic;
DRQ : out std_logic;
INT : out std_logic;
READY : out std_logic;
DB_INn : in std_logic_vector(7 downto 0);
DB_OUTn : out std_logic_vector(7 downto 0);
DB_EN : out std_logic;
DBP_INn : in std_logic;
DBP_OUTn : out std_logic;
DBP_EN : out std_logic;
RST_INn : in std_logic;
RST_OUTn : out std_logic;
RST_EN : out std_logic;
BSY_INn : in std_logic;
BSY_OUTn : out std_logic;
BSY_EN : out std_logic;
SEL_INn : in std_logic;
SEL_OUTn : out std_logic;
SEL_EN : out std_logic;
ACK_INn : in std_logic;
ACK_OUTn : out std_logic;
ACK_EN : out std_logic;
ATN_INn : in std_logic;
ATN_OUTn : out std_logic;
ATN_EN : out std_logic;
REQ_INn : in std_logic;
REQ_OUTn : out std_logic;
REQ_EN : out std_logic;
IOn_IN : in std_logic;
IOn_OUT : out std_logic;
IO_EN : out std_logic;
CDn_IN : in std_logic;
CDn_OUT : out std_logic;
CD_EN : out std_logic;
MSG_INn : in std_logic;
MSG_OUTn : out std_logic;
MSG_EN : out std_logic
);
end component WF5380_TOP_SOC;
component WF1772IP_TOP_SOC -- FDC.
port (
CLK : in std_logic; -- 16MHz clock!
RESETn : in std_logic;
CSn : in std_logic;
RWn : in std_logic;
A1, A0 : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
RDn : in std_logic;
TR00n : in std_logic;
IPn : in std_logic;
WPRTn : in std_logic;
DDEn : in std_logic;
HDTYPE : in std_logic; -- '0' = DD disks, '1' = HD disks.
MO : out std_logic;
WG : out std_logic;
WD : out std_logic;
STEP : out std_logic;
DIRC : out std_logic;
DRQ : out std_logic;
INTRQ : out std_logic
);
end component WF1772IP_TOP_SOC;
component WF68901IP_TOP_SOC -- MFP.
port ( -- System control:
CLK : in std_logic;
RESETn : in std_logic;
-- Asynchronous bus control:
DSn : in std_logic;
CSn : in std_logic;
RWn : in std_logic;
DTACKn : out std_logic;
-- Data and Adresses:
RS : in std_logic_vector(5 downto 1);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
GPIP_IN : in std_logic_vector(7 downto 0);
GPIP_OUT : out std_logic_vector(7 downto 0);
GPIP_EN : out std_logic_vector(7 downto 0);
-- Interrupt control:
IACKn : in std_logic;
IEIn : in std_logic;
IEOn : out std_logic;
IRQn : out std_logic;
-- Timers and timer control:
XTAL1 : in std_logic; -- Use an oszillator instead of a quartz.
TAI : in std_logic;
TBI : in std_logic;
TAO : out std_logic;
TBO : out std_logic;
TCO : out std_logic;
TDO : out std_logic;
-- Serial I/O control:
RC : in std_logic;
TC : in std_logic;
SI : in std_logic;
SO : out std_logic;
SO_EN : out std_logic;
-- DMA control:
RRn : out std_logic;
TRn : out std_logic
);
end component WF68901IP_TOP_SOC;
component WF2149IP_TOP_SOC -- Sound.
port(
SYS_CLK : in std_logic; -- Read the inforation in the header!
RESETn : in std_logic;
WAV_CLK : in std_logic; -- Read the inforation in the header!
SELn : in std_logic;
BDIR : in std_logic;
BC2, BC1 : in std_logic;
A9n, A8 : in std_logic;
DA_IN : in std_logic_vector(7 downto 0);
DA_OUT : out std_logic_vector(7 downto 0);
DA_EN : out std_logic;
IO_A_IN : in std_logic_vector(7 downto 0);
IO_A_OUT : out std_logic_vector(7 downto 0);
IO_A_EN : out std_logic;
IO_B_IN : in std_logic_vector(7 downto 0);
IO_B_OUT : out std_logic_vector(7 downto 0);
IO_B_EN : out std_logic;
OUT_A : out std_logic; -- Analog (PWM) outputs.
OUT_B : out std_logic;
OUT_C : out std_logic
);
end component WF2149IP_TOP_SOC;
component WF6850IP_TOP_SOC -- ACIA.
port (
CLK : in std_logic;
RESETn : in std_logic;
CS2n, CS1, CS0 : in std_logic;
E : in std_logic;
RWn : in std_logic;
RS : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
TXCLK : in std_logic;
RXCLK : in std_logic;
RXDATA : in std_logic;
CTSn : in std_logic;
DCDn : in std_logic;
IRQn : out std_logic;
TXDATA : out std_logic;
RTSn : out std_logic
);
end component WF6850IP_TOP_SOC;
component WF_SD_CARD
port (
RESETn : in std_logic;
CLK : in std_logic;
ACSI_A1 : in std_logic;
ACSI_CSn : in std_logic;
ACSI_ACKn : in std_logic;
ACSI_INTn : out std_logic;
ACSI_DRQn : out std_logic;
ACSI_D_IN : in std_logic_vector(7 downto 0);
ACSI_D_OUT : out std_logic_vector(7 downto 0);
ACSI_D_EN : out std_logic;
MC_DO : in std_logic;
MC_PIO_DMAn : in std_logic;
MC_RWn : in std_logic;
MC_CLR_CMD : in std_logic;
MC_DONE : out std_logic;
MC_GOT_CMD : out std_logic;
MC_D_IN : in std_logic_vector(7 downto 0);
MC_D_OUT : out std_logic_vector(7 downto 0);
MC_D_EN : out std_logic
);
end component WF_SD_CARD;
component dcfifo0
PORT (
aclr : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (5 DOWNTO 0)
);
end component dcfifo0;
component dcfifo1
PORT (
aclr : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
rdusedw : OUT STD_LOGIC_VECTOR (5 DOWNTO 0)
);
end component;
end FalconIO_SDCard_IDE_CF_PKG;

View File

@@ -0,0 +1,631 @@
----------------------------------------------------------------------
---- ----
---- WF5380 IP Core ----
---- ----
---- Description: ----
---- This model provides an asynchronous SCSI interface compa- ----
---- tible to the DP5380 from National Semiconductor and others. ----
---- ----
---- This file is the 5380's system controller. ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K9A 2009/06/20 WF
-- Initial Release.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF5380_CONTROL is
port (
-- System controls:
CLK : in bit;
RESETn : in bit; -- System reset.
-- System controls:
BSY_INn : in bit; -- SCSI BSY_INn bit.
BSY_OUTn : out bit; -- SCSI BSY_INn bit.
DATA_EN : out bit; -- Enable the SCSI data lines.
SEL_INn : in bit; -- SCSI SEL_INn bit.
ARB_EN : in bit; -- Arbitration enable.
BSY_DISn : in bit; -- BSY monitoring enable.
RSTn : in bit; -- SCSI reset.
ARB : out bit; -- Arbitration flag.
AIP : out bit; -- Arbitration in progress flag.
LA : out bit; -- Lost arbitration flag.
ACK_INn : in bit;
ACK_OUTn : out bit;
REQ_INn : in bit;
REQ_OUTn : out bit;
DACKn : in bit; -- Data acknowledge.
READY : out bit;
DRQ : out bit; -- Data request.
TARG : in bit; -- Target mode indicator.
BLK : in bit; -- Block mode indicator.
PINT_EN : in bit; -- Parity interrupt enable.
SPER : in bit; -- Parity error.
SER_ID : in bit; -- SER matches ODR bits.
RPI : in bit; -- Reset interrupts.
DMA_EN : in bit; -- DMA mode enable.
SDS : in bit; -- Start DMA send, write only.
SDT : in bit; -- Start DMA target receive, write only.
SDI : in bit; -- Start DMA initiator receive, write only.
EOP_EN : in bit; -- EOP interrupt enable.
EOPn : in bit; -- End of process indicator.
PHSM : in bit; -- Phase match flag.
INT : out bit; -- Interrupt.
IDR_WR : out bit; -- Write input data register during DMA.
ODR_WR : out bit; -- Write output data register, during DMA.
CHK_PAR : out bit; -- Check Parity during DMA operation.
BSY_ERR : out bit; -- Busy monitoring error.
DMA_SND : out bit; -- Indicates direction of target DMA.
DMA_ACTIVE : out bit -- DMA is active.
);
end entity WF5380_CONTROL;
architecture BEHAVIOUR of WF5380_CONTROL is
type CTRL_STATES is (IDLE, WAIT_800ns, WAIT_2200ns, DMA_SEND, DMA_TARG_RCV, DMA_INIT_RCV);
type DMA_STATES is (IDLE, DMA_STEP_1, DMA_STEP_2, DMA_STEP_3, DMA_STEP_4);
signal CTRL_STATE : CTRL_STATES;
signal NEXT_CTRL_STATE : CTRL_STATES;
signal DMA_STATE : DMA_STATES;
signal NEXT_DMA_STATE : DMA_STATES;
signal BUS_FREE : bit;
signal DELAY_800ns : boolean;
signal DELAY_2200ns : boolean;
signal DMA_ACTIVE_I : bit;
signal EOP_In : bit;
begin
IN_BUFFER: process
-- This buffer shall prevent some signals against
-- setup hold effects and thus the state machine
-- against unpredictable behaviour.
begin
wait until CLK = '1' and CLK' event;
EOP_In <= EOPn;
end process IN_BUFFER;
STATE_REGISTERS: process(RESETn, CLK)
-- This is the controller's state machine register.
variable BSY_LOCK : boolean;
begin
if RESETn = '0' then
CTRL_STATE <= IDLE;
DMA_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if RSTn = '0' then -- SCSI reset.
CTRL_STATE <= IDLE;
DMA_STATE <= IDLE;
else
CTRL_STATE <= NEXT_CTRL_STATE;
DMA_STATE <= NEXT_DMA_STATE;
end if;
--
if DMA_EN = '0' then
DMA_STATE <= IDLE;
end if;
end if;
end process STATE_REGISTERS;
CTRL_DECODER: process(CTRL_STATE, ARB_EN, BUS_FREE, DELAY_800ns, SEL_INn, DMA_ACTIVE_I, SDS, SDT, SDI)
-- This is the controller's state machine decoder.
variable BSY_LOCK : boolean;
begin
-- Defaults.
DMA_SND <= '0';
--
case CTRL_STATE is
when IDLE =>
if ARB_EN = '1' and BUS_FREE = '1' then
NEXT_CTRL_STATE <= WAIT_800ns;
else
NEXT_CTRL_STATE <= IDLE;
end if;
when WAIT_800ns =>
if DELAY_800ns = true then
NEXT_CTRL_STATE <= WAIT_2200ns;
else
NEXT_CTRL_STATE <= WAIT_800ns;
end if;
when WAIT_2200ns =>
-- In this state the delay is provided by the
-- microprocessor and is at least 2.2us. The
-- delay is released by deasserting SELn.
if SEL_INn = '1' and SDS = '1' then
NEXT_CTRL_STATE <= DMA_SEND;
elsif SEL_INn = '1' and SDT = '1' then
NEXT_CTRL_STATE <= DMA_TARG_RCV;
elsif SEL_INn = '1' and SDI = '1' then
NEXT_CTRL_STATE <= DMA_INIT_RCV;
else
NEXT_CTRL_STATE <= WAIT_2200ns;
end if;
when DMA_SEND =>
if DMA_ACTIVE_I = '0' then
NEXT_CTRL_STATE <= IDLE;
else
NEXT_CTRL_STATE <= DMA_SEND;
end if;
--
DMA_SND <= '1';
when DMA_TARG_RCV =>
if DMA_ACTIVE_I = '0' then
NEXT_CTRL_STATE <= IDLE;
else
NEXT_CTRL_STATE <= DMA_TARG_RCV;
end if;
when DMA_INIT_RCV =>
if DMA_ACTIVE_I = '0' then
NEXT_CTRL_STATE <= IDLE;
else
NEXT_CTRL_STATE <= DMA_INIT_RCV;
end if;
end case;
end process CTRL_DECODER;
DMA_DECODER: process(CTRL_STATE, DMA_STATE, TARG, BLK, DACKn, REQ_INn, ACK_INn)
-- This is the DMA state machine decoder.
begin
-- Defaults:
IDR_WR <= '0';
ODR_WR <= '0';
CHK_PAR <= '0';
--
case DMA_STATE is
when IDLE =>
if CTRL_STATE = DMA_SEND then
NEXT_DMA_STATE <= DMA_STEP_1;
elsif CTRL_STATE = DMA_INIT_RCV then
NEXT_DMA_STATE <= DMA_STEP_1;
elsif CTRL_STATE = DMA_TARG_RCV then
NEXT_DMA_STATE <= DMA_STEP_1;
else
NEXT_DMA_STATE <= IDLE;
end if;
when DMA_STEP_1 =>
-- Initiator modes:
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
ODR_WR <= '1';
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
ODR_WR <= '1';
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and REQ_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for REQn asserted.
IDR_WR <= '1';
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and REQ_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for REQn asserted.
IDR_WR <= '1';
-- Target modes:
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
ODR_WR <= '1';
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
ODR_WR <= '1';
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and ACK_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for ACKn asserted.
IDR_WR <= '1';
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and ACK_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for ACKn asserted.
IDR_WR <= '1';
else
NEXT_DMA_STATE <= DMA_STEP_1;
end if;
when DMA_STEP_2 =>
-- Initiator modes:
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and REQ_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for REQn deasserted.
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and REQ_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for REQn deasserted.
-- Target modes:
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and ACK_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for ACKn deasserted.
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and ACK_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for ACKn deasserted.
else
NEXT_DMA_STATE <= DMA_STEP_2;
end if;
when DMA_STEP_3 =>
-- Initiator modes:
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and REQ_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait REQn asserted.
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and REQ_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait REQn asserted.
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
CHK_PAR <= '1';
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
CHK_PAR <= '1';
-- Target modes:
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and ACK_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait ACKn asserted.
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' and ACK_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait ACKn asserted.
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
CHK_PAR <= '1';
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
CHK_PAR <= '1';
else
NEXT_DMA_STATE <= DMA_STEP_3;
end if;
when DMA_STEP_4 =>
-- Initiator modes:
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and REQ_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait REQn deasserted.
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and REQ_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait REQn deasserted.
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
-- Target modes:
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and ACK_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait ACKn deasserted.
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' and ACK_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait ACKn deasserted.
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
else
NEXT_DMA_STATE <= DMA_STEP_4;
end if;
end case;
end process DMA_DECODER;
P_REQn: process(DMA_STATE, CTRL_STATE, TARG, BLK)
-- This logic controls the REQn output in target mode.
begin
if DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '0' then
REQ_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '1' then
REQ_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' then
REQ_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' then
REQ_OUTn <= '0';
else
REQ_OUTn <= '1';
end if;
end process P_REQn;
P_ACKn: process(DMA_STATE, CTRL_STATE, TARG, BLK)
-- This logic controls the ACKn output in initiator mode.
begin
if DMA_STATE = DMA_STEP_2 and CTRL_STATE = DMA_INIT_RCV and BLK = '0' then
ACK_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_2 and CTRL_STATE = DMA_INIT_RCV and BLK = '1' then
ACK_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_4 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' then
ACK_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_4 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' then
ACK_OUTn <= '0';
else
ACK_OUTn <= '1';
end if;
end process P_ACKn;
P_READY: process(DMA_STATE, CTRL_STATE, TARG, BLK)
-- This logic controls the READY output in initiator and target block mode.
begin
if DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' then
READY <= '1';
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '1' then
READY <= '1';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' then
READY <= '1';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_INIT_RCV and BLK = '1' then
READY <= '1';
else
READY <= '0';
end if;
end process P_READY;
P_DRQ: process(RESETn, CLK)
-- This flip flop controls the DRQ flag during all initiator and all target modes
-- for both block mode and non block mode operation.
variable LOCK : boolean;
begin
if RESETn = '0' then
DRQ <= '0';
LOCK := false;
elsif CLK = '1' and CLK' event then
-- Initiator modes:
if DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' then
DRQ <= '1';
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and LOCK = false then
DRQ <= '1';
LOCK := true;
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_INIT_RCV and BLK = '0' then
DRQ <= '1';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_INIT_RCV and BLK = '1' then
DRQ <= '1';
LOCK := true;
-- Target modes:
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' then
DRQ <= '1';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' then
DRQ <= '1';
LOCK := true;
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '0' then
DRQ <= '1';
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '1' then
DRQ <= '1';
LOCK := true;
elsif DACKn = '0' and LOCK = false then
DRQ <= '0';
elsif EOPn = '0' and DACKn = '0' then
DRQ <= '0';
LOCK := false;
end if;
end if;
end process P_DRQ;
P_BUSFREE: process(RESETn, CLK)
-- This is the logic for the bus free signal.
-- A bus free is valid if the BSY_INn signal is
-- at least 437.5ns inactive ans SEL_INn is inactive.
-- The delay are 7 clock cycles of 16MHz.
variable TMP : std_logic_vector(2 downto 0);
begin
if RESETn = '0' then
BUS_FREE <= '0';
TMP := "000";
elsif CLK = '1' and CLK' event then
if BSY_INn = '1' and TMP < x"111" then
TMP := TMP + '1';
elsif BSY_INn = '0' then
TMP := "000";
end if;
--
if RSTn = '0' then -- SCSI reset.
BUS_FREE <= '0';
elsif SEL_INn = '1' and TMP = "111" then
BUS_FREE <= '1';
else
BUS_FREE <= '0';
end if;
end if;
end process P_BUSFREE;
DELAY_800: process(RESETn, CLK)
-- This is the delay of 812.5ns.
-- It is derived from 13 16MHz clock cycles.
variable TMP : std_logic_vector(3 downto 0);
begin
if RESETn = '0' then
DELAY_800ns <= false;
TMP := x"0";
elsif CLK = '1' and CLK' event then
if CTRL_STATE /= WAIT_800ns then
TMP := x"0";
elsif TMP <= x"D" then
TMP := TMP + '1';
end if;
--
if TMP = x"D" then
DELAY_800ns <= true;
else
DELAY_800ns <= false;
end if;
end if;
end process DELAY_800;
P_ARB: process(RESETn, CLK)
-- This flip flop controls the ARB flag read back
-- by the microcontroller.
begin
if RESETn = '0' then
ARB <= '0';
elsif CLK = '1' and CLK' event then
if CTRL_STATE /= WAIT_800ns and NEXT_CTRL_STATE = WAIT_800ns then
ARB <= '1';
elsif ARB_EN = '0' then
ARB <= '0';
end if;
end if;
end process P_ARB;
P_AIP: process(RESETn, CLK)
-- This flip flop controls the AIP flag read back
-- by the microcontroller.
begin
if RESETn = '0' then
AIP <= '0';
elsif CLK = '1' and CLK' event then
if CTRL_STATE = WAIT_800ns and NEXT_CTRL_STATE /= WAIT_800ns then
AIP <= '1';
elsif ARB_EN = '0' then
AIP <= '0';
end if;
end if;
end process P_AIP;
P_BSY: process
-- This flip flop controls the BSYn output
-- to the SCSI bus.
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
BSY_OUTn <= '1';
elsif CTRL_STATE = WAIT_800ns and NEXT_CTRL_STATE /= WAIT_800ns then
BSY_OUTn <= '0';
elsif ARB_EN = '0' then
BSY_OUTn <= '1';
end if;
end process P_BSY;
P_DATA_EN: process(RESETn, CLK)
-- This flip flop controls the data enable
-- of the SCSI bus.
begin
if RESETn = '0' then
DATA_EN <= '0';
elsif CLK = '1' and CLK' event then
if CTRL_STATE = WAIT_800ns and NEXT_CTRL_STATE /= WAIT_800ns then
DATA_EN <= '1';
elsif ARB_EN = '0' then
DATA_EN <= '0';
end if;
end if;
end process P_DATA_EN;
P_LA: process(RESETn, CLK)
-- This flip flop controls the LA
-- (lost arbitration) flag.
begin
if RESETn = '0' then
LA <= '0';
elsif CLK = '1' and CLK' event then
if (CTRL_STATE = WAIT_800ns or CTRL_STATE = WAIT_2200ns) and SEL_INn = '0' then
LA <= '1';
elsif ARB_EN = '0' then
LA <= '0';
end if;
end if;
end process P_LA;
P_DMA_ACTIVE: process(RESETn, CLK, DMA_ACTIVE_I)
-- This is the Flip Flop indicating if there is DMA
-- operation.
begin
if RESETn = '0' then
DMA_ACTIVE_I <= '0';
elsif CLK = '1' and CLK' event then
if DMA_EN = '1' and SDS = '1' then
DMA_ACTIVE_I <= '1'; -- Start DMA send.
elsif DMA_EN = '1' and SDT = '1' then
DMA_ACTIVE_I <= '1'; -- Start DMA target receive.
elsif DMA_EN = '1' and SDI = '1' then
DMA_ACTIVE_I <= '1'; -- Start DMA initiator receive.
elsif DMA_EN = '0' then
DMA_ACTIVE_I <= '0'; -- Halt DMA via DMA flag in MR2.
elsif EOP_In = '0' then
DMA_ACTIVE_I <= '0'; -- Halt DMA via EOPn.
elsif PHSM = '0' then
DMA_ACTIVE_I <= '0'; -- Halt DMA via phase mismatch.
end if;
end if;
--
DMA_ACTIVE <= DMA_ACTIVE_I;
end process P_DMA_ACTIVE;
INTERRUPTS: process(RESETn, CLK)
-- This is the logic for all DP5380's interrupt sources.
-- A busy interrupt occurs if the BSY_INn signal is at
-- least 437.5ns inactive. The delay are 7 clock cycles
-- of 16MHz. This logic also provides the respective
-- error flags for the BSR.
variable TMP : std_logic_vector(2 downto 0);
begin
if RESETn = '0' then
INT <= '0';
BSY_ERR <= '0';
TMP := "000";
elsif CLK = '1' and CLK' event then
if SPER = '1' and PINT_EN = '1' then
INT <= '1'; -- Parity interrupt.
elsif RPI = '0' then -- Reset interrupts.
INT <= '0';
end if;
--
if EOP_In = '0' and CTRL_STATE = DMA_SEND then
BSY_ERR <= '1'; -- End of DMA error.
elsif EOP_In = '0' and CTRL_STATE = DMA_TARG_RCV then
BSY_ERR <= '1'; -- End of DMA error.
elsif EOP_In = '0' and CTRL_STATE = DMA_INIT_RCV then
BSY_ERR <= '1'; -- End of DMA error.
elsif DMA_EN = '0' then -- Reset error.
INT <= '0';
end if;
--
if EOP_EN = '1' and EOP_In = '0' and CTRL_STATE = DMA_SEND then
INT <= '1'; -- End of DMA interrupt.
elsif EOP_EN = '1' and EOP_In = '0' and CTRL_STATE = DMA_TARG_RCV then
INT <= '1'; -- End of DMA interrupt.
elsif EOP_EN = '1' and EOP_In = '0' and CTRL_STATE = DMA_INIT_RCV then
INT <= '1'; -- End of DMA interrupt.
elsif DMA_EN = '0' then -- Reset interrupt.
INT <= '0';
end if;
--
if PHSM = '0' then
INT <= '1'; -- Phase mismatch interrupt.
elsif DMA_EN = '0' then -- Reset interrupts.
INT <= '0';
end if;
--
if SEL_INn = '0' and BSY_INn = '1' and SER_ID = '1' then
INT <= '1'; -- (Re)Selection interrupt.
elsif RPI = '1' then -- Reset interrupts.
INT <= '0';
end if;
--
if BSY_INn = '1' and TMP < x"111" then
TMP := TMP + '1'; -- Bus settle delay.
elsif BSY_INn = '0' then
TMP := "000";
end if;
--
if BSY_DISn = '1' and BSY_INn = '1' and TMP = x"111" then
INT <= '1'; -- Busy monitoring interrupt.
BSY_ERR <= '1';
elsif RPI = '1' then -- Reset interrupts.
INT <= '0';
BSY_ERR <= '0';
end if;
--
end if;
end process INTERRUPTS;
end BEHAVIOUR;

View File

@@ -0,0 +1,139 @@
----------------------------------------------------------------------
---- ----
---- WF5380 IP Core ----
---- ----
---- Description: ----
---- This model provides an asynchronous SCSI interface compa- ----
---- tible to the DP5380 from National Semiconductor and others. ----
---- ----
---- This file is the package file of the ip core. ----
---- ----
---- ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K9A 2009/06/20 WF
-- Initial Release.
library ieee;
use ieee.std_logic_1164.all;
package WF5380_PKG is
component WF5380_REGISTERS
port (
CLK : in bit;
RESETn : in bit;
ADR : in bit_vector(2 downto 0);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
CSn : in bit;
RDn : in bit;
WRn : in bit;
RSTn : in bit;
RST : out bit;
ARB_EN : out bit;
DMA_ACTIVE : in bit;
DMA_EN : out bit;
BSY_DISn : out bit;
EOP_EN : out bit;
PINT_EN : out bit;
SPER : out bit;
TARG : out bit;
BLK : out bit;
DMA_DIS : in bit;
IDR_WR : in bit;
ODR_WR : in bit;
CHK_PAR : in bit;
AIP : in bit;
ARB : in bit;
LA : in bit;
CSD : in bit_vector(7 downto 0);
CSB : in bit_vector(7 downto 0);
BSR : in bit_vector(7 downto 0);
ODR_OUT : out bit_vector(7 downto 0);
ICR_OUT : out bit_vector(7 downto 0);
TCR_OUT : out bit_vector(3 downto 0);
SER_OUT : out bit_vector(7 downto 0);
SDS : out bit;
SDT : out bit;
SDI : out bit;
RPI : out bit
);
end component;
component WF5380_CONTROL
port (
CLK : in bit;
RESETn : in bit;
BSY_INn : in bit;
BSY_OUTn : out bit;
DATA_EN : out bit;
SEL_INn : in bit;
ARB_EN : in bit;
BSY_DISn : in bit;
RSTn : in bit;
ARB : out bit;
AIP : out bit;
LA : out bit;
ACK_INn : in bit;
ACK_OUTn : out bit;
REQ_INn : in bit;
REQ_OUTn : out bit;
DACKn : in bit;
READY : out bit;
DRQ : out bit;
TARG : in bit;
BLK : in bit;
PINT_EN : in bit;
SPER : in bit;
SER_ID : in bit;
RPI : in bit;
DMA_EN : in bit;
SDS : in bit;
SDT : in bit;
SDI : in bit;
EOP_EN : in bit;
EOPn : in bit;
PHSM : in bit;
INT : out bit;
IDR_WR : out bit;
ODR_WR : out bit;
CHK_PAR : out bit;
BSY_ERR : out bit;
DMA_SND : out bit;
DMA_ACTIVE : out bit
);
end component;
end WF5380_PKG;

View File

@@ -0,0 +1,265 @@
----------------------------------------------------------------------
---- ----
---- WF5380 IP Core ----
---- ----
---- Description: ----
---- This model provides an asynchronous SCSI interface compa- ----
---- tible to the DP5380 from National Semiconductor and others. ----
---- ----
---- This file is the 5380's register model. ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Register description (for more information see the DP5380 ----
---- data sheet: ----
---- ODR (address 0) Output data register, write only. ----
---- CSD (address 0) Current SCSI data, read only. ----
---- ICR (address 1) Initiator command register, read/write. ----
---- MR2 (address 2) Mode register 2, read/write. ----
---- TCR (address 3) Target command register, read/write. ----
---- SER (address 4) Select enable register, write only. ----
---- CSB (address 4) Current SCSI bus status, read only. ----
---- BSR (address 5) Start DMA send, write only. ----
---- SDS (address 5) Bus and status, read only. ----
---- SDT (address 6) Start DMA target receive, write only. ----
---- IDR (address 6) Input data register, read only. ----
---- SDI (address 7) Start DMA initiator recive, write only. ----
---- RPI (address 7) Reset parity / interrupts, read only. ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K9A 2009/06/20 WF
-- Initial Release.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF5380_REGISTERS is
port (
-- System controls:
CLK : in bit;
RESETn : in bit; -- System reset.
-- Address and data:
ADR : in bit_vector(2 downto 0);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
-- Bus and DMA controls:
CSn : in bit;
RDn : in bit;
WRn : in bit;
-- Core controls:
RSTn : in bit; -- SCSI reset.
RST : out bit; -- Programmed SCSI reset.
ARB_EN : out bit; -- Arbitration enable.
DMA_ACTIVE : in bit; -- DMA is running.
DMA_EN : out bit; -- DMA mode enable.
BSY_DISn : out bit; -- BSY monitoring enable.
EOP_EN : out bit; -- EOP interrupt enable.
PINT_EN : out bit; -- Parity interrupt enable.
SPER : out bit; -- Parity error.
TARG : out bit; -- Target mode.
BLK : out bit; -- Block DMA mode.
DMA_DIS : in bit; -- Reset the DMA_EN by this signal.
IDR_WR : in bit; -- Write input data register during DMA.
ODR_WR : in bit; -- Write output data register, during DMA.
CHK_PAR : in bit; -- Check Parity during DMA operation.
AIP : in bit; -- Arbitration in progress.
ARB : in bit; -- Arbitration.
LA : in bit; -- Lost arbitration.
CSD : in bit_vector(7 downto 0); -- SCSI data.
CSB : in bit_vector(7 downto 0); -- Current SCSI bus status.
BSR : in bit_vector(7 downto 0); -- Bus and status.
ODR_OUT : out bit_vector(7 downto 0); -- This is the ODR register.
ICR_OUT : out bit_vector(7 downto 0); -- This is the ICR register.
TCR_OUT : out bit_vector(3 downto 0); -- This is the TCR register.
SER_OUT : out bit_vector(7 downto 0); -- This is the SER register.
SDS : out bit; -- Start DMA send, write only.
SDT : out bit; -- Start DMA target receive, write only.
SDI : out bit; -- Start DMA initiator receive, write only.
RPI : out bit
);
end entity WF5380_REGISTERS;
architecture BEHAVIOUR of WF5380_REGISTERS is
signal ICR : bit_vector(7 downto 0); -- Initiator command register, read/write.
signal IDR : bit_vector(7 downto 0); -- Input data register.
signal MR2 : bit_vector(7 downto 0); -- Mode register 2, read/write.
signal ODR : bit_vector(7 downto 0); -- Output data register, write only.
signal SER : bit_vector(7 downto 0); -- Select enable register, write only.
signal TCR : bit_vector(3 downto 0); -- Target command register, read/write.
begin
REGISTERS: process(RESETn, CLK)
-- This process reflects all registers in the 5380.
variable BSY_LOCK : boolean;
begin
if RESETn = '0' then
ODR <= (others => '0');
ICR <= (others => '0');
MR2 <= (others => '0');
TCR <= (others => '0');
SER <= (others => '0');
BSY_LOCK := false;
elsif CLK = '1' and CLK' event then
if RSTn = '0' then -- SCSI reset.
ODR <= (others => '0');
ICR(6 downto 0) <= (others => '0');
MR2(7) <= '0';
MR2(5 downto 0) <= (others => '0');
TCR <= (others => '0');
SER <= (others => '0');
BSY_LOCK := false;
elsif ADR = "000" and CSn = '0' and WRn = '0' then
ODR <= DATA_IN;
elsif ADR = "001" and CSn = '0' and WRn = '0' then
ICR <= DATA_IN;
elsif ADR = "010" and CSn = '0' and WRn = '0' then
MR2 <= DATA_IN;
elsif ADR = "011" and CSn = '0' and WRn = '0' then
TCR <= DATA_IN(3 downto 0);
elsif ADR = "100" and CSn = '0' and WRn = '0' then
SER <= DATA_IN;
end if;
--
if ODR_WR = '1' then
ODR <= DATA_IN;
end if;
--
-- This reset function is edge triggered on the 'Monitor Busy'
-- MR2(2).
if MR2(2) = '1' and BSY_LOCK = false then
ICR(5 downto 0) <= "000000";
BSY_LOCK := true;
elsif MR2(2) = '0' then
BSY_LOCK := false;
end if;
--
if DMA_DIS = '1' then
MR2(1) <= '0';
end if;
end if;
end process REGISTERS;
IDR_REGISTER: process(RESETn, CLK)
begin
if RESETn = '0' then
IDR <= x"00";
elsif CLK = '1' and CLK' event then
if RSTn = '0' or ICR(7) = '1' then
IDR <= x"00"; -- SCSI reset.
elsif IDR_WR = '1' then
IDR <= CSD;
end if;
end if;
end process IDR_REGISTER;
PARITY: process(RESETn, CLK)
-- This is the parity generating logic with it's related
-- error generation.
variable PAR_VAR : bit;
variable LOCK : boolean;
begin
if RESETn = '0' then
SPER <= '0';
LOCK := false;
elsif CLK = '1' and CLK' event then
-- Parity checked during 'Read from CSD'
-- (registered I/O and selection/reselection):
if ADR = "000" and CSn = '0' and RDn = '0' and LOCK = false then
for i in 1 to 7 loop
PAR_VAR := CSD(i) xor CSD(i-1);
end loop;
SPER <= not PAR_VAR;
LOCK := true;
end if;
--
-- Parity checking during DMA operation:
if DMA_ACTIVE = '1' and CHK_PAR = '1' then
for i in 1 to 7 loop
PAR_VAR := IDR(i) xor IDR(i-1);
end loop;
SPER <= not PAR_VAR;
LOCK := true;
end if;
--
-- Reset parity flag:
if MR2(5) <= '0' then -- MR2(5) = PCHK (disabled).
SPER <= '0';
elsif ADR = "111" and CSn = '0' and RDn = '0' then -- Reset parity/interrupts.
SPER <= '0';
LOCK := false;
end if;
end if;
end process PARITY;
DATA_EN <= '1' when ADR < "101" and CSn = '0' and WRn = '0' else '0';
SDS <= '1' when ADR = "101" and CSn = '0' and WRn = '0' else '0';
SDT <= '1' when ADR = "110" and CSn = '0' and WRn = '0' else '0';
SDI <= '1' when ADR = "111" and CSn = '0' and WRn = '0' else '0';
ICR_OUT <= ICR;
TCR_OUT <= TCR;
SER_OUT <= SER;
ODR_OUT <= ODR;
ARB_EN <= MR2(0);
DMA_EN <= MR2(1);
BSY_DISn <= MR2(2);
EOP_EN <= MR2(3);
PINT_EN <= MR2(4);
TARG <= MR2(6);
BLK <= MR2(7);
RST <= ICR(7);
-- Readback, unused bit positions are read back zero.
DATA_OUT <= CSD when ADR = "000" and CSn = '0' and RDn = '0' else -- Current SCSI data.
ICR(7) & AIP & LA & ICR(4 downto 0) when ADR = "001" and CSn = '0' and RDn = '0' else
MR2 when ADR = "010" and CSn = '0' and RDn = '0' else
x"0" & TCR when ADR = "011" and CSn = '0' and RDn = '0' else
CSB when ADR = "100" and CSn = '0' and RDn = '0' else -- Current SCSI bus status.
BSR when ADR = "101" and CSn = '0' and RDn = '0' else -- Bus and status.
IDR when ADR = "110" and CSn = '0' and RDn = '0' else x"00"; -- Input data register.
RPI <= '1' when ADR = "111" and CSn = '0' and RDn = '0' else '0'; -- Reset parity/interrupts.
end BEHAVIOUR;

View File

@@ -0,0 +1,300 @@
----------------------------------------------------------------------
---- ----
---- WF5380 IP Core ----
---- ----
---- Description: ----
---- This model provides an asynchronous SCSI interface compa- ----
---- tible to the DP5380 from National Semiconductor and others. ----
---- ----
---- Some remarks to the required input clock: ----
---- This core is provided for a 16MHz input clock. To use other ----
---- frequencies, it is necessary to modify the following proces- ----
---- ses in the control file section: ----
---- P_BUSFREE, DELAY_800, INTERRUPTS. ----
---- ----
---- This file is the top level file without tree state buses for ----
---- use in 'systems on chip' designs. ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K9A 2009/06/20 WF
-- Initial Release.
--
library work;
use work.wf5380_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF5380_TOP_SOC is
port (
-- System controls:
CLK : in bit; -- Use a 16MHz Clock.
RESETn : in bit;
-- Address and data:
ADR : in bit_vector(2 downto 0);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
-- Bus and DMA controls:
CSn : in bit;
RDn : in bit;
WRn : in bit;
EOPn : in bit;
DACKn : in bit;
DRQ : out bit;
INT : out bit;
READY : out bit;
-- SCSI bus:
DB_INn : in bit_vector(7 downto 0);
DB_OUTn : out bit_vector(7 downto 0);
DB_EN : out bit;
DBP_INn : in bit;
DBP_OUTn : out bit;
DBP_EN : out bit;
RST_INn : in bit;
RST_OUTn : out bit;
RST_EN : out bit;
BSY_INn : in bit;
BSY_OUTn : out bit;
BSY_EN : out bit;
SEL_INn : in bit;
SEL_OUTn : out bit;
SEL_EN : out bit;
ACK_INn : in bit;
ACK_OUTn : out bit;
ACK_EN : out bit;
ATN_INn : in bit;
ATN_OUTn : out bit;
ATN_EN : out bit;
REQ_INn : in bit;
REQ_OUTn : out bit;
REQ_EN : out bit;
IOn_IN : in bit;
IOn_OUT : out bit;
IO_EN : out bit;
CDn_IN : in bit;
CDn_OUT : out bit;
CD_EN : out bit;
MSG_INn : in bit;
MSG_OUTn : out bit;
MSG_EN : out bit
);
end entity WF5380_TOP_SOC;
architecture STRUCTURE of WF5380_TOP_SOC is
signal ACK_OUT_CTRLn : bit;
signal AIP : bit;
signal ARB : bit;
signal ARB_EN : bit;
signal BLK : bit;
signal BSR : bit_vector(7 downto 0);
signal BSY_DISn : bit;
signal BSY_ERR : bit;
signal BSY_OUT_CTRLn : bit;
signal CHK_PAR : bit;
signal CSD : bit_vector(7 downto 0);
signal CSB : bit_vector(7 downto 0);
signal DATA_EN_CTRL : bit;
signal DB_EN_I : bit;
signal DMA_ACTIVE : bit;
signal DMA_EN : bit;
signal DMA_DIS : bit;
signal DMA_SND : bit;
signal DRQ_I : bit;
signal EDMA : bit;
signal EOP_EN : bit;
signal ICR : bit_vector(7 downto 0);
signal IDR_WR : bit;
signal INT_I : bit;
signal LA : bit;
signal ODR : bit_vector(7 downto 0);
signal ODR_WR : bit;
signal PCHK : bit;
signal PHSM : bit;
signal PINT_EN : bit;
signal REQ_OUT_CTRLn : bit;
signal RPI : bit;
signal RST : bit;
signal SDI : bit;
signal SDS : bit;
signal SDT : bit;
signal SER : bit_vector(7 downto 0);
signal SER_ID : bit;
signal SPER : bit;
signal TARG : bit;
signal TCR : bit_vector(3 downto 0);
begin
EDMA <= '1' when EOPn = '0' and DACKn = '0' and RDn = '0' else
'1' when EOPn = '0' and DACKn = '0' and WRn = '0' else '0';
PHSM <= '1' when DMA_ACTIVE = '0' else -- Always true, if there is no DMA.
'1' when DMA_ACTIVE = '1' and REQ_INn = '0' and CDn_In = TCR(1) and IOn_IN = TCR(0) and MSG_INn = TCR(2) else '0'; -- Phasematch.
DMA_DIS <= '1' when DMA_ACTIVE = '1' and BSY_INn = '1' else '0';
SER_ID <= '1' when SER /= x"00" and SER = not CSD else '0';
DRQ <= DRQ_I;
INT <= INT_I;
-- Pay attention: the SCSI bus is driven with inverted signals.
ACK_OUTn <= ACK_OUT_CTRLn when DMA_ACTIVE = '1' else not ICR(4); -- Valid in initiator mode.
REQ_OUTn <= REQ_OUT_CTRLn when DMA_ACTIVE = '1' else not TCR(3); -- Valid in Target mode.
BSY_OUTn <= '0' when BSY_OUT_CTRLn = '0' and TARG = '0' else -- Valid in initiator mode.
'0' when ICR(3) = '1' else '1';
ATN_OUTn <= not ICR(1); -- Valid in initiator mode.
SEL_OUTn <= not ICR(2); -- Valid in initiator mode.
IOn_OUT <= not TCR(0); -- Valid in Target mode.
CDn_OUT <= not TCR(1); -- Valid in Target mode.
MSG_OUTn <= not TCR(2); -- Valid in Target mode.
RST_OUTn <= not RST;
DB_OUTn <= not ODR;
DBP_OUTn <= not SPER;
CSD <= not DB_INn;
CSB <= not RST_INn & not BSY_INn & not REQ_INn & not MSG_INn & not CDn_IN & not IOn_IN & not SEL_INn & not DBP_INn;
BSR <= EDMA & DRQ_I & SPER & INT_I & PHSM & BSY_ERR & not ATN_INn & not ACK_INn;
-- Hi impedance control:
ATN_EN <= '1' when TARG = '0' else '0'; -- Initiator mode.
SEL_EN <= '1' when TARG = '0' else '0'; -- Initiator mode.
BSY_EN <= '1' when TARG = '0' else '0'; -- Initiator mode.
ACK_EN <= '1' when TARG = '0' else '0'; -- Initiator mode.
IO_EN <= '1' when TARG = '1' else '0'; -- Target mode.
CD_EN <= '1' when TARG = '1' else '0'; -- Target mode.
MSG_EN <= '1' when TARG = '1' else '0'; -- Target mode.
REQ_EN <= '1' when TARG = '1' else '0'; -- Target mode.
RST_EN <= '1' when RST = '1' else '0'; -- Open drain control.
-- Data enables:
DB_EN_I <= '1' when DATA_EN_CTRL = '1' else -- During Arbitration.
'1' when ICR(0) = '1' and TARG = '1' and DMA_SND = '1' else -- Target 'Send' mode.
'1' when ICR(0) = '1' and TARG = '0' and IOn_IN = '0' and PHSM = '1' else
'1' when ICR(6) = '1' else '0'; -- Test mode enable.
DB_EN <= DB_EN_I;
DBP_EN <= DB_EN_I;
I_REGISTERS: WF5380_REGISTERS
port map(
CLK => CLK,
RESETn => RESETn,
ADR => ADR,
DATA_IN => DATA_IN,
DATA_OUT => DATA_OUT,
DATA_EN => DATA_EN,
CSn => CSn,
RDn => RDn,
WRn => WRn,
RSTn => RST_INn,
RST => RST,
ARB_EN => ARB_EN,
DMA_ACTIVE => DMA_ACTIVE,
DMA_EN => DMA_EN,
BSY_DISn => BSY_DISn,
EOP_EN => EOP_EN,
PINT_EN => PINT_EN,
SPER => SPER,
TARG => TARG,
BLK => BLK,
DMA_DIS => DMA_DIS,
IDR_WR => IDR_WR,
ODR_WR => ODR_WR,
CHK_PAR => CHK_PAR,
AIP => AIP,
ARB => ARB,
LA => LA,
CSD => CSD,
CSB => CSB,
BSR => BSR,
ODR_OUT => ODR,
ICR_OUT => ICR,
TCR_OUT => TCR,
SER_OUT => SER,
SDS => SDS,
SDT => SDT,
SDI => SDI,
RPI => RPI
);
I_CONTROL: WF5380_CONTROL
port map(
CLK => CLK,
RESETn => RESETn,
BSY_INn => BSY_INn,
BSY_OUTn => BSY_OUT_CTRLn,
DATA_EN => DATA_EN_CTRL,
SEL_INn => SEL_INn,
ARB_EN => ARB_EN,
BSY_DISn => BSY_DISn,
RSTn => RST_INn,
ARB => ARB,
AIP => AIP,
LA => LA,
ACK_INn => ACK_INn,
ACK_OUTn => ACK_OUT_CTRLn,
REQ_INn => REQ_INn,
REQ_OUTn => REQ_OUT_CTRLn,
DACKn => DACKn,
READY => READY,
DRQ => DRQ_I,
TARG => TARG,
BLK => BLK,
PINT_EN => PINT_EN,
SPER => SPER,
SER_ID => SER_ID,
RPI => RPI,
DMA_EN => DMA_EN,
SDS => SDS,
SDT => SDT,
SDI => SDI,
EOP_EN => EOP_EN,
EOPn => EOPn,
PHSM => PHSM,
INT => INT_I,
IDR_WR => IDR_WR,
ODR_WR => ODR_WR,
CHK_PAR => CHK_PAR,
BSY_ERR => BSY_ERR,
DMA_SND => DMA_SND,
DMA_ACTIVE => DMA_ACTIVE
);
end STRUCTURE;

View File

@@ -0,0 +1,275 @@
----------------------------------------------------------------------
---- ----
---- WF5380 IP Core ----
---- ----
---- Description: ----
---- This model provides an asynchronous SCSI interface compa- ----
---- tible to the DP5380 from National Semiconductor and others. ----
---- ----
---- This file is the top level file with tree state buses. ----
---- ----
---- ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K9A 2009/06/20 WF
-- Initial Release.
--
library work;
use work.wf5380_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF5380_TOP is
port (
-- System controls:
CLK : in bit;
RESETn : in bit;
-- Address and data:
ADR : in std_logic_vector(2 downto 0);
DATA : inout std_logic_vector(7 downto 0);
-- Bus and DMA controls:
CSn : in bit;
RDn : in bit;
WRn : in bit;
EOPn : in bit;
DACKn : in bit;
DRQ : out bit;
INT : out bit;
READY : out bit;
-- SCSI bus:
DBn : inout std_logic_vector(7 downto 0);
DBPn : inout std_logic;
RSTn : inout std_logic;
BSYn : inout std_logic;
SELn : inout std_logic;
ACKn : inout std_logic;
ATNn : inout std_logic;
REQn : inout std_logic;
IOn : inout std_logic;
CDn : inout std_logic;
MSGn : inout std_logic
);
end entity WF5380_TOP;
architecture STRUCTURE of WF5380_TOP is
component WF5380_TOP_SOC
port (
-- System controls:
CLK : in bit;
RESETn : in bit;
ADR : in bit_vector(2 downto 0);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
CSn : in bit;
RDn : in bit;
WRn : in bit;
EOPn : in bit;
DACKn : in bit;
DRQ : out bit;
INT : out bit;
READY : out bit;
DB_INn : in bit_vector(7 downto 0);
DB_OUTn : out bit_vector(7 downto 0);
DB_EN : out bit;
DBP_INn : in bit;
DBP_OUTn : out bit;
DBP_EN : out bit;
RST_INn : in bit;
RST_OUTn : out bit;
RST_EN : out bit;
BSY_INn : in bit;
BSY_OUTn : out bit;
BSY_EN : out bit;
SEL_INn : in bit;
SEL_OUTn : out bit;
SEL_EN : out bit;
ACK_INn : in bit;
ACK_OUTn : out bit;
ACK_EN : out bit;
ATN_INn : in bit;
ATN_OUTn : out bit;
ATN_EN : out bit;
REQ_INn : in bit;
REQ_OUTn : out bit;
REQ_EN : out bit;
IOn_IN : in bit;
IOn_OUT : out bit;
IO_EN : out bit;
CDn_IN : in bit;
CDn_OUT : out bit;
CD_EN : out bit;
MSG_INn : in bit;
MSG_OUTn : out bit;
MSG_EN : out bit
);
end component;
--
signal ADR_IN : bit_vector(2 downto 0);
signal DATA_IN : bit_vector(7 downto 0);
signal DATA_OUT : bit_vector(7 downto 0);
signal DATA_EN : bit;
signal DB_INn : bit_vector(7 downto 0);
signal DB_OUTn : bit_vector(7 downto 0);
signal DB_EN : bit;
signal DBP_INn : bit;
signal DBP_OUTn : bit;
signal DBP_EN : bit;
signal RST_INn : bit;
signal RST_OUTn : bit;
signal RST_EN : bit;
signal BSY_INn : bit;
signal BSY_OUTn : bit;
signal BSY_EN : bit;
signal SEL_INn : bit;
signal SEL_OUTn : bit;
signal SEL_EN : bit;
signal ACK_INn : bit;
signal ACK_OUTn : bit;
signal ACK_EN : bit;
signal ATN_INn : bit;
signal ATN_OUTn : bit;
signal ATN_EN : bit;
signal REQ_INn : bit;
signal REQ_OUTn : bit;
signal REQ_EN : bit;
signal IOn_IN : bit;
signal IOn_OUT : bit;
signal IO_EN : bit;
signal CDn_IN : bit;
signal CDn_OUT : bit;
signal CD_EN : bit;
signal MSG_INn : bit;
signal MSG_OUTn : bit;
signal MSG_EN : bit;
begin
ADR_IN <= To_BitVector(ADR);
DATA_IN <= To_BitVector(DATA);
DATA <= To_StdLogicVector(DATA_OUT) when DATA_EN = '1' else (others => 'Z');
DB_INn <= To_BitVector(DBn);
DBn <= To_StdLogicVector(DB_OUTn) when DB_EN = '1' else (others => 'Z');
DBP_INn <= To_Bit(DBPn);
RST_INn <= To_Bit(RSTn);
BSY_INn <= To_Bit(BSYn);
SEL_INn <= To_Bit(SELn);
ACK_INn <= To_Bit(ACKn);
ATN_INn <= To_Bit(ATNn);
REQ_INn <= To_Bit(REQn);
IOn_IN <= To_Bit(IOn);
CDn_IN <= To_Bit(CDn);
MSG_INn <= To_Bit(MSGn);
DBPn <= '1' when DBP_OUTn = '1' and DBP_EN = '1' else
'0' when DBP_OUTn = '0' and DBP_EN = '1' else 'Z';
RSTn <= '1' when RST_OUTn = '1' and RST_EN = '1'else
'0' when RST_OUTn = '0' and RST_EN = '1' else 'Z';
BSYn <= '1' when BSY_OUTn = '1' and BSY_EN = '1' else
'0' when BSY_OUTn = '0' and BSY_EN = '1' else 'Z';
SELn <= '1' when SEL_OUTn = '1' and SEL_EN = '1' else
'0' when SEL_OUTn = '0' and SEL_EN = '1' else 'Z';
ACKn <= '1' when ACK_OUTn = '1' and ACK_EN = '1' else
'0' when ACK_OUTn = '0' and ACK_EN = '1' else 'Z';
ATNn <= '1' when ATN_OUTn = '1' and ATN_EN = '1' else
'0' when ATN_OUTn = '0' and ATN_EN = '1' else 'Z';
REQn <= '1' when REQ_OUTn = '1' and REQ_EN = '1' else
'0' when REQ_OUTn = '0' and REQ_EN = '1' else 'Z';
IOn <= '1' when IOn_OUT = '1' and IO_EN = '1' else
'0' when IOn_OUT = '0' and IO_EN = '1' else 'Z';
CDn <= '1' when CDn_OUT = '1' and CD_EN = '1' else
'0' when CDn_OUT = '0' and CD_EN = '1' else 'Z';
MSGn <= '1' when MSG_OUTn = '1' and MSG_EN = '1' else
'0' when MSG_OUTn = '0' and MSG_EN = '1' else 'Z';
I_5380: WF5380_TOP_SOC
port map(
CLK => CLK,
RESETn => RESETn,
ADR => ADR_IN,
DATA_IN => DATA_IN,
DATA_OUT => DATA_OUT,
DATA_EN => DATA_EN,
CSn => CSn,
RDn => RDn,
WRn => WRn,
EOPn => EOPn,
DACKn => DACKn,
DRQ => DRQ,
INT => INT,
READY => READY,
DB_INn => DB_INn,
DB_OUTn => DB_OUTn,
DB_EN => DB_EN,
DBP_INn => DBP_INn,
DBP_OUTn => DBP_OUTn,
DBP_EN => DBP_EN,
RST_INn => RST_INn,
RST_OUTn => RST_OUTn,
RST_EN => RST_EN,
BSY_INn => BSY_INn,
BSY_OUTn => BSY_OUTn,
BSY_EN => BSY_EN,
SEL_INn => SEL_INn,
SEL_OUTn => SEL_OUTn,
SEL_EN => SEL_EN,
ACK_INn => ACK_INn,
ACK_OUTn => ACK_OUTn,
ACK_EN => ACK_EN,
ATN_INn => ATN_INn,
ATN_OUTn => ATN_OUTn,
ATN_EN => ATN_EN,
REQ_INn => REQ_INn,
REQ_OUTn => REQ_OUTn,
REQ_EN => REQ_EN,
IOn_IN => IOn_IN,
IOn_OUT => IOn_OUT,
IO_EN => IO_EN,
CDn_IN => CDn_IN,
CDn_OUT => CDn_OUT,
CD_EN => CD_EN,
MSG_INn => MSG_INn,
MSG_OUTn => MSG_OUTn,
MSG_EN => MSG_EN
);
end STRUCTURE;

View File

@@ -0,0 +1,253 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- Address mark detector file. This part detects the address ----
---- mark in the incoming data stream in FM and also in MFM mode ----
---- and provides therewith synchronisation information for the ----
---- control state machine and for the data separator in the ----
---- transceiver unit. ----
---- ----
------------------------------- Some theory -------------------------------------
---- Frequency modulation FM: ----
---- The frequency modulation works as follows: ----
---- 1. every first pulse of the clock and data line is a clock. ----
---- 2. every second pulse is a data. ----
---- 3. a logic 1 is represented by two consecutive pulses (clock and data). ----
---- 4. a logic 0 is represented by one clock pulse and no data pulse. ----
---- 5. Hence there are a maximum of two pulses per data bit. ----
---- 6. one clock and one data pulse come together in one bit cell. ----
---- 7. the duration of a bit cell in FM is 4 microseconds. ----
---- 8. an ID address mark is represented as data FE with clock C7. ----
---- 9. a DATA address mark is represented as data FB with clock C7. ----
---- Examples: ----
---- Binary data 1 1 0 0 1 0 1 1 is represented in FM as follows: ----
---- 1111101011101111 ----
---- the FE data 1 1 1 1 1 1 1 0 is represented as follows: ----
---- 1111111111111110 ----
---- with C7 clock mask 1 1 0 0 0 1 1 1 which masks the clock pulses there ----
---- results: 1111010101111110 this is the ID address mark. ----
---- the FB data 1 1 1 1 1 0 1 1 is represented as follows: ----
---- 1111111111101111 ----
---- with C7 clock mask 1 1 0 0 0 1 1 1 which masks the clock pulses there ----
---- results: 1111010101101111 this is the DATA address mark. ----
---- the F8 data 1 1 1 1 1 0 0 0 is represented as follows: ----
---- 1111111111101010 ----
---- with C7 clock mask 1 1 0 0 0 1 1 1 which masks the clock pulses there ----
---- results: 1111010101101010 this is the deleted DATA mark. ----
---- ----
---- ----
---- Modified frequency modulation MFM: ----
---- The modified frequency modulation works as follows: ----
---- 1. every first pulse of the clock and data line is a clock. ----
---- 2. every second pulse is a data. ----
---- 3. a logic 1 is represented by no clock but a data pulse. ----
---- 4. a logic 0 is represented by a clock pulse and no data pulse if ----
---- following a 0. ----
---- 5. a logic 0 is represented by no pulse if following a 1. ----
---- 6. Hence there are a maximum of one pulse per data bit. ----
---- 7. one clock and one data pulse form together one bit cell. ----
---- 8. the duration of a bit cell in MFM is 2 microseconds. ----
---- 9. an address mark sync is represented as data A1 with missing clock ----
---- pulse between bit 4 and 5. ----
---- Examples: ----
---- Binary data FE 1 1 1 1 1 1 1 0 is represented in MFM as follows: ----
---- 0101010101010100 this is the ID address mark. ----
---- Binary data FB 1 1 1 1 1 0 1 1 is represented in MFM as follows: ----
---- 0101010101000101 this is the DATA address mark. ----
---- Binary data F8 1 1 1 1 1 0 0 0 is represented in MFM as follows: ----
---- 0101010101001010 this is the deleted DATA address mark. ----
---- the A1 data 1 0 1 0 0 0 0 1 is represented as follows: ----
---- 0100010010101001 ----
---- with the missing clock pulse between bits 4 and 5 there results: ----
---- results: 0100010010001001 this is the address mark sync. ----
---- ----
---- Both MFM and FM are during read and write shifted with most significant ----
---- bit (MSB) first. During the FM address marks are written without a ----
---- SYNC pulse the MFM coded data requires a synchronisation (A1 with ----
---- missing clock pulse because at the beginning of the data stream it is ----
---- not defined wether a clock pulse or a data pulse appears first. In FM ----
---- coding the first pulse is in any case a clock pulse. ----
---------------------------------------------------------------------------------
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2006A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_AM_DETECTOR is
port(
-- System control
CLK : in bit;
RESETn : in bit;
-- Controls:
DDEn : in bit;
-- Serial data and clock:
DATA : in bit;
DATA_STRB : in bit;
-- Address mark detector:
ID_AM : out bit; -- ID address mark strobe.
DATA_AM : out bit; -- Data address mark strobe.
DDATA_AM : out bit -- Deleted data address mark strobe.
);
end WF1772IP_AM_DETECTOR;
architecture BEHAVIOR of WF1772IP_AM_DETECTOR is
signal SHIFT : bit_vector(15 downto 0);
signal SYNC : boolean;
signal ID_AM_I : bit;
signal DATA_AM_I : bit;
signal DDATA_AM_I : bit;
begin
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT <= (others => '0');
elsif CLK = '1' and CLK' event then
if DATA_STRB = '1' then
-- MSB first leads to a shift left operation.
SHIFT <= SHIFT(14 downto 0) & DATA;
elsif DDEn = '0' and SHIFT = "0100010010001001" then -- This is the synchronisation in MFM.
SHIFT <= (others => '0');
end if;
end if;
end process SHIFTREG;
MFM_SYNCLOCK: process(RESETn, CLK)
-- The SYNC pulse is generated in MFM mode only when the sync character
-- appears in the shift register (A1 sync mark, see file header).
-- After the sync character is detected, the sync time counter is loaded
-- with a value of 17. During counting the following 17 read clock pulses
-- down, the SYNC is true. After exactly 16 pulses the address mark is
-- detected if the pattern in the shift register fits one of the address
-- marks. The address mark pulses are valid for one read clock cycle until
-- SYNC goes low again. This mechanism is used to detect the correct address
-- marks in the MFM data stream during the type III read track command.
-- This is an improvement over the original WD1772 chip.
variable TMP : std_logic_vector(4 downto 0);
begin
if RESETn = '0' then
TMP := "00000";
elsif CLK = '1' and CLK' event then
if SHIFT = "0100010010001001" and DDEn = '0' then
TMP := "10001"; -- Load sync time counter.
elsif DATA_STRB = '1' and TMP > "00000" then
TMP := TMP - '1';
end if;
end if;
case TMP is
when "00000" => SYNC <= false;
when others => SYNC <= true;
end case;
end process MFM_SYNCLOCK;
-- The addressmark is nominally valid for one data pulse cycle (1us, 2us, 4us).
-- The pulse is shorter due to the fact that the detected address marks change the
-- state of the control state machine and so clear the address mark shift register...
ID_AM_I <= '1' when DDEn = '1' and SHIFT = "1111010101111110" else
'1' when DDEn = '0' and SHIFT = "0101010101010100" and SYNC = true else '0';
DATA_AM_I <= '1' when DDEn = '1' and SHIFT = "1111010101101111" else
-- Normal data address mark...
'1' when DDEn = '0' and SHIFT = "0101010101000101" and SYNC = true else '0';
DDATA_AM_I <= '1' when DDEn = '1' and SHIFT = "1111010101101010" else
-- ... and deleted address mark in MFM mode:
'1' when DDEn = '0' and SHIFT = "0101010101001010" and SYNC = true else '0';
ADRMARK_STROBES: process(RESETn, CLK)
-- ... nevertheless The controller and the transceiver require ID address mark strobes
-- and DATA address mark strobes. Therefore this process provides these strobe
-- signals independant of any 'feedbacks' like pulse shortening by the controller
-- state machine itself.
variable ID_AM_LOCK, DATA_AM_LOCK, DDATA_AM_LOCK : boolean;
begin
if RESETn = '0' then
ID_AM_LOCK := false;
DATA_AM_LOCK := false;
ID_AM <= '0';
DATA_AM <= '0';
elsif CLK = '1' and CLK' event then
-- ID address mark:
if ID_AM_I = '1' and ID_AM_LOCK = false then
ID_AM <= '1';
ID_AM_LOCK := true;
elsif ID_AM_I = '0' then
ID_AM <= '0';
ID_AM_LOCK := false;
else
ID_AM <= '0';
end if;
-- Data address mark:
if DATA_AM_I = '1' and DATA_AM_LOCK = false then
DATA_AM <= '1';
DATA_AM_LOCK := true;
elsif DATA_AM_I = '0' then
DATA_AM <= '0';
DATA_AM_LOCK := false;
else
DATA_AM <= '0';
end if;
-- Deleted data address mark:
if DDATA_AM_I = '1' and DDATA_AM_LOCK = false then
DDATA_AM <= '1';
DDATA_AM_LOCK := true;
elsif DDATA_AM_I = '0' then
DDATA_AM <= '0';
DDATA_AM_LOCK := false;
else
DDATA_AM <= '0';
end if;
end if;
end process ADRMARK_STROBES;
end architecture BEHAVIOR;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- The CRC cyclic redundancy checker unit. Further description ----
---- see below. ----
---- ----
---- Working principle of the CRC generator and verify unit: ----
---- During read operation: ----
---- The CRC generator is switched on via after the detection of ----
---- the address ID of the data ID mark. The CRC generation last ----
---- in case of the address ID until the lenght byte is read. ----
---- In case of generation after the data address mark the CRC ----
---- generator is activated until the last data byte is read. ----
---- The number of data bytes to be read depends on the LENGHT ----
---- information in the header file. After generation of the CRC ----
---- the CRC_GEN is switched off and the VERIFY procedure begins ----
---- by activating CRC_VERIFY. The previously generated CRC is ----
---- then compared (serially) with the two consecutive read CRC ----
---- bytes. The CRC error appeas, when the comparision fails. ----
---- During write operation: ----
---- The CRC generator is switched on via after the detection of ----
---- the address ID of the data ID mark. The CRC generation last ----
---- in case of the address ID until the lenght byte is read. ----
---- In case of generation after the data address mark the CRC ----
---- generator is activated until the last data byte is read. ----
---- The number of data bytes to be read depends on the LENGHT ----
---- information in the header file. After the generation of the ----
---- two CRC bytes, the write out process begins by activating ----
---- CRC_SHFTOUT. The CRC data appears in this case serially on ----
---- the CRC_SDOUT. ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2006A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- CRC_SHIFT has now synchronous reset to meeet preset behaviour.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_CRC_LOGIC is
port(
-- System control
CLK : in bit;
RESETn : in bit;
DISK_RWn : in bit;
-- Preset controls:
DDEn : in bit;
ID_AM : in bit;
DATA_AM : in Bit;
DDATA_AM : in Bit;
-- CRC unit:
SD : in bit; -- Serial data input.
CRC_STRB : in bit; -- Data strobe.
CRC_2_DISK : in bit; -- Forces the unit to flush the CRC remainder.
CRC_PRES : in bit; -- Presets the CRC unit during write to disk.
CRC_SDOUT : out bit; -- Serial data output.
CRC_ERR : out bit -- Indicates CRC error.
);
end WF1772IP_CRC_LOGIC;
architecture BEHAVIOR of WF1772IP_CRC_LOGIC is
signal CRC_SHIFT : bit_vector(15 downto 0);
begin
P_CRC: process
-- The shift register is initialised with appropriate values in HD or DD mode.
-- In theory the shift register should be preset to ones. Due to a latency of one byte
-- in FM mode or 4 bytes in MFM mode it is necessary to preset the shift register with
-- the CRC values of this ID address mark, data address mark and the A1 sync bytes. The
-- latency is caused by the addressmark detector which needs one or 4 byte time(s) for
-- detection. The CRC unit therefore starts with every detection of an address mark and
-- ends if the CRC unit is flushed.
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
CRC_SHIFT <= (others => '1');
elsif CRC_2_DISK = '1' then
if CRC_STRB = '1' then
CRC_SHIFT <= CRC_SHIFT(14 downto 0) & '0';
end if;
elsif CRC_PRES = '1' then -- Preset during write sector or write track command.
CRC_SHIFT <= x"FFFF";
elsif DDEn = '1' and ID_AM = '1' then -- DD mode and ID address mark detected.
CRC_SHIFT <= x"EF21"; -- The CRC-CCITT for data x"FE" is x"EF21"
elsif DDEn = '1' and DATA_AM = '1' then -- DD mode and data address mark detected.
CRC_SHIFT <= x"BF84"; -- The CRC-CCITT for data x"FB" is x"BF84"
elsif DDEn = '1' and DDATA_AM = '1' then -- DD mode and deleted data address mark detected.
CRC_SHIFT <= x"8FE7"; -- The CRC-CCITT for data x"F8" is x"8FE7"
elsif DDEn = '0' and ID_AM = '1' then -- HD mode and ID address mark detected.
CRC_SHIFT <= x"B230"; -- The CRC-CCITT for data x"A1A1A1FE" is x"B230"
elsif DDEn = '0' and DATA_AM = '1' then -- HD mode and data address mark detected.
CRC_SHIFT <= x"E295"; -- The CRC-CCITT for data x"A1A1A1FB" is x"E295"
elsif DDEn = '0' and DDATA_AM = '1' then -- HD mode and deleted data address mark detected.
CRC_SHIFT <= x"D2F6"; -- The CRC-CCITT for data x"A1A1A1F8" is x"D2F6"
elsif CRC_STRB = '1' then
-- CRC-CCITT (xFFFF):
-- the polynomial is G(x) = x^16 + x^12 + x^5 + 1
-- In this mode the CRC is encoded. In read from disk mode, the encoding works as CRC
-- verification. In this operating condition the ID or the data field is compared
-- against the CRC checksum. if there are no errors, the shift register's value is
-- x"0000" after the last bit of the checksum is shifted in. In write to disk mode the
-- CRC linear feedback shift register (lfsr) works to generate the CRC remainder of the
-- ID or data field.
CRC_SHIFT <= CRC_SHIFT(14 downto 12) & (CRC_SHIFT(15) xor CRC_SHIFT(11) xor SD) &
CRC_SHIFT(10 downto 5) & (CRC_SHIFT(15) xor CRC_SHIFT(4) xor SD) &
CRC_SHIFT(3 downto 0) & (CRC_SHIFT(15) xor SD);
end if;
end process P_CRC;
CRC_SDOUT <= CRC_SHIFT(15);
CRC_ERR <= '0' when CRC_SHIFT = x"0000" else '1';
end architecture BEHAVIOR;

View File

@@ -0,0 +1,426 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- The digital PLL is responsible to detect the incoming serial ----
---- data stream and provide a system clock synchronous signal ----
---- containing the data and clock information. ----
---- To understand how the code works in detail refer to the free ----
---- US patent no. 4,780,844. ----
---- ----
---- Attention: The settings for TOP and BOTTOM, which control ----
---- the PLL frequency and for PHASE_CORR which control the PLL ----
---- phase are rather critical for a good read condition! To test ----
---- the PLL in the WD1772 compatible core do the following: ----
---- Sample on an oscilloscope on one channel the falling edge of ----
---- the RDn pulse and on the other channel the PLL_DSTRB. The ----
---- RDn must be located exactly between the PLL_DSTRB pulses. ----
---- Otherwise, the parameters TOP, BOTTOM and PHASE_CORR have to ----
---- be optimized. ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2006A 2006/06/03 WF
-- Initial Release: the MFM portion for HD and DD floppies is tested.
-- The FM mode (DDEn = '1') is not completely tested due to lack of FM
-- drives.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K7B 2006/12/29 WF
-- Introduced several improvements based on a very good examination
-- of the pll code by Jean Louis-Guerin.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K8B 2008/12/24 WF
-- Improvement of the INPORT process.
-- Bugfix of the FREQ_AMOUNT counter: now stops if its value is zero.
-- Several changes concerning the PLL parameters to improve the
-- stability of the PLL.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_DIGITAL_PLL is
generic(
-- The valid range of the period counter of the PLL is given by the TOP and BOTTOM
-- limits. The counter range is therefore BOTTOM <= counter value <= TOP.
-- The generic PHASE_CORR is responsible fo the center setting of PLL_DSTRB concerning
-- the RDn period.
-- The nominal frequency setting is 128. So it is recommended to use TOP and BOTTOM
-- settings symmetrically around 128. If TOP = BOTTOM = 128, the frequency control
-- is disabled. TOP + PHASE_CORR may not exceed a value of 255. BOTTOM - PHASE_CORR
-- may not drop below zero.
TOP : integer range 0 to 255 := 152; -- +18.0%
BOTTOM : integer range 0 to 255 := 104; -- -18.0%
PHASE_CORR : integer range 0 to 128 := 75
);
port(
-- System control
CLK : in bit; -- 16MHz clock.
RESETn : in bit;
-- Controls
DDEn : in bit; -- Double density enable.
HDTYPE : in bit; -- This control is '1' when HD disks are inserted.
DISK_RWn : in bit; -- Read write control.
-- Data and clock lines
RDn : in bit; -- Read signal from the disk.
PLL_D : out bit; -- Synchronous read signal.
PLL_DSTRB : out bit -- Read strobe.
);
end WF1772IP_DIGITAL_PLL;
architecture BEHAVIOR of WF1772IP_DIGITAL_PLL is
signal RD_In : bit;
signal UP, DOWN : bit;
signal PHASE_DECREASE : bit;
signal PHASE_INCREASE : bit;
signal HI_STOP, LOW_STOP : bit;
signal PER_CNT : std_logic_vector(7 downto 0);
signal ADDER_IN : std_logic_vector(7 downto 0);
signal ADDER_MSBs : bit_vector(2 downto 0);
signal RD_PULSE : bit;
signal ROLL_OVER : bit;
signal HISTORY_REG : bit_vector(1 downto 0);
signal ERROR_HISTORY : integer range 0 to 2;
begin
INPORT: process
-- This process is necessary due to the poor quality of the rising
-- edge of RDn. Let it work on the negative clock edge.
begin
wait until CLK = '0' and CLK' event;
RD_In <= RDn;
end process INPORT;
EDGEDETECT: process(RESETn, CLK)
-- This process forms a falling edge detector for the incoming
-- data read port. The output (RD_PULSE) goes high for exactly
-- one clock period after the RDn is low and the positive
-- clock edge is detected.
variable LOCK : boolean;
begin
if RESETn = '0' then
RD_PULSE <= '0';
LOCK := false;
elsif CLK = '1' and CLK' event then
if DISK_RWn = '0' then -- Disable detector in write mode.
RD_PULSE <= '0';
elsif RD_In = '0' and LOCK = false then
RD_PULSE <= '1'; -- READ_PULSE is inverted against RDn
LOCK := true;
elsif RD_In = '1' then
LOCK := false;
RD_PULSE <= '0';
else
RD_PULSE <= '0';
end if;
end if;
end process EDGEDETECT;
PERIOD_CNT: process(RESETn, CLK)
-- This process provides the nominal variable added to the adder. To achieve a good
-- settling time of the PLL in all cases, the period counter is controlled via the DDEn
-- and HDTYPE flags respective to its added value. Be aware, that in case of adding "10"
-- or "11", the TOP value may be exceeded or the period counter may drop below the BOTTOM
-- value. The higher the value added, the faster will be the settling time of phase locked
-- loop .
begin
if RESETn = '0' then
PER_CNT <= "10000000"; -- Initial value is 128.
elsif CLK = '1' and CLK' event then
if UP = '1' then
PER_CNT <= PER_CNT + '1';
elsif DOWN = '1' then
PER_CNT <= PER_CNT - '1';
end if;
end if;
end process PERIOD_CNT;
HI_STOP <= '1' when PER_CNT >= TOP else '0';
LOW_STOP <= '1' when PER_CNT <= BOTTOM else '0';
ADDER_IN <= -- This DISK_RWn = '0' implementation keeps the last phase information
-- of the PLL in read from disk mode. It should be a good solution concer-
-- ning alternative read write cycles.
"10000000" when DISK_RWn = '0' else -- Nominal value for write to disk.
PER_CNT + PHASE_CORR when PHASE_INCREASE = '1' else -- Phase lags.
PER_CNT - PHASE_CORR when PHASE_DECREASE = '1' else -- Phase leeds.
PER_CNT; -- No phase correction;
ADDER: process(RESETn, CLK, DDEn, HDTYPE)
-- Clock adjustment: The clock cycle is 62.5ns for the 16MHz system clock.
-- The offset (LSBs) of the adder input is chosen to be conform with the required
-- rollover period in the different DDEn and HDTYPE modi as follows:
-- With a nominal adder input term of 128:
-- The adder rolls over every 4us for DDEn = 1 and HDTYPE = 0.
-- The adder rolls over every 2us for DDEn = 1 and HDTYPE = 1.
-- The adder rolls over every 2us for DDEn = 0 and HDTYPE = 0.
-- The adder rolls over every 1us for DDEn = 0 and HDTYPE = 1.
-- The given times are the half of a data period time in MFM or FM.
variable ADDER_DATA : std_logic_vector(12 downto 0);
begin
if RESETn = '0' then
ADDER_DATA := (others => '0');
elsif CLK = '1' and CLK' event then
ADDER_DATA := ADDER_DATA + ADDER_IN;
end if;
--
case DDEn & HDTYPE is
when "01" => -- MFM mode using HD disks, results in 1us inspection period:
ADDER_MSBs <= To_BitVector(ADDER_DATA(10 downto 8));
when "00" => -- MFM mode using DD disks, results in 2us inspection period:
ADDER_MSBs <= To_BitVector(ADDER_DATA(11 downto 9));
when "11" => -- FM mode using HD disks, results in 2us inspection period:
ADDER_MSBs <= To_BitVector(ADDER_DATA(11 downto 9));
when "10" => -- FM mode using DD disks, results in 4us inspection period:
ADDER_MSBs <= To_BitVector(ADDER_DATA(12 downto 10));
end case;
end process ADDER;
ROLLOVER: process(RESETn, CLK)
-- This process forms a falling edge detector for the detection
-- of the adder's rollover time. The output goes low for exactly
-- one clock period after the rollover is detected and the positive
-- clock edge appears.
variable LOCK : boolean;
begin
if RESETn = '0' then
ROLL_OVER <= '0';
LOCK := false;
elsif CLK = '1' and CLK' event then
if ADDER_MSBs /= "111" and LOCK = false then
ROLL_OVER <= '1';
LOCK := true;
elsif ADDER_MSBs = "111" then
LOCK := false;
ROLL_OVER <= '0';
else
ROLL_OVER <= '0';
end if;
end if;
end process ROLLOVER;
PLL_DSTRB <= ROLL_OVER;
DATA_FLIP_FLOP: process(RESETn, CLK, RD_PULSE)
-- This flip-flop is responsible for 'catching' the read pulses of the
-- serial data input.
begin
if RESETn = '0' then
PLL_D <= '0'; -- Asynchronous reset.
elsif CLK = '1' and CLK' event then
if RD_PULSE = '1' then
PLL_D <= '1'; -- Read pulse detected.
elsif ROLL_OVER = '1' then
PLL_D <= '0';
end if;
end if;
end process DATA_FLIP_FLOP;
WIN_HISTORY: process(RESETn, CLK)
begin
if RESETn = '0' then
HISTORY_REG <= "00";
elsif CLK = '1' and CLK' event then
if RD_PULSE = '1' then
HISTORY_REG <= ADDER_MSBs(2) & HISTORY_REG(1);
end if;
end if;
end process WIN_HISTORY;
-- Error history:
-- This signal indicates the number of consequtive levels of the adder's
-- MSB and the history register as shown in the following table. The default
-- setting of 0 was added to compile with the Xilinx ISE.
ERROR_HISTORY <= 2 when ADDER_MSBs(2) = '0' and HISTORY_REG = "00" else -- Speed strongly up.
1 when ADDER_MSBs(2) = '0' and HISTORY_REG = "01" else -- Speed up.
0 when ADDER_MSBs(2) = '0' and HISTORY_REG = "10" else -- o.k.
0 when ADDER_MSBs(2) = '0' and HISTORY_REG = "11" else -- Now adjusted.
0 when ADDER_MSBs(2) = '1' and HISTORY_REG = "00" else -- Now adjusted.
0 when ADDER_MSBs(2) = '1' and HISTORY_REG = "01" else -- o.k.
1 when ADDER_MSBs(2) = '1' and HISTORY_REG = "10" else -- Slow down.
2 when ADDER_MSBs(2) = '1' and HISTORY_REG = "11" else 0; -- Slow strongly down.
FREQUENCY_DECODER: process(RESETn, CLK, HI_STOP, LOW_STOP)
-- The frequency decoder controls the period of the data inspection window respective to the
-- ERROR_HISTORY for the 11 bit adder is as follows:
-- ERROR_HISTORY = 0:
-- -> no correction necessary <-
-- ERROR_HISTORY = 1:
-- MSBs input: 7 6 5 4 3 2 1 0
-- Correction output: -3 -2 -1 0 0 +1 +2 +3
-- ERROR_HISTORY = 2:
-- MSBs input: 7 6 5 4 3 2 1 0
-- Correction output: -4 -3 -2 -1 +1 +2 +3 +4
-- The most significant bit of the FREQ_AMOUNT controls incrementation or decrementation
-- of the adder (0 is up).
variable FREQ_AMOUNT: std_logic_vector(3 downto 0);
begin
if RESETn = '0' then
FREQ_AMOUNT := "0000";
elsif CLK = '1' and CLK' event then
if RD_PULSE = '1' then -- Load the frequency amount register.
case ERROR_HISTORY is
when 2 =>
case ADDER_MSBs is
when "000" => FREQ_AMOUNT := "0100";
when "001" => FREQ_AMOUNT := "0011";
when "010" => FREQ_AMOUNT := "0010";
when "011" => FREQ_AMOUNT := "0001";
when "100" => FREQ_AMOUNT := "1001";
when "101" => FREQ_AMOUNT := "1010";
when "110" => FREQ_AMOUNT := "1011";
when "111" => FREQ_AMOUNT := "1100";
end case;
when 1 =>
case ADDER_MSBs is
when "000" => FREQ_AMOUNT := "0011";
when "001" => FREQ_AMOUNT := "0010";
when "010" => FREQ_AMOUNT := "0001";
when "011" => FREQ_AMOUNT := "0000";
when "100" => FREQ_AMOUNT := "1000";
when "101" => FREQ_AMOUNT := "1001";
when "110" => FREQ_AMOUNT := "1010";
when "111" => FREQ_AMOUNT := "1011";
end case;
when others =>
FREQ_AMOUNT := "0000";
end case;
elsif FREQ_AMOUNT(2 downto 0) > "000" then
FREQ_AMOUNT := FREQ_AMOUNT - '1'; -- Modify the frequency amount register.
end if;
end if;
--
if FREQ_AMOUNT(3) = '0' and FREQ_AMOUNT(2 downto 0) /= "000" and HI_STOP = '0' then
-- FREQ_AMOUNT(3) = '0' means Frequency is too low. Count up when counter is not at HI_STOP.
UP <= '1';
DOWN <= '0';
elsif FREQ_AMOUNT(3) = '1' and FREQ_AMOUNT (2 downto 0) /= "000" and LOW_STOP = '0' then
-- FREQ_AMOUNT(3) = '1' means Frequency is too high. Count down when counter is not at LOW_STOP.
UP <= '0';
DOWN <= '1';
else
UP <= '0';
DOWN <= '0';
end if;
end process FREQUENCY_DECODER;
PHASE_DECODER: process(RESETn, CLK)
-- The phase decoder depends on the value of ADDER_MSBs. If the phase leeds, the most significant bit
-- of PHASE_AMOUNT indicates with a '0', that the next rollover should appear earlier. In case of a
-- phase lag, the next rollover should come later (indicated by a '1' of the most significant bit of
-- PHASE_AMOUNT).
-- This implementation gives the freedom to adjust the phase amount individually for every mode
-- depending on DDEn and HDTYPE.
variable PHASE_AMOUNT: std_logic_vector(5 downto 0);
begin
if RESETn = '0' then
PHASE_AMOUNT := "000000";
elsif CLK = '1' and CLK' event then
if RD_PULSE = '1' and DDEn = '1' and HDTYPE = '0' then -- FM mode, single density.
case ADDER_MSBs is -- Multiplier: 4.
when "000" => PHASE_AMOUNT := "010000";
when "001" => PHASE_AMOUNT := "001101";
when "010" => PHASE_AMOUNT := "001000";
when "011" => PHASE_AMOUNT := "000100";
when "100" => PHASE_AMOUNT := "100100";
when "101" => PHASE_AMOUNT := "101000";
when "110" => PHASE_AMOUNT := "101100";
when "111" => PHASE_AMOUNT := "110000";
end case;
elsif RD_PULSE = '1' and DDEn = '1' and HDTYPE = '1' then -- FM mode, double density
case ADDER_MSBs is -- Multiplier: 2.
when "000" => PHASE_AMOUNT := "001000";
when "001" => PHASE_AMOUNT := "000110";
when "010" => PHASE_AMOUNT := "000100";
when "011" => PHASE_AMOUNT := "000010";
when "100" => PHASE_AMOUNT := "100010";
when "101" => PHASE_AMOUNT := "100100";
when "110" => PHASE_AMOUNT := "100110";
when "111" => PHASE_AMOUNT := "101000";
end case;
elsif RD_PULSE = '1' and DDEn = '0' and HDTYPE = '0' then -- MFM mode, single density
case ADDER_MSBs is -- Multiplier: 2.
when "000" => PHASE_AMOUNT := "000110";
when "001" => PHASE_AMOUNT := "000100";
when "010" => PHASE_AMOUNT := "000011";
when "011" => PHASE_AMOUNT := "000010";
when "100" => PHASE_AMOUNT := "100010";
when "101" => PHASE_AMOUNT := "100011";
when "110" => PHASE_AMOUNT := "100100";
when "111" => PHASE_AMOUNT := "100110";
end case;
elsif RD_PULSE = '1' and DDEn = '0' and HDTYPE = '1' then -- MFM mode, double density.
case ADDER_MSBs is -- Multiplier: 1.
when "000" => PHASE_AMOUNT := "000100";
when "001" => PHASE_AMOUNT := "000011";
when "010" => PHASE_AMOUNT := "000010";
when "011" => PHASE_AMOUNT := "000001";
when "100" => PHASE_AMOUNT := "100001";
when "101" => PHASE_AMOUNT := "100010";
when "110" => PHASE_AMOUNT := "100011";
when "111" => PHASE_AMOUNT := "100100";
end case;
else -- Modify phase amount register:
if PHASE_AMOUNT(4 downto 0) > x"0" then
PHASE_AMOUNT := PHASE_AMOUNT - 1;
end if;
end if;
end if;
--
if PHASE_AMOUNT(5) = '0' and PHASE_AMOUNT(4 downto 0) > x"0" then
-- PHASE_AMOUNT(5) = '0' means, that the phase leeds.
PHASE_INCREASE <= '1'; -- Speed phase up, accelerate next rollover.
PHASE_DECREASE <= '0';
elsif PHASE_AMOUNT(5) = '1' and PHASE_AMOUNT(4 downto 0) > x"0" then
-- PHASE_AMOUNT(5) = '1' means, that the phase lags.
PHASE_INCREASE <= '0';
PHASE_DECREASE <= '1'; -- Speed phase down, delay of next rollover.
else
PHASE_INCREASE <= '0';
PHASE_DECREASE <= '0';
end if;
end process PHASE_DECODER;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,232 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- This is the package file containing the component ----
---- declarations. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2006A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Removed CRC_BUSY.
library ieee;
use ieee.std_logic_1164.all;
package WF1772IP_PKG is
-- component declarations:
component WF1772IP_AM_DETECTOR
port(
CLK : in bit;
RESETn : in bit;
DDEn : in bit;
DATA : in bit;
DATA_STRB : in bit;
ID_AM : out bit;
DATA_AM : out bit;
DDATA_AM : out bit
);
end component;
component WF1772IP_CONTROL
port(
CLK : in bit;
RESETn : in bit;
A1, A0 : in bit;
RWn : in bit;
CSn : in bit;
DDEn : in bit;
DR : in bit_vector(7 downto 0);
CMD : in std_logic_vector(7 downto 0);
DSR : in std_logic_vector(7 downto 0);
TR : in std_logic_vector(7 downto 0);
SR : in std_logic_vector(7 downto 0);
MO : out bit;
WR_PR : out bit;
SPINUP_RECTYPE : out bit;
SEEK_RNF : out bit;
CRC_ERRFLAG : out bit;
LOST_DATA_TR00 : out bit;
DRQ : out bit;
DRQ_IPn : out bit;
BUSY : out bit;
AM_2_DISK : out bit;
ID_AM : in bit;
DATA_AM : in bit;
DDATA_AM : in bit;
CRC_ERR : in bit;
CRC_PRES : out bit;
TR_PRES : out bit;
TR_CLR : out bit;
TR_INC : out bit;
TR_DEC : out bit;
SR_LOAD : out bit;
SR_INC : out bit;
TRACK_NR : out std_logic_vector(7 downto 0);
DR_CLR : out bit;
DR_LOAD : out bit;
SHFT_LOAD_SD : out bit;
SHFT_LOAD_ND : out bit;
CRC_2_DISK : out bit;
DSR_2_DISK : out bit;
FF_2_DISK : out bit;
PRECOMP_EN : out bit;
DATA_STRB : in bit;
DISK_RWn : out bit;
WPRTn : in bit;
TRACK00n : in bit;
IPn : in bit;
DIRC : out bit;
STEP : out bit;
WG : out bit;
INTRQ : out bit
);
end component;
component WF1772IP_CRC_LOGIC
port(
CLK : in bit;
RESETn : in bit;
DDEn : in bit;
DISK_RWn : in bit;
ID_AM : in bit;
DATA_AM : in bit;
DDATA_AM : in bit;
SD : in bit;
CRC_STRB : in bit;
CRC_2_DISK : in bit;
CRC_PRES : in bit;
CRC_SDOUT : out bit;
CRC_ERR : out bit
);
end component;
component WF1772IP_DIGITAL_PLL
port(
CLK : in bit;
RESETn : in bit;
DDEn : in bit;
HDTYPE : in bit;
DISK_RWn : in bit;
RDn : in bit;
PLL_D : out bit;
PLL_DSTRB : out bit
);
end component;
component WF1772IP_REGISTERS
port(
CLK : in bit;
RESETn : in bit;
CSn : in bit;
ADR : in bit_vector(1 downto 0);
RWn : in bit;
DATA_IN : in std_logic_vector (7 downto 0);
DATA_OUT : out std_logic_vector (7 downto 0);
DATA_EN : out bit;
CMD : out std_logic_vector(7 downto 0);
SR : out std_logic_vector(7 downto 0);
TR : out std_logic_vector(7 downto 0);
DSR : out std_logic_vector(7 downto 0);
DR : out bit_vector(7 downto 0);
SD_R : in bit;
DATA_STRB : in bit;
DR_CLR : in bit;
DR_LOAD : in bit;
TR_PRES : in bit;
TR_CLR : in bit;
TR_INC : in bit;
TR_DEC : in bit;
TRACK_NR : in std_logic_vector(7 downto 0);
SR_LOAD : in bit;
SR_INC : in bit;
SHFT_LOAD_SD : in bit;
SHFT_LOAD_ND : in bit;
MOTOR_ON : in bit;
WRITE_PROTECT : in bit;
SPINUP_RECTYPE : in bit;
SEEK_RNF : in bit;
CRC_ERRFLAG : in bit;
LOST_DATA_TR00 : in bit;
DRQ : in bit;
DRQ_IPn : in bit;
BUSY : in bit;
DDEn : in bit
);
end component;
component WF1772IP_TRANSCEIVER
port(
CLK : in bit;
RESETn : in bit;
DDEn : in bit;
HDTYPE : in bit;
ID_AM : in bit;
DATA_AM : in bit;
DDATA_AM : in bit;
SHFT_LOAD_SD : in bit;
DR : in bit_vector(7 downto 0);
PRECOMP_EN : in bit;
AM_TYPE : in bit;
AM_2_DISK : in bit;
CRC_2_DISK : in bit;
DSR_2_DISK : in bit;
FF_2_DISK : in bit;
SR_SDOUT : in std_logic;
CRC_SDOUT : in bit;
WRn : out bit;
PLL_DSTRB : in bit;
PLL_D : in bit;
WDATA : out bit;
DATA_STRB : out bit;
SD_R : out bit
);
end component;
end WF1772IP_PKG;

View File

@@ -0,0 +1,264 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- This file models all the five WD1772 registers: DATA-, ----
---- COMMAND-, SECTOR-, TRACK- and STATUS register as also the ----
---- shift register. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2006A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_REGISTERS is
port(
-- System control:
CLK : in bit;
RESETn : in bit;
-- Bus interface:
CSn : in bit;
ADR : in bit_vector(1 downto 0);
RWn : in bit;
DATA_IN : in std_logic_vector (7 downto 0);
DATA_OUT : out std_logic_vector (7 downto 0);
DATA_EN : out bit;
-- FDC data:
CMD : out std_logic_vector(7 downto 0); -- Command register.
SR : out std_logic_vector(7 downto 0); -- Sector register.
TR : out std_logic_vector(7 downto 0); -- Track register.
DSR : out std_logic_vector(7 downto 0); -- Data shift register.
DR : out bit_vector(7 downto 0); -- Data register.
-- Serial data and clock strobes (in and out):
DATA_STRB : in bit; -- Strobe for the incoming data.
SD_R : in bit; -- Serial data input.
-- DATA register control:
DR_CLR : in bit; -- Clear.
DR_LOAD : in bit; -- LOAD.
-- Track register controls:
TR_PRES : in bit; -- Set x"FF".
TR_CLR : in bit; -- Clear.
TR_INC : in bit; -- Increment.
TR_DEC : in bit; -- Decrement.
-- Sector register control:
TRACK_NR : in std_logic_vector(7 downto 0);
SR_LOAD : in bit; -- Load.
SR_INC : in bit; -- Increment.
-- Shift register control:
SHFT_LOAD_SD : in bit;
SHFT_LOAD_ND : in bit;
-- Status register stuff
MOTOR_ON : in bit;
WRITE_PROTECT : in bit;
SPINUP_RECTYPE : in bit; -- Disk is on speed / data mark status.
SEEK_RNF : in bit; -- Seek error / record not found status flag.
CRC_ERRFLAG : in bit; -- CRC status flag.
LOST_DATA_TR00 : in bit;
DRQ : in bit;
DRQ_IPn : in bit;
BUSY : in bit;
-- Others:
DDEn : in bit
);
end WF1772IP_REGISTERS;
architecture BEHAVIOR of WF1772IP_REGISTERS is
-- Remark: In the original data sheet 'WD17X-00' there is the following statement:
-- "After any register is written to, the same register cannot be read from until
-- 16us in MFM or 32us in FMMM have elapsed." If this is a hint for a hardware read
-- lock ... this lock is not implemented in this code.
signal SHIFT_REG : std_logic_vector(7 downto 0);
signal DATA_REG : std_logic_vector(7 downto 0);
signal COMMAND_REG : std_logic_vector(7 downto 0);
signal SECTOR_REG : std_logic_vector(7 downto 0);
signal TRACK_REG : std_logic_vector(7 downto 0);
signal STATUS_REG : bit_vector(7 downto 0);
signal SD_R_I : std_logic;
begin
-- Type conversion To_Std_Logic:
SD_R_I <= '1' when SD_R = '1' else '0';
P_SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if SHFT_LOAD_ND = '1' then
SHIFT_REG <= DATA_REG; -- Load data register stuff.
elsif SHFT_LOAD_SD = '1' and DDEn = '1' then
SHIFT_REG <= DATA_REG; -- Normal data in FM mode.
elsif SHFT_LOAD_SD = '1' and DDEn = '0' then -- MFM mode:
case DATA_REG is
when x"F5" => SHIFT_REG <= x"A1"; -- Special character.
when x"F6" => SHIFT_REG <= x"C2"; -- Special character.
when others => SHIFT_REG <= DATA_REG; -- Normal MFM data.
end case;
elsif DATA_STRB = '1' then -- Shift left during read from disk or write to disk.
SHIFT_REG <= SHIFT_REG(6 downto 0) & SD_R_I; -- for write operation SD_R_I is a dummy.
end if;
end if;
end process P_SHIFTREG;
DSR <= SHIFT_REG;
DATAREG: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= x"00";
elsif CLK = '1' and CLK' event then
if CSn = '0' and ADR = "11" and RWn = '0' then
DATA_REG <= DATA_IN; -- Write bus data to register
elsif DR_LOAD = '1' and DRQ = '0' then
DATA_REG <= SHIFT_REG; -- Correct data loaded to shift register.
elsif DR_LOAD = '1' and DRQ = '1' then
DATA_REG <= x"00"; -- Dummy byte due to lost data loaded to shift register.
elsif DR_CLR = '1' then
DATA_REG <= (others => '0');
end if;
end if;
end process DATAREG;
-- Data register buffered for further data processing.
DR <= To_BitVector(DATA_REG);
SECTORREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SECTOR_REG <= x"00";
elsif CLK = '1' and CLK' event then
if CSn = '0' and ADR = "10" and RWn = '0' and BUSY = '0' then
SECTOR_REG <= DATA_IN; -- Write to register when device is not busy.
elsif SR_LOAD = '1' then
-- Load the track number to the sector register in the type III command
-- 'Read Address'.
SECTOR_REG <= TRACK_NR;
elsif SR_INC = '1' then
SECTOR_REG <= SECTOR_REG + '1';
end if;
end if;
end process SECTORREG;
SR <= SECTOR_REG;
TRACKREG: process(RESETn, CLK)
begin
if RESETn = '0' then
TRACK_REG <= x"00";
elsif CLK = '1' and CLK' event then
if CSn = '0' and ADR = "01" and RWn = '0' and BUSY = '0' then
TRACK_REG <= DATA_IN; -- Write to register when device is busy.
elsif TR_PRES = '1' then
TRACK_REG <= (others => '1'); -- Preset the track register.
elsif TR_CLR = '1' then
TRACK_REG <= (others => '0'); -- Reset the track register.
elsif TR_INC = '1' then
TRACK_REG <= TRACK_REG + '1'; -- Increment register contents.
elsif TR_DEC = '1' then
TRACK_REG <= TRACK_REG - '1'; -- Decrement register contents.
end if;
end if;
end process TRACKREG;
TR <= TRACK_REG;
COMMANDREG: process(RESETn, CLK)
-- The command register is write only.
begin
if RESETn = '0' then
COMMAND_REG <= x"00";
elsif CLK = '1' and CLK' event then
if CSn = '0' and ADR = "00" and RWn = '0' and BUSY = '0' then
COMMAND_REG <= DATA_IN; -- Write to register when device is not busy.
-- Write 'force interrupt' to register even when device is busy:
elsif CSn = '0' and ADR = "00" and RWn = '0' and DATA_IN(7 downto 4) = x"D" then
COMMAND_REG <= DATA_IN;
end if;
end if;
end process COMMANDREG;
CMD <= COMMAND_REG;
STATUSREG: process(RESETn, CLK)
-- The status register is read only to the data bus.
begin
-- Status register wiring:
if RESETn = '0' then
STATUS_REG <= x"00";
elsif CLK = '1' and CLK' event then
STATUS_REG(7) <= MOTOR_ON;
STATUS_REG(6) <= WRITE_PROTECT;
STATUS_REG(5) <= SPINUP_RECTYPE;
STATUS_REG(4) <= SEEK_RNF;
STATUS_REG(3) <= CRC_ERRFLAG;
STATUS_REG(2) <= LOST_DATA_TR00;
STATUS_REG(1) <= DRQ_IPn;
STATUS_REG(0) <= BUSY;
end if;
end process STATUSREG;
-- Read from track, sector or data register:
-- The register data after writing to the track register is valid at least
-- after 32us in FM mode and after 16us in MFM mode.
-- Read from status register. This register is read only:
-- Be aware, that the status register data bits 7 to 1 after writing
-- the command regsiter are valid at least after 64us in FM mode or 32us in MFM mode and
-- the bit 0 (BUSY) is valid after 48us in FM mode or 24us in MFM mode.
DATA_OUT <= TRACK_REG when CSn = '0' and ADR = "01" and RWn = '1' else
SECTOR_REG when CSn = '0' and ADR = "10" and RWn = '1' else
DATA_REG when CSn = '0' and ADR = "11" and RWn = '1' else
To_StdLogicVector(STATUS_REG) when CSn = '0' and ADR = "00" and RWn = '1' else (others => '0');
DATA_EN <= '1' when CSn = '0' and RWn = '1' else '0';
end architecture BEHAVIOR;

View File

@@ -0,0 +1,154 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- This is the top level file. ----
---- ----
---- ----
---- To Do: ----
---- - Test of the FM portion of the code (if there is any need). ----
---- - Test of the read track command. ----
---- - Test of the read address command. ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2006A 2006/06/03 WF
-- Initial Release: the MFM portion for HD and DD floppies is tested.
-- The FM mode (DDEn = '1') is not completely tested due to the lack
-- of FM drives.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Fixed the polarity of the precompensation flag.
-- The flag is no active '0'. Thanks to Jorma
-- Oksanen for the information.
-- Revision 2K7B 2006/12/29 WF
-- Introduced several improvements based on a very good examination
-- of the pll code by Jean Louis-Guerin.
-- Revision 2K8B 2008/12/24 WF
-- Rewritten this top level file as a wrapper for the top_soc file.
library work;
use work.WF1772IP_PKG.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_TOP is
port (
CLK : in bit; -- 16MHz clock!
MRn : in bit;
CSn : in bit;
RWn : in bit;
A1, A0 : in bit;
DATA : inout std_logic_vector(7 downto 0);
RDn : in bit;
TR00n : in bit;
IPn : in bit;
WPRTn : in bit;
DDEn : in bit;
HDTYPE : in bit; -- '0' = DD disks, '1' = HD disks.
MO : out bit;
WG : out bit;
WD : out bit;
STEP : out bit;
DIRC : out bit;
DRQ : out bit;
INTRQ : out bit
);
end entity WF1772IP_TOP;
architecture STRUCTURE of WF1772IP_TOP is
component WF1772IP_TOP_SOC
port (
CLK : in bit;
RESETn : in bit;
CSn : in bit;
RWn : in bit;
A1, A0 : in bit;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
RDn : in bit;
TR00n : in bit;
IPn : in bit;
WPRTn : in bit;
DDEn : in bit;
HDTYPE : in bit;
MO : out bit;
WG : out bit;
WD : out bit;
STEP : out bit;
DIRC : out bit;
DRQ : out bit;
INTRQ : out bit
);
end component;
signal DATA_OUT : std_logic_vector(7 downto 0);
signal DATA_EN : bit;
begin
DATA <= DATA_OUT when DATA_EN = '1' else (others => 'Z');
I_1772: WF1772IP_TOP_SOC
port map(
CLK => CLK,
RESETn => MRn,
CSn => CSn,
RWn => RWn,
A1 => A1,
A0 => A0,
DATA_IN => DATA,
DATA_OUT => DATA_OUT,
DATA_EN => DATA_EN,
RDn => RDn,
TR00n => TR00n,
IPn => IPn,
WPRTn => WPRTn,
DDEn => DDEn,
HDTYPE => HDTYPE,
MO => MO,
WG => WG,
WD => WD,
STEP => STEP,
DIRC => DIRC,
DRQ => DRQ,
INTRQ => INTRQ
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,333 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- Top level file for use in systems on programmable chips. ----
---- ----
---- ----
---- To Do: ----
---- - Test of the FM portion of the code (if there is any need). ----
---- - Test of the read track command. ----
---- - Test of the read address command. ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2006A 2006/06/03 WF
-- Initial Release: the MFM portion for HD and DD floppies is tested.
-- The FM mode (DDEn = '1') is not completely tested due to the lack
-- of FM drives.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Fixed the polarity of the precompensation flag.
-- The flag is no active '0'. Thanks to Jorma Oksanen for the information.
-- Top level file provided for SOC (systems on programmable chips).
-- Revision 2K7B 2006/12/29 WF
-- Introduced several improvements based on a very good examination
-- of the pll code by Jean Louis-Guerin.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K8B 2008/12/24 WF
-- Bugfixes in the controller due to hanging state machine.
-- Removed CRC_BUSY.
--
library work;
use work.WF1772IP_PKG.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_TOP_SOC is
port (
CLK : in bit; -- 16MHz clock!
RESETn : in bit;
CSn : in bit;
RWn : in bit;
A1, A0 : in bit;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
RDn : in bit;
TR00n : in bit;
IPn : in bit;
WPRTn : in bit;
DDEn : in bit;
HDTYPE : in bit; -- '0' = DD disks, '1' = HD disks.
MO : out bit;
WG : out bit;
WD : out bit;
STEP : out bit;
DIRC : out bit;
DRQ : out bit;
INTRQ : out bit
);
end entity WF1772IP_TOP_SOC;
architecture STRUCTURE of WF1772IP_TOP_SOC is
signal DATA_OUT_REG : std_logic_vector(7 downto 0);
signal DATA_EN_REG : bit;
signal CMD_I : std_logic_vector(7 downto 0);
signal DR_I : bit_vector(7 downto 0);
signal DSR_I : std_logic_vector(7 downto 0);
signal TR_I : std_logic_vector(7 downto 0);
signal SR_I : std_logic_vector(7 downto 0);
signal ID_AM_I : bit;
signal DATA_AM_I : bit;
signal DDATA_AM_I : bit;
signal AM_TYPE_I : bit;
signal AM_2_DISK_I : bit;
signal DATA_STRB_I : bit;
signal BUSY_I : bit;
signal DRQ_I : bit;
signal DRQ_IPn_I : bit;
signal LD_TR00_I : bit;
signal SP_RT_I : bit;
signal SEEK_RNF_I : bit;
signal WR_PR_I : bit;
signal MO_I : bit;
signal PLL_DSTRB_I : bit;
signal PLL_D_I : bit;
signal CRC_SD_I : bit;
signal CRC_ERR_I : bit;
signal CRC_PRES_I : bit;
signal CRC_ERRFLAG_I : bit;
signal SD_R_I : bit;
signal CRC_SDOUT_I : bit;
signal SHFT_LOAD_SD_I : bit;
signal SHFT_LOAD_ND_I : bit;
signal WR_In : bit;
signal TR_PRES_I : bit;
signal TR_CLR_I : bit;
signal TR_INC_I : bit;
signal TR_DEC_I : bit;
signal SR_LOAD_I : bit;
signal SR_INC_I : bit;
signal DR_CLR_I : bit;
signal DR_LOAD_I : bit;
signal TRACK_NR_I : std_logic_vector(7 downto 0);
signal CRC_2_DISK_I : bit;
signal DSR_2_DISK_I : bit;
signal FF_2_DISK_I : bit;
signal PRECOMP_EN_I : bit;
signal DISK_RWn_I : bit;
signal WDATA_I : bit;
begin
-- Three state data bus:
DATA_OUT <= DATA_OUT_REG when DATA_EN_REG = '1' else (others => '0');
DATA_EN <= DATA_EN_REG;
-- Some signals copied to the outputs:
WD <= not WR_In;
MO <= MO_I;
DRQ <= DRQ_I;
-- Write deleted data address mark in MFM mode in 'Write Sector' command in
-- case of asserted command bit 0.
AM_TYPE_I <= '0' when CMD_I(7 downto 5) = "101" and CMD_I(0) = '1' else '1';
-- The CRC unit is used during read from disk and write to disk.
-- This is the data multiplexer for the data stream to encode.
CRC_SD_I <= SD_R_I when DISK_RWn_I = '1' else WDATA_I;
I_CONTROL: WF1772IP_CONTROL
port map(
CLK => CLK,
RESETn => RESETn,
A1 => A0,
A0 => A1,
RWn => RWn,
CSn => CSn,
DDEn => DDEn,
DR => DR_I,
CMD => CMD_I,
DSR => DSR_I,
TR => TR_I,
SR => SR_I,
MO => MO_I,
WR_PR => WR_PR_I,
SPINUP_RECTYPE => SP_RT_I,
SEEK_RNF => SEEK_RNF_I,
CRC_ERRFLAG => CRC_ERRFLAG_I,
LOST_DATA_TR00 => LD_TR00_I,
DRQ => DRQ_I,
DRQ_IPn => DRQ_IPn_I,
BUSY => BUSY_I,
AM_2_DISK => AM_2_DISK_I,
ID_AM => ID_AM_I,
DATA_AM => DATA_AM_I,
DDATA_AM => DDATA_AM_I,
CRC_ERR => CRC_ERR_I,
CRC_PRES => CRC_PRES_I,
TR_PRES => TR_PRES_I,
TR_CLR => TR_CLR_I,
TR_INC => TR_INC_I,
TR_DEC => TR_DEC_I,
SR_LOAD => SR_LOAD_I,
SR_INC => SR_INC_I,
TRACK_NR => TRACK_NR_I,
DR_CLR => DR_CLR_I,
DR_LOAD => DR_LOAD_I,
SHFT_LOAD_SD => SHFT_LOAD_SD_I,
SHFT_LOAD_ND => SHFT_LOAD_ND_I,
CRC_2_DISK => CRC_2_DISK_I,
DSR_2_DISK => DSR_2_DISK_I,
FF_2_DISK => FF_2_DISK_I,
PRECOMP_EN => PRECOMP_EN_I,
DATA_STRB => DATA_STRB_I,
DISK_RWn => DISK_RWn_I,
WPRTn => WPRTn,
TRACK00n => TR00n,
IPn => IPn,
DIRC => DIRC,
STEP => STEP,
WG => WG,
INTRQ => INTRQ
);
I_REGISTERS: WF1772IP_REGISTERS
port map(
CLK => CLK,
RESETn => RESETn,
CSn => CSn,
ADR(1) => A1,
ADR(0) => A0,
RWn => RWn,
DATA_IN => DATA_IN,
DATA_OUT => DATA_OUT_REG,
DATA_EN => DATA_EN_REG,
CMD => CMD_I,
TR => TR_I,
SR => SR_I,
DSR => DSR_I,
DR => DR_I,
SD_R => SD_R_I,
DATA_STRB => DATA_STRB_I,
DR_CLR => DR_CLR_I,
DR_LOAD => DR_LOAD_I,
TR_PRES => TR_PRES_I,
TR_CLR => TR_CLR_I,
TR_INC => TR_INC_I,
TR_DEC => TR_DEC_I,
TRACK_NR => TRACK_NR_I,
SR_LOAD => SR_LOAD_I,
SR_INC => SR_INC_I,
SHFT_LOAD_SD => SHFT_LOAD_SD_I,
SHFT_LOAD_ND => SHFT_LOAD_ND_I,
MOTOR_ON => MO_I,
WRITE_PROTECT => WR_PR_I,
SPINUP_RECTYPE => SP_RT_I,
SEEK_RNF => SEEK_RNF_I,
CRC_ERRFLAG => CRC_ERRFLAG_I,
LOST_DATA_TR00 => LD_TR00_I,
DRQ => DRQ_I,
DRQ_IPn => DRQ_IPn_I,
BUSY => BUSY_I,
DDEn => DDEn
);
I_DIGITAL_PLL: WF1772IP_DIGITAL_PLL
port map(
CLK => CLK,
RESETn => RESETn,
DDEn => DDEn,
HDTYPE => HDTYPE,
DISK_RWn => DISK_RWn_I,
RDn => RDn,
PLL_D => PLL_D_I,
PLL_DSTRB => PLL_DSTRB_I
);
I_AM_DETECTOR: WF1772IP_AM_DETECTOR
port map(
CLK => CLK,
RESETn => RESETn,
DDEn => DDEn,
DATA => PLL_D_I,
DATA_STRB => PLL_DSTRB_I,
ID_AM => ID_AM_I,
DATA_AM => DATA_AM_I,
DDATA_AM => DDATA_AM_I
);
I_CRC_LOGIC: WF1772IP_CRC_LOGIC
port map(
CLK => CLK,
RESETn => RESETn,
DDEn => DDEn,
DISK_RWn => DISK_RWn_I,
ID_AM => ID_AM_I,
DATA_AM => DATA_AM_I,
DDATA_AM => DDATA_AM_I,
SD => CRC_SD_I,
CRC_STRB => DATA_STRB_I,
CRC_2_DISK => CRC_2_DISK_I,
CRC_PRES => CRC_PRES_I,
CRC_SDOUT => CRC_SDOUT_I,
CRC_ERR => CRC_ERR_I
);
I_TRANSCEIVER: WF1772IP_TRANSCEIVER
port map(
CLK => CLK,
RESETn => RESETn,
DDEn => DDEn,
HDTYPE => HDTYPE,
ID_AM => ID_AM_I,
DATA_AM => DATA_AM_I,
DDATA_AM => DDATA_AM_I,
SHFT_LOAD_SD => SHFT_LOAD_SD_I,
DR => DR_I,
PRECOMP_EN => PRECOMP_EN_I,
AM_TYPE => AM_TYPE_I,
AM_2_DISK => AM_2_DISK_I,
CRC_2_DISK => CRC_2_DISK_I,
DSR_2_DISK => DSR_2_DISK_I,
FF_2_DISK => FF_2_DISK_I,
SR_SDOUT => DSR_I(7),
CRC_SDOUT => CRC_SDOUT_I,
WRn => WR_In,
WDATA => WDATA_I,
PLL_DSTRB => PLL_DSTRB_I,
PLL_D => PLL_D_I,
DATA_STRB => DATA_STRB_I,
SD_R => SD_R_I
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,517 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- The transceiver unit contains on the one hand the receiver ----
---- part which strips off the clock signal from the data stream ----
---- and on the other hand the transmitter unit which provides in ----
---- the different modes (FM and MFM) all functions which are ----
---- necessary to send data, CRC bytes, 'FF', '00' or the address ----
---- marks. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2006A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- MFM_In and MASK_SHFT have now synchronous reset to meet preset requirement.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_TRANSCEIVER is
port(
-- System control
CLK : in bit; -- must be 16MHz
RESETn : in bit;
-- Data and Control:
HDTYPE : in bit; -- Floppy type HD or DD.
DDEn : in bit; -- Double density select (FM or MFM).
ID_AM : in bit; -- ID addressmark strobe.
DATA_AM : in Bit; -- Data addressmark strobe.
DDATA_AM : in Bit; -- Deleted data addressmark strobe.
SHFT_LOAD_SD : in bit; -- Indication for shift register load time.
DR : in bit_vector(7 downto 0); -- Content of the data register.
-- Data strobes:
PLL_DSTRB : in bit; -- Clock strobe for RD serial data input.
DATA_STRB : buffer bit;
-- Data strobe and data for the CRC during write operation:
WDATA : buffer bit;
-- Encoder (logic to disk):
PRECOMP_EN : in bit; -- control signal for MFM write precompensation.
AM_TYPE : in bit; -- Write deleted address mark in MFM mode when 0.
AM_2_DISK : in bit;
DSR_2_DISK : in bit;
FF_2_DISK : in bit;
CRC_2_DISK : in bit;
SR_SDOUT : in std_logic; -- encoder's data input from the shift register (serial).
CRC_SDOUT : in bit; -- encoder's data input from the CRC unit (serial).
WRn : out bit; -- write output for the MFM drive containing clock and data.
-- Decoder (disk to logic):
PLL_D : in bit; -- Serial data input.
SD_R : out bit -- Serial (decoded) data output.
);
end WF1772IP_TRANSCEIVER;
architecture BEHAVIOR of WF1772IP_TRANSCEIVER is
type MFM_STATES is (A_00, B_01, C_10);
type PRECOMP_VALUES is (EARLY, NOMINAL, LATE);
type DEC_STATES is (CLK_PHASE, DATA_PHASE);
signal MFM_STATE : MFM_STATES;
signal NEXT_MFM_STATE : MFM_STATES;
signal PRECOMP : PRECOMP_VALUES;
signal DEC_STATE : DEC_STATES;
signal NEXT_DEC_STATE : DEC_STATES;
signal FM_In : bit;
signal CLKMASK : bit; -- Control for suppression of FM clock transitions.
signal MFM_10_STRB : bit;
signal MFM_01_STRB : bit;
signal WR_CNT : std_logic_vector(3 downto 0);
signal MFM_In : bit;
signal AM_SHFT : bit_vector(31 downto 0);
begin
-- ####################### encoder stuff ###########################
ADRMARK: process(RESETn, CLK)
-- This process provides the address mark data for both FM and MFM in
-- write to disk mode. In FM only one byte is written where in MFM
-- 3 sync bytes x"A1" and one data address mark is written.
-- In this process only the data address mark is provided. The only way
-- writing the ID address mark is the write track command.
begin
if RESETn = '0' then
AM_SHFT <= (others => '0');
elsif CLK = '1' and CLK' event then
if AM_2_DISK = '1' and DATA_STRB = '1' then
AM_SHFT <= AM_SHFT (30 downto 0) & '0'; -- Shift out.
elsif AM_2_DISK = '0' and DDEn = '1' and AM_TYPE = '0' then -- FM mode.
AM_SHFT <= x"F8000000"; -- Load deleted FM address mark.
elsif AM_2_DISK = '0' and DDEn = '1' and AM_TYPE = '1' then -- FM mode.
AM_SHFT <= x"FB000000"; -- Load normal FM address mark.
elsif AM_2_DISK = '0' and DDEn = '0' and AM_TYPE = '0' then -- MFM mode deleted data mark.
AM_SHFT <= x"A1A1A1F8"; -- Load MFM syncs and address mark.
elsif AM_2_DISK = '0' and DDEn = '0' and AM_TYPE = '1' then -- Default: MFM mode normal data mark.
AM_SHFT <= x"A1A1A1FB"; -- Load MFM syncs and address mark.
end if;
end if;
end process ADRMARK;
-- Input multiplexer:
WDATA <= AM_SHFT(31) when AM_2_DISK = '1' else -- Address mark data data.
To_Bit(SR_SDOUT) when DSR_2_DISK = '1' else -- Shift register data.
CRC_SDOUT when CRC_2_DISK = '1' else -- CRC data.
'1' when FF_2_DISK = '1' else '0'; -- Write zeros is default.
-- Output multiplexer:
WRn <= '0' when FM_In = '0' and DDEn = '1' else -- FM portion.
'0' when MFM_In = '0' and DDEn = '0' else '1'; -- MFM portion and default.
CLK_MASK: process(CLK)
-- This part of software controls the suppression of the clock pulses
-- during transmission of several FM special characters. During writing
-- 'normal' data to the disk, only 8 mask bits of the shift register are
-- used. During writing MFM sync and address mark bits, the register is
-- used with 32 mask bits.
variable MASK_SHFT : bit_vector(23 downto 0);
variable LOCK : boolean;
begin
if CLK = '1' and CLK' event then
if RESETn = '0' then
MASK_SHFT := (others => '1');
LOCK := false;
-- Load the mask shift register just in time when the shift register is
-- loaded with valid data from the data register.
elsif SHFT_LOAD_SD = '1' and DDEn = '1' then -- FM mode.
case DR is
when x"F8" | x"F9" | x"FA" | x"FB" | x"FE" => MASK_SHFT := x"C7FFFF";
when x"FC" => MASK_SHFT := x"D7FFFF";
when x"F5" | x"F6" => MASK_SHFT := (others => '0'); -- Not allowed.
when others => MASK_SHFT := x"FFFFFF"; -- Normal data.
end case;
elsif SHFT_LOAD_SD = '1' and DDEn = '0' then -- MFM mode.
case DR is
when x"F5" => MASK_SHFT := x"FBFFFF"; -- Suppress clock pulse between bits 4 and 5.
when x"F6" => MASK_SHFT := x"F7FFFF"; -- Suppress clock pulse between bits 3 and 4.
when others => MASK_SHFT := x"FFFFFF"; -- Normal data.
end case;
elsif AM_2_DISK = '1' and DDEn = '1' and LOCK = false then -- FM mode.
MASK_SHFT := x"C7FFFF"; -- Load just once per AM_2_DISK rising edge.
LOCK := true;
elsif AM_2_DISK = '1' and DDEn = '0' and LOCK = false then -- MFM mode.
MASK_SHFT := x"FBFBFB"; -- Three syncs with suppressed clock pulse then transparent mask.
LOCK := true;
elsif DATA_STRB = '1' then -- shift as long as transmission is active
-- The Shift register is shifted left. After shifting the clockmasks out it is
-- transparent due to the '1's filled up from the left.
MASK_SHFT := MASK_SHFT(22 downto 0) & '1'; -- Shift left.
elsif AM_2_DISK = '0' then
LOCK := false; -- Release the lock after address mark has been written.
end if;
end if;
CLKMASK <= MASK_SHFT(23);
end process CLK_MASK;
FM_ENCODER: process (RESETn, DATA_STRB, CLK)
-- For DD type floppies the data rate is 125kBps. Therefore there are 128 16-MHz clocks cycles
-- per FM bit.
-- For HD type floppies the data rate is 250kBps. Therefore there are 64 16-MHz clocks cycles
-- per FM bit.
-- The FM write pulse width is 1.375us for DD and 0.750us HD type floppies.
-- This process provides the FM encoded signal. The first pulse is in any case the clock
-- pulse and the second pulse is due to data. The FM encoding is very simple and therefore
-- self explaining.
variable CNT : std_logic_vector(7 downto 0);
begin
if RESETn = '0' then
FM_In <= '1';
CNT := x"00";
elsif CLK = '1' and CLK' event then
-- In case of HD type floppies the counter reaches a value of b"0100000"
-- In case of DD type floppies the counter reaches a value of b"1000000"
if DATA_STRB = '1' then
CNT := x"00";
else
CNT := CNT + '1';
end if;
-- The flux reversal pulses are centered between the DATA_STRB pulses.
-- In detail: the clock pulse appears in the middle of the first half
-- of the DATA_STRB period and the data pulse appears in the middle of
-- the second half.
case HDTYPE is
when '0' => -- DD type floppies:
if CNT > "00010101" and CNT <= "00101011" then
FM_In <= not CLKMASK; -- FM clock.
elsif CNT > "01010101" and CNT <= "01101011" then
FM_In <= not WDATA; -- FM data.
else
FM_In <= '1';
end if;
when '1' => -- HD type floppies:
if CNT > "00001010" and CNT <= "00010110" then
FM_In <= not CLKMASK; -- FM clock.
elsif CNT > "00101010" and CNT <= "00110110" then
FM_In <= not WDATA; -- FM data.
else
FM_In <= '1';
end if;
end case;
end if;
end process FM_ENCODER;
MFM_ENCODE_REG: process(RESETn, CLK)
-- This process is the first portion of the more complicated MFM encoder. It can be interpreted
-- as a Moore machine. This part is the current state register.
begin
if RESETn = '0' then
MFM_STATE <= A_00;
elsif CLK = '1' and CLK' event then
MFM_STATE <= NEXT_MFM_STATE;
end if;
end process MFM_ENCODE_REG;
MFM_ENCODE_LOGIC: process(MFM_STATE, WDATA, DATA_STRB)
-- Rules for Encoding:
-- transitions are never located at the mid point of a 'zero'.
-- transistions are always located at the mid point of a '1'.
-- no transitions at the borders of a '1'.
-- transitions appear between two adjacent 'zeros'.
-- states are as follows:
-- A_00: idle state, no transition.
-- B_01: transistion between the MFM clock edges.
-- C_10: transition on the leading MFM clock edges.
-- The timing of the MFM output is done in the process MFM_WR_OUT.
begin
case MFM_STATE is
when A_00 =>
if WDATA = '0' and DATA_STRB = '1' then
NEXT_MFM_STATE <= C_10;
elsif WDATA = '1' and DATA_STRB = '1' then
NEXT_MFM_STATE <= B_01;
else
NEXT_MFM_STATE <= A_00; -- Stay, if there is no strobe.
end if;
when C_10 =>
if WDATA = '0' and DATA_STRB = '1' then
NEXT_MFM_STATE <= C_10;
elsif WDATA = '1' and DATA_STRB = '1' then
NEXT_MFM_STATE <= B_01;
else
NEXT_MFM_STATE <= C_10; -- Stay, if there is no strobe.
end if;
when B_01 =>
if WDATA = '0' and DATA_STRB = '1' then
NEXT_MFM_STATE <= A_00;
elsif WDATA = '1' and DATA_STRB = '1' then
NEXT_MFM_STATE <= B_01;
else
NEXT_MFM_STATE <= B_01; -- Stay, if there is no strobe.
end if;
end case;
end process MFM_ENCODE_LOGIC;
MFM_PRECOMPENSATION: process(RESETn, CLK)
-- The write pattern is adjusted in the MFM write timing process as follows:
-- after DATA_STRB (the duty cycle of this strobe is exactly one CLK) the
-- incoming data is bufferd in WRITEPATTERN. After the following DATA_STRB
-- the WDATA is shifted through WRITEPATTERN. After further DATA_STRBs the
-- WRITEPATTERN consists of previous, current and next WDATA like this:
-- WRITEPATTERN(3) is the second previous WDATA.
-- WRITEPATTERN(2) is the previous WDATA.
-- WRITEPATTERN(1) is the current WDATA to be sent.
-- WRITEPATTERN(0) is the next WDATA to be sent.
variable WRITEPATTERN : bit_vector(3 downto 0);
begin
if RESETn = '0' then
PRECOMP <= NOMINAL;
WRITEPATTERN := "0000";
elsif CLK = '1' and CLK' event then
if DATA_STRB = '1' then
WRITEPATTERN := WRITEPATTERN(2 downto 0) & WDATA; -- shift left
end if;
if PRECOMP_EN = '0' then
PRECOMP <= NOMINAL; -- no precompensation
else
case WRITEPATTERN is
when "1110" | "0110" => PRECOMP <= EARLY;
when "1011" | "0011" => PRECOMP <= LATE;
when "0001" => PRECOMP <= EARLY;
when "1000" => PRECOMP <= LATE;
when others => PRECOMP <= NOMINAL;
end case;
end if;
end if;
end process MFM_PRECOMPENSATION;
MFM_STROBES: process (RESETn, DATA_STRB, CLK)
-- For the MFM frequency is 250 kBps for DD type floppies, there are 64
-- 16 MHz clock cycles per MFM bit and for HD type floppies, which have
-- 500 kBps there are 32 16MHz clock pulses for one MFM bit.
-- The MFM state machine (Moore) switches on the DATA_STRB.
-- During one cycle there are the two further strobes MFM_10_STRB and
-- MFM_01_STRB which control the MFM output in the process MFM_WR_OUT.
-- The strobes are centered in the middle of the first half and in the
-- middle of the second half of the DATA_STRB cycle.
variable CNT : std_logic_vector(5 downto 0);
begin
if RESETn = '0' then
CNT := "000000";
elsif CLK = '1' and CLK' event then
if DATA_STRB = '1' then
CNT := (others => '0');
else
CNT := CNT + '1';
end if;
if HDTYPE = '1' then
case CNT is
-- encoder timing for MFM and HD type floppies.
when "000100" => MFM_10_STRB <= '1'; MFM_01_STRB <= '0'; -- Pulse centered in the first half.
when "010100" => MFM_10_STRB <= '0'; MFM_01_STRB <= '1'; -- Pulse centered in the second half.
when others => MFM_10_STRB <= '0'; MFM_01_STRB <= '0';
end case;
else
case CNT is
-- encoder timing for MFM and DD type floppies.
when "001010" => MFM_10_STRB <= '1'; MFM_01_STRB <= '0'; -- Pulse centered in the first half.
when "101000" => MFM_10_STRB <= '0'; MFM_01_STRB <= '1'; -- Pulse centered in the second half.
when others => MFM_10_STRB <= '0'; MFM_01_STRB <= '0';
end case;
end if;
end if;
end process MFM_STROBES;
-- MFM_WR_TIMING generates the timing for the write pulses which are
-- required by a MFM device like floppy disk drive. The pulse timing
-- meets the timing of the MFM data with pulse width of 700ns +/- 100ns
-- depending on write precompensation.
-- The original WD1772 (CLK = 8MHz) data timing was as follows:
-- The output is asserted as long as CNT is active; in detail
-- this are 4,5; 5,5 or 6,5 CLK cycles depending on the write
-- precompensation.
-- The new design which works with a 16MHz clock requires the following
-- timing: 9; 11 or 13 CLK cycles depending on the writeprecompensation
-- for DD floppies and 5; 6 or 7 CLK cycles depending on the write
-- precompensation for HD floppies.
-- To meet the timing requirements of half clocks
-- the WRn is controlled by the following three processes where the one
-- syncs on the positive clock edge and the other on the negative.
-- For more information on the WTn timing see the datasheet of the
-- WD177x floppy disc controller.
MFM_WR_TIMING: process(RESETn, CLK)
variable CLKMASK_MFM : bit;
begin
if RESETn = '0' then
WR_CNT <= x"F";
elsif CLK = '1' and CLK' event then
if DATA_STRB = '1' then
-- The CLKMASK_MFM is synchronised to DATA_STRB. This brings one strobe latency.
-- The timing in connection with the data is correct because the MFM encoder state machine
-- causes the data to be 1 DATA_STRB late too.
CLKMASK_MFM := CLKMASK;
end if;
if MFM_STATE = C_10 and MFM_10_STRB = '1' and CLKMASK_MFM = '1' then
WR_CNT <= x"0";
elsif MFM_STATE = B_01 and MFM_01_STRB = '1' then
WR_CNT <= x"0";
elsif WR_CNT < x"F" then
WR_CNT <= WR_CNT + '1';
end if;
end if;
end process MFM_WR_TIMING;
MFM_WR_OUT: process
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
MFM_In <= '1';
else
case HDTYPE is
when '1' => -- HD type.
if PRECOMP = EARLY and WR_CNT > x"0" and WR_CNT <= x"9" then
MFM_In <= '0'; -- 9,0 clock cycles for WRn --> early timing
elsif PRECOMP = NOMINAL and WR_CNT > x"0" and WR_CNT <= x"8" then
MFM_In <= '0'; -- 8,0 clock cycles for WRn --> nominal timing
elsif PRECOMP = LATE and WR_CNT > x"0" and WR_CNT <= x"7" then
MFM_In <= '0'; -- 7,0 clock cycles for WRn --> late timing
else
MFM_In <= '1';
end if;
when '0' => -- DD type.
if PRECOMP = EARLY and WR_CNT > x"0" and WR_CNT <= x"D" then
MFM_In <= '0'; -- 13,0 clock cycles for WRn --> early timing
elsif PRECOMP = NOMINAL and WR_CNT > x"0" and WR_CNT <= x"B" then
MFM_In <= '0'; -- 11,0 clock cycles for WRn --> nominal timing
elsif PRECOMP = LATE and WR_CNT > x"0" and WR_CNT <= x"9" then
MFM_In <= '0'; -- 9,0 clock cycles for WRn --> late timing
else
MFM_In <= '1';
end if;
end case;
end if;
end process MFM_WR_OUT;
-- ####################### Decoder stuff ###########################
-- The decoding of the serial FM or MFM encoded data stream
-- is done in the following two processes (Moore machine).
-- The decoder works in principle like a simple toggle Flip-Flop.
-- It is important to synchronise it in a way, that the clock
-- pulses are separated from the data pulses. The principle
-- works for both FM and MFM data due to the digital phase
-- locked loop, which delivers the serial data and the clock
-- strobe. In general this decoder can be understood as the
-- data separator where the digital phase locked loop provides
-- the FM or the MFM decoding. The data separation lives from
-- the fact, that FM and also MFM encoded signals consist of a
-- mixture of alternating data and clock pulses.
-- FM works as follows:
-- every first pulse of the FM signal is a clock pulse and every
-- second pulse is a logic '1' of the data. A missing second
-- pulse represents a logic '0' of the data.
-- MFM works as follows:
-- every first pulse of the MFM signal is a clock pulse. The coding
-- principle causes clock pulses to be absent in some conditions.
-- Every second pulse is a logic '1' of the data. A missing second
-- pulse represents a logic '0' of the data.
-- So FM and MFM compared, the data is represented directly by the
-- second pulses and the data separator has to look only for these.
-- The missing MFM clock pulses do not cause a problem because the
-- digital PLL used in conjunction with this data separator fills
-- up the clock pulses and delivers a PLL_DSTRB containing aequidistant
-- clock strobes and data strobes.
DEC_REG: process(RESETn, CLK)
begin
if RESETn = '0' then
DEC_STATE <= CLK_PHASE;
elsif CLK = '1' and CLK' event then
DEC_STATE <= NEXT_DEC_STATE;
end if;
end process DEC_REG;
DEC_LOGIC: process(DEC_STATE, ID_AM, DATA_AM, DDATA_AM, PLL_DSTRB, PLL_D)
begin
case DEC_STATE is
when CLK_PHASE =>
if PLL_DSTRB = '1' then
NEXT_DEC_STATE <= DATA_PHASE;
else
NEXT_DEC_STATE <= CLK_PHASE;
end if;
DATA_STRB <= '0'; -- Inactive during clock pulse time.
SD_R <= '0'; -- Inactive during clock pulse time.
when DATA_PHASE =>
if ID_AM = '1' or DATA_AM = '1' or DDATA_AM = '1' then
-- Here the state machine is synchronised
-- to separate data and clock pulses correctly.
NEXT_DEC_STATE <= CLK_PHASE;
elsif PLL_DSTRB = '1' then
NEXT_DEC_STATE <= CLK_PHASE;
else
NEXT_DEC_STATE <= DATA_PHASE;
end if;
-- During the data phase valid data appears at SD.
-- The data is valid during DATA_STRB.
DATA_STRB <= PLL_DSTRB;
SD_R <= PLL_D;
end case;
end process DEC_LOGIC;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,141 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This are the SUSKA MFP IP core's general purpose I/Os. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_GPIO is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
-- Timer controls:
AER_4 : out bit;
AER_3 : out bit;
GPIP_IN : in bit_vector(7 downto 0);
GPIP_OUT : out bit_vector(7 downto 0);
GPIP_OUT_EN : buffer bit_vector(7 downto 0);
GP_INT : out bit_vector(7 downto 0)
);
end entity WF68901IP_GPIO;
architecture BEHAVIOR of WF68901IP_GPIO is
signal GPDR : bit_vector(7 downto 0);
signal DDR : bit_vector(7 downto 0);
signal AER : bit_vector(7 downto 0);
signal GPDR_I : bit_vector(7 downto 0);
begin
-- These two bits control the timers A and B pulse width operation and the
-- timers A and B event count operation.
AER_4 <= AER(4);
AER_3 <= AER(3);
-- This statement provides 8 XOR units setting the desired interrupt polarity.
-- While the level control is done here, the edge triggering is provided by
-- the interrupt control hardware. The level control is individually for each
-- GPIP port pin. The interrupt edge trigger unit must operate in any case on
-- the low to high transistion of the respective port pin.
GP_INT <= AER xnor GPIP_IN;
GPIO_REGISTERS: process(RESETn, CLK)
begin
if RESETn = '0' then
GPDR <= (others => '0');
DDR <= (others => '0');
AER <= (others => '0');
elsif CLK = '1' and CLK' event then
if CSn = '0' and DSn = '0' and RWn = '0' then
case RS is
when "00000" => GPDR <= DATA_IN;
when "00001" => AER <= DATA_IN;
when "00010" => DDR <= DATA_IN;
when others => null;
end case;
end if;
end if;
end process GPIO_REGISTERS;
GPIP_OUT <= GPDR; -- Port outputs.
GPIP_OUT_EN <= DDR; -- The DDR is capable to control bitwise the GPIP.
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS <= "00010" else '0';
DATA_OUT <= DDR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00010" else
AER when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00001" else
GPDR_I when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00000" else (others => '0');
P_GPDR: process(GPIP_IN, GPIP_OUT_EN, GPDR)
-- Read back control: Read the port pins, if the data direction is configured as input.
-- Read the respective GPDR register bit, if the data direction is configured as output.
begin
for i in 7 downto 0 loop
if GPIP_OUT_EN(i) = '1' then -- Port is configured output.
GPDR_I(i) <= GPDR(i);
else
GPDR_I(i) <= GPIP_IN(i); -- Port is configured input.
end if;
end loop;
end process P_GPDR;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,391 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the SUSKA MFP IP core interrupt logic file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/06/03 WF
-- Fixed Pending register logic.
-- Revision 2K9A 2009/06/20 WF
-- Fixed interrupt polarity for TA_I and TB_I.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_INTERRUPTS is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
-- Interrupt control:
IACKn : in bit;
IEIn : in bit;
IEOn : out bit;
IRQn : out bit;
-- Interrupt sources:
GP_INT : in bit_vector(7 downto 0);
AER_4 : in bit;
AER_3 : in bit;
TAI : in bit;
TBI : in bit;
TA_PWM : in bit;
TB_PWM : in bit;
TIMER_A_INT : in bit;
TIMER_B_INT : in bit;
TIMER_C_INT : in bit;
TIMER_D_INT : in bit;
RCV_ERR : in bit;
TRM_ERR : in bit;
RCV_BUF_F : in bit;
TRM_BUF_E : in bit
);
end entity WF68901IP_INTERRUPTS;
architecture BEHAVIOR of WF68901IP_INTERRUPTS is
-- Interrupt state machine:
type INT_STATES is (SCAN, REQUEST, VECTOR_OUT);
signal INT_STATE : INT_STATES;
-- The registers:
signal IERA : bit_vector(7 downto 0);
signal IERB : bit_vector(7 downto 0);
signal IPRA : bit_vector(7 downto 0);
signal IPRB : bit_vector(7 downto 0);
signal ISRA : bit_vector(7 downto 0);
signal ISRB : bit_vector(7 downto 0);
signal IMRA : bit_vector(7 downto 0);
signal IMRB : bit_vector(7 downto 0);
signal VR : bit_vector(7 downto 3);
-- Interconnect:
signal VECT_NUMBER : bit_vector(7 downto 0);
signal INT_SRC : bit_vector(15 downto 0);
signal INT_SRC_EDGE : bit_vector(15 downto 0);
signal INT_ENA : bit_vector(15 downto 0);
signal INT_MASK : bit_vector(15 downto 0);
signal INT_PENDING : bit_vector(15 downto 0);
signal INT_SERVICE : bit_vector(15 downto 0);
signal INT_PASS : bit_vector(15 downto 0);
signal INT_OUT : bit_vector(15 downto 0);
signal GP_INT_4 : bit;
signal GP_INT_3 : bit;
begin
-- Interrupt source for the GPI_4 and GPI_3 is normally the respective port pin.
-- But when the timers operate in their PWM modes, the GPI_4 and GPI_3 are associated
-- to timer A and timer B.
-- The xor logic provides polarity control for the interrupt transition. Be aware,
-- that the PWM signals cause an interrupt on the opposite transition like the
-- respective GPIP port pins (with the same AER settings).
--GP_INT_4 <= GP_INT(4) when TA_PWM = '0' else TAI xor AER_4;
--GP_INT_3 <= GP_INT(3) when TB_PWM = '0' else TBI xor AER_3;
GP_INT_4 <= GP_INT(4) when TA_PWM = '0' else TAI xnor AER_4; -- This should be correct.
GP_INT_3 <= GP_INT(3) when TB_PWM = '0' else TBI xnor AER_3;
-- Interrupt source priority sorted (15 = highest):
INT_SRC <= GP_INT(7 downto 6) & TIMER_A_INT & RCV_BUF_F & RCV_ERR & TRM_BUF_E & TRM_ERR & TIMER_B_INT &
GP_INT(5) & GP_INT_4 & TIMER_C_INT & TIMER_D_INT & GP_INT_3 & GP_INT(2 downto 0);
INT_ENA <= IERA & IERB;
INT_MASK <= IMRA & IMRB;
INT_PENDING <= IPRA & IPRB;
INT_SERVICE <= ISRA & ISRB;
INT_OUT <= INT_PENDING and INT_MASK; -- Masking:
-- Enable the daisy chain, if there is no pending interrupt and
-- the interrupt state machine is not in service.
IEOn <= '0' when INT_OUT = x"0000" and INT_STATE = SCAN else '1';
-- Interrupt request:
IRQn <= '0' when INT_OUT /= x"0000" and INT_STATE = REQUEST else '1';
EDGE_ENA: process(RESETn, CLK)
-- These are the 16 edge detectors of the 16 interrupt input sources. This
-- process also provides the disabling or enabling via the IERA and IERB registers.
variable LOCK : bit_vector(15 downto 0);
begin
if RESETn = '0' then
INT_SRC_EDGE <= x"0000";
LOCK := x"0000";
elsif CLK = '1' and CLK' event then
for i in 15 downto 0 loop
if INT_SRC(i) = '1' and INT_ENA(i) = '1' and LOCK(i) = '0' then
LOCK(i) := '1';
INT_SRC_EDGE(i) <= '1';
elsif INT_SRC(i) = '0' then
LOCK(i) := '0';
INT_SRC_EDGE(i) <= '0';
else
INT_SRC_EDGE(i) <= '0';
end if;
end loop;
end if;
end process EDGE_ENA;
INT_REGISTERS: process(RESETn, CLK)
begin
if RESETn = '0' then
IERA <= (others => '0');
IERB <= (others => '0');
IPRA <= (others => '0');
IPRB <= (others => '0');
ISRA <= (others => '0');
ISRB <= (others => '0');
IMRA <= (others => '0');
IMRB <= (others => '0');
elsif CLK = '1' and CLK' event then
if CSn = '0' and DSn = '0' and RWn = '0' then
case RS is
when "00011" => IERA <= DATA_IN; -- Enable A.
when "00100" => IERB <= DATA_IN; -- Enable B.
when "00101" =>
-- Only a '0' can be written to the pending register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
IPRA(i) <= '0'; -- Pending A.
end if;
end loop;
when "00110" =>
-- Only a '0' can be written to the pending register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
IPRB(i) <= '0'; -- Pending B.
end if;
end loop;
when "00111" =>
-- Only a '0' can be written to the in service register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
ISRA(i) <= '0'; -- In Service A.
end if;
end loop;
when "01000" =>
-- Only a '0' can be written to the in service register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
ISRB(i) <= '0'; -- In Service B.
end if;
end loop;
when "01001" => IMRA <= DATA_IN; -- Mask A.
when "01010" => IMRB <= DATA_IN; -- Mask B.
when "01011" => VR <= DATA_IN(7 downto 3); -- Vector register.
when others => null;
end case;
end if;
-- Pending register:
-- set and clear bit logic.
for i in 15 downto 8 loop
if INT_SRC_EDGE(i) = '1' then
IPRA(i-8) <= '1';
elsif INT_ENA(i) = '0' then
IPRA(i-8) <= '0'; -- Clear by disabling the channel.
elsif INT_PASS(i) = '1' then
IPRA(i-8) <= '0'; -- Clear by passing the interrupt.
end if;
end loop;
for i in 7 downto 0 loop
if INT_SRC_EDGE(i) = '1' then
IPRB(i) <= '1';
elsif INT_ENA(i) = '0' then
IPRB(i) <= '0'; -- Clear by disabling the channel.
elsif INT_PASS(i) = '1' then
IPRB(i) <= '0'; -- Clear by passing the interrupt.
end if;
end loop;
-- In-Service register:
-- Set bit logic, VR(3) is the service register enable.
for i in 15 downto 8 loop
if INT_OUT(i) = '1' and INT_PASS(i) = '1' and VR(3) = '1' then
ISRA(i-8) <= '1';
end if;
end loop;
for i in 7 downto 0 loop
if INT_OUT(i) = '1' and INT_PASS(i) = '1' and VR(3) = '1' then
ISRB(i) <= '1';
end if;
end loop;
end if;
end process INT_REGISTERS;
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS > "00010" and RS <= "01011" else '1' when INT_STATE = VECTOR_OUT else '0';
DATA_OUT <= IERA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00011" else
IERB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00100" else
IPRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00101" else
IPRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00110" else
ISRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00111" else
ISRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01000" else
IMRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01001" else
IMRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01010" else
VR & "000" when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01011" else
VECT_NUMBER when INT_STATE = VECTOR_OUT else x"00";
P_INT_STATE : process(RESETn, CLK)
begin
if RESETn = '0' then
INT_STATE <= SCAN;
elsif CLK = '1' and CLK' event then
case INT_STATE is
when SCAN =>
INT_PASS <= x"0000";
-- Automatic End of Interrupt mode. Service register disabled.
-- The MFP does not respond for an interrupt acknowledge cycle for an uninitialized
-- vector number (VR(7 downto 4) = x"0").
if INT_OUT /= x"0000" and VR(7 downto 4) /= x"0" and VR(3) = '0' and IEIn = '0' then
INT_STATE <= REQUEST; -- Non masked interrupt is pending.
-- The following 16 are the Software end of interrupt mode. Service register enabled.
-- The MFP does not respond for an interrupt acknowledge cycle for an uninitialized
-- vector number (VR(7 downto 4) = x"0"). The interrupts are prioritized.
elsif INT_OUT /= x"0000" and VR(7 downto 4) /= x"0" and VR(3) = '1' and IEIn = '0' then
if INT_OUT (15) = '1' and INT_SERVICE(15) = '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (14) = '1' and INT_SERVICE(15 downto 14) = "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (13) = '1' and INT_SERVICE(15 downto 13) = "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (12) = '1' and INT_SERVICE(15 downto 12) = x"0" then
INT_STATE <= REQUEST;
elsif INT_OUT (11) = '1' and INT_SERVICE(15 downto 11) = x"0" & '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (10) = '1' and INT_SERVICE(15 downto 10) = x"0" & "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (9) = '1' and INT_SERVICE(15 downto 9) = x"0" & "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (8) = '1' and INT_SERVICE(15 downto 8) = x"00" then
INT_STATE <= REQUEST;
elsif INT_OUT (7) = '1' and INT_SERVICE(15 downto 7) = x"00" & '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (6) = '1' and INT_SERVICE(15 downto 6) = x"00" & "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (5) = '1' and INT_SERVICE(15 downto 5) = x"00" & "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (4) = '1' and INT_SERVICE(15 downto 4) = x"000" then
INT_STATE <= REQUEST;
elsif INT_OUT (3) = '1' and INT_SERVICE(15 downto 3) = x"000" & '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (2) = '1' and INT_SERVICE(15 downto 2) = x"000" & "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (1) = '1' and INT_SERVICE(15 downto 1) = x"000" & "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (0) = '1' and INT_SERVICE(15 downto 0) = x"0000" then
INT_STATE <= REQUEST;
else
INT_STATE <= SCAN; -- Wait for interrupt.
end if;
else
INT_STATE <= SCAN;
end if;
when REQUEST =>
if IACKn = '0' and DSn = '0' then -- Vectored interrupt mode.
INT_STATE <= VECTOR_OUT; -- Non masked interrupt is pending.
if INT_OUT(15) = '1' then
INT_PASS(15) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"F"; -- GPI 7.
elsif INT_OUT(14) = '1' then
INT_PASS(14) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"E"; -- GPI 6.
elsif INT_OUT(13) = '1' then
INT_PASS(13) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"D"; -- TIMER A.
elsif INT_OUT(12) = '1' then
INT_PASS(12) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"C"; -- Receive buffer full.
elsif INT_OUT(11) = '1' then
INT_PASS(11) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"B"; -- Receiver error.
elsif INT_OUT(10) = '1' then
INT_PASS(10) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"A"; -- Transmit buffer empty.
elsif INT_OUT(9) = '1' then
INT_PASS(9) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"9"; -- Transmit error.
elsif INT_OUT(8) = '1' then
INT_PASS(8) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"8"; -- Timer B.
elsif INT_OUT(7) = '1' then
INT_PASS(7) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"7"; -- GPI 5.
elsif INT_OUT(6) = '1' then
INT_PASS(6) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"6"; -- GPI 4.
elsif INT_OUT(5) = '1' then
INT_PASS(5) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"5"; -- Timer C.
elsif INT_OUT(4) = '1' then
INT_PASS(4) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"4"; -- Timer D.
elsif INT_OUT(3) = '1' then
INT_PASS(3) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"3"; -- GPI 3.
elsif INT_OUT(2) = '1' then
INT_PASS(2) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"2"; -- GPI 2.
elsif INT_OUT(1) = '1' then
INT_PASS(1) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"1"; -- GPI 1.
elsif INT_OUT(0) = '1' then
INT_PASS(0) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"0"; -- GPI 0.
end if;
-- Polled interrupt mode: End of interrupt by writing to the pending registers.
elsif CSn = '0' and DSn = '0' and RWn = '0' and (RS = "00101" or RS = "00110") then
INT_STATE <= SCAN;
else
INT_STATE <= REQUEST; -- Wait.
end if;
when VECTOR_OUT =>
INT_PASS <= x"0000";
if DSn = '1' or IACKn = '1' then
INT_STATE <= SCAN; -- Finished.
else
INT_STATE <= VECTOR_OUT; -- Wait for processor to read the vector.
end if;
end case;
end if;
end process P_INT_STATE;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,263 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the package file containing the component ----
---- declarations. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
package WF68901IP_PKG is
component WF68901IP_USART_TOP
port ( CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
RC : in bit;
TC : in bit;
SI : in bit;
SO : out bit;
SO_EN : out bit;
RX_ERR_INT : out bit;
RX_BUFF_INT : out bit;
TX_ERR_INT : out bit;
TX_BUFF_INT : out bit;
RRn : out bit;
TRn : out bit
);
end component;
component WF68901IP_USART_CTRL
port (
CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
RX_SAMPLE : in bit;
RX_DATA : in bit_vector(7 downto 0);
TX_DATA : out bit_vector(7 downto 0);
SCR_OUT : out bit_vector(7 downto 0);
BF : in bit;
BE : in bit;
FE : in bit;
OE : in bit;
UE : in bit;
PE : in bit;
M_CIP : in bit;
FS_B : in bit;
TX_END : in bit;
CL : out bit_vector(1 downto 0);
ST : out bit_vector(1 downto 0);
FS_CLR : out bit;
RSR_READ : out bit;
TSR_READ : out bit;
UDR_READ : out bit;
UDR_WRITE : out bit;
LOOPBACK : out bit;
SDOUT_EN : out bit;
SD_LEVEL : out bit;
CLK_MODE : out bit;
RE : out bit;
TE : out bit;
P_ENA : out bit;
P_EOn : out bit;
SS : out bit;
BR : out bit
);
end component;
component WF68901IP_USART_TX
port (
CLK : in bit;
RESETn : in bit;
SCR : in bit_vector(7 downto 0);
TX_DATA : in bit_vector(7 downto 0);
SDATA_OUT : out bit;
TXCLK : in bit;
CL : in bit_vector(1 downto 0);
ST : in bit_vector(1 downto 0);
TE : in bit;
BR : in bit;
P_ENA : in bit;
P_EOn : in bit;
UDR_WRITE : in bit;
TSR_READ : in bit;
CLK_MODE : in bit;
TX_END : out bit;
UE : out bit;
BE : out bit
);
end component;
component WF68901IP_USART_RX
port (
CLK : in bit;
RESETn : in bit;
SCR : in bit_vector(7 downto 0);
RX_SAMPLE : out bit;
RX_DATA : out bit_vector(7 downto 0);
RXCLK : in bit;
SDATA_IN : in bit;
CL : in bit_vector(1 downto 0);
ST : in bit_vector(1 downto 0);
P_ENA : in bit;
P_EOn : in bit;
CLK_MODE : in bit;
RE : in bit;
FS_CLR : in bit;
SS : in bit;
RSR_READ : in bit;
UDR_READ : in bit;
M_CIP : out bit;
FS_B : out bit;
BF : out bit;
OE : out bit;
PE : out bit;
FE : out bit
);
end component;
component WF68901IP_INTERRUPTS
port (
CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
IACKn : in bit;
IEIn : in bit;
IEOn : out bit;
IRQn : out bit;
GP_INT : in bit_vector(7 downto 0);
AER_4 : in bit;
AER_3 : in bit;
TAI : in bit;
TBI : in bit;
TA_PWM : in bit;
TB_PWM : in bit;
TIMER_A_INT : in bit;
TIMER_B_INT : in bit;
TIMER_C_INT : in bit;
TIMER_D_INT : in bit;
RCV_ERR : in bit;
TRM_ERR : in bit;
RCV_BUF_F : in bit;
TRM_BUF_E : in bit
);
end component;
component WF68901IP_GPIO
port (
CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
AER_4 : out bit;
AER_3 : out bit;
GPIP_IN : in bit_vector(7 downto 0);
GPIP_OUT : out bit_vector(7 downto 0);
GPIP_OUT_EN : out bit_vector(7 downto 0);
GP_INT : out bit_vector(7 downto 0)
);
end component;
component WF68901IP_TIMERS
port (
CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
XTAL1 : in bit;
TAI : in bit;
TBI : in bit;
AER_4 : in bit;
AER_3 : in bit;
TA_PWM : out bit;
TB_PWM : out bit;
TAO : out bit;
TBO : out bit;
TCO : out bit;
TDO : out bit;
TIMER_A_INT : out bit;
TIMER_B_INT : out bit;
TIMER_C_INT : out bit;
TIMER_D_INT : out bit
);
end component;
end WF68901IP_PKG;

View File

@@ -0,0 +1,533 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the SUSKA MFP IP core timers logic file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K7A 2006/12/28 WF
-- The timer is modified to work on the CLK instead
-- of XTAL1. This modification is done to provide
-- a synchronous design.
-- Revision 2K8A 2008/02/29 WF
-- Fixed a serious prescaler bug.
-- Revision 2K9A 20090620 WF
-- Introduced timer readback registers.
-- TIMER_x_INT is now a strobe.
-- Minor improvements.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_TIMERS is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
-- Timers and timer control:
XTAL1 : in bit; -- Use an oszillator instead of a quartz.
TAI : in bit;
TBI : in bit;
AER_4 : in bit;
AER_3 : in bit;
TA_PWM : out bit; -- Indicates, that timer A is in PWM mode (used in Interrupt logic).
TB_PWM : out bit; -- Indicates, that timer B is in PWM mode (used in Interrupt logic).
TAO : buffer bit;
TBO : buffer bit;
TCO : buffer bit;
TDO : buffer bit;
TIMER_A_INT : out bit;
TIMER_B_INT : out bit;
TIMER_C_INT : out bit;
TIMER_D_INT : out bit
);
end entity WF68901IP_TIMERS;
architecture BEHAVIOR of WF68901IP_TIMERS is
signal XTAL1_S : bit;
signal XTAL_STRB : bit;
signal TACR : bit_vector(4 downto 0); -- Timer A control register.
signal TBCR : bit_vector(4 downto 0); -- Timer B control register.
signal TCDCR : bit_vector(5 downto 0); -- Timer C and D control register.
signal TADR : bit_vector(7 downto 0); -- Timer A data register.
signal TBDR : bit_vector(7 downto 0); -- Timer B data register.
signal TCDR : bit_vector(7 downto 0); -- Timer C data register.
signal TDDR : bit_vector(7 downto 0); -- Timer D data register.
signal TIMER_A : std_logic_vector(7 downto 0); -- Timer A count register.
signal TIMER_B : std_logic_vector(7 downto 0); -- Timer B count register.
signal TIMER_C : std_logic_vector(7 downto 0); -- Timer C count register.
signal TIMER_D : std_logic_vector(7 downto 0); -- Timer D count register.
signal TIMER_R_A : bit_vector(7 downto 0); -- Timer A readback register.
signal TIMER_R_B : bit_vector(7 downto 0); -- Timer B readback register.
signal TIMER_R_C : bit_vector(7 downto 0); -- Timer C readback register.
signal TIMER_R_D : bit_vector(7 downto 0); -- Timer D readback register.
signal A_CNTSTRB : bit;
signal B_CNTSTRB : bit;
signal C_CNTSTRB : bit;
signal D_CNTSTRB : bit;
signal TAI_I : bit;
signal TBI_I : bit;
signal TAI_STRB : bit; -- Strobe for the event counter mode.
signal TBI_STRB : bit; -- Strobe for the event counter mode.
signal TAO_I : bit; -- Timer A output signal.
signal TBO_I : bit; -- Timer A output signal.
begin
SYNC: process
-- This process provides a 'clean' XTAL1.
-- Without this sync, the edge detector for
-- XTAL_STRB does not work properly.
begin
wait until CLK = '1' and CLK' event;
XTAL1_S <= XTAL1;
-- Polarity control for the event counter and the PWM mode:
TAI_I <= TAI xnor AER_4;
TBI_I <= TBI xnor AER_3;
end process SYNC;
-- Output enables for timer A and timer B:
-- The outputs are held low for asserted reset flags in the control registers TACR
-- and TBCR but also during a write operation to these registers.
TAO <= '0' when TACR(4) = '1' else
'0' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "01100" else TAO_I;
TBO <= '0' when TBCR(4) = '1' else
'0' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "01101" else TBO_I;
-- Control outputs for the PWM modi of the timers A and B. These
-- controls are used in the interrupt logic to select the interrupt
-- sources GPIP4 or TAI repective GPIP3 or TBI.
TA_PWM <= '1' when TACR(3 downto 0) > x"8" else '0';
TB_PWM <= '1' when TBCR(3 downto 0) > x"8" else '0';
TIMER_REGISTERS: process(RESETn, CLK)
begin
if RESETn = '0' then
TACR <= (others => '0');
TBCR <= (others => '0');
TCDCR <= (others => '0');
-- TADR <= Do not clear during reset!
-- TBDR <= Do not clear during reset!
-- TCDR <= Do not clear during reset!
-- TDDR <= Do not clear during reset!
elsif CLK = '1' and CLK' event then
if CSn = '0' and DSn = '0' and RWn = '0' then
case RS is
when "01100" => TACR <= DATA_IN(4 downto 0);
when "01101" => TBCR <= DATA_IN(4 downto 0);
when "01110" => TCDCR <= DATA_IN(6 downto 4) & DATA_IN(2 downto 0);
when "01111" => TADR <= DATA_IN;
when "10000" => TBDR <= DATA_IN;
when "10001" => TCDR <= DATA_IN;
when "10010" => TDDR <= DATA_IN;
when others => null;
end case;
end if;
end if;
end process TIMER_REGISTERS;
TIMER_READBACK : process(RESETn, CLK)
-- This process provides the readback information for the
-- timers A to D. The information read is the information
-- last clocked into the timer read register when the DSn
-- pin had last gone high prior to the current read cycle.
variable READ_A : boolean;
variable READ_B : boolean;
variable READ_C : boolean;
variable READ_D : boolean;
begin
if RESETn = '0' then
TIMER_R_A <= x"00";
TIMER_R_B <= x"00";
TIMER_R_C <= x"00";
TIMER_R_D <= x"00";
elsif CLK = '1' and CLK' event then
if DSn = '0' and RS = "01111" then
READ_A := true;
elsif DSn = '0' and RS = "10000" then
READ_B := true;
elsif DSn = '0' and RS = "10001" then
READ_C := true;
elsif DSn = '0' and RS = "10010" then
READ_D := true;
elsif DSn = '1' and READ_A = true then
TIMER_R_A <= To_BitVector(TIMER_A);
READ_A := false;
elsif DSn = '1' and READ_B = true then
TIMER_R_B <= To_BitVector(TIMER_B);
READ_B := false;
elsif DSn = '1' and READ_C = true then
TIMER_R_C <= To_BitVector(TIMER_C);
READ_C := false;
elsif DSn = '1' and READ_D = true then
TIMER_R_D <= To_BitVector(TIMER_D);
READ_D := false;
end if;
end if;
end process TIMER_READBACK;
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS > "01011" and RS <= "10010" else '0';
DATA_OUT <= "000" & TACR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01100" else
"000" & TBCR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01101" else
'0' & TCDCR(5 downto 3) & '0' & TCDCR(2 downto 0) when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01110" else
TIMER_R_A when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01111" else
TIMER_R_B when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10000" else
TIMER_R_C when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10001" else
TIMER_R_D when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10010" else (others => '0');
XTAL_STROBE: process(RESETn, CLK)
-- This process provides a strobe with 1 clock cycle
-- (CLK) length after every rising edge of XTAL1.
variable LOCK : boolean;
begin
if RESETn = '0' then
XTAL_STRB <= '0';
elsif CLK = '1' and CLK' event then
if XTAL1_S = '1' and LOCK = false then
XTAL_STRB <= '1';
LOCK := true;
elsif XTAL1_S = '0' then
XTAL_STRB <= '0';
LOCK := false;
else
XTAL_STRB <= '0';
end if;
end if;
end process XTAL_STROBE;
TAI_STROBE: process(RESETn, CLK)
variable LOCK : boolean;
begin
if RESETn = '0' then
TAI_STRB <= '0';
elsif CLK = '1' and CLK' event then
if TAI_I = '1' and XTAL_STRB = '1' and LOCK = false then
LOCK := true;
TAI_STRB <= '1';
elsif TAI_I = '0' then
LOCK := false;
TAI_STRB <= '0';
else
TAI_STRB <= '0';
end if;
end if;
end process TAI_STROBE;
TBI_STROBE: process(RESETn, CLK)
variable LOCK : boolean;
begin
if RESETn = '0' then
TBI_STRB <= '0';
elsif CLK = '1' and CLK' event then
if TBI_I = '1' and XTAL_STRB = '1' and LOCK = false then
LOCK := true;
TBI_STRB <= '1';
elsif TBI_I = '0' then
LOCK := false;
TBI_STRB <= '0';
else
TBI_STRB <= '0';
end if;
end if;
end process TBI_STROBE;
PRESCALE_A: process
-- The prescalers work even if the RESETn is asserted.
variable PRESCALE : std_logic_vector(7 downto 0);
begin
wait until CLK = '1' and CLK' event;
A_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - '1';
elsif XTAL_STRB = '1' then
case TACR(2 downto 0) is
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
when "000" => PRESCALE := x"00"; -- Timer stopped or event count mode.
end case;
A_CNTSTRB <= '1';
end if;
end process PRESCALE_A;
PRESCALE_B: process
-- The prescalers work even if the RESETn is asserted.
variable PRESCALE : std_logic_vector(7 downto 0);
begin
wait until CLK = '1' and CLK' event;
B_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - '1';
elsif XTAL_STRB = '1' then
case TBCR(2 downto 0) is
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
when "000" => PRESCALE := x"00"; -- Timer stopped or event count mode.
end case;
B_CNTSTRB <= '1';
end if;
end process PRESCALE_B;
PRESCALE_C: process
-- The prescalers work even if the RESETn is asserted.
variable PRESCALE : std_logic_vector(7 downto 0);
begin
wait until CLK = '1' and CLK' event;
C_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - '1';
elsif XTAL_STRB = '1' then
case TCDCR(5 downto 3) is
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
when "000" => PRESCALE := x"00"; -- Timer stopped.
end case;
C_CNTSTRB <= '1';
end if;
end process PRESCALE_C;
PRESCALE_D: process
-- The prescalers work even if the RESETn is asserted.
variable PRESCALE : std_logic_vector(7 downto 0);
begin
wait until CLK = '1' and CLK' event;
D_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - '1';
elsif XTAL_STRB = '1' then
case TCDCR(2 downto 0) is
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
when "000" => PRESCALE := x"00"; -- Timer stopped.
end case;
D_CNTSTRB <= '1';
end if;
end process PRESCALE_D;
TIMERA: process(RESETn, CLK)
begin
if RESETn = '0' then
-- Do not clear the timer registers during system reset.
TAO_I <= '0';
TIMER_A_INT <= '0';
elsif CLK = '1' and CLK' event then
TIMER_A_INT <= '0';
--
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "01111" and TACR(3 downto 0) = x"0" then
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
-- The loading works asynchronous due to the possibly low XTAL1 clock.
TIMER_A <= To_StdLogicVector(DATA_IN);
else
case TACR(3 downto 0) is
when x"0" => -- Timer is off.
TAO_I <= '0';
when x"1" | x"2" | x"3" | x"4" | x"5" | x"6" | x"7" => -- Delay counter mode.
if A_CNTSTRB = '1' and TIMER_A /= x"01" then -- Count.
TIMER_A <= TIMER_A - '1';
elsif A_CNTSTRB = '1' and TIMER_A = x"01" then -- Reload.
TIMER_A <= To_StdLogicVector(TADR);
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
TIMER_A_INT <= '1';
end if;
when x"8" => -- Event count operation.
if TAI_STRB = '1' and TIMER_A /= x"01" then -- Count.
TIMER_A <= TIMER_A - '1';
elsif TAI_STRB = '1' and TIMER_A = x"01" then -- Reload.
TIMER_A <= To_StdLogicVector(TADR);
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
TIMER_A_INT <= '1';
end if;
when x"9" | x"A" | x"B" | x"C" | x"D" | x"E" | x"F" => -- PWM mode.
if TAI_I = '1' and A_CNTSTRB = '1' and TIMER_A /= x"01" then -- Count.
TIMER_A <= TIMER_A - '1';
elsif TAI_I = '1' and A_CNTSTRB = '1' and TIMER_A = x"01" then -- Reload.
TIMER_A <= To_StdLogicVector(TADR);
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
TIMER_A_INT <= '1';
end if;
end case;
end if;
end if;
end process TIMERA;
TIMERB: process(RESETn, CLK)
begin
if RESETn = '0' then
-- Do not clear the timer registers during system reset.
TBO_I <= '0';
TIMER_B_INT <= '0';
elsif CLK = '1' and CLK' event then
TIMER_B_INT <= '0';
--
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10000" and TBCR(3 downto 0) = x"0" then
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
-- The loading works asynchronous due to the possibly low XTAL1 clock.
TIMER_B <= To_StdLogicVector(DATA_IN);
else
case TBCR(3 downto 0) is
when x"0" => -- Timer is off.
TBO_I <= '0';
when x"1" | x"2" | x"3" | x"4" | x"5" | x"6" | x"7" => -- Delay counter mode.
if B_CNTSTRB = '1' and TIMER_B /= x"01" then -- Count.
TIMER_B <= TIMER_B - '1';
elsif B_CNTSTRB = '1' and TIMER_B = x"01" then -- Reload.
TIMER_B <= To_StdLogicVector(TBDR);
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
TIMER_B_INT <= '1';
end if;
when x"8" => -- Event count operation.
if TBI_STRB = '1' and TIMER_B /= x"01" then -- Count.
TIMER_B <= TIMER_B - '1';
elsif TBI_STRB = '1' and TIMER_B = x"01" then -- Reload.
TIMER_B <= To_StdLogicVector(TBDR);
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
TIMER_B_INT <= '1';
end if;
when x"9" | x"A" | x"B" | x"C" | x"D" | x"E" | x"F" => -- PWM mode.
if TBI_I = '1' and B_CNTSTRB = '1' and TIMER_B /= x"01" then -- Count.
TIMER_B <= TIMER_B - '1';
elsif TBI_I = '1' and B_CNTSTRB = '1' and TIMER_B = x"01" then -- Reload.
TIMER_B <= To_StdLogicVector(TBDR);
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
TIMER_B_INT <= '1';
end if;
end case;
end if;
end if;
end process TIMERB;
TIMERC: process(RESETn, CLK)
begin
if RESETn = '0' then
-- Do not clear the timer registers during system reset.
TCO <= '0';
TIMER_C_INT <= '0';
elsif CLK = '1' and CLK' event then
TIMER_C_INT <= '0';
--
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10001" and TCDCR(5 downto 3) = "000" then
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
-- The loading works asynchronous due to the possibly low XTAL1 clock.
TIMER_C <= To_StdLogicVector(DATA_IN);
else
case TCDCR(5 downto 3) is
when "000" => -- Timer is off.
TCO <= '0';
when others => -- Delay counter mode.
if C_CNTSTRB = '1' and TIMER_C /= x"01" then -- Count.
TIMER_C <= TIMER_C - '1';
elsif C_CNTSTRB = '1' and TIMER_C = x"01" then -- Reload.
TIMER_C <= To_StdLogicVector(TCDR);
TCO <= not TCO; -- Toggle the timer C output pin.
TIMER_C_INT <= '1';
end if;
end case;
end if;
end if;
end process TIMERC;
TIMERD: process(RESETn, CLK)
begin
if RESETn = '0' then
-- Do not clear the timer registers during system reset.
TDO <= '0';
TIMER_D_INT <= '0';
elsif CLK = '1' and CLK' event then
TIMER_D_INT <= '0';
--
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10010" and TCDCR(2 downto 0) = "000" then
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
-- The loading works asynchronous due to the possibly low XTAL1 clock.
TIMER_D <= To_StdLogicVector(DATA_IN);
else
case TCDCR(2 downto 0) is
when "000" => -- Timer is off.
TDO <= '0';
when others => -- Delay counter mode.
if D_CNTSTRB = '1' and TIMER_D /= x"01" then -- Count.
TIMER_D <= TIMER_D - '1';
elsif D_CNTSTRB = '1' and TIMER_D = x"01" then -- Reload.
TIMER_D <= To_StdLogicVector(TDDR);
TDO <= not TDO; -- Toggle the timer D output pin.
TIMER_D_INT <= '1';
end if;
end case;
end if;
end if;
end process TIMERD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,213 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the SUSKA MFP IP core top level file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K7A 2006/12/28 WF
-- The timer is modified to work on the CLK instead
-- of XTAL1. This modification is done to provide
-- a synchronous design.
-- Revision 2K8B 2008/12/24 WF
-- Rewritten this top level file as a wrapper for the top_soc file.
--
use work.wf68901ip_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_TOP is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
DTACKn : out std_logic;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA : inout std_logic_vector(7 downto 0);
GPIP : inout std_logic_vector(7 downto 0);
-- Interrupt control:
IACKn : in bit;
IEIn : in bit;
IEOn : out bit;
IRQn : out std_logic;
-- Timers and timer control:
XTAL1 : in bit; -- Use an oszillator instead of a quartz.
TAI : in bit;
TBI : in bit;
TAO : out bit;
TBO : out bit;
TCO : out bit;
TDO : out bit;
-- Serial I/O control:
RC : in bit;
TC : in bit;
SI : in bit;
SO : out std_logic;
-- DMA control:
RRn : out bit;
TRn : out bit
);
end entity WF68901IP_TOP;
architecture STRUCTURE of WF68901IP_TOP is
component WF68901IP_TOP_SOC
port(CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
DTACKn : out bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
GPIP_IN : in bit_vector(7 downto 0);
GPIP_OUT : out bit_vector(7 downto 0);
GPIP_EN : out bit_vector(7 downto 0);
IACKn : in bit;
IEIn : in bit;
IEOn : out bit;
IRQn : out bit;
XTAL1 : in bit;
TAI : in bit;
TBI : in bit;
TAO : out bit;
TBO : out bit;
TCO : out bit;
TDO : out bit;
RC : in bit;
TC : in bit;
SI : in bit;
SO : out bit;
SO_EN : out bit;
RRn : out bit;
TRn : out bit
);
end component;
--
signal DTACK_In : bit;
signal IRQ_In : bit;
signal DATA_OUT : std_logic_vector(7 downto 0);
signal DATA_EN : bit;
signal GPIP_IN : bit_vector(7 downto 0);
signal GPIP_OUT : bit_vector(7 downto 0);
signal GPIP_EN : bit_vector(7 downto 0);
signal SO_I : bit;
signal SO_EN : bit;
begin
DTACKn <= '0' when DTACK_In = '0' else 'Z'; -- Open drain.
IRQn <= '0' when IRQ_In = '0' else 'Z'; -- Open drain.
DATA <= DATA_OUT when DATA_EN = '1' else (others => 'Z');
GPIP_IN <= To_BitVector(GPIP);
P_GPIP_OUT: process(GPIP_OUT, GPIP_EN)
begin
for i in 7 downto 0 loop
if GPIP_EN(i) = '1' then
case GPIP_OUT(i) is
when '0' => GPIP(i) <= '0';
when others => GPIP(i) <= '1';
end case;
else
GPIP(i) <= 'Z';
end if;
end loop;
end process P_GPIP_OUT;
SO <= '0' when SO_I = '0' and SO_EN = '1' else
'1' when SO_I = '1' and SO_EN = '1' else 'Z';
I_MFP: WF68901IP_TOP_SOC
port map(CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
DTACKn => DTACK_In,
RS => RS,
DATA_IN => DATA,
DATA_OUT => DATA_OUT,
DATA_EN => DATA_EN,
GPIP_IN => GPIP_IN,
GPIP_OUT => GPIP_OUT,
GPIP_EN => GPIP_EN,
IACKn => IACKn,
IEIn => IEIn,
IEOn => IEOn,
IRQn => IRQ_In,
XTAL1 => XTAL1,
TAI => TAI,
TBI => TBI,
TAO => TAO,
TBO => TBO,
TCO => TCO,
TDO => TDO,
RC => RC,
TC => TC,
SI => SI,
SO => SO_I,
SO_EN => SO_EN,
RRn => RRn,
TRn => TRn
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,309 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the SUSKA MFP IP core top level file. ----
---- Top level file for use in systems on programmable chips. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Top level file provided for SOC (systems on programmable chips).
-- Revision 2K7A 2006/12/28 WF
-- The timer is modified to work on the CLK instead
-- of XTAL1. This modification is done to provide
-- a synchronous design.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- DTACK_OUTn has now synchronous reset to meet preset requirement.
--
--
use work.wf68901ip_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_TOP_SOC is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
DTACKn : out bit;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
GPIP_IN : in bit_vector(7 downto 0);
GPIP_OUT : out bit_vector(7 downto 0);
GPIP_EN : out bit_vector(7 downto 0);
-- Interrupt control:
IACKn : in bit;
IEIn : in bit;
IEOn : out bit;
IRQn : out bit;
-- Timers and timer control:
XTAL1 : in bit; -- Use an oszillator instead of a quartz.
TAI : in bit;
TBI : in bit;
TAO : out bit;
TBO : out bit;
TCO : out bit;
TDO : out bit;
-- Serial I/O control:
RC : in bit;
TC : in bit;
SI : in bit;
SO : out bit;
SO_EN : out bit;
-- DMA control:
RRn : out bit;
TRn : out bit
);
end entity WF68901IP_TOP_SOC;
architecture STRUCTURE of WF68901IP_TOP_SOC is
signal DATA_IN_I : bit_vector(7 downto 0);
signal DTACK_In : bit;
signal DTACK_LOCK : boolean;
signal DTACK_OUTn : bit;
signal RX_ERR_INT_I : bit;
signal TX_ERR_INT_I : bit;
signal RX_BUFF_INT_I : bit;
signal TX_BUFF_INT_I : bit;
signal DATA_OUT_USART_I : bit_vector(7 downto 0);
signal DATA_OUT_EN_USART_I : bit;
signal DATA_OUT_INT_I : bit_vector(7 downto 0);
signal DATA_OUT_EN_INT_I : bit;
signal DATA_OUT_GPIO_I : bit_vector(7 downto 0);
signal DATA_OUT_EN_GPIO_I : bit;
signal DATA_OUT_TIMERS_I : bit_vector(7 downto 0);
signal DATA_OUT_EN_TIMERS_I : bit;
signal SO_I : bit;
signal SO_EN_I : bit;
signal GPIP_IN_I : bit_vector(7 downto 0);
signal GPIP_OUT_I : bit_vector(7 downto 0);
signal GPIP_EN_I : bit_vector(7 downto 0);
signal GP_INT_I : bit_vector(7 downto 0);
signal TIMER_A_INT_I : bit;
signal TIMER_B_INT_I : bit;
signal TIMER_C_INT_I : bit;
signal TIMER_D_INT_I : bit;
signal IRQ_In : bit;
signal AER_4_I : bit;
signal AER_3_I : bit;
signal TA_PWM_I : bit;
signal TB_PWM_I : bit;
begin
-- Interrupt request (open drain):
IRQn <= IRQ_In;
-- Serial data output:
SO <= SO_I;
SO_EN <= SO_EN_I and RESETn;
-- General purpose port:
GPIP_IN_I <= GPIP_IN;
GPIP_OUT <= GPIP_OUT_I;
GPIP_EN <= GPIP_EN_I;
DATA_IN_I <= To_BitVector(DATA_IN);
DATA_EN <= DATA_OUT_EN_USART_I or DATA_OUT_EN_INT_I or DATA_OUT_EN_GPIO_I or DATA_OUT_EN_TIMERS_I;
-- Output data multiplexer:
DATA_OUT <= To_StdLogicVector(DATA_OUT_USART_I) when DATA_OUT_EN_USART_I = '1' else
To_StdLogicVector(DATA_OUT_INT_I) when DATA_OUT_EN_INT_I = '1' else
To_StdLogicVector(DATA_OUT_GPIO_I) when DATA_OUT_EN_GPIO_I = '1' else
To_StdLogicVector(DATA_OUT_TIMERS_I) when DATA_OUT_EN_TIMERS_I = '1' else (others => '1');
-- Data acknowledge handshake is provided by the following statement and the consecutive two
-- processes. For more information refer to the M68000 family reference manual.
DTACK_In <= '0' when CSn = '0' and DSn = '0' and RS <= "10111" else -- Read and write operation.
'0' when IACKn = '0' and DSn = '0' and IEIn = '0' else '1'; -- Interrupt vector data acknowledge.
P_DTACK_LOCK: process
-- This process releases a data acknowledge detect, one rising clock
-- edge after the DTACK_In occured. This is necessary to ensure write
-- data to registers for there is one rising clock edge required.
begin
wait until CLK = '1' and CLK' event;
if DTACK_In = '0' then
DTACK_LOCK <= false;
else
DTACK_LOCK <= true;
end if;
end process P_DTACK_LOCK;
DTACK_OUT: process
-- The DTACKn port pin is released on the falling clock edge after the data
-- acknowledge detect (DTACK_LOCK) is asserted. The DTACKn is deasserted
-- immediately when there is no further register access DTACK_In = '1';
begin
wait until CLK = '0' and CLK' event;
if RESETn = '0' then
DTACK_OUTn <= '1';
elsif DTACK_In = '1' then
DTACK_OUTn <= '1';
elsif DTACK_LOCK = false then
DTACK_OUTn <= '0';
end if;
end process DTACK_OUT;
DTACKn <= '0' when DTACK_OUTn = '0' else '1';
I_USART: WF68901IP_USART_TOP
port map(
CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
DATA_OUT => DATA_OUT_USART_I,
DATA_OUT_EN => DATA_OUT_EN_USART_I,
RC => RC,
TC => TC,
SI => SI,
SO => SO_I,
SO_EN => SO_EN_I,
RX_ERR_INT => RX_ERR_INT_I,
RX_BUFF_INT => RX_BUFF_INT_I,
TX_ERR_INT => TX_ERR_INT_I,
TX_BUFF_INT => TX_BUFF_INT_I,
RRn => RRn,
TRn => TRn
);
I_INTERRUPTS: WF68901IP_INTERRUPTS
port map(
CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
DATA_OUT => DATA_OUT_INT_I,
DATA_OUT_EN => DATA_OUT_EN_INT_I,
IACKn => IACKn,
IEIn => IEIn,
IEOn => IEOn,
IRQn => IRQ_In,
GP_INT => GP_INT_I,
AER_4 => AER_4_I,
AER_3 => AER_3_I,
TAI => TAI,
TBI => TBI,
TA_PWM => TA_PWM_I,
TB_PWM => TB_PWM_I,
TIMER_A_INT => TIMER_A_INT_I,
TIMER_B_INT => TIMER_B_INT_I,
TIMER_C_INT => TIMER_C_INT_I,
TIMER_D_INT => TIMER_D_INT_I,
RCV_ERR => RX_ERR_INT_I,
TRM_ERR => TX_ERR_INT_I,
RCV_BUF_F => RX_BUFF_INT_I,
TRM_BUF_E => TX_BUFF_INT_I
);
I_GPIO: WF68901IP_GPIO
port map(
CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
DATA_OUT => DATA_OUT_GPIO_I,
DATA_OUT_EN => DATA_OUT_EN_GPIO_I,
AER_4 => AER_4_I,
AER_3 => AER_3_I,
GPIP_IN => GPIP_IN_I,
GPIP_OUT => GPIP_OUT_I,
GPIP_OUT_EN => GPIP_EN_I,
GP_INT => GP_INT_I
);
I_TIMERS: WF68901IP_TIMERS
port map(
CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
DATA_OUT => DATA_OUT_TIMERS_I,
DATA_OUT_EN => DATA_OUT_EN_TIMERS_I,
XTAL1 => XTAL1,
AER_4 => AER_4_I,
AER_3 => AER_3_I,
TAI => TAI,
TBI => TBI,
TAO => TAO,
TBO => TBO,
TCO => TCO,
TDO => TDO,
TA_PWM => TA_PWM_I,
TB_PWM => TB_PWM_I,
TIMER_A_INT => TIMER_A_INT_I,
TIMER_B_INT => TIMER_B_INT_I,
TIMER_C_INT => TIMER_C_INT_I,
TIMER_D_INT => TIMER_D_INT_I
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,191 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- This is the SUSKA MFP IP core USART control file. ----
---- ----
---- Control unit and status logic. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_USART_CTRL is
port (
-- System Control:
CLK : in bit;
RESETn : in bit;
-- Bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
-- USART data register
RX_SAMPLE : in bit;
RX_DATA : in bit_vector(7 downto 0);
TX_DATA : out bit_vector(7 downto 0);
SCR_OUT : out bit_vector(7 downto 0);
-- USART control inputs:
BF : in bit;
BE : in bit;
FE : in bit;
OE : in bit;
UE : in bit;
PE : in bit;
M_CIP : in bit;
FS_B : in bit;
TX_END : in bit;
-- USART control outputs:
CL : out bit_vector(1 downto 0);
ST : out bit_vector(1 downto 0);
FS_CLR : out bit;
UDR_WRITE : out bit;
UDR_READ : out bit;
RSR_READ : out bit;
TSR_READ : out bit;
LOOPBACK : out bit;
SDOUT_EN : out bit;
SD_LEVEL : out bit;
CLK_MODE : out bit;
RE : out bit;
TE : out bit;
P_ENA : out bit;
P_EOn : out bit;
SS : out bit;
BR : out bit
);
end entity WF68901IP_USART_CTRL;
architecture BEHAVIOR of WF68901IP_USART_CTRL is
signal SCR : bit_vector(7 downto 0); -- Synchronous data register.
signal UCR : bit_vector(7 downto 1); -- USART control register.
signal RSR : bit_vector(7 downto 0); -- Receiver status register.
signal TSR : bit_vector(7 downto 0); -- Transmitter status register.
signal UDR : bit_vector(7 downto 0); -- USART data register.
begin
USART_REGISTERS: process(RESETn, CLK)
begin
if RESETn = '0' then
SCR <= (others => '0');
UCR <= (others => '0');
RSR <= (others => '0');
-- TSR and UDR are not cleared during an asserted RESETn
elsif CLK = '1' and CLK' event then
-- Loading via receiver shift register
-- has priority over data buss access:
if RX_SAMPLE = '1' then
UDR <= RX_DATA;
elsif CSn = '0' and DSn = '0' and RWn = '0' then
case RS is
when "10011" => SCR <= DATA_IN;
when "10100" => UCR <= DATA_IN(7 downto 1);
when "10101" => RSR(1 downto 0) <= DATA_IN(1 downto 0); -- Only the two LSB are read/write.
when "10110" => TSR(5) <= DATA_IN(5); TSR(3 downto 0) <= DATA_IN(3 downto 0);
when "10111" => UDR <= DATA_IN;
when others => null;
end case;
end if;
RSR(7 downto 2) <= BF & OE & PE & FE & FS_B & M_CIP;
TSR(7 downto 6) <= BE & UE;
TSR(4) <= TX_END;
TX_DATA <= UDR;
end if;
end process USART_REGISTERS;
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS >= "10011" and RS <= "10111" else '0';
DATA_OUT <= SCR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10011" else
UCR & '0' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10100" else
RSR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10101" else
TSR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10110" else
UDR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10111" else x"00";
UDR_WRITE <= '1' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "10111" else '0';
UDR_READ <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10111" else '0';
RSR_READ <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10101" else '0';
TSR_READ <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10110" else '0';
FS_CLR <= '1' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "10011" else '0';
RE <= '1' when RSR(0) = '1' else -- Receiver enable.
'1' when TSR(5) = '1' and TX_END = '1' else '0'; -- Auto Turnaround.
SS <= RSR(1); -- Synchronous strip enable.
BR <= TSR(3); -- Send break.
TE <= TSR(0); -- Transmitter enable.
SCR_OUT <= SCR;
CLK_MODE <= UCR(7); -- Clock mode.
CL <= UCR(6 downto 5); -- Character length.
ST <= UCR(4 downto 3); -- Start/Stop configuration.
P_ENA <= UCR(2); -- Parity enable.
P_EOn <= UCR(1); -- Even or odd parity.
SOUT_CONFIG: process
begin
wait until CLK = '1' and CLK' event;
-- Do not change the output configuration until the transmitter is disabled and
-- current character has been transmitted (TX_END = '1').
if TX_END = '1' then
case TSR(2 downto 1) is
when "00" => LOOPBACK <= '0'; SD_LEVEL <= '0'; SDOUT_EN <= '0';
when "01" => LOOPBACK <= '0'; SD_LEVEL <= '0'; SDOUT_EN <= '1';
when "10" => LOOPBACK <= '0'; SD_LEVEL <= '1'; SDOUT_EN <= '1';
when "11" => LOOPBACK <= '1'; SD_LEVEL <= '1'; SDOUT_EN <= '1';
end case;
end if;
end process SOUT_CONFIG;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,590 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- This is the SUSKA MFP IP core USART receiver file. ----
---- ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- Process P_STARTBIT has now synchronous reset to meet preset requirement.
-- Process P_SAMPLE has now synchronous reset to meet preset requirement.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_USART_RX is
port (
CLK : in bit;
RESETn : in bit;
SCR : in bit_vector(7 downto 0); -- Synchronous character.
RX_SAMPLE : buffer bit; -- Flag indicating valid shift register data.
RX_DATA : out bit_vector(7 downto 0); -- Received data.
RXCLK : in bit; -- Receiver clock.
SDATA_IN : in bit; -- Serial data input.
CL : in bit_vector(1 downto 0); -- Character length.
ST : in bit_vector(1 downto 0); -- Start and stop bit configuration.
P_ENA : in bit; -- Parity enable.
P_EOn : in bit; -- Even or odd parity.
CLK_MODE : in bit; -- Clock mode configuration bit.
RE : in bit; -- Receiver enable.
FS_CLR : in bit; -- Clear the Found/Search flag for resynchronisation purpose.
SS : in bit; -- Synchronous strip enable.
UDR_READ : in bit; -- Flag indicating reading the data register.
RSR_READ : in bit; -- Flag indicating reading the receiver status register.
M_CIP : out bit; -- Match/Character in progress.
FS_B : buffer bit; -- Find/Search or Break detect flag.
BF : out bit; -- Buffer full.
OE : out bit; -- Overrun error.
PE : out bit; -- Parity error.
FE : out bit -- Framing error.
);
end entity WF68901IP_USART_RX;
architecture BEHAVIOR of WF68901IP_USART_RX is
type RCV_STATES is (IDLE, WAIT_START, SAMPLE, PARITY, STOP1, STOP2, SYNC);
signal RCV_STATE, RCV_NEXT_STATE : RCV_STATES;
signal SDATA_DIV16 : bit;
signal SDATA_IN_I : bit;
signal SDATA_EDGE : bit;
signal SHIFT_REG : bit_vector(7 downto 0);
signal CLK_STRB : bit;
signal CLK_2_STRB : bit;
signal BITCNT : std_logic_vector(2 downto 0);
signal BREAK : boolean;
signal RDRF : bit;
signal STARTBIT : boolean;
begin
BF <= RDRF; -- Buffer full = Receiver Data Register Full.
RX_SAMPLE <= '1' when RCV_STATE = SYNC and ST /= "00" else -- Asynchronous mode:
-- Synchronous modes:
'1' when RCV_STATE = SYNC and ST = "00" and SS = '0' else
'1' when RCV_STATE = SYNC and ST = "00" and SS = '1' and SHIFT_REG /= SCR else '0';
-- Data multiplexer for the received data:
RX_DATA <= "000" & SHIFT_REG(7 downto 3) when RX_SAMPLE = '1' and CL = "11" else -- 5 databits.
"00" & SHIFT_REG(7 downto 2) when RX_SAMPLE = '1' and CL = "10" else -- 6 databits.
'0' & SHIFT_REG(7 downto 1) when RX_SAMPLE = '1' and CL = "01" else -- 6 databits.
SHIFT_REG when RX_SAMPLE = '1' and CL = "00" else x"00"; -- 8 databits.
P_SAMPLE: process
-- This process provides the 'valid transition logic' of the originally MC68901. For further
-- details see the 'M68000 FAMILY REFERENCE MANUAL'.
variable LOW_FLT : std_logic_vector(1 downto 0);
variable HI_FLT : std_logic_vector(1 downto 0);
variable CLK_LOCK : boolean;
variable EDGE_LOCK : boolean;
variable TIMER : std_logic_vector(2 downto 0);
variable TIMER_LOCK : boolean;
variable NEW_SDATA : bit;
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' or RE = '0' then
-- The reset condition assumes the SDATA_IN logic high. Otherwise
-- one not valid SDATA_EDGE pulse occurs during system startup.
CLK_LOCK := true;
EDGE_LOCK := true;
HI_FLT := "11";
LOW_FLT := "11";
SDATA_EDGE <= '0';
NEW_SDATA := '1';
-- Positive or negative edge detector for the incoming data.
-- Any transition must be valid for at least three receiver clock
-- cycles. The TIMER locking inhibits detecting four receiver
-- clock cycles after a valid transition.
elsif RXCLK = '1' and SDATA_IN = '0' and CLK_LOCK = false and LOW_FLT > "00" then
CLK_LOCK := true;
EDGE_LOCK := false;
HI_FLT := "00";
LOW_FLT := LOW_FLT - '1';
elsif RXCLK = '1' and SDATA_IN = '1' and CLK_LOCK = false and HI_FLT < "11" then
CLK_LOCK := true;
EDGE_LOCK := false;
LOW_FLT := "11";
HI_FLT := HI_FLT + '1';
elsif RXCLK = '1' and EDGE_LOCK = false and LOW_FLT = "00" then
EDGE_LOCK := true;
SDATA_EDGE <= '1'; -- Falling edge detected.
NEW_SDATA := '0';
elsif RXCLK = '1' and EDGE_LOCK = false and HI_FLT = "11" then
EDGE_LOCK := true;
SDATA_EDGE <= '1'; -- Rising edge detected.
NEW_SDATA := '1';
elsif RXCLK = '1' and CLK_LOCK = false then
CLK_LOCK := true;
SDATA_EDGE <= '0';
elsif RXCLK = '0' then
CLK_LOCK := false;
end if;
--
if RESETn = '0' or RE = '0' then
-- The reset condition assumes the SDATA_IN logic high. Otherwise
-- one not valid SDATA_EDGE pulse occurs during system startup.
TIMER := "111";
TIMER_LOCK := true;
SDATA_DIV16 <= '1';
-- The timer controls the SDATA in a way, that after a detected valid
-- Transistion, the serial data is sampled on the 8th receiver clock
-- edge after the initial valid transition occured.
elsif RXCLK = '1' and SDATA_EDGE = '1' and TIMER_LOCK = false then
TIMER_LOCK := true;
TIMER := "000"; -- Resynchronisation.
elsif RXCLK = '1' and TIMER = "011" and TIMER_LOCK = false then
TIMER_LOCK := true;
SDATA_DIV16 <= NEW_SDATA; -- Scan the new data.
TIMER := TIMER + '1'; -- Timing is active.
elsif RXCLK = '1' and TIMER < "111" and TIMER_LOCK = false then
TIMER_LOCK := true;
TIMER := TIMER + '1'; -- Timing is active.
elsif RXCLK = '0' then
TIMER_LOCK := false;
end if;
end process P_SAMPLE;
P_START_BIT: process(CLK)
-- This is the valid start bit logic of the original MC68901 multi function
-- port's USART receiver.
variable TMP : std_logic_vector(2 downto 0);
variable LOCK : boolean;
begin
if CLK = '1' and CLK' event then
if RESETn = '0' then
TMP := "000";
LOCK := true;
elsif RE = '0' or RCV_STATE /= IDLE then -- Start bit logic disabled.
TMP := "000";
LOCK := true;
elsif SDATA_EDGE = '1' then
TMP := "000"; -- (Re)-Initialize.
LOCK := false; -- Start counting.
elsif RXCLK = '1' and SDATA_IN = '0' and TMP < "111" and LOCK = false then
LOCK := true;
TMP := TMP + '1'; -- Count 8 low bits to declare start condition valid.
elsif RXCLK = '0' then
LOCK := false;
end if;
end if;
case TMP is
when "111" => STARTBIT <= true;
when others => STARTBIT <= false;
end case;
end process P_START_BIT;
SDATA_IN_I <= SDATA_IN when CLK_MODE = '0' else -- Clock div by 1 mode.
SDATA_IN when ST = "00" else SDATA_DIV16; -- Synchronous mode.
CLKDIV: process
variable CLK_LOCK : boolean;
variable STRB_LOCK : boolean;
variable CLK_DIVCNT : std_logic_vector(4 downto 0);
begin
wait until CLK = '1' and CLK' event;
if CLK_MODE = '0' then -- Divider off.
if RXCLK = '1' and STRB_LOCK = false then
CLK_STRB <= '1';
STRB_LOCK := true;
elsif RXCLK = '0' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
CLK_2_STRB <= '0'; -- No 1 1/2 stop bits in no div by 16 mode.
elsif SDATA_EDGE = '1' then
CLK_DIVCNT := "01100"; -- Div by 16 mode.
CLK_STRB <= '0'; -- Default.
CLK_2_STRB <= '0'; -- Default.
else
CLK_STRB <= '0'; -- Default.
CLK_2_STRB <= '0'; -- Default.
if CLK_DIVCNT > "00000" and RXCLK = '1' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_LOCK := true;
if CLK_DIVCNT = "01000" then
-- This strobe is asserted at half of the clock cycle.
-- It is used for the stop bit timing.
CLK_2_STRB <= '1';
end if;
elsif CLK_DIVCNT = "00000" then
CLK_DIVCNT := "10000"; -- Div by 16 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
end if;
elsif RXCLK = '0' then
CLK_LOCK := false;
STRB_LOCK := false;
end if;
end if;
end process CLKDIV;
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if RE = '0' then
SHIFT_REG <= x"00";
elsif RCV_STATE = SAMPLE and CLK_STRB = '1' then
SHIFT_REG <= SDATA_IN_I & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end process SHIFTREG;
P_M_CIP: process(RESETn, CLK)
-- In Synchronous mode this flag indicates wether a synchronous character M_CIP = '1'
-- or another character (M_CIP = '0') is transferred to the receive buffer.
-- In asynchronous mode the flag indicates sampling condition.
begin
if RESETn = '0' then
M_CIP <= '0';
elsif CLK = '0' and CLK' event then
if RE = '0' then
M_CIP <= '0';
elsif ST = "00" then -- Synchronous mode.
if RCV_STATE = SYNC and SHIFT_REG = SCR and RDRF = '0' then
M_CIP <= '1'; -- SCR transferred.
elsif RCV_STATE = SYNC and RDRF = '0' then
M_CIP <= '0'; -- No SCR transferred.
end if;
else -- Asynchronous mode.
case RCV_STATE is
when SAMPLE | PARITY | STOP1 | STOP2 => M_CIP <= '1'; -- Sampling.
when others => M_CIP <= '0'; -- No Sampling.
end case;
end if;
end if;
end process P_M_CIP;
BREAK_DETECT: process(RESETn, CLK)
-- A break condition occurs, if there is no STOP1 bit and the
-- shift register contains zero data.
begin
if RESETn = '0' then
BREAK <= false;
elsif CLK = '1' and CLK' event then
if RE = '0' then
BREAK <= false;
elsif CLK_STRB = '1' then
if RCV_STATE = STOP1 and SDATA_IN_I = '0' and SHIFT_REG = x"00" then
BREAK <= true; -- Break detected (empty shift register and no stop bit).
elsif RCV_STATE = STOP1 and SDATA_IN_I = '1' then
BREAK <= false; -- UPDATE.
elsif RCV_STATE = STOP1 and SDATA_IN_I = '0' and SHIFT_REG /= x"00" then
BREAK <= false; -- UPDATE, but framing error.
end if;
end if;
end if;
end process BREAK_DETECT;
P_FS_B: process(RESETn, CLK)
-- In the synchronous mode, this process provides the flag detecting the synchronous
-- character. In the asynchronous mode, the flag indicates a break condition.
variable FS_B_I : bit;
variable FIRST_READ : boolean;
begin
if RESETn = '0' then
FS_B <= '0';
FIRST_READ := false;
FS_B_I := '0';
elsif CLK = '0' and CLK' event then
if RE = '0' then
FS_B <= '0';
FS_B_I := '0';
else
if ST = "00" then -- Synchronous operation.
if FS_CLR = '1' then
FS_B <= '0'; -- Clear during writing to the SCR.
elsif SHIFT_REG = SCR then
FS_B <= '1'; -- SCR detected.
end if;
else -- Asynchronous operation.
if RX_SAMPLE = '1' and BREAK = true then -- Break condition detected.
FS_B_I := '1'; -- Update.
elsif RX_SAMPLE = '1' then -- No break condition.
FS_B_I := '0'; -- Update.
elsif RSR_READ = '1' and FS_B_I = '1' then
-- If a break condition was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the break flag is reset
-- and the break condition disappears after a second read
-- (in time) of the receiver status register.
if FIRST_READ = false then
FS_B <= '1';
FIRST_READ := true;
else
FS_B <= '0';
FIRST_READ := false;
end if;
end if;
end if;
end if;
end if;
end process P_FS_B;
P_BITCNT: process
begin
wait until CLK = '1' and CLK' event;
if RCV_STATE = SAMPLE and CLK_STRB = '1' and ST /= "00" then -- Asynchronous mode.
BITCNT <= BITCNT + '1';
elsif RCV_STATE = SAMPLE and CLK_STRB = '1' and ST = "00" and FS_B = '1' then -- Synchronous mode.
BITCNT <= BITCNT + '1'; -- Count, if matched data found (FS_B = '1').
elsif RCV_STATE /= SAMPLE then
BITCNT <= (others => '0');
end if;
end process P_BITCNT;
BUFFER_FULL: process(RESETn, CLK)
-- Receive data register full flag.
begin
if RESETn = '0' then
RDRF <= '0';
elsif CLK = '1' and CLK' event then
if RE = '0' then
RDRF <= '0';
elsif RX_SAMPLE = '1' then
RDRF <= '1'; -- Data register is full until now!
elsif UDR_READ = '1' then
RDRF <= '0'; -- After reading the data register ...
end if;
end if;
end process BUFFER_FULL;
OVERRUN: process(RESETn, CLK)
variable OE_I : bit;
variable FIRST_READ : boolean;
begin
if RESETn = '0' then
OE_I := '0';
OE <= '0';
FIRST_READ := false;
elsif CLK = '1' and CLK' event then
if RESETn = '0' then
OE_I := '0';
OE <= '0';
FIRST_READ := false;
elsif CLK_STRB = '1' and RCV_STATE = SYNC and BREAK = false then
-- Overrun appears if RDRF is '1' in this state and there
-- is no break condition.
OE_I := RDRF;
end if;
if RSR_READ = '1' and OE_I = '1' then
-- if an overrun was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the RDRF flag is reset
-- and the overrun disappears (OE_I goes low) after
-- a second read (in time) of the receiver data register.
if FIRST_READ = false then
OE <= '1';
FIRST_READ := true;
else
OE <= '0';
FIRST_READ := false;
end if;
end if;
end if;
end process OVERRUN;
PARITY_TEST: process(RESETn, CLK)
variable PAR_TMP : bit;
variable P_ERR : bit;
begin
if RESETn = '0' then
PE <= '0';
elsif CLK = '1' and CLK' event then
if RE = '0' then
PE <= '0';
elsif RX_SAMPLE = '1' then
PE <= P_ERR; -- Update on load shift register to data register.
elsif CLK_STRB = '1' then -- Sample parity on clock strobe.
P_ERR := '0'; -- Initialise.
if RCV_STATE = PARITY then
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if P_ENA = '1' and P_EOn = '1' then -- Even parity.
P_ERR := PAR_TMP xor SDATA_IN_I;
elsif P_ENA = '1' and P_EOn = '0' then -- Odd parity.
P_ERR := not PAR_TMP xor SDATA_IN_I;
elsif P_ENA = '0' then -- No parity.
P_ERR := '0';
end if;
end if;
end if;
end if;
end process PARITY_TEST;
FRAME_ERR: process(RESETn, CLK)
-- This module detects a framing error
-- during stop bit 1 and stop bit 2.
variable FE_I: bit;
begin
if RESETn = '0' then
FE_I := '0';
FE <= '0';
elsif CLK = '1' and CLK' event then
if RE = '0' then
FE_I := '0';
FE <= '0';
elsif CLK_STRB = '1' then
if RCV_STATE = STOP1 and SDATA_IN_I = '0' and SHIFT_REG /= x"00" then
FE_I := '1';
elsif RCV_STATE = STOP2 and SDATA_IN_I = '0' and SHIFT_REG /= x"00" then
FE_I := '1';
elsif RCV_STATE = STOP1 or RCV_STATE = STOP2 then
FE_I := '0'; -- Error resets when correct data appears.
end if;
end if;
if RCV_STATE = SYNC then
FE <= FE_I; -- Update the FE every SYNC time.
end if;
end if;
end process FRAME_ERR;
RCV_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
RCV_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if RE = '0' then
RCV_STATE <= IDLE;
else
RCV_STATE <= RCV_NEXT_STATE;
end if;
end if;
end process RCV_STATEREG;
RCV_STATEDEC: process(RCV_STATE, SDATA_IN_I, BITCNT, CLK_STRB, STARTBIT,
CLK_2_STRB, ST, CLK_MODE, CL, P_ENA, SHIFT_REG)
begin
case RCV_STATE is
when IDLE =>
if ST = "00" then
RCV_NEXT_STATE <= SAMPLE; -- Synchronous mode.
elsif SDATA_IN_I = '0' and CLK_MODE = '0' then
RCV_NEXT_STATE <= SAMPLE; -- Startbit detected in div by 1 mode.
elsif STARTBIT = true and CLK_MODE = '1' then
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 16 mode.
else
RCV_NEXT_STATE <= IDLE; -- No startbit; sleep well :-)
end if;
when WAIT_START =>
-- This state delays the sample process by one CLK_STRB pulse
-- to eliminate the start bit.
if CLK_STRB = '1' then
RCV_NEXT_STATE <= SAMPLE;
else
RCV_NEXT_STATE <= WAIT_START;
end if;
when SAMPLE =>
if CLK_STRB = '1' then
if CL = "11" and BITCNT < "100" then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 5 data bits.
elsif CL = "10" and BITCNT < "101" then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 6 data bits.
elsif CL = "01" and BITCNT < "110" then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 7 data bits.
elsif CL = "00" and BITCNT < "111" then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 8 data bits.
elsif ST = "00" and P_ENA = '0' then -- Synchronous mode (no stop bits).
RCV_NEXT_STATE <= IDLE; -- No parity check enabled.
elsif P_ENA = '0' then
RCV_NEXT_STATE <= STOP1; -- No parity check enabled.
else
RCV_NEXT_STATE <= PARITY; -- Parity enabled.
end if;
else
RCV_NEXT_STATE <= SAMPLE; -- Stay in sample mode.
end if;
when PARITY =>
if CLK_STRB = '1' then
if ST = "00" then -- Synchronous mode (no stop bits).
RCV_NEXT_STATE <= IDLE;
else
RCV_NEXT_STATE <= STOP1;
end if;
else
RCV_NEXT_STATE <= PARITY;
end if;
when STOP1 =>
if CLK_STRB = '1' then
if SHIFT_REG > x"00" and SDATA_IN_I = '0' then -- No Stop bit after non zero data.
RCV_NEXT_STATE <= SYNC; -- Framing error detected.
elsif ST = "11" or ST = "10" then
RCV_NEXT_STATE <= STOP2; -- More than one stop bits selected.
else
RCV_NEXT_STATE <= SYNC; -- One stop bit selected.
end if;
else
RCV_NEXT_STATE <= STOP1;
end if;
when STOP2 =>
if CLK_2_STRB = '1' and ST = "10" then
RCV_NEXT_STATE <= SYNC; -- One and a half stop bits selected.
elsif CLK_STRB = '1' then
RCV_NEXT_STATE <= SYNC; -- Two stop bits selected.
else
RCV_NEXT_STATE <= STOP2;
end if;
when SYNC =>
RCV_NEXT_STATE <= IDLE;
end case;
end process RCV_STATEDEC;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,238 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the SUSKA MFP IP core USART top level file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
use work.wf68901ip_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_USART_TOP is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
-- Serial I/O control:
RC : in bit; -- Receiver clock.
TC : in bit; -- Transmitter clock.
SI : in bit; -- Serial input.
SO : out bit; -- Serial output.
SO_EN : out bit; -- Serial output enable.
-- Interrupt channels:
RX_ERR_INT : out bit; -- Receiver errors.
RX_BUFF_INT : out bit; -- Receiver buffer full.
TX_ERR_INT : out bit; -- Transmitter errors.
TX_BUFF_INT : out bit; -- Transmitter buffer empty.
-- DMA control:
RRn : out bit;
TRn : out bit
);
end entity WF68901IP_USART_TOP;
architecture STRUCTURE of WF68901IP_USART_TOP is
signal BF_I : bit;
signal BE_I : bit;
signal FE_I : bit;
signal OE_I : bit;
signal UE_I : bit;
signal PE_I : bit;
signal LOOPBACK_I : bit;
signal SD_LEVEL_I : bit;
signal SDATA_IN_I : bit;
signal SDATA_OUT_I : bit;
signal RXCLK_I : bit;
signal CLK_MODE_I : bit;
signal SCR_I : bit_vector(7 downto 0);
signal RX_SAMPLE_I : bit;
signal RX_DATA_I : bit_vector(7 downto 0);
signal TX_DATA_I : bit_vector(7 downto 0);
signal CL_I : bit_vector(1 downto 0);
signal ST_I : bit_vector(1 downto 0);
signal P_ENA_I : bit;
signal P_EOn_I : bit;
signal RE_I : bit;
signal TE_I : bit;
signal FS_CLR_I : bit;
signal SS_I : bit;
signal M_CIP_I : bit;
signal FS_B_I : bit;
signal BR_I : bit;
signal UDR_READ_I : bit;
signal UDR_WRITE_I : bit;
signal RSR_READ_I : bit;
signal TSR_READ_I : bit;
signal TX_END_I : bit;
begin
SO <= SDATA_OUT_I when TE_I = '1' else SD_LEVEL_I;
-- Loopback mode:
SDATA_IN_I <= SDATA_OUT_I when LOOPBACK_I = '1' and TE_I = '1' else -- Loopback, transmitter enabled.
'1' when LOOPBACK_I = '1' and TE_I = '0' else SI; -- Loopback, transmitter disabled.
RXCLK_I <= TC when LOOPBACK_I = '1' else RC;
RRn <= '0' when BF_I = '1' and PE_I = '0' and FE_I = '0' else '1';
TRn <= not BE_I;
-- Interrupt sources:
RX_ERR_INT <= OE_I or PE_I or FE_I or FS_B_I;
RX_BUFF_INT <= BF_I;
TX_ERR_INT <= UE_I or TX_END_I;
TX_BUFF_INT <= BE_I;
I_USART_CTRL: WF68901IP_USART_CTRL
port map(
CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN,
DATA_OUT => DATA_OUT,
DATA_OUT_EN => DATA_OUT_EN,
LOOPBACK => LOOPBACK_I,
SDOUT_EN => SO_EN,
SD_LEVEL => SD_LEVEL_I,
CLK_MODE => CLK_MODE_I,
RE => RE_I,
TE => TE_I,
P_ENA => P_ENA_I,
P_EOn => P_EOn_I,
BF => BF_I,
BE => BE_I,
FE => FE_I,
OE => OE_I,
UE => UE_I,
PE => PE_I,
M_CIP => M_CIP_I,
FS_B => FS_B_I,
SCR_OUT => SCR_I,
TX_DATA => TX_DATA_I,
RX_SAMPLE => RX_SAMPLE_I,
RX_DATA => RX_DATA_I,
SS => SS_I,
BR => BR_I,
CL => CL_I,
ST => ST_I,
FS_CLR => FS_CLR_I,
UDR_READ => UDR_READ_I,
UDR_WRITE => UDR_WRITE_I,
RSR_READ => RSR_READ_I,
TSR_READ => TSR_READ_I,
TX_END => TX_END_I
);
I_USART_RECEIVE: WF68901IP_USART_RX
port map (
CLK => CLK,
RESETn => RESETn,
SCR => SCR_I,
RX_SAMPLE => RX_SAMPLE_I,
RX_DATA => RX_DATA_I,
CL => CL_I,
ST => ST_I,
P_ENA => P_ENA_I,
P_EOn => P_EOn_I,
CLK_MODE => CLK_MODE_I,
RE => RE_I,
FS_CLR => FS_CLR_I,
SS => SS_I,
RXCLK => RXCLK_I,
SDATA_IN => SDATA_IN_I,
RSR_READ => RSR_READ_I,
UDR_READ => UDR_READ_I,
M_CIP => M_CIP_I,
FS_B => FS_B_I,
BF => BF_I,
OE => OE_I,
PE => PE_I,
FE => FE_I
);
I_USART_TRANSMIT: WF68901IP_USART_TX
port map (
CLK => CLK,
RESETn => RESETn,
SCR => SCR_I,
TX_DATA => TX_DATA_I,
SDATA_OUT => SDATA_OUT_I,
TXCLK => TC,
CL => CL_I,
ST => ST_I,
TE => TE_I,
BR => BR_I,
P_ENA => P_ENA_I,
P_EOn => P_EOn_I,
UDR_WRITE => UDR_WRITE_I,
TSR_READ => TSR_READ_I,
CLK_MODE => CLK_MODE_I,
TX_END => TX_END_I,
UE => UE_I,
BE => BE_I
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,387 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- This is the SUSKA MFP IP core USART transmitter file. ----
---- ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- TDRE has now synchronous reset to meet preset requirement.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_USART_TX is
port (
CLK : in bit;
RESETn : in bit;
SCR : in bit_vector(7 downto 0); -- Synchronous character.
TX_DATA : in bit_vector(7 downto 0); -- Normal data.
SDATA_OUT : out bit; -- Serial data output.
TXCLK : in bit; -- Transmitter clock.
CL : in bit_vector(1 downto 0); -- Character length.
ST : in bit_vector(1 downto 0); -- Start and stop bit configuration.
TE : in bit; -- Transmitter enable.
BR : in bit; -- BREAK character send enable (all '0' without stop bit).
P_ENA : in bit; -- Parity enable.
P_EOn : in bit; -- Even or odd parity.
UDR_WRITE : in bit; -- Flag indicating writing the data register.
TSR_READ : in bit; -- Flag indicating reading the transmitter status register.
CLK_MODE : in bit; -- Transmitter clock mode.
TX_END : out bit; -- End of transmission flag.
UE : out bit; -- Underrun Flag.
BE : out bit -- Buffer empty flag.
);
end entity WF68901IP_USART_TX;
architecture BEHAVIOR of WF68901IP_USART_TX is
type TR_STATES is (IDLE, CHECK_BREAK, LOAD_SHFT, START, SHIFTOUT, PARITY, STOP1, STOP2);
signal TR_STATE, TR_NEXT_STATE : TR_STATES;
signal CLK_STRB : bit;
signal CLK_2_STRB : bit;
signal SHIFT_REG : bit_vector(7 downto 0);
signal BITCNT : std_logic_vector(2 downto 0);
signal PARITY_I : bit;
signal TDRE : bit;
signal BREAK : bit;
begin
BE <= TDRE; -- Buffer empty flag.
-- The default condition in this statement is to ensure
-- to cover all possibilities for example if there is a
-- one hot decoding of the state machine with wrong states
-- (e.g. not one of the given here).
SDATA_OUT <= '0' when BREAK = '1' else
'1' when TR_STATE = IDLE else
'1' when TR_STATE = LOAD_SHFT else
'0' when TR_STATE = START else
SHIFT_REG(0) when TR_STATE = SHIFTOUT else
PARITY_I when TR_STATE = PARITY else
'1' when TR_STATE = STOP1 else
'1' when TR_STATE = STOP2 else '1';
P_BREAK : process(RESETn, CLK)
-- This process is responsible to control the BREAK signal. After the break request
-- is asserted via BR, the break character will be sent after the current transmission has
-- finished. The BREAK character is sent until the BR is disabled.
variable LOCK : boolean;
begin
if RESETn = '0' then
BREAK <= '0';
elsif CLK = '1' and CLK' event then
-- Break is only available in the asynchronous mode (ST /= "00").
-- The LOCK mechanism is reponsible for sending the BREAK character just once.
if TE = '1' and BR = '1' and ST /= "00" and TR_STATE = IDLE and LOCK = false then
BREAK <= '1'; -- Break for the case that there is no current transmission.
LOCK := true;
elsif BR = '1' and ST /= "00" and TR_STATE = STOP1 then
BREAK <= '0'; -- Break character sent.
elsif BR = '0' then
BREAK <= '0';
LOCK := false;
else
BREAK <= '0';
end if;
end if;
end process P_BREAK;
CLKDIV: process
variable CLK_LOCK : boolean;
variable STRB_LOCK : boolean;
variable CLK_DIVCNT : std_logic_vector(4 downto 0);
begin
wait until CLK = '1' and CLK' event;
if CLK_MODE = '0' then -- Divider off.
if TXCLK = '0' and STRB_LOCK = false then -- Works on negative TXCLK edge.
CLK_STRB <= '1';
STRB_LOCK := true;
elsif TXCLK = '1' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
CLK_2_STRB <= '0'; -- No 1 1/2 stop bits in no div by 16 mode.
elsif TR_STATE = IDLE then
CLK_DIVCNT := "10000"; -- Div by 16 mode.
CLK_STRB <= '0';
else
CLK_STRB <= '0'; -- Default.
CLK_2_STRB <= '0'; -- Default.
-- Works on negative TXCLK edge:
if CLK_DIVCNT > "00000" and TXCLK = '0' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_LOCK := true;
if CLK_DIVCNT = "01000" then
-- This strobe is asserted at half of the clock cycle.
-- It is used for the stop bit timing.
CLK_2_STRB <= '1';
end if;
elsif CLK_DIVCNT = "00000" then
CLK_DIVCNT := "10000"; -- Div by 16 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
end if;
elsif TXCLK = '1' then
CLK_LOCK := false;
STRB_LOCK := false;
end if;
end if;
end process CLKDIV;
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if TR_STATE = LOAD_SHFT and TDRE = '1' then -- Lost data ...
case ST is
when "00" => -- Synchronous mode.
SHIFT_REG <= SCR; -- Send the synchronous character.
when others => -- Asynchronous mode.
SHIFT_REG <= x"5A"; -- Load the shift register with a mark (underrun).
end case;
elsif TR_STATE = LOAD_SHFT then
-- Load 'normal' data if there is no break condition:
case CL is
when "11" => SHIFT_REG <= "000" & TX_DATA(4 downto 0); -- 5 databits.
when "10" => SHIFT_REG <= "00" & TX_DATA(5 downto 0); -- 6 databits.
when "01" => SHIFT_REG <= '0' & TX_DATA(6 downto 0); -- 7 databits.
when "00" => SHIFT_REG <= TX_DATA; -- 8 databits.
end case;
elsif TR_STATE = SHIFTOUT and CLK_STRB = '1' then
SHIFT_REG <= '0' & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end process SHIFTREG;
P_BITCNT: process
-- Counter for the data bits transmitted.
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif TR_STATE /= SHIFTOUT then
BITCNT <= "000";
end if;
end process P_BITCNT;
BUFFER_EMPTY: process
-- Transmit data register empty flag.
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
TDRE <= '1';
elsif TE = '0' then
TDRE <= '1';
elsif TR_STATE = START and BREAK = '0' then
-- Data has been loaded to the shift register,
-- thus data register is free again.
-- If the BREAK flag is enabled, the BE flag
-- respective TDRE flag cannot be set.
TDRE <= '1';
elsif UDR_WRITE = '1' then
TDRE <= '0';
end if;
end process BUFFER_EMPTY;
UNDERRUN: process(RESETn, CLK)
variable LOCK : boolean;
begin
if RESETn = '0' then
UE <= '0';
LOCK := false;
elsif CLK = '1' and CLK' event then
if TE = '0' then
UE <= '0';
LOCK := false;
elsif CLK_STRB = '1' and TR_STATE = START then
-- Underrun appears if TDRE is '0' at the end of this state.
UE <= TDRE; -- Never true for enabled BREAK flag. See alos process BUFFER_EMPTY.
LOCK := true;
elsif CLK_STRB = '1' then
LOCK := false; -- Disables clearing UE one transmit clock cycle.
elsif TSR_READ = '1' and LOCK = false then
UE <= '0';
end if;
end if;
end process UNDERRUN;
P_TX_END: process(RESETn, CLK)
begin
if RESETn = '0' then
TX_END <= '0';
elsif CLK = '1' and CLK' event then
if TE = '1' then -- Transmitter enabled.
TX_END <= '0';
elsif TE = '0' and TR_STATE = IDLE then
TX_END <= '1';
end if;
end if;
end process P_TX_END;
PARITY_GEN: process
variable PAR_TMP : bit;
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = START then -- Calculate the parity during the start phase.
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if P_ENA = '1' and P_EOn = '1' then -- Even parity.
PARITY_I <= PAR_TMP;
elsif P_ENA = '1' and P_EOn = '0' then -- Odd parity.
PARITY_I <= not PAR_TMP;
else -- No parity.
PARITY_I <= '0';
end if;
end if;
end process PARITY_GEN;
TR_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
TR_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
TR_STATE <= TR_NEXT_STATE;
end if;
end process TR_STATEREG;
TR_STATEDEC: process(TR_STATE, CLK_STRB, CLK_2_STRB, BITCNT, TDRE, BREAK, TE, ST, P_ENA, CL, BR)
begin
case TR_STATE is
when IDLE =>
-- This IDLE state is just one clock cycle and is required to give the
-- break process time to set the BREAK flag.
TR_NEXT_STATE <= CHECK_BREAK;
when CHECK_BREAK =>
if BREAK = '1' then -- Send break character.
-- Do not load any data to the shift register, go directly
-- to the START state.
TR_NEXT_STATE <= START;
-- Start enabled transmitter, if the data register is not empty.
-- Do not send any further data for the case of an asserted BR flag.
elsif TE = '1' and TDRE = '0' and BR = '0' then
TR_NEXT_STATE <= LOAD_SHFT;
else
TR_NEXT_STATE <= IDLE; -- Go back, scan for BREAK.
end if;
when LOAD_SHFT =>
TR_NEXT_STATE <= START;
when START => -- Send the start bit.
if CLK_STRB = '1' then
TR_NEXT_STATE <= SHIFTOUT;
else
TR_NEXT_STATE <= START;
end if;
when SHIFTOUT =>
if CLK_STRB = '1' then
if BITCNT < "100" and CL = "11" then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 5 data bits.
elsif BITCNT < "101" and CL = "10" then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 6 data bits.
elsif BITCNT < "110" and CL = "01" then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 7 data bits.
elsif BITCNT < "111" and CL = "00" then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 8 data bits.
elsif P_ENA = '0' and BREAK = '1' then
TR_NEXT_STATE <= IDLE; -- Break condition, no parity check enabled, no stop bits.
elsif P_ENA = '0' and ST = "00" then
TR_NEXT_STATE <= IDLE; -- Synchronous mode, no parity check enabled.
elsif P_ENA = '0' then
TR_NEXT_STATE <= STOP1; -- Asynchronous mode, no parity check enabled.
else
TR_NEXT_STATE <= PARITY; -- Parity enabled.
end if;
else
TR_NEXT_STATE <= SHIFTOUT;
end if;
when PARITY =>
if CLK_STRB = '1' then
if ST = "00" then -- Synchronous mode (no stop bits).
TR_NEXT_STATE <= IDLE;
elsif BREAK = '1' then -- No stop bits during break condition.
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP1;
end if;
else
TR_NEXT_STATE <= PARITY;
end if;
when STOP1 =>
if CLK_STRB = '1' and (ST = "11" or ST = "10") then
TR_NEXT_STATE <= STOP2; -- More than one stop bits selected.
elsif CLK_STRB = '1' then
TR_NEXT_STATE <= IDLE; -- One stop bits selected.
else
TR_NEXT_STATE <= STOP1;
end if;
when STOP2 =>
if CLK_2_STRB = '1' and ST = "10" then
TR_NEXT_STATE <= IDLE; -- One and a half stop bits selected.
elsif CLK_STRB = '1' then
TR_NEXT_STATE <= IDLE; -- Two stop bits detected.
else
TR_NEXT_STATE <= STOP2;
end if;
end case;
end process TR_STATEDEC;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,228 @@
----------------------------------------------------------------------
---- ----
---- ATARI IP Core peripheral Add-On ----
---- ----
---- This file is part of the FPGA-ATARI project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- This hardware provides an interface to connect to a SD-Card. ----
---- ----
---- This interface is based on the project 'SatanDisk' of ----
---- Miroslav Nohaj 'Jookie'. The code is an interpretation of ----
---- the original code, written in VERILOG. It is provided for ----
---- the use in a system on programmable chips (SOPC). ----
---- ----
---- Timing: Use a clock frequency of 16MHz for this component. ----
---- Use the same clock frequency for the connected AVR ----
---- microcontroller. ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2007 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
---- This hardware works with the original ATARI ----
---- hard dik driver. ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 1.0 2007/01/05 WF
-- Initial Release.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF_SD_CARD is
port (
-- System:
RESETn : in bit;
CLK : in bit; -- 16MHz, see above.
-- ACSI section:
ACSI_A1 : in bit;
ACSI_CSn : in bit;
ACSI_ACKn : in bit;
ACSI_INTn : out bit;
ACSI_DRQn : out bit;
ACSI_D : inout std_logic_vector(7 downto 0);
-- Microcontroller interface:
MC_D : inout std_logic_vector(7 downto 0);
MC_DO : in bit;
MC_PIO_DMAn : in bit;
MC_RWn : in bit;
MC_CLR_CMD : in bit;
MC_DONE : out bit;
MC_GOT_CMD : out bit
);
end WF_SD_CARD;
architecture BEHAVIOR of WF_SD_CARD is
signal DATA_REG : std_logic_vector(7 downto 0);
signal D0_REG : bit;
signal INT_REG : bit;
signal DRQ_REG : bit;
signal DONE_REG : bit;
signal GOT_CMD_REG : bit;
signal HOLD : bit;
signal PREV_CSn : bit;
signal PREV_ACKn : bit;
begin
MC_D <= DATA_REG when MC_RWn = '0' and DONE_REG = '1' else (others => 'Z');
ACSI_D <= DATA_REG when MC_RWn = '1' and (ACSI_CSn = '0' or ACSI_ACKn = '0' or HOLD = '1') else (others => 'Z');
ACSI_INTn <= INT_REG;
ACSI_DRQn <= DRQ_REG;
MC_DONE <= DONE_REG;
MC_GOT_CMD <= GOT_CMD_REG;
P_DATA: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= (others => '0');
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' and MC_RWn = '1' then
DATA_REG <= MC_D; -- Read from AVR to ACSI.
end if;
--
if PREV_CSn = '0' and ACSI_CSn = '0' and MC_RWn = '0' and DONE_REG = '0' then
DATA_REG <= ACSI_D; -- Write from ACSI to AVR.
elsif PREV_ACKn = '0' and ACSI_ACKn = '0' and MC_RWn = '0' and DONE_REG = '0' then
DATA_REG <= ACSI_D; -- Write from ACSI to AVR.
end if;
end if;
end process P_DATA;
P_SYNC: process
begin
wait until CLK = '1' and CLK' event;
PREV_CSn <= ACSI_CSn;
PREV_ACKn <= ACSI_ACKn;
end process P_SYNC;
P_INT_DRQ: process(RESETn, CLK)
begin
if RESETn = '0' then
INT_REG <= '1'; -- No interrupt.
DRQ_REG <= '1'; -- No data request.
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' and MC_PIO_DMAn = '1' then -- Positive MC_DO edge.
INT_REG <= '0'; -- Release an interrupt.
DRQ_REG <= '1';
elsif D0_REG = '0' and MC_DO = '1' then
INT_REG <= '1';
DRQ_REG <= '0'; -- Release a data request.
end if;
--
if MC_CLR_CMD = '1' then -- Clear done.
INT_REG <= '1'; -- Restore INT_REG.
DRQ_REG <= '1'; -- Restore DRQ_REG.
end if;
--
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
if ACSI_CSn = '0' then
INT_REG <= '1';
end if;
--
if ACSI_ACKn = '0' then
DRQ_REG <= '1';
end if;
end if;
end if;
end process P_INT_DRQ;
P_HOLD: process(RESETn, CLK)
begin
if RESETn = '0' then
HOLD <= '0';
elsif CLK = '1' and CLK' event then
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
HOLD <= '1';
elsif PREV_CSn = '1' and ACSI_CSn = '1' then -- If signal is high.
HOLD <= '0';
elsif PREV_ACKn = '1' and ACSI_ACKn = '1' then -- If signal is high.
HOLD <= '0';
elsif PREV_CSn = '0' and ACSI_CSn = '1' then -- Rising edge.
HOLD <= '1';
elsif PREV_ACKn = '0' and ACSI_ACKn = '1' then -- Rising edge.
HOLD <= '1';
elsif MC_CLR_CMD = '1' then -- Clear done.
HOLD <= '0';
end if;
end if;
end process P_HOLD;
P_DONE: process(RESETn, CLK)
begin
if RESETn = '0' then
DONE_REG <= '0';
elsif CLK = '1' and CLK' event then
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
DONE_REG <= '1';
elsif MC_CLR_CMD = '1' then -- Clear done.
DONE_REG <= '0';
elsif D0_REG = '0' and MC_DO = '1' then -- Positive MC_DO edge.
DONE_REG <= '0';
elsif D0_REG = '1' and MC_DO = '0' then -- Negative MC_DO edge.
DONE_REG <= '0';
end if;
end if;
end process P_DONE;
P_DO_REG: process(RESETn, CLK)
begin
if RESETn = '0' then
D0_REG <= '0';
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' then -- Positive MC_DO edge.
D0_REG <= MC_DO;
elsif D0_REG = '1' and MC_DO = '0' then -- Negative MC_DO edge.
D0_REG <= MC_DO;
end if;
end if;
end process P_DO_REG;
P_GOT_CMD: process(RESETn, CLK)
begin
if RESETn = '0' then
GOT_CMD_REG <= '0';
elsif CLK = '1' and CLK' event then
if PREV_CSn = '0' and ACSI_CSn = '0' and ACSI_CSn = '0' and ACSI_A1 = '0' then
GOT_CMD_REG <= '1'; -- If command was received.
elsif PREV_ACKn = '0' and ACSI_ACKn = '0' and ACSI_CSn = '0' and ACSI_A1 = '0' then
GOT_CMD_REG <= '1'; -- If command was received.
elsif MC_CLR_CMD = '1' then -- Clear done.
GOT_CMD_REG <= '0';
end if;
end if;
end process P_GOT_CMD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,240 @@
----------------------------------------------------------------------
---- ----
---- ATARI IP Core peripheral Add-On ----
---- ----
---- This file is part of the FPGA-ATARI project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- This hardware provides an interface to connect to a SD-Card. ----
---- ----
---- This interface is based on the project 'SatanDisk' of ----
---- Miroslav Nohaj 'Jookie'. The code is an interpretation of ----
---- the original code, written in VERILOG. It is provided for ----
---- the use in a system on programmable chips (SOPC). ----
---- ----
---- Timing: Use a clock frequency of 16MHz for this component. ----
---- Use the same clock frequency for the connected AVR ----
---- microcontroller. ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2007 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
---- This hardware works with the original ATARI ----
---- hard dik driver. ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K7A 2007/01/05 WF
-- Initial Release.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF_SD_CARD is
port (
-- System:
RESETn : in bit;
CLK : in bit; -- 16MHz, see above.
-- ACSI section:
ACSI_A1 : in bit;
ACSI_CSn : in bit;
ACSI_ACKn : in bit;
ACSI_INTn : out bit;
ACSI_DRQn : out bit;
ACSI_D_IN : in std_logic_vector(7 downto 0);
ACSI_D_OUT : out std_logic_vector(7 downto 0);
ACSI_D_EN : out bit;
-- Microcontroller interface:
MC_DO : in bit;
MC_PIO_DMAn : in bit;
MC_RWn : in bit;
MC_CLR_CMD : in bit;
MC_DONE : out bit;
MC_GOT_CMD : out bit;
MC_D_IN : in std_logic_vector(7 downto 0);
MC_D_OUT : out std_logic_vector(7 downto 0);
MC_D_EN : out bit
);
end WF_SD_CARD;
architecture BEHAVIOR of WF_SD_CARD is
signal DATA_REG : std_logic_vector(7 downto 0);
signal D0_REG : bit;
signal INT_REG : bit;
signal DRQ_REG : bit;
signal DONE_REG : bit;
signal GOT_CMD_REG : bit;
signal HOLD : bit;
signal PREV_CSn : bit;
signal PREV_ACKn : bit;
begin
MC_D_OUT <= DATA_REG when MC_RWn = '0' and DONE_REG = '1' else (others => '0');
MC_D_EN <= '1' when MC_RWn = '0' and DONE_REG = '1' else '0';
ACSI_D_OUT <= DATA_REG when MC_RWn = '1' and (ACSI_CSn = '0' or ACSI_ACKn = '0' or HOLD = '1') else (others => '0');
--ACSI_D_EN <= '1' when MC_RWn = '1' and (ACSI_CSn = '0' or ACSI_ACKn = '0' or HOLD = '1') else '0';
ACSI_D_EN <= '0'; -- Disabled.
--ACSI_INTn <= INT_REG;
ACSI_INTn <= '1'; -- Disabled.
--ACSI_DRQn <= DRQ_REG;
ACSI_DRQn <= '1'; -- Disabled.
MC_DONE <= DONE_REG;
MC_GOT_CMD <= GOT_CMD_REG;
P_DATA: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= (others => '0');
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' and MC_RWn = '1' then
DATA_REG <= MC_D_IN; -- Read from AVR to ACSI.
end if;
--
if PREV_CSn = '0' and ACSI_CSn = '0' and MC_RWn = '0' and DONE_REG = '0' then
DATA_REG <= ACSI_D_IN; -- Write from ACSI to AVR.
elsif PREV_ACKn = '0' and ACSI_ACKn = '0' and MC_RWn = '0' and DONE_REG = '0' then
DATA_REG <= ACSI_D_IN; -- Write from ACSI to AVR.
end if;
end if;
end process P_DATA;
P_SYNC: process
begin
wait until CLK = '1' and CLK' event;
PREV_CSn <= ACSI_CSn;
PREV_ACKn <= ACSI_ACKn;
end process P_SYNC;
P_INT_DRQ: process(RESETn, CLK)
begin
if RESETn = '0' then
INT_REG <= '1'; -- No interrupt.
DRQ_REG <= '1'; -- No data request.
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' and MC_PIO_DMAn = '1' then -- Positive MC_DO edge.
INT_REG <= '0'; -- Release an interrupt.
DRQ_REG <= '1';
elsif D0_REG = '0' and MC_DO = '1' then
INT_REG <= '1';
DRQ_REG <= '0'; -- Release a data request.
end if;
--
if MC_CLR_CMD = '1' then -- Clear done.
INT_REG <= '1'; -- Restore INT_REG.
DRQ_REG <= '1'; -- Restore DRQ_REG.
end if;
--
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
if ACSI_CSn = '0' then
INT_REG <= '1';
end if;
--
if ACSI_ACKn = '0' then
DRQ_REG <= '1';
end if;
end if;
end if;
end process P_INT_DRQ;
P_HOLD: process(RESETn, CLK)
begin
if RESETn = '0' then
HOLD <= '0';
elsif CLK = '1' and CLK' event then
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
HOLD <= '1';
elsif PREV_CSn = '1' and ACSI_CSn = '1' then -- If signal is high.
HOLD <= '0';
elsif PREV_ACKn = '1' and ACSI_ACKn = '1' then -- If signal is high.
HOLD <= '0';
elsif PREV_CSn = '0' and ACSI_CSn = '1' then -- Rising edge.
HOLD <= '1';
elsif PREV_ACKn = '0' and ACSI_ACKn = '1' then -- Rising edge.
HOLD <= '1';
elsif MC_CLR_CMD = '1' then -- Clear done.
HOLD <= '0';
end if;
end if;
end process P_HOLD;
P_DONE: process(RESETn, CLK)
begin
if RESETn = '0' then
DONE_REG <= '0';
elsif CLK = '1' and CLK' event then
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
DONE_REG <= '1';
elsif MC_CLR_CMD = '1' then -- Clear done.
DONE_REG <= '0';
elsif D0_REG = '0' and MC_DO = '1' then -- Positive MC_DO edge.
DONE_REG <= '0';
elsif D0_REG = '1' and MC_DO = '0' then -- Negative MC_DO edge.
DONE_REG <= '0';
end if;
end if;
end process P_DONE;
P_DO_REG: process(RESETn, CLK)
begin
if RESETn = '0' then
D0_REG <= '0';
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' then -- Positive MC_DO edge.
D0_REG <= MC_DO;
elsif D0_REG = '1' and MC_DO = '0' then -- Negative MC_DO edge.
D0_REG <= MC_DO;
end if;
end if;
end process P_DO_REG;
P_GOT_CMD: process(RESETn, CLK)
begin
if RESETn = '0' then
GOT_CMD_REG <= '0';
elsif CLK = '1' and CLK' event then
-- ?? ACSI_CSn doppelt!
if PREV_CSn = '0' and ACSI_CSn = '0' and ACSI_CSn = '0' and ACSI_A1 = '0' then
GOT_CMD_REG <= '1'; -- If command was received.
elsif PREV_ACKn = '0' and ACSI_ACKn = '0' and ACSI_CSn = '0' and ACSI_A1 = '0' then
GOT_CMD_REG <= '1'; -- If command was received.
elsif MC_CLR_CMD = '1' then -- Clear done.
GOT_CMD_REG <= '0';
end if;
end if;
end process P_GOT_CMD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,239 @@
----------------------------------------------------------------------
---- ----
---- ATARI IP Core peripheral Add-On ----
---- ----
---- This file is part of the FPGA-ATARI project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- This hardware provides an interface to connect to a SD-Card. ----
---- ----
---- This interface is based on the project 'SatanDisk' of ----
---- Miroslav Nohaj 'Jookie'. The code is an interpretation of ----
---- the original code, written in VERILOG. It is provided for ----
---- the use in a system on programmable chips (SOPC). ----
---- ----
---- Timing: Use a clock frequency of 16MHz for this component. ----
---- Use the same clock frequency for the connected AVR ----
---- microcontroller. ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2007 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
---- This hardware works with the original ATARI ----
---- hard dik driver. ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K7A 2007/01/05 WF
-- Initial Release.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF_SD_CARD is
port (
-- System:
RESETn : in bit;
CLK : in bit; -- 16MHz, see above.
-- ACSI section:
ACSI_A1 : in bit;
ACSI_CSn : in bit;
ACSI_ACKn : in bit;
ACSI_INTn : out bit;
ACSI_DRQn : out bit;
ACSI_D_IN : in std_logic_vector(7 downto 0);
ACSI_D_OUT : out std_logic_vector(7 downto 0);
ACSI_D_EN : out bit;
-- Microcontroller interface:
MC_DO : in bit;
MC_PIO_DMAn : in bit;
MC_RWn : in bit;
MC_CLR_CMD : in bit;
MC_DONE : out bit;
MC_GOT_CMD : out bit;
MC_D_IN : in std_logic_vector(7 downto 0);
MC_D_OUT : out std_logic_vector(7 downto 0);
MC_D_EN : out bit
);
end WF_SD_CARD;
architecture BEHAVIOR of WF_SD_CARD is
signal DATA_REG : std_logic_vector(7 downto 0);
signal D0_REG : bit;
signal INT_REG : bit;
signal DRQ_REG : bit;
signal DONE_REG : bit;
signal GOT_CMD_REG : bit;
signal HOLD : bit;
signal PREV_CSn : bit;
signal PREV_ACKn : bit;
begin
MC_D_OUT <= DATA_REG when MC_RWn = '0' and DONE_REG = '1' else (others => '0');
MC_D_EN <= '1' when MC_RWn = '0' and DONE_REG = '1' else '0';
ACSI_D_OUT <= DATA_REG when MC_RWn = '1' and (ACSI_CSn = '0' or ACSI_ACKn = '0' or HOLD = '1') else (others => '0');
-- ???:
--ACSI_D_EN <= '1' when MC_RWn = '1' and (ACSI_CSn = '0' or ACSI_ACKn = '0' or HOLD = '1') else '0';
ACSI_D_EN <= '0';
ACSI_INTn <= INT_REG;
ACSI_DRQn <= DRQ_REG;
MC_DONE <= DONE_REG;
MC_GOT_CMD <= GOT_CMD_REG;
P_DATA: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= (others => '0');
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' and MC_RWn = '1' then
DATA_REG <= MC_D_IN; -- Read from AVR to ACSI.
end if;
--
if PREV_CSn = '0' and ACSI_CSn = '0' and MC_RWn = '0' and DONE_REG = '0' then
DATA_REG <= ACSI_D_IN; -- Write from ACSI to AVR.
elsif PREV_ACKn = '0' and ACSI_ACKn = '0' and MC_RWn = '0' and DONE_REG = '0' then
DATA_REG <= ACSI_D_IN; -- Write from ACSI to AVR.
end if;
end if;
end process P_DATA;
P_SYNC: process
begin
wait until CLK = '1' and CLK' event;
PREV_CSn <= ACSI_CSn;
PREV_ACKn <= ACSI_ACKn;
end process P_SYNC;
P_INT_DRQ: process(RESETn, CLK)
begin
if RESETn = '0' then
INT_REG <= '1'; -- No interrupt.
DRQ_REG <= '1'; -- No data request.
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' and MC_PIO_DMAn = '1' then -- Positive MC_DO edge.
INT_REG <= '0'; -- Release an interrupt.
DRQ_REG <= '1';
elsif D0_REG = '0' and MC_DO = '1' then
INT_REG <= '1';
DRQ_REG <= '0'; -- Release a data request.
end if;
--
if MC_CLR_CMD = '1' then -- Clear done.
INT_REG <= '1'; -- Restore INT_REG.
DRQ_REG <= '1'; -- Restore DRQ_REG.
end if;
--
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
if ACSI_CSn = '0' then
INT_REG <= '1';
end if;
--
if ACSI_ACKn = '0' then
DRQ_REG <= '1';
end if;
end if;
end if;
end process P_INT_DRQ;
P_HOLD: process(RESETn, CLK)
begin
if RESETn = '0' then
HOLD <= '0';
elsif CLK = '1' and CLK' event then
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
HOLD <= '1';
elsif PREV_CSn = '1' and ACSI_CSn = '1' then -- If signal is high.
HOLD <= '0';
elsif PREV_ACKn = '1' and ACSI_ACKn = '1' then -- If signal is high.
HOLD <= '0';
elsif PREV_CSn = '0' and ACSI_CSn = '1' then -- Rising edge.
HOLD <= '1';
elsif PREV_ACKn = '0' and ACSI_ACKn = '1' then -- Rising edge.
HOLD <= '1';
elsif MC_CLR_CMD = '1' then -- Clear done.
HOLD <= '0';
end if;
end if;
end process P_HOLD;
P_DONE: process(RESETn, CLK)
begin
if RESETn = '0' then
DONE_REG <= '0';
elsif CLK = '1' and CLK' event then
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
DONE_REG <= '1';
elsif MC_CLR_CMD = '1' then -- Clear done.
DONE_REG <= '0';
elsif D0_REG = '0' and MC_DO = '1' then -- Positive MC_DO edge.
DONE_REG <= '0';
elsif D0_REG = '1' and MC_DO = '0' then -- Negative MC_DO edge.
DONE_REG <= '0';
end if;
end if;
end process P_DONE;
P_DO_REG: process(RESETn, CLK)
begin
if RESETn = '0' then
D0_REG <= '0';
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' then -- Positive MC_DO edge.
D0_REG <= MC_DO;
elsif D0_REG = '1' and MC_DO = '0' then -- Negative MC_DO edge.
D0_REG <= MC_DO;
end if;
end if;
end process P_DO_REG;
P_GOT_CMD: process(RESETn, CLK)
begin
if RESETn = '0' then
GOT_CMD_REG <= '0';
elsif CLK = '1' and CLK' event then
-- ?? ACSI_CSn doppelt!
--if PREV_CSn = '0' and ACSI_CSn = '0' and ACSI_CSn = '0' and ACSI_A1 = '0' then
GOT_CMD_REG <= '1'; -- If command was received.
elsif PREV_ACKn = '0' and ACSI_ACKn = '0' and ACSI_CSn = '0' and ACSI_A1 = '0' then
GOT_CMD_REG <= '1'; -- If command was received.
elsif MC_CLR_CMD = '1' then -- Clear done.
GOT_CMD_REG <= '0';
end if;
end if;
end process P_GOT_CMD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,84 @@
----------------------------------------------------------------------
---- ----
---- YM2149 compatible sound generator. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Model of the ST or STE's YM2149 sound generator. ----
---- ----
---- This is the package file containing the component ----
---- declarations. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
package WF2149IP_PKG is
type BUSCYCLES is (INACTIVE, R_READ, R_WRITE, ADDRESS);
component WF2149IP_WAVE
port(
RESETn : in bit;
SYS_CLK : in bit;
WAV_STRB : in bit;
ADR : in bit_vector(3 downto 0);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
BUSCYCLE : in BUSCYCLES;
CTRL_REG : in bit_vector(5 downto 0);
OUT_A : out bit;
OUT_B : out bit;
OUT_C : out bit
);
end component;
end WF2149IP_PKG;

View File

@@ -0,0 +1,170 @@
----------------------------------------------------------------------
---- ----
---- YM2149 compatible sound generator. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Model of the ST or STE's YM2149 sound generator. ----
---- This IP core of the sound generator differs slightly from ----
---- the original. Firstly it is a synchronous design without any ----
---- latches (like assumed in the original chip). This required ----
---- the introduction of a system adequate clock. In detail this ----
---- SYS_CLK should on the one hand be fast enough to meet the ----
---- timing requirements of the system's bus cycle and should one ----
---- the other hand drive the PWM modules correctly. To meet both ----
---- a SYS_CLK of 16MHz or above is recommended. ----
---- Secondly, the original chip has an implemented DA converter. ----
---- This feature is not possible in today's FPGAs. Therefore the ----
---- converter is replaced by pulse width modulators. This solu- ----
---- tion is very simple in comparison to other approaches like ----
---- external DA converters with wave tables etc. The soltution ----
---- with the pulse width modulators is probably not as accurate ----
---- DAs with wavetables. For a detailed descrition of the hard- ----
---- ware PWM filter look at the end of the wave file, where the ----
---- pulse width modulators can be found. ----
---- For a proper operation it is required, that the wave clock ----
---- is lower than the system clock. A good choice is for example ----
---- 2MHz for the wave clock and 16MHz for the system clock. ----
---- ----
---- Main module file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8B 2008/12/24 WF
-- Rewritten this top level file as a wrapper for the top_soc file.
--
library ieee;
use ieee.std_logic_1164.all;
use work.wf2149ip_pkg.all;
entity WF2149IP_TOP is
port(
SYS_CLK : in bit; -- Read the inforation in the header!
RESETn : in bit;
WAV_CLK : in bit; -- Read the inforation in the header!
SELn : in bit;
BDIR : in bit;
BC2, BC1 : in bit;
A9n, A8 : in bit;
DA : inout std_logic_vector(7 downto 0);
IO_A : inout std_logic_vector(7 downto 0);
IO_B : inout std_logic_vector(7 downto 0);
OUT_A : out bit; -- Analog (PWM) outputs.
OUT_B : out bit;
OUT_C : out bit
);
end WF2149IP_TOP;
architecture STRUCTURE of WF2149IP_TOP is
component WF2149IP_TOP_SOC
port(
SYS_CLK : in bit;
RESETn : in bit;
WAV_CLK : in bit;
SELn : in bit;
BDIR : in bit;
BC2, BC1 : in bit;
A9n, A8 : in bit;
DA_IN : in std_logic_vector(7 downto 0);
DA_OUT : out std_logic_vector(7 downto 0);
DA_EN : out bit;
IO_A_IN : in bit_vector(7 downto 0);
IO_A_OUT : out bit_vector(7 downto 0);
IO_A_EN : out bit;
IO_B_IN : in bit_vector(7 downto 0);
IO_B_OUT : out bit_vector(7 downto 0);
IO_B_EN : out bit;
OUT_A : out bit;
OUT_B : out bit;
OUT_C : out bit
);
end component;
--
signal DA_OUT : std_logic_vector(7 downto 0);
signal DA_EN : bit;
signal IO_A_IN : bit_vector(7 downto 0);
signal IO_A_OUT : bit_vector(7 downto 0);
signal IO_A_EN : bit;
signal IO_B_IN : bit_vector(7 downto 0);
signal IO_B_OUT : bit_vector(7 downto 0);
signal IO_B_EN : bit;
begin
IO_A_IN <= To_BitVector(IO_A);
IO_B_IN <= To_BitVector(IO_B);
IO_A <= To_StdLogicVector(IO_A_OUT) when IO_A_EN = '1' else (others => 'Z');
IO_B <= To_StdLogicVector(IO_B_OUT) when IO_B_EN = '1' else (others => 'Z');
DA <= DA_OUT when DA_EN = '1' else (others => 'Z');
I_SOUND: WF2149IP_TOP_SOC
port map(SYS_CLK => SYS_CLK,
RESETn => RESETn,
WAV_CLK => WAV_CLK,
SELn => SELn,
BDIR => BDIR,
BC2 => BC2,
BC1 => BC1,
A9n => A9n,
A8 => A8,
DA_IN => DA,
DA_OUT => DA_OUT,
DA_EN => DA_EN,
IO_A_IN => IO_A_IN,
IO_A_OUT => IO_A_OUT,
IO_A_EN => IO_A_EN,
IO_B_IN => IO_B_IN,
IO_B_OUT => IO_B_OUT,
IO_B_EN => IO_B_EN,
OUT_A => OUT_A,
OUT_B => OUT_B,
OUT_C => OUT_C
);
end STRUCTURE;

View File

@@ -0,0 +1,229 @@
----------------------------------------------------------------------
---- ----
---- YM2149 compatible sound generator. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Model of the ST or STE's YM2149 sound generator. ----
---- This IP core of the sound generator differs slightly from ----
---- the original. Firstly it is a synchronous design without any ----
---- latches (like assumed in the original chip). This required ----
---- the introduction of a system adequate clock. In detail this ----
---- SYS_CLK should on the one hand be fast enough to meet the ----
---- timing requirements of the system's bus cycle and should one ----
---- the other hand drive the PWM modules correctly. To meet both ----
---- a SYS_CLK of 16MHz or above is recommended. ----
---- Secondly, the original chip has an implemented DA converter. ----
---- This feature is not possible in today's FPGAs. Therefore the ----
---- converter is replaced by pulse width modulators. This solu- ----
---- tion is very simple in comparison to other approaches like ----
---- external DA converters with wave tables etc. The soltution ----
---- with the pulse width modulators is probably not as accurate ----
---- DAs with wavetables. For a detailed descrition of the hard- ----
---- ware PWM filter look at the end of the wave file, where the ----
---- pulse width modulators can be found. ----
---- For a proper operation it is required, that the wave clock ----
---- is lower than the system clock. A good choice is for example ----
---- 2MHz for the wave clock and 16MHz for the system clock. ----
---- ----
---- Main module file. ----
---- Top level file for use in systems on programmable chips. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Top level file provided for SOC (systems on programmable chips).
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use work.wf2149ip_pkg.all;
entity WF2149IP_TOP_SOC is
port(
SYS_CLK : in bit; -- Read the inforation in the header!
RESETn : in bit;
WAV_CLK : in bit; -- Read the inforation in the header!
SELn : in bit;
BDIR : in bit;
BC2, BC1 : in bit;
A9n, A8 : in bit;
DA_IN : in std_logic_vector(7 downto 0);
DA_OUT : out std_logic_vector(7 downto 0);
DA_EN : out bit;
IO_A_IN : in bit_vector(7 downto 0);
IO_A_OUT : out bit_vector(7 downto 0);
IO_A_EN : out bit;
IO_B_IN : in bit_vector(7 downto 0);
IO_B_OUT : out bit_vector(7 downto 0);
IO_B_EN : out bit;
OUT_A : out bit; -- Analog (PWM) outputs.
OUT_B : out bit;
OUT_C : out bit
);
end WF2149IP_TOP_SOC;
architecture STRUCTURE of WF2149IP_TOP_SOC is
signal BUSCYCLE : BUSCYCLES;
signal DATA_OUT_I : std_logic_vector(7 downto 0);
signal DATA_EN_I : bit;
signal WAV_STRB : bit;
signal ADR_I : bit_vector(3 downto 0);
signal CTRL_REG : bit_vector(7 downto 0);
signal PORT_A : bit_vector(7 downto 0);
signal PORT_B : bit_vector(7 downto 0);
begin
P_WAVSTRB: process(RESETn, SYS_CLK)
variable LOCK : boolean;
variable TMP : bit;
begin
if RESETn = '0' then
LOCK := false;
TMP := '0';
elsif SYS_CLK = '1' and SYS_CLK' event then
if WAV_CLK = '1' and LOCK = false then
LOCK := true;
TMP := not TMP; -- Divider by 2.
case SELn is
when '1' => WAV_STRB <= '1';
when others => WAV_STRB <= TMP;
end case;
elsif WAV_CLK = '0' then
LOCK := false;
WAV_STRB <= '0';
else
WAV_STRB <= '0';
end if;
end if;
end process P_WAVSTRB;
with BDIR & BC2 & BC1 select
BUSCYCLE <= INACTIVE when "000" | "010" | "101",
ADDRESS when "001" | "100" | "111",
R_READ when "011",
R_WRITE when "110";
ADDRESSLATCH: process(RESETn, SYS_CLK)
-- This process is responsible to store the desired register
-- address. The default (after reset) is channel A fine tone
-- adjustment.
begin
if RESETn = '0' then
ADR_I <= (others => '0');
elsif SYS_CLK = '1' and SYS_CLK' event then
if BUSCYCLE = ADDRESS and A9n = '0' and A8 = '1' and DA_IN(7 downto 4) = x"0" then
ADR_I <= To_BitVector(DA_IN(3 downto 0));
end if;
end if;
end process ADDRESSLATCH;
P_CTRL_REG: process(RESETn, SYS_CLK)
-- THIS is the Control register for the mixer and for the I/O ports.
begin
if RESETn = '0' then
CTRL_REG <= x"00";
elsif SYS_CLK = '1' and SYS_CLK' event then
if BUSCYCLE = R_WRITE and ADR_I = x"7" then
CTRL_REG <= To_BitVector(DA_IN);
end if;
end if;
end process P_CTRL_REG;
DIG_PORTS: process(RESETn, SYS_CLK)
begin
if RESETn = '0' then
PORT_A <= x"00";
PORT_B <= x"00";
elsif SYS_CLK = '1' and SYS_CLK' event then
if BUSCYCLE = R_WRITE and ADR_I = x"E" then
PORT_A <= To_BitVector(DA_IN);
elsif BUSCYCLE = R_WRITE and ADR_I = x"F" then
PORT_B <= To_BitVector(DA_IN);
end if;
end if;
end process DIG_PORTS;
-- Set port direction to input or to output:
IO_A_EN <= '1' when CTRL_REG(6) = '1' else '0';
IO_B_EN <= '1' when CTRL_REG(7) = '1' else '0';
IO_A_OUT <= PORT_A;
IO_B_OUT <= PORT_B;
I_PSG_WAVE: WF2149IP_WAVE
port map(
RESETn => RESETn,
SYS_CLK => SYS_CLK,
WAV_STRB => WAV_STRB,
ADR => ADR_I,
DATA_IN => DA_IN,
DATA_OUT => DATA_OUT_I,
DATA_EN => DATA_EN_I,
BUSCYCLE => BUSCYCLE,
CTRL_REG => CTRL_REG(5 downto 0),
OUT_A => OUT_A,
OUT_B => OUT_B,
OUT_C => OUT_C
);
-- Read the ports and registers:
DA_EN <= '1' when DATA_EN_I = '1' else
'1' when BUSCYCLE = R_READ and ADR_I = x"7" else
'1' when BUSCYCLE = R_READ and ADR_I = x"E" else
'1' when BUSCYCLE = R_READ and ADR_I = x"F" else '0';
DA_OUT <= DATA_OUT_I when DATA_EN_I = '1' else -- WAV stuff.
To_StdLogicVector(IO_A_IN) when BUSCYCLE = R_READ and ADR_I = x"E" else
To_StdLogicVector(IO_B_IN) when BUSCYCLE = R_READ and ADR_I = x"F" else
To_StdLogicVector(CTRL_REG) when BUSCYCLE = R_READ and ADR_I = x"7" else (others => '0');
end STRUCTURE;

View File

@@ -0,0 +1,533 @@
----------------------------------------------------------------------
---- ----
---- YM2149 compatible sound generator. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Model of the ST or STE's YM2149 sound generator. ----
---- ----
---- Waveform generator. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- NOISE_OUT has now synchronous reset to meet preset requirement.
-- Fixed a bug in the envelope generator. Thanks to Lyndon Amsdon finding it.
-- Correction of the schematic given in the end of this file.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use work.wf2149ip_pkg.all;
entity WF2149IP_WAVE is
port(
RESETn : in bit;
SYS_CLK : in bit;
WAV_STRB : in bit;
ADR : in bit_vector(3 downto 0);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
BUSCYCLE : in BUSCYCLES;
CTRL_REG : in bit_vector(5 downto 0);
OUT_A : out bit;
OUT_B : out bit;
OUT_C : out bit
);
end entity WF2149IP_WAVE;
architecture BEHAVIOR of WF2149IP_WAVE is
signal FREQUENCY_A : std_logic_vector(11 downto 0);
signal FREQUENCY_B : std_logic_vector(11 downto 0);
signal FREQUENCY_C : std_logic_vector(11 downto 0);
signal NOISE_FREQ : std_logic_vector(4 downto 0);
signal LEVEL_A : std_logic_vector(4 downto 0);
signal LEVEL_B : std_logic_vector(4 downto 0);
signal LEVEL_C : std_logic_vector(4 downto 0);
signal ENV_FREQ : std_logic_vector(15 downto 0);
signal ENV_SHAPE : std_logic_vector(3 downto 0);
signal ENV_RESET : boolean;
signal ENV_STRB : bit;
signal OSC_A_OUT : bit;
signal OSC_B_OUT : bit;
signal OSC_C_OUT : bit;
signal NOISE_OUT : bit;
signal AUDIO_A : bit;
signal AUDIO_B : bit;
signal AUDIO_C : bit;
signal VOL_ENV : std_logic_vector(4 downto 0);
signal AMPLITUDE_A : std_logic_vector(4 downto 0);
signal AMPLITUDE_B : std_logic_vector(4 downto 0);
signal AMPLITUDE_C : std_logic_vector(4 downto 0);
signal VOLUME_A : std_logic_vector(7 downto 0);
signal VOLUME_B : std_logic_vector(7 downto 0);
signal VOLUME_C : std_logic_vector(7 downto 0);
signal PWM_RAMP : std_logic_vector(7 downto 0);
begin
REGISTERS: process(RESETn, SYS_CLK)
-- This process is responsible for initialisation
-- and write access to the configuration registers.
begin
if RESETn = '0' then
FREQUENCY_A <= x"000";
FREQUENCY_B <= x"000";
FREQUENCY_C <= x"000";
NOISE_FREQ <= "00000";
LEVEL_A <= "00000";
LEVEL_B <= "00000";
LEVEL_C <= "00000";
ENV_FREQ <= (others => '0');
ENV_SHAPE <= "0000";
elsif SYS_CLK = '1' and SYS_CLK' event then
ENV_RESET <= false; -- Initialize signal.
if BUSCYCLE = R_WRITE then
case ADR is
when x"0" => FREQUENCY_A(7 downto 0) <= DATA_IN;
when x"1" => FREQUENCY_A(11 downto 8) <= DATA_IN(3 downto 0);
when x"2" => FREQUENCY_B(7 downto 0) <= DATA_IN;
when x"3" => FREQUENCY_B(11 downto 8) <= DATA_IN(3 downto 0);
when x"4" => FREQUENCY_C(7 downto 0) <= DATA_IN;
when x"5" => FREQUENCY_C(11 downto 8) <= DATA_IN(3 downto 0);
when x"6" => NOISE_FREQ <= DATA_IN(4 downto 0);
when x"8" => LEVEL_A <= DATA_IN(4 downto 0);
when x"9" => LEVEL_B <= DATA_IN(4 downto 0);
when x"A" => LEVEL_C <= DATA_IN(4 downto 0);
when x"B" => ENV_FREQ(7 downto 0) <= DATA_IN;
when x"C" => ENV_FREQ(15 downto 8) <= DATA_IN;
ENV_RESET <= true; -- Initialize the envelope generator.
when x"D" => ENV_SHAPE <= DATA_IN(3 downto 0);
when others => null;
end case;
end if;
end if;
end process REGISTERS;
-- Read back the configuration registers:
DATA_OUT <= FREQUENCY_A(7 downto 0) when BUSCYCLE = R_READ and ADR = x"0" else
"0000" & FREQUENCY_A(11 downto 8) when BUSCYCLE = R_READ and ADR = x"1" else
FREQUENCY_B(7 downto 0) when BUSCYCLE = R_READ and ADR = x"2" else
"0000" & FREQUENCY_B(11 downto 8) when BUSCYCLE = R_READ and ADR = x"3" else
FREQUENCY_C(7 downto 0) when BUSCYCLE = R_READ and ADR = x"4" else
"0000" & FREQUENCY_C(11 downto 8) when BUSCYCLE = R_READ and ADR = x"5" else
"000" & NOISE_FREQ when BUSCYCLE = R_READ and ADR = x"6" else
"000" & LEVEL_A when BUSCYCLE = R_READ and ADR = x"8" else
"000" & LEVEL_B when BUSCYCLE = R_READ and ADR = x"9" else
"000" & LEVEL_C when BUSCYCLE = R_READ and ADR = x"A" else
ENV_FREQ(7 downto 0) when BUSCYCLE = R_READ and ADR = x"B" else
ENV_FREQ(15 downto 8) when BUSCYCLE = R_READ and ADR = x"C" else
x"0" & ENV_SHAPE when BUSCYCLE = R_READ and ADR = x"D" else (others => '0');
DATA_EN <= '1' when BUSCYCLE = R_READ and ADR >= x"0" and ADR <= x"6" else
'1' when BUSCYCLE = R_READ and ADR >= x"8" and ADR <= x"D" else '0';
MUSICGENERATOR: process(RESETn, SYS_CLK)
variable CLK_DIV : std_logic_vector(2 downto 0);
variable CNT_CH_A : std_logic_vector(11 downto 0);
variable CNT_CH_B : std_logic_vector(11 downto 0);
variable CNT_CH_C : std_logic_vector(11 downto 0);
begin
if RESETn = '0' then
CLK_DIV := "000";
CNT_CH_A := (others => '0');
CNT_CH_B := (others => '0');
CNT_CH_C := (others => '0');
OSC_A_OUT <= '0';
OSC_B_OUT <= '0';
OSC_C_OUT <= '0';
elsif SYS_CLK = '1' and SYS_CLK' event then
if WAV_STRB = '1' then
-- Divider by 8 for the oscillators brings in connection
-- with the toggle flip flops CH_x_OUT the required divider
-- ratio of 16.
CLK_DIV := CLK_DIV + '1';
if CLK_DIV = "000" then
if FREQUENCY_A = x"000" then
CNT_CH_A := (others => '0');
OSC_A_OUT <= '0';
elsif CNT_CH_A = x"000" then
CNT_CH_A := FREQUENCY_A - '1' ;
OSC_A_OUT <= not OSC_A_OUT;
else
CNT_CH_A := CNT_CH_A - '1';
end if;
if FREQUENCY_B = x"000" then
CNT_CH_B := (others => '0');
OSC_B_OUT <= '0';
elsif CNT_CH_B = x"000" then
CNT_CH_B := FREQUENCY_B - '1' ;
OSC_B_OUT <= not OSC_B_OUT;
else
CNT_CH_B := CNT_CH_B - '1';
end if;
if FREQUENCY_C = x"000" then
CNT_CH_C := (others => '0');
OSC_C_OUT <= '0';
elsif CNT_CH_C = x"000" then
CNT_CH_C := FREQUENCY_C - '1' ;
OSC_C_OUT <= not OSC_C_OUT;
else
CNT_CH_C := CNT_CH_C - '1';
end if;
end if;
end if;
end if;
end process MUSICGENERATOR;
NOISEGENERATOR: process
-- The noise shift polynomial is taken from a template of Kazuhiro TSUJIKAWA's
-- (ESE Artists' factory) approach for a 2149 equivalent. But the implementation
-- is done in another way.
-- LFSR (linear feedback shift register polynomial: f(x) = x^17 + x^14 + 1.
variable CLK_DIV : std_logic_vector(3 downto 0);
variable CNT_NOISE : std_logic_vector(4 downto 0);
variable N_SHFT : std_logic_vector(16 downto 0);
begin
wait until SYS_CLK = '1' and SYS_CLK' event;
if RESETn = '0' then
CLK_DIV := x"0";
CNT_NOISE := (others => '1'); -- Preset the polynomial shift register.
NOISE_OUT <= '1';
elsif WAV_STRB = '1' then
-- Divider by 16 for the noise generator.
CLK_DIV := CLK_DIV + '1';
if CLK_DIV = x"0" then
-- Noise frequency counter.
if NOISE_FREQ = "00000" then
CNT_NOISE := (others => '0');
elsif CNT_NOISE = "00000" then
CNT_NOISE := NOISE_FREQ - '1' ;
N_SHFT := N_SHFT(15 downto 14) & not(N_SHFT(16) xor N_SHFT(13)) &
N_SHFT(12 downto 0) & not N_SHFT(16);
else
CNT_NOISE := CNT_NOISE - '1';
end if;
end if;
end if;
NOISE_OUT <= To_Bit(N_SHFT(16));
end process NOISEGENERATOR;
ENVELOPE_PERIOD: process(RESETn, SYS_CLK)
-- The envelope period is controlled by the Envelope Frequency and the divider ratio which is
-- 256/32 = 8. For further information see the original data sheet.
variable ENV_CLK : std_logic_vector(18 downto 0);
variable LOCK : boolean;
begin
if RESETn = '0' then
ENV_STRB <= '0';
ENV_CLK := (others => '0');
LOCK := false;
elsif SYS_CLK = '1' and SYS_CLK' event then
if WAV_STRB = '1' and LOCK = false then
LOCK := true;
if ENV_FREQ = x"0000" then
ENV_STRB <= '0';
elsif ENV_CLK = x"0000" & "000" then
ENV_CLK := (ENV_FREQ & "111") - '1' ;
ENV_STRB <= '1';
else
ENV_CLK := ENV_CLK - '1';
ENV_STRB <= '0';
end if;
elsif WAV_STRB = '0' then
LOCK := false;
ENV_STRB <= '0';
else
ENV_STRB <= '0';
end if;
end if;
end process ENVELOPE_PERIOD;
ENVELOPE: process(RESETn, SYS_CLK)
-- Envelope shapes:
-- case ENV_SHAPE:
--
-- 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 /|___
--
variable ENV_STOP : boolean;
variable ENV_UP_DNn : bit;
begin
if RESETn = '0' then
VOL_ENV <= (others => '0');
ENV_UP_DNn := '0';
ENV_STOP := false;
elsif SYS_CLK = '1' and SYS_CLK' event then
if ENV_RESET = true then
ENV_STOP := false;
case ENV_SHAPE is
when "1011" | "1010" | "1001" | "1000" | "0011" | "0010" | "0001" | "0000" =>
VOL_ENV <= "11111"; -- Start on top.
ENV_UP_DNn := '0';
when others =>
VOL_ENV <= "00000"; -- Start at bottom.
ENV_UP_DNn := '1';
end case;
elsif ENV_STRB = '1' then
case ENV_SHAPE is
when "1001" | "0011" | "0010" | "0001" | "0000" =>
if VOL_ENV > "00000" then
VOL_ENV <= VOL_ENV - '1';
end if;
when "1111" | "0111" | "0110" | "0101" | "0100" =>
if VOL_ENV < "11111" and ENV_STOP = false then
VOL_ENV <= VOL_ENV + '1';
else
VOL_ENV <= "00000";
ENV_STOP := true;
end if;
when "1000" =>
VOL_ENV <= VOL_ENV - '1';
when "1110" | "1010" =>
if ENV_UP_DNn = '0' then
VOL_ENV <= VOL_ENV - '1';
else
VOL_ENV <= VOL_ENV + '1';
end if;
--
if VOL_ENV = "00001" then
ENV_UP_DNn := '1';
elsif VOL_ENV = "11110" then
ENV_UP_DNn := '0';
end if;
when "1011" =>
if VOL_ENV > "00000" and ENV_STOP = false then
VOL_ENV <= VOL_ENV - '1';
else
VOL_ENV <= "11111";
ENV_STOP := true;
end if;
when "1100" =>
VOL_ENV <= VOL_ENV + '1';
when "1101" =>
if VOL_ENV < "11111" then
VOL_ENV <= VOL_ENV + '1';
end if;
when others => null; -- Covers U, X, Z, W, H, L, -.
end case;
end if;
end if;
end process ENVELOPE;
--MIXER:
-- The mixer controls are dependant on the mixer settings and the output of the
-- audio data for all three channels. The noise generator and the square wave
-- generators A, B and C are mixed together by a simple boolean OR.
AUDIO_A <= (OSC_A_OUT and not CTRL_REG(0)) or (NOISE_OUT and not CTRL_REG(3));
AUDIO_B <= (OSC_B_OUT and not CTRL_REG(1)) or (NOISE_OUT and not CTRL_REG(4));
AUDIO_C <= (OSC_C_OUT and not CTRL_REG(2)) or (NOISE_OUT and not CTRL_REG(5));
--LEVEL (e.g. volume control):
-- The linear amplitude for the DA converters of channel A, B or C are fixed
-- (LEVEL(3 downto 0)) or delivered by the envelope generator.
-- The following behavior is taken from the 2149 IP core of Mike J (www.fpgaarcade.com):
-- "make sure level 31 (env) = level 15 (tone)"
-- Thus there is a resulting & '1' modeling if LEVEL amplitudes are selected.
AMPLITUDE_A <= LEVEL_A(3 downto 0) & '1' when LEVEL_A(4) = '0' and AUDIO_A = '1' else
VOL_ENV when LEVEL_A(4) = '1' and AUDIO_A = '1' else "00000";
AMPLITUDE_B <= LEVEL_B(3 downto 0) & '1' when LEVEL_B(4) = '0' and AUDIO_B = '1' else
VOL_ENV when LEVEL_B(4) = '1' and AUDIO_B = '1' else "00000";
AMPLITUDE_C <= LEVEL_C(3 downto 0) & '1' when LEVEL_C(4) = '0' and AUDIO_C = '1' else
VOL_ENV when LEVEL_C(4) = '1' and AUDIO_C = '1' else "00000";
-- The values for the logarithmic DA converter volume controls are taken from the linear
-- mixer of Mike J's 2149 IP core (www.fpgaarcade.com).
with AMPLITUDE_A select
VOLUME_A <= x"FF" when "11111",
x"D9" when "11110",
x"BA" when "11101",
x"9F" when "11100",
x"88" when "11011",
x"74" when "11010",
x"63" when "11001",
x"54" when "11000",
x"48" when "10111",
x"3D" when "10110",
x"34" when "10101",
x"2C" when "10100",
x"25" when "10011",
x"1F" when "10010",
x"1A" when "10001",
x"16" when "10000",
x"13" when "01111",
x"10" when "01110",
x"0D" when "01101",
x"0B" when "01100",
x"09" when "01011",
x"08" when "01010",
x"07" when "01001",
x"06" when "01000",
x"05" when "00111",
x"04" when "00110",
x"03" when "00101",
x"03" when "00100",
x"02" when "00011",
x"02" when "00010",
x"01" when "00001",
x"00" when others; -- Also covers U, X, Z, W, H, L, -.
with AMPLITUDE_B select
VOLUME_B <= x"FF" when "11111",
x"D9" when "11110",
x"BA" when "11101",
x"9F" when "11100",
x"88" when "11011",
x"74" when "11010",
x"63" when "11001",
x"54" when "11000",
x"48" when "10111",
x"3D" when "10110",
x"34" when "10101",
x"2C" when "10100",
x"25" when "10011",
x"1F" when "10010",
x"1A" when "10001",
x"16" when "10000",
x"13" when "01111",
x"10" when "01110",
x"0D" when "01101",
x"0B" when "01100",
x"09" when "01011",
x"08" when "01010",
x"07" when "01001",
x"06" when "01000",
x"05" when "00111",
x"04" when "00110",
x"03" when "00101",
x"03" when "00100",
x"02" when "00011",
x"02" when "00010",
x"01" when "00001",
x"00" when others; -- Also covers U, X, Z, W, H, L, -.
with AMPLITUDE_C select
VOLUME_C <= x"FF" when "11111",
x"D9" when "11110",
x"BA" when "11101",
x"9F" when "11100",
x"88" when "11011",
x"74" when "11010",
x"63" when "11001",
x"54" when "11000",
x"48" when "10111",
x"3D" when "10110",
x"34" when "10101",
x"2C" when "10100",
x"25" when "10011",
x"1F" when "10010",
x"1A" when "10001",
x"16" when "10000",
x"13" when "01111",
x"10" when "01110",
x"0D" when "01101",
x"0B" when "01100",
x"09" when "01011",
x"08" when "01010",
x"07" when "01001",
x"06" when "01000",
x"05" when "00111",
x"04" when "00110",
x"03" when "00101",
x"03" when "00100",
x"02" when "00011",
x"02" when "00010",
x"01" when "00001",
x"00" when others; -- Also covers U, X, Z, W, H, L, -.
DA_CONVERSION: process
-- The DA conversion for the three analog outputs is originally performed by a built in DA converter.
-- For this is not possible in current FPGA designs, the converter is replaced by three PWM units
-- operating at a frequency which is 100 times higher than the highest noise or music frequency which
-- is 2MHz/16 = 125kHz. So the PWM frequency requires about 12.5MHz or more. The design is done for
-- a PWM frequency of 16MHz).
begin
wait until SYS_CLK = '1' and SYS_CLK' event;
PWM_RAMP <= PWM_RAMP + '1';
end process DA_CONVERSION;
OUT_A <= '0' when VOLUME_A = x"00" else '1' when PWM_RAMP < VOLUME_A else '0';
OUT_B <= '0' when VOLUME_B = x"00" else '1' when PWM_RAMP < VOLUME_B else '0';
OUT_C <= '0' when VOLUME_C = x"00" else '1' when PWM_RAMP < VOLUME_C else '0';
--
-- To obtain proper analog output it is necessary to install analog RC filters to the pulse width
-- outputs. An example is given for the direct wiring of the three analog outputs and for a system
-- clock frequency of 16MHz. The output circuitry looks in this case as follows:
--
-- OUT_A ---------|1kOhm|-----------| |\ e.g. LM741
-- |----------------------|+\ ||
-- OUT_B ---------|1kOhm|-----------| | OP------||--- Analog Signal
-- | |-----|-/ | ||
-- OUT_C ---------|1kOhm|-----------| | |/ | 4u7
-- | |__________|
-- |
-- --- 10nF.
-- ---
-- |
-- |
-- ---
-- WF.
end architecture BEHAVIOR;

View File

@@ -0,0 +1,244 @@
----------------------------------------------------------------------
---- ----
---- 6850 compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- UART 6850 compatible IP core ----
---- ----
---- Control unit and status logic. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- CTRL_REG has now synchronous reset to meet preset requirements.
-- Process P_DCD has now synchronous reset to meet preset requirements.
-- IRQ_In has now synchronous reset to meet preset requirement.
-- Revision 2K9B 2009/12/24 WF
-- Fixed the interrupt logic.
-- Introduced a minor RTSn correction.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_CTRL_STATUS is
port (
CLK : in bit;
RESETn : in bit;
CS : in bit_vector(2 downto 0); -- Active if "011".
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
-- Status register stuff:
RDRF : in bit; -- Receive data register full.
TDRE : in bit; -- Transmit data register empty.
DCDn : in bit; -- Data carrier detect.
CTSn : in bit; -- Clear to send.
FE : in bit; -- Framing error.
OVR : in bit; -- Overrun error.
PE : in bit; -- Parity error.
-- Control register stuff:
MCLR : buffer bit; -- Master clear (high active).
RTSn : out bit; -- Request to send.
CDS : out bit_vector(1 downto 0); -- Clock control.
WS : out bit_vector(2 downto 0); -- Word select.
TC : out bit_vector(1 downto 0); -- Transmit control.
IRQn : out bit -- Interrupt request.
);
end entity WF6850IP_CTRL_STATUS;
architecture BEHAVIOR of WF6850IP_CTRL_STATUS is
signal CTRL_REG : bit_vector(7 downto 0);
signal STATUS_REG : bit_vector(7 downto 0);
signal RIE : bit;
signal IRQ_I : bit;
signal CTS_In : bit;
signal DCD_In : bit;
signal DCD_FLAGn : bit;
begin
P_SAMPLE: process
begin
wait until CLK = '0' and CLK' event;
CTS_In <= CTSn; -- Sample CTSn on the negative clock edge.
DCD_In <= DCDn; -- Sample DCDn on the negative clock edge.
end process P_SAMPLE;
STATUS_REG(7) <= IRQ_I;
STATUS_REG(6) <= PE;
STATUS_REG(5) <= OVR;
STATUS_REG(4) <= FE;
STATUS_REG(3) <= CTS_In; -- Reflexion of the input pin.
STATUS_REG(2) <= DCD_FLAGn;
STATUS_REG(1) <= TDRE and not CTS_In; -- No TDRE for CTSn = '1'.
STATUS_REG(0) <= RDRF and not DCD_In; -- DCDn = '1' indicates empty.
DATA_OUT <= STATUS_REG when CS = "011" and RWn = '1' and RS = '0' and E = '1' else (others => '0');
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '0' and E = '1' else '0';
MCLR <= '1' when CTRL_REG(1 downto 0) = "11" else '0';
RTSn <= '0' when CTRL_REG(6 downto 5) /= "10" else '1';
CDS <= CTRL_REG(1 downto 0);
WS <= CTRL_REG(4 downto 2);
TC <= CTRL_REG(6 downto 5);
RIE <= CTRL_REG(7);
P_IRQ: process
variable DCD_OVR_LOCK : boolean;
variable DCD_LOCK : boolean;
variable DCD_TRANS : boolean;
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
DCD_OVR_LOCK := false;
IRQn <= '1';
IRQ_I <= '0';
elsif CS = "011" and RWn = '1' and RS = '0' and E = '1' then
DCD_OVR_LOCK := false; -- Enable reset by reading the status.
end if;
-- Clear interrupts when disabled.
if CTRL_REG(7) = '0' then
IRQn <= '1';
IRQ_I <= '0';
elsif CTRL_REG(6 downto 5) /= "01" then
IRQn <= '1';
IRQ_I <= '0';
end if;
-- Transmitter interrupt:
if TDRE = '1' and CTRL_REG(6 downto 5) = "01" and CTS_In = '0' then
IRQn <= '0';
IRQ_I <= '1';
elsif CS = "011" and RWn = '0' and RS = '1' and E = '1' then
IRQn <= '1'; -- Clear by writing to the transmit data register.
end if;
-- Receiver interrupts:
if RDRF = '1' and RIE = '1' and DCD_In = '0' then
IRQn <= '0';
IRQ_I <= '1';
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' then
IRQn <= '1'; -- Clear by reading the receive data register.
end if;
if OVR = '1' and RIE = '1' then
IRQn <= '0';
IRQ_I <= '1';
DCD_OVR_LOCK := true;
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' and DCD_OVR_LOCK = false then
IRQn <= '1'; -- Clear by reading the receive data register after the status.
end if;
if DCD_In = '1' and RIE = '1' and DCD_TRANS = false then
IRQn <= '0';
IRQ_I <= '1';
-- DCD_TRANS is used to detect a low to high transition of DCDn.
DCD_TRANS := true;
DCD_OVR_LOCK := true;
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' and DCD_OVR_LOCK = false then
IRQn <= '1'; -- Clear by reading the receive data register after the status.
elsif DCD_In = '0' then
DCD_TRANS := false;
end if;
-- The reset of the IRQ status flag:
-- Clear by writing to the transmit data register.
-- Clear by reading the receive data register.
if CS = "011" and RS = '1' and E = '1' then
IRQ_I <= '0';
end if;
end process P_IRQ;
CONTROL: process
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
CTRL_REG <= "01000000";
elsif CS = "011" and RWn = '0' and RS = '0' and E = '1' then
CTRL_REG <= DATA_IN;
end if;
end process CONTROL;
P_DCD: process
-- This process is some kind of tricky. Refer to the MC6850 data
-- sheet for more information.
variable READ_LOCK : boolean;
variable DCD_RELEASE : boolean;
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
DCD_FLAGn <= '0'; -- This interrupt source must initialise low.
READ_LOCK := true;
DCD_RELEASE := false;
elsif MCLR = '1' then
DCD_FLAGn <= DCD_In;
READ_LOCK := true;
elsif DCD_In = '1' then
DCD_FLAGn <= '1';
elsif CS = "011" and RWn = '1' and RS = '0' and E = '1' then
READ_LOCK := false; -- Un-READ_LOCK if receiver data register is read.
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' and READ_LOCK = false then
-- Clear if receiver status register read access.
-- After data register has ben read and READ_LOCK again.
DCD_RELEASE := true;
READ_LOCK := true;
DCD_FLAGn <= DCD_In;
elsif DCD_In = '0' and DCD_RELEASE = true then
DCD_FLAGn <= '0';
DCD_RELEASE := false;
end if;
end process P_DCD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,244 @@
----------------------------------------------------------------------
---- ----
---- 6850 compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- UART 6850 compatible IP core ----
---- ----
---- Control unit and status logic. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- CTRL_REG has now synchronous reset to meet preset requirements.
-- Process P_DCD has now synchronous reset to meet preset requirements.
-- IRQ_In has now synchronous reset to meet preset requirement.
-- Revision 2K9B 2009/12/24 WF
-- Fixed the interrupt logic.
-- Introduced a minor RTSn correction.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_CTRL_STATUS is
port (
CLK : in bit;
RESETn : in bit;
CS : in bit_vector(2 downto 0); -- Active if "011".
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
-- Status register stuff:
RDRF : in bit; -- Receive data register full.
TDRE : in bit; -- Transmit data register empty.
DCDn : in bit; -- Data carrier detect.
CTSn : in bit; -- Clear to send.
FE : in bit; -- Framing error.
OVR : in bit; -- Overrun error.
PE : in bit; -- Parity error.
-- Control register stuff:
MCLR : buffer bit; -- Master clear (high active).
RTSn : out bit; -- Request to send.
CDS : out bit_vector(1 downto 0); -- Clock control.
WS : out bit_vector(2 downto 0); -- Word select.
TC : out bit_vector(1 downto 0); -- Transmit control.
IRQn : out bit -- Interrupt request.
);
end entity WF6850IP_CTRL_STATUS;
architecture BEHAVIOR of WF6850IP_CTRL_STATUS is
signal CTRL_REG : bit_vector(7 downto 0);
signal STATUS_REG : bit_vector(7 downto 0);
signal RIE : bit;
signal IRQ_I : bit;
signal CTS_In : bit;
signal DCD_In : bit;
signal DCD_FLAGn : bit;
begin
P_SAMPLE: process
begin
wait until CLK = '0' and CLK' event;
CTS_In <= CTSn; -- Sample CTSn on the negative clock edge.
DCD_In <= DCDn; -- Sample DCDn on the negative clock edge.
end process P_SAMPLE;
STATUS_REG(7) <= IRQ_I;
STATUS_REG(6) <= PE;
STATUS_REG(5) <= OVR;
STATUS_REG(4) <= FE;
STATUS_REG(3) <= CTS_In; -- Reflexion of the input pin.
STATUS_REG(2) <= DCD_FLAGn;
STATUS_REG(1) <= TDRE and not CTS_In; -- No TDRE for CTSn = '1'.
STATUS_REG(0) <= RDRF and not DCD_In; -- DCDn = '1' indicates empty.
DATA_OUT <= STATUS_REG when CS = "011" and RWn = '1' and RS = '0' and E = '1' else (others => '0');
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '0' and E = '1' else '0';
MCLR <= '1' when CTRL_REG(1 downto 0) = "11" else '0';
RTSn <= '0' when CTRL_REG(6 downto 5) /= "10" else '1';
CDS <= CTRL_REG(1 downto 0);
WS <= CTRL_REG(4 downto 2);
TC <= CTRL_REG(6 downto 5);
RIE <= CTRL_REG(7);
P_IRQ: process
variable DCD_OVR_LOCK : boolean;
variable DCD_LOCK : boolean;
variable DCD_TRANS : boolean;
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
DCD_OVR_LOCK := false;
IRQn <= '1';
IRQ_I <= '0';
elsif CS = "011" and RWn = '1' and RS = '0' and E = '1' then
DCD_OVR_LOCK := false; -- Enable reset by reading the status.
end if;
-- Clear interrupts when disabled.
if CTRL_REG(7) = '0' then
IRQn <= '1';
IRQ_I <= '0';
elsif CTRL_REG(6 downto 5) /= "01" then
IRQn <= '1';
IRQ_I <= '0';
end if;
-- Transmitter interrupt:
if TDRE = '1' and CTRL_REG(6 downto 5) = "01" and CTS_In = '0' then
IRQn <= '0';
IRQ_I <= '1';
elsif CS = "011" and RWn = '0' and RS = '1' and E = '1' then
IRQn <= '1'; -- Clear by writing to the transmit data register.
end if;
-- Receiver interrupts:
if RDRF = '1' and RIE = '1' and DCD_In = '0' then
IRQn <= '0';
IRQ_I <= '1';
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' then
IRQn <= '1'; -- Clear by reading the receive data register.
end if;
if OVR = '1' and RIE = '1' then
IRQn <= '0';
IRQ_I <= '1';
DCD_OVR_LOCK := true;
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' and DCD_OVR_LOCK = false then
IRQn <= '1'; -- Clear by reading the receive data register after the status.
end if;
if DCD_In = '1' and RIE = '1' and DCD_TRANS = false then
IRQn <= '0';
IRQ_I <= '1';
-- DCD_TRANS is used to detect a low to high transition of DCDn.
DCD_TRANS := true;
DCD_OVR_LOCK := true;
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' and DCD_OVR_LOCK = false then
IRQn <= '1'; -- Clear by reading the receive data register after the status.
elsif DCD_In = '0' then
DCD_TRANS := false;
end if;
-- The reset of the IRQ status flag:
-- Clear by writing to the transmit data register.
-- Clear by reading the receive data register.
if CS = "011" and RS = '1' and E = '1' then
IRQ_I <= '0';
end if;
end process P_IRQ;
CONTROL: process
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
CTRL_REG <= "01000000";
elsif CS = "011" and RWn = '0' and RS = '0' and E = '1' then
CTRL_REG <= DATA_IN;
end if;
end process CONTROL;
P_DCD: process
-- This process is some kind of tricky. Refer to the MC6850 data
-- sheet for more information.
variable READ_LOCK : boolean;
variable DCD_RELEASE : boolean;
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
DCD_FLAGn <= '0'; -- This interrupt source must initialise low.
READ_LOCK := true;
DCD_RELEASE := false;
elsif MCLR = '1' then
DCD_FLAGn <= DCD_In;
READ_LOCK := true;
elsif DCD_In = '1' then
DCD_FLAGn <= '1';
elsif CS = "011" and RWn = '1' and RS = '0' and E = '1' then
READ_LOCK := false; -- Un-READ_LOCK if receiver data register is read.
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' and READ_LOCK = false then
-- Clear if receiver status register read access.
-- After data register has ben read and READ_LOCK again.
DCD_RELEASE := true;
READ_LOCK := true;
DCD_FLAGn <= DCD_In;
elsif DCD_In = '0' and DCD_RELEASE = true then
DCD_FLAGn <= '0';
DCD_RELEASE := false;
end if;
end process P_DCD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,415 @@
----------------------------------------------------------------------
---- ----
---- 6850 compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- UART 6850 compatible IP core ----
---- ----
---- 6850's receiver unit. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_RECEIVE is
port (
CLK : in bit;
RESETn : in bit;
MCLR : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
WS : in bit_vector(2 downto 0);
CDS : in bit_vector(1 downto 0);
RXCLK : in bit;
RXDATA : in bit;
RDRF : buffer bit;
OVR : out bit;
PE : out bit;
FE : out bit
);
end entity WF6850IP_RECEIVE;
architecture BEHAVIOR of WF6850IP_RECEIVE is
type RCV_STATES is (IDLE, WAIT_START, SAMPLE, PARITY, STOP1, STOP2, SYNC);
signal RCV_STATE, RCV_NEXT_STATE : RCV_STATES;
signal RXDATA_I : bit;
signal RXDATA_S : bit;
signal DATA_REG : bit_vector(7 downto 0);
signal SHIFT_REG : bit_vector(7 downto 0);
signal CLK_STRB : bit;
signal BITCNT : std_logic_vector(2 downto 0);
begin
P_SAMPLE: process
-- This filter provides a synchronisation to the system
-- clock, even for random baud rates of the received data
-- stream.
variable FLT_TMP : integer range 0 to 2;
begin
wait until CLK = '1' and CLK' event;
--
RXDATA_I <= RXDATA;
--
if RXDATA_I = '1' and FLT_TMP < 2 then
FLT_TMP := FLT_TMP + 1;
elsif RXDATA_I = '1' then
RXDATA_S <= '1';
elsif RXDATA_I = '0' and FLT_TMP > 0 then
FLT_TMP := FLT_TMP - 1;
elsif RXDATA_I = '0' then
RXDATA_S <= '0';
end if;
end process P_SAMPLE;
CLKDIV: process
variable CLK_LOCK : boolean;
variable STRB_LOCK : boolean;
variable CLK_DIVCNT : std_logic_vector(6 downto 0);
begin
wait until CLK = '1' and CLK' event;
if CDS = "00" then -- Divider off.
if RXCLK = '1' and STRB_LOCK = false then
CLK_STRB <= '1';
STRB_LOCK := true;
elsif RXCLK = '0' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
elsif RCV_STATE = IDLE then
-- Preset the CLKDIV with the start delays.
if CDS = "01" then
CLK_DIVCNT := "0001000"; -- Half of div by 16 mode.
elsif CDS = "10" then
CLK_DIVCNT := "0100000"; -- Half of div by 64 mode.
end if;
CLK_STRB <= '0';
else
if CLK_DIVCNT > "0000000" and RXCLK = '1' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_STRB <= '0';
CLK_LOCK := true;
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
--
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif RXCLK = '0' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
end if;
end if;
end process CLKDIV;
DATAREG: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= x"00";
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
DATA_REG <= x"00";
elsif RCV_STATE = SYNC and WS(2) = '0' and RDRF = '0' then -- 7 bit data.
-- Transfer from shift- to data register only if
-- data register is empty (RDRF = '0').
DATA_REG <= '0' & SHIFT_REG(7 downto 1);
elsif RCV_STATE = SYNC and WS(2) = '1' and RDRF = '0' then -- 8 bit data.
-- Transfer from shift- to data register only if
-- data register is empty (RDRF = '0').
DATA_REG <= SHIFT_REG;
end if;
end if;
end process DATAREG;
DATA_OUT <= DATA_REG when CS = "011" and RWn = '1' and RS = '1' and E = '1' else (others => '0');
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '1' and E = '1' else '0';
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
SHIFT_REG <= x"00";
elsif RCV_STATE = SAMPLE and CLK_STRB = '1' then
SHIFT_REG <= RXDATA_S & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end process SHIFTREG;
P_BITCNT: process
begin
wait until CLK = '1' and CLK' event;
if RCV_STATE = SAMPLE and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif RCV_STATE /= SAMPLE then
BITCNT <= (others => '0');
end if;
end process P_BITCNT;
FRAME_ERR: process(RESETn, CLK)
-- This module detects a framing error
-- during stop bit 1 and stop bit 2.
variable FE_I: bit;
begin
if RESETn = '0' then
FE_I := '0';
FE <= '0';
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
FE_I := '0';
FE <= '0';
elsif CLK_STRB = '1' then
if RCV_STATE = STOP1 and RXDATA_S = '0' then
FE_I := '1';
elsif RCV_STATE = STOP2 and RXDATA_S = '0' then
FE_I := '1';
elsif RCV_STATE = STOP1 or RCV_STATE = STOP2 then
FE_I := '0'; -- Error resets when correct data appears.
end if;
end if;
if RCV_STATE = SYNC then
FE <= FE_I; -- Update the FE every SYNC time.
end if;
end if;
end process FRAME_ERR;
OVERRUN: process(RESETn, CLK)
variable OVR_I : bit;
variable FIRST_READ : boolean;
begin
if RESETn = '0' then
OVR_I := '0';
OVR <= '0';
FIRST_READ := false;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
OVR_I := '0';
OVR <= '0';
FIRST_READ := false;
elsif CLK_STRB = '1' and RCV_STATE = STOP1 then
-- Overrun appears if RDRF is '1' in this state.
OVR_I := RDRF;
end if;
if CS = "011" and RWn = '1' and RS = '1' and E = '1' and OVR_I = '1' then
-- If an overrun was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the RDRF flag is reset
-- and the overrun disappears (OVR_I goes low) after
-- a second read (in time) of the receiver data register.
if FIRST_READ = false then
OVR <= '1';
FIRST_READ := true;
else
OVR <= '0';
FIRST_READ := false;
end if;
end if;
end if;
end process OVERRUN;
PARITY_TEST: process(RESETn, CLK)
variable PAR_TMP : bit;
variable PE_I : bit;
begin
if RESETn = '0' then
PE <= '0';
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
PE <= '0';
elsif CLK_STRB = '1' then -- Sample parity on clock strobe.
PE_I := '0'; -- Initialise.
if RCV_STATE = PARITY then
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if WS = "000" or WS = "010" or WS = "110" then -- Even parity.
PE_I := PAR_TMP xor RXDATA_S;
elsif WS = "001" or WS = "011" or WS = "111" then -- Odd parity.
PE_I := not PAR_TMP xor RXDATA_S;
else -- No parity for WS = "100" and WS = "101".
PE_I := '0';
end if;
end if;
end if;
-- Transmit the parity flag together with the data
-- In other words: no parity to the status register
-- when RDRF inhibits the data transfer to the
-- receiver data register.
if RCV_STATE = SYNC and RDRF = '0' then
PE <= PE_I;
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' then
PE <= '0'; -- Clear when reading the data register.
end if;
end if;
end process PARITY_TEST;
P_RDRF: process(RESETn, CLK)
-- Receive data register full flag.
begin
if RESETn = '0' then
RDRF <= '0';
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
RDRF <= '0';
elsif RCV_STATE = SYNC then
RDRF <= '1'; -- Data register is full until now!
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' then
RDRF <= '0'; -- After reading the data register ...
end if;
end if;
end process P_RDRF;
RCV_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
RCV_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
RCV_STATE <= IDLE;
else
RCV_STATE <= RCV_NEXT_STATE;
end if;
end if;
end process RCV_STATEREG;
RCV_STATEDEC: process(RCV_STATE, RXDATA_S, CDS, WS, BITCNT, CLK_STRB)
begin
case RCV_STATE is
when IDLE =>
if RXDATA_S = '0' and CDS = "00" then
RCV_NEXT_STATE <= SAMPLE; -- Startbit detected in div by 1 mode.
elsif RXDATA_S = '0' and CDS = "01" then
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 16 mode.
elsif RXDATA_S = '0' and CDS = "10" then
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 64 mode.
else
RCV_NEXT_STATE <= IDLE; -- No startbit; sleep well :-)
end if;
when WAIT_START =>
if CLK_STRB = '1' then
if RXDATA_S = '0' then
RCV_NEXT_STATE <= SAMPLE; -- Start condition in no div by 1 modes.
else
RCV_NEXT_STATE <= IDLE; -- No valid start condition, go back.
end if;
else
RCV_NEXT_STATE <= WAIT_START; -- Stay.
end if;
when SAMPLE =>
if CLK_STRB = '1' then
if BITCNT < "110" and WS(2) = '0' then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 7 data bits.
elsif BITCNT < "111" and WS(2) = '1' then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 8 data bits.
elsif WS = "100" or WS = "101" then
RCV_NEXT_STATE <= STOP1; -- No parity check enabled.
else
RCV_NEXT_STATE <= PARITY; -- Parity enabled.
end if;
else
RCV_NEXT_STATE <= SAMPLE; -- Stay in sample mode.
end if;
when PARITY =>
if CLK_STRB = '1' then
RCV_NEXT_STATE <= STOP1;
else
RCV_NEXT_STATE <= PARITY;
end if;
when STOP1 =>
if CLK_STRB = '1' then
if RXDATA_S = '0' then
RCV_NEXT_STATE <= SYNC; -- Framing error detected.
elsif WS = "000" or WS = "001" or WS = "100" then
RCV_NEXT_STATE <= STOP2; -- Two stop bits selected.
else
RCV_NEXT_STATE <= SYNC; -- One stop bit selected.
end if;
else
RCV_NEXT_STATE <= STOP1;
end if;
when STOP2 =>
if CLK_STRB = '1' then
RCV_NEXT_STATE <= SYNC;
else
RCV_NEXT_STATE <= STOP2;
end if;
when SYNC =>
RCV_NEXT_STATE <= IDLE;
end case;
end process RCV_STATEDEC;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,415 @@
----------------------------------------------------------------------
---- ----
---- 6850 compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- UART 6850 compatible IP core ----
---- ----
---- 6850's receiver unit. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_RECEIVE is
port (
CLK : in bit;
RESETn : in bit;
MCLR : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
WS : in bit_vector(2 downto 0);
CDS : in bit_vector(1 downto 0);
RXCLK : in bit;
RXDATA : in bit;
RDRF : buffer bit;
OVR : out bit;
PE : out bit;
FE : out bit
);
end entity WF6850IP_RECEIVE;
architecture BEHAVIOR of WF6850IP_RECEIVE is
type RCV_STATES is (IDLE, WAIT_START, SAMPLE, PARITY, STOP1, STOP2, SYNC);
signal RCV_STATE, RCV_NEXT_STATE : RCV_STATES;
signal RXDATA_I : bit;
signal RXDATA_S : bit;
signal DATA_REG : bit_vector(7 downto 0);
signal SHIFT_REG : bit_vector(7 downto 0);
signal CLK_STRB : bit;
signal BITCNT : std_logic_vector(2 downto 0);
begin
P_SAMPLE: process
-- This filter provides a synchronisation to the system
-- clock, even for random baud rates of the received data
-- stream.
variable FLT_TMP : integer range 0 to 2;
begin
wait until CLK = '1' and CLK' event;
--
RXDATA_I <= RXDATA;
--
if RXDATA_I = '1' and FLT_TMP < 2 then
FLT_TMP := FLT_TMP + 1;
elsif RXDATA_I = '1' then
RXDATA_S <= '1';
elsif RXDATA_I = '0' and FLT_TMP > 0 then
FLT_TMP := FLT_TMP - 1;
elsif RXDATA_I = '0' then
RXDATA_S <= '0';
end if;
end process P_SAMPLE;
CLKDIV: process
variable CLK_LOCK : boolean;
variable STRB_LOCK : boolean;
variable CLK_DIVCNT : std_logic_vector(6 downto 0);
begin
wait until CLK = '1' and CLK' event;
if CDS = "00" then -- Divider off.
if RXCLK = '1' and STRB_LOCK = false then
CLK_STRB <= '1';
STRB_LOCK := true;
elsif RXCLK = '0' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
elsif RCV_STATE = IDLE then
-- Preset the CLKDIV with the start delays.
if CDS = "01" then
CLK_DIVCNT := "0001000"; -- Half of div by 16 mode.
elsif CDS = "10" then
CLK_DIVCNT := "0100000"; -- Half of div by 64 mode.
end if;
CLK_STRB <= '0';
else
if CLK_DIVCNT > "0000000" and RXCLK = '1' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_STRB <= '0';
CLK_LOCK := true;
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
--
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif RXCLK = '0' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
end if;
end if;
end process CLKDIV;
DATAREG: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= x"00";
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
DATA_REG <= x"00";
elsif RCV_STATE = SYNC and WS(2) = '0' and RDRF = '0' then -- 7 bit data.
-- Transfer from shift- to data register only if
-- data register is empty (RDRF = '0').
DATA_REG <= '0' & SHIFT_REG(7 downto 1);
elsif RCV_STATE = SYNC and WS(2) = '1' and RDRF = '0' then -- 8 bit data.
-- Transfer from shift- to data register only if
-- data register is empty (RDRF = '0').
DATA_REG <= SHIFT_REG;
end if;
end if;
end process DATAREG;
--DATA_OUT <= DATA_REG when CS = "011" and RWn = '1' and RS = '1' and E = '1' else (others => '0');
--DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '1' and E = '1' else '0';
DATA_OUT <= DATA_REG when CS = "011" and RWn = '1' and RS = '1' else (others => '0');
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '1' else '0';
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
SHIFT_REG <= x"00";
elsif RCV_STATE = SAMPLE and CLK_STRB = '1' then
SHIFT_REG <= RXDATA_S & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end process SHIFTREG;
P_BITCNT: process
begin
wait until CLK = '1' and CLK' event;
if RCV_STATE = SAMPLE and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif RCV_STATE /= SAMPLE then
BITCNT <= (others => '0');
end if;
end process P_BITCNT;
FRAME_ERR: process(RESETn, CLK)
-- This module detects a framing error
-- during stop bit 1 and stop bit 2.
variable FE_I: bit;
begin
if RESETn = '0' then
FE_I := '0';
FE <= '0';
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
FE_I := '0';
FE <= '0';
elsif CLK_STRB = '1' then
if RCV_STATE = STOP1 and RXDATA_S = '0' then
FE_I := '1';
elsif RCV_STATE = STOP2 and RXDATA_S = '0' then
FE_I := '1';
elsif RCV_STATE = STOP1 or RCV_STATE = STOP2 then
FE_I := '0'; -- Error resets when correct data appears.
end if;
end if;
if RCV_STATE = SYNC then
FE <= FE_I; -- Update the FE every SYNC time.
end if;
end if;
end process FRAME_ERR;
OVERRUN: process(RESETn, CLK)
variable OVR_I : bit;
variable FIRST_READ : boolean;
begin
if RESETn = '0' then
OVR_I := '0';
OVR <= '0';
FIRST_READ := false;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
OVR_I := '0';
OVR <= '0';
FIRST_READ := false;
elsif CLK_STRB = '1' and RCV_STATE = STOP1 then
-- Overrun appears if RDRF is '1' in this state.
OVR_I := RDRF;
end if;
if CS = "011" and RWn = '1' and RS = '1' and E = '1' and OVR_I = '1' then
-- If an overrun was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the RDRF flag is reset
-- and the overrun disappears (OVR_I goes low) after
-- a second read (in time) of the receiver data register.
if FIRST_READ = false then
OVR <= '1';
FIRST_READ := true;
else
OVR <= '0';
FIRST_READ := false;
end if;
end if;
end if;
end process OVERRUN;
PARITY_TEST: process(RESETn, CLK)
variable PAR_TMP : bit;
variable PE_I : bit;
begin
if RESETn = '0' then
PE <= '0';
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
PE <= '0';
elsif CLK_STRB = '1' then -- Sample parity on clock strobe.
PE_I := '0'; -- Initialise.
if RCV_STATE = PARITY then
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if WS = "000" or WS = "010" or WS = "110" then -- Even parity.
PE_I := PAR_TMP xor RXDATA_S;
elsif WS = "001" or WS = "011" or WS = "111" then -- Odd parity.
PE_I := not PAR_TMP xor RXDATA_S;
else -- No parity for WS = "100" and WS = "101".
PE_I := '0';
end if;
end if;
end if;
-- Transmit the parity flag together with the data
-- In other words: no parity to the status register
-- when RDRF inhibits the data transfer to the
-- receiver data register.
if RCV_STATE = SYNC and RDRF = '0' then
PE <= PE_I;
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' then
PE <= '0'; -- Clear when reading the data register.
end if;
end if;
end process PARITY_TEST;
P_RDRF: process(RESETn, CLK)
-- Receive data register full flag.
begin
if RESETn = '0' then
RDRF <= '0';
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
RDRF <= '0';
elsif RCV_STATE = SYNC then
RDRF <= '1'; -- Data register is full until now!
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' then
RDRF <= '0'; -- After reading the data register ...
end if;
end if;
end process P_RDRF;
RCV_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
RCV_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
RCV_STATE <= IDLE;
else
RCV_STATE <= RCV_NEXT_STATE;
end if;
end if;
end process RCV_STATEREG;
RCV_STATEDEC: process(RCV_STATE, RXDATA_S, CDS, WS, BITCNT, CLK_STRB)
begin
case RCV_STATE is
when IDLE =>
if RXDATA_S = '0' and CDS = "00" then
RCV_NEXT_STATE <= SAMPLE; -- Startbit detected in div by 1 mode.
elsif RXDATA_S = '0' and CDS = "01" then
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 16 mode.
elsif RXDATA_S = '0' and CDS = "10" then
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 64 mode.
else
RCV_NEXT_STATE <= IDLE; -- No startbit; sleep well :-)
end if;
when WAIT_START =>
if CLK_STRB = '1' then
if RXDATA_S = '0' then
RCV_NEXT_STATE <= SAMPLE; -- Start condition in no div by 1 modes.
else
RCV_NEXT_STATE <= IDLE; -- No valid start condition, go back.
end if;
else
RCV_NEXT_STATE <= WAIT_START; -- Stay.
end if;
when SAMPLE =>
if CLK_STRB = '1' then
if BITCNT < "110" and WS(2) = '0' then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 7 data bits.
elsif BITCNT < "111" and WS(2) = '1' then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 8 data bits.
elsif WS = "100" or WS = "101" then
RCV_NEXT_STATE <= STOP1; -- No parity check enabled.
else
RCV_NEXT_STATE <= PARITY; -- Parity enabled.
end if;
else
RCV_NEXT_STATE <= SAMPLE; -- Stay in sample mode.
end if;
when PARITY =>
if CLK_STRB = '1' then
RCV_NEXT_STATE <= STOP1;
else
RCV_NEXT_STATE <= PARITY;
end if;
when STOP1 =>
if CLK_STRB = '1' then
if RXDATA_S = '0' then
RCV_NEXT_STATE <= SYNC; -- Framing error detected.
elsif WS = "000" or WS = "001" or WS = "100" then
RCV_NEXT_STATE <= STOP2; -- Two stop bits selected.
else
RCV_NEXT_STATE <= SYNC; -- One stop bit selected.
end if;
else
RCV_NEXT_STATE <= STOP1;
end if;
when STOP2 =>
if CLK_STRB = '1' then
RCV_NEXT_STATE <= SYNC;
else
RCV_NEXT_STATE <= STOP2;
end if;
when SYNC =>
RCV_NEXT_STATE <= IDLE;
end case;
end process RCV_STATEDEC;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,135 @@
----------------------------------------------------------------------
---- ----
---- 6850 compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- UART 6850 compatible IP core ----
---- ----
---- This is the top level file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8B 2008/12/24 WF
-- Rewritten this top level file as a wrapper for the top_soc file.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_TOP is
port (
CLK : in bit;
RESETn : in bit;
CS2n, CS1, CS0 : in bit;
E : in bit;
RWn : in bit;
RS : in bit;
DATA : inout std_logic_vector(7 downto 0);
TXCLK : in bit;
RXCLK : in bit;
RXDATA : in bit;
CTSn : in bit;
DCDn : in bit;
IRQn : out std_logic;
TXDATA : out bit;
RTSn : out bit
);
end entity WF6850IP_TOP;
architecture STRUCTURE of WF6850IP_TOP is
component WF6850IP_TOP_SOC
port (
CLK : in bit;
RESETn : in bit;
CS2n, CS1, CS0 : in bit;
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
TXCLK : in bit;
RXCLK : in bit;
RXDATA : in bit;
CTSn : in bit;
DCDn : in bit;
IRQn : out bit;
TXDATA : out bit;
RTSn : out bit
);
end component;
signal DATA_OUT : std_logic_vector(7 downto 0);
signal DATA_EN : bit;
signal IRQ_In : bit;
begin
DATA <= DATA_OUT when DATA_EN = '1' else (others => 'Z');
IRQn <= '0' when IRQ_In = '0' else 'Z'; -- Open drain.
I_UART: WF6850IP_TOP_SOC
port map(CLK => CLK,
RESETn => RESETn,
CS2n => CS2n,
CS1 => CS1,
CS0 => CS0,
E => E,
RWn => RWn,
RS => RS,
DATA_IN => DATA,
DATA_OUT => DATA_OUT,
DATA_EN => DATA_EN,
TXCLK => TXCLK,
RXCLK => RXCLK,
RXDATA => RXDATA,
CTSn => CTSn,
DCDn => DCDn,
IRQn => IRQ_In,
TXDATA => TXDATA,
RTSn => RTSn
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,255 @@
----------------------------------------------------------------------
---- ----
---- 6850 compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- UART 6850 compatible IP core ----
---- ----
---- This is the top level file. ----
---- Top level file for use in systems on programmable chips. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Top level file provided for SOC (systems on programmable chips).
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9B 2009/12/24 WF
-- Fixed the interrupt logic.
-- Introduced a minor RTSn correction.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_TOP_SOC is
port (
CLK : in bit;
RESETn : in bit;
CS2n, CS1, CS0 : in bit;
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
TXCLK : in bit;
RXCLK : in bit;
RXDATA : in bit;
CTSn : in bit;
DCDn : in bit;
IRQn : out bit;
TXDATA : out bit;
RTSn : out bit
);
end entity WF6850IP_TOP_SOC;
architecture STRUCTURE of WF6850IP_TOP_SOC is
component WF6850IP_CTRL_STATUS
port (
CLK : in bit;
RESETn : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
RDRF : in bit;
TDRE : in bit;
DCDn : in bit;
CTSn : in bit;
FE : in bit;
OVR : in bit;
PE : in bit;
MCLR : out bit;
RTSn : out bit;
CDS : out bit_vector(1 downto 0);
WS : out bit_vector(2 downto 0);
TC : out bit_vector(1 downto 0);
IRQn : out bit
);
end component;
component WF6850IP_RECEIVE
port (
CLK : in bit;
RESETn : in bit;
MCLR : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
WS : in bit_vector(2 downto 0);
CDS : in bit_vector(1 downto 0);
RXCLK : in bit;
RXDATA : in bit;
RDRF : out bit;
OVR : out bit;
PE : out bit;
FE : out bit
);
end component;
component WF6850IP_TRANSMIT
port (
CLK : in bit;
RESETn : in bit;
MCLR : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in bit_vector(7 downto 0);
CTSn : in bit;
TC : in bit_vector(1 downto 0);
WS : in bit_vector(2 downto 0);
CDS : in bit_vector(1 downto 0);
TXCLK : in bit;
TDRE : out bit;
TXDATA : out bit
);
end component;
signal DATA_IN_I : bit_vector(7 downto 0);
signal DATA_RX : bit_vector(7 downto 0);
signal DATA_RX_EN : bit;
signal DATA_CTRL : bit_vector(7 downto 0);
signal DATA_CTRL_EN : bit;
signal RDRF_I : bit;
signal TDRE_I : bit;
signal FE_I : bit;
signal OVR_I : bit;
signal PE_I : bit;
signal MCLR_I : bit;
signal CDS_I : bit_vector(1 downto 0);
signal WS_I : bit_vector(2 downto 0);
signal TC_I : bit_vector(1 downto 0);
signal IRQ_In : bit;
begin
DATA_IN_I <= To_BitVector(DATA_IN);
DATA_EN <= DATA_RX_EN or DATA_CTRL_EN;
DATA_OUT <= To_StdLogicVector(DATA_RX) when DATA_RX_EN = '1' else
To_StdLogicVector(DATA_CTRL) when DATA_CTRL_EN = '1' else (others => '0');
IRQn <= '0' when IRQ_In = '0' else '1';
I_UART_CTRL_STATUS: WF6850IP_CTRL_STATUS
port map(
CLK => CLK,
RESETn => RESETn,
CS(2) => CS2n,
CS(1) => CS1,
CS(0) => CS0,
E => E,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
DATA_OUT => DATA_CTRL,
DATA_EN => DATA_CTRL_EN,
RDRF => RDRF_I,
TDRE => TDRE_I,
DCDn => DCDn,
CTSn => CTSn,
FE => FE_I,
OVR => OVR_I,
PE => PE_I,
MCLR => MCLR_I,
RTSn => RTSn,
CDS => CDS_I,
WS => WS_I,
TC => TC_I,
IRQn => IRQ_In
);
I_UART_RECEIVE: WF6850IP_RECEIVE
port map (
CLK => CLK,
RESETn => RESETn,
MCLR => MCLR_I,
CS(2) => CS2n,
CS(1) => CS1,
CS(0) => CS0,
E => E,
RWn => RWn,
RS => RS,
DATA_OUT => DATA_RX,
DATA_EN => DATA_RX_EN,
WS => WS_I,
CDS => CDS_I,
RXCLK => RXCLK,
RXDATA => RXDATA,
RDRF => RDRF_I,
OVR => OVR_I,
PE => PE_I,
FE => FE_I
);
I_UART_TRANSMIT: WF6850IP_TRANSMIT
port map (
CLK => CLK,
RESETn => RESETn,
MCLR => MCLR_I,
CS(2) => CS2n,
CS(1) => CS1,
CS(0) => CS0,
E => E,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
CTSn => CTSn,
TC => TC_I,
WS => WS_I,
CDS => CDS_I,
TDRE => TDRE_I,
TXCLK => TXCLK,
TXDATA => TXDATA
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,252 @@
----------------------------------------------------------------------
---- ----
---- 6850 compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- UART 6850 compatible IP core ----
---- ----
---- This is the top level file. ----
---- Top level file for use in systems on programmable chips. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Top level file provided for SOC (systems on programmable chips).
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_TOP_SOC is
port (
CLK : in bit;
RESETn : in bit;
CS2n, CS1, CS0 : in bit;
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
TXCLK : in bit;
RXCLK : in bit;
RXDATA : in bit;
CTSn : in bit;
DCDn : in bit;
IRQn : out bit;
TXDATA : out bit;
RTSn : out bit
);
end entity WF6850IP_TOP_SOC;
architecture STRUCTURE of WF6850IP_TOP_SOC is
component WF6850IP_CTRL_STATUS
port (
CLK : in bit;
RESETn : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
RDRF : in bit;
TDRE : in bit;
DCDn : in bit;
CTSn : in bit;
FE : in bit;
OVR : in bit;
PE : in bit;
MCLR : out bit;
RTSn : out bit;
CDS : out bit_vector(1 downto 0);
WS : out bit_vector(2 downto 0);
TC : out bit_vector(1 downto 0);
IRQn : out bit
);
end component;
component WF6850IP_RECEIVE
port (
CLK : in bit;
RESETn : in bit;
MCLR : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
WS : in bit_vector(2 downto 0);
CDS : in bit_vector(1 downto 0);
RXCLK : in bit;
RXDATA : in bit;
RDRF : out bit;
OVR : out bit;
PE : out bit;
FE : out bit
);
end component;
component WF6850IP_TRANSMIT
port (
CLK : in bit;
RESETn : in bit;
MCLR : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in bit_vector(7 downto 0);
CTSn : in bit;
TC : in bit_vector(1 downto 0);
WS : in bit_vector(2 downto 0);
CDS : in bit_vector(1 downto 0);
TXCLK : in bit;
TDRE : out bit;
TXDATA : out bit
);
end component;
signal DATA_IN_I : bit_vector(7 downto 0);
signal DATA_RX : bit_vector(7 downto 0);
signal DATA_RX_EN : bit;
signal DATA_CTRL : bit_vector(7 downto 0);
signal DATA_CTRL_EN : bit;
signal RDRF_I : bit;
signal TDRE_I : bit;
signal FE_I : bit;
signal OVR_I : bit;
signal PE_I : bit;
signal MCLR_I : bit;
signal CDS_I : bit_vector(1 downto 0);
signal WS_I : bit_vector(2 downto 0);
signal TC_I : bit_vector(1 downto 0);
signal IRQ_In : bit;
begin
DATA_IN_I <= To_BitVector(DATA_IN);
DATA_EN <= DATA_RX_EN or DATA_CTRL_EN;
DATA_OUT <= To_StdLogicVector(DATA_RX) when DATA_RX_EN = '1' else
To_StdLogicVector(DATA_CTRL) when DATA_CTRL_EN = '1' else (others => '0');
IRQn <= '0' when IRQ_In = '0' else '1';
I_UART_CTRL_STATUS: WF6850IP_CTRL_STATUS
port map(
CLK => CLK,
RESETn => RESETn,
CS(2) => CS2n,
CS(1) => CS1,
CS(0) => CS0,
E => E,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
DATA_OUT => DATA_CTRL,
DATA_EN => DATA_CTRL_EN,
RDRF => RDRF_I,
TDRE => TDRE_I,
DCDn => DCDn,
CTSn => CTSn,
FE => FE_I,
OVR => OVR_I,
PE => PE_I,
MCLR => MCLR_I,
RTSn => RTSn,
CDS => CDS_I,
WS => WS_I,
TC => TC_I,
IRQn => IRQ_In
);
I_UART_RECEIVE: WF6850IP_RECEIVE
port map (
CLK => CLK,
RESETn => RESETn,
MCLR => MCLR_I,
CS(2) => CS2n,
CS(1) => CS1,
CS(0) => CS0,
E => E,
RWn => RWn,
RS => RS,
DATA_OUT => DATA_RX,
DATA_EN => DATA_RX_EN,
WS => WS_I,
CDS => CDS_I,
RXCLK => RXCLK,
RXDATA => RXDATA,
RDRF => RDRF_I,
OVR => OVR_I,
PE => PE_I,
FE => FE_I
);
I_UART_TRANSMIT: WF6850IP_TRANSMIT
port map (
CLK => CLK,
RESETn => RESETn,
MCLR => MCLR_I,
CS(2) => CS2n,
CS(1) => CS1,
CS(0) => CS0,
E => E,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
CTSn => CTSn,
TC => TC_I,
WS => WS_I,
CDS => CDS_I,
TDRE => TDRE_I,
TXCLK => TXCLK,
TXDATA => TXDATA
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,339 @@
----------------------------------------------------------------------
---- ----
---- 6850 compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- UART 6850 compatible IP core ----
---- ----
---- 6850's transmitter unit. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K8B 2008/11/01 WF
-- Fixed the T_DRE process concerning the TDRE <= '1' setting.
-- Thanks to Lyndon Amsdon finding the bug.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_TRANSMIT is
port (
CLK : in bit;
RESETn : in bit;
MCLR : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in bit_vector(7 downto 0);
CTSn : in bit;
TC : in bit_vector(1 downto 0);
WS : in bit_vector(2 downto 0);
CDS : in bit_vector(1 downto 0);
TXCLK : in bit;
TDRE : buffer bit;
TXDATA : out bit
);
end entity WF6850IP_TRANSMIT;
architecture BEHAVIOR of WF6850IP_TRANSMIT is
type TR_STATES is (IDLE, LOAD_SHFT, START, SHIFTOUT, PARITY, STOP1, STOP2);
signal TR_STATE, TR_NEXT_STATE : TR_STATES;
signal CLK_STRB : bit;
signal DATA_REG : bit_vector(7 downto 0);
signal SHIFT_REG : bit_vector(7 downto 0);
signal BITCNT : std_logic_vector(2 downto 0);
signal PARITY_I : bit;
begin
-- The default condition in this statement is to ensure
-- to cover all possibilities for example if there is a
-- one hot decoding of the state machine with wrong states
-- (e.g. not one of the given here).
TXDATA <= '1' when TR_STATE = IDLE else
'1' when TR_STATE = LOAD_SHFT else
'0' when TR_STATE = START else
SHIFT_REG(0) when TR_STATE = SHIFTOUT else
PARITY_I when TR_STATE = PARITY else
'1' when TR_STATE = STOP1 else
'1' when TR_STATE = STOP2 else '1';
CLKDIV: process
variable CLK_LOCK : boolean;
variable STRB_LOCK : boolean;
variable CLK_DIVCNT : std_logic_vector(6 downto 0);
begin
wait until CLK = '1' and CLK' event;
if CDS = "00" then -- divider off
if TXCLK = '0' and STRB_LOCK = false then -- Works on negative TXCLK edge.
CLK_STRB <= '1';
STRB_LOCK := true;
elsif TXCLK = '1' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
elsif TR_STATE = IDLE then
-- preset the CLKDIV with the start delays
if CDS = "01" then
CLK_DIVCNT := "0010000"; -- div by 16 mode
elsif CDS = "10" then
CLK_DIVCNT := "1000000"; -- div by 64 mode
end if;
CLK_STRB <= '0';
else
-- Works on negative TXCLK edge:
if CLK_DIVCNT > "0000000" and TXCLK = '0' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_STRB <= '0';
CLK_LOCK := true;
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif TXCLK = '1' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
end if;
end if;
end process CLKDIV;
DATAREG: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= x"00";
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
DATA_REG <= x"00";
elsif WS(2) = '0' and CS = "011" and RWn = '0' and RS = '1' and E = '1' then
DATA_REG <= '0' & DATA_IN(6 downto 0); -- 7 bit data mode.
elsif WS(2) = '1' and CS = "011" and RWn = '0' and RS = '1' and E = '1' then
DATA_REG <= DATA_IN; -- 8 bit data mode.
end if;
end if;
end process DATAREG;
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
SHIFT_REG <= x"00";
elsif TR_STATE = LOAD_SHFT and TDRE = '0' then
-- If during LOAD_SHIFT the transmitter data register
-- is empty (TDRE = '1') the shift register will not
-- be loaded. When additionally TC = "11", the break
-- character (zero data and no stop bits) is sent.
SHIFT_REG <= DATA_REG;
elsif TR_STATE = SHIFTOUT and CLK_STRB = '1' then
SHIFT_REG <= '0' & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end process SHIFTREG;
P_BITCNT: process
-- Counter for the data bits transmitted.
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif TR_STATE /= SHIFTOUT then
BITCNT <= "000";
end if;
end process P_BITCNT;
P_TDRE: process(RESETn, CLK)
-- Transmit data register empty flag.
variable LOCK : boolean;
begin
if RESETn = '0' then
TDRE <= '1';
LOCK := false;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
TDRE <= '1';
elsif TR_NEXT_STATE = START and TR_STATE /= START then
-- Data has been loaded to shift register, thus data register is free again.
-- Thanks to Lyndon Amsdon for finding a bug here. The TDRE is set to one once
-- entering the state now.
TDRE <= '1';
elsif CS = "011" and RWn = '0' and RS = '1' and E = '1' and LOCK = false then
LOCK := true;
elsif E = '0' and LOCK = true then
-- This construction clears TDRE after the falling edge of E
-- and after the transmit data register has been written to.
TDRE <= '0';
LOCK := false;
end if;
end if;
end process P_TDRE;
PARITY_GEN: process
variable PAR_TMP : bit;
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = START then -- Calculate the parity during the start phase.
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if WS = "000" or WS = "010" or WS = "110" then -- Even parity.
PARITY_I <= PAR_TMP;
elsif WS = "001" or WS = "011" or WS = "111" then -- Odd parity.
PARITY_I <= not PAR_TMP;
else -- No parity for WS = "100" and WS = "101".
PARITY_I <= '0';
end if;
end if;
end process PARITY_GEN;
TR_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
TR_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
TR_STATE <= IDLE;
else
TR_STATE <= TR_NEXT_STATE;
end if;
end if;
end process TR_STATEREG;
TR_STATEDEC: process(TR_STATE, CLK_STRB, TC, BITCNT, WS, TDRE, CTSn)
begin
case TR_STATE is
when IDLE =>
if TDRE = '1' and TC = "11" then
TR_NEXT_STATE <= LOAD_SHFT;
elsif TDRE = '0' and CTSn = '0' then -- Start if data register is not empty.
TR_NEXT_STATE <= LOAD_SHFT;
else
TR_NEXT_STATE <= IDLE;
end if;
when LOAD_SHFT =>
TR_NEXT_STATE <= START;
when START =>
if CLK_STRB = '1' then
TR_NEXT_STATE <= SHIFTOUT;
else
TR_NEXT_STATE <= START;
end if;
when SHIFTOUT =>
if CLK_STRB = '1' then
if BITCNT < "110" and WS(2) = '0' then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 7 data bits.
elsif BITCNT < "111" and WS(2) = '1' then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 8 data bits.
elsif WS = "100" or WS = "101" then
if TDRE = '1' and TC = "11" then
-- Break condition, do not send a stop bit.
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP1; -- No parity check enabled.
end if;
else
TR_NEXT_STATE <= PARITY; -- Parity enabled.
end if;
else
TR_NEXT_STATE <= SHIFTOUT;
end if;
when PARITY =>
if CLK_STRB = '1' then
if TDRE = '1' and TC = "11" then
-- Break condition, do not send a stop bit.
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP1; -- No parity check enabled.
end if;
else
TR_NEXT_STATE <= PARITY;
end if;
when STOP1 =>
if CLK_STRB = '1' and (WS = "000" or WS = "001" or WS = "100") then
TR_NEXT_STATE <= STOP2; -- Two stop bits selected.
elsif CLK_STRB = '1' then
TR_NEXT_STATE <= IDLE; -- One stop bits selected.
else
TR_NEXT_STATE <= STOP1;
end if;
when STOP2 =>
if CLK_STRB = '1' then
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP2;
end if;
end case;
end process TR_STATEDEC;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,339 @@
----------------------------------------------------------------------
---- ----
---- 6850 compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- UART 6850 compatible IP core ----
---- ----
---- 6850's transmitter unit. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K8B 2008/11/01 WF
-- Fixed the T_DRE process concerning the TDRE <= '1' setting.
-- Thanks to Lyndon Amsdon finding the bug.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_TRANSMIT is
port (
CLK : in bit;
RESETn : in bit;
MCLR : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_IN : in bit_vector(7 downto 0);
CTSn : in bit;
TC : in bit_vector(1 downto 0);
WS : in bit_vector(2 downto 0);
CDS : in bit_vector(1 downto 0);
TXCLK : in bit;
TDRE : buffer bit;
TXDATA : out bit
);
end entity WF6850IP_TRANSMIT;
architecture BEHAVIOR of WF6850IP_TRANSMIT is
type TR_STATES is (IDLE, LOAD_SHFT, START, SHIFTOUT, PARITY, STOP1, STOP2);
signal TR_STATE, TR_NEXT_STATE : TR_STATES;
signal CLK_STRB : bit;
signal DATA_REG : bit_vector(7 downto 0);
signal SHIFT_REG : bit_vector(7 downto 0);
signal BITCNT : std_logic_vector(2 downto 0);
signal PARITY_I : bit;
begin
-- The default condition in this statement is to ensure
-- to cover all possibilities for example if there is a
-- one hot decoding of the state machine with wrong states
-- (e.g. not one of the given here).
TXDATA <= '1' when TR_STATE = IDLE else
'1' when TR_STATE = LOAD_SHFT else
'0' when TR_STATE = START else
SHIFT_REG(0) when TR_STATE = SHIFTOUT else
PARITY_I when TR_STATE = PARITY else
'1' when TR_STATE = STOP1 else
'1' when TR_STATE = STOP2 else '1';
CLKDIV: process
variable CLK_LOCK : boolean;
variable STRB_LOCK : boolean;
variable CLK_DIVCNT : std_logic_vector(6 downto 0);
begin
wait until CLK = '1' and CLK' event;
if CDS = "00" then -- divider off
if TXCLK = '0' and STRB_LOCK = false then -- Works on negative TXCLK edge.
CLK_STRB <= '1';
STRB_LOCK := true;
elsif TXCLK = '1' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
elsif TR_STATE = IDLE then
-- preset the CLKDIV with the start delays
if CDS = "01" then
CLK_DIVCNT := "0010000"; -- div by 16 mode
elsif CDS = "10" then
CLK_DIVCNT := "1000000"; -- div by 64 mode
end if;
CLK_STRB <= '0';
else
-- Works on negative TXCLK edge:
if CLK_DIVCNT > "0000000" and TXCLK = '0' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_STRB <= '0';
CLK_LOCK := true;
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif TXCLK = '1' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
end if;
end if;
end process CLKDIV;
DATAREG: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= x"00";
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
DATA_REG <= x"00";
elsif WS(2) = '0' and CS = "011" and RWn = '0' and RS = '1' and E = '1' then
DATA_REG <= '0' & DATA_IN(6 downto 0); -- 7 bit data mode.
elsif WS(2) = '1' and CS = "011" and RWn = '0' and RS = '1' and E = '1' then
DATA_REG <= DATA_IN; -- 8 bit data mode.
end if;
end if;
end process DATAREG;
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
SHIFT_REG <= x"00";
elsif TR_STATE = LOAD_SHFT and TDRE = '0' then
-- If during LOAD_SHIFT the transmitter data register
-- is empty (TDRE = '1') the shift register will not
-- be loaded. When additionally TC = "11", the break
-- character (zero data and no stop bits) is sent.
SHIFT_REG <= DATA_REG;
elsif TR_STATE = SHIFTOUT and CLK_STRB = '1' then
SHIFT_REG <= '0' & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end process SHIFTREG;
P_BITCNT: process
-- Counter for the data bits transmitted.
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif TR_STATE /= SHIFTOUT then
BITCNT <= "000";
end if;
end process P_BITCNT;
P_TDRE: process(RESETn, CLK)
-- Transmit data register empty flag.
variable LOCK : boolean;
begin
if RESETn = '0' then
TDRE <= '1';
LOCK := false;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
TDRE <= '1';
elsif TR_NEXT_STATE = START and TR_STATE /= START then
-- Data has been loaded to shift register, thus data register is free again.
-- Thanks to Lyndon Amsdon for finding a bug here. The TDRE is set to one once
-- entering the state now.
TDRE <= '1';
elsif CS = "011" and RWn = '0' and RS = '1' and E = '1' and LOCK = false then
LOCK := true;
elsif E = '0' and LOCK = true and CS /= "011" then
-- This construction clears TDRE after the falling edge of E
-- and after the transmit data register has been written to.
TDRE <= '0';
LOCK := false;
end if;
end if;
end process P_TDRE;
PARITY_GEN: process
variable PAR_TMP : bit;
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = START then -- Calculate the parity during the start phase.
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if WS = "000" or WS = "010" or WS = "110" then -- Even parity.
PARITY_I <= PAR_TMP;
elsif WS = "001" or WS = "011" or WS = "111" then -- Odd parity.
PARITY_I <= not PAR_TMP;
else -- No parity for WS = "100" and WS = "101".
PARITY_I <= '0';
end if;
end if;
end process PARITY_GEN;
TR_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
TR_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
TR_STATE <= IDLE;
else
TR_STATE <= TR_NEXT_STATE;
end if;
end if;
end process TR_STATEREG;
TR_STATEDEC: process(TR_STATE, CLK_STRB, TC, BITCNT, WS, TDRE, CTSn)
begin
case TR_STATE is
when IDLE =>
if TDRE = '1' and TC = "11" then
TR_NEXT_STATE <= LOAD_SHFT;
elsif TDRE = '0' and CTSn = '0' then -- Start if data register is not empty.
TR_NEXT_STATE <= LOAD_SHFT;
else
TR_NEXT_STATE <= IDLE;
end if;
when LOAD_SHFT =>
TR_NEXT_STATE <= START;
when START =>
if CLK_STRB = '1' then
TR_NEXT_STATE <= SHIFTOUT;
else
TR_NEXT_STATE <= START;
end if;
when SHIFTOUT =>
if CLK_STRB = '1' then
if BITCNT < "110" and WS(2) = '0' then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 7 data bits.
elsif BITCNT < "111" and WS(2) = '1' then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 8 data bits.
elsif WS = "100" or WS = "101" then
if TDRE = '1' and TC = "11" then
-- Break condition, do not send a stop bit.
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP1; -- No parity check enabled.
end if;
else
TR_NEXT_STATE <= PARITY; -- Parity enabled.
end if;
else
TR_NEXT_STATE <= SHIFTOUT;
end if;
when PARITY =>
if CLK_STRB = '1' then
if TDRE = '1' and TC = "11" then
-- Break condition, do not send a stop bit.
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP1; -- No parity check enabled.
end if;
else
TR_NEXT_STATE <= PARITY;
end if;
when STOP1 =>
if CLK_STRB = '1' and (WS = "000" or WS = "001" or WS = "100") then
TR_NEXT_STATE <= STOP2; -- Two stop bits selected.
elsif CLK_STRB = '1' then
TR_NEXT_STATE <= IDLE; -- One stop bits selected.
else
TR_NEXT_STATE <= STOP1;
end if;
when STOP2 =>
if CLK_STRB = '1' then
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP2;
end if;
end case;
end process TR_STATEDEC;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,95 @@
/*
WARNING: Do NOT edit the input and output ports in this file in a text
editor if you plan to continue editing the block that represents it in
the Block Editor! File corruption is VERY likely to occur.
*/
/*
Copyright (C) 1991-2009 Altera Corporation
Your use of Altera Corporation's design tools, logic functions
and other software and tools, and its AMPP partner logic
functions, and any output files from any of the foregoing
(including device programming or simulation files), and any
associated documentation or information are expressly subject
to the terms and conditions of the Altera Program License
Subscription Agreement, Altera MegaCore Function License
Agreement, or other applicable license agreement, including,
without limitation, that your use is for the sole purpose of
programming logic devices manufactured by Altera and sold by
Altera or its authorized distributors. Please refer to the
applicable agreement for further details.
*/
(header "symbol" (version "1.1"))
(symbol
(rect 0 0 160 168)
(text "dcfifo0" (rect 62 1 105 17)(font "Arial" (font_size 10)))
(text "inst" (rect 8 152 25 164)(font "Arial" ))
(port
(pt 0 32)
(input)
(text "data[7..0]" (rect 0 0 53 14)(font "Arial" (font_size 8)))
(text "data[7..0]" (rect 20 26 65 39)(font "Arial" (font_size 8)))
(line (pt 0 32)(pt 16 32)(line_width 3))
)
(port
(pt 0 56)
(input)
(text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))
(text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))
(line (pt 0 56)(pt 16 56)(line_width 1))
)
(port
(pt 0 72)
(input)
(text "wrclk" (rect 0 0 31 14)(font "Arial" (font_size 8)))
(text "wrclk" (rect 26 66 48 79)(font "Arial" (font_size 8)))
(line (pt 0 72)(pt 16 72)(line_width 1))
)
(port
(pt 0 104)
(input)
(text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))
(text "rdreq" (rect 20 98 44 111)(font "Arial" (font_size 8)))
(line (pt 0 104)(pt 16 104)(line_width 1))
)
(port
(pt 0 120)
(input)
(text "rdclk" (rect 0 0 27 14)(font "Arial" (font_size 8)))
(text "rdclk" (rect 26 114 47 127)(font "Arial" (font_size 8)))
(line (pt 0 120)(pt 16 120)(line_width 1))
)
(port
(pt 0 144)
(input)
(text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))
(text "aclr" (rect 20 138 37 151)(font "Arial" (font_size 8)))
(line (pt 0 144)(pt 16 144)(line_width 1))
)
(port
(pt 160 72)
(output)
(text "wrusedw[9..0]" (rect 0 0 84 14)(font "Arial" (font_size 8)))
(text "wrusedw[9..0]" (rect 69 66 132 79)(font "Arial" (font_size 8)))
(line (pt 160 72)(pt 144 72)(line_width 3))
)
(port
(pt 160 96)
(output)
(text "q[31..0]" (rect 0 0 42 14)(font "Arial" (font_size 8)))
(text "q[31..0]" (rect 105 90 141 103)(font "Arial" (font_size 8)))
(line (pt 160 96)(pt 144 96)(line_width 3))
)
(drawing
(text "8 bits x 1024 words" (rect 63 140 144 152)(font "Arial" ))
(line (pt 16 16)(pt 144 16)(line_width 1))
(line (pt 144 16)(pt 144 152)(line_width 1))
(line (pt 144 152)(pt 16 152)(line_width 1))
(line (pt 16 152)(pt 16 16)(line_width 1))
(line (pt 16 84)(pt 144 84)(line_width 1))
(line (pt 16 132)(pt 144 132)(line_width 1))
(line (pt 16 66)(pt 22 72)(line_width 1))
(line (pt 22 72)(pt 16 78)(line_width 1))
(line (pt 16 114)(pt 22 120)(line_width 1))
(line (pt 22 120)(pt 16 126)(line_width 1))
)
)

View File

@@ -0,0 +1,28 @@
--Copyright (C) 1991-2009 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
component dcfifo0
PORT
(
aclr : IN STD_LOGIC := '0';
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
end component;

View File

@@ -0,0 +1,5 @@
set_global_assignment -name IP_TOOL_NAME "LPM_FIFO+"
set_global_assignment -name IP_TOOL_VERSION "9.1"
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "dcfifo0.vhd"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "dcfifo0.bsf"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "dcfifo0.cmp"]

View File

@@ -0,0 +1,202 @@
-- megafunction wizard: %LPM_FIFO+%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: dcfifo_mixed_widths
-- ============================================================
-- File Name: dcfifo0.vhd
-- Megafunction Name(s):
-- dcfifo_mixed_widths
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 9.1 Build 222 10/21/2009 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2009 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY dcfifo0 IS
PORT
(
aclr : IN STD_LOGIC := '0';
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
END dcfifo0;
ARCHITECTURE SYN OF dcfifo0 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (9 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (31 DOWNTO 0);
COMPONENT dcfifo_mixed_widths
GENERIC (
intended_device_family : STRING;
lpm_numwords : NATURAL;
lpm_showahead : STRING;
lpm_type : STRING;
lpm_width : NATURAL;
lpm_widthu : NATURAL;
lpm_widthu_r : NATURAL;
lpm_width_r : NATURAL;
overflow_checking : STRING;
rdsync_delaypipe : NATURAL;
underflow_checking : STRING;
use_eab : STRING;
write_aclr_synch : STRING;
wrsync_delaypipe : NATURAL
);
PORT (
wrclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0);
aclr : IN STD_LOGIC ;
rdclk : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
wrreq : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END COMPONENT;
BEGIN
wrusedw <= sub_wire0(9 DOWNTO 0);
q <= sub_wire1(31 DOWNTO 0);
dcfifo_mixed_widths_component : dcfifo_mixed_widths
GENERIC MAP (
intended_device_family => "Cyclone III",
lpm_numwords => 1024,
lpm_showahead => "OFF",
lpm_type => "dcfifo",
lpm_width => 8,
lpm_widthu => 10,
lpm_widthu_r => 8,
lpm_width_r => 32,
overflow_checking => "ON",
rdsync_delaypipe => 5,
underflow_checking => "ON",
use_eab => "ON",
write_aclr_synch => "OFF",
wrsync_delaypipe => 5
)
PORT MAP (
wrclk => wrclk,
rdreq => rdreq,
aclr => aclr,
rdclk => rdclk,
wrreq => wrreq,
data => data,
wrusedw => sub_wire0,
q => sub_wire1
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
-- Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
-- Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
-- Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
-- Retrieval info: PRIVATE: Clock NUMERIC "4"
-- Retrieval info: PRIVATE: Depth NUMERIC "1024"
-- Retrieval info: PRIVATE: Empty NUMERIC "1"
-- Retrieval info: PRIVATE: Full NUMERIC "1"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
-- Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"
-- Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
-- Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
-- Retrieval info: PRIVATE: Optimize NUMERIC "1"
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
-- Retrieval info: PRIVATE: UsedW NUMERIC "1"
-- Retrieval info: PRIVATE: Width NUMERIC "8"
-- Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
-- Retrieval info: PRIVATE: diff_widths NUMERIC "1"
-- Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
-- Retrieval info: PRIVATE: output_width NUMERIC "32"
-- Retrieval info: PRIVATE: rsEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: rsFull NUMERIC "0"
-- Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
-- Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
-- Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
-- Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: wsFull NUMERIC "0"
-- Retrieval info: PRIVATE: wsUsedW NUMERIC "1"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
-- Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
-- Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"
-- Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "10"
-- Retrieval info: CONSTANT: LPM_WIDTHU_R NUMERIC "8"
-- Retrieval info: CONSTANT: LPM_WIDTH_R NUMERIC "32"
-- Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
-- Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "5"
-- Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
-- Retrieval info: CONSTANT: USE_EAB STRING "ON"
-- Retrieval info: CONSTANT: WRITE_ACLR_SYNCH STRING "OFF"
-- Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "5"
-- Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr
-- Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL data[7..0]
-- Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL q[31..0]
-- Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk
-- Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq
-- Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk
-- Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq
-- Retrieval info: USED_PORT: wrusedw 0 0 10 0 OUTPUT NODEFVAL wrusedw[9..0]
-- Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0
-- Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 0
-- Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
-- Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
-- Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
-- Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
-- Retrieval info: CONNECT: wrusedw 0 0 10 0 @wrusedw 0 0 10 0
-- Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.bsf TRUE FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_waveforms.html FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,202 @@
-- megafunction wizard: %LPM_FIFO+%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: dcfifo_mixed_widths
-- ============================================================
-- File Name: dcfifo0.vhd
-- Megafunction Name(s):
-- dcfifo_mixed_widths
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 9.1 Build 222 10/21/2009 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2009 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY dcfifo0 IS
PORT
(
aclr : IN STD_LOGIC := '0';
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (4 DOWNTO 0)
);
END dcfifo0;
ARCHITECTURE SYN OF dcfifo0 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (15 DOWNTO 0);
COMPONENT dcfifo_mixed_widths
GENERIC (
intended_device_family : STRING;
lpm_numwords : NATURAL;
lpm_showahead : STRING;
lpm_type : STRING;
lpm_width : NATURAL;
lpm_widthu : NATURAL;
lpm_widthu_r : NATURAL;
lpm_width_r : NATURAL;
overflow_checking : STRING;
rdsync_delaypipe : NATURAL;
underflow_checking : STRING;
use_eab : STRING;
write_aclr_synch : STRING;
wrsync_delaypipe : NATURAL
);
PORT (
wrclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrusedw : OUT STD_LOGIC_VECTOR (4 DOWNTO 0);
aclr : IN STD_LOGIC ;
rdclk : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
wrreq : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END COMPONENT;
BEGIN
wrusedw <= sub_wire0(4 DOWNTO 0);
q <= sub_wire1(15 DOWNTO 0);
dcfifo_mixed_widths_component : dcfifo_mixed_widths
GENERIC MAP (
intended_device_family => "Cyclone III",
lpm_numwords => 32,
lpm_showahead => "OFF",
lpm_type => "dcfifo",
lpm_width => 8,
lpm_widthu => 5,
lpm_widthu_r => 4,
lpm_width_r => 16,
overflow_checking => "ON",
rdsync_delaypipe => 5,
underflow_checking => "ON",
use_eab => "ON",
write_aclr_synch => "OFF",
wrsync_delaypipe => 5
)
PORT MAP (
wrclk => wrclk,
rdreq => rdreq,
aclr => aclr,
rdclk => rdclk,
wrreq => wrreq,
data => data,
wrusedw => sub_wire0,
q => sub_wire1
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
-- Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
-- Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
-- Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
-- Retrieval info: PRIVATE: Clock NUMERIC "4"
-- Retrieval info: PRIVATE: Depth NUMERIC "32"
-- Retrieval info: PRIVATE: Empty NUMERIC "1"
-- Retrieval info: PRIVATE: Full NUMERIC "1"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
-- Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"
-- Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
-- Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
-- Retrieval info: PRIVATE: Optimize NUMERIC "1"
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
-- Retrieval info: PRIVATE: UsedW NUMERIC "1"
-- Retrieval info: PRIVATE: Width NUMERIC "8"
-- Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
-- Retrieval info: PRIVATE: diff_widths NUMERIC "1"
-- Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
-- Retrieval info: PRIVATE: output_width NUMERIC "16"
-- Retrieval info: PRIVATE: rsEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: rsFull NUMERIC "0"
-- Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
-- Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
-- Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
-- Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: wsFull NUMERIC "0"
-- Retrieval info: PRIVATE: wsUsedW NUMERIC "1"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "32"
-- Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
-- Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"
-- Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "5"
-- Retrieval info: CONSTANT: LPM_WIDTHU_R NUMERIC "4"
-- Retrieval info: CONSTANT: LPM_WIDTH_R NUMERIC "16"
-- Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
-- Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "5"
-- Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
-- Retrieval info: CONSTANT: USE_EAB STRING "ON"
-- Retrieval info: CONSTANT: WRITE_ACLR_SYNCH STRING "OFF"
-- Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "5"
-- Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr
-- Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL data[7..0]
-- Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]
-- Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk
-- Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq
-- Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk
-- Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq
-- Retrieval info: USED_PORT: wrusedw 0 0 5 0 OUTPUT NODEFVAL wrusedw[4..0]
-- Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0
-- Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0
-- Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
-- Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
-- Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
-- Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
-- Retrieval info: CONNECT: wrusedw 0 0 5 0 @wrusedw 0 0 5 0
-- Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.bsf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_waveforms.html FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,95 @@
/*
WARNING: Do NOT edit the input and output ports in this file in a text
editor if you plan to continue editing the block that represents it in
the Block Editor! File corruption is VERY likely to occur.
*/
/*
Copyright (C) 1991-2009 Altera Corporation
Your use of Altera Corporation's design tools, logic functions
and other software and tools, and its AMPP partner logic
functions, and any output files from any of the foregoing
(including device programming or simulation files), and any
associated documentation or information are expressly subject
to the terms and conditions of the Altera Program License
Subscription Agreement, Altera MegaCore Function License
Agreement, or other applicable license agreement, including,
without limitation, that your use is for the sole purpose of
programming logic devices manufactured by Altera and sold by
Altera or its authorized distributors. Please refer to the
applicable agreement for further details.
*/
(header "symbol" (version "1.1"))
(symbol
(rect 0 0 160 168)
(text "dcfifo1" (rect 62 1 105 17)(font "Arial" (font_size 10)))
(text "inst" (rect 8 152 25 164)(font "Arial" ))
(port
(pt 0 32)
(input)
(text "data[31..0]" (rect 0 0 60 14)(font "Arial" (font_size 8)))
(text "data[31..0]" (rect 20 26 71 39)(font "Arial" (font_size 8)))
(line (pt 0 32)(pt 16 32)(line_width 3))
)
(port
(pt 0 56)
(input)
(text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))
(text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))
(line (pt 0 56)(pt 16 56)(line_width 1))
)
(port
(pt 0 72)
(input)
(text "wrclk" (rect 0 0 31 14)(font "Arial" (font_size 8)))
(text "wrclk" (rect 26 66 48 79)(font "Arial" (font_size 8)))
(line (pt 0 72)(pt 16 72)(line_width 1))
)
(port
(pt 0 104)
(input)
(text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))
(text "rdreq" (rect 20 98 44 111)(font "Arial" (font_size 8)))
(line (pt 0 104)(pt 16 104)(line_width 1))
)
(port
(pt 0 120)
(input)
(text "rdclk" (rect 0 0 27 14)(font "Arial" (font_size 8)))
(text "rdclk" (rect 26 114 47 127)(font "Arial" (font_size 8)))
(line (pt 0 120)(pt 16 120)(line_width 1))
)
(port
(pt 0 144)
(input)
(text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))
(text "aclr" (rect 20 138 37 151)(font "Arial" (font_size 8)))
(line (pt 0 144)(pt 16 144)(line_width 1))
)
(port
(pt 160 96)
(output)
(text "q[7..0]" (rect 0 0 35 14)(font "Arial" (font_size 8)))
(text "q[7..0]" (rect 111 90 141 103)(font "Arial" (font_size 8)))
(line (pt 160 96)(pt 144 96)(line_width 3))
)
(port
(pt 160 120)
(output)
(text "rdusedw[9..0]" (rect 0 0 80 14)(font "Arial" (font_size 8)))
(text "rdusedw[9..0]" (rect 73 114 135 127)(font "Arial" (font_size 8)))
(line (pt 160 120)(pt 144 120)(line_width 3))
)
(drawing
(text "32 bits x 256 words" (rect 63 140 144 152)(font "Arial" ))
(line (pt 16 16)(pt 144 16)(line_width 1))
(line (pt 144 16)(pt 144 152)(line_width 1))
(line (pt 144 152)(pt 16 152)(line_width 1))
(line (pt 16 152)(pt 16 16)(line_width 1))
(line (pt 16 84)(pt 144 84)(line_width 1))
(line (pt 16 132)(pt 144 132)(line_width 1))
(line (pt 16 66)(pt 22 72)(line_width 1))
(line (pt 22 72)(pt 16 78)(line_width 1))
(line (pt 16 114)(pt 22 120)(line_width 1))
(line (pt 22 120)(pt 16 126)(line_width 1))
)
)

View File

@@ -0,0 +1,28 @@
--Copyright (C) 1991-2009 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
component dcfifo1
PORT
(
aclr : IN STD_LOGIC := '0';
data : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
rdusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
end component;

View File

@@ -0,0 +1,5 @@
set_global_assignment -name IP_TOOL_NAME "LPM_FIFO+"
set_global_assignment -name IP_TOOL_VERSION "9.1"
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "dcfifo1.vhd"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "dcfifo1.bsf"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "dcfifo1.cmp"]

View File

@@ -0,0 +1,202 @@
-- megafunction wizard: %LPM_FIFO+%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: dcfifo_mixed_widths
-- ============================================================
-- File Name: dcfifo1.vhd
-- Megafunction Name(s):
-- dcfifo_mixed_widths
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 9.1 Build 222 10/21/2009 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2009 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY dcfifo1 IS
PORT
(
aclr : IN STD_LOGIC := '0';
data : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
rdusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
END dcfifo1;
ARCHITECTURE SYN OF dcfifo1 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (9 DOWNTO 0);
COMPONENT dcfifo_mixed_widths
GENERIC (
intended_device_family : STRING;
lpm_numwords : NATURAL;
lpm_showahead : STRING;
lpm_type : STRING;
lpm_width : NATURAL;
lpm_widthu : NATURAL;
lpm_widthu_r : NATURAL;
lpm_width_r : NATURAL;
overflow_checking : STRING;
rdsync_delaypipe : NATURAL;
underflow_checking : STRING;
use_eab : STRING;
write_aclr_synch : STRING;
wrsync_delaypipe : NATURAL
);
PORT (
wrclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
aclr : IN STD_LOGIC ;
rdclk : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
wrreq : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
rdusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
END COMPONENT;
BEGIN
q <= sub_wire0(7 DOWNTO 0);
rdusedw <= sub_wire1(9 DOWNTO 0);
dcfifo_mixed_widths_component : dcfifo_mixed_widths
GENERIC MAP (
intended_device_family => "Cyclone III",
lpm_numwords => 256,
lpm_showahead => "OFF",
lpm_type => "dcfifo",
lpm_width => 32,
lpm_widthu => 8,
lpm_widthu_r => 10,
lpm_width_r => 8,
overflow_checking => "ON",
rdsync_delaypipe => 5,
underflow_checking => "ON",
use_eab => "ON",
write_aclr_synch => "OFF",
wrsync_delaypipe => 5
)
PORT MAP (
wrclk => wrclk,
rdreq => rdreq,
aclr => aclr,
rdclk => rdclk,
wrreq => wrreq,
data => data,
q => sub_wire0,
rdusedw => sub_wire1
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
-- Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
-- Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
-- Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
-- Retrieval info: PRIVATE: Clock NUMERIC "4"
-- Retrieval info: PRIVATE: Depth NUMERIC "256"
-- Retrieval info: PRIVATE: Empty NUMERIC "1"
-- Retrieval info: PRIVATE: Full NUMERIC "1"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
-- Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"
-- Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
-- Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
-- Retrieval info: PRIVATE: Optimize NUMERIC "1"
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
-- Retrieval info: PRIVATE: UsedW NUMERIC "1"
-- Retrieval info: PRIVATE: Width NUMERIC "32"
-- Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
-- Retrieval info: PRIVATE: diff_widths NUMERIC "1"
-- Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
-- Retrieval info: PRIVATE: output_width NUMERIC "8"
-- Retrieval info: PRIVATE: rsEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: rsFull NUMERIC "0"
-- Retrieval info: PRIVATE: rsUsedW NUMERIC "1"
-- Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
-- Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
-- Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: wsFull NUMERIC "0"
-- Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "256"
-- Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
-- Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"
-- Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "8"
-- Retrieval info: CONSTANT: LPM_WIDTHU_R NUMERIC "10"
-- Retrieval info: CONSTANT: LPM_WIDTH_R NUMERIC "8"
-- Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
-- Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "5"
-- Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
-- Retrieval info: CONSTANT: USE_EAB STRING "ON"
-- Retrieval info: CONSTANT: WRITE_ACLR_SYNCH STRING "OFF"
-- Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "5"
-- Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr
-- Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL data[31..0]
-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0]
-- Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk
-- Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq
-- Retrieval info: USED_PORT: rdusedw 0 0 10 0 OUTPUT NODEFVAL rdusedw[9..0]
-- Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk
-- Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq
-- Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0
-- Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
-- Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
-- Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
-- Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
-- Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
-- Retrieval info: CONNECT: rdusedw 0 0 10 0 @rdusedw 0 0 10 0
-- Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.bsf TRUE FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1_waveforms.html FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,202 @@
-- megafunction wizard: %LPM_FIFO+%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: dcfifo_mixed_widths
-- ============================================================
-- File Name: dcfifo1.vhd
-- Megafunction Name(s):
-- dcfifo_mixed_widths
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 9.1 Build 222 10/21/2009 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2009 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY dcfifo1 IS
PORT
(
aclr : IN STD_LOGIC := '0';
data : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
END dcfifo1;
ARCHITECTURE SYN OF dcfifo1 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (7 DOWNTO 0);
COMPONENT dcfifo_mixed_widths
GENERIC (
intended_device_family : STRING;
lpm_numwords : NATURAL;
lpm_showahead : STRING;
lpm_type : STRING;
lpm_width : NATURAL;
lpm_widthu : NATURAL;
lpm_widthu_r : NATURAL;
lpm_width_r : NATURAL;
overflow_checking : STRING;
rdsync_delaypipe : NATURAL;
underflow_checking : STRING;
use_eab : STRING;
write_aclr_synch : STRING;
wrsync_delaypipe : NATURAL
);
PORT (
wrclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrusedw : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);
aclr : IN STD_LOGIC ;
rdclk : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
wrreq : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (15 DOWNTO 0)
);
END COMPONENT;
BEGIN
wrusedw <= sub_wire0(3 DOWNTO 0);
q <= sub_wire1(7 DOWNTO 0);
dcfifo_mixed_widths_component : dcfifo_mixed_widths
GENERIC MAP (
intended_device_family => "Cyclone III",
lpm_numwords => 16,
lpm_showahead => "OFF",
lpm_type => "dcfifo",
lpm_width => 16,
lpm_widthu => 4,
lpm_widthu_r => 5,
lpm_width_r => 8,
overflow_checking => "ON",
rdsync_delaypipe => 5,
underflow_checking => "ON",
use_eab => "ON",
write_aclr_synch => "OFF",
wrsync_delaypipe => 5
)
PORT MAP (
wrclk => wrclk,
rdreq => rdreq,
aclr => aclr,
rdclk => rdclk,
wrreq => wrreq,
data => data,
wrusedw => sub_wire0,
q => sub_wire1
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
-- Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
-- Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
-- Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
-- Retrieval info: PRIVATE: Clock NUMERIC "4"
-- Retrieval info: PRIVATE: Depth NUMERIC "16"
-- Retrieval info: PRIVATE: Empty NUMERIC "1"
-- Retrieval info: PRIVATE: Full NUMERIC "1"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
-- Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"
-- Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
-- Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
-- Retrieval info: PRIVATE: Optimize NUMERIC "1"
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
-- Retrieval info: PRIVATE: UsedW NUMERIC "1"
-- Retrieval info: PRIVATE: Width NUMERIC "16"
-- Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
-- Retrieval info: PRIVATE: diff_widths NUMERIC "1"
-- Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
-- Retrieval info: PRIVATE: output_width NUMERIC "8"
-- Retrieval info: PRIVATE: rsEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: rsFull NUMERIC "0"
-- Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
-- Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
-- Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
-- Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
-- Retrieval info: PRIVATE: wsFull NUMERIC "0"
-- Retrieval info: PRIVATE: wsUsedW NUMERIC "1"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "16"
-- Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
-- Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"
-- Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "4"
-- Retrieval info: CONSTANT: LPM_WIDTHU_R NUMERIC "5"
-- Retrieval info: CONSTANT: LPM_WIDTH_R NUMERIC "8"
-- Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
-- Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "5"
-- Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
-- Retrieval info: CONSTANT: USE_EAB STRING "ON"
-- Retrieval info: CONSTANT: WRITE_ACLR_SYNCH STRING "OFF"
-- Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "5"
-- Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr
-- Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]
-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0]
-- Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk
-- Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq
-- Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk
-- Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq
-- Retrieval info: USED_PORT: wrusedw 0 0 4 0 OUTPUT NODEFVAL wrusedw[3..0]
-- Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0
-- Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
-- Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
-- Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
-- Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
-- Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
-- Retrieval info: CONNECT: wrusedw 0 0 4 0 @wrusedw 0 0 4 0
-- Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.bsf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1_waveforms.html FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,478 @@
TITLE "INTERRUPT HANDLER UND C1287";
-- CREATED BY FREDI ASCHWANDEN
INCLUDE "lpm_bustri_LONG.inc";
INCLUDE "lpm_bustri_BYT.inc";
-- Parameters Statement (optional)
-- {{ALTERA_PARAMETERS_BEGIN}} DO NOT REMOVE THIS LINE!
-- {{ALTERA_PARAMETERS_END}} DO NOT REMOVE THIS LINE!
-- Subdesign Section
SUBDESIGN interrupt_handler
(
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
MAIN_CLK : INPUT;
nFB_WR : INPUT;
nFB_CS1 : INPUT;
nFB_CS2 : INPUT;
FB_SIZE0 : INPUT;
FB_SIZE1 : INPUT;
FB_ADR[31..0] : INPUT;
PIC_INT : INPUT;
E0_INT : INPUT;
DVI_INT : INPUT;
nPCI_INTA : INPUT;
nPCI_INTB : INPUT;
nPCI_INTC : INPUT;
nPCI_INTD : INPUT;
nMFP_INT : INPUT;
nFB_OE : INPUT;
DSP_INT : INPUT;
VSYNC : INPUT;
HSYNC : INPUT;
DMA_DRQ : INPUT;
nIRQ[7..2] : OUTPUT;
INT_HANDLER_TA : OUTPUT;
ACP_CONF[31..0] : OUTPUT;
TIN0 : OUTPUT;
FB_AD[31..0] : BIDIR;
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
)
VARIABLE
FB_B[3..0] :NODE;
INT_CTR[31..0] :DFFE;
INT_CTR_CS :NODE;
INT_LATCH[31..0] :DFF;
INT_LATCH_CS :NODE;
INT_CLEAR[31..0] :DFF;
INT_CLEAR_CS :NODE;
INT_IN[31..0] :NODE;
INT_ENA[31..0] :DFFE;
INT_ENA_CS :NODE;
ACP_CONF[31..0] :DFFE;
ACP_CONF_CS :NODE;
PSEUDO_BUS_ERROR :NODE;
UHR_AS :NODE;
UHR_DS :NODE;
RTC_ADR[5..0] :DFFE;
ACHTELSEKUNDEN[2..0] :DFFE;
WERTE[7..0][63..0] :DFFE; -- WERTE REGISTER 0-63
PIC_INT_SYNC[2..0] :DFF;
INC_SEC :NODE;
INC_MIN :NODE;
INC_STD :NODE;
INC_TAG :NODE;
ANZAHL_TAGE_DES_MONATS[7..0]:NODE;
WINTERZEIT :NODE;
SOMMERZEIT :NODE;
INC_MONAT :NODE;
INC_JAHR :NODE;
UPDATE_ON :NODE;
BEGIN
-- BYT SELECT
FB_B0 = FB_SIZE1 & !FB_SIZE0 & !FB_ADR1 -- HWORD
# !FB_SIZE1 & FB_SIZE0 & !FB_ADR1 & !FB_ADR0 -- HHBYT
# !FB_SIZE1 & !FB_SIZE0 # FB_SIZE1 & FB_SIZE0; -- LONG UND LINE
FB_B1 = FB_SIZE1 & !FB_SIZE0 & !FB_ADR1 -- HWORD
# !FB_SIZE1 & FB_SIZE0 & !FB_ADR1 & FB_ADR0 -- HLBYT
# !FB_SIZE1 & !FB_SIZE0 # FB_SIZE1 & FB_SIZE0; -- LONG UND LINE
FB_B2 = FB_SIZE1 & !FB_SIZE0 & FB_ADR1 -- LWORD
# !FB_SIZE1 & FB_SIZE0 & FB_ADR1 & !FB_ADR0 -- LHBYT
# !FB_SIZE1 & !FB_SIZE0 # FB_SIZE1 & FB_SIZE0; -- LONG UND LINE
FB_B3 = FB_SIZE1 & !FB_SIZE0 & FB_ADR1 -- LWORD
# !FB_SIZE1 & FB_SIZE0 & FB_ADR1 & FB_ADR0 -- LLBYT
# !FB_SIZE1 & !FB_SIZE0 # FB_SIZE1 & FB_SIZE0; -- LONG UND LINE
-- INTERRUPT CONTROL REGISTER: BIT0=INT5 AUSL<53>SEN, 1=INT7 AUSL<53>SEN
INT_CTR[].CLK = MAIN_CLK;
INT_CTR_CS = !nFB_CS2 & FB_ADR[27..2]==H"4000"; -- $10000/4
INT_CTR[] = FB_AD[];
INT_CTR[31..24].ENA = INT_CTR_CS & FB_B0 & !nFB_WR;
INT_CTR[23..16].ENA = INT_CTR_CS & FB_B1 & !nFB_WR;
INT_CTR[15..8].ENA = INT_CTR_CS & FB_B2 & !nFB_WR;
INT_CTR[7..0].ENA = INT_CTR_CS & FB_B3 & !nFB_WR;
-- INTERRUPT ENABLE REGISTER BIT31=INT7,30=INT6,29=INT5,28=INT4,27=INT3,26=INT2
INT_ENA[].CLK = MAIN_CLK;
INT_ENA_CS = !nFB_CS2 & FB_ADR[27..2]==H"4001"; -- $10004/4
INT_ENA[] = FB_AD[];
INT_ENA[31..24].ENA = INT_ENA_CS & FB_B0 & !nFB_WR;
INT_ENA[23..16].ENA = INT_ENA_CS & FB_B1 & !nFB_WR;
INT_ENA[15..8].ENA = INT_ENA_CS & FB_B2 & !nFB_WR;
INT_ENA[7..0].ENA = INT_ENA_CS & FB_B3 & !nFB_WR;
-- INTERRUPT CLEAR REGISTER WRITE ONLY 1=INTERRUPT CLEAR
INT_CLEAR[].CLK = MAIN_CLK;
INT_CLEAR_CS = !nFB_CS2 & FB_ADR[27..2]==H"4002"; -- $10008/4
INT_CLEAR[31..24] = FB_AD[31..24] & INT_CLEAR_CS & FB_B0 & !nFB_WR;
INT_CLEAR[23..16] = FB_AD[23..16] & INT_CLEAR_CS & FB_B1 & !nFB_WR;
INT_CLEAR[15..8] = FB_AD[15..8] & INT_CLEAR_CS & FB_B2 & !nFB_WR;
INT_CLEAR[7..0] = FB_AD[7..0] & INT_CLEAR_CS & FB_B3 & !nFB_WR;
-- INTERRUPT LATCH REGISTER READ ONLY
INT_LATCH_CS = !nFB_CS2 & FB_ADR[27..2]==H"4003"; -- $1000C/4
-- INTERRUPT
!nIRQ2 = HSYNC & INT_ENA[26];
!nIRQ3 = INT_CTR0 & INT_ENA[27];
!nIRQ4 = VSYNC & INT_ENA[28];
nIRQ5 = INT_LATCH[]==H"00000000" & INT_ENA[29];
!nIRQ6 = !nMFP_INT & INT_ENA[30];
!nIRQ7 = PSEUDO_BUS_ERROR & INT_ENA[31];
PSEUDO_BUS_ERROR = !nFB_CS1 & (FB_ADR[19..4]==H"F8C8" -- SCC
# FB_ADR[19..4]==H"F8E0" -- VME
# FB_ADR[19..4]==H"F920" -- PADDLE
# FB_ADR[19..4]==H"F921" -- PADDLE
# FB_ADR[19..4]==H"F922" -- PADDLE
# FB_ADR[19..4]==H"FFA8" -- MFP2
# FB_ADR[19..4]==H"FFA9" -- MFP2
# FB_ADR[19..4]==H"FFAA" -- MFP2
# FB_ADR[19..4]==H"FFA8" -- MFP2
# FB_ADR[19..8]==H"F87" -- TT SCSI
# FB_ADR[19..4]==H"FFC2" -- ST UHR
# FB_ADR[19..4]==H"FFC3" -- ST UHR
# FB_ADR[19..4]==H"F890" -- DMA SOUND
# FB_ADR[19..4]==H"F891" -- DMA SOUND
# FB_ADR[19..4]==H"F892"); -- DMA SOUND
-- IF VIDEO ADR CHANGE
TIN0 = !nFB_CS1 & FB_ADR[19..1]==H"7C100" & !nFB_WR; -- WRITE VIDEO BASE ADR HIGH 0xFFFF8201/2
-- INTERRUPT LATCH
INT_LATCH[] = H"FFFFFFFF";
INT_LATCH0.CLK = PIC_INT & INT_ENA[0];
INT_LATCH1.CLK = E0_INT & INT_ENA[1];
INT_LATCH2.CLK = DVI_INT & INT_ENA[2];
INT_LATCH3.CLK = !nPCI_INTA & INT_ENA[3];
INT_LATCH4.CLK = !nPCI_INTB & INT_ENA[4];
INT_LATCH5.CLK = !nPCI_INTC & INT_ENA[5];
INT_LATCH6.CLK = !nPCI_INTD & INT_ENA[6];
INT_LATCH7.CLK = DSP_INT & INT_ENA[7];
INT_LATCH8.CLK = VSYNC & INT_ENA[8];
INT_LATCH9.CLK = HSYNC & INT_ENA[9];
-- INTERRUPT CLEAR
INT_LATCH[].CLRN = !INT_CLEAR[];
-- INT_IN
INT_IN0 = PIC_INT;
INT_IN1 = E0_INT;
INT_IN2 = DVI_INT;
INT_IN3 = !nPCI_INTA;
INT_IN4 = !nPCI_INTB;
INT_IN5 = !nPCI_INTC;
INT_IN6 = !nPCI_INTD;
INT_IN7 = DSP_INT;
INT_IN8 = VSYNC;
INT_IN9 = HSYNC;
INT_IN[25..10] = H"0";
INT_IN26 = HSYNC;
INT_IN27 = INT_CTR0;
INT_IN28 = VSYNC;
INT_IN29 = INT_LATCH[]!=H"00000000";
INT_IN30 = !nMFP_INT;
INT_IN31 = DMA_DRQ;
--***************************************************************************************
-- ACP CONFIG REGISTER: BIT 31-> 0=CF 1=IDE
ACP_CONF[].CLK = MAIN_CLK;
ACP_CONF_CS = !nFB_CS2 & FB_ADR[27..2]==H"10000"; -- $4'0000/4
ACP_CONF[] = FB_AD[];
ACP_CONF[31..24].ENA = ACP_CONF_CS & FB_B0 & !nFB_WR;
ACP_CONF[23..16].ENA = ACP_CONF_CS & FB_B1 & !nFB_WR;
ACP_CONF[15..8].ENA = ACP_CONF_CS & FB_B2 & !nFB_WR;
ACP_CONF[7..0].ENA = ACP_CONF_CS & FB_B3 & !nFB_WR;
--***************************************************************************************
--------------------------------------------------------------
-- C1287 0=SEK 2=MIN 4=STD 6=WOCHENTAG 7=TAG 8=MONAT 9=JAHR
----------------------------------------------------------
RTC_ADR[].CLK = MAIN_CLK;
RTC_ADR[] = FB_AD[21..16];
UHR_AS = !nFB_CS1 & FB_ADR[19..1]==H"7C4B0" & FB_B1; -- FFFF8961
UHR_DS = !nFB_CS1 & FB_ADR[19..1]==H"7C4B1" & FB_B3; -- FFFF8963
RTC_ADR[].ENA = UHR_AS & !nFB_WR;
WERTE[][].CLK = MAIN_CLK;
WERTE[7..0][0] = FB_AD[23..16] & RTC_ADR[]==0 & UHR_DS & !nFB_WR;
WERTE[7..0][1] = FB_AD[23..16];
WERTE[7..0][2] = FB_AD[23..16] & RTC_ADR[]==2 & UHR_DS & !nFB_WR;
WERTE[7..0][3] = FB_AD[23..16];
WERTE[7..0][4] = FB_AD[23..16] & RTC_ADR[]==4 & UHR_DS & !nFB_WR;
WERTE[7..0][5] = FB_AD[23..16];
WERTE[7..0][6] = FB_AD[23..16] & RTC_ADR[]==6 & UHR_DS & !nFB_WR;
WERTE[7..0][7] = FB_AD[23..16] & RTC_ADR[]==7 & UHR_DS & !nFB_WR;
WERTE[7..0][8] = FB_AD[23..16] & RTC_ADR[]==8 & UHR_DS & !nFB_WR;
WERTE[7..0][9] = FB_AD[23..16] & RTC_ADR[]==9 & UHR_DS & !nFB_WR;
WERTE[7..0][10] = FB_AD[23..16];
WERTE[7..0][11] = FB_AD[23..16];
WERTE[7..0][12] = FB_AD[23..16];
WERTE[7..0][13] = FB_AD[23..16];
WERTE[7..0][14] = FB_AD[23..16];
WERTE[7..0][15] = FB_AD[23..16];
WERTE[7..0][16] = FB_AD[23..16];
WERTE[7..0][17] = FB_AD[23..16];
WERTE[7..0][18] = FB_AD[23..16];
WERTE[7..0][19] = FB_AD[23..16];
WERTE[7..0][20] = FB_AD[23..16];
WERTE[7..0][21] = FB_AD[23..16];
WERTE[7..0][22] = FB_AD[23..16];
WERTE[7..0][23] = FB_AD[23..16];
WERTE[7..0][24] = FB_AD[23..16];
WERTE[7..0][25] = FB_AD[23..16];
WERTE[7..0][26] = FB_AD[23..16];
WERTE[7..0][27] = FB_AD[23..16];
WERTE[7..0][28] = FB_AD[23..16];
WERTE[7..0][29] = FB_AD[23..16];
WERTE[7..0][30] = FB_AD[23..16];
WERTE[7..0][31] = FB_AD[23..16];
WERTE[7..0][32] = FB_AD[23..16];
WERTE[7..0][33] = FB_AD[23..16];
WERTE[7..0][34] = FB_AD[23..16];
WERTE[7..0][35] = FB_AD[23..16];
WERTE[7..0][36] = FB_AD[23..16];
WERTE[7..0][37] = FB_AD[23..16];
WERTE[7..0][38] = FB_AD[23..16];
WERTE[7..0][39] = FB_AD[23..16];
WERTE[7..0][40] = FB_AD[23..16];
WERTE[7..0][41] = FB_AD[23..16];
WERTE[7..0][42] = FB_AD[23..16];
WERTE[7..0][43] = FB_AD[23..16];
WERTE[7..0][44] = FB_AD[23..16];
WERTE[7..0][45] = FB_AD[23..16];
WERTE[7..0][46] = FB_AD[23..16];
WERTE[7..0][47] = FB_AD[23..16];
WERTE[7..0][48] = FB_AD[23..16];
WERTE[7..0][49] = FB_AD[23..16];
WERTE[7..0][50] = FB_AD[23..16];
WERTE[7..0][51] = FB_AD[23..16];
WERTE[7..0][52] = FB_AD[23..16];
WERTE[7..0][53] = FB_AD[23..16];
WERTE[7..0][54] = FB_AD[23..16];
WERTE[7..0][55] = FB_AD[23..16];
WERTE[7..0][56] = FB_AD[23..16];
WERTE[7..0][57] = FB_AD[23..16];
WERTE[7..0][58] = FB_AD[23..16];
WERTE[7..0][59] = FB_AD[23..16];
WERTE[7..0][60] = FB_AD[23..16];
WERTE[7..0][61] = FB_AD[23..16];
WERTE[7..0][62] = FB_AD[23..16];
WERTE[7..0][63] = FB_AD[23..16];
WERTE[][0].ENA = RTC_ADR[]==0 & UHR_DS & !nFB_WR;
WERTE[][1].ENA = RTC_ADR[]==1 & UHR_DS & !nFB_WR;
WERTE[][2].ENA = RTC_ADR[]==2 & UHR_DS & !nFB_WR;
WERTE[][3].ENA = RTC_ADR[]==3 & UHR_DS & !nFB_WR;
WERTE[][4].ENA = RTC_ADR[]==4 & UHR_DS & !nFB_WR;
WERTE[][5].ENA = RTC_ADR[]==5 & UHR_DS & !nFB_WR;
WERTE[][6].ENA = RTC_ADR[]==6 & UHR_DS & !nFB_WR;
WERTE[][7].ENA = RTC_ADR[]==7 & UHR_DS & !nFB_WR;
WERTE[][8].ENA = RTC_ADR[]==8 & UHR_DS & !nFB_WR;
WERTE[][9].ENA = RTC_ADR[]==9 & UHR_DS & !nFB_WR;
WERTE[][10].ENA = RTC_ADR[]==10 & UHR_DS & !nFB_WR;
WERTE[][11].ENA = RTC_ADR[]==11 & UHR_DS & !nFB_WR;
WERTE[][12].ENA = RTC_ADR[]==12 & UHR_DS & !nFB_WR;
WERTE[][13].ENA = RTC_ADR[]==13 & UHR_DS & !nFB_WR;
WERTE[][14].ENA = RTC_ADR[]==14 & UHR_DS & !nFB_WR;
WERTE[][15].ENA = RTC_ADR[]==15 & UHR_DS & !nFB_WR;
WERTE[][16].ENA = RTC_ADR[]==16 & UHR_DS & !nFB_WR;
WERTE[][17].ENA = RTC_ADR[]==17 & UHR_DS & !nFB_WR;
WERTE[][18].ENA = RTC_ADR[]==18 & UHR_DS & !nFB_WR;
WERTE[][19].ENA = RTC_ADR[]==19 & UHR_DS & !nFB_WR;
WERTE[][20].ENA = RTC_ADR[]==20 & UHR_DS & !nFB_WR;
WERTE[][21].ENA = RTC_ADR[]==21 & UHR_DS & !nFB_WR;
WERTE[][22].ENA = RTC_ADR[]==22 & UHR_DS & !nFB_WR;
WERTE[][23].ENA = RTC_ADR[]==23 & UHR_DS & !nFB_WR;
WERTE[][24].ENA = RTC_ADR[]==24 & UHR_DS & !nFB_WR;
WERTE[][25].ENA = RTC_ADR[]==25 & UHR_DS & !nFB_WR;
WERTE[][26].ENA = RTC_ADR[]==26 & UHR_DS & !nFB_WR;
WERTE[][27].ENA = RTC_ADR[]==27 & UHR_DS & !nFB_WR;
WERTE[][28].ENA = RTC_ADR[]==28 & UHR_DS & !nFB_WR;
WERTE[][29].ENA = RTC_ADR[]==29 & UHR_DS & !nFB_WR;
WERTE[][30].ENA = RTC_ADR[]==30 & UHR_DS & !nFB_WR;
WERTE[][31].ENA = RTC_ADR[]==31 & UHR_DS & !nFB_WR;
WERTE[][32].ENA = RTC_ADR[]==32 & UHR_DS & !nFB_WR;
WERTE[][33].ENA = RTC_ADR[]==33 & UHR_DS & !nFB_WR;
WERTE[][34].ENA = RTC_ADR[]==34 & UHR_DS & !nFB_WR;
WERTE[][35].ENA = RTC_ADR[]==35 & UHR_DS & !nFB_WR;
WERTE[][36].ENA = RTC_ADR[]==36 & UHR_DS & !nFB_WR;
WERTE[][37].ENA = RTC_ADR[]==37 & UHR_DS & !nFB_WR;
WERTE[][38].ENA = RTC_ADR[]==38 & UHR_DS & !nFB_WR;
WERTE[][39].ENA = RTC_ADR[]==39 & UHR_DS & !nFB_WR;
WERTE[][40].ENA = RTC_ADR[]==40 & UHR_DS & !nFB_WR;
WERTE[][41].ENA = RTC_ADR[]==41 & UHR_DS & !nFB_WR;
WERTE[][42].ENA = RTC_ADR[]==42 & UHR_DS & !nFB_WR;
WERTE[][43].ENA = RTC_ADR[]==43 & UHR_DS & !nFB_WR;
WERTE[][44].ENA = RTC_ADR[]==44 & UHR_DS & !nFB_WR;
WERTE[][45].ENA = RTC_ADR[]==45 & UHR_DS & !nFB_WR;
WERTE[][46].ENA = RTC_ADR[]==46 & UHR_DS & !nFB_WR;
WERTE[][47].ENA = RTC_ADR[]==47 & UHR_DS & !nFB_WR;
WERTE[][48].ENA = RTC_ADR[]==48 & UHR_DS & !nFB_WR;
WERTE[][49].ENA = RTC_ADR[]==49 & UHR_DS & !nFB_WR;
WERTE[][50].ENA = RTC_ADR[]==50 & UHR_DS & !nFB_WR;
WERTE[][51].ENA = RTC_ADR[]==51 & UHR_DS & !nFB_WR;
WERTE[][52].ENA = RTC_ADR[]==52 & UHR_DS & !nFB_WR;
WERTE[][53].ENA = RTC_ADR[]==53 & UHR_DS & !nFB_WR;
WERTE[][54].ENA = RTC_ADR[]==54 & UHR_DS & !nFB_WR;
WERTE[][55].ENA = RTC_ADR[]==55 & UHR_DS & !nFB_WR;
WERTE[][56].ENA = RTC_ADR[]==56 & UHR_DS & !nFB_WR;
WERTE[][57].ENA = RTC_ADR[]==57 & UHR_DS & !nFB_WR;
WERTE[][58].ENA = RTC_ADR[]==58 & UHR_DS & !nFB_WR;
WERTE[][59].ENA = RTC_ADR[]==59 & UHR_DS & !nFB_WR;
WERTE[][60].ENA = RTC_ADR[]==60 & UHR_DS & !nFB_WR;
WERTE[][61].ENA = RTC_ADR[]==61 & UHR_DS & !nFB_WR;
WERTE[][62].ENA = RTC_ADR[]==62 & UHR_DS & !nFB_WR;
WERTE[][63].ENA = RTC_ADR[]==63 & UHR_DS & !nFB_WR;
PIC_INT_SYNC[].CLK = MAIN_CLK; PIC_INT_SYNC[0] = PIC_INT;
PIC_INT_SYNC[1] = PIC_INT_SYNC[0];
PIC_INT_SYNC[2] = !PIC_INT_SYNC[1] & PIC_INT_SYNC[0];
UPDATE_ON = !WERTE[7][11];
WERTE[6][10].CLRN = GND; -- KEIN UIP
UPDATE_ON = !WERTE[7][11]; -- UPDATE ON OFF
WERTE[2][11] = VCC; -- IMMER BINARY
WERTE[1][11] = VCC; -- IMMER 24H FORMAT
WERTE[0][11] = VCC; -- IMMER SOMMERZEITKORREKTUR
WERTE[7][13] = VCC; -- IMMER RICHTIG
-- SOMMER WINTERZEIT: BIT 0 IM REGISTER D IST DIE INFORMATION OB SOMMERZEIT IST (BRAUCHT MAN F<>R R<>CKSCHALTUNG)
SOMMERZEIT = WERTE[][6]==1 & WERTE[][4]==1 & WERTE[][8]==4 & WERTE[][7]>23; --LETZTER SONNTAG IM APRIL
WERTE[0][13] = SOMMERZEIT;
WERTE[0][13].ENA = INC_STD & (SOMMERZEIT # WINTERZEIT);
WINTERZEIT = WERTE[][6]==1 & WERTE[][4]==1 & WERTE[][8]==10 & WERTE[][7]>24 & WERTE[0][13]; --LETZTER SONNTAG IM OKTOBER
-- ACHTELSEKUNDEN
ACHTELSEKUNDEN[].CLK = MAIN_CLK;
ACHTELSEKUNDEN[] = ACHTELSEKUNDEN[]+1;
ACHTELSEKUNDEN[].ENA = PIC_INT_SYNC[2] & UPDATE_ON;
-- SEKUNDEN
INC_SEC = ACHTELSEKUNDEN[]==7 & PIC_INT_SYNC[2] & UPDATE_ON;
WERTE[][0] = (WERTE[][0]+1) & WERTE[][0]!=59 & !(RTC_ADR[]==0 & UHR_DS & !nFB_WR); -- SEKUNDEN Z<>HLEN BIS 59
WERTE[][0].ENA = INC_SEC & !(RTC_ADR[]==0 & UHR_DS & !nFB_WR);
-- MINUTEN
INC_MIN = INC_SEC & WERTE[][0]==59; --
WERTE[][2] = (WERTE[][2]+1) & WERTE[][2]!=59 & !(RTC_ADR[]==2 & UHR_DS & !nFB_WR); -- MINUTEN Z<>HLEN BIS 59
WERTE[][2].ENA = INC_MIN & !(RTC_ADR[]==2 & UHR_DS & !nFB_WR); --
-- STUNDEN
INC_STD = INC_MIN & WERTE[][2]==59;
WERTE[][4] = (WERTE[][4]+1+(1 & SOMMERZEIT)) & WERTE[][4]!=23 & !(RTC_ADR[]==4 & UHR_DS & !nFB_WR); -- STUNDEN Z<>HLEN BIS 23
WERTE[][4].ENA = INC_STD & !(WINTERZEIT & WERTE[0][12]) & !(RTC_ADR[]==4 & UHR_DS & !nFB_WR); -- EINE STUNDE AUSLASSEN WENN WINTERZEITUMSCHALTUNG UND NOCH SOMMERZEIT
-- WOCHENTAG UND TAG
INC_TAG = INC_STD & WERTE[][2]==23;
WERTE[][6] = (WERTE[][6]+1) & WERTE[][6]!=7 & !(RTC_ADR[]==6 & UHR_DS & !nFB_WR) -- WOCHENTAG Z<>HLEN BIS 7
# 1 & WERTE[][6]==7 & !(RTC_ADR[]==6 & UHR_DS & !nFB_WR); -- DANN BEI 1 WEITER
WERTE[][6].ENA = INC_TAG & !(RTC_ADR[]==6 & UHR_DS & !nFB_WR);
ANZAHL_TAGE_DES_MONATS[] = 31 & (WERTE[][8]==1 # WERTE[][8]==3 # WERTE[][8]==5 # WERTE[][8]==7 # WERTE[][8]==8 # WERTE[][8]==10 # WERTE[][8]==12)
# 30 & (WERTE[][8]==4 # WERTE[][8]==6 # WERTE[][8]==9 # WERTE[][8]==11)
# 29 & WERTE[][8]==2 & WERTE[1..0][9]==0
# 28 & WERTE[][8]==2 & WERTE[1..0][9]!=0;
WERTE[][7] = (WERTE[][7]+1) & WERTE[][7]!=ANZAHL_TAGE_DES_MONATS[] & !(RTC_ADR[]==7 & UHR_DS & !nFB_WR) -- TAG Z<>HLEN BIS MONATSENDE
# 1 & WERTE[][7]==ANZAHL_TAGE_DES_MONATS[] & !(RTC_ADR[]==7 & UHR_DS & !nFB_WR); -- DANN BEI 1 WEITER
WERTE[][7].ENA = INC_TAG & !(RTC_ADR[]==7 & UHR_DS & !nFB_WR); --
-- MONATE
INC_MONAT = INC_TAG & WERTE[][7]==ANZAHL_TAGE_DES_MONATS[]; --
WERTE[][8] = (WERTE[][8]+1) & WERTE[][8]!=12 & !(RTC_ADR[]==8 & UHR_DS & !nFB_WR) -- MONATE Z<>HLEN BIS 12
# 1 & WERTE[][8]==12 & !(RTC_ADR[]==8 & UHR_DS & !nFB_WR); -- DANN BEI 1 WEITER
WERTE[][8].ENA = INC_MONAT & !(RTC_ADR[]==8 & UHR_DS & !nFB_WR);
-- JAHR
INC_JAHR = INC_MONAT & WERTE[][8]==12; --
WERTE[][9] = (WERTE[][9]+1) & WERTE[][9]!=99 & !(RTC_ADR[]==9 & UHR_DS & !nFB_WR); -- JAHRE Z<>HLEN BIS 99
WERTE[][9].ENA = INC_JAHR & !(RTC_ADR[]==9 & UHR_DS & !nFB_WR);
-- TRISTATE OUTPUT
FB_AD[31..24] = lpm_bustri_BYT(
INT_CTR_CS & INT_CTR[31..24]
# INT_ENA_CS & INT_ENA[31..24]
# INT_LATCH_CS & INT_LATCH[31..24]
# INT_CLEAR_CS & INT_IN[31..24]
# ACP_CONF_CS & ACP_CONF[31..24]
,(INT_CTR_CS # INT_ENA_CS # INT_LATCH_CS # INT_CLEAR_CS # ACP_CONF_CS) & !nFB_OE);
FB_AD[23..16] = lpm_bustri_BYT(
WERTE[][0] & RTC_ADR[]==0 & UHR_DS
# WERTE[][1] & RTC_ADR[]==1 & UHR_DS
# WERTE[][2] & RTC_ADR[]==2 & UHR_DS
# WERTE[][3] & RTC_ADR[]==3 & UHR_DS
# WERTE[][4] & RTC_ADR[]==4 & UHR_DS
# WERTE[][5] & RTC_ADR[]==5 & UHR_DS
# WERTE[][6] & RTC_ADR[]==6 & UHR_DS
# WERTE[][7] & RTC_ADR[]==7 & UHR_DS
# WERTE[][8] & RTC_ADR[]==8 & UHR_DS
# WERTE[][9] & RTC_ADR[]==9 & UHR_DS
# WERTE[][10] & RTC_ADR[]==10 & UHR_DS
# WERTE[][11] & RTC_ADR[]==11 & UHR_DS
# WERTE[][12] & RTC_ADR[]==12 & UHR_DS
# WERTE[][13] & RTC_ADR[]==13 & UHR_DS
# WERTE[][14] & RTC_ADR[]==14 & UHR_DS
# WERTE[][15] & RTC_ADR[]==15 & UHR_DS
# WERTE[][16] & RTC_ADR[]==16 & UHR_DS
# WERTE[][17] & RTC_ADR[]==17 & UHR_DS
# WERTE[][18] & RTC_ADR[]==18 & UHR_DS
# WERTE[][19] & RTC_ADR[]==19 & UHR_DS
# WERTE[][20] & RTC_ADR[]==20 & UHR_DS
# WERTE[][21] & RTC_ADR[]==21 & UHR_DS
# WERTE[][22] & RTC_ADR[]==22 & UHR_DS
# WERTE[][23] & RTC_ADR[]==23 & UHR_DS
# WERTE[][24] & RTC_ADR[]==24 & UHR_DS
# WERTE[][25] & RTC_ADR[]==25 & UHR_DS
# WERTE[][26] & RTC_ADR[]==26 & UHR_DS
# WERTE[][27] & RTC_ADR[]==27 & UHR_DS
# WERTE[][28] & RTC_ADR[]==28 & UHR_DS
# WERTE[][29] & RTC_ADR[]==29 & UHR_DS
# WERTE[][30] & RTC_ADR[]==30 & UHR_DS
# WERTE[][31] & RTC_ADR[]==31 & UHR_DS
# WERTE[][32] & RTC_ADR[]==32 & UHR_DS
# WERTE[][33] & RTC_ADR[]==33 & UHR_DS
# WERTE[][34] & RTC_ADR[]==34 & UHR_DS
# WERTE[][35] & RTC_ADR[]==35 & UHR_DS
# WERTE[][36] & RTC_ADR[]==36 & UHR_DS
# WERTE[][37] & RTC_ADR[]==37 & UHR_DS
# WERTE[][38] & RTC_ADR[]==38 & UHR_DS
# WERTE[][39] & RTC_ADR[]==39 & UHR_DS
# WERTE[][40] & RTC_ADR[]==40 & UHR_DS
# WERTE[][41] & RTC_ADR[]==41 & UHR_DS
# WERTE[][42] & RTC_ADR[]==42 & UHR_DS
# WERTE[][43] & RTC_ADR[]==43 & UHR_DS
# WERTE[][44] & RTC_ADR[]==44 & UHR_DS
# WERTE[][45] & RTC_ADR[]==45 & UHR_DS
# WERTE[][46] & RTC_ADR[]==46 & UHR_DS
# WERTE[][47] & RTC_ADR[]==47 & UHR_DS
# WERTE[][48] & RTC_ADR[]==48 & UHR_DS
# WERTE[][49] & RTC_ADR[]==49 & UHR_DS
# WERTE[][50] & RTC_ADR[]==50 & UHR_DS
# WERTE[][51] & RTC_ADR[]==51 & UHR_DS
# WERTE[][52] & RTC_ADR[]==52 & UHR_DS
# WERTE[][53] & RTC_ADR[]==53 & UHR_DS
# WERTE[][54] & RTC_ADR[]==54 & UHR_DS
# WERTE[][55] & RTC_ADR[]==55 & UHR_DS
# WERTE[][56] & RTC_ADR[]==56 & UHR_DS
# WERTE[][57] & RTC_ADR[]==57 & UHR_DS
# WERTE[][58] & RTC_ADR[]==58 & UHR_DS
# WERTE[][59] & RTC_ADR[]==59 & UHR_DS
# WERTE[][60] & RTC_ADR[]==60 & UHR_DS
# WERTE[][61] & RTC_ADR[]==61 & UHR_DS
# WERTE[][62] & RTC_ADR[]==62 & UHR_DS
# WERTE[][63] & RTC_ADR[]==63 & UHR_DS
# (0,RTC_ADR[]) & UHR_AS
# INT_CTR_CS & INT_CTR[23..16]
# INT_ENA_CS & INT_ENA[23..16]
# INT_LATCH_CS & INT_LATCH[23..16]
# INT_CLEAR_CS & INT_IN[23..16]
# ACP_CONF_CS & ACP_CONF[23..16]
,(UHR_DS # UHR_AS # INT_CTR_CS # INT_ENA_CS # INT_LATCH_CS # INT_CLEAR_CS # ACP_CONF_CS) & !nFB_OE);
FB_AD[15..8] = lpm_bustri_BYT(
INT_CTR_CS & INT_CTR[15..8]
# INT_ENA_CS & INT_ENA[15..8]
# INT_LATCH_CS & INT_LATCH[15..8]
# INT_CLEAR_CS & INT_IN[15..8]
# ACP_CONF_CS & ACP_CONF[15..8]
,(INT_CTR_CS # INT_ENA_CS # INT_LATCH_CS # INT_CLEAR_CS # ACP_CONF_CS) & !nFB_OE);
FB_AD[7..0] = lpm_bustri_BYT(
INT_CTR_CS & INT_CTR[7..0]
# INT_ENA_CS & INT_ENA[7..0]
# INT_LATCH_CS & INT_LATCH[7..0]
# INT_CLEAR_CS & INT_IN[7..0]
# ACP_CONF_CS & ACP_CONF[7..0]
,(INT_CTR_CS # INT_ENA_CS # INT_LATCH_CS # INT_CLEAR_CS # ACP_CONF_CS) & !nFB_OE);
INT_HANDLER_TA = INT_CTR_CS # INT_ENA_CS # INT_LATCH_CS # INT_CLEAR_CS;
END;

View File

@@ -0,0 +1,478 @@
TITLE "INTERRUPT HANDLER UND C1287";
-- CREATED BY FREDI ASCHWANDEN
INCLUDE "lpm_bustri_LONG.inc";
INCLUDE "lpm_bustri_BYT.inc";
-- Parameters Statement (optional)
-- {{ALTERA_PARAMETERS_BEGIN}} DO NOT REMOVE THIS LINE!
-- {{ALTERA_PARAMETERS_END}} DO NOT REMOVE THIS LINE!
-- Subdesign Section
SUBDESIGN interrupt_handler
(
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
MAIN_CLK : INPUT;
nFB_WR : INPUT;
nFB_CS1 : INPUT;
nFB_CS2 : INPUT;
FB_SIZE0 : INPUT;
FB_SIZE1 : INPUT;
FB_ADR[31..0] : INPUT;
PIC_INT : INPUT;
E0_INT : INPUT;
DVI_INT : INPUT;
nPCI_INTA : INPUT;
nPCI_INTB : INPUT;
nPCI_INTC : INPUT;
nPCI_INTD : INPUT;
nMFP_INT : INPUT;
nFB_OE : INPUT;
DSP_INT : INPUT;
VSYNC : INPUT;
HSYNC : INPUT;
DMA_DRQ : INPUT;
nIRQ[7..2] : OUTPUT;
INT_HANDLER_TA : OUTPUT;
ACP_CONF[31..0] : OUTPUT;
TIN0 : OUTPUT;
FB_AD[31..0] : BIDIR;
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
)
VARIABLE
FB_B[3..0] :NODE;
INT_CTR[31..0] :DFFE;
INT_CTR_CS :NODE;
INT_LATCH[31..0] :DFF;
INT_LATCH_CS :NODE;
INT_CLEAR[31..0] :DFF;
INT_CLEAR_CS :NODE;
INT_IN[31..0] :NODE;
INT_ENA[31..0] :DFFE;
INT_ENA_CS :NODE;
ACP_CONF[31..0] :DFFE;
ACP_CONF_CS :NODE;
PSEUDO_BUS_ERROR :NODE;
UHR_AS :NODE;
UHR_DS :NODE;
RTC_ADR[5..0] :DFFE;
ACHTELSEKUNDEN[2..0] :DFFE;
WERTE[7..0][63..0] :DFFE; -- WERTE REGISTER 0-63
PIC_INT_SYNC[2..0] :DFF;
INC_SEC :NODE;
INC_MIN :NODE;
INC_STD :NODE;
INC_TAG :NODE;
ANZAHL_TAGE_DES_MONATS[7..0]:NODE;
WINTERZEIT :NODE;
SOMMERZEIT :NODE;
INC_MONAT :NODE;
INC_JAHR :NODE;
UPDATE_ON :NODE;
BEGIN
-- BYT SELECT
FB_B0 = FB_SIZE1 & !FB_SIZE0 & !FB_ADR1 -- HWORD
# !FB_SIZE1 & FB_SIZE0 & !FB_ADR1 & !FB_ADR0 -- HHBYT
# !FB_SIZE1 & !FB_SIZE0 # FB_SIZE1 & FB_SIZE0; -- LONG UND LINE
FB_B1 = FB_SIZE1 & !FB_SIZE0 & !FB_ADR1 -- HWORD
# !FB_SIZE1 & FB_SIZE0 & !FB_ADR1 & FB_ADR0 -- HLBYT
# !FB_SIZE1 & !FB_SIZE0 # FB_SIZE1 & FB_SIZE0; -- LONG UND LINE
FB_B2 = FB_SIZE1 & !FB_SIZE0 & FB_ADR1 -- LWORD
# !FB_SIZE1 & FB_SIZE0 & FB_ADR1 & !FB_ADR0 -- LHBYT
# !FB_SIZE1 & !FB_SIZE0 # FB_SIZE1 & FB_SIZE0; -- LONG UND LINE
FB_B3 = FB_SIZE1 & !FB_SIZE0 & FB_ADR1 -- LWORD
# !FB_SIZE1 & FB_SIZE0 & FB_ADR1 & FB_ADR0 -- LLBYT
# !FB_SIZE1 & !FB_SIZE0 # FB_SIZE1 & FB_SIZE0; -- LONG UND LINE
-- INTERRUPT CONTROL REGISTER: BIT0=INT5 AUSL<53>SEN, 1=INT7 AUSL<53>SEN
INT_CTR[].CLK = MAIN_CLK;
INT_CTR_CS = !nFB_CS2 & FB_ADR[27..2]==H"4000"; -- $10000/4
INT_CTR[] = FB_AD[];
INT_CTR[31..24].ENA = INT_CTR_CS & FB_B0 & !nFB_WR;
INT_CTR[23..16].ENA = INT_CTR_CS & FB_B1 & !nFB_WR;
INT_CTR[15..8].ENA = INT_CTR_CS & FB_B2 & !nFB_WR;
INT_CTR[7..0].ENA = INT_CTR_CS & FB_B3 & !nFB_WR;
-- INTERRUPT ENABLE REGISTER BIT31=INT7,30=INT6,29=INT5,28=INT4,27=INT3,26=INT2
INT_ENA[].CLK = MAIN_CLK;
INT_ENA_CS = !nFB_CS2 & FB_ADR[27..2]==H"4001"; -- $10004/4
INT_ENA[] = FB_AD[];
INT_ENA[31..24].ENA = INT_ENA_CS & FB_B0 & !nFB_WR;
INT_ENA[23..16].ENA = INT_ENA_CS & FB_B1 & !nFB_WR;
INT_ENA[15..8].ENA = INT_ENA_CS & FB_B2 & !nFB_WR;
INT_ENA[7..0].ENA = INT_ENA_CS & FB_B3 & !nFB_WR;
-- INTERRUPT CLEAR REGISTER WRITE ONLY 1=INTERRUPT CLEAR
INT_CLEAR[].CLK = MAIN_CLK;
INT_CLEAR_CS = !nFB_CS2 & FB_ADR[27..2]==H"4002"; -- $10008/4
INT_CLEAR[31..24] = FB_AD[31..24] & INT_CLEAR_CS & FB_B0 & !nFB_WR;
INT_CLEAR[23..16] = FB_AD[23..16] & INT_CLEAR_CS & FB_B1 & !nFB_WR;
INT_CLEAR[15..8] = FB_AD[15..8] & INT_CLEAR_CS & FB_B2 & !nFB_WR;
INT_CLEAR[7..0] = FB_AD[7..0] & INT_CLEAR_CS & FB_B3 & !nFB_WR;
-- INTERRUPT LATCH REGISTER READ ONLY
INT_LATCH_CS = !nFB_CS2 & FB_ADR[27..2]==H"4003"; -- $1000C/4
-- INTERRUPT
!nIRQ2 = HSYNC & INT_ENA[26];
!nIRQ3 = INT_CTR0 & INT_ENA[27];
!nIRQ4 = VSYNC & INT_ENA[28];
nIRQ5 = INT_LATCH[]==H"00000000" & INT_ENA[29];
!nIRQ6 = !nMFP_INT & INT_ENA[30];
!nIRQ7 = PSEUDO_BUS_ERROR & INT_ENA[31];
PSEUDO_BUS_ERROR = !nFB_CS1 & (FB_ADR[19..4]==H"F8C8" -- SCC
# FB_ADR[19..4]==H"F8E0" -- VME
# FB_ADR[19..4]==H"F920" -- PADDLE
# FB_ADR[19..4]==H"F921" -- PADDLE
# FB_ADR[19..4]==H"F922" -- PADDLE
# FB_ADR[19..4]==H"FFA8" -- MFP2
# FB_ADR[19..4]==H"FFA9" -- MFP2
# FB_ADR[19..4]==H"FFAA" -- MFP2
# FB_ADR[19..4]==H"FFA8" -- MFP2
# FB_ADR[19..8]==H"F87" -- TT SCSI
# FB_ADR[19..4]==H"FFC2" -- ST UHR
# FB_ADR[19..4]==H"FFC3" -- ST UHR
# FB_ADR[19..4]==H"F890" -- DMA SOUND
# FB_ADR[19..4]==H"F891" -- DMA SOUND
# FB_ADR[19..4]==H"F892"); -- DMA SOUND
-- IF VIDEO ADR CHANGE
TIN0 = !nFB_CS1 & FB_ADR[19..1]==H"7C100"; -- VIDEO BASE ADR HIGH 0xFFFF8201/2
-- INTERRUPT LATCH
INT_LATCH[] = H"FFFFFFFF";
INT_LATCH0.CLK = PIC_INT & INT_ENA[0];
INT_LATCH1.CLK = E0_INT & INT_ENA[1];
INT_LATCH2.CLK = DVI_INT & INT_ENA[2];
INT_LATCH3.CLK = !nPCI_INTA & INT_ENA[3];
INT_LATCH4.CLK = !nPCI_INTB & INT_ENA[4];
INT_LATCH5.CLK = !nPCI_INTC & INT_ENA[5];
INT_LATCH6.CLK = !nPCI_INTD & INT_ENA[6];
INT_LATCH7.CLK = DSP_INT & INT_ENA[7];
INT_LATCH8.CLK = VSYNC & INT_ENA[8];
INT_LATCH9.CLK = HSYNC & INT_ENA[9];
-- INTERRUPT CLEAR
INT_LATCH[].CLRN = !INT_CLEAR[];
-- INT_IN
INT_IN0 = PIC_INT;
INT_IN1 = E0_INT;
INT_IN2 = DVI_INT;
INT_IN3 = !nPCI_INTA;
INT_IN4 = !nPCI_INTB;
INT_IN5 = !nPCI_INTC;
INT_IN6 = !nPCI_INTD;
INT_IN7 = DSP_INT;
INT_IN8 = VSYNC;
INT_IN9 = HSYNC;
INT_IN[25..10] = H"0";
INT_IN26 = HSYNC;
INT_IN27 = INT_CTR0;
INT_IN28 = VSYNC;
INT_IN29 = INT_LATCH[]!=H"00000000";
INT_IN30 = !nMFP_INT;
INT_IN31 = DMA_DRQ;
--***************************************************************************************
-- ACP CONFIG REGISTER: BIT 31-> 0=CF 1=IDE
ACP_CONF[].CLK = MAIN_CLK;
ACP_CONF_CS = !nFB_CS2 & FB_ADR[27..2]==H"10000"; -- $4'0000/4
ACP_CONF[] = FB_AD[];
ACP_CONF[31..24].ENA = ACP_CONF_CS & FB_B0 & !nFB_WR;
ACP_CONF[23..16].ENA = ACP_CONF_CS & FB_B1 & !nFB_WR;
ACP_CONF[15..8].ENA = ACP_CONF_CS & FB_B2 & !nFB_WR;
ACP_CONF[7..0].ENA = ACP_CONF_CS & FB_B3 & !nFB_WR;
--***************************************************************************************
--------------------------------------------------------------
-- C1287 0=SEK 2=MIN 4=STD 6=WOCHENTAG 7=TAG 8=MONAT 9=JAHR
----------------------------------------------------------
RTC_ADR[].CLK = MAIN_CLK;
RTC_ADR[] = FB_AD[21..16];
UHR_AS = !nFB_CS1 & FB_ADR[19..1]==H"7C4B0" & FB_B1; -- FFFF8961
UHR_DS = !nFB_CS1 & FB_ADR[19..1]==H"7C4B1" & FB_B3; -- FFFF8963
RTC_ADR[].ENA = UHR_AS & !nFB_WR;
WERTE[][].CLK = MAIN_CLK;
WERTE[7..0][0] = FB_AD[23..16] & RTC_ADR[]==0 & UHR_DS & !nFB_WR;
WERTE[7..0][1] = FB_AD[23..16];
WERTE[7..0][2] = FB_AD[23..16] & RTC_ADR[]==2 & UHR_DS & !nFB_WR;
WERTE[7..0][3] = FB_AD[23..16];
WERTE[7..0][4] = FB_AD[23..16] & RTC_ADR[]==4 & UHR_DS & !nFB_WR;
WERTE[7..0][5] = FB_AD[23..16];
WERTE[7..0][6] = FB_AD[23..16] & RTC_ADR[]==6 & UHR_DS & !nFB_WR;
WERTE[7..0][7] = FB_AD[23..16] & RTC_ADR[]==7 & UHR_DS & !nFB_WR;
WERTE[7..0][8] = FB_AD[23..16] & RTC_ADR[]==8 & UHR_DS & !nFB_WR;
WERTE[7..0][9] = FB_AD[23..16] & RTC_ADR[]==9 & UHR_DS & !nFB_WR;
WERTE[7..0][10] = FB_AD[23..16];
WERTE[7..0][11] = FB_AD[23..16];
WERTE[7..0][12] = FB_AD[23..16];
WERTE[7..0][13] = FB_AD[23..16];
WERTE[7..0][14] = FB_AD[23..16];
WERTE[7..0][15] = FB_AD[23..16];
WERTE[7..0][16] = FB_AD[23..16];
WERTE[7..0][17] = FB_AD[23..16];
WERTE[7..0][18] = FB_AD[23..16];
WERTE[7..0][19] = FB_AD[23..16];
WERTE[7..0][20] = FB_AD[23..16];
WERTE[7..0][21] = FB_AD[23..16];
WERTE[7..0][22] = FB_AD[23..16];
WERTE[7..0][23] = FB_AD[23..16];
WERTE[7..0][24] = FB_AD[23..16];
WERTE[7..0][25] = FB_AD[23..16];
WERTE[7..0][26] = FB_AD[23..16];
WERTE[7..0][27] = FB_AD[23..16];
WERTE[7..0][28] = FB_AD[23..16];
WERTE[7..0][29] = FB_AD[23..16];
WERTE[7..0][30] = FB_AD[23..16];
WERTE[7..0][31] = FB_AD[23..16];
WERTE[7..0][32] = FB_AD[23..16];
WERTE[7..0][33] = FB_AD[23..16];
WERTE[7..0][34] = FB_AD[23..16];
WERTE[7..0][35] = FB_AD[23..16];
WERTE[7..0][36] = FB_AD[23..16];
WERTE[7..0][37] = FB_AD[23..16];
WERTE[7..0][38] = FB_AD[23..16];
WERTE[7..0][39] = FB_AD[23..16];
WERTE[7..0][40] = FB_AD[23..16];
WERTE[7..0][41] = FB_AD[23..16];
WERTE[7..0][42] = FB_AD[23..16];
WERTE[7..0][43] = FB_AD[23..16];
WERTE[7..0][44] = FB_AD[23..16];
WERTE[7..0][45] = FB_AD[23..16];
WERTE[7..0][46] = FB_AD[23..16];
WERTE[7..0][47] = FB_AD[23..16];
WERTE[7..0][48] = FB_AD[23..16];
WERTE[7..0][49] = FB_AD[23..16];
WERTE[7..0][50] = FB_AD[23..16];
WERTE[7..0][51] = FB_AD[23..16];
WERTE[7..0][52] = FB_AD[23..16];
WERTE[7..0][53] = FB_AD[23..16];
WERTE[7..0][54] = FB_AD[23..16];
WERTE[7..0][55] = FB_AD[23..16];
WERTE[7..0][56] = FB_AD[23..16];
WERTE[7..0][57] = FB_AD[23..16];
WERTE[7..0][58] = FB_AD[23..16];
WERTE[7..0][59] = FB_AD[23..16];
WERTE[7..0][60] = FB_AD[23..16];
WERTE[7..0][61] = FB_AD[23..16];
WERTE[7..0][62] = FB_AD[23..16];
WERTE[7..0][63] = FB_AD[23..16];
WERTE[][0].ENA = RTC_ADR[]==0 & UHR_DS & !nFB_WR;
WERTE[][1].ENA = RTC_ADR[]==1 & UHR_DS & !nFB_WR;
WERTE[][2].ENA = RTC_ADR[]==2 & UHR_DS & !nFB_WR;
WERTE[][3].ENA = RTC_ADR[]==3 & UHR_DS & !nFB_WR;
WERTE[][4].ENA = RTC_ADR[]==4 & UHR_DS & !nFB_WR;
WERTE[][5].ENA = RTC_ADR[]==5 & UHR_DS & !nFB_WR;
WERTE[][6].ENA = RTC_ADR[]==6 & UHR_DS & !nFB_WR;
WERTE[][7].ENA = RTC_ADR[]==7 & UHR_DS & !nFB_WR;
WERTE[][8].ENA = RTC_ADR[]==8 & UHR_DS & !nFB_WR;
WERTE[][9].ENA = RTC_ADR[]==9 & UHR_DS & !nFB_WR;
WERTE[][10].ENA = RTC_ADR[]==10 & UHR_DS & !nFB_WR;
WERTE[][11].ENA = RTC_ADR[]==11 & UHR_DS & !nFB_WR;
WERTE[][12].ENA = RTC_ADR[]==12 & UHR_DS & !nFB_WR;
WERTE[][13].ENA = RTC_ADR[]==13 & UHR_DS & !nFB_WR;
WERTE[][14].ENA = RTC_ADR[]==14 & UHR_DS & !nFB_WR;
WERTE[][15].ENA = RTC_ADR[]==15 & UHR_DS & !nFB_WR;
WERTE[][16].ENA = RTC_ADR[]==16 & UHR_DS & !nFB_WR;
WERTE[][17].ENA = RTC_ADR[]==17 & UHR_DS & !nFB_WR;
WERTE[][18].ENA = RTC_ADR[]==18 & UHR_DS & !nFB_WR;
WERTE[][19].ENA = RTC_ADR[]==19 & UHR_DS & !nFB_WR;
WERTE[][20].ENA = RTC_ADR[]==20 & UHR_DS & !nFB_WR;
WERTE[][21].ENA = RTC_ADR[]==21 & UHR_DS & !nFB_WR;
WERTE[][22].ENA = RTC_ADR[]==22 & UHR_DS & !nFB_WR;
WERTE[][23].ENA = RTC_ADR[]==23 & UHR_DS & !nFB_WR;
WERTE[][24].ENA = RTC_ADR[]==24 & UHR_DS & !nFB_WR;
WERTE[][25].ENA = RTC_ADR[]==25 & UHR_DS & !nFB_WR;
WERTE[][26].ENA = RTC_ADR[]==26 & UHR_DS & !nFB_WR;
WERTE[][27].ENA = RTC_ADR[]==27 & UHR_DS & !nFB_WR;
WERTE[][28].ENA = RTC_ADR[]==28 & UHR_DS & !nFB_WR;
WERTE[][29].ENA = RTC_ADR[]==29 & UHR_DS & !nFB_WR;
WERTE[][30].ENA = RTC_ADR[]==30 & UHR_DS & !nFB_WR;
WERTE[][31].ENA = RTC_ADR[]==31 & UHR_DS & !nFB_WR;
WERTE[][32].ENA = RTC_ADR[]==32 & UHR_DS & !nFB_WR;
WERTE[][33].ENA = RTC_ADR[]==33 & UHR_DS & !nFB_WR;
WERTE[][34].ENA = RTC_ADR[]==34 & UHR_DS & !nFB_WR;
WERTE[][35].ENA = RTC_ADR[]==35 & UHR_DS & !nFB_WR;
WERTE[][36].ENA = RTC_ADR[]==36 & UHR_DS & !nFB_WR;
WERTE[][37].ENA = RTC_ADR[]==37 & UHR_DS & !nFB_WR;
WERTE[][38].ENA = RTC_ADR[]==38 & UHR_DS & !nFB_WR;
WERTE[][39].ENA = RTC_ADR[]==39 & UHR_DS & !nFB_WR;
WERTE[][40].ENA = RTC_ADR[]==40 & UHR_DS & !nFB_WR;
WERTE[][41].ENA = RTC_ADR[]==41 & UHR_DS & !nFB_WR;
WERTE[][42].ENA = RTC_ADR[]==42 & UHR_DS & !nFB_WR;
WERTE[][43].ENA = RTC_ADR[]==43 & UHR_DS & !nFB_WR;
WERTE[][44].ENA = RTC_ADR[]==44 & UHR_DS & !nFB_WR;
WERTE[][45].ENA = RTC_ADR[]==45 & UHR_DS & !nFB_WR;
WERTE[][46].ENA = RTC_ADR[]==46 & UHR_DS & !nFB_WR;
WERTE[][47].ENA = RTC_ADR[]==47 & UHR_DS & !nFB_WR;
WERTE[][48].ENA = RTC_ADR[]==48 & UHR_DS & !nFB_WR;
WERTE[][49].ENA = RTC_ADR[]==49 & UHR_DS & !nFB_WR;
WERTE[][50].ENA = RTC_ADR[]==50 & UHR_DS & !nFB_WR;
WERTE[][51].ENA = RTC_ADR[]==51 & UHR_DS & !nFB_WR;
WERTE[][52].ENA = RTC_ADR[]==52 & UHR_DS & !nFB_WR;
WERTE[][53].ENA = RTC_ADR[]==53 & UHR_DS & !nFB_WR;
WERTE[][54].ENA = RTC_ADR[]==54 & UHR_DS & !nFB_WR;
WERTE[][55].ENA = RTC_ADR[]==55 & UHR_DS & !nFB_WR;
WERTE[][56].ENA = RTC_ADR[]==56 & UHR_DS & !nFB_WR;
WERTE[][57].ENA = RTC_ADR[]==57 & UHR_DS & !nFB_WR;
WERTE[][58].ENA = RTC_ADR[]==58 & UHR_DS & !nFB_WR;
WERTE[][59].ENA = RTC_ADR[]==59 & UHR_DS & !nFB_WR;
WERTE[][60].ENA = RTC_ADR[]==60 & UHR_DS & !nFB_WR;
WERTE[][61].ENA = RTC_ADR[]==61 & UHR_DS & !nFB_WR;
WERTE[][62].ENA = RTC_ADR[]==62 & UHR_DS & !nFB_WR;
WERTE[][63].ENA = RTC_ADR[]==63 & UHR_DS & !nFB_WR;
PIC_INT_SYNC[].CLK = MAIN_CLK; PIC_INT_SYNC[0] = PIC_INT;
PIC_INT_SYNC[1] = PIC_INT_SYNC[0];
PIC_INT_SYNC[2] = !PIC_INT_SYNC[1] & PIC_INT_SYNC[0];
UPDATE_ON = !WERTE[7][11];
WERTE[6][10].CLRN = GND; -- KEIN UIP
UPDATE_ON = !WERTE[7][11]; -- UPDATE ON OFF
WERTE[2][11] = VCC; -- IMMER BINARY
WERTE[1][11] = VCC; -- IMMER 24H FORMAT
WERTE[0][11] = VCC; -- IMMER SOMMERZEITKORREKTUR
WERTE[7][13] = VCC; -- IMMER RICHTIG
-- SOMMER WINTERZEIT: BIT 0 IM REGISTER D IST DIE INFORMATION OB SOMMERZEIT IST (BRAUCHT MAN F<>R R<>CKSCHALTUNG)
SOMMERZEIT = WERTE[][6]==1 & WERTE[][4]==1 & WERTE[][8]==4 & WERTE[][7]>23; --LETZTER SONNTAG IM APRIL
WERTE[0][13] = SOMMERZEIT;
WERTE[0][13].ENA = INC_STD & (SOMMERZEIT # WINTERZEIT);
WINTERZEIT = WERTE[][6]==1 & WERTE[][4]==1 & WERTE[][8]==10 & WERTE[][7]>24 & WERTE[0][13]; --LETZTER SONNTAG IM OKTOBER
-- ACHTELSEKUNDEN
ACHTELSEKUNDEN[].CLK = MAIN_CLK;
ACHTELSEKUNDEN[] = ACHTELSEKUNDEN[]+1;
ACHTELSEKUNDEN[].ENA = PIC_INT_SYNC[2] & UPDATE_ON;
-- SEKUNDEN
INC_SEC = ACHTELSEKUNDEN[]==7 & PIC_INT_SYNC[2] & UPDATE_ON;
WERTE[][0] = (WERTE[][0]+1) & WERTE[][0]!=59 & !(RTC_ADR[]==0 & UHR_DS & !nFB_WR); -- SEKUNDEN Z<>HLEN BIS 59
WERTE[][0].ENA = INC_SEC & !(RTC_ADR[]==0 & UHR_DS & !nFB_WR);
-- MINUTEN
INC_MIN = INC_SEC & WERTE[][0]==59; --
WERTE[][2] = (WERTE[][2]+1) & WERTE[][2]!=59 & !(RTC_ADR[]==2 & UHR_DS & !nFB_WR); -- MINUTEN Z<>HLEN BIS 59
WERTE[][2].ENA = INC_MIN & !(RTC_ADR[]==2 & UHR_DS & !nFB_WR); --
-- STUNDEN
INC_STD = INC_MIN & WERTE[][2]==59;
WERTE[][4] = (WERTE[][4]+1+(1 & SOMMERZEIT)) & WERTE[][4]!=23 & !(RTC_ADR[]==4 & UHR_DS & !nFB_WR); -- STUNDEN Z<>HLEN BIS 23
WERTE[][4].ENA = INC_STD & !(WINTERZEIT & WERTE[0][12]) & !(RTC_ADR[]==4 & UHR_DS & !nFB_WR); -- EINE STUNDE AUSLASSEN WENN WINTERZEITUMSCHALTUNG UND NOCH SOMMERZEIT
-- WOCHENTAG UND TAG
INC_TAG = INC_STD & WERTE[][2]==23;
WERTE[][6] = (WERTE[][6]+1) & WERTE[][6]!=7 & !(RTC_ADR[]==6 & UHR_DS & !nFB_WR) -- WOCHENTAG Z<>HLEN BIS 7
# 1 & WERTE[][6]==7 & !(RTC_ADR[]==6 & UHR_DS & !nFB_WR); -- DANN BEI 1 WEITER
WERTE[][6].ENA = INC_TAG & !(RTC_ADR[]==6 & UHR_DS & !nFB_WR);
ANZAHL_TAGE_DES_MONATS[] = 31 & (WERTE[][8]==1 # WERTE[][8]==3 # WERTE[][8]==5 # WERTE[][8]==7 # WERTE[][8]==8 # WERTE[][8]==10 # WERTE[][8]==12)
# 30 & (WERTE[][8]==4 # WERTE[][8]==6 # WERTE[][8]==9 # WERTE[][8]==11)
# 29 & WERTE[][8]==2 & WERTE[1..0][9]==0
# 28 & WERTE[][8]==2 & WERTE[1..0][9]!=0;
WERTE[][7] = (WERTE[][7]+1) & WERTE[][7]!=ANZAHL_TAGE_DES_MONATS[] & !(RTC_ADR[]==7 & UHR_DS & !nFB_WR) -- TAG Z<>HLEN BIS MONATSENDE
# 1 & WERTE[][7]==ANZAHL_TAGE_DES_MONATS[] & !(RTC_ADR[]==7 & UHR_DS & !nFB_WR); -- DANN BEI 1 WEITER
WERTE[][7].ENA = INC_TAG & !(RTC_ADR[]==7 & UHR_DS & !nFB_WR); --
-- MONATE
INC_MONAT = INC_TAG & WERTE[][7]==ANZAHL_TAGE_DES_MONATS[]; --
WERTE[][8] = (WERTE[][8]+1) & WERTE[][8]!=12 & !(RTC_ADR[]==8 & UHR_DS & !nFB_WR) -- MONATE Z<>HLEN BIS 12
# 1 & WERTE[][8]==12 & !(RTC_ADR[]==8 & UHR_DS & !nFB_WR); -- DANN BEI 1 WEITER
WERTE[][8].ENA = INC_MONAT & !(RTC_ADR[]==8 & UHR_DS & !nFB_WR);
-- JAHR
INC_JAHR = INC_MONAT & WERTE[][8]==12; --
WERTE[][9] = (WERTE[][9]+1) & WERTE[][9]!=99 & !(RTC_ADR[]==9 & UHR_DS & !nFB_WR); -- JAHRE Z<>HLEN BIS 99
WERTE[][9].ENA = INC_JAHR & !(RTC_ADR[]==9 & UHR_DS & !nFB_WR);
-- TRISTATE OUTPUT
FB_AD[31..24] = lpm_bustri_BYT(
INT_CTR_CS & INT_CTR[31..24]
# INT_ENA_CS & INT_ENA[31..24]
# INT_LATCH_CS & INT_LATCH[31..24]
# INT_CLEAR_CS & INT_IN[31..24]
# ACP_CONF_CS & ACP_CONF[31..24]
,(INT_CTR_CS # INT_ENA_CS # INT_LATCH_CS # INT_CLEAR_CS # ACP_CONF_CS) & !nFB_OE);
FB_AD[23..16] = lpm_bustri_BYT(
WERTE[][0] & RTC_ADR[]==0 & UHR_DS
# WERTE[][1] & RTC_ADR[]==1 & UHR_DS
# WERTE[][2] & RTC_ADR[]==2 & UHR_DS
# WERTE[][3] & RTC_ADR[]==3 & UHR_DS
# WERTE[][4] & RTC_ADR[]==4 & UHR_DS
# WERTE[][5] & RTC_ADR[]==5 & UHR_DS
# WERTE[][6] & RTC_ADR[]==6 & UHR_DS
# WERTE[][7] & RTC_ADR[]==7 & UHR_DS
# WERTE[][8] & RTC_ADR[]==8 & UHR_DS
# WERTE[][9] & RTC_ADR[]==9 & UHR_DS
# WERTE[][10] & RTC_ADR[]==10 & UHR_DS
# WERTE[][11] & RTC_ADR[]==11 & UHR_DS
# WERTE[][12] & RTC_ADR[]==12 & UHR_DS
# WERTE[][13] & RTC_ADR[]==13 & UHR_DS
# WERTE[][14] & RTC_ADR[]==14 & UHR_DS
# WERTE[][15] & RTC_ADR[]==15 & UHR_DS
# WERTE[][16] & RTC_ADR[]==16 & UHR_DS
# WERTE[][17] & RTC_ADR[]==17 & UHR_DS
# WERTE[][18] & RTC_ADR[]==18 & UHR_DS
# WERTE[][19] & RTC_ADR[]==19 & UHR_DS
# WERTE[][20] & RTC_ADR[]==20 & UHR_DS
# WERTE[][21] & RTC_ADR[]==21 & UHR_DS
# WERTE[][22] & RTC_ADR[]==22 & UHR_DS
# WERTE[][23] & RTC_ADR[]==23 & UHR_DS
# WERTE[][24] & RTC_ADR[]==24 & UHR_DS
# WERTE[][25] & RTC_ADR[]==25 & UHR_DS
# WERTE[][26] & RTC_ADR[]==26 & UHR_DS
# WERTE[][27] & RTC_ADR[]==27 & UHR_DS
# WERTE[][28] & RTC_ADR[]==28 & UHR_DS
# WERTE[][29] & RTC_ADR[]==29 & UHR_DS
# WERTE[][30] & RTC_ADR[]==30 & UHR_DS
# WERTE[][31] & RTC_ADR[]==31 & UHR_DS
# WERTE[][32] & RTC_ADR[]==32 & UHR_DS
# WERTE[][33] & RTC_ADR[]==33 & UHR_DS
# WERTE[][34] & RTC_ADR[]==34 & UHR_DS
# WERTE[][35] & RTC_ADR[]==35 & UHR_DS
# WERTE[][36] & RTC_ADR[]==36 & UHR_DS
# WERTE[][37] & RTC_ADR[]==37 & UHR_DS
# WERTE[][38] & RTC_ADR[]==38 & UHR_DS
# WERTE[][39] & RTC_ADR[]==39 & UHR_DS
# WERTE[][40] & RTC_ADR[]==40 & UHR_DS
# WERTE[][41] & RTC_ADR[]==41 & UHR_DS
# WERTE[][42] & RTC_ADR[]==42 & UHR_DS
# WERTE[][43] & RTC_ADR[]==43 & UHR_DS
# WERTE[][44] & RTC_ADR[]==44 & UHR_DS
# WERTE[][45] & RTC_ADR[]==45 & UHR_DS
# WERTE[][46] & RTC_ADR[]==46 & UHR_DS
# WERTE[][47] & RTC_ADR[]==47 & UHR_DS
# WERTE[][48] & RTC_ADR[]==48 & UHR_DS
# WERTE[][49] & RTC_ADR[]==49 & UHR_DS
# WERTE[][50] & RTC_ADR[]==50 & UHR_DS
# WERTE[][51] & RTC_ADR[]==51 & UHR_DS
# WERTE[][52] & RTC_ADR[]==52 & UHR_DS
# WERTE[][53] & RTC_ADR[]==53 & UHR_DS
# WERTE[][54] & RTC_ADR[]==54 & UHR_DS
# WERTE[][55] & RTC_ADR[]==55 & UHR_DS
# WERTE[][56] & RTC_ADR[]==56 & UHR_DS
# WERTE[][57] & RTC_ADR[]==57 & UHR_DS
# WERTE[][58] & RTC_ADR[]==58 & UHR_DS
# WERTE[][59] & RTC_ADR[]==59 & UHR_DS
# WERTE[][60] & RTC_ADR[]==60 & UHR_DS
# WERTE[][61] & RTC_ADR[]==61 & UHR_DS
# WERTE[][62] & RTC_ADR[]==62 & UHR_DS
# WERTE[][63] & RTC_ADR[]==63 & UHR_DS
# (0,RTC_ADR[]) & UHR_AS
# INT_CTR_CS & INT_CTR[23..16]
# INT_ENA_CS & INT_ENA[23..16]
# INT_LATCH_CS & INT_LATCH[23..16]
# INT_CLEAR_CS & INT_IN[23..16]
# ACP_CONF_CS & ACP_CONF[23..16]
,(UHR_DS # UHR_AS # INT_CTR_CS # INT_ENA_CS # INT_LATCH_CS # INT_CLEAR_CS # ACP_CONF_CS) & !nFB_OE);
FB_AD[15..8] = lpm_bustri_BYT(
INT_CTR_CS & INT_CTR[15..8]
# INT_ENA_CS & INT_ENA[15..8]
# INT_LATCH_CS & INT_LATCH[15..8]
# INT_CLEAR_CS & INT_IN[15..8]
# ACP_CONF_CS & ACP_CONF[15..8]
,(INT_CTR_CS # INT_ENA_CS # INT_LATCH_CS # INT_CLEAR_CS # ACP_CONF_CS) & !nFB_OE);
FB_AD[7..0] = lpm_bustri_BYT(
INT_CTR_CS & INT_CTR[7..0]
# INT_ENA_CS & INT_ENA[7..0]
# INT_LATCH_CS & INT_LATCH[7..0]
# INT_CLEAR_CS & INT_IN[7..0]
# ACP_CONF_CS & ACP_CONF[7..0]
,(INT_CTR_CS # INT_ENA_CS # INT_LATCH_CS # INT_CLEAR_CS # ACP_CONF_CS) & !nFB_OE);
INT_HANDLER_TA = INT_CTR_CS # INT_ENA_CS # INT_LATCH_CS # INT_CLEAR_CS;
END;

27
FPGA_Quartus_13.1/UNUSED Normal file
View File

@@ -0,0 +1,27 @@
-- Clearbox generated Memory Initialization File (.mif)
WIDTH=3;
DEPTH=16;
ADDRESS_RADIX=HEX;
DATA_RADIX=HEX;
CONTENT BEGIN
00 : 7;
01 : 6;
02 : 5;
03 : 4;
04 : 3;
05 : 2;
06 : 1;
07 : 0;
08 : 7;
09 : 6;
0a : 5;
0b : 4;
0c : 3;
0d : 2;
0e : 1;
0f : 0;
END;

View File

@@ -0,0 +1,75 @@
-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.
-- Copyright (C) 1991-2008 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- Generated by Quartus II Version 8.1 (Build Build 163 10/28/2008)
-- Created on Fri Oct 16 15:40:59 2009
LIBRARY ieee;
USE ieee.std_logic_1164.all;
-- Entity Declaration
ENTITY BLITTER IS
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
PORT
(
nRSTO : IN STD_LOGIC;
MAIN_CLK : IN STD_LOGIC;
FB_ALE : IN STD_LOGIC;
nFB_WR : IN STD_LOGIC;
nFB_OE : IN STD_LOGIC;
FB_SIZE0 : IN STD_LOGIC;
FB_SIZE1 : IN STD_LOGIC;
VIDEO_RAM_CTR : IN STD_LOGIC_VECTOR(15 downto 0);
BLITTER_ON : IN STD_LOGIC;
FB_ADR : IN STD_LOGIC_VECTOR(31 downto 0);
nFB_CS1 : IN STD_LOGIC;
nFB_CS2 : IN STD_LOGIC;
nFB_CS3 : IN STD_LOGIC;
DDRCLK0 : IN STD_LOGIC;
BLITTER_DIN : IN STD_LOGIC_VECTOR(127 downto 0);
BLITTER_DACK : IN STD_LOGIC_VECTOR(4 downto 0);
BLITTER_RUN : OUT STD_LOGIC;
BLITTER_DOUT : OUT STD_LOGIC_VECTOR(127 downto 0);
BLITTER_ADR : OUT STD_LOGIC_VECTOR(31 downto 0);
BLITTER_SIG : OUT STD_LOGIC;
BLITTER_WR : OUT STD_LOGIC;
BLITTER_TA : OUT STD_LOGIC;
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0)
);
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
END BLITTER;
-- Architecture Body
ARCHITECTURE BLITTER_architecture OF BLITTER IS
BEGIN
BLITTER_RUN <= '0';
BLITTER_DOUT <= x"FEDCBA9876543210F0F0F0F0F0F0F0F0";
BLITTER_ADR <= x"76543210";
BLITTER_SIG <= '0';
BLITTER_WR <= '0';
BLITTER_TA <= '0';
END BLITTER_architecture;

View File

@@ -0,0 +1,75 @@
-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.
-- Copyright (C) 1991-2008 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- Generated by Quartus II Version 8.1 (Build Build 163 10/28/2008)
-- Created on Fri Oct 16 15:40:59 2009
LIBRARY ieee;
USE ieee.std_logic_1164.all;
-- Entity Declaration
ENTITY BLITTER IS
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
PORT
(
nRSTO : IN STD_LOGIC;
MAIN_CLK : IN STD_LOGIC;
FB_ALE : IN STD_LOGIC;
nFB_WR : IN STD_LOGIC;
nFB_OE : IN STD_LOGIC;
FB_SIZE0 : IN STD_LOGIC;
FB_SIZE1 : IN STD_LOGIC;
VIDEO_RAM_CTR : IN STD_LOGIC_VECTOR(15 downto 0);
BLITTER_ON : IN STD_LOGIC;
FB_ADR : IN STD_LOGIC_VECTOR(31 downto 0);
nFB_CS1 : IN STD_LOGIC;
nFB_CS2 : IN STD_LOGIC;
nFB_CS3 : IN STD_LOGIC;
DDRCLK0 : IN STD_LOGIC;
BLITTER_DIN : IN STD_LOGIC_VECTOR(127 downto 0);
BLITTER_DACK : IN STD_LOGIC_VECTOR(4 downto 0);
BLITTER_RUN : OUT STD_LOGIC;
BLITTER_DOUT : OUT STD_LOGIC_VECTOR(127 downto 0);
BLITTER_ADR : OUT STD_LOGIC_VECTOR(31 downto 0);
BLITTER_SIG : OUT STD_LOGIC;
BLITTER_WR : OUT STD_LOGIC;
BLITTER_TA : OUT STD_LOGIC;
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0)
);
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
END BLITTER;
-- Architecture Body
ARCHITECTURE BLITTER_architecture OF BLITTER IS
BEGIN
BLITTER_RUN <= '0';
BLITTER_DOUT <= x"FEDCBA9876543210F0F0F0F0F0F0F0F0";
BLITTER_ADR <= x"FEDCBA9876543210";
BLITTER_SIG <= '0';
BLITTER_WR <= '0';
BLITTER_TA <= '0';
END BLITTER_architecture;

View File

@@ -0,0 +1,659 @@
TITLE "DDR_CTR";
-- CREATED BY FREDI ASCHWANDEN
INCLUDE "lpm_bustri_BYT.inc";
-- FIFO WATER MARK
CONSTANT FIFO_LWM = 0;
CONSTANT FIFO_MWM = 200;
CONSTANT FIFO_HWM = 500;
-- {{ALTERA_PARAMETERS_BEGIN}} DO NOT REMOVE THIS LINE!
-- {{ALTERA_PARAMETERS_END}} DO NOT REMOVE THIS LINE!
SUBDESIGN DDR_CTR
(
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
FB_ADR[31..0] : INPUT;
nFB_CS1 : INPUT;
nFB_CS2 : INPUT;
nFB_CS3 : INPUT;
nFB_OE : INPUT;
FB_SIZE0 : INPUT;
FB_SIZE1 : INPUT;
nRSTO : INPUT;
MAIN_CLK : INPUT;
FB_ALE : INPUT;
nFB_WR : INPUT;
DDR_SYNC_66M : INPUT;
CLR_FIFO : INPUT;
VIDEO_RAM_CTR[15..0] : INPUT;
BLITTER_ADR[31..0] : INPUT;
BLITTER_SIG : INPUT;
BLITTER_WR : INPUT;
DDRCLK0 : INPUT;
CLK33M : INPUT;
FIFO_MW[8..0] : INPUT;
VA[12..0] : OUTPUT;
nVWE : OUTPUT;
nVRAS : OUTPUT;
nVCS : OUTPUT;
VCKE : OUTPUT;
nVCAS : OUTPUT;
FB_LE[3..0] : OUTPUT;
FB_VDOE[3..0] : OUTPUT;
SR_FIFO_WRE : OUTPUT;
SR_DDR_FB : OUTPUT;
SR_DDR_WR : OUTPUT;
SR_DDRWR_D_SEL : OUTPUT;
SR_VDMP[7..0] : OUTPUT;
VIDEO_DDR_TA : OUTPUT;
SR_BLITTER_DACK : OUTPUT;
BA[1..0] : OUTPUT;
DDRWR_D_SEL1 : OUTPUT;
VDM_SEL[3..0] : OUTPUT;
FB_AD[31..0] : BIDIR;
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
)
VARIABLE
FB_REGDDR :MACHINE WITH STATES(FR_WAIT,FR_S0,FR_S1,FR_S2,FR_S3);
DDR_SM :MACHINE WITH STATES(DS_T1,DS_T2A,DS_T2B,DS_T3,DS_N5,DS_N6, DS_N7, DS_N8, -- START (NORMAL 8 CYCLES TOTAL = 60ns)
DS_C2,DS_C3,DS_C4, DS_C5, DS_C6, DS_C7, -- CONFIG
DS_T4R,DS_T5R, -- READ CPU UND BLITTER,
DS_T4W,DS_T5W,DS_T6W,DS_T7W,DS_T8W,DS_T9W, -- WRITE CPU UND BLITTER
DS_T4F,DS_T5F,DS_T6F,DS_T7F,DS_T8F,DS_T9F,DS_T10F, -- READ FIFO
DS_CB6, DS_CB8, -- CLOSE FIFO BANK
DS_R2,DS_R3,DS_R4, DS_R5, DS_R6); -- REFRESH 10X7.5NS=75NS
LINE :NODE;
FB_B[3..0] :NODE;
VCAS :NODE;
VRAS :NODE;
VWE :NODE;
VA_P[12..0] :DFF;
BA_P[1..0] :DFF;
VA_S[12..0] :DFF;
BA_S[1..0] :DFF;
MCS[1..0] :DFF;
CPU_DDR_SYNC :DFF;
DDR_SEL :NODE;
DDR_CS :DFFE;
DDR_CONFIG :NODE;
SR_DDR_WR :DFF;
SR_DDRWR_D_SEL :DFF;
SR_VDMP[7..0] :DFF;
CPU_ROW_ADR[12..0] :NODE;
CPU_BA[1..0] :NODE;
CPU_COL_ADR[9..0] :NODE;
CPU_SIG :NODE;
CPU_REQ :DFF;
CPU_AC :DFF;
BUS_CYC :DFF;
BUS_CYC_END :NODE;
BLITTER_REQ :DFF;
BLITTER_AC :DFF;
BLITTER_ROW_ADR[12..0] :NODE;
BLITTER_BA[1..0] :NODE;
BLITTER_COL_ADR[9..0] :NODE;
FIFO_REQ :DFF;
FIFO_AC :DFF;
FIFO_ROW_ADR[12..0] :NODE;
FIFO_BA[1..0] :NODE;
FIFO_COL_ADR[9..0] :NODE;
FIFO_ACTIVE :NODE;
CLR_FIFO_SYNC :DFF;
CLEAR_FIFO_CNT :DFF;
STOP :DFF;
SR_FIFO_WRE :DFF;
FIFO_BANK_OK :DFF;
FIFO_BANK_NOT_OK :NODE;
DDR_REFRESH_ON :NODE;
DDR_REFRESH_CNT[10..0] :DFF;
DDR_REFRESH_REQ :DFF;
DDR_REFRESH_SIG[3..0] :DFFE;
REFRESH_TIME :DFF;
VIDEO_BASE_L_D[7..0] :DFFE;
VIDEO_BASE_L :NODE;
VIDEO_BASE_M_D[7..0] :DFFE;
VIDEO_BASE_M :NODE;
VIDEO_BASE_H_D[7..0] :DFFE;
VIDEO_BASE_H :NODE;
VIDEO_BASE_X_D[2..0] :DFFE;
VIDEO_ADR_CNT[22..0] :DFFE;
VIDEO_CNT_L :NODE;
VIDEO_CNT_M :NODE;
VIDEO_CNT_H :NODE;
VIDEO_BASE_ADR[22..0] :NODE;
VIDEO_ACT_ADR[26..0] :NODE;
BEGIN
LINE = FB_SIZE0 & FB_SIZE1;
-- BYT SELECT
FB_B0 = FB_ADR[1..0]==0 -- ADR==0
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B1 = FB_ADR[1..0]==1 -- ADR==1
# FB_SIZE1 & !FB_SIZE0 & !FB_ADR1 -- HIGH WORD
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B2 = FB_ADR[1..0]==2 -- ADR==2
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B3 = FB_ADR[1..0]==3 -- ADR==3
# FB_SIZE1 & !FB_SIZE0 & FB_ADR1 -- LOW WORD
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
-- CPU READ (REG DDR => CPU) AND WRITE (CPU => REG DDR) --------------------------------------------------
FB_REGDDR.CLK = MAIN_CLK;
CASE FB_REGDDR IS
WHEN FR_WAIT =>
FB_LE0 = !nFB_WR;
IF BUS_CYC # DDR_SEL & LINE & !nFB_WR THEN -- LOS WENN BEREIT ODER IMMER BEI LINE WRITE
FB_REGDDR = FR_S0;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
WHEN FR_S0 =>
IF DDR_CS THEN
FB_LE0 = !nFB_WR;
VIDEO_DDR_TA = VCC;
IF LINE THEN
FB_VDOE0 = !nFB_OE & !DDR_CONFIG;
FB_REGDDR = FR_S1;
ELSE
BUS_CYC_END = VCC;
FB_VDOE0 = !nFB_OE & !MAIN_CLK & !DDR_CONFIG;
FB_REGDDR = FR_WAIT;
END IF;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
WHEN FR_S1 =>
IF DDR_CS THEN
FB_VDOE1 = !nFB_OE & !DDR_CONFIG;
FB_LE1 = !nFB_WR;
VIDEO_DDR_TA = VCC;
FB_REGDDR = FR_S2;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
WHEN FR_S2 =>
IF DDR_CS THEN
FB_VDOE2 = !nFB_OE & !DDR_CONFIG;
FB_LE2 = !nFB_WR;
IF !BUS_CYC & LINE & !nFB_WR THEN -- BEI LINE WRITE EVT. WARTEN
FB_REGDDR = FR_S2;
ELSE
VIDEO_DDR_TA = VCC;
FB_REGDDR = FR_S3;
END IF;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
WHEN FR_S3 =>
IF DDR_CS THEN
FB_VDOE3 = !nFB_OE & !MAIN_CLK & !DDR_CONFIG;
FB_LE3 = !nFB_WR;
VIDEO_DDR_TA = VCC;
BUS_CYC_END = VCC;
FB_REGDDR = FR_WAIT;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
END CASE;
-- DDR STEUERUNG -----------------------------------------------------
-- VIDEO RAM CONTROL REGISTER (IST IN VIDEO_MUX_CTR) $F0000400: BIT 0: VCKE; 1: !nVCS ;2:REFRESH ON , (0=FIFO UND CNT CLEAR); 3: CONFIG; 8: FIFO_ACTIVE;
VCKE = VIDEO_RAM_CTR0;
nVCS = !VIDEO_RAM_CTR1;
DDR_REFRESH_ON = VIDEO_RAM_CTR2;
DDR_CONFIG = VIDEO_RAM_CTR3;
FIFO_ACTIVE = VIDEO_RAM_CTR8;
--------------------------------
CPU_ROW_ADR[] = FB_ADR[26..14];
CPU_BA[] = FB_ADR[13..12];
CPU_COL_ADR[] = FB_ADR[11..2];
nVRAS = !VRAS;
nVCAS = !VCAS;
nVWE = !VWE;
SR_DDR_WR.CLK = DDRCLK0;
SR_DDRWR_D_SEL.CLK = DDRCLK0;
SR_VDMP[7..0].CLK = DDRCLK0;
SR_FIFO_WRE.CLK = DDRCLK0;
CPU_AC.CLK = DDRCLK0;
FIFO_AC.CLK = DDRCLK0;
BLITTER_AC.CLK = DDRCLK0;
DDRWR_D_SEL1 = BLITTER_AC;
-- SELECT LOGIC
DDR_SEL = FB_ALE & FB_AD[31..30]==B"01";
DDR_CS.CLK = MAIN_CLK;
DDR_CS.ENA = FB_ALE;
DDR_CS = DDR_SEL;
-- WENN READ ODER WRITE B,W,L DDR SOFORT ANFORDERN, BEI WRITE LINE SP<53>TER
CPU_SIG = DDR_SEL & (nFB_WR # !LINE) & !DDR_CONFIG -- NICHT LINE ODER READ SOFORT LOS WENN NICHT CONFIG
# DDR_SEL & DDR_CONFIG -- CONFIG SOFORT LOS
# FB_REGDDR==FR_S1 & !nFB_WR; -- LINE WRITE SP<53>TER
CPU_REQ.CLK = DDR_SYNC_66M;
CPU_REQ = CPU_SIG
# CPU_REQ & FB_REGDDR!=FR_S1 & FB_REGDDR!=FR_S3 & !BUS_CYC_END & !BUS_CYC; -- HALTEN BUS CYC BEGONNEN ODER FERTIG
BUS_CYC.CLK = DDRCLK0;
BUS_CYC = BUS_CYC & !BUS_CYC_END;
-- STATE MACHINE SYNCHRONISIEREN -----------------
MCS[].CLK = DDRCLK0;
MCS0 = MAIN_CLK;
MCS1 = MCS0;
CPU_DDR_SYNC.CLK = DDRCLK0;
CPU_DDR_SYNC = MCS[]==2 & VCKE & !nVCS; -- NUR 1 WENN EIN
---------------------------------------------------
VA_S[].CLK = DDRCLK0;
BA_S[].CLK = DDRCLK0;
VA[] = VA_S[];
BA[] = BA_S[];
VA_P[].CLK = DDRCLK0;
BA_P[].CLK = DDRCLK0;
-- DDR STATE MACHINE -----------------------------------------------
DDR_SM.CLK = DDRCLK0;
CASE DDR_SM IS
WHEN DS_T1 =>
IF DDR_REFRESH_REQ THEN
DDR_SM = DS_R2;
ELSE
IF CPU_DDR_SYNC THEN -- SYNCHRON UND EIN?
IF DDR_CONFIG THEN -- JA
DDR_SM = DS_C2;
ELSE
IF CPU_REQ THEN -- BEI WAIT UND LINE WRITE
VA_S[] = CPU_ROW_ADR[];
BA_S[] = CPU_BA[];
CPU_AC = VCC;
BUS_CYC = VCC;
DDR_SM = DS_T2B;
ELSE
IF FIFO_REQ # !BLITTER_REQ THEN -- FIFO IST DEFAULT
VA_P[] = FIFO_ROW_ADR[];
BA_P[] = FIFO_BA[];
FIFO_AC = VCC; -- VORBESETZEN
ELSE
VA_P[] = BLITTER_ROW_ADR[];
BA_P[] = BLITTER_BA[];
BLITTER_AC = VCC; -- VORBESETZEN
END IF;
DDR_SM = DS_T2A;
END IF;
END IF;
ELSE
DDR_SM = DS_T1; -- NEIN ->SYNCHRONISIEREN
END IF;
END IF;
WHEN DS_T2A => -- SCHNELLZUGRIFF *** HIER IST PAGE IMMER NOT OK ***
IF DDR_SEL & (nFB_WR # !LINE) THEN
VRAS = VCC;
VA[] = FB_AD[26..14];
BA[] = FB_AD[13..12];
VA_S[10] = VCC; -- AUTO PRECHARGE DA NICHT FIFO PAGE
CPU_AC = VCC;
BUS_CYC = VCC; -- BUS CYCLUS LOSTRETEN
ELSE
VRAS = FIFO_AC & FIFO_REQ # BLITTER_AC & BLITTER_REQ;
VA[] = VA_P[];
BA[] = BA_P[];
VA_S[10] = !(FIFO_AC & FIFO_REQ);
FIFO_BANK_OK = FIFO_AC & FIFO_REQ;
FIFO_AC = FIFO_AC & FIFO_REQ;
BLITTER_AC = BLITTER_AC & BLITTER_REQ;
END IF;
DDR_SM = DS_T3;
WHEN DS_T2B =>
VRAS = VCC;
FIFO_BANK_NOT_OK = VCC;
CPU_AC = VCC;
BUS_CYC = VCC; -- BUS CYCLUS LOSTRETEN
DDR_SM = DS_T3;
WHEN DS_T3 =>
CPU_AC = CPU_AC;
FIFO_AC = FIFO_AC;
BLITTER_AC = BLITTER_AC;
VA_S[10] = VA_S[10]; -- AUTO PRECHARGE WENN NICHT FIFO PAGE
IF !nFB_WR & CPU_AC # BLITTER_WR & BLITTER_AC THEN
DDR_SM = DS_T4W;
ELSE
IF CPU_AC THEN -- CPU?
VA_S[9..0] = CPU_COL_ADR[];
BA_S[] = CPU_BA[];
DDR_SM = DS_T4R;
ELSE
IF FIFO_AC THEN -- FIFO?
VA_S[9..0] = FIFO_COL_ADR[];
BA_S[] = FIFO_BA[];
DDR_SM = DS_T4F;
ELSE
IF BLITTER_AC THEN
VA_S[9..0] = BLITTER_COL_ADR[];
BA_S[] = BLITTER_BA[];
DDR_SM = DS_T4R;
ELSE
DDR_SM = DS_N8;
END IF;
END IF;
END IF;
END IF;
-- READ
WHEN DS_T4R =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
VCAS = VCC;
SR_DDR_FB = CPU_AC; -- READ DATEN F<>R CPU
SR_BLITTER_DACK = BLITTER_AC; -- BLITTER DACK AND BLITTER LATCH DATEN
DDR_SM = DS_T5R;
WHEN DS_T5R =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
IF FIFO_REQ & FIFO_BANK_OK THEN -- FIFO READ EINSCHIEBEN WENN BANK OK
VA_S[9..0] = FIFO_COL_ADR[];
VA_S[10] = GND; -- MANUEL PRECHARGE
BA_S[] = FIFO_BA[];
DDR_SM = DS_T6F;
ELSE
VA_S[10] = VCC; -- ALLE PAGES SCHLIESSEN
DDR_SM = DS_CB6;
END IF;
-- WRITE
WHEN DS_T4W =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
SR_BLITTER_DACK = BLITTER_AC; -- BLITTER ACK AND BLITTER LATCH DATEN
VA_S[10] = VA_S[10]; -- AUTO PRECHARGE WENN NICHT FIFO PAGE
DDR_SM = DS_T5W;
WHEN DS_T5W =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
VA_S[9..0] = CPU_AC & CPU_COL_ADR[]
# BLITTER_AC & BLITTER_COL_ADR[];
VA_S[10] = VA_S[10]; -- AUTO PRECHARGE WENN NICHT FIFO PAGE
BA_S[] = CPU_AC & CPU_BA[]
# BLITTER_AC & BLITTER_BA[];
SR_VDMP[7..4] = FB_B[]; -- BYTE ENABLE WRITE
SR_VDMP[3..0] = LINE & B"1111"; -- LINE ENABLE WRITE
DDR_SM = DS_T6W;
WHEN DS_T6W =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
VCAS = VCC;
VWE = VCC;
SR_DDR_WR = VCC; -- WRITE COMMAND CPU UND BLITTER IF WRITER
SR_DDRWR_D_SEL = VCC; -- 2. H<>LFTE WRITE DATEN SELEKTIEREN
SR_VDMP[] = LINE & B"11111111"; -- WENN LINE DANN ACTIV
DDR_SM = DS_T7W;
WHEN DS_T7W =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
SR_DDR_WR = VCC; -- WRITE COMMAND CPU UND BLITTER IF WRITE
SR_DDRWR_D_SEL = VCC; -- 2. H<>LFTE WRITE DATEN SELEKTIEREN
DDR_SM = DS_T8W;
WHEN DS_T8W =>
DDR_SM = DS_T9W;
WHEN DS_T9W =>
IF FIFO_REQ & FIFO_BANK_OK THEN
VA_S[9..0] = FIFO_COL_ADR[];
VA_S[10] = GND; -- NON AUTO PRECHARGE
BA_S[] = FIFO_BA[];
DDR_SM = DS_T6F;
ELSE
VA_S[10] = VCC; -- ALLE PAGES SCHLIESSEN
DDR_SM = DS_CB6;
END IF;
-- FIFO READ
WHEN DS_T4F =>
VCAS = VCC;
SR_FIFO_WRE = VCC; -- DATEN WRITE FIFO
DDR_SM = DS_T5F;
WHEN DS_T5F =>
IF FIFO_REQ THEN
IF VIDEO_ADR_CNT[7..0]==H"FF" THEN -- NEUE PAGE?
VA_S[10] = VCC; -- ALLE PAGES SCHLIESSEN
DDR_SM = DS_CB6; -- BANK SCHLIESSEN
ELSE
VA_S[9..0] = FIFO_COL_ADR[]+4;
VA_S[10] = GND; -- NON AUTO PRECHARGE
BA_S[] = FIFO_BA[];
DDR_SM = DS_T6F;
END IF;
ELSE
VA_S[10] = VCC; -- ALLE PAGES SCHLIESSEN
DDR_SM = DS_CB6; -- NOCH OFFEN LASSEN
END IF;
WHEN DS_T6F =>
VCAS = VCC;
SR_FIFO_WRE = VCC; -- DATEN WRITE FIFO
DDR_SM = DS_T7F;
WHEN DS_T7F =>
IF CPU_REQ & FIFO_MW[]>FIFO_LWM THEN
VA_S[10] = VCC; -- ALLE PAGES SCHLIESEN
DDR_SM = DS_CB8; -- BANK SCHLIESSEN
ELSE
IF FIFO_REQ THEN
IF VIDEO_ADR_CNT[7..0]==H"FF" THEN -- NEUE PAGE?
VA_S[10] = VCC; -- ALLE PAGES SCHLIESSEN
DDR_SM = DS_CB8; -- BANK SCHLIESSEN
ELSE
VA_S[9..0] = FIFO_COL_ADR[]+4;
VA_S[10] = GND; -- NON AUTO PRECHARGE
BA_S[] = FIFO_BA[];
DDR_SM = DS_T8F;
END IF;
ELSE
VA_S[10] = VCC; -- ALLE PAGES SCHLIESEN
DDR_SM = DS_CB8; -- BANK SCHLIESSEN
END IF;
END IF;
WHEN DS_T8F =>
VCAS = VCC;
SR_FIFO_WRE = VCC; -- DATEN WRITE FIFO
IF FIFO_MW[]<FIFO_LWM THEN -- NOTFALL?
DDR_SM = DS_T5F; -- JA->
ELSE
DDR_SM = DS_T9F;
END IF;
WHEN DS_T9F =>
IF FIFO_REQ THEN
IF VIDEO_ADR_CNT[7..0]==H"FF" THEN -- NEUE PAGE?
VA_S[10] = VCC; -- ALLE BANKS SCHLIESEN
DDR_SM = DS_CB6; -- BANK SCHLIESSEN
ELSE
VA_P[9..0] = FIFO_COL_ADR[]+4;
VA_P[10] = GND; -- NON AUTO PRECHARGE
BA_P[] = FIFO_BA[];
DDR_SM = DS_T10F;
END IF;
ELSE
VA_S[10] = VCC; -- ALLE BANKS SCHLIESEN
DDR_SM = DS_CB6; -- BANK SCHLIESSEN
END IF;
WHEN DS_T10F =>
IF DDR_SEL & (nFB_WR # !LINE) & FB_AD[13..12]!=FIFO_BA[] THEN
VRAS = VCC;
VA[] = FB_AD[26..14];
BA[] = FB_AD[13..12];
CPU_AC = VCC;
BUS_CYC = VCC; -- BUS CYCLUS LOSTRETEN
VA_S[10] = VCC; -- AUTO PRECHARGE DA NICHT FIFO BANK
DDR_SM = DS_T3;
ELSE
VCAS = VCC;
VA[] = VA_P[];
BA[] = BA_P[];
SR_FIFO_WRE = VCC; -- DATEN WRITE FIFO
DDR_SM = DS_T7F;
END IF;
-- CONFIG CYCLUS
WHEN DS_C2 =>
DDR_SM = DS_C3;
WHEN DS_C3 =>
BUS_CYC = CPU_REQ;
DDR_SM = DS_C4;
WHEN DS_C4 =>
IF CPU_REQ THEN
DDR_SM = DS_C5;
ELSE
DDR_SM = DS_T1;
END IF;
WHEN DS_C5 =>
DDR_SM = DS_C6;
WHEN DS_C6 =>
VA_S[] = FB_AD[12..0];
BA_S[] = FB_AD[14..13];
DDR_SM = DS_C7;
WHEN DS_C7 =>
VRAS = FB_AD18 & !nFB_WR & !FB_SIZE0 & !FB_SIZE1; -- NUR BEI LONG WRITE
VCAS = FB_AD17 & !nFB_WR & !FB_SIZE0 & !FB_SIZE1; -- NUR BEI LONG WRITE
VWE = FB_AD16 & !nFB_WR & !FB_SIZE0 & !FB_SIZE1; -- NUR BEI LONG WRITE
DDR_SM = DS_N8;
-- CLOSE FIFO BANK
WHEN DS_CB6 =>
FIFO_BANK_NOT_OK = VCC; -- AUF NOT OK
VRAS = VCC; -- B<>NKE SCHLIESSEN
VWE = VCC;
DDR_SM = DS_N7;
WHEN DS_CB8 =>
FIFO_BANK_NOT_OK = VCC; -- AUF NOT OK
VRAS = VCC; -- B<>NKE SCHLIESSEN
VWE = VCC;
DDR_SM = DS_T1;
-- REFRESH 70NS = 10 ZYCLEN
WHEN DS_R2 =>
IF DDR_REFRESH_SIG[]==9 THEN -- EIN CYCLUS VORLAUF UM BANKS ZU SCHLIESSEN
VRAS = VCC; -- ALLE BANKS SCHLIESSEN
VWE = VCC;
VA[10] = VCC;
FIFO_BANK_NOT_OK = VCC;
DDR_SM = DS_R4;
ELSE
VCAS = VCC;
VRAS = VCC;
DDR_SM = DS_R3;
END IF;
WHEN DS_R3 =>
DDR_SM = DS_R4;
WHEN DS_R4 =>
DDR_SM = DS_R5;
WHEN DS_R5 =>
DDR_SM = DS_R6;
WHEN DS_R6 =>
DDR_SM = DS_N5;
-- LEERSCHLAUFE
WHEN DS_N5 =>
DDR_SM = DS_N6;
WHEN DS_N6 =>
DDR_SM = DS_N7;
WHEN DS_N7 =>
DDR_SM = DS_N8;
WHEN DS_N8 =>
DDR_SM = DS_T1;
END CASE;
---------------------------------------------------------------
-- BLITTER ----------------------
-----------------------------------------
BLITTER_REQ.CLK = DDRCLK0;
BLITTER_REQ = BLITTER_SIG & !DDR_CONFIG & VCKE & !nVCS;
BLITTER_ROW_ADR[] = BLITTER_ADR[26..14];
BLITTER_BA1 = BLITTER_ADR13;
BLITTER_BA0 = BLITTER_ADR12;
BLITTER_COL_ADR[] = BLITTER_ADR[11..2];
------------------------------------------------------------------------------
-- FIFO ---------------------------------
--------------------------------------------------------
FIFO_REQ.CLK = DDRCLK0;
FIFO_REQ = (FIFO_MW[]<FIFO_MWM
# FIFO_MW[]<FIFO_HWM & FIFO_REQ) & FIFO_ACTIVE & !CLEAR_FIFO_CNT & !STOP & !DDR_CONFIG & VCKE & !nVCS;
FIFO_ROW_ADR[] = VIDEO_ADR_CNT[22..10];
FIFO_BA1 = VIDEO_ADR_CNT9;
FIFO_BA0 = VIDEO_ADR_CNT8;
FIFO_COL_ADR[] = (VIDEO_ADR_CNT[7..0],B"00");
FIFO_BANK_OK.CLK = DDRCLK0;
FIFO_BANK_OK = FIFO_BANK_OK & !FIFO_BANK_NOT_OK;
-- Z<>HLER R<>CKSETZEN WENN CLR FIFO ----------------
CLR_FIFO_SYNC.CLK =DDRCLK0;
CLR_FIFO_SYNC = CLR_FIFO; -- SYNCHRONISIEREN
CLEAR_FIFO_CNT.CLK = DDRCLK0;
CLEAR_FIFO_CNT = CLR_FIFO_SYNC # !FIFO_ACTIVE;
STOP.CLK = DDRCLK0;
STOP = CLR_FIFO_SYNC # CLEAR_FIFO_CNT;
-- Z<>HLEN -----------------------------------------------
VIDEO_ADR_CNT[].CLK = DDRCLK0;
VIDEO_ADR_CNT[].ENA = SR_FIFO_WRE # CLEAR_FIFO_CNT;
VIDEO_ADR_CNT[] = CLEAR_FIFO_CNT & VIDEO_BASE_ADR[]
# !CLEAR_FIFO_CNT & VIDEO_ADR_CNT[]+1;
VIDEO_BASE_ADR[22..20] = VIDEO_BASE_X_D[];
VIDEO_BASE_ADR[19..12] = VIDEO_BASE_H_D[];
VIDEO_BASE_ADR[11..4] = VIDEO_BASE_M_D[];
VIDEO_BASE_ADR[3..0] = VIDEO_BASE_L_D[7..4];
VDM_SEL[] = VIDEO_BASE_L_D[3..0];
-- AKTUELLE VIDEO ADRESSE
VIDEO_ACT_ADR[26..4] = VIDEO_ADR_CNT[] - (0,FIFO_MW[]);
VIDEO_ACT_ADR[3..0] = VDM_SEL[];
-----------------------------------------------------------------------------------------
-- REFRESH: IMMER 8 AUFS MAL, ANFORDERUNG ALLE 7.8us X 8 STCK. = 62.4us = 2059->2048 33MHz CLOCKS
-----------------------------------------------------------------------------------------
DDR_REFRESH_CNT[].CLK = CLK33M;
DDR_REFRESH_CNT[] = DDR_REFRESH_CNT[]+1; -- Z<>HLEN 0-2047
REFRESH_TIME.CLK = DDRCLK0;
REFRESH_TIME = DDR_REFRESH_CNT[]==0 & !MAIN_CLK; -- SYNC
DDR_REFRESH_SIG[].CLK = DDRCLK0;
DDR_REFRESH_SIG[].ENA = REFRESH_TIME # DDR_SM==DS_R6;
DDR_REFRESH_SIG[] = REFRESH_TIME & 9 & DDR_REFRESH_ON & !DDR_CONFIG -- 9 ST<53>CK (8 REFRESH UND 1 ALS VORLAUF)
# !REFRESH_TIME & (DDR_REFRESH_SIG[]-1) & DDR_REFRESH_ON & !DDR_CONFIG; -- MINUS 1 WENN GEMACHT
DDR_REFRESH_REQ.CLK = DDRCLK0;
DDR_REFRESH_REQ = DDR_REFRESH_SIG[]!=0 & DDR_REFRESH_ON & !REFRESH_TIME & !DDR_CONFIG;
-----------------------------------------------------------
-- VIDEO REGISTER -----------------------
---------------------------------------------------------------------------------------------------------------------
VIDEO_BASE_L_D[].CLK = MAIN_CLK;
VIDEO_BASE_L = !nFB_CS1 & FB_ADR[19..1]==H"7C106"; -- 820D/2
VIDEO_BASE_L_D[] = FB_AD[23..16]; -- SORRY, NUR 16 BYT GRENZEN
VIDEO_BASE_L_D[].ENA = !nFB_WR & VIDEO_BASE_L & FB_B1;
VIDEO_BASE_M_D[].CLK = MAIN_CLK;
VIDEO_BASE_M = !nFB_CS1 & FB_ADR[19..1]==H"7C101"; -- 8203/2
VIDEO_BASE_M_D[] = FB_AD[23..16];
VIDEO_BASE_M_D[].ENA = !nFB_WR & VIDEO_BASE_M & FB_B3;
VIDEO_BASE_H_D[].CLK = MAIN_CLK;
VIDEO_BASE_H = !nFB_CS1 & FB_ADR[19..1]==H"7C100"; -- 8200-1/2
VIDEO_BASE_H_D[] = FB_AD[23..16];
VIDEO_BASE_H_D[].ENA = !nFB_WR & VIDEO_BASE_H & FB_B1;
VIDEO_BASE_X_D[].CLK = MAIN_CLK;
VIDEO_BASE_X_D[] = FB_AD[26..24];
VIDEO_BASE_X_D[].ENA = !nFB_WR & VIDEO_BASE_H & FB_B0;
VIDEO_CNT_L = !nFB_CS1 & FB_ADR[19..1]==H"7C104"; -- 8209/2
VIDEO_CNT_M = !nFB_CS1 & FB_ADR[19..1]==H"7C103"; -- 8207/2
VIDEO_CNT_H = !nFB_CS1 & FB_ADR[19..1]==H"7C102"; -- 8204,5/2
FB_AD[31..24] = lpm_bustri_BYT(
VIDEO_BASE_H & (0,VIDEO_BASE_X_D[])
# VIDEO_CNT_H & (0,VIDEO_ACT_ADR[26..24])
,(VIDEO_BASE_H # VIDEO_CNT_H) & !nFB_OE);
FB_AD[23..16] = lpm_bustri_BYT(
VIDEO_BASE_L & VIDEO_BASE_L_D[]
# VIDEO_BASE_M & VIDEO_BASE_M_D[]
# VIDEO_BASE_H & VIDEO_BASE_H_D[]
# VIDEO_CNT_L & VIDEO_ACT_ADR[7..0]
# VIDEO_CNT_M & VIDEO_ACT_ADR[15..8]
# VIDEO_CNT_H & VIDEO_ACT_ADR[23..16]
,(VIDEO_BASE_L # VIDEO_BASE_M # VIDEO_BASE_H # VIDEO_CNT_L # VIDEO_CNT_M # VIDEO_CNT_H) & !nFB_OE);
END;

View File

@@ -0,0 +1,660 @@
TITLE "DDR_CTR";
-- CREATED BY FREDI ASCHWANDEN
INCLUDE "lpm_bustri_BYT.inc";
-- FIFO WATER MARK
CONSTANT FIFO_LWM = 0;
CONSTANT FIFO_MWM = 200;
CONSTANT FIFO_HWM = 500;
-- {{ALTERA_PARAMETERS_BEGIN}} DO NOT REMOVE THIS LINE!
-- {{ALTERA_PARAMETERS_END}} DO NOT REMOVE THIS LINE!
SUBDESIGN DDR_CTR
(
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
FB_ADR[31..0] : INPUT;
nFB_CS1 : INPUT;
nFB_CS2 : INPUT;
nFB_CS3 : INPUT;
nFB_OE : INPUT;
FB_SIZE0 : INPUT;
FB_SIZE1 : INPUT;
nRSTO : INPUT;
MAIN_CLK : INPUT;
FB_ALE : INPUT;
nFB_WR : INPUT;
DDR_SYNC_66M : INPUT;
CLR_FIFO : INPUT;
VIDEO_RAM_CTR[15..0] : INPUT;
BLITTER_ADR[31..0] : INPUT;
BLITTER_SIG : INPUT;
BLITTER_WR : INPUT;
DDRCLK0 : INPUT;
CLK33M : INPUT;
FIFO_MW[8..0] : INPUT;
VA[12..0] : OUTPUT;
nVWE : OUTPUT;
nVRAS : OUTPUT;
nVCS : OUTPUT;
VCKE : OUTPUT;
nVCAS : OUTPUT;
FB_LE[3..0] : OUTPUT;
FB_VDOE[3..0] : OUTPUT;
CLEAR_FIFO_CNT : OUTPUT;
SR_FIFO_WRE : OUTPUT;
SR_DDR_FB : OUTPUT;
SR_DDR_WR : OUTPUT;
SR_DDRWR_D_SEL : OUTPUT;
SR_VDMP[7..0] : OUTPUT;
VIDEO_DDR_TA : OUTPUT;
SR_BLITTER_DACK : OUTPUT;
BA[1..0] : OUTPUT;
DDRWR_D_SEL1 : OUTPUT;
VDM_SEL[3..0] : OUTPUT;
FB_AD[31..0] : BIDIR;
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
)
VARIABLE
FB_REGDDR :MACHINE WITH STATES(FR_WAIT,FR_S0,FR_S1,FR_S2,FR_S3);
DDR_SM :MACHINE WITH STATES(DS_T1,DS_T2A,DS_T2B,DS_T3,DS_N5,DS_N6, DS_N7, DS_N8, -- START (NORMAL 8 CYCLES TOTAL = 60ns)
DS_C2,DS_C3,DS_C4, DS_C5, DS_C6, DS_C7, -- CONFIG
DS_T4R,DS_T5R, -- READ CPU UND BLITTER,
DS_T4W,DS_T5W,DS_T6W,DS_T7W,DS_T8W,DS_T9W, -- WRITE CPU UND BLITTER
DS_T4F,DS_T5F,DS_T6F,DS_T7F,DS_T8F,DS_T9F,DS_T10F, -- READ FIFO
DS_CB6, DS_CB8, -- CLOSE FIFO BANK
DS_R2,DS_R3,DS_R4, DS_R5, DS_R6); -- REFRESH 10X7.5NS=75NS
LINE :NODE;
FB_B[3..0] :NODE;
VCAS :NODE;
VRAS :NODE;
VWE :NODE;
VA_P[12..0] :DFF;
BA_P[1..0] :DFF;
VA_S[12..0] :DFF;
BA_S[1..0] :DFF;
MCS[1..0] :DFF;
CPU_DDR_SYNC :DFF;
DDR_SEL :NODE;
DDR_CS :DFFE;
DDR_CONFIG :NODE;
SR_DDR_WR :DFF;
SR_DDRWR_D_SEL :DFF;
SR_VDMP[7..0] :DFF;
CPU_ROW_ADR[12..0] :NODE;
CPU_BA[1..0] :NODE;
CPU_COL_ADR[9..0] :NODE;
CPU_SIG :NODE;
CPU_REQ :DFF;
CPU_AC :DFF;
BUS_CYC :DFF;
BUS_CYC_END :NODE;
BLITTER_REQ :DFF;
BLITTER_AC :DFF;
BLITTER_ROW_ADR[12..0] :NODE;
BLITTER_BA[1..0] :NODE;
BLITTER_COL_ADR[9..0] :NODE;
FIFO_REQ :DFF;
FIFO_AC :DFF;
FIFO_ROW_ADR[12..0] :NODE;
FIFO_BA[1..0] :NODE;
FIFO_COL_ADR[9..0] :NODE;
FIFO_ACTIVE :NODE;
CLR_FIFO_SYNC :DFF;
CLEAR_FIFO_CNT :DFF;
STOP :DFF;
SR_FIFO_WRE :DFF;
FIFO_BANK_OK :DFF;
FIFO_BANK_NOT_OK :NODE;
DDR_REFRESH_ON :NODE;
DDR_REFRESH_CNT[10..0] :DFF;
DDR_REFRESH_REQ :DFF;
DDR_REFRESH_SIG[3..0] :DFFE;
REFRESH_TIME :DFF;
VIDEO_BASE_L_D[7..0] :DFFE;
VIDEO_BASE_L :NODE;
VIDEO_BASE_M_D[7..0] :DFFE;
VIDEO_BASE_M :NODE;
VIDEO_BASE_H_D[7..0] :DFFE;
VIDEO_BASE_H :NODE;
VIDEO_BASE_X_D[2..0] :DFFE;
VIDEO_ADR_CNT[22..0] :DFFE;
VIDEO_CNT_L :NODE;
VIDEO_CNT_M :NODE;
VIDEO_CNT_H :NODE;
VIDEO_BASE_ADR[22..0] :NODE;
VIDEO_ACT_ADR[26..0] :NODE;
BEGIN
LINE = FB_SIZE0 & FB_SIZE1;
-- BYT SELECT
FB_B0 = FB_ADR[1..0]==0 -- ADR==0
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B1 = FB_ADR[1..0]==1 -- ADR==1
# FB_SIZE1 & !FB_SIZE0 & !FB_ADR1 -- HIGH WORD
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B2 = FB_ADR[1..0]==2 -- ADR==2
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B3 = FB_ADR[1..0]==3 -- ADR==3
# FB_SIZE1 & !FB_SIZE0 & FB_ADR1 -- LOW WORD
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
-- CPU READ (REG DDR => CPU) AND WRITE (CPU => REG DDR) --------------------------------------------------
FB_REGDDR.CLK = MAIN_CLK;
CASE FB_REGDDR IS
WHEN FR_WAIT =>
FB_LE0 = !nFB_WR;
IF BUS_CYC # DDR_SEL & LINE & !nFB_WR THEN -- LOS WENN BEREIT ODER IMMER BEI LINE WRITE
FB_REGDDR = FR_S0;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
WHEN FR_S0 =>
IF DDR_CS THEN
FB_LE0 = !nFB_WR;
VIDEO_DDR_TA = VCC;
IF LINE THEN
FB_VDOE0 = !nFB_OE & !DDR_CONFIG;
FB_REGDDR = FR_S1;
ELSE
BUS_CYC_END = VCC;
FB_VDOE0 = !nFB_OE & !MAIN_CLK & !DDR_CONFIG;
FB_REGDDR = FR_WAIT;
END IF;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
WHEN FR_S1 =>
IF DDR_CS THEN
FB_VDOE1 = !nFB_OE & !DDR_CONFIG;
FB_LE1 = !nFB_WR;
VIDEO_DDR_TA = VCC;
FB_REGDDR = FR_S2;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
WHEN FR_S2 =>
IF DDR_CS THEN
FB_VDOE2 = !nFB_OE & !DDR_CONFIG;
FB_LE2 = !nFB_WR;
IF !BUS_CYC & LINE & !nFB_WR THEN -- BEI LINE WRITE EVT. WARTEN
FB_REGDDR = FR_S2;
ELSE
VIDEO_DDR_TA = VCC;
FB_REGDDR = FR_S3;
END IF;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
WHEN FR_S3 =>
IF DDR_CS THEN
FB_VDOE3 = !nFB_OE & !MAIN_CLK & !DDR_CONFIG;
FB_LE3 = !nFB_WR;
VIDEO_DDR_TA = VCC;
BUS_CYC_END = VCC;
FB_REGDDR = FR_WAIT;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
END CASE;
-- DDR STEUERUNG -----------------------------------------------------
-- VIDEO RAM CONTROL REGISTER (IST IN VIDEO_MUX_CTR) $F0000400: BIT 0: VCKE; 1: !nVCS ;2:REFRESH ON , (0=FIFO UND CNT CLEAR); 3: CONFIG; 8: FIFO_ACTIVE;
VCKE = VIDEO_RAM_CTR0;
nVCS = !VIDEO_RAM_CTR1;
DDR_REFRESH_ON = VIDEO_RAM_CTR2;
DDR_CONFIG = VIDEO_RAM_CTR3;
FIFO_ACTIVE = VIDEO_RAM_CTR8;
--------------------------------
CPU_ROW_ADR[] = FB_ADR[26..14];
CPU_BA[] = FB_ADR[13..12];
CPU_COL_ADR[] = FB_ADR[11..2];
nVRAS = !VRAS;
nVCAS = !VCAS;
nVWE = !VWE;
SR_DDR_WR.CLK = DDRCLK0;
SR_DDRWR_D_SEL.CLK = DDRCLK0;
SR_VDMP[7..0].CLK = DDRCLK0;
SR_FIFO_WRE.CLK = DDRCLK0;
CPU_AC.CLK = DDRCLK0;
FIFO_AC.CLK = DDRCLK0;
BLITTER_AC.CLK = DDRCLK0;
DDRWR_D_SEL1 = BLITTER_AC;
-- SELECT LOGIC
DDR_SEL = FB_ALE & FB_AD[31..30]==B"01";
DDR_CS.CLK = MAIN_CLK;
DDR_CS.ENA = FB_ALE;
DDR_CS = DDR_SEL;
-- WENN READ ODER WRITE B,W,L DDR SOFORT ANFORDERN, BEI WRITE LINE SP<53>TER
CPU_SIG = DDR_SEL & (nFB_WR # !LINE) & !DDR_CONFIG -- NICHT LINE ODER READ SOFORT LOS WENN NICHT CONFIG
# DDR_SEL & DDR_CONFIG -- CONFIG SOFORT LOS
# FB_REGDDR==FR_S1 & !nFB_WR; -- LINE WRITE SP<53>TER
CPU_REQ.CLK = DDR_SYNC_66M;
CPU_REQ = CPU_SIG
# CPU_REQ & FB_REGDDR!=FR_S1 & FB_REGDDR!=FR_S3 & !BUS_CYC_END & !BUS_CYC; -- HALTEN BUS CYC BEGONNEN ODER FERTIG
BUS_CYC.CLK = DDRCLK0;
BUS_CYC = BUS_CYC & !BUS_CYC_END;
-- STATE MACHINE SYNCHRONISIEREN -----------------
MCS[].CLK = DDRCLK0;
MCS0 = MAIN_CLK;
MCS1 = MCS0;
CPU_DDR_SYNC.CLK = DDRCLK0;
CPU_DDR_SYNC = MCS[]==2 & VCKE & !nVCS; -- NUR 1 WENN EIN
---------------------------------------------------
VA_S[].CLK = DDRCLK0;
BA_S[].CLK = DDRCLK0;
VA[] = VA_S[];
BA[] = BA_S[];
VA_P[].CLK = DDRCLK0;
BA_P[].CLK = DDRCLK0;
-- DDR STATE MACHINE -----------------------------------------------
DDR_SM.CLK = DDRCLK0;
CASE DDR_SM IS
WHEN DS_T1 =>
IF DDR_REFRESH_REQ THEN
DDR_SM = DS_R2;
ELSE
IF CPU_DDR_SYNC THEN -- SYNCHRON UND EIN?
IF DDR_CONFIG THEN -- JA
DDR_SM = DS_C2;
ELSE
IF CPU_REQ THEN -- BEI WAIT UND LINE WRITE
VA_S[] = CPU_ROW_ADR[];
BA_S[] = CPU_BA[];
CPU_AC = VCC;
BUS_CYC = VCC;
DDR_SM = DS_T2B;
ELSE
IF FIFO_REQ # !BLITTER_REQ THEN -- FIFO IST DEFAULT
VA_P[] = FIFO_ROW_ADR[];
BA_P[] = FIFO_BA[];
FIFO_AC = VCC; -- VORBESETZEN
ELSE
VA_P[] = BLITTER_ROW_ADR[];
BA_P[] = BLITTER_BA[];
BLITTER_AC = VCC; -- VORBESETZEN
END IF;
DDR_SM = DS_T2A;
END IF;
END IF;
ELSE
DDR_SM = DS_T1; -- NEIN ->SYNCHRONISIEREN
END IF;
END IF;
WHEN DS_T2A => -- SCHNELLZUGRIFF *** HIER IST PAGE IMMER NOT OK ***
IF DDR_SEL & (nFB_WR # !LINE) THEN
VRAS = VCC;
VA[] = FB_AD[26..14];
BA[] = FB_AD[13..12];
VA_S[10] = VCC; -- AUTO PRECHARGE DA NICHT FIFO PAGE
CPU_AC = VCC;
BUS_CYC = VCC; -- BUS CYCLUS LOSTRETEN
ELSE
VRAS = FIFO_AC & FIFO_REQ # BLITTER_AC & BLITTER_REQ;
VA[] = VA_P[];
BA[] = BA_P[];
VA_S[10] = !(FIFO_AC & FIFO_REQ);
FIFO_BANK_OK = FIFO_AC & FIFO_REQ;
FIFO_AC = FIFO_AC & FIFO_REQ;
BLITTER_AC = BLITTER_AC & BLITTER_REQ;
END IF;
DDR_SM = DS_T3;
WHEN DS_T2B =>
VRAS = VCC;
FIFO_BANK_NOT_OK = VCC;
CPU_AC = VCC;
BUS_CYC = VCC; -- BUS CYCLUS LOSTRETEN
DDR_SM = DS_T3;
WHEN DS_T3 =>
CPU_AC = CPU_AC;
FIFO_AC = FIFO_AC;
BLITTER_AC = BLITTER_AC;
VA_S[10] = VA_S[10]; -- AUTO PRECHARGE WENN NICHT FIFO PAGE
IF !nFB_WR & CPU_AC # BLITTER_WR & BLITTER_AC THEN
DDR_SM = DS_T4W;
ELSE
IF CPU_AC THEN -- CPU?
VA_S[9..0] = CPU_COL_ADR[];
BA_S[] = CPU_BA[];
DDR_SM = DS_T4R;
ELSE
IF FIFO_AC THEN -- FIFO?
VA_S[9..0] = FIFO_COL_ADR[];
BA_S[] = FIFO_BA[];
DDR_SM = DS_T4F;
ELSE
IF BLITTER_AC THEN
VA_S[9..0] = BLITTER_COL_ADR[];
BA_S[] = BLITTER_BA[];
DDR_SM = DS_T4R;
ELSE
DDR_SM = DS_N8;
END IF;
END IF;
END IF;
END IF;
-- READ
WHEN DS_T4R =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
VCAS = VCC;
SR_DDR_FB = CPU_AC; -- READ DATEN F<>R CPU
SR_BLITTER_DACK = BLITTER_AC; -- BLITTER DACK AND BLITTER LATCH DATEN
DDR_SM = DS_T5R;
WHEN DS_T5R =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
IF FIFO_REQ & FIFO_BANK_OK THEN -- FIFO READ EINSCHIEBEN WENN BANK OK
VA_S[9..0] = FIFO_COL_ADR[];
VA_S[10] = GND; -- MANUEL PRECHARGE
BA_S[] = FIFO_BA[];
DDR_SM = DS_T6F;
ELSE
VA_S[10] = VCC; -- ALLE PAGES SCHLIESSEN
DDR_SM = DS_CB6;
END IF;
-- WRITE
WHEN DS_T4W =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
SR_BLITTER_DACK = BLITTER_AC; -- BLITTER ACK AND BLITTER LATCH DATEN
VA_S[10] = VA_S[10]; -- AUTO PRECHARGE WENN NICHT FIFO PAGE
DDR_SM = DS_T5W;
WHEN DS_T5W =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
VA_S[9..0] = CPU_AC & CPU_COL_ADR[]
# BLITTER_AC & BLITTER_COL_ADR[];
VA_S[10] = VA_S[10]; -- AUTO PRECHARGE WENN NICHT FIFO PAGE
BA_S[] = CPU_AC & CPU_BA[]
# BLITTER_AC & BLITTER_BA[];
SR_VDMP[7..4] = FB_B[]; -- BYTE ENABLE WRITE
SR_VDMP[3..0] = LINE & B"1111"; -- LINE ENABLE WRITE
DDR_SM = DS_T6W;
WHEN DS_T6W =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
VCAS = VCC;
VWE = VCC;
SR_DDR_WR = VCC; -- WRITE COMMAND CPU UND BLITTER IF WRITER
SR_DDRWR_D_SEL = VCC; -- 2. H<>LFTE WRITE DATEN SELEKTIEREN
SR_VDMP[] = LINE & B"11111111"; -- WENN LINE DANN ACTIV
DDR_SM = DS_T7W;
WHEN DS_T7W =>
CPU_AC = CPU_AC;
BLITTER_AC = BLITTER_AC;
SR_DDR_WR = VCC; -- WRITE COMMAND CPU UND BLITTER IF WRITE
SR_DDRWR_D_SEL = VCC; -- 2. H<>LFTE WRITE DATEN SELEKTIEREN
DDR_SM = DS_T8W;
WHEN DS_T8W =>
DDR_SM = DS_T9W;
WHEN DS_T9W =>
IF FIFO_REQ & FIFO_BANK_OK THEN
VA_S[9..0] = FIFO_COL_ADR[];
VA_S[10] = GND; -- NON AUTO PRECHARGE
BA_S[] = FIFO_BA[];
DDR_SM = DS_T6F;
ELSE
VA_S[10] = VCC; -- ALLE PAGES SCHLIESSEN
DDR_SM = DS_CB6;
END IF;
-- FIFO READ
WHEN DS_T4F =>
VCAS = VCC;
SR_FIFO_WRE = VCC; -- DATEN WRITE FIFO
DDR_SM = DS_T5F;
WHEN DS_T5F =>
IF FIFO_REQ THEN
IF VIDEO_ADR_CNT[7..0]==H"FF" THEN -- NEUE PAGE?
VA_S[10] = VCC; -- ALLE PAGES SCHLIESSEN
DDR_SM = DS_CB6; -- BANK SCHLIESSEN
ELSE
VA_S[9..0] = FIFO_COL_ADR[]+4;
VA_S[10] = GND; -- NON AUTO PRECHARGE
BA_S[] = FIFO_BA[];
DDR_SM = DS_T6F;
END IF;
ELSE
VA_S[10] = VCC; -- ALLE PAGES SCHLIESSEN
DDR_SM = DS_CB6; -- NOCH OFFEN LASSEN
END IF;
WHEN DS_T6F =>
VCAS = VCC;
SR_FIFO_WRE = VCC; -- DATEN WRITE FIFO
DDR_SM = DS_T7F;
WHEN DS_T7F =>
IF CPU_REQ & FIFO_MW[]>FIFO_LWM THEN
VA_S[10] = VCC; -- ALLE PAGES SCHLIESEN
DDR_SM = DS_CB8; -- BANK SCHLIESSEN
ELSE
IF FIFO_REQ THEN
IF VIDEO_ADR_CNT[7..0]==H"FF" THEN -- NEUE PAGE?
VA_S[10] = VCC; -- ALLE PAGES SCHLIESSEN
DDR_SM = DS_CB8; -- BANK SCHLIESSEN
ELSE
VA_S[9..0] = FIFO_COL_ADR[]+4;
VA_S[10] = GND; -- NON AUTO PRECHARGE
BA_S[] = FIFO_BA[];
DDR_SM = DS_T8F;
END IF;
ELSE
VA_S[10] = VCC; -- ALLE PAGES SCHLIESEN
DDR_SM = DS_CB8; -- BANK SCHLIESSEN
END IF;
END IF;
WHEN DS_T8F =>
VCAS = VCC;
SR_FIFO_WRE = VCC; -- DATEN WRITE FIFO
IF FIFO_MW[]<FIFO_LWM THEN -- NOTFALL?
DDR_SM = DS_T5F; -- JA->
ELSE
DDR_SM = DS_T9F;
END IF;
WHEN DS_T9F =>
IF FIFO_REQ THEN
IF VIDEO_ADR_CNT[7..0]==H"FF" THEN -- NEUE PAGE?
VA_S[10] = VCC; -- ALLE BANKS SCHLIESEN
DDR_SM = DS_CB6; -- BANK SCHLIESSEN
ELSE
VA_P[9..0] = FIFO_COL_ADR[]+4;
VA_P[10] = GND; -- NON AUTO PRECHARGE
BA_P[] = FIFO_BA[];
DDR_SM = DS_T10F;
END IF;
ELSE
VA_S[10] = VCC; -- ALLE BANKS SCHLIESEN
DDR_SM = DS_CB6; -- BANK SCHLIESSEN
END IF;
WHEN DS_T10F =>
IF DDR_SEL & (nFB_WR # !LINE) & FB_AD[13..12]!=FIFO_BA[] THEN
VRAS = VCC;
VA[] = FB_AD[26..14];
BA[] = FB_AD[13..12];
CPU_AC = VCC;
BUS_CYC = VCC; -- BUS CYCLUS LOSTRETEN
VA_S[10] = VCC; -- AUTO PRECHARGE DA NICHT FIFO BANK
DDR_SM = DS_T3;
ELSE
VCAS = VCC;
VA[] = VA_P[];
BA[] = BA_P[];
SR_FIFO_WRE = VCC; -- DATEN WRITE FIFO
DDR_SM = DS_T7F;
END IF;
-- CONFIG CYCLUS
WHEN DS_C2 =>
DDR_SM = DS_C3;
WHEN DS_C3 =>
BUS_CYC = CPU_REQ;
DDR_SM = DS_C4;
WHEN DS_C4 =>
IF CPU_REQ THEN
DDR_SM = DS_C5;
ELSE
DDR_SM = DS_T1;
END IF;
WHEN DS_C5 =>
DDR_SM = DS_C6;
WHEN DS_C6 =>
VA_S[] = FB_AD[12..0];
BA_S[] = FB_AD[14..13];
DDR_SM = DS_C7;
WHEN DS_C7 =>
VRAS = FB_AD18 & !nFB_WR & !FB_SIZE0 & !FB_SIZE1; -- NUR BEI LONG WRITE
VCAS = FB_AD17 & !nFB_WR & !FB_SIZE0 & !FB_SIZE1; -- NUR BEI LONG WRITE
VWE = FB_AD16 & !nFB_WR & !FB_SIZE0 & !FB_SIZE1; -- NUR BEI LONG WRITE
DDR_SM = DS_N8;
-- CLOSE FIFO BANK
WHEN DS_CB6 =>
FIFO_BANK_NOT_OK = VCC; -- AUF NOT OK
VRAS = VCC; -- B<>NKE SCHLIESSEN
VWE = VCC;
DDR_SM = DS_N7;
WHEN DS_CB8 =>
FIFO_BANK_NOT_OK = VCC; -- AUF NOT OK
VRAS = VCC; -- B<>NKE SCHLIESSEN
VWE = VCC;
DDR_SM = DS_T1;
-- REFRESH 70NS = 10 ZYCLEN
WHEN DS_R2 =>
IF DDR_REFRESH_SIG[]==9 THEN -- EIN CYCLUS VORLAUF UM BANKS ZU SCHLIESSEN
VRAS = VCC; -- ALLE BANKS SCHLIESSEN
VWE = VCC;
VA[10] = VCC;
FIFO_BANK_NOT_OK = VCC;
DDR_SM = DS_R4;
ELSE
VCAS = VCC;
VRAS = VCC;
DDR_SM = DS_R3;
END IF;
WHEN DS_R3 =>
DDR_SM = DS_R4;
WHEN DS_R4 =>
DDR_SM = DS_R5;
WHEN DS_R5 =>
DDR_SM = DS_R6;
WHEN DS_R6 =>
DDR_SM = DS_N5;
-- LEERSCHLAUFE
WHEN DS_N5 =>
DDR_SM = DS_N6;
WHEN DS_N6 =>
DDR_SM = DS_N7;
WHEN DS_N7 =>
DDR_SM = DS_N8;
WHEN DS_N8 =>
DDR_SM = DS_T1;
END CASE;
---------------------------------------------------------------
-- BLITTER ----------------------
-----------------------------------------
BLITTER_REQ.CLK = DDRCLK0;
BLITTER_REQ = BLITTER_SIG & !DDR_CONFIG & VCKE & !nVCS;
BLITTER_ROW_ADR[] = BLITTER_ADR[26..14];
BLITTER_BA1 = BLITTER_ADR13;
BLITTER_BA0 = BLITTER_ADR12;
BLITTER_COL_ADR[] = BLITTER_ADR[11..2];
------------------------------------------------------------------------------
-- FIFO ---------------------------------
--------------------------------------------------------
FIFO_REQ.CLK = DDRCLK0;
FIFO_REQ = (FIFO_MW[]<FIFO_MWM
# FIFO_MW[]<FIFO_HWM & FIFO_REQ) & FIFO_ACTIVE & !CLEAR_FIFO_CNT & !STOP & !DDR_CONFIG & VCKE & !nVCS;
FIFO_ROW_ADR[] = VIDEO_ADR_CNT[22..10];
FIFO_BA1 = VIDEO_ADR_CNT9;
FIFO_BA0 = VIDEO_ADR_CNT8;
FIFO_COL_ADR[] = (VIDEO_ADR_CNT[7..0],B"00");
FIFO_BANK_OK.CLK = DDRCLK0;
FIFO_BANK_OK = FIFO_BANK_OK & !FIFO_BANK_NOT_OK;
-- Z<>HLER R<>CKSETZEN WENN CLR FIFO ----------------
CLR_FIFO_SYNC.CLK =DDRCLK0;
CLR_FIFO_SYNC = CLR_FIFO; -- SYNCHRONISIEREN
CLEAR_FIFO_CNT.CLK = DDRCLK0;
CLEAR_FIFO_CNT = CLR_FIFO_SYNC # !FIFO_ACTIVE;
STOP.CLK = DDRCLK0;
STOP = CLR_FIFO_SYNC # CLEAR_FIFO_CNT;
-- Z<>HLEN -----------------------------------------------
VIDEO_ADR_CNT[].CLK = DDRCLK0;
VIDEO_ADR_CNT[].ENA = SR_FIFO_WRE # CLEAR_FIFO_CNT;
VIDEO_ADR_CNT[] = CLEAR_FIFO_CNT & VIDEO_BASE_ADR[]
# !CLEAR_FIFO_CNT & VIDEO_ADR_CNT[]+1;
VIDEO_BASE_ADR[22..20] = VIDEO_BASE_X_D[];
VIDEO_BASE_ADR[19..12] = VIDEO_BASE_H_D[];
VIDEO_BASE_ADR[11..4] = VIDEO_BASE_M_D[];
VIDEO_BASE_ADR[3..0] = VIDEO_BASE_L_D[7..4];
VDM_SEL[] = VIDEO_BASE_L_D[3..0];
-- AKTUELLE VIDEO ADRESSE
VIDEO_ACT_ADR[26..4] = VIDEO_ADR_CNT[] - (0,FIFO_MW[]);
VIDEO_ACT_ADR[3..0] = VDM_SEL[];
-----------------------------------------------------------------------------------------
-- REFRESH: IMMER 8 AUFS MAL, ANFORDERUNG ALLE 7.8us X 8 STCK. = 62.4us = 2059->2048 33MHz CLOCKS
-----------------------------------------------------------------------------------------
DDR_REFRESH_CNT[].CLK = CLK33M;
DDR_REFRESH_CNT[] = DDR_REFRESH_CNT[]+1; -- Z<>HLEN 0-2047
REFRESH_TIME.CLK = DDRCLK0;
REFRESH_TIME = DDR_REFRESH_CNT[]==0 & !MAIN_CLK; -- SYNC
DDR_REFRESH_SIG[].CLK = DDRCLK0;
DDR_REFRESH_SIG[].ENA = REFRESH_TIME # DDR_SM==DS_R6;
DDR_REFRESH_SIG[] = REFRESH_TIME & 9 & DDR_REFRESH_ON & !DDR_CONFIG -- 9 ST<53>CK (8 REFRESH UND 1 ALS VORLAUF)
# !REFRESH_TIME & (DDR_REFRESH_SIG[]-1) & DDR_REFRESH_ON & !DDR_CONFIG; -- MINUS 1 WENN GEMACHT
DDR_REFRESH_REQ.CLK = DDRCLK0;
DDR_REFRESH_REQ = DDR_REFRESH_SIG[]!=0 & DDR_REFRESH_ON & !REFRESH_TIME & !DDR_CONFIG;
-----------------------------------------------------------
-- VIDEO REGISTER -----------------------
---------------------------------------------------------------------------------------------------------------------
VIDEO_BASE_L_D[].CLK = MAIN_CLK;
VIDEO_BASE_L = !nFB_CS1 & FB_ADR[19..1]==H"7C106"; -- 820D/2
VIDEO_BASE_L_D[] = FB_AD[23..16]; -- SORRY, NUR 16 BYT GRENZEN
VIDEO_BASE_L_D[].ENA = !nFB_WR & VIDEO_BASE_L & FB_B1;
VIDEO_BASE_M_D[].CLK = MAIN_CLK;
VIDEO_BASE_M = !nFB_CS1 & FB_ADR[19..1]==H"7C101"; -- 8203/2
VIDEO_BASE_M_D[] = FB_AD[23..16];
VIDEO_BASE_M_D[].ENA = !nFB_WR & VIDEO_BASE_M & FB_B3;
VIDEO_BASE_H_D[].CLK = MAIN_CLK;
VIDEO_BASE_H = !nFB_CS1 & FB_ADR[19..1]==H"7C100"; -- 8200-1/2
VIDEO_BASE_H_D[] = FB_AD[23..16];
VIDEO_BASE_H_D[].ENA = !nFB_WR & VIDEO_BASE_H & FB_B1;
VIDEO_BASE_X_D[].CLK = MAIN_CLK;
VIDEO_BASE_X_D[] = FB_AD[26..24];
VIDEO_BASE_X_D[].ENA = !nFB_WR & VIDEO_BASE_H & FB_B0;
VIDEO_CNT_L = !nFB_CS1 & FB_ADR[19..1]==H"7C104"; -- 8209/2
VIDEO_CNT_M = !nFB_CS1 & FB_ADR[19..1]==H"7C103"; -- 8207/2
VIDEO_CNT_H = !nFB_CS1 & FB_ADR[19..1]==H"7C102"; -- 8204,5/2
FB_AD[31..24] = lpm_bustri_BYT(
VIDEO_BASE_H & (0,VIDEO_BASE_X_D[])
# VIDEO_CNT_H & (0,VIDEO_ACT_ADR[26..24])
,(VIDEO_BASE_H # VIDEO_CNT_H) & !nFB_OE);
FB_AD[23..16] = lpm_bustri_BYT(
VIDEO_BASE_L & VIDEO_BASE_L_D[]
# VIDEO_BASE_M & VIDEO_BASE_M_D[]
# VIDEO_BASE_H & VIDEO_BASE_H_D[]
# VIDEO_CNT_L & VIDEO_ACT_ADR[7..0]
# VIDEO_CNT_M & VIDEO_ACT_ADR[15..8]
# VIDEO_CNT_H & VIDEO_ACT_ADR[23..16]
,(VIDEO_BASE_L # VIDEO_BASE_M # VIDEO_BASE_H # VIDEO_CNT_L # VIDEO_CNT_M # VIDEO_CNT_H) & !nFB_OE);
END;

View File

@@ -0,0 +1,352 @@
TITLE "DDR_CTR_BLITTER";
-- CREATED BY FREDI ASCHWANDEN
INCLUDE "lpm_bustri_BYT.inc";
-- {{ALTERA_PARAMETERS_BEGIN}} DO NOT REMOVE THIS LINE!
-- {{ALTERA_PARAMETERS_END}} DO NOT REMOVE THIS LINE!
SUBDESIGN DDR_CTR_BLITTER
(
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
FB_ADR[31..0] : INPUT;
nFB_CS1 : INPUT;
nFB_CS2 : INPUT;
nFB_CS3 : INPUT;
nFB_OE : INPUT;
FB_SIZE0 : INPUT;
FB_SIZE1 : INPUT;
nRSTO : INPUT;
MAIN_CLK : INPUT;
FIFO_FULL : INPUT;
FB_ALE : INPUT;
nFB_WR : INPUT;
DDR_SYNC_66M : INPUT;
VSYNC : INPUT;
BLITTER_ON : INPUT;
VIDEO_RAM_CTR[15..0] : INPUT;
VDVZ[127..0] : INPUT;
DDRCLK[3..0] : INPUT;
BA0 : OUTPUT;
BA1 : OUTPUT;
VA[12..0] : OUTPUT;
nVWE : OUTPUT;
nVRAS : OUTPUT;
nVCS : OUTPUT;
VCKE : OUTPUT;
nVCAS : OUTPUT;
FIFO_WRE : OUTPUT;
FB_LE[3..0] : OUTPUT;
FB_VDOE[3..0] : OUTPUT;
START_CYC_RDWR : OUTPUT;
DDR_WR : OUTPUT;
CLEAR_FIFO_CNT : OUTPUT;
BLITTER_RUN : OUTPUT;
BLITTER_DOUT[127..0] : OUTPUT;
BLITTER_LE[3..0] : OUTPUT;
BLITTER_RDE : OUTPUT;
DDRWR_D_SEL[1..0] : OUTPUT;
VDMP[7..0] : OUTPUT;
FB_AD[31..0] : BIDIR;
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
)
VARIABLE
FB_REGDDR :MACHINE WITH STATES(FR_WAIT,FR_S0,FR_S1,FR_S2,FR_S3);
DDR_SM :MACHINE WITH STATES(DS_T1,DS_T2,DS_T3,DS_T4,DS_T5,DS_T6,DS_T7,DS_T8,DS_LS);
LINE :NODE;
FB_B[3..0] :NODE;
VCAS :NODE;
VRAS :NODE;
VWE :NODE;
VA[12..0] :NODE;
BA0 :NODE;
BA1 :NODE;
DDR_WR :DFF;
DDR_SEL :NODE;
DDR_CONFIG :NODE;
DDRWR_D_SEL[1..0] :DFF;
CPU_ROW_ADR[12..0] :NODE;
CPU_BA0 :NODE;
CPU_BA1 :NODE;
CPU_COL_ADR[9..0] :NODE;
CPU_SIG :NODE;
CPU_REQ :DFF;
BLITTER_SIG :NODE;
BLITTER_REQ :DFF;
BLITTER_RUN :DFF;
BLITTER_WR :DFF;
BLITTER_ROW_ADR[12..0] :NODE;
BLITTER_BA0 :NODE;
BLITTER_BA1 :NODE;
BLITTER_COL_ADR[9..0] :NODE;
FIFO_SIG :NODE;
FIFO_REQ :DFF;
FIFO_ROW_ADR[12..0] :NODE;
FIFO_BA0 :NODE;
FIFO_BA1 :NODE;
FIFO_COL_ADR[9..0] :NODE;
FIFO_WRE :DFF;
FIFO_ACTIVE :NODE;
CLEAR_FIFO_CNT :DFF;
STOP :DFF;
DDR_REFRESH_ON :NODE;
VIDEO_BASE_L_D[3..0] :DFFE;
VIDEO_BASE_L :NODE;
VIDEO_BASE_M_D[7..0] :DFFE;
VIDEO_BASE_M :NODE;
VIDEO_BASE_H_D[7..0] :DFFE;
VIDEO_BASE_H :NODE;
VIDEO_BASE_X_D[7..0] :DFFE;
VIDEO_ADR_CNT[27..0] :DFFE;
VIDEO_CNT_L :NODE;
VIDEO_CNT_M :NODE;
VIDEO_CNT_H :NODE;
VIDEO_BASE_ADR[27..0] :NODE;
BEGIN
LINE = FB_SIZE0 & FB_SIZE1;
-- BYT SELECT
FB_B0 = FB_ADR[1..0]==0; -- ADR==0
FB_B1 = FB_ADR[1..0]==1 -- ADR==1
# FB_SIZE1 & !FB_SIZE0 & !FB_ADR1 -- HIGH WORD
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B2 = FB_ADR[1..0]==2 -- ADR==2
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B3 = FB_ADR[1..0]==3 -- ADR==3
# FB_SIZE1 & !FB_SIZE0 & FB_ADR1 -- LOW WORD
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
-- CPU READ (REG DDR => CPU) AND WRITE (CPU => REG DDR) --------------------------------------------------
FB_REGDDR.CLK = MAIN_CLK;
CASE FB_REGDDR IS
WHEN FR_WAIT =>
IF DDR_SEL THEN
FB_REGDDR = FR_S0;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
WHEN FR_S0 =>
FB_VDOE0 = !nFB_OE & !DDR_CONFIG;
FB_LE0 = !nFB_WR;
IF LINE THEN
FB_REGDDR = FR_S1;
ELSE
FB_REGDDR = FR_WAIT;
END IF;
WHEN FR_S1 =>
FB_VDOE1 = !nFB_OE & !DDR_CONFIG;
FB_LE1 = !nFB_WR;
FB_REGDDR = FR_S2;
WHEN FR_S2 =>
FB_VDOE2 = !nFB_OE & !DDR_CONFIG;
FB_LE2 = !nFB_WR;
FB_REGDDR = FR_S3;
WHEN FR_S3 =>
FB_VDOE3 = !nFB_OE & !DDR_CONFIG;
FB_LE3 = !nFB_WR;
FB_REGDDR = FR_WAIT;
END CASE;
-- DDR STEUERUNG -----------------------------------------------------
-- VIDEO RAM CONTROL REGISTER (IST IN VIDEO_MUX_CTR) $F0000400: BIT 0=VCKE,1=!nVCS,2=FIFO_ACTIVE,3=FIFO UND CNT CLEAR,15..11=VIDEO RAM BASE
VCKE = VIDEO_RAM_CTR0;
nVCS = !VIDEO_RAM_CTR1;
FIFO_ACTIVE = VIDEO_RAM_CTR2;
DDR_CONFIG = VIDEO_RAM_CTR3;
DDR_REFRESH_ON = VIDEO_RAM_CTR4;
--------------------------------
CPU_ROW_ADR[] = FB_ADR[26..14];
CPU_BA1 = FB_ADR13;
CPU_BA0 = FB_ADR12;
CPU_COL_ADR[] = FB_ADR[11..2];
nVRAS = !VRAS;
nVCAS = !VCAS;
nVWE = !VWE;
DDR_WR.CLK = DDRCLK0;
-- SELECT LOGIC
DDR_SEL = FB_ALE & FB_AD[31..29]==B"011";
-- WENN READ ODER WRITE B,W,L DDR SOFORT ANFORDERN, BEI WRITE LINE SP<53>TER
CPU_SIG = DDR_SEL & nFB_WR & !DDR_CONFIG -- READ SOFORT LOS
# FR_S0 & !nFB_WR -- WRITE SP<53>TER AUCH CONFIG
# FR_S3 & !nFB_WR & LINE & !DDR_CONFIG; -- LINE WRITE
CPU_REQ = CPU_SIG;
CPU_REQ.CLK = DDR_SYNC_66M;
DDR_D_SEL[].CLK = DDRCLK3;
-- DDR STATE MACHINE -----------------------------------------------
DDR_SM.CLK = DDRCLK0;
CASE DDR_SM IS
WHEN DS_T1 =>
IF MAIN_CLK THEN
DDR_WR = DDR_WR; -- WRITE HALTEN (VON T4)
DDR_SM = DS_T2;
ELSE
DDR_SM = DS_LS; -- SYNCHRONISIEREN
END IF;
WHEN DS_T2 =>
IF !DDR_CONFIG THEN
VRAS = CPU_SIG # BLITTER_SIG # FIFO_SIG # DDR_REFRESH_ON;
VA[] = CPU_SIG & CPU_ROW_ADR[]
# BLITTER_SIG & BLITTER_ROW_ADR[]
# FIFO_SIG & FIFO_ROW_ADR[];
BA0 = CPU_SIG & CPU_BA0
# BLITTER_SIG & BLITTER_BA0
# FIFO_SIG & FIFO_BA0;
BA1 = CPU_SIG & CPU_BA1
# BLITTER_SIG & BLITTER_BA1
# FIFO_SIG & FIFO_BA1;
VCAS = !CPU_SIG & !BLITTER_SIG & !FIFO_SIG & DDR_REFRESH_ON; -- AUTO REFRESH WENN SONST NICHTS
BLITTER_REQ = BLITTER_SIG;
FIFO_REQ = FIFO_SIG;
END IF;
IF MAIN_CLK THEN
DDR_SM = DS_T3;
ELSE
DDR_SM = DS_LS;
END IF;
WHEN DS_T3 =>
IF DDR_CONFIG & CPU_REQ THEN
VRAS = FB_AD18;
VCAS = FB_AD17;
VWE = FB_AD16;
BA1 = FB_AD14;
BA0 = FB_AD13;
VA[] = FB_AD[12..0];
END IF;
IF !CPU_REQ & !BLITTER_REQ & !FIFO_REQ # DDR_CONFIG THEN
DDR_SM = DS_LS;
ELSE
BLITTER_REQ = BLITTER_SIG;
FIFO_REQ = FIFO_SIG;
DDR_SM = DS_T4;
END IF;
WHEN DS_T4 =>
FIFO_REQ = FIFO_SIG;
VCAS = VCC;
VWE = !nFB_WR & CPU_REQ # BLITTER_WR & BLITTER_REQ;
VA[9..0] = CPU_REQ & CPU_COL_ADR[]
# BLITTER_REQ & BLITTER_COL_ADR[]
# FIFO_REQ & FIFO_COL_ADR[];
VA10 = VCC; -- AUTO PRECHARGE
BA0 = CPU_REQ & CPU_BA0
# BLITTER_REQ & BLITTER_BA0
# FIFO_REQ & FIFO_BA0;
BA1 = CPU_REQ & CPU_BA1
# BLITTER_REQ & BLITTER_BA1
# FIFO_REQ & FIFO_BA1;
DDR_WR = !nFB_WR & CPU_REQ # BLITTER_WR & BLITTER_REQ;
FIFO_REQ = FIFO_SIG;
IF FIFO_REQ & FIFO_COL_ADR[]!= H"3FF" THEN -- GLEICHE PAGE?
DDR_SM = DS_T5; -- JA->
ELSE
DDR_SM = DS_T1; -- SONST NEUE PAGE AUFMACHEN
END IF;
WHEN DS_T5 =>
FIFO_REQ = FIFO_SIG;
DDR_SM = DS_T6;
WHEN DS_T6 =>
IF CPU_SIG THEN -- SOFORT UMSCHALTEN WENN CPU REQ
VRAS = VCC;
VA[] = CPU_ROW_ADR[];
BA1 = CPU_BA1;
BA0 = CPU_BA0;
DDR_SM = DS_T3;
ELSE
FIFO_REQ = FIFO_SIG;
VCAS = VCC;
VA[9..0] = FIFO_COL_ADR[];
VA10 = VCC; -- AUTO PRECHARGE
BA0 = FIFO_BA0;
BA1 = FIFO_BA1;
FIFO_WRE = FIFO_REQ; -- ODER FIFO LATCH IN 5 CYC 133
IF FIFO_REQ & FIFO_COL_ADR[]!= H"3FF" THEN -- GLEICHE PAGE?
DDR_SM = DS_T5; -- JA->
ELSE
DDR_SM = DS_T1; -- SONST NEUE PAGE AUFMACHEN
END IF;
END IF;
WHEN DS_LS =>
IF !MAIN_CLK THEN -- LEERSTATE UND SYNC
DDR_SM = DS_T1;
ELSE
DDR_SM = DS_LS;
END IF;
END CASE;
------------------------------------------------------------------------------
-- FIFO ---------------------------------
FIFO_SIG = FIFO_ACTIVE & !FIFO_FULL & !BLITTER_SIG & !CPU_SIG;
FIFO_REQ.CLK = DDR_SYNC_66M;
FIFO_ROW_ADR[] = VIDEO_ADR_CNT[24..12];
FIFO_BA1 = VIDEO_ADR_CNT11;
FIFO_BA0 = VIDEO_ADR_CNT10;
FIFO_COL_ADR[] = VIDEO_ADR_CNT[9..0];
-- Z<>HLER R<>CKSETZEN WENN VSYNC ----------------
CLEAR_FIFO_CNT.CLK = DDRCLK0;
CLEAR_FIFO_CNT = VSYNC # !FIFO_ACTIVE;
STOP.CLK = DDRCLK0;
STOP = VSYNC # CLEAR_FIFO_CNT;
VIDEO_ADR_CNT[].CLK = DDRCLK0;
VIDEO_ADR_CNT[] = CLEAR_FIFO_CNT & VIDEO_BASE_ADR[] -- SET
# !CLEAR_FIFO_CNT & (VIDEO_ADR_CNT[]+1); -- NEXT 16 BYTS
VIDEO_ADR_CNT[].ENA = CLEAR_FIFO_CNT # FIFO_WRE;
FIFO_WRE.CLK = DDRCLK0;
---------------------------------------------------------------
-- BLITTER BUS IST 128 BIT BREIT ------
BLITTER_SIG = GND & !CPU_SIG;
BLITTER_REQ.CLK = DDR_SYNC_66M;
BLITTER_RUN.CLK = DDRCLK0;
BLITTER_RUN = GND;
BLITTER_WR.CLK = DDRCLK0;
BLITTER_WR = GND;
DDRWR_D_SEL1 = BLITTER_WR;
BLITTER_ROW_ADR[] = H"0";
BLITTER_BA1 = GND;
BLITTER_BA0 = GND;
BLITTER_COL_ADR[] = H"0";
BLITTER_DOUT[] = H"0";
BLITTER_LE[] = H"0";
-----------------------------------------------------------
-- VIDEO REGISTER -----------------------
---------------------------------------------------------------------------------------------------------------------
VIDEO_BASE_L_D[].CLK = MAIN_CLK;
VIDEO_BASE_L = !nFB_CS1 & FB_ADR[15..1]==H"4106"; -- 820D/2
VIDEO_BASE_L_D[] = FB_AD[23..20]; -- SORRY, NUR 16 BYT GRENZEN
VIDEO_BASE_L_D[].ENA = !nFB_WR & VIDEO_BASE_L & FB_B1;
VIDEO_BASE_M_D[].CLK = MAIN_CLK;
VIDEO_BASE_M = !nFB_CS1 & FB_ADR[15..1]==H"4101"; -- 8203/2
VIDEO_BASE_M_D[] = FB_AD[23..16];
VIDEO_BASE_M_D[].ENA = !nFB_WR & VIDEO_BASE_M & FB_B3;
VIDEO_BASE_H_D[].CLK = MAIN_CLK;
VIDEO_BASE_H = !nFB_CS1 & FB_ADR[15..1]==H"4100"; -- 8200-1/2
VIDEO_BASE_H_D[] = FB_AD[23..16];
VIDEO_BASE_H_D[].ENA = !nFB_WR & VIDEO_BASE_H & FB_B1;
VIDEO_BASE_X_D[].CLK = MAIN_CLK;
VIDEO_BASE_X_D[] = FB_AD[31..24];
VIDEO_BASE_X_D[].ENA = !nFB_WR & VIDEO_BASE_H & FB_B0;
VIDEO_CNT_L = !nFB_CS1 & FB_ADR[15..1]==H"4104"; -- 8209/2
VIDEO_CNT_M = !nFB_CS1 & FB_ADR[15..1]==H"4103"; -- 8207/2
VIDEO_CNT_H = !nFB_CS1 & FB_ADR[15..1]==H"4102"; -- 8205/2
FB_AD[31..24] = lpm_bustri_BYT(
VIDEO_BASE_H & VIDEO_BASE_X_D[]
# VIDEO_CNT_H & VIDEO_ADR_CNT[27..20]
,(VIDEO_BASE_H # VIDEO_CNT_H) & !nFB_OE);
FB_AD[23..16] = lpm_bustri_BYT(
VIDEO_BASE_L & (VIDEO_BASE_L_D[],B"0000")
# VIDEO_BASE_M & VIDEO_BASE_M_D[]
# VIDEO_BASE_H & VIDEO_BASE_H_D[]
# VIDEO_CNT_L & (VIDEO_ADR_CNT[3..0],B"0000")
# VIDEO_CNT_M & VIDEO_ADR_CNT[11..4]
# VIDEO_CNT_H & VIDEO_ADR_CNT[19..12]
,(VIDEO_BASE_L # VIDEO_BASE_M # VIDEO_BASE_H # VIDEO_CNT_L # VIDEO_CNT_M # VIDEO_CNT_H) & !nFB_OE);
VIDEO_BASE_ADR[27..20] = VIDEO_BASE_X_D[];
VIDEO_BASE_ADR[19..12] = VIDEO_BASE_H_D[];
VIDEO_BASE_ADR[11..4] = VIDEO_BASE_M_D[];
VIDEO_BASE_ADR[3..0] = VIDEO_BASE_L_D[];
END;

View File

@@ -0,0 +1,267 @@
-- Clearbox generated Memory Initialization File (.mif)
WIDTH=6;
DEPTH=256;
ADDRESS_RADIX=HEX;
DATA_RADIX=HEX;
CONTENT BEGIN
000 : 0F;
001 : 0E;
002 : 0D;
003 : 0C;
004 : 0B;
005 : 0A;
006 : 09;
007 : 08;
008 : 07;
009 : 06;
00a : 05;
00b : 04;
00c : 03;
00d : 02;
00e : 01;
00f : 00;
010 : 0F;
011 : 0E;
012 : 0D;
013 : 0C;
014 : 0B;
015 : 0A;
016 : 09;
017 : 08;
018 : 07;
019 : 06;
01a : 05;
01b : 04;
01c : 03;
01d : 02;
01e : 01;
01f : 00;
020 : 0F;
021 : 0E;
022 : 0D;
023 : 0C;
024 : 0B;
025 : 0A;
026 : 09;
027 : 08;
028 : 07;
029 : 06;
02a : 05;
02b : 04;
02c : 03;
02d : 02;
02e : 01;
02f : 00;
030 : 0F;
031 : 0E;
032 : 0D;
033 : 0C;
034 : 0B;
035 : 0A;
036 : 09;
037 : 08;
038 : 07;
039 : 06;
03a : 05;
03b : 04;
03c : 03;
03d : 02;
03e : 01;
03f : 00;
040 : 0F;
041 : 0E;
042 : 0D;
043 : 0C;
044 : 0B;
045 : 0A;
046 : 09;
047 : 08;
048 : 07;
049 : 06;
04a : 05;
04b : 04;
04c : 03;
04d : 02;
04e : 01;
04f : 00;
050 : 0F;
051 : 0E;
052 : 0D;
053 : 0C;
054 : 0B;
055 : 0A;
056 : 09;
057 : 08;
058 : 07;
059 : 06;
05a : 05;
05b : 04;
05c : 03;
05d : 02;
05e : 01;
05f : 00;
060 : 0F;
061 : 0E;
062 : 0D;
063 : 0C;
064 : 0B;
065 : 0A;
066 : 09;
067 : 08;
068 : 07;
069 : 06;
06a : 05;
06b : 04;
06c : 03;
06d : 02;
06e : 01;
06f : 00;
070 : 0F;
071 : 0E;
072 : 0D;
073 : 0C;
074 : 0B;
075 : 0A;
076 : 09;
077 : 08;
078 : 07;
079 : 06;
07a : 05;
07b : 04;
07c : 03;
07d : 02;
07e : 01;
07f : 00;
080 : 0F;
081 : 0E;
082 : 0D;
083 : 0C;
084 : 0B;
085 : 0A;
086 : 09;
087 : 08;
088 : 07;
089 : 06;
08a : 05;
08b : 04;
08c : 03;
08d : 02;
08e : 01;
08f : 00;
090 : 0F;
091 : 0E;
092 : 0D;
093 : 0C;
094 : 0B;
095 : 0A;
096 : 09;
097 : 08;
098 : 07;
099 : 06;
09a : 05;
09b : 04;
09c : 03;
09d : 02;
09e : 01;
09f : 00;
0a0 : 0F;
0a1 : 0E;
0a2 : 0D;
0a3 : 0C;
0a4 : 0B;
0a5 : 0A;
0a6 : 09;
0a7 : 08;
0a8 : 07;
0a9 : 06;
0aa : 05;
0ab : 04;
0ac : 03;
0ad : 02;
0ae : 01;
0af : 00;
0b0 : 0F;
0b1 : 0E;
0b2 : 0D;
0b3 : 0C;
0b4 : 0B;
0b5 : 0A;
0b6 : 09;
0b7 : 08;
0b8 : 07;
0b9 : 06;
0ba : 05;
0bb : 04;
0bc : 03;
0bd : 02;
0be : 01;
0bf : 00;
0c0 : 0F;
0c1 : 0E;
0c2 : 0D;
0c3 : 0C;
0c4 : 0B;
0c5 : 0A;
0c6 : 09;
0c7 : 08;
0c8 : 07;
0c9 : 06;
0ca : 05;
0cb : 04;
0cc : 03;
0cd : 02;
0ce : 01;
0cf : 00;
0d0 : 0F;
0d1 : 0E;
0d2 : 0D;
0d3 : 0C;
0d4 : 0B;
0d5 : 0A;
0d6 : 09;
0d7 : 08;
0d8 : 07;
0d9 : 06;
0da : 05;
0db : 04;
0dc : 03;
0dd : 02;
0de : 01;
0df : 00;
0e0 : 0F;
0e1 : 0E;
0e2 : 0D;
0e3 : 0C;
0e4 : 0B;
0e5 : 0A;
0e6 : 09;
0e7 : 08;
0e8 : 07;
0e9 : 06;
0ea : 05;
0eb : 04;
0ec : 03;
0ed : 02;
0ee : 01;
0ef : 00;
0f0 : 0F;
0f1 : 0E;
0f2 : 0D;
0f3 : 0C;
0f4 : 0B;
0f5 : 0A;
0f6 : 09;
0f7 : 08;
0f8 : 07;
0f9 : 06;
0fa : 05;
0fb : 04;
0fc : 03;
0fd : 02;
0fe : 01;
0ff : 00;
END;

View File

@@ -0,0 +1,675 @@
TITLE "VIDEO MODUSE UND CLUT CONTROL";
-- CREATED BY FREDI ASCHWANDEN
INCLUDE "lpm_bustri_WORD.inc";
INCLUDE "lpm_bustri_BYT.inc";
-- {{ALTERA_PARAMETERS_BEGIN}} DO NOT REMOVE THIS LINE!
-- {{ALTERA_PARAMETERS_END}} DO NOT REMOVE THIS LINE!
SUBDESIGN VIDEO_MOD_MUX_CLUTCTR
(
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
nRSTO : INPUT;
MAIN_CLK : INPUT;
nFB_CS1 : INPUT;
nFB_CS2 : INPUT;
nFB_CS3 : INPUT;
nFB_WR : INPUT;
nFB_OE : INPUT;
FB_SIZE0 : INPUT;
FB_SIZE1 : INPUT;
nFB_BURST : INPUT;
FB_ADR[31..0] : INPUT;
CLK33M : INPUT;
CLK25M : INPUT;
BLITTER_RUN : INPUT;
CLK_VIDEO : INPUT;
VR_D[8..0] : INPUT;
VR_BUSY : INPUT;
COLOR8 : OUTPUT;
ACP_CLUT_RD : OUTPUT;
COLOR1 : OUTPUT;
FALCON_CLUT_RDH : OUTPUT;
FALCON_CLUT_RDL : OUTPUT;
FALCON_CLUT_WR[3..0] : OUTPUT;
ST_CLUT_RD : OUTPUT;
ST_CLUT_WR[1..0] : OUTPUT;
CLUT_MUX_ADR[3..0] : OUTPUT;
HSYNC : OUTPUT;
VSYNC : OUTPUT;
nBLANK : OUTPUT;
nSYNC : OUTPUT;
nPD_VGA : OUTPUT;
FIFO_RDE : OUTPUT;
COLOR2 : OUTPUT;
COLOR4 : OUTPUT;
PIXEL_CLK : OUTPUT;
CLUT_OFF[3..0] : OUTPUT;
BLITTER_ON : OUTPUT;
VIDEO_RAM_CTR[15..0] : OUTPUT;
VIDEO_MOD_TA : OUTPUT;
CCR[23..0] : OUTPUT;
CCSEL[2..0] : OUTPUT;
ACP_CLUT_WR[3..0] : OUTPUT;
INTER_ZEI : OUTPUT;
DOP_FIFO_CLR : OUTPUT;
VIDEO_RECONFIG : OUTPUT;
VR_WR : OUTPUT;
VR_RD : OUTPUT;
CLR_FIFO : OUTPUT;
FB_AD[31..0] : BIDIR;
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
)
VARIABLE
CLK17M :DFF;
CLK13M :DFF;
ACP_CLUT_CS :NODE;
ACP_CLUT :NODE;
VIDEO_PLL_CONFIG_CS :NODE;
VR_WR :DFF;
VR_DOUT[8..0] :DFFE;
VR_FRQ[7..0] :DFFE;
VIDEO_PLL_RECONFIG_CS :NODE;
VIDEO_RECONFIG :DFF;
FALCON_CLUT_CS :NODE;
FALCON_CLUT :NODE;
ST_CLUT_CS :NODE;
ST_CLUT :NODE;
FB_B[3..0] :NODE;
FB_16B[1..0] :NODE;
ST_SHIFT_MODE[1..0] :DFFE;
ST_SHIFT_MODE_CS :NODE;
FALCON_SHIFT_MODE[10..0] :DFFE;
FALCON_SHIFT_MODE_CS :NODE;
CLUT_MUX_ADR[3..0] :DFF;
CLUT_MUX_AV[1..0][3..0] :DFF;
ACP_VCTR_CS :NODE;
ACP_VCTR[31..0] :DFFE;
CCR_CS :NODE;
CCR[23..0] :DFFE;
ACP_VIDEO_ON :NODE;
SYS_CTR[6..0] :DFFE;
SYS_CTR_CS :NODE;
VDL_LOF[15..0] :DFFE;
VDL_LOF_CS :NODE;
VDL_LWD[15..0] :DFFE;
VDL_LWD_CS :NODE;
-- DIV. CONTROL REGISTER
CLUT_TA :DFF; -- BRAUCHT EIN WAITSTAT
HSYNC :DFF;
HSYNC_I[7..0] :DFF;
HSY_LEN[7..0] :DFF; -- L<>NGE HSYNC PULS IN PIXEL_CLK
HSYNC_START :DFF;
LAST :DFF; -- LETZTES PIXEL EINER ZEILE ERREICHT
VSYNC :DFF;
VSYNC_START :DFFE;
VSYNC_I[2..0] :DFFE;
nBLANK :DFF;
DISP_ON :DFF;
DPO_ZL :DFFE;
DPO_ON :DFF;
DPO_OFF :DFF;
VDTRON :DFF;
VDO_ZL :DFFE;
VDO_ON :DFF;
VDO_OFF :DFF;
VHCNT[11..0] :DFF;
SUB_PIXEL_CNT[6..0] :DFFE;
VVCNT[10..0] :DFFE;
VERZ[2..0][9..0] :DFF;
RAND[6..0] :DFF;
RAND_ON :NODE;
FIFO_RDE :DFF;
CLR_FIFO :DFFE;
START_ZEILE :DFFE;
SYNC_PIX :DFF;
SYNC_PIX1 :DFF;
SYNC_PIX2 :DFF;
CCSEL[2..0] :DFF;
COLOR16 :NODE;
COLOR24 :NODE;
-- ATARI RESOLUTION
ATARI_SYNC :NODE;
ATARI_HH[31..0] :DFFE; -- HORIZONTAL TIMING 640x480
ATARI_HH_CS :NODE;
ATARI_VH[31..0] :DFFE; -- VERTIKAL TIMING 640x480
ATARI_VH_CS :NODE;
ATARI_HL[31..0] :DFFE; -- HORIZONTAL TIMING 320x240
ATARI_HL_CS :NODE;
ATARI_VL[31..0] :DFFE; -- VERTIKAL TIMING 320x240
ATARI_VL_CS :NODE;
-- HORIZONTAL
RAND_LINKS[11..0] :NODE;
HDIS_START[11..0] :NODE;
HDIS_END[11..0] :NODE;
RAND_RECHTS[11..0] :NODE;
HS_START[11..0] :NODE;
H_TOTAL[11..0] :NODE;
HDIS_LEN[11..0] :NODE;
MULF[5..0] :NODE;
VDL_HHT[11..0] :DFFE;
VDL_HHT_CS :NODE;
VDL_HBE[11..0] :DFFE;
VDL_HBE_CS :NODE;
VDL_HDB[11..0] :DFFE;
VDL_HDB_CS :NODE;
VDL_HDE[11..0] :DFFE;
VDL_HDE_CS :NODE;
VDL_HBB[11..0] :DFFE;
VDL_HBB_CS :NODE;
VDL_HSS[11..0] :DFFE;
VDL_HSS_CS :NODE;
-- VERTIKAL
RAND_OBEN[10..0] :NODE;
VDIS_START[10..0] :NODE;
VDIS_END[10..0] :NODE;
RAND_UNTEN[10..0] :NODE;
VS_START[10..0] :NODE;
V_TOTAL[10..0] :NODE;
FALCON_VIDEO :NODE;
ST_VIDEO :NODE;
INTER_ZEI :DFF;
DOP_ZEI :DFF;
DOP_FIFO_CLR :DFF;
VDL_VBE[10..0] :DFFE;
VDL_VBE_CS :NODE;
VDL_VDB[10..0] :DFFE;
VDL_VDB_CS :NODE;
VDL_VDE[10..0] :DFFE;
VDL_VDE_CS :NODE;
VDL_VBB[10..0] :DFFE;
VDL_VBB_CS :NODE;
VDL_VSS[10..0] :DFFE;
VDL_VSS_CS :NODE;
VDL_VFT[10..0] :DFFE;
VDL_VFT_CS :NODE;
VDL_VCT[8..0] :DFFE;
VDL_VCT_CS :NODE;
VDL_VMD[3..0] :DFFE;
VDL_VMD_CS :NODE;
BEGIN
-- BYT SELECT 32 BIT
FB_B0 = FB_ADR[1..0]==0; -- ADR==0
FB_B1 = FB_ADR[1..0]==1 -- ADR==1
# FB_SIZE1 & !FB_SIZE0 & !FB_ADR1 -- HIGH WORD
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B2 = FB_ADR[1..0]==2 -- ADR==2
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B3 = FB_ADR[1..0]==3 -- ADR==3
# FB_SIZE1 & !FB_SIZE0 & FB_ADR1 -- LOW WORD
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
-- BYT SELECT 16 BIT
FB_16B0 = FB_ADR[0]==0; -- ADR==0
FB_16B1 = FB_ADR[0]==1 -- ADR==1
# !(!FB_SIZE1 & FB_SIZE0); -- NOT BYT
-- ACP CLUT --
ACP_CLUT_CS = !nFB_CS2 & FB_ADR[27..10]==H"0"; -- 0-3FF/1024
ACP_CLUT_RD = ACP_CLUT_CS & !nFB_OE;
ACP_CLUT_WR[] = FB_B[] & ACP_CLUT_CS & !nFB_WR;
CLUT_TA.CLK = MAIN_CLK;
CLUT_TA = (ACP_CLUT_CS # FALCON_CLUT_CS # ST_CLUT_CS) & !VIDEO_MOD_TA;
--FALCON CLUT --
FALCON_CLUT_CS = !nFB_CS1 & FB_ADR[19..10]==H"3E6"; -- $F9800/$400
FALCON_CLUT_RDH = FALCON_CLUT_CS & !nFB_OE & !FB_ADR1; -- HIGH WORD
FALCON_CLUT_RDL = FALCON_CLUT_CS & !nFB_OE & FB_ADR1; -- LOW WORD
FALCON_CLUT_WR[1..0] = FB_16B[] & !FB_ADR1 & FALCON_CLUT_CS & !nFB_WR;
FALCON_CLUT_WR[3..2] = FB_16B[] & FB_ADR1 & FALCON_CLUT_CS & !nFB_WR;
-- ST CLUT --
ST_CLUT_CS = !nFB_CS1 & FB_ADR[19..5]==H"7C12"; -- $F8240/$20
ST_CLUT_RD = ST_CLUT_CS & !nFB_OE;
ST_CLUT_WR[] = FB_16B[] & ST_CLUT_CS & !nFB_WR;
-- ST SHIFT MODE
ST_SHIFT_MODE[].CLK = MAIN_CLK;
ST_SHIFT_MODE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C130"; -- $F8260/2
ST_SHIFT_MODE[] = FB_AD[25..24];
ST_SHIFT_MODE[].ENA = ST_SHIFT_MODE_CS & !nFB_WR & FB_B0;
COLOR1 = ST_SHIFT_MODE[]==B"10" & !COLOR8 & ST_VIDEO & !ACP_VIDEO_ON; -- MONO
COLOR2 = ST_SHIFT_MODE[]==B"01" & !COLOR8 & ST_VIDEO & !ACP_VIDEO_ON; -- 4 FARBEN
COLOR4 = ST_SHIFT_MODE[]==B"00" & !COLOR8 & ST_VIDEO & !ACP_VIDEO_ON; -- 16 FARBEN
-- FALCON SHIFT MODE
FALCON_SHIFT_MODE[].CLK = MAIN_CLK;
FALCON_SHIFT_MODE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C133"; -- $F8266/2
FALCON_SHIFT_MODE[] = FB_AD[26..16];
FALCON_SHIFT_MODE[10..8].ENA = FALCON_SHIFT_MODE_CS & !nFB_WR & FB_B2;
FALCON_SHIFT_MODE[7..0].ENA = FALCON_SHIFT_MODE_CS & !nFB_WR & FB_B3;
CLUT_OFF[3..0] = FALCON_SHIFT_MODE[3..0] & COLOR4;
COLOR1 = FALCON_SHIFT_MODE10 & !COLOR16 & !COLOR8 & FALCON_VIDEO & !ACP_VIDEO_ON;
COLOR8 = FALCON_SHIFT_MODE4 & !COLOR16 & FALCON_VIDEO & !ACP_VIDEO_ON;
COLOR16 = FALCON_SHIFT_MODE8 & FALCON_VIDEO & !ACP_VIDEO_ON;
COLOR4 = !COLOR1 & !COLOR16 & !COLOR8 & FALCON_VIDEO & !ACP_VIDEO_ON;
-- ACP VIDEO CONTROL BIT 0=ACP VIDEO ON, 1=POWER ON VIDEO DAC, 2=ACP 24BIT,3=ACP 16BIT,4=ACP 8BIT,5=ACP 1BIT, 6=FALCON SHIFT MODE;7=ST SHIFT MODE;9..8= VCLK FREQUENZ;15=-SYNC ALLOWED; 31..16=VIDEO_RAM_CTR,25=RANDFARBE EINSCHALTEN, 26=STANDARD ATARI SYNCS
ACP_VCTR[].CLK = MAIN_CLK;
ACP_VCTR_CS = !nFB_CS2 & FB_ADR[27..2]==H"100"; -- $400/4
ACP_VCTR[31..8] = FB_AD[31..8];
ACP_VCTR[5..0] = FB_AD[5..0];
ACP_VCTR[31..24].ENA = ACP_VCTR_CS & FB_B0 & !nFB_WR;
ACP_VCTR[23..16].ENA = ACP_VCTR_CS & FB_B1 & !nFB_WR;
ACP_VCTR[15..8].ENA = ACP_VCTR_CS & FB_B2 & !nFB_WR;
ACP_VCTR[5..0].ENA = ACP_VCTR_CS & FB_B3 & !nFB_WR;
ACP_VIDEO_ON = ACP_VCTR0;
nPD_VGA = ACP_VCTR1;
-- ATARI MODUS
ATARI_SYNC = ACP_VCTR26; -- WENN 1 AUTOMATISCHE AUFL<46>SUNG
-- HORIZONTAL TIMING 640x480
ATARI_HH[].CLK = MAIN_CLK;
ATARI_HH_CS = !nFB_CS2 & FB_ADR[27..2]==H"104"; -- $410/4
ATARI_HH[] = FB_AD[];
ATARI_HH[31..24].ENA = ATARI_HH_CS & FB_B0 & !nFB_WR;
ATARI_HH[23..16].ENA = ATARI_HH_CS & FB_B1 & !nFB_WR;
ATARI_HH[15..8].ENA = ATARI_HH_CS & FB_B2 & !nFB_WR;
ATARI_HH[7..0].ENA = ATARI_HH_CS & FB_B3 & !nFB_WR;
-- VERTIKAL TIMING 640x480
ATARI_VH[].CLK = MAIN_CLK;
ATARI_VH_CS = !nFB_CS2 & FB_ADR[27..2]==H"105"; -- $414/4
ATARI_VH[] = FB_AD[];
ATARI_VH[31..24].ENA = ATARI_VH_CS & FB_B0 & !nFB_WR;
ATARI_VH[23..16].ENA = ATARI_VH_CS & FB_B1 & !nFB_WR;
ATARI_VH[15..8].ENA = ATARI_VH_CS & FB_B2 & !nFB_WR;
ATARI_VH[7..0].ENA = ATARI_VH_CS & FB_B3 & !nFB_WR;
-- HORIZONTAL TIMING 320x240
ATARI_HL[].CLK = MAIN_CLK;
ATARI_HL_CS = !nFB_CS2 & FB_ADR[27..2]==H"106"; -- $418/4
ATARI_HL[] = FB_AD[];
ATARI_HL[31..24].ENA = ATARI_HL_CS & FB_B0 & !nFB_WR;
ATARI_HL[23..16].ENA = ATARI_HL_CS & FB_B1 & !nFB_WR;
ATARI_HL[15..8].ENA = ATARI_HL_CS & FB_B2 & !nFB_WR;
ATARI_HL[7..0].ENA = ATARI_HL_CS & FB_B3 & !nFB_WR;
-- VERTIKAL TIMING 320x240
ATARI_VL[].CLK = MAIN_CLK;
ATARI_VL_CS = !nFB_CS2 & FB_ADR[27..2]==H"107"; -- $41C/4
ATARI_VL[] = FB_AD[];
ATARI_VL[31..24].ENA = ATARI_VL_CS & FB_B0 & !nFB_WR;
ATARI_VL[23..16].ENA = ATARI_VL_CS & FB_B1 & !nFB_WR;
ATARI_VL[15..8].ENA = ATARI_VL_CS & FB_B2 & !nFB_WR;
ATARI_VL[7..0].ENA = ATARI_VL_CS & FB_B3 & !nFB_WR;
-- VIDEO PLL CONFIG
VIDEO_PLL_CONFIG_CS = !nFB_CS2 & FB_ADR[27..9]==H"3" & FB_B0 & FB_B1; -- $(F)000'0600-7FF ->6/2 WORD RESP LONG ONLY
VR_WR.CLK = MAIN_CLK;
VR_WR = VIDEO_PLL_CONFIG_CS & !nFB_WR & !VR_BUSY & !VR_WR;
VR_RD = VIDEO_PLL_CONFIG_CS & nFB_WR & !VR_BUSY;
VR_DOUT[].CLK = MAIN_CLK;
VR_DOUT[].ENA = !VR_BUSY;
VR_DOUT[] = VR_D[];
VR_FRQ[].CLK = MAIN_CLK;
VR_FRQ[].ENA = VR_WR & FB_ADR[8..0]==H"04";
VR_FRQ[] = FB_AD[23..16];
-- VIDEO PLL RECONFIG
VIDEO_PLL_RECONFIG_CS = !nFB_CS2 & FB_ADR[27..0]==H"800" & FB_B0; -- $(F)000'0800
VIDEO_RECONFIG.CLK = MAIN_CLK;
VIDEO_RECONFIG = VIDEO_PLL_RECONFIG_CS & !nFB_WR & !VR_BUSY & !VIDEO_RECONFIG;
------------------------------------------------------------------------------------------------------------------------
VIDEO_RAM_CTR[] = ACP_VCTR[31..16];
-------------- COLOR MODE IM ACP SETZEN
COLOR1 = ACP_VCTR5 & !ACP_VCTR4 & !ACP_VCTR3 & !ACP_VCTR2 & ACP_VIDEO_ON;
COLOR8 = ACP_VCTR4 & !ACP_VCTR3 & !ACP_VCTR2 & ACP_VIDEO_ON;
COLOR16 = ACP_VCTR3 & !ACP_VCTR2 & ACP_VIDEO_ON;
COLOR24 = ACP_VCTR2 & ACP_VIDEO_ON;
ACP_CLUT = ACP_VIDEO_ON & (COLOR1 # COLOR8) # ST_VIDEO & COLOR1;
-- ST ODER FALCON SHIFT MODE SETZEN WENN WRITE X..SHIFT REGISTER
ACP_VCTR7 = FALCON_SHIFT_MODE_CS & !nFB_WR & !ACP_VIDEO_ON;
ACP_VCTR6 = ST_SHIFT_MODE_CS & !nFB_WR & !ACP_VIDEO_ON;
ACP_VCTR[7..6].ENA = FALCON_SHIFT_MODE_CS & !nFB_WR # ST_SHIFT_MODE_CS & !nFB_WR # ACP_VCTR_CS & FB_B3 & !nFB_WR & FB_AD0;
FALCON_VIDEO = ACP_VCTR7;
FALCON_CLUT = FALCON_VIDEO & !ACP_VIDEO_ON & !COLOR16;
ST_VIDEO = ACP_VCTR6;
ST_CLUT = ST_VIDEO & !ACP_VIDEO_ON & !FALCON_CLUT & !COLOR1;
CCSEL[].CLK = PIXEL_CLK;
CCSEL[] = B"000" & ST_CLUT -- ONLY FOR INFORMATION
# B"001" & FALCON_CLUT
# B"100" & ACP_CLUT
# B"101" & COLOR16
# B"110" & COLOR24
# B"111" & RAND_ON;
-- DIVERSE (VIDEO)-REGISTER ----------------------------
-- RANDFARBE
CCR[].CLK = MAIN_CLK;
CCR_CS = !nFB_CS2 & FB_ADR[27..2]==H"101"; -- $404/4
CCR[] = FB_AD[23..0];
CCR[23..16].ENA = CCR_CS & FB_B1 & !nFB_WR;
CCR[15..8].ENA = CCR_CS & FB_B2 & !nFB_WR;
CCR[7..0].ENA = CCR_CS & FB_B3 & !nFB_WR;
--SYS CTR
SYS_CTR_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C003"; -- $8006/2
SYS_CTR[].CLK = MAIN_CLK;
SYS_CTR[6..0] = FB_AD[22..16];
SYS_CTR[6..0].ENA = SYS_CTR_CS & !nFB_WR & FB_B3;
BLITTER_ON = !SYS_CTR3;
--VDL_LOF
VDL_LOF_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C107"; -- $820E/2
VDL_LOF[].CLK = MAIN_CLK;
VDL_LOF[] = FB_AD[31..16];
VDL_LOF[15..8].ENA = VDL_LOF_CS & !nFB_WR & FB_B2;
VDL_LOF[7..0].ENA = VDL_LOF_CS & !nFB_WR & FB_B3;
--VDL_LWD
VDL_LWD_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C108"; -- $8210/2
VDL_LWD[].CLK = MAIN_CLK;
VDL_LWD[] = FB_AD[31..16];
VDL_LWD[15..8].ENA = VDL_LWD_CS & !nFB_WR & FB_B0;
VDL_LWD[7..0].ENA = VDL_LWD_CS & !nFB_WR & FB_B1;
-- HORIZONTAL
-- VDL_HHT
VDL_HHT_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C141"; -- $8282/2
VDL_HHT[].CLK = MAIN_CLK;
VDL_HHT[] = FB_AD[27..16];
VDL_HHT[11..8].ENA = VDL_HHT_CS & !nFB_WR & FB_B2;
VDL_HHT[7..0].ENA = VDL_HHT_CS & !nFB_WR & FB_B3;
-- VDL_HBE
VDL_HBE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C143"; -- $8286/2
VDL_HBE[].CLK = MAIN_CLK;
VDL_HBE[] = FB_AD[27..16];
VDL_HBE[11..8].ENA = VDL_HBE_CS & !nFB_WR & FB_B2;
VDL_HBE[7..0].ENA = VDL_HBE_CS & !nFB_WR & FB_B3;
-- VDL_HDB
VDL_HDB_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C144"; -- $8288/2
VDL_HDB[].CLK = MAIN_CLK;
VDL_HDB[] = FB_AD[27..16];
VDL_HDB[11..8].ENA = VDL_HDB_CS & !nFB_WR & FB_B0;
VDL_HDB[7..0].ENA = VDL_HDB_CS & !nFB_WR & FB_B1;
-- VDL_HDE
VDL_HDE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C145"; -- $828A/2
VDL_HDE[].CLK = MAIN_CLK;
VDL_HDE[] = FB_AD[27..16];
VDL_HDE[11..8].ENA = VDL_HDE_CS & !nFB_WR & FB_B2;
VDL_HDE[7..0].ENA = VDL_HDE_CS & !nFB_WR & FB_B3;
-- VDL_HBB
VDL_HBB_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C142"; -- $8284/2
VDL_HBB[].CLK = MAIN_CLK;
VDL_HBB[] = FB_AD[27..16];
VDL_HBB[11..8].ENA = VDL_HBB_CS & !nFB_WR & FB_B0;
VDL_HBB[7..0].ENA = VDL_HBB_CS & !nFB_WR & FB_B1;
-- VDL_HSS
VDL_HSS_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C146"; -- $828C/2
VDL_HSS[].CLK = MAIN_CLK;
VDL_HSS[] = FB_AD[27..16];
VDL_HSS[11..8].ENA = VDL_HSS_CS & !nFB_WR & FB_B0;
VDL_HSS[7..0].ENA = VDL_HSS_CS & !nFB_WR & FB_B1;
-- VERTIKAL
-- VDL_VBE
VDL_VBE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C153"; -- $82A6/2
VDL_VBE[].CLK = MAIN_CLK;
VDL_VBE[] = FB_AD[26..16];
VDL_VBE[10..8].ENA = VDL_VBE_CS & !nFB_WR & FB_B2;
VDL_VBE[7..0].ENA = VDL_VBE_CS & !nFB_WR & FB_B3;
-- VDL_VDB
VDL_VDB_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C154"; -- $82A8/2
VDL_VDB[].CLK = MAIN_CLK;
VDL_VDB[] = FB_AD[26..16];
VDL_VDB[10..8].ENA = VDL_VDB_CS & !nFB_WR & FB_B0;
VDL_VDB[7..0].ENA = VDL_VDB_CS & !nFB_WR & FB_B1;
-- VDL_VDE
VDL_VDE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C155"; -- $82AA/2
VDL_VDE[].CLK = MAIN_CLK;
VDL_VDE[] = FB_AD[26..16];
VDL_VDE[10..8].ENA = VDL_VDE_CS & !nFB_WR & FB_B2;
VDL_VDE[7..0].ENA = VDL_VDE_CS & !nFB_WR & FB_B3;
-- VDL_VBB
VDL_VBB_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C152"; -- $82A4/2
VDL_VBB[].CLK = MAIN_CLK;
VDL_VBB[] = FB_AD[26..16];
VDL_VBB[10..8].ENA = VDL_VBB_CS & !nFB_WR & FB_B0;
VDL_VBB[7..0].ENA = VDL_VBB_CS & !nFB_WR & FB_B1;
-- VDL_VSS
VDL_VSS_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C156"; -- $82AC/2
VDL_VSS[].CLK = MAIN_CLK;
VDL_VSS[] = FB_AD[26..16];
VDL_VSS[10..8].ENA = VDL_VSS_CS & !nFB_WR & FB_B0;
VDL_VSS[7..0].ENA = VDL_VSS_CS & !nFB_WR & FB_B1;
-- VDL_VFT
VDL_VFT_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C151"; -- $82A2/2
VDL_VFT[].CLK = MAIN_CLK;
VDL_VFT[] = FB_AD[26..16];
VDL_VFT[10..8].ENA = VDL_VFT_CS & !nFB_WR & FB_B2;
VDL_VFT[7..0].ENA = VDL_VFT_CS & !nFB_WR & FB_B3;
-- VDL_VCT
VDL_VCT_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C160"; -- $82C0/2
VDL_VCT[].CLK = MAIN_CLK;
VDL_VCT[] = FB_AD[24..16];
VDL_VCT[8].ENA = VDL_VCT_CS & !nFB_WR & FB_B0;
VDL_VCT[7..0].ENA = VDL_VCT_CS & !nFB_WR & FB_B1;
-- VDL_VMD
VDL_VMD_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C161"; -- $82C2/2
VDL_VMD[].CLK = MAIN_CLK;
VDL_VMD[] = FB_AD[19..16];
VDL_VMD[3..0].ENA = VDL_VMD_CS & !nFB_WR & FB_B3;
--- REGISTER OUT
FB_AD[31..16] = lpm_bustri_WORD(
ST_SHIFT_MODE_CS & (0,ST_SHIFT_MODE[],B"00000000")
# FALCON_SHIFT_MODE_CS & (0,FALCON_SHIFT_MODE[])
# SYS_CTR_CS & (B"100000000",SYS_CTR[6..4],!BLITTER_RUN,SYS_CTR[2..0])
# VDL_LOF_CS & VDL_LOF[]
# VDL_LWD_CS & VDL_LWD[]
# VDL_HBE_CS & (0,VDL_HBE[])
# VDL_HDB_CS & (0,VDL_HDB[])
# VDL_HDE_CS & (0,VDL_HDE[])
# VDL_HBB_CS & (0,VDL_HBB[])
# VDL_HSS_CS & (0,VDL_HSS[])
# VDL_HHT_CS & (0,VDL_HHT[])
# VDL_VBE_CS & (0,VDL_VBE[])
# VDL_VDB_CS & (0,VDL_VDB[])
# VDL_VDE_CS & (0,VDL_VDE[])
# VDL_VBB_CS & (0,VDL_VBB[])
# VDL_VSS_CS & (0,VDL_VSS[])
# VDL_VFT_CS & (0,VDL_VFT[])
# VDL_VCT_CS & (0,VDL_VCT[])
# VDL_VMD_CS & (0,VDL_VMD[])
# ACP_VCTR_CS & ACP_VCTR[31..16]
# ATARI_HH_CS & ATARI_HH[31..16]
# ATARI_VH_CS & ATARI_VH[31..16]
# ATARI_HL_CS & ATARI_HL[31..16]
# ATARI_VL_CS & ATARI_VL[31..16]
# CCR_CS & (0,CCR[23..16])
# VIDEO_PLL_CONFIG_CS & (0,VR_DOUT[])
# VIDEO_PLL_RECONFIG_CS & (VR_BUSY,B"0000",VR_WR,VR_RD,VIDEO_RECONFIG,H"FA")
,(ST_SHIFT_MODE_CS # FALCON_SHIFT_MODE_CS # ACP_VCTR_CS # CCR_CS # SYS_CTR_CS # VDL_LOF_CS # VDL_LWD_CS
# VDL_HBE_CS # VDL_HDB_CS # VDL_HDE_CS # VDL_HBB_CS # VDL_HSS_CS # VDL_HHT_CS
# ATARI_HH_CS # ATARI_VH_CS # ATARI_HL_CS # ATARI_VL_CS # VIDEO_PLL_CONFIG_CS # VIDEO_PLL_RECONFIG_CS
# VDL_VBE_CS # VDL_VDB_CS # VDL_VDE_CS # VDL_VBB_CS # VDL_VSS_CS # VDL_VFT_CS # VDL_VCT_CS # VDL_VMD_CS) & !nFB_OE);
FB_AD[15..0] = lpm_bustri_WORD(
ACP_VCTR_CS & ACP_VCTR[15..0]
# ATARI_HH_CS & ATARI_HH[15..0]
# ATARI_VH_CS & ATARI_VH[15..0]
# ATARI_HL_CS & ATARI_HL[15..0]
# ATARI_VL_CS & ATARI_VL[15..0]
# CCR_CS & CCR[15..0]
,(ACP_VCTR_CS # CCR_CS # ATARI_HH_CS # ATARI_VH_CS # ATARI_HL_CS # ATARI_VL_CS ) & !nFB_OE);
VIDEO_MOD_TA = CLUT_TA # ST_SHIFT_MODE_CS # FALCON_SHIFT_MODE_CS # ACP_VCTR_CS # SYS_CTR_CS # VDL_LOF_CS # VDL_LWD_CS
# VDL_HBE_CS # VDL_HDB_CS # VDL_HDE_CS # VDL_HBB_CS # VDL_HSS_CS # VDL_HHT_CS
# ATARI_HH_CS # ATARI_VH_CS # ATARI_HL_CS # ATARI_VL_CS
# VDL_VBE_CS # VDL_VDB_CS # VDL_VDE_CS # VDL_VBB_CS # VDL_VSS_CS # VDL_VFT_CS # VDL_VCT_CS # VDL_VMD_CS;
-- VIDEO AUSGABE SETZEN
CLK17M.CLK = CLK33M;
CLK17M = !CLK17M;
CLK13M.CLK = CLK25M;
CLK13M = !CLK13M;
PIXEL_CLK = CLK13M & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & ( VDL_VMD2 & VDL_VCT2 # VDL_VCT0)
# CLK17M & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & ( VDL_VMD2 & !VDL_VCT2 # VDL_VCT0)
# CLK25M & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & !VDL_VMD2 & VDL_VCT2 & !VDL_VCT0
# CLK33M & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & !VDL_VMD2 & !VDL_VCT2 & !VDL_VCT0
# CLK25M & ACP_VIDEO_ON & ACP_VCTR[9..8]==B"00"
# CLK33M & ACP_VIDEO_ON & ACP_VCTR[9..8]==B"01"
# CLK_VIDEO & ACP_VIDEO_ON & ACP_VCTR[9];
--------------------------------------------------------------
-- HORIZONTALE SYNC L<>NGE in PIXEL_CLK
----------------------------------------------------------------
HSY_LEN[].CLK = MAIN_CLK;
HSY_LEN[] = 14 & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & ( VDL_VMD2 & VDL_VCT2 # VDL_VCT0)
# 16 & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & ( VDL_VMD2 & !VDL_VCT2 # VDL_VCT0)
# 28 & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & !VDL_VMD2 & VDL_VCT2 & !VDL_VCT0
# 32 & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & !VDL_VMD2 & !VDL_VCT2 & !VDL_VCT0
# 28 & ACP_VIDEO_ON & ACP_VCTR[9..8]==B"00"
# 32 & ACP_VIDEO_ON & ACP_VCTR[9..8]==B"01"
# 16 + (0,VR_FRQ[7..1]) & ACP_VIDEO_ON & ACP_VCTR[9]; -- hsync puls length in pixeln=frequenz/ = 500ns
MULF[] = 2 & !ST_VIDEO & VDL_VMD2 -- MULTIPLIKATIONS FAKTOR
# 4 & !ST_VIDEO & !VDL_VMD2
# 16 & ST_VIDEO & VDL_VMD2
# 32 & ST_VIDEO & !VDL_VMD2;
HDIS_LEN[] = 320 & VDL_VMD2 -- BREITE IN PIXELN
# 640 & !VDL_VMD2;
-- DOPPELZEILENMODUS
DOP_ZEI.CLK = MAIN_CLK;
DOP_ZEI = VDL_VMD0 & ST_VIDEO; -- ZEILENVERDOPPELUNG EIN AUS
INTER_ZEI.CLK = PIXEL_CLK;
INTER_ZEI = DOP_ZEI & VVCNT0!=VDIS_START0 & VVCNT[]!=0 & VHCNT[]<(HDIS_END[]-1) -- EINSCHIEBEZEILE AUF "DOPPEL" ZEILEN UND ZEILE NULL WEGEN SYNC
# DOP_ZEI & VVCNT0==VDIS_START0 & VVCNT[]!=0 & VHCNT[]>(HDIS_END[]-2); -- EINSCHIEBEZEILE AUF "NORMAL" ZEILEN UND ZEILE NULL WEGEN SYNC
DOP_FIFO_CLR.CLK = PIXEL_CLK;
DOP_FIFO_CLR = INTER_ZEI & HSYNC_START # SYNC_PIX; -- DOPPELZEILENFIFO L<>SCHEN AM ENDE DER DOPPELZEILE UND BEI MAIN FIFO START
RAND_LINKS[] = VDL_HBE[] & ACP_VIDEO_ON
# 21 & !ACP_VIDEO_ON & ATARI_SYNC & VDL_VMD2
# 42 & !ACP_VIDEO_ON & ATARI_SYNC & !VDL_VMD2
# VDL_HBE[] * (0,MULF[5..1]) & !ACP_VIDEO_ON & !ATARI_SYNC; --
HDIS_START[] = VDL_HDB[] & ACP_VIDEO_ON
# RAND_LINKS[]+1 & !ACP_VIDEO_ON; --
HDIS_END[] = VDL_HDE[] & ACP_VIDEO_ON
# RAND_LINKS[]+HDIS_LEN[] & !ACP_VIDEO_ON; --
RAND_RECHTS[] = VDL_HBB[] & ACP_VIDEO_ON
# HDIS_END[]+1 & !ACP_VIDEO_ON; --
HS_START[] = VDL_HSS[] & ACP_VIDEO_ON
# ATARI_HL[11..0] & !ACP_VIDEO_ON & ATARI_SYNC & VDL_VMD2
# ATARI_HH[11..0] & !ACP_VIDEO_ON & ATARI_SYNC & !VDL_VMD2
# (VDL_HHT[]+1+VDL_HSS[]) * (0,MULF[5..1]) & !ACP_VIDEO_ON & !ATARI_SYNC; --
H_TOTAL[] = VDL_HHT[] & ACP_VIDEO_ON
# ATARI_HL[27..16] & !ACP_VIDEO_ON & ATARI_SYNC & VDL_VMD2
# ATARI_HH[27..16] & !ACP_VIDEO_ON & ATARI_SYNC & !VDL_VMD2
# (VDL_HHT[]+2) * (0,MULF[]) & !ACP_VIDEO_ON & !ATARI_SYNC; --
RAND_OBEN[] = VDL_VBE[] & ACP_VIDEO_ON
# 31 & !ACP_VIDEO_ON & ATARI_SYNC
# (0,VDL_VBE[10..1]) & !ACP_VIDEO_ON & !ATARI_SYNC;
VDIS_START[] = VDL_VDB[] & ACP_VIDEO_ON
# 32 & !ACP_VIDEO_ON & ATARI_SYNC
# (0,VDL_VDB[10..1])+1 & !ACP_VIDEO_ON & !ATARI_SYNC;
VDIS_END[] = VDL_VDE[] & ACP_VIDEO_ON
# 431 & !ACP_VIDEO_ON & ATARI_SYNC & ST_VIDEO
# 511 & !ACP_VIDEO_ON & ATARI_SYNC & !ST_VIDEO
# (0,VDL_VDE[10..1]) & !ACP_VIDEO_ON & !ATARI_SYNC;
RAND_UNTEN[] = VDL_VBB[] & ACP_VIDEO_ON
# VDIS_END[]+1 & !ACP_VIDEO_ON & ATARI_SYNC
# (0,VDL_VBB[10..1])+1 & !ACP_VIDEO_ON & !ATARI_SYNC;
VS_START[] = VDL_VSS[] & ACP_VIDEO_ON
# ATARI_VL[10..0] & !ACP_VIDEO_ON & ATARI_SYNC & VDL_VMD2
# ATARI_VH[10..0] & !ACP_VIDEO_ON & ATARI_SYNC & !VDL_VMD2
# (0,VDL_VSS[10..1]) & !ACP_VIDEO_ON & !ATARI_SYNC;
V_TOTAL[] = VDL_VFT[] & ACP_VIDEO_ON
# ATARI_VL[26..16] & !ACP_VIDEO_ON & ATARI_SYNC & VDL_VMD2
# ATARI_VH[26..16] & !ACP_VIDEO_ON & ATARI_SYNC & !VDL_VMD2
# (0,VDL_VFT[10..1]) & !ACP_VIDEO_ON & !ATARI_SYNC;
-- Z<>HLER
LAST.CLK = PIXEL_CLK;
LAST = VHCNT[]==(H_TOTAL[]-2);
VHCNT[].CLK = PIXEL_CLK;
VHCNT[] = (VHCNT[] + 1) & !LAST;
VVCNT[].CLK = PIXEL_CLK;
VVCNT[].ENA = LAST;
VVCNT[] = (VVCNT[] + 1) & (VVCNT[]!=V_TOTAL[]-1);
-- DISPLAY ON OFF
DPO_ZL.CLK = PIXEL_CLK;
DPO_ZL = (VVCNT[]>RAND_OBEN[]-1) & (VVCNT[]<RAND_UNTEN[]-1); -- 1 ZEILE DAVOR ON OFF
DPO_ZL.ENA = LAST; -- AM ZEILENENDE <20>BERNEHMEN
DPO_ON.CLK = PIXEL_CLK;
DPO_ON = VHCNT[]==RAND_LINKS[]; -- BESSER EINZELN WEGEN TIMING
DPO_OFF.CLK = PIXEL_CLK;
DPO_OFF = VHCNT[]==(RAND_RECHTS[]-1);
DISP_ON.CLK = PIXEL_CLK;
DISP_ON = DISP_ON & !DPO_OFF
# DPO_ON & DPO_ZL;
-- DATENTRANSFER ON OFF
VDO_ON.CLK = PIXEL_CLK;
VDO_ON = VHCNT[]==(HDIS_START[]-1); -- BESSER EINZELN WEGEN TIMING
VDO_OFF.CLK = PIXEL_CLK;
VDO_OFF = VHCNT[]==HDIS_END[];
VDO_ZL.CLK = PIXEL_CLK;
VDO_ZL.ENA = LAST; -- AM ZEILENENDE <20>BERNEHMEN
VDO_ZL = (VVCNT[]>=(VDIS_START[]-1)) & (VVCNT[]<VDIS_END[]); -- 1 ZEILE DAVOR ON OFF
VDTRON.CLK = PIXEL_CLK;
VDTRON = VDTRON & !VDO_OFF
# VDO_ON & VDO_ZL;
-- VERZ<52>GERUNG UND SYNC
HSYNC_START.CLK = PIXEL_CLK;
HSYNC_START = VHCNT[]==HS_START[]-3;
HSYNC_I[].CLK = PIXEL_CLK;
HSYNC_I[] = HSY_LEN[] & HSYNC_START
# (HSYNC_I[]-1) & !HSYNC_START & HSYNC_I[]!=0;
VSYNC_START.CLK = PIXEL_CLK;
VSYNC_START.ENA = LAST;
VSYNC_START = VVCNT[]==(VS_START[]-3); -- start am ende der Zeile vor dem vsync
VSYNC_I[].CLK = PIXEL_CLK;
VSYNC_I[].ENA = LAST; -- start am ende der Zeile vor dem vsync
VSYNC_I[] = 3 & VSYNC_START -- 3 zeilen vsync length
# (VSYNC_I[]-1) & !VSYNC_START & VSYNC_I[]!=0; -- runterz<72>hlen bis 0
VERZ[][].CLK = PIXEL_CLK;
VERZ[][1] = VERZ[][0];
VERZ[][2] = VERZ[][1];
VERZ[][3] = VERZ[][2];
VERZ[][4] = VERZ[][3];
VERZ[][5] = VERZ[][4];
VERZ[][6] = VERZ[][5];
VERZ[][7] = VERZ[][6];
VERZ[][8] = VERZ[][7];
VERZ[][9] = VERZ[][8];
VERZ[0][0] = DISP_ON;
VERZ[1][0] = HSYNC_I[]!=0;
VERZ[1][0] = (!ACP_VCTR15 # !VDL_VCT6) & HSYNC_I[]!=0
# ACP_VCTR15 & VDL_VCT6 & HSYNC_I[]==0; -- NUR M<>GLICH WENN BEIDE
VERZ[2][0] = (!ACP_VCTR15 # !VDL_VCT5) & VSYNC_I[]!=0
# ACP_VCTR15 & VDL_VCT5 & VSYNC_I[]==0; -- NUR M<>GLICH WENN BEIDE
nBLANK.CLK = PIXEL_CLK;
nBLANK = VERZ[0][8];
HSYNC.CLK = PIXEL_CLK;
HSYNC = VERZ[1][9];
VSYNC.CLK = PIXEL_CLK;
VSYNC = VERZ[2][9];
nSYNC = GND;
-- RANDFARBE MACHEN ------------------------------------
RAND[].CLK = PIXEL_CLK;
RAND[0] = DISP_ON & !VDTRON & ACP_VCTR25;
RAND[1] = RAND[0];
RAND[2] = RAND[1];
RAND[3] = RAND[2];
RAND[4] = RAND[3];
RAND[5] = RAND[4];
RAND[6] = RAND[5];
RAND_ON = RAND[6];
----------------------------------------------------------
CLR_FIFO.CLK = PIXEL_CLK;
CLR_FIFO.ENA = LAST;
CLR_FIFO = VVCNT[]==V_TOTAL[]-2; -- IN LETZTER ZEILE L<>SCHEN
START_ZEILE.CLK = PIXEL_CLK;
START_ZEILE.ENA = LAST;
START_ZEILE = VVCNT[]==0; -- ZEILE 1
SYNC_PIX.CLK = PIXEL_CLK;
SYNC_PIX = VHCNT[]==3 & START_ZEILE; -- SUB PIXEL Z<>HLER SYNCHRONISIEREN
SYNC_PIX1.CLK = PIXEL_CLK;
SYNC_PIX1 = VHCNT[]==5 & START_ZEILE; -- SUB PIXEL Z<>HLER SYNCHRONISIEREN
SYNC_PIX2.CLK = PIXEL_CLK;
SYNC_PIX2 = VHCNT[]==7 & START_ZEILE; -- SUB PIXEL Z<>HLER SYNCHRONISIEREN
SUB_PIXEL_CNT[].CLK = PIXEL_CLK;
SUB_PIXEL_CNT[].ENA = VDTRON # SYNC_PIX;
SUB_PIXEL_CNT[] = (SUB_PIXEL_CNT[] + 1) & !SYNC_PIX; --count up if display on sonst clear bei sync pix
FIFO_RDE.CLK = PIXEL_CLK;
FIFO_RDE = (SUB_PIXEL_CNT[6..0]==1 & COLOR1
# SUB_PIXEL_CNT[5..0]==1 & COLOR2
# SUB_PIXEL_CNT[4..0]==1 & COLOR4
# SUB_PIXEL_CNT[3..0]==1 & COLOR8
# SUB_PIXEL_CNT[2..0]==1 & COLOR16
# SUB_PIXEL_CNT[1..0]==1 & COLOR24) & VDTRON
# SYNC_PIX # SYNC_PIX1 # SYNC_PIX2; -- 3 CLOCK ZUS<55>TZLICH F<>R FIFO SHIFT DATAOUT UND SHIFT RIGTH POSITION
CLUT_MUX_ADR[].CLK = PIXEL_CLK;
CLUT_MUX_AV[][].CLK = PIXEL_CLK;
CLUT_MUX_AV[0][] = SUB_PIXEL_CNT[3..0];
CLUT_MUX_AV[1][] = CLUT_MUX_AV[0][];
CLUT_MUX_ADR[] = CLUT_MUX_AV[1][];
END;

View File

@@ -0,0 +1,675 @@
TITLE "VIDEO MODUSE UND CLUT CONTROL";
-- CREATED BY FREDI ASCHWANDEN
INCLUDE "lpm_bustri_WORD.inc";
INCLUDE "lpm_bustri_BYT.inc";
-- {{ALTERA_PARAMETERS_BEGIN}} DO NOT REMOVE THIS LINE!
-- {{ALTERA_PARAMETERS_END}} DO NOT REMOVE THIS LINE!
SUBDESIGN VIDEO_MOD_MUX_CLUTCTR
(
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
nRSTO : INPUT;
MAIN_CLK : INPUT;
nFB_CS1 : INPUT;
nFB_CS2 : INPUT;
nFB_CS3 : INPUT;
nFB_WR : INPUT;
nFB_OE : INPUT;
FB_SIZE0 : INPUT;
FB_SIZE1 : INPUT;
nFB_BURST : INPUT;
FB_ADR[31..0] : INPUT;
CLK33M : INPUT;
CLK25M : INPUT;
BLITTER_RUN : INPUT;
CLK_VIDEO : INPUT;
VR_D[8..0] : INPUT;
VR_BUSY : INPUT;
COLOR8 : OUTPUT;
ACP_CLUT_RD : OUTPUT;
COLOR1 : OUTPUT;
FALCON_CLUT_RDH : OUTPUT;
FALCON_CLUT_RDL : OUTPUT;
FALCON_CLUT_WR[3..0] : OUTPUT;
ST_CLUT_RD : OUTPUT;
ST_CLUT_WR[1..0] : OUTPUT;
CLUT_MUX_ADR[3..0] : OUTPUT;
HSYNC : OUTPUT;
VSYNC : OUTPUT;
nBLANK : OUTPUT;
nSYNC : OUTPUT;
nPD_VGA : OUTPUT;
FIFO_RDE : OUTPUT;
COLOR2 : OUTPUT;
COLOR4 : OUTPUT;
PIXEL_CLK : OUTPUT;
CLUT_OFF[3..0] : OUTPUT;
BLITTER_ON : OUTPUT;
VIDEO_RAM_CTR[15..0] : OUTPUT;
VIDEO_MOD_TA : OUTPUT;
CCR[23..0] : OUTPUT;
CCSEL[2..0] : OUTPUT;
ACP_CLUT_WR[3..0] : OUTPUT;
INTER_ZEI : OUTPUT;
DOP_FIFO_CLR : OUTPUT;
VIDEO_RECONFIG : OUTPUT;
VR_WR : OUTPUT;
VR_RD : OUTPUT;
CLR_FIFO : OUTPUT;
FB_AD[31..0] : BIDIR;
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
)
VARIABLE
CLK17M :DFF;
CLK13M :DFF;
ACP_CLUT_CS :NODE;
ACP_CLUT :NODE;
VIDEO_PLL_CONFIG_CS :NODE;
VR_WR :DFF;
VR_DOUT[8..0] :DFFE;
VR_FRQ[7..0] :DFFE;
VIDEO_PLL_RECONFIG_CS :NODE;
VIDEO_RECONFIG :DFF;
FALCON_CLUT_CS :NODE;
FALCON_CLUT :NODE;
ST_CLUT_CS :NODE;
ST_CLUT :NODE;
FB_B[3..0] :NODE;
FB_16B[1..0] :NODE;
ST_SHIFT_MODE[1..0] :DFFE;
ST_SHIFT_MODE_CS :NODE;
FALCON_SHIFT_MODE[10..0] :DFFE;
FALCON_SHIFT_MODE_CS :NODE;
CLUT_MUX_ADR[3..0] :DFF;
CLUT_MUX_AV[1..0][3..0] :DFF;
ACP_VCTR_CS :NODE;
ACP_VCTR[31..0] :DFFE;
CCR_CS :NODE;
CCR[23..0] :DFFE;
ACP_VIDEO_ON :NODE;
SYS_CTR[6..0] :DFFE;
SYS_CTR_CS :NODE;
VDL_LOF[15..0] :DFFE;
VDL_LOF_CS :NODE;
VDL_LWD[15..0] :DFFE;
VDL_LWD_CS :NODE;
-- DIV. CONTROL REGISTER
CLUT_TA :DFF; -- BRAUCHT EIN WAITSTAT
HSYNC :DFF;
HSYNC_I[7..0] :DFF;
HSY_LEN[7..0] :DFF; -- L<>NGE HSYNC PULS IN PIXEL_CLK
HSYNC_START :DFF;
LAST :DFF; -- LETZTES PIXEL EINER ZEILE ERREICHT
VSYNC :DFF;
VSYNC_START :DFFE;
VSYNC_I[2..0] :DFFE;
nBLANK :DFF;
DISP_ON :DFF;
DPO_ZL :DFFE;
DPO_ON :DFF;
DPO_OFF :DFF;
VDTRON :DFF;
VDO_ZL :DFFE;
VDO_ON :DFF;
VDO_OFF :DFF;
VHCNT[11..0] :DFF;
SUB_PIXEL_CNT[6..0] :DFFE;
VVCNT[10..0] :DFFE;
VERZ[2..0][9..0] :DFF;
RAND[6..0] :DFF;
RAND_ON :NODE;
FIFO_RDE :DFF;
CLR_FIFO :DFFE;
START_ZEILE :DFFE;
SYNC_PIX :DFF;
SYNC_PIX1 :DFF;
SYNC_PIX2 :DFF;
CCSEL[2..0] :DFF;
COLOR16 :NODE;
COLOR24 :NODE;
-- ATARI RESOLUTION
ATARI_SYNC :NODE;
ATARI_HH[31..0] :DFFE; -- HORIZONTAL TIMING 640x480
ATARI_HH_CS :NODE;
ATARI_VH[31..0] :DFFE; -- VERTIKAL TIMING 640x480
ATARI_VH_CS :NODE;
ATARI_HL[31..0] :DFFE; -- HORIZONTAL TIMING 320x240
ATARI_HL_CS :NODE;
ATARI_VL[31..0] :DFFE; -- VERTIKAL TIMING 320x240
ATARI_VL_CS :NODE;
-- HORIZONTAL
RAND_LINKS[11..0] :NODE;
HDIS_START[11..0] :NODE;
HDIS_END[11..0] :NODE;
RAND_RECHTS[11..0] :NODE;
HS_START[11..0] :NODE;
H_TOTAL[11..0] :NODE;
HDIS_LEN[11..0] :NODE;
MULF[5..0] :NODE;
VDL_HHT[11..0] :DFFE;
VDL_HHT_CS :NODE;
VDL_HBE[11..0] :DFFE;
VDL_HBE_CS :NODE;
VDL_HDB[11..0] :DFFE;
VDL_HDB_CS :NODE;
VDL_HDE[11..0] :DFFE;
VDL_HDE_CS :NODE;
VDL_HBB[11..0] :DFFE;
VDL_HBB_CS :NODE;
VDL_HSS[11..0] :DFFE;
VDL_HSS_CS :NODE;
-- VERTIKAL
RAND_OBEN[10..0] :NODE;
VDIS_START[10..0] :NODE;
VDIS_END[10..0] :NODE;
RAND_UNTEN[10..0] :NODE;
VS_START[10..0] :NODE;
V_TOTAL[10..0] :NODE;
FALCON_VIDEO :NODE;
ST_VIDEO :NODE;
INTER_ZEI :DFF;
DOP_ZEI :DFF;
DOP_FIFO_CLR :DFF;
VDL_VBE[10..0] :DFFE;
VDL_VBE_CS :NODE;
VDL_VDB[10..0] :DFFE;
VDL_VDB_CS :NODE;
VDL_VDE[10..0] :DFFE;
VDL_VDE_CS :NODE;
VDL_VBB[10..0] :DFFE;
VDL_VBB_CS :NODE;
VDL_VSS[10..0] :DFFE;
VDL_VSS_CS :NODE;
VDL_VFT[10..0] :DFFE;
VDL_VFT_CS :NODE;
VDL_VCT[8..0] :DFFE;
VDL_VCT_CS :NODE;
VDL_VMD[3..0] :DFFE;
VDL_VMD_CS :NODE;
BEGIN
-- BYT SELECT 32 BIT
FB_B0 = FB_ADR[1..0]==0; -- ADR==0
FB_B1 = FB_ADR[1..0]==1 -- ADR==1
# FB_SIZE1 & !FB_SIZE0 & !FB_ADR1 -- HIGH WORD
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B2 = FB_ADR[1..0]==2 -- ADR==2
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
FB_B3 = FB_ADR[1..0]==3 -- ADR==3
# FB_SIZE1 & !FB_SIZE0 & FB_ADR1 -- LOW WORD
# FB_SIZE1 & FB_SIZE0 # !FB_SIZE1 & !FB_SIZE0; -- LONG UND LINE
-- BYT SELECT 16 BIT
FB_16B0 = FB_ADR[0]==0; -- ADR==0
FB_16B1 = FB_ADR[0]==1 -- ADR==1
# !(!FB_SIZE1 & FB_SIZE0); -- NOT BYT
-- ACP CLUT --
ACP_CLUT_CS = !nFB_CS2 & FB_ADR[27..10]==H"0"; -- 0-3FF/1024
ACP_CLUT_RD = ACP_CLUT_CS & !nFB_OE;
ACP_CLUT_WR[] = FB_B[] & ACP_CLUT_CS & !nFB_WR;
CLUT_TA.CLK = MAIN_CLK;
CLUT_TA = (ACP_CLUT_CS # FALCON_CLUT_CS # ST_CLUT_CS) & !VIDEO_MOD_TA;
--FALCON CLUT --
FALCON_CLUT_CS = !nFB_CS1 & FB_ADR[19..10]==H"3E6"; -- $F9800/$400
FALCON_CLUT_RDH = FALCON_CLUT_CS & !nFB_OE & !FB_ADR1; -- HIGH WORD
FALCON_CLUT_RDL = FALCON_CLUT_CS & !nFB_OE & FB_ADR1; -- LOW WORD
FALCON_CLUT_WR[1..0] = FB_16B[] & !FB_ADR1 & FALCON_CLUT_CS & !nFB_WR;
FALCON_CLUT_WR[3..2] = FB_16B[] & FB_ADR1 & FALCON_CLUT_CS & !nFB_WR;
-- ST CLUT --
ST_CLUT_CS = !nFB_CS1 & FB_ADR[19..5]==H"7C12"; -- $F8240/$20
ST_CLUT_RD = ST_CLUT_CS & !nFB_OE;
ST_CLUT_WR[] = FB_16B[] & ST_CLUT_CS & !nFB_WR;
-- ST SHIFT MODE
ST_SHIFT_MODE[].CLK = MAIN_CLK;
ST_SHIFT_MODE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C130"; -- $F8260/2
ST_SHIFT_MODE[] = FB_AD[25..24];
ST_SHIFT_MODE[].ENA = ST_SHIFT_MODE_CS & !nFB_WR & FB_B0;
COLOR1 = ST_SHIFT_MODE[]==B"10" & !COLOR8 & ST_VIDEO & !ACP_VIDEO_ON; -- MONO
COLOR2 = ST_SHIFT_MODE[]==B"01" & !COLOR8 & ST_VIDEO & !ACP_VIDEO_ON; -- 4 FARBEN
COLOR4 = ST_SHIFT_MODE[]==B"00" & !COLOR8 & ST_VIDEO & !ACP_VIDEO_ON; -- 16 FARBEN
-- FALCON SHIFT MODE
FALCON_SHIFT_MODE[].CLK = MAIN_CLK;
FALCON_SHIFT_MODE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C133"; -- $F8266/2
FALCON_SHIFT_MODE[] = FB_AD[26..16];
FALCON_SHIFT_MODE[10..8].ENA = FALCON_SHIFT_MODE_CS & !nFB_WR & FB_B2;
FALCON_SHIFT_MODE[7..0].ENA = FALCON_SHIFT_MODE_CS & !nFB_WR & FB_B3;
CLUT_OFF[3..0] = FALCON_SHIFT_MODE[3..0] & COLOR4;
COLOR1 = FALCON_SHIFT_MODE10 & !COLOR16 & !COLOR8 & FALCON_VIDEO & !ACP_VIDEO_ON;
COLOR8 = FALCON_SHIFT_MODE4 & !COLOR16 & FALCON_VIDEO & !ACP_VIDEO_ON;
COLOR16 = FALCON_SHIFT_MODE8 & FALCON_VIDEO & !ACP_VIDEO_ON;
COLOR4 = !COLOR1 & !COLOR16 & !COLOR8 & FALCON_VIDEO & !ACP_VIDEO_ON;
-- ACP VIDEO CONTROL BIT 0=ACP VIDEO ON, 1=POWER ON VIDEO DAC, 2=ACP 24BIT,3=ACP 16BIT,4=ACP 8BIT,5=ACP 1BIT, 6=FALCON SHIFT MODE;7=ST SHIFT MODE;9..8= VCLK FREQUENZ;15=-SYNC ALLOWED; 31..16=VIDEO_RAM_CTR,25=RANDFARBE EINSCHALTEN, 26=STANDARD ATARI SYNCS
ACP_VCTR[].CLK = MAIN_CLK;
ACP_VCTR_CS = !nFB_CS2 & FB_ADR[27..2]==H"100"; -- $400/4
ACP_VCTR[31..8] = FB_AD[31..8];
ACP_VCTR[5..0] = FB_AD[5..0];
ACP_VCTR[31..24].ENA = ACP_VCTR_CS & FB_B0 & !nFB_WR;
ACP_VCTR[23..16].ENA = ACP_VCTR_CS & FB_B1 & !nFB_WR;
ACP_VCTR[15..8].ENA = ACP_VCTR_CS & FB_B2 & !nFB_WR;
ACP_VCTR[5..0].ENA = ACP_VCTR_CS & FB_B3 & !nFB_WR;
ACP_VIDEO_ON = ACP_VCTR0;
nPD_VGA = ACP_VCTR1;
-- ATARI MODUS
ATARI_SYNC = ACP_VCTR26; -- WENN 1 AUTOMATISCHE AUFL<46>SUNG
-- HORIZONTAL TIMING 640x480
ATARI_HH[].CLK = MAIN_CLK;
ATARI_HH_CS = !nFB_CS2 & FB_ADR[27..2]==H"104"; -- $410/4
ATARI_HH[] = FB_AD[];
ATARI_HH[31..24].ENA = ATARI_HH_CS & FB_B0 & !nFB_WR;
ATARI_HH[23..16].ENA = ATARI_HH_CS & FB_B1 & !nFB_WR;
ATARI_HH[15..8].ENA = ATARI_HH_CS & FB_B2 & !nFB_WR;
ATARI_HH[7..0].ENA = ATARI_HH_CS & FB_B3 & !nFB_WR;
-- VERTIKAL TIMING 640x480
ATARI_VH[].CLK = MAIN_CLK;
ATARI_VH_CS = !nFB_CS2 & FB_ADR[27..2]==H"105"; -- $414/4
ATARI_VH[] = FB_AD[];
ATARI_VH[31..24].ENA = ATARI_VH_CS & FB_B0 & !nFB_WR;
ATARI_VH[23..16].ENA = ATARI_VH_CS & FB_B1 & !nFB_WR;
ATARI_VH[15..8].ENA = ATARI_VH_CS & FB_B2 & !nFB_WR;
ATARI_VH[7..0].ENA = ATARI_VH_CS & FB_B3 & !nFB_WR;
-- HORIZONTAL TIMING 320x240
ATARI_HL[].CLK = MAIN_CLK;
ATARI_HL_CS = !nFB_CS2 & FB_ADR[27..2]==H"106"; -- $418/4
ATARI_HL[] = FB_AD[];
ATARI_HL[31..24].ENA = ATARI_HL_CS & FB_B0 & !nFB_WR;
ATARI_HL[23..16].ENA = ATARI_HL_CS & FB_B1 & !nFB_WR;
ATARI_HL[15..8].ENA = ATARI_HL_CS & FB_B2 & !nFB_WR;
ATARI_HL[7..0].ENA = ATARI_HL_CS & FB_B3 & !nFB_WR;
-- VERTIKAL TIMING 320x240
ATARI_VL[].CLK = MAIN_CLK;
ATARI_VL_CS = !nFB_CS2 & FB_ADR[27..2]==H"107"; -- $41C/4
ATARI_VL[] = FB_AD[];
ATARI_VL[31..24].ENA = ATARI_VL_CS & FB_B0 & !nFB_WR;
ATARI_VL[23..16].ENA = ATARI_VL_CS & FB_B1 & !nFB_WR;
ATARI_VL[15..8].ENA = ATARI_VL_CS & FB_B2 & !nFB_WR;
ATARI_VL[7..0].ENA = ATARI_VL_CS & FB_B3 & !nFB_WR;
-- VIDEO PLL CONFIG
VIDEO_PLL_CONFIG_CS = !nFB_CS2 & FB_ADR[27..9]==H"3" & FB_B0 & FB_B1; -- $(F)000'0600-7FF ->6/2 WORD RESP LONG ONLY
VR_WR.CLK = MAIN_CLK;
VR_WR = VIDEO_PLL_CONFIG_CS & !nFB_WR & !VR_BUSY & !VR_WR;
VR_RD = VIDEO_PLL_CONFIG_CS & nFB_WR & !VR_BUSY;
VR_DOUT[].CLK = MAIN_CLK;
VR_DOUT[].ENA = !VR_BUSY;
VR_DOUT[] = VR_D[];
VR_FRQ[].CLK = MAIN_CLK;
VR_FRQ[].ENA = VR_WR & FB_ADR[8..0]==H"04";
VR_FRQ[] = FB_AD[23..16];
-- VIDEO PLL RECONFIG
VIDEO_PLL_RECONFIG_CS = !nFB_CS2 & FB_ADR[27..0]==H"800" & FB_B0; -- $(F)000'0800
VIDEO_RECONFIG.CLK = MAIN_CLK;
VIDEO_RECONFIG = VIDEO_PLL_RECONFIG_CS & !nFB_WR & !VR_BUSY & !VIDEO_RECONFIG;
------------------------------------------------------------------------------------------------------------------------
VIDEO_RAM_CTR[] = ACP_VCTR[31..16];
-------------- COLOR MODE IM ACP SETZEN
COLOR1 = ACP_VCTR5 & !ACP_VCTR4 & !ACP_VCTR3 & !ACP_VCTR2 & ACP_VIDEO_ON;
COLOR8 = ACP_VCTR4 & !ACP_VCTR3 & !ACP_VCTR2 & ACP_VIDEO_ON;
COLOR16 = ACP_VCTR3 & !ACP_VCTR2 & ACP_VIDEO_ON;
COLOR24 = ACP_VCTR2 & ACP_VIDEO_ON;
ACP_CLUT = ACP_VIDEO_ON & (COLOR1 # COLOR8) # ST_VIDEO & COLOR1;
-- ST ODER FALCON SHIFT MODE SETZEN WENN WRITE X..SHIFT REGISTER
ACP_VCTR7 = FALCON_SHIFT_MODE_CS & !nFB_WR & !ACP_VIDEO_ON;
ACP_VCTR6 = ST_SHIFT_MODE_CS & !nFB_WR & !ACP_VIDEO_ON;
ACP_VCTR[7..6].ENA = FALCON_SHIFT_MODE_CS & !nFB_WR # ST_SHIFT_MODE_CS & !nFB_WR # ACP_VCTR_CS & FB_B3 & !nFB_WR & FB_AD0;
FALCON_VIDEO = ACP_VCTR7;
FALCON_CLUT = FALCON_VIDEO & !ACP_VIDEO_ON & !COLOR16;
ST_VIDEO = ACP_VCTR6;
ST_CLUT = ST_VIDEO & !ACP_VIDEO_ON & !FALCON_CLUT & !COLOR1;
CCSEL[].CLK = PIXEL_CLK;
CCSEL[] = B"000" & ST_CLUT -- ONLY FOR INFORMATION
# B"001" & FALCON_CLUT
# B"100" & ACP_CLUT
# B"101" & COLOR16
# B"110" & COLOR24
# B"111" & RAND_ON;
-- DIVERSE (VIDEO)-REGISTER ----------------------------
-- RANDFARBE
CCR[].CLK = MAIN_CLK;
CCR_CS = !nFB_CS2 & FB_ADR[27..2]==H"101"; -- $404/4
CCR[] = FB_AD[23..0];
CCR[23..16].ENA = CCR_CS & FB_B1 & !nFB_WR;
CCR[15..8].ENA = CCR_CS & FB_B2 & !nFB_WR;
CCR[7..0].ENA = CCR_CS & FB_B3 & !nFB_WR;
--SYS CTR
SYS_CTR_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C003"; -- $8006/2
SYS_CTR[].CLK = MAIN_CLK;
SYS_CTR[6..0] = FB_AD[22..16];
SYS_CTR[6..0].ENA = SYS_CTR_CS & !nFB_WR & FB_B3;
BLITTER_ON = !SYS_CTR3;
--VDL_LOF
VDL_LOF_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C107"; -- $820E/2
VDL_LOF[].CLK = MAIN_CLK;
VDL_LOF[] = FB_AD[31..16];
VDL_LOF[15..8].ENA = VDL_LOF_CS & !nFB_WR & FB_B2;
VDL_LOF[7..0].ENA = VDL_LOF_CS & !nFB_WR & FB_B3;
--VDL_LWD
VDL_LWD_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C108"; -- $8210/2
VDL_LWD[].CLK = MAIN_CLK;
VDL_LWD[] = FB_AD[31..16];
VDL_LWD[15..8].ENA = VDL_LWD_CS & !nFB_WR & FB_B0;
VDL_LWD[7..0].ENA = VDL_LWD_CS & !nFB_WR & FB_B1;
-- HORIZONTAL
-- VDL_HHT
VDL_HHT_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C141"; -- $8282/2
VDL_HHT[].CLK = MAIN_CLK;
VDL_HHT[] = FB_AD[27..16];
VDL_HHT[11..8].ENA = VDL_HHT_CS & !nFB_WR & FB_B2;
VDL_HHT[7..0].ENA = VDL_HHT_CS & !nFB_WR & FB_B3;
-- VDL_HBE
VDL_HBE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C143"; -- $8286/2
VDL_HBE[].CLK = MAIN_CLK;
VDL_HBE[] = FB_AD[27..16];
VDL_HBE[11..8].ENA = VDL_HBE_CS & !nFB_WR & FB_B2;
VDL_HBE[7..0].ENA = VDL_HBE_CS & !nFB_WR & FB_B3;
-- VDL_HDB
VDL_HDB_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C144"; -- $8288/2
VDL_HDB[].CLK = MAIN_CLK;
VDL_HDB[] = FB_AD[27..16];
VDL_HDB[11..8].ENA = VDL_HDB_CS & !nFB_WR & FB_B0;
VDL_HDB[7..0].ENA = VDL_HDB_CS & !nFB_WR & FB_B1;
-- VDL_HDE
VDL_HDE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C145"; -- $828A/2
VDL_HDE[].CLK = MAIN_CLK;
VDL_HDE[] = FB_AD[27..16];
VDL_HDE[11..8].ENA = VDL_HDE_CS & !nFB_WR & FB_B2;
VDL_HDE[7..0].ENA = VDL_HDE_CS & !nFB_WR & FB_B3;
-- VDL_HBB
VDL_HBB_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C142"; -- $8284/2
VDL_HBB[].CLK = MAIN_CLK;
VDL_HBB[] = FB_AD[27..16];
VDL_HBB[11..8].ENA = VDL_HBB_CS & !nFB_WR & FB_B0;
VDL_HBB[7..0].ENA = VDL_HBB_CS & !nFB_WR & FB_B1;
-- VDL_HSS
VDL_HSS_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C146"; -- $828C/2
VDL_HSS[].CLK = MAIN_CLK;
VDL_HSS[] = FB_AD[27..16];
VDL_HSS[11..8].ENA = VDL_HSS_CS & !nFB_WR & FB_B0;
VDL_HSS[7..0].ENA = VDL_HSS_CS & !nFB_WR & FB_B1;
-- VERTIKAL
-- VDL_VBE
VDL_VBE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C153"; -- $82A6/2
VDL_VBE[].CLK = MAIN_CLK;
VDL_VBE[] = FB_AD[26..16];
VDL_VBE[10..8].ENA = VDL_VBE_CS & !nFB_WR & FB_B2;
VDL_VBE[7..0].ENA = VDL_VBE_CS & !nFB_WR & FB_B3;
-- VDL_VDB
VDL_VDB_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C154"; -- $82A8/2
VDL_VDB[].CLK = MAIN_CLK;
VDL_VDB[] = FB_AD[26..16];
VDL_VDB[10..8].ENA = VDL_VDB_CS & !nFB_WR & FB_B0;
VDL_VDB[7..0].ENA = VDL_VDB_CS & !nFB_WR & FB_B1;
-- VDL_VDE
VDL_VDE_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C155"; -- $82AA/2
VDL_VDE[].CLK = MAIN_CLK;
VDL_VDE[] = FB_AD[26..16];
VDL_VDE[10..8].ENA = VDL_VDE_CS & !nFB_WR & FB_B2;
VDL_VDE[7..0].ENA = VDL_VDE_CS & !nFB_WR & FB_B3;
-- VDL_VBB
VDL_VBB_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C152"; -- $82A4/2
VDL_VBB[].CLK = MAIN_CLK;
VDL_VBB[] = FB_AD[26..16];
VDL_VBB[10..8].ENA = VDL_VBB_CS & !nFB_WR & FB_B0;
VDL_VBB[7..0].ENA = VDL_VBB_CS & !nFB_WR & FB_B1;
-- VDL_VSS
VDL_VSS_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C156"; -- $82AC/2
VDL_VSS[].CLK = MAIN_CLK;
VDL_VSS[] = FB_AD[26..16];
VDL_VSS[10..8].ENA = VDL_VSS_CS & !nFB_WR & FB_B0;
VDL_VSS[7..0].ENA = VDL_VSS_CS & !nFB_WR & FB_B1;
-- VDL_VFT
VDL_VFT_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C151"; -- $82A2/2
VDL_VFT[].CLK = MAIN_CLK;
VDL_VFT[] = FB_AD[26..16];
VDL_VFT[10..8].ENA = VDL_VFT_CS & !nFB_WR & FB_B2;
VDL_VFT[7..0].ENA = VDL_VFT_CS & !nFB_WR & FB_B3;
-- VDL_VCT
VDL_VCT_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C160"; -- $82C0/2
VDL_VCT[].CLK = MAIN_CLK;
VDL_VCT[] = FB_AD[24..16];
VDL_VCT[8].ENA = VDL_VCT_CS & !nFB_WR & FB_B0;
VDL_VCT[7..0].ENA = VDL_VCT_CS & !nFB_WR & FB_B1;
-- VDL_VMD
VDL_VMD_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C161"; -- $82C2/2
VDL_VMD[].CLK = MAIN_CLK;
VDL_VMD[] = FB_AD[19..16];
VDL_VMD[3..0].ENA = VDL_VMD_CS & !nFB_WR & FB_B3;
--- REGISTER OUT
FB_AD[31..16] = lpm_bustri_WORD(
ST_SHIFT_MODE_CS & (0,ST_SHIFT_MODE[],B"00000000")
# FALCON_SHIFT_MODE_CS & (0,FALCON_SHIFT_MODE[])
# SYS_CTR_CS & (B"100000000",SYS_CTR[6..4],!BLITTER_RUN,SYS_CTR[2..0])
# VDL_LOF_CS & VDL_LOF[]
# VDL_LWD_CS & VDL_LWD[]
# VDL_HBE_CS & (0,VDL_HBE[])
# VDL_HDB_CS & (0,VDL_HDB[])
# VDL_HDE_CS & (0,VDL_HDE[])
# VDL_HBB_CS & (0,VDL_HBB[])
# VDL_HSS_CS & (0,VDL_HSS[])
# VDL_HHT_CS & (0,VDL_HHT[])
# VDL_VBE_CS & (0,VDL_VBE[])
# VDL_VDB_CS & (0,VDL_VDB[])
# VDL_VDE_CS & (0,VDL_VDE[])
# VDL_VBB_CS & (0,VDL_VBB[])
# VDL_VSS_CS & (0,VDL_VSS[])
# VDL_VFT_CS & (0,VDL_VFT[])
# VDL_VCT_CS & (0,VDL_VCT[])
# VDL_VMD_CS & (0,VDL_VMD[])
# ACP_VCTR_CS & ACP_VCTR[31..16]
# ATARI_HH_CS & ATARI_HH[31..16]
# ATARI_VH_CS & ATARI_VH[31..16]
# ATARI_HL_CS & ATARI_HL[31..16]
# ATARI_VL_CS & ATARI_VL[31..16]
# CCR_CS & (0,CCR[23..16])
# VIDEO_PLL_CONFIG_CS & (0,VR_DOUT[])
# VIDEO_PLL_RECONFIG_CS & (VR_BUSY,B"0000",VR_WR,VR_RD,VIDEO_RECONFIG,H"FA")
,(ST_SHIFT_MODE_CS # FALCON_SHIFT_MODE_CS # ACP_VCTR_CS # CCR_CS # SYS_CTR_CS # VDL_LOF_CS # VDL_LWD_CS
# VDL_HBE_CS # VDL_HDB_CS # VDL_HDE_CS # VDL_HBB_CS # VDL_HSS_CS # VDL_HHT_CS
# ATARI_HH_CS # ATARI_VH_CS # ATARI_HL_CS # ATARI_VL_CS # VIDEO_PLL_CONFIG_CS # VIDEO_PLL_RECONFIG_CS
# VDL_VBE_CS # VDL_VDB_CS # VDL_VDE_CS # VDL_VBB_CS # VDL_VSS_CS # VDL_VFT_CS # VDL_VCT_CS # VDL_VMD_CS) & !nFB_OE);
FB_AD[15..0] = lpm_bustri_WORD(
ACP_VCTR_CS & ACP_VCTR[15..0]
# ATARI_HH_CS & ATARI_HH[15..0]
# ATARI_VH_CS & ATARI_VH[15..0]
# ATARI_HL_CS & ATARI_HL[15..0]
# ATARI_VL_CS & ATARI_VL[15..0]
# CCR_CS & CCR[15..0]
,(ACP_VCTR_CS # CCR_CS # ATARI_HH_CS # ATARI_VH_CS # ATARI_HL_CS # ATARI_VL_CS ) & !nFB_OE);
VIDEO_MOD_TA = CLUT_TA # ST_SHIFT_MODE_CS # FALCON_SHIFT_MODE_CS # ACP_VCTR_CS # SYS_CTR_CS # VDL_LOF_CS # VDL_LWD_CS
# VDL_HBE_CS # VDL_HDB_CS # VDL_HDE_CS # VDL_HBB_CS # VDL_HSS_CS # VDL_HHT_CS
# ATARI_HH_CS # ATARI_VH_CS # ATARI_HL_CS # ATARI_VL_CS
# VDL_VBE_CS # VDL_VDB_CS # VDL_VDE_CS # VDL_VBB_CS # VDL_VSS_CS # VDL_VFT_CS # VDL_VCT_CS # VDL_VMD_CS;
-- VIDEO AUSGABE SETZEN
CLK17M.CLK = CLK33M;
CLK17M = !CLK17M;
CLK13M.CLK = CLK25M;
CLK13M = !CLK13M;
PIXEL_CLK = CLK13M & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & ( VDL_VMD2 & VDL_VCT2 # VDL_VCT0)
# CLK17M & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & ( VDL_VMD2 & !VDL_VCT2 # VDL_VCT0)
# CLK25M & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & !VDL_VMD2 & VDL_VCT2 & !VDL_VCT0
# CLK33M & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & !VDL_VMD2 & !VDL_VCT2 & !VDL_VCT0
# CLK25M & ACP_VIDEO_ON & ACP_VCTR[9..8]==B"00"
# CLK33M & ACP_VIDEO_ON & ACP_VCTR[9..8]==B"01"
# CLK_VIDEO & ACP_VIDEO_ON & ACP_VCTR[9];
--------------------------------------------------------------
-- HORIZONTALE SYNC L<>NGE in PIXEL_CLK
----------------------------------------------------------------
HSY_LEN[].CLK = MAIN_CLK;
HSY_LEN[] = 14 & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & ( VDL_VMD2 & VDL_VCT2 # VDL_VCT0)
# 16 & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & ( VDL_VMD2 & !VDL_VCT2 # VDL_VCT0)
# 28 & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & !VDL_VMD2 & VDL_VCT2 & !VDL_VCT0
# 32 & !ACP_VIDEO_ON & (FALCON_VIDEO # ST_VIDEO) & !VDL_VMD2 & !VDL_VCT2 & !VDL_VCT0
# 28 & ACP_VIDEO_ON & ACP_VCTR[9..8]==B"00"
# 32 & ACP_VIDEO_ON & ACP_VCTR[9..8]==B"01"
# 16 + (0,VR_FRQ[7..1]) & ACP_VIDEO_ON & ACP_VCTR[9]; -- hsync puls length in pixeln=frequenz/ = 500ns
MULF[] = 2 & !ST_VIDEO & VDL_VMD2 -- MULTIPLIKATIONS FAKTOR
# 4 & !ST_VIDEO & !VDL_VMD2
# 16 & ST_VIDEO & VDL_VMD2
# 32 & ST_VIDEO & !VDL_VMD2;
HDIS_LEN[] = 320 & VDL_VMD2 -- BREITE IN PIXELN
# 640 & !VDL_VMD2;
-- DOPPELZEILENMODUS
DOP_ZEI.CLK = MAIN_CLK;
DOP_ZEI = VDL_VMD0 & ST_VIDEO; -- ZEILENVERDOPPELUNG EIN AUS
INTER_ZEI.CLK = PIXEL_CLK;
INTER_ZEI = DOP_ZEI & VVCNT0!=VDIS_START0 & VVCNT[]!=0 & VHCNT[]<(HDIS_END[]-1) -- EINSCHIEBEZEILE AUF "DOPPEL" ZEILEN UND ZEILE NULL WEGEN SYNC
# DOP_ZEI & VVCNT0==VDIS_START0 & VVCNT[]!=0 & VHCNT[]>(HDIS_END[]-2); -- EINSCHIEBEZEILE AUF "NORMAL" ZEILEN UND ZEILE NULL WEGEN SYNC
DOP_FIFO_CLR.CLK = PIXEL_CLK;
DOP_FIFO_CLR = INTER_ZEI & HSYNC_START # SYNC_PIX; -- DOPPELZEILENFIFO L<>SCHEN AM ENDE DER DOPPELZEILE UND BEI MAIN FIFO START
RAND_LINKS[] = VDL_HBE[] & ACP_VIDEO_ON
# 21 & !ACP_VIDEO_ON & ATARI_SYNC & VDL_VMD2
# 42 & !ACP_VIDEO_ON & ATARI_SYNC & !VDL_VMD2
# VDL_HBE[] * (0,MULF[5..1]) & !ACP_VIDEO_ON & !ATARI_SYNC; --
HDIS_START[] = VDL_HDB[] & ACP_VIDEO_ON
# RAND_LINKS[]+1 & !ACP_VIDEO_ON; --
HDIS_END[] = VDL_HDE[] & ACP_VIDEO_ON
# RAND_LINKS[]+HDIS_LEN[] & !ACP_VIDEO_ON; --
RAND_RECHTS[] = VDL_HBB[] & ACP_VIDEO_ON
# HDIS_END[]+1 & !ACP_VIDEO_ON; --
HS_START[] = VDL_HSS[] & ACP_VIDEO_ON
# ATARI_HL[11..0] & !ACP_VIDEO_ON & ATARI_SYNC & VDL_VMD2
# ATARI_HH[11..0] & !ACP_VIDEO_ON & ATARI_SYNC & !VDL_VMD2
# (VDL_HHT[]+1+VDL_HSS[]) * (0,MULF[5..1]) & !ACP_VIDEO_ON & !ATARI_SYNC; --
H_TOTAL[] = VDL_HHT[] & ACP_VIDEO_ON
# ATARI_HL[27..16] & !ACP_VIDEO_ON & ATARI_SYNC & VDL_VMD2
# ATARI_HH[27..16] & !ACP_VIDEO_ON & ATARI_SYNC & !VDL_VMD2
# (VDL_HHT[]+2) * (0,MULF[]) & !ACP_VIDEO_ON & !ATARI_SYNC; --
RAND_OBEN[] = VDL_VBE[] & ACP_VIDEO_ON
# 31 & !ACP_VIDEO_ON & ATARI_SYNC
# (0,VDL_VBE[10..1]) & !ACP_VIDEO_ON & !ATARI_SYNC;
VDIS_START[] = VDL_VDB[] & ACP_VIDEO_ON
# 32 & !ACP_VIDEO_ON & ATARI_SYNC
# (0,VDL_VDB[10..1])+1 & !ACP_VIDEO_ON & !ATARI_SYNC;
VDIS_END[] = VDL_VDE[] & ACP_VIDEO_ON
# 431 & !ACP_VIDEO_ON & ATARI_SYNC & ST_VIDEO
# 511 & !ACP_VIDEO_ON & ATARI_SYNC & !ST_VIDEO
# (0,VDL_VDE[10..1]) & !ACP_VIDEO_ON & !ATARI_SYNC;
RAND_UNTEN[] = VDL_VBB[] & ACP_VIDEO_ON
# VDIS_END[]+1 & !ACP_VIDEO_ON & ATARI_SYNC
# (0,VDL_VBB[10..1])+1 & !ACP_VIDEO_ON & !ATARI_SYNC;
VS_START[] = VDL_VSS[] & ACP_VIDEO_ON
# ATARI_VL[10..0] & !ACP_VIDEO_ON & ATARI_SYNC & VDL_VMD2
# ATARI_VH[10..0] & !ACP_VIDEO_ON & ATARI_SYNC & !VDL_VMD2
# (0,VDL_VSS[10..1]) & !ACP_VIDEO_ON & !ATARI_SYNC;
V_TOTAL[] = VDL_VFT[] & ACP_VIDEO_ON
# ATARI_VL[26..16] & !ACP_VIDEO_ON & ATARI_SYNC & VDL_VMD2
# ATARI_VH[26..16] & !ACP_VIDEO_ON & ATARI_SYNC & !VDL_VMD2
# (0,VDL_VFT[10..1]) & !ACP_VIDEO_ON & !ATARI_SYNC;
-- Z<>HLER
LAST.CLK = PIXEL_CLK;
LAST = VHCNT[]==(H_TOTAL[]-2);
VHCNT[].CLK = PIXEL_CLK;
VHCNT[] = (VHCNT[] + 1) & !LAST;
VVCNT[].CLK = PIXEL_CLK;
VVCNT[].ENA = LAST;
VVCNT[] = (VVCNT[] + 1) & (VVCNT[]!=V_TOTAL[]-1);
-- DISPLAY ON OFF
DPO_ZL.CLK = PIXEL_CLK;
DPO_ZL = (VVCNT[]>RAND_OBEN[]-1) & (VVCNT[]<RAND_UNTEN[]-1); -- 1 ZEILE DAVOR ON OFF
DPO_ZL.ENA = LAST; -- AM ZEILENENDE <20>BERNEHMEN
DPO_ON.CLK = PIXEL_CLK;
DPO_ON = VHCNT[]==RAND_LINKS[]; -- BESSER EINZELN WEGEN TIMING
DPO_OFF.CLK = PIXEL_CLK;
DPO_OFF = VHCNT[]==(RAND_RECHTS[]-1);
DISP_ON.CLK = PIXEL_CLK;
DISP_ON = DISP_ON & !DPO_OFF
# DPO_ON & DPO_ZL;
-- DATENTRANSFER ON OFF
VDO_ON.CLK = PIXEL_CLK;
VDO_ON = VHCNT[]==(HDIS_START[]-1); -- BESSER EINZELN WEGEN TIMING
VDO_OFF.CLK = PIXEL_CLK;
VDO_OFF = VHCNT[]==HDIS_END[];
VDO_ZL.CLK = PIXEL_CLK;
VDO_ZL.ENA = LAST; -- AM ZEILENENDE <20>BERNEHMEN
VDO_ZL = (VVCNT[]>=(VDIS_START[]-1)) & (VVCNT[]<VDIS_END[]); -- 1 ZEILE DAVOR ON OFF
VDTRON.CLK = PIXEL_CLK;
VDTRON = VDTRON & !VDO_OFF
# VDO_ON & VDO_ZL;
-- VERZ<52>GERUNG UND SYNC
HSYNC_START.CLK = PIXEL_CLK;
HSYNC_START = VHCNT[]==HS_START[]-3;
HSYNC_I[].CLK = PIXEL_CLK;
HSYNC_I[] = HSY_LEN[] & HSYNC_START
# (HSYNC_I[]-1) & !HSYNC_START & HSYNC_I[]!=0;
VSYNC_START.CLK = PIXEL_CLK;
VSYNC_START.ENA = LAST;
VSYNC_START = VVCNT[]==(VS_START[]-3); -- start am ende der Zeile vor dem vsync
VSYNC_I[].CLK = PIXEL_CLK;
VSYNC_I[].ENA = LAST; -- start am ende der Zeile vor dem vsync
VSYNC_I[] = 3 & VSYNC_START -- 3 zeilen vsync length
# (VSYNC_I[]-1) & !VSYNC_START & VSYNC_I[]!=0; -- runterz<72>hlen bis 0
VERZ[][].CLK = PIXEL_CLK;
VERZ[][1] = VERZ[][0];
VERZ[][2] = VERZ[][1];
VERZ[][3] = VERZ[][2];
VERZ[][4] = VERZ[][3];
VERZ[][5] = VERZ[][4];
VERZ[][6] = VERZ[][5];
VERZ[][7] = VERZ[][6];
VERZ[][8] = VERZ[][7];
VERZ[][9] = VERZ[][8];
VERZ[0][0] = DISP_ON;
VERZ[1][0] = HSYNC_I[]!=0;
VERZ[1][0] = (!ACP_VCTR15 # !VDL_VCT6) & HSYNC_I[]!=0
# ACP_VCTR15 & VDL_VCT6 & HSYNC_I[]==0; -- NUR M<>GLICH WENN BEIDE
VERZ[2][0] = (!ACP_VCTR15 # !VDL_VCT5) & VSYNC_I[]!=0
# ACP_VCTR15 & VDL_VCT5 & VSYNC_I[]==0; -- NUR M<>GLICH WENN BEIDE
nBLANK.CLK = PIXEL_CLK;
nBLANK = VERZ[0][8];
HSYNC.CLK = PIXEL_CLK;
HSYNC = VERZ[1][9];
VSYNC.CLK = PIXEL_CLK;
VSYNC = VERZ[2][9];
nSYNC = GND;
-- RANDFARBE MACHEN ------------------------------------
RAND[].CLK = PIXEL_CLK;
RAND[0] = DISP_ON & !VDTRON & ACP_VCTR25;
RAND[1] = RAND[0];
RAND[2] = RAND[1];
RAND[3] = RAND[2];
RAND[4] = RAND[3];
RAND[5] = RAND[4];
RAND[6] = RAND[5];
RAND_ON = RAND[6];
----------------------------------------------------------
CLR_FIFO.CLK = PIXEL_CLK;
CLR_FIFO.ENA = LAST;
CLR_FIFO = VVCNT[]==V_TOTAL[]-2; -- IN LETZTER ZEILE L<>SCHEN
START_ZEILE.CLK = PIXEL_CLK;
START_ZEILE.ENA = LAST;
START_ZEILE = VVCNT[]==0; -- ZEILE 1
SYNC_PIX.CLK = PIXEL_CLK;
SYNC_PIX = VHCNT[]==1 & START_ZEILE; -- SUB PIXEL Z<>HLER SYNCHRONISIEREN
SYNC_PIX1.CLK = PIXEL_CLK;
SYNC_PIX1 = VHCNT[]==3 & START_ZEILE; -- SUB PIXEL Z<>HLER SYNCHRONISIEREN
SYNC_PIX2.CLK = PIXEL_CLK;
SYNC_PIX2 = VHCNT[]==5 & START_ZEILE; -- SUB PIXEL Z<>HLER SYNCHRONISIEREN
SUB_PIXEL_CNT[].CLK = PIXEL_CLK;
SUB_PIXEL_CNT[].ENA = VDTRON # SYNC_PIX;
SUB_PIXEL_CNT[] = (SUB_PIXEL_CNT[] + 1) & !SYNC_PIX; --count up if display on sonst clear bei sync pix
FIFO_RDE.CLK = PIXEL_CLK;
FIFO_RDE = (SUB_PIXEL_CNT[6..0]==1 & COLOR1
# SUB_PIXEL_CNT[5..0]==1 & COLOR2
# SUB_PIXEL_CNT[4..0]==1 & COLOR4
# SUB_PIXEL_CNT[3..0]==1 & COLOR8
# SUB_PIXEL_CNT[2..0]==1 & COLOR16
# SUB_PIXEL_CNT[1..0]==1 & COLOR24) & VDTRON
# SYNC_PIX # SYNC_PIX1 # SYNC_PIX2; -- 3 CLOCK ZUS<55>TZLICH F<>R FIFO SHIFT DATAOUT UND SHIFT RIGTH POSITION
CLUT_MUX_ADR[].CLK = PIXEL_CLK;
CLUT_MUX_AV[][].CLK = PIXEL_CLK;
CLUT_MUX_AV[0][] = SUB_PIXEL_CNT[3..0];
CLUT_MUX_AV[1][] = CLUT_MUX_AV[0][];
CLUT_MUX_ADR[] = CLUT_MUX_AV[1][];
END;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
/*
WARNING: Do NOT edit the input and output ports in this file in a text
editor if you plan to continue editing the block that represents it in
the Block Editor! File corruption is VERY likely to occur.
*/
/*
Copyright (C) 1991-2008 Altera Corporation
Your use of Altera Corporation's design tools, logic functions
and other software and tools, and its AMPP partner logic
functions, and any output files from any of the foregoing
(including device programming or simulation files), and any
associated documentation or information are expressly subject
to the terms and conditions of the Altera Program License
Subscription Agreement, Altera MegaCore Function License
Agreement, or other applicable license agreement, including,
without limitation, that your use is for the sole purpose of
programming logic devices manufactured by Altera and sold by
Altera or its authorized distributors. Please refer to the
applicable agreement for further details.
*/
(header "symbol" (version "1.1"))
(symbol
(rect 0 0 240 136)
(text "altddio_bidir0" (rect 82 1 171 17)(font "Arial" (font_size 10)))
(text "inst" (rect 8 120 25 132)(font "Arial" ))
(port
(pt 0 24)
(input)
(text "datain_h[31..0]" (rect 0 0 83 14)(font "Arial" (font_size 8)))
(text "datain_h[31..0]" (rect 4 11 76 24)(font "Arial" (font_size 8)))
(line (pt 0 24)(pt 88 24)(line_width 3))
)
(port
(pt 0 40)
(input)
(text "datain_l[31..0]" (rect 0 0 79 14)(font "Arial" (font_size 8)))
(text "datain_l[31..0]" (rect 4 27 73 40)(font "Arial" (font_size 8)))
(line (pt 0 40)(pt 88 40)(line_width 3))
)
(port
(pt 0 56)
(input)
(text "oe" (rect 0 0 14 14)(font "Arial" (font_size 8)))
(text "oe" (rect 4 43 16 56)(font "Arial" (font_size 8)))
(line (pt 0 56)(pt 88 56)(line_width 1))
)
(port
(pt 0 72)
(input)
(text "inclock" (rect 0 0 38 14)(font "Arial" (font_size 8)))
(text "inclock" (rect 4 59 36 72)(font "Arial" (font_size 8)))
(line (pt 0 72)(pt 88 72)(line_width 1))
)
(port
(pt 0 88)
(input)
(text "outclock" (rect 0 0 47 14)(font "Arial" (font_size 8)))
(text "outclock" (rect 4 75 42 88)(font "Arial" (font_size 8)))
(line (pt 0 88)(pt 88 88)(line_width 1))
)
(port
(pt 240 24)
(output)
(text "dataout_h[31..0]" (rect 0 0 92 14)(font "Arial" (font_size 8)))
(text "dataout_h[31..0]" (rect 159 11 237 24)(font "Arial" (font_size 8)))
(line (pt 240 24)(pt 144 24)(line_width 3))
)
(port
(pt 240 40)
(output)
(text "dataout_l[31..0]" (rect 0 0 87 14)(font "Arial" (font_size 8)))
(text "dataout_l[31..0]" (rect 163 27 238 40)(font "Arial" (font_size 8)))
(line (pt 240 40)(pt 144 40)(line_width 3))
)
(port
(pt 240 72)
(output)
(text "combout[31..0]" (rect 0 0 83 14)(font "Arial" (font_size 8)))
(text "combout[31..0]" (rect 166 59 237 72)(font "Arial" (font_size 8)))
(line (pt 240 72)(pt 144 72)(line_width 3))
)
(port
(pt 240 56)
(bidir)
(text "padio[31..0]" (rect 0 0 66 14)(font "Arial" (font_size 8)))
(text "padio[31..0]" (rect 181 43 238 56)(font "Arial" (font_size 8)))
(line (pt 240 56)(pt 144 56)(line_width 3))
)
(drawing
(text "ddio" (rect 108 27 129 40)(font "Arial" (font_size 8)))
(text "bidir" (rect 108 42 129 55)(font "Arial" (font_size 8)))
(text "power up" (rect 92 90 129 102)(font "Arial" ))
(text "low" (rect 92 100 105 112)(font "Arial" ))
(line (pt 88 16)(pt 144 16)(line_width 1))
(line (pt 144 16)(pt 144 112)(line_width 1))
(line (pt 144 112)(pt 88 112)(line_width 1))
(line (pt 88 112)(pt 88 16)(line_width 1))
)
)

View File

@@ -0,0 +1,29 @@
--Copyright (C) 1991-2008 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
component altddio_bidir0
PORT
(
datain_h : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
datain_l : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
inclock : IN STD_LOGIC ;
oe : IN STD_LOGIC := '1';
outclock : IN STD_LOGIC ;
combout : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
dataout_h : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
dataout_l : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
padio : INOUT STD_LOGIC_VECTOR (31 DOWNTO 0)
);
end component;

View File

@@ -0,0 +1,30 @@
--Copyright (C) 1991-2008 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
FUNCTION altddio_bidir0
(
datain_h[31..0],
datain_l[31..0],
inclock,
oe,
outclock
)
RETURNS (
combout[31..0],
dataout_h[31..0],
dataout_l[31..0],
padio[31..0]
);

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="Cyclone III" variation_name="altddio_bidir0" megafunction_name="ALTDDIO_BIDIR" specifies="all_ports">
<global>
<pin name="datain_h[31..0]" direction="input" scope="external" />
<pin name="datain_l[31..0]" direction="input" scope="external" />
<pin name="inclock" direction="input" scope="external" source="clock" />
<pin name="oe" direction="input" scope="external" />
<pin name="outclock" direction="input" scope="external" source="clock" />
<pin name="combout[31..0]" direction="output" scope="external" />
<pin name="dataout_h[31..0]" direction="output" scope="external" />
<pin name="dataout_l[31..0]" direction="output" scope="external" />
<pin name="padio[31..0]" direction="bidir" scope="external" />
</global>
</pinplan>

View File

@@ -0,0 +1,7 @@
set_global_assignment -name IP_TOOL_NAME "ALTDDIO_BIDIR"
set_global_assignment -name IP_TOOL_VERSION "8.1"
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "altddio_bidir0.vhd"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altddio_bidir0.bsf"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altddio_bidir0.inc"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altddio_bidir0.cmp"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altddio_bidir0.ppf"]

View File

@@ -0,0 +1,172 @@
-- megafunction wizard: %ALTDDIO_BIDIR%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altddio_bidir
-- ============================================================
-- File Name: altddio_bidir0.vhd
-- Megafunction Name(s):
-- altddio_bidir
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 8.1 Build 163 10/28/2008 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2008 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY altddio_bidir0 IS
PORT
(
datain_h : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
datain_l : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
inclock : IN STD_LOGIC ;
oe : IN STD_LOGIC := '1';
outclock : IN STD_LOGIC ;
combout : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
dataout_h : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
dataout_l : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
padio : INOUT STD_LOGIC_VECTOR (31 DOWNTO 0)
);
END altddio_bidir0;
ARCHITECTURE SYN OF altddio_bidir0 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (31 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (31 DOWNTO 0);
SIGNAL sub_wire2 : STD_LOGIC_VECTOR (31 DOWNTO 0);
COMPONENT altddio_bidir
GENERIC (
extend_oe_disable : STRING;
implement_input_in_lcell : STRING;
intended_device_family : STRING;
invert_output : STRING;
lpm_type : STRING;
oe_reg : STRING;
power_up_high : STRING;
width : NATURAL
);
PORT (
outclock : IN STD_LOGIC ;
padio : INOUT STD_LOGIC_VECTOR (31 DOWNTO 0);
inclock : IN STD_LOGIC ;
dataout_h : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
oe : IN STD_LOGIC ;
datain_h : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
combout : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
dataout_l : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
datain_l : IN STD_LOGIC_VECTOR (31 DOWNTO 0)
);
END COMPONENT;
BEGIN
dataout_h <= sub_wire0(31 DOWNTO 0);
combout <= sub_wire1(31 DOWNTO 0);
dataout_l <= sub_wire2(31 DOWNTO 0);
altddio_bidir_component : altddio_bidir
GENERIC MAP (
extend_oe_disable => "UNUSED",
implement_input_in_lcell => "ON",
intended_device_family => "Cyclone III",
invert_output => "OFF",
lpm_type => "altddio_bidir",
oe_reg => "UNUSED",
power_up_high => "OFF",
width => 32
)
PORT MAP (
outclock => outclock,
inclock => inclock,
oe => oe,
datain_h => datain_h,
datain_l => datain_l,
dataout_h => sub_wire0,
combout => sub_wire1,
dataout_l => sub_wire2,
padio => padio
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ARESET_MODE NUMERIC "2"
-- Retrieval info: PRIVATE: CLKEN NUMERIC "0"
-- Retrieval info: PRIVATE: EXTEND_OE_DISABLE NUMERIC "0"
-- Retrieval info: PRIVATE: IMPLEMENT_INPUT_IN_LCELL NUMERIC "0"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: OE NUMERIC "1"
-- Retrieval info: PRIVATE: OE_REG NUMERIC "0"
-- Retrieval info: PRIVATE: POWER_UP_HIGH NUMERIC "0"
-- Retrieval info: PRIVATE: SRESET_MODE NUMERIC "2"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: USE_COMBOUT NUMERIC "1"
-- Retrieval info: PRIVATE: USE_DATAOUT NUMERIC "1"
-- Retrieval info: PRIVATE: USE_DQS_UNDELAYOUT NUMERIC "0"
-- Retrieval info: PRIVATE: WIDTH NUMERIC "32"
-- Retrieval info: CONSTANT: EXTEND_OE_DISABLE STRING "UNUSED"
-- Retrieval info: CONSTANT: IMPLEMENT_INPUT_IN_LCELL STRING "ON"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: INVERT_OUTPUT STRING "OFF"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altddio_bidir"
-- Retrieval info: CONSTANT: OE_REG STRING "UNUSED"
-- Retrieval info: CONSTANT: POWER_UP_HIGH STRING "OFF"
-- Retrieval info: CONSTANT: WIDTH NUMERIC "32"
-- Retrieval info: USED_PORT: combout 0 0 32 0 OUTPUT NODEFVAL combout[31..0]
-- Retrieval info: USED_PORT: datain_h 0 0 32 0 INPUT NODEFVAL datain_h[31..0]
-- Retrieval info: USED_PORT: datain_l 0 0 32 0 INPUT NODEFVAL datain_l[31..0]
-- Retrieval info: USED_PORT: dataout_h 0 0 32 0 OUTPUT NODEFVAL dataout_h[31..0]
-- Retrieval info: USED_PORT: dataout_l 0 0 32 0 OUTPUT NODEFVAL dataout_l[31..0]
-- Retrieval info: USED_PORT: inclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL inclock
-- Retrieval info: USED_PORT: oe 0 0 0 0 INPUT VCC oe
-- Retrieval info: USED_PORT: outclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL outclock
-- Retrieval info: USED_PORT: padio 0 0 32 0 BIDIR NODEFVAL padio[31..0]
-- Retrieval info: CONNECT: @datain_h 0 0 32 0 datain_h 0 0 32 0
-- Retrieval info: CONNECT: @datain_l 0 0 32 0 datain_l 0 0 32 0
-- Retrieval info: CONNECT: padio 0 0 32 0 @padio 0 0 32 0
-- Retrieval info: CONNECT: @outclock 0 0 0 0 outclock 0 0 0 0
-- Retrieval info: CONNECT: @oe 0 0 0 0 oe 0 0 0 0
-- Retrieval info: CONNECT: dataout_h 0 0 32 0 @dataout_h 0 0 32 0
-- Retrieval info: CONNECT: dataout_l 0 0 32 0 @dataout_l 0 0 32 0
-- Retrieval info: CONNECT: @inclock 0 0 0 0 inclock 0 0 0 0
-- Retrieval info: CONNECT: combout 0 0 32 0 @combout 0 0 32 0
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_bidir0.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_bidir0.ppf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_bidir0.inc TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_bidir0.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_bidir0.bsf TRUE FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_bidir0_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,64 @@
/*
WARNING: Do NOT edit the input and output ports in this file in a text
editor if you plan to continue editing the block that represents it in
the Block Editor! File corruption is VERY likely to occur.
*/
/*
Copyright (C) 1991-2008 Altera Corporation
Your use of Altera Corporation's design tools, logic functions
and other software and tools, and its AMPP partner logic
functions, and any output files from any of the foregoing
(including device programming or simulation files), and any
associated documentation or information are expressly subject
to the terms and conditions of the Altera Program License
Subscription Agreement, Altera MegaCore Function License
Agreement, or other applicable license agreement, including,
without limitation, that your use is for the sole purpose of
programming logic devices manufactured by Altera and sold by
Altera or its authorized distributors. Please refer to the
applicable agreement for further details.
*/
(header "symbol" (version "1.1"))
(symbol
(rect 0 0 232 120)
(text "altddio_out0" (rect 81 1 163 17)(font "Arial" (font_size 10)))
(text "inst" (rect 8 104 25 116)(font "Arial" ))
(port
(pt 0 24)
(input)
(text "datain_h[3..0]" (rect 0 0 76 14)(font "Arial" (font_size 8)))
(text "datain_h[3..0]" (rect 4 11 70 24)(font "Arial" (font_size 8)))
(line (pt 0 24)(pt 88 24)(line_width 3))
)
(port
(pt 0 40)
(input)
(text "datain_l[3..0]" (rect 0 0 71 14)(font "Arial" (font_size 8)))
(text "datain_l[3..0]" (rect 4 27 67 40)(font "Arial" (font_size 8)))
(line (pt 0 40)(pt 88 40)(line_width 3))
)
(port
(pt 0 56)
(input)
(text "outclock" (rect 0 0 47 14)(font "Arial" (font_size 8)))
(text "outclock" (rect 4 43 42 56)(font "Arial" (font_size 8)))
(line (pt 0 56)(pt 88 56)(line_width 1))
)
(port
(pt 232 24)
(output)
(text "dataout[3..0]" (rect 0 0 70 14)(font "Arial" (font_size 8)))
(text "dataout[3..0]" (rect 169 11 229 24)(font "Arial" (font_size 8)))
(line (pt 232 24)(pt 152 24)(line_width 3))
)
(drawing
(text "ddio" (rect 110 27 131 40)(font "Arial" (font_size 8)))
(text "output" (rect 105 42 135 55)(font "Arial" (font_size 8)))
(text "power up" (rect 92 74 129 86)(font "Arial" ))
(text "high" (rect 92 84 109 96)(font "Arial" ))
(line (pt 88 16)(pt 152 16)(line_width 1))
(line (pt 152 16)(pt 152 96)(line_width 1))
(line (pt 152 96)(pt 88 96)(line_width 1))
(line (pt 88 96)(pt 88 16)(line_width 1))
)
)

View File

@@ -0,0 +1,24 @@
--Copyright (C) 1991-2008 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
component altddio_out0
PORT
(
datain_h : IN STD_LOGIC_VECTOR (3 DOWNTO 0);
datain_l : IN STD_LOGIC_VECTOR (3 DOWNTO 0);
outclock : IN STD_LOGIC ;
dataout : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
end component;

View File

@@ -0,0 +1,25 @@
--Copyright (C) 1991-2008 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
FUNCTION altddio_out0
(
datain_h[3..0],
datain_l[3..0],
outclock
)
RETURNS (
dataout[3..0]
);

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="Cyclone III" variation_name="altddio_out0" megafunction_name="ALTDDIO_OUT" specifies="all_ports">
<global>
<pin name="datain_h[3..0]" direction="input" scope="external" />
<pin name="datain_l[3..0]" direction="input" scope="external" />
<pin name="outclock" direction="input" scope="external" source="clock" />
<pin name="dataout[3..0]" direction="output" scope="external" />
</global>
</pinplan>

View File

@@ -0,0 +1,7 @@
set_global_assignment -name IP_TOOL_NAME "ALTDDIO_OUT"
set_global_assignment -name IP_TOOL_VERSION "8.1"
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "altddio_out0.vhd"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altddio_out0.bsf"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altddio_out0.inc"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altddio_out0.cmp"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altddio_out0.ppf"]

View File

@@ -0,0 +1,136 @@
-- megafunction wizard: %ALTDDIO_OUT%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altddio_out
-- ============================================================
-- File Name: altddio_out0.vhd
-- Megafunction Name(s):
-- altddio_out
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 8.1 Build 163 10/28/2008 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2008 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY altddio_out0 IS
PORT
(
datain_h : IN STD_LOGIC_VECTOR (3 DOWNTO 0);
datain_l : IN STD_LOGIC_VECTOR (3 DOWNTO 0);
outclock : IN STD_LOGIC ;
dataout : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
END altddio_out0;
ARCHITECTURE SYN OF altddio_out0 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0);
COMPONENT altddio_out
GENERIC (
extend_oe_disable : STRING;
intended_device_family : STRING;
invert_output : STRING;
lpm_type : STRING;
oe_reg : STRING;
power_up_high : STRING;
width : NATURAL
);
PORT (
dataout : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);
outclock : IN STD_LOGIC ;
datain_h : IN STD_LOGIC_VECTOR (3 DOWNTO 0);
datain_l : IN STD_LOGIC_VECTOR (3 DOWNTO 0)
);
END COMPONENT;
BEGIN
dataout <= sub_wire0(3 DOWNTO 0);
altddio_out_component : altddio_out
GENERIC MAP (
extend_oe_disable => "UNUSED",
intended_device_family => "Cyclone III",
invert_output => "ON",
lpm_type => "altddio_out",
oe_reg => "UNUSED",
power_up_high => "ON",
width => 4
)
PORT MAP (
outclock => outclock,
datain_h => datain_h,
datain_l => datain_l,
dataout => sub_wire0
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ARESET_MODE NUMERIC "2"
-- Retrieval info: PRIVATE: CLKEN NUMERIC "0"
-- Retrieval info: PRIVATE: EXTEND_OE_DISABLE NUMERIC "0"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: OE NUMERIC "0"
-- Retrieval info: PRIVATE: OE_REG NUMERIC "0"
-- Retrieval info: PRIVATE: POWER_UP_HIGH NUMERIC "1"
-- Retrieval info: PRIVATE: SRESET_MODE NUMERIC "2"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: WIDTH NUMERIC "4"
-- Retrieval info: CONSTANT: EXTEND_OE_DISABLE STRING "UNUSED"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: INVERT_OUTPUT STRING "ON"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altddio_out"
-- Retrieval info: CONSTANT: OE_REG STRING "UNUSED"
-- Retrieval info: CONSTANT: POWER_UP_HIGH STRING "ON"
-- Retrieval info: CONSTANT: WIDTH NUMERIC "4"
-- Retrieval info: USED_PORT: datain_h 0 0 4 0 INPUT NODEFVAL datain_h[3..0]
-- Retrieval info: USED_PORT: datain_l 0 0 4 0 INPUT NODEFVAL datain_l[3..0]
-- Retrieval info: USED_PORT: dataout 0 0 4 0 OUTPUT NODEFVAL dataout[3..0]
-- Retrieval info: USED_PORT: outclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL outclock
-- Retrieval info: CONNECT: @datain_h 0 0 4 0 datain_h 0 0 4 0
-- Retrieval info: CONNECT: @datain_l 0 0 4 0 datain_l 0 0 4 0
-- Retrieval info: CONNECT: dataout 0 0 4 0 @dataout 0 0 4 0
-- Retrieval info: CONNECT: @outclock 0 0 0 0 outclock 0 0 0 0
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0.ppf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0.inc TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0.bsf TRUE FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,64 @@
/*
WARNING: Do NOT edit the input and output ports in this file in a text
editor if you plan to continue editing the block that represents it in
the Block Editor! File corruption is VERY likely to occur.
*/
/*
Copyright (C) 1991-2008 Altera Corporation
Your use of Altera Corporation's design tools, logic functions
and other software and tools, and its AMPP partner logic
functions, and any output files from any of the foregoing
(including device programming or simulation files), and any
associated documentation or information are expressly subject
to the terms and conditions of the Altera Program License
Subscription Agreement, Altera MegaCore Function License
Agreement, or other applicable license agreement, including,
without limitation, that your use is for the sole purpose of
programming logic devices manufactured by Altera and sold by
Altera or its authorized distributors. Please refer to the
applicable agreement for further details.
*/
(header "symbol" (version "1.1"))
(symbol
(rect 0 0 232 120)
(text "altddio_out1" (rect 81 1 163 17)(font "Arial" (font_size 10)))
(text "inst" (rect 8 104 25 116)(font "Arial" ))
(port
(pt 0 24)
(input)
(text "datain_h" (rect 0 0 48 14)(font "Arial" (font_size 8)))
(text "datain_h" (rect 4 11 46 24)(font "Arial" (font_size 8)))
(line (pt 0 24)(pt 88 24)(line_width 1))
)
(port
(pt 0 40)
(input)
(text "datain_l" (rect 0 0 43 14)(font "Arial" (font_size 8)))
(text "datain_l" (rect 4 27 43 40)(font "Arial" (font_size 8)))
(line (pt 0 40)(pt 88 40)(line_width 1))
)
(port
(pt 0 56)
(input)
(text "outclock" (rect 0 0 47 14)(font "Arial" (font_size 8)))
(text "outclock" (rect 4 43 42 56)(font "Arial" (font_size 8)))
(line (pt 0 56)(pt 88 56)(line_width 1))
)
(port
(pt 232 24)
(output)
(text "dataout" (rect 0 0 42 14)(font "Arial" (font_size 8)))
(text "dataout" (rect 193 11 229 24)(font "Arial" (font_size 8)))
(line (pt 232 24)(pt 152 24)(line_width 1))
)
(drawing
(text "ddio" (rect 110 27 131 40)(font "Arial" (font_size 8)))
(text "output" (rect 105 42 135 55)(font "Arial" (font_size 8)))
(text "power up" (rect 92 74 129 86)(font "Arial" ))
(text "low" (rect 92 84 105 96)(font "Arial" ))
(line (pt 88 16)(pt 152 16)(line_width 1))
(line (pt 152 16)(pt 152 96)(line_width 1))
(line (pt 152 96)(pt 88 96)(line_width 1))
(line (pt 88 96)(pt 88 16)(line_width 1))
)
)

View File

@@ -0,0 +1,24 @@
--Copyright (C) 1991-2008 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
component altddio_out1
PORT
(
datain_h : IN STD_LOGIC ;
datain_l : IN STD_LOGIC ;
outclock : IN STD_LOGIC ;
dataout : OUT STD_LOGIC
);
end component;

Some files were not shown because too many files have changed in this diff Show More