2
\$\begingroup\$

I just started VHDL today and I'm the type of person that can only learn by doing stuff, so after I made some basic gates in VHDL, I tried making a simple D-latch(so no clock signal), however without success. I get all kinds of errors such as in1 not defined, std_logic not defined, etc.

Here is my code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dflip is

end dflip;

architecture structural of dflip is

    component AND2
        port (in1, in2:in std_logic; out1: out std_logic);
    end component;

    component OR2
        port (in1, in2:in std_logic; out1: out std_logic);
    end component;

    component NOT1
        port (in1: in std_logic; out1: out std_logic);
    end component;

    signal D, E, E_NOT, Q, OUT_AND1, OUT_AND2: std_logic;

begin   
    U0: NOT1    port map (E, E_NOT);
    U1: AND2    port map (E, D, OUT_AND1);
    U2: AND2    port map (E_NOT, Q, OUT_AND2);
    U3: OR2     port map (OUT_AND1, OUT_AND2, Q);
end structural;


entity NOT1 is
    port (in1: in std_logic; out1: out std_logic);
end NOT1;

architecture behavioral_not of NOT1 is
begin
    out1 <= not in1;
end behavioral_not;


entity AND2 is
    port(in1, in2: in std_logic; out1: out std_logic);
end AND2;

architecture behavioral_and2 of AND2 is
begin

    out1 <= in1 and in2;

end behavioral_and2;


entity OR2 is
    port (in1, in2: in std_logic; out1: out std_logic);
end OR2;

architecture behavioral_or of OR2 is
begin
    out1 <= in1 or in2;
end behavioral_or;

I made it structural, because I could not make it to work behavioral, because it seems I cannot use if statements if I write behavioral(makes sense). The problem is with that Q output which needs to be connected back to the input of an AND gate.

So how do I do this?

\$\endgroup\$
  • \$\begingroup\$ The code between 'ARCHITECTURE ... BEGIN' and 'END ...' is concurrent. Each line like 'U0 : NOT port map' is re-evaluated by the simulator each time an event (for example a transition) occurs on one of the inputs. Code order is irrelevant. Sequential parts (like 'traditional' imperative code) must be inside PROCESS declarations. Unlike C code, there is no problem with 'using a variable before assigning it', as long as the signal is assigned somewhere. \$\endgroup\$ – TEMLIB Mar 15 '15 at 17:47
2
\$\begingroup\$

Latches and flip-flop can't be modeled with logic gates in VHDL, this is for analog simulators only! The feedback logic doesn't bode well with the VHDL simulator. Furthermore, no synthesiser would recognize it as a latch/flip-flop.

To instantiate a latch/flip-flop, you can either instantiate your vendor's primitives or use this generic code:

LATCH: process(en, d)
begin
    if en = '1' then
        q <= d;
    end if;
end process LATCH;

DFF_ASYNC: process(rst, clk)
begin
    if rst = '1' then
        q <= '0';
    elsif rising_edge(clk) then
        q <= d;
    end if;
end process DFF_ASYNC;

DFF_SYNC: process(clk)
begin
    if rising_edge(clk) then
        if rst = '1' then
             q <= '0';
        else
             q <= d;
        end if;
    end if;
end process DFF_SYNC;

Use logic gates for combinational circuits only. If you want a challenge, you may be better with simulating ALU logic then synchronous elements. As a final note, keep in mind that using logic gates to design circuits is reserved for masochists, most VHDL designer use higher level construct that are easier to read and to debug.

Update

Apparently, latches can be simulated in VHDL using logic gates (thanks @David Koontz). Look at his answer to see how!

\$\endgroup\$
  • \$\begingroup\$ Thanks a lot! By higher level constructs you mean using behavioral models? \$\endgroup\$ – Calin Mar 15 '15 at 18:09
  • 1
    \$\begingroup\$ I mean RTL (register transfer level). It's a model where you describe registers (using my sample code) and how they are connected. As an example, an adder would have registers x, y and s and the statement s <= x + y enclosed in a rising_edge statement. I consider behavioral VHDL code that is not synthesisable. \$\endgroup\$ – Jonathan Drolet Mar 15 '15 at 18:17
6
\$\begingroup\$

It is possible to generate a structural gate model of a D latch in VHDL. Take a page out of PLD design where we find it requires a consensus term:

library ieee;
use ieee.std_logic_1164.all;

entity not1 is
    port ( 
        in1:    in  std_logic;
        outp:   out std_logic
    );
end entity;

architecture foo of not1 is

begin
    outp <= not in1;
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity and2 is 
    port (
        in1:    in  std_logic;
        in2:    in  std_logic;
        outp:   out std_logic
    );
end entity;

architecture foo of and2 is

begin
    outp <= in1 and in2;
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity or3 is 
    port (
        in1:    in  std_logic;
        in2:    in  std_logic;
        in3:    in  std_logic;
        outp:   out std_logic
    );
end entity;

architecture foo of or3 is

begin
    outp <= in1 or in2 or in3;
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity dlatch is
    port (
        d:  in  std_logic;
        en: in  std_logic;
        q:  out std_logic
    );
end entity;

architecture fum of dlatch is

    signal not_en:      std_logic;
    signal w1, w2, w3:  std_logic;
    signal q_int:       std_logic;

    component not1 is
        port (
        in1:    in  std_logic;
        outp:   out std_logic
        );
    end component;

    component and2 is
        port (
        in1:    in  std_logic;
        in2:    in  std_logic;
        outp:   out std_logic
        );
    end component;    

    component or3 is
        port (
        in1:    in  std_logic;
        in2:    in  std_logic;
        in3:    in  std_logic;
        outp:   out std_logic
        );
    end component;

begin
U0:
    not1 
        port map (
        in1 => en,
        outp => not_en
        );
U1:
    and2
        port map (
        in1 => q_int,
        in2 => not_en,
        outp => w1
        );

U2:
    and2
        port map (
        in1 => d,
        in2 =>  en,
        outp => w2 
        );

U3: -- consensus term
    and2
        port map (
        in1 =>  d,
        in2 => q_int,
        outp => w3
        );

U4:
    or3
        port map (
            in1 => w1,
            in2 => w2,
            in3 => w3,
            outp => q_int
        );

    q <= q_int;

end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity dlatch_tb is
end entity;

architecture test of dlatch_tb is
    signal d:   std_logic := '0';
    signal en:  std_logic := '0';
    signal q:   std_logic;

    component dlatch is
        port (
            d:  in  std_logic;
            en: in  std_logic;
            q:  out std_logic
        );
    end component;

begin
DUT:
    dlatch
        port map (
            d => d,
            en => en,
            q => q
        );
STIM:
    process
    begin
        wait for 10 ns;
        en <= '1';
        wait for 10 ns;
        en <= '0';
        wait for 10 ns;
        d <= '1';
        wait for 10 ns;
        en <= '1';
        wait for 10 ns;
        en <= '0';
        wait for 10 ns;
        wait;
    end process;
end architecture;

The structural architecture using instantiated gates produces:

dlatch_tb structural.png (clickable)

Latches and flip-flop can't be modeled with logic gates in VHDL, this is for analog simulators only!

The moral of the story is that you can't always separate opinion from knowledge or experience in answers here. This little tidbit can be found in Digital Design Principles and Practices, 3rd edition by John F. Wakerly, 8.2.6 Registers and Latches in ABEL and PLDs, least digital design become a lost art. It used to be common knowledge when digital design was dominated by PLDs (PALs).

Without the consensus term the output will oscillate. There are other ways of stopping the oscillation which is caused by the delta cycle delay through the not1. This is one of at least two ways that a structural design can both be simulated and implemented.

And of course the big question is just how many real digital designers are needed in the world today? Knowledge and experience comes from solving real world problems and as the accepted answer points out however indirectly it isn't necessary to know there is an answer in VHDL.

For those with an actual need to digital design with structural elements it might be useful to google for hazard logic and/or consensus term along with digital design.

This particular one comes to mind because it was once an interview question for a job doing digital design in VHDL in an era of more primitive synthesis tools and slower simulations, meaning digital design experience counted for more.

If you look and the meat and potatoes part of the latch accomplished with three AND gates and one OR gate. We see that this is also called an Earle latch:

Earle Latch

This image taken from Page 40 of The Microarchitecture of Pipelined and Superscalar Computers, 1999 by Amos R. Omandi. The book and the Earle latch link tell us we can embed an Earle latch in other AND OR structures (like Carry Look Ahead Adders) and the history, used on an IBM 360/91 in the early 1960's.

The consensus term, the middle AND gate in the figure above overcomes the equal number of gates delay (or delta simulation cycle delays in a zero timed model) in the feedback path, preserving a '1' on the output when the input is also a '1'.

In the VHDL design shown above the not1 inverter also provides that feedback unsettling, at least in one direction, if the not1 output had been used by the dlatch d input AND gate (U2) - in other words if the latch had been supplied externally with not_en and produced en via the inverter not1.

Use in hiding latches in existing AND OR structures is predicated on a wide number of terms that is somewhat atypical for early CPLDs (PALs) an advantage we don't have in FPGAs today, which implement other carry chain implementations in any event. It doubles the number of terms.

You can eliminate the need for consensus terms in RS based latches and flip flops by unbalancing the feedback delays between the R and S sides, typically by adding delay (as in a gate delay). This affects set up and hold times.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the correction, as you can probably tell, I only touched a PAL in logic classes, before I learned about VHDL and FPGAs. Do you know if this would mapped to a latch primitive on any synthesizer? \$\endgroup\$ – Jonathan Drolet Mar 16 '15 at 20:23
  • \$\begingroup\$ I wouldn't bet it would map to a latch primitive anywhere. It should generate a working latch based on an three term AND OR structure. The driving reason it was well known in PLDs/PALs has to do with scarcity of resources, there's generally no reason in an FPGA today. You can also use consensus terms to get gate level models of flip flops to work. For the behavioral latch q_int <= (q_int and not en) or (d and en); works just fine, because there is no delta cycle delay needing consensus term coverage. \$\endgroup\$ – user8352 Mar 16 '15 at 23:47
0
\$\begingroup\$

If you want structural design then component instantiation is the way to go but one really does not model latch using structural modeling. Behavioral is easier and you can use if statement for this method. Take a look at this video-

http://appliedelectronicsengineering.blogspot.com/2015/10/how-to-implement-d-latch-in-vhdl.html

\$\endgroup\$
  • 1
    \$\begingroup\$ Please summarize some of the information in the video. \$\endgroup\$ – Null Oct 22 '15 at 2:38
0
\$\begingroup\$

Latches can be modeled in many ways in VHDL, including with logic gates; and the VHDL code thus produced can be synthesised (at least with Synplify Pro).

The reported error messages,

in1 not defined, std_logic not defined, etc.

indicate that the error is missing library and use clauses. Indeed, basically the only thing I did to correct your code was to add those before every entity declaration. Here is the corrected code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity NOT1 is
port (in1: in std_logic; out1: out std_logic);
end;

architecture behavioral_not of NOT1 is
begin
    out1 <= not in1;
end;


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity AND2 is
port (in1, in2: in std_logic; out1: out std_logic);
end;

architecture behavioral_and2 of AND2 is
begin
    out1 <= in1 and in2;
end;


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity OR2 is
port (in1, in2: in std_logic; out1: out std_logic);
end;

architecture behavioral_or of OR2 is
begin
    out1 <= in1 or in2;
end;


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dflip is
port (D, E: in std_logic; Q: out std_logic);
end;

architecture structural of dflip is
    signal E_NOT, Q_int, OUT_AND1, OUT_AND2: std_logic;
begin   
    U0: entity work.NOT1
    port map (E, E_NOT);
    U1: entity work.AND2
    port map (E, D, OUT_AND1);
    U2: entity work.AND2
    port map (E_NOT, Q_int, OUT_AND2);
    U3: entity work.OR2
    port map (OUT_AND1, OUT_AND2, Q_int);

    Q <= Q_int;
end;

As a bonus, let us see a shorter implementation of the unclocked D latch, with the same gates, but without separate entities for each gate:

architecture short of dflip is
    signal Q_int: std_logic;
begin
    Q_int <= (D and E) or (not E and Q_int);
    Q <= Q_int;
end;

Note that in practice you would almost surely use clocked, edge triggered flipflops instead of latches. Those can be nicely expressed with conditional signal assignment:

Q <= D when rising_edge(clock) and E = '1';
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.