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
/ttl_library
- from Rev 13 to Rev 14
- ↔ Reverse comparison
Rev 13 → Rev 14
/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; |
|