Konstruktion av kombinatorisk och sekventiell logik ETAC48 Föreläsning 3 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 Copyright Bengt Oelmann 2002 BO
Copyright Bengt Oelmann 2002 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. tpLH Low-to-High Propagation delay & A B Z High-to-Low B A Z tpLH tpHL tpHL Mäts från punkterna då signalerna nått 50% av sitt slutvärde Copyright Bengt Oelmann 2002
Fördröjningar i kombinatorisk logik Bestäm fördröjningen i ett kombinatoriskt nät tp-cf A B C D f Logisk funktion C B A D f tp-df 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 Fördröjningar för Samtliga signalvägar: tpHL-af , tpLH-af tpHL-bf , tpLH-bf tpHL-cf , tpLH-cf tpHL-df , tpLH-df Ta fram den längsta fördröjningen i grindnätet. (tp-cf eller tp-df): Tp-cf = 0.21 + 0.35 + 0.47 ns = 1.03 ns Copyright Bengt Oelmann 2002
Multiplexer/demultiplexer Väljer varifrån operanden A ska tas ifrån Väljer varifrån operanden B ska tas ifrån MUX A B Sum Sa Ss Sb B0 DEMUX B1 A0 A1 S0 S1 Väljer vart resultatet S ska gå någonstans Copyright Bengt Oelmann 2002
4-till-1 multiplexer i VHDL Y S0 S1 4-1 Multiplexer 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; Alla ingångar i sensitivitetslistan Slå ihop de enskilda bitarna till en bitvektor så att det blir enkelt att hantera i case-satsen Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 Avkodare – generellt Avkodare Binär kod Gray-kod BCD-kod One-hot Egen kod Binär kod Gray-kod BCD-kod One-hot Egen kod Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 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 Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 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 u3 u2 u1 u0 a1 a0 4-2 kodare c3 c2 c1 c0 p3 p2 p1 p0 prioritering 1 prioencoder 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; Copyright Bengt Oelmann 2002
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; Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 Adderare Carry-Ripple Adderare Enkel Långsam a b cout cin a0 b0 s0 FA a1 b1 s1 a2 b2 s2 a3 b3 s3 aN-1 bN-1 sN-1 cN Fördröjningen i en n-bitars adderare är ntFA Copyright Bengt Oelmann 2002
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 + X Y S 0 1 1 0 0 0 1 1 + X Y S 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 För att genomföra additionen i position så ser man på bitarna i position samtidigt för att bestämma carry in. Copyright Bengt Oelmann 2002
Carry-Lookahead logik Logik för att beräkna carry signaler 0 1 1 0 0 0 1 1 + X Y S a b cin xi yi Si§ FA Carry-Lookahed Logic xi-1 yi-1 ci Speciell logik för att beräkna carry signalerna Copyright Bengt Oelmann 2002
Carry-Lookahead logic Carry-Lookahead logiken är baserad på två funktioner Carry generate: Addition i position i sägs generera en carry om den producerar en carry=1 oberoende av xi-1, yi-1, … x0, y0, c0 Carry propagate: Addition i position i sägs propagera en carry om den producerar en carry=1 (ci+1)då xi-1, yi-1, … x0, y0, c0 orsakar en carry-in (Ci=1) Ett additionssteg genererar en carry (ci+1): Om ingångarna (xi, yi) antingen genererar en carry (gi=1) eller att steget propagerar carry-in (pi=1) Copyright Bengt Oelmann 2002
Exempel på propagate och generate funktionerna 0 1 0 1 1 0 0 0 1 1 0 1 X Y + 0 0 0 1 0 0 0 1 1 1 1 1 0 1 1 1 0 0 Addition utan carry-propagering 0 1 0 1 1 0 0 0 1 1 0 1 X Y + 0 1 1 1 0 0 1 0 0 0 1 1 S C Copyright Bengt Oelmann 2002
Utveckla uttryck för CLA-logik Utveckla uttrycken rekursivt Ta fram uttryck för c1, c2, c3 och c4 c1, c2, c3 och c4 är funktioner av g- och p Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 12-bitars CLA Adderare Längsta kombinatoriska fördröjningen 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] C8 C4 ADD X[11-8] Y[11-8] S[11-8] ADD X[7-4] Y[7-4] S[7-4] ADD X[3-0] Y[3-0] S[3-0] Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 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; Ska vara med för att + ska fungera för vektorer av std_logic ’0’&X är med för att + ska returnera en summa på N+1 bitar Summan ut (S) är de N minst signifikanta bitarna Carry-out är den mest signifikanta biten Copyright Bengt Oelmann 2002
Exempel på syntes av adderare VHDL- beskrivning Krav på fördröjning Fördröjning [ns] 5 35 CLA adderare Rippel adderare Syntesverktyg Area 200 700 CLA adderare Rippel adderare Grind- nätlista Rapport-fil Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 Multiplikation 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; Ska vara med för att * ska fungera för vektorer av std_logic Antal bitar i produkten är summan av antalet bitar i multiplikator och multiplikand Copyright Bengt Oelmann 2002
Timing i synkrona system Generell modell för synkront system tC-Q och tSETUP är fördröjningar i vippan Kombinatorisk logik Q1 D2 Q2 C tSETUP tC-Q tLOGIK En klockcykel är summan av alla fördröjningar: Då vi inte har någon timing-marginal så klockas system på maximal klockfrekvens: C tC-Q tSETUP Q1 D2 tLOGIK tMARGINAL Copyright Bengt Oelmann 2002
Synkrona processer i VHDL 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 Copyright Bengt Oelmann 2002
Exempel: positivt flanktriggad D-vippa i VHDL clk d q dff 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 clk’event clk’event and clk=’1’ Läser in det nya värdet i vippan Behåller det gamla värdet Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 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 Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 Exempel på D-latch architecture dataflow of dlatch is q <= d when (clk = ’1’) else q; D Q Copyright Bengt Oelmann 2002
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) if (clk'event and clk = '1') then if d > 10 then q <= d; else q <= conv_std_logic_vector(10,8); end if; end process; end rtl; 10 d q 2:1 MUX clk 1 d>10 Signal- och variabeltilldelningar leder till införande av register Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 Initiering av vippor Initiering av vippor behövs efter systemstart Två typer av initiering Synkron reset/preset Asynkron reset/preset Exempel: synkron reset D Q reset if (clk’event and clk = ’1’) then if reset = ’1’ then q <= ’0’; else q <= d; end if; end if; Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 Mealy typ i VHDL 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 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; aIn yOut present_state next_state Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 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=1 aIn=1 Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 Räknare i VHDL Modulo-8 räknare 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; Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 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) 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 Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 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 Copyright Bengt Oelmann 2002
Copyright Bengt Oelmann 2002 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; Copyright Bengt Oelmann 2002
Exempel #1: RAM i VHDL Definiera färdig RAM module från ett bibliotek 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; Definiera färdig RAM module från ett bibliotek din dout address0 address1 we RAM4_8 a0 a1 q Copyright Bengt Oelmann 2002
Exempel #2: RAM i VHDL Definiera en minnesmatris 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) if clk'event and clk='1' then if we_n='0' then ram_array(conv_integer(addr)) <= din; end if; end process; dout <= ram_array(conv_integer(addr)); end rtl; Definiera en minnesmatris din dout addr we_n RAM32_16 Copyright Bengt Oelmann 2002