forked from Firebee/FPGA_Config
Initial commit
This commit is contained in:
44
FPGA_by_Fredi/Coldari1.qsf
Normal file
44
FPGA_by_Fredi/Coldari1.qsf
Normal 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
|
||||
79
FPGA_by_Fredi/DSP/DSP.vhd
Normal file
79
FPGA_by_Fredi/DSP/DSP.vhd
Normal 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;
|
||||
79
FPGA_by_Fredi/DSP/DSP.vhd.bak
Normal file
79
FPGA_by_Fredi/DSP/DSP.vhd.bak
Normal 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;
|
||||
BIN
FPGA_by_Fredi/DSP/dsp56k.zip
Normal file
BIN
FPGA_by_Fredi/DSP/dsp56k.zip
Normal file
Binary file not shown.
216
FPGA_by_Fredi/DSP/src/adgen_stage.vhd
Normal file
216
FPGA_by_Fredi/DSP/src/adgen_stage.vhd
Normal 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;
|
||||
62
FPGA_by_Fredi/DSP/src/constants_pkg.vhd
Normal file
62
FPGA_by_Fredi/DSP/src/constants_pkg.vhd
Normal 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;
|
||||
1221
FPGA_by_Fredi/DSP/src/decode_stage.vhd
Normal file
1221
FPGA_by_Fredi/DSP/src/decode_stage.vhd
Normal file
File diff suppressed because it is too large
Load Diff
603
FPGA_by_Fredi/DSP/src/exec_stage_alu.vhd
Normal file
603
FPGA_by_Fredi/DSP/src/exec_stage_alu.vhd
Normal 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;
|
||||
79
FPGA_by_Fredi/DSP/src/exec_stage_bit_modify.vhd
Normal file
79
FPGA_by_Fredi/DSP/src/exec_stage_bit_modify.vhd
Normal 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;
|
||||
117
FPGA_by_Fredi/DSP/src/exec_stage_branch.vhd
Normal file
117
FPGA_by_Fredi/DSP/src/exec_stage_branch.vhd
Normal 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;
|
||||
75
FPGA_by_Fredi/DSP/src/exec_stage_cc_flag_calc.vhd
Normal file
75
FPGA_by_Fredi/DSP/src/exec_stage_cc_flag_calc.vhd
Normal 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;
|
||||
72
FPGA_by_Fredi/DSP/src/exec_stage_cr_mod.vhd
Normal file
72
FPGA_by_Fredi/DSP/src/exec_stage_cr_mod.vhd
Normal 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;
|
||||
200
FPGA_by_Fredi/DSP/src/exec_stage_loops.vhd
Normal file
200
FPGA_by_Fredi/DSP/src/exec_stage_loops.vhd
Normal 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;
|
||||
60
FPGA_by_Fredi/DSP/src/fetch_stage.vhd
Normal file
60
FPGA_by_Fredi/DSP/src/fetch_stage.vhd
Normal 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;
|
||||
|
||||
1519
FPGA_by_Fredi/DSP/src/mem_control.vhd
Normal file
1519
FPGA_by_Fredi/DSP/src/mem_control.vhd
Normal file
File diff suppressed because it is too large
Load Diff
206
FPGA_by_Fredi/DSP/src/memory_management.vhd
Normal file
206
FPGA_by_Fredi/DSP/src/memory_management.vhd
Normal 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;
|
||||
|
||||
10
FPGA_by_Fredi/DSP/src/parameter_pkg.vhd
Normal file
10
FPGA_by_Fredi/DSP/src/parameter_pkg.vhd
Normal 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;
|
||||
968
FPGA_by_Fredi/DSP/src/pipeline.vhd
Normal file
968
FPGA_by_Fredi/DSP/src/pipeline.vhd
Normal 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;
|
||||
679
FPGA_by_Fredi/DSP/src/reg_file.vhd
Normal file
679
FPGA_by_Fredi/DSP/src/reg_file.vhd
Normal 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;
|
||||
167
FPGA_by_Fredi/DSP/src/types_pkg.vhd
Normal file
167
FPGA_by_Fredi/DSP/src/types_pkg.vhd
Normal 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;
|
||||
971
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/FalconIO_SDCard_IDE_CF.vhd
Normal file
971
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/FalconIO_SDCard_IDE_CF.vhd
Normal 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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
631
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/WF5380/wf5380_control.vhd
Normal file
631
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/WF5380/wf5380_control.vhd
Normal 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;
|
||||
139
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/WF5380/wf5380_pkg.vhd
Normal file
139
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/WF5380/wf5380_pkg.vhd
Normal 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;
|
||||
265
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/WF5380/wf5380_registers.vhd
Normal file
265
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/WF5380/wf5380_registers.vhd
Normal 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;
|
||||
300
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/WF5380/wf5380_soc_top.vhd
Normal file
300
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/WF5380/wf5380_soc_top.vhd
Normal 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;
|
||||
275
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/WF5380/wf5380_top.vhd
Normal file
275
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/WF5380/wf5380_top.vhd
Normal 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;
|
||||
@@ -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
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
95
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo0.bsf
Normal file
95
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo0.bsf
Normal 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))
|
||||
)
|
||||
)
|
||||
28
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo0.cmp
Normal file
28
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo0.cmp
Normal 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;
|
||||
5
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo0.qip
Normal file
5
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo0.qip
Normal 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"]
|
||||
202
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo0.vhd
Normal file
202
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo0.vhd
Normal 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
|
||||
202
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo0.vhd.bak
Normal file
202
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo0.vhd.bak
Normal 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
|
||||
95
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.bsf
Normal file
95
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.bsf
Normal 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))
|
||||
)
|
||||
)
|
||||
28
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.cmp
Normal file
28
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.cmp
Normal 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;
|
||||
5
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.qip
Normal file
5
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.qip
Normal 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"]
|
||||
202
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.vhd
Normal file
202
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.vhd
Normal 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
|
||||
202
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.vhd.bak
Normal file
202
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.vhd.bak
Normal 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
|
||||
478
FPGA_by_Fredi/Interrupt_Handler/interrupt_handler.tdf
Normal file
478
FPGA_by_Fredi/Interrupt_Handler/interrupt_handler.tdf
Normal 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;
|
||||
|
||||
|
||||
478
FPGA_by_Fredi/Interrupt_Handler/interrupt_handler.tdf.bak
Normal file
478
FPGA_by_Fredi/Interrupt_Handler/interrupt_handler.tdf.bak
Normal 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_by_Fredi/UNUSED
Normal file
27
FPGA_by_Fredi/UNUSED
Normal 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;
|
||||
75
FPGA_by_Fredi/Video/BLITTER/BLITTER.vhd
Normal file
75
FPGA_by_Fredi/Video/BLITTER/BLITTER.vhd
Normal 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;
|
||||
75
FPGA_by_Fredi/Video/BLITTER/BLITTER.vhd.bak
Normal file
75
FPGA_by_Fredi/Video/BLITTER/BLITTER.vhd.bak
Normal 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;
|
||||
659
FPGA_by_Fredi/Video/DDR_CTR.tdf
Normal file
659
FPGA_by_Fredi/Video/DDR_CTR.tdf
Normal 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;
|
||||
|
||||
660
FPGA_by_Fredi/Video/DDR_CTR.tdf.bak
Normal file
660
FPGA_by_Fredi/Video/DDR_CTR.tdf.bak
Normal 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;
|
||||
|
||||
352
FPGA_by_Fredi/Video/DDR_CTR_BLITTER.tdf.bak
Normal file
352
FPGA_by_Fredi/Video/DDR_CTR_BLITTER.tdf.bak
Normal 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;
|
||||
|
||||
267
FPGA_by_Fredi/Video/UNUSED
Normal file
267
FPGA_by_Fredi/Video/UNUSED
Normal 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;
|
||||
675
FPGA_by_Fredi/Video/VIDEO_MOD_MUX_CLUTCTR.tdf
Normal file
675
FPGA_by_Fredi/Video/VIDEO_MOD_MUX_CLUTCTR.tdf
Normal 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;
|
||||
675
FPGA_by_Fredi/Video/VIDEO_MOD_MUX_CLUTCTR.tdf.bak
Normal file
675
FPGA_by_Fredi/Video/VIDEO_MOD_MUX_CLUTCTR.tdf.bak
Normal 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;
|
||||
10651
FPGA_by_Fredi/Video/Video.bdf
Normal file
10651
FPGA_by_Fredi/Video/Video.bdf
Normal file
File diff suppressed because it is too large
Load Diff
99
FPGA_by_Fredi/Video/altddio_bidir0.bsf
Normal file
99
FPGA_by_Fredi/Video/altddio_bidir0.bsf
Normal 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))
|
||||
)
|
||||
)
|
||||
29
FPGA_by_Fredi/Video/altddio_bidir0.cmp
Normal file
29
FPGA_by_Fredi/Video/altddio_bidir0.cmp
Normal 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;
|
||||
30
FPGA_by_Fredi/Video/altddio_bidir0.inc
Normal file
30
FPGA_by_Fredi/Video/altddio_bidir0.inc
Normal 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]
|
||||
);
|
||||
16
FPGA_by_Fredi/Video/altddio_bidir0.ppf
Normal file
16
FPGA_by_Fredi/Video/altddio_bidir0.ppf
Normal 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>
|
||||
7
FPGA_by_Fredi/Video/altddio_bidir0.qip
Normal file
7
FPGA_by_Fredi/Video/altddio_bidir0.qip
Normal 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"]
|
||||
172
FPGA_by_Fredi/Video/altddio_bidir0.vhd
Normal file
172
FPGA_by_Fredi/Video/altddio_bidir0.vhd
Normal 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
|
||||
64
FPGA_by_Fredi/Video/altddio_out0.bsf
Normal file
64
FPGA_by_Fredi/Video/altddio_out0.bsf
Normal 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))
|
||||
)
|
||||
)
|
||||
24
FPGA_by_Fredi/Video/altddio_out0.cmp
Normal file
24
FPGA_by_Fredi/Video/altddio_out0.cmp
Normal 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;
|
||||
25
FPGA_by_Fredi/Video/altddio_out0.inc
Normal file
25
FPGA_by_Fredi/Video/altddio_out0.inc
Normal 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]
|
||||
);
|
||||
11
FPGA_by_Fredi/Video/altddio_out0.ppf
Normal file
11
FPGA_by_Fredi/Video/altddio_out0.ppf
Normal 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>
|
||||
7
FPGA_by_Fredi/Video/altddio_out0.qip
Normal file
7
FPGA_by_Fredi/Video/altddio_out0.qip
Normal 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"]
|
||||
136
FPGA_by_Fredi/Video/altddio_out0.vhd
Normal file
136
FPGA_by_Fredi/Video/altddio_out0.vhd
Normal 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
|
||||
64
FPGA_by_Fredi/Video/altddio_out1.bsf
Normal file
64
FPGA_by_Fredi/Video/altddio_out1.bsf
Normal 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))
|
||||
)
|
||||
)
|
||||
24
FPGA_by_Fredi/Video/altddio_out1.cmp
Normal file
24
FPGA_by_Fredi/Video/altddio_out1.cmp
Normal 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
Reference in New Issue
Block a user