Wednesday, June 26, 2013

VHDL Subtelities

1. What is the difference between the following code snippets?

(a)
architecture RTL of tbcount is
signal count: integer := 0;
begin
tb_count : process (clk) is
begin
if rising_edge(clk) then
count <= count + 1;
end if;
end process tb_count;
tbcount <= count;
end architecture RTL;

(b)
architecture RTL of tbcount is
signal count: integer := 0;
begin
tb_count : process (clk) is
begin
if rising_edge(clk) then
count <= count + 1;
end if;
                        tbcount <= count;
end process tb_count;
end architecture RTL;

Solution:

(a) In this case, count will be updated on the rising edge. tbcount will updated delta clock period after the rising edge.
(b) In this case, tbcount will be updated on the falling edge. count gets updated on rising edge, tbcount gets updated on falling edge.

process (clk) has events both on rising edge and falling edge. The events happen both on rising and falling edge, in 

Tuesday, June 25, 2013

Test Benches

Best Practices in writing test benches. There are number of books which talk about writing good test benches. However, my heart tells me that best practices on test benches will be written by some experienced people on the web. This is because techniques are not in step wise and they are too theoretical.

1. Automating Test Bench Creation

--tbcounter
tbcounter: work.simpkg.tbcount port map(clk,tbcount);

Example:
sw0 <= '1' when (TbCount >=300 and tbcount <302) else '0';

2. 

Step 2e. Bit shifting in VHDL

Today, I was playing with bit shifting to write test bench. The DUT had an input shift register, to apply the input I had to play with shifting operations

1) sra, srl etc.,

For a while, I had trouble getting it to work.

variable temp: std_logic_vector (3 downto 0);

stim := stim sra 1;

I was getting all kinds of errors when I compile. Finally, I found from this wesite that

a) Include use.ieee.numeric_bit.all;

variable temp: bit_vector(3 downto 0);

stim := stim sra 1;

Now it started compiling. I wonder now, is there a way to get std_logic_vector working with sra, sla.

To convert bit to std_ulogic use

to_stdulogic(stim(0));

Friday, June 21, 2013

Step 2d: My Experiments with Counter

1. Today, I wrote code for counter is asynchronous reset. Below are the code and RTL schematic generated.

VHDL Code:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

entity CounterSTD is
port 
(
    clk,rst : in std_logic;
    counter : out std_logic_vector(3 downto 0)
);
end CounterSTD;

architecture Behavioral of CounterSTD is
    signal count : std_logic_vector(3 downto 0);

begin

counter0 : process (clk, rst) is
begin
    if rst = '1' then
        count<= (others => '0');
    elsif rising_edge(clk) then
        count <= count + 1;
    end if;
end process counter0;

counter <= count;

end Behavioral;


RTL Schematic



Note: The name of Flip-Flop is fdc => D Flip-flop with Clear Input. Clear => Asynchronous Reset

2. Counter with Synchronous Reset


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity counterwithsyncreset is
    port (
        clk    :    in        std_logic;
        rst    :    in        std_logic;
        counter: out std_logic_vector(3 downto 0)
    );
end entity counterwithsyncreset;

architecture RTL of counterwithsyncreset is
    signal count: std_logic_vector(3 downto 0);
begin
    counter0 : process (clk) is
    begin
        if rising_edge(clk) then
            if rst = '1' then
                count <= ((others => '0'));
            else
                count <= count + 1;
            end if;
        end if;
    end process counter0;
    
counter <= count;
end architecture RTL;




Note: In this case Flip Flop Name: fdr => D Flip Flop with Reset. Reset is connected to Reset Pin.

3. Counters with Integers


library ieee;
use ieee.std_logic_1164.all;

entity counterintegersyncreset is
    port (
        clk    :    in        std_logic;
        rst    :    in        std_logic;
        counter: out     integer range 0 to 10
    );
end entity counterintegersyncreset;

architecture RTL of counterintegersyncreset is
    signal count: integer range 0 to 10;
begin

    counter0 : process (clk) is
    begin
        if rising_edge(clk) then
            if rst = '1' then
                count <= 0;
            else
                count <= count +1 ;
            end if;
        end if;
    end process counter0;
counter <= count;    
end architecture RTL;



Note: The synthesizer automatically figured out the required size for the end output. 
This is a great feature. However, integer usage has it's pros and cons.

Comments from another post:
http://electronics.stackexchange.com/questions/11774/vhdl-integers-for-synthesis
Integers are fine in synthesis, I use them all the time.
I use std_logic at top level ports, but internally I was using ranged integers all over the place
That's fine!
Be aware:
  • You are simulating first aren't you :) - Integer types don't automatically "roll-over" in simulation - it's an error to go out of the range you've specified for them. If you want roll-over behaviour, you have to code it explicitly. 
In the simulation even though integer was constrained for 0 to 100, it went to 997. 

  • They are only specced to go from $-2^{32}-1$ to $+2^{31}-1$ (i.e. not quite the full range of a 32-bit integer, you can't use $-2^{32}$ and remain portable), which is a bit of a pain at times. If you need to use "big" numbers, you'll have to use unsigned and signed.
  • If you don't constrain them, you can sometimes end up with 32-bit counters where less would do (if the synth and subsequent tools can't "see" that they could optimise bits away).
On the upside:
  • They are much faster to simulate than unsigned/signed vectors
  • They don't automatically roll-over in simulation (yes, it's in both lists :). This is handy - for example you get early warning that your counter is too small.
When you do use vector types, you are using ieee.numeric_stdnot ieee.std_logic_arith aren't you?
I use integers where I can, but if I explicitly want "roll-over n-bit counters", I tend to use unsigned.

4. Exericse: Explain why does the circuit gets optimized



library ieee;
use ieee.std_logic_1164.all;

entity counterintegersyncreset is
    port (
        clk    :    in        std_logic;
        rst    :    in        std_logic;
        counter: out     integer range 0 to 10
    );
end entity counterintegersyncreset;

architecture RTL of counterintegersyncreset is
    signal count: integer range 0 to 10;
begin

    counter0 : process (clk) is
    begin
        if rising_edge(clk) then
            if rst = '1' then
                count <= 0;
            else
                if (count = 10) then
                    count <= 0;
                end if;
                count <= count +1 ;
            end if;
        end if;
    end process counter0;
counter <= count;    
end architecture RTL;




Monday, June 17, 2013

Curious Questions: Q1

1. What is the difference between these two codes
Code 1:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity DFlipFlop is
port 
(
    clk,D,ResetN     : in std_logic;
    Q                 : out std_logic
);
end DFlipFlop;

architecture Behavioral of DFlipFlop is

begin
DFlipFlop : process (clk,ResetN)
begin
if (resetn = '0') then
    Q <= '0';
    elsif    rising_edge(clk) then
    Q <= D;
end if;
--
end process DFlipFlop;


end Behavioral;

Code 2:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity DFlipFlop is
port 
(
    clk,D,ResetN     : in std_logic;
    Q                 : out std_logic
);
end DFlipFlop;

architecture Behavioral of DFlipFlop is

begin
DFlipFlop : process (clk,ResetN)
begin
    if rising_edge(clk) then
        if (ResetN = '0') then
            Q <='0';
        else
            Q <= D;
        end if;
    end if;

end process DFlipFlop;


end Behavioral;


Investigation so far:

Synthesized Circuit for Code 1


Synthesized Circuit for Code 2

Notice that one has FDC and other is FDR. What is the difference between them?

Sunday, June 16, 2013

Step 2c: Regular Encoder 4 to 2 (Problem of NULL discovered)

Encoder Code:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity encoder4to2 is
port 
(
     ilines    : in std_logic_vector(3 downto 0);
     dout     : out std_logic_vector(1 downto 0);
     valid    : out std_logic
);
end encoder4to2;

architecture Behavioral of encoder4to2 is

begin

encoder4 : with ilines select
    dout <=
        "00" when "0001",
        "01" when "0010",
        "10" when "0100",
        "11" when "1000",
        "11" when others;
        
validout : with ilines select
    valid <=
        '1' when "0001",
        '1' when "0010",
        '1' when "0100",
        '1' when "1000",
        '0' when others;

end Behavioral;


Test bench for Encoder: Attempt 1 using case statement



library ieee;
use ieee.std_logic_1164.all;
use IEEE.Std_Logic_Unsigned.all ;
use IEEE.Std_Logic_Arith.all;
use work.simpkg.all;

entity tb_encoder4to2 is
end tb_encoder4to2;

architecture Test of tb_encoder4to2 is
-- Declare/Import DUT
component encoder4to2
    port(ilines : in  std_logic_vector(3 downto 0);
         dout   : out std_logic_vector(1 downto 0);
         valid  : out std_logic);
end component encoder4to2;
-- Declare Internal Signals which act as Input and Output to DUT
    signal clk : std_logic;     --- clock driver signal

-- Constants ---
    constant period     : time := 10 ns;
    constant update     : time := 1 ns;
    signal ilines : std_logic_vector(3 downto 0);
    signal dout : std_logic_vector(1 downto 0);
    signal valid : std_logic;
--Start of Test Bench
begin

-- Define the Clock required for simulation --
testbenchclk : process
begin
    clk <= '0';
    wait for period / 2;
    clk <= '1';
    wait for period / 2;
end process testbenchclk;

-- Instantiate DUT -----
dut:component encoder4to2
    port map(ilines => ilines,
             dout   => dout,
             valid  => valid);

-- Stim Loop --
 stim_loop : process
 variable expected:std_logic_vector(1 downto 0);
 begin
     for i in 0 to 15 loop
         -- Apply Stim to DUT Inputs & update
         ilines <= CONV_STD_LOGIC_VECTOR(i,4);
         
         wait for update ;
         
         -- Equations for expected response
         case ilines is
             when "0001" => expected := "00";
             when "0010" => expected := "01";
             when "0100" => expected := "10";
             when "1000" => expected := "11";
             when others => null;
         end case;
          
         --- Check response
         assert (expected = dout ) 
              report "Test Failed" & CR &
              "dut.stimulus= "& vec2str(ilines) & "; " &"dut.response =" & vec2str(dout) & "; "&"expected =" & vec2str(expected)&"; "
              severity error;
         
         -- Next Stim after a delay
         wait for period;    
     end loop;
     
     -- Wait Indefinitely No more Stim
     wait;
 end process stim_loop;

--End of Test Bench --
end architecture Test;


Xilinx ISE Simulator Output:


at 1 ns: Error: Test Failed
dut.stimulus= 0000; dut.response =11; expected =XX; 
at 34 ns: Error: Test Failed
dut.stimulus= 0011; dut.response =11; expected =01; 
at 56 ns: Error: Test Failed
dut.stimulus= 0101; dut.response =11; expected =10; 
at 67 ns: Error: Test Failed
dut.stimulus= 0110; dut.response =11; expected =10; 
at 78 ns: Error: Test Failed
dut.stimulus= 0111; dut.response =11; expected =10; 

Insight into the problem:
The DUT response seems to be as expected, however the expected response has been calculated incorrectly. To debug this problem, I have stepped through the code in debugger mode of Xilinx ISE.
Here is what I found

Notice the case structure in expected response :
when others => null
This was the culprit, what it was doing was that whenever the input wasn't one-hot encoded, it would enter the case when others => null.
What null does is that doesn't change the previous output, this poses problem
was we want the dut to send 11 not the previous values

Solution:
To fix the problem, change the statement as follows
when others => expected := "11";

Final Modified test bench



library ieee;
use ieee.std_logic_1164.all;
use IEEE.Std_Logic_Unsigned.all ;
use IEEE.Std_Logic_Arith.all;
use work.simpkg.all;

entity tb_encoder4to2 is
end tb_encoder4to2;

architecture Test of tb_encoder4to2 is
-- Declare/Import DUT
component encoder4to2
    port(ilines : in  std_logic_vector(3 downto 0);
         dout   : out std_logic_vector(1 downto 0);
         valid  : out std_logic);
end component encoder4to2;
-- Declare Internal Signals which act as Input and Output to DUT
    signal clk : std_logic;     --- clock driver signal

-- Constants ---
    constant period     : time := 10 ns;
    constant update     : time := 1 ns;
    signal ilines : std_logic_vector(3 downto 0);
    signal dout : std_logic_vector(1 downto 0);
    signal valid : std_logic;
--Start of Test Bench
begin

-- Define the Clock required for simulation --
testbenchclk : process
begin
    clk <= '0';
    wait for period / 2;
    clk <= '1';
    wait for period / 2;
end process testbenchclk;

-- Instantiate DUT -----
dut:component encoder4to2
    port map(ilines => ilines,
             dout   => dout,
             valid  => valid);

-- Stim Loop --
 stim_loop : process
 variable expected:std_logic_vector(1 downto 0);
 begin
     for i in 0 to 15 loop
         -- Apply Stim to DUT Inputs & update
         ilines <= CONV_STD_LOGIC_VECTOR(i,4);
         
         wait for update ;
         
         -- Equations for expected response
         case ilines is
             when "0001" => expected := "00";
             when "0010" => expected := "01";
             when "0100" => expected := "10";
             when "1000" => expected := "11";
             when others => expected := "11";
         end case;
          
         --- Check response
         assert (expected = dout ) 
              report "Test Failed" & CR &
              "dut.stimulus= "& vec2str(ilines) & "; " &"dut.response =" & vec2str(dout) & "; "&"expected =" & vec2str(expected)&"; "
              severity error;
         
         -- Next Stim after a delay
         wait for period;    
     end loop;
     
     -- Wait Indefinitely No more Stim
     wait;
 end process stim_loop;

--End of Test Bench --
end architecture Test;


Xilinx ISE and Simulation

1. Variables in Xilinx ISIM
I'm Using Xilinx Simulator, so how do I get the simulator window to displays my variables? I have defined a variable as variable datacount : integer : 0;  
 but I dont see it in the Sim Hierarchy window, and cannot find out how to see the value of this variable along with my sim waveforms.

Ans: 
Variables are not visible simulation objects in ISim waveforms.  Status of variables can be observed using the command line / Tcl console using the show command.  Example:

show value <variable>

2. Details about working with ISim from Command Line
http://www.rte.se/blog/blogg-modesty-corex/isim-hdl-simulator

3.  Displaying Integers in Isim in decimal format

Currently, Isim doesn't support changing radix value of integers through GUI.


Soln: wave add -radix unsigned </path/to/integer>


Wednesday, June 12, 2013

Step 2b: Priority Encoder

1. Less Efficient Code in VHDL



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity PE4to2 is
port 
(
    w         : in  std_logic_vector(3 downto 0);
    z         : out std_logic_vector(1 downto 0);
    valid    : out std_logic    
);
end PE4to2;

architecture Behavioral of PE4to2 is

begin

pen : with w select
    z <=
        "00" when "0001",
        "01" when "0010",
        "01" when "0011",
        "10" when "0100",
        "10" when "0101",
        "10" when "0110",
        "10" when "0111",
        "11" when others;
        
validsig : with w select
    valid <=
        '0' when "0000",                
        '1' when others;
    
end Behavioral;


Note that to express 001x we had to use two lines, this makes the above code inefficient

2. Test Bench for code in above section 1
library ieee;
use ieee.std_logic_1164.all;
use IEEE.Std_Logic_Unsigned.all ;
use IEEE.Std_Logic_Arith.all;
use std.textio.all;
use work.simpkg.all;


entity tb_PE4to2 is
end tb_PE4to2;

architecture Test of tb_PE4to2 is
-- Declare/Import DUT
component PE4to2
    port(w     : in  std_logic_vector(3 downto 0);
         z     : out std_logic_vector(1 downto 0);
         valid : out std_logic);
end component PE4to2;

-- Functions
function leading1 (s : std_logic_vector) return integer is
begin
    for i in s'range loop
        if (s(i) = '1') then
            return i; -- Return for loop index
        end if;
    end loop;
    return 0;
end function leading1;

-- Declare Internal Signals which act as Input and Output to DUT
    signal clk : std_logic;     --- clock driver signal

-- Constants ---
    constant period     : time := 10 ns;
    constant update     : time := 1 ns;
    signal w : std_logic_vector(3 downto 0);
    signal z : std_logic_vector(1 downto 0);
    signal valid : std_logic;
--Start of Test Bench
begin

-- Define the Clock required for simulation --
testbenchclk : process
begin
    clk <= '0';
    wait for period / 2;
    clk <= '1';
    wait for period / 2;
end process testbenchclk;

-- Instantiate DUT -----
dut:component PE4to2
    port map(w     => w,
             z     => z,
             valid => valid);

-- Response Equation


-- Stim Loop --
 stim_loop : process
 variable expected: integer:=0;
 begin
     for i in 0 to 15 loop
         -- Apply Stim to DUT Inputs & update
         w <= CONV_STD_LOGIC_VECTOR(i,4);
        wait for update ;
         --report "Input =" & integer'image(i);
        
         -- Equations for response
         expected:= leading1(w);
         
         --- Check response
         if ( w /= "0000") then
             assert (z = expected) 
                  report "Test Failed " & CR &
                  "dut.stimulus= "& vec2str(w) & "; " &"dut.response =" & vec2str(z) & "; "&"expected =" & integer'image(expected)&"; "    
                  severity error;
        else
            -- Input = 0000 is  a special where output is don't cares and valid signal should be false
            assert (valid = '0')
            report "Test failed" & CR &
            "dut stimulus = 0000, Expected Valid to be false" & "found expected to be = " & std2str(valid)
            severity error;
          
          end if;
         
         -- Next Stim after a delay
         wait for period;    
     end loop;
     
     -- Wait Indefinitely No more Stim
     wait;
 end process stim_loop;

--End of Test Bench --
end architecture Test;


Note the usage of function in the above. Functions have to be declared in the architecture section before begin. Notice how leading1 function is used to detect the position of first '1' in the for loop.
Loop runs in reverse order, for i in s'range loop.
Notice that it is not for i in s'range to 0 loop



Tuesday, June 11, 2013

VHDL Concepts Learned

1. Types of Statements

a) Selected Signal Statement
Syntax: With...select

b) Conditional Signal Statement

c) Generate Statement

d) if-then-else

e) case statements

2. 

Free IP Cores Websites

Step 2b: Write VHDL Code for 2-to-4 binary decoder

library ieee;
use ieee.std_logic_1164.all;

entity Decodervvhdl is
    port (
        w            :    in        std_logic_vector(1 downto 0);
        y            :    out        std_logic_vector(3 downto 0);
        en            :     in        std_logic
    );
end entity Decodervvhdl;

architecture RTL of Decodervvhdl is
    signal Enw : std_logic_vector(2 downto 0);
    
begin

Enw <= en & w ;
decoder : with Enw select
    y <=
        "0001" when "100",
        "0010" when "101",
        "0100" when "110",
        "1000" when "111",
        "0000" when others;

end architecture RTL;



Synthesized Circuit of VHDL Code in Xilinx ISE:
The interesting aspect of this circuit is that FPGA Synthesizer use RAM module for decode operation.



Test Bench:

library ieee;
use ieee.std_logic_1164.all;
use IEEE.Std_Logic_Unsigned.all ;
use IEEE.Std_Logic_Arith.all;
use work.simpkg.all;
use std.textio.all;

entity tb_decoder is
end tb_decoder;

architecture Test of tb_decoder is
-- Declare/Import DUT
component Decodervvhdl
    port(w  : in  std_logic_vector(1 downto 0);
         y  : out std_logic_vector(3 downto 0);
         en : in  std_logic);
end component Decodervvhdl;
-- Declare Internal Signals which act as Input and Output to DUT
    signal clk : std_logic;     --- clock driver signal

-- Constants ---
    constant period     : time := 10 ns;
    constant update     : time := 1 ns;
    signal w : std_logic_vector(1 downto 0);
    signal y : std_logic_vector(3 downto 0);
    signal en : std_logic;

--Start of Test Bench
begin

-- Define the Clock required for simulation --
testbenchclk : process
begin
    clk <= '0';
    wait for period / 2;
    clk <= '1';
    wait for period / 2;
end process testbenchclk;

-- Instantiate DUT -----
dut:component Decodervvhdl
    port map(w  => w,
             y  => y,
             en => en);

-- Stim Loop --
 stim_loop : process
 variable expected: integer:=1;

 begin
     for i in 0 to 3 loop
         -- Apply Stim to DUT Inputs & update
             w <= CONV_STD_LOGIC_VECTOR(i,2);
             en <= '1';
         wait for update ;
         
         
         --- Check DUT response
         assert (y = CONV_STD_LOGIC_VECTOR(expected,4)) 
              report "Test Failed" &
              "stimulus =" & vec2str(w)    &
              "dut. response =" & vec2str(y) &
              "expected.response="& vec2str(CONV_STD_LOGIC_VECTOR(expected,4))
              severity error;
              
         --- Next Expected response
         expected := expected*2;
         

         -- Next Stim after a delay
         wait for period;    
     end loop;
     wait ;
 end process stim_loop;

--End of Test Bench --
end architecture Test;


Monday, June 10, 2013

FPGA Logic Synthesis

1. Shannon Expansion
2. Binary Decision Diagram
3. 

Step2a: Design of Flipflip using NOR gates in VHDL

I was reading about flip-flops in digital design yesterday. It was intriguing as how feedback circuits of gates can form a flip-flop.

Here is VHDL Code for a flip-flop:

First Attempt:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity SRFlipflop is
port 
(
    set,reset     : in std_logic;
    q, q_not     : in std_logic
);
end SRFlipflop;

architecture Behavioral of SRFlipflop is
component nor_component
    port(a, b : in  std_logic;
         y    : out std_logic);
end component nor_component;
begin

n_1:entity work.nor_component
    port map(a => set,
             b => q,
             y => q_not);
             
n_2:component nor_component
    port map(a => q_not,
             b => reset,
             y => q);


end Behavioral;




Errors: 
COMP96 ERROR COMP96_0413: "Actual of mode 'in' cannot be assigned to formal "y" of mode 'out'." "C:\Users\kvemishe\Documents\FPGA\Xilinx Course\SimpleLatch\SRFlipflop.vhd" 23 13

Second Attempt:
To fix the above problem, we make q, and qnot as "inout" rather than "out only

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity SRFlipflop is
port 
(
    set,reset     : in std_logic;
    q, q_not     : inout std_logic
);
end SRFlipflop;

architecture Behavioral of SRFlipflop is
component nor_component
    port(a, b : in  std_logic;
         y    : out std_logic);
end component nor_component;
begin

n_1:entity work.nor_component
    port map(a => set,
             b => q,
             y => q_not);
             
n_2:component nor_component
    port map(a => q_not,
             b => reset,
             y => q);


end Behavioral;


Friday, June 7, 2013

Confidence Exercises

1. Derive a scheme for subtraction of two BCD operands. Show a block diagram for the circuit
2. What is A xor 0 =? and A xor 1 = ?
3. Write circuit for building 3-to-8 decoder using N number of 2-to-4 decoders? Build 4-16 decoder using N number of 2 to 4 decoders? Write VHDL Code
4.Draw Combinatorial circuit for 4-to-2 binary enccoder using Karnaugh Map (not priority encoder).  (very tricky one)
5. Draw Combinatorial circuit for 4-to-2 priority encoder using karnaugh map (tricky one)
6. Write VHDL Code for BCD-to-7 Segment Decoder? Hint: Case Statement

Thursday, June 6, 2013

Step 2: Designing Combinatorial Circuit for Magnitude Comparator of two 4-bit numbers

I wrote code for 4 bit magnitude comparator today in VHDL and ran it through simulation. The VHDL code is straight forward and it a combinatorial circuit.

The equation for this taken from Morris Mano

magcomp.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity magcomp is
port 
(
  A : in std_logic_vector(3 downto 0);
  B : in std_logic_vector(3 downto 0);
  greater : out std_logic
);
end magcomp;

architecture Behavioral of magcomp is
  signal a3 : std_logic;
  signal x3 : std_logic;
  signal a2 : std_logic;
  signal x2 : std_logic;
  signal a1 : std_logic;
  signal x1 : std_logic;
  signal a0 : std_logic;
  signal x0 : std_logic;
begin

 a3 <= A(3) and not B(3);
 a2 <= A(2) and not B(2);
 a1 <= A(1) and not B(1);
 a0 <= A(0) and not B(0);
 
 x3 <= (a(3) and b(3)) or (not a(3) and not b(3));
 x2 <= (a(2) and b(2)) or (not a(2) and not b(2));
 x1 <= (a(1) and b(1)) or (not a(1) and not b(1));
 x0 <= (a(0) and b(0)) or (not a(0) and not b(0));
 
 greater <= a3 or (x3 and a2) or (x3 and x2 and a1) or (x3 and x2 and x1 and a0);

end Behavioral;



tb_magcomp.vhd
library ieee;
use ieee.std_logic_1164.all;
use IEEE.Std_Logic_Unsigned.all ;
use IEEE.Std_Logic_Arith.all;
use ieee.numeric_std;

use work.magcomp_pkg.all;
entity tb_magcomp is
end tb_magcomp;

architecture Test of tb_magcomp is
-- Declare/Import DUT

-- Declare Internal Signals which act as Input and Output to DUT
  signal clk : std_logic;     --- clock driver signal
  signal A : std_logic_vector(3 downto 0):=(others => '0');
  signal B : std_logic_vector(3 downto 0):=(others => '0');
  signal greater : std_logic:='0';
  signal expout: std_logic;
  constant period : time := 10 ns;
  constant update : time := 1 ns;

--Start of Test Bench
begin

-- Define the Clock required for simulation --

testbenchclk : process
  
begin
  clk <= '0';
  wait for period / 2;
  clk <= '1';
  wait for period / 2;
end process testbenchclk;

-- Instantiate DUT -----
dut:component magcomp
  port map(A       => A,
         B       => B,
         greater => greater);
-- Create Stimulus Signal  ---
stim : process

begin
wait for 0 ns;
for i in 0 to 15 loop
  A<= CONV_STD_LOGIC_VECTOR(i,4);
  for j in 0 to 15 loop
    B <= CONV_STD_LOGIC_VECTOR(j,4);
    wait for 0 ns;
        
    if (a>b) then
      expout <= '1';
      else
      expout <= '0';
    end if;
    wait for update;
    assert(greater = expout) report "incorrect answer" &"A="& integer'image(CONV_INTEGER(unsigned(a)))&"and B=" &integer'image(CONV_INTEGER(unsigned(a))) severity error;
    wait for period;
  end loop;
end loop;
wait;
--test
end process stim;

--End of Test Bench --
end architecture Test;


Note: 

a) Delta Clock Cycle:
wait for 0 ns in the loop. Wait statement is when all the concurrent signals will be updated by the simulator. This is called delta cycle. If you want values to be updated instantaneously inside the process, use variables instead of concurrent assignments when possible. without wait for 0ns, (a>b) will use old a,b values and will result in mismatch between expected result and output result

b) std_logic vector to string: 
It was very hard to print the actual values of std_logic_vector whenever there was a failure. std_logic_vector had to be converted to integer and then converted to string using image. In upcoming exercises, I plan to create a testbench_packages which will have functions to convert std_logic_vector to strings. There were lots of examples on the web and I plan to combine them into package.

Concepts to Master by end of the Journey

1) Download bitfiles toFPGA boards
2) Advanced Testing (delta clock cycle)
3) State Machines (Encoding Styles: One Hot Encoding)
4) Memory Interface
5) Modeling
6) Clock Domains (Crossing)
7) Embedded Micros
8) Communication Buses (SPI, I2C, VGA, HDMI)
9) DSP using FIR, FFT
10) Combinational Logic: Adders, Multipliers
11) Sequential Logic: Counters, LFSR, Latches, Flipflops

Wednesday, June 5, 2013

Conversions in VHDL

1. How to convert integer to std_logic_vector
Use conv_std_logic_vector

Stimulus Generation in VHDL

General Structure for Simulation


a) UUT: Test Component Instantiation
b) Signals to generate stimulus
c) assert statements 

1. A simple template for stimulus generation in VHDL is:

Here is a simple stimulus which would test a 2x2 multiplier

Notice that in the process below, there is no sensitivity list and it uses wait statements.


---------- Stimulus to DUT-----
stim:process
begin
A <= "00";
B <= "00";

wait for 10 ns;
A<= "01";
B<= "01";

wait for 10 ns;
A <= "10";
B <= "10";

wait for 10 ns;
A <= "11";
B <= "11";

 wait;

end process stim;

Note: "Wait;" is an important statement at the end. If not for this, stimulus will be generated repeatedly and will enter into infinite loop. This might be OK if it is exactly what you want.
I will update the post to have more advanced stimulus generation styles in future such as reading stimulus for text file, using python to generate stimulus.

1a. Improvement# 1

A little bit better approach to above stimulus generation is shown below. We declare a constant which is called "period" with default value of 10 ns.

---------- Stimulus to DUT-----
stim:process
constant period: time := 10 ns;
begin
A <= "00";
B <= "00";
wait for period;
A<= "01";
B<= "01";

wait for period;
A <= "10";
B <= "10";

wait for period;
A <= "11";
B <= "11";

wait;

end process stim;

2. Improvement #2

While the above example 1a shows how to create stimulus, it lacks code check the response from the dut and ensure that it is indeed working as expected. How do we check correctness of the response?

One approach is to use assert statements
assert (dut response = expected response); If dut response is not equal to expected response, assert will throw an error.

e.g., for stimulus wait for 10 ns;
A<= "01";
B<= "01";

We expect the output to be 0001. So, we would write the statement as
assert (P = "0001") report "TEST FAILED";
An example code is shown below:
---------- Stimulus to DUT-----
stim:process
constant period: time := 10 ns;
constant update: time := 1  ns;
begin

-- Case#1:
wait for period;
A <= "00";
B <= "00";
wait for update;
assert (P = "0000")report "TEST FAILED" severity error;

-- Case#2:
wait for period;
A<= "01";
B<= "01";
wait for update;
assert (P = "0001")report "TEST FAILED" severity error;

-- Case#3:
wait for period;
A <= "10";
B <= "10";
wait for update;
assert (P = "0010") report "TEST FAILED" severity error;

-- Case#4:
wait for period;
A <= "11";
B <= "11";
wait for update;
assert (P = "1001") report "TEST FAILED" severity error;

wait;
end process stim;


3. Improvement#3

While the above approach is nicely structured, it is cumbersome to write all the statements every time. Also, there is a regularity in the stimulus vector. A better approach would be to store all the stimulus elements in a vetcor/array and read the stimulus from vector/array using a for loop

---------- Stimulus to DUT-----
stim:process
constant period: time := 10 ns;
constant update: time := 1  ns;
begin

--- Apply Stimulus recursively
for i in 0 to 3 loop
    wait for period;
    A <= CONV_STD_LOGIC_VECTOR(i,2);
    B <= CONV_STD_LOGIC_VECTOR(i,2);
    wait for update;
    assert (P = i*i)report "TEST FAILED" severity error;
end loop;

wait;
end process stim;

In this case I have shown how you could create stimulus on the fly using for loop and apply to the DUT. However, there will be situations where you want to precalculate the stimulus through some other code and store in file.

Note: For some debugging purposes, you want to print out the input values when a test case fails. Often times, the input value is a std_logic_vector. To convert std_logic_vector use "integer'image(CONV_INTEGER(unsigned(a)))"

4. Improvement# 4: Make a Simpkg, printing objects in VHDL
Start adding all the utility functions for testbenches such as vec2str, std2str into a package so that it can be reused. To print variable i of integer type use, integer'image(i);

Tutorial: Printing Objects in VHDL
http://www-ee.uta.edu/Online/Zhu/spring_2007/tutorial/how_to_print_objexts.txt

5. Improvement# 5: Assert in multiple lines

Assert statement in VHDL by default only allows one line. To break it into multiple lines use concatenate  (&) operator

e.g.,  assert (y= remainder(0)) 
  report "Test Failed" &
  "dut y =" & std2str(y) & " expected y =" & std2str(remainder(0))

  severity error;

5. Random Value Stimulus in VHDL Testbenches
The IEEE "math_real" VHDL package supplies a function called "UNIFORM" which returns a pseudo-random number (of type REAL) in the range 0 to 1.0. 

Using Packages in VHDL

Today, I was playing with code to write 2 x 2 multiplier. In the process of writing code for the multiplier, I had to use couple of full adders and half adders. Normally, I would write code for the full adder and half adder in separate files and declare them as components in my main file.

Code Style #1: mult2x2.vhd

library ieee;
use ieee.std_logic_1164.all;
use work.adderpackage.all;

entity mult2x2 is
    port (
        A,B    :    in        std_logic_vector(1 downto 0);
        P    :    out        std_logic_vector (3 downto 0)
    );
end entity mult2x2;

architecture RTL of mult2x2 is
    signal p00,p10,p01,p11: std_logic;
    signal c1,c2:std_logic;
    
    --- Full Adder Circuit
    component fa
        port(a, b, cin : in  std_logic;
             s, cout   : out std_logic);
    end component fa;
    
-- Half Adder Circuit
    component ha
        port(a, b    : in  std_logic;
             s, cout : out std_logic);
    end component ha;
begin

p00 <= A(0) and B(0);
p01 <= A(1) and B(0);
p10 <= A(0) and B(1);
p11 <= A(1) and B(1);

P(0) <= p00;
S0:component ha
    port map(a    => p01,
             b    => p10,
             s    => P(1),
             cout => C1);
             
S2:component ha
    port map(a    => C1,
             b    => p11,
             s    => P(2),
             cout => c2);
P(3) <= c2;

end architecture RTL;



However, adding the component instantiations into the main code makes the code look bloated. To simply the code, we can put the component declaration into packages (very similar to header file) and import the package (header file) into main code.

The code below shows how it is done:
Coding Style #2: Mult 2x2


library ieee;
use ieee.std_logic_1164.all;
use work.adderpackage.all;

entity mult2x2 is
    port (
        A,B    :    in        std_logic_vector(1 downto 0);
        P    :    out        std_logic_vector (3 downto 0)
    );
end entity mult2x2;

architecture RTL of mult2x2 is
    signal p00,p10,p01,p11: std_logic;
    signal c1,c2:std_logic;
begin

p00 <= A(0) and B(0);
p01 <= A(1) and B(0);
p10 <= A(0) and B(1);
p11 <= A(1) and B(1);

P(0) <= p00;
S0:component ha
    port map(a    => p01,
             b    => p10,
             s    => P(1),
             cout => C1);
             
S2:component ha
    port map(a    => C1,
             b    => p11,
             s    => P(2),
             cout => c2);
P(3) <= c2;

end architecture RTL;


adderpackage.vhd
library ieee;
use ieee.std_logic_1164.all;

package adderpackage is

--- Full Adder Circuit
  component fa
    port(a, b, cin : in  std_logic;
       s, cout   : out std_logic);
  end component fa;
  
-- Half Adder Circuit
  component ha
    port(a, b    : in  std_logic;
       s, cout : out std_logic);
  end component ha;
    
end package adderpackage;

package body adderpackage is
  
end package body adderpackage;

Other interesting VHDL and FPGA Blogs

1. FPGALink for USB Communication

2. Got an interesting FPGA Coding/ Design Philosophy Issue?
check out to see if Jan has take on it.

I like his take on integers vs std_logic_vectors for counters in VHDL.

3. Good HDL Design Practices from Industry Expert
http://fpga-hdl.blogspot.com/

4. Some interesting open source fpga cors
opencores.org

5. Innovation in FPGAs
http://tcfpga.org/

Editors for vhdl coding

1. Sigasi

2. Veditor

Tuesday, June 4, 2013

Arithmetic Circuits on FPGA

Exercises to do in VHDL

1) Write code for 4x4 Array Multiplier in VHDL, serial multiplier in VHDL
2) Write code to check for sequence in VHDL
3) Write code for bubble sort in VHDL
4) VGA output in 7 slices

FPGA Interview Questions

1. I found some good VLSI questions at this website
        - Design full adder using half adder
2. What are gray codes?
3. What is Gray Code Counter, Binary Counter, Johnson Counter, Ring Counter?
4. What is a Linear Feedback Shift Register (LFSR) and where is it used?
5. What are the advantages of gray code counter?
6. Write code for 4-bit adder in VHDL with carryin, carryout and arithmetic overflow
advanced: Arithmetic Overflow detection code
7. How do you design 3-bit comparator if a and b are signed numbers?
8. Make a digital circuit that takes a BCD digit as input and produces the output that is equal to 5 times the digit in same format. Soln:
9. What are the different type of overloading in VHDL? Soln:
Ans: Literal Overloading, Operator Overloading, Subprogram Overloading
10. Why are multiplexers typically designed with 2^N inputs?
Ans: This is because "select input" pins of multiplexer requires log (inputs).
11. Draw circuit for building 4:1 multiplexer using 2:1 multiplexer?
12. What is Shannon's Expansion Theorem?
13. What is one-hot encoding? Hint: Decoder Output
14. What are static hazards and dynamic hazards?
15.What does NULL in case statement do?


Questions at other websites:
1. http://www.vlsibank.com/sessionspage.asp?titl_id=6069
2. http://electronicsbus.com/vlsi-jobs-fpga-design-jobs-vhdl-interview-questions/

Monday, June 3, 2013

Web Classes on FPGA and VHDL

1) Class at UCR
2) Class at NYU
3) Class at WPI
4) Advanced FPGA Class at WPI
5) Digital Logic Lab at SUNY
6) CSE45208 at SUNY
7) EECS150: Components and Design Techniques for Digital Systems (UC Berkeley)
8) CS150: FPGA Course at UC Berkeley by Ed Aalon
9) EE458/478: HDL Based Digital Design with Programmable Logic (Second Course)
10) EE459/500: HDL Based Digital Design with Programmable Logic (Latest Version)
11) FPGA and ASIC Design with VHDL (George Mason Univeristy)
12) Introductory Digital Systems Lab at MIT 
13) EE762: Theory and Design of Computers
14) ECT 466: Microcomputer Architecture (Good Exercises using Microblaze)
15) ECEN 449: Microprocessor System Design (Xilinx Embedded and Linux Programming)
16) ECEN427 at BYU (DMA and FPGA)
17) CS352H @ UT Austin
18) MIT Lab Kit (Additional Examples to Play)

VHDL Resources

Book References

1) Rapid Prototyping of Digital Systems, by Hamblen, James etal. Springer 2008 (online link)
2) Digital Design: Principles and Practices Package by Wakerly (Amazon Buy Link)


Online References

1) Good website on VHDL Projects and Tutorials
John's FPGA Page

2) Good VHDL Power Point Tutorials
CENG340

3) Good website on VHDL Testbenches and Verification
Stefan's webpage

4) Good VHDL website for beginners
Ask AdamVHDL

5) Green Mountain VHDL Tutorial

4) Another good blog on VHDL and FPGA: noasic.com

5) FPGA FAQs

Video Tutorial References

1. https://www.youtube.com/watch?v=UJlgND6sWHk&list=PLB0255B9D637FF445
2.

Saturday, June 1, 2013

Books on Digital Design, FPGA and VHDL

I have started compiling list of books I found that were enjoyable for digital design.

1) Digital Design by Morris:
I found that this book very useful to build basic digital design skills before starting off VHDL.

The chapters on Karnaugh Map were  very useful. I will be reading some more chapters soon...

2) Digital Electronics: A Practical Approach with VHDL (Bill Klietz)
You can find his videos on youtube also.
http://www.amazon.com/Digital-Electronics-Practical-Approach-VHDL/dp/0132543036

3) Design Recipes for FPGAs: Using Verilog and VHDL (Peter Wilson)
Discusses Cameralink

TestBenches

1. Writing Testbenches: Functional Verification of HDL Models (Janick Beregeron)

Additional Books to read:

1) Digital Electronics and Design with VHDL by Pedroni
The preview shows that State Machines were simplified. Any book which simplifies State Machines in VHDL are books of ineterest for me.

2) Fundamental of Digital Logic Design with VHDL design (Stephen Brown)
Solution Manual
Seems to have similar content as Morris Mano

3) VHDL Coding Styles and Methodologies (Ben Cohen)

4) Digital Design and Computer Architecture (Harris and Harris)

4)  VHDL for logic synthesis (Andrew Rushton)

5) Essential VHDL: RTL Synthesis Done Right (Sundar Rajan)

6) Computer Arithmetic: Algortihms and Hardware Design (Behrooz Parhmani)
Behrooz Parmani's website

7) RTL Hardware Design using VHDL: Coding for Efficiency, Portability, Scalability (Pong P.Chu)

8) Reuse Methodology Manual for System-on-a-Chip Designs (Pierre Bricaud)

8)  Contemporary Logic Design (Randy H. Katz)

8) Computer Organization: The Hardware Software Interface (David Patterson)
9) M.J. Flynn, Computer Architecture: Pipelined and Parallel Processor Design
10) Architectures for Digital Signal Processing by Peter Pirsch

Digital Electronics Videos