Post on 14-Dec-2015
VHDL Refresher
ECE 437
April 18, 2023
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 StyleENTITY 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 assignmentY1 <= 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 StyleENTITY d_ff IS PORT (CLR, D, CLK: IN std_logic; Q: OUT std_logic);END d_ff;
ARCHITECTURE behavioral OF d_ff ISBEGIN
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 ListFF: 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 Processentity 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 bea 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)
Common Synthesis Mistakes
• Mostly based on App. A of VHDL Made Easy (Pellerin & Taylor, © 1997 Prentice-Hall, Inc.)
– Also look in Synopsys docs: Core Synthesis-> Guide to HDL Coding Styles… Section 5
• Structure of your VHDL code effects– Circuit speed– Circuit area
• for FPGAs, may cause circuit not to fit
• Just because it simulates & maybe even synthesizes…
1. Unintended (inferred) latchesThey will drive you nuts.
process(address,address_strobe)
begin
if address_strobe = ‘1’ then
decode_signal <= address;
end if;
end process
What is probably wrong with this?
(Pellerin & Taylor, © 1997 Prentice-Hall, Inc.)
1. Unintended latches
process(address,address_strobe)
begin
if address_strobe = ‘1’ then
decode_signal <= address;
else
decode_signal <= false;
end if;
end process
(Pellerin & Taylor, © 1997 Prentice-Hall, Inc.)
One way to fix:
1. Unintended latches
process(address,address_strobe)
begin
decode_signal <= false;
if address_strobe = ‘1’ then
decode_signal <= address;
end if;
end process
(Pellerin & Taylor, © 1997 Prentice-Hall, Inc.)
Another way to fix:
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 isport (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 omittedsignal 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
3. Relying on initial value
Signal res1: bit := ‘0’;
Begin
process(tmpval,INIT)
begin
if (tmpval = 2) then
res1 <= 1;
elsif (INIT = ‘1’) then
res1 <= 1;
end if;
end process
process(tmpval,INIT)
begin
if (tmpval = 2) then
res1 <= 1;
elsif (INIT = ‘1’) then
res1 <= 1;
else res1 <= ‘0’;
end if;
end process
(Pellerin & Taylor, © 1997 Prentice-Hall, Inc.)
Good Design Guidelines
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; 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; 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.
Questions?