PDA

View Full Version : clock delay when testing different inputs in FSM ?


07-02-2007, 01:45 AM
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_con dition,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

07-02-2007, 03:10 AM
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.

[email protected] 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_con dition,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

KJ
07-02-2007, 11:52 AM
<[email protected]> wrote in message
news:[email protected] ups.com...
>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

07-02-2007, 02:58 PM
On Jul 2, 7:52 pm, "KJ" <[email protected]> wrote:
> <[email protected]> wrote in message
>
> news:[email protected] ups.com...>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

07-02-2007, 03:34 PM
On Jul 2, 10:58 pm, [email protected] wrote:
> On Jul 2, 7:52 pm, "KJ" <[email protected]> wrote:
>
>
>
>
>
> > <[email protected]> wrote in message
>
> >news:[email protected] ups.com...>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: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 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:out std_logic;
frame_good:out std_logic;
frame_mrk:out 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: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 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:out std_logic_vector(4 downto 0);
empty:out std_logic;
full:out std_logic;
prog_empty:out std_logic;
prog_full:out 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:out std_logic;
cpu_rx_en:in std_logic;
rx_cpu_flg:out std_logic;
prog_empty_thresh:out std_logic_vector(10 downto 0);
data:in std_logic_vector (4 downto 0);
rx_cpu_data:out 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:out 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:out 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

KJ
07-03-2007, 01:56 AM
<[email protected]> wrote in message
news:[email protected] ups.com...
> On Jul 2, 10:58 pm, [email protected] wrote:
>> On Jul 2, 7:52 pm, "KJ" <[email protected]> wrote:
>>
>>
>>
>>
>>
>> > <[email protected]> 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

07-03-2007, 03:56 PM
On Jul 3, 9:56 am, "KJ" <[email protected]> wrote:
> <[email protected]> wrote in message
>
> news:[email protected] ups.com...> On Jul 2, 10:58 pm, [email protected] wrote:
> >> On Jul 2, 7:52 pm, "KJ" <[email protected]> wrote:
>
> >> > <[email protected]> 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;