Presentation on theme: "VHDL Refresher ECE 437 April 13, 2015 Motivation ECE 337 is a prerequisite But… –You may have taken 337 a few semesters previous –Breaks causes memory."— Presentation transcript:
VHDL Refresher ECE 437 April 13, 2015
Motivation ECE 337 is a prerequisite But… –You may have taken 337 a few semesters previous –Breaks causes memory loss –First lab actually requires you to make a register file
Lecture Objectives After completing this lecture, you should be able to: –Identify the differences between dataflow and behavioral styles –Resolve common mistakes –Make acquaintances with modular design –Improve your productivity
Dataflow Style Directly describes how the inputs flow to the outputs through the various logic functions Applies only to combinational logic Think of each line as describing a logic gate or collection of logic gates All dataflow statements are “concurrent”
Example: Dataflow Style ENTITY nand_nor IS PORT (Sel, A, B: IN std_logic; Y: OUT std_logic); END nand_nor; ARCHITECTURE dataflow OF nand_nor IS SIGNAL Y1, Y2, Y3, Y4 :std_logic; -- define internal signals BEGIN -- The following are concurrent statements Y <= Y3 OR Y4; -- Y is NAND for Sel='1' -- and NOR for Sel='0’ Y1 <= A AND B ; -- Y1 is AND Y2 <= A OR B; -- Y2 is OR Y3 <= NOT Y1 AND Sel; Y4 <= NOT Y2 AND NOT Sel; END dataflow;
Other Dataflow Statements Conditional assignment -- NAND (when in doubt about operator precedence, use parenthesis) Y1 <= ‘1’ when (A = ‘0’ or B = ‘0’) and Sel = ‘1’ else ‘0’; -- NOR Y2 <= ‘0’ when A = ‘1’ or B = ‘1’ or Sel = ‘1’ else ‘1’; Y <= Y1 or Y2 Selected signal assignment Y1 <= not (A AND B); Y2 <= not (A OR B); with Sel select Y <= Y1 when ‘1’, Y2 when ‘0’, ‘0’ when others; -- good practice
Behavioral Style Similar to C programming style –can use constructs including "if", "for“, “case” etc. –order of statements is significant –Best used for complex combinational logic –Possibly easier to write, But very easy to foul up –In general, code has to translate into combinational logic! –Keep your code simple!!!!!! –Beware! Easy to accidentally create latches Consider example of a D flip-flop
Example: Behavioral Style ENTITY d_ff IS PORT (CLR, D, CLK: IN std_logic; Q: OUT std_logic); END d_ff; ARCHITECTURE behavioral OF d_ff IS BEGIN process( D, CLR, CLK ) -- sensitivity list begin if( CLR = ‘0’ ) then -- asynchronous clear Q <= ‘0’; elsif( rising_edge(CLK) ) -- assign output on clock edge Q <= D; end if; end process; END d_ff;
Behavioral Syntax Process Block (translates into a block of circuitry) –Usually concurrent statement that merely contains sequential statements (e.g. the if/then/else). –This is the only place for sequential statements –The Process block, as a whole, is a “concurrent” statement –Reminder: concurrent statements are interpreted as parallel sequential statements are interpreted in order –Signal values are assigned at THE END of a process block
Sensitivity List Simple minded, safe approach –identify all inputs to the process signals appear on right hand side of <= or := signals appear in conditional expressions –if rst=‘1’ then etc. –case Sel is – when “00” => Y <= d0; etc. –Always do this for combinational logic Never include output in sensitivity list –can lead to infinite iteration –may imply combinational feedback loop
Sensitivity List A more sophisticated approach –only applies to sequential blocks changes triggered on edge of clock i.e., flip-flops or registers –identify asynchronous inputs & clock signal assignments and conditional expressions that are NOT inside of a rising_edge(), falling_edge(), or clk’event branch
Example: Sensitivity List FF: process(Clk) -- nRst not included in sensitivity list begin if nRst=‘0’ then q <= ‘0’; elsif rising_edge(Clk) then q <= d; end if; end process; Changes to nRst not handled because not included in sensitivity list!
Latches & Flip-Flops In ECE 337 and 437, always use FF’s Problems with latches –Easy to accidentally create loops Really big problem in the completed design! –Quite often, you need a feedback path In such cases, timing becomes tricky –Makes automated testing difficult Big issue in industry You have been warned
Example: Flip-Flop v. Latch REG: process(Clk,Rst) begin if Rst = '1' then Q_int <= '0'; elsif rising_edge(Clk) then Q_int <= int_d; end if; end process REG; LATCH: process(Clk, int_d) begin if Clk = '1' then Q_int <= int_d; end if; end process LATCH;
Edge-Triggering Advice ’EVENT, RISING_EDGE, or FALLING_EDGE: –Do NOT use on multiple signals in your DESIGN (unless we tell you to… although I can’t imagine where!) –There should usually be only a single clock Do NOT mix clock edge with other signals in an if() or elsif() expression –if (RISING_EDGE(CLK) and A=‘1’) then you lose; end if; Signal for ’EVENT, RISING_EDGE, or FALLING_EDGE –MUST be a CLOCK signal –Must not be a random signal. There are exceptions, but not in this class! Violators usually create unsynthesizeable designs
Concurrent Processes Use multiple processes in an entity for –State machines & other sequential functions –One process for registers or storage elements –One or more process for combinational logic Generate register inputs (e.g., next state logic) Generate output signals You may be putting too much in one entity –If you have multiple sequential processes –If you have more than 3 or 4 processes
Example: Concurrent Process entity cp_example is port (Clk, X, Y, Rst: in std_logic; Q: out std_logic); end cp_example; architecture behav of cp_example is signal int_d, q_int: std_logic; Begin Q <= Q_int; REG: process(Clk,Rst) begin if Rst = '1' then Q_int <= '0'; elsif rising_edge(Clk) then Q_int <= int_d; end if; end process REG; NEXT_D: process(X,Y,Q_int) begin int_d <= ‘0’; if X = ‘0’ and Y = ‘0’ and Q_int = ‘0’ then int_d <= ‘1’; end if; end process NEXT_D; end behav; Note: dataflow code would be a better choice for process NEXT_D
Reminder! To improve chances of synthesis –Think of each block of code as a circuit rather than as code. –Until proficient, stick to styles and syntax from ECE 337. –Major difference from sequential programming languages, Order of concurrent statements has nothing to do with order of execution! –Use data flow whenever possible –Keep your behavioral blocks as simple as possible –Most code has to translate into combinational logic (except where you intentionally create latches or registers)
Common Synthesis Mistakes “In the immortal words of Socrates, ‘I drank what?’” -- Val Kilmer (Real Genius)
2. Trying to read an output Example: a state machine –You may want “state” signal as output –VHDL won’t let you read an output
entity updn02 is port (UP,DOWN,Clk,Rst: in std_logic; TOP,BOT: out std_logic; state: out std_logic_vector(1 downto 0)); end updn02; architecture behavioral of updn02 is -- constant declarations omitted signal nextstate: std_logic_vector(1 downto 0); begin TOP <= state(1) AND NOT state(0); BOT <= NOT state(1) AND NOT state(0); REGS: process(Clk,Rst) begin if Rst=‘1’ then state <= NUM0; elsif rising_edge(Clk) then state <= nextstate; end if; end process; NEXTSTATE: process(state,UP,DOWN) begin case state is when NUM0 => if UP = ‘1’ and DOWN = ‘0’ then nextstate <= NUM1; elsif UP = ‘0’ and DOWN = ‘1’ then -- rest of code omitted WRONG
entity updn02 is port (UP,DOWN,Clk,Rst: in std_logic; TOP,BOT: out std_logic; St: out std_logic_vector(1 downto 0)); end updn02; architecture behavioral of updn02 is -- constant declarations omitted signal state, nextstate: std_logic_vector(1 downto 0); begin TOP <= state(1) AND NOT state(0); BOT <= NOT state(1) AND NOT state(0); St <= state; REGS: process(Clk,Rst) begin if Rst=‘1’ then state <= NUM0; elsif rising_edge(Clk) then state <= nextstate; end if; end process; NEXTSTATE: process(state,UP,DOWN) begin case state is when NUM0 => if UP = ‘1’ and DOWN = ‘0’ then nextstate <= NUM1; elsif UP = ‘0’ and DOWN = ‘1’ then -- rest of code omitted One right way.
Other ways? Type inout: wrong –Means signal is bidirectional (tri-state) –Probably requires I/O pin if using FPGA –Advice, avoid tri-state busses except for bidirectional I/O pins
3. Relying on initial value Initialization at signal declaration have no meaning for circuit synthesis. In an actual circuit (and in synthesis), FF’s or registers are the only thing that can be initialized
Modularity Break down the intended design into simple blocks that may be assembled to create the final design. Each.vhd file should contain a block and be as simple as possible. Modularity facilitates reuse, debugging, modifications.
Example Program Counter PC 4 Adder
Program Counter Modularity Simple register and an Adder Yes NO Do not combine the logic, make them separate Process (pc_in, clk, nReset) if (nReset = ‘0’) then pc_out <= ZERO; elsif (rising_edge(clk)) then if (we = ‘1’) then pc_out <= pc_in; endif; Process (pc_in, clk, nReset) if (nReset = ‘0’) then pc_out <= ZERO; elsif (rising_edge(clk)) then if (we = ‘1’) then pc_out <= pc_in + 4; endif;
Modelsim Waveforms Save the waveform window so you may quickly regain signals. –Synthesis will not show most signals. –It will show top level signals Use dividers to group signals logically. Add all relevant signals to waveform. –You will need more than just the top level signals!
Modelsim Debugging Modelsim allows you to set break points –Use this to find iteration limit loops –Beware Sensitivity lists If everything looks correct double check the list The waveform should first be looked at before you make any changes to your code –Check signal interaction Do not just look at the output and modify your code –You will spend more time debugging hacks in later labs
Modifying your code Small hacks will lead to 10x increase in debug time. –Think through the modification. –Think about what components will be added to the design. Modify one component at a time –This will allow you to narrow down the cause of the problem. –This also avoids causing other problems.