Copyright Bengt Oelmann 2 1
Konstruktion av kombinatorisk och sekventiell logik
Innehåll
Fördröjningar i kombinatorisk logik
Kombinatoriska byggblock
Multiplexer / Demultiplexer
Kodare / Avkodare
Aritmetiska funktioner
Fördröjningar i sekventiell logik
Synkrona processer i VHDL
Mealy- och Moore maskiner i VHDL
Byggblock: räknare, skiftregister, RAM/ROM
High-to-Low Propagation delay Low-to-High
Grindfördröjning
Grindfördröjning är den tid det tar för en
förändring på ingången ger en förändring på utgången.
&
A B
Z
B A
Z
t
pLHt
pHLt pLH
t pHL
Fördröjningar i kombinatorisk logik
Bestäm fördröjningen i ett kombinatoriskt nät
C B A D
f
A B C D
f Logisk funktion
Grind Fördröjning tpLH = 0.21 tpHL = 0.19 Inv
tpLH = 0.32 tpHL = 0.35 and2
tpLH = 0.47 tpHL = 0.43 or3
Grindfördröjningar från datablad
t
p-cft
p-dfTa fram den längsta fördröjningen i grindnätet. (t
p-cfeller t
p-df):
T
p-cf= 0.21 + 0.35 + 0.47 ns = 1.03 ns
Fördröjningar för
Samtliga signalvägar:
•t
pHL-af ,t
pLH-af•t
pHL-bf ,t
pLH-bf•t
pHL-cf ,t
pLH-cf•t
pHL-df ,t
pLH-dfMultiplexer/demultiplexer
MUX
A B
Sum Sa
Ss
Sb B0
MUX
DEMUX
B1
A0 A1 Väljer varifrån operanden B
ska tas ifrån Väljer varifrån operanden A ska
tas ifrån
Väljer vart resultatet S ska gå
någonstans
Slå ihop de enskilda bitarna till en bitvektor så att det blir enkelt att hantera i case-satsen Alla ingångar i
sensitivitetslistan
4-till-1 multiplexer i VHDL
architecture rtl of mux4_1 is begin -- rtl
process (I0, I1, I2, I3, S0, S1)
variable sel: bit_vector(1 downto 0);
begin -- process comb sel := S1 & S0;
case sel is
when "00" => Y <= I0;
when "01" => Y <= I1;
when "10" => Y <= I2;
when others => Y <= I3;
end case;
end process;
end rtl;
I0 I1 I2 I3
Y
S0 S1
4-1 Multiplexer
Avkodare – generellt
Binär kod Gray-kod BCD-kod One-hot Egen kod
Binär kod Gray-kod BCD-kod One-hot Egen kod
Avkodare
2-4 binär avkodare i VHDL
architecture rtl of encoder_2_4 is
begin -- rtl
process (I0, I1)
variable I10 : bit_vector(1 downto 0);
begin -- process I10 := I1 & I0;
case I10 is
when "00" => Y3 <= ’0’; Y2 <= ’0’; Y1 <= ’0’; Y0 <= ’1’;
when "01" => Y3 <= ’0’; Y2 <= ’0’; Y1 <= ’1’; Y0 <= ’0’;
when "10" => Y3 <= ’0’; Y2 <= ’1’; Y1 <= ’0’; Y0 <= ’0’;
when "11" => Y3 <= ’1’; Y2 <= ’0’; Y1 <= ’0’; Y0 <= ’0’;
when others =>
Y3 <= ’1’; Y2 <= ’0’; Y1 <= ’0’; Y0 <= ’0’;
end case;
end process;
end rtl;
Y0 Y1 Y2 Y3 I0
2-4 avkodare
I1
Prioritetsavkodare
Ingångarna har inbördes prioritet
När mer än en ingång är aktiv så genereras en kod för den ingång med högst prioritet
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity prioencoder is port (
C3, C2, C1, C0: in std_logic;
A1, A0 : out std_logic);
end prioencoder;
u3 u2 u1 u0
a1 a0
4-2 kodare
c3 c2 c1 c0
p3 p2 p1 p0
prioritering
0 1 1 0
0 1 0 0
1 0
prioencoder
Forts. prioritetsavkodare
architecture rtl of prioencoder is begin -- rtl
process (C3, C2, C1, C0)
variable out_vector : std_logic_vector(1 downto 0);
begin
if C3= ’1’ then
out_vector := ”11";
elsif C2 = ’1’ then out_vector := ”10";
elsif C1 = ’1’ then out_vector := ”01";
elsif C0= ’1’ then out_vector := ”01";
end if;
A1 <= out_vector(1);
A0 <= out_vector(0);
end process;
end rtl;
Adderare
Carry-Ripple Adderare
Enkel
Långsam
a b c
outc
ina
0b
0s
0FA a b
c
outc
ina
1b
1s
1FA a b
c
outc
ina
2b
2s
2FA a b
c
outc
ina
3b
3s
3FA a b
c
outc
ina
N-1b
N-1s
N-1c
NFA
c
inc
outFördröjningen i en n-bitars
adderare är nt
FAFör att genomföra additionen i position
så ser man på bitarna i position
samtidigt för att bestämma carry in.
I en carry-ripple adderare så ser man bara på en bit åt gången och utnyttjar resultatet från additionen i föregående position
Carry-Lookahead-adderare
Snabbare adderare
Snabbar upp beräkningen av carry-bitarna
Idé: Att samtidigt titta på flera positioner av det tal ska ska adderas
Exempel:
0 1 1 0 0 0 1 1 0 1 1 0
+ X
Y S
0 1 1 0
0 0 1 1 0 1 1 0
+ X
Y S
Carry-Lookahead logik
Logik för att beräkna carry signaler
0 1 1 0 0 0 1 1 0 1 1 0
+ X
Y S
a b c
inx
iy
iFA
Carry-Lookahed Logic
x
iy
ix
i-1y
i-1c
iSpeciell logik för att beräkna
carry signalerna
Carry-Lookahead logic
Carry-Lookahead logiken är baserad på två funktioner
Carry generate:
Carry propagate:
Addition i position i sägs generera en carry om den producerar en carry=1 oberoende av x
i-1, y
i-1, … x
0, y
0, c
0Addition i position i sägs propagera en carry om den producerar en carry=1 (c
i+1)då x
i-1, y
i-1, … x
0, y
0, c
0orsakar en carry-in (C
i=1)
i i
i
x y
g
Ett additionssteg genererar en carry (c
i+1):
Om ingångarna (x
i, y
i) antingen genererar en carry (g
i=1) eller att steget propagerar carry-in (p
i=1)
i i
i
x y
p
i i i
i
g p c
c
1
Exempel på propagate och generate funktionerna
0 1 0 1 1 0 0 0 1 1 0 1
X + Y
0 1 1 1 1 1 p
i x
i y
i0 0 0 1 0 0 g
i x
i y
i0 1 1 1 0 0 c
i1 g
i p
i c
iAddition utan carry-propagering
0 1 0 1 1 0 0 0 1 1 0 1
X
Y
Utveckla uttryck för CLA-logik
Utveckla uttrycken rekursivt
Ta fram uttryck för c 1 , c 2 , c 3 och c 4
0 0 0
1
g p c
c
1 1 1
2
g p c
c
)
(
0 0 01
1
p g p c
g
0 0 1 0
1
1
p g p p c
g
2 2 2
3
g p c
c
)
(
1 1 0 1 0 02
2
p g p g p p c
g
0 0 1
2 0
1 2
1 2
2
p g p p g p p p c
g
3 3 3
4
g p c
c
)
(
2 2 1 2 1 0 2 1 0 03
3
p g p g p p g p p p c
g
0
)
0 1
2 3
0 1
2 3
1 2 3
2 3
3
p g p p g p p p g p p p p c
g
c
1, c
2, c
3och c
4är
funktioner av g- och p
ADD ADD
X[11-8] Y[11-8]
ADD ADD
X[7-4] Y[7-4]
ADD ADD
X[3-0] Y[3-0]
12-bitars CLA Adderare
X[11-8] Y[11-8]
P G
P[11-8] G[11-8]
X[7-4] Y[7-4]
P G
P[7-4] G[7-4]
X[3-0] Y[3-0]
P G
P[3-0] G[3-0]
CLA-L
C[11-9]
CLA-L
C[7-5]
CLA-L
C[3-1]
C4 C8
Längsta kombinatoriska
fördröjningen
Ska vara med för att + ska
fungera för vektorer av std_logicSumman ut (S) är de N minst signifikanta bitarna
’0’&X är med för att + ska returnera en summa på N+1 bitar
Carry-out är den mest signifikanta biten
Adderare i VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity add is generic (
N : integer := 32);
port (
X, Y : in std_logic_vector(N-1 downto 0);
S : out std_logic_vector(N-1 downto 0);
Cout : out std_logic);
end add;
architecture rtl of add is begin -- rtl
add_sub : process (X, Y)
variable sum : std_logic_vector(N downto 0);
begin -- process add_sub
sum := (’0’ & X) + (’0’ & Y);
S <= sum(N-1 downto 0);
Cout <= sum(N);
end process add;
end rtl;
Exempel på syntes av adderare
Syntesverktyg
VHDL- beskrivning
Krav på fördröjning
Grind- nätlista
Rapport-fil
Fördröjning [ns]
5 35
CLA adderare
Rippel adderare
Area
200 700
CLA adderare
Rippel adderare
Antal bitar i produkten är summan av antalet bitar i multiplikator och multiplikand
Ska vara med för att * ska
fungera för vektorer av std_logicMultiplikation i VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity multiplikator is generic (
N : integer := 32);
port (
X, Y : in std_logic_vector(N-1 downto 0);
P : out std_logic_vector(2*N-1 downto 0);
end multiplikator;
architecture rtl of multiplikator is begin -- rtl
process (X, Y) begin -- process P <= X*Y;
end process;
end rtl;
Timing i synkrona system
Generell modell för synkront system
Kombinatorisk logik
Q1 D2 Q2
C
t
C-Qt
C-Qt t
C
Q1 D2
t
LOGIKt
SETUPEn klockcykel är summan av alla fördröjningar:
MARGINAL SETUP
LOGIK Q
C
t t t
t
T
Då vi inte har någon timing-marginal så klockas system på maximal klockfrekvens:
f 1 1
t
C-Qoch t
SETUPär
fördröjningar i vippan
Synkrona processer i VHDL
Synkrona processer
Kallas även för klockade processer
Alla aktiveras samtidigt, på t.ex positiv klockflank
Signal- och variabeltilldelningar i processen resulterar i D-vippor
ingångar utgångar
clock
Läser in det nya värdet i vippan
clk’event and clk=’1’
clk
clk’event
Exempel: positivt flanktriggad D-vippa i VHDL
library ieee;
use ieee.std_logic_1164.ALL
entity dff IS
port (d, clk : in std_logic;
q : out std_logic);
end dff;
architecture behavior of dff is begin
process(clk) begin
if (clk’event and clk = ’1’) then q <= d;
else
q <= q;
end if;
end process;
end behavior;
clk
d q
dff
Fler exempel på vippor
architecture dataflow of pos_dff is
q <= d when (clk’event and clk=’1’) else q;
D Q
architecture dataflow of neg_dff is
q <= d when (clk’event and clk=’0’) else q;
D Q
Exempel på D-latch
architecture dataflow of dlatch is q <= d when (clk = ’1’) else q;
D Q
Signal- och variabeltilldelningar leder till införande av register
Exempel: Kod som inför vippor i konstruktionen
Skriv en funktion som tar in ett 8-bitars tal i ett register om det är större än 10.
Om det är mindre än 10 ska registret innehålla 10.
entity load_ge_10 is port (
clk : in std_logic;
d : in std_logic_vector (7 downto 0);
q : out std_logic_vector (7 downto 0));
end load_ge_10;
architecture rtl of load_ge_10 is begin
process (clk) begin
if (clk'event and clk = '1') then if d > 10 then
q <= d;
else
q <= conv_std_logic_vector(10,8);
end if;
end if;
end process;
end rtl;
10
10 d
q 2:1 MUX
clk
0
1
d>10
Initiering av vippor
Initiering av vippor behövs efter systemstart
Två typer av initiering
Synkron reset/preset
Asynkron reset/preset
Exempel: synkron reset
if (clk’event and clk = ’1’) then if reset = ’1’ then q <= ’0’;
else q <= d;
end if;
end if;
D Q
reset
Mealy typ i VHDL
architecture mealy of fsm2 is
type state is (S1, S2, S3, S4);
signal present_state, next_state: state;
begin
process (aIn, present_state) begin CASE present_state IS
when s1 => if (aIn = ’1’)
then yOut <= ’0’; next_state <= s4;
else yOut <= ’1’; next_state <= s3;
end if;
when s2 => yOut <= ’1’; next_state <= s3;
when s3 => yOut <= ’1’; next_state <= s1;
when s4 => if (aIn = ’1’)
then yOut <= ’1’; next_state <= s2;
else yOut <= ’0’; next_state <= s1;
end if;
end case;
end process;
process begin
wail until clk = ’1’;
present_state <= next_state;
end process;
end mealy;
S1 S4
S3 S2
aIn=1/yOut=1
aIn=-/yOut=1 aIn=0/yOut=0
aIn=1/yOut=0
aIn=0/
yOut=1 aIn=-/
yOut=1
aIn yOut
next_state present_state
Moore typ i VHDL
library ieee; use ieee.std_logic_1164.all;
entity fsm1 is
port (aIn, clk: in std_logic; yOut: out std_logic);
end fsm1;
architecture moore of fsm1 is type state is (s1, s2, s3, s4);
signal present_state, next_state: state;
begin
process (aIn, present_state) begin case present_state is
when s1 => yOut <= ’0’;
if (aIn = ’1’) then next_state <= s1 else next_state <= s2;
when s2 => yOut <= ’0’; next_state <= s3;
when s3 => yOut <= ’1’; next_state <= s4;
when s4 => yOut <= ’1’; next_state <= s1;
end case;
end process;
process begin
wait until clk = ’1’;
present_state <= next_state;
end process;
end moore;
S1 S2
S4 S3
yOut=0
aIn=0
yOut=0
yOut=1 yOut=1
aIn=0
aIn=0 aIn=0 aIn=1
Räknare i VHDL
library ieee;
use ieee.std_logic_1164.ALL;
use work.numeric_std.ALL;
entity modulo8 IS
PORT(clk: in std_logic;
cnt: buffer unsigned (7 downto 0));
END count8;
architecture rtl of count8 is begin
process (clk) begin
if rising_edge(clk) then cnt <= cnt +1;
end if end process;
end rtl;
Modulo-8 räknare
Skiftregister i VHDL
entity shift_r is port (
clk, resetn, d_in, shift_en : in std_logic;
shift_out : out std_logic_vector(3 downto 0));
end shift_r;
architecture rtl of shift_r is
signal shift_reg: std_logic_vector(3 downto 0);
begin
process (clk, resetn) begin
if resetn = '0' then
shift_reg <= (others=>'0');
elsif clk'event and clk = '1' then if shift_en='1' then
shift_reg(3 downto 1) <= shift_reg(2 downto 0);
-- shift_reg <= shl(shift_reg, "1");
-- shift_reg <= shift_reg sll 1;
shift_reg(0) <= d_in;
end if;
f;
end process;
shift_out <= shift_reg;
end rtl;
d_in shift_out shift_en
resetn
Alternativa skrivsätt
Minnen i VHDL
Ett RAM eller ROM kan skapas på två sätt
Man använder en array med konstanter
Man instansierar en färdig minnesmodul
Exempel på 48 ROM i VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ROM is
port (
address : in std_logic_vector(1 downto 0);
dout : out std_logic_vector(7 downto 0));
end ROM;
architecture rtl of ROM is
type rom_table is array (0 to 3) of std_logic_vector(7 downto 0);
constant rom_contents : rom_table := rom_table'("00101111", "11010000", "01101010", "11101101");
begin -- rtl
dout <= rom_contents(conv_integer(address));
end rtl;
Definiera färdig RAM module från ett bibliotek
Exempel #1: RAM i VHDL
architecture rtl of rmodul is component RAM4_8
port (
din: in std_logic_vector(7 downto 0), address0, address1, we : in std_logic;
dout : out std_logic_vector(7 downto 0);
end component;
begin -- rtl ram1:
RAM4_8 port map ( din => d, address0 => a0, address1 => a1, we => we, dout => q) end rtl;
din dout
address0 address1
we
RAM4_8 din
a0 a1 we
q
Definiera en minnesmatris
Exempel #2: RAM i VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ram32_16 is port (
addr : in std_logic_vector(4 downto 0);
clk, we_n : in std_logic;
din : in std_logic_vector(15 downto 0);
dout : out std_logic_vector(15 downto 0));
end ram32_16;
architecture rtl of ram32_16 is
type ram_type is array (31 downto 0) of std_logic_vector(15 downto 0);
signal ram_array : ram_type;
begin
process(clk) begin
if clk'event and clk='1' then if we_n='0' then
ram_array(conv_integer(addr)) <= din;
end if;
end if;
din dout
addr we_n
RAM32_16