Jump to content
  • 0

This darn simulator...


Tickstart

Question

I'm trying to learn how to use it properly but sometimes it's just hopeless.. My design works in hardware but not in the simulator. I get "undefined" as always on my output, which is obviously a lie, I feel violated.

Yesterday I posted a design on a signal synchronizer or stabilizer but I suspect it might be susceptible to metastability so I decided to redesign it today using more flipflops instead of a sneaky xnor gate on an enable pin.

I want the thing to ignore signal changes that are shorter than two clock cycles. I made a state diagram:

state_diagram.jpg.23a68e1831ed1c7cd679020f780395a1.jpg

A state transition table:

state_transition_table.thumb.jpg.65e63ef5fc7922d7249a2b01fbd6164c.jpg

And the next state calculations (I suggest you just read the code, I've written it there too obviously but it's actually readable):

DFF_calculation.jpg.88bf330c4123ec3ed999d35841995830.jpg

Here's the code for the actual module:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity IO_sync_v2 is
  Port ( clk, I : in STD_LOGIC;
         Q, I_R, I_F : out STD_LOGIC);
end IO_sync_v2;

architecture Behavioral of IO_sync_v2 is

component D_flipflop is
    Port ( clk, d : in STD_LOGIC;
           q : out STD_LOGIC);
end component;

signal s0, s0p, s1, s1p, s2, s2p, q_pre, q_new : STD_LOGIC := '0';

begin

    Delay_0: D_flipflop port map(clk => clk, d => s0p, q => s0);
    Delay_1: D_flipflop port map(clk => clk, d => s1p, q => s1);
    Delay_2: D_flipflop port map(clk => clk, d => s2p, q => s2);
    Edge: D_flipflop port map(clk => clk, d => q_new, q => q_pre);
    
    s2p <= (s2 and (s0 xnor I)) or (s1 and s0 and not I);
    s1p <= I and (s1 or (s2 xor s0));
    s0p <= (not s0 and (s2 or s1 or I)) or (s1 and I);

    q_new <= (s2 and ((s0 xnor I) or I)) or (s1 and (s0 or I));
    Q <= q_new;

    I_R <= not q_pre and q_new;
    I_F <= q_pre and not q_new;

end Behavioral;

The testbench:

library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;

entity IO_sync_v2_tb is
end;

architecture bench of IO_sync_v2_tb is

  component IO_sync_v2
    Port ( clk, I : in STD_LOGIC;
           Q, I_R, I_F : out STD_LOGIC);
  end component;

  signal clk, I: STD_LOGIC;
  signal Q, I_R, I_F: STD_LOGIC;

  constant clock_period: time := 10 ns;
  signal stop_the_clock: boolean;

begin

  uut: IO_sync_v2 port map ( clk => clk,
                             I   => I,
                             Q   => Q,
                             I_R => I_R,
                             I_F => I_F );

  stimulus: process
  begin
  
    -- Put initialisation code here
    
    I <= '1';
    wait for clock_period;
    I <= '0';
    wait for clock_period;
    I <= '1';
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    I <= '0';
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    I <= '1';
    wait for clock_period;
    wait for clock_period;
    I <= '0';
    wait for clock_period;
    I <= '1';
    wait for clock_period;
    I <= '0';
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    I <= '1';
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    I <= '0';
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    I <= '1';
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    I <= '0';
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    
    -- Put test bench stimulus code here

    stop_the_clock <= true;
    wait;
  end process;

  clocking: process
  begin
    while not stop_the_clock loop
      clk <= '0', '1' after clock_period / 2;
      wait for clock_period;
    end loop;
    wait;
  end process;

end;

The simulation:

new_synchronizer_sim.thumb.PNG.f11df31d1b0d68527a2a5e0692820f0c.PNG

If this was true, my hardware would not work, but it does. What is the cause of this?

Link to comment
Share on other sites

11 answers to this question

Recommended Posts

19 minutes ago, D@n said:

@Tickstart,

I'm not sure I understand from your description above ... what are you trying to do?  The high level description, please ...

Thanks,

Dan

Sorry, yes.. It's the SPI thing from yesterday. The clock from the Arduino, ie master clock, I want to make it glitch free (not the technical term exactly but you know..). So X/Y in the state diagram means X = input from Arduino clock, Y = internal signal representing it. It must lag behind a couple cycles and not change if there is a temporary change.

Link to comment
Share on other sites

@Tickstart

The simulator can have issues with figuring out what a signal should be when it is derived from itself or another signal that is derived from the first signal. This is only a problem when the signal is not initially defined or all of the paths to derive it depend on it. I am more familiar with verilog, so take vhdl suggestions from me with that in mind, but the following is what I would suspect would help fix the problem.

//file D_flipflop.v:
//Verilog Before:

`timescale 1ns / 1ps
module dff (
	input clk,
	input d,
	output reg q
);
	always@(posedge clk)
		q <= d;
endmodule

//Verilog After:

`timescale 1ns / 1ps
module dff (
	input clk,
	input d,
	output reg q
);
	initial q <= 0;
	always@(posedge clk)
		q <= d;
endmodule

And my attempt at VHDL for the same thing:

//File D_flipflop.vhd
//Before:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity D_flipflop is
    Port ( clk : in STD_LOGIC;
           d : in STD_LOGIC;
           q : out STD_LOGIC
           );
end D_flipflop;

architecture Behavioral of D_flipflop is
begin
    name: process (clk) begin
        if rising_edge(clk) then
            q <= d;
        end if;
    end process name;
end Behavioral;


//File D_flipflop.vhd
//After addition of initial value:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity D_flipflop is
    Port ( clk : in STD_LOGIC;
           d : in STD_LOGIC;
           q : out STD_LOGIC := '0'
           );
end D_flipflop;

architecture Behavioral of D_flipflop is
begin
    name: process (clk) begin
        if rising_edge(clk) then
            q <= d;
        end if;
    end process name;
end Behavioral;

 

My other suggestion would be to take a look at the RTL Analysis -> Elaborated Design -> Schematic for your project, this tool is used to help figure out what the logical circuits that your design is being translated into are. I've attached the schematic I generated for your design. The important thing here is that looking at the I signal's paths, everything route from I to a 'd' pin goes through an AND gate. This means that if the other input to each gate is undefined, the output of that gate will be undefined.

sch.thumb.JPG.81aa3bb7888f6c57f5d9cd150aa0c546.JPG

In short, this was just a long way of saying that you probably need to add ' := '0' ' to your D_flipflop file.

Hope this helps,

Arthur

Link to comment
Share on other sites

2 hours ago, artvvb said:

@Tickstart

The simulator can have issues with figuring out what a signal should be when it is derived from itself or another signal that is derived from the first signal. This is only a problem when the signal is not initially defined or all of the paths to derive it depend on it. I am more familiar with verilog, so take vhdl suggestions from me with that in mind, but the following is what I would suspect would help fix the problem.


//file D_flipflop.v:
//Verilog Before:

`timescale 1ns / 1ps
module dff (
	input clk,
	input d,
	output reg q
);
	always@(posedge clk)
		q <= d;
endmodule

//Verilog After:

`timescale 1ns / 1ps
module dff (
	input clk,
	input d,
	output reg q
);
	initial q <= 0;
	always@(posedge clk)
		q <= d;
endmodule

And my attempt at VHDL for the same thing:


//File D_flipflop.vhd
//Before:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity D_flipflop is
    Port ( clk : in STD_LOGIC;
           d : in STD_LOGIC;
           q : out STD_LOGIC
           );
end D_flipflop;

architecture Behavioral of D_flipflop is
begin
    name: process (clk) begin
        if rising_edge(clk) then
            q <= d;
        end if;
    end process name;
end Behavioral;


//File D_flipflop.vhd
//After addition of initial value:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity D_flipflop is
    Port ( clk : in STD_LOGIC;
           d : in STD_LOGIC;
           q : out STD_LOGIC := '0'
           );
end D_flipflop;

architecture Behavioral of D_flipflop is
begin
    name: process (clk) begin
        if rising_edge(clk) then
            q <= d;
        end if;
    end process name;
end Behavioral;

 

My other suggestion would be to take a look at the RTL Analysis -> Elaborated Design -> Schematic for your project, this tool is used to help figure out what the logical circuits that your design is being translated into are. I've attached the schematic I generated for your design. The important thing here is that looking at the I signal's paths, everything route from I to a 'd' pin goes through an AND gate. This means that if the other input to each gate is undefined, the output of that gate will be undefined.

sch.thumb.JPG.81aa3bb7888f6c57f5d9cd150aa0c546.JPG

In short, this was just a long way of saying that you probably need to add ' := '0' ' to your D_flipflop file.

Hope this helps,

Arthur

Wow, that actually worked, thanks! Now I can see that my code is garbage again. Everything is as it should. I should go back to a design I did earlier where state S2 jumped back to state S0 and state S5 jumped back to state S3 and not the intermediate one... Maybe. I'll do some more research. Thanks again for all your help. I'll probably write here again for some conclusions or more questions.

Link to comment
Share on other sites

Since I made a Mealy machine my result depended on I, but I had not tied the input itself to a flip-flop, only the state variables. When I did, everything worked as expected (not the issue I started this thread for, artvvb came up with the solution to that for me).

 

Is this what you should do, i.e tie all inputs to a flipflop? It makes sense, but that might be just because it solved my weird simulation results..

Link to comment
Share on other sites

@Tickstart

Generally speaking, it's recommended to let Vivado handle the tricky bits and just describe the behavior from a higher level, unless you really need to do the tricky stuff for learning purposes. In this situation, you can get the same effect by shifting the input into a std_logic_vector and then using that vector to determine your outputs.

Where are you coming from with this? Do you want to make something that works and is easy to read/maintain, or do you really need to dig heavily into the details?

Thanks,

Arthur

Link to comment
Share on other sites

14 minutes ago, artvvb said:

@Tickstart

Generally speaking, it's recommended to let Vivado handle the tricky bits and just describe the behavior from a higher level, unless you really need to do the tricky stuff for learning purposes. In this situation, you can get the same effect by shifting the input into a std_logic_vector and then using that vector to determine your outputs.

Where are you coming from with this? Do you want to make something that works and is easy to read/maintain, or do you really need to dig heavily into the details?

Thanks,

Arthur

I see what you mean. I don't know really, I'm sort of self learning, for better or worse. I've taken university courses in digital design etc but I didn't pay much attention back then. I did retake the class and learnt a lot that time around, but we concentrated not so much on details like we've gone through here today. I have a book on the subject which covers a lot of ground but I haven't read it thoroughly "pärm till pärm", or beginning to end.

Link to comment
Share on other sites

Here's my new and improved design:

improved_synchro.jpg.c1fe440750b18f534934edfff07a2b80.jpg

That's actually more what I had in mind but since I didn't tie the input to a clocked module (DFF in this case) I thought I was "missing" a delay cycle. Simulation:

I - Input

Q - Slightly delayed output that should be a "clean" input I.

I_R, I_F - rising- and falling edge

improved_synchro_sim.thumb.jpg.312211e154125026087bff6ac174fabd.jpg

Link to comment
Share on other sites

Dear @Tickstart

I might be too late to bring this but hope not.

1. It is typical to use switch - case construct for designing finite state machines. Xilinx even included synthesizable language templates. When you are in the VHDL design window you can see it the Vivado help (click light bulb icon), see the snapshot of it. Using flip-flop seems to be the hardest way to me, however, it is a matter of choice.

2. There is a Digilent project called Active Power Meter reference design with an example of SPI using FSM posted here 

I would suggest to simulate it for better understanding.

Good luck!

Capture.PNG

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...