Saturday, August 24, 2013

Bachelor's level coursework rtl codes

These are the vhdl labs from my BE E&TC course VLSI design. I was in the 4th year of engineering at that time. Having seen the undergrad coursework from my Master's university in the US, these seem too childish assignments. Its high time we revamp the course, and really really notch up the difficulty level of the course. Engineering colleges in India pop up like mushrooms, and the whole system is a disaster. Around 6 lakh students of my batch graduated from Engineering in Maharashtra alone!!

//-----------2 bit comparator------------
// This blog is not meant to spoon feed any juniors to a ready made code.
// Please write the truth table yourself, and that is your dataflow architecture for the comparator.
altb = a1b.b1 + a1b.a0b.b0 + b1.b0.a0b
aeqb = (a1 exnor b1).(a0 exnor b0)
agtb = a1.b1 + a1.a0.b0b + b0b.b1b.a0

architecture behav of 2bcomp is
begin
process (a,b)
begin
    if (a=b) then
        aeb<='1'; agb <='0'; alb<='0';
    elsif (a<b) then
        aeb<='0'; agb <='0'; alb<='1';

    elsif (a>b) then
        aeb<='0'; agb <='1'; alb<='0';

    else
        aeb<='0'; agb <='0'; alb<='0';

        end if;
end process;
end behav;

struct: define for exor, or3, inv, and3
declare as components, connect using port map


//------------delay ff-------------------//
clear input: highest priority

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity DFF is
    port( D, clk, pre, clr: in STD_LOGIC;
          q, qb: out STD_LOGIC);
end DFF;

architecture DFF of DFF is
signal s: std_logic;
begin
    process(D, clk, pre, clr, s)
    begin
        if clr='0' then s<='0';
        else if pr='1' then s<='1';
             else if clk'event and clk='1' then s<=d;
                   end if;
             end if;
        end if;
    end process;
    q<=s;
    qb<=not s;
end DFF;

//-----T FF: T = 1 output toggles-------//

architecture TFF of TFF is
signal s: std_logic;
begin
    process(T, clk, pre, clr, s)
    begin
        if clr='0' then s<='0';
         elsif clk'event and clk='1' then
            if pre='1' then s<='1';
            elsif t='1' then s<= not s;
            else s<=s;
                end if;
        end if;
    end process;
    q<=s;
    qb<=not s;
end TFF;

Note: D-FF is already a component of FPGAs. 
T FF using D FF
clr =0, pre =0, clk = rising: T=0 q+ = q
                  T=1 q+ = qb
feedback D-FF q to input thru XOR

//----------shift resi--------------//
entity shift is
    port ( clk, clr, load, dir, bs: in std_logic;
        din: in STD_LOGIC_VECTOR(3 downto 0);
        dout: out STD_LOGIC_VECTOR(3 downto 0));
end shift;

architecture shift of shift is
signal s: STD_LOGIC_VECTOR(3 downto 0);
begin
    process(clk, clr, load, dir, bs, din, s)
    begin
        if clr='0' then s<="0000";
         elsif clk'event and clk='1' then
            if load='1' then s<=din;
            elsif bs='0' then
                if dir='1' then s<=s(2 downto 0) & '0';
                else s<='0' & s(3 downto 1);
                end if;
            else
                if dir='1' then s<=s(2 downto 0) & s(3);
                else s<=s(0) & s(3 downto 1);
                end if;
            end if;
        end if;
    end process;
    dout<=s;
end shift;


//--------up/down adder------------//
entity cntr is
    port (clk, rst, sel, load: in STD_LOGIC;
        din: in STD_LOGIC_VECTOR(3 downto 0);
        dout: out STD_LOGIC_VECTOR(3 downto 0));
end cntr;

architecture behave of cntr is
signal count: STD_LOGIC_VECTOR(3 downto 0);
signal clk1: std_logic;
signal count1: STD_LOGIC_VECTOR(19 downto 0);
begin
    process(clk1, rst)
    begin
        if(rst='0') then count<="0000";
        elsif (clk1='1' and clk1'event) then
            if load='0' then count<=din;
            elsif load='1' then count<=count;
            end if;
           
            if(sel='0') then count<=count+1;
            elsif(sel='1') then count<=count-1;
            end if;
        end if;
    end process;
    dout<=count;

    process(clk)
    begin
        if (clk='1' and clk'event) then
            count1<=count1+"0000_0000_0000_0000_001";
        end if;
        clk1<=count1(19);
    end process;
end behave;

//----------bidi buffer---------------------//
architecture bidi_buf of bidi_buf is
begin
    b<=a when (mode='1')
    else "zzzz";
    a<=b when (mode='0')
    else "zzzz";
end bidi_buf;

//-----------Traffic light controller FSM------------//
Description: green path 1: 20 sec, other 3 paths: red
yellow: 5 sec
green path 2: on 20 sec, other 3 red n so on


I need to code FSM and D-FF day in and day out at work. But my "highly accredited" Bachelor's engineering course never taught me to code FSM. :x 
My coursework took a shortcut approach to generated code from the tool using state diagram.

2 fsms in total: 1st is 8 state fsm outputs of which control the 12 lights
2nd is a clock gen
Reset -> S0 clk=0 -> S1 clk=0 -> S2 clk=0 -> S3 clk=0 ->
S4 clk=0 -> S5 clk=0 -> S6 clk=0 -> S7 clk=1 ->
S8 clk=1 -> S9 clk=0 -> S10 clk 1 -> S0

//------------FSM as generated by the tool-----------
entity traffic is
port (clk, rst: in std logic;
    light: out STD_LOGIC_VECTOR911 downto 0));
end traffic;

architecture arch of traffic is

signal clk2: STD_LOGIC;

type Sreg0_type is (S1, S2, S3, S4, S5, S6, S7, S8);
signal Sreg0: Sreg0_type;

FSM1: process (clk2, rst)
begin
    if rst='1' then Sreg0 <= S0;
    elsif clk2'event and clk2='1' then
        case Sreg0 is
            when S0 => Sreg0 <= S1;
            when S1 => Sreg0 <= S2;
            when S2 => Sreg0 <= S3;
            when S3 => Sreg0 <= S4;
            when S4 => Sreg0 <= S5;
            when S5 => Sreg0 <= S6;
            when S6 => Sreg0 <= S7;
            when S7 => Sreg0 <= S0;
            when others => null;
        end case;
    end if;
end process;

light <= "100_001_001_001" when (Sreg0 = S0) else
     "010_001_001_001" when (Sreg0 = S1) else
     "001_100_001_001" when (Sreg0 = S2) else
     "001_010_001_001" when (Sreg0 = S3) else
     "001_001_100_001" when (Sreg0 = S4) else
     "001_001_010_001" when (Sreg0 = S5) else
     "001_001_001_100" when (Sreg0 = S6) else
     "001_001_001_010" when (Sreg0 = S7) else


FSM2: process (clk, rst)
begin
    if rst='1' then Sreg1 <= SS0; clk2<= '0';
    elsif clk'event and clk='1' then
        case Sreg1 is
            when SS0 => Sreg1 <= SS1; clk2<= '0';
            when SS1 => Sreg1 <= SS2; clk2<= '0';
            when SS2 => Sreg1 <= SS3; clk2<= '0';
            when SS3 => Sreg1 <= SS4; clk2<= '0';
            when SS4 => Sreg1 <= SS5; clk2<= '0';
            when SS5 => Sreg1 <= SS6; clk2<= '0';
            when SS6 => Sreg1 <= SS7; clk2<= '0';
            when SS7 => Sreg1 <= SS8; clk2<= '0';
            when SS8 => Sreg1 <= SS9; clk2<= '1';
            when SS9 => Sreg1 <= SS10; clk2<= '0';
            when SS10 => Sreg1 <= SS0; clk2<= '1';
            when others => null;
        end case;
    end if;
end process;
end arch;


//--------------Static RAM----------
holds data till power is there, dynamic ram: needs refresh
ram contains address decoders, memory address array, out_en, rd/wrb

architecture behav of ram is
type vector_array is array (0 to 255) of std_logic_vector(7 downto 0);
signal memory: vector_array;
begin
    process(clk, rwb)
    begin
        if rwb='0' then
            if clk'event & clk='1' then
                memory(addr)<=data_in;
            end if;
        else
            if clk'event & clk='1' then
                data_out <= memory(addr);
            end if;
        end if;
    end process;
end behav;

synchronous read would allow you to use existing block RAM resources in FPGA for optimum device usage, improved timing.

Disclaimer: This is not even my code! I do not take any responsibility for its correctness. There are many better ways to code the same stuff esp the FSM. Please google for coursework from other Engineering colleges abroad/ use code examples from good authors like Frank Vahid etc.