Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

weird vhdl simulation result

Status
Not open for further replies.

Taher_Selim

Member level 5
Joined
Mar 26, 2008
Messages
83
Helped
11
Reputation
22
Reaction score
4
Trophy points
1,298
Location
Egypt
Activity points
1,801
Hallo,
I have simulated the following code using ModelSim.

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity fifo_SCnt is
generic(
RAMsize: integer := 256;
DataWidth: integer := 8
);
port(
    clk: in std_logic;
    rst: in std_logic;
    data_in: in std_logic_vector (DataWidth-1 downto 0);
    data_out: out std_logic_vector(DataWidth-1 downto 0);
    readReq: in std_logic;  
    writeReq: in std_logic;
    data_in_ack: out std_logic;
    data_out_stb: out std_logic;
    empty: out std_logic;  
    full: out std_logic
);
end entity;

architecture rtl of fifo_SCnt is 

type memory_type is array (0 to RAMsize-1) of std_logic_vector(DataWidth-1 downto 0);
signal memory : memory_type :=(others => (others => '0'));

signal read_ptr : integer range 0 to RAMsize-1  :=0;
signal write_ptr : integer range 0 to RAMsize-1 :=0;
signal isFull : std_logic;
signal isEmpty : std_logic;
signal writereq_cnt: integer := 0;
signal readreq_cnt: integer := 0;

begin
process (clk, rst)
begin 
  
  clk_rst : if (rst = '1') then
    memory <= (others => (others => '0'));
    empty <='1';
	isEmpty <= '1';
    full <='0'; 
    isFull <= '0';	
    data_out  <= (others => '0');
    data_out_stb <= '0';
	data_in_ack <= '0';
    read_ptr  <= 0;
    write_ptr <= 0;

elsif (clk'event and clk='1') then

memory(write_ptr+1)<=X"65";
        if(write_ptr < RAMsize-1) then
            write_ptr <= write_ptr+1;
        else
            write_ptr <= 0;
        end if;

if (readReq='1') then
        data_out <= memory(read_ptr+1);
        data_out_stb <= '1';
        full <= '0';
        isFull <= '0';
end if;

end if clk_rst; 
  

end process;

end rtl;

I got weird results. I expect data_out_stb to be raised at next clk cycle after (readReq='1') but as you can see in the simulation wave, it is raised at the same clock edge. does anyone has explanation for that
01.PNG

To understand why it is weird, I modified the code to be
Code:
elsif (clk'event and clk='1') then

if (readReq='1') then
        data_out <= memory(read_ptr+1);
        data_out_stb <= '1';
        full <= '0';
        isFull <= '0';
                data_in_ack <= '0';
end if;

if (writeReq='1') then
        memory(read_ptr+1) <= data_in;
        data_in_ack <= '1';
        empty <= '0';
        isEmpty <= '0';
        if(write_ptr < RAMsize-1) then
            write_ptr <= write_ptr+1;
        else
            write_ptr <= 0;
        end if;
end if;

end if clk_rst;

the "data_in_ack <= '1';" is updated in next clk cycle as shown in photo 02
02.PNG
 
Last edited:

You don't show your testbench. What's the relationship between readReq and the clock? Is it synchronous? If readReq is coincident with the clock edge, what do think will happen?
 

In my testbench readReq is synchronized. please find below my testbench
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity fifo_tb is
  generic(
RAMsize: integer := 256;
DataWidth: integer := 8
);
end fifo_tb;

architecture tb of fifo_tb is
  
  component fifo_SCnt
generic(
RAMsize: integer := 256;
DataWidth: integer := 8
);
port(
    clk: in std_logic;
    rst: in std_logic;
    data_in: in std_logic_vector (DataWidth-1 downto 0);
    data_out: out std_logic_vector(DataWidth-1 downto 0);
    readReq: in std_logic;  
    writeReq: in std_logic;
    data_in_ack: out std_logic;
    data_out_stb: out std_logic;
    empty: out std_logic;  
    full: out std_logic
);
end component;

CONSTANT clk_period : TIME := 2 NS;

signal clk_tb: std_logic;
signal rst_tb: std_logic;
signal data_in_tb: std_logic_vector (DataWidth-1 downto 0);
signal data_out_tb: std_logic_vector(DataWidth-1 downto 0);
signal readReq_tb: std_logic;  
signal writeReq_tb: std_logic;
signal data_in_ack_tb: std_logic;
signal data_out_stb_tb: std_logic;
signal empty_tb: std_logic;  
signal full_tb: std_logic;
  
begin
  
  
 fifo_DUT : fifo_SCnt
generic map(
RAMsize => 256,
DataWidth => 8
)
port map(
    clk => clk_tb,
    rst => rst_tb,
    data_in => data_in_tb,
    data_out => data_out_tb,
    readReq => readReq_tb,
    writeReq => writeReq_tb,
    data_in_ack => data_in_ack_tb,
    data_out_stb => data_out_stb_tb,
    empty => empty_tb,
    full => full_tb
);

  -- RESET PROCESS
  ----------------
  reset : PROCESS
  BEGIN
    rst_tb <= '1';
    WAIT FOR clk_period;
    rst_tb <= '0';
    WAIT;
  END PROCESS reset;
  
    -- CLOCK PROCESS
  ----------------
  clock_generation : PROCESS
  BEGIN
    clk_tb <= '0';
    WAIT FOR clk_period/2;
    clk_tb <= '1';
    WAIT FOR clk_period/2;
  END PROCESS clock_generation;
  
  
  -- Input Stimulus
  -------------------
  Stim : PROCESS
  BEGIN
    WAIT UNTIL (rst_tb = '0' AND rising_edge(clk_tb));
    data_in_tb <= X"65";
    writeReq_tb <= '1';
    readReq_tb <= '0';
    WAIT FOR clk_period*4;
    data_in_tb <= X"66";
    writeReq_tb <= '0';
    readReq_tb <= '1';
    WAIT FOR clk_period*4;
    
  END PROCESS Stim;

  
end tb;
 

I'm not sure what's going on here but I suspect it's something to do with the fact that the clock edge is coincident with the readReq changing state. Just as an experiment I would try changing the time that readReq changes from WAIT FOR clk_period*4 to WAIT FOR 8.1 ns (I.e., clkperiod*4+delta). This will move the transition of readReq away from the clock edge.

Update: it just occurred to me that maybe it's because you don't have an ELSE statement associated with ith IF that sets readReq. Just a thought.
 

This is your problem:

WAIT FOR clk_period*4;

here, this means writeReq_tb actually goes to '0' just before the clock edge, meaning it gets clocked as if it is '1' and not '0'.
In the testbench, it is best to synchronise everything with the clock:

Code:
for i in 1 to 4 loop
  wait until rising_edge(clk_tb); 
end loop;

writeReq_tb <= '0';
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top