0

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;
Morde
  • 25
  • 1
  • 5
  • 1
    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. –  Nov 05 '14 at 13:38
  • Sorry, but where do I declare D_last as? In the variable? – Morde Nov 05 '14 at 13:46
  • 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 : http://stackoverflow.com/questions/13954193/is-process-in-vhdl-reentrant/13956532#13956532 –  Nov 05 '14 at 13:46
  • 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 Nov 05 '14 at 15:05

2 Answers2

1

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;

Community
  • 1
  • 1
grorel
  • 1,408
  • 15
  • 21
  • Thanks for the reply mate. So if i add another statement, signal count_in: std_logic_vector(2 downto 0); then in the architecture, i use count_in=count_in+1, then transfer it back to count outside the process. It should be ok tis way? 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? Kinda confused. – Morde Nov 05 '14 at 18:27
  • You got it for the first part! Do not mismatch with the solution given by David Koontz on the count affectation. In his solution, he uses a variable (cnt) instead of a signal in mine (count_in). Then his affectation is made inside the process whereas mine is outside. Both solutions are fine, it's only coder's habits. – grorel Nov 05 '14 at 22:22
0

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.

  • Very insightful. I am trying to increment my learning by slowly adding more conditions to the question. This is the last part of my system I am trying to implement. What if I want to assert an output, say an alarm if count reaches 6 and count will not increase until it is reset after 0 for 3 clk cycles? How to translate will not increase in terms of VHDL? – Morde Nov 06 '14 at 01:45
  • Just to clarify, for D_last1, I will need to declare a new process that is done similarly for D_last right? thanks!!! – Morde Nov 06 '14 at 02:03
  • You could do all the clocked processes using the same clk as one process. The original one was split in two to make the point that signal value update is independent of evaluating the current value. –  Nov 06 '14 at 02:41
  • When count reaches 6, the system will assert an output alarm and the count will not increase until it is reset by giving d_in 0 for 3 clk cycles. I think i didn't phrase it properly. This is a continued version of the original code i posted. – Morde Nov 06 '14 at 03:48
  • For the code u helped me, you have implement if d_last>d_in+2, den count+1 if not if d_in is 0 for 3 clk cycles, it resets the count. But now i want to check if count is 6, alarm will output or '1' and count will stop increasing until it is reset again after d_in is 0 for 3 clk cycles – Morde Nov 06 '14 at 03:57