johnnysmith911
Newbie level 5
I have a design like this ( full code, UCF & test bench towards the end)..
"data" is an inout port & it's value is fed into "counter" if the flag "readwrite" is 0, i.e. in read mode. In this mode, I have a constraint that the "data" port's value must be registered only after 9ns from the rising clock edge, which is done through this line in the UCF.
When I simulate my design via a test bench, I can see that the input is actually being registered before the 9 ns mark.
Now, as you can see from the post-P&R timing diagram, at the 9 ns mark as pointed to by the 2nd cursor, the value of "data" is 10101010 but at the end of that clock cycle/start of the next clock cycle, you can see that the value of "counter_out" is 01010101 which is the value before the 9 ns mark.
If the data port was read at the 9ns mark as specified by the constraint,
TIMEGRP "DATA_GROUP" OFFSET = IN 11 ns VALID 20 ns BEFORE "clk" RISING;
shouldn't the value at the end of that clock cycle be 10101010?
Thanks,
John
VHDL code:
UCF:
Testbench:
Code:
data_in <= data when (readwrite = '0' and reset = '0') else (others =>'0');
process(clk,reset)
.
.
if(reset = '1') then
.
.
elsif(clk'event and clk = '1') then
.
if(readwrite = '0') then
counter <= data_in;
end if;
.
counter_out <= counter;
end if;
"data" is an inout port & it's value is fed into "counter" if the flag "readwrite" is 0, i.e. in read mode. In this mode, I have a constraint that the "data" port's value must be registered only after 9ns from the rising clock edge, which is done through this line in the UCF.
Code:
NET "data[*]" TNM = "DATA_GROUP";
TIMEGRP "DATA_GROUP" OFFSET = OUT 12.5 ns AFTER "clk" RISING;
[B]TIMEGRP "DATA_GROUP" OFFSET = IN 11 ns VALID 20 ns BEFORE "clk" RISING[/B];
When I simulate my design via a test bench, I can see that the input is actually being registered before the 9 ns mark.
Now, as you can see from the post-P&R timing diagram, at the 9 ns mark as pointed to by the 2nd cursor, the value of "data" is 10101010 but at the end of that clock cycle/start of the next clock cycle, you can see that the value of "counter_out" is 01010101 which is the value before the 9 ns mark.
If the data port was read at the 9ns mark as specified by the constraint,
TIMEGRP "DATA_GROUP" OFFSET = IN 11 ns VALID 20 ns BEFORE "clk" RISING;
shouldn't the value at the end of that clock cycle be 10101010?
Thanks,
John
VHDL code:
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity interface is
port(
clk : in std_logic;
reset: in std_logic;
data : inout std_logic_vector(7 downto 0);
readwrite: in std_logic;
counter_out : out std_logic_vector(7 downto 0)
);
end interface;
architecture Behavioral of interface is
type counter_state is
(
state_read,
state_wait,
state_write
);
signal counter : std_logic_vector(7 downto 0);-- := (OTHERS => '0');
signal data_in, data_out : std_logic_vector(7 downto 0);-- := (OTHERS => '0');
signal state_counter : counter_state;
begin
--Get data from bus everytime
data_in <= data when (readwrite = '0' and reset = '0') else (others =>'0');
--Write counter to data_out all the time
data_out <= counter when (reset = '0') else (others =>'0');
--Driver to send data out of the inout port
data_bus_driver: process(reset,readwrite,data_out)
begin
--
if(reset = '1') then
data <= (OTHERS => 'Z');
elsif(readwrite = '1') then
data <= data_out;
else
data <= (OTHERS => 'Z');
end if;
end process;
--State machine
process(clk,reset)
begin
if(reset = '1') then
state_counter <= state_read;
counter <= (OTHERS => '0');
counter_out <= (OTHERS => '0');
--data <= (OTHERS => 'Z');
elsif(clk'event and clk = '1') then
case state_counter is
when state_read =>
if(readwrite = '0') then
counter <= data_in;
state_counter <= state_read;
else
state_counter <= state_wait;
end if;
when state_wait =>
if(readwrite = '1') then
counter <= std_logic_vector(unsigned(counter) + 1);
state_counter <= state_write;
else
state_counter <= state_read;
end if;
when state_write =>
if(readwrite = '1') then
counter <= std_logic_vector(unsigned(counter) + 1);
state_counter <= state_write;
else
state_counter <= state_wait;
end if;
end case;
counter_out <= counter;
end if;
end process;
end Behavioral;
UCF:
Code:
NET "clk" TNM_NET = "clk";
TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50 %;
NET "readwrite" OFFSET = IN 11 ns VALID 20 ns BEFORE "clk" RISING;
#NET "readwrite" TNM = "enable";
#TIMESPEC TS_tristate = FROM "enable" TO "DATA_GROUP" 4.5 ns ;
NET "data[*]" TNM = "DATA_GROUP";
TIMEGRP "DATA_GROUP" OFFSET = OUT 12.5 ns AFTER "clk" RISING;
TIMEGRP "DATA_GROUP" OFFSET = IN 11 ns VALID 20 ns BEFORE "clk" RISING;
# PlanAhead Generated IO constraints
NET "data[7]" IOSTANDARD = LVCMOS33;
NET "data[6]" IOSTANDARD = LVCMOS33;
NET "data[5]" IOSTANDARD = LVCMOS33;
NET "data[4]" IOSTANDARD = LVCMOS33;
NET "data[3]" IOSTANDARD = LVCMOS33;
NET "data[2]" IOSTANDARD = LVCMOS33;
NET "data[1]" IOSTANDARD = LVCMOS33;
NET "data[0]" IOSTANDARD = LVCMOS33;
NET "data[7]" SLEW = FAST;
NET "data[6]" SLEW = FAST;
NET "data[5]" SLEW = FAST;
NET "data[4]" SLEW = FAST;
NET "data[3]" SLEW = FAST;
NET "data[2]" SLEW = FAST;
NET "data[1]" SLEW = FAST;
NET "data[0]" SLEW = FAST;
NET "clk" IOSTANDARD = LVCMOS33;
NET "readwrite" IOSTANDARD = LVCMOS33;
# PlanAhead Generated physical constraints
NET "data[5]" LOC = U7;
NET "data[1]" LOC = V7;
NET "data[4]" LOC = T4;
NET "data[0]" LOC = V4;
NET "data[7]" LOC = U5;
NET "data[6]" LOC = V5;
NET "data[3]" LOC = R3;
NET "data[2]" LOC = T3;
NET "clk" LOC = R8;
NET "readwrite" LOC = U8;
Testbench:
Code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY inout_test_tb IS
END inout_test_tb;
ARCHITECTURE behavior OF inout_test_tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT interface
PORT(
clk : IN std_logic;
reset : IN std_logic;
data : INOUT std_logic_vector(7 downto 0);
readwrite : IN std_logic;
counter_out : out std_logic_vector(7 downto 0)
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal reset : std_logic := '0';
signal readwrite : std_logic := '0';
--BiDirs
signal data : std_logic_vector(7 downto 0);
--Outputs
signal counter_out : std_logic_vector(7 downto 0);
signal data_out_tb : std_logic_vector(7 downto 0) := (OTHERS => '0');
signal data_in_tb : std_logic_vector(7 downto 0) := (OTHERS => '0');
-- Clock period definitions
constant clk_period : time := 20 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: interface PORT MAP (
clk => clk,
reset => reset,
data => data,
readwrite => readwrite,
counter_out => counter_out
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
--data <= data_in_tb when (readwrite = '0') else (others => 'Z');
--data_out_tb <= data when (readwrite = '1') else (others => '0');
-- Stimulus process
stim_proc: process
begin
reset <= '1';
data <= (others => '0');
wait for clk_period*10;
reset <= '0';
readwrite <= '0';
data_in_tb <= "01010101";
data <= "01010101";
wait until rising_edge(clk);
wait for 6 ns;
data_in_tb <= "10101010";
data <= "10101010";
wait until rising_edge(clk);
wait for 6 ns;
data_in_tb <= "11111111";
data <= "11111111";
wait for clk_period*10;
wait until rising_edge(clk);
wait for 8 ns;
readwrite <= '1';
wait until rising_edge(clk);
data <= (others => 'Z');
data_out_tb <= data;
wait until rising_edge(clk);
data <= (others => 'Z');
data_out_tb <= data;
wait until rising_edge(clk);
data <= (others => 'Z');
data_out_tb <= data;
wait until rising_edge(clk);
data <= (others => 'Z');
data_out_tb <= data;
wait until rising_edge(clk);
data <= (others => 'Z');
data_out_tb <= data;
wait for 8 ns;
readwrite <= '0';
wait until rising_edge(clk);
data_in_tb <= "10101010";
data <= "10101010";
wait;
end process;
END;