0
votes

I have a system that has a 3 input D_in which is read at every positive clk edge. If say I want to see if the current input, D_in is greater then the previous D_in by at least 2, then a count will increment. How do I write this in VHDL?

if clk'event and clk = '1' then  --read at positive edge
if D_in > (D_in + 010) then  <---I am sure this is wrong. How to write the proper code?   

Entity ABC is
Port(D_in: in std_logic_vector(2 downto 0);
     Count: out std_logic_vector(2 downto 0));
Architecture ABC_1 of ABC is
    signal D_last: std_logic_vector(2 downto 0); 
Begin
     Process(D_in)   
         D_last <= D_in;
         if clk'event and clk = '1' then
         if D_last > (D_in + 2) then
         count <= count + 1;
end if;
end process; 
end ABC_1;
2
If D_in, D_last are numeric_std.unsigned signals, then D_last <= D_in; if D_in > D_last + 2 then ... inside your clocked part will do nicely.user_1818839
Sorry, but where do I declare D_last as? In the variable?Morde
I said it was a signal. If you declare D_last a variable, you have to interchange the order of the statements. Read up on the differences between signal and variable assignments to see why. For example, here : stackoverflow.com/questions/13954193/…user_1818839
Hi, I have updated the code. Is that right? Or do I need to put the D_last<= D_in before the if statement? Anyways, for the count output, I need to increment it if D_last > D_in+2. Do I need to create a signal to store the counter when it increases? Sorry for the many questions man! I just pick up VHDL.Morde

2 Answers

1
votes

The "good" way to write this process is as follow :

process (clk)
begin
  if (rising_edge(clk)) then
    -- store the value for the next time the process will be activated
    -- Note that D_last value will be changed after the whole process is completed
    D_last <= D_in;   

    -- compare the actual D_in value with the previous one stored in D_last. 
    -- D_last value is its value at the very beginning of the process activation
    if (D_in > D_last + 2) then   
      -- increment the counter
      count <= count + 1;
    end if;
  end if;
end process;

Note that D_in, D_last and count has to be declared as unsigned and not as std_logic_vector.

I suggest you to read this post which explains how a process actually works : when are signals updated and which signal value is used into the process.

Cheers

[edit] This answer should be fine for your question. But the code you show has other errors :

  • The signal clk has to be an input for your entity.
  • The signal count can't be read in your architecture because it's defined as output in the entity. Then the line "count <= count + 1" can't be resolved. You have to use an internal signal and then assign its value to "count" outside of a process :

    count <= count_in;

0
votes

There are several other errors in your design specification as well. This answer attempts to answer all concerns in one place.

VHDL is simulated by executing processes in simulation cycles. Every concurrent statement can be expresses as either an equivalent process statement or combination of process statements and block statements.

Signal assignment is to a projected output waveform queue for a specified time. When no time is specified it's the current time, and the value will be updated prior to executing processes in the next simulation cycle, a delta cycle, simulation time is advanced when there are no remaining events scheduled for the current simulation time.

To avoid confusion over when signal assignments occur, view them as separate processes (whether you express them that way or not).

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity abc is
    port (
        clk:    in  std_logic;       -- Note 1
        d_in:   in  std_logic_vector(2 downto 0);
        count:  out std_logic_vector(2 downto 0)
    );
end entity;   -- Note 2

architecture foo of abc is
    signal d_last: std_logic_vector(2 downto 0); 
begin

DLAST:                        -- Note 3
     process (clk)   
     begin
         if rising_edge(clk) then   -- Note 4
             d_last <= d_in;
         end if;
     end process; 

INC_COUNT:
    process (clk)
        variable cnt: unsigned(2 downto 0) := "000";  -- Note 5
    begin
        if rising_edge(clk) and 
                unsigned(d_last) >  unsigned(d_in) + 2 then  -- Mote 6,7
            cnt := cnt + 1;
        end if;
        count <= std_logic_vector(cnt);
    end process;

end architecture;

Notes

  1. Missing clk from port interface
  2. Missing end statement for entity ABC.
  3. Conceptually view D_last register separately from Count counter sensitive to clk. (Can be merged as one process)
  4. rising_edge function expresses clk'event and clk = '1' ('event and "=" are both functions)
  5. The counter must represent a binary value for "+" to produce a binary result
  6. "+" is higher priority than ">", which is higher priority than "and" (you don't need parentheses)
  7. Package numeric_std provide relational and adding operators for
    type sign and type unsigned, requiring type conversion for D_last
    and D_in.

    Alternatively use Synopsys package std_logic_unsigned which depends on Synopsys package std_logic_arith and treats std_logic_vector as unsigned. This avoids type conversion, and allows array types to be declared as type std_logic_vector.

The variable cnt can be done away with if port count were to be declared mode buffer and provided a default value:

        count:  buffer std_logic_vector(2 downto 0) :="000" -- Note 5

and

INC_COUNT:
    process (clk)
    begin
        if rising_edge(clk) and
                unsigned(d_last) >  unsigned(d_in) + 2 then  -- Note 6,7
            count <= std_logic_vector(unsigned(count) + 1);
        end if;
    end process;

You can't use Count as mode out to algorithmically modify it's own value. The ability to access the value of a mode out port is intended for verification and is a IEEE Std 1076-2008 feature.

And about now you can see the value of Synopsys's std_logic_unsigned package, at least as far avoiding type conversions.

Also, i got another question. If d_in is 0 for 3 consecutive clk cycles, i want to reset count to 0. How do i write the code to represent for 3 clk cycles?

Add another pipeline signal for D_in:

    signal d_last:  std_logic_vector(2 downto 0) := "000";
    signal d_last1: std_logic_vector(2 downto 0) := "000";

Note these also have default values, which FPGA synthesis will generally honor, it's represented by the state of the flip flop in the bistream image used for programming the FPGA.

And modify how the counter is operated:

INC_COUNT:
    process (clk)
    begin
        if rising_edge(clk)  then
            if d_in = "000" and d_last = "000" and d_last1 = "000" then
                count <= "000";
            elsif unsigned(d_last) >  unsigned(d_in) + 2 then  -- Note 6,7
                count <= std_logic_vector(unsigned(count) + 1);
            end if;
        end if;
    end process;

The three incarnations of the example all analyze, they haven't been simulation and should be synthesis eligible.