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