now gets accepted by Modelsim

This commit is contained in:
Markus Fröschle
2014-09-01 14:24:55 +00:00
parent 029388c6c4
commit 3b0e69127f
7 changed files with 296 additions and 277 deletions

View File

@@ -54,14 +54,14 @@
-- 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.
-- Revision 2K11A 20110620 WF
-- A minor change in the data readback logic (RWn is now taken into consideration).
-- 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.
-- Revision 2K11A 20110620 WF
-- A minor change in the data readback logic (RWn is now taken into consideration).
library ieee;
use ieee.std_logic_1164.all;
@@ -102,7 +102,7 @@ entity WF68901IP_TIMERS is
);
end entity WF68901IP_TIMERS;
architecture BEHAVIOR of WF68901IP_TIMERS is
architecture BEHAVIOR of WF68901IP_TIMERS is
signal XTAL1_S : std_logic;
signal XTAL_STRB : std_logic;
signal TACR : std_logic_vector(4 downto 0); -- Timer A control register.
@@ -115,11 +115,11 @@ signal TDDR : std_logic_vector(7 downto 0); -- Timer D data register.
signal TIMER_A : unsigned (7 downto 0); -- Timer A count register.
signal TIMER_B : unsigned (7 downto 0); -- Timer B count register.
signal TIMER_C : unsigned (7 downto 0); -- Timer C count register.
signal TIMER_D : unsigned (7 downto 0); -- Timer D count register.
signal TIMER_D : unsigned (7 downto 0); -- Timer D count register.
signal TIMER_R_A : std_logic_vector (7 downto 0); -- Timer A readback register.
signal TIMER_R_B : std_logic_vector (7 downto 0); -- Timer B readback register.
signal TIMER_R_C : std_logic_vector (7 downto 0); -- Timer C readback register.
signal TIMER_R_D : std_logic_vector (7 downto 0); -- Timer D readback register.
signal TIMER_R_B : std_logic_vector (7 downto 0); -- Timer B readback register.
signal TIMER_R_C : std_logic_vector (7 downto 0); -- Timer C readback register.
signal TIMER_R_D : std_logic_vector (7 downto 0); -- Timer D readback register.
signal A_CNTSTRB : std_logic;
signal B_CNTSTRB : std_logic;
signal C_CNTSTRB : std_logic;
@@ -129,19 +129,19 @@ signal TBI_I : std_logic;
signal TAI_STRB : std_logic; -- Strobe for the event counter mode.
signal TBI_STRB : std_logic; -- Strobe for the event counter mode.
signal TAO_I : std_logic; -- Timer A output signal.
signal TBO_I : std_logic; -- 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;
signal TBO_I : std_logic; -- 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
@@ -181,47 +181,47 @@ begin
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 RWn = '1' and RS = "01111" then
READ_A := true;
elsif DSn = '0' and RWn = '1' and RS = "10000" then
READ_B := true;
elsif DSn = '0' and RWn = '1' and RS = "10001" then
READ_C := true;
elsif DSn = '0' and RWn = '1' and RS = "10010" then
READ_D := true;
elsif DSn = '1' and READ_A = true then
TIMER_R_A <= std_logic_vector(TIMER_A);
READ_A := false;
elsif DSn = '1' and READ_B = true then
TIMER_R_B <= std_logic_vector(TIMER_B);
READ_B := false;
elsif DSn = '1' and READ_C = true then
TIMER_R_C <= std_logic_vector(TIMER_C);
READ_C := false;
elsif DSn = '1' and READ_D = true then
TIMER_R_D <= std_logic_vector(TIMER_D);
READ_D := false;
end if;
end if;
end process TIMER_READBACK;
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 RWn = '1' and RS = "01111" then
READ_A := true;
elsif DSn = '0' and RWn = '1' and RS = "10000" then
READ_B := true;
elsif DSn = '0' and RWn = '1' and RS = "10001" then
READ_C := true;
elsif DSn = '0' and RWn = '1' and RS = "10010" then
READ_D := true;
elsif DSn = '1' and READ_A = true then
TIMER_R_A <= std_logic_vector(TIMER_A);
READ_A := false;
elsif DSn = '1' and READ_B = true then
TIMER_R_B <= std_logic_vector(TIMER_B);
READ_B := false;
elsif DSn = '1' and READ_C = true then
TIMER_R_C <= std_logic_vector(TIMER_C);
READ_C := false;
elsif DSn = '1' and READ_D = true then
TIMER_R_D <= std_logic_vector(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
@@ -230,17 +230,17 @@ begin
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');
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;
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 <= '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
@@ -293,7 +293,7 @@ begin
variable PRESCALE : unsigned (7 downto 0);
begin
wait until CLK = '1' and CLK' event;
A_CNTSTRB <= '0';
A_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - 1;
elsif XTAL_STRB = '1' then
@@ -306,8 +306,9 @@ begin
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.
when others => PRESCALE := x"00";
end case;
A_CNTSTRB <= '1';
A_CNTSTRB <= '1';
end if;
end process PRESCALE_A;
@@ -316,7 +317,7 @@ begin
variable PRESCALE : unsigned (7 downto 0);
begin
wait until CLK = '1' and CLK' event;
B_CNTSTRB <= '0';
B_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - 1;
elsif XTAL_STRB = '1' then
@@ -329,40 +330,42 @@ begin
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.
when others => PRESCALE := x"00";
end case;
B_CNTSTRB <= '1';
B_CNTSTRB <= '1';
end if;
end process PRESCALE_B;
PRESCALE_C: process
-- The prescalers work even if the RESETn is asserted.
variable PRESCALE : unsigned (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_C: process
-- The prescalers work even if the RESETn is asserted.
variable PRESCALE : unsigned (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.
when others => PRESCALE := x"00";
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 : unsigned (7 downto 0);
begin
wait until CLK = '1' and CLK' event;
D_CNTSTRB <= '0';
D_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - 1;
elsif XTAL_STRB = '1' then
@@ -375,8 +378,9 @@ begin
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
when "000" => PRESCALE := x"00"; -- Timer stopped.
when others => PRESCALE := x"00";
end case;
D_CNTSTRB <= '1';
D_CNTSTRB <= '1';
end if;
end process PRESCALE_D;
@@ -386,16 +390,16 @@ begin
-- 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';
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.
TIMER_A <= unsigned(DATA_IN);
else
case TACR(3 downto 0) is
when x"0" => -- Timer is off.
TAO_I <= '0';
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;
@@ -420,6 +424,7 @@ begin
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
TIMER_A_INT <= '1';
end if;
when others => TAO_I <= '0';
end case;
end if;
end if;
@@ -431,16 +436,16 @@ begin
-- 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';
--
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.
TIMER_B <= unsigned(DATA_IN);
else
case TBCR(3 downto 0) is
when x"0" => -- Timer is off.
TBO_I <= '0';
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;
@@ -465,27 +470,28 @@ begin
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
TIMER_B_INT <= '1';
end if;
when others => TBO_I <= '0';
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';
--
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.
TIMER_C <= unsigned(DATA_IN);
else
else
case TCDCR(5 downto 3) is
when "000" => -- Timer is off.
TCO <= '0';
TCO <= '0';
when others => -- Delay counter mode.
if C_CNTSTRB = '1' and TIMER_C /= x"01" then -- Count.
TIMER_C <= TIMER_C - 1;
@@ -505,16 +511,16 @@ begin
-- 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';
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.
TIMER_D <= unsigned(DATA_IN);
else
case TCDCR(2 downto 0) is
when "000" => -- Timer is off.
TDO <= '0';
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;

View File

@@ -50,8 +50,8 @@
-- 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 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
@@ -184,6 +184,7 @@ begin
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';
when others => LOOPBACK <= '0'; SD_LEVEL <= '0'; SDOUT_EN <= '0';
end case;
end if;
end process SOUT_CONFIG;

View File

@@ -49,10 +49,10 @@
-- 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.
-- 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;
@@ -197,10 +197,11 @@ begin
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 datastd_logics.
when "10" => SHIFT_REG <= "00" & TX_DATA(5 downto 0); -- 6 datastd_logics.
when "01" => SHIFT_REG <= '0' & TX_DATA(6 downto 0); -- 7 datastd_logics.
when "00" => SHIFT_REG <= TX_DATA; -- 8 datastd_logics.
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
when others => SHIFT_REG <= x"00";
end case;
elsif TR_STATE = SHIFTOUT and CLK_STRB = '1' then
SHIFT_REG <= '0' & SHIFT_REG(7 downto 1); -- Shift right.
@@ -223,8 +224,8 @@ begin
-- Transmit data register empty flag.
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
TDRE <= '1';
if RESETn = '0' then
TDRE <= '1';
elsif TE = '0' then
TDRE <= '1';
elsif TR_STATE = START and BREAK = '0' then