139 Commits

Author SHA1 Message Date
ragnar
2f7c3d93aa Merge FPGA_by_Gregory_Estrade/master 2025-09-02 14:22:39 +02:00
ragnar
c2fa66c258 Merge FPGA_Quartus_13.1/master 2025-09-02 14:22:38 +02:00
ragnar
648461457f Merge FPGA_by_Fredi/Quartus_13_1 2025-09-02 14:22:36 +02:00
ragnar
86b4c5a67e Merge FPGA_by_Fredi/master 2025-09-02 14:22:36 +02:00
ragnar
fcf615048b Initial commit 2025-09-02 14:14:12 +02:00
Markus Fröschle
523a5f0287 create datestamp on the fly during compilation 2021-07-11 19:37:07 +02:00
Markus Fröschle
384f7f42a6 fix file format 2018-08-19 19:10:37 +02:00
Markus Fröschle
4164ee3a7b improve formatting 2018-08-19 19:02:11 +02:00
Markus Fröschle
d774f3bd95 fix formatting 2018-08-19 19:01:52 +02:00
Markus Fröschle
81f5aa6f23 fix wrong semicolon 2018-08-19 18:18:13 +02:00
Markus
992ac9dc63 Create README.md
Beware. This code doesn't work (yet).
2018-04-28 08:17:13 +02:00
DavidGZ
23f23bd70c Create README.md 2018-04-09 09:57:02 +02:00
torlus
d2a3f1f4ff IP migration and cleanup - again 2018-04-06 19:07:31 +02:00
torlus
923b18b2d3 better reupload the whole thing :/ 2018-04-06 19:07:31 +02:00
torlus
84f029b1fc IP migration and cleanup 2018-04-06 19:07:31 +02:00
torlus
e6da46a57f video.v fixed (wrong version) 2018-04-06 19:07:30 +02:00
torlus
3b80809684 First full HDL version 2018-04-06 19:07:30 +02:00
Markus Fröschle
f0405d6aa7 reordered pins 2016-07-30 07:30:45 +00:00
Markus Fröschle
22b53a8560 rename video (again?) 2016-07-30 07:17:34 +00:00
Markus Fröschle
c458e4babe increased setup overconstraint 2016-07-29 18:22:56 +00:00
Markus Fröschle
dc54546004 updated workspace 2016-07-29 13:27:45 +00:00
Markus Fröschle
7a04666154 complete flexbus_register component (nearly) 2016-07-29 13:27:25 +00:00
Markus Fröschle
4ae6e349cd this one escaped me ... 2016-07-29 07:16:07 +00:00
Markus Fröschle
386851c02b delete remaininf .bsf (schematics) files 2016-07-29 07:13:44 +00:00
Markus Fröschle
e0269dc6c9 remove remaining .bsf (schematics) files 2016-07-29 06:43:24 +00:00
Markus Fröschle
799f41e8d5 rename file and paths to lower case 2016-07-29 06:29:14 +00:00
Markus Fröschle
268147a9be extend flexbus_register 2016-07-29 05:25:13 +00:00
Markus Fröschle
02e1530cce fix capitalization 2016-07-29 04:49:50 +00:00
Markus Fröschle
7bb446d5ce fix hold timing violations 2016-07-28 21:12:58 +00:00
Markus Fröschle
479861c1c0 fix hold time violations in .sdc 2016-07-28 21:05:55 +00:00
Markus Fröschle
4e6efb55fc add missing file 2016-07-28 16:39:46 +00:00
Markus Fröschle
80880574d8 cleanup interrupt handler chip selects 2016-07-28 15:41:03 +00:00
Markus Fröschle
d2e11f660a fix inthandler_ta which was errornously always enabled 2016-07-28 15:06:33 +00:00
Markus Fröschle
87a7353ee8 remove unneeded tristate bus driver 2016-07-28 12:46:05 +00:00
Markus Fröschle
00511897bf fix capitalisation 2016-07-28 12:33:14 +00:00
Markus Fröschle
f1a038e3a5 finally fixed multiple drivers problem 2016-07-28 11:48:10 +00:00
Markus Fröschle
c6f8a7d4e8 compiles again, but needs reconnecting the split FlexBus signal at top level 2016-07-28 07:11:19 +00:00
Markus Fröschle
cf0c449258 remove inout buffers 2016-07-28 06:08:31 +00:00
Markus Fröschle
8199db400a removed (most) stuck buffers 2016-07-28 05:33:31 +00:00
Markus Fröschle
43c8e5e149 add firebee_utils_pkg 2016-06-04 06:36:00 +00:00
Markus Fröschle
26125ea4a8 formatting 2016-06-03 07:43:07 +00:00
Markus Fröschle
a40b7175e5 replace translator output with more clear VHDL 2016-06-02 16:28:02 +00:00
Markus Fröschle
f03a1eb525 more fixes 2016-06-02 15:57:06 +00:00
Markus Fröschle
ba5713a154 multiple driver problem 2016-04-28 04:34:30 +00:00
Markus Fröschle
761b807e92 reenable nFB_TA 2016-04-27 15:08:14 +00:00
Markus Fröschle
790663a7cf remove unneeded component declarations 2016-04-27 11:32:14 +00:00
Markus Fröschle
777e7a4b1c remove strange constant assignment 2016-04-27 05:59:07 +00:00
Markus Fröschle
36f41e4fb7 fix assignment vector length 2016-04-27 05:24:49 +00:00
Markus Fröschle
195025b4be fix hold time violations 2016-04-27 05:10:46 +00:00
Markus Fröschle
6cf7000199 fix number of bits to compare 2016-04-26 19:58:21 +00:00
Markus Fröschle
1a972f2c64 reformatting 2016-04-26 19:34:39 +00:00
Markus Fröschle
fa4a3f686c simplify and fix errors 2016-04-26 16:39:22 +00:00
Markus Fröschle
a7f6d4191e add function f_addr_cmp() 2016-04-26 06:14:03 +00:00
Markus Fröschle
6a0eebf068 change formatting 2016-04-25 19:09:52 +00:00
Markus Fröschle
fb71e53c7e fix timing violation at border color assignment 2016-04-14 18:11:14 +00:00
Markus Fröschle
8114dcadf3 fix hsync len calculation for Firebee mode 2016-04-14 05:56:39 +00:00
Markus Fröschle
accc7e85f0 make it compile again 2016-02-10 17:06:57 +00:00
Markus Fröschle
5f55a6738a cast to std_logic_vector 2016-01-19 17:36:29 +00:00
Markus Fröschle
752b4cd0ad modify to use WHEN statements instead of binary logic 2016-01-19 15:50:36 +00:00
Markus Fröschle
1846f7eff2 remove specialised clocks 2016-01-19 07:27:27 +00:00
Markus Fröschle
2724be31d1 removed more "indirect" clocks 2016-01-19 07:07:31 +00:00
Markus Fröschle
9f01c704dc saved 2016-01-18 18:45:17 +00:00
Markus Fröschle
e2ab4af020 get rid of BUFFER parameters 2016-01-18 18:32:50 +00:00
Markus Fröschle
652dd1c124 hold time fix test 2016-01-18 18:15:02 +00:00
Markus Fröschle
e623e668c2 more flexbus_register work 2016-01-18 07:40:08 +00:00
Markus Fröschle
47f6884bbe add more functionality 2016-01-17 21:45:53 +00:00
Markus Fröschle
b9c3ec9366 modify indent 2016-01-17 20:39:25 +00:00
Markus Fröschle
21a4a80fb7 start of flexbus_register implementation to simplify that 2016-01-17 20:28:18 +00:00
Markus Fröschle
ddad975d6f fix 13MHz clock sdc 2016-01-17 08:43:20 +00:00
Markus Fröschle
91791dfb5d do not automatically insert delay chains 2016-01-16 22:11:51 +00:00
Markus Fröschle
58a69ffc5f reformat 2016-01-16 22:04:05 +00:00
Markus Fröschle
7bf4d912a0 fix timing 2016-01-16 21:38:17 +00:00
Markus Fröschle
0fe61bedef fix output delay 2016-01-15 17:38:29 +00:00
Markus Fröschle
11bd410c15 simplify processes 2016-01-15 08:37:40 +00:00
Markus Fröschle
f11629ac29 fix video base address and video counter register 2016-01-14 22:02:44 +00:00
Markus Fröschle
c4d56bb652 reformat 2016-01-14 16:49:11 +00:00
Markus Fröschle
b7a34c8abf reformat 2016-01-14 07:17:08 +00:00
Markus Fröschle
69c107ef32 remove unused connections 2016-01-14 06:45:15 +00:00
Markus Fröschle
52e1b53192 formatting 2016-01-14 06:44:52 +00:00
Markus Fröschle
4ed4616156 remove unused generated signals 2016-01-13 16:43:54 +00:00
Markus Fröschle
97a48bf636 reactivated delay chain 2016-01-13 15:04:24 +00:00
Markus Fröschle
fd5abf8b4a reformat 2016-01-13 13:23:46 +00:00
Markus Fröschle
90c0f7758d remove AHDL files 2016-01-13 12:54:00 +00:00
Markus Fröschle
5183d08d60 finish conversion to vhdl 2016-01-13 12:53:03 +00:00
Markus Fröschle
79a14e2a70 reformat internal signals 2016-01-13 07:27:57 +00:00
Markus Fröschle
621e2267a7 renamed pixel_clk_i 2016-01-13 07:16:24 +00:00
Markus Fröschle
c8b693d755 add file 2016-01-12 17:11:58 +00:00
Markus Fröschle
29df555945 reformat 2016-01-12 17:11:07 +00:00
Markus Fröschle
f1f893bc44 fix ports 2016-01-12 17:10:19 +00:00
Markus Fröschle
87100a7d62 fix formatting 2016-01-12 08:00:20 +00:00
Markus Fröschle
703d95ee75 fix wire loop
still works (kind of) - pixel errors in MiNT, does not boot (no picture) with "pure" EmuTOS?
2016-01-12 07:58:07 +00:00
Markus Fröschle
7d2430a62c reformat converted VHDL 2016-01-12 07:14:33 +00:00
Markus Fröschle
3ec978dff5 translate DDR_CTR to vhd 2016-01-11 17:55:18 +00:00
Markus Fröschle
35d70dc637 fix min instead of max 2016-01-11 17:07:35 +00:00
Markus Fröschle
b35e12b329 add more DDR clk signals to sdc 2016-01-11 17:05:39 +00:00
Markus Fröschle
476825a3ba translate interrupt_controller to vhd 2016-01-11 16:11:04 +00:00
Markus Fröschle
98a362dc90 replace video.bdf with video.vhd 2016-01-11 08:43:42 +00:00
Markus Fröschle
f6aa56ac7a convert firebee1.bdf to vhdl 2016-01-11 08:18:06 +00:00
Markus Fröschle
b3edfcd457 reformat 2016-01-11 07:13:36 +00:00
Markus Fröschle
9cfde26eef modify settings 2016-01-10 19:05:15 +00:00
Markus Fröschle
7296970eb6 rename Video.bdf to lower case 2016-01-10 10:24:30 +00:00
Markus Fröschle
f887503255 rename to make it usable as alternative in Quartus 2016-01-10 07:44:20 +00:00
Markus Fröschle
f94b5f265e remove delay chains 2016-01-09 21:36:02 +00:00
Markus Fröschle
7bdeac0860 rename video registers to their Falcon names 2016-01-09 18:49:18 +00:00
Markus Fröschle
5c933580a2 fix ACP web address 2015-11-18 06:41:49 +00:00
Markus Fröschle
fc8034d93b patch with Fredi's lp fix (and others) 2015-10-26 06:48:18 +00:00
Markus Fröschle
1c661c8052 formatting 2015-10-18 19:33:25 +00:00
Markus Fröschle
13032a8635 reformat 2015-10-18 19:27:57 +00:00
Markus Fröschle
56adcdd218 added another false path to fix timing 2015-10-18 01:02:05 +00:00
Markus Fröschle
8b7fe5f731 fix timing (set_false_path was missing) 2015-10-18 00:57:04 +00:00
Markus Fröschle
7f4b30f483 changed component name to lower case 2015-10-17 16:10:06 +00:00
Markus Fröschle
602c20bb30 add missing project file 2015-10-17 10:58:27 +00:00
Markus Fröschle
9180cca701 basically working config. Resolution changes still scramble the screen, however 2015-10-17 09:40:48 +00:00
Markus Fröschle
7e2181fbc9 improved timing, added timing constraints, got rid of CLK_33M
Design compiles and runs, but still has issues with different screen resolutions and video clocks
2015-09-23 09:49:05 +00:00
Markus Fröschle
ad05ca8523 cleanup 2015-09-21 05:32:56 +00:00
Markus Fröschle
32b95cf958 cleanup 2015-09-21 05:21:50 +00:00
Markus Fröschle
988bf01340 cleanup 2015-09-21 05:16:42 +00:00
Markus Fröschle
a640ef35f6 removed absolute DOS path 2015-09-20 21:41:31 +00:00
Markus Fröschle
865bbf15c5 reformatted 2015-09-20 20:14:42 +00:00
Markus Fröschle
6f0464a1c7 added derive_clock_uncertainty 2015-09-20 19:50:38 +00:00
Markus Fröschle
d9364d9da5 more false_path settings 2015-09-20 19:24:59 +00:00
Markus Fröschle
5d4920f849 upgrade lpm components 2015-09-20 18:08:31 +00:00
Markus Fröschle
bb0f702a45 reformatted, forced tighter timing
Config works, but screen is still scrambled
2015-09-20 17:13:10 +00:00
Markus Fröschle
fb3fcdf996 add false paths to design constraints 2015-09-20 16:23:52 +00:00
Markus Fröschle
f72db5f2b5 renamed components to lower case 2015-09-20 15:07:18 +00:00
Markus Fröschle
6288a1e16b reformatted. 2015-09-20 14:54:16 +00:00
Markus Fröschle
f416539480 get rid of CLK33M 2015-09-20 12:32:02 +00:00
Markus Fröschle
489fb04b16 get rid of generated files 2015-09-20 12:24:45 +00:00
Markus Fröschle
32cb8b0206 reformatted 2015-09-20 08:23:00 +00:00
Markus Fröschle
4f57571130 renamed many instances to more meaningful names 2015-09-20 08:06:12 +00:00
Markus Fröschle
8ec08da1fd add TimeQuest Synopsis Design Constraint file 2015-09-20 07:01:21 +00:00
Markus Fröschle
7efdf33216 get rid of more generated files 2015-09-20 07:00:34 +00:00
Markus Fröschle
f60e37521b reordered files in project 2015-09-20 06:21:11 +00:00
Markus Fröschle
428c51b9ee remove absolute paths in project file 2015-09-20 05:52:52 +00:00
Markus Fröschle
a639206992 get rid of more generated files 2015-09-20 05:49:54 +00:00
Markus Fröschle
0a33b29b95 get rid of generated files 2015-09-20 05:48:22 +00:00
Markus Fröschle
aa1041cb3f another try to make the old config work 2015-09-20 05:45:41 +00:00
David Gálvez
95ac8a3004 Moved source_fa into trunk 2011-01-03 08:10:50 +00:00
aschi54
1b6b1201a2 2010-12-27 13:20:36 +00:00
786 changed files with 222745 additions and 7670 deletions

View File

@@ -0,0 +1,52 @@
library ieee;
use ieee.std_logic_1164.all;
-- Entity Declaration
entity dsp is
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_in : in std_logic_vector(31 downto 0);
fb_ad_out : out std_logic_vector(31 downto 0);
IO : inout std_logic_vector(17 downto 0);
SRD : inout std_logic_vector(15 downto 0)
);
end dsp;
-- Architecture Body
architecture rtl 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_in(31 downto 16) when nFB_WR = '0' and nSRCS = '0' else (others => 'Z');
-- fb_ad_out(31 downto 16) <= srd(15 DOWNTO 0 )when nFB_OE = '0' AND nSRCS = '0' ELSE (others => 'Z');
fb_ad_out(31 downto 0) <= (others => 'Z'); -- otherwise we get a constant driver error
end rtl;

Binary file not shown.

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,202 @@
----------------------------------------------------------------------
---- ----
---- 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 std_logic;
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 : buffer 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 CTS_In : bit;
signal DCD_In : bit;
signal DCD_FLAGn : bit;
begin
CTS_In <= CTSn;
DCD_In <= DCDn; -- immer 0
STATUS_REG(7) <= not IRQn;
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' else (others => '0');
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '0' 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(CLK)
begin
if rising_edge(CLK) then
if RESETn = '0' or MCLR = '1' then
IRQn <= '1';
else
-- Transmitter interrupt:
if TDRE = '1' and CTRL_REG(6 downto 5) = "01" then
IRQn <= '0';
end if;
-- Receiver interrupts:
if RDRF = '1' and RIE = '1' then
IRQn <= '0';
end if;
-- Overrun
if OVR = '1' and RIE = '1' then
IRQn <= '0';
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' then
IRQn <= '1';
end if;
end if;
end if;
end process P_IRQ;
CONTROL: process(CLK)
begin
if rising_edge(CLK) then
if RESETn = '0' then
CTRL_REG <= "01000000";
elsif CS = "011" and RWn = '0' and RS = '0' then
CTRL_REG <= DATA_IN;
end if;
end if;
end process CONTROL;
P_DCD: process(CLK)
-- 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
if rising_edge(CLK) then
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' then
READ_LOCK := false; -- Un-READ_LOCK if receiver data register is read.
elsif CS = "011" and RWn = '1' and RS = '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 if;
end process P_DCD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,432 @@
----------------------------------------------------------------------
---- ----
---- 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 std_logic;
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 rtl 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(CLK)
-- 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
IF rising_edge(CLK) THEN
--
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 IF;
END PROCESS p_sample;
clkdiv : PROCESS(CLK)
VARIABLE CLK_LOCK : boolean;
VARIABLE STRB_LOCK : boolean;
VARIABLE CLK_DIVCNT : std_logic_vector(6 DOWNTO 0);
BEGIN
IF rising_edge(CLK) THEN
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 IF;
END PROCESS clkdiv;
datareg : PROCESS(RESETn, CLK)
BEGIN
IF RESETn = '0' or MCLR = '1' THEN
DATA_REG <= x"00";
ELSE
IF rising_edge(CLK) THEN
IF 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 IF;
END PROCESS datareg;
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' or MCLR = '1' THEN
SHIFT_REG <= x"00";
ELSE
IF rising_edge(CLK) THEN
IF RCV_STATE = SAMPLE and CLK_STRB = '1' THEN
SHIFT_REG <= RXDATA_S & SHIFT_REG(7 DOWNTO 1); -- Shift right.
END IF;
END IF;
END IF;
END PROCESS shiftreg;
p_bitcnt : PROCESS(CLK)
BEGIN
IF rising_edge(CLK) THEN
IF RCV_STATE = SAMPLE and CLK_STRB = '1' THEN
BITCNT <= BITCNT + '1';
ELSIF RCV_STATE /= SAMPLE THEN
BITCNT <= (OTHERS => '0');
END IF;
END IF;
END PROCESS p_bitcnt;
p_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';
ELSE
IF rising_edge(CLK) 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 IF;
END PROCESS p_frame_err;
p_overrun : PROCESS(RESETn, CLK)
VARIABLE OVR_I : bit;
VARIABLE FIRST_READ : boolean;
BEGIN
IF rising_edge(CLK) THEN
IF RESETn = '0' or MCLR = '1' THEN
OVR_I := '0';
OVR <= '0';
FIRST_READ := false;
ELSE
IF 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' 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
IF OVR_I = '1' THEN
OVR <= '1';
OVR_I := '0';
FIRST_READ := true;
ELSE
OVR <= '0';
END IF;
END IF;
ELSE
FIRST_READ := false;
END IF;
END IF;
END IF;
END PROCESS p_overrun;
p_parity_test : PROCESS(RESETn,MCLR,CLK)
VARIABLE PAR_TMP : bit;
VARIABLE PE_I : bit;
BEGIN
IF RESETn = '0' or MCLR = '1' THEN
PE <= '0';
ELSE
IF rising_edge(CLK) THEN
IF 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;
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' THEN
PE <= '0'; -- Clear when reading the data register.
END IF;
END IF;
END PROCESS p_parity_test;
p_rdrf : process(RESETn, CLK)
-- Receive data register full flag.
BEGIN
IF rising_edge(CLK) THEN
IF RESETn = '0' or MCLR = '1' THEN
RDRF <= '0';
ELSE
IF RCV_STATE = SYNC THEN
RDRF <= '1'; -- Data register is full until now!
END IF;
IF CS = "011" and RWn = '1' and RS = '1' THEN
RDRF <= '0'; -- when reading the data register ...
END IF;
END IF;
END IF;
END PROCESS p_rdrf;
p_rcv_statereg : PROCESS(RESETn, CLK)
BEGIN
IF RESETn = '0' THEN
RCV_STATE <= IDLE;
ELSE
IF rising_edge(CLK) THEN
IF MCLR = '1' THEN
RCV_STATE <= IDLE;
ELSE
RCV_STATE <= RCV_NEXT_STATE;
END IF;
END IF;
END IF;
END PROCESS p_rcv_statereg;
p_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 p_rcv_statedec;
END ARCHITECTURE rtl;

View File

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

View File

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

View File

@@ -0,0 +1,338 @@
----------------------------------------------------------------------
---- ----
---- 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 std_logic;
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(CLK)
variable CLK_LOCK : boolean;
variable STRB_LOCK : boolean;
variable CLK_DIVCNT : std_logic_vector(6 downto 0);
begin
if rising_edge(CLK) then
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 if;
end process CLKDIV;
DATAREG: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= x"00";
elsif rising_edge(CLK) 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 rising_edge(CLK) 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(CLK)
-- Counter for the data bits transmitted.
begin
if rising_edge(CLK) then
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif TR_STATE /= SHIFTOUT then
BITCNT <= "000";
end if;
end if;
end process P_BITCNT;
P_TDRE: process(RESETn, CLK)
-- Transmit data register empty flag.
begin
if rising_edge(CLK) then
if RESETn = '0' or MCLR = '1' then
TDRE <= '1';
else
if 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';
end if;
if CS = "011" and RWn = '0' and RS = '1' then
TDRE <= '0';
end if;
end if;
end if;
end process P_TDRE;
PARITY_GEN: process(CLK)
variable PAR_TMP : bit;
begin
if rising_edge(CLK) then
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 if;
end process PARITY_GEN;
TR_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
TR_STATE <= IDLE;
else
if rising_edge(CLK) then
if MCLR = '1' then
TR_STATE <= IDLE;
else
TR_STATE <= TR_NEXT_STATE;
end if;
end if;
end if;
end process TR_STATEREG;
TR_STATEDEC: process(TR_STATE, CLK_STRB, TC, BITCNT, WS, TDRE, CTSn)
begin
case TR_STATE is
when IDLE =>
if TDRE = '1' and TC = "11" then
TR_NEXT_STATE <= LOAD_SHFT;
elsif TDRE = '0' and CTSn = '0' then -- Start if data register is not empty.
TR_NEXT_STATE <= LOAD_SHFT;
else
TR_NEXT_STATE <= IDLE;
end if;
when LOAD_SHFT =>
TR_NEXT_STATE <= START;
when START =>
if CLK_STRB = '1' then
TR_NEXT_STATE <= SHIFTOUT;
else
TR_NEXT_STATE <= START;
end if;
when SHIFTOUT =>
if CLK_STRB = '1' then
if BITCNT < "110" and WS(2) = '0' then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 7 data bits.
elsif BITCNT < "111" and WS(2) = '1' then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 8 data bits.
elsif WS = "100" or WS = "101" then
if TDRE = '1' and TC = "11" then
-- Break condition, do not send a stop bit.
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP1; -- No parity check enabled.
end if;
else
TR_NEXT_STATE <= PARITY; -- Parity enabled.
end if;
else
TR_NEXT_STATE <= SHIFTOUT;
end if;
when PARITY =>
if CLK_STRB = '1' then
if TDRE = '1' and TC = "11" then
-- Break condition, do not send a stop bit.
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP1; -- No parity check enabled.
end if;
else
TR_NEXT_STATE <= PARITY;
end if;
when STOP1 =>
if CLK_STRB = '1' and (WS = "000" or WS = "001" or WS = "100") then
TR_NEXT_STATE <= STOP2; -- Two stop bits selected.
elsif CLK_STRB = '1' then
TR_NEXT_STATE <= IDLE; -- One stop bits selected.
else
TR_NEXT_STATE <= STOP1;
end if;
when STOP2 =>
if CLK_STRB = '1' then
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP2;
end if;
end case;
end process TR_STATEDEC;
end architecture BEHAVIOR;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,390 @@
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;
nRSTO : 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;
INT_L[9..0] :DFF;
INT_LA[9..0][3..0] :DFF;
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ÖSEN, 1=INT7 AUSLÖ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[].CLRN = nRSTO;
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_L[].CLK = MAIN_CLK;
INT_L[].CLRN = nRSTO;
INT_L0 = PIC_INT & INT_ENA[0];
INT_L1 = E0_INT & INT_ENA[1];
INT_L2 = DVI_INT & INT_ENA[2];
INT_L3 = !nPCI_INTA & INT_ENA[3];
INT_L4 = !nPCI_INTB & INT_ENA[4];
INT_L5 = !nPCI_INTC & INT_ENA[5];
INT_L6 = !nPCI_INTD & INT_ENA[6];
INT_L7 = DSP_INT & INT_ENA[7];
INT_L8 = VSYNC & INT_ENA[8];
INT_L9 = HSYNC & INT_ENA[9];
INT_LA[][].CLK = MAIN_CLK;
INT_LATCH[] = H"FFFFFFFF";
INT_LATCH[].CLRN = !INT_CLEAR[] & nRSTO;
FOR I IN 0 TO 9 GENERATE
INT_LA[I][].CLRN = INT_ENA[I] & nRSTO;
INT_LA[I][] = INT_LA[I][]+1 & INT_L[I] & INT_LA[I][]<7
# INT_LA[I][]-1 & !INT_L[I] & INT_LA[I][]>8
# 15 & INT_L[I] & INT_LA[I][]>6
# 0 & !INT_L[I] & INT_LA[I][]<9;
INT_LATCH[I].CLK = INT_LA[I][3];
END GENERATE;
-- 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;
FOR I IN 10 TO 63 GENERATE
WERTE[7..0][I] = FB_AD[23..16];
END GENERATE;
FOR I IN 0 TO 63 GENERATE
WERTE[][I].ENA = RTC_ADR[]==I & UHR_DS & !nFB_WR;
END GENERATE;
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;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
# FPGA_Quartus_13.1
FireBee's FPGA developed on Quartus 13.1

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,146 @@
-- 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 ;
datain_l : IN STD_LOGIC ;
outclock : IN STD_LOGIC ;
dataout : OUT STD_LOGIC
);
END altddio_out0;
ARCHITECTURE SYN OF altddio_out0 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (0 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC ;
SIGNAL sub_wire2 : STD_LOGIC ;
SIGNAL sub_wire3 : STD_LOGIC_VECTOR (0 DOWNTO 0);
SIGNAL sub_wire4 : STD_LOGIC ;
SIGNAL sub_wire5 : STD_LOGIC_VECTOR (0 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 (0 DOWNTO 0);
outclock : IN STD_LOGIC ;
datain_h : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
datain_l : IN STD_LOGIC_VECTOR (0 DOWNTO 0)
);
END COMPONENT;
BEGIN
sub_wire1 <= sub_wire0(0);
dataout <= sub_wire1;
sub_wire2 <= datain_h;
sub_wire3(0) <= sub_wire2;
sub_wire4 <= datain_l;
sub_wire5(0) <= sub_wire4;
altddio_out_component : altddio_out
GENERIC MAP (
extend_oe_disable => "UNUSED",
intended_device_family => "Cyclone III",
invert_output => "OFF",
lpm_type => "altddio_out",
oe_reg => "UNUSED",
power_up_high => "OFF",
width => 1
)
PORT MAP (
outclock => outclock,
datain_h => sub_wire3,
datain_l => sub_wire5,
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 "0"
-- Retrieval info: PRIVATE: SRESET_MODE NUMERIC "2"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: WIDTH NUMERIC "1"
-- Retrieval info: CONSTANT: EXTEND_OE_DISABLE STRING "UNUSED"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: INVERT_OUTPUT STRING "OFF"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altddio_out"
-- Retrieval info: CONSTANT: OE_REG STRING "UNUSED"
-- Retrieval info: CONSTANT: POWER_UP_HIGH STRING "OFF"
-- Retrieval info: CONSTANT: WIDTH NUMERIC "1"
-- Retrieval info: USED_PORT: datain_h 0 0 0 0 INPUT NODEFVAL datain_h
-- Retrieval info: USED_PORT: datain_l 0 0 0 0 INPUT NODEFVAL datain_l
-- Retrieval info: USED_PORT: dataout 0 0 0 0 OUTPUT NODEFVAL dataout
-- Retrieval info: USED_PORT: outclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL outclock
-- Retrieval info: CONNECT: @datain_h 0 0 1 0 datain_h 0 0 0 0
-- Retrieval info: CONNECT: @datain_l 0 0 1 0 datain_l 0 0 0 0
-- Retrieval info: CONNECT: dataout 0 0 0 0 @dataout 0 0 1 0
-- Retrieval info: CONNECT: @outclock 0 0 0 0 outclock 0 0 0 0
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0.ppf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0.inc TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0.bsf TRUE FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out0_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,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_out3
PORT
(
datain_h : IN STD_LOGIC ;
datain_l : IN STD_LOGIC ;
outclock : IN STD_LOGIC ;
dataout : OUT STD_LOGIC
);
end component;

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,146 @@
-- megafunction wizard: %ALTDDIO_OUT%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altddio_out
-- ============================================================
-- File Name: altddio_out3.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_out3 IS
PORT
(
datain_h : IN STD_LOGIC ;
datain_l : IN STD_LOGIC ;
outclock : IN STD_LOGIC ;
dataout : OUT STD_LOGIC
);
END altddio_out3;
ARCHITECTURE SYN OF altddio_out3 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (0 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC ;
SIGNAL sub_wire2 : STD_LOGIC ;
SIGNAL sub_wire3 : STD_LOGIC_VECTOR (0 DOWNTO 0);
SIGNAL sub_wire4 : STD_LOGIC ;
SIGNAL sub_wire5 : STD_LOGIC_VECTOR (0 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 (0 DOWNTO 0);
outclock : IN STD_LOGIC ;
datain_h : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
datain_l : IN STD_LOGIC_VECTOR (0 DOWNTO 0)
);
END COMPONENT;
BEGIN
sub_wire1 <= sub_wire0(0);
dataout <= sub_wire1;
sub_wire2 <= datain_h;
sub_wire3(0) <= sub_wire2;
sub_wire4 <= datain_l;
sub_wire5(0) <= sub_wire4;
altddio_out_component : altddio_out
GENERIC MAP (
extend_oe_disable => "UNUSED",
intended_device_family => "Cyclone III",
invert_output => "OFF",
lpm_type => "altddio_out",
oe_reg => "UNUSED",
power_up_high => "OFF",
width => 1
)
PORT MAP (
outclock => outclock,
datain_h => sub_wire3,
datain_l => sub_wire5,
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 "0"
-- Retrieval info: PRIVATE: SRESET_MODE NUMERIC "2"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: WIDTH NUMERIC "1"
-- Retrieval info: CONSTANT: EXTEND_OE_DISABLE STRING "UNUSED"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: INVERT_OUTPUT STRING "OFF"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altddio_out"
-- Retrieval info: CONSTANT: OE_REG STRING "UNUSED"
-- Retrieval info: CONSTANT: POWER_UP_HIGH STRING "OFF"
-- Retrieval info: CONSTANT: WIDTH NUMERIC "1"
-- Retrieval info: USED_PORT: datain_h 0 0 0 0 INPUT NODEFVAL datain_h
-- Retrieval info: USED_PORT: datain_l 0 0 0 0 INPUT NODEFVAL datain_l
-- Retrieval info: USED_PORT: dataout 0 0 0 0 OUTPUT NODEFVAL dataout
-- Retrieval info: USED_PORT: outclock 0 0 0 0 INPUT_CLK_EXT NODEFVAL outclock
-- Retrieval info: CONNECT: @datain_h 0 0 1 0 datain_h 0 0 0 0
-- Retrieval info: CONNECT: @datain_l 0 0 1 0 datain_l 0 0 0 0
-- Retrieval info: CONNECT: dataout 0 0 0 0 @dataout 0 0 1 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_out3.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out3.ppf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out3.inc TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out3.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out3.bsf TRUE FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altddio_out3_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,6 @@
set_global_assignment -name IP_TOOL_NAME "ALTIOBUF"
set_global_assignment -name IP_TOOL_VERSION "9.1"
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altiobuf_bidir0.tdf"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altiobuf_bidir0.bsf"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altiobuf_bidir0.inc"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altiobuf_bidir0.cmp"]

View File

@@ -0,0 +1,26 @@
--Copyright (C) 1991-2010 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 altpll0
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC ;
c3 : OUT STD_LOGIC ;
c4 : OUT STD_LOGIC
);
end component;

View File

@@ -0,0 +1,27 @@
--Copyright (C) 1991-2010 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 altpll0
(
inclk0
)
RETURNS (
c0,
c1,
c2,
c3,
c4
);

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="Cyclone III" variation_name="altpll0" megafunction_name="ALTPLL" specifies="all_ports">
<global>
<pin name="inclk0" direction="input" scope="external" source="clock" />
<pin name="c0" direction="output" scope="external" source="clock" />
<pin name="c1" direction="output" scope="external" source="clock" />
<pin name="c2" direction="output" scope="external" source="clock" />
<pin name="c3" direction="output" scope="external" source="clock" />
<pin name="c4" direction="output" scope="external" source="clock" />
</global>
</pinplan>

View File

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

View File

@@ -0,0 +1,477 @@
-- megafunction wizard: %ALTPLL%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altpll
-- ============================================================
-- File Name: altpll0.vhd
-- Megafunction Name(s):
-- altpll
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 9.1 Build 350 03/24/2010 SP 2 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2010 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 altpll0 IS
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC ;
c3 : OUT STD_LOGIC ;
c4 : OUT STD_LOGIC
);
END altpll0;
ARCHITECTURE SYN OF altpll0 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC ;
SIGNAL sub_wire2 : STD_LOGIC ;
SIGNAL sub_wire3 : STD_LOGIC ;
SIGNAL sub_wire4 : STD_LOGIC ;
SIGNAL sub_wire5 : STD_LOGIC ;
SIGNAL sub_wire6 : STD_LOGIC ;
SIGNAL sub_wire7 : STD_LOGIC_VECTOR (1 DOWNTO 0);
SIGNAL sub_wire8_bv : BIT_VECTOR (0 DOWNTO 0);
SIGNAL sub_wire8 : STD_LOGIC_VECTOR (0 DOWNTO 0);
COMPONENT altpll
GENERIC (
bandwidth_type : STRING;
clk0_divide_by : NATURAL;
clk0_duty_cycle : NATURAL;
clk0_multiply_by : NATURAL;
clk0_phase_shift : STRING;
clk1_divide_by : NATURAL;
clk1_duty_cycle : NATURAL;
clk1_multiply_by : NATURAL;
clk1_phase_shift : STRING;
clk2_divide_by : NATURAL;
clk2_duty_cycle : NATURAL;
clk2_multiply_by : NATURAL;
clk2_phase_shift : STRING;
clk3_divide_by : NATURAL;
clk3_duty_cycle : NATURAL;
clk3_multiply_by : NATURAL;
clk3_phase_shift : STRING;
clk4_divide_by : NATURAL;
clk4_duty_cycle : NATURAL;
clk4_multiply_by : NATURAL;
clk4_phase_shift : STRING;
compensate_clock : STRING;
inclk0_input_frequency : NATURAL;
intended_device_family : STRING;
lpm_type : STRING;
operation_mode : STRING;
pll_type : STRING;
port_activeclock : STRING;
port_areset : STRING;
port_clkbad0 : STRING;
port_clkbad1 : STRING;
port_clkloss : STRING;
port_clkswitch : STRING;
port_configupdate : STRING;
port_fbin : STRING;
port_inclk0 : STRING;
port_inclk1 : STRING;
port_locked : STRING;
port_pfdena : STRING;
port_phasecounterselect : STRING;
port_phasedone : STRING;
port_phasestep : STRING;
port_phaseupdown : STRING;
port_pllena : STRING;
port_scanaclr : STRING;
port_scanclk : STRING;
port_scanclkena : STRING;
port_scandata : STRING;
port_scandataout : STRING;
port_scandone : STRING;
port_scanread : STRING;
port_scanwrite : STRING;
port_clk0 : STRING;
port_clk1 : STRING;
port_clk2 : STRING;
port_clk3 : STRING;
port_clk4 : STRING;
port_clk5 : STRING;
port_clkena0 : STRING;
port_clkena1 : STRING;
port_clkena2 : STRING;
port_clkena3 : STRING;
port_clkena4 : STRING;
port_clkena5 : STRING;
port_extclk0 : STRING;
port_extclk1 : STRING;
port_extclk2 : STRING;
port_extclk3 : STRING;
width_clock : NATURAL
);
PORT (
inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0)
);
END COMPONENT;
BEGIN
sub_wire8_bv(0 DOWNTO 0) <= "0";
sub_wire8 <= To_stdlogicvector(sub_wire8_bv);
sub_wire5 <= sub_wire0(4);
sub_wire4 <= sub_wire0(3);
sub_wire3 <= sub_wire0(2);
sub_wire2 <= sub_wire0(1);
sub_wire1 <= sub_wire0(0);
c0 <= sub_wire1;
c1 <= sub_wire2;
c2 <= sub_wire3;
c3 <= sub_wire4;
c4 <= sub_wire5;
sub_wire6 <= inclk0;
sub_wire7 <= sub_wire8(0 DOWNTO 0) & sub_wire6;
altpll_component : altpll
GENERIC MAP (
bandwidth_type => "AUTO",
clk0_divide_by => 11,
clk0_duty_cycle => 50,
clk0_multiply_by => 16,
clk0_phase_shift => "0",
clk1_divide_by => 11,
clk1_duty_cycle => 50,
clk1_multiply_by => 50,
clk1_phase_shift => "0",
clk2_divide_by => 11,
clk2_duty_cycle => 50,
clk2_multiply_by => 40,
clk2_phase_shift => "0",
clk3_divide_by => 33,
clk3_duty_cycle => 50,
clk3_multiply_by => 109,
clk3_phase_shift => "0",
clk4_divide_by => 39,
clk4_duty_cycle => 50,
clk4_multiply_by => 109,
clk4_phase_shift => "0",
compensate_clock => "CLK0",
inclk0_input_frequency => 30303,
intended_device_family => "Cyclone III",
lpm_type => "altpll",
operation_mode => "NORMAL",
pll_type => "AUTO",
port_activeclock => "PORT_UNUSED",
port_areset => "PORT_UNUSED",
port_clkbad0 => "PORT_UNUSED",
port_clkbad1 => "PORT_UNUSED",
port_clkloss => "PORT_UNUSED",
port_clkswitch => "PORT_UNUSED",
port_configupdate => "PORT_UNUSED",
port_fbin => "PORT_UNUSED",
port_inclk0 => "PORT_USED",
port_inclk1 => "PORT_UNUSED",
port_locked => "PORT_UNUSED",
port_pfdena => "PORT_UNUSED",
port_phasecounterselect => "PORT_UNUSED",
port_phasedone => "PORT_UNUSED",
port_phasestep => "PORT_UNUSED",
port_phaseupdown => "PORT_UNUSED",
port_pllena => "PORT_UNUSED",
port_scanaclr => "PORT_UNUSED",
port_scanclk => "PORT_UNUSED",
port_scanclkena => "PORT_UNUSED",
port_scandata => "PORT_UNUSED",
port_scandataout => "PORT_UNUSED",
port_scandone => "PORT_UNUSED",
port_scanread => "PORT_UNUSED",
port_scanwrite => "PORT_UNUSED",
port_clk0 => "PORT_USED",
port_clk1 => "PORT_USED",
port_clk2 => "PORT_USED",
port_clk3 => "PORT_USED",
port_clk4 => "PORT_USED",
port_clk5 => "PORT_UNUSED",
port_clkena0 => "PORT_UNUSED",
port_clkena1 => "PORT_UNUSED",
port_clkena2 => "PORT_UNUSED",
port_clkena3 => "PORT_UNUSED",
port_clkena4 => "PORT_UNUSED",
port_clkena5 => "PORT_UNUSED",
port_extclk0 => "PORT_UNUSED",
port_extclk1 => "PORT_UNUSED",
port_extclk2 => "PORT_UNUSED",
port_extclk3 => "PORT_UNUSED",
width_clock => 5
)
PORT MAP (
inclk => sub_wire7,
clk => sub_wire0
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0"
-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "75"
-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "33"
-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "36"
-- Retrieval info: PRIVATE: DIV_FACTOR3 NUMERIC "39"
-- Retrieval info: PRIVATE: DIV_FACTOR4 NUMERIC "39"
-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE3 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE4 STRING "50.00000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "48.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "150.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "120.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE3 STRING "109.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE4 STRING "92.230766"
-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "33.000"
-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0"
-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "330.000"
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT3 STRING "ps"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT4 STRING "ps"
-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK3 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK4 STRING "0"
-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "109"
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "109"
-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "109"
-- Retrieval info: PRIVATE: MULT_FACTOR3 NUMERIC "109"
-- Retrieval info: PRIVATE: MULT_FACTOR4 NUMERIC "109"
-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "48.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "150.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "120.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ3 STRING "109.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ4 STRING "92.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE3 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE4 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT3 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT4 STRING "MHz"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT3 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT4 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "ps"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT3 STRING "ps"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT4 STRING "ps"
-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "altpll0.mif"
-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
-- Retrieval info: PRIVATE: SPREAD_USE STRING "0"
-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK3 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK4 STRING "1"
-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: USE_CLK0 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK1 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK2 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK3 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK4 STRING "1"
-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA3 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA4 STRING "0"
-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "11"
-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "16"
-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "11"
-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "50"
-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "11"
-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "40"
-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK3_DIVIDE_BY NUMERIC "33"
-- Retrieval info: CONSTANT: CLK3_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK3_MULTIPLY_BY NUMERIC "109"
-- Retrieval info: CONSTANT: CLK3_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK4_DIVIDE_BY NUMERIC "39"
-- Retrieval info: CONSTANT: CLK4_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK4_MULTIPLY_BY NUMERIC "109"
-- Retrieval info: CONSTANT: CLK4_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "30303"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
-- Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]"
-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
-- Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
-- Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
-- Retrieval info: USED_PORT: c3 0 0 0 0 OUTPUT_CLK_EXT VCC "c3"
-- Retrieval info: USED_PORT: c4 0 0 0 0 OUTPUT_CLK_EXT VCC "c4"
-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
-- Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
-- Retrieval info: CONNECT: c3 0 0 0 0 @clk 0 0 1 3
-- Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2
-- Retrieval info: CONNECT: c4 0 0 0 0 @clk 0 0 1 4
-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll0.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll0.ppf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll0.inc TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll0.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll0.bsf TRUE FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll0_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll0_waveforms.html TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll0_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,25 @@
--Copyright (C) 1991-2014 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 altpll1
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC ;
locked : OUT STD_LOGIC
);
end component;

View File

@@ -0,0 +1,26 @@
--Copyright (C) 1991-2014 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 altpll1
(
inclk0
)
RETURNS (
c0,
c1,
c2,
locked
);

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="Cyclone III" variation_name="altpll1" megafunction_name="ALTPLL" specifies="all_ports">
<global>
<pin name="inclk0" direction="input" scope="external" source="clock" />
<pin name="c0" direction="output" scope="external" source="clock" />
<pin name="c1" direction="output" scope="external" source="clock" />
<pin name="c2" direction="output" scope="external" source="clock" />
<pin name="locked" direction="output" scope="external" />
</global>
</pinplan>

View File

@@ -0,0 +1,4 @@
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
set_global_assignment -name IP_TOOL_VERSION "13.1"
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "altpll1.vhd"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altpll1.ppf"]

View File

@@ -0,0 +1,420 @@
-- megafunction wizard: %ALTPLL%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altpll
-- ============================================================
-- File Name: altpll1.vhd
-- Megafunction Name(s):
-- altpll
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 13.1.4 Build 182 03/12/2014 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2014 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 altpll1 IS
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC ;
locked : OUT STD_LOGIC
);
END altpll1;
ARCHITECTURE SYN OF altpll1 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC ;
SIGNAL sub_wire2 : STD_LOGIC ;
SIGNAL sub_wire3 : STD_LOGIC ;
SIGNAL sub_wire4 : STD_LOGIC ;
SIGNAL sub_wire5 : STD_LOGIC ;
SIGNAL sub_wire6 : STD_LOGIC_VECTOR (1 DOWNTO 0);
SIGNAL sub_wire7_bv : BIT_VECTOR (0 DOWNTO 0);
SIGNAL sub_wire7 : STD_LOGIC_VECTOR (0 DOWNTO 0);
COMPONENT altpll
GENERIC (
bandwidth_type : STRING;
clk0_divide_by : NATURAL;
clk0_duty_cycle : NATURAL;
clk0_multiply_by : NATURAL;
clk0_phase_shift : STRING;
clk1_divide_by : NATURAL;
clk1_duty_cycle : NATURAL;
clk1_multiply_by : NATURAL;
clk1_phase_shift : STRING;
clk2_divide_by : NATURAL;
clk2_duty_cycle : NATURAL;
clk2_multiply_by : NATURAL;
clk2_phase_shift : STRING;
inclk0_input_frequency : NATURAL;
intended_device_family : STRING;
lpm_type : STRING;
operation_mode : STRING;
pll_type : STRING;
port_activeclock : STRING;
port_areset : STRING;
port_clkbad0 : STRING;
port_clkbad1 : STRING;
port_clkloss : STRING;
port_clkswitch : STRING;
port_configupdate : STRING;
port_fbin : STRING;
port_inclk0 : STRING;
port_inclk1 : STRING;
port_locked : STRING;
port_pfdena : STRING;
port_phasecounterselect : STRING;
port_phasedone : STRING;
port_phasestep : STRING;
port_phaseupdown : STRING;
port_pllena : STRING;
port_scanaclr : STRING;
port_scanclk : STRING;
port_scanclkena : STRING;
port_scandata : STRING;
port_scandataout : STRING;
port_scandone : STRING;
port_scanread : STRING;
port_scanwrite : STRING;
port_clk0 : STRING;
port_clk1 : STRING;
port_clk2 : STRING;
port_clk3 : STRING;
port_clk4 : STRING;
port_clk5 : STRING;
port_clkena0 : STRING;
port_clkena1 : STRING;
port_clkena2 : STRING;
port_clkena3 : STRING;
port_clkena4 : STRING;
port_clkena5 : STRING;
port_extclk0 : STRING;
port_extclk1 : STRING;
port_extclk2 : STRING;
port_extclk3 : STRING;
self_reset_on_loss_lock : STRING;
width_clock : NATURAL
);
PORT (
clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0);
inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
locked : OUT STD_LOGIC
);
END COMPONENT;
BEGIN
sub_wire7_bv(0 DOWNTO 0) <= "0";
sub_wire7 <= To_stdlogicvector(sub_wire7_bv);
sub_wire4 <= sub_wire0(2);
sub_wire3 <= sub_wire0(0);
sub_wire1 <= sub_wire0(1);
c1 <= sub_wire1;
locked <= sub_wire2;
c0 <= sub_wire3;
c2 <= sub_wire4;
sub_wire5 <= inclk0;
sub_wire6 <= sub_wire7(0 DOWNTO 0) & sub_wire5;
altpll_component : altpll
GENERIC MAP (
bandwidth_type => "LOW",
clk0_divide_by => 11,
clk0_duty_cycle => 50,
clk0_multiply_by => 16,
clk0_phase_shift => "0",
clk1_divide_by => 33,
clk1_duty_cycle => 50,
clk1_multiply_by => 16,
clk1_phase_shift => "0",
clk2_divide_by => 1375,
clk2_duty_cycle => 50,
clk2_multiply_by => 1024,
clk2_phase_shift => "0",
inclk0_input_frequency => 30303,
intended_device_family => "Cyclone III",
lpm_type => "altpll",
operation_mode => "NO_COMPENSATION",
pll_type => "AUTO",
port_activeclock => "PORT_UNUSED",
port_areset => "PORT_UNUSED",
port_clkbad0 => "PORT_UNUSED",
port_clkbad1 => "PORT_UNUSED",
port_clkloss => "PORT_UNUSED",
port_clkswitch => "PORT_UNUSED",
port_configupdate => "PORT_UNUSED",
port_fbin => "PORT_UNUSED",
port_inclk0 => "PORT_USED",
port_inclk1 => "PORT_UNUSED",
port_locked => "PORT_USED",
port_pfdena => "PORT_UNUSED",
port_phasecounterselect => "PORT_UNUSED",
port_phasedone => "PORT_UNUSED",
port_phasestep => "PORT_UNUSED",
port_phaseupdown => "PORT_UNUSED",
port_pllena => "PORT_UNUSED",
port_scanaclr => "PORT_UNUSED",
port_scanclk => "PORT_UNUSED",
port_scanclkena => "PORT_UNUSED",
port_scandata => "PORT_UNUSED",
port_scandataout => "PORT_UNUSED",
port_scandone => "PORT_UNUSED",
port_scanread => "PORT_UNUSED",
port_scanwrite => "PORT_UNUSED",
port_clk0 => "PORT_USED",
port_clk1 => "PORT_USED",
port_clk2 => "PORT_USED",
port_clk3 => "PORT_UNUSED",
port_clk4 => "PORT_UNUSED",
port_clk5 => "PORT_UNUSED",
port_clkena0 => "PORT_UNUSED",
port_clkena1 => "PORT_UNUSED",
port_clkena2 => "PORT_UNUSED",
port_clkena3 => "PORT_UNUSED",
port_clkena4 => "PORT_UNUSED",
port_clkena5 => "PORT_UNUSED",
port_extclk0 => "PORT_UNUSED",
port_extclk1 => "PORT_UNUSED",
port_extclk2 => "PORT_UNUSED",
port_extclk3 => "PORT_UNUSED",
self_reset_on_loss_lock => "OFF",
width_clock => 5
)
PORT MAP (
inclk => sub_wire6,
clk => sub_wire0,
locked => sub_wire2
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "0"
-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "1"
-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "1"
-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0"
-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "900"
-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "90"
-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "48.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "16.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "24.576000"
-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "33.000"
-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "ps"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "deg"
-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "67"
-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "67"
-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "48.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "16.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "24.57600000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "ps"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "deg"
-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "altpll1.mif"
-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
-- Retrieval info: PRIVATE: SPREAD_USE STRING "0"
-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"
-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: USE_CLK0 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK1 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK2 STRING "1"
-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"
-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "LOW"
-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "11"
-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "16"
-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "33"
-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "16"
-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "1375"
-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "1024"
-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "30303"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NO_COMPENSATION"
-- Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]"
-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
-- Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
-- Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
-- Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
-- Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
-- Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2
-- Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll1.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll1.ppf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll1.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll1.cmp FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll1.bsf FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll1_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll1_waveforms.html FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll1_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,26 @@
--Copyright (C) 1991-2014 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 altpll2
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC ;
c3 : OUT STD_LOGIC ;
c4 : OUT STD_LOGIC
);
end component;

View File

@@ -0,0 +1,27 @@
--Copyright (C) 1991-2014 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 altpll2
(
inclk0
)
RETURNS (
c0,
c1,
c2,
c3,
c4
);

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="Cyclone III" variation_name="altpll2" megafunction_name="ALTPLL" specifies="all_ports">
<global>
<pin name="inclk0" direction="input" scope="external" source="clock" />
<pin name="c0" direction="output" scope="external" source="clock" />
<pin name="c1" direction="output" scope="external" source="clock" />
<pin name="c2" direction="output" scope="external" source="clock" />
<pin name="c3" direction="output" scope="external" source="clock" />
<pin name="c4" direction="output" scope="external" source="clock" />
</global>
</pinplan>

View File

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

View File

@@ -0,0 +1,477 @@
-- megafunction wizard: %ALTPLL%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altpll
-- ============================================================
-- File Name: altpll2.vhd
-- Megafunction Name(s):
-- altpll
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 13.1.4 Build 182 03/12/2014 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2014 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 altpll2 IS
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC ;
c3 : OUT STD_LOGIC ;
c4 : OUT STD_LOGIC
);
END altpll2;
ARCHITECTURE SYN OF altpll2 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC ;
SIGNAL sub_wire2 : STD_LOGIC ;
SIGNAL sub_wire3 : STD_LOGIC ;
SIGNAL sub_wire4 : STD_LOGIC ;
SIGNAL sub_wire5 : STD_LOGIC ;
SIGNAL sub_wire6 : STD_LOGIC ;
SIGNAL sub_wire7 : STD_LOGIC_VECTOR (1 DOWNTO 0);
SIGNAL sub_wire8_bv : BIT_VECTOR (0 DOWNTO 0);
SIGNAL sub_wire8 : STD_LOGIC_VECTOR (0 DOWNTO 0);
COMPONENT altpll
GENERIC (
bandwidth_type : STRING;
clk0_divide_by : NATURAL;
clk0_duty_cycle : NATURAL;
clk0_multiply_by : NATURAL;
clk0_phase_shift : STRING;
clk1_divide_by : NATURAL;
clk1_duty_cycle : NATURAL;
clk1_multiply_by : NATURAL;
clk1_phase_shift : STRING;
clk2_divide_by : NATURAL;
clk2_duty_cycle : NATURAL;
clk2_multiply_by : NATURAL;
clk2_phase_shift : STRING;
clk3_divide_by : NATURAL;
clk3_duty_cycle : NATURAL;
clk3_multiply_by : NATURAL;
clk3_phase_shift : STRING;
clk4_divide_by : NATURAL;
clk4_duty_cycle : NATURAL;
clk4_multiply_by : NATURAL;
clk4_phase_shift : STRING;
compensate_clock : STRING;
inclk0_input_frequency : NATURAL;
intended_device_family : STRING;
lpm_type : STRING;
operation_mode : STRING;
pll_type : STRING;
port_activeclock : STRING;
port_areset : STRING;
port_clkbad0 : STRING;
port_clkbad1 : STRING;
port_clkloss : STRING;
port_clkswitch : STRING;
port_configupdate : STRING;
port_fbin : STRING;
port_inclk0 : STRING;
port_inclk1 : STRING;
port_locked : STRING;
port_pfdena : STRING;
port_phasecounterselect : STRING;
port_phasedone : STRING;
port_phasestep : STRING;
port_phaseupdown : STRING;
port_pllena : STRING;
port_scanaclr : STRING;
port_scanclk : STRING;
port_scanclkena : STRING;
port_scandata : STRING;
port_scandataout : STRING;
port_scandone : STRING;
port_scanread : STRING;
port_scanwrite : STRING;
port_clk0 : STRING;
port_clk1 : STRING;
port_clk2 : STRING;
port_clk3 : STRING;
port_clk4 : STRING;
port_clk5 : STRING;
port_clkena0 : STRING;
port_clkena1 : STRING;
port_clkena2 : STRING;
port_clkena3 : STRING;
port_clkena4 : STRING;
port_clkena5 : STRING;
port_extclk0 : STRING;
port_extclk1 : STRING;
port_extclk2 : STRING;
port_extclk3 : STRING;
width_clock : NATURAL
);
PORT (
clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0);
inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0)
);
END COMPONENT;
BEGIN
sub_wire8_bv(0 DOWNTO 0) <= "0";
sub_wire8 <= To_stdlogicvector(sub_wire8_bv);
sub_wire5 <= sub_wire0(4);
sub_wire4 <= sub_wire0(2);
sub_wire3 <= sub_wire0(0);
sub_wire2 <= sub_wire0(3);
sub_wire1 <= sub_wire0(1);
c1 <= sub_wire1;
c3 <= sub_wire2;
c0 <= sub_wire3;
c2 <= sub_wire4;
c4 <= sub_wire5;
sub_wire6 <= inclk0;
sub_wire7 <= sub_wire8(0 DOWNTO 0) & sub_wire6;
altpll_component : altpll
GENERIC MAP (
bandwidth_type => "AUTO",
clk0_divide_by => 1,
clk0_duty_cycle => 50,
clk0_multiply_by => 4,
clk0_phase_shift => "5051",
clk1_divide_by => 1,
clk1_duty_cycle => 50,
clk1_multiply_by => 4,
clk1_phase_shift => "0",
clk2_divide_by => 1,
clk2_duty_cycle => 50,
clk2_multiply_by => 4,
clk2_phase_shift => "3788",
clk3_divide_by => 1,
clk3_duty_cycle => 50,
clk3_multiply_by => 4,
clk3_phase_shift => "2210",
clk4_divide_by => 1,
clk4_duty_cycle => 50,
clk4_multiply_by => 2,
clk4_phase_shift => "11364",
compensate_clock => "CLK0",
inclk0_input_frequency => 30303,
intended_device_family => "Cyclone III",
lpm_type => "altpll",
operation_mode => "SOURCE_SYNCHRONOUS",
pll_type => "AUTO",
port_activeclock => "PORT_UNUSED",
port_areset => "PORT_UNUSED",
port_clkbad0 => "PORT_UNUSED",
port_clkbad1 => "PORT_UNUSED",
port_clkloss => "PORT_UNUSED",
port_clkswitch => "PORT_UNUSED",
port_configupdate => "PORT_UNUSED",
port_fbin => "PORT_UNUSED",
port_inclk0 => "PORT_USED",
port_inclk1 => "PORT_UNUSED",
port_locked => "PORT_UNUSED",
port_pfdena => "PORT_UNUSED",
port_phasecounterselect => "PORT_UNUSED",
port_phasedone => "PORT_UNUSED",
port_phasestep => "PORT_UNUSED",
port_phaseupdown => "PORT_UNUSED",
port_pllena => "PORT_UNUSED",
port_scanaclr => "PORT_UNUSED",
port_scanclk => "PORT_UNUSED",
port_scanclkena => "PORT_UNUSED",
port_scandata => "PORT_UNUSED",
port_scandataout => "PORT_UNUSED",
port_scandone => "PORT_UNUSED",
port_scanread => "PORT_UNUSED",
port_scanwrite => "PORT_UNUSED",
port_clk0 => "PORT_USED",
port_clk1 => "PORT_USED",
port_clk2 => "PORT_USED",
port_clk3 => "PORT_USED",
port_clk4 => "PORT_USED",
port_clk5 => "PORT_UNUSED",
port_clkena0 => "PORT_UNUSED",
port_clkena1 => "PORT_UNUSED",
port_clkena2 => "PORT_UNUSED",
port_clkena3 => "PORT_UNUSED",
port_clkena4 => "PORT_UNUSED",
port_clkena5 => "PORT_UNUSED",
port_extclk0 => "PORT_UNUSED",
port_extclk1 => "PORT_UNUSED",
port_extclk2 => "PORT_UNUSED",
port_extclk3 => "PORT_UNUSED",
width_clock => 5
)
PORT MAP (
inclk => sub_wire7,
clk => sub_wire0
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1"
-- Retrieval info: PRIVATE: DIV_FACTOR3 NUMERIC "1"
-- Retrieval info: PRIVATE: DIV_FACTOR4 NUMERIC "1"
-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE3 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE4 STRING "50.00000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "132.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "132.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "132.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE3 STRING "132.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE4 STRING "66.000000"
-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "33.000"
-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0"
-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "deg"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT3 STRING "ps"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT4 STRING "ps"
-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK3 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK4 STRING "0"
-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "4"
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "4"
-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "4"
-- Retrieval info: PRIVATE: MULT_FACTOR3 NUMERIC "4"
-- Retrieval info: PRIVATE: MULT_FACTOR4 NUMERIC "2"
-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "133.33333000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "133.33330000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "133.33330000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ3 STRING "133.33330000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ4 STRING "100.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE3 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE4 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT3 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT4 STRING "MHz"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "240.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "180.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT3 STRING "105.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT4 STRING "270.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT3 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT4 STRING "deg"
-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "altpll2.mif"
-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
-- Retrieval info: PRIVATE: SPREAD_USE STRING "0"
-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK3 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK4 STRING "1"
-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: USE_CLK0 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK1 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK2 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK3 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK4 STRING "1"
-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA3 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA4 STRING "0"
-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1"
-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "4"
-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "5051"
-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1"
-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "4"
-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "1"
-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "4"
-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "3788"
-- Retrieval info: CONSTANT: CLK3_DIVIDE_BY NUMERIC "1"
-- Retrieval info: CONSTANT: CLK3_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK3_MULTIPLY_BY NUMERIC "4"
-- Retrieval info: CONSTANT: CLK3_PHASE_SHIFT STRING "2210"
-- Retrieval info: CONSTANT: CLK4_DIVIDE_BY NUMERIC "1"
-- Retrieval info: CONSTANT: CLK4_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK4_MULTIPLY_BY NUMERIC "2"
-- Retrieval info: CONSTANT: CLK4_PHASE_SHIFT STRING "11364"
-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "30303"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "SOURCE_SYNCHRONOUS"
-- Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]"
-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
-- Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
-- Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
-- Retrieval info: USED_PORT: c3 0 0 0 0 OUTPUT_CLK_EXT VCC "c3"
-- Retrieval info: USED_PORT: c4 0 0 0 0 OUTPUT_CLK_EXT VCC "c4"
-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
-- Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
-- Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2
-- Retrieval info: CONNECT: c3 0 0 0 0 @clk 0 0 1 3
-- Retrieval info: CONNECT: c4 0 0 0 0 @clk 0 0 1 4
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll2.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll2.ppf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll2.inc TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll2.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll2.bsf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll2_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll2_waveforms.html TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll2_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,26 @@
--Copyright (C) 1991-2010 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 altpll3
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC ;
c3 : OUT STD_LOGIC ;
locked : OUT STD_LOGIC
);
end component;

View File

@@ -1,23 +1,27 @@
--Copyright (C) 1991-2010 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 FPGA_DATE
(
)
RETURNS (
result[31..0]
);
--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 altpll3
(
inclk0
)
RETURNS (
c0,
c1,
c2,
c3,
locked
);

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="Cyclone III" variation_name="altpll3" megafunction_name="ALTPLL" specifies="all_ports">
<global>
<pin name="inclk0" direction="input" scope="external" source="clock" />
<pin name="c0" direction="output" scope="external" source="clock" />
<pin name="c1" direction="output" scope="external" source="clock" />
<pin name="c2" direction="output" scope="external" source="clock" />
<pin name="c3" direction="output" scope="external" source="clock" />
<pin name="locked" direction="output" scope="external" />
</global>
</pinplan>

View File

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

View File

@@ -0,0 +1,455 @@
-- megafunction wizard: %ALTPLL%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altpll
-- ============================================================
-- File Name: altpll3.vhd
-- Megafunction Name(s):
-- altpll
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 9.1 Build 350 03/24/2010 SP 2 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2010 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 altpll3 IS
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC ;
c3 : OUT STD_LOGIC ;
locked : OUT STD_LOGIC
);
END altpll3;
ARCHITECTURE SYN OF altpll3 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC ;
SIGNAL sub_wire2 : STD_LOGIC ;
SIGNAL sub_wire3 : STD_LOGIC ;
SIGNAL sub_wire4 : STD_LOGIC ;
SIGNAL sub_wire5 : STD_LOGIC ;
SIGNAL sub_wire6 : STD_LOGIC ;
SIGNAL sub_wire7 : STD_LOGIC_VECTOR (1 DOWNTO 0);
SIGNAL sub_wire8_bv : BIT_VECTOR (0 DOWNTO 0);
SIGNAL sub_wire8 : STD_LOGIC_VECTOR (0 DOWNTO 0);
COMPONENT altpll
GENERIC (
bandwidth_type : STRING;
clk0_divide_by : NATURAL;
clk0_duty_cycle : NATURAL;
clk0_multiply_by : NATURAL;
clk0_phase_shift : STRING;
clk1_divide_by : NATURAL;
clk1_duty_cycle : NATURAL;
clk1_multiply_by : NATURAL;
clk1_phase_shift : STRING;
clk2_divide_by : NATURAL;
clk2_duty_cycle : NATURAL;
clk2_multiply_by : NATURAL;
clk2_phase_shift : STRING;
clk3_divide_by : NATURAL;
clk3_duty_cycle : NATURAL;
clk3_multiply_by : NATURAL;
clk3_phase_shift : STRING;
compensate_clock : STRING;
inclk0_input_frequency : NATURAL;
intended_device_family : STRING;
lpm_type : STRING;
operation_mode : STRING;
pll_type : STRING;
port_activeclock : STRING;
port_areset : STRING;
port_clkbad0 : STRING;
port_clkbad1 : STRING;
port_clkloss : STRING;
port_clkswitch : STRING;
port_configupdate : STRING;
port_fbin : STRING;
port_inclk0 : STRING;
port_inclk1 : STRING;
port_locked : STRING;
port_pfdena : STRING;
port_phasecounterselect : STRING;
port_phasedone : STRING;
port_phasestep : STRING;
port_phaseupdown : STRING;
port_pllena : STRING;
port_scanaclr : STRING;
port_scanclk : STRING;
port_scanclkena : STRING;
port_scandata : STRING;
port_scandataout : STRING;
port_scandone : STRING;
port_scanread : STRING;
port_scanwrite : STRING;
port_clk0 : STRING;
port_clk1 : STRING;
port_clk2 : STRING;
port_clk3 : STRING;
port_clk4 : STRING;
port_clk5 : STRING;
port_clkena0 : STRING;
port_clkena1 : STRING;
port_clkena2 : STRING;
port_clkena3 : STRING;
port_clkena4 : STRING;
port_clkena5 : STRING;
port_extclk0 : STRING;
port_extclk1 : STRING;
port_extclk2 : STRING;
port_extclk3 : STRING;
self_reset_on_loss_lock : STRING;
width_clock : NATURAL
);
PORT (
inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
locked : OUT STD_LOGIC ;
clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0)
);
END COMPONENT;
BEGIN
sub_wire8_bv(0 DOWNTO 0) <= "0";
sub_wire8 <= To_stdlogicvector(sub_wire8_bv);
sub_wire4 <= sub_wire0(3);
sub_wire3 <= sub_wire0(2);
sub_wire2 <= sub_wire0(1);
sub_wire1 <= sub_wire0(0);
c0 <= sub_wire1;
c1 <= sub_wire2;
c2 <= sub_wire3;
c3 <= sub_wire4;
locked <= sub_wire5;
sub_wire6 <= inclk0;
sub_wire7 <= sub_wire8(0 DOWNTO 0) & sub_wire6;
altpll_component : altpll
GENERIC MAP (
bandwidth_type => "AUTO",
clk0_divide_by => 33,
clk0_duty_cycle => 50,
clk0_multiply_by => 25,
clk0_phase_shift => "0",
clk1_divide_by => 33,
clk1_duty_cycle => 50,
clk1_multiply_by => 2,
clk1_phase_shift => "0",
clk2_divide_by => 66,
clk2_duty_cycle => 50,
clk2_multiply_by => 1,
clk2_phase_shift => "0",
clk3_divide_by => 6875,
clk3_duty_cycle => 50,
clk3_multiply_by => 512,
clk3_phase_shift => "0",
compensate_clock => "CLK0",
inclk0_input_frequency => 30303,
intended_device_family => "Cyclone III",
lpm_type => "altpll",
operation_mode => "SOURCE_SYNCHRONOUS",
pll_type => "AUTO",
port_activeclock => "PORT_UNUSED",
port_areset => "PORT_UNUSED",
port_clkbad0 => "PORT_UNUSED",
port_clkbad1 => "PORT_UNUSED",
port_clkloss => "PORT_UNUSED",
port_clkswitch => "PORT_UNUSED",
port_configupdate => "PORT_UNUSED",
port_fbin => "PORT_UNUSED",
port_inclk0 => "PORT_USED",
port_inclk1 => "PORT_UNUSED",
port_locked => "PORT_USED",
port_pfdena => "PORT_UNUSED",
port_phasecounterselect => "PORT_UNUSED",
port_phasedone => "PORT_UNUSED",
port_phasestep => "PORT_UNUSED",
port_phaseupdown => "PORT_UNUSED",
port_pllena => "PORT_UNUSED",
port_scanaclr => "PORT_UNUSED",
port_scanclk => "PORT_UNUSED",
port_scanclkena => "PORT_UNUSED",
port_scandata => "PORT_UNUSED",
port_scandataout => "PORT_UNUSED",
port_scandone => "PORT_UNUSED",
port_scanread => "PORT_UNUSED",
port_scanwrite => "PORT_UNUSED",
port_clk0 => "PORT_USED",
port_clk1 => "PORT_USED",
port_clk2 => "PORT_USED",
port_clk3 => "PORT_USED",
port_clk4 => "PORT_UNUSED",
port_clk5 => "PORT_UNUSED",
port_clkena0 => "PORT_UNUSED",
port_clkena1 => "PORT_UNUSED",
port_clkena2 => "PORT_UNUSED",
port_clkena3 => "PORT_UNUSED",
port_clkena4 => "PORT_UNUSED",
port_clkena5 => "PORT_UNUSED",
port_extclk0 => "PORT_UNUSED",
port_extclk1 => "PORT_UNUSED",
port_extclk2 => "PORT_UNUSED",
port_extclk3 => "PORT_UNUSED",
self_reset_on_loss_lock => "OFF",
width_clock => 5
)
PORT MAP (
inclk => sub_wire7,
clk => sub_wire0,
locked => sub_wire5
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0"
-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "72"
-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "906"
-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "3072"
-- Retrieval info: PRIVATE: DIV_FACTOR3 NUMERIC "738"
-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE3 STRING "50.00000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "25.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "2.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "0.500000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE3 STRING "2.457600"
-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "33.000"
-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "330.000"
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "deg"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT3 STRING "ps"
-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK3 STRING "0"
-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "55"
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "55"
-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "55"
-- Retrieval info: PRIVATE: MULT_FACTOR3 NUMERIC "55"
-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "25.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "2.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "0.50000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ3 STRING "2.45760000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE3 STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT3 STRING "MHz"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT3 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT3 STRING "ns"
-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "altpll3.mif"
-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
-- Retrieval info: PRIVATE: SPREAD_USE STRING "0"
-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK3 STRING "1"
-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: USE_CLK0 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK1 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK2 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK3 STRING "1"
-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA3 STRING "0"
-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "33"
-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "25"
-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "33"
-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "2"
-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "66"
-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "1"
-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK3_DIVIDE_BY NUMERIC "6875"
-- Retrieval info: CONSTANT: CLK3_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK3_MULTIPLY_BY NUMERIC "512"
-- Retrieval info: CONSTANT: CLK3_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "30303"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "SOURCE_SYNCHRONOUS"
-- Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]"
-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
-- Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
-- Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
-- Retrieval info: USED_PORT: c3 0 0 0 0 OUTPUT_CLK_EXT VCC "c3"
-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
-- Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
-- Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
-- Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
-- Retrieval info: CONNECT: c3 0 0 0 0 @clk 0 0 1 3
-- Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2
-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll3.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll3.ppf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll3.inc TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll3.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll3.bsf TRUE FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll3_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll3_waveforms.html TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL altpll3_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,30 @@
--Copyright (C) 1991-2014 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 altpll4
PORT
(
areset : IN STD_LOGIC := '0';
configupdate : IN STD_LOGIC := '0';
inclk0 : IN STD_LOGIC := '0';
scanclk : IN STD_LOGIC := '1';
scanclkena : IN STD_LOGIC := '0';
scandata : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
locked : OUT STD_LOGIC ;
scandataout : OUT STD_LOGIC ;
scandone : OUT STD_LOGIC
);
end component;

View File

@@ -0,0 +1,31 @@
--Copyright (C) 1991-2014 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 altpll4
(
areset,
configupdate,
inclk0,
scanclk,
scanclkena,
scandata
)
RETURNS (
c0,
locked,
scandataout,
scandone
);

View File

@@ -0,0 +1,174 @@
-- Copyright (C) 1991-2014 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.
-- MIF file representing initial state of PLL Scan Chain
-- Device Family: Cyclone III
-- Device Part: -
-- Device Speed Grade: 8
-- PLL Scan Chain: Fast PLL (144 bits)
-- File Name: /home/mfro/Dokumente/Development/workspace/FPGA_quartus_ori/altpll4.mif
-- Generated: Fri Oct 30 21:50:08 2015
WIDTH=1;
DEPTH=144;
ADDRESS_RADIX=UNS;
DATA_RADIX=UNS;
CONTENT BEGIN
0 : 0; -- Reserved Bits = 0 (1 bit(s))
1 : 0; -- Reserved Bits = 0 (1 bit(s))
2 : 0; -- Loop Filter Capacitance = 0 (2 bit(s)) (Setting 0)
3 : 0;
4 : 1; -- Loop Filter Resistance = 27 (5 bit(s)) (Setting 27)
5 : 1;
6 : 0;
7 : 1;
8 : 1;
9 : 0; -- VCO Post Scale = 0 (1 bit(s)) (VCO post-scale divider counter value = 2)
10 : 0; -- Reserved Bits = 0 (5 bit(s))
11 : 0;
12 : 0;
13 : 0;
14 : 0;
15 : 0; -- Charge Pump Current = 1 (3 bit(s)) (Setting 1)
16 : 0;
17 : 1;
18 : 1; -- N counter: Bypass = 1 (1 bit(s))
19 : 0; -- N counter: High Count = 0 (8 bit(s))
20 : 0;
21 : 0;
22 : 0;
23 : 0;
24 : 0;
25 : 0;
26 : 0;
27 : 0; -- N counter: Odd Division = 0 (1 bit(s))
28 : 0; -- N counter: Low Count = 0 (8 bit(s))
29 : 0;
30 : 0;
31 : 0;
32 : 0;
33 : 0;
34 : 0;
35 : 0;
36 : 0; -- M counter: Bypass = 0 (1 bit(s))
37 : 0; -- M counter: High Count = 6 (8 bit(s))
38 : 0;
39 : 0;
40 : 0;
41 : 0;
42 : 1;
43 : 1;
44 : 0;
45 : 0; -- M counter: Odd Division = 0 (1 bit(s))
46 : 0; -- M counter: Low Count = 6 (8 bit(s))
47 : 0;
48 : 0;
49 : 0;
50 : 0;
51 : 1;
52 : 1;
53 : 0;
54 : 0; -- clk0 counter: Bypass = 0 (1 bit(s))
55 : 0; -- clk0 counter: High Count = 3 (8 bit(s))
56 : 0;
57 : 0;
58 : 0;
59 : 0;
60 : 0;
61 : 1;
62 : 1;
63 : 0; -- clk0 counter: Odd Division = 0 (1 bit(s))
64 : 0; -- clk0 counter: Low Count = 3 (8 bit(s))
65 : 0;
66 : 0;
67 : 0;
68 : 0;
69 : 0;
70 : 1;
71 : 1;
72 : 1; -- clk1 counter: Bypass = 1 (1 bit(s))
73 : 0; -- clk1 counter: High Count = 0 (8 bit(s))
74 : 0;
75 : 0;
76 : 0;
77 : 0;
78 : 0;
79 : 0;
80 : 0;
81 : 0; -- clk1 counter: Odd Division = 0 (1 bit(s))
82 : 0; -- clk1 counter: Low Count = 0 (8 bit(s))
83 : 0;
84 : 0;
85 : 0;
86 : 0;
87 : 0;
88 : 0;
89 : 0;
90 : 1; -- clk2 counter: Bypass = 1 (1 bit(s))
91 : 0; -- clk2 counter: High Count = 0 (8 bit(s))
92 : 0;
93 : 0;
94 : 0;
95 : 0;
96 : 0;
97 : 0;
98 : 0;
99 : 0; -- clk2 counter: Odd Division = 0 (1 bit(s))
100 : 0; -- clk2 counter: Low Count = 0 (8 bit(s))
101 : 0;
102 : 0;
103 : 0;
104 : 0;
105 : 0;
106 : 0;
107 : 0;
108 : 1; -- clk3 counter: Bypass = 1 (1 bit(s))
109 : 0; -- clk3 counter: High Count = 0 (8 bit(s))
110 : 0;
111 : 0;
112 : 0;
113 : 0;
114 : 0;
115 : 0;
116 : 0;
117 : 0; -- clk3 counter: Odd Division = 0 (1 bit(s))
118 : 0; -- clk3 counter: Low Count = 0 (8 bit(s))
119 : 0;
120 : 0;
121 : 0;
122 : 0;
123 : 0;
124 : 0;
125 : 0;
126 : 1; -- clk4 counter: Bypass = 1 (1 bit(s))
127 : 0; -- clk4 counter: High Count = 0 (8 bit(s))
128 : 0;
129 : 0;
130 : 0;
131 : 0;
132 : 0;
133 : 0;
134 : 0;
135 : 0; -- clk4 counter: Odd Division = 0 (1 bit(s))
136 : 0; -- clk4 counter: Low Count = 0 (8 bit(s))
137 : 0;
138 : 0;
139 : 0;
140 : 0;
141 : 0;
142 : 0;
143 : 0;
END;

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="Cyclone III" variation_name="altpll4" megafunction_name="ALTPLL" specifies="all_ports">
<global>
<pin name="areset" direction="input" scope="external" />
<pin name="configupdate" direction="input" scope="external" />
<pin name="inclk0" direction="input" scope="external" source="clock" />
<pin name="scanclk" direction="input" scope="external" source="clock" />
<pin name="scanclkena" direction="input" scope="external" />
<pin name="scandata" direction="input" scope="external" />
<pin name="c0" direction="output" scope="external" source="clock" />
<pin name="locked" direction="output" scope="external" />
<pin name="scandataout" direction="output" scope="external" />
<pin name="scandone" direction="output" scope="external" />
</global>
</pinplan>

View File

@@ -0,0 +1,7 @@
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
set_global_assignment -name IP_TOOL_VERSION "13.1"
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altpll4.tdf"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altpll4.bsf"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altpll4.inc"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altpll4.cmp"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "altpll4.ppf"]

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