OpenCores
URL https://opencores.org/ocsvn/ttl_library/ttl_library/trunk

Subversion Repositories ttl_library

[/] [ttl_library/] [trunk/] [TTLPrivatePkg.vhd] - Rev 14

Compare with Previous | Blame | View Log

-----------------------------------------------------------------------
-- Bipolar TTL models (VHDL)                                         --
-- David R Brooks                                                    --
-- May, 2016.  Perth, Australia                                      --
-- Compliance: VHDL 2008                                             --
-- NB Simulation only: they are NOT synthesizable.                   --
-- Private package, used internally by the models.                   --
-----------------------------------------------------------------------
 
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_misc.all;
    use ieee.numeric_std.all;
    use ieee.std_logic_textio.all;
 
    use std.textio.all;
 
 
package TTLPrivate is
 
--                          For each gate      For each input
type    TTLInputs  is array(positive range <>, positive range <>) of std_logic;
type    TTLOutputs is array(positive range <>) of std_logic;
 
type    TTLMode    is (Zand, Zor, Zxor, Zbuf);      -- 'Z' so they aren't keywords
type    TTLSingle  is array(1 to 1) of std_logic;
 
subtype TTLword    is unsigned(3 downto 0);
type    TTL2word   is    array(2 downto 1) of TTLword;
 
subtype TTLquad    is std_logic_vector(4 downto 1);
type    TTLmem     is array(15 downto 0) of TTLquad;
subtype TTLaddr    is natural range 15 downto 0;
 
type    TTLmemop   is (Totem, OpenColl, TriState);  -- Memory-block outputs
type    TTLmemory  is array(natural range <>, natural range <>) of std_logic;
type    TTLmemptr  is access TTLmemory;
 
subtype TTLbyte    is integer range 0 to 255;       -- 8-bit integer
type    TTLline    is array(0 to 299) of TTLbyte;
 
-----------------------------------------------------------------------
-- Procedure: Initialise memory-block from a file (Intel format)
-----------------------------------------------------------------------
procedure TTL_mem_init(fname : in String; MA : inout TTLmemptr);
 
-----------------------------------------------------------------------
-- Function: "safe" conversion from unsigned to natural
-- Only "impure" because it references "now"   
-----------------------------------------------------------------------
impure function TTL_to_integer(i : unsigned) return natural;
 
-----------------------------------------------------------------------
-- Function: simulate open-collector outputs    
-----------------------------------------------------------------------
pure function TTL_OC(i : std_logic) return std_logic;
 
-----------------------------------------------------------------------
-- Function: successor fn. for LS490 & similar counters    
-----------------------------------------------------------------------
pure function TTL490(i : TTLword) return TTLword;
 
-----------------------------------------------------------------------
-- Function: "not", safe with 3-state signals
-----------------------------------------------------------------------
pure function notz(i : std_logic) return std_logic;
 
-----------------------------------------------------------------------
-- Function: "not", safe with 3-state signals
-----------------------------------------------------------------------
pure function notz(i : std_logic_vector) return std_logic_vector;
 
-----------------------------------------------------------------------
-- Function: reverse bit order
-----------------------------------------------------------------------
pure function TTL_REV(i : std_logic_vector) return std_logic_vector;
pure function TTL_REV(i : unsigned) return unsigned;
pure function TTL_REV(i : std_logic_vector) return unsigned;
pure function TTL_REV(i : unsigned) return std_logic_vector;
 
-----------------------------------------------------------------------
-- Standard testbench support
-----------------------------------------------------------------------
component TTLBench is
generic(
    StimClk   : std_logic      := '1';  -- Values after the relevant clock edge 
    CheckClk  : std_logic      := '0';
    Period    : time           := 50 ns;
    Finish    : time           := 20 us;
    SevLevel  : severity_level := failure
);
port(
    J    : out unsigned;
    B    : out unsigned;            -- Indefinite range
    CLK  : out std_logic;
    RS   : out std_logic;
    D    : in  std_logic_vector;
    E    : in  std_logic_vector;    -- Indefinite range
    ANS  : out std_logic            -- Result flag: view in waveforms, 'X' if fault
);
end component TTLBench;
 
-----------------------------------------------------------------------
-- Universal simple gate implementation
-----------------------------------------------------------------------
component TTLgate is
generic(
    mode   : TTLMode;       -- Zand, Zor, Zxor, Zbuf
    invert : std_logic;     -- '1' will invert the output
    ohigh  : std_logic;     -- '1' = normal, 'Z' = open collectors
    tPLH   : time := 10 ns;
    tPHL   : time := 10 ns
);
port(
    ins   : in  TTLInputs;
    outs  : out TTLOutputs
);
end component TTLgate;    
 
-----------------------------------------------------------------------
-- Asymmetric propagation delays
-----------------------------------------------------------------------
component TTLdelay is
generic(
    tPLH : time := 10 ns;
    tPHL : time := 10 ns
);
port(
    A : in  std_logic;
    B : out std_logic
);
end component TTLdelay;
 
component TTLdelays is     -- The same, for a vector
generic(
    tPLH : time := 10 ns;
    tPHL : time := 10 ns
);
port(
    A : in  std_logic_vector;
    B : out std_logic_vector
);
end component TTLdelays;
 
-----------------------------------------------------------------------
-- 3-state buffer with delays
-----------------------------------------------------------------------
component TTL3State is    
generic(
    tPLH : time :=  6.0 ns;
    tPHL : time :=  7.5 ns;
    tPZH : time := 19.5 ns;
    tPZL : time := 21.0 ns;
    tPHZ : time :=  8.5 ns;
    tPLZ : time := 14.0 ns
);
port(
    A    : in  std_logic;
    E    : in  std_logic;       -- Enable, active high
    Y    : out std_logic
);
end component TTL3State;
 
-----------------------------------------------------------------------
-- Basic monostable element
-----------------------------------------------------------------------
component TTLmonostable is
generic(
    pwidth        : time    := 100 us;  -- Triggered pulse width
    mintrig       : time    :=  50 ns;  -- Minimum trigger width
    retriggerable : boolean := true
);
port(
    trig  : in  std_logic;
    reset : in  std_logic;
    Q     : out std_logic
);
end component TTLmonostable;
 
-----------------------------------------------------------------------
-- Elementary flipflop
-- A basic JK flipflop with resets. All active high
-----------------------------------------------------------------------
component TTLflipflop is
generic(
    tPLHCP  : time    := 20 ns;     -- Clock rising
    tPHLCP  : time    := 30 ns;     -- Clock falling
    tPLHSC  : time    := 20 ns;     -- S/C rising
    tPHLSC  : time    := 30 ns;     -- S/C falling
    tSETUP  : time    :=  0 ns;     -- Setup time before clock (0 = no test)
    Safeclk : boolean := false      -- Enforce stable inputs before active clock edge
);
port(
    J, K, C, S, R : in  std_logic;
    Q, QB         : out std_logic
);
end component TTLflipflop;
 
-----------------------------------------------------------------------
-- 1-bit & 3-bit counter with adjustable modulus
-- See 7490/92/93 & similar parts
-----------------------------------------------------------------------
component TTLcount4 is
generic(
    tPLH0   : time     := 16 ns;
    tPHL0   : time     := 18 ns;
    tPLH1   : time     := 16 ns;
    tPHL1   : time     := 21 ns;
    tPLH2   : time     := 32 ns;
    tPHL2   : time     := 35 ns;
    tPLH3   : time     := 32 ns;
    tPHL3   : time     := 35 ns;
    modulus : positive := 10        -- Legal values are 10,12,16
);
port(
    ld          : in  std_logic;
    d           : in  std_logic_vector(3 downto 0);
    clka, clkb  : in  std_logic;    -- Falling-edge clock
    rst, set    : in  std_logic;    -- Active-low reset, set
    val         : out std_logic_vector(3 downto 0) 
);
end component TTLcount4;
 
-----------------------------------------------------------------------
-- 4-bit synchronous counter with adjustable modulus
-- See 74160..3 & similar parts
-----------------------------------------------------------------------
component TTLsynccount is
generic(
    asyncreset : boolean := false;
    modulus    : natural := 10;     -- 10, 16 are legal
    tPLHT      : time    := 25 ns;
    tPHLT      : time    := 23 ns;
    tPLHQ      : time    := 24 ns;
    tPHLQ      : time    := 27 ns
);
port(
    PE, CP, CEP, CET, RST : in  std_logic;
    TC                    : out std_logic;
    P                     : in  std_logic_vector(3 downto 0);
    Q                     : out std_logic_vector(3 downto 0)    
);
end component TTLsynccount;
 
-----------------------------------------------------------------------
-- Synchronous bidirectional binary/decade bidirectional counter
-----------------------------------------------------------------------
component TTLbiCount is
generic(
    decade  : boolean := true;
    tPLHQ   : time    := 20 ns;
    tPHLQ   : time    := 20 ns;
    tPLHT   : time    := 30 ns;
    tPHLT   : time    := 30 ns;
    tSU     : time    := 15 ns;
    tSUPE   : time    := 20 ns
);
port(
    PE, CP, CEP, CET, U_D : in std_logic;
    P                     : in  std_logic_vector(3 downto 0);
    Q                     : out std_logic_vector(3 downto 0);
    TC                    : out std_logic    
);
end component TTLbiCount;
 
-----------------------------------------------------------------------
-- Generic RAM block with 3-wire asynchronous control
-- NB Control inputs are active low (as in physical chips)
-----------------------------------------------------------------------
component TTLramblock is
generic(
    fname : String    := "";        -- Name of initialisation file (if any)
    Omode : TTLmemop  := OpenColl;  -- Output mode
    INVT  : std_logic := '0';       -- '1' will invert outputs
    tPLC  : time      := 10 ns;
    tPLA  : time      := 37 ns;
    tSUD  : time      := 25 ns;
    tSUA  : time      := 10 ns
);        
port(     
    RA    : in    std_logic_vector;
    WA    : in    std_logic_vector;
    D     : in    std_logic_vector;
    O     : out   std_logic_vector;
    CE    : in    std_logic;
    RE    : in    std_logic;
    WE    : in    std_logic
);
end component TTLramblock;
 
-----------------------------------------------------------------------
-- Generic addressable latch
-----------------------------------------------------------------------
component TTLadLatch is
generic(
    ABits   : positive := 2;
    tPXDA   : time     := 30 ns;
    tPHLC   : time     := 18 ns
);
port(
    D   : in  std_logic;
    En  : in  std_logic;
    Cn  : in  std_logic;
    A   : in  unsigned(ABits-1 downto 0);
    Z   : out std_logic_vector(2**ABits-1 downto 0)
);
end component TTLadLatch;
 
-----------------------------------------------------------------------
-- Simple blocks used by testbenches
-----------------------------------------------------------------------
component TTLxcvr is
generic(
    INVT : boolean := false;
    tPLH : time    :=  6.0 ns;
    tPHL : time    :=  7.5 ns;
    tPZH : time    := 19.5 ns;
    tPZL : time    := 21.0 ns;
    tPHZ : time    :=  8.5 ns;
    tPLZ : time    := 14.0 ns
);
port(
    A, B : inout  std_logic_vector; -- Ports, indefinite width       
    EN   : in     std_logic;        -- Enable, active low
    A2B  : in     std_logic         -- Direction
);
end component TTLxcvr;
 
component TTL_FF is 
port(
    q   : out std_logic;
    d   : in  std_logic;
    clk : in  std_logic;
    cl  : in  std_logic
);
end component TTL_FF;
 
end package TTLPrivate;
 
--=====================================================================
package body TTLPrivate is
--=====================================================================
 
-----------------------------------------------------------------------
-- Procedure: Initialise memory-block from a file (Intel format)
-----------------------------------------------------------------------
procedure TTL_mem_init(fname : in String; MA : inout TTLmemptr) is
    file     fptr   : text;                                 -- Source file, Intel hex format
    variable lptr   : line;                                 -- Line from file
    variable data   : TTLline;                              -- Ditto, converted to bytes
    variable lsize  : integer;                              -- Line size
    variable stchar : character;                            -- Start char. - ':'
    variable valid  : boolean;                              -- Result of "read"
    variable abyte  : std_logic_vector(7 downto 0);         -- Byte, read by hread
    variable sum    : TTLbyte;                              -- Intel-hex checksum
    variable adbase : natural;                              -- MS 16 bits of load address
    variable addr   : natural;                              -- Current load address
    variable word   : std_logic_vector(MA.all'range(2));    -- 1 word of memory
    variable nwrds  : natural;                              -- No. of words in the line
    variable bptr   : natural;                              -- Byte pointer
    variable linum  : natural := 0;                         -- Source line number (for messages)
 
    constant nbytes : natural := (MA.all'length(2) / 8);    -- No. of bytes per memory word
 
begin
    if fname /= "" then             -- If no file, skip initialisation
        assert MA.all'length(2) mod 8 = 0
            report "Memory <" & fname & "> memory width /= 8*N"
            severity failure;       -- Loads 8-bit bytes
 
        file_open(fptr, fname, READ_MODE);
        adbase := 0;                -- Default address-base
        while not endfile(fptr) loop
            readline(fptr, lptr);
            linum := linum + 1;
            read(lptr, stchar, valid);
            assert valid and stchar = ':'
                report "Memory <" & fname & "> line " & natural'image(linum) 
                                  & ": bad start"
                severity failure;   -- Line should start with ':'
            hread(lptr, abyte);     -- Read 1st byte
            data(0) := to_integer(unsigned(abyte));
            sum     := data(0);
            lsize   := sum + 4;     -- Total record length (excl. length byte)
            for i in 1 to lsize loop
                hread(lptr, abyte);
                data(i) := to_integer(unsigned(abyte));
                sum     := (sum + data(i)) mod 256;
            end loop;
            assert sum = 0          -- Line checksum
                report "Memory <" & fname & "> line " & natural'image(linum) 
                                  & ": bad checksum: " & natural'image(sum)
                severity failure;
 
            case data(3) is         -- Record type...
                when 0      =>          -- Data
                    assert data(0) mod nbytes = 0
                        report "Memory <" & fname & "> line " & natural'image(linum) 
                                          & ": line length not an exact number of words"
                        severity failure;
                    addr := adbase + (data(1) * 2**8) + data(2);
                    assert addr mod nbytes = 0
                        report "Memory <" & fname & "> line " & natural'image(linum) 
                                          & ": line not word aligned"
                        severity failure;
                    addr  := addr / nbytes;             -- Make a word address
                    nwrds := data(0) / nbytes;          -- No. of words, this line
                    bptr  := 4;                         -- 1st data byte
                    for j in 0 to nwrds-1 loop
                        word := (others => '0');    
                        for i in 0 to nbytes-1 loop     -- Assemble 1 memory word
                            word := word(word'left-8 downto 0) 
                                    & std_logic_vector(to_unsigned(data(bptr), 8));
                            bptr := bptr + 1;
                        end loop;
                        for i in word'range loop
                            MA.all(addr,i) := word(i);  -- Load, bit by bit
                        end loop;
                        addr := addr + 1;
                    end loop;
 
                when 1      =>          -- End of file
                    exit;
 
                when 4      =>          -- Extended linear address
                    adbase := (data(4) * 2**24) + (data(5) * 2**16);
 
                when others =>          -- Garbage
                    assert false
                        report "Memory <" & fname & "> line " & natural'image(linum) 
                                          & ": bad record type"
                        severity failure;
            end case;
        end loop;
        file_close(fptr);
    end if;
end TTL_mem_init;
 
-----------------------------------------------------------------------
-- Function: "safe" conversion from unsigned to natural   
-- Only "impure" because it references "now"   
-----------------------------------------------------------------------
impure function TTL_to_integer(i : unsigned) return natural is
begin
    if now < 1 ns then          -- Suppress bad values at start-up
        return 0;
    else
        return to_integer(i);
    end if;
end function TTL_to_integer;
 
-----------------------------------------------------------------------
-- Function: simulate open-collector outputs    
-----------------------------------------------------------------------
pure function TTL_OC(i : std_logic) return std_logic is
begin
    if i = '1' then return 'Z';
               else return i;
    end if;
end function TTL_OC;  
 
-----------------------------------------------------------------------
-- Function: successor fn. for LS490 & similar counters    
-----------------------------------------------------------------------
pure function TTL490(i : TTLword) return TTLword is
begin
    case to_integer(i) is
        when 11 | 13 | 15 => return i - 9;
        when others       => return i + 1;
    end case;
end function TTL490;
 
-----------------------------------------------------------------------
-- Function: "not", safe with 3-state signals
-----------------------------------------------------------------------
pure function notz(i : std_logic) return std_logic is
begin
    case i is
        when 'Z'    => return 'Z';  -- IEEE "not" would return 'X'
        when others => return not i;
    end case;
end function notz;
 
-----------------------------------------------------------------------
-- Function: "not", safe with 3-state signals
-----------------------------------------------------------------------
pure function notz(i : std_logic_vector) return std_logic_vector is
    variable k : std_logic_vector(i'range);
begin
    for j in i'range loop
        case i(j) is
            when 'Z'    => k(j) := 'Z';  -- IEEE "not" would return 'X'
            when others => k(j) := not i(j);
        end case;
    end loop;
    return k;
end function notz;
 
-----------------------------------------------------------------------
-- Function: reverse bit order
-----------------------------------------------------------------------
pure function TTL_REV(i : std_logic_vector) return std_logic_vector is
    variable result: std_logic_vector(i'RANGE);
    alias aa: std_logic_vector(i'REVERSE_RANGE) is i;
begin
    for i in aa'RANGE loop
        result(i) := aa(i);
    end loop;
    return result;
end function TTL_REV;
 
pure function TTL_REV(i : unsigned) return unsigned is
    variable result: unsigned(i'RANGE);
    alias aa: unsigned(i'REVERSE_RANGE) is i;
begin
    for i in aa'RANGE loop
        result(i) := aa(i);
    end loop;
    return result;
end function TTL_REV;
 
pure function TTL_REV(i : std_logic_vector) return unsigned is
    variable result: unsigned(i'RANGE);
    alias aa: std_logic_vector(i'REVERSE_RANGE) is i;
begin
    for i in aa'RANGE loop
        result(i) := aa(i);
    end loop;
    return result;
end function TTL_REV;
 
pure function TTL_REV(i : unsigned) return std_logic_vector is
    variable result: std_logic_vector(i'RANGE);
    alias aa: unsigned(i'REVERSE_RANGE) is i;
begin
    for i in aa'RANGE loop
        result(i) := aa(i);
    end loop;
    return result;
end function TTL_REV;
 
 
 
--=====================================================================
end package body TTLPrivate;
--=====================================================================
 
-----------------------------------------------------------------------
-- Standard testbench support
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use work.TTLPrivate.all;
 
entity TTLBench is
generic(
    StimClk   : std_logic      := '1';  -- Values after the relevant clock edge 
    CheckClk  : std_logic      := '0';
    Period    : time           := 50 ns;
    Finish    : time           := 20 us;
    SevLevel  : severity_level := failure
);
port(
    J    : out unsigned;
    B    : out unsigned;            -- Indefinite range
    CLK  : out std_logic;
    RS   : out std_logic;
    D    : in  std_logic_vector;
    E    : in  std_logic_vector;    -- Indefinite range
    ANS  : out std_logic            -- Result flag: view in waveforms, 'X' if fault
);
end entity;
 
architecture Test of TTLBench is
    signal JI, BI : unsigned(J'length-1 downto 0) := (others => '0');
    signal CLKI   : std_logic := not StimClk;
    signal RSI    : std_logic;
 
begin
    J   <= JI;
    B   <= BI;
    CLK <= CLKI;
    RS  <= RSI;
 
    -----------------------------------------------------------------------
    -- Test-Pattern Generators                        
    -----------------------------------------------------------------------
    process is                              -- Generate clock, until we stop
    begin
        if now > Finish then
            wait;
        else
            wait for Period / 2;
            CLKI <= not CLKI;
        end if;
    end process;
 
    -- To ensure things really do reset, ensure an active transition of RS
    -- after the simulation initialises.
    RSI <= '1', '0' after 5 ns, '1' after Period * 1.25;            -- Active-low reset
 
    process(CLKI) is
        variable MLS : unsigned(32 downto 0) := (others => '1');
    begin
        if CLKI'event and CLKI = StimClk then
            MLS := MLS(31 downto 0) & (MLS(32) xor MLS(12));        -- Max-length sequence
            JI  <= MLS(JI'range);
            BI <= BI + 1;                                           -- Binary counter
        end if;
    end process;
 
    -----------------------------------------------------------------------
    -- Validate the results
    -- Test patterns change on CLK active, check on CLK inactive
    -----------------------------------------------------------------------
    process(CLKI) is
    begin
        if CLKI'event and CLKI = CheckClk then
            if D /= E then          -- Verify failed
                ANS <= 'X';
                assert RSI = '0'    -- Don't check during initialisation
                    report "Verify failed: Exp """ & to_string(D) & """" &
                                         " Rcv """ & to_string(E) & """" &
                                            " at " & time'image(now)
                    severity SevLevel;
            else
                ANS <= '0';
            end if;    
        end if;
    end process;
 
end architecture Test;
 
-----------------------------------------------------------------------
-- Universal simple gate implementation
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_misc.all;
    use work.TTLPrivate.all;
 
entity TTLgate is
generic(
    mode   : TTLMode;
    invert : std_logic;     -- '1' will invert the output
    ohigh  : std_logic;     -- '1' = normal, 'Z' = open collectors
    tPLH   : time := 10 ns;
    tPHL   : time := 10 ns
);
port(
    ins   : in  TTLInputs;
    outs  : out TTLOutputs
);
end entity TTLgate; 
 
architecture BEHAV of TTLgate is
    signal Y, Z : TTLOutputs(outs'range);
begin
    process(ins) is
        variable X : std_logic_vector(ins'range(2));
    begin
        for i in outs'range loop
            for j in ins'range(2) loop
                X(j) := ins(i,j);   -- Extract column into a slv
            end loop;
 
            case mode is            -- The gate function
                when Zand   => Y(i) <= and_reduce(X);
                when Zor    => Y(i) <= or_reduce(X);
                when Zxor   => Y(i) <= xor_reduce(X);
                when others => Y(i) <= X(1);  -- Just a 1-input buffer
            end case;
        end loop;
    end process;
    G1: for i in outs'range generate
    begin
                                    -- Output inverted & open collector, as reqd.
        Z(i) <= '0' when Y(i) = invert else ohigh;
 
        OP: TTLdelay                -- Apply gate delays
        generic map(
            tPLH => tPLH,
            tPHL => tPHL
        )
        port map(
            A => Z(i),
            B => outs(i)
        );
    end generate;
end architecture BEHAV;  
 
-----------------------------------------------------------------------
-- Apply asymmetric propagation delays
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
 
entity TTLdelay is
generic(
    tPLH : time := 10 ns;
    tPHL : time := 10 ns
);
port(
    A : in  std_logic;
    B : out std_logic := 'U'
);
end entity TTLdelay;
 
architecture BEHAV of TTLdelay is
begin
    process(A) is
    begin
        if    rising_edge(A) then
            B <= 'X', A after tPLH;     -- Rising delay
        elsif falling_edge(A) then
            B <= 'X', A after tPHL;     -- Falling delay
        else
            B <= A;                     -- 'Z', or bad value
        end if;
    end process;
end architecture BEHAV;
 
library ieee;
    use ieee.std_logic_1164.all;
    use work.TTLPrivate.all;
 
entity TTLdelays is     -- The same, for a vector
generic(
    tPLH : time := 10 ns;
    tPHL : time := 10 ns
);
port(
    A : in  std_logic_vector;
    B : out std_logic_vector
);
end entity TTLdelays;
 
architecture BEHAV of TTLdelays is
begin
    G: for i in A'range generate
        DO: TTLdelay
        generic map(
            tPLH => tPLH,
            tPHL => tPHL
        )
        port map(
            A => A(i),
            B => B(i)
        );
    end generate;
end architecture BEHAV;
 
-----------------------------------------------------------------------
-- 3-state buffer with delays
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
 
entity TTL3State is    
generic(
    tPLH : time :=  6.0 ns;
    tPHL : time :=  7.5 ns;
    tPZH : time := 19.5 ns;
    tPZL : time := 21.0 ns;
    tPHZ : time :=  8.5 ns;
    tPLZ : time := 14.0 ns
);
port(
    A    : in  std_logic;
    E    : in  std_logic;       -- Enable, active high
    Y    : out std_logic
);
end entity TTL3State;
 
architecture BEHAV of TTL3State is
begin
    process(A, E) is
        variable tPD, tPZX, tPXZ : time;
    begin
        if A = '1' then
            tPD  := tPLH;
            tPZX := tPZH;
            tPXZ := tPHZ;
        else
            tPD  := tPHL;
            tPZX := tPZL;
            tPXZ := tPLZ;
        end if;
 
        if    rising_edge(E)      then  -- Enable
            Y <= A after tPZX;
        elsif falling_edge(E)     then  -- Disable
            Y <= 'Z' after tPXZ;
        elsif A'event and E = '1' then  -- Data change (& enabled)
            Y <= A after tPD;
        else
            Y <= 'Z';                   -- Correct? (or null)
        end if;
    end process;
end architecture BEHAV;
 
-----------------------------------------------------------------------
-- 3-state transceiver with delays
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
 
entity TTLxcvr is    
generic(
    INVT : boolean := false;
    tPLH : time    :=  6.0 ns;
    tPHL : time    :=  7.5 ns;
    tPZH : time    := 19.5 ns;
    tPZL : time    := 21.0 ns;
    tPHZ : time    :=  8.5 ns;
    tPLZ : time    := 14.0 ns
);
port(
    A, B : inout  std_logic_vector; -- Ports, indefinite width       
    EN   : in     std_logic;        -- Enable, active low
    A2B  : in     std_logic         -- Direction
);
end entity TTLxcvr;
 
architecture BEHAV of TTLxcvr is
begin
    assert A'left = B'left and A'right = B'right report "Range mismatch" severity failure;
 
    process(all) is
        variable STATE   : std_logic_vector(3 downto 0);
        variable OUTPUTS : std_logic_vector(1 downto 0);
    begin
        for i in A'range loop
            STATE := (EN, A2B, A(i), B(i));
            if INVT then
                STATE := STATE xor "0011";
            end if;
 
            case STATE is
                when "X---" => OUTPUTS := "XX";     -- Bad controls
                when "-X--" => OUTPUTS := "XX";
                when "00-0" => OUTPUTS := "0Z";     -- Drive B -> A
                when "00-1" => OUTPUTS := "1Z";
                when "00-X" => OUTPUTS := "XZ";
                when "010-" => OUTPUTS := "Z0";     -- Drive A -> B
                when "011-" => OUTPUTS := "Z1";
                when "01X-" => OUTPUTS := "ZX";
                when others => OUTPUTS := "ZZ";     -- Disable
            end case;
            A(i) <= OUTPUTS(1);
            B(i) <= OUTPUTS(0);
        end loop;
    end process;
 
end architecture BEHAV;
 
-----------------------------------------------------------------------
-- Basic monostable element
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
 
entity TTLmonostable is
generic(
    pwidth        : time    := 100 us;  -- Triggered pulse width
    mintrig       : time    :=  50 ns;  -- Minimum trigger width
    retriggerable : boolean := true
);
port(
    trig  : in  std_logic;
    reset : in  std_logic;
    Q     : out std_logic
);
end entity TTLmonostable;
 
architecture BEHAV of TTLmonostable is
  constant resolution : positive := pwidth / mintrig;
 
  signal clk : std_logic := '0';
  signal ctr : natural   :=  0;
begin
    osc: process is                     -- "Clock oscillator"
    begin
        if ctr /= 0 then
            wait for mintrig / 2;
            clk <= not clk;             -- <resolution> clocks = width
        else
            wait on ctr;
        end if;
    end process;
 
    tim: process(all) is                -- The timer proper
    begin
        if reset = '1' then
            ctr <= 0;
        elsif rising_edge(trig) and (ctr = 0 or retriggerable) then
            ctr <= 1;                   -- Start (or restart) a cycle
        elsif rising_edge(clk) and ctr > 0 then
            if ctr = resolution then
                ctr <= 0;               -- Cycle completed
            else
                ctr <= ctr + 1;         -- Advance count
            end if;
        end if;
    end process;
 
    Q <= '0' when ctr = 0 else '1';     -- '1' while time runs
 
end architecture BEHAV;
 
-----------------------------------------------------------------------
-- Elementary TTLflipflop
-- A basic JK TTLflipflop with resets. All active high
--
-- NB This package models gate delay variation by setting outputs to
--    'X' during the uncertain period. If such an output is used as a
--    clock, the active edge will transition from 'X' to the active
--    level. This will NOT trigger the rising/falling_edge() functions,
--    so this model uses the (CLK'event and CLK='1') paradigm.
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
 
entity TTLflipflop is
generic(
    tPLHCP  : time    := 20 ns;     -- Clock rising
    tPHLCP  : time    := 30 ns;     -- Clock falling
    tPLHSC  : time    := 20 ns;     -- S/C rising
    tPHLSC  : time    := 30 ns;     -- S/C falling
    tSETUP  : time    :=  0 ns;     -- Setup time before clock (0 = no test)
    Safeclk : boolean := false      -- Enforce stable inputs over inactive clock edge
);
port(
    J, K, C, S, R : in  std_logic;
    Q, QB         : out std_logic
);
end entity TTLflipflop;
 
architecture BEHAV of TTLflipflop is
    signal qi : std_logic := 'X';
begin
    VV: process(J, K) is            -- Verify data is stable before active clock edge
    begin
        if J'event or K'event then                  -- Either is unstable
            if Safeclk and ((R or S) = '0') then    -- Test requested, & not defeated by reset/set
                assert C = '1' report "Data unstable" severity error;
            end if;
        end if;
    end process;
 
    FF: process(C, S, R) is         -- The flipflop proper
        variable ip : std_logic_vector(1 downto 0);
        variable qt : std_logic;
        variable dl : time;
    begin
        if    R = '1' then
            if qi /= '0' then               -- Only apply delays if state is changed
                qi <= 'X', '0' after tPHLSC;
            end if;
        elsif S = '1' then
            if qi /= '1' then
                qi <= 'X', '1' after tPLHSC;
            end if;
        elsif C'event and C = '1' then      -- Don't use "rising_edge": unsafe with 'X' values
            if tSETUP > 0 ns then
                assert J'stable(tSETUP) and K'stable(tSETUP)
                    report "Setup time violation"
                    severity warning;
            end if;
            ip := J & K;
            case ip is
                when "00"   => 
                    qt := qi;           -- Hold
                    dl := 0 ns;
                when "01"   => 
                    qt := '0';          -- Reset
                    dl := tPHLCP;
                when "10"   => 
                    qt := '1';          -- Set
                    dl := tPLHCP;
                when "11"   =>         
                    if    qi = '0' then -- Toggle
                        qt := '1';
                        dl := tPLHCP;
                    elsif qi = '1' then
                        qt := '0';
                        dl := tPHLCP;
                    end if;
                when others => 
                    qt := 'X';          -- Illegal
                    dl := tPLHCP;
            end case;
            if qt /= qi then            -- Only apply delays if state is changed
                qi <= 'X', qt after dl;
            end if;
        end if;
    end process;
 
    Q  <= qi;
    QB <= not qi;
end architecture BEHAV;
 
---------------------------------------------------------------
-- 1-bit & 3-bit counter with adjustable modulus
--         See 7490/92/93 & similar parts
-- NB Don't use "falling_edge" for clocks: the drivers model delays,
--    & set 'X' during the delay period. So a clock goes '1' - 'X' - '0'
--    This must read as a valid edge.
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use work.TTLPrivate.all;
 
entity TTLcount4 is
generic(
    tPLH0   : time     := 16 ns;
    tPHL0   : time     := 18 ns;
    tPLH1   : time     := 16 ns;
    tPHL1   : time     := 21 ns;
    tPLH2   : time     := 32 ns;
    tPHL2   : time     := 35 ns;
    tPLH3   : time     := 32 ns;
    tPHL3   : time     := 35 ns;
    modulus : positive := 10        -- Legal values are 10,12,16
);
port(
    ld          : in  std_logic;
    d           : in  std_logic_vector(3 downto 0);
    clka, clkb  : in  std_logic;    -- Falling-edge clock
    rst, set    : in  std_logic;    -- Active-low reset / set
    val         : out std_logic_vector(3 downto 0) 
);
end entity TTLcount4;
 
architecture BEHAV of TTLcount4 is
    type tval is array(0 to 7) of natural;      -- Next counter values
    -- Current count value: 0 1 2 3 4 5 6 7
    constant D5 : tval :=  (1,2,3,4,0,1,2,3);   -- For the 3 moduli
    constant D6 : tval :=  (1,2,4,0,5,6,0,0);   -- A "bi-ternary" count
    constant D8 : tval :=  (1,2,3,4,5,6,7,0);
 
    signal q   : natural := 100;  -- Use 100 as "undefined"
    signal q0  : std_logic;
    signal q31 : std_logic_vector(3 downto 1);
 
begin
    process(ld, clka, rst, set) is
    begin
        if    rst = '0' then
            q0 <= '0';
        elsif ld  = '0' then
            q0 <= d(0);
        elsif set = '0' then
            q0 <= '1';
        elsif clka'event and clka = '0' then
            q0 <= not q0;
        end if;
    end process;
 
    process(ld, clkb, rst, set) is
    begin
        if    rst = '0' then
            q <= 0;
        elsif ld  = '0' then
            q <= to_integer(unsigned(d(3 downto 1)));
        elsif set = '0' then
            case modulus is
                when 10     => q <= 4;
                when 16     => q <= 7;
                when others => assert false report "Illegal modulus" severity failure;
            end case;
        elsif clkb'event and clkb = '0' and q < 8 then
            case modulus is
                when 10     => q <= D5(q);
                when 12     => q <= D6(q);
                when 16     => q <= D8(q);
                when others => assert false report "Illegal modulus" severity failure;
            end case;
        end if;
    end process;
 
    process(all) is
    begin
        if q < 8 then
            q31 <= std_logic_vector(to_unsigned(q, q31'length));
        else
            q31 <= (others => 'X');
        end if;
--        val <= q31 & q0;
    end process;
 
 
    D0: TTLdelay
    generic map(
        tPLH => tPLH0,
        tPHL => tPHL0
    )
    port map(
        A => q0,
        B => val(0)
    );
 
    D1: TTLdelay
    generic map(
        tPLH => tPLH1,
        tPHL => tPHL1
    )
    port map(
        A => q31(1),
        B => val(1)
    );
 
    D2: TTLdelay
    generic map(
        tPLH => tPLH2,
        tPHL => tPHL2
    )
    port map(
        A => q31(2),
        B => val(2)
    );
 
    D3: TTLdelay
    generic map(
        tPLH => tPLH3,
        tPHL => tPHL3
    )
    port map(
        A => q31(3),
        B => val(3)
    );
end architecture BEHAV;
 
-----------------------------------------------------------------------
-- 4-bit synchronous counter with adjustable modulus
-- See 74160..3 & similar parts
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use work.TTLPrivate.all;
 
entity TTLsynccount is
generic(
    asyncreset : boolean := false;
    modulus    : natural := 10;     -- 10, 16 are legal
    tPLHT      : time    := 25 ns;
    tPHLT      : time    := 23 ns;
    tPLHQ      : time    := 24 ns;
    tPHLQ      : time    := 27 ns
);
port(
    PE, CP, CEP, CET, RST : in  std_logic;
    TC                    : out std_logic;
    P                     : in  std_logic_vector(3 downto 0);
    Q                     : out std_logic_vector(3 downto 0)   
);
end entity TTLsynccount;
 
architecture BEHAV of TTLsynccount is
    signal Z   : std_logic_vector(3 downto 0);
    signal TCI : std_logic;
begin
    process(RST, CP, CET) is
        variable N : unsigned(3 downto 0);
    begin
        if asyncreset and (RST = '0') then
            N := (others => '0');
        elsif CP'event and CP = '1' then
            if RST = '0' then
                N := (others => '0');
            elsif PE = '0' then
                N := unsigned(P);
            elsif (CEP and CET) = '1' then
                if modulus = 16 then        -- Simple binary count
                    N := N + 1;
                else                        -- Decade count, cover illegal cases
                    case N is
                        when "1001"          => N := "0000";
                        when "1011" | "1101" => N := "0100";
                        when "1111"          => N := "1000";
                        when others          => N := N + 1;
                    end case;
                end if;
            end if;
        end if;
        Z <= std_logic_vector(N);           -- Export results
        if TTL_to_integer(N) = modulus-1 then
            TCI <= CET;
        else
            TCI <= '0';
        end if;
    end process;
 
    OQ: TTLdelays 
    generic map(
        tPLH => tPLHQ,
        tPHL => tPHLQ
    )
    port map(
        A => Z,
        B => Q
    );
 
    OT: TTLdelay 
    generic map(
        tPLH => tPLHT,
        tPHL => tPHLT
    )
    port map(
        A => TCI,
        B => TC
    );
end architecture BEHAV;
 
-----------------------------------------------------------------------
-- Synchronous bidirectional binary/decade bidirectional counter
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_misc.all;
    use ieee.numeric_std.all;
 
    use work.LSTTL.all;
    use work.TTLPrivate.all;
 
entity TTLbiCount is
generic(
    decade  : boolean := true;
    tPLHQ   : time    := 20 ns;
    tPHLQ   : time    := 20 ns;
    tPLHT   : time    := 30 ns;
    tPHLT   : time    := 30 ns;
    tSU     : time    := 15 ns;
    tSUPE   : time    := 20 ns
);
port(
    PE, CP, CEP, CET, U_D : in std_logic;
    P                     : in  std_logic_vector(3 downto 0);
    Q                     : out std_logic_vector(3 downto 0);
    TC                    : out std_logic    
);
end entity TTLbiCount;
 
architecture BEHAV of TTLbiCount is
    signal R       : unsigned(3 downto 0);
    signal CEN     : std_logic;
    signal X, Y, Z : std_logic;
    signal W       : std_logic_vector(3 downto 0);
 
begin
    X <= R(0) and R(3) and not CET when decade else and_reduce(std_logic_vector(R)) and not CET;
    Y <= nor_reduce(std_logic_vector(R)) and not CET;
    Z <= not X when U_D = '1' else not Y;
    W <= std_logic_vector(R);
 
    process(CP) is
        variable SW : std_logic_vector(3 downto 0);
    begin
        if CP'event and CP = '1' then       -- Everything is synchronous
            assert PE'stable(tSUPE) report "PE setup violation"  severity failure;
            assert CEP'stable(tSU)  report "CEP setup violation" severity failure;
            assert CET'stable(tSU)  report "CET setup violation" severity failure;
            SW := (PE, CEP, CET, U_D);
            case SW is
                when "0000" | "0001" | "0010" | "0011" |
                     "0100" | "0101" | "0110" | "0111"=>              -- Load
                    assert P'stable(tSU) report "P setup violation" severity failure;
                    R <= unsigned(P);
                when "1001" =>              -- Count up
                    if decade then
                        case R is
                            when "1001" => R <= "0000";
                            when "1011" => R <= "0100";
                            when "1101" => R <= "0100";
                            when others => R <= R + 1;
                        end case;
                    else
                        R <= R + 1;
                    end if;
                when "1000" =>              -- Count down
                    if decade then
                        case R is
                            when "0000" => R <= "1001";
                            when "1010" => R <= "0001";
                            when "1100" => R <= "0011";
                            when "1110" => R <= "0101";
                            when others => R <= R - 1;
                        end case;
                    else
                        R <= R - 1;
                    end if;
                when others =>              -- No change
                    null;
            end case;
        end if;
    end process;
 
    OQ: TTLdelays 
    generic map(
        tPLH => tPLHQ,
        tPHL => tPHLQ
    )
    port map(
        A => W,
        B => Q
    );
 
    OT: TTLdelay 
    generic map(
        tPLH => tPLHT,
        tPHL => tPHLT
    )
    port map(
        A => Z,
        B => TC
    );
end architecture BEHAV;
 
-----------------------------------------------------------------------
-- Generic RAM block with 3-wire asynchronous control
-- NB Control inputs are active low (as in physical chips)
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_misc.all;
    use ieee.numeric_std.all;
 
    use work.LSTTL.all;
    use work.TTLPrivate.all;
 
entity TTLramblock is
generic(
    fname : String    := "";        -- Name of initialisation file (if any)
    Omode : TTLmemop  := OpenColl;  -- Output mode
    INVT  : std_logic := '0';       -- '1' will invert outputs
    tPLC  : time      := 10 ns;
    tPLA  : time      := 37 ns;
    tSUD  : time      := 25 ns;
    tSUA  : time      := 10 ns
);        
port(     
    RA    : in    std_logic_vector;
    WA    : in    std_logic_vector;
    D     : in    std_logic_vector;
    O     : out   std_logic_vector;
    CE    : in    std_logic;
    RE    : in    std_logic;
    WE    : in    std_logic
);
end entity TTLramblock;
 
architecture BEHAV of TTLramblock is
    subtype  T_word  is std_logic_vector(O'range);
    constant C_size  :  positive := 2**RA'length;
 
    signal   RP, WP     : natural;
    signal   CI, RI, WI : std_logic;
 
begin
    assert RA'left = WA'left and RA'right = WA'right report "Address range mismatch" severity failure;
    assert  D'left =  O'left and  D'right =  O'right report "Data range mismatch"    severity failure;
 
    VR: process(all) is
    begin
        if WA'event or D'event then
            assert WE = '1' report "Address or data changed during write" severity failure;
        end if;
        if WE'event and WE = '0' then
            assert WA'stable(tSUA) report "Address setup violation" severity failure;
            assert D'stable(tSUD)  report "Data setup violation" severity failure;
        end if;
    end process;
 
    RP <= to_integer(unsigned(RA)) after tPLA;
    WP <= to_integer(unsigned(WA)) after tPLA;
    CI <= CE after tPLC;
    RI <= RE after tPLC;
    WI <= WE after tPLC;
 
    RM: process(all) is
        variable QQ : std_logic;
        variable MA : TTLmemptr := null;
    begin
        if MA = null then               -- Create the memory array, once only
            MA := new TTLmemory(C_size-1 downto 0, O'range);
            TTL_mem_init(fname, MA);    -- Initialise from file, if given
        end if;
 
        for i in O'range loop           -- Can't use "others" with unconstrained array
            O(i) <= 'Z';                -- Deselected, or not reading
        end loop;
 
        if CI = '0' then
            if WI = '0' then
                for i in O'range loop
                    MA.all(WP,i) := D(i);
                end loop;
            end if;    
 
            if RI = '0' then
                for i in O'range loop
                    QQ := MA.all(RP,i) xor INVT;
                    case Omode is
                        when Totem    => O(i) <= QQ;
                        when OpenColl => O(i) <= TTL_OC(QQ);
                        when TriState => O(i) <= QQ;
                        when others => null;
                    end case;
                end loop;
 
            end if;
        end if;
    end process;
end architecture BEHAV;
 
-----------------------------------------------------------------------
-- Generic addressable latch
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_misc.all;
    use ieee.numeric_std.all;
 
    use work.LSTTL.all;
    use work.TTLPrivate.all;
 
entity TTLadLatch is
generic(
    ABits   : positive := 2;        -- No. of address bits (so no. of latches)
    tPXDA   : time     := 30 ns;
    tPHLC   : time     := 18 ns
);
port(
    D   : in  std_logic;
    En  : in  std_logic;
    Cn  : in  std_logic;
    A   : in  unsigned(ABits-1 downto 0);
    Z   : out std_logic_vector(2**ABits-1 downto 0)
);
end entity TTLadLatch;
 
architecture BEHAV of TTLadLatch is
--    signal latch : std_logic_vector(2**ABits-1 downto 0);
    signal addr  : natural;
begin
--    Z    <= latch;                  -- Export the latch
--    addr <= to_integer(A);
 
    process(all)
    begin
        if falling_edge(Cn) then 
            Z <= (others => '0') after tPHLC;
        elsif Cn = '1' then
            if En = '0' then
                Z(to_integer(A)) <= D after tPXDA;
            end if;
        end if;
    end process;
end architecture BEHAV;
 
-----------------------------------------------------------------------
-- Simple blocks used by testbenches
-----------------------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_misc.all;
    use ieee.numeric_std.all;
 
    use work.LSTTL.all;
    use work.TTLPrivate.all;
 
entity TTL_FF is 
port(
    q   : out std_logic;
    d   : in  std_logic;
    clk : in  std_logic;
    cl  : in  std_logic
);
end entity TTL_FF;
 
architecture BEHAV of TTL_FF is
begin
    process(clk, cl) is
    begin
        if cl = '0' then
            q <= '0';
        elsif rising_edge(clk) then
            q <= d;
        end if;
    end process;
end architecture BEHAV;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.