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

Subversion Repositories ttl_library

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 13 to Rev 14
    Reverse comparison

Rev 13 → Rev 14

/ttl_library/trunk/TTLPrivatePkg.vhd
0,0 → 1,1495
-----------------------------------------------------------------------
-- 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;

powered by: WebSVN 2.1.0

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