0

As you can imagine by seeing my code right there, I'm a beginner at VHDL so I'm really wondering why this isn't working as it seems it logically should work.

In fact the part that isn't behaving the way that I'd like it to isn't doing anything at all.

To make this a bit more simple to understand, I'll explain at least a bit what this is supposed to do. First, the IN port New_Data indicates on 1 that a new data is available and should be evaluated. The input Code is the value to evaluate/interpret. The output is the new speed value and current is the current/previous one. Direction is inverted by input code 10.

The part that doesn't work or actually do anything: If the code is + (val 43) you increase it by 1, if the code is - (val 45) you reduce it by 1 then the result it sent to the speed output.

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.NUMERIC_STD.ALL;

ENTITY Code_Interpret IS
    PORT (
            New_Data: IN STD_LOGIC;
            Current_Speed: IN UNSIGNED(7 DOWNTO 0);
            Code: IN UNSIGNED(7 DOWNTO 0);
            Speed: OUT UNSIGNED(7 DOWNTO 0);
            Direction: OUT STD_LOGIC
         );
END Code_Interpret;

ARCHITECTURE rtl OF Code_Interpret IS

SIGNAL s_speed: UNSIGNED(7 DOWNTO 0):= "00110000";
SIGNAL s_case: INTEGER RANGE 0 TO 64 := 48;
SIGNAL s_direction: STD_LOGIC := '1';

BEGIN
    PROCESS (New_Data, Code)
    BEGIN
        s_case <= TO_INTEGER(Code);
        IF RISING_EDGE(New_Data) THEN
            CASE s_case IS
                WHEN 48 TO 55 =>
                    --s_speed <= Code;
                    s_speed <= Code;
                WHEN 43 =>
                    IF Current_Speed < 55 THEN
                        s_speed <= Current_Speed + 1;
                    ELSE
                        s_speed <= Current_Speed;
                    END IF;
                WHEN 45 =>
                    IF Current_Speed > 48 THEN
                        s_speed <= Current_Speed - 1;
                    ELSE
                        s_speed <= Current_Speed;
                    END IF;
                WHEN 10 =>
                    s_direction <= NOT s_direction;
                WHEN OTHERS =>
                    NULL;
            END CASE;
        END IF;
        Speed <= s_speed;
        Direction <= s_direction;
    END PROCESS;
END;

The part that isn't doing what I want:

WHEN 43 =>
    IF Current_Speed < 55 THEN
        s_speed <= Current_Speed + 1;
    ELSE
        s_speed <= Current_Speed;
    END IF;
WHEN 45 =>
    IF Current_Speed > 48 THEN
        s_speed <= Current_Speed - 1;
    ELSE
        s_speed <= Current_Speed;
    END IF;

Here is what my simulation looks like. There are 6 markers on the timeline , the first is + then - then a Direction switch and the same codes repeated in the same order.

Quartus Simulation #1

I've tried a lot of different things but I haven't managed to grasp what the problem is and I'd love to know why this isn't working.

Ok so now I'm simulating only the VHDL code and working straight with the inputs and outputs instead of using useless pins and in a schematic I didn't need. Also I read the Quartus II simulation manual so that helped me fix the radixes. (Like I said, I'm fairly new to this..)

Change in the code to attempt using a VAR:

--....
--SIGNAL s_case: INTEGER RANGE 0 TO 64 := 48;
SIGNAL s_direction: STD_LOGIC := '1';

BEGIN
    PROCESS (New_Data, Code)
        VARIABLE s_case: INTEGER RANGE 0 TO 64 := 48;
    BEGIN
        s_case := TO_INTEGER(Code);
        IF RISING_EDGE(New_Data) THEN
            CASE s_case IS
    --....

The resulting simulation: Quartus Simulation #2

  • Looks like it's working as intended, but you might want to issue code 45 somewhere in your tests. –  Apr 28 '16 at 09:36
  • In the simulation screen capture you can see the value for code is 43 around 520ns and 700ns and yet nothing happens and 45 also appears in code at 570ns and 760ns "speed" changes at every new_data rising edge except for the 6 last rising edges. (well, except that it behaves as it should for code 0000 1010) – Guillaume Drolet Apr 28 '16 at 09:59
  • Your simulation does not quite seem to reflect the code. For example, 'vitesse' is not in the code. I think you need to run a behavioral simulation, logging the exact ports in the entity above, as well as your three signals. As it stands, you seem to be trying to debug without looking at the lowest level. – scary_jeff Apr 28 '16 at 10:48
  • You are correct, that both codes 43 and 45 are issued - I would recommend using sane radixes on the waveform display to avoid having to convert from binary - that's just making life insanely difficult. I think you have an issue with postponed assignment (signal assignment) and an incomplete sensitivity list on the process. If you made `s_case` a variable (it has no use outside the process and restricting scope is good practice) this would be avoided. –  Apr 28 '16 at 11:05
  • @scary_jeff I have fixed that part. I was simulating my VHDL code after generating a block and connecting it to pins (which was not necessary, thanks for making me realize that) – Guillaume Drolet Apr 28 '16 at 12:42
  • @BrianDrummond Yaeh thanks I fixed that as you can see, I edited my post. I have attempted to change the signal to a variable and it does not seem to change anything (the second simulation is with the var). You can look up the change in code as well. As for sensitivity list, is it necessary to add other variables? I do not want my process to be re-evaluated to be done on variation of any other input or signal than my clock. – Guillaume Drolet Apr 28 '16 at 12:47
  • Your code isn't a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve), lacking a way of replicating your results. There's an alternative to making s_code a variable. You can assign it outside the process (another process or a concurrent signal assignment). There's also assignment delay to speed and direction in the first waveform not accounted in your code, and these assignments should be external to the process otherwise only being updated on an event on new_data or code. The sensitivity list should only contain new_data. –  Apr 28 '16 at 18:36

1 Answers1

0

Please, rethink what you are trying to do in the first place. Your process implementation is a funny mix of sequential and combinational logic. The semantic traps you are running into:

  • A signal is only updated in the next delta cycle, i.e. the changes on your s_* signals become effective only in the next iteration of the process.
  • The process is only triggered by changes on the New_data and Code inputs.

Make sure you have a clear idea on what should be sequential and, hence, trigger on the clock and use 'rising_edge(clock)' and what should be combinational and, hence, must trigger on all processed inputs - without checking for an edge.

Thomas B Preusser
  • 1,159
  • 5
  • 10
  • Thank you for the information. So, if I understand correctly, it will update when the process is "called" again most likely by the clock. It seems that it does so after the rising edge if I take a look at my first simulation, before the "+ [0011 1011]". My problem here is that my speed does not change at all for '+' and '-'. I will do more tests then... And what in the case of a Variable? Does it update on the next delta cycle as well or it will update on the same cycle? From what I've read this is how it should behave. – Guillaume Drolet Apr 28 '16 at 13:15
  • @GuillaumeDrolet I really think you would benefit from adding your internal signals to the simulation wave window. This would immediately show any delayed assignment issues. – scary_jeff Apr 28 '16 at 13:51
  • The execution of a process is triggered by an event on any of the signals in its sensitivity list. This should be the clock if and only if you describe sequential logic. And yes, variables are updated instantly. However, many tools will not allow you to drag them into waveforms for inspection over time. – Thomas B Preusser Apr 28 '16 at 14:36