320 likes | 702 Views
Introduction to Structured VLSI Design - VHDL IV. Joachim Rodrigues. Overview. Recap Datapath Memories Strictly Structured VHDL. library IEEE; use IEEE.std_logic_1164.all; package example_pack1 is -------------------------------- -- constants --------------------------------
E N D
Introduction to Structured VLSI Design- VHDL IV Joachim Rodrigues
Overview • Recap • Datapath • Memories • Strictly Structured VHDL
library IEEE; use IEEE.std_logic_1164.all; package example_pack1 is -------------------------------- -- constants -------------------------------- constant N : integer := 8; constant halfperiod : time := 100 NS; constant dataskew : time := 1 NS; -------------------------------- -- component declarations -------------------------------- component FF generic (N : integer); port(D : in std_logic_vector(N-1 downto 0); Q : out std_logic_vector(N-1 downto 0); reset, clk : in std_logic); end component; end example_pack1; Own packages need to be Compiled declared like the IEEE packages. use work.example_pack1.all; Package- Example
Generate-Replicates concurrent statements ff8 ff7 ff0 library IEEE; use IEEE.std_logic_1164.all; use work.common.flipflop; entity ff_mem is generic( bits : integer := 3; rows : integer := 352 ); port( clk : in std_logic; d : in std_logic_vector(bits-1 downto 0); q : out std_logic_vector(bits-1 downto 0)); end; architecture behavioral of ff_mem is type wire_type is array (rows downto 0) ofstd_logic_vector(bits-1 downto 0); signal wire : wire_type; begin wire(rows) <= d; ff_gen: for i in rows-1 downto 0 generate ff : flipflop generic map (N => bits) port map ( CLK => clk, d => wire(i+1), q => wire(i)); end generate ff_gen; q <= wire(0); end;
Datapath • RTL description is characterized by registers in a design, and the combinational logic inbetween. • This can be illustrated by a "register and cloud" diagram . • Registers and the combinational logic are described separately in two different processes.
Datapath-Sequential part architecture SPLIT of DATAPATH issignal X1, Y1, X2, Y2 : ... begin seq : process (CLK) beginif (CLK'eventand CLK = '1') then X1 <= Y0; X2 <= Y1; X3 <= Y2; endif; end process;
Datapath-Combinatorial part LOGIC : process (X1, X2) begin - F(X1) and G(X2) can be replaced with the code - implementing the desired combinational logic - or appropriate functions must be defined. Y1 <= F(X1); Y2 <= G(X2); endprocess; end SPLIT; Do not constraint the synhtesis tool by splitting operations, e.g., y1=x1+x12.
Pipelining • The instructions on the preceeding slides introduced pipelining of the DP. • The critical path is reduced from F(X1)+ G(X2) to the either F(X1) or G(X2).
Memories • Abstraction levels • Behavorial model (arrays) • Synthesizable model (registers) • Hard macros (technology dependent) Hard macros are technolgy dependent and require less area than registers.
Ram vs Register RAM characteristics • RAM cell designed at transistor level • Cell use minimal area • Is combinatorial and behaves like a latch • For mass storage • Requires a special interface logic Register characteristics • DFF (may) require much larger area • Synchronous • For small, fast storage • e.g., register file, fast FIFO
RAM-Single Port LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; ENTITY ram IS GENERIC ( ADDRESS_WIDTH : integer := 4; DATA_WIDTH : integer := 8 ); PORT ( clock : INstd_logic; data : IN std_logic_vector(DATA_WIDTH - 1 DOWNTO 0); write_address, read_adress : IN std_logic_vector(ADDRESS_WIDTH - 1 DOWNTO 0); we : INstd_logic; q : OUT std_logic_vector(DATA_WIDTH - 1 DOWNTO 0) ); END ram; ARCHITECTURE rtl OF ram IS TYPE RAM IS ARRAY(0 TO 2 ** ADDRESS_WIDTH - 1) OF std_logic_vector(DATA_WIDTH - 1 DOWNTO 0); ram_block : RAM; BEGINPROCESS (clock,we) BEGIN IF (clock'event AND clock = '1') THEN IF (we = '1') THEN ram_block(to_integer(unsigned(write_address))) <= data; END IF; q <= ram_block(to_integer(unsigned(read_address))); END IF; END PROCESS; END rtl; A single word may be read or written during one clock cycle. an adress is always positiv
RAM-dual port Dual Port: Concurrent Read and Write Dual-port RAMs Are very expensive in area and should be avoided !! Dual port functionality may be realized by a hybrid single-port RAM. Read on pos edge and write on neg edge. USE work.ram_package.ALL; ENTITY ram_dual IS PORT (clock1, clock2 : IN std_logic; data : IN word; write_address, read_address : IN address_vector; we : IN std_logic; q : OUT word ); END ram_dual; ARCHITECTURE rtl OF ram_dual IS SIGNAL ram_block : RAM; SIGNAL read_address_reg : address_vector; BEGINPROCESS (clock1) BEGIN IF (clock1'event AND clock1 = '1') THEN IF (we = '1') THEN ram_block(write_address) <= data; END IF; END IF; END PROCESS; PROCESS (clock2) BEGIN IF (clock2'event AND clock2 = '1') THEN q <= ram_block(read_address_reg); read_address_reg <= read_address; END IF; END PROCESS; END rtl;
ROM Behavioral 16x4 ROM model library IEEE;use IEEE.std_logic_1164.all;entity rom_rtl isport (ADDR: in INTEGER range 0 to 15; DATA: out STD_LOGIC_VECTOR (3 downto 0));end rom_rtl; architecture XILINX of rom_rtl issubtype ROM_WORD is STD_LOGIC_VECTOR (3 downto 0);type ROM_TABLE isarray (0 to 15) of ROM_WORD;constant ROM: ROM_TABLE := ROM_TABLE'( ROM_WORD'("0000"), ROM_WORD'("0001"), ROM_WORD'("0010"), ... beginDATA <= ROM(ADDR); -- Read from the ROMend XILINX;
Register File Registers are arranged as an 1-d array • Each register is accessible with an address • Usually 1 write port (with write enable signal) • May have multiple read ports
Register File cont’d 4 word, 1 write and 2 read
Strictly Structured VHDL “Gaisler’s method” is a design methodology (code style), which is summarized below: • Use records • Use case statements to model FSMs • Use synchronous reset • Apply strong hierarchies
Strictly Structured VHDL • How is it done? • Local signals (r, rin) are stored in records and contain all registered values. • All outputs are stored in a entity specific record type declared in a global interface package – enables re-use. • Use a local variable (v) of the same type as the registered values. • reset handling moves to combinatorial part.
Realization of FSMs- behavorial architecture implementation of state_machine is type state_type is (st0, st1,st2, st3); -- defines the states type reg_type isrecord output : STD_LOGIC_VECTOR (m-1 downto 0); state : state_type; endrecord; Signal r ,rin : reg_type; begin combinatorial : process (input,reset,r) -- Combinatorial part variable v : reg_type; begin v : = r; -- Setting the variable case (r.state) is -- Current state and input dependent when st0 => if (input = ”01”) then v.state := st1; v.output := ”01” end if; when ... whenothers=> v.state := st0; -- Default v.output := ”00”; endcase; if (reset = ’1’) then -- Synchronous reset v.state := st0; -- Start in idle state endif; rin <= v; -- update values at register input output <= v.output; -- Combinational output --output <= r.output; -- Registered output endprocess;
Realization of FSMs - sequential synchronous : process (clk)– This part is always the same begin if clk’event and clk = ’1’ then r <= rin; endif; endprocess; endarchitecture;
Strictly Structured VHDL-Advantages DUT DUT Adding a signal in traditional style • Add port in entity declaration • Add signal to sensitivity list • Add port in component declaration • Add port in component instantiation Adding a signal in Strictly Structured VHDL methodology • Add element in record declaration
Structured VHDL Obvious Advantages Readability Less written code Maintainance and re-useability Hidden Advantages Synthesizable Synchronous reset No need to update sensitivity lists Faster simulation (less concurrent statements)
Structured VHDL-Stored signals Adding a stored signal in traditional style • Add two signals (current, next) • Add signal to sensitivity list • Add reset value • Update on clock edge Comb Current Next Adding a signal in Structured VHDL methodology • Add element in declaration record Comb r rin
Realization of FSMs -Example architecture implementation of state_machine is type state_type is (st0, st1,st2, st3); -- defines the states type reg_type isrecord output : STD_LOGIC_VECTOR (m-1 downto 0); state : state_type; new_signal : std_logic; endrecord; Signal r ,rin : reg_type; begin combinatorial : process (input,reset,r) -- Combinatorial part variable v : reg_type; begin v : = r; -- Setting the variable case (r.state) is -- Current state and input dependent when st0 => if (input = ’1’) then v.state := st1; v.output := ”01” end if; when ... whenothers=> v.state := st0; -- Default v.output := ”00”; endcase;
Structured VHDL state_machine output_type input_type library IEEE;use IEEE.STD_LOGIC_1164.all; library global_interface is input_type is record -- Type record newsignal : std_logic; end record; end; library IEEE; use IEEE.STD_LOGIC_1164.all; Use work.global_interface.pkg; entity state_machine is port (clk : in STD_LOGIC; reset : in STD_LOGIC; input : in input_type; output : out output_type; end state_machine;
Conclusions Recommendations • Use structured VHDL • Use synchronous reset • Use hierarchy (instantiation) extensively • Let the testbench set the input signals and not the simulator (No signal forcing in ModelSim)
Configuration • Testbench is reused by declaring a different configuration • A configuration may realize different architectures, memories, etc. • Examples: • A synthesizable model / behavorial model • A synthesizable model / gate-level model Syntax: configurationconfiguration_nameofentity_nameisforarchitecture_nameforlabel|others|all: comp_nameuseentity [lib_name.]comp_entity_name(comp_arch_name) | useconfiguration [lib_name.]comp_configuration_name [generic map (...)] [port map (...)] ; end for; ... end for; endconfiguration_name;
Configuration-Example configuration THREE of FULLADDER isfor STRUCTURAL forINST_HA1, INST_HA2: HA useentityWORK.HALFADDER(CONCURRENT); end for; for INST_XOR: XOR useentityWORK.XOR2D1(CONCURRENT); end for; end for; end THREE;
Non-synthesizable VHDL • The following VHDL keywords/constructs are ignored or rejected by most RTL synthesis tools: • after, (transport and inertial) • wait for xx ns • File operations • generic parameters must have default values • All dynamically elaborated data structures • Floating point data types, e.g. Real • Initial values of signals and variables • Multiple drivers for a signal (unless tri-stated) • The process sensitivity list is ignored • Configurations • Division (/) is only supported if the right operand is a constant power of 2
After Command 0 ns 100 ns • <signal_name> <= value after <time> • Example: A <= ‘1’, ‘0’ after 100 ns, ‘1’ after 200 ns; Not synthesizable 200 ns
Wait Command • Usage: waiton <sensitivity list> waituntil <expression> waitfor <time interval> • Examples : process(a) begin waituntil (a=c) b<= not a; end process; process(a,b) begin sum <= a xor b after T_pd; carry <= a and b after T_pd; wait on a,b; end process; process (a,c) begin b <= a + c; waitfor T_pd; end process; Not synthesizable
Assertion Statement To be used in the testbench • Usage: assert <expression> report <message> severity <Note | Warning | Error | Failure>; • Example: assert simulation(test_input_vector(i))=test_output_vector(i);report “Test vector failure”;severity failure; Not synthesizable
Already mentioned: get rid of any Latches. Check the synthesis report and correct eventual case/if instructions Watch out: Inferred Latches