clock delay when testing different inputs in FSM ?

Discussion in 'VHDL' started by maurizio.gencarelli@dsto.defence.gov.au, Jul 2, 2007.

  1. Guest

    I have lack of consistency with my FSM code.


    If the input condition in state "idle" is "if data="1101" then", the
    state imediately changes to "write_fifo" and sets wr_fifo_en to '1'.
    However, if in state "idle" and the input condition is "if
    frame_mrk='1' then", the state changes one clock later to "write_fifo"
    and sets wr_fifo_en to '1'.

    Why is there is a delay with frame_mrk ? When does the input that you
    are testing affect the variable assignment of state ?

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.numeric_std.all;

    entity RX_FIFO_WR_CONTROL is
    Port ( data_clk : in STD_LOGIC;
    data:in STD_LOGIC_VECTOR (3 downto 0);
    frame_mrk : in STD_LOGIC;
    rxdv: in STD_LOGIC;
    fifo_full : in STD_LOGIC;
    frame_good: in STD_LOGIC;
    frame_bad: in STD_LOGIC;
    fifo_wr_data: out STD_LOGIC_VECTOR (4 downto 0);
    wr_fifo_en : out STD_LOGIC;
    rst: in STD_LOGIC;
    prog_full_thresh: out std_logic_VECTOR(10 downto 0));
    end RX_FIFO_WR_CONTROL;

    architecture RTL of RX_FIFO_WR_CONTROL is



    signal ovr_flow: std_logic;




    begin

    prog_full_thresh<="11111111110";


    -- FSM
    process (data_clk,rst)
    type fifo_cntrl_state is
    (idle,write_fifo,over_flow,wait_end,read_frame_condition,write_frame_status);
    variable state:fifo_cntrl_state;
    begin
    if rst='1' then
    state:=idle;
    ovr_flow<='0';
    wr_fifo_en<='0';
    fifo_wr_data<="00000";

    elsif rising_edge(data_clk) then

    case state is
    when idle =>
    if frame_mrk='1' then
    --if data="1101" then
    state:=write_fifo;
    else
    state:=idle;
    end if;


    when write_fifo =>
    if frame_mrk='0' then
    state:= wait_end;
    elsif fifo_full='1' then
    state:= over_flow;
    else
    state:=write_fifo;
    end if;

    when over_flow=>
    state:=wait_end;

    when wait_end =>
    if rxdv='0' then
    state:=read_frame_condition;
    else
    state:=wait_end;
    end if;

    when read_frame_condition =>
    state:=write_frame_status;

    when write_frame_status =>
    state:=idle;
    when others =>
    state:= idle;

    end case;

    case state is

    when idle=>
    ovr_flow<='0';
    wr_fifo_en<='0';
    fifo_wr_data(3 downto 0)<="0000";
    fifo_wr_data(4)<='0';


    when write_fifo=>

    ovr_flow<='0';
    wr_fifo_en<='1';
    fifo_wr_data(3 downto 0)<=data;
    fifo_wr_data(4)<='1';

    when over_flow=>
    fifo_wr_data(3 downto 0)<=data;
    fifo_wr_data(4)<='0';
    ovr_flow<='1';
    wr_fifo_en<='0';

    when wait_end=>
    fifo_wr_data(3 downto 0)<="0000";
    fifo_wr_data(4)<='0';
    wr_fifo_en<='0';

    when read_frame_condition=>
    wr_fifo_en<='0';

    when write_frame_status=>

    fifo_wr_data(4)<='0';
    fifo_wr_data(3)<=ovr_flow;
    fifo_wr_data(2)<=frame_good;
    fifo_wr_data(1)<=frame_bad;
    fifo_wr_data(0)<='0';

    wr_fifo_en<='1';
    ovr_flow<='0';

    when others=>

    ovr_flow<='0';
    wr_fifo_en<='0';
    fifo_wr_data(3 downto 0)<=data;
    fifo_wr_data(4)<='0';
    end case;

    end if;

    end process;


    end RTL;


    Cheers

    Maurizio Gencarelli
    Defence &Technology Organisation Salisbury
    Australia
     
    , Jul 2, 2007
    #1
    1. Advertising

  2. Guest

    The latest with this problem, is it seems to happen when the input has
    gone through layers of instantiation. That is, frame_mrk comes from
    "receiver.vhdl" entity which is within a higher level entity of
    "receiver_mac". So frame_mrk is instantiated from "receiver.vhdl" to
    toplevel "receiver_mac.vhdl" frame_mrk output port. This in turn is
    instantiated to frame_mrk input port of "rx_fifo_wr_control.vhdl".
    Frame_mrk is connected from "receiver_mac" to
    "rx_fifo_wr_control.vhdl" using a signal. I thought this would not
    intrduce delta delays ? Data on the other hand comes directly from the
    toplevel entity so no problems.

    wrote:
    > I have lack of consistency with my FSM code.
    >
    >
    > If the input condition in state "idle" is "if data="1101" then", the
    > state imediately changes to "write_fifo" and sets wr_fifo_en to '1'.
    > However, if in state "idle" and the input condition is "if
    > frame_mrk='1' then", the state changes one clock later to "write_fifo"
    > and sets wr_fifo_en to '1'.
    >
    > Why is there is a delay with frame_mrk ? When does the input that you
    > are testing affect the variable assignment of state ?
    >
    > library IEEE;
    > use IEEE.STD_LOGIC_1164.ALL;
    > use IEEE.numeric_std.all;
    >
    > entity RX_FIFO_WR_CONTROL is
    > Port ( data_clk : in STD_LOGIC;
    > data:in STD_LOGIC_VECTOR (3 downto 0);
    > frame_mrk : in STD_LOGIC;
    > rxdv: in STD_LOGIC;
    > fifo_full : in STD_LOGIC;
    > frame_good: in STD_LOGIC;
    > frame_bad: in STD_LOGIC;
    > fifo_wr_data: out STD_LOGIC_VECTOR (4 downto 0);
    > wr_fifo_en : out STD_LOGIC;
    > rst: in STD_LOGIC;
    > prog_full_thresh: out std_logic_VECTOR(10 downto 0));
    > end RX_FIFO_WR_CONTROL;
    >
    > architecture RTL of RX_FIFO_WR_CONTROL is
    >
    >
    >
    > signal ovr_flow: std_logic;
    >
    >
    >
    >
    > begin
    >
    > prog_full_thresh<="11111111110";
    >
    >
    > -- FSM
    > process (data_clk,rst)
    > type fifo_cntrl_state is
    > (idle,write_fifo,over_flow,wait_end,read_frame_condition,write_frame_status);
    > variable state:fifo_cntrl_state;
    > begin
    > if rst='1' then
    > state:=idle;
    > ovr_flow<='0';
    > wr_fifo_en<='0';
    > fifo_wr_data<="00000";
    >
    > elsif rising_edge(data_clk) then
    >
    > case state is
    > when idle =>
    > if frame_mrk='1' then
    > --if data="1101" then
    > state:=write_fifo;
    > else
    > state:=idle;
    > end if;
    >
    >
    > when write_fifo =>
    > if frame_mrk='0' then
    > state:= wait_end;
    > elsif fifo_full='1' then
    > state:= over_flow;
    > else
    > state:=write_fifo;
    > end if;
    >
    > when over_flow=>
    > state:=wait_end;
    >
    > when wait_end =>
    > if rxdv='0' then
    > state:=read_frame_condition;
    > else
    > state:=wait_end;
    > end if;
    >
    > when read_frame_condition =>
    > state:=write_frame_status;
    >
    > when write_frame_status =>
    > state:=idle;
    > when others =>
    > state:= idle;
    >
    > end case;
    >
    > case state is
    >
    > when idle=>
    > ovr_flow<='0';
    > wr_fifo_en<='0';
    > fifo_wr_data(3 downto 0)<="0000";
    > fifo_wr_data(4)<='0';
    >
    >
    > when write_fifo=>
    >
    > ovr_flow<='0';
    > wr_fifo_en<='1';
    > fifo_wr_data(3 downto 0)<=data;
    > fifo_wr_data(4)<='1';
    >
    > when over_flow=>
    > fifo_wr_data(3 downto 0)<=data;
    > fifo_wr_data(4)<='0';
    > ovr_flow<='1';
    > wr_fifo_en<='0';
    >
    > when wait_end=>
    > fifo_wr_data(3 downto 0)<="0000";
    > fifo_wr_data(4)<='0';
    > wr_fifo_en<='0';
    >
    > when read_frame_condition=>
    > wr_fifo_en<='0';
    >
    > when write_frame_status=>
    >
    > fifo_wr_data(4)<='0';
    > fifo_wr_data(3)<=ovr_flow;
    > fifo_wr_data(2)<=frame_good;
    > fifo_wr_data(1)<=frame_bad;
    > fifo_wr_data(0)<='0';
    >
    > wr_fifo_en<='1';
    > ovr_flow<='0';
    >
    > when others=>
    >
    > ovr_flow<='0';
    > wr_fifo_en<='0';
    > fifo_wr_data(3 downto 0)<=data;
    > fifo_wr_data(4)<='0';
    > end case;
    >
    > end if;
    >
    > end process;
    >
    >
    > end RTL;
    >
    >
    > Cheers
    >
    > Maurizio Gencarelli
    > Defence &Technology Organisation Salisbury
    > Australia
     
    , Jul 2, 2007
    #2
    1. Advertising

  3. KJ Guest

    <> wrote in message
    news:...
    >I have lack of consistency with my FSM code.
    >
    >
    > If the input condition in state "idle" is "if data="1101" then", the
    > state imediately changes to "write_fifo" and sets wr_fifo_en to '1'.
    > However, if in state "idle" and the input condition is "if
    > frame_mrk='1' then", the state changes one clock later to "write_fifo"
    > and sets wr_fifo_en to '1'.
    >
    > Why is there is a delay with frame_mrk ?

    Most likely because 'data' is being generated incorrectly in your testbench
    and 'frame_mrk' is not. You don't show how you're generating the input
    'data' but I'll bet it is transitioning on the same simulation delta cycle
    where the clock switches from '0' to '1'. 'frame_mrk' is most likely
    transitioning on the simulation delta cycle after clock switches from '0' to
    '1' so it won't get picked up until the next rising edge.

    > When does the input that you
    > are testing affect the variable assignment of state ?

    When you have a timing problem....like it appears that you do. Try moving
    the assignments to 'data' so that they occur around the falling edge of the
    clock and you'll see that the response to 'data' and 'frame_mrk' now are the
    same.

    Now before you even start wondering how to change the timing on 'frame_mrk'
    so that it works like 'data', don't bother. Any synthesizable system (and
    I'm assuming that you intend to try to build this) will have finite,
    non-zero clock to output delays, propogation delays and input setup times
    and it will be impossible to build a working system where you have any input
    transition exactly at the rising edge of the clock. Instead, you need to
    first fix your testbench so that 'data' happens at least one simulation
    delta after the rising edge of the clock and then (if necessary), fix your
    design so that it does what you want it to.

    KJ
     
    KJ, Jul 2, 2007
    #3
  4. Guest

    On Jul 2, 7:52 pm, "KJ" <> wrote:
    > <> wrote in message
    >
    > news:...>I have lack of consistency with my FSM code.
    >
    > > If the input condition in state "idle" is "if data="1101" then", the
    > > state imediately changes to "write_fifo" and sets wr_fifo_en to '1'.
    > > However, if in state "idle" and the input condition is "if
    > > frame_mrk='1' then", the state changes one clock later to "write_fifo"
    > > and sets wr_fifo_en to '1'.

    >
    > > Why is there is a delay with frame_mrk ?

    >
    > Most likely because 'data' is being generated incorrectly in your testbench
    > and 'frame_mrk' is not. You don't show how you're generating the input
    > 'data' but I'll bet it is transitioning on the same simulation delta cycle
    > where the clock switches from '0' to '1'. 'frame_mrk' is most likely
    > transitioning on the simulation delta cycle after clock switches from '0' to
    > '1' so it won't get picked up until the next rising edge.
    >
    > > When does the input that you
    > > are testing affect the variable assignment of state ?

    >
    > When you have a timing problem....like it appears that you do. Try moving
    > the assignments to 'data' so that they occur around the falling edge of the
    > clock and you'll see that the response to 'data' and 'frame_mrk' now are the
    > same.
    >
    > Now before you even start wondering how to change the timing on 'frame_mrk'
    > so that it works like 'data', don't bother. Any synthesizable system (and
    > I'm assuming that you intend to try to build this) will have finite,
    > non-zero clock to output delays, propogation delays and input setup times
    > and it will be impossible to build a working system where you have any input
    > transition exactly at the rising edge of the clock. Instead, you need to
    > first fix your testbench so that 'data' happens at least one simulation
    > delta after the rising edge of the clock and then (if necessary), fix your
    > design so that it does what you want it to.
    >
    > KJ


    Thanks KJ for you comments.

    Attached is the test bench and other entities. If the test condition
    is on "data" or rxdv, no clock delay, but if I
     
    , Jul 2, 2007
    #4
  5. Guest

    On Jul 2, 10:58 pm, wrote:
    > On Jul 2, 7:52 pm, "KJ" <> wrote:
    >
    >
    >
    >
    >
    > > <> wrote in message

    >
    > >news:...>Ihave lack of consistency with my FSM code.

    >
    > > > If the input condition in state "idle" is "if data="1101" then", the
    > > > state imediately changes to "write_fifo" and sets wr_fifo_en to '1'.
    > > > However, if in state "idle" and the input condition is "if
    > > > frame_mrk='1' then", the state changes one clock later to "write_fifo"
    > > > and sets wr_fifo_en to '1'.

    >
    > > > Why is there is a delay with frame_mrk ?

    >
    > > Most likely because 'data' is being generated incorrectly in your testbench
    > > and 'frame_mrk' is not. You don't show how you're generating the input
    > > 'data' but I'll bet it is transitioning on the same simulation delta cycle
    > > where the clock switches from '0' to '1'. 'frame_mrk' is most likely
    > > transitioning on the simulation delta cycle after clock switches from '0' to
    > > '1' so it won't get picked up until the next rising edge.

    >
    > > > When does the input that you
    > > > are testing affect the variable assignment of state ?

    >
    > > When you have a timing problem....like it appears that you do. Try moving
    > > the assignments to 'data' so that they occur around the falling edge of the
    > > clock and you'll see that the response to 'data' and 'frame_mrk' now are the
    > > same.

    >
    > > Now before you even start wondering how to change the timing on 'frame_mrk'
    > > so that it works like 'data', don't bother. Any synthesizable system (and
    > > I'm assuming that you intend to try to build this) will have finite,
    > > non-zero clock to output delays, propogation delays and input setup times
    > > and it will be impossible to build a working system where you have any input
    > > transition exactly at the rising edge of the clock. Instead, you need to
    > > first fix your testbench so that 'data' happens at least one simulation
    > > delta after the rising edge of the clock and then (if necessary), fix your
    > > design so that it does what you want it to.

    >
    > > KJ


    Thanks KJ for you comments.

    Attached is the test bench and some of the other entities that are
    affected. If the test condition
    is on DATA or RXDV (ie. "if DATA='1' then" or "if RXDV='1' then" in
    the "idle" state of RX_FIFO_WR_CONTROL.VHDL) I get no clock delay, but
    if I use an signal which is generated not from the test bench directly
    but from another entity e.g frame_bad, frame_good, or frame_mrk
    signals from RECEIVER.VHDL enity, I get the delay.It is like the
    signal interconnects (ie. SIG_1,SIG_2 etc) within the instantiation
    that connects these signals from RECEIVER.VHDL entity to
    RX_FIFO_WR_CONTROL.VHDL via RECEIVER_MAC.VHDL entity is introducing
    delta delays. Signals frame_bad, frame_good, or frame_mrk and signals
    data and rxdv from the test bench are all registered, so why the
    delay ?.


    ======Test
    Bench===============================================================================



    ENTITY ether_rx_toplevel_tb_vhd IS
    END ether_rx_toplevel_tb_vhd;

    ARCHITECTURE behavior OF ether_rx_toplevel_tb_vhd IS

    -- Declare Functions

    function str_to_stdvec( s_inp : string) return std_logic_vector is
    variable l_temp : std_logic_vector( s_inp'range) := (others =>
    'X');
    begin
    for i in s_inp'range loop
    if( s_inp( i) = '1') then
    l_temp( i) := '1';
    elsif( s_inp(i) = '0') then
    l_temp( i) := '0';
    end if;
    end loop;
    return l_temp;
    end function str_to_stdvec;

    COMPONENT ETHER_RX_TOPLEVEL is
    Port ( rst : in STD_LOGIC;
    rxclk : in STD_LOGIC;
    rxdv : in STD_LOGIC;
    rxd : in STD_LOGIC_VECTOR (3 downto 0);
    rx_cpu_data : out STD_LOGIC_VECTOR (4 downto 0);
    rx_cpu_data_clk : in STD_LOGIC;
    cpu_rx_en:in STD_LOGIC;
    rx_cpu_flg : out STD_LOGIC);

    end COMPONENT;

    signal RXCLK_sig : std_logic:='1';
    signal rx_cpu_data_clk_sig:std_logic:='1';
    signal CLK_sig : std_logic:='0';
    signal RXD_sig: std_logic_vector(3 downto
    0):="0000";
    signal RXDV_sig : std_logic:='0';
    signal RESET_sig:std_logic:='0';
    signal cpu_rx_en_sig : std_logic:='1';
    signal rx_cpu_flg_sig : std_logic:='1';

    BEGIN
    uut: ETHER_RX_TOPLEVEL
    port map(
    rxclk=>RXCLK_sig,
    rxd=>RXD_sig,
    rxdv=>RXDV_sig,
    rst=>RESET_sig,
    rx_cpu_data_clk=>rx_cpu_data_clk_sig,
    cpu_rx_en=>cpu_rx_en_sig,
    rx_cpu_flg=>rx_cpu_flg_sig
    );

    CLK_sig<=not CLK_sig after 20 ns;
    rx_cpu_data_clk_sig<=not rx_cpu_data_clk_sig after 50 ns;

    reset_sig<='0','1' after 50 ns, '0' after 150 ns;


    -- Test Bench Statements
    tb : process(CLK_sig)

    file vector_file : TEXT open READ_MODE is "c:/edata.txt";
    variable file_line:line;


    variable str_stimulus_in: string(8 downto 1);
    variable stimulus_in: std_logic_vector(7 downto 0);

    begin

    if not endFILE(VECTOR_FILE) then
    if rising_edge(CLK_sig) then
    readline(VECTOR_FILE,file_line);
    read(file_line,str_stimulus_in);
    stimulus_in := str_to_stdvec( str_stimulus_in);
    end if;
    end if;



    rxclk_sig<=CLK_sig;
    rxdv_sig<=stimulus_in(4);
    rxd_sig(3)<=stimulus_in(3);
    rxd_sig(2)<=stimulus_in(2);
    rxd_sig(1)<=stimulus_in(1);
    rxd_sig(0)<=stimulus_in(0);


    end PROCESS tb;


    process

    begin


    for i in 0 to 4096 loop
    wait until rising_edge(rx_cpu_flg_sig);
    wait for 50 ns;
    cpu_rx_en_sig<='0';
    wait for 20 ns;
    cpu_rx_en_sig<='1';
    wait for 50 ns;
    cpu_rx_en_sig<='0';
    end loop;

    wait;

    end process;

    -- end Test Bench

    end;


    ================Top Level Entity-
    ===========================================================================

    entity ether_rx_toplevel is
    Port(rst:in std_logic;
    rxclk:in std_logic;
    rxdv:in std_logic;
    rxd:in std_logic_vector (3 downto 0);
    rx_cpu_data:eek:ut std_logic_vector (4 downto 0);
    rx_cpu_data_clk:in std_logic;
    cpu_rx_en:in std_logic;
    rx_cpu_flg:eek:ut std_logic);
    end ether_rx_toplevel;

    architecture Behavioral of ether_rx_toplevel is
    component receiver_mac is
    Port(rst:in std_logic;
    rxclk:in std_logic;
    rxdv:in std_logic;
    rxd:in std_logic_vector (3 downto 0);
    frame_bad:eek:ut std_logic;
    frame_good:eek:ut std_logic;
    frame_mrk:eek:ut std_logic);
    end component;

    component rx_fifo_wr_control is
    Port(data_clk:in std_logic;
    data:in std_logic_vector (3 downto 0);
    frame_mrk:in std_logic;
    rxdv:in std_logic;
    fifo_full:in std_logic;
    frame_good:in std_logic;
    frame_bad:in std_logic;
    fifo_wr_data:eek:ut std_logic_vector (4 downto 0);
    wr_fifo_en:eek:ut std_logic;
    rst:in std_logic;
    prog_full_thresh:eek:ut std_logic_vector(10 downto 0));
    end component;


    component rx_fifo is
    port (din:in std_logic_vector(4 downto 0);
    prog_empty_thresh:in std_logic_vector(10 downto 0);
    prog_full_thresh:in std_logic_vector(10 downto 0);
    rd_clk:in std_logic;
    rd_en:in std_logic;
    rst:in std_logic;
    wr_clk:in std_logic;
    wr_en:in std_logic;
    dout:eek:ut std_logic_vector(4 downto 0);
    empty:eek:ut std_logic;
    full:eek:ut std_logic;
    prog_empty:eek:ut std_logic;
    prog_full:eek:ut std_logic);
    end component;


    component cpu_rx_interface is
    port(rst:in std_logic;
    fifo_empty:in std_logic;
    rx_cpu_data_clk:in std_logic;
    rd_fifo_en:eek:ut std_logic;
    cpu_rx_en:in std_logic;
    rx_cpu_flg:eek:ut std_logic;
    prog_empty_thresh:eek:ut std_logic_vector(10 downto 0);
    data:in std_logic_vector (4 downto 0);
    rx_cpu_data:eek:ut std_logic_vector (4 downto 0));
    end component;


    signal sig_1:std_logic;
    signal sig_2:std_logic;
    signal sig_3:std_logic;
    signal sig_4:std_logic_vector(4 downto 0);
    signal sig_5:std_logic;
    signal sig_6:std_logic;
    signal sig_7:std_logic;
    signal sig_8:std_logic;
    signal sig_9:std_logic_vector(10 downto 0);
    signal sig_10:std_logic_vector(10 downto 0);
    signal sig_11:std_logic_vector(4 downto 0);


    begin

    U0:receiver_mac port map(rst=>rst,rxclk=>rxclk,rxdv=>rxdv,rxd=>rxd,
    frame_bad=>sig_1,frame_good=>sig_2,frame_mrk=>sig_3);

    U1:rx_fifo_wr_control port
    map(data_clk=>rxclk,frame_mrk=>sig_3,fifo_full=>sig_8,
    data=>rxd,rst=>rst,frame_good=>sig_2,frame_bad=>sig_1,

    rxdv=>rxdv,wr_fifo_en=>sig_6,fifo_wr_data=>sig_4,prog_full_thresh=>sig_9);

    U2:rx_fifo port
    map(din=>sig_4,rd_clk=>rx_cpu_data_clk,rd_en=>sig_5,rst=>rst,wr_clk=>rxclk,

    wr_en=>sig_6,dout=>sig_11,prog_empty=>sig_7,prog_full=>sig_8,prog_full_thresh=>sig_9,
    prog_empty_thresh=>sig_10,empty=>OPEN,full=>OPEN);

    U3:cpu_rx_interface port
    map(fifo_empty=>sig_7,rx_cpu_data_clk=>rx_cpu_data_clk,rd_fifo_en=>sig_5,

    cpu_rx_en=>cpu_rx_en,rx_cpu_flg=>rx_cpu_flg,rst=>rst,prog_empty_thresh=>sig_10,

    data=>sig_11,rx_cpu_data=>rx_cpu_data);

    end behavioral;


    ========Receiver
    MAC=========================================================================

    entity RECEIVER_MAC is
    Port ( rst : in STD_LOGIC;
    rxclk : in STD_LOGIC;
    rxdv : in STD_LOGIC;
    rxd : in STD_LOGIC_VECTOR (3 downto 0);
    frame_bad : out STD_LOGIC;
    frame_good : out STD_LOGIC;
    frame_mrk : out STD_LOGIC);
    end RECEIVER_MAC;

    architecture RTL of RECEIVER_MAC is
    component RECEIVER is
    Port ( rxd : in std_logic_vector (3 downto 0);
    rst :in std_logic;
    rxclk : in std_logic;
    rxdv : in STD_LOGIC;
    frame_bad : out std_logic;
    frame_good : out std_logic;
    frame_mrk : out std_logic;
    crcgen_en: out std_logic:='0';
    crcgen_rst:eek:ut std_logic:='0';
    crc:in std_logic_vector (31 downto 0));

    end component;

    component CRCGENERATOR is
    Port ( data_clk : in STD_LOGIC;
    data : in STD_LOGIC_VECTOR (3 downto 0);
    crc : out STD_LOGIC_VECTOR (31 downto 0):=x"00000000";
    gen_en : in STD_LOGIC;
    rst: in STD_LOGIC);
    end component;

    signal SIG_1:std_logic_vector(31 downto 0);
    signal SIG_2,SIG_3:std_logic;


    begin

    U0:RECEIVER port
    map(rst=>rst,rxclk=>RXCLK,rxdv=>RXDV,rxd=>RXD,crc=>SIG_1,

    frame_bad=>FRAME_BAD,frame_good=>FRAME_GOOD,frame_mrk=>frame_mrk,
    crcgen_en=>SIG_2,crcgen_rst=>SIG_3);

    U1:CRCGENERATOR port
    map(data_clk=>rxclk,gen_en=>SIG_2,data=>rxd,rst=>SIG_3,crc=>SIG_1);

    end RTL;

    ======================Receiver===============================================

    entity Receiver is
    Port ( rxd : in std_logic_vector (3 downto 0);
    rst :in std_logic;
    rxclk : in std_logic;
    rxdv : in STD_LOGIC;
    frame_bad : out std_logic;
    frame_good : out std_logic;
    frame_mrk : out std_logic;
    crcgen_en: out std_logic:='0';
    crcgen_rst:eek:ut std_logic:='0';
    crc:in std_logic_vector (31 downto 0));
    end Receiver;

    architecture RTL of Receiver is




    signal nibble_counter:integer range 0 to 4096;
    signal ip_length:std_logic_vector (15 downto 0);
    signal fcs_position:integer range 0 to 4096;
    signal err_flag:std_logic;
    signal nibble_counter_rst:std_logic;
    signal fcs:std_logic_vector (31 downto 0);



    begin

    sync: process
    (rxdv,rxd,nibble_counter,ip_length,crc,rst,nibble_counter_rst,rxclk)
    type receiver_state is
    (idle,wait_for_sfd,start_crcgen,stop_crcgen,check_da,check_protocol,
    read_data_till_fcs,check_fcs,wait_end,frm_good,frm_bad);
    variable state:receiver_state;

    begin

    if (rst = '1') then
    state:= idle;
    nibble_counter<=0;
    nibble_counter_rst<='0';
    fcs<=(others=>'0');
    ip_length<=(others=>'0');
    fcs_position<=0;
    err_flag<='0';
    elsif rising_edge(rxclk)then
    if (nibble_counter_rst='1') then
    nibble_counter<=0;
    else
    nibble_counter<=nibble_counter+1;
    end if;
    case state is
    when idle =>
    if rxdv='1' and rxd="0101" then
    state:= wait_for_sfd;
    nibble_counter_rst<='0';
    else
    nibble_counter_rst<='1';
    state:=idle;
    end if;

    when wait_for_sfd=>
    if rxd="1101" then
    state:=start_crcgen;
    end if;

    when start_crcgen=>
    state:=check_da;

    when check_da=>
    case nibble_counter is

    when 15=>
    if rxd=board_mac_address(43 downto 40) or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 16=>
    if rxd=board_mac_address(47 downto 44) or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 17=>
    if rxd=board_mac_address(35 downto 32) or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 18=>
    if rxd=board_mac_address(39 downto 36) or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 19=>
    if rxd=board_mac_address(27 downto 24) or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 20=>
    if rxd=board_mac_address(31 downto 28) or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 21=>
    if rxd=board_mac_address(19 downto 16) or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 22=>
    if rxd=board_mac_address(23 downto 20) or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 23=>
    if rxd=board_mac_address(11 downto 8) or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 24=>
    if rxd=board_mac_address(15 downto 12) or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 25=>
    if rxd=board_mac_address(3 downto 0)or rxd=x"F" then
    err_flag<='0';
    state:= check_da;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when 26=>
    if rxd=board_mac_address(7 downto 4) or rxd=x"F" then
    err_flag<='0';
    state:= check_protocol;
    else
    err_flag<='1';
    state:= wait_end;
    end if;
    when others=>
    state:= check_da;
    err_flag<='0';
    end case;

    when check_protocol=>
    case nibble_counter is

    --only valid protocols are IP and ARP
    when 39=>
    if rxd="1000" then
    state:= check_protocol;
    err_flag<='0';
    else
    state:= wait_end;
    err_flag<='1';
    end if;

    when 40=>
    if rxd="0000" then
    state:= check_protocol;
    err_flag<='0';
    else
    state:= wait_end;
    err_flag<='1';
    end if;


    when 41=>
    if rxd="0110" then --Frame type is ARP, hence frame size is 60
    bytes (data of 92 nibbles, type of 4 nibbles, 24 nibbles for dest and
    source addresses)
    fcs_position<=135; --fcs position will be a (frame size of 120
    nibbles+32 nibbles for preample and sfd)-1
    state:= read_data_till_fcs;
    err_flag<='0';

    elsif rxd="0000" then
    fcs_position<=0;
    state:= check_protocol;
    err_flag<='0';
    else
    state:= wait_end;
    err_flag<='1';
    end if;

    when 47=>
    ip_length(11 downto 8)<=rxd;
    state:= check_protocol;
    when 48=>
    ip_length(15 downto 12)<=rxd;
    state:= check_protocol;
    when 49=>
    ip_length(3 downto 0)<=rxd;
    state:= check_protocol;
    when 50=>
    ip_length(7 downto 4)<=rxd;
    state:= check_protocol;
    when 51=>
    if ip_length<"0000000000101110" then --payload length under
    minimum 46 bytes, frame size will be padded to 60 bytes
    fcs_position<=135;
    state:=read_data_till_fcs;
    else
    fcs_position<=conv_integer((ip_length+14)+(ip_length
    +14)+16-1);--frame size will be 2* (ip_length+14) where 14 is for
    preample in nibbles
    state:=read_data_till_fcs;
    end if;

    when others=>
    state:= check_protocol;
    err_flag<='0';
    end case;

    when read_data_till_fcs=>

    if nibble_counter=fcs_position then
    state:=stop_crcgen;
    --get first nibble of fcs--
    fcs(31 downto 28)<=rxd;
    fcs(27 downto 24)<=fcs(31 downto 28);
    fcs(23 downto 20)<=fcs(27 downto 24);
    fcs(19 downto 16)<=fcs(23 downto 20);
    fcs(15 downto 12)<=fcs(19 downto 16);
    fcs(11 downto 8)<=fcs(15 downto 12);
    fcs(7 downto 4)<=fcs(11 downto 8);
    fcs(3 downto 0)<=fcs(7 downto 4);

    else
    state:=read_data_till_fcs;
    end if;

    when stop_crcgen=>

    if nibble_counter=fcs_position+7 then

    state:=check_fcs;

    else

    state:=stop_crcgen;
    end if;


    fcs(31 downto 28)<=rxd;
    fcs(27 downto 24)<=fcs(31 downto 28);
    fcs(23 downto 20)<=fcs(27 downto 24);
    fcs(19 downto 16)<=fcs(23 downto 20);
    fcs(15 downto 12)<=fcs(19 downto 16);
    fcs(11 downto 8)<=fcs(15 downto 12);
    fcs(7 downto 4)<=fcs(11 downto 8);
    fcs(3 downto 0)<=fcs(7 downto 4);


    when check_fcs=>

    if crc(31 downto 0)=fcs(31 downto 0) then

    state:=frm_good;
    else
    state:=frm_bad;
    end if;



    when wait_end=>

    if rxdv='0' then
    if err_flag='1' then
    state:=frm_bad;
    else
    state:=frm_good;
    end if;
    end if;

    when frm_bad=>
    state:=idle;

    when frm_good=>
    state:=idle;

    when others =>
    state:= idle;
    end case;

    case state is
    when idle=>

    frame_mrk<='0';
    frame_good<='0';
    frame_bad<='0';
    crcgen_en<='0';
    crcgen_rst<='1';

    when wait_for_sfd=>
    frame_mrk<='0';
    frame_good<='0';
    frame_bad<='0';
    crcgen_en<='0';
    crcgen_rst<='0';

    when start_crcgen=>
    frame_mrk<='0';
    frame_good<='0';
    frame_bad<='0';
    crcgen_en<='1';
    crcgen_rst<='0';


    when check_da=>
    frame_mrk<='1';
    frame_good<='0';
    frame_bad<='0';
    crcgen_en<='1';
    crcgen_rst<='0';

    when check_protocol=>
    frame_mrk<='1';
    frame_good<='0';
    frame_bad<='0';
    crcgen_en<='1';
    crcgen_rst<='0';

    when read_data_till_fcs=>
    frame_mrk<='1';
    frame_good<='0';
    frame_bad<='0';
    crcgen_en<='1';
    crcgen_rst<='0';

    when stop_crcgen=>
    frame_mrk<='0';
    frame_good<='0';
    frame_bad<='0';
    crcgen_en<='0';
    crcgen_rst<='0';

    when check_fcs=>
    frame_mrk<='0';
    frame_good<='0';
    frame_bad<='0';
    crcgen_en<='0';
    crcgen_rst<='0';

    when wait_end=>
    frame_mrk<='0';
    frame_good<='0';
    frame_bad<='0';
    crcgen_en<='0';
    crcgen_rst<='0';

    when frm_good=>
    frame_mrk<='0';
    frame_good<='1';
    frame_bad<='0';
    crcgen_en<='0';
    crcgen_rst<='0';

    when frm_bad=>
    frame_mrk<='0';
    frame_good<='0';
    frame_bad<='1';
    crcgen_en<='0';
    crcgen_rst<='0';

    when others=>
    frame_mrk<='0';
    frame_good<='0';
    frame_bad<='0';
    crcgen_en<='0';
    crcgen_rst<='1';
    end case;

    end if;
    end process;

    end RTL;


    =======================

    Cheers

    Maurizio Gencarelli
    Defence Science & Technology Organisation Salisbury
    Australia
     
    , Jul 2, 2007
    #5
  6. KJ Guest

    <> wrote in message
    news:...
    > On Jul 2, 10:58 pm, wrote:
    >> On Jul 2, 7:52 pm, "KJ" <> wrote:
    >>
    >>
    >>
    >>
    >>
    >> > <> wrote in message

    >>

    <snip>
    >It is like the
    > signal interconnects (ie. SIG_1,SIG_2 etc) within the instantiation
    > that connects these signals from RECEIVER.VHDL entity to
    > RX_FIFO_WR_CONTROL.VHDL via RECEIVER_MAC.VHDL entity is introducing
    > delta delays.

    It's not..trust me

    >Signals frame_bad, frame_good, or frame_mrk and signals
    > data and rxdv from the test bench are all registered, so why the
    > delay ?.


    I've snipped out small portions of your testbench and added my comments
    below the sections.

    KJ: OK, so here you instantiate the unit you're testing and giving it the
    signal rxclk_sig as the clock input.
    BEGIN
    uut: ETHER_RX_TOPLEVEL
    port map(
    rxclk=>RXCLK_sig,
    rxd=>RXD_sig,
    ...);

    -----------------
    KJ: Here you assign rxclk_sig from some other signal called clk_sig
    rxclk_sig<=CLK_sig;

    -- Test Bench Statements
    tb : process(CLK_sig)
    file vector_file : TEXT open READ_MODE is "c:/edata.txt";
    variable file_line:line;
    variable str_stimulus_in: string(8 downto 1);
    variable stimulus_in: std_logic_vector(7 downto 0);
    begin
    if rising_edge(CLK_sig) then
    readline(VECTOR_FILE,file_line);
    read(file_line,str_stimulus_in);
    stimulus_in := str_to_stdvec( str_stimulus_in);
    end if;
    end if;

    rxclk_sig<=CLK_sig;
    rxdv_sig<=stimulus_in(4);
    rxd_sig(3)<=stimulus_in(3);
    rxd_sig(2)<=stimulus_in(2);
    rxd_sig(1)<=stimulus_in(1);
    rxd_sig(0)<=stimulus_in(0);
    end PROCESS tb;
    KJ: Here you have a process that is clocked by CLK_sig that ends up
    assigning to the signals rxd_sig.
    -----------------------

    Now take a close look at what happens at the rising edge of CLK_sig. On the
    simulation delta cycle AFTER CLK_sig switches from 0 to 1, the following
    will happen:
    - rxclk_sig will change from 0 to 1
    - rxd_sig will change as well.

    So any code inside UUT that looks for the rising edge of rxclk will be
    catching the 'latest' values of 'rxd' because they changed at the exact same
    moment. But now look at code inside UUT that generates some output signal,
    that output will not change until the NEXT simulation delta so anything that
    reads it (like some other entity) will not pick it up until the next rising
    edge.

    As I said in the previous post, you've got your inputs switching on the
    exact same simulation delta that you're switching the inputs...which is a
    'no-no', you've violated setup time. If you took UUT and assigned
    "rxclk=>CLK_sig," you wouldn't be seeing the differences. What you need to
    keep in mind is that each assignment takes one simulation delta cycle to
    occur. A perverse example would be something like

    clk_dly1 <= clk;
    clk_dly2 <= clk_dly1;
    clk_dly3 <= clk_dly2;
    clk_dly4 <= clk_dly3;
    clk_dly5 <= clk_dly4;

    The signal clk_dly5 would happen 5 simulation deltas (but 0 'time') later
    then the signal 'clk'. You don't see this if you look at the waveforms but
    if you look at a listing that shows every transition you will.

    KJ
     
    KJ, Jul 3, 2007
    #6
  7. Guest

    On Jul 3, 9:56 am, "KJ" <> wrote:
    > <> wrote in message
    >
    > news:...> On Jul 2, 10:58 pm, wrote:
    > >> On Jul 2, 7:52 pm, "KJ" <> wrote:

    >
    > >> > <> wrote in message

    >
    > <snip>
    > >It is like the
    > > signal interconnects (ie. SIG_1,SIG_2 etc) within the instantiation
    > > that connects these signals from RECEIVER.VHDL entity to
    > > RX_FIFO_WR_CONTROL.VHDL via RECEIVER_MAC.VHDL entity is introducing
    > > delta delays.

    >
    > It's not..trust me
    >
    > >Signals frame_bad, frame_good, or frame_mrk and signals
    > > data and rxdv from the test bench are all registered, so why the
    > > delay ?.

    >
    > I've snipped out small portions of your testbench and added my comments
    > below the sections.
    >
    > KJ: OK, so here you instantiate the unit you're testing and giving it the
    > signal rxclk_sig as the clock input.
    > BEGIN
    > uut: ETHER_RX_TOPLEVEL
    > port map(
    > rxclk=>RXCLK_sig,
    > rxd=>RXD_sig,
    > ...);
    >
    > -----------------
    > KJ: Here you assign rxclk_sig from some other signal called clk_sig
    > rxclk_sig<=CLK_sig;
    >
    > -- Test Bench Statements
    > tb : process(CLK_sig)
    > file vector_file : TEXT open READ_MODE is "c:/edata.txt";
    > variable file_line:line;
    > variable str_stimulus_in: string(8 downto 1);
    > variable stimulus_in: std_logic_vector(7 downto 0);
    > begin
    > if rising_edge(CLK_sig) then
    > readline(VECTOR_FILE,file_line);
    > read(file_line,str_stimulus_in);
    > stimulus_in := str_to_stdvec( str_stimulus_in);
    > end if;
    > end if;
    >
    > rxclk_sig<=CLK_sig;
    > rxdv_sig<=stimulus_in(4);
    > rxd_sig(3)<=stimulus_in(3);
    > rxd_sig(2)<=stimulus_in(2);
    > rxd_sig(1)<=stimulus_in(1);
    > rxd_sig(0)<=stimulus_in(0);
    > end PROCESS tb;
    > KJ: Here you have a process that is clocked by CLK_sig that ends up
    > assigning to the signals rxd_sig.
    > -----------------------
    >
    > Now take a close look at what happens at the rising edge of CLK_sig. On the
    > simulation delta cycle AFTER CLK_sig switches from 0 to 1, the following
    > will happen:
    > - rxclk_sig will change from 0 to 1
    > - rxd_sig will change as well.
    >
    > So any code inside UUT that looks for the rising edge of rxclk will be
    > catching the 'latest' values of 'rxd' because they changed at the exact same
    > moment. But now look at code inside UUT that generates some output signal,
    > that output will not change until the NEXT simulation delta so anything that
    > reads it (like some other entity) will not pick it up until the next rising
    > edge.
    >
    > As I said in the previous post, you've got your inputs switching on the
    > exact same simulation delta that you're switching the inputs...which is a
    > 'no-no', you've violated setup time. If you took UUT and assigned
    > "rxclk=>CLK_sig," you wouldn't be seeing the differences. What you need to
    > keep in mind is that each assignment takes one simulation delta cycle to
    > occur. A perverse example would be something like
    >
    > clk_dly1 <= clk;
    > clk_dly2 <= clk_dly1;
    > clk_dly3 <= clk_dly2;
    > clk_dly4 <= clk_dly3;
    > clk_dly5 <= clk_dly4;
    >
    > The signal clk_dly5 would happen 5 simulation deltas (but 0 'time') later
    > then the signal 'clk'. You don't see this if you look at the waveforms but
    > if you look at a listing that shows every transition you will.
    >
    > KJ


    Thanks KJ, now I understand.

    I changed my test bench to below and it works !

    I never suspected my test bench, it looked okay in Modelsim.

    rxclk_sig<=CLK_sig;
    -- Test Bench Statements
    tb : process(rxclk_sig)

    file vector_file : TEXT open READ_MODE is "c:/edata.txt";
    variable file_line:line;


    variable str_stimulus_in: string(8 downto 1);
    variable stimulus_in: std_logic_vector(7 downto 0);

    begin

    if not endFILE(VECTOR_FILE) then
    if rising_edge(rxclk_sig) then
    readline(VECTOR_FILE,file_line);
    read(file_line,str_stimulus_in);
    stimulus_in := str_to_stdvec( str_stimulus_in);
    end if;
    end if;

    -- Stimulus Assignments ----------------------------------


    rxdv_sig<=stimulus_in(4);
    rxd_sig(3)<=stimulus_in(3);
    rxd_sig(2)<=stimulus_in(2);
    rxd_sig(1)<=stimulus_in(1);
    rxd_sig(0)<=stimulus_in(0);


    end PROCESS tb;
     
    , Jul 3, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    24
    Views:
    1,003
    Mike Treseler
    Jul 29, 2005
  2. Edvard Majakari
    Replies:
    6
    Views:
    349
    Peter Otten
    Feb 18, 2004
  3. Elmo Fuchs
    Replies:
    4
    Views:
    2,697
    PeteS
    Nov 18, 2006
  4. himassk
    Replies:
    1
    Views:
    1,254
    Paul Uiterlinden
    May 16, 2007
  5. Replies:
    2
    Views:
    672
    Martin Thompson
    Jun 27, 2007
Loading...

Share This Page