972 - How is the FIXEDDELAY attribute used and implemented in Single Data Rate (SDR) mode in a LatticeECP3 device?
In SDR mode, the DELAYB has a fixed value calculated by the tool.
This value will compensate for the delay from the input clock buffer through the primary or secondary (no edge) clock network to the input CLK pin of the input IO register. The DELAYB value will be different depending on whether the clock routes to a primary or secondary clock network.
You can implement the delay via the HDL "FIXEDDELAY" attribute on the input buffer.
This delay will ensure that even if the input data and clock have 0 hold-time delay relationship, delaying the data by FIXEDELAY will compensate for the clock delay in the chip and prevent hold-time violations.
In order for this property to work, you need to assign the input clock to an SCLK input. No PLL or DLLs can be in the path of the SCLK. Otherwise the tool may miscalculate the required delay .The clock route has to be Primary or Secondary, not an edge clock.
Please see below a Verilog and VHDL example.
- Verilog:
module top(clk, rstn, din, dout);
input clk;
input rstn;
input din ;
output dout;
reg din_io;
reg din_ff;
reg dout;
IB IB (.I(din), .O(din_buf)) /* synthesis FIXEDDELAY="TRUE" */ ;
always @(posedge clk or negedge rstn)
begin
if (~rstn)
begin
din_io <= 1'b0;
din_ff <= 1'b0;
dout <= 1'b0;
end
else
begin
din_io <= din_buf;
din_ff <= din_io;
dout <= din_ff;
end
end
endmodule
--------------------
- VHDL:
-- synopsys translate_off
library ECP3;
use ECP3.COMPONENTS.all;
-- synopsys translate_on
library IEEE;
use IEEE.std_logic_1164.all;
entity top is
port (
clk: in std_logic ;
rstn: in std_logic ;
din: in std_logic ;
dout: out std_logic
);
end entity top;
architecture top_arch of top is
component IB
port (
I : in std_logic;
O : out std_logic);
end component;
attribute FIXEDDELAY: string;
attribute FIXEDDELAY of IB_inst : label is "TRUE";
signal din_io : std_logic ;
signal din_ff : std_logic ;
signal din_buf : std_logic ;
begin
IB_inst : IB
port map (
I => din,
O => din_buf
);
SEQ: process (clk, rstn)
begin
if (rstn='0') then
din_io <= '0';
din_ff <= '0';
dout <= '0';
elsif rising_edge(clk) then
din_io <= din_buf;
din_ff <= din_io;
dout <= din_ff;
end if;
end process SEQ;
end architecture top_arch ;