git-svn-id: http://moon:8086/svn/vhdl/trunk@1095 cc03376c-175c-47c8-b038-4cd826a8556b
52597 lines
2.3 MiB
Plaintext
52597 lines
2.3 MiB
Plaintext
-- Copyright (C) 1991-2015 Altera Corporation. All rights reserved.
|
|
-- Your use of Altera Corporation's design tools, logic functions
|
|
-- and other software and tools, and its AMPP partner logic
|
|
-- functions, and any output files from any of the foregoing
|
|
-- (including device programming or simulation files), and any
|
|
-- associated documentation or information are expressly subject
|
|
-- to the terms and conditions of the Altera Program License
|
|
-- Subscription Agreement, the Altera Quartus II License Agreement,
|
|
-- the Altera MegaCore Function License Agreement, or other
|
|
-- applicable license agreement, including, without limitation,
|
|
-- that your use is for the sole purpose of programming logic
|
|
-- devices manufactured by Altera and sold by Altera or its
|
|
-- authorized distributors. Please refer to the applicable
|
|
-- agreement for further details.
|
|
-- Quartus II 15.0.0 Build 145 04/22/2015
|
|
---START_PACKAGE_HEADER-----------------------------------------------------
|
|
--
|
|
-- Package Name : ALTERA_COMMON_CONVERSION
|
|
--
|
|
-- Description : Common conversion functions
|
|
--
|
|
---END_PACKAGE_HEADER--------------------------------------------------------
|
|
|
|
-- BEGINING OF PRIMITIVE
|
|
|
|
Library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
entity LCELL is
|
|
port(
|
|
a_in : in std_logic;
|
|
a_out : out std_logic);
|
|
end LCELL;
|
|
architecture BEHAVIOR of LCELL is
|
|
begin
|
|
a_out <= a_in;
|
|
end BEHAVIOR;
|
|
|
|
-- BEGINING OF PACKAGE
|
|
Library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use std.textio.all;
|
|
|
|
-- PACKAGE DECLARATION
|
|
package ALTERA_COMMON_CONVERSION is
|
|
-- FUNCTION DECLARATION
|
|
function INT_TO_STR_RAM (value : in integer) return string;
|
|
function INT_TO_STR_ARITH (value : in integer) return string;
|
|
function HEX_STR_TO_INT (str : in string) return integer;
|
|
function BIN_STR_TO_INT (str : in string) return integer;
|
|
function OCT_STR_TO_INT (str : in string) return integer;
|
|
function INT_STR_TO_INT (str : in string) return integer;
|
|
function ALPHA_TOLOWER (given_string : in string) return string;
|
|
procedure SHRINK_LINE (str_line : inout line; pos : in integer);
|
|
end ALTERA_COMMON_CONVERSION;
|
|
|
|
package body ALTERA_COMMON_CONVERSION is
|
|
-- This function converts an integer to a string
|
|
function INT_TO_STR_RAM (value : in integer) return string is
|
|
variable ivalue : integer := 0;
|
|
variable index : integer := 0;
|
|
variable digit : integer := 0;
|
|
variable line_no: string(8 downto 1) := " ";
|
|
begin
|
|
ivalue := value;
|
|
index := 1;
|
|
|
|
while (ivalue > 0) loop
|
|
digit := ivalue MOD 10;
|
|
ivalue := ivalue/10;
|
|
case digit is
|
|
when 0 => line_no(index) := '0';
|
|
when 1 => line_no(index) := '1';
|
|
when 2 => line_no(index) := '2';
|
|
when 3 => line_no(index) := '3';
|
|
when 4 => line_no(index) := '4';
|
|
when 5 => line_no(index) := '5';
|
|
when 6 => line_no(index) := '6';
|
|
when 7 => line_no(index) := '7';
|
|
when 8 => line_no(index) := '8';
|
|
when 9 => line_no(index) := '9';
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Illegal number!"
|
|
SEVERITY ERROR;
|
|
end case;
|
|
index := index + 1;
|
|
end loop;
|
|
|
|
return line_no;
|
|
end INT_TO_STR_RAM;
|
|
|
|
function INT_TO_STR_ARITH (value : in integer) return string is
|
|
variable ivalue : integer := 0;
|
|
variable index : integer := 0;
|
|
variable digit : integer := 0;
|
|
variable temp: string(10 downto 1) := "0000000000";
|
|
begin
|
|
ivalue := value;
|
|
index := 1;
|
|
|
|
while (ivalue > 0) loop
|
|
digit := ivalue mod 10;
|
|
ivalue := ivalue/10;
|
|
|
|
case digit is
|
|
when 0 => temp(index) := '0';
|
|
when 1 => temp(index) := '1';
|
|
when 2 => temp(index) := '2';
|
|
when 3 => temp(index) := '3';
|
|
when 4 => temp(index) := '4';
|
|
when 5 => temp(index) := '5';
|
|
when 6 => temp(index) := '6';
|
|
when 7 => temp(index) := '7';
|
|
when 8 => temp(index) := '8';
|
|
when 9 => temp(index) := '9';
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Illegal number!"
|
|
SEVERITY ERROR;
|
|
end case;
|
|
index := index + 1;
|
|
end loop;
|
|
|
|
if value < 0 then
|
|
return '-'& temp(index downto 1);
|
|
else
|
|
return temp(index downto 1);
|
|
end if;
|
|
end INT_TO_STR_ARITH;
|
|
|
|
-- This function converts a hexadecimal number to an integer
|
|
function HEX_STR_TO_INT (str : in string) return integer is
|
|
variable len : integer := str'length;
|
|
variable ivalue : integer := 0;
|
|
variable digit : integer := 0;
|
|
begin
|
|
for i in len downto 1 loop
|
|
case str(i) is
|
|
when '0' => digit := 0;
|
|
when '1' => digit := 1;
|
|
when '2' => digit := 2;
|
|
when '3' => digit := 3;
|
|
when '4' => digit := 4;
|
|
when '5' => digit := 5;
|
|
when '6' => digit := 6;
|
|
when '7' => digit := 7;
|
|
when '8' => digit := 8;
|
|
when '9' => digit := 9;
|
|
when 'A' => digit := 10;
|
|
when 'a' => digit := 10;
|
|
when 'B' => digit := 11;
|
|
when 'b' => digit := 11;
|
|
when 'C' => digit := 12;
|
|
when 'c' => digit := 12;
|
|
when 'D' => digit := 13;
|
|
when 'd' => digit := 13;
|
|
when 'E' => digit := 14;
|
|
when 'e' => digit := 14;
|
|
when 'F' => digit := 15;
|
|
when 'f' => digit := 15;
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Illegal hex character "& str(i) & "! "
|
|
SEVERITY ERROR;
|
|
end case;
|
|
ivalue := ivalue * 16 + digit;
|
|
end loop;
|
|
return ivalue;
|
|
end HEX_STR_TO_INT;
|
|
|
|
-- This function converts a binary number to an integer
|
|
function BIN_STR_TO_INT (str : in string) return integer is
|
|
variable len : integer := str'length;
|
|
variable ivalue : integer := 0;
|
|
variable digit : integer := 0;
|
|
begin
|
|
for i in len downto 1 loop
|
|
case str(i) is
|
|
when '0' => digit := 0;
|
|
when '1' => digit := 1;
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Illegal bin character "& str(i) & "! "
|
|
SEVERITY ERROR;
|
|
end case;
|
|
ivalue := ivalue * 2 + digit;
|
|
end loop;
|
|
return ivalue;
|
|
end BIN_STR_TO_INT;
|
|
|
|
-- This function converts a octadecimal number to an integer
|
|
function OCT_STR_TO_INT (str : in string) return integer is
|
|
variable len : integer := str'length;
|
|
variable ivalue : integer := 0;
|
|
variable digit : integer := 0;
|
|
begin
|
|
for i in len downto 1 loop
|
|
case str(i) is
|
|
when '0' => digit := 0;
|
|
when '1' => digit := 1;
|
|
when '2' => digit := 2;
|
|
when '3' => digit := 3;
|
|
when '4' => digit := 4;
|
|
when '5' => digit := 5;
|
|
when '6' => digit := 6;
|
|
when '7' => digit := 7;
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Illegal octadecimal character "& str(i) & "! "
|
|
SEVERITY ERROR;
|
|
end case;
|
|
ivalue := ivalue * 8 + digit;
|
|
end loop;
|
|
return ivalue;
|
|
end OCT_STR_TO_INT;
|
|
|
|
-- This function converts a integer string to an integer
|
|
function INT_STR_TO_INT (str : in string) return integer is
|
|
variable len : integer := str'length;
|
|
variable newdigit : integer := 0;
|
|
variable sign : integer := 1;
|
|
variable digit : integer := 0;
|
|
begin
|
|
for i in 1 to len loop
|
|
case str(i) is
|
|
when '-' =>
|
|
if i = 1 then
|
|
sign := -1;
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "Illegal Character "& str(i) & "i n string parameter! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
when '0' =>
|
|
digit := 0;
|
|
when '1' =>
|
|
digit := 1;
|
|
when '2' =>
|
|
digit := 2;
|
|
when '3' =>
|
|
digit := 3;
|
|
when '4' =>
|
|
digit := 4;
|
|
when '5' =>
|
|
digit := 5;
|
|
when '6' =>
|
|
digit := 6;
|
|
when '7' =>
|
|
digit := 7;
|
|
when '8' =>
|
|
digit := 8;
|
|
when '9' =>
|
|
digit := 9;
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Illegal Character "& str(i) & "in string parameter! "
|
|
SEVERITY ERROR;
|
|
end case;
|
|
newdigit := newdigit * 10 + digit;
|
|
end loop;
|
|
|
|
return (sign*newdigit);
|
|
end;
|
|
|
|
-- converts uppercase parameter values (e.g. "AUTO") to lowercase ("auto")
|
|
function ALPHA_TOLOWER (given_string : in string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable result_string : string(given_string'low to given_string'high);
|
|
|
|
begin
|
|
for i in given_string'low to given_string'high loop
|
|
case given_string(i) is
|
|
when 'A' => result_string(i) := 'a';
|
|
when 'B' => result_string(i) := 'b';
|
|
when 'C' => result_string(i) := 'c';
|
|
when 'D' => result_string(i) := 'd';
|
|
when 'E' => result_string(i) := 'e';
|
|
when 'F' => result_string(i) := 'f';
|
|
when 'G' => result_string(i) := 'g';
|
|
when 'H' => result_string(i) := 'h';
|
|
when 'I' => result_string(i) := 'i';
|
|
when 'J' => result_string(i) := 'j';
|
|
when 'K' => result_string(i) := 'k';
|
|
when 'L' => result_string(i) := 'l';
|
|
when 'M' => result_string(i) := 'm';
|
|
when 'N' => result_string(i) := 'n';
|
|
when 'O' => result_string(i) := 'o';
|
|
when 'P' => result_string(i) := 'p';
|
|
when 'Q' => result_string(i) := 'q';
|
|
when 'R' => result_string(i) := 'r';
|
|
when 'S' => result_string(i) := 's';
|
|
when 'T' => result_string(i) := 't';
|
|
when 'U' => result_string(i) := 'u';
|
|
when 'V' => result_string(i) := 'v';
|
|
when 'W' => result_string(i) := 'w';
|
|
when 'X' => result_string(i) := 'x';
|
|
when 'Y' => result_string(i) := 'y';
|
|
when 'Z' => result_string(i) := 'z';
|
|
when others => result_string(i) := given_string(i);
|
|
end case;
|
|
end loop;
|
|
|
|
return (result_string(given_string'low to given_string'high));
|
|
end;
|
|
|
|
-- This procedure "cuts" the str_line into desired length
|
|
procedure SHRINK_LINE (str_line : inout line; pos : in integer) is
|
|
subtype nstring is string(1 to pos);
|
|
variable str : nstring;
|
|
begin
|
|
if (pos >= 1) then
|
|
read(str_line, str);
|
|
end if;
|
|
end;
|
|
end ALTERA_COMMON_CONVERSION;
|
|
-- END OF PACKAGE
|
|
|
|
---START_PACKAGE_HEADER-----------------------------------------------------
|
|
--
|
|
-- Package Name : ALTERA_MF_HINT_EVALUATION
|
|
--
|
|
-- Description : Common function to grep the value of altera specific parameters
|
|
-- within the lpm_hint parameter.
|
|
--
|
|
---END_PACKAGE_HEADER--------------------------------------------------------
|
|
|
|
-- BEGINING OF PACKAGE
|
|
Library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
-- PACKAGE DECLARATION
|
|
package ALTERA_MF_HINT_EVALUATION is
|
|
-- FUNCTION DECLARATION
|
|
function get_parameter_value( constant given_string : string;
|
|
compare_param_name : string) return string;
|
|
end ALTERA_MF_HINT_EVALUATION;
|
|
|
|
package body ALTERA_MF_HINT_EVALUATION is
|
|
|
|
-- This function will search through the string (given string) to look for a match for the
|
|
-- a given parameter(compare_param_name). It will return the value for the given parameter.
|
|
function get_parameter_value( constant given_string : string;
|
|
compare_param_name : string) return string is
|
|
variable param_name_left_index : integer := given_string'length;
|
|
variable param_name_right_index : integer := given_string'length;
|
|
variable param_value_left_index : integer := given_string'length;
|
|
variable param_value_right_index : integer := given_string'length;
|
|
variable set_right_index : boolean := true;
|
|
variable extract_param_value : boolean := true;
|
|
variable extract_param_name : boolean := false;
|
|
variable param_found : boolean := false;
|
|
|
|
begin
|
|
|
|
-- checking every character of the given_string from right to left.
|
|
for i in given_string'length downto 1 loop
|
|
if (given_string(i) /= ' ') then
|
|
if (given_string(i) = '=') then
|
|
extract_param_value := false;
|
|
extract_param_name := true;
|
|
set_right_index := true;
|
|
elsif (given_string(i) = ',') then
|
|
extract_param_value := true;
|
|
extract_param_name := false;
|
|
set_right_index := true;
|
|
|
|
if (compare_param_name = given_string(param_name_left_index to param_name_right_index)) then
|
|
param_found := true; -- the compare_param_name have been found in the given_string
|
|
exit;
|
|
end if;
|
|
else
|
|
if (extract_param_value = true) then
|
|
if (set_right_index = true) then
|
|
param_value_right_index := i;
|
|
set_right_index := false;
|
|
end if;
|
|
param_value_left_index := i;
|
|
elsif (extract_param_name = true) then
|
|
if (set_right_index = true) then
|
|
param_name_right_index := i;
|
|
set_right_index := false;
|
|
end if;
|
|
param_name_left_index := i;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
|
|
-- for the case whether parameter's name is the left most part of the given_string
|
|
if (extract_param_name = true) then
|
|
if(compare_param_name = given_string(param_name_left_index to param_name_right_index)) then
|
|
param_found := true;
|
|
end if;
|
|
end if;
|
|
|
|
if(param_found = true) then
|
|
return given_string(param_value_left_index to param_value_right_index);
|
|
else
|
|
return ""; -- return empty string if parameter not found
|
|
end if;
|
|
|
|
end get_parameter_value;
|
|
end ALTERA_MF_HINT_EVALUATION;
|
|
-- END OF PACKAGE
|
|
|
|
---START_PACKAGE_HEADER-----------------------------------------------------
|
|
--
|
|
-- Package Name : ALTERA_DEVICE_FAMILIES
|
|
--
|
|
-- Description : Common Altera device families comparison
|
|
--
|
|
---END_PACKAGE_HEADER--------------------------------------------------------
|
|
|
|
-- BEGINING OF PACKAGES
|
|
Library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
-- PACKAGE DECLARATION
|
|
package ALTERA_DEVICE_FAMILIES is
|
|
-- FUNCTION DECLARATION
|
|
function IS_FAMILY_ARRIA10 (device : in string) return boolean;
|
|
function IS_FAMILY_ARRIAGX (device : in string) return boolean;
|
|
function IS_FAMILY_ARRIAIIGX (device : in string) return boolean;
|
|
function IS_FAMILY_ARRIAIIGZ (device : in string) return boolean;
|
|
function IS_FAMILY_ARRIAVGZ (device : in string) return boolean;
|
|
function IS_FAMILY_ARRIAV (device : in string) return boolean;
|
|
function IS_FAMILY_CYCLONEII (device : in string) return boolean;
|
|
function IS_FAMILY_CYCLONEIIILS (device : in string) return boolean;
|
|
function IS_FAMILY_CYCLONEIII (device : in string) return boolean;
|
|
function IS_FAMILY_CYCLONEIVE (device : in string) return boolean;
|
|
function IS_FAMILY_CYCLONEIVGX (device : in string) return boolean;
|
|
function IS_FAMILY_CYCLONEV (device : in string) return boolean;
|
|
function IS_FAMILY_CYCLONE (device : in string) return boolean;
|
|
function IS_FAMILY_HARDCOPYII (device : in string) return boolean;
|
|
function IS_FAMILY_HARDCOPYIII (device : in string) return boolean;
|
|
function IS_FAMILY_HARDCOPYIV (device : in string) return boolean;
|
|
function IS_FAMILY_MAX10 (device : in string) return boolean;
|
|
function IS_FAMILY_MAXII (device : in string) return boolean;
|
|
function IS_FAMILY_MAXV (device : in string) return boolean;
|
|
function IS_FAMILY_STRATIX10 (device : in string) return boolean;
|
|
function IS_FAMILY_STRATIXGX (device : in string) return boolean;
|
|
function IS_FAMILY_STRATIXIIGX (device : in string) return boolean;
|
|
function IS_FAMILY_STRATIXII (device : in string) return boolean;
|
|
function IS_FAMILY_STRATIXIII (device : in string) return boolean;
|
|
function IS_FAMILY_STRATIXIV (device : in string) return boolean;
|
|
function IS_FAMILY_STRATIXV (device : in string) return boolean;
|
|
function IS_FAMILY_STRATIX (device : in string) return boolean;
|
|
function FEATURE_FAMILY_STRATIXGX (device : in string) return boolean;
|
|
function FEATURE_FAMILY_CYCLONE (device : in string) return boolean;
|
|
function FEATURE_FAMILY_STRATIXIIGX (device : in string) return boolean;
|
|
function FEATURE_FAMILY_STRATIXIII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_ARRIAVGZ (device : in string) return boolean;
|
|
function FEATURE_FAMILY_STRATIXV (device : in string) return boolean;
|
|
function FEATURE_FAMILY_ARRIA10 (device : in string) return boolean;
|
|
function FEATURE_FAMILY_STRATIXII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_CYCLONEIVGX (device : in string) return boolean;
|
|
function FEATURE_FAMILY_CYCLONEIVE (device : in string) return boolean;
|
|
function FEATURE_FAMILY_CYCLONEIII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_STRATIX_HC (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HARDCOPYII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_STRATIX (device : in string) return boolean;
|
|
function FEATURE_FAMILY_MAXII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_MAXV (device : in string) return boolean;
|
|
function FEATURE_FAMILY_CYCLONEII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_STRATIXIV (device : in string) return boolean;
|
|
function FEATURE_FAMILY_ARRIAIIGZ (device : in string) return boolean;
|
|
function FEATURE_FAMILY_ARRIAIIGX (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HARDCOPYIII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HARDCOPYIV (device : in string) return boolean;
|
|
function FEATURE_FAMILY_CYCLONEV (device : in string) return boolean;
|
|
function FEATURE_FAMILY_ARRIAV (device : in string) return boolean;
|
|
function FEATURE_FAMILY_MAX10 (device : in string) return boolean;
|
|
function FEATURE_FAMILY_STRATIX10 (device : in string) return boolean;
|
|
function FEATURE_FAMILY_BASE_STRATIXII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_BASE_STRATIX (device : in string) return boolean;
|
|
function FEATURE_FAMILY_BASE_CYCLONEII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_BASE_CYCLONE (device : in string) return boolean;
|
|
function FEATURE_FAMILY_BASE_CYCLONEIII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_BASE_STRATIXIII (device : in string) return boolean;
|
|
function FEATURE_FAMILY_STRATIX_NONGX (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_ALTERA_MULT_ADD_FLOW (device : in string) return boolean;
|
|
function FEATURE_FAMILY_IS_ALTMULT_ADD_EOL (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_STRATIXV_STYLE_RAM (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_MEGARAM (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_M512 (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_LUTRAM (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_STRATIXI_STYLE_RAM (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL (device : in string) return boolean;
|
|
function FEATURE_FAMILY_USES_STRATIXIII_PLL (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_FLEXIBLE_LVDS (device : in string) return boolean;
|
|
function FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO (device : in string) return boolean;
|
|
function IS_VALID_FAMILY (device: in string) return boolean;
|
|
end ALTERA_DEVICE_FAMILIES;
|
|
|
|
package body ALTERA_DEVICE_FAMILIES is
|
|
|
|
|
|
function IS_FAMILY_ARRIA10 (device : in string) return boolean is
|
|
variable is_arria10 : boolean := false;
|
|
begin
|
|
if ((device = "Arria 10") or (device = "ARRIA 10") or (device = "arria 10") or (device = "Arria10") or (device = "ARRIA10") or (device = "arria10") or (device = "Arria VI") or (device = "ARRIA VI") or (device = "arria vi") or (device = "ArriaVI") or (device = "ARRIAVI") or (device = "arriavi") or (device = "Night Fury") or (device = "NIGHT FURY") or (device = "night fury") or (device = "nightfury") or (device = "NIGHTFURY") or (device = "Arria 10 (GX/SX/GT)") or (device = "ARRIA 10 (GX/SX/GT)") or (device = "arria 10 (gx/sx/gt)") or (device = "Arria10(GX/SX/GT)") or (device = "ARRIA10(GX/SX/GT)") or (device = "arria10(gx/sx/gt)") or (device = "Arria 10 (GX)") or (device = "ARRIA 10 (GX)") or (device = "arria 10 (gx)") or (device = "Arria10(GX)") or (device = "ARRIA10(GX)") or (device = "arria10(gx)") or (device = "Arria 10 (SX)") or (device = "ARRIA 10 (SX)") or (device = "arria 10 (sx)") or (device = "Arria10(SX)") or (device = "ARRIA10(SX)") or (device = "arria10(sx)") or (device = "Arria 10 (GT)") or (device = "ARRIA 10 (GT)") or (device = "arria 10 (gt)") or (device = "Arria10(GT)") or (device = "ARRIA10(GT)") or (device = "arria10(gt)"))
|
|
then
|
|
is_arria10 := true;
|
|
end if;
|
|
return is_arria10;
|
|
end IS_FAMILY_ARRIA10;
|
|
|
|
function IS_FAMILY_ARRIAGX (device : in string) return boolean is
|
|
variable is_arriagx : boolean := false;
|
|
begin
|
|
if ((device = "Arria GX") or (device = "ARRIA GX") or (device = "arria gx") or (device = "ArriaGX") or (device = "ARRIAGX") or (device = "arriagx") or (device = "Stratix II GX Lite") or (device = "STRATIX II GX LITE") or (device = "stratix ii gx lite") or (device = "StratixIIGXLite") or (device = "STRATIXIIGXLITE") or (device = "stratixiigxlite"))
|
|
then
|
|
is_arriagx := true;
|
|
end if;
|
|
return is_arriagx;
|
|
end IS_FAMILY_ARRIAGX;
|
|
|
|
function IS_FAMILY_ARRIAIIGX (device : in string) return boolean is
|
|
variable is_arriaiigx : boolean := false;
|
|
begin
|
|
if ((device = "Arria II GX") or (device = "ARRIA II GX") or (device = "arria ii gx") or (device = "ArriaIIGX") or (device = "ARRIAIIGX") or (device = "arriaiigx") or (device = "Arria IIGX") or (device = "ARRIA IIGX") or (device = "arria iigx") or (device = "ArriaII GX") or (device = "ARRIAII GX") or (device = "arriaii gx") or (device = "Arria II") or (device = "ARRIA II") or (device = "arria ii") or (device = "ArriaII") or (device = "ARRIAII") or (device = "arriaii") or (device = "Arria II (GX/E)") or (device = "ARRIA II (GX/E)") or (device = "arria ii (gx/e)") or (device = "ArriaII(GX/E)") or (device = "ARRIAII(GX/E)") or (device = "arriaii(gx/e)") or (device = "PIRANHA") or (device = "piranha"))
|
|
then
|
|
is_arriaiigx := true;
|
|
end if;
|
|
return is_arriaiigx;
|
|
end IS_FAMILY_ARRIAIIGX;
|
|
|
|
function IS_FAMILY_ARRIAIIGZ (device : in string) return boolean is
|
|
variable is_arriaiigz : boolean := false;
|
|
begin
|
|
if ((device = "Arria II GZ") or (device = "ARRIA II GZ") or (device = "arria ii gz") or (device = "ArriaII GZ") or (device = "ARRIAII GZ") or (device = "arriaii gz") or (device = "Arria IIGZ") or (device = "ARRIA IIGZ") or (device = "arria iigz") or (device = "ArriaIIGZ") or (device = "ARRIAIIGZ") or (device = "arriaiigz"))
|
|
then
|
|
is_arriaiigz := true;
|
|
end if;
|
|
return is_arriaiigz;
|
|
end IS_FAMILY_ARRIAIIGZ;
|
|
|
|
function IS_FAMILY_ARRIAVGZ (device : in string) return boolean is
|
|
variable is_arriavgz : boolean := false;
|
|
begin
|
|
if ((device = "Arria V GZ") or (device = "ARRIA V GZ") or (device = "arria v gz") or (device = "ArriaVGZ") or (device = "ARRIAVGZ") or (device = "arriavgz"))
|
|
then
|
|
is_arriavgz := true;
|
|
end if;
|
|
return is_arriavgz;
|
|
end IS_FAMILY_ARRIAVGZ;
|
|
|
|
function IS_FAMILY_ARRIAV (device : in string) return boolean is
|
|
variable is_arriav : boolean := false;
|
|
begin
|
|
if ((device = "Arria V") or (device = "ARRIA V") or (device = "arria v") or (device = "Arria V (GT/GX)") or (device = "ARRIA V (GT/GX)") or (device = "arria v (gt/gx)") or (device = "ArriaV(GT/GX)") or (device = "ARRIAV(GT/GX)") or (device = "arriav(gt/gx)") or (device = "ArriaV") or (device = "ARRIAV") or (device = "arriav") or (device = "Arria V (GT/GX/ST/SX)") or (device = "ARRIA V (GT/GX/ST/SX)") or (device = "arria v (gt/gx/st/sx)") or (device = "ArriaV(GT/GX/ST/SX)") or (device = "ARRIAV(GT/GX/ST/SX)") or (device = "arriav(gt/gx/st/sx)") or (device = "Arria V (GT)") or (device = "ARRIA V (GT)") or (device = "arria v (gt)") or (device = "ArriaV(GT)") or (device = "ARRIAV(GT)") or (device = "arriav(gt)") or (device = "Arria V (GX)") or (device = "ARRIA V (GX)") or (device = "arria v (gx)") or (device = "ArriaV(GX)") or (device = "ARRIAV(GX)") or (device = "arriav(gx)") or (device = "Arria V (ST)") or (device = "ARRIA V (ST)") or (device = "arria v (st)") or (device = "ArriaV(ST)") or (device = "ARRIAV(ST)") or (device = "arriav(st)") or (device = "Arria V (SX)") or (device = "ARRIA V (SX)") or (device = "arria v (sx)") or (device = "ArriaV(SX)") or (device = "ARRIAV(SX)") or (device = "arriav(sx)"))
|
|
then
|
|
is_arriav := true;
|
|
end if;
|
|
return is_arriav;
|
|
end IS_FAMILY_ARRIAV;
|
|
|
|
function IS_FAMILY_CYCLONEII (device : in string) return boolean is
|
|
variable is_cycloneii : boolean := false;
|
|
begin
|
|
if ((device = "Cyclone II") or (device = "CYCLONE II") or (device = "cyclone ii") or (device = "Cycloneii") or (device = "CYCLONEII") or (device = "cycloneii") or (device = "Magellan") or (device = "MAGELLAN") or (device = "magellan") or (device = "CycloneII") or (device = "CYCLONEII") or (device = "cycloneii"))
|
|
then
|
|
is_cycloneii := true;
|
|
end if;
|
|
return is_cycloneii;
|
|
end IS_FAMILY_CYCLONEII;
|
|
|
|
function IS_FAMILY_CYCLONEIIILS (device : in string) return boolean is
|
|
variable is_cycloneiiils : boolean := false;
|
|
begin
|
|
if ((device = "Cyclone III LS") or (device = "CYCLONE III LS") or (device = "cyclone iii ls") or (device = "CycloneIIILS") or (device = "CYCLONEIIILS") or (device = "cycloneiiils") or (device = "Cyclone III LPS") or (device = "CYCLONE III LPS") or (device = "cyclone iii lps") or (device = "Cyclone LPS") or (device = "CYCLONE LPS") or (device = "cyclone lps") or (device = "CycloneLPS") or (device = "CYCLONELPS") or (device = "cyclonelps") or (device = "Tarpon") or (device = "TARPON") or (device = "tarpon") or (device = "Cyclone IIIE") or (device = "CYCLONE IIIE") or (device = "cyclone iiie"))
|
|
then
|
|
is_cycloneiiils := true;
|
|
end if;
|
|
return is_cycloneiiils;
|
|
end IS_FAMILY_CYCLONEIIILS;
|
|
|
|
function IS_FAMILY_CYCLONEIII (device : in string) return boolean is
|
|
variable is_cycloneiii : boolean := false;
|
|
begin
|
|
if ((device = "Cyclone III") or (device = "CYCLONE III") or (device = "cyclone iii") or (device = "CycloneIII") or (device = "CYCLONEIII") or (device = "cycloneiii") or (device = "Barracuda") or (device = "BARRACUDA") or (device = "barracuda") or (device = "Cuda") or (device = "CUDA") or (device = "cuda") or (device = "CIII") or (device = "ciii"))
|
|
then
|
|
is_cycloneiii := true;
|
|
end if;
|
|
return is_cycloneiii;
|
|
end IS_FAMILY_CYCLONEIII;
|
|
|
|
function IS_FAMILY_CYCLONEIVE (device : in string) return boolean is
|
|
variable is_cycloneive : boolean := false;
|
|
begin
|
|
if ((device = "Cyclone IV E") or (device = "CYCLONE IV E") or (device = "cyclone iv e") or (device = "CycloneIV E") or (device = "CYCLONEIV E") or (device = "cycloneiv e") or (device = "Cyclone IVE") or (device = "CYCLONE IVE") or (device = "cyclone ive") or (device = "CycloneIVE") or (device = "CYCLONEIVE") or (device = "cycloneive"))
|
|
then
|
|
is_cycloneive := true;
|
|
end if;
|
|
return is_cycloneive;
|
|
end IS_FAMILY_CYCLONEIVE;
|
|
|
|
function IS_FAMILY_CYCLONEIVGX (device : in string) return boolean is
|
|
variable is_cycloneivgx : boolean := false;
|
|
begin
|
|
if ((device = "Cyclone IV GX") or (device = "CYCLONE IV GX") or (device = "cyclone iv gx") or (device = "Cyclone IVGX") or (device = "CYCLONE IVGX") or (device = "cyclone ivgx") or (device = "CycloneIV GX") or (device = "CYCLONEIV GX") or (device = "cycloneiv gx") or (device = "CycloneIVGX") or (device = "CYCLONEIVGX") or (device = "cycloneivgx") or (device = "Cyclone IV") or (device = "CYCLONE IV") or (device = "cyclone iv") or (device = "CycloneIV") or (device = "CYCLONEIV") or (device = "cycloneiv") or (device = "Cyclone IV (GX)") or (device = "CYCLONE IV (GX)") or (device = "cyclone iv (gx)") or (device = "CycloneIV(GX)") or (device = "CYCLONEIV(GX)") or (device = "cycloneiv(gx)") or (device = "Cyclone III GX") or (device = "CYCLONE III GX") or (device = "cyclone iii gx") or (device = "CycloneIII GX") or (device = "CYCLONEIII GX") or (device = "cycloneiii gx") or (device = "Cyclone IIIGX") or (device = "CYCLONE IIIGX") or (device = "cyclone iiigx") or (device = "CycloneIIIGX") or (device = "CYCLONEIIIGX") or (device = "cycloneiiigx") or (device = "Cyclone III GL") or (device = "CYCLONE III GL") or (device = "cyclone iii gl") or (device = "CycloneIII GL") or (device = "CYCLONEIII GL") or (device = "cycloneiii gl") or (device = "Cyclone IIIGL") or (device = "CYCLONE IIIGL") or (device = "cyclone iiigl") or (device = "CycloneIIIGL") or (device = "CYCLONEIIIGL") or (device = "cycloneiiigl") or (device = "Stingray") or (device = "STINGRAY") or (device = "stingray"))
|
|
then
|
|
is_cycloneivgx := true;
|
|
end if;
|
|
return is_cycloneivgx;
|
|
end IS_FAMILY_CYCLONEIVGX;
|
|
|
|
function IS_FAMILY_CYCLONEV (device : in string) return boolean is
|
|
variable is_cyclonev : boolean := false;
|
|
begin
|
|
if ((device = "Cyclone V") or (device = "CYCLONE V") or (device = "cyclone v") or (device = "CycloneV") or (device = "CYCLONEV") or (device = "cyclonev") or (device = "Cyclone V (GT/GX/E/SX)") or (device = "CYCLONE V (GT/GX/E/SX)") or (device = "cyclone v (gt/gx/e/sx)") or (device = "CycloneV(GT/GX/E/SX)") or (device = "CYCLONEV(GT/GX/E/SX)") or (device = "cyclonev(gt/gx/e/sx)") or (device = "Cyclone V (E/GX/GT/SX/SE/ST)") or (device = "CYCLONE V (E/GX/GT/SX/SE/ST)") or (device = "cyclone v (e/gx/gt/sx/se/st)") or (device = "CycloneV(E/GX/GT/SX/SE/ST)") or (device = "CYCLONEV(E/GX/GT/SX/SE/ST)") or (device = "cyclonev(e/gx/gt/sx/se/st)") or (device = "Cyclone V (E)") or (device = "CYCLONE V (E)") or (device = "cyclone v (e)") or (device = "CycloneV(E)") or (device = "CYCLONEV(E)") or (device = "cyclonev(e)") or (device = "Cyclone V (GX)") or (device = "CYCLONE V (GX)") or (device = "cyclone v (gx)") or (device = "CycloneV(GX)") or (device = "CYCLONEV(GX)") or (device = "cyclonev(gx)") or (device = "Cyclone V (GT)") or (device = "CYCLONE V (GT)") or (device = "cyclone v (gt)") or (device = "CycloneV(GT)") or (device = "CYCLONEV(GT)") or (device = "cyclonev(gt)") or (device = "Cyclone V (SX)") or (device = "CYCLONE V (SX)") or (device = "cyclone v (sx)") or (device = "CycloneV(SX)") or (device = "CYCLONEV(SX)") or (device = "cyclonev(sx)") or (device = "Cyclone V (SE)") or (device = "CYCLONE V (SE)") or (device = "cyclone v (se)") or (device = "CycloneV(SE)") or (device = "CYCLONEV(SE)") or (device = "cyclonev(se)") or (device = "Cyclone V (ST)") or (device = "CYCLONE V (ST)") or (device = "cyclone v (st)") or (device = "CycloneV(ST)") or (device = "CYCLONEV(ST)") or (device = "cyclonev(st)"))
|
|
then
|
|
is_cyclonev := true;
|
|
end if;
|
|
return is_cyclonev;
|
|
end IS_FAMILY_CYCLONEV;
|
|
|
|
function IS_FAMILY_CYCLONE (device : in string) return boolean is
|
|
variable is_cyclone : boolean := false;
|
|
begin
|
|
if ((device = "Cyclone") or (device = "CYCLONE") or (device = "cyclone") or (device = "ACEX2K") or (device = "acex2k") or (device = "ACEX 2K") or (device = "acex 2k") or (device = "Tornado") or (device = "TORNADO") or (device = "tornado"))
|
|
then
|
|
is_cyclone := true;
|
|
end if;
|
|
return is_cyclone;
|
|
end IS_FAMILY_CYCLONE;
|
|
|
|
function IS_FAMILY_HARDCOPYII (device : in string) return boolean is
|
|
variable is_hardcopyii : boolean := false;
|
|
begin
|
|
if ((device = "HardCopy II") or (device = "HARDCOPY II") or (device = "hardcopy ii") or (device = "HardCopyII") or (device = "HARDCOPYII") or (device = "hardcopyii") or (device = "Fusion") or (device = "FUSION") or (device = "fusion"))
|
|
then
|
|
is_hardcopyii := true;
|
|
end if;
|
|
return is_hardcopyii;
|
|
end IS_FAMILY_HARDCOPYII;
|
|
|
|
function IS_FAMILY_HARDCOPYIII (device : in string) return boolean is
|
|
variable is_hardcopyiii : boolean := false;
|
|
begin
|
|
if ((device = "HardCopy III") or (device = "HARDCOPY III") or (device = "hardcopy iii") or (device = "HardCopyIII") or (device = "HARDCOPYIII") or (device = "hardcopyiii") or (device = "HCX") or (device = "hcx"))
|
|
then
|
|
is_hardcopyiii := true;
|
|
end if;
|
|
return is_hardcopyiii;
|
|
end IS_FAMILY_HARDCOPYIII;
|
|
|
|
function IS_FAMILY_HARDCOPYIV (device : in string) return boolean is
|
|
variable is_hardcopyiv : boolean := false;
|
|
begin
|
|
if ((device = "HardCopy IV") or (device = "HARDCOPY IV") or (device = "hardcopy iv") or (device = "HardCopyIV") or (device = "HARDCOPYIV") or (device = "hardcopyiv") or (device = "HardCopy IV (GX)") or (device = "HARDCOPY IV (GX)") or (device = "hardcopy iv (gx)") or (device = "HardCopy IV (E)") or (device = "HARDCOPY IV (E)") or (device = "hardcopy iv (e)") or (device = "HardCopyIV(GX)") or (device = "HARDCOPYIV(GX)") or (device = "hardcopyiv(gx)") or (device = "HardCopyIV(E)") or (device = "HARDCOPYIV(E)") or (device = "hardcopyiv(e)") or (device = "HCXIV") or (device = "hcxiv") or (device = "HardCopy IV (GX/E)") or (device = "HARDCOPY IV (GX/E)") or (device = "hardcopy iv (gx/e)") or (device = "HardCopy IV (E/GX)") or (device = "HARDCOPY IV (E/GX)") or (device = "hardcopy iv (e/gx)") or (device = "HardCopyIV(GX/E)") or (device = "HARDCOPYIV(GX/E)") or (device = "hardcopyiv(gx/e)") or (device = "HardCopyIV(E/GX)") or (device = "HARDCOPYIV(E/GX)") or (device = "hardcopyiv(e/gx)"))
|
|
then
|
|
is_hardcopyiv := true;
|
|
end if;
|
|
return is_hardcopyiv;
|
|
end IS_FAMILY_HARDCOPYIV;
|
|
|
|
function IS_FAMILY_MAX10 (device : in string) return boolean is
|
|
variable is_max10 : boolean := false;
|
|
begin
|
|
if ((device = "MAX 10") or (device = "max 10") or (device = "MAX 10 FPGA") or (device = "max 10 fpga") or (device = "Zippleback") or (device = "ZIPPLEBACK") or (device = "zippleback") or (device = "MAX10") or (device = "max10") or (device = "MAX 10 (DA/DF/DC/SA/SF/SC)") or (device = "max 10 (da/df/dc/sa/sf/sc)") or (device = "MAX10(DA/DF/DC/SA/SF/SC)") or (device = "max10(da/df/dc/sa/sf/sc)") or (device = "MAX 10 (DA)") or (device = "max 10 (da)") or (device = "MAX10(DA)") or (device = "max10(da)") or (device = "MAX 10 (DF)") or (device = "max 10 (df)") or (device = "MAX10(DF)") or (device = "max10(df)") or (device = "MAX 10 (DC)") or (device = "max 10 (dc)") or (device = "MAX10(DC)") or (device = "max10(dc)") or (device = "MAX 10 (SA)") or (device = "max 10 (sa)") or (device = "MAX10(SA)") or (device = "max10(sa)") or (device = "MAX 10 (SF)") or (device = "max 10 (sf)") or (device = "MAX10(SF)") or (device = "max10(sf)") or (device = "MAX 10 (SC)") or (device = "max 10 (sc)") or (device = "MAX10(SC)") or (device = "max10(sc)"))
|
|
then
|
|
is_max10 := true;
|
|
end if;
|
|
return is_max10;
|
|
end IS_FAMILY_MAX10;
|
|
|
|
function IS_FAMILY_MAXII (device : in string) return boolean is
|
|
variable is_maxii : boolean := false;
|
|
begin
|
|
if ((device = "MAX II") or (device = "max ii") or (device = "MAXII") or (device = "maxii") or (device = "Tsunami") or (device = "TSUNAMI") or (device = "tsunami"))
|
|
then
|
|
is_maxii := true;
|
|
end if;
|
|
return is_maxii;
|
|
end IS_FAMILY_MAXII;
|
|
|
|
function IS_FAMILY_MAXV (device : in string) return boolean is
|
|
variable is_maxv : boolean := false;
|
|
begin
|
|
if ((device = "MAX V") or (device = "max v") or (device = "MAXV") or (device = "maxv") or (device = "Jade") or (device = "JADE") or (device = "jade"))
|
|
then
|
|
is_maxv := true;
|
|
end if;
|
|
return is_maxv;
|
|
end IS_FAMILY_MAXV;
|
|
|
|
function IS_FAMILY_STRATIX10 (device : in string) return boolean is
|
|
variable is_stratix10 : boolean := false;
|
|
begin
|
|
if ((device = "Stratix 10") or (device = "STRATIX 10") or (device = "stratix 10") or (device = "Stratix10") or (device = "STRATIX10") or (device = "stratix10") or (device = "nadder") or (device = "NADDER"))
|
|
then
|
|
is_stratix10 := true;
|
|
end if;
|
|
return is_stratix10;
|
|
end IS_FAMILY_STRATIX10;
|
|
|
|
function IS_FAMILY_STRATIXGX (device : in string) return boolean is
|
|
variable is_stratixgx : boolean := false;
|
|
begin
|
|
if ((device = "Stratix GX") or (device = "STRATIX GX") or (device = "stratix gx") or (device = "Stratix-GX") or (device = "STRATIX-GX") or (device = "stratix-gx") or (device = "StratixGX") or (device = "STRATIXGX") or (device = "stratixgx") or (device = "Aurora") or (device = "AURORA") or (device = "aurora"))
|
|
then
|
|
is_stratixgx := true;
|
|
end if;
|
|
return is_stratixgx;
|
|
end IS_FAMILY_STRATIXGX;
|
|
|
|
function IS_FAMILY_STRATIXIIGX (device : in string) return boolean is
|
|
variable is_stratixiigx : boolean := false;
|
|
begin
|
|
if ((device = "Stratix II GX") or (device = "STRATIX II GX") or (device = "stratix ii gx") or (device = "StratixIIGX") or (device = "STRATIXIIGX") or (device = "stratixiigx"))
|
|
then
|
|
is_stratixiigx := true;
|
|
end if;
|
|
return is_stratixiigx;
|
|
end IS_FAMILY_STRATIXIIGX;
|
|
|
|
function IS_FAMILY_STRATIXII (device : in string) return boolean is
|
|
variable is_stratixii : boolean := false;
|
|
begin
|
|
if ((device = "Stratix II") or (device = "STRATIX II") or (device = "stratix ii") or (device = "StratixII") or (device = "STRATIXII") or (device = "stratixii") or (device = "Armstrong") or (device = "ARMSTRONG") or (device = "armstrong"))
|
|
then
|
|
is_stratixii := true;
|
|
end if;
|
|
return is_stratixii;
|
|
end IS_FAMILY_STRATIXII;
|
|
|
|
function IS_FAMILY_STRATIXIII (device : in string) return boolean is
|
|
variable is_stratixiii : boolean := false;
|
|
begin
|
|
if ((device = "Stratix III") or (device = "STRATIX III") or (device = "stratix iii") or (device = "StratixIII") or (device = "STRATIXIII") or (device = "stratixiii") or (device = "Titan") or (device = "TITAN") or (device = "titan") or (device = "SIII") or (device = "siii"))
|
|
then
|
|
is_stratixiii := true;
|
|
end if;
|
|
return is_stratixiii;
|
|
end IS_FAMILY_STRATIXIII;
|
|
|
|
function IS_FAMILY_STRATIXIV (device : in string) return boolean is
|
|
variable is_stratixiv : boolean := false;
|
|
begin
|
|
if ((device = "Stratix IV") or (device = "STRATIX IV") or (device = "stratix iv") or (device = "TGX") or (device = "tgx") or (device = "StratixIV") or (device = "STRATIXIV") or (device = "stratixiv") or (device = "Stratix IV (GT)") or (device = "STRATIX IV (GT)") or (device = "stratix iv (gt)") or (device = "Stratix IV (GX)") or (device = "STRATIX IV (GX)") or (device = "stratix iv (gx)") or (device = "Stratix IV (E)") or (device = "STRATIX IV (E)") or (device = "stratix iv (e)") or (device = "StratixIV(GT)") or (device = "STRATIXIV(GT)") or (device = "stratixiv(gt)") or (device = "StratixIV(GX)") or (device = "STRATIXIV(GX)") or (device = "stratixiv(gx)") or (device = "StratixIV(E)") or (device = "STRATIXIV(E)") or (device = "stratixiv(e)") or (device = "StratixIIIGX") or (device = "STRATIXIIIGX") or (device = "stratixiiigx") or (device = "Stratix IV (GT/GX/E)") or (device = "STRATIX IV (GT/GX/E)") or (device = "stratix iv (gt/gx/e)") or (device = "Stratix IV (GT/E/GX)") or (device = "STRATIX IV (GT/E/GX)") or (device = "stratix iv (gt/e/gx)") or (device = "Stratix IV (E/GT/GX)") or (device = "STRATIX IV (E/GT/GX)") or (device = "stratix iv (e/gt/gx)") or (device = "Stratix IV (E/GX/GT)") or (device = "STRATIX IV (E/GX/GT)") or (device = "stratix iv (e/gx/gt)") or (device = "StratixIV(GT/GX/E)") or (device = "STRATIXIV(GT/GX/E)") or (device = "stratixiv(gt/gx/e)") or (device = "StratixIV(GT/E/GX)") or (device = "STRATIXIV(GT/E/GX)") or (device = "stratixiv(gt/e/gx)") or (device = "StratixIV(E/GX/GT)") or (device = "STRATIXIV(E/GX/GT)") or (device = "stratixiv(e/gx/gt)") or (device = "StratixIV(E/GT/GX)") or (device = "STRATIXIV(E/GT/GX)") or (device = "stratixiv(e/gt/gx)") or (device = "Stratix IV (GX/E)") or (device = "STRATIX IV (GX/E)") or (device = "stratix iv (gx/e)") or (device = "StratixIV(GX/E)") or (device = "STRATIXIV(GX/E)") or (device = "stratixiv(gx/e)"))
|
|
then
|
|
is_stratixiv := true;
|
|
end if;
|
|
return is_stratixiv;
|
|
end IS_FAMILY_STRATIXIV;
|
|
|
|
function IS_FAMILY_STRATIXV (device : in string) return boolean is
|
|
variable is_stratixv : boolean := false;
|
|
begin
|
|
if ((device = "Stratix V") or (device = "STRATIX V") or (device = "stratix v") or (device = "StratixV") or (device = "STRATIXV") or (device = "stratixv") or (device = "Stratix V (GS)") or (device = "STRATIX V (GS)") or (device = "stratix v (gs)") or (device = "StratixV(GS)") or (device = "STRATIXV(GS)") or (device = "stratixv(gs)") or (device = "Stratix V (GT)") or (device = "STRATIX V (GT)") or (device = "stratix v (gt)") or (device = "StratixV(GT)") or (device = "STRATIXV(GT)") or (device = "stratixv(gt)") or (device = "Stratix V (GX)") or (device = "STRATIX V (GX)") or (device = "stratix v (gx)") or (device = "StratixV(GX)") or (device = "STRATIXV(GX)") or (device = "stratixv(gx)") or (device = "Stratix V (GS/GX)") or (device = "STRATIX V (GS/GX)") or (device = "stratix v (gs/gx)") or (device = "StratixV(GS/GX)") or (device = "STRATIXV(GS/GX)") or (device = "stratixv(gs/gx)") or (device = "Stratix V (GS/GT)") or (device = "STRATIX V (GS/GT)") or (device = "stratix v (gs/gt)") or (device = "StratixV(GS/GT)") or (device = "STRATIXV(GS/GT)") or (device = "stratixv(gs/gt)") or (device = "Stratix V (GT/GX)") or (device = "STRATIX V (GT/GX)") or (device = "stratix v (gt/gx)") or (device = "StratixV(GT/GX)") or (device = "STRATIXV(GT/GX)") or (device = "stratixv(gt/gx)") or (device = "Stratix V (GX/GS)") or (device = "STRATIX V (GX/GS)") or (device = "stratix v (gx/gs)") or (device = "StratixV(GX/GS)") or (device = "STRATIXV(GX/GS)") or (device = "stratixv(gx/gs)") or (device = "Stratix V (GT/GS)") or (device = "STRATIX V (GT/GS)") or (device = "stratix v (gt/gs)") or (device = "StratixV(GT/GS)") or (device = "STRATIXV(GT/GS)") or (device = "stratixv(gt/gs)") or (device = "Stratix V (GX/GT)") or (device = "STRATIX V (GX/GT)") or (device = "stratix v (gx/gt)") or (device = "StratixV(GX/GT)") or (device = "STRATIXV(GX/GT)") or (device = "stratixv(gx/gt)") or (device = "Stratix V (GS/GT/GX)") or (device = "STRATIX V (GS/GT/GX)") or (device = "stratix v (gs/gt/gx)") or (device = "Stratix V (GS/GX/GT)") or (device = "STRATIX V (GS/GX/GT)") or (device = "stratix v (gs/gx/gt)") or (device = "Stratix V (GT/GS/GX)") or (device = "STRATIX V (GT/GS/GX)") or (device = "stratix v (gt/gs/gx)") or (device = "Stratix V (GT/GX/GS)") or (device = "STRATIX V (GT/GX/GS)") or (device = "stratix v (gt/gx/gs)") or (device = "Stratix V (GX/GS/GT)") or (device = "STRATIX V (GX/GS/GT)") or (device = "stratix v (gx/gs/gt)") or (device = "Stratix V (GX/GT/GS)") or (device = "STRATIX V (GX/GT/GS)") or (device = "stratix v (gx/gt/gs)") or (device = "StratixV(GS/GT/GX)") or (device = "STRATIXV(GS/GT/GX)") or (device = "stratixv(gs/gt/gx)") or (device = "StratixV(GS/GX/GT)") or (device = "STRATIXV(GS/GX/GT)") or (device = "stratixv(gs/gx/gt)") or (device = "StratixV(GT/GS/GX)") or (device = "STRATIXV(GT/GS/GX)") or (device = "stratixv(gt/gs/gx)") or (device = "StratixV(GT/GX/GS)") or (device = "STRATIXV(GT/GX/GS)") or (device = "stratixv(gt/gx/gs)") or (device = "StratixV(GX/GS/GT)") or (device = "STRATIXV(GX/GS/GT)") or (device = "stratixv(gx/gs/gt)") or (device = "StratixV(GX/GT/GS)") or (device = "STRATIXV(GX/GT/GS)") or (device = "stratixv(gx/gt/gs)") or (device = "Stratix V (GS/GT/GX/E)") or (device = "STRATIX V (GS/GT/GX/E)") or (device = "stratix v (gs/gt/gx/e)") or (device = "StratixV(GS/GT/GX/E)") or (device = "STRATIXV(GS/GT/GX/E)") or (device = "stratixv(gs/gt/gx/e)") or (device = "Stratix V (E)") or (device = "STRATIX V (E)") or (device = "stratix v (e)") or (device = "StratixV(E)") or (device = "STRATIXV(E)") or (device = "stratixv(e)"))
|
|
then
|
|
is_stratixv := true;
|
|
end if;
|
|
return is_stratixv;
|
|
end IS_FAMILY_STRATIXV;
|
|
|
|
function IS_FAMILY_STRATIX (device : in string) return boolean is
|
|
variable is_stratix : boolean := false;
|
|
begin
|
|
if ((device = "Stratix") or (device = "STRATIX") or (device = "stratix") or (device = "Yeager") or (device = "YEAGER") or (device = "yeager"))
|
|
then
|
|
is_stratix := true;
|
|
end if;
|
|
return is_stratix;
|
|
end IS_FAMILY_STRATIX;
|
|
|
|
function FEATURE_FAMILY_STRATIXGX (device : in string) return boolean is
|
|
variable var_family_stratixgx : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIXGX(device) )
|
|
then
|
|
var_family_stratixgx := true;
|
|
end if;
|
|
return var_family_stratixgx;
|
|
end FEATURE_FAMILY_STRATIXGX;
|
|
|
|
|
|
function FEATURE_FAMILY_CYCLONE (device : in string) return boolean is
|
|
variable var_family_cyclone : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_CYCLONE(device) )
|
|
then
|
|
var_family_cyclone := true;
|
|
end if;
|
|
return var_family_cyclone;
|
|
end FEATURE_FAMILY_CYCLONE;
|
|
|
|
|
|
function FEATURE_FAMILY_STRATIXIIGX (device : in string) return boolean is
|
|
variable var_family_stratixiigx : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIXIIGX(device) or IS_FAMILY_ARRIAGX(device) )
|
|
then
|
|
var_family_stratixiigx := true;
|
|
end if;
|
|
return var_family_stratixiigx;
|
|
end FEATURE_FAMILY_STRATIXIIGX;
|
|
|
|
|
|
function FEATURE_FAMILY_STRATIXIII (device : in string) return boolean is
|
|
variable var_family_stratixiii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIXIII(device) or FEATURE_FAMILY_STRATIXIV(device) or FEATURE_FAMILY_HARDCOPYIII(device) )
|
|
then
|
|
var_family_stratixiii := true;
|
|
end if;
|
|
return var_family_stratixiii;
|
|
end FEATURE_FAMILY_STRATIXIII;
|
|
|
|
|
|
function FEATURE_FAMILY_ARRIAVGZ (device : in string) return boolean is
|
|
variable var_family_arriavgz : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_ARRIAVGZ(device) )
|
|
then
|
|
var_family_arriavgz := true;
|
|
end if;
|
|
return var_family_arriavgz;
|
|
end FEATURE_FAMILY_ARRIAVGZ;
|
|
|
|
|
|
function FEATURE_FAMILY_STRATIXV (device : in string) return boolean is
|
|
variable var_family_stratixv : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIXV(device) or FEATURE_FAMILY_ARRIAVGZ(device) )
|
|
then
|
|
var_family_stratixv := true;
|
|
end if;
|
|
return var_family_stratixv;
|
|
end FEATURE_FAMILY_STRATIXV;
|
|
|
|
|
|
function FEATURE_FAMILY_ARRIA10 (device : in string) return boolean is
|
|
variable var_family_arria10 : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_ARRIA10(device) or IS_FAMILY_ARRIA10(device) )
|
|
then
|
|
var_family_arria10 := true;
|
|
end if;
|
|
return var_family_arria10;
|
|
end FEATURE_FAMILY_ARRIA10;
|
|
|
|
|
|
function FEATURE_FAMILY_STRATIXII (device : in string) return boolean is
|
|
variable var_family_stratixii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIXII(device) or IS_FAMILY_HARDCOPYII(device) or FEATURE_FAMILY_STRATIXIIGX(device) or FEATURE_FAMILY_STRATIXIII(device) )
|
|
then
|
|
var_family_stratixii := true;
|
|
end if;
|
|
return var_family_stratixii;
|
|
end FEATURE_FAMILY_STRATIXII;
|
|
|
|
|
|
function FEATURE_FAMILY_CYCLONEIVGX (device : in string) return boolean is
|
|
variable var_family_cycloneivgx : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_CYCLONEIVGX(device) or IS_FAMILY_CYCLONEIVGX(device) )
|
|
then
|
|
var_family_cycloneivgx := true;
|
|
end if;
|
|
return var_family_cycloneivgx;
|
|
end FEATURE_FAMILY_CYCLONEIVGX;
|
|
|
|
|
|
function FEATURE_FAMILY_CYCLONEIVE (device : in string) return boolean is
|
|
variable var_family_cycloneive : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_CYCLONEIVE(device) )
|
|
then
|
|
var_family_cycloneive := true;
|
|
end if;
|
|
return var_family_cycloneive;
|
|
end FEATURE_FAMILY_CYCLONEIVE;
|
|
|
|
|
|
function FEATURE_FAMILY_CYCLONEIII (device : in string) return boolean is
|
|
variable var_family_cycloneiii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_CYCLONEIII(device) or IS_FAMILY_CYCLONEIIILS(device) or FEATURE_FAMILY_CYCLONEIVGX(device) or FEATURE_FAMILY_CYCLONEIVE(device) or FEATURE_FAMILY_MAX10(device) )
|
|
then
|
|
var_family_cycloneiii := true;
|
|
end if;
|
|
return var_family_cycloneiii;
|
|
end FEATURE_FAMILY_CYCLONEIII;
|
|
|
|
|
|
function FEATURE_FAMILY_STRATIX_HC (device : in string) return boolean is
|
|
variable var_family_stratix_hc : boolean := false;
|
|
begin
|
|
if ((device = "StratixHC") )
|
|
then
|
|
var_family_stratix_hc := true;
|
|
end if;
|
|
return var_family_stratix_hc;
|
|
end FEATURE_FAMILY_STRATIX_HC;
|
|
|
|
|
|
function FEATURE_FAMILY_HARDCOPYII (device : in string) return boolean is
|
|
variable var_family_hardcopyii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_HARDCOPYII(device) )
|
|
then
|
|
var_family_hardcopyii := true;
|
|
end if;
|
|
return var_family_hardcopyii;
|
|
end FEATURE_FAMILY_HARDCOPYII;
|
|
|
|
|
|
function FEATURE_FAMILY_STRATIX (device : in string) return boolean is
|
|
variable var_family_stratix : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIX(device) or FEATURE_FAMILY_STRATIX_HC(device) or FEATURE_FAMILY_STRATIXGX(device) or FEATURE_FAMILY_CYCLONE(device) or FEATURE_FAMILY_STRATIXII(device) or FEATURE_FAMILY_MAXII(device) or FEATURE_FAMILY_CYCLONEII(device) )
|
|
then
|
|
var_family_stratix := true;
|
|
end if;
|
|
return var_family_stratix;
|
|
end FEATURE_FAMILY_STRATIX;
|
|
|
|
|
|
function FEATURE_FAMILY_MAXII (device : in string) return boolean is
|
|
variable var_family_maxii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_MAXII(device) or FEATURE_FAMILY_MAXV(device) )
|
|
then
|
|
var_family_maxii := true;
|
|
end if;
|
|
return var_family_maxii;
|
|
end FEATURE_FAMILY_MAXII;
|
|
|
|
|
|
function FEATURE_FAMILY_MAXV (device : in string) return boolean is
|
|
variable var_family_maxv : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_MAXV(device) )
|
|
then
|
|
var_family_maxv := true;
|
|
end if;
|
|
return var_family_maxv;
|
|
end FEATURE_FAMILY_MAXV;
|
|
|
|
|
|
function FEATURE_FAMILY_CYCLONEII (device : in string) return boolean is
|
|
variable var_family_cycloneii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_CYCLONEII(device) or FEATURE_FAMILY_CYCLONEIII(device) )
|
|
then
|
|
var_family_cycloneii := true;
|
|
end if;
|
|
return var_family_cycloneii;
|
|
end FEATURE_FAMILY_CYCLONEII;
|
|
|
|
|
|
function FEATURE_FAMILY_STRATIXIV (device : in string) return boolean is
|
|
variable var_family_stratixiv : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIXIV(device) or IS_FAMILY_ARRIAIIGX(device) or FEATURE_FAMILY_HARDCOPYIV(device) or FEATURE_FAMILY_STRATIXV(device) or FEATURE_FAMILY_ARRIAV(device) or FEATURE_FAMILY_ARRIAIIGZ(device) or FEATURE_FAMILY_ARRIA10(device) )
|
|
then
|
|
var_family_stratixiv := true;
|
|
end if;
|
|
return var_family_stratixiv;
|
|
end FEATURE_FAMILY_STRATIXIV;
|
|
|
|
|
|
function FEATURE_FAMILY_ARRIAIIGZ (device : in string) return boolean is
|
|
variable var_family_arriaiigz : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_ARRIAIIGZ(device) )
|
|
then
|
|
var_family_arriaiigz := true;
|
|
end if;
|
|
return var_family_arriaiigz;
|
|
end FEATURE_FAMILY_ARRIAIIGZ;
|
|
|
|
|
|
function FEATURE_FAMILY_ARRIAIIGX (device : in string) return boolean is
|
|
variable var_family_arriaiigx : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_ARRIAIIGX(device) )
|
|
then
|
|
var_family_arriaiigx := true;
|
|
end if;
|
|
return var_family_arriaiigx;
|
|
end FEATURE_FAMILY_ARRIAIIGX;
|
|
|
|
|
|
function FEATURE_FAMILY_HARDCOPYIII (device : in string) return boolean is
|
|
variable var_family_hardcopyiii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_HARDCOPYIII(device) or IS_FAMILY_HARDCOPYIII(device) )
|
|
then
|
|
var_family_hardcopyiii := true;
|
|
end if;
|
|
return var_family_hardcopyiii;
|
|
end FEATURE_FAMILY_HARDCOPYIII;
|
|
|
|
|
|
function FEATURE_FAMILY_HARDCOPYIV (device : in string) return boolean is
|
|
variable var_family_hardcopyiv : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_HARDCOPYIV(device) or IS_FAMILY_HARDCOPYIV(device) )
|
|
then
|
|
var_family_hardcopyiv := true;
|
|
end if;
|
|
return var_family_hardcopyiv;
|
|
end FEATURE_FAMILY_HARDCOPYIV;
|
|
|
|
|
|
function FEATURE_FAMILY_CYCLONEV (device : in string) return boolean is
|
|
variable var_family_cyclonev : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_CYCLONEV(device) )
|
|
then
|
|
var_family_cyclonev := true;
|
|
end if;
|
|
return var_family_cyclonev;
|
|
end FEATURE_FAMILY_CYCLONEV;
|
|
|
|
|
|
function FEATURE_FAMILY_ARRIAV (device : in string) return boolean is
|
|
variable var_family_arriav : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_ARRIAV(device) or FEATURE_FAMILY_CYCLONEV(device) )
|
|
then
|
|
var_family_arriav := true;
|
|
end if;
|
|
return var_family_arriav;
|
|
end FEATURE_FAMILY_ARRIAV;
|
|
|
|
|
|
function FEATURE_FAMILY_MAX10 (device : in string) return boolean is
|
|
variable var_family_max10 : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_MAX10(device) )
|
|
then
|
|
var_family_max10 := true;
|
|
end if;
|
|
return var_family_max10;
|
|
end FEATURE_FAMILY_MAX10;
|
|
|
|
|
|
function FEATURE_FAMILY_STRATIX10 (device : in string) return boolean is
|
|
variable var_family_stratix10 : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIX10(device) or IS_FAMILY_STRATIX10(device) )
|
|
then
|
|
var_family_stratix10 := true;
|
|
end if;
|
|
return var_family_stratix10;
|
|
end FEATURE_FAMILY_STRATIX10;
|
|
|
|
|
|
function FEATURE_FAMILY_BASE_STRATIXII (device : in string) return boolean is
|
|
variable var_family_base_stratixii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIXII(device) or IS_FAMILY_HARDCOPYII(device) or FEATURE_FAMILY_STRATIXIIGX(device) )
|
|
then
|
|
var_family_base_stratixii := true;
|
|
end if;
|
|
return var_family_base_stratixii;
|
|
end FEATURE_FAMILY_BASE_STRATIXII;
|
|
|
|
|
|
function FEATURE_FAMILY_BASE_STRATIX (device : in string) return boolean is
|
|
variable var_family_base_stratix : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIX(device) or IS_FAMILY_STRATIXGX(device) )
|
|
then
|
|
var_family_base_stratix := true;
|
|
end if;
|
|
return var_family_base_stratix;
|
|
end FEATURE_FAMILY_BASE_STRATIX;
|
|
|
|
|
|
function FEATURE_FAMILY_BASE_CYCLONEII (device : in string) return boolean is
|
|
variable var_family_base_cycloneii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_CYCLONEII(device) )
|
|
then
|
|
var_family_base_cycloneii := true;
|
|
end if;
|
|
return var_family_base_cycloneii;
|
|
end FEATURE_FAMILY_BASE_CYCLONEII;
|
|
|
|
|
|
function FEATURE_FAMILY_BASE_CYCLONE (device : in string) return boolean is
|
|
variable var_family_base_cyclone : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_CYCLONE(device) )
|
|
then
|
|
var_family_base_cyclone := true;
|
|
end if;
|
|
return var_family_base_cyclone;
|
|
end FEATURE_FAMILY_BASE_CYCLONE;
|
|
|
|
|
|
function FEATURE_FAMILY_BASE_CYCLONEIII (device : in string) return boolean is
|
|
variable var_family_base_cycloneiii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_CYCLONEIII(device) or IS_FAMILY_CYCLONEIIILS(device) or IS_FAMILY_CYCLONEIVGX(device) or FEATURE_FAMILY_CYCLONEIVE(device) or FEATURE_FAMILY_MAX10(device) )
|
|
then
|
|
var_family_base_cycloneiii := true;
|
|
end if;
|
|
return var_family_base_cycloneiii;
|
|
end FEATURE_FAMILY_BASE_CYCLONEIII;
|
|
|
|
|
|
function FEATURE_FAMILY_BASE_STRATIXIII (device : in string) return boolean is
|
|
variable var_family_base_stratixiii : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIXIII(device) or FEATURE_FAMILY_STRATIXIV(device) or IS_FAMILY_HARDCOPYIII(device) )
|
|
then
|
|
var_family_base_stratixiii := true;
|
|
end if;
|
|
return var_family_base_stratixiii;
|
|
end FEATURE_FAMILY_BASE_STRATIXIII;
|
|
|
|
|
|
function FEATURE_FAMILY_STRATIX_NONGX (device : in string) return boolean is
|
|
variable var_family_stratix_nongx : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIX(device) )
|
|
then
|
|
var_family_stratix_nongx := true;
|
|
end if;
|
|
return var_family_stratix_nongx;
|
|
end FEATURE_FAMILY_STRATIX_NONGX;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_ALTERA_MULT_ADD_FLOW (device : in string) return boolean is
|
|
variable var_family_has_altera_mult_add_flow : boolean := false;
|
|
begin
|
|
if (FEATURE_FAMILY_STRATIXV(device) or FEATURE_FAMILY_ARRIAV(device) or FEATURE_FAMILY_CYCLONEV(device) or FEATURE_FAMILY_ARRIA10(device) or FEATURE_FAMILY_STRATIX10(device) )
|
|
then
|
|
var_family_has_altera_mult_add_flow := true;
|
|
end if;
|
|
return var_family_has_altera_mult_add_flow;
|
|
end FEATURE_FAMILY_HAS_ALTERA_MULT_ADD_FLOW;
|
|
|
|
|
|
function FEATURE_FAMILY_IS_ALTMULT_ADD_EOL (device : in string) return boolean is
|
|
variable var_family_is_altmult_add_eol : boolean := false;
|
|
begin
|
|
if (FEATURE_FAMILY_ARRIA10(device) or FEATURE_FAMILY_STRATIX10(device) )
|
|
then
|
|
var_family_is_altmult_add_eol := true;
|
|
end if;
|
|
return var_family_is_altmult_add_eol;
|
|
end FEATURE_FAMILY_IS_ALTMULT_ADD_EOL;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_STRATIXV_STYLE_RAM (device : in string) return boolean is
|
|
variable var_family_has_stratixv_style_ram : boolean := false;
|
|
begin
|
|
if (FEATURE_FAMILY_STRATIXV(device) or FEATURE_FAMILY_ARRIAV(device) or FEATURE_FAMILY_ARRIA10(device) )
|
|
then
|
|
var_family_has_stratixv_style_ram := true;
|
|
end if;
|
|
return var_family_has_stratixv_style_ram;
|
|
end FEATURE_FAMILY_HAS_STRATIXV_STYLE_RAM;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_MEGARAM (device : in string) return boolean is
|
|
variable var_family_has_megaram : boolean := false;
|
|
begin
|
|
if (( ( IS_FAMILY_STRATIX(device) or FEATURE_FAMILY_STRATIX_HC(device) or IS_FAMILY_STRATIXGX(device) or FEATURE_FAMILY_STRATIXII(device) ) and NOT FEATURE_FAMILY_ARRIAIIGX(device) ) and NOT FEATURE_FAMILY_HAS_STRATIXV_STYLE_RAM(device) )
|
|
then
|
|
var_family_has_megaram := true;
|
|
end if;
|
|
return var_family_has_megaram;
|
|
end FEATURE_FAMILY_HAS_MEGARAM;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_M512 (device : in string) return boolean is
|
|
variable var_family_has_m512 : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIX(device) or FEATURE_FAMILY_STRATIX_HC(device) or IS_FAMILY_STRATIXGX(device) or IS_FAMILY_STRATIXII(device) or FEATURE_FAMILY_STRATIXIIGX(device) )
|
|
then
|
|
var_family_has_m512 := true;
|
|
end if;
|
|
return var_family_has_m512;
|
|
end FEATURE_FAMILY_HAS_M512;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_LUTRAM (device : in string) return boolean is
|
|
variable var_family_has_lutram : boolean := false;
|
|
begin
|
|
if (FEATURE_FAMILY_STRATIXIII(device) or FEATURE_FAMILY_HAS_STRATIXV_STYLE_RAM(device) or FEATURE_FAMILY_STRATIX10(device) )
|
|
then
|
|
var_family_has_lutram := true;
|
|
end if;
|
|
return var_family_has_lutram;
|
|
end FEATURE_FAMILY_HAS_LUTRAM;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_STRATIXI_STYLE_RAM (device : in string) return boolean is
|
|
variable var_family_has_stratixi_style_ram : boolean := false;
|
|
begin
|
|
if (IS_FAMILY_STRATIX(device) or FEATURE_FAMILY_STRATIX_HC(device) or FEATURE_FAMILY_STRATIXGX(device) or FEATURE_FAMILY_CYCLONE(device) )
|
|
then
|
|
var_family_has_stratixi_style_ram := true;
|
|
end if;
|
|
return var_family_has_stratixi_style_ram;
|
|
end FEATURE_FAMILY_HAS_STRATIXI_STYLE_RAM;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM (device : in string) return boolean is
|
|
variable var_family_has_stratixii_style_ram : boolean := false;
|
|
begin
|
|
if (FEATURE_FAMILY_STRATIXII(device) or FEATURE_FAMILY_CYCLONEII(device) )
|
|
then
|
|
var_family_has_stratixii_style_ram := true;
|
|
end if;
|
|
return var_family_has_stratixii_style_ram;
|
|
end FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM (device : in string) return boolean is
|
|
variable var_family_has_stratixiii_style_ram : boolean := false;
|
|
begin
|
|
if (FEATURE_FAMILY_STRATIXIII(device) or FEATURE_FAMILY_CYCLONEIII(device) )
|
|
then
|
|
var_family_has_stratixiii_style_ram := true;
|
|
end if;
|
|
return var_family_has_stratixiii_style_ram;
|
|
end FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL (device : in string) return boolean is
|
|
variable var_family_has_stratix_style_pll : boolean := false;
|
|
begin
|
|
if (FEATURE_FAMILY_CYCLONE(device) or FEATURE_FAMILY_STRATIX_HC(device) or IS_FAMILY_STRATIX(device) or FEATURE_FAMILY_STRATIXGX(device) )
|
|
then
|
|
var_family_has_stratix_style_pll := true;
|
|
end if;
|
|
return var_family_has_stratix_style_pll;
|
|
end FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL (device : in string) return boolean is
|
|
variable var_family_has_stratixii_style_pll : boolean := false;
|
|
begin
|
|
if (( ( FEATURE_FAMILY_STRATIXII(device) and NOT FEATURE_FAMILY_STRATIXIII(device) ) or FEATURE_FAMILY_CYCLONEII(device) ) and NOT FEATURE_FAMILY_CYCLONEIII(device) )
|
|
then
|
|
var_family_has_stratixii_style_pll := true;
|
|
end if;
|
|
return var_family_has_stratixii_style_pll;
|
|
end FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL;
|
|
|
|
|
|
function FEATURE_FAMILY_USES_STRATIXIII_PLL (device : in string) return boolean is
|
|
variable var_family_uses_stratixiii_pll : boolean := false;
|
|
begin
|
|
if (FEATURE_FAMILY_STRATIXIII(device) or FEATURE_FAMILY_CYCLONEIII(device) )
|
|
then
|
|
var_family_uses_stratixiii_pll := true;
|
|
end if;
|
|
return var_family_uses_stratixiii_pll;
|
|
end FEATURE_FAMILY_USES_STRATIXIII_PLL;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_FLEXIBLE_LVDS (device : in string) return boolean is
|
|
variable var_family_has_flexible_lvds : boolean := false;
|
|
begin
|
|
if (FEATURE_FAMILY_CYCLONE(device) or FEATURE_FAMILY_CYCLONEII(device) or FEATURE_FAMILY_MAXV(device) )
|
|
then
|
|
var_family_has_flexible_lvds := true;
|
|
end if;
|
|
return var_family_has_flexible_lvds;
|
|
end FEATURE_FAMILY_HAS_FLEXIBLE_LVDS;
|
|
|
|
|
|
function FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO (device : in string) return boolean is
|
|
variable var_family_has_inverted_output_ddio : boolean := false;
|
|
begin
|
|
if (FEATURE_FAMILY_CYCLONEII(device) )
|
|
then
|
|
var_family_has_inverted_output_ddio := true;
|
|
end if;
|
|
return var_family_has_inverted_output_ddio;
|
|
end FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO;
|
|
|
|
|
|
function IS_VALID_FAMILY (device : in string) return boolean is
|
|
variable is_valid : boolean := false;
|
|
begin
|
|
if (((device = "Arria 10") or (device = "ARRIA 10") or (device = "arria 10") or (device = "Arria10") or (device = "ARRIA10") or (device = "arria10") or (device = "Arria VI") or (device = "ARRIA VI") or (device = "arria vi") or (device = "ArriaVI") or (device = "ARRIAVI") or (device = "arriavi") or (device = "Night Fury") or (device = "NIGHT FURY") or (device = "night fury") or (device = "nightfury") or (device = "NIGHTFURY") or (device = "Arria 10 (GX/SX/GT)") or (device = "ARRIA 10 (GX/SX/GT)") or (device = "arria 10 (gx/sx/gt)") or (device = "Arria10(GX/SX/GT)") or (device = "ARRIA10(GX/SX/GT)") or (device = "arria10(gx/sx/gt)") or (device = "Arria 10 (GX)") or (device = "ARRIA 10 (GX)") or (device = "arria 10 (gx)") or (device = "Arria10(GX)") or (device = "ARRIA10(GX)") or (device = "arria10(gx)") or (device = "Arria 10 (SX)") or (device = "ARRIA 10 (SX)") or (device = "arria 10 (sx)") or (device = "Arria10(SX)") or (device = "ARRIA10(SX)") or (device = "arria10(sx)") or (device = "Arria 10 (GT)") or (device = "ARRIA 10 (GT)") or (device = "arria 10 (gt)") or (device = "Arria10(GT)") or (device = "ARRIA10(GT)") or (device = "arria10(gt)"))
|
|
or ((device = "Arria GX") or (device = "ARRIA GX") or (device = "arria gx") or (device = "ArriaGX") or (device = "ARRIAGX") or (device = "arriagx") or (device = "Stratix II GX Lite") or (device = "STRATIX II GX LITE") or (device = "stratix ii gx lite") or (device = "StratixIIGXLite") or (device = "STRATIXIIGXLITE") or (device = "stratixiigxlite"))
|
|
or ((device = "Arria II GX") or (device = "ARRIA II GX") or (device = "arria ii gx") or (device = "ArriaIIGX") or (device = "ARRIAIIGX") or (device = "arriaiigx") or (device = "Arria IIGX") or (device = "ARRIA IIGX") or (device = "arria iigx") or (device = "ArriaII GX") or (device = "ARRIAII GX") or (device = "arriaii gx") or (device = "Arria II") or (device = "ARRIA II") or (device = "arria ii") or (device = "ArriaII") or (device = "ARRIAII") or (device = "arriaii") or (device = "Arria II (GX/E)") or (device = "ARRIA II (GX/E)") or (device = "arria ii (gx/e)") or (device = "ArriaII(GX/E)") or (device = "ARRIAII(GX/E)") or (device = "arriaii(gx/e)") or (device = "PIRANHA") or (device = "piranha"))
|
|
or ((device = "Arria II GZ") or (device = "ARRIA II GZ") or (device = "arria ii gz") or (device = "ArriaII GZ") or (device = "ARRIAII GZ") or (device = "arriaii gz") or (device = "Arria IIGZ") or (device = "ARRIA IIGZ") or (device = "arria iigz") or (device = "ArriaIIGZ") or (device = "ARRIAIIGZ") or (device = "arriaiigz"))
|
|
or ((device = "Arria V GZ") or (device = "ARRIA V GZ") or (device = "arria v gz") or (device = "ArriaVGZ") or (device = "ARRIAVGZ") or (device = "arriavgz"))
|
|
or ((device = "Arria V") or (device = "ARRIA V") or (device = "arria v") or (device = "Arria V (GT/GX)") or (device = "ARRIA V (GT/GX)") or (device = "arria v (gt/gx)") or (device = "ArriaV(GT/GX)") or (device = "ARRIAV(GT/GX)") or (device = "arriav(gt/gx)") or (device = "ArriaV") or (device = "ARRIAV") or (device = "arriav") or (device = "Arria V (GT/GX/ST/SX)") or (device = "ARRIA V (GT/GX/ST/SX)") or (device = "arria v (gt/gx/st/sx)") or (device = "ArriaV(GT/GX/ST/SX)") or (device = "ARRIAV(GT/GX/ST/SX)") or (device = "arriav(gt/gx/st/sx)") or (device = "Arria V (GT)") or (device = "ARRIA V (GT)") or (device = "arria v (gt)") or (device = "ArriaV(GT)") or (device = "ARRIAV(GT)") or (device = "arriav(gt)") or (device = "Arria V (GX)") or (device = "ARRIA V (GX)") or (device = "arria v (gx)") or (device = "ArriaV(GX)") or (device = "ARRIAV(GX)") or (device = "arriav(gx)") or (device = "Arria V (ST)") or (device = "ARRIA V (ST)") or (device = "arria v (st)") or (device = "ArriaV(ST)") or (device = "ARRIAV(ST)") or (device = "arriav(st)") or (device = "Arria V (SX)") or (device = "ARRIA V (SX)") or (device = "arria v (sx)") or (device = "ArriaV(SX)") or (device = "ARRIAV(SX)") or (device = "arriav(sx)"))
|
|
or ((device = "BS") or (device = "bs"))
|
|
or ((device = "Cyclone II") or (device = "CYCLONE II") or (device = "cyclone ii") or (device = "Cycloneii") or (device = "CYCLONEII") or (device = "cycloneii") or (device = "Magellan") or (device = "MAGELLAN") or (device = "magellan") or (device = "CycloneII") or (device = "CYCLONEII") or (device = "cycloneii"))
|
|
or ((device = "Cyclone III LS") or (device = "CYCLONE III LS") or (device = "cyclone iii ls") or (device = "CycloneIIILS") or (device = "CYCLONEIIILS") or (device = "cycloneiiils") or (device = "Cyclone III LPS") or (device = "CYCLONE III LPS") or (device = "cyclone iii lps") or (device = "Cyclone LPS") or (device = "CYCLONE LPS") or (device = "cyclone lps") or (device = "CycloneLPS") or (device = "CYCLONELPS") or (device = "cyclonelps") or (device = "Tarpon") or (device = "TARPON") or (device = "tarpon") or (device = "Cyclone IIIE") or (device = "CYCLONE IIIE") or (device = "cyclone iiie"))
|
|
or ((device = "Cyclone III") or (device = "CYCLONE III") or (device = "cyclone iii") or (device = "CycloneIII") or (device = "CYCLONEIII") or (device = "cycloneiii") or (device = "Barracuda") or (device = "BARRACUDA") or (device = "barracuda") or (device = "Cuda") or (device = "CUDA") or (device = "cuda") or (device = "CIII") or (device = "ciii"))
|
|
or ((device = "Cyclone IV E") or (device = "CYCLONE IV E") or (device = "cyclone iv e") or (device = "CycloneIV E") or (device = "CYCLONEIV E") or (device = "cycloneiv e") or (device = "Cyclone IVE") or (device = "CYCLONE IVE") or (device = "cyclone ive") or (device = "CycloneIVE") or (device = "CYCLONEIVE") or (device = "cycloneive"))
|
|
or ((device = "Cyclone IV GX") or (device = "CYCLONE IV GX") or (device = "cyclone iv gx") or (device = "Cyclone IVGX") or (device = "CYCLONE IVGX") or (device = "cyclone ivgx") or (device = "CycloneIV GX") or (device = "CYCLONEIV GX") or (device = "cycloneiv gx") or (device = "CycloneIVGX") or (device = "CYCLONEIVGX") or (device = "cycloneivgx") or (device = "Cyclone IV") or (device = "CYCLONE IV") or (device = "cyclone iv") or (device = "CycloneIV") or (device = "CYCLONEIV") or (device = "cycloneiv") or (device = "Cyclone IV (GX)") or (device = "CYCLONE IV (GX)") or (device = "cyclone iv (gx)") or (device = "CycloneIV(GX)") or (device = "CYCLONEIV(GX)") or (device = "cycloneiv(gx)") or (device = "Cyclone III GX") or (device = "CYCLONE III GX") or (device = "cyclone iii gx") or (device = "CycloneIII GX") or (device = "CYCLONEIII GX") or (device = "cycloneiii gx") or (device = "Cyclone IIIGX") or (device = "CYCLONE IIIGX") or (device = "cyclone iiigx") or (device = "CycloneIIIGX") or (device = "CYCLONEIIIGX") or (device = "cycloneiiigx") or (device = "Cyclone III GL") or (device = "CYCLONE III GL") or (device = "cyclone iii gl") or (device = "CycloneIII GL") or (device = "CYCLONEIII GL") or (device = "cycloneiii gl") or (device = "Cyclone IIIGL") or (device = "CYCLONE IIIGL") or (device = "cyclone iiigl") or (device = "CycloneIIIGL") or (device = "CYCLONEIIIGL") or (device = "cycloneiiigl") or (device = "Stingray") or (device = "STINGRAY") or (device = "stingray"))
|
|
or ((device = "Cyclone V") or (device = "CYCLONE V") or (device = "cyclone v") or (device = "CycloneV") or (device = "CYCLONEV") or (device = "cyclonev") or (device = "Cyclone V (GT/GX/E/SX)") or (device = "CYCLONE V (GT/GX/E/SX)") or (device = "cyclone v (gt/gx/e/sx)") or (device = "CycloneV(GT/GX/E/SX)") or (device = "CYCLONEV(GT/GX/E/SX)") or (device = "cyclonev(gt/gx/e/sx)") or (device = "Cyclone V (E/GX/GT/SX/SE/ST)") or (device = "CYCLONE V (E/GX/GT/SX/SE/ST)") or (device = "cyclone v (e/gx/gt/sx/se/st)") or (device = "CycloneV(E/GX/GT/SX/SE/ST)") or (device = "CYCLONEV(E/GX/GT/SX/SE/ST)") or (device = "cyclonev(e/gx/gt/sx/se/st)") or (device = "Cyclone V (E)") or (device = "CYCLONE V (E)") or (device = "cyclone v (e)") or (device = "CycloneV(E)") or (device = "CYCLONEV(E)") or (device = "cyclonev(e)") or (device = "Cyclone V (GX)") or (device = "CYCLONE V (GX)") or (device = "cyclone v (gx)") or (device = "CycloneV(GX)") or (device = "CYCLONEV(GX)") or (device = "cyclonev(gx)") or (device = "Cyclone V (GT)") or (device = "CYCLONE V (GT)") or (device = "cyclone v (gt)") or (device = "CycloneV(GT)") or (device = "CYCLONEV(GT)") or (device = "cyclonev(gt)") or (device = "Cyclone V (SX)") or (device = "CYCLONE V (SX)") or (device = "cyclone v (sx)") or (device = "CycloneV(SX)") or (device = "CYCLONEV(SX)") or (device = "cyclonev(sx)") or (device = "Cyclone V (SE)") or (device = "CYCLONE V (SE)") or (device = "cyclone v (se)") or (device = "CycloneV(SE)") or (device = "CYCLONEV(SE)") or (device = "cyclonev(se)") or (device = "Cyclone V (ST)") or (device = "CYCLONE V (ST)") or (device = "cyclone v (st)") or (device = "CycloneV(ST)") or (device = "CYCLONEV(ST)") or (device = "cyclonev(st)"))
|
|
or ((device = "Cyclone") or (device = "CYCLONE") or (device = "cyclone") or (device = "ACEX2K") or (device = "acex2k") or (device = "ACEX 2K") or (device = "acex 2k") or (device = "Tornado") or (device = "TORNADO") or (device = "tornado"))
|
|
or ((device = "HardCopy II") or (device = "HARDCOPY II") or (device = "hardcopy ii") or (device = "HardCopyII") or (device = "HARDCOPYII") or (device = "hardcopyii") or (device = "Fusion") or (device = "FUSION") or (device = "fusion"))
|
|
or ((device = "HardCopy III") or (device = "HARDCOPY III") or (device = "hardcopy iii") or (device = "HardCopyIII") or (device = "HARDCOPYIII") or (device = "hardcopyiii") or (device = "HCX") or (device = "hcx"))
|
|
or ((device = "HardCopy IV") or (device = "HARDCOPY IV") or (device = "hardcopy iv") or (device = "HardCopyIV") or (device = "HARDCOPYIV") or (device = "hardcopyiv") or (device = "HardCopy IV (GX)") or (device = "HARDCOPY IV (GX)") or (device = "hardcopy iv (gx)") or (device = "HardCopy IV (E)") or (device = "HARDCOPY IV (E)") or (device = "hardcopy iv (e)") or (device = "HardCopyIV(GX)") or (device = "HARDCOPYIV(GX)") or (device = "hardcopyiv(gx)") or (device = "HardCopyIV(E)") or (device = "HARDCOPYIV(E)") or (device = "hardcopyiv(e)") or (device = "HCXIV") or (device = "hcxiv") or (device = "HardCopy IV (GX/E)") or (device = "HARDCOPY IV (GX/E)") or (device = "hardcopy iv (gx/e)") or (device = "HardCopy IV (E/GX)") or (device = "HARDCOPY IV (E/GX)") or (device = "hardcopy iv (e/gx)") or (device = "HardCopyIV(GX/E)") or (device = "HARDCOPYIV(GX/E)") or (device = "hardcopyiv(gx/e)") or (device = "HardCopyIV(E/GX)") or (device = "HARDCOPYIV(E/GX)") or (device = "hardcopyiv(e/gx)"))
|
|
or ((device = "MAX 10") or (device = "max 10") or (device = "MAX 10 FPGA") or (device = "max 10 fpga") or (device = "Zippleback") or (device = "ZIPPLEBACK") or (device = "zippleback") or (device = "MAX10") or (device = "max10") or (device = "MAX 10 (DA/DF/DC/SA/SF/SC)") or (device = "max 10 (da/df/dc/sa/sf/sc)") or (device = "MAX10(DA/DF/DC/SA/SF/SC)") or (device = "max10(da/df/dc/sa/sf/sc)") or (device = "MAX 10 (DA)") or (device = "max 10 (da)") or (device = "MAX10(DA)") or (device = "max10(da)") or (device = "MAX 10 (DF)") or (device = "max 10 (df)") or (device = "MAX10(DF)") or (device = "max10(df)") or (device = "MAX 10 (DC)") or (device = "max 10 (dc)") or (device = "MAX10(DC)") or (device = "max10(dc)") or (device = "MAX 10 (SA)") or (device = "max 10 (sa)") or (device = "MAX10(SA)") or (device = "max10(sa)") or (device = "MAX 10 (SF)") or (device = "max 10 (sf)") or (device = "MAX10(SF)") or (device = "max10(sf)") or (device = "MAX 10 (SC)") or (device = "max 10 (sc)") or (device = "MAX10(SC)") or (device = "max10(sc)"))
|
|
or ((device = "MAX II") or (device = "max ii") or (device = "MAXII") or (device = "maxii") or (device = "Tsunami") or (device = "TSUNAMI") or (device = "tsunami"))
|
|
or ((device = "MAX V") or (device = "max v") or (device = "MAXV") or (device = "maxv") or (device = "Jade") or (device = "JADE") or (device = "jade"))
|
|
or ((device = "MAX3000A") or (device = "max3000a") or (device = "MAX 3000A") or (device = "max 3000a"))
|
|
or ((device = "MAX7000A") or (device = "max7000a") or (device = "MAX 7000A") or (device = "max 7000a"))
|
|
or ((device = "MAX7000AE") or (device = "max7000ae") or (device = "MAX 7000AE") or (device = "max 7000ae"))
|
|
or ((device = "MAX7000B") or (device = "max7000b") or (device = "MAX 7000B") or (device = "max 7000b"))
|
|
or ((device = "MAX7000S") or (device = "max7000s") or (device = "MAX 7000S") or (device = "max 7000s"))
|
|
or ((device = "Stratix 10") or (device = "STRATIX 10") or (device = "stratix 10") or (device = "Stratix10") or (device = "STRATIX10") or (device = "stratix10") or (device = "nadder") or (device = "NADDER"))
|
|
or ((device = "Stratix GX") or (device = "STRATIX GX") or (device = "stratix gx") or (device = "Stratix-GX") or (device = "STRATIX-GX") or (device = "stratix-gx") or (device = "StratixGX") or (device = "STRATIXGX") or (device = "stratixgx") or (device = "Aurora") or (device = "AURORA") or (device = "aurora"))
|
|
or ((device = "Stratix II GX") or (device = "STRATIX II GX") or (device = "stratix ii gx") or (device = "StratixIIGX") or (device = "STRATIXIIGX") or (device = "stratixiigx"))
|
|
or ((device = "Stratix II") or (device = "STRATIX II") or (device = "stratix ii") or (device = "StratixII") or (device = "STRATIXII") or (device = "stratixii") or (device = "Armstrong") or (device = "ARMSTRONG") or (device = "armstrong"))
|
|
or ((device = "Stratix III") or (device = "STRATIX III") or (device = "stratix iii") or (device = "StratixIII") or (device = "STRATIXIII") or (device = "stratixiii") or (device = "Titan") or (device = "TITAN") or (device = "titan") or (device = "SIII") or (device = "siii"))
|
|
or ((device = "Stratix IV") or (device = "STRATIX IV") or (device = "stratix iv") or (device = "TGX") or (device = "tgx") or (device = "StratixIV") or (device = "STRATIXIV") or (device = "stratixiv") or (device = "Stratix IV (GT)") or (device = "STRATIX IV (GT)") or (device = "stratix iv (gt)") or (device = "Stratix IV (GX)") or (device = "STRATIX IV (GX)") or (device = "stratix iv (gx)") or (device = "Stratix IV (E)") or (device = "STRATIX IV (E)") or (device = "stratix iv (e)") or (device = "StratixIV(GT)") or (device = "STRATIXIV(GT)") or (device = "stratixiv(gt)") or (device = "StratixIV(GX)") or (device = "STRATIXIV(GX)") or (device = "stratixiv(gx)") or (device = "StratixIV(E)") or (device = "STRATIXIV(E)") or (device = "stratixiv(e)") or (device = "StratixIIIGX") or (device = "STRATIXIIIGX") or (device = "stratixiiigx") or (device = "Stratix IV (GT/GX/E)") or (device = "STRATIX IV (GT/GX/E)") or (device = "stratix iv (gt/gx/e)") or (device = "Stratix IV (GT/E/GX)") or (device = "STRATIX IV (GT/E/GX)") or (device = "stratix iv (gt/e/gx)") or (device = "Stratix IV (E/GT/GX)") or (device = "STRATIX IV (E/GT/GX)") or (device = "stratix iv (e/gt/gx)") or (device = "Stratix IV (E/GX/GT)") or (device = "STRATIX IV (E/GX/GT)") or (device = "stratix iv (e/gx/gt)") or (device = "StratixIV(GT/GX/E)") or (device = "STRATIXIV(GT/GX/E)") or (device = "stratixiv(gt/gx/e)") or (device = "StratixIV(GT/E/GX)") or (device = "STRATIXIV(GT/E/GX)") or (device = "stratixiv(gt/e/gx)") or (device = "StratixIV(E/GX/GT)") or (device = "STRATIXIV(E/GX/GT)") or (device = "stratixiv(e/gx/gt)") or (device = "StratixIV(E/GT/GX)") or (device = "STRATIXIV(E/GT/GX)") or (device = "stratixiv(e/gt/gx)") or (device = "Stratix IV (GX/E)") or (device = "STRATIX IV (GX/E)") or (device = "stratix iv (gx/e)") or (device = "StratixIV(GX/E)") or (device = "STRATIXIV(GX/E)") or (device = "stratixiv(gx/e)"))
|
|
or ((device = "Stratix V") or (device = "STRATIX V") or (device = "stratix v") or (device = "StratixV") or (device = "STRATIXV") or (device = "stratixv") or (device = "Stratix V (GS)") or (device = "STRATIX V (GS)") or (device = "stratix v (gs)") or (device = "StratixV(GS)") or (device = "STRATIXV(GS)") or (device = "stratixv(gs)") or (device = "Stratix V (GT)") or (device = "STRATIX V (GT)") or (device = "stratix v (gt)") or (device = "StratixV(GT)") or (device = "STRATIXV(GT)") or (device = "stratixv(gt)") or (device = "Stratix V (GX)") or (device = "STRATIX V (GX)") or (device = "stratix v (gx)") or (device = "StratixV(GX)") or (device = "STRATIXV(GX)") or (device = "stratixv(gx)") or (device = "Stratix V (GS/GX)") or (device = "STRATIX V (GS/GX)") or (device = "stratix v (gs/gx)") or (device = "StratixV(GS/GX)") or (device = "STRATIXV(GS/GX)") or (device = "stratixv(gs/gx)") or (device = "Stratix V (GS/GT)") or (device = "STRATIX V (GS/GT)") or (device = "stratix v (gs/gt)") or (device = "StratixV(GS/GT)") or (device = "STRATIXV(GS/GT)") or (device = "stratixv(gs/gt)") or (device = "Stratix V (GT/GX)") or (device = "STRATIX V (GT/GX)") or (device = "stratix v (gt/gx)") or (device = "StratixV(GT/GX)") or (device = "STRATIXV(GT/GX)") or (device = "stratixv(gt/gx)") or (device = "Stratix V (GX/GS)") or (device = "STRATIX V (GX/GS)") or (device = "stratix v (gx/gs)") or (device = "StratixV(GX/GS)") or (device = "STRATIXV(GX/GS)") or (device = "stratixv(gx/gs)") or (device = "Stratix V (GT/GS)") or (device = "STRATIX V (GT/GS)") or (device = "stratix v (gt/gs)") or (device = "StratixV(GT/GS)") or (device = "STRATIXV(GT/GS)") or (device = "stratixv(gt/gs)") or (device = "Stratix V (GX/GT)") or (device = "STRATIX V (GX/GT)") or (device = "stratix v (gx/gt)") or (device = "StratixV(GX/GT)") or (device = "STRATIXV(GX/GT)") or (device = "stratixv(gx/gt)") or (device = "Stratix V (GS/GT/GX)") or (device = "STRATIX V (GS/GT/GX)") or (device = "stratix v (gs/gt/gx)") or (device = "Stratix V (GS/GX/GT)") or (device = "STRATIX V (GS/GX/GT)") or (device = "stratix v (gs/gx/gt)") or (device = "Stratix V (GT/GS/GX)") or (device = "STRATIX V (GT/GS/GX)") or (device = "stratix v (gt/gs/gx)") or (device = "Stratix V (GT/GX/GS)") or (device = "STRATIX V (GT/GX/GS)") or (device = "stratix v (gt/gx/gs)") or (device = "Stratix V (GX/GS/GT)") or (device = "STRATIX V (GX/GS/GT)") or (device = "stratix v (gx/gs/gt)") or (device = "Stratix V (GX/GT/GS)") or (device = "STRATIX V (GX/GT/GS)") or (device = "stratix v (gx/gt/gs)") or (device = "StratixV(GS/GT/GX)") or (device = "STRATIXV(GS/GT/GX)") or (device = "stratixv(gs/gt/gx)") or (device = "StratixV(GS/GX/GT)") or (device = "STRATIXV(GS/GX/GT)") or (device = "stratixv(gs/gx/gt)") or (device = "StratixV(GT/GS/GX)") or (device = "STRATIXV(GT/GS/GX)") or (device = "stratixv(gt/gs/gx)") or (device = "StratixV(GT/GX/GS)") or (device = "STRATIXV(GT/GX/GS)") or (device = "stratixv(gt/gx/gs)") or (device = "StratixV(GX/GS/GT)") or (device = "STRATIXV(GX/GS/GT)") or (device = "stratixv(gx/gs/gt)") or (device = "StratixV(GX/GT/GS)") or (device = "STRATIXV(GX/GT/GS)") or (device = "stratixv(gx/gt/gs)") or (device = "Stratix V (GS/GT/GX/E)") or (device = "STRATIX V (GS/GT/GX/E)") or (device = "stratix v (gs/gt/gx/e)") or (device = "StratixV(GS/GT/GX/E)") or (device = "STRATIXV(GS/GT/GX/E)") or (device = "stratixv(gs/gt/gx/e)") or (device = "Stratix V (E)") or (device = "STRATIX V (E)") or (device = "stratix v (e)") or (device = "StratixV(E)") or (device = "STRATIXV(E)") or (device = "stratixv(e)"))
|
|
or ((device = "Stratix") or (device = "STRATIX") or (device = "stratix") or (device = "Yeager") or (device = "YEAGER") or (device = "yeager"))
|
|
or ((device = "eFPGA 28 HPM") or (device = "EFPGA 28 HPM") or (device = "efpga 28 hpm") or (device = "eFPGA28HPM") or (device = "EFPGA28HPM") or (device = "efpga28hpm") or (device = "Bedrock") or (device = "BEDROCK") or (device = "bedrock")))
|
|
then
|
|
is_valid := true;
|
|
end if;
|
|
return is_valid;
|
|
end IS_VALID_FAMILY;
|
|
|
|
|
|
end ALTERA_DEVICE_FAMILIES;
|
|
-- END OF PACKAGE
|
|
|
|
Library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
-- START PACKAGE HEADER --------------------------------------------------------
|
|
--
|
|
-- Package Name : MF_pllpack
|
|
--
|
|
-- Description : Used by altpll model to calculate required advanced parameters
|
|
-- for PLL simulation. Also has functions to do string->integer,
|
|
-- integer->string conversions.
|
|
--
|
|
-- END PACKAGE HEADER ----------------------------------------------------------
|
|
|
|
-- PACKAGE DECLARATION
|
|
package MF_pllpack is
|
|
|
|
-- FUNCTION DECLARATION
|
|
function int2str (value : integer)
|
|
return string;
|
|
function alt_conv_integer(arg : in std_logic_vector) return integer;
|
|
|
|
|
|
procedure find_simple_integer_fraction( numerator : in integer;
|
|
denominator : in integer;
|
|
max_denom : in integer;
|
|
fraction_num : out integer;
|
|
fraction_div : out integer);
|
|
|
|
procedure find_m_and_n_4_manual_phase ( inclock_period : in integer;
|
|
vco_phase_shift_step : in integer;
|
|
clk0_mult: in integer; clk1_mult: in integer;
|
|
clk2_mult: in integer; clk3_mult: in integer;
|
|
clk4_mult: in integer; clk5_mult: in integer;
|
|
clk6_mult: in integer; clk7_mult: in integer;
|
|
clk8_mult: in integer; clk9_mult: in integer;
|
|
clk0_div : in integer; clk1_div : in integer;
|
|
clk2_div : in integer; clk3_div : in integer;
|
|
clk4_div : in integer; clk5_div : in integer;
|
|
clk6_div : in integer; clk7_div : in integer;
|
|
clk8_div : in integer; clk9_div : in integer;
|
|
clk0_used : in string; clk1_used : in string;
|
|
clk2_used : in string; clk3_used : in string;
|
|
clk4_used : in string; clk5_used : in string;
|
|
clk6_used : in string; clk7_used : in string;
|
|
clk8_used : in string; clk9_used : in string;
|
|
m : out integer;
|
|
n : out integer );
|
|
|
|
function gcd (X: integer; Y: integer) return integer;
|
|
|
|
function count_digit (X: integer) return integer;
|
|
|
|
function scale_num (X: integer; Y: integer) return integer;
|
|
|
|
function lcm (A1: integer; A2: integer; A3: integer; A4: integer;
|
|
A5: integer; A6: integer; A7: integer;
|
|
A8: integer; A9: integer; A10: integer; P: integer) return integer;
|
|
|
|
function output_counter_value (clk_divide: integer; clk_mult : integer ;
|
|
M: integer; N: integer ) return integer;
|
|
|
|
function counter_mode (duty_cycle: integer; output_counter_value: integer) return string;
|
|
|
|
function counter_high (output_counter_value: integer := 1; duty_cycle: integer)
|
|
return integer;
|
|
|
|
function counter_low (output_counter_value: integer; duty_cycle: integer)
|
|
return integer;
|
|
|
|
function mintimedelay (t1: integer; t2: integer; t3: integer; t4: integer;
|
|
t5: integer; t6: integer; t7: integer; t8: integer;
|
|
t9: integer; t10: integer) return integer;
|
|
|
|
function maxnegabs (t1: integer; t2: integer; t3: integer; t4: integer;
|
|
t5: integer; t6: integer; t7: integer; t8: integer;
|
|
t9: integer; t10: integer) return integer;
|
|
|
|
function counter_time_delay ( clk_time_delay: integer;
|
|
m_time_delay: integer; n_time_delay: integer)
|
|
return integer;
|
|
|
|
function get_phase_degree (phase_shift: integer; clk_period: integer) return integer;
|
|
|
|
function counter_initial (tap_phase: integer; m: integer; n: integer)
|
|
return integer;
|
|
|
|
function counter_ph (tap_phase: integer; m : integer; n: integer) return integer;
|
|
|
|
function ph_adjust (tap_phase: integer; ph_base : integer) return integer;
|
|
|
|
function translate_string (mode : string) return string;
|
|
|
|
function str2int (s : string) return integer;
|
|
end MF_pllpack;
|
|
|
|
-- BEGINNING OF PACKAGE
|
|
package body MF_pllpack is
|
|
|
|
-- convert integer to string
|
|
function int2str( value : integer ) return string is
|
|
variable ivalue : integer := 0;
|
|
variable index : integer := 1;
|
|
variable digit : integer := 0;
|
|
variable temp: string(10 downto 1) := "0000000000";
|
|
|
|
begin
|
|
ivalue := value;
|
|
index := 1;
|
|
|
|
while (ivalue > 0) loop
|
|
digit := ivalue mod 10;
|
|
ivalue := ivalue/10;
|
|
|
|
case digit is
|
|
when 0 => temp(index) := '0';
|
|
when 1 => temp(index) := '1';
|
|
when 2 => temp(index) := '2';
|
|
when 3 => temp(index) := '3';
|
|
when 4 => temp(index) := '4';
|
|
when 5 => temp(index) := '5';
|
|
when 6 => temp(index) := '6';
|
|
when 7 => temp(index) := '7';
|
|
when 8 => temp(index) := '8';
|
|
when 9 => temp(index) := '9';
|
|
when others => ASSERT FALSE
|
|
REPORT "Illegal number!"
|
|
SEVERITY ERROR;
|
|
end case;
|
|
|
|
index := index + 1;
|
|
end loop;
|
|
|
|
if (value < 0) then
|
|
return ('-'& temp(index downto 1));
|
|
else
|
|
return temp(index downto 1);
|
|
end if;
|
|
|
|
end int2str;
|
|
|
|
function alt_conv_integer(arg : in std_logic_vector) return integer is
|
|
variable result : integer;
|
|
begin
|
|
result := 0;
|
|
for i in arg'range loop
|
|
if arg(i) = '1' then
|
|
result := result + 2**i;
|
|
end if;
|
|
end loop;
|
|
return result;
|
|
end alt_conv_integer;
|
|
|
|
|
|
-- finds the closest integer fraction of a given pair of numerator and denominator.
|
|
procedure find_simple_integer_fraction( numerator : in integer;
|
|
denominator : in integer;
|
|
max_denom : in integer;
|
|
fraction_num : out integer;
|
|
fraction_div : out integer) is
|
|
constant MAX_ITER : integer := 20;
|
|
type INT_ARRAY is array ((MAX_ITER-1) downto 0) of integer;
|
|
|
|
variable quotient_array : INT_ARRAY;
|
|
variable int_loop_iter : integer;
|
|
variable int_quot : integer;
|
|
variable m_value : integer;
|
|
variable d_value : integer;
|
|
variable old_m_value : integer;
|
|
variable swap : integer;
|
|
variable loop_iter : integer;
|
|
variable num : integer;
|
|
variable den : integer;
|
|
variable i_max_iter : integer;
|
|
|
|
begin
|
|
loop_iter := 0;
|
|
|
|
if (numerator = 0) then
|
|
num := 1;
|
|
else
|
|
num := numerator;
|
|
end if;
|
|
|
|
if (denominator = 0) then
|
|
den := 1;
|
|
else
|
|
den := denominator;
|
|
end if;
|
|
|
|
i_max_iter := max_iter;
|
|
|
|
while (loop_iter < i_max_iter) loop
|
|
int_quot := num / den;
|
|
quotient_array(loop_iter) := int_quot;
|
|
num := num - (den*int_quot);
|
|
loop_iter := loop_iter+1;
|
|
|
|
if ((num = 0) or (max_denom /= -1) or (loop_iter = i_max_iter)) then
|
|
-- calculate the numerator and denominator if there is a restriction on the
|
|
-- max denom value or if the loop is ending
|
|
m_value := 0;
|
|
d_value := 1;
|
|
-- get the rounded value at this stage for the remaining fraction
|
|
if (den /= 0) then
|
|
m_value := (2*num/den);
|
|
end if;
|
|
-- calculate the fraction numerator and denominator at this stage
|
|
for int_loop_iter in (loop_iter-1) downto 0 loop
|
|
if (m_value = 0) then
|
|
m_value := quotient_array(int_loop_iter);
|
|
d_value := 1;
|
|
else
|
|
old_m_value := m_value;
|
|
m_value := (quotient_array(int_loop_iter)*m_value) + d_value;
|
|
d_value := old_m_value;
|
|
end if;
|
|
end loop;
|
|
-- if the denominator is less than the maximum denom_value or if there is no restriction save it
|
|
if ((d_value <= max_denom) or (max_denom = -1)) then
|
|
if ((m_value = 0) or (d_value = 0)) then
|
|
fraction_num := numerator;
|
|
fraction_div := denominator;
|
|
else
|
|
fraction_num := m_value;
|
|
fraction_div := d_value;
|
|
end if;
|
|
end if;
|
|
-- end the loop if the denomitor has overflown or the numerator is zero (no remainder during this round)
|
|
if (((d_value > max_denom) and (max_denom /= -1)) or (num = 0)) then
|
|
i_max_iter := loop_iter;
|
|
end if;
|
|
end if;
|
|
-- swap the numerator and denominator for the next round
|
|
swap := den;
|
|
den := num;
|
|
num := swap;
|
|
end loop;
|
|
end find_simple_integer_fraction;
|
|
|
|
-- find the M and N values for Manual phase based on the following 5 criterias:
|
|
-- 1. The PFD frequency (i.e. Fin / N) must be in the range 5 MHz to 720 MHz
|
|
-- 2. The VCO frequency (i.e. Fin * M / N) must be in the range 300 MHz to 1300 MHz
|
|
-- 3. M is less than 512
|
|
-- 4. N is less than 512
|
|
-- 5. It's the smallest M/N which satisfies all the above constraints, and is within 2ps
|
|
-- of the desired vco-phase-shift-step
|
|
procedure find_m_and_n_4_manual_phase ( inclock_period : in integer;
|
|
vco_phase_shift_step : in integer;
|
|
clk0_mult: in integer; clk1_mult: in integer;
|
|
clk2_mult: in integer; clk3_mult: in integer;
|
|
clk4_mult: in integer; clk5_mult: in integer;
|
|
clk6_mult: in integer; clk7_mult: in integer;
|
|
clk8_mult: in integer; clk9_mult: in integer;
|
|
clk0_div : in integer; clk1_div : in integer;
|
|
clk2_div : in integer; clk3_div : in integer;
|
|
clk4_div : in integer; clk5_div : in integer;
|
|
clk6_div : in integer; clk7_div : in integer;
|
|
clk8_div : in integer; clk9_div : in integer;
|
|
clk0_used : in string; clk1_used : in string;
|
|
clk2_used : in string; clk3_used : in string;
|
|
clk4_used : in string; clk5_used : in string;
|
|
clk6_used : in string; clk7_used : in string;
|
|
clk8_used : in string; clk9_used : in string;
|
|
m : out integer;
|
|
n : out integer ) is
|
|
constant MAX_M : integer := 511;
|
|
constant MAX_N : integer := 511;
|
|
constant MAX_PFD : integer := 720;
|
|
constant MIN_PFD : integer := 5;
|
|
constant MAX_VCO : integer := 1600; -- max vco frequency. (in mHz)
|
|
constant MIN_VCO : integer := 300; -- min vco frequency. (in mHz)
|
|
constant MAX_OFFSET : real := 0.004;
|
|
|
|
variable vco_period : integer;
|
|
variable pfd_freq : integer;
|
|
variable vco_freq : integer;
|
|
variable vco_ps_step_value : integer;
|
|
|
|
variable i_m : integer;
|
|
variable i_n : integer;
|
|
|
|
variable i_pre_m : integer;
|
|
variable i_pre_n : integer;
|
|
|
|
variable closest_vco_step_value : integer;
|
|
|
|
variable i_max_iter : integer;
|
|
variable loop_iter : integer;
|
|
|
|
variable clk0_div_factor_real : real;
|
|
variable clk1_div_factor_real : real;
|
|
variable clk2_div_factor_real : real;
|
|
variable clk3_div_factor_real : real;
|
|
variable clk4_div_factor_real : real;
|
|
variable clk5_div_factor_real : real;
|
|
variable clk6_div_factor_real : real;
|
|
variable clk7_div_factor_real : real;
|
|
variable clk8_div_factor_real : real;
|
|
variable clk9_div_factor_real : real;
|
|
variable clk0_div_factor_int : integer;
|
|
variable clk1_div_factor_int : integer;
|
|
variable clk2_div_factor_int : integer;
|
|
variable clk3_div_factor_int : integer;
|
|
variable clk4_div_factor_int : integer;
|
|
variable clk5_div_factor_int : integer;
|
|
variable clk6_div_factor_int : integer;
|
|
variable clk7_div_factor_int : integer;
|
|
variable clk8_div_factor_int : integer;
|
|
variable clk9_div_factor_int : integer;
|
|
begin
|
|
vco_period := vco_phase_shift_step * 8;
|
|
i_pre_m := 0;
|
|
i_pre_n := 0;
|
|
closest_vco_step_value := 0;
|
|
|
|
LOOP_1 : for i_n_out in 1 to MAX_N loop
|
|
for i_m_out in 1 to MAX_M loop
|
|
|
|
clk0_div_factor_real := real(clk0_div * i_m_out) / real(clk0_mult * i_n_out);
|
|
clk1_div_factor_real := real(clk1_div * i_m_out) / real(clk1_mult * i_n_out);
|
|
clk2_div_factor_real := real(clk2_div * i_m_out) / real(clk2_mult * i_n_out);
|
|
clk3_div_factor_real := real(clk3_div * i_m_out) / real(clk3_mult * i_n_out);
|
|
clk4_div_factor_real := real(clk4_div * i_m_out) / real(clk4_mult * i_n_out);
|
|
clk5_div_factor_real := real(clk5_div * i_m_out) / real(clk5_mult * i_n_out);
|
|
clk6_div_factor_real := real(clk6_div * i_m_out) / real(clk6_mult * i_n_out);
|
|
clk7_div_factor_real := real(clk7_div * i_m_out) / real(clk7_mult * i_n_out);
|
|
clk8_div_factor_real := real(clk8_div * i_m_out) / real(clk8_mult * i_n_out);
|
|
clk9_div_factor_real := real(clk9_div * i_m_out) / real(clk9_mult * i_n_out);
|
|
|
|
clk0_div_factor_int := integer(clk0_div_factor_real);
|
|
clk1_div_factor_int := integer(clk1_div_factor_real);
|
|
clk2_div_factor_int := integer(clk2_div_factor_real);
|
|
clk3_div_factor_int := integer(clk3_div_factor_real);
|
|
clk4_div_factor_int := integer(clk4_div_factor_real);
|
|
clk5_div_factor_int := integer(clk5_div_factor_real);
|
|
clk6_div_factor_int := integer(clk6_div_factor_real);
|
|
clk7_div_factor_int := integer(clk7_div_factor_real);
|
|
clk8_div_factor_int := integer(clk8_div_factor_real);
|
|
clk9_div_factor_int := integer(clk9_div_factor_real);
|
|
|
|
if (((abs(clk0_div_factor_real - real(clk0_div_factor_int)) < MAX_OFFSET) or (clk0_used = "unused")) and
|
|
((abs(clk1_div_factor_real - real(clk1_div_factor_int)) < MAX_OFFSET) or (clk1_used = "unused")) and
|
|
((abs(clk2_div_factor_real - real(clk2_div_factor_int)) < MAX_OFFSET) or (clk2_used = "unused")) and
|
|
((abs(clk3_div_factor_real - real(clk3_div_factor_int)) < MAX_OFFSET) or (clk3_used = "unused")) and
|
|
((abs(clk4_div_factor_real - real(clk4_div_factor_int)) < MAX_OFFSET) or (clk4_used = "unused")) and
|
|
((abs(clk5_div_factor_real - real(clk5_div_factor_int)) < MAX_OFFSET) or (clk5_used = "unused")) and
|
|
((abs(clk6_div_factor_real - real(clk6_div_factor_int)) < MAX_OFFSET) or (clk6_used = "unused")) and
|
|
((abs(clk7_div_factor_real - real(clk7_div_factor_int)) < MAX_OFFSET) or (clk7_used = "unused")) and
|
|
((abs(clk8_div_factor_real - real(clk8_div_factor_int)) < MAX_OFFSET) or (clk8_used = "unused")) and
|
|
((abs(clk9_div_factor_real - real(clk9_div_factor_int)) < MAX_OFFSET) or (clk9_used = "unused")) )
|
|
then
|
|
if ((i_m_out /= 0) and (i_n_out /= 0))
|
|
then
|
|
pfd_freq := 1000000 / (inclock_period * i_n_out);
|
|
vco_freq := (1000000 * i_m_out) / (inclock_period * i_n_out);
|
|
vco_ps_step_value := (inclock_period * i_n_out) / (8 * i_m_out);
|
|
|
|
if ( (i_m_out < max_m) and (i_n_out < max_n) and (pfd_freq >= min_pfd) and (pfd_freq <= max_pfd) and
|
|
(vco_freq >= min_vco) and (vco_freq <= max_vco) )
|
|
then
|
|
if (abs(vco_ps_step_value - vco_phase_shift_step) <= 2)
|
|
then
|
|
i_pre_m := i_m_out;
|
|
i_pre_n := i_n_out;
|
|
exit LOOP_1;
|
|
else
|
|
if ((closest_vco_step_value = 0) or (abs(vco_ps_step_value - vco_phase_shift_step) < abs(closest_vco_step_value - vco_phase_shift_step)))
|
|
then
|
|
i_pre_m := i_m_out;
|
|
i_pre_n := i_n_out;
|
|
closest_vco_step_value := vco_ps_step_value;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
|
|
if ((i_pre_m /= 0) and (i_pre_n /= 0))
|
|
then
|
|
find_simple_integer_fraction(i_pre_m, i_pre_n,
|
|
MAX_N, m, n);
|
|
else
|
|
n := 1;
|
|
m := lcm (clk0_mult, clk1_mult, clk2_mult, clk3_mult,
|
|
clk4_mult, clk5_mult, clk6_mult,
|
|
clk7_mult, clk8_mult, clk9_mult, inclock_period);
|
|
end if;
|
|
end find_m_and_n_4_manual_phase;
|
|
|
|
-- find the greatest common denominator of X and Y
|
|
function gcd (X: integer; Y: integer) return integer is
|
|
variable L, S, R, G : integer := 1;
|
|
begin
|
|
if (X < Y) then -- find which is smaller.
|
|
S := X;
|
|
L := Y;
|
|
else
|
|
S := Y;
|
|
L := X;
|
|
end if;
|
|
|
|
R := S;
|
|
while ( R > 1) loop
|
|
S := L;
|
|
L := R;
|
|
R := S rem L; -- divide bigger number by smaller.
|
|
-- remainder becomes smaller number.
|
|
end loop;
|
|
if (R = 0) then -- if evenly divisible then L is gcd else it is 1.
|
|
G := L;
|
|
else
|
|
G := R;
|
|
end if;
|
|
|
|
return G;
|
|
end gcd;
|
|
|
|
-- count the number of digits in the given integer
|
|
function count_digit (X: integer)
|
|
return integer is
|
|
variable count, result: integer := 0;
|
|
begin
|
|
result := X;
|
|
while (result /= 0) loop
|
|
result := (result / 10);
|
|
count := count + 1;
|
|
end loop;
|
|
|
|
return count;
|
|
end count_digit;
|
|
|
|
-- reduce the given huge number to Y significant digits
|
|
function scale_num (X: integer; Y: integer)
|
|
return integer is
|
|
variable count : integer := 0;
|
|
variable lc, fac_ten, result: integer := 1;
|
|
begin
|
|
count := count_digit(X);
|
|
|
|
for lc in 1 to (count-Y) loop
|
|
fac_ten := fac_ten * 10;
|
|
end loop;
|
|
|
|
result := (X / fac_ten);
|
|
|
|
return result;
|
|
end scale_num;
|
|
|
|
-- find the least common multiple of A1 to A10
|
|
function lcm (A1: integer; A2: integer; A3: integer; A4: integer;
|
|
A5: integer; A6: integer; A7: integer;
|
|
A8: integer; A9: integer; A10: integer; P: integer)
|
|
return integer is
|
|
variable M1, M2, M3, M4, M5 , M6, M7, M8, M9, R: integer := 1;
|
|
begin
|
|
M1 := (A1 * A2)/gcd(A1, A2);
|
|
M2 := (M1 * A3)/gcd(M1, A3);
|
|
M3 := (M2 * A4)/gcd(M2, A4);
|
|
M4 := (M3 * A5)/gcd(M3, A5);
|
|
M5 := (M4 * A6)/gcd(M4, A6);
|
|
M6 := (M5 * A7)/gcd(M5, A7);
|
|
M7 := (M6 * A8)/gcd(M6, A8);
|
|
M8 := (M7 * A9)/gcd(M7, A9);
|
|
M9 := (M8 * A10)/gcd(M8, A10);
|
|
if (M9 < 3) then
|
|
R := 10;
|
|
elsif (M9 = 3) then
|
|
R := 9;
|
|
elsif ((M9 <= 10) and (M9 > 3)) then
|
|
R := 4 * M9;
|
|
elsif (M9 > 1000) then
|
|
R := scale_num(M9,3);
|
|
else
|
|
R := M9 ;
|
|
end if;
|
|
|
|
return R;
|
|
end lcm;
|
|
|
|
-- find the factor of division of the output clock frequency compared to the VCO
|
|
function output_counter_value (clk_divide: integer; clk_mult: integer ;
|
|
M: integer; N: integer ) return integer is
|
|
variable r_real : real := 1.0;
|
|
variable r: integer := 1;
|
|
begin
|
|
r_real := real(clk_divide * M)/ real(clk_mult * N);
|
|
r := integer(r_real);
|
|
|
|
return R;
|
|
end output_counter_value;
|
|
|
|
-- find the mode of each PLL counter - bypass, even or odd
|
|
function counter_mode (duty_cycle: integer; output_counter_value: integer)
|
|
return string is
|
|
variable R: string (1 to 6) := " ";
|
|
variable counter_value: integer := 1;
|
|
begin
|
|
counter_value := (2*duty_cycle*output_counter_value)/100;
|
|
if output_counter_value = 1 then
|
|
R := "bypass";
|
|
elsif (counter_value REM 2) = 0 then
|
|
R := " even";
|
|
else
|
|
R := " odd";
|
|
end if;
|
|
|
|
return R;
|
|
end counter_mode;
|
|
|
|
-- find the number of VCO clock cycles to hold the output clock high
|
|
function counter_high (output_counter_value: integer := 1; duty_cycle: integer)
|
|
return integer is
|
|
variable R: integer := 1;
|
|
variable half_cycle_high : integer := 1;
|
|
begin
|
|
half_cycle_high := (duty_cycle * output_counter_value *2)/100 ;
|
|
if (half_cycle_high REM 2 = 0) then
|
|
R := half_cycle_high/2 ;
|
|
else
|
|
R := (half_cycle_high/2) + 1;
|
|
end if;
|
|
|
|
return R;
|
|
end;
|
|
|
|
-- find the number of VCO clock cycles to hold the output clock low
|
|
function counter_low (output_counter_value: integer; duty_cycle: integer)
|
|
return integer is
|
|
variable R, R1: integer := 1;
|
|
variable half_cycle_high : integer := 1;
|
|
begin
|
|
half_cycle_high := (duty_cycle * output_counter_value*2)/100 ;
|
|
if (half_cycle_high REM 2 = 0) then
|
|
R1 := half_cycle_high/2 ;
|
|
else
|
|
R1 := (half_cycle_high/2) + 1;
|
|
end if;
|
|
|
|
R := output_counter_value - R1;
|
|
|
|
if (R = 0) then
|
|
R := 1;
|
|
end if;
|
|
|
|
return R;
|
|
end;
|
|
|
|
-- find the smallest time delay amongst t1 to t10
|
|
function mintimedelay (t1: integer; t2: integer; t3: integer; t4: integer;
|
|
t5: integer; t6: integer; t7: integer; t8: integer;
|
|
t9: integer; t10: integer) return integer is
|
|
variable m1,m2,m3,m4,m5,m6,m7,m8,m9 : integer := 0;
|
|
begin
|
|
if (t1 < t2) then m1 := t1; else m1 := t2; end if;
|
|
if (m1 < t3) then m2 := m1; else m2 := t3; end if;
|
|
if (m2 < t4) then m3 := m2; else m3 := t4; end if;
|
|
if (m3 < t5) then m4 := m3; else m4 := t5; end if;
|
|
if (m4 < t6) then m5 := m4; else m5 := t6; end if;
|
|
if (m5 < t7) then m6 := m5; else m6 := t7; end if;
|
|
if (m6 < t8) then m7 := m6; else m7 := t8; end if;
|
|
if (m7 < t9) then m8 := m7; else m8 := t9; end if;
|
|
if (m8 < t10) then m9 := m8; else m9 := t10; end if;
|
|
if (m9 > 0) then return m9; else return 0; end if;
|
|
end;
|
|
|
|
-- find the numerically largest negative number, and return its absolute value
|
|
function maxnegabs (t1: integer; t2: integer; t3: integer; t4: integer;
|
|
t5: integer; t6: integer; t7: integer; t8: integer;
|
|
t9: integer; t10: integer) return integer is
|
|
variable m1,m2,m3,m4,m5,m6,m7,m8,m9 : integer := 0;
|
|
begin
|
|
if (t1 < t2) then m1 := t1; else m1 := t2; end if;
|
|
if (m1 < t3) then m2 := m1; else m2 := t3; end if;
|
|
if (m2 < t4) then m3 := m2; else m3 := t4; end if;
|
|
if (m3 < t5) then m4 := m3; else m4 := t5; end if;
|
|
if (m4 < t6) then m5 := m4; else m5 := t6; end if;
|
|
if (m5 < t7) then m6 := m5; else m6 := t7; end if;
|
|
if (m6 < t8) then m7 := m6; else m7 := t8; end if;
|
|
if (m7 < t9) then m8 := m7; else m8 := t9; end if;
|
|
if (m8 < t10) then m9 := m8; else m9 := t10; end if;
|
|
if (m9 < 0) then return (0 - m9); else return 0; end if;
|
|
end;
|
|
|
|
-- adjust the phase (tap_phase) with the largest negative number (ph_base)
|
|
function ph_adjust (tap_phase: integer; ph_base : integer) return integer is
|
|
begin
|
|
return (tap_phase + ph_base);
|
|
end;
|
|
|
|
-- find the time delay for each PLL counter
|
|
function counter_time_delay (clk_time_delay: integer;
|
|
m_time_delay: integer; n_time_delay: integer)
|
|
return integer is
|
|
variable R: integer := 0;
|
|
begin
|
|
R := clk_time_delay + m_time_delay - n_time_delay;
|
|
|
|
return R;
|
|
end;
|
|
|
|
-- calculate the given phase shift (in ps) in terms of degrees
|
|
function get_phase_degree (phase_shift: integer; clk_period: integer)
|
|
return integer is
|
|
variable result: integer := 0;
|
|
begin
|
|
result := ( phase_shift * 360 ) / clk_period;
|
|
-- to round up the calculation result
|
|
if (result > 0) then
|
|
result := result + 1;
|
|
elsif (result < 0) then
|
|
result := result - 1;
|
|
else
|
|
result := 0;
|
|
end if;
|
|
|
|
return result;
|
|
end;
|
|
|
|
-- find the number of VCO clock cycles to wait initially before the first rising
|
|
-- edge of the output clock
|
|
function counter_initial (tap_phase: integer; m: integer; n: integer)
|
|
return integer is
|
|
variable R: integer;
|
|
variable R1: real;
|
|
begin
|
|
R1 := (real(abs(tap_phase)) * real(m))/(360.0 * real(n)) + 0.6;
|
|
-- Note NCSim VHDL had problem in rounding up for 0.5 - 0.99.
|
|
-- This checking will ensure that the rounding up is done.
|
|
if (R1 >= 0.5) and (R1 <= 1.0) then
|
|
R1 := 1.0;
|
|
end if;
|
|
|
|
R := integer(R1);
|
|
|
|
return R;
|
|
end;
|
|
|
|
-- find which VCO phase tap (0 to 7) to align the rising edge of the output clock to
|
|
function counter_ph (tap_phase: integer; m: integer; n: integer) return integer is
|
|
variable R: integer := 0;
|
|
begin
|
|
-- 0.5 is added for proper rounding of the tap_phase.
|
|
R := integer(real(integer(real(tap_phase * m / n)+ 0.5) REM 360)/45.0) rem 8;
|
|
|
|
return R;
|
|
end;
|
|
|
|
-- convert given string to length 6 by padding with spaces
|
|
function translate_string (mode : string) return string is
|
|
variable new_mode : string (1 to 6) := " ";
|
|
begin
|
|
if (mode = "bypass") then
|
|
new_mode := "bypass";
|
|
elsif (mode = "even") then
|
|
new_mode := " even";
|
|
elsif (mode = "odd") then
|
|
new_mode := " odd";
|
|
end if;
|
|
|
|
return new_mode;
|
|
end;
|
|
|
|
function str2int (s : string) return integer is
|
|
variable len : integer := s'length;
|
|
variable newdigit : integer := 0;
|
|
variable sign : integer := 1;
|
|
variable digit : integer := 0;
|
|
begin
|
|
for i in 1 to len loop
|
|
case s(i) is
|
|
when '-' =>
|
|
if i = 1 then
|
|
sign := -1;
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "Illegal Character "& s(i) & "i n string parameter! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
when '0' =>
|
|
digit := 0;
|
|
when '1' =>
|
|
digit := 1;
|
|
when '2' =>
|
|
digit := 2;
|
|
when '3' =>
|
|
digit := 3;
|
|
when '4' =>
|
|
digit := 4;
|
|
when '5' =>
|
|
digit := 5;
|
|
when '6' =>
|
|
digit := 6;
|
|
when '7' =>
|
|
digit := 7;
|
|
when '8' =>
|
|
digit := 8;
|
|
when '9' =>
|
|
digit := 9;
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Illegal Character "& s(i) & "in string parameter! "
|
|
SEVERITY ERROR;
|
|
end case;
|
|
newdigit := newdigit * 10 + digit;
|
|
end loop;
|
|
|
|
return (sign*newdigit);
|
|
end;
|
|
end MF_pllpack;
|
|
-- END OF PACKAGE MF_pllpack
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
-- DFFP
|
|
entity DFFP is
|
|
port(
|
|
clk : in std_logic;
|
|
ena : in std_logic := '1';
|
|
d : in std_logic;
|
|
clrn : in std_logic := '1';
|
|
prn : in std_logic := '1';
|
|
q : out std_logic := '0'
|
|
);
|
|
end DFFP;
|
|
architecture behave of DFFP is
|
|
begin
|
|
process (clk, prn, clrn)
|
|
begin
|
|
if (prn = '0') then
|
|
q <= '1';
|
|
elsif (clrn = '0') then
|
|
q <= '0';
|
|
else
|
|
if (ena = '1') then
|
|
q <= d;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end behave;
|
|
|
|
Library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
entity pll_iobuf is
|
|
port(
|
|
i : in std_logic;
|
|
oe : in std_logic;
|
|
io : inout std_logic;
|
|
o : out std_logic);
|
|
end pll_iobuf;
|
|
architecture BEHAVIOR of pll_iobuf is
|
|
begin
|
|
process(i, io, oe)
|
|
begin
|
|
if oe = '1' then
|
|
io <= i;
|
|
else
|
|
io <= 'Z';
|
|
end if;
|
|
o <= io;
|
|
end process;
|
|
end BEHAVIOR;
|
|
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_m_cntr
|
|
--
|
|
-- Description : Simulation model for the M counter. This is a
|
|
-- model for the loop feedback counter of the Stratix PLL.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
|
|
ENTITY MF_m_cntr is
|
|
PORT ( clk : IN std_logic;
|
|
reset : IN std_logic;
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer;
|
|
modulus : IN integer;
|
|
time_delay : IN integer;
|
|
ph : IN integer := 0);
|
|
END MF_m_cntr;
|
|
|
|
ARCHITECTURE behave of MF_m_cntr is
|
|
begin
|
|
|
|
process (clk, reset)
|
|
variable count : integer := 1;
|
|
variable first_rising_edge : boolean := true;
|
|
variable tmp_cout : std_logic;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := true;
|
|
elsif (clk'event) then
|
|
if (clk = '1' and first_rising_edge) then
|
|
first_rising_edge := false;
|
|
tmp_cout := clk;
|
|
elsif (not first_rising_edge) then
|
|
if (count < modulus) then
|
|
count := count + 1;
|
|
else
|
|
count := 1;
|
|
tmp_cout := not tmp_cout;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout after time_delay * 1 ps;
|
|
end process;
|
|
end behave;
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_n_cntr
|
|
--
|
|
-- Description : Simulation model for the N counter. This is a
|
|
-- model for the input counter of the Stratix PLL.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
|
|
ENTITY MF_n_cntr is
|
|
PORT ( clk : IN std_logic;
|
|
reset : IN std_logic;
|
|
cout : OUT std_logic;
|
|
modulus : IN integer;
|
|
time_delay : IN integer);
|
|
END MF_n_cntr;
|
|
|
|
ARCHITECTURE behave of MF_n_cntr is
|
|
begin
|
|
|
|
process (clk, reset)
|
|
variable count : integer := 1;
|
|
variable first_rising_edge : boolean := true;
|
|
variable tmp_cout : std_logic;
|
|
variable clk_last_valid_value : std_logic;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := true;
|
|
elsif (clk'event) then
|
|
if (clk = 'X') then
|
|
ASSERT FALSE REPORT "Invalid transition to 'X' detected on Stratix PLL input clk. This edge will be ignored" severity warning;
|
|
elsif (clk = '1' and first_rising_edge) then
|
|
first_rising_edge := false;
|
|
tmp_cout := clk;
|
|
elsif (not first_rising_edge and (clk_last_valid_value /= clk)) then
|
|
if (count < modulus) then
|
|
count := count + 1;
|
|
else
|
|
count := 1;
|
|
tmp_cout := not tmp_cout;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (clk /= 'X') then
|
|
clk_last_valid_value := clk;
|
|
end if;
|
|
cout <= transport tmp_cout after time_delay * 1 ps;
|
|
end process;
|
|
end behave;
|
|
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : stx_scale_cntr
|
|
--
|
|
-- Description : Simulation model for the output scale-down counters.
|
|
-- This is a common model for the L0, L1, G0, G1, G2, G3, E0,
|
|
-- E1, E2 and E3 output counters of the Stratix PLL.
|
|
--
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
|
|
ENTITY stx_scale_cntr is
|
|
PORT ( clk : IN std_logic;
|
|
reset : IN std_logic;
|
|
initial : IN integer;
|
|
high : IN integer;
|
|
low : IN integer;
|
|
mode : IN string := "bypass";
|
|
time_delay : IN integer;
|
|
ph_tap : IN natural;
|
|
cout : OUT std_logic);
|
|
END stx_scale_cntr;
|
|
|
|
ARCHITECTURE behave of stx_scale_cntr is
|
|
begin
|
|
process (clk, reset)
|
|
variable tmp_cout : std_logic := '0';
|
|
variable count : integer := 1;
|
|
variable output_shift_count : integer := 0;
|
|
variable first_rising_edge : boolean := false;
|
|
variable high_reg : integer := 0;
|
|
variable low_reg : integer := 0;
|
|
variable init : boolean := true;
|
|
variable high_cnt_xfer_done : boolean := false;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
output_shift_count := 0;
|
|
tmp_cout := '0';
|
|
first_rising_edge := false;
|
|
elsif (clk'event) then
|
|
if (init) then
|
|
init := false;
|
|
high_reg := high;
|
|
low_reg := low;
|
|
end if;
|
|
if (mode = " off") then
|
|
tmp_cout := '0';
|
|
elsif (mode = "bypass") then
|
|
tmp_cout := clk;
|
|
elsif (not first_rising_edge) then
|
|
if (clk = '1') then
|
|
output_shift_count := output_shift_count + 1;
|
|
if (output_shift_count = initial) then
|
|
tmp_cout := clk;
|
|
first_rising_edge := true;
|
|
end if;
|
|
end if;
|
|
elsif (output_shift_count < initial) then
|
|
if (clk = '1') then
|
|
output_shift_count := output_shift_count + 1;
|
|
end if;
|
|
else
|
|
count := count + 1;
|
|
if (mode = " even" and (count = (high_reg*2) + 1)) then
|
|
tmp_cout := '0';
|
|
if (high_cnt_xfer_done) then
|
|
low_reg := low;
|
|
high_cnt_xfer_done := false;
|
|
end if;
|
|
elsif (mode = " odd" and (count = high_reg*2)) then
|
|
tmp_cout := '0';
|
|
if (high_cnt_xfer_done) then
|
|
low_reg := low;
|
|
high_cnt_xfer_done := false;
|
|
end if;
|
|
elsif (count = (high_reg + low_reg)*2 + 1) then
|
|
tmp_cout := '1';
|
|
count := 1; -- reset count
|
|
if (high_reg /= high) then
|
|
high_cnt_xfer_done := true;
|
|
high_reg := high;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout after time_delay * 1 ps;
|
|
end process;
|
|
|
|
end behave;
|
|
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_pll_reg
|
|
--
|
|
-- Description : Simulation model for a simple DFF.
|
|
-- This is required for the generation of the bit slip-signals.
|
|
-- No timing, powers upto 0.
|
|
--
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
|
|
ENTITY MF_pll_reg is
|
|
PORT ( clk : in std_logic;
|
|
ena : in std_logic := '1';
|
|
d : in std_logic;
|
|
clrn : in std_logic := '1';
|
|
prn : in std_logic := '1';
|
|
q : out std_logic);
|
|
end MF_pll_reg;
|
|
|
|
ARCHITECTURE behave of MF_pll_reg is
|
|
begin
|
|
process (clk, prn, clrn)
|
|
variable q_reg : std_logic := '0';
|
|
begin
|
|
if (prn = '0') then
|
|
q_reg := '1';
|
|
elsif (clrn = '0') then
|
|
q_reg := '0';
|
|
elsif (clk'event and clk = '1' and (ena = '1')) then
|
|
q_reg := D;
|
|
end if;
|
|
|
|
Q <= q_reg;
|
|
end process;
|
|
end behave;
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_stratix_pll
|
|
--
|
|
-- Description : The behavioral model for Stratix PLL
|
|
--
|
|
-- Limitations : Applies to the Stratix and Stratix GX device families
|
|
-- No support for spread spectrum feature in the model
|
|
--
|
|
-- Outputs : Up to 10 output clocks, each defined by its own set of
|
|
-- parameters. Locked output (active high) indicates when the
|
|
-- PLL locks. clkbad, clkloss and activeclock are used for
|
|
-- clock switchover to indicate which input clock has gone
|
|
-- bad, when the clock switchover initiates and which input
|
|
-- clock is being used as the reference, respectively.
|
|
-- scandataout is the data output of the serial scan chain.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
USE STD.TEXTIO.all;
|
|
USE work.MF_pllpack.all;
|
|
USE work.MF_m_cntr;
|
|
USE work.MF_n_cntr;
|
|
USE work.stx_scale_cntr;
|
|
USE work.dffp;
|
|
USE work.MF_pll_reg;
|
|
|
|
ENTITY MF_stratix_pll is
|
|
GENERIC ( operation_mode : string := "normal";
|
|
qualify_conf_done : string := "off";
|
|
compensate_clock : string := "clk0";
|
|
pll_type : string := "auto"; -- EGPP/FAST/AUTO
|
|
scan_chain : string := "long";
|
|
|
|
clk0_multiply_by : integer := 1;
|
|
clk0_divide_by : integer := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk0_time_delay : string := "0";
|
|
clk0_duty_cycle : integer := 50;
|
|
|
|
clk1_multiply_by : integer := 1;
|
|
clk1_divide_by : integer := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_time_delay : string := "0";
|
|
clk1_duty_cycle : integer := 50;
|
|
|
|
clk2_multiply_by : integer := 1;
|
|
clk2_divide_by : integer := 1;
|
|
clk2_phase_shift : string := "0";
|
|
clk2_time_delay : string := "0";
|
|
clk2_duty_cycle : integer := 50;
|
|
|
|
clk3_multiply_by : integer := 1;
|
|
clk3_divide_by : integer := 1;
|
|
clk3_phase_shift : string := "0";
|
|
clk3_time_delay : string := "0";
|
|
clk3_duty_cycle : integer := 50;
|
|
|
|
clk4_multiply_by : integer := 1;
|
|
clk4_divide_by : integer := 1;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_time_delay : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
|
|
clk5_multiply_by : integer := 1;
|
|
clk5_divide_by : integer := 1;
|
|
clk5_phase_shift : string := "0";
|
|
clk5_time_delay : string := "0";
|
|
clk5_duty_cycle : integer := 50;
|
|
|
|
extclk0_multiply_by : integer := 1;
|
|
extclk0_divide_by : integer := 1;
|
|
extclk0_phase_shift : string := "0";
|
|
extclk0_time_delay : string := "0";
|
|
extclk0_duty_cycle : integer := 50;
|
|
|
|
extclk1_multiply_by : integer := 1;
|
|
extclk1_divide_by : integer := 1;
|
|
extclk1_phase_shift : string := "0";
|
|
extclk1_time_delay : string := "0";
|
|
extclk1_duty_cycle : integer := 50;
|
|
|
|
extclk2_multiply_by : integer := 1;
|
|
extclk2_divide_by : integer := 1;
|
|
extclk2_phase_shift : string := "0";
|
|
extclk2_time_delay : string := "0";
|
|
extclk2_duty_cycle : integer := 50;
|
|
|
|
extclk3_multiply_by : integer := 1;
|
|
extclk3_divide_by : integer := 1;
|
|
extclk3_phase_shift : string := "0";
|
|
extclk3_time_delay : string := "0";
|
|
extclk3_duty_cycle : integer := 50;
|
|
|
|
primary_clock : string := "inclk0";
|
|
inclk0_input_frequency : integer := 10000;
|
|
inclk1_input_frequency : integer := 10000;
|
|
gate_lock_signal : string := "no";
|
|
gate_lock_counter : integer := 1;
|
|
valid_lock_multiplier : integer := 5;
|
|
invalid_lock_multiplier : integer := 5;
|
|
|
|
switch_over_on_lossclk : string := "off";
|
|
switch_over_on_gated_lock : string := "off";
|
|
switch_over_counter : integer := 1;
|
|
enable_switch_over_counter : string := "off";
|
|
feedback_source : string := "extclk0";
|
|
bandwidth_type : string := "auto";
|
|
bandwidth : integer := 0;
|
|
spread_frequency : integer := 0;
|
|
down_spread : string := "0.0";
|
|
|
|
pfd_min : integer := 0;
|
|
pfd_max : integer := 0;
|
|
vco_min : integer := 0;
|
|
vco_max : integer := 0;
|
|
vco_center : integer := 0;
|
|
|
|
-- ADVANCED USER PARAMETERS
|
|
m_initial : integer := 1;
|
|
m : integer := 0;
|
|
n : integer := 1;
|
|
m2 : integer := 1;
|
|
n2 : integer := 1;
|
|
ss : integer := 0;
|
|
|
|
l0_high : integer := 1;
|
|
l0_low : integer := 1;
|
|
l0_initial : integer := 1;
|
|
l0_mode : string := "bypass";
|
|
l0_ph : integer := 0;
|
|
l0_time_delay : integer := 0;
|
|
|
|
l1_high : integer := 1;
|
|
l1_low : integer := 1;
|
|
l1_initial : integer := 1;
|
|
l1_mode : string := "bypass";
|
|
l1_ph : integer := 0;
|
|
l1_time_delay : integer := 0;
|
|
|
|
g0_high : integer := 1;
|
|
g0_low : integer := 1;
|
|
g0_initial : integer := 1;
|
|
g0_mode : string := "bypass";
|
|
g0_ph : integer := 0;
|
|
g0_time_delay : integer := 0;
|
|
|
|
g1_high : integer := 1;
|
|
g1_low : integer := 1;
|
|
g1_initial : integer := 1;
|
|
g1_mode : string := "bypass";
|
|
g1_ph : integer := 0;
|
|
g1_time_delay : integer := 0;
|
|
|
|
g2_high : integer := 1;
|
|
g2_low : integer := 1;
|
|
g2_initial : integer := 1;
|
|
g2_mode : string := "bypass";
|
|
g2_ph : integer := 0;
|
|
g2_time_delay : integer := 0;
|
|
|
|
g3_high : integer := 1;
|
|
g3_low : integer := 1;
|
|
g3_initial : integer := 1;
|
|
g3_mode : string := "bypass";
|
|
g3_ph : integer := 0;
|
|
g3_time_delay : integer := 0;
|
|
|
|
e0_high : integer := 1;
|
|
e0_low : integer := 1;
|
|
e0_initial : integer := 1;
|
|
e0_mode : string := "bypass";
|
|
e0_ph : integer := 0;
|
|
e0_time_delay : integer := 0;
|
|
|
|
e1_high : integer := 1;
|
|
e1_low : integer := 1;
|
|
e1_initial : integer := 1;
|
|
e1_mode : string := "bypass";
|
|
e1_ph : integer := 0;
|
|
e1_time_delay : integer := 0;
|
|
|
|
e2_high : integer := 1;
|
|
e2_low : integer := 1;
|
|
e2_initial : integer := 1;
|
|
e2_mode : string := "bypass";
|
|
e2_ph : integer := 0;
|
|
e2_time_delay : integer := 0;
|
|
|
|
e3_high : integer := 1;
|
|
e3_low : integer := 1;
|
|
e3_initial : integer := 1;
|
|
e3_mode : string := "bypass";
|
|
e3_ph : integer := 0;
|
|
e3_time_delay : integer := 0;
|
|
|
|
m_ph : integer := 0;
|
|
m_time_delay : integer := 0;
|
|
n_time_delay : integer := 0;
|
|
|
|
extclk0_counter : string := "e0";
|
|
extclk1_counter : string := "e1";
|
|
extclk2_counter : string := "e2";
|
|
extclk3_counter : string := "e3";
|
|
|
|
clk0_counter : string := "g0";
|
|
clk1_counter : string := "g1";
|
|
clk2_counter : string := "g2";
|
|
clk3_counter : string := "g3";
|
|
clk4_counter : string := "l0";
|
|
clk5_counter : string := "l1";
|
|
|
|
-- LVDS mode parameters
|
|
enable0_counter : string := "l0";
|
|
enable1_counter : string := "l0";
|
|
|
|
charge_pump_current : integer := 0;
|
|
loop_filter_r : string := "1.0";
|
|
loop_filter_c : integer := 1;
|
|
common_rx_tx : string := "off";
|
|
rx_outclock_resource : string := "auto";
|
|
use_vco_bypass : string := "false";
|
|
use_dc_coupling : string := "false";
|
|
|
|
pll_compensation_delay : integer := 0;
|
|
simulation_type : string := "timing";
|
|
|
|
clk0_use_even_counter_mode : string := "off";
|
|
clk1_use_even_counter_mode : string := "off";
|
|
clk2_use_even_counter_mode : string := "off";
|
|
clk3_use_even_counter_mode : string := "off";
|
|
clk4_use_even_counter_mode : string := "off";
|
|
clk5_use_even_counter_mode : string := "off";
|
|
extclk0_use_even_counter_mode : string := "off";
|
|
extclk1_use_even_counter_mode : string := "off";
|
|
extclk2_use_even_counter_mode : string := "off";
|
|
extclk3_use_even_counter_mode : string := "off";
|
|
|
|
clk0_use_even_counter_value : string := "off";
|
|
clk1_use_even_counter_value : string := "off";
|
|
clk2_use_even_counter_value : string := "off";
|
|
clk3_use_even_counter_value : string := "off";
|
|
clk4_use_even_counter_value : string := "off";
|
|
clk5_use_even_counter_value : string := "off";
|
|
extclk0_use_even_counter_value : string := "off";
|
|
extclk1_use_even_counter_value : string := "off";
|
|
extclk2_use_even_counter_value : string := "off";
|
|
extclk3_use_even_counter_value : string := "off";
|
|
scan_chain_mif_file : string := "";
|
|
|
|
-- Simulation only generics
|
|
family_name : string := "Stratix";
|
|
|
|
skip_vco : string := "off"
|
|
|
|
);
|
|
|
|
PORT ( inclk : in std_logic_vector(1 downto 0);
|
|
fbin : in std_logic := '0';
|
|
ena : in std_logic := '1';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
clkena : in std_logic_vector(5 downto 0) := "111111";
|
|
extclkena : in std_logic_vector(3 downto 0) := "1111";
|
|
scanaclr : in std_logic := '0';
|
|
scandata : in std_logic := '0';
|
|
scanclk : in std_logic := '0';
|
|
clk : out std_logic_vector(5 downto 0);
|
|
extclk : out std_logic_vector(3 downto 0);
|
|
clkbad : out std_logic_vector(1 downto 0);
|
|
activeclock : out std_logic;
|
|
locked : out std_logic;
|
|
clkloss : out std_logic;
|
|
scandataout : out std_logic;
|
|
-- lvds specific ports
|
|
comparator : in std_logic := '0';
|
|
enable0 : out std_logic;
|
|
enable1 : out std_logic
|
|
);
|
|
END MF_stratix_pll;
|
|
|
|
ARCHITECTURE vital_pll of MF_stratix_pll is
|
|
|
|
-- internal advanced parameter signals
|
|
signal i_vco_min : natural;
|
|
signal i_vco_max : natural;
|
|
signal i_vco_center : natural;
|
|
signal i_pfd_min : natural;
|
|
signal i_pfd_max : natural;
|
|
signal l0_ph_val : natural;
|
|
signal l1_ph_val : natural;
|
|
signal g0_ph_val : natural;
|
|
signal g1_ph_val : natural;
|
|
signal g2_ph_val : natural;
|
|
signal g3_ph_val : natural;
|
|
signal e0_ph_val : natural;
|
|
signal e1_ph_val : natural;
|
|
signal e2_ph_val : natural;
|
|
signal e3_ph_val : natural;
|
|
signal i_extclk3_counter : string(1 to 2) := "e3";
|
|
signal i_extclk2_counter : string(1 to 2) := "e2";
|
|
signal i_extclk1_counter : string(1 to 2) := "e1";
|
|
signal i_extclk0_counter : string(1 to 2) := "e0";
|
|
signal i_clk5_counter : string(1 to 2) := "l1";
|
|
signal i_clk4_counter : string(1 to 2) := "l0";
|
|
signal i_clk3_counter : string(1 to 2) := "g3";
|
|
signal i_clk2_counter : string(1 to 2) := "g2";
|
|
signal i_clk1_counter : string(1 to 2) := "g1";
|
|
signal i_clk0_counter : string(1 to 2) := "g0";
|
|
signal i_charge_pump_current : natural;
|
|
signal i_loop_filter_r : natural;
|
|
|
|
-- end internal advanced parameter signals
|
|
|
|
-- CONSTANTS
|
|
CONSTANT EGPP_SCAN_CHAIN : integer := 289;
|
|
CONSTANT GPP_SCAN_CHAIN : integer := 193;
|
|
CONSTANT TRST : time := 5000 ps;
|
|
CONSTANT TRSTCLK : time := 5000 ps;
|
|
|
|
-- signals
|
|
|
|
signal vcc : std_logic := '1';
|
|
|
|
signal fbclk : std_logic;
|
|
signal refclk : std_logic;
|
|
|
|
signal l0_clk : std_logic;
|
|
signal l1_clk : std_logic;
|
|
signal g0_clk : std_logic;
|
|
signal g1_clk : std_logic;
|
|
signal g2_clk : std_logic;
|
|
signal g3_clk : std_logic;
|
|
signal e0_clk : std_logic;
|
|
signal e1_clk : std_logic;
|
|
signal e2_clk : std_logic;
|
|
signal e3_clk : std_logic;
|
|
|
|
signal vco_out : std_logic_vector(7 downto 0) := (OTHERS => '0');
|
|
|
|
-- signals to assign values to counter params
|
|
signal m_val : integer := 1;
|
|
signal m_val_tmp : integer := 1;
|
|
signal m2_val : integer := 1;
|
|
signal n_val : integer := 1;
|
|
signal n_val_tmp : integer := 1;
|
|
signal n2_val : integer := 1;
|
|
signal m_time_delay_val, n_time_delay_val : integer := 0;
|
|
signal m_ph_val : integer := 0;
|
|
signal m_initial_val : integer := m_initial;
|
|
|
|
signal l0_initial_val : integer := l0_initial;
|
|
signal l1_initial_val : integer := l1_initial;
|
|
signal l0_high_val : integer := l0_high;
|
|
signal l1_high_val : integer := l1_high;
|
|
signal l0_low_val : integer := l0_low;
|
|
signal l1_low_val : integer := l1_low;
|
|
signal l0_mode_val : string(1 to 6) := "bypass";
|
|
signal l1_mode_val : string(1 to 6) := "bypass";
|
|
signal l0_time_delay_val : integer := l0_time_delay;
|
|
signal l1_time_delay_val : integer := l1_time_delay;
|
|
|
|
signal g0_initial_val : integer := g0_initial;
|
|
signal g1_initial_val : integer := g1_initial;
|
|
signal g2_initial_val : integer := g2_initial;
|
|
signal g3_initial_val : integer := g3_initial;
|
|
signal g0_high_val : integer := g0_high;
|
|
signal g1_high_val : integer := g1_high;
|
|
signal g2_high_val : integer := g2_high;
|
|
signal g3_high_val : integer := g3_high;
|
|
signal g0_mode_val : string(1 to 6) := "bypass";
|
|
signal g1_mode_val : string(1 to 6) := "bypass";
|
|
signal g2_mode_val : string(1 to 6) := "bypass";
|
|
signal g3_mode_val : string(1 to 6) := "bypass";
|
|
signal g0_low_val : integer := g0_low;
|
|
signal g1_low_val : integer := g1_low;
|
|
signal g2_low_val : integer := g2_low;
|
|
signal g3_low_val : integer := g3_low;
|
|
signal g0_time_delay_val : integer := g0_time_delay;
|
|
signal g1_time_delay_val : integer := g1_time_delay;
|
|
signal g2_time_delay_val : integer := g2_time_delay;
|
|
signal g3_time_delay_val : integer := g3_time_delay;
|
|
|
|
signal e0_initial_val : integer := e0_initial;
|
|
signal e1_initial_val : integer := e1_initial;
|
|
signal e2_initial_val : integer := e2_initial;
|
|
signal e3_initial_val : integer := e3_initial;
|
|
signal e0_high_val : integer := e0_high;
|
|
signal e1_high_val : integer := e1_high;
|
|
signal e2_high_val : integer := e2_high;
|
|
signal e3_high_val : integer := e3_high;
|
|
signal e0_low_val : integer := e0_low;
|
|
signal e1_low_val : integer := e1_low;
|
|
signal e2_low_val : integer := e2_low;
|
|
signal e3_low_val : integer := e3_low;
|
|
signal e0_time_delay_val : integer := e0_time_delay;
|
|
signal e1_time_delay_val : integer := e1_time_delay;
|
|
signal e2_time_delay_val : integer := e2_time_delay;
|
|
signal e3_time_delay_val : integer := e3_time_delay;
|
|
signal e0_mode_val : string(1 to 6) := "bypass";
|
|
signal e1_mode_val : string(1 to 6) := "bypass";
|
|
signal e2_mode_val : string(1 to 6) := "bypass";
|
|
signal e3_mode_val : string(1 to 6) := "bypass";
|
|
|
|
signal m_mode_val : string(1 to 6) := " ";
|
|
signal m2_mode_val : string(1 to 6) := " ";
|
|
signal n_mode_val : string(1 to 6) := " ";
|
|
signal n2_mode_val : string(1 to 6) := " ";
|
|
|
|
signal cntr_e0_initial : integer := 1;
|
|
signal cntr_e1_initial : integer := 1;
|
|
signal cntr_e2_initial : integer := 1;
|
|
signal cntr_e3_initial : integer := 1;
|
|
signal ext_fbk_delay : integer := 0;
|
|
signal cntr_e0_delay : integer := 0;
|
|
signal cntr_e1_delay : integer := 0;
|
|
signal cntr_e2_delay : integer := 0;
|
|
signal cntr_e3_delay : integer := 0;
|
|
|
|
signal transfer : std_logic := '0';
|
|
|
|
signal scan_data : std_logic_vector(288 downto 0) := (OTHERS => '0');
|
|
signal ena0 : std_logic;
|
|
signal ena1 : std_logic;
|
|
signal ena2 : std_logic;
|
|
signal ena3 : std_logic;
|
|
signal ena4 : std_logic;
|
|
signal ena5 : std_logic;
|
|
signal extena0 : std_logic;
|
|
signal extena1 : std_logic;
|
|
signal extena2 : std_logic;
|
|
signal extena3 : std_logic;
|
|
|
|
signal clk0_tmp : std_logic;
|
|
signal clk1_tmp : std_logic;
|
|
signal clk2_tmp : std_logic;
|
|
signal clk3_tmp : std_logic;
|
|
signal clk4_tmp : std_logic;
|
|
signal clk5_tmp : std_logic;
|
|
signal extclk0_tmp : std_logic;
|
|
signal extclk1_tmp : std_logic;
|
|
signal extclk2_tmp : std_logic;
|
|
signal extclk3_tmp : std_logic;
|
|
|
|
signal not_clk0_tmp : std_logic;
|
|
signal not_clk1_tmp : std_logic;
|
|
signal not_clk2_tmp : std_logic;
|
|
signal not_clk3_tmp : std_logic;
|
|
signal not_clk4_tmp : std_logic;
|
|
signal not_clk5_tmp : std_logic;
|
|
|
|
signal not_extclk0_tmp : std_logic;
|
|
signal not_extclk1_tmp : std_logic;
|
|
signal not_extclk2_tmp : std_logic;
|
|
signal not_extclk3_tmp : std_logic;
|
|
|
|
signal clkin : std_logic := '0';
|
|
signal gate_locked : std_logic := '0';
|
|
signal lock : std_logic := '0';
|
|
signal about_to_lock : boolean := false;
|
|
signal quiet_period_violation : boolean := false;
|
|
signal reconfig_err : boolean := false;
|
|
signal scanclr_violation : boolean := false;
|
|
signal scanclr_clk_violation : boolean := false;
|
|
|
|
signal inclk_l0 : std_logic;
|
|
signal inclk_l1 : std_logic;
|
|
signal inclk_g0 : std_logic;
|
|
signal inclk_g1 : std_logic;
|
|
signal inclk_g2 : std_logic;
|
|
signal inclk_g3 : std_logic;
|
|
signal inclk_e0 : std_logic;
|
|
signal inclk_e1 : std_logic;
|
|
signal inclk_e2 : std_logic;
|
|
signal inclk_e3 : std_logic;
|
|
signal inclk_m : std_logic;
|
|
signal devpor : std_logic;
|
|
signal devclrn : std_logic;
|
|
|
|
signal inclk0_ipd : std_logic;
|
|
signal inclk1_ipd : std_logic;
|
|
signal ena_ipd : std_logic;
|
|
signal pfdena_ipd : std_logic;
|
|
signal comparator_ipd : std_logic;
|
|
signal areset_ipd : std_logic;
|
|
signal fbin_ipd : std_logic;
|
|
signal clkena0_ipd : std_logic;
|
|
signal clkena1_ipd : std_logic;
|
|
signal clkena2_ipd : std_logic;
|
|
signal clkena3_ipd : std_logic;
|
|
signal clkena4_ipd : std_logic;
|
|
signal clkena5_ipd : std_logic;
|
|
signal extclkena0_ipd : std_logic;
|
|
signal extclkena1_ipd : std_logic;
|
|
signal extclkena2_ipd : std_logic;
|
|
signal extclkena3_ipd : std_logic;
|
|
signal scanclk_ipd : std_logic;
|
|
signal scanaclr_ipd : std_logic;
|
|
signal scandata_ipd : std_logic;
|
|
signal clkswitch_ipd : std_logic;
|
|
|
|
signal lvds_dffa_clk : std_logic;
|
|
signal lvds_dffb_clk : std_logic;
|
|
signal lvds_dffc_clk : std_logic;
|
|
signal lvds_dffd_clk : std_logic;
|
|
signal dffa_out : std_logic := '0';
|
|
signal dffb_out : std_logic := '0';
|
|
signal dffc_out : std_logic := '0';
|
|
signal dffd_out : std_logic := '0';
|
|
signal nce_temp : std_logic := '0';
|
|
signal nce_l0 : std_logic := '0';
|
|
signal nce_l1 : std_logic := '0';
|
|
|
|
signal inclk_l0_dly1 : std_logic := '0';
|
|
signal inclk_l0_dly2 : std_logic := '0';
|
|
signal inclk_l0_dly3 : std_logic := '0';
|
|
signal inclk_l0_dly4 : std_logic := '0';
|
|
signal inclk_l0_dly5 : std_logic := '0';
|
|
signal inclk_l0_dly6 : std_logic := '0';
|
|
signal inclk_l1_dly1 : std_logic := '0';
|
|
signal inclk_l1_dly2 : std_logic := '0';
|
|
signal inclk_l1_dly3 : std_logic := '0';
|
|
signal inclk_l1_dly4 : std_logic := '0';
|
|
signal inclk_l1_dly5 : std_logic := '0';
|
|
signal inclk_l1_dly6 : std_logic := '0';
|
|
|
|
|
|
signal sig_offset : time := 0 ps;
|
|
signal sig_refclk_time : time := 0 ps;
|
|
signal sig_fbclk_time : time := 0 ps;
|
|
signal sig_fbclk_period : time := 0 ps;
|
|
signal sig_vco_period_was_phase_adjusted : boolean := false;
|
|
signal sig_phase_adjust_was_scheduled : boolean := false;
|
|
signal sig_stop_vco : std_logic := '0';
|
|
signal sig_m_times_vco_period : time := 0 ps;
|
|
signal sig_new_m_times_vco_period : time := 0 ps;
|
|
signal sig_got_refclk_posedge : boolean := false;
|
|
signal sig_got_fbclk_posedge : boolean := false;
|
|
signal sig_got_second_refclk : boolean := false;
|
|
signal sig_current_clock : string(1 to 6);
|
|
|
|
signal m_delay : integer := 0;
|
|
signal n_delay : integer := 0;
|
|
|
|
signal sig_curr_clock : string(1 to 6) := primary_clock;
|
|
signal scan_chain_length : integer := GPP_SCAN_CHAIN;
|
|
|
|
signal ext_fbk_cntr_high : integer := 0;
|
|
signal ext_fbk_cntr_low : integer := 0;
|
|
signal ext_fbk_cntr_delay : integer := 0;
|
|
signal ext_fbk_cntr_ph : integer := 0;
|
|
signal ext_fbk_cntr_initial : integer := 1;
|
|
signal ext_fbk_cntr : string(1 to 2) := "e0";
|
|
signal ext_fbk_cntr_mode : string(1 to 6) := "bypass";
|
|
|
|
signal enable0_tmp : std_logic := '0';
|
|
signal enable1_tmp : std_logic := '0';
|
|
signal reset_low : std_logic := '0';
|
|
|
|
signal scandataout_tmp : std_logic := '0';
|
|
signal sdataout_trig : std_logic := '0';
|
|
signal sdataout_rst_trig : std_logic := '0';
|
|
|
|
signal sig_refclk_period : time := (inclk0_input_frequency * 1 ps) * n;
|
|
|
|
signal schedule_vco : std_logic := '0';
|
|
|
|
signal areset_ena_sig : std_logic := '0';
|
|
signal done_with_param_calc : boolean := false;
|
|
|
|
COMPONENT MF_m_cntr
|
|
PORT ( clk : IN std_logic;
|
|
reset : IN std_logic;
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer;
|
|
time_delay : IN integer;
|
|
ph : IN integer := 0 );
|
|
END COMPONENT;
|
|
|
|
COMPONENT MF_n_cntr
|
|
PORT ( clk : IN std_logic;
|
|
reset : IN std_logic;
|
|
cout : OUT std_logic;
|
|
modulus : IN integer;
|
|
time_delay : IN integer);
|
|
END COMPONENT;
|
|
|
|
COMPONENT stx_scale_cntr
|
|
PORT ( clk : IN std_logic;
|
|
reset : IN std_logic;
|
|
cout : OUT std_logic;
|
|
initial : IN integer := 1;
|
|
high : IN integer := 1;
|
|
low : IN integer := 1;
|
|
mode : IN string := "bypass";
|
|
time_delay : IN integer := 0;
|
|
ph_tap : IN natural );
|
|
END COMPONENT;
|
|
|
|
COMPONENT dffp
|
|
|
|
PORT ( Q : out STD_LOGIC := '0';
|
|
D : in STD_LOGIC := '1';
|
|
CLRN : in STD_LOGIC := '1';
|
|
PRN : in STD_LOGIC := '1';
|
|
CLK : in STD_LOGIC := '0';
|
|
ENA : in STD_LOGIC := '1');
|
|
END COMPONENT;
|
|
|
|
COMPONENT MF_pll_reg
|
|
PORT ( Q : out STD_LOGIC := '0';
|
|
D : in STD_LOGIC := '1';
|
|
CLRN : in STD_LOGIC := '1';
|
|
PRN : in STD_LOGIC := '1';
|
|
CLK : in STD_LOGIC := '0';
|
|
ENA : in STD_LOGIC := '1');
|
|
END COMPONENT;
|
|
|
|
begin
|
|
|
|
----------------------
|
|
-- INPUT PATH DELAYs
|
|
----------------------
|
|
WireDelay : block
|
|
begin
|
|
inclk0_ipd <= inclk(0);
|
|
inclk1_ipd <= inclk(1);
|
|
areset_ipd <= areset;
|
|
ena_ipd <= ena;
|
|
fbin_ipd <= fbin;
|
|
pfdena_ipd <= pfdena;
|
|
clkena0_ipd <= clkena(0);
|
|
clkena1_ipd <= clkena(1);
|
|
clkena2_ipd <= clkena(2);
|
|
clkena3_ipd <= clkena(3);
|
|
clkena4_ipd <= clkena(4);
|
|
clkena5_ipd <= clkena(5);
|
|
extclkena0_ipd <= extclkena(0);
|
|
extclkena1_ipd <= extclkena(1);
|
|
extclkena2_ipd <= extclkena(2);
|
|
extclkena3_ipd <= extclkena(3);
|
|
scanclk_ipd <= scanclk;
|
|
scanaclr_ipd <= scanaclr;
|
|
scandata_ipd <= scandata;
|
|
comparator_ipd <= comparator;
|
|
clkswitch_ipd <= clkswitch;
|
|
end block;
|
|
|
|
-- User to Advanced parameter conversion
|
|
|
|
i_extclk3_counter <= "e3" when m=0 else extclk3_counter;
|
|
i_extclk2_counter <= "e2" when m=0 else extclk2_counter;
|
|
i_extclk1_counter <= "e1" when m=0 else extclk1_counter;
|
|
i_extclk0_counter <= "e0" when m=0 else extclk0_counter;
|
|
i_clk5_counter <= "l1" when m=0 else clk5_counter;
|
|
i_clk4_counter <= "l0" when m=0 else clk4_counter;
|
|
i_clk3_counter <= "g3" when m=0 else clk3_counter;
|
|
i_clk2_counter <= "g2" when m=0 else clk2_counter;
|
|
i_clk1_counter <= "g1" when m=0 else clk1_counter;
|
|
i_clk0_counter <= "l0" when m=0 and pll_type = "lvds" else
|
|
"g0" when m=0 else clk0_counter;
|
|
|
|
-- end parameter conversion
|
|
|
|
inclk_m <= extclk0_tmp when operation_mode = "external_feedback" and feedback_source = "extclk0" else
|
|
extclk1_tmp when operation_mode = "external_feedback" and feedback_source = "extclk1" else
|
|
extclk2_tmp when operation_mode = "external_feedback" and feedback_source = "extclk2" else
|
|
extclk3_tmp when operation_mode = "external_feedback" and feedback_source = "extclk3" else
|
|
vco_out(m_ph_val);
|
|
|
|
ext_fbk_cntr <= "e0" when (feedback_source = "extclk0" and extclk0_counter = "e0") or (feedback_source = "extclk1" and extclk1_counter = "e0") or (feedback_source = "extclk2" and extclk2_counter = "e0") or (feedback_source = "extclk3" and extclk3_counter = "e0") else
|
|
"e1" when (feedback_source = "extclk0" and extclk0_counter = "e1") or (feedback_source = "extclk1" and extclk1_counter = "e1") or (feedback_source = "extclk2" and extclk2_counter = "e1") or (feedback_source = "extclk3" and extclk3_counter = "e1") else
|
|
"e2" when (feedback_source = "extclk0" and extclk0_counter = "e2") or (feedback_source = "extclk1" and extclk1_counter = "e2") or (feedback_source = "extclk2" and extclk2_counter = "e2") or (feedback_source = "extclk3" and extclk3_counter = "e2") else
|
|
"e3" when (feedback_source = "extclk0" and extclk0_counter = "e3") or (feedback_source = "extclk1" and extclk1_counter = "e3") or (feedback_source = "extclk2" and extclk2_counter = "e3") or (feedback_source = "extclk3" and extclk3_counter = "e3") else
|
|
"e0";
|
|
|
|
ext_fbk_cntr_high <= e0_high_val when ext_fbk_cntr = "e0" else
|
|
e1_high_val when ext_fbk_cntr = "e1" else
|
|
e2_high_val when ext_fbk_cntr = "e2" else
|
|
e3_high_val when ext_fbk_cntr = "e3" else
|
|
1;
|
|
ext_fbk_cntr_low <= e0_low_val when ext_fbk_cntr = "e0" else
|
|
e1_low_val when ext_fbk_cntr = "e1" else
|
|
e2_low_val when ext_fbk_cntr = "e2" else
|
|
e3_low_val when ext_fbk_cntr = "e3" else
|
|
1;
|
|
ext_fbk_cntr_delay <= e0_time_delay_val when ext_fbk_cntr = "e0" else
|
|
e1_time_delay_val when ext_fbk_cntr = "e1" else
|
|
e2_time_delay_val when ext_fbk_cntr = "e2" else
|
|
e3_time_delay_val when ext_fbk_cntr = "e3" else
|
|
0;
|
|
|
|
ext_fbk_cntr_ph <= e0_ph_val when ext_fbk_cntr = "e0" else
|
|
e1_ph_val when ext_fbk_cntr = "e1" else
|
|
e2_ph_val when ext_fbk_cntr = "e2" else
|
|
e3_ph_val when ext_fbk_cntr = "e3" else
|
|
0;
|
|
|
|
ext_fbk_cntr_initial <= e0_initial_val when ext_fbk_cntr = "e0" else
|
|
e1_initial_val when ext_fbk_cntr = "e1" else
|
|
e2_initial_val when ext_fbk_cntr = "e2" else
|
|
e3_initial_val when ext_fbk_cntr = "e3" else
|
|
0;
|
|
ext_fbk_cntr_mode <= e0_mode_val when ext_fbk_cntr = "e0" else
|
|
e1_mode_val when ext_fbk_cntr = "e1" else
|
|
e2_mode_val when ext_fbk_cntr = "e2" else
|
|
e3_mode_val when ext_fbk_cntr = "e3" else
|
|
e0_mode_val;
|
|
|
|
areset_ena_sig <= areset_ipd or (not ena_ipd) or sig_stop_vco;
|
|
|
|
m1 : MF_m_cntr
|
|
port map ( clk => inclk_m,
|
|
reset => areset_ena_sig,
|
|
cout => fbclk,
|
|
initial_value => m_initial_val,
|
|
modulus => m_val,
|
|
time_delay => m_delay,
|
|
ph => m_ph_val );
|
|
|
|
-- add delta delay to inclk1 to ensure inclk0 and inclk1 are processed
|
|
-- in different simulation deltas.
|
|
|
|
n1 : MF_n_cntr
|
|
port map ( clk => clkin,
|
|
reset => areset_ipd,
|
|
cout => refclk,
|
|
modulus => n_val,
|
|
time_delay => n_time_delay_val);
|
|
|
|
inclk_l0 <= vco_out(l0_ph_val);
|
|
l0 : stx_scale_cntr
|
|
port map ( clk => inclk_l0,
|
|
reset => areset_ena_sig,
|
|
cout => l0_clk,
|
|
initial => l0_initial_val,
|
|
high => l0_high_val,
|
|
low => l0_low_val,
|
|
mode => l0_mode_val,
|
|
time_delay => l0_time_delay_val,
|
|
ph_tap => l0_ph_val);
|
|
|
|
inclk_l1 <= vco_out(l1_ph_val);
|
|
l1 : stx_scale_cntr
|
|
port map ( clk => inclk_l1,
|
|
reset => areset_ena_sig,
|
|
cout => l1_clk,
|
|
initial => l1_initial_val,
|
|
high => l1_high_val,
|
|
low => l1_low_val,
|
|
mode => l1_mode_val,
|
|
time_delay => l1_time_delay_val,
|
|
ph_tap => l1_ph_val);
|
|
|
|
inclk_g0 <= vco_out(g0_ph_val);
|
|
g0 : stx_scale_cntr
|
|
port map ( clk => inclk_g0,
|
|
reset => areset_ena_sig,
|
|
cout => g0_clk,
|
|
initial => g0_initial_val,
|
|
high => g0_high_val,
|
|
low => g0_low_val,
|
|
mode => g0_mode_val,
|
|
time_delay => g0_time_delay_val,
|
|
ph_tap => g0_ph_val);
|
|
|
|
|
|
process(g0_clk, l0_clk, l1_clk)
|
|
begin
|
|
if (g0_clk'event and g0_clk = '1') then
|
|
dffa_out <= comparator_ipd;
|
|
end if;
|
|
if (l0_clk'event and l0_clk = '1' and enable0_counter = "l0") then
|
|
dffb_out <= dffa_out;
|
|
dffc_out <= dffb_out;
|
|
dffd_out <= nce_temp;
|
|
end if;
|
|
if (l1_clk'event and l1_clk = '1' and enable0_counter = "l1") then
|
|
dffb_out <= dffa_out;
|
|
dffc_out <= dffb_out;
|
|
dffd_out <= nce_temp;
|
|
end if;
|
|
end process;
|
|
|
|
nce_temp <= (not dffc_out) and dffb_out;
|
|
|
|
nce_l0 <= dffd_out when enable0_counter = "l0" else '0';
|
|
nce_l1 <= dffd_out when enable0_counter = "l1" else '0';
|
|
|
|
inclk_g1 <= vco_out(g1_ph_val);
|
|
g1 : stx_scale_cntr
|
|
port map ( clk => inclk_g1,
|
|
reset => areset_ena_sig,
|
|
cout => g1_clk,
|
|
initial => g1_initial_val,
|
|
high => g1_high_val,
|
|
low => g1_low_val,
|
|
mode => g1_mode_val,
|
|
time_delay => g1_time_delay_val,
|
|
ph_tap => g1_ph_val);
|
|
|
|
inclk_g2 <= vco_out(g2_ph_val);
|
|
g2 : stx_scale_cntr
|
|
port map ( clk => inclk_g2,
|
|
reset => areset_ena_sig,
|
|
cout => g2_clk,
|
|
initial => g2_initial_val,
|
|
high => g2_high_val,
|
|
low => g2_low_val,
|
|
mode => g2_mode_val,
|
|
time_delay => g2_time_delay_val,
|
|
ph_tap => g2_ph_val);
|
|
|
|
inclk_g3 <= vco_out(g3_ph_val);
|
|
g3 : stx_scale_cntr
|
|
port map ( clk => inclk_g3,
|
|
reset => areset_ena_sig,
|
|
cout => g3_clk,
|
|
initial => g3_initial_val,
|
|
high => g3_high_val,
|
|
low => g3_low_val,
|
|
mode => g3_mode_val,
|
|
time_delay => g3_time_delay_val,
|
|
ph_tap => g3_ph_val);
|
|
|
|
inclk_e0 <= vco_out(e0_ph_val);
|
|
cntr_e0_initial <= 1 when operation_mode = "external_feedback" and
|
|
ext_fbk_cntr = "e0" else e0_initial_val;
|
|
cntr_e0_delay <= ext_fbk_delay when operation_mode = "external_feedback" and
|
|
ext_fbk_cntr = "e0" else
|
|
e0_time_delay_val;
|
|
e0 : stx_scale_cntr
|
|
port map ( clk => inclk_e0,
|
|
reset => areset_ena_sig,
|
|
cout => e0_clk,
|
|
initial => cntr_e0_initial,
|
|
high => e0_high_val,
|
|
low => e0_low_val,
|
|
mode => e0_mode_val,
|
|
time_delay => cntr_e0_delay,
|
|
ph_tap => e0_ph_val);
|
|
|
|
inclk_e1 <= vco_out(e1_ph_val);
|
|
cntr_e1_initial <= 1 when operation_mode = "external_feedback" and
|
|
ext_fbk_cntr = "e1" else e1_initial_val;
|
|
cntr_e1_delay <= ext_fbk_delay when operation_mode = "external_feedback" and
|
|
ext_fbk_cntr = "e1" else
|
|
e1_time_delay_val;
|
|
e1 : stx_scale_cntr
|
|
port map ( clk => inclk_e1,
|
|
reset => areset_ena_sig,
|
|
cout => e1_clk,
|
|
initial => cntr_e1_initial,
|
|
high => e1_high_val,
|
|
low => e1_low_val,
|
|
mode => e1_mode_val,
|
|
time_delay => cntr_e1_delay,
|
|
ph_tap => e1_ph_val);
|
|
|
|
inclk_e2 <= vco_out(e2_ph_val);
|
|
cntr_e2_initial <= 1 when operation_mode = "external_feedback" and
|
|
ext_fbk_cntr = "e2" else e2_initial_val;
|
|
cntr_e2_delay <= ext_fbk_delay when operation_mode = "external_feedback" and
|
|
ext_fbk_cntr = "e2" else
|
|
e2_time_delay_val;
|
|
e2 : stx_scale_cntr
|
|
port map ( clk => inclk_e2,
|
|
reset => areset_ena_sig,
|
|
cout => e2_clk,
|
|
initial => cntr_e2_initial,
|
|
high => e2_high_val,
|
|
low => e2_low_val,
|
|
mode => e2_mode_val,
|
|
time_delay => cntr_e2_delay,
|
|
ph_tap => e2_ph_val);
|
|
|
|
inclk_e3 <= vco_out(e3_ph_val);
|
|
cntr_e3_initial <= 1 when operation_mode = "external_feedback" and
|
|
ext_fbk_cntr = "e3" else e3_initial_val;
|
|
cntr_e3_delay <= ext_fbk_delay when operation_mode = "external_feedback" and
|
|
ext_fbk_cntr = "e3" else
|
|
e3_time_delay_val;
|
|
e3 : stx_scale_cntr
|
|
port map ( clk => inclk_e3,
|
|
reset => areset_ena_sig,
|
|
cout => e3_clk,
|
|
initial => cntr_e3_initial,
|
|
high => e3_high_val,
|
|
low => e3_low_val,
|
|
mode => e3_mode_val,
|
|
time_delay => cntr_e3_delay,
|
|
ph_tap => e3_ph_val);
|
|
|
|
inclk_l0_dly1 <= inclk_l0;
|
|
inclk_l0_dly2 <= inclk_l0_dly1;
|
|
inclk_l0_dly3 <= inclk_l0_dly2;
|
|
inclk_l0_dly4 <= inclk_l0_dly3;
|
|
inclk_l0_dly5 <= inclk_l0_dly4;
|
|
inclk_l0_dly6 <= inclk_l0_dly5;
|
|
|
|
inclk_l1_dly1 <= inclk_l1;
|
|
inclk_l1_dly2 <= inclk_l1_dly1;
|
|
inclk_l1_dly3 <= inclk_l1_dly2;
|
|
inclk_l1_dly4 <= inclk_l1_dly3;
|
|
inclk_l1_dly5 <= inclk_l1_dly4;
|
|
inclk_l1_dly6 <= inclk_l1_dly5;
|
|
|
|
process(inclk_l0_dly6, inclk_l1_dly6, areset_ipd, ena_ipd, sig_stop_vco)
|
|
variable l0_got_first_rising_edge : boolean := false;
|
|
variable l0_count : integer := 1;
|
|
variable l0_tmp, l1_tmp : std_logic := '0';
|
|
variable l1_got_first_rising_edge : boolean := false;
|
|
variable l1_count : integer := 1;
|
|
begin
|
|
if (areset_ipd = '1' or ena_ipd = '0' or sig_stop_vco = '1') then
|
|
l0_count := 1;
|
|
l1_count := 1;
|
|
l0_got_first_rising_edge := false;
|
|
l1_got_first_rising_edge := false;
|
|
else
|
|
if (nce_l0 = '0') then
|
|
if (not l0_got_first_rising_edge) then
|
|
if (inclk_l0_dly6'event and inclk_l0_dly6 = '1') then
|
|
l0_got_first_rising_edge := true;
|
|
end if;
|
|
elsif (inclk_l0_dly6'event) then
|
|
l0_count := l0_count + 1;
|
|
if (l0_count = (l0_high_val + l0_low_val) * 2) then
|
|
l0_count := 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (inclk_l0_dly6'event and inclk_l0_dly6 = '0') then
|
|
if (l0_count = 1) then
|
|
l0_tmp := '1';
|
|
l0_got_first_rising_edge := false;
|
|
else
|
|
l0_tmp := '0';
|
|
end if;
|
|
end if;
|
|
|
|
if (nce_l1 = '0') then
|
|
if (not l1_got_first_rising_edge) then
|
|
if (inclk_l1_dly6'event and inclk_l1_dly6 = '1') then
|
|
l1_got_first_rising_edge := true;
|
|
end if;
|
|
elsif (inclk_l1_dly6'event) then
|
|
l1_count := l1_count + 1;
|
|
if (l1_count = (l1_high_val + l1_low_val) * 2) then
|
|
l1_count := 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (inclk_l1_dly6'event and inclk_l1_dly6 = '0') then
|
|
if (l1_count = 1) then
|
|
l1_tmp := '1';
|
|
l1_got_first_rising_edge := false;
|
|
else
|
|
l1_tmp := '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (enable0_counter = "l0") then
|
|
enable0_tmp <= l0_tmp;
|
|
elsif (enable0_counter = "l1") then
|
|
enable0_tmp <= l1_tmp;
|
|
else
|
|
enable0_tmp <= '0';
|
|
end if;
|
|
|
|
if (enable1_counter = "l0") then
|
|
enable1_tmp <= l0_tmp;
|
|
elsif (enable1_counter = "l1") then
|
|
enable1_tmp <= l1_tmp;
|
|
else
|
|
enable1_tmp <= '0';
|
|
end if;
|
|
|
|
end process;
|
|
|
|
glocked_cntr : process(clkin, ena_ipd, areset_ipd)
|
|
variable count : integer := 0;
|
|
variable output : std_logic := '0';
|
|
begin
|
|
if (areset_ipd = '1') then
|
|
count := 0;
|
|
output := '0';
|
|
elsif (clkin'event and clkin = '1') then
|
|
if (ena_ipd = '1') then
|
|
count := count + 1;
|
|
if (count = gate_lock_counter) then
|
|
output := '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
gate_locked <= output;
|
|
end process;
|
|
|
|
locked <= gate_locked and lock when gate_lock_signal = "yes" else
|
|
lock;
|
|
|
|
process (transfer)
|
|
variable init : boolean := true;
|
|
variable low, high : std_logic_vector(8 downto 0);
|
|
variable delay_chain : std_logic_vector(3 downto 0);
|
|
variable mn_delay_chain : std_logic_vector(0 to 3);
|
|
variable mode : string(1 to 6) := "bypass";
|
|
variable delay_val : integer := 0;
|
|
variable is_error : boolean := false;
|
|
variable buf : line;
|
|
|
|
-- user to advanced variables
|
|
|
|
variable i_m_initial : natural;
|
|
variable i_m : integer := 1;
|
|
variable i_n : natural := 1;
|
|
variable i_m2 : natural;
|
|
variable i_n2 : natural;
|
|
variable i_ss : natural;
|
|
variable i_l0_high : natural;
|
|
variable i_l1_high : natural;
|
|
variable i_g0_high : natural;
|
|
variable i_g1_high : natural;
|
|
variable i_g2_high : natural;
|
|
variable i_g3_high : natural;
|
|
variable i_e0_high : natural;
|
|
variable i_e1_high : natural;
|
|
variable i_e2_high : natural;
|
|
variable i_e3_high : natural;
|
|
variable i_l0_low : natural;
|
|
variable i_l1_low : natural;
|
|
variable i_g0_low : natural;
|
|
variable i_g1_low : natural;
|
|
variable i_g2_low : natural;
|
|
variable i_g3_low : natural;
|
|
variable i_e0_low : natural;
|
|
variable i_e1_low : natural;
|
|
variable i_e2_low : natural;
|
|
variable i_e3_low : natural;
|
|
variable i_l0_initial : natural;
|
|
variable i_l1_initial : natural;
|
|
variable i_g0_initial : natural;
|
|
variable i_g1_initial : natural;
|
|
variable i_g2_initial : natural;
|
|
variable i_g3_initial : natural;
|
|
variable i_e0_initial : natural;
|
|
variable i_e1_initial : natural;
|
|
variable i_e2_initial : natural;
|
|
variable i_e3_initial : natural;
|
|
variable i_l0_mode : string(1 to 6);
|
|
variable i_l1_mode : string(1 to 6);
|
|
variable i_g0_mode : string(1 to 6);
|
|
variable i_g1_mode : string(1 to 6);
|
|
variable i_g2_mode : string(1 to 6);
|
|
variable i_g3_mode : string(1 to 6);
|
|
variable i_e0_mode : string(1 to 6);
|
|
variable i_e1_mode : string(1 to 6);
|
|
variable i_e2_mode : string(1 to 6);
|
|
variable i_e3_mode : string(1 to 6);
|
|
variable max_neg_abs : integer := 0;
|
|
variable i_l0_time_delay : natural;
|
|
variable i_l1_time_delay : natural;
|
|
variable i_g0_time_delay : natural;
|
|
variable i_g1_time_delay : natural;
|
|
variable i_g2_time_delay : natural;
|
|
variable i_g3_time_delay : natural;
|
|
variable i_e0_time_delay : natural;
|
|
variable i_e1_time_delay : natural;
|
|
variable i_e2_time_delay : natural;
|
|
variable i_e3_time_delay : natural;
|
|
variable i_m_time_delay : natural;
|
|
variable i_n_time_delay : natural;
|
|
variable i_l0_ph : natural;
|
|
variable i_l1_ph : natural;
|
|
variable i_g0_ph : natural;
|
|
variable i_g1_ph : natural;
|
|
variable i_g2_ph : natural;
|
|
variable i_g3_ph : natural;
|
|
variable i_e0_ph : natural;
|
|
variable i_e1_ph : natural;
|
|
variable i_e2_ph : natural;
|
|
variable i_e3_ph : natural;
|
|
variable i_m_ph : natural;
|
|
variable output_count : natural;
|
|
variable new_divisor : natural;
|
|
|
|
-- variables for scaling of multiply_by and divide_by values
|
|
variable i_clk0_mult_by : integer := 1;
|
|
variable i_clk0_div_by : integer := 1;
|
|
variable i_clk1_mult_by : integer := 1;
|
|
variable i_clk1_div_by : integer := 1;
|
|
variable i_clk2_mult_by : integer := 1;
|
|
variable i_clk2_div_by : integer := 1;
|
|
variable i_clk3_mult_by : integer := 1;
|
|
variable i_clk3_div_by : integer := 1;
|
|
variable i_clk4_mult_by : integer := 1;
|
|
variable i_clk4_div_by : integer := 1;
|
|
variable i_clk5_mult_by : integer := 1;
|
|
variable i_clk5_div_by : integer := 1;
|
|
variable i_extclk0_mult_by : integer := 1;
|
|
variable i_extclk0_div_by : integer := 1;
|
|
variable i_extclk1_mult_by : integer := 1;
|
|
variable i_extclk1_div_by : integer := 1;
|
|
variable i_extclk2_mult_by : integer := 1;
|
|
variable i_extclk2_div_by : integer := 1;
|
|
variable i_extclk3_mult_by : integer := 1;
|
|
variable i_extclk3_div_by : integer := 1;
|
|
variable max_d_value : integer := 1;
|
|
variable new_multiplier : integer := 1;
|
|
|
|
-- internal variables for storing the phase shift number.(used in lvds mode only)
|
|
variable i_clk0_phase_shift : integer := 1;
|
|
variable i_clk1_phase_shift : integer := 1;
|
|
variable i_clk2_phase_shift : integer := 1;
|
|
|
|
begin
|
|
if (init) then
|
|
if (m = 0) then -- convert user parameters to advanced
|
|
-- set the limit of the divide_by value that can be returned by
|
|
-- the following function.
|
|
max_d_value := 500;
|
|
|
|
-- scale down the multiply_by and divide_by values provided by the design
|
|
-- before attempting to use them in the calculations below
|
|
find_simple_integer_fraction(clk0_multiply_by, clk0_divide_by,
|
|
max_d_value, i_clk0_mult_by, i_clk0_div_by);
|
|
find_simple_integer_fraction(clk1_multiply_by, clk1_divide_by,
|
|
max_d_value, i_clk1_mult_by, i_clk1_div_by);
|
|
find_simple_integer_fraction(clk2_multiply_by, clk2_divide_by,
|
|
max_d_value, i_clk2_mult_by, i_clk2_div_by);
|
|
find_simple_integer_fraction(clk3_multiply_by, clk3_divide_by,
|
|
max_d_value, i_clk3_mult_by, i_clk3_div_by);
|
|
find_simple_integer_fraction(clk4_multiply_by, clk4_divide_by,
|
|
max_d_value, i_clk4_mult_by, i_clk4_div_by);
|
|
find_simple_integer_fraction(clk5_multiply_by, clk5_divide_by,
|
|
max_d_value, i_clk5_mult_by, i_clk5_div_by);
|
|
find_simple_integer_fraction(extclk0_multiply_by, extclk0_divide_by,
|
|
max_d_value, i_extclk0_mult_by, i_extclk0_div_by);
|
|
find_simple_integer_fraction(extclk1_multiply_by, extclk1_divide_by,
|
|
max_d_value, i_extclk1_mult_by, i_extclk1_div_by);
|
|
find_simple_integer_fraction(extclk2_multiply_by, extclk2_divide_by,
|
|
max_d_value, i_extclk2_mult_by, i_extclk2_div_by);
|
|
find_simple_integer_fraction(extclk3_multiply_by, extclk3_divide_by,
|
|
max_d_value, i_extclk3_mult_by, i_extclk3_div_by);
|
|
|
|
i_n := 1;
|
|
if (pll_type = "lvds") then
|
|
i_m := clk0_multiply_by;
|
|
else
|
|
i_m := lcm (i_clk0_mult_by, i_clk1_mult_by,
|
|
i_clk2_mult_by, i_clk3_mult_by,
|
|
i_clk4_mult_by, i_clk5_mult_by,
|
|
i_extclk0_mult_by,
|
|
i_extclk1_mult_by, i_extclk2_mult_by,
|
|
i_extclk3_mult_by, inclk0_input_frequency);
|
|
end if;
|
|
i_m_time_delay := maxnegabs ( str2int(clk0_time_delay),
|
|
str2int(clk1_time_delay),
|
|
str2int(clk2_time_delay),
|
|
str2int(clk3_time_delay),
|
|
str2int(clk4_time_delay),
|
|
str2int(clk5_time_delay),
|
|
str2int(extclk0_time_delay),
|
|
str2int(extclk1_time_delay),
|
|
str2int(extclk2_time_delay),
|
|
str2int(extclk3_time_delay));
|
|
i_n_time_delay := mintimedelay(str2int(clk0_time_delay),
|
|
str2int(clk1_time_delay),
|
|
str2int(clk2_time_delay),
|
|
str2int(clk3_time_delay),
|
|
str2int(clk4_time_delay),
|
|
str2int(clk5_time_delay),
|
|
str2int(extclk0_time_delay),
|
|
str2int(extclk1_time_delay),
|
|
str2int(extclk2_time_delay),
|
|
str2int(extclk3_time_delay));
|
|
if (pll_type = "lvds") then
|
|
i_g0_time_delay := counter_time_delay ( str2int(clk2_time_delay),
|
|
i_m_time_delay, i_n_time_delay);
|
|
else
|
|
i_g0_time_delay := counter_time_delay ( str2int(clk0_time_delay),
|
|
i_m_time_delay,i_n_time_delay);
|
|
end if;
|
|
i_g1_time_delay := counter_time_delay ( str2int(clk1_time_delay),
|
|
i_m_time_delay, i_n_time_delay);
|
|
i_g2_time_delay := counter_time_delay ( str2int(clk2_time_delay),
|
|
i_m_time_delay, i_n_time_delay);
|
|
i_g3_time_delay := counter_time_delay ( str2int(clk3_time_delay),
|
|
i_m_time_delay, i_n_time_delay);
|
|
if (pll_type = "lvds") then
|
|
i_l0_time_delay := i_g0_time_delay;
|
|
i_l1_time_delay := i_g0_time_delay;
|
|
else
|
|
i_l0_time_delay := counter_time_delay ( str2int(clk4_time_delay),
|
|
i_m_time_delay, i_n_time_delay);
|
|
i_l1_time_delay := counter_time_delay ( str2int(clk5_time_delay),
|
|
i_m_time_delay, i_n_time_delay);
|
|
end if;
|
|
i_e0_time_delay := counter_time_delay ( str2int(extclk0_time_delay),
|
|
i_m_time_delay, i_n_time_delay);
|
|
i_e1_time_delay := counter_time_delay ( str2int(extclk1_time_delay),
|
|
i_m_time_delay, i_n_time_delay);
|
|
i_e2_time_delay := counter_time_delay ( str2int(extclk2_time_delay),
|
|
i_m_time_delay, i_n_time_delay);
|
|
i_e3_time_delay := counter_time_delay ( str2int(extclk3_time_delay),
|
|
i_m_time_delay, i_n_time_delay);
|
|
|
|
if (pll_type = "flvds") then
|
|
-- Need to readjust phase shift values when the clock multiply value has been readjusted.
|
|
new_multiplier := clk0_multiply_by / i_clk0_mult_by;
|
|
i_clk0_phase_shift := str2int(clk0_phase_shift) * new_multiplier;
|
|
i_clk1_phase_shift := str2int(clk1_phase_shift) * new_multiplier;
|
|
i_clk2_phase_shift := str2int(clk2_phase_shift) * new_multiplier;
|
|
else
|
|
i_clk0_phase_shift := str2int(clk0_phase_shift);
|
|
i_clk1_phase_shift := str2int(clk1_phase_shift);
|
|
i_clk2_phase_shift := str2int(clk2_phase_shift);
|
|
end if;
|
|
|
|
max_neg_abs := maxnegabs ( i_clk0_phase_shift,
|
|
i_clk1_phase_shift,
|
|
i_clk2_phase_shift,
|
|
str2int(clk3_phase_shift),
|
|
str2int(clk4_phase_shift),
|
|
str2int(clk5_phase_shift),
|
|
str2int(extclk0_phase_shift),
|
|
str2int(extclk1_phase_shift),
|
|
str2int(extclk2_phase_shift),
|
|
str2int(extclk3_phase_shift));
|
|
i_m_ph := counter_ph(get_phase_degree(max_neg_abs,inclk0_input_frequency), i_m, i_n);
|
|
if (pll_type = "lvds") then
|
|
i_g0_ph := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
else
|
|
i_g0_ph := counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
end if;
|
|
|
|
i_g1_ph := counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_g2_ph := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_g3_ph := counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
|
|
if (pll_type = "lvds") then
|
|
i_l0_ph := i_g0_ph;
|
|
i_l1_ph := i_g0_ph;
|
|
else
|
|
i_l0_ph := counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_l1_ph := counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
end if;
|
|
i_e0_ph := counter_ph(get_phase_degree(ph_adjust(str2int(extclk0_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_e1_ph := counter_ph(get_phase_degree(ph_adjust(str2int(extclk1_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_e2_ph := counter_ph(get_phase_degree(ph_adjust(str2int(extclk2_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_e3_ph := counter_ph(get_phase_degree(ph_adjust(str2int(extclk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
if (pll_type = "lvds") then
|
|
i_g0_high := counter_high ( output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
else
|
|
i_g0_high := counter_high ( output_counter_value(i_clk0_div_by,
|
|
i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
|
|
end if;
|
|
i_g1_high := counter_high ( output_counter_value(i_clk1_div_by,
|
|
i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
|
|
i_g2_high := counter_high ( output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
i_g3_high := counter_high ( output_counter_value(i_clk3_div_by,
|
|
i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
|
|
if (pll_type = "lvds") then
|
|
i_l0_high := i_g0_high;
|
|
i_l1_high := i_g0_high;
|
|
else
|
|
i_l0_high := counter_high ( output_counter_value(i_clk4_div_by,
|
|
i_clk4_mult_by, i_m, i_n), clk4_duty_cycle);
|
|
i_l1_high := counter_high ( output_counter_value(i_clk5_div_by,
|
|
i_clk5_mult_by, i_m, i_n), clk5_duty_cycle);
|
|
end if;
|
|
i_e0_high := counter_high ( output_counter_value(i_extclk0_div_by,
|
|
i_extclk0_mult_by, i_m, i_n), extclk0_duty_cycle);
|
|
i_e1_high := counter_high ( output_counter_value(i_extclk1_div_by,
|
|
i_extclk1_mult_by, i_m, i_n), extclk1_duty_cycle);
|
|
i_e2_high := counter_high ( output_counter_value(i_extclk2_div_by,
|
|
i_extclk2_mult_by, i_m, i_n), extclk2_duty_cycle);
|
|
i_e3_high := counter_high ( output_counter_value(i_extclk3_div_by,
|
|
i_extclk3_mult_by, i_m, i_n), extclk3_duty_cycle);
|
|
if (pll_type = "lvds") then
|
|
i_g0_low := counter_low ( output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
else
|
|
i_g0_low := counter_low ( output_counter_value(i_clk0_div_by,
|
|
i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
|
|
end if;
|
|
i_g1_low := counter_low ( output_counter_value(i_clk1_div_by,
|
|
i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
|
|
i_g2_low := counter_low ( output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
i_g3_low := counter_low ( output_counter_value(i_clk3_div_by,
|
|
i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
|
|
if (pll_type = "lvds") then
|
|
i_l0_low := i_g0_low;
|
|
i_l1_low := i_g0_low;
|
|
else
|
|
i_l0_low := counter_low ( output_counter_value(i_clk4_div_by,
|
|
i_clk4_mult_by, i_m, i_n), clk4_duty_cycle);
|
|
i_l1_low := counter_low ( output_counter_value(i_clk5_div_by,
|
|
i_clk5_mult_by, i_m, i_n), clk5_duty_cycle);
|
|
end if;
|
|
i_e0_low := counter_low ( output_counter_value(i_extclk0_div_by,
|
|
i_extclk0_mult_by, i_m, i_n), extclk0_duty_cycle);
|
|
i_e1_low := counter_low ( output_counter_value(i_extclk1_div_by,
|
|
i_extclk1_mult_by, i_m, i_n), extclk1_duty_cycle);
|
|
i_e2_low := counter_low ( output_counter_value(i_extclk2_div_by,
|
|
i_extclk2_mult_by, i_m, i_n), extclk2_duty_cycle);
|
|
i_e3_low := counter_low ( output_counter_value(i_extclk3_div_by,
|
|
i_extclk3_mult_by, i_m, i_n), extclk3_duty_cycle);
|
|
i_m_initial := counter_initial(get_phase_degree(max_neg_abs, inclk0_input_frequency), i_m,i_n);
|
|
if (pll_type = "lvds") then
|
|
i_g0_initial := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
else
|
|
i_g0_initial := counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
end if;
|
|
|
|
i_g1_initial := counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_g2_initial := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_g3_initial := counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
if (pll_type = "lvds") then
|
|
i_l0_initial := i_g0_initial;
|
|
i_l1_initial := i_g0_initial;
|
|
else
|
|
i_l0_initial := counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_l1_initial := counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
end if;
|
|
i_e0_initial := counter_initial(get_phase_degree(ph_adjust(str2int(extclk0_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_e1_initial := counter_initial(get_phase_degree(ph_adjust(str2int(extclk1_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_e2_initial := counter_initial(get_phase_degree(ph_adjust(str2int(extclk2_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_e3_initial := counter_initial(get_phase_degree(ph_adjust(str2int(extclk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
if (pll_type = "lvds") then
|
|
i_g0_mode := counter_mode(clk2_duty_cycle, output_counter_value(i_clk2_div_by, i_clk2_mult_by, i_m, i_n));
|
|
else
|
|
i_g0_mode := counter_mode(clk0_duty_cycle, output_counter_value(i_clk0_div_by, i_clk0_mult_by, i_m, i_n));
|
|
end if;
|
|
i_g1_mode := counter_mode(clk1_duty_cycle, output_counter_value(i_clk1_div_by, i_clk1_mult_by, i_m, i_n));
|
|
i_g2_mode := counter_mode(clk2_duty_cycle, output_counter_value(i_clk2_div_by, i_clk2_mult_by, i_m, i_n));
|
|
i_g3_mode := counter_mode(clk3_duty_cycle, output_counter_value(i_clk3_div_by, i_clk3_mult_by, i_m, i_n));
|
|
if (pll_type = "lvds") then
|
|
i_l0_mode := "bypass";
|
|
i_l1_mode := "bypass";
|
|
else
|
|
i_l0_mode := counter_mode(clk4_duty_cycle, output_counter_value(i_clk4_div_by, i_clk4_mult_by, i_m, i_n));
|
|
i_l1_mode := counter_mode(clk5_duty_cycle, output_counter_value(i_clk5_div_by, i_clk5_mult_by, i_m, i_n));
|
|
end if;
|
|
i_e0_mode := counter_mode(extclk0_duty_cycle, output_counter_value(i_extclk0_div_by, i_extclk0_mult_by, i_m, i_n));
|
|
i_e1_mode := counter_mode(extclk1_duty_cycle, output_counter_value(i_extclk1_div_by, i_extclk1_mult_by, i_m, i_n));
|
|
i_e2_mode := counter_mode(extclk2_duty_cycle, output_counter_value(i_extclk2_div_by, i_extclk2_mult_by, i_m, i_n));
|
|
i_e3_mode := counter_mode(extclk3_duty_cycle, output_counter_value(i_extclk3_div_by, i_extclk3_mult_by, i_m, i_n));
|
|
|
|
-- in external feedback mode, need to adjust M value to take
|
|
-- into consideration the external feedback counter value
|
|
if(operation_mode = "external_feedback") then
|
|
-- if there is a negative phase shift, m_initial can
|
|
-- only be 1
|
|
if (max_neg_abs > 0) then
|
|
i_m_initial := 1;
|
|
end if;
|
|
|
|
-- calculate the feedback counter multiplier
|
|
if (feedback_source = "extclk0") then
|
|
if (i_e0_mode = "bypass") then
|
|
output_count := 1;
|
|
else
|
|
output_count := i_e0_high + i_e0_low;
|
|
end if;
|
|
elsif (feedback_source = "extclk1") then
|
|
if (i_e1_mode = "bypass") then
|
|
output_count := 1;
|
|
else
|
|
output_count := i_e1_high + i_e1_low;
|
|
end if;
|
|
elsif (feedback_source = "extclk2") then
|
|
if (i_e2_mode = "bypass") then
|
|
output_count := 1;
|
|
else
|
|
output_count := i_e2_high + i_e2_low;
|
|
end if;
|
|
elsif (feedback_source = "extclk3") then
|
|
if (i_e3_mode = "bypass") then
|
|
output_count := 1;
|
|
else
|
|
output_count := i_e3_high + i_e3_low;
|
|
end if;
|
|
else -- default to e0
|
|
if (i_e0_mode = "bypass") then
|
|
output_count := 1;
|
|
else
|
|
output_count := i_e0_high + i_e0_low;
|
|
end if;
|
|
end if;
|
|
|
|
new_divisor := gcd(i_m, output_count);
|
|
i_m := i_m / new_divisor;
|
|
i_n := output_count / new_divisor;
|
|
end if;
|
|
|
|
else -- m /= 0
|
|
|
|
i_n := n;
|
|
i_m := m;
|
|
i_m_initial := m_initial;
|
|
i_m_time_delay := m_time_delay;
|
|
i_n_time_delay := n_time_delay;
|
|
i_l0_time_delay := l0_time_delay;
|
|
i_l1_time_delay := l1_time_delay;
|
|
i_g0_time_delay := g0_time_delay;
|
|
i_g1_time_delay := g1_time_delay;
|
|
i_g2_time_delay := g2_time_delay;
|
|
i_g3_time_delay := g3_time_delay;
|
|
i_e0_time_delay := e0_time_delay;
|
|
i_e1_time_delay := e1_time_delay;
|
|
i_e2_time_delay := e2_time_delay;
|
|
i_e3_time_delay := e3_time_delay;
|
|
i_m_ph := m_ph;
|
|
i_l0_ph := l0_ph;
|
|
i_l1_ph := l1_ph;
|
|
i_g0_ph := g0_ph;
|
|
i_g1_ph := g1_ph;
|
|
i_g2_ph := g2_ph;
|
|
i_g3_ph := g3_ph;
|
|
i_e0_ph := e0_ph;
|
|
i_e1_ph := e1_ph;
|
|
i_e2_ph := e2_ph;
|
|
i_e3_ph := e3_ph;
|
|
i_l0_high := l0_high;
|
|
i_l1_high := l1_high;
|
|
i_g0_high := g0_high;
|
|
i_g1_high := g1_high;
|
|
i_g2_high := g2_high;
|
|
i_g3_high := g3_high;
|
|
i_e0_high := e0_high;
|
|
i_e1_high := e1_high;
|
|
i_e2_high := e2_high;
|
|
i_e3_high := e3_high;
|
|
i_l0_low := l0_low;
|
|
i_l1_low := l1_low;
|
|
i_g0_low := g0_low;
|
|
i_g1_low := g1_low;
|
|
i_g2_low := g2_low;
|
|
i_g3_low := g3_low;
|
|
i_e0_low := e0_low;
|
|
i_e1_low := e1_low;
|
|
i_e2_low := e2_low;
|
|
i_e3_low := e3_low;
|
|
i_l0_initial := l0_initial;
|
|
i_l1_initial := l1_initial;
|
|
i_g0_initial := g0_initial;
|
|
i_g1_initial := g1_initial;
|
|
i_g2_initial := g2_initial;
|
|
i_g3_initial := g3_initial;
|
|
i_e0_initial := e0_initial;
|
|
i_e1_initial := e1_initial;
|
|
i_e2_initial := e2_initial;
|
|
i_e3_initial := e3_initial;
|
|
i_l0_mode := translate_string(l0_mode);
|
|
i_l1_mode := translate_string(l1_mode);
|
|
i_g0_mode := translate_string(g0_mode);
|
|
i_g1_mode := translate_string(g1_mode);
|
|
i_g2_mode := translate_string(g2_mode);
|
|
i_g3_mode := translate_string(g3_mode);
|
|
i_e0_mode := translate_string(e0_mode);
|
|
i_e1_mode := translate_string(e1_mode);
|
|
i_e2_mode := translate_string(e2_mode);
|
|
i_e3_mode := translate_string(e3_mode);
|
|
|
|
end if; -- user to advanced conversion.
|
|
|
|
m_initial_val <= i_m_initial;
|
|
n_val_tmp <= i_n;
|
|
m_val_tmp <= i_m;
|
|
|
|
if (i_m = 1) then
|
|
m_mode_val <= "bypass";
|
|
end if;
|
|
if (i_n = 1) then
|
|
n_mode_val <= "bypass";
|
|
end if;
|
|
|
|
-- NOTE: m_time_delay (vco time delay) not supported for external
|
|
-- feedback mode
|
|
-- in feedback mode, m_time_delay = delay of feedback loop tap
|
|
|
|
m_time_delay_val <= i_m_time_delay;
|
|
n_time_delay_val <= i_n_time_delay;
|
|
|
|
m_ph_val <= i_m_ph;
|
|
|
|
m2_val <= m2;
|
|
n2_val <= n2;
|
|
if (m2 = 1) then
|
|
m2_mode_val <= "bypass";
|
|
end if;
|
|
if (n2 = 1) then
|
|
n2_mode_val <= "bypass";
|
|
end if;
|
|
|
|
if (skip_vco = "on") then
|
|
m_val_tmp <= 1;
|
|
m_initial_val <= 1;
|
|
m_time_delay_val <= 0;
|
|
m_ph_val <= 0;
|
|
end if;
|
|
|
|
l0_ph_val <= i_l0_ph;
|
|
l1_ph_val <= i_l1_ph;
|
|
g0_ph_val <= i_g0_ph;
|
|
g1_ph_val <= i_g1_ph;
|
|
g2_ph_val <= i_g2_ph;
|
|
g3_ph_val <= i_g3_ph;
|
|
e0_ph_val <= i_e0_ph;
|
|
e1_ph_val <= i_e1_ph;
|
|
e2_ph_val <= i_e2_ph;
|
|
e3_ph_val <= i_e3_ph;
|
|
|
|
l0_initial_val <= i_l0_initial;
|
|
l0_high_val <= i_l0_high;
|
|
l0_low_val <= i_l0_low;
|
|
l0_mode_val <= i_l0_mode;
|
|
l0_time_delay_val <= i_l0_time_delay;
|
|
|
|
l1_initial_val <= i_l1_initial;
|
|
l1_high_val <= i_l1_high;
|
|
l1_low_val <= i_l1_low;
|
|
l1_mode_val <= i_l1_mode;
|
|
l1_time_delay_val <= i_l1_time_delay;
|
|
|
|
g0_initial_val <= i_g0_initial;
|
|
g0_high_val <= i_g0_high;
|
|
g0_low_val <= i_g0_low;
|
|
g0_mode_val <= i_g0_mode;
|
|
g0_time_delay_val <= i_g0_time_delay;
|
|
|
|
g1_initial_val <= i_g1_initial;
|
|
g1_high_val <= i_g1_high;
|
|
g1_low_val <= i_g1_low;
|
|
g1_mode_val <= i_g1_mode;
|
|
g1_time_delay_val <= i_g1_time_delay;
|
|
|
|
g2_initial_val <= i_g2_initial;
|
|
g2_high_val <= i_g2_high;
|
|
g2_low_val <= i_g2_low;
|
|
g2_mode_val <= i_g2_mode;
|
|
g2_time_delay_val <= i_g2_time_delay;
|
|
|
|
g3_initial_val <= i_g3_initial;
|
|
g3_high_val <= i_g3_high;
|
|
g3_low_val <= i_g3_low;
|
|
g3_mode_val <= i_g3_mode;
|
|
g3_time_delay_val <= i_g3_time_delay;
|
|
|
|
if (scan_chain = "long") then
|
|
e0_initial_val <= i_e0_initial;
|
|
e0_high_val <= i_e0_high;
|
|
e0_low_val <= i_e0_low;
|
|
e0_mode_val <= i_e0_mode;
|
|
e0_time_delay_val <= i_e0_time_delay;
|
|
|
|
e1_initial_val <= i_e1_initial;
|
|
e1_high_val <= i_e1_high;
|
|
e1_low_val <= i_e1_low;
|
|
e1_mode_val <= i_e1_mode;
|
|
e1_time_delay_val <= i_e1_time_delay;
|
|
|
|
e2_initial_val <= i_e2_initial;
|
|
e2_high_val <= i_e2_high;
|
|
e2_low_val <= i_e2_low;
|
|
e2_mode_val <= i_e2_mode;
|
|
e2_time_delay_val <= i_e2_time_delay;
|
|
|
|
e3_initial_val <= i_e3_initial;
|
|
e3_high_val <= i_e3_high;
|
|
e3_low_val <= i_e3_low;
|
|
e3_mode_val <= i_e3_mode;
|
|
e3_time_delay_val <= i_e3_time_delay;
|
|
|
|
scan_chain_length <= EGPP_SCAN_CHAIN;
|
|
end if;
|
|
init := false;
|
|
done_with_param_calc <= true;
|
|
elsif (transfer'event and transfer = '1') then
|
|
reconfig_err <= false;
|
|
ASSERT false REPORT "Reconfiguring PLL" severity note;
|
|
if (scan_chain = "long") then
|
|
-- cntr e3
|
|
delay_chain := scan_data(287 downto 284);
|
|
if (scan_data(273) = '1') then
|
|
e3_mode_val <= "bypass";
|
|
if (scan_data(283) = '1') then
|
|
e3_mode_val <= " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the E3 counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (scan_data(283) = '1') then
|
|
e3_mode_val <= " odd";
|
|
else
|
|
e3_mode_val <= " even";
|
|
end if;
|
|
high := scan_data(272 downto 264);
|
|
low := scan_data(282 downto 274);
|
|
e3_low_val <= alt_conv_integer(low);
|
|
e3_high_val <= alt_conv_integer(high);
|
|
-- count value of 0 is actually 512
|
|
if (alt_conv_integer(high) = 0) then
|
|
e3_high_val <= 512;
|
|
end if;
|
|
if (alt_conv_integer(low) = 0) then
|
|
e3_low_val <= 512;
|
|
end if;
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
e3_time_delay_val <= delay_val;
|
|
|
|
-- cntr e2
|
|
delay_chain := scan_data(263 downto 260);
|
|
if (scan_data(249) = '1') then
|
|
e2_mode_val <= "bypass";
|
|
if (scan_data(259) = '1') then
|
|
e2_mode_val <= " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the E2 counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (scan_data(259) = '1') then
|
|
e2_mode_val <= " odd";
|
|
else
|
|
e2_mode_val <= " even";
|
|
end if;
|
|
high := scan_data(248 downto 240);
|
|
low := scan_data(258 downto 250);
|
|
e2_low_val <= alt_conv_integer(low);
|
|
e2_high_val <= alt_conv_integer(high);
|
|
if (alt_conv_integer(high) = 0) then
|
|
e2_high_val <= 512;
|
|
end if;
|
|
if (alt_conv_integer(low) = 0) then
|
|
e2_low_val <= 512;
|
|
end if;
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
e2_time_delay_val <= delay_val;
|
|
|
|
-- cntr e1
|
|
delay_chain := scan_data(239 downto 236);
|
|
if (scan_data(225) = '1') then
|
|
e1_mode_val <= "bypass";
|
|
if (scan_data(235) = '1') then
|
|
e1_mode_val <= " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the E1 counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (scan_data(235) = '1') then
|
|
e1_mode_val <= " odd";
|
|
else
|
|
e1_mode_val <= " even";
|
|
end if;
|
|
high := scan_data(224 downto 216);
|
|
low := scan_data(234 downto 226);
|
|
e1_low_val <= alt_conv_integer(low);
|
|
e1_high_val <= alt_conv_integer(high);
|
|
if (alt_conv_integer(high) = 0) then
|
|
e1_high_val <= 512;
|
|
end if;
|
|
if (alt_conv_integer(low) = 0) then
|
|
e1_low_val <= 512;
|
|
end if;
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
e1_time_delay_val <= delay_val;
|
|
|
|
-- cntr e0
|
|
delay_chain := scan_data(215 downto 212);
|
|
if (scan_data(201) = '1') then
|
|
e0_mode_val <= "bypass";
|
|
if (scan_data(211) = '1') then
|
|
e0_mode_val <= " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the E0 counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (scan_data(211) = '1') then
|
|
e0_mode_val <= " odd";
|
|
else
|
|
e0_mode_val <= " even";
|
|
end if;
|
|
high := scan_data(200 downto 192);
|
|
low := scan_data(210 downto 202);
|
|
e0_low_val <= alt_conv_integer(low);
|
|
e0_high_val <= alt_conv_integer(high);
|
|
if (alt_conv_integer(high) = 0) then
|
|
e0_high_val <= 512;
|
|
end if;
|
|
if (alt_conv_integer(low) = 0) then
|
|
e0_low_val <= 512;
|
|
end if;
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
e0_time_delay_val <= delay_val;
|
|
|
|
end if;
|
|
-- cntr l1
|
|
delay_chain := scan_data(191 downto 188);
|
|
if (scan_data(177) = '1') then
|
|
l1_mode_val <= "bypass";
|
|
if (scan_data(187) = '1') then
|
|
l1_mode_val <= " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the L1 counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (scan_data(187) = '1') then
|
|
l1_mode_val <= " odd";
|
|
else
|
|
l1_mode_val <= " even";
|
|
end if;
|
|
high := scan_data(176 downto 168);
|
|
low := scan_data(186 downto 178);
|
|
l1_low_val <= alt_conv_integer(low);
|
|
l1_high_val <= alt_conv_integer(high);
|
|
if (alt_conv_integer(high) = 0) then
|
|
l1_high_val <= 512;
|
|
end if;
|
|
if (alt_conv_integer(low) = 0) then
|
|
l1_low_val <= 512;
|
|
end if;
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
l1_time_delay_val <= delay_val;
|
|
|
|
-- cntr l0
|
|
delay_chain := scan_data(167 downto 164);
|
|
if (scan_data(153) = '1') then
|
|
l0_mode_val <= "bypass";
|
|
if (scan_data(163) = '1') then
|
|
l0_mode_val <= " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the L0 counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (scan_data(163) = '1') then
|
|
l0_mode_val <= " odd";
|
|
else
|
|
l0_mode_val <= " even";
|
|
end if;
|
|
high := scan_data(152 downto 144);
|
|
low := scan_data(162 downto 154);
|
|
l0_low_val <= alt_conv_integer(low);
|
|
l0_high_val <= alt_conv_integer(high);
|
|
if (alt_conv_integer(high) = 0) then
|
|
l0_high_val <= 512;
|
|
end if;
|
|
if (alt_conv_integer(low) = 0) then
|
|
l0_low_val <= 512;
|
|
end if;
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
l0_time_delay_val <= delay_val;
|
|
|
|
-- cntr g3
|
|
delay_chain := scan_data(143 downto 140);
|
|
if (scan_data(129) = '1') then
|
|
g3_mode_val <= "bypass";
|
|
if (scan_data(139) = '1') then
|
|
g3_mode_val <= " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the G3 counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (scan_data(139) = '1') then
|
|
g3_mode_val <= " odd";
|
|
else
|
|
g3_mode_val <= " even";
|
|
end if;
|
|
high := scan_data(128 downto 120);
|
|
low := scan_data(138 downto 130);
|
|
g3_low_val <= alt_conv_integer(low);
|
|
g3_high_val <= alt_conv_integer(high);
|
|
if (alt_conv_integer(high) = 0) then
|
|
g3_high_val <= 512;
|
|
end if;
|
|
if (alt_conv_integer(low) = 0) then
|
|
g3_low_val <= 512;
|
|
end if;
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
g3_time_delay_val <= delay_val;
|
|
|
|
-- cntr g2
|
|
delay_chain := scan_data(119 downto 116);
|
|
if (scan_data(105) = '1') then
|
|
g2_mode_val <= "bypass";
|
|
if (scan_data(115) = '1') then
|
|
g2_mode_val <= " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the G2 counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (scan_data(115) = '1') then
|
|
g2_mode_val <= " odd";
|
|
else
|
|
g2_mode_val <= " even";
|
|
end if;
|
|
high := scan_data(104 downto 96);
|
|
low := scan_data(114 downto 106);
|
|
g2_low_val <= alt_conv_integer(low);
|
|
g2_high_val <= alt_conv_integer(high);
|
|
if (alt_conv_integer(high) = 0) then
|
|
g2_high_val <= 512;
|
|
end if;
|
|
if (alt_conv_integer(low) = 0) then
|
|
g2_low_val <= 512;
|
|
end if;
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
g2_time_delay_val <= delay_val;
|
|
|
|
-- cntr g1
|
|
delay_chain := scan_data(95 downto 92);
|
|
if (scan_data(81) = '1') then
|
|
g1_mode_val <= "bypass";
|
|
if (scan_data(91) = '1') then
|
|
g1_mode_val <= " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the G1 counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (scan_data(91) = '1') then
|
|
g1_mode_val <= " odd";
|
|
else
|
|
g1_mode_val <= " even";
|
|
end if;
|
|
high := scan_data(80 downto 72);
|
|
low := scan_data(90 downto 82);
|
|
g1_low_val <= alt_conv_integer(low);
|
|
g1_high_val <= alt_conv_integer(high);
|
|
if (alt_conv_integer(high) = 0) then
|
|
g1_high_val <= 512;
|
|
end if;
|
|
if (alt_conv_integer(low) = 0) then
|
|
g1_low_val <= 512;
|
|
end if;
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
g1_time_delay_val <= delay_val;
|
|
|
|
-- cntr g0
|
|
delay_chain := scan_data(71 downto 68);
|
|
if (scan_data(57) = '1') then
|
|
g0_mode_val <= "bypass";
|
|
if (scan_data(67) = '1') then
|
|
g0_mode_val <= " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the G0 counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (scan_data(67) = '1') then
|
|
g0_mode_val <= " odd";
|
|
else
|
|
g0_mode_val <= " even";
|
|
end if;
|
|
high := scan_data(56 downto 48);
|
|
low := scan_data(66 downto 58);
|
|
g0_low_val <= alt_conv_integer(low);
|
|
g0_high_val <= alt_conv_integer(high);
|
|
if (alt_conv_integer(high) = 0) then
|
|
g0_high_val <= 512;
|
|
end if;
|
|
if (alt_conv_integer(low) = 0) then
|
|
g0_low_val <= 512;
|
|
end if;
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
g0_time_delay_val <= delay_val;
|
|
|
|
-- cntr M
|
|
is_error := false;
|
|
-- 'low' contains modulus for m_cntr(spread_spectrum disabled)
|
|
low := scan_data(32 downto 24);
|
|
m_val_tmp <= alt_conv_integer(low);
|
|
if (scan_data(33) /= '1') then
|
|
if (alt_conv_integer(low) = 1) then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Illegal 1 value for M counter. Instead, M counter should be BYPASSED. Reconfiguration may not work." severity warning;
|
|
elsif (alt_conv_integer(low) = 0) then
|
|
m_val_tmp <= 512;
|
|
end if;
|
|
if (not is_error) then
|
|
if (m_mode_val = "bypass") then
|
|
ASSERT false REPORT "M counter switched from BYPASS mode to enabled (M modulus = " &int2str(alt_conv_integer(low))& "). PLL may lose lock." severity warning;
|
|
else
|
|
write (buf, string'(" M modulus = "));
|
|
write (buf, alt_conv_integer(low));
|
|
writeline (output, buf);
|
|
end if;
|
|
m_mode_val <= " ";
|
|
end if;
|
|
elsif (scan_data(33) = '1') then
|
|
if (scan_data(24) /= '0') then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Illegal value for M counter in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work." severity warning;
|
|
else
|
|
if (m_mode_val /= "bypass") then
|
|
ASSERT false REPORT "M counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
|
|
end if;
|
|
write (buf, string'(" M modulus = "));
|
|
write (buf, 1);
|
|
writeline (output, buf);
|
|
m_val_tmp <= 1;
|
|
m_mode_val <= "bypass";
|
|
end if;
|
|
end if;
|
|
|
|
if (skip_vco = "on") then
|
|
m_val_tmp <= 1;
|
|
ASSERT FALSE REPORT "VCO is bypassed, setting M modulus = 1, M time delay = 0" severity note;
|
|
end if;
|
|
|
|
-- cntr M2
|
|
if (ss > 0) then
|
|
is_error := false;
|
|
low := scan_data(42 downto 34);
|
|
m2_val <= alt_conv_integer(low);
|
|
if (scan_data(43) /= '1') then
|
|
if (alt_conv_integer(low) = 1) then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Illegal 1 value for M2 counter. Instead, M counter should be BYPASSED. Reconfiguration may not work." severity warning;
|
|
elsif (alt_conv_integer(low) = 0) then
|
|
m2_val <= 512;
|
|
end if;
|
|
if (not is_error) then
|
|
if (m2_mode_val = "bypass") then
|
|
ASSERT false REPORT "M2 counter switched from BYPASS mode to enabled (M2 modulus = " &int2str(alt_conv_integer(low))& "). PLL may lose lock." severity warning;
|
|
else
|
|
write (buf, string'(" M2 modulus = "));
|
|
write (buf, alt_conv_integer(low));
|
|
writeline (output, buf);
|
|
end if;
|
|
m2_mode_val <= " ";
|
|
end if;
|
|
elsif (scan_data(43) = '1') then
|
|
if (scan_data(34) /= '0') then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Illegal value for M2 counter in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work." severity warning;
|
|
else
|
|
if (m2_mode_val /= "bypass") then
|
|
ASSERT false REPORT "M2 counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
|
|
end if;
|
|
write (buf, string'(" M2 modulus = "));
|
|
write (buf, 1);
|
|
writeline (output, buf);
|
|
m2_val <= 1;
|
|
m2_mode_val <= "bypass";
|
|
end if;
|
|
end if;
|
|
if (m_mode_val /= m2_mode_val) then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Incompatible modes for M1/M2 counters. Either both should be BYPASSED or both NON-BYPASSED. Reconfiguration may not work." severity warning;
|
|
end if;
|
|
end if;
|
|
|
|
delay_chain := scan_data(47 downto 44);
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
m_time_delay_val <= delay_val;
|
|
if (skip_vco = "on") then
|
|
m_time_delay_val <= 0;
|
|
delay_val := 0;
|
|
end if;
|
|
write (buf, string'(" M time delay = "));
|
|
write (buf, delay_val);
|
|
writeline (output, buf);
|
|
|
|
-- cntr N
|
|
is_error := false;
|
|
-- 'low' contains modulus for n_cntr(spread_spectrum disabled)
|
|
low := scan_data(8 downto 0);
|
|
n_val_tmp <= alt_conv_integer(low);
|
|
if (scan_data(9) /= '1') then
|
|
if (alt_conv_integer(low) = 1) then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Illegal 1 value for N counter. Instead, N counter should be BYPASSED. Reconfiguration may not work." severity warning;
|
|
elsif (alt_conv_integer(low) = 0) then
|
|
n_val_tmp <= 512;
|
|
write (buf, string'(" N modulus = "));
|
|
write (buf, 512);
|
|
writeline (output, buf);
|
|
else
|
|
write (buf, string'(" N modulus = "));
|
|
write (buf, alt_conv_integer(low));
|
|
writeline (output, buf);
|
|
end if;
|
|
if (not is_error) then
|
|
if (n_mode_val = "bypass") then
|
|
ASSERT false REPORT "N Counter switched from BYPASS mode to enabled (N modulus = " &int2str(alt_conv_integer(low))& "). PLL may lose lock." severity warning;
|
|
else
|
|
write (buf, string'(" N modulus = "));
|
|
write (buf, alt_conv_integer(low));
|
|
writeline (output, buf);
|
|
end if;
|
|
n_mode_val <= " ";
|
|
end if;
|
|
elsif (scan_data(9) = '1') then
|
|
if (scan_data(0) /= '0') then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Illegal value for N counter in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work." severity warning;
|
|
else
|
|
if (n_mode_val /= "bypass") then
|
|
ASSERT false REPORT "N counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
|
|
end if;
|
|
write (buf, string'(" N modulus = "));
|
|
write (buf, 1);
|
|
writeline (output, buf);
|
|
n_val_tmp <= 1;
|
|
n_mode_val <= "bypass";
|
|
end if;
|
|
end if;
|
|
|
|
-- cntr N2
|
|
if (ss > 0) then
|
|
is_error := false;
|
|
low := scan_data(18 downto 10);
|
|
n2_val <= alt_conv_integer(low);
|
|
if (scan_data(19) /= '1') then
|
|
if (alt_conv_integer(low) = 1) then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Illegal 1 value for N2 counter. Instead, N counter should be BYPASSED. Reconfiguration may not work." severity warning;
|
|
elsif (alt_conv_integer(low) = 0) then
|
|
n2_val <= 512;
|
|
end if;
|
|
if (not is_error) then
|
|
if (n2_mode_val = "bypass") then
|
|
ASSERT false REPORT "N2 counter switched from BYPASS mode to enabled (N2 modulus = " &int2str(alt_conv_integer(low))& "). PLL may lose lock." severity warning;
|
|
else
|
|
write (buf, string'(" N2 modulus = "));
|
|
write (buf, alt_conv_integer(low));
|
|
writeline (output, buf);
|
|
end if;
|
|
n2_mode_val <= " ";
|
|
end if;
|
|
elsif (scan_data(19) = '1') then
|
|
if (scan_data(10) /= '0') then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Illegal value for N2 counter in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work." severity warning;
|
|
else
|
|
if (n2_mode_val /= "bypass") then
|
|
ASSERT false REPORT "N2 counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
|
|
end if;
|
|
write (buf, string'(" N2 modulus = "));
|
|
write (buf, 1);
|
|
writeline (output, buf);
|
|
n2_val <= 1;
|
|
n2_mode_val <= "bypass";
|
|
end if;
|
|
end if;
|
|
if (n_mode_val /= n2_mode_val) then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Incompatible modes for N1/N2 counters. Either both should be BYPASSED or both NON-BYPASSED. Reconfiguration may not work." severity warning;
|
|
end if;
|
|
end if;
|
|
|
|
delay_chain := scan_data(23 downto 20);
|
|
delay_val := alt_conv_integer(delay_chain);
|
|
delay_val := delay_val * 250;
|
|
if (delay_val > 3000) then
|
|
delay_val := 3000;
|
|
end if;
|
|
n_time_delay_val <= delay_val;
|
|
write (buf, string'(" N time delay = "));
|
|
write (buf, delay_val);
|
|
writeline (output, buf);
|
|
|
|
else
|
|
if (scan_chain = "long") then
|
|
write (buf, string'(" E3 high = "));
|
|
write (buf, e3_high_val);
|
|
write (buf, string'(" , E3 low = "));
|
|
write (buf, e3_low_val);
|
|
write (buf, string'(" , E3 mode = "));
|
|
write (buf, e3_mode_val);
|
|
write (buf, string'(" , E3 time delay = "));
|
|
write (buf, e3_time_delay_val);
|
|
writeline(output, buf);
|
|
|
|
write (buf, string'(" E2 high = "));
|
|
write (buf, e2_high_val);
|
|
write (buf, string'(" , E2 low = "));
|
|
write (buf, e2_low_val);
|
|
write (buf, string'(" , E2 mode = "));
|
|
write (buf, e2_mode_val);
|
|
write (buf, string'(" , E2 time delay = "));
|
|
write (buf, e2_time_delay_val);
|
|
writeline(output, buf);
|
|
|
|
write (buf, string'(" E1 high = "));
|
|
write (buf, e1_high_val);
|
|
write (buf, string'(" , E1 low = "));
|
|
write (buf, e1_low_val);
|
|
write (buf, string'(" , E1 mode = "));
|
|
write (buf, e1_mode_val);
|
|
write (buf, string'(" , E1 time delay = "));
|
|
write (buf, e1_time_delay_val);
|
|
writeline(output, buf);
|
|
|
|
write (buf, string'(" E0 high = "));
|
|
write (buf, e0_high_val);
|
|
write (buf, string'(" , E0 low = "));
|
|
write (buf, e0_low_val);
|
|
write (buf, string'(" , E0 mode = "));
|
|
write (buf, e0_mode_val);
|
|
write (buf, string'(" , E0 time delay = "));
|
|
write (buf, e0_time_delay_val);
|
|
writeline(output, buf);
|
|
end if;
|
|
|
|
write (buf, string'(" L1 high = "));
|
|
write (buf, l1_high_val);
|
|
write (buf, string'(" , L1 low = "));
|
|
write (buf, l1_low_val);
|
|
write (buf, string'(" , L1 mode = "));
|
|
write (buf, l1_mode_val);
|
|
write (buf, string'(" , L1 time delay = "));
|
|
write (buf, l1_time_delay_val);
|
|
writeline(output, buf);
|
|
|
|
write (buf, string'(" L0 high = "));
|
|
write (buf, l0_high_val);
|
|
write (buf, string'(" , L0 low = "));
|
|
write (buf, l0_low_val);
|
|
write (buf, string'(" , L0 mode = "));
|
|
write (buf, l0_mode_val);
|
|
write (buf, string'(" , L0 time delay = "));
|
|
write (buf, l0_time_delay_val);
|
|
writeline(output, buf);
|
|
|
|
write (buf, string'(" G3 high = "));
|
|
write (buf, g3_high_val);
|
|
write (buf, string'(" , G3 low = "));
|
|
write (buf, g3_low_val);
|
|
write (buf, string'(" , G3 mode = "));
|
|
write (buf, g3_mode_val);
|
|
write (buf, string'(" , G3 time delay = "));
|
|
write (buf, g3_time_delay_val);
|
|
writeline(output, buf);
|
|
|
|
write (buf, string'(" G2 high = "));
|
|
write (buf, g2_high_val);
|
|
write (buf, string'(" , G2 low = "));
|
|
write (buf, g2_low_val);
|
|
write (buf, string'(" , G2 mode = "));
|
|
write (buf, g2_mode_val);
|
|
write (buf, string'(" , G2 time delay = "));
|
|
write (buf, g2_time_delay_val);
|
|
writeline(output, buf);
|
|
|
|
write (buf, string'(" G1 high = "));
|
|
write (buf, g1_high_val);
|
|
write (buf, string'(" , G1 low = "));
|
|
write (buf, g1_low_val);
|
|
write (buf, string'(" , G1 mode = "));
|
|
write (buf, g1_mode_val);
|
|
write (buf, string'(" , G1 time delay = "));
|
|
write (buf, g1_time_delay_val);
|
|
writeline(output, buf);
|
|
|
|
write (buf, string'(" G0 high = "));
|
|
write (buf, g0_high_val);
|
|
write (buf, string'(" , G0 low = "));
|
|
write (buf, g0_low_val);
|
|
write (buf, string'(" , G0 mode = "));
|
|
write (buf, g0_mode_val);
|
|
write (buf, string'(" , G0 time delay = "));
|
|
write (buf, g0_time_delay_val);
|
|
writeline(output, buf);
|
|
|
|
end if;
|
|
end process;
|
|
|
|
process (schedule_vco, areset_ipd, ena_ipd, pfdena_ipd, refclk, fbclk, inclk0_ipd, inclk1_ipd, clkswitch_ipd, done_with_param_calc)
|
|
variable sched_time : time := 0 ps;
|
|
|
|
TYPE time_array is ARRAY (0 to 7) of time;
|
|
variable init : boolean := true;
|
|
variable refclk_period : time;
|
|
variable primary_clock_frequency : time;
|
|
variable m_times_vco_period : time;
|
|
variable new_m_times_vco_period : time;
|
|
|
|
variable phase_shift : time_array := (OTHERS => 0 ps);
|
|
variable last_phase_shift : time_array := (OTHERS => 0 ps);
|
|
|
|
variable l_index : integer := 1;
|
|
variable cycle_to_adjust : integer := 0;
|
|
|
|
variable stop_vco : boolean := false;
|
|
|
|
variable locked_tmp : std_logic := '0';
|
|
variable pll_is_locked : boolean := false;
|
|
variable pll_about_to_lock : boolean := false;
|
|
variable cycles_to_lock : integer := 0;
|
|
variable cycles_to_unlock : integer := 0;
|
|
|
|
variable got_first_refclk : boolean := false;
|
|
variable got_second_refclk : boolean := false;
|
|
variable got_first_fbclk : boolean := false;
|
|
|
|
variable refclk_time : time := 0 ps;
|
|
variable fbclk_time : time := 0 ps;
|
|
variable first_fbclk_time : time := 0 ps;
|
|
|
|
variable fbclk_period : time := 0 ps;
|
|
|
|
variable first_schedule : boolean := true;
|
|
variable schedule_offset : boolean := true;
|
|
|
|
variable vco_val : std_logic := '0';
|
|
variable vco_period_was_phase_adjusted : boolean := false;
|
|
variable phase_adjust_was_scheduled : boolean := false;
|
|
|
|
variable loop_xplier : integer;
|
|
variable loop_initial : integer := 0;
|
|
variable loop_ph : integer := 0;
|
|
variable loop_time_delay : integer := 0;
|
|
|
|
variable initial_delay : time := 0 ps;
|
|
variable vco_per : time;
|
|
variable tmp_rem : integer;
|
|
variable my_rem : integer;
|
|
variable fbk_phase : integer := 0;
|
|
|
|
variable pull_back_ext_fbk_cntr : integer := 0;
|
|
variable pull_back_M : integer := 0;
|
|
variable total_pull_back : integer := 0;
|
|
variable fbk_delay : integer := 0;
|
|
|
|
variable offset : time := 0 ps;
|
|
|
|
variable tmp_vco_per : integer := 0;
|
|
variable high_time : time;
|
|
variable low_time : time;
|
|
|
|
variable got_refclk_posedge : boolean := false;
|
|
variable got_fbclk_posedge : boolean := false;
|
|
variable inclk_out_of_range : boolean := false;
|
|
variable no_warn : boolean := false;
|
|
variable init_clks : boolean := true;
|
|
variable ext_fbk_cntr_modulus : integer := 1;
|
|
variable pll_is_in_reset : boolean := false;
|
|
|
|
-- clkswitch variables
|
|
variable other_clock_value : std_logic := '0';
|
|
variable other_clock_last_value : std_logic;
|
|
variable current_clock : string(1 to 6) := primary_clock;
|
|
variable clk0_count, clk1_count : integer := 0;
|
|
variable clk0_is_bad, clk1_is_bad : std_logic := '0';
|
|
variable primary_clk_is_bad : boolean := false;
|
|
variable current_clk_is_bad : boolean := false;
|
|
variable got_curr_clk_falling_edge_after_clkswitch : boolean := false;
|
|
variable switch_over_count : integer := 0;
|
|
variable active_clock : std_logic := '0';
|
|
variable external_switch : boolean := false;
|
|
|
|
begin
|
|
if (init and done_with_param_calc) then
|
|
if (pll_type = "fast") then
|
|
locked_tmp := '1';
|
|
end if;
|
|
m_val <= m_val_tmp;
|
|
n_val <= n_val_tmp;
|
|
-- jump-start the VCO
|
|
-- add 1 ps delay to ensure all signals are updated to initial
|
|
-- values
|
|
schedule_vco <= transport not schedule_vco after 1 ps;
|
|
|
|
init := false;
|
|
end if;
|
|
|
|
-- merged from separate process
|
|
if (now = 0 ps) then
|
|
if (current_clock = "inclk1") then
|
|
active_clock := '1';
|
|
end if;
|
|
end if;
|
|
if (clkswitch_ipd'event and clkswitch_ipd = '1') then
|
|
external_switch := true;
|
|
end if;
|
|
-- save the current inclk event value
|
|
if (inclk0_ipd'event) then
|
|
if (current_clock /= "inclk0") then
|
|
other_clock_value := inclk0_ipd;
|
|
end if;
|
|
end if;
|
|
if (inclk1_ipd'event) then
|
|
if (current_clock /= "inclk1") then
|
|
other_clock_value := inclk1_ipd;
|
|
end if;
|
|
end if;
|
|
|
|
-- check if either input clk is bad
|
|
if (inclk0_ipd'event and inclk0_ipd = '1') then
|
|
clk0_count := clk0_count + 1;
|
|
clk0_is_bad := '0';
|
|
if (current_clock = "inclk0") then
|
|
current_clk_is_bad := false;
|
|
end if;
|
|
clk1_count := 0;
|
|
if (clk0_count > 2) then
|
|
-- no event on other clk for 2 cycles
|
|
clk1_is_bad := '1';
|
|
if (current_clock = "inclk1") then
|
|
current_clk_is_bad := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (inclk1_ipd'event and inclk1_ipd = '1') then
|
|
clk1_count := clk1_count + 1;
|
|
clk1_is_bad := '0';
|
|
if (current_clock = "inclk1") then
|
|
current_clk_is_bad := false;
|
|
end if;
|
|
clk0_count := 0;
|
|
if (clk1_count > 2) then
|
|
-- no event on other clk for 2 cycles
|
|
clk0_is_bad := '1';
|
|
if (current_clock = "inclk0") then
|
|
current_clk_is_bad := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- check if the bad clk is the primary clock
|
|
if ((primary_clock = "inclk0" and clk0_is_bad = '1') or (primary_clock = "inclk1" and clk1_is_bad = '1')) then
|
|
primary_clk_is_bad := true;
|
|
else
|
|
primary_clk_is_bad := false;
|
|
end if;
|
|
|
|
-- actual switching
|
|
if (inclk0_ipd'event and current_clock = "inclk0") then
|
|
if (external_switch) then
|
|
if (not got_curr_clk_falling_edge_after_clkswitch) then
|
|
if (inclk0_ipd = '0') then
|
|
got_curr_clk_falling_edge_after_clkswitch := true;
|
|
end if;
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
else
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
end if;
|
|
if (inclk1_ipd'event and current_clock = "inclk1") then
|
|
if (external_switch) then
|
|
if (not got_curr_clk_falling_edge_after_clkswitch) then
|
|
if (inclk1_ipd = '0') then
|
|
got_curr_clk_falling_edge_after_clkswitch := true;
|
|
end if;
|
|
clkin <= transport inclk1_ipd;
|
|
end if;
|
|
else
|
|
clkin <= transport inclk1_ipd;
|
|
end if;
|
|
end if;
|
|
if (inclk0_ipd'event or inclk1_ipd'event) then
|
|
if ( (other_clock_value = '1') and
|
|
(other_clock_value /= other_clock_last_value) and
|
|
(switch_over_on_lossclk = "on") and
|
|
(enable_switch_over_counter = "on") and
|
|
(primary_clk_is_bad) ) then
|
|
switch_over_count := switch_over_count + 1;
|
|
end if;
|
|
if ((other_clock_value = '0') and (other_clock_value /= other_clock_last_value)) then
|
|
if (external_switch and (got_curr_clk_falling_edge_after_clkswitch or current_clk_is_bad)) or (switch_over_on_lossclk = "on" and primary_clk_is_bad and (enable_switch_over_counter = "off" or switch_over_count = switch_over_counter)) then
|
|
got_curr_clk_falling_edge_after_clkswitch := false;
|
|
if (current_clock = "inclk0") then
|
|
current_clock := "inclk1";
|
|
else
|
|
current_clock := "inclk0";
|
|
end if;
|
|
active_clock := not active_clock;
|
|
switch_over_count := 0;
|
|
external_switch := false;
|
|
current_clk_is_bad := false;
|
|
end if;
|
|
end if;
|
|
other_clock_last_value := other_clock_value;
|
|
end if;
|
|
|
|
-- schedule outputs
|
|
clkbad(0) <= clk0_is_bad;
|
|
clkbad(1) <= clk1_is_bad;
|
|
if (switch_over_on_lossclk = "on" and clkswitch_ipd /= '1') then
|
|
if (primary_clk_is_bad) then
|
|
-- assert clkloss
|
|
clkloss <= '1';
|
|
else
|
|
clkloss <= '0';
|
|
end if;
|
|
else
|
|
clkloss <= clkswitch_ipd;
|
|
end if;
|
|
activeclock <= active_clock;
|
|
|
|
-- end -- clkswitch
|
|
|
|
if (schedule_vco'event) then
|
|
if (init_clks) then
|
|
if (primary_clock = "inclk0") then
|
|
refclk_period := inclk0_input_frequency * n_val * 1 ps;
|
|
primary_clock_frequency := inclk0_input_frequency * 1 ps;
|
|
elsif (primary_clock = "inclk1") then
|
|
refclk_period := inclk1_input_frequency * n_val * 1 ps;
|
|
primary_clock_frequency := inclk1_input_frequency * 1 ps;
|
|
end if;
|
|
|
|
m_times_vco_period := refclk_period;
|
|
new_m_times_vco_period := refclk_period;
|
|
init_clks := false;
|
|
end if;
|
|
sched_time := 0 ps;
|
|
for i in 0 to 7 loop
|
|
last_phase_shift(i) := phase_shift(i);
|
|
end loop;
|
|
cycle_to_adjust := 0;
|
|
l_index := 1;
|
|
m_times_vco_period := new_m_times_vco_period;
|
|
end if;
|
|
|
|
-- areset was asserted
|
|
if (areset_ipd'event and areset_ipd = '1') then
|
|
assert false report family_name & " PLL was reset" severity note;
|
|
end if;
|
|
|
|
-- areset deasserted
|
|
if (areset_ipd'event and areset_ipd = '0') then
|
|
if (scandataout_tmp = '1') then
|
|
sdataout_rst_trig <= transport not sdataout_rst_trig;
|
|
end if;
|
|
end if;
|
|
|
|
-- ena was deasserted
|
|
if (ena_ipd'event and ena_ipd = '0') then
|
|
assert false report family_name & " PLL was disabled" severity note;
|
|
end if;
|
|
|
|
if (schedule_vco'event and (areset_ipd = '1' or ena_ipd = '0' or stop_vco)) then
|
|
if (areset_ipd = '1') then
|
|
pll_is_in_reset := true;
|
|
end if;
|
|
|
|
-- drop VCO taps to 0
|
|
for i in 0 to 7 loop
|
|
vco_out(i) <= transport '0' after last_phase_shift(i);
|
|
phase_shift(i) := 0 ps;
|
|
last_phase_shift(i) := 0 ps;
|
|
end loop;
|
|
|
|
-- reset lock parameters
|
|
locked_tmp := '0';
|
|
if (pll_type = "fast") then
|
|
locked_tmp := '1';
|
|
end if;
|
|
pll_is_locked := false;
|
|
pll_about_to_lock := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
refclk_time := 0 ps;
|
|
got_first_fbclk := false;
|
|
fbclk_time := 0 ps;
|
|
first_fbclk_time := 0 ps;
|
|
fbclk_period := 0 ps;
|
|
|
|
first_schedule := true;
|
|
schedule_offset := true;
|
|
vco_val := '0';
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
|
|
elsif ((schedule_vco'event or ena_ipd'event or areset_ipd'event) and areset_ipd = '0' and ena_ipd = '1' and (not stop_vco) and (now > 0 ps)) then
|
|
|
|
-- note areset deassert time
|
|
-- note it as refclk_time to prevent false triggering
|
|
-- of stop_vco after areset
|
|
if (areset_ipd'event and areset_ipd = '0' and pll_is_in_reset) then
|
|
refclk_time := now;
|
|
pll_is_in_reset := false;
|
|
end if;
|
|
|
|
-- calculate loop_xplier : this will be different from m_val
|
|
-- in external_feedback_mode
|
|
loop_xplier := m_val;
|
|
loop_initial := m_initial_val - 1;
|
|
loop_ph := m_ph_val;
|
|
loop_time_delay := m_time_delay_val;
|
|
|
|
if (operation_mode = "external_feedback") then
|
|
if (ext_fbk_cntr_mode = "bypass") then
|
|
ext_fbk_cntr_modulus := 1;
|
|
else
|
|
ext_fbk_cntr_modulus := ext_fbk_cntr_high + ext_fbk_cntr_low;
|
|
end if;
|
|
|
|
loop_xplier := m_val * (ext_fbk_cntr_modulus);
|
|
loop_ph := ext_fbk_cntr_ph;
|
|
loop_initial := ext_fbk_cntr_initial - 1 + ((m_initial_val - 1) * (ext_fbk_cntr_modulus));
|
|
loop_time_delay := m_time_delay_val + ext_fbk_cntr_delay;
|
|
end if;
|
|
|
|
-- convert initial value to delay
|
|
initial_delay := (loop_initial * m_times_vco_period)/loop_xplier;
|
|
|
|
-- convert loop ph_tap to delay
|
|
my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
|
|
tmp_vco_per := (m_times_vco_period/1 ps) / loop_xplier;
|
|
if (my_rem /= 0) then
|
|
tmp_vco_per := tmp_vco_per + 1;
|
|
end if;
|
|
fbk_phase := (loop_ph * tmp_vco_per)/8;
|
|
|
|
if (operation_mode = "external_feedback") then
|
|
pull_back_ext_fbk_cntr := ext_fbk_cntr_delay + (ext_fbk_cntr_initial - 1) * (m_times_vco_period/loop_xplier)/1 ps + fbk_phase;
|
|
while (pull_back_ext_fbk_cntr > refclk_period/1 ps) loop
|
|
pull_back_ext_fbk_cntr := pull_back_ext_fbk_cntr - refclk_period/ 1 ps;
|
|
end loop;
|
|
pull_back_M := m_time_delay_val + (m_initial_val - 1) * (ext_fbk_cntr_modulus) * ((refclk_period/loop_xplier)/1 ps);
|
|
while (pull_back_M > refclk_period/1 ps) loop
|
|
pull_back_M := pull_back_M - refclk_period/ 1 ps;
|
|
end loop;
|
|
else
|
|
pull_back_ext_fbk_cntr := 0;
|
|
pull_back_M := initial_delay/1 ps + m_time_delay_val + fbk_phase;
|
|
end if;
|
|
|
|
total_pull_back := pull_back_M + pull_back_ext_fbk_cntr;
|
|
|
|
if (simulation_type = "timing") then
|
|
total_pull_back := total_pull_back + pll_compensation_delay;
|
|
end if;
|
|
while (total_pull_back > refclk_period/1 ps) loop
|
|
total_pull_back := total_pull_back - refclk_period/1 ps;
|
|
end loop;
|
|
|
|
if (total_pull_back > 0) then
|
|
offset := refclk_period - (total_pull_back * 1 ps);
|
|
end if;
|
|
if (operation_mode = "external_feedback") then
|
|
fbk_delay := pull_back_M;
|
|
if (simulation_type = "timing") then
|
|
fbk_delay := fbk_delay + pll_compensation_delay;
|
|
end if;
|
|
ext_fbk_delay <= transport (pull_back_ext_fbk_cntr - fbk_phase) after 1 ps;
|
|
else
|
|
fbk_delay := total_pull_back - fbk_phase;
|
|
if (fbk_delay < 0) then
|
|
offset := offset - (fbk_phase * 1 ps);
|
|
fbk_delay := total_pull_back;
|
|
end if;
|
|
end if;
|
|
|
|
-- assign m_delay
|
|
m_delay <= transport fbk_delay after 1 ps;
|
|
|
|
my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
|
|
for i in 1 to loop_xplier loop
|
|
-- adjust cycles
|
|
tmp_vco_per := (m_times_vco_period/1 ps)/loop_xplier;
|
|
if (my_rem /= 0 and l_index <= my_rem) then
|
|
tmp_rem := (loop_xplier * l_index) rem my_rem;
|
|
cycle_to_adjust := (loop_xplier * l_index) / my_rem;
|
|
if (tmp_rem /= 0) then
|
|
cycle_to_adjust := cycle_to_adjust + 1;
|
|
end if;
|
|
end if;
|
|
if (cycle_to_adjust = i) then
|
|
tmp_vco_per := tmp_vco_per + 1;
|
|
l_index := l_index + 1;
|
|
end if;
|
|
|
|
-- calculate high and low periods
|
|
vco_per := tmp_vco_per * 1 ps;
|
|
high_time := (tmp_vco_per/2) * 1 ps;
|
|
if (tmp_vco_per rem 2 /= 0) then
|
|
high_time := high_time + 1 ps;
|
|
end if;
|
|
low_time := vco_per - high_time;
|
|
|
|
-- schedule the rising and falling edges
|
|
for j in 1 to 2 loop
|
|
vco_val := not vco_val;
|
|
if (vco_val = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (vco_val = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
|
|
-- add offset
|
|
if (schedule_offset) then
|
|
sched_time := sched_time + offset;
|
|
schedule_offset := false;
|
|
end if;
|
|
|
|
-- schedule the phase taps
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
if (first_schedule) then
|
|
vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
|
|
else
|
|
vco_out(k) <= transport vco_val after (sched_time + last_phase_shift(k));
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
end loop;
|
|
|
|
-- schedule once more
|
|
if (first_schedule) then
|
|
vco_val := not vco_val;
|
|
if (vco_val = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (vco_val = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
-- schedule the phase taps
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
|
|
end loop;
|
|
first_schedule := false;
|
|
end if;
|
|
|
|
if (sched_time > 0 ps) then
|
|
schedule_vco <= transport not schedule_vco after sched_time;
|
|
end if;
|
|
|
|
if (vco_period_was_phase_adjusted) then
|
|
m_times_vco_period := refclk_period;
|
|
new_m_times_vco_period := refclk_period;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := true;
|
|
|
|
vco_per := m_times_vco_period/loop_xplier;
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
|
|
if (refclk'event and refclk = '1' and areset_ipd = '0') then
|
|
n_val <= n_val_tmp;
|
|
got_refclk_posedge := true;
|
|
if (not got_first_refclk) then
|
|
got_first_refclk := true;
|
|
else
|
|
got_second_refclk := true;
|
|
refclk_period := now - refclk_time;
|
|
|
|
-- check if incoming freq. will cause VCO range to be
|
|
-- exceeded
|
|
if ((vco_max /= 0 and vco_min /= 0 and skip_vco = "off" and pfdena_ipd = '1') and
|
|
(((refclk_period/1 ps)/loop_xplier > vco_max) or
|
|
((refclk_period/1 ps)/loop_xplier < vco_min)) ) then
|
|
if (pll_is_locked) then
|
|
assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may lose lock" severity warning;
|
|
if (inclk_out_of_range) then
|
|
-- unlock
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
if (pll_type = "fast") then
|
|
locked_tmp := '1';
|
|
end if;
|
|
pll_about_to_lock := false;
|
|
cycles_to_lock := 0;
|
|
assert false report family_name & " PLL lost lock" severity note;
|
|
first_schedule := true;
|
|
schedule_offset := true;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
end if;
|
|
elsif (not no_warn) then
|
|
assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may not lock." severity warning;
|
|
no_warn := true;
|
|
end if;
|
|
inclk_out_of_range := true;
|
|
else
|
|
inclk_out_of_range := false;
|
|
end if;
|
|
end if;
|
|
|
|
if (stop_vco) then
|
|
stop_vco := false;
|
|
schedule_vco <= not schedule_vco;
|
|
end if;
|
|
|
|
refclk_time := now;
|
|
else
|
|
got_refclk_posedge := false;
|
|
end if;
|
|
|
|
if (fbclk'event and fbclk = '1') then
|
|
m_val <= transport m_val_tmp after 1 ps;
|
|
got_fbclk_posedge := true;
|
|
if (not got_first_fbclk) then
|
|
got_first_fbclk := true;
|
|
else
|
|
fbclk_period := now - fbclk_time;
|
|
end if;
|
|
|
|
-- need refclk_period here, so initialized to proper value above
|
|
if ( ( (now - refclk_time > 1.5 * refclk_period) and pfdena_ipd = '1' and pll_is_locked) or ((now - refclk_time > 5 * refclk_period) and pfdena_ipd = '1') ) then
|
|
stop_vco := true;
|
|
-- reset
|
|
got_first_refclk := false;
|
|
got_first_fbclk := false;
|
|
got_second_refclk := false;
|
|
if (pll_is_locked) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
if (pll_type = "fast") then
|
|
locked_tmp := '1';
|
|
end if;
|
|
assert false report family_name & " PLL lost lock due to loss of input clock" severity note;
|
|
end if;
|
|
pll_about_to_lock := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
first_schedule := true;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
end if;
|
|
fbclk_time := now;
|
|
else
|
|
got_fbclk_posedge := false;
|
|
end if;
|
|
|
|
if ((got_refclk_posedge or got_fbclk_posedge) and got_second_refclk and pfdena_ipd = '1' and (not inclk_out_of_range)) then
|
|
|
|
-- now we know actual incoming period
|
|
if ( abs(fbclk_time - refclk_time) <= 5 ps or
|
|
(got_first_fbclk and abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
|
|
-- considered in phase
|
|
if (cycles_to_lock = valid_lock_multiplier - 1) then
|
|
pll_about_to_lock := true;
|
|
end if;
|
|
if (cycles_to_lock = valid_lock_multiplier) then
|
|
if (not pll_is_locked) then
|
|
assert (quiet_period_violation) report family_name & " PLL locked to incoming clock" severity note;
|
|
end if;
|
|
pll_is_locked := true;
|
|
locked_tmp := '1';
|
|
if (pll_type = "fast") then
|
|
locked_tmp := '0';
|
|
end if;
|
|
end if;
|
|
-- increment lock counter only if second part of above
|
|
-- time check is NOT true
|
|
if (not(abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
|
|
cycles_to_lock := cycles_to_lock + 1;
|
|
end if;
|
|
|
|
-- adjust m_times_vco_period
|
|
new_m_times_vco_period := refclk_period;
|
|
else
|
|
-- if locked, begin unlock
|
|
if (pll_is_locked) then
|
|
cycles_to_unlock := cycles_to_unlock + 1;
|
|
if (cycles_to_unlock = invalid_lock_multiplier) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
if (pll_type = "fast") then
|
|
locked_tmp := '1';
|
|
end if;
|
|
pll_about_to_lock := false;
|
|
cycles_to_lock := 0;
|
|
assert (quiet_period_violation) report family_name & " PLL lost lock" severity note;
|
|
first_schedule := true;
|
|
schedule_offset := true;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
end if;
|
|
end if;
|
|
if ( abs(refclk_period - fbclk_period) <= 2 ps ) then
|
|
-- frequency is still good
|
|
if (now = fbclk_time and (not phase_adjust_was_scheduled)) then
|
|
if ( abs(fbclk_time - refclk_time) > refclk_period/2) then
|
|
if ( abs(fbclk_time - refclk_time) > 1.5 * refclk_period) then
|
|
-- input clock may have stopped; do nothing
|
|
else
|
|
new_m_times_vco_period := m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time));
|
|
vco_period_was_phase_adjusted := true;
|
|
end if;
|
|
else
|
|
new_m_times_vco_period := m_times_vco_period - abs(fbclk_time - refclk_time);
|
|
vco_period_was_phase_adjusted := true;
|
|
end if;
|
|
|
|
end if;
|
|
else
|
|
phase_adjust_was_scheduled := false;
|
|
new_m_times_vco_period := refclk_period;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (pfdena_ipd = '0') then
|
|
locked_tmp := 'X';
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
end if;
|
|
|
|
-- give message only at time of deassertion
|
|
if (pfdena_ipd'event and pfdena_ipd = '0') then
|
|
assert false report "PFDENA deasserted." severity note;
|
|
elsif (pfdena_ipd'event and pfdena_ipd = '1') then
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
refclk_time := now;
|
|
end if;
|
|
|
|
if (quiet_period_violation or reconfig_err or scanclr_violation or scanclr_clk_violation) then
|
|
lock <= '0';
|
|
if (pll_type = "fast") then
|
|
lock <= '1';
|
|
end if;
|
|
else
|
|
lock <= locked_tmp;
|
|
end if;
|
|
about_to_lock <= pll_about_to_lock after 1 ps;
|
|
|
|
-- signal to calculate quiet_time
|
|
sig_refclk_period <= refclk_period;
|
|
sig_current_clock <= current_clock;
|
|
|
|
-- signals for debugging
|
|
sig_offset <= offset;
|
|
sig_refclk_time <= refclk_time;
|
|
sig_fbclk_time <= fbclk_time;
|
|
sig_fbclk_period <= fbclk_period;
|
|
sig_vco_period_was_phase_adjusted <= vco_period_was_phase_adjusted;
|
|
sig_phase_adjust_was_scheduled <= phase_adjust_was_scheduled;
|
|
if (stop_vco = true) then
|
|
sig_stop_vco <= '1';
|
|
else
|
|
sig_stop_vco <= '0';
|
|
end if;
|
|
sig_m_times_vco_period <= m_times_vco_period;
|
|
sig_new_m_times_vco_period <= new_m_times_vco_period;
|
|
sig_got_refclk_posedge <= got_refclk_posedge;
|
|
sig_got_fbclk_posedge <= got_fbclk_posedge;
|
|
sig_got_second_refclk <= got_second_refclk;
|
|
end process;
|
|
|
|
process (scanclk_ipd, scanaclr_ipd, scan_data, transfer, sdataout_trig, sdataout_rst_trig)
|
|
variable j : integer := 0;
|
|
variable pll_in_quiet_period : boolean := false;
|
|
variable start_quiet_time : time := 0 ps;
|
|
variable quiet_time : time := 0 ps;
|
|
variable scanclr_rising_time : time := 0 ps;
|
|
variable scanclr_falling_time : time := 0 ps;
|
|
variable got_first_scanclk_after_scanclr_inactive_edge : boolean := false;
|
|
variable scan_chain_being_reset : boolean := false;
|
|
|
|
function slowest_clk ( L0 : integer; L0_mode : string(1 to 6);
|
|
L1 : integer; L1_mode : string(1 to 6);
|
|
G0 : integer; G0_mode : string(1 to 6);
|
|
G1 : integer; G1_mode : string(1 to 6);
|
|
G2 : integer; G2_mode : string(1 to 6);
|
|
G3 : integer; G3_mode : string(1 to 6);
|
|
E0 : integer; E0_mode : string(1 to 6);
|
|
E1 : integer; E1_mode : string(1 to 6);
|
|
E2 : integer; E2_mode : string(1 to 6);
|
|
E3 : integer; E3_mode : string(1 to 6);
|
|
scan_chain : string;
|
|
refclk : time; m_mod : integer) return time is
|
|
variable max_modulus : integer := 1;
|
|
variable q_period : time := 0 ps;
|
|
variable refclk_int : integer := 0;
|
|
begin
|
|
if (L0_mode /= "bypass" and L0_mode /= " off") then
|
|
max_modulus := L0;
|
|
end if;
|
|
if (L1 > max_modulus and L1_mode /= "bypass" and L1_mode /= " off") then
|
|
max_modulus := L1;
|
|
end if;
|
|
if (G0 > max_modulus and G0_mode /= "bypass" and G0_mode /= " off") then
|
|
max_modulus := G0;
|
|
end if;
|
|
if (G1 > max_modulus and G1_mode /= "bypass" and G1_mode /= " off") then
|
|
max_modulus := G1;
|
|
end if;
|
|
if (G2 > max_modulus and G2_mode /= "bypass" and G2_mode /= " off") then
|
|
max_modulus := G2;
|
|
end if;
|
|
if (G3 > max_modulus and G3_mode /= "bypass" and G3_mode /= " off") then
|
|
max_modulus := G3;
|
|
end if;
|
|
if (scan_chain = "long") then
|
|
if (E0 > max_modulus and E0_mode /= "bypass" and E0_mode /= " off") then
|
|
max_modulus := E0;
|
|
end if;
|
|
if (E1 > max_modulus and E1_mode /= "bypass" and E1_mode /= " off") then
|
|
max_modulus := E1;
|
|
end if;
|
|
if (E2 > max_modulus and E2_mode /= "bypass" and E2_mode /= " off") then
|
|
max_modulus := E2;
|
|
end if;
|
|
if (E3 > max_modulus and E3_mode /= "bypass" and E3_mode /= " off") then
|
|
max_modulus := E3;
|
|
end if;
|
|
end if;
|
|
refclk_int := refclk / 1 ps;
|
|
if (m_mod /= 0) then
|
|
q_period := ((refclk_int/m_mod) * max_modulus) * 1 ps;
|
|
end if;
|
|
return (2*q_period);
|
|
end slowest_clk;
|
|
|
|
begin
|
|
if (transfer'event) then
|
|
if (transfer = '0') then
|
|
-- clear the chain
|
|
for i in scan_data'range loop
|
|
scan_data(i) <= '0';
|
|
end loop;
|
|
end if;
|
|
elsif (scanaclr_ipd'event and scanaclr_ipd = '1') then
|
|
-- scanaclr rising
|
|
scanclr_rising_time := now;
|
|
scan_chain_being_reset := true;
|
|
elsif (scanaclr_ipd'event and scanaclr_ipd = '0') then
|
|
-- scanaclr falling
|
|
scanclr_falling_time := now;
|
|
if (scan_chain_being_reset and (now - scanclr_rising_time < TRST)) then
|
|
scanclr_violation <= true;
|
|
ASSERT false REPORT "Detected SCANACLR ACTIVE pulse width violation. Required is 5000 ps, actual is "& int2str((now - scanclr_rising_time) / 1 ps) &". The PLL may not function correctly." severity warning;
|
|
else
|
|
scanclr_violation <= false;
|
|
for i in scan_data'range loop
|
|
scan_data(i) <= '0';
|
|
end loop;
|
|
end if;
|
|
scan_chain_being_reset := false;
|
|
got_first_scanclk_after_scanclr_inactive_edge := false;
|
|
elsif (scanclk_ipd'event and scanclk_ipd = '1' and not got_first_scanclk_after_scanclr_inactive_edge and (now - scanclr_falling_time < TRSTCLK)) then
|
|
scanclr_clk_violation <= true;
|
|
got_first_scanclk_after_scanclr_inactive_edge := true;
|
|
|
|
ASSERT false REPORT "Detected SCANACLR INACTIVE time violation before rising edge of SCANCLK. Required is 5000 ps, actual is "& int2str((now - scanclr_falling_time) / 1 ps) &". Reconfiguration may not work." severity warning;
|
|
elsif (scanclk_ipd'event and scanclk_ipd = '1' and scanaclr_ipd = '0') then
|
|
if (pll_in_quiet_period and (now - start_quiet_time < quiet_time)) then
|
|
ASSERT false REPORT "Detected transition on SCANCLK during quiet period. The PLL may not function correctly." severity warning;
|
|
quiet_period_violation <= true;
|
|
else
|
|
pll_in_quiet_period := false;
|
|
for j in scan_chain_length-1 downto 1 loop
|
|
scan_data(j) <= scan_data(j-1);
|
|
end loop;
|
|
scan_data(0) <= scandata_ipd;
|
|
end if;
|
|
if (not got_first_scanclk_after_scanclr_inactive_edge) then
|
|
got_first_scanclk_after_scanclr_inactive_edge := true;
|
|
scanclr_clk_violation <= false;
|
|
end if;
|
|
elsif (scanclk_ipd'event and scanclk_ipd = '0' and scanaclr_ipd = '0') then
|
|
if (pll_in_quiet_period and (now - start_quiet_time < quiet_time)) then
|
|
ASSERT false REPORT "Detected transition on SCANCLK during quiet period. The PLL may not function correctly." severity warning;
|
|
quiet_period_violation <= true;
|
|
elsif (scan_data(scan_chain_length-1) = '1') then
|
|
-- reset violation flag only after another reconfig seq.
|
|
quiet_period_violation <= false;
|
|
|
|
-- initiate transfer
|
|
transfer <= '1';
|
|
transfer <= transport '0' after 1 ps;
|
|
scandataout_tmp <= '1';
|
|
pll_in_quiet_period := true;
|
|
start_quiet_time := now;
|
|
quiet_time := slowest_clk ( l0_high_val+l0_low_val, l0_mode_val,
|
|
l1_high_val+l1_low_val, l1_mode_val,
|
|
g0_high_val+g0_low_val, g0_mode_val,
|
|
g1_high_val+g1_low_val, g1_mode_val,
|
|
g2_high_val+g2_low_val, g2_mode_val,
|
|
g3_high_val+g3_low_val, g3_mode_val,
|
|
e0_high_val+e0_low_val, e0_mode_val,
|
|
e1_high_val+e1_low_val, e1_mode_val,
|
|
e2_high_val+e2_low_val, e2_mode_val,
|
|
e3_high_val+e3_low_val, e3_mode_val,
|
|
scan_chain, sig_refclk_period, m_val);
|
|
sdataout_trig <= transport not sdataout_trig after quiet_time;
|
|
end if;
|
|
elsif (sdataout_trig'event) then
|
|
if (areset_ipd = '0') then
|
|
scandataout_tmp <= transport '0';
|
|
end if;
|
|
elsif (sdataout_rst_trig'event) then
|
|
scandataout_tmp <= transport '0' after quiet_time;
|
|
end if;
|
|
end process;
|
|
|
|
clk0_tmp <= l0_clk when i_clk0_counter = "l0" else
|
|
l1_clk when i_clk0_counter = "l1" else
|
|
g0_clk when i_clk0_counter = "g0" else
|
|
g1_clk when i_clk0_counter = "g1" else
|
|
g2_clk when i_clk0_counter = "g2" else
|
|
g3_clk when i_clk0_counter = "g3" else
|
|
'0';
|
|
not_clk0_tmp <= not clk0_tmp;
|
|
ena0_reg : dffp
|
|
port map ( D => clkena(0),
|
|
CLRN => vcc,
|
|
PRN => vcc,
|
|
ENA => vcc,
|
|
CLK => not_clk0_tmp,
|
|
Q => ena0 );
|
|
|
|
clk(0) <= ena0 and clk0_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
ena0 and 'X';
|
|
|
|
clk1_tmp <= l0_clk when i_clk1_counter = "l0" else
|
|
l1_clk when i_clk1_counter = "l1" else
|
|
g0_clk when i_clk1_counter = "g0" else
|
|
g1_clk when i_clk1_counter = "g1" else
|
|
g2_clk when i_clk1_counter = "g2" else
|
|
g3_clk when i_clk1_counter = "g3" else
|
|
'0';
|
|
not_clk1_tmp <= not clk1_tmp;
|
|
ena1_reg : dffp
|
|
port map ( D => clkena(1),
|
|
CLRN => vcc,
|
|
PRN => vcc,
|
|
ENA => vcc,
|
|
CLK => not_clk1_tmp,
|
|
Q => ena1 );
|
|
|
|
clk(1) <= ena1 and clk1_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
ena1 and 'X';
|
|
|
|
clk2_tmp <= l0_clk when i_clk2_counter = "l0" else
|
|
l1_clk when i_clk2_counter = "l1" else
|
|
g0_clk when i_clk2_counter = "g0" else
|
|
g1_clk when i_clk2_counter = "g1" else
|
|
g2_clk when i_clk2_counter = "g2" else
|
|
g3_clk when i_clk2_counter = "g3" else
|
|
'0';
|
|
not_clk2_tmp <= not clk2_tmp;
|
|
ena2_reg : dffp
|
|
port map ( D => clkena(2),
|
|
CLRN => vcc,
|
|
PRN => vcc,
|
|
ENA => vcc,
|
|
CLK => not_clk2_tmp,
|
|
Q => ena2 );
|
|
|
|
clk(2) <= ena2 and clk2_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
ena2 and 'X';
|
|
|
|
clk3_tmp <= l0_clk when i_clk3_counter = "l0" else
|
|
l1_clk when i_clk3_counter = "l1" else
|
|
g0_clk when i_clk3_counter = "g0" else
|
|
g1_clk when i_clk3_counter = "g1" else
|
|
g2_clk when i_clk3_counter = "g2" else
|
|
g3_clk when i_clk3_counter = "g3" else
|
|
'0';
|
|
not_clk3_tmp <= not clk3_tmp;
|
|
ena3_reg : dffp
|
|
port map ( D => clkena(3),
|
|
CLRN => vcc,
|
|
PRN => vcc,
|
|
ENA => vcc,
|
|
CLK => not_clk3_tmp,
|
|
Q => ena3 );
|
|
|
|
clk(3) <= ena3 and clk3_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
ena3 and 'X';
|
|
|
|
clk4_tmp <= l0_clk when i_clk4_counter = "l0" else
|
|
l1_clk when i_clk4_counter = "l1" else
|
|
g0_clk when i_clk4_counter = "g0" else
|
|
g1_clk when i_clk4_counter = "g1" else
|
|
g2_clk when i_clk4_counter = "g2" else
|
|
g3_clk when i_clk4_counter = "g3" else
|
|
'0';
|
|
not_clk4_tmp <= not clk4_tmp;
|
|
ena4_reg : dffp
|
|
port map ( D => clkena(4),
|
|
CLRN => vcc,
|
|
PRN => vcc,
|
|
ENA => vcc,
|
|
CLK => not_clk4_tmp,
|
|
Q => ena4 );
|
|
|
|
clk(4) <= ena4 and clk4_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
ena4 and 'X';
|
|
|
|
clk5_tmp <= l0_clk when i_clk5_counter = "l0" else
|
|
l1_clk when i_clk5_counter = "l1" else
|
|
g0_clk when i_clk5_counter = "g0" else
|
|
g1_clk when i_clk5_counter = "g1" else
|
|
g2_clk when i_clk5_counter = "g2" else
|
|
g3_clk when i_clk5_counter = "g3" else
|
|
'0';
|
|
not_clk5_tmp <= not clk5_tmp;
|
|
ena5_reg : dffp
|
|
port map ( D => clkena(5),
|
|
CLRN => vcc,
|
|
PRN => vcc,
|
|
ENA => vcc,
|
|
CLK => not_clk5_tmp,
|
|
Q => ena5 );
|
|
|
|
clk(5) <= ena5 and clk5_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
ena5 and 'X';
|
|
|
|
extclk0_tmp <= e0_clk when i_extclk0_counter = "e0" else
|
|
e1_clk when i_extclk0_counter = "e1" else
|
|
e2_clk when i_extclk0_counter = "e2" else
|
|
e3_clk when i_extclk0_counter = "e3" else
|
|
g0_clk when i_extclk0_counter = "g0" else
|
|
'0';
|
|
not_extclk0_tmp <= not extclk0_tmp;
|
|
extena0_reg : dffp
|
|
port map ( D => extclkena(0),
|
|
CLRN => vcc,
|
|
PRN => vcc,
|
|
ENA => vcc,
|
|
CLK => not_extclk0_tmp,
|
|
Q => extena0 );
|
|
|
|
extclk(0) <= extena0 and extclk0_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
extena0 and 'X';
|
|
|
|
extclk1_tmp <= e0_clk when i_extclk1_counter = "e0" else
|
|
e1_clk when i_extclk1_counter = "e1" else
|
|
e2_clk when i_extclk1_counter = "e2" else
|
|
e3_clk when i_extclk1_counter = "e3" else
|
|
g0_clk when i_extclk1_counter = "g0" else
|
|
'0';
|
|
not_extclk1_tmp <= not extclk1_tmp;
|
|
extena1_reg : dffp
|
|
port map ( D => extclkena(1),
|
|
CLRN => vcc,
|
|
PRN => vcc,
|
|
ENA => vcc,
|
|
CLK => not_extclk1_tmp,
|
|
Q => extena1 );
|
|
|
|
extclk(1) <= extena1 and extclk1_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
extena1 and 'X';
|
|
|
|
extclk2_tmp <= e0_clk when i_extclk2_counter = "e0" else
|
|
e1_clk when i_extclk2_counter = "e1" else
|
|
e2_clk when i_extclk2_counter = "e2" else
|
|
e3_clk when i_extclk2_counter = "e3" else
|
|
g0_clk when i_extclk2_counter = "g0" else
|
|
'0';
|
|
not_extclk2_tmp <= not extclk2_tmp;
|
|
extena2_reg : dffp
|
|
port map ( D => extclkena(2),
|
|
CLRN => vcc,
|
|
PRN => vcc,
|
|
ENA => vcc,
|
|
CLK => not_extclk2_tmp,
|
|
Q => extena2 );
|
|
|
|
extclk(2) <= extena2 and extclk2_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
extena2 and 'X';
|
|
|
|
extclk3_tmp <= e0_clk when i_extclk3_counter = "e0" else
|
|
e1_clk when i_extclk3_counter = "e1" else
|
|
e2_clk when i_extclk3_counter = "e2" else
|
|
e3_clk when i_extclk3_counter = "e3" else
|
|
g0_clk when i_extclk3_counter = "g0" else
|
|
'0';
|
|
not_extclk3_tmp <= not extclk3_tmp;
|
|
extena3_reg : dffp
|
|
port map ( D => extclkena(3),
|
|
CLRN => vcc,
|
|
PRN => vcc,
|
|
ENA => vcc,
|
|
CLK => not_extclk3_tmp,
|
|
Q => extena3 );
|
|
|
|
extclk(3) <= extena3 and extclk3_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
extena3 and 'X';
|
|
|
|
enable0 <= enable0_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
'X';
|
|
enable1 <= enable1_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
|
|
'X';
|
|
|
|
scandataout <= scandataout_tmp;
|
|
|
|
end vital_pll;
|
|
-- END ARCHITECTURE VITAL_PLL
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : arm_m_cntr
|
|
--
|
|
-- Description : Simulation model for the M counter. M is the loop
|
|
-- feedback counter of the StratixII PLL.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
|
|
ENTITY arm_m_cntr is
|
|
PORT( clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer := 1;
|
|
time_delay : IN integer := 0
|
|
);
|
|
END arm_m_cntr;
|
|
|
|
ARCHITECTURE behave of arm_m_cntr is
|
|
begin
|
|
|
|
process (clk, reset)
|
|
variable count : integer := 1;
|
|
variable first_rising_edge : boolean := true;
|
|
variable tmp_cout : std_logic;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := true;
|
|
elsif (clk'event) then
|
|
if (clk = '1' and first_rising_edge) then
|
|
first_rising_edge := false;
|
|
tmp_cout := clk;
|
|
elsif (not first_rising_edge) then
|
|
if (count < modulus) then
|
|
count := count + 1;
|
|
else
|
|
count := 1;
|
|
tmp_cout := not tmp_cout;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout after time_delay * 1 ps;
|
|
end process;
|
|
end behave;
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : arm_n_cntr
|
|
--
|
|
-- Description : Simulation model for the N counter. N is the
|
|
-- input counter of the StratixII PLL.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
|
|
ENTITY arm_n_cntr is
|
|
PORT( clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer := 1;
|
|
time_delay : IN integer := 0
|
|
);
|
|
END arm_n_cntr;
|
|
|
|
ARCHITECTURE behave of arm_n_cntr is
|
|
begin
|
|
|
|
process (clk, reset)
|
|
variable count : integer := 1;
|
|
variable first_rising_edge : boolean := true;
|
|
variable tmp_cout : std_logic;
|
|
variable clk_last_valid_value : std_logic;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := true;
|
|
elsif (clk'event) then
|
|
if (clk = 'X') then
|
|
ASSERT FALSE REPORT "Invalid transition to 'X' detected on PLL input clk. This edge will be ignored." severity warning;
|
|
elsif (clk = '1' and first_rising_edge) then
|
|
first_rising_edge := false;
|
|
tmp_cout := clk;
|
|
elsif (not first_rising_edge) then
|
|
if (count < modulus) then
|
|
count := count + 1;
|
|
else
|
|
count := 1;
|
|
tmp_cout := not tmp_cout;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (clk /= 'X') then
|
|
clk_last_valid_value := clk;
|
|
end if;
|
|
cout <= transport tmp_cout after time_delay * 1 ps;
|
|
end process;
|
|
end behave;
|
|
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : arm_scale_cntr
|
|
--
|
|
-- Description : Simulation model for the output scale-down counters.
|
|
-- This is a common model for the C0, C1, C2, C3, C4 and C5
|
|
-- output counters of the StratixII PLL.
|
|
--
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
|
|
ENTITY arm_scale_cntr is
|
|
PORT( clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
initial : IN integer := 1;
|
|
high : IN integer := 1;
|
|
low : IN integer := 1;
|
|
mode : IN string := "bypass";
|
|
ph_tap : IN integer := 0;
|
|
cout : OUT std_logic
|
|
);
|
|
END arm_scale_cntr;
|
|
|
|
ARCHITECTURE behave of arm_scale_cntr is
|
|
begin
|
|
process (clk, reset)
|
|
variable tmp_cout : std_logic := '0';
|
|
variable count : integer := 1;
|
|
variable output_shift_count : integer := 1;
|
|
variable first_rising_edge : boolean := false;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
output_shift_count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := false;
|
|
elsif (clk'event) then
|
|
if (mode = " off") then
|
|
tmp_cout := '0';
|
|
elsif (mode = "bypass") then
|
|
tmp_cout := clk;
|
|
first_rising_edge := true;
|
|
elsif (not first_rising_edge) then
|
|
if (clk = '1') then
|
|
if (output_shift_count = initial) then
|
|
tmp_cout := clk;
|
|
first_rising_edge := true;
|
|
else
|
|
output_shift_count := output_shift_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (output_shift_count < initial) then
|
|
if (clk = '1') then
|
|
output_shift_count := output_shift_count + 1;
|
|
end if;
|
|
else
|
|
count := count + 1;
|
|
if (mode = " even" and (count = (high*2) + 1)) then
|
|
tmp_cout := '0';
|
|
elsif (mode = " odd" and (count = high*2)) then
|
|
tmp_cout := '0';
|
|
elsif (count = (high + low)*2 + 1) then
|
|
tmp_cout := '1';
|
|
count := 1; -- reset count
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout;
|
|
end process;
|
|
|
|
end behave;
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_stratixii_pll
|
|
--
|
|
-- Description : Simulation model for the StratixII PLL.
|
|
-- In the functional mode, it is also the model for the altpll
|
|
-- megafunction.
|
|
--
|
|
-- Limitations : Does not support Spread Spectrum and Bandwidth.
|
|
--
|
|
-- Outputs : Up to 6 output clocks, each defined by its own set of
|
|
-- parameters. Locked output (active high) indicates when the
|
|
-- PLL locks. clkbad, clkloss and activeclock are used for
|
|
-- clock switchover to indicate which input clock has gone
|
|
-- bad, when the clock switchover initiates and which input
|
|
-- clock is being used as the reference, respectively.
|
|
-- scandataout is the data output of the serial scan chain.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
LIBRARY IEEE, std;
|
|
USE IEEE.std_logic_1164.all;
|
|
USE STD.TEXTIO.all;
|
|
USE work.MF_pllpack.all;
|
|
USE work.arm_m_cntr;
|
|
USE work.arm_n_cntr;
|
|
USE work.arm_scale_cntr;
|
|
USE work.dffp;
|
|
USE work.MF_pll_reg;
|
|
|
|
ENTITY MF_stratixii_pll is
|
|
GENERIC (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "auto"; -- EGPP/FAST/AUTO
|
|
compensate_clock : string := "clk0";
|
|
feedback_source : string := "clk0";
|
|
qualify_conf_done : string := "off";
|
|
|
|
test_input_comp_delay : integer := 0;
|
|
test_feedback_comp_delay : integer := 0;
|
|
|
|
inclk0_input_frequency : integer := 10000;
|
|
inclk1_input_frequency : integer := 10000;
|
|
|
|
gate_lock_signal : string := "no";
|
|
gate_lock_counter : integer := 1;
|
|
self_reset_on_gated_loss_lock : string := "off";
|
|
valid_lock_multiplier : integer := 1;
|
|
invalid_lock_multiplier : integer := 5;
|
|
sim_gate_lock_device_behavior : string := "off";
|
|
|
|
switch_over_type : string := "auto";
|
|
switch_over_on_lossclk : string := "off";
|
|
switch_over_on_gated_lock : string := "off";
|
|
switch_over_counter : integer := 1;
|
|
enable_switch_over_counter : string := "on";
|
|
|
|
bandwidth : integer := 0;
|
|
bandwidth_type : string := "auto";
|
|
down_spread : string := "0.0";
|
|
spread_frequency : integer := 0;
|
|
|
|
clk0_output_frequency : integer := 0;
|
|
clk0_multiply_by : integer := 1;
|
|
clk0_divide_by : integer := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk0_duty_cycle : integer := 50;
|
|
|
|
clk1_output_frequency : integer := 0;
|
|
clk1_multiply_by : integer := 1;
|
|
clk1_divide_by : integer := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_duty_cycle : integer := 50;
|
|
|
|
clk2_output_frequency : integer := 0;
|
|
clk2_multiply_by : integer := 1;
|
|
clk2_divide_by : integer := 1;
|
|
clk2_phase_shift : string := "0";
|
|
clk2_duty_cycle : integer := 50;
|
|
|
|
clk3_output_frequency : integer := 0;
|
|
clk3_multiply_by : integer := 1;
|
|
clk3_divide_by : integer := 1;
|
|
clk3_phase_shift : string := "0";
|
|
clk3_duty_cycle : integer := 50;
|
|
|
|
clk4_output_frequency : integer := 0;
|
|
clk4_multiply_by : integer := 1;
|
|
clk4_divide_by : integer := 1;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
|
|
clk5_output_frequency : integer := 0;
|
|
clk5_multiply_by : integer := 1;
|
|
clk5_divide_by : integer := 1;
|
|
clk5_phase_shift : string := "0";
|
|
clk5_duty_cycle : integer := 50;
|
|
|
|
pfd_min : integer := 0;
|
|
pfd_max : integer := 0;
|
|
vco_min : integer := 0;
|
|
vco_max : integer := 0;
|
|
vco_center : integer := 0;
|
|
|
|
-- ADVANCED USER PARAMETERS
|
|
m_initial : integer := 1;
|
|
m : integer := 0;
|
|
n : integer := 1;
|
|
m2 : integer := 1;
|
|
n2 : integer := 1;
|
|
ss : integer := 0;
|
|
|
|
c0_high : integer := 1;
|
|
c0_low : integer := 1;
|
|
c0_initial : integer := 1;
|
|
c0_mode : string := "bypass";
|
|
c0_ph : integer := 0;
|
|
|
|
c1_high : integer := 1;
|
|
c1_low : integer := 1;
|
|
c1_initial : integer := 1;
|
|
c1_mode : string := "bypass";
|
|
c1_ph : integer := 0;
|
|
|
|
c2_high : integer := 1;
|
|
c2_low : integer := 1;
|
|
c2_initial : integer := 1;
|
|
c2_mode : string := "bypass";
|
|
c2_ph : integer := 0;
|
|
|
|
c3_high : integer := 1;
|
|
c3_low : integer := 1;
|
|
c3_initial : integer := 1;
|
|
c3_mode : string := "bypass";
|
|
c3_ph : integer := 0;
|
|
|
|
c4_high : integer := 1;
|
|
c4_low : integer := 1;
|
|
c4_initial : integer := 1;
|
|
c4_mode : string := "bypass";
|
|
c4_ph : integer := 0;
|
|
|
|
c5_high : integer := 1;
|
|
c5_low : integer := 1;
|
|
c5_initial : integer := 1;
|
|
c5_mode : string := "bypass";
|
|
c5_ph : integer := 0;
|
|
|
|
m_ph : integer := 0;
|
|
|
|
clk0_counter : string := "c0";
|
|
clk1_counter : string := "c1";
|
|
clk2_counter : string := "c2";
|
|
clk3_counter : string := "c3";
|
|
clk4_counter : string := "c4";
|
|
clk5_counter : string := "c5";
|
|
|
|
c1_use_casc_in : string := "off";
|
|
c2_use_casc_in : string := "off";
|
|
c3_use_casc_in : string := "off";
|
|
c4_use_casc_in : string := "off";
|
|
c5_use_casc_in : string := "off";
|
|
|
|
m_test_source : integer := 5;
|
|
c0_test_source : integer := 5;
|
|
c1_test_source : integer := 5;
|
|
c2_test_source : integer := 5;
|
|
c3_test_source : integer := 5;
|
|
c4_test_source : integer := 5;
|
|
c5_test_source : integer := 5;
|
|
|
|
-- LVDS mode parameters
|
|
enable0_counter : string := "c0";
|
|
enable1_counter : string := "c1";
|
|
sclkout0_phase_shift : string := "0";
|
|
sclkout1_phase_shift : string := "0";
|
|
|
|
charge_pump_current : integer := 52;
|
|
loop_filter_r : string := " 1.000000";
|
|
loop_filter_c : integer := 16;
|
|
common_rx_tx : string := "off";
|
|
use_vco_bypass : string := "false";
|
|
use_dc_coupling : string := "false";
|
|
|
|
pll_compensation_delay : integer := 0;
|
|
simulation_type : string := "functional";
|
|
|
|
-- Simulation only generics
|
|
family_name : string := "StratixII";
|
|
|
|
clk0_use_even_counter_mode : string := "off";
|
|
clk1_use_even_counter_mode : string := "off";
|
|
clk2_use_even_counter_mode : string := "off";
|
|
clk3_use_even_counter_mode : string := "off";
|
|
clk4_use_even_counter_mode : string := "off";
|
|
clk5_use_even_counter_mode : string := "off";
|
|
|
|
clk0_use_even_counter_value : string := "off";
|
|
clk1_use_even_counter_value : string := "off";
|
|
clk2_use_even_counter_value : string := "off";
|
|
clk3_use_even_counter_value : string := "off";
|
|
clk4_use_even_counter_value : string := "off";
|
|
clk5_use_even_counter_value : string := "off";
|
|
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
scan_chain_mif_file : string := "";
|
|
vco_post_scale : integer := 1
|
|
|
|
);
|
|
|
|
PORT
|
|
(
|
|
inclk : in std_logic_vector(1 downto 0);
|
|
fbin : in std_logic := '0';
|
|
ena : in std_logic := '1';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scanread : in std_logic := '0';
|
|
scanwrite : in std_logic := '0';
|
|
scandata : in std_logic := '0';
|
|
scanclk : in std_logic := '0';
|
|
testin : in std_logic_vector(3 downto 0) := "0000";
|
|
clk : out std_logic_vector(5 downto 0);
|
|
clkbad : out std_logic_vector(1 downto 0);
|
|
activeclock : out std_logic;
|
|
locked : out std_logic;
|
|
clkloss : out std_logic;
|
|
scandataout : out std_logic;
|
|
scandone : out std_logic;
|
|
testupout : out std_logic;
|
|
testdownout : out std_logic;
|
|
-- lvds specific ports
|
|
enable0 : out std_logic;
|
|
enable1 : out std_logic;
|
|
sclkout : out std_logic_vector(1 downto 0)
|
|
);
|
|
END MF_stratixii_pll;
|
|
|
|
ARCHITECTURE vital_pll of MF_stratixii_pll is
|
|
|
|
TYPE int_array is ARRAY(NATURAL RANGE <>) of integer;
|
|
TYPE str_array is ARRAY(NATURAL RANGE <>) of string(1 to 6);
|
|
TYPE str_array1 is ARRAY(NATURAL RANGE <>) of string(1 to 9);
|
|
TYPE std_logic_array is ARRAY(NATURAL RANGE <>) of std_logic;
|
|
|
|
-- internal advanced parameter signals
|
|
signal i_vco_min : integer;
|
|
signal i_vco_max : integer;
|
|
signal i_vco_center : integer;
|
|
signal i_pfd_min : integer;
|
|
signal i_pfd_max : integer;
|
|
signal c_ph_val : int_array(0 to 5) := (OTHERS => 0);
|
|
signal c_high_val : int_array(0 to 5) := (OTHERS => 1);
|
|
signal c_low_val : int_array(0 to 5) := (OTHERS => 1);
|
|
signal c_initial_val : int_array(0 to 5) := (OTHERS => 1);
|
|
signal c_mode_val : str_array(0 to 5);
|
|
|
|
-- old values
|
|
signal c_high_val_old : int_array(0 to 5) := (OTHERS => 1);
|
|
signal c_low_val_old : int_array(0 to 5) := (OTHERS => 1);
|
|
signal c_ph_val_old : int_array(0 to 5) := (OTHERS => 0);
|
|
signal c_mode_val_old : str_array(0 to 5);
|
|
|
|
-- hold registers
|
|
signal c_high_val_hold : int_array(0 to 5) := (OTHERS => 1);
|
|
signal c_low_val_hold : int_array(0 to 5) := (OTHERS => 1);
|
|
signal c_ph_val_hold : int_array(0 to 5) := (OTHERS => 0);
|
|
signal c_mode_val_hold : str_array(0 to 5);
|
|
|
|
-- temp registers
|
|
signal sig_c_ph_val_tmp : int_array(0 to 5) := (OTHERS => 0);
|
|
signal sig_c_low_val_tmp : int_array(0 to 5) := (OTHERS => 1);
|
|
signal sig_c_hi_val_tmp : int_array(0 to 5) := (OTHERS => 1);
|
|
signal c_ph_val_orig : int_array(0 to 5) := (OTHERS => 0);
|
|
|
|
--signal i_clk5_counter : string(1 to 2) := "c5";
|
|
--signal i_clk4_counter : string(1 to 2) := "c4";
|
|
--signal i_clk3_counter : string(1 to 2) := "c3";
|
|
--signal i_clk2_counter : string(1 to 2) := "c2";
|
|
--signal i_clk1_counter : string(1 to 2) := "c1";
|
|
--signal i_clk0_counter : string(1 to 2) := "c0";
|
|
|
|
signal i_clk5_counter : integer := 5;
|
|
signal i_clk4_counter : integer := 4;
|
|
signal i_clk3_counter : integer := 3;
|
|
signal i_clk2_counter : integer := 2;
|
|
signal i_clk1_counter : integer := 1;
|
|
signal i_clk0_counter : integer := 0;
|
|
signal i_charge_pump_current : integer;
|
|
signal i_loop_filter_r : integer;
|
|
|
|
-- end internal advanced parameter signals
|
|
|
|
-- CONSTANTS
|
|
CONSTANT GPP_SCAN_CHAIN : integer := 174;
|
|
CONSTANT FAST_SCAN_CHAIN : integer := 75;
|
|
CONSTANT GATE_LOCK_CYCLES : integer := 7;
|
|
|
|
CONSTANT cntrs : str_array(5 downto 0) := (" C5", " C4", " C3", " C2", " C1", " C0");
|
|
CONSTANT ss_cntrs : str_array(0 to 3) := (" M", " M2", " N", " N2");
|
|
|
|
CONSTANT loop_filter_c_arr : int_array(0 to 3) := (57, 16, 36, 5);
|
|
CONSTANT fpll_loop_filter_c_arr : int_array(0 to 3) := (18, 13, 8, 2);
|
|
CONSTANT charge_pump_curr_arr : int_array(0 to 15) := (6, 12, 30, 36, 52, 57, 72, 77, 92, 96, 110, 114, 127, 131, 144, 148);
|
|
CONSTANT loop_filter_r_arr : str_array1(0 to 39) := (" 1.000000", " 1.500000", " 2.000000", " 2.500000", " 3.000000", " 3.500000", " 4.000000", " 4.500000", " 5.000000", " 5.500000", " 6.000000", " 6.500000", " 7.000000", " 7.500000", " 8.000000", " 8.500000", " 9.000000", " 9.500000", "10.000000", "10.500000", "11.000000", "11.500000", "12.000000", "12.500000", "13.000000", "13.500000", "14.000000", "14.500000", "15.000000", "15.500000", "16.000000", "16.500000", "17.000000", "17.500000", "18.000000", "18.500000", "19.000000", "19.500000", "20.000000", "20.500000");
|
|
|
|
-- signals
|
|
|
|
signal vcc : std_logic := '1';
|
|
|
|
signal fbclk : std_logic;
|
|
signal refclk : std_logic;
|
|
|
|
signal c_clk : std_logic_array(0 to 5);
|
|
signal vco_out : std_logic_vector(7 downto 0) := (OTHERS => '0');
|
|
signal vco_tap : std_logic_vector(7 downto 0) := (OTHERS => '0');
|
|
signal vco_out_last_value : std_logic_vector(7 downto 0);
|
|
signal vco_tap_last_value : std_logic_vector(7 downto 0);
|
|
|
|
-- signals to assign values to counter params
|
|
signal m_val : int_array(0 to 1) := (OTHERS => 1);
|
|
signal n_val : int_array(0 to 1) := (OTHERS => 1);
|
|
signal m_ph_val : integer := 0;
|
|
signal m_initial_val : integer := m_initial;
|
|
|
|
signal m_mode_val : str_array(0 to 1) := (OTHERS => " ");
|
|
signal n_mode_val : str_array(0 to 1) := (OTHERS => " ");
|
|
signal lfc_val : integer := 0;
|
|
signal cp_curr_val : integer := 0;
|
|
signal lfr_val : string(1 to 9) := " ";
|
|
|
|
-- old values
|
|
signal m_val_old : int_array(0 to 1) := (OTHERS => 1);
|
|
signal n_val_old : int_array(0 to 1) := (OTHERS => 1);
|
|
signal m_mode_val_old : str_array(0 to 1) := (OTHERS => " ");
|
|
signal n_mode_val_old : str_array(0 to 1) := (OTHERS => " ");
|
|
signal m_ph_val_old : integer := 0;
|
|
signal lfc_old : integer := 0;
|
|
signal cp_curr_old : integer := 0;
|
|
signal lfr_old : string(1 to 9) := " ";
|
|
signal num_output_cntrs : integer := 6;
|
|
|
|
signal scan_data : std_logic_vector(173 downto 0) := (OTHERS => '0');
|
|
|
|
signal clk0_tmp : std_logic;
|
|
signal clk1_tmp : std_logic;
|
|
signal clk2_tmp : std_logic;
|
|
signal clk3_tmp : std_logic;
|
|
signal clk4_tmp : std_logic;
|
|
signal clk5_tmp : std_logic;
|
|
signal sclkout0_tmp : std_logic;
|
|
signal sclkout1_tmp : std_logic;
|
|
|
|
signal clkin : std_logic := '0';
|
|
signal gate_locked : std_logic := '0';
|
|
signal lock : std_logic := '0';
|
|
signal about_to_lock : boolean := false;
|
|
signal reconfig_err : boolean := false;
|
|
|
|
signal inclk_c0 : std_logic;
|
|
signal inclk_c1 : std_logic;
|
|
signal inclk_c2 : std_logic;
|
|
signal inclk_c3 : std_logic;
|
|
signal inclk_c4 : std_logic;
|
|
signal inclk_c5 : std_logic;
|
|
signal inclk_m : std_logic;
|
|
signal devpor : std_logic;
|
|
signal devclrn : std_logic;
|
|
|
|
signal inclk0_ipd : std_logic;
|
|
signal inclk1_ipd : std_logic;
|
|
signal ena_ipd : std_logic;
|
|
signal pfdena_ipd : std_logic;
|
|
signal areset_ipd : std_logic;
|
|
signal fbin_ipd : std_logic;
|
|
signal scanclk_ipd : std_logic;
|
|
signal scanread_ipd : std_logic;
|
|
signal scanwrite_ipd : std_logic;
|
|
signal scandata_ipd : std_logic;
|
|
signal clkswitch_ipd : std_logic;
|
|
-- registered signals
|
|
signal scanread_reg : std_logic := '0';
|
|
signal scanwrite_reg : std_logic := '0';
|
|
signal scanwrite_enabled : std_logic := '0';
|
|
signal gated_scanclk : std_logic := '1';
|
|
|
|
signal inclk_c0_dly1 : std_logic := '0';
|
|
signal inclk_c0_dly2 : std_logic := '0';
|
|
signal inclk_c0_dly3 : std_logic := '0';
|
|
signal inclk_c0_dly4 : std_logic := '0';
|
|
signal inclk_c0_dly5 : std_logic := '0';
|
|
signal inclk_c0_dly6 : std_logic := '0';
|
|
signal inclk_c1_dly1 : std_logic := '0';
|
|
signal inclk_c1_dly2 : std_logic := '0';
|
|
signal inclk_c1_dly3 : std_logic := '0';
|
|
signal inclk_c1_dly4 : std_logic := '0';
|
|
signal inclk_c1_dly5 : std_logic := '0';
|
|
signal inclk_c1_dly6 : std_logic := '0';
|
|
|
|
|
|
signal sig_offset : time := 0 ps;
|
|
signal sig_refclk_time : time := 0 ps;
|
|
signal sig_fbclk_period : time := 0 ps;
|
|
signal sig_vco_period_was_phase_adjusted : boolean := false;
|
|
signal sig_phase_adjust_was_scheduled : boolean := false;
|
|
signal sig_stop_vco : std_logic := '0';
|
|
signal sig_m_times_vco_period : time := 0 ps;
|
|
signal sig_new_m_times_vco_period : time := 0 ps;
|
|
signal sig_got_refclk_posedge : boolean := false;
|
|
signal sig_got_fbclk_posedge : boolean := false;
|
|
signal sig_got_second_refclk : boolean := false;
|
|
|
|
signal m_delay : integer := 0;
|
|
signal n_delay : integer := 0;
|
|
|
|
signal inclk1_tmp : std_logic := '0';
|
|
|
|
signal ext_fbk_cntr_high : integer := 0;
|
|
signal ext_fbk_cntr_low : integer := 0;
|
|
signal ext_fbk_cntr_ph : integer := 0;
|
|
signal ext_fbk_cntr_initial : integer := 1;
|
|
signal ext_fbk_cntr : string(1 to 2) := "c0";
|
|
signal ext_fbk_cntr_mode : string(1 to 6) := "bypass";
|
|
signal ext_fbk_cntr_index : integer := 0;
|
|
|
|
signal enable0_tmp : std_logic := '0';
|
|
signal enable1_tmp : std_logic := '0';
|
|
signal reset_low : std_logic := '0';
|
|
|
|
signal scandataout_tmp : std_logic := '0';
|
|
signal scandone_tmp : std_logic := '0';
|
|
|
|
signal sig_refclk_period : time := (inclk0_input_frequency * 1 ps) * n;
|
|
|
|
signal schedule_vco : std_logic := '0';
|
|
|
|
signal areset_ena_sig : std_logic := '0';
|
|
signal pll_in_test_mode : boolean := false;
|
|
|
|
signal inclk_c_from_vco : std_logic_array(0 to 5);
|
|
|
|
signal inclk_m_from_vco : std_logic;
|
|
signal inclk_sclkout0_from_vco : std_logic;
|
|
signal inclk_sclkout1_from_vco : std_logic;
|
|
|
|
--signal tap0_is_active : boolean := true;
|
|
signal sig_quiet_time : time := 0 ps;
|
|
signal sig_slowest_clk_old : time := 0 ps;
|
|
signal sig_slowest_clk_new : time := 0 ps;
|
|
signal sig_m_val_tmp : int_array(0 to 1) := (OTHERS => 1);
|
|
|
|
COMPONENT arm_m_cntr
|
|
PORT (
|
|
clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer := 1;
|
|
time_delay : IN integer := 0
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT arm_n_cntr
|
|
PORT (
|
|
clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer := 1;
|
|
time_delay : IN integer := 0
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT arm_scale_cntr
|
|
PORT (
|
|
clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial : IN integer := 1;
|
|
high : IN integer := 1;
|
|
low : IN integer := 1;
|
|
mode : IN string := "bypass";
|
|
ph_tap : IN integer := 0
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT dffp
|
|
|
|
PORT(
|
|
Q : out STD_LOGIC := '0';
|
|
D : in STD_LOGIC := '1';
|
|
CLRN : in STD_LOGIC := '1';
|
|
PRN : in STD_LOGIC := '1';
|
|
CLK : in STD_LOGIC := '0';
|
|
ENA : in STD_LOGIC := '1');
|
|
END COMPONENT;
|
|
|
|
COMPONENT MF_pll_reg
|
|
PORT(
|
|
Q : out STD_LOGIC := '0';
|
|
D : in STD_LOGIC := '1';
|
|
CLRN : in STD_LOGIC := '1';
|
|
PRN : in STD_LOGIC := '1';
|
|
CLK : in STD_LOGIC := '0';
|
|
ENA : in STD_LOGIC := '1');
|
|
END COMPONENT;
|
|
|
|
begin
|
|
|
|
----------------------
|
|
-- INPUT PATH DELAYs
|
|
----------------------
|
|
WireDelay : block
|
|
begin
|
|
inclk0_ipd <= inclk(0);
|
|
inclk1_ipd <= inclk(1);
|
|
areset_ipd <= areset;
|
|
ena_ipd <= ena;
|
|
fbin_ipd <= fbin;
|
|
pfdena_ipd <= pfdena;
|
|
scanclk_ipd <= scanclk;
|
|
scanread_ipd <= scanread;
|
|
scandata_ipd <= scandata;
|
|
scanwrite_ipd <= scanwrite;
|
|
clkswitch_ipd <= clkswitch;
|
|
end block;
|
|
|
|
inclk_m <= clkin when m_test_source = 0 else
|
|
clk0_tmp when operation_mode = "external_feedback" and feedback_source = "clk0" else
|
|
clk1_tmp when operation_mode = "external_feedback" and feedback_source = "clk1" else
|
|
clk2_tmp when operation_mode = "external_feedback" and feedback_source = "clk2" else
|
|
clk3_tmp when operation_mode = "external_feedback" and feedback_source = "clk3" else
|
|
clk4_tmp when operation_mode = "external_feedback" and feedback_source = "clk4" else
|
|
clk5_tmp when operation_mode = "external_feedback" and feedback_source = "clk5" else
|
|
inclk_m_from_vco;
|
|
|
|
|
|
ext_fbk_cntr_high <= c_high_val(ext_fbk_cntr_index);
|
|
ext_fbk_cntr_low <= c_low_val(ext_fbk_cntr_index);
|
|
ext_fbk_cntr_ph <= c_ph_val(ext_fbk_cntr_index);
|
|
ext_fbk_cntr_initial <= c_initial_val(ext_fbk_cntr_index);
|
|
ext_fbk_cntr_mode <= c_mode_val(ext_fbk_cntr_index);
|
|
|
|
areset_ena_sig <= areset_ipd or (not ena_ipd) or sig_stop_vco;
|
|
|
|
pll_in_test_mode <= true when m_test_source /= 5 or c0_test_source /= 5 or
|
|
c1_test_source /= 5 or c2_test_source /= 5 or
|
|
c3_test_source /= 5 or c4_test_source /= 5 or
|
|
c5_test_source /= 5 else
|
|
false;
|
|
|
|
|
|
m1 : arm_m_cntr
|
|
port map ( clk => inclk_m,
|
|
reset => areset_ena_sig,
|
|
cout => fbclk,
|
|
initial_value => m_initial_val,
|
|
modulus => m_val(0),
|
|
time_delay => m_delay
|
|
);
|
|
|
|
-- add delta delay to inclk1 to ensure inclk0 and inclk1 are processed
|
|
-- in different simulation deltas.
|
|
inclk1_tmp <= inclk1_ipd;
|
|
|
|
process (inclk0_ipd, inclk1_tmp, clkswitch_ipd)
|
|
variable input_value : std_logic := '0';
|
|
variable current_clock : integer := 0;
|
|
variable clk0_count, clk1_count : integer := 0;
|
|
variable clk0_is_bad, clk1_is_bad : std_logic := '0';
|
|
variable primary_clk_is_bad : boolean := false;
|
|
variable current_clk_is_bad : boolean := false;
|
|
variable got_curr_clk_falling_edge_after_clkswitch : boolean := false;
|
|
variable switch_over_count : integer := 0;
|
|
variable active_clock : std_logic := '0';
|
|
variable external_switch : boolean := false;
|
|
begin
|
|
if (now = 0 ps) then
|
|
if (switch_over_type = "manual" and clkswitch_ipd = '1') then
|
|
current_clock := 1;
|
|
active_clock := '1';
|
|
end if;
|
|
end if;
|
|
if (clkswitch_ipd'event and clkswitch_ipd = '1' and switch_over_type = "auto") then
|
|
external_switch := true;
|
|
elsif (switch_over_type = "manual") then
|
|
if (clkswitch_ipd'event and clkswitch_ipd = '1') then
|
|
current_clock := 1;
|
|
active_clock := '1';
|
|
clkin <= transport inclk1_tmp;
|
|
elsif (clkswitch_ipd'event and clkswitch_ipd = '0') then
|
|
current_clock := 0;
|
|
active_clock := '0';
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
end if;
|
|
-- save the current inclk event value
|
|
if (inclk0_ipd'event) then
|
|
input_value := inclk0_ipd;
|
|
elsif (inclk1_tmp'event) then
|
|
input_value := inclk1_tmp;
|
|
end if;
|
|
|
|
-- check if either input clk is bad
|
|
if (inclk0_ipd'event and inclk0_ipd = '1') then
|
|
clk0_count := clk0_count + 1;
|
|
clk0_is_bad := '0';
|
|
clk1_count := 0;
|
|
if (clk0_count > 2) then
|
|
-- no event on other clk for 2 cycles
|
|
clk1_is_bad := '1';
|
|
if (current_clock = 1) then
|
|
current_clk_is_bad := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (inclk1_tmp'event and inclk1_tmp = '1') then
|
|
clk1_count := clk1_count + 1;
|
|
clk1_is_bad := '0';
|
|
clk0_count := 0;
|
|
if (clk1_count > 2) then
|
|
-- no event on other clk for 2 cycles
|
|
clk0_is_bad := '1';
|
|
if (current_clock = 0) then
|
|
current_clk_is_bad := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- check if the bad clk is the primary clock
|
|
if (clk0_is_bad = '1') then
|
|
primary_clk_is_bad := true;
|
|
else
|
|
primary_clk_is_bad := false;
|
|
end if;
|
|
|
|
-- actual switching
|
|
if (inclk0_ipd'event and current_clock = 0) then
|
|
if (external_switch) then
|
|
if (not got_curr_clk_falling_edge_after_clkswitch) then
|
|
if (inclk0_ipd = '0') then
|
|
got_curr_clk_falling_edge_after_clkswitch := true;
|
|
end if;
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
else
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
elsif (inclk1_tmp'event and current_clock = 1) then
|
|
if (external_switch) then
|
|
if (not got_curr_clk_falling_edge_after_clkswitch) then
|
|
if (inclk1_tmp = '0') then
|
|
got_curr_clk_falling_edge_after_clkswitch := true;
|
|
end if;
|
|
clkin <= transport inclk1_tmp;
|
|
end if;
|
|
else
|
|
clkin <= transport inclk1_tmp;
|
|
end if;
|
|
else
|
|
if (input_value = '1' and switch_over_on_lossclk = "on" and enable_switch_over_counter = "on" and primary_clk_is_bad) then
|
|
switch_over_count := switch_over_count + 1;
|
|
end if;
|
|
if (input_value = '0') then
|
|
if (external_switch and (got_curr_clk_falling_edge_after_clkswitch or current_clk_is_bad)) or (switch_over_on_lossclk = "on" and primary_clk_is_bad and clkswitch_ipd /= '1' and (enable_switch_over_counter = "off" or switch_over_count = switch_over_counter)) then
|
|
got_curr_clk_falling_edge_after_clkswitch := false;
|
|
if (current_clock = 0) then
|
|
current_clock := 1;
|
|
else
|
|
current_clock := 0;
|
|
end if;
|
|
active_clock := not active_clock;
|
|
switch_over_count := 0;
|
|
external_switch := false;
|
|
current_clk_is_bad := false;
|
|
end if;
|
|
|
|
end if;
|
|
end if;
|
|
|
|
-- schedule outputs
|
|
clkbad(0) <= clk0_is_bad;
|
|
clkbad(1) <= clk1_is_bad;
|
|
if (switch_over_on_lossclk = "on" and clkswitch_ipd /= '1') then
|
|
if (primary_clk_is_bad) then
|
|
-- assert clkloss
|
|
clkloss <= '1';
|
|
else
|
|
clkloss <= '0';
|
|
end if;
|
|
else
|
|
clkloss <= clkswitch_ipd;
|
|
end if;
|
|
activeclock <= active_clock;
|
|
|
|
end process;
|
|
|
|
process (inclk_sclkout0_from_vco)
|
|
begin
|
|
sclkout0_tmp <= inclk_sclkout0_from_vco;
|
|
end process;
|
|
|
|
process (inclk_sclkout1_from_vco)
|
|
begin
|
|
sclkout1_tmp <= inclk_sclkout1_from_vco;
|
|
end process;
|
|
|
|
n1 : arm_n_cntr
|
|
port map (
|
|
clk => clkin,
|
|
reset => areset_ipd,
|
|
cout => refclk,
|
|
initial_value => n_val(0),
|
|
modulus => n_val(0));
|
|
|
|
|
|
inclk_c0 <= clkin when c0_test_source = 0 else
|
|
refclk when c0_test_source = 1 else
|
|
inclk_c_from_vco(0);
|
|
c0 : arm_scale_cntr
|
|
port map (
|
|
clk => inclk_c0,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(0),
|
|
initial => c_initial_val(0),
|
|
high => c_high_val(0),
|
|
low => c_low_val(0),
|
|
mode => c_mode_val(0),
|
|
ph_tap => c_ph_val(0));
|
|
|
|
|
|
inclk_c1 <= clkin when c1_test_source = 0 else
|
|
fbclk when c1_test_source = 2 else
|
|
c_clk(0) when c1_use_casc_in = "on" else
|
|
inclk_c_from_vco(1);
|
|
c1 : arm_scale_cntr
|
|
port map (
|
|
clk => inclk_c1,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(1),
|
|
initial => c_initial_val(1),
|
|
high => c_high_val(1),
|
|
low => c_low_val(1),
|
|
mode => c_mode_val(1),
|
|
ph_tap => c_ph_val(1));
|
|
|
|
|
|
inclk_c2 <= clkin when c2_test_source = 0 else
|
|
c_clk(1) when c2_use_casc_in = "on" else
|
|
inclk_c_from_vco(2);
|
|
c2 : arm_scale_cntr
|
|
port map (
|
|
clk => inclk_c2,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(2),
|
|
initial => c_initial_val(2),
|
|
high => c_high_val(2),
|
|
low => c_low_val(2),
|
|
mode => c_mode_val(2),
|
|
ph_tap => c_ph_val(2));
|
|
|
|
|
|
inclk_c3 <= clkin when c3_test_source = 0 else
|
|
c_clk(2) when c3_use_casc_in = "on" else
|
|
inclk_c_from_vco(3);
|
|
c3 : arm_scale_cntr
|
|
port map (
|
|
clk => inclk_c3,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(3),
|
|
initial => c_initial_val(3),
|
|
high => c_high_val(3),
|
|
low => c_low_val(3),
|
|
mode => c_mode_val(3),
|
|
ph_tap => c_ph_val(3));
|
|
|
|
inclk_c4 <= '0' when (pll_type = "fast") else
|
|
clkin when (c4_test_source = 0) else
|
|
c_clk(3) when (c4_use_casc_in = "on") else
|
|
inclk_c_from_vco(4);
|
|
c4 : arm_scale_cntr
|
|
port map (
|
|
clk => inclk_c4,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(4),
|
|
initial => c_initial_val(4),
|
|
high => c_high_val(4),
|
|
low => c_low_val(4),
|
|
mode => c_mode_val(4),
|
|
ph_tap => c_ph_val(4));
|
|
|
|
inclk_c5 <= '0' when (pll_type = "fast") else
|
|
clkin when c5_test_source = 0 else
|
|
c_clk(4) when c5_use_casc_in = "on" else
|
|
inclk_c_from_vco(5);
|
|
c5 : arm_scale_cntr
|
|
port map (
|
|
clk => inclk_c5,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(5),
|
|
initial => c_initial_val(5),
|
|
high => c_high_val(5),
|
|
low => c_low_val(5),
|
|
mode => c_mode_val(5),
|
|
ph_tap => c_ph_val(5));
|
|
|
|
inclk_c0_dly1 <= inclk_c0 when (pll_type = "fast" or pll_type = "lvds")
|
|
else '0';
|
|
inclk_c0_dly2 <= inclk_c0_dly1;
|
|
inclk_c0_dly3 <= inclk_c0_dly2;
|
|
inclk_c0_dly4 <= inclk_c0_dly3;
|
|
inclk_c0_dly5 <= inclk_c0_dly4;
|
|
inclk_c0_dly6 <= inclk_c0_dly5;
|
|
|
|
inclk_c1_dly1 <= inclk_c1 when (pll_type = "fast" or pll_type = "lvds")
|
|
else '0';
|
|
inclk_c1_dly2 <= inclk_c1_dly1;
|
|
inclk_c1_dly3 <= inclk_c1_dly2;
|
|
inclk_c1_dly4 <= inclk_c1_dly3;
|
|
inclk_c1_dly5 <= inclk_c1_dly4;
|
|
inclk_c1_dly6 <= inclk_c1_dly5;
|
|
|
|
process(inclk_c0_dly6, inclk_c1_dly6, areset_ipd, ena_ipd, sig_stop_vco)
|
|
variable c0_got_first_rising_edge : boolean := false;
|
|
variable c0_count : integer := 2;
|
|
variable c0_initial_count : integer := 1;
|
|
variable c0_tmp, c1_tmp : std_logic := '0';
|
|
variable c1_got_first_rising_edge : boolean := false;
|
|
variable c1_count : integer := 2;
|
|
variable c1_initial_count : integer := 1;
|
|
begin
|
|
if (areset_ipd = '1' or ena_ipd = '0' or sig_stop_vco = '1') then
|
|
c0_count := 2;
|
|
c1_count := 2;
|
|
c0_initial_count := 1;
|
|
c1_initial_count := 1;
|
|
c0_got_first_rising_edge := false;
|
|
c1_got_first_rising_edge := false;
|
|
else
|
|
if (not c0_got_first_rising_edge) then
|
|
if (inclk_c0_dly6'event and inclk_c0_dly6 = '1') then
|
|
if (c0_initial_count = c_initial_val(0)) then
|
|
c0_got_first_rising_edge := true;
|
|
else
|
|
c0_initial_count := c0_initial_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (inclk_c0_dly6'event) then
|
|
c0_count := c0_count + 1;
|
|
if (c0_count = (c_high_val(0) + c_low_val(0)) * 2) then
|
|
c0_count := 1;
|
|
end if;
|
|
end if;
|
|
if (inclk_c0_dly6'event and inclk_c0_dly6 = '0') then
|
|
if (c0_count = 1) then
|
|
c0_tmp := '1';
|
|
c0_got_first_rising_edge := false;
|
|
else
|
|
c0_tmp := '0';
|
|
end if;
|
|
end if;
|
|
|
|
if (not c1_got_first_rising_edge) then
|
|
if (inclk_c1_dly6'event and inclk_c1_dly6 = '1') then
|
|
if (c1_initial_count = c_initial_val(1)) then
|
|
c1_got_first_rising_edge := true;
|
|
else
|
|
c1_initial_count := c1_initial_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (inclk_c1_dly6'event) then
|
|
c1_count := c1_count + 1;
|
|
if (c1_count = (c_high_val(1) + c_low_val(1)) * 2) then
|
|
c1_count := 1;
|
|
end if;
|
|
end if;
|
|
if (inclk_c1_dly6'event and inclk_c1_dly6 = '0') then
|
|
if (c1_count = 1) then
|
|
c1_tmp := '1';
|
|
c1_got_first_rising_edge := false;
|
|
else
|
|
c1_tmp := '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (enable0_counter = "c0") then
|
|
enable0_tmp <= c0_tmp;
|
|
elsif (enable0_counter = "c1") then
|
|
enable0_tmp <= c1_tmp;
|
|
else
|
|
enable0_tmp <= '0';
|
|
end if;
|
|
|
|
if (enable1_counter = "c0") then
|
|
enable1_tmp <= c0_tmp;
|
|
elsif (enable1_counter = "c1") then
|
|
enable1_tmp <= c1_tmp;
|
|
else
|
|
enable1_tmp <= '0';
|
|
end if;
|
|
|
|
end process;
|
|
|
|
glocked_cntr : process(clkin, ena_ipd, areset_ipd)
|
|
variable count : integer := 0;
|
|
variable output : std_logic := '0';
|
|
begin
|
|
if (areset_ipd = '1') then
|
|
count := 0;
|
|
output := '0';
|
|
elsif (clkin'event and clkin = '1') then
|
|
if (ena_ipd = '1') then
|
|
count := count + 1;
|
|
if (sim_gate_lock_device_behavior = "on") then
|
|
if (count = gate_lock_counter) then
|
|
output := '1';
|
|
end if;
|
|
elsif (count = GATE_LOCK_CYCLES) then
|
|
output := '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
gate_locked <= output;
|
|
end process;
|
|
|
|
locked <= gate_locked and lock when gate_lock_signal = "yes" else
|
|
lock;
|
|
|
|
|
|
process (scandone_tmp)
|
|
variable buf : line;
|
|
begin
|
|
if (scandone_tmp'event and scandone_tmp = '1') then
|
|
if (reconfig_err = false) then
|
|
ASSERT false REPORT family_name & " PLL Reprogramming completed with the following values (Values in parantheses indicate values before reprogramming) :" severity note;
|
|
write (buf, string'(" N modulus = "));
|
|
write (buf, n_val(0));
|
|
write (buf, string'(" ( "));
|
|
write (buf, n_val_old(0));
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" M modulus = "));
|
|
write (buf, m_val(0));
|
|
write (buf, string'(" ( "));
|
|
write (buf, m_val_old(0));
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" M ph_tap = "));
|
|
write (buf, m_ph_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, m_ph_val_old);
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
if (ss > 0) then
|
|
write (buf, string'(" M2 modulus = "));
|
|
write (buf, m_val(1));
|
|
write (buf, string'(" ( "));
|
|
write (buf, m_val_old(1));
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" N2 modulus = "));
|
|
write (buf, n_val(1));
|
|
write (buf, string'(" ( "));
|
|
write (buf, n_val_old(1));
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
end if;
|
|
|
|
for i in 0 to (num_output_cntrs-1) loop
|
|
write (buf, cntrs(i));
|
|
write (buf, string'(" : high = "));
|
|
write (buf, c_high_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_high_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , low = "));
|
|
write (buf, sig_c_low_val_tmp(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_low_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , mode = "));
|
|
write (buf, c_mode_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_mode_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , phase tap = "));
|
|
write (buf, c_ph_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_ph_val_old(i));
|
|
write (buf, string'(") "));
|
|
writeline(output, buf);
|
|
end loop;
|
|
|
|
write (buf, string'(" Charge Pump Current (uA) = "));
|
|
write (buf, cp_curr_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, cp_curr_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Capacitor (pF) = "));
|
|
write (buf, lfc_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfc_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Resistor (Kohm) = "));
|
|
write (buf, lfr_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfr_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
else ASSERT false REPORT "Errors were encountered during PLL reprogramming. Please refer to error/warning messages above." severity warning;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process (scanwrite_enabled, c_clk(0), c_clk(1), c_clk(2), c_clk(3), c_clk(4), c_clk(5), vco_tap, fbclk, scanclk_ipd, gated_scanclk)
|
|
variable init : boolean := true;
|
|
variable low, high : std_logic_vector(7 downto 0);
|
|
variable low_fast, high_fast : std_logic_vector(3 downto 0);
|
|
variable mode : string(1 to 6) := "bypass";
|
|
variable is_error : boolean := false;
|
|
variable m_tmp, n_tmp : std_logic_vector(8 downto 0);
|
|
variable n_fast : std_logic_vector(1 downto 0);
|
|
variable c_high_val_tmp : int_array(0 to 5) := (OTHERS => 1);
|
|
variable c_low_val_tmp : int_array(0 to 5) := (OTHERS => 1);
|
|
variable c_ph_val_tmp : int_array(0 to 5) := (OTHERS => 0);
|
|
variable c_mode_val_tmp : str_array(0 to 5);
|
|
variable m_ph_val_tmp : integer := 0;
|
|
variable m_val_tmp : int_array(0 to 1) := (OTHERS => 1);
|
|
variable c0_rising_edge_transfer_done : boolean := false;
|
|
variable c1_rising_edge_transfer_done : boolean := false;
|
|
variable c2_rising_edge_transfer_done : boolean := false;
|
|
variable c3_rising_edge_transfer_done : boolean := false;
|
|
variable c4_rising_edge_transfer_done : boolean := false;
|
|
variable c5_rising_edge_transfer_done : boolean := false;
|
|
|
|
-- variables for scaling of multiply_by and divide_by values
|
|
variable i_clk0_mult_by : integer := 1;
|
|
variable i_clk0_div_by : integer := 1;
|
|
variable i_clk1_mult_by : integer := 1;
|
|
variable i_clk1_div_by : integer := 1;
|
|
variable i_clk2_mult_by : integer := 1;
|
|
variable i_clk2_div_by : integer := 1;
|
|
variable i_clk3_mult_by : integer := 1;
|
|
variable i_clk3_div_by : integer := 1;
|
|
variable i_clk4_mult_by : integer := 1;
|
|
variable i_clk4_div_by : integer := 1;
|
|
variable i_clk5_mult_by : integer := 1;
|
|
variable i_clk5_div_by : integer := 1;
|
|
variable max_d_value : integer := 1;
|
|
variable new_multiplier : integer := 1;
|
|
|
|
-- internal variables for storing the phase shift number.(used in lvds mode only)
|
|
variable i_clk0_phase_shift : integer := 1;
|
|
variable i_clk1_phase_shift : integer := 1;
|
|
variable i_clk2_phase_shift : integer := 1;
|
|
|
|
-- user to advanced variables
|
|
|
|
variable max_neg_abs : integer := 0;
|
|
variable i_m_initial : integer;
|
|
variable i_m : integer := 1;
|
|
variable i_n : integer := 1;
|
|
variable i_m2 : integer;
|
|
variable i_n2 : integer;
|
|
variable i_ss : integer;
|
|
variable i_c_high : int_array(0 to 5);
|
|
variable i_c_low : int_array(0 to 5);
|
|
variable i_c_initial : int_array(0 to 5);
|
|
variable i_c_ph : int_array(0 to 5);
|
|
variable i_c_mode : str_array(0 to 5);
|
|
variable i_m_ph : integer;
|
|
variable output_count : integer;
|
|
variable new_divisor : integer;
|
|
|
|
variable clk0_cntr : string(1 to 2) := "c0";
|
|
variable clk1_cntr : string(1 to 2) := "c1";
|
|
variable clk2_cntr : string(1 to 2) := "c2";
|
|
variable clk3_cntr : string(1 to 2) := "c3";
|
|
variable clk4_cntr : string(1 to 2) := "c4";
|
|
variable clk5_cntr : string(1 to 2) := "c5";
|
|
|
|
variable fbk_cntr : string(1 to 2);
|
|
variable fbk_cntr_index : integer;
|
|
variable start_bit : integer;
|
|
variable quiet_time : time := 0 ps;
|
|
variable slowest_clk_old : time := 0 ps;
|
|
variable slowest_clk_new : time := 0 ps;
|
|
variable tmp_scan_data : std_logic_vector(173 downto 0) := (OTHERS => '0');
|
|
variable m_lo, m_hi : std_logic_vector(4 downto 0);
|
|
|
|
variable j : integer := 0;
|
|
variable scanread_active_edge : time := 0 ps;
|
|
variable got_first_scanclk : boolean := false;
|
|
variable got_first_gated_scanclk : boolean := false;
|
|
variable scanclk_last_rising_edge : time := 0 ps;
|
|
variable scanclk_period : time := 0 ps;
|
|
variable current_scan_data : std_logic_vector(173 downto 0) := (OTHERS => '0');
|
|
variable index : integer := 0;
|
|
variable scan_chain_length : integer := GPP_SCAN_CHAIN;
|
|
variable tmp_rem : integer := 0;
|
|
variable scanclk_cycles : integer := 0;
|
|
variable lfc_tmp : std_logic_vector(1 downto 0);
|
|
variable lfr_tmp : std_logic_vector(5 downto 0);
|
|
variable lfr_int : integer := 0;
|
|
|
|
function slowest_clk (
|
|
C0 : integer; C0_mode : string(1 to 6);
|
|
C1 : integer; C1_mode : string(1 to 6);
|
|
C2 : integer; C2_mode : string(1 to 6);
|
|
C3 : integer; C3_mode : string(1 to 6);
|
|
C4 : integer; C4_mode : string(1 to 6);
|
|
C5 : integer; C5_mode : string(1 to 6);
|
|
refclk : time; m_mod : integer) return time is
|
|
variable max_modulus : integer := 1;
|
|
variable q_period : time := 0 ps;
|
|
variable refclk_int : integer := 0;
|
|
begin
|
|
if (C0_mode /= "bypass" and C0_mode /= " off") then
|
|
max_modulus := C0;
|
|
end if;
|
|
if (C1 > max_modulus and C1_mode /= "bypass" and C1_mode /= " off") then
|
|
max_modulus := C1;
|
|
end if;
|
|
if (C2 > max_modulus and C2_mode /= "bypass" and C2_mode /= " off") then
|
|
max_modulus := C2;
|
|
end if;
|
|
if (C3 > max_modulus and C3_mode /= "bypass" and C3_mode /= " off") then
|
|
max_modulus := C3;
|
|
end if;
|
|
if (C4 > max_modulus and C4_mode /= "bypass" and C4_mode /= " off") then
|
|
max_modulus := C4;
|
|
end if;
|
|
if (C5 > max_modulus and C5_mode /= "bypass" and C5_mode /= " off") then
|
|
max_modulus := C5;
|
|
end if;
|
|
|
|
refclk_int := refclk / 1 ps;
|
|
if (m_mod /= 0) then
|
|
if (refclk_int > (refclk_int * max_modulus / m_mod)) then
|
|
q_period := refclk_int * 1 ps;
|
|
else
|
|
q_period := (refclk_int * max_modulus / m_mod) * 1 ps;
|
|
end if;
|
|
end if;
|
|
return (2*q_period);
|
|
end slowest_clk;
|
|
|
|
function int2bin (arg : integer; size : integer) return std_logic_vector is
|
|
variable int_val : integer := arg;
|
|
variable result : std_logic_vector(size-1 downto 0);
|
|
begin
|
|
for i in 0 to result'left loop
|
|
if ((int_val mod 2) = 0) then
|
|
result(i) := '0';
|
|
else
|
|
result(i) := '1';
|
|
end if;
|
|
int_val := int_val/2;
|
|
end loop;
|
|
return result;
|
|
end int2bin;
|
|
|
|
function extract_cntr_index (arg:string) return integer is
|
|
variable index : integer := 0;
|
|
begin
|
|
if (arg(2) = '0') then
|
|
index := 0;
|
|
elsif (arg(2) = '1') then
|
|
index := 1;
|
|
elsif (arg(2) = '2') then
|
|
index := 2;
|
|
elsif (arg(2) = '3') then
|
|
index := 3;
|
|
elsif (arg(2) = '4') then
|
|
index := 4;
|
|
else index := 5;
|
|
end if;
|
|
|
|
return index;
|
|
end extract_cntr_index;
|
|
|
|
begin
|
|
if (init) then
|
|
if (m = 0) then
|
|
clk5_cntr := "c5";
|
|
clk4_cntr := "c4";
|
|
clk3_cntr := "c3";
|
|
clk2_cntr := "c2";
|
|
clk1_cntr := "c1";
|
|
clk0_cntr := "c0";
|
|
else
|
|
clk5_cntr := clk5_counter;
|
|
clk4_cntr := clk4_counter;
|
|
clk3_cntr := clk3_counter;
|
|
clk2_cntr := clk2_counter;
|
|
clk1_cntr := clk1_counter;
|
|
clk0_cntr := clk0_counter;
|
|
end if;
|
|
|
|
if (operation_mode = "external_feedback") then
|
|
if (feedback_source = "clk0") then
|
|
fbk_cntr := clk0_cntr;
|
|
elsif (feedback_source = "clk1") then
|
|
fbk_cntr := clk1_cntr;
|
|
elsif (feedback_source = "clk2") then
|
|
fbk_cntr := clk2_cntr;
|
|
elsif (feedback_source = "clk3") then
|
|
fbk_cntr := clk3_cntr;
|
|
elsif (feedback_source = "clk4") then
|
|
fbk_cntr := clk4_cntr;
|
|
elsif (feedback_source = "clk5") then
|
|
fbk_cntr := clk5_cntr;
|
|
else
|
|
fbk_cntr := "c0";
|
|
end if;
|
|
|
|
if (fbk_cntr = "c0") then
|
|
fbk_cntr_index := 0;
|
|
elsif (fbk_cntr = "c1") then
|
|
fbk_cntr_index := 1;
|
|
elsif (fbk_cntr = "c2") then
|
|
fbk_cntr_index := 2;
|
|
elsif (fbk_cntr = "c3") then
|
|
fbk_cntr_index := 3;
|
|
elsif (fbk_cntr = "c4") then
|
|
fbk_cntr_index := 4;
|
|
elsif (fbk_cntr = "c5") then
|
|
fbk_cntr_index := 5;
|
|
end if;
|
|
|
|
ext_fbk_cntr <= fbk_cntr;
|
|
ext_fbk_cntr_index <= fbk_cntr_index;
|
|
end if;
|
|
i_clk0_counter <= extract_cntr_index(clk0_cntr);
|
|
i_clk1_counter <= extract_cntr_index(clk1_cntr);
|
|
i_clk2_counter <= extract_cntr_index(clk2_cntr);
|
|
i_clk3_counter <= extract_cntr_index(clk3_cntr);
|
|
i_clk4_counter <= extract_cntr_index(clk4_cntr);
|
|
i_clk5_counter <= extract_cntr_index(clk5_cntr);
|
|
|
|
|
|
if (m = 0) then -- convert user parameters to advanced
|
|
-- set the limit of the divide_by value that can be returned by
|
|
-- the following function.
|
|
max_d_value := 500;
|
|
|
|
-- scale down the multiply_by and divide_by values provided by the design
|
|
-- before attempting to use them in the calculations below
|
|
find_simple_integer_fraction(clk0_multiply_by, clk0_divide_by,
|
|
max_d_value, i_clk0_mult_by, i_clk0_div_by);
|
|
find_simple_integer_fraction(clk1_multiply_by, clk1_divide_by,
|
|
max_d_value, i_clk1_mult_by, i_clk1_div_by);
|
|
find_simple_integer_fraction(clk2_multiply_by, clk2_divide_by,
|
|
max_d_value, i_clk2_mult_by, i_clk2_div_by);
|
|
find_simple_integer_fraction(clk3_multiply_by, clk3_divide_by,
|
|
max_d_value, i_clk3_mult_by, i_clk3_div_by);
|
|
find_simple_integer_fraction(clk4_multiply_by, clk4_divide_by,
|
|
max_d_value, i_clk4_mult_by, i_clk4_div_by);
|
|
find_simple_integer_fraction(clk5_multiply_by, clk5_divide_by,
|
|
max_d_value, i_clk5_mult_by, i_clk5_div_by);
|
|
|
|
if (((pll_type = "fast") or (pll_type = "lvds")) and ((vco_multiply_by /= 0) and (vco_divide_by /= 0))) then
|
|
i_n := vco_divide_by;
|
|
i_m := vco_multiply_by;
|
|
else
|
|
i_n := 1;
|
|
i_m := lcm (i_clk0_mult_by, i_clk1_mult_by,
|
|
i_clk2_mult_by, i_clk3_mult_by,
|
|
i_clk4_mult_by, i_clk5_mult_by,
|
|
1, 1, 1, 1, inclk0_input_frequency);
|
|
end if;
|
|
|
|
if (pll_type = "flvds") then
|
|
-- Need to readjust phase shift values when the clock multiply value has been readjusted.
|
|
new_multiplier := clk0_multiply_by / i_clk0_mult_by;
|
|
i_clk0_phase_shift := str2int(clk0_phase_shift) * new_multiplier;
|
|
i_clk1_phase_shift := str2int(clk1_phase_shift) * new_multiplier;
|
|
i_clk2_phase_shift := str2int(clk2_phase_shift) * new_multiplier;
|
|
else
|
|
i_clk0_phase_shift := str2int(clk0_phase_shift);
|
|
i_clk1_phase_shift := str2int(clk1_phase_shift);
|
|
i_clk2_phase_shift := str2int(clk2_phase_shift);
|
|
end if;
|
|
|
|
max_neg_abs := maxnegabs(i_clk0_phase_shift,
|
|
i_clk1_phase_shift,
|
|
i_clk2_phase_shift,
|
|
str2int(clk3_phase_shift),
|
|
str2int(clk4_phase_shift),
|
|
str2int(clk5_phase_shift),
|
|
0, 0, 0, 0);
|
|
i_m_ph := counter_ph(get_phase_degree(max_neg_abs,inclk0_input_frequency), i_m, i_n);
|
|
|
|
i_c_ph(0) := counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(1) := counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(2) := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(3) := counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(4) := counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(5) := counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_high(0) := counter_high(output_counter_value(i_clk0_div_by,
|
|
i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
|
|
i_c_high(1) := counter_high(output_counter_value(i_clk1_div_by,
|
|
i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
|
|
i_c_high(2) := counter_high(output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
i_c_high(3) := counter_high(output_counter_value(i_clk3_div_by,
|
|
i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
|
|
i_c_high(4) := counter_high(output_counter_value(i_clk4_div_by,
|
|
i_clk4_mult_by, i_m, i_n), clk4_duty_cycle);
|
|
i_c_high(5) := counter_high(output_counter_value(i_clk5_div_by,
|
|
i_clk5_mult_by, i_m, i_n), clk5_duty_cycle);
|
|
i_c_low(0) := counter_low(output_counter_value(i_clk0_div_by,
|
|
i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
|
|
i_c_low(1) := counter_low(output_counter_value(i_clk1_div_by,
|
|
i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
|
|
i_c_low(2) := counter_low(output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
i_c_low(3) := counter_low(output_counter_value(i_clk3_div_by,
|
|
i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
|
|
i_c_low(4) := counter_low(output_counter_value(i_clk4_div_by,
|
|
i_clk4_mult_by, i_m, i_n), clk4_duty_cycle);
|
|
i_c_low(5) := counter_low(output_counter_value(i_clk5_div_by,
|
|
i_clk5_mult_by, i_m, i_n), clk5_duty_cycle);
|
|
i_m_initial := counter_initial(get_phase_degree(max_neg_abs, inclk0_input_frequency), i_m,i_n);
|
|
|
|
i_c_initial(0) := counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(1) := counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(2) := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(3) := counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(4) := counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(5) := counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_mode(0) := counter_mode(clk0_duty_cycle, output_counter_value(i_clk0_div_by, i_clk0_mult_by, i_m, i_n));
|
|
i_c_mode(1) := counter_mode(clk1_duty_cycle, output_counter_value(i_clk1_div_by, i_clk1_mult_by, i_m, i_n));
|
|
i_c_mode(2) := counter_mode(clk2_duty_cycle, output_counter_value(i_clk2_div_by, i_clk2_mult_by, i_m, i_n));
|
|
i_c_mode(3) := counter_mode(clk3_duty_cycle, output_counter_value(i_clk3_div_by, i_clk3_mult_by, i_m, i_n));
|
|
i_c_mode(4) := counter_mode(clk4_duty_cycle, output_counter_value(i_clk4_div_by, i_clk4_mult_by, i_m, i_n));
|
|
i_c_mode(5) := counter_mode(clk5_duty_cycle, output_counter_value(i_clk5_div_by, i_clk5_mult_by, i_m, i_n));
|
|
|
|
-- in external feedback mode, need to adjust M value to take
|
|
-- into consideration the external feedback counter value
|
|
if(operation_mode = "external_feedback") then
|
|
-- if there is a negative phase shift, m_initial can
|
|
-- only be 1
|
|
if (max_neg_abs > 0) then
|
|
i_m_initial := 1;
|
|
end if;
|
|
|
|
-- calculate the feedback counter multiplier
|
|
if (i_c_mode(fbk_cntr_index) = "bypass") then
|
|
output_count := 1;
|
|
else
|
|
output_count := i_c_high(fbk_cntr_index) + i_c_low(fbk_cntr_index);
|
|
end if;
|
|
|
|
new_divisor := gcd(i_m, output_count);
|
|
i_m := i_m / new_divisor;
|
|
i_n := output_count / new_divisor;
|
|
end if;
|
|
|
|
else -- m /= 0
|
|
|
|
i_n := n;
|
|
i_m := m;
|
|
i_m_initial := m_initial;
|
|
i_m_ph := m_ph;
|
|
i_c_ph(0) := c0_ph;
|
|
i_c_ph(1) := c1_ph;
|
|
i_c_ph(2) := c2_ph;
|
|
i_c_ph(3) := c3_ph;
|
|
i_c_ph(4) := c4_ph;
|
|
i_c_ph(5) := c5_ph;
|
|
i_c_high(0) := c0_high;
|
|
i_c_high(1) := c1_high;
|
|
i_c_high(2) := c2_high;
|
|
i_c_high(3) := c3_high;
|
|
i_c_high(4) := c4_high;
|
|
i_c_high(5) := c5_high;
|
|
i_c_low(0) := c0_low;
|
|
i_c_low(1) := c1_low;
|
|
i_c_low(2) := c2_low;
|
|
i_c_low(3) := c3_low;
|
|
i_c_low(4) := c4_low;
|
|
i_c_low(5) := c5_low;
|
|
i_c_initial(0) := c0_initial;
|
|
i_c_initial(1) := c1_initial;
|
|
i_c_initial(2) := c2_initial;
|
|
i_c_initial(3) := c3_initial;
|
|
i_c_initial(4) := c4_initial;
|
|
i_c_initial(5) := c5_initial;
|
|
i_c_mode(0) := translate_string(c0_mode);
|
|
i_c_mode(1) := translate_string(c1_mode);
|
|
i_c_mode(2) := translate_string(c2_mode);
|
|
i_c_mode(3) := translate_string(c3_mode);
|
|
i_c_mode(4) := translate_string(c4_mode);
|
|
i_c_mode(5) := translate_string(c5_mode);
|
|
|
|
end if; -- user to advanced conversion.
|
|
|
|
m_initial_val <= i_m_initial;
|
|
n_val(0) <= i_n;
|
|
m_val(0) <= i_m;
|
|
m_val(1) <= m2;
|
|
n_val(1) <= n2;
|
|
|
|
if (i_m = 1) then
|
|
m_mode_val(0) <= "bypass";
|
|
else
|
|
m_mode_val(0) <= " ";
|
|
end if;
|
|
if (m2 = 1) then
|
|
m_mode_val(1) <= "bypass";
|
|
end if;
|
|
if (i_n = 1) then
|
|
n_mode_val(0) <= "bypass";
|
|
end if;
|
|
if (n2 = 1) then
|
|
n_mode_val(1) <= "bypass";
|
|
end if;
|
|
|
|
m_ph_val <= i_m_ph;
|
|
m_ph_val_tmp := i_m_ph;
|
|
m_val_tmp := m_val;
|
|
|
|
for i in 0 to 5 loop
|
|
if (i_c_mode(i) = "bypass") then
|
|
if (pll_type = "fast" or pll_type = "lvds") then
|
|
i_c_high(i) := 16;
|
|
i_c_low(i) := 16;
|
|
else
|
|
i_c_high(i) := 256;
|
|
i_c_low(i) := 256;
|
|
end if;
|
|
end if;
|
|
c_ph_val(i) <= i_c_ph(i);
|
|
c_initial_val(i) <= i_c_initial(i);
|
|
c_high_val(i) <= i_c_high(i);
|
|
c_low_val(i) <= i_c_low(i);
|
|
c_mode_val(i) <= i_c_mode(i);
|
|
c_high_val_tmp(i) := i_c_high(i);
|
|
c_low_val_tmp(i) := i_c_low(i);
|
|
c_mode_val_tmp(i) := i_c_mode(i);
|
|
c_ph_val_tmp(i) := i_c_ph(i);
|
|
c_ph_val_orig(i) <= i_c_ph(i);
|
|
c_high_val_hold(i) <= i_c_high(i);
|
|
c_low_val_hold(i) <= i_c_low(i);
|
|
c_mode_val_hold(i) <= i_c_mode(i);
|
|
end loop;
|
|
|
|
lfc_val <= loop_filter_c;
|
|
lfr_val <= loop_filter_r;
|
|
cp_curr_val <= charge_pump_current;
|
|
|
|
if (pll_type = "fast") then
|
|
scan_chain_length := FAST_SCAN_CHAIN;
|
|
end if;
|
|
-- initialize the scan_chain contents
|
|
-- CP/LF bits
|
|
scan_data(11 downto 0) <= "000000000000";
|
|
for i in 0 to 3 loop
|
|
if (pll_type = "fast" or pll_type = "lvds") then
|
|
if (fpll_loop_filter_c_arr(i) = loop_filter_c) then
|
|
scan_data(11 downto 10) <= int2bin(i, 2);
|
|
end if;
|
|
else
|
|
if (loop_filter_c_arr(i) = loop_filter_c) then
|
|
scan_data(11 downto 10) <= int2bin(i, 2);
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
for i in 0 to 15 loop
|
|
if (charge_pump_curr_arr(i) = charge_pump_current) then
|
|
scan_data(3 downto 0) <= int2bin(i, 4);
|
|
end if;
|
|
end loop;
|
|
for i in 0 to 39 loop
|
|
if (loop_filter_r_arr(i) = loop_filter_r) then
|
|
if (i >= 16 and i <= 23) then
|
|
scan_data(9 downto 4) <= int2bin((i+8), 6);
|
|
elsif (i >= 24 and i <= 31) then
|
|
scan_data(9 downto 4) <= int2bin((i+16), 6);
|
|
elsif (i >= 32) then
|
|
scan_data(9 downto 4) <= int2bin((i+24), 6);
|
|
else
|
|
scan_data(9 downto 4) <= int2bin(i, 6);
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
|
|
if (pll_type = "fast" or pll_type = "lvds") then
|
|
scan_data(21 downto 12) <= "0000000000"; -- M, C3-C0 ph
|
|
-- C0-C3 high
|
|
scan_data(25 downto 22) <= int2bin(i_c_high(0), 4);
|
|
scan_data(35 downto 32) <= int2bin(i_c_high(1), 4);
|
|
scan_data(45 downto 42) <= int2bin(i_c_high(2), 4);
|
|
scan_data(55 downto 52) <= int2bin(i_c_high(3), 4);
|
|
-- C0-C3 low
|
|
scan_data(30 downto 27) <= int2bin(i_c_low(0), 4);
|
|
scan_data(40 downto 37) <= int2bin(i_c_low(1), 4);
|
|
scan_data(50 downto 47) <= int2bin(i_c_low(2), 4);
|
|
scan_data(60 downto 57) <= int2bin(i_c_low(3), 4);
|
|
-- C0-C3 mode
|
|
for i in 0 to 3 loop
|
|
if (i_c_mode(i) = " off" or i_c_mode(i) = "bypass") then
|
|
scan_data(26 + (10*i)) <= '1';
|
|
if (i_c_mode(i) = " off") then
|
|
scan_data(31 + (10*i)) <= '1';
|
|
else
|
|
scan_data(31 + (10*i)) <= '0';
|
|
end if;
|
|
else
|
|
scan_data(26 + (10*i)) <= '0';
|
|
if (i_c_mode(i) = " odd") then
|
|
scan_data(31 + (10*i)) <= '1';
|
|
else
|
|
scan_data(31 + (10*i)) <= '0';
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
-- M
|
|
if (i_m = 1) then
|
|
scan_data(66) <= '1';
|
|
scan_data(71) <= '0';
|
|
scan_data(65 downto 62) <= "0000";
|
|
scan_data(70 downto 67) <= "0000";
|
|
else
|
|
scan_data(66) <= '0'; -- set BYPASS bit to 0
|
|
scan_data(70 downto 67) <= int2bin(i_m/2, 4); -- set M low
|
|
if (i_m rem 2 = 0) then
|
|
-- M is an even no. : set M high = low,
|
|
-- set odd/even bit to 0
|
|
scan_data(65 downto 62) <= int2bin(i_m/2, 4);
|
|
scan_data(71) <= '0';
|
|
else -- M is odd : M high = low + 1
|
|
scan_data(65 downto 62) <= int2bin((i_m/2) + 1, 4);
|
|
scan_data(71) <= '1';
|
|
end if;
|
|
end if;
|
|
-- N
|
|
scan_data(73 downto 72) <= int2bin(i_n, 2);
|
|
if (i_n = 1) then
|
|
scan_data(74) <= '1';
|
|
scan_data(73 downto 72) <= "00";
|
|
end if;
|
|
else -- PLL type is auto or enhanced
|
|
scan_data(25 downto 12) <= "00000000000000"; -- M, C5-C0 ph
|
|
-- C0-C5 high
|
|
scan_data(123 downto 116) <= int2bin(i_c_high(0), 8);
|
|
scan_data(105 downto 98) <= int2bin(i_c_high(1), 8);
|
|
scan_data(87 downto 80) <= int2bin(i_c_high(2), 8);
|
|
scan_data(69 downto 62) <= int2bin(i_c_high(3), 8);
|
|
scan_data(51 downto 44) <= int2bin(i_c_high(4), 8);
|
|
scan_data(33 downto 26) <= int2bin(i_c_high(5), 8);
|
|
-- C0-C5 low
|
|
scan_data(132 downto 125) <= int2bin(i_c_low(0), 8);
|
|
scan_data(114 downto 107) <= int2bin(i_c_low(1), 8);
|
|
scan_data(96 downto 89) <= int2bin(i_c_low(2), 8);
|
|
scan_data(78 downto 71) <= int2bin(i_c_low(3), 8);
|
|
scan_data(60 downto 53) <= int2bin(i_c_low(4), 8);
|
|
scan_data(42 downto 35) <= int2bin(i_c_low(5), 8);
|
|
-- C0-C5 mode
|
|
for i in 0 to 5 loop
|
|
if (i_c_mode(i) = " off" or i_c_mode(i) = "bypass") then
|
|
scan_data(124 - (18*i)) <= '1';
|
|
if (i_c_mode(i) = " off") then
|
|
scan_data(133 - (18*i)) <= '1';
|
|
else
|
|
scan_data(133 - (18*i)) <= '0';
|
|
end if;
|
|
else
|
|
scan_data(124 - (18*i)) <= '0';
|
|
if (i_c_mode(i) = " odd") then
|
|
scan_data(133 - (18*i)) <= '1';
|
|
else
|
|
scan_data(133 - (18*i)) <= '0';
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
|
|
-- M/M2
|
|
scan_data(142 downto 134) <= int2bin(i_m, 9);
|
|
scan_data(143) <= '0';
|
|
scan_data(152 downto 144) <= int2bin(m2, 9);
|
|
scan_data(153) <= '0';
|
|
if (i_m = 1) then
|
|
scan_data(143) <= '1';
|
|
scan_data(142 downto 134) <= "000000000";
|
|
end if;
|
|
if (m2 = 1) then
|
|
scan_data(153) <= '1';
|
|
scan_data(152 downto 144) <= "000000000";
|
|
end if;
|
|
|
|
-- N/N2
|
|
scan_data(162 downto 154) <= int2bin(i_n, 9);
|
|
scan_data(172 downto 164) <= int2bin(n2, 9);
|
|
if (i_n = 1) then
|
|
scan_data(163) <= '1';
|
|
scan_data(162 downto 154) <= "000000000";
|
|
end if;
|
|
if (n2 = 1) then
|
|
scan_data(173) <= '1';
|
|
scan_data(172 downto 164) <= "000000000";
|
|
end if;
|
|
|
|
end if;
|
|
if (pll_type = "fast" or pll_type = "lvds") then
|
|
num_output_cntrs <= 4;
|
|
else
|
|
num_output_cntrs <= 6;
|
|
end if;
|
|
|
|
init := false;
|
|
elsif (scanwrite_enabled'event and scanwrite_enabled = '0') then
|
|
-- falling edge : deassert scandone
|
|
scandone_tmp <= transport '0' after (1.5 * scanclk_period);
|
|
c0_rising_edge_transfer_done := false;
|
|
c1_rising_edge_transfer_done := false;
|
|
c2_rising_edge_transfer_done := false;
|
|
c3_rising_edge_transfer_done := false;
|
|
c4_rising_edge_transfer_done := false;
|
|
c5_rising_edge_transfer_done := false;
|
|
elsif (scanwrite_enabled'event and scanwrite_enabled = '1') then
|
|
ASSERT false REPORT "PLL Reprogramming Initiated" severity note;
|
|
|
|
reconfig_err <= false;
|
|
|
|
-- make temporary copy of scan_data for processing
|
|
tmp_scan_data := scan_data;
|
|
|
|
-- save old values
|
|
lfc_old <= lfc_val;
|
|
lfr_old <= lfr_val;
|
|
cp_curr_old <= cp_curr_val;
|
|
|
|
-- CP
|
|
-- Bits 0-3 : all values are legal
|
|
cp_curr_val <= charge_pump_curr_arr(alt_conv_integer(scan_data(3 downto 0)));
|
|
|
|
-- LF Resistance : bits 4-9
|
|
-- values from 010000 - 010111, 100000 - 100111,
|
|
-- 110000 - 110111 are illegal
|
|
lfr_tmp := tmp_scan_data(9 downto 4);
|
|
lfr_int := alt_conv_integer(lfr_tmp);
|
|
if (((lfr_int >= 16) and (lfr_int <= 23)) or
|
|
((lfr_int >= 32) and (lfr_int <= 39)) or
|
|
((lfr_int >= 48) and (lfr_int <= 55))) then
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Illegal bit settings for Loop Filter Resistance. Legal bit values range from 000000-001111, 011000-011111, 101000-101111 and 111000-111111. Reconfiguration may not work." severity warning;
|
|
else
|
|
if (lfr_int >= 56) then
|
|
lfr_int := lfr_int - 24;
|
|
elsif ((lfr_int >= 40) and (lfr_int <= 47)) then
|
|
lfr_int := lfr_int - 16;
|
|
elsif ((lfr_int >= 24) and (lfr_int <= 31)) then
|
|
lfr_int := lfr_int - 8;
|
|
end if;
|
|
lfr_val <= loop_filter_r_arr(lfr_int);
|
|
end if;
|
|
|
|
-- LF Capacitance : bits 10,11 : all values are legal
|
|
lfc_tmp := scan_data(11 downto 10);
|
|
if (pll_type = "fast" or pll_type = "lvds") then
|
|
lfc_val <= fpll_loop_filter_c_arr(alt_conv_integer(lfc_tmp));
|
|
else
|
|
lfc_val <= loop_filter_c_arr(alt_conv_integer(lfc_tmp));
|
|
end if;
|
|
|
|
-- cntrs c0-c5
|
|
-- save old values for display info.
|
|
m_val_old <= m_val;
|
|
n_val_old <= n_val;
|
|
m_mode_val_old <= m_mode_val;
|
|
n_mode_val_old <= n_mode_val;
|
|
m_ph_val_old <= m_ph_val;
|
|
c_high_val_old <= c_high_val;
|
|
c_low_val_old <= c_low_val;
|
|
c_ph_val_old <= c_ph_val;
|
|
c_mode_val_old <= c_mode_val;
|
|
|
|
-- first the M counter phase : bit order same for fast and GPP
|
|
if (scan_data(12) = '0') then
|
|
-- do nothing
|
|
elsif (scan_data(12) = '1' and scan_data(13) = '1') then
|
|
m_ph_val_tmp := m_ph_val_tmp + 1;
|
|
if (m_ph_val_tmp > 7) then
|
|
m_ph_val_tmp := 0;
|
|
end if;
|
|
elsif (scan_data(12) = '1' and scan_data(13) = '0') then
|
|
m_ph_val_tmp := m_ph_val_tmp - 1;
|
|
if (m_ph_val_tmp < 0) then
|
|
m_ph_val_tmp := 7;
|
|
end if;
|
|
else
|
|
reconfig_err <= true;
|
|
ASSERT false REPORT "Illegal values for M counter phase tap. Reconfiguration may not work." severity warning;
|
|
end if;
|
|
|
|
-- read the fast PLL bits
|
|
if (pll_type = "fast" or pll_type = "lvds") then
|
|
-- C3-C0 phase bits
|
|
for i in 3 downto 0 loop
|
|
start_bit := 14 + ((3-i)*2);
|
|
if (tmp_scan_data(start_bit) = '0') then
|
|
-- do nothing
|
|
elsif (tmp_scan_data(start_bit) = '1') then
|
|
if (tmp_scan_data(start_bit + 1) = '1') then
|
|
c_ph_val_tmp(i) := c_ph_val_tmp(i) + 1;
|
|
if (c_ph_val_tmp(i) > 7) then
|
|
c_ph_val_tmp(i) := 0;
|
|
end if;
|
|
elsif (tmp_scan_data(start_bit + 1) = '0') then
|
|
c_ph_val_tmp(i) := c_ph_val_tmp(i) - 1;
|
|
if (c_ph_val_tmp(i) < 0) then
|
|
c_ph_val_tmp(i) := 7;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
-- C0-C3 counter moduli
|
|
for i in 0 to 3 loop
|
|
start_bit := 22 + (i*10);
|
|
if (tmp_scan_data(start_bit + 4) = '1') then
|
|
c_mode_val_tmp(i) := "bypass";
|
|
if (tmp_scan_data(start_bit + 9) = '1') then
|
|
c_mode_val_tmp(i) := " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the " &cntrs(i)& "counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (tmp_scan_data(start_bit + 9) = '1') then
|
|
c_mode_val_tmp(i) := " odd";
|
|
else
|
|
c_mode_val_tmp(i) := " even";
|
|
end if;
|
|
high_fast := tmp_scan_data(start_bit+3 downto start_bit);
|
|
low_fast := tmp_scan_data(start_bit+8 downto start_bit+5);
|
|
if (tmp_scan_data(start_bit+3 downto start_bit) = "0000") then
|
|
c_high_val_tmp(i) := 16;
|
|
else
|
|
c_high_val_tmp(i) := alt_conv_integer(high_fast);
|
|
end if;
|
|
if (tmp_scan_data(start_bit+8 downto start_bit+5) = "0000") then
|
|
c_low_val_tmp(i) := 16;
|
|
else
|
|
c_low_val_tmp(i) := alt_conv_integer(low_fast);
|
|
end if;
|
|
end loop;
|
|
sig_c_ph_val_tmp <= c_ph_val_tmp;
|
|
sig_c_low_val_tmp <= c_low_val_tmp;
|
|
sig_c_hi_val_tmp <= c_high_val_tmp;
|
|
-- M
|
|
-- some temporary storage
|
|
if (tmp_scan_data(65 downto 62) = "0000") then
|
|
m_hi := "10000";
|
|
else
|
|
m_hi := "0" & tmp_scan_data(65 downto 62);
|
|
end if;
|
|
if (tmp_scan_data(70 downto 67) = "0000") then
|
|
m_lo := "10000";
|
|
else
|
|
m_lo := "0" & tmp_scan_data(70 downto 67);
|
|
end if;
|
|
m_val_tmp(0) := alt_conv_integer(m_hi) + alt_conv_integer(m_lo);
|
|
if (tmp_scan_data(66) = '1') then
|
|
if (tmp_scan_data(71) = '1') then
|
|
-- this will turn off the M counter : error
|
|
reconfig_err <= true;
|
|
is_error := true;
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the M counter. This is illegal. Reconfiguration may not work." severity warning;
|
|
else -- M counter is being bypassed
|
|
if (m_mode_val(0) /= "bypass") then
|
|
-- mode is switched : give warning
|
|
ASSERT false REPORT "M counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
|
|
end if;
|
|
m_val_tmp(0) := 1;
|
|
m_mode_val(0) <= "bypass";
|
|
end if;
|
|
else
|
|
if (m_mode_val(0) = "bypass") then
|
|
-- mode is switched : give warning
|
|
ASSERT false REPORT "M counter switched BYPASS mode to enabled. PLL may lose lock." severity warning;
|
|
end if;
|
|
m_mode_val(0) <= " ";
|
|
if (tmp_scan_data(71) = '1') then
|
|
-- odd : check for duty cycle, if not 50% -- error
|
|
if (alt_conv_integer(m_hi) - alt_conv_integer(m_lo) /= 1) then
|
|
reconfig_err <= true;
|
|
ASSERT FALSE REPORT "The M counter of the " & family_name & " FAST PLL can be configured for 50% duty cycle only. In this case, the HIGH and LOW moduli programmed will result in a duty cycle other than 50%, which is illegal. Reconfiguration may not work." severity warning;
|
|
end if;
|
|
else -- even
|
|
if (alt_conv_integer(m_hi) /= alt_conv_integer(m_lo)) then
|
|
reconfig_err <= true;
|
|
ASSERT FALSE REPORT "The M counter of the " & family_name & " FAST PLL can be configured for 50% duty cycle only. In this case, the HIGH and LOW moduli programmed will result in a duty cycle other than 50%, which is illegal. Reconfiguration may not work." severity warning;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- N
|
|
is_error := false;
|
|
n_fast := tmp_scan_data(73 downto 72);
|
|
n_val(0) <= alt_conv_integer(n_fast);
|
|
if (tmp_scan_data(74) /= '1') then
|
|
if (alt_conv_integer(n_fast) = 1) then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
-- cntr value is illegal : give warning
|
|
ASSERT false REPORT "Illegal 1 value for N counter. Instead the counter should be BYPASSED. Reconfiguration may not work." severity warning;
|
|
elsif (alt_conv_integer(n_fast) = 0) then
|
|
n_val(0) <= 4;
|
|
ASSERT FALSE REPORT "N Modulus = " &int2str(4)& " " severity note;
|
|
end if;
|
|
if (not is_error) then
|
|
if (n_mode_val(0) = "bypass") then
|
|
ASSERT false REPORT "N Counter switched from BYPASS mode to enabled (N modulus = " &int2str(alt_conv_integer(n_fast))& "). PLL may lose lock." severity warning;
|
|
else
|
|
ASSERT FALSE REPORT "N modulus = " &int2str(alt_conv_integer(n_fast))& " "severity note;
|
|
end if;
|
|
n_mode_val(0) <= " ";
|
|
end if;
|
|
elsif (tmp_scan_data(74) = '1') then
|
|
if (tmp_scan_data(72) /= '0') then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false report "Illegal value for N counter in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work." severity warning;
|
|
else
|
|
if (n_mode_val(0) /= "bypass") then
|
|
ASSERT false REPORT "N Counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
|
|
end if;
|
|
n_val(0) <= 1;
|
|
n_mode_val(0) <= "bypass";
|
|
end if;
|
|
end if;
|
|
else -- GENERAL PURPOSE PLL
|
|
for i in 0 to 5 loop
|
|
start_bit := 116 - (i*18);
|
|
if (tmp_scan_data(start_bit + 8) = '1') then
|
|
c_mode_val_tmp(i) := "bypass";
|
|
if (tmp_scan_data(start_bit + 17) = '1') then
|
|
c_mode_val_tmp(i) := " off";
|
|
ASSERT false REPORT "The specified bit settings will turn OFF the " &cntrs(i)& "counter. It cannot be turned on unless the part is re-initialized." severity warning;
|
|
end if;
|
|
elsif (tmp_scan_data(start_bit + 17) = '1') then
|
|
c_mode_val_tmp(i) := " odd";
|
|
else
|
|
c_mode_val_tmp(i) := " even";
|
|
end if;
|
|
high := tmp_scan_data(start_bit + 7 downto start_bit);
|
|
low := tmp_scan_data(start_bit+16 downto start_bit+9);
|
|
if (tmp_scan_data(start_bit+7 downto start_bit) = "00000000") then
|
|
c_high_val_tmp(i) := 256;
|
|
else
|
|
c_high_val_tmp(i) := alt_conv_integer(high);
|
|
end if;
|
|
if (tmp_scan_data(start_bit+16 downto start_bit+9) = "00000000") then
|
|
c_low_val_tmp(i) := 256;
|
|
else
|
|
c_low_val_tmp(i) := alt_conv_integer(low);
|
|
end if;
|
|
end loop;
|
|
-- the phase taps
|
|
for i in 0 to 5 loop
|
|
start_bit := 14 + (i*2);
|
|
if (tmp_scan_data(start_bit) = '0') then
|
|
-- do nothing
|
|
elsif (tmp_scan_data(start_bit) = '1') then
|
|
if (tmp_scan_data(start_bit + 1) = '1') then
|
|
c_ph_val_tmp(i) := c_ph_val_tmp(i) + 1;
|
|
if (c_ph_val_tmp(i) > 7) then
|
|
c_ph_val_tmp(i) := 0;
|
|
end if;
|
|
elsif (tmp_scan_data(start_bit + 1) = '0') then
|
|
c_ph_val_tmp(i) := c_ph_val_tmp(i) - 1;
|
|
if (c_ph_val_tmp(i) < 0) then
|
|
c_ph_val_tmp(i) := 7;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
sig_c_ph_val_tmp <= c_ph_val_tmp;
|
|
sig_c_low_val_tmp <= c_low_val_tmp;
|
|
sig_c_hi_val_tmp <= c_high_val_tmp;
|
|
|
|
-- cntrs M/M2
|
|
for i in 0 to 1 loop
|
|
start_bit := 134 + (i*10);
|
|
if ( i = 0 or (i = 1 and ss > 0) ) then
|
|
is_error := false;
|
|
m_tmp := tmp_scan_data(start_bit+8 downto start_bit);
|
|
m_val_tmp(i) := alt_conv_integer(m_tmp);
|
|
if (tmp_scan_data(start_bit+9) /= '1') then
|
|
if (alt_conv_integer(m_tmp) = 1) then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
-- cntr value is illegal : give warning
|
|
ASSERT false REPORT "Illegal 1 value for " &ss_cntrs(i)& "counter. Instead " &ss_cntrs(i)& "should be BYPASSED. Reconfiguration may not work." severity warning;
|
|
elsif (tmp_scan_data(start_bit+8 downto start_bit) = "000000000") then
|
|
m_val_tmp(i) := 512;
|
|
end if;
|
|
if (not is_error) then
|
|
if (m_mode_val(i) = "bypass") then
|
|
-- Mode is switched : give warning
|
|
ASSERT false REPORT "M Counter switched from BYPASS mode to enabled (M modulus = " &int2str(alt_conv_integer(m_tmp))& "). PLL may lose lock." severity warning;
|
|
else
|
|
end if;
|
|
m_mode_val(i) <= " ";
|
|
end if;
|
|
elsif (tmp_scan_data(start_bit+9) = '1') then
|
|
if (tmp_scan_data(start_bit) /= '0') then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false report "Illegal value for counter " &ss_cntrs(i)& "in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work." severity warning;
|
|
else
|
|
if (m_mode_val(i) /= "bypass") then
|
|
-- Mode is switched : give warning
|
|
ASSERT false REPORT "M Counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
|
|
end if;
|
|
m_val_tmp(i) := 1;
|
|
m_mode_val(i) <= "bypass";
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
if (ss > 0) then
|
|
if (m_mode_val(0) /= m_mode_val(1)) then
|
|
reconfig_err <= true;
|
|
is_error := true;
|
|
ASSERT false REPORT "Incompatible modes for M/M2 counters. Either both should be BYPASSED or both NON-BYPASSED. Reconfiguration may not work." severity warning;
|
|
end if;
|
|
end if;
|
|
sig_m_val_tmp <= m_val_tmp;
|
|
-- cntrs N/N2
|
|
for i in 0 to 1 loop
|
|
start_bit := 154 + i*10;
|
|
if ( i = 0 or (i = 1 and ss > 0) ) then
|
|
is_error := false;
|
|
n_tmp := tmp_scan_data(start_bit+8 downto start_bit);
|
|
n_val(i) <= alt_conv_integer(n_tmp);
|
|
if (tmp_scan_data(start_bit+9) /= '1') then
|
|
if (alt_conv_integer(n_tmp) = 1) then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
-- cntr value is illegal : give warning
|
|
ASSERT false REPORT "Illegal 1 value for " &ss_cntrs(2+i)& "counter. Instead " &ss_cntrs(2+i)& "should be BYPASSED. Reconfiguration may not work." severity warning;
|
|
elsif (alt_conv_integer(n_tmp) = 0) then
|
|
n_val(i) <= 512;
|
|
end if;
|
|
if (not is_error) then
|
|
if (n_mode_val(i) = "bypass") then
|
|
ASSERT false REPORT "N Counter switched from BYPASS mode to enabled (N modulus = " &int2str(alt_conv_integer(n_tmp))& "). PLL may lose lock." severity warning;
|
|
else
|
|
end if;
|
|
n_mode_val(i) <= " ";
|
|
end if;
|
|
elsif (tmp_scan_data(start_bit+9) = '1') then
|
|
if (tmp_scan_data(start_bit) /= '0') then
|
|
is_error := true;
|
|
reconfig_err <= true;
|
|
ASSERT false report "Illegal value for counter " &ss_cntrs(2+i)& "in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work." severity warning;
|
|
else
|
|
if (n_mode_val(i) /= "bypass") then
|
|
ASSERT false REPORT "N Counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
|
|
end if;
|
|
n_val(i) <= 1;
|
|
n_mode_val(i) <= "bypass";
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
if (ss > 0) then
|
|
if (n_mode_val(0) /= n_mode_val(1)) then
|
|
reconfig_err <= true;
|
|
is_error := true;
|
|
ASSERT false REPORT "Incompatible modes for N/N2 counters. Either both should be BYPASSED or both NON-BYPASSED. Reconfiguration may not work." severity warning;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
slowest_clk_old := slowest_clk(c_high_val(0)+c_low_val(0), c_mode_val(0),
|
|
c_high_val(1)+c_low_val(1), c_mode_val(1),
|
|
c_high_val(2)+c_low_val(2), c_mode_val(2),
|
|
c_high_val(3)+c_low_val(3), c_mode_val(3),
|
|
c_high_val(4)+c_low_val(4), c_mode_val(4),
|
|
c_high_val(5)+c_low_val(5), c_mode_val(5),
|
|
sig_refclk_period, m_val(0));
|
|
|
|
slowest_clk_new := slowest_clk(c_high_val_tmp(0)+c_low_val_tmp(0), c_mode_val_tmp(0),
|
|
c_high_val_tmp(1)+c_low_val_tmp(1), c_mode_val_tmp(1),
|
|
c_high_val_tmp(2)+c_low_val_tmp(2), c_mode_val_tmp(2),
|
|
c_high_val_tmp(3)+c_low_val_tmp(3), c_mode_val_tmp(3),
|
|
c_high_val_tmp(4)+c_low_val_tmp(4), c_mode_val_tmp(4),
|
|
c_high_val_tmp(5)+c_low_val_tmp(5), c_mode_val_tmp(5),
|
|
sig_refclk_period, m_val_tmp(0));
|
|
|
|
if (slowest_clk_new > slowest_clk_old) then
|
|
quiet_time := slowest_clk_new;
|
|
else
|
|
quiet_time := slowest_clk_old;
|
|
end if;
|
|
sig_quiet_time <= quiet_time;
|
|
sig_slowest_clk_old <= slowest_clk_old;
|
|
sig_slowest_clk_new <= slowest_clk_new;
|
|
tmp_rem := (quiet_time/1 ps) rem (scanclk_period/ 1 ps);
|
|
scanclk_cycles := (quiet_time/1 ps) / (scanclk_period/1 ps);
|
|
if (tmp_rem /= 0) then
|
|
scanclk_cycles := scanclk_cycles + 1;
|
|
end if;
|
|
scandone_tmp <= transport '1' after ((scanclk_cycles+1)*scanclk_period - (scanclk_period/2));
|
|
end if;
|
|
|
|
if (scanwrite_enabled = '1') then
|
|
if (fbclk'event and fbclk = '1') then
|
|
m_val <= m_val_tmp;
|
|
end if;
|
|
|
|
if (c_clk(0)'event and c_clk(0) = '1') then
|
|
c_high_val(0) <= c_high_val_tmp(0);
|
|
c_mode_val(0) <= c_mode_val_tmp(0);
|
|
c0_rising_edge_transfer_done := true;
|
|
end if;
|
|
if (c_clk(1)'event and c_clk(1) = '1') then
|
|
c_high_val(1) <= c_high_val_tmp(1);
|
|
c_mode_val(1) <= c_mode_val_tmp(1);
|
|
c1_rising_edge_transfer_done := true;
|
|
end if;
|
|
if (c_clk(2)'event and c_clk(2) = '1') then
|
|
c_high_val(2) <= c_high_val_tmp(2);
|
|
c_mode_val(2) <= c_mode_val_tmp(2);
|
|
c2_rising_edge_transfer_done := true;
|
|
end if;
|
|
if (c_clk(3)'event and c_clk(3) = '1') then
|
|
c_high_val(3) <= c_high_val_tmp(3);
|
|
c_mode_val(3) <= c_mode_val_tmp(3);
|
|
c3_rising_edge_transfer_done := true;
|
|
end if;
|
|
if (c_clk(4)'event and c_clk(4) = '1') then
|
|
c_high_val(4) <= c_high_val_tmp(4);
|
|
c_mode_val(4) <= c_mode_val_tmp(4);
|
|
c4_rising_edge_transfer_done := true;
|
|
end if;
|
|
if (c_clk(5)'event and c_clk(5) = '1') then
|
|
c_high_val(5) <= c_high_val_tmp(5);
|
|
c_mode_val(5) <= c_mode_val_tmp(5);
|
|
c5_rising_edge_transfer_done := true;
|
|
end if;
|
|
end if;
|
|
|
|
if (c_clk(0)'event and c_clk(0) = '0' and c0_rising_edge_transfer_done) then
|
|
c_low_val(0) <= c_low_val_tmp(0);
|
|
end if;
|
|
if (c_clk(1)'event and c_clk(1) = '0' and c1_rising_edge_transfer_done) then
|
|
c_low_val(1) <= c_low_val_tmp(1);
|
|
end if;
|
|
if (c_clk(2)'event and c_clk(2) = '0' and c2_rising_edge_transfer_done) then
|
|
c_low_val(2) <= c_low_val_tmp(2);
|
|
end if;
|
|
if (c_clk(3)'event and c_clk(3) = '0' and c3_rising_edge_transfer_done) then
|
|
c_low_val(3) <= c_low_val_tmp(3);
|
|
end if;
|
|
if (c_clk(4)'event and c_clk(4) = '0' and c4_rising_edge_transfer_done) then
|
|
c_low_val(4) <= c_low_val_tmp(4);
|
|
end if;
|
|
if (c_clk(5)'event and c_clk(5) = '0' and c5_rising_edge_transfer_done) then
|
|
c_low_val(5) <= c_low_val_tmp(5);
|
|
end if;
|
|
|
|
if (scanwrite_enabled = '1') then
|
|
for x in 0 to 7 loop
|
|
if (vco_tap(x) /= vco_tap_last_value(x) and vco_tap(x) = '0') then
|
|
-- TAP X has event
|
|
for i in 0 to 5 loop
|
|
if (c_ph_val(i) = x) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = x) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
|
|
-- revert counter phase tap values to POF programmed values
|
|
-- if PLL is reset
|
|
|
|
if (areset_ipd = '1') then
|
|
c_ph_val <= i_c_ph;
|
|
c_ph_val_tmp := i_c_ph;
|
|
m_ph_val <= i_m_ph;
|
|
m_ph_val_tmp := i_m_ph;
|
|
end if;
|
|
|
|
for x in 0 to 7 loop
|
|
if (vco_tap(x) /= vco_tap_last_value(x)) then
|
|
-- TAP X has event
|
|
for i in 0 to 5 loop
|
|
if (c_ph_val(i) = x) then
|
|
inclk_c_from_vco(i) <= vco_tap(x);
|
|
if (i = 0 and enable0_counter = "c0") then
|
|
inclk_sclkout0_from_vco <= vco_tap(x);
|
|
end if;
|
|
if (i = 0 and enable1_counter = "c0") then
|
|
inclk_sclkout1_from_vco <= vco_tap(x);
|
|
end if;
|
|
if (i = 1 and enable0_counter = "c1") then
|
|
inclk_sclkout0_from_vco <= vco_tap(x);
|
|
end if;
|
|
if (i = 1 and enable1_counter = "c1") then
|
|
inclk_sclkout1_from_vco <= vco_tap(x);
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
|
|
if (m_ph_val = x) then
|
|
inclk_m_from_vco <= vco_tap(x);
|
|
end if;
|
|
|
|
vco_tap_last_value(x) <= vco_tap(x);
|
|
end if;
|
|
end loop;
|
|
|
|
|
|
|
|
if (scanclk_ipd'event and scanclk_ipd = '0') then
|
|
-- enable scanwrite on falling edge
|
|
scanwrite_enabled <= scanwrite_reg;
|
|
end if;
|
|
|
|
if (scanread_reg = '1') then
|
|
gated_scanclk <= transport scanclk_ipd and scanread_reg;
|
|
else
|
|
gated_scanclk <= transport '1';
|
|
end if;
|
|
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
-- register scanread and scanwrite
|
|
scanread_reg <= scanread_ipd;
|
|
scanwrite_reg <= scanwrite_ipd;
|
|
|
|
if (got_first_scanclk) then
|
|
scanclk_period := now - scanclk_last_rising_edge;
|
|
else
|
|
got_first_scanclk := true;
|
|
end if;
|
|
-- reset got_first_scanclk on falling edge of scanread_reg
|
|
if (scanread_ipd = '0' and scanread_reg = '1') then
|
|
got_first_scanclk := false;
|
|
got_first_gated_scanclk := false;
|
|
end if;
|
|
|
|
scanclk_last_rising_edge := now;
|
|
end if;
|
|
|
|
if (gated_scanclk'event and gated_scanclk = '1' and now > 0 ps) then
|
|
if (not got_first_gated_scanclk) then
|
|
got_first_gated_scanclk := true;
|
|
end if;
|
|
for j in scan_chain_length - 1 downto 1 loop
|
|
scan_data(j) <= scan_data(j-1);
|
|
end loop;
|
|
scan_data(0) <= scandata_ipd;
|
|
end if;
|
|
end process;
|
|
|
|
scandataout_tmp <= scan_data(FAST_SCAN_CHAIN-1) when (pll_type = "fast" or pll_type = "lvds") else scan_data(GPP_SCAN_CHAIN-1);
|
|
|
|
|
|
SCHEDULE : process (schedule_vco, areset_ipd, ena_ipd, pfdena_ipd, refclk, fbclk, vco_out)
|
|
variable sched_time : time := 0 ps;
|
|
|
|
TYPE time_array is ARRAY (0 to 7) of time;
|
|
variable init : boolean := true;
|
|
variable refclk_period : time;
|
|
variable m_times_vco_period : time;
|
|
variable new_m_times_vco_period : time;
|
|
|
|
variable phase_shift : time_array := (OTHERS => 0 ps);
|
|
variable last_phase_shift : time_array := (OTHERS => 0 ps);
|
|
|
|
variable l_index : integer := 1;
|
|
variable cycle_to_adjust : integer := 0;
|
|
|
|
variable stop_vco : boolean := false;
|
|
|
|
variable locked_tmp : std_logic := '0';
|
|
variable pll_is_locked : boolean := false;
|
|
variable pll_about_to_lock : boolean := false;
|
|
variable cycles_to_lock : integer := 0;
|
|
variable cycles_to_unlock : integer := 0;
|
|
|
|
variable got_first_refclk : boolean := false;
|
|
variable got_second_refclk : boolean := false;
|
|
variable got_first_fbclk : boolean := false;
|
|
|
|
variable refclk_time : time := 0 ps;
|
|
variable fbclk_time : time := 0 ps;
|
|
variable first_fbclk_time : time := 0 ps;
|
|
|
|
variable fbclk_period : time := 0 ps;
|
|
|
|
variable first_schedule : boolean := true;
|
|
|
|
variable vco_val : std_logic := '0';
|
|
variable vco_period_was_phase_adjusted : boolean := false;
|
|
variable phase_adjust_was_scheduled : boolean := false;
|
|
|
|
variable loop_xplier : integer;
|
|
variable loop_initial : integer := 0;
|
|
variable loop_ph : integer := 0;
|
|
variable loop_time_delay : integer := 0;
|
|
|
|
variable initial_delay : time := 0 ps;
|
|
variable vco_per : time;
|
|
variable tmp_rem : integer;
|
|
variable my_rem : integer;
|
|
variable fbk_phase : integer := 0;
|
|
|
|
variable pull_back_M : integer := 0;
|
|
variable total_pull_back : integer := 0;
|
|
variable fbk_delay : integer := 0;
|
|
|
|
variable offset : time := 0 ps;
|
|
|
|
variable tmp_vco_per : integer := 0;
|
|
variable high_time : time;
|
|
variable low_time : time;
|
|
|
|
variable got_refclk_posedge : boolean := false;
|
|
variable got_fbclk_posedge : boolean := false;
|
|
variable inclk_out_of_range : boolean := false;
|
|
variable no_warn : boolean := false;
|
|
|
|
variable ext_fbk_cntr_modulus : integer := 1;
|
|
variable init_clks : boolean := true;
|
|
variable pll_is_in_reset : boolean := false;
|
|
variable pll_is_disabled : boolean := false;
|
|
variable next_vco_sched_time : time := 0 ps;
|
|
variable tap0_is_active : boolean := true;
|
|
|
|
begin
|
|
if (init) then
|
|
|
|
-- jump-start the VCO
|
|
-- add 1 ps delay to ensure all signals are updated to initial
|
|
-- values
|
|
schedule_vco <= transport not schedule_vco after 1 ps;
|
|
|
|
init := false;
|
|
end if;
|
|
|
|
if (schedule_vco'event) then
|
|
if (init_clks) then
|
|
refclk_period := inclk0_input_frequency * n_val(0) * 1 ps;
|
|
|
|
m_times_vco_period := refclk_period;
|
|
new_m_times_vco_period := refclk_period;
|
|
init_clks := false;
|
|
end if;
|
|
sched_time := 0 ps;
|
|
for i in 0 to 7 loop
|
|
last_phase_shift(i) := phase_shift(i);
|
|
end loop;
|
|
cycle_to_adjust := 0;
|
|
l_index := 1;
|
|
m_times_vco_period := new_m_times_vco_period;
|
|
end if;
|
|
|
|
-- areset was asserted
|
|
if (areset_ipd'event and areset_ipd = '1') then
|
|
assert false report family_name & " PLL was reset" severity note;
|
|
-- reset lock parameters
|
|
locked_tmp := '0';
|
|
pll_is_locked := false;
|
|
pll_about_to_lock := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
pll_is_in_reset := true;
|
|
tap0_is_active := false;
|
|
for x in 0 to 7 loop
|
|
vco_tap(x) <= '0';
|
|
end loop;
|
|
end if;
|
|
|
|
-- note areset deassert time
|
|
-- note it as refclk_time to prevent false triggering
|
|
-- of stop_vco after areset
|
|
if (areset_ipd'event and areset_ipd = '0' and pll_is_in_reset) then
|
|
refclk_time := now;
|
|
pll_is_in_reset := false;
|
|
if (ena_ipd = '1' and not stop_vco and next_vco_sched_time <= now) then
|
|
schedule_vco <= not schedule_vco;
|
|
end if;
|
|
end if;
|
|
|
|
-- ena was deasserted
|
|
if (ena_ipd'event and ena_ipd = '0') then
|
|
assert false report family_name & " PLL was disabled" severity note;
|
|
pll_is_disabled := true;
|
|
tap0_is_active := false;
|
|
for x in 0 to 7 loop
|
|
vco_tap(x) <= '0';
|
|
end loop;
|
|
end if;
|
|
|
|
if (ena_ipd'event and ena_ipd = '1') then
|
|
assert false report family_name & " PLL is enabled" severity note;
|
|
pll_is_disabled := false;
|
|
if (areset_ipd /= '1' and not stop_vco and next_vco_sched_time < now) then
|
|
schedule_vco <= not schedule_vco;
|
|
end if;
|
|
end if;
|
|
|
|
-- illegal value on areset_ipd
|
|
if (areset_ipd'event and areset_ipd = 'X') then
|
|
assert false report "Illegal value 'X' detected on ARESET input" severity warning;
|
|
end if;
|
|
|
|
if (areset_ipd = '1' or ena_ipd = '0' or stop_vco) then
|
|
|
|
-- reset lock parameters
|
|
locked_tmp := '0';
|
|
pll_is_locked := false;
|
|
pll_about_to_lock := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
refclk_time := 0 ps;
|
|
got_first_fbclk := false;
|
|
fbclk_time := 0 ps;
|
|
first_fbclk_time := 0 ps;
|
|
fbclk_period := 0 ps;
|
|
|
|
-- first_schedule := true;
|
|
-- vco_val := '0';
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
|
|
-- reset all counter phase taps to POF programmed values
|
|
end if;
|
|
|
|
if (schedule_vco'event and areset_ipd /= '1' and ena_ipd /= '0' and (not stop_vco) and now > 0 ps) then
|
|
|
|
|
|
-- calculate loop_xplier : this will be different from m_val
|
|
-- in external_feedback_mode
|
|
loop_xplier := m_val(0);
|
|
loop_initial := m_initial_val - 1;
|
|
loop_ph := m_ph_val;
|
|
|
|
if (operation_mode = "external_feedback") then
|
|
if (ext_fbk_cntr_mode = "bypass") then
|
|
ext_fbk_cntr_modulus := 1;
|
|
else
|
|
ext_fbk_cntr_modulus := ext_fbk_cntr_high + ext_fbk_cntr_low;
|
|
end if;
|
|
loop_xplier := m_val(0) * (ext_fbk_cntr_modulus);
|
|
loop_ph := ext_fbk_cntr_ph;
|
|
loop_initial := ext_fbk_cntr_initial - 1 + ((m_initial_val - 1) * ext_fbk_cntr_modulus);
|
|
end if;
|
|
|
|
-- convert initial value to delay
|
|
initial_delay := (loop_initial * m_times_vco_period)/loop_xplier;
|
|
|
|
-- convert loop ph_tap to delay
|
|
my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
|
|
tmp_vco_per := (m_times_vco_period/1 ps) / loop_xplier;
|
|
if (my_rem /= 0) then
|
|
tmp_vco_per := tmp_vco_per + 1;
|
|
end if;
|
|
fbk_phase := (loop_ph * tmp_vco_per)/8;
|
|
|
|
if (operation_mode = "external_feedback") then
|
|
pull_back_M := (m_initial_val - 1) * ext_fbk_cntr_modulus * ((refclk_period/loop_xplier)/1 ps);
|
|
while (pull_back_M > refclk_period/1 ps) loop
|
|
pull_back_M := pull_back_M - refclk_period/ 1 ps;
|
|
end loop;
|
|
else
|
|
pull_back_M := initial_delay/1 ps + fbk_phase;
|
|
end if;
|
|
|
|
total_pull_back := pull_back_M;
|
|
|
|
if (simulation_type = "timing") then
|
|
total_pull_back := total_pull_back + pll_compensation_delay;
|
|
end if;
|
|
while (total_pull_back > refclk_period/1 ps) loop
|
|
total_pull_back := total_pull_back - refclk_period/1 ps;
|
|
end loop;
|
|
|
|
if (total_pull_back > 0) then
|
|
offset := refclk_period - (total_pull_back * 1 ps);
|
|
end if;
|
|
if (operation_mode = "external_feedback") then
|
|
fbk_delay := pull_back_M;
|
|
if (simulation_type = "timing") then
|
|
fbk_delay := fbk_delay + pll_compensation_delay;
|
|
end if;
|
|
else
|
|
fbk_delay := total_pull_back - fbk_phase;
|
|
if (fbk_delay < 0) then
|
|
offset := offset - (fbk_phase * 1 ps);
|
|
fbk_delay := total_pull_back;
|
|
end if;
|
|
end if;
|
|
|
|
-- assign m_delay
|
|
m_delay <= transport fbk_delay after 1 ps;
|
|
|
|
my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
|
|
for i in 1 to loop_xplier loop
|
|
-- adjust cycles
|
|
tmp_vco_per := (m_times_vco_period/1 ps)/loop_xplier;
|
|
if (my_rem /= 0 and l_index <= my_rem) then
|
|
tmp_rem := (loop_xplier * l_index) rem my_rem;
|
|
cycle_to_adjust := (loop_xplier * l_index) / my_rem;
|
|
if (tmp_rem /= 0) then
|
|
cycle_to_adjust := cycle_to_adjust + 1;
|
|
end if;
|
|
end if;
|
|
if (cycle_to_adjust = i) then
|
|
tmp_vco_per := tmp_vco_per + 1;
|
|
l_index := l_index + 1;
|
|
end if;
|
|
|
|
-- calculate high and low periods
|
|
vco_per := tmp_vco_per * 1 ps;
|
|
high_time := (tmp_vco_per/2) * 1 ps;
|
|
if (tmp_vco_per rem 2 /= 0) then
|
|
high_time := high_time + 1 ps;
|
|
end if;
|
|
low_time := vco_per - high_time;
|
|
|
|
-- schedule the rising and falling edges
|
|
for j in 1 to 2 loop
|
|
vco_val := not vco_val;
|
|
if (vco_val = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (vco_val = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
|
|
-- schedule tap0
|
|
vco_out(0) <= transport vco_val after sched_time;
|
|
end loop;
|
|
end loop;
|
|
|
|
-- schedule once more
|
|
if (first_schedule) then
|
|
vco_val := not vco_val;
|
|
if (vco_val = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (vco_val = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
-- schedule tap 0
|
|
vco_out(0) <= transport vco_val after sched_time;
|
|
|
|
first_schedule := false;
|
|
end if;
|
|
|
|
schedule_vco <= transport not schedule_vco after sched_time;
|
|
next_vco_sched_time := now + sched_time;
|
|
|
|
if (vco_period_was_phase_adjusted) then
|
|
m_times_vco_period := refclk_period;
|
|
new_m_times_vco_period := refclk_period;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := true;
|
|
|
|
vco_per := m_times_vco_period/loop_xplier;
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
|
|
-- now schedule the other taps with the appropriate phase-shift
|
|
if (vco_out(0)'event) then
|
|
for k in 1 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
vco_out(k) <= transport vco_out(0) after phase_shift(k);
|
|
end loop;
|
|
end if;
|
|
|
|
if (refclk'event and refclk = '1' and areset_ipd = '0') then
|
|
got_refclk_posedge := true;
|
|
if (not got_first_refclk) then
|
|
got_first_refclk := true;
|
|
else
|
|
got_second_refclk := true;
|
|
refclk_period := now - refclk_time;
|
|
|
|
-- check if incoming freq. will cause VCO range to be
|
|
-- exceeded
|
|
if ( (vco_max /= 0 and vco_min /= 0 and pfdena_ipd = '1') and
|
|
(((refclk_period/1 ps)/loop_xplier > vco_max) or
|
|
((refclk_period/1 ps)/loop_xplier < vco_min)) ) then
|
|
if (pll_is_locked) then
|
|
assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may lose lock" severity warning;
|
|
if (inclk_out_of_range) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
pll_about_to_lock := false;
|
|
cycles_to_lock := 0;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
assert false report family_name & " PLL lost lock." severity note;
|
|
end if;
|
|
elsif (not no_warn) then
|
|
assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may not lock. Please use the correct frequency." severity warning;
|
|
no_warn := true;
|
|
end if;
|
|
inclk_out_of_range := true;
|
|
else
|
|
inclk_out_of_range := false;
|
|
end if;
|
|
end if;
|
|
|
|
if (stop_vco) then
|
|
stop_vco := false;
|
|
schedule_vco <= not schedule_vco;
|
|
end if;
|
|
|
|
refclk_time := now;
|
|
else
|
|
got_refclk_posedge := false;
|
|
end if;
|
|
|
|
if (fbclk'event and fbclk = '1') then
|
|
got_fbclk_posedge := true;
|
|
if (not got_first_fbclk) then
|
|
got_first_fbclk := true;
|
|
else
|
|
fbclk_period := now - fbclk_time;
|
|
end if;
|
|
|
|
-- need refclk_period here, so initialized to proper value above
|
|
if ( ( (now - refclk_time > 1.5 * refclk_period) and pfdena_ipd = '1' and pll_is_locked) or ( (now - refclk_time > 5 * refclk_period) and pfdena_ipd = '1') ) then
|
|
stop_vco := true;
|
|
-- reset
|
|
got_first_refclk := false;
|
|
got_first_fbclk := false;
|
|
got_second_refclk := false;
|
|
if (pll_is_locked) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
assert false report family_name & " PLL lost lock due to loss of input clock" severity note;
|
|
end if;
|
|
pll_about_to_lock := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
first_schedule := true;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
tap0_is_active := false;
|
|
for x in 0 to 7 loop
|
|
vco_tap(x) <= '0';
|
|
end loop;
|
|
end if;
|
|
fbclk_time := now;
|
|
else
|
|
got_fbclk_posedge := false;
|
|
end if;
|
|
|
|
if ((got_refclk_posedge or got_fbclk_posedge) and got_second_refclk and pfdena_ipd = '1' and (not inclk_out_of_range)) then
|
|
|
|
-- now we know actual incoming period
|
|
if ( abs(fbclk_time - refclk_time) <= 5 ps or
|
|
(got_first_fbclk and abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
|
|
-- considered in phase
|
|
if (cycles_to_lock = valid_lock_multiplier - 1) then
|
|
pll_about_to_lock := true;
|
|
end if;
|
|
if (cycles_to_lock = valid_lock_multiplier) then
|
|
if (not pll_is_locked) then
|
|
assert false report family_name & " PLL locked to incoming clock" severity note;
|
|
end if;
|
|
pll_is_locked := true;
|
|
locked_tmp := '1';
|
|
cycles_to_unlock := 0;
|
|
end if;
|
|
-- increment lock counter only if second part of above
|
|
-- time check is NOT true
|
|
if (not(abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
|
|
cycles_to_lock := cycles_to_lock + 1;
|
|
end if;
|
|
|
|
-- adjust m_times_vco_period
|
|
new_m_times_vco_period := refclk_period;
|
|
else
|
|
-- if locked, begin unlock
|
|
if (pll_is_locked) then
|
|
cycles_to_unlock := cycles_to_unlock + 1;
|
|
if (cycles_to_unlock = invalid_lock_multiplier) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
pll_about_to_lock := false;
|
|
cycles_to_lock := 0;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
assert false report family_name & " PLL lost lock." severity note;
|
|
end if;
|
|
end if;
|
|
if ( abs(refclk_period - fbclk_period) <= 2 ps ) then
|
|
-- frequency is still good
|
|
if (now = fbclk_time and (not phase_adjust_was_scheduled)) then
|
|
if ( abs(fbclk_time - refclk_time) > refclk_period/2) then
|
|
if ( abs(fbclk_time - refclk_time) > 1.5 * refclk_period) then
|
|
-- input clock may have stopped : do nothing
|
|
else
|
|
new_m_times_vco_period := m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time));
|
|
vco_period_was_phase_adjusted := true;
|
|
end if;
|
|
else
|
|
new_m_times_vco_period := m_times_vco_period - abs(fbclk_time - refclk_time);
|
|
vco_period_was_phase_adjusted := true;
|
|
end if;
|
|
|
|
end if;
|
|
else
|
|
phase_adjust_was_scheduled := false;
|
|
new_m_times_vco_period := refclk_period;
|
|
end if;
|
|
|
|
end if;
|
|
end if;
|
|
|
|
-- check which vco_tap has event
|
|
for x in 0 to 7 loop
|
|
if (vco_out(x) /= vco_out_last_value(x)) then
|
|
-- TAP X has event
|
|
if (x = 0 and areset_ipd = '0' and ena_ipd = '1' and sig_stop_vco = '0') then
|
|
if (vco_out(0) = '1') then
|
|
tap0_is_active := true;
|
|
end if;
|
|
if (tap0_is_active) then
|
|
vco_tap(0) <= vco_out(0);
|
|
end if;
|
|
elsif (tap0_is_active) then
|
|
vco_tap(x) <= vco_out(x);
|
|
end if;
|
|
if (sig_stop_vco = '1') then
|
|
vco_tap(x) <= '0';
|
|
end if;
|
|
vco_out_last_value(x) <= vco_out(x);
|
|
end if;
|
|
end loop;
|
|
|
|
if (pfdena_ipd = '0') then
|
|
if (pll_is_locked) then
|
|
locked_tmp := 'X';
|
|
end if;
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
end if;
|
|
|
|
-- give message only at time of deassertion
|
|
if (pfdena_ipd'event and pfdena_ipd = '0') then
|
|
assert false report "PFDENA deasserted." severity note;
|
|
elsif (pfdena_ipd'event and pfdena_ipd = '1') then
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
refclk_time := now;
|
|
end if;
|
|
|
|
if (reconfig_err) then
|
|
lock <= '0';
|
|
else
|
|
lock <= locked_tmp;
|
|
end if;
|
|
about_to_lock <= pll_about_to_lock after 1 ps;
|
|
|
|
-- signal to calculate quiet_time
|
|
sig_refclk_period <= refclk_period;
|
|
|
|
if (stop_vco = true) then
|
|
sig_stop_vco <= '1';
|
|
else
|
|
sig_stop_vco <= '0';
|
|
end if;
|
|
end process SCHEDULE;
|
|
|
|
clk0_tmp <= c_clk(i_clk0_counter);
|
|
clk(0) <= clk0_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
|
|
'X';
|
|
|
|
clk1_tmp <= c_clk(i_clk1_counter);
|
|
clk(1) <= clk1_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
|
|
'X';
|
|
|
|
clk2_tmp <= c_clk(i_clk2_counter);
|
|
clk(2) <= clk2_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
|
|
'X';
|
|
|
|
clk3_tmp <= c_clk(i_clk3_counter);
|
|
clk(3) <= clk3_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
|
|
'X';
|
|
|
|
clk4_tmp <= c_clk(i_clk4_counter);
|
|
clk(4) <= clk4_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
|
|
'X';
|
|
|
|
clk5_tmp <= c_clk(i_clk5_counter);
|
|
clk(5) <= clk5_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
|
|
'X';
|
|
|
|
sclkout(0) <= sclkout0_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
|
|
'X';
|
|
|
|
sclkout(1) <= sclkout1_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
|
|
'X';
|
|
|
|
enable0 <= enable0_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
|
|
'X';
|
|
enable1 <= enable1_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
|
|
'X';
|
|
|
|
scandataout <= scandataout_tmp;
|
|
scandone <= scandone_tmp;
|
|
|
|
end vital_pll;
|
|
-- END ARCHITECTURE VITAL_PLL
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_ttn_mn_cntr
|
|
--
|
|
-- Description : Simulation model for the M and N counter. This is a
|
|
-- common model for the input counter and the loop feedback
|
|
-- counter of the StratixIII PLL.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
USE IEEE.std_logic_arith.all;
|
|
USE IEEE.std_logic_unsigned.all;
|
|
|
|
ENTITY MF_ttn_mn_cntr is
|
|
PORT( clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer := 1;
|
|
time_delay : IN integer := 0
|
|
);
|
|
END MF_ttn_mn_cntr;
|
|
|
|
ARCHITECTURE behave of MF_ttn_mn_cntr is
|
|
begin
|
|
|
|
process (clk, reset)
|
|
variable count : integer := 1;
|
|
variable first_rising_edge : boolean := true;
|
|
variable tmp_cout : std_logic;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := true;
|
|
elsif (clk'event) then
|
|
if (clk = '1' and first_rising_edge) then
|
|
first_rising_edge := false;
|
|
tmp_cout := clk;
|
|
elsif (not first_rising_edge) then
|
|
if (count < modulus) then
|
|
count := count + 1;
|
|
else
|
|
count := 1;
|
|
tmp_cout := not tmp_cout;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout after time_delay * 1 ps;
|
|
end process;
|
|
end behave;
|
|
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_ttn_scale_cntr
|
|
--
|
|
-- Description : Simulation model for the output scale-down counters.
|
|
-- This is a common model for the C0, C1, C2, C3, C4 and C5
|
|
-- output counters of the StratixII PLL.
|
|
--
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
|
|
ENTITY MF_ttn_scale_cntr is
|
|
PORT( clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
initial : IN integer := 1;
|
|
high : IN integer := 1;
|
|
low : IN integer := 1;
|
|
mode : IN string := "bypass";
|
|
ph_tap : IN integer := 0;
|
|
cout : OUT std_logic
|
|
);
|
|
END MF_ttn_scale_cntr;
|
|
|
|
ARCHITECTURE behave of MF_ttn_scale_cntr is
|
|
begin
|
|
process (clk, reset)
|
|
variable tmp_cout : std_logic := '0';
|
|
variable count : integer := 1;
|
|
variable output_shift_count : integer := 1;
|
|
variable first_rising_edge : boolean := false;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
output_shift_count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := false;
|
|
elsif (clk'event) then
|
|
if (mode = " off") then
|
|
tmp_cout := '0';
|
|
elsif (mode = "bypass") then
|
|
tmp_cout := clk;
|
|
first_rising_edge := true;
|
|
elsif (not first_rising_edge) then
|
|
if (clk = '1') then
|
|
if (output_shift_count = initial) then
|
|
tmp_cout := clk;
|
|
first_rising_edge := true;
|
|
else
|
|
output_shift_count := output_shift_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (output_shift_count < initial) then
|
|
if (clk = '1') then
|
|
output_shift_count := output_shift_count + 1;
|
|
end if;
|
|
else
|
|
count := count + 1;
|
|
if (mode = " even" and (count = (high*2) + 1)) then
|
|
tmp_cout := '0';
|
|
elsif (mode = " odd" and (count = high*2)) then
|
|
tmp_cout := '0';
|
|
elsif (count = (high + low)*2 + 1) then
|
|
tmp_cout := '1';
|
|
count := 1; -- reset count
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout;
|
|
end process;
|
|
|
|
end behave;
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_stratixiii_pll
|
|
--
|
|
-- Description : Simulation model for the StratixII PLL.
|
|
-- In the functional mode, it is also the model for the altpll
|
|
-- megafunction.
|
|
--
|
|
-- Limitations : Does not support Spread Spectrum and Bandwidth.
|
|
--
|
|
-- Outputs : Up to 10 output clocks, each defined by its own set of
|
|
-- parameters. Locked output (active high) indicates when the
|
|
-- PLL locks. clkbad and activeclock are used for
|
|
-- clock switchover to indicate which input clock has gone
|
|
-- bad, when the clock switchover initiates and which input
|
|
-- clock is being used as the reference, respectively.
|
|
-- scandataout is the data output of the serial scan chain.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
LIBRARY IEEE, std;
|
|
USE IEEE.std_logic_1164.all;
|
|
USE STD.TEXTIO.all;
|
|
USE work.MF_pllpack.all;
|
|
USE work.MF_ttn_mn_cntr;
|
|
USE work.MF_ttn_scale_cntr;
|
|
USE work.dffp;
|
|
USE work.MF_pll_reg;
|
|
|
|
-- New Features : The list below outlines key new features in TITAN:
|
|
-- 1. Dynamic Phase Reconfiguration
|
|
-- 2. Dynamic PLL Reconfiguration (different protocol)
|
|
-- 3. More output counters
|
|
|
|
ENTITY MF_stratixiii_pll is
|
|
GENERIC (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "auto"; -- AUTO/FAST/ENHANCED/LEFT_RIGHT/TOP_BOTTOM
|
|
compensate_clock : string := "clock0";
|
|
|
|
inclk0_input_frequency : integer := 0;
|
|
inclk1_input_frequency : integer := 0;
|
|
|
|
self_reset_on_loss_lock : string := "off";
|
|
switch_over_type : string := "auto";
|
|
switch_over_counter : integer := 1;
|
|
enable_switch_over_counter : string := "off";
|
|
|
|
dpa_multiply_by : integer := 0;
|
|
dpa_divide_by : integer := 0;
|
|
dpa_divider : integer := 0;
|
|
|
|
bandwidth : integer := 0;
|
|
bandwidth_type : string := "auto";
|
|
use_dc_coupling : string := "false";
|
|
|
|
|
|
|
|
lock_c : integer := 4;
|
|
sim_gate_lock_device_behavior : string := "off";
|
|
lock_high : integer := 0;
|
|
lock_low : integer := 0;
|
|
lock_window_ui : string := "0.05";
|
|
lock_window : time := 5 ps;
|
|
test_bypass_lock_detect : string := "off";
|
|
|
|
|
|
clk0_output_frequency : integer := 0;
|
|
clk0_multiply_by : integer := 0;
|
|
clk0_divide_by : integer := 0;
|
|
clk0_phase_shift : string := "0";
|
|
clk0_duty_cycle : integer := 50;
|
|
|
|
clk1_output_frequency : integer := 0;
|
|
clk1_multiply_by : integer := 0;
|
|
clk1_divide_by : integer := 0;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_duty_cycle : integer := 50;
|
|
|
|
clk2_output_frequency : integer := 0;
|
|
clk2_multiply_by : integer := 0;
|
|
clk2_divide_by : integer := 0;
|
|
clk2_phase_shift : string := "0";
|
|
clk2_duty_cycle : integer := 50;
|
|
|
|
clk3_output_frequency : integer := 0;
|
|
clk3_multiply_by : integer := 0;
|
|
clk3_divide_by : integer := 0;
|
|
clk3_phase_shift : string := "0";
|
|
clk3_duty_cycle : integer := 50;
|
|
|
|
clk4_output_frequency : integer := 0;
|
|
clk4_multiply_by : integer := 0;
|
|
clk4_divide_by : integer := 0;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
|
|
clk5_output_frequency : integer := 0;
|
|
clk5_multiply_by : integer := 0;
|
|
clk5_divide_by : integer := 0;
|
|
clk5_phase_shift : string := "0";
|
|
clk5_duty_cycle : integer := 50;
|
|
|
|
clk6_output_frequency : integer := 0;
|
|
clk6_multiply_by : integer := 0;
|
|
clk6_divide_by : integer := 0;
|
|
clk6_phase_shift : string := "0";
|
|
clk6_duty_cycle : integer := 50;
|
|
|
|
clk7_output_frequency : integer := 0;
|
|
clk7_multiply_by : integer := 0;
|
|
clk7_divide_by : integer := 0;
|
|
clk7_phase_shift : string := "0";
|
|
clk7_duty_cycle : integer := 50;
|
|
|
|
clk8_output_frequency : integer := 0;
|
|
clk8_multiply_by : integer := 0;
|
|
clk8_divide_by : integer := 0;
|
|
clk8_phase_shift : string := "0";
|
|
clk8_duty_cycle : integer := 50;
|
|
|
|
clk9_output_frequency : integer := 0;
|
|
clk9_multiply_by : integer := 0;
|
|
clk9_divide_by : integer := 0;
|
|
clk9_phase_shift : string := "0";
|
|
clk9_duty_cycle : integer := 50;
|
|
|
|
|
|
pfd_min : integer := 0;
|
|
pfd_max : integer := 0;
|
|
vco_min : integer := 0;
|
|
vco_max : integer := 0;
|
|
vco_center : integer := 0;
|
|
|
|
-- ADVANCED USER PARAMETERS
|
|
m_initial : integer := 1;
|
|
m : integer := 0;
|
|
n : integer := 1;
|
|
|
|
c0_high : integer := 1;
|
|
c0_low : integer := 1;
|
|
c0_initial : integer := 1;
|
|
c0_mode : string := "bypass";
|
|
c0_ph : integer := 0;
|
|
|
|
c1_high : integer := 1;
|
|
c1_low : integer := 1;
|
|
c1_initial : integer := 1;
|
|
c1_mode : string := "bypass";
|
|
c1_ph : integer := 0;
|
|
|
|
c2_high : integer := 1;
|
|
c2_low : integer := 1;
|
|
c2_initial : integer := 1;
|
|
c2_mode : string := "bypass";
|
|
c2_ph : integer := 0;
|
|
|
|
c3_high : integer := 1;
|
|
c3_low : integer := 1;
|
|
c3_initial : integer := 1;
|
|
c3_mode : string := "bypass";
|
|
c3_ph : integer := 0;
|
|
|
|
c4_high : integer := 1;
|
|
c4_low : integer := 1;
|
|
c4_initial : integer := 1;
|
|
c4_mode : string := "bypass";
|
|
c4_ph : integer := 0;
|
|
|
|
c5_high : integer := 1;
|
|
c5_low : integer := 1;
|
|
c5_initial : integer := 1;
|
|
c5_mode : string := "bypass";
|
|
c5_ph : integer := 0;
|
|
|
|
c6_high : integer := 1;
|
|
c6_low : integer := 1;
|
|
c6_initial : integer := 1;
|
|
c6_mode : string := "bypass";
|
|
c6_ph : integer := 0;
|
|
|
|
c7_high : integer := 1;
|
|
c7_low : integer := 1;
|
|
c7_initial : integer := 1;
|
|
c7_mode : string := "bypass";
|
|
c7_ph : integer := 0;
|
|
|
|
c8_high : integer := 1;
|
|
c8_low : integer := 1;
|
|
c8_initial : integer := 1;
|
|
c8_mode : string := "bypass";
|
|
c8_ph : integer := 0;
|
|
|
|
c9_high : integer := 1;
|
|
c9_low : integer := 1;
|
|
c9_initial : integer := 1;
|
|
c9_mode : string := "bypass";
|
|
c9_ph : integer := 0;
|
|
|
|
m_ph : integer := 0;
|
|
|
|
clk0_counter : string := "unused";
|
|
clk1_counter : string := "unused";
|
|
clk2_counter : string := "unused";
|
|
clk3_counter : string := "unused";
|
|
clk4_counter : string := "unused";
|
|
clk5_counter : string := "unused";
|
|
clk6_counter : string := "unused";
|
|
clk7_counter : string := "unused";
|
|
clk8_counter : string := "unused";
|
|
clk9_counter : string := "unused";
|
|
|
|
c1_use_casc_in : string := "off";
|
|
c2_use_casc_in : string := "off";
|
|
c3_use_casc_in : string := "off";
|
|
c4_use_casc_in : string := "off";
|
|
c5_use_casc_in : string := "off";
|
|
c6_use_casc_in : string := "off";
|
|
c7_use_casc_in : string := "off";
|
|
c8_use_casc_in : string := "off";
|
|
c9_use_casc_in : string := "off";
|
|
|
|
m_test_source : integer := -1;
|
|
c0_test_source : integer := -1;
|
|
c1_test_source : integer := -1;
|
|
c2_test_source : integer := -1;
|
|
c3_test_source : integer := -1;
|
|
c4_test_source : integer := -1;
|
|
c5_test_source : integer := -1;
|
|
c6_test_source : integer := -1;
|
|
c7_test_source : integer := -1;
|
|
c8_test_source : integer := -1;
|
|
c9_test_source : integer := -1;
|
|
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
vco_post_scale : integer := 1;
|
|
vco_frequency_control : string := "auto";
|
|
vco_phase_shift_step : integer := 0;
|
|
|
|
charge_pump_current : integer := 10;
|
|
loop_filter_r : string := " 1.0";
|
|
loop_filter_c : integer := 0;
|
|
|
|
|
|
pll_compensation_delay : integer := 0;
|
|
simulation_type : string := "functional";
|
|
|
|
clk0_use_even_counter_mode : string := "off";
|
|
clk1_use_even_counter_mode : string := "off";
|
|
clk2_use_even_counter_mode : string := "off";
|
|
clk3_use_even_counter_mode : string := "off";
|
|
clk4_use_even_counter_mode : string := "off";
|
|
clk5_use_even_counter_mode : string := "off";
|
|
clk6_use_even_counter_mode : string := "off";
|
|
clk7_use_even_counter_mode : string := "off";
|
|
clk8_use_even_counter_mode : string := "off";
|
|
clk9_use_even_counter_mode : string := "off";
|
|
|
|
clk0_use_even_counter_value : string := "off";
|
|
clk1_use_even_counter_value : string := "off";
|
|
clk2_use_even_counter_value : string := "off";
|
|
clk3_use_even_counter_value : string := "off";
|
|
clk4_use_even_counter_value : string := "off";
|
|
clk5_use_even_counter_value : string := "off";
|
|
clk6_use_even_counter_value : string := "off";
|
|
clk7_use_even_counter_value : string := "off";
|
|
clk8_use_even_counter_value : string := "off";
|
|
clk9_use_even_counter_value : string := "off";
|
|
|
|
-- Test only
|
|
init_block_reset_a_count : integer := 1;
|
|
init_block_reset_b_count : integer := 1;
|
|
charge_pump_current_bits : integer := 0;
|
|
lock_window_ui_bits : integer := 0;
|
|
loop_filter_c_bits : integer := 0;
|
|
loop_filter_r_bits : integer := 0;
|
|
test_counter_c0_delay_chain_bits : integer := 0;
|
|
test_counter_c1_delay_chain_bits : integer := 0;
|
|
test_counter_c2_delay_chain_bits : integer := 0;
|
|
test_counter_c3_delay_chain_bits : integer := 0;
|
|
test_counter_c4_delay_chain_bits : integer := 0;
|
|
test_counter_c5_delay_chain_bits : integer := 0;
|
|
test_counter_c6_delay_chain_bits : integer := 0;
|
|
test_counter_c7_delay_chain_bits : integer := 0;
|
|
test_counter_c8_delay_chain_bits : integer := 0;
|
|
test_counter_c9_delay_chain_bits : integer := 0;
|
|
test_counter_m_delay_chain_bits : integer := 0;
|
|
test_counter_n_delay_chain_bits : integer := 0;
|
|
test_feedback_comp_delay_chain_bits : integer := 0;
|
|
test_input_comp_delay_chain_bits : integer := 0;
|
|
test_volt_reg_output_mode_bits : integer := 0;
|
|
test_volt_reg_output_voltage_bits : integer := 0;
|
|
test_volt_reg_test_mode : string := "false";
|
|
vco_range_detector_high_bits : integer := -1;
|
|
vco_range_detector_low_bits : integer := -1;
|
|
scan_chain_mif_file : string := "";
|
|
dpa_output_clock_phase_shift : integer := 0;
|
|
test_counter_c3_sclk_delay_chain_bits : integer := -1;
|
|
test_counter_c4_sclk_delay_chain_bits : integer := -1;
|
|
test_counter_c5_lden_delay_chain_bits : integer := -1;
|
|
test_counter_c6_lden_delay_chain_bits : integer := -1;
|
|
|
|
auto_settings : string := "true";
|
|
-- Simulation only generics
|
|
family_name : string := "StratixIII";
|
|
|
|
use_vco_bypass : string := "false"
|
|
);
|
|
|
|
PORT
|
|
(
|
|
inclk : in std_logic_vector(1 downto 0);
|
|
fbin : in std_logic := '0';
|
|
fbout : out std_logic;
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scandata : in std_logic := '0';
|
|
scanclk : in std_logic := '0';
|
|
scanclkena : in std_logic := '1';
|
|
configupdate : in std_logic := '0';
|
|
clk : out std_logic_vector(9 downto 0);
|
|
phasecounterselect : in std_logic_vector(3 downto 0) := "0000";
|
|
phaseupdown : in std_logic := '0';
|
|
phasestep : in std_logic := '0';
|
|
clkbad : out std_logic_vector(1 downto 0);
|
|
activeclock : out std_logic;
|
|
locked : out std_logic;
|
|
scandataout : out std_logic;
|
|
scandone : out std_logic;
|
|
phasedone : out std_logic;
|
|
vcooverrange : out std_logic;
|
|
vcounderrange : out std_logic
|
|
|
|
);
|
|
END MF_stratixiii_pll;
|
|
|
|
ARCHITECTURE vital_pll of MF_stratixiii_pll is
|
|
|
|
function get_vco_min_no_division(i_vco_post_scale : INTEGER) return INTEGER is
|
|
begin
|
|
if (i_vco_post_scale = 1) then
|
|
return vco_min * 2;
|
|
else
|
|
return vco_min;
|
|
end if;
|
|
end;
|
|
|
|
function get_vco_max_no_division(i_vco_post_scale : INTEGER) return INTEGER is
|
|
begin
|
|
if (i_vco_post_scale = 1) then
|
|
return vco_max * 2;
|
|
else
|
|
return vco_max;
|
|
end if;
|
|
end;
|
|
|
|
TYPE int_array is ARRAY(NATURAL RANGE <>) of integer;
|
|
TYPE str_array is ARRAY(NATURAL RANGE <>) of string(1 to 6);
|
|
TYPE str_array1 is ARRAY(NATURAL RANGE <>) of string(1 to 9);
|
|
TYPE std_logic_array is ARRAY(NATURAL RANGE <>) of std_logic;
|
|
|
|
constant VCO_MIN_NO_DIVISION : integer := get_vco_min_no_division(vco_post_scale);
|
|
constant VCO_MAX_NO_DIVISION : integer := get_vco_max_no_division(vco_post_scale);
|
|
|
|
-- internal advanced parameter signals
|
|
signal i_vco_min : integer := vco_min;
|
|
signal i_vco_max : integer := vco_max;
|
|
signal i_vco_center : integer;
|
|
signal i_pfd_min : integer;
|
|
signal i_pfd_max : integer;
|
|
signal c_ph_val : int_array(0 to 9) := (OTHERS => 0);
|
|
signal c_ph_val_tmp : int_array(0 to 9) := (OTHERS => 0);
|
|
signal c_high_val : int_array(0 to 9) := (OTHERS => 1);
|
|
signal c_low_val : int_array(0 to 9) := (OTHERS => 1);
|
|
signal c_initial_val : int_array(0 to 9) := (OTHERS => 1);
|
|
signal c_mode_val : str_array(0 to 9);
|
|
signal clk_num : str_array(0 to 9);
|
|
|
|
-- old values
|
|
signal c_high_val_old : int_array(0 to 9) := (OTHERS => 1);
|
|
signal c_low_val_old : int_array(0 to 9) := (OTHERS => 1);
|
|
signal c_ph_val_old : int_array(0 to 9) := (OTHERS => 0);
|
|
signal c_mode_val_old : str_array(0 to 9);
|
|
-- hold registers
|
|
signal c_high_val_hold : int_array(0 to 9) := (OTHERS => 1);
|
|
signal c_low_val_hold : int_array(0 to 9) := (OTHERS => 1);
|
|
signal c_ph_val_hold : int_array(0 to 9) := (OTHERS => 0);
|
|
signal c_mode_val_hold : str_array(0 to 9);
|
|
|
|
-- temp registers
|
|
signal sig_c_ph_val_tmp : int_array(0 to 9) := (OTHERS => 0);
|
|
signal c_ph_val_orig : int_array(0 to 9) := (OTHERS => 0);
|
|
|
|
signal i_clk9_counter : integer := 9;
|
|
signal i_clk8_counter : integer := 8;
|
|
signal i_clk7_counter : integer := 7;
|
|
signal i_clk6_counter : integer := 6;
|
|
signal i_clk5_counter : integer := 5;
|
|
signal real_lock_high : integer := 0;
|
|
signal i_clk4_counter : integer := 4;
|
|
signal i_clk3_counter : integer := 3;
|
|
signal i_clk2_counter : integer := 2;
|
|
signal i_clk1_counter : integer := 1;
|
|
signal i_clk0_counter : integer := 0;
|
|
signal i_charge_pump_current : integer;
|
|
signal i_loop_filter_r : integer;
|
|
|
|
-- end internal advanced parameter signals
|
|
|
|
-- CONSTANTS
|
|
CONSTANT SCAN_CHAIN : integer := 144;
|
|
CONSTANT GPP_SCAN_CHAIN : integer := 234;
|
|
CONSTANT FAST_SCAN_CHAIN : integer := 180;
|
|
CONSTANT cntrs : str_array(9 downto 0) := (" C9", " C8", " C7", " C6", " C5", " C4", " C3", " C2", " C1", " C0");
|
|
CONSTANT ss_cntrs : str_array(0 to 3) := (" M", " M2", " N", " N2");
|
|
|
|
CONSTANT loop_filter_c_arr : int_array(0 to 3) := (0,0,0,0);
|
|
CONSTANT fpll_loop_filter_c_arr : int_array(0 to 3) := (0,0,0,0);
|
|
CONSTANT charge_pump_curr_arr : int_array(0 to 15) := (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
|
|
|
|
CONSTANT num_phase_taps : integer := 8;
|
|
-- signals
|
|
|
|
signal vcc : std_logic := '1';
|
|
|
|
signal fbclk : std_logic;
|
|
signal refclk : std_logic;
|
|
signal vco_over : std_logic := '0';
|
|
signal vco_under : std_logic := '1';
|
|
|
|
signal pll_locked : boolean := false;
|
|
|
|
|
|
signal c_clk : std_logic_array(0 to 9);
|
|
signal vco_out : std_logic_vector(7 downto 0) := (OTHERS => '0');
|
|
|
|
-- signals to assign values to counter params
|
|
signal m_val : integer := 1;
|
|
signal n_val : integer := 1;
|
|
signal m_ph_val : integer := 0;
|
|
signal m_ph_initial : integer := 0;
|
|
signal m_ph_val_tmp : integer := 0;
|
|
signal m_initial_val : integer := m_initial;
|
|
|
|
signal m_mode_val : string(1 to 6) := " ";
|
|
signal n_mode_val : string(1 to 6) := " ";
|
|
signal lfc_val : integer := 0;
|
|
signal vco_cur : integer := vco_post_scale;
|
|
signal cp_curr_val : integer := 0;
|
|
signal lfr_val : string(1 to 2) := " ";
|
|
|
|
signal cp_curr_old_bit_setting : integer := charge_pump_current_bits;
|
|
signal cp_curr_val_bit_setting : std_logic_vector(2 downto 0) := (OTHERS => '0');
|
|
signal lfr_old_bit_setting : integer := loop_filter_r_bits;
|
|
signal lfr_val_bit_setting : std_logic_vector(4 downto 0) := (OTHERS => '0');
|
|
signal lfc_old_bit_setting : integer := loop_filter_c_bits;
|
|
signal lfc_val_bit_setting : std_logic_vector(1 downto 0) := (OTHERS => '0');
|
|
|
|
signal pll_reconfig_display_full_setting : boolean := FALSE; -- display full setting, change to true
|
|
-- old values
|
|
signal m_val_old : integer := 1;
|
|
signal n_val_old : integer := 1;
|
|
signal m_mode_val_old : string(1 to 6) := " ";
|
|
signal n_mode_val_old : string(1 to 6) := " ";
|
|
signal m_ph_val_old : integer := 0;
|
|
signal lfc_old : integer := 0;
|
|
signal vco_old : integer := 0;
|
|
signal cp_curr_old : integer := 0;
|
|
signal lfr_old : string(1 to 2) := " ";
|
|
signal num_output_cntrs : integer := 10;
|
|
signal scanclk_period : time := 1 ps;
|
|
signal scan_data : std_logic_vector(0 to 233) := (OTHERS => '0');
|
|
|
|
|
|
signal clk_pfd : std_logic_vector(0 to 9);
|
|
signal clk0_tmp : std_logic;
|
|
signal clk1_tmp : std_logic;
|
|
signal clk2_tmp : std_logic;
|
|
signal clk3_tmp : std_logic;
|
|
signal clk4_tmp : std_logic;
|
|
signal clk5_tmp : std_logic;
|
|
signal clk6_tmp : std_logic;
|
|
signal clk7_tmp : std_logic;
|
|
signal clk8_tmp : std_logic;
|
|
signal clk9_tmp : std_logic;
|
|
|
|
signal update_conf_latches : std_logic := '0';
|
|
signal update_conf_latches_reg : std_logic := '0';
|
|
|
|
signal clkin : std_logic := '0';
|
|
signal gate_locked : std_logic := '0';
|
|
signal pfd_locked : std_logic := '0';
|
|
signal lock : std_logic := '0';
|
|
signal about_to_lock : boolean := false;
|
|
signal reconfig_err : boolean := false;
|
|
|
|
signal inclk_c0 : std_logic;
|
|
signal inclk_c1 : std_logic;
|
|
signal inclk_c2 : std_logic;
|
|
signal inclk_c3 : std_logic;
|
|
signal inclk_c4 : std_logic;
|
|
signal inclk_c5 : std_logic;
|
|
signal inclk_c6 : std_logic;
|
|
signal inclk_c7 : std_logic;
|
|
signal inclk_c8 : std_logic;
|
|
signal inclk_c9 : std_logic;
|
|
signal inclk_m : std_logic;
|
|
signal devpor : std_logic;
|
|
signal devclrn : std_logic;
|
|
|
|
signal inclk0_ipd : std_logic;
|
|
signal inclk1_ipd : std_logic;
|
|
signal pfdena_ipd : std_logic;
|
|
signal areset_ipd : std_logic;
|
|
signal fbin_ipd : std_logic;
|
|
signal scanclk_ipd : std_logic;
|
|
signal scanclkena_ipd, scanclkena_reg : std_logic;
|
|
signal scandata_ipd : std_logic;
|
|
signal clkswitch_ipd : std_logic;
|
|
signal phasecounterselect_ipd : std_logic_vector(3 downto 0);
|
|
signal phaseupdown_ipd : std_logic;
|
|
signal phasestep_ipd : std_logic;
|
|
signal configupdate_ipd : std_logic;
|
|
-- registered signals
|
|
|
|
signal sig_offset : time := 0 ps;
|
|
signal sig_refclk_time : time := 0 ps;
|
|
signal sig_fbclk_period : time := 0 ps;
|
|
signal sig_vco_period_was_phase_adjusted : boolean := false;
|
|
signal sig_phase_adjust_was_scheduled : boolean := false;
|
|
signal sig_stop_vco : std_logic := '0';
|
|
signal sig_m_times_vco_period : time := 0 ps;
|
|
signal sig_new_m_times_vco_period : time := 0 ps;
|
|
signal sig_got_refclk_posedge : boolean := false;
|
|
signal sig_got_fbclk_posedge : boolean := false;
|
|
signal sig_got_second_refclk : boolean := false;
|
|
|
|
signal m_delay : integer := 0;
|
|
signal n_delay : integer := 0;
|
|
|
|
signal inclk1_tmp : std_logic := '0';
|
|
|
|
|
|
signal reset_low : std_logic := '0';
|
|
|
|
-- Phase Reconfig
|
|
|
|
SIGNAL phasecounterselect_reg : std_logic_vector(3 DOWNTO 0);
|
|
|
|
SIGNAL phaseupdown_reg : std_logic := '0';
|
|
SIGNAL phasestep_reg : std_logic := '0';
|
|
SIGNAL phasestep_high_count : integer := 0;
|
|
SIGNAL update_phase : std_logic := '0';
|
|
|
|
signal scandataout_tmp : std_logic := '0';
|
|
signal scandata_in : std_logic := '0';
|
|
signal scandata_out : std_logic := '0';
|
|
signal scandone_tmp : std_logic := '1';
|
|
signal initiate_reconfig : std_logic := '0';
|
|
|
|
signal sig_refclk_period : time := (inclk0_input_frequency * 1 ps) * n;
|
|
|
|
signal schedule_vco : std_logic := '0';
|
|
|
|
signal areset_ena_sig : std_logic := '0';
|
|
signal pll_in_test_mode : boolean := false;
|
|
signal pll_has_just_been_reconfigured : boolean := false;
|
|
|
|
signal inclk_c_from_vco : std_logic_array(0 to 9);
|
|
|
|
signal inclk_m_from_vco : std_logic;
|
|
|
|
SIGNAL inclk0_period : time := 0 ps;
|
|
SIGNAL last_inclk0_period : time := 0 ps;
|
|
SIGNAL last_inclk0_edge : time := 0 ps;
|
|
SIGNAL first_inclk0_edge_detect : STD_LOGIC := '0';
|
|
SIGNAL inclk1_period : time := 0 ps;
|
|
SIGNAL last_inclk1_period : time := 0 ps;
|
|
SIGNAL last_inclk1_edge : time := 0 ps;
|
|
SIGNAL first_inclk1_edge_detect : STD_LOGIC := '0';
|
|
|
|
|
|
|
|
COMPONENT MF_ttn_mn_cntr
|
|
PORT (
|
|
clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer := 1;
|
|
time_delay : IN integer := 0
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT MF_ttn_scale_cntr
|
|
PORT (
|
|
clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial : IN integer := 1;
|
|
high : IN integer := 1;
|
|
low : IN integer := 1;
|
|
mode : IN string := "bypass";
|
|
ph_tap : IN integer := 0
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT dffp
|
|
|
|
PORT(
|
|
Q : out STD_LOGIC := '0';
|
|
D : in STD_LOGIC := '1';
|
|
CLRN : in STD_LOGIC := '1';
|
|
PRN : in STD_LOGIC := '1';
|
|
CLK : in STD_LOGIC := '0';
|
|
ENA : in STD_LOGIC := '1');
|
|
END COMPONENT;
|
|
|
|
COMPONENT MF_pll_reg
|
|
PORT(
|
|
Q : out STD_LOGIC := '0';
|
|
D : in STD_LOGIC := '1';
|
|
CLRN : in STD_LOGIC := '1';
|
|
PRN : in STD_LOGIC := '1';
|
|
CLK : in STD_LOGIC := '0';
|
|
ENA : in STD_LOGIC := '1');
|
|
END COMPONENT;
|
|
|
|
begin
|
|
|
|
----------------------
|
|
-- INPUT PATH DELAYs
|
|
----------------------
|
|
WireDelay : block
|
|
begin
|
|
inclk0_ipd <= inclk(0);
|
|
inclk1_ipd <= inclk(1);
|
|
areset_ipd <= areset;
|
|
fbin_ipd <= fbin;
|
|
pfdena_ipd <= pfdena;
|
|
scanclk_ipd <= scanclk;
|
|
scanclkena_ipd <= scanclkena;
|
|
scandata_ipd <= scandata;
|
|
configupdate_ipd <= configupdate;
|
|
clkswitch_ipd <= clkswitch;
|
|
phaseupdown_ipd <= phaseupdown;
|
|
phasestep_ipd <= phasestep;
|
|
phasecounterselect_ipd(0) <= phasecounterselect(0);
|
|
phasecounterselect_ipd(1) <= phasecounterselect(1);
|
|
phasecounterselect_ipd(2) <= phasecounterselect(2);
|
|
phasecounterselect_ipd(3) <= phasecounterselect(3);
|
|
|
|
end block;
|
|
|
|
inclk_m <= fbclk when m_test_source = 0 else
|
|
refclk when m_test_source = 1 else
|
|
inclk_m_from_vco;
|
|
|
|
areset_ena_sig <= areset_ipd or sig_stop_vco;
|
|
|
|
pll_in_test_mode <= true when (m_test_source /= -1 or c0_test_source /= -1 or
|
|
c1_test_source /= -1 or c2_test_source /= -1 or
|
|
c3_test_source /= -1 or c4_test_source /= -1 or
|
|
c5_test_source /= -1 or c6_test_source /= -1 or
|
|
c7_test_source /= -1 or c8_test_source /= -1 or
|
|
c9_test_source /= -1)
|
|
else
|
|
false;
|
|
|
|
|
|
real_lock_high <= lock_high WHEN (sim_gate_lock_device_behavior = "on") ELSE 0;
|
|
m1 : MF_ttn_mn_cntr
|
|
port map ( clk => inclk_m,
|
|
reset => areset_ena_sig,
|
|
cout => fbclk,
|
|
initial_value => m_initial_val,
|
|
modulus => m_val,
|
|
time_delay => m_delay
|
|
);
|
|
|
|
-- add delta delay to inclk1 to ensure inclk0 and inclk1 are processed
|
|
-- in different simulation deltas.
|
|
inclk1_tmp <= inclk1_ipd;
|
|
|
|
-- Calculate the inclk0 period
|
|
PROCESS
|
|
VARIABLE inclk0_period_tmp : time := 0 ps;
|
|
BEGIN
|
|
WAIT UNTIL (inclk0_ipd'EVENT AND inclk0_ipd = '1');
|
|
IF (first_inclk0_edge_detect = '0') THEN
|
|
first_inclk0_edge_detect <= '1';
|
|
ELSE
|
|
last_inclk0_period <= inclk0_period;
|
|
inclk0_period_tmp := NOW - last_inclk0_edge;
|
|
END IF;
|
|
last_inclk0_edge <= NOW;
|
|
inclk0_period <= inclk0_period_tmp;
|
|
END PROCESS;
|
|
|
|
|
|
-- Calculate the inclk1 period
|
|
PROCESS
|
|
VARIABLE inclk1_period_tmp : time := 0 ps;
|
|
BEGIN
|
|
WAIT UNTIL (inclk1_ipd'EVENT AND inclk1_ipd = '1');
|
|
IF (first_inclk1_edge_detect = '0') THEN
|
|
first_inclk1_edge_detect <= '1';
|
|
ELSE
|
|
last_inclk1_period <= inclk1_period;
|
|
inclk1_period_tmp := NOW - last_inclk1_edge;
|
|
END IF;
|
|
last_inclk1_edge <= NOW;
|
|
inclk1_period <= inclk1_period_tmp;
|
|
END PROCESS;
|
|
|
|
process (inclk0_ipd, inclk1_tmp, clkswitch_ipd)
|
|
variable input_value : std_logic := '0';
|
|
variable current_clock : integer := 0;
|
|
variable clk0_count, clk1_count : integer := 0;
|
|
variable clk0_is_bad, clk1_is_bad : std_logic := '0';
|
|
variable primary_clk_is_bad : boolean := false;
|
|
variable current_clk_is_bad : boolean := false;
|
|
variable got_curr_clk_falling_edge_after_clkswitch : boolean := false;
|
|
variable switch_over_count : integer := 0;
|
|
variable active_clock : std_logic := '0';
|
|
variable external_switch : boolean := false;
|
|
variable diff_percent_period : integer := 0;
|
|
variable buf : line;
|
|
variable switch_clock : boolean := false;
|
|
|
|
begin
|
|
if (now = 0 ps) then
|
|
if (switch_over_type = "manual" and clkswitch_ipd = '1') then
|
|
current_clock := 1;
|
|
active_clock := '1';
|
|
end if;
|
|
end if;
|
|
if (clkswitch_ipd'event and clkswitch_ipd = '1' and switch_over_type = "auto") then
|
|
external_switch := true;
|
|
elsif (switch_over_type = "manual") then
|
|
if (clkswitch_ipd'event and clkswitch_ipd = '1') then
|
|
switch_clock := true;
|
|
elsif (clkswitch_ipd'event and clkswitch_ipd = '0') then
|
|
switch_clock := false;
|
|
end if;
|
|
end if;
|
|
|
|
if (switch_clock = true) then
|
|
if (inclk0_ipd'event or inclk1_tmp'event) then
|
|
if (current_clock = 0) then
|
|
current_clock := 1;
|
|
active_clock := '1';
|
|
clkin <= transport inclk1_tmp;
|
|
elsif (current_clock = 1) then
|
|
current_clock := 0;
|
|
active_clock := '0';
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
switch_clock := false;
|
|
end if;
|
|
end if;
|
|
|
|
-- save the current inclk event value
|
|
if (inclk0_ipd'event) then
|
|
input_value := inclk0_ipd;
|
|
elsif (inclk1_tmp'event) then
|
|
input_value := inclk1_tmp;
|
|
end if;
|
|
|
|
-- check if either input clk is bad
|
|
if (inclk0_ipd'event and inclk0_ipd = '1') then
|
|
clk0_count := clk0_count + 1;
|
|
clk0_is_bad := '0';
|
|
clk1_count := 0;
|
|
if (clk0_count > 2) then
|
|
-- no event on other clk for 2 cycles
|
|
clk1_is_bad := '1';
|
|
if (current_clock = 1) then
|
|
current_clk_is_bad := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (inclk1_tmp'event and inclk1_tmp = '1') then
|
|
clk1_count := clk1_count + 1;
|
|
clk1_is_bad := '0';
|
|
clk0_count := 0;
|
|
if (clk1_count > 2) then
|
|
-- no event on other clk for 2 cycles
|
|
clk0_is_bad := '1';
|
|
if (current_clock = 0) then
|
|
current_clk_is_bad := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- check if the bad clk is the primary clock
|
|
if (clk0_is_bad = '1') then
|
|
primary_clk_is_bad := true;
|
|
else
|
|
primary_clk_is_bad := false;
|
|
end if;
|
|
|
|
-- actual switching
|
|
if (inclk0_ipd'event and current_clock = 0) then
|
|
if (external_switch) then
|
|
if (not got_curr_clk_falling_edge_after_clkswitch) then
|
|
if (inclk0_ipd = '0') then
|
|
got_curr_clk_falling_edge_after_clkswitch := true;
|
|
end if;
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
else
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
elsif (inclk1_tmp'event and current_clock = 1) then
|
|
if (external_switch) then
|
|
if (not got_curr_clk_falling_edge_after_clkswitch) then
|
|
if (inclk1_tmp = '0') then
|
|
got_curr_clk_falling_edge_after_clkswitch := true;
|
|
end if;
|
|
clkin <= transport inclk1_tmp;
|
|
end if;
|
|
else
|
|
clkin <= transport inclk1_tmp;
|
|
end if;
|
|
else
|
|
if (input_value = '1' and enable_switch_over_counter = "on" and primary_clk_is_bad) then
|
|
switch_over_count := switch_over_count + 1;
|
|
end if;
|
|
if ((input_value = '0')) then
|
|
if (external_switch and (got_curr_clk_falling_edge_after_clkswitch or current_clk_is_bad)) or (primary_clk_is_bad and clkswitch_ipd /= '1' and (enable_switch_over_counter = "off" or switch_over_count = switch_over_counter)) then
|
|
got_curr_clk_falling_edge_after_clkswitch := false;
|
|
|
|
if (areset_ipd = '0') then
|
|
if ((inclk0_period > inclk1_period) and (inclk1_period /= 0 ps)) then
|
|
diff_percent_period := (( inclk0_period - inclk1_period ) * 100) / inclk1_period;
|
|
elsif (inclk0_period /= 0 ps) then
|
|
diff_percent_period := (( inclk1_period - inclk0_period ) * 100) / inclk0_period;
|
|
end if;
|
|
|
|
if((diff_percent_period > 20)and ( switch_over_type = "auto")) then
|
|
WRITE(buf,string'("Warning : The input clock frequencies specified for the specified PLL are too far apart for auto-switch-over feature to work properly. Please make sure that the clock frequencies are 20 percent apart for correct functionality."));
|
|
writeline(output, buf);
|
|
end if;
|
|
end if;
|
|
|
|
if (current_clock = 0) then
|
|
current_clock := 1;
|
|
else
|
|
current_clock := 0;
|
|
end if;
|
|
active_clock := not active_clock;
|
|
switch_over_count := 0;
|
|
external_switch := false;
|
|
current_clk_is_bad := false;
|
|
else
|
|
if(switch_over_type = "auto") then
|
|
if(current_clock = 0 and clk0_is_bad = '1' and clk1_is_bad = '0' ) then
|
|
current_clock := 1;
|
|
active_clock := not active_clock;
|
|
end if;
|
|
|
|
if(current_clock = 1 and clk0_is_bad = '0' and clk1_is_bad = '1' ) then
|
|
current_clock := 0;
|
|
active_clock := not active_clock;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end if;
|
|
end if;
|
|
|
|
-- schedule outputs
|
|
clkbad(0) <= clk0_is_bad;
|
|
clkbad(1) <= clk1_is_bad;
|
|
activeclock <= active_clock;
|
|
|
|
end process;
|
|
|
|
|
|
n1 : MF_ttn_mn_cntr
|
|
port map (
|
|
clk => clkin,
|
|
reset => areset_ipd,
|
|
cout => refclk,
|
|
initial_value => n_val,
|
|
modulus => n_val);
|
|
|
|
inclk_c0 <= refclk when c0_test_source = 1 else
|
|
fbclk when c0_test_source = 0 else
|
|
inclk_c_from_vco(0);
|
|
|
|
|
|
c0 : MF_ttn_scale_cntr
|
|
port map (
|
|
clk => inclk_c0,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(0),
|
|
initial => c_initial_val(0),
|
|
high => c_high_val(0),
|
|
low => c_low_val(0),
|
|
mode => c_mode_val(0),
|
|
ph_tap => c_ph_val(0));
|
|
|
|
inclk_c1 <= refclk when c1_test_source = 1 else
|
|
fbclk when c1_test_source = 0 else
|
|
c_clk(0) when c1_use_casc_in = "on" else
|
|
inclk_c_from_vco(1);
|
|
|
|
|
|
c1 : MF_ttn_scale_cntr
|
|
port map (
|
|
clk => inclk_c1,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(1),
|
|
initial => c_initial_val(1),
|
|
high => c_high_val(1),
|
|
low => c_low_val(1),
|
|
mode => c_mode_val(1),
|
|
ph_tap => c_ph_val(1));
|
|
|
|
inclk_c2 <= refclk when c2_test_source = 1 else
|
|
fbclk when c2_test_source = 0 else
|
|
c_clk(1) when c2_use_casc_in = "on" else
|
|
inclk_c_from_vco(2);
|
|
|
|
c2 : MF_ttn_scale_cntr
|
|
port map (
|
|
clk => inclk_c2,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(2),
|
|
initial => c_initial_val(2),
|
|
high => c_high_val(2),
|
|
low => c_low_val(2),
|
|
mode => c_mode_val(2),
|
|
ph_tap => c_ph_val(2));
|
|
|
|
|
|
inclk_c3 <= refclk when c3_test_source = 1 else
|
|
fbclk when c3_test_source = 0 else
|
|
c_clk(2) when c3_use_casc_in = "on" else
|
|
inclk_c_from_vco(3);
|
|
|
|
c3 : MF_ttn_scale_cntr
|
|
port map (
|
|
clk => inclk_c3,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(3),
|
|
initial => c_initial_val(3),
|
|
high => c_high_val(3),
|
|
low => c_low_val(3),
|
|
mode => c_mode_val(3),
|
|
ph_tap => c_ph_val(3));
|
|
|
|
inclk_c4 <= refclk when c4_test_source = 1 else
|
|
fbclk when c4_test_source = 0 else
|
|
c_clk(3) when (c4_use_casc_in = "on") else
|
|
inclk_c_from_vco(4);
|
|
|
|
c4 : MF_ttn_scale_cntr
|
|
port map (
|
|
clk => inclk_c4,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(4),
|
|
initial => c_initial_val(4),
|
|
high => c_high_val(4),
|
|
low => c_low_val(4),
|
|
mode => c_mode_val(4),
|
|
ph_tap => c_ph_val(4));
|
|
|
|
inclk_c5 <= refclk when c5_test_source = 1 else
|
|
fbclk when c5_test_source = 0 else
|
|
c_clk(4) when c5_use_casc_in = "on" else
|
|
inclk_c_from_vco(5);
|
|
|
|
c5 : MF_ttn_scale_cntr
|
|
port map (
|
|
clk => inclk_c5,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(5),
|
|
initial => c_initial_val(5),
|
|
high => c_high_val(5),
|
|
low => c_low_val(5),
|
|
mode => c_mode_val(5),
|
|
ph_tap => c_ph_val(5));
|
|
|
|
inclk_c6 <= refclk when c6_test_source = 1 else
|
|
fbclk when c6_test_source = 0 else
|
|
c_clk(5) when c6_use_casc_in = "on" else
|
|
inclk_c_from_vco(6);
|
|
|
|
c6 : MF_ttn_scale_cntr
|
|
port map (
|
|
clk => inclk_c6,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(6),
|
|
initial => c_initial_val(6),
|
|
high => c_high_val(6),
|
|
low => c_low_val(6),
|
|
mode => c_mode_val(6),
|
|
ph_tap => c_ph_val(6));
|
|
|
|
inclk_c7 <= refclk when c7_test_source = 1 else
|
|
fbclk when c7_test_source = 0 else
|
|
c_clk(6) when c7_use_casc_in = "on" else
|
|
inclk_c_from_vco(7);
|
|
|
|
c7 : MF_ttn_scale_cntr
|
|
port map (
|
|
clk => inclk_c7,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(7),
|
|
initial => c_initial_val(7),
|
|
high => c_high_val(7),
|
|
low => c_low_val(7),
|
|
mode => c_mode_val(7),
|
|
ph_tap => c_ph_val(7));
|
|
|
|
inclk_c8 <= refclk when c8_test_source = 1 else
|
|
fbclk when c8_test_source = 0 else
|
|
c_clk(7) when c8_use_casc_in = "on" else
|
|
inclk_c_from_vco(8);
|
|
|
|
c8 : MF_ttn_scale_cntr
|
|
port map (
|
|
clk => inclk_c8,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(8),
|
|
initial => c_initial_val(8),
|
|
high => c_high_val(8),
|
|
low => c_low_val(8),
|
|
mode => c_mode_val(8),
|
|
ph_tap => c_ph_val(8));
|
|
|
|
inclk_c9 <= refclk when c9_test_source = 1 else
|
|
fbclk when c9_test_source = 0 else
|
|
c_clk(8) when c9_use_casc_in = "on" else
|
|
inclk_c_from_vco(9);
|
|
|
|
c9 : MF_ttn_scale_cntr
|
|
port map (
|
|
clk => inclk_c9,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(9),
|
|
initial => c_initial_val(9),
|
|
high => c_high_val(9),
|
|
low => c_low_val(9),
|
|
mode => c_mode_val(9),
|
|
ph_tap => c_ph_val(9));
|
|
|
|
process(scandone_tmp, lock)
|
|
begin
|
|
if (scandone_tmp'event and (scandone_tmp = '1')) then
|
|
pll_has_just_been_reconfigured <= true;
|
|
elsif (lock'event and (lock = '1')) then
|
|
pll_has_just_been_reconfigured <= false;
|
|
end if;
|
|
end process;
|
|
|
|
process(inclk_c0, inclk_c1, areset_ipd, sig_stop_vco)
|
|
variable c0_got_first_rising_edge : boolean := false;
|
|
variable c0_count : integer := 2;
|
|
variable c0_initial_count : integer := 1;
|
|
variable c0_tmp, c1_tmp : std_logic := '0';
|
|
variable c1_got_first_rising_edge : boolean := false;
|
|
variable c1_count : integer := 2;
|
|
variable c1_initial_count : integer := 1;
|
|
begin
|
|
if (areset_ipd = '1' or sig_stop_vco = '1') then
|
|
c0_count := 2;
|
|
c1_count := 2;
|
|
c0_initial_count := 1;
|
|
c1_initial_count := 1;
|
|
c0_got_first_rising_edge := false;
|
|
c1_got_first_rising_edge := false;
|
|
else
|
|
if (not c0_got_first_rising_edge) then
|
|
if (inclk_c0'event and inclk_c0 = '1') then
|
|
if (c0_initial_count = c_initial_val(0)) then
|
|
c0_got_first_rising_edge := true;
|
|
else
|
|
c0_initial_count := c0_initial_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (inclk_c0'event) then
|
|
c0_count := c0_count + 1;
|
|
if (c0_count = (c_high_val(0) + c_low_val(0)) * 2) then
|
|
c0_count := 1;
|
|
end if;
|
|
end if;
|
|
if (inclk_c0'event and inclk_c0 = '0') then
|
|
if (c0_count = 1) then
|
|
c0_tmp := '1';
|
|
c0_got_first_rising_edge := false;
|
|
else
|
|
c0_tmp := '0';
|
|
end if;
|
|
end if;
|
|
|
|
if (not c1_got_first_rising_edge) then
|
|
if (inclk_c1'event and inclk_c1 = '1') then
|
|
if (c1_initial_count = c_initial_val(1)) then
|
|
c1_got_first_rising_edge := true;
|
|
else
|
|
c1_initial_count := c1_initial_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (inclk_c1'event) then
|
|
c1_count := c1_count + 1;
|
|
if (c1_count = (c_high_val(1) + c_low_val(1)) * 2) then
|
|
c1_count := 1;
|
|
end if;
|
|
end if;
|
|
if (inclk_c1'event and inclk_c1 = '0') then
|
|
if (c1_count = 1) then
|
|
c1_tmp := '1';
|
|
c1_got_first_rising_edge := false;
|
|
else
|
|
c1_tmp := '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
locked <= pfd_locked WHEN (test_bypass_lock_detect = "on") ELSE
|
|
lock;
|
|
|
|
|
|
process (scandone_tmp)
|
|
variable buf : line;
|
|
begin
|
|
if (scandone_tmp'event and scandone_tmp = '1') then
|
|
if (reconfig_err = false) then
|
|
ASSERT false REPORT "PLL Reprogramming completed with the following values (Values in parantheses indicate values before reprogramming) :" severity note;
|
|
write (buf, string'(" N modulus = "));
|
|
write (buf, n_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, n_val_old);
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" M modulus = "));
|
|
write (buf, m_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, m_val_old);
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" M ph_tap = "));
|
|
write (buf, m_ph_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, m_ph_val_old);
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
for i in 0 to (num_output_cntrs-1) loop
|
|
write (buf, clk_num(i));
|
|
write (buf, string'(" : "));
|
|
write (buf, cntrs(i));
|
|
write (buf, string'(" : high = "));
|
|
write (buf, c_high_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_high_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , low = "));
|
|
write (buf, c_low_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_low_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , mode = "));
|
|
write (buf, c_mode_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_mode_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , phase tap = "));
|
|
write (buf, c_ph_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_ph_val_old(i));
|
|
write (buf, string'(") "));
|
|
writeline(output, buf);
|
|
end loop;
|
|
|
|
IF (pll_reconfig_display_full_setting) THEN
|
|
write (buf, string'(" Charge Pump Current (uA) = "));
|
|
write (buf, cp_curr_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, cp_curr_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Capacitor (pF) = "));
|
|
write (buf, lfc_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfc_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Resistor (Kohm) = "));
|
|
write (buf, lfr_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfr_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" VCO_Post_Scale = "));
|
|
write (buf, vco_cur);
|
|
write (buf, string'(" ( "));
|
|
write (buf, vco_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
|
|
ELSE
|
|
write (buf, string'(" Charge Pump Current (bit setting) = "));
|
|
write (buf, alt_conv_integer(cp_curr_val_bit_setting));
|
|
write (buf, string'(" ( "));
|
|
write (buf, cp_curr_old_bit_setting);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Capacitor (bit setting) = "));
|
|
write (buf, alt_conv_integer(lfc_val_bit_setting));
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfc_old_bit_setting);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Resistor (bit setting) = "));
|
|
write (buf, alt_conv_integer(lfr_val_bit_setting));
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfr_old_bit_setting);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" VCO_Post_Scale = "));
|
|
write (buf, vco_cur);
|
|
write (buf, string'(" ( "));
|
|
write (buf, vco_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
END IF;
|
|
cp_curr_old_bit_setting <= alt_conv_integer(cp_curr_val_bit_setting);
|
|
lfc_old_bit_setting <= alt_conv_integer(lfc_val_bit_setting);
|
|
lfr_old_bit_setting <= alt_conv_integer(lfr_val_bit_setting);
|
|
else ASSERT false REPORT "Errors were encountered during PLL reprogramming. Please refer to error/warning messages above." severity warning;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
update_conf_latches <= configupdate_ipd;
|
|
|
|
|
|
process (scandone_tmp,areset_ipd,update_conf_latches, c_clk(0), c_clk(1), c_clk(2), c_clk(3), c_clk(4), c_clk(5), c_clk(6), c_clk(7), c_clk(8), c_clk(9), vco_out, fbclk, scanclk_ipd)
|
|
variable init : boolean := true;
|
|
variable low, high : std_logic_vector(7 downto 0);
|
|
variable low_fast, high_fast : std_logic_vector(3 downto 0);
|
|
variable mode : string(1 to 6) := "bypass";
|
|
variable is_error : boolean := false;
|
|
variable m_tmp, n_tmp : std_logic_vector(8 downto 0);
|
|
variable lfr_val_tmp : string(1 to 2) := " ";
|
|
|
|
variable c_high_val_tmp,c_hval : int_array(0 to 9) := (OTHERS => 1);
|
|
variable c_low_val_tmp,c_lval : int_array(0 to 9) := (OTHERS => 1);
|
|
variable c_mode_val_tmp : str_array(0 to 9);
|
|
variable m_val_tmp : integer := 0;
|
|
variable c0_rising_edge_transfer_done : boolean := false;
|
|
variable c1_rising_edge_transfer_done : boolean := false;
|
|
variable c2_rising_edge_transfer_done : boolean := false;
|
|
variable c3_rising_edge_transfer_done : boolean := false;
|
|
variable c4_rising_edge_transfer_done : boolean := false;
|
|
variable c5_rising_edge_transfer_done : boolean := false;
|
|
variable c6_rising_edge_transfer_done : boolean := false;
|
|
variable c7_rising_edge_transfer_done : boolean := false;
|
|
variable c8_rising_edge_transfer_done : boolean := false;
|
|
variable c9_rising_edge_transfer_done : boolean := false;
|
|
|
|
-- variables for scaling of multiply_by and divide_by values
|
|
variable i_clk0_mult_by : integer := 1;
|
|
variable i_clk0_div_by : integer := 1;
|
|
variable i_clk1_mult_by : integer := 1;
|
|
variable i_clk1_div_by : integer := 1;
|
|
variable i_clk2_mult_by : integer := 1;
|
|
variable i_clk2_div_by : integer := 1;
|
|
variable i_clk3_mult_by : integer := 1;
|
|
variable i_clk3_div_by : integer := 1;
|
|
variable i_clk4_mult_by : integer := 1;
|
|
variable i_clk4_div_by : integer := 1;
|
|
variable i_clk5_mult_by : integer := 1;
|
|
variable i_clk5_div_by : integer := 1;
|
|
variable i_clk6_mult_by : integer := 1;
|
|
variable i_clk6_div_by : integer := 1;
|
|
variable i_clk7_mult_by : integer := 1;
|
|
variable i_clk7_div_by : integer := 1;
|
|
variable i_clk8_mult_by : integer := 1;
|
|
variable i_clk8_div_by : integer := 1;
|
|
variable i_clk9_mult_by : integer := 1;
|
|
variable i_clk9_div_by : integer := 1;
|
|
variable max_d_value : integer := 1;
|
|
variable new_multiplier : integer := 1;
|
|
|
|
-- internal variables for storing the phase shift number.(used in lvds mode only)
|
|
variable i_clk0_phase_shift : integer := 1;
|
|
variable i_clk1_phase_shift : integer := 1;
|
|
variable i_clk2_phase_shift : integer := 1;
|
|
|
|
-- user to advanced variables
|
|
|
|
variable max_neg_abs : integer := 0;
|
|
variable i_m_initial : integer;
|
|
variable i_m : integer := 1;
|
|
variable i_n : integer := 1;
|
|
variable i_c_high : int_array(0 to 9);
|
|
variable i_c_low : int_array(0 to 9);
|
|
variable i_c_initial : int_array(0 to 9);
|
|
variable i_c_ph : int_array(0 to 9);
|
|
variable i_c_mode : str_array(0 to 9);
|
|
variable i_m_ph : integer;
|
|
variable output_count : integer;
|
|
variable new_divisor : integer;
|
|
|
|
variable clk0_cntr : string(1 to 6) := " c0";
|
|
variable clk1_cntr : string(1 to 6) := " c1";
|
|
variable clk2_cntr : string(1 to 6) := " c2";
|
|
variable clk3_cntr : string(1 to 6) := " c3";
|
|
variable clk4_cntr : string(1 to 6) := " c4";
|
|
variable clk5_cntr : string(1 to 6) := " c5";
|
|
variable clk6_cntr : string(1 to 6) := " c6";
|
|
variable clk7_cntr : string(1 to 6) := " c7";
|
|
variable clk8_cntr : string(1 to 6) := " c8";
|
|
variable clk9_cntr : string(1 to 6) := " c9";
|
|
|
|
variable fbk_cntr : string(1 to 2);
|
|
variable fbk_cntr_index : integer;
|
|
variable start_bit : integer;
|
|
variable quiet_time : time := 0 ps;
|
|
variable slowest_clk_old : time := 0 ps;
|
|
variable slowest_clk_new : time := 0 ps;
|
|
|
|
variable i : integer := 0;
|
|
variable j : integer := 0;
|
|
variable scanread_active_edge : time := 0 ps;
|
|
variable got_first_scanclk : boolean := false;
|
|
variable scanclk_last_rising_edge : time := 0 ps;
|
|
variable current_scan_data : std_logic_vector(0 to 233) := (OTHERS => '0');
|
|
|
|
variable index : integer := 0;
|
|
variable scan_chain_length : integer := GPP_SCAN_CHAIN;
|
|
variable tmp_rem : integer := 0;
|
|
variable scanclk_cycles : integer := 0;
|
|
variable lfc_tmp : std_logic_vector(1 downto 0);
|
|
variable lfr_tmp : std_logic_vector(5 downto 0);
|
|
variable lfr_int : integer := 0;
|
|
|
|
variable n_hi,n_lo,m_hi,m_lo : std_logic_vector(7 downto 0);
|
|
variable buf : line;
|
|
variable buf_scan_data : STD_LOGIC_VECTOR(0 TO 1) := (OTHERS => '0');
|
|
variable buf_scan_data_2 : STD_LOGIC_VECTOR(0 TO 2) := (OTHERS => '0');
|
|
|
|
function slowest_clk (
|
|
C0 : integer; C0_mode : string(1 to 6);
|
|
C1 : integer; C1_mode : string(1 to 6);
|
|
C2 : integer; C2_mode : string(1 to 6);
|
|
C3 : integer; C3_mode : string(1 to 6);
|
|
C4 : integer; C4_mode : string(1 to 6);
|
|
C5 : integer; C5_mode : string(1 to 6);
|
|
C6 : integer; C6_mode : string(1 to 6);
|
|
C7 : integer; C7_mode : string(1 to 6);
|
|
C8 : integer; C8_mode : string(1 to 6);
|
|
C9 : integer; C9_mode : string(1 to 6);
|
|
refclk : time; m_mod : integer) return time is
|
|
variable max_modulus : integer := 1;
|
|
variable q_period : time := 0 ps;
|
|
variable refclk_int : integer := 0;
|
|
begin
|
|
if (C0_mode /= "bypass" and C0_mode /= " off") then
|
|
max_modulus := C0;
|
|
end if;
|
|
if (C1 > max_modulus and C1_mode /= "bypass" and C1_mode /= " off") then
|
|
max_modulus := C1;
|
|
end if;
|
|
if (C2 > max_modulus and C2_mode /= "bypass" and C2_mode /= " off") then
|
|
max_modulus := C2;
|
|
end if;
|
|
if (C3 > max_modulus and C3_mode /= "bypass" and C3_mode /= " off") then
|
|
max_modulus := C3;
|
|
end if;
|
|
if (C4 > max_modulus and C4_mode /= "bypass" and C4_mode /= " off") then
|
|
max_modulus := C4;
|
|
end if;
|
|
if (C5 > max_modulus and C5_mode /= "bypass" and C5_mode /= " off") then
|
|
max_modulus := C5;
|
|
end if;
|
|
if (C6 > max_modulus and C6_mode /= "bypass" and C6_mode /= " off") then
|
|
max_modulus := C6;
|
|
end if;
|
|
if (C7 > max_modulus and C7_mode /= "bypass" and C7_mode /= " off") then
|
|
max_modulus := C7;
|
|
end if;
|
|
if (C8 > max_modulus and C8_mode /= "bypass" and C8_mode /= " off") then
|
|
max_modulus := C8;
|
|
end if;
|
|
if (C9 > max_modulus and C9_mode /= "bypass" and C9_mode /= " off") then
|
|
max_modulus := C9;
|
|
end if;
|
|
|
|
refclk_int := refclk / 1 ps;
|
|
if (m_mod /= 0) then
|
|
q_period := (refclk_int * max_modulus / m_mod) * 1 ps;
|
|
end if;
|
|
return (2*q_period);
|
|
end slowest_clk;
|
|
|
|
function int2bin (arg : integer; size : integer) return std_logic_vector is
|
|
variable int_val : integer := arg;
|
|
variable result : std_logic_vector(size-1 downto 0);
|
|
begin
|
|
for i in 0 to result'left loop
|
|
if ((int_val mod 2) = 0) then
|
|
result(i) := '0';
|
|
else
|
|
result(i) := '1';
|
|
end if;
|
|
int_val := int_val/2;
|
|
end loop;
|
|
return result;
|
|
end int2bin;
|
|
|
|
function extract_cntr_string (arg:string) return string is
|
|
variable str : string(1 to 6) := " c0";
|
|
begin
|
|
if (arg = "c0") then
|
|
str := " c0";
|
|
elsif (arg = "c1") then
|
|
str := " c1";
|
|
elsif (arg = "c2") then
|
|
str := " c2";
|
|
elsif (arg = "c3") then
|
|
str := " c3";
|
|
elsif (arg = "c4") then
|
|
str := " c4";
|
|
elsif (arg = "c5") then
|
|
str := " c5";
|
|
elsif (arg = "c6") then
|
|
str := " c6";
|
|
elsif (arg = "c7") then
|
|
str := " c7";
|
|
elsif (arg = "c8") then
|
|
str := " c8";
|
|
elsif (arg = "c9") then
|
|
str := " c9";
|
|
else str := " c0";
|
|
|
|
end if;
|
|
|
|
return str;
|
|
|
|
end extract_cntr_string;
|
|
|
|
function extract_cntr_index (arg:string) return integer is
|
|
variable index : integer := 0;
|
|
begin
|
|
if (arg(6) = '0') then
|
|
index := 0;
|
|
elsif (arg(6) = '1') then
|
|
index := 1;
|
|
elsif (arg(6) = '2') then
|
|
index := 2;
|
|
elsif (arg(6) = '3') then
|
|
index := 3;
|
|
elsif (arg(6) = '4') then
|
|
index := 4;
|
|
elsif (arg(6) = '5') then
|
|
index := 5;
|
|
elsif (arg(6) = '6') then
|
|
index := 6;
|
|
elsif (arg(6) = '7') then
|
|
index := 7;
|
|
elsif (arg(6) = '8') then
|
|
index := 8;
|
|
else index := 9;
|
|
end if;
|
|
|
|
return index;
|
|
end extract_cntr_index;
|
|
|
|
function output_cntr_num (arg:string) return string is
|
|
variable str : string(1 to 6) := "unused";
|
|
begin
|
|
if (arg = "c0") then
|
|
str := " clk0";
|
|
elsif (arg = "c1") then
|
|
str := " clk1";
|
|
elsif (arg = "c2") then
|
|
str := " clk2";
|
|
elsif (arg = "c3") then
|
|
str := " clk3";
|
|
elsif (arg = "c4") then
|
|
str := " clk4";
|
|
elsif (arg = "c5") then
|
|
str := " clk5";
|
|
elsif (arg = "c6") then
|
|
str := " clk6";
|
|
elsif (arg = "c7") then
|
|
str := " clk7";
|
|
elsif (arg = "c8") then
|
|
str := " clk8";
|
|
elsif (arg = "c9") then
|
|
str := " clk9";
|
|
else str := "unused";
|
|
end if;
|
|
return str;
|
|
end output_cntr_num;
|
|
|
|
begin
|
|
IF (areset_ipd'EVENT AND areset_ipd = '1') then
|
|
c_ph_val <= i_c_ph;
|
|
END IF;
|
|
|
|
if (init) then
|
|
if (m = 0) then
|
|
clk9_cntr := " c9";
|
|
clk8_cntr := " c8";
|
|
clk7_cntr := " c7";
|
|
clk6_cntr := " c6";
|
|
clk5_cntr := " c5";
|
|
clk4_cntr := " c4";
|
|
clk3_cntr := " c3";
|
|
clk2_cntr := " c2";
|
|
clk1_cntr := " c1";
|
|
clk0_cntr := " c0";
|
|
else
|
|
clk9_cntr := extract_cntr_string(clk9_counter);
|
|
clk8_cntr := extract_cntr_string(clk8_counter);
|
|
clk7_cntr := extract_cntr_string(clk7_counter);
|
|
clk6_cntr := extract_cntr_string(clk6_counter);
|
|
clk5_cntr := extract_cntr_string(clk5_counter);
|
|
clk4_cntr := extract_cntr_string(clk4_counter);
|
|
clk3_cntr := extract_cntr_string(clk3_counter);
|
|
clk2_cntr := extract_cntr_string(clk2_counter);
|
|
clk1_cntr := extract_cntr_string(clk1_counter);
|
|
clk0_cntr := extract_cntr_string(clk0_counter);
|
|
end if;
|
|
|
|
clk_num(9) <= output_cntr_num(clk9_counter);
|
|
clk_num(8) <= output_cntr_num(clk8_counter);
|
|
clk_num(7) <= output_cntr_num(clk7_counter);
|
|
clk_num(6) <= output_cntr_num(clk6_counter);
|
|
clk_num(5) <= output_cntr_num(clk5_counter);
|
|
clk_num(4) <= output_cntr_num(clk4_counter);
|
|
clk_num(3) <= output_cntr_num(clk3_counter);
|
|
clk_num(2) <= output_cntr_num(clk2_counter);
|
|
clk_num(1) <= output_cntr_num(clk1_counter);
|
|
clk_num(0) <= output_cntr_num(clk0_counter);
|
|
|
|
i_clk0_counter <= extract_cntr_index(clk0_cntr);
|
|
i_clk1_counter <= extract_cntr_index(clk1_cntr);
|
|
i_clk2_counter <= extract_cntr_index(clk2_cntr);
|
|
i_clk3_counter <= extract_cntr_index(clk3_cntr);
|
|
i_clk4_counter <= extract_cntr_index(clk4_cntr);
|
|
i_clk5_counter <= extract_cntr_index(clk5_cntr);
|
|
i_clk6_counter <= extract_cntr_index(clk6_cntr);
|
|
i_clk7_counter <= extract_cntr_index(clk7_cntr);
|
|
i_clk8_counter <= extract_cntr_index(clk8_cntr);
|
|
i_clk9_counter <= extract_cntr_index(clk9_cntr);
|
|
|
|
|
|
if (m = 0) then -- convert user parameters to advanced
|
|
-- set the limit of the divide_by value that can be returned by
|
|
-- the following function.
|
|
max_d_value := 1500;
|
|
|
|
-- scale down the multiply_by and divide_by values provided by the design
|
|
-- before attempting to use them in the calculations below
|
|
find_simple_integer_fraction(clk0_multiply_by, clk0_divide_by,
|
|
max_d_value, i_clk0_mult_by, i_clk0_div_by);
|
|
find_simple_integer_fraction(clk1_multiply_by, clk1_divide_by,
|
|
max_d_value, i_clk1_mult_by, i_clk1_div_by);
|
|
find_simple_integer_fraction(clk2_multiply_by, clk2_divide_by,
|
|
max_d_value, i_clk2_mult_by, i_clk2_div_by);
|
|
find_simple_integer_fraction(clk3_multiply_by, clk3_divide_by,
|
|
max_d_value, i_clk3_mult_by, i_clk3_div_by);
|
|
find_simple_integer_fraction(clk4_multiply_by, clk4_divide_by,
|
|
max_d_value, i_clk4_mult_by, i_clk4_div_by);
|
|
find_simple_integer_fraction(clk5_multiply_by, clk5_divide_by,
|
|
max_d_value, i_clk5_mult_by, i_clk5_div_by);
|
|
find_simple_integer_fraction(clk6_multiply_by, clk6_divide_by,
|
|
max_d_value, i_clk6_mult_by, i_clk6_div_by);
|
|
find_simple_integer_fraction(clk7_multiply_by, clk7_divide_by,
|
|
max_d_value, i_clk7_mult_by, i_clk7_div_by);
|
|
find_simple_integer_fraction(clk8_multiply_by, clk8_divide_by,
|
|
max_d_value, i_clk8_mult_by, i_clk8_div_by);
|
|
find_simple_integer_fraction(clk9_multiply_by, clk9_divide_by,
|
|
max_d_value, i_clk9_mult_by, i_clk9_div_by);
|
|
|
|
if (vco_frequency_control = "manual_phase") then
|
|
find_m_and_n_4_manual_phase(inclk0_input_frequency, vco_phase_shift_step,
|
|
i_clk0_mult_by, i_clk1_mult_by,
|
|
i_clk2_mult_by, i_clk3_mult_by,
|
|
i_clk4_mult_by,
|
|
i_clk5_mult_by,i_clk6_mult_by,
|
|
i_clk7_mult_by,i_clk8_mult_by,i_clk9_mult_by,
|
|
i_clk0_div_by, i_clk1_div_by,
|
|
i_clk2_div_by, i_clk3_div_by,
|
|
i_clk4_div_by,
|
|
i_clk5_div_by,i_clk6_div_by,
|
|
i_clk7_div_by,i_clk8_div_by,i_clk9_div_by,
|
|
clk0_counter, clk1_counter,
|
|
clk2_counter, clk3_counter,
|
|
clk4_counter,
|
|
clk5_counter,clk6_counter,
|
|
clk7_counter,clk8_counter,clk9_counter,
|
|
i_m, i_n);
|
|
elsif (((pll_type = "fast") or (pll_type = "lvds") OR (pll_type = "left_right")) and ((vco_multiply_by /= 0) and (vco_divide_by /= 0))) then
|
|
i_n := vco_divide_by;
|
|
i_m := vco_multiply_by;
|
|
else
|
|
i_n := 1;
|
|
|
|
if (((pll_type = "fast") or (pll_type = "left_right")) and (compensate_clock = "lvdsclk")) then
|
|
i_m := i_clk0_mult_by;
|
|
else
|
|
i_m := lcm (i_clk0_mult_by, i_clk1_mult_by,
|
|
i_clk2_mult_by, i_clk3_mult_by,
|
|
i_clk4_mult_by,
|
|
i_clk5_mult_by,i_clk6_mult_by,
|
|
i_clk7_mult_by,i_clk8_mult_by,i_clk9_mult_by,
|
|
inclk0_input_frequency);
|
|
end if;
|
|
end if;
|
|
|
|
if (pll_type = "flvds") then
|
|
-- Need to readjust phase shift values when the clock multiply value has been readjusted.
|
|
new_multiplier := clk0_multiply_by / i_clk0_mult_by;
|
|
i_clk0_phase_shift := str2int(clk0_phase_shift) * new_multiplier;
|
|
i_clk1_phase_shift := str2int(clk1_phase_shift) * new_multiplier;
|
|
i_clk2_phase_shift := str2int(clk2_phase_shift) * new_multiplier;
|
|
else
|
|
i_clk0_phase_shift := str2int(clk0_phase_shift);
|
|
i_clk1_phase_shift := str2int(clk1_phase_shift);
|
|
i_clk2_phase_shift := str2int(clk2_phase_shift);
|
|
end if;
|
|
|
|
max_neg_abs := maxnegabs(i_clk0_phase_shift,
|
|
i_clk1_phase_shift,
|
|
i_clk2_phase_shift,
|
|
str2int(clk3_phase_shift),
|
|
str2int(clk4_phase_shift),
|
|
str2int(clk5_phase_shift),
|
|
str2int(clk6_phase_shift),
|
|
str2int(clk7_phase_shift),
|
|
str2int(clk8_phase_shift),
|
|
str2int(clk9_phase_shift)
|
|
);
|
|
i_m_ph := counter_ph(get_phase_degree(max_neg_abs,inclk0_input_frequency), i_m, i_n);
|
|
|
|
i_c_ph(0) := counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(1) := counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(2) := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(3) := counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(4) := counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(5) := counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(6) := counter_ph(get_phase_degree(ph_adjust(str2int(clk6_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(7) := counter_ph(get_phase_degree(ph_adjust(str2int(clk7_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(8) := counter_ph(get_phase_degree(ph_adjust(str2int(clk8_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(9) := counter_ph(get_phase_degree(ph_adjust(str2int(clk9_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
|
|
|
|
i_c_high(0) := counter_high(output_counter_value(i_clk0_div_by,
|
|
i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
|
|
i_c_high(1) := counter_high(output_counter_value(i_clk1_div_by,
|
|
i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
|
|
i_c_high(2) := counter_high(output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
i_c_high(3) := counter_high(output_counter_value(i_clk3_div_by,
|
|
i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
|
|
i_c_high(4) := counter_high(output_counter_value(i_clk4_div_by,
|
|
i_clk4_mult_by, i_m, i_n), clk4_duty_cycle);
|
|
i_c_high(5) := counter_high(output_counter_value(i_clk5_div_by,
|
|
i_clk5_mult_by, i_m, i_n), clk5_duty_cycle);
|
|
i_c_high(6) := counter_high(output_counter_value(i_clk6_div_by,
|
|
i_clk6_mult_by, i_m, i_n), clk6_duty_cycle);
|
|
|
|
i_c_high(7) := counter_high(output_counter_value(i_clk7_div_by,
|
|
i_clk7_mult_by, i_m, i_n), clk7_duty_cycle);
|
|
|
|
i_c_high(8) := counter_high(output_counter_value(i_clk8_div_by,
|
|
i_clk8_mult_by, i_m, i_n), clk8_duty_cycle);
|
|
|
|
i_c_high(9) := counter_high(output_counter_value(i_clk9_div_by,
|
|
i_clk9_mult_by, i_m, i_n), clk9_duty_cycle);
|
|
|
|
i_c_low(0) := counter_low(output_counter_value(i_clk0_div_by,
|
|
i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
|
|
i_c_low(1) := counter_low(output_counter_value(i_clk1_div_by,
|
|
i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
|
|
i_c_low(2) := counter_low(output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
i_c_low(3) := counter_low(output_counter_value(i_clk3_div_by,
|
|
i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
|
|
i_c_low(4) := counter_low(output_counter_value(i_clk4_div_by,
|
|
i_clk4_mult_by, i_m, i_n), clk4_duty_cycle);
|
|
i_c_low(5) := counter_low(output_counter_value(i_clk5_div_by,
|
|
i_clk5_mult_by, i_m, i_n), clk5_duty_cycle);
|
|
i_c_low(6) := counter_low(output_counter_value(i_clk6_div_by,
|
|
i_clk6_mult_by, i_m, i_n), clk6_duty_cycle);
|
|
i_c_low(7) := counter_low(output_counter_value(i_clk7_div_by,
|
|
i_clk7_mult_by, i_m, i_n), clk7_duty_cycle);
|
|
i_c_low(8) := counter_low(output_counter_value(i_clk8_div_by,
|
|
i_clk8_mult_by, i_m, i_n), clk8_duty_cycle);
|
|
i_c_low(9) := counter_low(output_counter_value(i_clk9_div_by,
|
|
i_clk9_mult_by, i_m, i_n), clk9_duty_cycle);
|
|
|
|
i_m_initial := counter_initial(get_phase_degree(max_neg_abs, inclk0_input_frequency), i_m,i_n);
|
|
|
|
i_c_initial(0) := counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(1) := counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(2) := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(3) := counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(4) := counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(5) := counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(6) := counter_initial(get_phase_degree(ph_adjust(str2int(clk6_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(7) := counter_initial(get_phase_degree(ph_adjust(str2int(clk7_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(8) := counter_initial(get_phase_degree(ph_adjust(str2int(clk8_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(9) := counter_initial(get_phase_degree(ph_adjust(str2int(clk9_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_mode(0) := counter_mode(clk0_duty_cycle, output_counter_value(i_clk0_div_by, i_clk0_mult_by, i_m, i_n));
|
|
i_c_mode(1) := counter_mode(clk1_duty_cycle, output_counter_value(i_clk1_div_by, i_clk1_mult_by, i_m, i_n));
|
|
i_c_mode(2) := counter_mode(clk2_duty_cycle, output_counter_value(i_clk2_div_by, i_clk2_mult_by, i_m, i_n));
|
|
i_c_mode(3) := counter_mode(clk3_duty_cycle, output_counter_value(i_clk3_div_by, i_clk3_mult_by, i_m, i_n));
|
|
i_c_mode(4) := counter_mode(clk4_duty_cycle, output_counter_value(i_clk4_div_by, i_clk4_mult_by, i_m, i_n));
|
|
i_c_mode(5) := counter_mode(clk5_duty_cycle, output_counter_value(i_clk5_div_by, i_clk5_mult_by, i_m, i_n));
|
|
i_c_mode(6) := counter_mode(clk6_duty_cycle, output_counter_value(i_clk6_div_by, i_clk6_mult_by, i_m, i_n));
|
|
i_c_mode(7) := counter_mode(clk7_duty_cycle, output_counter_value(i_clk7_div_by, i_clk7_mult_by, i_m, i_n));
|
|
i_c_mode(8) := counter_mode(clk8_duty_cycle, output_counter_value(i_clk8_div_by, i_clk8_mult_by, i_m, i_n));
|
|
i_c_mode(9) := counter_mode(clk9_duty_cycle, output_counter_value(i_clk9_div_by, i_clk9_mult_by, i_m, i_n));
|
|
|
|
|
|
|
|
else -- m /= 0
|
|
|
|
i_n := n;
|
|
i_m := m;
|
|
i_m_initial := m_initial;
|
|
i_m_ph := m_ph;
|
|
i_c_ph(0) := c0_ph;
|
|
i_c_ph(1) := c1_ph;
|
|
i_c_ph(2) := c2_ph;
|
|
i_c_ph(3) := c3_ph;
|
|
i_c_ph(4) := c4_ph;
|
|
i_c_ph(5) := c5_ph;
|
|
i_c_ph(6) := c6_ph;
|
|
i_c_ph(7) := c7_ph;
|
|
i_c_ph(8) := c8_ph;
|
|
i_c_ph(9) := c9_ph;
|
|
i_c_high(0) := c0_high;
|
|
i_c_high(1) := c1_high;
|
|
i_c_high(2) := c2_high;
|
|
i_c_high(3) := c3_high;
|
|
i_c_high(4) := c4_high;
|
|
i_c_high(5) := c5_high;
|
|
i_c_high(6) := c6_high;
|
|
i_c_high(7) := c7_high;
|
|
i_c_high(8) := c8_high;
|
|
i_c_high(9) := c9_high;
|
|
i_c_low(0) := c0_low;
|
|
i_c_low(1) := c1_low;
|
|
i_c_low(2) := c2_low;
|
|
i_c_low(3) := c3_low;
|
|
i_c_low(4) := c4_low;
|
|
i_c_low(5) := c5_low;
|
|
i_c_low(6) := c6_low;
|
|
i_c_low(7) := c7_low;
|
|
i_c_low(8) := c8_low;
|
|
i_c_low(9) := c9_low;
|
|
i_c_initial(0) := c0_initial;
|
|
i_c_initial(1) := c1_initial;
|
|
i_c_initial(2) := c2_initial;
|
|
i_c_initial(3) := c3_initial;
|
|
i_c_initial(4) := c4_initial;
|
|
i_c_initial(5) := c5_initial;
|
|
i_c_initial(6) := c6_initial;
|
|
i_c_initial(7) := c7_initial;
|
|
i_c_initial(8) := c8_initial;
|
|
i_c_initial(9) := c9_initial;
|
|
i_c_mode(0) := translate_string(c0_mode);
|
|
i_c_mode(1) := translate_string(c1_mode);
|
|
i_c_mode(2) := translate_string(c2_mode);
|
|
i_c_mode(3) := translate_string(c3_mode);
|
|
i_c_mode(4) := translate_string(c4_mode);
|
|
i_c_mode(5) := translate_string(c5_mode);
|
|
i_c_mode(6) := translate_string(c6_mode);
|
|
i_c_mode(7) := translate_string(c7_mode);
|
|
i_c_mode(8) := translate_string(c8_mode);
|
|
i_c_mode(9) := translate_string(c9_mode);
|
|
|
|
end if; -- user to advanced conversion.
|
|
|
|
m_initial_val <= i_m_initial;
|
|
n_val <= i_n;
|
|
m_val <= i_m;
|
|
|
|
if (i_m = 1) then
|
|
m_mode_val <= "bypass";
|
|
else
|
|
m_mode_val <= " ";
|
|
end if;
|
|
if (i_n = 1) then
|
|
n_mode_val <= "bypass";
|
|
else
|
|
n_mode_val <= " ";
|
|
end if;
|
|
|
|
m_ph_val <= i_m_ph;
|
|
m_ph_initial <= i_m_ph;
|
|
m_val_tmp := i_m;
|
|
|
|
for i in 0 to 9 loop
|
|
if (i_c_mode(i) = "bypass") then
|
|
if (pll_type = "fast" or pll_type = "lvds" OR (pll_type = "left_right")) then
|
|
i_c_high(i) := 16;
|
|
i_c_low(i) := 16;
|
|
else
|
|
i_c_high(i) := 256;
|
|
i_c_low(i) := 256;
|
|
end if;
|
|
end if;
|
|
c_ph_val(i) <= i_c_ph(i);
|
|
c_initial_val(i) <= i_c_initial(i);
|
|
c_high_val(i) <= i_c_high(i);
|
|
c_low_val(i) <= i_c_low(i);
|
|
c_mode_val(i) <= i_c_mode(i);
|
|
c_high_val_tmp(i) := i_c_high(i);
|
|
c_hval(i) := i_c_high(i);
|
|
c_low_val_tmp(i) := i_c_low(i);
|
|
c_lval(i) := i_c_low(i);
|
|
c_mode_val_tmp(i) := i_c_mode(i);
|
|
c_ph_val_orig(i) <= i_c_ph(i);
|
|
c_high_val_hold(i) <= i_c_high(i);
|
|
c_low_val_hold(i) <= i_c_low(i);
|
|
c_mode_val_hold(i) <= i_c_mode(i);
|
|
end loop;
|
|
|
|
|
|
|
|
if (pll_type = "fast" OR (pll_type = "left_right")) then
|
|
scan_chain_length := FAST_SCAN_CHAIN;
|
|
else
|
|
scan_chain_length := GPP_SCAN_CHAIN;
|
|
end if;
|
|
|
|
|
|
if (pll_type = "fast" or pll_type = "lvds" OR (pll_type = "left_right")) then
|
|
num_output_cntrs <= 7;
|
|
else
|
|
num_output_cntrs <= 10;
|
|
end if;
|
|
|
|
init := false;
|
|
elsif (scandone_tmp'EVENT AND scandone_tmp = '1') then
|
|
c0_rising_edge_transfer_done := false;
|
|
c1_rising_edge_transfer_done := false;
|
|
c2_rising_edge_transfer_done := false;
|
|
c3_rising_edge_transfer_done := false;
|
|
c4_rising_edge_transfer_done := false;
|
|
c5_rising_edge_transfer_done := false;
|
|
c6_rising_edge_transfer_done := false;
|
|
c7_rising_edge_transfer_done := false;
|
|
c8_rising_edge_transfer_done := false;
|
|
c9_rising_edge_transfer_done := false;
|
|
update_conf_latches_reg <= '0';
|
|
elsif (update_conf_latches'event and update_conf_latches = '1') then
|
|
initiate_reconfig <= '1';
|
|
elsif (areset_ipd'event AND areset_ipd = '1') then
|
|
if (scandone_tmp = '0') then scandone_tmp <= '1' AFTER scanclk_period; end if;
|
|
elsif (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
IF (initiate_reconfig = '1') THEN
|
|
initiate_reconfig <= '0';
|
|
ASSERT false REPORT "PLL Reprogramming Initiated" severity note;
|
|
|
|
update_conf_latches_reg <= update_conf_latches;
|
|
reconfig_err <= false;
|
|
scandone_tmp <= '0';
|
|
cp_curr_old <= cp_curr_val;
|
|
lfc_old <= lfc_val;
|
|
lfr_old <= lfr_val;
|
|
vco_old <= vco_cur;
|
|
-- LF unused : bit 0,1
|
|
-- LF Capacitance : bits 2,3 : all values are legal
|
|
buf_scan_data := scan_data(2 TO 3);
|
|
|
|
IF ((pll_type = "fast") OR (pll_type = "lvds") OR (pll_type = "left_right")) THEN
|
|
lfc_val <= fpll_loop_filter_c_arr(alt_conv_integer(buf_scan_data));
|
|
ELSE
|
|
lfc_val <= loop_filter_c_arr(alt_conv_integer(buf_scan_data));
|
|
END IF;
|
|
-- LF Resistance : bits 4-8
|
|
-- valid values - 00000,00100,10000,10100,11000,11011,11100,11110
|
|
IF (scan_data(4 TO 8) = "00000") THEN
|
|
lfr_val <= "20";
|
|
ELSIF (scan_data(4 TO 8) = "00100") THEN
|
|
lfr_val <= "16";
|
|
ELSIF (scan_data(4 TO 8) = "10000") THEN
|
|
lfr_val <= "12";
|
|
ELSIF (scan_data(4 TO 8) = "10100") THEN
|
|
lfr_val <= "08";
|
|
ELSIF (scan_data(4 TO 8) = "11000") THEN
|
|
lfr_val <= "06";
|
|
ELSIF (scan_data(4 TO 8) = "11011") THEN
|
|
lfr_val <= "04";
|
|
ELSIF (scan_data(4 TO 8) = "11100") THEN
|
|
lfr_val <= "02";
|
|
ELSE
|
|
lfr_val <= "01";
|
|
END IF;
|
|
|
|
|
|
-- VCO post scale assignment
|
|
if (scan_data(9) = '1') then -- vco_post_scale = 1
|
|
i_vco_max <= VCO_MAX_NO_DIVISION/2;
|
|
i_vco_min <= VCO_MIN_NO_DIVISION/2;
|
|
vco_cur <= 1;
|
|
else
|
|
i_vco_max <= vco_max;
|
|
i_vco_min <= vco_min;
|
|
vco_cur <= 2;
|
|
end if;
|
|
-- CP
|
|
-- Bit 9 : CRBYPASS
|
|
-- Bit 10-14 : unused
|
|
-- Bits 15-17 : all values are legal
|
|
|
|
buf_scan_data_2 := scan_data(15 TO 17);
|
|
cp_curr_val <= charge_pump_curr_arr(alt_conv_integer(buf_scan_data_2));
|
|
-- save old values for display info.
|
|
|
|
cp_curr_val_bit_setting <= scan_data(15 TO 17);
|
|
lfc_val_bit_setting <= scan_data(2 TO 3);
|
|
lfr_val_bit_setting <= scan_data(4 TO 8);
|
|
|
|
m_val_old <= m_val;
|
|
n_val_old <= n_val;
|
|
m_mode_val_old <= m_mode_val;
|
|
n_mode_val_old <= n_mode_val;
|
|
WHILE (i < num_output_cntrs) LOOP
|
|
c_high_val_old(i) <= c_high_val(i);
|
|
c_low_val_old(i) <= c_low_val(i);
|
|
c_mode_val_old(i) <= c_mode_val(i);
|
|
i := i + 1;
|
|
END LOOP;
|
|
-- M counter
|
|
-- 1. Mode - bypass (bit 18)
|
|
|
|
IF (scan_data(18) = '1') THEN
|
|
m_mode_val <= "bypass";
|
|
-- 3. Mode - odd/even (bit 27)
|
|
ELSIF (scan_data(27) = '1') THEN
|
|
m_mode_val <= " odd";
|
|
ELSE
|
|
m_mode_val <= " even";
|
|
END IF;
|
|
|
|
-- 2. High (bit 19-26)
|
|
|
|
m_hi := scan_data(19 TO 26);
|
|
|
|
-- 4. Low (bit 28-35)
|
|
|
|
m_lo := scan_data(28 TO 35);
|
|
-- N counter
|
|
-- 1. Mode - bypass (bit 36)
|
|
|
|
IF (scan_data(36) = '1') THEN
|
|
n_mode_val <= "bypass";
|
|
-- 3. Mode - odd/even (bit 45)
|
|
ELSIF (scan_data(45) = '1') THEN
|
|
n_mode_val <= " odd";
|
|
ELSE
|
|
n_mode_val <= " even";
|
|
END IF;
|
|
|
|
-- 2. High (bit 37-44)
|
|
|
|
n_hi := scan_data(37 TO 44);
|
|
|
|
-- 4. Low (bit 46-53)
|
|
|
|
n_lo := scan_data(46 TO 53);
|
|
-- C counters (start bit 54) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low
|
|
|
|
i := 0;
|
|
WHILE (i < num_output_cntrs) LOOP
|
|
-- 1. Mode - bypass
|
|
|
|
IF (scan_data(54 + i * 18 + 0) = '1') THEN
|
|
c_mode_val_tmp(i) := "bypass";
|
|
-- 3. Mode - odd/even
|
|
ELSIF (scan_data(54 + i * 18 + 9) = '1') THEN
|
|
c_mode_val_tmp(i) := " odd";
|
|
ELSE
|
|
c_mode_val_tmp(i) := " even";
|
|
END IF;
|
|
-- 2. Hi
|
|
|
|
high := scan_data(54 + i * 18 + 1 TO 54 + i * 18 + 8);
|
|
c_hval(i) := alt_conv_integer(high);
|
|
IF (c_hval(i) /= 0) THEN
|
|
c_high_val_tmp(i) := c_hval(i);
|
|
ELSE
|
|
c_high_val_tmp(i) := alt_conv_integer("000000001");
|
|
END IF;
|
|
|
|
-- 4. Low
|
|
|
|
low := scan_data(54 + i * 18 + 10 TO 54 + i * 18 + 17);
|
|
c_lval(i) := alt_conv_integer(low);
|
|
IF (c_lval(i) /= 0) THEN
|
|
c_low_val_tmp(i) := c_lval(i);
|
|
ELSE
|
|
c_low_val_tmp(i) := alt_conv_integer("000000001");
|
|
END IF;
|
|
i := i + 1;
|
|
END LOOP;
|
|
-- Legality Checks
|
|
|
|
-- M counter value
|
|
IF(scan_data(18) /= '1') THEN
|
|
IF ((m_hi /= m_lo) and (scan_data(27) /= '1')) THEN
|
|
reconfig_err <= TRUE;
|
|
WRITE(buf,string'("Warning : The M counter of the " & family_name & " Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work"));
|
|
writeline(output, buf);
|
|
ELSIF (m_hi /= "00000000") THEN
|
|
m_val_tmp := alt_conv_integer(m_hi) + alt_conv_integer(m_lo);
|
|
ELSE
|
|
m_val_tmp := alt_conv_integer("000000001");
|
|
END IF;
|
|
ELSE
|
|
m_val_tmp := alt_conv_integer("10000000");
|
|
END IF;
|
|
-- N counter value
|
|
IF(scan_data(36) /= '1') THEN
|
|
IF ((n_hi /= n_lo)and (scan_data(45) /= '1')) THEN
|
|
reconfig_err <= TRUE;
|
|
WRITE(buf,string'("Warning : The N counter of the " & family_name & " Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work"));
|
|
writeline(output, buf);
|
|
ELSIF (n_hi /= "00000000") THEN
|
|
n_val <= alt_conv_integer(n_hi) + alt_conv_integer(n_lo);
|
|
ELSE
|
|
n_val <= alt_conv_integer("000000001");
|
|
END IF;
|
|
ELSE
|
|
n_val <= alt_conv_integer("10000000");
|
|
END IF;
|
|
-- TODO : Give warnings/errors in the following cases?
|
|
-- 1. Illegal counter values (error)
|
|
-- 2. Change of mode (warning)
|
|
-- 3. Only 50% duty cycle allowed for M counter (odd mode - hi-lo=1,even - hi-lo=0)
|
|
|
|
END IF;
|
|
end if;
|
|
|
|
|
|
if (fbclk'event and fbclk = '1') then
|
|
m_val <= m_val_tmp;
|
|
end if;
|
|
|
|
if (update_conf_latches_reg = '1') then
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c0_rising_edge_transfer_done := true;
|
|
c_high_val(0) <= c_high_val_tmp(0);
|
|
c_mode_val(0) <= c_mode_val_tmp(0);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c1_rising_edge_transfer_done := true;
|
|
c_high_val(1) <= c_high_val_tmp(1);
|
|
c_mode_val(1) <= c_mode_val_tmp(1);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c2_rising_edge_transfer_done := true;
|
|
c_high_val(2) <= c_high_val_tmp(2);
|
|
c_mode_val(2) <= c_mode_val_tmp(2);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(3) <= c_high_val_tmp(3);
|
|
c_mode_val(3) <= c_mode_val_tmp(3);
|
|
c3_rising_edge_transfer_done := true;
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(4) <= c_high_val_tmp(4);
|
|
c_mode_val(4) <= c_mode_val_tmp(4);
|
|
c4_rising_edge_transfer_done := true;
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(5) <= c_high_val_tmp(5);
|
|
c_mode_val(5) <= c_mode_val_tmp(5);
|
|
c5_rising_edge_transfer_done := true;
|
|
end if;
|
|
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(6) <= c_high_val_tmp(6);
|
|
c_mode_val(6) <= c_mode_val_tmp(6);
|
|
c6_rising_edge_transfer_done := true;
|
|
end if;
|
|
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(7) <= c_high_val_tmp(7);
|
|
c_mode_val(7) <= c_mode_val_tmp(7);
|
|
c7_rising_edge_transfer_done := true;
|
|
end if;
|
|
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(8) <= c_high_val_tmp(8);
|
|
c_mode_val(8) <= c_mode_val_tmp(8);
|
|
c8_rising_edge_transfer_done := true;
|
|
end if;
|
|
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(9) <= c_high_val_tmp(9);
|
|
c_mode_val(9) <= c_mode_val_tmp(9);
|
|
c9_rising_edge_transfer_done := true;
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c0_rising_edge_transfer_done) then
|
|
c_low_val(0) <= c_low_val_tmp(0);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c1_rising_edge_transfer_done) then
|
|
c_low_val(1) <= c_low_val_tmp(1);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c2_rising_edge_transfer_done) then
|
|
c_low_val(2) <= c_low_val_tmp(2);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c3_rising_edge_transfer_done) then
|
|
c_low_val(3) <= c_low_val_tmp(3);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c4_rising_edge_transfer_done) then
|
|
c_low_val(4) <= c_low_val_tmp(4);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c5_rising_edge_transfer_done) then
|
|
c_low_val(5) <= c_low_val_tmp(5);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c6_rising_edge_transfer_done) then
|
|
c_low_val(6) <= c_low_val_tmp(6);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c7_rising_edge_transfer_done) then
|
|
c_low_val(7) <= c_low_val_tmp(7);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c8_rising_edge_transfer_done) then
|
|
c_low_val(8) <= c_low_val_tmp(8);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c9_rising_edge_transfer_done) then
|
|
c_low_val(9) <= c_low_val_tmp(9);
|
|
end if;
|
|
|
|
if (update_phase = '1') then
|
|
if (vco_out(0)'event and vco_out(0) = '0') then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 0) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 0) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(1)'event and vco_out(1) = '0') then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 1) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 1) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(2)'event and vco_out(2) = '0') then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 2) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 2) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(3)'event and vco_out(3) = '0') then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 3) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 3) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(4)'event and vco_out(4) = '0') then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 4) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 4) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(5)'event and vco_out(5) = '0') then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 5) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 5) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(6)'event and vco_out(6) = '0') then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 6) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 6) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(7)'event and vco_out(7) = '0') then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 7) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 7) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
|
|
|
|
if (vco_out(0)'event) then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 0) then
|
|
inclk_c_from_vco(i) <= vco_out(0);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 0) then
|
|
inclk_m_from_vco <= vco_out(0);
|
|
end if;
|
|
end if;
|
|
if (vco_out(1)'event) then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 1) then
|
|
inclk_c_from_vco(i) <= vco_out(1);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 1) then
|
|
inclk_m_from_vco <= vco_out(1);
|
|
end if;
|
|
end if;
|
|
if (vco_out(2)'event) then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 2) then
|
|
inclk_c_from_vco(i) <= vco_out(2);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 2) then
|
|
inclk_m_from_vco <= vco_out(2);
|
|
end if;
|
|
end if;
|
|
if (vco_out(3)'event) then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 3) then
|
|
inclk_c_from_vco(i) <= vco_out(3);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 3) then
|
|
inclk_m_from_vco <= vco_out(3);
|
|
end if;
|
|
end if;
|
|
if (vco_out(4)'event) then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 4) then
|
|
inclk_c_from_vco(i) <= vco_out(4);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 4) then
|
|
inclk_m_from_vco <= vco_out(4);
|
|
end if;
|
|
end if;
|
|
if (vco_out(5)'event) then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 5) then
|
|
inclk_c_from_vco(i) <= vco_out(5);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 5) then
|
|
inclk_m_from_vco <= vco_out(5);
|
|
end if;
|
|
end if;
|
|
if (vco_out(6)'event) then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 6) then
|
|
inclk_c_from_vco(i) <= vco_out(6);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 6) then
|
|
inclk_m_from_vco <= vco_out(6);
|
|
end if;
|
|
end if;
|
|
if (vco_out(7)'event) then
|
|
for i in 0 to 9 loop
|
|
if (c_ph_val(i) = 7) then
|
|
inclk_c_from_vco(i) <= vco_out(7);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 7) then
|
|
inclk_m_from_vco <= vco_out(7);
|
|
end if;
|
|
end if;
|
|
|
|
|
|
|
|
|
|
if (scanclk_ipd'event AND scanclk_ipd = '0' AND now > 0 ps) then
|
|
scanclkena_reg <= scanclkena_ipd;
|
|
if (scanclkena_reg = '1') then
|
|
scandata_in <= scandata_ipd;
|
|
scandata_out <= scandataout_tmp;
|
|
end if;
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1' and now > 0 ps) then
|
|
if (got_first_scanclk) then
|
|
scanclk_period <= now - scanclk_last_rising_edge;
|
|
else
|
|
got_first_scanclk := true;
|
|
end if;
|
|
if (scanclkena_reg = '1') then
|
|
for j in scan_chain_length - 1 downto 1 loop
|
|
scan_data(j) <= scan_data(j-1);
|
|
end loop;
|
|
scan_data(0) <= scandata_in;
|
|
end if;
|
|
scanclk_last_rising_edge := now;
|
|
end if;
|
|
end process;
|
|
|
|
-- PLL Phase Reconfiguration
|
|
|
|
PROCESS(scanclk_ipd, areset_ipd,phasestep_ipd)
|
|
VARIABLE i : INTEGER := 0;
|
|
VARIABLE c_ph : INTEGER := 0;
|
|
VARIABLE m_ph : INTEGER := 0;
|
|
VARIABLE select_counter : INTEGER := 0;
|
|
BEGIN
|
|
IF (NOW = 0 ps) THEN
|
|
m_ph_val_tmp <= m_ph_initial;
|
|
END IF;
|
|
|
|
-- Latch phase enable (same as phasestep) on neg edge of scan clock
|
|
IF (scanclk_ipd'EVENT AND scanclk_ipd = '0') THEN
|
|
phasestep_reg <= phasestep_ipd;
|
|
END IF;
|
|
|
|
IF (phasestep_ipd'EVENT and phasestep_ipd = '1') THEN
|
|
IF (update_phase = '0') THEN
|
|
phasestep_high_count <= 0; -- phase adjustments must be 1 cycle apart
|
|
-- if not, next phasestep cycle is skipped
|
|
END IF;
|
|
END IF;
|
|
-- revert counter phase tap values to POF programmed values
|
|
-- if PLL is reset
|
|
|
|
IF (areset_ipd'EVENT AND areset_ipd = '1') then
|
|
c_ph_val_tmp <= c_ph_val_orig;
|
|
m_ph_val_tmp <= m_ph_initial;
|
|
END IF;
|
|
|
|
IF (scanclk_ipd'EVENT AND scanclk_ipd = '1') THEN
|
|
IF (phasestep_reg = '1') THEN
|
|
IF (phasestep_high_count = 1) THEN
|
|
phasecounterselect_reg <= phasecounterselect_ipd;
|
|
phaseupdown_reg <= phaseupdown_ipd;
|
|
-- start reconfiguration
|
|
IF (phasecounterselect_ipd < "1100") THEN -- no counters selected
|
|
IF (phasecounterselect_ipd = "0000") THEN
|
|
i := 0;
|
|
WHILE (i < num_output_cntrs) LOOP
|
|
c_ph := c_ph_val(i);
|
|
IF (phaseupdown_ipd = '1') THEN
|
|
c_ph := (c_ph + 1) mod num_phase_taps;
|
|
ELSIF (c_ph = 0) THEN
|
|
c_ph := num_phase_taps - 1;
|
|
ELSE
|
|
c_ph := (c_ph - 1) mod num_phase_taps;
|
|
END IF;
|
|
c_ph_val_tmp(i) <= c_ph;
|
|
i := i + 1;
|
|
END LOOP;
|
|
ELSIF (phasecounterselect_ipd = "0001") THEN
|
|
m_ph := m_ph_val;
|
|
IF (phaseupdown_ipd = '1') THEN
|
|
m_ph := (m_ph + 1) mod num_phase_taps;
|
|
ELSIF (m_ph = 0) THEN
|
|
m_ph := num_phase_taps - 1;
|
|
ELSE
|
|
m_ph := (m_ph - 1) mod num_phase_taps;
|
|
END IF;
|
|
m_ph_val_tmp <= m_ph;
|
|
ELSE
|
|
select_counter := alt_conv_integer(phasecounterselect_ipd) - 2;
|
|
c_ph := c_ph_val(select_counter);
|
|
IF (phaseupdown_ipd = '1') THEN
|
|
c_ph := (c_ph + 1) mod num_phase_taps;
|
|
ELSIF (c_ph = 0) THEN
|
|
c_ph := num_phase_taps - 1;
|
|
ELSE
|
|
c_ph := (c_ph - 1) mod num_phase_taps;
|
|
END IF;
|
|
c_ph_val_tmp(select_counter) <= c_ph;
|
|
END IF;
|
|
update_phase <= '1','0' AFTER (0.5 * scanclk_period);
|
|
END IF;
|
|
END IF;
|
|
phasestep_high_count <= phasestep_high_count + 1;
|
|
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
scandataout_tmp <= scan_data(FAST_SCAN_CHAIN-2) when (pll_type = "fast" or pll_type = "lvds" or pll_type = "left_right") else scan_data(GPP_SCAN_CHAIN-2);
|
|
|
|
process (schedule_vco, areset_ipd, pfdena_ipd, refclk, fbclk)
|
|
variable sched_time : time := 0 ps;
|
|
|
|
TYPE time_array is ARRAY (0 to 7) of time;
|
|
variable init : boolean := true;
|
|
variable refclk_period : time;
|
|
variable m_times_vco_period : time;
|
|
variable new_m_times_vco_period : time;
|
|
|
|
variable phase_shift : time_array := (OTHERS => 0 ps);
|
|
variable last_phase_shift : time_array := (OTHERS => 0 ps);
|
|
|
|
variable l_index : integer := 1;
|
|
variable cycle_to_adjust : integer := 0;
|
|
|
|
variable stop_vco : boolean := false;
|
|
|
|
variable locked_tmp : std_logic := '0';
|
|
variable pll_is_locked : boolean := false;
|
|
variable cycles_pfd_low : integer := 0;
|
|
variable cycles_pfd_high : integer := 0;
|
|
variable cycles_to_lock : integer := 0;
|
|
variable cycles_to_unlock : integer := 0;
|
|
|
|
variable got_first_refclk : boolean := false;
|
|
variable got_second_refclk : boolean := false;
|
|
variable got_first_fbclk : boolean := false;
|
|
|
|
variable refclk_time : time := 0 ps;
|
|
variable fbclk_time : time := 0 ps;
|
|
variable first_fbclk_time : time := 0 ps;
|
|
|
|
variable fbclk_period : time := 0 ps;
|
|
|
|
variable first_schedule : boolean := true;
|
|
|
|
variable vco_val : std_logic := '0';
|
|
variable vco_period_was_phase_adjusted : boolean := false;
|
|
variable phase_adjust_was_scheduled : boolean := false;
|
|
|
|
variable loop_xplier : integer;
|
|
variable loop_initial : integer := 0;
|
|
variable loop_ph : integer := 0;
|
|
variable loop_time_delay : integer := 0;
|
|
|
|
variable initial_delay : time := 0 ps;
|
|
variable vco_per : time;
|
|
variable tmp_rem : integer;
|
|
variable my_rem : integer;
|
|
variable fbk_phase : integer := 0;
|
|
|
|
variable pull_back_M : integer := 0;
|
|
variable total_pull_back : integer := 0;
|
|
variable fbk_delay : integer := 0;
|
|
|
|
variable offset : time := 0 ps;
|
|
|
|
variable tmp_vco_per : integer := 0;
|
|
variable high_time : time;
|
|
variable low_time : time;
|
|
|
|
variable got_refclk_posedge : boolean := false;
|
|
variable got_fbclk_posedge : boolean := false;
|
|
variable inclk_out_of_range : boolean := false;
|
|
variable no_warn : boolean := false;
|
|
|
|
variable ext_fbk_cntr_modulus : integer := 1;
|
|
variable init_clks : boolean := true;
|
|
variable pll_is_in_reset : boolean := false;
|
|
variable buf : line;
|
|
begin
|
|
if (init) then
|
|
|
|
-- jump-start the VCO
|
|
-- add 1 ps delay to ensure all signals are updated to initial
|
|
-- values
|
|
schedule_vco <= transport not schedule_vco after 1 ps;
|
|
|
|
init := false;
|
|
end if;
|
|
|
|
if (schedule_vco'event) then
|
|
if (init_clks) then
|
|
refclk_period := inclk0_input_frequency * n_val * 1 ps;
|
|
|
|
m_times_vco_period := refclk_period;
|
|
new_m_times_vco_period := refclk_period;
|
|
init_clks := false;
|
|
end if;
|
|
sched_time := 0 ps;
|
|
for i in 0 to 7 loop
|
|
last_phase_shift(i) := phase_shift(i);
|
|
end loop;
|
|
cycle_to_adjust := 0;
|
|
l_index := 1;
|
|
m_times_vco_period := new_m_times_vco_period;
|
|
end if;
|
|
|
|
-- areset was asserted
|
|
if (areset_ipd'event and areset_ipd = '1') then
|
|
assert false report family_name & " PLL was reset" severity note;
|
|
-- reset lock parameters
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
end if;
|
|
|
|
if (areset_ipd = '1') then
|
|
pll_is_in_reset := true;
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
|
|
-- drop VCO taps to 0
|
|
for i in 0 to 7 loop
|
|
vco_out(i) <= transport '0' after 1 ps;
|
|
end loop;
|
|
end if;
|
|
|
|
|
|
if (schedule_vco'event and (areset_ipd = '1' or stop_vco)) then
|
|
|
|
-- drop VCO taps to 0
|
|
for i in 0 to 7 loop
|
|
vco_out(i) <= transport '0' after last_phase_shift(i);
|
|
phase_shift(i) := 0 ps;
|
|
last_phase_shift(i) := 0 ps;
|
|
end loop;
|
|
|
|
-- reset lock parameters
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
refclk_time := 0 ps;
|
|
got_first_fbclk := false;
|
|
fbclk_time := 0 ps;
|
|
first_fbclk_time := 0 ps;
|
|
fbclk_period := 0 ps;
|
|
|
|
first_schedule := true;
|
|
vco_val := '0';
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
|
|
elsif ((schedule_vco'event or areset_ipd'event) and areset_ipd = '0' and (not stop_vco) and now > 0 ps) then
|
|
|
|
-- note areset deassert time
|
|
-- note it as refclk_time to prevent false triggering
|
|
-- of stop_vco after areset
|
|
if (areset_ipd'event and areset_ipd = '0' and pll_is_in_reset) then
|
|
refclk_time := now;
|
|
locked_tmp := '0';
|
|
end if;
|
|
|
|
pll_is_in_reset := false;
|
|
-- calculate loop_xplier : this will be different from m_val
|
|
-- in external_feedback_mode
|
|
loop_xplier := m_val;
|
|
loop_initial := m_initial_val - 1;
|
|
loop_ph := m_ph_val;
|
|
|
|
|
|
-- convert initial value to delay
|
|
initial_delay := (loop_initial * m_times_vco_period)/loop_xplier;
|
|
|
|
-- convert loop ph_tap to delay
|
|
my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
|
|
tmp_vco_per := (m_times_vco_period/1 ps) / loop_xplier;
|
|
if (my_rem /= 0) then
|
|
tmp_vco_per := tmp_vco_per + 1;
|
|
end if;
|
|
fbk_phase := (loop_ph * tmp_vco_per)/8;
|
|
|
|
pull_back_M := initial_delay/1 ps + fbk_phase;
|
|
|
|
total_pull_back := pull_back_M;
|
|
|
|
if (simulation_type = "timing") then
|
|
total_pull_back := total_pull_back + pll_compensation_delay;
|
|
end if;
|
|
while (total_pull_back > refclk_period/1 ps) loop
|
|
total_pull_back := total_pull_back - refclk_period/1 ps;
|
|
end loop;
|
|
|
|
if (total_pull_back > 0) then
|
|
offset := refclk_period - (total_pull_back * 1 ps);
|
|
end if;
|
|
|
|
fbk_delay := total_pull_back - fbk_phase;
|
|
if (fbk_delay < 0) then
|
|
offset := offset - (fbk_phase * 1 ps);
|
|
fbk_delay := total_pull_back;
|
|
end if;
|
|
|
|
-- assign m_delay
|
|
m_delay <= transport fbk_delay after 1 ps;
|
|
|
|
my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
|
|
for i in 1 to loop_xplier loop
|
|
-- adjust cycles
|
|
tmp_vco_per := (m_times_vco_period/1 ps)/loop_xplier;
|
|
if (my_rem /= 0 and l_index <= my_rem) then
|
|
tmp_rem := (loop_xplier * l_index) rem my_rem;
|
|
cycle_to_adjust := (loop_xplier * l_index) / my_rem;
|
|
if (tmp_rem /= 0) then
|
|
cycle_to_adjust := cycle_to_adjust + 1;
|
|
end if;
|
|
end if;
|
|
if (cycle_to_adjust = i) then
|
|
tmp_vco_per := tmp_vco_per + 1;
|
|
l_index := l_index + 1;
|
|
end if;
|
|
|
|
-- calculate high and low periods
|
|
vco_per := tmp_vco_per * 1 ps;
|
|
high_time := (tmp_vco_per/2) * 1 ps;
|
|
if (tmp_vco_per rem 2 /= 0) then
|
|
high_time := high_time + 1 ps;
|
|
end if;
|
|
low_time := vco_per - high_time;
|
|
|
|
-- schedule the rising and falling edges
|
|
for j in 1 to 2 loop
|
|
vco_val := not vco_val;
|
|
if (vco_val = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (vco_val = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
|
|
-- schedule the phase taps
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
if (first_schedule) then
|
|
vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
|
|
else
|
|
vco_out(k) <= transport vco_val after (sched_time + last_phase_shift(k));
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
end loop;
|
|
|
|
-- schedule once more
|
|
if (first_schedule) then
|
|
vco_val := not vco_val;
|
|
if (vco_val = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (vco_val = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
-- schedule the phase taps
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
|
|
end loop;
|
|
first_schedule := false;
|
|
end if;
|
|
|
|
schedule_vco <= transport not schedule_vco after sched_time;
|
|
|
|
if (vco_period_was_phase_adjusted) then
|
|
m_times_vco_period := refclk_period;
|
|
new_m_times_vco_period := refclk_period;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := true;
|
|
|
|
vco_per := m_times_vco_period/loop_xplier;
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
-- Bypass lock detect
|
|
|
|
if (refclk'event and refclk = '1' and areset_ipd = '0') then
|
|
if (test_bypass_lock_detect = "on") then
|
|
if (pfdena_ipd = '1') then
|
|
cycles_pfd_low := 0;
|
|
if (pfd_locked = '0') then
|
|
if (cycles_pfd_high = lock_high) then
|
|
assert false report family_name & " PLL locked in test mode on PFD enable assertion." severity warning;
|
|
pfd_locked <= '1';
|
|
end if;
|
|
cycles_pfd_high := cycles_pfd_high + 1;
|
|
end if;
|
|
end if;
|
|
|
|
if (pfdena_ipd = '0') then
|
|
cycles_pfd_high := 0;
|
|
if (pfd_locked = '1') then
|
|
if (cycles_pfd_low = lock_low) then
|
|
assert false report family_name & " PLL lost lock in test mode on PFD enable de-assertion." severity warning;
|
|
pfd_locked <= '0';
|
|
end if;
|
|
cycles_pfd_low := cycles_pfd_low + 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
|
|
if (refclk'event and refclk = '1' and areset_ipd = '0') then
|
|
got_refclk_posedge := true;
|
|
if (not got_first_refclk) then
|
|
got_first_refclk := true;
|
|
else
|
|
got_second_refclk := true;
|
|
refclk_period := now - refclk_time;
|
|
|
|
-- check if incoming freq. will cause VCO range to be
|
|
-- exceeded
|
|
if ( (i_vco_max /= 0 and i_vco_min /= 0 and pfdena_ipd = '1') and
|
|
(((refclk_period/1 ps)/loop_xplier > i_vco_max) or
|
|
((refclk_period/1 ps)/loop_xplier < i_vco_min)) ) then
|
|
if (pll_is_locked) then
|
|
if ((refclk_period/1 ps)/loop_xplier > i_vco_max) then
|
|
assert false report "Input clock freq. is over VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_over <= '1';
|
|
end if;
|
|
if ((refclk_period/1 ps)/loop_xplier < i_vco_min) then
|
|
assert false report "Input clock freq. is under VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_under <= '1';
|
|
end if;
|
|
if (inclk_out_of_range) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
cycles_to_lock := 0;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
assert false report family_name & " PLL lost lock." severity note;
|
|
end if;
|
|
elsif (not no_warn) then
|
|
if ((refclk_period/1 ps)/loop_xplier > i_vco_max) then
|
|
assert false report "Input clock freq. is over VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_over <= '1';
|
|
end if;
|
|
if ((refclk_period/1 ps)/loop_xplier < i_vco_min) then
|
|
assert false report "Input clock freq. is under VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_under <= '1';
|
|
end if;
|
|
assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may not lock. Please use the correct frequency." severity warning;
|
|
no_warn := true;
|
|
end if;
|
|
inclk_out_of_range := true;
|
|
else
|
|
vco_over <= '0';
|
|
vco_under <= '0';
|
|
inclk_out_of_range := false;
|
|
no_warn := false;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (stop_vco) then
|
|
stop_vco := false;
|
|
schedule_vco <= not schedule_vco;
|
|
end if;
|
|
|
|
refclk_time := now;
|
|
else
|
|
got_refclk_posedge := false;
|
|
end if;
|
|
|
|
-- Update M counter value on feedback clock edge
|
|
|
|
if (fbclk'event and fbclk = '1') then
|
|
got_fbclk_posedge := true;
|
|
if (not got_first_fbclk) then
|
|
got_first_fbclk := true;
|
|
else
|
|
fbclk_period := now - fbclk_time;
|
|
end if;
|
|
|
|
-- need refclk_period here, so initialized to proper value above
|
|
if ( ( (now - refclk_time > 1.5 * refclk_period) and pfdena_ipd = '1' and pll_is_locked) or
|
|
( (now - refclk_time > 5 * refclk_period) and pfdena_ipd = '1' and pll_has_just_been_reconfigured = false) or
|
|
( (now - refclk_time > 50 * refclk_period) and pfdena_ipd = '1' and pll_has_just_been_reconfigured = true) ) then
|
|
stop_vco := true;
|
|
-- reset
|
|
got_first_refclk := false;
|
|
got_first_fbclk := false;
|
|
got_second_refclk := false;
|
|
if (pll_is_locked) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
assert false report family_name & " PLL lost lock due to loss of input clock or the input clock is not detected within the allowed time frame." severity note;
|
|
if ((i_vco_max = 0) and (i_vco_min = 0)) then
|
|
assert false report "Please run timing simulation to check whether the input clock is operating within the supported VCO range or not." severity note;
|
|
end if;
|
|
end if;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
first_schedule := true;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
end if;
|
|
fbclk_time := now;
|
|
else
|
|
got_fbclk_posedge := false;
|
|
end if;
|
|
|
|
if ((got_refclk_posedge or got_fbclk_posedge) and got_second_refclk and pfdena_ipd = '1' and (not inclk_out_of_range)) then
|
|
|
|
-- now we know actual incoming period
|
|
if ( abs(fbclk_time - refclk_time) <= 5 ps or
|
|
(got_first_fbclk and abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
|
|
-- considered in phase
|
|
if (cycles_to_lock = real_lock_high) then
|
|
if (not pll_is_locked) then
|
|
assert false report family_name & " PLL locked to incoming clock" severity note;
|
|
end if;
|
|
pll_is_locked := true;
|
|
locked_tmp := '1';
|
|
cycles_to_unlock := 0;
|
|
end if;
|
|
-- increment lock counter only if second part of above
|
|
-- time check is NOT true
|
|
if (not(abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window)) then
|
|
cycles_to_lock := cycles_to_lock + 1;
|
|
end if;
|
|
|
|
-- adjust m_times_vco_period
|
|
new_m_times_vco_period := refclk_period;
|
|
else
|
|
-- if locked, begin unlock
|
|
if (pll_is_locked) then
|
|
cycles_to_unlock := cycles_to_unlock + 1;
|
|
if (cycles_to_unlock = lock_low) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
cycles_to_lock := 0;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
assert false report family_name & " PLL lost lock." severity note;
|
|
got_first_refclk := false;
|
|
got_first_fbclk := false;
|
|
got_second_refclk := false;
|
|
end if;
|
|
end if;
|
|
if ( abs(refclk_period - fbclk_period) <= 2 ps ) then
|
|
-- frequency is still good
|
|
if (now = fbclk_time and (not phase_adjust_was_scheduled)) then
|
|
if ( abs(fbclk_time - refclk_time) > refclk_period/2) then
|
|
new_m_times_vco_period := m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time));
|
|
vco_period_was_phase_adjusted := true;
|
|
else
|
|
new_m_times_vco_period := m_times_vco_period - abs(fbclk_time - refclk_time);
|
|
vco_period_was_phase_adjusted := true;
|
|
end if;
|
|
|
|
end if;
|
|
else
|
|
phase_adjust_was_scheduled := false;
|
|
new_m_times_vco_period := refclk_period;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (pfdena_ipd = '0') then
|
|
if (pll_is_locked) then
|
|
locked_tmp := 'X';
|
|
end if;
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
end if;
|
|
|
|
-- give message only at time of deassertion
|
|
if (pfdena_ipd'event and pfdena_ipd = '0') then
|
|
assert false report "PFDENA deasserted." severity note;
|
|
elsif (pfdena_ipd'event and pfdena_ipd = '1') then
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
refclk_time := now;
|
|
end if;
|
|
|
|
if (reconfig_err) then
|
|
lock <= '0';
|
|
else
|
|
lock <= locked_tmp;
|
|
end if;
|
|
|
|
-- signal to calculate quiet_time
|
|
sig_refclk_period <= refclk_period;
|
|
|
|
if (stop_vco = true) then
|
|
sig_stop_vco <= '1';
|
|
else
|
|
sig_stop_vco <= '0';
|
|
end if;
|
|
|
|
pll_locked <= pll_is_locked;
|
|
end process;
|
|
|
|
clk0_tmp <= c_clk(i_clk0_counter);
|
|
clk_pfd(0) <= clk0_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(0) <= clk_pfd(0) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk0_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else
|
|
'X';
|
|
|
|
clk1_tmp <= c_clk(i_clk1_counter);
|
|
clk_pfd(1) <= clk1_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(1) <= clk_pfd(1) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk1_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
clk2_tmp <= c_clk(i_clk2_counter);
|
|
clk_pfd(2) <= clk2_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(2) <= clk_pfd(2) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk2_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
clk3_tmp <= c_clk(i_clk3_counter);
|
|
clk_pfd(3) <= clk3_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(3) <= clk_pfd(3) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk3_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
clk4_tmp <= c_clk(i_clk4_counter);
|
|
clk_pfd(4) <= clk4_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(4) <= clk_pfd(4) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk4_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
clk5_tmp <= c_clk(i_clk5_counter);
|
|
clk_pfd(5) <= clk5_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(5) <= clk_pfd(5) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk5_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
|
|
clk6_tmp <= c_clk(i_clk6_counter);
|
|
clk_pfd(6) <= clk6_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(6) <= clk_pfd(6) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk6_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
|
|
clk7_tmp <= c_clk(i_clk7_counter);
|
|
clk_pfd(7) <= clk7_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(7) <= clk_pfd(7) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk7_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
|
|
clk8_tmp <= c_clk(i_clk8_counter);
|
|
clk_pfd(8) <= clk8_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(8) <= clk_pfd(8) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk8_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
|
|
clk9_tmp <= c_clk(i_clk9_counter);
|
|
clk_pfd(9) <= clk9_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(9) <= clk_pfd(9) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk9_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
|
|
|
|
scandataout <= scandata_out;
|
|
scandone <= NOT scandone_tmp;
|
|
phasedone <= NOT update_phase;
|
|
vcooverrange <= 'Z' WHEN (vco_range_detector_high_bits = -1) ELSE vco_over;
|
|
vcounderrange <= 'Z' WHEN (vco_range_detector_low_bits = -1) ELSE vco_under;
|
|
fbout <= fbclk;
|
|
end vital_pll;
|
|
-- END ARCHITECTURE VITAL_PLL
|
|
|
|
-- cycloneiii_msg
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_cda_mn_cntr
|
|
--
|
|
-- Description : Simulation model for the M and N counter. This is a
|
|
-- common model for the input counter and the loop feedback
|
|
-- counter of the CycloneIII PLL.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
USE IEEE.std_logic_arith.all;
|
|
USE IEEE.std_logic_unsigned.all;
|
|
|
|
ENTITY MF_cda_mn_cntr is
|
|
PORT( clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer := 1;
|
|
time_delay : IN integer := 0
|
|
);
|
|
END MF_cda_mn_cntr;
|
|
|
|
ARCHITECTURE behave of MF_cda_mn_cntr is
|
|
begin
|
|
|
|
process (clk, reset)
|
|
variable count : integer := 1;
|
|
variable first_rising_edge : boolean := true;
|
|
variable tmp_cout : std_logic;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := true;
|
|
elsif (clk'event) then
|
|
if (clk = '1' and first_rising_edge) then
|
|
first_rising_edge := false;
|
|
tmp_cout := clk;
|
|
elsif (not first_rising_edge) then
|
|
if (count < modulus) then
|
|
count := count + 1;
|
|
else
|
|
count := 1;
|
|
tmp_cout := not tmp_cout;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout after time_delay * 1 ps;
|
|
end process;
|
|
end behave;
|
|
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_cda_scale_cntr
|
|
--
|
|
-- Description : Simulation model for the output scale-down counters.
|
|
-- This is a common model for the C0, C1, C2, C3, C4 and C5
|
|
-- output counters of the StratixII PLL.
|
|
--
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
|
|
ENTITY MF_cda_scale_cntr is
|
|
PORT( clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
initial : IN integer := 1;
|
|
high : IN integer := 1;
|
|
low : IN integer := 1;
|
|
mode : IN string := "bypass";
|
|
ph_tap : IN integer := 0;
|
|
cout : OUT std_logic
|
|
);
|
|
END MF_cda_scale_cntr;
|
|
|
|
ARCHITECTURE behave of MF_cda_scale_cntr is
|
|
begin
|
|
process (clk, reset)
|
|
variable tmp_cout : std_logic := '0';
|
|
variable count : integer := 1;
|
|
variable output_shift_count : integer := 1;
|
|
variable first_rising_edge : boolean := false;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
output_shift_count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := false;
|
|
elsif (clk'event) then
|
|
if (mode = " off") then
|
|
tmp_cout := '0';
|
|
elsif (mode = "bypass") then
|
|
tmp_cout := clk;
|
|
first_rising_edge := true;
|
|
elsif (not first_rising_edge) then
|
|
if (clk = '1') then
|
|
if (output_shift_count = initial) then
|
|
tmp_cout := clk;
|
|
first_rising_edge := true;
|
|
else
|
|
output_shift_count := output_shift_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (output_shift_count < initial) then
|
|
if (clk = '1') then
|
|
output_shift_count := output_shift_count + 1;
|
|
end if;
|
|
else
|
|
count := count + 1;
|
|
if (mode = " even" and (count = (high*2) + 1)) then
|
|
tmp_cout := '0';
|
|
elsif (mode = " odd" and (count = high*2)) then
|
|
tmp_cout := '0';
|
|
elsif (count = (high + low)*2 + 1) then
|
|
tmp_cout := '1';
|
|
count := 1; -- reset count
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout;
|
|
end process;
|
|
|
|
end behave;
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_cycloneiii_pll
|
|
--
|
|
-- Description : Simulation model for the StratixII PLL.
|
|
-- In the functional mode, it is also the model for the altpll
|
|
-- megafunction.
|
|
--
|
|
-- Limitations : Does not support Spread Spectrum and Bandwidth.
|
|
--
|
|
-- Outputs : Up to 10 output clocks, each defined by its own set of
|
|
-- parameters. Locked output (active high) indicates when the
|
|
-- PLL locks. clkbad and activeclock are used for
|
|
-- clock switchover to indicate which input clock has gone
|
|
-- bad, when the clock switchover initiates and which input
|
|
-- clock is being used as the reference, respectively.
|
|
-- scandataout is the data output of the serial scan chain.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
LIBRARY IEEE, std;
|
|
USE IEEE.std_logic_1164.all;
|
|
USE STD.TEXTIO.all;
|
|
USE work.MF_pllpack.all;
|
|
USE work.MF_cda_mn_cntr;
|
|
USE work.MF_cda_scale_cntr;
|
|
USE work.dffp;
|
|
USE work.MF_pll_reg;
|
|
|
|
-- New Features : The list below outlines key new features in TITAN:
|
|
-- 1. Dynamic Phase Reconfiguration
|
|
-- 2. Dynamic PLL Reconfiguration (different protocol)
|
|
-- 3. More output counters
|
|
|
|
ENTITY MF_cycloneiii_pll is
|
|
GENERIC (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "auto"; -- AUTO/FAST/ENHANCED/LEFT_RIGHT/TOP_BOTTOM
|
|
compensate_clock : string := "clock0";
|
|
|
|
inclk0_input_frequency : integer := 0;
|
|
inclk1_input_frequency : integer := 0;
|
|
|
|
self_reset_on_loss_lock : string := "off";
|
|
switch_over_type : string := "auto";
|
|
switch_over_counter : integer := 1;
|
|
enable_switch_over_counter : string := "off";
|
|
|
|
|
|
bandwidth : integer := 0;
|
|
bandwidth_type : string := "auto";
|
|
use_dc_coupling : string := "false";
|
|
|
|
|
|
|
|
lock_c : integer := 4;
|
|
sim_gate_lock_device_behavior : string := "off";
|
|
lock_high : integer := 0;
|
|
lock_low : integer := 0;
|
|
lock_window_ui : string := "0.05";
|
|
lock_window : time := 5 ps;
|
|
test_bypass_lock_detect : string := "off";
|
|
|
|
|
|
clk0_output_frequency : integer := 0;
|
|
clk0_multiply_by : integer := 0;
|
|
clk0_divide_by : integer := 0;
|
|
clk0_phase_shift : string := "0";
|
|
clk0_duty_cycle : integer := 50;
|
|
|
|
clk1_output_frequency : integer := 0;
|
|
clk1_multiply_by : integer := 0;
|
|
clk1_divide_by : integer := 0;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_duty_cycle : integer := 50;
|
|
|
|
clk2_output_frequency : integer := 0;
|
|
clk2_multiply_by : integer := 0;
|
|
clk2_divide_by : integer := 0;
|
|
clk2_phase_shift : string := "0";
|
|
clk2_duty_cycle : integer := 50;
|
|
|
|
clk3_output_frequency : integer := 0;
|
|
clk3_multiply_by : integer := 0;
|
|
clk3_divide_by : integer := 0;
|
|
clk3_phase_shift : string := "0";
|
|
clk3_duty_cycle : integer := 50;
|
|
|
|
clk4_output_frequency : integer := 0;
|
|
clk4_multiply_by : integer := 0;
|
|
clk4_divide_by : integer := 0;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pfd_min : integer := 0;
|
|
pfd_max : integer := 0;
|
|
vco_min : integer := 0;
|
|
vco_max : integer := 0;
|
|
vco_center : integer := 0;
|
|
|
|
-- ADVANCED USER PARAMETERS
|
|
m_initial : integer := 1;
|
|
m : integer := 0;
|
|
n : integer := 1;
|
|
|
|
c0_high : integer := 1;
|
|
c0_low : integer := 1;
|
|
c0_initial : integer := 1;
|
|
c0_mode : string := "bypass";
|
|
c0_ph : integer := 0;
|
|
|
|
c1_high : integer := 1;
|
|
c1_low : integer := 1;
|
|
c1_initial : integer := 1;
|
|
c1_mode : string := "bypass";
|
|
c1_ph : integer := 0;
|
|
|
|
c2_high : integer := 1;
|
|
c2_low : integer := 1;
|
|
c2_initial : integer := 1;
|
|
c2_mode : string := "bypass";
|
|
c2_ph : integer := 0;
|
|
|
|
c3_high : integer := 1;
|
|
c3_low : integer := 1;
|
|
c3_initial : integer := 1;
|
|
c3_mode : string := "bypass";
|
|
c3_ph : integer := 0;
|
|
|
|
c4_high : integer := 1;
|
|
c4_low : integer := 1;
|
|
c4_initial : integer := 1;
|
|
c4_mode : string := "bypass";
|
|
c4_ph : integer := 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_ph : integer := 0;
|
|
|
|
clk0_counter : string := "unused";
|
|
clk1_counter : string := "unused";
|
|
clk2_counter : string := "unused";
|
|
clk3_counter : string := "unused";
|
|
clk4_counter : string := "unused";
|
|
|
|
c1_use_casc_in : string := "off";
|
|
c2_use_casc_in : string := "off";
|
|
c3_use_casc_in : string := "off";
|
|
c4_use_casc_in : string := "off";
|
|
|
|
m_test_source : integer := -1;
|
|
c0_test_source : integer := -1;
|
|
c1_test_source : integer := -1;
|
|
c2_test_source : integer := -1;
|
|
c3_test_source : integer := -1;
|
|
c4_test_source : integer := -1;
|
|
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
vco_post_scale : integer := 1;
|
|
vco_frequency_control : string := "auto";
|
|
vco_phase_shift_step : integer := 0;
|
|
|
|
charge_pump_current : integer := 10;
|
|
loop_filter_r : string := " 1.0";
|
|
loop_filter_c : integer := 0;
|
|
|
|
|
|
pll_compensation_delay : integer := 0;
|
|
simulation_type : string := "functional";
|
|
|
|
clk0_use_even_counter_mode : string := "off";
|
|
clk1_use_even_counter_mode : string := "off";
|
|
clk2_use_even_counter_mode : string := "off";
|
|
clk3_use_even_counter_mode : string := "off";
|
|
clk4_use_even_counter_mode : string := "off";
|
|
|
|
clk0_use_even_counter_value : string := "off";
|
|
clk1_use_even_counter_value : string := "off";
|
|
clk2_use_even_counter_value : string := "off";
|
|
clk3_use_even_counter_value : string := "off";
|
|
clk4_use_even_counter_value : string := "off";
|
|
|
|
-- Test only
|
|
init_block_reset_a_count : integer := 1;
|
|
init_block_reset_b_count : integer := 1;
|
|
charge_pump_current_bits : integer := 0;
|
|
lock_window_ui_bits : integer := 0;
|
|
loop_filter_c_bits : integer := 0;
|
|
loop_filter_r_bits : integer := 0;
|
|
test_counter_c0_delay_chain_bits : integer := 0;
|
|
test_counter_c1_delay_chain_bits : integer := 0;
|
|
test_counter_c2_delay_chain_bits : integer := 0;
|
|
test_counter_c3_delay_chain_bits : integer := 0;
|
|
test_counter_c4_delay_chain_bits : integer := 0;
|
|
test_counter_c5_delay_chain_bits : integer := 0;
|
|
test_counter_m_delay_chain_bits : integer := 0;
|
|
test_counter_n_delay_chain_bits : integer := 0;
|
|
test_feedback_comp_delay_chain_bits : integer := 0;
|
|
test_input_comp_delay_chain_bits : integer := 0;
|
|
test_volt_reg_output_mode_bits : integer := 0;
|
|
test_volt_reg_output_voltage_bits : integer := 0;
|
|
test_volt_reg_test_mode : string := "false";
|
|
vco_range_detector_high_bits : integer := -1;
|
|
vco_range_detector_low_bits : integer := -1;
|
|
scan_chain_mif_file : string := "";
|
|
|
|
auto_settings : string := "true";
|
|
-- Simulation only generics
|
|
family_name : string := "StratixIII";
|
|
|
|
use_vco_bypass : string := "false"
|
|
);
|
|
|
|
PORT
|
|
(
|
|
inclk : in std_logic_vector(1 downto 0);
|
|
fbin : in std_logic := '0';
|
|
fbout : out std_logic;
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scandata : in std_logic := '0';
|
|
scanclk : in std_logic := '0';
|
|
scanclkena : in std_logic := '1';
|
|
configupdate : in std_logic := '0';
|
|
clk : out std_logic_vector(4 downto 0);
|
|
phasecounterselect : in std_logic_vector(2 downto 0) := "000";
|
|
phaseupdown : in std_logic := '0';
|
|
phasestep : in std_logic := '0';
|
|
clkbad : out std_logic_vector(1 downto 0);
|
|
activeclock : out std_logic;
|
|
locked : out std_logic;
|
|
scandataout : out std_logic;
|
|
scandone : out std_logic;
|
|
phasedone : out std_logic;
|
|
vcooverrange : out std_logic;
|
|
vcounderrange : out std_logic
|
|
|
|
);
|
|
END MF_cycloneiii_pll;
|
|
|
|
ARCHITECTURE vital_pll of MF_cycloneiii_pll is
|
|
|
|
function get_vco_min_no_division(i_vco_post_scale : INTEGER) return INTEGER is
|
|
begin
|
|
if (i_vco_post_scale = 1) then
|
|
return vco_min * 2;
|
|
else
|
|
return vco_min;
|
|
end if;
|
|
end;
|
|
|
|
function get_vco_max_no_division(i_vco_post_scale : INTEGER) return INTEGER is
|
|
begin
|
|
if (i_vco_post_scale = 1) then
|
|
return vco_max * 2;
|
|
else
|
|
return vco_max;
|
|
end if;
|
|
end;
|
|
|
|
TYPE int_array is ARRAY(NATURAL RANGE <>) of integer;
|
|
TYPE str_array is ARRAY(NATURAL RANGE <>) of string(1 to 6);
|
|
TYPE str_array1 is ARRAY(NATURAL RANGE <>) of string(1 to 9);
|
|
TYPE std_logic_array is ARRAY(NATURAL RANGE <>) of std_logic;
|
|
|
|
constant VCO_MIN_NO_DIVISION : integer := get_vco_min_no_division(vco_post_scale);
|
|
constant VCO_MAX_NO_DIVISION : integer := get_vco_max_no_division(vco_post_scale);
|
|
|
|
-- internal advanced parameter signals
|
|
signal i_vco_min : integer := vco_min;
|
|
signal i_vco_max : integer := vco_max;
|
|
signal i_vco_center : integer;
|
|
signal i_pfd_min : integer;
|
|
signal i_pfd_max : integer;
|
|
signal c_ph_val : int_array(0 to 4) := (OTHERS => 0);
|
|
signal c_ph_val_tmp : int_array(0 to 4) := (OTHERS => 0);
|
|
signal c_high_val : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_low_val : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_initial_val : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_mode_val : str_array(0 to 4);
|
|
signal clk_num : str_array(0 to 4);
|
|
|
|
-- old values
|
|
signal c_high_val_old : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_low_val_old : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_ph_val_old : int_array(0 to 4) := (OTHERS => 0);
|
|
signal c_mode_val_old : str_array(0 to 4);
|
|
-- hold registers
|
|
signal c_high_val_hold : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_low_val_hold : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_ph_val_hold : int_array(0 to 4) := (OTHERS => 0);
|
|
signal c_mode_val_hold : str_array(0 to 4);
|
|
|
|
-- temp registers
|
|
signal sig_c_ph_val_tmp : int_array(0 to 4) := (OTHERS => 0);
|
|
signal c_ph_val_orig : int_array(0 to 4) := (OTHERS => 0);
|
|
|
|
signal real_lock_high : integer := 0;
|
|
signal i_clk4_counter : integer := 4;
|
|
signal i_clk3_counter : integer := 3;
|
|
signal i_clk2_counter : integer := 2;
|
|
signal i_clk1_counter : integer := 1;
|
|
signal i_clk0_counter : integer := 0;
|
|
signal i_charge_pump_current : integer;
|
|
signal i_loop_filter_r : integer;
|
|
|
|
-- end internal advanced parameter signals
|
|
|
|
-- CONSTANTS
|
|
CONSTANT SCAN_CHAIN : integer := 144;
|
|
CONSTANT GPP_SCAN_CHAIN : integer := 234;
|
|
CONSTANT FAST_SCAN_CHAIN : integer := 180;
|
|
CONSTANT cntrs : str_array(4 downto 0) := (" C4", " C3", " C2", " C1", " C0");
|
|
CONSTANT ss_cntrs : str_array(0 to 3) := (" M", " M2", " N", " N2");
|
|
|
|
CONSTANT loop_filter_c_arr : int_array(0 to 3) := (0,0,0,0);
|
|
CONSTANT fpll_loop_filter_c_arr : int_array(0 to 3) := (0,0,0,0);
|
|
CONSTANT charge_pump_curr_arr : int_array(0 to 15) := (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
|
|
|
|
CONSTANT num_phase_taps : integer := 8;
|
|
-- signals
|
|
|
|
signal vcc : std_logic := '1';
|
|
|
|
signal fbclk : std_logic;
|
|
signal refclk : std_logic;
|
|
signal vco_over : std_logic := '0';
|
|
signal vco_under : std_logic := '1';
|
|
|
|
signal pll_locked : boolean := false;
|
|
|
|
|
|
signal c_clk : std_logic_array(0 to 4);
|
|
signal vco_out : std_logic_vector(7 downto 0) := (OTHERS => '0');
|
|
|
|
-- signals to assign values to counter params
|
|
signal m_val : integer := 1;
|
|
signal n_val : integer := 1;
|
|
signal m_ph_val : integer := 0;
|
|
signal m_ph_initial : integer := 0;
|
|
signal m_ph_val_tmp : integer := 0;
|
|
signal m_initial_val : integer := m_initial;
|
|
|
|
signal m_mode_val : string(1 to 6) := " ";
|
|
signal n_mode_val : string(1 to 6) := " ";
|
|
signal lfc_val : integer := 0;
|
|
signal vco_cur : integer := vco_post_scale;
|
|
signal cp_curr_val : integer := 0;
|
|
signal lfr_val : string(1 to 2) := " ";
|
|
|
|
signal cp_curr_old_bit_setting : integer := charge_pump_current_bits;
|
|
signal cp_curr_val_bit_setting : std_logic_vector(2 downto 0) := (OTHERS => '0');
|
|
signal lfr_old_bit_setting : integer := loop_filter_r_bits;
|
|
signal lfr_val_bit_setting : std_logic_vector(4 downto 0) := (OTHERS => '0');
|
|
signal lfc_old_bit_setting : integer := loop_filter_c_bits;
|
|
signal lfc_val_bit_setting : std_logic_vector(1 downto 0) := (OTHERS => '0');
|
|
|
|
signal pll_reconfig_display_full_setting : boolean := FALSE; -- display full setting, change to true
|
|
-- old values
|
|
signal m_val_old : integer := 1;
|
|
signal n_val_old : integer := 1;
|
|
signal m_mode_val_old : string(1 to 6) := " ";
|
|
signal n_mode_val_old : string(1 to 6) := " ";
|
|
signal m_ph_val_old : integer := 0;
|
|
signal lfc_old : integer := 0;
|
|
signal vco_old : integer := 0;
|
|
signal cp_curr_old : integer := 0;
|
|
signal lfr_old : string(1 to 2) := " ";
|
|
signal num_output_cntrs : integer := 5;
|
|
signal scanclk_period : time := 1 ps;
|
|
signal scan_data : std_logic_vector(0 to 143) := (OTHERS => '0');
|
|
|
|
|
|
signal clk_pfd : std_logic_vector(0 to 4);
|
|
signal clk0_tmp : std_logic;
|
|
signal clk1_tmp : std_logic;
|
|
signal clk2_tmp : std_logic;
|
|
signal clk3_tmp : std_logic;
|
|
signal clk4_tmp : std_logic;
|
|
|
|
signal update_conf_latches : std_logic := '0';
|
|
signal update_conf_latches_reg : std_logic := '0';
|
|
|
|
signal clkin : std_logic := '0';
|
|
signal gate_locked : std_logic := '0';
|
|
signal pfd_locked : std_logic := '0';
|
|
signal lock : std_logic := '0';
|
|
signal about_to_lock : boolean := false;
|
|
signal reconfig_err : boolean := false;
|
|
|
|
signal inclk_c0 : std_logic;
|
|
signal inclk_c1 : std_logic;
|
|
signal inclk_c2 : std_logic;
|
|
signal inclk_c3 : std_logic;
|
|
signal inclk_c4 : std_logic;
|
|
signal inclk_m : std_logic;
|
|
signal devpor : std_logic;
|
|
signal devclrn : std_logic;
|
|
|
|
signal inclk0_ipd : std_logic;
|
|
signal inclk1_ipd : std_logic;
|
|
signal pfdena_ipd : std_logic;
|
|
signal areset_ipd : std_logic;
|
|
signal fbin_ipd : std_logic;
|
|
signal scanclk_ipd : std_logic;
|
|
signal scanclkena_ipd, scanclkena_reg : std_logic;
|
|
signal scandata_ipd : std_logic;
|
|
signal clkswitch_ipd : std_logic;
|
|
signal phasecounterselect_ipd : std_logic_vector(2 downto 0);
|
|
signal phaseupdown_ipd : std_logic;
|
|
signal phasestep_ipd : std_logic;
|
|
signal configupdate_ipd : std_logic;
|
|
-- registered signals
|
|
|
|
signal sig_offset : time := 0 ps;
|
|
signal sig_refclk_time : time := 0 ps;
|
|
signal sig_fbclk_period : time := 0 ps;
|
|
signal sig_vco_period_was_phase_adjusted : boolean := false;
|
|
signal sig_phase_adjust_was_scheduled : boolean := false;
|
|
signal sig_stop_vco : std_logic := '0';
|
|
signal sig_m_times_vco_period : time := 0 ps;
|
|
signal sig_new_m_times_vco_period : time := 0 ps;
|
|
signal sig_got_refclk_posedge : boolean := false;
|
|
signal sig_got_fbclk_posedge : boolean := false;
|
|
signal sig_got_second_refclk : boolean := false;
|
|
|
|
signal m_delay : integer := 0;
|
|
signal n_delay : integer := 0;
|
|
|
|
signal inclk1_tmp : std_logic := '0';
|
|
|
|
|
|
signal reset_low : std_logic := '0';
|
|
|
|
-- Phase Reconfig
|
|
|
|
SIGNAL phasecounterselect_reg : std_logic_vector(2 DOWNTO 0);
|
|
|
|
SIGNAL phaseupdown_reg : std_logic := '0';
|
|
SIGNAL phasestep_reg : std_logic := '0';
|
|
SIGNAL phasestep_high_count : integer := 0;
|
|
SIGNAL update_phase : std_logic := '0';
|
|
|
|
signal scandataout_tmp : std_logic := '0';
|
|
signal scandata_in : std_logic := '0';
|
|
signal scandata_out : std_logic := '0';
|
|
signal scandone_tmp : std_logic := '1';
|
|
signal initiate_reconfig : std_logic := '0';
|
|
|
|
signal sig_refclk_period : time := (inclk0_input_frequency * 1 ps) * n;
|
|
|
|
signal schedule_vco : std_logic := '0';
|
|
|
|
signal areset_ena_sig : std_logic := '0';
|
|
signal pll_in_test_mode : boolean := false;
|
|
signal pll_has_just_been_reconfigured : boolean := false;
|
|
|
|
signal inclk_c_from_vco : std_logic_array(0 to 4);
|
|
|
|
signal inclk_m_from_vco : std_logic;
|
|
|
|
SIGNAL inclk0_period : time := 0 ps;
|
|
SIGNAL last_inclk0_period : time := 0 ps;
|
|
SIGNAL last_inclk0_edge : time := 0 ps;
|
|
SIGNAL first_inclk0_edge_detect : STD_LOGIC := '0';
|
|
SIGNAL inclk1_period : time := 0 ps;
|
|
SIGNAL last_inclk1_period : time := 0 ps;
|
|
SIGNAL last_inclk1_edge : time := 0 ps;
|
|
SIGNAL first_inclk1_edge_detect : STD_LOGIC := '0';
|
|
|
|
|
|
|
|
COMPONENT MF_cda_mn_cntr
|
|
PORT (
|
|
clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer := 1;
|
|
time_delay : IN integer := 0
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT MF_cda_scale_cntr
|
|
PORT (
|
|
clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial : IN integer := 1;
|
|
high : IN integer := 1;
|
|
low : IN integer := 1;
|
|
mode : IN string := "bypass";
|
|
ph_tap : IN integer := 0
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT dffp
|
|
|
|
PORT(
|
|
Q : out STD_LOGIC := '0';
|
|
D : in STD_LOGIC := '1';
|
|
CLRN : in STD_LOGIC := '1';
|
|
PRN : in STD_LOGIC := '1';
|
|
CLK : in STD_LOGIC := '0';
|
|
ENA : in STD_LOGIC := '1');
|
|
END COMPONENT;
|
|
|
|
COMPONENT MF_pll_reg
|
|
PORT(
|
|
Q : out STD_LOGIC := '0';
|
|
D : in STD_LOGIC := '1';
|
|
CLRN : in STD_LOGIC := '1';
|
|
PRN : in STD_LOGIC := '1';
|
|
CLK : in STD_LOGIC := '0';
|
|
ENA : in STD_LOGIC := '1');
|
|
END COMPONENT;
|
|
|
|
begin
|
|
|
|
----------------------
|
|
-- INPUT PATH DELAYs
|
|
----------------------
|
|
WireDelay : block
|
|
begin
|
|
inclk0_ipd <= inclk(0);
|
|
inclk1_ipd <= inclk(1);
|
|
areset_ipd <= areset;
|
|
pfdena_ipd <= pfdena;
|
|
scanclk_ipd <= scanclk;
|
|
scanclkena_ipd <= scanclkena;
|
|
scandata_ipd <= scandata;
|
|
configupdate_ipd <= configupdate;
|
|
clkswitch_ipd <= clkswitch;
|
|
phaseupdown_ipd <= phaseupdown;
|
|
phasestep_ipd <= phasestep;
|
|
phasecounterselect_ipd(0) <= phasecounterselect(0);
|
|
phasecounterselect_ipd(1) <= phasecounterselect(1);
|
|
phasecounterselect_ipd(2) <= phasecounterselect(2);
|
|
|
|
end block;
|
|
|
|
inclk_m <= fbclk when m_test_source = 0 else
|
|
refclk when m_test_source = 1 else
|
|
inclk_m_from_vco;
|
|
|
|
areset_ena_sig <= areset_ipd or sig_stop_vco;
|
|
|
|
|
|
pll_in_test_mode <= true when (m_test_source /= -1 or c0_test_source /= -1 or
|
|
c1_test_source /= -1 or c2_test_source /= -1 or
|
|
c3_test_source /= -1 or c4_test_source /= -1)
|
|
else false;
|
|
|
|
real_lock_high <= lock_high WHEN (sim_gate_lock_device_behavior = "on") ELSE 0;
|
|
m1 : MF_cda_mn_cntr
|
|
port map ( clk => inclk_m,
|
|
reset => areset_ena_sig,
|
|
cout => fbclk,
|
|
initial_value => m_initial_val,
|
|
modulus => m_val,
|
|
time_delay => m_delay
|
|
);
|
|
|
|
-- add delta delay to inclk1 to ensure inclk0 and inclk1 are processed
|
|
-- in different simulation deltas.
|
|
inclk1_tmp <= inclk1_ipd;
|
|
|
|
-- Calculate the inclk0 period
|
|
PROCESS
|
|
VARIABLE inclk0_period_tmp : time := 0 ps;
|
|
BEGIN
|
|
WAIT UNTIL (inclk0_ipd'EVENT AND inclk0_ipd = '1');
|
|
IF (first_inclk0_edge_detect = '0') THEN
|
|
first_inclk0_edge_detect <= '1';
|
|
ELSE
|
|
last_inclk0_period <= inclk0_period;
|
|
inclk0_period_tmp := NOW - last_inclk0_edge;
|
|
END IF;
|
|
last_inclk0_edge <= NOW;
|
|
inclk0_period <= inclk0_period_tmp;
|
|
END PROCESS;
|
|
|
|
|
|
-- Calculate the inclk1 period
|
|
PROCESS
|
|
VARIABLE inclk1_period_tmp : time := 0 ps;
|
|
BEGIN
|
|
WAIT UNTIL (inclk1_ipd'EVENT AND inclk1_ipd = '1');
|
|
IF (first_inclk1_edge_detect = '0') THEN
|
|
first_inclk1_edge_detect <= '1';
|
|
ELSE
|
|
last_inclk1_period <= inclk1_period;
|
|
inclk1_period_tmp := NOW - last_inclk1_edge;
|
|
END IF;
|
|
last_inclk1_edge <= NOW;
|
|
inclk1_period <= inclk1_period_tmp;
|
|
END PROCESS;
|
|
|
|
process (inclk0_ipd, inclk1_tmp, clkswitch_ipd)
|
|
variable input_value : std_logic := '0';
|
|
variable current_clock : integer := 0;
|
|
variable clk0_count, clk1_count : integer := 0;
|
|
variable clk0_is_bad, clk1_is_bad : std_logic := '0';
|
|
variable primary_clk_is_bad : boolean := false;
|
|
variable current_clk_is_bad : boolean := false;
|
|
variable got_curr_clk_falling_edge_after_clkswitch : boolean := false;
|
|
variable switch_over_count : integer := 0;
|
|
variable active_clock : std_logic := '0';
|
|
variable external_switch : boolean := false;
|
|
variable diff_percent_period : integer := 0;
|
|
variable buf : line;
|
|
variable switch_clock : boolean := false;
|
|
|
|
begin
|
|
if (now = 0 ps) then
|
|
if (switch_over_type = "manual" and clkswitch_ipd = '1') then
|
|
current_clock := 1;
|
|
active_clock := '1';
|
|
end if;
|
|
end if;
|
|
if (clkswitch_ipd'event and clkswitch_ipd = '1' and switch_over_type = "auto") then
|
|
external_switch := true;
|
|
elsif (switch_over_type = "manual") then
|
|
if (clkswitch_ipd'event and clkswitch_ipd = '1') then
|
|
switch_clock := true;
|
|
elsif (clkswitch_ipd'event and clkswitch_ipd = '0') then
|
|
switch_clock := false;
|
|
end if;
|
|
end if;
|
|
|
|
if (switch_clock = true) then
|
|
if (inclk0_ipd'event or inclk1_tmp'event) then
|
|
if (current_clock = 0) then
|
|
current_clock := 1;
|
|
active_clock := '1';
|
|
clkin <= transport inclk1_tmp;
|
|
elsif (current_clock = 1) then
|
|
current_clock := 0;
|
|
active_clock := '0';
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
switch_clock := false;
|
|
end if;
|
|
end if;
|
|
|
|
-- save the current inclk event value
|
|
if (inclk0_ipd'event) then
|
|
input_value := inclk0_ipd;
|
|
elsif (inclk1_tmp'event) then
|
|
input_value := inclk1_tmp;
|
|
end if;
|
|
|
|
-- check if either input clk is bad
|
|
if (inclk0_ipd'event and inclk0_ipd = '1') then
|
|
clk0_count := clk0_count + 1;
|
|
clk0_is_bad := '0';
|
|
clk1_count := 0;
|
|
if (clk0_count > 2) then
|
|
-- no event on other clk for 2 cycles
|
|
clk1_is_bad := '1';
|
|
if (current_clock = 1) then
|
|
current_clk_is_bad := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (inclk1_tmp'event and inclk1_tmp = '1') then
|
|
clk1_count := clk1_count + 1;
|
|
clk1_is_bad := '0';
|
|
clk0_count := 0;
|
|
if (clk1_count > 2) then
|
|
-- no event on other clk for 2 cycles
|
|
clk0_is_bad := '1';
|
|
if (current_clock = 0) then
|
|
current_clk_is_bad := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- check if the bad clk is the primary clock
|
|
if (clk0_is_bad = '1') then
|
|
primary_clk_is_bad := true;
|
|
else
|
|
primary_clk_is_bad := false;
|
|
end if;
|
|
|
|
-- actual switching
|
|
if (inclk0_ipd'event and current_clock = 0) then
|
|
if (external_switch) then
|
|
if (not got_curr_clk_falling_edge_after_clkswitch) then
|
|
if (inclk0_ipd = '0') then
|
|
got_curr_clk_falling_edge_after_clkswitch := true;
|
|
end if;
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
else
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
elsif (inclk1_tmp'event and current_clock = 1) then
|
|
if (external_switch) then
|
|
if (not got_curr_clk_falling_edge_after_clkswitch) then
|
|
if (inclk1_tmp = '0') then
|
|
got_curr_clk_falling_edge_after_clkswitch := true;
|
|
end if;
|
|
clkin <= transport inclk1_tmp;
|
|
end if;
|
|
else
|
|
clkin <= transport inclk1_tmp;
|
|
end if;
|
|
else
|
|
if (input_value = '1' and enable_switch_over_counter = "on" and primary_clk_is_bad) then
|
|
switch_over_count := switch_over_count + 1;
|
|
end if;
|
|
if ((input_value = '0')) then
|
|
if (external_switch and (got_curr_clk_falling_edge_after_clkswitch or current_clk_is_bad)) or (primary_clk_is_bad and clkswitch_ipd /= '1' and (enable_switch_over_counter = "off" or switch_over_count = switch_over_counter)) then
|
|
got_curr_clk_falling_edge_after_clkswitch := false;
|
|
|
|
if (areset_ipd = '0') then
|
|
if ((inclk0_period > inclk1_period) and (inclk1_period /= 0 ps)) then
|
|
diff_percent_period := (( inclk0_period - inclk1_period ) * 100) / inclk1_period;
|
|
elsif (inclk0_period /= 0 ps) then
|
|
diff_percent_period := (( inclk1_period - inclk0_period ) * 100) / inclk0_period;
|
|
end if;
|
|
|
|
if((diff_percent_period > 20)and ( switch_over_type = "auto")) then
|
|
WRITE(buf,string'("Warning : The input clock frequencies specified for the specified PLL are too far apart for auto-switch-over feature to work properly. Please make sure that the clock frequencies are 20 percent apart for correct functionality."));
|
|
writeline(output, buf);
|
|
end if;
|
|
end if;
|
|
|
|
if (current_clock = 0) then
|
|
current_clock := 1;
|
|
else
|
|
current_clock := 0;
|
|
end if;
|
|
active_clock := not active_clock;
|
|
switch_over_count := 0;
|
|
external_switch := false;
|
|
current_clk_is_bad := false;
|
|
else
|
|
if(switch_over_type = "auto") then
|
|
if(current_clock = 0 and clk0_is_bad = '1' and clk1_is_bad = '0' ) then
|
|
current_clock := 1;
|
|
active_clock := not active_clock;
|
|
end if;
|
|
|
|
if(current_clock = 1 and clk0_is_bad = '0' and clk1_is_bad = '1' ) then
|
|
current_clock := 0;
|
|
active_clock := not active_clock;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end if;
|
|
end if;
|
|
|
|
-- schedule outputs
|
|
clkbad(0) <= clk0_is_bad;
|
|
clkbad(1) <= clk1_is_bad;
|
|
activeclock <= active_clock;
|
|
|
|
end process;
|
|
|
|
|
|
n1 : MF_cda_mn_cntr
|
|
port map (
|
|
clk => clkin,
|
|
reset => areset_ipd,
|
|
cout => refclk,
|
|
initial_value => n_val,
|
|
modulus => n_val);
|
|
|
|
inclk_c0 <= refclk when c0_test_source = 1 else
|
|
fbclk when c0_test_source = 0 else
|
|
inclk_c_from_vco(0);
|
|
|
|
|
|
c0 : MF_cda_scale_cntr
|
|
port map (
|
|
clk => inclk_c0,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(0),
|
|
initial => c_initial_val(0),
|
|
high => c_high_val(0),
|
|
low => c_low_val(0),
|
|
mode => c_mode_val(0),
|
|
ph_tap => c_ph_val(0));
|
|
|
|
inclk_c1 <= refclk when c1_test_source = 1 else
|
|
fbclk when c1_test_source = 0 else
|
|
c_clk(0) when c1_use_casc_in = "on" else
|
|
inclk_c_from_vco(1);
|
|
|
|
|
|
c1 : MF_cda_scale_cntr
|
|
port map (
|
|
clk => inclk_c1,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(1),
|
|
initial => c_initial_val(1),
|
|
high => c_high_val(1),
|
|
low => c_low_val(1),
|
|
mode => c_mode_val(1),
|
|
ph_tap => c_ph_val(1));
|
|
|
|
inclk_c2 <= refclk when c2_test_source = 1 else
|
|
fbclk when c2_test_source = 0 else
|
|
c_clk(1) when c2_use_casc_in = "on" else
|
|
inclk_c_from_vco(2);
|
|
|
|
c2 : MF_cda_scale_cntr
|
|
port map (
|
|
clk => inclk_c2,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(2),
|
|
initial => c_initial_val(2),
|
|
high => c_high_val(2),
|
|
low => c_low_val(2),
|
|
mode => c_mode_val(2),
|
|
ph_tap => c_ph_val(2));
|
|
|
|
|
|
inclk_c3 <= refclk when c3_test_source = 1 else
|
|
fbclk when c3_test_source = 0 else
|
|
c_clk(2) when c3_use_casc_in = "on" else
|
|
inclk_c_from_vco(3);
|
|
|
|
c3 : MF_cda_scale_cntr
|
|
port map (
|
|
clk => inclk_c3,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(3),
|
|
initial => c_initial_val(3),
|
|
high => c_high_val(3),
|
|
low => c_low_val(3),
|
|
mode => c_mode_val(3),
|
|
ph_tap => c_ph_val(3));
|
|
|
|
inclk_c4 <= refclk when c4_test_source = 1 else
|
|
fbclk when c4_test_source = 0 else
|
|
c_clk(3) when (c4_use_casc_in = "on") else
|
|
inclk_c_from_vco(4);
|
|
|
|
c4 : MF_cda_scale_cntr
|
|
port map (
|
|
clk => inclk_c4,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(4),
|
|
initial => c_initial_val(4),
|
|
high => c_high_val(4),
|
|
low => c_low_val(4),
|
|
mode => c_mode_val(4),
|
|
ph_tap => c_ph_val(4));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
process(scandone_tmp, lock)
|
|
begin
|
|
if (scandone_tmp'event and (scandone_tmp = '1')) then
|
|
pll_has_just_been_reconfigured <= true;
|
|
elsif (lock'event and (lock = '1')) then
|
|
pll_has_just_been_reconfigured <= false;
|
|
end if;
|
|
end process;
|
|
|
|
process(inclk_c0, inclk_c1, areset_ipd, sig_stop_vco)
|
|
variable c0_got_first_rising_edge : boolean := false;
|
|
variable c0_count : integer := 2;
|
|
variable c0_initial_count : integer := 1;
|
|
variable c0_tmp, c1_tmp : std_logic := '0';
|
|
variable c1_got_first_rising_edge : boolean := false;
|
|
variable c1_count : integer := 2;
|
|
variable c1_initial_count : integer := 1;
|
|
begin
|
|
if (areset_ipd = '1' or sig_stop_vco = '1') then
|
|
c0_count := 2;
|
|
c1_count := 2;
|
|
c0_initial_count := 1;
|
|
c1_initial_count := 1;
|
|
c0_got_first_rising_edge := false;
|
|
c1_got_first_rising_edge := false;
|
|
else
|
|
if (not c0_got_first_rising_edge) then
|
|
if (inclk_c0'event and inclk_c0 = '1') then
|
|
if (c0_initial_count = c_initial_val(0)) then
|
|
c0_got_first_rising_edge := true;
|
|
else
|
|
c0_initial_count := c0_initial_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (inclk_c0'event) then
|
|
c0_count := c0_count + 1;
|
|
if (c0_count = (c_high_val(0) + c_low_val(0)) * 2) then
|
|
c0_count := 1;
|
|
end if;
|
|
end if;
|
|
if (inclk_c0'event and inclk_c0 = '0') then
|
|
if (c0_count = 1) then
|
|
c0_tmp := '1';
|
|
c0_got_first_rising_edge := false;
|
|
else
|
|
c0_tmp := '0';
|
|
end if;
|
|
end if;
|
|
|
|
if (not c1_got_first_rising_edge) then
|
|
if (inclk_c1'event and inclk_c1 = '1') then
|
|
if (c1_initial_count = c_initial_val(1)) then
|
|
c1_got_first_rising_edge := true;
|
|
else
|
|
c1_initial_count := c1_initial_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (inclk_c1'event) then
|
|
c1_count := c1_count + 1;
|
|
if (c1_count = (c_high_val(1) + c_low_val(1)) * 2) then
|
|
c1_count := 1;
|
|
end if;
|
|
end if;
|
|
if (inclk_c1'event and inclk_c1 = '0') then
|
|
if (c1_count = 1) then
|
|
c1_tmp := '1';
|
|
c1_got_first_rising_edge := false;
|
|
else
|
|
c1_tmp := '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
locked <= pfd_locked WHEN (test_bypass_lock_detect = "on") ELSE
|
|
lock;
|
|
|
|
|
|
process (scandone_tmp)
|
|
variable buf : line;
|
|
begin
|
|
if (scandone_tmp'event and scandone_tmp = '1') then
|
|
if (reconfig_err = false) then
|
|
ASSERT false REPORT "PLL Reprogramming completed with the following values (Values in parantheses indicate values before reprogramming) :" severity note;
|
|
write (buf, string'(" N modulus = "));
|
|
write (buf, n_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, n_val_old);
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" M modulus = "));
|
|
write (buf, m_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, m_val_old);
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" M ph_tap = "));
|
|
write (buf, m_ph_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, m_ph_val_old);
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
for i in 0 to (num_output_cntrs-1) loop
|
|
write (buf, clk_num(i));
|
|
write (buf, string'(" : "));
|
|
write (buf, cntrs(i));
|
|
write (buf, string'(" : high = "));
|
|
write (buf, c_high_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_high_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , low = "));
|
|
write (buf, c_low_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_low_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , mode = "));
|
|
write (buf, c_mode_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_mode_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , phase tap = "));
|
|
write (buf, c_ph_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_ph_val_old(i));
|
|
write (buf, string'(") "));
|
|
writeline(output, buf);
|
|
end loop;
|
|
|
|
IF (pll_reconfig_display_full_setting) THEN
|
|
write (buf, string'(" Charge Pump Current (uA) = "));
|
|
write (buf, cp_curr_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, cp_curr_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Capacitor (pF) = "));
|
|
write (buf, lfc_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfc_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Resistor (Kohm) = "));
|
|
write (buf, lfr_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfr_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" VCO_Post_Scale = "));
|
|
write (buf, vco_cur);
|
|
write (buf, string'(" ( "));
|
|
write (buf, vco_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
|
|
ELSE
|
|
write (buf, string'(" Charge Pump Current (bit setting) = "));
|
|
write (buf, alt_conv_integer(cp_curr_val_bit_setting));
|
|
write (buf, string'(" ( "));
|
|
write (buf, cp_curr_old_bit_setting);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Capacitor (bit setting) = "));
|
|
write (buf, alt_conv_integer(lfc_val_bit_setting));
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfc_old_bit_setting);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Resistor (bit setting) = "));
|
|
write (buf, alt_conv_integer(lfr_val_bit_setting));
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfr_old_bit_setting);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" VCO_Post_Scale = "));
|
|
write (buf, vco_cur);
|
|
write (buf, string'(" ( "));
|
|
write (buf, vco_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
END IF;
|
|
cp_curr_old_bit_setting <= alt_conv_integer(cp_curr_val_bit_setting);
|
|
lfc_old_bit_setting <= alt_conv_integer(lfc_val_bit_setting);
|
|
lfr_old_bit_setting <= alt_conv_integer(lfr_val_bit_setting);
|
|
else ASSERT false REPORT "Errors were encountered during PLL reprogramming. Please refer to error/warning messages above." severity warning;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
update_conf_latches <= configupdate_ipd;
|
|
|
|
|
|
process (scandone_tmp,areset_ipd,update_conf_latches, c_clk(0), c_clk(1), c_clk(2), c_clk(3), c_clk(4), vco_out, fbclk, scanclk_ipd)
|
|
variable init : boolean := true;
|
|
variable low, high : std_logic_vector(7 downto 0);
|
|
variable low_fast, high_fast : std_logic_vector(3 downto 0);
|
|
variable mode : string(1 to 6) := "bypass";
|
|
variable is_error : boolean := false;
|
|
variable m_tmp, n_tmp : std_logic_vector(8 downto 0);
|
|
variable lfr_val_tmp : string(1 to 2) := " ";
|
|
|
|
variable c_high_val_tmp,c_hval : int_array(0 to 4) := (OTHERS => 1);
|
|
variable c_low_val_tmp,c_lval : int_array(0 to 4) := (OTHERS => 1);
|
|
variable c_mode_val_tmp : str_array(0 to 4);
|
|
variable m_val_tmp : integer := 0;
|
|
variable c0_rising_edge_transfer_done : boolean := false;
|
|
variable c1_rising_edge_transfer_done : boolean := false;
|
|
variable c2_rising_edge_transfer_done : boolean := false;
|
|
variable c3_rising_edge_transfer_done : boolean := false;
|
|
variable c4_rising_edge_transfer_done : boolean := false;
|
|
|
|
-- variables for scaling of multiply_by and divide_by values
|
|
variable i_clk0_mult_by : integer := 1;
|
|
variable i_clk0_div_by : integer := 1;
|
|
variable i_clk1_mult_by : integer := 1;
|
|
variable i_clk1_div_by : integer := 1;
|
|
variable i_clk2_mult_by : integer := 1;
|
|
variable i_clk2_div_by : integer := 1;
|
|
variable i_clk3_mult_by : integer := 1;
|
|
variable i_clk3_div_by : integer := 1;
|
|
variable i_clk4_mult_by : integer := 1;
|
|
variable i_clk4_div_by : integer := 1;
|
|
variable max_d_value : integer := 1;
|
|
variable new_multiplier : integer := 1;
|
|
|
|
-- internal variables for storing the phase shift number.(used in lvds mode only)
|
|
variable i_clk0_phase_shift : integer := 1;
|
|
variable i_clk1_phase_shift : integer := 1;
|
|
variable i_clk2_phase_shift : integer := 1;
|
|
|
|
-- user to advanced variables
|
|
|
|
variable max_neg_abs : integer := 0;
|
|
variable i_m_initial : integer;
|
|
variable i_m : integer := 1;
|
|
variable i_n : integer := 1;
|
|
variable i_c_high : int_array(0 to 4);
|
|
variable i_c_low : int_array(0 to 4);
|
|
variable i_c_initial : int_array(0 to 4);
|
|
variable i_c_ph : int_array(0 to 4);
|
|
variable i_c_mode : str_array(0 to 4);
|
|
variable i_m_ph : integer;
|
|
variable output_count : integer;
|
|
variable new_divisor : integer;
|
|
|
|
variable clk0_cntr : string(1 to 6) := " c0";
|
|
variable clk1_cntr : string(1 to 6) := " c1";
|
|
variable clk2_cntr : string(1 to 6) := " c2";
|
|
variable clk3_cntr : string(1 to 6) := " c3";
|
|
variable clk4_cntr : string(1 to 6) := " c4";
|
|
|
|
variable fbk_cntr : string(1 to 2);
|
|
variable fbk_cntr_index : integer;
|
|
variable start_bit : integer;
|
|
variable quiet_time : time := 0 ps;
|
|
variable slowest_clk_old : time := 0 ps;
|
|
variable slowest_clk_new : time := 0 ps;
|
|
|
|
variable i : integer := 0;
|
|
variable j : integer := 0;
|
|
variable scanread_active_edge : time := 0 ps;
|
|
variable got_first_scanclk : boolean := false;
|
|
variable scanclk_last_rising_edge : time := 0 ps;
|
|
variable current_scan_data : std_logic_vector(0 to 143) := (OTHERS => '0');
|
|
|
|
variable index : integer := 0;
|
|
variable scan_chain_length : integer := GPP_SCAN_CHAIN;
|
|
variable tmp_rem : integer := 0;
|
|
variable scanclk_cycles : integer := 0;
|
|
variable lfc_tmp : std_logic_vector(1 downto 0);
|
|
variable lfr_tmp : std_logic_vector(5 downto 0);
|
|
variable lfr_int : integer := 0;
|
|
|
|
variable n_hi,n_lo,m_hi,m_lo : std_logic_vector(7 downto 0);
|
|
variable buf : line;
|
|
variable buf_scan_data : STD_LOGIC_VECTOR(0 TO 1) := (OTHERS => '0');
|
|
variable buf_scan_data_2 : STD_LOGIC_VECTOR(0 TO 2) := (OTHERS => '0');
|
|
|
|
function slowest_clk (
|
|
C0 : integer; C0_mode : string(1 to 6);
|
|
C1 : integer; C1_mode : string(1 to 6);
|
|
C2 : integer; C2_mode : string(1 to 6);
|
|
C3 : integer; C3_mode : string(1 to 6);
|
|
C4 : integer; C4_mode : string(1 to 6);
|
|
C5 : integer; C5_mode : string(1 to 6);
|
|
C6 : integer; C6_mode : string(1 to 6);
|
|
C7 : integer; C7_mode : string(1 to 6);
|
|
C8 : integer; C8_mode : string(1 to 6);
|
|
C9 : integer; C9_mode : string(1 to 6);
|
|
refclk : time; m_mod : integer) return time is
|
|
variable max_modulus : integer := 1;
|
|
variable q_period : time := 0 ps;
|
|
variable refclk_int : integer := 0;
|
|
begin
|
|
if (C0_mode /= "bypass" and C0_mode /= " off") then
|
|
max_modulus := C0;
|
|
end if;
|
|
if (C1 > max_modulus and C1_mode /= "bypass" and C1_mode /= " off") then
|
|
max_modulus := C1;
|
|
end if;
|
|
if (C2 > max_modulus and C2_mode /= "bypass" and C2_mode /= " off") then
|
|
max_modulus := C2;
|
|
end if;
|
|
if (C3 > max_modulus and C3_mode /= "bypass" and C3_mode /= " off") then
|
|
max_modulus := C3;
|
|
end if;
|
|
if (C4 > max_modulus and C4_mode /= "bypass" and C4_mode /= " off") then
|
|
max_modulus := C4;
|
|
end if;
|
|
if (C5 > max_modulus and C5_mode /= "bypass" and C5_mode /= " off") then
|
|
max_modulus := C5;
|
|
end if;
|
|
if (C6 > max_modulus and C6_mode /= "bypass" and C6_mode /= " off") then
|
|
max_modulus := C6;
|
|
end if;
|
|
if (C7 > max_modulus and C7_mode /= "bypass" and C7_mode /= " off") then
|
|
max_modulus := C7;
|
|
end if;
|
|
if (C8 > max_modulus and C8_mode /= "bypass" and C8_mode /= " off") then
|
|
max_modulus := C8;
|
|
end if;
|
|
if (C9 > max_modulus and C9_mode /= "bypass" and C9_mode /= " off") then
|
|
max_modulus := C9;
|
|
end if;
|
|
|
|
refclk_int := refclk / 1 ps;
|
|
if (m_mod /= 0) then
|
|
q_period := (refclk_int * max_modulus / m_mod) * 1 ps;
|
|
end if;
|
|
return (2*q_period);
|
|
end slowest_clk;
|
|
|
|
function int2bin (arg : integer; size : integer) return std_logic_vector is
|
|
variable int_val : integer := arg;
|
|
variable result : std_logic_vector(size-1 downto 0);
|
|
begin
|
|
for i in 0 to result'left loop
|
|
if ((int_val mod 2) = 0) then
|
|
result(i) := '0';
|
|
else
|
|
result(i) := '1';
|
|
end if;
|
|
int_val := int_val/2;
|
|
end loop;
|
|
return result;
|
|
end int2bin;
|
|
|
|
function extract_cntr_string (arg:string) return string is
|
|
variable str : string(1 to 6) := " c0";
|
|
begin
|
|
if (arg = "c0") then
|
|
str := " c0";
|
|
elsif (arg = "c1") then
|
|
str := " c1";
|
|
elsif (arg = "c2") then
|
|
str := " c2";
|
|
elsif (arg = "c3") then
|
|
str := " c3";
|
|
elsif (arg = "c4") then
|
|
str := " c4";
|
|
elsif (arg = "c5") then
|
|
str := " c5";
|
|
elsif (arg = "c6") then
|
|
str := " c6";
|
|
elsif (arg = "c7") then
|
|
str := " c7";
|
|
elsif (arg = "c8") then
|
|
str := " c8";
|
|
elsif (arg = "c9") then
|
|
str := " c9";
|
|
else str := " c0";
|
|
|
|
end if;
|
|
|
|
return str;
|
|
|
|
end extract_cntr_string;
|
|
|
|
function extract_cntr_index (arg:string) return integer is
|
|
variable index : integer := 0;
|
|
begin
|
|
if (arg(6) = '0') then
|
|
index := 0;
|
|
elsif (arg(6) = '1') then
|
|
index := 1;
|
|
elsif (arg(6) = '2') then
|
|
index := 2;
|
|
elsif (arg(6) = '3') then
|
|
index := 3;
|
|
elsif (arg(6) = '4') then
|
|
index := 4;
|
|
elsif (arg(6) = '5') then
|
|
index := 5;
|
|
elsif (arg(6) = '6') then
|
|
index := 6;
|
|
elsif (arg(6) = '7') then
|
|
index := 7;
|
|
elsif (arg(6) = '8') then
|
|
index := 8;
|
|
else index := 9;
|
|
end if;
|
|
|
|
return index;
|
|
end extract_cntr_index;
|
|
|
|
function output_cntr_num (arg:string) return string is
|
|
variable str : string(1 to 6) := "unused";
|
|
begin
|
|
if (arg = "c0") then
|
|
str := " clk0";
|
|
elsif (arg = "c1") then
|
|
str := " clk1";
|
|
elsif (arg = "c2") then
|
|
str := " clk2";
|
|
elsif (arg = "c3") then
|
|
str := " clk3";
|
|
elsif (arg = "c4") then
|
|
str := " clk4";
|
|
elsif (arg = "c5") then
|
|
str := " clk5";
|
|
elsif (arg = "c6") then
|
|
str := " clk6";
|
|
elsif (arg = "c7") then
|
|
str := " clk7";
|
|
elsif (arg = "c8") then
|
|
str := " clk8";
|
|
elsif (arg = "c9") then
|
|
str := " clk9";
|
|
else str := "unused";
|
|
end if;
|
|
return str;
|
|
end output_cntr_num;
|
|
|
|
begin
|
|
IF (areset_ipd'EVENT AND areset_ipd = '1') then
|
|
c_ph_val <= i_c_ph;
|
|
END IF;
|
|
|
|
if (init) then
|
|
if (m = 0) then
|
|
clk4_cntr := " c4";
|
|
clk3_cntr := " c3";
|
|
clk2_cntr := " c2";
|
|
clk1_cntr := " c1";
|
|
clk0_cntr := " c0";
|
|
else
|
|
clk4_cntr := extract_cntr_string(clk4_counter);
|
|
clk3_cntr := extract_cntr_string(clk3_counter);
|
|
clk2_cntr := extract_cntr_string(clk2_counter);
|
|
clk1_cntr := extract_cntr_string(clk1_counter);
|
|
clk0_cntr := extract_cntr_string(clk0_counter);
|
|
end if;
|
|
|
|
clk_num(4) <= output_cntr_num(clk4_counter);
|
|
clk_num(3) <= output_cntr_num(clk3_counter);
|
|
clk_num(2) <= output_cntr_num(clk2_counter);
|
|
clk_num(1) <= output_cntr_num(clk1_counter);
|
|
clk_num(0) <= output_cntr_num(clk0_counter);
|
|
|
|
i_clk0_counter <= extract_cntr_index(clk0_cntr);
|
|
i_clk1_counter <= extract_cntr_index(clk1_cntr);
|
|
i_clk2_counter <= extract_cntr_index(clk2_cntr);
|
|
i_clk3_counter <= extract_cntr_index(clk3_cntr);
|
|
i_clk4_counter <= extract_cntr_index(clk4_cntr);
|
|
|
|
|
|
if (m = 0) then -- convert user parameters to advanced
|
|
-- set the limit of the divide_by value that can be returned by
|
|
-- the following function.
|
|
max_d_value := 1500;
|
|
|
|
-- scale down the multiply_by and divide_by values provided by the design
|
|
-- before attempting to use them in the calculations below
|
|
find_simple_integer_fraction(clk0_multiply_by, clk0_divide_by,
|
|
max_d_value, i_clk0_mult_by, i_clk0_div_by);
|
|
find_simple_integer_fraction(clk1_multiply_by, clk1_divide_by,
|
|
max_d_value, i_clk1_mult_by, i_clk1_div_by);
|
|
find_simple_integer_fraction(clk2_multiply_by, clk2_divide_by,
|
|
max_d_value, i_clk2_mult_by, i_clk2_div_by);
|
|
find_simple_integer_fraction(clk3_multiply_by, clk3_divide_by,
|
|
max_d_value, i_clk3_mult_by, i_clk3_div_by);
|
|
find_simple_integer_fraction(clk4_multiply_by, clk4_divide_by,
|
|
max_d_value, i_clk4_mult_by, i_clk4_div_by);
|
|
|
|
if (vco_frequency_control = "manual_phase") then
|
|
find_m_and_n_4_manual_phase(inclk0_input_frequency, vco_phase_shift_step,
|
|
i_clk0_mult_by, i_clk1_mult_by,
|
|
i_clk2_mult_by, i_clk3_mult_by,
|
|
i_clk4_mult_by,
|
|
1,1,1,1,1,
|
|
i_clk0_div_by, i_clk1_div_by,
|
|
i_clk2_div_by, i_clk3_div_by,
|
|
i_clk4_div_by,
|
|
1,1,1,1,1,
|
|
clk0_counter, clk1_counter,
|
|
clk2_counter, clk3_counter,
|
|
clk4_counter,
|
|
"unused","unused","unused","unused","unused",
|
|
i_m, i_n);
|
|
elsif (((pll_type = "fast") or (pll_type = "lvds") OR (pll_type = "left_right")) and ((vco_multiply_by /= 0) and (vco_divide_by /= 0))) then
|
|
i_n := vco_divide_by;
|
|
i_m := vco_multiply_by;
|
|
else
|
|
i_n := 1;
|
|
|
|
if (((pll_type = "fast") or (pll_type = "left_right")) and (compensate_clock = "lvdsclk")) then
|
|
i_m := i_clk0_mult_by;
|
|
else
|
|
i_m := lcm (i_clk0_mult_by, i_clk1_mult_by,
|
|
i_clk2_mult_by, i_clk3_mult_by,
|
|
i_clk4_mult_by,
|
|
1,1,1,1,1,
|
|
inclk0_input_frequency);
|
|
end if;
|
|
end if;
|
|
|
|
if (pll_type = "flvds") then
|
|
-- Need to readjust phase shift values when the clock multiply value has been readjusted.
|
|
new_multiplier := clk0_multiply_by / i_clk0_mult_by;
|
|
i_clk0_phase_shift := str2int(clk0_phase_shift) * new_multiplier;
|
|
i_clk1_phase_shift := str2int(clk1_phase_shift) * new_multiplier;
|
|
i_clk2_phase_shift := str2int(clk2_phase_shift) * new_multiplier;
|
|
else
|
|
i_clk0_phase_shift := str2int(clk0_phase_shift);
|
|
i_clk1_phase_shift := str2int(clk1_phase_shift);
|
|
i_clk2_phase_shift := str2int(clk2_phase_shift);
|
|
end if;
|
|
|
|
max_neg_abs := maxnegabs(i_clk0_phase_shift,
|
|
i_clk1_phase_shift,
|
|
i_clk2_phase_shift,
|
|
str2int(clk3_phase_shift),
|
|
str2int(clk4_phase_shift),
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
i_m_ph := counter_ph(get_phase_degree(max_neg_abs,inclk0_input_frequency), i_m, i_n);
|
|
|
|
i_c_ph(0) := counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(1) := counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(2) := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(3) := counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(4) := counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
|
|
|
|
i_c_high(0) := counter_high(output_counter_value(i_clk0_div_by,
|
|
i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
|
|
i_c_high(1) := counter_high(output_counter_value(i_clk1_div_by,
|
|
i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
|
|
i_c_high(2) := counter_high(output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
i_c_high(3) := counter_high(output_counter_value(i_clk3_div_by,
|
|
i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
|
|
i_c_high(4) := counter_high(output_counter_value(i_clk4_div_by,
|
|
i_clk4_mult_by, i_m, i_n), clk4_duty_cycle);
|
|
|
|
|
|
|
|
|
|
i_c_low(0) := counter_low(output_counter_value(i_clk0_div_by,
|
|
i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
|
|
i_c_low(1) := counter_low(output_counter_value(i_clk1_div_by,
|
|
i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
|
|
i_c_low(2) := counter_low(output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
i_c_low(3) := counter_low(output_counter_value(i_clk3_div_by,
|
|
i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
|
|
i_c_low(4) := counter_low(output_counter_value(i_clk4_div_by,
|
|
i_clk4_mult_by, i_m, i_n), clk4_duty_cycle);
|
|
|
|
i_m_initial := counter_initial(get_phase_degree(max_neg_abs, inclk0_input_frequency), i_m,i_n);
|
|
|
|
i_c_initial(0) := counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(1) := counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(2) := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(3) := counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(4) := counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_mode(0) := counter_mode(clk0_duty_cycle, output_counter_value(i_clk0_div_by, i_clk0_mult_by, i_m, i_n));
|
|
i_c_mode(1) := counter_mode(clk1_duty_cycle, output_counter_value(i_clk1_div_by, i_clk1_mult_by, i_m, i_n));
|
|
i_c_mode(2) := counter_mode(clk2_duty_cycle, output_counter_value(i_clk2_div_by, i_clk2_mult_by, i_m, i_n));
|
|
i_c_mode(3) := counter_mode(clk3_duty_cycle, output_counter_value(i_clk3_div_by, i_clk3_mult_by, i_m, i_n));
|
|
i_c_mode(4) := counter_mode(clk4_duty_cycle, output_counter_value(i_clk4_div_by, i_clk4_mult_by, i_m, i_n));
|
|
|
|
|
|
|
|
else -- m /= 0
|
|
|
|
i_n := n;
|
|
i_m := m;
|
|
i_m_initial := m_initial;
|
|
i_m_ph := m_ph;
|
|
i_c_ph(0) := c0_ph;
|
|
i_c_ph(1) := c1_ph;
|
|
i_c_ph(2) := c2_ph;
|
|
i_c_ph(3) := c3_ph;
|
|
i_c_ph(4) := c4_ph;
|
|
i_c_high(0) := c0_high;
|
|
i_c_high(1) := c1_high;
|
|
i_c_high(2) := c2_high;
|
|
i_c_high(3) := c3_high;
|
|
i_c_high(4) := c4_high;
|
|
i_c_low(0) := c0_low;
|
|
i_c_low(1) := c1_low;
|
|
i_c_low(2) := c2_low;
|
|
i_c_low(3) := c3_low;
|
|
i_c_low(4) := c4_low;
|
|
i_c_initial(0) := c0_initial;
|
|
i_c_initial(1) := c1_initial;
|
|
i_c_initial(2) := c2_initial;
|
|
i_c_initial(3) := c3_initial;
|
|
i_c_initial(4) := c4_initial;
|
|
i_c_mode(0) := translate_string(c0_mode);
|
|
i_c_mode(1) := translate_string(c1_mode);
|
|
i_c_mode(2) := translate_string(c2_mode);
|
|
i_c_mode(3) := translate_string(c3_mode);
|
|
i_c_mode(4) := translate_string(c4_mode);
|
|
|
|
end if; -- user to advanced conversion.
|
|
|
|
m_initial_val <= i_m_initial;
|
|
n_val <= i_n;
|
|
m_val <= i_m;
|
|
|
|
if (i_m = 1) then
|
|
m_mode_val <= "bypass";
|
|
else
|
|
m_mode_val <= " ";
|
|
end if;
|
|
if (i_n = 1) then
|
|
n_mode_val <= "bypass";
|
|
else
|
|
n_mode_val <= " ";
|
|
end if;
|
|
|
|
m_ph_val <= i_m_ph;
|
|
m_ph_initial <= i_m_ph;
|
|
m_val_tmp := i_m;
|
|
|
|
for i in 0 to 4 loop
|
|
if (i_c_mode(i) = "bypass") then
|
|
if (pll_type = "fast" or pll_type = "lvds" OR (pll_type = "left_right")) then
|
|
i_c_high(i) := 16;
|
|
i_c_low(i) := 16;
|
|
else
|
|
i_c_high(i) := 256;
|
|
i_c_low(i) := 256;
|
|
end if;
|
|
end if;
|
|
c_ph_val(i) <= i_c_ph(i);
|
|
c_initial_val(i) <= i_c_initial(i);
|
|
c_high_val(i) <= i_c_high(i);
|
|
c_low_val(i) <= i_c_low(i);
|
|
c_mode_val(i) <= i_c_mode(i);
|
|
c_high_val_tmp(i) := i_c_high(i);
|
|
c_hval(i) := i_c_high(i);
|
|
c_low_val_tmp(i) := i_c_low(i);
|
|
c_lval(i) := i_c_low(i);
|
|
c_mode_val_tmp(i) := i_c_mode(i);
|
|
c_ph_val_orig(i) <= i_c_ph(i);
|
|
c_high_val_hold(i) <= i_c_high(i);
|
|
c_low_val_hold(i) <= i_c_low(i);
|
|
c_mode_val_hold(i) <= i_c_mode(i);
|
|
end loop;
|
|
|
|
|
|
|
|
scan_chain_length := SCAN_CHAIN;
|
|
|
|
|
|
num_output_cntrs <= 5;
|
|
|
|
init := false;
|
|
elsif (scandone_tmp'EVENT AND scandone_tmp = '1') then
|
|
c0_rising_edge_transfer_done := false;
|
|
c1_rising_edge_transfer_done := false;
|
|
c2_rising_edge_transfer_done := false;
|
|
c3_rising_edge_transfer_done := false;
|
|
c4_rising_edge_transfer_done := false;
|
|
update_conf_latches_reg <= '0';
|
|
elsif (update_conf_latches'event and update_conf_latches = '1') then
|
|
initiate_reconfig <= '1';
|
|
elsif (areset_ipd'event AND areset_ipd = '1') then
|
|
if (scandone_tmp = '0') then scandone_tmp <= '1' AFTER scanclk_period; end if;
|
|
elsif (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
IF (initiate_reconfig = '1') THEN
|
|
initiate_reconfig <= '0';
|
|
ASSERT false REPORT "PLL Reprogramming Initiated" severity note;
|
|
|
|
update_conf_latches_reg <= update_conf_latches;
|
|
reconfig_err <= false;
|
|
scandone_tmp <= '0';
|
|
cp_curr_old <= cp_curr_val;
|
|
lfc_old <= lfc_val;
|
|
lfr_old <= lfr_val;
|
|
vco_old <= vco_cur;
|
|
-- LF unused : bit 0,1
|
|
-- LF Capacitance : bits 2,3 : all values are legal
|
|
buf_scan_data := scan_data(2 TO 3);
|
|
|
|
IF ((pll_type = "fast") OR (pll_type = "lvds") OR (pll_type = "left_right")) THEN
|
|
lfc_val <= fpll_loop_filter_c_arr(alt_conv_integer(buf_scan_data));
|
|
ELSE
|
|
lfc_val <= loop_filter_c_arr(alt_conv_integer(buf_scan_data));
|
|
END IF;
|
|
-- LF Resistance : bits 4-8
|
|
-- valid values - 00000,00100,10000,10100,11000,11011,11100,11110
|
|
IF (scan_data(4 TO 8) = "00000") THEN
|
|
lfr_val <= "20";
|
|
ELSIF (scan_data(4 TO 8) = "00100") THEN
|
|
lfr_val <= "16";
|
|
ELSIF (scan_data(4 TO 8) = "10000") THEN
|
|
lfr_val <= "12";
|
|
ELSIF (scan_data(4 TO 8) = "10100") THEN
|
|
lfr_val <= "08";
|
|
ELSIF (scan_data(4 TO 8) = "11000") THEN
|
|
lfr_val <= "06";
|
|
ELSIF (scan_data(4 TO 8) = "11011") THEN
|
|
lfr_val <= "04";
|
|
ELSIF (scan_data(4 TO 8) = "11100") THEN
|
|
lfr_val <= "02";
|
|
ELSE
|
|
lfr_val <= "01";
|
|
END IF;
|
|
|
|
|
|
-- VCO post scale assignment
|
|
if (scan_data(9) = '1') then -- vco_post_scale = 1
|
|
i_vco_max <= VCO_MAX_NO_DIVISION/2;
|
|
i_vco_min <= VCO_MIN_NO_DIVISION/2;
|
|
vco_cur <= 1;
|
|
else
|
|
i_vco_max <= vco_max;
|
|
i_vco_min <= vco_min;
|
|
vco_cur <= 2;
|
|
end if;
|
|
-- CP
|
|
-- Bit 9 : CRBYPASS
|
|
-- Bit 10-14 : unused
|
|
-- Bits 15-17 : all values are legal
|
|
|
|
buf_scan_data_2 := scan_data(15 TO 17);
|
|
cp_curr_val <= charge_pump_curr_arr(alt_conv_integer(buf_scan_data_2));
|
|
-- save old values for display info.
|
|
|
|
cp_curr_val_bit_setting <= scan_data(15 TO 17);
|
|
lfc_val_bit_setting <= scan_data(2 TO 3);
|
|
lfr_val_bit_setting <= scan_data(4 TO 8);
|
|
|
|
m_val_old <= m_val;
|
|
n_val_old <= n_val;
|
|
m_mode_val_old <= m_mode_val;
|
|
n_mode_val_old <= n_mode_val;
|
|
WHILE (i < num_output_cntrs) LOOP
|
|
c_high_val_old(i) <= c_high_val(i);
|
|
c_low_val_old(i) <= c_low_val(i);
|
|
c_mode_val_old(i) <= c_mode_val(i);
|
|
i := i + 1;
|
|
END LOOP;
|
|
-- M counter
|
|
-- 1. Mode - bypass (bit 18)
|
|
|
|
IF (scan_data(18) = '1') THEN
|
|
n_mode_val <= "bypass";
|
|
-- 3. Mode - odd/even (bit 27)
|
|
ELSIF (scan_data(27) = '1') THEN
|
|
n_mode_val <= " odd";
|
|
ELSE
|
|
n_mode_val <= " even";
|
|
END IF;
|
|
|
|
-- 2. High (bit 19-26)
|
|
|
|
n_hi := scan_data(19 TO 26);
|
|
|
|
-- 4. Low (bit 28-35)
|
|
|
|
n_lo := scan_data(28 TO 35);
|
|
-- N counter
|
|
-- 1. Mode - bypass (bit 36)
|
|
|
|
IF (scan_data(36) = '1') THEN
|
|
m_mode_val <= "bypass";
|
|
-- 3. Mode - odd/even (bit 45)
|
|
ELSIF (scan_data(45) = '1') THEN
|
|
m_mode_val <= " odd";
|
|
ELSE
|
|
m_mode_val <= " even";
|
|
END IF;
|
|
|
|
-- 2. High (bit 37-44)
|
|
|
|
m_hi := scan_data(37 TO 44);
|
|
|
|
-- 4. Low (bit 46-53)
|
|
|
|
m_lo := scan_data(46 TO 53);
|
|
-- C counters (start bit 54) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low
|
|
|
|
i := 0;
|
|
WHILE (i < num_output_cntrs) LOOP
|
|
-- 1. Mode - bypass
|
|
|
|
IF (scan_data(54 + i * 18 + 0) = '1') THEN
|
|
c_mode_val_tmp(i) := "bypass";
|
|
-- 3. Mode - odd/even
|
|
ELSIF (scan_data(54 + i * 18 + 9) = '1') THEN
|
|
c_mode_val_tmp(i) := " odd";
|
|
ELSE
|
|
c_mode_val_tmp(i) := " even";
|
|
END IF;
|
|
-- 2. Hi
|
|
|
|
high := scan_data(54 + i * 18 + 1 TO 54 + i * 18 + 8);
|
|
c_hval(i) := alt_conv_integer(high);
|
|
IF (c_hval(i) /= 0) THEN
|
|
c_high_val_tmp(i) := c_hval(i);
|
|
ELSE
|
|
c_high_val_tmp(i) := alt_conv_integer("000000001");
|
|
END IF;
|
|
|
|
-- 4. Low
|
|
|
|
low := scan_data(54 + i * 18 + 10 TO 54 + i * 18 + 17);
|
|
c_lval(i) := alt_conv_integer(low);
|
|
IF (c_lval(i) /= 0) THEN
|
|
c_low_val_tmp(i) := c_lval(i);
|
|
ELSE
|
|
c_low_val_tmp(i) := alt_conv_integer("000000001");
|
|
END IF;
|
|
i := i + 1;
|
|
END LOOP;
|
|
-- Legality Checks
|
|
|
|
-- M counter value
|
|
IF(scan_data(36) /= '1') THEN
|
|
IF ((m_hi /= m_lo) and (scan_data(45) /= '1')) THEN
|
|
reconfig_err <= TRUE;
|
|
WRITE(buf,string'("Warning : The M counter of the " & family_name & " Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work"));
|
|
writeline(output, buf);
|
|
ELSIF (m_hi /= "00000000") THEN
|
|
m_val_tmp := alt_conv_integer(m_hi) + alt_conv_integer(m_lo);
|
|
ELSE
|
|
m_val_tmp := alt_conv_integer("000000001");
|
|
END IF;
|
|
ELSE
|
|
m_val_tmp := alt_conv_integer("10000000");
|
|
END IF;
|
|
-- N counter value
|
|
IF(scan_data(18) /= '1') THEN
|
|
IF ((n_hi /= n_lo)and (scan_data(27) /= '1')) THEN
|
|
reconfig_err <= TRUE;
|
|
WRITE(buf,string'("Warning : The N counter of the " & family_name & " Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work"));
|
|
writeline(output, buf);
|
|
ELSIF (n_hi /= "00000000") THEN
|
|
n_val <= alt_conv_integer(n_hi) + alt_conv_integer(n_lo);
|
|
ELSE
|
|
n_val <= alt_conv_integer("000000001");
|
|
END IF;
|
|
ELSE
|
|
n_val <= alt_conv_integer("10000000");
|
|
END IF;
|
|
-- TODO : Give warnings/errors in the following cases?
|
|
-- 1. Illegal counter values (error)
|
|
-- 2. Change of mode (warning)
|
|
-- 3. Only 50% duty cycle allowed for M counter (odd mode - hi-lo=1,even - hi-lo=0)
|
|
|
|
END IF;
|
|
end if;
|
|
|
|
|
|
if (fbclk'event and fbclk = '1') then
|
|
m_val <= m_val_tmp;
|
|
end if;
|
|
|
|
if (update_conf_latches_reg = '1') then
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c0_rising_edge_transfer_done := true;
|
|
c_high_val(0) <= c_high_val_tmp(0);
|
|
c_mode_val(0) <= c_mode_val_tmp(0);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c1_rising_edge_transfer_done := true;
|
|
c_high_val(1) <= c_high_val_tmp(1);
|
|
c_mode_val(1) <= c_mode_val_tmp(1);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c2_rising_edge_transfer_done := true;
|
|
c_high_val(2) <= c_high_val_tmp(2);
|
|
c_mode_val(2) <= c_mode_val_tmp(2);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(3) <= c_high_val_tmp(3);
|
|
c_mode_val(3) <= c_mode_val_tmp(3);
|
|
c3_rising_edge_transfer_done := true;
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(4) <= c_high_val_tmp(4);
|
|
c_mode_val(4) <= c_mode_val_tmp(4);
|
|
c4_rising_edge_transfer_done := true;
|
|
end if;
|
|
|
|
|
|
|
|
|
|
|
|
end if;
|
|
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c0_rising_edge_transfer_done) then
|
|
c_low_val(0) <= c_low_val_tmp(0);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c1_rising_edge_transfer_done) then
|
|
c_low_val(1) <= c_low_val_tmp(1);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c2_rising_edge_transfer_done) then
|
|
c_low_val(2) <= c_low_val_tmp(2);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c3_rising_edge_transfer_done) then
|
|
c_low_val(3) <= c_low_val_tmp(3);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c4_rising_edge_transfer_done) then
|
|
c_low_val(4) <= c_low_val_tmp(4);
|
|
end if;
|
|
|
|
if (update_phase = '1') then
|
|
if (vco_out(0)'event and vco_out(0) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 0) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 0) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(1)'event and vco_out(1) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 1) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 1) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(2)'event and vco_out(2) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 2) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 2) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(3)'event and vco_out(3) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 3) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 3) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(4)'event and vco_out(4) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 4) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 4) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(5)'event and vco_out(5) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 5) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 5) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(6)'event and vco_out(6) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 6) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 6) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(7)'event and vco_out(7) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 7) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 7) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
|
|
|
|
if (vco_out(0)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 0) then
|
|
inclk_c_from_vco(i) <= vco_out(0);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 0) then
|
|
inclk_m_from_vco <= vco_out(0);
|
|
end if;
|
|
end if;
|
|
if (vco_out(1)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 1) then
|
|
inclk_c_from_vco(i) <= vco_out(1);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 1) then
|
|
inclk_m_from_vco <= vco_out(1);
|
|
end if;
|
|
end if;
|
|
if (vco_out(2)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 2) then
|
|
inclk_c_from_vco(i) <= vco_out(2);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 2) then
|
|
inclk_m_from_vco <= vco_out(2);
|
|
end if;
|
|
end if;
|
|
if (vco_out(3)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 3) then
|
|
inclk_c_from_vco(i) <= vco_out(3);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 3) then
|
|
inclk_m_from_vco <= vco_out(3);
|
|
end if;
|
|
end if;
|
|
if (vco_out(4)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 4) then
|
|
inclk_c_from_vco(i) <= vco_out(4);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 4) then
|
|
inclk_m_from_vco <= vco_out(4);
|
|
end if;
|
|
end if;
|
|
if (vco_out(5)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 5) then
|
|
inclk_c_from_vco(i) <= vco_out(5);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 5) then
|
|
inclk_m_from_vco <= vco_out(5);
|
|
end if;
|
|
end if;
|
|
if (vco_out(6)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 6) then
|
|
inclk_c_from_vco(i) <= vco_out(6);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 6) then
|
|
inclk_m_from_vco <= vco_out(6);
|
|
end if;
|
|
end if;
|
|
if (vco_out(7)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 7) then
|
|
inclk_c_from_vco(i) <= vco_out(7);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 7) then
|
|
inclk_m_from_vco <= vco_out(7);
|
|
end if;
|
|
end if;
|
|
|
|
|
|
|
|
|
|
if (scanclk_ipd'event AND scanclk_ipd = '0' AND now > 0 ps) then
|
|
scanclkena_reg <= scanclkena_ipd;
|
|
if (scanclkena_reg = '1') then
|
|
scandata_in <= scandata_ipd;
|
|
scandata_out <= scandataout_tmp;
|
|
end if;
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1' and now > 0 ps) then
|
|
if (got_first_scanclk) then
|
|
scanclk_period <= now - scanclk_last_rising_edge;
|
|
else
|
|
got_first_scanclk := true;
|
|
end if;
|
|
if (scanclkena_reg = '1') then
|
|
for j in scan_chain_length - 1 downto 1 loop
|
|
scan_data(j) <= scan_data(j-1);
|
|
end loop;
|
|
scan_data(0) <= scandata_in;
|
|
end if;
|
|
scanclk_last_rising_edge := now;
|
|
end if;
|
|
end process;
|
|
|
|
-- PLL Phase Reconfiguration
|
|
|
|
PROCESS(scanclk_ipd, areset_ipd,phasestep_ipd)
|
|
VARIABLE i : INTEGER := 0;
|
|
VARIABLE c_ph : INTEGER := 0;
|
|
VARIABLE m_ph : INTEGER := 0;
|
|
VARIABLE select_counter : INTEGER := 0;
|
|
BEGIN
|
|
IF (NOW = 0 ps) THEN
|
|
m_ph_val_tmp <= m_ph_initial;
|
|
END IF;
|
|
|
|
-- Latch phase enable (same as phasestep) on neg edge of scan clock
|
|
IF (scanclk_ipd'EVENT AND scanclk_ipd = '0') THEN
|
|
phasestep_reg <= phasestep_ipd;
|
|
END IF;
|
|
|
|
IF (phasestep_ipd'EVENT and phasestep_ipd = '1') THEN
|
|
IF (update_phase = '0') THEN
|
|
phasestep_high_count <= 0; -- phase adjustments must be 1 cycle apart
|
|
-- if not, next phasestep cycle is skipped
|
|
END IF;
|
|
END IF;
|
|
-- revert counter phase tap values to POF programmed values
|
|
-- if PLL is reset
|
|
|
|
IF (areset_ipd'EVENT AND areset_ipd = '1') then
|
|
c_ph_val_tmp <= c_ph_val_orig;
|
|
m_ph_val_tmp <= m_ph_initial;
|
|
END IF;
|
|
|
|
IF (scanclk_ipd'EVENT AND scanclk_ipd = '1') THEN
|
|
IF (phasestep_reg = '1') THEN
|
|
IF (phasestep_high_count = 1) THEN
|
|
phasecounterselect_reg <= phasecounterselect_ipd;
|
|
phaseupdown_reg <= phaseupdown_ipd;
|
|
-- start reconfiguration
|
|
IF (phasecounterselect_ipd < "111") THEN -- no counters selected
|
|
IF (phasecounterselect_ipd = "000") THEN
|
|
i := 0;
|
|
WHILE (i < num_output_cntrs) LOOP
|
|
c_ph := c_ph_val(i);
|
|
IF (phaseupdown_ipd = '1') THEN
|
|
c_ph := (c_ph + 1) mod num_phase_taps;
|
|
ELSIF (c_ph = 0) THEN
|
|
c_ph := num_phase_taps - 1;
|
|
ELSE
|
|
c_ph := (c_ph - 1) mod num_phase_taps;
|
|
END IF;
|
|
c_ph_val_tmp(i) <= c_ph;
|
|
i := i + 1;
|
|
END LOOP;
|
|
ELSIF (phasecounterselect_ipd = "001") THEN
|
|
m_ph := m_ph_val;
|
|
IF (phaseupdown_ipd = '1') THEN
|
|
m_ph := (m_ph + 1) mod num_phase_taps;
|
|
ELSIF (m_ph = 0) THEN
|
|
m_ph := num_phase_taps - 1;
|
|
ELSE
|
|
m_ph := (m_ph - 1) mod num_phase_taps;
|
|
END IF;
|
|
m_ph_val_tmp <= m_ph;
|
|
ELSE
|
|
select_counter := alt_conv_integer(phasecounterselect_ipd) - 2;
|
|
c_ph := c_ph_val(select_counter);
|
|
IF (phaseupdown_ipd = '1') THEN
|
|
c_ph := (c_ph + 1) mod num_phase_taps;
|
|
ELSIF (c_ph = 0) THEN
|
|
c_ph := num_phase_taps - 1;
|
|
ELSE
|
|
c_ph := (c_ph - 1) mod num_phase_taps;
|
|
END IF;
|
|
c_ph_val_tmp(select_counter) <= c_ph;
|
|
END IF;
|
|
update_phase <= '1','0' AFTER (0.5 * scanclk_period);
|
|
END IF;
|
|
END IF;
|
|
phasestep_high_count <= phasestep_high_count + 1;
|
|
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
scandataout_tmp <= scan_data(SCAN_CHAIN - 2);
|
|
|
|
process (schedule_vco, areset_ipd, pfdena_ipd, refclk, fbclk)
|
|
variable sched_time : time := 0 ps;
|
|
|
|
TYPE time_array is ARRAY (0 to 7) of time;
|
|
variable init : boolean := true;
|
|
variable refclk_period : time;
|
|
variable m_times_vco_period : time;
|
|
variable new_m_times_vco_period : time;
|
|
|
|
variable phase_shift : time_array := (OTHERS => 0 ps);
|
|
variable last_phase_shift : time_array := (OTHERS => 0 ps);
|
|
|
|
variable l_index : integer := 1;
|
|
variable cycle_to_adjust : integer := 0;
|
|
|
|
variable stop_vco : boolean := false;
|
|
|
|
variable locked_tmp : std_logic := '0';
|
|
variable pll_is_locked : boolean := false;
|
|
variable cycles_pfd_low : integer := 0;
|
|
variable cycles_pfd_high : integer := 0;
|
|
variable cycles_to_lock : integer := 0;
|
|
variable cycles_to_unlock : integer := 0;
|
|
|
|
variable got_first_refclk : boolean := false;
|
|
variable got_second_refclk : boolean := false;
|
|
variable got_first_fbclk : boolean := false;
|
|
|
|
variable refclk_time : time := 0 ps;
|
|
variable fbclk_time : time := 0 ps;
|
|
variable first_fbclk_time : time := 0 ps;
|
|
|
|
variable fbclk_period : time := 0 ps;
|
|
|
|
variable first_schedule : boolean := true;
|
|
|
|
variable vco_val : std_logic := '0';
|
|
variable vco_period_was_phase_adjusted : boolean := false;
|
|
variable phase_adjust_was_scheduled : boolean := false;
|
|
|
|
variable loop_xplier : integer;
|
|
variable loop_initial : integer := 0;
|
|
variable loop_ph : integer := 0;
|
|
variable loop_time_delay : integer := 0;
|
|
|
|
variable initial_delay : time := 0 ps;
|
|
variable vco_per : time;
|
|
variable tmp_rem : integer;
|
|
variable my_rem : integer;
|
|
variable fbk_phase : integer := 0;
|
|
|
|
variable pull_back_M : integer := 0;
|
|
variable total_pull_back : integer := 0;
|
|
variable fbk_delay : integer := 0;
|
|
|
|
variable offset : time := 0 ps;
|
|
|
|
variable tmp_vco_per : integer := 0;
|
|
variable high_time : time;
|
|
variable low_time : time;
|
|
|
|
variable got_refclk_posedge : boolean := false;
|
|
variable got_fbclk_posedge : boolean := false;
|
|
variable inclk_out_of_range : boolean := false;
|
|
variable no_warn : boolean := false;
|
|
|
|
variable ext_fbk_cntr_modulus : integer := 1;
|
|
variable init_clks : boolean := true;
|
|
variable pll_is_in_reset : boolean := false;
|
|
variable buf : line;
|
|
begin
|
|
if (init) then
|
|
|
|
-- jump-start the VCO
|
|
-- add 1 ps delay to ensure all signals are updated to initial
|
|
-- values
|
|
schedule_vco <= transport not schedule_vco after 1 ps;
|
|
|
|
init := false;
|
|
end if;
|
|
|
|
if (schedule_vco'event) then
|
|
if (init_clks) then
|
|
refclk_period := inclk0_input_frequency * n_val * 1 ps;
|
|
|
|
m_times_vco_period := refclk_period;
|
|
new_m_times_vco_period := refclk_period;
|
|
init_clks := false;
|
|
end if;
|
|
sched_time := 0 ps;
|
|
for i in 0 to 7 loop
|
|
last_phase_shift(i) := phase_shift(i);
|
|
end loop;
|
|
cycle_to_adjust := 0;
|
|
l_index := 1;
|
|
m_times_vco_period := new_m_times_vco_period;
|
|
end if;
|
|
|
|
-- areset was asserted
|
|
if (areset_ipd'event and areset_ipd = '1') then
|
|
assert false report family_name & " PLL was reset" severity note;
|
|
-- reset lock parameters
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
end if;
|
|
|
|
if (areset_ipd = '1') then
|
|
pll_is_in_reset := true;
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
|
|
-- drop VCO taps to 0
|
|
for i in 0 to 7 loop
|
|
vco_out(i) <= transport '0' after 1 ps;
|
|
end loop;
|
|
end if;
|
|
|
|
|
|
if (schedule_vco'event and (areset_ipd = '1' or stop_vco)) then
|
|
|
|
-- drop VCO taps to 0
|
|
for i in 0 to 7 loop
|
|
vco_out(i) <= transport '0' after last_phase_shift(i);
|
|
phase_shift(i) := 0 ps;
|
|
last_phase_shift(i) := 0 ps;
|
|
end loop;
|
|
|
|
-- reset lock parameters
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
refclk_time := 0 ps;
|
|
got_first_fbclk := false;
|
|
fbclk_time := 0 ps;
|
|
first_fbclk_time := 0 ps;
|
|
fbclk_period := 0 ps;
|
|
|
|
first_schedule := true;
|
|
vco_val := '0';
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
|
|
elsif ((schedule_vco'event or areset_ipd'event) and areset_ipd = '0' and (not stop_vco) and now > 0 ps) then
|
|
|
|
-- note areset deassert time
|
|
-- note it as refclk_time to prevent false triggering
|
|
-- of stop_vco after areset
|
|
if (areset_ipd'event and areset_ipd = '0' and pll_is_in_reset) then
|
|
refclk_time := now;
|
|
locked_tmp := '0';
|
|
end if;
|
|
|
|
pll_is_in_reset := false;
|
|
-- calculate loop_xplier : this will be different from m_val
|
|
-- in external_feedback_mode
|
|
loop_xplier := m_val;
|
|
loop_initial := m_initial_val - 1;
|
|
loop_ph := m_ph_val;
|
|
|
|
|
|
-- convert initial value to delay
|
|
initial_delay := (loop_initial * m_times_vco_period)/loop_xplier;
|
|
|
|
-- convert loop ph_tap to delay
|
|
my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
|
|
tmp_vco_per := (m_times_vco_period/1 ps) / loop_xplier;
|
|
if (my_rem /= 0) then
|
|
tmp_vco_per := tmp_vco_per + 1;
|
|
end if;
|
|
fbk_phase := (loop_ph * tmp_vco_per)/8;
|
|
|
|
pull_back_M := initial_delay/1 ps + fbk_phase;
|
|
|
|
total_pull_back := pull_back_M;
|
|
|
|
if (simulation_type = "timing") then
|
|
total_pull_back := total_pull_back + pll_compensation_delay;
|
|
end if;
|
|
while (total_pull_back > refclk_period/1 ps) loop
|
|
total_pull_back := total_pull_back - refclk_period/1 ps;
|
|
end loop;
|
|
|
|
if (total_pull_back > 0) then
|
|
offset := refclk_period - (total_pull_back * 1 ps);
|
|
end if;
|
|
|
|
fbk_delay := total_pull_back - fbk_phase;
|
|
if (fbk_delay < 0) then
|
|
offset := offset - (fbk_phase * 1 ps);
|
|
fbk_delay := total_pull_back;
|
|
end if;
|
|
|
|
-- assign m_delay
|
|
m_delay <= transport fbk_delay after 1 ps;
|
|
|
|
my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
|
|
for i in 1 to loop_xplier loop
|
|
-- adjust cycles
|
|
tmp_vco_per := (m_times_vco_period/1 ps)/loop_xplier;
|
|
if (my_rem /= 0 and l_index <= my_rem) then
|
|
tmp_rem := (loop_xplier * l_index) rem my_rem;
|
|
cycle_to_adjust := (loop_xplier * l_index) / my_rem;
|
|
if (tmp_rem /= 0) then
|
|
cycle_to_adjust := cycle_to_adjust + 1;
|
|
end if;
|
|
end if;
|
|
if (cycle_to_adjust = i) then
|
|
tmp_vco_per := tmp_vco_per + 1;
|
|
l_index := l_index + 1;
|
|
end if;
|
|
|
|
-- calculate high and low periods
|
|
vco_per := tmp_vco_per * 1 ps;
|
|
high_time := (tmp_vco_per/2) * 1 ps;
|
|
if (tmp_vco_per rem 2 /= 0) then
|
|
high_time := high_time + 1 ps;
|
|
end if;
|
|
low_time := vco_per - high_time;
|
|
|
|
-- schedule the rising and falling edges
|
|
for j in 1 to 2 loop
|
|
vco_val := not vco_val;
|
|
if (vco_val = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (vco_val = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
|
|
-- schedule the phase taps
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
if (first_schedule) then
|
|
vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
|
|
else
|
|
vco_out(k) <= transport vco_val after (sched_time + last_phase_shift(k));
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
end loop;
|
|
|
|
-- schedule once more
|
|
if (first_schedule) then
|
|
vco_val := not vco_val;
|
|
if (vco_val = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (vco_val = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
-- schedule the phase taps
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
|
|
end loop;
|
|
first_schedule := false;
|
|
end if;
|
|
|
|
schedule_vco <= transport not schedule_vco after sched_time;
|
|
|
|
if (vco_period_was_phase_adjusted) then
|
|
m_times_vco_period := refclk_period;
|
|
new_m_times_vco_period := refclk_period;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := true;
|
|
|
|
vco_per := m_times_vco_period/loop_xplier;
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
-- Bypass lock detect
|
|
|
|
if (refclk'event and refclk = '1' and areset_ipd = '0') then
|
|
if (test_bypass_lock_detect = "on") then
|
|
if (pfdena_ipd = '1') then
|
|
cycles_pfd_low := 0;
|
|
if (pfd_locked = '0') then
|
|
if (cycles_pfd_high = lock_high) then
|
|
assert false report family_name & " PLL locked in test mode on PFD enable assertion." severity warning;
|
|
pfd_locked <= '1';
|
|
end if;
|
|
cycles_pfd_high := cycles_pfd_high + 1;
|
|
end if;
|
|
end if;
|
|
|
|
if (pfdena_ipd = '0') then
|
|
cycles_pfd_high := 0;
|
|
if (pfd_locked = '1') then
|
|
if (cycles_pfd_low = lock_low) then
|
|
assert false report family_name & " PLL lost lock in test mode on PFD enable de-assertion." severity warning;
|
|
pfd_locked <= '0';
|
|
end if;
|
|
cycles_pfd_low := cycles_pfd_low + 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
|
|
if (refclk'event and refclk = '1' and areset_ipd = '0') then
|
|
got_refclk_posedge := true;
|
|
if (not got_first_refclk) then
|
|
got_first_refclk := true;
|
|
else
|
|
got_second_refclk := true;
|
|
refclk_period := now - refclk_time;
|
|
|
|
-- check if incoming freq. will cause VCO range to be
|
|
-- exceeded
|
|
if ( (i_vco_max /= 0 and i_vco_min /= 0 and pfdena_ipd = '1') and
|
|
(((refclk_period/1 ps)/loop_xplier > i_vco_max) or
|
|
((refclk_period/1 ps)/loop_xplier < i_vco_min)) ) then
|
|
if (pll_is_locked) then
|
|
if ((refclk_period/1 ps)/loop_xplier > i_vco_max) then
|
|
assert false report "Input clock freq. is over VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_over <= '1';
|
|
end if;
|
|
if ((refclk_period/1 ps)/loop_xplier < i_vco_min) then
|
|
assert false report "Input clock freq. is under VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_under <= '1';
|
|
end if;
|
|
if (inclk_out_of_range) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
cycles_to_lock := 0;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
assert false report family_name & " PLL lost lock." severity note;
|
|
end if;
|
|
elsif (not no_warn) then
|
|
if ((refclk_period/1 ps)/loop_xplier > i_vco_max) then
|
|
assert false report "Input clock freq. is over VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_over <= '1';
|
|
end if;
|
|
if ((refclk_period/1 ps)/loop_xplier < i_vco_min) then
|
|
assert false report "Input clock freq. is under VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_under <= '1';
|
|
end if;
|
|
assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may not lock. Please use the correct frequency." severity warning;
|
|
no_warn := true;
|
|
end if;
|
|
inclk_out_of_range := true;
|
|
else
|
|
vco_over <= '0';
|
|
vco_under <= '0';
|
|
inclk_out_of_range := false;
|
|
no_warn := false;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (stop_vco) then
|
|
stop_vco := false;
|
|
schedule_vco <= not schedule_vco;
|
|
end if;
|
|
|
|
refclk_time := now;
|
|
else
|
|
got_refclk_posedge := false;
|
|
end if;
|
|
|
|
-- Update M counter value on feedback clock edge
|
|
|
|
if (fbclk'event and fbclk = '1') then
|
|
got_fbclk_posedge := true;
|
|
if (not got_first_fbclk) then
|
|
got_first_fbclk := true;
|
|
else
|
|
fbclk_period := now - fbclk_time;
|
|
end if;
|
|
|
|
-- need refclk_period here, so initialized to proper value above
|
|
if ( ( (now - refclk_time > 1.5 * refclk_period) and pfdena_ipd = '1' and pll_is_locked) or
|
|
( (now - refclk_time > 5 * refclk_period) and pfdena_ipd = '1' and pll_has_just_been_reconfigured = false) or
|
|
( (now - refclk_time > 50 * refclk_period) and pfdena_ipd = '1' and pll_has_just_been_reconfigured = true) ) then
|
|
stop_vco := true;
|
|
-- reset
|
|
got_first_refclk := false;
|
|
got_first_fbclk := false;
|
|
got_second_refclk := false;
|
|
if (pll_is_locked) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
assert false report family_name & " PLL lost lock due to loss of input clock or the input clock is not detected within the allowed time frame." severity note;
|
|
if ((i_vco_max = 0) and (i_vco_min = 0)) then
|
|
assert false report "Please run timing simulation to check whether the input clock is operating within the supported VCO range or not." severity note;
|
|
end if;
|
|
end if;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
first_schedule := true;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
end if;
|
|
fbclk_time := now;
|
|
else
|
|
got_fbclk_posedge := false;
|
|
end if;
|
|
|
|
if ((got_refclk_posedge or got_fbclk_posedge) and got_second_refclk and pfdena_ipd = '1' and (not inclk_out_of_range)) then
|
|
|
|
-- now we know actual incoming period
|
|
if ( abs(fbclk_time - refclk_time) <= 5 ps or
|
|
(got_first_fbclk and abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
|
|
-- considered in phase
|
|
if (cycles_to_lock = real_lock_high) then
|
|
if (not pll_is_locked) then
|
|
assert false report family_name & " PLL locked to incoming clock" severity note;
|
|
end if;
|
|
pll_is_locked := true;
|
|
locked_tmp := '1';
|
|
cycles_to_unlock := 0;
|
|
end if;
|
|
-- increment lock counter only if second part of above
|
|
-- time check is NOT true
|
|
if (not(abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window)) then
|
|
cycles_to_lock := cycles_to_lock + 1;
|
|
end if;
|
|
|
|
-- adjust m_times_vco_period
|
|
new_m_times_vco_period := refclk_period;
|
|
else
|
|
-- if locked, begin unlock
|
|
if (pll_is_locked) then
|
|
cycles_to_unlock := cycles_to_unlock + 1;
|
|
if (cycles_to_unlock = lock_low) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
cycles_to_lock := 0;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
assert false report family_name & " PLL lost lock." severity note;
|
|
got_first_refclk := false;
|
|
got_first_fbclk := false;
|
|
got_second_refclk := false;
|
|
end if;
|
|
end if;
|
|
if ( abs(refclk_period - fbclk_period) <= 2 ps ) then
|
|
-- frequency is still good
|
|
if (now = fbclk_time and (not phase_adjust_was_scheduled)) then
|
|
if ( abs(fbclk_time - refclk_time) > refclk_period/2) then
|
|
new_m_times_vco_period := m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time));
|
|
vco_period_was_phase_adjusted := true;
|
|
else
|
|
new_m_times_vco_period := m_times_vco_period - abs(fbclk_time - refclk_time);
|
|
vco_period_was_phase_adjusted := true;
|
|
end if;
|
|
|
|
end if;
|
|
else
|
|
phase_adjust_was_scheduled := false;
|
|
new_m_times_vco_period := refclk_period;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (pfdena_ipd = '0') then
|
|
if (pll_is_locked) then
|
|
locked_tmp := 'X';
|
|
end if;
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
end if;
|
|
|
|
-- give message only at time of deassertion
|
|
if (pfdena_ipd'event and pfdena_ipd = '0') then
|
|
assert false report "PFDENA deasserted." severity note;
|
|
elsif (pfdena_ipd'event and pfdena_ipd = '1') then
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
refclk_time := now;
|
|
end if;
|
|
|
|
if (reconfig_err) then
|
|
lock <= '0';
|
|
else
|
|
lock <= locked_tmp;
|
|
end if;
|
|
|
|
-- signal to calculate quiet_time
|
|
sig_refclk_period <= refclk_period;
|
|
|
|
if (stop_vco = true) then
|
|
sig_stop_vco <= '1';
|
|
else
|
|
sig_stop_vco <= '0';
|
|
end if;
|
|
|
|
pll_locked <= pll_is_locked;
|
|
end process;
|
|
|
|
clk0_tmp <= c_clk(i_clk0_counter);
|
|
clk_pfd(0) <= clk0_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(0) <= clk_pfd(0) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk0_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else
|
|
'X';
|
|
|
|
clk1_tmp <= c_clk(i_clk1_counter);
|
|
clk_pfd(1) <= clk1_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(1) <= clk_pfd(1) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk1_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
clk2_tmp <= c_clk(i_clk2_counter);
|
|
clk_pfd(2) <= clk2_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(2) <= clk_pfd(2) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk2_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
clk3_tmp <= c_clk(i_clk3_counter);
|
|
clk_pfd(3) <= clk3_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(3) <= clk_pfd(3) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk3_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
clk4_tmp <= c_clk(i_clk4_counter);
|
|
clk_pfd(4) <= clk4_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(4) <= clk_pfd(4) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk4_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
scandataout <= scandata_out;
|
|
scandone <= NOT scandone_tmp;
|
|
phasedone <= NOT update_phase;
|
|
vcooverrange <= 'Z' WHEN (vco_range_detector_high_bits = -1) ELSE vco_over;
|
|
vcounderrange <= 'Z' WHEN (vco_range_detector_low_bits = -1) ELSE vco_under;
|
|
fbout <= fbclk;
|
|
end vital_pll;
|
|
-- END ARCHITECTURE VITAL_PLL
|
|
-- cycloneiii_msg
|
|
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_stingray_mn_cntr
|
|
--
|
|
-- Description : Simulation model for the M and N counter. This is a
|
|
-- common model for the input counter and the loop feedback
|
|
-- counter of the CycloneIIIGL PLL.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
USE IEEE.std_logic_arith.all;
|
|
USE IEEE.std_logic_unsigned.all;
|
|
|
|
ENTITY MF_stingray_mn_cntr is
|
|
PORT( clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer := 1;
|
|
time_delay : IN integer := 0
|
|
);
|
|
END MF_stingray_mn_cntr;
|
|
|
|
ARCHITECTURE behave of MF_stingray_mn_cntr is
|
|
begin
|
|
|
|
process (clk, reset)
|
|
variable count : integer := 1;
|
|
variable first_rising_edge : boolean := true;
|
|
variable tmp_cout : std_logic;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := true;
|
|
elsif (clk'event) then
|
|
if (clk = '1' and first_rising_edge) then
|
|
first_rising_edge := false;
|
|
tmp_cout := clk;
|
|
elsif (not first_rising_edge) then
|
|
if (count < modulus) then
|
|
count := count + 1;
|
|
else
|
|
count := 1;
|
|
tmp_cout := not tmp_cout;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout after time_delay * 1 ps;
|
|
end process;
|
|
end behave;
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_stingray_post_divider
|
|
--
|
|
-- Description : Simulation model that models the icdrclk output.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
USE IEEE.std_logic_arith.all;
|
|
USE IEEE.std_logic_unsigned.all;
|
|
|
|
ENTITY MF_stingray_post_divider is
|
|
GENERIC ( dpa_divider : integer := 1
|
|
);
|
|
PORT( clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic
|
|
);
|
|
END MF_stingray_post_divider;
|
|
|
|
ARCHITECTURE behave of MF_stingray_post_divider is
|
|
begin
|
|
|
|
process (clk, reset)
|
|
variable count : integer := 1;
|
|
variable first_rising_edge : boolean := true;
|
|
variable tmp_cout : std_logic;
|
|
variable modules : integer := 0;
|
|
variable init : boolean := true;
|
|
begin
|
|
if (init = true) then
|
|
if (dpa_divider = 0) then
|
|
modules := 1;
|
|
else
|
|
modules := dpa_divider;
|
|
end if;
|
|
init := false;
|
|
end if;
|
|
|
|
if (reset = '1') then
|
|
count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := true;
|
|
elsif (clk'event) then
|
|
if (clk = '1' and first_rising_edge) then
|
|
first_rising_edge := false;
|
|
tmp_cout := clk;
|
|
elsif (not first_rising_edge) then
|
|
if (count < modules) then
|
|
count := count + 1;
|
|
else
|
|
count := 1;
|
|
tmp_cout := not tmp_cout;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout;
|
|
end process;
|
|
end behave;
|
|
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_stingray_scale_cntr
|
|
--
|
|
-- Description : Simulation model for the output scale-down counters.
|
|
-- This is a common model for the C0, C1, C2, C3, C4 and C5
|
|
-- output counters of the Stingray PLL.
|
|
--
|
|
--/////////////////////////////////////////////////////////////////////////////
|
|
|
|
LIBRARY IEEE;
|
|
USE IEEE.std_logic_1164.all;
|
|
|
|
ENTITY MF_stingray_scale_cntr is
|
|
PORT( clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
initial : IN integer := 1;
|
|
high : IN integer := 1;
|
|
low : IN integer := 1;
|
|
mode : IN string := "bypass";
|
|
ph_tap : IN integer := 0;
|
|
cout : OUT std_logic
|
|
);
|
|
END MF_stingray_scale_cntr;
|
|
|
|
ARCHITECTURE behave of MF_stingray_scale_cntr is
|
|
begin
|
|
process (clk, reset)
|
|
variable tmp_cout : std_logic := '0';
|
|
variable count : integer := 1;
|
|
variable output_shift_count : integer := 1;
|
|
variable first_rising_edge : boolean := false;
|
|
begin
|
|
if (reset = '1') then
|
|
count := 1;
|
|
output_shift_count := 1;
|
|
tmp_cout := '0';
|
|
first_rising_edge := false;
|
|
elsif (clk'event) then
|
|
if (mode = " off") then
|
|
tmp_cout := '0';
|
|
elsif (mode = "bypass") then
|
|
tmp_cout := clk;
|
|
first_rising_edge := true;
|
|
elsif (not first_rising_edge) then
|
|
if (clk = '1') then
|
|
if (output_shift_count = initial) then
|
|
tmp_cout := clk;
|
|
first_rising_edge := true;
|
|
else
|
|
output_shift_count := output_shift_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (output_shift_count < initial) then
|
|
if (clk = '1') then
|
|
output_shift_count := output_shift_count + 1;
|
|
end if;
|
|
else
|
|
count := count + 1;
|
|
if (mode = " even" and (count = (high*2) + 1)) then
|
|
tmp_cout := '0';
|
|
elsif (mode = " odd" and (count = high*2)) then
|
|
tmp_cout := '0';
|
|
elsif (count = (high + low)*2 + 1) then
|
|
tmp_cout := '1';
|
|
count := 1; -- reset count
|
|
end if;
|
|
end if;
|
|
end if;
|
|
cout <= transport tmp_cout;
|
|
end process;
|
|
|
|
end behave;
|
|
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
--
|
|
-- Entity Name : MF_cycloneiiigl_pll
|
|
--
|
|
-- Description : Simulation model for the Stingray PLL.
|
|
-- In the functional mode, it is also the model for the altpll
|
|
-- megafunction.
|
|
--
|
|
-- Limitations : Does not support Spread Spectrum and Bandwidth.
|
|
--
|
|
-- Outputs : Up to 10 output clocks, each defined by its own set of
|
|
-- parameters. Locked output (active high) indicates when the
|
|
-- PLL locks. clkbad and activeclock are used for
|
|
-- clock switchover to indicate which input clock has gone
|
|
-- bad, when the clock switchover initiates and which input
|
|
-- clock is being used as the reference, respectively.
|
|
-- scandataout is the data output of the serial scan chain.
|
|
--
|
|
--///////////////////////////////////////////////////////////////////////////
|
|
LIBRARY IEEE, std;
|
|
USE IEEE.std_logic_1164.all;
|
|
USE STD.TEXTIO.all;
|
|
USE work.MF_pllpack.all;
|
|
USE work.MF_stingray_mn_cntr;
|
|
USE work.MF_stingray_scale_cntr;
|
|
USE work.dffp;
|
|
USE work.MF_pll_reg;
|
|
|
|
|
|
ENTITY MF_cycloneiiigl_pll is
|
|
GENERIC (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "auto"; -- AUTO/FAST/ENHANCED/LEFT_RIGHT/TOP_BOTTOM
|
|
compensate_clock : string := "clock0";
|
|
|
|
inclk0_input_frequency : integer := 0;
|
|
inclk1_input_frequency : integer := 0;
|
|
|
|
self_reset_on_loss_lock : string := "off";
|
|
switch_over_type : string := "auto";
|
|
switch_over_counter : integer := 1;
|
|
enable_switch_over_counter : string := "off";
|
|
|
|
bandwidth : integer := 0;
|
|
bandwidth_type : string := "auto";
|
|
use_dc_coupling : string := "false";
|
|
|
|
lock_c : integer := 4;
|
|
sim_gate_lock_device_behavior : string := "off";
|
|
lock_high : integer := 0;
|
|
lock_low : integer := 0;
|
|
lock_window_ui : string := "0.05";
|
|
lock_window : time := 5 ps;
|
|
test_bypass_lock_detect : string := "off";
|
|
|
|
|
|
clk0_output_frequency : integer := 0;
|
|
clk0_multiply_by : integer := 0;
|
|
clk0_divide_by : integer := 0;
|
|
clk0_phase_shift : string := "0";
|
|
clk0_duty_cycle : integer := 50;
|
|
|
|
clk1_output_frequency : integer := 0;
|
|
clk1_multiply_by : integer := 0;
|
|
clk1_divide_by : integer := 0;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_duty_cycle : integer := 50;
|
|
|
|
clk2_output_frequency : integer := 0;
|
|
clk2_multiply_by : integer := 0;
|
|
clk2_divide_by : integer := 0;
|
|
clk2_phase_shift : string := "0";
|
|
clk2_duty_cycle : integer := 50;
|
|
|
|
clk3_output_frequency : integer := 0;
|
|
clk3_multiply_by : integer := 0;
|
|
clk3_divide_by : integer := 0;
|
|
clk3_phase_shift : string := "0";
|
|
clk3_duty_cycle : integer := 50;
|
|
|
|
clk4_output_frequency : integer := 0;
|
|
clk4_multiply_by : integer := 0;
|
|
clk4_divide_by : integer := 0;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
|
|
pfd_min : integer := 0;
|
|
pfd_max : integer := 0;
|
|
vco_min : integer := 0;
|
|
vco_max : integer := 0;
|
|
vco_center : integer := 0;
|
|
|
|
feedback_source : integer := 0;
|
|
feedback_external_loop_divider : string := "false";
|
|
|
|
|
|
-- ADVANCED USER PARAMETERS
|
|
m_initial : integer := 1;
|
|
m : integer := 0;
|
|
n : integer := 1;
|
|
|
|
c0_high : integer := 1;
|
|
c0_low : integer := 1;
|
|
c0_initial : integer := 1;
|
|
c0_mode : string := "bypass";
|
|
c0_ph : integer := 0;
|
|
|
|
c1_high : integer := 1;
|
|
c1_low : integer := 1;
|
|
c1_initial : integer := 1;
|
|
c1_mode : string := "bypass";
|
|
c1_ph : integer := 0;
|
|
|
|
c2_high : integer := 1;
|
|
c2_low : integer := 1;
|
|
c2_initial : integer := 1;
|
|
c2_mode : string := "bypass";
|
|
c2_ph : integer := 0;
|
|
|
|
c3_high : integer := 1;
|
|
c3_low : integer := 1;
|
|
c3_initial : integer := 1;
|
|
c3_mode : string := "bypass";
|
|
c3_ph : integer := 0;
|
|
|
|
c4_high : integer := 1;
|
|
c4_low : integer := 1;
|
|
c4_initial : integer := 1;
|
|
c4_mode : string := "bypass";
|
|
c4_ph : integer := 0;
|
|
|
|
m_ph : integer := 0;
|
|
|
|
clk0_counter : string := "unused";
|
|
clk1_counter : string := "unused";
|
|
clk2_counter : string := "unused";
|
|
clk3_counter : string := "unused";
|
|
clk4_counter : string := "unused";
|
|
|
|
c1_use_casc_in : string := "off";
|
|
c2_use_casc_in : string := "off";
|
|
c3_use_casc_in : string := "off";
|
|
c4_use_casc_in : string := "off";
|
|
|
|
m_test_source : integer := -1;
|
|
c0_test_source : integer := -1;
|
|
c1_test_source : integer := -1;
|
|
c2_test_source : integer := -1;
|
|
c3_test_source : integer := -1;
|
|
c4_test_source : integer := -1;
|
|
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
vco_post_scale : integer := 1;
|
|
vco_frequency_control : string := "auto";
|
|
vco_phase_shift_step : integer := 0;
|
|
|
|
dpa_multiply_by : integer := 0;
|
|
dpa_divide_by : integer := 0;
|
|
dpa_divider : integer := 1;
|
|
|
|
charge_pump_current : integer := 10;
|
|
loop_filter_r : string := " 1.0";
|
|
loop_filter_c : integer := 0;
|
|
|
|
pll_compensation_delay : integer := 0;
|
|
simulation_type : string := "functional";
|
|
lpm_hint : string := "unused";
|
|
|
|
clk0_use_even_counter_mode : string := "off";
|
|
clk1_use_even_counter_mode : string := "off";
|
|
clk2_use_even_counter_mode : string := "off";
|
|
clk3_use_even_counter_mode : string := "off";
|
|
clk4_use_even_counter_mode : string := "off";
|
|
|
|
clk0_use_even_counter_value : string := "off";
|
|
clk1_use_even_counter_value : string := "off";
|
|
clk2_use_even_counter_value : string := "off";
|
|
clk3_use_even_counter_value : string := "off";
|
|
clk4_use_even_counter_value : string := "off";
|
|
|
|
-- Test only
|
|
init_block_reset_a_count : integer := 1;
|
|
init_block_reset_b_count : integer := 1;
|
|
charge_pump_current_bits : integer := 0;
|
|
lock_window_ui_bits : integer := 0;
|
|
loop_filter_c_bits : integer := 0;
|
|
loop_filter_r_bits : integer := 0;
|
|
test_counter_c0_delay_chain_bits : integer := 0;
|
|
test_counter_c1_delay_chain_bits : integer := 0;
|
|
test_counter_c2_delay_chain_bits : integer := 0;
|
|
test_counter_c3_delay_chain_bits : integer := 0;
|
|
test_counter_c4_delay_chain_bits : integer := 0;
|
|
test_counter_m_delay_chain_bits : integer := 0;
|
|
test_counter_n_delay_chain_bits : integer := 0;
|
|
test_feedback_comp_delay_chain_bits : integer := 0;
|
|
test_input_comp_delay_chain_bits : integer := 0;
|
|
test_volt_reg_output_mode_bits : integer := 0;
|
|
test_volt_reg_output_voltage_bits : integer := 0;
|
|
test_volt_reg_test_mode : string := "false";
|
|
vco_range_detector_high_bits : integer := -1;
|
|
vco_range_detector_low_bits : integer := -1;
|
|
scan_chain_mif_file : string := "";
|
|
|
|
auto_settings : string := "true";
|
|
-- Simulation only generics
|
|
family_name : string := "Stingray";
|
|
|
|
use_vco_bypass : string := "false"
|
|
);
|
|
|
|
PORT
|
|
(
|
|
inclk : in std_logic_vector(1 downto 0);
|
|
fbin : in std_logic := '0';
|
|
fbout : out std_logic;
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scandata : in std_logic := '0';
|
|
scanclk : in std_logic := '0';
|
|
scanclkena : in std_logic := '1';
|
|
configupdate : in std_logic := '0';
|
|
clk : out std_logic_vector(4 downto 0);
|
|
phasecounterselect : in std_logic_vector(2 downto 0) := "000";
|
|
phaseupdown : in std_logic := '0';
|
|
phasestep : in std_logic := '0';
|
|
clkbad : out std_logic_vector(1 downto 0);
|
|
activeclock : out std_logic;
|
|
locked : out std_logic;
|
|
scandataout : out std_logic;
|
|
scandone : out std_logic;
|
|
phasedone : out std_logic;
|
|
vcooverrange : out std_logic;
|
|
vcounderrange : out std_logic;
|
|
fref : out std_logic;
|
|
icdrclk : out std_logic
|
|
);
|
|
END MF_cycloneiiigl_pll;
|
|
|
|
ARCHITECTURE vital_pll of MF_cycloneiiigl_pll is
|
|
|
|
TYPE int_array is ARRAY(NATURAL RANGE <>) of integer;
|
|
TYPE str_array is ARRAY(NATURAL RANGE <>) of string(1 to 6);
|
|
TYPE str_array1 is ARRAY(NATURAL RANGE <>) of string(1 to 9);
|
|
TYPE std_logic_array is ARRAY(NATURAL RANGE <>) of std_logic;
|
|
|
|
-- internal advanced parameter signals
|
|
signal i_vco_min : integer := vco_min * (vco_post_scale/2);
|
|
signal i_vco_max : integer := vco_max * (vco_post_scale/2);
|
|
signal i_vco_center : integer;
|
|
signal i_pfd_min : integer;
|
|
signal i_pfd_max : integer;
|
|
signal c_ph_val : int_array(0 to 4) := (OTHERS => 0);
|
|
signal c_ph_val_tmp : int_array(0 to 4) := (OTHERS => 0);
|
|
signal c_high_val : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_low_val : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_initial_val : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_mode_val : str_array(0 to 4);
|
|
signal clk_num : str_array(0 to 4);
|
|
|
|
-- old values
|
|
signal c_high_val_old : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_low_val_old : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_ph_val_old : int_array(0 to 4) := (OTHERS => 0);
|
|
signal c_mode_val_old : str_array(0 to 4);
|
|
-- hold registers
|
|
signal c_high_val_hold : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_low_val_hold : int_array(0 to 4) := (OTHERS => 1);
|
|
signal c_ph_val_hold : int_array(0 to 4) := (OTHERS => 0);
|
|
signal c_mode_val_hold : str_array(0 to 4);
|
|
|
|
-- temp registers
|
|
signal sig_c_ph_val_tmp : int_array(0 to 4) := (OTHERS => 0);
|
|
signal c_ph_val_orig : int_array(0 to 4) := (OTHERS => 0);
|
|
|
|
signal real_lock_high : integer := 0;
|
|
signal i_clk4_counter : integer := 4;
|
|
signal i_clk3_counter : integer := 3;
|
|
signal i_clk2_counter : integer := 2;
|
|
signal i_clk1_counter : integer := 1;
|
|
signal i_clk0_counter : integer := 0;
|
|
signal i_charge_pump_current : integer;
|
|
signal i_loop_filter_r : integer;
|
|
|
|
-- end internal advanced parameter signals
|
|
|
|
-- CONSTANTS
|
|
CONSTANT SCAN_CHAIN : integer := 144;
|
|
CONSTANT GPP_SCAN_CHAIN : integer := 234;
|
|
CONSTANT FAST_SCAN_CHAIN : integer := 180;
|
|
CONSTANT cntrs : str_array(4 downto 0) := (" C4", " C3", " C2", " C1", " C0");
|
|
CONSTANT ss_cntrs : str_array(0 to 3) := (" M", " M2", " N", " N2");
|
|
|
|
CONSTANT loop_filter_c_arr : int_array(0 to 3) := (0,0,0,0);
|
|
CONSTANT fpll_loop_filter_c_arr : int_array(0 to 3) := (0,0,0,0);
|
|
CONSTANT charge_pump_curr_arr : int_array(0 to 15) := (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
|
|
|
|
CONSTANT num_phase_taps : integer := 8;
|
|
-- signals
|
|
|
|
signal vcc : std_logic := '1';
|
|
|
|
signal fbclk : std_logic;
|
|
signal refclk : std_logic;
|
|
|
|
signal icdr_clk : std_logic;
|
|
|
|
signal vco_over : std_logic := '0';
|
|
signal vco_under : std_logic := '1';
|
|
|
|
signal pll_locked : boolean := false;
|
|
|
|
|
|
signal c_clk : std_logic_array(0 to 4);
|
|
signal vco_out : std_logic_vector(7 downto 0) := (OTHERS => '0');
|
|
|
|
-- signals to assign values to counter params
|
|
signal m_val : integer := 1;
|
|
signal n_val : integer := 1;
|
|
signal m_ph_val : integer := 0;
|
|
signal m_ph_initial : integer := 0;
|
|
signal m_ph_val_tmp : integer := 0;
|
|
signal m_initial_val : integer := m_initial;
|
|
|
|
signal m_mode_val : string(1 to 6) := " ";
|
|
signal n_mode_val : string(1 to 6) := " ";
|
|
signal lfc_val : integer := 0;
|
|
signal vco_cur : integer := vco_post_scale;
|
|
signal cp_curr_val : integer := 0;
|
|
signal lfr_val : string(1 to 2) := " ";
|
|
|
|
signal cp_curr_old_bit_setting : integer := charge_pump_current_bits;
|
|
signal cp_curr_val_bit_setting : std_logic_vector(2 downto 0) := (OTHERS => '0');
|
|
signal lfr_old_bit_setting : integer := loop_filter_r_bits;
|
|
signal lfr_val_bit_setting : std_logic_vector(4 downto 0) := (OTHERS => '0');
|
|
signal lfc_old_bit_setting : integer := loop_filter_c_bits;
|
|
signal lfc_val_bit_setting : std_logic_vector(1 downto 0) := (OTHERS => '0');
|
|
|
|
signal pll_reconfig_display_full_setting : boolean := FALSE; -- display full setting, change to true
|
|
-- old values
|
|
signal m_val_old : integer := 1;
|
|
signal n_val_old : integer := 1;
|
|
signal m_mode_val_old : string(1 to 6) := " ";
|
|
signal n_mode_val_old : string(1 to 6) := " ";
|
|
signal m_ph_val_old : integer := 0;
|
|
signal lfc_old : integer := 0;
|
|
signal vco_old : integer := 0;
|
|
signal cp_curr_old : integer := 0;
|
|
signal lfr_old : string(1 to 2) := " ";
|
|
signal num_output_cntrs : integer := 5;
|
|
signal scanclk_period : time := 1 ps;
|
|
signal scan_data : std_logic_vector(0 to 143) := (OTHERS => '0');
|
|
|
|
|
|
signal clk_pfd : std_logic_vector(0 to 4);
|
|
signal clk0_tmp : std_logic;
|
|
signal clk1_tmp : std_logic;
|
|
signal clk2_tmp : std_logic;
|
|
signal clk3_tmp : std_logic;
|
|
signal clk4_tmp : std_logic;
|
|
|
|
signal update_conf_latches : std_logic := '0';
|
|
signal update_conf_latches_reg : std_logic := '0';
|
|
|
|
signal clkin : std_logic := '0';
|
|
signal gate_locked : std_logic := '0';
|
|
signal pfd_locked : std_logic := '0';
|
|
signal lock : std_logic := '0';
|
|
signal about_to_lock : boolean := false;
|
|
signal reconfig_err : boolean := false;
|
|
|
|
signal inclk_c0 : std_logic;
|
|
signal inclk_c1 : std_logic;
|
|
signal inclk_c2 : std_logic;
|
|
signal inclk_c3 : std_logic;
|
|
signal inclk_c4 : std_logic;
|
|
signal inclk_m : std_logic;
|
|
signal devpor : std_logic;
|
|
signal devclrn : std_logic;
|
|
|
|
signal inclk0_ipd : std_logic;
|
|
signal inclk1_ipd : std_logic;
|
|
signal pfdena_ipd : std_logic;
|
|
signal areset_ipd : std_logic;
|
|
signal fbin_ipd : std_logic;
|
|
signal scanclk_ipd : std_logic;
|
|
signal scanclkena_ipd, scanclkena_reg : std_logic;
|
|
signal scandata_ipd : std_logic;
|
|
signal clkswitch_ipd : std_logic;
|
|
signal phasecounterselect_ipd : std_logic_vector(2 downto 0);
|
|
signal phaseupdown_ipd : std_logic;
|
|
signal phasestep_ipd : std_logic;
|
|
signal configupdate_ipd : std_logic;
|
|
-- registered signals
|
|
|
|
signal sig_offset : time := 0 ps;
|
|
signal sig_refclk_time : time := 0 ps;
|
|
signal sig_fbclk_period : time := 0 ps;
|
|
signal sig_vco_period_was_phase_adjusted : boolean := false;
|
|
signal sig_phase_adjust_was_scheduled : boolean := false;
|
|
signal sig_stop_vco : std_logic := '0';
|
|
signal sig_m_times_vco_period : time := 0 ps;
|
|
signal sig_new_m_times_vco_period : time := 0 ps;
|
|
signal sig_got_refclk_posedge : boolean := false;
|
|
signal sig_got_fbclk_posedge : boolean := false;
|
|
signal sig_got_second_refclk : boolean := false;
|
|
|
|
signal m_delay : integer := 0;
|
|
signal n_delay : integer := 0;
|
|
|
|
signal inclk1_tmp : std_logic := '0';
|
|
|
|
|
|
signal reset_low : std_logic := '0';
|
|
|
|
-- Phase Reconfig
|
|
|
|
SIGNAL phasecounterselect_reg : std_logic_vector(2 DOWNTO 0);
|
|
|
|
SIGNAL phaseupdown_reg : std_logic := '0';
|
|
SIGNAL phasestep_reg : std_logic := '0';
|
|
SIGNAL phasestep_high_count : integer := 0;
|
|
SIGNAL update_phase : std_logic := '0';
|
|
|
|
signal scandataout_tmp : std_logic := '0';
|
|
signal scandata_in : std_logic := '0';
|
|
signal scandata_out : std_logic := '0';
|
|
signal scandone_tmp : std_logic := '1';
|
|
signal initiate_reconfig : std_logic := '0';
|
|
|
|
signal sig_refclk_period : time := (inclk0_input_frequency * 1 ps) * n;
|
|
|
|
signal schedule_vco : std_logic := '0';
|
|
|
|
signal areset_ena_sig : std_logic := '0';
|
|
signal pll_in_test_mode : boolean := false;
|
|
signal pll_has_just_been_reconfigured : boolean := false;
|
|
|
|
signal inclk_c_from_vco : std_logic_array(0 to 4);
|
|
|
|
signal inclk_m_from_vco : std_logic;
|
|
|
|
SIGNAL inclk0_period : time := 0 ps;
|
|
SIGNAL last_inclk0_period : time := 0 ps;
|
|
SIGNAL last_inclk0_edge : time := 0 ps;
|
|
SIGNAL first_inclk0_edge_detect : STD_LOGIC := '0';
|
|
SIGNAL inclk1_period : time := 0 ps;
|
|
SIGNAL last_inclk1_period : time := 0 ps;
|
|
SIGNAL last_inclk1_edge : time := 0 ps;
|
|
SIGNAL first_inclk1_edge_detect : STD_LOGIC := '0';
|
|
|
|
|
|
|
|
COMPONENT MF_stingray_mn_cntr
|
|
PORT (
|
|
clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial_value : IN integer := 1;
|
|
modulus : IN integer := 1;
|
|
time_delay : IN integer := 0
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT MF_stingray_post_divider
|
|
GENERIC ( dpa_divider : integer := 0
|
|
);
|
|
PORT (
|
|
clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic
|
|
);
|
|
END COMPONENT;
|
|
|
|
|
|
COMPONENT MF_stingray_scale_cntr
|
|
PORT (
|
|
clk : IN std_logic;
|
|
reset : IN std_logic := '0';
|
|
cout : OUT std_logic;
|
|
initial : IN integer := 1;
|
|
high : IN integer := 1;
|
|
low : IN integer := 1;
|
|
mode : IN string := "bypass";
|
|
ph_tap : IN integer := 0
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT dffp
|
|
|
|
PORT(
|
|
Q : out STD_LOGIC := '0';
|
|
D : in STD_LOGIC := '1';
|
|
CLRN : in STD_LOGIC := '1';
|
|
PRN : in STD_LOGIC := '1';
|
|
CLK : in STD_LOGIC := '0';
|
|
ENA : in STD_LOGIC := '1');
|
|
END COMPONENT;
|
|
|
|
COMPONENT MF_pll_reg
|
|
PORT(
|
|
Q : out STD_LOGIC := '0';
|
|
D : in STD_LOGIC := '1';
|
|
CLRN : in STD_LOGIC := '1';
|
|
PRN : in STD_LOGIC := '1';
|
|
CLK : in STD_LOGIC := '0';
|
|
ENA : in STD_LOGIC := '1');
|
|
END COMPONENT;
|
|
|
|
begin
|
|
|
|
----------------------
|
|
-- INPUT PATH DELAYs
|
|
----------------------
|
|
WireDelay : block
|
|
begin
|
|
inclk0_ipd <= inclk(0);
|
|
inclk1_ipd <= inclk(1);
|
|
areset_ipd <= areset;
|
|
pfdena_ipd <= pfdena;
|
|
scanclk_ipd <= scanclk;
|
|
scanclkena_ipd <= scanclkena;
|
|
scandata_ipd <= scandata;
|
|
configupdate_ipd <= configupdate;
|
|
clkswitch_ipd <= clkswitch;
|
|
phaseupdown_ipd <= phaseupdown;
|
|
phasestep_ipd <= phasestep;
|
|
phasecounterselect_ipd(0) <= phasecounterselect(0);
|
|
phasecounterselect_ipd(1) <= phasecounterselect(1);
|
|
phasecounterselect_ipd(2) <= phasecounterselect(2);
|
|
|
|
end block;
|
|
|
|
inclk_m <= fbclk when m_test_source = 0 else
|
|
refclk when m_test_source = 1 else
|
|
inclk_m_from_vco;
|
|
|
|
areset_ena_sig <= areset_ipd or sig_stop_vco;
|
|
|
|
|
|
pll_in_test_mode <= true when (m_test_source /= -1 or c0_test_source /= -1 or
|
|
c1_test_source /= -1 or c2_test_source /= -1 or
|
|
c3_test_source /= -1 or c4_test_source /= -1)
|
|
else false;
|
|
|
|
real_lock_high <= lock_high WHEN (sim_gate_lock_device_behavior = "on") ELSE 0;
|
|
m1 : MF_stingray_mn_cntr
|
|
port map ( clk => inclk_m,
|
|
reset => areset_ena_sig,
|
|
cout => fbclk,
|
|
initial_value => m_initial_val,
|
|
modulus => m_val,
|
|
time_delay => m_delay
|
|
);
|
|
|
|
-- add delta delay to inclk1 to ensure inclk0 and inclk1 are processed
|
|
-- in different simulation deltas.
|
|
inclk1_tmp <= inclk1_ipd;
|
|
|
|
-- Calculate the inclk0 period
|
|
PROCESS
|
|
VARIABLE inclk0_period_tmp : time := 0 ps;
|
|
BEGIN
|
|
WAIT UNTIL (inclk0_ipd'EVENT AND inclk0_ipd = '1');
|
|
IF (first_inclk0_edge_detect = '0') THEN
|
|
first_inclk0_edge_detect <= '1';
|
|
ELSE
|
|
last_inclk0_period <= inclk0_period;
|
|
inclk0_period_tmp := NOW - last_inclk0_edge;
|
|
END IF;
|
|
last_inclk0_edge <= NOW;
|
|
inclk0_period <= inclk0_period_tmp;
|
|
END PROCESS;
|
|
|
|
|
|
-- Calculate the inclk1 period
|
|
PROCESS
|
|
VARIABLE inclk1_period_tmp : time := 0 ps;
|
|
BEGIN
|
|
WAIT UNTIL (inclk1_ipd'EVENT AND inclk1_ipd = '1');
|
|
IF (first_inclk1_edge_detect = '0') THEN
|
|
first_inclk1_edge_detect <= '1';
|
|
ELSE
|
|
last_inclk1_period <= inclk1_period;
|
|
inclk1_period_tmp := NOW - last_inclk1_edge;
|
|
END IF;
|
|
last_inclk1_edge <= NOW;
|
|
inclk1_period <= inclk1_period_tmp;
|
|
END PROCESS;
|
|
|
|
process (inclk0_ipd, inclk1_tmp, clkswitch_ipd)
|
|
variable input_value : std_logic := '0';
|
|
variable current_clock : integer := 0;
|
|
variable clk0_count, clk1_count : integer := 0;
|
|
variable clk0_is_bad, clk1_is_bad : std_logic := '0';
|
|
variable primary_clk_is_bad : boolean := false;
|
|
variable current_clk_is_bad : boolean := false;
|
|
variable got_curr_clk_falling_edge_after_clkswitch : boolean := false;
|
|
variable switch_over_count : integer := 0;
|
|
variable active_clock : std_logic := '0';
|
|
variable external_switch : boolean := false;
|
|
variable diff_percent_period : integer := 0;
|
|
variable buf : line;
|
|
variable switch_clock : boolean := false;
|
|
|
|
begin
|
|
if (now = 0 ps) then
|
|
if (switch_over_type = "manual" and clkswitch_ipd = '1') then
|
|
current_clock := 1;
|
|
active_clock := '1';
|
|
end if;
|
|
end if;
|
|
if (clkswitch_ipd'event and clkswitch_ipd = '1' and switch_over_type = "auto") then
|
|
external_switch := true;
|
|
elsif (switch_over_type = "manual") then
|
|
if (clkswitch_ipd'event and clkswitch_ipd = '1') then
|
|
switch_clock := true;
|
|
elsif (clkswitch_ipd'event and clkswitch_ipd = '0') then
|
|
switch_clock := false;
|
|
end if;
|
|
end if;
|
|
|
|
if (switch_clock = true) then
|
|
if (inclk0_ipd'event or inclk1_tmp'event) then
|
|
if (current_clock = 0) then
|
|
current_clock := 1;
|
|
active_clock := '1';
|
|
clkin <= transport inclk1_tmp;
|
|
elsif (current_clock = 1) then
|
|
current_clock := 0;
|
|
active_clock := '0';
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
switch_clock := false;
|
|
end if;
|
|
end if;
|
|
|
|
-- save the current inclk event value
|
|
if (inclk0_ipd'event) then
|
|
input_value := inclk0_ipd;
|
|
elsif (inclk1_tmp'event) then
|
|
input_value := inclk1_tmp;
|
|
end if;
|
|
|
|
-- check if either input clk is bad
|
|
if (inclk0_ipd'event and inclk0_ipd = '1') then
|
|
clk0_count := clk0_count + 1;
|
|
clk0_is_bad := '0';
|
|
clk1_count := 0;
|
|
if (clk0_count > 2) then
|
|
-- no event on other clk for 2 cycles
|
|
clk1_is_bad := '1';
|
|
if (current_clock = 1) then
|
|
current_clk_is_bad := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (inclk1_tmp'event and inclk1_tmp = '1') then
|
|
clk1_count := clk1_count + 1;
|
|
clk1_is_bad := '0';
|
|
clk0_count := 0;
|
|
if (clk1_count > 2) then
|
|
-- no event on other clk for 2 cycles
|
|
clk0_is_bad := '1';
|
|
if (current_clock = 0) then
|
|
current_clk_is_bad := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- check if the bad clk is the primary clock
|
|
if (clk0_is_bad = '1') then
|
|
primary_clk_is_bad := true;
|
|
else
|
|
primary_clk_is_bad := false;
|
|
end if;
|
|
|
|
-- actual switching
|
|
if (inclk0_ipd'event and current_clock = 0) then
|
|
if (external_switch) then
|
|
if (not got_curr_clk_falling_edge_after_clkswitch) then
|
|
if (inclk0_ipd = '0') then
|
|
got_curr_clk_falling_edge_after_clkswitch := true;
|
|
end if;
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
else
|
|
clkin <= transport inclk0_ipd;
|
|
end if;
|
|
elsif (inclk1_tmp'event and current_clock = 1) then
|
|
if (external_switch) then
|
|
if (not got_curr_clk_falling_edge_after_clkswitch) then
|
|
if (inclk1_tmp = '0') then
|
|
got_curr_clk_falling_edge_after_clkswitch := true;
|
|
end if;
|
|
clkin <= transport inclk1_tmp;
|
|
end if;
|
|
else
|
|
clkin <= transport inclk1_tmp;
|
|
end if;
|
|
else
|
|
if (input_value = '1' and enable_switch_over_counter = "on" and primary_clk_is_bad) then
|
|
switch_over_count := switch_over_count + 1;
|
|
end if;
|
|
if ((input_value = '0')) then
|
|
if (external_switch and (got_curr_clk_falling_edge_after_clkswitch or current_clk_is_bad)) or (primary_clk_is_bad and clkswitch_ipd /= '1' and (enable_switch_over_counter = "off" or switch_over_count = switch_over_counter)) then
|
|
got_curr_clk_falling_edge_after_clkswitch := false;
|
|
|
|
if (areset_ipd = '0') then
|
|
if ((inclk0_period > inclk1_period) and (inclk1_period /= 0 ps)) then
|
|
diff_percent_period := (( inclk0_period - inclk1_period ) * 100) / inclk1_period;
|
|
elsif (inclk0_period /= 0 ps) then
|
|
diff_percent_period := (( inclk1_period - inclk0_period ) * 100) / inclk0_period;
|
|
end if;
|
|
|
|
if((diff_percent_period > 20)and ( switch_over_type = "auto")) then
|
|
WRITE(buf,string'("Warning : The input clock frequencies specified for the specified PLL are too far apart for auto-switch-over feature to work properly. Please make sure that the clock frequencies are 20 percent apart for correct functionality."));
|
|
writeline(output, buf);
|
|
end if;
|
|
end if;
|
|
|
|
if (current_clock = 0) then
|
|
current_clock := 1;
|
|
else
|
|
current_clock := 0;
|
|
end if;
|
|
active_clock := not active_clock;
|
|
switch_over_count := 0;
|
|
external_switch := false;
|
|
current_clk_is_bad := false;
|
|
else
|
|
if(switch_over_type = "auto") then
|
|
if(current_clock = 0 and clk0_is_bad = '1' and clk1_is_bad = '0' ) then
|
|
current_clock := 1;
|
|
active_clock := not active_clock;
|
|
end if;
|
|
|
|
if(current_clock = 1 and clk0_is_bad = '0' and clk1_is_bad = '1' ) then
|
|
current_clock := 0;
|
|
active_clock := not active_clock;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end if;
|
|
end if;
|
|
|
|
-- schedule outputs
|
|
clkbad(0) <= clk0_is_bad;
|
|
clkbad(1) <= clk1_is_bad;
|
|
activeclock <= active_clock;
|
|
|
|
end process;
|
|
|
|
|
|
n1 : MF_stingray_mn_cntr
|
|
port map (
|
|
clk => clkin,
|
|
reset => areset_ipd,
|
|
cout => refclk,
|
|
initial_value => n_val,
|
|
modulus => n_val);
|
|
|
|
d1 : MF_stingray_post_divider
|
|
generic map ( dpa_divider => dpa_divider)
|
|
port map (
|
|
clk => inclk_m_from_vco,
|
|
reset => areset_ipd,
|
|
cout => icdr_clk);
|
|
|
|
|
|
inclk_c0 <= refclk when c0_test_source = 1 else
|
|
fbclk when c0_test_source = 0 else
|
|
inclk_c_from_vco(0);
|
|
|
|
|
|
c0 : MF_stingray_scale_cntr
|
|
port map (
|
|
clk => inclk_c0,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(0),
|
|
initial => c_initial_val(0),
|
|
high => c_high_val(0),
|
|
low => c_low_val(0),
|
|
mode => c_mode_val(0),
|
|
ph_tap => c_ph_val(0));
|
|
|
|
inclk_c1 <= refclk when c1_test_source = 1 else
|
|
fbclk when c1_test_source = 0 else
|
|
c_clk(0) when c1_use_casc_in = "on" else
|
|
inclk_c_from_vco(1);
|
|
|
|
|
|
c1 : MF_stingray_scale_cntr
|
|
port map (
|
|
clk => inclk_c1,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(1),
|
|
initial => c_initial_val(1),
|
|
high => c_high_val(1),
|
|
low => c_low_val(1),
|
|
mode => c_mode_val(1),
|
|
ph_tap => c_ph_val(1));
|
|
|
|
inclk_c2 <= refclk when c2_test_source = 1 else
|
|
fbclk when c2_test_source = 0 else
|
|
c_clk(1) when c2_use_casc_in = "on" else
|
|
inclk_c_from_vco(2);
|
|
|
|
c2 : MF_stingray_scale_cntr
|
|
port map (
|
|
clk => inclk_c2,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(2),
|
|
initial => c_initial_val(2),
|
|
high => c_high_val(2),
|
|
low => c_low_val(2),
|
|
mode => c_mode_val(2),
|
|
ph_tap => c_ph_val(2));
|
|
|
|
|
|
inclk_c3 <= refclk when c3_test_source = 1 else
|
|
fbclk when c3_test_source = 0 else
|
|
c_clk(2) when c3_use_casc_in = "on" else
|
|
inclk_c_from_vco(3);
|
|
|
|
c3 : MF_stingray_scale_cntr
|
|
port map (
|
|
clk => inclk_c3,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(3),
|
|
initial => c_initial_val(3),
|
|
high => c_high_val(3),
|
|
low => c_low_val(3),
|
|
mode => c_mode_val(3),
|
|
ph_tap => c_ph_val(3));
|
|
|
|
inclk_c4 <= refclk when c4_test_source = 1 else
|
|
fbclk when c4_test_source = 0 else
|
|
c_clk(3) when (c4_use_casc_in = "on") else
|
|
inclk_c_from_vco(4);
|
|
|
|
c4 : MF_stingray_scale_cntr
|
|
port map (
|
|
clk => inclk_c4,
|
|
reset => areset_ena_sig,
|
|
cout => c_clk(4),
|
|
initial => c_initial_val(4),
|
|
high => c_high_val(4),
|
|
low => c_low_val(4),
|
|
mode => c_mode_val(4),
|
|
ph_tap => c_ph_val(4));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
process(scandone_tmp, lock)
|
|
begin
|
|
if (scandone_tmp'event and (scandone_tmp = '1')) then
|
|
pll_has_just_been_reconfigured <= true;
|
|
elsif (lock'event and (lock = '1')) then
|
|
pll_has_just_been_reconfigured <= false;
|
|
end if;
|
|
end process;
|
|
|
|
process(inclk_c0, inclk_c1, areset_ipd, sig_stop_vco)
|
|
variable c0_got_first_rising_edge : boolean := false;
|
|
variable c0_count : integer := 2;
|
|
variable c0_initial_count : integer := 1;
|
|
variable c0_tmp, c1_tmp : std_logic := '0';
|
|
variable c1_got_first_rising_edge : boolean := false;
|
|
variable c1_count : integer := 2;
|
|
variable c1_initial_count : integer := 1;
|
|
begin
|
|
if (areset_ipd = '1' or sig_stop_vco = '1') then
|
|
c0_count := 2;
|
|
c1_count := 2;
|
|
c0_initial_count := 1;
|
|
c1_initial_count := 1;
|
|
c0_got_first_rising_edge := false;
|
|
c1_got_first_rising_edge := false;
|
|
else
|
|
if (not c0_got_first_rising_edge) then
|
|
if (inclk_c0'event and inclk_c0 = '1') then
|
|
if (c0_initial_count = c_initial_val(0)) then
|
|
c0_got_first_rising_edge := true;
|
|
else
|
|
c0_initial_count := c0_initial_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (inclk_c0'event) then
|
|
c0_count := c0_count + 1;
|
|
if (c0_count = (c_high_val(0) + c_low_val(0)) * 2) then
|
|
c0_count := 1;
|
|
end if;
|
|
end if;
|
|
if (inclk_c0'event and inclk_c0 = '0') then
|
|
if (c0_count = 1) then
|
|
c0_tmp := '1';
|
|
c0_got_first_rising_edge := false;
|
|
else
|
|
c0_tmp := '0';
|
|
end if;
|
|
end if;
|
|
|
|
if (not c1_got_first_rising_edge) then
|
|
if (inclk_c1'event and inclk_c1 = '1') then
|
|
if (c1_initial_count = c_initial_val(1)) then
|
|
c1_got_first_rising_edge := true;
|
|
else
|
|
c1_initial_count := c1_initial_count + 1;
|
|
end if;
|
|
end if;
|
|
elsif (inclk_c1'event) then
|
|
c1_count := c1_count + 1;
|
|
if (c1_count = (c_high_val(1) + c_low_val(1)) * 2) then
|
|
c1_count := 1;
|
|
end if;
|
|
end if;
|
|
if (inclk_c1'event and inclk_c1 = '0') then
|
|
if (c1_count = 1) then
|
|
c1_tmp := '1';
|
|
c1_got_first_rising_edge := false;
|
|
else
|
|
c1_tmp := '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
locked <= pfd_locked WHEN (test_bypass_lock_detect = "on") ELSE
|
|
lock;
|
|
|
|
|
|
process (scandone_tmp)
|
|
variable buf : line;
|
|
begin
|
|
if (scandone_tmp'event and scandone_tmp = '1') then
|
|
if (reconfig_err = false) then
|
|
ASSERT false REPORT "PLL Reprogramming completed with the following values (Values in parantheses indicate values before reprogramming) :" severity note;
|
|
write (buf, string'(" N modulus = "));
|
|
write (buf, n_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, n_val_old);
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" M modulus = "));
|
|
write (buf, m_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, m_val_old);
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" M ph_tap = "));
|
|
write (buf, m_ph_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, m_ph_val_old);
|
|
write (buf, string'(" )"));
|
|
writeline (output, buf);
|
|
|
|
for i in 0 to (num_output_cntrs-1) loop
|
|
write (buf, clk_num(i));
|
|
write (buf, string'(" : "));
|
|
write (buf, cntrs(i));
|
|
write (buf, string'(" : high = "));
|
|
write (buf, c_high_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_high_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , low = "));
|
|
write (buf, c_low_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_low_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , mode = "));
|
|
write (buf, c_mode_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_mode_val_old(i));
|
|
write (buf, string'(") "));
|
|
write (buf, string'(" , phase tap = "));
|
|
write (buf, c_ph_val(i));
|
|
write (buf, string'(" ("));
|
|
write (buf, c_ph_val_old(i));
|
|
write (buf, string'(") "));
|
|
writeline(output, buf);
|
|
end loop;
|
|
|
|
IF (pll_reconfig_display_full_setting) THEN
|
|
write (buf, string'(" Charge Pump Current (uA) = "));
|
|
write (buf, cp_curr_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, cp_curr_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Capacitor (pF) = "));
|
|
write (buf, lfc_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfc_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Resistor (Kohm) = "));
|
|
write (buf, lfr_val);
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfr_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" VCO_Post_Scale = "));
|
|
write (buf, vco_cur);
|
|
write (buf, string'(" ( "));
|
|
write (buf, vco_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
|
|
ELSE
|
|
write (buf, string'(" Charge Pump Current (bit setting) = "));
|
|
write (buf, alt_conv_integer(cp_curr_val_bit_setting));
|
|
write (buf, string'(" ( "));
|
|
write (buf, cp_curr_old_bit_setting);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Capacitor (bit setting) = "));
|
|
write (buf, alt_conv_integer(lfc_val_bit_setting));
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfc_old_bit_setting);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" Loop Filter Resistor (bit setting) = "));
|
|
write (buf, alt_conv_integer(lfr_val_bit_setting));
|
|
write (buf, string'(" ( "));
|
|
write (buf, lfr_old_bit_setting);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
write (buf, string'(" VCO_Post_Scale = "));
|
|
write (buf, vco_cur);
|
|
write (buf, string'(" ( "));
|
|
write (buf, vco_old);
|
|
write (buf, string'(" ) "));
|
|
writeline (output, buf);
|
|
|
|
END IF;
|
|
cp_curr_old_bit_setting <= alt_conv_integer(cp_curr_val_bit_setting);
|
|
lfc_old_bit_setting <= alt_conv_integer(lfc_val_bit_setting);
|
|
lfr_old_bit_setting <= alt_conv_integer(lfr_val_bit_setting);
|
|
else ASSERT false REPORT "Errors were encountered during PLL reprogramming. Please refer to error/warning messages above." severity warning;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
update_conf_latches <= configupdate_ipd;
|
|
|
|
|
|
process (scandone_tmp,areset_ipd,update_conf_latches, c_clk(0), c_clk(1), c_clk(2), c_clk(3), c_clk(4), vco_out, fbclk, scanclk_ipd)
|
|
variable init : boolean := true;
|
|
variable low, high : std_logic_vector(7 downto 0);
|
|
variable low_fast, high_fast : std_logic_vector(3 downto 0);
|
|
variable mode : string(1 to 6) := "bypass";
|
|
variable is_error : boolean := false;
|
|
variable m_tmp, n_tmp : std_logic_vector(8 downto 0);
|
|
variable lfr_val_tmp : string(1 to 2) := " ";
|
|
|
|
variable c_high_val_tmp,c_hval : int_array(0 to 4) := (OTHERS => 1);
|
|
variable c_low_val_tmp,c_lval : int_array(0 to 4) := (OTHERS => 1);
|
|
variable c_mode_val_tmp : str_array(0 to 4);
|
|
variable m_val_tmp : integer := 0;
|
|
variable c0_rising_edge_transfer_done : boolean := false;
|
|
variable c1_rising_edge_transfer_done : boolean := false;
|
|
variable c2_rising_edge_transfer_done : boolean := false;
|
|
variable c3_rising_edge_transfer_done : boolean := false;
|
|
variable c4_rising_edge_transfer_done : boolean := false;
|
|
|
|
-- variables for scaling of multiply_by and divide_by values
|
|
variable i_clk0_mult_by : integer := 1;
|
|
variable i_clk0_div_by : integer := 1;
|
|
variable i_clk1_mult_by : integer := 1;
|
|
variable i_clk1_div_by : integer := 1;
|
|
variable i_clk2_mult_by : integer := 1;
|
|
variable i_clk2_div_by : integer := 1;
|
|
variable i_clk3_mult_by : integer := 1;
|
|
variable i_clk3_div_by : integer := 1;
|
|
variable i_clk4_mult_by : integer := 1;
|
|
variable i_clk4_div_by : integer := 1;
|
|
variable max_d_value : integer := 1;
|
|
variable new_multiplier : integer := 1;
|
|
|
|
-- internal variables for storing the phase shift number.(used in lvds mode only)
|
|
variable i_clk0_phase_shift : integer := 1;
|
|
variable i_clk1_phase_shift : integer := 1;
|
|
variable i_clk2_phase_shift : integer := 1;
|
|
|
|
-- user to advanced variables
|
|
|
|
variable max_neg_abs : integer := 0;
|
|
variable i_m_initial : integer;
|
|
variable i_m : integer := 1;
|
|
variable i_n : integer := 1;
|
|
variable i_c_high : int_array(0 to 4);
|
|
variable i_c_low : int_array(0 to 4);
|
|
variable i_c_initial : int_array(0 to 4);
|
|
variable i_c_ph : int_array(0 to 4);
|
|
variable i_c_mode : str_array(0 to 4);
|
|
variable i_m_ph : integer;
|
|
variable output_count : integer;
|
|
variable new_divisor : integer;
|
|
|
|
variable clk0_cntr : string(1 to 6) := " c0";
|
|
variable clk1_cntr : string(1 to 6) := " c1";
|
|
variable clk2_cntr : string(1 to 6) := " c2";
|
|
variable clk3_cntr : string(1 to 6) := " c3";
|
|
variable clk4_cntr : string(1 to 6) := " c4";
|
|
|
|
variable i_clk4_cntr : integer := 4;
|
|
variable i_clk3_cntr : integer := 3;
|
|
variable i_clk2_cntr : integer := 2;
|
|
variable i_clk1_cntr : integer := 1;
|
|
variable i_clk0_cntr : integer := 0;
|
|
|
|
variable fbk_cntr : string(1 to 2);
|
|
variable fbk_cntr_index : integer;
|
|
variable start_bit : integer;
|
|
variable quiet_time : time := 0 ps;
|
|
variable slowest_clk_old : time := 0 ps;
|
|
variable slowest_clk_new : time := 0 ps;
|
|
|
|
variable i : integer := 0;
|
|
variable j : integer := 0;
|
|
variable scanread_active_edge : time := 0 ps;
|
|
variable got_first_scanclk : boolean := false;
|
|
variable scanclk_last_rising_edge : time := 0 ps;
|
|
variable current_scan_data : std_logic_vector(0 to 143) := (OTHERS => '0');
|
|
|
|
variable index : integer := 0;
|
|
variable scan_chain_length : integer := GPP_SCAN_CHAIN;
|
|
variable tmp_rem : integer := 0;
|
|
variable scanclk_cycles : integer := 0;
|
|
variable lfc_tmp : std_logic_vector(1 downto 0);
|
|
variable lfr_tmp : std_logic_vector(5 downto 0);
|
|
variable lfr_int : integer := 0;
|
|
|
|
variable n_hi,n_lo,m_hi,m_lo : std_logic_vector(7 downto 0);
|
|
variable buf : line;
|
|
variable buf_scan_data : STD_LOGIC_VECTOR(0 TO 1) := (OTHERS => '0');
|
|
variable buf_scan_data_2 : STD_LOGIC_VECTOR(0 TO 2) := (OTHERS => '0');
|
|
|
|
variable clk_index : integer := 0;
|
|
|
|
function slowest_clk (
|
|
C0 : integer; C0_mode : string(1 to 6);
|
|
C1 : integer; C1_mode : string(1 to 6);
|
|
C2 : integer; C2_mode : string(1 to 6);
|
|
C3 : integer; C3_mode : string(1 to 6);
|
|
C4 : integer; C4_mode : string(1 to 6);
|
|
C5 : integer; C5_mode : string(1 to 6);
|
|
C6 : integer; C6_mode : string(1 to 6);
|
|
C7 : integer; C7_mode : string(1 to 6);
|
|
C8 : integer; C8_mode : string(1 to 6);
|
|
C9 : integer; C9_mode : string(1 to 6);
|
|
refclk : time; m_mod : integer) return time is
|
|
variable max_modulus : integer := 1;
|
|
variable q_period : time := 0 ps;
|
|
variable refclk_int : integer := 0;
|
|
begin
|
|
if (C0_mode /= "bypass" and C0_mode /= " off") then
|
|
max_modulus := C0;
|
|
end if;
|
|
if (C1 > max_modulus and C1_mode /= "bypass" and C1_mode /= " off") then
|
|
max_modulus := C1;
|
|
end if;
|
|
if (C2 > max_modulus and C2_mode /= "bypass" and C2_mode /= " off") then
|
|
max_modulus := C2;
|
|
end if;
|
|
if (C3 > max_modulus and C3_mode /= "bypass" and C3_mode /= " off") then
|
|
max_modulus := C3;
|
|
end if;
|
|
if (C4 > max_modulus and C4_mode /= "bypass" and C4_mode /= " off") then
|
|
max_modulus := C4;
|
|
end if;
|
|
if (C5 > max_modulus and C5_mode /= "bypass" and C5_mode /= " off") then
|
|
max_modulus := C5;
|
|
end if;
|
|
if (C6 > max_modulus and C6_mode /= "bypass" and C6_mode /= " off") then
|
|
max_modulus := C6;
|
|
end if;
|
|
if (C7 > max_modulus and C7_mode /= "bypass" and C7_mode /= " off") then
|
|
max_modulus := C7;
|
|
end if;
|
|
if (C8 > max_modulus and C8_mode /= "bypass" and C8_mode /= " off") then
|
|
max_modulus := C8;
|
|
end if;
|
|
if (C9 > max_modulus and C9_mode /= "bypass" and C9_mode /= " off") then
|
|
max_modulus := C9;
|
|
end if;
|
|
|
|
refclk_int := refclk / 1 ps;
|
|
if (m_mod /= 0) then
|
|
q_period := (refclk_int * max_modulus / m_mod) * 1 ps;
|
|
end if;
|
|
return (2*q_period);
|
|
end slowest_clk;
|
|
|
|
function int2bin (arg : integer; size : integer) return std_logic_vector is
|
|
variable int_val : integer := arg;
|
|
variable result : std_logic_vector(size-1 downto 0);
|
|
begin
|
|
for i in 0 to result'left loop
|
|
if ((int_val mod 2) = 0) then
|
|
result(i) := '0';
|
|
else
|
|
result(i) := '1';
|
|
end if;
|
|
int_val := int_val/2;
|
|
end loop;
|
|
return result;
|
|
end int2bin;
|
|
|
|
function extract_cntr_string (arg:string) return string is
|
|
variable str : string(1 to 6) := " c0";
|
|
begin
|
|
if (arg = "c0") then
|
|
str := " c0";
|
|
elsif (arg = "c1") then
|
|
str := " c1";
|
|
elsif (arg = "c2") then
|
|
str := " c2";
|
|
elsif (arg = "c3") then
|
|
str := " c3";
|
|
elsif (arg = "c4") then
|
|
str := " c4";
|
|
elsif (arg = "c5") then
|
|
str := " c5";
|
|
elsif (arg = "c6") then
|
|
str := " c6";
|
|
elsif (arg = "c7") then
|
|
str := " c7";
|
|
elsif (arg = "c8") then
|
|
str := " c8";
|
|
elsif (arg = "c9") then
|
|
str := " c9";
|
|
else str := " c0";
|
|
|
|
end if;
|
|
|
|
return str;
|
|
|
|
end extract_cntr_string;
|
|
|
|
function extract_cntr_index (arg:string) return integer is
|
|
variable index : integer := 0;
|
|
begin
|
|
if (arg(6) = '0') then
|
|
index := 0;
|
|
elsif (arg(6) = '1') then
|
|
index := 1;
|
|
elsif (arg(6) = '2') then
|
|
index := 2;
|
|
elsif (arg(6) = '3') then
|
|
index := 3;
|
|
elsif (arg(6) = '4') then
|
|
index := 4;
|
|
elsif (arg(6) = '5') then
|
|
index := 5;
|
|
elsif (arg(6) = '6') then
|
|
index := 6;
|
|
elsif (arg(6) = '7') then
|
|
index := 7;
|
|
elsif (arg(6) = '8') then
|
|
index := 8;
|
|
else index := 9;
|
|
end if;
|
|
|
|
return index;
|
|
end extract_cntr_index;
|
|
|
|
function output_cntr_num (arg:string) return string is
|
|
variable str : string(1 to 6) := "unused";
|
|
begin
|
|
if (arg = "c0") then
|
|
str := " clk0";
|
|
elsif (arg = "c1") then
|
|
str := " clk1";
|
|
elsif (arg = "c2") then
|
|
str := " clk2";
|
|
elsif (arg = "c3") then
|
|
str := " clk3";
|
|
elsif (arg = "c4") then
|
|
str := " clk4";
|
|
elsif (arg = "c5") then
|
|
str := " clk5";
|
|
elsif (arg = "c6") then
|
|
str := " clk6";
|
|
elsif (arg = "c7") then
|
|
str := " clk7";
|
|
elsif (arg = "c8") then
|
|
str := " clk8";
|
|
elsif (arg = "c9") then
|
|
str := " clk9";
|
|
else str := "unused";
|
|
end if;
|
|
return str;
|
|
end output_cntr_num;
|
|
|
|
begin
|
|
IF (areset_ipd'EVENT AND areset_ipd = '1') then
|
|
c_ph_val <= i_c_ph;
|
|
END IF;
|
|
|
|
if (init) then
|
|
if (m = 0) then
|
|
clk4_cntr := " c4";
|
|
clk3_cntr := " c3";
|
|
clk2_cntr := " c2";
|
|
clk1_cntr := " c1";
|
|
clk0_cntr := " c0";
|
|
else
|
|
clk4_cntr := extract_cntr_string(clk4_counter);
|
|
clk3_cntr := extract_cntr_string(clk3_counter);
|
|
clk2_cntr := extract_cntr_string(clk2_counter);
|
|
clk1_cntr := extract_cntr_string(clk1_counter);
|
|
clk0_cntr := extract_cntr_string(clk0_counter);
|
|
end if;
|
|
|
|
clk_num(4) <= output_cntr_num(clk4_counter);
|
|
clk_num(3) <= output_cntr_num(clk3_counter);
|
|
clk_num(2) <= output_cntr_num(clk2_counter);
|
|
clk_num(1) <= output_cntr_num(clk1_counter);
|
|
clk_num(0) <= output_cntr_num(clk0_counter);
|
|
|
|
i_clk0_counter <= extract_cntr_index(clk0_cntr);
|
|
i_clk1_counter <= extract_cntr_index(clk1_cntr);
|
|
i_clk2_counter <= extract_cntr_index(clk2_cntr);
|
|
i_clk3_counter <= extract_cntr_index(clk3_cntr);
|
|
i_clk4_counter <= extract_cntr_index(clk4_cntr);
|
|
|
|
i_clk0_cntr := extract_cntr_index(clk0_cntr);
|
|
i_clk1_cntr := extract_cntr_index(clk1_cntr);
|
|
i_clk2_cntr := extract_cntr_index(clk2_cntr);
|
|
i_clk3_cntr := extract_cntr_index(clk3_cntr);
|
|
i_clk4_cntr := extract_cntr_index(clk4_cntr);
|
|
|
|
if (m = 0) then -- convert user parameters to advanced
|
|
-- set the limit of the divide_by value that can be returned by
|
|
-- the following function.
|
|
max_d_value := 500;
|
|
|
|
-- scale down the multiply_by and divide_by values provided by the design
|
|
-- before attempting to use them in the calculations below
|
|
find_simple_integer_fraction(clk0_multiply_by, clk0_divide_by,
|
|
max_d_value, i_clk0_mult_by, i_clk0_div_by);
|
|
find_simple_integer_fraction(clk1_multiply_by, clk1_divide_by,
|
|
max_d_value, i_clk1_mult_by, i_clk1_div_by);
|
|
find_simple_integer_fraction(clk2_multiply_by, clk2_divide_by,
|
|
max_d_value, i_clk2_mult_by, i_clk2_div_by);
|
|
find_simple_integer_fraction(clk3_multiply_by, clk3_divide_by,
|
|
max_d_value, i_clk3_mult_by, i_clk3_div_by);
|
|
find_simple_integer_fraction(clk4_multiply_by, clk4_divide_by,
|
|
max_d_value, i_clk4_mult_by, i_clk4_div_by);
|
|
|
|
if (vco_frequency_control = "manual_phase") then
|
|
find_m_and_n_4_manual_phase(inclk0_input_frequency, vco_phase_shift_step,
|
|
i_clk0_mult_by, i_clk1_mult_by,
|
|
i_clk2_mult_by, i_clk3_mult_by,
|
|
i_clk4_mult_by,
|
|
1,1,1,1,1,
|
|
i_clk0_div_by, i_clk1_div_by,
|
|
i_clk2_div_by, i_clk3_div_by,
|
|
i_clk4_div_by,
|
|
1,1,1,1,1,
|
|
clk0_counter, clk1_counter,
|
|
clk2_counter, clk3_counter,
|
|
clk4_counter,
|
|
"unused","unused","unused","unused","unused",
|
|
i_m, i_n);
|
|
elsif (((pll_type = "fast") or (pll_type = "lvds") OR (pll_type = "left_right")) and ((vco_multiply_by /= 0) and (vco_divide_by /= 0))) then
|
|
i_n := vco_divide_by;
|
|
i_m := vco_multiply_by;
|
|
elsif ((dpa_multiply_by /= 0) and (dpa_divide_by /= 0)) then
|
|
i_n := dpa_divide_by;
|
|
i_m := dpa_multiply_by;
|
|
else
|
|
i_n := 1;
|
|
|
|
if (((pll_type = "fast") or (pll_type = "left_right")) and (compensate_clock = "lvdsclk")) then
|
|
i_m := i_clk0_mult_by;
|
|
else
|
|
i_m := lcm (i_clk0_mult_by, i_clk1_mult_by,
|
|
i_clk2_mult_by, i_clk3_mult_by,
|
|
i_clk4_mult_by,
|
|
1,1,1,1,1,
|
|
inclk0_input_frequency);
|
|
end if;
|
|
end if;
|
|
|
|
if (pll_type = "flvds") then
|
|
-- Need to readjust phase shift values when the clock multiply value has been readjusted.
|
|
new_multiplier := clk0_multiply_by / i_clk0_mult_by;
|
|
i_clk0_phase_shift := str2int(clk0_phase_shift) * new_multiplier;
|
|
i_clk1_phase_shift := str2int(clk1_phase_shift) * new_multiplier;
|
|
i_clk2_phase_shift := str2int(clk2_phase_shift) * new_multiplier;
|
|
else
|
|
i_clk0_phase_shift := str2int(clk0_phase_shift);
|
|
i_clk1_phase_shift := str2int(clk1_phase_shift);
|
|
i_clk2_phase_shift := str2int(clk2_phase_shift);
|
|
end if;
|
|
|
|
max_neg_abs := maxnegabs(i_clk0_phase_shift,
|
|
i_clk1_phase_shift,
|
|
i_clk2_phase_shift,
|
|
str2int(clk3_phase_shift),
|
|
str2int(clk4_phase_shift),
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
i_m_ph := counter_ph(get_phase_degree(max_neg_abs,inclk0_input_frequency), i_m, i_n);
|
|
|
|
i_c_ph(0) := counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(1) := counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(2) := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(3) := counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
i_c_ph(4) := counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
|
|
|
|
|
|
i_c_high(0) := counter_high(output_counter_value(i_clk0_div_by,
|
|
i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
|
|
i_c_high(1) := counter_high(output_counter_value(i_clk1_div_by,
|
|
i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
|
|
i_c_high(2) := counter_high(output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
i_c_high(3) := counter_high(output_counter_value(i_clk3_div_by,
|
|
i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
|
|
i_c_high(4) := counter_high(output_counter_value(i_clk4_div_by,
|
|
i_clk4_mult_by, i_m, i_n), clk4_duty_cycle);
|
|
|
|
|
|
|
|
|
|
i_c_low(0) := counter_low(output_counter_value(i_clk0_div_by,
|
|
i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
|
|
i_c_low(1) := counter_low(output_counter_value(i_clk1_div_by,
|
|
i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
|
|
i_c_low(2) := counter_low(output_counter_value(i_clk2_div_by,
|
|
i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
|
|
i_c_low(3) := counter_low(output_counter_value(i_clk3_div_by,
|
|
i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
|
|
i_c_low(4) := counter_low(output_counter_value(i_clk4_div_by,
|
|
i_clk4_mult_by, i_m, i_n), clk4_duty_cycle);
|
|
|
|
i_m_initial := counter_initial(get_phase_degree(max_neg_abs, inclk0_input_frequency), i_m,i_n);
|
|
|
|
i_c_initial(0) := counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(1) := counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(2) := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(3) := counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_initial(4) := counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
|
|
i_c_mode(0) := counter_mode(clk0_duty_cycle, output_counter_value(i_clk0_div_by, i_clk0_mult_by, i_m, i_n));
|
|
i_c_mode(1) := counter_mode(clk1_duty_cycle, output_counter_value(i_clk1_div_by, i_clk1_mult_by, i_m, i_n));
|
|
i_c_mode(2) := counter_mode(clk2_duty_cycle, output_counter_value(i_clk2_div_by, i_clk2_mult_by, i_m, i_n));
|
|
i_c_mode(3) := counter_mode(clk3_duty_cycle, output_counter_value(i_clk3_div_by, i_clk3_mult_by, i_m, i_n));
|
|
i_c_mode(4) := counter_mode(clk4_duty_cycle, output_counter_value(i_clk4_div_by, i_clk4_mult_by, i_m, i_n));
|
|
|
|
|
|
|
|
else -- m /= 0
|
|
|
|
i_n := n;
|
|
i_m := m;
|
|
i_m_initial := m_initial;
|
|
i_m_ph := m_ph;
|
|
i_c_ph(0) := c0_ph;
|
|
i_c_ph(1) := c1_ph;
|
|
i_c_ph(2) := c2_ph;
|
|
i_c_ph(3) := c3_ph;
|
|
i_c_ph(4) := c4_ph;
|
|
i_c_high(0) := c0_high;
|
|
i_c_high(1) := c1_high;
|
|
i_c_high(2) := c2_high;
|
|
i_c_high(3) := c3_high;
|
|
i_c_high(4) := c4_high;
|
|
i_c_low(0) := c0_low;
|
|
i_c_low(1) := c1_low;
|
|
i_c_low(2) := c2_low;
|
|
i_c_low(3) := c3_low;
|
|
i_c_low(4) := c4_low;
|
|
i_c_initial(0) := c0_initial;
|
|
i_c_initial(1) := c1_initial;
|
|
i_c_initial(2) := c2_initial;
|
|
i_c_initial(3) := c3_initial;
|
|
i_c_initial(4) := c4_initial;
|
|
i_c_mode(0) := translate_string(c0_mode);
|
|
i_c_mode(1) := translate_string(c1_mode);
|
|
i_c_mode(2) := translate_string(c2_mode);
|
|
i_c_mode(3) := translate_string(c3_mode);
|
|
i_c_mode(4) := translate_string(c4_mode);
|
|
|
|
end if; -- user to advanced conversion.
|
|
|
|
m_initial_val <= i_m_initial;
|
|
|
|
if ((compensate_clock = "iqtxrxclk") and (m /= 0)) then
|
|
|
|
case feedback_source is
|
|
when 0 => clk_index := i_clk0_cntr;
|
|
when 1 => clk_index := i_clk1_cntr;
|
|
when 2 => clk_index := i_clk2_cntr;
|
|
when 3 => clk_index := i_clk3_cntr;
|
|
when 4 => clk_index := i_clk4_cntr;
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Invalid feedback_source value (" & int2str(feedback_source) & ")!"
|
|
SEVERITY ERROR;
|
|
end case;
|
|
|
|
if(feedback_external_loop_divider = "true") then
|
|
m_val <= i_m * (i_c_high(clk_index) + i_c_low(clk_index)) * 2;
|
|
m_val_tmp := i_m * (i_c_high(clk_index) + i_c_low(clk_index)) * 2;
|
|
else
|
|
m_val <= i_m * (i_c_high(clk_index) + i_c_low(clk_index));
|
|
m_val_tmp := i_m * (i_c_high(clk_index) + i_c_low(clk_index));
|
|
end if;
|
|
else
|
|
m_val <= i_m;
|
|
m_val_tmp := i_m;
|
|
end if;
|
|
|
|
n_val <= i_n;
|
|
|
|
|
|
if (i_m = 1) then
|
|
m_mode_val <= "bypass";
|
|
else
|
|
m_mode_val <= " ";
|
|
end if;
|
|
if (i_n = 1) then
|
|
n_mode_val <= "bypass";
|
|
else
|
|
n_mode_val <= " ";
|
|
end if;
|
|
|
|
m_ph_val <= i_m_ph;
|
|
m_ph_initial <= i_m_ph;
|
|
|
|
|
|
for i in 0 to 4 loop
|
|
if (i_c_mode(i) = "bypass") then
|
|
if (pll_type = "fast" or pll_type = "lvds" OR (pll_type = "left_right")) then
|
|
i_c_high(i) := 16;
|
|
i_c_low(i) := 16;
|
|
else
|
|
i_c_high(i) := 256;
|
|
i_c_low(i) := 256;
|
|
end if;
|
|
end if;
|
|
c_ph_val(i) <= i_c_ph(i);
|
|
c_initial_val(i) <= i_c_initial(i);
|
|
c_high_val(i) <= i_c_high(i);
|
|
c_low_val(i) <= i_c_low(i);
|
|
c_mode_val(i) <= i_c_mode(i);
|
|
c_high_val_tmp(i) := i_c_high(i);
|
|
c_hval(i) := i_c_high(i);
|
|
c_low_val_tmp(i) := i_c_low(i);
|
|
c_lval(i) := i_c_low(i);
|
|
c_mode_val_tmp(i) := i_c_mode(i);
|
|
c_ph_val_orig(i) <= i_c_ph(i);
|
|
c_high_val_hold(i) <= i_c_high(i);
|
|
c_low_val_hold(i) <= i_c_low(i);
|
|
c_mode_val_hold(i) <= i_c_mode(i);
|
|
end loop;
|
|
|
|
|
|
|
|
scan_chain_length := SCAN_CHAIN;
|
|
|
|
|
|
num_output_cntrs <= 5;
|
|
|
|
init := false;
|
|
elsif (scandone_tmp'EVENT AND scandone_tmp = '1') then
|
|
c0_rising_edge_transfer_done := false;
|
|
c1_rising_edge_transfer_done := false;
|
|
c2_rising_edge_transfer_done := false;
|
|
c3_rising_edge_transfer_done := false;
|
|
c4_rising_edge_transfer_done := false;
|
|
update_conf_latches_reg <= '0';
|
|
elsif (update_conf_latches'event and update_conf_latches = '1') then
|
|
initiate_reconfig <= '1';
|
|
elsif (areset_ipd'event AND areset_ipd = '1') then
|
|
if (scandone_tmp = '0') then scandone_tmp <= '1' ; end if;
|
|
elsif (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
IF (initiate_reconfig = '1') THEN
|
|
initiate_reconfig <= '0';
|
|
ASSERT false REPORT "PLL Reprogramming Initiated" severity note;
|
|
|
|
update_conf_latches_reg <= update_conf_latches;
|
|
reconfig_err <= false;
|
|
scandone_tmp <= '0' AFTER scanclk_period;
|
|
cp_curr_old <= cp_curr_val;
|
|
lfc_old <= lfc_val;
|
|
lfr_old <= lfr_val;
|
|
vco_old <= vco_cur;
|
|
-- LF unused : bit 0,1
|
|
-- LF Capacitance : bits 2,3 : all values are legal
|
|
buf_scan_data := scan_data(2 TO 3);
|
|
|
|
IF ((pll_type = "fast") OR (pll_type = "lvds") OR (pll_type = "left_right")) THEN
|
|
lfc_val <= fpll_loop_filter_c_arr(alt_conv_integer(buf_scan_data));
|
|
ELSE
|
|
lfc_val <= loop_filter_c_arr(alt_conv_integer(buf_scan_data));
|
|
END IF;
|
|
-- LF Resistance : bits 4-8
|
|
-- valid values - 00000,00100,10000,10100,11000,11011,11100,11110
|
|
IF (scan_data(4 TO 8) = "00000") THEN
|
|
lfr_val <= "20";
|
|
ELSIF (scan_data(4 TO 8) = "00100") THEN
|
|
lfr_val <= "16";
|
|
ELSIF (scan_data(4 TO 8) = "10000") THEN
|
|
lfr_val <= "12";
|
|
ELSIF (scan_data(4 TO 8) = "10100") THEN
|
|
lfr_val <= "08";
|
|
ELSIF (scan_data(4 TO 8) = "11000") THEN
|
|
lfr_val <= "06";
|
|
ELSIF (scan_data(4 TO 8) = "11011") THEN
|
|
lfr_val <= "04";
|
|
ELSIF (scan_data(4 TO 8) = "11100") THEN
|
|
lfr_val <= "02";
|
|
ELSE
|
|
lfr_val <= "01";
|
|
END IF;
|
|
|
|
|
|
-- VCO post scale assignment
|
|
if (scan_data(9) = '1') then -- vco_post_scale = 1
|
|
i_vco_max <= vco_max/2;
|
|
i_vco_min <= vco_min/2;
|
|
vco_cur <= 1;
|
|
else
|
|
i_vco_max <= vco_max;
|
|
i_vco_min <= vco_min;
|
|
vco_cur <= 2;
|
|
end if;
|
|
-- CP
|
|
-- Bit 9 : CRBYPASS
|
|
-- Bit 10-14 : unused
|
|
-- Bits 15-17 : all values are legal
|
|
|
|
buf_scan_data_2 := scan_data(15 TO 17);
|
|
cp_curr_val <= charge_pump_curr_arr(alt_conv_integer(buf_scan_data_2));
|
|
-- save old values for display info.
|
|
|
|
cp_curr_val_bit_setting <= scan_data(15 TO 17);
|
|
lfc_val_bit_setting <= scan_data(2 TO 3);
|
|
lfr_val_bit_setting <= scan_data(4 TO 8);
|
|
|
|
m_val_old <= m_val;
|
|
n_val_old <= n_val;
|
|
m_mode_val_old <= m_mode_val;
|
|
n_mode_val_old <= n_mode_val;
|
|
WHILE (i < num_output_cntrs) LOOP
|
|
c_high_val_old(i) <= c_high_val(i);
|
|
c_low_val_old(i) <= c_low_val(i);
|
|
c_mode_val_old(i) <= c_mode_val(i);
|
|
i := i + 1;
|
|
END LOOP;
|
|
-- M counter
|
|
-- 1. Mode - bypass (bit 18)
|
|
|
|
IF (scan_data(18) = '1') THEN
|
|
n_mode_val <= "bypass";
|
|
-- 3. Mode - odd/even (bit 27)
|
|
ELSIF (scan_data(27) = '1') THEN
|
|
n_mode_val <= " odd";
|
|
ELSE
|
|
n_mode_val <= " even";
|
|
END IF;
|
|
|
|
-- 2. High (bit 19-26)
|
|
|
|
n_hi := scan_data(19 TO 26);
|
|
|
|
-- 4. Low (bit 28-35)
|
|
|
|
n_lo := scan_data(28 TO 35);
|
|
-- N counter
|
|
-- 1. Mode - bypass (bit 36)
|
|
|
|
IF (scan_data(36) = '1') THEN
|
|
m_mode_val <= "bypass";
|
|
-- 3. Mode - odd/even (bit 45)
|
|
ELSIF (scan_data(45) = '1') THEN
|
|
m_mode_val <= " odd";
|
|
ELSE
|
|
m_mode_val <= " even";
|
|
END IF;
|
|
|
|
-- 2. High (bit 37-44)
|
|
|
|
m_hi := scan_data(37 TO 44);
|
|
|
|
-- 4. Low (bit 46-53)
|
|
|
|
m_lo := scan_data(46 TO 53);
|
|
-- C counters (start bit 54) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low
|
|
|
|
i := 0;
|
|
WHILE (i < num_output_cntrs) LOOP
|
|
-- 1. Mode - bypass
|
|
|
|
IF (scan_data(54 + i * 18 + 0) = '1') THEN
|
|
c_mode_val_tmp(i) := "bypass";
|
|
-- 3. Mode - odd/even
|
|
ELSIF (scan_data(54 + i * 18 + 9) = '1') THEN
|
|
c_mode_val_tmp(i) := " odd";
|
|
ELSE
|
|
c_mode_val_tmp(i) := " even";
|
|
END IF;
|
|
-- 2. Hi
|
|
|
|
high := scan_data(54 + i * 18 + 1 TO 54 + i * 18 + 8);
|
|
c_hval(i) := alt_conv_integer(high);
|
|
IF (c_hval(i) /= 0) THEN
|
|
c_high_val_tmp(i) := c_hval(i);
|
|
ELSE
|
|
c_high_val_tmp(i) := alt_conv_integer("000000001");
|
|
END IF;
|
|
|
|
-- 4. Low
|
|
|
|
low := scan_data(54 + i * 18 + 10 TO 54 + i * 18 + 17);
|
|
c_lval(i) := alt_conv_integer(low);
|
|
IF (c_lval(i) /= 0) THEN
|
|
c_low_val_tmp(i) := c_lval(i);
|
|
ELSE
|
|
c_low_val_tmp(i) := alt_conv_integer("000000001");
|
|
END IF;
|
|
i := i + 1;
|
|
END LOOP;
|
|
-- Legality Checks
|
|
|
|
-- M counter value
|
|
IF(scan_data(36) /= '1') THEN
|
|
IF ((m_hi /= m_lo) and (scan_data(45) /= '1')) THEN
|
|
reconfig_err <= TRUE;
|
|
WRITE(buf,string'("Warning : The M counter of the " & family_name & " Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work"));
|
|
writeline(output, buf);
|
|
ELSIF (m_hi /= "00000000") THEN
|
|
m_val_tmp := alt_conv_integer(m_hi) + alt_conv_integer(m_lo);
|
|
ELSE
|
|
m_val_tmp := alt_conv_integer("000000001");
|
|
END IF;
|
|
ELSE
|
|
m_val_tmp := alt_conv_integer("10000000");
|
|
END IF;
|
|
-- N counter value
|
|
IF(scan_data(18) /= '1') THEN
|
|
IF ((n_hi /= n_lo)and (scan_data(27) /= '1')) THEN
|
|
reconfig_err <= TRUE;
|
|
WRITE(buf,string'("Warning : The N counter of the " & family_name & " Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work"));
|
|
writeline(output, buf);
|
|
ELSIF (n_hi /= "00000000") THEN
|
|
n_val <= alt_conv_integer(n_hi) + alt_conv_integer(n_lo);
|
|
ELSE
|
|
n_val <= alt_conv_integer("000000001");
|
|
END IF;
|
|
ELSE
|
|
n_val <= alt_conv_integer("10000000");
|
|
END IF;
|
|
-- TODO : Give warnings/errors in the following cases?
|
|
-- 1. Illegal counter values (error)
|
|
-- 2. Change of mode (warning)
|
|
-- 3. Only 50% duty cycle allowed for M counter (odd mode - hi-lo=1,even - hi-lo=0)
|
|
|
|
END IF;
|
|
end if;
|
|
|
|
|
|
if (fbclk'event and fbclk = '1') then
|
|
m_val <= m_val_tmp;
|
|
end if;
|
|
|
|
if (update_conf_latches_reg = '1') then
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c0_rising_edge_transfer_done := true;
|
|
c_high_val(0) <= c_high_val_tmp(0);
|
|
c_mode_val(0) <= c_mode_val_tmp(0);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c1_rising_edge_transfer_done := true;
|
|
c_high_val(1) <= c_high_val_tmp(1);
|
|
c_mode_val(1) <= c_mode_val_tmp(1);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c2_rising_edge_transfer_done := true;
|
|
c_high_val(2) <= c_high_val_tmp(2);
|
|
c_mode_val(2) <= c_mode_val_tmp(2);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(3) <= c_high_val_tmp(3);
|
|
c_mode_val(3) <= c_mode_val_tmp(3);
|
|
c3_rising_edge_transfer_done := true;
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1') then
|
|
c_high_val(4) <= c_high_val_tmp(4);
|
|
c_mode_val(4) <= c_mode_val_tmp(4);
|
|
c4_rising_edge_transfer_done := true;
|
|
end if;
|
|
|
|
|
|
|
|
|
|
|
|
end if;
|
|
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c0_rising_edge_transfer_done) then
|
|
c_low_val(0) <= c_low_val_tmp(0);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c1_rising_edge_transfer_done) then
|
|
c_low_val(1) <= c_low_val_tmp(1);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c2_rising_edge_transfer_done) then
|
|
c_low_val(2) <= c_low_val_tmp(2);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c3_rising_edge_transfer_done) then
|
|
c_low_val(3) <= c_low_val_tmp(3);
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '0' and c4_rising_edge_transfer_done) then
|
|
c_low_val(4) <= c_low_val_tmp(4);
|
|
end if;
|
|
|
|
if (update_phase = '1') then
|
|
if (vco_out(0)'event and vco_out(0) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 0) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 0) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(1)'event and vco_out(1) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 1) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 1) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(2)'event and vco_out(2) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 2) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 2) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(3)'event and vco_out(3) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 3) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 3) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(4)'event and vco_out(4) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 4) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 4) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(5)'event and vco_out(5) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 5) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 5) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(6)'event and vco_out(6) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 6) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 6) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
if (vco_out(7)'event and vco_out(7) = '0') then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 7) then
|
|
c_ph_val(i) <= c_ph_val_tmp(i);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 7) then
|
|
m_ph_val <= m_ph_val_tmp;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
|
|
|
|
if (vco_out(0)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 0) then
|
|
inclk_c_from_vco(i) <= vco_out(0);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 0) then
|
|
inclk_m_from_vco <= vco_out(0);
|
|
end if;
|
|
end if;
|
|
if (vco_out(1)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 1) then
|
|
inclk_c_from_vco(i) <= vco_out(1);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 1) then
|
|
inclk_m_from_vco <= vco_out(1);
|
|
end if;
|
|
end if;
|
|
if (vco_out(2)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 2) then
|
|
inclk_c_from_vco(i) <= vco_out(2);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 2) then
|
|
inclk_m_from_vco <= vco_out(2);
|
|
end if;
|
|
end if;
|
|
if (vco_out(3)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 3) then
|
|
inclk_c_from_vco(i) <= vco_out(3);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 3) then
|
|
inclk_m_from_vco <= vco_out(3);
|
|
end if;
|
|
end if;
|
|
if (vco_out(4)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 4) then
|
|
inclk_c_from_vco(i) <= vco_out(4);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 4) then
|
|
inclk_m_from_vco <= vco_out(4);
|
|
end if;
|
|
end if;
|
|
if (vco_out(5)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 5) then
|
|
inclk_c_from_vco(i) <= vco_out(5);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 5) then
|
|
inclk_m_from_vco <= vco_out(5);
|
|
end if;
|
|
end if;
|
|
if (vco_out(6)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 6) then
|
|
inclk_c_from_vco(i) <= vco_out(6);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 6) then
|
|
inclk_m_from_vco <= vco_out(6);
|
|
end if;
|
|
end if;
|
|
if (vco_out(7)'event) then
|
|
for i in 0 to 4 loop
|
|
if (c_ph_val(i) = 7) then
|
|
inclk_c_from_vco(i) <= vco_out(7);
|
|
end if;
|
|
end loop;
|
|
if (m_ph_val = 7) then
|
|
inclk_m_from_vco <= vco_out(7);
|
|
end if;
|
|
end if;
|
|
|
|
|
|
|
|
|
|
if (scanclk_ipd'event AND scanclk_ipd = '0' AND now > 0 ps) then
|
|
scanclkena_reg <= scanclkena_ipd;
|
|
if (scanclkena_reg = '1') then
|
|
scandata_in <= scandata_ipd;
|
|
scandata_out <= scandataout_tmp;
|
|
end if;
|
|
end if;
|
|
if (scanclk_ipd'event and scanclk_ipd = '1' and now > 0 ps) then
|
|
if (got_first_scanclk) then
|
|
scanclk_period <= now - scanclk_last_rising_edge;
|
|
else
|
|
got_first_scanclk := true;
|
|
end if;
|
|
if (scanclkena_reg = '1') then
|
|
for j in scan_chain_length - 1 downto 1 loop
|
|
scan_data(j) <= scan_data(j-1);
|
|
end loop;
|
|
scan_data(0) <= scandata_in;
|
|
end if;
|
|
scanclk_last_rising_edge := now;
|
|
end if;
|
|
end process;
|
|
|
|
-- PLL Phase Reconfiguration
|
|
|
|
PROCESS(scanclk_ipd, areset_ipd,phasestep_ipd)
|
|
VARIABLE i : INTEGER := 0;
|
|
VARIABLE c_ph : INTEGER := 0;
|
|
VARIABLE m_ph : INTEGER := 0;
|
|
VARIABLE select_counter : INTEGER := 0;
|
|
BEGIN
|
|
IF (NOW = 0 ps) THEN
|
|
m_ph_val_tmp <= m_ph_initial;
|
|
END IF;
|
|
|
|
-- Latch phase enable (same as phasestep) on neg edge of scan clock
|
|
IF (scanclk_ipd'EVENT AND scanclk_ipd = '0') THEN
|
|
phasestep_reg <= phasestep_ipd;
|
|
END IF;
|
|
|
|
IF (phasestep_ipd'EVENT and phasestep_ipd = '1') THEN
|
|
IF (update_phase = '0') THEN
|
|
phasestep_high_count <= 0; -- phase adjustments must be 1 cycle apart
|
|
-- if not, next phasestep cycle is skipped
|
|
END IF;
|
|
END IF;
|
|
-- revert counter phase tap values to POF programmed values
|
|
-- if PLL is reset
|
|
|
|
IF (areset_ipd'EVENT AND areset_ipd = '1') then
|
|
c_ph_val_tmp <= c_ph_val_orig;
|
|
m_ph_val_tmp <= m_ph_initial;
|
|
END IF;
|
|
|
|
IF (scanclk_ipd'EVENT AND scanclk_ipd = '1') THEN
|
|
IF (phasestep_reg = '1') THEN
|
|
IF (phasestep_high_count = 1) THEN
|
|
phasecounterselect_reg <= phasecounterselect_ipd;
|
|
phaseupdown_reg <= phaseupdown_ipd;
|
|
-- start reconfiguration
|
|
IF (phasecounterselect_ipd < "111") THEN -- no counters selected
|
|
IF (phasecounterselect_ipd = "000") THEN
|
|
i := 0;
|
|
WHILE (i < num_output_cntrs) LOOP
|
|
c_ph := c_ph_val(i);
|
|
IF (phaseupdown_ipd = '1') THEN
|
|
c_ph := (c_ph + 1) mod num_phase_taps;
|
|
ELSIF (c_ph = 0) THEN
|
|
c_ph := num_phase_taps - 1;
|
|
ELSE
|
|
c_ph := (c_ph - 1) mod num_phase_taps;
|
|
END IF;
|
|
c_ph_val_tmp(i) <= c_ph;
|
|
i := i + 1;
|
|
END LOOP;
|
|
ELSIF (phasecounterselect_ipd = "001") THEN
|
|
m_ph := m_ph_val;
|
|
IF (phaseupdown_ipd = '1') THEN
|
|
m_ph := (m_ph + 1) mod num_phase_taps;
|
|
ELSIF (m_ph = 0) THEN
|
|
m_ph := num_phase_taps - 1;
|
|
ELSE
|
|
m_ph := (m_ph - 1) mod num_phase_taps;
|
|
END IF;
|
|
m_ph_val_tmp <= m_ph;
|
|
ELSE
|
|
select_counter := alt_conv_integer(phasecounterselect_ipd) - 2;
|
|
c_ph := c_ph_val(select_counter);
|
|
IF (phaseupdown_ipd = '1') THEN
|
|
c_ph := (c_ph + 1) mod num_phase_taps;
|
|
ELSIF (c_ph = 0) THEN
|
|
c_ph := num_phase_taps - 1;
|
|
ELSE
|
|
c_ph := (c_ph - 1) mod num_phase_taps;
|
|
END IF;
|
|
c_ph_val_tmp(select_counter) <= c_ph;
|
|
END IF;
|
|
update_phase <= '1','0' AFTER (0.5 * scanclk_period);
|
|
END IF;
|
|
END IF;
|
|
phasestep_high_count <= phasestep_high_count + 1;
|
|
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
scandataout_tmp <= scan_data(SCAN_CHAIN - 2);
|
|
|
|
process (schedule_vco, areset_ipd, pfdena_ipd, refclk, fbclk)
|
|
variable sched_time : time := 0 ps;
|
|
|
|
TYPE time_array is ARRAY (0 to 7) of time;
|
|
variable init : boolean := true;
|
|
variable refclk_period : time;
|
|
variable m_times_vco_period : time;
|
|
variable new_m_times_vco_period : time;
|
|
|
|
variable phase_shift : time_array := (OTHERS => 0 ps);
|
|
variable last_phase_shift : time_array := (OTHERS => 0 ps);
|
|
|
|
variable l_index : integer := 1;
|
|
variable cycle_to_adjust : integer := 0;
|
|
|
|
variable stop_vco : boolean := false;
|
|
|
|
variable locked_tmp : std_logic := '0';
|
|
variable pll_is_locked : boolean := false;
|
|
variable cycles_pfd_low : integer := 0;
|
|
variable cycles_pfd_high : integer := 0;
|
|
variable cycles_to_lock : integer := 0;
|
|
variable cycles_to_unlock : integer := 0;
|
|
|
|
variable got_first_refclk : boolean := false;
|
|
variable got_second_refclk : boolean := false;
|
|
variable got_first_fbclk : boolean := false;
|
|
|
|
variable refclk_time : time := 0 ps;
|
|
variable fbclk_time : time := 0 ps;
|
|
variable first_fbclk_time : time := 0 ps;
|
|
|
|
variable fbclk_period : time := 0 ps;
|
|
|
|
variable first_schedule : boolean := true;
|
|
|
|
variable vco_val : std_logic := '0';
|
|
variable vco_period_was_phase_adjusted : boolean := false;
|
|
variable phase_adjust_was_scheduled : boolean := false;
|
|
|
|
variable loop_xplier : integer;
|
|
variable loop_initial : integer := 0;
|
|
variable loop_ph : integer := 0;
|
|
variable loop_time_delay : integer := 0;
|
|
|
|
variable initial_delay : time := 0 ps;
|
|
variable vco_per : time;
|
|
variable tmp_rem : integer;
|
|
variable my_rem : integer;
|
|
variable fbk_phase : integer := 0;
|
|
|
|
variable pull_back_M : integer := 0;
|
|
variable total_pull_back : integer := 0;
|
|
variable fbk_delay : integer := 0;
|
|
|
|
variable offset : time := 0 ps;
|
|
|
|
variable tmp_vco_per : integer := 0;
|
|
variable high_time : time;
|
|
variable low_time : time;
|
|
variable time_resolution : time;
|
|
|
|
variable got_refclk_posedge : boolean := false;
|
|
variable got_fbclk_posedge : boolean := false;
|
|
variable inclk_out_of_range : boolean := false;
|
|
variable no_warn : boolean := false;
|
|
|
|
variable ext_fbk_cntr_modulus : integer := 1;
|
|
variable init_clks : boolean := true;
|
|
variable pll_is_in_reset : boolean := false;
|
|
variable buf : line;
|
|
begin
|
|
if (init) then
|
|
|
|
if (lpm_hint = "time_resolution=100fs") then
|
|
time_resolution := 100 fs;
|
|
elsif (lpm_hint = "time_resolution=10fs") then
|
|
time_resolution := 10 fs;
|
|
elsif (lpm_hint = "time_resolution=fs") then
|
|
time_resolution := 1 fs;
|
|
else
|
|
time_resolution := 1 ps;
|
|
end if;
|
|
|
|
-- jump-start the VCO
|
|
-- add 1 ps delay to ensure all signals are updated to initial
|
|
-- values
|
|
schedule_vco <= transport not schedule_vco after 1 ps;
|
|
|
|
init := false;
|
|
end if;
|
|
|
|
if (schedule_vco'event) then
|
|
if (init_clks) then
|
|
refclk_period := inclk0_input_frequency * n_val * 1 ps;
|
|
|
|
m_times_vco_period := refclk_period;
|
|
new_m_times_vco_period := refclk_period;
|
|
init_clks := false;
|
|
end if;
|
|
sched_time := 0 ps;
|
|
for i in 0 to 7 loop
|
|
last_phase_shift(i) := phase_shift(i);
|
|
end loop;
|
|
cycle_to_adjust := 0;
|
|
l_index := 1;
|
|
m_times_vco_period := new_m_times_vco_period;
|
|
end if;
|
|
|
|
-- areset was asserted
|
|
if (areset_ipd'event and areset_ipd = '1') then
|
|
assert false report family_name & " PLL was reset" severity note;
|
|
-- reset lock parameters
|
|
locked_tmp := '0';
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
end if;
|
|
|
|
|
|
if (schedule_vco'event and (areset_ipd = '1' or stop_vco)) then
|
|
|
|
if (areset_ipd = '1') then
|
|
pll_is_in_reset := true;
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
end if;
|
|
|
|
-- drop VCO taps to 0
|
|
for i in 0 to 7 loop
|
|
vco_out(i) <= transport '0' after last_phase_shift(i);
|
|
phase_shift(i) := 0 ps;
|
|
last_phase_shift(i) := 0 ps;
|
|
end loop;
|
|
|
|
-- reset lock parameters
|
|
locked_tmp := '0';
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
refclk_time := 0 ps;
|
|
got_first_fbclk := false;
|
|
fbclk_time := 0 ps;
|
|
first_fbclk_time := 0 ps;
|
|
fbclk_period := 0 ps;
|
|
|
|
first_schedule := true;
|
|
vco_val := '0';
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
|
|
elsif ((schedule_vco'event or areset_ipd'event) and areset_ipd = '0' and (not stop_vco) and now > 0 ps) then
|
|
|
|
-- note areset deassert time
|
|
-- note it as refclk_time to prevent false triggering
|
|
-- of stop_vco after areset
|
|
if (areset_ipd'event and areset_ipd = '0' and pll_is_in_reset) then
|
|
refclk_time := now;
|
|
pll_is_in_reset := false;
|
|
locked_tmp := '0';
|
|
end if;
|
|
|
|
-- calculate loop_xplier : this will be different from m_val
|
|
-- in external_feedback_mode
|
|
loop_xplier := m_val;
|
|
loop_initial := m_initial_val - 1;
|
|
loop_ph := m_ph_val;
|
|
|
|
|
|
-- convert initial value to delay
|
|
initial_delay := (loop_initial * m_times_vco_period)/loop_xplier;
|
|
|
|
-- convert loop ph_tap to delay
|
|
my_rem := (m_times_vco_period/time_resolution) rem loop_xplier;
|
|
tmp_vco_per := (m_times_vco_period/time_resolution) / loop_xplier;
|
|
if (my_rem /= 0) then
|
|
tmp_vco_per := tmp_vco_per + 1;
|
|
end if;
|
|
fbk_phase := (loop_ph * tmp_vco_per)/8;
|
|
|
|
pull_back_M := initial_delay/time_resolution + fbk_phase;
|
|
|
|
total_pull_back := pull_back_M;
|
|
|
|
if (simulation_type = "timing") then
|
|
total_pull_back := total_pull_back + pll_compensation_delay;
|
|
end if;
|
|
while (total_pull_back > refclk_period/time_resolution) loop
|
|
total_pull_back := total_pull_back - refclk_period/time_resolution;
|
|
end loop;
|
|
|
|
if (total_pull_back > 0) then
|
|
offset := refclk_period - (total_pull_back * time_resolution);
|
|
end if;
|
|
|
|
fbk_delay := total_pull_back - fbk_phase;
|
|
if (fbk_delay < 0) then
|
|
offset := offset - (fbk_phase * time_resolution);
|
|
fbk_delay := total_pull_back;
|
|
end if;
|
|
|
|
-- assign m_delay
|
|
m_delay <= transport fbk_delay after time_resolution;
|
|
|
|
my_rem := (m_times_vco_period/time_resolution) rem loop_xplier;
|
|
for i in 1 to loop_xplier loop
|
|
-- adjust cycles
|
|
tmp_vco_per := (m_times_vco_period/time_resolution)/loop_xplier;
|
|
if (my_rem /= 0 and l_index <= my_rem) then
|
|
tmp_rem := (loop_xplier * l_index) rem my_rem;
|
|
cycle_to_adjust := (loop_xplier * l_index) / my_rem;
|
|
if (tmp_rem /= 0) then
|
|
cycle_to_adjust := cycle_to_adjust + 1;
|
|
end if;
|
|
end if;
|
|
if (cycle_to_adjust = i) then
|
|
tmp_vco_per := tmp_vco_per + 1;
|
|
l_index := l_index + 1;
|
|
end if;
|
|
|
|
-- calculate high and low periods
|
|
vco_per := tmp_vco_per * time_resolution;
|
|
high_time := (tmp_vco_per/2) * time_resolution;
|
|
if (tmp_vco_per rem 2 /= 0) then
|
|
high_time := high_time + time_resolution;
|
|
end if;
|
|
low_time := vco_per - high_time;
|
|
|
|
-- schedule the rising and falling edges
|
|
for j in 1 to 2 loop
|
|
vco_val := not vco_val;
|
|
if (vco_val = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (vco_val = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
|
|
-- schedule the phase taps
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
if (first_schedule) then
|
|
vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
|
|
else
|
|
vco_out(k) <= transport vco_val after (sched_time + last_phase_shift(k));
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
end loop;
|
|
|
|
-- schedule once more
|
|
if (first_schedule) then
|
|
vco_val := not vco_val;
|
|
if (vco_val = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (vco_val = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
-- schedule the phase taps
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
|
|
end loop;
|
|
first_schedule := false;
|
|
end if;
|
|
|
|
schedule_vco <= transport not schedule_vco after sched_time;
|
|
|
|
if (vco_period_was_phase_adjusted) then
|
|
m_times_vco_period := refclk_period;
|
|
new_m_times_vco_period := refclk_period;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := true;
|
|
|
|
vco_per := m_times_vco_period/loop_xplier;
|
|
for k in 0 to 7 loop
|
|
phase_shift(k) := (k * vco_per)/8;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
-- Bypass lock detect
|
|
|
|
if (refclk'event and refclk = '1' and areset_ipd = '0') then
|
|
if (test_bypass_lock_detect = "on") then
|
|
if (pfdena_ipd = '1') then
|
|
cycles_pfd_low := 0;
|
|
if (pfd_locked = '0') then
|
|
if (cycles_pfd_high = lock_high) then
|
|
assert false report family_name & " PLL locked in test mode on PFD enable assertion." severity warning;
|
|
pfd_locked <= '1';
|
|
end if;
|
|
cycles_pfd_high := cycles_pfd_high + 1;
|
|
end if;
|
|
end if;
|
|
|
|
if (pfdena_ipd = '0') then
|
|
cycles_pfd_high := 0;
|
|
if (pfd_locked = '1') then
|
|
if (cycles_pfd_low = lock_low) then
|
|
assert false report family_name & " PLL lost lock in test mode on PFD enable de-assertion." severity warning;
|
|
pfd_locked <= '0';
|
|
end if;
|
|
cycles_pfd_low := cycles_pfd_low + 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
|
|
if (refclk'event and refclk = '1' and areset_ipd = '0') then
|
|
got_refclk_posedge := true;
|
|
if (not got_first_refclk) then
|
|
got_first_refclk := true;
|
|
else
|
|
got_second_refclk := true;
|
|
refclk_period := now - refclk_time;
|
|
|
|
-- check if incoming freq. will cause VCO range to be
|
|
-- exceeded
|
|
if ( (i_vco_max /= 0 and i_vco_min /= 0 and pfdena_ipd = '1') and
|
|
(((refclk_period/1 ps)/loop_xplier > i_vco_max) or
|
|
((refclk_period/1 ps)/loop_xplier < i_vco_min)) ) then
|
|
if (pll_is_locked) then
|
|
if ((refclk_period/1 ps)/loop_xplier > i_vco_max) then
|
|
assert false report "Input clock freq. is over VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_over <= '1';
|
|
end if;
|
|
if ((refclk_period/1 ps)/loop_xplier < i_vco_min) then
|
|
assert false report "Input clock freq. is under VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_under <= '1';
|
|
end if;
|
|
if (inclk_out_of_range) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
cycles_to_lock := 0;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
assert false report family_name & " PLL lost lock." severity note;
|
|
end if;
|
|
elsif (not no_warn) then
|
|
if ((refclk_period/1 ps)/loop_xplier > i_vco_max) then
|
|
assert false report "Input clock freq. is over VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_over <= '1';
|
|
end if;
|
|
if ((refclk_period/1 ps)/loop_xplier < i_vco_min) then
|
|
assert false report "Input clock freq. is under VCO range. " & family_name & " PLL may lose lock" severity warning;
|
|
vco_under <= '1';
|
|
end if;
|
|
assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may not lock. Please use the correct frequency." severity warning;
|
|
no_warn := true;
|
|
end if;
|
|
inclk_out_of_range := true;
|
|
else
|
|
vco_over <= '0';
|
|
vco_under <= '0';
|
|
inclk_out_of_range := false;
|
|
no_warn := false;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (stop_vco) then
|
|
stop_vco := false;
|
|
schedule_vco <= not schedule_vco;
|
|
end if;
|
|
|
|
refclk_time := now;
|
|
else
|
|
got_refclk_posedge := false;
|
|
end if;
|
|
|
|
-- Update M counter value on feedback clock edge
|
|
|
|
if (fbclk'event and fbclk = '1') then
|
|
got_fbclk_posedge := true;
|
|
if (not got_first_fbclk) then
|
|
got_first_fbclk := true;
|
|
else
|
|
fbclk_period := now - fbclk_time;
|
|
end if;
|
|
|
|
-- need refclk_period here, so initialized to proper value above
|
|
if ( ( (now - refclk_time > 1.5 * refclk_period) and pfdena_ipd = '1' and pll_is_locked) or
|
|
( (now - refclk_time > 5 * refclk_period) and pfdena_ipd = '1' and pll_has_just_been_reconfigured = false) or
|
|
( (now - refclk_time > 50 * refclk_period) and pfdena_ipd = '1' and pll_has_just_been_reconfigured = true) ) then
|
|
stop_vco := true;
|
|
-- reset
|
|
got_first_refclk := false;
|
|
got_first_fbclk := false;
|
|
got_second_refclk := false;
|
|
if (pll_is_locked) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
assert false report family_name & " PLL lost lock due to loss of input clock or the input clock is not detected within the allowed time frame." severity note;
|
|
if ((i_vco_max = 0) and (i_vco_min = 0)) then
|
|
assert false report "Please run timing simulation to check whether the input clock is operating within the supported VCO range or not." severity note;
|
|
end if;
|
|
end if;
|
|
cycles_to_lock := 0;
|
|
cycles_to_unlock := 0;
|
|
first_schedule := true;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
end if;
|
|
fbclk_time := now;
|
|
else
|
|
got_fbclk_posedge := false;
|
|
end if;
|
|
|
|
if ((got_refclk_posedge or got_fbclk_posedge) and got_second_refclk and pfdena_ipd = '1' and (not inclk_out_of_range)) then
|
|
|
|
-- now we know actual incoming period
|
|
if ( abs(fbclk_time - refclk_time) <= 5 ps or
|
|
(got_first_fbclk and abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
|
|
-- considered in phase
|
|
if (cycles_to_lock = real_lock_high) then
|
|
if (not pll_is_locked) then
|
|
assert false report family_name & " PLL locked to incoming clock" severity note;
|
|
end if;
|
|
pll_is_locked := true;
|
|
locked_tmp := '1';
|
|
cycles_to_unlock := 0;
|
|
end if;
|
|
-- increment lock counter only if second part of above
|
|
-- time check is NOT true
|
|
if (not(abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window)) then
|
|
cycles_to_lock := cycles_to_lock + 1;
|
|
end if;
|
|
|
|
-- adjust m_times_vco_period
|
|
new_m_times_vco_period := refclk_period;
|
|
else
|
|
-- if locked, begin unlock
|
|
if (pll_is_locked) then
|
|
cycles_to_unlock := cycles_to_unlock + 1;
|
|
if (cycles_to_unlock = lock_low) then
|
|
pll_is_locked := false;
|
|
locked_tmp := '0';
|
|
cycles_to_lock := 0;
|
|
vco_period_was_phase_adjusted := false;
|
|
phase_adjust_was_scheduled := false;
|
|
assert false report family_name & " PLL lost lock." severity note;
|
|
got_first_refclk := false;
|
|
got_first_fbclk := false;
|
|
got_second_refclk := false;
|
|
end if;
|
|
end if;
|
|
if ( abs(refclk_period - fbclk_period) <= 2 ps ) then
|
|
-- frequency is still good
|
|
if (now = fbclk_time and (not phase_adjust_was_scheduled)) then
|
|
if ( abs(fbclk_time - refclk_time) > refclk_period/2) then
|
|
new_m_times_vco_period := m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time));
|
|
vco_period_was_phase_adjusted := true;
|
|
else
|
|
new_m_times_vco_period := m_times_vco_period - abs(fbclk_time - refclk_time);
|
|
vco_period_was_phase_adjusted := true;
|
|
end if;
|
|
|
|
end if;
|
|
else
|
|
phase_adjust_was_scheduled := false;
|
|
new_m_times_vco_period := refclk_period;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (pfdena_ipd = '0') then
|
|
if (pll_is_locked) then
|
|
locked_tmp := 'X';
|
|
end if;
|
|
pll_is_locked := false;
|
|
cycles_to_lock := 0;
|
|
end if;
|
|
|
|
-- give message only at time of deassertion
|
|
if (pfdena_ipd'event and pfdena_ipd = '0') then
|
|
assert false report "PFDENA deasserted." severity note;
|
|
elsif (pfdena_ipd'event and pfdena_ipd = '1') then
|
|
got_first_refclk := false;
|
|
got_second_refclk := false;
|
|
refclk_time := now;
|
|
end if;
|
|
|
|
if (reconfig_err) then
|
|
lock <= '0';
|
|
else
|
|
lock <= locked_tmp;
|
|
end if;
|
|
|
|
-- signal to calculate quiet_time
|
|
sig_refclk_period <= refclk_period;
|
|
|
|
if (stop_vco = true) then
|
|
sig_stop_vco <= '1';
|
|
else
|
|
sig_stop_vco <= '0';
|
|
end if;
|
|
|
|
pll_locked <= pll_is_locked;
|
|
end process;
|
|
|
|
clk0_tmp <= c_clk(i_clk0_counter);
|
|
clk_pfd(0) <= clk0_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(0) <= clk_pfd(0) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk0_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else
|
|
'X';
|
|
|
|
clk1_tmp <= c_clk(i_clk1_counter);
|
|
clk_pfd(1) <= clk1_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(1) <= clk_pfd(1) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk1_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
clk2_tmp <= c_clk(i_clk2_counter);
|
|
clk_pfd(2) <= clk2_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(2) <= clk_pfd(2) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk2_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
clk3_tmp <= c_clk(i_clk3_counter);
|
|
clk_pfd(3) <= clk3_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(3) <= clk_pfd(3) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk3_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
clk4_tmp <= c_clk(i_clk4_counter);
|
|
clk_pfd(4) <= clk4_tmp WHEN (pfd_locked = '1') ELSE 'X';
|
|
clk(4) <= clk_pfd(4) WHEN (test_bypass_lock_detect = "on") ELSE
|
|
clk4_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';
|
|
|
|
scandataout <= scandata_out;
|
|
scandone <= NOT scandone_tmp;
|
|
phasedone <= NOT update_phase;
|
|
vcooverrange <= 'Z' WHEN (vco_range_detector_high_bits = -1) ELSE vco_over;
|
|
vcounderrange <= 'Z' WHEN (vco_range_detector_low_bits = -1) ELSE vco_under;
|
|
fbout <= fbclk;
|
|
fref <= refclk;
|
|
icdrclk <= icdr_clk;
|
|
end vital_pll;
|
|
-- END ARCHITECTURE VITAL_PLL
|
|
|
|
-- START ENTITY HEADER ---------------------------------------------------------
|
|
--
|
|
-- Entity Name : ALTPLL
|
|
--
|
|
-- Description : Phase-Locked Loop (PLL) behavioral model. Model supports
|
|
-- basic PLL features such as clock division and
|
|
-- multiplication, programmable duty cycle and phase shifts,
|
|
-- various feedback modes and clock delays. Also supports
|
|
-- real-time reconfiguration of PLL "parameters" and clock
|
|
-- switchover between the 2 input reference clocks.
|
|
-- Up to 10 clock outputs may be used.
|
|
--
|
|
-- Limitations : Applicable to Stratix, Stratix-GX, Stratix II and Cyclone II
|
|
-- device families only. There is no support in the model for
|
|
-- spread-spectrum feature.
|
|
--
|
|
-- Expected results : Up to 10 different output clocks, each defined by its own
|
|
-- parameters. Locked output (active high) indicates when
|
|
-- the PLL locks. clkbad, clkloss and activeclock highlights
|
|
-- which clock has gone bad, when clock switchover initiates,
|
|
-- and which input clock (0 or 1) is the reference clock,
|
|
-- respectively. scandataout is the data output of the serial
|
|
-- scan chain.
|
|
--
|
|
-- END ENTITY HEADER -----------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
use work.MF_stratix_pll;
|
|
use work.MF_stratixii_pll;
|
|
use work.MF_stratixiii_pll;
|
|
use work.MF_cycloneiii_pll;
|
|
use work.MF_cycloneiiigl_pll;
|
|
use work.pll_iobuf;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altpll is
|
|
generic (
|
|
intended_device_family : string := "Stratix" ;
|
|
operation_mode : string := "NORMAL" ;
|
|
pll_type : string := "AUTO" ;
|
|
qualify_conf_done : string := "OFF" ;
|
|
compensate_clock : string := "CLK0" ;
|
|
scan_chain : string := "LONG";
|
|
primary_clock : string := "inclk0" ;
|
|
inclk0_input_frequency : natural; -- required parameter
|
|
inclk1_input_frequency : natural := 0;
|
|
gate_lock_signal : string := "NO";
|
|
gate_lock_counter : integer := 0;
|
|
lock_high : natural := 1;
|
|
lock_low : natural := 0;
|
|
valid_lock_multiplier : natural := 1;
|
|
invalid_lock_multiplier : natural := 5;
|
|
switch_over_type : string := "AUTO" ;
|
|
switch_over_on_lossclk : string := "OFF" ;
|
|
switch_over_on_gated_lock : string := "OFF" ;
|
|
enable_switch_over_counter : string := "OFF";
|
|
switch_over_counter : natural := 0;
|
|
feedback_source : string := "EXTCLK0" ;
|
|
bandwidth : natural := 0;
|
|
bandwidth_type : string := "UNUSED";
|
|
lpm_hint : string := "UNUSED";
|
|
spread_frequency : natural := 0;
|
|
down_spread : string := "0.0";
|
|
self_reset_on_gated_loss_lock : string := "OFF";
|
|
self_reset_on_loss_lock : string := "OFF";
|
|
lock_window_ui : string := "0.05";
|
|
width_clock : natural := 6;
|
|
width_phasecounterselect : natural := 4;
|
|
using_fbmimicbidir_port : string := "ON";
|
|
charge_pump_current_bits : natural := 9999;
|
|
loop_filter_c_bits : natural := 9999;
|
|
loop_filter_r_bits : natural := 9999;
|
|
scan_chain_mif_file : string := "UNUSED";
|
|
|
|
-- simulation-only parameters
|
|
simulation_type : string := "functional";
|
|
source_is_pll : string := "off";
|
|
skip_vco : string := "off";
|
|
-- internal clock (i.e. clock that feeds the core) specifications
|
|
clk9_multiply_by : natural := 1;
|
|
clk8_multiply_by : natural := 1;
|
|
clk7_multiply_by : natural := 1;
|
|
clk6_multiply_by : natural := 1;
|
|
clk5_multiply_by : natural := 1;
|
|
clk4_multiply_by : natural := 1;
|
|
clk3_multiply_by : natural := 1;
|
|
clk2_multiply_by : natural := 1;
|
|
clk1_multiply_by : natural := 1;
|
|
clk0_multiply_by : natural := 1;
|
|
clk9_divide_by : natural := 1;
|
|
clk8_divide_by : natural := 1;
|
|
clk7_divide_by : natural := 1;
|
|
clk6_divide_by : natural := 1;
|
|
clk5_divide_by : natural := 1;
|
|
clk4_divide_by : natural := 1;
|
|
clk3_divide_by : natural := 1;
|
|
clk2_divide_by : natural := 1;
|
|
clk1_divide_by : natural := 1;
|
|
clk0_divide_by : natural := 1;
|
|
clk9_phase_shift : string := "0";
|
|
clk8_phase_shift : string := "0";
|
|
clk7_phase_shift : string := "0";
|
|
clk6_phase_shift : string := "0";
|
|
clk5_phase_shift : string := "0";
|
|
clk4_phase_shift : string := "0";
|
|
clk3_phase_shift : string := "0";
|
|
clk2_phase_shift : string := "0";
|
|
clk1_phase_shift : string := "0";
|
|
clk0_phase_shift : string := "0";
|
|
clk5_time_delay : string := "0";
|
|
clk4_time_delay : string := "0";
|
|
clk3_time_delay : string := "0";
|
|
clk2_time_delay : string := "0";
|
|
clk1_time_delay : string := "0";
|
|
clk0_time_delay : string := "0";
|
|
clk9_duty_cycle : natural := 50;
|
|
clk8_duty_cycle : natural := 50;
|
|
clk7_duty_cycle : natural := 50;
|
|
clk6_duty_cycle : natural := 50;
|
|
clk5_duty_cycle : natural := 50;
|
|
clk4_duty_cycle : natural := 50;
|
|
clk3_duty_cycle : natural := 50;
|
|
clk2_duty_cycle : natural := 50;
|
|
clk1_duty_cycle : natural := 50;
|
|
clk0_duty_cycle : natural := 50;
|
|
clk9_use_even_counter_mode : string := "OFF";
|
|
clk8_use_even_counter_mode : string := "OFF";
|
|
clk7_use_even_counter_mode : string := "OFF";
|
|
clk6_use_even_counter_mode : string := "OFF";
|
|
clk5_use_even_counter_mode : string := "OFF";
|
|
clk4_use_even_counter_mode : string := "OFF";
|
|
clk3_use_even_counter_mode : string := "OFF";
|
|
clk2_use_even_counter_mode : string := "OFF";
|
|
clk1_use_even_counter_mode : string := "OFF";
|
|
clk0_use_even_counter_mode : string := "OFF";
|
|
clk9_use_even_counter_value : string := "OFF";
|
|
clk8_use_even_counter_value : string := "OFF";
|
|
clk7_use_even_counter_value : string := "OFF";
|
|
clk6_use_even_counter_value : string := "OFF";
|
|
clk5_use_even_counter_value : string := "OFF";
|
|
clk4_use_even_counter_value : string := "OFF";
|
|
clk3_use_even_counter_value : string := "OFF";
|
|
clk2_use_even_counter_value : string := "OFF";
|
|
clk1_use_even_counter_value : string := "OFF";
|
|
clk0_use_even_counter_value : string := "OFF";
|
|
|
|
clk2_output_frequency : natural := 0;
|
|
clk1_output_frequency : natural := 0;
|
|
clk0_output_frequency : natural := 0;
|
|
|
|
-- external clock (i.e. clock that feeds pins) specifications
|
|
extclk3_multiply_by : natural := 1;
|
|
extclk2_multiply_by : natural := 1;
|
|
extclk1_multiply_by : natural := 1;
|
|
extclk0_multiply_by : natural := 1;
|
|
extclk3_divide_by : natural := 1;
|
|
extclk2_divide_by : natural := 1;
|
|
extclk1_divide_by : natural := 1;
|
|
extclk0_divide_by : natural := 1;
|
|
extclk3_phase_shift : string := "0";
|
|
extclk2_phase_shift : string := "0";
|
|
extclk1_phase_shift : string := "0";
|
|
extclk0_phase_shift : string := "0";
|
|
extclk3_time_delay : string := "0";
|
|
extclk2_time_delay : string := "0";
|
|
extclk1_time_delay : string := "0";
|
|
extclk0_time_delay : string := "0";
|
|
extclk3_duty_cycle : natural := 50;
|
|
extclk2_duty_cycle : natural := 50;
|
|
extclk1_duty_cycle : natural := 50;
|
|
extclk0_duty_cycle : natural := 50;
|
|
|
|
-- The following 4 parameters are for Stratix II pll in lvds mode only
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
sclkout0_phase_shift : string := "0";
|
|
sclkout1_phase_shift : string := "0";
|
|
|
|
dpa_multiply_by : integer := 0;
|
|
dpa_divide_by : integer := 0;
|
|
dpa_divider : integer := 0;
|
|
|
|
|
|
-- advanced user parameters
|
|
vco_min : natural := 0;
|
|
vco_max : natural := 0;
|
|
vco_center : natural := 0;
|
|
pfd_min : natural := 0;
|
|
pfd_max : natural := 0;
|
|
m_initial : natural := 1;
|
|
m : natural := 0; -- m must default to 0 to force altpll to calculate the internal parameters for itself
|
|
n : natural := 1;
|
|
m2 : natural := 1;
|
|
n2 : natural := 1;
|
|
ss : natural := 0;
|
|
c0_high : natural := 1;
|
|
c1_high : natural := 1;
|
|
c2_high : natural := 1;
|
|
c3_high : natural := 1;
|
|
c4_high : natural := 1;
|
|
c5_high : natural := 1;
|
|
c6_high : natural := 1;
|
|
c7_high : natural := 1;
|
|
c8_high : natural := 1;
|
|
c9_high : natural := 1;
|
|
l0_high : natural := 1;
|
|
l1_high : natural := 1;
|
|
g0_high : natural := 1;
|
|
g1_high : natural := 1;
|
|
g2_high : natural := 1;
|
|
g3_high : natural := 1;
|
|
e0_high : natural := 1;
|
|
e1_high : natural := 1;
|
|
e2_high : natural := 1;
|
|
e3_high : natural := 1;
|
|
c0_low : natural := 1;
|
|
c1_low : natural := 1;
|
|
c2_low : natural := 1;
|
|
c3_low : natural := 1;
|
|
c4_low : natural := 1;
|
|
c5_low : natural := 1;
|
|
c6_low : natural := 1;
|
|
c7_low : natural := 1;
|
|
c8_low : natural := 1;
|
|
c9_low : natural := 1;
|
|
l0_low : natural := 1;
|
|
l1_low : natural := 1;
|
|
g0_low : natural := 1;
|
|
g1_low : natural := 1;
|
|
g2_low : natural := 1;
|
|
g3_low : natural := 1;
|
|
e0_low : natural := 1;
|
|
e1_low : natural := 1;
|
|
e2_low : natural := 1;
|
|
e3_low : natural := 1;
|
|
c0_initial : natural := 1;
|
|
c1_initial : natural := 1;
|
|
c2_initial : natural := 1;
|
|
c3_initial : natural := 1;
|
|
c4_initial : natural := 1;
|
|
c5_initial : natural := 1;
|
|
c6_initial : natural := 1;
|
|
c7_initial : natural := 1;
|
|
c8_initial : natural := 1;
|
|
c9_initial : natural := 1;
|
|
l0_initial : natural := 1;
|
|
l1_initial : natural := 1;
|
|
g0_initial : natural := 1;
|
|
g1_initial : natural := 1;
|
|
g2_initial : natural := 1;
|
|
g3_initial : natural := 1;
|
|
e0_initial : natural := 1;
|
|
e1_initial : natural := 1;
|
|
e2_initial : natural := 1;
|
|
e3_initial : natural := 1;
|
|
c0_mode : string := "bypass" ;
|
|
c1_mode : string := "bypass" ;
|
|
c2_mode : string := "bypass" ;
|
|
c3_mode : string := "bypass" ;
|
|
c4_mode : string := "bypass" ;
|
|
c5_mode : string := "bypass" ;
|
|
c6_mode : string := "bypass" ;
|
|
c7_mode : string := "bypass" ;
|
|
c8_mode : string := "bypass" ;
|
|
c9_mode : string := "bypass" ;
|
|
l0_mode : string := "bypass" ;
|
|
l1_mode : string := "bypass" ;
|
|
g0_mode : string := "bypass" ;
|
|
g1_mode : string := "bypass" ;
|
|
g2_mode : string := "bypass" ;
|
|
g3_mode : string := "bypass" ;
|
|
e0_mode : string := "bypass" ;
|
|
e1_mode : string := "bypass" ;
|
|
e2_mode : string := "bypass" ;
|
|
e3_mode : string := "bypass" ;
|
|
c0_ph : natural := 0;
|
|
c1_ph : natural := 0;
|
|
c2_ph : natural := 0;
|
|
c3_ph : natural := 0;
|
|
c4_ph : natural := 0;
|
|
c5_ph : natural := 0;
|
|
c6_ph : natural := 0;
|
|
c7_ph : natural := 0;
|
|
c8_ph : natural := 0;
|
|
c9_ph : natural := 0;
|
|
l0_ph : natural := 0;
|
|
l1_ph : natural := 0;
|
|
g0_ph : natural := 0;
|
|
g1_ph : natural := 0;
|
|
g2_ph : natural := 0;
|
|
g3_ph : natural := 0;
|
|
e0_ph : natural := 0;
|
|
e1_ph : natural := 0;
|
|
e2_ph : natural := 0;
|
|
e3_ph : natural := 0;
|
|
m_ph : natural := 0;
|
|
l0_time_delay : natural := 0;
|
|
l1_time_delay : natural := 0;
|
|
g0_time_delay : natural := 0;
|
|
g1_time_delay : natural := 0;
|
|
g2_time_delay : natural := 0;
|
|
g3_time_delay : natural := 0;
|
|
e0_time_delay : natural := 0;
|
|
e1_time_delay : natural := 0;
|
|
e2_time_delay : natural := 0;
|
|
e3_time_delay : natural := 0;
|
|
m_time_delay : natural := 0;
|
|
n_time_delay : natural := 0;
|
|
c1_use_casc_in : string := "off";
|
|
c2_use_casc_in : string := "off";
|
|
c3_use_casc_in : string := "off";
|
|
c4_use_casc_in : string := "off";
|
|
c5_use_casc_in : string := "off";
|
|
c6_use_casc_in : string := "off";
|
|
c7_use_casc_in : string := "off";
|
|
c8_use_casc_in : string := "off";
|
|
c9_use_casc_in : string := "off";
|
|
extclk3_counter : string := "e3" ;
|
|
extclk2_counter : string := "e2" ;
|
|
extclk1_counter : string := "e1" ;
|
|
extclk0_counter : string := "e0" ;
|
|
clk9_counter : string := "c9" ;
|
|
clk8_counter : string := "c8" ;
|
|
clk7_counter : string := "c7" ;
|
|
clk6_counter : string := "c6" ;
|
|
clk5_counter : string := "l1" ;
|
|
clk4_counter : string := "l0" ;
|
|
clk3_counter : string := "g3" ;
|
|
clk2_counter : string := "g2" ;
|
|
clk1_counter : string := "g1" ;
|
|
clk0_counter : string := "g0" ;
|
|
enable0_counter : string := "l0";
|
|
enable1_counter : string := "l0";
|
|
charge_pump_current : natural := 2;
|
|
loop_filter_r : string := " 1.000000";
|
|
loop_filter_c : natural := 5;
|
|
vco_post_scale : natural := 0;
|
|
vco_frequency_control : string := "AUTO";
|
|
vco_phase_shift_step : natural := 0;
|
|
|
|
m_test_source : integer := 5;
|
|
c0_test_source : integer := 5;
|
|
c1_test_source : integer := 5;
|
|
c2_test_source : integer := 5;
|
|
c3_test_source : integer := 5;
|
|
c4_test_source : integer := 5;
|
|
c5_test_source : integer := 5;
|
|
c6_test_source : integer := 5;
|
|
c7_test_source : integer := 5;
|
|
c8_test_source : integer := 5;
|
|
c9_test_source : integer := 5;
|
|
sim_gate_lock_device_behavior : string := "OFF";
|
|
lpm_type : string := "altpll";
|
|
|
|
-- The following parameter are used to define the connectivity for some
|
|
-- of the input and output ports.
|
|
port_clkena0 : string := "PORT_CONNECTIVITY";
|
|
port_clkena1 : string := "PORT_CONNECTIVITY";
|
|
port_clkena2 : string := "PORT_CONNECTIVITY";
|
|
port_clkena3 : string := "PORT_CONNECTIVITY";
|
|
port_clkena4 : string := "PORT_CONNECTIVITY";
|
|
port_clkena5 : string := "PORT_CONNECTIVITY";
|
|
port_extclkena0 : string := "PORT_CONNECTIVITY";
|
|
port_extclkena1 : string := "PORT_CONNECTIVITY";
|
|
port_extclkena2 : string := "PORT_CONNECTIVITY";
|
|
port_extclkena3 : string := "PORT_CONNECTIVITY";
|
|
port_extclk0 : string := "PORT_CONNECTIVITY";
|
|
port_extclk1 : string := "PORT_CONNECTIVITY";
|
|
port_extclk2 : string := "PORT_CONNECTIVITY";
|
|
port_extclk3 : string := "PORT_CONNECTIVITY";
|
|
port_clk0 : string := "PORT_CONNECTIVITY";
|
|
port_clk1 : string := "PORT_CONNECTIVITY";
|
|
port_clk2 : string := "PORT_CONNECTIVITY";
|
|
port_clk3 : string := "PORT_CONNECTIVITY";
|
|
port_clk4 : string := "PORT_CONNECTIVITY";
|
|
port_clk5 : string := "PORT_CONNECTIVITY";
|
|
port_clk6 : string := "PORT_CONNECTIVITY";
|
|
port_clk7 : string := "PORT_CONNECTIVITY";
|
|
port_clk8 : string := "PORT_CONNECTIVITY";
|
|
port_clk9 : string := "PORT_CONNECTIVITY";
|
|
port_scandata : string := "PORT_CONNECTIVITY";
|
|
port_scandataout : string := "PORT_CONNECTIVITY";
|
|
port_scandone : string := "PORT_CONNECTIVITY";
|
|
port_sclkout1 : string := "PORT_CONNECTIVITY";
|
|
port_sclkout0 : string := "PORT_CONNECTIVITY";
|
|
port_clkbad0 : string := "PORT_CONNECTIVITY";
|
|
port_clkbad1 : string := "PORT_CONNECTIVITY";
|
|
port_activeclock : string := "PORT_CONNECTIVITY";
|
|
port_clkloss : string := "PORT_CONNECTIVITY";
|
|
port_inclk1 : string := "PORT_CONNECTIVITY";
|
|
port_inclk0 : string := "PORT_CONNECTIVITY";
|
|
port_fbin : string := "PORT_CONNECTIVITY";
|
|
port_fbout : string := "PORT_CONNECTIVITY";
|
|
port_pllena : string := "PORT_CONNECTIVITY";
|
|
port_clkswitch : string := "PORT_CONNECTIVITY";
|
|
port_areset : string := "PORT_CONNECTIVITY";
|
|
port_pfdena : string := "PORT_CONNECTIVITY";
|
|
port_scanclk : string := "PORT_CONNECTIVITY";
|
|
port_scanaclr : string := "PORT_CONNECTIVITY";
|
|
port_scanread : string := "PORT_CONNECTIVITY";
|
|
port_scanwrite : string := "PORT_CONNECTIVITY";
|
|
port_enable0 : string := "PORT_CONNECTIVITY";
|
|
port_enable1 : string := "PORT_CONNECTIVITY";
|
|
port_locked : string := "PORT_CONNECTIVITY";
|
|
port_configupdate : string := "PORT_CONNECTIVITY";
|
|
port_phasecounterselect : string := "PORT_CONNECTIVITY";
|
|
port_phasedone : string := "PORT_CONNECTIVITY";
|
|
port_phasestep : string := "PORT_CONNECTIVITY";
|
|
port_phaseupdown : string := "PORT_CONNECTIVITY";
|
|
port_vcooverrange : string := "PORT_CONNECTIVITY";
|
|
port_vcounderrange : string := "PORT_CONNECTIVITY";
|
|
port_scanclkena : string := "PORT_CONNECTIVITY"
|
|
);
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (others => '0'); -- input clocks, up to 2 can be used
|
|
fbin : in std_logic := '0'; -- external feedback port
|
|
pllena : in std_logic := '1'; -- PLL enable signal
|
|
clkswitch : in std_logic := '0'; -- switch between inclk0 and inclk1
|
|
areset : in std_logic := '0'; -- asynchronous reset
|
|
pfdena : in std_logic := '1'; -- enable Phase Frequency Detector (PFD)
|
|
clkena : in std_logic_vector(5 downto 0) := (others => '1'); -- enable clk0-clk5 outputs
|
|
extclkena : in std_logic_vector(3 downto 0) := (others => '1'); -- enable extclk0-extclk3 outputs
|
|
scanclk : in std_logic := '0'; -- clock for scan chain
|
|
scanclkena : in std_logic := '1';
|
|
scanaclr : in std_logic := '0'; -- asynchronous clear for the scan chain
|
|
scanread : in std_logic := '0'; -- determines when the scan chain can read in data from the scandata port
|
|
scanwrite : in std_logic := '0'; -- determines when the scan chain can write out data into pll
|
|
scandata : in std_logic := '0'; -- data for the scan chain
|
|
comparator : in std_logic := '0'; -- control the enable0 pulse generation to achieve data realignment in lvds.
|
|
phasecounterselect : in std_logic_vector(width_phasecounterselect-1 downto 0) := (others => '0');
|
|
phaseupdown : in std_logic := '0';
|
|
phasestep : in std_logic := '0';
|
|
configupdate : in std_logic := '0';
|
|
fbmimicbidir : inout std_logic := '1';
|
|
|
|
clk : out std_logic_vector(width_clock-1 downto 0); -- internal clock outputs (feeds the core)
|
|
extclk : out std_logic_vector(3 downto 0); -- external clock outputs (feeds pins)
|
|
clkbad : out std_logic_vector(1 downto 0); -- indicates if inclk0/inclk1 has gone bad
|
|
enable0 : out std_logic; -- load enable pulse 0 for lvds
|
|
enable1 : out std_logic; -- load enable pulse 1 for lvds
|
|
activeclock : out std_logic; -- indicates which input clock is being used
|
|
clkloss : out std_logic; -- indicates when clock switchover initiates
|
|
locked : out std_logic; -- indicates when the PLL locks
|
|
scandataout : out std_logic; -- data output from the scan chain
|
|
scandone : out std_logic; -- indicates when pll reconfiguration is complete
|
|
sclkout0 : out std_logic; -- serial clock output 0 for lvds
|
|
sclkout1 : out std_logic; -- serial clock output 1 for lvds
|
|
phasedone : out std_logic;
|
|
vcooverrange : out std_logic;
|
|
vcounderrange : out std_logic;
|
|
fbout : out std_logic;
|
|
fref : out std_logic;
|
|
icdrclk : out std_logic
|
|
|
|
);
|
|
end altpll;
|
|
|
|
-- BEGINNING OF ARCHITECURE BEHAVIOR
|
|
architecture behavior of altpll is
|
|
|
|
-----------------------
|
|
-- CONSTANT DECLARATION
|
|
-----------------------
|
|
constant IS_STRATIXII : boolean := FEATURE_FAMILY_STRATIXII(intended_device_family);
|
|
constant IS_STRATIXIII : boolean := FEATURE_FAMILY_STRATIXIII(intended_device_family);
|
|
constant IS_CYCLONEII : boolean := FEATURE_FAMILY_CYCLONEII(intended_device_family);
|
|
constant IS_CYCLONEIII : boolean := FEATURE_FAMILY_CYCLONEIII(intended_device_family) or FEATURE_FAMILY_MAX10(intended_device_family);
|
|
constant IS_PIRANHA : boolean := FEATURE_FAMILY_ARRIAIIGX(intended_device_family);
|
|
constant IS_STINGRAY : boolean := FEATURE_FAMILY_CYCLONEIVGX(intended_device_family);
|
|
|
|
-- converts uppercase parameter values (e.g. "AUTO") to lowercase ("auto")
|
|
-- as expected by stratix_pll model
|
|
function alpha_tolower (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
|
|
begin
|
|
for i in 1 to string_length loop
|
|
case given_string(i) is
|
|
when 'A' => result_string(i) := 'a';
|
|
when 'B' => result_string(i) := 'b';
|
|
when 'C' => result_string(i) := 'c';
|
|
when 'D' => result_string(i) := 'd';
|
|
when 'E' => result_string(i) := 'e';
|
|
when 'F' => result_string(i) := 'f';
|
|
when 'G' => result_string(i) := 'g';
|
|
when 'H' => result_string(i) := 'h';
|
|
when 'I' => result_string(i) := 'i';
|
|
when 'J' => result_string(i) := 'j';
|
|
when 'K' => result_string(i) := 'k';
|
|
when 'L' => result_string(i) := 'l';
|
|
when 'M' => result_string(i) := 'm';
|
|
when 'N' => result_string(i) := 'n';
|
|
when 'O' => result_string(i) := 'o';
|
|
when 'P' => result_string(i) := 'p';
|
|
when 'Q' => result_string(i) := 'q';
|
|
when 'R' => result_string(i) := 'r';
|
|
when 'S' => result_string(i) := 's';
|
|
when 'T' => result_string(i) := 't';
|
|
when 'U' => result_string(i) := 'u';
|
|
when 'V' => result_string(i) := 'v';
|
|
when 'W' => result_string(i) := 'w';
|
|
when 'X' => result_string(i) := 'x';
|
|
when 'Y' => result_string(i) := 'y';
|
|
when 'Z' => result_string(i) := 'z';
|
|
when others => result_string(i) := given_string(i);
|
|
end case;
|
|
end loop;
|
|
|
|
return (result_string(1 to string_length));
|
|
end;
|
|
|
|
-- The following functions are used to set the default parameters' values for
|
|
-- Stratix II if user do not specify these parameters' values.
|
|
|
|
function get_clk0_counter (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
begin
|
|
if (given_string = "g0") then
|
|
return "c0";
|
|
else
|
|
result_string(1 to string_length) := alpha_tolower(given_string);
|
|
return (result_string(1 to string_length));
|
|
end if;
|
|
end;
|
|
|
|
-- get feedback source for stratixii
|
|
function get_clk1_counter (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
begin
|
|
if (given_string = "g1") then
|
|
return "c1";
|
|
else
|
|
result_string(1 to string_length) := alpha_tolower(given_string);
|
|
return (result_string(1 to string_length));
|
|
end if;
|
|
end;
|
|
|
|
|
|
function get_clk2_counter (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
begin
|
|
if (given_string = "g2") then
|
|
return "c2";
|
|
else
|
|
result_string(1 to string_length) := alpha_tolower(given_string);
|
|
return (result_string(1 to string_length));
|
|
end if;
|
|
end;
|
|
|
|
function get_clk3_counter (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
begin
|
|
if (given_string = "g3") then
|
|
return "c3";
|
|
else
|
|
result_string(1 to string_length) := alpha_tolower(given_string);
|
|
return (result_string(1 to string_length));
|
|
end if;
|
|
end;
|
|
|
|
function get_clk4_counter (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
begin
|
|
if (given_string = "l0") then
|
|
return "c4";
|
|
else
|
|
result_string(1 to string_length) := alpha_tolower(given_string);
|
|
return (result_string(1 to string_length));
|
|
end if;
|
|
end;
|
|
|
|
function get_clk5_counter (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
begin
|
|
if (given_string = "l1") then
|
|
return "c5";
|
|
else
|
|
result_string(1 to string_length) := alpha_tolower(given_string);
|
|
return (result_string(1 to string_length));
|
|
end if;
|
|
end;
|
|
|
|
function get_clk_counter (counter_value : string; port_usage : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := counter_value'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
begin
|
|
if (port_usage /= "PORT_USED") then
|
|
return "unused";
|
|
else
|
|
result_string(1 to string_length) := alpha_tolower(counter_value);
|
|
return (result_string(1 to string_length));
|
|
end if;
|
|
end;
|
|
|
|
function get_enable0_counter (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
begin
|
|
if (given_string = "l0") then
|
|
return "c0";
|
|
else
|
|
result_string(1 to string_length) := alpha_tolower(given_string);
|
|
return (result_string(1 to string_length));
|
|
end if;
|
|
end;
|
|
|
|
function get_enable1_counter (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
begin
|
|
if (given_string = "l0") then
|
|
return "c1";
|
|
else
|
|
result_string(1 to string_length) := alpha_tolower(given_string);
|
|
return (result_string(1 to string_length));
|
|
end if;
|
|
end;
|
|
|
|
-- get feedback source for stratixii
|
|
function get_feedback_source (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
begin
|
|
if (given_string = "extclk0") then
|
|
return "clk0";
|
|
else
|
|
result_string(1 to string_length) := alpha_tolower(given_string);
|
|
return (result_string(1 to string_length));
|
|
end if;
|
|
end;
|
|
|
|
-- get charge_pump_current for stratixii
|
|
function get_charge_pump_current (m_value : integer; charge_pump_current : integer) return integer is
|
|
begin
|
|
if (m_value = 0) then
|
|
return 52;
|
|
else
|
|
return charge_pump_current;
|
|
end if;
|
|
end;
|
|
|
|
-- get loop_filter_c for stratixii
|
|
function get_loop_filter_c (m_value : integer; loop_filter_c : integer) return integer is
|
|
begin
|
|
if (m_value = 0) then
|
|
return 16;
|
|
else
|
|
return loop_filter_c;
|
|
end if;
|
|
end;
|
|
|
|
function get_test_source (test_source : integer) return integer is
|
|
begin
|
|
if (test_source = 5) then
|
|
return -1;
|
|
else
|
|
return test_source;
|
|
end if;
|
|
end;
|
|
|
|
function get_vco_min_s (vco_min : integer) return integer is
|
|
begin
|
|
if (vco_min = 0 AND m /= 0 ) then
|
|
return 1000;
|
|
else
|
|
return vco_min;
|
|
end if;
|
|
end;
|
|
|
|
function get_vco_min_s2 (vco_min : integer) return integer is
|
|
begin
|
|
if (vco_min = 0 AND m /= 0) then
|
|
return 700;
|
|
else
|
|
return vco_min;
|
|
end if;
|
|
end;
|
|
|
|
function get_vco_min_c2 (vco_min : integer) return integer is
|
|
begin
|
|
if (vco_min = 0 AND m /= 0) then
|
|
return 300;
|
|
else
|
|
return vco_min;
|
|
end if;
|
|
end;
|
|
|
|
function get_vco_min_s3 (vco_min : integer) return integer is
|
|
begin
|
|
if (vco_min = 0 AND m /= 0) then
|
|
return 100;
|
|
else
|
|
return vco_min;
|
|
end if;
|
|
end;
|
|
|
|
function get_vco_min_c3 (vco_min : integer) return integer is
|
|
begin
|
|
if (vco_min = 0 AND m /= 0) then
|
|
return 200;
|
|
else
|
|
return vco_min;
|
|
end if;
|
|
end;
|
|
|
|
function get_vco_max (vco_max : integer) return integer is
|
|
begin
|
|
if (vco_max = 0 AND m /= 0) then
|
|
return 3600;
|
|
else
|
|
return vco_max;
|
|
end if;
|
|
end;
|
|
|
|
-- COMPONENT DECLARATION
|
|
component MF_stratix_pll
|
|
generic (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "auto";
|
|
qualify_conf_done : string := "off";
|
|
compensate_clock : string := "clk0";
|
|
scan_chain : string := "long";
|
|
primary_clock : string := "inclk0";
|
|
inclk0_input_frequency : integer := 1000;
|
|
inclk1_input_frequency : integer := 1000;
|
|
gate_lock_signal : string := "no";
|
|
gate_lock_counter : integer := 0;
|
|
valid_lock_multiplier : integer := 1;
|
|
invalid_lock_multiplier : integer := 5;
|
|
switch_over_on_lossclk : string := "off";
|
|
switch_over_on_gated_lock : string := "off";
|
|
enable_switch_over_counter : string := "off";
|
|
switch_over_counter : integer := 0;
|
|
feedback_source : string := "extclk0";
|
|
bandwidth : integer := 0;
|
|
bandwidth_type : string := "auto";
|
|
spread_frequency : integer := 0;
|
|
down_spread : string := "0.0";
|
|
simulation_type : string := "functional";
|
|
skip_vco : string := "off";
|
|
family_name : string := "Stratix";
|
|
|
|
clk0_multiply_by : integer := 1;
|
|
clk0_divide_by : integer := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk0_time_delay : string := "0";
|
|
clk0_duty_cycle : integer := 50;
|
|
|
|
clk1_multiply_by : integer := 1;
|
|
clk1_divide_by : integer := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_time_delay : string := "0";
|
|
clk1_duty_cycle : integer := 50;
|
|
|
|
clk2_multiply_by : integer := 1;
|
|
clk2_divide_by : integer := 1;
|
|
clk2_phase_shift : string := "0";
|
|
clk2_time_delay : string := "0";
|
|
clk2_duty_cycle : integer := 50;
|
|
|
|
clk3_multiply_by : integer := 1;
|
|
clk3_divide_by : integer := 1;
|
|
clk3_phase_shift : string := "0";
|
|
clk3_time_delay : string := "0";
|
|
clk3_duty_cycle : integer := 50;
|
|
|
|
clk4_multiply_by : integer := 1;
|
|
clk4_divide_by : integer := 1;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_time_delay : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
|
|
clk5_multiply_by : integer := 1;
|
|
clk5_divide_by : integer := 1;
|
|
clk5_phase_shift : string := "0";
|
|
clk5_time_delay : string := "0";
|
|
clk5_duty_cycle : integer := 50;
|
|
|
|
extclk0_multiply_by : integer := 1;
|
|
extclk0_divide_by : integer := 1;
|
|
extclk0_phase_shift : string := "0";
|
|
extclk0_time_delay : string := "0";
|
|
extclk0_duty_cycle : integer := 50;
|
|
|
|
extclk1_multiply_by : integer := 1;
|
|
extclk1_divide_by : integer := 1;
|
|
extclk1_phase_shift : string := "0";
|
|
extclk1_time_delay : string := "0";
|
|
extclk1_duty_cycle : integer := 50;
|
|
|
|
extclk2_multiply_by : integer := 1;
|
|
extclk2_divide_by : integer := 1;
|
|
extclk2_phase_shift : string := "0";
|
|
extclk2_time_delay : string := "0";
|
|
extclk2_duty_cycle : integer := 50;
|
|
|
|
extclk3_multiply_by : integer := 1;
|
|
extclk3_divide_by : integer := 1;
|
|
extclk3_phase_shift : string := "0";
|
|
extclk3_time_delay : string := "0";
|
|
extclk3_duty_cycle : integer := 50;
|
|
|
|
vco_min : integer := 0;
|
|
vco_max : integer := 0;
|
|
vco_center : integer := 0;
|
|
pfd_min : integer := 0;
|
|
pfd_max : integer := 0;
|
|
|
|
-- ADVANCED USER PARAMETERS
|
|
m_initial : integer := 1; -- 1-1024
|
|
m : integer := 1; -- 1-1024
|
|
n : integer := 1; -- 1-1024
|
|
m2 : integer := 1; -- 1-1024
|
|
n2 : integer := 1; -- 1-1024
|
|
ss : integer := 0;
|
|
|
|
l0_high : integer := 1; -- 1-512
|
|
l0_low : integer := 1; -- 1-512
|
|
l0_initial : integer := 1; -- 1-512
|
|
l0_mode : string := "bypass"; -- bypass,odd,even
|
|
l0_ph : integer := 0;
|
|
l0_time_delay : integer := 0;
|
|
|
|
l1_high : integer := 1;
|
|
l1_low : integer := 1;
|
|
l1_initial : integer := 1;
|
|
l1_mode : string := "bypass";
|
|
l1_ph : integer := 0;
|
|
l1_time_delay : integer := 0;
|
|
|
|
g0_high : integer := 1;
|
|
g0_low : integer := 1;
|
|
g0_initial : integer := 1;
|
|
g0_mode : string := "bypass";
|
|
g0_ph : integer := 0;
|
|
g0_time_delay : integer := 0;
|
|
|
|
g1_high : integer := 1;
|
|
g1_low : integer := 1;
|
|
g1_initial : integer := 1;
|
|
g1_mode : string := "bypass";
|
|
g1_ph : integer := 0;
|
|
g1_time_delay : integer := 0;
|
|
|
|
g2_high : integer := 1;
|
|
g2_low : integer := 1;
|
|
g2_initial : integer := 1;
|
|
g2_mode : string := "bypass";
|
|
g2_ph : integer := 0;
|
|
g2_time_delay : integer := 0;
|
|
|
|
g3_high : integer := 1;
|
|
g3_low : integer := 1;
|
|
g3_initial : integer := 1;
|
|
g3_mode : string := "bypass";
|
|
g3_ph : integer := 0;
|
|
g3_time_delay : integer := 0;
|
|
|
|
e0_high : integer := 1;
|
|
e0_low : integer := 1;
|
|
e0_initial : integer := 1;
|
|
e0_mode : string := "bypass";
|
|
e0_ph : integer := 0;
|
|
e0_time_delay : integer := 0;
|
|
|
|
e1_high : integer := 1;
|
|
e1_low : integer := 1;
|
|
e1_initial : integer := 1;
|
|
e1_mode : string := "bypass";
|
|
e1_ph : integer := 0;
|
|
e1_time_delay : integer := 0;
|
|
|
|
e2_high : integer := 1;
|
|
e2_low : integer := 1;
|
|
e2_initial : integer := 1;
|
|
e2_mode : string := "bypass";
|
|
e2_ph : integer := 0;
|
|
e2_time_delay : integer := 0;
|
|
|
|
e3_high : integer := 1;
|
|
e3_low : integer := 1;
|
|
e3_initial : integer := 1;
|
|
e3_mode : string := "bypass";
|
|
e3_ph : integer := 0;
|
|
e3_time_delay : integer := 0;
|
|
|
|
m_ph : integer := 0;
|
|
m_time_delay : integer := 0;
|
|
n_time_delay : integer := 0;
|
|
|
|
extclk0_counter : string := "e0";
|
|
extclk1_counter : string := "e1";
|
|
extclk2_counter : string := "e2";
|
|
extclk3_counter : string := "e3";
|
|
|
|
clk0_counter : string := "g0";
|
|
clk1_counter : string := "g1";
|
|
clk2_counter : string := "g2";
|
|
clk3_counter : string := "g3";
|
|
clk4_counter : string := "l0";
|
|
clk5_counter : string := "l1";
|
|
|
|
enable0_counter : string := "l0";
|
|
enable1_counter : string := "l0";
|
|
|
|
charge_pump_current : integer := 2;
|
|
|
|
loop_filter_r : string := "1.0";
|
|
loop_filter_c : natural := 5
|
|
);
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (OTHERS=>'0');
|
|
fbin : in std_logic := '0';
|
|
ena : in std_logic := '1';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
clkena : in std_logic_vector(5 downto 0) := (OTHERS=>'1');
|
|
extclkena : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
|
|
scanclk : in std_logic := '0';
|
|
scanaclr : in std_logic := '0';
|
|
scandata : in std_logic := '0';
|
|
clk : out std_logic_vector(5 downto 0);
|
|
extclk : out std_logic_vector(3 downto 0);
|
|
clkbad : out std_logic_vector(1 downto 0);
|
|
activeclock : out std_logic;
|
|
clkloss : out std_logic;
|
|
locked : out std_logic;
|
|
scandataout : out std_logic;
|
|
|
|
-- lvds specific ports
|
|
comparator : in std_logic := '0';
|
|
enable0 : out std_logic;
|
|
enable1 : out std_logic
|
|
);
|
|
end component;
|
|
|
|
|
|
component MF_stratixii_pll
|
|
generic (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "auto";
|
|
qualify_conf_done : string := "off";
|
|
compensate_clock : string := "clk0";
|
|
inclk0_input_frequency : integer := 1000;
|
|
inclk1_input_frequency : integer := 1000;
|
|
gate_lock_signal : string := "no";
|
|
gate_lock_counter : integer := 0;
|
|
valid_lock_multiplier : integer := 1;
|
|
invalid_lock_multiplier : integer := 5;
|
|
switch_over_type : string := "auto";
|
|
switch_over_on_lossclk : string := "off";
|
|
switch_over_on_gated_lock : string := "off";
|
|
enable_switch_over_counter : string := "off";
|
|
switch_over_counter : integer := 0;
|
|
feedback_source : string := "extclk0";
|
|
bandwidth : integer := 0;
|
|
bandwidth_type : string := "auto";
|
|
spread_frequency : integer := 0;
|
|
down_spread : string := "0.0";
|
|
self_reset_on_gated_loss_lock : string := "OFF";
|
|
simulation_type : string := "functional";
|
|
family_name : string := "StratixII";
|
|
|
|
clk0_output_frequency : natural := 0;
|
|
clk0_multiply_by : integer := 1;
|
|
clk0_divide_by : integer := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk0_duty_cycle : integer := 50;
|
|
|
|
clk1_output_frequency : natural := 0;
|
|
clk1_multiply_by : integer := 1;
|
|
clk1_divide_by : integer := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_duty_cycle : integer := 50;
|
|
|
|
clk2_output_frequency : natural := 0;
|
|
clk2_multiply_by : integer := 1;
|
|
clk2_divide_by : integer := 1;
|
|
clk2_phase_shift : string := "0";
|
|
clk2_duty_cycle : integer := 50;
|
|
|
|
clk3_multiply_by : integer := 1;
|
|
clk3_divide_by : integer := 1;
|
|
clk3_phase_shift : string := "0";
|
|
clk3_duty_cycle : integer := 50;
|
|
|
|
clk4_multiply_by : integer := 1;
|
|
clk4_divide_by : integer := 1;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
|
|
clk5_multiply_by : integer := 1;
|
|
clk5_divide_by : integer := 1;
|
|
clk5_phase_shift : string := "0";
|
|
clk5_duty_cycle : integer := 50;
|
|
|
|
vco_min : integer := 0;
|
|
vco_max : integer := 0;
|
|
vco_center : integer := 0;
|
|
pfd_min : integer := 0;
|
|
pfd_max : integer := 0;
|
|
|
|
-- ADVANCED USER PARAMETERS
|
|
m_initial : integer := 1; -- 1-1024
|
|
m : integer := 1; -- 1-1024
|
|
n : integer := 1; -- 1-1024
|
|
m2 : integer := 1; -- 1-1024
|
|
n2 : integer := 1; -- 1-1024
|
|
ss : integer := 0;
|
|
|
|
c0_high : integer := 1; -- 1-512
|
|
c0_low : integer := 1; -- 1-512
|
|
c0_initial : integer := 1; -- 1-512
|
|
c0_mode : string := "bypass"; -- bypass,odd,even
|
|
c0_ph : integer := 0;
|
|
|
|
c1_high : integer := 1;
|
|
c1_low : integer := 1;
|
|
c1_initial : integer := 1;
|
|
c1_mode : string := "bypass";
|
|
c1_ph : integer := 0;
|
|
|
|
c2_high : integer := 1;
|
|
c2_low : integer := 1;
|
|
c2_initial : integer := 1;
|
|
c2_mode : string := "bypass";
|
|
c2_ph : integer := 0;
|
|
|
|
c3_high : integer := 1;
|
|
c3_low : integer := 1;
|
|
c3_initial : integer := 1;
|
|
c3_mode : string := "bypass";
|
|
c3_ph : integer := 0;
|
|
|
|
c4_high : integer := 1;
|
|
c4_low : integer := 1;
|
|
c4_initial : integer := 1;
|
|
c4_mode : string := "bypass";
|
|
c4_ph : integer := 0;
|
|
|
|
c5_high : integer := 1;
|
|
c5_low : integer := 1;
|
|
c5_initial : integer := 1;
|
|
c5_mode : string := "bypass";
|
|
c5_ph : integer := 0;
|
|
|
|
m_ph : integer := 0;
|
|
|
|
c1_use_casc_in : string := "off";
|
|
c2_use_casc_in : string := "off";
|
|
c3_use_casc_in : string := "off";
|
|
c4_use_casc_in : string := "off";
|
|
c5_use_casc_in : string := "off";
|
|
|
|
m_test_source : integer := 5;
|
|
c0_test_source : integer := 5;
|
|
c1_test_source : integer := 5;
|
|
c2_test_source : integer := 5;
|
|
c3_test_source : integer := 5;
|
|
c4_test_source : integer := 5;
|
|
c5_test_source : integer := 5;
|
|
|
|
clk0_counter : string := "c0";
|
|
clk1_counter : string := "c1";
|
|
clk2_counter : string := "c2";
|
|
clk3_counter : string := "c3";
|
|
clk4_counter : string := "c4";
|
|
clk5_counter : string := "c5";
|
|
|
|
enable0_counter : string := "c0";
|
|
enable1_counter : string := "c0";
|
|
sclkout0_phase_shift : string := "0";
|
|
sclkout1_phase_shift : string := "0";
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
|
|
charge_pump_current : integer := 2;
|
|
|
|
loop_filter_r : string := "1.0";
|
|
loop_filter_c : natural := 5;
|
|
sim_gate_lock_device_behavior : string := "OFF"
|
|
);
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (OTHERS=>'0');
|
|
fbin : in std_logic := '0';
|
|
ena : in std_logic := '1';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scanclk : in std_logic := '1';
|
|
scanread : in std_logic := '1';
|
|
scanwrite : in std_logic := '1';
|
|
scandata : in std_logic := '1';
|
|
testin : in std_logic_vector(3 downto 0) := (OTHERS=>'0');
|
|
clk : out std_logic_vector(5 downto 0);
|
|
clkbad : out std_logic_vector(1 downto 0);
|
|
activeclock : out std_logic;
|
|
clkloss : out std_logic;
|
|
locked : out std_logic;
|
|
scandataout : out std_logic;
|
|
scandone : out std_logic;
|
|
|
|
-- lvds specific ports
|
|
enable0 : out std_logic;
|
|
enable1 : out std_logic;
|
|
sclkout : out std_logic_vector(1 downto 0)
|
|
);
|
|
end component;
|
|
|
|
component MF_stratixiii_pll
|
|
generic (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "auto";
|
|
compensate_clock : string := "clk0";
|
|
inclk0_input_frequency : integer := 1000;
|
|
inclk1_input_frequency : integer := 1000;
|
|
self_reset_on_loss_lock : string := "off";
|
|
switch_over_type : string := "auto";
|
|
enable_switch_over_counter : string := "off";
|
|
switch_over_counter : integer := 0;
|
|
bandwidth : integer := 0;
|
|
bandwidth_type : string := "auto";
|
|
lock_high : integer := 0;
|
|
lock_low : integer := 0;
|
|
lock_window_ui : string := " 0.05";
|
|
lock_c : integer := 4;
|
|
simulation_type : string := "functional";
|
|
family_name : string := "StratixIII";
|
|
|
|
clk0_output_frequency : natural := 0;
|
|
clk0_multiply_by : integer := 1;
|
|
clk0_divide_by : integer := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk0_duty_cycle : integer := 50;
|
|
clk0_use_even_counter_mode : string := "OFF";
|
|
clk0_use_even_counter_value : string := "OFF";
|
|
|
|
clk1_output_frequency : natural := 0;
|
|
clk1_multiply_by : integer := 1;
|
|
clk1_divide_by : integer := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_duty_cycle : integer := 50;
|
|
clk1_use_even_counter_mode : string := "OFF";
|
|
clk1_use_even_counter_value : string := "OFF";
|
|
|
|
clk2_output_frequency : natural := 0;
|
|
clk2_multiply_by : integer := 1;
|
|
clk2_divide_by : integer := 1;
|
|
clk2_phase_shift : string := "0";
|
|
clk2_duty_cycle : integer := 50;
|
|
clk2_use_even_counter_mode : string := "OFF";
|
|
clk2_use_even_counter_value : string := "OFF";
|
|
|
|
clk3_multiply_by : integer := 1;
|
|
clk3_divide_by : integer := 1;
|
|
clk3_phase_shift : string := "0";
|
|
clk3_duty_cycle : integer := 50;
|
|
clk3_use_even_counter_mode : string := "OFF";
|
|
clk3_use_even_counter_value : string := "OFF";
|
|
|
|
clk4_multiply_by : integer := 1;
|
|
clk4_divide_by : integer := 1;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
clk4_use_even_counter_mode : string := "OFF";
|
|
clk4_use_even_counter_value : string := "OFF";
|
|
|
|
clk5_multiply_by : integer := 1;
|
|
clk5_divide_by : integer := 1;
|
|
clk5_phase_shift : string := "0";
|
|
clk5_duty_cycle : integer := 50;
|
|
clk5_use_even_counter_mode : string := "OFF";
|
|
clk5_use_even_counter_value : string := "OFF";
|
|
|
|
clk6_multiply_by : integer := 1;
|
|
clk6_divide_by : integer := 1;
|
|
clk6_phase_shift : string := "0";
|
|
clk6_duty_cycle : integer := 50;
|
|
clk6_use_even_counter_mode : string := "OFF";
|
|
clk6_use_even_counter_value : string := "OFF";
|
|
|
|
clk7_multiply_by : integer := 1;
|
|
clk7_divide_by : integer := 1;
|
|
clk7_phase_shift : string := "0";
|
|
clk7_duty_cycle : integer := 50;
|
|
clk7_use_even_counter_mode : string := "OFF";
|
|
clk7_use_even_counter_value : string := "OFF";
|
|
|
|
clk8_multiply_by : integer := 1;
|
|
clk8_divide_by : integer := 1;
|
|
clk8_phase_shift : string := "0";
|
|
clk8_duty_cycle : integer := 50;
|
|
clk8_use_even_counter_mode : string := "OFF";
|
|
clk8_use_even_counter_value : string := "OFF";
|
|
|
|
clk9_multiply_by : integer := 1;
|
|
clk9_divide_by : integer := 1;
|
|
clk9_phase_shift : string := "0";
|
|
clk9_duty_cycle : integer := 50;
|
|
clk9_use_even_counter_mode : string := "OFF";
|
|
clk9_use_even_counter_value : string := "OFF";
|
|
|
|
vco_min : integer := 0;
|
|
vco_max : integer := 0;
|
|
vco_center : integer := 0;
|
|
pfd_min : integer := 0;
|
|
pfd_max : integer := 0;
|
|
|
|
-- ADVANCED USER PARAMETERS
|
|
m_initial : integer := 1; -- 1-1024
|
|
m : integer := 1; -- 1-1024
|
|
n : integer := 1; -- 1-1024
|
|
|
|
c0_high : integer := 1; -- 1-512
|
|
c0_low : integer := 1; -- 1-512
|
|
c0_initial : integer := 1; -- 1-512
|
|
c0_mode : string := "bypass"; -- bypass,odd,even
|
|
c0_ph : integer := 0;
|
|
|
|
c1_high : integer := 1;
|
|
c1_low : integer := 1;
|
|
c1_initial : integer := 1;
|
|
c1_mode : string := "bypass";
|
|
c1_ph : integer := 0;
|
|
|
|
c2_high : integer := 1;
|
|
c2_low : integer := 1;
|
|
c2_initial : integer := 1;
|
|
c2_mode : string := "bypass";
|
|
c2_ph : integer := 0;
|
|
|
|
c3_high : integer := 1;
|
|
c3_low : integer := 1;
|
|
c3_initial : integer := 1;
|
|
c3_mode : string := "bypass";
|
|
c3_ph : integer := 0;
|
|
|
|
c4_high : integer := 1;
|
|
c4_low : integer := 1;
|
|
c4_initial : integer := 1;
|
|
c4_mode : string := "bypass";
|
|
c4_ph : integer := 0;
|
|
|
|
c5_high : integer := 1;
|
|
c5_low : integer := 1;
|
|
c5_initial : integer := 1;
|
|
c5_mode : string := "bypass";
|
|
c5_ph : integer := 0;
|
|
|
|
c6_high : integer := 1;
|
|
c6_low : integer := 1;
|
|
c6_initial : integer := 1;
|
|
c6_mode : string := "bypass";
|
|
c6_ph : integer := 0;
|
|
|
|
c7_high : integer := 1;
|
|
c7_low : integer := 1;
|
|
c7_initial : integer := 1;
|
|
c7_mode : string := "bypass";
|
|
c7_ph : integer := 0;
|
|
|
|
c8_high : integer := 1;
|
|
c8_low : integer := 1;
|
|
c8_initial : integer := 1;
|
|
c8_mode : string := "bypass";
|
|
c8_ph : integer := 0;
|
|
|
|
c9_high : integer := 1;
|
|
c9_low : integer := 1;
|
|
c9_initial : integer := 1;
|
|
c9_mode : string := "bypass";
|
|
c9_ph : integer := 0;
|
|
|
|
m_ph : integer := 0;
|
|
|
|
c1_use_casc_in : string := "off";
|
|
c2_use_casc_in : string := "off";
|
|
c3_use_casc_in : string := "off";
|
|
c4_use_casc_in : string := "off";
|
|
c5_use_casc_in : string := "off";
|
|
c6_use_casc_in : string := "off";
|
|
c7_use_casc_in : string := "off";
|
|
c8_use_casc_in : string := "off";
|
|
c9_use_casc_in : string := "off";
|
|
|
|
m_test_source : integer := -1;
|
|
c0_test_source : integer := -1;
|
|
c1_test_source : integer := -1;
|
|
c2_test_source : integer := -1;
|
|
c3_test_source : integer := -1;
|
|
c4_test_source : integer := -1;
|
|
c5_test_source : integer := -1;
|
|
c6_test_source : integer := -1;
|
|
c7_test_source : integer := -1;
|
|
c8_test_source : integer := -1;
|
|
c9_test_source : integer := -1;
|
|
|
|
clk0_counter : string := "c0";
|
|
clk1_counter : string := "c1";
|
|
clk2_counter : string := "c2";
|
|
clk3_counter : string := "c3";
|
|
clk4_counter : string := "c4";
|
|
clk5_counter : string := "c5";
|
|
clk6_counter : string := "c6";
|
|
clk7_counter : string := "c7";
|
|
clk8_counter : string := "c8";
|
|
clk9_counter : string := "c9";
|
|
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
|
|
dpa_multiply_by : integer := 0;
|
|
dpa_divide_by : integer := 0;
|
|
dpa_divider : integer := 0;
|
|
|
|
vco_frequency_control : string := "AUTO";
|
|
vco_phase_shift_step : natural := 0;
|
|
charge_pump_current_bits : natural := 9999;
|
|
loop_filter_c_bits : natural := 9999;
|
|
loop_filter_r_bits : natural := 9999;
|
|
|
|
charge_pump_current : integer := 2;
|
|
|
|
loop_filter_r : string := "1.0";
|
|
loop_filter_c : natural := 5
|
|
);
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (OTHERS=>'0');
|
|
fbin : in std_logic := '0';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scanclk : in std_logic := '1';
|
|
scandata : in std_logic := '1';
|
|
scanclkena : in std_logic := '1';
|
|
configupdate : in std_logic := '0';
|
|
phasecounterselect : in std_logic_vector(3 downto 0) := (OTHERS=>'0');
|
|
phaseupdown : in std_logic := '0';
|
|
phasestep : in std_logic := '0';
|
|
|
|
clk : out std_logic_vector(9 downto 0);
|
|
clkbad : out std_logic_vector(1 downto 0);
|
|
activeclock : out std_logic;
|
|
locked : out std_logic;
|
|
scandataout : out std_logic;
|
|
scandone : out std_logic;
|
|
phasedone : out std_logic;
|
|
vcooverrange : out std_logic;
|
|
vcounderrange : out std_logic;
|
|
fbout : out std_logic
|
|
);
|
|
end component;
|
|
|
|
component MF_cycloneiii_pll
|
|
generic (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "auto";
|
|
compensate_clock : string := "clk0";
|
|
inclk0_input_frequency : integer := 1000;
|
|
inclk1_input_frequency : integer := 1000;
|
|
self_reset_on_loss_lock : string := "off";
|
|
switch_over_type : string := "auto";
|
|
enable_switch_over_counter : string := "off";
|
|
switch_over_counter : integer := 0;
|
|
bandwidth : integer := 0;
|
|
bandwidth_type : string := "auto";
|
|
lock_high : integer := 0;
|
|
lock_low : integer := 0;
|
|
lock_window_ui : string := "0.05";
|
|
lock_c : integer := 4;
|
|
simulation_type : string := "functional";
|
|
family_name : string := "CycloneIII";
|
|
|
|
clk0_output_frequency : natural := 0;
|
|
clk0_multiply_by : integer := 1;
|
|
clk0_divide_by : integer := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk0_duty_cycle : integer := 50;
|
|
clk0_use_even_counter_mode : string := "OFF";
|
|
clk0_use_even_counter_value : string := "OFF";
|
|
|
|
clk1_output_frequency : natural := 0;
|
|
clk1_multiply_by : integer := 1;
|
|
clk1_divide_by : integer := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_duty_cycle : integer := 50;
|
|
clk1_use_even_counter_mode : string := "OFF";
|
|
clk1_use_even_counter_value : string := "OFF";
|
|
|
|
clk2_output_frequency : natural := 0;
|
|
clk2_multiply_by : integer := 1;
|
|
clk2_divide_by : integer := 1;
|
|
clk2_phase_shift : string := "0";
|
|
clk2_duty_cycle : integer := 50;
|
|
clk2_use_even_counter_mode : string := "OFF";
|
|
clk2_use_even_counter_value : string := "OFF";
|
|
|
|
clk3_multiply_by : integer := 1;
|
|
clk3_divide_by : integer := 1;
|
|
clk3_phase_shift : string := "0";
|
|
clk3_duty_cycle : integer := 50;
|
|
clk3_use_even_counter_mode : string := "OFF";
|
|
clk3_use_even_counter_value : string := "OFF";
|
|
|
|
clk4_multiply_by : integer := 1;
|
|
clk4_divide_by : integer := 1;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
clk4_use_even_counter_mode : string := "OFF";
|
|
clk4_use_even_counter_value : string := "OFF";
|
|
|
|
vco_min : integer := 0;
|
|
vco_max : integer := 0;
|
|
vco_center : integer := 0;
|
|
pfd_min : integer := 0;
|
|
pfd_max : integer := 0;
|
|
|
|
-- ADVANCED USER PARAMETERS
|
|
m_initial : integer := 1; -- 1-1024
|
|
m : integer := 1; -- 1-1024
|
|
n : integer := 1; -- 1-1024
|
|
|
|
c0_high : integer := 1; -- 1-512
|
|
c0_low : integer := 1; -- 1-512
|
|
c0_initial : integer := 1; -- 1-512
|
|
c0_mode : string := "bypass"; -- bypass,odd,even
|
|
c0_ph : integer := 0;
|
|
|
|
c1_high : integer := 1;
|
|
c1_low : integer := 1;
|
|
c1_initial : integer := 1;
|
|
c1_mode : string := "bypass";
|
|
c1_ph : integer := 0;
|
|
|
|
c2_high : integer := 1;
|
|
c2_low : integer := 1;
|
|
c2_initial : integer := 1;
|
|
c2_mode : string := "bypass";
|
|
c2_ph : integer := 0;
|
|
|
|
c3_high : integer := 1;
|
|
c3_low : integer := 1;
|
|
c3_initial : integer := 1;
|
|
c3_mode : string := "bypass";
|
|
c3_ph : integer := 0;
|
|
|
|
c4_high : integer := 1;
|
|
c4_low : integer := 1;
|
|
c4_initial : integer := 1;
|
|
c4_mode : string := "bypass";
|
|
c4_ph : integer := 0;
|
|
|
|
m_ph : integer := 0;
|
|
|
|
c1_use_casc_in : string := "off";
|
|
c2_use_casc_in : string := "off";
|
|
c3_use_casc_in : string := "off";
|
|
c4_use_casc_in : string := "off";
|
|
|
|
m_test_source : integer := -1;
|
|
c0_test_source : integer := -1;
|
|
c1_test_source : integer := -1;
|
|
c2_test_source : integer := -1;
|
|
c3_test_source : integer := -1;
|
|
c4_test_source : integer := -1;
|
|
|
|
clk0_counter : string := "c0";
|
|
clk1_counter : string := "c1";
|
|
clk2_counter : string := "c2";
|
|
clk3_counter : string := "c3";
|
|
clk4_counter : string := "c4";
|
|
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
|
|
vco_frequency_control : string := "AUTO";
|
|
vco_phase_shift_step : natural := 0;
|
|
charge_pump_current_bits : natural := 9999;
|
|
loop_filter_c_bits : natural := 9999;
|
|
loop_filter_r_bits : natural := 9999;
|
|
|
|
charge_pump_current : integer := 2;
|
|
|
|
loop_filter_r : string := "1.0";
|
|
loop_filter_c : natural := 5
|
|
);
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (OTHERS=>'0');
|
|
fbin : in std_logic := '0';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scanclk : in std_logic := '1';
|
|
scandata : in std_logic := '1';
|
|
scanclkena : in std_logic := '1';
|
|
configupdate : in std_logic := '0';
|
|
phasecounterselect : in std_logic_vector(2 downto 0) := (OTHERS=>'0');
|
|
phaseupdown : in std_logic := '0';
|
|
phasestep : in std_logic := '0';
|
|
|
|
clk : out std_logic_vector(4 downto 0);
|
|
clkbad : out std_logic_vector(1 downto 0);
|
|
activeclock : out std_logic;
|
|
locked : out std_logic;
|
|
scandataout : out std_logic;
|
|
scandone : out std_logic;
|
|
phasedone : out std_logic;
|
|
vcooverrange : out std_logic;
|
|
vcounderrange : out std_logic;
|
|
fbout : out std_logic
|
|
);
|
|
end component;
|
|
|
|
component MF_cycloneiiigl_pll
|
|
generic (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "auto";
|
|
compensate_clock : string := "clk0";
|
|
inclk0_input_frequency : integer := 1000;
|
|
inclk1_input_frequency : integer := 1000;
|
|
self_reset_on_loss_lock : string := "off";
|
|
switch_over_type : string := "auto";
|
|
enable_switch_over_counter : string := "off";
|
|
switch_over_counter : integer := 0;
|
|
bandwidth : integer := 0;
|
|
bandwidth_type : string := "auto";
|
|
lock_high : integer := 0;
|
|
lock_low : integer := 0;
|
|
lock_window_ui : string := "0.05";
|
|
lock_c : integer := 4;
|
|
simulation_type : string := "functional";
|
|
family_name : string := "CycloneIIIGL";
|
|
lpm_hint : string := "unused";
|
|
|
|
clk0_output_frequency : natural := 0;
|
|
clk0_multiply_by : integer := 1;
|
|
clk0_divide_by : integer := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk0_duty_cycle : integer := 50;
|
|
clk0_use_even_counter_mode : string := "OFF";
|
|
clk0_use_even_counter_value : string := "OFF";
|
|
|
|
clk1_output_frequency : natural := 0;
|
|
clk1_multiply_by : integer := 1;
|
|
clk1_divide_by : integer := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_duty_cycle : integer := 50;
|
|
clk1_use_even_counter_mode : string := "OFF";
|
|
clk1_use_even_counter_value : string := "OFF";
|
|
|
|
clk2_output_frequency : natural := 0;
|
|
clk2_multiply_by : integer := 1;
|
|
clk2_divide_by : integer := 1;
|
|
clk2_phase_shift : string := "0";
|
|
clk2_duty_cycle : integer := 50;
|
|
clk2_use_even_counter_mode : string := "OFF";
|
|
clk2_use_even_counter_value : string := "OFF";
|
|
|
|
clk3_multiply_by : integer := 1;
|
|
clk3_divide_by : integer := 1;
|
|
clk3_phase_shift : string := "0";
|
|
clk3_duty_cycle : integer := 50;
|
|
clk3_use_even_counter_mode : string := "OFF";
|
|
clk3_use_even_counter_value : string := "OFF";
|
|
|
|
clk4_multiply_by : integer := 1;
|
|
clk4_divide_by : integer := 1;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
clk4_use_even_counter_mode : string := "OFF";
|
|
clk4_use_even_counter_value : string := "OFF";
|
|
|
|
vco_min : integer := 0;
|
|
vco_max : integer := 0;
|
|
vco_center : integer := 0;
|
|
dpa_multiply_by : integer := 0;
|
|
dpa_divide_by : integer := 0;
|
|
dpa_divider : integer := 0;
|
|
pfd_min : integer := 0;
|
|
pfd_max : integer := 0;
|
|
|
|
-- ADVANCED USER PARAMETERS
|
|
m_initial : integer := 1; -- 1-1024
|
|
m : integer := 1; -- 1-1024
|
|
n : integer := 1; -- 1-1024
|
|
|
|
c0_high : integer := 1; -- 1-512
|
|
c0_low : integer := 1; -- 1-512
|
|
c0_initial : integer := 1; -- 1-512
|
|
c0_mode : string := "bypass"; -- bypass,odd,even
|
|
c0_ph : integer := 0;
|
|
|
|
c1_high : integer := 1;
|
|
c1_low : integer := 1;
|
|
c1_initial : integer := 1;
|
|
c1_mode : string := "bypass";
|
|
c1_ph : integer := 0;
|
|
|
|
c2_high : integer := 1;
|
|
c2_low : integer := 1;
|
|
c2_initial : integer := 1;
|
|
c2_mode : string := "bypass";
|
|
c2_ph : integer := 0;
|
|
|
|
c3_high : integer := 1;
|
|
c3_low : integer := 1;
|
|
c3_initial : integer := 1;
|
|
c3_mode : string := "bypass";
|
|
c3_ph : integer := 0;
|
|
|
|
c4_high : integer := 1;
|
|
c4_low : integer := 1;
|
|
c4_initial : integer := 1;
|
|
c4_mode : string := "bypass";
|
|
c4_ph : integer := 0;
|
|
|
|
m_ph : integer := 0;
|
|
|
|
c1_use_casc_in : string := "off";
|
|
c2_use_casc_in : string := "off";
|
|
c3_use_casc_in : string := "off";
|
|
c4_use_casc_in : string := "off";
|
|
|
|
m_test_source : integer := -1;
|
|
c0_test_source : integer := -1;
|
|
c1_test_source : integer := -1;
|
|
c2_test_source : integer := -1;
|
|
c3_test_source : integer := -1;
|
|
c4_test_source : integer := -1;
|
|
|
|
clk0_counter : string := "c0";
|
|
clk1_counter : string := "c1";
|
|
clk2_counter : string := "c2";
|
|
clk3_counter : string := "c3";
|
|
clk4_counter : string := "c4";
|
|
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
|
|
vco_frequency_control : string := "AUTO";
|
|
vco_phase_shift_step : natural := 0;
|
|
charge_pump_current_bits : natural := 9999;
|
|
loop_filter_c_bits : natural := 9999;
|
|
loop_filter_r_bits : natural := 9999;
|
|
|
|
charge_pump_current : integer := 2;
|
|
|
|
loop_filter_r : string := "1.0";
|
|
loop_filter_c : natural := 5
|
|
);
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (OTHERS=>'0');
|
|
fbin : in std_logic := '0';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scanclk : in std_logic := '1';
|
|
scandata : in std_logic := '1';
|
|
scanclkena : in std_logic := '1';
|
|
configupdate : in std_logic := '0';
|
|
phasecounterselect : in std_logic_vector(2 downto 0) := (OTHERS=>'0');
|
|
phaseupdown : in std_logic := '0';
|
|
phasestep : in std_logic := '0';
|
|
|
|
clk : out std_logic_vector(4 downto 0);
|
|
clkbad : out std_logic_vector(1 downto 0);
|
|
activeclock : out std_logic;
|
|
locked : out std_logic;
|
|
scandataout : out std_logic;
|
|
scandone : out std_logic;
|
|
phasedone : out std_logic;
|
|
vcooverrange : out std_logic;
|
|
vcounderrange : out std_logic;
|
|
fbout : out std_logic;
|
|
fref : out std_logic;
|
|
icdrclk : out std_logic
|
|
);
|
|
end component;
|
|
|
|
component pll_iobuf
|
|
port (
|
|
i : in std_logic;
|
|
oe : in std_logic;
|
|
io : inout std_logic;
|
|
o : out std_logic
|
|
);
|
|
end component;
|
|
|
|
signal locked_tmp : std_logic;
|
|
signal clk_tmp : std_logic_vector(6 downto 0);
|
|
|
|
signal fbin_wire : std_logic;
|
|
signal pllena_wire : std_logic;
|
|
signal clkswitch_wire : std_logic;
|
|
signal areset_wire : std_logic;
|
|
signal pfdena_wire : std_logic;
|
|
signal scanclk_wire : std_logic;
|
|
signal scanaclr_wire : std_logic;
|
|
signal scanread_wire : std_logic;
|
|
signal scanwrite_wire : std_logic;
|
|
signal scandata_wire : std_logic;
|
|
signal clkena_wire : std_logic_vector(5 downto 0);
|
|
signal extclkena_wire : std_logic_vector(3 downto 0);
|
|
signal clk_wire : std_logic_vector(9 downto 0);
|
|
signal extclk_wire : std_logic_vector(3 downto 0);
|
|
signal clkbad_wire : std_logic_vector(1 downto 0);
|
|
signal activeclock_wire : std_logic;
|
|
signal clkloss_wire : std_logic;
|
|
signal scandataout_wire : std_logic;
|
|
signal scandone_wire : std_logic;
|
|
signal sclkout0_wire : std_logic;
|
|
signal sclkout1_wire : std_logic;
|
|
signal locked_wire : std_logic;
|
|
signal configupdate_wire : std_logic;
|
|
signal phasecounterselect_wire : std_logic_vector(3 downto 0);
|
|
signal phasestep_wire : std_logic;
|
|
signal phaseupdown_wire : std_logic;
|
|
signal scanclkena_wire : std_logic;
|
|
signal phasedone_wire : std_logic;
|
|
signal vcooverrange_wire : std_logic;
|
|
signal vcounderrange_wire : std_logic;
|
|
signal fbout_wire : std_logic;
|
|
signal iobuf_o : std_logic;
|
|
signal stratix3_fbin : std_logic;
|
|
signal oe_wire : std_logic;
|
|
signal pll_lock_sync : std_logic := '1';
|
|
signal fref_wire : std_logic;
|
|
signal icdrclk_wire : std_logic;
|
|
|
|
begin
|
|
|
|
-- checking for invalid parameters
|
|
MSG: process
|
|
begin
|
|
|
|
if (clk5_multiply_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk5_multiply_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk4_multiply_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk4_multiply_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk3_multiply_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk3_multiply_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk2_multiply_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk2_multiply_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk1_multiply_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk1_multiply_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk0_multiply_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk0_multiply_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk5_divide_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk5_divide_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk4_divide_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk4_divide_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk3_divide_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk3_divide_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk2_divide_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk2_divide_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk1_divide_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk1_divide_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (clk0_divide_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The clk0_divide_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
|
|
if (extclk3_multiply_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The extclk3_multiply_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (extclk2_multiply_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The extclk2_multiply_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (extclk1_multiply_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The extclk1_multiply_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (extclk0_multiply_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The extclk0_multiply_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
|
|
if (extclk3_divide_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The extclk3_divide_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (extclk2_divide_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The extclk2_divide_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (extclk1_divide_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The extclk1_divide_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (extclk0_divide_by <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The extclk0_divide_by parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if not ((alpha_tolower(primary_clock) = "inclk0") or (alpha_tolower(primary_clock) = "inclk1")) then
|
|
ASSERT FALSE
|
|
REPORT "The primary clock is set to an illegal value"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if ((IS_PIRANHA) and (alpha_tolower(operation_mode) = "external_feedback")) then
|
|
ASSERT FALSE
|
|
REPORT "The external feedback mode is not supported for the ARRIA II family."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if((IS_PIRANHA) and (alpha_tolower(pll_type) = "top_bottom")) then
|
|
ASSERT FALSE
|
|
REPORT "A pll_type specification is not supported for the ARRIA II family. It will be ignored."
|
|
SEVERITY WARNING;
|
|
end if;
|
|
|
|
if((IS_PIRANHA) and ((port_clk7 /= "PORT_UNUSED") or (port_clk8 /= "PORT_UNUSED") or (port_clk9 /= "PORT_UNUSED"))) then
|
|
ASSERT FALSE
|
|
REPORT "One or more clock outputs used in the design are not supported in ARRIA II family."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
wait;
|
|
end process MSG;
|
|
|
|
-- For fast mode, the stratix pll atom model will give active low signal on locked output.
|
|
-- Therefore, need to invert the lock signal for fast mode as in user view, locked signal is
|
|
-- always active high.
|
|
locked_wire <= (not locked_tmp) when ((not IS_STRATIXII) and
|
|
(not IS_CYCLONEII) and
|
|
alpha_tolower(pll_type) = "fast")
|
|
else (locked_tmp and pll_lock_sync) when (IS_STRATIXIII) or
|
|
(IS_CYCLONEIII)
|
|
else locked_tmp;
|
|
|
|
clkena_wire(0) <= clkena(0) when ((alpha_tolower(pll_type) /= "fast") or
|
|
(port_clkena0 = "PORT_USED")) and
|
|
(port_clkena0 /= "PORT_UNUSED")
|
|
else '1';
|
|
clkena_wire(1) <= clkena(1) when ((alpha_tolower(pll_type) /= "fast") or
|
|
(port_clkena1 = "PORT_USED")) and
|
|
(port_clkena1 /= "PORT_UNUSED")
|
|
else '1';
|
|
clkena_wire(2) <= clkena(2) when ((alpha_tolower(pll_type) /= "fast") or
|
|
(port_clkena2 = "PORT_USED")) and
|
|
(port_clkena2 /= "PORT_UNUSED")
|
|
else '1';
|
|
clkena_wire(3) <= clkena(3) when ((alpha_tolower(pll_type) /= "fast") or
|
|
(port_clkena3 = "PORT_USED")) and
|
|
(port_clkena3 /= "PORT_UNUSED")
|
|
else '1';
|
|
clkena_wire(4) <= clkena(4) when ((alpha_tolower(pll_type) /= "fast") or
|
|
(port_clkena4 = "PORT_USED")) and
|
|
(port_clkena4 /= "PORT_UNUSED")
|
|
else '1';
|
|
clkena_wire(5) <= clkena(5) when ((alpha_tolower(pll_type) /= "fast") or
|
|
(port_clkena5 = "PORT_USED")) and
|
|
(port_clkena5 /= "PORT_UNUSED")
|
|
else '1';
|
|
|
|
extclkena_wire(0) <= extclkena(0) when ((alpha_tolower(pll_type) /= "fast") or
|
|
(port_extclkena0 = "PORT_USED")) and
|
|
(port_extclkena0 /= "PORT_UNUSED")
|
|
else '1';
|
|
extclkena_wire(1) <= extclkena(1) when ((alpha_tolower(pll_type) /= "fast") or
|
|
(port_extclkena1 = "PORT_USED")) and
|
|
(port_extclkena1 /= "PORT_UNUSED")
|
|
else '1';
|
|
extclkena_wire(2) <= extclkena(2) when ((alpha_tolower(pll_type) /= "fast") or
|
|
(port_extclkena2 = "PORT_USED")) and
|
|
(port_extclkena2 /= "PORT_UNUSED")
|
|
else '1';
|
|
extclkena_wire(3) <= extclkena(3) when ((alpha_tolower(pll_type) /= "fast") or
|
|
(port_extclkena3 = "PORT_USED")) and
|
|
(port_extclkena3 /= "PORT_UNUSED")
|
|
else '1';
|
|
|
|
fbin_wire <= fbin when ((port_fbin = "PORT_CONNECTIVITY") or
|
|
(port_fbin = "PORT_USED"))
|
|
else '0';
|
|
|
|
pllena_wire <= pllena when ((port_pllena = "PORT_CONNECTIVITY") or
|
|
(port_pllena = "PORT_USED"))
|
|
else '1';
|
|
|
|
clkswitch_wire <= clkswitch when ((port_clkswitch = "PORT_CONNECTIVITY") or
|
|
(port_clkswitch = "PORT_USED"))
|
|
else '0';
|
|
|
|
areset_wire <= areset when ((port_areset = "PORT_CONNECTIVITY") or
|
|
(port_areset = "PORT_USED"))
|
|
else '0';
|
|
|
|
pfdena_wire <= pfdena when ((port_pfdena = "PORT_CONNECTIVITY") or
|
|
(port_pfdena = "PORT_USED"))
|
|
else '1';
|
|
|
|
scanclk_wire <= scanclk when (port_scanclk /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
scandata_wire <= scandata when (port_scandata /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
scanaclr_wire <= scanaclr when (port_scanaclr /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
scanread_wire <= scanread when (port_scanread /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
scanwrite_wire <= scanwrite when (port_scanwrite /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
configupdate_wire <= configupdate when (port_configupdate /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
phasecounterselect_wire(width_phasecounterselect-1 downto 0) <= phasecounterselect(width_phasecounterselect-1 downto 0) when (port_phasecounterselect /= "PORT_UNUSED")
|
|
else (others => '0');
|
|
|
|
phasecounterselect3 : if (width_phasecounterselect < 3) generate
|
|
phasecounterselect_wire(3) <= '0';
|
|
end generate phasecounterselect3;
|
|
|
|
phasestep_wire <= phasestep when (port_phasestep /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
phaseupdown_wire <= phaseupdown when (port_phaseupdown /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
scanclkena_wire <= scanclkena when (port_scanclkena /= "PORT_UNUSED")
|
|
else '1';
|
|
|
|
clk(0) <= clk_wire(0) when (port_clk0 /= "PORT_UNUSED")
|
|
else '0';
|
|
clk(1) <= clk_wire(1) when (port_clk1 /= "PORT_UNUSED")
|
|
else '0';
|
|
clk(2) <= clk_wire(2) when (port_clk2 /= "PORT_UNUSED")
|
|
else '0';
|
|
clk(3) <= clk_wire(3) when (port_clk3 /= "PORT_UNUSED")
|
|
else '0';
|
|
clk(4) <= clk_wire(4) when (port_clk4 /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
CLK5 : if (width_clock = 6) generate
|
|
clk(5) <= clk_wire(5) when (port_clk5 /= "PORT_UNUSED")
|
|
else '0';
|
|
end generate CLK5;
|
|
|
|
CLK5TO6: if (width_clock = 7) generate
|
|
clk(5) <= clk_wire(5) when (port_clk5 /= "PORT_UNUSED")
|
|
else '0';
|
|
clk(6) <= clk_wire(6) when (port_clk6 /= "PORT_UNUSED")
|
|
else '0';
|
|
end generate CLK5TO6;
|
|
|
|
CLK5TO9: if (width_clock = 10) generate
|
|
clk(5) <= clk_wire(5) when (port_clk5 /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
clk(6) <= clk_wire(6) when (port_clk6 /= "PORT_UNUSED")
|
|
else '0';
|
|
clk(7) <= clk_wire(7) when (port_clk7 /= "PORT_UNUSED")
|
|
else '0';
|
|
clk(8) <= clk_wire(8) when (port_clk8 /= "PORT_UNUSED")
|
|
else '0';
|
|
clk(9) <= clk_wire(9) when (port_clk9 /= "PORT_UNUSED")
|
|
else '0';
|
|
end generate CLK5TO9;
|
|
|
|
extclk(0) <= extclk_wire(0) when (port_extclk0 /= "PORT_UNUSED")
|
|
else '0';
|
|
extclk(1) <= extclk_wire(1) when (port_extclk1 /= "PORT_UNUSED")
|
|
else '0';
|
|
extclk(2) <= extclk_wire(2) when (port_extclk2 /= "PORT_UNUSED")
|
|
else '0';
|
|
extclk(3) <= extclk_wire(3) when (port_extclk3 /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
clkbad(0) <= clkbad_wire(0) when (port_clkbad0 /= "PORT_UNUSED")
|
|
else '0';
|
|
clkbad(1) <= clkbad_wire(1) when (port_clkbad1 /= "PORT_UNUSED")
|
|
else '0';
|
|
activeclock <= activeclock_wire when (port_activeclock /= "PORT_UNUSED")
|
|
else '0';
|
|
clkloss <= clkloss_wire when (port_clkloss /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
scandataout <= scandataout_wire when (port_scandataout /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
scandone <= scandone_wire when (port_scandone /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
sclkout0 <= sclkout0_wire when (port_sclkout0 /= "PORT_UNUSED")
|
|
else '0';
|
|
sclkout1 <= sclkout1_wire when (port_sclkout1 /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
locked <= locked_wire when (port_locked /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
phasedone <= phasedone_wire when (port_phasedone /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
vcooverrange <= vcooverrange_wire when (port_vcooverrange /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
vcounderrange <= vcounderrange_wire when (port_vcounderrange /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
fbout <= fbout_wire when (port_fbout /= "PORT_UNUSED")
|
|
else '0';
|
|
|
|
stratix3_fbin <= iobuf_o when ((using_fbmimicbidir_port = "ON") and (alpha_tolower(operation_mode) = "zero_delay_buffer") and (IS_STRATIXIII) and (not IS_PIRANHA))
|
|
else fbout_wire when ((alpha_tolower(operation_mode) = "zero_delay_buffer") and (IS_PIRANHA))
|
|
else fbin;
|
|
|
|
oe_wire <= '1';
|
|
|
|
fref <= fref_wire;
|
|
|
|
icdrclk <= icdrclk_wire;
|
|
|
|
-- Instantiate stratix_pll
|
|
STRATIX_ALTPLL:
|
|
if (FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL(intended_device_family) = true) generate
|
|
M0: MF_stratix_pll
|
|
generic map(
|
|
operation_mode => alpha_tolower(operation_mode),
|
|
pll_type => alpha_tolower(pll_type),
|
|
qualify_conf_done => alpha_tolower(qualify_conf_done),
|
|
compensate_clock => alpha_tolower(compensate_clock),
|
|
scan_chain => alpha_tolower(scan_chain),
|
|
primary_clock => alpha_tolower(primary_clock),
|
|
inclk0_input_frequency => inclk0_input_frequency,
|
|
inclk1_input_frequency => inclk1_input_frequency,
|
|
gate_lock_signal => alpha_tolower(gate_lock_signal),
|
|
gate_lock_counter => gate_lock_counter,
|
|
valid_lock_multiplier => valid_lock_multiplier,
|
|
invalid_lock_multiplier => invalid_lock_multiplier,
|
|
switch_over_on_lossclk => alpha_tolower(switch_over_on_lossclk),
|
|
switch_over_on_gated_lock => alpha_tolower(switch_over_on_gated_lock),
|
|
enable_switch_over_counter => alpha_tolower(enable_switch_over_counter),
|
|
switch_over_counter => switch_over_counter,
|
|
feedback_source => alpha_tolower(feedback_source),
|
|
bandwidth => bandwidth,
|
|
bandwidth_type => alpha_tolower(bandwidth_type),
|
|
spread_frequency => spread_frequency,
|
|
down_spread => down_spread,
|
|
simulation_type => alpha_tolower(simulation_type),
|
|
skip_vco => alpha_tolower(skip_vco),
|
|
family_name => intended_device_family,
|
|
|
|
-- internal clock specifications
|
|
clk5_multiply_by => clk5_multiply_by,
|
|
clk4_multiply_by => clk4_multiply_by,
|
|
clk3_multiply_by => clk3_multiply_by,
|
|
clk2_multiply_by => clk2_multiply_by,
|
|
clk1_multiply_by => clk1_multiply_by,
|
|
clk0_multiply_by => clk0_multiply_by,
|
|
clk5_divide_by => clk5_divide_by,
|
|
clk4_divide_by => clk4_divide_by,
|
|
clk3_divide_by => clk3_divide_by,
|
|
clk2_divide_by => clk2_divide_by,
|
|
clk1_divide_by => clk1_divide_by,
|
|
clk0_divide_by => clk0_divide_by,
|
|
clk5_phase_shift => clk5_phase_shift,
|
|
clk4_phase_shift => clk4_phase_shift,
|
|
clk3_phase_shift => clk3_phase_shift,
|
|
clk2_phase_shift => clk2_phase_shift,
|
|
clk1_phase_shift => clk1_phase_shift,
|
|
clk0_phase_shift => clk0_phase_shift,
|
|
clk5_time_delay => clk5_time_delay,
|
|
clk4_time_delay => clk4_time_delay,
|
|
clk3_time_delay => clk3_time_delay,
|
|
clk2_time_delay => clk2_time_delay,
|
|
clk1_time_delay => clk1_time_delay,
|
|
clk0_time_delay => clk0_time_delay,
|
|
clk5_duty_cycle => clk5_duty_cycle,
|
|
clk4_duty_cycle => clk4_duty_cycle,
|
|
clk3_duty_cycle => clk3_duty_cycle,
|
|
clk2_duty_cycle => clk2_duty_cycle,
|
|
clk1_duty_cycle => clk1_duty_cycle,
|
|
clk0_duty_cycle => clk0_duty_cycle,
|
|
|
|
-- external clock specifications
|
|
extclk3_multiply_by => extclk3_multiply_by,
|
|
extclk2_multiply_by => extclk2_multiply_by,
|
|
extclk1_multiply_by => extclk1_multiply_by,
|
|
extclk0_multiply_by => extclk0_multiply_by,
|
|
extclk3_divide_by => extclk3_divide_by,
|
|
extclk2_divide_by => extclk2_divide_by,
|
|
extclk1_divide_by => extclk1_divide_by,
|
|
extclk0_divide_by => extclk0_divide_by,
|
|
extclk3_phase_shift => extclk3_phase_shift,
|
|
extclk2_phase_shift => extclk2_phase_shift,
|
|
extclk1_phase_shift => extclk1_phase_shift,
|
|
extclk0_phase_shift => extclk0_phase_shift,
|
|
extclk3_time_delay => extclk3_time_delay,
|
|
extclk2_time_delay => extclk2_time_delay,
|
|
extclk1_time_delay => extclk1_time_delay,
|
|
extclk0_time_delay => extclk0_time_delay,
|
|
extclk3_duty_cycle => extclk3_duty_cycle,
|
|
extclk2_duty_cycle => extclk2_duty_cycle,
|
|
extclk1_duty_cycle => extclk1_duty_cycle,
|
|
extclk0_duty_cycle => extclk0_duty_cycle,
|
|
|
|
-- advanced user parameters
|
|
vco_min => get_vco_min_s(vco_min),
|
|
vco_max => get_vco_max(vco_max),
|
|
vco_center => vco_center,
|
|
pfd_min => pfd_min,
|
|
pfd_max => pfd_max,
|
|
m_initial => m_initial,
|
|
m => m,
|
|
n => n,
|
|
m2 => m2,
|
|
n2 => n2,
|
|
ss => ss,
|
|
l0_high => l0_high,
|
|
l1_high => l1_high,
|
|
g0_high => g0_high,
|
|
g1_high => g1_high,
|
|
g2_high => g2_high,
|
|
g3_high => g3_high,
|
|
e0_high => e0_high,
|
|
e1_high => e1_high,
|
|
e2_high => e2_high,
|
|
e3_high => e3_high,
|
|
l0_low => l0_low,
|
|
l1_low => l1_low,
|
|
g0_low => g0_low,
|
|
g1_low => g1_low,
|
|
g2_low => g2_low,
|
|
g3_low => g3_low,
|
|
e0_low => e0_low,
|
|
e1_low => e1_low,
|
|
e2_low => e2_low,
|
|
e3_low => e3_low,
|
|
l0_initial => l0_initial,
|
|
l1_initial => l1_initial,
|
|
g0_initial => g0_initial,
|
|
g1_initial => g1_initial,
|
|
g2_initial => g2_initial,
|
|
g3_initial => g3_initial,
|
|
e0_initial => e0_initial,
|
|
e1_initial => e1_initial,
|
|
e2_initial => e2_initial,
|
|
e3_initial => e3_initial,
|
|
l0_mode => alpha_tolower(l0_mode),
|
|
l1_mode => alpha_tolower(l1_mode),
|
|
g0_mode => alpha_tolower(g0_mode),
|
|
g1_mode => alpha_tolower(g1_mode),
|
|
g2_mode => alpha_tolower(g2_mode),
|
|
g3_mode => alpha_tolower(g3_mode),
|
|
e0_mode => alpha_tolower(e0_mode),
|
|
e1_mode => alpha_tolower(e1_mode),
|
|
e2_mode => alpha_tolower(e2_mode),
|
|
e3_mode => alpha_tolower(e3_mode),
|
|
l0_ph => l0_ph,
|
|
l1_ph => l1_ph,
|
|
g0_ph => g0_ph,
|
|
g1_ph => g1_ph,
|
|
g2_ph => g2_ph,
|
|
g3_ph => g3_ph,
|
|
e0_ph => e0_ph,
|
|
e1_ph => e1_ph,
|
|
e2_ph => e2_ph,
|
|
e3_ph => e3_ph,
|
|
m_ph => m_ph,
|
|
l0_time_delay => l0_time_delay,
|
|
l1_time_delay => l1_time_delay,
|
|
g0_time_delay => g0_time_delay,
|
|
g1_time_delay => g1_time_delay,
|
|
g2_time_delay => g2_time_delay,
|
|
g3_time_delay => g3_time_delay,
|
|
e0_time_delay => e0_time_delay,
|
|
e1_time_delay => e1_time_delay,
|
|
e2_time_delay => e2_time_delay,
|
|
e3_time_delay => e3_time_delay,
|
|
m_time_delay => m_time_delay,
|
|
n_time_delay => n_time_delay,
|
|
|
|
extclk3_counter => alpha_tolower(extclk3_counter),
|
|
extclk2_counter => alpha_tolower(extclk2_counter),
|
|
extclk1_counter => alpha_tolower(extclk1_counter),
|
|
extclk0_counter => alpha_tolower(extclk0_counter),
|
|
clk5_counter => alpha_tolower(clk5_counter),
|
|
clk4_counter => alpha_tolower(clk4_counter),
|
|
clk3_counter => alpha_tolower(clk3_counter),
|
|
clk2_counter => alpha_tolower(clk2_counter),
|
|
clk1_counter => alpha_tolower(clk1_counter),
|
|
clk0_counter => alpha_tolower(clk0_counter),
|
|
enable0_counter => alpha_tolower(enable0_counter),
|
|
enable1_counter => alpha_tolower(enable1_counter),
|
|
|
|
charge_pump_current => charge_pump_current,
|
|
loop_filter_r => loop_filter_r,
|
|
loop_filter_c => loop_filter_c
|
|
)
|
|
port map (
|
|
inclk => inclk,
|
|
fbin => fbin_wire,
|
|
ena => pllena_wire,
|
|
clkswitch => clkswitch_wire,
|
|
areset => areset_wire,
|
|
pfdena => pfdena_wire,
|
|
clkena => clkena_wire,
|
|
extclkena => extclkena_wire,
|
|
scanclk => scanclk_wire,
|
|
scanaclr => scanaclr_wire,
|
|
scandata => scandata_wire,
|
|
comparator => comparator,
|
|
clk(0) => clk_wire(0),
|
|
clk(1) => clk_wire(1),
|
|
clk(2) => clk_wire(2),
|
|
clk(3) => clk_wire(3),
|
|
clk(4) => clk_wire(4),
|
|
clk(5) => clk_wire(5),
|
|
extclk => extclk_wire,
|
|
clkbad => clkbad_wire,
|
|
enable0 => enable0,
|
|
enable1 => enable1,
|
|
activeclock => activeclock_wire,
|
|
clkloss => clkloss_wire,
|
|
locked => locked_tmp,
|
|
scandataout => scandataout_wire
|
|
);
|
|
end generate STRATIX_ALTPLL;
|
|
|
|
-- Instantiate stratixii_pll
|
|
STRATIXII_ALTPLL:
|
|
if ((FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL(intended_device_family) = true) and
|
|
(FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family) = false)) generate
|
|
M1 : MF_stratixii_pll
|
|
generic map(
|
|
operation_mode => alpha_tolower(operation_mode),
|
|
pll_type => alpha_tolower(pll_type),
|
|
qualify_conf_done => alpha_tolower(qualify_conf_done),
|
|
compensate_clock => alpha_tolower(compensate_clock),
|
|
inclk0_input_frequency => inclk0_input_frequency,
|
|
inclk1_input_frequency => inclk1_input_frequency,
|
|
gate_lock_signal => alpha_tolower(gate_lock_signal),
|
|
gate_lock_counter => gate_lock_counter,
|
|
valid_lock_multiplier => valid_lock_multiplier,
|
|
invalid_lock_multiplier => invalid_lock_multiplier,
|
|
switch_over_type => alpha_tolower(switch_over_type),
|
|
switch_over_on_lossclk => alpha_tolower(switch_over_on_lossclk),
|
|
switch_over_on_gated_lock => alpha_tolower(switch_over_on_gated_lock),
|
|
enable_switch_over_counter => alpha_tolower(enable_switch_over_counter),
|
|
switch_over_counter => switch_over_counter,
|
|
feedback_source => get_feedback_source(feedback_source),
|
|
bandwidth => bandwidth,
|
|
bandwidth_type => alpha_tolower(bandwidth_type),
|
|
spread_frequency => spread_frequency,
|
|
down_spread => down_spread,
|
|
self_reset_on_gated_loss_lock => self_reset_on_gated_loss_lock,
|
|
simulation_type => alpha_tolower(simulation_type),
|
|
family_name => intended_device_family,
|
|
|
|
-- internal clock specifications
|
|
clk5_multiply_by => clk5_multiply_by,
|
|
clk4_multiply_by => clk4_multiply_by,
|
|
clk3_multiply_by => clk3_multiply_by,
|
|
clk2_multiply_by => clk2_multiply_by,
|
|
clk1_multiply_by => clk1_multiply_by,
|
|
clk0_multiply_by => clk0_multiply_by,
|
|
clk5_divide_by => clk5_divide_by,
|
|
clk4_divide_by => clk4_divide_by,
|
|
clk3_divide_by => clk3_divide_by,
|
|
clk2_divide_by => clk2_divide_by,
|
|
clk1_divide_by => clk1_divide_by,
|
|
clk0_divide_by => clk0_divide_by,
|
|
clk5_phase_shift => clk5_phase_shift,
|
|
clk4_phase_shift => clk4_phase_shift,
|
|
clk3_phase_shift => clk3_phase_shift,
|
|
clk2_phase_shift => clk2_phase_shift,
|
|
clk1_phase_shift => clk1_phase_shift,
|
|
clk0_phase_shift => clk0_phase_shift,
|
|
clk5_duty_cycle => clk5_duty_cycle,
|
|
clk4_duty_cycle => clk4_duty_cycle,
|
|
clk3_duty_cycle => clk3_duty_cycle,
|
|
clk2_duty_cycle => clk2_duty_cycle,
|
|
clk1_duty_cycle => clk1_duty_cycle,
|
|
clk0_duty_cycle => clk0_duty_cycle,
|
|
|
|
-- advanced user parameters
|
|
vco_min => get_vco_min_s2(vco_min),
|
|
vco_max => get_vco_max(vco_max),
|
|
vco_center => vco_center,
|
|
pfd_min => pfd_min,
|
|
pfd_max => pfd_max,
|
|
m_initial => m_initial,
|
|
m => m,
|
|
n => n,
|
|
m2 => m2,
|
|
n2 => n2,
|
|
ss => ss,
|
|
c0_high => c0_high,
|
|
c1_high => c1_high,
|
|
c2_high => c2_high,
|
|
c3_high => c3_high,
|
|
c4_high => c4_high,
|
|
c5_high => c5_high,
|
|
c0_low => c0_low,
|
|
c1_low => c1_low,
|
|
c2_low => c2_low,
|
|
c3_low => c3_low,
|
|
c4_low => c4_low,
|
|
c5_low => c5_low,
|
|
c0_initial => c0_initial,
|
|
c1_initial => c1_initial,
|
|
c2_initial => c2_initial,
|
|
c3_initial => c3_initial,
|
|
c4_initial => c4_initial,
|
|
c5_initial => c5_initial,
|
|
c0_mode => alpha_tolower(c0_mode),
|
|
c1_mode => alpha_tolower(c1_mode),
|
|
c2_mode => alpha_tolower(c2_mode),
|
|
c3_mode => alpha_tolower(c3_mode),
|
|
c4_mode => alpha_tolower(c4_mode),
|
|
c5_mode => alpha_tolower(c5_mode),
|
|
c0_ph => c0_ph,
|
|
c1_ph => c1_ph,
|
|
c2_ph => c2_ph,
|
|
c3_ph => c3_ph,
|
|
c4_ph => c4_ph,
|
|
c5_ph => c5_ph,
|
|
m_ph => m_ph,
|
|
c1_use_casc_in => c1_use_casc_in,
|
|
c2_use_casc_in => c2_use_casc_in,
|
|
c3_use_casc_in => c3_use_casc_in,
|
|
c4_use_casc_in => c4_use_casc_in,
|
|
c5_use_casc_in => c5_use_casc_in,
|
|
m_test_source => m_test_source,
|
|
c0_test_source => c0_test_source,
|
|
c1_test_source => c1_test_source,
|
|
c2_test_source => c2_test_source,
|
|
c3_test_source => c3_test_source,
|
|
c4_test_source => c4_test_source,
|
|
c5_test_source => c5_test_source,
|
|
clk5_counter => get_clk5_counter(clk5_counter),
|
|
clk4_counter => get_clk4_counter(clk4_counter),
|
|
clk3_counter => get_clk3_counter(clk3_counter),
|
|
clk2_counter => get_clk2_counter(clk2_counter),
|
|
clk1_counter => get_clk1_counter(clk1_counter),
|
|
clk0_counter => get_clk0_counter(clk0_counter),
|
|
enable0_counter => get_enable0_counter(enable0_counter),
|
|
enable1_counter => get_enable1_counter(enable1_counter),
|
|
sclkout0_phase_shift => sclkout0_phase_shift,
|
|
sclkout1_phase_shift => sclkout1_phase_shift,
|
|
vco_multiply_by => vco_multiply_by,
|
|
vco_divide_by => vco_divide_by,
|
|
charge_pump_current => get_charge_pump_current(m, charge_pump_current),
|
|
loop_filter_r => loop_filter_r,
|
|
loop_filter_c => get_loop_filter_c(m, loop_filter_c),
|
|
sim_gate_lock_device_behavior => alpha_tolower(sim_gate_lock_device_behavior)
|
|
)
|
|
port map (
|
|
inclk => inclk,
|
|
fbin => fbin_wire,
|
|
ena => pllena_wire,
|
|
clkswitch => clkswitch_wire,
|
|
areset => areset_wire,
|
|
pfdena => pfdena_wire,
|
|
scanclk => scanclk_wire,
|
|
scanread => scanread_wire,
|
|
scanwrite => scanwrite_wire,
|
|
scandata => scandata_wire,
|
|
clk(0) => clk_wire(0),
|
|
clk(1) => clk_wire(1),
|
|
clk(2) => clk_wire(2),
|
|
clk(3) => clk_wire(3),
|
|
clk(4) => clk_wire(4),
|
|
clk(5) => clk_wire(5),
|
|
clkbad => clkbad_wire,
|
|
enable0 => enable0,
|
|
enable1 => enable1,
|
|
activeclock => activeclock_wire,
|
|
clkloss => clkloss_wire,
|
|
locked => locked_tmp,
|
|
scandataout => scandataout_wire,
|
|
scandone => scandone_wire,
|
|
sclkout(0) => sclkout0_wire,
|
|
sclkout(1) => sclkout1_wire
|
|
);
|
|
end generate STRATIXII_ALTPLL;
|
|
|
|
-- Instantiate cycloneii_pll
|
|
CYCLONEII_ALTPLL:
|
|
if (FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family) = true) generate
|
|
M3 : MF_stratixii_pll
|
|
generic map(
|
|
operation_mode => alpha_tolower(operation_mode),
|
|
pll_type => alpha_tolower(pll_type),
|
|
qualify_conf_done => alpha_tolower(qualify_conf_done),
|
|
compensate_clock => alpha_tolower(compensate_clock),
|
|
inclk0_input_frequency => inclk0_input_frequency,
|
|
inclk1_input_frequency => inclk1_input_frequency,
|
|
gate_lock_signal => alpha_tolower(gate_lock_signal),
|
|
gate_lock_counter => gate_lock_counter,
|
|
valid_lock_multiplier => valid_lock_multiplier,
|
|
invalid_lock_multiplier => invalid_lock_multiplier,
|
|
switch_over_type => "manual",
|
|
switch_over_on_lossclk => alpha_tolower(switch_over_on_lossclk),
|
|
switch_over_on_gated_lock => alpha_tolower(switch_over_on_gated_lock),
|
|
enable_switch_over_counter => alpha_tolower(enable_switch_over_counter),
|
|
switch_over_counter => switch_over_counter,
|
|
feedback_source => get_feedback_source(feedback_source),
|
|
bandwidth => bandwidth,
|
|
bandwidth_type => alpha_tolower(bandwidth_type),
|
|
spread_frequency => spread_frequency,
|
|
down_spread => down_spread,
|
|
simulation_type => alpha_tolower(simulation_type),
|
|
family_name => intended_device_family,
|
|
|
|
-- internal clock specifications
|
|
clk5_multiply_by => clk5_multiply_by,
|
|
clk4_multiply_by => clk4_multiply_by,
|
|
clk3_multiply_by => clk3_multiply_by,
|
|
clk2_multiply_by => clk2_multiply_by,
|
|
clk1_multiply_by => clk1_multiply_by,
|
|
clk0_multiply_by => clk0_multiply_by,
|
|
clk5_divide_by => clk5_divide_by,
|
|
clk4_divide_by => clk4_divide_by,
|
|
clk3_divide_by => clk3_divide_by,
|
|
clk2_divide_by => clk2_divide_by,
|
|
clk1_divide_by => clk1_divide_by,
|
|
clk0_divide_by => clk0_divide_by,
|
|
clk5_phase_shift => clk5_phase_shift,
|
|
clk4_phase_shift => clk4_phase_shift,
|
|
clk3_phase_shift => clk3_phase_shift,
|
|
clk2_phase_shift => clk2_phase_shift,
|
|
clk1_phase_shift => clk1_phase_shift,
|
|
clk0_phase_shift => clk0_phase_shift,
|
|
clk5_duty_cycle => clk5_duty_cycle,
|
|
clk4_duty_cycle => clk4_duty_cycle,
|
|
clk3_duty_cycle => clk3_duty_cycle,
|
|
clk2_duty_cycle => clk2_duty_cycle,
|
|
clk1_duty_cycle => clk1_duty_cycle,
|
|
clk0_duty_cycle => clk0_duty_cycle,
|
|
clk2_output_frequency => clk2_output_frequency,
|
|
clk1_output_frequency => clk1_output_frequency,
|
|
clk0_output_frequency => clk0_output_frequency,
|
|
|
|
-- advanced user parameters
|
|
vco_min => get_vco_min_c2(vco_min),
|
|
vco_max => get_vco_max(vco_max),
|
|
vco_center => vco_center,
|
|
pfd_min => pfd_min,
|
|
pfd_max => pfd_max,
|
|
m_initial => m_initial,
|
|
m => m,
|
|
n => n,
|
|
m2 => m2,
|
|
n2 => n2,
|
|
ss => ss,
|
|
c0_high => c0_high,
|
|
c1_high => c1_high,
|
|
c2_high => c2_high,
|
|
c3_high => c3_high,
|
|
c4_high => c4_high,
|
|
c5_high => c5_high,
|
|
c0_low => c0_low,
|
|
c1_low => c1_low,
|
|
c2_low => c2_low,
|
|
c3_low => c3_low,
|
|
c4_low => c4_low,
|
|
c5_low => c5_low,
|
|
c0_initial => c0_initial,
|
|
c1_initial => c1_initial,
|
|
c2_initial => c2_initial,
|
|
c3_initial => c3_initial,
|
|
c4_initial => c4_initial,
|
|
c5_initial => c5_initial,
|
|
c0_mode => alpha_tolower(c0_mode),
|
|
c1_mode => alpha_tolower(c1_mode),
|
|
c2_mode => alpha_tolower(c2_mode),
|
|
c3_mode => alpha_tolower(c3_mode),
|
|
c4_mode => alpha_tolower(c4_mode),
|
|
c5_mode => alpha_tolower(c5_mode),
|
|
c0_ph => c0_ph,
|
|
c1_ph => c1_ph,
|
|
c2_ph => c2_ph,
|
|
c3_ph => c3_ph,
|
|
c4_ph => c4_ph,
|
|
c5_ph => c5_ph,
|
|
m_ph => m_ph,
|
|
c1_use_casc_in => c1_use_casc_in,
|
|
c2_use_casc_in => c2_use_casc_in,
|
|
c3_use_casc_in => c3_use_casc_in,
|
|
c4_use_casc_in => c4_use_casc_in,
|
|
c5_use_casc_in => c5_use_casc_in,
|
|
clk5_counter => get_clk5_counter(clk5_counter),
|
|
clk4_counter => get_clk4_counter(clk4_counter),
|
|
clk3_counter => get_clk3_counter(clk3_counter),
|
|
clk2_counter => get_clk2_counter(clk2_counter),
|
|
clk1_counter => get_clk1_counter(clk1_counter),
|
|
clk0_counter => get_clk0_counter(clk0_counter),
|
|
enable0_counter => get_enable0_counter(enable0_counter),
|
|
enable1_counter => get_enable1_counter(enable1_counter),
|
|
sclkout0_phase_shift => sclkout0_phase_shift,
|
|
sclkout1_phase_shift => sclkout1_phase_shift,
|
|
vco_multiply_by => vco_multiply_by,
|
|
vco_divide_by => vco_divide_by,
|
|
charge_pump_current => get_charge_pump_current(m, charge_pump_current),
|
|
loop_filter_r => loop_filter_r,
|
|
loop_filter_c => get_loop_filter_c(m, loop_filter_c),
|
|
sim_gate_lock_device_behavior => alpha_tolower(sim_gate_lock_device_behavior)
|
|
)
|
|
port map (
|
|
inclk => inclk,
|
|
fbin => open,
|
|
ena => pllena_wire,
|
|
clkswitch => clkswitch_wire,
|
|
areset => areset_wire,
|
|
pfdena => pfdena_wire,
|
|
scanclk => open,
|
|
scanread => open,
|
|
scanwrite => open,
|
|
scandata => open,
|
|
clk(0) => clk_wire(0),
|
|
clk(1) => clk_wire(1),
|
|
clk(2) => clk_wire(2),
|
|
clk(3) => clk_tmp(0),
|
|
clk(4) => clk_tmp(1),
|
|
clk(5) => clk_tmp(2),
|
|
clkbad => open,
|
|
enable0 => open,
|
|
enable1 => open,
|
|
activeclock => open,
|
|
clkloss => open,
|
|
locked => locked_tmp,
|
|
scandataout => open,
|
|
scandone => open,
|
|
sclkout => open
|
|
);
|
|
end generate CYCLONEII_ALTPLL;
|
|
|
|
-- Instantiate stratixiii_pll
|
|
STRATIXIII_ALTPLL:
|
|
if (IS_STRATIXIII) generate
|
|
M4 : MF_stratixiii_pll
|
|
generic map(
|
|
operation_mode => alpha_tolower(operation_mode),
|
|
pll_type => alpha_tolower(pll_type),
|
|
compensate_clock => alpha_tolower(compensate_clock),
|
|
inclk0_input_frequency => inclk0_input_frequency,
|
|
inclk1_input_frequency => inclk1_input_frequency,
|
|
self_reset_on_loss_lock => alpha_tolower(self_reset_on_loss_lock),
|
|
switch_over_type => alpha_tolower(switch_over_type),
|
|
enable_switch_over_counter => alpha_tolower(enable_switch_over_counter),
|
|
switch_over_counter => switch_over_counter,
|
|
bandwidth => bandwidth,
|
|
bandwidth_type => alpha_tolower(bandwidth_type),
|
|
lock_high => lock_high,
|
|
lock_low => lock_low,
|
|
lock_window_ui => lock_window_ui,
|
|
simulation_type => alpha_tolower(simulation_type),
|
|
family_name => intended_device_family,
|
|
|
|
-- internal clock specifications
|
|
clk9_multiply_by => clk9_multiply_by,
|
|
clk8_multiply_by => clk8_multiply_by,
|
|
clk7_multiply_by => clk7_multiply_by,
|
|
clk6_multiply_by => clk6_multiply_by,
|
|
clk5_multiply_by => clk5_multiply_by,
|
|
clk4_multiply_by => clk4_multiply_by,
|
|
clk3_multiply_by => clk3_multiply_by,
|
|
clk2_multiply_by => clk2_multiply_by,
|
|
clk1_multiply_by => clk1_multiply_by,
|
|
clk0_multiply_by => clk0_multiply_by,
|
|
clk9_divide_by => clk9_divide_by,
|
|
clk8_divide_by => clk8_divide_by,
|
|
clk7_divide_by => clk7_divide_by,
|
|
clk6_divide_by => clk6_divide_by,
|
|
clk5_divide_by => clk5_divide_by,
|
|
clk4_divide_by => clk4_divide_by,
|
|
clk3_divide_by => clk3_divide_by,
|
|
clk2_divide_by => clk2_divide_by,
|
|
clk1_divide_by => clk1_divide_by,
|
|
clk0_divide_by => clk0_divide_by,
|
|
clk9_phase_shift => clk9_phase_shift,
|
|
clk8_phase_shift => clk8_phase_shift,
|
|
clk7_phase_shift => clk7_phase_shift,
|
|
clk6_phase_shift => clk6_phase_shift,
|
|
clk5_phase_shift => clk5_phase_shift,
|
|
clk4_phase_shift => clk4_phase_shift,
|
|
clk3_phase_shift => clk3_phase_shift,
|
|
clk2_phase_shift => clk2_phase_shift,
|
|
clk1_phase_shift => clk1_phase_shift,
|
|
clk0_phase_shift => clk0_phase_shift,
|
|
clk9_duty_cycle => clk9_duty_cycle,
|
|
clk8_duty_cycle => clk8_duty_cycle,
|
|
clk7_duty_cycle => clk7_duty_cycle,
|
|
clk6_duty_cycle => clk6_duty_cycle,
|
|
clk5_duty_cycle => clk5_duty_cycle,
|
|
clk4_duty_cycle => clk4_duty_cycle,
|
|
clk3_duty_cycle => clk3_duty_cycle,
|
|
clk2_duty_cycle => clk2_duty_cycle,
|
|
clk1_duty_cycle => clk1_duty_cycle,
|
|
clk0_duty_cycle => clk0_duty_cycle,
|
|
|
|
-- advanced user parameters
|
|
vco_min => get_vco_min_s3(vco_min),
|
|
vco_max => get_vco_max(vco_max),
|
|
vco_center => vco_center,
|
|
pfd_min => pfd_min,
|
|
pfd_max => pfd_max,
|
|
m_initial => m_initial,
|
|
m => m,
|
|
n => n,
|
|
c0_high => c0_high,
|
|
c1_high => c1_high,
|
|
c2_high => c2_high,
|
|
c3_high => c3_high,
|
|
c4_high => c4_high,
|
|
c5_high => c5_high,
|
|
c6_high => c6_high,
|
|
c7_high => c7_high,
|
|
c8_high => c8_high,
|
|
c9_high => c9_high,
|
|
c0_low => c0_low,
|
|
c1_low => c1_low,
|
|
c2_low => c2_low,
|
|
c3_low => c3_low,
|
|
c4_low => c4_low,
|
|
c5_low => c5_low,
|
|
c6_low => c6_low,
|
|
c7_low => c7_low,
|
|
c8_low => c8_low,
|
|
c9_low => c9_low,
|
|
c0_initial => c0_initial,
|
|
c1_initial => c1_initial,
|
|
c2_initial => c2_initial,
|
|
c3_initial => c3_initial,
|
|
c4_initial => c4_initial,
|
|
c5_initial => c5_initial,
|
|
c6_initial => c6_initial,
|
|
c7_initial => c7_initial,
|
|
c8_initial => c8_initial,
|
|
c9_initial => c9_initial,
|
|
c0_mode => alpha_tolower(c0_mode),
|
|
c1_mode => alpha_tolower(c1_mode),
|
|
c2_mode => alpha_tolower(c2_mode),
|
|
c3_mode => alpha_tolower(c3_mode),
|
|
c4_mode => alpha_tolower(c4_mode),
|
|
c5_mode => alpha_tolower(c5_mode),
|
|
c6_mode => alpha_tolower(c6_mode),
|
|
c7_mode => alpha_tolower(c7_mode),
|
|
c8_mode => alpha_tolower(c8_mode),
|
|
c9_mode => alpha_tolower(c9_mode),
|
|
c0_ph => c0_ph,
|
|
c1_ph => c1_ph,
|
|
c2_ph => c2_ph,
|
|
c3_ph => c3_ph,
|
|
c4_ph => c4_ph,
|
|
c5_ph => c5_ph,
|
|
c6_ph => c6_ph,
|
|
c7_ph => c7_ph,
|
|
c8_ph => c8_ph,
|
|
c9_ph => c9_ph,
|
|
m_ph => m_ph,
|
|
c1_use_casc_in => c1_use_casc_in,
|
|
c2_use_casc_in => c2_use_casc_in,
|
|
c3_use_casc_in => c3_use_casc_in,
|
|
c4_use_casc_in => c4_use_casc_in,
|
|
c5_use_casc_in => c5_use_casc_in,
|
|
c6_use_casc_in => c6_use_casc_in,
|
|
c7_use_casc_in => c7_use_casc_in,
|
|
c8_use_casc_in => c8_use_casc_in,
|
|
c9_use_casc_in => c9_use_casc_in,
|
|
m_test_source => get_test_source(m_test_source),
|
|
c0_test_source => get_test_source(c0_test_source),
|
|
c1_test_source => get_test_source(c1_test_source),
|
|
c2_test_source => get_test_source(c2_test_source),
|
|
c3_test_source => get_test_source(c3_test_source),
|
|
c4_test_source => get_test_source(c4_test_source),
|
|
c5_test_source => get_test_source(c5_test_source),
|
|
c6_test_source => get_test_source(c6_test_source),
|
|
c7_test_source => get_test_source(c7_test_source),
|
|
c8_test_source => get_test_source(c8_test_source),
|
|
c9_test_source => get_test_source(c9_test_source),
|
|
clk9_counter => get_clk_counter(clk9_counter, port_clk9),
|
|
clk8_counter => get_clk_counter(clk8_counter, port_clk8),
|
|
clk7_counter => get_clk_counter(clk7_counter, port_clk7),
|
|
clk6_counter => get_clk_counter(clk6_counter, port_clk6),
|
|
clk5_counter => get_clk_counter(get_clk5_counter(clk5_counter), port_clk5),
|
|
clk4_counter => get_clk_counter(get_clk4_counter(clk4_counter), port_clk4),
|
|
clk3_counter => get_clk_counter(get_clk3_counter(clk3_counter), port_clk3),
|
|
clk2_counter => get_clk_counter(get_clk2_counter(clk2_counter), port_clk2),
|
|
clk1_counter => get_clk_counter(get_clk1_counter(clk1_counter), port_clk1),
|
|
clk0_counter => get_clk_counter(get_clk0_counter(clk0_counter), port_clk0),
|
|
dpa_multiply_by => dpa_multiply_by,
|
|
dpa_divide_by => dpa_divide_by,
|
|
dpa_divider => dpa_divider,
|
|
vco_multiply_by => vco_multiply_by,
|
|
vco_divide_by => vco_divide_by,
|
|
vco_frequency_control => alpha_tolower(vco_frequency_control),
|
|
vco_phase_shift_step => vco_phase_shift_step,
|
|
charge_pump_current => charge_pump_current,
|
|
loop_filter_r => loop_filter_r,
|
|
loop_filter_c => loop_filter_c,
|
|
charge_pump_current_bits => charge_pump_current_bits,
|
|
loop_filter_c_bits => loop_filter_c_bits,
|
|
loop_filter_r_bits => loop_filter_r_bits,
|
|
clk9_use_even_counter_mode => alpha_tolower(clk0_use_even_counter_mode),
|
|
clk8_use_even_counter_mode => alpha_tolower(clk1_use_even_counter_mode),
|
|
clk7_use_even_counter_mode => alpha_tolower(clk2_use_even_counter_mode),
|
|
clk6_use_even_counter_mode => alpha_tolower(clk3_use_even_counter_mode),
|
|
clk5_use_even_counter_mode => alpha_tolower(clk4_use_even_counter_mode),
|
|
clk4_use_even_counter_mode => alpha_tolower(clk5_use_even_counter_mode),
|
|
clk3_use_even_counter_mode => alpha_tolower(clk6_use_even_counter_mode),
|
|
clk2_use_even_counter_mode => alpha_tolower(clk7_use_even_counter_mode),
|
|
clk1_use_even_counter_mode => alpha_tolower(clk8_use_even_counter_mode),
|
|
clk0_use_even_counter_mode => alpha_tolower(clk9_use_even_counter_mode),
|
|
clk9_use_even_counter_value => alpha_tolower(clk9_use_even_counter_value),
|
|
clk8_use_even_counter_value => alpha_tolower(clk8_use_even_counter_value),
|
|
clk7_use_even_counter_value => alpha_tolower(clk7_use_even_counter_value),
|
|
clk6_use_even_counter_value => alpha_tolower(clk6_use_even_counter_value),
|
|
clk5_use_even_counter_value => alpha_tolower(clk5_use_even_counter_value),
|
|
clk4_use_even_counter_value => alpha_tolower(clk4_use_even_counter_value),
|
|
clk3_use_even_counter_value => alpha_tolower(clk3_use_even_counter_value),
|
|
clk2_use_even_counter_value => alpha_tolower(clk2_use_even_counter_value),
|
|
clk1_use_even_counter_value => alpha_tolower(clk1_use_even_counter_value),
|
|
clk0_use_even_counter_value => alpha_tolower(clk0_use_even_counter_value)
|
|
)
|
|
port map (
|
|
inclk => inclk,
|
|
fbin => stratix3_fbin,
|
|
clkswitch => clkswitch_wire,
|
|
areset => areset_wire,
|
|
pfdena => pfdena_wire,
|
|
scanclk => scanclk_wire,
|
|
scandata => scandata_wire,
|
|
scanclkena => scanclkena_wire,
|
|
phasecounterselect => phasecounterselect_wire,
|
|
phaseupdown => phaseupdown_wire,
|
|
phasestep => phasestep_wire,
|
|
configupdate => configupdate_wire,
|
|
clk(0) => clk_wire(0),
|
|
clk(1) => clk_wire(1),
|
|
clk(2) => clk_wire(2),
|
|
clk(3) => clk_wire(3),
|
|
clk(4) => clk_wire(4),
|
|
clk(5) => clk_wire(5),
|
|
clk(6) => clk_wire(6),
|
|
clk(7) => clk_wire(7),
|
|
clk(8) => clk_wire(8),
|
|
clk(9) => clk_wire(9),
|
|
clkbad => clkbad_wire,
|
|
activeclock => activeclock_wire,
|
|
locked => locked_tmp,
|
|
scandataout => scandataout_wire,
|
|
scandone => scandone_wire,
|
|
phasedone => phasedone_wire,
|
|
vcooverrange => vcooverrange_wire,
|
|
vcounderrange => vcounderrange_wire,
|
|
fbout => fbout_wire
|
|
);
|
|
end generate STRATIXIII_ALTPLL;
|
|
|
|
-- Instantiate cycloneiii_pll
|
|
CYCLONEIII_ALTPLL:
|
|
if ((not IS_STINGRAY) and
|
|
(IS_CYCLONEIII)) generate
|
|
M5 : MF_cycloneiii_pll
|
|
generic map(
|
|
operation_mode => alpha_tolower(operation_mode),
|
|
pll_type => alpha_tolower(pll_type),
|
|
compensate_clock => alpha_tolower(compensate_clock),
|
|
inclk0_input_frequency => inclk0_input_frequency,
|
|
inclk1_input_frequency => inclk1_input_frequency,
|
|
self_reset_on_loss_lock => alpha_tolower(self_reset_on_loss_lock),
|
|
switch_over_type => alpha_tolower(switch_over_type),
|
|
enable_switch_over_counter => alpha_tolower(enable_switch_over_counter),
|
|
switch_over_counter => switch_over_counter,
|
|
bandwidth => bandwidth,
|
|
bandwidth_type => alpha_tolower(bandwidth_type),
|
|
lock_high => lock_high,
|
|
lock_low => lock_low,
|
|
lock_window_ui => lock_window_ui,
|
|
simulation_type => alpha_tolower(simulation_type),
|
|
family_name => intended_device_family,
|
|
|
|
-- internal clock specifications
|
|
clk4_multiply_by => clk4_multiply_by,
|
|
clk3_multiply_by => clk3_multiply_by,
|
|
clk2_multiply_by => clk2_multiply_by,
|
|
clk1_multiply_by => clk1_multiply_by,
|
|
clk0_multiply_by => clk0_multiply_by,
|
|
clk4_divide_by => clk4_divide_by,
|
|
clk3_divide_by => clk3_divide_by,
|
|
clk2_divide_by => clk2_divide_by,
|
|
clk1_divide_by => clk1_divide_by,
|
|
clk0_divide_by => clk0_divide_by,
|
|
clk4_phase_shift => clk4_phase_shift,
|
|
clk3_phase_shift => clk3_phase_shift,
|
|
clk2_phase_shift => clk2_phase_shift,
|
|
clk1_phase_shift => clk1_phase_shift,
|
|
clk0_phase_shift => clk0_phase_shift,
|
|
clk4_duty_cycle => clk4_duty_cycle,
|
|
clk3_duty_cycle => clk3_duty_cycle,
|
|
clk2_duty_cycle => clk2_duty_cycle,
|
|
clk1_duty_cycle => clk1_duty_cycle,
|
|
clk0_duty_cycle => clk0_duty_cycle,
|
|
|
|
-- advanced user parameters
|
|
vco_min => get_vco_min_c3(vco_min),
|
|
vco_max => get_vco_max(vco_max),
|
|
vco_center => vco_center,
|
|
pfd_min => pfd_min,
|
|
pfd_max => pfd_max,
|
|
m_initial => m_initial,
|
|
m => m,
|
|
n => n,
|
|
c0_high => c0_high,
|
|
c1_high => c1_high,
|
|
c2_high => c2_high,
|
|
c3_high => c3_high,
|
|
c4_high => c4_high,
|
|
c0_low => c0_low,
|
|
c1_low => c1_low,
|
|
c2_low => c2_low,
|
|
c3_low => c3_low,
|
|
c4_low => c4_low,
|
|
c0_initial => c0_initial,
|
|
c1_initial => c1_initial,
|
|
c2_initial => c2_initial,
|
|
c3_initial => c3_initial,
|
|
c4_initial => c4_initial,
|
|
c0_mode => alpha_tolower(c0_mode),
|
|
c1_mode => alpha_tolower(c1_mode),
|
|
c2_mode => alpha_tolower(c2_mode),
|
|
c3_mode => alpha_tolower(c3_mode),
|
|
c4_mode => alpha_tolower(c4_mode),
|
|
c0_ph => c0_ph,
|
|
c1_ph => c1_ph,
|
|
c2_ph => c2_ph,
|
|
c3_ph => c3_ph,
|
|
c4_ph => c4_ph,
|
|
m_ph => m_ph,
|
|
c1_use_casc_in => c1_use_casc_in,
|
|
c2_use_casc_in => c2_use_casc_in,
|
|
c3_use_casc_in => c3_use_casc_in,
|
|
c4_use_casc_in => c4_use_casc_in,
|
|
m_test_source => get_test_source(m_test_source),
|
|
c0_test_source => get_test_source(c0_test_source),
|
|
c1_test_source => get_test_source(c1_test_source),
|
|
c2_test_source => get_test_source(c2_test_source),
|
|
c3_test_source => get_test_source(c3_test_source),
|
|
c4_test_source => get_test_source(c4_test_source),
|
|
clk4_counter => get_clk_counter(get_clk4_counter(clk4_counter), port_clk4),
|
|
clk3_counter => get_clk_counter(get_clk3_counter(clk3_counter), port_clk3),
|
|
clk2_counter => get_clk_counter(get_clk2_counter(clk2_counter), port_clk2),
|
|
clk1_counter => get_clk_counter(get_clk1_counter(clk1_counter), port_clk1),
|
|
clk0_counter => get_clk_counter(get_clk0_counter(clk0_counter), port_clk0),
|
|
vco_multiply_by => vco_multiply_by,
|
|
vco_divide_by => vco_divide_by,
|
|
vco_frequency_control => alpha_tolower(vco_frequency_control),
|
|
vco_phase_shift_step => vco_phase_shift_step,
|
|
charge_pump_current => charge_pump_current,
|
|
loop_filter_r => loop_filter_r,
|
|
loop_filter_c => loop_filter_c,
|
|
charge_pump_current_bits => charge_pump_current_bits,
|
|
loop_filter_c_bits => loop_filter_c_bits,
|
|
loop_filter_r_bits => loop_filter_r_bits,
|
|
clk4_use_even_counter_mode => alpha_tolower(clk5_use_even_counter_mode),
|
|
clk3_use_even_counter_mode => alpha_tolower(clk6_use_even_counter_mode),
|
|
clk2_use_even_counter_mode => alpha_tolower(clk7_use_even_counter_mode),
|
|
clk1_use_even_counter_mode => alpha_tolower(clk8_use_even_counter_mode),
|
|
clk0_use_even_counter_mode => alpha_tolower(clk9_use_even_counter_mode),
|
|
clk4_use_even_counter_value => alpha_tolower(clk4_use_even_counter_value),
|
|
clk3_use_even_counter_value => alpha_tolower(clk3_use_even_counter_value),
|
|
clk2_use_even_counter_value => alpha_tolower(clk2_use_even_counter_value),
|
|
clk1_use_even_counter_value => alpha_tolower(clk1_use_even_counter_value),
|
|
clk0_use_even_counter_value => alpha_tolower(clk0_use_even_counter_value)
|
|
)
|
|
port map (
|
|
inclk => inclk,
|
|
fbin => fbin_wire,
|
|
clkswitch => clkswitch_wire,
|
|
areset => areset_wire,
|
|
pfdena => pfdena_wire,
|
|
scanclk => scanclk,
|
|
scandata => scandata,
|
|
scanclkena => scanclkena_wire,
|
|
configupdate => configupdate_wire,
|
|
phasecounterselect => phasecounterselect_wire(2 downto 0),
|
|
phaseupdown => phaseupdown_wire,
|
|
phasestep => phasestep_wire,
|
|
clk(0) => clk_wire(0),
|
|
clk(1) => clk_wire(1),
|
|
clk(2) => clk_wire(2),
|
|
clk(3) => clk_wire(3),
|
|
clk(4) => clk_wire(4),
|
|
clkbad => clkbad_wire,
|
|
activeclock => activeclock_wire,
|
|
locked => locked_tmp,
|
|
scandataout => scandataout_wire,
|
|
scandone => scandone_wire,
|
|
phasedone => phasedone_wire,
|
|
vcooverrange => vcooverrange_wire,
|
|
vcounderrange => vcounderrange_wire,
|
|
fbout => fbout_wire
|
|
);
|
|
end generate CYCLONEIII_ALTPLL;
|
|
|
|
-- Instantiate cycloneiiigx_pll
|
|
CYCLONEIIIGL_ALTPLL:
|
|
if (IS_STINGRAY) generate
|
|
M6 : MF_cycloneiiigl_pll
|
|
generic map(
|
|
operation_mode => alpha_tolower(operation_mode),
|
|
pll_type => alpha_tolower(pll_type),
|
|
compensate_clock => alpha_tolower(compensate_clock),
|
|
inclk0_input_frequency => inclk0_input_frequency,
|
|
inclk1_input_frequency => inclk1_input_frequency,
|
|
self_reset_on_loss_lock => alpha_tolower(self_reset_on_loss_lock),
|
|
switch_over_type => alpha_tolower(switch_over_type),
|
|
enable_switch_over_counter => alpha_tolower(enable_switch_over_counter),
|
|
switch_over_counter => switch_over_counter,
|
|
bandwidth => bandwidth,
|
|
bandwidth_type => alpha_tolower(bandwidth_type),
|
|
lock_high => lock_high,
|
|
lock_low => lock_low,
|
|
lock_window_ui => lock_window_ui,
|
|
simulation_type => alpha_tolower(simulation_type),
|
|
family_name => intended_device_family,
|
|
lpm_hint => lpm_hint,
|
|
|
|
-- internal clock specifications
|
|
clk4_multiply_by => clk4_multiply_by,
|
|
clk3_multiply_by => clk3_multiply_by,
|
|
clk2_multiply_by => clk2_multiply_by,
|
|
clk1_multiply_by => clk1_multiply_by,
|
|
clk0_multiply_by => clk0_multiply_by,
|
|
clk4_divide_by => clk4_divide_by,
|
|
clk3_divide_by => clk3_divide_by,
|
|
clk2_divide_by => clk2_divide_by,
|
|
clk1_divide_by => clk1_divide_by,
|
|
clk0_divide_by => clk0_divide_by,
|
|
clk4_phase_shift => clk4_phase_shift,
|
|
clk3_phase_shift => clk3_phase_shift,
|
|
clk2_phase_shift => clk2_phase_shift,
|
|
clk1_phase_shift => clk1_phase_shift,
|
|
clk0_phase_shift => clk0_phase_shift,
|
|
clk4_duty_cycle => clk4_duty_cycle,
|
|
clk3_duty_cycle => clk3_duty_cycle,
|
|
clk2_duty_cycle => clk2_duty_cycle,
|
|
clk1_duty_cycle => clk1_duty_cycle,
|
|
clk0_duty_cycle => clk0_duty_cycle,
|
|
|
|
-- advanced user parameters
|
|
vco_min => get_vco_min_c3(vco_min),
|
|
vco_max => get_vco_max(vco_max),
|
|
vco_center => vco_center,
|
|
dpa_multiply_by => dpa_multiply_by,
|
|
dpa_divide_by => dpa_divide_by,
|
|
dpa_divider => dpa_divider,
|
|
pfd_min => pfd_min,
|
|
pfd_max => pfd_max,
|
|
m_initial => m_initial,
|
|
m => m,
|
|
n => n,
|
|
c0_high => c0_high,
|
|
c1_high => c1_high,
|
|
c2_high => c2_high,
|
|
c3_high => c3_high,
|
|
c4_high => c4_high,
|
|
c0_low => c0_low,
|
|
c1_low => c1_low,
|
|
c2_low => c2_low,
|
|
c3_low => c3_low,
|
|
c4_low => c4_low,
|
|
c0_initial => c0_initial,
|
|
c1_initial => c1_initial,
|
|
c2_initial => c2_initial,
|
|
c3_initial => c3_initial,
|
|
c4_initial => c4_initial,
|
|
c0_mode => alpha_tolower(c0_mode),
|
|
c1_mode => alpha_tolower(c1_mode),
|
|
c2_mode => alpha_tolower(c2_mode),
|
|
c3_mode => alpha_tolower(c3_mode),
|
|
c4_mode => alpha_tolower(c4_mode),
|
|
c0_ph => c0_ph,
|
|
c1_ph => c1_ph,
|
|
c2_ph => c2_ph,
|
|
c3_ph => c3_ph,
|
|
c4_ph => c4_ph,
|
|
m_ph => m_ph,
|
|
c1_use_casc_in => c1_use_casc_in,
|
|
c2_use_casc_in => c2_use_casc_in,
|
|
c3_use_casc_in => c3_use_casc_in,
|
|
c4_use_casc_in => c4_use_casc_in,
|
|
m_test_source => get_test_source(m_test_source),
|
|
c0_test_source => get_test_source(c0_test_source),
|
|
c1_test_source => get_test_source(c1_test_source),
|
|
c2_test_source => get_test_source(c2_test_source),
|
|
c3_test_source => get_test_source(c3_test_source),
|
|
c4_test_source => get_test_source(c4_test_source),
|
|
clk4_counter => get_clk_counter(get_clk4_counter(clk4_counter), port_clk4),
|
|
clk3_counter => get_clk_counter(get_clk3_counter(clk3_counter), port_clk3),
|
|
clk2_counter => get_clk_counter(get_clk2_counter(clk2_counter), port_clk2),
|
|
clk1_counter => get_clk_counter(get_clk1_counter(clk1_counter), port_clk1),
|
|
clk0_counter => get_clk_counter(get_clk0_counter(clk0_counter), port_clk0),
|
|
vco_multiply_by => vco_multiply_by,
|
|
vco_divide_by => vco_divide_by,
|
|
vco_frequency_control => alpha_tolower(vco_frequency_control),
|
|
vco_phase_shift_step => vco_phase_shift_step,
|
|
charge_pump_current => charge_pump_current,
|
|
loop_filter_r => loop_filter_r,
|
|
loop_filter_c => loop_filter_c,
|
|
charge_pump_current_bits => charge_pump_current_bits,
|
|
loop_filter_c_bits => loop_filter_c_bits,
|
|
loop_filter_r_bits => loop_filter_r_bits,
|
|
clk4_use_even_counter_mode => alpha_tolower(clk5_use_even_counter_mode),
|
|
clk3_use_even_counter_mode => alpha_tolower(clk6_use_even_counter_mode),
|
|
clk2_use_even_counter_mode => alpha_tolower(clk7_use_even_counter_mode),
|
|
clk1_use_even_counter_mode => alpha_tolower(clk8_use_even_counter_mode),
|
|
clk0_use_even_counter_mode => alpha_tolower(clk9_use_even_counter_mode),
|
|
clk4_use_even_counter_value => alpha_tolower(clk4_use_even_counter_value),
|
|
clk3_use_even_counter_value => alpha_tolower(clk3_use_even_counter_value),
|
|
clk2_use_even_counter_value => alpha_tolower(clk2_use_even_counter_value),
|
|
clk1_use_even_counter_value => alpha_tolower(clk1_use_even_counter_value),
|
|
clk0_use_even_counter_value => alpha_tolower(clk0_use_even_counter_value)
|
|
)
|
|
port map (
|
|
inclk => inclk,
|
|
fbin => fbin_wire,
|
|
clkswitch => clkswitch_wire,
|
|
areset => areset_wire,
|
|
pfdena => pfdena_wire,
|
|
scanclk => scanclk,
|
|
scandata => scandata,
|
|
scanclkena => scanclkena_wire,
|
|
configupdate => configupdate_wire,
|
|
phasecounterselect => phasecounterselect_wire(2 downto 0),
|
|
phaseupdown => phaseupdown_wire,
|
|
phasestep => phasestep_wire,
|
|
clk(0) => clk_wire(0),
|
|
clk(1) => clk_wire(1),
|
|
clk(2) => clk_wire(2),
|
|
clk(3) => clk_wire(3),
|
|
clk(4) => clk_wire(4),
|
|
clkbad => clkbad_wire,
|
|
activeclock => activeclock_wire,
|
|
locked => locked_tmp,
|
|
scandataout => scandataout_wire,
|
|
scandone => scandone_wire,
|
|
phasedone => phasedone_wire,
|
|
vcooverrange => vcooverrange_wire,
|
|
vcounderrange => vcounderrange_wire,
|
|
fbout => fbout_wire,
|
|
fref => fref_wire,
|
|
icdrclk => icdrclk_wire
|
|
);
|
|
end generate CYCLONEIIIGL_ALTPLL;
|
|
|
|
-- Instantiate pll_iobuf
|
|
STRATIXIIIPLL_IOBUF:
|
|
if ((IS_STRATIXIII) and (not IS_PIRANHA)
|
|
and (alpha_tolower(operation_mode) = "zero_delay_buffer")
|
|
and (using_fbmimicbidir_port = "ON")) generate
|
|
iobuf1 : pll_iobuf
|
|
port map (
|
|
i => fbout_wire,
|
|
oe => oe_wire,
|
|
o => iobuf_o,
|
|
io => fbmimicbidir
|
|
);
|
|
|
|
|
|
end generate STRATIXIIIPLL_IOBUF;
|
|
|
|
process (locked_tmp, areset)
|
|
begin
|
|
if (areset = '1') then
|
|
pll_lock_sync <= '0';
|
|
elsif (locked_tmp = '1' and locked_tmp'event) then
|
|
pll_lock_sync <= '1';
|
|
end if;
|
|
end process;
|
|
|
|
|
|
end behavior;
|
|
-- END ARCHITECTURE BEHAVIOR
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : altaccumulate
|
|
--
|
|
-- Description : Parameterized accumulator megafunction. The accumulator
|
|
-- performs an add function or a subtract function based on the add_sub
|
|
-- parameter. The input data can be signed or unsigned.
|
|
--
|
|
-- Limitation : n/a
|
|
--
|
|
-- Results expected: result - The results of add or subtract operation. Output
|
|
-- port [width_out-1 .. 0] wide.
|
|
-- cout - The cout port has a physical interpretation as
|
|
-- the carry-out (borrow-in) of the MSB. The cout
|
|
-- port is most meaningful for detecting overflow
|
|
-- in unsigned operations. The cout port operates
|
|
-- in the same manner for signed and unsigned
|
|
-- operations.
|
|
-- overflow - Indicates the accumulator is overflow.
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
|
|
-- BEGINNING OF ENTITY
|
|
entity altaccumulate is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
width_in : natural := 4; -- Required
|
|
width_out : natural := 8; -- Required
|
|
lpm_representation : string := "UNSIGNED";
|
|
extra_latency : integer := 0;
|
|
use_wys : string := "ON";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altaccumulate"
|
|
);
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
cin : in std_logic := 'Z';
|
|
data : in std_logic_vector(width_in -1 downto 0); -- Required port
|
|
add_sub : in std_logic := '1';
|
|
clock : in std_logic; -- Required port
|
|
sload : in std_logic := '0';
|
|
clken : in std_logic := '1';
|
|
sign_data : in std_logic := '0';
|
|
aclr : in std_logic := '0';
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
result : out std_logic_vector(width_out -1 downto 0) := (others => '0'); -- Required port
|
|
cout : out std_logic := '0';
|
|
overflow : out std_logic := '0'
|
|
);
|
|
end altaccumulate;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
architecture behaviour of altaccumulate is
|
|
|
|
-- TYPE DECLARATION
|
|
type pipeline is array (extra_latency-1 downto 0) of std_logic_vector (width_out+1 downto 0);
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal temp_sum : std_logic_vector (width_out downto 0) := (others => '0');
|
|
signal cout_int : std_logic := '0';
|
|
signal overflow_int : std_logic := '0';
|
|
signal result_int : std_logic_vector (width_out+1 downto 0) := (others => '0');
|
|
|
|
signal result_pipe : pipeline := (others => (others => '0'));
|
|
|
|
|
|
begin
|
|
MSG: process
|
|
begin
|
|
if( width_in <= 0 ) then
|
|
ASSERT FALSE
|
|
REPORT "Error! Value of width_in parameter must be greater than 0."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if( width_out <= 0 ) then
|
|
ASSERT FALSE
|
|
REPORT "Error! Value of width_out parameter must be greater than 0."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if( extra_latency > width_out ) then
|
|
ASSERT FALSE
|
|
REPORT "Info: Value of extra_latency parameter should be lower than width_out parameter for better performance/utilization."
|
|
SEVERITY NOTE;
|
|
end if;
|
|
|
|
if( width_in > width_out ) then
|
|
ASSERT FALSE
|
|
REPORT "Error! Value of width_in parameter should be lower than or equal to width_out."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
wait;
|
|
end process MSG;
|
|
|
|
-- PROCESS DECLARATION
|
|
ADDSUB : process (data, add_sub, sload, cin, sign_data,
|
|
result_int (width_out-1 downto 0))
|
|
|
|
-- VARIABLE DECLARATIOM
|
|
variable fb_int : std_logic_vector (width_out downto 0) := (others => '0');
|
|
variable data_int : std_logic_vector (width_out-1 downto 0) := (others => '0');
|
|
variable zeropad : std_logic_vector ((width_out - width_in)-1 downto 0) := (others => '0');
|
|
variable temp_sum_int : std_logic_vector (width_out downto 0) := (others => '0');
|
|
variable cout_temp, borrow : std_logic;
|
|
variable result_full : std_logic_vector (width_out downto 0);
|
|
variable temp_sum_zero : std_logic_vector (width_out downto 0) := (others => '0');
|
|
variable cin_int : std_logic;
|
|
begin
|
|
|
|
if ((LPM_REPRESENTATION = "SIGNED") or (sign_data = '1')) then
|
|
zeropad := (others => data (width_in-1));
|
|
else
|
|
zeropad := (others => '0');
|
|
end if;
|
|
|
|
if (sload = '1') then
|
|
fb_int := (others => '0');
|
|
else
|
|
fb_int := ('0' & result_int (width_out-1 downto 0));
|
|
end if;
|
|
|
|
if ((data (0) = '1') or (data (0) = '0')) then
|
|
data_int := (zeropad & data);
|
|
end if;
|
|
|
|
-- If cin is omitted (i.e. cin = 'z'), cin default is 0 for add operation
|
|
-- and 1 for subtract operation.
|
|
if ((cin /= '0') and (cin /= '1')) then
|
|
cin_int := not add_sub;
|
|
else
|
|
cin_int := cin;
|
|
end if;
|
|
|
|
if (sload = '1') then
|
|
temp_sum_int := unsigned(temp_sum_zero) + unsigned(data_int);
|
|
else
|
|
if (add_sub = '1') then
|
|
temp_sum_int := unsigned(temp_sum_zero) + unsigned(fb_int) +
|
|
unsigned(data_int) + cin_int;
|
|
cout_temp := temp_sum_int(width_out);
|
|
else
|
|
borrow := not cin_int;
|
|
if ((borrow /= '1') and (borrow /= '0')) then
|
|
borrow := '0';
|
|
end if;
|
|
|
|
temp_sum_int := unsigned(temp_sum_zero) + unsigned (fb_int) -
|
|
unsigned (data_int) - borrow;
|
|
result_full := unsigned(temp_sum_zero) + unsigned(data_int) +
|
|
borrow;
|
|
|
|
if (fb_int >= result_full) then
|
|
cout_temp :='1';
|
|
else
|
|
cout_temp :='0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (sload = '0') then
|
|
if ((LPM_REPRESENTATION = "SIGNED") or (sign_data = '1')) then
|
|
overflow_int <= ((not (data (width_in-1) xor result_int (width_out -1))) xor (not (add_sub))) and
|
|
(result_int (width_out -1) xor temp_sum_int (width_out -1));
|
|
else
|
|
overflow_int <= not (add_sub xor cout_temp);
|
|
end if;
|
|
else
|
|
overflow_int <= '0';
|
|
cout_temp := not add_sub;
|
|
end if;
|
|
|
|
cout_int <= cout_temp;
|
|
temp_sum <= temp_sum_int;
|
|
|
|
end process ADDSUB;
|
|
|
|
ACC: process (clock, aclr, cout_int)
|
|
|
|
-- VARIABLE DECLARATIOM
|
|
variable head_pipe : integer;
|
|
variable head : integer := 0;
|
|
variable full_res: std_logic_vector (width_out+1 downto 0);
|
|
begin
|
|
head_pipe := head;
|
|
|
|
if ((aclr /= '1') and (extra_latency = 0)) then
|
|
cout <= cout_int;
|
|
end if;
|
|
|
|
if (aclr = '1') then
|
|
result <= (others => '0');
|
|
result_int <= (others => '0');
|
|
if (extra_latency > 0) then
|
|
cout <= '0';
|
|
else
|
|
cout <= cout_int;
|
|
end if;
|
|
overflow <= '0';
|
|
result_pipe <= (others => (others => '0'));
|
|
|
|
elsif rising_edge(clock) then
|
|
if (clken = '1') then
|
|
if (extra_latency > 0) then
|
|
result_pipe (head_pipe) <= (result_int (width_out+1) &
|
|
cout_int &
|
|
result_int (width_out-1 downto 0));
|
|
|
|
head_pipe := (head_pipe + 1) mod (extra_latency);
|
|
if (head_pipe = head) then
|
|
full_res := (result_int (width_out+1) &
|
|
cout_int &
|
|
result_int (width_out-1 downto 0));
|
|
else
|
|
full_res := result_pipe (head_pipe);
|
|
end if;
|
|
cout <= full_res (width_out);
|
|
result <= full_res (width_out-1 downto 0);
|
|
overflow <= full_res (width_out+1);
|
|
else
|
|
overflow <= overflow_int;
|
|
result <= temp_sum (width_out-1 downto 0);
|
|
end if;
|
|
result_int <= (overflow_int & cout_int &
|
|
temp_sum (width_out-1 downto 0));
|
|
end if;
|
|
end if;
|
|
|
|
head := head_pipe;
|
|
end process ACC;
|
|
|
|
end behaviour; -- End behaviour of altaccumulate
|
|
-- END OF ARCHITECTURE
|
|
|
|
-- --------------------------------------------------------------------------
|
|
-- Module Name : altmult_accum
|
|
--
|
|
-- Description : a*b + x (MAC)
|
|
--
|
|
-- Limitation : Stratix DSP block
|
|
--
|
|
-- Results expected : signed & unsigned, maximum of 3 pipelines(latency) each.
|
|
--
|
|
-- --------------------------------------------------------------------------
|
|
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
|
|
entity altmult_accum is
|
|
generic (
|
|
|
|
-- ---------------------
|
|
-- PARAMETER DECLARATION
|
|
-- ---------------------
|
|
width_a : natural := 1;
|
|
width_b : natural := 1;
|
|
width_c : natural := 1;
|
|
width_result : natural := 2;
|
|
width_upper_data : natural := 1;
|
|
input_source_a : string := "DATAA";
|
|
input_source_b : string := "DATAB";
|
|
input_reg_a : string := "CLOCK0";
|
|
input_aclr_a : string := "ACLR3";
|
|
input_reg_b : string := "CLOCK0";
|
|
input_aclr_b : string := "ACLR3";
|
|
port_addnsub : string := "PORT_CONNECTIVITY";
|
|
addnsub_reg : string := "CLOCK0";
|
|
addnsub_aclr : string := "ACLR3";
|
|
addnsub_pipeline_reg : string := "CLOCK0";
|
|
addnsub_pipeline_aclr : string := "ACLR3";
|
|
accum_direction : string := "ADD";
|
|
accum_sload_reg : string := "CLOCK0";
|
|
accum_sload_aclr : string := "ACLR3";
|
|
accum_sload_pipeline_reg : string := "CLOCK0";
|
|
accum_sload_pipeline_aclr : string := "ACLR3";
|
|
representation_a : string := "UNSIGNED";
|
|
port_signa : string := "PORT_CONNECTIVITY";
|
|
sign_reg_a : string := "CLOCK0";
|
|
sign_aclr_a : string := "ACLR3";
|
|
sign_pipeline_reg_a : string := "CLOCK0";
|
|
sign_pipeline_aclr_a : string := "ACLR3";
|
|
representation_b : string := "UNSIGNED";
|
|
port_signb : string := "PORT_CONNECTIVITY";
|
|
sign_reg_b : string := "CLOCK0";
|
|
sign_aclr_b : string := "ACLR3";
|
|
sign_pipeline_reg_b : string := "CLOCK0";
|
|
sign_pipeline_aclr_b : string := "ACLR3";
|
|
multiplier_reg : string := "CLOCK0";
|
|
multiplier_aclr : string := "ACLR3";
|
|
output_reg : string := "CLOCK0";
|
|
output_aclr : string := "ACLR3";
|
|
extra_multiplier_latency : integer := 0;
|
|
extra_accumulator_latency : integer := 0;
|
|
dedicated_multiplier_circuitry : string := "AUTO";
|
|
dsp_block_balancing : string := "AUTO";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altmult_accum";
|
|
intended_device_family : string := "Stratix";
|
|
multiplier_rounding : string := "NO";
|
|
mult_round_aclr : string := "ACLR3";
|
|
mult_round_reg : string := "CLOCK0";
|
|
multiplier_saturation : string := "NO";
|
|
mult_saturation_aclr : string := "ACLR3";
|
|
mult_saturation_reg : string := "CLOCK0";
|
|
accumulator_rounding : string := "NO";
|
|
accum_round_aclr : string := "ACLR3";
|
|
accum_round_reg : string := "CLOCK0";
|
|
accum_round_pipeline_aclr : string := "ACLR3";
|
|
accum_round_pipeline_reg : string := "CLOCK0";
|
|
accumulator_saturation : string := "NO";
|
|
accum_saturation_aclr : string := "ACLR3";
|
|
accum_saturation_reg : string := "CLOCK0";
|
|
accum_saturation_pipeline_aclr : string := "ACLR3";
|
|
accum_saturation_pipeline_reg : string := "CLOCK0";
|
|
accum_sload_upper_data_aclr : string := "ACLR3";
|
|
accum_sload_upper_data_pipeline_aclr : string := "ACLR3";
|
|
accum_sload_upper_data_pipeline_reg : string := "CLOCK0";
|
|
accum_sload_upper_data_reg : string := "CLOCK0";
|
|
port_mult_is_saturated : string := "UNUSED";
|
|
port_accum_is_saturated : string := "UNUSED";
|
|
-- StratixV parameters
|
|
preadder_mode : string := "SIMPLE";
|
|
loadconst_value : integer := 0;
|
|
width_coef : integer := 0;
|
|
|
|
loadconst_control_register : string := "CLOCK0";
|
|
loadconst_control_aclr : string := "ACLR0";
|
|
|
|
coefsel0_register : string := "CLOCK0";
|
|
coefsel1_register : string := "CLOCK0";
|
|
coefsel2_register : string := "CLOCK0";
|
|
coefsel3_register : string := "CLOCK0";
|
|
coefsel0_aclr : string := "ACLR0";
|
|
coefsel1_aclr : string := "ACLR0";
|
|
coefsel2_aclr : string := "ACLR0";
|
|
coefsel3_aclr : string := "ACLR0";
|
|
|
|
preadder_direction_0 : string := "ADD";
|
|
preadder_direction_1 : string := "ADD";
|
|
preadder_direction_2 : string := "ADD";
|
|
preadder_direction_3 : string := "ADD";
|
|
|
|
systolic_delay1 : string := "UNREGISTERED";
|
|
systolic_delay3 : string := "UNREGISTERED";
|
|
systolic_aclr1 : string := "NONE";
|
|
systolic_aclr3 : string := "NONE";
|
|
-- coefficient storage
|
|
coef0_0 : integer := 0;
|
|
coef0_1 : integer := 0;
|
|
coef0_2 : integer := 0;
|
|
coef0_3 : integer := 0;
|
|
coef0_4 : integer := 0;
|
|
coef0_5 : integer := 0;
|
|
coef0_6 : integer := 0;
|
|
coef0_7 : integer := 0;
|
|
|
|
coef1_0 : integer := 0;
|
|
coef1_1 : integer := 0;
|
|
coef1_2 : integer := 0;
|
|
coef1_3 : integer := 0;
|
|
coef1_4 : integer := 0;
|
|
coef1_5 : integer := 0;
|
|
coef1_6 : integer := 0;
|
|
coef1_7 : integer := 0;
|
|
|
|
coef2_0 : integer := 0;
|
|
coef2_1 : integer := 0;
|
|
coef2_2 : integer := 0;
|
|
coef2_3 : integer := 0;
|
|
coef2_4 : integer := 0;
|
|
coef2_5 : integer := 0;
|
|
coef2_6 : integer := 0;
|
|
coef2_7 : integer := 0;
|
|
|
|
coef3_0 : integer := 0;
|
|
coef3_1 : integer := 0;
|
|
coef3_2 : integer := 0;
|
|
coef3_3 : integer := 0;
|
|
coef3_4 : integer := 0;
|
|
coef3_5 : integer := 0;
|
|
coef3_6 : integer := 0;
|
|
coef3_7 : integer := 0
|
|
);
|
|
|
|
port (
|
|
|
|
-- ----------------
|
|
-- PORT DECLARATION
|
|
-- ----------------
|
|
|
|
-- input data ports
|
|
dataa : in std_logic_vector(width_a -1 downto 0) := (others => '0');
|
|
datab : in std_logic_vector(width_b -1 downto 0) := (others => '0');
|
|
datac : in std_logic_vector(width_c -1 downto 0) := (others => '0');
|
|
scanina : in std_logic_vector(width_a -1 downto 0) := (others => 'Z');
|
|
scaninb : in std_logic_vector(width_b -1 downto 0) := (others => 'Z');
|
|
accum_sload_upper_data : in std_logic_vector(width_upper_data - 1 downto 0) := (others => '0');
|
|
sourcea : in std_logic := '0';
|
|
sourceb : in std_logic := '0';
|
|
-- control signals
|
|
addnsub : in std_logic := 'Z';
|
|
accum_sload : in std_logic := '0';
|
|
signa : in std_logic := 'Z';
|
|
signb : in std_logic := 'Z';
|
|
-- clock ports
|
|
clock0 : in std_logic := '1';
|
|
clock1 : in std_logic := '1';
|
|
clock2 : in std_logic := '1';
|
|
clock3 : in std_logic := '1';
|
|
-- clock enable ports
|
|
ena0 : in std_logic := '1';
|
|
ena1 : in std_logic := '1';
|
|
ena2 : in std_logic := '1';
|
|
ena3 : in std_logic := '1';
|
|
-- clear ports
|
|
aclr0 : in std_logic := '0';
|
|
aclr1 : in std_logic := '0';
|
|
aclr2 : in std_logic := '0';
|
|
aclr3 : in std_logic := '0';
|
|
-- round and saturation ports
|
|
mult_round : in std_logic := '0';
|
|
mult_saturation : in std_logic := '0';
|
|
accum_round : in std_logic := '0';
|
|
accum_saturation : in std_logic := '0';
|
|
-- StratixV only input ports
|
|
coefsel0 : in std_logic_vector(2 downto 0) := (others => '0');
|
|
coefsel1 : in std_logic_vector(2 downto 0) := (others => '0');
|
|
coefsel2 : in std_logic_vector(2 downto 0) := (others => '0');
|
|
coefsel3 : in std_logic_vector(2 downto 0) := (others => '0');
|
|
-- output ports
|
|
result : out std_logic_vector(width_result -1 downto 0) := (others => '0');
|
|
overflow : out std_logic :='0';
|
|
scanouta : out std_logic_vector (width_a -1 downto 0) := (others => '0');
|
|
scanoutb : out std_logic_vector (width_b -1 downto 0) := (others => '0');
|
|
mult_is_saturated : out std_logic := '0';
|
|
accum_is_saturated : out std_logic := '0'
|
|
);
|
|
end altmult_accum;
|
|
|
|
|
|
architecture behaviour of altmult_accum is
|
|
-- -------------------------------------
|
|
-- INTERNAL SIGNALS AND TYPE DECLARATION
|
|
-- -------------------------------------
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant IS_STRATIXV : boolean := FEATURE_FAMILY_STRATIXV(intended_device_family);
|
|
constant IS_STRATIXIII : boolean := FEATURE_FAMILY_STRATIXIII(intended_device_family);
|
|
constant IS_STRATIXII : boolean := FEATURE_FAMILY_STRATIXII(intended_device_family);
|
|
constant IS_CYCLONEII : boolean := FEATURE_FAMILY_CYCLONEII(intended_device_family);
|
|
constant altera_mult_add_block : boolean := FEATURE_FAMILY_HAS_ALTERA_MULT_ADD_FLOW(intended_device_family);
|
|
constant altmult_add_eol_block : boolean := FEATURE_FAMILY_IS_ALTMULT_ADD_EOL(intended_device_family);
|
|
|
|
function resolve_internal_width (ARG : integer;ARG2 : integer) return integer is
|
|
variable changed_width:integer := 0;
|
|
begin
|
|
if (multiplier_saturation = "NO" and multiplier_rounding = "NO" and
|
|
accumulator_saturation = "NO" and accumulator_rounding = "NO") then
|
|
if (ARG2 = 0) then
|
|
changed_width := width_a;
|
|
else
|
|
changed_width := width_b;
|
|
end if;
|
|
else
|
|
changed_width := 18;
|
|
end if;
|
|
return changed_width;
|
|
end resolve_internal_width;
|
|
|
|
-- This constant int_width_a would be used internally in this model
|
|
-- to represent width_a
|
|
constant int_width_a : natural := resolve_internal_width(width_a, 0);
|
|
|
|
-- This constant int_width_b woudl be used internally in this model
|
|
-- to represent width_b
|
|
constant int_width_b : natural := resolve_internal_width(width_b, 1);
|
|
|
|
function resolve_internal_extra_width return integer is
|
|
variable changed_value :integer := 0;
|
|
begin
|
|
if (multiplier_saturation = "NO" and multiplier_rounding = "NO" and
|
|
accumulator_saturation = "NO" and accumulator_rounding = "NO") then
|
|
changed_value := 0;
|
|
else
|
|
changed_value := int_width_a + int_width_b - width_a - width_b;
|
|
end if;
|
|
return changed_value;
|
|
end resolve_internal_extra_width;
|
|
|
|
constant int_extra_width : integer := resolve_internal_extra_width;
|
|
|
|
function resolve_internal_width_result return integer is
|
|
variable changed_width_result:integer := 0;
|
|
begin
|
|
if (multiplier_saturation = "NO" and multiplier_rounding = "NO" and
|
|
accumulator_saturation = "NO" and accumulator_rounding = "NO") then
|
|
if ((int_width_a + int_width_b - 1) > width_result) then
|
|
changed_width_result := int_width_a + int_width_b - 1;
|
|
else
|
|
changed_width_result := width_result;
|
|
end if;
|
|
else
|
|
if ((int_width_a + int_width_b - 1) > 52) then
|
|
changed_width_result := int_width_a + int_width_b - 1;
|
|
else
|
|
changed_width_result := 52;
|
|
end if;
|
|
end if;
|
|
return changed_width_result;
|
|
end resolve_internal_width_result;
|
|
|
|
constant int_width_result : natural := resolve_internal_width_result;
|
|
|
|
-- -------------------------------------
|
|
-- INTERNAL TEMPLATE DECLARATION
|
|
-- -------------------------------------
|
|
type pipeline_accum is array (extra_accumulator_latency downto 0) of std_logic_vector (int_width_result downto 0);
|
|
type pipeline_multi is array (extra_multiplier_latency downto 0) of std_logic_vector (int_width_a + int_width_b + 4 downto 0);
|
|
type pipeline_sload is array (extra_multiplier_latency downto 0) of std_logic_vector (width_upper_data - 1 downto 0);
|
|
|
|
signal mult_a : std_logic_vector (width_a - 1 downto 0):= (others => '0');
|
|
signal mult_b : std_logic_vector (width_b - 1 downto 0):= (others => '0');
|
|
signal mult_res : std_logic_vector (int_width_a + int_width_b - 1 downto 0):= (others => '0');
|
|
signal acc_sload_reg : std_logic := '0';
|
|
signal accum_sload_pipe : std_logic := '0';
|
|
signal sign_a_reg : std_logic := '0';
|
|
signal sign_a_pipe : std_logic := '0';
|
|
signal sign_a_latent : std_logic := '0';
|
|
signal sign_b_reg : std_logic := '0';
|
|
signal sign_b_pipe : std_logic := '0';
|
|
signal sign_b_latent : std_logic := '0';
|
|
signal addsub_reg : std_logic := '0';
|
|
signal addsub_pipe : std_logic := '0';
|
|
signal addsub_latent : std_logic := '0';
|
|
signal accum_sload_latent : std_logic := '0';
|
|
|
|
signal mult_pipe : pipeline_multi := (others => (others => '0'));
|
|
signal sload_upper_data_pipe : pipeline_sload := (others => (others => '0'));
|
|
|
|
signal mult_out_latent : std_logic_vector (int_width_a + int_width_b - 1 downto 0):= (others => '0');
|
|
signal result_int : std_logic_vector (int_width_result - 1 downto 0):= (others => '0');
|
|
signal temp_mult_zero : std_logic_vector (int_width_a + int_width_b downto 0):= (others => '0');
|
|
signal mult_full : std_logic_vector (int_width_a + int_width_b + 4 downto 0):= (others => '0');
|
|
|
|
signal mult_signed : std_logic := '0';
|
|
signal do_add : std_logic := '0';
|
|
signal temp_mult_signed : std_logic := '0';
|
|
signal head_result : natural := 0;
|
|
signal head_mult : natural := 0;
|
|
|
|
signal lower_bits : std_logic_vector (width_result + width_upper_data - 1 downto 0) := (others => '0');
|
|
signal sload_upper_data_reg : std_logic_vector (width_upper_data - 1 downto 0) := (others => '0');
|
|
signal sload_upper_data_latent : std_logic_vector (width_upper_data - 1 downto 0) := (others => '0');
|
|
signal sload_upper_data_wire : std_logic_vector (width_upper_data - 1 downto 0) := (others => '0');
|
|
signal sload_upper_data_full : std_logic_vector (width_upper_data - 1 downto 0) := (others => '0');
|
|
|
|
signal mult_is_saturated_wire : std_logic := '0';
|
|
signal mult_is_saturated_reg : std_logic := '0';
|
|
signal mult_is_saturated_out : std_logic := '0';
|
|
signal accum_is_saturated_out : std_logic := '0';
|
|
|
|
signal mult_round_wire : std_logic := '0';
|
|
signal mult_saturate_wire : std_logic := '0';
|
|
signal mult_final_out : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
|
|
|
|
signal accum_round_pipe_wire : std_logic := '0';
|
|
signal accum_round_wire : std_logic := '0';
|
|
signal accum_saturation_pipe_wire : std_logic := '0';
|
|
signal accum_saturate_wire : std_logic := '0';
|
|
|
|
begin
|
|
|
|
scanouta <= mult_a;
|
|
scanoutb <= mult_b;
|
|
sign_a_latent <= mult_full (int_width_a + int_width_b + 4) when extra_multiplier_latency >0 else sign_a_reg;
|
|
sign_b_latent <= mult_full (int_width_a + int_width_b + 3) when extra_multiplier_latency >0 else sign_b_reg;
|
|
accum_sload_latent <= mult_full (int_width_a + int_width_b + 2) when extra_multiplier_latency >0 else acc_sload_reg;
|
|
addsub_latent <= mult_full (int_width_a + int_width_b + 1) when extra_multiplier_latency >0 else addsub_reg;
|
|
mult_signed <= mult_full (int_width_a + int_width_b + 0) when extra_multiplier_latency >0 else temp_mult_signed;
|
|
mult_out_latent <= mult_full (int_width_a + int_width_b - 1 downto 0) when extra_multiplier_latency >0 else mult_final_out;
|
|
sload_upper_data_latent <= sload_upper_data_full when extra_multiplier_latency >0 else sload_upper_data_reg;
|
|
|
|
mult_is_saturated <= mult_is_saturated_out when (port_mult_is_saturated = "USED") else '0';
|
|
accum_is_saturated <= accum_is_saturated_out when (port_accum_is_saturated = "USED") else '0';
|
|
|
|
|
|
-- Parameter Checking
|
|
process
|
|
begin
|
|
|
|
-- Legality check, family from Night Fury and moving forwards is officially EOL
|
|
if (altmult_add_eol_block) then
|
|
assert false
|
|
report "ALTMULT_ACCUM is EOL for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
|
|
-- Legality check, block unsupported family from running pre_layout simulation using altera_mf (family with altera_mult_add flow)
|
|
if (altera_mult_add_block or altmult_add_eol_block) then
|
|
assert false
|
|
report "ALTMULT_ACCUM is not supported for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
|
|
if ((dedicated_multiplier_circuitry /= "AUTO") and
|
|
(dedicated_multiplier_circuitry /= "YES") and
|
|
(dedicated_multiplier_circuitry /= "NO")) then
|
|
assert false
|
|
report "Error: The DEDICATED_MULTIPLIER_CIRCUITRY parameter is set to an illegal value."
|
|
severity error;
|
|
end if;
|
|
|
|
if (width_a <= 0) then
|
|
assert false
|
|
report "Error: width_a must be greater than 0."
|
|
severity error;
|
|
end if;
|
|
|
|
if (width_b <= 0) then
|
|
assert false
|
|
report "Error: width_b must be greater than 0."
|
|
severity error;
|
|
end if;
|
|
|
|
if (width_result <= 0) then
|
|
assert false
|
|
report "Error: width_result must be greater than 0."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not IS_STRATIXII) and
|
|
(not IS_CYCLONEII) and
|
|
(input_source_a /= "DATAA")) then
|
|
assert false
|
|
report "Error: The input source for port A are limited to input dataa."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not IS_STRATIXII) and
|
|
(not IS_CYCLONEII) and
|
|
(input_source_b /= "DATAB")) then
|
|
assert false
|
|
report "Error: The input source for port B are limited to input datab."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (multiplier_rounding /= "NO")) then
|
|
assert false
|
|
report "Error: There is no rounding feature for " & intended_device_family & " device."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not IS_STRATIXII) and (accumulator_rounding /= "NO")) then
|
|
assert false
|
|
report "Error: There is no rounding feature for "& intended_device_family &" device."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (multiplier_saturation /= "NO")) then
|
|
assert false
|
|
report "Error: There is no saturation feature for "& intended_device_family &" device."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not IS_STRATIXII) and (accumulator_saturation /= "NO")) then
|
|
assert false
|
|
report "Error: There is no saturation feature for "& intended_device_family &" device."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((IS_STRATIXIII) and (port_addnsub /= "PORT_UNUSED")) then
|
|
assert false
|
|
report "Error: The addnsub port is not available for "& intended_device_family &" device."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((IS_STRATIXIII) and (accum_direction /= "ADD") and
|
|
(accum_direction /= "SUB")) then
|
|
assert false
|
|
report "Error: Invalid value for ACCUM_DIRECTION parameter for "& intended_device_family &" device."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((IS_STRATIXIII) and not(IS_STRATIXV) and (input_source_a = "VARIABLE")) then
|
|
assert false
|
|
report "Error: Invalid value for INPUT_SOURCE_A parameter for "& intended_device_family &" device."
|
|
severity error;
|
|
end if;
|
|
|
|
wait;
|
|
|
|
end process;
|
|
|
|
G1:if (input_reg_a = "UNREGISTERED") generate
|
|
process (dataa, scanina, sourcea)
|
|
begin
|
|
if (input_source_a = "DATAA") then
|
|
mult_a <= dataa;
|
|
elsif (input_source_a = "SCANA") then
|
|
mult_a <= scanina;
|
|
elsif (input_source_a = "VARIABLE") then
|
|
if (sourcea = '1') then
|
|
mult_a <= dataa;
|
|
else
|
|
mult_a <= scanina;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate G1;
|
|
|
|
G2:if (input_reg_b = "UNREGISTERED") generate
|
|
process (datab, scaninb, sourceb)
|
|
begin
|
|
if (input_source_b = "DATAB") then
|
|
mult_b <= datab;
|
|
elsif (input_source_b = "SCANB") then
|
|
mult_b <= scaninb;
|
|
elsif (input_source_b = "VARIABLE") then
|
|
if (sourceb = '1') then
|
|
mult_b <= datab;
|
|
else
|
|
mult_b <= scaninb;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate G2;
|
|
|
|
G3: if (addnsub_reg = "UNREGISTERED") generate
|
|
addsub_reg <= addnsub;
|
|
end generate G3;
|
|
|
|
G4: if (addnsub_pipeline_reg = "UNREGISTERED") generate
|
|
addsub_pipe <= addsub_latent;
|
|
end generate G4;
|
|
|
|
G5: if (accum_sload_reg = "UNREGISTERED") generate
|
|
acc_sload_reg <= accum_sload;
|
|
end generate G5;
|
|
|
|
G6: if (accum_sload_pipeline_reg = "UNREGISTERED") generate
|
|
accum_sload_pipe <= accum_sload_latent;
|
|
end generate G6;
|
|
|
|
G7: if (sign_reg_a = "UNREGISTERED") generate
|
|
sign_a_reg <= signa;
|
|
end generate G7;
|
|
|
|
G8: if sign_reg_b= "UNREGISTERED" generate
|
|
sign_b_reg <= signb;
|
|
end generate G8;
|
|
|
|
G9: if (sign_pipeline_reg_a = "UNREGISTERED") generate
|
|
sign_a_pipe <= sign_a_latent;
|
|
end generate G9;
|
|
|
|
G10: if (sign_pipeline_reg_b = "UNREGISTERED") generate
|
|
sign_b_pipe <= sign_b_latent;
|
|
end generate G10;
|
|
|
|
G11: if (accum_round_reg = "UNREGISTERED") generate
|
|
process (accum_round, accum_sload)
|
|
begin
|
|
if (IS_STRATIXIII) then
|
|
accum_round_pipe_wire <= accum_sload;
|
|
else
|
|
accum_round_pipe_wire <= accum_round;
|
|
end if;
|
|
end process;
|
|
end generate G11;
|
|
|
|
G12: if (accum_round_pipeline_reg = "UNREGISTERED") generate
|
|
accum_round_wire <= accum_round_pipe_wire;
|
|
end generate G12;
|
|
|
|
G12b: if (accum_saturation_reg = "UNREGISTERED") generate
|
|
accum_saturation_pipe_wire <= accum_saturation;
|
|
end generate G12b;
|
|
|
|
G14: if (accum_saturation_pipeline_reg = "UNREGISTERED") generate
|
|
accum_saturate_wire <= accum_saturation_pipe_wire;
|
|
end generate G14;
|
|
|
|
G15: if (mult_round_reg = "UNREGISTERED") generate
|
|
mult_round_wire <= mult_round;
|
|
end generate G15;
|
|
|
|
G16: if (mult_saturation_reg = "UNREGISTERED") generate
|
|
mult_saturate_wire <= mult_saturation;
|
|
end generate G16;
|
|
|
|
G17: if (accum_sload_upper_data_reg = "UNREGISTERED") generate
|
|
sload_upper_data_reg <= accum_sload_upper_data;
|
|
end generate G17;
|
|
|
|
G18: if (accum_sload_upper_data_pipeline_reg = "UNREGISTERED") generate
|
|
sload_upper_data_wire <= sload_upper_data_latent;
|
|
end generate G18;
|
|
|
|
G19: if (multiplier_reg = "UNREGISTERED") generate
|
|
mult_res <= mult_out_latent;
|
|
mult_is_saturated_reg <= mult_is_saturated_wire;
|
|
end generate G19;
|
|
|
|
-- ----------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set mult_a)
|
|
-- The signal registered is dataa
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if input_reg_a is unregistered and
|
|
-- dataa changes value
|
|
-- ---------------------------------------------------------------------------
|
|
|
|
IFG1: if (input_reg_a = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, dataa, scanina, sourcea)
|
|
begin
|
|
if (((input_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_a <= (others => '0');
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
if (input_source_a = "DATAA") then
|
|
mult_a <= dataa;
|
|
elsif (input_source_a = "SCANA") then
|
|
mult_a <= scanina;
|
|
elsif (input_source_a = "VARIABLE") then
|
|
if (sourcea = '1') then
|
|
mult_a <= dataa;
|
|
else
|
|
mult_a <= scanina;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG1;
|
|
|
|
IFG2: if (input_reg_a = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, dataa, scanina, sourcea)
|
|
begin
|
|
if (((input_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_a <= (others => '0');
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
if (input_source_a = "DATAA") then
|
|
mult_a <= dataa;
|
|
elsif (input_source_a = "SCANA") then
|
|
mult_a <= scanina;
|
|
elsif (input_source_a = "VARIABLE") then
|
|
if (sourcea = '1') then
|
|
mult_a <= dataa;
|
|
else
|
|
mult_a <= scanina;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG2;
|
|
|
|
IFG3: if (input_reg_a = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, dataa, scanina, sourcea)
|
|
begin
|
|
if (((input_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_a <= (others => '0');
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1'))then
|
|
if (input_source_a = "DATAA") then
|
|
mult_a <= dataa;
|
|
elsif (input_source_a = "SCANA") then
|
|
mult_a <= scanina;
|
|
elsif (input_source_a = "VARIABLE") then
|
|
if (sourcea = '1') then
|
|
mult_a <= dataa;
|
|
else
|
|
mult_a <= scanina;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG3;
|
|
|
|
IFG4: if (input_reg_a = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, dataa, scanina, sourcea)
|
|
begin
|
|
if (((input_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_a <= (others => '0');
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
if (input_source_a = "DATAA") then
|
|
mult_a <= dataa;
|
|
elsif (input_source_a = "SCANA") then
|
|
mult_a <= scanina;
|
|
elsif (input_source_a = "VARIABLE") then
|
|
if (sourcea = '1') then
|
|
mult_a <= dataa;
|
|
else
|
|
mult_a <= scanina;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG4;
|
|
-- ----------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set mult_b)
|
|
-- The signal registered is datab
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if input_reg_b is unregistered and
|
|
-- datab changes value
|
|
-- ---------------------------------------------------------------------------
|
|
IFG5: if (input_reg_b = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, datab, scaninb, sourceb)
|
|
begin
|
|
if (((input_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_b <= (others => '0');
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
if (input_source_b = "DATAB") then
|
|
mult_b <= datab;
|
|
elsif (input_source_b = "SCANB") then
|
|
mult_b <= scaninb;
|
|
elsif (input_source_b = "VARIABLE") then
|
|
if (sourceb = '1') then
|
|
mult_b <= datab;
|
|
else
|
|
mult_b <= scaninb;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG5;
|
|
|
|
IFG6: if (input_reg_b = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, datab, scaninb, sourceb)
|
|
begin
|
|
if (((input_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_b <= (others => '0');
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
if (input_source_b = "DATAB") then
|
|
mult_b <= datab;
|
|
elsif (input_source_b = "SCANB") then
|
|
mult_b <= scaninb;
|
|
elsif (input_source_b = "VARIABLE") then
|
|
if (sourceb = '1') then
|
|
mult_b <= datab;
|
|
else
|
|
mult_b <= scaninb;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG6;
|
|
|
|
IFG7: if (input_reg_b = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, datab, scaninb, sourceb)
|
|
begin
|
|
if (((input_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_b <= (others => '0');
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
if (input_source_b = "DATAB") then
|
|
mult_b <= datab;
|
|
elsif (input_source_b = "SCANB") then
|
|
mult_b <= scaninb;
|
|
elsif (input_source_b = "VARIABLE") then
|
|
if (sourceb = '1') then
|
|
mult_b <= datab;
|
|
else
|
|
mult_b <= scaninb;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG7;
|
|
|
|
IFG8: if (input_reg_b = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, datab, scaninb, sourceb)
|
|
begin
|
|
if (((input_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_b <= (others => '0');
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
if (input_source_b = "DATAB") then
|
|
mult_b <= datab;
|
|
elsif (input_source_b = "SCANB") then
|
|
mult_b <= scaninb;
|
|
elsif (input_source_b = "VARIABLE") then
|
|
if (sourceb = '1') then
|
|
mult_b <= datab;
|
|
else
|
|
mult_b <= scaninb;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG8;
|
|
|
|
-- ------------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set addsub_reg)
|
|
-- The signal registered is addnsub
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if addnsub_reg is unregistered and
|
|
-- addnsub changes value
|
|
-- ------------------------------------------------------------------------------
|
|
IFG9: if (addnsub_reg = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub)
|
|
begin
|
|
if (((addnsub_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
addsub_reg <= addnsub;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG9;
|
|
|
|
IFG10: if (addnsub_reg = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub)
|
|
begin
|
|
if (((addnsub_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
addsub_reg <= addnsub;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG10;
|
|
|
|
IFG11: if (addnsub_reg = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub)
|
|
begin
|
|
if (((addnsub_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
addsub_reg <= addnsub;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG11;
|
|
|
|
IFG12: if (addnsub_reg = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub)
|
|
begin
|
|
if (((addnsub_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
addsub_reg <= addnsub;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG12;
|
|
|
|
|
|
-- ------------------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set addsub_pipe)
|
|
-- The signal registered is addnsub_latent
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if addnsub_pipeline_reg is unregistered and
|
|
-- addsub_latent changes value
|
|
-- ------------------------------------------------------------------------------------
|
|
|
|
IFG12b: if (addnsub_pipeline_reg = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, addsub_latent)
|
|
begin
|
|
if (((addnsub_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
addsub_pipe <= addsub_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG12b;
|
|
|
|
IFG14: if (addnsub_pipeline_reg = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, addsub_latent)
|
|
begin
|
|
if (((addnsub_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
addsub_pipe <= addsub_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG14;
|
|
|
|
IFG15: if (addnsub_pipeline_reg = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, addsub_latent)
|
|
begin
|
|
if (((addnsub_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
addsub_pipe <= addsub_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG15;
|
|
|
|
IFG16: if (addnsub_pipeline_reg = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, addsub_latent)
|
|
begin
|
|
if (((addnsub_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
addsub_pipe <= addsub_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG16;
|
|
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set acc_sload_reg)
|
|
-- The signal registered is accum_sload
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if accum_sload_reg is unregistered and
|
|
-- accum_sload changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
IFG17: if (accum_sload_reg = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, accum_sload)
|
|
begin
|
|
if (((accum_sload_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
acc_sload_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
acc_sload_reg <= accum_sload;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG17;
|
|
|
|
IFG18: if (accum_sload_reg = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, accum_sload)
|
|
begin
|
|
if (((accum_sload_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
acc_sload_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
acc_sload_reg <= accum_sload;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG18;
|
|
|
|
IFG19: if (accum_sload_reg = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, accum_sload)
|
|
begin
|
|
if (((accum_sload_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
acc_sload_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if((ena2 ='1')) then
|
|
acc_sload_reg <= accum_sload;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG19;
|
|
|
|
IFG20: if (accum_sload_reg = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, accum_sload)
|
|
begin
|
|
if (((accum_sload_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
acc_sload_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
acc_sload_reg <= accum_sload;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG20;
|
|
|
|
|
|
|
|
-- ------------------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set accum_sload_pipe)
|
|
-- The signal registered is accum_sload_latent
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if accum_sload_pipeline_reg
|
|
-- is unregistered and accum_sload_latent changes value
|
|
-- ------------------------------------------------------------------------------------
|
|
IFG21: if (accum_sload_pipeline_reg = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, accum_sload_latent)
|
|
begin
|
|
if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_sload_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 = '1')) then
|
|
accum_sload_pipe <= accum_sload_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG21;
|
|
|
|
IFG22: if (accum_sload_pipeline_reg = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, accum_sload_latent)
|
|
begin
|
|
if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_sload_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 = '1')) then
|
|
accum_sload_pipe <= accum_sload_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG22;
|
|
|
|
IFG23: if (accum_sload_pipeline_reg = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, accum_sload_latent)
|
|
begin
|
|
if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_sload_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 = '1')) then
|
|
accum_sload_pipe <= accum_sload_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG23;
|
|
|
|
IFG24: if (accum_sload_pipeline_reg = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, accum_sload_latent)
|
|
begin
|
|
if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_sload_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 = '1')) then
|
|
accum_sload_pipe <= accum_sload_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG24;
|
|
|
|
|
|
-- ------------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set sign_a_reg)
|
|
-- The signal registered is signa
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if sign_reg_a is unregistered and
|
|
-- signa changes value
|
|
-- ------------------------------------------------------------------------------
|
|
|
|
IFG25: if (sign_reg_a = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, signa)
|
|
begin
|
|
if (((sign_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_reg <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 ='1') then
|
|
sign_a_reg <= signa;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG25;
|
|
|
|
IFG26: if (sign_reg_a = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, signa)
|
|
begin
|
|
if (((sign_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_reg <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 ='1')) then
|
|
sign_a_reg <= signa;
|
|
end if;
|
|
end process;
|
|
end generate IFG26;
|
|
|
|
IFG27: if (sign_reg_a = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, signa)
|
|
begin
|
|
if (((sign_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_reg <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 ='1')) then
|
|
sign_a_reg <= signa;
|
|
end if;
|
|
end process;
|
|
end generate IFG27;
|
|
|
|
IFG28: if (sign_reg_a = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, signa)
|
|
begin
|
|
if (((sign_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_reg <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 ='1')) then
|
|
sign_a_reg <= signa;
|
|
end if;
|
|
end process;
|
|
end generate IFG28;
|
|
|
|
|
|
|
|
|
|
-- ------------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set sign_b_reg)
|
|
-- The signal registered is signb
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if sign_reg_b is unregistered and
|
|
-- signb changes value
|
|
-- ------------------------------------------------------------------------------
|
|
|
|
IFG29: if (sign_reg_b = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, signb)
|
|
begin
|
|
if (((sign_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_reg <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 ='1') then
|
|
sign_b_reg <= signb;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG29;
|
|
|
|
IFG30: if (sign_reg_b = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, signb)
|
|
begin
|
|
if (((sign_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_reg <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 ='1')) then
|
|
sign_b_reg <= signb;
|
|
end if;
|
|
end process;
|
|
end generate IFG30;
|
|
|
|
IFG31: if (sign_reg_b = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, signb)
|
|
begin
|
|
if (((sign_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_reg <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 ='1')) then
|
|
sign_b_reg <= signb;
|
|
end if;
|
|
end process;
|
|
end generate IFG31;
|
|
|
|
IFG32: if (sign_reg_b = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, signb)
|
|
begin
|
|
if (((sign_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_reg <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 ='1'))then
|
|
sign_b_reg <= signb;
|
|
end if;
|
|
end process;
|
|
end generate IFG32;
|
|
|
|
|
|
-- -------------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set sign_a_pipe)
|
|
-- The signal registered is sign_a_latent
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if sign_pipeline_reg_a
|
|
-- is unregistered and sign_a_latent changes value
|
|
-- -------------------------------------------------------------------------------
|
|
|
|
IFG33: if (sign_pipeline_reg_a = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, sign_a_latent)
|
|
begin
|
|
if (((sign_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_pipe <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 ='1') then
|
|
sign_a_pipe <= sign_a_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG33;
|
|
|
|
IFG34: if (sign_pipeline_reg_a = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, sign_a_latent)
|
|
begin
|
|
if (((sign_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_pipe <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 ='1')) then
|
|
sign_a_pipe <= sign_a_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG34;
|
|
|
|
IFG35: if (sign_pipeline_reg_a = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, sign_a_latent)
|
|
begin
|
|
if (((sign_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_pipe <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 ='1')) then
|
|
sign_a_pipe <= sign_a_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG35;
|
|
|
|
IFG36: if (sign_pipeline_reg_a = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, sign_a_latent)
|
|
begin
|
|
if (((sign_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_pipe <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 ='1')) then
|
|
sign_a_pipe <= sign_a_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG36;
|
|
|
|
|
|
-- -------------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set sign_b_pipe)
|
|
-- The signal registered is sign_b_latent
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if sign_pipeline_reg_b
|
|
-- is unregistered and sign_b_latent changes value
|
|
-- -------------------------------------------------------------------------------
|
|
|
|
IFG37: if (sign_pipeline_reg_b = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, sign_b_latent)
|
|
begin
|
|
if (((sign_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_pipe <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 ='1') then
|
|
sign_b_pipe <= sign_b_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG37;
|
|
|
|
IFG38: if (sign_pipeline_reg_b = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, sign_b_latent)
|
|
begin
|
|
if (((sign_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_pipe <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 ='1')) then
|
|
sign_b_pipe <= sign_b_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG38;
|
|
|
|
IFG39: if (sign_pipeline_reg_b = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, sign_b_latent)
|
|
begin
|
|
if (((sign_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_pipe <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 ='1')) then
|
|
sign_b_pipe <= sign_b_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG39;
|
|
|
|
IFG40: if (sign_pipeline_reg_b = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, sign_b_latent)
|
|
begin
|
|
if (((sign_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((sign_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_pipe <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 ='1')) then
|
|
sign_b_pipe <= sign_b_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG40;
|
|
|
|
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set accum_round_pipe_wire)
|
|
-- The signal registered is accum_round
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if accum_round_reg
|
|
-- is unregistered and accum_round changes value
|
|
-------------------------------------------------------------------------------------
|
|
|
|
IFG41: if (accum_round_reg = "CLOCK0") generate
|
|
process (clock0, accum_round, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_round_pipe_wire <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 = '1') then
|
|
if (IS_STRATIXIII) then
|
|
accum_round_pipe_wire <= accum_sload;
|
|
else
|
|
accum_round_pipe_wire <= accum_round;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG41;
|
|
|
|
IFG42: if (accum_round_reg = "CLOCK1") generate
|
|
process (clock1, accum_round, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
|
|
if (((accum_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_round_pipe_wire <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 = '1')) then
|
|
if (IS_STRATIXIII) then
|
|
accum_round_pipe_wire <= accum_sload;
|
|
else
|
|
accum_round_pipe_wire <= accum_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG42;
|
|
|
|
IFG43: if (accum_round_reg = "CLOCK2") generate
|
|
process (clock2, accum_round, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
|
|
if (((accum_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_round_pipe_wire <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 = '1')) then
|
|
if (IS_STRATIXIII) then
|
|
accum_round_pipe_wire <= accum_sload;
|
|
else
|
|
accum_round_pipe_wire <= accum_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG43;
|
|
|
|
IFG44: if (accum_round_reg = "CLOCK3") generate
|
|
process (clock3, accum_round, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_round_pipe_wire <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 = '1')) then
|
|
if (IS_STRATIXIII) then
|
|
accum_round_pipe_wire <= accum_sload;
|
|
else
|
|
accum_round_pipe_wire <= accum_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG44;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set accum_round_wire)
|
|
-- The signal registered is accum_round_pipe_wire
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if accum_round_pipeline_reg
|
|
-- is unregistered and accum_round_pipe_wire changes value
|
|
-------------------------------------------------------------------------------------
|
|
|
|
IFG45: if (accum_round_pipeline_reg = "CLOCK0") generate
|
|
process (clock0, accum_round_pipe_wire, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_round_wire <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 = '1') then
|
|
accum_round_wire <= accum_round_pipe_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG45;
|
|
|
|
IFG46: if (accum_round_pipeline_reg = "CLOCK1") generate
|
|
process (clock1, accum_round_pipe_wire, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_round_wire <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 = '1')) then
|
|
accum_round_wire <= accum_round_pipe_wire;
|
|
end if;
|
|
end process;
|
|
end generate IFG46;
|
|
|
|
IFG47: if (accum_round_pipeline_reg = "CLOCK2") generate
|
|
process (clock2, accum_round_pipe_wire, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_round_wire <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 = '1')) then
|
|
accum_round_wire <= accum_round_pipe_wire;
|
|
end if;
|
|
end process;
|
|
end generate IFG47;
|
|
|
|
IFG48: if (accum_round_pipeline_reg = "CLOCK3") generate
|
|
process (clock3, accum_round_pipe_wire, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_round_wire <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 = '1')) then
|
|
accum_round_wire <= accum_round_pipe_wire;
|
|
end if;
|
|
end process;
|
|
end generate IFG48;
|
|
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set accum_saturation_pipe_wire)
|
|
-- The signal registered is accum_saturation
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if accum_saturation_reg
|
|
-- is unregistered and accum_saturation changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
IFG49: if (accum_saturation_reg = "CLOCK0") generate
|
|
process (clock0, accum_saturation, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_saturation_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_saturation_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_saturation_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_saturation_pipe_wire <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 = '1')then
|
|
accum_saturation_pipe_wire <= accum_saturation;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG49;
|
|
|
|
IFG50: if (accum_saturation_reg = "CLOCK1") generate
|
|
process (clock1, accum_saturation, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_saturation_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_saturation_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_saturation_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_saturation_pipe_wire <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 = '1')) then
|
|
accum_saturation_pipe_wire <= accum_saturation;
|
|
end if;
|
|
end process;
|
|
end generate IFG50;
|
|
|
|
IFG51: if (accum_saturation_reg = "CLOCK2") generate
|
|
process (clock2, accum_saturation, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_saturation_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_saturation_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_saturation_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_saturation_pipe_wire <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 = '1')) then
|
|
accum_saturation_pipe_wire <= accum_saturation;
|
|
end if;
|
|
end process;
|
|
end generate IFG51;
|
|
|
|
IFG52: if (accum_saturation_reg = "CLOCK3") generate
|
|
process (clock3, accum_saturation, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_saturation_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_saturation_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_saturation_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_saturation_pipe_wire <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 = '1')) then
|
|
accum_saturation_pipe_wire <= accum_saturation;
|
|
end if;
|
|
end process;
|
|
end generate IFG52;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set accum_saturate_wire)
|
|
-- The signal registered is accum_saturation_pipe_wire
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if accum_saturation_pipeline_reg
|
|
-- is unregistered and accum_saturation_pipe_wire changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
IFG53: if (accum_saturation_pipeline_reg = "CLOCK0") generate
|
|
process (clock0, accum_saturation_pipe_wire, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_saturation_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_saturate_wire <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 = '1') then
|
|
accum_saturate_wire <= accum_saturation_pipe_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG53;
|
|
|
|
IFG54: if (accum_saturation_pipeline_reg = "CLOCK1") generate
|
|
process (clock1, accum_saturation_pipe_wire, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_saturation_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_saturate_wire <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 = '1')) then
|
|
accum_saturate_wire <= accum_saturation_pipe_wire;
|
|
end if;
|
|
end process;
|
|
end generate IFG54;
|
|
|
|
IFG55: if (accum_saturation_pipeline_reg = "CLOCK2") generate
|
|
process (clock2, accum_saturation_pipe_wire, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_saturation_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_saturate_wire <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 = '1')) then
|
|
accum_saturate_wire <= accum_saturation_pipe_wire;
|
|
end if;
|
|
end process;
|
|
end generate IFG55;
|
|
|
|
IFG56: if (accum_saturation_pipeline_reg = "CLOCK3") generate
|
|
process (clock3, accum_saturation_pipe_wire, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_saturation_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_saturation_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accum_saturate_wire <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 = '1')) then
|
|
accum_saturate_wire <= accum_saturation_pipe_wire;
|
|
end if;
|
|
end process;
|
|
end generate IFG56;
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set mult_round_wire)
|
|
-- The signal registered is mult_round
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if mult_round_reg
|
|
-- is unregistered and mult_round changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
IFG57: if (mult_round_reg = "CLOCK0") generate
|
|
process (clock0, mult_round, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((mult_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult_round_wire <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 = '1') then
|
|
mult_round_wire <= mult_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG57;
|
|
|
|
IFG58: if (mult_round_reg = "CLOCK1") generate
|
|
process (clock1, mult_round, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((mult_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult_round_wire <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 = '1')) then
|
|
mult_round_wire <= mult_round;
|
|
end if;
|
|
end process;
|
|
end generate IFG58;
|
|
|
|
IFG59: if (mult_round_reg = "CLOCK2") generate
|
|
process (clock2, mult_round, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((mult_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult_round_wire <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 = '1')) then
|
|
mult_round_wire <= mult_round;
|
|
end if;
|
|
end process;
|
|
end generate IFG59;
|
|
|
|
IFG60: if (mult_round_reg = "CLOCK3") generate
|
|
process (clock3, mult_round, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((mult_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult_round_wire <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 = '1')) then
|
|
mult_round_wire <= mult_round;
|
|
end if;
|
|
end process;
|
|
end generate IFG60;
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set mult_saturation_wire)
|
|
-- The signal registered is mult_saturation
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if mult_saturation_reg
|
|
-- is unregistered and mult_saturation changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
IFG61: if (mult_saturation_reg = "CLOCK0") generate
|
|
process (clock0, mult_saturation, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((mult_saturation_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult_saturation_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult_saturation_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult_saturate_wire <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 = '1') then
|
|
mult_saturate_wire <= mult_saturation;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG61;
|
|
|
|
IFG62: if (mult_saturation_reg = "CLOCK1") generate
|
|
process (clock1, mult_saturation, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((mult_saturation_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult_saturation_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult_saturation_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult_saturate_wire <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 = '1')) then
|
|
mult_saturate_wire <= mult_saturation;
|
|
end if;
|
|
end process;
|
|
end generate IFG62;
|
|
|
|
IFG63: if (mult_saturation_reg = "CLOCK2") generate
|
|
process (clock2, mult_saturation, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((mult_saturation_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult_saturation_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult_saturation_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult_saturate_wire <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 = '1')) then
|
|
mult_saturate_wire <= mult_saturation;
|
|
end if;
|
|
end process;
|
|
end generate IFG63;
|
|
|
|
IFG64: if (mult_saturation_reg = "CLOCK3") generate
|
|
process (clock3, mult_saturation, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((mult_saturation_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult_saturation_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult_saturation_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult_saturate_wire <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 = '1')) then
|
|
mult_saturate_wire <= mult_saturation;
|
|
end if;
|
|
end process;
|
|
end generate IFG64;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set sload_upper_data_reg)
|
|
-- The signal registered is accum_sload_upper_data
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if accum_sload_upper_data_reg
|
|
-- is unregistered and accum_sload_upper_data changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
IFG65: if (accum_sload_upper_data_reg = "CLOCK0") generate
|
|
process (clock0, accum_sload_upper_data, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_sload_upper_data_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
sload_upper_data_reg <= (others => '0');
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 = '1') then
|
|
sload_upper_data_reg <= accum_sload_upper_data;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG65;
|
|
|
|
IFG66: if (accum_sload_upper_data_reg = "CLOCK1") generate
|
|
process (clock1, accum_sload_upper_data, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_sload_upper_data_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
sload_upper_data_reg <= (others => '0');
|
|
elsif (rising_edge(clock1) and (ena1 = '1')) then
|
|
sload_upper_data_reg <= accum_sload_upper_data;
|
|
end if;
|
|
end process;
|
|
end generate IFG66;
|
|
|
|
IFG67: if (accum_sload_upper_data_reg = "CLOCK2") generate
|
|
process (clock2, accum_sload_upper_data, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_sload_upper_data_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
sload_upper_data_reg <= (others => '0');
|
|
elsif (rising_edge(clock2) and (ena2 = '1')) then
|
|
sload_upper_data_reg <= accum_sload_upper_data;
|
|
end if;
|
|
end process;
|
|
end generate IFG67;
|
|
|
|
IFG68: if (accum_sload_upper_data_reg = "CLOCK3") generate
|
|
process (clock3, accum_sload_upper_data, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_sload_upper_data_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_upper_data_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
sload_upper_data_reg <= (others => '0');
|
|
elsif (rising_edge(clock3) and (ena3 = '1')) then
|
|
sload_upper_data_reg <= accum_sload_upper_data;
|
|
end if;
|
|
end process;
|
|
end generate IFG68;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set sload_upper_data_wire)
|
|
-- The signal registered is sload_upper_data_latent
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if accum_sload_upper_data_pipeline_reg
|
|
-- is unregistered and sload_upper_data_latent changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
IFG69: if (accum_sload_upper_data_pipeline_reg = "CLOCK0") generate
|
|
process (clock0, sload_upper_data_latent, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_sload_upper_data_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
sload_upper_data_wire <= (others => '0');
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 = '1') then
|
|
sload_upper_data_wire <= sload_upper_data_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG69;
|
|
|
|
IFG70: if (accum_sload_upper_data_pipeline_reg = "CLOCK1") generate
|
|
process (clock1, sload_upper_data_latent, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_sload_upper_data_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
sload_upper_data_wire <= (others => '0');
|
|
elsif (rising_edge(clock1) and (ena1 = '1')) then
|
|
sload_upper_data_wire <= sload_upper_data_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG70;
|
|
|
|
IFG71: if (accum_sload_upper_data_pipeline_reg = "CLOCK2") generate
|
|
process (clock2, sload_upper_data_latent, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_sload_upper_data_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
sload_upper_data_wire <= (others => '0');
|
|
elsif (rising_edge(clock2) and (ena2 = '1')) then
|
|
sload_upper_data_wire <= sload_upper_data_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG71;
|
|
|
|
IFG72: if (accum_sload_upper_data_pipeline_reg = "CLOCK3") generate
|
|
process (clock3, sload_upper_data_latent, aclr0, aclr1, aclr2, aclr3)
|
|
begin
|
|
if (((accum_sload_upper_data_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_upper_data_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
sload_upper_data_wire <= (others => '0');
|
|
elsif (rising_edge(clock3) and (ena3 = '1')) then
|
|
sload_upper_data_wire <= sload_upper_data_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG72;
|
|
|
|
|
|
-- ----------------------------------------------------------------------------
|
|
-- This block multiplies the two input numbers and sets the result to mult_final_out
|
|
-- ----------------------------------------------------------------------------
|
|
process (mult_a, mult_b, sign_a_reg, sign_b_reg, mult_round_wire, mult_saturate_wire, signa, signb, temp_mult_zero)
|
|
variable temp_mult_int : std_logic_vector (int_width_a + int_width_b downto 0);
|
|
variable temp_mult : std_logic_vector (int_width_a + int_width_b -1 downto 0):= (others => '0');
|
|
variable neg_a, neg_b, is_signed : std_logic;
|
|
variable mult_round_out : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
|
|
variable mult_saturate_overflow : std_logic := '0';
|
|
variable mult_saturate_out : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
|
|
variable mult_result : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
|
|
|
|
variable int_mult_a : std_logic_vector (int_width_a - 1 downto 0);
|
|
variable int_mult_b : std_logic_vector (int_width_b - 1 downto 0);
|
|
variable mult_a_zero_bits_pad : std_logic_vector (int_width_a - width_a - 1 downto 0) := (others => '0');
|
|
variable mult_b_zero_bits_pad : std_logic_vector (int_width_b - width_b - 1 downto 0) := (others => '0');
|
|
begin
|
|
is_signed := '0';
|
|
|
|
if (port_signa = "PORT_CONNECTIVITY") then
|
|
if (((representation_a = "SIGNED") and (signa = 'Z')) or (sign_a_reg = '1')) then
|
|
neg_a := mult_a (width_a-1);
|
|
is_signed :='1';
|
|
end if;
|
|
else
|
|
if (((representation_a = "SIGNED") and (port_signa = "PORT_UNUSED")) or (sign_a_reg = '1')) then
|
|
neg_a := mult_a (width_a-1);
|
|
is_signed :='1';
|
|
end if;
|
|
end if;
|
|
|
|
if (port_signb = "PORT_CONNECTIVITY") then
|
|
if (((representation_b = "SIGNED") and (signb = 'Z')) or (sign_b_reg = '1')) then
|
|
neg_b := mult_b (width_b-1);
|
|
is_signed :='1';
|
|
end if;
|
|
else
|
|
if (((representation_b = "SIGNED") and (port_signb = "PORT_UNUSED")) or (sign_b_reg = '1')) then
|
|
neg_b := mult_b (width_b-1);
|
|
is_signed :='1';
|
|
end if;
|
|
end if;
|
|
|
|
if(int_width_a > width_a) then
|
|
int_mult_a := mult_a & mult_a_zero_bits_pad;
|
|
else
|
|
int_mult_a := mult_a;
|
|
end if;
|
|
|
|
if(int_width_b > width_b) then
|
|
int_mult_b := mult_b & mult_b_zero_bits_pad;
|
|
else
|
|
int_mult_b := mult_b;
|
|
end if;
|
|
|
|
if (port_signa = "PORT_CONNECTIVITY" and port_signb ="PORT_CONNECTIVITY") then
|
|
if (((representation_a = "SIGNED") and (signa = 'Z')) or (sign_a_reg = '1')) then
|
|
if (((representation_b = "SIGNED") and( signb = 'Z')) or (sign_b_reg = '1')) then
|
|
temp_mult_int := signed (temp_mult_zero) + (signed (int_mult_a) * signed (int_mult_b));
|
|
else
|
|
temp_mult_int := signed (temp_mult_zero) + (signed (int_mult_a) * unsigned (int_mult_b));
|
|
end if;
|
|
else
|
|
if (((representation_b = "SIGNED") and (signb = 'Z')) or (sign_b_reg = '1')) then
|
|
temp_mult_int := signed (temp_mult_zero) + (unsigned (int_mult_a) * signed (int_mult_b));
|
|
else
|
|
temp_mult_int := signed (temp_mult_zero) + (unsigned (int_mult_a) * unsigned (int_mult_b));
|
|
end if;
|
|
end if;
|
|
else
|
|
if (((representation_a = "SIGNED") and (port_signa = "PORT_UNUSED")) or (sign_a_reg = '1')) then
|
|
if (((representation_b = "SIGNED") and(port_signb = "PORT_UNUSED")) or (sign_b_reg = '1')) then
|
|
temp_mult_int := signed (temp_mult_zero) + (signed (int_mult_a) * signed (int_mult_b));
|
|
else
|
|
temp_mult_int := signed (temp_mult_zero) + (signed (int_mult_a) * unsigned (int_mult_b));
|
|
end if;
|
|
else
|
|
if (((representation_b = "SIGNED") and (port_signb = "PORT_UNUSED")) or (sign_b_reg = '1')) then
|
|
temp_mult_int := signed (temp_mult_zero) + (unsigned (int_mult_a) * signed (int_mult_b));
|
|
else
|
|
temp_mult_int := signed (temp_mult_zero) + (unsigned (int_mult_a) * unsigned (int_mult_b));
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
temp_mult := temp_mult_int (int_width_a + int_width_b -1 downto 0);
|
|
|
|
if (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) then
|
|
-- StratixII rounding support
|
|
|
|
-- This is based on both input is in Q1.15 format with assumption
|
|
-- width_a = 16 and width_b = 16
|
|
|
|
if ((multiplier_rounding = "YES") or
|
|
((multiplier_rounding = "VARIABLE") and (mult_round_wire = '1'))) then
|
|
mult_round_out := unsigned (temp_mult) + ( 2 ** (int_width_a + int_width_b - 18));
|
|
else
|
|
mult_round_out := temp_mult;
|
|
end if;
|
|
|
|
-- StratixII saturation support
|
|
|
|
if ((multiplier_saturation = "YES") or
|
|
(( multiplier_saturation = "VARIABLE") and (mult_saturate_wire = '1'))) then
|
|
if((mult_round_out(int_width_a + int_width_b - 1) = '0') and (mult_round_out(int_width_a + int_width_b - 2) = '1')) then
|
|
mult_saturate_overflow := '1';
|
|
else
|
|
mult_saturate_overflow := '0';
|
|
end if;
|
|
|
|
if (mult_saturate_overflow = '0') then
|
|
mult_saturate_out := mult_round_out;
|
|
else
|
|
for i in (int_width_a + int_width_b - 1) downto (int_width_a + int_width_b - 2) loop
|
|
mult_saturate_out(i) := mult_round_out(int_width_a + int_width_b - 1);
|
|
end loop;
|
|
|
|
for i in (int_width_a + int_width_b - 3) downto 0 loop
|
|
mult_saturate_out(i) := not mult_round_out(int_width_a + int_width_b - 1);
|
|
end loop;
|
|
|
|
for i in (int_width_a + int_width_b - 34) downto 0 loop
|
|
mult_saturate_out(i) := '0';
|
|
end loop;
|
|
|
|
end if;
|
|
else
|
|
mult_saturate_out := mult_round_out;
|
|
mult_saturate_overflow := '0';
|
|
end if;
|
|
|
|
if ((multiplier_rounding = "YES") or
|
|
((multiplier_rounding = "VARIABLE") and (mult_round_wire = '1'))) then
|
|
|
|
mult_result := mult_saturate_out;
|
|
|
|
for i in (int_width_a + int_width_b - 18) downto 0 loop
|
|
mult_result(i) := '0';
|
|
end loop;
|
|
else
|
|
mult_result := mult_saturate_out;
|
|
end if;
|
|
|
|
mult_is_saturated_wire <= mult_saturate_overflow;
|
|
end if;
|
|
|
|
if (not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) then
|
|
mult_final_out <= temp_mult;
|
|
else
|
|
mult_final_out <= mult_result;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
-- ----------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set mult_res)
|
|
-- The signal registered is mult_out_latent
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if multiplier_reg
|
|
-- is unregistered and mult_out_latent changes value
|
|
-- ----------------------------------------------------------------------------
|
|
IFG73: if (multiplier_reg = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, mult_out_latent)
|
|
begin
|
|
if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_res <= (others =>'0');
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 ='1') then
|
|
mult_res <= mult_out_latent;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG73;
|
|
|
|
IFG74: if (multiplier_reg = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, mult_out_latent)
|
|
begin
|
|
if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_res <= (others =>'0');
|
|
elsif (rising_edge(clock1) and (ena1 ='1')) then
|
|
mult_res <= mult_out_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG74;
|
|
|
|
IFG75: if (multiplier_reg = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, mult_out_latent)
|
|
begin
|
|
if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_res <= (others =>'0');
|
|
elsif (rising_edge(clock2) and (ena2 ='1')) then
|
|
mult_res <= mult_out_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG75;
|
|
|
|
IFG76: if (multiplier_reg = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, mult_out_latent)
|
|
begin
|
|
if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_res <= (others =>'0');
|
|
elsif (rising_edge(clock3) and (ena3 ='1')) then
|
|
mult_res <= mult_out_latent;
|
|
end if;
|
|
end process;
|
|
end generate IFG76;
|
|
|
|
-- ----------------------------------------------------------------------------
|
|
-- This process contains 1 register and a combinatorial block (to set mult_is_saturated_reg)
|
|
-- The signal registered is mult_is_saturated_wire
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if multiplier_reg
|
|
-- is unregistered and mult_is_saturated_wire changes value
|
|
-- ----------------------------------------------------------------------------
|
|
IFG77: if (multiplier_reg = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, mult_is_saturated_wire)
|
|
begin
|
|
if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_is_saturated_reg <= '0';
|
|
elsif (rising_edge(clock0)) then
|
|
if (ena0 ='1') then
|
|
mult_is_saturated_reg <= mult_is_saturated_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG77;
|
|
|
|
IFG78: if (multiplier_reg = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, mult_is_saturated_wire)
|
|
begin
|
|
if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_is_saturated_reg <= '0';
|
|
elsif (rising_edge(clock1) and (ena1 ='1')) then
|
|
mult_is_saturated_reg <= mult_is_saturated_wire;
|
|
end if;
|
|
end process;
|
|
end generate IFG78;
|
|
|
|
IFG79: if (multiplier_reg = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, mult_is_saturated_wire)
|
|
begin
|
|
if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_is_saturated_reg <= '0';
|
|
elsif (rising_edge(clock2) and (ena2 ='1')) then
|
|
mult_is_saturated_reg <= mult_is_saturated_wire;
|
|
end if;
|
|
end process;
|
|
end generate IFG79;
|
|
|
|
IFG80: if (multiplier_reg = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, mult_is_saturated_wire)
|
|
begin
|
|
if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult_is_saturated_reg <= '0';
|
|
elsif (rising_edge(clock3) and (ena3 ='1')) then
|
|
mult_is_saturated_reg <= mult_is_saturated_wire;
|
|
end if;
|
|
end process;
|
|
end generate IFG80;
|
|
|
|
IFG81: if (extra_multiplier_latency >0) generate
|
|
process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3)
|
|
-- ------------------------------------------------------------------------
|
|
-- This process is only valid if extra_multiplier_latency is greater then 0
|
|
-- ------------------------------------------------------------------------
|
|
variable head_mult_int: integer := 0;
|
|
|
|
begin
|
|
-- ------------------------------------------------------------------------
|
|
-- This process is only valid if extra_multiplier_latency is greater then 0
|
|
-- ------------------------------------------------------------------------
|
|
|
|
if ( (((multiplier_aclr= "ACLR0") or (multiplier_reg = "UNREGISTERED")) and (aclr0 = '1')) or
|
|
((multiplier_reg /= "UNREGISTERED") and
|
|
( ((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((multiplier_aclr= "ACLR3") and (aclr3 = '1')) )) ) then
|
|
mult_pipe <= (others => (others => '0'));
|
|
mult_full <= (others => '0');
|
|
sload_upper_data_full <= (others => '0');
|
|
sload_upper_data_pipe <= (others => (others => '0'));
|
|
|
|
|
|
elsif ( (rising_edge(clock0) and ((multiplier_reg = "CLOCK0") or (multiplier_reg = "UNREGISTERED"))) or
|
|
(rising_edge(clock1) and (multiplier_reg = "CLOCK1")) or
|
|
(rising_edge(clock2) and (multiplier_reg = "CLOCK2")) or
|
|
(rising_edge(clock3) and (multiplier_reg = "CLOCK3")) ) then
|
|
|
|
if ((((multiplier_reg = "CLOCK0") or (multiplier_reg = "UNREGISTERED")) and (ena0 ='1')) or
|
|
((multiplier_reg = "CLOCK1") and (ena1 ='1')) or
|
|
((multiplier_reg = "CLOCK2") and (ena2 ='1')) or
|
|
((multiplier_reg = "CLOCK3") and (ena3 ='1')) ) then
|
|
|
|
if (extra_multiplier_latency >0) then
|
|
head_mult_int := head_mult;
|
|
mult_pipe (head_mult_int) <= sign_a_reg & sign_b_reg & acc_sload_reg & addsub_reg & '0' & mult_final_out;
|
|
sload_upper_data_pipe (head_mult_int) <= sload_upper_data_reg;
|
|
head_mult_int := (head_mult_int +1) mod (extra_multiplier_latency);
|
|
|
|
if (extra_multiplier_latency = 1) then
|
|
mult_full <= sign_a_reg & sign_b_reg & acc_sload_reg & addsub_reg & '0' & mult_final_out;
|
|
sload_upper_data_full <= sload_upper_data_reg;
|
|
else
|
|
mult_full <= (mult_pipe(head_mult_int));
|
|
sload_upper_data_full <= (sload_upper_data_pipe(head_mult_int));
|
|
end if;
|
|
|
|
head_mult <= head_mult_int;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG81;
|
|
|
|
process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3)
|
|
-- -------------------------------------------------------------
|
|
-- This is the main process block that performs the accumulation
|
|
-- -------------------------------------------------------------
|
|
variable head_result_int : integer := 0;
|
|
variable temp_sum : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
variable result_full : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
|
|
variable cout_int, overflow_int :std_logic;
|
|
variable temp_sum_zero : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
variable accum_int, addsub_int, signed_int : std_logic;
|
|
variable result_temp : std_logic_vector (int_width_result -1 downto 0);
|
|
variable sign_extend : std_logic_vector (int_width_result - int_width_a - int_width_b - 1 downto 0) := (others => '0');
|
|
variable mult_res_temp : std_logic_vector (int_width_result -1 downto 0) := (others => '0');
|
|
variable accum_final_out : std_logic_vector (int_width_result - 1 downto 0) := (others => '0');
|
|
variable accum_round_out : std_logic_vector (int_width_result - 1 downto 0) := (others => '0');
|
|
variable accum_saturate_overflow : std_logic := '0';
|
|
variable accum_saturate_out : std_logic_vector (int_width_result - 1 downto 0) := (others => '0');
|
|
variable accum_result_sign_bits : std_logic_vector (int_width_result - int_width_a - int_width_b + 2 - 1 downto 0) := (others => '0');
|
|
variable accum_result_sign_bits_ones : std_logic_vector (int_width_result - int_width_a - int_width_b + 2 - 1 downto 0) := (others => '1');
|
|
variable accum_result_sign_bits_zeros : std_logic_vector (int_width_result - int_width_a - int_width_b + 2 - 1 downto 0) := (others => '0');
|
|
variable accum_result : std_logic_vector (int_width_result - 1 downto 0) := (others => '0');
|
|
variable upper_data_sign_extend : std_logic := '0';
|
|
variable upper_data_sign_bit : std_logic := '0';
|
|
variable result_pipe : pipeline_accum := (others => (others => '0'));
|
|
variable sat_for_ini : integer := int_width_a + int_width_b - 34;
|
|
variable bits_to_round : integer := int_width_a + int_width_b - 18;
|
|
variable accum_sat_for_limit : integer := int_width_a + int_width_b - 33;
|
|
|
|
begin
|
|
|
|
-- -------------------------------------------------------------
|
|
-- This is the main process block that performs the accumulation
|
|
-- -------------------------------------------------------------
|
|
|
|
if (((output_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((output_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((output_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((output_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
temp_sum := (others => '0');
|
|
result_pipe := (others => (others => '0'));
|
|
result <= (others => '0');
|
|
result_int <= (others => '0');
|
|
overflow_int := '0';
|
|
overflow <= '0';
|
|
accum_is_saturated_out <= '0';
|
|
mult_is_saturated_out <= '0';
|
|
|
|
elsif ( (rising_edge(clock0) and (output_reg = "CLOCK0")) or
|
|
(rising_edge(clock1) and (output_reg = "CLOCK1")) or
|
|
(rising_edge(clock2) and (output_reg = "CLOCK2")) or
|
|
(rising_edge(clock3) and (output_reg = "CLOCK3")) ) then
|
|
|
|
if (((output_reg = "CLOCK0") and (ena0 ='1')) or
|
|
((output_reg = "CLOCK1") and (ena1 ='1')) or
|
|
((output_reg = "CLOCK2") and (ena2 ='1')) or
|
|
((output_reg = "CLOCK3") and (ena3 ='1')) ) then
|
|
|
|
if (accum_sload = 'Z') then
|
|
accum_int := '0';
|
|
else
|
|
accum_int := accum_sload_pipe;
|
|
end if;
|
|
|
|
-- check if addition flag is to be set
|
|
if (port_addnsub = "PORT_CONNECTIVITY") then
|
|
if (((addnsub = 'Z') and (accum_direction = "ADD")) or (addsub_pipe = '1')) then
|
|
addsub_int := '1';
|
|
else
|
|
addsub_int := '0';
|
|
end if;
|
|
else
|
|
if (((port_addnsub = "PORT_UNUSED") and (accum_direction = "ADD")) or (addsub_pipe = '1')) then
|
|
addsub_int := '1';
|
|
else
|
|
addsub_int := '0';
|
|
end if;
|
|
end if;
|
|
|
|
-- check if signed flag is to be set
|
|
if (port_signa = "PORT_CONNECTIVITY" and port_signb = "PORT_CONNECTIVITY") then
|
|
if ((((representation_b = "SIGNED") and (signb = 'Z')) or (sign_b_pipe = '1')) or
|
|
(((representation_a = "SIGNED") and (signa = 'Z')) or (sign_a_pipe = '1'))) then
|
|
signed_int := '1';
|
|
else
|
|
signed_int := '0';
|
|
end if;
|
|
else
|
|
if ((((representation_b = "SIGNED") and (port_signb = "PORT_UNUSED")) or (sign_b_pipe = '1')) or
|
|
(((representation_a = "SIGNED") and (port_signa = "PORT_UNUSED")) or (sign_a_pipe = '1'))) then
|
|
signed_int := '1';
|
|
else
|
|
signed_int := '0';
|
|
end if;
|
|
end if;
|
|
|
|
sign_extend := (others => (signed_int and mult_res (int_width_a + int_width_b -1)));
|
|
if (int_width_result >= (int_width_a + int_width_b)) then
|
|
mult_res_temp := sign_extend & mult_res;
|
|
else
|
|
mult_res_temp := sign_extend & mult_res(int_width_result -1 downto 0);
|
|
end if;
|
|
|
|
if (int_width_result > width_result) then
|
|
upper_data_sign_extend := '1';
|
|
else
|
|
upper_data_sign_extend := '0';
|
|
end if;
|
|
|
|
if (accum_int ='1') then
|
|
if ((not IS_STRATIXII) and
|
|
(not IS_CYCLONEII)) then
|
|
result_temp := (others => '0');
|
|
else
|
|
upper_data_sign_bit := (signed_int and sload_upper_data_wire(width_upper_data - 1));
|
|
result_temp := (others => '0');
|
|
|
|
if(upper_data_sign_extend = '1') then
|
|
for i in (int_width_result - 1) downto (int_extra_width + width_result) loop
|
|
result_temp(i) := upper_data_sign_bit;
|
|
end loop;
|
|
end if;
|
|
|
|
if(width_upper_data > width_result) then
|
|
result_temp(int_extra_width + width_result - 1 downto int_extra_width) := sload_upper_data_wire(width_result - 1 downto 0);
|
|
else
|
|
result_temp(int_extra_width + width_result - 1 downto int_extra_width + width_result - width_upper_data) := sload_upper_data_wire;
|
|
end if;
|
|
end if;
|
|
else
|
|
result_temp := result_int;
|
|
end if;
|
|
|
|
|
|
if (addsub_int = '1') then -- add the numbers if the add flag is turned on
|
|
temp_sum := unsigned(temp_sum_zero)+ unsigned (result_temp) + unsigned (mult_res_temp);
|
|
|
|
cout_int := temp_sum (int_width_result);
|
|
else -- subtract the numbers if the add flag is turned off
|
|
temp_sum := unsigned(temp_sum_zero)+ unsigned (result_temp) - unsigned (mult_res_temp);
|
|
|
|
|
|
if (unsigned (result_temp) >= unsigned (mult_res_temp)) then
|
|
cout_int := '1';
|
|
else
|
|
cout_int := '0';
|
|
end if;
|
|
end if;
|
|
|
|
if (signed_int = '1' and (not (mult_res = temp_mult_zero))) then
|
|
overflow_int := (((not (mult_res (int_width_a + int_width_b-1) xor result_temp (int_width_result -1))) xor (not (addsub_int)))
|
|
and (result_temp (int_width_result -1) xor temp_sum (int_width_result -1)));
|
|
else
|
|
overflow_int := not (addsub_int xor cout_int);
|
|
end if;
|
|
|
|
|
|
if (IS_STRATIXII) then
|
|
-- StratixII rounding support
|
|
|
|
-- This is based on both input is in Q1.15 format with assumption
|
|
-- width_a = 16 and width_b = 16
|
|
-- result_width = widht_a + width_b
|
|
|
|
if ((accumulator_rounding = "YES") or
|
|
((accumulator_rounding = "VARIABLE") and (accum_round_wire = '1'))) then
|
|
accum_round_out := temp_sum(int_width_result -1 downto 0);
|
|
accum_round_out := signed (accum_round_out) + ( 2 ** bits_to_round);
|
|
else
|
|
accum_round_out := temp_sum(int_width_result -1 downto 0);
|
|
end if;
|
|
|
|
-- StratixII saturation support
|
|
|
|
if ((accumulator_saturation = "YES") or
|
|
((accumulator_saturation = "VARIABLE") and (accum_saturate_wire = '1'))) then
|
|
accum_result_sign_bits := accum_round_out(int_width_result - 1 downto int_width_a + int_width_b - 2);
|
|
if ((accum_result_sign_bits = accum_result_sign_bits_ones) or
|
|
(accum_result_sign_bits = accum_result_sign_bits_zeros)) then
|
|
accum_saturate_overflow := '0';
|
|
else
|
|
accum_saturate_overflow := '1';
|
|
end if;
|
|
|
|
if (accum_saturate_overflow = '0') then
|
|
accum_saturate_out := accum_round_out;
|
|
accum_saturate_out(sat_for_ini) := '0';
|
|
else
|
|
|
|
for i in (int_width_result - 1) downto (int_width_a + int_width_b - 2) loop
|
|
accum_saturate_out(i) := accum_round_out(int_width_result - 1);
|
|
end loop;
|
|
|
|
for i in (int_width_a + int_width_b - 3) downto (accum_sat_for_limit) loop
|
|
accum_saturate_out(i) := not accum_round_out(int_width_result - 1);
|
|
end loop;
|
|
|
|
for i in (sat_for_ini) downto 0 loop
|
|
accum_saturate_out(i) := '0';
|
|
end loop;
|
|
|
|
end if;
|
|
else
|
|
accum_saturate_out := accum_round_out;
|
|
accum_saturate_overflow := '0';
|
|
end if;
|
|
|
|
if ((accumulator_rounding = "YES") or
|
|
((accumulator_rounding = "VARIABLE") and (accum_round_wire = '1'))) then
|
|
|
|
accum_result := accum_saturate_out;
|
|
for i in (bits_to_round) downto 0 loop
|
|
accum_result(i) := '0';
|
|
end loop;
|
|
else
|
|
accum_result := accum_saturate_out;
|
|
end if;
|
|
|
|
accum_is_saturated_out <= accum_saturate_overflow;
|
|
mult_is_saturated_out <= mult_is_saturated_reg;
|
|
|
|
end if;
|
|
|
|
if (not IS_STRATIXII) then
|
|
accum_final_out := temp_sum(int_width_result -1 downto 0);
|
|
else
|
|
accum_final_out := accum_result;
|
|
end if;
|
|
|
|
if (extra_accumulator_latency = 0) then
|
|
result <= accum_final_out(width_result - 1 + int_extra_width downto int_extra_width);
|
|
overflow <= overflow_int;
|
|
else
|
|
head_result_int := head_result;
|
|
result_pipe (head_result_int) := (overflow_int & accum_final_out);
|
|
head_result_int := (head_result_int +1) mod (extra_accumulator_latency + 1);
|
|
result_full := result_pipe(head_result_int);
|
|
result <= result_full (width_result - 1 + int_extra_width downto int_extra_width);
|
|
overflow <= result_full (int_width_result);
|
|
head_result <= head_result_int;
|
|
end if;
|
|
|
|
result_int <= accum_final_out;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
end behaviour; -- end of ALT_MULT_ACCUM
|
|
|
|
----------------------------------------------------------------------------
|
|
-- Module Name : altmult_add
|
|
--
|
|
-- Description : a*b + c*d
|
|
--
|
|
-- Limitation : Stratix DSP block
|
|
--
|
|
-- Results expected : signed & unsigned, maximum of 3 pipelines(latency) each.
|
|
-- possible of zero pipeline.
|
|
--
|
|
----------------------------------------------------------------------------
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
|
|
entity altmult_add is
|
|
generic (
|
|
|
|
-- ---------------------
|
|
-- PARAMETER DECLARATION
|
|
-- ---------------------
|
|
width_a : natural := 1;
|
|
width_b : natural := 1;
|
|
width_result : natural := 1;
|
|
number_of_multipliers : natural := 1;
|
|
|
|
-- A inputs
|
|
input_register_a0 : string := "CLOCK0";
|
|
input_aclr_a0 : string := "ACLR3";
|
|
input_source_a0 : string := "DATAA";
|
|
|
|
input_register_a1 : string := "CLOCK0";
|
|
input_aclr_a1 : string := "ACLR3";
|
|
input_source_a1 : string := "DATAA";
|
|
|
|
input_register_a2 : string := "CLOCK0";
|
|
input_aclr_a2 : string := "ACLR3";
|
|
input_source_a2 : string := "DATAA";
|
|
|
|
input_register_a3 : string := "CLOCK0";
|
|
input_aclr_a3 : string := "ACLR3";
|
|
input_source_a3 : string := "DATAA";
|
|
|
|
port_signa : string := "PORT_CONNECTIVITY";
|
|
representation_a : string := "UNSIGNED";
|
|
signed_register_a : string := "CLOCK0";
|
|
signed_aclr_a : string := "ACLR3";
|
|
signed_pipeline_register_a : string := "CLOCK0";
|
|
signed_pipeline_aclr_a : string := "ACLR3";
|
|
|
|
scanouta_register : string := "UNREGISTERED";
|
|
scanouta_aclr : string := "NONE";
|
|
|
|
|
|
-- B inputs
|
|
input_register_b0 : string := "CLOCK0";
|
|
input_aclr_b0 : string := "ACLR3";
|
|
input_source_b0 : string := "DATAB";
|
|
|
|
input_register_b1 : string := "CLOCK0";
|
|
input_aclr_b1 : string := "ACLR3";
|
|
input_source_b1 : string := "DATAB";
|
|
|
|
input_register_b2 : string := "CLOCK0";
|
|
input_aclr_b2 : string := "ACLR3";
|
|
input_source_b2 : string := "DATAB";
|
|
|
|
input_register_b3 : string := "CLOCK0";
|
|
input_aclr_b3 : string := "ACLR3";
|
|
input_source_b3 : string := "DATAB";
|
|
|
|
port_signb : string := "PORT_CONNECTIVITY";
|
|
representation_b : string := "UNSIGNED";
|
|
signed_register_b : string := "CLOCK0";
|
|
signed_aclr_b : string := "ACLR3";
|
|
signed_pipeline_register_b : string := "CLOCK0";
|
|
signed_pipeline_aclr_b : string := "ACLR3";
|
|
|
|
-- Multiplier parameter
|
|
multiplier_register0 : string := "CLOCK0";
|
|
multiplier_aclr0 : string := "ACLR3";
|
|
multiplier_register1 : string := "CLOCK0";
|
|
multiplier_aclr1 : string := "ACLR3";
|
|
multiplier_register2 : string := "CLOCK0";
|
|
multiplier_aclr2 : string := "ACLR3";
|
|
multiplier_register3 : string := "CLOCK0";
|
|
multiplier_aclr3 : string := "ACLR3";
|
|
|
|
port_addnsub1 : string := "PORT_CONNECTIVITY";
|
|
addnsub_multiplier_register1 : string := "CLOCK0";
|
|
addnsub_multiplier_aclr1 : string := "ACLR3";
|
|
addnsub_multiplier_pipeline_register1 : string := "CLOCK0";
|
|
addnsub_multiplier_pipeline_aclr1 : string := "ACLR3";
|
|
|
|
port_addnsub3 : string := "PORT_CONNECTIVITY";
|
|
addnsub_multiplier_register3 : string := "CLOCK0";
|
|
addnsub_multiplier_aclr3 : string := "ACLR3";
|
|
addnsub_multiplier_pipeline_register3 : string := "CLOCK0";
|
|
addnsub_multiplier_pipeline_aclr3 : string := "ACLR3";
|
|
|
|
multiplier1_direction : string := "ADD";
|
|
multiplier3_direction : string := "ADD";
|
|
|
|
-- output parameters
|
|
output_register : string := "CLOCK0";
|
|
output_aclr : string := "ACLR3";
|
|
|
|
-- StratixII parameters
|
|
multiplier01_rounding : string := "NO";
|
|
multiplier01_saturation : string := "NO";
|
|
mult01_round_aclr : string := "ACLR3";
|
|
mult01_round_register : string := "CLOCK0";
|
|
mult01_saturation_register : string := "CLOCK0";
|
|
mult01_saturation_aclr : string := "ACLR3";
|
|
multiplier23_rounding : string := "NO";
|
|
multiplier23_saturation : string := "NO";
|
|
mult23_round_aclr : string := "ACLR3";
|
|
mult23_round_register : string := "CLOCK0";
|
|
mult23_saturation_register : string := "CLOCK0";
|
|
mult23_saturation_aclr : string := "ACLR3";
|
|
adder1_rounding : string := "NO";
|
|
adder3_rounding : string := "NO";
|
|
addnsub1_round_aclr : string := "ACLR3";
|
|
addnsub1_round_pipeline_aclr : string := "ACLR3";
|
|
addnsub1_round_register : string := "CLOCK0";
|
|
addnsub1_round_pipeline_register : string := "CLOCK0";
|
|
addnsub3_round_aclr : string := "ACLR3";
|
|
addnsub3_round_pipeline_aclr : string := "ACLR3";
|
|
addnsub3_round_register : string := "CLOCK0";
|
|
addnsub3_round_pipeline_register : string := "CLOCK0";
|
|
port_mult0_is_saturated : string := "UNUSED";
|
|
port_mult1_is_saturated : string := "UNUSED";
|
|
port_mult2_is_saturated : string := "UNUSED";
|
|
port_mult3_is_saturated : string := "UNUSED";
|
|
|
|
-- Stratix III parameters
|
|
-- Rounding parameters
|
|
output_rounding : string := "NO";
|
|
output_round_type : string := "NEAREST_INTEGER";
|
|
width_msb : integer := 17;
|
|
output_round_register : string := "UNREGISTERED";
|
|
output_round_aclr : string := "NONE";
|
|
output_round_pipeline_register : string := "UNREGISTERED";
|
|
output_round_pipeline_aclr : string := "NONE";
|
|
|
|
chainout_rounding : string := "NO";
|
|
chainout_round_register : string := "UNREGISTERED";
|
|
chainout_round_aclr : string := "NONE";
|
|
chainout_round_pipeline_register : string := "UNREGISTERED";
|
|
chainout_round_pipeline_aclr : string := "NONE";
|
|
chainout_round_output_register : string := "UNREGISTERED";
|
|
chainout_round_output_aclr : string := "NONE";
|
|
|
|
-- saturation parameters
|
|
port_output_is_overflow : string := "PORT_UNUSED";
|
|
port_chainout_sat_is_overflow : string := "PORT_UNUSED";
|
|
output_saturation : string := "NO";
|
|
output_saturate_type : string := "ASYMMETRIC";
|
|
width_saturate_sign : integer := 1;
|
|
output_saturate_register : string := "UNREGISTERED";
|
|
output_saturate_aclr : string := "NONE";
|
|
output_saturate_pipeline_register : string := "UNREGISTERED";
|
|
output_saturate_pipeline_aclr : string := "NONE";
|
|
|
|
chainout_saturation : string := "NO";
|
|
chainout_saturate_register : string := "UNREGISTERED";
|
|
chainout_saturate_aclr : string := "NONE";
|
|
chainout_saturate_pipeline_register : string := "UNREGISTERED";
|
|
chainout_saturate_pipeline_aclr : string := "NONE";
|
|
chainout_saturate_output_register : string := "UNREGISTERED";
|
|
chainout_saturate_output_aclr : string := "NONE";
|
|
|
|
-- chainout parameters
|
|
chainout_adder : string := "NO";
|
|
chainout_register : string := "UNREGISTERED";
|
|
chainout_aclr : string := "ACLR3";
|
|
width_chainin : integer := 1;
|
|
zero_chainout_output_register : string := "UNREGISTERED";
|
|
zero_chainout_output_aclr : string := "NONE";
|
|
|
|
-- rotate & shift parameters
|
|
shift_mode : string := "NO";
|
|
rotate_aclr : string := "NONE";
|
|
rotate_register : string := "UNREGISTERED";
|
|
rotate_pipeline_register : string := "UNREGISTERED";
|
|
rotate_pipeline_aclr : string := "NONE";
|
|
rotate_output_register : string := "UNREGISTERED";
|
|
rotate_output_aclr : string := "NONE";
|
|
shift_right_register : string := "UNREGISTERED";
|
|
shift_right_aclr : string := "NONE";
|
|
shift_right_pipeline_register : string := "UNREGISTERED";
|
|
shift_right_pipeline_aclr : string := "NONE";
|
|
shift_right_output_register : string := "UNREGISTERED";
|
|
shift_right_output_aclr : string := "NONE";
|
|
|
|
-- loopback parameters
|
|
zero_loopback_register : string := "UNREGISTERED";
|
|
zero_loopback_aclr : string := "NONE";
|
|
zero_loopback_pipeline_register : string := "UNREGISTERED";
|
|
zero_loopback_pipeline_aclr : string := "NONE";
|
|
zero_loopback_output_register : string := "UNREGISTERED";
|
|
zero_loopback_output_aclr : string := "NONE";
|
|
|
|
-- accumulator parameters
|
|
accum_sload_register : string := "UNREGISTERED";
|
|
accum_sload_aclr : string := "NONE";
|
|
accum_sload_pipeline_register : string := "UNREGISTERED";
|
|
accum_sload_pipeline_aclr : string := "NONE";
|
|
accum_direction : string := "ADD";
|
|
accumulator : string := "NO";
|
|
|
|
-- Stratix V parameters
|
|
width_c : integer := 22;
|
|
loadconst_value : integer := 64;
|
|
preadder_mode : string := "SIMPLE";
|
|
preadder_direction_0 : string := "ADD";
|
|
preadder_direction_1 : string := "ADD";
|
|
preadder_direction_2 : string := "ADD";
|
|
preadder_direction_3 : string := "ADD";
|
|
input_register_c0 : string := "CLOCK0";
|
|
input_aclr_c0 : string := "ACLR0";
|
|
coefsel0_register : string := "CLOCK0";
|
|
coefsel1_register : string := "CLOCK0";
|
|
coefsel2_register : string := "CLOCK0";
|
|
coefsel3_register : string := "CLOCK0";
|
|
coefsel0_aclr : string := "ACLR0";
|
|
coefsel1_aclr : string := "ACLR0";
|
|
coefsel2_aclr : string := "ACLR0";
|
|
coefsel3_aclr : string := "ACLR0";
|
|
systolic_delay1 : string := "UNREGISTERED";
|
|
systolic_delay3 : string := "UNREGISTERED";
|
|
systolic_aclr1 : string := "NONE";
|
|
systolic_aclr3 : string := "NONE";
|
|
coef0_0 : integer := 0;
|
|
coef0_1 : integer := 0;
|
|
coef0_2 : integer := 0;
|
|
coef0_3 : integer := 0;
|
|
coef0_4 : integer := 0;
|
|
coef0_5 : integer := 0;
|
|
coef0_6 : integer := 0;
|
|
coef0_7 : integer := 0;
|
|
coef1_0 : integer := 0;
|
|
coef1_1 : integer := 0;
|
|
coef1_2 : integer := 0;
|
|
coef1_3 : integer := 0;
|
|
coef1_4 : integer := 0;
|
|
coef1_5 : integer := 0;
|
|
coef1_6 : integer := 0;
|
|
coef1_7 : integer := 0;
|
|
coef2_0 : integer := 0;
|
|
coef2_1 : integer := 0;
|
|
coef2_2 : integer := 0;
|
|
coef2_3 : integer := 0;
|
|
coef2_4 : integer := 0;
|
|
coef2_5 : integer := 0;
|
|
coef2_6 : integer := 0;
|
|
coef2_7 : integer := 0;
|
|
coef3_0 : integer := 0;
|
|
coef3_1 : integer := 0;
|
|
coef3_2 : integer := 0;
|
|
coef3_3 : integer := 0;
|
|
coef3_4 : integer := 0;
|
|
coef3_5 : integer := 0;
|
|
coef3_6 : integer := 0;
|
|
coef3_7 : integer := 0;
|
|
width_coef : integer := 18;
|
|
|
|
-- General setting parameters
|
|
extra_latency : integer := 0;
|
|
dedicated_multiplier_circuitry : string := "AUTO";
|
|
dsp_block_balancing : string := "AUTO";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altmult_add";
|
|
intended_device_family : string := "Stratix"
|
|
);
|
|
|
|
port (
|
|
|
|
-- ----------------
|
|
-- PORT DECLARATION
|
|
-- ----------------
|
|
|
|
-- data input ports
|
|
dataa : in std_logic_vector(number_of_multipliers * width_a -1 downto 0);
|
|
datab : in std_logic_vector(number_of_multipliers * width_b -1 downto 0);
|
|
|
|
scanina : in std_logic_vector(width_a -1 downto 0) := (others => '0');
|
|
scaninb : in std_logic_vector(width_b -1 downto 0) := (others => '0');
|
|
|
|
sourcea : in std_logic_vector((number_of_multipliers -1) downto 0) := (others => '0');
|
|
sourceb : in std_logic_vector((number_of_multipliers -1) downto 0) := (others => '0');
|
|
|
|
-- clock ports
|
|
clock3 : in std_logic := '1';
|
|
clock2 : in std_logic := '1';
|
|
clock1 : in std_logic := '1';
|
|
clock0 : in std_logic := '1';
|
|
|
|
-- clear ports
|
|
aclr3 : in std_logic := '0';
|
|
aclr2 : in std_logic := '0';
|
|
aclr1 : in std_logic := '0';
|
|
aclr0 : in std_logic := '0';
|
|
|
|
-- clock enable signals
|
|
ena3 : in std_logic := '1';
|
|
ena2 : in std_logic := '1';
|
|
ena1 : in std_logic := '1';
|
|
ena0 : in std_logic := '1';
|
|
|
|
-- control signals
|
|
signa : in std_logic := 'Z';
|
|
signb : in std_logic := 'Z';
|
|
addnsub1 : in std_logic := 'Z';
|
|
addnsub3 : in std_logic := 'Z';
|
|
|
|
-- StratixII only input ports
|
|
mult01_round : in std_logic := '0';
|
|
mult23_round : in std_logic := '0';
|
|
mult01_saturation : in std_logic := '0';
|
|
mult23_saturation : in std_logic := '0';
|
|
addnsub1_round : in std_logic := '0';
|
|
addnsub3_round : in std_logic := '0';
|
|
|
|
-- Stratix III only input ports
|
|
output_round : in std_logic := '0';
|
|
chainout_round : in std_logic := '0';
|
|
output_saturate : in std_logic := '0';
|
|
chainout_saturate : in std_logic := '0';
|
|
chainin : in std_logic_vector (width_chainin - 1 downto 0) := (others => '0');
|
|
zero_chainout : in std_logic := '0';
|
|
rotate : in std_logic := '0';
|
|
shift_right : in std_logic := '0';
|
|
zero_loopback : in std_logic := '0';
|
|
accum_sload : in std_logic := '0';
|
|
|
|
-- Stratix V only input ports
|
|
coefsel0 : in std_logic_vector (2 downto 0) := (others => '0');
|
|
coefsel1 : in std_logic_vector (2 downto 0) := (others => '0');
|
|
coefsel2 : in std_logic_vector (2 downto 0) := (others => '0');
|
|
coefsel3 : in std_logic_vector (2 downto 0) := (others => '0');
|
|
datac : in std_logic_vector (number_of_multipliers * width_c -1 downto 0) := (others => '0');
|
|
|
|
|
|
-- output ports
|
|
result : out std_logic_vector(width_result -1 downto 0) := (others => '0');
|
|
scanouta : out std_logic_vector (width_a -1 downto 0) := (others => '0');
|
|
scanoutb : out std_logic_vector (width_b -1 downto 0) := (others => '0');
|
|
|
|
-- StratixII only output ports
|
|
mult0_is_saturated : out std_logic := '0';
|
|
mult1_is_saturated : out std_logic := '0';
|
|
mult2_is_saturated : out std_logic := '0';
|
|
mult3_is_saturated : out std_logic := '0';
|
|
|
|
-- Stratix III only output ports
|
|
overflow : out std_logic := '0';
|
|
chainout_sat_overflow : out std_logic := '0'
|
|
|
|
);
|
|
|
|
end altmult_add;
|
|
|
|
architecture behaviour of altmult_add is
|
|
|
|
-- ---------------------------
|
|
-- SIGNAL AND TYPE DECLARATION
|
|
-- ---------------------------
|
|
|
|
function resolve_internal_width (ARG : integer;ARG2 : integer) return integer is
|
|
variable changed_width:integer := 0;
|
|
begin
|
|
if (multiplier01_saturation = "NO" and multiplier23_saturation = "NO" and multiplier01_rounding = "NO" and multiplier23_rounding = "NO"
|
|
and output_saturation = "NO" and output_rounding = "NO" and chainout_adder = "NO" and input_source_b0 /= "LOOPBACK" ) then
|
|
if (ARG2 = 0) then
|
|
changed_width := width_a;
|
|
else
|
|
changed_width := width_b;
|
|
end if;
|
|
else
|
|
if (ARG < 18) then
|
|
changed_width := 18;
|
|
else
|
|
if (ARG2 = 0) then
|
|
changed_width := width_a;
|
|
else
|
|
changed_width := width_b;
|
|
end if;
|
|
end if;
|
|
|
|
end if;
|
|
return changed_width;
|
|
end resolve_internal_width;
|
|
-- This constant int_width_a would be used internally in this model
|
|
-- to represent width_a
|
|
constant int_width_a : natural := resolve_internal_width(width_a, 0);
|
|
-- This constant int_width_b woudl be used internally in this model
|
|
-- to represent width_b
|
|
constant int_width_b : natural := resolve_internal_width(width_b, 1);
|
|
|
|
function resolve_internal_mult_diff return integer is
|
|
variable changed_value :integer := 0;
|
|
begin
|
|
if (multiplier01_saturation = "NO" and multiplier23_saturation = "NO" and multiplier01_rounding = "NO" and multiplier23_rounding = "NO"
|
|
and output_rounding = "NO" and output_saturation = "NO" and chainout_adder = "NO") then
|
|
changed_value := 0;
|
|
else
|
|
if (chainout_adder = "YES") then
|
|
if (width_result > width_a + width_b + 8) then
|
|
changed_value := 0;
|
|
else
|
|
changed_value := int_width_a - width_a + int_width_b - width_b;
|
|
end if;
|
|
else
|
|
changed_value := int_width_a - width_a + int_width_b - width_b;
|
|
end if;
|
|
end if;
|
|
return changed_value;
|
|
end resolve_internal_mult_diff;
|
|
|
|
constant int_mult_diff_bit : integer := resolve_internal_mult_diff;
|
|
|
|
function resolve_internal_width_result return integer is
|
|
variable changed_width_result:integer := 0;
|
|
begin
|
|
if (multiplier01_saturation = "NO" and multiplier23_saturation = "NO" and multiplier01_rounding = "NO" and multiplier23_rounding = "NO"
|
|
and output_rounding = "NO" and output_saturation = "NO" and chainout_rounding = "NO" and chainout_saturation = "NO" and chainout_adder = "NO" and shift_mode = "NO") then
|
|
changed_width_result := width_result;
|
|
else
|
|
if (shift_mode /= "NO") then
|
|
changed_width_result := 64;
|
|
elsif (chainout_adder = "YES") then
|
|
changed_width_result := 44;
|
|
elsif (width_result > (int_width_a + int_width_b)) then
|
|
changed_width_result := width_result + (width_result - int_width_a - int_width_b);
|
|
else
|
|
changed_width_result := int_width_a + int_width_b;
|
|
end if;
|
|
end if;
|
|
return changed_width_result;
|
|
end resolve_internal_width_result;
|
|
|
|
constant int_width_result : natural := resolve_internal_width_result;
|
|
|
|
function resolve_result_width return integer is
|
|
variable width_value :integer := 0;
|
|
begin
|
|
width_value := 44;
|
|
return width_value;
|
|
end resolve_result_width;
|
|
|
|
constant result_width : integer := resolve_result_width;
|
|
|
|
function resolve_saturation_position return integer is
|
|
variable saturation_value :integer := 0;
|
|
begin
|
|
if (output_saturation /= "NO" and chainout_saturation = "NO") then
|
|
if (((width_a + width_b )> width_result) and (width_result >= width_saturate_sign)) then
|
|
saturation_value := (int_width_a + int_width_b - width_saturate_sign - (width_a + width_b - width_result));
|
|
elsif (((width_a + width_b) = width_result) and (width_result >= width_saturate_sign)) then
|
|
saturation_value:= (int_width_a + int_width_b - width_saturate_sign);
|
|
elsif (width_result >= width_saturate_sign) then
|
|
saturation_value := (int_width_a + int_width_b - width_saturate_sign + (width_result - width_saturate_sign) + (width_saturate_sign - width_a - width_b));
|
|
end if;
|
|
elsif (chainout_saturation /= "NO") then
|
|
if ((width_result >= int_width_result) and (width_result > width_saturate_sign)) then
|
|
saturation_value := width_result - width_saturate_sign;
|
|
elsif (width_result > width_saturate_sign) then
|
|
saturation_value := width_result + int_mult_diff_bit - width_saturate_sign;
|
|
end if;
|
|
else
|
|
saturation_value:= 2;
|
|
end if;
|
|
return saturation_value;
|
|
end resolve_saturation_position;
|
|
|
|
constant saturation_position : natural := resolve_saturation_position;
|
|
|
|
function resolve_chainout_saturation_position return integer is
|
|
variable saturation_value :integer := 0;
|
|
begin
|
|
if (chainout_saturation /= "NO") then
|
|
if ((width_result >= int_width_result) and (width_result > width_saturate_sign)) then
|
|
saturation_value := width_result - width_saturate_sign;
|
|
elsif (width_result > width_saturate_sign) then
|
|
saturation_value := width_result + int_mult_diff_bit - width_saturate_sign;
|
|
end if;
|
|
else
|
|
saturation_value := 2;
|
|
end if;
|
|
|
|
if (saturation_value < 0) then
|
|
saturation_value:= 2;
|
|
elsif (saturation_value > int_width_result) then
|
|
saturation_value:= (int_width_a + int_width_b - width_saturate_sign);
|
|
end if;
|
|
return saturation_value;
|
|
end resolve_chainout_saturation_position;
|
|
|
|
constant chainout_saturation_position : natural := resolve_chainout_saturation_position;
|
|
|
|
function resolve_round_position return integer is
|
|
variable round_value :integer := 2;
|
|
begin
|
|
if (output_rounding /= "NO" or output_saturate_type = "SYMMETRIC") then
|
|
if (input_source_b0 = "LOOPBACK") then
|
|
round_value := 18;
|
|
elsif (((width_a + width_b )> width_result) and (width_msb < width_result)) then
|
|
round_value := (int_width_a + int_width_b - width_msb - (width_a + width_b - width_result));
|
|
elsif (((width_a + width_b) = width_result) and (width_msb < width_result)) then
|
|
round_value:= (int_width_a + int_width_b - width_msb);
|
|
elsif (width_msb < width_result) then
|
|
round_value := (int_width_a + int_width_b - width_msb + (width_result - width_a - width_b));
|
|
end if;
|
|
else
|
|
round_value := 2;
|
|
end if;
|
|
|
|
if (output_rounding /= "NO" or output_saturate_type = "SYMMETRIC") then
|
|
if (round_value < 0) then
|
|
round_value := 2;
|
|
elsif (round_value > int_width_result) then
|
|
round_value := int_width_result - width_msb;
|
|
end if;
|
|
end if;
|
|
return round_value;
|
|
end resolve_round_position;
|
|
|
|
constant round_position : natural := resolve_round_position;
|
|
|
|
function resolve_chainout_round_position return integer is
|
|
variable round_value :integer := 2;
|
|
begin
|
|
if (chainout_rounding /= "NO" or output_saturate_type = "SYMMETRIC") then
|
|
if ((width_result >= int_width_result) and (width_msb < width_result)) then
|
|
round_value := width_result - width_msb;
|
|
elsif (width_msb < width_result) then
|
|
round_value := width_result + int_mult_diff_bit - width_msb;
|
|
end if;
|
|
else
|
|
round_value := 2;
|
|
end if;
|
|
|
|
if (chainout_rounding /= "NO" or output_saturate_type = "SYMMETRIC") then
|
|
if (round_value < 0) then
|
|
round_value := 2;
|
|
elsif (round_value > int_width_result) then
|
|
round_value := int_width_result - width_msb;
|
|
end if;
|
|
end if;
|
|
return round_value;
|
|
end resolve_chainout_round_position;
|
|
|
|
constant chainout_round_position : natural := resolve_chainout_round_position;
|
|
|
|
function resolve_chainout_input_a return integer is
|
|
variable input_a_value :integer := 0;
|
|
begin
|
|
if (chainout_adder = "YES") then
|
|
if (width_a < 18) then
|
|
input_a_value := 18 - width_a;
|
|
else
|
|
input_a_value := 1;
|
|
end if;
|
|
end if;
|
|
return input_a_value;
|
|
end resolve_chainout_input_a;
|
|
|
|
constant chainout_input_a : natural := resolve_chainout_input_a;
|
|
|
|
function resolve_chainout_input_b return integer is
|
|
variable input_b_value :integer := 0;
|
|
begin
|
|
if (chainout_adder = "YES") then
|
|
if (width_b < 18) then
|
|
input_b_value := 18 - width_b;
|
|
else
|
|
input_b_value := 1;
|
|
end if;
|
|
end if;
|
|
return input_b_value;
|
|
end resolve_chainout_input_b;
|
|
|
|
constant chainout_input_b : natural := resolve_chainout_input_b;
|
|
|
|
function resolve_accum_width return integer is
|
|
variable accum_value :integer := 0;
|
|
begin
|
|
if((int_width_a + int_width_b) < 44) then
|
|
accum_value := 44;
|
|
else
|
|
accum_value := int_width_a + int_width_b;
|
|
end if;
|
|
return accum_value;
|
|
end resolve_accum_width;
|
|
|
|
constant accum_width : natural := resolve_accum_width;
|
|
|
|
function resolve_loopback_width return integer is
|
|
variable loopback_value :integer := 0;
|
|
begin
|
|
loopback_value := 17;
|
|
return loopback_value;
|
|
end resolve_loopback_width;
|
|
|
|
constant loopback_width : natural := resolve_loopback_width;
|
|
|
|
function resolve_lsb_position return integer is
|
|
variable lsb_position_value :integer := 0;
|
|
begin
|
|
lsb_position_value := 36 - width_a - width_b;
|
|
|
|
if(lsb_position_value < 0) then
|
|
lsb_position_value := 0;
|
|
end if;
|
|
return lsb_position_value;
|
|
end resolve_lsb_position;
|
|
|
|
constant lsb_position : natural := resolve_lsb_position;
|
|
|
|
function resolve_extra_sign_bit_width return integer is
|
|
variable extra_sign_bit_width_value :integer :=0;
|
|
begin
|
|
if(port_signa = "PORT_USED" or port_signb = "PORT_USED") then
|
|
extra_sign_bit_width_value := accum_width - width_result - lsb_position;
|
|
elsif(representation_a = "UNSIGNED" and representation_b = "UNSIGNED") then
|
|
extra_sign_bit_width_value := accum_width - width_result - lsb_position;
|
|
else
|
|
extra_sign_bit_width_value := accum_width - width_result + 1 - lsb_position;
|
|
end if;
|
|
|
|
if(extra_sign_bit_width_value < 0) then
|
|
extra_sign_bit_width_value := 0;
|
|
end if;
|
|
|
|
return extra_sign_bit_width_value;
|
|
|
|
end resolve_extra_sign_bit_width;
|
|
|
|
constant extra_sign_bit_width : natural := resolve_extra_sign_bit_width;
|
|
|
|
function resolve_bit_position return integer is
|
|
variable bit_position_value :integer := 0;
|
|
begin
|
|
bit_position_value := accum_width - lsb_position - extra_sign_bit_width - 1;
|
|
|
|
return bit_position_value;
|
|
end resolve_bit_position;
|
|
|
|
constant bit_position : natural := resolve_bit_position;
|
|
type pipeline_accum is array (extra_latency downto 0) of std_logic_vector (width_result - 1 downto 0);
|
|
|
|
signal mult_a : std_logic_vector ((4 * int_width_a) -1 downto 0) := (others => '0');
|
|
signal mult_b : std_logic_vector ((4 * int_width_b) -1 downto 0) := (others => '0');
|
|
signal mult_res : std_logic_vector ((number_of_multipliers * (int_width_a + int_width_b)) + number_of_multipliers downto 0) := (others => '0');
|
|
signal tmp_mult_a : std_logic_vector ((4 * int_width_a) -1 downto 0) := (others => '0');
|
|
signal tmp_mult_b : std_logic_vector ((4 * int_width_b) -1 downto 0) := (others => '0');
|
|
|
|
signal sign_a_reg : std_logic := '0';
|
|
signal sign_a_pipe : std_logic := '0';
|
|
signal sign_b_reg : std_logic := '0';
|
|
signal sign_b_pipe : std_logic := '0';
|
|
signal addsub_reg1 : std_logic := '0';
|
|
signal addsub_pipe1 : std_logic := '0';
|
|
signal addsub_reg3 : std_logic := '0';
|
|
signal addsub_pipe3 : std_logic := '0';
|
|
|
|
signal mult_clock : std_logic_vector (3 downto 0) := (others => '0');
|
|
signal mult_ena : std_logic_vector (3 downto 0) := (others => '0');
|
|
signal mult_aclr : std_logic_vector (3 downto 0) := (others => '0');
|
|
|
|
signal clock_vector : std_logic_vector (3 downto 0) := (others => '0');
|
|
signal ena_vector : std_logic_vector (3 downto 0) := (others => '0');
|
|
signal aclr_vector : std_logic_vector (3 downto 0) := (others => '0');
|
|
|
|
signal dataa_int : std_logic_vector (4 * int_width_a -1 downto 0) := (others => '0');
|
|
signal dataa_int1 : std_logic_vector (int_width_a -1 downto 0) := (others => '0');
|
|
signal dataa_int2 : std_logic_vector (int_width_a -1 downto 0) := (others => '0');
|
|
signal dataa_int3 : std_logic_vector (int_width_a -1 downto 0) := (others => '0');
|
|
signal dataa_int4 : std_logic_vector (int_width_a -1 downto 0) := (others => '0');
|
|
signal datab_int : std_logic_vector (4 * int_width_b -1 downto 0) := (others => '0');
|
|
signal datab_int1 : std_logic_vector (int_width_b -1 downto 0) := (others => '0');
|
|
signal datab_int2 : std_logic_vector (int_width_b -1 downto 0) := (others => '0');
|
|
signal datab_int3 : std_logic_vector (int_width_b -1 downto 0) := (others => '0');
|
|
signal datab_int4 : std_logic_vector (int_width_b -1 downto 0) := (others => '0');
|
|
signal is_reg : std_logic_vector (3 downto 0) := (others => '0');
|
|
signal temp_mult_zero : std_logic_vector ((int_width_a + int_width_b) -1 downto 0) := (others => '0');
|
|
|
|
signal head_result : natural := 0;
|
|
signal head_result_siii : natural := 0;
|
|
|
|
signal head_overflow : natural := 0;
|
|
|
|
signal mult01_round_wire : std_logic := '0';
|
|
signal mult01_saturate_wire : std_logic := '0';
|
|
signal mult23_round_wire : std_logic := '0';
|
|
signal mult23_saturate_wire : std_logic := '0';
|
|
signal mult_is_saturated : std_logic_vector ((number_of_multipliers - 1) downto 0) := (others => '0');
|
|
signal mult_is_saturated_pipe : std_logic_vector ((number_of_multipliers - 1) downto 0) := (others => '0');
|
|
|
|
signal sourcea_wire : std_logic_vector (3 downto 0) := (others => '0');
|
|
signal sourceb_wire : std_logic_vector (3 downto 0) := (others => '0');
|
|
|
|
|
|
signal addnsub1_round_wire : std_logic := '0';
|
|
signal addnsub1_round_pipe_wire : std_logic := '0';
|
|
signal addnsub3_round_wire : std_logic := '0';
|
|
signal addnsub3_round_pipe_wire : std_logic := '0';
|
|
|
|
signal outround_reg : std_logic := '0';
|
|
signal outround_pipe : std_logic := '0';
|
|
signal chainout_round_reg : std_logic := '0';
|
|
signal chainout_round_pipe : std_logic := '0';
|
|
signal chainout_round_out_reg : std_logic := '0';
|
|
signal outsat_reg : std_logic := '0';
|
|
signal outsat_pipe : std_logic := '0';
|
|
signal chainout_sat_reg : std_logic := '0';
|
|
signal chainout_sat_pipe : std_logic := '0';
|
|
signal chainout_sat_out : std_logic := '0';
|
|
signal scanouta_reg : std_logic_vector (width_a - 1 downto 0) := (others => '0');
|
|
signal zerochainout_reg : std_logic := '0';
|
|
signal rotate_reg : std_logic := '0';
|
|
signal rotate_pipe : std_logic := '0';
|
|
signal rotate_out : std_logic := '0';
|
|
signal shiftr_reg : std_logic := '0';
|
|
signal shiftr_pipe : std_logic := '0';
|
|
signal shiftr_out : std_logic := '0';
|
|
signal zeroloopback_reg : std_logic := '0';
|
|
signal zeroloopback_pipe : std_logic := '0';
|
|
signal zeroloopback_out : std_logic := '0';
|
|
signal accumsload_reg : std_logic := '0';
|
|
signal accumsload_pipe : std_logic := '0';
|
|
signal acc_feedback : std_logic_vector (int_width_result + int_width_a + int_width_b downto 0) := (others => '0');
|
|
signal loopback_wire : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
signal shift_rot_result : std_logic_vector ((int_width_result/2) - 1 downto 0) := (others => '0');
|
|
signal chainout_output : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
signal output_result : std_logic_vector (int_width_result + int_width_a + int_width_b downto 0) := (others => '0');
|
|
signal overflow_int : std_logic := '0';
|
|
signal chainout_overflow_int : std_logic := '0';
|
|
signal adder1_reg : std_logic_vector (int_width_result + int_width_a + int_width_b downto 0) := (others => '0');
|
|
signal adder3_reg : std_logic_vector (int_width_result + int_width_a + int_width_b downto 0) := (others => '0');
|
|
signal chainout_sat_block_res_wire : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
signal acc_feedback_temp : std_logic_vector (accum_width downto 0) := (others => '0');
|
|
signal accum_res : std_logic_vector (accum_width downto 0) := (others => '0');
|
|
signal feedback : std_logic_vector (loopback_width downto 0) := (others => '0');
|
|
signal unsigned_sub1_overflow_reg : std_logic := '0';
|
|
signal unsigned_sub3_overflow_reg : std_logic := '0';
|
|
signal unsigned_sub1_overflow_mult_reg : std_logic := '0';
|
|
signal unsigned_sub3_overflow_mult_reg : std_logic := '0';
|
|
|
|
constant stratixii_block : boolean := FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or (FEATURE_FAMILY_STRATIXIII(intended_device_family) and (dedicated_multiplier_circuitry = "NO"));
|
|
constant stratixiii_block : boolean := FEATURE_FAMILY_STRATIXIII(intended_device_family) and (dedicated_multiplier_circuitry /= "NO");
|
|
constant stratixv_block : boolean := FEATURE_FAMILY_STRATIXV(intended_device_family);
|
|
constant altera_mult_add_block : boolean := FEATURE_FAMILY_HAS_ALTERA_MULT_ADD_FLOW(intended_device_family);
|
|
constant altmult_add_eol_block : boolean := FEATURE_FAMILY_IS_ALTMULT_ADD_EOL(intended_device_family);
|
|
|
|
-- -------------------------------------------------------------------
|
|
-- This function takes in a string that describes the clock name
|
|
-- and returns the correct number that corresponds to that particular
|
|
-- clock signal
|
|
-- -------------------------------------------------------------------
|
|
function resolve_clock (ARG : string) return integer is
|
|
variable clock_num:integer := 0;
|
|
begin
|
|
if (ARG = "CLOCK0") then
|
|
clock_num := 0;
|
|
elsif ARG = "CLOCK1" then
|
|
clock_num := 1;
|
|
elsif ARG = "CLOCK2" then
|
|
clock_num := 2;
|
|
elsif ARG = "CLOCK3" then
|
|
clock_num := 3;
|
|
end if;
|
|
|
|
return clock_num;
|
|
end resolve_clock;
|
|
|
|
|
|
-- -------------------------------------------------------------------
|
|
-- This function takes in a string that describes the clear name
|
|
-- and returns the correct number that corresponds to that particular
|
|
-- clear signal
|
|
-- -------------------------------------------------------------------
|
|
function resolve_aclr (ARG : string) return integer is
|
|
variable aclr_num:integer := 0;
|
|
begin
|
|
if (ARG = "ACLR0") then
|
|
aclr_num := 0;
|
|
elsif ARG = "ACLR1" then
|
|
aclr_num := 1;
|
|
elsif ARG = "ACLR2" then
|
|
aclr_num := 2;
|
|
elsif ARG = "ACLR3" then
|
|
aclr_num := 3;
|
|
end if;
|
|
|
|
return aclr_num;
|
|
end resolve_aclr;
|
|
|
|
|
|
-- -------------------------------------------------------------------
|
|
-- This function takes in a integer that describes the particular
|
|
-- clock signal returns the correct string
|
|
-- -------------------------------------------------------------------
|
|
function check_clock (arg: integer) return string is
|
|
variable ret_val:string (1 to 6);
|
|
begin
|
|
if (arg = 0) then
|
|
ret_val := multiplier_register0 (1 to 6);
|
|
elsif arg =1 then
|
|
ret_val := multiplier_register1 (1 to 6);
|
|
elsif arg=2 then
|
|
ret_val := multiplier_register2 (1 to 6);
|
|
elsif arg=3 then
|
|
ret_val := multiplier_register3 (1 to 6);
|
|
else
|
|
ret_val := "CLOCK0";
|
|
end if;
|
|
|
|
return ret_val;
|
|
end check_clock;
|
|
|
|
|
|
begin
|
|
|
|
process(mult_b)
|
|
begin
|
|
if (altera_mult_add_block) then
|
|
scanoutb <= (others => 'Z');
|
|
elsif (chainout_adder = "YES" and (width_result > width_a + width_b + 8)) then
|
|
scanoutb <= mult_b((number_of_multipliers * int_width_b) - 1 - (int_width_b - width_b) downto ((number_of_multipliers-1) * int_width_b));
|
|
else
|
|
scanoutb <= mult_b ((number_of_multipliers * int_width_b) -1 downto ((number_of_multipliers -1 ) * int_width_b) + int_width_b - width_b);
|
|
end if;
|
|
end process;
|
|
|
|
clock_vector (0) <= clock0;
|
|
clock_vector (1) <= clock1;
|
|
clock_vector (2) <= clock2;
|
|
clock_vector (3) <= clock3;
|
|
|
|
ena_vector (0) <= ena0;
|
|
ena_vector (1) <= ena1;
|
|
ena_vector (2) <= ena2;
|
|
ena_vector (3) <= ena3;
|
|
|
|
aclr_vector (0) <= aclr0;
|
|
aclr_vector (1) <= aclr1;
|
|
aclr_vector (2) <= aclr2;
|
|
aclr_vector (3) <= aclr3;
|
|
|
|
sourcea_wire ( number_of_multipliers - 1 downto 0) <= sourcea (number_of_multipliers -1 downto 0);
|
|
sourceb_wire ( number_of_multipliers - 1 downto 0) <= sourceb (number_of_multipliers - 1 downto 0);
|
|
|
|
tmp_mult_a <= mult_a;
|
|
tmp_mult_b <= mult_b;
|
|
|
|
-- Parameter Checking
|
|
process
|
|
begin
|
|
|
|
-- Legality check, family from Night Fury and moving forwards is officially EOL
|
|
if (altmult_add_eol_block) then
|
|
assert false
|
|
report "ALTMULT_ADD is EOL for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
|
|
-- Legality check, block new family from running pre_layout simulation using altera_mf (family with altera_mult_add flow)
|
|
if (altera_mult_add_block) then
|
|
if(accumulator /= "NO") then
|
|
assert false
|
|
report "Accumulator mode is not supported in altera_mf for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
if (port_addnsub1 /= "PORT_UNUSED" or port_addnsub3 /= "PORT_UNUSED") then
|
|
assert false
|
|
report "Dynamic adder is not supported in altera_mf for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
if (chainout_adder /= "NO") then
|
|
assert false
|
|
report "Chain adder is not supported in altera_mf for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
if (systolic_delay1 /= "UNREGISTERED" or systolic_delay3 /= "UNREGISTERED") then
|
|
assert false
|
|
report "Systolic mode is not supported in altera_mf for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
if (input_source_a0 /= "DATAA" or input_source_a1 /= "DATAA" or input_source_a2 /= "DATAA" or input_source_a3 /= "DATAA") then
|
|
assert false
|
|
report "The INPUT_SOURCE_A parameter is set to an unsupported value. Only DATAA input is supported in altera_mf for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
if (input_source_b0 /= "DATAB" or input_source_b1 /= "DATAB" or input_source_b2 /= "DATAB" or input_source_b3 /= "DATAB") then
|
|
assert false
|
|
report "The INPUT_SOURCE_B parameter is set to an unsupported value. Only DATAB input is supported in altera_mf for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
if (preadder_mode /= "SIMPLE") then
|
|
assert false
|
|
report "The PREADDER_MODE parameter is set to an unsupported value. Only SIMPLE mode is supported in altera_mf for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
if (output_rounding /= "NO" or chainout_rounding /= "NO" or
|
|
adder1_rounding /= "NO" or adder3_rounding /= "NO" or
|
|
multiplier01_rounding /= "NO" or multiplier23_rounding /= "NO") then
|
|
assert false
|
|
report "Rounding is not supported in altera_mf for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
if (output_saturation /= "NO" or chainout_saturation /= "NO" or
|
|
port_mult0_is_saturated /= "UNUSED" or port_mult1_is_saturated /= "UNUSED" or port_mult2_is_saturated /= "UNUSED" or port_mult3_is_saturated /= "UNUSED" or
|
|
multiplier01_saturation /= "NO" or multiplier23_saturation /= "NO" or
|
|
port_output_is_overflow /= "PORT_UNUSED") then
|
|
assert false
|
|
report "Saturation is not supported in altera_mf for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
if (shift_mode /= "NO") then
|
|
assert false
|
|
report "Shift is not supported in altera_mf for "& intended_device_family &" device family"
|
|
severity failure;
|
|
end if;
|
|
if (signed_pipeline_register_a /= "UNREGISTERED" or signed_pipeline_register_b /= "UNREGISTERED" or
|
|
addnsub_multiplier_pipeline_register1 /= "UNREGISTERED" or addnsub_multiplier_pipeline_register3 /= "UNREGISTERED" or
|
|
accum_sload_pipeline_register /= "UNREGISTERED") then
|
|
assert false
|
|
report "Pipeline register is not supported in altera_mf for "& intended_device_family &" device family"
|
|
severity warning;
|
|
end if;
|
|
end if;
|
|
|
|
-- Checking for invalid parameters, in case Wizard is bypassed (hand-modified).
|
|
if (number_of_multipliers > 4) then
|
|
assert false
|
|
report "Altmult_add does not currently support NUMBER_OF_MULTIPLIERS > 4"
|
|
severity error;
|
|
end if;
|
|
|
|
if (number_of_multipliers <= 0) then
|
|
assert false
|
|
report "NUMBER_OF_MULTIPLIERS must be greater than 0."
|
|
severity error;
|
|
end if;
|
|
|
|
if (width_a <= 0) then
|
|
assert false
|
|
report "Error: width_a must be greater than 0."
|
|
severity error;
|
|
end if;
|
|
|
|
if (width_b <= 0) then
|
|
assert false
|
|
report "Error: width_b must be greater than 0."
|
|
severity error;
|
|
end if;
|
|
|
|
if (width_result <= 0) then
|
|
assert false
|
|
report "Error: width_result must be greater than 0."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((dedicated_multiplier_circuitry /= "AUTO") and
|
|
(dedicated_multiplier_circuitry /= "YES") and
|
|
(dedicated_multiplier_circuitry /= "NO")) then
|
|
assert false
|
|
report "Error: The DEDICATED_MULTIPLIER_CIRCUITRY parameter is set to an illegal value."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((input_source_a0 /= "DATAA") and
|
|
(input_source_a0 /= "SCANA") and
|
|
(input_source_a0 /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The INPUT_SOURCE_A0 parameter is set to an illegal value."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((input_source_a1 /= "DATAA") and
|
|
(input_source_a1 /= "SCANA") and
|
|
(input_source_a1 /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The INPUT_SOURCE_A1 parameter is set to an illegal value."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((input_source_a2 /= "DATAA") and
|
|
(input_source_a2 /= "SCANA") and
|
|
(input_source_a2 /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The INPUT_SOURCE_A2 parameter is set to an illegal value."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((input_source_a3 /= "DATAA") and
|
|
(input_source_a3 /= "SCANA") and
|
|
(input_source_a3 /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The INPUT_SOURCE_A3 parameter is set to an illegal value."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((input_source_b0 /= "DATAB") and
|
|
(input_source_b0 /= "SCANB") and
|
|
(input_source_b0 /= "VARIABLE") and
|
|
(input_source_b0 /= "LOOPBACK")) then
|
|
assert false
|
|
report "Error: The INPUT_SOURCE_B0 parameter is set to an illegal value."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((input_source_b1 /= "DATAB") and
|
|
(input_source_b1 /= "SCANB") and
|
|
(input_source_b1 /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The INPUT_SOURCE_B1 parameter is set to an illegal value."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((input_source_b2 /= "DATAB") and
|
|
(input_source_b2 /= "SCANB") and
|
|
(input_source_b2 /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The INPUT_SOURCE_B2 parameter is set to an illegal value."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((input_source_b3 /= "DATAB") and
|
|
(input_source_b3 /= "SCANB") and
|
|
(input_source_b3 /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The INPUT_SOURCE_B3 parameter is set to an illegal value."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
|
|
(input_source_a0 = "VARIABLE")) then
|
|
assert false
|
|
report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
|
|
(input_source_a1 = "VARIABLE")) then
|
|
assert false
|
|
report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
|
|
(input_source_a2 = "VARIABLE")) then
|
|
assert false
|
|
report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
|
|
(input_source_a3 = "VARIABLE")) then
|
|
assert false
|
|
report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
|
|
(input_source_b0 = "VARIABLE")) then
|
|
assert false
|
|
report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
|
|
(input_source_b1 = "VARIABLE")) then
|
|
assert false
|
|
report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
|
|
(input_source_b2 = "VARIABLE")) then
|
|
assert false
|
|
report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
|
|
(input_source_b3 = "VARIABLE")) then
|
|
assert false
|
|
report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and
|
|
((multiplier01_rounding = "YES") or (multiplier01_rounding = "VARIABLE") or
|
|
(multiplier23_rounding = "YES") or (multiplier23_rounding = "VARIABLE"))) then
|
|
assert false
|
|
report "Error: Rounding for multiplier is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and
|
|
((multiplier01_saturation = "YES") or (multiplier01_saturation = "VARIABLE") or
|
|
(multiplier23_saturation = "YES") or (multiplier23_saturation = "VARIABLE"))) then
|
|
assert false
|
|
report "Error: Saturation for multiplier is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and
|
|
((adder1_rounding = "YES") or (adder1_rounding = "VARIABLE") or
|
|
(adder3_rounding = "YES") or (adder3_rounding = "VARIABLE"))) then
|
|
assert false
|
|
report "Error: Rounding for adder is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((multiplier01_saturation = "NO") and (multiplier23_saturation = "NO")
|
|
and (multiplier01_rounding = "NO") and (multiplier23_rounding = "NO") and
|
|
(output_rounding = "NO") and (output_saturation = "NO") and (shift_mode ="NO") and (chainout_adder = "NO")) then
|
|
if (int_width_result /= width_result) then
|
|
assert false
|
|
report "Error: Internal parameter setting of int_width_result is illegal"
|
|
severity error;
|
|
end if;
|
|
|
|
if (int_mult_diff_bit /= 0) then
|
|
assert false
|
|
report "Error: Internal parameter setting of int_mult_diff_bit is illegal"
|
|
severity error;
|
|
end if;
|
|
else
|
|
if (((width_a < 18) and (int_width_a /= 18)) or
|
|
((width_a >= 18) and (int_width_a /= width_a))) then
|
|
assert false
|
|
report "Error: Internal parameter setting of int_width_a is illegal"
|
|
severity error;
|
|
end if;
|
|
|
|
if (((width_b < 18) and (int_width_b /= 18)) or
|
|
((width_b >= 18) and (int_width_b /= width_b))) then
|
|
assert false
|
|
report "Error: Internal parameter setting of int_width_b is illegal"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((chainout_adder = "NO") and (shift_mode = "NO")) then
|
|
if ((int_width_result > (int_width_a + int_width_b))) then
|
|
if (int_width_result /= (width_result + width_result - int_width_a - int_width_b)) then
|
|
assert false
|
|
report "Error: Internal parameter setting of int_width_result is illegal"
|
|
severity error;
|
|
end if;
|
|
elsif ((int_width_result /= (int_width_a + int_width_b))) then
|
|
assert false
|
|
report "Error: Internal parameter setting of int_width_result is illegal"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((int_mult_diff_bit /= (int_width_a - width_a + int_width_b - width_b))) then
|
|
assert false
|
|
report "Error: Internal parameter setting of int_mult_diff_bit is illegal"
|
|
severity error;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- Stratix III parameter checking
|
|
if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and ((output_rounding = "YES") or
|
|
(output_rounding = "VARIABLE") or (chainout_rounding = "YES") or (chainout_rounding = "VARIABLE"))) then
|
|
assert false
|
|
report "Error: Output rounding and/or Chainout rounding are not supported for "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and ((output_saturation = "YES") or
|
|
(output_saturation = "VARIABLE") or (chainout_saturation = "YES") or (chainout_saturation = "VARIABLE"))) then
|
|
assert false
|
|
report "Error: Output saturation and/or Chainout saturation are not supported for "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (input_source_b0 = "LOOPBACK")) then
|
|
assert false
|
|
report "Error: Loopback mode is not supported for "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (chainout_adder = "YES")) then
|
|
assert false
|
|
report "Error: Chainout mode is not supported for "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (shift_mode /= "NO")) then
|
|
assert false
|
|
report "Error: shift and rotate modes are not supported for "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (accumulator = "YES")) then
|
|
assert false
|
|
report "Error: Accumulator mode is not supported for "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((output_rounding /= "YES") and (output_rounding /= "NO") and (output_rounding /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The OUTPUT_ROUNDING parameter is set to an invalid value"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((chainout_rounding /= "YES") and (chainout_rounding /= "NO") and (chainout_rounding /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The CHAINOUT_ROUNDING parameter is set to an invalid value"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((output_saturation /= "YES") and (output_saturation /= "NO") and (output_saturation /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The OUTPUT_SATURATION parameter is set to an invalid value"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((chainout_saturation /= "YES") and (chainout_saturation /= "NO") and (chainout_saturation /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The CHAINOUT_SATURATION parameter is set to an invalid value"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((output_rounding /= "NO") and ((output_round_type /= "NEAREST_INTEGER") and (output_round_type /= "NEAREST_EVEN"))) then
|
|
assert false
|
|
report "Error: The OUTPUT_ROUND_TYPE parameter is set to an invalid value"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((output_saturation /= "NO") and ((output_saturate_type /= "ASYMMETRIC") and (output_saturate_type /= "SYMMETRIC"))) then
|
|
assert false
|
|
report "Error: The OUTPUT_SATURATE_TYPE parameter is set to an invalid value"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((shift_mode /= "NO") and (shift_mode /= "LEFT") and (shift_mode /= "RIGHT") and (shift_mode /= "ROTATION") and
|
|
(shift_mode /= "VARIABLE")) then
|
|
assert false
|
|
report "Error: The SHIFT_MODE parameter is set to an inavlid value"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((accumulator = "YES") and (accum_direction /= "ADD") and (accum_direction /= "SUB")) then
|
|
assert false
|
|
report "Error: The ACCUM_DIRECTION parameter is set to an invalid value"
|
|
severity error;
|
|
end if;
|
|
|
|
if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
|
|
if ((output_rounding = "YES") and (accumulator = "YES")) then
|
|
assert false
|
|
report "Error: In accumulator mode, the OUTPUT_ROUNDING parameter has to be set to VARIABLE if used"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((chainout_adder = "YES") and (output_rounding /= "NO")) then
|
|
assert false
|
|
report "Error: In chainout mode, output rounding cannot be turned on"
|
|
severity error;
|
|
end if;
|
|
end if;
|
|
|
|
|
|
wait;
|
|
|
|
end process;
|
|
|
|
-- ----------------------------------------------------------------
|
|
-- This process updates the dataa_int everytime dataa changes value
|
|
-- ----------------------------------------------------------------
|
|
IFG01: if (number_of_multipliers >= 1) generate
|
|
process (dataa, signa, sign_a_reg, sign_a_pipe)
|
|
variable dataa1_cnt : integer := 0;
|
|
variable dataa_word_temp : std_logic_vector (int_width_a -1 downto 0) := (others=>'0');
|
|
variable asign : boolean;
|
|
variable is_rep_a_sign : boolean;
|
|
variable is_rep_a_pipe_sign : boolean;
|
|
begin
|
|
is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
-- Use sign_a_reg instead of sign_a_pipe when signed_pipeline_register_a is unregistered
|
|
-- to set the asign flag
|
|
if (signed_pipeline_register_a = "UNREGISTERED") then
|
|
if (is_rep_a_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_a_pipe_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
end if;
|
|
|
|
dataa_word_temp := (others => '0');
|
|
if ((chainout_adder = "YES") and (stratixiii_block)) then
|
|
if ((width_result > width_a + width_b + 8) and (width_a < 18)) then
|
|
if (asign = true) then -- signed number, extend MSB with sign bit
|
|
for dataa1_cnt in 1 to (chainout_input_a) loop
|
|
dataa_word_temp(int_width_a - dataa1_cnt) := dataa(width_a - 1);
|
|
end loop;
|
|
else -- unsigned number, extend MSB with "0"
|
|
for dataa1_cnt in 1 to (chainout_input_a) loop
|
|
dataa_word_temp(int_width_a - dataa1_cnt) := '0';
|
|
end loop;
|
|
end if;
|
|
|
|
for dataa1_cnt in 0 to (width_a - 1) loop
|
|
dataa_word_temp(dataa1_cnt) := dataa(dataa1_cnt);
|
|
end loop;
|
|
|
|
dataa_int1 <= dataa_word_temp(int_width_a -1 downto 0);
|
|
else
|
|
dataa_int1((int_width_a) - 1 downto ((int_width_a) - width_a)) <= dataa(width_a - 1 downto 0);
|
|
end if;
|
|
else
|
|
dataa_int1((int_width_a) - 1 downto ((int_width_a) - width_a)) <= dataa(width_a - 1 downto 0);
|
|
end if;
|
|
end process;
|
|
end generate IFG01;
|
|
|
|
IFG02: if (number_of_multipliers >= 2) generate
|
|
process (dataa, signa, sign_a_reg, sign_a_pipe)
|
|
variable dataa2_cnt : integer := 0;
|
|
variable dataa2_word_temp : std_logic_vector (int_width_a -1 downto 0) := (others=>'0');
|
|
variable asign : boolean;
|
|
variable is_rep_a_sign : boolean;
|
|
variable is_rep_a_pipe_sign : boolean;
|
|
begin
|
|
is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
-- Use sign_a_reg instead of sign_a_pipe when signed_pipeline_register_a is unregistered
|
|
-- to set the asign flag
|
|
if (signed_pipeline_register_a = "UNREGISTERED") then
|
|
if (is_rep_a_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_a_pipe_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
end if;
|
|
|
|
dataa2_word_temp := (others => '0');
|
|
if ((chainout_adder = "YES") and (stratixiii_block)) then
|
|
if ((width_result > width_a + width_b + 8) and (width_a < 18)) then
|
|
if (asign = true) then -- signed number, extend MSB with sign bit
|
|
for dataa2_cnt in 1 to (chainout_input_a) loop
|
|
dataa2_word_temp(int_width_a - dataa2_cnt) := dataa((2*width_a) - 1);
|
|
end loop;
|
|
else -- unsigned number, extend MSB with "0"
|
|
for dataa2_cnt in 1 to (chainout_input_a) loop
|
|
dataa2_word_temp(int_width_a - dataa2_cnt) := '0';
|
|
end loop;
|
|
end if;
|
|
|
|
for dataa2_cnt in 0 to (width_a - 1) loop
|
|
dataa2_word_temp(dataa2_cnt) := dataa(width_a + dataa2_cnt);
|
|
end loop;
|
|
|
|
dataa_int2 <= dataa2_word_temp(int_width_a -1 downto 0);
|
|
|
|
else
|
|
dataa_int2((int_width_a) - 1 downto ((int_width_a) - width_a)) <= dataa((2*width_a) - 1 downto width_a);
|
|
end if;
|
|
else
|
|
dataa_int2((int_width_a) - 1 downto ((int_width_a) - width_a)) <= dataa((2 * width_a) - 1 downto width_a);
|
|
end if;
|
|
end process;
|
|
end generate IFG02;
|
|
|
|
IFG03: if (number_of_multipliers >= 3) generate
|
|
process (dataa, signa, sign_a_reg, sign_a_pipe)
|
|
variable dataa3_cnt : integer := 0;
|
|
variable dataa3_word_temp : std_logic_vector (int_width_a -1 downto 0) := (others=>'0');
|
|
variable asign : boolean;
|
|
variable is_rep_a_sign : boolean;
|
|
variable is_rep_a_pipe_sign : boolean;
|
|
begin
|
|
is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
-- Use sign_a_reg instead of sign_a_pipe when signed_pipeline_register_a is unregistered
|
|
-- to set the asign flag
|
|
if (signed_pipeline_register_a = "UNREGISTERED") then
|
|
if (is_rep_a_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_a_pipe_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
end if;
|
|
|
|
dataa3_word_temp := (others => '0');
|
|
if ((chainout_adder = "YES") and (stratixiii_block)) then
|
|
if ((width_result > width_a + width_b + 8) and (width_a < 18)) then
|
|
if (asign = true) then -- signed number, extend MSB with sign bit
|
|
for dataa3_cnt in 1 to (chainout_input_a) loop
|
|
dataa3_word_temp(int_width_a - dataa3_cnt) := dataa((3*width_a) - 1);
|
|
end loop;
|
|
else -- unsigned number, extend MSB with "0"
|
|
for dataa3_cnt in 1 to (chainout_input_a) loop
|
|
dataa3_word_temp(int_width_a - dataa3_cnt) := '0';
|
|
end loop;
|
|
end if;
|
|
|
|
for dataa3_cnt in 0 to (width_a - 1) loop
|
|
dataa3_word_temp (dataa3_cnt) := dataa((2*width_a) + dataa3_cnt);
|
|
end loop;
|
|
|
|
dataa_int3 <= dataa3_word_temp(int_width_a -1 downto 0);
|
|
|
|
else
|
|
dataa_int3((int_width_a) - 1 downto ((int_width_a) - width_a)) <= dataa((3*width_a) - 1 downto (2*width_a));
|
|
end if;
|
|
else
|
|
dataa_int3((int_width_a) - 1 downto (int_width_a) - width_a) <= dataa((3 * width_a) - 1 downto (2 * width_a));
|
|
end if;
|
|
end process;
|
|
end generate IFG03;
|
|
|
|
IFG04: if (number_of_multipliers >= 4) generate
|
|
process (dataa, signa, sign_a_reg, sign_a_pipe)
|
|
variable dataa4_cnt : integer := 0;
|
|
variable dataa4_word_temp : std_logic_vector (int_width_a -1 downto 0) := (others=>'0');
|
|
variable asign : boolean;
|
|
variable is_rep_a_sign : boolean;
|
|
variable is_rep_a_pipe_sign : boolean;
|
|
begin
|
|
is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
-- Use sign_a_reg instead of sign_a_pipe when signed_pipeline_register_a is unregistered
|
|
-- to set the asign flag
|
|
if (signed_pipeline_register_a = "UNREGISTERED") then
|
|
if (is_rep_a_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_a_pipe_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
end if;
|
|
|
|
dataa4_word_temp := (others => '0');
|
|
if ((chainout_adder = "YES") and (stratixiii_block)) then
|
|
if ((width_result > width_a + width_b + 8) and (width_a < 18)) then
|
|
if (asign = true) then -- signed number, extend MSB with sign bit
|
|
for dataa4_cnt in 1 to (chainout_input_a) loop
|
|
dataa4_word_temp(int_width_a - dataa4_cnt) := dataa((4*width_a) - 1);
|
|
end loop;
|
|
else -- unsigned number, extend MSB with "0"
|
|
for dataa4_cnt in 1 to (chainout_input_a) loop
|
|
dataa4_word_temp(int_width_a - dataa4_cnt) := '0';
|
|
end loop;
|
|
end if;
|
|
|
|
for dataa4_cnt in 0 to (width_a - 1) loop
|
|
dataa4_word_temp(dataa4_cnt) := dataa((3*width_a) + dataa4_cnt);
|
|
end loop;
|
|
|
|
dataa_int4 <= dataa4_word_temp(int_width_a -1 downto 0);
|
|
|
|
else
|
|
dataa_int4((int_width_a) - 1 downto ((int_width_a) - width_a)) <= dataa((4*width_a) - 1 downto (3*width_a));
|
|
end if;
|
|
else
|
|
dataa_int4((int_width_a) - 1 downto (int_width_a) - width_a) <= dataa((4 * width_a) - 1 downto (3 * width_a));
|
|
end if;
|
|
end process;
|
|
end generate IFG04;
|
|
|
|
-- ----------------------------------------------------------------
|
|
-- This process updates the datab_int everytime datab changes value
|
|
-- ----------------------------------------------------------------
|
|
|
|
IFG05: if (number_of_multipliers >= 1) generate
|
|
process (datab, signb, sign_b_reg, sign_b_pipe)
|
|
variable datab1_cnt : integer := 0;
|
|
variable datab_word_temp : std_logic_vector(int_width_b -1 downto 0) := (others => '0');
|
|
variable bsign : boolean;
|
|
variable is_rep_b_sign : boolean;
|
|
variable is_rep_b_pipe_sign : boolean;
|
|
begin
|
|
is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
-- Use sign_b_reg instead of sign_b_pipe when
|
|
-- signed_pipeline_register_b is unregistered
|
|
-- to set the bsign flag
|
|
if (signed_pipeline_register_b = "UNREGISTERED") then
|
|
if (is_rep_b_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_b_pipe_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
end if;
|
|
|
|
datab_word_temp := (others => '0');
|
|
if ((chainout_adder = "YES") and (stratixiii_block)) then
|
|
if ((width_result > width_a + width_b + 8) and (width_b < 18))then
|
|
if (bsign = true) then -- signed number, extend MSB with sign bit
|
|
for datab1_cnt in 1 to (chainout_input_b) loop
|
|
datab_word_temp(int_width_b - datab1_cnt) := datab(width_b - 1);
|
|
end loop;
|
|
else -- unsigned number, extend MSB with "0"
|
|
for datab1_cnt in 1 to (chainout_input_b) loop
|
|
datab_word_temp(int_width_b - datab1_cnt) := '0';
|
|
end loop;
|
|
end if;
|
|
|
|
for datab1_cnt in 0 to (width_b - 1) loop
|
|
datab_word_temp(datab1_cnt) := datab(datab1_cnt);
|
|
end loop;
|
|
|
|
datab_int1 <= datab_word_temp(int_width_b - 1 downto 0);
|
|
else
|
|
datab_int1((int_width_b) - 1 downto ((int_width_b) - width_b)) <= datab(width_b - 1 downto 0);
|
|
end if;
|
|
else
|
|
datab_int1((int_width_b) - 1 downto ((int_width_b) - width_b)) <= datab(width_b - 1 downto 0);
|
|
end if;
|
|
end process;
|
|
end generate IFG05;
|
|
|
|
IFG06: if (number_of_multipliers >= 2) generate
|
|
process (datab, signb, sign_b_reg, sign_b_pipe)
|
|
variable datab2_cnt : integer := 0;
|
|
variable datab2_word_temp : std_logic_vector(int_width_b -1 downto 0) := (others => '0');
|
|
variable bsign : boolean;
|
|
variable is_rep_b_sign : boolean;
|
|
variable is_rep_b_pipe_sign : boolean;
|
|
begin
|
|
is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
-- Use sign_b_reg instead of sign_b_pipe when
|
|
-- signed_pipeline_register_b is unregistered
|
|
-- to set the bsign flag
|
|
if (signed_pipeline_register_b = "UNREGISTERED") then
|
|
if (is_rep_b_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_b_pipe_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
end if;
|
|
|
|
datab2_word_temp := (others => '0');
|
|
if ((chainout_adder = "YES") and (stratixiii_block)) then
|
|
if ((width_result > width_a + width_b + 8) and (width_b < 18)) then
|
|
if (bsign = true) then -- signed number, extend MSB with sign bit
|
|
for datab2_cnt in 1 to (chainout_input_b) loop
|
|
datab2_word_temp(int_width_b - datab2_cnt) := datab((2*width_b) - 1);
|
|
end loop;
|
|
else -- unsigned number, extend MSB with "0"
|
|
for datab2_cnt in 1 to (chainout_input_b) loop
|
|
datab2_word_temp(int_width_b - datab2_cnt) := '0';
|
|
end loop;
|
|
end if;
|
|
|
|
for datab2_cnt in 0 to (width_b - 1) loop
|
|
datab2_word_temp(datab2_cnt) := datab(width_b + datab2_cnt);
|
|
end loop;
|
|
|
|
datab_int2 <= datab2_word_temp(int_width_b -1 downto 0);
|
|
else
|
|
datab_int2((int_width_b) - 1 downto ((int_width_b) - width_b)) <= datab((2*width_b) - 1 downto width_b);
|
|
end if;
|
|
else
|
|
datab_int2((int_width_b) - 1 downto ((int_width_b) - width_b)) <= datab((2 * width_b) - 1 downto width_b);
|
|
end if;
|
|
end process;
|
|
end generate IFG06;
|
|
|
|
IFG07: if (number_of_multipliers >= 3) generate
|
|
process (datab, signb, sign_b_reg, sign_b_pipe)
|
|
variable datab3_cnt : integer := 0;
|
|
variable datab3_word_temp : std_logic_vector(int_width_b -1 downto 0) := (others => '0');
|
|
variable bsign : boolean;
|
|
variable is_rep_b_sign : boolean;
|
|
variable is_rep_b_pipe_sign : boolean;
|
|
begin
|
|
is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
-- Use sign_b_reg instead of sign_b_pipe when
|
|
-- signed_pipeline_register_b is unregistered
|
|
-- to set the bsign flag
|
|
if (signed_pipeline_register_b = "UNREGISTERED") then
|
|
if (is_rep_b_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_b_pipe_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
end if;
|
|
|
|
datab3_word_temp := (others => '0');
|
|
if ((chainout_adder = "YES") and (stratixiii_block)) then
|
|
if ((width_result > width_a + width_b + 8) and (width_b < 18)) then
|
|
if (bsign = true) then -- signed number, extend MSB with sign bit
|
|
for datab3_cnt in 1 to (chainout_input_b) loop
|
|
datab3_word_temp(int_width_b - datab3_cnt) := datab((3*width_b) - 1);
|
|
end loop;
|
|
else -- unsigned number, extend MSB with "0"
|
|
for datab3_cnt in 1 to (chainout_input_b) loop
|
|
datab3_word_temp(int_width_b - datab3_cnt) := '0';
|
|
end loop;
|
|
end if;
|
|
|
|
for datab3_cnt in 0 to (width_b - 1) loop
|
|
datab3_word_temp(datab3_cnt) := datab((2*width_b) + datab3_cnt);
|
|
end loop;
|
|
|
|
datab_int3 <= datab3_word_temp(int_width_b - 1 downto 0);
|
|
else
|
|
datab_int3((int_width_b) - 1 downto ((int_width_b) - width_b)) <= datab((3*width_b) - 1 downto (2*width_b));
|
|
end if;
|
|
else
|
|
datab_int3((int_width_b) - 1 downto ((int_width_b) - width_b)) <= datab((3 * width_b) - 1 downto (2 * width_b));
|
|
end if;
|
|
end process;
|
|
end generate IFG07;
|
|
|
|
IFG08: if (number_of_multipliers >= 4) generate
|
|
process (datab, signb, sign_b_reg, sign_b_pipe)
|
|
variable datab4_cnt : integer := 0;
|
|
variable datab4_word_temp : std_logic_vector(int_width_b -1 downto 0) := (others => '0');
|
|
variable bsign : boolean;
|
|
variable is_rep_b_sign : boolean;
|
|
variable is_rep_b_pipe_sign : boolean;
|
|
begin
|
|
is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
-- Use sign_b_reg instead of sign_b_pipe when
|
|
-- signed_pipeline_register_b is unregistered
|
|
-- to set the bsign flag
|
|
if (signed_pipeline_register_b = "UNREGISTERED") then
|
|
if (is_rep_b_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_b_pipe_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
end if;
|
|
|
|
datab4_word_temp := (others => '0');
|
|
if ((chainout_adder = "YES") and (stratixiii_block)) then
|
|
if ((width_result > width_a + width_b + 8) and (width_b < 18)) then
|
|
if (bsign = true) then -- signed number, extend MSB with sign bit
|
|
for datab4_cnt in 1 to (chainout_input_b) loop
|
|
datab4_word_temp(int_width_b - datab4_cnt) := datab((4*width_b) - 1);
|
|
end loop;
|
|
else -- unsigned number, extend MSB with "0"
|
|
for datab4_cnt in 1 to (chainout_input_b) loop
|
|
datab4_word_temp(int_width_b - datab4_cnt) := '0';
|
|
end loop;
|
|
end if;
|
|
|
|
for datab4_cnt in 0 to (width_b - 1) loop
|
|
datab4_word_temp(datab4_cnt) := datab((3*width_b) + datab4_cnt);
|
|
end loop;
|
|
|
|
datab_int4 <= datab4_word_temp(int_width_b - 1 downto 0);
|
|
|
|
else
|
|
datab_int4((int_width_b) - 1 downto ((int_width_b) - width_b)) <= datab((4*width_b) - 1 downto (3*width_b));
|
|
end if;
|
|
else
|
|
datab_int4((int_width_b) - 1 downto ((int_width_b) - width_b)) <= datab((4 * width_b) - 1 downto (3 * width_b));
|
|
end if;
|
|
end process;
|
|
end generate IFG08;
|
|
|
|
-- This process updates scanouta depending on which family is being used
|
|
process (mult_a, scanouta_reg)
|
|
begin
|
|
if (altera_mult_add_block) then
|
|
scanouta <= (others => 'Z');
|
|
elsif (stratixiii_block) then
|
|
scanouta <= scanouta_reg (width_a - 1 downto 0);
|
|
else
|
|
scanouta <= mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
|
|
end if;
|
|
end process;
|
|
|
|
-- This process updates dataa_int and datab_int
|
|
process (dataa_int1, dataa_int2, dataa_int3, dataa_int4, datab_int1, datab_int2, datab_int3, datab_int4)
|
|
begin
|
|
dataa_int <= dataa_int4 & dataa_int3 & dataa_int2 & dataa_int1;
|
|
datab_int <= datab_int4 & datab_int3 & datab_int2 & datab_int1;
|
|
end process;
|
|
|
|
-- ------------------------------------------------------------------------------------
|
|
-- This process sets up all the clock, clock enable and clear signals for all registers
|
|
-- ------------------------------------------------------------------------------------
|
|
-- ---------------------------------------
|
|
-- SETTING UP THE CONTROL SIGNAL REGISTERS
|
|
-- ---------------------------------------
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set addsub_reg1)
|
|
-- The signal registered is addnsub1
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if addnsub_multiplier_register1
|
|
-- is unregistered and addnsub1 changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G1: if (addnsub_multiplier_register1 = "UNREGISTERED") generate
|
|
addsub_reg1 <= addnsub1;
|
|
end generate G1;
|
|
|
|
IFG9: if (addnsub_multiplier_register1 = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub1)
|
|
begin
|
|
if (((addnsub_multiplier_aclr1= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg1 <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
addsub_reg1 <= addnsub1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG9;
|
|
|
|
IFG10: if (addnsub_multiplier_register1 = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub1)
|
|
begin
|
|
if (((addnsub_multiplier_aclr1= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg1 <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
addsub_reg1 <= addnsub1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG10;
|
|
|
|
IFG11: if (addnsub_multiplier_register1 = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub1)
|
|
begin
|
|
if (((addnsub_multiplier_aclr1= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg1 <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
addsub_reg1 <= addnsub1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG11;
|
|
|
|
IFG12: if (addnsub_multiplier_register1 = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub1)
|
|
begin
|
|
if (((addnsub_multiplier_aclr1= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_aclr1= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg1 <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
addsub_reg1 <= addnsub1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG12;
|
|
|
|
-- ----------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set addsub_pipe1)
|
|
-- The signal registered is addsub_reg1
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if addnsub_multiplier_pipeline_register1
|
|
-- is unregistered and addsub_reg1 changes value
|
|
-- ----------------------------------------------------------------------------------
|
|
|
|
G2: if (addnsub_multiplier_pipeline_register1 = "UNREGISTERED") generate
|
|
addsub_pipe1 <= addsub_reg1;
|
|
end generate G2;
|
|
|
|
IFG14: if (addnsub_multiplier_pipeline_register1 = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, addsub_reg1)
|
|
begin
|
|
if (((addnsub_multiplier_pipeline_aclr1= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe1<= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
addsub_pipe1 <= addsub_reg1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG14;
|
|
|
|
IFG14a: if (addnsub_multiplier_pipeline_register1 = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, addsub_reg1)
|
|
begin
|
|
if (((addnsub_multiplier_pipeline_aclr1= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe1<= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
addsub_pipe1 <= addsub_reg1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG14a;
|
|
|
|
IFG15: if (addnsub_multiplier_pipeline_register1 = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, addsub_reg1)
|
|
begin
|
|
if (((addnsub_multiplier_pipeline_aclr1= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe1<= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
addsub_pipe1 <= addsub_reg1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG15;
|
|
|
|
IFG16: if (addnsub_multiplier_pipeline_register1 = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, addsub_reg1)
|
|
begin
|
|
if (((addnsub_multiplier_pipeline_aclr1= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr1= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe1<= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
addsub_pipe1 <= addsub_reg1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG16;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set addsub_reg3)
|
|
-- The signal registered is addsub3
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if addnsub_multiplier_register3
|
|
-- is unregistered and addnsub3 changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G3: if (addnsub_multiplier_register3 = "UNREGISTERED") generate
|
|
addsub_reg3 <= addnsub3;
|
|
end generate G3;
|
|
|
|
IFG17: if (addnsub_multiplier_register3 = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub3)
|
|
begin
|
|
if (((addnsub_multiplier_aclr3= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg3 <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
addsub_reg3 <= addnsub3;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG17;
|
|
|
|
IFG18: if (addnsub_multiplier_register3 = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub3)
|
|
begin
|
|
if (((addnsub_multiplier_aclr3= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg3 <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
addsub_reg3 <= addnsub3;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG18;
|
|
|
|
IFG19: if (addnsub_multiplier_register3 = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub3)
|
|
begin
|
|
if (((addnsub_multiplier_aclr3= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg3 <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
addsub_reg3 <= addnsub3;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG19;
|
|
|
|
IFG20: if (addnsub_multiplier_register3 = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub3)
|
|
begin
|
|
if (((addnsub_multiplier_aclr3= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_aclr3= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_reg3 <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
addsub_reg3 <= addnsub3;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG20;
|
|
|
|
-- ----------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set addsub_pipe3)
|
|
-- The signal registered is addsub_reg3
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if addnsub_multiplier_pipeline_register3
|
|
-- is unregistered and addsub_reg3 changes value
|
|
-- ----------------------------------------------------------------------------------
|
|
|
|
G4: if (addnsub_multiplier_pipeline_register3 = "UNREGISTERED") generate
|
|
addsub_pipe3 <= addsub_reg3;
|
|
end generate G4;
|
|
|
|
IFG21: if (addnsub_multiplier_pipeline_register3 = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, addsub_reg3)
|
|
begin
|
|
if (((addnsub_multiplier_pipeline_aclr3= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe3<= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
addsub_pipe3 <= addsub_reg3;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG21;
|
|
|
|
IFG22: if (addnsub_multiplier_pipeline_register3 = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, addsub_reg3)
|
|
begin
|
|
if (((addnsub_multiplier_pipeline_aclr3= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe3<= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
addsub_pipe3 <= addsub_reg3;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG22;
|
|
|
|
IFG23: if (addnsub_multiplier_pipeline_register3 = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, addsub_reg3)
|
|
begin
|
|
if (((addnsub_multiplier_pipeline_aclr3= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe3<= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
addsub_pipe3 <= addsub_reg3;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG23;
|
|
|
|
IFG24: if (addnsub_multiplier_pipeline_register3 = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, addsub_reg3)
|
|
begin
|
|
if (((addnsub_multiplier_pipeline_aclr3= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub_multiplier_pipeline_aclr3= "ACLR3") and (aclr3 = '1'))) then
|
|
addsub_pipe3<= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
addsub_pipe3 <= addsub_reg3;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG24;
|
|
|
|
-- --------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set sign_a_reg)
|
|
-- The signal registered is signa
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if signed_register_a
|
|
-- is unregistered and signa changes value
|
|
-- --------------------------------------------------------------------------------
|
|
|
|
G5: if (signed_register_a = "UNREGISTERED") generate
|
|
sign_a_reg <= signa;
|
|
end generate G5;
|
|
|
|
IFG25: if (signed_register_a = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, signa)
|
|
begin
|
|
if (((signed_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
sign_a_reg <= signa;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG25;
|
|
|
|
IFG26: if (signed_register_a = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, signa)
|
|
begin
|
|
if (((signed_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
sign_a_reg <= signa;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG26;
|
|
|
|
IFG27: if (signed_register_a = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, signa)
|
|
begin
|
|
if (((signed_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
sign_a_reg <= signa;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG27;
|
|
|
|
IFG28: if (signed_register_a = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, signa)
|
|
begin
|
|
if (((signed_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
sign_a_reg <= signa;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG28;
|
|
|
|
-- --------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set sign_b_reg)
|
|
-- The signal registered is signb
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if signed_register_b
|
|
-- is unregistered and signb changes value
|
|
-- --------------------------------------------------------------------------------
|
|
|
|
G6: if (signed_register_b = "UNREGISTERED") generate
|
|
sign_b_reg <= signb;
|
|
end generate G6;
|
|
|
|
IFG29: if (signed_register_b = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, signb)
|
|
begin
|
|
if (((signed_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
sign_b_reg <= signb;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG29;
|
|
|
|
IFG30: if (signed_register_b = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, signb)
|
|
begin
|
|
if (((signed_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
sign_b_reg <= signb;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG30;
|
|
|
|
IFG31: if (signed_register_b = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, signb)
|
|
begin
|
|
if (((signed_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
sign_b_reg <= signb;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG31;
|
|
|
|
IFG32: if (signed_register_b = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, signb)
|
|
begin
|
|
if (((signed_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
sign_b_reg <= signb;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG32;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set sign_a_pipe)
|
|
-- The signal registered is sign_a_reg
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if signed_pipeline_register_a
|
|
-- is unregistered and sign_a_reg changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G7: if (signed_pipeline_register_a = "UNREGISTERED") generate
|
|
sign_a_pipe <= sign_a_reg;
|
|
end generate G7;
|
|
|
|
IFG33: if (signed_pipeline_register_a = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, sign_a_reg)
|
|
begin
|
|
if (((signed_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
sign_a_pipe <= sign_a_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG33;
|
|
|
|
IFG34: if (signed_pipeline_register_a = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, sign_a_reg)
|
|
begin
|
|
if (((signed_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
sign_a_pipe <= sign_a_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG34;
|
|
|
|
IFG35: if (signed_pipeline_register_a = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, sign_a_reg)
|
|
begin
|
|
if (((signed_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
sign_a_pipe <= sign_a_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG35;
|
|
|
|
IFG36: if (signed_pipeline_register_a = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, sign_a_reg)
|
|
begin
|
|
if (((signed_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_a_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
sign_a_pipe <= sign_a_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG36;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set sign_b_pipe)
|
|
-- The signal registered is sign_b_reg
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if signed_pipeline_register_b
|
|
-- is unregistered and sign_b_reg changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G8: if (signed_pipeline_register_b = "UNREGISTERED") generate
|
|
sign_b_pipe <= sign_b_reg;
|
|
end generate G8;
|
|
|
|
IFG37: if (signed_pipeline_register_b = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, sign_b_reg)
|
|
begin
|
|
if (((signed_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
sign_b_pipe <= sign_b_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG37;
|
|
|
|
IFG38: if (signed_pipeline_register_b = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, sign_b_reg)
|
|
begin
|
|
if (((signed_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
sign_b_pipe <= sign_b_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG38;
|
|
|
|
IFG39: if (signed_pipeline_register_b = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, sign_b_reg)
|
|
begin
|
|
if (((signed_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
sign_b_pipe <= sign_b_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG39;
|
|
|
|
IFG40: if (signed_pipeline_register_b = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, sign_b_reg)
|
|
begin
|
|
if (((signed_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
|
|
((signed_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
|
|
sign_b_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
sign_b_pipe <= sign_b_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG40;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set outround_reg)
|
|
-- The signal registered is output_round
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if output_round_register
|
|
-- is unregistered and output_round changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G17 : if (output_round_register = "UNREGISTERED") generate
|
|
outround_reg <= output_round;
|
|
end generate G17;
|
|
|
|
IFG73: if (output_round_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, output_round)
|
|
begin
|
|
if (((output_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outround_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
outround_reg <= output_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG73;
|
|
|
|
IFG74: if (output_round_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, output_round)
|
|
begin
|
|
if (((output_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outround_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
outround_reg <= output_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG74;
|
|
|
|
IFG75: if (output_round_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, output_round)
|
|
begin
|
|
if (((output_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outround_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
outround_reg <= output_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG75;
|
|
|
|
IFG76: if (output_round_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, output_round)
|
|
begin
|
|
if (((output_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outround_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
outround_reg <= output_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG76;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set outround_pipe)
|
|
-- The signal registered is outround_reg
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if output_round_pipeline_register
|
|
-- is unregistered and outround_reg changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G18 : if (output_round_pipeline_register = "UNREGISTERED") generate
|
|
outround_pipe <= outround_reg;
|
|
end generate G18;
|
|
|
|
IFG77: if (output_round_pipeline_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, outround_reg)
|
|
begin
|
|
if (((output_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outround_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
outround_pipe <= outround_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG77;
|
|
|
|
IFG78: if (output_round_pipeline_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, outround_reg)
|
|
begin
|
|
if (((output_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outround_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
outround_pipe <= outround_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG78;
|
|
|
|
IFG79: if (output_round_pipeline_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, outround_reg)
|
|
begin
|
|
if (((output_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outround_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
outround_pipe <= outround_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG79;
|
|
|
|
IFG80: if (output_round_pipeline_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, outround_reg)
|
|
begin
|
|
if (((output_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outround_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
outround_pipe <= outround_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG80;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set chainout_round_reg)
|
|
-- The signal registered is chainout_round
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if chainout_round_register
|
|
-- is unregistered and chainout_round changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G19 : if (chainout_round_register = "UNREGISTERED") generate
|
|
chainout_round_reg <= chainout_round;
|
|
end generate G19;
|
|
|
|
IFG81: if (chainout_round_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_round)
|
|
begin
|
|
if (((chainout_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
chainout_round_reg <= chainout_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG81;
|
|
|
|
IFG82: if (chainout_round_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_round)
|
|
begin
|
|
if (((chainout_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
chainout_round_reg <= chainout_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG82;
|
|
|
|
IFG83: if (chainout_round_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_round)
|
|
begin
|
|
if (((chainout_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
chainout_round_reg <= chainout_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG83;
|
|
|
|
IFG84: if (chainout_round_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_round)
|
|
begin
|
|
if (((chainout_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
chainout_round_reg <= chainout_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG84;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set chainout_round_pipe)
|
|
-- The signal registered is chainout_round_reg
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if chainout_round_pipeline_register
|
|
-- is unregistered and chainout_round_reg changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G20 : if (chainout_round_pipeline_register = "UNREGISTERED") generate
|
|
chainout_round_pipe <= chainout_round_reg;
|
|
end generate G20;
|
|
|
|
IFG85: if (chainout_round_pipeline_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_round_reg)
|
|
begin
|
|
if (((chainout_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
chainout_round_pipe <= chainout_round_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG85;
|
|
|
|
IFG86: if (chainout_round_pipeline_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_round_reg)
|
|
begin
|
|
if (((chainout_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
chainout_round_pipe <= chainout_round_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG86;
|
|
|
|
IFG87: if (chainout_round_pipeline_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_round_reg)
|
|
begin
|
|
if (((chainout_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
chainout_round_pipe <= chainout_round_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG87;
|
|
|
|
IFG88: if (chainout_round_pipeline_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_round_reg)
|
|
begin
|
|
if (((chainout_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
chainout_round_pipe <= chainout_round_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG88;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set chainout_round_out_reg)
|
|
-- The signal registered is chainout_round_pipe
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if chainout_round_output_register
|
|
-- is unregistered and chainout_round_pipe changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G21 : if (chainout_round_output_register = "UNREGISTERED") generate
|
|
chainout_round_out_reg <= chainout_round_pipe;
|
|
end generate G21;
|
|
|
|
IFG89: if (chainout_round_output_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_round_pipe)
|
|
begin
|
|
if (((chainout_round_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_out_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
chainout_round_out_reg <= chainout_round_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG89;
|
|
|
|
IFG90: if (chainout_round_output_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_round_pipe)
|
|
begin
|
|
if (((chainout_round_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_out_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
chainout_round_out_reg <= chainout_round_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG90;
|
|
|
|
IFG91: if (chainout_round_output_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_round_pipe)
|
|
begin
|
|
if (((chainout_round_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_out_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
chainout_round_out_reg <= chainout_round_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG91;
|
|
|
|
IFG92: if (chainout_round_output_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_round_pipe)
|
|
begin
|
|
if (((chainout_round_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_round_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_round_out_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
chainout_round_out_reg <= chainout_round_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG92;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set outsat_reg)
|
|
-- The signal registered is output_saturate
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if output_saturate_register
|
|
-- is unregistered and output_saturate changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G22 : if (output_saturate_register = "UNREGISTERED") generate
|
|
outsat_reg <= output_saturate;
|
|
end generate G22;
|
|
|
|
IFG93: if (output_saturate_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, output_saturate)
|
|
begin
|
|
if (((output_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outsat_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
outsat_reg <= output_saturate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG93;
|
|
|
|
IFG94: if (output_saturate_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, output_saturate)
|
|
begin
|
|
if (((output_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outsat_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
outsat_reg <= output_saturate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG94;
|
|
|
|
IFG95: if (output_saturate_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, output_saturate)
|
|
begin
|
|
if (((output_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outsat_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
outsat_reg <= output_saturate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG95;
|
|
|
|
IFG96: if (output_saturate_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, output_saturate)
|
|
begin
|
|
if (((output_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outsat_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
outsat_reg <= output_saturate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG96;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set outsat_pipe)
|
|
-- The signal registered is outsat_reg
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if output_saturate_pipeline_register
|
|
-- is unregistered and outsat_reg changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G23 : if (output_saturate_pipeline_register = "UNREGISTERED") generate
|
|
outsat_pipe <= outsat_reg;
|
|
end generate G23;
|
|
|
|
IFG97: if (output_saturate_pipeline_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, outsat_reg)
|
|
begin
|
|
if (((output_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outsat_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
outsat_pipe <= outsat_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG97;
|
|
|
|
IFG98: if (output_saturate_pipeline_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, outsat_reg)
|
|
begin
|
|
if (((output_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outsat_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
outsat_pipe <= outsat_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG98;
|
|
|
|
IFG99: if (output_saturate_pipeline_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, outsat_reg)
|
|
begin
|
|
if (((output_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outsat_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
outsat_pipe <= outsat_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG99;
|
|
|
|
IFG100: if (output_saturate_pipeline_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, outsat_reg)
|
|
begin
|
|
if (((output_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
outsat_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
outsat_pipe <= outsat_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG100;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set chainout_sat_reg)
|
|
-- The signal registered is chainout_saturate
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if chainout_saturate_register
|
|
-- is unregistered and chainout_saturate changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G24 : if (chainout_saturate_register = "UNREGISTERED") generate
|
|
chainout_sat_reg <= chainout_saturate;
|
|
end generate G24;
|
|
|
|
IFG101: if (chainout_saturate_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_saturate)
|
|
begin
|
|
if (((chainout_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
chainout_sat_reg <= chainout_saturate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG101;
|
|
|
|
IFG102: if (chainout_saturate_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_saturate)
|
|
begin
|
|
if (((chainout_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
chainout_sat_reg <= chainout_saturate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG102;
|
|
|
|
IFG103: if (chainout_saturate_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_saturate)
|
|
begin
|
|
if (((chainout_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
chainout_sat_reg <= chainout_saturate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG103;
|
|
|
|
IFG104: if (chainout_saturate_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_saturate)
|
|
begin
|
|
if (((chainout_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
chainout_sat_reg <= chainout_saturate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG104;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set chainout_sat_pipe)
|
|
-- The signal registered is chainout_sat_reg
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if chainout_saturate_pipeline_register
|
|
-- is unregistered and chainout_sat_reg changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G25 : if (chainout_saturate_pipeline_register = "UNREGISTERED") generate
|
|
chainout_sat_pipe <= chainout_sat_reg;
|
|
end generate G25;
|
|
|
|
IFG105: if (chainout_saturate_pipeline_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_sat_reg)
|
|
begin
|
|
if (((chainout_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
chainout_sat_pipe <= chainout_sat_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG105;
|
|
|
|
IFG106: if (chainout_saturate_pipeline_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_sat_reg)
|
|
begin
|
|
if (((chainout_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
chainout_sat_pipe <= chainout_sat_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG106;
|
|
|
|
IFG107: if (chainout_saturate_pipeline_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_sat_reg)
|
|
begin
|
|
if (((chainout_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
chainout_sat_pipe <= chainout_sat_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG107;
|
|
|
|
IFG108: if (chainout_saturate_pipeline_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_sat_reg)
|
|
begin
|
|
if (((chainout_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
chainout_sat_pipe <= chainout_sat_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG108;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set chainout_sat_out)
|
|
-- The signal registered is chainout_sat_pipe
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if chainout_saturate_output_register
|
|
-- is unregistered and chainout_sat_pipe changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G26 : if (chainout_saturate_output_register = "UNREGISTERED") generate
|
|
chainout_sat_out <= chainout_sat_pipe;
|
|
end generate G26;
|
|
|
|
IFG109: if (chainout_saturate_output_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_sat_pipe)
|
|
begin
|
|
if (((chainout_saturate_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_out <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
chainout_sat_out <= chainout_sat_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG109;
|
|
|
|
IFG110: if (chainout_saturate_output_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_sat_pipe)
|
|
begin
|
|
if (((chainout_saturate_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_out <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
chainout_sat_out <= chainout_sat_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG110;
|
|
|
|
IFG111: if (chainout_saturate_output_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_sat_pipe)
|
|
begin
|
|
if (((chainout_saturate_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_out <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
chainout_sat_out <= chainout_sat_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG111;
|
|
|
|
IFG112: if (chainout_saturate_output_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_sat_pipe)
|
|
begin
|
|
if (((chainout_saturate_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_saturate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
chainout_sat_out <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
chainout_sat_out <= chainout_sat_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG112;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set scanouta_reg)
|
|
-- The signal registered is mult_a
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if scanouta_register
|
|
-- is unregistered and mult_a changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
G27 : if ((scanouta_register = "UNREGISTERED" and chainout_adder = "YES") and (width_result > width_a + width_b + 8))generate
|
|
scanouta_reg <= mult_a((number_of_multipliers * int_width_a) - 1 - (int_width_a - width_a) downto ((number_of_multipliers-1) * int_width_a));
|
|
end generate G27;
|
|
|
|
G27_1: if (scanouta_register = "UNREGISTERED" and chainout_adder /= "YES") generate
|
|
scanouta_reg <= mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
|
|
end generate G27_1;
|
|
|
|
G27_2: if ((scanouta_register = "UNREGISTERED" and chainout_adder = "YES") and (width_result <= width_a + width_b + 8))generate
|
|
scanouta_reg <= mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
|
|
end generate G27_2;
|
|
|
|
IFG113: if (scanouta_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, mult_a)
|
|
begin
|
|
if (((scanouta_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((scanouta_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((scanouta_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((scanouta_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
scanouta_reg <= (others => '0');
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
if (chainout_adder = "YES" and (width_result > width_a + width_b + 8)) then
|
|
scanouta_reg <= mult_a((number_of_multipliers * int_width_a) - 1 - (int_width_a - width_a) downto ((number_of_multipliers-1) * int_width_a));
|
|
else
|
|
scanouta_reg <= mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG113;
|
|
|
|
IFG114: if (scanouta_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, mult_a)
|
|
begin
|
|
if (((scanouta_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((scanouta_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((scanouta_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((scanouta_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
scanouta_reg <= (others => '0');
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
if (chainout_adder = "YES" and (width_result > width_a + width_b + 8)) then
|
|
scanouta_reg <= mult_a((number_of_multipliers * int_width_a) - 1 - (int_width_a - width_a) downto ((number_of_multipliers-1) * int_width_a));
|
|
else
|
|
scanouta_reg <= mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG114;
|
|
|
|
IFG115: if (scanouta_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, mult_a)
|
|
begin
|
|
if (((scanouta_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((scanouta_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((scanouta_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((scanouta_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
scanouta_reg <= (others => '0');
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
if (chainout_adder = "YES" and (width_result > width_a + width_b + 8)) then
|
|
scanouta_reg <= mult_a((number_of_multipliers * int_width_a) - 1 - (int_width_a - width_a) downto ((number_of_multipliers-1) * int_width_a));
|
|
else
|
|
scanouta_reg <= mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG115;
|
|
|
|
IFG116: if (scanouta_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, mult_a)
|
|
begin
|
|
if (((scanouta_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((scanouta_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((scanouta_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((scanouta_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
scanouta_reg <= (others => '0');
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
if (chainout_adder = "YES" and (width_result > width_a + width_b + 8)) then
|
|
scanouta_reg <= mult_a((number_of_multipliers * int_width_a) - 1 - (int_width_a - width_a) downto ((number_of_multipliers-1) * int_width_a));
|
|
else
|
|
scanouta_reg <= mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG116;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set zerochainout_reg)
|
|
-- The signal registered is zero_chainout
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if zero_chainout_output_register
|
|
-- is unregistered and zero_chainout changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G28 : if (zero_chainout_output_register = "UNREGISTERED") generate
|
|
zerochainout_reg <= zero_chainout;
|
|
end generate G28;
|
|
|
|
IFG117: if (zero_chainout_output_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, zero_chainout)
|
|
begin
|
|
if (((zero_chainout_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zerochainout_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
zerochainout_reg <= zero_chainout;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG117;
|
|
|
|
IFG118: if (zero_chainout_output_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, zero_chainout)
|
|
begin
|
|
if (((zero_chainout_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zerochainout_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
zerochainout_reg <= zero_chainout;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG118;
|
|
|
|
IFG119: if (zero_chainout_output_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, zero_chainout)
|
|
begin
|
|
if (((zero_chainout_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zerochainout_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
zerochainout_reg <= zero_chainout;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG119;
|
|
|
|
IFG120: if (zero_chainout_output_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, zero_chainout)
|
|
begin
|
|
if (((zero_chainout_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_chainout_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zerochainout_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
zerochainout_reg <= zero_chainout;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG120;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set rotate_reg)
|
|
-- The signal registered is rotate
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if rotate_register
|
|
-- is unregistered and rotate changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G29 : if (rotate_register = "UNREGISTERED") generate
|
|
rotate_reg <= rotate;
|
|
end generate G29;
|
|
|
|
IFG121: if (rotate_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, rotate)
|
|
begin
|
|
if (((rotate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
rotate_reg <= rotate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG121;
|
|
|
|
IFG122: if (rotate_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, rotate)
|
|
begin
|
|
if (((rotate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
rotate_reg <= rotate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG122;
|
|
|
|
IFG123: if (rotate_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, rotate)
|
|
begin
|
|
if (((rotate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
rotate_reg <= rotate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG123;
|
|
|
|
IFG124: if (rotate_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, rotate)
|
|
begin
|
|
if (((rotate_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
rotate_reg <= rotate;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG124;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set rotate_pipe)
|
|
-- The signal registered is rotate_reg
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if rotate_pipeline_register
|
|
-- is unregistered and rotate_reg changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G30 : if (rotate_pipeline_register = "UNREGISTERED") generate
|
|
rotate_pipe <= rotate_reg;
|
|
end generate G30;
|
|
|
|
IFG125: if (rotate_pipeline_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, rotate_reg)
|
|
begin
|
|
if (((rotate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
rotate_pipe <= rotate_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG125;
|
|
|
|
IFG126: if (rotate_pipeline_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, rotate_reg)
|
|
begin
|
|
if (((rotate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
rotate_pipe <= rotate_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG126;
|
|
|
|
IFG127: if (rotate_pipeline_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, rotate_reg)
|
|
begin
|
|
if (((rotate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
rotate_pipe <= rotate_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG127;
|
|
|
|
IFG128: if (rotate_pipeline_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, rotate_reg)
|
|
begin
|
|
if (((rotate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
rotate_pipe <= rotate_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG128;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set rotate_out)
|
|
-- The signal registered is rotate_pipe
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if rotate_output_register
|
|
-- is unregistered and rotate_pipe changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G31 : if (rotate_output_register = "UNREGISTERED") generate
|
|
rotate_out <= rotate_pipe;
|
|
end generate G31;
|
|
|
|
IFG129: if (rotate_output_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, rotate_out)
|
|
begin
|
|
if (((rotate_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_out <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
rotate_out <= rotate_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG129;
|
|
|
|
IFG130: if (rotate_output_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, rotate_out)
|
|
begin
|
|
if (((rotate_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_out <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
rotate_out <= rotate_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG130;
|
|
|
|
IFG131: if (rotate_output_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, rotate_out)
|
|
begin
|
|
if (((rotate_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_out <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
rotate_out <= rotate_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG131;
|
|
|
|
IFG132: if (rotate_output_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, rotate_out)
|
|
begin
|
|
if (((rotate_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((rotate_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((rotate_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((rotate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
rotate_out <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
rotate_out <= rotate_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG132;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set shiftr_reg)
|
|
-- The signal registered is shift_right
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if shift_right_register
|
|
-- is unregistered and shift_right changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G32 : if (shift_right_register = "UNREGISTERED") generate
|
|
shiftr_reg <= shift_right;
|
|
end generate G32;
|
|
|
|
IFG133: if (shift_right_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, shift_right)
|
|
begin
|
|
if (((shift_right_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
shiftr_reg <= shift_right;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG133;
|
|
|
|
IFG134: if (shift_right_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, shift_right)
|
|
begin
|
|
if (((shift_right_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
shiftr_reg <= shift_right;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG134;
|
|
|
|
IFG135: if (shift_right_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, shift_right)
|
|
begin
|
|
if (((shift_right_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
shiftr_reg <= shift_right;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG135;
|
|
|
|
IFG136: if (shift_right_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, shift_right)
|
|
begin
|
|
if (((shift_right_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
shiftr_reg <= shift_right;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG136;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set shiftr_pipe)
|
|
-- The signal registered is shiftr_reg
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if shift_right_pipeline_register
|
|
-- is unregistered and shiftr_reg changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G33 : if (shift_right_pipeline_register = "UNREGISTERED") generate
|
|
shiftr_pipe <= shiftr_reg;
|
|
end generate G33;
|
|
|
|
IFG137: if (shift_right_pipeline_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, shiftr_reg)
|
|
begin
|
|
if (((shift_right_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
shiftr_pipe <= shiftr_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG137;
|
|
|
|
IFG138: if (shift_right_pipeline_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, shiftr_reg)
|
|
begin
|
|
if (((shift_right_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
shiftr_pipe <= shiftr_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG138;
|
|
|
|
IFG139: if (shift_right_pipeline_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, shiftr_reg)
|
|
begin
|
|
if (((shift_right_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
shiftr_pipe <= shiftr_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG139;
|
|
|
|
IFG140: if (shift_right_pipeline_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, shiftr_reg)
|
|
begin
|
|
if (((shift_right_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
shiftr_pipe <= shiftr_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG140;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set shiftr_out)
|
|
-- The signal registered is shiftr_pipe
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if shift_right_output_register
|
|
-- is unregistered and shiftr_pipe changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G34 : if (shift_right_output_register = "UNREGISTERED") generate
|
|
shiftr_out <= shiftr_pipe;
|
|
end generate G34;
|
|
|
|
IFG141: if (shift_right_output_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, shiftr_pipe)
|
|
begin
|
|
if (((shift_right_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_out <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
shiftr_out <= shiftr_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG141;
|
|
|
|
IFG142: if (shift_right_output_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, shiftr_pipe)
|
|
begin
|
|
if (((shift_right_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_out <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
shiftr_out <= shiftr_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG142;
|
|
|
|
IFG143: if (shift_right_output_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, shiftr_pipe)
|
|
begin
|
|
if (((shift_right_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_out <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
shiftr_out <= shiftr_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG143;
|
|
|
|
IFG144: if (shift_right_output_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, shiftr_pipe)
|
|
begin
|
|
if (((shift_right_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((shift_right_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((shift_right_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((shift_right_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
shiftr_out <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
shiftr_out <= shiftr_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG144;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set zeroloopback_reg)
|
|
-- The signal registered is zero_loopback
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if zero_loopback_register
|
|
-- is unregistered and zero_loopback changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G35 : if (zero_loopback_register = "UNREGISTERED") generate
|
|
zeroloopback_reg <= zero_loopback;
|
|
end generate G35;
|
|
|
|
IFG145: if (zero_loopback_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, zero_loopback)
|
|
begin
|
|
if (((zero_loopback_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
zeroloopback_reg <= zero_loopback;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG145;
|
|
|
|
IFG146: if (zero_loopback_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, zero_loopback)
|
|
begin
|
|
if (((zero_loopback_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
zeroloopback_reg <= zero_loopback;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG146;
|
|
|
|
IFG147: if (zero_loopback_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, zero_loopback)
|
|
begin
|
|
if (((zero_loopback_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
zeroloopback_reg <= zero_loopback;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG147;
|
|
|
|
IFG148: if (zero_loopback_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, zero_loopback)
|
|
begin
|
|
if (((zero_loopback_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
zeroloopback_reg <= zero_loopback;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG148;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set zeroloopback_pipe)
|
|
-- The signal registered is zeroloopback_reg
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if zero_loopback_pipeline_register
|
|
-- is unregistered and zeroloopback_reg changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G36 : if (zero_loopback_pipeline_register = "UNREGISTERED") generate
|
|
zeroloopback_pipe <= zeroloopback_reg;
|
|
end generate G36;
|
|
|
|
IFG149: if (zero_loopback_pipeline_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, zeroloopback_reg)
|
|
begin
|
|
if (((zero_loopback_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
zeroloopback_pipe <= zeroloopback_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG149;
|
|
|
|
IFG150: if (zero_loopback_pipeline_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, zeroloopback_reg)
|
|
begin
|
|
if (((zero_loopback_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
zeroloopback_pipe <= zeroloopback_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG150;
|
|
|
|
IFG151: if (zero_loopback_pipeline_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, zeroloopback_reg)
|
|
begin
|
|
if (((zero_loopback_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
zeroloopback_pipe <= zeroloopback_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG151;
|
|
|
|
IFG152: if (zero_loopback_pipeline_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, zeroloopback_reg)
|
|
begin
|
|
if (((zero_loopback_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
zeroloopback_pipe <= zeroloopback_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG152;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set zeroloopback_out)
|
|
-- The signal registered is zeroloopback_pipe
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if zero_loopback_output_register
|
|
-- is unregistered and zeroloopback_pipe changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G37 : if (zero_loopback_output_register = "UNREGISTERED") generate
|
|
zeroloopback_out <= zeroloopback_pipe;
|
|
end generate G37;
|
|
|
|
IFG153: if (zero_loopback_output_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, zeroloopback_pipe)
|
|
begin
|
|
if (((zero_loopback_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_out <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
zeroloopback_out <= zeroloopback_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG153;
|
|
|
|
IFG154: if (zero_loopback_output_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, zeroloopback_pipe)
|
|
begin
|
|
if (((zero_loopback_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_out <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
zeroloopback_out <= zeroloopback_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG154;
|
|
|
|
IFG155: if (zero_loopback_output_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, zeroloopback_pipe)
|
|
begin
|
|
if (((zero_loopback_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_out <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
zeroloopback_out <= zeroloopback_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG155;
|
|
|
|
IFG156: if (zero_loopback_output_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, zeroloopback_pipe)
|
|
begin
|
|
if (((zero_loopback_output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((zero_loopback_output_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
zeroloopback_out <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
zeroloopback_out <= zeroloopback_pipe;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG156;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set accumsload_reg)
|
|
-- The signal registered is accum_sload
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if accum_sload_register
|
|
-- is unregistered and accum_sload changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G38 : if (accum_sload_register = "UNREGISTERED") generate
|
|
process (accum_sload, output_round)
|
|
begin
|
|
if ((accumulator = "YES") and (output_rounding = "VARIABLE") and (chainout_adder = "NO")) then
|
|
accumsload_reg <= output_round;
|
|
else
|
|
accumsload_reg <= accum_sload;
|
|
end if;
|
|
end process;
|
|
end generate G38;
|
|
|
|
IFG157: if (accum_sload_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, accum_sload)
|
|
begin
|
|
if (((accum_sload_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accumsload_reg <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
if ((accumulator = "YES") and (output_rounding = "VARIABLE") and (chainout_adder = "NO")) then
|
|
accumsload_reg <= output_round;
|
|
else
|
|
accumsload_reg <= accum_sload;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG157;
|
|
|
|
IFG158: if (accum_sload_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, accum_sload)
|
|
begin
|
|
if (((accum_sload_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accumsload_reg <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
if ((accumulator = "YES") and (output_rounding = "VARIABLE") and (chainout_adder = "NO")) then
|
|
accumsload_reg <= output_round;
|
|
else
|
|
accumsload_reg <= accum_sload;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG158;
|
|
|
|
IFG159: if (accum_sload_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, accum_sload)
|
|
begin
|
|
if (((accum_sload_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accumsload_reg <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
if ((accumulator = "YES") and (output_rounding = "VARIABLE") and (chainout_adder = "NO")) then
|
|
accumsload_reg <= output_round;
|
|
else
|
|
accumsload_reg <= accum_sload;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG159;
|
|
|
|
IFG160: if (accum_sload_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, accum_sload)
|
|
begin
|
|
if (((accum_sload_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accumsload_reg <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
if ((accumulator = "YES") and (output_rounding = "VARIABLE") and (chainout_adder = "NO")) then
|
|
accumsload_reg <= output_round;
|
|
else
|
|
accumsload_reg <= accum_sload;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG160;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set accumsload_pipe)
|
|
-- The signal registered is accumsload_reg
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if accum_sload_pipeline_register
|
|
-- is unregistered and accumsload_reg changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G39 : if (accum_sload_pipeline_register = "UNREGISTERED") generate
|
|
accumsload_pipe <= accumsload_reg;
|
|
end generate G39;
|
|
|
|
IFG161: if (accum_sload_pipeline_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, accumsload_reg)
|
|
begin
|
|
if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accumsload_pipe <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if (ena0 = '1') then
|
|
accumsload_pipe <= accumsload_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG161;
|
|
|
|
IFG162: if (accum_sload_pipeline_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, accumsload_reg)
|
|
begin
|
|
if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accumsload_pipe <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if (ena1 = '1') then
|
|
accumsload_pipe <= accumsload_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG162;
|
|
|
|
IFG163: if (accum_sload_pipeline_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, accumsload_reg)
|
|
begin
|
|
if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accumsload_pipe <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if (ena2 = '1') then
|
|
accumsload_pipe <= accumsload_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG163;
|
|
|
|
IFG164: if (accum_sload_pipeline_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, accumsload_reg)
|
|
begin
|
|
if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
accumsload_pipe <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if (ena3 = '1') then
|
|
accumsload_pipe <= accumsload_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG164;
|
|
|
|
---------------------------------------------------------------------------
|
|
|
|
process (clock0, clock1, clock2, clock3, aclr_vector, dataa_int, datab_int, scanina, scaninb, clock_vector, ena_vector,
|
|
aclr0, aclr1, aclr2, aclr3, sourcea_wire, sourceb_wire, tmp_mult_a, tmp_mult_b, feedback)
|
|
variable temp_clock : integer := 0;
|
|
variable temp_aclr : integer := 0;
|
|
variable x : integer := 0;
|
|
variable scanina_var : std_logic_vector (int_width_a -1 downto 0):= (others => '0');
|
|
variable scaninb_var : std_logic_vector (int_width_b -1 downto 0):= (others => '0');
|
|
variable mult_a_pre0 : std_logic_vector (4 * int_width_a -1 downto 0):= (others => '0');
|
|
variable mult_a_pre1 : std_logic_vector (4 * int_width_a -1 downto 0):= (others => '0');
|
|
variable mult_a_pre2 : std_logic_vector (4 * int_width_a -1 downto 0):= (others => '0');
|
|
variable mult_a_pre3 : std_logic_vector (4 * int_width_a -1 downto 0):= (others => '0');
|
|
variable mult_b_pre0 : std_logic_vector (4 * int_width_b -1 downto 0):= (others => '0');
|
|
variable mult_b_pre1 : std_logic_vector (4 * int_width_b -1 downto 0):= (others => '0');
|
|
variable mult_b_pre2 : std_logic_vector (4 * int_width_b -1 downto 0):= (others => '0');
|
|
variable mult_b_pre3 : std_logic_vector (4 * int_width_b -1 downto 0):= (others => '0');
|
|
variable mult1_source_scanin_en : std_logic := '0';
|
|
variable mult2_source_scanin_en : std_logic := '0';
|
|
variable mult3_source_scanin_en : std_logic := '0';
|
|
begin
|
|
scanina_var(int_width_a - 1 downto (int_width_a - width_a)) := scanina (width_a - 1 downto 0);
|
|
scaninb_var(int_width_b - 1 downto (int_width_b - width_b)) := scaninb (width_b - 1 downto 0);
|
|
|
|
--sets up all the clock, clock enable and clear signals for multiplier0
|
|
if not (multiplier_register0 = "UNREGISTERED") then
|
|
temp_clock := resolve_clock (multiplier_register0);
|
|
mult_clock(0) <= clock_vector (temp_clock);
|
|
mult_ena(0) <= ena_vector (temp_clock);
|
|
temp_aclr := resolve_aclr (multiplier_aclr0);
|
|
mult_aclr(0) <= aclr_vector (temp_aclr);
|
|
is_reg(0) <= '1';
|
|
end if;
|
|
|
|
--sets up all the clock, clock enable and clear signals for multiplier1
|
|
if not (multiplier_register1 = "UNREGISTERED") then
|
|
temp_clock := resolve_clock (multiplier_register1);
|
|
mult_clock(1) <= clock_vector (temp_clock);
|
|
mult_ena(1) <= ena_vector (temp_clock);
|
|
temp_aclr := resolve_aclr (multiplier_aclr1);
|
|
mult_aclr(1) <= aclr_vector (temp_aclr);
|
|
is_reg(1) <= '1';
|
|
end if;
|
|
|
|
--sets up all the clock, clock enable and clear signals for multiplier2
|
|
if not (multiplier_register2 = "UNREGISTERED") then
|
|
temp_clock := resolve_clock (multiplier_register2);
|
|
mult_clock(2) <= clock_vector (temp_clock);
|
|
mult_ena(2) <= ena_vector (temp_clock);
|
|
temp_aclr := resolve_aclr (multiplier_aclr2);
|
|
mult_aclr(2) <= aclr_vector (temp_aclr);
|
|
is_reg(2) <= '1';
|
|
end if;
|
|
|
|
--sets up all the clock, clock enable and clear signals for multiplier3
|
|
if not (multiplier_register3 = "UNREGISTERED") then
|
|
temp_clock := resolve_clock (multiplier_register3);
|
|
mult_clock(3) <= clock_vector (temp_clock);
|
|
mult_ena(3) <= ena_vector (temp_clock);
|
|
temp_aclr := resolve_aclr (multiplier_aclr3);
|
|
mult_aclr(3) <= aclr_vector (temp_aclr);
|
|
is_reg(3) <= '1';
|
|
end if;
|
|
|
|
|
|
-- ---------------------------------------------
|
|
-- SETTING UP THE DATA INPUT REGISTERS OF PORT A
|
|
-- ---------------------------------------------
|
|
|
|
-- -----------------
|
|
-- INPUT_REGISTER_A0
|
|
-- -----------------
|
|
|
|
-- set the initial value for mult_a_pre0 from dataa_int
|
|
if (input_source_a0 = "DATAA") then
|
|
mult_a_pre0 (int_width_a-1 downto 0) := dataa_int (int_width_a-1 downto 0);
|
|
elsif (input_source_a0 = "SCANA") then
|
|
if (stratixii_block) then
|
|
mult_a_pre0 (int_width_a-1 downto 0) := scanina_var;
|
|
else
|
|
mult_a_pre0 (int_width_a-1 downto 0) := dataa_int (int_width_a-1 downto 0);
|
|
end if;
|
|
else
|
|
if (sourcea_wire(0) = '1') then
|
|
mult_a_pre0 (int_width_a-1 downto 0) := scanina_var;
|
|
else
|
|
mult_a_pre0 (int_width_a-1 downto 0) := dataa_int (int_width_a-1 downto 0);
|
|
end if;
|
|
end if;
|
|
|
|
-- -----------------------------------------------------------------------------------
|
|
-- Clears mult_a and mult_a_pre1 (this is the next variable to be used by register_a1)
|
|
-- whenever clear signal is triggered
|
|
--
|
|
-- If clock is triggered or register is not used, assign mult_a to mult_a_pre0
|
|
--
|
|
-- Check make sure that register_a1 doesnt use the same clock as register_a0,
|
|
-- or if register_a0 is unregistered
|
|
-- If so, then update mult_a_pre1 with mult_a_pre0 to be used for register_a1
|
|
--
|
|
-- if nothing happens (ie. clock/clear is not triggered),
|
|
-- then update mult_a_pre1 with the current value of mult_a
|
|
-- -----------------------------------------------------------------------------------
|
|
if ((((input_aclr_a0 = "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_a0 = "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_a0 = "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_a0 = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (input_register_a0 = "UNREGISTERED"))) then
|
|
mult_a(int_width_a-1 downto 0) <= (others => '0');
|
|
mult_a_pre1(int_width_a-1 downto 0) := (others => '0');
|
|
elsif (((input_register_a0 = "CLOCK0") and rising_edge(clock0)) or
|
|
((input_register_a0 = "CLOCK1") and rising_edge(clock1)) or
|
|
((input_register_a0 = "CLOCK2") and rising_edge(clock2)) or
|
|
((input_register_a0 = "CLOCK3") and rising_edge(clock3)) or
|
|
(input_register_a0 = "UNREGISTERED")) then
|
|
if (((input_register_a0 = "CLOCK0") and (ena0 = '1')) or
|
|
((input_register_a0 = "CLOCK1") and (ena1 = '1')) or
|
|
((input_register_a0 = "CLOCK2") and (ena2 = '1')) or
|
|
((input_register_a0 = "CLOCK3") and (ena3 = '1')) or
|
|
(input_register_a0 = "UNREGISTERED")) then
|
|
mult_a (int_width_a-1 downto 0) <= mult_a_pre0 (int_width_a-1 downto 0);
|
|
if ((not(input_register_a0 = input_register_a1)) or (input_register_a0 = "UNREGISTERED")) then
|
|
mult_a_pre1 (int_width_a-1 downto 0) := mult_a_pre0 (int_width_a-1 downto 0);
|
|
end if;
|
|
end if;
|
|
else
|
|
mult_a_pre1 (int_width_a-1 downto 0) := tmp_mult_a (int_width_a-1 downto 0);
|
|
end if;
|
|
|
|
|
|
-- -----------------
|
|
-- INPUT_REGISTER_A1
|
|
-- -----------------
|
|
|
|
-- set the initial value for mult_a_pre1 from dataa_int if input source is from dataa
|
|
-- otherwise, load it from the mult_a_pre1 that stored the previous value from register_a0
|
|
if (input_source_a1 = "DATAA") then
|
|
if (mult1_source_scanin_en = '1') then
|
|
mult_a_pre1 ((2)*int_width_a-1 downto (int_width_a)) := mult_a_pre1(int_width_a-1 downto 0);
|
|
else
|
|
mult_a_pre1 ((2)*int_width_a-1 downto (int_width_a)) := dataa_int ((2)*int_width_a-1 downto (int_width_a));
|
|
end if;
|
|
elsif (input_source_a1 = "SCANA") then
|
|
mult_a_pre1 ((2)*int_width_a-1 downto (int_width_a)) := mult_a_pre1(int_width_a-1 downto 0);
|
|
else
|
|
if (sourcea_wire(1) = '1') then
|
|
mult_a_pre1 ((2)*int_width_a-1 downto (int_width_a)) := mult_a_pre1(int_width_a-1 downto 0);
|
|
else
|
|
mult_a_pre1 ((2)*int_width_a-1 downto (int_width_a)) := dataa_int ((2)*int_width_a-1 downto (int_width_a));
|
|
end if;
|
|
end if;
|
|
|
|
-- -----------------------------------------------------------------------------------
|
|
-- Clears mult_a and mult_a_pre2 (this is the next variable to be used by register_a2)
|
|
-- whenever clear signal is triggered
|
|
--
|
|
-- If clock is triggered or register is not used, assign mult_a to mult_a_pre1
|
|
--
|
|
-- Check make sure that register_a1 doesnt use the same clock as register_a2,
|
|
-- or if register_a1 is unregistered
|
|
-- If so, then update mult_a_pre2 with mult_a_pre1 to be used for register_a2
|
|
--
|
|
-- if nothing happens (ie. clock/clear is not triggered),
|
|
-- then update mult_a_pre2 with the current value of mult_a
|
|
-- -----------------------------------------------------------------------------------
|
|
if ((((input_aclr_a1 = "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_a1 = "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_a1 = "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_a1 = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (input_register_a1 = "UNREGISTERED"))) then
|
|
mult_a ((2)*int_width_a-1 downto (int_width_a)) <= (others => '0');
|
|
mult_a_pre2 ((2)*int_width_a-1 downto (int_width_a)) := (others => '0');
|
|
elsif (((input_register_a1 = "CLOCK0") and rising_edge(clock0)) or
|
|
((input_register_a1 = "CLOCK1") and rising_edge(clock1)) or
|
|
((input_register_a1 = "CLOCK2") and rising_edge(clock2)) or
|
|
((input_register_a1 = "CLOCK3") and rising_edge(clock3)) or
|
|
(input_register_a1 = "UNREGISTERED")) then
|
|
if (((input_register_a1 = "CLOCK0") and (ena0 = '1')) or
|
|
((input_register_a1 = "CLOCK1") and (ena1 = '1')) or
|
|
((input_register_a1 = "CLOCK2") and (ena2 = '1')) or
|
|
((input_register_a1 = "CLOCK3") and (ena3 = '1')) or
|
|
(input_register_a1 = "UNREGISTERED")) then
|
|
mult_a ((2)*int_width_a-1 downto (int_width_a)) <= mult_a_pre1 ((2)*int_width_a-1 downto int_width_a);
|
|
if ((not(input_register_a1 = input_register_a2)) or (input_register_a1 = "UNREGISTERED")) then
|
|
mult_a_pre2 ((2)*int_width_a-1 downto (int_width_a)) := mult_a_pre1 ((2)*int_width_a-1 downto int_width_a);
|
|
end if;
|
|
end if;
|
|
else
|
|
mult_a_pre2 ((2)*int_width_a-1 downto (int_width_a)) := tmp_mult_a ((2)*int_width_a-1 downto (int_width_a));
|
|
end if;
|
|
|
|
|
|
-- -----------------
|
|
-- INPUT_REGISTER_A2
|
|
-- -----------------
|
|
|
|
-- set the initial value for mult_a_pre2 from dataa_int if input source is from dataa
|
|
-- otherwise, load it from the mult_a_pre2 that stored the previous value from register_a1
|
|
if (input_source_a2 = "DATAA") then
|
|
if (mult2_source_scanin_en = '1') then
|
|
mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a)) := mult_a_pre2((2)*int_width_a-1 downto (int_width_a));
|
|
else
|
|
mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a)) := dataa_int ((3)*int_width_a-1 downto (2*int_width_a));
|
|
end if;
|
|
elsif (input_source_a2 = "SCANA") then
|
|
mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a)) := mult_a_pre2((2)*int_width_a-1 downto (int_width_a));
|
|
else
|
|
if (sourcea_wire(2) = '1') then
|
|
mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a)) := mult_a_pre2((2)*int_width_a-1 downto (int_width_a));
|
|
else
|
|
mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a)) := dataa_int ((3)*int_width_a-1 downto (2*int_width_a));
|
|
end if;
|
|
end if;
|
|
|
|
-- -----------------------------------------------------------------------------------
|
|
-- Clears mult_a and mult_a_pre3 (this is the next variable to be used by register_a3)
|
|
-- whenever clear signal is triggered
|
|
--
|
|
-- If clock is triggered or register is not used, assign mult_a to mult_a_pre2
|
|
--
|
|
-- Check make sure that register_a2 doesnt use the same clock as register_a3,
|
|
-- or if register_a2 is unregistered
|
|
-- If so, then update mult_a_pre3 with mult_a_pre2 to be used for register_a3
|
|
--
|
|
-- if nothing happens (ie. clock/clear is not triggered),
|
|
-- then update mult_a_pre3 with the current value of mult_a
|
|
-- -----------------------------------------------------------------------------------
|
|
if ((((input_aclr_a2 = "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_a2 = "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_a2 = "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_a2 = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (input_register_a2 = "UNREGISTERED"))) then
|
|
|
|
mult_a ((3)*int_width_a-1 downto (2*int_width_a)) <= (others => '0');
|
|
mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a)) := (others => '0');
|
|
|
|
elsif (((input_register_a2 = "CLOCK0") and rising_edge(clock0)) or
|
|
((input_register_a2 = "CLOCK1") and rising_edge(clock1)) or
|
|
((input_register_a2 = "CLOCK2") and rising_edge(clock2)) or
|
|
((input_register_a2 = "CLOCK3") and rising_edge(clock3)) or
|
|
(input_register_a2 = "UNREGISTERED")) then
|
|
if (((input_register_a2 = "CLOCK0") and (ena0 = '1')) or
|
|
((input_register_a2 = "CLOCK1") and (ena1 = '1')) or
|
|
((input_register_a2 = "CLOCK2") and (ena2 = '1')) or
|
|
((input_register_a2 = "CLOCK3") and (ena3 = '1')) or
|
|
(input_register_a2 = "UNREGISTERED")) then
|
|
|
|
mult_a ((3)*int_width_a-1 downto (2*int_width_a)) <= mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a));
|
|
|
|
if ((not(input_register_a2 = input_register_a3)) or (input_register_a2 = "UNREGISTERED")) then
|
|
mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a)) := mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a));
|
|
end if;
|
|
end if;
|
|
else
|
|
mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a)) := tmp_mult_a ((3)*int_width_a-1 downto (2*int_width_a));
|
|
end if;
|
|
|
|
|
|
-- -----------------
|
|
-- INPUT_REGISTER_A3
|
|
-- -----------------
|
|
|
|
-- set the initial value for mult_a_pre3 from dataa_int if input source is from dataa
|
|
-- otherwise, load it from the mult_a_pre3 that stored the previous value from register_a2
|
|
if (input_source_a3 = "DATAA") then
|
|
if (mult3_source_scanin_en = '1') then
|
|
mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a)) := mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a));
|
|
else
|
|
mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a)) := dataa_int ((4)*int_width_a-1 downto (3*int_width_a));
|
|
end if;
|
|
elsif (input_source_a3 = "SCANA") then
|
|
mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a)) := mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a));
|
|
else
|
|
if (sourcea_wire(3) = '1') then
|
|
mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a)) := mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a));
|
|
else
|
|
mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a)) := dataa_int ((4)*int_width_a-1 downto (3*int_width_a));
|
|
end if;
|
|
end if;
|
|
|
|
-- -----------------------------------------------------------------------------------
|
|
-- Clears mult_a whenever clear signal is triggered
|
|
-- If clock is triggered or register is not used, assign mult_a to mult_a_pre3
|
|
-- -----------------------------------------------------------------------------------
|
|
if ((((input_aclr_a3 = "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_a3 = "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_a3 = "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_a3 = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (input_register_a3 = "UNREGISTERED"))) then
|
|
mult_a ((4)*int_width_a-1 downto (3*int_width_a)) <= (others => '0');
|
|
elsif (((input_register_a3 = "CLOCK0") and rising_edge(clock0)) or
|
|
((input_register_a3 = "CLOCK1") and rising_edge(clock1)) or
|
|
((input_register_a3 = "CLOCK2") and rising_edge(clock2)) or
|
|
((input_register_a3 = "CLOCK3") and rising_edge(clock3)) or
|
|
(input_register_a3 = "UNREGISTERED")) then
|
|
if (((input_register_a3 = "CLOCK0") and (ena0 = '1')) or
|
|
((input_register_a3 = "CLOCK1") and (ena1 = '1')) or
|
|
((input_register_a3 = "CLOCK2") and (ena2 = '1')) or
|
|
((input_register_a3 = "CLOCK3") and (ena3 = '1')) or
|
|
(input_register_a3 = "UNREGISTERED")) then
|
|
mult_a ((4)*int_width_a-1 downto (3*int_width_a)) <= mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a));
|
|
|
|
end if;
|
|
end if;
|
|
|
|
|
|
-- ---------------------------------------------
|
|
-- SETTING UP THE DATA INPUT REGISTERS OF PORT B
|
|
-- ---------------------------------------------
|
|
|
|
-- -----------------
|
|
-- INPUT_REGISTER_B0
|
|
-- -----------------
|
|
|
|
-- set the initial value for mult_b_pre0 from datab_int
|
|
if (input_source_b0 = "DATAB") then
|
|
mult_b_pre0 (int_width_b-1 downto 0) := datab_int (int_width_b-1 downto 0);
|
|
elsif (input_source_b0 = "SCANB") then
|
|
if (stratixii_block) then
|
|
mult_b_pre0 (int_width_b-1 downto 0) := scaninb_var;
|
|
else
|
|
mult_b_pre0 (int_width_b-1 downto 0) := datab_int (int_width_b-1 downto 0);
|
|
end if;
|
|
elsif (stratixiii_block and (input_source_b0 = "LOOPBACK")) then
|
|
mult_b_pre0 (int_width_b - 1 downto 0) := feedback;
|
|
else
|
|
if (sourceb_wire(0) = '1') then
|
|
mult_b_pre0 (int_width_b-1 downto 0) := scaninb_var;
|
|
else
|
|
mult_b_pre0 (int_width_b-1 downto 0) := datab_int (int_width_b-1 downto 0);
|
|
end if;
|
|
end if;
|
|
|
|
-- -----------------------------------------------------------------------------------
|
|
-- Clears mult_b and mult_b_pre1 (this is the next variable to be used by register_b1)
|
|
-- whenever clear signal is triggered
|
|
--
|
|
-- If clock is triggered or register is not used, assign mult_b to mult_b_pre0
|
|
--
|
|
-- Check make sure that register_b1 doesnt use the same clock as register_b0,
|
|
-- or if register_b0 is unregistered
|
|
-- If so, then update mult_b_pre1 with mult_b_pre0 to be used for register_b1
|
|
--
|
|
-- if nothing happens (ie. clock/clear is not triggered),
|
|
-- then update mult_b_pre1 with the current value of mult_b
|
|
-- -----------------------------------------------------------------------------------
|
|
if ((((input_aclr_b0 = "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_b0 = "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_b0 = "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_b0 = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (input_register_b0 = "UNREGISTERED"))) then
|
|
mult_b (int_width_b-1 downto 0) <= (others => '0');
|
|
mult_b_pre1 (int_width_b-1 downto 0) := (others => '0');
|
|
elsif (((input_register_b0 = "CLOCK0") and rising_edge(clock0)) or
|
|
((input_register_b0 = "CLOCK1") and rising_edge(clock1)) or
|
|
((input_register_b0 = "CLOCK2") and rising_edge(clock2)) or
|
|
((input_register_b0 = "CLOCK3") and rising_edge(clock3)) or
|
|
(input_register_b0 = "UNREGISTERED")) then
|
|
if (((input_register_b0 = "CLOCK0") and (ena0 = '1')) or
|
|
((input_register_b0 = "CLOCK1") and (ena1 = '1')) or
|
|
((input_register_b0 = "CLOCK2") and (ena2 = '1')) or
|
|
((input_register_b0 = "CLOCK3") and (ena3 = '1')) or
|
|
(input_register_b0 = "UNREGISTERED")) then
|
|
mult_b (int_width_b-1 downto 0) <= mult_b_pre0 (int_width_b-1 downto 0);
|
|
if ((not(input_register_b0 = input_register_b1)) or (input_register_b0 = "UNREGISTERED")) then
|
|
mult_b_pre1 (int_width_b-1 downto 0) := mult_b_pre0 (int_width_b-1 downto 0);
|
|
end if;
|
|
end if;
|
|
else
|
|
mult_b_pre1 (int_width_b-1 downto 0) := tmp_mult_b (int_width_b-1 downto 0);
|
|
end if;
|
|
|
|
|
|
-- -----------------
|
|
-- INPUT_REGISTER_B1
|
|
-- -----------------
|
|
|
|
-- set the initial value for mult_b_pre1 from datab_int if input source is from datab
|
|
-- otherwise, load it from the mult_b_pre1 that stored the previous value from register_b0
|
|
if (input_source_b1 = "DATAB") then
|
|
-- if loopback mode is used, the data input for b1 comes from datab[width_b-1 to 0]
|
|
if (input_source_b0 = "LOOPBACK") then
|
|
mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := datab_int (int_width_b-1 downto 0);
|
|
else
|
|
mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := datab_int ((2)*int_width_b-1 downto (int_width_b));
|
|
end if;
|
|
elsif (input_source_b1 = "SCANB") then
|
|
if (mult1_source_scanin_en = '1') then
|
|
mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := datab_int ((2)*int_width_b-1 downto (int_width_b));
|
|
else
|
|
mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := mult_b_pre1 (int_width_b-1 downto 0);
|
|
end if;
|
|
else
|
|
if (sourceb_wire(1) = '1') then
|
|
mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := mult_b_pre1 (int_width_b-1 downto 0);
|
|
else
|
|
mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := datab_int ((2)*int_width_b-1 downto (int_width_b));
|
|
end if;
|
|
end if;
|
|
|
|
-- -----------------------------------------------------------------------------------
|
|
-- Clears mult_b and mult_b_pre2 (this is the next variable to be used by register_b2)
|
|
-- whenever clear signal is triggered
|
|
--
|
|
-- If clock is triggered or register is not used, assign mult_b to mult_b_pre1
|
|
--
|
|
-- Check make sure that register_a1 doesnt use the same clock as register_b2,
|
|
-- or if register_b1 is unregistered
|
|
-- If so, then update mult_b_pre2 with mult_b_pre1 to be used for register_b2
|
|
--
|
|
-- if nothing happens (ie. clock/clear is not triggered),
|
|
-- then update mult_b_pre2 with the current value of mult_b
|
|
-- -----------------------------------------------------------------------------------
|
|
if ((((input_aclr_b1 = "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_b1 = "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_b1 = "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_b1 = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (input_register_b1 = "UNREGISTERED"))) then
|
|
mult_b ((2)*int_width_b-1 downto (int_width_b)) <= (others => '0');
|
|
mult_b_pre2 ((2)*int_width_b-1 downto (int_width_b)) := (others => '0');
|
|
elsif (((input_register_b1 = "CLOCK0") and rising_edge(clock0)) or
|
|
((input_register_b1 = "CLOCK1") and rising_edge(clock1)) or
|
|
((input_register_b1 = "CLOCK2") and rising_edge(clock2)) or
|
|
((input_register_b1 = "CLOCK3") and rising_edge(clock3)) or
|
|
(input_register_b1 = "UNREGISTERED")) then
|
|
if (((input_register_b1 = "CLOCK0") and (ena0 = '1')) or
|
|
((input_register_b1 = "CLOCK1") and (ena1 = '1')) or
|
|
((input_register_b1 = "CLOCK2") and (ena2 = '1')) or
|
|
((input_register_b1 = "CLOCK3") and (ena3 = '1')) or
|
|
(input_register_b1 = "UNREGISTERED")) then
|
|
mult_b ((2)*int_width_b-1 downto (int_width_b)) <= mult_b_pre1 ((2)*int_width_b-1 downto int_width_b);
|
|
if ((not(input_register_b1 = input_register_b2)) or (input_register_b1 = "UNREGISTERED")) then
|
|
mult_b_pre2 ((2)*int_width_b-1 downto (int_width_b)) := mult_b_pre1 ((2)*int_width_b-1 downto int_width_b);
|
|
end if;
|
|
end if;
|
|
else
|
|
mult_b_pre2 ((2)*int_width_b-1 downto (int_width_b)) := tmp_mult_b ((2)*int_width_b-1 downto (int_width_b));
|
|
end if;
|
|
|
|
|
|
-- -----------------
|
|
-- INPUT_REGISTER_B2
|
|
-- -----------------
|
|
|
|
-- set the initial value for mult_b_pre2 from datab_int if input source is from datab
|
|
-- otherwise, load it from the mult_b_pre2 that stored the previous value from register_b1
|
|
if (input_source_b2 = "DATAB") then
|
|
if (input_source_b0 = "LOOPBACK") then
|
|
mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := datab_int ((2*int_width_b) -1 downto int_width_b);
|
|
else
|
|
mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := datab_int ((3)*int_width_b-1 downto (2*int_width_b));
|
|
end if;
|
|
elsif (input_source_b2 = "SCANB") then
|
|
if (mult2_source_scanin_en = '1') then
|
|
mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := datab_int ((3)*int_width_b-1 downto (2*int_width_b));
|
|
else
|
|
mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := mult_b_pre2 ((2)*int_width_b-1 downto (int_width_b));
|
|
end if;
|
|
else
|
|
if (sourceb_wire(2) = '1') then
|
|
mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := mult_b_pre2 ((2)*int_width_b-1 downto (int_width_b));
|
|
else
|
|
mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := datab_int ((3)*int_width_b-1 downto (2*int_width_b));
|
|
end if;
|
|
end if;
|
|
|
|
-- -----------------------------------------------------------------------------------
|
|
-- Clears mult_b and mult_b_pre3 (this is the next variable to be used by register_b3)
|
|
-- whenever clear signal is triggered
|
|
--
|
|
-- If clock is triggered or register is not used, assign mult_b to mult_b_pre2
|
|
--
|
|
-- Check make sure that register_b2 doesnt use the same clock as register_b3,
|
|
-- or if register_b2 is unregistered
|
|
-- If so, then update mult_b_pre3 with mult_b_pre2 to be used for register_b3
|
|
--
|
|
-- if nothing happens (ie. clock/clear is not triggered),
|
|
-- then update mult_b_pre3 with the current value of mult_b
|
|
-- -----------------------------------------------------------------------------------
|
|
if ((((input_aclr_b2 = "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_b2 = "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_b2 = "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_b2 = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (input_register_b2 = "UNREGISTERED"))) then
|
|
mult_b ((3)*int_width_b-1 downto (2*int_width_b)) <= (others => '0');
|
|
mult_b_pre3 ((3)*int_width_b-1 downto (2*int_width_b)) := (others => '0');
|
|
elsif (((input_register_b2 = "CLOCK0") and rising_edge(clock0)) or
|
|
((input_register_b2 = "CLOCK1") and rising_edge(clock1)) or
|
|
((input_register_b2 = "CLOCK2") and rising_edge(clock2)) or
|
|
((input_register_b2 = "CLOCK3") and rising_edge(clock3)) or
|
|
(input_register_b2 = "UNREGISTERED")) then
|
|
if (((input_register_b2 = "CLOCK0") and (ena0 = '1')) or
|
|
((input_register_b2 = "CLOCK1") and (ena1 = '1')) or
|
|
((input_register_b2 = "CLOCK2") and (ena2 = '1')) or
|
|
((input_register_b2 = "CLOCK3") and (ena3 = '1')) or
|
|
(input_register_b2 = "UNREGISTERED")) then
|
|
mult_b ((3)*int_width_b-1 downto (2*int_width_b)) <= mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b));
|
|
if ((not(input_register_b2 = input_register_b3)) or (input_register_b2 = "UNREGISTERED")) then
|
|
mult_b_pre3 ((3)*int_width_b-1 downto (2*int_width_b)) := mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b));
|
|
end if;
|
|
end if;
|
|
else
|
|
mult_b_pre3 ((3)*int_width_b-1 downto (2*int_width_b)) := tmp_mult_b ((3)*int_width_b-1 downto (2*int_width_b));
|
|
end if;
|
|
|
|
|
|
-- -----------------
|
|
-- INPUT_REGISTER_B3
|
|
-- -----------------
|
|
|
|
-- set the initial value for mult_b_pre3 from datab_int if input source is from datab
|
|
-- otherwise, load it from the mult_b_pre3 that stored the previous value from register_b2
|
|
if (input_source_b3 = "DATAB") then
|
|
if (input_source_b0 = "LOOPBACK") then
|
|
mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b)) := datab_int ((3)*int_width_b-1 downto (2*int_width_b));
|
|
else
|
|
mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b)) := datab_int ((4)*int_width_b-1 downto (3*int_width_b));
|
|
end if;
|
|
elsif (input_source_b3 = "SCANB") then
|
|
if (mult3_source_scanin_en = '1') then
|
|
mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b)) := datab_int ((4)*int_width_b-1 downto (3*int_width_b));
|
|
else
|
|
mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b)) := mult_b_pre3 ((3)*int_width_b-1 downto (2*int_width_b));
|
|
end if;
|
|
else
|
|
if (sourceb_wire(3) = '1') then
|
|
mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b)) := mult_b_pre3 ((3)*int_width_b-1 downto (2*int_width_b));
|
|
else
|
|
mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b)) := datab_int ((4)*int_width_b-1 downto (3*int_width_b));
|
|
end if;
|
|
end if;
|
|
|
|
-- -----------------------------------------------------------------------------------
|
|
-- Clears mult_b whenever clear signal is triggered
|
|
-- If clock is triggered or register is not used, assign mult_b to mult_b_pre3
|
|
-- -----------------------------------------------------------------------------------
|
|
if ((((input_aclr_b3 = "ACLR0") and (aclr0 = '1')) or
|
|
((input_aclr_b3 = "ACLR1") and (aclr1 = '1')) or
|
|
((input_aclr_b3 = "ACLR2") and (aclr2 = '1')) or
|
|
((input_aclr_b3 = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (input_register_b3 = "UNREGISTERED"))) then
|
|
mult_b ((4)*int_width_b-1 downto (3*int_width_b)) <= (others => '0');
|
|
elsif (((input_register_b3 = "CLOCK0") and rising_edge(clock0)) or
|
|
((input_register_b3 = "CLOCK1") and rising_edge(clock1)) or
|
|
((input_register_b3 = "CLOCK2") and rising_edge(clock2)) or
|
|
((input_register_b3 = "CLOCK3") and rising_edge(clock3)) or
|
|
(input_register_b3 = "UNREGISTERED")) then
|
|
if (((input_register_b3 = "CLOCK0") and (ena0 = '1')) or
|
|
((input_register_b3 = "CLOCK1") and (ena1 = '1')) or
|
|
((input_register_b3 = "CLOCK2") and (ena2 = '1')) or
|
|
((input_register_b3 = "CLOCK3") and (ena3 = '1')) or
|
|
(input_register_b3 = "UNREGISTERED")) then
|
|
mult_b ((4)*int_width_b-1 downto (3*int_width_b)) <= mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b));
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
-- -----------------------------------------------------------------------
|
|
-- This process block performs the rounding and saturation control signal
|
|
-- setting
|
|
-- -----------------------------------------------------------------------
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set mult01_round_wire)
|
|
-- The signal registered is mult01_round
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if mult01_round_register
|
|
-- is unregistered and mult01_round changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G9: if (mult01_round_register = "UNREGISTERED") generate
|
|
mult01_round_wire <= mult01_round;
|
|
end generate G9;
|
|
|
|
IFG41: if (mult01_round_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, mult01_round)
|
|
begin
|
|
if (((mult01_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult01_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult01_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult01_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult01_round_wire <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
mult01_round_wire <= mult01_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG41;
|
|
|
|
IFG42: if (mult01_round_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, mult01_round)
|
|
begin
|
|
if (((mult01_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult01_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult01_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult01_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult01_round_wire <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
mult01_round_wire <= mult01_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG42;
|
|
|
|
IFG43: if (mult01_round_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, mult01_round)
|
|
begin
|
|
if (((mult01_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult01_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult01_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult01_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult01_round_wire <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
mult01_round_wire <= mult01_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG43;
|
|
|
|
IFG44: if (mult01_round_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, mult01_round)
|
|
begin
|
|
if (((mult01_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult01_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult01_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult01_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult01_round_wire <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
mult01_round_wire <= mult01_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG44;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set mult01_saturate_wire)
|
|
-- The signal registered is mult01_saturation
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if mult01_saturate_register
|
|
-- is unregistered and mult01_saturation changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G10: if (mult01_saturation_register = "UNREGISTERED") generate
|
|
mult01_saturate_wire <= mult01_saturation;
|
|
end generate G10;
|
|
|
|
IFG45: if (mult01_saturation_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, mult01_saturation)
|
|
begin
|
|
if (((mult01_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult01_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult01_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult01_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult01_saturate_wire <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
mult01_saturate_wire <= mult01_saturation;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG45;
|
|
|
|
IFG46: if (mult01_saturation_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, mult01_saturation)
|
|
begin
|
|
if (((mult01_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult01_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult01_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult01_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult01_saturate_wire <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
mult01_saturate_wire <= mult01_saturation;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG46;
|
|
|
|
IFG47: if (mult01_saturation_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, mult01_saturation)
|
|
begin
|
|
if (((mult01_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult01_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult01_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult01_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult01_saturate_wire <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
mult01_saturate_wire <= mult01_saturation;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG47;
|
|
|
|
IFG48: if (mult01_saturation_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, mult01_saturation)
|
|
begin
|
|
if (((mult01_saturation_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult01_saturation_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult01_saturation_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult01_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult01_saturate_wire <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
mult01_saturate_wire <= mult01_saturation;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG48;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set mult23_round_wire)
|
|
-- The signal registered is mult23_round
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if mult23_round_register
|
|
-- is unregistered and mult23_round changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G11: if (mult23_round_register = "UNREGISTERED") generate
|
|
mult23_round_wire <= mult23_round;
|
|
end generate G11;
|
|
|
|
IFG49: if (mult23_round_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, mult23_round)
|
|
begin
|
|
if (((mult23_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult23_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult23_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult23_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult23_round_wire <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
mult23_round_wire <= mult23_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG49;
|
|
|
|
IFG50: if (mult23_round_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, mult23_round)
|
|
begin
|
|
if (((mult23_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult23_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult23_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult23_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult23_round_wire <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
mult23_round_wire <= mult23_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG50;
|
|
|
|
IFG51: if (mult23_round_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, mult23_round)
|
|
begin
|
|
if (((mult23_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult23_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult23_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult23_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult23_round_wire <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
mult23_round_wire <= mult23_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG51;
|
|
|
|
IFG52: if (mult23_round_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, mult23_round)
|
|
begin
|
|
if (((mult23_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult23_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult23_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult23_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult23_round_wire <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
mult23_round_wire <= mult23_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG52;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set mult23_saturate_wire)
|
|
-- The signal registered is mult23_saturation
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if mult23_saturate_register
|
|
-- is unregistered and mult23_saturation changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G12: if (mult23_saturation_register = "UNREGISTERED") generate
|
|
mult23_saturate_wire <= mult23_saturation;
|
|
end generate G12;
|
|
|
|
IFG53: if (mult23_saturation_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, mult23_saturation)
|
|
begin
|
|
if (((mult23_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult23_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult23_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult23_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult23_saturate_wire <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
mult23_saturate_wire <= mult23_saturation;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG53;
|
|
|
|
IFG54: if (mult23_saturation_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, mult23_saturation)
|
|
begin
|
|
if (((mult23_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult23_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult23_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult23_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult23_saturate_wire <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
mult23_saturate_wire <= mult23_saturation;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG54;
|
|
|
|
IFG55: if (mult23_saturation_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, mult23_saturation)
|
|
begin
|
|
if (((mult23_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((mult23_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((mult23_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((mult23_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
mult23_saturate_wire <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
mult23_saturate_wire <= mult23_saturation;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG55;
|
|
|
|
IFG56: if (mult23_saturation_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, mult23_saturation)
|
|
begin
|
|
if (((mult23_saturation_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((mult23_saturation_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((mult23_saturation_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((mult23_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
mult23_saturate_wire <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
mult23_saturate_wire <= mult23_saturation;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG56;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set addnsub1_round_wire)
|
|
-- The signal registered is addnsub1_round
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if addnsub1_round_register
|
|
-- is unregistered and addnsub1_round changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G13: if (addnsub1_round_register = "UNREGISTERED") generate
|
|
addnsub1_round_wire <= addnsub1_round;
|
|
end generate G13;
|
|
|
|
IFG57: if (addnsub1_round_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub1_round)
|
|
begin
|
|
if (((addnsub1_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub1_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub1_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub1_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub1_round_wire <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
addnsub1_round_wire <= addnsub1_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG57;
|
|
|
|
IFG58: if (addnsub1_round_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub1_round)
|
|
begin
|
|
if (((addnsub1_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub1_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub1_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub1_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub1_round_wire <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
addnsub1_round_wire <= addnsub1_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG58;
|
|
|
|
IFG59: if (addnsub1_round_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub1_round)
|
|
begin
|
|
if (((addnsub1_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub1_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub1_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub1_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub1_round_wire <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
addnsub1_round_wire <= addnsub1_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG59;
|
|
|
|
IFG60: if (addnsub1_round_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub1_round)
|
|
begin
|
|
if (((addnsub1_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub1_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub1_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub1_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub1_round_wire <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
addnsub1_round_wire <= addnsub1_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG60;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set addnsub1_round_pipe_wire)
|
|
-- The signal registered is addnsub1_round_wire
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if addnsub1_round_pipe_register
|
|
-- is unregistered and addnsub1_round_wire changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G14: if (addnsub1_round_pipeline_register = "UNREGISTERED") generate
|
|
addnsub1_round_pipe_wire <= addnsub1_round_wire;
|
|
end generate G14;
|
|
|
|
IFG61: if (addnsub1_round_pipeline_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub1_round_wire)
|
|
begin
|
|
if (((addnsub1_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub1_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub1_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub1_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub1_round_pipe_wire <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
addnsub1_round_pipe_wire <= addnsub1_round_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG61;
|
|
|
|
IFG62: if (addnsub1_round_pipeline_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub1_round_wire)
|
|
begin
|
|
if (((addnsub1_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub1_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub1_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub1_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub1_round_pipe_wire <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
addnsub1_round_pipe_wire <= addnsub1_round_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG62;
|
|
|
|
IFG63: if (addnsub1_round_pipeline_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub1_round_wire)
|
|
begin
|
|
if (((addnsub1_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub1_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub1_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub1_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub1_round_pipe_wire <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
addnsub1_round_pipe_wire <= addnsub1_round_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG63;
|
|
|
|
IFG64: if (addnsub1_round_pipeline_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub1_round_wire)
|
|
begin
|
|
if (((addnsub1_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub1_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub1_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub1_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub1_round_pipe_wire <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
addnsub1_round_pipe_wire <= addnsub1_round_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG64;
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set addnsub3_round_wire)
|
|
-- The signal registered is addnsub3_round
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if addnsub3_round_register
|
|
-- is unregistered and addnsub3_round changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
|
|
G15: if (addnsub3_round_register = "UNREGISTERED") generate
|
|
addnsub3_round_wire <= addnsub3_round;
|
|
end generate G15;
|
|
|
|
IFG65: if (addnsub3_round_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub3_round)
|
|
begin
|
|
if (((addnsub3_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub3_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub3_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub3_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub3_round_wire <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
addnsub3_round_wire <= addnsub3_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG65;
|
|
|
|
IFG66: if (addnsub3_round_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub3_round)
|
|
begin
|
|
if (((addnsub3_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub3_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub3_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub3_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub3_round_wire <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
addnsub3_round_wire <= addnsub3_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG66;
|
|
|
|
IFG67: if (addnsub3_round_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub3_round)
|
|
begin
|
|
if (((addnsub3_round_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub3_round_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub3_round_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub3_round_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub3_round_wire <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
addnsub3_round_wire <= addnsub3_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG67;
|
|
|
|
IFG68: if (addnsub3_round_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub3_round)
|
|
begin
|
|
if (((addnsub3_round_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub3_round_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub3_round_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub3_round_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub3_round_wire <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
addnsub3_round_wire <= addnsub3_round;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG68;
|
|
|
|
|
|
-- ---------------------------------------------------------------------------------
|
|
-- This statement contains 1 register and a combinatorial block (to set addnsub3_round_pipe_wire)
|
|
-- The signal registered is addnsub3_round_wire
|
|
--
|
|
-- The register has an asynchronous clear and a clock enable signal
|
|
-- NOTE: the combinatorial block is trigged if addnsub3_round_pipeline_register
|
|
-- is unregistered and addnsub3_round_wire changes value
|
|
-- ---------------------------------------------------------------------------------
|
|
G16: if (addnsub3_round_pipeline_register = "UNREGISTERED") generate
|
|
addnsub3_round_pipe_wire <= addnsub3_round_wire;
|
|
end generate G16;
|
|
|
|
IFG69: if (addnsub3_round_pipeline_register = "CLOCK0") generate
|
|
process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub3_round_wire)
|
|
begin
|
|
if (((addnsub3_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub3_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub3_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub3_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub3_round_pipe_wire <= '0';
|
|
elsif rising_edge(clock0) then
|
|
if ((ena0 ='1')) then
|
|
addnsub3_round_pipe_wire <= addnsub3_round_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG69;
|
|
|
|
IFG70: if (addnsub3_round_pipeline_register = "CLOCK1") generate
|
|
process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub3_round_wire)
|
|
begin
|
|
if (((addnsub3_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub3_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub3_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub3_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub3_round_pipe_wire <= '0';
|
|
elsif rising_edge(clock1) then
|
|
if ((ena1 ='1')) then
|
|
addnsub3_round_pipe_wire <= addnsub3_round_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG70;
|
|
|
|
IFG71: if (addnsub3_round_pipeline_register = "CLOCK2") generate
|
|
process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub3_round_wire)
|
|
begin
|
|
if (((addnsub3_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub3_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub3_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub3_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub3_round_pipe_wire <= '0';
|
|
elsif rising_edge(clock2) then
|
|
if ((ena2 ='1')) then
|
|
addnsub3_round_pipe_wire <= addnsub3_round_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG71;
|
|
|
|
IFG72: if (addnsub3_round_pipeline_register = "CLOCK3") generate
|
|
process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub3_round_wire)
|
|
begin
|
|
if (((addnsub3_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
|
|
((addnsub3_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
|
|
((addnsub3_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
|
|
((addnsub3_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
|
|
addnsub3_round_pipe_wire <= '0';
|
|
elsif rising_edge(clock3) then
|
|
if ((ena3 ='1')) then
|
|
addnsub3_round_pipe_wire <= addnsub3_round_wire;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG72;
|
|
|
|
|
|
-- -----------------------------------------------------------------------
|
|
-- This process block performs the multiplication of the two input numbers
|
|
-- -----------------------------------------------------------------------
|
|
process (clock0, clock1, clock2, clock3, mult_aclr, mult_a, mult_b, sign_a_reg, sign_b_reg,
|
|
mult01_round_wire, mult01_saturate_wire, mult23_round_wire, mult23_saturate_wire, mult_clock, is_reg, signa, signb)
|
|
variable mult_a_int : std_logic_vector (int_width_a -1 downto 0);
|
|
variable mult_b_int : std_logic_vector (int_width_b -1 downto 0);
|
|
variable mult_round_out : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
|
|
variable mult_result : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
|
|
variable mult_saturate_overflow : std_logic := '0';
|
|
variable mult_saturate_out : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
|
|
variable neg_a : std_logic := '0';
|
|
variable neg_b : std_logic := '0';
|
|
variable temp_mult_int : std_logic_vector ((int_width_a + int_width_b)-1 downto 0);
|
|
variable mux_clock : std_logic;
|
|
variable check_clock_out : string (1 to 6);
|
|
variable x : integer;
|
|
variable mult_round_bits : integer;
|
|
variable zero_pad : std_logic := '0';
|
|
variable is_rep_a_sign : std_logic := '1';
|
|
variable is_rep_b_sign : std_logic := '1';
|
|
begin
|
|
|
|
if (((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or (sign_a_reg = '1'))) or
|
|
((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"))) then
|
|
is_rep_a_sign := '1';
|
|
else
|
|
is_rep_a_sign := '0';
|
|
end if;
|
|
|
|
if (((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or (sign_b_reg = '1'))) or
|
|
((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"))) then
|
|
is_rep_b_sign := '1';
|
|
else
|
|
is_rep_b_sign := '0';
|
|
end if;
|
|
|
|
for i in 0 to (number_of_multipliers -1) loop
|
|
x := i;
|
|
|
|
if (i > 3) then
|
|
x := 3;
|
|
end if;
|
|
|
|
mux_clock := mult_clock (x);
|
|
check_clock_out := check_clock (x);
|
|
|
|
if ((not stratixiii_block) and
|
|
((is_reg (x) = '1') and (mult_aclr (x) = '1'))) then
|
|
mult_res ( ((i+1)*(int_width_a + int_width_b)) - 1 downto (i*(int_width_a + int_width_b))) <= (others => '0');
|
|
mult_is_saturated(x) <= '0';
|
|
elsif ((not stratixiii_block) and
|
|
(((check_clock_out = "CLOCK0") and rising_edge(clock0)) or
|
|
((check_clock_out = "CLOCK1") and rising_edge(clock1)) or
|
|
((check_clock_out = "CLOCK2") and rising_edge(clock2)) or
|
|
((check_clock_out = "CLOCK3") and rising_edge(clock3)) or
|
|
(is_reg (x) = '0'))) or
|
|
(stratixiii_block) then
|
|
|
|
if ((not stratixiii_block) and
|
|
(((check_clock_out = "CLOCK0") and (ena0 = '1')) or
|
|
((check_clock_out = "CLOCK1") and (ena1 = '1')) or
|
|
((check_clock_out = "CLOCK2") and (ena2 = '1')) or
|
|
((check_clock_out = "CLOCK3") and (ena3 = '1')) or
|
|
is_reg (x) = '0')) or
|
|
(stratixiii_block) then
|
|
neg_a := '0';
|
|
neg_b := '0';
|
|
|
|
-- check if mult_a is to be interpreted as negative
|
|
if (is_rep_a_sign = '1') then
|
|
neg_a := mult_a ( (i+1)*int_width_a-1);
|
|
end if;
|
|
|
|
-- check if mult_b is to be interpreted as negative
|
|
if (is_rep_b_sign = '1') then
|
|
if (input_source_b0 = "LOOPBACK" and i=1) then
|
|
neg_b := mult_b ( (i+1)*int_width_b-1 );-- + (int_width_b - width_b));
|
|
else
|
|
neg_b := mult_b ( (i+1)*int_width_b-1);
|
|
end if;
|
|
end if;
|
|
|
|
-- perform 2's complement if mult_a is negative
|
|
if (neg_a ='1') then
|
|
mult_a_int := unsigned (not mult_a ( (i+1)*int_width_a-1 downto (i*int_width_a))) + 1;
|
|
else
|
|
mult_a_int := mult_a ( (i+1)*int_width_a-1 downto (i*int_width_a));
|
|
end if;
|
|
|
|
-- perform 2's complement if mult_b is negative
|
|
if (neg_b ='1') then
|
|
if(input_source_b0 = "LOOPBACK" and i=1) then
|
|
mult_b_int(width_b - 1 downto 0) := unsigned (not mult_b ( (i+1)*int_width_b-1 downto (i*int_width_b + (int_width_b - width_b)))) + 1;
|
|
else
|
|
mult_b_int := unsigned (not mult_b ( (i+1)*int_width_b-1 downto (i*int_width_b))) + 1;
|
|
end if;
|
|
else
|
|
if(input_source_b0 = "LOOPBACK" and i=1) then
|
|
mult_b_int := mult_b ( (i+1)*int_width_b-1 + (int_width_b - width_b) downto (i*int_width_b + (int_width_b - width_b)));
|
|
else
|
|
mult_b_int := mult_b ( (i+1)*int_width_b-1 downto (i*int_width_b));
|
|
end if;
|
|
end if;
|
|
-- perform multiplication
|
|
temp_mult_int := unsigned (temp_mult_zero) + unsigned(mult_a_int) * unsigned(mult_b_int);
|
|
|
|
-- determining if the result should be a negative number
|
|
-- based on the 2 input numbers
|
|
if ((neg_a xor neg_b) = '1') then
|
|
temp_mult_int := unsigned(temp_mult_zero) - unsigned(temp_mult_int);
|
|
end if;
|
|
|
|
if (stratixii_block) then
|
|
-- -------------------------------------------------------
|
|
-- Stratix II Rounding support
|
|
-- This block basically carries out the rounding for the
|
|
-- temp_mult_int. The equation to get the mult_round_out is
|
|
-- obtained from the Stratix II Mac FFD which is below:
|
|
-- round_adder_constant = (1 << (wfraction - wfraction_round - 1))
|
|
-- roundout[] = datain[] + round_adder_constant
|
|
-- For Stratix II rounding, we round up the bits to 15 bits
|
|
-- or in another word wfraction_round = 15. The sign bits would be 2 bits
|
|
-- --------------------------------------------------------
|
|
|
|
if ((((x = 0) or (x = 1)) and ((multiplier01_rounding = "YES") or
|
|
((multiplier01_rounding = "VARIABLE") and (mult01_round_wire = '1')))) or
|
|
(((x = 2) or (x = 3)) and ((multiplier23_rounding = "YES") or
|
|
((multiplier23_rounding = "VARIABLE") and (mult23_round_wire = '1')))))
|
|
then
|
|
-- Here the value 17 is from the 2 bits of sign and the rounding for 15 bits
|
|
mult_round_bits := (int_width_a + int_width_b) - 17;
|
|
mult_round_out := unsigned (temp_mult_int) + ( 2 ** (mult_round_bits - 1));
|
|
else
|
|
mult_round_out := temp_mult_int;
|
|
end if;
|
|
|
|
-- -------------------------------------------------------
|
|
-- Stratix II Saturation support
|
|
-- This carries out the saturation for mult_round_out.
|
|
-- The equation to get the saturated result is obtained
|
|
-- from Stratix II MAC FFD which is below:
|
|
-- satoverflow = 1 if sign bit is different
|
|
-- satvalue[wtotal-1 : wfraction] = roundout[wtotal-1]
|
|
-- satvalue[wfraction-1 : 0] = !roundout[wtotal-1]
|
|
-- -------------------------------------------------------
|
|
|
|
if ((((x = 0) or (x = 1)) and ((multiplier01_saturation = "YES") or
|
|
(( multiplier01_saturation = "VARIABLE") and (mult01_saturate_wire = '1')))) or
|
|
(((x = 2) or (x = 3)) and ((multiplier23_saturation = "YES") or
|
|
(( multiplier23_saturation = "VARIABLE") and (mult23_saturate_wire = '1')))))
|
|
then
|
|
mult_saturate_overflow := (not mult_round_out(int_width_a + int_width_b - 1)) and (mult_round_out(int_width_a + int_width_b - 2));
|
|
|
|
if (mult_saturate_overflow = '0') then
|
|
mult_saturate_out := mult_round_out;
|
|
mult_is_saturated(x) <= mult_round_out(0);
|
|
else
|
|
-- We are doing the Q2.31 saturation, thus there is a bit
|
|
-- insertion over here
|
|
for i in (int_width_a + int_width_b - 1) downto (int_width_a + int_width_b - 2) loop
|
|
mult_saturate_out(i) := mult_round_out(int_width_a + int_width_b - 1);
|
|
end loop;
|
|
|
|
for i in (int_width_a + int_width_b - 3) downto 3 loop
|
|
mult_saturate_out(i) := not mult_round_out(int_width_a + int_width_b - 1);
|
|
end loop;
|
|
|
|
mult_saturate_out(2 downto 0) := mult_round_out(2 downto 0);
|
|
mult_is_saturated(x) <= mult_saturate_overflow;
|
|
end if;
|
|
else
|
|
mult_is_saturated(x) <= mult_saturate_overflow;
|
|
mult_saturate_out := mult_round_out;
|
|
end if;
|
|
|
|
if ((((x = 0) or (x = 1)) and ((multiplier01_rounding = "YES") or
|
|
(( multiplier01_rounding = "VARIABLE") and (mult01_round_wire = '1')))) or
|
|
(((x = 2) or (x = 3)) and ((multiplier23_rounding = "YES") or
|
|
(( multiplier23_rounding = "VARIABLE") and (mult23_round_wire = '1')))))
|
|
then
|
|
mult_result := mult_saturate_out;
|
|
|
|
for i in (mult_round_bits - 1) downto 0 loop
|
|
mult_result(i) := '0';
|
|
end loop;
|
|
|
|
else
|
|
mult_result := mult_saturate_out;
|
|
end if;
|
|
else
|
|
mult_result := temp_mult_int;
|
|
end if;
|
|
|
|
mult_res ( ((i+1)*(int_width_a + int_width_b)) - 1 downto (i*(int_width_a + int_width_b)) ) <= mult_result;
|
|
end if;
|
|
|
|
end if;
|
|
end loop;
|
|
end process;
|
|
|
|
-- -----------------------------------------------------------------
|
|
-- This is the main block that performs the addition and subtraction
|
|
-- -----------------------------------------------------------------
|
|
IFGFAM0: if (not stratixiii_block) generate
|
|
process (clock0, clock1, clock2, clock3,
|
|
aclr0, aclr1, aclr2, aclr3,
|
|
mult_res, sign_a_reg, sign_b_reg, sign_a_pipe, sign_b_pipe,
|
|
addsub_pipe1, addsub_pipe3, addsub_reg1, addsub_reg3, addnsub1_round_pipe_wire,
|
|
addnsub3_round_pipe_wire, mult_is_saturated)
|
|
variable head_result_int : integer := 0;
|
|
variable do_add : boolean;
|
|
variable asign : boolean;
|
|
variable bsign : boolean;
|
|
variable temp_sum : std_logic_vector (int_width_a + int_width_b + int_width_result downto 0) := (others => '0');
|
|
variable mult_res_temp : std_logic_vector ((int_width_a + int_width_b - 1) downto 0);
|
|
variable mult_res_ext : std_logic_vector (int_width_result-1 downto 0);
|
|
variable adder_round_bits: integer;
|
|
variable adder_result : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
variable adder1_result : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
variable adder3_result : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
variable adder_final_out : std_logic_vector (2*int_width_result - 1 downto 0) := (others => '0');
|
|
variable adder_round_out : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
variable is_rep_a_sign : boolean;
|
|
variable is_rep_b_sign : boolean;
|
|
variable is_rep_a_pipe_sign : boolean;
|
|
variable is_rep_b_pipe_sign : boolean;
|
|
variable is_adder1_add : boolean;
|
|
variable is_adder3_add : boolean;
|
|
variable is_adder1_pipe_add : boolean;
|
|
variable is_adder3_pipe_add : boolean;
|
|
variable result_temp : std_logic_vector (width_result - 1 downto 0) := (others => '0');
|
|
variable result_ext : std_logic_vector (width_result - 1 downto 0) := (others => '0');
|
|
variable result_pipe : pipeline_accum := (others => (others => '0'));
|
|
|
|
begin
|
|
|
|
if ((((output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_aclr = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (output_register = "UNREGISTERED"))) then
|
|
temp_sum := (others => '0');
|
|
result_pipe := (others => (others => '0'));
|
|
result <= (others => '0');
|
|
mult_is_saturated_pipe <= (others => '0');
|
|
|
|
elsif (((output_register = "CLOCK0") and rising_edge(clock0) and (ena0 = '1')) or
|
|
((output_register = "CLOCK1") and rising_edge(clock1) and (ena1 = '1')) or
|
|
((output_register = "CLOCK2") and rising_edge(clock2) and (ena2 = '1')) or
|
|
((output_register = "CLOCK3") and rising_edge(clock3) and (ena3 = '1')) or
|
|
(output_register = "UNREGISTERED")) then
|
|
if (((output_register = "CLOCK0") and (ena0 = '1')) or
|
|
((output_register = "CLOCK1") and (ena1 = '1')) or
|
|
((output_register = "CLOCK2") and (ena2 = '1')) or
|
|
((output_register = "CLOCK3") and (ena3 = '1')) or
|
|
(output_register = "UNREGISTERED")) then
|
|
temp_sum := (others => '0');
|
|
|
|
is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
is_adder1_add := ((port_addnsub1 = "PORT_CONNECTIVITY") and (((multiplier1_direction = "ADD") and (addnsub1 = 'Z')) or
|
|
(addsub_reg1 = '1'))) or ((port_addnsub1 = "PORT_USED") and (addsub_reg1 = '1')) or
|
|
((port_addnsub1 = "PORT_UNUSED") and (multiplier1_direction = "ADD"));
|
|
|
|
is_adder3_add := ((port_addnsub3 = "PORT_CONNECTIVITY") and (((multiplier3_direction = "ADD") and (addnsub3 = 'Z')) or
|
|
(addsub_reg3 = '1'))) or ((port_addnsub3 = "PORT_USED") and (addsub_reg3 = '1')) or
|
|
((port_addnsub3 = "PORT_UNUSED") and (multiplier3_direction = "ADD"));
|
|
|
|
|
|
is_adder1_pipe_add := ((port_addnsub1 = "PORT_CONNECTIVITY") and (((multiplier1_direction = "ADD") and (addnsub1 = 'Z')) or
|
|
(addsub_pipe1 = '1'))) or ((port_addnsub1 = "PORT_USED") and (addsub_pipe1 = '1')) or
|
|
((port_addnsub1 = "PORT_UNUSED") and (multiplier1_direction = "ADD"));
|
|
|
|
is_adder3_pipe_add := ((port_addnsub3 = "PORT_CONNECTIVITY") and (((multiplier3_direction = "ADD") and (addnsub3 = 'Z')) or
|
|
(addsub_pipe3 = '1'))) or ((port_addnsub3 = "PORT_USED") and (addsub_pipe3 = '1')) or
|
|
((port_addnsub3 = "PORT_UNUSED") and (multiplier3_direction = "ADD"));
|
|
|
|
|
|
for i in 0 to (number_of_multipliers -1) loop
|
|
|
|
-- use addsub_reg instead of addsub_pipe if
|
|
-- addnsub_multiplier_pipeline_register is unregistered
|
|
-- to determine the do_add flag
|
|
if ((addnsub_multiplier_pipeline_register1 = "UNREGISTERED") and
|
|
(addnsub_multiplier_pipeline_register3 = "UNREGISTERED"))then
|
|
if (((i = 1) and (is_adder1_add)) or
|
|
((i = 3) and (is_adder3_add)) or
|
|
(i = 0) or
|
|
(i = 2) or
|
|
(i > 3)) then
|
|
do_add := true;
|
|
else
|
|
do_add := false;
|
|
end if;
|
|
elsif ((addnsub_multiplier_pipeline_register1 = "UNREGISTERED") and
|
|
(not (addnsub_multiplier_pipeline_register3 = "UNREGISTERED")))then
|
|
if (((i = 1) and (is_adder1_add)) or
|
|
((i = 3) and (is_adder3_pipe_add)) or
|
|
(i = 0) or
|
|
(i = 2) or
|
|
(i > 3)) then
|
|
do_add := true;
|
|
else
|
|
do_add := false;
|
|
end if;
|
|
elsif ((not (addnsub_multiplier_pipeline_register1 = "UNREGISTERED")) and
|
|
(addnsub_multiplier_pipeline_register3 = "UNREGISTERED")) then
|
|
if (((i = 1) and (is_adder1_pipe_add)) or
|
|
((i = 3) and (is_adder3_add)) or
|
|
(i = 0) or
|
|
(i = 2) or
|
|
(i > 3)) then
|
|
do_add := true;
|
|
else
|
|
do_add := false;
|
|
end if;
|
|
else
|
|
if (((i = 1) and (is_adder1_pipe_add)) or
|
|
((i = 3) and (is_adder3_pipe_add)) or
|
|
(i = 0) or
|
|
(i = 2) or
|
|
(i > 3)) then
|
|
do_add := true;
|
|
else
|
|
do_add := false;
|
|
end if;
|
|
end if;
|
|
|
|
mult_res_temp := mult_res( ((i+1)*(int_width_a + int_width_b) - 1) downto (i*(int_width_a + int_width_b)));
|
|
|
|
-- Use sign_a_reg instead of sign_a_pipe when
|
|
-- signed_pipeline_register_a is unregistered
|
|
-- to set the asign flag
|
|
if (signed_pipeline_register_a = "UNREGISTERED") then
|
|
if (is_rep_a_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_a_pipe_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
end if;
|
|
|
|
-- Use sign_b_reg instead of sign_b_pipe when
|
|
-- signed_pipeline_register_b is unregistered
|
|
-- to set the bsign flag
|
|
if (signed_pipeline_register_b = "UNREGISTERED") then
|
|
if (is_rep_b_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_b_pipe_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
end if;
|
|
|
|
-- perform addition/subrtaction based on the do_add flag
|
|
if (do_add = true) then
|
|
if ((asign = true) or (bsign = true)) then
|
|
temp_sum := signed (temp_sum) + signed(mult_res_temp);
|
|
else
|
|
temp_sum := unsigned (temp_sum) + unsigned(mult_res_temp);
|
|
end if;
|
|
else
|
|
if ((asign = true) or (bsign = true)) then
|
|
temp_sum := signed (temp_sum) - signed(mult_res_temp);
|
|
else
|
|
temp_sum := unsigned (temp_sum) - unsigned(mult_res_temp);
|
|
end if;
|
|
end if;
|
|
|
|
if (stratixii_block) then
|
|
-- -------------------------------------------------------
|
|
-- Stratix II Rounding support
|
|
-- This block basically carries out the rounding for the
|
|
-- temp_sum. The equation to get the adder_round_out is
|
|
-- obtained from the Stratix II Mac FFD which is below:
|
|
-- round_adder_constant = (1 << (wfraction - wfraction_round - 1))
|
|
-- roundout[] = datain[] + round_adder_constant
|
|
-- For Stratix II rounding, we round up the bits to 15 bits
|
|
-- or in another word wfraction_round = 15.
|
|
-- --------------------------------------------------------
|
|
|
|
if (((i = 1) and ((adder1_rounding = "YES") or
|
|
((adder1_rounding = "VARIABLE") and (addnsub1_round_pipe_wire = '1')))) or
|
|
((i = 2) and (number_of_multipliers = 3) and ((adder3_rounding = "YES") or
|
|
((adder3_rounding = "VARIABLE") and (addnsub3_round_pipe_wire = '1')))) or
|
|
((i = 3) and ((adder3_rounding = "YES") or
|
|
((adder3_rounding = "VARIABLE") and (addnsub3_round_pipe_wire = '1')))))
|
|
then
|
|
|
|
-- Here the value 17 is from the 2 bits of sign and the rounding for 15 bits
|
|
|
|
adder_round_bits := (int_width_a + int_width_b) - 17;
|
|
adder_round_out := signed (temp_sum(int_width_result downto 0)) + ( 2 ** (adder_round_bits - 1));
|
|
|
|
for j in (adder_round_bits - 1) downto 0 loop
|
|
adder_round_out(j) := '0';
|
|
end loop;
|
|
|
|
--adder_result := adder_round_out;
|
|
|
|
if ((i=2) or (i=3)) then
|
|
for j in (int_width_result - 1) downto 0 loop
|
|
temp_sum(j) := adder_round_out(j);
|
|
end loop;
|
|
end if;
|
|
|
|
else
|
|
adder_round_out := temp_sum(int_width_result downto 0);
|
|
|
|
end if;
|
|
|
|
if (i = 0) then
|
|
adder_result := adder_round_out;
|
|
end if;
|
|
|
|
if (i = 1) then
|
|
adder1_result := adder_round_out;
|
|
adder_result := adder1_result;
|
|
temp_sum := (others => '0');
|
|
end if;
|
|
|
|
if ((i=2) or (i=3))then
|
|
adder3_result := adder_round_out;
|
|
if ((asign = true) or (bsign = true)) then
|
|
adder_result := signed (adder3_result) + signed(adder1_result);
|
|
else
|
|
adder_result := unsigned (adder3_result) + unsigned(adder1_result);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (not stratixii_block) then
|
|
adder_final_out(int_width_result - 1 downto 0) := temp_sum(int_width_result - 1 downto 0);
|
|
adder_final_out(2*int_width_result - 1 downto int_width_result) := (others => temp_sum(int_width_result -1));
|
|
|
|
else
|
|
adder_final_out(int_width_result - 1 downto 0) := adder_result(int_width_result - 1 downto 0);
|
|
adder_final_out(2*int_width_result - 1 downto int_width_result) := (others => adder_result(int_width_result));
|
|
end if;
|
|
|
|
end loop; -- for i in 0 to (number_of_multipliers -1) loop
|
|
|
|
mult_is_saturated_pipe <= mult_is_saturated;
|
|
|
|
if (extra_latency = 0) then
|
|
result_temp := adder_final_out((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
|
|
|
|
-- need to extend the MSB for cases where width_result is larger than width_a + width_b
|
|
|
|
if ((number_of_multipliers = 1) and (width_result > width_a + width_b)) then
|
|
if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
|
|
for res_cnt in 1 to (width_result - width_a - width_b) loop
|
|
result_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - width_a - width_b) loop
|
|
result_ext(width_result - res_cnt) := result_temp(width_a + width_b - 1);
|
|
end loop;
|
|
end if;
|
|
result_ext(width_a + width_b - 1 downto 0) := result_temp(width_a + width_b - 1 downto 0);
|
|
elsif ((number_of_multipliers = 2) and (width_result > width_a + width_b + 1)) then
|
|
if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
|
|
result_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
|
|
result_ext(width_result - res_cnt) := result_temp(width_a + width_b);
|
|
end loop;
|
|
end if;
|
|
result_ext(width_a + width_b downto 0) := result_temp(width_a + width_b downto 0);
|
|
elsif ((number_of_multipliers > 2) and (width_result > width_a + width_b + 2)) then
|
|
if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
|
|
result_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
|
|
result_ext(width_result - res_cnt) := result_temp(width_a + width_b + 1);
|
|
end loop;
|
|
end if;
|
|
result_ext(width_a + width_b + 1 downto 0) := result_temp(width_a + width_b + 1 downto 0);
|
|
else
|
|
result_ext(width_result - 1 downto 0) := result_temp(width_result - 1 downto 0);
|
|
end if;
|
|
|
|
result <= result_ext;
|
|
|
|
else
|
|
result_temp := adder_final_out((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
|
|
|
|
if ((number_of_multipliers = 1) and (width_result > width_a + width_b)) then
|
|
if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
|
|
for res_cnt in 1 to (width_result - width_a - width_b) loop
|
|
result_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - width_a - width_b) loop
|
|
result_ext(width_result - res_cnt) := result_temp(width_a + width_b - 1);
|
|
end loop;
|
|
end if;
|
|
result_ext(width_a + width_b - 1 downto 0) := result_temp(width_a + width_b - 1 downto 0);
|
|
elsif ((number_of_multipliers = 2) and (width_result > width_a + width_b + 1)) then
|
|
if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
|
|
result_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
|
|
result_ext(width_result - res_cnt) := result_temp(width_a + width_b);
|
|
end loop;
|
|
end if;
|
|
result_ext(width_a + width_b downto 0) := result_temp(width_a + width_b downto 0);
|
|
elsif ((number_of_multipliers > 2) and (width_result > width_a + width_b + 2)) then
|
|
if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
|
|
result_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
|
|
result_ext(width_result - res_cnt) := result_temp(width_a + width_b + 1);
|
|
end loop;
|
|
end if;
|
|
result_ext(width_a + width_b + 1 downto 0) := result_temp(width_a + width_b + 1 downto 0);
|
|
else
|
|
result_ext(width_result - 1 downto 0) := result_temp(width_result - 1 downto 0);
|
|
end if;
|
|
|
|
head_result_int := head_result;
|
|
result_pipe (head_result_int) := adder_final_out(width_result - 1 downto 0);
|
|
head_result_int := (head_result_int +1) mod (extra_latency + 1);
|
|
result <= result_pipe(head_result_int);
|
|
head_result <= head_result_int;
|
|
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFGFAM0;
|
|
|
|
process (mult_is_saturated_pipe)
|
|
begin
|
|
-- We also need to update the multpilier saturated port. The reason we update it here
|
|
-- is that the signal whether the multiplier is saturated or not can appear the same
|
|
-- time as the adder result
|
|
for num_mult in 0 to (number_of_multipliers -1) loop
|
|
|
|
if (num_mult = 0) then
|
|
if (port_mult0_is_saturated = "USED") then
|
|
mult0_is_saturated <= mult_is_saturated_pipe(num_mult);
|
|
end if;
|
|
elsif (num_mult = 1) then
|
|
if (port_mult1_is_saturated = "USED") then
|
|
mult1_is_saturated <= mult_is_saturated_pipe(num_mult);
|
|
end if;
|
|
elsif (num_mult = 2) then
|
|
if (port_mult2_is_saturated = "USED") then
|
|
mult2_is_saturated <= mult_is_saturated_pipe(num_mult);
|
|
end if;
|
|
elsif (num_mult = 3) then
|
|
if (port_mult3_is_saturated = "USED") then
|
|
mult3_is_saturated <= mult_is_saturated_pipe(num_mult);
|
|
end if;
|
|
else
|
|
assert false
|
|
report "Error: Not supported number of multipliers in saturation";
|
|
end if;
|
|
|
|
end loop; -- for i in 0 to (number_of_multipliers -1) loop
|
|
end process;
|
|
|
|
-- The addition, subtraction and other functionality for Stratix III
|
|
IFGFAM1: if (stratixiii_block) generate
|
|
process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3,
|
|
adder1_reg, adder3_reg, acc_feedback, acc_feedback_temp,
|
|
outround_pipe, outsat_pipe,
|
|
mult_res)
|
|
|
|
variable asign : boolean;
|
|
variable bsign : boolean;
|
|
variable is_rep_a_sign : boolean;
|
|
variable is_rep_b_sign : boolean;
|
|
variable is_rep_a_pipe_sign : boolean;
|
|
variable is_rep_b_pipe_sign : boolean;
|
|
variable round_happen : boolean;
|
|
|
|
variable adder1_sum : std_logic_vector (int_width_a + int_width_b + int_width_result downto 0) := (others => '0');
|
|
variable adder3_sum : std_logic_vector (int_width_a + int_width_b + int_width_result downto 0) := (others => '0');
|
|
variable mult_res_temp : std_logic_vector ((int_width_a + int_width_b - 1) downto 0);
|
|
variable mult_res_temp_int : std_logic_vector ((int_width_a + int_width_b + int_width_result) downto 0) := (others => '0');
|
|
|
|
variable stckbit_cnt : integer := 0;
|
|
variable rndbit_cnt : integer := 0;
|
|
variable sat_bit_cnt : integer := 0;
|
|
variable leadsat_bit_cnt : integer := 0;
|
|
variable trailsat_bit_cnt : integer := 0;
|
|
variable allsat_bit_cnt : integer := 0;
|
|
variable satbit_or_cnt : integer := 0;
|
|
variable overflow_status_bit_pos : integer :=0;
|
|
variable i : integer := 0;
|
|
variable stick_bits_or : std_logic := '0';
|
|
variable overflow_status : std_logic := '0';
|
|
variable sat_bits_or : std_logic := '0';
|
|
|
|
variable round_sat_in_result : std_logic_vector (int_width_result + int_width_a + int_width_b downto 0) := (others => '0');
|
|
variable round_block_result : std_logic_vector (int_width_result + int_width_a + int_width_b downto 0) := (others => '0');
|
|
variable sat_block_result : std_logic_vector (int_width_result + int_width_a + int_width_b downto 0) := (others => '0');
|
|
variable output_result_temp : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
|
|
variable adder1_reg_temp : std_logic_vector (accum_width downto 0) := (others => '0');
|
|
variable adder3_reg_temp : std_logic_vector (accum_width downto 0) := (others => '0');
|
|
variable accum_res_temp : std_logic_vector (accum_width downto 0) := (others => '0');
|
|
variable accum_overflow : std_logic := '0';
|
|
variable acc_feedback_int : std_logic_vector (accum_width downto 0) := (others => '0');
|
|
variable accum_res_int : std_logic_vector (accum_width downto 0) := (others => '0');
|
|
variable and_sign_wire : std_logic := '0';
|
|
variable or_sign_wire : std_logic := '0';
|
|
variable accum_overflow_int : std_logic := '0';
|
|
variable msb : std_logic := '0';
|
|
variable unsigned_sub1_overflow : std_logic := '0';
|
|
variable unsigned_sub3_overflow : std_logic := '0';
|
|
|
|
begin
|
|
-- determine whether dataa and datab are signed or unsigned numbers
|
|
is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
-- Use sign_a_reg instead of sign_a_pipe when
|
|
-- signed_pipeline_register_a is unregistered
|
|
-- to set the asign flag
|
|
if (signed_pipeline_register_a = "UNREGISTERED") then
|
|
if (is_rep_a_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_a_pipe_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
end if;
|
|
|
|
-- Use sign_b_reg instead of sign_b_pipe when
|
|
-- signed_pipeline_register_b is unregistered
|
|
-- to set the bsign flag
|
|
if (signed_pipeline_register_b = "UNREGISTERED") then
|
|
if (is_rep_b_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_b_pipe_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
end if;
|
|
|
|
acc_feedback_int(accum_width - 1 downto 0) := acc_feedback_temp(accum_width - 1 downto 0);
|
|
|
|
if ((((output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_aclr = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (output_register = "UNREGISTERED"))) then
|
|
accum_res <= (others => '0');
|
|
accum_res_temp := (others => '0');
|
|
acc_feedback_int := (others => '0');
|
|
elsif (((output_register = "CLOCK0") and rising_edge (clock0) and (ena0 = '1')) or
|
|
((output_register = "CLOCK1") and rising_edge (clock1) and (ena1 = '1')) or
|
|
((output_register = "CLOCK2") and rising_edge (clock2) and (ena2 = '1')) or
|
|
((output_register = "CLOCK3") and rising_edge (clock3) and (ena3 = '1')) or
|
|
(output_register = "UNREGISTERED")) then
|
|
end if;
|
|
|
|
|
|
-- model the registering of the 1st-level adder/subtractor results
|
|
-- note: For Stratix III, multiplier_register0 should be the same setting as
|
|
-- multiplier_register1, multiplier_register2 and multiplier_register3, so just use 1 parameter will do
|
|
if ((((multiplier_aclr0 = "ACLR0") and (aclr0 = '1')) or
|
|
((multiplier_aclr0 = "ACLR1") and (aclr1 = '1')) or
|
|
((multiplier_aclr0 = "ACLR2") and (aclr2 = '1')) or
|
|
((multiplier_aclr0 = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (multiplier_register0 = "UNREGISTERED"))) then
|
|
|
|
adder1_sum := (others => '0');
|
|
adder3_sum := (others => '0');
|
|
adder1_reg <= (others => '0');
|
|
adder3_reg <= (others => '0');
|
|
|
|
elsif (((multiplier_register0 = "CLOCK0") and rising_edge (clock0)) or
|
|
((multiplier_register0 = "CLOCK1") and rising_edge (clock1)) or
|
|
((multiplier_register0 = "CLOCK2") and rising_edge (clock2)) or
|
|
((multiplier_register0 = "CLOCK3") and rising_edge (clock3)) or
|
|
(multiplier_register0 = "UNREGISTERED")) then
|
|
|
|
if (((multiplier_register0 = "CLOCK0") and (ena0 = '1')) or
|
|
((multiplier_register0 = "CLOCK1") and (ena1 = '1')) or
|
|
((multiplier_register0 = "CLOCK2") and (ena2 = '1')) or
|
|
((multiplier_register0 = "CLOCK3") and (ena3 = '1')) or
|
|
(multiplier_register0 = "UNREGISTERED")) then
|
|
|
|
adder1_sum := (others => '0');
|
|
adder3_sum := (others => '0');
|
|
-- model the first level adder/subtractor
|
|
for i in 0 to (number_of_multipliers - 1) loop
|
|
|
|
mult_res_temp := mult_res( ((i+1)*(int_width_a + int_width_b) - 1) downto (i*(int_width_a + int_width_b)));
|
|
mult_res_temp_int(int_width_a + int_width_b - 1 downto 0) := mult_res_temp;
|
|
|
|
if ((is_rep_a_sign) or (is_rep_b_sign))then
|
|
mult_res_temp_int(int_width_result + int_width_a + int_width_b downto int_width_a + int_width_b) := (others => mult_res_temp_int(int_width_a + int_width_b - 1));
|
|
else
|
|
mult_res_temp_int(int_width_result + int_width_a + int_width_b downto int_width_a + int_width_b) := (others => '0');
|
|
end if;
|
|
-- perform 1st level addition/subtraction
|
|
if ((i= 0) or (i = 1)) then
|
|
if ((multiplier1_direction = "ADD") or (i=0)) then
|
|
if ((asign = true) or (bsign = true)) then
|
|
adder1_sum := signed (adder1_sum) + signed(mult_res_temp_int);
|
|
else
|
|
adder1_sum := unsigned (adder1_sum) + unsigned(mult_res_temp_int);
|
|
end if;
|
|
else -- subtract
|
|
if ((asign = true) or (bsign = true)) then
|
|
adder1_sum := signed (adder1_sum) - signed(mult_res_temp_int);
|
|
else
|
|
adder1_sum := unsigned (adder1_sum) - unsigned(mult_res_temp_int);
|
|
if(adder1_sum(int_width_a + int_width_b + int_width_result) = '1') then
|
|
unsigned_sub1_overflow := '1';
|
|
else
|
|
unsigned_sub1_overflow := '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else -- 3rd and 4th multiplier
|
|
if ((multiplier3_direction = "ADD") or (i=2)) then
|
|
if ((asign = true) or (bsign = true)) then
|
|
adder3_sum := signed (adder3_sum) + signed(mult_res_temp_int);
|
|
else
|
|
adder3_sum := unsigned (adder3_sum) + unsigned(mult_res_temp_int);
|
|
end if;
|
|
else -- subtract
|
|
if ((asign = true) or (bsign = true)) then
|
|
adder3_sum := signed (adder3_sum) - signed(mult_res_temp_int);
|
|
else
|
|
adder3_sum := unsigned (adder3_sum) - unsigned(mult_res_temp_int);
|
|
if(adder3_sum(int_width_a + int_width_b + int_width_result) = '1') then
|
|
unsigned_sub3_overflow := '1';
|
|
else
|
|
unsigned_sub3_overflow := '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
|
|
-- assign the results to signals
|
|
adder1_reg <= adder1_sum (int_width_result + int_width_a + int_width_b downto 0);
|
|
adder3_reg <= adder3_sum (int_width_result + int_width_a + int_width_b downto 0);
|
|
unsigned_sub1_overflow_mult_reg <= unsigned_sub1_overflow;
|
|
unsigned_sub3_overflow_mult_reg <= unsigned_sub3_overflow;
|
|
end if;
|
|
end if; -- end 1st adder register stage
|
|
|
|
-- extend width for adder1_reg, adder2_reg and acc_feedback to set accumulator overflow bit
|
|
if(accum_width < int_width_result + int_width_a + int_width_b + 1) then
|
|
adder1_reg_temp(accum_width - 1 downto 0) := adder1_reg(accum_width - 1 downto 0);
|
|
adder3_reg_temp(accum_width - 1 downto 0) := adder3_reg(accum_width - 1 downto 0);
|
|
else
|
|
adder1_reg_temp(int_width_result + int_width_a + int_width_b downto 0) := adder1_reg(int_width_result + int_width_a + int_width_b downto 0);
|
|
adder3_reg_temp(int_width_result + int_width_a + int_width_b downto 0) := adder3_reg(int_width_result + int_width_a + int_width_b downto 0);
|
|
if ((asign = true) or (bsign = true)) then
|
|
adder1_reg_temp(accum_width - 1 downto int_width_result + int_width_a + int_width_b + 1) := (others => adder1_reg(int_width_result + int_width_a + int_width_b));
|
|
adder3_reg_temp(accum_width - 1 downto int_width_result + int_width_a + int_width_b + 1) := (others => adder3_reg(int_width_result + int_width_a + int_width_b));
|
|
else
|
|
adder1_reg_temp(accum_width - 1 downto int_width_result + int_width_a + int_width_b + 1) := (others => '0');
|
|
adder3_reg_temp(accum_width - 1 downto int_width_result + int_width_a + int_width_b + 1) := (others => '0');
|
|
end if;
|
|
end if;
|
|
|
|
if ((asign = true) or (bsign = true)) then
|
|
if(acc_feedback_int(accum_width - 1) = '1') then
|
|
acc_feedback_int(accum_width) := '1';
|
|
else
|
|
acc_feedback_int(accum_width) := '0';
|
|
end if;
|
|
if((adder1_reg_temp(accum_width - 1) = '1') and (accum_direction = "SUB")) then
|
|
adder1_reg_temp(accum_width) := '1';
|
|
else
|
|
adder1_reg_temp(accum_width) := '0';
|
|
end if;
|
|
else
|
|
acc_feedback_int(accum_width) := '0';
|
|
end if;
|
|
|
|
adder1_reg_temp(accum_width) := '0';
|
|
adder3_reg_temp(accum_width) := '0';
|
|
-- model the output register
|
|
if ((((output_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((output_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((output_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((output_aclr = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (output_register = "UNREGISTERED"))) then
|
|
|
|
output_result <= (others => '0');
|
|
overflow_int <= '0';
|
|
unsigned_sub1_overflow_reg <= '0';
|
|
unsigned_sub3_overflow_reg <= '0';
|
|
|
|
elsif (((output_register = "CLOCK0") and rising_edge (clock0)) or
|
|
((output_register = "CLOCK1") and rising_edge (clock1)) or
|
|
((output_register = "CLOCK2") and rising_edge (clock2)) or
|
|
((output_register = "CLOCK3") and rising_edge (clock3)) or
|
|
(output_register = "UNREGISTERED")) then
|
|
|
|
if (((output_register = "CLOCK0") and (ena0 = '1')) or
|
|
((output_register = "CLOCK1") and (ena1 = '1')) or
|
|
((output_register = "CLOCK2") and (ena2 = '1')) or
|
|
((output_register = "CLOCK3") and (ena3 = '1')) or
|
|
(output_register = "UNREGISTERED")) then
|
|
|
|
unsigned_sub1_overflow_reg <= unsigned_sub1_overflow_mult_reg;
|
|
unsigned_sub3_overflow_reg <= unsigned_sub3_overflow_mult_reg;
|
|
|
|
if ((asign = true) or (bsign = true)) then
|
|
if(accum_direction = "ADD") then
|
|
accum_res_temp := signed (adder3_reg_temp) + signed (adder1_reg_temp);
|
|
else
|
|
accum_res_temp := signed (acc_feedback_int) - signed (adder1_reg_temp);
|
|
end if;
|
|
else
|
|
if(accum_direction = "ADD") then
|
|
accum_res_temp := unsigned (adder3_reg_temp) + unsigned (adder1_reg_temp);
|
|
else
|
|
accum_res_temp := unsigned (acc_feedback_int) - unsigned (adder1_reg_temp);
|
|
end if;
|
|
end if;
|
|
|
|
if ((asign = true) or (bsign = true)) then
|
|
if(accum_res_temp(accum_width - 1) = '1') then
|
|
accum_res_temp(accum_width) := '1';
|
|
else
|
|
accum_res_temp(accum_width) := '0';
|
|
end if;
|
|
|
|
if(adder3_reg_temp(accum_width - 1) = '1') then
|
|
adder3_reg_temp(accum_width) := '1';
|
|
else
|
|
adder3_reg_temp(accum_width) := '0';
|
|
end if;
|
|
--else
|
|
-- accum_res_temp(accum_width) := '0';
|
|
end if;
|
|
|
|
if ((asign = true) or (bsign = true)) then
|
|
if(accum_direction = "ADD") then
|
|
accum_res_int := signed (acc_feedback_int) + signed (accum_res_temp);
|
|
else
|
|
accum_res_int := signed(accum_res_temp) - signed(adder3_reg_temp);
|
|
end if;
|
|
else
|
|
if(accum_direction = "ADD") then
|
|
accum_res_int := unsigned (acc_feedback_int) + unsigned (accum_res_temp);
|
|
else
|
|
accum_res_int := unsigned (accum_res_temp) - unsigned (adder3_reg_temp);
|
|
end if;
|
|
end if;
|
|
|
|
or_sign_wire := '0';
|
|
and_sign_wire := '0';
|
|
|
|
if(extra_sign_bit_width >= 1) then
|
|
and_sign_wire := '1';
|
|
for i in (accum_width -lsb_position - extra_sign_bit_width) to (accum_width -lsb_position - 1) loop
|
|
if(accum_res_int(i) = '1') then
|
|
or_sign_wire := '1';
|
|
end if;
|
|
|
|
if(accum_res_int(i) = '0') then
|
|
and_sign_wire := '0';
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
|
|
if(port_signa = "PORT_USED" or port_signb = "PORT_USED") then
|
|
if ((asign = true) or (bsign = true)) then
|
|
--signed data
|
|
if(accum_res_int(44) /= accum_res_int(43)) then
|
|
accum_overflow_int := '1';
|
|
else
|
|
accum_overflow_int := '0';
|
|
end if;
|
|
else
|
|
-- unsigned data
|
|
if(accum_direction = "ADD") then -- addition
|
|
if(accum_res_int(44) = '1') then
|
|
accum_overflow_int := '1';
|
|
else
|
|
accum_overflow_int := '0';
|
|
end if;
|
|
else -- subtraction
|
|
if(accum_res_int(44) = '0') then
|
|
accum_overflow_int := '0';
|
|
else
|
|
accum_overflow_int := '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- dynamic sign input
|
|
|
|
if(accum_res_int(bit_position) = '1') then
|
|
msb := '1';
|
|
else
|
|
msb := '0';
|
|
end if;
|
|
|
|
if(extra_sign_bit_width >= 1) then
|
|
if((and_sign_wire = '1') and ((not(asign = true or bsign = true)) or ((asign = true or bsign = true) and (msb = '1')))) then
|
|
and_sign_wire := '1';
|
|
else
|
|
and_sign_wire := '0';
|
|
end if;
|
|
|
|
if ((asign = true or bsign = true) and (msb = '1')) then
|
|
or_sign_wire := '1';
|
|
end if;
|
|
end if;
|
|
|
|
--operation XOR
|
|
if ((or_sign_wire /= and_sign_wire) or accum_overflow_int = '1') then
|
|
accum_overflow := '1';
|
|
else
|
|
accum_overflow := '0';
|
|
end if;
|
|
elsif(representation_a = "SIGNED" or representation_b = "SIGNED") then
|
|
--signed data
|
|
if (accum_res_int(44) /= accum_res_int(43)) then
|
|
accum_overflow_int := '1';
|
|
else
|
|
accum_overflow_int := '0';
|
|
end if;
|
|
|
|
--operation XOR
|
|
if ((or_sign_wire /= and_sign_wire) or accum_overflow_int = '1') then
|
|
accum_overflow := '1';
|
|
else
|
|
accum_overflow := '0';
|
|
end if;
|
|
else
|
|
-- unsigned data
|
|
if(accum_direction = "ADD") then
|
|
-- addition
|
|
if ((accum_res_int(44) = '1') or ((adder1_reg_temp(43) = '1') and (adder3_reg_temp(43) = '1')))then
|
|
accum_overflow_int := '1';
|
|
else
|
|
accum_overflow_int := '0';
|
|
end if;
|
|
else
|
|
-- subtraction
|
|
if (accum_res_int(44) = '0') then
|
|
accum_overflow_int := '1';
|
|
else
|
|
accum_overflow_int := '0';
|
|
end if;
|
|
end if;
|
|
|
|
if(or_sign_wire = '1' or accum_overflow_int = '1') then
|
|
accum_overflow := '1';
|
|
else
|
|
accum_overflow := '0';
|
|
end if;
|
|
end if;
|
|
|
|
accum_res <= accum_res_int;
|
|
|
|
-- model the 2nd stage adder or accumulator
|
|
if (accumulator = "NO") then
|
|
if ((asign = true) or (bsign = true)) then
|
|
round_sat_in_result := signed (adder1_reg) + signed (adder3_reg);
|
|
else
|
|
round_sat_in_result := unsigned (adder1_reg) + unsigned (adder3_reg);
|
|
end if;
|
|
elsif (accum_direction = "ADD") then
|
|
if ((asign = true) or (bsign = true)) then
|
|
round_sat_in_result := signed (acc_feedback) + signed (adder1_reg) + signed (adder3_reg);
|
|
else
|
|
round_sat_in_result := unsigned (acc_feedback) + unsigned (adder1_reg) + unsigned (adder3_reg);
|
|
end if;
|
|
elsif (accum_direction = "SUB") then
|
|
if ((asign = true) or (bsign = true)) then
|
|
round_sat_in_result := signed (acc_feedback) - signed (adder1_reg) - signed (adder3_reg);
|
|
else
|
|
round_sat_in_result := unsigned (acc_feedback) - unsigned (adder1_reg) - unsigned (adder3_reg);
|
|
end if;
|
|
end if;
|
|
|
|
round_happen := false;
|
|
-- 1st rounding block
|
|
if (output_rounding = "NO") then
|
|
round_block_result := round_sat_in_result;
|
|
else
|
|
if (((output_rounding = "VARIABLE") and (outround_pipe = '1')) or (output_rounding = "YES")) then
|
|
-- guard bit is '1'
|
|
if (round_sat_in_result(round_position - 1) = '1') then
|
|
if (output_round_type = "NEAREST_INTEGER") then -- round to nearest integer
|
|
round_block_result := unsigned(round_sat_in_result) + (2 ** (round_position));
|
|
|
|
else -- round to nearest even
|
|
stick_bits_or := '0';
|
|
-- determine if any sticky bit is '1'
|
|
for stckbit_cnt in 0 to (round_position - 2) loop
|
|
stick_bits_or := stick_bits_or or round_sat_in_result(stckbit_cnt);
|
|
end loop;
|
|
|
|
if (stick_bits_or = '1') then -- if sticky bits = 1, do rounding
|
|
round_block_result := unsigned(round_sat_in_result) + (2 ** (round_position));
|
|
|
|
else -- all sticky bits are 0, look at the LSB to determine to round or not
|
|
if (round_sat_in_result (round_position) = '1') then -- LSB is odd, so do rounding
|
|
round_block_result := unsigned(round_sat_in_result) + (2 ** (round_position));
|
|
|
|
else
|
|
round_block_result := round_sat_in_result;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else -- guard bit is 0, so no need to round
|
|
round_block_result := round_sat_in_result;
|
|
end if;
|
|
|
|
-- if unsigned numbers enter into the rounding & saturation block, "X" the entire data
|
|
-- since unsigned numbers are illegal
|
|
if (((asign = false) and (bsign = false)) and (((port_signa = "PORT_USED") and (port_signb = "PORT_USED")) or
|
|
((representation_a /= "UNUSED") and (representation_b /= "UNUSED")))) then
|
|
round_block_result := (others => 'X');
|
|
end if;
|
|
|
|
-- force the LSBs beyond the rounding position to "X"
|
|
if(input_source_b0 /= "LOOPBACK") then
|
|
for rndbit_cnt in 0 to (round_position - 1) loop
|
|
round_block_result(rndbit_cnt) := 'X';
|
|
end loop;
|
|
end if;
|
|
|
|
round_happen := true;
|
|
else
|
|
round_block_result := round_sat_in_result;
|
|
end if;
|
|
end if;
|
|
|
|
-- prevent the previous overflow_status being taken into consideration when determining the overflow
|
|
if ((overflow_status = '0') and (port_output_is_overflow = "PORT_UNUSED") and (chainout_adder = "NO")) then
|
|
overflow_status_bit_pos := int_width_result + int_mult_diff_bit - 1;
|
|
else
|
|
overflow_status_bit_pos := int_width_result + 1;
|
|
end if;
|
|
|
|
-- 1st saturation block
|
|
if (output_saturation = "NO") then
|
|
sat_block_result := round_block_result;
|
|
else
|
|
overflow_status := '0';
|
|
if (((output_saturation = "VARIABLE") and (outsat_pipe = '1')) or (output_saturation = "YES")) then
|
|
if (round_block_result (int_width_result) = '0') then -- carry bit is 0, positive number
|
|
for sat_bit_cnt in (saturation_position) to (int_width_result) loop
|
|
if (sat_bit_cnt /= overflow_status_bit_pos) then
|
|
overflow_status := overflow_status or round_block_result (sat_bit_cnt);
|
|
end if;
|
|
end loop;
|
|
else -- carry bit is 1, negative number
|
|
for sat_bit_cnt in (saturation_position) to (int_width_result) loop
|
|
if (sat_bit_cnt /= overflow_status_bit_pos) then
|
|
overflow_status := overflow_status or (not round_block_result (sat_bit_cnt));
|
|
end if;
|
|
end loop;
|
|
|
|
if ((output_saturate_type = "SYMMETRIC") and (overflow_status = '0')) then
|
|
overflow_status := '1';
|
|
if (round_happen) then
|
|
for sat_bit_cnt in (round_position) to (saturation_position - 1) loop
|
|
overflow_status := overflow_status and not(round_block_result (sat_bit_cnt));
|
|
end loop;
|
|
else
|
|
for sat_bit_cnt in (0) to (saturation_position - 1) loop
|
|
overflow_status := overflow_status and not(round_block_result (sat_bit_cnt));
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (overflow_status = '1') then
|
|
if (round_block_result (int_width_result) = '0') then -- positive number
|
|
if (port_output_is_overflow = "PORT_UNUSED") then
|
|
sat_block_result (int_width_a + int_width_b - 1) := overflow_status;
|
|
elsif (accumulator = "NO") then
|
|
sat_block_result (int_width_a + int_width_b - 1) := 'X';
|
|
end if;
|
|
|
|
for leadsat_bit_cnt in (saturation_position) to (int_width_a + int_width_b) loop
|
|
sat_block_result (leadsat_bit_cnt) := '0';
|
|
end loop;
|
|
|
|
if (round_happen) then
|
|
for trailsat_bit_cnt in (round_position) to (saturation_position - 1) loop
|
|
sat_block_result (trailsat_bit_cnt) := '1';
|
|
end loop;
|
|
else
|
|
for trailsat_bit_cnt in 0 to (saturation_position - 1) loop
|
|
sat_block_result (trailsat_bit_cnt) := '1';
|
|
end loop;
|
|
end if;
|
|
|
|
sat_block_result(int_width_result + int_width_a + int_width_b - 1 downto int_width_a + int_width_b + 1) := (others => '0');
|
|
|
|
else -- negative number
|
|
if (port_output_is_overflow = "PORT_UNUSED") then
|
|
sat_block_result (int_width_a + int_width_b - 1) := overflow_status;
|
|
elsif (accumulator = "NO") then
|
|
sat_block_result (int_width_a + int_width_b - 1) := 'X';
|
|
end if;
|
|
|
|
for allsat_bit_cnt in (saturation_position) to (int_width_a + int_width_b) loop
|
|
sat_block_result (allsat_bit_cnt) := '1'; -- set all sign bits to '1'
|
|
end loop;
|
|
|
|
if ((output_rounding /= "NO") and (output_saturate_type = "SYMMETRIC")) then
|
|
for allsat_bit_cnt in (round_position) to (saturation_position - 1) loop
|
|
sat_block_result (allsat_bit_cnt) := '0'; -- set all bits to "0"
|
|
end loop;
|
|
|
|
if(accumulator = "NO") then
|
|
for allsat_bit_cnt in 0 to (round_position - 1) loop
|
|
sat_block_result (allsat_bit_cnt) := 'X'; -- set LSBs to "X"
|
|
end loop;
|
|
else
|
|
for allsat_bit_cnt in 0 to (round_position - 1) loop
|
|
sat_block_result (allsat_bit_cnt) := '0'; -- set LSBs to "X"
|
|
end loop;
|
|
end if;
|
|
else
|
|
for allsat_bit_cnt in 0 to (saturation_position - 1) loop
|
|
sat_block_result (allsat_bit_cnt) := '0'; -- set all bits to "0"
|
|
end loop;
|
|
end if;
|
|
|
|
if ((output_rounding /= "NO") and (output_saturate_type = "SYMMETRIC")) then
|
|
sat_block_result (round_position) := '1';
|
|
elsif (output_saturate_type = "SYMMETRIC") then
|
|
sat_block_result (int_mult_diff_bit) := '1';
|
|
end if;
|
|
|
|
sat_block_result(int_width_result + int_width_a + int_width_b - 1 downto int_width_a + int_width_b + 1) := (others => '1');
|
|
end if;
|
|
else -- if not overflow
|
|
sat_block_result := round_block_result;
|
|
|
|
if (port_output_is_overflow = "PORT_UNUSED" and chainout_adder = "NO" and ((output_saturation = "VARIABLE") and (outsat_pipe = '1'))) then
|
|
sat_block_result (int_width_result + int_mult_diff_bit - 1) := overflow_status;
|
|
end if;
|
|
-- if negative number & output_saturate_type is symmetric, need to check for special case
|
|
if (sat_block_result (int_width_a + int_width_b - 1) = '1') then
|
|
if (output_saturate_type = "SYMMETRIC") then
|
|
for satbit_or_cnt in (round_position) to (int_width_a + int_width_b - 2) loop
|
|
sat_bits_or := sat_bits_or or sat_block_result (satbit_or_cnt);
|
|
end loop;
|
|
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- if unsigned numbers enter into the rounding & saturation block, "X" the entire data
|
|
-- since unsigned numbers are illegal
|
|
if (((asign = false) and (bsign = false)) and (((port_signa = "PORT_USED") and (port_signb = "PORT_USED")) or
|
|
((representation_a /= "UNUSED") and (representation_b /= "UNUSED")))) then
|
|
sat_block_result := (others => 'X');
|
|
end if;
|
|
elsif ((output_saturation = "VARIABLE") and (outsat_pipe = '0')) then
|
|
sat_block_result := round_block_result;
|
|
overflow_status := '0';
|
|
else
|
|
sat_block_result := round_block_result;
|
|
end if;
|
|
end if;
|
|
|
|
-- assign the saturation block output to a signal
|
|
output_result <= sat_block_result;
|
|
|
|
-- assign the overflow status to the overflow port
|
|
if (port_output_is_overflow = "PORT_USED") then
|
|
if(output_saturation = "NO" and accumulator = "YES") then
|
|
overflow_int <= accum_overflow;
|
|
elsif(output_saturation /= "NO") then
|
|
overflow_int <= overflow_status;
|
|
end if;
|
|
end if;
|
|
|
|
end if;
|
|
end if; -- end of output_register block
|
|
end process;
|
|
end generate IFGFAM1;
|
|
|
|
IFGFAM10: if (stratixiii_block) generate
|
|
process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3,
|
|
chainout_round_out_reg, chainout_sat_out,
|
|
zerochainout_reg, chainin, output_result)
|
|
|
|
variable asign : boolean;
|
|
variable bsign : boolean;
|
|
variable is_rep_a_sign : boolean;
|
|
variable is_rep_b_sign : boolean;
|
|
variable is_rep_a_pipe_sign : boolean;
|
|
variable is_rep_b_pipe_sign : boolean;
|
|
variable cho_round_happen : boolean;
|
|
|
|
variable cho_rndbit_cnt : integer := 0;
|
|
variable cho_stckbit_cnt : integer := 0;
|
|
variable cho_sat_bit_cnt : integer := 0;
|
|
variable cho_leadsat_bit_cnt : integer := 0;
|
|
variable cho_trailsat_bit_cnt : integer := 0;
|
|
variable cho_allsat_bit_cnt : integer := 0;
|
|
variable cho_satbit_or_cnt : integer := 0;
|
|
|
|
variable cho_stick_bits_or : std_logic := '0';
|
|
variable cho_sat_bits_or : std_logic := '0';
|
|
variable chainout_overflow_status : std_logic := '0';
|
|
|
|
variable chainout_round_block_result : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
variable chainout_add_result : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
variable chainout_sat_block_result : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
|
|
variable overflow_checking : std_logic;
|
|
variable round_checking : std_logic;
|
|
|
|
begin
|
|
-- determine whether dataa and datab are signed or unsigned numbers
|
|
is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or
|
|
(sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
|
|
((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
|
|
|
|
is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or
|
|
(sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
|
|
((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
|
|
|
|
-- Use sign_a_reg instead of sign_a_pipe when
|
|
-- signed_pipeline_register_a is unregistered
|
|
-- to set the asign flag
|
|
if (signed_pipeline_register_a = "UNREGISTERED") then
|
|
if (is_rep_a_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_a_pipe_sign) then
|
|
asign := true;
|
|
else
|
|
asign := false;
|
|
end if;
|
|
end if;
|
|
|
|
-- Use sign_b_reg instead of sign_b_pipe when
|
|
-- signed_pipeline_register_b is unregistered
|
|
-- to set the bsign flag
|
|
if (signed_pipeline_register_b = "UNREGISTERED") then
|
|
if (is_rep_b_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
else
|
|
if (is_rep_b_pipe_sign) then
|
|
bsign := true;
|
|
else
|
|
bsign := false;
|
|
end if;
|
|
end if;
|
|
|
|
-- model the chainout stage
|
|
if ((((chainout_aclr = "ACLR0") and (aclr0 = '1')) or
|
|
((chainout_aclr = "ACLR1") and (aclr1 = '1')) or
|
|
((chainout_aclr = "ACLR2") and (aclr2 = '1')) or
|
|
((chainout_aclr = "ACLR3") and (aclr3 = '1'))) and
|
|
(not (chainout_register = "UNREGISTERED"))) then
|
|
|
|
chainout_sat_block_res_wire <= (others => '0');
|
|
chainout_sat_overflow <= '0';
|
|
chainout_overflow_int <= '0';
|
|
|
|
elsif (((chainout_register = "CLOCK0") and rising_edge (clock0)) or
|
|
((chainout_register = "CLOCK1") and rising_edge (clock1)) or
|
|
((chainout_register = "CLOCK2") and rising_edge (clock2)) or
|
|
((chainout_register = "CLOCK3") and rising_edge (clock3)) or
|
|
(chainout_register = "UNREGISTERED")) then
|
|
|
|
if (((chainout_register = "CLOCK0") and (ena0 = '1')) or
|
|
((chainout_register = "CLOCK1") and (ena1 = '1')) or
|
|
((chainout_register = "CLOCK2") and (ena2 = '1')) or
|
|
((chainout_register = "CLOCK3") and (ena3 = '1')) or
|
|
(chainout_register = "UNREGISTERED")) then
|
|
|
|
-- model the chainout adder
|
|
if (chainout_adder = "YES") then
|
|
if ((asign = true) or (bsign = true)) then
|
|
chainout_add_result := signed (output_result(int_width_result downto 0)) + signed (chainin);
|
|
else
|
|
chainout_add_result := unsigned (output_result(int_width_result downto 0)) + unsigned (chainin);
|
|
end if;
|
|
|
|
cho_round_happen := false;
|
|
-- model the chainout stage rounding block
|
|
if (chainout_rounding = "NO") then
|
|
chainout_round_block_result := chainout_add_result;
|
|
else
|
|
if (((chainout_rounding = "VARIABLE") and (chainout_round_out_reg = '1')) or (chainout_rounding = "YES")) then
|
|
overflow_checking := chainout_add_result(int_width_result - 1);
|
|
-- guard bit is '1'
|
|
if (chainout_add_result(chainout_round_position - 1) = '1') then
|
|
if (output_round_type = "NEAREST_INTEGER") then -- round to nearest integer
|
|
round_checking := '1';
|
|
chainout_round_block_result := unsigned(chainout_add_result) + (2 ** (chainout_round_position));
|
|
|
|
else -- round to nearest even
|
|
-- determine if any sticky bit is '1'
|
|
cho_stick_bits_or := '0';
|
|
for cho_stckbit_cnt in 0 to (chainout_round_position - 2) loop
|
|
cho_stick_bits_or := cho_stick_bits_or or chainout_add_result(cho_stckbit_cnt);
|
|
end loop;
|
|
|
|
if (cho_stick_bits_or = '1') then -- if sticky bits = 1, do rounding
|
|
chainout_round_block_result := unsigned(chainout_add_result) + (2 ** (chainout_round_position));
|
|
|
|
else -- all sticky bits are 0, look at the LSB to determine to round or not
|
|
if (chainout_add_result (chainout_round_position) = '1') then -- LSB is odd, so do rounding
|
|
chainout_round_block_result := unsigned(chainout_add_result) + (2 ** (chainout_round_position));
|
|
else
|
|
chainout_round_block_result := chainout_add_result;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else -- guard bit is 0, so no need to round
|
|
chainout_round_block_result := chainout_add_result;
|
|
end if;
|
|
-- if unsigned numbers enter into the rounding & saturation block, "X" the entire data
|
|
-- since unsigned numbers are illegal
|
|
if (((asign = false) and (bsign = false)) and (((port_signa = "PORT_USED") and (port_signb = "PORT_USED")) or
|
|
((representation_a /= "UNUSED") and (representation_b /= "UNUSED")))) then
|
|
chainout_round_block_result := (others => 'X');
|
|
end if;
|
|
|
|
cho_round_happen := true;
|
|
else
|
|
chainout_round_block_result := chainout_add_result;
|
|
end if;
|
|
end if;
|
|
|
|
chainout_overflow_status := '0';
|
|
if (chainout_saturation = "NO") then
|
|
chainout_sat_block_result := chainout_round_block_result;
|
|
else
|
|
if (((chainout_saturation = "VARIABLE") and (chainout_sat_out = '1')) or (chainout_saturation = "YES")) then
|
|
if ((((chainout_rounding = "VARIABLE") and (chainout_round_out_reg = '1')) or (chainout_rounding = "YES")) and round_checking = '1' and width_saturate_sign = 1 and width_result = result_width) then
|
|
if (chainout_round_block_result(int_width_result - 1) /= overflow_checking) then
|
|
chainout_overflow_status := '1';
|
|
else
|
|
chainout_overflow_status := '0';
|
|
end if;
|
|
elsif (chainout_round_block_result (int_width_result - 1) = '0') then -- carry bit is 0, positive number
|
|
for cho_sat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
|
|
chainout_overflow_status := chainout_overflow_status or chainout_round_block_result (cho_sat_bit_cnt);
|
|
end loop;
|
|
else -- carry bit is 1, negative number
|
|
for cho_sat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
|
|
chainout_overflow_status := chainout_overflow_status or (not chainout_round_block_result (cho_sat_bit_cnt));
|
|
end loop;
|
|
|
|
if ((output_saturate_type = "SYMMETRIC") and (chainout_overflow_status = '0')) then
|
|
chainout_overflow_status := '1';
|
|
if (cho_round_happen) then
|
|
for cho_sat_bit_cnt in (chainout_round_position) to (chainout_saturation_position - 1) loop
|
|
chainout_overflow_status := chainout_overflow_status and not(chainout_round_block_result (cho_sat_bit_cnt));
|
|
end loop;
|
|
else
|
|
for cho_sat_bit_cnt in (0) to (chainout_saturation_position - 1) loop
|
|
chainout_overflow_status := chainout_overflow_status and not(chainout_round_block_result (cho_sat_bit_cnt));
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (chainout_overflow_status = '1') then
|
|
if ((((chainout_rounding = "VARIABLE") and (chainout_round_out_reg = '1')) or (chainout_rounding = "YES")) and round_checking = '1' and width_saturate_sign = 1 and width_result = result_width) then
|
|
if (chainout_round_block_result (int_width_result - 1) = '1') then -- positive number
|
|
if (port_chainout_sat_is_overflow = "PORT_UNUSED") then
|
|
chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
|
|
else
|
|
chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
|
|
end if;
|
|
|
|
for cho_leadsat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
|
|
chainout_sat_block_result (cho_leadsat_bit_cnt) := '0';
|
|
end loop;
|
|
|
|
if (cho_round_happen) then
|
|
for cho_trailsat_bit_cnt in (0) to (chainout_saturation_position - 1) loop
|
|
chainout_sat_block_result (cho_trailsat_bit_cnt) := '1';
|
|
end loop;
|
|
else
|
|
for cho_trailsat_bit_cnt in 0 to (chainout_saturation_position - 1) loop
|
|
chainout_sat_block_result (cho_trailsat_bit_cnt) := '1';
|
|
end loop;
|
|
end if;
|
|
|
|
else -- negative number
|
|
if (port_chainout_sat_is_overflow = "PORT_UNUSED") then
|
|
chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
|
|
else
|
|
chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
|
|
end if;
|
|
|
|
for cho_allsat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
|
|
chainout_sat_block_result (cho_allsat_bit_cnt) := '1'; -- set all sign bits to '1'
|
|
end loop;
|
|
|
|
if ((chainout_rounding /= "NO") and (output_saturate_type = "SYMMETRIC")) then
|
|
for cho_allsat_bit_cnt in (chainout_round_position) to (chainout_saturation_position - 1) loop
|
|
chainout_sat_block_result (cho_allsat_bit_cnt) := '0'; -- set all bits to '0'
|
|
end loop;
|
|
|
|
for cho_allsat_bit_cnt in 0 to (chainout_round_position - 1) loop
|
|
chainout_sat_block_result (cho_allsat_bit_cnt) := '0'; -- set LSBs to '0'
|
|
end loop;
|
|
else
|
|
for cho_allsat_bit_cnt in 0 to (chainout_saturation_position - 1) loop
|
|
chainout_sat_block_result (cho_allsat_bit_cnt) := '0'; -- set all bits to '0'
|
|
end loop;
|
|
end if;
|
|
|
|
if ((chainout_rounding /= "NO") and (output_saturate_type = "SYMMETRIC")) then
|
|
chainout_sat_block_result (chainout_round_position) := '1';
|
|
elsif (output_saturate_type = "SYMMETRIC") then
|
|
chainout_sat_block_result (int_mult_diff_bit) := '1';
|
|
end if;
|
|
end if;
|
|
else
|
|
if (chainout_round_block_result (int_width_result - 1) = '0') then -- positive number
|
|
if (port_chainout_sat_is_overflow = "PORT_UNUSED") then
|
|
chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
|
|
else
|
|
chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
|
|
end if;
|
|
|
|
for cho_leadsat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
|
|
chainout_sat_block_result (cho_leadsat_bit_cnt) := '0';
|
|
end loop;
|
|
|
|
if (cho_round_happen) then
|
|
for cho_trailsat_bit_cnt in (0) to (chainout_saturation_position - 1) loop
|
|
chainout_sat_block_result (cho_trailsat_bit_cnt) := '1';
|
|
end loop;
|
|
else
|
|
for cho_trailsat_bit_cnt in 0 to (chainout_saturation_position - 1) loop
|
|
chainout_sat_block_result (cho_trailsat_bit_cnt) := '1';
|
|
end loop;
|
|
end if;
|
|
|
|
else -- negative number
|
|
if (port_chainout_sat_is_overflow = "PORT_UNUSED") then
|
|
chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
|
|
else
|
|
chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
|
|
end if;
|
|
|
|
for cho_allsat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
|
|
chainout_sat_block_result (cho_allsat_bit_cnt) := '1'; -- set all sign bits to '1'
|
|
end loop;
|
|
|
|
if ((chainout_rounding /= "NO") or (output_saturate_type = "SYMMETRIC")) then
|
|
for cho_allsat_bit_cnt in (chainout_round_position) to (chainout_saturation_position - 1) loop
|
|
chainout_sat_block_result (cho_allsat_bit_cnt) := '0'; -- set all bits to '0'
|
|
end loop;
|
|
|
|
for cho_allsat_bit_cnt in 0 to (chainout_round_position - 1) loop
|
|
chainout_sat_block_result (cho_allsat_bit_cnt) := '0'; -- set LSBs to 'X'
|
|
end loop;
|
|
else
|
|
for cho_allsat_bit_cnt in 0 to (chainout_saturation_position - 1) loop
|
|
chainout_sat_block_result (cho_allsat_bit_cnt) := '0'; -- set all bits to '0'
|
|
end loop;
|
|
end if;
|
|
|
|
if ((chainout_rounding /= "NO") and (output_saturate_type = "SYMMETRIC")) then
|
|
chainout_sat_block_result (chainout_round_position) := '1';
|
|
elsif (output_saturate_type = "SYMMETRIC") then
|
|
chainout_sat_block_result (int_mult_diff_bit) := '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else -- if not overflow
|
|
chainout_sat_block_result := chainout_round_block_result;
|
|
|
|
-- if negative number & output_saturate_type is symmetric, need to check for special case
|
|
if (chainout_sat_block_result (int_width_result) = '1') then
|
|
if (output_saturate_type = "SYMMETRIC") then
|
|
for cho_satbit_or_cnt in (chainout_round_position) to (int_width_result - 2) loop
|
|
cho_sat_bits_or := cho_sat_bits_or or chainout_sat_block_result (cho_satbit_or_cnt);
|
|
end loop;
|
|
|
|
if ((cho_sat_bits_or = '0') and (chainout_sat_block_result (int_width_result - 1) = '1')) then
|
|
chainout_sat_block_result (chainout_round_position) := '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- if unsigned numbers enter into the rounding & saturation block, "X" the entire data
|
|
-- since unsigned numbers are illegal
|
|
if (((asign = false) and (bsign = false)) and (((port_signa = "PORT_USED") and (port_signb = "PORT_USED")) or
|
|
((representation_a /= "UNUSED") and (representation_b /= "UNUSED")))) then
|
|
chainout_sat_block_result := (others => 'X');
|
|
end if;
|
|
else
|
|
chainout_sat_block_result := chainout_round_block_result;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- assign the chainout overflow status to the chainout_sat_overflow port
|
|
if (port_chainout_sat_is_overflow = "PORT_USED") then
|
|
chainout_sat_overflow <= chainout_overflow_status;
|
|
chainout_overflow_int <= chainout_overflow_status;
|
|
end if;
|
|
|
|
chainout_sat_block_res_wire <= chainout_sat_block_result;
|
|
|
|
end if;
|
|
end if; -- end of chainout register stage
|
|
end process;
|
|
end generate IFGFAM10;
|
|
|
|
IFGFAM11: if (stratixiii_block) generate
|
|
process (chainout_sat_block_res_wire, zerochainout_reg)
|
|
variable cho_cnt : integer := 0;
|
|
variable chainout_out_temp : std_logic_vector (int_width_result downto 0) := (others => '0');
|
|
begin
|
|
chainout_out_temp := (others => '0');
|
|
-- the chainout output after factoring in zero_chainout
|
|
for cho_cnt in 0 to int_width_result loop
|
|
chainout_out_temp(cho_cnt) := (not zerochainout_reg) and (chainout_sat_block_res_wire(cho_cnt));
|
|
end loop;
|
|
|
|
chainout_output(int_width_result downto 0) <= chainout_out_temp(int_width_result downto 0);
|
|
end process;
|
|
end generate IFGFAM11;
|
|
|
|
-- model the shift & rotate blocks for Stratix III
|
|
IFGFAM2: if (stratixiii_block) generate
|
|
process (output_result, shiftr_out, rotate_out)
|
|
begin
|
|
if (not (shift_mode = "NO")) then
|
|
if ((shift_mode = "LEFT") or ((shift_mode = "VARIABLE") and (shiftr_out = '0') and (rotate_out = '0'))) then
|
|
shift_rot_result <= output_result((int_width_result / 2) - 1 downto 0);
|
|
elsif ((shift_mode = "RIGHT") or ((shift_mode = "VARIABLE") and (shiftr_out = '1') and (rotate_out = '0'))) then
|
|
shift_rot_result <= output_result(int_width_result - 1 downto (int_width_result / 2));
|
|
elsif ((shift_mode = "ROTATION") or ((shift_mode = "VARIABLE") and (shiftr_out = '0') and (rotate_out = '1'))) then
|
|
shift_rot_result <= (output_result(int_width_result - 1 downto (int_width_result / 2))) or
|
|
(output_result((int_width_result / 2) - 1 downto 0));
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFGFAM2;
|
|
|
|
IFGFAM3: if (stratixiii_block) generate
|
|
process (output_result, zeroloopback_out)
|
|
|
|
variable lpbk_cnt : integer := 0;
|
|
|
|
begin
|
|
if (input_source_b0 = "LOOPBACK") then
|
|
for lpbk_cnt in 0 to (int_width_result - 1) loop
|
|
loopback_wire(lpbk_cnt) <= output_result(lpbk_cnt + (int_width_b - width_b)) and (not zeroloopback_out);
|
|
end loop;
|
|
end if;
|
|
end process;
|
|
end generate IFGFAM3;
|
|
|
|
IFLOOPBACK: if (stratixiii_block) generate
|
|
process (loopback_wire)
|
|
begin
|
|
if(input_source_b0 = "LOOPBACK") then
|
|
feedback <= loopback_wire(width_a + 18 - 1 downto width_a);
|
|
end if;
|
|
end process;
|
|
end generate IFLOOPBACK;
|
|
|
|
IFGFAM4: if (stratixiii_block) generate
|
|
process (output_result, accumsload_pipe)
|
|
|
|
variable acfdbk_cnt : integer := 0;
|
|
|
|
begin
|
|
if (accumulator = "YES") then
|
|
for acfdbk_cnt in 0 to (int_width_result + int_width_a + int_width_b) loop
|
|
acc_feedback(acfdbk_cnt) <= output_result(acfdbk_cnt) and (not accumsload_pipe);
|
|
end loop;
|
|
end if;
|
|
end process;
|
|
end generate IFGFAM4;
|
|
|
|
IFACCUM: if (stratixiii_block) generate
|
|
process (accum_res, accumsload_pipe)
|
|
|
|
variable acfdbk_cnt : integer := 0;
|
|
|
|
begin
|
|
if (accumulator = "YES") then
|
|
for acfdbk_cnt in 0 to (accum_width) loop
|
|
acc_feedback_temp(acfdbk_cnt) <= accum_res(acfdbk_cnt) and (not accumsload_pipe);
|
|
end loop;
|
|
end if;
|
|
end process;
|
|
end generate IFACCUM;
|
|
|
|
|
|
IFGFAM5: if (stratixiii_block) generate
|
|
process (output_result, overflow_int, chainout_overflow_int, shift_rot_result, chainout_output, clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3, unsigned_sub1_overflow_reg, unsigned_sub3_overflow_reg)
|
|
|
|
variable head_result_int : integer := 0;
|
|
variable res_cnt : integer := 0;
|
|
variable result_pipe : pipeline_accum := (others => (others => '0'));
|
|
variable result_stxiii : std_logic_vector (width_result - 1 downto 0) := (others => '0');
|
|
variable result_stxiii_ext : std_logic_vector (width_result - 1 downto 0) := (others => '0');
|
|
variable count : integer := 0;
|
|
variable overflow_stat_pipe_reg : std_logic_vector (extra_latency downto 0) := (others => '0');
|
|
variable head_overflow_int : integer := 0;
|
|
|
|
begin
|
|
if (extra_latency = 0) then
|
|
if (not (shift_mode = "NO")) then
|
|
result_stxiii := shift_rot_result((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
|
|
elsif (chainout_adder = "YES") then
|
|
result_stxiii := chainout_output((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
|
|
elsif (input_source_b0 = "LOOPBACK") then
|
|
result_stxiii := output_result((width_result - 1 + (int_width_b - width_b)) downto int_width_b - width_b);
|
|
else
|
|
result_stxiii := output_result((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
|
|
end if;
|
|
|
|
-- need to extend the MSB for cases where width_result is larger than width_a + width_b
|
|
if ((chainout_adder = "YES") or (accumulator = "YES")) then
|
|
result_stxiii_ext(width_result - 1 downto 0) := result_stxiii(width_result - 1 downto 0);
|
|
elsif ((number_of_multipliers = 1) and (width_result > width_a + width_b)) then
|
|
if (((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) and (unsigned_sub1_overflow_reg = '0' and unsigned_sub3_overflow_reg = '0')) then
|
|
for res_cnt in 1 to (width_result - width_a - width_b) loop
|
|
result_stxiii_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - width_a - width_b) loop
|
|
result_stxiii_ext(width_result - res_cnt) := result_stxiii(width_a + width_b - 1);
|
|
end loop;
|
|
end if;
|
|
result_stxiii_ext(width_a + width_b - 1 downto 0) := result_stxiii(width_a + width_b - 1 downto 0);
|
|
elsif (((number_of_multipliers = 2) or (input_source_b0 = "LOOPBACK")) and (width_result > width_a + width_b + 1)) then
|
|
if (((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) and (unsigned_sub1_overflow_reg = '0' and unsigned_sub3_overflow_reg = '0')) then
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
|
|
result_stxiii_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
|
|
result_stxiii_ext(width_result - res_cnt) := result_stxiii(width_a + width_b);
|
|
end loop;
|
|
end if;
|
|
result_stxiii_ext(width_a + width_b downto 0) := result_stxiii(width_a + width_b downto 0);
|
|
elsif ((number_of_multipliers > 2) and (width_result > width_a + width_b + 2)) then
|
|
if (((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) and (unsigned_sub1_overflow_reg = '0' and unsigned_sub3_overflow_reg = '0')) then
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
|
|
result_stxiii_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
|
|
result_stxiii_ext(width_result - res_cnt) := result_stxiii(width_a + width_b + 1);
|
|
end loop;
|
|
end if;
|
|
result_stxiii_ext(width_a + width_b + 1 downto 0) := result_stxiii(width_a + width_b + 1 downto 0);
|
|
else
|
|
result_stxiii_ext(width_result - 1 downto 0) := result_stxiii(width_result - 1 downto 0);
|
|
end if;
|
|
|
|
result <= result_stxiii_ext;
|
|
if(chainout_saturation /= "NO") then
|
|
overflow <= chainout_overflow_int ;
|
|
else
|
|
overflow <= overflow_int;
|
|
end if;
|
|
|
|
else
|
|
if (input_source_b0 = "LOOPBACK") then
|
|
result_stxiii := output_result((width_result - 1 + (int_width_b - width_b)) downto int_width_b - width_b);
|
|
else
|
|
result_stxiii := output_result((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
|
|
end if;
|
|
|
|
if ((chainout_adder = "YES") or (accumulator = "YES")) then
|
|
result_stxiii_ext(width_result - 1 downto 0) := result_stxiii(width_result - 1 downto 0);
|
|
elsif ((number_of_multipliers = 1) and (width_result > int_width_a + int_width_b)) then
|
|
if (((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) and (unsigned_sub1_overflow_reg = '0' and unsigned_sub3_overflow_reg = '0')) then
|
|
for res_cnt in 1 to (width_result - int_width_a - int_width_b) loop
|
|
result_stxiii_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - int_width_a - int_width_b) loop
|
|
result_stxiii_ext(width_result - res_cnt) := result_stxiii(int_width_a + int_width_b - 1);
|
|
end loop;
|
|
end if;
|
|
result_stxiii_ext(int_width_a + int_width_b - 1 downto 0) := result_stxiii(int_width_a + int_width_b - 1 downto 0);
|
|
elsif (((number_of_multipliers = 2) or (input_source_b0 = "LOOPBACK")) and (width_result > int_width_a + int_width_b + 1)) then
|
|
if (((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) and (unsigned_sub1_overflow_reg = '0' and unsigned_sub3_overflow_reg = '0')) then
|
|
for res_cnt in 1 to (width_result - int_width_a - int_width_b - 1) loop
|
|
result_stxiii_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - int_width_a - int_width_b - 1) loop
|
|
result_stxiii_ext(width_result - res_cnt) := result_stxiii(int_width_a + int_width_b);
|
|
end loop;
|
|
end if;
|
|
result_stxiii_ext(int_width_a + int_width_b downto 0) := result_stxiii(int_width_a + int_width_b downto 0);
|
|
elsif ((number_of_multipliers > 2) and (width_result > int_width_a + int_width_b + 2)) then
|
|
if (((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) and (unsigned_sub1_overflow_reg = '0' and unsigned_sub3_overflow_reg = '0')) then
|
|
for res_cnt in 1 to (width_result - int_width_a - int_width_b - 2) loop
|
|
result_stxiii_ext(width_result - res_cnt) := '0';
|
|
end loop;
|
|
else
|
|
for res_cnt in 1 to (width_result - int_width_a - int_width_b - 2) loop
|
|
result_stxiii_ext(width_result - res_cnt) := result_stxiii(int_width_a + int_width_b + 1);
|
|
end loop;
|
|
end if;
|
|
result_stxiii_ext(int_width_a + int_width_b + 1 downto 0) := result_stxiii(int_width_a + int_width_b + 1 downto 0);
|
|
else
|
|
result_stxiii_ext(width_result - 1 downto 0) := result_stxiii(width_result - 1 downto 0);
|
|
end if;
|
|
|
|
if(output_aclr = "ACLR0" and aclr0 = '1') then
|
|
for count in 0 to extra_latency loop
|
|
result_pipe(count) := (others => '0');
|
|
overflow_stat_pipe_reg (count) := '0';
|
|
head_result_siii <= 0;
|
|
head_overflow <= 0;
|
|
result <= (others => '0');
|
|
overflow <= '0';
|
|
end loop;
|
|
elsif(output_aclr = "ACLR1" and aclr1 = '1') then
|
|
for count in 0 to extra_latency loop
|
|
result_pipe(count) := (others => '0');
|
|
overflow_stat_pipe_reg (count) := '0';
|
|
head_result_siii <= 0;
|
|
head_overflow <= 0;
|
|
result <= (others => '0');
|
|
overflow <= '0';
|
|
end loop;
|
|
elsif(output_aclr = "ACLR2" and aclr2 = '1') then
|
|
for count in 0 to extra_latency loop
|
|
result_pipe(count) := (others => '0');
|
|
overflow_stat_pipe_reg (count) := '0';
|
|
head_result_siii <= 0;
|
|
head_overflow <= 0;
|
|
result <= (others => '0');
|
|
overflow <= '0';
|
|
end loop;
|
|
elsif(output_aclr = "ACLR3" and aclr3 = '1') then
|
|
for count in 0 to extra_latency loop
|
|
result_pipe(count) := (others => '0');
|
|
overflow_stat_pipe_reg (count) := '0';
|
|
head_result_siii <= 0;
|
|
head_overflow <= 0;
|
|
result <= (others => '0');
|
|
overflow <= '0';
|
|
end loop;
|
|
end if;
|
|
|
|
if ((output_register = "CLOCK0") and (rising_edge(clock0) and ena0 = '1')) then
|
|
head_result_int := head_result_siii;
|
|
head_overflow_int := head_overflow;
|
|
result_pipe(head_result_int) := result_stxiii_ext;
|
|
if(chainout_saturation /= "NO") then
|
|
overflow_stat_pipe_reg (head_overflow_int) := chainout_overflow_int;
|
|
else
|
|
overflow_stat_pipe_reg (head_overflow_int) := overflow_int;
|
|
end if;
|
|
head_result_int := (head_result_int +1) mod (extra_latency);
|
|
head_overflow_int := (head_overflow_int +1) mod (extra_latency);
|
|
overflow <= overflow_stat_pipe_reg(head_overflow_int);
|
|
result <= result_pipe(head_result_int);
|
|
head_result_siii <= head_result_int;
|
|
head_overflow <= head_overflow_int;
|
|
elsif ((output_register = "CLOCK1") and (rising_edge(clock1) and ena1 = '1')) then
|
|
head_result_int := head_result_siii;
|
|
head_overflow_int := head_overflow;
|
|
result_pipe(head_result_int) := result_stxiii_ext;
|
|
if(chainout_saturation /= "NO") then
|
|
overflow_stat_pipe_reg (head_overflow_int) := chainout_overflow_int;
|
|
else
|
|
overflow_stat_pipe_reg (head_overflow_int) := overflow_int;
|
|
end if;
|
|
head_result_int := (head_result_int +1) mod (extra_latency);
|
|
head_overflow_int := (head_overflow_int +1) mod (extra_latency);
|
|
overflow <= overflow_stat_pipe_reg(head_overflow_int);
|
|
result <= result_pipe(head_result_int);
|
|
head_result_siii <= head_result_int;
|
|
head_overflow <= head_overflow_int;
|
|
elsif ((output_register = "CLOCK2") and (rising_edge(clock2) and ena2 = '1')) then
|
|
head_result_int := head_result_siii;
|
|
head_overflow_int := head_overflow;
|
|
result_pipe(head_result_int) := result_stxiii_ext;
|
|
if(chainout_saturation /= "NO") then
|
|
overflow_stat_pipe_reg (head_overflow_int) := chainout_overflow_int;
|
|
else
|
|
overflow_stat_pipe_reg (head_overflow_int) := overflow_int;
|
|
end if;
|
|
head_result_int := (head_result_int +1) mod (extra_latency);
|
|
head_overflow_int := (head_overflow_int +1) mod (extra_latency);
|
|
overflow <= overflow_stat_pipe_reg(head_overflow_int);
|
|
result <= result_pipe(head_result_int);
|
|
head_result_siii <= head_result_int;
|
|
head_overflow <= head_overflow_int;
|
|
elsif ((output_register = "CLOCK3") and (rising_edge(clock3) and ena3 = '1')) then
|
|
head_result_int := head_result_siii;
|
|
head_overflow_int := head_overflow;
|
|
result_pipe(head_result_int) := result_stxiii_ext;
|
|
if(chainout_saturation /= "NO") then
|
|
overflow_stat_pipe_reg (head_overflow_int) := chainout_overflow_int;
|
|
else
|
|
overflow_stat_pipe_reg (head_overflow_int) := overflow_int;
|
|
end if;
|
|
head_result_int := (head_result_int +1) mod (extra_latency);
|
|
head_overflow_int := (head_overflow_int +1) mod (extra_latency);
|
|
overflow <= overflow_stat_pipe_reg(head_overflow_int);
|
|
result <= result_pipe(head_result_int);
|
|
head_result_siii <= head_result_int;
|
|
head_overflow <= head_overflow_int;
|
|
end if;
|
|
|
|
if((width_a > 36) or (width_b > 36)) then
|
|
if (rising_edge(clock0) or rising_edge(clock1) or rising_edge(clock2) or rising_edge(clock3)) then
|
|
head_result_int := head_result_siii;
|
|
head_overflow_int := head_overflow;
|
|
result_pipe(head_result_int) := result_stxiii_ext;
|
|
overflow_stat_pipe_reg (head_overflow) := overflow_int;
|
|
head_result_int := (head_result_int +1) mod (extra_latency);
|
|
head_overflow_int := (head_overflow_int +1) mod (extra_latency);
|
|
overflow <= overflow_stat_pipe_reg(head_overflow_int);
|
|
result <= result_pipe(head_result_int);
|
|
head_result_siii <= head_result_int;
|
|
head_overflow <= head_overflow_int;
|
|
end if;
|
|
end if;
|
|
|
|
if((width_a > 36) or (width_b > 36)) then
|
|
if (rising_edge(aclr0) or rising_edge(aclr1) or rising_edge(aclr2) or rising_edge(aclr3)) then
|
|
for count in 0 to extra_latency loop
|
|
result_pipe(count) := (others => '0');
|
|
head_result_siii <= 0;
|
|
head_overflow <= 0;
|
|
result <= (others => '0');
|
|
overflow <= '0';
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
|
|
if((output_register = "UNREGISTERED") and (width_a < 36 and width_b < 36)) then
|
|
head_result_int := head_result_siii;
|
|
result_pipe(head_result_int) := result_stxiii_ext;
|
|
result <= result_pipe(head_result_int);
|
|
if(chainout_saturation /= "NO") then
|
|
overflow_stat_pipe_reg (head_overflow_int) := chainout_overflow_int;
|
|
else
|
|
overflow_stat_pipe_reg (head_overflow_int) := overflow_int;
|
|
end if;
|
|
overflow <= overflow_stat_pipe_reg(head_overflow_int);
|
|
head_result_siii <= head_result_int;
|
|
head_overflow <= head_overflow_int;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFGFAM5;
|
|
|
|
|
|
IFGFAM6: if (stratixv_block and not(preadder_mode = "SIMPLE")) generate
|
|
assert false
|
|
report "Error: Stratix V simulation model not support other mode beside simple mode in the current Quartus II Version";
|
|
end generate IFGFAM6;
|
|
|
|
end behaviour; -- end of ALTMULT_ADD
|
|
|
|
-- START ENTITY HEADER ---------------------------------------------------------
|
|
--
|
|
-- Entity Name : altfp_mult
|
|
--
|
|
-- Description : Parameterized floating point multiplier megafunction.
|
|
-- This module implements IEEE-754 Compliant Floating Poing
|
|
-- Multiplier. The module supports Single Precision, Single
|
|
-- Extended Precision, and Double Precision floating point
|
|
-- multiplication.
|
|
--
|
|
-- Limitations : Fixed clock latency with 4 clock cycle delay.
|
|
--
|
|
--Results expected : result of multiplication and the result's status bits
|
|
|
|
-- END ENTITY HEADER -----------------------------------------------------------
|
|
|
|
|
|
-- LIBRARY USED-----------------------------------------------------------------
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use work.ALTERA_COMMON_CONVERSION.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altfp_mult is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
-- exponent width, Minimum = 8, Maximum = 31
|
|
width_exp : natural := 8;
|
|
-- mantissa width, Minimum = 23, Maximum = 52
|
|
width_man : natural := 23;
|
|
-- Specifies whether to use dedicated multiplier circuitry.
|
|
dedicated_multiplier_circuitry : string := "AUTO";
|
|
reduced_functionality : string := "NO";
|
|
pipeline : natural := 5;
|
|
denormal_support : string := "YES";
|
|
exception_handling : string := "YES";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altfp_mult" );
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
-- Clock input to the multiplier.(Required)
|
|
clock : in std_logic;
|
|
-- Clock enable for the multiplier.
|
|
clk_en : in std_logic := '1';
|
|
-- Asynchronous clear for the multiplier.
|
|
aclr : in std_logic := '0';
|
|
-- Data input to the multiplier.(Required)
|
|
dataa : in std_logic_vector(width_exp + width_man downto 0);
|
|
datab : in std_logic_vector(width_exp + width_man downto 0);
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
-- Multiplier output port.(Required)
|
|
result : out std_logic_vector(width_exp + width_man downto 0);
|
|
overflow : out std_logic ;
|
|
underflow : out std_logic ;
|
|
zero : out std_logic;
|
|
denormal : out std_logic ;
|
|
indefinite : out std_logic;
|
|
nan : out std_logic );
|
|
|
|
end altfp_mult;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ACHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of altfp_mult is
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant LATENCY : integer := pipeline -1;
|
|
constant WIDTH_MAN_EXP : integer := width_exp + width_man;
|
|
|
|
-- TYPE DECLARATION
|
|
type PIPELINE_MULT is array (LATENCY downto 0) of std_logic_vector(WIDTH_MAN_EXP + 6 downto 0);
|
|
|
|
-- FUNCTION DECLARATION
|
|
-- Bitwise left shift
|
|
procedure shift_left ( val : inout std_logic_vector) is
|
|
variable temp : std_logic_vector((val'length - 1) downto 0);
|
|
begin
|
|
temp := val;
|
|
if (val'length > 1) then
|
|
for i in temp'high downto 1 loop
|
|
temp(i) := temp(i-1);
|
|
end loop;
|
|
end if;
|
|
temp(0) :='0';
|
|
val := temp;
|
|
end shift_left;
|
|
|
|
-- Bitwise right shift
|
|
procedure shift_right ( cout: in std_logic;
|
|
val : inout std_logic_vector ) is
|
|
variable temp : std_logic_vector(val'length-1 downto 0);
|
|
begin
|
|
temp := val;
|
|
if (val'length > 1) then
|
|
for i in 0 to temp'high - 1 loop
|
|
temp(i) := temp(i+1);
|
|
end loop;
|
|
end if;
|
|
temp(temp'high) := cout;
|
|
val := temp;
|
|
end shift_right;
|
|
|
|
-- Check whether all the bits is '0' or not
|
|
function bit_all_0 ( val : std_logic_vector ) return boolean is
|
|
variable all_0 : boolean := true;
|
|
begin
|
|
for i in val'range loop
|
|
if (val(i) = '1') then
|
|
all_0 := false;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
return all_0;
|
|
end bit_all_0;
|
|
|
|
-- Check whether all the bits is '0' or not (with specific range)
|
|
function bit_all_0 (val : std_logic_vector;
|
|
index1 : integer;
|
|
index2 : integer ) return boolean is
|
|
variable all_0 : boolean := true;
|
|
begin
|
|
for i in index1 to index2 loop
|
|
if (val(i) = '1') then
|
|
all_0 := false;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
return all_0;
|
|
end bit_all_0;
|
|
|
|
-- add val1 to temporary result
|
|
procedure add_bits( val1 : in std_logic_vector;
|
|
result : inout std_logic_vector;
|
|
cout : out std_logic) is
|
|
variable co : std_logic;
|
|
variable i : integer := 0;
|
|
begin
|
|
co := '0';
|
|
for i in 0 to val1'high loop
|
|
if (co = '0') then
|
|
if (val1(i) /= result(i + width_man + 1)) then
|
|
result(i + width_man + 1) := '1';
|
|
else
|
|
co := val1(i) and result(i + width_man + 1);
|
|
result(i + width_man + 1) := '0';
|
|
end if;
|
|
else
|
|
co := val1(i) or result(i + width_man + 1);
|
|
if (val1(i) /= result(i + width_man + 1)) then
|
|
result(i + width_man + 1) := '0';
|
|
else
|
|
result(i + width_man + 1) := '1';
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
cout := co;
|
|
end add_bits;
|
|
|
|
|
|
begin
|
|
|
|
-- basic error checking for invalid deserialization factors
|
|
MSG: process
|
|
begin
|
|
-- Check for illegal mode setting
|
|
if ((width_exp + width_man) >= 64) then
|
|
ASSERT FALSE
|
|
REPORT "The sum of width_exp (" & INT_TO_STR_ARITH(width_exp) &
|
|
") and width_man (" & INT_TO_STR_ARITH(width_man) &
|
|
") must be less than 64"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if (width_exp < 8) then
|
|
ASSERT FALSE
|
|
REPORT "width_exp (" & INT_TO_STR_ARITH(width_exp) & ") must be at least 8"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if (width_man < 23) then
|
|
ASSERT FALSE
|
|
REPORT "width_man (" & INT_TO_STR_ARITH(width_man) & ") must be at least 23"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if not ((width_exp >= 11) or ((width_exp = 8) and (width_man = 23))) then
|
|
ASSERT FALSE
|
|
REPORT "Found width_exp (" & INT_TO_STR_ARITH(width_exp) &
|
|
") inside the range of Single Precision. width_exp must be 8" &
|
|
" and width_man must be 23 for Single Precision"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if not ((width_man >= 31) or ((width_exp = 8) and (width_man = 23))) then
|
|
ASSERT FALSE
|
|
REPORT "Found width_man (" & INT_TO_STR_ARITH(width_man) &
|
|
") inside the range of Single Precision. width_exp must be 8" &
|
|
" and width_man must be 23 for Single Precision"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if (width_exp >= width_man) then
|
|
ASSERT FALSE
|
|
REPORT "width_exp (" & INT_TO_STR_ARITH(width_exp) &
|
|
") must be less than width_man (" & INT_TO_STR_ARITH(width_man) & ")"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((pipeline /= 5) and (pipeline /= 6) and (pipeline /= 10) and (pipeline /= 11)) then
|
|
ASSERT FALSE
|
|
REPORT "The legal value for pipeline is 5, 6, 10 or 11."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((reduced_functionality /= "NO") and (reduced_functionality /= "YES")) then
|
|
ASSERT FALSE
|
|
REPORT "reduced_functionality value must be ""YES"" or ""NO""."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if ((denormal_support /= "NO") and (denormal_support /= "YES")) then
|
|
ASSERT FALSE
|
|
REPORT "denormal_support value must be ""YES"" or ""NO""."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (reduced_functionality /= "NO") then
|
|
ASSERT FALSE
|
|
REPORT "The Clearbox support is available for reduced functionality Floating Point Multiplier."
|
|
SEVERITY WARNING;
|
|
end if;
|
|
wait;
|
|
end process; -- MSG process
|
|
|
|
MULTIPLY_FP: process(clock, aclr)
|
|
variable exp_dataa : integer := 0;
|
|
variable exp_datab : integer := 0;
|
|
variable exp_result : integer := 0;
|
|
variable mant_dataa : std_logic_vector (width_man downto 0)
|
|
:= (others => '0');
|
|
variable mant_datab : std_logic_vector (width_man downto 0)
|
|
:= (others => '0');
|
|
variable mant_result : std_logic_vector ((2 * (width_man + 1)) - 1 downto 0)
|
|
:= (others => '0');
|
|
variable cout : std_logic := '0';
|
|
variable zero_mant_dataa : boolean := false;
|
|
variable zero_mant_datab : boolean := false;
|
|
variable zero_dataa : boolean := false;
|
|
variable zero_datab : boolean := false;
|
|
variable inf_dataa : boolean := false;
|
|
variable inf_datab : boolean := false;
|
|
variable nan_dataa : boolean := false;
|
|
variable nan_datab : boolean := false;
|
|
variable den_dataa : boolean := false;
|
|
variable den_datab : boolean := false;
|
|
variable no_multiply : boolean := false;
|
|
variable no_rounding : boolean := false;
|
|
variable mant_result_msb : std_logic := '0';
|
|
variable sticky_bit : std_logic := '0';
|
|
variable round_bit : std_logic := '0';
|
|
variable guard_bit : std_logic := '0';
|
|
variable carry : boolean := false;
|
|
variable temp_result : PIPELINE_MULT := (others => (others => '0'));
|
|
|
|
begin
|
|
|
|
if (aclr = '1') then --clear the output ports
|
|
temp_result := (others => (others => '0'));
|
|
for i in LATENCY downto 0 loop
|
|
temp_result(i)(WIDTH_MAN_EXP + 3) := '1'; -- set zero status
|
|
end loop;
|
|
result <= (others => '0');
|
|
overflow <= '0';
|
|
underflow <= '0';
|
|
zero <= '1';
|
|
denormal <= '0';
|
|
indefinite <= '0';
|
|
nan <= '0';
|
|
elsif (clock = '1') and clock'event and (clock'last_value = '0') then
|
|
if (clk_en = '1') then
|
|
-- Create latency for the output result
|
|
for i in LATENCY downto 1 loop
|
|
temp_result(i) := temp_result(i - 1);
|
|
end loop;
|
|
|
|
temp_result(0) := (others => '0');
|
|
mant_result := (others => '0');
|
|
|
|
--convert exponent of dataa[] to integer
|
|
exp_dataa := 0;
|
|
for i in 0 to width_exp -1 loop
|
|
if (dataa(width_man + i) = '1') then
|
|
exp_dataa := (2**i) + exp_dataa;
|
|
end if;
|
|
end loop;
|
|
|
|
--convert exponent of datab[] to integer
|
|
exp_datab := 0;
|
|
for i in 0 to width_exp -1 loop
|
|
if (datab(width_man + i) = '1') then
|
|
exp_datab := (2**i) + exp_datab;
|
|
end if;
|
|
end loop;
|
|
|
|
--check whether all the bits in mantissa of dataa[] is '0'
|
|
zero_mant_dataa := true;
|
|
for i in 0 to width_man -1 loop
|
|
if (dataa(i) = '1') then
|
|
zero_mant_dataa := false;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
|
|
--check whether all the bits in mantissa of datab[] is '0'
|
|
zero_mant_datab := true;
|
|
for i in 0 to width_man -1 loop
|
|
if (datab(i) = '1') then
|
|
zero_mant_datab := false;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
|
|
--check whether dataa is special input
|
|
zero_dataa := false;
|
|
den_dataa := false;
|
|
inf_dataa := false;
|
|
nan_dataa := false;
|
|
if (exp_dataa = 0) then
|
|
if ((zero_mant_dataa = true) or
|
|
(reduced_functionality /= "NO")) then
|
|
zero_dataa := true;
|
|
else
|
|
if (denormal_support = "YES") then
|
|
den_dataa := true;
|
|
else
|
|
zero_dataa := true;
|
|
end if;
|
|
end if;
|
|
elsif (exp_dataa = (2**width_exp) -1) then
|
|
if (zero_mant_dataa = true) then
|
|
inf_dataa := true;
|
|
else
|
|
nan_dataa := true;
|
|
end if;
|
|
end if;
|
|
|
|
--check whether datab is special input
|
|
zero_datab := false;
|
|
den_datab := false;
|
|
inf_datab := false;
|
|
nan_datab := false;
|
|
if (exp_datab = 0) then
|
|
if ((zero_mant_datab = true) or
|
|
(reduced_functionality /= "NO")) then
|
|
zero_datab := true;
|
|
else
|
|
if (denormal_support = "YES") then
|
|
den_datab := true;
|
|
else
|
|
zero_datab := true;
|
|
end if;
|
|
end if;
|
|
elsif (exp_datab = (2**width_exp) -1) then
|
|
if (zero_mant_datab = true) then
|
|
inf_datab := true;
|
|
else
|
|
nan_datab := true;
|
|
end if;
|
|
end if;
|
|
|
|
--set status flag if special input exists
|
|
no_multiply := false;
|
|
if (nan_dataa or nan_datab or (inf_dataa and zero_datab) or
|
|
(inf_datab and zero_dataa)) then
|
|
temp_result(0)(WIDTH_MAN_EXP + 6) := '1'; --NaN
|
|
temp_result(0)(WIDTH_MAN_EXP - 1 downto width_man -1) := (others => '1');
|
|
no_multiply := true;
|
|
elsif (zero_dataa) then
|
|
temp_result(0)(WIDTH_MAN_EXP + 3) := '1'; --zero result
|
|
temp_result(0)(WIDTH_MAN_EXP downto 0) := (others => '0');
|
|
no_multiply := true;
|
|
elsif (zero_datab) then
|
|
temp_result(0)(WIDTH_MAN_EXP + 3) := '1'; --zero result
|
|
temp_result(0)(WIDTH_MAN_EXP downto 0) := (others => '0');
|
|
no_multiply := true;
|
|
elsif (inf_dataa) then
|
|
temp_result(0)(WIDTH_MAN_EXP + 1) := '1'; --overflow
|
|
temp_result(0)(WIDTH_MAN_EXP downto 0) := dataa; --result
|
|
no_multiply := true;
|
|
elsif (inf_datab) then
|
|
temp_result(0)(WIDTH_MAN_EXP + 1) := '1'; --overflow
|
|
temp_result(0)(WIDTH_MAN_EXP downto 0) := datab; --result
|
|
no_multiply := true;
|
|
end if;
|
|
|
|
-- do multiplication
|
|
if (no_multiply = false) then
|
|
|
|
--perform exponent operation
|
|
exp_result := (exp_dataa + exp_datab) - ((2**(width_exp -1)) - 1);
|
|
|
|
-- mantissa multiplication
|
|
--first operand for multiplication
|
|
mant_dataa(width_man downto 0) := "1" & dataa(width_man - 1 downto 0);
|
|
|
|
--second operand for multiplication
|
|
mant_datab(width_man downto 0) := "1" & datab(width_man - 1 downto 0);
|
|
|
|
--multiplication using add and shift algorithm
|
|
for i in 0 to width_man loop
|
|
cout := '0';
|
|
if (mant_dataa(i) = '1') then
|
|
add_bits(mant_datab, mant_result, cout);
|
|
end if;
|
|
shift_right(cout, mant_result);
|
|
end loop;
|
|
sticky_bit := '0';
|
|
mant_result_msb := mant_result(mant_result'high);
|
|
--Normalize the Result
|
|
if (mant_result_msb = '1') then
|
|
sticky_bit := mant_result(mant_result'low);
|
|
shift_right('0', mant_result);
|
|
exp_result := exp_result + 1;
|
|
end if;
|
|
round_bit := mant_result(width_man - 1);
|
|
guard_bit := mant_result(width_man);
|
|
no_rounding := false;
|
|
|
|
-- check whether should perform rounding or not
|
|
if (round_bit = '0') then
|
|
no_rounding := true;
|
|
else
|
|
if (reduced_functionality = "NO") then
|
|
for i in 0 to width_man - 2 loop
|
|
sticky_bit := sticky_bit or mant_result(i);
|
|
end loop;
|
|
else
|
|
sticky_bit := (mant_result(width_man - 2) and
|
|
mant_result_msb);
|
|
end if;
|
|
|
|
if ((sticky_bit = '0') and (guard_bit = '0')) then
|
|
no_rounding := true;
|
|
end if;
|
|
|
|
end if;
|
|
if (no_rounding = false) then
|
|
--do rounding
|
|
carry := true;
|
|
for i in width_man to mant_result'high loop
|
|
if (carry = true) then
|
|
if (mant_result(i) = '0') then
|
|
mant_result(i) := '1';
|
|
carry := false;
|
|
else
|
|
mant_result(i) := '0';
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
|
|
-- If the mantissa of the result is 10.00.. after rounding, right shift the
|
|
-- mantissa of the result by 1 bit and increase the exponent of the result by 1.
|
|
if (mant_result(mant_result'high) = '1') then
|
|
shift_right('0', mant_result);
|
|
exp_result := exp_result + 1;
|
|
end if;
|
|
end if;
|
|
|
|
--Normalize the Result
|
|
if ((not bit_all_0(mant_result)) and (mant_result(mant_result'high -1) = '0')) then
|
|
while ((mant_result(mant_result'high -1) = '0') and (exp_result /= 0)) loop
|
|
shift_left(mant_result);
|
|
exp_result := exp_result - 1;
|
|
end loop;
|
|
elsif ((exp_result < 0) and (exp_result >= - (2 * width_man))) then
|
|
while (exp_result /= 0) loop
|
|
shift_right('0', mant_result);
|
|
exp_result := exp_result + 1;
|
|
end loop;
|
|
end if;
|
|
|
|
--set status flag "indefinite" if normal * denormal
|
|
--(ignore other status port since we dont care the output
|
|
if (den_dataa or den_datab) then
|
|
temp_result(0)(WIDTH_MAN_EXP + 5) := '1'; --indefinite
|
|
--set status flag if special output exists
|
|
elsif (exp_result >= ((2**width_exp) - 1)) then
|
|
temp_result(0)(WIDTH_MAN_EXP + 1) := '1'; --overflow
|
|
elsif (exp_result < 0) then
|
|
temp_result(0)(WIDTH_MAN_EXP + 2) := '1'; --underflow
|
|
temp_result(0)(WIDTH_MAN_EXP + 3) := '1'; --zero
|
|
elsif (exp_result = 0) then
|
|
temp_result(0)(WIDTH_MAN_EXP + 2) := '1'; --underflow
|
|
if (bit_all_0 (mant_result, width_man + 1, mant_result'high -1)) then
|
|
temp_result(0)(WIDTH_MAN_EXP + 3) := '1'; --zero
|
|
else
|
|
temp_result(0)(WIDTH_MAN_EXP + 4) := '1'; --denormal
|
|
end if;
|
|
end if;
|
|
|
|
--get result mantissa
|
|
if (exp_result < 0) then --result underflow
|
|
temp_result(0)(width_man - 1 downto 0) := (others => '0');
|
|
elsif (exp_result = 0) then --denormalized output
|
|
if ((reduced_functionality = "NO") and (denormal_support = "YES")) then
|
|
for i in (mant_result'high - 1) downto (mant_result'high - width_man) loop
|
|
temp_result(0)(i - width_man - 1) := mant_result(i);
|
|
end loop;
|
|
else
|
|
temp_result(0)(width_man - 1 downto 0) := (others => '0');
|
|
temp_result(0)(WIDTH_MAN_EXP + 3) := '1';
|
|
end if;
|
|
elsif exp_result >= ((2**width_exp) -1) then --result overflow
|
|
temp_result(0)(width_man - 1 downto 0) := (others => '0');
|
|
elsif (exp_result > 0) then --normalized output
|
|
for i in (mant_result'high - 2) downto (mant_result'high - width_man - 1) loop
|
|
temp_result(0)(i - width_man) := mant_result(i);
|
|
end loop;
|
|
end if;
|
|
|
|
--get result exponent
|
|
if (exp_result <= 0) then
|
|
temp_result(0)(WIDTH_MAN_EXP -1 downto width_man) := (others => '0');
|
|
elsif (exp_result >= ((2**width_exp) -1)) then
|
|
for i in width_man to (WIDTH_MAN_EXP -1) loop
|
|
temp_result(0)(i) := '1';
|
|
end loop;
|
|
else
|
|
--convert integer to binary bit
|
|
for i in width_man to (WIDTH_MAN_EXP -1) loop
|
|
if ((exp_result mod 2) = 1) then
|
|
temp_result(0)(i) := '1';
|
|
else
|
|
temp_result(0)(i) := '0';
|
|
end if;
|
|
exp_result := exp_result / 2;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
|
|
--get result sign
|
|
temp_result(0)(WIDTH_MAN_EXP) := dataa(dataa'high) xor datab(datab'high);
|
|
end if;
|
|
end if;
|
|
|
|
--output port
|
|
result <= temp_result(LATENCY)(WIDTH_MAN_EXP downto 0 );
|
|
overflow <= temp_result(LATENCY)(WIDTH_MAN_EXP + 1 );
|
|
|
|
if ((reduced_functionality = "YES") or (denormal_support = "YES")) then
|
|
underflow <= temp_result(LATENCY)(WIDTH_MAN_EXP + 2 );
|
|
else
|
|
underflow <= '0';
|
|
end if;
|
|
|
|
if (reduced_functionality = "NO") then
|
|
zero <= temp_result(LATENCY)(WIDTH_MAN_EXP + 3 );
|
|
|
|
if (denormal_support = "YES") then
|
|
denormal <= temp_result(LATENCY)(WIDTH_MAN_EXP + 4 );
|
|
indefinite <= temp_result(LATENCY)(WIDTH_MAN_EXP + 5 );
|
|
else
|
|
denormal <= '0';
|
|
indefinite <= '0';
|
|
end if;
|
|
else
|
|
zero <= '0';
|
|
denormal <= '0';
|
|
indefinite <= '0';
|
|
end if;
|
|
nan <= temp_result(LATENCY)(WIDTH_MAN_EXP + 6 );
|
|
|
|
end process MULTIPLY_FP;
|
|
|
|
end behavior; -- altfp_mult
|
|
-- END OF ARCHITECTURE
|
|
|
|
-- START ENTITY HEADER ---------------------------------------------------------
|
|
--
|
|
-- Entity Name : altsqrt
|
|
--
|
|
-- Description : Parameterized integer square root megafunction.
|
|
-- This module computes q[] and remainder so that
|
|
-- q[]^2 + remainder[] == radical[] (remainder <= 2 * q[])
|
|
-- It can support the sequential mode(pipeline > 0) or
|
|
-- combinational mode (pipeline = 0).
|
|
--
|
|
-- Limitations : The radical is assumed to be unsigned integer.
|
|
--
|
|
--Results expected : Square root of the radical and the remainder.
|
|
|
|
-- END ENTITY HEADER -----------------------------------------------------------
|
|
|
|
|
|
-- LIBRARY USED
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use IEEE.std_logic_unsigned.all;
|
|
use work.ALTERA_COMMON_CONVERSION.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altsqrt is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
q_port_width : natural := 1; -- The width of the q port
|
|
r_port_width : natural := 1; -- The width of the remainder port
|
|
width : natural := 1; -- The width of the radical
|
|
pipeline : natural := 0; -- The latency for the output
|
|
-- (0 for comb. mode)
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altsqrt" );
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
|
|
-- Input port for the radical
|
|
radical : in std_logic_vector(width - 1 downto 0);
|
|
|
|
-- Clock port
|
|
clk : in std_logic := '1';
|
|
|
|
-- Clock enable port
|
|
ena : in std_logic := '1';
|
|
|
|
-- Asynchronous clear port
|
|
aclr : in std_logic := '0';
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
|
|
-- Output port for returning the square root of the radical
|
|
q : out std_logic_vector( q_port_width - 1 downto 0)
|
|
:= (others => '0');
|
|
|
|
-- Output port for returning the remainder of the square root.
|
|
remainder : out std_logic_vector( r_port_width - 1 downto 0)
|
|
:= (others => '0') );
|
|
|
|
end altsqrt;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
architecture behavior of altsqrt is
|
|
|
|
-- TYPE DECLARATION
|
|
type PIPELINE_Q is array (pipeline downto 0) of std_logic_vector( q_port_width - 1 downto 0);
|
|
type PIPELINE_R is array (pipeline downto 0) of std_logic_vector( r_port_width - 1 downto 0);
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal q_pipe : std_logic_vector (q_port_width - 1 downto 0)
|
|
:= (others => '0');
|
|
signal q_value : std_logic_vector (q_port_width - 1 downto 0)
|
|
:= (others => '0');
|
|
signal remainder_pipe : std_logic_vector (r_port_width - 1 downto 0)
|
|
:= (others => '0');
|
|
signal remainder_value : std_logic_vector (r_port_width - 1 downto 0)
|
|
:= (others => '0');
|
|
|
|
begin
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
q <= q_pipe when (pipeline > 0) else q_value;
|
|
remainder <= remainder_pipe when (pipeline > 0) else remainder_value;
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
-- Perform square root calculation.
|
|
-- In general, below are the steps to calculate the square root and the
|
|
-- remainder.
|
|
--
|
|
-- Start of with q = 0 and remainder= 0
|
|
-- For every iteration, do the same thing:
|
|
-- 1) Shift in the next 2 bits of the radical into the remainder
|
|
-- Eg. if the radical is b"101100". For the first iteration,
|
|
-- the remainder will be equal to b"10".
|
|
-- 2) Compare it to the 4* q + 1
|
|
-- 3) if the remainder is greater than or equal to 4*q + 1
|
|
-- remainder = remainder - (4*q + 1)
|
|
-- q = 2*q + 1
|
|
-- otherwise
|
|
-- q = 2*q
|
|
SQUARE_ROOT: process(radical)
|
|
variable value1 : integer := 0;
|
|
variable value2 : integer := 0;
|
|
variable i : integer := 0;
|
|
variable index : integer := 0;
|
|
variable q_index : integer := 0;
|
|
variable q_temp : std_logic_vector (q_port_width - 1 downto 0)
|
|
:= (others => '0');
|
|
variable q_value_temp : std_logic_vector (q_port_width - 1 downto 0)
|
|
:= (others => '0');
|
|
variable q_value_comp : std_logic_vector (r_port_width downto 0)
|
|
:= (others => '0');
|
|
variable r_temp : std_logic_vector (r_port_width downto 0)
|
|
:= (others => '0');
|
|
variable radical_tmp : std_logic_vector(width - 1 downto 0)
|
|
:= (others => '0');
|
|
begin
|
|
|
|
-- Check for illegal mode
|
|
if (width < 1) then
|
|
ASSERT FALSE
|
|
REPORT "width (" & INT_TO_STR_ARITH(width) & ") must be greater than 0."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
-- Reset variables
|
|
value1 := 0;
|
|
value2 := 0;
|
|
q_index := (width - 1) / 2;
|
|
index := width;
|
|
q_temp := (others => '0');
|
|
q_value_temp := (others => '0');
|
|
q_value_comp := (others => '0');
|
|
r_temp := (others => '0');
|
|
radical_tmp := radical;
|
|
|
|
-- If the number of the bits of the radical is an odd number,
|
|
-- Then for the first iteration, only the 1st bit will be shifted
|
|
-- into the remainder.
|
|
-- Eg. if the radical is b"11111", then the remainder is b"01".
|
|
if ((width rem 2) = 1) then
|
|
value1 := 0;
|
|
|
|
if (radical_tmp(width - 1) = '1') then
|
|
value2 := 1;
|
|
else
|
|
value2 := 0;
|
|
end if;
|
|
|
|
index := index + 1;
|
|
elsif (width > 1) then
|
|
-- Otherwise, for the first iteration, the first two bits will be
|
|
-- shifted into the remainder.
|
|
-- Eg. if the radical is b"101111", then the remainder is b"10".
|
|
if (radical_tmp(width - 1) = '1') then
|
|
value1 := 1;
|
|
else
|
|
value1 := 0;
|
|
end if;
|
|
|
|
if (radical_tmp(width - 2) = '1') then
|
|
value2 := 1;
|
|
else
|
|
value2 := 0;
|
|
end if;
|
|
|
|
end if;
|
|
|
|
-- For every iteration
|
|
while (index >= 2) loop
|
|
-- Get the remainder value by shifting in the next 2 bits
|
|
-- of the radical into the remainder
|
|
r_temp := r_temp(r_port_width-2 downto 0) & conv_std_logic_vector(value1, 1) & conv_std_logic_vector(value2, 1);
|
|
q_value_comp := q_value_temp(q_port_width-1 downto 0) & conv_std_logic_vector(1, 2);
|
|
|
|
-- if remainder >= (4*q + 1)
|
|
if (r_temp >= q_value_comp) then
|
|
-- remainder = remainder - (4*q + 1)
|
|
r_temp := r_temp - q_value_comp;
|
|
-- q = 2*q + 1
|
|
q_value_temp := q_value_temp(q_port_width-2 downto 0) & conv_std_logic_vector(1, 1);
|
|
-- set the q[q_index] = 1
|
|
q_temp(q_index) := '1';
|
|
else -- if remainder < (4*q + 1)
|
|
-- q = 2*q
|
|
q_value_temp := q_value_temp(q_port_width-2 downto 0) & '0';
|
|
-- set the q[q_index] = 0
|
|
q_temp(q_index) := '0';
|
|
end if;
|
|
|
|
index := index - 2;
|
|
|
|
-- if not the last iteration, get the next 2 bits of the radical
|
|
if (index >= 2) then
|
|
if (radical(index - 1) = '1') then
|
|
value1 := 1;
|
|
else
|
|
value1 := 0;
|
|
end if;
|
|
|
|
if (radical(index - 2) = '1') then
|
|
value2 := 1;
|
|
else
|
|
value2 := 0;
|
|
end if;
|
|
end if;
|
|
|
|
-- Reduce the current index of q by 1
|
|
q_index := q_index - 1;
|
|
|
|
end loop;
|
|
|
|
-- Store current result into the pipeline to create latency
|
|
q_value <= q_temp;
|
|
remainder_value <= r_temp(r_port_width-1 downto 0);
|
|
|
|
end process SQUARE_ROOT;
|
|
|
|
PIPELINE_REG : process(clk, aclr)
|
|
variable pipe_ptr : natural := 0;
|
|
variable q_pipeline : PIPELINE_Q := (others => (others => '0'));
|
|
variable remainder_pipeline : PIPELINE_R := (others => (others => '0'));
|
|
begin
|
|
-- if asynchronous clear signal has been asserted
|
|
if (aclr = '1') then
|
|
-- reset pipelines and clear the output ports
|
|
q_pipeline := (others => (others => '0'));
|
|
remainder_pipeline := (others => (others => '0'));
|
|
q_pipe <= (others => '0');
|
|
remainder_pipe <= (others => '0');
|
|
|
|
elsif (rising_edge(clk)) then
|
|
if (ena = '1') then
|
|
q_pipeline(pipe_ptr) := q_value;
|
|
remainder_pipeline(pipe_ptr) := remainder_value;
|
|
|
|
if (pipeline > 1) then
|
|
pipe_ptr := (pipe_ptr + 1) mod pipeline;
|
|
end if;
|
|
|
|
q_pipe <= q_pipeline(pipe_ptr);
|
|
remainder_pipe <= remainder_pipeline(pipe_ptr);
|
|
end if;
|
|
end if;
|
|
end process PIPELINE_REG;
|
|
|
|
end behavior; -- altsqrt
|
|
-- END OF ARCHITECTURE
|
|
|
|
-- START ENTITY HEADER ---------------------------------------------------------
|
|
--
|
|
-- Entity Name : ALTCLKLOCK
|
|
--
|
|
-- Description : Phase-Locked Loop (PLL) behavioral model. Supports basic
|
|
-- PLL features such as multiplication and division of input
|
|
-- clock frequency and phase shift.
|
|
--
|
|
-- Limitations : Model supports NORMAL operation mode only. External
|
|
-- feedback mode and zero-delay-buffer mode are not simulated.
|
|
--
|
|
-- Expected results : Up to 4 clock outputs (clock0, clock1, clock2, clock_ext).
|
|
-- locked output indicates when PLL locks.
|
|
--
|
|
-- END ENTITY HEADER -----------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altclklock is
|
|
generic(
|
|
inclock_period : natural := 10000; -- units in ps
|
|
inclock_settings : string := "UNUSED";
|
|
valid_lock_cycles : natural := 5;
|
|
invalid_lock_cycles : natural := 5;
|
|
valid_lock_multiplier : natural := 5;
|
|
invalid_lock_multiplier : natural := 5;
|
|
operation_mode : string := "NORMAL";
|
|
clock0_boost : natural := 1;
|
|
clock0_divide : natural := 1;
|
|
clock0_settings : string := "UNUSED";
|
|
clock0_time_delay : string := "0";
|
|
clock1_boost : natural := 1;
|
|
clock1_divide : natural := 1;
|
|
clock1_settings : string := "UNUSED";
|
|
clock1_time_delay : string := "0";
|
|
clock2_boost : natural := 1;
|
|
clock2_divide : natural := 1;
|
|
clock2_settings : string := "UNUSED";
|
|
clock2_time_delay : string := "0";
|
|
clock_ext_boost : natural := 1;
|
|
clock_ext_divide : natural := 1;
|
|
clock_ext_settings : string := "UNUSED";
|
|
clock_ext_time_delay : string := "0";
|
|
outclock_phase_shift : natural := 0; -- units in ps
|
|
intended_device_family : string := "Stratix" ;
|
|
lpm_type : string := "altclklock";
|
|
lpm_hint : string := "UNUSED"
|
|
);
|
|
port(
|
|
inclock : in std_logic; -- required port, input reference clock
|
|
inclocken : in std_logic := '1'; -- PLL enable signal
|
|
fbin : in std_logic := '1'; -- feedback input for the PLL
|
|
|
|
clock0 : out std_logic; -- clock0 output
|
|
clock1 : out std_logic; -- clock1 output
|
|
clock2 : out std_logic; -- clock2 output
|
|
clock_ext : out std_logic; -- external clock output
|
|
locked : out std_logic -- PLL lock signal
|
|
);
|
|
|
|
--
|
|
-- function time_delay - converts time_delay in string format to time, and
|
|
-- add result to outclock_phase_shift
|
|
--
|
|
function time_delay (s : string) return time is
|
|
-- VARIABLE DECLARATION
|
|
variable outclock_phase_shift_adj : integer := 0;
|
|
variable len : integer := s'length;
|
|
variable sign : integer := 1;
|
|
variable digit : integer := 0;
|
|
|
|
begin
|
|
for i in 1 to len loop
|
|
case s(i) is
|
|
when '-' =>
|
|
if (i = 1) then
|
|
sign := -1;
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "Illegal Character "& s(i) & "in string parameter! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
when '0' =>
|
|
digit := 0;
|
|
when '1' =>
|
|
digit := 1;
|
|
when '2' =>
|
|
digit := 2;
|
|
when '3' =>
|
|
digit := 3;
|
|
when '4' =>
|
|
digit := 4;
|
|
when '5' =>
|
|
digit := 5;
|
|
when '6' =>
|
|
digit := 6;
|
|
when '7' =>
|
|
digit := 7;
|
|
when '8' =>
|
|
digit := 8;
|
|
when '9' =>
|
|
digit := 9;
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Illegal Character "& s(i) & "in string parameter! "
|
|
SEVERITY ERROR;
|
|
end case;
|
|
|
|
outclock_phase_shift_adj := (outclock_phase_shift_adj * 10) + digit;
|
|
end loop;
|
|
|
|
-- add outclock phase shift to the time delay
|
|
outclock_phase_shift_adj := outclock_phase_shift + (sign * outclock_phase_shift_adj);
|
|
|
|
-- adjust phase shift so that it is between 0 and 1 full inclock_period
|
|
while (outclock_phase_shift_adj < 0) loop
|
|
outclock_phase_shift_adj := outclock_phase_shift_adj + inclock_period;
|
|
end loop;
|
|
while (outclock_phase_shift_adj >= inclock_period) loop
|
|
outclock_phase_shift_adj := outclock_phase_shift_adj - inclock_period;
|
|
end loop;
|
|
|
|
-- return the phase shift in ps
|
|
return (outclock_phase_shift_adj * 1 ps);
|
|
end;
|
|
|
|
end altclklock;
|
|
-- END ENTITY DECLARATION
|
|
|
|
-- BEGINNING OF ARCHITECTURE BEHAVIOR
|
|
architecture behavior of altclklock is
|
|
-- SIGNAL DECLARATION
|
|
|
|
SIGNAL pll_lock : std_logic := '0';
|
|
SIGNAL check_lock : std_logic := '0';
|
|
|
|
SIGNAL clk0_tmp : std_logic := 'X';
|
|
SIGNAL clk1_tmp : std_logic := 'X';
|
|
SIGNAL clk2_tmp : std_logic := 'X';
|
|
SIGNAL extclk_tmp : std_logic := 'X';
|
|
begin
|
|
|
|
-- checking for invalid parameters
|
|
MSG: process
|
|
begin
|
|
if (inclock_period <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The period of the input clock (inclock_period) must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if ((clock0_boost <= 0) or (clock0_divide <= 0)) then
|
|
ASSERT FALSE
|
|
REPORT "The multiplication and division factors for clock0 must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if ((clock1_boost <= 0) or (clock1_divide <= 0)) then
|
|
ASSERT FALSE
|
|
REPORT "The multiplication and division factors for clock1 must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if ((clock2_boost <= 0) or (clock2_divide <= 0)) then
|
|
ASSERT FALSE
|
|
REPORT "The multiplication and division factors for clock2 must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if ((clock_ext_boost <= 0) or (clock_ext_divide <= 0)) then
|
|
ASSERT FALSE
|
|
REPORT "The multiplication and division factors for clock_ext must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (FEATURE_FAMILY_STRATIX(intended_device_family) = false) then
|
|
ASSERT FALSE
|
|
REPORT "Device family specified by the intended_device_family parameter, "& intended_device_family &", may not be supported by altclklock"
|
|
SEVERITY WARNING;
|
|
end if;
|
|
wait;
|
|
|
|
end process MSG;
|
|
|
|
LOCK: process(inclock, inclocken, pll_lock, check_lock)
|
|
-- VARIABLE DECLARATION
|
|
variable inclk_ps : time := 0 ps;
|
|
variable violation : boolean := false;
|
|
variable pll_lock_tmp : std_logic := '0';
|
|
variable start_lock_count, stop_lock_count : integer := 0;
|
|
variable pll_last_rising_edge, pll_last_falling_edge : time := 0 ps;
|
|
variable pll_rising_edge_count : integer := 0;
|
|
variable pll_cycle, pll_duty_cycle : time := 0 ps;
|
|
variable expected_next_clk_edge : time := 0 ps;
|
|
variable clk_per_tolerance : time := 0 ps;
|
|
|
|
variable last_synchronizing_rising_edge_for_clk0 : time := 0 ps;
|
|
variable last_synchronizing_rising_edge_for_clk1 : time := 0 ps;
|
|
variable last_synchronizing_rising_edge_for_clk2 : time := 0 ps;
|
|
variable last_synchronizing_rising_edge_for_extclk : time := 0 ps;
|
|
variable input_cycles_per_clk0 : integer := clock0_divide;
|
|
variable input_cycles_per_clk1 : integer := clock1_divide;
|
|
variable input_cycles_per_clk2 : integer := clock2_divide;
|
|
variable input_cycles_per_extclk : integer := clock_ext_divide;
|
|
variable input_cycle_count_to_sync0 : integer := 0;
|
|
variable input_cycle_count_to_sync1 : integer := 0;
|
|
variable input_cycle_count_to_sync2 : integer := 0;
|
|
variable input_cycle_count_to_sync_extclk : integer := 0;
|
|
variable init : boolean := true;
|
|
variable output_value : std_logic := '0';
|
|
variable vco_per : time := 0 ps;
|
|
variable high_time : time := 0 ps;
|
|
variable low_time : time := 0 ps;
|
|
variable sched_time : time := 0 ps;
|
|
variable tmp_per : integer := 0;
|
|
variable temp, tmp_rem, my_rem : integer := 0;
|
|
variable inc : integer := 1;
|
|
variable cycle_to_adjust : integer := 0;
|
|
variable clk0_synchronizing_period, clk1_synchronizing_period : time;
|
|
variable clk2_synchronizing_period, extclk_synchronizing_period : time;
|
|
variable clk0_cycles_per_sync_period : integer := clock0_boost;
|
|
variable clk1_cycles_per_sync_period : integer := clock1_boost;
|
|
variable clk2_cycles_per_sync_period : integer := clock2_boost;
|
|
variable extclk_cycles_per_sync_period : integer := clock_ext_boost;
|
|
variable schedule_clk0, schedule_clk1 : boolean := false;
|
|
variable schedule_clk2, schedule_extclk : boolean := false;
|
|
variable clk0_phase_delay : time := time_delay(clock0_time_delay);
|
|
variable clk1_phase_delay : time := time_delay(clock1_time_delay);
|
|
variable clk2_phase_delay : time := time_delay(clock2_time_delay);
|
|
variable extclk_phase_delay : time := time_delay(clock_ext_time_delay);
|
|
|
|
begin
|
|
if (init) then
|
|
if ((clock0_boost rem clock0_divide) = 0) then
|
|
clk0_cycles_per_sync_period := clock0_boost / clock0_divide;
|
|
input_cycles_per_clk0 := 1;
|
|
end if;
|
|
if ((clock1_boost rem clock1_divide) = 0) then
|
|
clk1_cycles_per_sync_period := clock1_boost / clock1_divide;
|
|
input_cycles_per_clk1 := 1;
|
|
end if;
|
|
if ((clock2_boost rem clock2_divide) = 0) then
|
|
clk2_cycles_per_sync_period := clock2_boost / clock2_divide;
|
|
input_cycles_per_clk2 := 1;
|
|
end if;
|
|
if ((clock_ext_boost rem clock_ext_divide) = 0) then
|
|
extclk_cycles_per_sync_period := clock_ext_boost / clock_ext_divide;
|
|
input_cycles_per_extclk := 1;
|
|
end if;
|
|
|
|
clk_per_tolerance := (0.1 * real(inclock_period)) * 1 ps;
|
|
|
|
init := false;
|
|
end if;
|
|
|
|
if (inclocken = '0') then
|
|
pll_lock_tmp := '0';
|
|
pll_rising_edge_count := 0;
|
|
elsif (inclock'event and inclock = '1') then
|
|
if (pll_lock_tmp = '1') then
|
|
check_lock <= not check_lock after (inclk_ps+clk_per_tolerance)/2.0;
|
|
end if;
|
|
if pll_rising_edge_count = 0 then -- at 1st rising edge
|
|
inclk_ps := (inclock_period / 1) * 1 ps;
|
|
pll_duty_cycle := inclk_ps/2;
|
|
elsif pll_rising_edge_count = 1 then -- at 2nd rising edge
|
|
pll_cycle := now - pll_last_rising_edge; -- calculate period
|
|
if ((NOW - pll_last_rising_edge) < (inclk_ps - clk_per_tolerance) or
|
|
(NOW - pll_last_rising_edge) > (inclk_ps + clk_per_tolerance)) then
|
|
ASSERT FALSE
|
|
REPORT "Inclock_Period Violation"
|
|
SEVERITY WARNING;
|
|
violation := true;
|
|
if (pll_lock = '1') then
|
|
stop_lock_count := stop_lock_count + 1;
|
|
if (stop_lock_count = invalid_lock_cycles) then
|
|
pll_lock_tmp := '0';
|
|
ASSERT FALSE
|
|
REPORT "altclklock out of lock."
|
|
SEVERITY WARNING;
|
|
end if;
|
|
else
|
|
start_lock_count := 1;
|
|
end if;
|
|
else
|
|
violation := false;
|
|
end if;
|
|
if ((now - pll_last_falling_edge) < (pll_duty_cycle - clk_per_tolerance/2) or
|
|
(now - pll_last_falling_edge) > (pll_duty_cycle + clk_per_tolerance/2)) then
|
|
ASSERT FALSE
|
|
REPORT "Duty Cycle Violation"
|
|
SEVERITY WARNING;
|
|
violation := true;
|
|
else
|
|
violation := false;
|
|
end if;
|
|
else
|
|
pll_cycle := now - pll_last_rising_edge; -- calculate period
|
|
if ((now - pll_last_rising_edge) < (inclk_ps - clk_per_tolerance) or
|
|
(now - pll_last_rising_edge) > (inclk_ps + clk_per_tolerance)) then
|
|
ASSERT FALSE
|
|
REPORT "Cycle Violation"
|
|
SEVERITY WARNING;
|
|
violation := true;
|
|
if (pll_lock = '1') then
|
|
stop_lock_count := stop_lock_count + 1;
|
|
if (stop_lock_count = invalid_lock_cycles) then
|
|
pll_lock_tmp := '0';
|
|
ASSERT FALSE
|
|
REPORT "altclklock out of lock."
|
|
SEVERITY WARNING;
|
|
end if;
|
|
else
|
|
start_lock_count := 1;
|
|
end if;
|
|
else
|
|
violation := false;
|
|
end if;
|
|
end if;
|
|
pll_last_rising_edge := now;
|
|
pll_rising_edge_count := pll_rising_edge_count +1;
|
|
if (not violation) then
|
|
if (pll_lock_tmp = '1') then
|
|
input_cycle_count_to_sync0 := input_cycle_count_to_sync0 + 1;
|
|
if (input_cycle_count_to_sync0 = input_cycles_per_clk0) then
|
|
clk0_synchronizing_period := now - last_synchronizing_rising_edge_for_clk0;
|
|
last_synchronizing_rising_edge_for_clk0 := now;
|
|
schedule_clk0 := true;
|
|
input_cycle_count_to_sync0 := 0;
|
|
end if;
|
|
input_cycle_count_to_sync1 := input_cycle_count_to_sync1 + 1;
|
|
if (input_cycle_count_to_sync1 = input_cycles_per_clk1) then
|
|
clk1_synchronizing_period := now - last_synchronizing_rising_edge_for_clk1;
|
|
last_synchronizing_rising_edge_for_clk1 := now;
|
|
schedule_clk1 := true;
|
|
input_cycle_count_to_sync1 := 0;
|
|
end if;
|
|
input_cycle_count_to_sync2 := input_cycle_count_to_sync2 + 1;
|
|
if (input_cycle_count_to_sync2 = input_cycles_per_clk2) then
|
|
clk2_synchronizing_period := now - last_synchronizing_rising_edge_for_clk2;
|
|
last_synchronizing_rising_edge_for_clk2 := now;
|
|
schedule_clk2 := true;
|
|
input_cycle_count_to_sync2 := 0;
|
|
end if;
|
|
input_cycle_count_to_sync_extclk := input_cycle_count_to_sync_extclk + 1;
|
|
if (input_cycle_count_to_sync_extclk = input_cycles_per_extclk) then
|
|
extclk_synchronizing_period := now - last_synchronizing_rising_edge_for_extclk;
|
|
last_synchronizing_rising_edge_for_extclk := now;
|
|
schedule_extclk := true;
|
|
input_cycle_count_to_sync_extclk := 0;
|
|
end if;
|
|
else
|
|
start_lock_count := start_lock_count + 1;
|
|
if (start_lock_count >= valid_lock_cycles) then
|
|
pll_lock_tmp := '1';
|
|
input_cycle_count_to_sync0 := 0;
|
|
input_cycle_count_to_sync1 := 0;
|
|
input_cycle_count_to_sync2 := 0;
|
|
input_cycle_count_to_sync_extclk := 0;
|
|
clk0_synchronizing_period := ((pll_cycle/1 ps) * input_cycles_per_clk0) * 1 ps;
|
|
clk1_synchronizing_period := ((pll_cycle/1 ps) * input_cycles_per_clk1) * 1 ps;
|
|
clk2_synchronizing_period := ((pll_cycle/1 ps) * input_cycles_per_clk2) * 1 ps;
|
|
extclk_synchronizing_period := ((pll_cycle/1 ps) * input_cycles_per_extclk) * 1 ps;
|
|
last_synchronizing_rising_edge_for_clk0 := now;
|
|
last_synchronizing_rising_edge_for_clk1 := now;
|
|
last_synchronizing_rising_edge_for_clk2 := now;
|
|
last_synchronizing_rising_edge_for_extclk := now;
|
|
schedule_clk0 := true;
|
|
schedule_clk1 := true;
|
|
schedule_clk2 := true;
|
|
schedule_extclk := true;
|
|
end if;
|
|
end if;
|
|
else
|
|
start_lock_count := 1;
|
|
end if;
|
|
|
|
elsif (inclock'event and inclock= '0') then
|
|
if (pll_lock_tmp = '1') then
|
|
check_lock <= not check_lock after (inclk_ps+clk_per_tolerance)/2.0;
|
|
if (now > 0 ns and ((now - pll_last_rising_edge) < (pll_duty_cycle - clk_per_tolerance/2) or
|
|
(now - pll_last_rising_edge) > (pll_duty_cycle + clk_per_tolerance/2))) then
|
|
ASSERT FALSE
|
|
REPORT "Duty Cycle Violation"
|
|
SEVERITY WARNING;
|
|
violation := true;
|
|
if (pll_lock = '1') then
|
|
stop_lock_count := stop_lock_count + 1;
|
|
if (stop_lock_count = invalid_lock_cycles) then
|
|
pll_lock_tmp := '0';
|
|
ASSERT FALSE
|
|
REPORT "altclklock out of lock."
|
|
SEVERITY WARNING;
|
|
end if;
|
|
end if;
|
|
else
|
|
violation := false;
|
|
end if;
|
|
else
|
|
start_lock_count := start_lock_count + 1;
|
|
end if;
|
|
pll_last_falling_edge := now;
|
|
else
|
|
if pll_lock_tmp = '1' then
|
|
if (inclock = '1') then
|
|
expected_next_clk_edge := pll_last_rising_edge + (inclk_ps+clk_per_tolerance)/2.0;
|
|
else
|
|
expected_next_clk_edge := pll_last_falling_edge + (inclk_ps+clk_per_tolerance)/2.0;
|
|
end if;
|
|
violation := false;
|
|
if (now < expected_next_clk_edge) then
|
|
check_lock <= not check_lock after (expected_next_clk_edge - now);
|
|
elsif (now = expected_next_clk_edge) then
|
|
check_lock <= not check_lock after (inclk_ps+clk_per_tolerance)/2.0;
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "Inclock_Period Violation"
|
|
SEVERITY WARNING;
|
|
violation := true;
|
|
if (pll_lock = '1') then
|
|
stop_lock_count := stop_lock_count + 1;
|
|
if (stop_lock_count = invalid_lock_cycles) then
|
|
pll_lock_tmp := '0';
|
|
ASSERT FALSE
|
|
REPORT "altclklock out of lock."
|
|
SEVERITY WARNING;
|
|
else
|
|
check_lock <= not check_lock after (inclk_ps/2.0);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
pll_lock <= pll_lock_tmp;
|
|
if (pll_lock'event and pll_lock = '0') then
|
|
start_lock_count := 1;
|
|
|
|
stop_lock_count := 0;
|
|
clk0_tmp <= 'X';
|
|
clk1_tmp <= 'X';
|
|
clk2_tmp <= 'X';
|
|
extclk_tmp <= 'X';
|
|
end if;
|
|
|
|
-- clock0 output
|
|
if (schedule_clk0 = true) then
|
|
-- initialize variables
|
|
sched_time := clk0_phase_delay;
|
|
cycle_to_adjust := 0;
|
|
inc := 1;
|
|
output_value := '1';
|
|
temp := clk0_synchronizing_period / 1 ps;
|
|
my_rem := temp rem clk0_cycles_per_sync_period;
|
|
|
|
-- schedule <clk0_cycles_per_sync_period> number of output clock
|
|
-- cycles in this loop in order to synchronize the output clock to the
|
|
-- input clock - to get rid of drifting for cases where the input clock
|
|
-- period is not always divisible
|
|
for i in 1 to clk0_cycles_per_sync_period loop
|
|
tmp_per := temp/clk0_cycles_per_sync_period;
|
|
if ((my_rem /= 0) and (inc <= my_rem)) then
|
|
tmp_rem := (clk0_cycles_per_sync_period * inc) rem my_rem;
|
|
cycle_to_adjust := (clk0_cycles_per_sync_period * inc) / my_rem;
|
|
if (tmp_rem /= 0) then
|
|
cycle_to_adjust := cycle_to_adjust + 1;
|
|
end if;
|
|
end if;
|
|
|
|
-- if this cycle is the one to adjust the output period in, then
|
|
-- increment the period by 1 unit
|
|
if (cycle_to_adjust = i) then
|
|
tmp_per := tmp_per + 1;
|
|
inc := inc + 1;
|
|
end if;
|
|
|
|
-- adjust the high and low cycle period
|
|
vco_per := tmp_per * 1 ps;
|
|
high_time := (tmp_per / 2) * 1 ps;
|
|
if ((tmp_per rem 2) /= 0) then
|
|
high_time := high_time + 1 ps;
|
|
end if;
|
|
|
|
low_time := vco_per - high_time;
|
|
|
|
-- schedule the high and low cycle of 1 output clock period
|
|
for j in 1 to 2 loop
|
|
clk0_tmp <= transport output_value after sched_time;
|
|
output_value := not output_value;
|
|
if (output_value = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (output_value = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
|
|
-- reset schedule_clk0
|
|
schedule_clk0 := false;
|
|
end if; -- schedule_clk0
|
|
|
|
if (schedule_clk1 = true) then
|
|
-- initialize variables
|
|
sched_time := clk1_phase_delay;
|
|
cycle_to_adjust := 0;
|
|
inc := 1;
|
|
output_value := '1';
|
|
temp := clk1_synchronizing_period / 1 ps;
|
|
my_rem := temp rem clk1_cycles_per_sync_period;
|
|
|
|
-- schedule <clk1_cycles_per_sync_period> number of output clock
|
|
-- cycles in this loop in order to synchronize the output clock to the
|
|
-- input clock - to get rid of drifting for cases where the input clock
|
|
-- period is not always divisible
|
|
for i in 1 to clk1_cycles_per_sync_period loop
|
|
tmp_per := temp/clk1_cycles_per_sync_period;
|
|
if ((my_rem /= 0) and (inc <= my_rem)) then
|
|
tmp_rem := (clk1_cycles_per_sync_period * inc) rem my_rem;
|
|
cycle_to_adjust := (clk1_cycles_per_sync_period * inc) / my_rem;
|
|
if (tmp_rem /= 0) then
|
|
cycle_to_adjust := cycle_to_adjust + 1;
|
|
end if;
|
|
end if;
|
|
|
|
-- if this cycle is the one to adjust the output period in, then
|
|
-- increment the period by 1 unit
|
|
if (cycle_to_adjust = i) then
|
|
tmp_per := tmp_per + 1;
|
|
inc := inc + 1;
|
|
end if;
|
|
|
|
-- adjust the high and low cycle period
|
|
vco_per := tmp_per * 1 ps;
|
|
high_time := (tmp_per/2) * 1 ps;
|
|
if ((tmp_per rem 2) /= 0) then
|
|
high_time := high_time + 1 ps;
|
|
end if;
|
|
|
|
low_time := vco_per - high_time;
|
|
|
|
-- schedule the high and low cycle of 1 output clock period
|
|
for j in 1 to 2 loop
|
|
clk1_tmp <= transport output_value after sched_time;
|
|
output_value := not output_value;
|
|
if (output_value = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (output_value = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
|
|
-- reset schedule_clk1
|
|
schedule_clk1 := false;
|
|
end if; -- schedule_clk1
|
|
|
|
if (FEATURE_FAMILY_STRATIX(intended_device_family)) then
|
|
-- clock2 output
|
|
if (schedule_clk2 = true) then
|
|
-- initialize variables
|
|
sched_time := clk2_phase_delay;
|
|
cycle_to_adjust := 0;
|
|
inc := 1;
|
|
output_value := '1';
|
|
temp := clk2_synchronizing_period/1 ps;
|
|
my_rem := temp rem clk2_cycles_per_sync_period;
|
|
|
|
-- schedule <clk2_cycles_per_sync_period> number of output clock
|
|
-- cycles in this loop in order to synchronize the output clock to the
|
|
-- input clock - to get rid of drifting for cases where the input clock
|
|
-- period is not always divisible
|
|
for i in 1 to clk2_cycles_per_sync_period loop
|
|
tmp_per := temp/clk2_cycles_per_sync_period;
|
|
if ((my_rem /= 0) and (inc <= my_rem)) then
|
|
tmp_rem := (clk2_cycles_per_sync_period * inc) rem my_rem;
|
|
cycle_to_adjust := (clk2_cycles_per_sync_period * inc) / my_rem;
|
|
if (tmp_rem /= 0) then
|
|
cycle_to_adjust := cycle_to_adjust + 1;
|
|
end if;
|
|
end if;
|
|
|
|
-- if this cycle is the one to adjust the output period in, then
|
|
-- increment the period by 1 unit
|
|
if (cycle_to_adjust = i) then
|
|
tmp_per := tmp_per + 1;
|
|
inc := inc + 1;
|
|
end if;
|
|
|
|
-- adjust the high and low cycle period
|
|
vco_per := tmp_per * 1 ps;
|
|
high_time := (tmp_per/2) * 1 ps;
|
|
if ((tmp_per rem 2) /= 0) then
|
|
high_time := high_time + 1 ps;
|
|
end if;
|
|
|
|
low_time := vco_per - high_time;
|
|
|
|
-- schedule the high and low cycle of 1 output clock period
|
|
for j in 1 to 2 loop
|
|
clk2_tmp <= transport output_value after sched_time;
|
|
output_value := not output_value;
|
|
if (output_value = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (output_value = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
|
|
-- reset schedule_clk2
|
|
schedule_clk2 := false;
|
|
end if; -- schedule_clk2
|
|
|
|
-- clock_ext output
|
|
if (schedule_extclk = true) then
|
|
-- initialize variables
|
|
sched_time := extclk_phase_delay;
|
|
cycle_to_adjust := 0;
|
|
inc := 1;
|
|
output_value := '1';
|
|
temp := extclk_synchronizing_period/1 ps;
|
|
my_rem := temp rem extclk_cycles_per_sync_period;
|
|
|
|
-- schedule <extclk_cycles_per_sync_period> number of output clock
|
|
-- cycles in this loop in order to synchronize the output clock to the
|
|
-- input clock - to get rid of drifting for cases where the input clock
|
|
-- period is not always divisible
|
|
for i in 1 to extclk_cycles_per_sync_period loop
|
|
tmp_per := temp/extclk_cycles_per_sync_period;
|
|
if ((my_rem /= 0) and (inc <= my_rem)) then
|
|
tmp_rem := (extclk_cycles_per_sync_period * inc) rem my_rem;
|
|
cycle_to_adjust := (extclk_cycles_per_sync_period * inc) / my_rem;
|
|
if (tmp_rem /= 0) then
|
|
cycle_to_adjust := cycle_to_adjust + 1;
|
|
end if;
|
|
end if;
|
|
|
|
-- if this cycle is the one to adjust the output period in, then
|
|
-- increment the period by 1 unit
|
|
if (cycle_to_adjust = i) then
|
|
tmp_per := tmp_per + 1;
|
|
inc := inc + 1;
|
|
end if;
|
|
|
|
-- adjust the high and low cycle period
|
|
vco_per := tmp_per * 1 ps;
|
|
high_time := (tmp_per/2) * 1 ps;
|
|
if ((tmp_per rem 2) /= 0) then
|
|
high_time := high_time + 1 ps;
|
|
end if;
|
|
|
|
low_time := vco_per - high_time;
|
|
|
|
-- schedule the high and low cycle of 1 output clock period
|
|
for j in 1 to 2 loop
|
|
extclk_tmp <= transport output_value after sched_time;
|
|
output_value := not output_value;
|
|
if (output_value = '0') then
|
|
sched_time := sched_time + high_time;
|
|
elsif (output_value = '1') then
|
|
sched_time := sched_time + low_time;
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
|
|
-- reset schedule_extclk
|
|
schedule_extclk := false;
|
|
end if; -- schedule_extclk
|
|
end if;
|
|
|
|
end process LOCK;
|
|
|
|
clock0 <= clk0_tmp;
|
|
clock1 <= clk1_tmp;
|
|
clock2 <= clk2_tmp;
|
|
clock_ext <= extclk_tmp;
|
|
locked <= pll_lock;
|
|
|
|
end behavior;
|
|
-- END ARCHITECTURE BEHAVIOR
|
|
-- START ENTITY NAME -----------------------------------------------------------
|
|
--
|
|
-- Entity Name : ALTDDIO_IN
|
|
--
|
|
-- Description : Double Data Rate (DDR) input behavioural model. Receives
|
|
-- data on both edges of the reference clock.
|
|
--
|
|
-- Limitations : Not available for MAX device families.
|
|
--
|
|
-- Expected results : Data sampled from the datain port at the rising edge of
|
|
-- the reference clock (dataout_h) and at the falling edge of
|
|
-- the reference clock (dataout_l).
|
|
--
|
|
-- END ENTITY NAME -------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altddio_in is
|
|
generic (
|
|
width : positive; -- required parameter
|
|
invert_input_clocks : string := "OFF";
|
|
intended_device_family : string := "Stratix";
|
|
power_up_high : string := "OFF";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altddio_in"
|
|
);
|
|
port (
|
|
datain : in std_logic_vector(width-1 downto 0); -- required port, DDR
|
|
-- input data
|
|
inclock : in std_logic := '0'; -- input reference clock
|
|
inclocken : in std_logic := '1'; -- input clock enable signal
|
|
aset : in std_logic := '0'; -- asynchronous set
|
|
aclr : in std_logic := '0'; -- asynchronous clear
|
|
sset : in std_logic := '0'; -- synchronous set
|
|
sclr : in std_logic := '0'; -- synchronous clear
|
|
dataout_h : out std_logic_vector(width-1 downto 0); --data sampled at
|
|
--rising edge of inclock
|
|
dataout_l : out std_logic_vector(width-1 downto 0) --data sampled at
|
|
--falling edge of inclock
|
|
);
|
|
end altddio_in;
|
|
-- END ENTITY DECLARATION
|
|
|
|
-- BEGINNING OF ARCHITECTURE BEHAVE
|
|
architecture behave of altddio_in is
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant IS_STRATIXIII : boolean := FEATURE_FAMILY_STRATIXIII(intended_device_family);
|
|
constant IS_STRATIX : boolean := FEATURE_FAMILY_STRATIX(intended_device_family);
|
|
constant IS_MAXII : boolean := FEATURE_FAMILY_MAXII(intended_device_family);
|
|
|
|
begin
|
|
|
|
-- checking for invalid parameters
|
|
MSG: process
|
|
begin
|
|
if (width <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The width parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (IS_VALID_FAMILY(intended_device_family) = false) then
|
|
ASSERT FALSE
|
|
REPORT intended_device_family & " is not a valid device family!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (not ((IS_STRATIX and
|
|
(not IS_MAXII)))) then
|
|
ASSERT FALSE
|
|
REPORT "Megafunction altddio_in is not supported in " & intended_device_family &"!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
wait;
|
|
end process MSG;
|
|
|
|
|
|
|
|
|
|
process (inclock, aset, aclr)
|
|
-- VARIABLE DECLARATION
|
|
variable dataout_h_tmp : std_logic_vector(width-1 downto 0)
|
|
:= (OTHERS=>'0');
|
|
variable dataout_l_tmp : std_logic_vector(width-1 downto 0)
|
|
:= (OTHERS=>'0');
|
|
variable datain_latched : std_logic_vector(width-1 downto 0)
|
|
:= (OTHERS=>'0');
|
|
variable need_init : boolean := true;
|
|
|
|
begin
|
|
-- power up registers according the power_up_high parameter setting
|
|
if ((NOW = 0 ps) or (need_init = true)) then
|
|
if (power_up_high = "OFF") then
|
|
dataout_h_tmp := (others => '0');
|
|
dataout_l_tmp := (others => '0');
|
|
datain_latched := (others => '0');
|
|
else
|
|
dataout_h_tmp := (others => '1');
|
|
dataout_l_tmp := (others => '1');
|
|
datain_latched := (others => '1');
|
|
end if;
|
|
need_init := false;
|
|
end if;
|
|
|
|
-- asynchronous clear is asserted
|
|
if (aclr = '1') then
|
|
dataout_h_tmp := (others => '0');
|
|
dataout_l_tmp := (others => '0');
|
|
datain_latched := (others => '0');
|
|
-- else asynchronous set is asserted
|
|
elsif (aset = '1') then
|
|
dataout_h_tmp := (others => '1');
|
|
dataout_l_tmp := (others => '1');
|
|
datain_latched := (others => '1');
|
|
-- not being cleared or preset
|
|
-- rising edge of inclock
|
|
elsif (inclock'event and (inclock = '1')) then
|
|
if (inclocken = '1') then
|
|
if (invert_input_clocks = "ON") then
|
|
if (sclr = '1') then
|
|
datain_latched := (others => '0');
|
|
elsif (sset = '1') then
|
|
datain_latched := (others => '1');
|
|
else
|
|
datain_latched := datain;
|
|
end if;
|
|
else
|
|
if (IS_STRATIXIII) then
|
|
if (sclr = '1') then
|
|
dataout_h_tmp := (others => '0');
|
|
dataout_l_tmp := (others => '0');
|
|
elsif (sset = '1') then
|
|
dataout_h_tmp := (others => '1');
|
|
dataout_l_tmp := (others => '1');
|
|
else
|
|
dataout_h_tmp := datain;
|
|
dataout_l_tmp := datain_latched;
|
|
end if;
|
|
else
|
|
if (sclr = '1') then
|
|
dataout_h_tmp := (others => '0');
|
|
elsif (sset = '1') then
|
|
dataout_h_tmp := (others => '1');
|
|
else
|
|
dataout_h_tmp := datain;
|
|
end if;
|
|
dataout_l_tmp := datain_latched;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- falling edge of inclock
|
|
elsif (inclock'event and (inclock = '0')) then
|
|
if ((IS_STRATIX and
|
|
(not IS_MAXII))) then
|
|
|
|
if (inclocken = '1') then
|
|
if (invert_input_clocks = "ON") then
|
|
if (IS_STRATIXIII) then
|
|
if (sclr = '1') then
|
|
dataout_h_tmp := (others => '0');
|
|
dataout_l_tmp := (others => '0');
|
|
elsif (sset = '1') then
|
|
dataout_h_tmp := (others => '1');
|
|
dataout_l_tmp := (others => '1');
|
|
else
|
|
dataout_h_tmp := datain;
|
|
dataout_l_tmp := datain_latched;
|
|
end if;
|
|
else
|
|
if (sclr = '1') then
|
|
dataout_h_tmp := (others => '0');
|
|
elsif (sset = '1') then
|
|
dataout_h_tmp := (others => '1');
|
|
else
|
|
dataout_h_tmp := datain;
|
|
end if;
|
|
dataout_l_tmp := datain_latched;
|
|
end if;
|
|
else
|
|
if (sclr = '1') then
|
|
datain_latched := (others => '0');
|
|
elsif (sset = '1') then
|
|
datain_latched := (others => '1');
|
|
else
|
|
datain_latched := datain;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else -- for future families
|
|
if (invert_input_clocks = "ON") then
|
|
dataout_h_tmp := datain;
|
|
dataout_l_tmp := datain_latched;
|
|
else
|
|
datain_latched := datain;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- assign variables to output ports
|
|
dataout_l <= dataout_l_tmp;
|
|
dataout_h <= dataout_h_tmp;
|
|
end process;
|
|
|
|
end behave;
|
|
-- END ARCHITECTURE BEHAVE
|
|
|
|
-- START ENTITY NAME -----------------------------------------------------------
|
|
--
|
|
-- Entity Name : ALTDDIO_OUT
|
|
--
|
|
-- Description : Double Data Rate (DDR) output behavioural model.
|
|
-- Transmits data on both edges of the reference clock.
|
|
--
|
|
-- Limitations : Not available for MAX device families.
|
|
--
|
|
-- Expected results : Double data rate output on dataout.
|
|
--
|
|
--END ENTITY NAME -------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altddio_out is
|
|
generic (
|
|
width : positive; -- required parameter
|
|
power_up_high : string := "OFF";
|
|
oe_reg : string := "UNUSED";
|
|
extend_oe_disable : string := "UNUSED";
|
|
invert_output : string := "OFF";
|
|
intended_device_family : string := "Stratix";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altddio_out"
|
|
);
|
|
port (
|
|
datain_h : in std_logic_vector(width-1 downto 0); --required port, data
|
|
--input for the rising
|
|
--edge of outclock
|
|
datain_l : in std_logic_vector(width-1 downto 0); --required port, data
|
|
--input for the falling
|
|
--edge of outclock
|
|
outclock : in std_logic; -- required port, input reference clock to output
|
|
-- data by
|
|
outclocken : in std_logic := '1'; -- clock enable signal for outclock
|
|
aset : in std_logic := '0'; -- asynchronous set
|
|
aclr : in std_logic := '0'; -- asynchronous clear
|
|
sset : in std_logic := '0'; -- synchronous set
|
|
sclr : in std_logic := '0'; -- synchronous clear
|
|
oe : in std_logic := '1'; -- output enable for dataout
|
|
dataout : out std_logic_vector(width-1 downto 0); -- DDR data output
|
|
oe_out : out std_logic_vector(width-1 downto 0) -- DDR data output
|
|
);
|
|
end altddio_out;
|
|
-- END ENTITY DECLARATION
|
|
|
|
-- BEGINNING OF ARCHITECTURE BEHAVE
|
|
architecture behave of altddio_out is
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant INVERT_DATAOUT : boolean := FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO(intended_device_family) and
|
|
(invert_output = "ON");
|
|
constant IS_STRATIXIII : boolean := FEATURE_FAMILY_STRATIXIII(intended_device_family);
|
|
constant IS_STRATIX : boolean := FEATURE_FAMILY_STRATIX(intended_device_family);
|
|
constant IS_MAXII : boolean := FEATURE_FAMILY_MAXII(intended_device_family);
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal outclock_dly : std_logic;
|
|
signal dataout_h : std_logic_vector(width-1 downto 0) := (OTHERS=>'0');
|
|
signal dataout_l : std_logic_vector(width-1 downto 0) := (OTHERS=>'0');
|
|
signal oe_rgd : std_logic := '0';
|
|
signal oe_reg_ext : std_logic := '0';
|
|
signal stratix_oe : std_logic;
|
|
signal output_enable : std_logic;
|
|
|
|
begin
|
|
|
|
-- checking for invalid parameters
|
|
MSG: process
|
|
begin
|
|
if (width <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The width parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (IS_VALID_FAMILY(intended_device_family) = false) then
|
|
ASSERT FALSE
|
|
REPORT intended_device_family & " is not a valid device family!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (not ((IS_STRATIX and
|
|
(not IS_MAXII)))) then
|
|
ASSERT FALSE
|
|
REPORT "Megafunction altddio_out is not supported in " & intended_device_family &"!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
wait;
|
|
end process MSG;
|
|
|
|
outclock_dly <= outclock;
|
|
|
|
-- output enable signals
|
|
output_enable <= stratix_oe when ((IS_STRATIX and
|
|
(not IS_MAXII)))
|
|
else oe;
|
|
|
|
stratix_oe <= (oe_reg_ext and oe_rgd)
|
|
when (extend_oe_disable = "ON")
|
|
else oe_rgd
|
|
when ((oe_reg = "REGISTERED") and (extend_oe_disable /= "ON"))
|
|
else oe;
|
|
|
|
oe_out <= (others => output_enable);
|
|
|
|
REGS: process (outclock, aset, aclr)
|
|
-- VARIABLE DECLARATION
|
|
variable need_init : boolean := true;
|
|
|
|
begin
|
|
-- power up the registers according to the power_up_high parameter setting
|
|
if ((NOW = 0 ps) or (need_init = true)) then
|
|
if (power_up_high = "OFF") then
|
|
dataout_h <= (others => '0');
|
|
dataout_l <= (others => '0');
|
|
oe_rgd <= '0';
|
|
oe_reg_ext <= '0';
|
|
else
|
|
dataout_h <= (others => '1');
|
|
dataout_l <= (others => '1');
|
|
oe_rgd <= '1';
|
|
oe_reg_ext <= '1';
|
|
end if;
|
|
need_init := false;
|
|
end if;
|
|
|
|
-- asynchronous clear is asserted
|
|
if (aclr = '1') then
|
|
dataout_h <= (others => '0');
|
|
dataout_l <= (others => '0');
|
|
oe_rgd <= '0';
|
|
oe_reg_ext <= '0';
|
|
-- else if asynchronous set is asserted
|
|
elsif (aset = '1') then
|
|
dataout_h <= (others => '1');
|
|
dataout_l <= (others => '1');
|
|
oe_rgd <= '1';
|
|
oe_reg_ext <= '1';
|
|
-- else outclock is triggered
|
|
elsif ((outclock = '1') and outclock'event) then
|
|
-- rising edge of outclock
|
|
if (outclocken = '1') then
|
|
-- synchronous clear is asserted
|
|
if (sclr = '1') then
|
|
dataout_h <= (others => '0');
|
|
dataout_l <= (others => '0');
|
|
oe_rgd <= '0';
|
|
oe_reg_ext <= '0';
|
|
-- else if synchronous set is asserted
|
|
elsif (sset = '1') then
|
|
dataout_h <= (others => '1');
|
|
dataout_l <= (others => '1');
|
|
oe_rgd <= '1';
|
|
oe_reg_ext <= '1';
|
|
else
|
|
if (INVERT_DATAOUT = true) then
|
|
dataout_h <= not datain_h;
|
|
dataout_l <= not datain_l;
|
|
else
|
|
dataout_h <= datain_h;
|
|
dataout_l <= datain_l;
|
|
end if;
|
|
oe_rgd <= oe;
|
|
end if;
|
|
end if;
|
|
elsif ((outclock = '0') and outclock'event) then
|
|
-- falling edge of outclock
|
|
if (outclocken = '1') then
|
|
oe_reg_ext <= oe_rgd;
|
|
end if;
|
|
end if;
|
|
end process REGS;
|
|
|
|
DATA_OUTPUT: process(outclock_dly, dataout_h, dataout_l, output_enable)
|
|
begin
|
|
if (output_enable = '1') then
|
|
if (outclock_dly = '1') then
|
|
dataout <= dataout_h;
|
|
else
|
|
dataout <= dataout_l;
|
|
end if;
|
|
else -- output is not enabled
|
|
dataout <= (others => 'Z');
|
|
end if;
|
|
end process DATA_OUTPUT;
|
|
|
|
end behave;
|
|
-- END ARCHITECTURE BEHAVE
|
|
|
|
-- START ENTITY NAME -----------------------------------------------------------
|
|
--
|
|
-- Entity Name : ALTDDIO_BIDIR
|
|
--
|
|
-- Description : Double Data Rate (DDR) bi-directional behavioural model.
|
|
-- Transmits and receives data on both edges of the reference
|
|
-- clock.
|
|
--
|
|
-- Limitations : Not available for MAX device families.
|
|
--
|
|
-- Expected results : Data output sampled from padio port on rising edge of
|
|
-- inclock signal (dataout_h) and falling edge of inclock
|
|
-- signal (dataout_l). Combinatorial output fed by padio
|
|
-- directly (combout).
|
|
--
|
|
--END ENTITY NAME --------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.altddio_in;
|
|
use work.altddio_out;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altddio_bidir is
|
|
generic(
|
|
width : positive; -- required parameter
|
|
power_up_high : string := "OFF";
|
|
oe_reg : string := "UNUSED";
|
|
extend_oe_disable : string := "UNUSED";
|
|
implement_input_in_lcell : string := "UNUSED";
|
|
invert_output : string := "OFF";
|
|
intended_device_family : string := "Stratix";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altddio_bidir"
|
|
);
|
|
port (
|
|
datain_h : in std_logic_vector(width-1 downto 0); --input data to be
|
|
--output of padio port
|
|
--at the rising edge of
|
|
--outclock
|
|
datain_l : in std_logic_vector(width-1 downto 0); --input data to be
|
|
--output of padio port
|
|
--at the falling edge of
|
|
--outclock
|
|
inclock : in std_logic := '0'; -- input reference clock to sample DDR input.
|
|
inclocken : in std_logic := '1'; -- inclock enable
|
|
outclock : in std_logic; -- input reference clock to register data output
|
|
outclocken : in std_logic := '1'; -- outclock enable
|
|
aset : in std_logic := '0'; -- asynchronour set
|
|
aclr : in std_logic := '0'; -- asynchronous clear
|
|
sset : in std_logic := '0'; -- synchronour set
|
|
sclr : in std_logic := '0'; -- synchronous clear
|
|
oe : in std_logic := '1'; -- output enable for padio port
|
|
|
|
dataout_h : out std_logic_vector(width-1 downto 0);--data sampled from the
|
|
--padio port at the
|
|
--rising edge of
|
|
--inclock
|
|
dataout_l : out std_logic_vector(width-1 downto 0);--data sampled from the
|
|
--padio port at the
|
|
--falling edge of
|
|
--inclock
|
|
combout : out std_logic_vector(width-1 downto 0);--combinatorial output
|
|
--directly fed by padio
|
|
|
|
oe_out : out std_logic_vector(width-1 downto 0);--DDR OE output
|
|
|
|
dqsundelayedout : out std_logic_vector(width-1 downto 0); -- undelayed DQS
|
|
-- signal to the
|
|
-- PLD core
|
|
|
|
padio : inout std_logic_vector(width-1 downto 0) --bidirectional DDR
|
|
--port
|
|
);
|
|
end altddio_bidir;
|
|
-- END ENTITY DECLARATION
|
|
|
|
-- BEGINNING ARCHITECTURE STRUCT
|
|
architecture struct of altddio_bidir is
|
|
-- COMPONENT DECLARATION
|
|
component altddio_in
|
|
generic (
|
|
width : positive := 1;
|
|
intended_device_family : string := "Stratix";
|
|
power_up_high : string := "OFF"
|
|
);
|
|
port (
|
|
datain : in std_logic_vector(width-1 downto 0);
|
|
inclock : in std_logic;
|
|
inclocken : in std_logic := '1';
|
|
aset : in std_logic := '0';
|
|
aclr : in std_logic := '0';
|
|
sset : in std_logic := '0';
|
|
sclr : in std_logic := '0';
|
|
dataout_h : out std_logic_vector(width-1 downto 0);
|
|
dataout_l : out std_logic_vector(width-1 downto 0)
|
|
);
|
|
end component;
|
|
|
|
component altddio_out
|
|
generic (
|
|
width : positive := 1;
|
|
power_up_high : string := "OFF";
|
|
intended_device_family : string := "Stratix";
|
|
oe_reg : string := "UNUSED";
|
|
extend_oe_disable : string := "UNUSED";
|
|
invert_output : string := "OFF"
|
|
);
|
|
port (
|
|
datain_h : in std_logic_vector(width-1 downto 0);
|
|
datain_l : in std_logic_vector(width-1 downto 0);
|
|
outclock : in std_logic;
|
|
outclocken : in std_logic := '1';
|
|
aset : in std_logic := '0';
|
|
aclr : in std_logic := '0';
|
|
sset : in std_logic := '0';
|
|
sclr : in std_logic := '0';
|
|
oe : in std_logic := '1';
|
|
dataout : out std_logic_vector(width-1 downto 0);
|
|
oe_out : out std_logic_vector(width-1 downto 0)
|
|
);
|
|
end component;
|
|
|
|
begin
|
|
|
|
-- checking for invalid parameters
|
|
MSG: process
|
|
begin
|
|
if (width <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The width parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
wait;
|
|
end process MSG;
|
|
|
|
|
|
|
|
-- COMPONENT INSTANTIATION
|
|
U1: altddio_in
|
|
generic map (
|
|
width => width,
|
|
intended_device_family => intended_device_family,
|
|
power_up_high => power_up_high
|
|
)
|
|
port map (
|
|
datain => padio,
|
|
inclock => inclock,
|
|
inclocken => inclocken,
|
|
aset => aset,
|
|
aclr => aclr,
|
|
sset => sset,
|
|
sclr => sclr,
|
|
dataout_h => dataout_h,
|
|
dataout_l => dataout_l
|
|
);
|
|
|
|
U2: altddio_out
|
|
generic map (
|
|
width => width,
|
|
power_up_high => power_up_high,
|
|
intended_device_family => intended_device_family,
|
|
oe_reg => oe_reg,
|
|
extend_oe_disable => extend_oe_disable,
|
|
invert_output => invert_output
|
|
)
|
|
port map (
|
|
datain_h => datain_h,
|
|
datain_l => datain_l,
|
|
outclock => outclock,
|
|
outclocken => outclocken,
|
|
aset => aset,
|
|
aclr => aclr,
|
|
sset => sset,
|
|
sclr => sclr,
|
|
oe => oe,
|
|
dataout => padio,
|
|
oe_out => oe_out
|
|
);
|
|
|
|
-- assign padio to feed combout port
|
|
combout <= padio;
|
|
dqsundelayedout <= padio;
|
|
end struct;
|
|
-- END ARCHITECTURE STRUCT
|
|
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : stratixii_lvds_rx
|
|
--
|
|
-- Description : Stratix II lvds receiver. Support both the dpa and non-dpa
|
|
-- mode.
|
|
--
|
|
-- Limitation : Only available to Stratix II.
|
|
--
|
|
-- Results Expected: Deserialized output data, dpa lock signal and status bit
|
|
-- indicating whether maximum bitslip has been reached.
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- LIBRARY USED----------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity stratixii_lvds_rx is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
number_of_channels : natural; -- Required parameter
|
|
deserialization_factor : natural; -- Required parameter
|
|
enable_dpa_mode : string := "OFF";
|
|
data_align_rollover : natural := 10;
|
|
lose_lock_on_one_change : string := "OFF";
|
|
reset_fifo_at_first_lock : string := "ON";
|
|
x_on_bitslip : string := "ON" );
|
|
|
|
-- PORT DECLARATION
|
|
port(
|
|
--INPUT PORT DECLARATION
|
|
rx_in : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_fastclk : in std_logic; --Required port
|
|
rx_enable : in std_logic := '1';
|
|
rx_locked : in std_logic;
|
|
rx_dpaclock : in std_logic := '0';
|
|
rx_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_hold : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_enable : in std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
|
|
rx_fifo_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_channel_data_align : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_cda_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
rx_out : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
|
|
rx_dpa_locked : out std_logic_vector(number_of_channels-1 downto 0);
|
|
rx_cda_max : out std_logic_vector(number_of_channels-1 downto 0) := (others => '0') );
|
|
|
|
end stratixii_lvds_rx;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of stratixii_lvds_rx is
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant REGISTER_WIDTH : natural := deserialization_factor * number_of_channels;
|
|
constant MUX_WIDTH : natural := 12;
|
|
|
|
-- TYPE DECLARATION
|
|
type CHANNEL_CNT is array (number_of_channels-1 downto 0) of integer;
|
|
type CHANNEL_BOOL is array (number_of_channels-1 downto 0) of boolean;
|
|
type DPA_FIFO_RAM is array (number_of_channels -1 downto 0) of std_logic_vector(5 downto 0);
|
|
type BITSLIP_REG_CHAIN is array (number_of_channels-1 downto 0) of std_logic_vector(MUX_WIDTH-1 downto 0);
|
|
|
|
|
|
-- SIGNAL DECLARATION
|
|
|
|
-- constant signals
|
|
signal fifo_write_clk : std_logic := '0';
|
|
signal fifo_read_clk : std_logic := '0';
|
|
|
|
signal temp_zero : std_logic := '0';
|
|
|
|
signal enable0_reg : std_logic := '0';
|
|
signal enable_negedge_count : boolean := false;
|
|
|
|
signal rx_shift_reg : std_logic_vector(REGISTER_WIDTH-1 downto 0) := (others => '0');
|
|
signal rx_parallel_load_reg : std_logic_vector(REGISTER_WIDTH-1 downto 0) := (others => '0');
|
|
|
|
signal rx_in_reg : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal fifo_out_sync_reg : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal bitslip_mux_out : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal dpa_in : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal retime_data : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal dpll_lock : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal dpll_first_lock : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal rx_channel_data_align_pre : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal write_side_sync_reset : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal read_side_sync_reset : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
|
|
signal ram_array : DPA_FIFO_RAM := (others => (others => '0'));
|
|
|
|
signal dpa_fifo_in : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal dpa_fifo_out : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal rx_in_reg_clk : std_logic := '0';
|
|
signal rx_bload : std_logic := '0';
|
|
|
|
begin
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
rx_out <= rx_parallel_load_reg;
|
|
dpa_fifo_in <= retime_data;
|
|
dpa_fifo_out <= fifo_out_sync_reg;
|
|
fifo_write_clk <= rx_fastclk;
|
|
fifo_read_clk <= rx_fastclk;
|
|
rx_in_reg_clk <= rx_fastclk;
|
|
rx_dpa_locked <= dpll_lock;
|
|
rx_bload <= enable0_reg;
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
-- the deserializer
|
|
STRATIXII_DESER : process(rx_fastclk)
|
|
begin
|
|
if (rx_fastclk'event and (rx_fastclk = '1')) then
|
|
if (rx_bload = '1') then
|
|
rx_parallel_load_reg <= rx_shift_reg;
|
|
end if;
|
|
|
|
for i in 0 to number_of_channels -1 loop
|
|
for x in deserialization_factor-1 downto 1 loop
|
|
rx_shift_reg(x + (i * deserialization_factor)) <= rx_shift_reg(x-1 + (i * deserialization_factor));
|
|
end loop;
|
|
rx_shift_reg(i * deserialization_factor) <= bitslip_mux_out(i);
|
|
end loop;
|
|
|
|
-- Registering load enable signal
|
|
enable0_reg <= rx_enable;
|
|
end if;
|
|
end process STRATIXII_DESER;
|
|
|
|
-- input synchronization register
|
|
IN_SYNC_REGISTER : process (rx_in_reg_clk)
|
|
begin
|
|
if (rx_in_reg_clk = '1' and rx_in_reg_clk'event) then
|
|
rx_in_reg <= rx_in;
|
|
end if;
|
|
end process IN_SYNC_REGISTER;
|
|
|
|
-- STRATIXII bitslip logic
|
|
STRATIXII_BITSLIP : process (rx_fastclk, rx_cda_reset)
|
|
variable start_corrupt_bits : CHANNEL_BOOL := (others => false);
|
|
variable num_corrupt_bits : CHANNEL_CNT := (others => 0);
|
|
variable bitslip_count : CHANNEL_CNT := (others => 0);
|
|
variable shift_reg_chain : BITSLIP_REG_CHAIN := (others => (others => '0'));
|
|
begin
|
|
for i in 0 to number_of_channels-1 loop
|
|
if (rx_cda_reset(i) = '1') then
|
|
bitslip_count(i) := 0;
|
|
rx_cda_max(i) <= '0';
|
|
end if;
|
|
if (rx_fastclk'event and (rx_fastclk = '1')) then
|
|
if ((((rx_channel_data_align(i) = '1') and
|
|
(rx_channel_data_align_pre(i) = '0')) or
|
|
((start_corrupt_bits(i) = true) and
|
|
(num_corrupt_bits(i) < 4) and
|
|
(rx_channel_data_align(i) = '1'))) and
|
|
(x_on_bitslip = "ON")) then
|
|
bitslip_mux_out(i) <= 'X';
|
|
else
|
|
bitslip_mux_out(i) <= shift_reg_chain(i)(bitslip_count(i));
|
|
end if;
|
|
|
|
for j in data_align_rollover -1 downto 0 loop
|
|
shift_reg_chain(i)(j + 1) := shift_reg_chain(i)(j);
|
|
end loop;
|
|
|
|
if ((enable_dpa_mode = "ON") and (rx_dpll_enable(i) = '1')) then
|
|
shift_reg_chain(i)(0) := dpa_fifo_out(i);
|
|
else
|
|
shift_reg_chain(i)(0) := rx_in_reg(i);
|
|
end if;
|
|
|
|
if ((rx_channel_data_align(i) = '1') and
|
|
(rx_channel_data_align_pre(i) = '0'))then
|
|
bitslip_count(i) := (bitslip_count(i) + 1) rem (data_align_rollover + 1);
|
|
if (bitslip_count(i) = data_align_rollover) then
|
|
rx_cda_max(i) <= '1';
|
|
else
|
|
rx_cda_max(i) <= '0';
|
|
end if;
|
|
|
|
start_corrupt_bits(i) := true;
|
|
num_corrupt_bits(i) := 1;
|
|
elsif ((rx_channel_data_align(i) = '0') and
|
|
(rx_channel_data_align_pre(i) = '1'))then
|
|
start_corrupt_bits(i) := false;
|
|
num_corrupt_bits(i) := 0;
|
|
end if;
|
|
|
|
if (start_corrupt_bits(i) = true) then
|
|
if (num_corrupt_bits(i) = 3) then
|
|
start_corrupt_bits(i) := false;
|
|
else
|
|
num_corrupt_bits(i) := num_corrupt_bits(i) + 1;
|
|
end if;
|
|
end if;
|
|
rx_channel_data_align_pre(i) <= rx_channel_data_align(i);
|
|
|
|
end if;
|
|
end loop;
|
|
end process STRATIXII_BITSLIP;
|
|
|
|
-- STRATIXII Phase Compensation FIFO
|
|
STRATIXII_DPA_FIFO : process (fifo_write_clk, fifo_read_clk, rx_reset)
|
|
variable wrPtr : CHANNEL_CNT := (others => 0);
|
|
variable rdPtr : CHANNEL_CNT := (others => 3);
|
|
variable fifo_in_sync_reg : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
|
|
begin
|
|
for i in 0 to number_of_channels-1 loop
|
|
if (rx_reset(i) = '1') then
|
|
wrPtr(i) := 0;
|
|
rdPtr(i) := 3;
|
|
ram_array(i) <= (others => '0');
|
|
fifo_in_sync_reg(i) := '0';
|
|
fifo_out_sync_reg(i) <= '0';
|
|
write_side_sync_reset(i) <= '1';
|
|
read_side_sync_reset(i) <= '1';
|
|
end if;
|
|
end loop;
|
|
|
|
if (fifo_write_clk'event and (fifo_write_clk = '1')) then
|
|
for i in 0 to number_of_channels-1 loop
|
|
if ((rx_reset(i) = '1') or (rx_fifo_reset(i) = '1') or
|
|
((reset_fifo_at_first_lock = "ON") and (dpll_first_lock(i) = '0'))) then
|
|
wrPtr(i) := 0;
|
|
ram_array(i) <= (others => '0');
|
|
fifo_in_sync_reg(i) := '0';
|
|
write_side_sync_reset(i) <= '1';
|
|
else
|
|
write_side_sync_reset(i) <= '0';
|
|
if (write_side_sync_reset(i) = '0') then
|
|
ram_array(i)(wrPtr(i)) <= fifo_in_sync_reg(i);
|
|
fifo_in_sync_reg(i) := dpa_fifo_in(i);
|
|
wrPtr(i) := (wrPtr(i) + 1) rem 6;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
|
|
if (fifo_read_clk'event and (fifo_read_clk = '1')) then
|
|
for i in 0 to number_of_channels-1 loop
|
|
if ((rx_reset(i) = '1') or (rx_fifo_reset(i) = '1') or
|
|
((reset_fifo_at_first_lock = "ON") and (dpll_first_lock(i) = '0'))) then
|
|
rdPtr(i) := 3;
|
|
ram_array(i) <= (others =>'0');
|
|
fifo_out_sync_reg(i) <= '0';
|
|
read_side_sync_reset(i) <= '1';
|
|
else
|
|
read_side_sync_reset(i) <= '0';
|
|
if (read_side_sync_reset(i) = '0') then
|
|
fifo_out_sync_reg(i) <= ram_array(i)(rdPtr(i));
|
|
rdPtr(i) := (rdPtr(i) + 1) rem 6;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
end process STRATIXII_DPA_FIFO;
|
|
|
|
-- STRATIXII DPA Block
|
|
STRATIXII_DPA_BLOCK : process (rx_fastclk, rx_reset)
|
|
variable dpll_clk_count : CHANNEL_CNT := (others => 0);
|
|
variable init : boolean := true;
|
|
begin
|
|
if (init = true) then
|
|
if (enable_dpa_mode = "ON") then
|
|
ASSERT false
|
|
REPORT "DPA Phase tracking is not modeled, and once locked, DPA will continue to lock until the next reset is asserted. Please refer to the device handbook for further details."
|
|
SEVERITY warning;
|
|
end if;
|
|
init := false;
|
|
end if;
|
|
|
|
for i in 0 to number_of_channels-1 loop
|
|
if (rx_reset(i) = '1') then
|
|
dpll_clk_count(i) := 0;
|
|
dpll_lock(i) <= '0';
|
|
end if;
|
|
|
|
if (rx_fastclk'event and (rx_fastclk = '1')) then
|
|
dpa_in(i) <= rx_in(i);
|
|
retime_data(i) <= dpa_in(i);
|
|
|
|
if (rx_reset(i) /= '1') then
|
|
dpll_clk_count(i) := dpll_clk_count(i) + 1;
|
|
|
|
if (dpll_clk_count(i) > 2) then
|
|
dpll_lock(i) <= '1';
|
|
dpll_first_lock(i) <= '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
end process STRATIXII_DPA_BLOCK;
|
|
|
|
end behavior;
|
|
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : flexible_lvds_rx
|
|
--
|
|
-- Description : flexible lvds receiver
|
|
--
|
|
-- Limitation : Only available to Cyclone and Cyclone II families.
|
|
--
|
|
-- Results Expected: Deserialized output data.
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- LIBRARY USED----------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity flexible_lvds_rx is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
number_of_channels : natural; -- Required parameter
|
|
deserialization_factor : natural;
|
|
use_extra_ddio_register : boolean := true;
|
|
use_extra_pll_clk : boolean := false;
|
|
buffer_implementation : string := "RAM";
|
|
registered_data_align_input : string := "OFF";
|
|
use_external_pll : string := "OFF";
|
|
registered_output : string := "OFF";
|
|
add_latency : boolean := true
|
|
);
|
|
|
|
-- PORT DECLARATION
|
|
port(
|
|
--INPUT PORT DECLARATION
|
|
rx_in : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_fastclk : in std_logic; --Required port
|
|
rx_slowclk : in std_logic; --Required port
|
|
rx_syncclk : in std_logic; --Required port
|
|
pll_areset : in std_logic; --Required port
|
|
rx_data_reset : in std_logic;
|
|
rx_data_align : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_cda_reset : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_locked : in std_logic;
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
rx_out : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0));
|
|
|
|
end flexible_lvds_rx;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of flexible_lvds_rx is
|
|
|
|
-- FUNCTION DECLARATION
|
|
function get_latency ( constant i_deserialization_factor : in natural) return natural is
|
|
begin
|
|
if ((deserialization_factor rem 2) = 1) then
|
|
return (deserialization_factor / 2) + 1;
|
|
else
|
|
return (deserialization_factor / 2);
|
|
end if;
|
|
end get_latency;
|
|
|
|
function get_num_of_sync_stages ( constant i_latency : in natural) return natural is
|
|
variable num_of_sync_stages : natural := 0;
|
|
begin
|
|
|
|
if ((deserialization_factor = 4) and (add_latency = true)) then
|
|
num_of_sync_stages := 1;
|
|
else
|
|
if (add_latency = false) then
|
|
num_of_sync_stages := i_latency-2;
|
|
else
|
|
num_of_sync_stages := i_latency-3;
|
|
end if;
|
|
end if;
|
|
|
|
if (((deserialization_factor rem 2) = 1) and (not (((buffer_implementation = "RAM") or (buffer_implementation = "LES"))))) then
|
|
num_of_sync_stages := num_of_sync_stages + deserialization_factor/2;
|
|
end if;
|
|
|
|
return num_of_sync_stages;
|
|
|
|
end get_num_of_sync_stages;
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant REGISTER_WIDTH : natural := deserialization_factor * number_of_channels;
|
|
constant LATENCY : natural := get_latency(deserialization_factor);
|
|
constant NUM_OF_SYNC_STAGES : natural := get_num_of_sync_stages(LATENCY);
|
|
|
|
-- TYPE DECLARATION
|
|
type CHANNEL_CNT is array (number_of_channels-1 downto 0) of integer;
|
|
type DFFPIPE is array (NUM_OF_SYNC_STAGES downto 0) of std_logic_vector(number_of_channels -1 downto 0);
|
|
|
|
|
|
-- SIGNAL DECLARATION
|
|
|
|
-- constant signals
|
|
signal rx_shift_reg : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_shift_reg1 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_shift_reg2 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_sync_reg1 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_sync_reg2 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_sync_reg1_buf1 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_sync_reg1_buf1_pipe : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_sync_reg2_buf1 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_sync_reg1_buf2 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_sync_reg1_buf2_pipe : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_sync_reg2_buf2 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_out_odd : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_out_odd_mode : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_out_reg : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal rx_out_int : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal h_int_reg : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal l_int_reg : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
|
|
signal ddio_h_reg : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
|
|
signal ddio_l_reg : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
|
|
signal datain_h_reg : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
|
|
signal datain_l_reg : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
|
|
signal datain_l_latch : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
|
|
signal select_bit : std_logic := '0';
|
|
signal sync_clock : std_logic := '0';
|
|
signal rx_data_align_reg : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
|
|
signal rx_data_align_int : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
|
|
signal rx_data_align_clk : std_logic := '0';
|
|
signal int_bitslip_reg : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
|
|
signal bitslip_count : CHANNEL_CNT := (others => 0);
|
|
signal rx_reg_clk : std_logic := '0';
|
|
|
|
begin
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
rx_out_int <= rx_shift_reg when ((deserialization_factor rem 2) = 0)
|
|
else rx_out_odd when (buffer_implementation /= "MUX")
|
|
else rx_sync_reg1_buf1 when (select_bit = '1')
|
|
else rx_sync_reg2_buf1;
|
|
|
|
rx_out <= rx_out_reg when ((registered_output = "ON") and (use_external_pll = "OFF"))
|
|
else rx_out_int;
|
|
|
|
rx_reg_clk <= rx_slowclk when (registered_output = "ON")
|
|
else '0';
|
|
|
|
rx_data_align_clk <= rx_slowclk when ((deserialization_factor rem 2) = 0)
|
|
else sync_clock when (use_extra_pll_clk = false)
|
|
else rx_syncclk;
|
|
|
|
rx_data_align_int <= rx_data_align_reg when (registered_data_align_input = "ON") and (use_external_pll = "OFF")
|
|
else rx_data_align;
|
|
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
-- This always block implements the altddio_in that takes in the input serial
|
|
-- data of each channel and deserialized it into two parallel data stream
|
|
-- (ddio_h_reg and ddio_l_reg). Each parallel data stream will be registered
|
|
-- before send to shift registers.
|
|
DDIO_IN : process(rx_fastclk, pll_areset, rx_data_reset)
|
|
variable datain_h_reg_int : DFFPIPE := (others => (others => '0'));
|
|
variable datain_l_reg_int : DFFPIPE := (others => (others => '0'));
|
|
variable pipe_ptr : natural := 0;
|
|
begin
|
|
if (pll_areset = '1' or rx_data_reset = '1') then
|
|
ddio_h_reg <= (others => '0');
|
|
datain_h_reg <= (others => '0');
|
|
ddio_l_reg <= (others => '0');
|
|
datain_l_reg <= (others => '0');
|
|
datain_l_latch <= (others => '0');
|
|
datain_h_reg_int := (others => (others => '0'));
|
|
datain_l_reg_int := (others => (others => '0'));
|
|
elsif ((rx_fastclk = '1') and rx_fastclk'event) then
|
|
if (NUM_OF_SYNC_STAGES > 0) then
|
|
|
|
datain_h_reg <= datain_h_reg_int(pipe_ptr);
|
|
datain_l_reg <= datain_l_reg_int(pipe_ptr);
|
|
|
|
if (use_extra_ddio_register = true) then
|
|
ddio_h_reg <= rx_in;
|
|
datain_h_reg_int(pipe_ptr) := ddio_h_reg;
|
|
else
|
|
datain_h_reg_int(pipe_ptr) := rx_in;
|
|
end if;
|
|
|
|
datain_l_reg_int(pipe_ptr) := datain_l_latch;
|
|
|
|
if (NUM_OF_SYNC_STAGES > 1) then
|
|
pipe_ptr := (pipe_ptr + 1) rem NUM_OF_SYNC_STAGES;
|
|
end if;
|
|
|
|
else
|
|
if (use_extra_ddio_register = true) then
|
|
ddio_h_reg <= rx_in;
|
|
datain_h_reg <= ddio_h_reg;
|
|
else
|
|
datain_h_reg <= rx_in;
|
|
end if;
|
|
datain_l_reg <= datain_l_latch;
|
|
end if;
|
|
elsif (rx_fastclk'event and (rx_fastclk = '0')) then
|
|
if (use_extra_ddio_register = true) then
|
|
ddio_l_reg <= rx_in;
|
|
datain_l_latch <= ddio_l_reg;
|
|
else
|
|
datain_l_latch <= rx_in;
|
|
end if;
|
|
end if;
|
|
end process DDIO_IN;
|
|
|
|
-- bitslip counter
|
|
BITSLIP_CNT : process(rx_fastclk, rx_cda_reset)
|
|
begin
|
|
for i in 0 to number_of_channels-1 loop
|
|
if (rx_cda_reset(i) = '1') then
|
|
bitslip_count(i) <= 0;
|
|
elsif ((rx_fastclk = '1') and rx_fastclk'event) then
|
|
if (((not int_bitslip_reg(i)) and rx_data_align_int(i)) = '1') then
|
|
bitslip_count(i) <= (bitslip_count(i) + 1) rem deserialization_factor;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
end process BITSLIP_CNT;
|
|
|
|
DATA_ALIGN_REG : process(rx_data_align_clk)
|
|
begin
|
|
if ((rx_data_align_clk = '1') and rx_data_align_clk'event) then
|
|
rx_data_align_reg <= rx_data_align;
|
|
end if;
|
|
end process DATA_ALIGN_REG;
|
|
|
|
BITSLIP_REG : process(rx_fastclk)
|
|
begin
|
|
if ((rx_fastclk = '1') and rx_fastclk'event) then
|
|
int_bitslip_reg <= rx_data_align_int;
|
|
end if;
|
|
end process BITSLIP_REG;
|
|
|
|
-- Loading input data to shift register
|
|
SHIFTREG : process(rx_fastclk, pll_areset, rx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or rx_data_reset = '1') then
|
|
rx_shift_reg <= (others => '0');
|
|
rx_shift_reg1 <= (others => '0');
|
|
rx_shift_reg2 <= (others => '0');
|
|
h_int_reg <= (others => '0');
|
|
l_int_reg <= (others => '0');
|
|
elsif ((rx_fastclk = '1') and rx_fastclk'event) then
|
|
-- Implementation for even deserialization factor.
|
|
if ((deserialization_factor rem 2) = 0) then
|
|
for i in 0 to number_of_channels-1 loop
|
|
for x in (deserialization_factor-1) downto 2 loop
|
|
rx_shift_reg(x + (i * deserialization_factor)) <=
|
|
rx_shift_reg(x-2 + (i * deserialization_factor));
|
|
end loop;
|
|
|
|
for x in (deserialization_factor-1) downto 1 loop
|
|
h_int_reg(x + (i * deserialization_factor)) <=
|
|
h_int_reg(x-1 + (i * deserialization_factor));
|
|
|
|
l_int_reg(x + (i * deserialization_factor)) <=
|
|
l_int_reg(x-1 + (i * deserialization_factor));
|
|
end loop;
|
|
h_int_reg(i * deserialization_factor) <= datain_h_reg(i);
|
|
l_int_reg(i * deserialization_factor) <= datain_l_reg(i);
|
|
|
|
if (bitslip_count(i) = 0) then
|
|
rx_shift_reg(i * deserialization_factor) <= datain_h_reg(i);
|
|
rx_shift_reg((i * deserialization_factor)+1) <= datain_l_reg(i);
|
|
elsif (bitslip_count(i) = 1) then
|
|
rx_shift_reg(i * deserialization_factor) <= datain_l_reg(i);
|
|
rx_shift_reg((i * deserialization_factor)+1) <= h_int_reg(i * deserialization_factor);
|
|
else
|
|
if (bitslip_count(i) rem 2 = 1) then
|
|
rx_shift_reg(i * deserialization_factor) <= l_int_reg((bitslip_count(i)/2) -1 + (i * deserialization_factor));
|
|
rx_shift_reg((i * deserialization_factor)+1) <= h_int_reg((bitslip_count(i)/2) + (i * deserialization_factor));
|
|
else
|
|
rx_shift_reg(i * deserialization_factor) <= h_int_reg((bitslip_count(i)/2) -1 + (i * deserialization_factor));
|
|
rx_shift_reg((i * deserialization_factor)+1) <= l_int_reg((bitslip_count(i)/2) -1 + (i * deserialization_factor));
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
else -- Implementation for odd deserialization factor.
|
|
for i in 0 to number_of_channels-1 loop
|
|
for x in (deserialization_factor-1) downto 2 loop
|
|
rx_shift_reg1(x + (i * deserialization_factor)) <=
|
|
rx_shift_reg1(x-2 + (i * deserialization_factor));
|
|
|
|
rx_shift_reg2(x + (i * deserialization_factor)) <=
|
|
rx_shift_reg2(x-2 + (i * deserialization_factor));
|
|
end loop;
|
|
for x in (deserialization_factor-1) downto 1 loop
|
|
h_int_reg(x + (i * deserialization_factor)) <=
|
|
h_int_reg(x-1 + (i * deserialization_factor));
|
|
|
|
l_int_reg(x + (i * deserialization_factor)) <=
|
|
l_int_reg(x-1 + (i * deserialization_factor));
|
|
end loop;
|
|
h_int_reg(i * deserialization_factor) <= datain_h_reg(i);
|
|
l_int_reg(i * deserialization_factor) <= datain_l_reg(i);
|
|
|
|
if (bitslip_count(i) = 0) then
|
|
rx_shift_reg1(i * deserialization_factor) <= datain_h_reg(i);
|
|
rx_shift_reg1((i * deserialization_factor)+1) <= datain_l_reg(i);
|
|
elsif (bitslip_count(i) = 1) then
|
|
rx_shift_reg1(i * deserialization_factor) <= datain_l_reg(i);
|
|
rx_shift_reg1((i * deserialization_factor)+1) <= h_int_reg(i*deserialization_factor);
|
|
elsif (bitslip_count(i) rem 2 = 0) then
|
|
rx_shift_reg1(i * deserialization_factor) <= h_int_reg(bitslip_count(i)/2 -1 + (i * deserialization_factor));
|
|
rx_shift_reg1((i * deserialization_factor)+1) <= l_int_reg(bitslip_count(i)/2 -1 + (i * deserialization_factor));
|
|
else
|
|
rx_shift_reg1(i * deserialization_factor) <= l_int_reg(bitslip_count(i)/2 -1 + (i * deserialization_factor));
|
|
rx_shift_reg1((i * deserialization_factor)+1) <= h_int_reg(bitslip_count(i)/2 + (i * deserialization_factor));
|
|
end if;
|
|
|
|
rx_shift_reg2(i * deserialization_factor) <= rx_shift_reg1(((i+1)* deserialization_factor)-2);
|
|
rx_shift_reg2((i * deserialization_factor)+1) <= rx_shift_reg1(((i+1)* deserialization_factor)-1);
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end process SHIFTREG;
|
|
|
|
-- Loading input data to shift register
|
|
BIT_SELECT : process(rx_slowclk, pll_areset, rx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or rx_data_reset = '1') then
|
|
rx_sync_reg1 <= (others => '0');
|
|
rx_sync_reg2 <= (others => '0');
|
|
rx_sync_reg1_buf2_pipe <= (others => '0');
|
|
rx_out_odd <= (others => '0');
|
|
rx_out_odd_mode <= (others => '0');
|
|
elsif ((rx_slowclk = '1') and rx_slowclk'event) then
|
|
rx_sync_reg1 <= rx_shift_reg1;
|
|
rx_sync_reg2 <= rx_shift_reg2;
|
|
rx_sync_reg1_buf2_pipe <= rx_sync_reg1_buf2;
|
|
|
|
if(use_extra_pll_clk = false) then
|
|
if (select_bit = '1') then
|
|
rx_out_odd_mode <= rx_sync_reg1_buf1_pipe;
|
|
else
|
|
rx_out_odd_mode <= rx_sync_reg2_buf1;
|
|
end if;
|
|
else
|
|
if (select_bit = '1') then
|
|
rx_out_odd_mode <= rx_sync_reg1_buf2_pipe;
|
|
else
|
|
rx_out_odd_mode <= rx_sync_reg2_buf2;
|
|
end if;
|
|
end if;
|
|
|
|
rx_out_odd <= rx_out_odd_mode;
|
|
end if;
|
|
end process BIT_SELECT;
|
|
|
|
process(rx_slowclk)
|
|
begin
|
|
if ((rx_slowclk = '1') and rx_slowclk'event) then
|
|
sync_clock <= not sync_clock;
|
|
select_bit <= not select_bit;
|
|
end if;
|
|
end process;
|
|
|
|
SYNC_REG : process(sync_clock, pll_areset, rx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or rx_data_reset = '1') then
|
|
rx_sync_reg1_buf1 <= (others => '0');
|
|
rx_sync_reg2_buf1 <= (others => '0');
|
|
rx_sync_reg1_buf1_pipe <= (others => '0');
|
|
elsif ((sync_clock = '1') and sync_clock'event) then
|
|
rx_sync_reg1_buf1 <= rx_sync_reg1;
|
|
rx_sync_reg2_buf1 <= rx_sync_reg2;
|
|
rx_sync_reg1_buf1_pipe <= rx_sync_reg1_buf1;
|
|
end if;
|
|
end process SYNC_REG;
|
|
|
|
SYNC_REG2 : process(rx_syncclk, pll_areset, rx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or rx_data_reset = '1') then
|
|
rx_sync_reg1_buf2 <= (others => '0');
|
|
rx_sync_reg2_buf2 <= (others => '0');
|
|
elsif ((rx_syncclk = '1') and rx_syncclk'event) then
|
|
rx_sync_reg1_buf2 <= rx_sync_reg1;
|
|
rx_sync_reg2_buf2 <= rx_sync_reg2;
|
|
end if;
|
|
end process SYNC_REG2;
|
|
|
|
OUTPUT_REG : process(rx_reg_clk, pll_areset, rx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or rx_data_reset = '1') then
|
|
rx_out_reg <= (others => '0');
|
|
elsif ((rx_reg_clk = '1') and rx_reg_clk'event) then
|
|
rx_out_reg <= rx_out_int;
|
|
end if;
|
|
end process;
|
|
|
|
end behavior; -- flexible_lvds_rx
|
|
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : stratixiii_lvds_rx_dpa
|
|
--
|
|
-- Description : Simulation model for Stratix III DPA block.
|
|
--
|
|
-- Limitation : Only available to Stratix III.
|
|
--
|
|
-- Results expected: Retimed data, dpa clock, enable and lock signal with the selected phase.
|
|
--
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- LIBRARY USED----------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity stratixiii_lvds_rx_dpa is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
enable_soft_cdr_mode : string := "OFF";
|
|
sim_dpa_is_negative_ppm_drift : string := "OFF";
|
|
sim_dpa_net_ppm_variation : natural := 0;
|
|
enable_dpa_align_to_rising_edge_only : string := "OFF";
|
|
enable_dpa_initial_phase_selection : string := "OFF";
|
|
dpa_initial_phase_value : natural := 0 );
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
--INPUT PORT DECLARATION
|
|
rx_in : in std_logic;
|
|
rx_fastclk : in std_logic;
|
|
rx_enable : in std_logic;
|
|
rx_dpa_reset : in std_logic;
|
|
rx_dpa_hold : in std_logic;
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
rx_out : out std_logic := '0';
|
|
rx_dpa_clk : out std_logic := '0';
|
|
rx_dpa_loaden : out std_logic := '0';
|
|
rx_dpa_locked : out std_logic := '0' );
|
|
|
|
end stratixiii_lvds_rx_dpa;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of stratixiii_lvds_rx_dpa is
|
|
|
|
-- FUNCTION DECLARATION
|
|
-- get phase_shift value for the clock that acts as enable signal (for StratixIII lvds)
|
|
function get_initial_phase_select ( constant i_initial_phase_select : in natural) return natural is
|
|
begin
|
|
|
|
if ((enable_dpa_initial_phase_selection = "ON") and
|
|
(i_initial_phase_select > 0) and
|
|
(i_initial_phase_select <= 7)) then
|
|
return i_initial_phase_select;
|
|
else
|
|
return 0;
|
|
end if;
|
|
end get_initial_phase_select;
|
|
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant INITIAL_PHASE_SELECT : natural := get_initial_phase_select(dpa_initial_phase_value);
|
|
constant PHASE_NUM : natural := 8;
|
|
|
|
-- TYPE DECLARATION
|
|
type PHASE_TAP is array (PHASE_NUM -1 downto 0) of natural;
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal dpa_clk_tmp : std_logic_vector (PHASE_NUM -1 downto 0);
|
|
signal dpa_loaden : std_logic_vector (PHASE_NUM -1 downto 0) := (others => '0');
|
|
signal dpa_dataout_tmp : std_logic_vector (PHASE_NUM -1 downto 0) := (others => '0');
|
|
signal ppm_offset : integer := 0;
|
|
signal count : integer := 0;
|
|
signal rx_in_reg0 : std_logic := '0';
|
|
signal rx_in_reg1 : std_logic := '0';
|
|
signal dpa_locked_tmp : std_logic := '0';
|
|
signal first_clkin_edge_detect : std_logic := '0';
|
|
signal reg_clk : std_logic;
|
|
signal counter_reset_value : integer ;
|
|
signal count_value : integer ;
|
|
signal clk_period : time := 0 ps;
|
|
signal last_clk_period : time := 0 ps;
|
|
signal last_clkin_edge : time := 0 ps;
|
|
signal j : integer ;
|
|
|
|
begin
|
|
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
rx_dpa_loaden <= '0' when (enable_soft_cdr_mode = "ON")
|
|
else dpa_loaden(INITIAL_PHASE_SELECT);
|
|
|
|
reg_clk <= dpa_clk_tmp(INITIAL_PHASE_SELECT);
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
-- Calculate the clock period
|
|
process (rx_fastclk)
|
|
variable clk_period_tmp : time := 0 ps;
|
|
begin
|
|
if (rx_fastclk'event and rx_fastclk = '1') then
|
|
if (first_clkin_edge_detect = '0') then
|
|
first_clkin_edge_detect <= '1';
|
|
else
|
|
clk_period_tmp := now - last_clkin_edge;
|
|
end if;
|
|
|
|
if (((clk_period_tmp = last_clk_period) or (clk_period_tmp = last_clk_period + 1 ps) or
|
|
(clk_period_tmp = last_clk_period - 1 ps)) and (clk_period_tmp /= 0 ps ) and (last_clk_period /= 0 ps)) then
|
|
dpa_locked_tmp <= '1';
|
|
else
|
|
dpa_locked_tmp <= '0';
|
|
end if;
|
|
|
|
last_clkin_edge <= now;
|
|
last_clk_period <= clk_period_tmp;
|
|
end if;
|
|
end process;
|
|
|
|
-- Generate the phase shifted dpa clock signals
|
|
process (rx_fastclk)
|
|
begin
|
|
dpa_clk_tmp(0) <= rx_fastclk;
|
|
dpa_clk_tmp(1) <= transport rx_fastclk after (clk_period * 0.125);
|
|
dpa_clk_tmp(2) <= transport rx_fastclk after (clk_period * 0.25);
|
|
dpa_clk_tmp(3) <= transport rx_fastclk after (clk_period * 0.375);
|
|
dpa_clk_tmp(4) <= transport rx_fastclk after (clk_period * 0.5);
|
|
dpa_clk_tmp(5) <= transport rx_fastclk after (clk_period * 0.625);
|
|
dpa_clk_tmp(6) <= transport rx_fastclk after (clk_period * 0.75);
|
|
dpa_clk_tmp(7) <= transport rx_fastclk after (clk_period * 0.875);
|
|
end process;
|
|
|
|
-- Generate the phase shifted dpa enable signals
|
|
process (rx_enable)
|
|
begin
|
|
dpa_loaden(0) <= rx_enable;
|
|
dpa_loaden(1) <= transport rx_enable after (clk_period * 0.125);
|
|
dpa_loaden(2) <= transport rx_enable after (clk_period * 0.25);
|
|
dpa_loaden(3) <= transport rx_enable after (clk_period * 0.375);
|
|
dpa_loaden(4) <= transport rx_enable after (clk_period * 0.5);
|
|
dpa_loaden(5) <= transport rx_enable after (clk_period * 0.625);
|
|
dpa_loaden(6) <= transport rx_enable after (clk_period * 0.75);
|
|
dpa_loaden(7) <= transport rx_enable after (clk_period * 0.875);
|
|
end process;
|
|
|
|
|
|
-- Generate the phase shifted data signals
|
|
process (rx_in_reg1)
|
|
begin
|
|
dpa_dataout_tmp(0) <= rx_in_reg1;
|
|
dpa_dataout_tmp(1) <= transport rx_in_reg1 after (clk_period * 0.125) ;
|
|
dpa_dataout_tmp(2) <= transport rx_in_reg1 after (clk_period * 0.25) ;
|
|
dpa_dataout_tmp(3) <= transport rx_in_reg1 after (clk_period * 0.375) ;
|
|
dpa_dataout_tmp(4) <= transport rx_in_reg1 after (clk_period * 0.5) ;
|
|
dpa_dataout_tmp(5) <= transport rx_in_reg1 after (clk_period * 0.625) ;
|
|
dpa_dataout_tmp(6) <= transport rx_in_reg1 after (clk_period * 0.75) ;
|
|
dpa_dataout_tmp(7) <= transport rx_in_reg1 after (clk_period * 0.875) ;
|
|
end process;
|
|
|
|
process (reg_clk)
|
|
begin
|
|
if (reg_clk'event and reg_clk = '1') then
|
|
rx_in_reg0 <= rx_in;
|
|
rx_in_reg1 <= rx_in_reg0;
|
|
end if;
|
|
end process;
|
|
|
|
process (dpa_dataout_tmp, ppm_offset, rx_dpa_reset)
|
|
begin
|
|
if (enable_soft_cdr_mode = "OFF") then
|
|
rx_out <= dpa_dataout_tmp(0);
|
|
else
|
|
if (rx_dpa_reset = '1') then
|
|
rx_out <= '0';
|
|
else
|
|
if (sim_dpa_is_negative_ppm_drift = "ON") then
|
|
rx_out <= dpa_dataout_tmp(ppm_offset rem PHASE_NUM);
|
|
elsif (ppm_offset = 0) then
|
|
rx_out <= dpa_dataout_tmp(0);
|
|
else
|
|
rx_out <= transport dpa_dataout_tmp(0) after (clk_period * 0.125 * ppm_offset);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process (dpa_clk_tmp, ppm_offset, rx_dpa_reset)
|
|
begin
|
|
if (enable_soft_cdr_mode = "OFF") then
|
|
rx_dpa_clk <= dpa_clk_tmp(INITIAL_PHASE_SELECT);
|
|
else
|
|
if (rx_dpa_reset = '1') then
|
|
rx_dpa_clk <= '0';
|
|
else
|
|
if (sim_dpa_is_negative_ppm_drift = "ON") then
|
|
rx_dpa_clk <= dpa_clk_tmp((INITIAL_PHASE_SELECT + ppm_offset) rem PHASE_NUM);
|
|
elsif ((INITIAL_PHASE_SELECT + ppm_offset) = 0) then
|
|
rx_dpa_clk <= dpa_clk_tmp(0);
|
|
else
|
|
rx_dpa_clk <= transport dpa_clk_tmp(0) after (clk_period * 0.125 * (INITIAL_PHASE_SELECT + ppm_offset));
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process (dpa_locked_tmp, rx_dpa_reset)
|
|
begin
|
|
if (rx_dpa_reset = '1') then
|
|
rx_dpa_locked <= '0';
|
|
else
|
|
rx_dpa_locked <= dpa_locked_tmp;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
STRATIXIII_PPM_OFFSET :
|
|
|
|
if (enable_soft_cdr_mode = "ON") generate
|
|
|
|
process (rx_fastclk, rx_dpa_reset, rx_dpa_hold)
|
|
variable initial : boolean := true;
|
|
begin
|
|
if(initial) then
|
|
if(sim_dpa_net_ppm_variation = 0) then
|
|
counter_reset_value <= 1;
|
|
count_value <= 1;
|
|
else
|
|
counter_reset_value <= 1000000 / (sim_dpa_net_ppm_variation * 8);
|
|
count_value <= 1000000 / (sim_dpa_net_ppm_variation * 8);
|
|
end if;
|
|
initial := false;
|
|
end if;
|
|
|
|
if (sim_dpa_net_ppm_variation = 0) then
|
|
ppm_offset <= 0;
|
|
else
|
|
if (rx_dpa_reset = '1') then
|
|
count <= 0;
|
|
ppm_offset <= 0;
|
|
else
|
|
if(rx_dpa_hold = '0') then
|
|
if (rx_fastclk'event and rx_fastclk = '1') then
|
|
if (count < count_value) then
|
|
count <= count + 1;
|
|
else
|
|
if (sim_dpa_is_negative_ppm_drift = "ON") then
|
|
ppm_offset <= (ppm_offset - 1 + PHASE_NUM) rem PHASE_NUM;
|
|
else
|
|
ppm_offset <= ppm_offset + 1;
|
|
end if;
|
|
count <= 0;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate STRATIXIII_PPM_OFFSET;
|
|
|
|
end behavior;
|
|
|
|
-- END OF ARCHITECTURE
|
|
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : stratixv_local_clk_divider
|
|
--
|
|
-- Description : Simulation model for Stratix V local clock divider.
|
|
--
|
|
-- Limitation : Only available to Stratix V.
|
|
--
|
|
-- Results expected: This module is used to generate the local loaden signal from fast clock for StratixV
|
|
-- family. To mimic local clock divider block.
|
|
--
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- LIBRARY USED----------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity stratixv_local_clk_divider is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
clk_divide_by : natural := 4 );
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
--INPUT PORT DECLARATION
|
|
clkin : in std_logic;
|
|
-- OUTPUT PORT DECLARATION
|
|
lloaden : out std_logic := '0' );
|
|
|
|
end stratixv_local_clk_divider;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of stratixv_local_clk_divider is
|
|
|
|
-- FUNCTION DECLARATION
|
|
|
|
-- CONSTANT DECLARATION
|
|
|
|
-- TYPE DECLARATION
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal lloaden_tmp : std_logic := '0';
|
|
signal cnt : integer := 0;
|
|
signal count : integer := 0;
|
|
|
|
begin
|
|
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
lloaden <= lloaden_tmp;
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
process (clkin)
|
|
begin
|
|
if (clkin'event and clkin = '1') then
|
|
count <= 1;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
process (clkin)
|
|
begin
|
|
if (clkin'event and clkin = '0') then --falling edge on fastclock
|
|
if (count = 1) then
|
|
if (cnt < (clk_divide_by-1)) then
|
|
cnt <= cnt + 1;
|
|
else
|
|
cnt <= 0;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
process (cnt)
|
|
begin
|
|
if (cnt = (clk_divide_by-1)) then
|
|
lloaden_tmp <= '1';
|
|
else
|
|
lloaden_tmp <= '0';
|
|
end if;
|
|
end process;
|
|
|
|
end behavior;
|
|
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : stratixiii_lvds_rx_channel
|
|
--
|
|
-- Description : Simulation model for each channel of Stratix III lvds receiver.
|
|
-- Support both the dpa and non-dpa mode.
|
|
--
|
|
-- Limitation : Only available to Stratix III.
|
|
--
|
|
-- Results Expected: Deserialized output data, dpa lock signal, forwarded clock
|
|
-- and status bit indicating whether maximum bitslip has been
|
|
-- reached.
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- LIBRARY USED----------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
use work.stratixiii_lvds_rx_dpa;
|
|
use work.stratixv_local_clk_divider;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity stratixiii_lvds_rx_channel is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
deserialization_factor : natural; -- Required parameter
|
|
enable_dpa_mode : string := "OFF";
|
|
data_align_rollover : natural := 10;
|
|
lose_lock_on_one_change : string := "OFF";
|
|
reset_fifo_at_first_lock : string := "ON";
|
|
x_on_bitslip : string := "ON";
|
|
rx_align_data_reg : string := "RISING_EDGE";
|
|
enable_soft_cdr_mode : string := "OFF";
|
|
sim_dpa_output_clock_phase_shift : integer := 0;
|
|
sim_dpa_is_negative_ppm_drift : string := "OFF";
|
|
sim_dpa_net_ppm_variation : natural := 0;
|
|
enable_dpa_align_to_rising_edge_only : string := "OFF";
|
|
enable_dpa_initial_phase_selection : string := "OFF";
|
|
dpa_initial_phase_value : natural := 0;
|
|
registered_output : string := "ON";
|
|
use_external_pll : string := "OFF";
|
|
use_dpa_calibration : boolean := false;
|
|
enable_clock_pin_mode : string := "UNUSED";
|
|
ARRIAII_RX_STYLE : boolean := false;
|
|
STRATIXV_RX_STYLE : boolean := false );
|
|
|
|
-- PORT DECLARATION
|
|
port(
|
|
--INPUT PORT DECLARATION
|
|
rx_in : in std_logic;
|
|
rx_fastclk : in std_logic;
|
|
rx_slowclk : in std_logic;
|
|
rx_dpaclock : in std_logic := '0';
|
|
rx_enable : in std_logic;
|
|
rx_reset : in std_logic;
|
|
rx_dpll_reset : in std_logic;
|
|
rx_dpll_hold : in std_logic;
|
|
rx_dpll_enable : in std_logic;
|
|
rx_fifo_reset : in std_logic;
|
|
rx_channel_data_align : in std_logic;
|
|
rx_cda_reset : in std_logic;
|
|
rx_dpa_lock_reset : in std_logic;
|
|
rx_locked : in std_logic;
|
|
-- OUTPUT PORT DECLARATION
|
|
rx_out : out std_logic_vector(deserialization_factor-1 downto 0);
|
|
rx_dpa_locked : out std_logic := '0';
|
|
rx_cda_max : out std_logic := '0';
|
|
rx_divfwdclk : out std_logic := '0' );
|
|
|
|
end stratixiii_lvds_rx_channel;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of stratixiii_lvds_rx_channel is
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant RAM_WIDTH : natural := 6;
|
|
constant MUX_WIDTH : natural := 12;
|
|
|
|
-- TYPE DECLARATION
|
|
|
|
|
|
-- SIGNAL DECLARATION
|
|
|
|
-- constant signals
|
|
signal fifo_write_clk : std_logic := '0';
|
|
signal fifo_read_clk : std_logic := '0';
|
|
|
|
signal temp_zero : std_logic := '0';
|
|
|
|
signal enable0_reg : std_logic := '0';
|
|
signal enable_negedge_count : boolean := false;
|
|
|
|
signal rx_shift_reg : std_logic_vector(deserialization_factor-1 downto 0) := (others => '0');
|
|
signal rx_parallel_load_reg : std_logic_vector(deserialization_factor-1 downto 0) := (others => '0');
|
|
signal rx_out_reg : std_logic_vector(deserialization_factor-1 downto 0) := (others => '0');
|
|
signal rx_dpa_sync_reg : std_logic_vector(deserialization_factor-1 downto 0) := (others => '0');
|
|
|
|
signal rx_in_reg_pos : std_logic := '0';
|
|
signal rx_in_reg_neg : std_logic := '0';
|
|
signal fifo_out_sync_reg : std_logic := '0';
|
|
signal bitslip_mux_out : std_logic := '0';
|
|
signal dpa_in : std_logic := '0';
|
|
signal retime_data : std_logic := '0';
|
|
signal dpll_lock : std_logic := '0';
|
|
signal dpll_first_lock : std_logic := '0';
|
|
signal rx_channel_data_align_pre : std_logic := '0';
|
|
signal write_side_sync_reset : std_logic := '0';
|
|
signal read_side_sync_reset : std_logic := '0';
|
|
|
|
signal ram_array : std_logic_vector(RAM_WIDTH-1 downto 0) := (others => '0');
|
|
|
|
signal dpa_fifo_in : std_logic := '0';
|
|
signal dpa_fifo_out : std_logic := '0';
|
|
signal rx_in_reg_clk : std_logic := '0';
|
|
signal rx_bload : std_logic := '0';
|
|
signal rx_enable_dly : std_logic := '0';
|
|
signal load_enable_cdr : std_logic := '0';
|
|
signal dpa_clock : std_logic := '0';
|
|
signal dpa_locked : std_logic := '0';
|
|
signal dpa_loaden : std_logic := '0';
|
|
signal fast_clock : std_logic := '0';
|
|
signal start_counter : std_logic := '0';
|
|
signal rx_reg_clk : std_logic := '0';
|
|
signal rx_dpa_sync_reg_clk : std_logic := '0';
|
|
signal rx_divfwdclk_int : std_logic := '0';
|
|
signal j : integer ;
|
|
signal lock_out_regr : std_logic := '0';
|
|
signal pad_regr : std_logic_vector(deserialization_factor-1 downto 0) := (others => '0');
|
|
signal extra_regr : std_logic := '0';
|
|
signal in_bus_add : std_logic_vector(deserialization_factor-1 downto 0) := (others => '0');
|
|
signal lock_out_reg_dly : std_logic := '0';
|
|
signal fifo_reset_regr : std_logic := '0';
|
|
signal int_pll_kick_reset : std_logic := '0';
|
|
signal dpa_lock_fifo_reset : std_logic := '0';
|
|
signal pll_locked : std_logic := '0';
|
|
signal wire_lock_state_mc_d : std_logic_vector(1 DOWNTO 0);
|
|
signal lock_state_mc : std_logic_vector(1 DOWNTO 0) := (others => '0');
|
|
signal wire_lock_state_mc_ena : std_logic_vector(1 DOWNTO 0);
|
|
signal dpaswitch : std_logic := '0';
|
|
signal rx_in_wire : std_logic := '0';
|
|
signal rx_dpaclock_wire : std_logic := '0';
|
|
signal local_clk_div_lloaden : std_logic := '0';
|
|
|
|
-- COMPONENT DECLARATION
|
|
|
|
-- stratixiii dpa block
|
|
component stratixiii_lvds_rx_dpa
|
|
generic (
|
|
enable_soft_cdr_mode : string := "OFF";
|
|
sim_dpa_is_negative_ppm_drift : string := "OFF";
|
|
sim_dpa_net_ppm_variation : natural := 0;
|
|
enable_dpa_align_to_rising_edge_only : string := "OFF";
|
|
enable_dpa_initial_phase_selection : string := "OFF";
|
|
dpa_initial_phase_value : natural := 0 );
|
|
|
|
port(
|
|
rx_in : in std_logic;
|
|
rx_fastclk : in std_logic;
|
|
rx_enable : in std_logic := '1';
|
|
rx_dpa_reset : in std_logic;
|
|
rx_dpa_hold : in std_logic;
|
|
rx_out : out std_logic := '0';
|
|
rx_dpa_clk : out std_logic := '0';
|
|
rx_dpa_loaden : out std_logic := '0';
|
|
rx_dpa_locked : out std_logic := '0' );
|
|
end component; -- stratixiii_lvds_rx_dpa
|
|
|
|
-- stratix V local clock divider block
|
|
component stratixv_local_clk_divider
|
|
generic (
|
|
clk_divide_by : natural := 4 );
|
|
|
|
port(
|
|
clkin : in std_logic;
|
|
lloaden : out std_logic := '0' );
|
|
end component; -- stratix V local clock divider block
|
|
|
|
begin
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
rx_out <= rx_out_reg when (registered_output = "ON")
|
|
else rx_parallel_load_reg;
|
|
rx_divfwdclk <= not rx_divfwdclk_int;
|
|
dpa_fifo_in <= retime_data;
|
|
dpa_fifo_out <= fifo_out_sync_reg;
|
|
fifo_write_clk <= dpa_clock;
|
|
fifo_read_clk <= rx_fastclk;
|
|
rx_in_reg_clk <= rx_fastclk;
|
|
rx_dpa_locked <=((lock_state_mc(0) and lock_state_mc(1)) and lock_out_reg_dly) when (use_dpa_calibration = true)
|
|
else lock_out_reg_dly;
|
|
rx_bload <= enable0_reg;
|
|
rx_enable_dly <= local_clk_div_lloaden when ((STRATIXV_RX_STYLE = true) and (enable_clock_pin_mode = "ON"))
|
|
else rx_enable;
|
|
fast_clock <= dpa_clock when ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON"))
|
|
else rx_fastclk;
|
|
rx_reg_clk <= not rx_divfwdclk_int when ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON"))
|
|
else rx_slowclk;
|
|
rx_dpa_sync_reg_clk <= rx_divfwdclk_int when ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON"))
|
|
else '0';
|
|
int_pll_kick_reset <= ((lock_state_mc(0) and (not lock_state_mc(1))) or ((lock_state_mc(0) and lock_state_mc(1)) and rx_dpa_lock_reset)) when (use_dpa_calibration = true)
|
|
else rx_dpa_lock_reset;
|
|
pll_locked <= rx_locked;
|
|
wire_lock_state_mc_ena(1 downto 0) <= (others => ((lock_state_mc(0) and lock_state_mc(1) and rx_dpa_lock_reset) or (not lock_state_mc(0) and not lock_state_mc(1) and lock_out_regr) or (lock_state_mc(0) and not lock_state_mc(1) and lock_out_reg_dly) or (not lock_state_mc(0) and lock_state_mc(1) and lock_out_regr)));
|
|
wire_lock_state_mc_d <= ((((lock_state_mc(0) and (not lock_state_mc(1))) and lock_out_reg_dly) or (((not lock_state_mc(0)) and lock_state_mc(1)) and lock_out_regr)) and (not (((lock_state_mc(0) and lock_state_mc(1)) and rx_dpa_lock_reset) or (((not lock_state_mc(0)) and (not lock_state_mc(1))) and lock_out_regr)))) & (((((not lock_state_mc(0)) and (not lock_state_mc(1))) and lock_out_regr) or (((not lock_state_mc(0)) and lock_state_mc(1)) and lock_out_regr)) and (not (((lock_state_mc(0) and lock_state_mc(1)) and rx_dpa_lock_reset) or ((lock_state_mc(0) and (not lock_state_mc(1))) and lock_out_reg_dly))));
|
|
dpaswitch <= ((not lock_state_mc(0)) and (not lock_state_mc(1))) when (use_dpa_calibration = true)
|
|
else '1';
|
|
fifo_reset_regr <= (((not lock_state_mc(0)) and lock_state_mc(1)) and (lock_out_regr xor lock_out_reg_dly)) when (use_dpa_calibration = true)
|
|
else ((lock_out_regr xor lock_out_reg_dly) or (not dpa_locked) or rx_fifo_reset);
|
|
rx_in_wire <= TRANSPORT rx_in after 120 ps when ((use_dpa_calibration = true) and (dpaswitch = '1'))
|
|
else rx_in;
|
|
rx_dpaclock_wire <= TRANSPORT rx_dpaclock when ((use_external_pll = "ON") and (STRATIXV_RX_STYLE = true) and (enable_dpa_mode = "ON"))
|
|
else rx_fastclk;
|
|
|
|
-- COMPONENT ASSIGNMENTS
|
|
STRATIXIII_DPA:
|
|
if (enable_dpa_mode = "ON") generate
|
|
|
|
dpa_block : stratixiii_lvds_rx_dpa -- Stratix III DPA block
|
|
generic map (
|
|
enable_soft_cdr_mode => enable_soft_cdr_mode,
|
|
sim_dpa_is_negative_ppm_drift => sim_dpa_is_negative_ppm_drift,
|
|
sim_dpa_net_ppm_variation => sim_dpa_net_ppm_variation,
|
|
enable_dpa_align_to_rising_edge_only => enable_dpa_align_to_rising_edge_only,
|
|
enable_dpa_initial_phase_selection => enable_dpa_initial_phase_selection,
|
|
dpa_initial_phase_value => dpa_initial_phase_value )
|
|
|
|
port map (
|
|
rx_in => rx_in_wire,
|
|
rx_fastclk => rx_dpaclock_wire,
|
|
rx_enable => rx_enable,
|
|
rx_dpa_reset => rx_reset,
|
|
rx_dpa_hold => rx_dpll_hold,
|
|
rx_out => retime_data,
|
|
rx_dpa_clk => dpa_clock,
|
|
rx_dpa_loaden => dpa_loaden,
|
|
rx_dpa_locked => dpa_locked );
|
|
|
|
end generate STRATIXIII_DPA;
|
|
|
|
|
|
STRATIXV_RX_LOCAL_CLK_DIVIDER:
|
|
if ((STRATIXV_RX_STYLE = true) and (enable_clock_pin_mode = "ON")) generate
|
|
|
|
rx_local_clk_divider : stratixv_local_clk_divider -- Stratix V local clock divider block
|
|
generic map (
|
|
clk_divide_by => deserialization_factor )
|
|
|
|
port map (
|
|
clkin => fast_clock,
|
|
lloaden => local_clk_div_lloaden );
|
|
|
|
end generate STRATIXV_RX_LOCAL_CLK_DIVIDER;
|
|
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
|
|
|
|
-- input synchronization register
|
|
IN_SYNC_REGISTER : process (fast_clock)
|
|
begin
|
|
if (fast_clock = '1' and fast_clock'event) then
|
|
rx_in_reg_pos <= rx_in_wire;
|
|
elsif (fast_clock = '0' and fast_clock'event) then
|
|
rx_in_reg_neg <= rx_in_wire;
|
|
end if;
|
|
end process IN_SYNC_REGISTER;
|
|
|
|
-- the deserializer
|
|
STRATIXIII_DESER : process(fast_clock)
|
|
begin
|
|
if (fast_clock'event and (fast_clock = '1')) then
|
|
if (rx_bload = '1') then
|
|
rx_parallel_load_reg <= rx_shift_reg;
|
|
end if;
|
|
|
|
rx_shift_reg <= rx_shift_reg(deserialization_factor-2 downto 0) & bitslip_mux_out;
|
|
|
|
-- Registering load enable signal
|
|
if ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON")) then
|
|
enable0_reg <= load_enable_cdr;
|
|
else
|
|
enable0_reg <= rx_enable_dly;
|
|
end if;
|
|
end if;
|
|
end process STRATIXIII_DESER;
|
|
|
|
STRATIXIII_FWDCLK :
|
|
|
|
if ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON")) generate
|
|
-- STRATIXIII forwarded clock
|
|
process (fast_clock)
|
|
variable div_clk_count_pos : integer := 0;
|
|
variable div_clk_count_neg : integer := 0;
|
|
begin
|
|
if (fast_clock = '1' and fast_clock'event) then
|
|
if (div_clk_count_pos = deserialization_factor) then
|
|
div_clk_count_pos := 1;
|
|
else
|
|
div_clk_count_pos := div_clk_count_pos + 1;
|
|
end if;
|
|
elsif (fast_clock = '0' and fast_clock'event) then
|
|
div_clk_count_neg := div_clk_count_pos;
|
|
end if;
|
|
|
|
-- even deser mode
|
|
if (deserialization_factor rem 2 = 0) then
|
|
if (div_clk_count_pos = 1) then
|
|
rx_divfwdclk_int <= '0';
|
|
elsif (div_clk_count_pos = ((deserialization_factor/2) + 1)) then
|
|
rx_divfwdclk_int <= '1';
|
|
end if;
|
|
else
|
|
-- odd deser mode
|
|
if (div_clk_count_pos = 1) then
|
|
rx_divfwdclk_int <= '0';
|
|
elsif (div_clk_count_neg = ((deserialization_factor+1) / 2)) then
|
|
rx_divfwdclk_int <= '1';
|
|
end if;
|
|
end if;
|
|
|
|
if (div_clk_count_neg = (deserialization_factor-1)) then
|
|
load_enable_cdr <= '1';
|
|
elsif (div_clk_count_neg = deserialization_factor) then
|
|
load_enable_cdr <= '0';
|
|
end if;
|
|
|
|
end process;
|
|
|
|
end generate STRATIXIII_FWDCLK;
|
|
|
|
-- STRATIXIII bitslip logic
|
|
STRATIXIII_BITSLIP : process (fast_clock, rx_cda_reset)
|
|
variable start_corrupt_bits : boolean := false;
|
|
variable num_corrupt_bits : integer := 0;
|
|
variable bitslip_count : integer := 0;
|
|
variable shift_reg_chain : std_logic_vector(MUX_WIDTH-1 downto 0) := (others => '0');
|
|
begin
|
|
if (rx_cda_reset = '1') then
|
|
bitslip_count := 0;
|
|
rx_cda_max <= '0';
|
|
end if;
|
|
if (fast_clock'event and (fast_clock = '1')) then
|
|
if ((((rx_channel_data_align = '1') and
|
|
(rx_channel_data_align_pre = '0')) or
|
|
((start_corrupt_bits = true) and
|
|
(num_corrupt_bits < 4) and
|
|
(rx_channel_data_align = '1'))) and
|
|
(x_on_bitslip = "ON")) then
|
|
bitslip_mux_out <= 'X';
|
|
else
|
|
bitslip_mux_out <= shift_reg_chain(bitslip_count);
|
|
end if;
|
|
|
|
for j in data_align_rollover -1 downto 0 loop
|
|
shift_reg_chain(j + 1) := shift_reg_chain(j);
|
|
end loop;
|
|
|
|
if ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON"))then
|
|
shift_reg_chain(0) := retime_data;
|
|
elsif ((enable_dpa_mode = "ON") and ((rx_dpll_enable = '1') or (dpaswitch = '1')))then
|
|
shift_reg_chain(0) := dpa_fifo_out;
|
|
elsif (rx_align_data_reg = "RISING_EDGE") then
|
|
shift_reg_chain(0) := rx_in_reg_pos;
|
|
else
|
|
shift_reg_chain(0) := rx_in_reg_neg;
|
|
end if;
|
|
|
|
if ((rx_channel_data_align = '1') and
|
|
(rx_channel_data_align_pre = '0'))then
|
|
bitslip_count := (bitslip_count + 1) rem (data_align_rollover + 1);
|
|
if (bitslip_count = data_align_rollover) then
|
|
rx_cda_max <= '1';
|
|
else
|
|
rx_cda_max <= '0';
|
|
end if;
|
|
|
|
start_corrupt_bits := true;
|
|
num_corrupt_bits := 1;
|
|
elsif ((rx_channel_data_align = '0') and
|
|
(rx_channel_data_align_pre = '1'))then
|
|
start_corrupt_bits := false;
|
|
num_corrupt_bits := 0;
|
|
end if;
|
|
|
|
if (start_corrupt_bits = true) then
|
|
if (num_corrupt_bits = 3) then
|
|
start_corrupt_bits := false;
|
|
else
|
|
num_corrupt_bits := num_corrupt_bits + 1;
|
|
end if;
|
|
end if;
|
|
rx_channel_data_align_pre <= rx_channel_data_align;
|
|
|
|
end if;
|
|
end process STRATIXIII_BITSLIP;
|
|
|
|
|
|
STRATIXIII_DPA_FIFO :
|
|
|
|
if ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "OFF")) generate
|
|
|
|
-- STRATIXIII Phase Compensation FIFO
|
|
DPA_FIFO : process (fifo_write_clk, fifo_read_clk, rx_reset, fifo_reset_regr)
|
|
variable wrPtr : integer := 0;
|
|
variable rdPtr : integer := 3;
|
|
variable fifo_in_sync_reg : std_logic := '0';
|
|
begin
|
|
if (rx_reset = '1' or fifo_reset_regr = '1') then
|
|
wrPtr := 0;
|
|
rdPtr := 3;
|
|
ram_array <= (others => '0');
|
|
fifo_in_sync_reg := '0';
|
|
fifo_out_sync_reg <= '0';
|
|
write_side_sync_reset <= '1';
|
|
read_side_sync_reset <= '1';
|
|
else
|
|
if (fifo_write_clk'event and (fifo_write_clk = '1')) then
|
|
write_side_sync_reset <= '0';
|
|
if (write_side_sync_reset = '0') then
|
|
ram_array(wrPtr) <= fifo_in_sync_reg;
|
|
fifo_in_sync_reg := dpa_fifo_in;
|
|
wrPtr := (wrPtr + 1) rem 6;
|
|
end if;
|
|
end if;
|
|
|
|
if (fifo_read_clk'event and (fifo_read_clk = '1')) then
|
|
read_side_sync_reset <= '0';
|
|
if (read_side_sync_reset = '0') then
|
|
fifo_out_sync_reg <= ram_array(rdPtr);
|
|
rdPtr := (rdPtr + 1) rem 6;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process DPA_FIFO;
|
|
|
|
end generate STRATIXIII_DPA_FIFO;
|
|
|
|
OUTPUT_REGISTER : process (rx_reg_clk)
|
|
begin
|
|
if (rx_reg_clk = '1' and rx_reg_clk'event) then
|
|
if ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON")) then
|
|
rx_out_reg <= rx_dpa_sync_reg;
|
|
else
|
|
rx_out_reg <= rx_parallel_load_reg;
|
|
end if;
|
|
end if;
|
|
end process OUTPUT_REGISTER;
|
|
|
|
DPA_SYNC_REGISTER : process (rx_dpa_sync_reg_clk)
|
|
begin
|
|
if ((rx_dpa_sync_reg_clk = '1') and rx_dpa_sync_reg_clk'event) then
|
|
rx_dpa_sync_reg <= rx_parallel_load_reg;
|
|
end if;
|
|
end process DPA_SYNC_REGISTER;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
STRATIXIII_DPA_LOCKED : process (rx_slowclk, rx_reset, rx_fifo_reset, pll_locked ,int_pll_kick_reset)
|
|
variable accum_regr_temp : unsigned(8 downto 0) := (others => '0');
|
|
variable int_accum_regr_temp : integer;
|
|
begin
|
|
if (rx_reset = '1' or pll_locked = '0' or int_pll_kick_reset = '1') then
|
|
extra_regr <= '0';
|
|
lock_out_regr <= '0';
|
|
for j in deserialization_factor-1 downto 0 loop
|
|
pad_regr(j) <= '0';
|
|
end loop;
|
|
for j in 8 downto 0 loop
|
|
accum_regr_temp(j) := '0';
|
|
end loop;
|
|
if (rx_reset = '1' or pll_locked = '0') then
|
|
lock_out_reg_dly <= '0';
|
|
end if;
|
|
elsif rising_edge(rx_slowclk) then
|
|
for j in deserialization_factor-1 downto 0 loop
|
|
if (registered_output = "ON") then
|
|
pad_regr <= rx_out_reg;
|
|
else
|
|
pad_regr <= rx_parallel_load_reg;
|
|
end if;
|
|
end loop;
|
|
extra_regr <= pad_regr(deserialization_factor-1);
|
|
in_bus_add(0) <= extra_regr xor pad_regr(0);
|
|
lock_out_reg_dly <= lock_out_regr;
|
|
for j in deserialization_factor-1 downto 1 loop
|
|
in_bus_add(j) <= pad_regr(j) xor pad_regr(j-1);
|
|
end loop;
|
|
int_accum_regr_temp := conv_integer(accum_regr_temp);
|
|
for j in deserialization_factor-1 downto 0 loop
|
|
if (in_bus_add(j) = '1') then
|
|
int_accum_regr_temp := int_accum_regr_temp + 1;
|
|
end if;
|
|
end loop;
|
|
accum_regr_temp := conv_unsigned(int_accum_regr_temp, 9);
|
|
if (accum_regr_temp >= 256) then
|
|
lock_out_regr <= '1';
|
|
end if;
|
|
end if;
|
|
|
|
if (use_dpa_calibration = true) then
|
|
if (rx_reset = '1' or pll_locked = '0') then
|
|
lock_state_mc(1 downto 0) <= (others => '0');
|
|
elsif rising_edge(rx_slowclk) then
|
|
if (wire_lock_state_mc_ena(1) = '1') then
|
|
lock_state_mc(1) <= wire_lock_state_mc_d(1);
|
|
end if;
|
|
if (wire_lock_state_mc_ena(0) = '1') then
|
|
lock_state_mc(0) <= wire_lock_state_mc_d(0);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process STRATIXIII_DPA_LOCKED;
|
|
|
|
end behavior;
|
|
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : stratixiii_lvds_rx
|
|
--
|
|
-- Description : Stratix III lvds receiver. Support both the dpa and non-dpa
|
|
-- mode.
|
|
--
|
|
-- Limitation : Only available to Stratix III.
|
|
--
|
|
-- Results Expected: Deserialized output data, dpa lock signal, forwarded clock
|
|
-- and status bit indicating whether maximum bitslip has been
|
|
-- reached.
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- LIBRARY USED----------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
use work.stratixiii_lvds_rx_channel;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity stratixiii_lvds_rx is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
number_of_channels : natural; -- Required parameter
|
|
deserialization_factor : natural; -- Required parameter
|
|
enable_dpa_mode : string := "OFF";
|
|
data_align_rollover : natural := 10;
|
|
lose_lock_on_one_change : string := "OFF";
|
|
reset_fifo_at_first_lock : string := "ON";
|
|
x_on_bitslip : string := "ON";
|
|
rx_align_data_reg : string := "RISING_EDGE";
|
|
enable_soft_cdr_mode : string := "OFF";
|
|
sim_dpa_output_clock_phase_shift : integer := 0;
|
|
sim_dpa_is_negative_ppm_drift : string := "OFF";
|
|
sim_dpa_net_ppm_variation : natural := 0;
|
|
enable_dpa_align_to_rising_edge_only : string := "OFF";
|
|
enable_dpa_initial_phase_selection : string := "OFF";
|
|
dpa_initial_phase_value : natural := 0;
|
|
registered_output : string := "ON";
|
|
enable_clock_pin_mode : string := "UNUSED";
|
|
use_dpa_calibration : boolean := false;
|
|
ARRIAII_RX_STYLE : boolean := false;
|
|
STRATIXV_RX_STYLE : boolean := false );
|
|
|
|
-- PORT DECLARATION
|
|
port(
|
|
--INPUT PORT DECLARATION
|
|
rx_in : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_fastclk : in std_logic; --Required port
|
|
rx_slowclk : in std_logic; --Required port
|
|
rx_enable : in std_logic := '1';
|
|
rx_dpaclock : in std_logic;
|
|
rx_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_hold : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_enable : in std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
|
|
rx_fifo_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_channel_data_align : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_cda_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpa_lock_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_locked : in std_logic;
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
rx_out : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
|
|
rx_dpa_locked : out std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_cda_max : out std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_divfwdclk : out std_logic_vector(number_of_channels-1 downto 0) := (others => '0') );
|
|
|
|
end stratixiii_lvds_rx;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of stratixiii_lvds_rx is
|
|
|
|
|
|
-- COMPONENT DECLARATION
|
|
|
|
-- stratixiii lvds_rx_channel
|
|
component stratixiii_lvds_rx_channel
|
|
generic (
|
|
deserialization_factor : natural; -- Required parameter
|
|
enable_dpa_mode : string := "OFF";
|
|
data_align_rollover : natural := 10;
|
|
lose_lock_on_one_change : string := "OFF";
|
|
reset_fifo_at_first_lock : string := "ON";
|
|
x_on_bitslip : string := "ON";
|
|
rx_align_data_reg : string := "RISING_EDGE";
|
|
enable_soft_cdr_mode : string := "OFF";
|
|
sim_dpa_output_clock_phase_shift : integer := 0;
|
|
sim_dpa_is_negative_ppm_drift : string := "OFF";
|
|
sim_dpa_net_ppm_variation : natural := 0;
|
|
enable_dpa_align_to_rising_edge_only : string := "OFF";
|
|
enable_dpa_initial_phase_selection : string := "OFF";
|
|
dpa_initial_phase_value : natural := 0;
|
|
registered_output : string := "ON";
|
|
enable_clock_pin_mode : string := "UNUSED";
|
|
use_dpa_calibration : boolean := false;
|
|
ARRIAII_RX_STYLE : boolean := false;
|
|
STRATIXV_RX_STYLE : boolean := false );
|
|
|
|
port (
|
|
rx_in : in std_logic; --Required port
|
|
rx_fastclk : in std_logic; --Required port
|
|
rx_slowclk : in std_logic; --Required port
|
|
rx_enable : in std_logic := '1';
|
|
rx_dpaclock : in std_logic;
|
|
rx_reset : in std_logic;
|
|
rx_dpll_reset : in std_logic;
|
|
rx_dpll_hold : in std_logic;
|
|
rx_dpll_enable : in std_logic;
|
|
rx_fifo_reset : in std_logic;
|
|
rx_channel_data_align : in std_logic;
|
|
rx_cda_reset : in std_logic;
|
|
rx_dpa_lock_reset : in std_logic;
|
|
rx_locked : in std_logic;
|
|
rx_out : out std_logic_vector(deserialization_factor-1 downto 0);
|
|
rx_dpa_locked : out std_logic;
|
|
rx_cda_max : out std_logic;
|
|
rx_divfwdclk : out std_logic );
|
|
end component; -- stratixiii_lvds_rx_channel
|
|
|
|
begin
|
|
|
|
|
|
-- COMPONENT ASSIGNMENTS
|
|
|
|
STRATIXIII_RX_CHANNEL :
|
|
for i in 0 to number_of_channels-1 generate
|
|
|
|
LVDS_CHANNEL: stratixiii_lvds_rx_channel
|
|
generic map (
|
|
deserialization_factor => deserialization_factor,
|
|
enable_dpa_mode => enable_dpa_mode,
|
|
data_align_rollover => data_align_rollover,
|
|
lose_lock_on_one_change => lose_lock_on_one_change,
|
|
reset_fifo_at_first_lock => reset_fifo_at_first_lock,
|
|
x_on_bitslip => x_on_bitslip,
|
|
rx_align_data_reg => rx_align_data_reg,
|
|
enable_soft_cdr_mode => enable_soft_cdr_mode,
|
|
sim_dpa_output_clock_phase_shift => sim_dpa_output_clock_phase_shift,
|
|
sim_dpa_is_negative_ppm_drift => sim_dpa_is_negative_ppm_drift,
|
|
sim_dpa_net_ppm_variation => sim_dpa_net_ppm_variation,
|
|
enable_dpa_align_to_rising_edge_only => enable_dpa_align_to_rising_edge_only,
|
|
enable_dpa_initial_phase_selection => enable_dpa_initial_phase_selection,
|
|
dpa_initial_phase_value => dpa_initial_phase_value,
|
|
registered_output => registered_output,
|
|
enable_clock_pin_mode => enable_clock_pin_mode,
|
|
use_dpa_calibration => use_dpa_calibration,
|
|
ARRIAII_RX_STYLE => ARRIAII_RX_STYLE,
|
|
STRATIXV_RX_STYLE => STRATIXV_RX_STYLE )
|
|
|
|
port map (
|
|
rx_in => rx_in(i),
|
|
rx_fastclk => rx_fastclk,
|
|
rx_slowclk => rx_slowclk,
|
|
rx_enable => rx_enable,
|
|
rx_dpaclock => rx_dpaclock,
|
|
rx_reset => rx_reset(i),
|
|
rx_dpll_reset => rx_dpll_reset(i),
|
|
rx_dpll_hold => rx_dpll_hold(i),
|
|
rx_dpll_enable => rx_dpll_enable(i),
|
|
rx_fifo_reset => rx_fifo_reset(i),
|
|
rx_channel_data_align => rx_channel_data_align(i),
|
|
rx_cda_reset => rx_cda_reset(i),
|
|
rx_out => rx_out((i+1)*deserialization_factor-1 downto i*deserialization_factor),
|
|
rx_dpa_locked => rx_dpa_locked(i),
|
|
rx_cda_max => rx_cda_max(i),
|
|
rx_dpa_lock_reset => rx_dpa_lock_reset(i),
|
|
rx_locked => rx_locked,
|
|
rx_divfwdclk => rx_divfwdclk(i) );
|
|
end generate STRATIXIII_RX_CHANNEL;
|
|
|
|
end behavior;
|
|
|
|
-- END OF ARCHITECTURE
|
|
|
|
|
|
-- START ENTITY HEADER ---------------------------------------------------------
|
|
--
|
|
-- Entity Name : altlvds_rx
|
|
--
|
|
-- Description : Low Voltage Differential Signaling (LVDS) receiver
|
|
-- megafunction. The altlvds_rx megafunction implements a
|
|
-- deserialization receiver. LVDS is a high speed IO interface
|
|
-- that uses inputs without a reference voltage. LVDS uses
|
|
-- two wires carrying differential values to create a single
|
|
-- channel. These wires are connected to two pins on
|
|
-- supported device to create a single LVDS channel
|
|
--
|
|
-- Limitations : Only available for STRATIX,
|
|
-- STRATIX GX, Stratix II, Cyclone and Cyclone II families.
|
|
--
|
|
--Results expected : output clock, deserialized output data and pll locked
|
|
-- signal.
|
|
--
|
|
-- END ENTITY HEADER -----------------------------------------------------------
|
|
|
|
|
|
-- LIBRARY USED-----------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
use work.MF_stratix_pll;
|
|
use work.MF_stratixii_pll;
|
|
use work.MF_stratixiii_pll;
|
|
use work.stratixii_lvds_rx;
|
|
use work.flexible_lvds_rx;
|
|
use work.stratixiii_lvds_rx;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altlvds_rx is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
number_of_channels : natural; -- Required parameter
|
|
deserialization_factor : natural; -- Required parameter
|
|
registered_output : string := "ON";
|
|
inclock_period : natural := 10000; -- Required parameter
|
|
inclock_boost : natural := 0;
|
|
cds_mode : string := "UNUSED";
|
|
intended_device_family : string := "Stratix";
|
|
input_data_rate : natural := 0;
|
|
inclock_data_alignment : string := "UNUSED";
|
|
registered_data_align_input : string := "ON";
|
|
common_rx_tx_pll : string := "ON";
|
|
enable_dpa_mode : string := "OFF";
|
|
enable_dpa_pll_calibration : string := "OFF";
|
|
enable_dpa_calibration : string := "ON";
|
|
enable_dpa_fifo : string := "ON";
|
|
use_dpll_rawperror : string := "OFF";
|
|
use_coreclock_input : string := "OFF";
|
|
dpll_lock_count : natural := 0;
|
|
dpll_lock_window : natural := 0;
|
|
outclock_resource : string := "AUTO";
|
|
data_align_rollover : natural := 10;
|
|
lose_lock_on_one_change : string := "OFF";
|
|
reset_fifo_at_first_lock : string := "ON";
|
|
use_external_pll : string := "OFF";
|
|
implement_in_les : string := "OFF";
|
|
buffer_implementation : string := "RAM";
|
|
port_rx_data_align : string := "PORT_CONNECTIVITY";
|
|
port_rx_channel_data_align : string := "PORT_CONNECTIVITY";
|
|
pll_operation_mode : string := "NORMAL";
|
|
x_on_bitslip : string := "ON";
|
|
use_no_phase_shift : string := "ON";
|
|
rx_align_data_reg : string := "RISING_EDGE";
|
|
inclock_phase_shift : integer := 0;
|
|
enable_soft_cdr_mode : string := "OFF";
|
|
sim_dpa_output_clock_phase_shift : integer := 0;
|
|
sim_dpa_is_negative_ppm_drift : string := "OFF";
|
|
sim_dpa_net_ppm_variation : natural := 0;
|
|
enable_dpa_align_to_rising_edge_only : string := "OFF";
|
|
enable_dpa_initial_phase_selection : string := "OFF";
|
|
dpa_initial_phase_value :natural := 0;
|
|
pll_self_reset_on_loss_lock : string := "OFF";
|
|
refclk_frequency : string := "UNUSED";
|
|
enable_clock_pin_mode : string := "UNUSED";
|
|
data_rate : string := "UNUSED";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altlvds_rx";
|
|
-- Specifies whether the source of the input clock is from the PLL
|
|
clk_src_is_pll : string := "off" );
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
--INPUT PORT DECLARATION
|
|
rx_in : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_inclock : in std_logic := '0';
|
|
rx_syncclock : in std_logic := '0';
|
|
rx_dpaclock : in std_logic := '0';
|
|
rx_readclock : in std_logic := '0';
|
|
rx_enable : in std_logic := '0';
|
|
rx_deskew : in std_logic := '0';
|
|
rx_pll_enable : in std_logic := '1';
|
|
rx_data_align : in std_logic := 'Z';
|
|
rx_data_align_reset : in std_logic := '0';
|
|
rx_reset : in std_logic_vector(number_of_channels-1 downto 0):= (others => '0');
|
|
rx_dpll_reset : in std_logic_vector(number_of_channels-1 downto 0):= (others => '0');
|
|
rx_dpll_hold : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_enable : in std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
|
|
rx_fifo_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_channel_data_align : in std_logic_vector(number_of_channels-1 downto 0) := (others => 'Z');
|
|
rx_cda_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_coreclk : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
pll_areset : in std_logic := '0';
|
|
rx_data_reset : in std_logic := '0';
|
|
dpa_pll_recal : in std_logic := '0';
|
|
pll_phasedone : in std_logic := '1';
|
|
rx_dpa_lock_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
rx_out : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
|
|
rx_outclock : out std_logic;
|
|
rx_locked : out std_logic;
|
|
rx_dpa_locked : out std_logic_vector(number_of_channels-1 downto 0);
|
|
rx_cda_max : out std_logic_vector(number_of_channels-1 downto 0);
|
|
rx_divfwdclk : out std_logic_vector(number_of_channels-1 downto 0);
|
|
dpa_pll_cal_busy : out std_logic;
|
|
pll_phasestep : out std_logic;
|
|
pll_phaseupdown : out std_logic;
|
|
pll_phasecounterselect: out std_logic_Vector(3 downto 0);
|
|
pll_scanclk : out std_logic);
|
|
|
|
end altlvds_rx;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of altlvds_rx is
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant STRATIX_RX_STYLE : boolean := (FEATURE_FAMILY_STRATIX_NONGX(intended_device_family) or
|
|
(FEATURE_FAMILY_STRATIXGX(intended_device_family) and
|
|
(enable_dpa_mode = "OFF")));
|
|
constant STRATIXGX_DPA_RX_STYLE : boolean := (FEATURE_FAMILY_STRATIXGX(intended_device_family) and
|
|
(enable_dpa_mode = "ON"));
|
|
constant STRATIXII_RX_STYLE : boolean := FEATURE_FAMILY_BASE_STRATIXII(intended_device_family);
|
|
constant STRATIXIII_RX_STYLE : boolean := FEATURE_FAMILY_BASE_STRATIXIII(intended_device_family);
|
|
constant CYCLONE_RX_STYLE : boolean := FEATURE_FAMILY_BASE_CYCLONE(intended_device_family);
|
|
constant CYCLONEII_RX_STYLE : boolean := FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family);
|
|
constant CYCLONEIII_RX_STYLE : boolean := FEATURE_FAMILY_BASE_CYCLONEIII(intended_device_family);
|
|
constant ARRIAII_RX_STYLE : boolean := FEATURE_FAMILY_ARRIAIIGX(intended_device_family);
|
|
constant STRATIXV_RX_STYLE : boolean := FEATURE_FAMILY_STRATIXV(intended_device_family);
|
|
constant FAMILY_HAS_FLEXIBLE_LVDS : boolean := FEATURE_FAMILY_HAS_FLEXIBLE_LVDS(intended_device_family) or
|
|
(((STRATIX_RX_STYLE = true) or (STRATIXII_RX_STYLE = true) or
|
|
(STRATIXIII_RX_STYLE = true)) and
|
|
(implement_in_les = "ON"));
|
|
constant FAMILY_HAS_STRATIX_STYLE_PLL : boolean := FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL(intended_device_family);
|
|
constant FAMILY_HAS_STRATIXII_STYLE_PLL : boolean := FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL(intended_device_family);
|
|
constant FAMILY_HAS_STRATIXIII_STYLE_PLL : boolean := FEATURE_FAMILY_USES_STRATIXIII_PLL(intended_device_family);
|
|
constant VSERIES_FAMILY : boolean := (FEATURE_FAMILY_STRATIXV(intended_device_family) or FEATURE_FAMILY_ARRIAV(intended_device_family));
|
|
|
|
-- FUNCTION DECLARATION
|
|
|
|
--- Convert integer to string ---
|
|
function int_to_str( constant value : integer ) return string is
|
|
variable ivalue : integer := 0;
|
|
variable index : integer := 0;
|
|
variable strlen : integer := 0;
|
|
variable digit : integer := 0;
|
|
variable temp : string(1 to 8) := "00000000";
|
|
|
|
begin
|
|
ivalue := abs(value);
|
|
strlen := 0;
|
|
|
|
|
|
while (ivalue > 0) loop
|
|
ivalue := ivalue/10;
|
|
strlen := strlen + 1;
|
|
end loop;
|
|
|
|
if (strlen = 0) then
|
|
strlen := 1;
|
|
end if;
|
|
|
|
ivalue := abs(value);
|
|
index := strlen;
|
|
|
|
while (ivalue > 0) loop
|
|
digit := ivalue mod 10;
|
|
ivalue := ivalue/10;
|
|
|
|
case digit is
|
|
when 0 => temp(index) := '0';
|
|
when 1 => temp(index) := '1';
|
|
when 2 => temp(index) := '2';
|
|
when 3 => temp(index) := '3';
|
|
when 4 => temp(index) := '4';
|
|
when 5 => temp(index) := '5';
|
|
when 6 => temp(index) := '6';
|
|
when 7 => temp(index) := '7';
|
|
when 8 => temp(index) := '8';
|
|
when 9 => temp(index) := '9';
|
|
when others => ASSERT FALSE
|
|
REPORT "Illegal number!"
|
|
SEVERITY ERROR;
|
|
end case;
|
|
|
|
index := index - 1;
|
|
|
|
end loop;
|
|
|
|
if (value < 0) then
|
|
return ('-' & temp(1 to strlen));
|
|
else
|
|
return temp(1 to strlen);
|
|
end if;
|
|
end int_to_str;
|
|
|
|
-- M value for stratix/stratix II/Cyclone/Cyclone II PLL
|
|
function pll_m_value(constant i_input_data_rate,
|
|
i_inclock_period : in natural) return natural is
|
|
variable i_pll_m_value : natural;
|
|
begin
|
|
i_pll_m_value := (((i_input_data_rate * i_inclock_period)
|
|
+ (5* 100000)) / 1000000);
|
|
|
|
return i_pll_m_value;
|
|
|
|
end pll_m_value;
|
|
|
|
-- D value for Stratix/Stratix II/Cyclone/Cyclone II PLL
|
|
function pll_d_value(constant i_input_data_rate,
|
|
i_inclock_period : in natural) return natural is
|
|
variable i_pll_d_value : natural;
|
|
begin
|
|
if ((i_input_data_rate /= 0) and (i_inclock_period /= 0)) then
|
|
if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
i_pll_d_value := 2;
|
|
else
|
|
i_pll_d_value := 1;
|
|
end if;
|
|
else
|
|
i_pll_d_value := 1;
|
|
end if;
|
|
|
|
return i_pll_d_value;
|
|
end pll_d_value;
|
|
|
|
--- calculate clock boost value need by the pll ---
|
|
function clock_boost_calc (constant i_input_data_rate,
|
|
i_inclock_period,
|
|
i_deserialization_factor,
|
|
i_inclock_boost : in natural) return natural is
|
|
variable i_input_clock_boost : natural;
|
|
|
|
begin
|
|
if ((i_input_data_rate /= 0) and (i_inclock_period /= 0)) then
|
|
i_input_clock_boost := pll_m_value (i_input_data_rate,
|
|
i_inclock_period);
|
|
else
|
|
if (inclock_boost = 0) then
|
|
i_input_clock_boost := i_deserialization_factor;
|
|
else
|
|
i_input_clock_boost := i_inclock_boost;
|
|
end if;
|
|
end if;
|
|
|
|
return i_input_clock_boost;
|
|
|
|
end clock_boost_calc;
|
|
|
|
|
|
--- get phase delay in ps for stratix pll ---
|
|
function get_phase_delay (constant i_phase_delay : in string) return integer is
|
|
variable my_phase : integer := 0;
|
|
variable x, int_delay : integer := 0;
|
|
|
|
begin
|
|
|
|
-- get delay in ps (<alignment degree> * inclock period / 360 degress )
|
|
if ((i_phase_delay = "UNUSED") or (VSERIES_FAMILY = true)) then
|
|
int_delay := inclock_phase_shift;
|
|
else
|
|
if (i_phase_delay = "EDGE_ALIGNED") then
|
|
my_phase := 0;
|
|
elsif (i_phase_delay = "CENTER_ALIGNED") then -- CENTER_ALIGNED means 180 degrees
|
|
my_phase := (180 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "45_DEGREES") then
|
|
my_phase := (45 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "90_DEGREES") then
|
|
my_phase := (90 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "135_DEGREES") then
|
|
my_phase := (135 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "180_DEGREES") then
|
|
my_phase := (180 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "225_DEGREES") then
|
|
my_phase := (225 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "270_DEGREES") then
|
|
my_phase := (270 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "315_DEGREES") then
|
|
my_phase := (315 * inclock_period) / 360;
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "Invalid clock data alignment. Using 'EDGE_ALIGNED' instead"
|
|
SEVERITY WARNING;
|
|
my_phase :=0;
|
|
end if;
|
|
|
|
-- Add 1 to "round up" calculation result
|
|
my_phase := my_phase + 1;
|
|
|
|
-- phase shift in ps = ( <alignment degree> * inclock_period / 360 ) / fast clock multiply_by factor
|
|
-- in other words, the phase shift is a percentage of the fast clock period
|
|
int_delay := my_phase / clock_boost_calc(input_data_rate, inclock_period, deserialization_factor, inclock_boost);
|
|
|
|
-- Add 1 to "round up" calculation result
|
|
int_delay := int_delay + 1;
|
|
end if;
|
|
|
|
return int_delay;
|
|
|
|
end get_phase_delay;
|
|
|
|
|
|
--- get phase delay in ps for stratix ii pll ---
|
|
function get_stxii_phase_delay (constant i_phase_delay : in string) return integer is
|
|
variable my_phase : integer := 0;
|
|
begin
|
|
|
|
my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (2 * clock_boost_calc(input_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
|
|
return my_phase;
|
|
|
|
end get_stxii_phase_delay;
|
|
|
|
--- get clk1_multiply_by value for PLL (for flexible lvds)
|
|
function get_flvds_clk1_multiply_by ( constant i_deserialization_factor : in natural) return natural is
|
|
variable clk1_mult_by : natural := 0;
|
|
begin
|
|
if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
if ((i_deserialization_factor rem 2) = 1) then
|
|
clk1_mult_by := clock_boost_calc(input_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost);
|
|
else
|
|
clk1_mult_by := 1;
|
|
end if;
|
|
end if;
|
|
|
|
return clk1_mult_by;
|
|
|
|
end get_flvds_clk1_multiply_by;
|
|
|
|
--- get clk1_divide_by value for PLL (for flexible lvds)
|
|
function get_flvds_clk1_divide_by ( constant i_deserialization_factor : in natural) return natural is
|
|
variable clk1_div_by : natural := 0;
|
|
begin
|
|
if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
if ((i_deserialization_factor rem 2) = 1) then
|
|
clk1_div_by := i_deserialization_factor;
|
|
clk1_div_by := clk1_div_by * pll_d_value(input_data_rate,
|
|
inclock_period);
|
|
else
|
|
clk1_div_by := 1;
|
|
end if;
|
|
end if;
|
|
|
|
return clk1_div_by;
|
|
|
|
end get_flvds_clk1_divide_by;
|
|
|
|
--- get clk1_phase_shift value for PLL (for flexible lvds)
|
|
function get_flvds_clk1_phase_shift ( constant i_deserialization_factor : in natural;
|
|
constant i_phase_shift : in string) return string is
|
|
begin
|
|
if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
if ((i_deserialization_factor rem 2) = 1) then
|
|
return i_phase_shift;
|
|
else
|
|
return "0";
|
|
end if;
|
|
else
|
|
return "0";
|
|
end if;
|
|
end get_flvds_clk1_phase_shift;
|
|
|
|
--- get clk2_multiply_by value for PLL (for flexible lvds)
|
|
function get_flvds_clk2_multiply_by ( constant i_deserialization_factor : in natural) return natural is
|
|
variable clk2_mult_by : natural := 0;
|
|
begin
|
|
if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
if ((i_deserialization_factor rem 2) = 1) then
|
|
clk2_mult_by := clock_boost_calc(input_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost) * 2;
|
|
else
|
|
clk2_mult_by := clock_boost_calc(input_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost);
|
|
end if;
|
|
end if;
|
|
|
|
return clk2_mult_by;
|
|
|
|
end get_flvds_clk2_multiply_by;
|
|
|
|
--- get clk2_divide_by value for PLL (for flexible lvds)
|
|
function get_flvds_clk2_divide_by ( constant i_deserialization_factor : in natural) return natural is
|
|
variable clk2_div_by : natural := 0;
|
|
begin
|
|
if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
if ((i_deserialization_factor rem 2) = 0) then
|
|
clk2_div_by := i_deserialization_factor / 2;
|
|
else
|
|
clk2_div_by := i_deserialization_factor;
|
|
end if;
|
|
end if;
|
|
|
|
clk2_div_by := clk2_div_by * pll_d_value(input_data_rate,
|
|
inclock_period);
|
|
return clk2_div_by;
|
|
|
|
end get_flvds_clk2_divide_by;
|
|
|
|
--- get pll_type for PLL (for flexible lvds)
|
|
function get_flvds_pll_type ( constant i_inclock_alignment : in string) return string is
|
|
begin
|
|
if (i_inclock_alignment = "UNUSED") then
|
|
return "auto";
|
|
else
|
|
return "flvds";
|
|
end if;
|
|
|
|
end get_flvds_pll_type;
|
|
|
|
--- get phase delay in ps for cyclone ii and stratix II in LE mode ---
|
|
function get_stxii_le_phase_delay (constant i_phase_delay : in string) return integer is
|
|
variable my_phase : integer := 0;
|
|
begin
|
|
if ((use_no_phase_shift = "OFF") and (pll_operation_mode = "SOURCE_SYNCHRONOUS")) then
|
|
my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(input_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
else
|
|
my_phase := get_phase_delay(i_phase_delay);
|
|
end if;
|
|
|
|
return my_phase;
|
|
|
|
end get_stxii_le_phase_delay;
|
|
|
|
--- get clk1_phase_shift value for PLL (for flexible lvds)
|
|
function get_stxii_le_clk1_phase_shift ( constant i_deserialization_factor : in natural;
|
|
constant i_phase_shift : in string) return string is
|
|
begin
|
|
if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
if ((i_deserialization_factor rem 2) = 1) then
|
|
return i_phase_shift;
|
|
else
|
|
return "0";
|
|
end if;
|
|
else
|
|
return "0";
|
|
end if;
|
|
end get_stxii_le_clk1_phase_shift;
|
|
|
|
--- get phase delay in ps for stratix III in LE mode ---
|
|
function get_stxiii_le_phase_delay (constant i_phase_delay : in string) return integer is
|
|
variable my_phase : integer := 0;
|
|
begin
|
|
my_phase := get_phase_delay(i_phase_delay) - (inclock_period * pll_d_value(input_data_rate,inclock_period)/
|
|
(4 * clock_boost_calc(input_data_rate,inclock_period, deserialization_factor, inclock_boost)));
|
|
return my_phase;
|
|
|
|
end get_stxiii_le_phase_delay;
|
|
|
|
--- get phase_shift value for the clock that acts as enable signal (for StratixIII lvds)
|
|
function get_clk_ena_phase_shift ( constant i_phase_shift : in string) return string is
|
|
variable fast_clk_ena_phase_shift : integer := 0;
|
|
begin
|
|
|
|
fast_clk_ena_phase_shift := (deserialization_factor*2-3) * (inclock_period/(2*clock_boost_calc(input_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
|
|
return int_to_str(get_stxii_phase_delay(i_phase_shift) + fast_clk_ena_phase_shift);
|
|
|
|
end get_clk_ena_phase_shift;
|
|
|
|
-- converts uppercase parameter values (e.g. "AUTO") to lowercase ("auto")
|
|
-- as expected by stratix_pll model
|
|
function alpha_tolower (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
|
|
begin
|
|
for i in 1 to string_length loop
|
|
case given_string(i) is
|
|
when 'A' => result_string(i) := 'a';
|
|
when 'B' => result_string(i) := 'b';
|
|
when 'C' => result_string(i) := 'c';
|
|
when 'D' => result_string(i) := 'd';
|
|
when 'E' => result_string(i) := 'e';
|
|
when 'F' => result_string(i) := 'f';
|
|
when 'G' => result_string(i) := 'g';
|
|
when 'H' => result_string(i) := 'h';
|
|
when 'I' => result_string(i) := 'i';
|
|
when 'J' => result_string(i) := 'j';
|
|
when 'K' => result_string(i) := 'k';
|
|
when 'L' => result_string(i) := 'l';
|
|
when 'M' => result_string(i) := 'm';
|
|
when 'N' => result_string(i) := 'n';
|
|
when 'O' => result_string(i) := 'o';
|
|
when 'P' => result_string(i) := 'p';
|
|
when 'Q' => result_string(i) := 'q';
|
|
when 'R' => result_string(i) := 'r';
|
|
when 'S' => result_string(i) := 's';
|
|
when 'T' => result_string(i) := 't';
|
|
when 'U' => result_string(i) := 'u';
|
|
when 'V' => result_string(i) := 'v';
|
|
when 'W' => result_string(i) := 'w';
|
|
when 'X' => result_string(i) := 'x';
|
|
when 'Y' => result_string(i) := 'y';
|
|
when 'Z' => result_string(i) := 'z';
|
|
when others => result_string(i) := given_string(i);
|
|
end case;
|
|
end loop;
|
|
|
|
return (result_string(1 to string_length));
|
|
end;
|
|
|
|
-- CONSTANT DECLARATION
|
|
-- these constants are PLL parameters calculated from the altlvds_rx parameters given
|
|
constant PHASE_INCLOCK : string := int_to_str(get_phase_delay(inclock_data_alignment));
|
|
constant STXII_PHASE_INCLOCK : string := int_to_str(get_stxii_phase_delay(inclock_data_alignment));
|
|
constant INT_CLOCK_BOOST : natural := clock_boost_calc(input_data_rate, inclock_period, deserialization_factor, inclock_boost);
|
|
constant REGISTER_WIDTH : natural := deserialization_factor * number_of_channels;
|
|
constant FLVDS_CLK0_DIV : natural := pll_d_value(input_data_rate, inclock_period);
|
|
constant FLVDS_CLK1_MULT : natural := get_flvds_clk1_multiply_by(deserialization_factor);
|
|
constant FLVDS_CLK1_DIV : natural := get_flvds_clk1_divide_by(deserialization_factor);
|
|
constant FLVDS_CLK2_MULT : natural := get_flvds_clk2_multiply_by(deserialization_factor);
|
|
constant FLVDS_CLK2_DIV : natural := get_flvds_clk2_divide_by(deserialization_factor);
|
|
constant FLVDS_CLK1_PHASE_SHIFT : string := get_flvds_clk1_phase_shift(deserialization_factor, PHASE_INCLOCK);
|
|
constant FLVDS_PLL_TYPE : string := get_flvds_pll_type(inclock_data_alignment);
|
|
constant STXII_LE_PHASE_INCLOCK : string := int_to_str(get_stxii_le_phase_delay(inclock_data_alignment));
|
|
constant STXII_LE_CLK1_PHASE_SHIFT : string := get_stxii_le_clk1_phase_shift(deserialization_factor, STXII_LE_PHASE_INCLOCK);
|
|
constant STXIII_LE_PHASE_INCLOCK : string := int_to_str(get_stxiii_le_phase_delay(inclock_data_alignment));
|
|
constant STXIII_LE_CLK1_PHASE_SHIFT : string := get_stxii_le_clk1_phase_shift(deserialization_factor, STXIII_LE_PHASE_INCLOCK);
|
|
constant IS_USING_EXTRA_DDIO_REG : boolean := (CYCLONE_RX_STYLE = true) or (CYCLONEII_RX_STYLE = true) or (CYCLONEIII_RX_STYLE = true);
|
|
constant IS_USING_EXTRA_PLL_CLK : boolean := (CYCLONE_RX_STYLE = false) and (CYCLONEII_RX_STYLE = false);
|
|
constant IS_ADDING_EXTRA_LATENCY : boolean := (CYCLONE_RX_STYLE = true) or (CYCLONEII_RX_STYLE = true) or (CYCLONEIII_RX_STYLE = true);
|
|
constant CLK_ENA_PHASE_SHIFT : string := get_clk_ena_phase_shift(inclock_data_alignment);
|
|
constant use_dpa_calibration : boolean := ((ARRIAII_RX_STYLE = true) and (enable_dpa_calibration = "ON"));
|
|
|
|
-- TYPE DECLARATION
|
|
type CHANNEL_CNT is array (number_of_channels-1 downto 0) of integer;
|
|
type DPA_FIFO_RAM is array (3 downto 0) of std_logic_vector(REGISTER_WIDTH -1 downto 0);
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal rxpdat1 : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal rxpdat2 : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal rxpdat3 : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal rxpdatout : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal rx_out_reg : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal rx_out_rgd : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal rx_out_rgd2 : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal rx_out_extra_yeager_reg : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal rx_out_int : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal data_out : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal serdes_data_out : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal write_data : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal read_data : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal rx_ddio_in : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal stratixii_dataout : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal stratixiii_dataout : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
signal flvds_dataout : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
|
|
-- to store previous port values
|
|
signal rx_coreclk_pre : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal rx_channel_data_align_wire : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal rx_channel_data_align_pre : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
signal pclk_pre : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
|
|
-- constant signals
|
|
signal temp_high : std_logic_vector (5 downto 0):= (others => '1');
|
|
signal temp_z : std_logic_vector (number_of_channels-1 downto 0):= (others => 'Z');
|
|
|
|
-- FIFO ram for Stratix GX
|
|
signal ram_array : DPA_FIFO_RAM := (others => (others => '0'));
|
|
|
|
-- PLL ports
|
|
signal rx_clock0_int : std_logic := '0'; -- fast clock
|
|
signal rx_clock1_int : std_logic := '0'; -- slow clock
|
|
signal rx_pll_clk0 : std_logic := '0';
|
|
signal rx_pll_clk1 : std_logic := '0';
|
|
signal rx_reg_clk : std_logic := '0';
|
|
signal yeager_locked_int : std_logic := '0';
|
|
signal aurora_locked_int : std_logic := '0';
|
|
signal stratixii_locked_int : std_logic := '0';
|
|
signal stratixiii_locked_int : std_logic := '0';
|
|
signal cyclone_locked_int : std_logic := '0';
|
|
signal cycloneii_locked_int : std_logic := '0';
|
|
signal rx_locked_int : std_logic := '0';
|
|
signal temp_zero : std_logic := '0';
|
|
|
|
-- Stratix, Stratix II, Stratix GX, Cyclone and Cyclone II specific signals
|
|
signal rx_data_align_reg : std_logic := '0';
|
|
signal rx_data_align_int : std_logic := '0';
|
|
signal rx_data_align_wire : std_logic := '0';
|
|
signal rx_data_align_clk : std_logic := '0';
|
|
signal enable0_reg : std_logic;
|
|
signal enable0_pipe : std_logic;
|
|
signal enable0_neg : std_logic;
|
|
signal enable1_reg : std_logic;
|
|
signal sampling : std_logic := '0';
|
|
signal yeager_clock : std_logic_vector (5 downto 0) := (others => '0');
|
|
signal aurora_clock : std_logic_vector (5 downto 0) := (others => '0');
|
|
signal stratixii_clock : std_logic_vector (5 downto 0) := (others => '0');
|
|
signal stratixiii_clock : std_logic_vector (9 downto 0) := (others => '0');
|
|
signal cyclone_clock : std_logic_vector (5 downto 0) := (others => '0');
|
|
signal cycloneii_clock : std_logic_vector (5 downto 0) := (others => '0');
|
|
signal pclk : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
|
|
signal clkout_tmp : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
|
|
signal sync_reset : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
|
|
signal stratixii_dpa_locked : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
|
|
signal stratixiii_dpa_locked : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
|
|
signal stratixii_cda_max : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
|
|
signal stratixiii_cda_max : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
|
|
signal stratixiii_divfwdclk : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
|
|
signal rx_pll_sclkout0 : std_logic := '0';
|
|
signal rx_pll_sclkout1 : std_logic := '0';
|
|
signal stratixii_sclkout0 : std_logic := '0';
|
|
signal stratixii_fastclk : std_logic := '0';
|
|
signal stratixii_enable : std_logic := '0';
|
|
signal stratixiii_fastclk : std_logic := '0';
|
|
signal stratixiii_slowclk : std_logic := '0';
|
|
signal stratixiii_enable : std_logic := '0';
|
|
signal rx_pll_enable0 : std_logic := '0';
|
|
signal rx_pll_enable1 : std_logic := '0';
|
|
signal rx_pll_sclkout0_dly : std_logic := '0';
|
|
signal flvds_fastclk : std_logic := '0';
|
|
signal flvds_slowclk : std_logic := '0';
|
|
signal flvds_syncclk : std_logic := '0';
|
|
signal flvds_rx_data_align : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
|
|
signal flvds_rx_cda_reset : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
|
|
signal pll_lock_sync : std_logic := '1';
|
|
|
|
|
|
-- COMPONENT DECLARATION
|
|
|
|
-- pll definition
|
|
component MF_stratix_pll
|
|
generic (
|
|
pll_type : string := "lvds";
|
|
inclk0_input_frequency : positive ;
|
|
inclk1_input_frequency : positive ;
|
|
valid_lock_multiplier : integer := 1;
|
|
simulation_type : string := "functional";
|
|
clk0_multiply_by : positive := 1;
|
|
clk0_divide_by : positive := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk1_multiply_by : positive := 1;
|
|
clk1_divide_by : positive := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk2_multiply_by : positive := 1;
|
|
clk2_divide_by : positive := 1;
|
|
clk2_phase_shift : string := "0";
|
|
enable0_counter : string := "l0";
|
|
enable1_counter : string := "l1";
|
|
family_name : string := "Stratix";
|
|
m : integer := 0 );
|
|
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (others => '0');
|
|
fbin : in std_logic := '1';
|
|
ena : in std_logic := '1';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
clkena : in std_logic_vector(5 downto 0) := (others => '1');
|
|
extclkena : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
|
|
scanaclr : in std_logic := '0';
|
|
scandata : in std_logic := '0';
|
|
scanclk : in std_logic := '0';
|
|
comparator : in std_logic := '0';
|
|
clk : out std_logic_vector(5 downto 0);
|
|
locked : out std_logic;
|
|
enable0 : out std_logic;
|
|
enable1 : out std_logic );
|
|
end component; -- MF_stratix_pll
|
|
|
|
component MF_stratixii_pll
|
|
generic (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "lvds";
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
inclk0_input_frequency : positive ;
|
|
inclk1_input_frequency : positive ;
|
|
simulation_type : string := "functional";
|
|
clk0_multiply_by : positive := 1;
|
|
clk0_divide_by : positive := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk1_multiply_by : positive := 1;
|
|
clk1_divide_by : positive := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk2_multiply_by : positive := 1;
|
|
clk2_divide_by : positive := 1;
|
|
clk2_phase_shift : string := "0";
|
|
sclkout0_phase_shift : string := "0";
|
|
enable0_counter : string := "c0";
|
|
enable1_counter : string := "c1";
|
|
family_name : string := "Stratix II";
|
|
m : integer := 0 );
|
|
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (others => '0');
|
|
fbin : in std_logic := '1';
|
|
ena : in std_logic := '1';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scanread : in std_logic := '0';
|
|
scanwrite : in std_logic := '0';
|
|
scandata : in std_logic := '0';
|
|
scanclk : in std_logic := '0';
|
|
testin : in std_logic_vector(3 downto 0) := (OTHERS=>'0');
|
|
clk : out std_logic_vector(5 downto 0);
|
|
locked : out std_logic;
|
|
enable0 : out std_logic;
|
|
enable1 : out std_logic;
|
|
sclkout : out std_logic_vector(1 downto 0) );
|
|
end component; -- MF_stratixii_pll
|
|
|
|
component MF_stratixiii_pll
|
|
generic (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "lvds";
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
inclk0_input_frequency : positive ;
|
|
inclk1_input_frequency : positive ;
|
|
simulation_type : string := "functional";
|
|
clk0_multiply_by : positive := 1;
|
|
clk0_divide_by : positive := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk1_multiply_by : positive := 1;
|
|
clk1_divide_by : positive := 1;
|
|
clk1_duty_cycle : integer := 50;
|
|
clk1_phase_shift : string := "0";
|
|
clk2_multiply_by : positive := 1;
|
|
clk2_divide_by : positive := 1;
|
|
clk2_phase_shift : string := "0";
|
|
family_name : string := "Stratix III";
|
|
self_reset_on_loss_lock : string := "OFF";
|
|
m : integer := 0 );
|
|
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (others => '0');
|
|
fbin : in std_logic := '1';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scanclk : in std_logic := '1';
|
|
scandata : in std_logic := '1';
|
|
scanclkena : in std_logic := '1';
|
|
configupdate : in std_logic := '0';
|
|
phasecounterselect : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
|
|
phaseupdown : in std_logic := '1';
|
|
phasestep : in std_logic := '1';
|
|
clk : out std_logic_vector(9 downto 0);
|
|
locked : out std_logic );
|
|
end component; -- MF_stratixiii_pll
|
|
|
|
component stratixii_lvds_rx
|
|
generic (
|
|
number_of_channels : natural; -- Required parameter
|
|
deserialization_factor : natural; -- Required parameter
|
|
enable_dpa_mode : string := "OFF";
|
|
data_align_rollover : natural := 10;
|
|
lose_lock_on_one_change : string := "OFF";
|
|
reset_fifo_at_first_lock : string := "ON";
|
|
x_on_bitslip : string := "ON" );
|
|
|
|
port (
|
|
rx_in : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_fastclk : in std_logic; --Required port
|
|
rx_enable : in std_logic := '1';
|
|
rx_locked : in std_logic;
|
|
rx_dpaclock : in std_logic := '0';
|
|
rx_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_hold : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_enable : in std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
|
|
rx_fifo_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_channel_data_align : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_cda_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_out : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
|
|
rx_dpa_locked : out std_logic_vector(number_of_channels-1 downto 0);
|
|
rx_cda_max : out std_logic_vector(number_of_channels-1 downto 0) );
|
|
end component; -- stratixii_lvds_rx
|
|
|
|
component stratixiii_lvds_rx
|
|
generic (
|
|
number_of_channels : natural; -- Required parameter
|
|
deserialization_factor : natural; -- Required parameter
|
|
enable_dpa_mode : string := "OFF";
|
|
data_align_rollover : natural := 10;
|
|
lose_lock_on_one_change : string := "OFF";
|
|
reset_fifo_at_first_lock : string := "ON";
|
|
x_on_bitslip : string := "ON";
|
|
rx_align_data_reg : string := "RISING_EDGE";
|
|
enable_soft_cdr_mode : string := "OFF";
|
|
sim_dpa_output_clock_phase_shift : integer := 0;
|
|
sim_dpa_is_negative_ppm_drift : string := "OFF";
|
|
sim_dpa_net_ppm_variation : natural := 0;
|
|
enable_dpa_align_to_rising_edge_only : string := "OFF";
|
|
enable_dpa_initial_phase_selection : string := "OFF";
|
|
dpa_initial_phase_value :natural := 0;
|
|
registered_output : string := "ON";
|
|
enable_clock_pin_mode : string := "UNUSED";
|
|
use_dpa_calibration : boolean := false;
|
|
ARRIAII_RX_STYLE : boolean := false;
|
|
STRATIXV_RX_STYLE : boolean := false );
|
|
|
|
port (
|
|
rx_in : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_fastclk : in std_logic; --Required port
|
|
rx_slowclk : in std_logic; --Required port
|
|
rx_dpaclock : in std_logic;
|
|
rx_enable : in std_logic := '1';
|
|
rx_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_hold : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_dpll_enable : in std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
|
|
rx_fifo_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_channel_data_align : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_cda_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_locked : in std_logic := '1';
|
|
rx_dpa_lock_reset : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
|
|
rx_out : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
|
|
rx_dpa_locked : out std_logic_vector(number_of_channels-1 downto 0);
|
|
rx_cda_max : out std_logic_vector(number_of_channels-1 downto 0);
|
|
rx_divfwdclk : out std_logic_vector(number_of_channels-1 downto 0) := (others => '0') );
|
|
end component; -- stratixiii_lvds_rx
|
|
|
|
component flexible_lvds_rx
|
|
generic (
|
|
number_of_channels : natural; -- Required parameter
|
|
deserialization_factor : natural;
|
|
use_extra_ddio_register : boolean := true;
|
|
use_extra_pll_clk : boolean := false;
|
|
buffer_implementation : string := "RAM";
|
|
registered_data_align_input : string := "OFF";
|
|
use_external_pll : string := "OFF";
|
|
registered_output : string := "OFF";
|
|
add_latency : boolean := true );
|
|
|
|
port (
|
|
rx_in : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_fastclk : in std_logic; --Required port
|
|
rx_slowclk : in std_logic; --Required port
|
|
rx_syncclk : in std_logic; --Required port
|
|
pll_areset : in std_logic; --Required port
|
|
rx_data_reset : in std_logic;
|
|
rx_locked : in std_logic; --Required port
|
|
rx_data_align : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_cda_reset : in std_logic_vector(number_of_channels-1 downto 0); --Required port
|
|
rx_out : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0) );
|
|
end component; -- flexible_lvds_rx
|
|
|
|
begin
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
rx_out <= flvds_dataout when (FAMILY_HAS_FLEXIBLE_LVDS = true) and (deserialization_factor > 2)
|
|
else stratixiii_dataout when (STRATIXIII_RX_STYLE = true) and (deserialization_factor > 2)
|
|
else rx_out_reg when (registered_output = "ON") and (use_external_pll = "OFF")
|
|
else rx_out_int;
|
|
|
|
rx_dpa_locked <= stratixii_dpa_locked when (STRATIXII_RX_STYLE = true)
|
|
else stratixiii_dpa_locked when (STRATIXIII_RX_STYLE = true)
|
|
else (others => '1');
|
|
|
|
rx_cda_max <= stratixii_cda_max when (STRATIXII_RX_STYLE = true)
|
|
else stratixiii_cda_max when (STRATIXIII_RX_STYLE = true)
|
|
else (others => '0');
|
|
|
|
rx_out_int <= rx_in when (deserialization_factor = 1)
|
|
else rx_ddio_in when (deserialization_factor = 2)
|
|
else stratixii_dataout when (STRATIXII_RX_STYLE = true)
|
|
else rxpdatout when (STRATIXGX_DPA_RX_STYLE = true)
|
|
else rx_out_extra_yeager_reg when (STRATIX_RX_STYLE = true)
|
|
else data_out;
|
|
|
|
rx_out_reg <= rx_out_rgd2 when ((STRATIXGX_DPA_RX_STYLE = true) and
|
|
(use_coreclock_input = "ON"))
|
|
else rx_out_rgd;
|
|
rx_clock0_int <= rx_pll_clk0 when (deserialization_factor > 2)
|
|
else rx_inclock;
|
|
|
|
rx_clock1_int <= rx_pll_clk1 when (deserialization_factor > 2)
|
|
else rx_inclock;
|
|
|
|
rx_divfwdclk <= stratixiii_divfwdclk;
|
|
|
|
rx_outclock <= rx_clock1_int;
|
|
|
|
rx_reg_clk <= rx_inclock when ((use_external_pll = "ON") or (deserialization_factor <= 2))
|
|
else rx_clock1_int;
|
|
|
|
rx_locked <= rx_locked_int and pll_lock_sync when (((STRATIXIII_RX_STYLE = true) or
|
|
(CYCLONEIII_RX_STYLE = true)) and
|
|
(deserialization_factor > 2))
|
|
else rx_locked_int when (deserialization_factor > 2)
|
|
else '1';
|
|
|
|
rx_pll_clk0 <= yeager_clock(0) when (STRATIX_RX_STYLE = true)
|
|
else aurora_clock(0) when (STRATIXGX_DPA_RX_STYLE = true)
|
|
else stratixii_clock(0) when (STRATIXII_RX_STYLE = true)
|
|
else '0';
|
|
|
|
rx_pll_clk1 <= cyclone_clock(2) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIX_STYLE_PLL = true))
|
|
else cycloneii_clock(2) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXII_STYLE_PLL = true))
|
|
else yeager_clock(2) when (STRATIX_RX_STYLE = true)
|
|
else aurora_clock(2) when (STRATIXGX_DPA_RX_STYLE = true)
|
|
else stratixii_clock(2) when (STRATIXII_RX_STYLE = true)
|
|
else stratixiii_clock(2) when (STRATIXIII_RX_STYLE = true) or (CYCLONEIII_RX_STYLE = true)
|
|
else '0';
|
|
|
|
rx_locked_int <= '1' when (use_external_pll = "ON")
|
|
else cyclone_locked_int when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIX_STYLE_PLL = true))
|
|
else cycloneii_locked_int when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXII_STYLE_PLL = true))
|
|
else yeager_locked_int when (STRATIX_RX_STYLE = true)
|
|
else aurora_locked_int when (STRATIXGX_DPA_RX_STYLE = true)
|
|
else stratixii_locked_int when (STRATIXII_RX_STYLE = true)
|
|
else stratixiii_locked_int when (STRATIXIII_RX_STYLE = true) or (CYCLONEIII_RX_STYLE = true)
|
|
else '1';
|
|
|
|
rxpdat1 <= read_data when ((STRATIXGX_DPA_RX_STYLE = true) and (enable_dpa_fifo = "ON"))
|
|
else serdes_data_out;
|
|
|
|
write_data <= serdes_data_out;
|
|
|
|
pclk <= clkout_tmp;
|
|
|
|
stratixii_fastclk <= '0' when (STRATIXII_RX_STYLE = false) or (implement_in_les = "ON")
|
|
else rx_inclock when (use_external_pll = "ON")
|
|
else rx_pll_sclkout0_dly;
|
|
|
|
stratixii_enable <= '0' when (STRATIXII_RX_STYLE = false) or (implement_in_les = "ON")
|
|
else rx_enable when (use_external_pll = "ON")
|
|
else rx_pll_enable0;
|
|
|
|
stratixiii_fastclk <= '0' when (STRATIXIII_RX_STYLE = false) or (implement_in_les = "ON")
|
|
else rx_inclock when (use_external_pll = "ON") or (enable_clock_pin_mode = "ON")
|
|
else stratixiii_clock(0);
|
|
|
|
stratixiii_slowclk <= '0' when (STRATIXIII_RX_STYLE = false) or (implement_in_les = "ON") or (enable_clock_pin_mode = "ON")
|
|
else rx_syncclock when (use_external_pll = "ON")
|
|
else stratixiii_clock(2);
|
|
|
|
stratixiii_enable <= '0' when (STRATIXIII_RX_STYLE = false) or (implement_in_les = "ON") or (enable_clock_pin_mode = "ON")
|
|
else rx_enable when (use_external_pll = "ON")
|
|
else stratixiii_clock(1);
|
|
|
|
rx_data_align_clk <= rx_clock1_int when ((STRATIX_RX_STYLE = true) or
|
|
(STRATIXII_RX_STYLE = true) or (STRATIXIII_RX_STYLE = true)) and
|
|
(implement_in_les = "OFF")
|
|
else '0';
|
|
|
|
rx_data_align_wire <= rx_data_align when (port_rx_data_align = "PORT_USED")
|
|
else '0' when (port_rx_data_align = "PORT_UNUSED")
|
|
else rx_data_align when (rx_data_align /= 'Z')
|
|
else '0';
|
|
|
|
rx_data_align_int <= rx_data_align_reg when (registered_data_align_input = "ON")
|
|
else rx_data_align_wire;
|
|
|
|
rx_channel_data_align_wire <= rx_channel_data_align when (rx_channel_data_align /= temp_z)
|
|
else (others => rx_data_align_int ) when ((STRATIXII_RX_STYLE = true) or
|
|
(STRATIXIII_RX_STYLE = true))
|
|
else (others => '0');
|
|
|
|
flvds_fastclk <= '0' when (FAMILY_HAS_FLEXIBLE_LVDS = false)
|
|
else rx_inclock when (use_external_pll = "ON")
|
|
else cyclone_clock(0) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIX_STYLE_PLL = true))
|
|
else cycloneii_clock(0) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXII_STYLE_PLL = true))
|
|
else stratixiii_clock(0) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXIII_STYLE_PLL = true))
|
|
else '0';
|
|
|
|
flvds_slowclk <= '0' when (FAMILY_HAS_FLEXIBLE_LVDS = false)
|
|
else rx_readclock when (use_external_pll = "ON")
|
|
else cyclone_clock(2) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIX_STYLE_PLL = true))
|
|
else cycloneii_clock(2) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXII_STYLE_PLL = true))
|
|
else stratixiii_clock(2) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXIII_STYLE_PLL = true))
|
|
else '0';
|
|
|
|
flvds_syncclk <= '0' when (FAMILY_HAS_FLEXIBLE_LVDS = false)
|
|
else rx_syncclock when (use_external_pll = "ON")
|
|
else cyclone_clock(1) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIX_STYLE_PLL = true))
|
|
else cycloneii_clock(1) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXII_STYLE_PLL = true))
|
|
else stratixiii_clock(1) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXIII_STYLE_PLL = true))
|
|
else '0';
|
|
|
|
flvds_rx_data_align <= rx_channel_data_align when ((port_rx_channel_data_align = "PORT_USED") or
|
|
((port_rx_channel_data_align = "PORT_CONNECTIVITY") and
|
|
(rx_channel_data_align /= temp_z)))
|
|
else (others => rx_data_align_wire ) when (port_rx_data_align /= "PORT_UNUSED")
|
|
else (others => '0');
|
|
|
|
flvds_rx_cda_reset <= rx_cda_reset when ((port_rx_channel_data_align = "PORT_USED") or
|
|
((port_rx_channel_data_align = "PORT_CONNECTIVITY") and
|
|
(rx_channel_data_align /= temp_z)))
|
|
else (others => rx_data_align_reset ) when (port_rx_data_align /= "PORT_UNUSED")
|
|
else (others => '0');
|
|
|
|
-- COMPONENT ASSIGNMENTS
|
|
|
|
-- instantiation of the PLLs used by LVDS_RX
|
|
-- MF_stratix_pll used for Stratix and Stratix GX
|
|
-- MF_stratixii_pll used for Stratix II
|
|
-- MF_stratixiii_pll used for Stratix III
|
|
STRATIX_PLL:
|
|
if ((STRATIX_RX_STYLE = true) and (implement_in_les = "OFF") and (deserialization_factor > 2)) generate
|
|
|
|
U2: MF_stratix_pll -- STRATIX PLL
|
|
generic map (
|
|
inclk0_input_frequency => inclock_period,
|
|
inclk1_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk2_multiply_by => INT_CLOCK_BOOST,
|
|
clk2_divide_by => deserialization_factor,
|
|
clk0_phase_shift => PHASE_INCLOCK,
|
|
clk2_phase_shift => PHASE_INCLOCK,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => rx_inclock,
|
|
inclk(1) => rx_inclock,
|
|
ena => rx_pll_enable,
|
|
areset => pll_areset,
|
|
clkena(5 downto 0) => temp_high,
|
|
comparator => rx_data_align_int,
|
|
clk => yeager_clock,
|
|
enable0 => rx_pll_enable0,
|
|
enable1 => rx_pll_enable1,
|
|
locked => yeager_locked_int );
|
|
|
|
end generate STRATIX_PLL;
|
|
|
|
|
|
STRATIXGX_DPA_PLL:
|
|
if ((STRATIXGX_DPA_RX_STYLE = true) and (implement_in_les = "OFF") and (deserialization_factor > 2)) generate
|
|
|
|
U2: MF_stratix_pll -- Stratix GX PLL
|
|
generic map (
|
|
inclk0_input_frequency => inclock_period,
|
|
inclk1_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk2_multiply_by => INT_CLOCK_BOOST,
|
|
clk2_divide_by => deserialization_factor,
|
|
clk0_phase_shift => "0",
|
|
clk2_phase_shift => "0",
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => rx_inclock,
|
|
inclk(1) => temp_zero,
|
|
ena => rx_pll_enable,
|
|
areset => pll_areset,
|
|
clkena(5 downto 0) => temp_high,
|
|
clk => aurora_clock,
|
|
locked => aurora_locked_int );
|
|
|
|
end generate STRATIXGX_DPA_PLL;
|
|
|
|
STRATIXII_PLL:
|
|
if ((STRATIXII_RX_STYLE = true) and (implement_in_les = "OFF") and (use_external_pll /= "ON") and
|
|
(deserialization_factor > 2)) generate
|
|
|
|
U3: MF_stratixii_pll -- Stratix II PLL
|
|
generic map (
|
|
vco_multiply_by => INT_CLOCK_BOOST,
|
|
vco_divide_by => 1,
|
|
inclk0_input_frequency => inclock_period,
|
|
inclk1_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => deserialization_factor,
|
|
clk2_multiply_by => INT_CLOCK_BOOST,
|
|
clk2_divide_by => deserialization_factor,
|
|
clk0_phase_shift => STXII_PHASE_INCLOCK,
|
|
clk2_phase_shift => STXII_PHASE_INCLOCK,
|
|
sclkout0_phase_shift => STXII_PHASE_INCLOCK,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => rx_inclock,
|
|
inclk(1) => temp_zero,
|
|
ena => rx_pll_enable,
|
|
areset => pll_areset,
|
|
clk => stratixii_clock,
|
|
locked => stratixii_locked_int,
|
|
enable0 => rx_pll_enable0,
|
|
sclkout(0) => rx_pll_sclkout0,
|
|
sclkout(1) => rx_pll_sclkout1 );
|
|
|
|
end generate STRATIXII_PLL;
|
|
|
|
STRATIXIII_PLL:
|
|
if ((STRATIXIII_RX_STYLE = true) and (implement_in_les = "OFF") and (use_external_pll /= "ON") and
|
|
(deserialization_factor > 2)) generate
|
|
|
|
U4: MF_stratixiii_pll -- Stratix III PLL
|
|
generic map (
|
|
vco_multiply_by => INT_CLOCK_BOOST,
|
|
vco_divide_by => 1,
|
|
inclk0_input_frequency => inclock_period,
|
|
inclk1_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => 1,
|
|
clk1_multiply_by => INT_CLOCK_BOOST,
|
|
clk1_divide_by => deserialization_factor,
|
|
clk1_duty_cycle => integer(real(100/deserialization_factor) + real(0.5)),
|
|
clk2_multiply_by => INT_CLOCK_BOOST,
|
|
clk2_divide_by => deserialization_factor,
|
|
clk0_phase_shift => STXII_PHASE_INCLOCK,
|
|
clk1_phase_shift => CLK_ENA_PHASE_SHIFT,
|
|
clk2_phase_shift => STXII_PHASE_INCLOCK,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => rx_inclock,
|
|
inclk(1) => temp_zero,
|
|
areset => pll_areset,
|
|
clk => stratixiii_clock,
|
|
locked => stratixiii_locked_int );
|
|
|
|
end generate STRATIXIII_PLL;
|
|
|
|
FLVDS_STX_PLL:
|
|
if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIX_STYLE_PLL = true) and (deserialization_factor > 2)) generate
|
|
|
|
U4: MF_stratix_pll -- Cyclone PLL
|
|
generic map (
|
|
pll_type => FLVDS_PLL_TYPE,
|
|
inclk0_input_frequency => inclock_period,
|
|
inclk1_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => FLVDS_CLK0_DIV,
|
|
clk1_multiply_by => FLVDS_CLK1_MULT,
|
|
clk1_divide_by => FLVDS_CLK1_DIV,
|
|
clk2_multiply_by => FLVDS_CLK2_MULT,
|
|
clk2_divide_by => FLVDS_CLK2_DIV,
|
|
clk0_phase_shift => PHASE_INCLOCK,
|
|
clk1_phase_shift => FLVDS_CLK1_PHASE_SHIFT,
|
|
clk2_phase_shift => PHASE_INCLOCK,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => rx_inclock,
|
|
inclk(1) => temp_zero,
|
|
ena => rx_pll_enable,
|
|
areset => pll_areset,
|
|
clkena(5 downto 0) => temp_high,
|
|
clk => cyclone_clock,
|
|
locked => cyclone_locked_int );
|
|
|
|
end generate FLVDS_STX_PLL;
|
|
|
|
FLVDS_STXII_PLL:
|
|
if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXII_STYLE_PLL = true) and (use_external_pll /= "ON") and
|
|
(deserialization_factor > 2)) generate
|
|
|
|
U5: MF_stratixii_pll -- Stratix II PLL
|
|
generic map (
|
|
operation_mode => alpha_tolower(pll_operation_mode),
|
|
pll_type => FLVDS_PLL_TYPE,
|
|
vco_multiply_by => INT_CLOCK_BOOST,
|
|
vco_divide_by => 1,
|
|
inclk0_input_frequency => inclock_period,
|
|
inclk1_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => FLVDS_CLK0_DIV,
|
|
clk1_multiply_by => FLVDS_CLK1_MULT,
|
|
clk1_divide_by => FLVDS_CLK1_DIV,
|
|
clk2_multiply_by => FLVDS_CLK2_MULT,
|
|
clk2_divide_by => FLVDS_CLK2_DIV,
|
|
clk0_phase_shift => STXII_LE_PHASE_INCLOCK,
|
|
clk1_phase_shift => STXII_LE_CLK1_PHASE_SHIFT,
|
|
clk2_phase_shift => STXII_LE_PHASE_INCLOCK,
|
|
sclkout0_phase_shift => PHASE_INCLOCK,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => rx_inclock,
|
|
inclk(1) => temp_zero,
|
|
ena => rx_pll_enable,
|
|
areset => pll_areset,
|
|
clk => cycloneii_clock,
|
|
locked => cycloneii_locked_int,
|
|
enable0 => rx_pll_enable0,
|
|
sclkout(0) => rx_pll_sclkout0,
|
|
sclkout(1) => rx_pll_sclkout1 );
|
|
|
|
end generate FLVDS_STXII_PLL;
|
|
|
|
FLVDS_STXIII_PLL:
|
|
if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXIII_STYLE_PLL = true) and (use_external_pll /= "ON") and
|
|
(deserialization_factor > 2)) generate
|
|
|
|
U5: MF_stratixiii_pll -- Stratix III PLL
|
|
generic map (
|
|
operation_mode => alpha_tolower(pll_operation_mode),
|
|
pll_type => FLVDS_PLL_TYPE,
|
|
vco_multiply_by => INT_CLOCK_BOOST,
|
|
vco_divide_by => 1,
|
|
inclk0_input_frequency => inclock_period,
|
|
inclk1_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => FLVDS_CLK0_DIV,
|
|
clk1_multiply_by => FLVDS_CLK1_MULT,
|
|
clk1_divide_by => FLVDS_CLK1_DIV,
|
|
clk2_multiply_by => FLVDS_CLK2_MULT,
|
|
clk2_divide_by => FLVDS_CLK2_DIV,
|
|
clk0_phase_shift => STXIII_LE_PHASE_INCLOCK,
|
|
clk1_phase_shift => STXIII_LE_CLK1_PHASE_SHIFT,
|
|
clk2_phase_shift => STXIII_LE_PHASE_INCLOCK,
|
|
family_name => intended_device_family,
|
|
self_reset_on_loss_lock => alpha_tolower(pll_self_reset_on_loss_lock) )
|
|
port map (
|
|
inclk(0) => rx_inclock,
|
|
inclk(1) => temp_zero,
|
|
areset => pll_areset,
|
|
clk => stratixiii_clock,
|
|
locked => stratixiii_locked_int );
|
|
|
|
end generate FLVDS_STXIII_PLL;
|
|
|
|
STRATIXII_LVDS_RECEIVER:
|
|
if ((STRATIXII_RX_STYLE = true) and (implement_in_les = "OFF") and (deserialization_factor > 2)) generate
|
|
|
|
U6: stratixii_lvds_rx
|
|
generic map (
|
|
number_of_channels => number_of_channels,
|
|
deserialization_factor => deserialization_factor,
|
|
enable_dpa_mode => enable_dpa_mode,
|
|
data_align_rollover => data_align_rollover,
|
|
lose_lock_on_one_change => lose_lock_on_one_change,
|
|
reset_fifo_at_first_lock => reset_fifo_at_first_lock,
|
|
x_on_bitslip => x_on_bitslip )
|
|
port map (
|
|
rx_in => rx_in,
|
|
rx_fastclk => stratixii_fastclk,
|
|
rx_enable => stratixii_enable,
|
|
rx_locked => stratixii_locked_int,
|
|
rx_reset => rx_reset,
|
|
rx_dpll_reset => rx_dpll_reset,
|
|
rx_dpll_hold => rx_dpll_hold,
|
|
rx_dpll_enable => rx_dpll_enable,
|
|
rx_fifo_reset => rx_fifo_reset,
|
|
rx_channel_data_align => rx_channel_data_align_wire,
|
|
rx_cda_reset => rx_cda_reset,
|
|
rx_out => stratixii_dataout,
|
|
rx_dpa_locked => stratixii_dpa_locked,
|
|
rx_cda_max => stratixii_cda_max );
|
|
end generate STRATIXII_LVDS_RECEIVER;
|
|
|
|
FLEXIBLE_LVDS_RECEIVER:
|
|
if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and (deserialization_factor > 2)) generate
|
|
|
|
U7: flexible_lvds_rx
|
|
generic map (
|
|
number_of_channels => number_of_channels,
|
|
deserialization_factor => deserialization_factor,
|
|
use_extra_ddio_register => IS_USING_EXTRA_DDIO_REG,
|
|
use_extra_pll_clk => IS_USING_EXTRA_PLL_CLK,
|
|
buffer_implementation => buffer_implementation,
|
|
registered_data_align_input => registered_data_align_input,
|
|
use_external_pll => use_external_pll,
|
|
registered_output => registered_output,
|
|
add_latency => IS_ADDING_EXTRA_LATENCY )
|
|
port map (
|
|
rx_in => rx_in,
|
|
rx_fastclk => flvds_fastclk,
|
|
rx_slowclk => flvds_slowclk,
|
|
rx_syncclk => flvds_syncclk,
|
|
pll_areset => pll_areset,
|
|
rx_data_reset => rx_data_reset,
|
|
rx_data_align => flvds_rx_data_align,
|
|
rx_cda_reset => flvds_rx_cda_reset,
|
|
rx_locked => rx_locked_int,
|
|
rx_out => flvds_dataout );
|
|
end generate FLEXIBLE_LVDS_RECEIVER;
|
|
|
|
STRATIXIII_LVDS_RECEIVER:
|
|
if ((STRATIXIII_RX_STYLE = true) and (implement_in_les = "OFF") and (deserialization_factor > 2)) generate
|
|
|
|
U8: stratixiii_lvds_rx
|
|
generic map (
|
|
number_of_channels => number_of_channels,
|
|
deserialization_factor => deserialization_factor,
|
|
enable_dpa_mode => enable_dpa_mode,
|
|
data_align_rollover => data_align_rollover,
|
|
lose_lock_on_one_change => lose_lock_on_one_change,
|
|
reset_fifo_at_first_lock => reset_fifo_at_first_lock,
|
|
x_on_bitslip => x_on_bitslip,
|
|
rx_align_data_reg => rx_align_data_reg,
|
|
enable_soft_cdr_mode => enable_soft_cdr_mode,
|
|
sim_dpa_output_clock_phase_shift => sim_dpa_output_clock_phase_shift,
|
|
sim_dpa_is_negative_ppm_drift => sim_dpa_is_negative_ppm_drift,
|
|
sim_dpa_net_ppm_variation => sim_dpa_net_ppm_variation,
|
|
enable_dpa_align_to_rising_edge_only => enable_dpa_align_to_rising_edge_only,
|
|
enable_dpa_initial_phase_selection => enable_dpa_initial_phase_selection,
|
|
dpa_initial_phase_value => dpa_initial_phase_value,
|
|
registered_output => registered_output,
|
|
enable_clock_pin_mode => enable_clock_pin_mode,
|
|
use_dpa_calibration => use_dpa_calibration,
|
|
ARRIAII_RX_STYLE => ARRIAII_RX_STYLE,
|
|
STRATIXV_RX_STYLE => STRATIXV_RX_STYLE )
|
|
port map (
|
|
rx_in => rx_in,
|
|
rx_fastclk => stratixiii_fastclk,
|
|
rx_slowclk => stratixiii_slowclk,
|
|
rx_enable => stratixiii_enable,
|
|
rx_dpaclock => rx_dpaclock,
|
|
rx_reset => rx_reset,
|
|
rx_dpll_reset => rx_dpll_reset,
|
|
rx_dpll_hold => rx_dpll_hold,
|
|
rx_dpll_enable => rx_dpll_enable,
|
|
rx_fifo_reset => rx_fifo_reset,
|
|
rx_channel_data_align => rx_channel_data_align_wire,
|
|
rx_cda_reset => rx_cda_reset,
|
|
rx_out => stratixiii_dataout,
|
|
rx_dpa_locked => stratixiii_dpa_locked,
|
|
rx_cda_max => stratixiii_cda_max,
|
|
rx_divfwdclk => stratixiii_divfwdclk );
|
|
end generate STRATIXIII_LVDS_RECEIVER;
|
|
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
STRATIXII_FCLK : process (rx_pll_sclkout0)
|
|
begin
|
|
rx_pll_sclkout0_dly <= rx_pll_sclkout0;
|
|
end process; -- STRATIXII_FCLK process
|
|
|
|
-- basic error checking for invalid deserialization factors
|
|
MSG: process(rx_channel_data_align, rx_data_align)
|
|
variable all_z : std_logic_vector(number_of_channels-1 downto 0)
|
|
:= (others =>'Z');
|
|
variable init : boolean := true;
|
|
begin
|
|
if (init = true) then
|
|
if (IS_VALID_FAMILY(intended_device_family) = false) then
|
|
ASSERT FALSE
|
|
REPORT intended_device_family & " is not a valid device family!"
|
|
SEVERITY ERROR;
|
|
elsif ((STRATIX_RX_STYLE = true) and
|
|
(deserialization_factor /= 1) and
|
|
(deserialization_factor /= 2) and
|
|
((deserialization_factor > 10) or
|
|
(deserialization_factor < 4))) then
|
|
ASSERT FALSE
|
|
REPORT "Stratix and Stratix GX (non DPA mode) does not support the specified deserialization factor!"
|
|
SEVERITY ERROR;
|
|
elsif ((STRATIXGX_DPA_RX_STYLE = true) and
|
|
(enable_dpa_mode = "ON") and
|
|
(deserialization_factor /= 8) and
|
|
(deserialization_factor /= 10)) then
|
|
ASSERT FALSE
|
|
REPORT "STRATIXGX in DPA mode does not support the specified deserialization factor!"
|
|
SEVERITY ERROR;
|
|
elsif ((STRATIXII_RX_STYLE = true) and
|
|
(deserialization_factor > 10)) then
|
|
ASSERT FALSE
|
|
REPORT "STRATIXII does not support the specified deserialization factor!"
|
|
SEVERITY ERROR;
|
|
elsif ((STRATIXII_RX_STYLE = true) and
|
|
(data_align_rollover > 11)) then
|
|
ASSERT FALSE
|
|
REPORT "Stratix II does not support data align rollover values > 11 !"
|
|
SEVERITY ERROR;
|
|
elsif (CYCLONE_RX_STYLE = true) then
|
|
if ((use_external_pll = "OFF") and ((deserialization_factor > 10) or (deserialization_factor = 3))) then
|
|
ASSERT FALSE
|
|
REPORT "Cyclone does not support the specified deserialization factor when use_external_pll is 'OFF'!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
elsif (CYCLONEII_RX_STYLE = true) then
|
|
if ((use_external_pll = "OFF") and ((deserialization_factor > 10) or (deserialization_factor = 3))) then
|
|
ASSERT FALSE
|
|
REPORT "Cyclone II does not support the specified deserialization factor when use_external_pll is 'OFF'!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
end if;
|
|
|
|
if (((STRATIXII_RX_STYLE = true) or (STRATIXIII_RX_STYLE = true)) and
|
|
(rx_channel_data_align = all_z) and
|
|
(rx_data_align /= 'Z')) then
|
|
ASSERT FALSE
|
|
REPORT "Data alignment on Stratix II/III devices introduces one bit of latency for each assertion of the data alignment signal. In comparison, Stratix and Stratix GX devices remove one bit of latency for each assertion."
|
|
SEVERITY Warning;
|
|
end if;
|
|
init := false;
|
|
end if;
|
|
|
|
end process; -- MSG process
|
|
|
|
X2_MODE :
|
|
if (deserialization_factor = 2) generate
|
|
|
|
-- For x2 mode, data input is sampled in both the rising edge and falling edge
|
|
-- of input clock.
|
|
DDIO_IN : process (rx_inclock)
|
|
variable datain_latched : std_logic_vector(number_of_channels-1 downto 0)
|
|
:= (others =>'0');
|
|
begin
|
|
if (rx_inclock'event and (rx_inclock = '1')) then
|
|
for i in 0 to number_of_channels -1 loop
|
|
if (CYCLONEIII_RX_STYLE = true) then
|
|
rx_ddio_in((i*2)+1) <= rx_in(i);
|
|
rx_ddio_in((i*2)) <= datain_latched(i);
|
|
else
|
|
rx_ddio_in((i*2)) <= rx_in(i);
|
|
rx_ddio_in((i*2)+1) <= datain_latched(i);
|
|
end if;
|
|
end loop;
|
|
-- falling edge of inclock
|
|
elsif (rx_inclock'event and (rx_inclock = '0')) then
|
|
for i in 0 to number_of_channels -1 loop
|
|
datain_latched(i) := rx_in(i);
|
|
end loop;
|
|
end if;
|
|
end process; -- DDIO_IN process
|
|
end generate X2_MODE;
|
|
|
|
-- Register the load enable signal for Stratix
|
|
LOAD_ENABLE_PROC: process (rx_clock0_int)
|
|
begin
|
|
if (rx_clock0_int'event and (rx_clock0_int ='1') and (rx_clock0_int'last_value ='0')) then
|
|
enable0_pipe <= enable0_reg;
|
|
enable0_reg <= rx_pll_enable0;
|
|
enable1_reg <= rx_pll_enable1;
|
|
elsif (rx_clock0_int'event and (rx_clock0_int = '0') and (rx_clock0_int'last_value ='1')) then
|
|
enable0_neg <= enable0_pipe;
|
|
elsif (rx_clock0_int'event and (rx_clock0_int = 'X')) then
|
|
enable0_pipe <= 'X';
|
|
enable0_reg <= 'X';
|
|
enable1_reg <= 'X';
|
|
enable0_neg <= 'X';
|
|
end if;
|
|
|
|
end process; -- LOAD_ENABLE_PROC process
|
|
|
|
-- the deserializer
|
|
LOAD_DATA: process(rx_clock0_int, rx_clock1_int)
|
|
variable count : CHANNEL_CNT := (others => 0);
|
|
variable sample : integer;
|
|
variable start_data : integer := 0;
|
|
variable data_int : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
variable x : integer:=0;
|
|
begin
|
|
|
|
if (rx_clock0_int'event and (rx_clock0_int = '0')) then
|
|
-- For Stratix and Stratix GX non-DPA mode, load data
|
|
-- when the registered load enable signal is high
|
|
if ((enable0_neg = '1') and
|
|
(STRATIX_RX_STYLE = true)) then
|
|
data_out <= data_int;
|
|
end if;
|
|
|
|
-- Deserialize the incoming bits
|
|
for i in 0 to number_of_channels -1 loop
|
|
if (STRATIX_RX_STYLE = true) then
|
|
for x in deserialization_factor-1 downto 1 loop
|
|
-- Data gets shifted into MSB first.
|
|
data_int(x + (i * deserialization_factor)) := data_int (x-1 + (i * deserialization_factor));
|
|
end loop;
|
|
data_int(i * deserialization_factor) := rx_in(i);
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
end process; -- LOAD_DATA process
|
|
|
|
-- the parallel and hold registers
|
|
PARALLEL_REG: process(rx_clock1_int, enable1_reg, stratixiii_divfwdclk)
|
|
begin
|
|
if (stratixiii_divfwdclk'event and (stratixiii_divfwdclk(0) = '1')) then
|
|
if (enable_soft_cdr_mode = "ON") then
|
|
rx_out_rgd <= rx_out_int;
|
|
end if;
|
|
end if;
|
|
|
|
if(rx_clock1_int'event and (rx_clock1_int = '1')) then
|
|
if (enable_soft_cdr_mode = "OFF") then
|
|
rx_out_rgd <= rx_out_int;
|
|
end if;
|
|
end if;
|
|
|
|
if (enable1_reg'event and (enable1_reg = '1')) then
|
|
rx_out_extra_yeager_reg <= data_out;
|
|
end if;
|
|
end process; -- PARALLEL_REG process
|
|
|
|
DATA_ALIGN_REG: process(rx_data_align_clk)
|
|
begin
|
|
if (rx_data_align_clk'event and (rx_data_align_clk = '1')) then
|
|
rx_data_align_reg <= rx_data_align_wire;
|
|
end if;
|
|
end process; --DATA_ALIGN_REG
|
|
|
|
|
|
-- Stratix GX DPA internal model
|
|
|
|
STRATIXGX_DPA_RX :
|
|
if (STRATIXGX_DPA_RX_STYLE = true) generate
|
|
|
|
-- the synchronization register
|
|
SYNC_REGISTER: process(rx_coreclk)
|
|
begin
|
|
if (use_coreclock_input = "ON") then
|
|
for i in 0 to number_of_channels -1 loop
|
|
if ((rx_coreclk_pre(i) = '0') and (rx_coreclk(i) = '1')) then
|
|
rx_out_rgd2(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rx_out_int(deserialization_factor*(i+1) -1 downto deserialization_factor*i);
|
|
end if;
|
|
rx_coreclk_pre(i) <= rx_coreclk(i);
|
|
end loop;
|
|
end if;
|
|
end process; --SYNC_REGISTER process
|
|
|
|
-- deserializer logic
|
|
DPA_SERDES: process(rx_clock0_int, rx_clock1_int, rx_coreclk, rx_reset, rx_dpll_reset)
|
|
variable negedge_count: CHANNEL_CNT := (others => 0);
|
|
variable posedge_count: CHANNEL_CNT := (others => 0);
|
|
variable fast_clk_count : CHANNEL_CNT := (others => deserialization_factor);
|
|
variable data_int : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
|
|
variable rx_in_pipe : std_logic_vector(number_of_channels -1 downto 0) := (others => '0');
|
|
begin
|
|
|
|
-- count the fast clock edge after the rising edge of the global slow
|
|
-- clock in order to generate the parallel unload enable signal
|
|
for i in 0 to number_of_channels -1 loop
|
|
if (((use_coreclock_input = "ON") and (rx_coreclk_pre(i) = '0') and (rx_coreclk(i) = '1')) or
|
|
((use_coreclock_input = "OFF") and rx_clock1_int'event and (rx_clock1_int = '1'))) then
|
|
negedge_count(i) := 0;
|
|
posedge_count(i) := 0;
|
|
|
|
if ((rx_reset(i) = '1') or (rx_dpll_reset(i) = '1')) then
|
|
sync_reset(i) <= '1';
|
|
else
|
|
sync_reset(i) <= '0';
|
|
end if;
|
|
end if;
|
|
rx_coreclk_pre(i) <= rx_coreclk(i);
|
|
end loop;
|
|
|
|
if (rx_clock0_int'event and (rx_clock0_int = '1')) then
|
|
for i in 0 to number_of_channels -1 loop
|
|
posedge_count(i) := posedge_count(i) + 1;
|
|
|
|
-- load the parallel data when parallel unload enable signal goes high
|
|
if (negedge_count(i) = 2) then
|
|
serdes_data_out <= data_int;
|
|
end if;
|
|
|
|
if (sync_reset(i) = '1') then
|
|
fast_clk_count(i) := deserialization_factor;
|
|
clkout_tmp(i) <= '0';
|
|
else
|
|
if (fast_clk_count(i) = deserialization_factor) then
|
|
fast_clk_count(i) := 0;
|
|
clkout_tmp(i) <= not clkout_tmp(i);
|
|
elsif (fast_clk_count(i) = (deserialization_factor+1)/2) then
|
|
clkout_tmp(i) <= not clkout_tmp(i);
|
|
end if;
|
|
fast_clk_count(i) := fast_clk_count(i) + 1;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
|
|
|
|
-- deserialize the incoming bits
|
|
if (rx_clock0_int'event and (rx_clock0_int = '0')) then
|
|
for i in 0 to number_of_channels -1 loop
|
|
for x in deserialization_factor-1 downto 1 loop
|
|
-- Data gets shifted into MSB first.
|
|
data_int(x + (i * deserialization_factor)) := data_int (x-1 + (i * deserialization_factor));
|
|
end loop;
|
|
|
|
data_int(i * deserialization_factor) := rx_in_pipe(i);
|
|
rx_in_pipe(i) := rx_in(i);
|
|
|
|
if (((use_coreclock_input = "ON") and (posedge_count(i) > 0)) or (use_coreclock_input = "OFF")) then
|
|
negedge_count(i) := negedge_count(i) + 1;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
end process; -- DPA_SERDES process
|
|
|
|
-- phase compensation FIFO
|
|
DPA_FIFO: process(pclk, rx_clock1_int, rx_coreclk)
|
|
variable rd_index : CHANNEL_CNT := (others => 2);
|
|
variable wr_index : CHANNEL_CNT := (others => 0);
|
|
variable enable_fifo : boolean := false;
|
|
variable clk0_posedge_count : integer := 0;
|
|
begin
|
|
-- enable the FIFO only when PLL locks
|
|
if (rx_locked_int = '1') then
|
|
enable_fifo := true;
|
|
end if;
|
|
|
|
if (enable_fifo = true) then
|
|
-- Update write pointer and write data into the FIFO
|
|
for i in 0 to number_of_channels-1 loop
|
|
if ((pclk(i) = '1') and (pclk_pre(i) = '0')) then
|
|
if (sync_reset(i) = '1') then
|
|
wr_index(i) := 0;
|
|
else
|
|
ram_array(wr_index(i)) <= write_data;
|
|
wr_index(i) := (wr_index(i) + 1) rem 4;
|
|
end if;
|
|
end if;
|
|
pclk_pre(i) <= pclk(i);
|
|
end loop;
|
|
|
|
-- Read data from the FIFO and update read pointer
|
|
for i in 0 to number_of_channels-1 loop
|
|
if (((use_coreclock_input = "ON") and (rx_coreclk_pre(i) = '0') and (rx_coreclk(i) = '1')) or
|
|
((use_coreclock_input = "OFF") and (rx_clock1_int'event) and (rx_clock1_int = '1'))) then
|
|
|
|
-- reset logic
|
|
if ((rx_reset(i) = '1') or (rx_dpll_reset(i) = '1') or (sync_reset(i) = '1')) then
|
|
read_data(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= (others => '0');
|
|
wr_index(i) := 0;
|
|
rd_index(i) := 2;
|
|
for j in 0 to 3 loop
|
|
ram_array(j)(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= (others => '0');
|
|
end loop;
|
|
else
|
|
-- read data and update read pointer
|
|
read_data(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= ram_array(rd_index(i))(deserialization_factor*(i+1) -1 downto deserialization_factor*i);
|
|
rd_index(i) := (rd_index(i) + 1) rem 4;
|
|
end if;
|
|
end if;
|
|
|
|
rx_coreclk_pre(i) <= rx_coreclk(i);
|
|
|
|
end loop;
|
|
end if;
|
|
|
|
end process; -- DPA_FIFO process
|
|
|
|
|
|
-- bit-slipping logic
|
|
DPA_BIT_SLIP: process(rx_coreclk, rx_clock1_int, rx_channel_data_align)
|
|
variable count: CHANNEL_CNT := (others => 0);
|
|
variable count2: CHANNEL_CNT := (others => 0);
|
|
variable count3: CHANNEL_CNT := (others => 0);
|
|
begin
|
|
|
|
for i in 0 to number_of_channels-1 loop
|
|
-- increment the number-of-bits-to-slip counter once for each rising edge of the bitslip control signal
|
|
if (((use_coreclock_input = "ON") and (rx_coreclk_pre(i) = '0') and (rx_coreclk(i) = '1')) or
|
|
((use_coreclock_input = "OFF") and rx_clock1_int'event and (rx_clock1_int = '1'))) then
|
|
count3(i) := count2(i);
|
|
count2(i) := count(i);
|
|
if ((rx_channel_data_align_pre(i) = '0') and (rx_channel_data_align(i) = '1')) then
|
|
count(i) := (count(i) + 1) rem deserialization_factor;
|
|
end if;
|
|
|
|
rx_channel_data_align_pre(i) <= rx_channel_data_align(i);
|
|
|
|
-- reset logic
|
|
if ((rx_reset(i) = '1') or (rx_dpll_reset(i) = '1') or (sync_reset(i) = '1')) then
|
|
rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= (others => '0');
|
|
rxpdat3(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= (others => '0');
|
|
count(i) := 0;
|
|
count2(i) := 0;
|
|
count3(i) := 0;
|
|
rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= (others => '0');
|
|
else
|
|
-- register the parallel data from either the FIFO or the SERDES
|
|
rxpdat2 <= rxpdat1;
|
|
rxpdat3 <= rxpdat2;
|
|
|
|
-- select which bits to output to core from rxpdat2 and rxpdat3 registers
|
|
-- the bitslip counter determines how many bits to skip from rxpdat3, and
|
|
-- how many to take from rxpdat2
|
|
-- MSB of the registers is the earliest bit to enter, hence the MSB will
|
|
-- be the first bit to be skipped
|
|
case count3(i) is
|
|
when 0 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*(i+1) -1 downto deserialization_factor*i);
|
|
--(RXPDAT3[8:0],RXPDAT2[9]
|
|
when 1 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*(i+1) -2 downto deserialization_factor*i)
|
|
& rxpdat2(deserialization_factor*(i+1) -1);
|
|
--(RXPDAT3[7:0],RXPDAT2[9:8]
|
|
when 2 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*(i+1) -3 downto deserialization_factor*i)
|
|
& rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -2);
|
|
--(RXPDAT3[6:0],RXPDAT2[9:7]
|
|
when 3 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*(i+1) -4 downto deserialization_factor*i)
|
|
& rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -3);
|
|
--(RXPDAT3[5:0],RXPDAT2[9:6]
|
|
when 4 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*(i+1) -5 downto deserialization_factor*i)
|
|
& rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -4);
|
|
--(RXPDAT3[4:0],RXPDAT2[9:5]
|
|
when 5 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*(i+1) -6 downto deserialization_factor*i)
|
|
& rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -5);
|
|
--(RXPDAT3[3:0],RXPDAT2[9:4]
|
|
when 6 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*(i+1) -7 downto deserialization_factor*i)
|
|
& rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -6);
|
|
--(RXPDAT3[2:0],RXPDAT2[9:3]
|
|
when 7 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*(i+1) -8 downto deserialization_factor*i)
|
|
& rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -7);
|
|
--(RXPDAT3[1:0],RXPDAT2[9:2]
|
|
when 8 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*(i+1) -9 downto deserialization_factor*i)
|
|
& rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -8);
|
|
--(RXPDAT3[0:0],RXPDAT2[9:1]
|
|
when 9 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*i)
|
|
& rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -9);
|
|
|
|
when others => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
|
|
<= rxpdat3(deserialization_factor*(i+1) -1 downto deserialization_factor*i);
|
|
end case;
|
|
end if;
|
|
end if;
|
|
|
|
rx_coreclk_pre(i) <= rx_coreclk(i);
|
|
end loop;
|
|
|
|
end process; -- DPA_BIT_SLIP process
|
|
end generate STRATIXGX_DPA_RX;
|
|
|
|
process (rx_locked_int, pll_areset)
|
|
begin
|
|
if (pll_areset = '1') then
|
|
pll_lock_sync <= '0';
|
|
elsif (rx_locked_int = '1' and rx_locked_int'event) then
|
|
pll_lock_sync <= '1';
|
|
end if;
|
|
end process;
|
|
|
|
end behavior;
|
|
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : stratix_tx_outclk
|
|
--
|
|
-- Description : This module is used to generate the tx_outclock for Stratix
|
|
-- and stratix GX family.
|
|
--
|
|
-- Limitation : Only available to Stratix and Stratix GX family.
|
|
--
|
|
-- Results Expected: Output clock.
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
|
|
-- LIBRARY USED----------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity stratix_tx_outclk is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
deserialization_factor : natural; -- Required parameter
|
|
bypass_serializer : boolean := FALSE;
|
|
invert_clock : boolean := FALSE;
|
|
use_falling_clock_edge : boolean := FALSE );
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
--INPUT PORT DECLARATION
|
|
tx_in : in std_logic_vector(deserialization_factor-1 downto 0);
|
|
tx_fastclk : in std_logic;
|
|
tx_enable : in std_logic := '1';
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
tx_out : out std_logic := '0' );
|
|
|
|
end stratix_tx_outclk;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of stratix_tx_outclk is
|
|
|
|
-- SIGNAL DECLARATION
|
|
|
|
-- constant signals
|
|
signal enable1_reg1 : std_logic;
|
|
signal enable1_reg2 : std_logic;
|
|
signal tx_out_neg : std_logic := '0';
|
|
signal tx_shift_reg : std_logic_vector(deserialization_factor-1 downto 0)
|
|
:= (others => '0');
|
|
signal tx_parallel_load_reg : std_logic_vector(deserialization_factor-1 downto 0)
|
|
:= (others => '0');
|
|
|
|
begin
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
tx_out <= tx_fastclk when (bypass_serializer = TRUE) and (invert_clock = FALSE)
|
|
else not tx_fastclk when (bypass_serializer = TRUE) and (invert_clock = TRUE)
|
|
else tx_out_neg when (use_falling_clock_edge = TRUE)
|
|
else tx_shift_reg(deserialization_factor-1);
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
-- Register the load enable signal
|
|
LOAD_ENABLE : process (tx_fastclk)
|
|
variable enable1_reg0 : std_logic;
|
|
begin
|
|
if (tx_fastclk'event and (tx_fastclk ='1') and (tx_fastclk'last_value ='0')) then
|
|
enable1_reg1 <= enable1_reg0;
|
|
enable1_reg0 := tx_enable;
|
|
elsif (tx_fastclk'event and (tx_fastclk = '0') and (tx_fastclk'last_value ='1')) then
|
|
enable1_reg2 <= enable1_reg1;
|
|
elsif (tx_fastclk'event and (tx_fastclk = 'X')) then
|
|
enable1_reg0 := 'X';
|
|
enable1_reg1 <= 'X';
|
|
enable1_reg2 <= 'X';
|
|
end if;
|
|
|
|
end process LOAD_ENABLE; -- LOAD_ENABLE process
|
|
|
|
-- the deserializer
|
|
FAST_CLOCK : process(tx_fastclk)
|
|
begin
|
|
if (tx_fastclk'event and (tx_fastclk = '0')) then
|
|
-- Shift data from shift register to tx_out on negative edge of
|
|
-- fast clock
|
|
tx_out_neg <= tx_shift_reg(deserialization_factor-1);
|
|
elsif (tx_fastclk'event and (tx_fastclk = '1')) then
|
|
if (enable1_reg2 = '1') then
|
|
tx_shift_reg <= tx_parallel_load_reg;
|
|
else
|
|
-- Shift data from shift register to tx_out on positive edge
|
|
-- of fast clock
|
|
for x in deserialization_factor-1 downto 1 loop
|
|
tx_shift_reg(x) <= tx_shift_reg (x-1);
|
|
end loop;
|
|
end if;
|
|
tx_parallel_load_reg <= tx_in;
|
|
end if;
|
|
end process FAST_CLOCK;
|
|
|
|
|
|
end behavior;
|
|
|
|
-- END OF ARCHITECTURE
|
|
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : stratixii_tx_outclk
|
|
--
|
|
-- Description : This module is used to generate the tx_outclock for StratixII
|
|
-- family.
|
|
--
|
|
-- Limitation : Only available to Stratix II family.
|
|
--
|
|
-- Results Expected: Output clock.
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- LIBRARY USED----------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity stratixii_tx_outclk is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
deserialization_factor : natural; -- Required parameter
|
|
bypass_serializer : boolean := FALSE;
|
|
invert_clock : boolean := FALSE;
|
|
use_falling_clock_edge : boolean := FALSE );
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
--INPUT PORT DECLARATION
|
|
tx_in : in std_logic_vector(deserialization_factor-1 downto 0);
|
|
tx_fastclk : in std_logic;
|
|
tx_enable : in std_logic := '1';
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
tx_out : out std_logic := '0' );
|
|
|
|
end stratixii_tx_outclk;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of stratixii_tx_outclk is
|
|
|
|
-- SIGNAL DECLARATION
|
|
|
|
-- constant signals
|
|
signal tx_out_neg : std_logic := '0';
|
|
signal tx_shift_reg : std_logic_vector(deserialization_factor-1 downto 0)
|
|
:= (others => '0');
|
|
signal tx_parallel_load_reg : std_logic_vector(deserialization_factor-1 downto 0)
|
|
:= (others => '0');
|
|
|
|
begin
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
tx_out <= tx_fastclk when (bypass_serializer = TRUE) and (invert_clock = FALSE)
|
|
else not tx_fastclk when (bypass_serializer = TRUE) and (invert_clock = TRUE)
|
|
else tx_out_neg when (use_falling_clock_edge = TRUE)
|
|
else tx_shift_reg(deserialization_factor-1);
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
-- the deserializer
|
|
FAST_CLOCK : process(tx_fastclk)
|
|
variable enable1_reg : std_logic := '0';
|
|
begin
|
|
if (tx_fastclk'event and (tx_fastclk = '0')) then
|
|
tx_out_neg <= tx_shift_reg(deserialization_factor-1);
|
|
elsif (tx_fastclk'event and (tx_fastclk = '1')) then
|
|
if (enable1_reg = '1') then
|
|
tx_shift_reg <= tx_parallel_load_reg;
|
|
else -- Shift data from shift register to tx_out
|
|
for x in deserialization_factor-1 downto 1 loop
|
|
tx_shift_reg(x) <= tx_shift_reg (x-1);
|
|
end loop;
|
|
end if;
|
|
|
|
-- registering enable1 signal
|
|
enable1_reg := tx_enable;
|
|
|
|
tx_parallel_load_reg <= tx_in;
|
|
end if;
|
|
end process FAST_CLOCK;
|
|
|
|
|
|
end behavior;
|
|
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : flexible_lvds_tx
|
|
--
|
|
-- Description : flexible lvds transmitter
|
|
--
|
|
-- Limitation : Only available to Cyclone and Cyclone II families.
|
|
--
|
|
-- Results Expected: Serialized output data.
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- LIBRARY USED----------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity flexible_lvds_tx is
|
|
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
number_of_channels : natural; -- Required parameter
|
|
deserialization_factor : natural; -- Required parameter
|
|
registered_input : string := "ON";
|
|
use_new_coreclk_ckt : boolean := false;
|
|
outclock_multiply_by : natural := 1;
|
|
outclock_divide_by : natural := 2;
|
|
outclock_duty_cycle : natural := 50;
|
|
use_self_generated_outclock : boolean := false );
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
--INPUT PORT DECLARATION
|
|
tx_in : in std_logic_vector(deserialization_factor*
|
|
number_of_channels -1 downto 0);
|
|
tx_fastclk : in std_logic;
|
|
tx_slowclk : in std_logic;
|
|
tx_regclk : in std_logic;
|
|
tx_data_reset : in std_logic;
|
|
pll_areset : in std_logic;
|
|
pll_outclock : in std_logic;
|
|
tx_locked : in std_logic;
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
tx_out : out std_logic_vector(number_of_channels-1 downto 0);
|
|
tx_outclock : out std_logic );
|
|
|
|
end flexible_lvds_tx;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of flexible_lvds_tx is
|
|
|
|
-- FUNCTION DECLARATION
|
|
function get_cntr_modulus(constant i_deserialization_factor : in natural) return natural is
|
|
begin
|
|
if (i_deserialization_factor rem 2 = 1) then
|
|
return i_deserialization_factor;
|
|
else
|
|
return i_deserialization_factor/2;
|
|
end if;
|
|
|
|
end get_cntr_modulus;
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant REGISTER_WIDTH : natural := deserialization_factor * number_of_channels;
|
|
constant ZEROS : std_logic_vector(number_of_channels-1 downto 0) := (OTHERS => '0');
|
|
constant LOAD_CNTR_MODULUS : natural := get_cntr_modulus(deserialization_factor);
|
|
|
|
-- TYPE DECLARATION
|
|
type CHANNEL_CNT is array (number_of_channels-1 downto 0) of integer;
|
|
type REG_ARRAY is array (deserialization_factor-1 downto 0) of std_logic_vector(number_of_channels -1 downto 0);
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal tx_reg : std_logic_vector(REGISTER_WIDTH-1 downto 0)
|
|
:= (others => '0');
|
|
signal tx_reg2 : std_logic_vector((REGISTER_WIDTH*2)-1 downto 0)
|
|
:= (others => '0');
|
|
signal tx_shift_reg : std_logic_vector(REGISTER_WIDTH-1 downto 0)
|
|
:= (others => '0');
|
|
signal tx_shift_reg2 : std_logic_vector((REGISTER_WIDTH*2)-1 downto 0)
|
|
:= (others => '0');
|
|
signal h_sync_a : std_logic_vector(REGISTER_WIDTH-1 downto 0)
|
|
:= (others => '0');
|
|
signal sync_b_reg : std_logic_vector((REGISTER_WIDTH*2)-1 downto 0)
|
|
:= (others => '0');
|
|
signal dataout_h : std_logic_vector(number_of_channels-1 downto 0)
|
|
:= (others => '0');
|
|
signal dataout_l : std_logic_vector(number_of_channels-1 downto 0)
|
|
:= (others => '0');
|
|
signal dataout_tmp : std_logic_vector(number_of_channels-1 downto 0)
|
|
:= (others => '0');
|
|
signal tx_ddio_out : std_logic_vector(number_of_channels-1 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal tx_in_int : std_logic_vector(REGISTER_WIDTH -1 downto 0)
|
|
:= (others => '0');
|
|
signal tx_in_int2 : std_logic_vector((REGISTER_WIDTH*2) -1 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal stage1_a : std_logic_vector((number_of_channels*2)-1 downto 0)
|
|
:= (others => '0');
|
|
signal stage1_b : std_logic_vector((number_of_channels*2)-1 downto 0)
|
|
:= (others => '0');
|
|
signal stage2 : std_logic_vector((number_of_channels*2)-1 downto 0)
|
|
:= (others => '0');
|
|
signal tx_reg_2ary : REG_ARRAY := (others => (others => '0'));
|
|
signal tx_slowclk_dly : std_logic;
|
|
signal tx_outclock_tmp : std_logic := '0';
|
|
signal start_sm_p2s : boolean := false;
|
|
|
|
signal loadcnt : natural := 0;
|
|
signal sm_p2s : natural := 0;
|
|
|
|
signal outclk_shift_l : std_logic_vector(deserialization_factor-1 downto 0)
|
|
:= (others => '0');
|
|
signal outclk_shift_h : std_logic_vector(deserialization_factor-1 downto 0)
|
|
:= (others => '0');
|
|
signal outclock_l : std_logic := '0';
|
|
signal outclock_h : std_logic := '0';
|
|
|
|
signal outclk_load_cntr : natural := 0;
|
|
signal sync_dffe : std_logic := '0';
|
|
signal load_enable : std_logic := '0';
|
|
signal load_cntr : natural := 0;
|
|
signal h_ff : natural := 0;
|
|
signal h_us_ff : natural := 0;
|
|
signal l_s_ff : natural := 0;
|
|
signal l_ff : natural := 0;
|
|
signal l_us_ff : natural := 0;
|
|
signal h_s_ff : natural := 0;
|
|
|
|
begin
|
|
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
tx_in_int <= tx_in when (registered_input = "OFF")
|
|
else tx_reg;
|
|
tx_in_int2 <= sync_b_reg when (registered_input = "OFF")
|
|
else tx_reg2;
|
|
tx_out <= tx_ddio_out;
|
|
tx_outclock <= tx_outclock_tmp when (use_self_generated_outclock = true)
|
|
else pll_outclock;
|
|
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
-- For each data channel, input data are separated into 2 data
|
|
-- stream which will be transmitted on different edge of input clock.
|
|
DDIO_OUT_RECEIVE : process(tx_fastclk, pll_areset, tx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or tx_data_reset = '1') then
|
|
dataout_h <= (others => '0');
|
|
dataout_l <= (others => '0');
|
|
dataout_tmp <= (others => '0');
|
|
elsif ((tx_fastclk = '1') and tx_fastclk'event) then
|
|
if ((deserialization_factor rem 2) = 0) then
|
|
for i in 0 to number_of_channels -1 loop
|
|
dataout_h(i) <= tx_shift_reg((i+1)*deserialization_factor-1);
|
|
dataout_l(i) <= tx_shift_reg((i+1)*deserialization_factor-2);
|
|
dataout_tmp(i) <= tx_shift_reg((i+1)*deserialization_factor-1);
|
|
end loop;
|
|
else
|
|
if (use_new_coreclk_ckt = false) then
|
|
for i in 0 to number_of_channels -1 loop
|
|
dataout_h(i) <= tx_shift_reg2((i+1)*2*deserialization_factor-1);
|
|
dataout_l(i) <= tx_shift_reg2((i+1)*2*deserialization_factor-2);
|
|
dataout_tmp(i) <= tx_shift_reg2((i+1)*2*deserialization_factor-1);
|
|
end loop;
|
|
else
|
|
dataout_h <= stage2(number_of_channels*2-1 downto number_of_channels);
|
|
dataout_l <= stage2(number_of_channels-1 downto 0);
|
|
dataout_tmp <= stage2(number_of_channels*2-1 downto number_of_channels);
|
|
end if;
|
|
end if;
|
|
elsif ((tx_fastclk = '0') and tx_fastclk'event) then
|
|
dataout_tmp <= dataout_l;
|
|
end if;
|
|
end process DDIO_OUT_RECEIVE;
|
|
|
|
-- Transmits data on both edges of the input clock.
|
|
DDIO_OUT_TRANSMIT : process (dataout_tmp)
|
|
begin
|
|
tx_ddio_out <= dataout_tmp;
|
|
end process DDIO_OUT_TRANSMIT;
|
|
|
|
-- Loading input data to shift register
|
|
SHIFTREG : process (tx_fastclk, pll_areset, tx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or tx_data_reset = '1') then
|
|
tx_shift_reg <= (others => '0');
|
|
tx_shift_reg2 <= (others => '0');
|
|
sm_p2s <= 0;
|
|
stage1_a <= (others => '0');
|
|
stage1_b <= (others => '0');
|
|
stage2 <= (others => '0');
|
|
tx_reg_2ary <= (others => (others => '0'));
|
|
elsif ((tx_fastclk = '1') and tx_fastclk'event) then
|
|
-- Implementation for even deserialization factor.
|
|
if ((deserialization_factor rem 2) = 0) then
|
|
|
|
if(load_enable = '1') then
|
|
tx_shift_reg <= tx_in_int;
|
|
else
|
|
for i in 0 to number_of_channels-1 loop
|
|
for x in deserialization_factor-1 downto 2 loop
|
|
tx_shift_reg(x + (i * deserialization_factor)) <=
|
|
tx_shift_reg (x-2 + (i * deserialization_factor));
|
|
end loop;
|
|
end loop;
|
|
end if;
|
|
else -- Implementation for odd deserialization factor.
|
|
if (use_new_coreclk_ckt = false) then
|
|
|
|
if(load_enable = '1') then
|
|
tx_shift_reg2 <= tx_in_int2;
|
|
else
|
|
for i in 0 to number_of_channels-1 loop
|
|
for x in deserialization_factor*2-1 downto 2 loop
|
|
tx_shift_reg2(x + (i * 2 * deserialization_factor)) <=
|
|
tx_shift_reg2 (x-2 + (i * 2 * deserialization_factor));
|
|
end loop;
|
|
end loop;
|
|
end if;
|
|
else
|
|
-- state machine counter
|
|
if (((sm_p2s = 0) and (start_sm_p2s = true)) or (sm_p2s /= 0)) then
|
|
sm_p2s <= (sm_p2s + 1) rem deserialization_factor;
|
|
end if;
|
|
|
|
-- synchronization register
|
|
if (((sm_p2s = 0) and (start_sm_p2s = true)) or (sm_p2s = (deserialization_factor/2) + 1)) then
|
|
for i in 0 to number_of_channels -1 loop
|
|
for x in 0 to deserialization_factor-1 loop
|
|
tx_reg_2ary(x)(i) <= tx_in_int(i*deserialization_factor + x);
|
|
end loop;
|
|
end loop;
|
|
end if;
|
|
|
|
-- stage 1a register
|
|
if ((sm_p2s > 0) and (sm_p2s < deserialization_factor/2 +1)) then
|
|
stage1_a <= tx_reg_2ary(deserialization_factor - (2*sm_p2s) + 1) & tx_reg_2ary(deserialization_factor - (2*sm_p2s));
|
|
elsif (sm_p2s = deserialization_factor/2 + 1) then
|
|
stage1_a <= tx_reg_2ary(0) & ZEROS;
|
|
end if;
|
|
|
|
-- stage 1b register
|
|
if ((sm_p2s = 0) and (start_sm_p2s = true)) then
|
|
stage1_b <= tx_reg_2ary(1) & tx_reg_2ary(0);
|
|
elsif ((sm_p2s > (deserialization_factor /2) + 1) and (sm_p2s < deserialization_factor)) then
|
|
stage1_b <= tx_reg_2ary((deserialization_factor - sm_p2s)*2 + 1) & tx_reg_2ary((deserialization_factor - sm_p2s)*2);
|
|
end if;
|
|
|
|
-- stage 2 register
|
|
if ((sm_p2s > 1) and (sm_p2s < (deserialization_factor/2) +2)) then
|
|
stage2 <= stage1_a;
|
|
elsif (((sm_p2s = 0) and (start_sm_p2s = true)) or (sm_p2s = 1) or
|
|
((sm_p2s > (deserialization_factor/2) + 2) and (sm_p2s < deserialization_factor))) then
|
|
stage2 <= stage1_b;
|
|
elsif (sm_p2s = (deserialization_factor/2) + 2) then
|
|
stage2 <= stage1_a((number_of_channels*2)-1 downto number_of_channels) & tx_reg_2ary(deserialization_factor - 1);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process SHIFTREG;
|
|
|
|
process (tx_fastclk)
|
|
begin
|
|
if ((tx_fastclk = '1') and tx_fastclk'event) then
|
|
tx_slowclk_dly <= tx_slowclk;
|
|
end if;
|
|
end process;
|
|
|
|
process (tx_slowclk, tx_slowclk_dly)
|
|
begin
|
|
if ((tx_slowclk_dly = '0') and (tx_slowclk = '1')) then
|
|
start_sm_p2s <= true;
|
|
else
|
|
start_sm_p2s <= false;
|
|
end if;
|
|
end process;
|
|
|
|
-- loading data to synchronization register
|
|
SYNC_REG : process (tx_slowclk, pll_areset, tx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or tx_data_reset = '1') then
|
|
h_sync_a <= (others => '0');
|
|
sync_b_reg <= (others => '0');
|
|
elsif ((tx_slowclk = '1') and tx_slowclk'event) then
|
|
h_sync_a <= tx_in;
|
|
elsif ((tx_slowclk = '0') and tx_slowclk'event) then
|
|
for i in 0 to number_of_channels-1 loop
|
|
for x in (deserialization_factor-1) downto 0 loop
|
|
sync_b_reg(x + (((i * 2) + 1) * deserialization_factor)) <=
|
|
h_sync_a(x + (i * deserialization_factor));
|
|
sync_b_reg(x + (i * 2 * deserialization_factor)) <=
|
|
tx_in(x + (i * deserialization_factor));
|
|
end loop;
|
|
end loop;
|
|
end if;
|
|
end process SYNC_REG;
|
|
|
|
-- loading data to input register
|
|
IN_REG : process (tx_regclk, pll_areset, tx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or tx_data_reset = '1') then
|
|
tx_reg <= (others => '0');
|
|
tx_reg2 <= (others => '0');
|
|
elsif (tx_regclk'event and (tx_regclk = '1')) then
|
|
if (((deserialization_factor rem 2) = 0) or (use_new_coreclk_ckt = true)) then
|
|
tx_reg <= tx_in;
|
|
else
|
|
tx_reg2 <= sync_b_reg;
|
|
end if;
|
|
end if;
|
|
end process IN_REG;
|
|
|
|
-- generate outclock
|
|
process (tx_fastclk, pll_areset, tx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or tx_data_reset = '1') then
|
|
outclk_load_cntr <= 0;
|
|
elsif (tx_fastclk'event and (tx_fastclk = '1')) then
|
|
outclk_load_cntr <= (outclk_load_cntr + 1) rem deserialization_factor;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
process (pll_outclock, pll_areset, tx_data_reset)
|
|
variable outclk_data_l : std_logic_vector(9 downto 0)
|
|
:= (others => '0');
|
|
variable outclk_data_h : std_logic_vector(9 downto 0)
|
|
:= (others => '0');
|
|
variable init : boolean := true;
|
|
begin
|
|
if (init = true) then
|
|
|
|
if ((deserialization_factor rem 2 = 1) or
|
|
(((deserialization_factor = 6) or
|
|
(deserialization_factor = 10)) and
|
|
(outclock_multiply_by = 2) and
|
|
(outclock_divide_by = deserialization_factor))) then
|
|
if (outclock_multiply_by = 2) then
|
|
if (use_new_coreclk_ckt = true) then
|
|
case deserialization_factor is
|
|
when 5 => outclk_data_l := conv_std_logic_vector(22, 10);
|
|
outclk_data_h := conv_std_logic_vector(21, 10);
|
|
when 7 => outclk_data_l := conv_std_logic_vector(102, 10);
|
|
outclk_data_h := conv_std_logic_vector(108, 10);
|
|
when 9 => outclk_data_l := conv_std_logic_vector(206, 10);
|
|
outclk_data_h := conv_std_logic_vector(460, 10);
|
|
when 6 => outclk_data_l := conv_std_logic_vector(9, 10);
|
|
outclk_data_h := conv_std_logic_vector(27, 10);
|
|
when 10 => outclk_data_l := conv_std_logic_vector(99, 10);
|
|
outclk_data_h := conv_std_logic_vector(231, 10);
|
|
when others =>
|
|
outclk_data_l := (others => '0');
|
|
outclk_data_h := (others => '0');
|
|
end case;
|
|
else
|
|
case deserialization_factor is
|
|
when 5 => outclk_data_l := conv_std_logic_vector(13, 10);
|
|
outclk_data_h := conv_std_logic_vector(11, 10);
|
|
when 7 => outclk_data_l := conv_std_logic_vector(27, 10);
|
|
outclk_data_h := conv_std_logic_vector(51, 10);
|
|
when 9 => outclk_data_l := conv_std_logic_vector(115, 10);
|
|
outclk_data_h := conv_std_logic_vector(103, 10);
|
|
when 6 => outclk_data_l := conv_std_logic_vector(9, 10);
|
|
outclk_data_h := conv_std_logic_vector(27, 10);
|
|
when 10 => outclk_data_l := conv_std_logic_vector(99, 10);
|
|
outclk_data_h := conv_std_logic_vector(231, 10);
|
|
when others =>
|
|
outclk_data_l := (others => '0');
|
|
outclk_data_h := (others => '0');
|
|
end case;
|
|
end if;
|
|
else
|
|
if (outclock_duty_cycle /= 50) then
|
|
if (use_new_coreclk_ckt = true) then
|
|
case deserialization_factor is
|
|
when 5 => outclk_data_l := conv_std_logic_vector(25, 10);
|
|
outclk_data_h := conv_std_logic_vector(25, 10);
|
|
when 7 => outclk_data_l := conv_std_logic_vector(113, 10);
|
|
outclk_data_h := conv_std_logic_vector(113, 10);
|
|
when 9 => outclk_data_l := conv_std_logic_vector(124, 10);
|
|
outclk_data_h := conv_std_logic_vector(124, 10);
|
|
when others =>
|
|
outclk_data_l := (others => '0');
|
|
outclk_data_h := (others => '0');
|
|
end case;
|
|
else
|
|
case deserialization_factor is
|
|
when 5 => outclk_data_l := conv_std_logic_vector(28, 10);
|
|
outclk_data_h := conv_std_logic_vector(25, 10);
|
|
when 7 => outclk_data_l := conv_std_logic_vector(120, 10);
|
|
outclk_data_h := conv_std_logic_vector(113, 10);
|
|
when 9 => outclk_data_l := conv_std_logic_vector(31, 10);
|
|
outclk_data_h := conv_std_logic_vector(31, 10);
|
|
when others =>
|
|
outclk_data_l := (others => '0');
|
|
outclk_data_h := (others => '0');
|
|
end case;
|
|
end if;
|
|
else
|
|
if (use_new_coreclk_ckt = true) then
|
|
case deserialization_factor is
|
|
when 5 => outclk_data_l := conv_std_logic_vector(24, 10);
|
|
outclk_data_h := conv_std_logic_vector(25, 10);
|
|
when 7 => outclk_data_l := conv_std_logic_vector(112, 10);
|
|
outclk_data_h := conv_std_logic_vector(113, 10);
|
|
when 9 => outclk_data_l := conv_std_logic_vector(60, 10);
|
|
outclk_data_h := conv_std_logic_vector(124, 10);
|
|
when 6 => outclk_data_l := conv_std_logic_vector(54, 10);
|
|
outclk_data_h := conv_std_logic_vector(36, 10);
|
|
when 10 => outclk_data_l := conv_std_logic_vector(924, 10);
|
|
outclk_data_h := conv_std_logic_vector(792, 10);
|
|
when others =>
|
|
outclk_data_l := (others => '0');
|
|
outclk_data_h := (others => '0');
|
|
end case;
|
|
else
|
|
case deserialization_factor is
|
|
when 5 => outclk_data_l := conv_std_logic_vector(28, 10);
|
|
outclk_data_h := conv_std_logic_vector(24, 10);
|
|
when 7 => outclk_data_l := conv_std_logic_vector(120, 10);
|
|
outclk_data_h := conv_std_logic_vector(112, 10);
|
|
when 9 => outclk_data_l := conv_std_logic_vector(15, 10);
|
|
outclk_data_h := conv_std_logic_vector(31, 10);
|
|
when 6 => outclk_data_l := conv_std_logic_vector(54, 10);
|
|
outclk_data_h := conv_std_logic_vector(36, 10);
|
|
when 10 => outclk_data_l := conv_std_logic_vector(924, 10);
|
|
outclk_data_h := conv_std_logic_vector(792, 10);
|
|
when others =>
|
|
outclk_data_l := (others => '0');
|
|
outclk_data_h := (others => '0');
|
|
end case;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else
|
|
if (deserialization_factor = 4) then
|
|
case outclock_divide_by is
|
|
when 2 => outclk_data_l := conv_std_logic_vector(5, 10);
|
|
when 4 => outclk_data_l := conv_std_logic_vector(12, 10);
|
|
when others => outclk_data_l := (others => '0');
|
|
end case;
|
|
elsif (deserialization_factor = 6) then
|
|
case outclock_divide_by is
|
|
when 2 => outclk_data_l := conv_std_logic_vector(42, 10);
|
|
when 6 => outclk_data_l := conv_std_logic_vector(56, 10);
|
|
when others => outclk_data_l := (others => '0');
|
|
end case;
|
|
elsif (deserialization_factor = 8) then
|
|
case outclock_divide_by is
|
|
when 2 => outclk_data_l := conv_std_logic_vector(170, 10);
|
|
when 4 => outclk_data_l := conv_std_logic_vector(51, 10);
|
|
when 8 => outclk_data_l := conv_std_logic_vector(240, 10);
|
|
when others => outclk_data_l := (others => '0');
|
|
end case;
|
|
elsif (deserialization_factor = 10) then
|
|
case outclock_divide_by is
|
|
when 2 => outclk_data_l := conv_std_logic_vector(682, 10);
|
|
when 10 => outclk_data_l := conv_std_logic_vector(992, 10);
|
|
when others => outclk_data_l := (others => '0');
|
|
end case;
|
|
elsif (deserialization_factor = 5) then
|
|
if (outclock_divide_by = 5) then
|
|
outclk_data_l := conv_std_logic_vector(19, 10);
|
|
else
|
|
outclk_data_l := (others => '0');
|
|
end if;
|
|
elsif (deserialization_factor = 7) then
|
|
if (outclock_divide_by = 7) then
|
|
outclk_data_l := conv_std_logic_vector(120, 10);
|
|
else
|
|
outclk_data_l := (others => '0');
|
|
end if;
|
|
elsif (deserialization_factor = 9) then
|
|
if (outclock_divide_by = 9) then
|
|
outclk_data_l := conv_std_logic_vector(391, 10);
|
|
else
|
|
outclk_data_l := (others => '0');
|
|
end if;
|
|
end if;
|
|
|
|
outclk_data_h := outclk_data_l;
|
|
end if;
|
|
init := false;
|
|
end if;
|
|
|
|
if (pll_areset = '1' or tx_data_reset = '1') then
|
|
outclk_shift_l <= (others => '0');
|
|
outclk_shift_h <= (others => '0');
|
|
elsif (pll_outclock'event and (pll_outclock = '1')) then
|
|
if (outclk_load_cntr = 0) then
|
|
outclk_shift_l <= outclk_data_l(deserialization_factor-1 downto 0);
|
|
outclk_shift_h <= outclk_data_h(deserialization_factor-1 downto 0);
|
|
else
|
|
outclk_shift_l <= ('0' & outclk_shift_l(deserialization_factor-1 downto 1));
|
|
outclk_shift_h <= ('0' & outclk_shift_h(deserialization_factor-1 downto 1));
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process (pll_outclock, pll_areset, tx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or tx_data_reset = '1') then
|
|
outclock_h <= '0';
|
|
outclock_l <= '0';
|
|
tx_outclock_tmp <= '0';
|
|
elsif (pll_outclock'event and (pll_outclock = '1')) then
|
|
if (outclock_divide_by = 1) then
|
|
outclock_h <= '1';
|
|
outclock_l <= '0';
|
|
tx_outclock_tmp <= '1';
|
|
else
|
|
outclock_h <= outclk_shift_h(0);
|
|
outclock_l <= outclk_shift_l(0);
|
|
tx_outclock_tmp <= outclk_shift_h(0);
|
|
end if;
|
|
elsif (pll_outclock'event and (pll_outclock = '0')) then
|
|
tx_outclock_tmp <= outclock_l;
|
|
end if;
|
|
end process;
|
|
|
|
-- new synchronization circuit to generate the load enable pulse
|
|
process (tx_slowclk)
|
|
begin
|
|
if (tx_slowclk'event and (tx_slowclk = '1')) then
|
|
sync_dffe <= not sync_dffe;
|
|
end if;
|
|
end process;
|
|
|
|
process (tx_fastclk, pll_areset, tx_data_reset)
|
|
begin
|
|
if (pll_areset = '1' or tx_data_reset = '1') then
|
|
load_cntr <= 0;
|
|
elsif (tx_fastclk'event and (tx_fastclk = '1')) then
|
|
if (sync_dffe ='1') then
|
|
load_cntr <= (load_cntr +1) rem LOAD_CNTR_MODULUS;
|
|
else
|
|
load_cntr <= (LOAD_CNTR_MODULUS + load_cntr - 1) rem LOAD_CNTR_MODULUS;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process (tx_fastclk)
|
|
begin
|
|
if (tx_fastclk'event and (tx_fastclk = '1')) then
|
|
if (sync_dffe = '1') then
|
|
h_ff <= load_cntr;
|
|
h_us_ff <= h_ff;
|
|
l_s_ff <= l_us_ff;
|
|
else
|
|
l_ff <= load_cntr;
|
|
l_us_ff <= l_ff;
|
|
h_s_ff <= h_us_ff;
|
|
end if;
|
|
|
|
if (((h_ff = h_s_ff) and (sync_dffe = '1')) or ((l_ff = l_s_ff) and (sync_dffe /= '1'))) then
|
|
load_enable <= '1';
|
|
else
|
|
load_enable <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
end behavior; -- flexible_lvds_tx
|
|
|
|
-- END OF ARCHITECTURE
|
|
|
|
|
|
-- START ENTITY HEADER ---------------------------------------------------------
|
|
--
|
|
-- Entity Name : altlvds_tx
|
|
--
|
|
-- Description : Low Voltage Differential Signaling (LVDS) transmitter
|
|
-- megafunction. The altlvds_tx megafunction implements a
|
|
-- serialization transmitter. LVDS is a high speed IO interface
|
|
-- that uses inputs without a reference voltage. LVDS uses two
|
|
-- wires carrying differential values to create a single
|
|
-- channel. These wires are connected to two pins on supported
|
|
-- device to create a single LVDS channel.
|
|
--
|
|
-- Limitations : Only available for Stratix,
|
|
-- Stratix GX, Stratix II, Cyclone and Cyclone II families.
|
|
--
|
|
--Results expected : output clock, serialized output data and pll locked signal.
|
|
|
|
-- END ENTITY HEADER -----------------------------------------------------------
|
|
|
|
|
|
-- LIBRARY USED-----------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
use work.MF_stratix_pll;
|
|
use work.MF_stratixii_pll;
|
|
use work.MF_stratixiii_pll;
|
|
use work.stratix_tx_outclk;
|
|
use work.stratixii_tx_outclk;
|
|
use work.flexible_lvds_tx;
|
|
use work.stratixv_local_clk_divider;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altlvds_tx is
|
|
generic (
|
|
-- Specifies the number of LVDS channels (required)
|
|
number_of_channels : natural;
|
|
|
|
-- Specifies the number of bits per channel (required)
|
|
deserialization_factor : natural := 4;
|
|
|
|
-- Indicates whether the tx_in[] and tx_outclock ports should be
|
|
-- registered. Choices for STRATIX are ON, OFF, TX_CLKIN or TX_CORECLK
|
|
registered_input : string := "ON";
|
|
|
|
-- "ON" means that sync_inclock is also used
|
|
-- (not used for Stratix and Stratix GX.)
|
|
multi_clock : string := "OFF";
|
|
|
|
-- Specifies the period of the input clock in ps (Required)
|
|
inclock_period : natural := 10000;
|
|
|
|
-- Specifies the period of the tx_outclock port as
|
|
-- [INCLOCK_PERIOD * OUTCLOCK_DIVIDE_BY]
|
|
outclock_divide_by : positive := 1;
|
|
|
|
-- The effective clock period used to sample output data
|
|
inclock_boost : natural := 0;
|
|
|
|
-- Aligns the Most Significant Bit(MSB) to the falling edge of the
|
|
-- clock instead of the rising edge
|
|
center_align_msb : string := "OFF";
|
|
|
|
-- Specifies the device family to be used
|
|
intended_device_family : string := "Stratix";
|
|
|
|
-- Specifies the data rate out of the PLL.
|
|
-- (required and only for Stratix and Stratix GX devices)
|
|
output_data_rate : natural := 0;
|
|
|
|
-- Specifies the alignment of the input data with respect to the
|
|
-- tx_inclock port. (required and only available for Stratix and
|
|
-- Stratix GX devices)
|
|
inclock_data_alignment : string := "EDGE_ALIGNED";
|
|
|
|
-- Specifies the alignment of the output data with respect to the
|
|
-- tx_outclock port. (required and only available for Stratix and
|
|
-- Stratix GX devices)
|
|
outclock_alignment : string := "EDGE_ALIGNED";
|
|
|
|
-- Specifies whether the compiler uses the same PLL for both the LVDS
|
|
-- receiver and the LVDS transmitter
|
|
common_rx_tx_pll : string := "ON";
|
|
|
|
outclock_resource : string := "AUTO";
|
|
|
|
use_external_pll : string := "OFF";
|
|
implement_in_les : STRING := "OFF";
|
|
preemphasis_setting : natural := 0;
|
|
vod_setting : natural := 0;
|
|
differential_drive : natural := 0;
|
|
outclock_multiply_by : natural := 1;
|
|
coreclock_divide_by : natural := 2;
|
|
outclock_duty_cycle : natural := 50;
|
|
inclock_phase_shift : integer := 0;
|
|
outclock_phase_shift : integer := 0;
|
|
use_no_phase_shift : string := "ON";
|
|
pll_self_reset_on_loss_lock : string := "OFF";
|
|
refclk_frequency : string := "UNUSED";
|
|
enable_clock_pin_mode : string := "UNUSED";
|
|
data_rate : string := "UNUSED";
|
|
lpm_type : string := "altlvds_tx";
|
|
lpm_hint : string := "UNUSED";
|
|
pll_compensation_mode : string := "AUTO";
|
|
|
|
-- Specifies whether the source of the input clock is from the PLL
|
|
clk_src_is_pll : string := "off" );
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
|
|
-- INPUT PORT DECLARATION
|
|
-- Input data (required)
|
|
tx_in : in std_logic_vector(deserialization_factor*
|
|
number_of_channels -1 downto 0);
|
|
|
|
-- Input clock (required)
|
|
tx_inclock : in std_logic := '0';
|
|
|
|
tx_syncclock : in std_logic := '0';
|
|
|
|
tx_enable : in std_logic := '1';
|
|
|
|
-- Optional clock for input registers (Required if "multi_clock"
|
|
-- parameters is turned on)
|
|
sync_inclock : in std_logic := '0';
|
|
|
|
-- Enable control for the LVDS PLL
|
|
tx_pll_enable : in std_logic := '1';
|
|
|
|
-- Asynchronously resets all counters to initial values (only for
|
|
--Stratix and Stratix GX devices)
|
|
pll_areset : in std_logic := '0';
|
|
|
|
tx_data_reset : in std_logic := '0';
|
|
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
-- Serialized data signal(required)
|
|
tx_out : out std_logic_vector(number_of_channels-1 downto 0)
|
|
:= (others => '0');
|
|
|
|
-- External reference clock
|
|
tx_outclock : out std_logic;
|
|
|
|
-- Output clock used to feed non-peripheral logic.
|
|
-- Only available for Stratix, and Stratix GX devices only.
|
|
tx_coreclock : out std_logic;
|
|
|
|
-- Gives the status of the LVDS PLL
|
|
-- (when the PLL is locked, this signal is VCC. GND otherwise)
|
|
tx_locked : out std_logic );
|
|
|
|
end altlvds_tx;
|
|
-- END OF ENTITY
|
|
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of altlvds_tx is
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant STRATIX_TX_STYLE : boolean := FEATURE_FAMILY_BASE_STRATIX(intended_device_family);
|
|
constant STRATIXII_TX_STYLE : boolean := FEATURE_FAMILY_BASE_STRATIXII(intended_device_family);
|
|
constant STRATIXIII_TX_STYLE : boolean := FEATURE_FAMILY_BASE_STRATIXIII(intended_device_family);
|
|
constant CYCLONE_TX_STYLE : boolean := FEATURE_FAMILY_BASE_CYCLONE(intended_device_family);
|
|
constant CYCLONEII_TX_STYLE : boolean := FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family);
|
|
constant CYCLONEIII_TX_STYLE : boolean := FEATURE_FAMILY_BASE_CYCLONEIII(intended_device_family);
|
|
constant MAXV_TX_STYLE : boolean := FEATURE_FAMILY_MAXV(intended_device_family);
|
|
constant FAMILY_HAS_FLEXIBLE_LVDS : boolean := FEATURE_FAMILY_HAS_FLEXIBLE_LVDS(intended_device_family) or
|
|
(((STRATIX_TX_STYLE = true) or (STRATIXII_TX_STYLE = true) or
|
|
(STRATIXIII_TX_STYLE = true)) and
|
|
(implement_in_les = "ON"));
|
|
constant FAMILY_HAS_STRATIX_STYLE_PLL : boolean := FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL(intended_device_family);
|
|
constant FAMILY_HAS_STRATIXII_STYLE_PLL : boolean := FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL(intended_device_family);
|
|
constant FAMILY_HAS_STRATIXIII_STYLE_PLL : boolean := FEATURE_FAMILY_USES_STRATIXIII_PLL(intended_device_family);
|
|
constant USE_NEW_CORECLK_CKT : boolean := ((deserialization_factor rem 2) = 1) and (coreclock_divide_by = 1);
|
|
constant USE_SELF_GENERATED_OUTCLOCK : boolean := not FEATURE_FAMILY_BASE_CYCLONE(intended_device_family);
|
|
|
|
-- FUNCTION DECLARATION
|
|
|
|
-- converts uppercase parameter values (e.g. "AUTO") to lowercase ("auto")
|
|
-- as expected by stratix_pll model
|
|
function alpha_tolower (given_string : string) return string is
|
|
-- VARIABLE DECLARATION
|
|
variable string_length : integer := given_string'length;
|
|
variable result_string : string(1 to 20) := " ";
|
|
|
|
begin
|
|
for i in 1 to string_length loop
|
|
case given_string(i) is
|
|
when 'A' => result_string(i) := 'a';
|
|
when 'B' => result_string(i) := 'b';
|
|
when 'C' => result_string(i) := 'c';
|
|
when 'D' => result_string(i) := 'd';
|
|
when 'E' => result_string(i) := 'e';
|
|
when 'F' => result_string(i) := 'f';
|
|
when 'G' => result_string(i) := 'g';
|
|
when 'H' => result_string(i) := 'h';
|
|
when 'I' => result_string(i) := 'i';
|
|
when 'J' => result_string(i) := 'j';
|
|
when 'K' => result_string(i) := 'k';
|
|
when 'L' => result_string(i) := 'l';
|
|
when 'M' => result_string(i) := 'm';
|
|
when 'N' => result_string(i) := 'n';
|
|
when 'O' => result_string(i) := 'o';
|
|
when 'P' => result_string(i) := 'p';
|
|
when 'Q' => result_string(i) := 'q';
|
|
when 'R' => result_string(i) := 'r';
|
|
when 'S' => result_string(i) := 's';
|
|
when 'T' => result_string(i) := 't';
|
|
when 'U' => result_string(i) := 'u';
|
|
when 'V' => result_string(i) := 'v';
|
|
when 'W' => result_string(i) := 'w';
|
|
when 'X' => result_string(i) := 'x';
|
|
when 'Y' => result_string(i) := 'y';
|
|
when 'Z' => result_string(i) := 'z';
|
|
when others => result_string(i) := given_string(i);
|
|
end case;
|
|
end loop;
|
|
|
|
return (result_string(1 to string_length));
|
|
end;
|
|
|
|
-- M value for stratix/stratix II/Cyclone/Cyclone II PLL
|
|
function pll_m_value(constant i_output_data_rate,
|
|
i_inclock_period : in natural) return natural is
|
|
variable i_pll_m_value : natural;
|
|
begin
|
|
i_pll_m_value := (((i_output_data_rate * i_inclock_period)
|
|
+ (5* 100000)) / 1000000);
|
|
|
|
return i_pll_m_value;
|
|
|
|
end pll_m_value;
|
|
|
|
-- D value for Stratix/Stratix II/Cyclone/Cyclone II PLL
|
|
function pll_d_value(constant i_output_data_rate,
|
|
i_inclock_period : in natural) return natural is
|
|
variable i_pll_d_value : natural;
|
|
begin
|
|
if ((i_output_data_rate /= 0) and (i_inclock_period /= 0)) then
|
|
if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
i_pll_d_value := 2;
|
|
else
|
|
i_pll_d_value := 1;
|
|
end if;
|
|
else
|
|
i_pll_d_value := 1;
|
|
end if;
|
|
|
|
return i_pll_d_value;
|
|
end pll_d_value;
|
|
|
|
-- clock_boost_calc calculates the multiply_by factor for the PLL clocks
|
|
-- used by LVDS_TX
|
|
function clock_boost_calc (constant i_output_data_rate,
|
|
i_inclock_period,
|
|
i_deserialization_factor,
|
|
i_inclock_boost : in natural) return natural is
|
|
variable i_input_clock_boost: natural := 1;
|
|
|
|
begin
|
|
if ((i_output_data_rate /= 0) and (i_inclock_period /= 0)) then
|
|
i_input_clock_boost := pll_m_value (i_output_data_rate,
|
|
i_inclock_period);
|
|
else
|
|
if (inclock_boost = 0) then
|
|
i_input_clock_boost := i_deserialization_factor;
|
|
else
|
|
i_input_clock_boost := i_inclock_boost;
|
|
end if;
|
|
end if;
|
|
|
|
return i_input_clock_boost;
|
|
|
|
end clock_boost_calc;
|
|
|
|
|
|
-- int_to_str converts an integer to a string. This is mainly used for
|
|
-- converting the calculated phase shift to a string as required by altpll
|
|
function int_to_str(constant value : integer ) return string is
|
|
variable ivalue : integer := 0;
|
|
variable index : integer := 0;
|
|
variable strlen : integer := 0;
|
|
variable digit : integer := 0;
|
|
variable str : string(1 to 8) := "00000000";
|
|
begin
|
|
|
|
ivalue := abs(value);
|
|
strlen := 0;
|
|
|
|
while (ivalue > 0) loop
|
|
ivalue := ivalue/10;
|
|
strlen := strlen + 1;
|
|
end loop;
|
|
|
|
if (strlen = 0) then
|
|
strlen := 1;
|
|
end if;
|
|
|
|
ivalue := abs(value);
|
|
index := strlen;
|
|
|
|
while (ivalue > 0) loop
|
|
digit := ivalue mod 10;
|
|
ivalue := ivalue / 10;
|
|
|
|
case digit is
|
|
when 0 => str(index) := '0';
|
|
when 1 => str(index) := '1';
|
|
when 2 => str(index) := '2';
|
|
when 3 => str(index) := '3';
|
|
when 4 => str(index) := '4';
|
|
when 5 => str(index) := '5';
|
|
when 6 => str(index) := '6';
|
|
when 7 => str(index) := '7';
|
|
when 8 => str(index) := '8';
|
|
when 9 => str(index) := '9';
|
|
when others => ASSERT FALSE
|
|
REPORT "Illegal number!"
|
|
SEVERITY ERROR;
|
|
end case;
|
|
|
|
index := index - 1;
|
|
end loop;
|
|
|
|
if (value < 0) then
|
|
return ('-'& str(1 to strlen));
|
|
else
|
|
return str(1 to strlen);
|
|
end if;
|
|
end int_to_str;
|
|
|
|
-- get_phase_delay calculates the phase shift for each PLL clock as
|
|
-- determined by the INCLOCK_DATA_ALIGNMENT parameter
|
|
function get_phase_delay (constant i_phase_delay : in string) return integer is
|
|
variable my_phase : integer := 0;
|
|
variable x : integer := 0;
|
|
variable int_delay : integer := 0;
|
|
begin
|
|
|
|
if (i_phase_delay = "UNUSED") then
|
|
int_delay := inclock_phase_shift;
|
|
else
|
|
-- returns the delay in ps
|
|
-- (<alignment degree> * inclock period / 360 degress)
|
|
if (i_phase_delay = "EDGE_ALIGNED") then
|
|
my_phase := 0;
|
|
-- CENTER_ALIGNED means 180 degrees
|
|
elsif (i_phase_delay = "CENTER_ALIGNED") then
|
|
my_phase := (180 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "45_DEGREES") then
|
|
my_phase := (45 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "90_DEGREES") then
|
|
my_phase := (90 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "135_DEGREES") then
|
|
my_phase := (135 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "180_DEGREES") then
|
|
my_phase := (180 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "225_DEGREES") then
|
|
my_phase := (225 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "270_DEGREES") then
|
|
my_phase := (270 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "315_DEGREES") then
|
|
my_phase := (315 * inclock_period) / 360;
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "Invalid clock data alignment. Using 'EDGE_ALIGNED' instead"
|
|
SEVERITY WARNING;
|
|
my_phase := 0;
|
|
end if;
|
|
|
|
-- add 1 to "round up" the calculation result
|
|
my_phase := my_phase + 1;
|
|
|
|
-- phase shift = ( <alignment degree> * inclock_period / 360 ) / (fast
|
|
-- clock multiply_by factor)
|
|
-- in other words, the data alignment phase shift is a percentage of the
|
|
-- fast clock period
|
|
int_delay := my_phase / clock_boost_calc(output_data_rate, inclock_period,
|
|
deserialization_factor, inclock_boost);
|
|
|
|
-- add 1 to "round up" the calculation result
|
|
int_delay := int_delay + 1;
|
|
end if;
|
|
|
|
return (int_delay);
|
|
|
|
end get_phase_delay;
|
|
|
|
-- get_stxii_inclock_phase_delay returns the adjusted input clock phase shift for Stratix II pll.
|
|
function get_stxii_inclock_phase_delay (constant i_phase_delay : in string)
|
|
return integer is
|
|
variable my_phase : integer := 0;
|
|
begin
|
|
|
|
my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (2 * clock_boost_calc (output_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
|
|
return (my_phase);
|
|
|
|
end get_stxii_inclock_phase_delay;
|
|
|
|
-- get_outclock_phase_delay calculates the phase shift for the outclock port
|
|
-- as determined by the OUTCLOCK_ALIGNMENT parameter
|
|
function get_outclock_phase_delay (constant i_phase_delay : in string)
|
|
return integer is
|
|
variable my_phase : integer := 0;
|
|
variable x : integer := 0;
|
|
variable int_delay : integer := 0;
|
|
begin
|
|
|
|
if (i_phase_delay = "UNUSED") then
|
|
my_phase := outclock_phase_shift;
|
|
else
|
|
-- returns the delay in ps
|
|
-- (<alignment degree> * inclock period / 360 degress )
|
|
if (i_phase_delay = "EDGE_ALIGNED") then
|
|
my_phase := 0;
|
|
-- CENTER_ALIGNED means 180 degrees
|
|
elsif (i_phase_delay = "CENTER_ALIGNED") then
|
|
my_phase := (180 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "45_DEGREES") then
|
|
my_phase := (45 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "90_DEGREES") then
|
|
my_phase := (90 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "135_DEGREES") then
|
|
my_phase := (135 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "180_DEGREES") then
|
|
my_phase := (180 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "225_DEGREES") then
|
|
my_phase := (225 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "270_DEGREES") then
|
|
my_phase := (270 * inclock_period) / 360;
|
|
elsif (i_phase_delay = "315_DEGREES") then
|
|
my_phase := (315 * inclock_period) / 360;
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "Invalid outclock alignment. Using 'EDGE_ALIGNED' instead"
|
|
SEVERITY WARNING;
|
|
my_phase := 0;
|
|
end if;
|
|
|
|
-- add 1 to "round up" calculation result
|
|
my_phase := my_phase + 1;
|
|
|
|
my_phase := my_phase / clock_boost_calc (output_data_rate, inclock_period,
|
|
deserialization_factor, inclock_boost);
|
|
|
|
-- add 1 to "round up" calculation result
|
|
my_phase := my_phase + 1;
|
|
|
|
end if;
|
|
|
|
if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
int_delay := my_phase;
|
|
else
|
|
int_delay := my_phase + get_phase_delay(inclock_data_alignment);
|
|
end if;
|
|
|
|
return int_delay;
|
|
|
|
end get_outclock_phase_delay;
|
|
|
|
|
|
-- Calculates the phase shift of the fastclk that feeds the
|
|
-- stratix_tx_outclk or stratixii_tx_outclk.
|
|
function get_lvds_outclock_phase_delay (constant i_phase_delay : in string;
|
|
constant i_outclock_divide_by : in positive;
|
|
constant i_intended_device_family : in string)
|
|
return integer is
|
|
variable my_phase : integer := 0;
|
|
begin
|
|
if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
my_phase := get_outclock_phase_delay(i_phase_delay);
|
|
elsif ((i_outclock_divide_by = 1) or
|
|
(i_phase_delay = "45_DEGREES") or
|
|
(i_phase_delay = "90_DEGREES") or
|
|
(i_phase_delay = "135_DEGREES")) then
|
|
my_phase := get_outclock_phase_delay(i_phase_delay);
|
|
elsif (outclock_alignment = "UNUSED") then
|
|
if (outclock_phase_shift >= get_phase_delay("180_DEGREES")) then
|
|
my_phase := get_outclock_phase_delay(i_phase_delay) - get_phase_delay("180_DEGREES");
|
|
else
|
|
my_phase := get_outclock_phase_delay(i_phase_delay);
|
|
end if;
|
|
elsif ((i_phase_delay = "180_DEGREES") or
|
|
(i_phase_delay = "CENTER_ALIGNED")) then
|
|
my_phase := get_phase_delay(inclock_data_alignment);
|
|
elsif (i_phase_delay = "225_DEGREES") then
|
|
my_phase := get_outclock_phase_delay("45_DEGREES");
|
|
elsif (i_phase_delay = "270_DEGREES") then
|
|
my_phase := get_outclock_phase_delay("90_DEGREES");
|
|
elsif (i_phase_delay = "315_DEGREES") then
|
|
my_phase := get_outclock_phase_delay("135_DEGREES");
|
|
else
|
|
my_phase := get_phase_delay(inclock_data_alignment);
|
|
end if;
|
|
|
|
if (FEATURE_FAMILY_STRATIXII(i_intended_device_family) and (implement_in_les = "OFF")) then
|
|
my_phase := my_phase - (inclock_period / ( 2 * clock_boost_calc (output_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
end if;
|
|
|
|
return my_phase;
|
|
end get_lvds_outclock_phase_delay;
|
|
|
|
-- get clk1_multiply_by value for PLL (for flexible lvds)
|
|
function get_flvds_clk1_multiply_by ( constant i_deserialization_factor : in natural;
|
|
constant i_outclock_multiply_by : in natural;
|
|
constant i_outclock_divide_by : in natural
|
|
) return natural is
|
|
variable clk1_mult_by : natural := 0;
|
|
begin
|
|
if (CYCLONE_TX_STYLE = false) then
|
|
clk1_mult_by := clock_boost_calc (output_data_rate, inclock_period,
|
|
deserialization_factor, inclock_boost);
|
|
elsif ( ( ((i_deserialization_factor rem 2) = 1) or
|
|
(i_deserialization_factor = 6) or
|
|
(i_deserialization_factor = 10) ) and (outclock_multiply_by = 2) and
|
|
(outclock_divide_by = deserialization_factor)) then
|
|
clk1_mult_by := clock_boost_calc (output_data_rate, inclock_period,
|
|
deserialization_factor, inclock_boost) * 2;
|
|
else
|
|
clk1_mult_by := clock_boost_calc (output_data_rate, inclock_period,
|
|
deserialization_factor, inclock_boost);
|
|
end if;
|
|
|
|
return clk1_mult_by;
|
|
|
|
end get_flvds_clk1_multiply_by;
|
|
|
|
-- get clk2_multiply_by value for PLL (for flexible lvds)
|
|
function get_flvds_clk2_multiply_by ( constant i_deserialization_factor : in natural) return natural is
|
|
variable clk2_mult_by : natural := 0;
|
|
begin
|
|
if (((i_deserialization_factor rem 2) = 0) or (USE_NEW_CORECLK_CKT = true)) then
|
|
clk2_mult_by := clock_boost_calc (output_data_rate, inclock_period,
|
|
deserialization_factor, inclock_boost) * 2;
|
|
else
|
|
clk2_mult_by := clock_boost_calc (output_data_rate, inclock_period,
|
|
deserialization_factor, inclock_boost);
|
|
end if;
|
|
|
|
return clk2_mult_by;
|
|
|
|
end get_flvds_clk2_multiply_by;
|
|
|
|
-- get clk1_divide_by value for PLL (for flexible lvds)
|
|
function get_flvds_clk1_divide_by ( constant i_outclock_divide_by : in natural) return natural is
|
|
variable clk1_div_by : natural := 0;
|
|
begin
|
|
if (CYCLONE_TX_STYLE = false) then
|
|
clk1_div_by := pll_d_value (output_data_rate, inclock_period);
|
|
else
|
|
clk1_div_by := i_outclock_divide_by * pll_d_value (output_data_rate, inclock_period);
|
|
end if;
|
|
|
|
return clk1_div_by;
|
|
|
|
end get_flvds_clk1_divide_by;
|
|
|
|
-- get clk2_divide_by value for PLL (for flexible lvds)
|
|
function get_flvds_clk2_divide_by ( constant i_deserialization_factor : in natural) return natural is
|
|
variable clk2_div_by : natural := 0;
|
|
begin
|
|
clk2_div_by := i_deserialization_factor * pll_d_value (output_data_rate,
|
|
inclock_period);
|
|
|
|
return clk2_div_by;
|
|
|
|
end get_flvds_clk2_divide_by;
|
|
|
|
--- get pll_type for PLL (for flexible lvds)
|
|
function get_flvds_pll_type ( constant i_inclock_alignment : in string) return string is
|
|
begin
|
|
if (i_inclock_alignment = "UNUSED") then
|
|
return "auto";
|
|
else
|
|
return "flvds";
|
|
end if;
|
|
|
|
end get_flvds_pll_type;
|
|
|
|
--- get phase delay in ps for cyclone ii and stratix II in LE mode ---
|
|
function get_stxii_le_phase_delay (constant i_phase_delay : in string) return integer is
|
|
variable my_phase : integer := 0;
|
|
begin
|
|
if (use_no_phase_shift = "OFF") then
|
|
my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(output_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
else
|
|
my_phase := get_phase_delay(i_phase_delay);
|
|
end if;
|
|
|
|
return my_phase;
|
|
|
|
end get_stxii_le_phase_delay;
|
|
|
|
--- get phase delay in ps for stratix III in LE mode ---
|
|
function get_stxiii_le_phase_delay (constant i_phase_delay : in string) return integer is
|
|
variable my_phase : integer := 0;
|
|
begin
|
|
if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
|
|
my_phase := get_phase_delay(i_phase_delay);
|
|
else
|
|
my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(output_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
end if;
|
|
return my_phase;
|
|
|
|
end get_stxiii_le_phase_delay;
|
|
|
|
--- get outclock phase delay in ps for cyclone ii and stratix II in LE mode ---
|
|
function get_stxii_le_outclock_phase_delay (constant i_phase_delay : in string) return integer is
|
|
variable my_phase : integer := 0;
|
|
begin
|
|
if (use_no_phase_shift = "OFF") then
|
|
my_phase := get_outclock_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(output_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
else
|
|
my_phase := get_outclock_phase_delay(i_phase_delay);
|
|
end if;
|
|
|
|
return my_phase;
|
|
|
|
end get_stxii_le_outclock_phase_delay;
|
|
|
|
--- get outclock phase delay in ps for stratix III in LE mode ---
|
|
function get_stxiii_le_outclock_phase_delay (constant i_phase_delay : in string) return integer is
|
|
variable my_phase : integer := 0;
|
|
begin
|
|
if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
|
|
my_phase := get_outclock_phase_delay(i_phase_delay);
|
|
else
|
|
my_phase := get_outclock_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(output_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
end if;
|
|
return my_phase;
|
|
|
|
end get_stxiii_le_outclock_phase_delay;
|
|
|
|
--- get phase_shift value for the clock that acts as enable signal (for StratixIII lvds)
|
|
function get_clk_ena_phase_shift ( constant i_phase_shift : in string) return string is
|
|
variable fast_clk_ena_phase_shift : integer := 0;
|
|
begin
|
|
|
|
fast_clk_ena_phase_shift := (deserialization_factor*2-3) * (inclock_period/(2*clock_boost_calc(output_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
|
|
return int_to_str(get_stxii_inclock_phase_delay(i_phase_shift) + fast_clk_ena_phase_shift);
|
|
|
|
end get_clk_ena_phase_shift;
|
|
|
|
--- get phase_shift value for the clock that acts as enable signal for outclock channel (for StratixIII lvds)
|
|
function get_outclk_ena_phase_shift ( constant i_phase_shift : in string) return string is
|
|
variable fast_clk_ena_phase_shift : integer := 0;
|
|
begin
|
|
|
|
fast_clk_ena_phase_shift := (deserialization_factor*2-3) * (inclock_period/(2*clock_boost_calc(output_data_rate,
|
|
inclock_period, deserialization_factor, inclock_boost)));
|
|
|
|
return int_to_str(get_lvds_outclock_phase_delay(i_phase_shift, outclock_divide_by,
|
|
intended_device_family) + fast_clk_ena_phase_shift);
|
|
|
|
end get_outclk_ena_phase_shift;
|
|
-- CONSTANT DECLARATION
|
|
|
|
-- these constants are PLL parameters calculated from the altlvds_tx
|
|
-- parameters given
|
|
constant PHASE_INCLOCK : string
|
|
:= int_to_str(get_phase_delay(inclock_data_alignment));
|
|
|
|
constant STXII_PHASE_INCLOCK : string
|
|
:= int_to_str(get_stxii_inclock_phase_delay(inclock_data_alignment));
|
|
|
|
constant PHASE_OUTCLOCK : string
|
|
:= int_to_str(get_lvds_outclock_phase_delay(outclock_alignment, outclock_divide_by,
|
|
intended_device_family));
|
|
|
|
constant INT_CLOCK_BOOST : natural
|
|
:= clock_boost_calc(output_data_rate, inclock_period,
|
|
deserialization_factor, inclock_boost);
|
|
|
|
constant REGISTER_WIDTH : natural
|
|
:= deserialization_factor * number_of_channels;
|
|
|
|
constant FLVDS_CLK1_MUL : natural := get_flvds_clk1_multiply_by(deserialization_factor,
|
|
outclock_multiply_by, outclock_divide_by);
|
|
constant FLVDS_CLK2_MUL : natural := get_flvds_clk2_multiply_by(deserialization_factor);
|
|
|
|
constant FLVDS_CLK0_DIV : natural := pll_d_value(output_data_rate, inclock_period);
|
|
constant FLVDS_CLK1_DIV : natural := get_flvds_clk1_divide_by(outclock_divide_by);
|
|
constant FLVDS_CLK2_DIV : natural := get_flvds_clk2_divide_by(deserialization_factor);
|
|
constant FLVDS_PLL_TYPE : string := get_flvds_pll_type(inclock_data_alignment);
|
|
|
|
constant STXII_LE_PHASE_INCLOCK : string := int_to_str(get_stxii_le_phase_delay(inclock_data_alignment));
|
|
constant STXII_LE_PHASE_OUTCLOCK : string := int_to_str(get_stxii_le_outclock_phase_delay(outclock_alignment));
|
|
|
|
constant STXIII_LE_PHASE_INCLOCK : string := int_to_str(get_stxiii_le_phase_delay(inclock_data_alignment));
|
|
constant STXIII_LE_PHASE_OUTCLOCK : string := int_to_str(get_stxiii_le_outclock_phase_delay(outclock_alignment));
|
|
|
|
|
|
constant CLK_ENA_PHASE_SHIFT : string := get_clk_ena_phase_shift(inclock_data_alignment);
|
|
constant OUTCLK_ENA_PHASE_SHIFT : string := get_outclk_ena_phase_shift(outclock_alignment);
|
|
|
|
constant BYPASS_NEEDED : boolean := (outclock_divide_by = 1);
|
|
|
|
constant INVERT_CLOCK_NEEDED : boolean := ((outclock_alignment = "180_DEGREES") or
|
|
(outclock_alignment = "CENTER_ALIGNED")) and (use_external_pll = "ON");
|
|
|
|
constant FALLING_CLOCK_EDGE_NEEDED : boolean := (outclock_phase_shift >= get_phase_delay("180_DEGREES")) or
|
|
(outclock_alignment = "180_DEGREES") or
|
|
(outclock_alignment = "CENTER_ALIGNED") or
|
|
(outclock_alignment = "225_DEGREES") or
|
|
(outclock_alignment = "270_DEGREES") or
|
|
(outclock_alignment = "315_DEGREES");
|
|
|
|
-- SIGNAL DECLARATION
|
|
|
|
-- registers
|
|
signal tx_in_reg : std_logic_vector(REGISTER_WIDTH -1 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal tx_in_int : std_logic_vector(REGISTER_WIDTH -1 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal tx_parallel_load_reg : std_logic_vector(REGISTER_WIDTH -1 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal dataout_l : std_logic_vector(number_of_channels -1 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal dataout_h : std_logic_vector(number_of_channels -1 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal tx_ddio_out : std_logic_vector(number_of_channels -1 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal tx_out_stratix : std_logic_vector(number_of_channels -1 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal flvds_dataout : std_logic_vector(number_of_channels -1 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal stx_phase_shift_txdata : std_logic_vector(9 downto 0)
|
|
:= (others => '0');
|
|
|
|
signal phase_shift_txdata : std_logic_vector(9 downto 0)
|
|
:= (others => '0');
|
|
|
|
-- clock signals
|
|
signal tx_fastclk : std_logic; -- fast clock
|
|
signal tx_slowclk : std_logic; -- slow clock
|
|
signal tx_pll_clk0 : std_logic; -- PLL clk0 output
|
|
signal tx_pll_clk1 : std_logic; -- PLL clk1 output
|
|
signal tx_pll_clk2 : std_logic; -- PLL clk2 output
|
|
signal tx_pll_clk3 : std_logic; -- PLL clk3 output
|
|
signal tx_pll_clk4 : std_logic; -- PLL clk4 output
|
|
signal tx_reg_clk : std_logic; -- clock for sync register
|
|
signal tx_coreclk_int : std_logic;
|
|
signal tx_pll_sclkout : std_logic_vector (1 downto 0)
|
|
:= (others => '0'); -- PLL serial clk output
|
|
|
|
signal stratix_inclock : std_logic
|
|
:= '0';
|
|
|
|
signal stratixii_inclock : std_logic
|
|
:= '0';
|
|
|
|
signal stratix_outclock : std_logic
|
|
:= '0';
|
|
|
|
signal stratixii_outclock : std_logic
|
|
:= '0';
|
|
|
|
signal flvds_fastclk : std_logic
|
|
:= '0';
|
|
|
|
signal flvds_slowclk : std_logic
|
|
:= '0';
|
|
|
|
signal flvds_outclock : std_logic
|
|
:= '0';
|
|
|
|
signal flvds_pll_outclock : std_logic
|
|
:= '0';
|
|
|
|
|
|
signal stratixiii_enable0 : std_logic
|
|
:= '0';
|
|
|
|
signal stratixiii_enable1 : std_logic
|
|
:= '0';
|
|
|
|
-- PLL locked signal
|
|
signal tx_locked_int : std_logic;
|
|
signal pll_lock_sync : std_logic := '1';
|
|
|
|
|
|
-- constant signals
|
|
signal temp_zero : std_logic := '0';
|
|
signal temp_high : std_logic_vector (5 downto 0)
|
|
:= (others => '1');
|
|
|
|
signal temp_clk : std_logic_vector (6 downto 0)
|
|
:= (others => '0');
|
|
|
|
-- load enable signals for Stratix, Stratix GX and Stratix II
|
|
signal tx_pll_enable0 : std_logic
|
|
:= '0';
|
|
|
|
signal tx_pll_enable1 : std_logic
|
|
:= '0';
|
|
|
|
signal enable0 : std_logic
|
|
:= '0';
|
|
|
|
signal enable0_reg : std_logic
|
|
:= '0';
|
|
|
|
signal enable0_pipe : std_logic
|
|
:= '0';
|
|
|
|
signal enable0_neg : std_logic
|
|
:= '0';
|
|
|
|
signal stratix_enable : std_logic
|
|
:= '0';
|
|
|
|
signal stratixii_enable : std_logic
|
|
:= '0';
|
|
|
|
signal local_clk_div_lloaden : std_logic
|
|
:= '0';
|
|
|
|
|
|
-- COMPONENT DECLARATION
|
|
-- PLL for Stratix and Stratix GX
|
|
component MF_stratix_pll
|
|
generic (
|
|
pll_type : string := "lvds";
|
|
inclk0_input_frequency : positive ; --Required
|
|
valid_lock_multiplier : integer := 1;
|
|
simulation_type : string := "functional";
|
|
clk0_multiply_by : positive := 1;
|
|
clk0_divide_by : positive := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk1_multiply_by : positive := 1;
|
|
clk1_divide_by : positive := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_duty_cycle : natural := 50;
|
|
clk2_multiply_by : positive := 1;
|
|
clk2_divide_by : positive := 1;
|
|
clk2_phase_shift : string := "0";
|
|
family_name : string := "Stratix";
|
|
m : integer := 0 );
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (others => '0');
|
|
fbin : in std_logic := '1';
|
|
ena : in std_logic := '1';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
clkena : in std_logic_vector(5 downto 0) := (others => '1');
|
|
extclkena : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
|
|
scanaclr : in std_logic := '0';
|
|
scandata : in std_logic := '0';
|
|
scanclk : in std_logic := '0';
|
|
comparator : in std_logic := '0';
|
|
clk : out std_logic_vector(5 downto 0);
|
|
locked : out std_logic;
|
|
enable0 : out std_logic;
|
|
enable1 : out std_logic );
|
|
end component; -- MF_stratix_pll
|
|
|
|
-- PLL for Stratix II
|
|
component MF_stratixii_pll
|
|
generic (
|
|
pll_type : string := "lvds";
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
inclk0_input_frequency : positive ; --Required
|
|
simulation_type : string := "functional";
|
|
clk0_multiply_by : positive := 1;
|
|
clk0_divide_by : positive := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk1_multiply_by : positive := 1;
|
|
clk1_divide_by : positive := 1;
|
|
clk1_phase_shift : string := "0";
|
|
clk1_duty_cycle : natural := 50;
|
|
clk2_multiply_by : positive := 1;
|
|
clk2_divide_by : positive := 1;
|
|
clk2_phase_shift : string := "0";
|
|
sclkout0_phase_shift : string := "0";
|
|
sclkout1_phase_shift : string := "0";
|
|
family_name : string := "Stratix II";
|
|
m : integer := 0 );
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (others => '0');
|
|
fbin : in std_logic := '1';
|
|
ena : in std_logic := '1';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scanread : in std_logic := '0';
|
|
scanwrite : in std_logic := '0';
|
|
scandata : in std_logic := '0';
|
|
scanclk : in std_logic := '0';
|
|
testin : in std_logic_vector(3 downto 0) := (OTHERS=>'0');
|
|
clk : out std_logic_vector(5 downto 0);
|
|
locked : out std_logic;
|
|
enable0 : out std_logic;
|
|
enable1 : out std_logic;
|
|
sclkout : out std_logic_vector(1 downto 0) );
|
|
end component; -- MF_stratixii_pll
|
|
|
|
-- PLL for Stratix III
|
|
component MF_stratixiii_pll
|
|
generic (
|
|
operation_mode : string := "normal";
|
|
pll_type : string := "lvds";
|
|
vco_multiply_by : integer := 0;
|
|
vco_divide_by : integer := 0;
|
|
inclk0_input_frequency : positive ;
|
|
simulation_type : string := "functional";
|
|
clk0_multiply_by : positive := 1;
|
|
clk0_divide_by : positive := 1;
|
|
clk0_phase_shift : string := "0";
|
|
clk1_multiply_by : positive := 1;
|
|
clk1_divide_by : positive := 1;
|
|
clk1_duty_cycle : integer := 50;
|
|
clk1_phase_shift : string := "0";
|
|
clk2_multiply_by : positive := 1;
|
|
clk2_divide_by : positive := 1;
|
|
clk2_phase_shift : string := "0";
|
|
clk3_multiply_by : positive := 1;
|
|
clk3_divide_by : positive := 1;
|
|
clk3_phase_shift : string := "0";
|
|
clk4_multiply_by : positive := 1;
|
|
clk4_divide_by : positive := 1;
|
|
clk4_phase_shift : string := "0";
|
|
clk4_duty_cycle : integer := 50;
|
|
family_name : string := "Stratix III";
|
|
self_reset_on_loss_lock : string := "OFF";
|
|
m : integer := 0 );
|
|
|
|
port (
|
|
inclk : in std_logic_vector(1 downto 0) := (others => '0');
|
|
fbin : in std_logic := '1';
|
|
clkswitch : in std_logic := '0';
|
|
areset : in std_logic := '0';
|
|
pfdena : in std_logic := '1';
|
|
scanclk : in std_logic := '1';
|
|
scandata : in std_logic := '1';
|
|
scanclkena : in std_logic := '1';
|
|
configupdate : in std_logic := '0';
|
|
phasecounterselect : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
|
|
phaseupdown : in std_logic := '1';
|
|
phasestep : in std_logic := '1';
|
|
clk : out std_logic_vector(9 downto 0);
|
|
locked : out std_logic );
|
|
end component; -- MF_stratixiii_pll
|
|
|
|
component stratix_tx_outclk
|
|
generic (
|
|
deserialization_factor : natural; -- Required parameter
|
|
bypass_serializer : boolean := FALSE;
|
|
invert_clock : boolean := FALSE;
|
|
use_falling_clock_edge : boolean := FALSE );
|
|
port (
|
|
tx_in : in std_logic_vector(deserialization_factor-1 downto 0);
|
|
tx_fastclk : in std_logic;
|
|
tx_enable : in std_logic := '1';
|
|
tx_out : out std_logic := '0' );
|
|
end component; -- stratix_tx_outclk
|
|
|
|
component stratixii_tx_outclk
|
|
generic (
|
|
deserialization_factor : natural; -- Required parameter
|
|
bypass_serializer : boolean := FALSE;
|
|
invert_clock : boolean := FALSE;
|
|
use_falling_clock_edge : boolean := FALSE );
|
|
port (
|
|
tx_in : in std_logic_vector(deserialization_factor-1 downto 0);
|
|
tx_fastclk : in std_logic;
|
|
tx_enable : in std_logic := '1';
|
|
tx_out : out std_logic := '0' );
|
|
end component; -- stratixii_tx_outclk
|
|
|
|
component flexible_lvds_tx
|
|
generic (
|
|
number_of_channels : natural; -- Required parameter
|
|
deserialization_factor : natural; -- Required parameter
|
|
registered_input : string := "ON";
|
|
use_new_coreclk_ckt : boolean := false;
|
|
outclock_multiply_by : natural := 1;
|
|
outclock_divide_by : natural := 2;
|
|
outclock_duty_cycle : natural := 50;
|
|
use_self_generated_outclock : boolean := false );
|
|
port (
|
|
tx_in : in std_logic_vector(REGISTER_WIDTH -1 downto 0);
|
|
tx_fastclk : in std_logic;
|
|
tx_slowclk : in std_logic;
|
|
tx_regclk : in std_logic;
|
|
pll_areset : in std_logic;
|
|
tx_data_reset : in std_logic;
|
|
pll_outclock : in std_logic;
|
|
tx_locked : in std_logic;
|
|
tx_out : out std_logic_vector(number_of_channels-1 downto 0);
|
|
tx_outclock : out std_logic );
|
|
end component; -- flexible_lvds_tx
|
|
|
|
|
|
component stratixv_local_clk_divider
|
|
generic (
|
|
clk_divide_by : natural := 4 );
|
|
port (
|
|
clkin : in std_logic;
|
|
lloaden : out std_logic := '0' );
|
|
end component; -- stratixv_local_clk_divider
|
|
|
|
|
|
begin
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
|
|
tx_out <= tx_in_int when (deserialization_factor = 1)
|
|
else tx_ddio_out when (deserialization_factor = 2)
|
|
else flvds_dataout when (FAMILY_HAS_FLEXIBLE_LVDS = true)
|
|
else tx_out_stratix when ((STRATIX_TX_STYLE = true) or
|
|
(STRATIXII_TX_STYLE = true) or
|
|
(STRATIXIII_TX_STYLE = true))
|
|
else tx_in_int;
|
|
|
|
tx_in_int <= tx_in_reg when (registered_input /= "OFF")
|
|
else tx_in;
|
|
|
|
tx_fastclk <= '0' when (deserialization_factor < 3)
|
|
else tx_inclock when ((use_external_pll = "ON") or (enable_clock_pin_mode = "ON"))
|
|
else tx_pll_sclkout(0) when (STRATIXII_TX_STYLE = true)
|
|
else tx_pll_clk0;
|
|
|
|
tx_slowclk <= '0' when ((use_external_pll = "ON") or
|
|
(deserialization_factor < 3))
|
|
else tx_pll_clk2 when ((STRATIX_TX_STYLE = true) or
|
|
(STRATIXII_TX_STYLE = true) or
|
|
(STRATIXIII_TX_STYLE = true) or
|
|
(CYCLONE_TX_STYLE = true) or
|
|
(CYCLONEIII_TX_STYLE = true) or
|
|
(CYCLONEII_TX_STYLE = true))
|
|
else tx_pll_clk1;
|
|
|
|
tx_outclock <= tx_inclock when (deserialization_factor < 3)
|
|
else flvds_outclock when (FAMILY_HAS_FLEXIBLE_LVDS = true)
|
|
else stratix_outclock when (STRATIX_TX_STYLE = true)
|
|
else stratixii_outclock when (STRATIXII_TX_STYLE = true) or
|
|
(STRATIXIII_TX_STYLE = true)
|
|
else tx_slowclk;
|
|
|
|
flvds_pll_outclock <= tx_pll_clk1;
|
|
|
|
tx_coreclk_int <= tx_slowclk;
|
|
|
|
tx_coreclock <= tx_coreclk_int;
|
|
|
|
tx_reg_clk <= tx_inclock when (use_external_pll = "ON")
|
|
else sync_inclock when (registered_input = "ON") and
|
|
(multi_clock = "ON") and
|
|
(STRATIX_TX_STYLE = false) and
|
|
(STRATIXII_TX_STYLE = false) and
|
|
(STRATIXIII_TX_STYLE = false) and
|
|
(CYCLONE_TX_STYLE = false) and
|
|
(CYCLONEIII_TX_STYLE = false) and
|
|
(CYCLONEII_TX_STYLE = false)
|
|
else tx_coreclk_int when (registered_input = "TX_CORECLK") and
|
|
((STRATIX_TX_STYLE = true) or
|
|
(STRATIXII_TX_STYLE = true) or
|
|
(STRATIXIII_TX_STYLE = true) or
|
|
(CYCLONE_TX_STYLE = true) or
|
|
(CYCLONEIII_TX_STYLE = true) or
|
|
(CYCLONEII_TX_STYLE = true))
|
|
else tx_inclock;
|
|
|
|
tx_locked <= tx_locked_int and pll_lock_sync when (((STRATIXIII_TX_STYLE = true) or
|
|
(CYCLONEIII_TX_STYLE = true)) and
|
|
(deserialization_factor > 2))
|
|
else tx_locked_int when (deserialization_factor > 2)
|
|
else '1';
|
|
|
|
enable0 <= tx_enable when (use_external_pll = "ON")
|
|
else stratixiii_enable0 when (STRATIXIII_TX_STYLE = true) and (implement_in_les = "OFF")
|
|
else tx_pll_enable0;
|
|
|
|
stratixiii_enable0 <= local_clk_div_lloaden when (enable_clock_pin_mode = "ON")
|
|
else tx_pll_clk1;
|
|
|
|
stratixiii_enable1 <= local_clk_div_lloaden when (enable_clock_pin_mode = "ON")
|
|
else tx_pll_clk4;
|
|
|
|
stratix_inclock <= '0' when (STRATIX_TX_STYLE = false) or
|
|
(implement_in_les = "ON")
|
|
else tx_pll_clk1;
|
|
|
|
stratix_enable <= '0' when (STRATIX_TX_STYLE = false) or
|
|
(implement_in_les = "ON")
|
|
else tx_pll_enable1;
|
|
|
|
stratixii_inclock <= '0' when ((STRATIXII_TX_STYLE = false) and
|
|
(STRATIXIII_TX_STYLE = false)) or
|
|
(implement_in_les = "ON")
|
|
else tx_inclock when ((use_external_pll = "ON") or (enable_clock_pin_mode = "ON"))
|
|
else tx_pll_clk3 when (STRATIXIII_TX_STYLE = true)
|
|
else tx_pll_sclkout(1);
|
|
|
|
stratixii_enable <= '0' when ((STRATIXII_TX_STYLE = false) and
|
|
(STRATIXIII_TX_STYLE = false)) or
|
|
(implement_in_les = "ON")
|
|
else tx_enable when (use_external_pll = "ON")
|
|
else stratixiii_enable1 when (STRATIXIII_TX_STYLE = true)
|
|
else tx_pll_enable1;
|
|
|
|
flvds_fastclk <= '0' when (FAMILY_HAS_FLEXIBLE_LVDS = false)
|
|
else tx_inclock when (use_external_pll = "ON")
|
|
else tx_pll_clk0;
|
|
|
|
flvds_slowclk <= '0' when (FAMILY_HAS_FLEXIBLE_LVDS = false)
|
|
else tx_syncclock when (use_external_pll = "ON")
|
|
else tx_pll_clk2;
|
|
|
|
|
|
-- COMPONENT ASSIGNMENTS
|
|
|
|
-- PLL instantiations
|
|
-- MF_stratix_pll used for Stratix and Stratix GX
|
|
-- MF_stratixii_pll used for Stratix II
|
|
-- MF_stratixiii_pll used for Stratix III
|
|
STRATIX_PLL:
|
|
if ((STRATIX_TX_STYLE = true) and (implement_in_les = "OFF") and
|
|
(deserialization_factor > 2)) generate
|
|
|
|
u2: MF_stratix_pll -- STRATIX PLL
|
|
generic map (
|
|
inclk0_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => 1,
|
|
clk0_phase_shift => PHASE_INCLOCK,
|
|
clk1_multiply_by => INT_CLOCK_BOOST,
|
|
clk1_divide_by => 1,
|
|
clk1_phase_shift => PHASE_OUTCLOCK,
|
|
clk1_duty_cycle => 50,
|
|
clk2_multiply_by => INT_CLOCK_BOOST,
|
|
clk2_divide_by => deserialization_factor,
|
|
clk2_phase_shift => PHASE_INCLOCK,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => tx_inclock,
|
|
inclk(1) => temp_zero,
|
|
ena => tx_pll_enable,
|
|
areset => pll_areset,
|
|
clkena(5 downto 0) => temp_high,
|
|
clk(0) => tx_pll_clk0,
|
|
clk(1) => tx_pll_clk1,
|
|
clk(2) => tx_pll_clk2,
|
|
clk (5 downto 3) => temp_clk(2 downto 0),
|
|
locked => tx_locked_int,
|
|
enable0 => tx_pll_enable0,
|
|
enable1 => tx_pll_enable1 );
|
|
end generate STRATIX_PLL;
|
|
|
|
STRATIXII_PLL:
|
|
if ((STRATIXII_TX_STYLE = true) and (implement_in_les = "OFF") and
|
|
(use_external_pll /= "ON") and (deserialization_factor > 2)) generate
|
|
|
|
u2: MF_stratixii_pll -- STRATIX II PLL
|
|
generic map (
|
|
vco_multiply_by => INT_CLOCK_BOOST,
|
|
vco_divide_by => 1,
|
|
inclk0_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => deserialization_factor,
|
|
clk0_phase_shift => STXII_PHASE_INCLOCK,
|
|
clk1_multiply_by => INT_CLOCK_BOOST,
|
|
clk1_divide_by => deserialization_factor,
|
|
clk1_phase_shift => PHASE_OUTCLOCK,
|
|
clk1_duty_cycle => 50,
|
|
clk2_multiply_by => INT_CLOCK_BOOST,
|
|
clk2_divide_by => deserialization_factor,
|
|
clk2_phase_shift => STXII_PHASE_INCLOCK,
|
|
sclkout0_phase_shift => STXII_PHASE_INCLOCK,
|
|
sclkout1_phase_shift => PHASE_OUTCLOCK,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => tx_inclock,
|
|
inclk(1) => temp_zero,
|
|
ena => tx_pll_enable,
|
|
areset => pll_areset,
|
|
clk(0) => tx_pll_clk0,
|
|
clk(1) => tx_pll_clk1,
|
|
clk(2) => tx_pll_clk2,
|
|
clk (5 downto 3) => temp_clk(2 downto 0),
|
|
locked => tx_locked_int,
|
|
enable0 => tx_pll_enable0,
|
|
enable1 => tx_pll_enable1,
|
|
sclkout(0) => tx_pll_sclkout(0),
|
|
sclkout(1) => tx_pll_sclkout(1) );
|
|
end generate STRATIXII_PLL;
|
|
|
|
STRATIXIII_PLL:
|
|
if ((STRATIXIII_TX_STYLE = true) and (implement_in_les = "OFF") and
|
|
(use_external_pll /= "ON") and (deserialization_factor > 2)) generate
|
|
|
|
U4: MF_stratixiii_pll -- Stratix III PLL
|
|
generic map (
|
|
vco_multiply_by => INT_CLOCK_BOOST,
|
|
vco_divide_by => 1,
|
|
inclk0_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => 1,
|
|
clk1_multiply_by => INT_CLOCK_BOOST,
|
|
clk1_divide_by => deserialization_factor,
|
|
clk1_duty_cycle => integer(real(100/deserialization_factor) + real(0.5)),
|
|
clk2_multiply_by => INT_CLOCK_BOOST,
|
|
clk2_divide_by => deserialization_factor,
|
|
clk3_multiply_by => INT_CLOCK_BOOST,
|
|
clk3_divide_by => 1,
|
|
clk4_multiply_by => INT_CLOCK_BOOST,
|
|
clk4_divide_by => deserialization_factor,
|
|
clk4_duty_cycle => integer(real(100/deserialization_factor) + real(0.5)),
|
|
clk0_phase_shift => STXII_PHASE_INCLOCK,
|
|
clk1_phase_shift => CLK_ENA_PHASE_SHIFT,
|
|
clk2_phase_shift => STXII_PHASE_INCLOCK,
|
|
clk3_phase_shift => PHASE_OUTCLOCK,
|
|
clk4_phase_shift => OUTCLK_ENA_PHASE_SHIFT,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => tx_inclock,
|
|
inclk(1) => temp_zero,
|
|
areset => pll_areset,
|
|
clk(0) => tx_pll_clk0,
|
|
clk(1) => tx_pll_clk1,
|
|
clk(2) => tx_pll_clk2,
|
|
clk(3) => tx_pll_clk3,
|
|
clk(4) => tx_pll_clk4,
|
|
clk (9 downto 5) => temp_clk(4 downto 0),
|
|
locked => tx_locked_int );
|
|
|
|
end generate STRATIXIII_PLL;
|
|
|
|
FLVDS_STX_PLL:
|
|
if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and (FAMILY_HAS_STRATIX_STYLE_PLL = true) and
|
|
(CYCLONE_TX_STYLE = false) and (deserialization_factor > 2)) generate
|
|
|
|
u2: MF_stratix_pll -- STRATIX PLL
|
|
generic map (
|
|
pll_type => FLVDS_PLL_TYPE,
|
|
inclk0_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => FLVDS_CLK0_DIV,
|
|
clk0_phase_shift => PHASE_INCLOCK,
|
|
clk1_multiply_by => FLVDS_CLK1_MUL,
|
|
clk1_divide_by => FLVDS_CLK1_DIV,
|
|
clk1_phase_shift => PHASE_OUTCLOCK,
|
|
clk1_duty_cycle => 50,
|
|
clk2_multiply_by => FLVDS_CLK2_MUL,
|
|
clk2_divide_by => FLVDS_CLK2_DIV,
|
|
clk2_phase_shift => PHASE_INCLOCK,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => tx_inclock,
|
|
inclk(1) => temp_zero,
|
|
ena => tx_pll_enable,
|
|
areset => pll_areset,
|
|
clkena(5 downto 0) => temp_high,
|
|
clk(0) => tx_pll_clk0,
|
|
clk(1) => tx_pll_clk1,
|
|
clk(2) => tx_pll_clk2,
|
|
clk (5 downto 3) => temp_clk(2 downto 0),
|
|
locked => tx_locked_int,
|
|
enable0 => tx_pll_enable0,
|
|
enable1 => tx_pll_enable1 );
|
|
end generate FLVDS_STX_PLL;
|
|
|
|
CYC_PLL:
|
|
if ((CYCLONE_TX_STYLE = true) and (deserialization_factor > 2)) generate
|
|
|
|
u2: MF_stratix_pll -- Cyclone PLL
|
|
generic map (
|
|
pll_type => FLVDS_PLL_TYPE,
|
|
inclk0_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => FLVDS_CLK0_DIV,
|
|
clk0_phase_shift => PHASE_INCLOCK,
|
|
clk1_multiply_by => FLVDS_CLK1_MUL,
|
|
clk1_divide_by => FLVDS_CLK1_DIV,
|
|
clk1_phase_shift => PHASE_OUTCLOCK,
|
|
clk1_duty_cycle => outclock_duty_cycle,
|
|
clk2_multiply_by => FLVDS_CLK2_MUL,
|
|
clk2_divide_by => FLVDS_CLK2_DIV,
|
|
clk2_phase_shift => PHASE_INCLOCK,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => tx_inclock,
|
|
inclk(1) => temp_zero,
|
|
ena => tx_pll_enable,
|
|
areset => pll_areset,
|
|
clkena(5 downto 0) => temp_high,
|
|
clk(0) => tx_pll_clk0,
|
|
clk(1) => tx_pll_clk1,
|
|
clk(2) => tx_pll_clk2,
|
|
clk (5 downto 3) => temp_clk(2 downto 0),
|
|
locked => tx_locked_int,
|
|
enable0 => tx_pll_enable0,
|
|
enable1 => tx_pll_enable1 );
|
|
end generate CYC_PLL;
|
|
|
|
FLVDS_STXII_PLL:
|
|
if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and (FAMILY_HAS_STRATIXII_STYLE_PLL = true) and
|
|
(use_external_pll /= "ON") and (deserialization_factor > 2)) generate
|
|
|
|
u2: MF_stratixii_pll -- STRATIX II PLL
|
|
generic map (
|
|
pll_type => FLVDS_PLL_TYPE,
|
|
vco_multiply_by => INT_CLOCK_BOOST,
|
|
vco_divide_by => 1,
|
|
inclk0_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => FLVDS_CLK0_DIV,
|
|
clk0_phase_shift => STXII_LE_PHASE_INCLOCK,
|
|
clk1_multiply_by => FLVDS_CLK1_MUL,
|
|
clk1_divide_by => FLVDS_CLK1_DIV,
|
|
clk1_phase_shift => STXII_LE_PHASE_OUTCLOCK,
|
|
clk1_duty_cycle => 50,
|
|
clk2_multiply_by => FLVDS_CLK2_MUL,
|
|
clk2_divide_by => FLVDS_CLK2_DIV,
|
|
clk2_phase_shift => STXII_LE_PHASE_INCLOCK,
|
|
sclkout0_phase_shift => STXII_LE_PHASE_INCLOCK,
|
|
sclkout1_phase_shift => STXII_LE_PHASE_OUTCLOCK,
|
|
family_name => intended_device_family )
|
|
port map (
|
|
inclk(0) => tx_inclock,
|
|
inclk(1) => temp_zero,
|
|
ena => tx_pll_enable,
|
|
areset => pll_areset,
|
|
clk(0) => tx_pll_clk0,
|
|
clk(1) => tx_pll_clk1,
|
|
clk(2) => tx_pll_clk2,
|
|
clk (5 downto 3) => temp_clk(2 downto 0),
|
|
locked => tx_locked_int,
|
|
enable0 => tx_pll_enable0,
|
|
enable1 => tx_pll_enable1,
|
|
sclkout(0) => tx_pll_sclkout(0),
|
|
sclkout(1) => tx_pll_sclkout(1) );
|
|
end generate FLVDS_STXII_PLL;
|
|
|
|
FLVDS_STXIII_PLL:
|
|
if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
|
|
(FAMILY_HAS_STRATIXIII_STYLE_PLL = true) and (use_external_pll /= "ON") and
|
|
(deserialization_factor > 2)) generate
|
|
|
|
U5: MF_stratixiii_pll -- Stratix III PLL
|
|
generic map (
|
|
pll_type => FLVDS_PLL_TYPE,
|
|
vco_multiply_by => INT_CLOCK_BOOST,
|
|
vco_divide_by => 1,
|
|
inclk0_input_frequency => inclock_period,
|
|
clk0_multiply_by => INT_CLOCK_BOOST,
|
|
clk0_divide_by => FLVDS_CLK0_DIV,
|
|
clk0_phase_shift => STXIII_LE_PHASE_INCLOCK,
|
|
clk1_multiply_by => FLVDS_CLK1_MUL,
|
|
clk1_divide_by => FLVDS_CLK1_DIV,
|
|
clk1_phase_shift => STXIII_LE_PHASE_OUTCLOCK,
|
|
clk1_duty_cycle => 50,
|
|
clk2_multiply_by => FLVDS_CLK2_MUL,
|
|
clk2_divide_by => FLVDS_CLK2_DIV,
|
|
clk2_phase_shift => STXIII_LE_PHASE_INCLOCK,
|
|
family_name => intended_device_family,
|
|
self_reset_on_loss_lock => alpha_tolower(pll_self_reset_on_loss_lock) )
|
|
port map (
|
|
inclk(0) => tx_inclock,
|
|
inclk(1) => temp_zero,
|
|
areset => pll_areset,
|
|
clk(0) => tx_pll_clk0,
|
|
clk(1) => tx_pll_clk1,
|
|
clk(2) => tx_pll_clk2,
|
|
clk (9 downto 3) => temp_clk(6 downto 0),
|
|
locked => tx_locked_int );
|
|
|
|
end generate FLVDS_STXIII_PLL;
|
|
|
|
STRATIX_OUTCLK :
|
|
if ((STRATIX_TX_STYLE = true) and (implement_in_les = "OFF") and
|
|
(deserialization_factor > 2)) generate
|
|
|
|
u3: stratix_tx_outclk
|
|
generic map (
|
|
deserialization_factor => deserialization_factor,
|
|
bypass_serializer => BYPASS_NEEDED,
|
|
invert_clock => INVERT_CLOCK_NEEDED,
|
|
use_falling_clock_edge => FALLING_CLOCK_EDGE_NEEDED )
|
|
port map (
|
|
tx_in => stx_phase_shift_txdata(deserialization_factor-1 downto 0),
|
|
tx_fastclk => stratix_inclock,
|
|
tx_enable => stratix_enable,
|
|
tx_out => stratix_outclock );
|
|
end generate STRATIX_OUTCLK;
|
|
|
|
STRATIXII_OUTCLK :
|
|
if (((STRATIXII_TX_STYLE = true) or (STRATIXIII_TX_STYLE = true)) and
|
|
(implement_in_les = "OFF") and (deserialization_factor > 2)) generate
|
|
|
|
u3: stratixii_tx_outclk
|
|
generic map (
|
|
deserialization_factor => deserialization_factor,
|
|
bypass_serializer => BYPASS_NEEDED,
|
|
invert_clock => INVERT_CLOCK_NEEDED,
|
|
use_falling_clock_edge => FALLING_CLOCK_EDGE_NEEDED )
|
|
port map (
|
|
tx_in => phase_shift_txdata(deserialization_factor-1 downto 0),
|
|
tx_fastclk => stratixii_inclock,
|
|
tx_enable => stratixii_enable,
|
|
tx_out => stratixii_outclock );
|
|
end generate STRATIXII_OUTCLK;
|
|
|
|
FLEXIBLE_LVDS_TRANSMITTER:
|
|
if (((FAMILY_HAS_FLEXIBLE_LVDS = true) and (deserialization_factor > 2)) or (MAXV_TX_STYLE = true)) generate
|
|
|
|
U4: flexible_lvds_tx
|
|
generic map (
|
|
number_of_channels => number_of_channels,
|
|
deserialization_factor => deserialization_factor,
|
|
registered_input => registered_input,
|
|
use_new_coreclk_ckt => USE_NEW_CORECLK_CKT,
|
|
outclock_multiply_by => outclock_multiply_by,
|
|
outclock_divide_by => outclock_divide_by,
|
|
outclock_duty_cycle => outclock_duty_cycle,
|
|
use_self_generated_outclock => USE_SELF_GENERATED_OUTCLOCK )
|
|
port map (
|
|
tx_in => tx_in,
|
|
tx_fastclk => flvds_fastclk,
|
|
tx_slowclk => flvds_slowclk,
|
|
tx_regclk => tx_reg_clk,
|
|
pll_areset => pll_areset,
|
|
tx_data_reset => tx_data_reset,
|
|
pll_outclock => flvds_pll_outclock,
|
|
tx_locked => tx_locked_int,
|
|
tx_out => flvds_dataout,
|
|
tx_outclock => flvds_outclock );
|
|
end generate FLEXIBLE_LVDS_TRANSMITTER;
|
|
|
|
STRATIXV_TX_LOCAL_CLK_DIVIDER:
|
|
if ((STRATIXIII_TX_STYLE = true) and (enable_clock_pin_mode = "ON")) generate
|
|
|
|
U6: stratixv_local_clk_divider -- Stratix V local clock divider block
|
|
generic map (
|
|
clk_divide_by => deserialization_factor )
|
|
|
|
port map (
|
|
clkin => tx_fastclk,
|
|
lloaden => local_clk_div_lloaden );
|
|
|
|
end generate STRATIXV_TX_LOCAL_CLK_DIVIDER;
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
INITIAL : process
|
|
variable non_50_duty_cycle_is_valid : boolean := false;
|
|
begin
|
|
-- basic error checking for invalid deserialization factors
|
|
if (IS_VALID_FAMILY(intended_device_family) = false) then
|
|
ASSERT FALSE
|
|
REPORT intended_device_family & " is not a valid device family!"
|
|
SEVERITY ERROR;
|
|
elsif ((STRATIX_TX_STYLE = true) and
|
|
(deserialization_factor /= 1) and
|
|
(deserialization_factor /= 2) and
|
|
((deserialization_factor > 10) or
|
|
(deserialization_factor < 4))) then
|
|
ASSERT FALSE
|
|
REPORT "Stratix and Stratix GX does not support the specified deserialization factor!"
|
|
SEVERITY ERROR;
|
|
elsif ((STRATIXII_TX_STYLE = true) and
|
|
(deserialization_factor > 10)) then
|
|
ASSERT FALSE
|
|
REPORT "Stratix II does not support the specified deserialization factor!"
|
|
SEVERITY ERROR;
|
|
elsif (FAMILY_HAS_FLEXIBLE_LVDS = true) then
|
|
if ((deserialization_factor rem 2) = 1) then
|
|
if ((outclock_multiply_by /= 1) and (outclock_multiply_by /= 2)) then
|
|
ASSERT FALSE
|
|
REPORT "Only values of 1 and 2 are allowed for outclock_multiply_by."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if ((coreclock_divide_by /= 1) and (coreclock_divide_by /= 2)) then
|
|
ASSERT FALSE
|
|
REPORT "Only values of 1 and 2 are allowed for coreclock_divide_by."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if ((coreclock_divide_by = 2) and ((deserialization_factor rem 2) = 1)) then
|
|
if (CYCLONE_TX_STYLE = true) then
|
|
if (outclock_multiply_by = 2) then
|
|
ASSERT FALSE
|
|
REPORT "The specified combination of coreclock_divide_by, outclock_multiply_by, outclock_divide_by and deserialization_factor is not supported for " & intended_device_family &
|
|
". Use the megawizard to generate a valid configuration."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (outclock_multiply_by = 2) then
|
|
if (outclock_divide_by /= deserialization_factor) then
|
|
ASSERT FALSE
|
|
REPORT "The specified combination of coreclock_divide_by, outclock_multiply_by, outclock_divide_by and deserialization_factor is not supported for " & intended_device_family &
|
|
". Use the megawizard to generate a valid configuration."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
end if;
|
|
|
|
if (CYCLONE_TX_STYLE = true) then
|
|
if ((outclock_divide_by = deserialization_factor) and (outclock_multiply_by = 1)) then
|
|
non_50_duty_cycle_is_valid := true;
|
|
end if;
|
|
else
|
|
if ((outclock_divide_by = deserialization_factor) and ((outclock_multiply_by = 1) or (coreclock_divide_by = 2))) then
|
|
non_50_duty_cycle_is_valid := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (outclock_duty_cycle /= 50) then
|
|
if (non_50_duty_cycle_is_valid = true) then
|
|
if ((outclock_multiply_by = 2) and ((deserialization_factor rem 2) = 1)) then
|
|
if (deserialization_factor = 7) then
|
|
if (outclock_duty_cycle /= 57) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 57."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
elsif (deserialization_factor = 9) then
|
|
if (outclock_duty_cycle /= 56) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 56."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
elsif (deserialization_factor = 5) then
|
|
if (outclock_duty_cycle /= 60) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 60."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
end if;
|
|
else
|
|
if (deserialization_factor = 7) then
|
|
if (outclock_duty_cycle /= 57) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50 and 57."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
elsif (deserialization_factor = 9) then
|
|
if (outclock_duty_cycle /= 56) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50 and 56."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
elsif (deserialization_factor = 5) then
|
|
if (outclock_duty_cycle /= 60) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50 and 60."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- Input data needed by stratix_tx_outclk in order to generate the tx_outclock.
|
|
if (outclock_divide_by > 1) then
|
|
if (deserialization_factor = 4) then
|
|
if ( outclock_divide_by = 2) then
|
|
stx_phase_shift_txdata(3 downto 0) <= "1010";
|
|
elsif (outclock_divide_by = 4) then
|
|
stx_phase_shift_txdata(3 downto 0) <= "0011";
|
|
end if;
|
|
elsif (deserialization_factor = 8) then
|
|
if (outclock_divide_by = 2) then
|
|
stx_phase_shift_txdata(7 downto 0) <= "10101010";
|
|
elsif (outclock_divide_by = 4) then
|
|
stx_phase_shift_txdata(7 downto 0) <= "00110011";
|
|
elsif (outclock_divide_by = 8) then
|
|
stx_phase_shift_txdata(7 downto 0) <= "11000011";
|
|
end if;
|
|
elsif (deserialization_factor = 10) then
|
|
if (outclock_divide_by = 2) then
|
|
stx_phase_shift_txdata(9 downto 0) <= "1010101010";
|
|
elsif (outclock_divide_by = 10) then
|
|
stx_phase_shift_txdata(9 downto 0) <= "1110000011";
|
|
end if;
|
|
elsif (deserialization_factor = 7) then
|
|
if (outclock_divide_by = 7) then
|
|
stx_phase_shift_txdata(6 downto 0) <= "1100011";
|
|
end if;
|
|
elsif (deserialization_factor = 9) then
|
|
if (outclock_divide_by = 9) then
|
|
stx_phase_shift_txdata(8 downto 0) <= "110000111";
|
|
end if;
|
|
elsif (deserialization_factor = 5) then
|
|
if (outclock_divide_by = 5) then
|
|
stx_phase_shift_txdata(4 downto 0) <= "10011";
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- Input data needed by stratixii_tx_outclk in order to generate the tx_outclock.
|
|
if (outclock_divide_by > 1) then
|
|
if (deserialization_factor = 4) then
|
|
if ( outclock_divide_by = 2) then
|
|
phase_shift_txdata(3 downto 0) <= "1010";
|
|
elsif (outclock_divide_by = 4) then
|
|
phase_shift_txdata(3 downto 0) <= "1100";
|
|
end if;
|
|
elsif (deserialization_factor = 6) then
|
|
if ( outclock_divide_by = 2) then
|
|
phase_shift_txdata(5 downto 0) <= "101010";
|
|
elsif (outclock_divide_by = 6) then
|
|
phase_shift_txdata(5 downto 0) <= "111000";
|
|
end if;
|
|
elsif (deserialization_factor = 8) then
|
|
if (outclock_divide_by = 2) then
|
|
phase_shift_txdata(7 downto 0) <= "10101010";
|
|
elsif (outclock_divide_by = 4) then
|
|
phase_shift_txdata(7 downto 0) <= "11001100";
|
|
elsif (outclock_divide_by = 8) then
|
|
phase_shift_txdata(7 downto 0) <= "11110000";
|
|
end if;
|
|
elsif (deserialization_factor = 10) then
|
|
if (outclock_divide_by = 2) then
|
|
phase_shift_txdata(9 downto 0) <= "1010101010";
|
|
elsif (outclock_divide_by = 10) then
|
|
phase_shift_txdata(9 downto 0) <= "1111100000";
|
|
end if;
|
|
elsif (deserialization_factor = 7) then
|
|
if (outclock_divide_by = 7) then
|
|
phase_shift_txdata(6 downto 0) <= "1111000";
|
|
end if;
|
|
elsif (deserialization_factor = 9) then
|
|
if (outclock_divide_by = 9) then
|
|
phase_shift_txdata(8 downto 0) <= "110000111";
|
|
end if;
|
|
elsif (deserialization_factor = 5) then
|
|
if (outclock_divide_by = 5) then
|
|
phase_shift_txdata(4 downto 0) <= "10011";
|
|
end if;
|
|
-- SPR 338253 - add support for SIII deserialization 3, outclock divide 3 mode.
|
|
elsif ((deserialization_factor = 3) and (STRATIXIII_TX_STYLE = true)) then
|
|
if (outclock_divide_by = 3) then
|
|
phase_shift_txdata(2 downto 0) <= "101";
|
|
end if;
|
|
end if;
|
|
end if;
|
|
wait;
|
|
end process; -- INITIAL process
|
|
|
|
|
|
DDIO_OUT_RECEIVE : process (tx_inclock, tx_in_int)
|
|
begin
|
|
if (deserialization_factor = 2) then
|
|
if (tx_inclock'event and (tx_inclock = '1')) then
|
|
for i in 0 to (number_of_channels-1) loop
|
|
dataout_l(i) <= tx_in_int(i*2);
|
|
dataout_h(i) <= tx_in_int((i*2)+1);
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end process; -- DDIO_OUT_RECEIVE process
|
|
|
|
|
|
DDIO_OUT_TRANSMIT : process(tx_inclock, dataout_h, dataout_l)
|
|
begin
|
|
if (deserialization_factor = 2) then
|
|
if (tx_inclock = '1') then
|
|
for i in 0 to (number_of_channels-1) loop
|
|
tx_ddio_out(i) <= dataout_h(i);
|
|
end loop;
|
|
else
|
|
for i in 0 to (number_of_channels-1) loop
|
|
tx_ddio_out(i) <= dataout_l(i);
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end process; -- DDIO_OUT_TRANSMIT process
|
|
|
|
|
|
-- Registering of the load enable signal for Stratix's registers
|
|
TXLOADEN: process (tx_fastclk)
|
|
begin
|
|
if (tx_fastclk'event and (tx_fastclk ='1')) then
|
|
enable0_pipe <= enable0_reg;
|
|
enable0_reg <= enable0;
|
|
elsif (tx_fastclk'event and (tx_fastclk = '0')) then
|
|
enable0_neg <= enable0_pipe;
|
|
end if;
|
|
|
|
end process; -- TXLOADEN process
|
|
|
|
STRATIX_SERIALIZE :
|
|
if ((implement_in_les = "OFF") and (deserialization_factor > 2)) generate
|
|
|
|
-- Load and serialize the data
|
|
SERIALIZE2: process(tx_fastclk, enable0_reg)
|
|
variable count : integer := 0;
|
|
variable sample : integer;
|
|
variable shift_data : std_logic := '0';
|
|
variable tx_shift_reg : std_logic_vector(REGISTER_WIDTH -1 downto 0)
|
|
:= (others => '0');
|
|
begin
|
|
|
|
-- Load data when registered load enable signal goes high
|
|
if (((STRATIX_TX_STYLE = true) and (enable0_reg = '1') and enable0_reg'event) or
|
|
(((STRATIXII_TX_STYLE = true) or (STRATIXIII_TX_STYLE = true)) and tx_fastclk'event and (tx_fastclk = '1'))) then
|
|
if (registered_input /= "OFF") then
|
|
tx_parallel_load_reg <= tx_in_reg;
|
|
else
|
|
tx_parallel_load_reg <= tx_in;
|
|
end if;
|
|
end if;
|
|
|
|
-- Serialize the data, MSB is the first bit to be shifted out
|
|
if (tx_fastclk'event and (tx_fastclk = '1')) then
|
|
if (((STRATIX_TX_STYLE = true) and (enable0_neg = '1')) or
|
|
(((STRATIXII_TX_STYLE = true) or (STRATIXIII_TX_STYLE = true)) and (enable0_reg = '1'))) then
|
|
tx_shift_reg := tx_parallel_load_reg;
|
|
count := 0;
|
|
shift_data := '1';
|
|
end if;
|
|
|
|
if (shift_data = '1') then
|
|
count := (count rem deserialization_factor) + 1;
|
|
for i in 0 to number_of_channels-1 loop
|
|
tx_out_stratix(i) <= tx_shift_reg((i+1)*deserialization_factor - count);
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end process; -- SERIALIZE2 process
|
|
end generate STRATIX_SERIALIZE;
|
|
|
|
-- synchronization register
|
|
-- registers the data_in before passing on to the parallel load register or
|
|
-- holding register
|
|
SYNC_REG: process(tx_reg_clk)
|
|
begin
|
|
if ((tx_reg_clk = '1') and tx_reg_clk'event) then
|
|
tx_in_reg <= tx_in after 5 ps;
|
|
end if;
|
|
end process; -- SYNC_REG process
|
|
|
|
process (tx_locked_int, pll_areset)
|
|
begin
|
|
if (pll_areset = '1') then
|
|
pll_lock_sync <= '0';
|
|
elsif (tx_locked_int = '1' and tx_locked_int'event) then
|
|
pll_lock_sync <= '1';
|
|
end if;
|
|
end process;
|
|
|
|
end behavior;
|
|
--END OF ARCHITECTURE
|
|
|
|
----------------------------------------------------------------------------
|
|
-- Module Name : altdpram
|
|
--
|
|
-- Description : Parameterized Dual Port RAM megafunction
|
|
--
|
|
-- Limitation : This megafunction is provided only for backward
|
|
-- compatibility in Cyclone, Stratix, and Stratix GX
|
|
-- designs.
|
|
--
|
|
-- Results expected : RAM having dual ports behaviour
|
|
--
|
|
----------------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
use std.textio.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
use work.ALTERA_COMMON_CONVERSION.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altdpram is
|
|
generic
|
|
( width : natural;
|
|
widthad : natural;
|
|
numwords : natural := 0;
|
|
lpm_file : string := "UNUSED";
|
|
lpm_hint : string := "USE_EAB=ON";
|
|
use_eab : string := "ON";
|
|
indata_reg : string := "INCLOCK";
|
|
indata_aclr : string := "ON";
|
|
wraddress_reg : string := "INCLOCK";
|
|
wraddress_aclr : string := "ON";
|
|
wrcontrol_reg : string := "INCLOCK";
|
|
wrcontrol_aclr : string := "ON";
|
|
rdaddress_reg : string := "OUTCLOCK";
|
|
rdaddress_aclr : string := "ON";
|
|
rdcontrol_reg : string := "OUTCLOCK";
|
|
rdcontrol_aclr : string := "ON";
|
|
outdata_reg : string := "UNREGISTERED";
|
|
outdata_aclr : string := "ON";
|
|
ram_block_type : string := "AUTO";
|
|
width_byteena : natural := 1;
|
|
byte_size : natural := 0;
|
|
read_during_write_mode_mixed_ports : string := "DONT_CARE";
|
|
maximum_depth : natural := 2048;
|
|
intended_device_family : string := "Stratix";
|
|
lpm_type : string := "altdpram");
|
|
port
|
|
( wren : in std_logic := '0';
|
|
data : in std_logic_vector(width-1 downto 0);
|
|
wraddress : in std_logic_vector(widthad-1 downto 0);
|
|
wraddressstall : in std_logic := '0';
|
|
inclock : in std_logic := '1';
|
|
inclocken : in std_logic := '1';
|
|
rden : in std_logic := '1';
|
|
rdaddress : in std_logic_vector(widthad-1 downto 0);
|
|
rdaddressstall : in std_logic := '0';
|
|
byteena : in std_logic_vector(width_byteena-1 downto 0) := (others => '1');
|
|
outclock : in std_logic := '1';
|
|
outclocken : in std_logic := '1';
|
|
aclr : in std_logic := '0';
|
|
q : out std_logic_vector(width-1 downto 0) );
|
|
|
|
end altdpram;
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of altdpram is
|
|
|
|
-- FUNCTION DEFINITION
|
|
|
|
function get_read_during_write_mode(read_during_write : string; wrcontrol_reg : string; rdaddress_reg : string; outdata_reg : string) return string is
|
|
begin
|
|
if ((wrcontrol_reg = "INCLOCK") and (rdaddress_reg = "INCLOCK") and (outdata_reg = "INCLOCK")) then
|
|
return read_during_write;
|
|
else
|
|
return "NEW_DATA";
|
|
end if;
|
|
end get_read_during_write_mode;
|
|
|
|
|
|
-- CONSTANT DEFINITION
|
|
|
|
constant i_read_during_write : string := get_read_during_write_mode(read_during_write_mode_mixed_ports, wrcontrol_reg, rdaddress_reg, outdata_reg);
|
|
|
|
|
|
-- TYPE DECLARATION
|
|
type alt_memory is array((2**WIDTHAD)-1 downto 0) of std_logic_vector(WIDTH-1 downto 0);
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal idata_tmp: std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
signal idata_reg: std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
signal idata_hi : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
signal idata_lo : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
signal ibyteena_tmp : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '1');
|
|
signal ibyteena_reg : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '1');
|
|
signal iq_tmp : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
signal iq_reg : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
signal irdaddress_tmp : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal irdaddress_reg : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal irdaddress_reg_low : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal iwraddress_tmp : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal iwraddress_reg : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal iwraddress_hi : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal iwraddress_lo : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal iwren_tmp : std_logic := '0';
|
|
signal iwren_reg : std_logic := '0';
|
|
signal iwren_hi : std_logic := '0';
|
|
signal iwren_lo : std_logic := '0';
|
|
signal irden_tmp : std_logic := '0';
|
|
signal irden_reg : std_logic := '0';
|
|
signal write_at_low_clock : boolean := false;
|
|
signal rden_low_output_0 : boolean := false;
|
|
signal i_byte_size : integer := 0;
|
|
signal i_byteena_mask_reg_hi : std_logic_vector(width - 1 downto 0) := (others => '1');
|
|
signal i_byteena_mask_reg_out_hi : std_logic_vector(width - 1 downto 0) := (others => '1');
|
|
signal i_byteena_mask_reg_x_hi : std_logic_vector(width - 1 downto 0) := (others => '0');
|
|
signal i_byteena_mask_reg_lo : std_logic_vector(width - 1 downto 0) := (others => '1');
|
|
signal i_byteena_mask_reg_out_lo : std_logic_vector(width - 1 downto 0) := (others => '1');
|
|
signal i_byteena_mask_reg_x_lo : std_logic_vector(width - 1 downto 0) := (others => '0');
|
|
signal first_clk_rising_edge : boolean := true;
|
|
|
|
begin
|
|
|
|
-- PROCESS BLOCKS
|
|
CHECKING: process
|
|
begin
|
|
if ((indata_aclr = "ON") and ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family)))) then
|
|
assert false
|
|
report intended_device_family & " device family does not support aclr on input data. Aclr on this port will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((wraddress_aclr = "ON") and ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family)))) then
|
|
assert false
|
|
report intended_device_family & " device family does not support aclr on write address. Aclr on this port will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((wrcontrol_aclr = "ON") and ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family)))) then
|
|
assert false
|
|
report intended_device_family & " device family does not support aclr on write control. Aclr on this port will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((rdcontrol_aclr = "ON") and ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family)))) then
|
|
assert false
|
|
report intended_device_family & "device family does not have read control (rden). Parameter rdcontrol_aclr will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family))) and (wrcontrol_reg /= "INCLOCK")) then
|
|
assert false
|
|
report "wrcontrol_reg can only be INCLOCK for " & intended_device_family
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family))) and (read_during_write_mode_mixed_ports = "OLD_DATA") and (rdaddress_aclr = "ON")) then
|
|
assert false
|
|
report "rdaddress_aclr cannot be turned on when it is " & intended_device_family & " with read_during_write_mode_mixed_ports = OLD_DATA"
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((((width / width_byteena) = 5) or (width / width_byteena = 10) or (width / width_byteena = 8) or (width / width_byteena = 9)) and (byte_size = 0)) and
|
|
((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
|
|
assert false
|
|
report "byte_size (width / width_byteena) should be in 5, 8, 9 or 10. It will default to 5."
|
|
severity warning;
|
|
end if;
|
|
|
|
wait;
|
|
end process;
|
|
|
|
INITIAL: process (inclock, outclock)
|
|
variable init : boolean := false;
|
|
begin
|
|
if (not init) then
|
|
if ((((lpm_hint = "USE_EAB=ON") and (use_eab /= "OFF")) or (use_eab = "ON")) ) then
|
|
if (wrcontrol_reg = "INCLOCK") then
|
|
if (not (FEATURE_FAMILY_STRATIXV(intended_device_family) or FEATURE_FAMILY_ARRIAV(intended_device_family) or FEATURE_FAMILY_ARRIA10(intended_device_family))) then
|
|
write_at_low_clock <= true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if ((byte_size = 0) and (width_byteena > 0)) then
|
|
if (((width / width_byteena) = 5) or (width / width_byteena = 10) or (width / width_byteena = 8) or (width / width_byteena = 9)) then
|
|
i_byte_size <= 5;
|
|
else
|
|
i_byte_size <= width / width_byteena;
|
|
end if;
|
|
else
|
|
i_byte_size <= byte_size;
|
|
end if;
|
|
|
|
init := true;
|
|
end if;
|
|
end process; -- initial
|
|
|
|
SYNC: process( data, idata_reg, rden, irden_reg, rdaddress, irdaddress_reg,
|
|
wren, iwren_reg, wraddress, iwraddress_reg, iq_tmp, iq_reg,
|
|
aclr, ibyteena_reg, irdaddress_reg_low)
|
|
begin
|
|
ibyteena_tmp <= ibyteena_reg;
|
|
|
|
if (((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family))) and (rdaddress_reg = "INCLOCK") and (i_read_during_write = "OLD_DATA")) then
|
|
irdaddress_tmp <= irdaddress_reg_low;
|
|
elsif ((rdaddress_reg = "INCLOCK") or (rdaddress_reg = "OUTCLOCK")) then
|
|
irdaddress_tmp <= irdaddress_reg;
|
|
else
|
|
irdaddress_tmp <= rdaddress;
|
|
end if;
|
|
|
|
if (((rdcontrol_reg = "INCLOCK") or (rdcontrol_reg = "OUTCLOCK")) and not ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family)))) then
|
|
irden_tmp <= irden_reg;
|
|
else
|
|
irden_tmp <= rden;
|
|
end if;
|
|
|
|
if (wraddress_reg = "INCLOCK") then
|
|
iwraddress_tmp <= iwraddress_reg;
|
|
else
|
|
iwraddress_tmp <= wraddress;
|
|
end if;
|
|
|
|
if (wrcontrol_reg = "INCLOCK") then
|
|
iwren_tmp <= iwren_reg;
|
|
else
|
|
iwren_tmp <= wren;
|
|
end if;
|
|
|
|
if (indata_reg = "INCLOCK") then
|
|
idata_tmp <= idata_reg;
|
|
else
|
|
idata_tmp <= data;
|
|
end if;
|
|
|
|
if (outdata_reg /= "UNREGISTERED") then
|
|
q <= iq_reg;
|
|
else
|
|
q <= iq_tmp;
|
|
end if;
|
|
|
|
if (aclr = '1') then
|
|
if( (indata_aclr = "ON") and ( indata_reg /= "UNREGISTERED") and not ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family)))) then
|
|
idata_tmp <= (OTHERS => '0');
|
|
end if;
|
|
|
|
if( (wraddress_aclr = "ON") and ( wraddress_reg /= "UNREGISTERED") and not ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family))))then
|
|
iwraddress_tmp <= (OTHERS => '0');
|
|
end if;
|
|
|
|
if( (wrcontrol_aclr = "ON") and ( wrcontrol_reg /= "UNREGISTERED") and not ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family))))then
|
|
iwren_tmp <= '0';
|
|
end if;
|
|
|
|
if( (rdaddress_aclr = "ON") and ( rdaddress_reg /= "UNREGISTERED") and not
|
|
((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family)))and (read_during_write_mode_mixed_ports = "OLD_DATA"))then
|
|
irdaddress_tmp <= (OTHERS => '0');
|
|
end if;
|
|
|
|
if( (rdcontrol_aclr = "ON") and ( rdcontrol_reg /= "UNREGISTERED") and not ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family))))then
|
|
irden_tmp <= '0';
|
|
end if;
|
|
|
|
if( (outdata_aclr = "ON") and (outdata_reg /= "UNREGISTERED") ) then
|
|
q <= (OTHERS => '0');
|
|
end if;
|
|
end if;
|
|
end process; -- sync
|
|
|
|
SYNC2: process( idata_hi, idata_lo, iwraddress_hi, iwraddress_lo,
|
|
iwren_hi, iwren_lo, write_at_low_clock,
|
|
i_byteena_mask_reg_hi, i_byteena_mask_reg_lo)
|
|
begin
|
|
if (write_at_low_clock) then
|
|
idata_reg <= idata_lo;
|
|
iwren_reg <= iwren_lo;
|
|
iwraddress_reg <= iwraddress_lo;
|
|
ibyteena_reg <= i_byteena_mask_reg_lo;
|
|
else
|
|
idata_reg <= idata_hi;
|
|
iwren_reg <= iwren_hi;
|
|
iwraddress_reg <= iwraddress_hi;
|
|
ibyteena_reg <= i_byteena_mask_reg_hi;
|
|
end if;
|
|
end process; -- sync2
|
|
|
|
|
|
IFG1: if (rdaddress_reg = "INCLOCK") generate
|
|
process (inclock, aclr)
|
|
begin
|
|
if ((aclr = '1') and (rdaddress_aclr = "ON") and
|
|
not ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family)))and (read_during_write_mode_mixed_ports = "OLD_DATA")) then
|
|
irdaddress_reg <= (OTHERS => '0');
|
|
elsif rising_edge(inclock) then
|
|
if ((inclocken = '1') and (rdaddressstall /= '1')) then
|
|
irdaddress_reg <= rdaddress;
|
|
end if;
|
|
end if;
|
|
|
|
if falling_edge(inclock) then
|
|
if (inclocken = '1') then
|
|
irdaddress_reg_low <= irdaddress_reg;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG1;
|
|
|
|
IFG2: if (rdcontrol_reg = "INCLOCK") generate
|
|
process (inclock, aclr)
|
|
begin
|
|
if ((aclr = '1') and (rdcontrol_aclr = "ON")) then
|
|
irden_reg <= '0';
|
|
elsif rising_edge(inclock) then
|
|
if (inclocken = '1') then
|
|
irden_reg <= rden;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG2;
|
|
|
|
IFG3: if (rdaddress_reg = "OUTCLOCK") generate
|
|
process (outclock, aclr)
|
|
begin
|
|
if ((aclr = '1') and (rdaddress_aclr = "ON") and
|
|
not ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family)))and (read_during_write_mode_mixed_ports = "OLD_DATA")) then
|
|
irdaddress_reg <= (OTHERS => '0');
|
|
elsif rising_edge(outclock) then
|
|
if ((outclocken = '1') and (rdaddressstall /= '1')) then
|
|
irdaddress_reg <= rdaddress;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG3;
|
|
|
|
IFG4: if (rdcontrol_reg = "OUTCLOCK") generate
|
|
process (outclock, aclr)
|
|
begin
|
|
if ((aclr = '1') and (rdcontrol_aclr = "ON")) then
|
|
irden_reg <= '0';
|
|
elsif rising_edge(outclock) then
|
|
if (outclocken = '1') then
|
|
irden_reg <= rden;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG4;
|
|
|
|
|
|
|
|
REGISTERS: process (inclock, outclock, aclr)
|
|
variable m_byteena_mask_reg : std_logic_vector(width - 1 downto 0);
|
|
variable m_byteena_mask_reg_out : std_logic_vector(width - 1 downto 0);
|
|
variable m_byteena_mask_reg_x : std_logic_vector(width - 1 downto 0):= (others => '0');
|
|
begin
|
|
|
|
-- WRITE REGS --
|
|
if ((aclr = '1') and (indata_aclr = "ON") and (indata_reg /= "UNREGISTERED") ) then
|
|
idata_hi <= (OTHERS => '0');
|
|
idata_lo <= (OTHERS => '0');
|
|
elsif rising_edge(inclock) then
|
|
if (inclocken = '1') then
|
|
idata_hi <= data;
|
|
end if;
|
|
elsif falling_edge(inclock) then
|
|
idata_lo <= idata_hi;
|
|
end if;
|
|
|
|
if ((aclr = '1') and (wraddress_aclr = "ON") and (wraddress_reg /= "UNREGISTERED") ) then
|
|
iwraddress_hi <= (OTHERS => '0');
|
|
iwraddress_lo <= (OTHERS => '0');
|
|
elsif rising_edge(inclock) then
|
|
if ((inclocken = '1') and (wraddressstall /= '1')) then
|
|
iwraddress_hi <= wraddress;
|
|
end if;
|
|
elsif falling_edge(inclock) then
|
|
iwraddress_lo <= iwraddress_hi;
|
|
end if;
|
|
|
|
if ((aclr = '1') and (wrcontrol_aclr = "ON") and (wrcontrol_reg /= "UNREGISTERED") ) then
|
|
iwren_hi <= '0';
|
|
iwren_lo <= '0';
|
|
elsif rising_edge(inclock) then
|
|
if (inclocken = '1') then
|
|
iwren_hi <= wren;
|
|
end if;
|
|
elsif falling_edge(inclock) then
|
|
iwren_lo <= iwren_hi;
|
|
end if;
|
|
|
|
if rising_edge(inclock) then
|
|
if (width_byteena = 1) then
|
|
m_byteena_mask_reg := (others => byteena(0));
|
|
if (byteena(0) = '1') then
|
|
m_byteena_mask_reg_out := (others => '0');
|
|
m_byteena_mask_reg_x := (others => '0');
|
|
elsif (byteena(0) = '0') then
|
|
m_byteena_mask_reg_x := (others => '0');
|
|
m_byteena_mask_reg_out := (others => 'X');
|
|
else
|
|
m_byteena_mask_reg_x := (others => 'X');
|
|
m_byteena_mask_reg_out := (others => 'X');
|
|
end if;
|
|
|
|
else
|
|
for k in 0 to (width - 1) loop
|
|
m_byteena_mask_reg(k) := byteena(k / i_byte_size);
|
|
if (m_byteena_mask_reg(k) = '1') then
|
|
m_byteena_mask_reg_out(k) := '0';
|
|
m_byteena_mask_reg_x(k) := '0';
|
|
elsif (m_byteena_mask_reg(k) = '0') then
|
|
m_byteena_mask_reg_x(k) := '0';
|
|
m_byteena_mask_reg_out(k) := 'X';
|
|
else
|
|
m_byteena_mask_reg_out(k) := 'X';
|
|
m_byteena_mask_reg_x(k) := 'X';
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
|
|
i_byteena_mask_reg_out_hi <= m_byteena_mask_reg_out;
|
|
i_byteena_mask_reg_hi <= m_byteena_mask_reg;
|
|
i_byteena_mask_reg_x_hi <= m_byteena_mask_reg_x;
|
|
|
|
if (inclocken = '1') then
|
|
first_clk_rising_edge <= false;
|
|
end if;
|
|
elsif falling_edge(inclock) then
|
|
|
|
i_byteena_mask_reg_out_lo <= i_byteena_mask_reg_out_hi;
|
|
i_byteena_mask_reg_lo <= i_byteena_mask_reg_hi;
|
|
i_byteena_mask_reg_x_lo <= i_byteena_mask_reg_x_hi;
|
|
|
|
end if;
|
|
|
|
-- READ REGS --
|
|
if ((aclr = '1') and (outdata_aclr = "ON") and ( outdata_reg /= "UNREGISTERED") ) then
|
|
iq_reg <= (OTHERS => '0');
|
|
elsif (rising_edge(outclock) and (outdata_reg = "OUTCLOCK")) then
|
|
if (outclocken = '1') then
|
|
iq_reg <= iq_tmp;
|
|
end if;
|
|
elsif (rising_edge(inclock) and (outdata_reg = "INCLOCK")) then
|
|
if (inclocken = '1') then
|
|
iq_reg <= iq_tmp;
|
|
end if;
|
|
end if;
|
|
|
|
end process; -- registers
|
|
|
|
MEMORY: process(idata_tmp, iwren_tmp, irden_tmp, irdaddress_tmp, iwraddress_tmp, ibyteena_tmp, rden_low_output_0, inclocken, first_clk_rising_edge)
|
|
variable mem_data : alt_memory;
|
|
variable mem_data_word : std_logic_vector(width-1 downto 0);
|
|
variable mem_init : boolean := false;
|
|
variable i : integer := 0;
|
|
variable j : integer := 0;
|
|
variable k : integer := 0;
|
|
variable n : integer := 0;
|
|
variable m : integer := 0;
|
|
variable lineno : integer := 0;
|
|
variable buf : line;
|
|
variable booval : boolean;
|
|
FILE mem_data_file : TEXT;
|
|
variable char : string(1 downto 1) := " ";
|
|
variable base : string(2 downto 1);
|
|
variable byte : string(2 downto 1);
|
|
variable rec_type : string(2 downto 1);
|
|
variable datain : string(2 downto 1);
|
|
variable addr : string(2 downto 1);
|
|
variable checksum : string(2 downto 1);
|
|
variable startadd: string(4 downto 1);
|
|
variable ibase : integer := 0;
|
|
variable ibyte : integer := 0;
|
|
variable istartadd : integer := 0;
|
|
variable check_sum_vec : std_logic_vector(7 downto 0);
|
|
variable check_sum_vec_tmp : std_logic_vector(7 downto 0);
|
|
variable m_write_event : std_logic := '0';
|
|
variable m_old_data : std_logic_vector(width-1 downto 0);
|
|
variable m_string : string(1 to 15);
|
|
variable m_data_radix : string(1 to 3);
|
|
variable m_address_radix : string(1 to 3);
|
|
variable m_width : integer;
|
|
variable m_depth : integer;
|
|
variable m_start_address_int : integer := 0;
|
|
variable m_end_address_int : integer := 0;
|
|
variable m_address_int : integer := 0;
|
|
variable m_data_int : std_logic_vector(width+4 downto 0) := (OTHERS => '0');
|
|
variable found_keyword_content : boolean := false;
|
|
variable get_memory_content : boolean := false;
|
|
variable get_start_Address : boolean := false;
|
|
variable get_end_Address : boolean := false;
|
|
begin
|
|
-- INITIALIZE --
|
|
if NOT(mem_init) then
|
|
-- INITIALIZE TO 0 --
|
|
for i in mem_data'LOW to mem_data'HIGH loop
|
|
mem_data(i) := (OTHERS => '0');
|
|
end loop;
|
|
|
|
if (lpm_file /= "UNUSED") then
|
|
FILE_OPEN(mem_data_file, LPM_FILE, READ_MODE);
|
|
if (ALPHA_TOLOWER(lpm_file(lpm_file'length -3 to lpm_file'length)) = ".hex") then
|
|
WHILE NOT ENDFILE(mem_data_file) loop
|
|
booval := true;
|
|
READLINE(mem_data_file, buf);
|
|
lineno := lineno + 1;
|
|
check_sum_vec := (OTHERS => '0');
|
|
|
|
if (buf(buf'LOW) = ':') then
|
|
i := 1;
|
|
SHRINK_LINE(buf, i);
|
|
READ(L=>buf, VALUE=>byte, good=>booval);
|
|
if (not booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
ibyte := HEX_STR_TO_INT(byte);
|
|
check_sum_vec := unsigned(check_sum_vec) +
|
|
unsigned(CONV_STD_LOGIC_VECTOR(ibyte, 8));
|
|
READ(L=>buf, VALUE=>startadd, good=>booval);
|
|
if (not booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
istartadd := HEX_STR_TO_INT(startadd);
|
|
addr(2) := startadd(4);
|
|
addr(1) := startadd(3);
|
|
check_sum_vec := unsigned(check_sum_vec) +
|
|
unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(addr), 8));
|
|
addr(2) := startadd(2);
|
|
addr(1) := startadd(1);
|
|
check_sum_vec := unsigned(check_sum_vec) +
|
|
unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(addr), 8));
|
|
READ(L=>buf, VALUE=>rec_type, good=>booval);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) +
|
|
unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(rec_type), 8));
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
case rec_type is
|
|
when "00"=> -- Data record
|
|
i := 0;
|
|
k := (WIDTH + 7) / 8; -- # of bytes per entry
|
|
while (i < ibyte) loop
|
|
mem_data_word := (others => '0');
|
|
j := 1;
|
|
while ( (j <= k) and (i < ibyte) ) loop
|
|
READ(L=>buf, VALUE=>datain,good=>booval); -- read in data a byte (2 hex chars) at a time.
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) +
|
|
unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), 8));
|
|
|
|
if (WIDTH > 8) then
|
|
mem_data_word := mem_data_word(WIDTH - 9 downto 0) & CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), 8);
|
|
else
|
|
mem_data_word := CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), WIDTH);
|
|
end if;
|
|
j := j + 1;
|
|
i := i + 1;
|
|
end loop;
|
|
|
|
if ((ibase + istartadd) <= (2 ** widthad - 1)) then
|
|
mem_data(ibase + istartadd) := mem_data_word;
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]: Unable to initialized memory with this data record since the specified address is out of valid address range!"
|
|
SEVERITY WARNING;
|
|
end if;
|
|
istartadd := istartadd + 1;
|
|
end loop;
|
|
when "01"=>
|
|
exit;
|
|
when "02"=>
|
|
ibase := 0;
|
|
if (ibyte /= 2) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format for record type 02! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (ibyte-1) loop
|
|
READ(L=>buf, VALUE=>base,good=>booval);
|
|
ibase := (ibase * 256) + HEX_STR_TO_INT(base);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) +
|
|
unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
|
|
end loop;
|
|
ibase := ibase * 16;
|
|
when "03"=>
|
|
if (ibyte /= 4) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format for record type 03! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (ibyte-1) loop
|
|
READ(L=>buf, VALUE=>base,good=>booval);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
|
|
end loop;
|
|
when "04"=>
|
|
ibase := 0;
|
|
if (ibyte /= 2) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format for record type 04! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (ibyte-1) loop
|
|
READ(L=>buf, VALUE=>base,good=>booval);
|
|
ibase := (ibase * 256) + HEX_STR_TO_INT(base);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
|
|
end loop;
|
|
ibase := ibase * 65536;
|
|
when "05"=>
|
|
if (ibyte /= 4) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format for record type 05! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (ibyte-1) loop
|
|
READ(L=>buf, VALUE=>base,good=>booval);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
|
|
end loop;
|
|
when OTHERS =>
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal record type in Intel Hex File! "
|
|
SEVERITY ERROR;
|
|
end case;
|
|
|
|
READ(L=>buf, VALUE=>checksum,good=>booval);
|
|
if (not booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Checksum is missing! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(not (check_sum_vec)) + 1 ;
|
|
check_sum_vec_tmp := CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(checksum),8);
|
|
|
|
if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Incorrect checksum!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
end loop;
|
|
elsif (ALPHA_TOLOWER(lpm_file(lpm_file'length -3 to lpm_file'length)) = ".mif") then
|
|
-- ************************************************
|
|
-- Read in RAM initialization file (mif)
|
|
-- ************************************************
|
|
while not endfile(mem_data_file) loop
|
|
booval := true;
|
|
readline(mem_data_file, buf);
|
|
lineno := lineno + 1;
|
|
LOOP2 : while (buf'length > 0) loop
|
|
if (buf(buf'low) = '-') then
|
|
if (buf(buf'low) = '-') then
|
|
-- ignore comment started with --.
|
|
exit LOOP2;
|
|
end if;
|
|
elsif (buf(buf'low) = '%') then
|
|
i := 1;
|
|
|
|
-- ignore comment which begin with % and end with another %.
|
|
while ((i < buf'high) and (buf(buf'low + i) /= '%')) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i >= buf'high) then
|
|
exit LOOP2;
|
|
else
|
|
SHRINK_LINE(buf, i+1);
|
|
end if;
|
|
elsif ((buf(buf'low) = ' ') or (buf(buf'low) = HT)) then
|
|
i := 1;
|
|
-- ignore space or tab character.
|
|
while ((i < buf'high-1) and ((buf(buf'low +i) = ' ') or
|
|
(buf(buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i >= buf'high) then
|
|
exit LOOP2;
|
|
else
|
|
SHRINK_LINE(buf, i);
|
|
end if;
|
|
elsif (get_memory_content = true) then
|
|
|
|
if ((buf(buf'low to buf'low +2) = "end") or
|
|
(buf(buf'low to buf'low +2) = "END") or
|
|
(buf(buf'low to buf'low +2) = "End")) then
|
|
get_memory_content := false;
|
|
exit LOOP2;
|
|
else
|
|
get_start_address := false;
|
|
get_end_address := false;
|
|
m_start_address_int := 0;
|
|
m_end_address_int := 0;
|
|
m_address_int := 0;
|
|
m_data_int := (others => '0');
|
|
if (buf(buf'low) = '[') then
|
|
get_start_Address := true;
|
|
SHRINK_LINE(buf, 1);
|
|
end if;
|
|
|
|
case m_address_radix is
|
|
when "hex" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ':') and (buf(buf'low) /= '.')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *16 + HEX_STR_TO_INT(char);
|
|
end loop;
|
|
when "bin" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ':') and (buf(buf'low) /= '.')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *2 + BIN_STR_TO_INT(char);
|
|
end loop;
|
|
when "dec" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ':') and (buf(buf'low) /= '.')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(char);
|
|
end loop;
|
|
when "uns" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ':') and (buf(buf'low) /= '.')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(char);
|
|
end loop;
|
|
when "oct" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ':') and (buf(buf'low) /= '.')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *8 + OCT_STR_TO_INT(char);
|
|
end loop;
|
|
when others =>
|
|
assert false
|
|
report "Unsupported address_radix!"
|
|
severity error;
|
|
end case;
|
|
|
|
if (get_start_Address = true) then
|
|
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < buf'high-1) and ((buf(buf'low +i) = ' ') or
|
|
(buf(buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(buf, i);
|
|
end if;
|
|
|
|
if ((buf(buf'low) = '.') and (buf(buf'low+1) = '.')) then
|
|
get_start_Address := false;
|
|
get_end_Address := true;
|
|
m_start_address_int := m_address_int;
|
|
SHRINK_LINE(buf, 2);
|
|
end if;
|
|
end if;
|
|
|
|
if (get_end_address = true) then
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < buf'high-1) and ((buf(buf'low +i) = ' ') or
|
|
(buf(buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(buf, i);
|
|
end if;
|
|
|
|
m_address_int := 0;
|
|
case m_address_radix is
|
|
when "hex" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ']')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *16 + HEX_STR_TO_INT(char);
|
|
end loop;
|
|
when "bin" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ']')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *2 + BIN_STR_TO_INT(char);
|
|
end loop;
|
|
when "dec" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ']')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(char);
|
|
end loop;
|
|
when "uns" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ']')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(char);
|
|
end loop;
|
|
when "oct" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ']')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *8 + OCT_STR_TO_INT(char);
|
|
end loop;
|
|
when others =>
|
|
assert false
|
|
report "Unsupported address_radix!"
|
|
severity error;
|
|
end case;
|
|
|
|
if (buf(buf'low) = ']') then
|
|
get_end_address := false;
|
|
m_end_address_int := m_address_int;
|
|
SHRINK_LINE(buf, 1);
|
|
end if;
|
|
end if;
|
|
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < buf'high-1) and ((buf(buf'low +i) = ' ') or
|
|
(buf(buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(buf, i);
|
|
end if;
|
|
|
|
if (buf(buf'low) = ':') then
|
|
SHRINK_LINE(buf, 1);
|
|
end if;
|
|
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < buf'high-1) and ((buf(buf'low +i) = ' ') or
|
|
(buf(buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(buf, i);
|
|
end if;
|
|
|
|
case m_data_radix is
|
|
when "hex" =>
|
|
while ((buf(buf'low) /= ';') and (buf(buf'low) /= ' ') and
|
|
(buf(buf'low) /= HT)) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_data_int(width+4 downto 0) := m_data_int(width-1 downto 0) * "10000" + conv_std_logic_vector(HEX_STR_TO_INT(char), 4);
|
|
end loop;
|
|
when "bin" =>
|
|
while ((buf(buf'low) /= ';') and (buf(buf'low) /= ' ') and
|
|
(buf(buf'low) /= HT)) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_data_int(width+1 downto 0) := m_data_int(width-1 downto 0) * "10" + conv_std_logic_vector(BIN_STR_TO_INT(char), 4);
|
|
end loop;
|
|
when "dec" =>
|
|
while ((buf(buf'low) /= ';') and (buf(buf'low) /= ' ') and
|
|
(buf(buf'low) /= HT)) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_data_int(width+3 downto 0) := m_data_int(width-1 downto 0) * "1010" + conv_std_logic_vector(INT_STR_TO_INT(char), 4);
|
|
end loop;
|
|
when "uns" =>
|
|
while ((buf(buf'low) /= ';') and (buf(buf'low) /= ' ') and
|
|
(buf(buf'low) /= HT)) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_data_int(width+3 downto 0) := m_data_int(width-1 downto 0) * "1010" + conv_std_logic_vector(INT_STR_TO_INT(char), 4);
|
|
end loop;
|
|
when "oct" =>
|
|
while ((buf(buf'low) /= ';') and (buf(buf'low) /= ' ') and
|
|
(buf(buf'low) /= HT)) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_data_int(width+3 downto 0) := m_data_int(width-1 downto 0) * "1000" + conv_std_logic_vector(OCT_STR_TO_INT(char), 4);
|
|
end loop;
|
|
when others =>
|
|
assert false
|
|
report "Unsupported data_radix!"
|
|
severity error;
|
|
end case;
|
|
|
|
if (m_start_address_int /= m_end_address_int) then
|
|
for i in m_start_address_int to m_end_address_int loop
|
|
mem_data(i) := m_data_int(width-1 downto 0);
|
|
end loop;
|
|
else
|
|
mem_data(m_address_int) := m_data_int(width-1 downto 0);
|
|
end if;
|
|
exit LOOP2;
|
|
end if;
|
|
elsif ((buf(buf'low) = 'W') or (buf(buf'low) = 'w')) then
|
|
read(l=>buf, value=>m_string(1 to 5));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 5)) = "width") then
|
|
i := 0;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (buf(buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((buf(buf'low +i) = ' ') or (buf(buf'low +i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(buf, i);
|
|
|
|
i := 0;
|
|
while (buf(buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>buf, value=>m_string(1 to i));
|
|
|
|
m_width := INT_STR_TO_INT(m_string(1 to i));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif (((buf(buf'low) = 'D') or (buf(buf'low) = 'd')) and
|
|
((buf(buf'low+1) = 'E') or (buf(buf'low+1) = 'e'))) then
|
|
read(l=>buf, value=>m_string(1 to 5));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 5)) = "depth") then
|
|
i := 0;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (buf(buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((buf(buf'low +i) = ' ') or (buf(buf'low +i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(buf, i);
|
|
|
|
i := 0;
|
|
while (buf(buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>buf, value=>m_string(1 to i));
|
|
|
|
m_depth := INT_STR_TO_INT(m_string(1 to i));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif ((buf(buf'low) = 'D') or (buf(buf'low) = 'd')) then
|
|
read(l=>buf, value=>m_string(1 to 10));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 10)) = "data_radix") then
|
|
i := 0;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (buf(buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(buf, i);
|
|
|
|
i := 0;
|
|
while (buf(buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>buf, value=>m_string(1 to 3));
|
|
|
|
m_data_radix := ALPHA_TOLOWER(m_string(1 to 3));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif ((buf(buf'low) = 'A') or (buf(buf'low) = 'a')) then
|
|
read(l=>buf, value=>m_string(1 to 13));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 13)) = "address_radix") then
|
|
i := 0;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (buf(buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(buf, i);
|
|
|
|
i := 0;
|
|
while (buf(buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>buf, value=>m_string(1 to 3));
|
|
|
|
m_address_radix := ALPHA_TOLOWER(m_string(1 to 3));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif ((buf(buf'low) = 'C') or (buf(buf'low) = 'c')) then
|
|
read(l=>buf, value=>m_string(1 to 7));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 7)) = "content") then
|
|
found_keyword_content := true;
|
|
end if;
|
|
elsif ((buf(buf'low) = 'B') or (buf(buf'low) = 'b')) then
|
|
read(l=>buf, value=>m_string(1 to 5));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 5)) = "begin") then
|
|
if (found_keyword_content = true) then
|
|
get_memory_content := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
|
|
else
|
|
assert false
|
|
report "Unsupported memory initialization file type (" & lpm_file(lpm_file'length -3 to lpm_file'length) & ")!"
|
|
severity error;
|
|
end if;
|
|
-- VHDL93 FILE_CLOSE(mem_data_file);
|
|
end if;
|
|
mem_init := TRUE;
|
|
|
|
else -- already initialized
|
|
|
|
if (iwren_tmp'event or iwraddress_tmp'event or idata_tmp'event or ibyteena_tmp'event) then
|
|
m_write_event := '1';
|
|
end if;
|
|
|
|
-- MEMORY FUNCTION --
|
|
-- Write and read data to and from the memory.
|
|
-- If write and read are at the same address, whatever wrote into
|
|
-- the memory will immediately reflected at the read results.
|
|
if ((iwren_tmp = '1') and (m_write_event = '1')) then
|
|
if ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
|
|
if (inclocken = '1') then
|
|
m_old_data := mem_data (ieee.std_logic_unsigned.conv_integer(iwraddress_tmp));
|
|
mem_data (ieee.std_logic_unsigned.conv_integer(iwraddress_tmp)) := ((idata_tmp and ibyteena_tmp) or
|
|
(mem_data(ieee.std_logic_unsigned.conv_integer(iwraddress_tmp)) and not ibyteena_tmp));
|
|
end if;
|
|
else
|
|
mem_data (ieee.std_logic_unsigned.conv_integer(iwraddress_tmp)) := idata_tmp;
|
|
end if;
|
|
end if;
|
|
|
|
m_write_event := '0';
|
|
|
|
if (irden_tmp = '1') then
|
|
if ((irdaddress_tmp = iwraddress_tmp) and (iwren_tmp = '1') and ((FEATURE_FAMILY_STRATIXV(intended_device_family)) or (FEATURE_FAMILY_STRATIXIII(intended_device_family)))) then
|
|
if ((i_read_during_write = "DONT_CARE") or (i_read_during_write = "CONSTRAINED_DONT_CARE")) then
|
|
iq_tmp <= (others => 'X');
|
|
elsif (i_read_during_write = "OLD_DATA") then
|
|
iq_tmp <= m_old_data;
|
|
else
|
|
iq_tmp <= mem_data(ieee.std_logic_unsigned.conv_integer(irdaddress_tmp));
|
|
end if;
|
|
elsif ((not first_clk_rising_edge) or (i_read_during_write /= "OLD_DATA")) then
|
|
iq_tmp <= mem_data(ieee.std_logic_unsigned.conv_integer(irdaddress_tmp));
|
|
end if;
|
|
elsif (rden_low_output_0) then
|
|
iq_tmp <= (OTHERS => '0');
|
|
end if;
|
|
|
|
end if; -- if NOT(mem_init)
|
|
|
|
end process; -- memory
|
|
|
|
end behavior; -- altdpram
|
|
|
|
---START_ENTITY_HEADER----------------------------------------------------------
|
|
--
|
|
-- Entity Name : ALTSYNCRAM
|
|
--
|
|
-- Description : Synchronous ram model for Stratix series family
|
|
--
|
|
-- Limitation :
|
|
--
|
|
---END_ENTITY_HEADER------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
use std.textio.all;
|
|
use work.ALTERA_COMMON_CONVERSION.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
|
|
-- BEGINNING OF ENTITY
|
|
|
|
-- ENTITY DECLARATION
|
|
|
|
entity altsyncram is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
-- PORT A PARAMETERS
|
|
width_a : integer := 1;
|
|
widthad_a : integer := 1;
|
|
numwords_a : integer := 0;
|
|
outdata_reg_a : string := "UNREGISTERED";
|
|
address_aclr_a : string := "NONE";
|
|
outdata_aclr_a : string := "NONE";
|
|
indata_aclr_a : string := "NONE";
|
|
wrcontrol_aclr_a : string := "NONE";
|
|
byteena_aclr_a : string := "NONE";
|
|
width_byteena_a : integer := 1;
|
|
clock_enable_input_a : string := "NORMAL";
|
|
clock_enable_output_a : string := "NORMAL";
|
|
clock_enable_core_a : string := "USE_INPUT_CLKEN";
|
|
read_during_write_mode_port_a : string := "NEW_DATA_NO_NBE_READ";
|
|
|
|
-- PORT B PARAMETERS
|
|
width_b : integer := 1;
|
|
widthad_b : integer := 1;
|
|
numwords_b : integer := 0;
|
|
rdcontrol_reg_b : string := "CLOCK1";
|
|
address_reg_b : string := "CLOCK1";
|
|
outdata_reg_b : string := "UNREGISTERED";
|
|
outdata_aclr_b : string := "NONE";
|
|
rdcontrol_aclr_b : string := "NONE";
|
|
indata_reg_b : string := "CLOCK1";
|
|
wrcontrol_wraddress_reg_b : string := "CLOCK1";
|
|
byteena_reg_b : string := "CLOCK1";
|
|
indata_aclr_b : string := "NONE";
|
|
wrcontrol_aclr_b : string := "NONE";
|
|
address_aclr_b : string := "NONE";
|
|
byteena_aclr_b : string := "NONE";
|
|
width_byteena_b : integer := 1;
|
|
clock_enable_input_b : string := "NORMAL";
|
|
clock_enable_output_b : string := "NORMAL";
|
|
clock_enable_core_b : string := "USE_INPUT_CLKEN";
|
|
read_during_write_mode_port_b : string := "NEW_DATA_NO_NBE_READ";
|
|
|
|
-- ECC STATUS PARAMETERS
|
|
enable_ecc : string := "FALSE";
|
|
width_eccstatus : integer := 3;
|
|
ecc_pipeline_stage_enabled : string := "FALSE";
|
|
|
|
-- GLOBAL PARAMETERS
|
|
operation_mode : string := "BIDIR_DUAL_PORT";
|
|
byte_size : integer := 0;
|
|
read_during_write_mode_mixed_ports : string := "DONT_CARE";
|
|
ram_block_type : string := "AUTO";
|
|
init_file : string := "UNUSED";
|
|
init_file_layout : string := "UNUSED";
|
|
maximum_depth : integer := 0;
|
|
intended_device_family : string := "Stratix";
|
|
power_up_uninitialized : string := "FALSE";
|
|
implement_in_les : string := "OFF";
|
|
sim_show_memory_data_in_port_b_layout : string := "OFF";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altsyncram"
|
|
);
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
wren_a : in std_logic := '0'; -- Port A write/read enable input
|
|
wren_b : in std_logic := '0'; -- Port B write enable input
|
|
rden_a : in std_logic := '1'; -- Port A read enable input
|
|
rden_b : in std_logic := '1'; -- Port B read enable input
|
|
data_a : in std_logic_vector(width_a - 1 downto 0) := (others => '1');
|
|
-- Port A data input
|
|
data_b : in std_logic_vector(width_b - 1 downto 0) := (others => '1');
|
|
-- Port B data input
|
|
address_a : in std_logic_vector(widthad_a - 1 downto 0);
|
|
-- Port A address input
|
|
address_b : in std_logic_vector(widthad_b - 1 downto 0) := (others => '1');
|
|
-- Port B address input
|
|
|
|
-- clock inputs on both ports and here are their usages:
|
|
-- Port A
|
|
-- 1. all input registers must be clocked by clock0.
|
|
-- 2. output register can be clocked by either by clock0, clock1 or none.
|
|
-- Port B
|
|
-- 1. all input registers must be clocked by either clock0 or clock1.
|
|
-- 2. output register can be clocked by either clock0, clock1 or none.
|
|
clock0 : in std_logic := '1';
|
|
clock1 : in std_logic := 'Z';
|
|
|
|
-- clock enable inputs and here are their usages:
|
|
-- clocken0 -- can only be used for enabling clock0.
|
|
-- clocken1 -- can only be used for enabling clock1.
|
|
-- clocken2 -- as an alternative for enabling clock0.
|
|
-- clocken3 -- as an alternative for enabling clock1.
|
|
clocken0 : in std_logic := '1';
|
|
clocken1 : in std_logic := '1';
|
|
clocken2 : in std_logic := '1';
|
|
clocken3 : in std_logic := '1';
|
|
|
|
-- clear inputs on both ports and here are their usages:
|
|
-- Port A
|
|
-- 1. all input registers can only be cleared by clear0 or none.
|
|
-- 2. output register can be cleared by either clear0, clear1 or none.
|
|
-- Port B
|
|
-- 1. all input registers can be cleared by either clear0, clear1 or none.
|
|
-- 2. output register can be cleared by either clear0, clear1 or none.
|
|
aclr0 : in std_logic := '0';
|
|
aclr1 : in std_logic := '0';
|
|
|
|
addressstall_a : in std_logic := '0';
|
|
addressstall_b : in std_logic := '0';
|
|
|
|
byteena_a : in std_logic_vector( (width_byteena_a) - 1 downto 0) := (others => '1');
|
|
-- Port A byte enable input
|
|
byteena_b : in std_logic_vector( (width_byteena_b) - 1 downto 0) := (others => 'Z');
|
|
-- Port B byte enable input
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
q_a : out std_logic_vector(width_a - 1 downto 0); -- Port A output
|
|
q_b : out std_logic_vector(width_b - 1 downto 0); -- Port B output
|
|
|
|
-- ECC status flag
|
|
eccstatus : out std_logic_vector(width_eccstatus-1 downto 0) := (others => '0')
|
|
);
|
|
|
|
-- TYPE DECLARATION
|
|
|
|
type width_a_array is array (2 ** widthad_a - 1 downto 0) of std_logic_vector(width_a - 1 downto 0);
|
|
type width_b_array is array (2 ** widthad_b - 1 downto 0) of std_logic_vector(width_b - 1 downto 0);
|
|
|
|
|
|
-- FUNCTION DEFINITION
|
|
|
|
-- This procedure read the hex file into the memory content
|
|
procedure read_my_memory (
|
|
constant use_a : in boolean;
|
|
variable mem_data_a : out width_a_array;
|
|
variable mem_data_b : out width_b_array
|
|
) is
|
|
|
|
variable m_mem_data_word_a : std_logic_vector(width_a-1 downto 0);
|
|
variable m_mem_data_word_b : std_logic_vector(width_b-1 downto 0);
|
|
variable i : integer := 0;
|
|
variable j : integer := 0;
|
|
variable m_num_of_bytes : integer := 0;
|
|
variable m_line_no : integer := 0;
|
|
variable m_line_buf : line ;
|
|
variable m_err_check : boolean := true;
|
|
variable m_base : string(2 downto 1);
|
|
variable m_ibase : integer := 0;
|
|
variable m_byte_str : string(2 downto 1);
|
|
variable m_rec_type : string(2 downto 1);
|
|
variable m_datain : string(2 downto 1);
|
|
variable m_character : string(1 downto 1);
|
|
variable m_addr : string(2 downto 1);
|
|
variable m_checksum : string(2 downto 1);
|
|
variable m_startadd : string(4 downto 1);
|
|
variable m_istartadd : integer := 0;
|
|
variable m_istartadd_pre : integer := 0;
|
|
variable m_byte_int : integer := 0;
|
|
variable m_check_sum_vec : std_logic_vector(7 downto 0);
|
|
variable m_check_sum_vec_tmp : std_logic_vector(7 downto 0);
|
|
variable m_string : string(1 to 15);
|
|
variable m_data_radix : string(1 to 3);
|
|
variable m_address_radix : string(1 to 3);
|
|
variable m_width : integer;
|
|
variable m_depth : integer;
|
|
variable m_start_address_int : integer := 0;
|
|
variable m_end_address_int : integer := 0;
|
|
variable m_address_int : integer := 0;
|
|
variable m_data_int : std_logic_vector(width_a+width_b+4 downto 0) := (OTHERS => '0');
|
|
variable found_keyword_content : boolean := false;
|
|
variable get_memory_content : boolean := false;
|
|
variable get_start_Address : boolean := false;
|
|
variable get_end_Address : boolean := false;
|
|
variable m_divide_factor : integer := 1;
|
|
variable first_normal_record : boolean := true;
|
|
variable is_word_address_format : boolean := false;
|
|
file m_mem_data_file : text;
|
|
|
|
begin
|
|
|
|
-- Initialize memory content
|
|
if (use_a) then
|
|
for i in mem_data_a'low to mem_data_a'high loop
|
|
mem_data_a(i) := (others => '0');
|
|
end loop;
|
|
else
|
|
for i in mem_data_b'low to mem_data_b'high loop
|
|
mem_data_b(i) := (others => '0');
|
|
end loop;
|
|
end if;
|
|
|
|
file_open(m_mem_data_file, init_file, read_mode);
|
|
|
|
if (ALPHA_TOLOWER(init_file(init_file'right -3 to init_file'right)) = ".hex") then
|
|
while not endfile(m_mem_data_file) loop
|
|
m_err_check := true;
|
|
readline(m_mem_data_file, m_line_buf);
|
|
m_line_no := m_line_no + 1;
|
|
m_check_sum_vec := (others=> '0');
|
|
|
|
if (m_line_buf(m_line_buf'low) = ':') then
|
|
i := 1;
|
|
SHRINK_LINE(m_line_buf, i);
|
|
read(l=>m_line_buf, value=>m_byte_str, good=>m_err_check);
|
|
|
|
if not (m_err_check) then
|
|
assert false
|
|
report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format!"
|
|
severity error;
|
|
end if;
|
|
|
|
m_byte_int := HEX_STR_TO_INT(m_byte_str);
|
|
m_check_sum_vec := unsigned(m_check_sum_vec) +
|
|
unsigned(conv_std_logic_vector(m_byte_int, 8));
|
|
read(l=>m_line_buf, value=>m_startadd, good=>m_err_check);
|
|
|
|
if not (m_err_check) then
|
|
assert false
|
|
report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format! "
|
|
severity error;
|
|
end if;
|
|
m_istartadd_pre := m_istartadd;
|
|
m_istartadd := HEX_STR_TO_INT(m_startadd);
|
|
m_addr(2) := m_startadd(4);
|
|
m_addr(1) := m_startadd(3);
|
|
m_check_sum_vec := unsigned(m_check_sum_vec) +
|
|
unsigned(conv_std_logic_vector(HEX_STR_TO_INT(m_addr), 8));
|
|
m_addr(2) := m_startadd(2);
|
|
m_addr(1) := m_startadd(1);
|
|
m_check_sum_vec := unsigned(m_check_sum_vec) +
|
|
unsigned(conv_std_logic_vector(HEX_STR_TO_INT(m_addr), 8));
|
|
read(l=>m_line_buf, value=>m_rec_type, good=>m_err_check);
|
|
|
|
if not (m_err_check) then
|
|
assert false
|
|
report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format! "
|
|
severity error;
|
|
end if;
|
|
|
|
m_check_sum_vec := unsigned(m_check_sum_vec) +
|
|
unsigned(conv_std_logic_vector(HEX_STR_TO_INT(m_rec_type), 8));
|
|
|
|
else
|
|
assert false
|
|
report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format! "
|
|
severity error;
|
|
end if;
|
|
|
|
case m_rec_type is
|
|
when "00"=> -- Data record
|
|
i := 0;
|
|
if (use_a) then
|
|
m_num_of_bytes := (width_a + 7) / 8;
|
|
else
|
|
m_num_of_bytes := (width_b + 7) / 8;
|
|
end if;
|
|
|
|
if ((first_normal_record = false) and (m_istartadd /= m_num_of_bytes)) then
|
|
is_word_address_format := true;
|
|
end if;
|
|
|
|
first_normal_record := false;
|
|
|
|
if ((m_istartadd = m_num_of_bytes) and (is_word_address_format = false)) then
|
|
m_divide_factor := m_num_of_bytes;
|
|
end if;
|
|
|
|
while (i < m_byte_int) loop
|
|
|
|
if (use_a) then
|
|
m_mem_data_word_a := (others => '0');
|
|
else
|
|
m_mem_data_word_b := (others => '0');
|
|
end if;
|
|
|
|
j := 1;
|
|
while ( j <= m_num_of_bytes and i < m_byte_int ) loop
|
|
read(l => m_line_buf, value => m_datain, good => m_err_check);
|
|
if not (m_err_check) then
|
|
assert false
|
|
report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format! "
|
|
severity error;
|
|
end if;
|
|
|
|
m_check_sum_vec := unsigned(m_check_sum_vec) +
|
|
unsigned(conv_std_logic_vector(HEX_STR_TO_INT(m_datain), 8));
|
|
|
|
if (use_a) then
|
|
if (width_a > 8) then
|
|
m_mem_data_word_a := m_mem_data_word_a(width_a - 9 downto 0) & conv_std_logic_vector(HEX_STR_TO_INT(m_datain), 8);
|
|
else
|
|
m_mem_data_word_a := conv_std_logic_vector(HEX_STR_TO_INT(m_datain), width_a);
|
|
end if;
|
|
else
|
|
if (width_b > 8) then
|
|
m_mem_data_word_b := m_mem_data_word_b(width_b - 9 downto 0) & conv_std_logic_vector(HEX_STR_TO_INT(m_datain), 8);
|
|
else
|
|
m_mem_data_word_b := conv_std_logic_vector(HEX_STR_TO_INT(m_datain), width_b);
|
|
end if;
|
|
end if;
|
|
|
|
|
|
j := j + 1;
|
|
i := i + 1;
|
|
end loop;
|
|
|
|
if ((use_a) and ((m_ibase + m_istartadd) / m_divide_factor <= (2 ** widthad_a - 1)))then
|
|
mem_data_a((m_ibase + m_istartadd) / m_divide_factor) := m_mem_data_word_a;
|
|
elsif ((m_ibase + m_istartadd) / m_divide_factor <= (2 ** widthad_b - 1)) then
|
|
mem_data_b((m_ibase + m_istartadd) / m_divide_factor) := m_mem_data_word_b;
|
|
else
|
|
assert false
|
|
report "[Line "& INT_TO_STR_RAM(m_line_no) & "]: Unable to initialized memory with this data record since the specified address is out of valid address range!"
|
|
severity warning;
|
|
end if;
|
|
m_istartadd := m_istartadd + 1;
|
|
end loop;
|
|
|
|
when "01"=>
|
|
exit;
|
|
|
|
when "02"=>
|
|
m_ibase := 0;
|
|
if (m_byte_int /= 2) then
|
|
assert false
|
|
report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format for record type 02! "
|
|
severity error;
|
|
end if;
|
|
|
|
for i in 0 to (m_byte_int-1) loop
|
|
read(l=>m_line_buf, value=>m_base,good=>m_err_check);
|
|
m_ibase := m_ibase * 256 + HEX_STR_TO_INT(m_base);
|
|
|
|
if not (m_err_check) then
|
|
assert false
|
|
report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format! "
|
|
severity error;
|
|
end if;
|
|
|
|
m_check_sum_vec := unsigned(m_check_sum_vec) +
|
|
unsigned(conv_std_logic_vector(HEX_STR_TO_INT(m_base), 8));
|
|
end loop;
|
|
|
|
m_ibase := m_ibase * 16;
|
|
|
|
when "03"=>
|
|
if (m_byte_int /= 4) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(m_line_no) &
|
|
"]:Illegal Intel Hex Format for record type 03! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (m_byte_int-1) loop
|
|
READ(L=>m_line_buf, VALUE=>m_base,good=>m_err_check);
|
|
if not (m_err_check) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(m_line_no) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
m_check_sum_vec := unsigned(m_check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(m_base), 8));
|
|
end loop;
|
|
when "04"=>
|
|
m_ibase := 0;
|
|
if (m_byte_int /= 2) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(m_line_no) &
|
|
"]:Illegal Intel Hex Format for record type 04! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (m_byte_int-1) loop
|
|
READ(L=>m_line_buf, VALUE=>m_base,good=>m_err_check);
|
|
m_ibase := (m_ibase * 256) + HEX_STR_TO_INT(m_base);
|
|
if not (m_err_check) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(m_line_no) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
m_check_sum_vec := unsigned(m_check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(m_base), 8));
|
|
end loop;
|
|
m_ibase := m_ibase * 65536;
|
|
when "05"=>
|
|
if (m_byte_int /= 4) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(m_line_no) &
|
|
"]:Illegal Intel Hex Format for record type 05! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (m_byte_int-1) loop
|
|
READ(L=>m_line_buf, VALUE=>m_base,good=>m_err_check);
|
|
if not (m_err_check) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(m_line_no) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
m_check_sum_vec := unsigned(m_check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(m_base), 8));
|
|
end loop;
|
|
|
|
when others=>
|
|
assert false
|
|
report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal record type in Intel Hex File! "
|
|
severity error;
|
|
|
|
end case;
|
|
|
|
read(l=>m_line_buf, value=>m_checksum, good=>m_err_check);
|
|
|
|
if not (m_err_check) then
|
|
assert false
|
|
report"[Line "& INT_TO_STR_RAM(m_line_no) & "]:Checksum is missing! "
|
|
severity error;
|
|
end if;
|
|
|
|
m_check_sum_vec := unsigned(not (m_check_sum_vec)) + 1;
|
|
m_check_sum_vec_tmp := conv_std_logic_vector(HEX_STR_TO_INT(m_checksum),8);
|
|
|
|
if (unsigned(m_check_sum_vec) /= unsigned(m_check_sum_vec_tmp)) then
|
|
assert false
|
|
report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Incorrect checksum!"
|
|
severity error;
|
|
end if;
|
|
end loop;
|
|
elsif (ALPHA_TOLOWER(init_file(init_file'length -3 to init_file'length)) = ".mif") then
|
|
while not endfile(m_mem_data_file) loop
|
|
m_err_check := true;
|
|
readline(m_mem_data_file, m_line_buf);
|
|
m_line_no := m_line_no + 1;
|
|
m_check_sum_vec := (others=> '0');
|
|
LOOP2 : while (m_line_buf'length > 0) loop
|
|
if (m_line_buf(m_line_buf'low) = CR) then
|
|
-- strip out CR (carriage return) character.
|
|
exit LOOP2;
|
|
elsif (m_line_buf(m_line_buf'low) = LF) then
|
|
-- strip out LF (line feed) character.
|
|
exit LOOP2;
|
|
elsif (m_line_buf(m_line_buf'low) = '-') then
|
|
if (m_line_buf(m_line_buf'low) = '-') then
|
|
-- ignore comment started with --.
|
|
exit LOOP2;
|
|
end if;
|
|
elsif (m_line_buf(m_line_buf'low) = '%') then
|
|
i := 1;
|
|
|
|
-- ignore comment which begin with % and end with another %.
|
|
while ((i < m_line_buf'high) and (m_line_buf(m_line_buf'low + i) /= '%')) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i >= m_line_buf'high) then
|
|
exit LOOP2;
|
|
else
|
|
SHRINK_LINE(m_line_buf, i+1);
|
|
end if;
|
|
elsif ((m_line_buf(m_line_buf'low) = ' ') or (m_line_buf(m_line_buf'low) = HT)) then
|
|
i := 1;
|
|
-- ignore space or tab character.
|
|
while ((i < m_line_buf'high-1) and ((m_line_buf(m_line_buf'low +i) = ' ') or
|
|
(m_line_buf(m_line_buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i >= m_line_buf'high) then
|
|
exit LOOP2;
|
|
else
|
|
SHRINK_LINE(m_line_buf, i);
|
|
end if;
|
|
elsif (get_memory_content = true) then
|
|
|
|
if ((m_line_buf(m_line_buf'low to m_line_buf'low +2) = "end") or
|
|
(m_line_buf(m_line_buf'low to m_line_buf'low +2) = "END") or
|
|
(m_line_buf(m_line_buf'low to m_line_buf'low +2) = "End")) then
|
|
get_memory_content := false;
|
|
exit LOOP2;
|
|
else
|
|
get_start_address := false;
|
|
get_end_address := false;
|
|
m_start_address_int := 0;
|
|
m_end_address_int := 0;
|
|
m_address_int := 0;
|
|
m_data_int := (others => '0');
|
|
if (m_line_buf(m_line_buf'low) = '[') then
|
|
get_start_Address := true;
|
|
SHRINK_LINE(m_line_buf, 1);
|
|
end if;
|
|
|
|
case m_address_radix is
|
|
when "hex" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ' ') and (m_line_buf(m_line_buf'low) /= HT) and
|
|
(m_line_buf(m_line_buf'low) /= ':') and (m_line_buf(m_line_buf'low) /= '.')) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_address_int := m_address_int *16 + HEX_STR_TO_INT(m_character);
|
|
end loop;
|
|
when "bin" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ' ') and (m_line_buf(m_line_buf'low) /= HT) and
|
|
(m_line_buf(m_line_buf'low) /= ':') and (m_line_buf(m_line_buf'low) /= '.')) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_address_int := m_address_int *2 + BIN_STR_TO_INT(m_character);
|
|
end loop;
|
|
when "dec" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ' ') and (m_line_buf(m_line_buf'low) /= HT) and
|
|
(m_line_buf(m_line_buf'low) /= ':') and (m_line_buf(m_line_buf'low) /= '.')) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(m_character);
|
|
end loop;
|
|
when "uns" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ' ') and (m_line_buf(m_line_buf'low) /= HT) and
|
|
(m_line_buf(m_line_buf'low) /= ':') and (m_line_buf(m_line_buf'low) /= '.')) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(m_character);
|
|
end loop;
|
|
when "oct" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ' ') and (m_line_buf(m_line_buf'low) /= HT) and
|
|
(m_line_buf(m_line_buf'low) /= ':') and (m_line_buf(m_line_buf'low) /= '.')) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_address_int := m_address_int *8 + OCT_STR_TO_INT(m_character);
|
|
end loop;
|
|
when others =>
|
|
assert false
|
|
report "Unsupported address_radix!"
|
|
severity error;
|
|
end case;
|
|
|
|
if (get_start_Address = true) then
|
|
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < m_line_buf'high-1) and ((m_line_buf(m_line_buf'low +i) = ' ') or
|
|
(m_line_buf(m_line_buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(m_line_buf, i);
|
|
end if;
|
|
|
|
if ((m_line_buf(m_line_buf'low) = '.') and (m_line_buf(m_line_buf'low+1) = '.')) then
|
|
get_start_Address := false;
|
|
get_end_Address := true;
|
|
m_start_address_int := m_address_int;
|
|
SHRINK_LINE(m_line_buf, 2);
|
|
end if;
|
|
end if;
|
|
|
|
if (get_end_address = true) then
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < m_line_buf'high-1) and ((m_line_buf(m_line_buf'low +i) = ' ') or
|
|
(m_line_buf(m_line_buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(m_line_buf, i);
|
|
end if;
|
|
|
|
m_address_int := 0;
|
|
case m_address_radix is
|
|
when "hex" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ' ') and (m_line_buf(m_line_buf'low) /= HT) and
|
|
(m_line_buf(m_line_buf'low) /= ']')) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_address_int := m_address_int *16 + HEX_STR_TO_INT(m_character);
|
|
end loop;
|
|
when "bin" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ' ') and (m_line_buf(m_line_buf'low) /= HT) and
|
|
(m_line_buf(m_line_buf'low) /= ']')) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_address_int := m_address_int *2 + BIN_STR_TO_INT(m_character);
|
|
end loop;
|
|
when "dec" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ' ') and (m_line_buf(m_line_buf'low) /= HT) and
|
|
(m_line_buf(m_line_buf'low) /= ']')) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(m_character);
|
|
end loop;
|
|
when "uns" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ' ') and (m_line_buf(m_line_buf'low) /= HT) and
|
|
(m_line_buf(m_line_buf'low) /= ']')) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(m_character);
|
|
end loop;
|
|
when "oct" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ' ') and (m_line_buf(m_line_buf'low) /= HT) and
|
|
(m_line_buf(m_line_buf'low) /= ']')) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_address_int := m_address_int *8 + OCT_STR_TO_INT(m_character);
|
|
end loop;
|
|
when others =>
|
|
assert false
|
|
report "Unsupported address_radix!"
|
|
severity error;
|
|
end case;
|
|
|
|
if (m_line_buf(m_line_buf'low) = ']') then
|
|
get_end_address := false;
|
|
m_end_address_int := m_address_int;
|
|
SHRINK_LINE(m_line_buf, 1);
|
|
end if;
|
|
end if;
|
|
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < m_line_buf'high-1) and ((m_line_buf(m_line_buf'low +i) = ' ') or
|
|
(m_line_buf(m_line_buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(m_line_buf, i);
|
|
end if;
|
|
|
|
if (m_line_buf(m_line_buf'low) = ':') then
|
|
SHRINK_LINE(m_line_buf, 1);
|
|
end if;
|
|
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < m_line_buf'high-1) and ((m_line_buf(m_line_buf'low +i) = ' ') or
|
|
(m_line_buf(m_line_buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(m_line_buf, i);
|
|
end if;
|
|
|
|
case m_data_radix is
|
|
when "hex" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ';') and (m_line_buf(m_line_buf'low) /= ' ') and
|
|
(m_line_buf(m_line_buf'low) /= HT)) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_data_int(width_a+width_b+4 downto 0) := m_data_int(width_a+width_b-1 downto 0) * "10000" + conv_std_logic_vector(HEX_STR_TO_INT(m_character), 4);
|
|
end loop;
|
|
when "bin" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ';') and (m_line_buf(m_line_buf'low) /= ' ') and
|
|
(m_line_buf(m_line_buf'low) /= HT)) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_data_int(width_a+width_b+1 downto 0) := m_data_int(width_a+width_b-1 downto 0) * "10" + conv_std_logic_vector(BIN_STR_TO_INT(m_character), 4);
|
|
end loop;
|
|
when "dec" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ';') and (m_line_buf(m_line_buf'low) /= ' ') and
|
|
(m_line_buf(m_line_buf'low) /= HT)) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_data_int(width_a+width_b+3 downto 0) := m_data_int(width_a+width_b-1 downto 0) * "1010" + conv_std_logic_vector(INT_STR_TO_INT(m_character), 4);
|
|
end loop;
|
|
when "uns" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ';') and (m_line_buf(m_line_buf'low) /= ' ') and
|
|
(m_line_buf(m_line_buf'low) /= HT)) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_data_int(width_a+width_b+3 downto 0) := m_data_int(width_a+width_b-1 downto 0) * "1010" + conv_std_logic_vector(INT_STR_TO_INT(m_character), 4);
|
|
end loop;
|
|
when "oct" =>
|
|
while ((m_line_buf(m_line_buf'low) /= ';') and (m_line_buf(m_line_buf'low) /= ' ') and
|
|
(m_line_buf(m_line_buf'low) /= HT)) loop
|
|
read(l => m_line_buf, value => m_character, good => m_err_check);
|
|
m_data_int(width_a+width_b+3 downto 0) := m_data_int(width_a+width_b-1 downto 0) * "1000" + conv_std_logic_vector(OCT_STR_TO_INT(m_character), 4);
|
|
end loop;
|
|
when others =>
|
|
assert false
|
|
report "Unsupported data_radix!"
|
|
severity error;
|
|
end case;
|
|
|
|
if (use_a) then
|
|
if (m_start_address_int /= m_end_address_int) then
|
|
for i in m_start_address_int to m_end_address_int loop
|
|
mem_data_a(i) := m_data_int(width_a-1 downto 0);
|
|
end loop;
|
|
else
|
|
mem_data_a(m_address_int) := m_data_int(width_a-1 downto 0);
|
|
end if;
|
|
else
|
|
if (m_start_address_int /= m_end_address_int) then
|
|
for i in m_start_address_int to m_end_address_int loop
|
|
mem_data_b(i) := m_data_int(width_b-1 downto 0);
|
|
end loop;
|
|
else
|
|
mem_data_b(m_address_int) := m_data_int(width_b-1 downto 0);
|
|
end if;
|
|
end if;
|
|
exit LOOP2;
|
|
end if;
|
|
elsif ((m_line_buf(m_line_buf'low) = 'W') or (m_line_buf(m_line_buf'low) = 'w')) then
|
|
read(l=>m_line_buf, value=>m_string(1 to 5));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 5)) = "width") then
|
|
i := 0;
|
|
|
|
while ((m_line_buf(m_line_buf'low+i) = ' ') or (m_line_buf(m_line_buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (m_line_buf(m_line_buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((m_line_buf(m_line_buf'low +i) = ' ') or (m_line_buf(m_line_buf'low +i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(m_line_buf, i);
|
|
|
|
i := 0;
|
|
while (m_line_buf(m_line_buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>m_line_buf, value=>m_string(1 to i));
|
|
|
|
m_width := INT_STR_TO_INT(m_string(1 to i));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif (((m_line_buf(m_line_buf'low) = 'D') or (m_line_buf(m_line_buf'low) = 'd')) and
|
|
((m_line_buf(m_line_buf'low+1) = 'E') or (m_line_buf(m_line_buf'low+1) = 'e'))) then
|
|
read(l=>m_line_buf, value=>m_string(1 to 5));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 5)) = "depth") then
|
|
i := 0;
|
|
|
|
while ((m_line_buf(m_line_buf'low+i) = ' ') or (m_line_buf(m_line_buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (m_line_buf(m_line_buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((m_line_buf(m_line_buf'low +i) = ' ') or (m_line_buf(m_line_buf'low +i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(m_line_buf, i);
|
|
|
|
i := 0;
|
|
while (m_line_buf(m_line_buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>m_line_buf, value=>m_string(1 to i));
|
|
|
|
m_depth := INT_STR_TO_INT(m_string(1 to i));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif ((m_line_buf(m_line_buf'low) = 'D') or (m_line_buf(m_line_buf'low) = 'd')) then
|
|
read(l=>m_line_buf, value=>m_string(1 to 10));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 10)) = "data_radix") then
|
|
i := 0;
|
|
|
|
while ((m_line_buf(m_line_buf'low+i) = ' ') or (m_line_buf(m_line_buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (m_line_buf(m_line_buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((m_line_buf(m_line_buf'low+i) = ' ') or (m_line_buf(m_line_buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(m_line_buf, i);
|
|
|
|
i := 0;
|
|
while (m_line_buf(m_line_buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>m_line_buf, value=>m_string(1 to 3));
|
|
|
|
m_data_radix := ALPHA_TOLOWER(m_string(1 to 3));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif ((m_line_buf(m_line_buf'low) = 'A') or (m_line_buf(m_line_buf'low) = 'a')) then
|
|
read(l=>m_line_buf, value=>m_string(1 to 13));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 13)) = "address_radix") then
|
|
i := 0;
|
|
|
|
while ((m_line_buf(m_line_buf'low+i) = ' ') or (m_line_buf(m_line_buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (m_line_buf(m_line_buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((m_line_buf(m_line_buf'low+i) = ' ') or (m_line_buf(m_line_buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(m_line_buf, i);
|
|
|
|
i := 0;
|
|
while (m_line_buf(m_line_buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>m_line_buf, value=>m_string(1 to 3));
|
|
|
|
m_address_radix := ALPHA_TOLOWER(m_string(1 to 3));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif ((m_line_buf(m_line_buf'low) = 'C') or (m_line_buf(m_line_buf'low) = 'c')) then
|
|
read(l=>m_line_buf, value=>m_string(1 to 7));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 7)) = "content") then
|
|
found_keyword_content := true;
|
|
end if;
|
|
elsif ((m_line_buf(m_line_buf'low) = 'B') or (m_line_buf(m_line_buf'low) = 'b')) then
|
|
read(l=>m_line_buf, value=>m_string(1 to 5));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 5)) = "begin") then
|
|
if (found_keyword_content = true) then
|
|
get_memory_content := true;
|
|
end if;
|
|
end if;
|
|
else
|
|
assert false
|
|
report "MIF contains illegal character" & m_line_buf(m_line_buf'low)
|
|
severity error;
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
|
|
else
|
|
assert false
|
|
report "Unsupported memory initialization file type (" & init_file(init_file'length -3 to init_file'length) & ")!"
|
|
severity error;
|
|
end if;
|
|
file_close(m_mem_data_file);
|
|
end read_my_memory;
|
|
|
|
end altsyncram;
|
|
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
architecture translated of altsyncram is
|
|
|
|
function is_lutram (ram_block_type : string) return boolean is
|
|
begin
|
|
if ((ram_block_type = "LUTRAM") or (ram_block_type = "MLAB")) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
end is_lutram;
|
|
|
|
function get_write_mode(read_during_write_mode_mixed_ports : string; device : string) return string is
|
|
begin
|
|
if (FEATURE_FAMILY_CYCLONE(device) or FEATURE_FAMILY_CYCLONEII(device)) then
|
|
return "OLD_DATA";
|
|
elsif (read_during_write_mode_mixed_ports = "UNUSED") or
|
|
(read_during_write_mode_mixed_ports = "DONT_CARE") then
|
|
return "DONT_CARE";
|
|
end if;
|
|
return read_during_write_mode_mixed_ports;
|
|
end get_write_mode;
|
|
|
|
function get_read_operation(operation_mode : string; port_name : string) return boolean is
|
|
begin
|
|
if (port_name = "A") then
|
|
if ((operation_mode = "BIDIR_DUAL_PORT") or
|
|
(operation_mode = "SINGLE_PORT") or (operation_mode= "ROM")) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
else
|
|
if ((operation_mode = "BIDIR_DUAL_PORT") or
|
|
(operation_mode = "DUAL_PORT")) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
end if;
|
|
end get_read_operation;
|
|
|
|
function get_write_operation(operation_mode : string; port_name : string) return boolean is
|
|
begin
|
|
if (port_name = "A") then
|
|
if ((operation_mode = "BIDIR_DUAL_PORT") or
|
|
(operation_mode = "SINGLE_PORT") or (operation_mode= "DUAL_PORT")) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
else
|
|
if (operation_mode = "BIDIR_DUAL_PORT") then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
end if;
|
|
end get_write_operation;
|
|
|
|
function check_simultaneous(operation_mode : string; ram_type : string; cread : string) return boolean is
|
|
begin
|
|
if (operation_mode = "BIDIR_DUAL_PORT") then
|
|
if ((ram_type = "MEGARAM") or (ram_type = "M-RAM") or
|
|
((cread = "DONT_CARE") and (ram_type = "AUTO")) or
|
|
((cread = "NEW_DATA") and (is_lutram(ram_type)))) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
else
|
|
return false;
|
|
end if;
|
|
end check_simultaneous;
|
|
|
|
function get_ram_block_type (intended_device_family : string; ram_block_type : string) return string is
|
|
begin
|
|
if (FEATURE_FAMILY_HAS_STRATIXV_STYLE_RAM(intended_device_family)) then
|
|
if ((((ram_block_type = "M10K") or (is_lutram(ram_block_type))) and FEATURE_FAMILY_ARRIAV(intended_device_family)) or
|
|
(((ram_block_type = "M20K") or (is_lutram(ram_block_type))) and (FEATURE_FAMILY_STRATIXV(intended_device_family) or FEATURE_FAMILY_ARRIA10(intended_device_family))) ) then
|
|
return ram_block_type;
|
|
else
|
|
return "AUTO";
|
|
end if;
|
|
elsif (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) then
|
|
if (((ram_block_type = "M-RAM") or (ram_block_type = "MEGARAM")) and FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
|
|
return "M144K";
|
|
elsif ((((ram_block_type = "M144K") or (is_lutram(ram_block_type))) and FEATURE_FAMILY_STRATIXIII(intended_device_family)) or
|
|
(ram_block_type = "M9K")) then
|
|
return ram_block_type;
|
|
else
|
|
return "AUTO";
|
|
end if;
|
|
else
|
|
if ((ram_block_type /= "AUTO") and (ram_block_type /= "M-RAM") and (ram_block_type /= "MEGARAM") and
|
|
(ram_block_type /= "M512") and (ram_block_type /= "M4K")) then
|
|
return "AUTO";
|
|
else
|
|
return ram_block_type;
|
|
end if;
|
|
end if;
|
|
end get_ram_block_type;
|
|
|
|
function get_byte_size (byte_size : integer; width_byteena_a : integer; width_a : integer; device_family : string) return integer is
|
|
variable temp : integer;
|
|
begin
|
|
if ((byte_size = 0) and (width_byteena_a > 1)) then
|
|
temp := width_a / width_byteena_a;
|
|
if (((FEATURE_FAMILY_STRATIX(device_family) or FEATURE_FAMILY_STRATIXV(device_family)) and (temp /= 8) and (temp /= 9)) or
|
|
((FEATURE_FAMILY_BASE_STRATIXII(device_family) or FEATURE_FAMILY_BASE_CYCLONEII(device_family)) and (temp /= 1) and (temp /= 2) and (temp /= 4)) or
|
|
((FEATURE_FAMILY_STRATIXIII(device_family) or FEATURE_FAMILY_STRATIXV(device_family)) and (temp /= 5) and (temp /= 10))) then
|
|
return 8;
|
|
else
|
|
return temp;
|
|
end if;
|
|
elsif (byte_size = 0) then
|
|
return 8;
|
|
else
|
|
return byte_size;
|
|
end if;
|
|
end get_byte_size;
|
|
|
|
function get_write_edge (ram_block_type : string; device_family : string) return boolean is
|
|
begin
|
|
if ((ram_block_type = "M-RAM") or (ram_block_type = "MEGARAM") or
|
|
(ram_block_type = "M9K") or (ram_block_type = "M144K") or
|
|
((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(device_family) and (ram_block_type = "AUTO")))) then
|
|
return true;
|
|
elsif ((ram_block_type = "M20K") or (ram_block_type = "M10K") or
|
|
(FEATURE_FAMILY_HAS_STRATIXV_STYLE_RAM(device_family) and (is_lutram(ram_block_type) or (ram_block_type = "AUTO")))) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
end get_write_edge;
|
|
|
|
function get_numwords(numwords : integer; widthad : integer) return integer is
|
|
begin
|
|
if (numwords /= 0) then
|
|
return numwords;
|
|
else
|
|
return (2 ** widthad);
|
|
end if;
|
|
end get_numwords;
|
|
|
|
function is_lutram_single_port_fast_read(ram_block_type : string; read_during_write : string; operation_mode : string) return boolean is
|
|
begin
|
|
if ((is_lutram(ram_block_type)) and
|
|
((read_during_write = "DONT_CARE") or ((outdata_reg_a = "UNREGISTERED") AND
|
|
(operation_mode = "SINGLE_PORT")))) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
end is_lutram_single_port_fast_read;
|
|
|
|
function is_lutram_dual_port_fast_read (ram_block_type : string; read_during_write_mixed_ports : string; address_reg_b : string; operation_mode : string) return boolean is
|
|
begin
|
|
if ((is_lutram(ram_block_type)) and
|
|
(operation_mode = "DUAL_PORT") and
|
|
((read_during_write_mixed_ports = "NEW_DATA") or
|
|
(read_during_write_mixed_ports = "DONT_CARE") or
|
|
(read_during_write_mixed_ports = "CONSTRAINED_DONT_CARE") or
|
|
((read_during_write_mixed_ports = "OLD_DATA") and (outdata_reg_b = "UNREGISTERED")))) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
end is_lutram_dual_port_fast_read;
|
|
|
|
function get_rden_reg_initial_value(device : string) return std_logic is
|
|
begin
|
|
if (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) then
|
|
return '0';
|
|
else
|
|
return '1';
|
|
end if;
|
|
end get_rden_reg_initial_value;
|
|
|
|
function get_byteena_reg_initial_value(device : string) return std_logic is
|
|
begin
|
|
if (FEATURE_FAMILY_HAS_STRATIXV_STYLE_RAM(intended_device_family)) then
|
|
return '0';
|
|
else
|
|
return '1';
|
|
end if;
|
|
end get_byteena_reg_initial_value;
|
|
|
|
-- CONSTANT DECLARATION
|
|
|
|
constant IS_STRATIXV : boolean := FEATURE_FAMILY_STRATIXV(intended_device_family);
|
|
constant IS_STRATIXIII : boolean := FEATURE_FAMILY_STRATIXIII(intended_device_family);
|
|
constant IS_HARDCOPYII : boolean := FEATURE_FAMILY_HARDCOPYII(intended_device_family);
|
|
constant IS_HARDCOPYIII : boolean := FEATURE_FAMILY_HARDCOPYIII(intended_device_family);
|
|
constant IS_HARDCOPYIV : boolean := FEATURE_FAMILY_HARDCOPYIV(intended_device_family);
|
|
constant IS_CYCLONEIII : boolean := FEATURE_FAMILY_CYCLONEIII(intended_device_family);
|
|
constant IS_BASE_STRATIXIII : boolean := FEATURE_FAMILY_BASE_STRATIXIII(intended_device_family);
|
|
constant IS_BASE_STRATIXII : boolean := FEATURE_FAMILY_BASE_STRATIXII(intended_device_family);
|
|
constant IS_BASE_CYCLONEII : boolean := FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family);
|
|
constant HAS_STRATIXI_STYLE_RAM : boolean := FEATURE_FAMILY_HAS_STRATIXI_STYLE_RAM(intended_device_family);
|
|
constant HAS_STRATIXII_STYLE_RAM : boolean := FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family);
|
|
constant HAS_STRATIXIII_STYLE_RAM : boolean := FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family);
|
|
constant HAS_STRATIXV_STYLE_RAM : boolean := FEATURE_FAMILY_HAS_STRATIXV_STYLE_RAM(intended_device_family);
|
|
constant HAS_LUTRAM : boolean := FEATURE_FAMILY_HAS_LUTRAM(intended_device_family);
|
|
constant HAS_M512 : boolean := FEATURE_FAMILY_HAS_M512(intended_device_family);
|
|
constant HAS_MEGARAM : boolean := FEATURE_FAMILY_HAS_MEGARAM(intended_device_family);
|
|
|
|
constant i_is_lutram : boolean := is_lutram(ram_block_type);
|
|
|
|
constant i_ram_block_type : string := get_ram_block_type(intended_device_family, ram_block_type);
|
|
|
|
constant cread_during_write_mode_mixed_ports : string := get_write_mode(read_during_write_mode_mixed_ports, intended_device_family);
|
|
|
|
constant read_operation_a : boolean := get_read_operation(operation_mode, "A");
|
|
|
|
constant write_operation_a : boolean := get_write_operation(operation_mode, "A");
|
|
|
|
constant read_operation_b : boolean := get_read_operation(operation_mode, "B");
|
|
|
|
constant write_operation_b : boolean := get_write_operation(operation_mode, "B");
|
|
|
|
constant check_simultaneous_read_write : boolean := check_simultaneous(operation_mode, ram_block_type, cread_during_write_mode_mixed_ports);
|
|
|
|
constant i_byte_size : integer := get_byte_size(byte_size, width_byteena_a, width_a, intended_device_family);
|
|
|
|
constant is_write_positive_edge : boolean := get_write_edge(i_ram_block_type, intended_device_family);
|
|
|
|
constant i_numwords_a : integer := get_numwords(numwords_a, widthad_a);
|
|
|
|
constant i_numwords_b : integer := get_numwords(numwords_b, widthad_b);
|
|
|
|
constant i_lutram_single_port_fast_read : boolean := is_lutram_single_port_fast_read(ram_block_type, read_during_write_mode_port_a, operation_mode);
|
|
|
|
constant i_lutram_dual_port_fast_read : boolean := is_lutram_dual_port_fast_read(ram_block_type, read_during_write_mode_mixed_ports, address_reg_b, operation_mode);
|
|
|
|
constant rden_reg_initial_value : std_logic := get_rden_reg_initial_value(intended_device_family);
|
|
|
|
constant byteena_reg_initial_value : std_logic := get_byteena_reg_initial_value(intended_device_family);
|
|
|
|
constant enable_mem_data_b_reading : boolean := (sim_show_memory_data_in_port_b_layout = "ON") and ((operation_mode = "BIDIR_DUAL_PORT") or (operation_mode = "DUAL_PORT"));
|
|
|
|
|
|
constant all_z : std_logic_vector(width_byteena_b-1 downto 0) := (others => 'Z');
|
|
|
|
|
|
-- SIGNAL DECLARATION
|
|
|
|
signal i_data_reg_a : std_logic_vector(width_a - 1 downto 0) := (others => '0');
|
|
signal i_data_reg_b : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
|
|
signal i_q_reg_a : std_logic_vector(width_a - 1 downto 0) := (others => '0');
|
|
signal i_q_tmp_a : std_logic_vector(width_a - 1 downto 0) := (others => '0');
|
|
signal i_q_tmp2_a : std_logic_vector(width_a - 1 downto 0) := (others => '0');
|
|
signal i_q_tmp_wren_a : std_logic_vector(width_a - 1 downto 0) := (others => '0');
|
|
signal i_q_tmp2_wren_a : std_logic_vector(width_a - 1 downto 0) := (others => '0');
|
|
signal i_q_tmp_wren_b : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
signal i_q_reg_b : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
signal i_q_tmp_b : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
signal i_q_tmp2_b : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
signal i_q_output_latch : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
|
|
signal i_q_ecc_reg_b : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
signal i_q_ecc_tmp_b : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
|
|
signal i_current_written_data_a : std_logic_vector(width_a - 1 downto 0) := (others => '0');
|
|
signal i_original_data_a : std_logic_vector(width_a - 1 downto 0) := (others => '0');
|
|
signal i_original_data_b : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
|
|
signal i_byteena_mask_reg_a_x : std_logic_vector(width_a - 1 downto 0) := (others => '0');
|
|
signal i_byteena_mask_reg_b_x : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
signal i_byteena_mask_reg_a : std_logic_vector(width_a - 1 downto 0) := (others => byteena_reg_initial_value);
|
|
signal i_byteena_mask_reg_b : std_logic_vector(width_b - 1 downto 0) := (others => byteena_reg_initial_value);
|
|
signal i_byteena_mask_reg_a_out : std_logic_vector(width_a - 1 downto 0) := (others => byteena_reg_initial_value);
|
|
signal i_byteena_mask_reg_b_out : std_logic_vector(width_b - 1 downto 0) := (others => byteena_reg_initial_value);
|
|
signal i_byteena_mask_reg_a_out_b : std_logic_vector(width_a - 1 downto 0) := (others => byteena_reg_initial_value);
|
|
signal i_byteena_mask_reg_b_out_a : std_logic_vector(width_b - 1 downto 0) := (others => byteena_reg_initial_value);
|
|
|
|
signal i_address_reg_a : std_logic_vector(widthad_a - 1 downto 0) := (others => '0');
|
|
signal i_address_reg_b : std_logic_vector(widthad_b - 1 downto 0) := (others => '0');
|
|
|
|
signal i_wren_reg_a : std_logic := '0';
|
|
signal i_wren_reg_b : std_logic := '0';
|
|
signal i_rden_reg_a : std_logic := rden_reg_initial_value;
|
|
signal i_rden_reg_b : std_logic := rden_reg_initial_value;
|
|
signal i_read_flag_a : std_logic := '0';
|
|
signal i_read_flag_b : std_logic := '0';
|
|
signal i_reread_flag_a : std_logic := '0';
|
|
signal i_reread_flag_b : std_logic := '0';
|
|
signal i_reread_flag2_a : std_logic := '0';
|
|
signal i_reread_flag2_b : std_logic := '0';
|
|
signal i_write_flag_a : std_logic := '0';
|
|
signal i_write_flag_b : std_logic := '0';
|
|
signal i_nmram_write_a : std_logic := '0';
|
|
signal i_nmram_write_b : std_logic := '0';
|
|
|
|
signal i_indata_aclr_a : std_logic := '0';
|
|
signal i_address_aclr_a : std_logic := '0';
|
|
signal i_wrcontrol_aclr_a : std_logic := '0';
|
|
signal i_indata_aclr_b : std_logic := '0';
|
|
signal i_address_aclr_b : std_logic := '0';
|
|
signal i_wrcontrol_aclr_b : std_logic := '0';
|
|
signal i_outdata_aclr_a : std_logic := '0';
|
|
signal i_outdata_aclr_b : std_logic := '0';
|
|
signal i_rdcontrol_aclr_b : std_logic := '0';
|
|
signal i_byteena_aclr_a : std_logic := '0';
|
|
signal i_byteena_aclr_b : std_logic := '0';
|
|
|
|
signal good_to_go_a : std_logic := '0';
|
|
signal good_to_go_b : std_logic := '0';
|
|
|
|
signal i_core_clocken_a : std_logic := '1';
|
|
signal i_core_clocken_b : std_logic := '1';
|
|
signal i_core_clocken_b0 : std_logic := '1';
|
|
signal i_core_clocken_b1 : std_logic := '1';
|
|
signal i_inclocken0 : std_logic := '0';
|
|
signal i_input_clocken_b : std_logic := '0';
|
|
signal i_outdata_clken_b : std_logic := '0';
|
|
signal i_outdata_clken_a : std_logic := '0';
|
|
signal i_outlatch_clken_a : std_logic := '1';
|
|
signal i_outlatch_clken_b : std_logic := '1';
|
|
signal i_core_clocken_a_reg : std_logic := '0';
|
|
signal i_core_clocken_b_reg : std_logic := '0';
|
|
|
|
signal default_val : std_logic := '0';
|
|
|
|
signal i_data_zero_a : std_logic_vector (width_a - 1 downto 0) := (others => '0');
|
|
signal i_data_zero_b : std_logic_vector (width_b - 1 downto 0) := (others => '0');
|
|
signal i_data_ones_a : std_logic_vector (width_a - 1 downto 0) := (others => '1');
|
|
signal i_data_ones_b : std_logic_vector (width_b - 1 downto 0) := (others => '1');
|
|
|
|
signal same_clock_pulse0 : std_logic := '0';
|
|
signal same_clock_pulse1 : std_logic := '0';
|
|
signal i_force_reread_a : std_logic := '0';
|
|
signal i_force_reread_a1 : std_logic := '0';
|
|
signal i_force_reread_b : std_logic := '0';
|
|
signal i_force_reread_b1 : std_logic := '0';
|
|
signal i_force_reread_signal_a : std_logic := '0';
|
|
signal i_force_reread_signal_b : std_logic := '0';
|
|
|
|
signal i_good_to_write_a : std_logic := '1';
|
|
signal i_good_to_write_b : std_logic := '1';
|
|
|
|
|
|
begin
|
|
|
|
|
|
-- Parameter Checking
|
|
process
|
|
begin
|
|
if ((operation_mode /= "BIDIR_DUAL_PORT") and (operation_mode /= "SINGLE_PORT") and
|
|
(operation_mode /= "DUAL_PORT") and (operation_mode /= "ROM")) then
|
|
assert false
|
|
report "Error: Not a valid operation mode."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((ram_block_type /= "M4K") and (ram_block_type /= "M512") and
|
|
(ram_block_type /= "LARGE") and (ram_block_type /= "MEGARAM") and
|
|
(ram_block_type /= "M-RAM") and (ram_block_type /= "AUTO") and
|
|
(ram_block_type /= "M9K") and (ram_block_type /= "M144K") and
|
|
(ram_block_type /= "M20K") and
|
|
(ram_block_type /= "M10K") and
|
|
(not i_is_lutram)) then
|
|
assert false
|
|
report "Error: RAM_BLOCK_TYPE has an invalid value."
|
|
severity error;
|
|
end if;
|
|
|
|
if (ram_block_type /= i_ram_block_type) then
|
|
assert false
|
|
report "Warning: RAM block type is assumed as " & i_ram_block_type
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((cread_during_write_mode_mixed_ports /= "DONT_CARE") and
|
|
(cread_during_write_mode_mixed_ports /= "CONSTRAINED_DONT_CARE") and
|
|
(cread_during_write_mode_mixed_ports /= "OLD_DATA") and
|
|
(cread_during_write_mode_mixed_ports /= "NEW_DATA")) then
|
|
assert false
|
|
report "Error: Invalid value for READ_DURING_WRITE_MODE_MIXED_PORTS parameter. It has to be OLD_DATA or DONT_CARE or CONSTRAINED_DONT_CARE or NEW_DATA"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((read_during_write_mode_mixed_ports /= cread_during_write_mode_mixed_ports) and ((operation_mode /= "SINGLE_PORT") and (operation_mode /= "ROM"))) then
|
|
assert false
|
|
report "Warning: READ_DURING_WRITE_MODE_MIXED_PORTS is assumed as " & cread_during_write_mode_mixed_ports
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((i_ram_block_type = "M-RAM") or (i_ram_block_type = "MEGARAM")) and
|
|
(init_file /= "UNUSED")) then
|
|
assert false
|
|
report "Error: M-RAM block type doesn't support the use of an initialization file"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((i_byte_size /= 8) and (i_byte_size /= 9) and
|
|
(HAS_STRATIXI_STYLE_RAM)) then
|
|
assert false
|
|
report "Error: BYTE_SIZE has to be either 8 or 9"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((i_byte_size /= 8) and (i_byte_size /= 9) and
|
|
(i_byte_size /= 1) and (i_byte_size /= 2) and (i_byte_size /= 4) and
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)) then
|
|
assert false
|
|
report "Error: BYTE_SIZE has to be either 1, 2, 4, 8 or 9"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((i_byte_size /= 8) and (i_byte_size /= 9) and
|
|
(i_byte_size /= 5) and (i_byte_size /= 10) and
|
|
((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) then
|
|
assert false
|
|
report "Error: BYTE_SIZE has to be either 5, 8, 9 or 10"
|
|
severity error;
|
|
end if;
|
|
|
|
if (width_a <= 0) then
|
|
assert false
|
|
report "Error: Invalid value for WIDTH_A parameter"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((width_b <= 0) and
|
|
((operation_mode /= "SINGLE_PORT") and (operation_mode /= "ROM"))) then
|
|
assert false
|
|
report "Error: Invalid value for WIDTH_B parameter"
|
|
severity error;
|
|
end if;
|
|
|
|
if (widthad_a <= 0) then
|
|
assert false
|
|
report "Error: Invalid value for WIDTHAD_A parameter"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((widthad_b <= 0) and
|
|
((operation_mode /= "SINGLE_PORT") and (operation_mode /= "ROM"))) then
|
|
assert false
|
|
report "Error: Invalid value for WIDTHAD_B parameter"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((operation_mode = "ROM") and
|
|
((i_ram_block_type = "M-RAM") or (i_ram_block_type = "MEGARAM"))) then
|
|
assert false
|
|
report "Error: ROM mode does not support ram_block_type = M-RAM"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((IS_BASE_STRATIXII or IS_BASE_CYCLONEII) and
|
|
(((indata_aclr_a /= "UNUSED") and (indata_aclr_a /= "NONE")) or
|
|
((wrcontrol_aclr_a /= "UNUSED") and (wrcontrol_aclr_a /= "NONE")) or
|
|
((byteena_aclr_a /= "UNUSED") and (byteena_aclr_a /= "NONE")) or
|
|
((address_aclr_a /= "UNUSED") and (address_aclr_a /= "NONE")) or
|
|
((indata_aclr_b /= "UNUSED") and (indata_aclr_b /= "NONE")) or
|
|
((rdcontrol_aclr_b /= "UNUSED") and (rdcontrol_aclr_b /= "NONE")) or
|
|
((wrcontrol_aclr_b /= "UNUSED") and (wrcontrol_aclr_b /= "NONE")) or
|
|
((byteena_aclr_b /= "UNUSED") and (byteena_aclr_b /= "NONE")) or
|
|
((address_aclr_b /= "UNUSED") and (address_aclr_b /= "NONE")))) then
|
|
assert false
|
|
report "Warning: " & intended_device_family & " device family does not support aclr signal on input ports. The aclr to input ports will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((not HAS_STRATIXV_STYLE_RAM)
|
|
and (not HAS_STRATIXIII_STYLE_RAM)
|
|
and (read_during_write_mode_port_a /= "NEW_DATA_NO_NBE_READ")) then
|
|
assert false
|
|
report "Warning: " & read_during_write_mode_port_a & " value for read_during_write_mode_port_a is not supported in " & intended_device_family & " device family, it might cause incorrect behavioural simulation result"
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((not HAS_STRATIXV_STYLE_RAM)
|
|
and (not HAS_STRATIXIII_STYLE_RAM)
|
|
and (read_during_write_mode_port_b /= "NEW_DATA_NO_NBE_READ")) then
|
|
assert false
|
|
report "Warning: " & read_during_write_mode_port_b & " value for read_during_write_mode_port_b is not supported in " & intended_device_family & " device family, it might cause incorrect behavioural simulation result"
|
|
severity warning;
|
|
end if;
|
|
-- SPR 249576: Enable don't care as RDW setting in MegaFunctions - eliminates checking for ram_block_type = "AUTO"
|
|
if (not (i_is_lutram or ((i_ram_block_type = "AUTO") and (HAS_LUTRAM)) or
|
|
((i_ram_block_type /= "AUTO") and ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)))) and
|
|
(operation_mode /= "SINGLE_PORT") and (read_during_write_mode_port_a = "DONT_CARE")) then
|
|
assert false
|
|
report "Error: " & read_during_write_mode_port_a & " value for read_during_write_mode_port_a is not supported in " &
|
|
intended_device_family & " device family for " & ram_block_type & " ram block type in " & operation_mode & " operation mode"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not i_is_lutram) and (cread_during_write_mode_mixed_ports = "CONSTRAINED_DONT_CARE")) then
|
|
assert false
|
|
report "Warning : read_during_write_mode_mixed_ports cannot be set to CONSTRAINED_DONT_CARE for non-LUTRAM ram block type. This will cause incorrect simulation result."
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((not i_is_lutram) and (cread_during_write_mode_mixed_ports = "NEW_DATA")) then
|
|
assert false
|
|
report "Warning : read_during_write_mode_mixed_ports cannot be set to NEW_DATA for non-LUTRAM ram block type. This will cause incorrect simulation result."
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((operation_mode = "DUAL_PORT") and (outdata_reg_b /= "CLOCK0") and (i_is_lutram) and
|
|
(cread_during_write_mode_mixed_ports = "OLD_DATA")) then
|
|
assert false
|
|
report "Warning: Value for read_during_write_mode_mixed_ports is not honoured in " & operation_mode & " operation mode when output registers are not clocked by clock0 for ram_block_type LUTRAM"
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((i_is_lutram) and (operation_mode = "BIDIR_DUAL_PORT")) then
|
|
assert false
|
|
report "Error: LUTRAM RAM block type does not support BIDIR_DUAL_PORT operation mode"
|
|
severity error;
|
|
end if;
|
|
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (indata_aclr_a /= "NONE") and (indata_aclr_a /= "UNUSED")) then
|
|
assert false
|
|
report "Warning : " & indata_aclr_a & "value for indata_aclr_a is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (wrcontrol_aclr_a /= "NONE") and (wrcontrol_aclr_a /= "UNUSED")) then
|
|
assert false
|
|
report "Warning : " & wrcontrol_aclr_a & " value for wrcontrol_aclr_a is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (byteena_aclr_a /= "NONE") and (byteena_aclr_a /= "UNUSED")) then
|
|
assert false
|
|
report "Warning : " & byteena_aclr_a & " value for byteena_aclr_a is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (address_aclr_a /= "NONE") and (address_aclr_a /= "UNUSED") and (operation_mode /= "ROM")) then
|
|
assert false
|
|
report "Warning : " & address_aclr_a & " value for address_aclr_a is not supported for write port in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (indata_aclr_b /= "NONE") and (indata_aclr_b /= "UNUSED")) then
|
|
assert false
|
|
report "Warning : " & indata_aclr_b & " value for indata_aclr_b is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (rdcontrol_aclr_b /= "NONE") and (rdcontrol_aclr_b /= "UNUSED")) then
|
|
assert false
|
|
report "Warning : " & rdcontrol_aclr_b & " value for rdcontrol_aclr_b is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (wrcontrol_aclr_b /= "NONE") and (wrcontrol_aclr_b /= "UNUSED")) then
|
|
assert false
|
|
report "Warning : " & wrcontrol_aclr_b & " value for wrcontrol_aclr_b is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (byteena_aclr_b /= "NONE") and (byteena_aclr_b /= "UNUSED")) then
|
|
assert false
|
|
report "Warning : " & byteena_aclr_b & " value for byteena_aclr_b is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (address_aclr_b /= "NONE") and (address_aclr_b /= "UNUSED") and (operation_mode = "BIDIR_DUAL_PORT")) then
|
|
assert false
|
|
report "Warning : " & address_aclr_b & " value for address_aclr_b is not supported for write port in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((i_is_lutram) and (address_aclr_b /= "NONE") and (address_aclr_b /= "UNUSED") and (operation_mode = "DUAL_PORT") and (cread_during_write_mode_mixed_ports = "OLD_DATA")) then
|
|
assert false
|
|
report "Warning : aclr signal for address_b is ignored for RAM block type " & ram_block_type & " when read_during_write_mode_mixed_ports is set to OLD_DATA"
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)) and
|
|
((clock_enable_core_a /= "USE_INPUT_CLKEN") and
|
|
(clock_enable_core_a /= clock_enable_input_a))) then
|
|
assert false
|
|
report "Warning: clock_enable_core_a value must be 'USE_INPUT_CLKEN' or same as clock_enable_input_a in " & intended_device_family & " device family. It will be set to follow clock_enable_input_a value."
|
|
severity warning;
|
|
end if;
|
|
|
|
if (((not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)) and
|
|
((clock_enable_core_b /= "USE_INPUT_CLKEN") and (clock_enable_core_b /= clock_enable_input_b))) then
|
|
assert false
|
|
report "Warning: clock_enable_core_b value must be 'USE_INPUT_CLKEN' or same as clock_enable_input_b in " & intended_device_family & " device family. It will be set to follow clock_enable_input_b value."
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM) and
|
|
(clock_enable_input_a = "ALTERNATE")) then
|
|
assert false
|
|
report "Error: ALTERNATE value for clock_enable_input_a is not supported in " & intended_device_family
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM) and
|
|
(clock_enable_input_b = "ALTERNATE")) then
|
|
assert false
|
|
report "Error: ALTERNATE value for clock_enable_input_b is not supported in " & intended_device_family
|
|
severity error;
|
|
end if;
|
|
|
|
if ((enable_ecc = "TRUE") and (((i_ram_block_type /= "M20K") and (i_ram_block_type /= "M144K")) or (operation_mode /= "DUAL_PORT"))) then
|
|
assert false
|
|
report "Error: " & enable_ecc & " value for enable_ecc is not supported in " & ram_block_type & " ram block type for " & intended_device_family & " device family in " & operation_mode & " operation mode."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((i_ram_block_type /= "M20K") and (ecc_pipeline_stage_enabled = "TRUE")) then
|
|
assert false
|
|
report "Error: " & ecc_pipeline_stage_enabled & " value for ecc_pipeline_stage_enabled is not supported in " & ram_block_type & " ram block type."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((outdata_reg_b = "UNREGISTERED") and (ecc_pipeline_stage_enabled = "TRUE")) then
|
|
assert false
|
|
report "Error: " & ecc_pipeline_stage_enabled & " is not supported when output_reg_b is set to " & outdata_reg_b & " ."
|
|
severity error;
|
|
end if;
|
|
|
|
--Setting this to only warning because in synthesis it will ignore the ecc_pipeline_stage_enabled parameter when enable_ecc is set to false
|
|
if ((ecc_pipeline_stage_enabled = "TRUE") and (enable_ecc /= "TRUE")) then
|
|
assert false
|
|
report "Warning: " & ecc_pipeline_stage_enabled & " value for ecc_pipeline_stage_enabled is not supported when enable_ecc is set to " & enable_ecc & " ."
|
|
severity warning;
|
|
end if;
|
|
|
|
if ((cread_during_write_mode_mixed_ports = "OLD_DATA") and (enable_ecc = "TRUE") and ((i_ram_block_type = "M20K") or (i_ram_block_type = "M144K"))) then
|
|
assert false
|
|
report "Error : ECC is not supported for read-before-write mode."
|
|
severity error;
|
|
end if;
|
|
|
|
if (((wrcontrol_aclr_a /= "NONE") and (wrcontrol_aclr_a /= "UNUSED")) and (i_ram_block_type = "M512") and (operation_mode = "SINGLE_PORT")) then
|
|
assert false
|
|
report "Error: Wren_a cannot have clear in single port mode for M512 block"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((operation_mode = "DUAL_PORT") and (numwords_a * width_a /= numwords_b * width_b)) then
|
|
assert false
|
|
report "Error: Total number of bits of port A and port B should be the same for dual port mode"
|
|
severity error;
|
|
end if;
|
|
|
|
if (((rdcontrol_aclr_b /= "NONE") and (rdcontrol_aclr_b /= "UNUSED")) and (i_ram_block_type = "M512") and (operation_mode = "DUAL_PORT")) then
|
|
assert false
|
|
report "Error: rden_b cannot have clear in simple dual port mode for M512 block"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((operation_mode = "BIDIR_DUAL_PORT") and (numwords_a * width_a /= numwords_b * width_b)) then
|
|
assert false
|
|
report "Error: Total number of bits of port A and port B should be the same for bidir dual port mode"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((operation_mode = "BIDIR_DUAL_PORT") and (i_ram_block_type = "M512")) then
|
|
assert false
|
|
report "Error: M512 block type doesn't support bidir dual mode"
|
|
severity error;
|
|
end if;
|
|
|
|
if (((i_ram_block_type = "M-RAM") or (i_ram_block_type = "MEGARAM")) and
|
|
(cread_during_write_mode_mixed_ports = "OLD_DATA")) then
|
|
assert false
|
|
report "Error: M-RAM doesn't support OLD_DATA value for READ_DURING_WRITE_MODE_MIXED_PORTS parameter"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not HAS_STRATIXII_STYLE_RAM) and
|
|
(clock_enable_input_a = "BYPASS")) then
|
|
assert false
|
|
report "Error: BYPASS value for CLOCK_ENABLE_INPUT_A is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
if ((not HAS_STRATIXII_STYLE_RAM) and
|
|
(clock_enable_output_a = "BYPASS")) then
|
|
assert false
|
|
report "Error: BYPASS value for CLOCK_ENABLE_OUTPUT_A is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
if ((not HAS_STRATIXII_STYLE_RAM) and
|
|
(clock_enable_input_b = "BYPASS") and
|
|
((operation_mode = "BIDIR_DUAL_PORT") or (operation_mode = "DUAL_PORT"))) then
|
|
assert false
|
|
report "Error: BYPASS value for CLOCK_ENABLE_INPUT_B is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not HAS_STRATIXII_STYLE_RAM) and
|
|
(clock_enable_output_b = "BYPASS") and
|
|
((operation_mode = "BIDIR_DUAL_PORT") or (operation_mode = "DUAL_PORT"))) then
|
|
assert false
|
|
report "Error: BYPASS value for CLOCK_ENABLE_OUTPUT_B is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((implement_in_les /= "OFF") and (implement_in_les /= "ON")) then
|
|
assert false
|
|
report "Error: Illegal parameter value for implement_in_les"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not HAS_M512) and (i_ram_block_type = "M512")) then
|
|
assert false
|
|
report "Error: M512 as ram_block_type is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if ((not HAS_MEGARAM) and (i_ram_block_type = "MEGARAM")) then
|
|
assert false
|
|
report "Error: MEGARAM as ram_block_type is not supported in "& intended_device_family &" device family"
|
|
severity error;
|
|
end if;
|
|
|
|
if (operation_mode /= "DUAL_PORT") then
|
|
if ((outdata_reg_a /= "CLOCK0") and (outdata_reg_a /= "CLOCK1") and (outdata_reg_a /= "UNUSED") and (outdata_reg_a /= "UNREGISTERED")) then
|
|
assert false
|
|
report "Error: " & outdata_reg_a & " value for outdata_reg_a is not supported."
|
|
severity error;
|
|
end if;
|
|
end if;
|
|
|
|
if ((operation_mode = "BIDIR_DUAL_PORT") or (operation_mode = "DUAL_PORT")) then
|
|
if ((address_reg_b /= "CLOCK0") and (address_reg_b /= "CLOCK1") and (address_reg_b /= "UNUSED")) then
|
|
assert false
|
|
report "Error: " & address_reg_b & " value for address_reg_b is not supported."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((outdata_reg_b /= "CLOCK0") and (outdata_reg_b /= "CLOCK1") and (outdata_reg_b /= "UNUSED") and (outdata_reg_b /= "UNREGISTERED")) then
|
|
assert false
|
|
report "Error: " & outdata_reg_b & " value for outdata_reg_b is not supported."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((rdcontrol_reg_b /= "CLOCK0") and (rdcontrol_reg_b /= "CLOCK1") and (rdcontrol_reg_b /= "UNUSED") and (operation_mode = "DUAL_PORT")) then
|
|
assert false
|
|
report "Error: " & rdcontrol_reg_b & " value for rdcontrol_reg_b is not supported."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((indata_reg_b /= "CLOCK0") and (indata_reg_b /= "CLOCK1") and (indata_reg_b /= "UNUSED") and (operation_mode = "BIDIR_DUAL_PORT")) then
|
|
assert false
|
|
report "Error: " & indata_reg_b & " value for indata_reg_b is not supported."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((wrcontrol_wraddress_reg_b /= "CLOCK0") and (wrcontrol_wraddress_reg_b /= "CLOCK1") and (wrcontrol_wraddress_reg_b /= "UNUSED") and (operation_mode = "BIDIR_DUAL_PORT")) then
|
|
assert false
|
|
report "Error: " & wrcontrol_wraddress_reg_b & " value for wrcontrol_wraddress_reg_b is not supported."
|
|
severity error;
|
|
end if;
|
|
|
|
if ((byteena_reg_b /= "CLOCK0") and (byteena_reg_b /= "CLOCK1") and (byteena_reg_b /= "UNUSED") and (operation_mode = "BIDIR_DUAL_PORT")) then
|
|
assert false
|
|
report "Error: " & byteena_reg_b & " value for byteena_reg_b is not supported."
|
|
severity error;
|
|
end if;
|
|
end if;
|
|
wait;
|
|
end process;
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
|
|
-- Checking for same clock phase
|
|
process (clock0, clock1)
|
|
begin
|
|
if (rising_edge(clock0)) then
|
|
if (clock1 = '1') then
|
|
same_clock_pulse0 <= '1';
|
|
else
|
|
same_clock_pulse0 <= '0';
|
|
end if;
|
|
end if;
|
|
if (rising_edge(clock1)) then
|
|
if (clock0 = '1') then
|
|
same_clock_pulse1 <= '1';
|
|
else
|
|
same_clock_pulse1 <= '0';
|
|
end if;
|
|
end if;
|
|
if (falling_edge(clock0) and (clock1 = '1')) then
|
|
same_clock_pulse0 <= '0';
|
|
end if;
|
|
if (falling_edge(clock1) and (clock0 = '1')) then
|
|
same_clock_pulse1 <= '0';
|
|
end if;
|
|
end process;
|
|
|
|
|
|
-- Checking ram_block_type and setting default_val
|
|
IFG01: if ((((i_ram_block_type = "AUTO") and
|
|
((cread_during_write_mode_mixed_ports = "DONT_CARE") or (cread_during_write_mode_mixed_ports = "CONSTRAINED_DONT_CARE"))) or
|
|
(i_ram_block_type = "MEGARAM") or
|
|
(i_ram_block_type = "M-RAM")) and
|
|
(operation_mode /= "ROM") and
|
|
not (HAS_STRATIXV_STYLE_RAM) and
|
|
not (HAS_STRATIXIII_STYLE_RAM)) generate
|
|
default_val <= 'X';
|
|
end generate IFG01;
|
|
|
|
IFG02: if (not ((((i_ram_block_type = "AUTO") and
|
|
((cread_during_write_mode_mixed_ports = "DONT_CARE") or (cread_during_write_mode_mixed_ports = "CONSTRAINED_DONT_CARE"))) or
|
|
(i_ram_block_type = "MEGARAM") or
|
|
(i_ram_block_type = "M-RAM")) and
|
|
(operation_mode /= "ROM") and
|
|
not (HAS_STRATIXV_STYLE_RAM) and
|
|
not (HAS_STRATIXIII_STYLE_RAM))) generate
|
|
default_val <= '0';
|
|
end generate IFG02;
|
|
|
|
|
|
-- Assigning the correct clock enable signals based on the input clock
|
|
|
|
-- for input ports in a
|
|
IFG03: if (clock_enable_input_a = "NORMAL") generate
|
|
i_inclocken0 <= clocken0;
|
|
end generate IFG03;
|
|
IFG03a: if (clock_enable_input_a = "BYPASS") generate
|
|
i_inclocken0 <= '1';
|
|
end generate IFG03a;
|
|
IFG03b: if (clock_enable_input_a = "ALTERNATE") generate
|
|
i_inclocken0 <= clocken2;
|
|
end generate IFG03b;
|
|
|
|
-- for input ports in b
|
|
IFG14: if ((address_reg_b = "CLOCK0") and (clock_enable_input_b = "NORMAL")) generate
|
|
i_input_clocken_b <= clocken0;
|
|
end generate IFG14;
|
|
IFG14b: if ((address_reg_b = "CLOCK0") and (clock_enable_input_b = "ALTERNATE")) generate
|
|
i_input_clocken_b <= clocken2;
|
|
end generate IFG14b;
|
|
IFG14a: if (clock_enable_input_b = "BYPASS") generate
|
|
i_input_clocken_b <= '1';
|
|
end generate IFG14a;
|
|
IFG15: if ((address_reg_b = "CLOCK1") and (clock_enable_input_b = "NORMAL")) generate
|
|
i_input_clocken_b <= clocken1;
|
|
end generate IFG15;
|
|
IFG14c: if ((address_reg_b = "CLOCK1") and (clock_enable_input_b = "ALTERNATE")) generate
|
|
i_input_clocken_b <= clocken3;
|
|
end generate IFG14c;
|
|
|
|
-- for data out a
|
|
IFG171: if ((outdata_reg_a = "CLOCK0") and (clock_enable_output_a = "NORMAL")) generate
|
|
i_outdata_clken_a <= clocken0;
|
|
end generate IFG171;
|
|
IFG172b: if ((outdata_reg_a = "CLOCK0") and (clock_enable_output_a = "ALTERNATE")) generate
|
|
i_outdata_clken_a <= clocken2;
|
|
end generate IFG172b;
|
|
IFG172a: if (clock_enable_output_a = "BYPASS") generate
|
|
i_outdata_clken_a <= '1';
|
|
end generate IFG172a;
|
|
IFG173 : if ((outdata_reg_a = "CLOCK1") and (clock_enable_output_a = "NORMAL")) generate
|
|
i_outdata_clken_a <= clocken1;
|
|
end generate IFG173;
|
|
IFG173a : if ((outdata_reg_a = "CLOCK1") and (clock_enable_output_a = "ALTERNATE")) generate
|
|
i_outdata_clken_a <= clocken3;
|
|
end generate IFG173a;
|
|
|
|
-- case:32394, on SV onwards clear deassertion depends on output clock instead of core clock
|
|
IFG171a: if ((clock_enable_output_b = "NORMAL") and (outdata_reg_a = "UNREGISTERED") and (outdata_reg_b = "CLOCK0") and (HAS_STRATIXV_STYLE_RAM) and (operation_mode = "BIDIR_DUAL_PORT")) generate
|
|
i_outlatch_clken_a <= clocken0;
|
|
end generate IFG171a;
|
|
|
|
-- for data out b
|
|
IFG17: if ((outdata_reg_b = "CLOCK0") and (clock_enable_output_b = "NORMAL")) generate
|
|
i_outdata_clken_b <= clocken0;
|
|
end generate IFG17;
|
|
IFG17b: if ((outdata_reg_b = "CLOCK0") and (clock_enable_output_b = "ALTERNATE")) generate
|
|
i_outdata_clken_b <= clocken2;
|
|
end generate IFG17b;
|
|
IFG17a: if (clock_enable_output_b = "BYPASS") generate
|
|
i_outdata_clken_b <= '1';
|
|
end generate IFG17a;
|
|
IFG18 : if ((outdata_reg_b = "CLOCK1") and (clock_enable_output_b = "NORMAL")) generate
|
|
i_outdata_clken_b <= clocken1;
|
|
end generate IFG18;
|
|
IFG18a : if ((outdata_reg_b = "CLOCK1") and (clock_enable_output_b = "ALTERNATE")) generate
|
|
i_outdata_clken_b <= clocken3;
|
|
end generate IFG18a;
|
|
|
|
-- case:32394, on SV onwards clear deassertion depends on output clock instead of core clock
|
|
IFG171b: if ((clock_enable_output_a = "NORMAL") and (outdata_reg_b = "UNREGISTERED") and (outdata_reg_a = "CLOCK0") and (address_reg_b = "CLOCK0") and (HAS_STRATIXV_STYLE_RAM) and (operation_mode = "BIDIR_DUAL_PORT")) generate
|
|
i_outlatch_clken_b <= clocken0;
|
|
end generate IFG171b;
|
|
|
|
-- case:32394, on SV onwards clear deassertion depends on output clock instead of core clock
|
|
IFG171c: if ((clock_enable_output_a = "NORMAL") and (outdata_reg_b = "UNREGISTERED") and (outdata_reg_a = "CLOCK1") and (address_reg_b = "CLOCK1") and (HAS_STRATIXV_STYLE_RAM) and (operation_mode = "BIDIR_DUAL_PORT")) generate
|
|
i_outlatch_clken_b <= clocken1;
|
|
end generate IFG171c;
|
|
|
|
-- for core clock a
|
|
IFG50a: if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (clock_enable_core_a = "USE_INPUT_CLKEN")) generate
|
|
i_core_clocken_a <= i_inclocken0;
|
|
end generate IFG50a;
|
|
IFG50b: if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (clock_enable_core_a = "ALTERNATE")) generate
|
|
i_core_clocken_a <= clocken2;
|
|
end generate IFG50b;
|
|
IFG50d: if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (clock_enable_core_a = "BYPASS")) generate
|
|
i_core_clocken_a <= '1';
|
|
end generate IFG50d;
|
|
IFG50c: if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (clock_enable_core_a = "NORMAL")) generate
|
|
i_core_clocken_a <= clocken0;
|
|
end generate IFG50c;
|
|
IFG50e: if ((not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)) generate
|
|
i_core_clocken_a <= i_inclocken0;
|
|
end generate IFG50e;
|
|
|
|
-- for core clock b
|
|
IFG51a: if ((((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (clock_enable_core_b = "USE_INPUT_CLKEN")) or
|
|
((not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM))) generate
|
|
i_core_clocken_b0 <= i_input_clocken_b;
|
|
i_core_clocken_b1 <= i_input_clocken_b;
|
|
end generate IFG51a;
|
|
IFG51e: if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (clock_enable_core_b = "NORMAL")) generate
|
|
i_core_clocken_b0 <= clocken0;
|
|
i_core_clocken_b1 <= clocken1;
|
|
end generate IFG51e;
|
|
IFG51b: if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (clock_enable_core_b = "ALTERNATE")) generate
|
|
i_core_clocken_b0 <= clocken2;
|
|
i_core_clocken_b1 <= clocken3;
|
|
end generate IFG51b;
|
|
IFG51c: if (((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (clock_enable_core_b = "BYPASS")) generate
|
|
i_core_clocken_b0 <= '1';
|
|
i_core_clocken_b1 <= '1';
|
|
end generate IFG51c;
|
|
IFG52a: if (address_reg_b = "CLOCK0") generate
|
|
i_core_clocken_b <= i_core_clocken_b0;
|
|
end generate IFG52a;
|
|
IFG52b: if (address_reg_b = "CLOCK1") generate
|
|
i_core_clocken_b <= i_core_clocken_b1;
|
|
end generate IFG52b;
|
|
|
|
|
|
|
|
-- Assigning the correct clear signals
|
|
|
|
-- for data in a
|
|
IFG20: if ((indata_aclr_a = "CLEAR0") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_indata_aclr_a <= aclr0;
|
|
end generate IFG20;
|
|
|
|
-- for address a
|
|
IFG22: if ((address_aclr_a = "CLEAR0") and
|
|
(not ((((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (operation_mode /= "ROM")) or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_address_aclr_a <= aclr0;
|
|
end generate IFG22;
|
|
|
|
-- for wren a
|
|
IFG24: if ((wrcontrol_aclr_a = "CLEAR0") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_wrcontrol_aclr_a <= aclr0;
|
|
end generate IFG24;
|
|
|
|
-- for byteena a
|
|
IFG26: if ((byteena_aclr_a = "CLEAR0") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_byteena_aclr_a <= aclr0;
|
|
end generate IFG26;
|
|
IFG27: if ((byteena_aclr_a = "CLEAR1") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_byteena_aclr_a <= aclr1;
|
|
end generate IFG27;
|
|
|
|
-- for data out a
|
|
IFG29: if (outdata_aclr_a = "CLEAR0") generate
|
|
i_outdata_aclr_a <= aclr0;
|
|
end generate IFG29;
|
|
IFG30: if (outdata_aclr_a = "CLEAR1") generate
|
|
i_outdata_aclr_a <= aclr1;
|
|
end generate IFG30;
|
|
|
|
-- for data out b
|
|
IFG31a: if (outdata_aclr_b = "CLEAR0") generate
|
|
i_outdata_aclr_b <= aclr0;
|
|
end generate IFG31a;
|
|
IFG31b: if (outdata_aclr_b = "CLEAR1") generate
|
|
i_outdata_aclr_b <= aclr1;
|
|
end generate IFG31b;
|
|
|
|
-- for data in b
|
|
IFG32: if ((indata_aclr_b = "CLEAR0") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_indata_aclr_b <= aclr0;
|
|
end generate IFG32;
|
|
IFG33: if ((indata_aclr_b = "CLEAR1") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_indata_aclr_b <= aclr1;
|
|
end generate IFG33;
|
|
|
|
-- for address b
|
|
IFG35: if ((address_aclr_b = "CLEAR0") and
|
|
not (IS_BASE_STRATIXII) and
|
|
not (IS_BASE_CYCLONEII) and
|
|
not (HAS_STRATIXV_STYLE_RAM) and
|
|
not (HAS_STRATIXIII_STYLE_RAM)) generate
|
|
i_address_aclr_b <= aclr0;
|
|
end generate IFG35;
|
|
IFG35a: if ((address_aclr_b = "CLEAR0") and (operation_mode = "DUAL_PORT") and
|
|
((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) generate
|
|
i_address_aclr_b <= aclr0;
|
|
end generate IFG35a;
|
|
IFG36: if ((address_aclr_b = "CLEAR1") and
|
|
not (IS_BASE_STRATIXII) and
|
|
not (IS_BASE_CYCLONEII) and
|
|
not ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) generate
|
|
i_address_aclr_b <= aclr1;
|
|
end generate IFG36;
|
|
IFG36a: if ((address_aclr_b = "CLEAR1") and (operation_mode = "DUAL_PORT") and
|
|
((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) generate
|
|
i_address_aclr_b <= aclr1;
|
|
end generate IFG36a;
|
|
|
|
-- for wren b
|
|
IFG38:if ((wrcontrol_aclr_b = "CLEAR0") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_wrcontrol_aclr_b <= aclr0;
|
|
end generate IFG38;
|
|
IFG39: if ((wrcontrol_aclr_b = "CLEAR1") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_wrcontrol_aclr_b <= aclr1;
|
|
end generate IFG39;
|
|
|
|
-- for rden b
|
|
IFG41: if ((rdcontrol_aclr_b = "CLEAR0") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_rdcontrol_aclr_b <= aclr0;
|
|
end generate IFG41;
|
|
IFG42: if ((rdcontrol_aclr_b = "CLEAR1") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_rdcontrol_aclr_b <= aclr1;
|
|
end generate IFG42;
|
|
|
|
-- for byteena b
|
|
IFG44: if ((byteena_aclr_b = "CLEAR0") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_byteena_aclr_b <= aclr0;
|
|
end generate IFG44;
|
|
IFG45: if ((byteena_aclr_b = "CLEAR1") and (not (HAS_STRATIXV_STYLE_RAM or HAS_STRATIXIII_STYLE_RAM or
|
|
(IS_BASE_STRATIXII or IS_BASE_CYCLONEII)))) generate
|
|
i_byteena_aclr_b <= aclr1;
|
|
end generate IFG45;
|
|
|
|
|
|
|
|
-- This process initializes and updates the memory content in the RAM accordingly
|
|
MEMORY: process (i_read_flag_a, i_write_flag_a, i_read_flag_b, i_write_flag_b, default_val, i_reread_flag_a, i_reread_flag_b, i_reread_flag2_a, i_reread_flag2_b)
|
|
|
|
variable j : integer := 0;
|
|
variable port_a_bit_count_low : integer := 0;
|
|
variable port_a_bit_count_high : integer := 0;
|
|
variable port_b_bit_count_low : integer := 0;
|
|
variable port_b_bit_count_high : integer := 0;
|
|
variable i_byteena_count : integer := 0;
|
|
variable m_mem_data_a : width_a_array;
|
|
variable m_mem_data_b : width_b_array;
|
|
variable m_temp_wa : std_logic_vector(width_a - 1 downto 0);
|
|
variable m_temp_wa2 : std_logic_vector(width_a - 1 downto 0) := (others => 'U');
|
|
variable m_temp_wa3 : std_logic_vector(width_a - 1 downto 0);
|
|
variable m_temp_wb : std_logic_vector(width_b - 1 downto 0);
|
|
variable m_temp_wb2 : std_logic;
|
|
variable m_init_file_b_port : boolean := false;
|
|
variable m_temp_wb3 : std_logic_vector(width_a - 1 downto 0);
|
|
variable m_current_written_data_b : std_logic_vector(width_b - 1 downto 0);
|
|
|
|
variable m_address_a : integer := 0;
|
|
variable m_address_b : integer := 0;
|
|
variable m_original_address_a : integer := 0;
|
|
variable m_data_write_time_a : time := 0 ps;
|
|
variable m_q_tmp2_a : std_logic_vector(width_a - 1 downto 0);
|
|
variable write_by_a : integer := 0;
|
|
variable prev_write_by_a : integer := 0;
|
|
|
|
variable write_by_b : integer := 0;
|
|
variable prev_write_by_b : integer := 0;
|
|
|
|
variable ctime : time := 0 ps;
|
|
variable reread_a : boolean := false;
|
|
variable reread_b : boolean := false;
|
|
variable last_read_a_event : boolean := false;
|
|
variable last_read_b_event : boolean := false;
|
|
variable need_init_var : boolean := true;
|
|
variable m_current_written_data_a : std_logic_vector(width_a - 1 downto 0);
|
|
variable m_original_data_a : std_logic_vector(width_a - 1 downto 0);
|
|
variable m_original_data_b : std_logic_vector(width_b - 1 downto 0);
|
|
variable m_data_a_x : std_logic_vector(width_a - 1 downto 0) := (others => 'X');
|
|
variable m_data_b_x : std_logic_vector(width_b - 1 downto 0) := (others => 'X');
|
|
|
|
begin
|
|
if (need_init_var) then
|
|
-- Begin of initializations
|
|
m_original_data_a := (others => default_val);
|
|
m_original_data_b := (others => default_val);
|
|
|
|
if (init_file = "UNUSED" or init_file = "NONE" or init_file = "") then
|
|
-- No memory file used
|
|
if (operation_mode /= "ROM") then
|
|
if (( ( (i_ram_block_type = "AUTO") and
|
|
( (cread_during_write_mode_mixed_ports = "DONT_CARE") or
|
|
(cread_during_write_mode_mixed_ports = "CONSTRAINED_DONT_CARE"))) or
|
|
IS_HARDCOPYII or
|
|
IS_HARDCOPYIII or
|
|
IS_HARDCOPYIV or
|
|
(i_ram_block_type = "MEGARAM") or (i_ram_block_type = "M-RAM") or
|
|
(power_up_uninitialized = "TRUE")) and
|
|
(implement_in_les = "OFF") and
|
|
not ((((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and (not IS_HARDCOPYIII) and (not IS_HARDCOPYIV) )
|
|
and (power_up_uninitialized /= "TRUE"))) then
|
|
|
|
for i in 0 to (2**widthad_a - 1) loop
|
|
m_mem_data_a(i) := (others => 'X');
|
|
end loop;
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
for i in 0 to (2**widthad_b - 1) loop
|
|
m_mem_data_b(i) := (others => 'X');
|
|
end loop;
|
|
end if;
|
|
else
|
|
|
|
for i in 0 to (2**widthad_a - 1) loop
|
|
m_mem_data_a(i) := (others => '0');
|
|
end loop;
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
for i in 0 to (2**widthad_b - 1) loop
|
|
m_mem_data_b(i) := (others => '0');
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
|
|
end if;
|
|
else
|
|
-- Using memory file to initialize memory content
|
|
if (( ((i_ram_block_type = "AUTO") and
|
|
( (cread_during_write_mode_mixed_ports = "DONT_CARE") or
|
|
(cread_during_write_mode_mixed_ports = "CONSTRAINED_DONT_CARE"))) or
|
|
IS_HARDCOPYII or
|
|
(power_up_uninitialized = "TRUE") or
|
|
(i_ram_block_type = "MEGARAM") or
|
|
(i_ram_block_type = "M-RAM")) and
|
|
not (HAS_STRATIXV_STYLE_RAM) and
|
|
not (HAS_STRATIXIII_STYLE_RAM) and
|
|
(operation_mode /= "ROM") ) then
|
|
for i in 0 to (2 ** widthad_a - 1) loop
|
|
m_mem_data_a(i) := (others => 'X');
|
|
end loop;
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
for i in 0 to (2**widthad_b - 1) loop
|
|
m_mem_data_b(i) := (others => 'X');
|
|
end loop;
|
|
end if;
|
|
else
|
|
for i in 0 to (2 ** widthad_a - 1) loop
|
|
m_mem_data_a(i) := (others => '0');
|
|
end loop;
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
for i in 0 to (2**widthad_b - 1) loop
|
|
m_mem_data_b(i) := (others => '0');
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
|
|
if (init_file_layout = "UNUSED") then
|
|
if (operation_mode = "DUAL_PORT") then
|
|
m_init_file_b_port := true;
|
|
else
|
|
m_init_file_b_port := false;
|
|
end if;
|
|
else
|
|
if (init_file_layout = "PORT_A") then
|
|
m_init_file_b_port := false;
|
|
elsif (init_file_layout = "PORT_B") then
|
|
m_init_file_b_port := true;
|
|
end if;
|
|
end if;
|
|
|
|
if (m_init_file_b_port) then
|
|
read_my_memory (false, m_mem_data_a, m_mem_data_b);
|
|
|
|
for i in 0 to (i_numwords_b * width_b - 1) loop
|
|
m_temp_wb := m_mem_data_b(i / width_b);
|
|
m_temp_wb2 := m_temp_wb((i)mod width_b);
|
|
m_temp_wa := m_mem_data_a(i / width_a);
|
|
m_temp_wa(i mod width_a) := m_temp_wb2;
|
|
m_mem_data_a(i / width_a) := m_temp_wa;
|
|
end loop;
|
|
else
|
|
read_my_memory (true, m_mem_data_a, m_mem_data_b);
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
for i in 0 to (i_numwords_a * width_a - 1) loop
|
|
m_temp_wa := m_mem_data_a(i / width_a);
|
|
m_temp_wb2 := m_temp_wa((i)mod width_a);
|
|
m_temp_wb := m_mem_data_b(i / width_b);
|
|
m_temp_wb(i mod width_b) := m_temp_wb2;
|
|
m_mem_data_b(i / width_b) := m_temp_wb;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (i_is_lutram) then
|
|
if (operation_mode = "DUAL_PORT") then
|
|
for i in 0 to (width_b - 1) loop
|
|
m_temp_wa2 := m_mem_data_a(i / width_a);
|
|
m_temp_wb(i) := m_temp_wa2(i mod width_a);
|
|
end loop;
|
|
i_q_tmp2_b <= m_temp_wb;
|
|
end if;
|
|
|
|
if ((operation_mode = "SINGLE_PORT") or (operation_mode = "ROM")) then
|
|
i_q_tmp2_a <= m_mem_data_a(0);
|
|
end if;
|
|
|
|
end if;
|
|
|
|
need_init_var := false;
|
|
|
|
-- End of initializations
|
|
|
|
end if;
|
|
|
|
-- Port A writing
|
|
if ((rising_edge(i_write_flag_a) or falling_edge(i_write_flag_a)) and (need_init_var = false)) then
|
|
if ((write_operation_a) and (i_good_to_write_a = '1')) then
|
|
m_original_data_a := m_mem_data_a(conv_integer(unsigned(i_address_reg_a)));
|
|
i_original_data_a <= m_mem_data_a(conv_integer(unsigned(i_address_reg_a)));
|
|
|
|
if (i_wren_reg_a = '1') then
|
|
if ((i_address_aclr_a = '1') and (conv_integer(unsigned(i_address_reg_a)) /= 0)) then
|
|
for i in 0 to (i_numwords_a - 1) loop
|
|
m_mem_data_a(i) := (others => 'X');
|
|
end loop;
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
for i in 0 to (i_numwords_b - 1) loop
|
|
m_mem_data_b(i) := (others => 'X');
|
|
end loop;
|
|
end if;
|
|
elsif (((i_indata_aclr_a = '1') and (i_data_reg_a /= i_data_zero_a)) or
|
|
((i_byteena_aclr_a = '1') and (i_byteena_mask_reg_a /= i_data_ones_a)) or
|
|
((i_wrcontrol_aclr_a = '1') and (i_wren_reg_a /= '0'))) then
|
|
m_mem_data_a (conv_integer(unsigned(i_address_reg_a))) := (others => 'X');
|
|
|
|
j := conv_integer(unsigned(i_address_reg_a)) * width_a;
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
for i in 0 to (width_a - 1) loop
|
|
m_temp_wb := m_mem_data_b((j + i) / width_b);
|
|
m_temp_wb((j + i) mod width_b) := 'X';
|
|
m_mem_data_b((j + i) / width_b) := m_temp_wb;
|
|
end loop;
|
|
end if;
|
|
else
|
|
port_a_bit_count_low := (conv_integer(unsigned(i_address_reg_a)) * width_a);
|
|
port_b_bit_count_low := (conv_integer(unsigned(i_address_reg_b)) * width_b);
|
|
port_b_bit_count_high := ((conv_integer(unsigned(i_address_reg_b)) * width_b) + width_b);
|
|
m_temp_wa := m_mem_data_a(conv_integer(unsigned(i_address_reg_a)));
|
|
|
|
for i in 0 to (width_a - 1) loop
|
|
port_a_bit_count_high := port_a_bit_count_low + i;
|
|
i_byteena_count := port_a_bit_count_high mod width_b;
|
|
|
|
if ((port_a_bit_count_high >= port_b_bit_count_low) and (port_a_bit_count_high < port_b_bit_count_high)) then
|
|
if ((i_core_clocken_b_reg = '1') and (i_wren_reg_b = '1') and ((address_reg_b = "CLOCK0") or (same_clock_pulse0 = '1' and same_clock_pulse1 = '1')) and
|
|
(i_byteena_mask_reg_b(i_byteena_count) = '1') and (i_byteena_mask_reg_a(i) = '1') and i_write_flag_b'event) then
|
|
m_temp_wa(i) := 'X';
|
|
elsif (i_byteena_mask_reg_a(i) = '1') then
|
|
m_temp_wa(i) := i_data_reg_a(i);
|
|
end if;
|
|
elsif (i_byteena_mask_reg_a(i) = '1') then
|
|
m_temp_wa(i) := i_data_reg_a(i);
|
|
end if;
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
m_temp_wb := m_mem_data_b(port_a_bit_count_high / width_b);
|
|
m_temp_wb(port_a_bit_count_high mod width_b) := m_temp_wa(i);
|
|
m_mem_data_b(port_a_bit_count_high / width_b) := m_temp_wb;
|
|
end if;
|
|
end loop;
|
|
|
|
m_mem_data_a (conv_integer(unsigned(i_address_reg_a))) := m_temp_wa;
|
|
m_original_address_a := conv_integer(unsigned(i_address_reg_a));
|
|
m_data_write_time_a := now;
|
|
write_by_a := write_by_a + 1;
|
|
end if;
|
|
end if;
|
|
|
|
m_current_written_data_a := m_mem_data_a(conv_integer(unsigned(i_address_reg_a)));
|
|
i_current_written_data_a <= m_mem_data_a(conv_integer(unsigned(i_address_reg_a)));
|
|
end if;
|
|
end if;
|
|
|
|
-- Port B writing
|
|
if ((rising_edge(i_write_flag_b) or falling_edge(i_write_flag_b)) and (need_init_var = false)) then
|
|
if ((write_operation_b) and (i_good_to_write_b = '1')) then
|
|
|
|
j := conv_integer(unsigned(i_address_reg_b)) * width_b;
|
|
for i in 0 to (width_b - 1) loop
|
|
m_temp_wb3 := m_mem_data_a((j + i) / width_a);
|
|
m_original_data_b(i) := m_temp_wb3((j + i) mod width_a);
|
|
i_original_data_b(i) <= m_temp_wb3((j + i) mod width_a);
|
|
end loop;
|
|
|
|
if (i_wren_reg_b = '1') then
|
|
if ((i_wrcontrol_aclr_b = '1') and (conv_integer(unsigned(i_address_reg_b)) /= 0)) then
|
|
for i in 0 to (i_numwords_a - 1) loop
|
|
m_mem_data_a(i) := (others => 'X');
|
|
end loop;
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
for i in 0 to (i_numwords_b - 1) loop
|
|
m_mem_data_b(i) := (others => 'X');
|
|
end loop;
|
|
end if;
|
|
elsif (((i_byteena_aclr_b = '1') and (i_byteena_mask_reg_b /= i_data_ones_b)) or
|
|
((i_indata_aclr_b = '1') and (i_data_reg_b /= i_data_zero_b)) or
|
|
((i_wrcontrol_aclr_b = '1') and (i_wren_reg_b /= '0'))) then
|
|
|
|
if (width_a = width_b) then
|
|
j := conv_integer(unsigned(i_address_reg_b));
|
|
m_mem_data_a(j) := (others => 'X');
|
|
else
|
|
j := conv_integer(unsigned(i_address_reg_b)) * width_b;
|
|
for i in 0 to (width_b - 1) loop
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wa2((j + i) mod width_a) := 'X';
|
|
m_mem_data_a((j + i) / width_a) := m_temp_wa2;
|
|
end loop;
|
|
end if;
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
m_mem_data_b(conv_integer(unsigned(i_address_reg_b))) := (others => 'X');
|
|
end if;
|
|
else
|
|
|
|
port_b_bit_count_low := (conv_integer(unsigned(i_address_reg_b)) * width_b);
|
|
port_a_bit_count_low := (conv_integer(unsigned(i_address_reg_a)) * width_a);
|
|
port_a_bit_count_high := (conv_integer(unsigned(i_address_reg_a)) * width_a) + width_a;
|
|
|
|
for i in 0 to (width_b - 1) loop
|
|
port_b_bit_count_high := port_b_bit_count_low + i;
|
|
m_temp_wa2 := m_mem_data_a((port_b_bit_count_high) / width_a);
|
|
if ((port_b_bit_count_high >= port_a_bit_count_low) and (port_b_bit_count_high < port_a_bit_count_high) and
|
|
(i_core_clocken_a_reg = '1') and (i_wren_reg_a = '1') and ((address_reg_b = "CLOCK0") or (same_clock_pulse0 = '1' and same_clock_pulse1 = '1')) and
|
|
(i_byteena_mask_reg_a((port_b_bit_count_high) mod width_a) = '1') and (i_byteena_mask_reg_b(i) = '1') and i_write_flag_a'event) then
|
|
m_temp_wa2((port_b_bit_count_high) mod width_a) := 'X';
|
|
elsif (i_byteena_mask_reg_b(i) = '1') then
|
|
m_temp_wa2((port_b_bit_count_high) mod width_a) := i_data_reg_b(i);
|
|
end if;
|
|
|
|
m_mem_data_a((port_b_bit_count_high) / width_a) := m_temp_wa2;
|
|
|
|
m_current_written_data_b(i) := m_temp_wa2((port_b_bit_count_high) mod width_a);
|
|
m_temp_wb(i) := m_temp_wa2((port_b_bit_count_high) mod width_a);
|
|
end loop;
|
|
|
|
if (enable_mem_data_b_reading = true) then
|
|
m_mem_data_b (conv_integer(unsigned(i_address_reg_b))) := m_temp_wb;
|
|
end if;
|
|
write_by_b := write_by_b + 1;
|
|
end if; -- end of choice selection
|
|
end if; -- i_wren_reg_b = '1'
|
|
|
|
end if;-- write_operation_b
|
|
end if; -- i_write_flag_b'event
|
|
|
|
-- To ensure that the model will reread port if two event (read & write) event triggered
|
|
-- at the different time quantum
|
|
reread_a := false;
|
|
reread_b := false;
|
|
if (ctime /= 0 ps) and (ctime = now) and
|
|
((i_write_flag_a'event) or
|
|
(i_write_flag_b'event)) then
|
|
if last_read_a_event then
|
|
reread_a := true;
|
|
end if;
|
|
if last_read_b_event then
|
|
reread_b := true;
|
|
end if;
|
|
end if;
|
|
|
|
if (i_write_flag_a'event and i_lutram_dual_port_fast_read) then
|
|
reread_b := true;
|
|
end if;
|
|
|
|
last_read_a_event := i_read_flag_a'event;
|
|
last_read_b_event := i_read_flag_b'event;
|
|
ctime := now;
|
|
|
|
|
|
-- Port A reading
|
|
if ((rising_edge(i_read_flag_a) or falling_edge(i_read_flag_a)) or (reread_a) or
|
|
rising_edge(i_reread_flag_a) or falling_edge(i_reread_flag_a) or rising_edge(i_reread_flag2_a) or falling_edge(i_reread_flag2_a)) then
|
|
if (write_by_a /= prev_write_by_a) then
|
|
prev_write_by_a := write_by_a;
|
|
end if;
|
|
|
|
if (read_operation_a) then
|
|
if (i_rden_reg_a = '1') then
|
|
m_address_a := conv_integer(unsigned(i_address_reg_a));
|
|
|
|
if (i_wren_reg_a = '1') then
|
|
if (i_core_clocken_a = '1') then
|
|
if (read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ") then
|
|
if (i_is_lutram and (clock0 = '1')) then
|
|
m_q_tmp2_a := m_mem_data_a(m_address_a);
|
|
else
|
|
m_q_tmp2_a := ((i_data_reg_a and i_byteena_mask_reg_a) or (m_data_a_x and not i_byteena_mask_reg_a));
|
|
end if;
|
|
elsif (read_during_write_mode_port_a = "NEW_DATA_WITH_NBE_READ") then
|
|
if (i_is_lutram and (clock0 = '1')) then
|
|
m_q_tmp2_a := m_mem_data_a(m_address_a);
|
|
else
|
|
m_q_tmp2_a := ((i_data_reg_a and i_byteena_mask_reg_a) or (m_mem_data_a(m_address_a) and not i_byteena_mask_reg_a)) xor i_byteena_mask_reg_a_x;
|
|
end if;
|
|
elsif (read_during_write_mode_port_a = "OLD_DATA") then
|
|
m_q_tmp2_a := m_original_data_a;
|
|
else
|
|
m_q_tmp2_a := i_data_reg_a xor i_byteena_mask_reg_a_out;
|
|
if ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) then
|
|
m_q_tmp2_a := (others => 'X');
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (i_lutram_single_port_fast_read) then
|
|
m_q_tmp2_a := m_mem_data_a(m_address_a);
|
|
end if;
|
|
else
|
|
|
|
m_address_a := conv_integer(unsigned(i_address_reg_a));
|
|
m_q_tmp2_a := m_mem_data_a(m_address_a);
|
|
|
|
-- This is to output an "X" when the other port is writing into the same location
|
|
-- when read_during_write_mode_mixed_ports = "DONT_CARE"
|
|
|
|
if (((address_reg_b = "CLOCK0") or (same_clock_pulse0 = '1' and same_clock_pulse1 = '1')) and (is_write_positive_edge)) then
|
|
if ((i_wren_reg_b = '1') and
|
|
(((i_core_clocken_b = '1') and ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) or
|
|
((i_input_clocken_b = '1') and (not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)))) then
|
|
|
|
m_address_b := conv_integer(unsigned(i_address_reg_b));
|
|
|
|
if (width_a = width_b) then
|
|
if (m_address_b = m_address_a) then
|
|
if (cread_during_write_mode_mixed_ports = "OLD_DATA") then
|
|
m_q_tmp2_a := m_original_data_b;
|
|
else
|
|
m_q_tmp2_a := m_q_tmp2_a xor i_byteena_mask_reg_b_out_a;
|
|
end if;
|
|
end if;
|
|
else
|
|
|
|
for i in (m_address_a * width_a) to ((m_address_a * width_a) + width_a - 1) loop
|
|
if ((i >= (m_address_b * width_b)) and (i <= ((m_address_b * width_b) + width_b - 1))) then
|
|
j := i - (m_address_a * width_a);
|
|
i_byteena_count := i - (m_address_b * width_b);
|
|
|
|
if (cread_during_write_mode_mixed_ports = "OLD_DATA") then
|
|
m_q_tmp2_a(j) := m_original_data_b(i_byteena_count);
|
|
else
|
|
m_q_tmp2_a(j) := m_q_tmp2_a(j) xor i_byteena_mask_reg_b_out_a(i_byteena_count);
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (conv_integer(unsigned(i_address_reg_a)) >= i_numwords_a) then
|
|
if ((i_wren_reg_a = '0') or (i_core_clocken_a = '0')) then
|
|
i_q_tmp2_a <= (others => 'X');
|
|
else
|
|
i_q_tmp2_a <= m_q_tmp2_a;
|
|
end if;
|
|
assert false
|
|
report "Address pointed at port A is out of bound! "
|
|
severity warning;
|
|
else
|
|
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (IS_CYCLONEIII)) and
|
|
(((outdata_aclr_a = "CLEAR0") and (aclr0 = '1')) or
|
|
((outdata_aclr_a = "CLEAR1") and (aclr1 = '1'))) and
|
|
(outdata_reg_a = "UNREGISTERED")) then
|
|
i_q_tmp2_a <= (others => '0');
|
|
else
|
|
i_q_tmp2_a <= m_q_tmp2_a;
|
|
end if;
|
|
|
|
if (i_is_lutram and (i_address_aclr_a = '1') and (operation_mode = "ROM")) then
|
|
i_q_tmp2_a <= m_mem_data_a(0);
|
|
end if;
|
|
end if;
|
|
|
|
else
|
|
if (((HAS_STRATIXV_STYLE_RAM) or (IS_CYCLONEIII)) and
|
|
(not i_is_lutram) and
|
|
(((outdata_aclr_a = "CLEAR0") and (aclr0 = '1')) or
|
|
((outdata_aclr_a = "CLEAR1") and (aclr1 = '1'))) and
|
|
(outdata_reg_a /= "CLOCK0") and (outdata_reg_a /= "CLOCK1")) then
|
|
i_q_tmp2_a <= (others => '0');
|
|
end if;
|
|
|
|
end if;
|
|
end if; -- end read_operation_a
|
|
|
|
end if;
|
|
|
|
-- Port B reading
|
|
if ((rising_edge(i_read_flag_b) or falling_edge(i_read_flag_b)) or (reread_b) or
|
|
rising_edge(i_reread_flag_b) or falling_edge(i_reread_flag_b) or rising_edge(i_reread_flag2_b) or falling_edge(i_reread_flag2_b)) then
|
|
|
|
if (write_by_b /= prev_write_by_b) then
|
|
prev_write_by_b := write_by_b;
|
|
end if;
|
|
|
|
if (read_operation_b) then
|
|
if (i_rden_reg_b = '1') then
|
|
m_address_a := conv_integer(unsigned(i_address_reg_a));
|
|
m_address_b := conv_integer(unsigned(i_address_reg_b));
|
|
|
|
-- No address conversion calculation if width_a is equals to width_b
|
|
if (width_a = width_b) then
|
|
|
|
if (i_wren_reg_b = '1') then
|
|
if (i_core_clocken_b = '1') then
|
|
if (read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ") then
|
|
i_q_tmp2_b <= ((i_data_reg_b and i_byteena_mask_reg_b) or
|
|
(m_data_b_x and not i_byteena_mask_reg_b));
|
|
elsif (read_during_write_mode_port_b = "NEW_DATA_WITH_NBE_READ") then
|
|
i_q_tmp2_b <= ((i_data_reg_b and i_byteena_mask_reg_b) or (m_mem_data_a(m_address_b) and
|
|
not i_byteena_mask_reg_b)) xor i_byteena_mask_reg_b_x;
|
|
elsif (read_during_write_mode_port_b = "OLD_DATA") then
|
|
i_q_tmp2_b <= m_original_data_b;
|
|
else
|
|
i_q_tmp2_b <= (others => 'X');
|
|
end if;
|
|
end if;
|
|
elsif (((m_data_write_time_a = now) and (operation_mode = "DUAL_PORT") and
|
|
(not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM))) then
|
|
if ((m_address_a = m_address_b) and (m_address_a = m_original_address_a)) then
|
|
if (address_reg_b /= "CLOCK0") then
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b) xor i_byteena_mask_reg_a_out_b;
|
|
elsif (cread_during_write_mode_mixed_ports = "OLD_DATA") then
|
|
i_q_tmp2_b <= m_original_data_a;
|
|
elsif ((cread_during_write_mode_mixed_ports = "DONT_CARE") or (cread_during_write_mode_mixed_ports = "CONSTRAINED_DONT_CARE")) then
|
|
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b) xor i_byteena_mask_reg_a_out_b;
|
|
else
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b);
|
|
end if;
|
|
else
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b);
|
|
end if;
|
|
else
|
|
if (m_address_a = m_address_b) then
|
|
if (i_is_lutram) then
|
|
if (((address_reg_b = "CLOCK0") or (same_clock_pulse0 = '1' and same_clock_pulse1 = '1')) and (is_write_positive_edge)) then
|
|
if ((i_wren_reg_a = '1') and
|
|
(((i_core_clocken_a = '1') and ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) or
|
|
((i_inclocken0 = '1') and (not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)))) then
|
|
if ((cread_during_write_mode_mixed_ports = "OLD_DATA") and (outdata_reg_b = "CLOCK0")) then
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b);
|
|
else
|
|
i_q_tmp2_b <= m_current_written_data_a;
|
|
end if;
|
|
else
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b);
|
|
end if;
|
|
else
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b);
|
|
end if;
|
|
elsif ((i_ram_block_type = "MEGARAM") or
|
|
(i_ram_block_type = "M-RAM") or
|
|
(((cread_during_write_mode_mixed_ports = "DONT_CARE") or (cread_during_write_mode_mixed_ports = "CONSTRAINED_DONT_CARE")) and (i_ram_block_type = "AUTO"))) then
|
|
if (((address_reg_b = "CLOCK0") or (same_clock_pulse0 = '1' and same_clock_pulse1 = '1')) and (is_write_positive_edge)) then
|
|
if ((i_wren_reg_a = '1') and
|
|
(((i_core_clocken_a = '1') and ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) or
|
|
((i_inclocken0 = '1') and (not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)))) then
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b) xor i_byteena_mask_reg_a_out_b;
|
|
else
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b);
|
|
end if;
|
|
else
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b);
|
|
end if;
|
|
else
|
|
if (((address_reg_b = "CLOCK0") or (same_clock_pulse0 = '1' and same_clock_pulse1 = '1')) and (is_write_positive_edge)) then
|
|
if ((i_wren_reg_a = '1') and
|
|
(((i_core_clocken_a = '1') and ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) or
|
|
((i_inclocken0 = '1') and (not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM))) and
|
|
(is_write_positive_edge)) then
|
|
if (cread_during_write_mode_mixed_ports = "OLD_DATA") then
|
|
i_q_tmp2_b <= m_original_data_a;
|
|
else
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b) xor i_byteena_mask_reg_a_out_b;
|
|
end if;
|
|
else
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b);
|
|
end if;
|
|
else
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b);
|
|
end if;
|
|
end if;
|
|
else
|
|
i_q_tmp2_b <= m_mem_data_a(m_address_b);
|
|
end if;
|
|
end if;
|
|
|
|
else
|
|
|
|
j := m_address_b * width_b;
|
|
|
|
for i in 0 to (width_b - 1) loop
|
|
|
|
if (i_wren_reg_b = '1') then
|
|
if (read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ") then
|
|
m_temp_wb(i) := ((i_data_reg_b(i) and i_byteena_mask_reg_b(i)) or
|
|
(m_data_b_x(i) and not i_byteena_mask_reg_b(i)));
|
|
elsif (read_during_write_mode_port_b = "NEW_DATA_WITH_NBE_READ") then
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := ((i_data_reg_b(i) and i_byteena_mask_reg_b(i)) or (m_temp_wa2((j + i) mod width_a) and not i_byteena_mask_reg_b(i))) xor i_byteena_mask_reg_b_x(i);
|
|
elsif (read_during_write_mode_port_b = "OLD_DATA") then
|
|
m_temp_wb(i) := m_original_data_b(i);
|
|
else
|
|
m_temp_wb(i) := 'X';
|
|
end if;
|
|
elsif ((m_data_write_time_a = now) and (operation_mode = "DUAL_PORT") and
|
|
(not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)) then
|
|
if ((m_address_a = ((j + i) / width_a)) and (m_address_a = m_original_address_a)) then
|
|
if (address_reg_b /= "CLOCK0") then
|
|
m_temp_wa2 := (m_mem_data_a((j + i) / width_a)) xor i_byteena_mask_reg_a_out_b;
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
elsif (cread_during_write_mode_mixed_ports = "OLD_DATA") then
|
|
m_temp_wb(i) := m_original_data_a((j + i) mod width_a);
|
|
elsif ((cread_during_write_mode_mixed_ports = "DONT_CARE") or (cread_during_write_mode_mixed_ports = "CONSTRAINED_DONT_CARE"))then
|
|
m_temp_wa2 := (m_mem_data_a((j + i) / width_a)) xor i_byteena_mask_reg_a_out_b;
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
else
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end if;
|
|
else
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end if;
|
|
else
|
|
if (((j + i) / width_a) = m_address_a) then
|
|
if (i_is_lutram) then
|
|
if (((address_reg_b = "CLOCK0") or (same_clock_pulse0 = '1' and same_clock_pulse1 = '1')) and (is_write_positive_edge)) then
|
|
if ((i_wren_reg_a = '1') and
|
|
(((i_core_clocken_a = '1') and ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) or
|
|
((i_inclocken0 = '1') and (not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)))) then
|
|
if ((cread_during_write_mode_mixed_ports = "OLD_DATA") and (outdata_reg_b = "CLOCK0")) then
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
else
|
|
m_temp_wb(i) := m_current_written_data_a((j + i) mod width_a);
|
|
end if;
|
|
else
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end if;
|
|
else
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end if;
|
|
elsif ((i_ram_block_type = "MEGARAM") or (i_ram_block_type = "M-RAM") or
|
|
(((cread_during_write_mode_mixed_ports = "DONT_CARE") or (cread_during_write_mode_mixed_ports = "CONSTRAINED_DONT_CARE")) and
|
|
(i_ram_block_type = "AUTO"))) then
|
|
if (((address_reg_b = "CLOCK0") or (same_clock_pulse0 = '1' and same_clock_pulse1 = '1')) and (is_write_positive_edge)) then
|
|
if ((i_wren_reg_a = '1') and
|
|
(((i_core_clocken_a = '1') or (i_inclocken0 = '1')) and
|
|
((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)))) then
|
|
m_temp_wa2 := (m_mem_data_a((j + i) / width_a)) xor i_byteena_mask_reg_a_out_b;
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
else
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end if;
|
|
else
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end if;
|
|
else
|
|
if (((address_reg_b = "CLOCK0") or (same_clock_pulse0 = '1' and same_clock_pulse1 = '1')) and (is_write_positive_edge)) then
|
|
if ((i_wren_reg_a = '1') and
|
|
(((i_core_clocken_a = '1') or (i_inclocken0 = '1')) and
|
|
((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) and
|
|
(is_write_positive_edge)) then
|
|
if (cread_during_write_mode_mixed_ports = "OLD_DATA") then
|
|
m_temp_wb(i) := m_original_data_a((j + i) mod width_a);
|
|
else
|
|
m_temp_wa2 := (m_mem_data_a((j + i) / width_a)) xor i_byteena_mask_reg_a_out_b;
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end if;
|
|
else
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end if;
|
|
|
|
else
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end if;
|
|
end if;
|
|
else
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
|
|
i_q_tmp2_b <= m_temp_wb;
|
|
end if;
|
|
end if;
|
|
|
|
if (i_is_lutram and (i_address_aclr_b = '1') and operation_mode = "DUAL_PORT") then
|
|
for i in 0 to (width_b - 1) loop
|
|
m_temp_wa2 := m_mem_data_a(i / width_a);
|
|
m_temp_wb(i) := m_temp_wa2(i mod width_a);
|
|
end loop;
|
|
i_q_tmp2_b <= m_temp_wb;
|
|
elsif (i_is_lutram and operation_mode = "DUAL_PORT") then
|
|
j := m_address_b * width_b;
|
|
|
|
for i in 0 to (width_b - 1) loop
|
|
m_temp_wa2 := m_mem_data_a((j + i) / width_a);
|
|
m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
|
|
end loop;
|
|
i_q_tmp2_b <= m_temp_wb;
|
|
end if;
|
|
|
|
if ((((outdata_aclr_b = "CLEAR0") and (aclr0 = '1')) or ((outdata_aclr_b = "CLEAR1") and (aclr1 = '1'))) and
|
|
(outdata_reg_b /= "CLOCK0") and (outdata_reg_b /= "CLOCK1") and
|
|
(((HAS_STRATIXV_STYLE_RAM) or (IS_CYCLONEIII)) and
|
|
(not i_is_lutram))) then
|
|
i_q_tmp2_b <= (others => '0');
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end process memory;
|
|
|
|
|
|
-- Port A inputs registered : indata, address, byeteena, wren
|
|
process (clock0)
|
|
variable m_byteena_mask_reg_a : std_logic_vector(width_a - 1 downto 0);
|
|
variable m_byteena_mask_reg_a_out : std_logic_vector(width_a - 1 downto 0);
|
|
variable m_byteena_mask_reg_a_x : std_logic_vector(width_a - 1 downto 0):= (others => '0');
|
|
variable m_indata_reg_aclr_a : std_logic := '0';
|
|
variable m_wren_reg_aclr_a : std_logic := '0';
|
|
variable m_byteena_reg_aclr_a : std_logic := '0';
|
|
variable m_address_reg_aclr_a : std_logic := '0';
|
|
variable m_byteena_mask_reg_a_out_b : std_logic_vector(width_a - 1 downto 0);
|
|
variable need_init_var : boolean := true;
|
|
begin
|
|
|
|
if (need_init_var = true) then
|
|
if ((IS_HARDCOPYII) and
|
|
(ram_block_type = "M4K") and (operation_mode /= "SINGLE_PORT") and (clock0 = '1')) then
|
|
i_good_to_write_b <= '0';
|
|
end if;
|
|
|
|
need_init_var := false;
|
|
end if;
|
|
|
|
if (rising_edge(clock0)) then
|
|
|
|
if (i_address_aclr_a = '1') then
|
|
i_address_reg_a <= (others => '0');
|
|
end if;
|
|
|
|
if (i_force_reread_a = '1' and (i_outlatch_clken_a = '1')) then
|
|
i_force_reread_signal_a <= not i_force_reread_signal_a;
|
|
end if;
|
|
|
|
i_core_clocken_a_reg <= i_core_clocken_a;
|
|
|
|
if (i_core_clocken_a = '1') then
|
|
if (i_force_reread_a1 = '1') then
|
|
i_force_reread_signal_a <= not i_force_reread_signal_a;
|
|
end if;
|
|
|
|
if ((HAS_STRATIXV_STYLE_RAM or IS_STRATIXIII) and (not i_is_lutram)) then
|
|
|
|
good_to_go_a <= '1';
|
|
|
|
if (i_wrcontrol_aclr_a = '1') then
|
|
i_wren_reg_a <= '0';
|
|
else
|
|
i_wren_reg_a <= wren_a;
|
|
end if;
|
|
|
|
i_rden_reg_a <= rden_a;
|
|
|
|
end if;
|
|
|
|
if ((not i_is_lutram) and ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) then
|
|
i_read_flag_a <= not i_read_flag_a;
|
|
end if;
|
|
|
|
if ((is_write_positive_edge) and ((wren_a = '1') or (i_wren_reg_a = '1'))) then
|
|
i_write_flag_a <= not i_write_flag_a;
|
|
end if;
|
|
|
|
if (operation_mode /= "ROM") then
|
|
i_nmram_write_a <= '1';
|
|
end if;
|
|
else
|
|
if (operation_mode /= "ROM") then
|
|
i_nmram_write_a <= '0';
|
|
end if;
|
|
end if;
|
|
|
|
if (i_is_lutram) then
|
|
if (i_wrcontrol_aclr_a = '1') then
|
|
i_wren_reg_a <= '0';
|
|
elsif (i_core_clocken_a = '1') then
|
|
i_wren_reg_a <= wren_a;
|
|
end if;
|
|
end if;
|
|
|
|
if (((clock_enable_input_a = "NORMAL") and (clocken0 = '1')) or
|
|
((clock_enable_input_a = "ALTERNATE") and (clocken2 = '1')) or
|
|
(clock_enable_input_a = "BYPASS")) then
|
|
|
|
if (((not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)) or i_is_lutram) then
|
|
i_read_flag_a <= not i_read_flag_a;
|
|
end if;
|
|
|
|
if (i_indata_aclr_a = '1') then
|
|
i_data_reg_a <= (others => '0');
|
|
else
|
|
i_data_reg_a <= data_a;
|
|
end if;
|
|
|
|
if (((not HAS_STRATIXV_STYLE_RAM) and (not IS_STRATIXIII)) or (i_is_lutram)) then
|
|
|
|
good_to_go_a <= '1';
|
|
|
|
if (i_wrcontrol_aclr_a = '1') then
|
|
i_wren_reg_a <= '0';
|
|
else
|
|
i_wren_reg_a <= wren_a;
|
|
end if;
|
|
|
|
i_rden_reg_a <= rden_a;
|
|
|
|
end if;
|
|
|
|
if (i_byteena_aclr_a = '1') then
|
|
m_byteena_mask_reg_a := (others => '1');
|
|
m_byteena_mask_reg_a_out := (others => '0');
|
|
m_byteena_mask_reg_a_out_b := (others => 'X');
|
|
else
|
|
if (width_byteena_a = 1) then
|
|
m_byteena_mask_reg_a := (others => byteena_a(0));
|
|
if (byteena_a(0) = '1') then
|
|
m_byteena_mask_reg_a_out := (others => '0');
|
|
m_byteena_mask_reg_a_x := (others => '0');
|
|
m_byteena_mask_reg_a_out_b := (others => 'X');
|
|
elsif (byteena_a(0) = '0') then
|
|
m_byteena_mask_reg_a_x := (others => '0');
|
|
m_byteena_mask_reg_a_out := (others => 'X');
|
|
m_byteena_mask_reg_a_out_b := (others => '0');
|
|
else
|
|
m_byteena_mask_reg_a_x := (others => 'X');
|
|
m_byteena_mask_reg_a_out := (others => 'X');
|
|
m_byteena_mask_reg_a_out_b := (others => 'X');
|
|
end if;
|
|
|
|
else
|
|
for k in 0 to (width_a - 1) loop
|
|
m_byteena_mask_reg_a(k) := byteena_a(k / i_byte_size);
|
|
if (m_byteena_mask_reg_a(k) = '1') then
|
|
m_byteena_mask_reg_a_out(k) := '0';
|
|
m_byteena_mask_reg_a_x(k) := '0';
|
|
m_byteena_mask_reg_a_out_b(k) := 'X';
|
|
elsif (m_byteena_mask_reg_a(k) = '0') then
|
|
m_byteena_mask_reg_a_x(k) := '0';
|
|
m_byteena_mask_reg_a_out(k) := 'X';
|
|
m_byteena_mask_reg_a_out_b(k) := '0';
|
|
else
|
|
m_byteena_mask_reg_a_out(k) := 'X';
|
|
m_byteena_mask_reg_a_x(k) := 'X';
|
|
m_byteena_mask_reg_a_out_b(k) := 'X';
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
|
|
i_byteena_mask_reg_a_out <= m_byteena_mask_reg_a_out;
|
|
i_byteena_mask_reg_a <= m_byteena_mask_reg_a;
|
|
i_byteena_mask_reg_a_x <= m_byteena_mask_reg_a_x;
|
|
i_byteena_mask_reg_a_out_b <= m_byteena_mask_reg_a_out_b;
|
|
|
|
if (i_address_aclr_a = '1') then
|
|
i_address_reg_a <= (others => '0');
|
|
elsif (addressstall_a /= '1') then
|
|
i_address_reg_a <= address_a;
|
|
end if;
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if (falling_edge(clock0)) then
|
|
|
|
if (i_core_clocken_a = '1') then
|
|
i_good_to_write_b <= '1';
|
|
end if;
|
|
|
|
if (not is_write_positive_edge) then
|
|
if (i_nmram_write_a = '1') then
|
|
i_write_flag_a <= not i_write_flag_a;
|
|
if (i_is_lutram) then
|
|
i_read_flag_a <= not i_read_flag_a;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
IFCLR01 : if ((HAS_STRATIXV_STYLE_RAM) or (IS_CYCLONEIII)) generate
|
|
process (i_outdata_aclr_a)
|
|
begin
|
|
if ((outdata_reg_a /= "CLOCK0") and (outdata_reg_a /= "CLOCK1")) then
|
|
if (rising_edge(i_outdata_aclr_a)) then
|
|
i_reread_flag_a <= not i_reread_flag_a;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process (i_outdata_aclr_b)
|
|
begin
|
|
if ((outdata_reg_b /= "CLOCK0") and (outdata_reg_b /= "CLOCK1")) then
|
|
if (rising_edge(i_outdata_aclr_b)) then
|
|
i_reread_flag_b <= not i_reread_flag_b;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFCLR01;
|
|
|
|
IFCLR02 : if (i_is_lutram and (operation_mode = "DUAL_PORT")) generate
|
|
process (i_address_aclr_b)
|
|
begin
|
|
if (rising_edge(i_address_aclr_b)) then
|
|
i_reread_flag2_b <= not i_reread_flag2_b;
|
|
end if;
|
|
end process;
|
|
end generate IFCLR02;
|
|
|
|
IFCLR03 : if (i_is_lutram and (operation_mode = "ROM")) generate
|
|
process (i_address_aclr_a)
|
|
begin
|
|
if (rising_edge(i_address_aclr_a)) then
|
|
i_reread_flag2_a <= not i_reread_flag2_a;
|
|
end if;
|
|
end process;
|
|
end generate IFCLR03;
|
|
|
|
|
|
-- Port B address input registered (for dual_port mode)
|
|
IFG48: if (((address_reg_b = "CLOCK0") or (address_reg_b = "CLOCK1")) and
|
|
(operation_mode = "DUAL_PORT")) generate
|
|
process (clock0, clock1, i_address_aclr_b)
|
|
variable need_init_var : boolean := true;
|
|
begin
|
|
|
|
if (need_init_var = true) then
|
|
if ((IS_HARDCOPYII) and
|
|
(ram_block_type = "M4K") and (operation_mode /= "SINGLE_PORT") and
|
|
(((address_reg_b = "CLOCK0") and (clock0 = '1')) or ((address_reg_b = "CLOCK1") and (clock1 = '1')))) then
|
|
i_good_to_write_a <= '0';
|
|
end if;
|
|
|
|
need_init_var := false;
|
|
end if;
|
|
|
|
if (rising_edge(i_address_aclr_b)) then
|
|
if (i_address_aclr_b = '1') then
|
|
if (i_is_lutram) then
|
|
i_address_reg_b <= (others => '0');
|
|
i_read_flag_b <= not i_read_flag_b;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if ((rising_edge(clock0) and (address_reg_b = "CLOCK0")) or
|
|
(rising_edge(clock1) and (address_reg_b = "CLOCK1"))) then
|
|
|
|
i_core_clocken_b_reg <= i_core_clocken_b;
|
|
|
|
if (i_force_reread_b = '1' and (i_outlatch_clken_b = '1')) then
|
|
i_force_reread_signal_b <= not i_force_reread_signal_b;
|
|
end if;
|
|
|
|
if (i_address_aclr_b = '1') then
|
|
i_address_reg_b <= (others => '0');
|
|
end if;
|
|
|
|
if (i_core_clocken_b = '1') then
|
|
if (i_force_reread_b1 = '1') then
|
|
i_force_reread_signal_b <= not i_force_reread_signal_b;
|
|
end if;
|
|
if ((HAS_STRATIXV_STYLE_RAM or IS_STRATIXIII) and not i_is_lutram) then
|
|
good_to_go_b <= '1';
|
|
|
|
if (i_rdcontrol_aclr_b = '1') then
|
|
i_rden_reg_b <= '1';
|
|
else
|
|
i_rden_reg_b <= rden_b;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (i_input_clocken_b = '1') then
|
|
|
|
if (((not HAS_STRATIXV_STYLE_RAM) and (not IS_STRATIXIII)) or i_is_lutram) then
|
|
good_to_go_b <= '1';
|
|
|
|
if (i_rdcontrol_aclr_b = '1') then
|
|
i_rden_reg_b <= '1';
|
|
else
|
|
i_rden_reg_b <= rden_b;
|
|
end if;
|
|
end if;
|
|
|
|
if (i_indata_aclr_b = '1') then
|
|
i_data_reg_b <= (others => '0');
|
|
else
|
|
i_data_reg_b <= data_b;
|
|
end if;
|
|
|
|
if (i_address_aclr_b = '1') then
|
|
i_address_reg_b <= (others => '0');
|
|
elsif (addressstall_b /= '1') then
|
|
i_address_reg_b <= address_b;
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if (not i_lutram_dual_port_fast_read and ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) then
|
|
if (i_core_clocken_b = '1') then
|
|
i_read_flag_b <= not i_read_flag_b;
|
|
end if;
|
|
elsif (((not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)) or (i_is_lutram)) then
|
|
if (i_input_clocken_b = '1') then
|
|
i_read_flag_b <= not i_read_flag_b;
|
|
end if;
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if (((i_is_lutram) and
|
|
(i_lutram_dual_port_fast_read)) and
|
|
falling_edge(clock0)) then
|
|
if (i_core_clocken_b = '1') then
|
|
i_read_flag_b <= not i_read_flag_b;
|
|
end if;
|
|
end if;
|
|
|
|
if ((falling_edge(clock0) and (address_reg_b = "CLOCK0")) or
|
|
(falling_edge(clock1) and (address_reg_b = "CLOCK1"))) then
|
|
if (i_core_clocken_b = '1') then
|
|
i_good_to_write_a <= '1';
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
end generate IFG48;
|
|
|
|
|
|
-- Port B inputs registered : wren, address, byteena (for bidir_dual_port mode)
|
|
IFG49: if (((address_reg_b = "CLOCK0") or
|
|
(address_reg_b = "CLOCK1")) and
|
|
(operation_mode = "BIDIR_DUAL_PORT")) generate
|
|
process (clock0, clock1)
|
|
variable m_byteena_mask_reg_b : std_logic_vector(width_b - 1 downto 0);
|
|
variable m_byteena_mask_reg_b_out : std_logic_vector(width_b - 1 downto 0);
|
|
variable m_byteena_mask_reg_b_x : std_logic_vector(width_b - 1 downto 0) := (others => '0');
|
|
variable m_byteena_mask_reg_b_out_a : std_logic_vector(width_b - 1 downto 0);
|
|
variable need_init_var : boolean := true;
|
|
begin
|
|
|
|
if (need_init_var = true) then
|
|
if ((IS_HARDCOPYII) and
|
|
(ram_block_type = "M4K") and (operation_mode /= "SINGLE_PORT") and
|
|
(((address_reg_b = "CLOCK0") and (clock0 = '1')) or ((address_reg_b = "CLOCK1") and (clock1 = '1')))) then
|
|
i_good_to_write_a <= '0';
|
|
end if;
|
|
|
|
need_init_var := false;
|
|
end if;
|
|
|
|
if (((address_reg_b = "CLOCK0") and
|
|
(rising_edge(clock0))) or
|
|
((address_reg_b = "CLOCK1") and
|
|
(rising_edge(clock1)))) then
|
|
|
|
if (i_force_reread_b = '1' and (i_outlatch_clken_b = '1')) then
|
|
i_force_reread_signal_b <= not i_force_reread_signal_b;
|
|
end if;
|
|
|
|
if (i_core_clocken_b = '1') then
|
|
if (HAS_STRATIXV_STYLE_RAM or IS_STRATIXIII) then
|
|
good_to_go_b <= '1';
|
|
|
|
if (i_rdcontrol_aclr_b = '1') then
|
|
i_rden_reg_b <= '1';
|
|
else
|
|
i_rden_reg_b <= rden_b;
|
|
end if;
|
|
|
|
if (i_wrcontrol_aclr_b = '1') then
|
|
i_wren_reg_b <= '0';
|
|
else
|
|
i_wren_reg_b <= wren_b;
|
|
|
|
i_read_flag_b <= not i_read_flag_b;
|
|
end if;
|
|
end if;
|
|
else
|
|
i_nmram_write_b <= '0';
|
|
end if;
|
|
|
|
if (i_input_clocken_b = '1') then
|
|
|
|
if ((not HAS_STRATIXV_STYLE_RAM) and (not HAS_STRATIXIII_STYLE_RAM)) then
|
|
i_read_flag_b <= not i_read_flag_b;
|
|
end if;
|
|
|
|
if (i_indata_aclr_b = '1') then
|
|
i_data_reg_b <= (others => '0');
|
|
else
|
|
i_data_reg_b <= data_b;
|
|
end if;
|
|
|
|
if ((not HAS_STRATIXV_STYLE_RAM) and (not IS_STRATIXIII)) then
|
|
good_to_go_b <= '1';
|
|
|
|
if (i_rdcontrol_aclr_b = '1') then
|
|
i_rden_reg_b <= '1';
|
|
else
|
|
i_rden_reg_b <= rden_b;
|
|
end if;
|
|
|
|
if (i_wrcontrol_aclr_b = '1') then
|
|
i_wren_reg_b <= '0';
|
|
else
|
|
i_wren_reg_b <= wren_b;
|
|
|
|
end if;
|
|
end if;
|
|
|
|
if (i_wrcontrol_aclr_b = '1') then
|
|
i_address_reg_b <= (others => '0');
|
|
elsif (addressstall_b /= '1') then
|
|
i_address_reg_b <= address_b;
|
|
end if;
|
|
|
|
if (i_byteena_aclr_b = '1') then
|
|
m_byteena_mask_reg_b := (others => '1');
|
|
m_byteena_mask_reg_b_out := (others => '0');
|
|
m_byteena_mask_reg_b_x := (others => '0');
|
|
m_byteena_mask_reg_b_out_a := (others => 'X');
|
|
else
|
|
if (width_byteena_b = 1) then
|
|
if (byteena_b(0) = 'Z') then
|
|
m_byteena_mask_reg_b := (others => '1');
|
|
else
|
|
m_byteena_mask_reg_b := (others => byteena_b(0));
|
|
end if;
|
|
if ((byteena_b(0) = '1') or (byteena_b(0) = 'Z')) then
|
|
m_byteena_mask_reg_b_out := (others => '0');
|
|
m_byteena_mask_reg_b_x := (others => '0');
|
|
m_byteena_mask_reg_b_out_a := (others => 'X');
|
|
elsif (byteena_b(0) = '0') then
|
|
m_byteena_mask_reg_b_x := (others => '0');
|
|
m_byteena_mask_reg_b_out := (others => 'X');
|
|
m_byteena_mask_reg_b_out_a := (others => '0');
|
|
else
|
|
m_byteena_mask_reg_b_x := (others => 'X');
|
|
m_byteena_mask_reg_b_out := (others => 'X');
|
|
m_byteena_mask_reg_b_out_a := (others => 'X');
|
|
end if;
|
|
else
|
|
for k in 0 to (width_b - 1) loop
|
|
if (byteena_b(k / i_byte_size) = 'Z') then
|
|
m_byteena_mask_reg_b(k) := '1';
|
|
else
|
|
m_byteena_mask_reg_b(k) := byteena_b(k / i_byte_size);
|
|
end if;
|
|
|
|
if (m_byteena_mask_reg_b(k) = '1') then
|
|
m_byteena_mask_reg_b_out(k) := '0';
|
|
m_byteena_mask_reg_b_x(k) := '0';
|
|
m_byteena_mask_reg_b_out_a(k) := 'X';
|
|
elsif (m_byteena_mask_reg_b(k) = '0') then
|
|
m_byteena_mask_reg_b_out(k) := 'X';
|
|
m_byteena_mask_reg_b_x(k) := '0';
|
|
m_byteena_mask_reg_b_out_a(k) := '0';
|
|
else
|
|
m_byteena_mask_reg_b_out(k) := 'X';
|
|
m_byteena_mask_reg_b_x(k) := 'X';
|
|
m_byteena_mask_reg_b_out_a(k) := 'X';
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
|
|
i_byteena_mask_reg_b_out <= m_byteena_mask_reg_b_out;
|
|
i_byteena_mask_reg_b <= m_byteena_mask_reg_b;
|
|
i_byteena_mask_reg_b_x <= m_byteena_mask_reg_b_x;
|
|
i_byteena_mask_reg_b_out_a <= m_byteena_mask_reg_b_out_a;
|
|
end if;
|
|
|
|
if ((i_core_clocken_b = '1') and ((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM))) then
|
|
i_read_flag_b <= not i_read_flag_b;
|
|
end if;
|
|
|
|
if ((i_core_clocken_b = '1') and ((wren_b = '1') or (i_wren_reg_b = '1'))) then
|
|
if (is_write_positive_edge) then
|
|
i_write_flag_b <= not i_write_flag_b;
|
|
end if;
|
|
|
|
i_nmram_write_b <= '1';
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if (((address_reg_b = "CLOCK0") and
|
|
(falling_edge(clock0))) or
|
|
((address_reg_b = "CLOCK1") and
|
|
(falling_edge(clock1)))) then
|
|
|
|
if (i_core_clocken_b = '1') then
|
|
i_good_to_write_a <= '1';
|
|
end if;
|
|
|
|
if (not is_write_positive_edge) then
|
|
if ((i_nmram_write_b = '1') and (i_wren_reg_b = '1')) then
|
|
i_write_flag_b <= not i_write_flag_b;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
end generate IFG49;
|
|
|
|
-- Port A : assigning the correct output values for i_q_tmp_a (non-registered output)
|
|
|
|
process (i_q_tmp2_a, i_force_reread_signal_a, i_outdata_aclr_a, good_to_go_a, default_val, i_address_aclr_a)
|
|
variable i_force_reread_a1_flag : std_logic := '0';
|
|
begin
|
|
if (not good_to_go_a = '1') then
|
|
if (i_is_lutram) then
|
|
i_q_tmp_a <= i_q_tmp2_a;
|
|
else
|
|
i_q_tmp_a <= (others => default_val);
|
|
end if;
|
|
else
|
|
if ((i_outdata_aclr_a = '1')and
|
|
(outdata_reg_a /= "CLOCK0") and
|
|
(outdata_reg_a /= "CLOCK1") and
|
|
(((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and
|
|
(not i_is_lutram))) then
|
|
i_q_tmp_a <= (others => '0');
|
|
elsif (falling_edge(i_outdata_aclr_a)and
|
|
(outdata_reg_a /= "CLOCK0") and
|
|
(outdata_reg_a /= "CLOCK1") and
|
|
(((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and
|
|
(not i_is_lutram))) then
|
|
i_force_reread_a <= '1';
|
|
elsif (rising_edge(i_address_aclr_a) and
|
|
(outdata_reg_a /= "CLOCK0") and
|
|
(outdata_reg_a /= "CLOCK1") and
|
|
(((HAS_STRATIXV_STYLE_RAM) or (IS_BASE_STRATIXIII)) and
|
|
(not i_is_lutram))) then
|
|
i_q_tmp_a <= (others => 'X');
|
|
i_force_reread_a1 <= '1';
|
|
i_force_reread_a1_flag := '1';
|
|
elsif ((i_force_reread_signal_a'event) or (i_force_reread_a1_flag = '0' and i_force_reread_a = '0')) then
|
|
if(i_force_reread_a = '0' or (not HAS_STRATIXV_STYLE_RAM)) then
|
|
i_q_tmp_a <= i_q_tmp2_a;
|
|
end if;
|
|
i_force_reread_a1 <= '0';
|
|
i_force_reread_a <= '0';
|
|
i_force_reread_a1_flag := '0';
|
|
elsif (i_force_reread_a = '1')then
|
|
i_q_tmp_a <= (others => '0');
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-- Port A outdata output registered
|
|
process (clock0, clock1, i_outdata_aclr_a, i_address_aclr_a, i_rden_reg_a)
|
|
variable i_address_aclr_a_flag : std_logic := '0';
|
|
begin
|
|
if ((i_address_aclr_a'event) and (i_address_aclr_a = '1') and
|
|
(i_rden_reg_a = '1')) then
|
|
i_address_aclr_a_flag := '1';
|
|
end if;
|
|
if (i_outdata_aclr_a = '1') then
|
|
i_q_reg_a <= (others => '0');
|
|
i_address_aclr_a_flag := '0';
|
|
elsif (((outdata_reg_a = "CLOCK0") and (rising_edge(clock0))) or
|
|
((outdata_reg_a = "CLOCK1") and (rising_edge(clock1)))) then
|
|
if i_outdata_clken_a = '1' then
|
|
-- clear for 1 clock cycle
|
|
if ((i_address_aclr_a_flag = '1') and
|
|
((HAS_STRATIXV_STYLE_RAM) or (IS_BASE_STRATIXIII)) and
|
|
(outdata_reg_a = "CLOCK0") and (not i_is_lutram)) then
|
|
i_q_reg_a <= (others => 'X');
|
|
else
|
|
i_q_reg_a <= i_q_tmp_a;
|
|
end if;
|
|
if (i_core_clocken_a = '1') then
|
|
i_address_aclr_a_flag := '0';
|
|
end if;
|
|
elsif (i_core_clocken_a = '1') then
|
|
i_address_aclr_a_flag := '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
-- Port A : assigning the correct output values for q_a
|
|
|
|
IFG52: if (((outdata_reg_a = "CLOCK0") or (outdata_reg_a = "CLOCK1")) and
|
|
(operation_mode /= "DUAL_PORT")) generate
|
|
q_a <= i_q_reg_a;
|
|
end generate IFG52;
|
|
|
|
IFG53: if (((outdata_reg_a /= "CLOCK0") and (outdata_reg_a /= "CLOCK1")) and
|
|
(operation_mode /= "DUAL_PORT")) generate
|
|
q_a <= i_q_tmp_a;
|
|
end generate IFG53;
|
|
|
|
IFG54: if (operation_mode = "DUAL_PORT") generate
|
|
q_a <= (others => '0');
|
|
end generate IFG54;
|
|
|
|
|
|
-- Port B : assigning the correct output values for i_q_tmp_b (non-registered output)
|
|
process (i_q_tmp2_b, good_to_go_b, i_rden_reg_b, i_wren_reg_b, i_data_reg_b, i_address_aclr_b,
|
|
i_byteena_mask_reg_b_out, default_val, i_address_reg_b, i_core_clocken_b,
|
|
i_original_data_b, i_outdata_aclr_b, i_force_reread_signal_b)
|
|
variable i_force_reread_b1_flag : std_logic := '0';
|
|
variable m_address_a : integer := 0;
|
|
variable m_address_b : integer := 0;
|
|
begin
|
|
if ((operation_mode = "DUAL_PORT") or (operation_mode = "BIDIR_DUAL_PORT")) then
|
|
if (not good_to_go_b = '1') then
|
|
if (i_is_lutram) then
|
|
i_q_tmp_b <= i_q_tmp2_b;
|
|
else
|
|
i_q_tmp_b <= (others => default_val);
|
|
end if;
|
|
else
|
|
|
|
if (i_q_tmp2_b'event or good_to_go_b'event or i_rden_reg_b'event or i_wren_reg_b'event or
|
|
i_data_reg_b'event or i_byteena_mask_reg_b_out'event or i_address_reg_b'event or
|
|
i_original_data_b'event or i_force_reread_signal_b'event) then
|
|
if (((i_rden_reg_b = '1') and (i_force_reread_b1_flag = '0')) or (i_is_lutram)) then
|
|
if ((conv_integer(unsigned(i_address_reg_b)) >= i_numwords_b)) then
|
|
if ((i_wren_reg_b = '1') and (i_core_clocken_b = '1')) then
|
|
i_q_tmp_b <= i_q_tmp2_b;
|
|
else
|
|
i_q_tmp_b <= (others => 'X');
|
|
end if;
|
|
assert false
|
|
report "Address pointed at port B is out of bound! "
|
|
severity warning;
|
|
else
|
|
i_q_tmp_b <= i_q_tmp2_b;
|
|
end if;
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if ((i_outdata_aclr_b = '1') and
|
|
(outdata_reg_b /= "CLOCK0") and
|
|
(outdata_reg_b /= "CLOCK1") and
|
|
(((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and
|
|
(not i_is_lutram))) then
|
|
i_q_tmp_b <= (others => '0');
|
|
elsif (falling_edge(i_outdata_aclr_b)and
|
|
(outdata_reg_b /= "CLOCK0") and
|
|
(outdata_reg_b /= "CLOCK1") and
|
|
(((HAS_STRATIXV_STYLE_RAM) or (HAS_STRATIXIII_STYLE_RAM)) and
|
|
(not i_is_lutram))) then
|
|
i_force_reread_b <= '1';
|
|
elsif (rising_edge(i_address_aclr_b) and
|
|
(outdata_reg_b /= "CLOCK0") and
|
|
(outdata_reg_b /= "CLOCK1") and
|
|
((HAS_STRATIXV_STYLE_RAM) or (IS_BASE_STRATIXIII)) and
|
|
(not i_is_lutram)) then
|
|
if (i_rden_reg_b = '1') then
|
|
i_q_tmp_b <= (others => 'X');
|
|
end if;
|
|
i_force_reread_b1 <= '1';
|
|
i_force_reread_b1_flag := '1';
|
|
elsif (i_force_reread_signal_b'event) then
|
|
if(i_force_reread_b = '0' or (not HAS_STRATIXV_STYLE_RAM)) then
|
|
i_q_tmp_b <= i_q_tmp2_b;
|
|
end if;
|
|
i_force_reread_b <= '0';
|
|
i_force_reread_b1 <= '0';
|
|
i_force_reread_b1_flag := '0';
|
|
elsif(i_force_reread_b = '1') then
|
|
i_q_tmp_b <= (others => '0');
|
|
end if;
|
|
|
|
|
|
|
|
if ((i_is_lutram) and (is_write_positive_edge) and (cread_during_write_mode_mixed_ports = "OLD_DATA")) then
|
|
m_address_a := conv_integer(unsigned(i_address_reg_a));
|
|
m_address_b := conv_integer(unsigned(i_address_reg_b));
|
|
if((width_a = width_b) and (m_address_a = m_address_b) and (i_wren_reg_a = '1') and (i_rden_reg_b = '1')) then
|
|
i_q_tmp_b <= i_original_data_a;
|
|
else
|
|
i_q_tmp_b <= i_q_tmp2_b;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
-- Port B outdata output registered
|
|
process (clock0, clock1, i_outdata_aclr_b, i_address_aclr_b, i_rden_reg_b)
|
|
variable i_address_aclr_b_flag : std_logic := '0';
|
|
variable m_address_a : integer := 0;
|
|
variable m_address_b : integer := 0;
|
|
begin
|
|
if ((i_address_aclr_b'event) and (i_address_aclr_b = '1') and
|
|
(i_rden_reg_b = '1')) then
|
|
i_address_aclr_b_flag := '1';
|
|
end if;
|
|
if (i_outdata_aclr_b = '1') then
|
|
i_q_reg_b <= (others => '0');
|
|
i_address_aclr_b_flag := '0';
|
|
elsif (((outdata_reg_b = "CLOCK0") and (rising_edge(clock0))) or
|
|
((outdata_reg_b = "CLOCK1") and (rising_edge(clock1)))) then
|
|
if (i_outdata_clken_b = '1') then
|
|
if ((i_is_lutram) and (cread_during_write_mode_mixed_ports = "OLD_DATA") and
|
|
(outdata_reg_b = "CLOCK0")) then
|
|
i_q_reg_b <= i_q_output_latch;
|
|
else
|
|
if ((i_address_aclr_b_flag = '1') and
|
|
((HAS_STRATIXV_STYLE_RAM) or (IS_BASE_STRATIXIII)) and
|
|
(outdata_reg_b = "CLOCK0") and (not i_is_lutram)) then
|
|
i_q_reg_b <= (others => 'X');
|
|
else
|
|
i_q_reg_b <= i_q_tmp_b;
|
|
end if;
|
|
if (i_core_clocken_b = '1') then
|
|
i_address_aclr_b_flag := '0';
|
|
end if;
|
|
end if;
|
|
elsif (i_core_clocken_b = '1') then
|
|
i_address_aclr_b_flag := '0';
|
|
end if;
|
|
end if;
|
|
|
|
if (((outdata_reg_b = "CLOCK0") and (falling_edge(clock0))) or
|
|
((outdata_reg_b = "CLOCK1") and (falling_edge(clock1)))) then
|
|
if (i_core_clocken_a = '1') then
|
|
m_address_a := conv_integer(unsigned(i_address_reg_a));
|
|
m_address_b := conv_integer(unsigned(i_address_reg_b));
|
|
if((width_a = width_b) and (m_address_a = m_address_b) and (i_wren_reg_a = '1') and (i_rden_reg_b = '1')) then
|
|
i_q_output_latch <= i_original_data_a;
|
|
else
|
|
i_q_output_latch <= i_q_tmp_b;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-- ECC Pipeline Register
|
|
process (clock0, clock1, i_outdata_aclr_b)
|
|
begin
|
|
if (i_outdata_aclr_b = '1') then
|
|
i_q_ecc_reg_b <= (others => '0');
|
|
elsif (((outdata_reg_b = "CLOCK0") and (rising_edge(clock0))) or
|
|
((outdata_reg_b = "CLOCK1") and (rising_edge(clock1)))) then
|
|
if (i_outdata_clken_b = '1') then
|
|
i_q_ecc_reg_b <= i_q_reg_b;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-- Port B : assigning the correct output values for q_b
|
|
|
|
IFG55: if ((ecc_pipeline_stage_enabled = "FALSE") and
|
|
((outdata_reg_b = "CLOCK0") or (outdata_reg_b = "CLOCK1")) and
|
|
(operation_mode /= "SINGLE_PORT") and (operation_mode /= "ROM")) generate
|
|
q_b <= i_q_reg_b;
|
|
end generate IFG55;
|
|
|
|
IFG56: if ((ecc_pipeline_stage_enabled = "FALSE") and
|
|
((outdata_reg_b /= "CLOCK0") and (outdata_reg_b /= "CLOCK1")) and
|
|
(operation_mode /= "SINGLE_PORT") and (operation_mode /= "ROM")) generate
|
|
q_b <= i_q_tmp_b;
|
|
end generate IFG56;
|
|
|
|
IFG57: if ((operation_mode = "SINGLE_PORT") or (operation_mode = "ROM")) generate
|
|
q_b <= (others => '0');
|
|
end generate IFG57;
|
|
|
|
IFG58: if ((ecc_pipeline_stage_enabled = "TRUE") and
|
|
((outdata_reg_b = "CLOCK0") or (outdata_reg_b = "CLOCK1")) and
|
|
(operation_mode /= "SINGLE_PORT") and (operation_mode /= "ROM")) generate
|
|
q_b <= i_q_ecc_reg_b;
|
|
end generate IFG58;
|
|
|
|
IFG59: if ((ecc_pipeline_stage_enabled = "TRUE") and
|
|
((outdata_reg_b /= "CLOCK0") and (outdata_reg_b /= "CLOCK1")) and
|
|
(operation_mode /= "SINGLE_PORT") and (operation_mode /= "ROM")) generate
|
|
q_b <= i_q_ecc_tmp_b; --i_q_ecc_tmp_b has 'x' output
|
|
end generate IFG59;
|
|
-- ECC status
|
|
|
|
eccstatus <= (others => '0');
|
|
|
|
end translated;
|
|
|
|
-- END OF ARCHITECTURE ALTSYNCRAM
|
|
|
|
-------------------------------------------------------------------------------+
|
|
-- Module Name : alt3pram
|
|
--
|
|
-- Description : Triple-Port RAM megafunction. This megafunction implements
|
|
-- RAM with 1 write port and 2 read ports.
|
|
--
|
|
-- Limitation : This megafunction is provided only for backward
|
|
-- compatibility in Stratix� designs; instead, Altera�
|
|
-- recommends using the altsyncram megafunction
|
|
--
|
|
-- In MAX 3000, and MAX 7000 devices,
|
|
-- or if the USE_EAB paramter is set to "OFF", uses one
|
|
-- logic cell (LCs) per memory bit.
|
|
--
|
|
--
|
|
-- Results expected : The alt3pram function represents asynchronous memory
|
|
-- or memory with synchronous inputs and/or outputs.
|
|
-- (note: ^ below indicates posedge)
|
|
--
|
|
-- [ Synchronous Write to Memory (all inputs registered) ]
|
|
-- inclock inclocken wren Function
|
|
-- X L L No change.
|
|
-- not ^ H H No change.
|
|
-- ^ L X No change.
|
|
-- ^ H H The memory location
|
|
-- pointed to by wraddress[]
|
|
-- is loaded with data[].
|
|
--
|
|
-- [ Synchronous Read from Memory ]
|
|
-- inclock inclocken rden_a/rden_b Function
|
|
-- X L L No change.
|
|
-- not ^ H H No change.
|
|
-- ^ L X No change.
|
|
-- ^ H H The q_a[]/q_b[]port
|
|
-- outputs the contents of
|
|
-- the memory location.
|
|
--
|
|
-- [ Asynchronous Memory Operations ]
|
|
-- wren Function
|
|
-- L No change.
|
|
-- H The memory location pointed to by wraddress[] is
|
|
-- loaded with data[] and controlled by wren.
|
|
-- The output q_a[] is asynchronous and reflects
|
|
-- the memory location pointed to by rdaddress_a[].
|
|
--
|
|
-------------------------------------------------------------------------------+
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
use std.textio.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
use work.ALTERA_COMMON_CONVERSION.all;
|
|
use work.altsyncram;
|
|
use work.ALTERA_MF_HINT_EVALUATION.all;
|
|
|
|
|
|
---------------------
|
|
-- ENTITY DECLARATION
|
|
---------------------
|
|
|
|
entity alt3pram is
|
|
generic
|
|
( width : natural; -- data[], qa[] and qb[]
|
|
widthad : natural; -- rdaddress_a,rdaddress_b,wraddress
|
|
numwords : natural := 0; -- words stored in memory
|
|
lpm_file : string := "UNUSED"; -- name of hex file
|
|
lpm_hint : string := "USE_EAB=ON"; -- non-LPM parameters (Altera)
|
|
indata_reg : string := "UNREGISTERED";-- clock used by data[] port
|
|
indata_aclr : string := "ON"; -- aclr affects data[]?
|
|
write_reg : string := "UNREGISTERED";-- clock used by wraddress & wren
|
|
write_aclr : string := "ON"; -- aclr affects wraddress?
|
|
rdaddress_reg_a : string := "UNREGISTERED";-- clock used by readdress_a
|
|
rdaddress_aclr_a : string := "ON"; -- aclr affects rdaddress_a?
|
|
rdaddress_reg_b : string := "UNREGISTERED";-- clock used by readdress_b
|
|
rdaddress_aclr_b : string := "ON"; -- aclr affects rdaddress_b?
|
|
rdcontrol_reg_a : string := "UNREGISTERED";-- clock used by rden_a
|
|
rdcontrol_aclr_a : string := "ON"; -- aclr affects rden_a?
|
|
rdcontrol_reg_b : string := "UNREGISTERED";-- clock used by rden_b
|
|
rdcontrol_aclr_b : string := "ON"; -- aclr affects rden_b?
|
|
outdata_reg_a : string := "UNREGISTERED";-- clock used by qa[]
|
|
outdata_aclr_a : string := "ON"; -- aclr affects qa[]?
|
|
outdata_reg_b : string := "UNREGISTERED";-- clock used by qb[]
|
|
outdata_aclr_b : string := "ON"; -- aclr affects qb[]?
|
|
intended_device_family : string := "Stratix";
|
|
ram_block_type : string := "AUTO"; -- ram block type to be used
|
|
maximum_depth : integer := 0; -- maximum segmented value of the RAM
|
|
lpm_type : string := "alt3pram"
|
|
);
|
|
|
|
port
|
|
( wren : in std_logic := '0';
|
|
data : in std_logic_vector(width-1 downto 0);
|
|
wraddress : in std_logic_vector(widthad-1 downto 0);
|
|
inclock : in std_logic := '0';
|
|
inclocken : in std_logic := '1';
|
|
rden_a : in std_logic := '1';
|
|
rden_b : in std_logic := '1';
|
|
rdaddress_a : in std_logic_vector(widthad-1 downto 0);
|
|
rdaddress_b : in std_logic_vector(widthad-1 downto 0);
|
|
outclock : in std_logic := '0';
|
|
outclocken : in std_logic := '1';
|
|
aclr : in std_logic := '0';
|
|
qa : out std_logic_vector(width-1 downto 0);
|
|
qb : out std_logic_vector(width-1 downto 0)
|
|
);
|
|
|
|
end alt3pram; -- Entity: alt3pram
|
|
|
|
---------------------------
|
|
-- ARCHITECTURE DECLARATION
|
|
---------------------------
|
|
architecture behavior of alt3pram is
|
|
|
|
------------------------
|
|
-- FUNCTION DECLARATION
|
|
------------------------
|
|
-- The following functions take in parameters values used in alt3pram and convert
|
|
-- to a corresponding(or suitable) parameters value that used in altsyncram.
|
|
function get_num_words (i_numwords : natural;
|
|
i_widthad : natural) return integer is
|
|
begin
|
|
if (i_numwords = 0) then
|
|
return 2**i_widthad;
|
|
else
|
|
return i_numwords;
|
|
end if;
|
|
end;
|
|
|
|
function get_read_during_write_mode_mixed_ports(i_ram_block_type : string) return string is
|
|
begin
|
|
if (i_ram_block_type = "AUTO") then
|
|
return "OLD_DATA";
|
|
else
|
|
return "DONT_CARE";
|
|
end if;
|
|
end;
|
|
|
|
function get_write_aclr_a_clk(i_write_aclr : string) return string is
|
|
begin
|
|
if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_write_aclr = "ON") then
|
|
return "CLEAR0";
|
|
else
|
|
return "NONE";
|
|
end if;
|
|
end;
|
|
|
|
function get_indata_aclr_a_clk(i_indata_aclr : string) return string is
|
|
begin
|
|
if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_indata_aclr = "ON") then
|
|
return "CLEAR0";
|
|
else
|
|
return "NONE";
|
|
end if;
|
|
end;
|
|
|
|
function get_rdcontrol_reg_a_clk(i_rdcontrol_reg_a : string) return string is
|
|
begin
|
|
if (i_rdcontrol_reg_a = "INCLOCK") then
|
|
return "CLOCK0";
|
|
elsif (i_rdcontrol_reg_a = "OUTCLOCK") then
|
|
return "CLOCK1";
|
|
else
|
|
return "UNUSED";
|
|
end if;
|
|
end;
|
|
|
|
function get_rdaddress_reg_a_clk(i_rdaddress_reg_a : string) return string is
|
|
begin
|
|
if (i_rdaddress_reg_a = "INCLOCK") then
|
|
return "CLOCK0";
|
|
elsif (i_rdaddress_reg_a = "OUTCLOCK") then
|
|
return "CLOCK1";
|
|
else
|
|
return "UNUSED";
|
|
end if;
|
|
end;
|
|
|
|
function get_outdata_reg_a_clk(i_outdata_reg_a : string) return string is
|
|
begin
|
|
if (i_outdata_reg_a = "INCLOCK") then
|
|
return "CLOCK0";
|
|
elsif (i_outdata_reg_a = "OUTCLOCK") then
|
|
return "CLOCK1";
|
|
else
|
|
return "UNREGISTERED";
|
|
end if;
|
|
end;
|
|
|
|
function get_outdata_aclr_a_clk(i_outdata_aclr_a : string) return string is
|
|
begin
|
|
if (i_outdata_aclr_a = "ON") then
|
|
return "CLEAR0";
|
|
else
|
|
return "NONE";
|
|
end if;
|
|
end;
|
|
|
|
function get_rdcontrol_aclr_a_clk(i_rdcontrol_aclr_a : string) return string is
|
|
begin
|
|
if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_rdcontrol_aclr_a = "ON") then
|
|
return "CLEAR0";
|
|
else
|
|
return "NONE";
|
|
end if;
|
|
end;
|
|
|
|
function get_rdaddress_aclr_a_clk(i_rdaddress_aclr_a : string) return string is
|
|
begin
|
|
if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_rdaddress_aclr_a = "ON") then
|
|
return "CLEAR0";
|
|
else
|
|
return "NONE";
|
|
end if;
|
|
end;
|
|
|
|
function get_rdcontrol_reg_b_clk(i_rdcontrol_reg_b : string) return string is
|
|
begin
|
|
if (i_rdcontrol_reg_b = "INCLOCK") then
|
|
return "CLOCK0";
|
|
elsif (i_rdcontrol_reg_b = "OUTCLOCK") then
|
|
return "CLOCK1";
|
|
else
|
|
return "UNUSED";
|
|
end if;
|
|
end;
|
|
|
|
function get_rdaddress_reg_b_clk(i_rdaddress_reg_b : string) return string is
|
|
begin
|
|
if (i_rdaddress_reg_b = "INCLOCK") then
|
|
return "CLOCK0";
|
|
elsif (i_rdaddress_reg_b = "OUTCLOCK") then
|
|
return "CLOCK1";
|
|
else
|
|
return "UNUSED";
|
|
end if;
|
|
end;
|
|
|
|
function get_outdata_reg_b_clk(i_outdata_reg_b : string) return string is
|
|
begin
|
|
if (i_outdata_reg_b = "INCLOCK") then
|
|
return "CLOCK0";
|
|
elsif (i_outdata_reg_b = "OUTCLOCK") then
|
|
return "CLOCK1";
|
|
else
|
|
return "UNREGISTERED";
|
|
end if;
|
|
end;
|
|
|
|
function get_outdata_aclr_b_clk(i_outdata_aclr_b : string) return string is
|
|
begin
|
|
if (i_outdata_aclr_b = "ON") then
|
|
return "CLEAR0";
|
|
else
|
|
return "NONE";
|
|
end if;
|
|
end;
|
|
|
|
function get_rdcontrol_aclr_b_clk(i_rdcontrol_aclr_b : string) return string is
|
|
begin
|
|
if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_rdcontrol_aclr_b = "ON") then
|
|
return "CLEAR0";
|
|
else
|
|
return "NONE";
|
|
end if;
|
|
end;
|
|
|
|
function get_rdaddress_aclr_b_clk(i_rdaddress_aclr_b : string) return string is
|
|
begin
|
|
if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_rdaddress_aclr_b = "ON") then
|
|
return "CLEAR0";
|
|
else
|
|
return "NONE";
|
|
end if;
|
|
end;
|
|
|
|
-------------------
|
|
-- TYPE DECLARATION
|
|
-------------------
|
|
type alt_memory is array((2**WIDTHAD)-1 downto 0) of std_logic_vector(WIDTH-1 downto 0);
|
|
|
|
-----------------------
|
|
-- CONSTANT DECLARATION
|
|
-----------------------
|
|
constant IS_STRATIX : boolean := FEATURE_FAMILY_STRATIX(intended_device_family);
|
|
constant NUM_WORDS : integer := get_num_words(numwords, widthad);
|
|
constant READ_DURING_WRITE_MODE : string := get_read_during_write_mode_mixed_ports(ram_block_type);
|
|
constant WRITE_ACLR_A_CLK : string := get_write_aclr_a_clk(write_aclr);
|
|
constant INDATA_ACLR_A_CLK : string := get_indata_aclr_a_clk(indata_aclr);
|
|
constant RDCONTROL_REG_A_CLK : string := get_rdcontrol_reg_a_clk(rdcontrol_reg_a);
|
|
constant RDADDRESS_REG_A_CLK : string := get_rdaddress_reg_a_clk(rdaddress_reg_a);
|
|
constant OUTDATA_REG_A_CLK : string := get_outdata_reg_a_clk(outdata_reg_a);
|
|
constant OUTDATA_ACLR_A_CLK : string := get_outdata_aclr_a_clk(outdata_aclr_a);
|
|
constant RDCONTROL_ACLR_A_CLK : string := get_rdcontrol_aclr_a_clk(rdcontrol_aclr_a);
|
|
constant RDADDRESS_ACLR_A_CLK : string := get_rdaddress_aclr_a_clk(rdaddress_aclr_a);
|
|
constant RDCONTROL_REG_B_CLK : string := get_rdcontrol_reg_b_clk(rdcontrol_reg_b);
|
|
constant RDADDRESS_REG_B_CLK : string := get_rdaddress_reg_b_clk(rdaddress_reg_b);
|
|
constant OUTDATA_REG_B_CLK : string := get_outdata_reg_b_clk(outdata_reg_b);
|
|
constant OUTDATA_ACLR_B_CLK : string := get_outdata_aclr_b_clk(outdata_aclr_b);
|
|
constant RDCONTROL_ACLR_B_CLK : string := get_rdcontrol_aclr_b_clk(rdcontrol_aclr_b);
|
|
constant RDADDRESS_ACLR_B_CLK : string := get_rdaddress_aclr_b_clk(rdaddress_aclr_b);
|
|
constant LPM_HINT_USE_EAB : string := GET_PARAMETER_VALUE(lpm_hint, "USE_EAB");
|
|
|
|
|
|
---------------------
|
|
-- SIGNAL DECLARATION
|
|
---------------------
|
|
signal idata_tmp : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
signal idata_reg : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
|
|
signal idata_hi : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
signal idata_lo : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
|
|
signal iqa_tmp : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
signal iqa_reg : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
|
|
signal iqb_tmp : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
signal iqb_reg : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
|
|
|
|
signal iwren_tmp : std_logic := '0';
|
|
signal iwren_reg : std_logic := '0';
|
|
|
|
signal iwren_hi : std_logic := '0';
|
|
signal iwren_lo : std_logic := '0';
|
|
|
|
signal irdaddress_tmp_a : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal irdaddress_reg_a : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
|
|
signal irdaddress_tmp_b : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal irdaddress_reg_b : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
|
|
signal iwraddress_tmp : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal iwraddress_reg : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
|
|
signal iwraddress_hi : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
signal iwraddress_lo : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
|
|
|
|
signal irden_tmp_a : std_logic := '0';
|
|
signal irden_reg_a : std_logic := '0';
|
|
|
|
signal irden_tmp_b : std_logic := '0';
|
|
signal irden_reg_b : std_logic := '0';
|
|
|
|
signal unused_port0 : std_logic_vector(width-1 downto 0);
|
|
signal unused_port1 : std_logic_vector(width-1 downto 0);
|
|
|
|
signal iqa_non_stratix : std_logic_vector(width-1 downto 0);
|
|
signal iqb_non_stratix : std_logic_vector(width-1 downto 0);
|
|
|
|
signal iqa_stratix : std_logic_vector(width-1 downto 0);
|
|
signal iqb_stratix : std_logic_vector(width-1 downto 0);
|
|
|
|
signal iinclock_non_stratix : std_logic; -- inclock signal for non-Stratix families
|
|
signal ioutclock_non_stratix : std_logic; -- outclock signal for non-Stratix families
|
|
|
|
signal write_at_low_clock : boolean := false;
|
|
signal rden_low_output_0 : boolean := false;
|
|
|
|
--------------------------
|
|
-- COMPONENTS DECLARATION
|
|
--------------------------
|
|
component altsyncram
|
|
GENERIC (
|
|
operation_mode : string := "SINGLE_PORT";
|
|
width_a : natural := 8;
|
|
widthad_a : natural := 2;
|
|
numwords_a : natural := 4;
|
|
address_aclr_a : string := "NONE";
|
|
indata_aclr_a : string := "CLEAR0";
|
|
wrcontrol_aclr_a : string := "NONE";
|
|
width_b : natural := 8;
|
|
widthad_b : natural := 4;
|
|
numwords_b : natural := 4;
|
|
rdcontrol_reg_b : string := "CLOCK1";
|
|
address_reg_b : string := "CLOCK1";
|
|
outdata_reg_b : string := "UNREGISTERED";
|
|
outdata_aclr_b : string := "NONE";
|
|
rdcontrol_aclr_b : string := "NONE";
|
|
address_aclr_b : string := "NONE";
|
|
read_during_write_mode_mixed_ports: string := READ_DURING_WRITE_MODE;
|
|
ram_block_type : string := "AUTO";
|
|
init_file : string := "UNUSED";
|
|
init_file_layout : string := "UNUSED";
|
|
maximum_depth : integer := 0;
|
|
intended_device_family : string := "Stratix" );
|
|
PORT (
|
|
wren_a : IN std_logic := '0';
|
|
rden_b : IN std_logic := '1';
|
|
data_a : IN std_logic_vector(width_a - 1 DOWNTO 0):= (others => '0');
|
|
address_a : IN std_logic_vector(widthad_a - 1 DOWNTO 0) := (others => '0');
|
|
address_b : IN std_logic_vector(widthad_b - 1 DOWNTO 0) := (others => '0');
|
|
clock0 : IN std_logic := '1';
|
|
clock1 : IN std_logic := '1';
|
|
clocken0 : IN std_logic := '1';
|
|
clocken1 : IN std_logic := '1';
|
|
aclr0 : IN std_logic := '0';
|
|
q_a : OUT std_logic_vector(width_a - 1 DOWNTO 0);
|
|
q_b : OUT std_logic_vector(width_b - 1 DOWNTO 0));
|
|
END component;
|
|
|
|
|
|
begin
|
|
|
|
--------------------------
|
|
-- COMPONENTS ASSIGNMENTS
|
|
--------------------------
|
|
-- The alt3pram for Stratix/Stratix II/ Stratix GX and Cyclone device families
|
|
-- are basically consists of 2 instances of altsyncram with write port of each
|
|
-- instance been tied together.
|
|
STRATIX_DUALPORT_RAM0:
|
|
if (IS_STRATIX = true) generate
|
|
U0: altsyncram
|
|
generic map
|
|
( operation_mode => "DUAL_PORT",
|
|
width_a => width,
|
|
widthad_a => widthad,
|
|
numwords_a => NUM_WORDS,
|
|
address_aclr_a => WRITE_ACLR_A_CLK,
|
|
indata_aclr_a => INDATA_ACLR_A_CLK,
|
|
wrcontrol_aclr_a => WRITE_ACLR_A_CLK,
|
|
width_b => width,
|
|
widthad_b => widthad,
|
|
numwords_b => NUM_WORDS,
|
|
rdcontrol_reg_b => RDCONTROL_REG_A_CLK,
|
|
address_reg_b => RDADDRESS_REG_A_CLK,
|
|
outdata_reg_b => OUTDATA_REG_A_CLK,
|
|
outdata_aclr_b => OUTDATA_ACLR_A_CLK,
|
|
rdcontrol_aclr_b => RDCONTROL_ACLR_A_CLK,
|
|
address_aclr_b => RDADDRESS_ACLR_A_CLK,
|
|
read_during_write_mode_mixed_ports => READ_DURING_WRITE_MODE,
|
|
ram_block_type => ram_block_type,
|
|
init_file => lpm_file,
|
|
init_file_layout => "PORT_B",
|
|
maximum_depth => maximum_depth,
|
|
intended_device_family => intended_device_family)
|
|
port map
|
|
( wren_a => wren,
|
|
rden_b => rden_a,
|
|
data_a => data,
|
|
address_a => wraddress,
|
|
address_b => rdaddress_a,
|
|
clock0 => inclock,
|
|
clock1 => outclock,
|
|
clocken0 => inclocken,
|
|
clocken1 => outclocken,
|
|
aclr0 => aclr,
|
|
q_a => unused_port0,
|
|
q_b => iqa_stratix);
|
|
end generate STRATIX_DUALPORT_RAM0;
|
|
|
|
STRATIX_DUALPORT_RAM1:
|
|
if (IS_STRATIX = true) generate
|
|
U1: altsyncram
|
|
generic map
|
|
( operation_mode => "DUAL_PORT",
|
|
width_a => width,
|
|
widthad_a => widthad,
|
|
numwords_a => NUM_WORDS,
|
|
address_aclr_a => WRITE_ACLR_A_CLK,
|
|
indata_aclr_a => INDATA_ACLR_A_CLK,
|
|
wrcontrol_aclr_a => WRITE_ACLR_A_CLK,
|
|
width_b => width,
|
|
widthad_b => widthad,
|
|
numwords_b => NUM_WORDS,
|
|
rdcontrol_reg_b => RDCONTROL_REG_B_CLK,
|
|
address_reg_b => RDADDRESS_REG_B_CLK,
|
|
outdata_reg_b => OUTDATA_REG_B_CLK,
|
|
outdata_aclr_b => OUTDATA_ACLR_B_CLK,
|
|
rdcontrol_aclr_b => RDCONTROL_ACLR_B_CLK,
|
|
address_aclr_b => RDADDRESS_ACLR_B_CLK,
|
|
read_during_write_mode_mixed_ports => READ_DURING_WRITE_MODE,
|
|
ram_block_type => ram_block_type,
|
|
init_file => lpm_file,
|
|
init_file_layout => "PORT_B",
|
|
maximum_depth => maximum_depth,
|
|
intended_device_family => intended_device_family)
|
|
port map
|
|
( wren_a => wren,
|
|
rden_b => rden_b,
|
|
data_a => data,
|
|
address_a => wraddress,
|
|
address_b => rdaddress_b,
|
|
clock0 => inclock,
|
|
clock1 => outclock,
|
|
clocken0 => inclocken,
|
|
clocken1 => outclocken,
|
|
aclr0 => aclr,
|
|
q_a => unused_port1,
|
|
q_b => iqb_stratix);
|
|
end generate STRATIX_DUALPORT_RAM1;
|
|
|
|
-- ******************
|
|
-- SIGNAL ASSIGNMENTS
|
|
-- ******************
|
|
qa <= iqa_stratix when (IS_STRATIX = true)
|
|
else iqa_non_stratix;
|
|
|
|
qb <= iqb_stratix when (IS_STRATIX = true)
|
|
else iqb_non_stratix;
|
|
|
|
iinclock_non_stratix <= inclock when (IS_STRATIX = false)
|
|
else '0';
|
|
|
|
ioutclock_non_stratix <= outclock when (IS_STRATIX = false)
|
|
else '0';
|
|
|
|
-- *************
|
|
-- PROCESS BLOCK
|
|
-- *************
|
|
|
|
-- The following process blocks are used to implement the alt3pram behavior for
|
|
-- device families other than Stratix/Stratix II/Stratix GX and Cyclone.
|
|
|
|
-- Initial Block
|
|
----------------
|
|
INITIAL: process (iinclock_non_stratix, ioutclock_non_stratix)
|
|
variable init : boolean := false;
|
|
begin
|
|
if (not init) then
|
|
if (LPM_HINT_USE_EAB = "ON") then
|
|
|
|
-- -------------------------------------------------------------------------
|
|
-- the following behaviour come in effect when RAM is implemented in EAB/ESB
|
|
|
|
-- This is the flag to indicate if the memory is constructed using EAB/ESB:
|
|
-- A write request requires both rising and falling edge of the clock
|
|
-- to complete. First the data will be clocked in (registered) at the
|
|
-- rising edge and will not be written into the ESB/EAB memory until
|
|
-- the falling edge appears on the the write clock.
|
|
-- No such restriction if the memory is constructed using LCs.
|
|
if (write_reg = "INCLOCK") then
|
|
write_at_low_clock <= true;
|
|
end if;
|
|
end if;
|
|
init := true;
|
|
end if;
|
|
end process INITIAL;
|
|
|
|
-------------------------
|
|
-- Syncronization Process
|
|
-------------------------
|
|
SYNC: process (data, idata_reg, rden_a, rden_b, irden_reg_a, irden_reg_b,
|
|
rdaddress_a, rdaddress_b, irdaddress_reg_a, irdaddress_reg_b,
|
|
wren, iwren_reg, wraddress, iwraddress_reg,
|
|
iqa_tmp, iqb_tmp, iqa_reg, iqb_reg, aclr)
|
|
begin
|
|
if ((rdaddress_reg_a = "INCLOCK") or (rdaddress_reg_a = "OUTCLOCK")) then
|
|
irdaddress_tmp_a <= irdaddress_reg_a;
|
|
else
|
|
irdaddress_tmp_a <= rdaddress_a;
|
|
end if;
|
|
|
|
if ((rdcontrol_reg_a = "INCLOCK") or (rdcontrol_reg_a = "OUTCLOCK")) then
|
|
irden_tmp_a <= irden_reg_a;
|
|
else
|
|
irden_tmp_a <= rden_a;
|
|
end if;
|
|
|
|
if ((rdaddress_reg_b = "INCLOCK") or (rdaddress_reg_b = "OUTCLOCK")) then
|
|
irdaddress_tmp_b <= irdaddress_reg_b;
|
|
else
|
|
irdaddress_tmp_b <= rdaddress_b;
|
|
end if;
|
|
|
|
if ((rdcontrol_reg_b = "INCLOCK") or (rdcontrol_reg_b = "OUTCLOCK")) then
|
|
irden_tmp_b <= irden_reg_b;
|
|
else
|
|
irden_tmp_b <= rden_b;
|
|
end if;
|
|
|
|
if (write_reg = "INCLOCK") then
|
|
iwraddress_tmp <= iwraddress_reg;
|
|
iwren_tmp <= iwren_reg;
|
|
else
|
|
iwraddress_tmp <= wraddress;
|
|
iwren_tmp <= wren;
|
|
end if;
|
|
|
|
if (indata_reg = "INCLOCK") then
|
|
idata_tmp <= idata_reg;
|
|
else
|
|
idata_tmp <= data;
|
|
end if;
|
|
|
|
if (outdata_reg_a = "OUTCLOCK") then
|
|
iqa_non_stratix <= iqa_reg;
|
|
else
|
|
iqa_non_stratix <= iqa_tmp;
|
|
end if;
|
|
|
|
if (outdata_reg_b = "OUTCLOCK") then
|
|
iqb_non_stratix <= iqb_reg;
|
|
else
|
|
iqb_non_stratix <= iqb_tmp;
|
|
end if;
|
|
|
|
if (aclr = '1') then
|
|
if(indata_aclr = "ON") then
|
|
idata_tmp <= (OTHERS => '0');
|
|
end if;
|
|
if(write_aclr = "ON") then
|
|
iwraddress_tmp <= (OTHERS => '0');
|
|
iwren_tmp <= '0';
|
|
end if;
|
|
if(rdaddress_aclr_a = "ON") then
|
|
irdaddress_tmp_a <= (OTHERS => '0');
|
|
end if;
|
|
if(rdcontrol_aclr_a = "ON") then
|
|
irden_tmp_a <= '0';
|
|
end if;
|
|
if(rdaddress_aclr_b = "ON") then
|
|
irdaddress_tmp_b <= (OTHERS => '0');
|
|
end if;
|
|
if(rdcontrol_aclr_b = "ON") then
|
|
irden_tmp_b <= '0';
|
|
end if;
|
|
if(outdata_aclr_a = "ON") then
|
|
iqa_non_stratix <= (OTHERS => '0');
|
|
end if;
|
|
if(outdata_aclr_b = "ON") then
|
|
iqb_non_stratix <= (OTHERS => '0');
|
|
end if;
|
|
end if;
|
|
end process SYNC;
|
|
|
|
-------------------------
|
|
-- Syncronization Process
|
|
-------------------------
|
|
SYNC2: process (idata_hi, idata_lo, iwraddress_hi, iwraddress_lo,
|
|
iwren_hi, iwren_lo, write_at_low_clock)
|
|
begin
|
|
if (write_at_low_clock) then
|
|
idata_reg <= idata_lo;
|
|
iwren_reg <= iwren_lo;
|
|
iwraddress_reg <= iwraddress_lo;
|
|
else
|
|
idata_reg <= idata_hi;
|
|
iwren_reg <= iwren_hi;
|
|
iwraddress_reg <= iwraddress_hi;
|
|
end if;
|
|
end process SYNC2;
|
|
|
|
-------------------------------------------------
|
|
-- Synchronous READ Operation (SHARED CLOCK MODE)
|
|
-------------------------------------------------
|
|
|
|
-- READ REGS PORT A
|
|
-------------------
|
|
IFG1: if (rdaddress_reg_a = "INCLOCK") generate
|
|
process (iinclock_non_stratix, aclr)
|
|
begin
|
|
if ((aclr = '1') and (rdaddress_aclr_a = "ON")) then
|
|
irdaddress_reg_a <= (OTHERS => '0');
|
|
elsif rising_edge(iinclock_non_stratix) then
|
|
if (inclocken = '1') then
|
|
irdaddress_reg_a <= rdaddress_a;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG1;
|
|
|
|
IFG2: if (rdcontrol_reg_a = "INCLOCK") generate
|
|
process (iinclock_non_stratix, aclr)
|
|
begin
|
|
if ((aclr = '1') and (rdcontrol_aclr_a = "ON")) then
|
|
irden_reg_a <= '0';
|
|
elsif rising_edge(iinclock_non_stratix) then
|
|
if (inclocken = '1') then
|
|
irden_reg_a <= rden_a;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG2;
|
|
|
|
IFG3: if (rdaddress_reg_a = "OUTCLOCK") generate
|
|
process (ioutclock_non_stratix, aclr)
|
|
begin
|
|
if ((aclr = '1') and (rdaddress_aclr_a = "ON")) then
|
|
irdaddress_reg_a <= (OTHERS => '0');
|
|
elsif rising_edge(ioutclock_non_stratix) then
|
|
if (outclocken = '1') then
|
|
irdaddress_reg_a <= rdaddress_a;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG3;
|
|
|
|
IFG4: if (rdcontrol_reg_a = "OUTCLOCK") generate
|
|
process (ioutclock_non_stratix, aclr)
|
|
begin
|
|
if ((aclr = '1') and (rdcontrol_aclr_a = "ON")) then
|
|
irden_reg_a <= '0';
|
|
elsif rising_edge(ioutclock_non_stratix) then
|
|
if (outclocken = '1') then
|
|
irden_reg_a <= rden_a;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG4;
|
|
|
|
IFG5: if (rdaddress_reg_b = "INCLOCK") generate
|
|
process (iinclock_non_stratix, aclr)
|
|
begin
|
|
if (aclr = '1' and rdaddress_aclr_b = "ON") then
|
|
irdaddress_reg_b <= (OTHERS => '0');
|
|
elsif rising_edge(iinclock_non_stratix) then
|
|
if (inclocken = '1') then
|
|
irdaddress_reg_b <= rdaddress_b;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG5;
|
|
|
|
IFG6: if (rdcontrol_reg_b = "INCLOCK") generate
|
|
process (iinclock_non_stratix, aclr)
|
|
begin
|
|
if (aclr = '1' and rdcontrol_aclr_b = "ON") then
|
|
irden_reg_b <= '0';
|
|
elsif rising_edge(iinclock_non_stratix) then
|
|
if (inclocken = '1') then
|
|
irden_reg_b <= rden_b;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG6;
|
|
|
|
IFG7 : if (rdaddress_reg_b = "OUTCLOCK") generate
|
|
process (ioutclock_non_stratix, aclr)
|
|
begin
|
|
if ((aclr = '1') and (rdaddress_aclr_b = "ON")) then
|
|
irdaddress_reg_b <= (OTHERS => '0');
|
|
elsif rising_edge(ioutclock_non_stratix) then
|
|
if (outclocken = '1') then
|
|
irdaddress_reg_b <= rdaddress_b;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG7;
|
|
|
|
IFG8: if (rdcontrol_reg_b = "OUTCLOCK") generate
|
|
process (ioutclock_non_stratix, aclr)
|
|
begin
|
|
if ((aclr = '1') and (rdcontrol_aclr_b = "ON")) then
|
|
irden_reg_b <= '0';
|
|
elsif rising_edge(ioutclock_non_stratix) then
|
|
if (outclocken = '1') then
|
|
irden_reg_b <= rden_b;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate IFG8;
|
|
|
|
-- At posedge of the write clock:
|
|
-- All input ports values (data, address and control) are
|
|
-- clocked in from physical ports to internal variables
|
|
-- Write Cycle: i*_hi
|
|
-- Read Cycle: i*_reg (Shared Clock Mode)
|
|
--
|
|
-- At negedge of the write clock:
|
|
-- Write Cycle: since internally data only completed written on memory
|
|
-- at the falling edge of write clock, the "write" related
|
|
-- data, address and controls need to be shift to another
|
|
-- varibles (i*_hi -> i*_lo) during falling edge.
|
|
PROC_INCLOCK_OUTCLOCK: process (iinclock_non_stratix, ioutclock_non_stratix, aclr)
|
|
begin
|
|
-- WRITE REGS --
|
|
if ((aclr = '1') and (indata_aclr = "ON")) then
|
|
idata_hi <= (OTHERS => '0');
|
|
idata_lo <= (OTHERS => '0');
|
|
elsif rising_edge(iinclock_non_stratix) then
|
|
if (inclocken = '1') then
|
|
idata_hi <= data;
|
|
end if;
|
|
elsif falling_edge(iinclock_non_stratix) then
|
|
idata_lo <= idata_hi;
|
|
end if;
|
|
|
|
if ((aclr = '1') and (write_aclr = "ON")) then
|
|
iwraddress_hi <= (OTHERS => '0');
|
|
iwraddress_lo <= (OTHERS => '0');
|
|
iwren_hi <= '0';
|
|
iwren_lo <= '0';
|
|
elsif rising_edge(iinclock_non_stratix) then
|
|
if (inclocken = '1') then
|
|
iwraddress_hi <= wraddress;
|
|
iwren_hi <= wren;
|
|
end if;
|
|
elsif falling_edge(iinclock_non_stratix) then
|
|
iwraddress_lo <= iwraddress_hi;
|
|
iwren_lo <= iwren_hi;
|
|
end if;
|
|
|
|
-- READ REGS PORT A--
|
|
if (aclr = '1' and outdata_aclr_a = "ON") then
|
|
iqa_reg <= (OTHERS => '0');
|
|
elsif rising_edge(ioutclock_non_stratix) then
|
|
if (outclocken = '1') then
|
|
iqa_reg <= iqa_tmp;
|
|
end if;
|
|
end if;
|
|
|
|
|
|
----------------------------------------------------
|
|
-- Synchronouse READ Operation (SEPERATE CLOCK MODE)
|
|
-- At posedge of read clock:
|
|
-- Read Cycle: This block is valid only if the operating mode is
|
|
-- in "Seperate Clock Mode". All read data, address
|
|
-- and control are clocked out from internal vars
|
|
-- (i*_reg) to output port.
|
|
----------------------------------------------------
|
|
|
|
-- READ REGS PORT B
|
|
-------------------
|
|
if ((aclr = '1') and (outdata_aclr_b = "ON")) then
|
|
iqb_reg <= (OTHERS => '0');
|
|
elsif rising_edge(ioutclock_non_stratix) then
|
|
if (outclocken = '1') then
|
|
iqb_reg <= iqb_tmp;
|
|
end if;
|
|
end if;
|
|
|
|
end process PROC_INCLOCK_OUTCLOCK;
|
|
|
|
-----------------------
|
|
-- MEMORY Process Block
|
|
-----------------------
|
|
MEMORY: process(idata_tmp, iwren_tmp, irden_tmp_a, irden_tmp_b, irdaddress_tmp_a,
|
|
irdaddress_tmp_b, iwraddress_tmp, rden_low_output_0)
|
|
variable mem_data : alt_memory;
|
|
variable mem_data_word : std_logic_vector(width-1 downto 0) := (OTHERS => '0');
|
|
variable mem_init : boolean := false;
|
|
variable i : integer := 0;
|
|
variable j : integer := 0;
|
|
variable k : integer := 0;
|
|
variable n : integer := 0;
|
|
variable m : integer := 0;
|
|
variable lineno : integer := 0;
|
|
variable buf : line;
|
|
variable booval : boolean := false;
|
|
FILE mem_data_file : TEXT;
|
|
variable char : string(1 downto 1) := " ";
|
|
variable base : string(2 downto 1) := " ";
|
|
variable byte : string(2 downto 1) := " ";
|
|
variable rec_type : string(2 downto 1) := " ";
|
|
variable datain : string(2 downto 1) := " ";
|
|
variable addr : string(2 downto 1) := " ";
|
|
variable checksum : string(2 downto 1) := " ";
|
|
variable startadd : string(4 downto 1) := " ";
|
|
variable ibase : integer := 0;
|
|
variable ibyte : integer := 0;
|
|
variable istartadd : integer := 0;
|
|
variable check_sum_vec : std_logic_vector(7 downto 0) := (OTHERS => '0');
|
|
variable check_sum_vec_tmp : std_logic_vector(7 downto 0) := (OTHERS => '0');
|
|
variable m_string : string(1 to 15);
|
|
variable m_data_radix : string(1 to 3);
|
|
variable m_address_radix : string(1 to 3);
|
|
variable m_width : integer;
|
|
variable m_depth : integer;
|
|
variable m_start_address_int : integer := 0;
|
|
variable m_end_address_int : integer := 0;
|
|
variable m_address_int : integer := 0;
|
|
variable m_data_int : std_logic_vector(width+4 downto 0) := (OTHERS => '0');
|
|
variable found_keyword_content : boolean := false;
|
|
variable get_memory_content : boolean := false;
|
|
variable get_start_Address : boolean := false;
|
|
variable get_end_Address : boolean := false;
|
|
|
|
begin
|
|
-- INITIALIZE --
|
|
if NOT(mem_init) then
|
|
|
|
--INITIALIZE TO X, IF WRITE_REG IS "UNREGISTERED"
|
|
if (write_reg = "UNREGISTERED") then
|
|
|
|
for i in mem_data'LOW to mem_data'HIGH loop
|
|
mem_data(i) := (OTHERS => 'X');
|
|
|
|
end loop;
|
|
|
|
|
|
else
|
|
|
|
-- INITIALIZE TO 0 --
|
|
for i in mem_data'LOW to mem_data'HIGH loop
|
|
mem_data(i) := (OTHERS => '0');
|
|
|
|
end loop;
|
|
end if;
|
|
|
|
|
|
if (lpm_file /= "UNUSED") then
|
|
FILE_OPEN(mem_data_file, lpm_file, READ_MODE);
|
|
if (ALPHA_TOLOWER(lpm_file(lpm_file'length -3 to lpm_file'length)) = ".hex") then
|
|
-- ************************************************
|
|
-- Read in RAM intialization file (hex)
|
|
-- ************************************************
|
|
WHILE NOT ENDFILE(mem_data_file) loop
|
|
booval := true;
|
|
READLINE(mem_data_file, buf);
|
|
lineno := lineno + 1;
|
|
check_sum_vec := (OTHERS => '0');
|
|
if (buf(buf'LOW) = ':') then
|
|
i := 1;
|
|
shrink_line(buf, i);
|
|
READ(L=>buf, VALUE=>byte, good=>booval);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
ibyte := HEX_STR_TO_INT(byte);
|
|
check_sum_vec := unsigned(check_sum_vec) +
|
|
unsigned(CONV_STD_LOGIC_VECTOR(ibyte, 8));
|
|
READ(L=>buf, VALUE=>startadd, good=>booval);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
istartadd := HEX_STR_TO_INT(startadd);
|
|
addr(2) := startadd(4);
|
|
addr(1) := startadd(3);
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(addr), 8));
|
|
addr(2) := startadd(2);
|
|
addr(1) := startadd(1);
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(addr), 8));
|
|
READ(L=>buf, VALUE=>rec_type, good=>booval);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(rec_type), 8));
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
case rec_type is
|
|
when "00"=> -- Data record
|
|
i := 0;
|
|
k := (WIDTH + 7) / 8; -- # of bytes per entry
|
|
while (i < ibyte) loop
|
|
mem_data_word := (others => '0');
|
|
|
|
j := 1;
|
|
while ( (j <= k) and (i < ibyte) ) loop
|
|
-- read in data a byte (2 hex chars) at a time.
|
|
READ(L=>buf, VALUE=>datain,good=>booval);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), 8));
|
|
if (WIDTH > 8) then
|
|
mem_data_word := mem_data_word(WIDTH - 9 downto 0) & CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), 8);
|
|
else
|
|
mem_data_word := CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), WIDTH);
|
|
end if;
|
|
j := j + 1;
|
|
i := i + 1;
|
|
end loop;
|
|
|
|
if ((ibase + istartadd) <= (2 ** widthad - 1)) then
|
|
mem_data(ibase + istartadd) := mem_data_word;
|
|
else
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]: Unable to initialized memory with this data record since the specified address is out of valid address range!"
|
|
SEVERITY WARNING;
|
|
end if;
|
|
istartadd := istartadd + 1;
|
|
end loop;
|
|
when "01"=>
|
|
exit;
|
|
when "02"=>
|
|
ibase := 0;
|
|
if (ibyte /= 2) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format for record type 02! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (ibyte-1) loop
|
|
READ(L=>buf, VALUE=>base,good=>booval);
|
|
ibase := (ibase * 256) + HEX_STR_TO_INT(base);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
|
|
end loop;
|
|
ibase := ibase * 16;
|
|
when "03"=>
|
|
if (ibyte /= 4) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format for record type 03! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (ibyte-1) loop
|
|
READ(L=>buf, VALUE=>base,good=>booval);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
|
|
end loop;
|
|
when "04"=>
|
|
ibase := 0;
|
|
if (ibyte /= 2) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format for record type 04! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (ibyte-1) loop
|
|
READ(L=>buf, VALUE=>base,good=>booval);
|
|
ibase := (ibase * 256) + HEX_STR_TO_INT(base);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
|
|
end loop;
|
|
ibase := ibase * 65536;
|
|
when "05"=>
|
|
if (ibyte /= 4) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format for record type 05! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (ibyte-1) loop
|
|
READ(L=>buf, VALUE=>base,good=>booval);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal Intel Hex Format! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
|
|
end loop;
|
|
when OTHERS =>
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) &
|
|
"]:Illegal record type in Intel Hex File! "
|
|
SEVERITY ERROR;
|
|
end case;
|
|
READ(L=>buf, VALUE=>checksum,good=>booval);
|
|
if not (booval) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Checksum is missing! "
|
|
SEVERITY ERROR;
|
|
end if;
|
|
check_sum_vec := unsigned(not (check_sum_vec)) + 1 ;
|
|
check_sum_vec_tmp := CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(checksum),8);
|
|
|
|
if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then
|
|
ASSERT FALSE
|
|
REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Incorrect checksum!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
end loop;
|
|
elsif (ALPHA_TOLOWER(lpm_file(lpm_file'length -3 to lpm_file'length)) = ".mif") then
|
|
-- ************************************************
|
|
-- Read in RAM initialization file (mif)
|
|
-- ************************************************
|
|
while not endfile(mem_data_file) loop
|
|
booval := true;
|
|
readline(mem_data_file, buf);
|
|
lineno := lineno + 1;
|
|
LOOP2 : while (buf'length > 0) loop
|
|
if (buf(buf'low) = '-') then
|
|
if (buf(buf'low) = '-') then
|
|
-- ignore comment started with --.
|
|
exit LOOP2;
|
|
end if;
|
|
elsif (buf(buf'low) = '%') then
|
|
i := 1;
|
|
|
|
-- ignore comment which begin with % and end with another %.
|
|
while ((i < buf'high) and (buf(buf'low + i) /= '%')) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i >= buf'high) then
|
|
exit LOOP2;
|
|
else
|
|
SHRINK_LINE(buf, i+1);
|
|
end if;
|
|
elsif ((buf(buf'low) = ' ') or (buf(buf'low) = HT)) then
|
|
i := 1;
|
|
-- ignore space or tab character.
|
|
while ((i < buf'high-1) and ((buf(buf'low +i) = ' ') or
|
|
(buf(buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i >= buf'high) then
|
|
exit LOOP2;
|
|
else
|
|
SHRINK_LINE(buf, i);
|
|
end if;
|
|
elsif (get_memory_content = true) then
|
|
|
|
if ((buf(buf'low to buf'low +2) = "end") or
|
|
(buf(buf'low to buf'low +2) = "END") or
|
|
(buf(buf'low to buf'low +2) = "End")) then
|
|
get_memory_content := false;
|
|
exit LOOP2;
|
|
else
|
|
get_start_address := false;
|
|
get_end_address := false;
|
|
m_start_address_int := 0;
|
|
m_end_address_int := 0;
|
|
m_address_int := 0;
|
|
m_data_int := (others => '0');
|
|
if (buf(buf'low) = '[') then
|
|
get_start_Address := true;
|
|
SHRINK_LINE(buf, 1);
|
|
end if;
|
|
|
|
case m_address_radix is
|
|
when "hex" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ':') and (buf(buf'low) /= '.')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *16 + HEX_STR_TO_INT(char);
|
|
end loop;
|
|
when "bin" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ':') and (buf(buf'low) /= '.')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *2 + BIN_STR_TO_INT(char);
|
|
end loop;
|
|
when "dec" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ':') and (buf(buf'low) /= '.')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(char);
|
|
end loop;
|
|
when "uns" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ':') and (buf(buf'low) /= '.')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(char);
|
|
end loop;
|
|
when "oct" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ':') and (buf(buf'low) /= '.')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *8 + OCT_STR_TO_INT(char);
|
|
end loop;
|
|
when others =>
|
|
assert false
|
|
report "Unsupported address_radix!"
|
|
severity error;
|
|
end case;
|
|
|
|
if (get_start_Address = true) then
|
|
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < buf'high-1) and ((buf(buf'low +i) = ' ') or
|
|
(buf(buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(buf, i);
|
|
end if;
|
|
|
|
if ((buf(buf'low) = '.') and (buf(buf'low+1) = '.')) then
|
|
get_start_Address := false;
|
|
get_end_Address := true;
|
|
m_start_address_int := m_address_int;
|
|
SHRINK_LINE(buf, 2);
|
|
end if;
|
|
end if;
|
|
|
|
if (get_end_address = true) then
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < buf'high-1) and ((buf(buf'low +i) = ' ') or
|
|
(buf(buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(buf, i);
|
|
end if;
|
|
|
|
m_address_int := 0;
|
|
case m_address_radix is
|
|
when "hex" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ']')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *16 + HEX_STR_TO_INT(char);
|
|
end loop;
|
|
when "bin" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ']')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *2 + BIN_STR_TO_INT(char);
|
|
end loop;
|
|
when "dec" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ']')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(char);
|
|
end loop;
|
|
when "uns" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ']')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *10 + INT_STR_TO_INT(char);
|
|
end loop;
|
|
when "oct" =>
|
|
while ((buf(buf'low) /= ' ') and (buf(buf'low) /= HT) and
|
|
(buf(buf'low) /= ']')) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_address_int := m_address_int *8 + OCT_STR_TO_INT(char);
|
|
end loop;
|
|
when others =>
|
|
assert false
|
|
report "Unsupported address_radix!"
|
|
severity error;
|
|
end case;
|
|
|
|
if (buf(buf'low) = ']') then
|
|
get_end_address := false;
|
|
m_end_address_int := m_address_int;
|
|
SHRINK_LINE(buf, 1);
|
|
end if;
|
|
end if;
|
|
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < buf'high-1) and ((buf(buf'low +i) = ' ') or
|
|
(buf(buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(buf, i);
|
|
end if;
|
|
|
|
if (buf(buf'low) = ':') then
|
|
SHRINK_LINE(buf, 1);
|
|
end if;
|
|
|
|
i := 0;
|
|
-- ignore space or tab character.
|
|
while ((i < buf'high-1) and ((buf(buf'low +i) = ' ') or
|
|
(buf(buf'low+i) = HT))) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (i > 0) then
|
|
SHRINK_LINE(buf, i);
|
|
end if;
|
|
|
|
case m_data_radix is
|
|
when "hex" =>
|
|
while ((buf(buf'low) /= ';') and (buf(buf'low) /= ' ') and
|
|
(buf(buf'low) /= HT)) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_data_int(width+4 downto 0) := m_data_int(width-1 downto 0) * "10000" + conv_std_logic_vector(HEX_STR_TO_INT(char), 4);
|
|
end loop;
|
|
when "bin" =>
|
|
while ((buf(buf'low) /= ';') and (buf(buf'low) /= ' ') and
|
|
(buf(buf'low) /= HT)) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_data_int(width+1 downto 0) := m_data_int(width-1 downto 0) * "10" + conv_std_logic_vector(BIN_STR_TO_INT(char), 4);
|
|
end loop;
|
|
when "dec" =>
|
|
while ((buf(buf'low) /= ';') and (buf(buf'low) /= ' ') and
|
|
(buf(buf'low) /= HT)) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_data_int(width+3 downto 0) := m_data_int(width-1 downto 0) * "1010" + conv_std_logic_vector(INT_STR_TO_INT(char), 4);
|
|
end loop;
|
|
when "uns" =>
|
|
while ((buf(buf'low) /= ';') and (buf(buf'low) /= ' ') and
|
|
(buf(buf'low) /= HT)) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_data_int(width+3 downto 0) := m_data_int(width-1 downto 0) * "1010" + conv_std_logic_vector(INT_STR_TO_INT(char), 4);
|
|
end loop;
|
|
when "oct" =>
|
|
while ((buf(buf'low) /= ';') and (buf(buf'low) /= ' ') and
|
|
(buf(buf'low) /= HT)) loop
|
|
read(l => buf, value => char, good => booval);
|
|
m_data_int(width+3 downto 0) := m_data_int(width-1 downto 0) * "1000" + conv_std_logic_vector(OCT_STR_TO_INT(char), 4);
|
|
end loop;
|
|
when others =>
|
|
assert false
|
|
report "Unsupported data_radix!"
|
|
severity error;
|
|
end case;
|
|
|
|
if (m_start_address_int /= m_end_address_int) then
|
|
for i in m_start_address_int to m_end_address_int loop
|
|
mem_data(i) := m_data_int(width-1 downto 0);
|
|
end loop;
|
|
else
|
|
mem_data(m_address_int) := m_data_int(width-1 downto 0);
|
|
end if;
|
|
exit LOOP2;
|
|
end if;
|
|
elsif ((buf(buf'low) = 'W') or (buf(buf'low) = 'w')) then
|
|
read(l=>buf, value=>m_string(1 to 5));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 5)) = "width") then
|
|
i := 0;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (buf(buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((buf(buf'low +i) = ' ') or (buf(buf'low +i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(buf, i);
|
|
|
|
i := 0;
|
|
while (buf(buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>buf, value=>m_string(1 to i));
|
|
|
|
m_width := INT_STR_TO_INT(m_string(1 to i));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif (((buf(buf'low) = 'D') or (buf(buf'low) = 'd')) and
|
|
((buf(buf'low+1) = 'E') or (buf(buf'low+1) = 'e'))) then
|
|
read(l=>buf, value=>m_string(1 to 5));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 5)) = "depth") then
|
|
i := 0;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (buf(buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((buf(buf'low +i) = ' ') or (buf(buf'low +i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(buf, i);
|
|
|
|
i := 0;
|
|
while (buf(buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>buf, value=>m_string(1 to i));
|
|
|
|
m_depth := INT_STR_TO_INT(m_string(1 to i));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif ((buf(buf'low) = 'D') or (buf(buf'low) = 'd')) then
|
|
read(l=>buf, value=>m_string(1 to 10));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 10)) = "data_radix") then
|
|
i := 0;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (buf(buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(buf, i);
|
|
|
|
i := 0;
|
|
while (buf(buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>buf, value=>m_string(1 to 3));
|
|
|
|
m_data_radix := ALPHA_TOLOWER(m_string(1 to 3));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif ((buf(buf'low) = 'A') or (buf(buf'low) = 'a')) then
|
|
read(l=>buf, value=>m_string(1 to 13));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 13)) = "address_radix") then
|
|
i := 0;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
if (buf(buf'low + i) = '=') then
|
|
i := i+1;
|
|
end if;
|
|
|
|
while ((buf(buf'low+i) = ' ') or (buf(buf'low+i) = HT)) loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
SHRINK_LINE(buf, i);
|
|
|
|
i := 0;
|
|
while (buf(buf'low + i) /= ';') loop
|
|
i := i+1;
|
|
end loop;
|
|
|
|
read(l=>buf, value=>m_string(1 to 3));
|
|
|
|
m_address_radix := ALPHA_TOLOWER(m_string(1 to 3));
|
|
end if;
|
|
exit LOOP2;
|
|
elsif ((buf(buf'low) = 'C') or (buf(buf'low) = 'c')) then
|
|
read(l=>buf, value=>m_string(1 to 7));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 7)) = "content") then
|
|
found_keyword_content := true;
|
|
end if;
|
|
elsif ((buf(buf'low) = 'B') or (buf(buf'low) = 'b')) then
|
|
read(l=>buf, value=>m_string(1 to 5));
|
|
|
|
if (ALPHA_TOLOWER(m_string(1 to 5)) = "begin") then
|
|
if (found_keyword_content = true) then
|
|
get_memory_content := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
|
|
else
|
|
assert false
|
|
report "Unsupported memory initialization file type (" & lpm_file(lpm_file'length -3 to lpm_file'length) & ")!"
|
|
severity error;
|
|
end if;
|
|
|
|
|
|
FILE_CLOSE(mem_data_file);
|
|
end if;
|
|
mem_init := TRUE;
|
|
--
|
|
--*******************************************
|
|
else -- already initialized
|
|
|
|
-- MEMORY FUNCTION --
|
|
-- This is where data is being write to the internal memory: mem_data[]
|
|
--
|
|
if (iwren_tmp = '1') then
|
|
mem_data (ieee.std_logic_unsigned.conv_integer(iwraddress_tmp)) := idata_tmp;
|
|
end if;
|
|
|
|
-- Triple-Port Ram (alt3pram) has one write port and two read ports (a and b)
|
|
-- Below is the operation to read data from internal memory (mem_data[])
|
|
-- to the output port (iqa_tmp or iqb_tmp)
|
|
-- Note: iq*_tmp will serve as the var directly link to the physical
|
|
-- output port q* if alt3pram is operate in "Shared Clock Mode",
|
|
-- else data read from iq*_tmp will need to be latched to i_q*_reg
|
|
-- through outclock before it is fed to the output port q* (qa or qb).
|
|
if (irden_tmp_a = '1') then
|
|
iqa_tmp <= mem_data(ieee.std_logic_unsigned.conv_integer(irdaddress_tmp_a));
|
|
elsif (rden_low_output_0) then
|
|
iqa_tmp <= (OTHERS => '0');
|
|
end if;
|
|
|
|
if (irden_tmp_b = '1') then
|
|
iqb_tmp <= mem_data(ieee.std_logic_unsigned.conv_integer(irdaddress_tmp_b));
|
|
elsif (rden_low_output_0) then
|
|
iqb_tmp <= (OTHERS => '0');
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end process MEMORY;
|
|
|
|
end behavior; -- architecture of alt3pram
|
|
|
|
--end of alt3pram
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- entity Name : parallel_add
|
|
--
|
|
-- Description : Parameterized parallel adder megafunction. The data input
|
|
-- is a concatenated group of input words. The size
|
|
-- parameter indicates the number of 'width'-bit words.
|
|
--
|
|
-- Each word is added together to generate the result output.
|
|
-- Each word is left shifted according to the shift
|
|
-- parameter. The shift amount is multiplied by the word
|
|
-- index, with the least significant word being word 0.
|
|
-- The shift for word I is (shift * I).
|
|
--
|
|
-- The most significant word can be subtracted from the total
|
|
-- by setting the msw_subtract parameter to 1.
|
|
-- if the result width is less than is required to show the
|
|
-- full result, the result output can be aligned to the MSB
|
|
-- or the LSB of the internal result. when aligning to the
|
|
-- MSB, the internally calculated BEST_RESULT_WIDTH is used
|
|
-- to find the true MSB.
|
|
-- The input data can be signed or unsigned, and the output
|
|
-- can be pipelined.
|
|
--
|
|
-- Limitations : Minimum data width is 1, and at least 2 words are required.
|
|
--
|
|
-- Results expected: result - The sum of all inputs.
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use work.altera_mf_components.all;
|
|
|
|
-- BEGINNING OF ENTITY
|
|
|
|
-- ENTITY DECLARATION
|
|
|
|
entity parallel_add is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
width : natural := 4;
|
|
size : natural := 2;
|
|
widthr : natural := 4;
|
|
shift : natural := 0;
|
|
msw_subtract : string := "NO";
|
|
representation : string := "UNSIGNED";
|
|
pipeline : natural := 0;
|
|
result_alignment : string := "LSB";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "parallel_add" );
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
data : in altera_mf_logic_2D(size - 1 downto 0, width- 1 downto 0);
|
|
clock : in std_logic := '1';
|
|
aclr : in std_logic := '0';
|
|
clken : in std_logic := '1';
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
result : out std_logic_vector(widthr - 1 downto 0) );
|
|
end parallel_add;
|
|
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
|
|
architecture behaviour OF parallel_add IS
|
|
|
|
-- TYPE DECLARATION
|
|
TYPE pipeline_type is ARRAY (pipeline downto 0) OF std_logic_vector(widthr - 1 downto 0);
|
|
|
|
-- Maximum precision required for internal calculations.
|
|
-- This is a pessimistic estimate, but it is guaranteed to be sufficient.
|
|
-- The +30 is there only to simplify the test generator, which occasionally asks
|
|
-- for output widths far in excess of what is needed. The excess is always less than 30.
|
|
constant MAX_PRECISION : natural := (width + size + shift * (size - 1) + 30);
|
|
|
|
-- Bitwise Left shift -- Bitwise Left shift
|
|
procedure shift_left ( val : inout std_logic_vector; num : in natural) is
|
|
variable temp : std_logic_vector((val'length - 1) downto 0);
|
|
begin
|
|
if num /= 0 then
|
|
temp := val;
|
|
if (val'length > 1) then
|
|
for i in temp'high downto num loop
|
|
temp(i) := temp(i- num);
|
|
end loop;
|
|
for i in num-1 downto 0 loop
|
|
temp(i) := '0';
|
|
end loop;
|
|
end if;
|
|
temp(0) :='0';
|
|
val := temp;
|
|
end if;
|
|
end shift_left;
|
|
|
|
-- Bitwise right shift
|
|
procedure shift_right ( val : inout std_logic_vector; num : in natural ) is
|
|
variable temp : std_logic_vector(val'length-1 downto 0);
|
|
begin
|
|
if num /= 0 then
|
|
temp := val;
|
|
if (val'length > 1) then
|
|
for i in 0 to temp'high - 1 loop
|
|
if (i + num) <= (temp'high - 1) then
|
|
temp(i) := temp(i+num);
|
|
else
|
|
temp(i) := '0';
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
temp(temp'high) := '0';
|
|
val := temp;
|
|
end if;
|
|
end shift_right;
|
|
|
|
|
|
function ceil_log2 (input_num : in std_logic_vector(MAX_PRECISION - 1 downto 0))
|
|
return natural IS
|
|
variable i : natural;
|
|
variable try_result : std_logic_vector(MAX_PRECISION - 1 downto 0);
|
|
variable ceil_log2 : natural;
|
|
begin
|
|
i := 0;
|
|
try_result := conv_std_logic_vector(1,MAX_PRECISION);
|
|
while (i < MAX_PRECISION) loop
|
|
shift_left(try_result,1);
|
|
if (unsigned(try_result) < unsigned(input_num)) then
|
|
i := i + 1;
|
|
else
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
ceil_log2 := i;
|
|
return (ceil_log2);
|
|
end ceil_log2;
|
|
|
|
-- best_result_width calculation
|
|
-- DEFINE CALC_PADD_WIDTHR(w, z, s) = (s == 0) ? CEIL(LOG2(z*((2^w)-1))) :
|
|
-- CEIL(LOG2(((2^w)-1) * (2^(z*s)-1) / ((2^s)-1)));
|
|
|
|
-- Note: The recommended value for WIDTHR parameter,
|
|
-- the width of addition result, for full
|
|
-- precision is:
|
|
-- if shift = 0 then
|
|
-- WIDTHR = CEIL(LOG2( ((2^WIDTH)-1) * SIZE))
|
|
--
|
|
--
|
|
-- if shift /= 0 then
|
|
-- ((2^WIDTH)-1) * (2^(SIZE*SHIFT)-1)
|
|
-- WIDTHR = CEIL(LOG2(-----------------------------------))
|
|
-- (2^SHIFT)-1
|
|
|
|
function get_best_result_width (shift, width, size : in natural) return natural is
|
|
variable best_result_width : natural;
|
|
variable input_num : std_logic_vector(MAX_PRECISION - 1 downto 0) := (others => '0');
|
|
variable size_vec : std_logic_vector(size downto 0) := (others => '0');
|
|
variable width_power : std_logic_vector(width downto 0) := (others => '0');
|
|
variable size_shift_power : std_logic_vector((size * shift) downto 0) := (others => '0');
|
|
|
|
variable i_denom : std_logic_vector(width + (size * shift) + 1 downto 0) := (others => '0');
|
|
variable mult_power : std_logic_vector(width + (size * shift) + 1 downto 0) := (others => '0');
|
|
variable max_width : natural;
|
|
variable trailing_zero_count : natural;
|
|
variable i_remain : std_logic_vector(width + (size * shift) + 1 downto 0) := (others => '0');
|
|
variable i_quotient : std_logic_vector(MAX_PRECISION - 1 downto 0) := (others => '0');
|
|
begin
|
|
|
|
-- Convert size natural into std logic vector
|
|
size_vec := conv_std_logic_vector(size,size+1);
|
|
|
|
-- width_power = (2^WIDTH)-1)
|
|
width_power := conv_std_logic_vector(1,width+1);
|
|
shift_left(width_power,width+1);
|
|
width_power := width_power - '1';
|
|
|
|
if (shift = 0) then
|
|
input_num(size + width + 1 downto 0) := (width_power * size_vec);
|
|
else
|
|
-- size_shift_power = (2^(SIZE*SHIFT)-1)
|
|
size_shift_power := conv_std_logic_vector(1, size * shift+1);
|
|
shift_left(size_shift_power,size * shift + 1);
|
|
size_shift_power := size_shift_power - '1';
|
|
-- i_denom = (2^SHIFT)-1
|
|
i_denom := conv_std_logic_vector(1, width + (size * shift) + 2);
|
|
shift_left(i_denom,shift+1);
|
|
i_denom := i_denom - '1';
|
|
|
|
-- mult_power := ((2^WIDTH)-1) * (2^(SIZE*SHIFT)-1)
|
|
mult_power := (width_power * size_shift_power);
|
|
max_width := width + (size * shift) + 1;
|
|
|
|
-- perform division using long division algorithm using LPM_DIVIDE method
|
|
|
|
trailing_zero_count := 0;
|
|
for i in 0 to max_width loop
|
|
if i_denom(i) /= '0' then
|
|
trailing_zero_count := i;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
|
|
for i in 0 to max_width loop
|
|
if i_denom(max_width - i) /= '0' then
|
|
shift_left(i_denom,i);
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
i_remain := mult_power;
|
|
if (unsigned(i_remain) >= unsigned(i_denom)) then
|
|
i_remain := i_remain - i_denom;
|
|
i_quotient(0) := '1';
|
|
else
|
|
i_quotient(0) := '0';
|
|
end if;
|
|
|
|
while (i_denom(trailing_zero_count) = '0') loop
|
|
shift_right(i_denom,1);
|
|
shift_left(i_quotient, 1);
|
|
if (unsigned(i_remain) >= unsigned(i_denom)) then
|
|
i_remain := i_remain - i_denom;
|
|
i_quotient(0) := '1';
|
|
else
|
|
i_quotient(0) := '0';
|
|
end if;
|
|
end loop;
|
|
input_num := i_quotient;
|
|
end if;
|
|
|
|
best_result_width := ceil_log2(input_num);
|
|
return (best_result_width);
|
|
end get_best_result_width;
|
|
|
|
|
|
|
|
constant BEST_RESULT_WIDTH : natural := get_best_result_width(shift, width, size);
|
|
-- constant BEST_RESULT_WIDTH : natural := 33;
|
|
|
|
-- INTERNAL SIGNAL DECLARATION
|
|
signal isigned : std_logic;
|
|
signal imsw_subtract : std_logic;
|
|
signal imsb_align : std_logic;
|
|
signal aligned_result : std_logic_vector(widthr - 1 downto 0);
|
|
signal result_tmp : std_logic_vector(widthr - 1 downto 0);
|
|
|
|
begin
|
|
|
|
-- checking for invalid parameters
|
|
MSG: process
|
|
begin
|
|
if (width <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "The width parameter must be greater than 0"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if (widthr > MAX_PRECISION) then
|
|
ASSERT FALSE
|
|
REPORT "Error! WIDTHR must not exceed WIDTH+SIZE+SHIFT*(SIZE-1)."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (size < 2) then
|
|
ASSERT FALSE
|
|
REPORT "Error! SIZE must be greater than 1."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
wait;
|
|
end process MSG;
|
|
|
|
isigned <= '0' when (representation = "UNSIGNED") else '1';
|
|
imsw_subtract <= '1' when (msw_subtract = "YES") else '0';
|
|
imsb_align <= '1' when (result_alignment = "MSB" and widthr < BEST_RESULT_WIDTH) else '0';
|
|
|
|
|
|
process (data, isigned, imsw_subtract, imsb_align)
|
|
variable zero_padding : std_logic_vector(MAX_PRECISION - width - 1 downto 0)
|
|
:= (others => '0');
|
|
variable one_padding : std_logic_vector(MAX_PRECISION - width - 1 downto 0)
|
|
:= (others => '1');
|
|
variable tmp_result : std_logic_vector(MAX_PRECISION - 1 downto 0);
|
|
variable idata_word : std_logic_vector(width - 1 downto 0);
|
|
variable idata : std_logic_vector(MAX_PRECISION - 1 downto 0);
|
|
variable idata_extended : std_logic_vector(MAX_PRECISION - 1 downto 0);
|
|
variable ni : natural;
|
|
variable nj : natural;
|
|
begin
|
|
tmp_result := (others => '0');
|
|
idata_extended := (others => '0');
|
|
idata_word := (others => '0');
|
|
for ni in 0 to (size - 1) loop
|
|
for nj in 0 to (width - 1) loop
|
|
idata_word(nj) := '0';
|
|
-- To ensure there is only '1' or '0' in idata_word to avoid any
|
|
-- warning arithmetic message .
|
|
if (data(ni, nj) = '1') then
|
|
idata_word(nj) := '1';
|
|
end if;
|
|
end loop;
|
|
|
|
if ((isigned = '1') and (idata_word(width - 1) = '1')) then
|
|
idata_extended := one_padding & idata_word;
|
|
shift_left(idata_extended, (shift * ni));
|
|
else
|
|
idata_extended := zero_padding & idata_word;
|
|
shift_left(idata_extended,(shift * ni));
|
|
end if;
|
|
|
|
if ((imsw_subtract = '1') and (ni = (size - 1))) then
|
|
tmp_result := tmp_result - idata_extended;
|
|
else
|
|
tmp_result := tmp_result + idata_extended;
|
|
end if;
|
|
|
|
end loop;
|
|
|
|
if (imsb_align = '1') then
|
|
shift_right(tmp_result, (BEST_RESULT_WIDTH - widthr));
|
|
end if;
|
|
aligned_result <= tmp_result(widthr - 1 downto 0);
|
|
|
|
end process;
|
|
|
|
process (clock, aclr, clken, aligned_result)
|
|
variable ni : natural;
|
|
variable pipe_ptr : natural := 0;
|
|
variable resultpipe : pipeline_type := (others => (others => '0'));
|
|
|
|
begin
|
|
if (aclr = '1') then
|
|
for ni in 0 to (pipeline - 1) loop
|
|
resultpipe(ni) := (others => '0');
|
|
end loop;
|
|
result_tmp <= (others => '0');
|
|
elsif ((clock = '1') and (clock'last_value = '0') and clock'event and
|
|
(clken = '1')) then
|
|
resultpipe(pipe_ptr) := aligned_result;
|
|
if (pipeline > 1) then
|
|
pipe_ptr := (pipe_ptr + 1) mod pipeline;
|
|
end if;
|
|
result_tmp <= resultpipe(pipe_ptr);
|
|
end if;
|
|
end process;
|
|
|
|
result <= result_tmp when (pipeline > 0) else aligned_result;
|
|
|
|
end behaviour;
|
|
-- END OF ARCHITECTURE PARALLEL_ADD
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : scfifo
|
|
--
|
|
-- Description : Single Clock FIFO
|
|
--
|
|
-- Limitation : USE_EAB=OFF is not supported
|
|
--
|
|
-- Results Expected:
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- BEGINNING OF ENTITY
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use IEEE.std_logic_unsigned.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity SCFIFO is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
lpm_width : natural;
|
|
lpm_widthu : natural;
|
|
lpm_numwords : natural;
|
|
lpm_showahead : string := "OFF";
|
|
lpm_type : string := "scfifo";
|
|
lpm_hint : string := "USE_EAB=ON";
|
|
intended_device_family : string := "Stratix";
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
allow_rwcycle_when_full : string := "OFF";
|
|
use_eab : string := "ON";
|
|
add_ram_output_register : string := "OFF";
|
|
almost_full_value : natural := 0;
|
|
almost_empty_value : natural := 0;
|
|
maximum_depth : natural := 0
|
|
);
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
data : in std_logic_vector(lpm_width-1 downto 0);
|
|
clock : in std_logic;
|
|
wrreq : in std_logic;
|
|
rdreq : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
sclr : in std_logic := '0';
|
|
-- OUTPUT PORT DECLARATION
|
|
q : out std_logic_vector(lpm_width-1 downto 0);
|
|
usedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
full : out std_logic;
|
|
empty : out std_logic;
|
|
almost_full : out std_logic;
|
|
almost_empty : out std_logic);
|
|
end SCFIFO;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of SCFIFO is
|
|
-- TYPE DECLARATION
|
|
type lpm_memory is array (2**lpm_widthu-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant ZEROS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
|
|
constant NIL : std_logic_vector(2**lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
constant UNKNOWNS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => 'X');
|
|
constant USEDW_UNKNOWNS : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => 'X');
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal i_count_id : integer := 0;
|
|
signal i_read_id : integer := 0;
|
|
signal i_full_flag : std_logic := '0';
|
|
signal i_empty_flag : std_logic := '1';
|
|
signal i_almost_full_flag : std_logic := '0';
|
|
signal i_almost_empty_flag : std_logic := '1';
|
|
signal i_set_q_to_x : std_logic := '0';
|
|
signal i_set_q_to_x_by_empty : std_logic := '0';
|
|
signal i_tmp_q : std_logic_vector(lpm_width-1 downto 0) := ZEROS;
|
|
|
|
signal i_write_id : integer := 0;
|
|
signal i_write_latency1 : integer := 0;
|
|
signal i_write_latency2 : integer := 0;
|
|
signal i_write_latency3 : integer := 0;
|
|
signal i_wrt_count : integer := 0;
|
|
signal i_empty_latency1 : std_logic := '1';
|
|
signal i_empty_latency2 : std_logic := '1';
|
|
signal i_data_ready : std_logic_vector(2**lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_data_shown : std_logic_vector(2**lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
|
|
begin
|
|
-- PROCESS DECLARATION
|
|
process (clock, aclr)
|
|
-- VARIABLE DECLARATION
|
|
variable mem_data : lpm_memory := (OTHERS => ZEROS);
|
|
variable tmp_data : std_logic_vector(lpm_width-1 downto 0) := ZEROS;
|
|
variable write_flag : boolean := false;
|
|
variable full_flag : boolean := false;
|
|
variable valid_rreq : boolean := false;
|
|
variable valid_wreq : boolean := false;
|
|
variable max_widthu : integer := 0;
|
|
variable numwords_minus_one : integer := 0;
|
|
variable almost_full_minus_one : integer := 0;
|
|
variable almost_empty_minus_one : integer := 0;
|
|
variable need_init : boolean := true;
|
|
variable stratix_family : boolean := ( FEATURE_FAMILY_STRATIX(intended_device_family) ) ;
|
|
variable showahead_area : boolean := (lpm_showahead = "ON" and add_ram_output_register = "OFF");
|
|
variable showahead_speed : boolean := (lpm_showahead = "ON" and add_ram_output_register = "ON");
|
|
variable legacy_speed : boolean := (lpm_showahead = "OFF" and add_ram_output_register = "ON");
|
|
begin
|
|
if (need_init) then
|
|
if ((lpm_showahead /= "ON") and (lpm_showahead /= "OFF")) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal LPM_SHOWAHEAD property value for SCFIFO!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((underflow_checking /= "ON") and (underflow_checking /= "OFF")) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal UNDERFLOW_CHECKING property value for SCFIFO!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((overflow_checking /= "ON") and (overflow_checking /= "OFF")) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal OVERFLOW_CHECKING property value for SCFIFO!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((allow_rwcycle_when_full /= "ON") and (allow_rwcycle_when_full /= "OFF")) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal ALLOW_RWCYCLE_WHEN_FULL property value for SCFIFO!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if (IS_VALID_FAMILY(intended_device_family) = false) then
|
|
ASSERT FALSE
|
|
REPORT "Illegal INTENDED_DEVICE_FAMILY for SCFIFO!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((add_ram_output_register /= "ON") and (add_ram_output_register /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! ADD_RAM_OUTPUT_REGISTER must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
for i in 0 to (lpm_widthu - 1) loop
|
|
if (stratix_family)
|
|
then
|
|
if ((add_ram_output_register = "ON") or (use_eab = "OFF") or
|
|
(FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)))
|
|
then
|
|
mem_data(i) := ZEROS;
|
|
else
|
|
mem_data(i) := UNKNOWNS;
|
|
end if;
|
|
else
|
|
mem_data(i) := ZEROS;
|
|
end if;
|
|
end loop;
|
|
|
|
if (stratix_family)
|
|
then
|
|
if ((add_ram_output_register = "ON") or (use_eab = "OFF") or
|
|
(FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)))
|
|
then
|
|
i_tmp_q <= ZEROS;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
else
|
|
i_tmp_q <= ZEROS;
|
|
end if;
|
|
|
|
if (almost_full_value = 0)
|
|
then
|
|
i_almost_full_flag <= '1';
|
|
else
|
|
i_almost_full_flag <= '0';
|
|
end if;
|
|
|
|
if (almost_empty_value = 0)
|
|
then
|
|
i_almost_empty_flag <= '0';
|
|
else
|
|
i_almost_empty_flag <= '1';
|
|
end if;
|
|
|
|
max_widthu := (2 ** lpm_widthu) - 1;
|
|
numwords_minus_one := lpm_numwords - 1;
|
|
|
|
almost_full_minus_one := almost_full_value - 1;
|
|
almost_empty_minus_one := almost_empty_value - 1;
|
|
|
|
i_write_latency1 <= max_widthu+1;
|
|
i_write_latency2 <= max_widthu+1;
|
|
i_write_latency3 <= max_widthu+1;
|
|
|
|
need_init := false;
|
|
end if;
|
|
|
|
if (aclr = '1') then
|
|
full_flag := false;
|
|
i_read_id <= 0;
|
|
i_count_id <= 0;
|
|
i_full_flag <= '0';
|
|
i_empty_flag <= '1';
|
|
i_empty_latency1 <= '1';
|
|
i_empty_latency2 <= '1';
|
|
i_set_q_to_x <= '0';
|
|
i_set_q_to_x_by_empty <= '0';
|
|
i_wrt_count <= 0;
|
|
|
|
if (add_ram_output_register = "ON") then
|
|
i_tmp_q <= ZEROS;
|
|
elsif ((lpm_showahead = "ON") and (use_eab = "ON")) then
|
|
i_tmp_q <= UNKNOWNS;
|
|
else
|
|
if (not stratix_family) then
|
|
i_tmp_q <= ZEROS;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (clock'event and (clock = '1') and
|
|
((aclr = '0') or (stratix_family)))
|
|
then
|
|
valid_rreq := rdreq = '1' and ((i_empty_flag = '0') or
|
|
(underflow_checking = "OFF"));
|
|
valid_wreq := wrreq = '1' and ((i_full_flag = '0') or
|
|
(overflow_checking = "OFF") or ((rdreq = '1') and
|
|
(allow_rwcycle_when_full = "ON")));
|
|
|
|
|
|
if ((sclr = '1') or (aclr = '1'))
|
|
then
|
|
if (add_ram_output_register = "ON") then
|
|
i_tmp_q <= ZEROS;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
|
|
i_read_id <= 0;
|
|
i_count_id <= 0;
|
|
i_full_flag <= '0';
|
|
i_empty_flag <= '1';
|
|
i_empty_latency1 <= '1';
|
|
i_empty_latency2 <= '1';
|
|
i_set_q_to_x <= '0';
|
|
i_set_q_to_x_by_empty <= '0';
|
|
i_wrt_count <= 0;
|
|
|
|
if (almost_full_value > 0)
|
|
then
|
|
i_almost_full_flag <= '0';
|
|
end if;
|
|
if (almost_empty_value > 0)
|
|
then
|
|
i_almost_empty_flag <= '1';
|
|
end if;
|
|
|
|
full_flag := false;
|
|
|
|
if (not(stratix_family))
|
|
then
|
|
if (valid_wreq)
|
|
then
|
|
tmp_data := data;
|
|
write_flag := true;
|
|
else
|
|
i_write_id <= 0;
|
|
end if;
|
|
else
|
|
i_write_id <= 0;
|
|
end if;
|
|
else
|
|
|
|
-- READ operation only
|
|
if (valid_rreq)
|
|
then
|
|
if (not ((i_set_q_to_x = '1') or (i_set_q_to_x_by_empty = '1')))
|
|
then
|
|
if (not valid_wreq)
|
|
then
|
|
i_wrt_count <= i_wrt_count - 1;
|
|
end if;
|
|
|
|
if (not valid_wreq)
|
|
then
|
|
i_full_flag <= '0';
|
|
full_flag := false;
|
|
|
|
if (i_count_id <= 0)
|
|
then
|
|
i_count_id <= max_widthu;
|
|
else
|
|
i_count_id <= i_count_id - 1;
|
|
end if;
|
|
end if;
|
|
|
|
if ((use_eab = "ON") and stratix_family and (showahead_speed or showahead_area or legacy_speed))
|
|
then
|
|
if ((i_wrt_count = 1) or ((i_wrt_count = 1) and valid_wreq and valid_rreq))
|
|
then
|
|
i_empty_flag <= '1';
|
|
else
|
|
if (showahead_speed)
|
|
then
|
|
if (i_write_latency2 <= max_widthu)
|
|
then
|
|
if (i_data_shown(i_write_latency2) = '0')
|
|
then
|
|
i_empty_flag <= '1';
|
|
end if;
|
|
end if;
|
|
else if (showahead_area or legacy_speed)
|
|
then
|
|
if (i_write_latency1 <= max_widthu)
|
|
then
|
|
if (i_data_shown(i_write_latency1) = '0')
|
|
then
|
|
i_empty_flag <= '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else
|
|
if (not(valid_wreq))
|
|
then
|
|
if (i_count_id = 1 and i_full_flag = '0')
|
|
then
|
|
i_empty_flag <= '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (i_empty_flag = '1')
|
|
then
|
|
|
|
if (underflow_checking = "ON") then
|
|
if ((use_eab = "OFF") or stratix_family) then
|
|
i_tmp_q <= ZEROS;
|
|
end if;
|
|
else
|
|
i_set_q_to_x_by_empty <= '1';
|
|
ASSERT FALSE
|
|
REPORT "Warning : Underflow occurred! Fifo output is unknown until the next reset is asserted"
|
|
SEVERITY WARNING;
|
|
end if;
|
|
|
|
else
|
|
if (i_read_id >= max_widthu)
|
|
then
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
if ((use_eab = "ON") and stratix_family and (showahead_speed or showahead_area))
|
|
then
|
|
if (showahead_speed)
|
|
then
|
|
if ((i_write_latency2 = ZEROS) or (i_data_ready(0) = '1'))
|
|
then
|
|
if (i_data_shown(0) = '1')
|
|
then
|
|
i_tmp_q <= mem_data(0);
|
|
i_data_shown(0) <= '0';
|
|
i_data_ready(0) <= '0';
|
|
end if;
|
|
end if;
|
|
else
|
|
if (i_count_id = 1 and i_full_flag = '0')
|
|
then
|
|
if (underflow_checking = "ON") then
|
|
if ((use_eab = "OFF") or stratix_family) then
|
|
i_tmp_q <= ZEROS;
|
|
end if;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
else
|
|
if ((i_write_latency1 = ZEROS) or (i_data_ready(0) = '1'))
|
|
then
|
|
if (i_data_shown(0) = '1')
|
|
then
|
|
i_tmp_q <= mem_data(0);
|
|
i_data_shown(0) <= '0';
|
|
i_data_ready(0) <= '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else
|
|
if (i_count_id = 1 and i_full_flag = '0')
|
|
then
|
|
if (valid_wreq)
|
|
then
|
|
i_tmp_q <= data;
|
|
else
|
|
if (underflow_checking = "ON") then
|
|
if ((use_eab = "OFF") or stratix_family) then
|
|
i_tmp_q <= ZEROS;
|
|
end if;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
end if;
|
|
else
|
|
i_tmp_q <= mem_data(0);
|
|
end if;
|
|
end if;
|
|
else
|
|
if ((use_eab = "ON") and (stratix_family and legacy_speed))
|
|
then
|
|
if ((i_write_latency1 = i_read_id) or (i_data_ready(i_read_id) = '1'))
|
|
then
|
|
if (i_data_shown(i_read_id) = '1')
|
|
then
|
|
i_tmp_q <= mem_data(i_read_id);
|
|
i_data_shown(i_read_id) <= '0';
|
|
i_data_ready(i_read_id) <= '0';
|
|
end if;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
else
|
|
i_tmp_q <= mem_data(i_read_id);
|
|
end if;
|
|
end if;
|
|
|
|
i_read_id <= 0;
|
|
else
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
if ((use_eab = "ON") and (stratix_family and (showahead_speed or showahead_area)))
|
|
then
|
|
if (showahead_speed)
|
|
then
|
|
if ((i_write_latency2 = i_read_id+1) or (i_data_ready(i_read_id+1) = '1'))
|
|
then
|
|
if (i_data_shown(i_read_id+1) = '1')
|
|
then
|
|
i_tmp_q <= mem_data(i_read_id + 1);
|
|
i_data_shown(i_read_id+1) <= '0';
|
|
i_data_ready(i_read_id+1) <= '0';
|
|
end if;
|
|
end if;
|
|
else
|
|
if (i_count_id = 1 and i_full_flag = '0')
|
|
then
|
|
if (underflow_checking = "ON") then
|
|
if ((use_eab = "OFF") or stratix_family) then
|
|
i_tmp_q <= ZEROS;
|
|
end if;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
else
|
|
if ((i_write_latency1 = i_read_id+1) or (i_data_ready(i_read_id+1) = '1'))
|
|
then
|
|
if (i_data_shown(i_read_id+1) = '1')
|
|
then
|
|
i_tmp_q <= mem_data(i_read_id + 1);
|
|
i_data_shown(i_read_id+1) <= '0';
|
|
i_data_ready(i_read_id+1) <= '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else
|
|
if (i_count_id = 1 and i_full_flag = '0')
|
|
then
|
|
if ((use_eab = "OFF") and stratix_family)
|
|
then
|
|
if (valid_wreq) then
|
|
i_tmp_q <= data;
|
|
else
|
|
if (underflow_checking = "ON") then
|
|
i_tmp_q <= ZEROS;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
end if;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
else
|
|
i_tmp_q <= mem_data(i_read_id + 1);
|
|
end if;
|
|
end if;
|
|
else
|
|
if ((use_eab = "ON") and stratix_family and legacy_speed)
|
|
then
|
|
if ((i_write_latency1 = i_read_id) or (i_data_ready(i_read_id) = '1'))
|
|
then
|
|
if (i_data_shown(i_read_id) = '1')
|
|
then
|
|
i_tmp_q <= mem_data(i_read_id);
|
|
i_data_shown(i_read_id) <= '0';
|
|
i_data_ready(i_read_id) <= '0';
|
|
end if;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
else
|
|
i_tmp_q <= mem_data(i_read_id);
|
|
end if;
|
|
end if;
|
|
|
|
i_read_id <= i_read_id + 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- WRITE operation only
|
|
if (valid_wreq)
|
|
then
|
|
if (not ((i_set_q_to_x = '1') or (i_set_q_to_x_by_empty = '1')))
|
|
then
|
|
if ((overflow_checking = "OFF") and full_flag)
|
|
then
|
|
i_set_q_to_x <= '1';
|
|
ASSERT FALSE
|
|
REPORT "Warning : Overflow occurred! Fifo output is unknown until the next reset is asserted"
|
|
SEVERITY WARNING;
|
|
else
|
|
tmp_data := data;
|
|
write_flag := true;
|
|
|
|
if (not((use_eab = "ON") and (stratix_family) and (showahead_speed or showahead_area or legacy_speed)))
|
|
then
|
|
i_empty_flag <= '0';
|
|
else
|
|
i_empty_latency1 <= '0';
|
|
end if;
|
|
|
|
if (not valid_rreq)
|
|
then
|
|
i_wrt_count <= i_wrt_count + 1;
|
|
end if;
|
|
|
|
if (not valid_rreq)
|
|
then
|
|
if (i_count_id >= max_widthu)
|
|
then
|
|
i_count_id <= 0;
|
|
else
|
|
i_count_id <= i_count_id + 1;
|
|
end if;
|
|
else
|
|
if (allow_rwcycle_when_full = "OFF")
|
|
then
|
|
i_full_flag <= '0';
|
|
end if;
|
|
end if;
|
|
|
|
if (not(stratix_family) or(stratix_family and not(showahead_speed or showahead_area or legacy_speed)))
|
|
then
|
|
if (not valid_rreq)
|
|
then
|
|
if ((i_count_id = numwords_minus_one) and (i_empty_flag = '0'))
|
|
then
|
|
i_full_flag <= '1';
|
|
full_flag := true;
|
|
end if;
|
|
end if;
|
|
else
|
|
if (not valid_rreq)
|
|
then
|
|
if (i_count_id = numwords_minus_one)
|
|
then
|
|
i_full_flag <= '1';
|
|
full_flag := true;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
if ((use_eab = "ON") and (stratix_family) and (showahead_speed or showahead_area))
|
|
then
|
|
i_write_latency1 <= i_write_id;
|
|
|
|
if (i_write_id <= max_widthu)
|
|
then
|
|
i_data_shown(i_write_id) <= '1';
|
|
i_data_ready(i_write_id) <= 'X';
|
|
end if;
|
|
else
|
|
if ((use_eab = "OFF") and stratix_family and (i_count_id = 0) and (not full_flag))
|
|
then
|
|
i_tmp_q <= data;
|
|
else
|
|
if ((not i_empty_flag = '0') and (not valid_rreq))
|
|
then
|
|
i_tmp_q <= mem_data(i_read_id);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else
|
|
if ((use_eab = "ON") and stratix_family and legacy_speed)
|
|
then
|
|
i_write_latency1 <= i_write_id;
|
|
|
|
if (i_write_id <= max_widthu)
|
|
then
|
|
i_data_shown(i_write_id) <= '1';
|
|
i_data_ready(i_write_id) <= 'X';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (almost_full_value = 0)
|
|
then
|
|
i_almost_full_flag <= '1';
|
|
elsif (lpm_numwords = almost_full_value)
|
|
then
|
|
if (full_flag)
|
|
then
|
|
i_almost_full_flag <= '1';
|
|
else
|
|
i_almost_full_flag <= '0';
|
|
end if;
|
|
else
|
|
if (i_almost_full_flag = '1')
|
|
then
|
|
if ((i_count_id = almost_full_value) and (wrreq = '0') and
|
|
(rdreq = '1'))
|
|
then
|
|
i_almost_full_flag <= '0';
|
|
end if;
|
|
else
|
|
if ((almost_full_value = 1) and (i_count_id = 0) and (wrreq = '1'))
|
|
then
|
|
i_almost_full_flag <= '1';
|
|
elsif ((almost_full_value > 1) and (i_count_id = almost_full_minus_one)
|
|
and (wrreq = '1') and (rdreq = '0'))
|
|
then
|
|
i_almost_full_flag <= '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (almost_empty_value = 0)
|
|
then
|
|
i_almost_empty_flag <= '0';
|
|
elsif (lpm_numwords = almost_empty_value)
|
|
then
|
|
if (full_flag)
|
|
then
|
|
i_almost_empty_flag <= '0';
|
|
else
|
|
i_almost_empty_flag <= '1';
|
|
end if;
|
|
else
|
|
if (i_almost_empty_flag = '1')
|
|
then
|
|
if ((almost_empty_value = 1) and (i_count_id = 0) and (wrreq = '1'))
|
|
then
|
|
i_almost_empty_flag <= '0';
|
|
elsif ((almost_empty_value > 1) and (i_count_id = almost_empty_minus_one)
|
|
and (wrreq = '1') and (rdreq = '0'))
|
|
then
|
|
i_almost_empty_flag <= '0';
|
|
end if;
|
|
else
|
|
if ((i_count_id = almost_empty_value) and (wrreq = '0') and
|
|
(rdreq = '1'))
|
|
then
|
|
i_almost_empty_flag <= '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if ((clock'event and (clock = '1')) and ((use_eab = "ON") and stratix_family))
|
|
then
|
|
if (showahead_speed)
|
|
then
|
|
i_write_latency2 <= i_write_latency1;
|
|
i_write_latency3 <= i_write_latency2;
|
|
|
|
if (i_write_latency3 /= i_write_latency2)
|
|
then
|
|
if (i_write_latency2 <= max_widthu)
|
|
then
|
|
i_data_ready(i_write_latency2) <= '1';
|
|
end if;
|
|
end if;
|
|
|
|
i_empty_latency2 <= i_empty_latency1;
|
|
|
|
if ((aclr = '1') or (sclr = '1'))
|
|
then
|
|
i_write_latency1 <= max_widthu+1;
|
|
i_write_latency2 <= max_widthu+1;
|
|
i_data_shown <= NIL;
|
|
if (add_ram_output_register = "ON") then
|
|
i_tmp_q <= ZEROS;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
end if;
|
|
|
|
if (i_write_latency2 <= max_widthu)
|
|
then
|
|
if (i_data_shown(i_write_latency2) = '1')
|
|
then
|
|
if ((i_read_id = i_write_latency2) or (aclr = '1') or (sclr = '1'))
|
|
then
|
|
if (not (aclr = '1') and (not(sclr = '1')))
|
|
then
|
|
i_tmp_q <= mem_data(i_write_latency2);
|
|
i_data_shown(i_write_latency2) <= '0';
|
|
i_data_ready(i_write_latency2) <= '0';
|
|
|
|
if (not valid_rreq)
|
|
then
|
|
i_empty_flag <= i_empty_latency2;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
elsif (showahead_area)
|
|
then
|
|
i_write_latency2 <= i_write_latency1;
|
|
|
|
if (i_write_latency2 /= i_write_latency1)
|
|
then
|
|
if (i_write_latency1 <= max_widthu)
|
|
then
|
|
i_data_ready(i_write_latency1) <= '1';
|
|
end if;
|
|
end if;
|
|
|
|
if ((aclr = '1') or (sclr = '1'))
|
|
then
|
|
i_write_latency1 <= max_widthu+1;
|
|
i_write_latency2 <= max_widthu+1;
|
|
i_data_shown <= NIL;
|
|
if (add_ram_output_register = "ON") then
|
|
i_tmp_q <= ZEROS;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
end if;
|
|
|
|
if (i_write_latency1 <= max_widthu)
|
|
then
|
|
if (i_data_shown(i_write_latency1) = '1')
|
|
then
|
|
if ((i_read_id = i_write_latency1) or (aclr = '1') or (sclr = '1'))
|
|
then
|
|
if (not (aclr = '1') and (not(sclr = '1')))
|
|
then
|
|
i_tmp_q <= mem_data(i_write_latency1);
|
|
i_data_shown(i_write_latency1) <= '0';
|
|
i_data_ready(i_write_latency1) <= '0';
|
|
|
|
if (not valid_rreq)
|
|
then
|
|
i_empty_flag <= i_empty_latency1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
else
|
|
if (legacy_speed)
|
|
then
|
|
i_write_latency2 <= i_write_latency1;
|
|
|
|
if (i_write_latency2 /= i_write_latency1)
|
|
then
|
|
if (i_write_latency1 <= max_widthu)
|
|
then
|
|
i_data_ready(i_write_latency1) <= '1';
|
|
end if;
|
|
end if;
|
|
|
|
if ((aclr = '1') or (sclr = '1'))
|
|
then
|
|
i_write_latency1 <= max_widthu+1;
|
|
i_write_latency2 <= max_widthu+1;
|
|
i_data_shown <= NIL;
|
|
if (add_ram_output_register = "ON") then
|
|
i_tmp_q <= ZEROS;
|
|
else
|
|
i_tmp_q <= UNKNOWNS;
|
|
end if;
|
|
end if;
|
|
|
|
if ((i_wrt_count = 0 and (not valid_wreq)) or (aclr = '1') or (sclr = '1') or (i_wrt_count = 1 and valid_rreq and (not valid_wreq)))
|
|
then
|
|
i_empty_flag <= '1';
|
|
i_empty_latency1 <= '1';
|
|
else
|
|
if (i_wrt_count = 1 and valid_wreq and valid_rreq)
|
|
then
|
|
i_empty_flag <= '1';
|
|
else
|
|
i_empty_flag <= i_empty_latency1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
elsif (clock'event and (clock = '0'))
|
|
then
|
|
if (write_flag)
|
|
then
|
|
write_flag := false;
|
|
mem_data(i_write_id) := tmp_data;
|
|
|
|
if ((aclr = '1') or (sclr = '1') or (i_write_id >= max_widthu))
|
|
then
|
|
i_write_id <= 0;
|
|
else
|
|
i_write_id <= i_write_id + 1;
|
|
end if;
|
|
end if;
|
|
|
|
if (not(stratix_family))
|
|
then
|
|
if (not i_empty_flag = '1')
|
|
then
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
i_tmp_q <= mem_data(i_read_id);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (aclr = '1') then
|
|
i_full_flag <= '0';
|
|
i_empty_flag <= '1';
|
|
if (almost_full_value > 0)
|
|
then
|
|
i_almost_full_flag <= '0';
|
|
end if;
|
|
if (almost_empty_value > 0)
|
|
then
|
|
i_almost_empty_flag <= '1';
|
|
end if;
|
|
|
|
i_read_id <= 0;
|
|
i_write_id <= 0;
|
|
i_count_id <= 0;
|
|
i_set_q_to_x <= '0';
|
|
i_wrt_count <= 0;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
q <= i_tmp_q when (not ((i_set_q_to_x = '1') or (i_set_q_to_x_by_empty = '1'))) else UNKNOWNS;
|
|
full <= i_full_flag when (not ((i_set_q_to_x = '1') or (i_set_q_to_x_by_empty = '1'))) else 'X';
|
|
empty <= i_empty_flag when (not ((i_set_q_to_x = '1') or (i_set_q_to_x_by_empty = '1'))) else 'X';
|
|
almost_full <= i_almost_full_flag when (not ((i_set_q_to_x = '1') or (i_set_q_to_x_by_empty = '1'))) else 'X';
|
|
almost_empty <= i_almost_empty_flag when (not ((i_set_q_to_x = '1') or (i_set_q_to_x_by_empty = '1'))) else 'X';
|
|
usedw <= conv_std_logic_vector(i_count_id, lpm_widthu) when (not ((i_set_q_to_x = '1') or (i_set_q_to_x_by_empty = '1'))) else USEDW_UNKNOWNS ;
|
|
|
|
end behavior; -- scfifo
|
|
-- END OF ARCHITECTURE
|
|
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : dcfifo_dffpipe
|
|
--
|
|
-- Description : Dual Clocks FIFO
|
|
--
|
|
-- Limitation :
|
|
--
|
|
-- Results Expected:
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- BEGINNING OF ENTITY
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use IEEE.std_logic_unsigned.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity DCFIFO_DFFPIPE is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
lpm_delay : natural;
|
|
lpm_width : natural);
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
d : in std_logic_vector (lpm_width-1 downto 0);
|
|
clock : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
-- OUTPUT PORT DECLARATION
|
|
q : out std_logic_vector (lpm_width-1 downto 0));
|
|
end DCFIFO_DFFPIPE;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of DCFIFO_DFFPIPE is
|
|
-- TYPE DECLARATION
|
|
type DELAYPIPE is array (lpm_delay downto 0) of std_logic_vector (lpm_width-1 downto 0);
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant ZEROS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
|
|
begin
|
|
|
|
-- PROCESS DECLARATION
|
|
process (clock, aclr, d)
|
|
------ VARIABLE DECLARATION
|
|
variable intpipe : DELAYPIPE := (OTHERS => ZEROS);
|
|
variable delay : integer := lpm_delay - 1;
|
|
variable need_init : boolean := true;
|
|
begin
|
|
if (lpm_delay = 0)
|
|
then
|
|
if ((aclr = '1') or need_init)
|
|
then
|
|
q <= ZEROS;
|
|
need_init := false;
|
|
else
|
|
q <= d;
|
|
end if;
|
|
else
|
|
if ((aclr = '1') or need_init)
|
|
then
|
|
for i in lpm_delay downto 0 loop
|
|
intpipe(i) := ZEROS;
|
|
end loop;
|
|
need_init := false;
|
|
q <= ZEROS;
|
|
end if;
|
|
|
|
if (clock'event and (clock = '1') and (NOW > 0 ns))
|
|
then
|
|
if (delay > 0) then
|
|
for i in delay downto 1 loop
|
|
intpipe(i) := intpipe(i-1);
|
|
end loop;
|
|
end if;
|
|
intpipe(0) := d;
|
|
q <= intpipe(delay);
|
|
end if;
|
|
end if; -- (lpm_delay = 0)
|
|
end process; -- clock, aclr, d events
|
|
end behavior; -- dcfifo_dffpipe
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : dcfifo_fefifo
|
|
--
|
|
-- Description : Dual Clocks FIFO
|
|
--
|
|
-- Limitation :
|
|
--
|
|
-- Results Expected:
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- BEGINNING OF ENTITY
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use IEEE.std_logic_unsigned.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity DCFIFO_FEFIFO is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
lpm_widthad : natural;
|
|
lpm_numwords : natural;
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
lpm_mode : string);
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
usedw_in : in std_logic_vector(lpm_widthad-1 downto 0);
|
|
wreq : in std_logic := 'Z';
|
|
rreq : in std_logic := 'Z';
|
|
clock : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
-- OUTPUT PORT DECLARATION
|
|
empty : out std_logic;
|
|
full : out std_logic);
|
|
end DCFIFO_FEFIFO;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of DCFIFO_FEFIFO is
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal i_empty : std_logic := '1';
|
|
signal i_full : std_logic := '0';
|
|
|
|
begin
|
|
|
|
-- PROCESS DECLARATION
|
|
process (clock, aclr)
|
|
------ VARIABLE DECLARATION
|
|
variable sm_empty : std_logic_vector(1 downto 0) := "00";
|
|
variable lrreq : std_logic := '0';
|
|
variable almost_full : integer := 0;
|
|
variable usedw_is_1 : boolean := false;
|
|
variable need_init : boolean := true;
|
|
begin
|
|
if (need_init)
|
|
then
|
|
if ((lpm_mode /= "READ") and (lpm_mode /= "WRITE"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! LPM_MODE must be READ or WRITE."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((underflow_checking /= "ON") and (underflow_checking /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! UNDERFLOW_CHECKING must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((overflow_checking /= "ON") and (overflow_checking /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! OVERFLOW_CHECKING must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
if (lpm_numwords >= 3)
|
|
then
|
|
almost_full := lpm_numwords - 3;
|
|
else
|
|
almost_full := 0;
|
|
end if;
|
|
|
|
need_init := false;
|
|
end if; -- need_init
|
|
|
|
if (aclr'event and (aclr = '1'))
|
|
then
|
|
sm_empty := "00";
|
|
lrreq := '0';
|
|
|
|
i_empty <= '1';
|
|
i_full <= '0';
|
|
end if; -- aclr event
|
|
|
|
if (clock'event and (clock = '1') and (aclr = '0') and (NOW > 0 ns))
|
|
then
|
|
if (lpm_mode = "READ")
|
|
then
|
|
case sm_empty is
|
|
-- state_empty
|
|
when "00" =>
|
|
if (usedw_in /= 0)
|
|
then
|
|
sm_empty := "01";
|
|
end if;
|
|
-- state_non_empty
|
|
when "01" =>
|
|
if (lpm_widthad > 1)
|
|
then
|
|
usedw_is_1 := ((usedw_in = 1) and (lrreq = '0')) or ((usedw_in = 2) and (lrreq = '1'));
|
|
else
|
|
usedw_is_1 := (usedw_in = 1) and (lrreq = '0');
|
|
end if;
|
|
|
|
if ((rreq = '1') and usedw_is_1)
|
|
then
|
|
sm_empty := "10";
|
|
end if;
|
|
-- state_emptywait
|
|
when "10" =>
|
|
if (usedw_in > 1)
|
|
then
|
|
sm_empty := "01";
|
|
else
|
|
sm_empty := "00";
|
|
end if;
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Error! Invalid sm_empty state in read mode."
|
|
SEVERITY ERROR;
|
|
end case;
|
|
elsif (lpm_mode = "WRITE")
|
|
then
|
|
case sm_empty is
|
|
-- state_empty
|
|
when "00" =>
|
|
if (wreq = '1')
|
|
then
|
|
sm_empty := "01";
|
|
end if;
|
|
-- state_one
|
|
when "01" =>
|
|
if (wreq = '0')
|
|
then
|
|
sm_empty := "11";
|
|
end if;
|
|
-- state_non_empty
|
|
when "11" =>
|
|
if (wreq = '1')
|
|
then
|
|
sm_empty := "01";
|
|
elsif (usedw_in = 0)
|
|
then
|
|
sm_empty := "00";
|
|
end if;
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Error! Invalid sm_empty state in write mode."
|
|
SEVERITY ERROR;
|
|
end case;
|
|
end if;
|
|
|
|
i_empty <= not sm_empty(0);
|
|
if ((aclr = '0') and (usedw_in >= almost_full) and (NOW > 0 ns))
|
|
then
|
|
i_full <= '1';
|
|
else
|
|
i_full <= '0';
|
|
end if;
|
|
|
|
if (underflow_checking = "OFF")
|
|
then
|
|
lrreq := rreq;
|
|
else
|
|
lrreq := rreq and not i_empty;
|
|
end if;
|
|
end if; -- clock event
|
|
end process; -- clock, aclr events
|
|
|
|
empty <= i_empty;
|
|
full <= i_full;
|
|
|
|
end behavior; -- dcfifo_fefifo
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : dcfifo_async
|
|
--
|
|
-- Description : Asynchoronous Dual Clocks FIFO
|
|
--
|
|
-- Limitation :
|
|
--
|
|
-- Results Expected:
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- BEGINNING OF ENTITY
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use IEEE.std_logic_unsigned.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
use work.DCFIFO_FEFIFO;
|
|
use work.DCFIFO_DFFPIPE;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity DCFIFO_ASYNC is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
lpm_width : natural;
|
|
lpm_widthu : natural;
|
|
lpm_numwords : natural;
|
|
delay_rdusedw : natural := 1;
|
|
delay_wrusedw : natural := 1;
|
|
rdsync_delaypipe : natural := 0;
|
|
wrsync_delaypipe : natural := 0;
|
|
intended_device_family : string := "Stratix";
|
|
lpm_showahead : string := "OFF";
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
use_eab : string := "ON";
|
|
add_ram_output_register : string := "OFF";
|
|
clocks_are_synchronized : string := "FALSE";
|
|
lpm_hint : string := "USE_EAB=ON");
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
data : in std_logic_vector(lpm_width-1 downto 0);
|
|
rdclk : in std_logic;
|
|
wrclk : in std_logic;
|
|
rdreq : in std_logic;
|
|
wrreq : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
-- OUTPUT PORT DECLARATION
|
|
rdempty : out std_logic;
|
|
wrempty : out std_logic;
|
|
rdfull : out std_logic;
|
|
wrfull : out std_logic;
|
|
rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
q : out std_logic_vector(lpm_width-1 downto 0));
|
|
end DCFIFO_ASYNC;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of DCFIFO_ASYNC is
|
|
-- TYPE DECLARATION
|
|
type LPM_MEMORY is array (2**lpm_widthu-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
|
|
type LPM_BOOLEAN is array (2**lpm_widthu-1 downto 0) of boolean;
|
|
type LPM_NATURAL is array (2**lpm_widthu-1 downto 0) of natural;
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant ZEROS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
|
|
constant UNKNOWN : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => 'X');
|
|
constant ZEROU : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
constant GRAY_DELAYPIPE : integer := 1;
|
|
constant WRUSEDW_DELAYPIPE : integer := 1; -- delayed usedw to compute empty/full
|
|
constant RDUSEDW_DELAYPIPE : integer := 1; -- delayed usedw to compute empty/full
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal i_data_tmp : std_logic_vector(lpm_width-1 downto 0);
|
|
signal i_rdptr : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_wrptr : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_wrptr_tmp : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_rdptrrg : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_wrdelaycycle : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_rden : std_logic := '0';
|
|
signal i_wren : std_logic := '0';
|
|
signal i_rdenclock : std_logic := '0';
|
|
signal i_wren_tmp : std_logic := '0';
|
|
signal i_rdempty : std_logic := '1';
|
|
signal i_wrempty : std_logic := '1';
|
|
signal i_rdfull : std_logic := '0';
|
|
signal i_wrfull : std_logic := '0';
|
|
signal i_rdusedw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_wrusedw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_ws_nbrp : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_rs_nbwp : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_ws_dbrp : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_rs_dbwp : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_wr_udwn : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_rd_udwn : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_wr_dbuw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_rd_dbuw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_q_tmp : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
|
|
signal i_showahead_flag : std_logic := '0';
|
|
signal i_showahead_flag1 : std_logic := '0';
|
|
signal i_showahead_flag2 : std_logic := '0';
|
|
signal i_showahead_flag3 : std_logic := '0';
|
|
signal i_data_ready : LPM_BOOLEAN := (OTHERS => false);
|
|
signal i_data_delay_count : LPM_NATURAL := (OTHERS => 0);
|
|
signal i_zero : std_logic := '0';
|
|
|
|
|
|
-- COMPONENT DECLARATION
|
|
component DCFIFO_FEFIFO
|
|
generic (
|
|
lpm_widthad : natural;
|
|
lpm_numwords : natural;
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
lpm_mode : string);
|
|
port (
|
|
usedw_in : in std_logic_vector(lpm_widthad-1 downto 0);
|
|
wreq : in std_logic := 'Z';
|
|
rreq : in std_logic := 'Z';
|
|
clock : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
empty : out std_logic;
|
|
full : out std_logic);
|
|
end component;
|
|
|
|
component DCFIFO_DFFPIPE
|
|
generic (
|
|
lpm_delay : natural;
|
|
lpm_width : natural);
|
|
port (
|
|
d : in std_logic_vector(lpm_width-1 downto 0);
|
|
clock : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
q : out std_logic_vector(lpm_width-1 downto 0));
|
|
end component;
|
|
|
|
begin
|
|
-- COMPONENT ASSIGNMENTS
|
|
-- Delays & DFF Pipes
|
|
DP_RDPTR_D: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => 0,
|
|
lpm_width => lpm_widthu)
|
|
port map (
|
|
d => i_rdptr,
|
|
clock => i_rdenclock,
|
|
aclr => aclr,
|
|
q => i_rdptrrg);
|
|
|
|
DP_WRPTR_D: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => 1,
|
|
lpm_width => lpm_widthu)
|
|
port map (
|
|
d => i_wrptr,
|
|
clock => wrclk,
|
|
aclr => aclr,
|
|
q => i_wrdelaycycle);
|
|
|
|
DP_WS_NBRP: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => WRSYNC_DELAYPIPE,
|
|
lpm_width => lpm_widthu)
|
|
port map (
|
|
d => i_rdptrrg,
|
|
clock => wrclk,
|
|
aclr => aclr,
|
|
q => i_ws_nbrp);
|
|
|
|
DP_RS_NBWP: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => RDSYNC_DELAYPIPE,
|
|
lpm_width => lpm_widthu)
|
|
port map (
|
|
d => i_wrdelaycycle,
|
|
clock => rdclk,
|
|
aclr => aclr,
|
|
q => i_rs_nbwp);
|
|
|
|
DP_WS_DBRP: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => GRAY_DELAYPIPE,
|
|
lpm_width => lpm_widthu)
|
|
port map (
|
|
d => i_ws_nbrp,
|
|
clock => wrclk,
|
|
aclr => aclr,
|
|
q => i_ws_dbrp);
|
|
|
|
DP_RS_DBWP: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => GRAY_DELAYPIPE,
|
|
lpm_width => lpm_widthu)
|
|
port map (
|
|
d => i_rs_nbwp,
|
|
clock => rdclk,
|
|
aclr => aclr,
|
|
q => i_rs_dbwp);
|
|
|
|
DP_WR_USEDW: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => DELAY_WRUSEDW,
|
|
lpm_width => lpm_widthu)
|
|
port map (
|
|
d => i_wr_udwn,
|
|
clock => wrclk,
|
|
aclr => aclr,
|
|
q => i_wrusedw);
|
|
|
|
DP_RD_USEDW: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => DELAY_RDUSEDW,
|
|
lpm_width => lpm_widthu)
|
|
port map (
|
|
d => i_rd_udwn,
|
|
clock => rdclk,
|
|
aclr => aclr,
|
|
q => i_rdusedw);
|
|
|
|
DP_WR_DBUW: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => WRUSEDW_DELAYPIPE,
|
|
lpm_width => lpm_widthu)
|
|
port map (
|
|
d => i_wr_udwn,
|
|
clock => wrclk,
|
|
aclr => aclr,
|
|
q => i_wr_dbuw);
|
|
|
|
DP_RD_DBUW: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => RDUSEDW_DELAYPIPE,
|
|
lpm_width => lpm_widthu)
|
|
port map (
|
|
d => i_rd_udwn,
|
|
clock => rdclk,
|
|
aclr => aclr,
|
|
q => i_rd_dbuw);
|
|
|
|
-- Empty/Full
|
|
WR_FE: DCFIFO_FEFIFO
|
|
generic map (
|
|
lpm_widthad => lpm_widthu,
|
|
lpm_numwords => lpm_numwords,
|
|
underflow_checking => UNDERFLOW_CHECKING,
|
|
overflow_checking => OVERFLOW_CHECKING,
|
|
lpm_mode => "WRITE")
|
|
port map (
|
|
usedw_in => i_wr_dbuw,
|
|
wreq => wrreq,
|
|
rreq => i_zero,
|
|
clock => wrclk,
|
|
aclr => aclr,
|
|
empty => i_wrempty,
|
|
full => i_wrfull);
|
|
|
|
RD_FE: DCFIFO_FEFIFO
|
|
generic map (
|
|
lpm_widthad => lpm_widthu,
|
|
lpm_numwords => lpm_numwords,
|
|
underflow_checking => underflow_checking,
|
|
overflow_checking => overflow_checking,
|
|
lpm_mode => "READ")
|
|
port map (
|
|
usedw_in => i_rd_dbuw,
|
|
wreq => i_zero,
|
|
rreq => rdreq,
|
|
clock => rdclk,
|
|
aclr => aclr,
|
|
empty => i_rdempty,
|
|
full => i_rdfull);
|
|
|
|
-- PROCESS DECLARATION
|
|
-- FIFOram
|
|
process (wrclk, rdclk, aclr, i_showahead_flag)
|
|
------ VARIABLE DECLARATION
|
|
variable max_widthu : integer := 0;
|
|
variable max_widthu_minus_one : integer := 0;
|
|
variable mem_data : LPM_MEMORY := (OTHERS => ZEROS);
|
|
variable mem_data2 : LPM_MEMORY := (OTHERS => ZEROS);
|
|
variable wrptr_tmp : integer := 0;
|
|
variable rdptr_tmp : integer := 0;
|
|
variable need_init : boolean := true;
|
|
begin
|
|
if (need_init) then
|
|
if ((lpm_showahead /= "ON") and (lpm_showahead /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! LPM_SHOWAHEAD must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((underflow_checking /= "ON") and (underflow_checking /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! UNDERFLOW_CHECKING must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((overflow_checking /= "ON") and (overflow_checking /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! OVERFLOW_CHECKING must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((use_eab /= "ON") and (use_eab /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! USE_EAB must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((add_ram_output_register /= "ON") and (add_ram_output_register /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! ADD_RAM_OUTPUT_REGISTER must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if (IS_VALID_FAMILY(intended_device_family) = false) then
|
|
ASSERT FALSE
|
|
REPORT "Error! Illegal INTENDED_DEVICE_FAMILY."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
max_widthu := 2 ** lpm_widthu;
|
|
max_widthu_minus_one := (2 ** lpm_widthu) - 1;
|
|
|
|
for i in lpm_numwords - 1 downto 0 loop
|
|
mem_data(i) := ZEROS;
|
|
end loop;
|
|
|
|
if ((add_ram_output_register = "OFF") and
|
|
(FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
|
|
then
|
|
for i in 0 to max_widthu_minus_one loop
|
|
mem_data2(i) := UNKNOWN;
|
|
end loop;
|
|
else
|
|
for i in 0 to max_widthu_minus_one loop
|
|
mem_data2(i) := ZEROS;
|
|
end loop;
|
|
end if;
|
|
|
|
need_init := false;
|
|
end if; -- need_init
|
|
|
|
if (aclr'event and (aclr = '1'))
|
|
then
|
|
i_rdptr <= ZEROU;
|
|
i_wrptr <= ZEROU;
|
|
if (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or
|
|
(use_eab = "OFF"))
|
|
then
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
i_q_tmp <= mem_data(0);
|
|
else
|
|
i_q_tmp <= ZEROS;
|
|
end if;
|
|
elsif ((add_ram_output_register = "ON") and
|
|
(FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
|
|
then
|
|
if (lpm_showahead = "OFF")
|
|
then
|
|
i_q_tmp <= ZEROS;
|
|
else
|
|
i_q_tmp <= UNKNOWN;
|
|
|
|
for i in 0 to max_widthu_minus_one loop
|
|
i_data_ready(i) <= false;
|
|
i_data_delay_count(i) <= 0;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end if; -- aclr event
|
|
|
|
if (wrclk'event and (wrclk = '1'))
|
|
then
|
|
if ((aclr = '1') and (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or
|
|
(add_ram_output_register = "ON") or (use_eab = "OFF")))
|
|
then
|
|
i_data_tmp <= ZEROS;
|
|
i_wrptr_tmp <= ZEROU;
|
|
i_wren_tmp <= '0';
|
|
elsif (NOW > 0 ns)
|
|
then
|
|
i_data_tmp <= data;
|
|
i_wrptr_tmp <= i_wrptr;
|
|
i_wren_tmp <= i_wren;
|
|
|
|
if (i_wren = '1')
|
|
then
|
|
if ((aclr = '0') and (i_wrptr < max_widthu_minus_one))
|
|
then
|
|
i_wrptr <= i_wrptr + 1;
|
|
else
|
|
i_wrptr <= ZEROU;
|
|
end if;
|
|
|
|
if (use_eab = "OFF")
|
|
then
|
|
mem_data(CONV_INTEGER(i_wrptr) mod max_widthu) := data;
|
|
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod max_widthu);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if (wrclk'event and (wrclk = '0'))
|
|
then
|
|
if ((use_eab = "ON") and (NOW > 0 ns))
|
|
then
|
|
if (i_wren_tmp = '1')
|
|
then
|
|
wrptr_tmp := CONV_INTEGER(i_wrptr_tmp) mod max_widthu;
|
|
mem_data(wrptr_tmp) := i_data_tmp;
|
|
i_data_ready(wrptr_tmp) <= false;
|
|
end if;
|
|
|
|
if ((lpm_showahead = "ON") and
|
|
(not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family))))
|
|
then
|
|
i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod max_widthu);
|
|
end if;
|
|
end if;
|
|
end if; -- wrclk'event and (wrclk = '0')
|
|
|
|
if ((rdclk'event) and (rdclk = '1') and (NOW > 0 ns))
|
|
then
|
|
if ((lpm_showahead = "ON") and (add_ram_output_register = "ON") and
|
|
(FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
|
|
then
|
|
for i in 0 to max_widthu_minus_one loop
|
|
if (i_data_ready(i) = false)
|
|
then
|
|
i_data_delay_count(i) <= i_data_delay_count(i) + 1;
|
|
end if;
|
|
|
|
if (i_data_delay_count(i) = (rdsync_delaypipe+2))
|
|
then
|
|
i_data_ready(i) <= true;
|
|
i_data_delay_count(i) <= 0;
|
|
end if;
|
|
end loop;
|
|
|
|
if (aclr = '0')
|
|
then
|
|
i_showahead_flag3 <= '1';
|
|
end if;
|
|
end if;
|
|
|
|
if ((aclr = '1') and (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or (use_eab = "OFF")))
|
|
then
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
i_q_tmp <= mem_data(0);
|
|
else
|
|
i_q_tmp <= ZEROS;
|
|
end if;
|
|
elsif ((aclr = '1') and (add_ram_output_register = "ON") and
|
|
(FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
|
|
then
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
i_q_tmp <= UNKNOWN;
|
|
else
|
|
i_q_tmp <= ZEROS;
|
|
end if;
|
|
elsif ((i_rden = '1') and (NOW > 0 ns))
|
|
then
|
|
if ((aclr = '0') and (i_rdptr < max_widthu_minus_one))
|
|
then
|
|
i_rdptr <= i_rdptr + 1;
|
|
else
|
|
i_rdptr <= ZEROU;
|
|
end if;
|
|
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
if ((add_ram_output_register = "ON") and
|
|
(FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
|
|
then
|
|
i_showahead_flag3 <= '1';
|
|
else
|
|
i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr + 1) mod max_widthu);
|
|
end if;
|
|
else
|
|
i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod max_widthu);
|
|
end if;
|
|
end if;
|
|
end if; -- (rdclk'event) and (rdclk = '1')
|
|
|
|
if (i_showahead_flag'event and (i_showahead_flag = '1'))
|
|
then
|
|
if ((lpm_showahead = "ON") and (add_ram_output_register = "ON") and
|
|
(FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
|
|
then
|
|
if (i_rdempty = '0')
|
|
then
|
|
rdptr_tmp := CONV_INTEGER(i_rdptr) mod max_widthu;
|
|
if (i_data_ready(rdptr_tmp) = true)
|
|
then
|
|
i_q_tmp <= mem_data(rdptr_tmp);
|
|
mem_data2(rdptr_tmp) := mem_data(rdptr_tmp);
|
|
else
|
|
i_q_tmp <= mem_data2(rdptr_tmp);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
i_showahead_flag3 <= '0';
|
|
end if;
|
|
|
|
end process; -- aclr, wrclk, rdclk events
|
|
|
|
process (i_showahead_flag3)
|
|
begin
|
|
i_showahead_flag2 <= i_showahead_flag3;
|
|
end process;
|
|
|
|
process (i_showahead_flag2)
|
|
begin
|
|
i_showahead_flag1 <= i_showahead_flag2;
|
|
end process;
|
|
|
|
process (i_showahead_flag1)
|
|
begin
|
|
i_showahead_flag <= i_showahead_flag1;
|
|
end process;
|
|
|
|
i_rden <= rdreq when underflow_checking = "OFF" else
|
|
rdreq and not i_rdempty;
|
|
i_wren <= wrreq when overflow_checking = "OFF" else
|
|
wrreq and not i_wrfull;
|
|
|
|
-- Delays & DFF Pipes
|
|
process (rdclk)
|
|
begin
|
|
if (rdclk'event and (rdclk = '0'))
|
|
then
|
|
i_rdenclock <= '0';
|
|
elsif (rdclk'event and (rdclk = '1'))
|
|
then
|
|
if (i_rden = '1')
|
|
then
|
|
i_rdenclock <= '1';
|
|
end if;
|
|
end if;
|
|
end process; -- rdclk event
|
|
|
|
process (i_wrptr, i_ws_dbrp)
|
|
begin
|
|
if (NOW > 0 ns)
|
|
then
|
|
i_wr_udwn <= i_wrptr - i_ws_dbrp;
|
|
end if;
|
|
end process; -- i_wrptr, i_ws_dbrp events
|
|
|
|
process (i_rdptr, i_rs_dbwp)
|
|
begin
|
|
if (NOW > 0 ns)
|
|
then
|
|
i_rd_udwn <= i_rs_dbwp - i_rdptr;
|
|
end if;
|
|
end process; -- i_rdptr, i_rs_dbwp events
|
|
|
|
-- Outputs
|
|
rdempty <= i_rdempty;
|
|
rdfull <= i_rdfull;
|
|
wrempty <= i_wrempty;
|
|
wrfull <= i_wrfull;
|
|
rdusedw <= i_rdusedw;
|
|
wrusedw <= i_wrusedw;
|
|
q <= i_q_tmp;
|
|
|
|
end behavior; -- dcfifo_async
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : dcfifo_sync
|
|
--
|
|
-- Description : Synchronous Dual Clocks FIFO
|
|
--
|
|
-- Limitation :
|
|
--
|
|
-- Results Expected:
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- BEGINNING OF ENTITY
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use IEEE.std_logic_unsigned.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
use work.DCFIFO_DFFPIPE;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity DCFIFO_SYNC is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
lpm_width : natural;
|
|
lpm_widthu : natural;
|
|
lpm_numwords : natural;
|
|
intended_device_family : string := "Stratix";
|
|
lpm_showahead : string := "OFF";
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
use_eab : string := "ON";
|
|
add_ram_output_register : string := "OFF");
|
|
|
|
-- PORT DECLARATION
|
|
port
|
|
(
|
|
-- INPUT PORT DECLARATION
|
|
data : in std_logic_vector(lpm_width-1 downto 0);
|
|
rdclk : in std_logic;
|
|
wrclk : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
rdreq : in std_logic;
|
|
wrreq : in std_logic;
|
|
-- OUTPUT PORT DECLARATION
|
|
rdfull : out std_logic;
|
|
wrfull : out std_logic;
|
|
rdempty : out std_logic;
|
|
wrempty : out std_logic;
|
|
rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
q : out std_logic_vector(lpm_width-1 downto 0));
|
|
end DCFIFO_SYNC;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of DCFIFO_SYNC is
|
|
-- TYPE DECLARATION
|
|
type LPM_MEMORY is array (2**lpm_widthu-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant ZEROS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
|
|
constant ZEROU : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal i_data_tmp : std_logic_vector(lpm_width-1 downto 0);
|
|
signal i_rdptr : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
|
|
signal i_wrptr : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
|
|
signal i_wrptr_tmp : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
|
|
signal i_rdptr_s : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
|
|
signal i_wrptr_r : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
|
|
signal i_wrptr_s : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
|
|
signal i_rdempty : std_logic := '1';
|
|
signal i_wrempty : std_logic := '1';
|
|
signal i_rdfull : std_logic := '0';
|
|
signal i_wrfull : std_logic := '0';
|
|
signal i_rden : std_logic := '0';
|
|
signal i_wren : std_logic := '0';
|
|
signal i_wren_tmp : std_logic := '0';
|
|
signal i_rdusedw : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
|
|
signal i_wrusedw : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
|
|
signal i_q_tmp : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
|
|
signal i_cnt_mod : natural := 0;
|
|
signal i_max_widthu : natural := 0;
|
|
|
|
-- COMPONENT DECLARATION
|
|
component DCFIFO_DFFPIPE
|
|
generic (
|
|
lpm_delay : natural;
|
|
lpm_width : natural);
|
|
port (
|
|
d : in std_logic_vector(LPM_WIDTH-1 downto 0);
|
|
clock : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
q : out std_logic_vector(LPM_WIDTH-1 downto 0));
|
|
end component;
|
|
|
|
begin
|
|
-- Delays
|
|
RDPTR_D: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => 1,
|
|
lpm_width => lpm_widthu + 1)
|
|
port map (
|
|
d => i_rdptr,
|
|
clock => wrclk,
|
|
aclr => aclr,
|
|
q => i_rdptr_s);
|
|
|
|
WRPTR_D: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => 1,
|
|
lpm_width => lpm_widthu + 1)
|
|
port map (
|
|
d => i_wrptr,
|
|
clock => wrclk,
|
|
aclr => aclr,
|
|
q => i_wrptr_r);
|
|
|
|
WRPTR_E: DCFIFO_DFFPIPE
|
|
generic map (
|
|
lpm_delay => 1,
|
|
lpm_width => lpm_widthu + 1)
|
|
port map (
|
|
d => i_wrptr_r,
|
|
clock => rdclk,
|
|
aclr => aclr,
|
|
q => i_wrptr_s);
|
|
|
|
-- PROCESS DECLARATION
|
|
-- FIFOram
|
|
process (aclr, wrclk, rdclk)
|
|
variable need_init : boolean := true;
|
|
variable mem_data : LPM_MEMORY := (OTHERS => ZEROS);
|
|
begin
|
|
if (need_init) then
|
|
if ((lpm_showahead /= "ON") and (lpm_showahead /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! LPM_SHOWAHEAD must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((underflow_checking /= "ON") and (underflow_checking /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! UNDERFLOW_CHECKING must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((overflow_checking /= "ON") and (overflow_checking /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! OVERFLOW_CHECKING must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((use_eab /= "ON") and (use_eab /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! USE_EAB must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if (lpm_numwords > 2 ** lpm_widthu)
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! LPM_NUMWORDS must be less than or equal to 2**LPM_WIDTHU."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((add_ram_output_register /= "ON") and (add_ram_output_register /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! ADD_RAM_OUTPUT_REGISTER must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if (IS_VALID_FAMILY(intended_device_family) = false) then
|
|
ASSERT FALSE
|
|
REPORT "Error! Illegal INTENDED_DEVICE_FAMILY."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
for i in lpm_numwords-1 downto 0 loop
|
|
mem_data(i) := ZEROS;
|
|
end loop;
|
|
|
|
if (lpm_numwords = 2 ** lpm_widthu)
|
|
then
|
|
i_cnt_mod <= 2 ** (lpm_widthu + 1);
|
|
else
|
|
i_cnt_mod <= 2 ** lpm_widthu;
|
|
end if;
|
|
|
|
i_max_widthu <= 2 ** lpm_widthu;
|
|
|
|
need_init := false;
|
|
end if; -- need_init
|
|
|
|
if (aclr'event and (aclr = '1'))
|
|
then
|
|
i_rdptr <= ZEROU;
|
|
i_wrptr <= ZEROU;
|
|
if (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or
|
|
((add_ram_output_register = "ON") and (use_eab = "OFF")))
|
|
then
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
if ((FEATURE_FAMILY_STRATIXII(intended_device_family)) or
|
|
(FEATURE_FAMILY_CYCLONEII(intended_device_family)))
|
|
then
|
|
i_q_tmp <= (OTHERS => 'X');
|
|
else
|
|
i_q_tmp <= mem_data(0);
|
|
end if;
|
|
else
|
|
i_q_tmp <= ZEROS;
|
|
end if;
|
|
end if;
|
|
end if; -- aclr event
|
|
|
|
if (wrclk'event and (wrclk = '1'))
|
|
then
|
|
if ((aclr = '1') and (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or
|
|
((add_ram_output_register = "ON") and (use_eab = "OFF"))))
|
|
then
|
|
i_data_tmp <= ZEROS;
|
|
i_wrptr_tmp <= ZEROU;
|
|
i_wren_tmp <= '0';
|
|
elsif (NOW > 0 ns)
|
|
then
|
|
i_data_tmp <= data;
|
|
i_wrptr_tmp <= i_wrptr;
|
|
i_wren_tmp <= i_wren;
|
|
|
|
if (i_wren = '1')
|
|
then
|
|
if ((aclr = '0') and (i_wrptr < i_cnt_mod - 1))
|
|
then
|
|
i_wrptr <= i_wrptr + 1;
|
|
else
|
|
i_wrptr <= ZEROU;
|
|
end if;
|
|
|
|
if (use_eab = "OFF")
|
|
then
|
|
mem_data(CONV_INTEGER(i_wrptr) mod i_max_widthu) := data;
|
|
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod i_max_widthu);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if; -- wrclk'event and (wrclk = '1')
|
|
|
|
if (wrclk'event and (wrclk = '0'))
|
|
then
|
|
if((use_eab = "ON") and (NOW > 0 ns))
|
|
then
|
|
if (i_wren_tmp = '1')
|
|
then
|
|
mem_data(CONV_INTEGER(i_wrptr_tmp) mod i_max_widthu) := i_data_tmp;
|
|
end if;
|
|
|
|
if ((lpm_showahead = "ON") and
|
|
(not(FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family))))
|
|
then
|
|
i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod i_max_widthu);
|
|
end if;
|
|
end if;
|
|
end if; -- wrclk'event and (wrclk = '0')
|
|
|
|
if (rdclk'event and (rdclk = '1'))
|
|
then
|
|
if ((aclr = '1') and (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or
|
|
((add_ram_output_register = "ON") and (use_eab = "OFF"))))
|
|
then
|
|
if (lpm_showahead = "ON")
|
|
then
|
|
if ((FEATURE_FAMILY_STRATIXII(intended_device_family)) or
|
|
(FEATURE_FAMILY_CYCLONEII(intended_device_family)))
|
|
then
|
|
i_q_tmp <= (OTHERS => 'X');
|
|
else
|
|
i_q_tmp <= mem_data(0);
|
|
end if;
|
|
else
|
|
i_q_tmp <= ZEROS;
|
|
end if;
|
|
elsif ((i_rden = '1') and (NOW > 0 ns))
|
|
then
|
|
if ((aclr = '0') and (i_rdptr < i_cnt_mod - 1))
|
|
then
|
|
i_rdptr <= i_rdptr + 1;
|
|
else
|
|
i_rdptr <= ZEROU;
|
|
end if;
|
|
|
|
if ((lpm_showahead = "ON") and (not ((use_eab = "ON") and
|
|
(FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
|
|
FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))))
|
|
then
|
|
i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr + 1) mod i_max_widthu);
|
|
else
|
|
i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod i_max_widthu);
|
|
end if;
|
|
end if;
|
|
end if; -- rdclk'event and (rdclk = '1')
|
|
end process; -- aclr, wrclk, rdclk events
|
|
|
|
i_rden <= rdreq when (underflow_checking = "OFF")
|
|
else
|
|
rdreq and not i_rdempty;
|
|
|
|
i_wren <= wrreq when (overflow_checking = "OFF")
|
|
else
|
|
wrreq and not i_wrfull;
|
|
|
|
-- Usedw/Empty/Full
|
|
process (i_rdptr, i_wrptr_s, i_cnt_mod)
|
|
begin
|
|
if (NOW > 0 ns)
|
|
then
|
|
if (CONV_INTEGER (i_wrptr_s) >= CONV_INTEGER (i_rdptr))
|
|
then
|
|
i_rdusedw <= i_wrptr_s - i_rdptr;
|
|
else
|
|
i_rdusedw <= i_wrptr_s + i_cnt_mod - i_rdptr;
|
|
end if;
|
|
end if;
|
|
end process; -- i_rdusedw event
|
|
|
|
process (i_wrptr, i_rdptr_s, i_cnt_mod)
|
|
begin
|
|
if (NOW > 0 ns)
|
|
then
|
|
if (CONV_INTEGER (i_wrptr) >= CONV_INTEGER (i_rdptr_s))
|
|
then
|
|
i_wrusedw <= i_wrptr - i_rdptr_s;
|
|
else
|
|
i_wrusedw <= i_wrptr + i_cnt_mod - i_rdptr_s;
|
|
end if;
|
|
end if;
|
|
end process; -- i_wrusedw event
|
|
|
|
process (i_rdusedw, i_max_widthu)
|
|
begin
|
|
if (i_rdusedw = 0)
|
|
then
|
|
i_rdempty <= '1';
|
|
else
|
|
i_rdempty <= '0';
|
|
end if;
|
|
|
|
if ((lpm_numwords = i_max_widthu) and (i_rdusedw >= i_max_widthu)) or
|
|
((lpm_numwords < i_max_widthu) and (i_rdusedw = lpm_numwords))
|
|
then
|
|
i_rdfull <= '1';
|
|
else
|
|
i_rdfull <= '0';
|
|
end if;
|
|
end process; -- i_rdempty and i_rdfull event
|
|
|
|
process (i_wrusedw, i_max_widthu)
|
|
begin
|
|
if (i_wrusedw = 0)
|
|
then
|
|
i_wrempty <= '1';
|
|
else
|
|
i_wrempty <= '0';
|
|
end if;
|
|
|
|
if ((lpm_numwords = i_max_widthu) and (i_wrusedw >= i_max_widthu)) or
|
|
((lpm_numwords < i_max_widthu) and (i_wrusedw = lpm_numwords))
|
|
then
|
|
i_wrfull <= '1';
|
|
else
|
|
i_wrfull <= '0';
|
|
end if;
|
|
end process; -- i_wrempty and i_wrfull event
|
|
|
|
-- Outputs
|
|
rdfull <= i_rdfull;
|
|
wrfull <= i_wrfull;
|
|
rdempty <= i_rdempty;
|
|
wrempty <= i_wrempty;
|
|
rdusedw <= i_rdusedw (lpm_widthu-1 downto 0);
|
|
wrusedw <= i_wrusedw (lpm_widthu-1 downto 0);
|
|
q <= i_q_tmp;
|
|
|
|
end behavior; -- dcfifo_sync
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : dcfifo_low_latency
|
|
--
|
|
-- Description : Dual Clocks FIFO with lowest latency. This fifo implements
|
|
-- the fifo behavior for Stratix II, Cyclone II, Stratix III,
|
|
-- Cyclone III and Stratix showahead area mode (LPM_SHOWAHEAD=
|
|
-- ON, ADD_RAM_OUTPUT_REGISTER=OFF)
|
|
--
|
|
-- Limitation :
|
|
--
|
|
-- Results Expected:
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- BEGINNING OF ENTITY
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use IEEE.std_logic_unsigned.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
use work.DCFIFO_DFFPIPE;
|
|
use work.ALTERA_MF_HINT_EVALUATION.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity DCFIFO_LOW_LATENCY is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
lpm_width : natural;
|
|
lpm_widthu : natural;
|
|
lpm_width_r : natural;
|
|
lpm_widthu_r : natural;
|
|
lpm_numwords : natural;
|
|
delay_rdusedw : natural := 2;
|
|
delay_wrusedw : natural := 2;
|
|
rdsync_delaypipe : natural := 0;
|
|
wrsync_delaypipe : natural := 0;
|
|
intended_device_family : string := "Stratix";
|
|
lpm_showahead : string := "OFF";
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
add_usedw_msb_bit : string := "OFF";
|
|
read_aclr_synch : string := "OFF";
|
|
write_aclr_synch : string := "OFF";
|
|
lpm_hint : string := "USE_EAB=ON");
|
|
|
|
-- PORT DECLARATION
|
|
port
|
|
(
|
|
-- INPUT PORT DECLARATION
|
|
data : in std_logic_vector(lpm_width-1 downto 0);
|
|
rdclk : in std_logic;
|
|
wrclk : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
rdreq : in std_logic;
|
|
wrreq : in std_logic;
|
|
-- OUTPUT PORT DECLARATION
|
|
rdfull : out std_logic;
|
|
wrfull : out std_logic;
|
|
rdempty : out std_logic;
|
|
wrempty : out std_logic;
|
|
rdusedw : out std_logic_vector(lpm_widthu_r-1 downto 0);
|
|
wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
q : out std_logic_vector(lpm_width_r-1 downto 0));
|
|
end DCFIFO_LOW_LATENCY;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of DCFIFO_LOW_LATENCY is
|
|
|
|
-- FUNCTION DECLARATION
|
|
function get_delay_rdusedw (constant i_input_delay_rdusedw : in natural)
|
|
return natural is
|
|
variable i_delay_rdusedw : natural;
|
|
begin
|
|
if (i_input_delay_rdusedw > 2)
|
|
then
|
|
i_delay_rdusedw := 2;
|
|
else
|
|
i_delay_rdusedw := i_input_delay_rdusedw;
|
|
end if;
|
|
|
|
return i_delay_rdusedw;
|
|
|
|
end get_delay_rdusedw;
|
|
|
|
function get_delay_wrusedw (constant i_input_delay_wrusedw : in natural)
|
|
return natural is
|
|
variable i_delay_wrusedw : natural;
|
|
begin
|
|
if (i_input_delay_wrusedw > 2)
|
|
then
|
|
i_delay_wrusedw := 2;
|
|
else
|
|
i_delay_wrusedw := i_input_delay_wrusedw;
|
|
end if;
|
|
|
|
return i_delay_wrusedw;
|
|
|
|
end get_delay_wrusedw;
|
|
|
|
function STR_TO_INT ( str : string ) return integer is
|
|
variable ivalue : integer := 0;
|
|
variable digit : integer := 0;
|
|
begin
|
|
for i in str'left to str'right loop
|
|
case str(i) is
|
|
when '0' =>
|
|
digit := 0;
|
|
when '1' =>
|
|
digit := 1;
|
|
when '2' =>
|
|
digit := 2;
|
|
when '3' =>
|
|
digit := 3;
|
|
when '4' =>
|
|
digit := 4;
|
|
when '5' =>
|
|
digit := 5;
|
|
when '6' =>
|
|
digit := 6;
|
|
when '7' =>
|
|
digit := 7;
|
|
when '8' =>
|
|
digit := 8;
|
|
when '9' =>
|
|
digit := 9;
|
|
when others =>
|
|
ASSERT FALSE
|
|
REPORT "Illegal Character "& str(i) & "in string parameter! "
|
|
SEVERITY ERROR;
|
|
end case;
|
|
ivalue := ivalue * 10 + digit;
|
|
end loop;
|
|
return ivalue;
|
|
end STR_TO_INT;
|
|
|
|
function is_wrempty_speed (constant i_maximize_speed : in string)
|
|
return boolean is
|
|
begin
|
|
if (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))
|
|
then
|
|
return true;
|
|
elsif (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family))
|
|
then
|
|
if ((STR_TO_INT(i_maximize_speed) > 5) or
|
|
(wrsync_delaypipe >= 2))
|
|
then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
else
|
|
return false;
|
|
end if;
|
|
end is_wrempty_speed;
|
|
|
|
function is_rdfull_speed (constant i_maximize_speed : in string)
|
|
return boolean is
|
|
begin
|
|
if (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))
|
|
then
|
|
return true;
|
|
elsif (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family))
|
|
then
|
|
if ((STR_TO_INT(i_maximize_speed) > 5) or
|
|
(rdsync_delaypipe >= 2))
|
|
then
|
|
return true;
|
|
else
|
|
return false;
|
|
end if;
|
|
else
|
|
return false;
|
|
end if;
|
|
end is_rdfull_speed;
|
|
|
|
function get_cnt_mod (constant i_intended_device_family : in string)
|
|
return natural is
|
|
begin
|
|
if (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(i_intended_device_family))
|
|
then
|
|
if (add_usedw_msb_bit = "OFF")
|
|
then
|
|
if (lpm_width_r > lpm_width)
|
|
then
|
|
return (2 ** lpm_widthu) + lpm_width_r/lpm_width;
|
|
else
|
|
return (2 ** lpm_widthu) + 1;
|
|
end if;
|
|
else
|
|
if (lpm_width_r > lpm_width)
|
|
then
|
|
return (2 ** (lpm_widthu-1)) + lpm_width_r/lpm_width;
|
|
else
|
|
return (2 ** (lpm_widthu-1)) + 1;
|
|
end if;
|
|
end if;
|
|
else
|
|
return 2 ** lpm_widthu;
|
|
end if;
|
|
end get_cnt_mod;
|
|
|
|
function get_cnt_mod_r (constant i_intended_device_family : in string)
|
|
return natural is
|
|
begin
|
|
if (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(i_intended_device_family))
|
|
then
|
|
if (add_usedw_msb_bit = "OFF")
|
|
then
|
|
if (lpm_width_r > lpm_width)
|
|
then
|
|
return (2 ** lpm_widthu_r) + 1;
|
|
else
|
|
return (2 ** lpm_widthu_r) + lpm_width/lpm_width_r;
|
|
end if;
|
|
else
|
|
if (lpm_width_r > lpm_width)
|
|
then
|
|
return (2 ** (lpm_widthu_r-1)) + 1;
|
|
else
|
|
return (2 ** (lpm_widthu_r-1)) + lpm_width/lpm_width_r;
|
|
end if;
|
|
end if;
|
|
else
|
|
return 2 ** lpm_widthu_r;
|
|
end if;
|
|
end get_cnt_mod_r;
|
|
|
|
function get_width_ratio (constant L, R : natural) return natural is
|
|
begin
|
|
if L > R then
|
|
return L/R;
|
|
else
|
|
return R/L;
|
|
end if;
|
|
end get_width_ratio;
|
|
|
|
function get_fifo_depth (constant widthu_r : natural) return natural is
|
|
begin
|
|
if (add_usedw_msb_bit = "OFF")
|
|
then
|
|
return widthu_r;
|
|
else
|
|
return widthu_r -1;
|
|
end if;
|
|
end get_fifo_depth;
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant ZEROS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
|
|
constant ZEROU : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
|
|
constant ZEROS_R : std_logic_vector(lpm_width_r-1 downto 0) := (OTHERS => '0');
|
|
constant ZEROU_R : std_logic_vector(lpm_widthu_r+1 downto 0) := (OTHERS => '0');
|
|
constant MAXIMIZE_SPEED : string := GET_PARAMETER_VALUE(lpm_hint, "MAXIMIZE_SPEED");
|
|
constant USE_WREMPTY_SPEED : boolean := is_wrempty_speed(MAXIMIZE_SPEED);
|
|
constant USE_RDFULL_SPEED : boolean := is_rdfull_speed(MAXIMIZE_SPEED);
|
|
constant CNT_MOD : natural := get_cnt_mod(intended_device_family);
|
|
constant CNT_MOD_R : natural := get_cnt_mod_r(intended_device_family);
|
|
constant WIDTH_RATIO : natural := get_width_ratio(lpm_width, lpm_width_r);
|
|
constant FIFO_DEPTH : natural := get_fifo_depth(lpm_widthu_r);
|
|
constant USE_SYNC_READ_ACLR : boolean := (FEATURE_FAMILY_STRATIXIII(intended_device_family) or
|
|
FEATURE_FAMILY_CYCLONEIII(intended_device_family)) and
|
|
(read_aclr_synch = "ON");
|
|
constant USE_SYNC_WRITE_ACLR : boolean := (FEATURE_FAMILY_STRATIXII(intended_device_family) or
|
|
FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
|
|
(write_aclr_synch = "ON");
|
|
|
|
-- TYPE DECLARATION
|
|
type LPM_MEMORY is array (2**(FIFO_DEPTH)+ WIDTH_RATIO downto 0) of std_logic_vector(lpm_width_r-1 downto 0);
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal mem_data : LPM_MEMORY := (OTHERS => ZEROS_R);
|
|
signal i_rdptr_g : std_logic_vector(lpm_widthu_r+1 downto 0) := (OTHERS => '0');
|
|
signal i_rdptr_g1p : std_logic_vector(lpm_widthu_r+1 downto 0) := CONV_STD_LOGIC_VECTOR(1, lpm_widthu_r+2);
|
|
signal i_wrptr_g : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
|
|
signal i_wrptr_g1 : std_logic_vector(lpm_widthu+1 downto 0) := CONV_STD_LOGIC_VECTOR(1, lpm_widthu+2);
|
|
signal i_delayed_wrptr_g : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
|
|
signal i_rden : std_logic := '0';
|
|
signal i_wren : std_logic := '0';
|
|
signal i_showahead_flag : std_logic := '0';
|
|
signal i_rdempty : std_logic := '1';
|
|
signal i_wrempty_area : std_logic := '1';
|
|
signal i_wrempty_speed : std_logic := '1';
|
|
signal i_rdempty_rreg : std_logic := '1';
|
|
signal i_rdfull_area : std_logic := '0';
|
|
signal i_rdfull_speed : std_logic := '0';
|
|
signal i_wrfull : std_logic := '0';
|
|
signal i_wrfull_wreg : std_logic := '0';
|
|
signal i_rdusedw : std_logic_vector(lpm_widthu_r+1 downto 0) := (OTHERS => '0');
|
|
signal i_wrusedw : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
|
|
signal i_rdusedw_tmp : std_logic_vector(lpm_widthu_r+1 downto 0) := (OTHERS => '0');
|
|
signal i_wrusedw_tmp : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
|
|
signal i_rs_dgwp : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
|
|
signal i_ws_dgrp : std_logic_vector(lpm_widthu_r+1 downto 0) := (OTHERS => '0');
|
|
signal i_q : std_logic_vector(lpm_width_r-1 downto 0) := (OTHERS => '0');
|
|
signal sync_rdaclr : std_logic := '1';
|
|
signal sync_rdaclr_pre : std_logic := '1';
|
|
signal read_aclr : std_logic := '0';
|
|
signal sync_wraclr : std_logic := '1';
|
|
signal sync_wraclr_pre : std_logic := '1';
|
|
signal write_aclr : std_logic := '0';
|
|
signal is_overflow : boolean := false;
|
|
signal is_underflow : boolean := false;
|
|
|
|
|
|
-- COMPONENT DECLARATION
|
|
component DCFIFO_DFFPIPE
|
|
generic (
|
|
lpm_delay : natural;
|
|
lpm_width : natural);
|
|
port (
|
|
d : in std_logic_vector(lpm_width-1 downto 0);
|
|
clock : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
q : out std_logic_vector(lpm_width-1 downto 0));
|
|
end component;
|
|
|
|
begin
|
|
|
|
-- COMPONENT INSTANTIATIONS
|
|
DP_WS_DGRP : dcfifo_dffpipe
|
|
generic map (
|
|
lpm_delay => wrsync_delaypipe,
|
|
lpm_width => lpm_widthu_r + 2)
|
|
port map (
|
|
d => i_rdptr_g,
|
|
clock => wrclk,
|
|
aclr => aclr,
|
|
q => i_ws_dgrp);
|
|
|
|
DP_RS_DGWP : dcfifo_dffpipe
|
|
generic map (
|
|
lpm_delay => rdsync_delaypipe,
|
|
lpm_width => lpm_widthu + 2)
|
|
port map (
|
|
d => i_delayed_wrptr_g,
|
|
clock => rdclk,
|
|
aclr => aclr,
|
|
q => i_rs_dgwp);
|
|
|
|
DP_RDUSEDW : dcfifo_dffpipe
|
|
generic map (
|
|
lpm_delay => get_delay_rdusedw(delay_rdusedw),
|
|
lpm_width => lpm_widthu_r + 2)
|
|
port map (
|
|
d => i_rdusedw_tmp,
|
|
clock => rdclk,
|
|
aclr => aclr,
|
|
q => i_rdusedw);
|
|
|
|
DP_WRUSEDW : dcfifo_dffpipe
|
|
generic map (
|
|
lpm_delay => get_delay_wrusedw(delay_wrusedw),
|
|
lpm_width => lpm_widthu + 2)
|
|
port map (
|
|
d => i_wrusedw_tmp,
|
|
clock => wrclk,
|
|
aclr => aclr,
|
|
q => i_wrusedw);
|
|
|
|
-- PROCESS DECLARATION
|
|
-- FIFOram
|
|
process (aclr, wrclk, rdclk, write_aclr, read_aclr)
|
|
variable need_init : boolean := true;
|
|
variable mem_data : LPM_MEMORY := (OTHERS => ZEROS_R);
|
|
variable i_q_is_registered : boolean := false;
|
|
variable max_widthu_r : integer := 0;
|
|
variable no_warn : boolean := false;
|
|
variable start_address : integer := 0;
|
|
begin
|
|
if (need_init) then
|
|
if ((lpm_showahead /= "ON") and (lpm_showahead /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! LPM_SHOWAHEAD must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((underflow_checking /= "ON") and (underflow_checking /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! UNDERFLOW_CHECKING must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if ((overflow_checking /= "ON") and (overflow_checking /= "OFF"))
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! OVERFLOW_CHECKING must be ON or OFF."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if (lpm_numwords > 2 ** lpm_widthu)
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! LPM_NUMWORDS must be less than or equal to 2**LPM_WIDTHU."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
if (IS_VALID_FAMILY(intended_device_family) = false)
|
|
then
|
|
ASSERT FALSE
|
|
REPORT "Error! Illegal INTENDED_DEVICE_FAMILY."
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
max_widthu_r := CNT_MOD_R;
|
|
|
|
if ((lpm_showahead = "OFF") and
|
|
((FEATURE_FAMILY_STRATIXII(intended_device_family)) or
|
|
(FEATURE_FAMILY_CYCLONEII(intended_device_family))))
|
|
then
|
|
i_q_is_registered := true;
|
|
else
|
|
i_q_is_registered := false;
|
|
end if;
|
|
|
|
need_init := false;
|
|
end if; -- need_init
|
|
|
|
if (aclr'event and (aclr = '1'))
|
|
then
|
|
i_rdptr_g <= ZEROU_R;
|
|
i_rdptr_g1p <= CONV_STD_LOGIC_VECTOR(1, lpm_widthu_r+2);
|
|
i_wrptr_g <= ZEROU;
|
|
i_wrptr_g1 <= CONV_STD_LOGIC_VECTOR(1, lpm_widthu+2);
|
|
i_delayed_wrptr_g <= ZEROU;
|
|
i_wrempty_area <= '1';
|
|
i_rdempty_rreg <= '1';
|
|
i_rdfull_area <= '0';
|
|
i_wrfull_wreg <= '0';
|
|
is_overflow <= false;
|
|
is_underflow <= false;
|
|
no_warn := false;
|
|
|
|
if(i_q_is_registered)
|
|
then
|
|
i_q <= (OTHERS => '0');
|
|
elsif ((FEATURE_FAMILY_STRATIXII(intended_device_family)) or
|
|
(FEATURE_FAMILY_CYCLONEII(intended_device_family)))
|
|
then
|
|
i_q <= (OTHERS => 'X');
|
|
end if;
|
|
end if;
|
|
|
|
if ((wrclk'event) and (wrclk = '1') and (NOW > 0 ns))
|
|
then
|
|
if (write_aclr = '0')
|
|
then
|
|
if (i_wren = '1')
|
|
then
|
|
if ((i_wrfull = '1') and (overflow_checking = "OFF")) then
|
|
if (no_warn = false) then
|
|
ASSERT FALSE
|
|
REPORT "Overflow occurred! Fifo output is unknown until the next reset is asserted"
|
|
SEVERITY WARNING;
|
|
no_warn := true;
|
|
end if;
|
|
is_overflow <= true;
|
|
else
|
|
if (i_wrptr_g1 < (cnt_mod - 1))
|
|
then
|
|
i_wrptr_g1 <= i_wrptr_g1 + 1;
|
|
else
|
|
i_wrptr_g1 <= ZEROU;
|
|
end if;
|
|
|
|
i_wrptr_g <= i_wrptr_g1;
|
|
|
|
if (lpm_width > lpm_width_r)
|
|
then
|
|
for i in 0 to (lpm_width/lpm_width_r-1)
|
|
loop
|
|
mem_data((CONV_INTEGER(i_wrptr_g)*lpm_width/lpm_width_r+i) mod max_widthu_r) := data(lpm_width_r*(i + 1) -1 downto lpm_width_r*i);
|
|
end loop;
|
|
elsif (lpm_width < lpm_width_r)
|
|
then
|
|
start_address := CONV_INTEGER(i_wrptr_g) mod (lpm_width_r/lpm_width);
|
|
mem_data((CONV_INTEGER(i_wrptr_g)*lpm_width/lpm_width_r) mod max_widthu_r)((start_address +1 )*lpm_width -1 downto (start_address * lpm_width)) := data;
|
|
else
|
|
mem_data(CONV_INTEGER(i_wrptr_g) mod max_widthu_r) := data;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
i_delayed_wrptr_g <= i_wrptr_g;
|
|
end if;
|
|
|
|
i_wrempty_area <= i_rdempty_rreg;
|
|
|
|
if ((aclr = '0') and (write_aclr_synch = "ON") and (FEATURE_FAMILY_STRATIXII(intended_device_family) or
|
|
FEATURE_FAMILY_CYCLONEII(intended_device_family)))
|
|
then
|
|
i_wrfull_wreg <= (i_wrfull or write_aclr);
|
|
else
|
|
i_wrfull_wreg <= i_wrfull;
|
|
end if;
|
|
end if;
|
|
|
|
if (rdclk'event and (rdclk = '1'))
|
|
then
|
|
if (read_aclr = '0')
|
|
then
|
|
if ((i_rden = '1') and (NOW > 0 ns))
|
|
then
|
|
if ((i_rdempty = '1') and (underflow_checking = "OFF")) then
|
|
if (no_warn = false) then
|
|
ASSERT FALSE
|
|
REPORT "Underflow occurred! Fifo output is unknown until the next reset is asserted"
|
|
SEVERITY WARNING;
|
|
no_warn := true;
|
|
end if;
|
|
is_underflow <= true;
|
|
else
|
|
if (i_rdptr_g1p < (cnt_mod_r - 1)) then
|
|
i_rdptr_g1p <= i_rdptr_g1p + 1;
|
|
else
|
|
i_rdptr_g1p <= ZEROU_R;
|
|
end if;
|
|
i_rdptr_g <= i_rdptr_g1p;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if ((is_overflow = true) or (is_underflow = true)) then
|
|
i_q <= (OTHERS => 'X');
|
|
else
|
|
if ((i_q_is_registered = false) and (NOW > 0 ns))
|
|
then
|
|
if ((read_aclr = '1') and ((FEATURE_FAMILY_STRATIXII(intended_device_family)) or
|
|
(FEATURE_FAMILY_CYCLONEII(intended_device_family))))
|
|
then
|
|
i_q <= (OTHERS => 'X');
|
|
else
|
|
if (i_rdempty = '1')
|
|
then
|
|
i_q <= mem_data(CONV_INTEGER(i_rdptr_g) mod max_widthu_r);
|
|
elsif (i_rden = '1')
|
|
then
|
|
i_q <= mem_data(CONV_INTEGER(i_rdptr_g1p) mod max_widthu_r);
|
|
end if;
|
|
end if;
|
|
elsif ((read_aclr = '0') and (i_rden = '1') and (NOW > 0 ns))
|
|
then
|
|
i_q <= mem_data(CONV_INTEGER(i_rdptr_g) mod max_widthu_r);
|
|
end if;
|
|
end if;
|
|
|
|
if ((rdclk = '1') and (NOW > 0 ns))
|
|
then
|
|
i_rdfull_area <= i_wrfull_wreg;
|
|
i_rdempty_rreg <= i_rdempty;
|
|
end if;
|
|
end if; -- rdclk event
|
|
end process;
|
|
|
|
process (wrclk, aclr)
|
|
begin
|
|
if (aclr = '1')
|
|
then
|
|
sync_wraclr <= '1';
|
|
sync_wraclr_pre <= '1';
|
|
elsif (wrclk'event and (wrclk = '1') and (NOW > 0 ns))
|
|
then
|
|
sync_wraclr <= sync_wraclr_pre;
|
|
sync_wraclr_pre <= '0';
|
|
end if;
|
|
end process;
|
|
|
|
process (rdclk, aclr)
|
|
begin
|
|
if (aclr = '1')
|
|
then
|
|
sync_rdaclr <= '1';
|
|
sync_rdaclr_pre <= '1';
|
|
elsif (rdclk'event and (rdclk = '1') and (NOW > 0 ns))
|
|
then
|
|
sync_rdaclr <= sync_rdaclr_pre;
|
|
sync_rdaclr_pre <= '0';
|
|
end if;
|
|
end process;
|
|
|
|
process (i_rdptr_g, i_rs_dgwp)
|
|
begin
|
|
if (lpm_width > lpm_width_r)
|
|
then
|
|
if (CONV_INTEGER(i_rdptr_g(lpm_widthu_r downto 0))*lpm_width_r/lpm_width = CONV_INTEGER((i_rs_dgwp(lpm_widthu downto 0))))
|
|
then
|
|
i_rdempty <= '1';
|
|
else
|
|
i_rdempty <= '0';
|
|
end if;
|
|
else
|
|
if (CONV_INTEGER(i_rdptr_g(lpm_widthu_r downto 0)) = CONV_INTEGER((i_rs_dgwp(lpm_widthu downto 0)))*lpm_width/lpm_width_r)
|
|
then
|
|
i_rdempty <= '1';
|
|
else
|
|
i_rdempty <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process (i_wrptr_g1, i_ws_dgrp)
|
|
begin
|
|
if (lpm_width < lpm_width_r)
|
|
then
|
|
if (((CONV_INTEGER(i_wrptr_g1(lpm_widthu downto 0)) + WIDTH_RATIO -1) mod CNT_MOD) = CONV_INTEGER(i_ws_dgrp(lpm_widthu_r downto 0))*lpm_width_r/lpm_width)
|
|
then
|
|
i_wrfull <= '1';
|
|
else
|
|
i_wrfull <= '0';
|
|
end if;
|
|
else
|
|
if (CONV_INTEGER(i_wrptr_g1(lpm_widthu downto 0)) = CONV_INTEGER(i_ws_dgrp(lpm_widthu_r downto 0))*lpm_width_r/lpm_width)
|
|
then
|
|
i_wrfull <= '1';
|
|
else
|
|
i_wrfull <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process (i_wrptr_g, i_ws_dgrp)
|
|
begin
|
|
if ((NOW > 0 ns) and (CONV_INTEGER(i_wrptr_g) < CONV_INTEGER(i_ws_dgrp)*lpm_width_r/lpm_width))
|
|
then
|
|
i_wrusedw_tmp <= CONV_STD_LOGIC_VECTOR(CNT_MOD + CONV_INTEGER(i_wrptr_g) - CONV_INTEGER(i_ws_dgrp)*lpm_width_r/lpm_width, lpm_widthu + 2);
|
|
else
|
|
i_wrusedw_tmp <= CONV_STD_LOGIC_VECTOR(CONV_INTEGER(i_wrptr_g) - CONV_INTEGER(i_ws_dgrp)*lpm_width_r/lpm_width, lpm_widthu + 2);
|
|
end if;
|
|
|
|
if (lpm_width > lpm_width_r)
|
|
then
|
|
if (CONV_INTEGER(i_wrptr_g) = CONV_INTEGER(i_ws_dgrp)*lpm_width_r/lpm_width)
|
|
then
|
|
i_wrempty_speed <= '1';
|
|
else
|
|
i_wrempty_speed <= '0';
|
|
end if;
|
|
else
|
|
if (CONV_INTEGER(i_wrptr_g)*lpm_width/lpm_width_r = CONV_INTEGER(i_ws_dgrp))
|
|
then
|
|
i_wrempty_speed <= '1';
|
|
else
|
|
i_wrempty_speed <= '0';
|
|
end if;
|
|
|
|
end if;
|
|
end process;
|
|
|
|
process (i_rdptr_g, i_rs_dgwp)
|
|
begin
|
|
if ((NOW > 0 ns) and (CONV_INTEGER(i_rs_dgwp)*lpm_width/lpm_width_r < CONV_INTEGER(i_rdptr_g)))
|
|
then
|
|
i_rdusedw_tmp <= CONV_STD_LOGIC_VECTOR((CNT_MOD + CONV_INTEGER(i_rs_dgwp))*lpm_width/lpm_width_r - CONV_INTEGER(i_rdptr_g), lpm_widthu_r + 2);
|
|
else
|
|
i_rdusedw_tmp <= CONV_STD_LOGIC_VECTOR(CONV_INTEGER(i_rs_dgwp)*lpm_width/lpm_width_r - CONV_INTEGER(i_rdptr_g), lpm_widthu_r + 2);
|
|
end if;
|
|
|
|
if (lpm_width < lpm_width_r)
|
|
then
|
|
if (CONV_INTEGER(i_rdptr_g)*lpm_width_r/lpm_width = ((CONV_INTEGER(i_rs_dgwp) + WIDTH_RATIO) mod CNT_MOD))
|
|
then
|
|
i_rdfull_speed <= '1';
|
|
else
|
|
i_rdfull_speed <= '0';
|
|
end if;
|
|
else
|
|
if (CONV_INTEGER(i_rdptr_g) = ((CONV_INTEGER(i_rs_dgwp) +1) mod CNT_MOD)*lpm_width/lpm_width_r)
|
|
then
|
|
i_rdfull_speed <= '1';
|
|
else
|
|
i_rdfull_speed <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-- SIGNAL ASSIGNMENTS
|
|
i_rden <= rdreq and not sync_rdaclr when ((underflow_checking = "OFF") and (USE_SYNC_READ_ACLR = true)) else
|
|
rdreq and not (i_rdempty or sync_rdaclr) when (USE_SYNC_READ_ACLR = true) else
|
|
rdreq when (underflow_checking = "OFF") else
|
|
rdreq and not i_rdempty;
|
|
i_wren <= wrreq and not sync_wraclr when ((overflow_checking = "OFF") and (USE_SYNC_WRITE_ACLR = true)) else
|
|
wrreq and not (i_wrfull or sync_wraclr) when (USE_SYNC_WRITE_ACLR = true) else
|
|
wrreq when (overflow_checking = "OFF") else
|
|
wrreq and not i_wrfull;
|
|
read_aclr <= sync_rdaclr when ((FEATURE_FAMILY_STRATIXIII(intended_device_family) or
|
|
FEATURE_FAMILY_CYCLONEIII(intended_device_family)) and
|
|
(read_aclr_synch = "ON")) else
|
|
aclr;
|
|
write_aclr <= sync_wraclr when ((FEATURE_FAMILY_STRATIXII(intended_device_family) or
|
|
FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
|
|
(write_aclr_synch = "ON")) else
|
|
aclr;
|
|
|
|
-- Outputs
|
|
rdempty <= 'X' when ((is_overflow = true) or (is_underflow = true)) else
|
|
(i_rdempty or sync_rdaclr) when (USE_SYNC_READ_ACLR = true) else
|
|
i_rdempty;
|
|
wrempty <= 'X' when ((is_overflow = true) or (is_underflow = true)) else
|
|
i_wrempty_speed when (USE_WREMPTY_SPEED) else
|
|
i_wrempty_area;
|
|
rdfull <= 'X' when ((is_overflow = true) or (is_underflow = true)) else
|
|
i_rdfull_speed when (USE_RDFULL_SPEED) else
|
|
i_rdfull_area;
|
|
wrfull <= 'X' when ((is_overflow = true) or (is_underflow = true)) else
|
|
(i_wrfull or sync_wraclr) when (USE_SYNC_WRITE_ACLR = true) else
|
|
i_wrfull;
|
|
wrusedw <= (OTHERS => 'X') when ((is_overflow = true) or (is_underflow = true)) else
|
|
i_wrusedw(lpm_widthu-1 downto 0);
|
|
rdusedw <= (OTHERS => 'X') when ((is_overflow = true) or (is_underflow = true)) else
|
|
i_rdusedw(lpm_widthu_r-1 downto 0);
|
|
q <= (OTHERS => 'X') when ((is_overflow = true) or (is_underflow = true)) else
|
|
i_q;
|
|
|
|
end behavior; -- dcfifo_low_latency
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : dcfifo_mixed_widths
|
|
--
|
|
-- Description : Mixed Widths Dual clocks FIFO
|
|
--
|
|
-- Limitation :
|
|
--
|
|
-- Results Expected:
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- BEGINNING OF ENTITY
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use IEEE.std_logic_unsigned.all;
|
|
use work.ALTERA_DEVICE_FAMILIES.all;
|
|
use work.DCFIFO_ASYNC;
|
|
use work.DCFIFO_SYNC;
|
|
use work.DCFIFO_LOW_LATENCY;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity DCFIFO_MIXED_WIDTHS is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
lpm_width : natural;
|
|
lpm_widthu : natural;
|
|
lpm_width_r : natural := 0;
|
|
lpm_widthu_r : natural := 0;
|
|
lpm_numwords : natural;
|
|
delay_rdusedw : natural := 1;
|
|
delay_wrusedw : natural := 1;
|
|
rdsync_delaypipe : natural := 0;
|
|
wrsync_delaypipe : natural := 0;
|
|
intended_device_family : string := "Stratix";
|
|
lpm_showahead : string := "OFF";
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
clocks_are_synchronized : string := "FALSE";
|
|
use_eab : string := "ON";
|
|
add_ram_output_register : string := "OFF";
|
|
add_width : natural := 1;
|
|
ram_block_type : string := "AUTO";
|
|
add_usedw_msb_bit : string := "OFF";
|
|
read_aclr_synch : string := "OFF";
|
|
write_aclr_synch : string := "OFF";
|
|
lpm_hint : string := "USE_EAB=ON";
|
|
lpm_type : string := "dcfifo_mixed_widths");
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
data : in std_logic_vector(lpm_width-1 downto 0);
|
|
rdclk : in std_logic;
|
|
wrclk : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
rdreq : in std_logic;
|
|
wrreq : in std_logic;
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
rdfull : out std_logic;
|
|
wrfull : out std_logic;
|
|
rdempty : out std_logic;
|
|
wrempty : out std_logic;
|
|
rdusedw : out std_logic_vector(lpm_widthu_r-1 downto 0);
|
|
wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
q : out std_logic_vector(lpm_width_r-1 downto 0));
|
|
end DCFIFO_MIXED_WIDTHS;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of DCFIFO_MIXED_WIDTHS is
|
|
|
|
-- FUNCTION DECLARATION
|
|
|
|
function dcfifo_max(L, R: INTEGER) return INTEGER is
|
|
begin
|
|
if L > R then
|
|
return L;
|
|
else
|
|
return R;
|
|
end if;
|
|
end;
|
|
|
|
function get_rdsync_delaypipe(i_rdsync_delaypipe : natural) return natural is
|
|
begin
|
|
if (i_rdsync_delaypipe = 0) then
|
|
|
|
if ((FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM (intended_device_family) or FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM (intended_device_family))
|
|
and (clocks_are_synchronized = "FALSE")) then
|
|
return 4;
|
|
else
|
|
return 3;
|
|
end if;
|
|
else
|
|
return i_rdsync_delaypipe;
|
|
end if;
|
|
end;
|
|
|
|
function get_wrsync_delaypipe(i_wrsync_delaypipe : natural) return natural is
|
|
begin
|
|
if (i_wrsync_delaypipe = 0) then
|
|
|
|
if ((FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM (intended_device_family) or FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM (intended_device_family))
|
|
and (clocks_are_synchronized = "FALSE")) then
|
|
return 4;
|
|
else
|
|
return 3;
|
|
end if;
|
|
else
|
|
return i_wrsync_delaypipe;
|
|
end if;
|
|
end;
|
|
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant USE_LOW_LATENCY_FIFO : boolean := (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM (intended_device_family) and
|
|
((use_eab = "ON") or ((use_eab = "OFF") and (lpm_width /= lpm_width_r) and (lpm_width_r /= 0)) or
|
|
((lpm_numwords < 16) and (clocks_are_synchronized = "FALSE")))) or
|
|
(FEATURE_FAMILY_STRATIX(intended_device_family) and (use_eab = "ON") and
|
|
(((lpm_showahead = "ON") and (add_ram_output_register = "OFF")) or
|
|
(clocks_are_synchronized = "FALSE_LOW_LATENCY")));
|
|
-- CONSTANT DECLARATION
|
|
constant READ_SIDE_SYNCHRONIZERS : natural := get_rdsync_delaypipe(rdsync_delaypipe);
|
|
constant WRITE_SIDE_SYNCHRONIZERS : natural := get_wrsync_delaypipe(wrsync_delaypipe);
|
|
-- For low-latency FIFO, reduce the default number of synchronization stages by 2, but need at least 1 stage
|
|
constant LOW_RDSYNC_DELAYPIPE : natural := dcfifo_max((READ_SIDE_SYNCHRONIZERS - 2), 1);
|
|
constant LOW_WRSYNC_DELAYPIPE : natural := dcfifo_max((WRITE_SIDE_SYNCHRONIZERS - 2), 1);
|
|
constant WIDTH_R : natural := lpm_width_r;
|
|
constant WIDTHU_R : natural := lpm_widthu_r;
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal i_rdfull_a : std_logic := '0';
|
|
signal i_wrfull_a : std_logic := '0';
|
|
signal i_rdempty_a : std_logic := '1';
|
|
signal i_wrempty_a : std_logic := '1';
|
|
signal i_rdfull_s : std_logic := '0';
|
|
signal i_wrfull_s : std_logic := '0';
|
|
signal i_rdempty_s : std_logic := '1';
|
|
signal i_wrempty_s : std_logic := '1';
|
|
signal i_rdfull_l : std_logic := '0';
|
|
signal i_wrfull_l : std_logic := '0';
|
|
signal i_rdempty_l : std_logic := '1';
|
|
signal i_wrempty_l : std_logic := '1';
|
|
signal i_rdusedw_a : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_wrusedw_a : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_rdusedw_s : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_wrusedw_s : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_rdusedw_l : std_logic_vector(WIDTHU_R-1 downto 0) := (OTHERS => '0');
|
|
signal i_wrusedw_l : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_q_a : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
|
|
signal i_q_s : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
|
|
signal i_q_l : std_logic_vector(WIDTH_R-1 downto 0) := (OTHERS => '0');
|
|
|
|
|
|
-- COMPONENT DECLARATION
|
|
component DCFIFO_ASYNC
|
|
generic (
|
|
lpm_width : natural;
|
|
lpm_widthu : natural;
|
|
lpm_numwords : natural;
|
|
delay_rdusedw : natural := 1;
|
|
delay_wrusedw : natural := 1;
|
|
rdsync_delaypipe : natural := 0;
|
|
wrsync_delaypipe : natural := 0;
|
|
intended_device_family : string := "Stratix";
|
|
lpm_showahead : string := "OFF";
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
use_eab : string := "ON";
|
|
add_ram_output_register : string := "OFF");
|
|
port (
|
|
data : in std_logic_vector(lpm_width-1 downto 0);
|
|
rdclk : in std_logic;
|
|
wrclk : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
rdreq : in std_logic;
|
|
wrreq : in std_logic;
|
|
rdfull : out std_logic;
|
|
wrfull : out std_logic;
|
|
rdempty : out std_logic;
|
|
wrempty : out std_logic;
|
|
rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
q : out std_logic_vector(lpm_width-1 downto 0));
|
|
end component;
|
|
|
|
component DCFIFO_SYNC
|
|
generic (
|
|
lpm_width : natural;
|
|
lpm_widthu : natural;
|
|
lpm_numwords : natural;
|
|
intended_device_family : string := "Stratix";
|
|
lpm_showahead : string := "OFF";
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
use_eab : string := "ON";
|
|
add_ram_output_register : string := "OFF");
|
|
port (
|
|
data : in std_logic_vector(lpm_width-1 downto 0);
|
|
rdclk : in std_logic;
|
|
wrclk : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
rdreq : in std_logic;
|
|
wrreq : in std_logic;
|
|
rdfull : out std_logic;
|
|
wrfull : out std_logic;
|
|
rdempty : out std_logic;
|
|
wrempty : out std_logic;
|
|
rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
q : out std_logic_vector(lpm_width-1 downto 0));
|
|
end component;
|
|
|
|
component DCFIFO_LOW_LATENCY
|
|
generic (
|
|
lpm_width : natural;
|
|
lpm_widthu : natural;
|
|
lpm_width_r : natural;
|
|
lpm_widthu_r : natural;
|
|
lpm_numwords : natural;
|
|
delay_rdusedw : natural := 2;
|
|
delay_wrusedw : natural := 2;
|
|
rdsync_delaypipe : natural := 0;
|
|
wrsync_delaypipe : natural := 0;
|
|
intended_device_family : string := "Stratix";
|
|
lpm_showahead : string := "OFF";
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
add_usedw_msb_bit : string := "OFF";
|
|
read_aclr_synch : string := "OFF";
|
|
write_aclr_synch : string := "OFF";
|
|
lpm_hint : string := "USE_EAB=ON");
|
|
port (
|
|
data : in std_logic_vector(lpm_width-1 downto 0);
|
|
rdclk : in std_logic;
|
|
wrclk : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
rdreq : in std_logic;
|
|
wrreq : in std_logic;
|
|
rdfull : out std_logic;
|
|
wrfull : out std_logic;
|
|
rdempty : out std_logic;
|
|
wrempty : out std_logic;
|
|
rdusedw : out std_logic_vector(WIDTHU_R-1 downto 0);
|
|
wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
q : out std_logic_vector(WIDTH_R-1 downto 0));
|
|
end component;
|
|
|
|
begin
|
|
-- COMPONENT ASSIGNMENTS
|
|
ASYNC: DCFIFO_ASYNC
|
|
generic map (
|
|
lpm_width => lpm_width,
|
|
lpm_widthu => lpm_widthu,
|
|
lpm_numwords => lpm_numwords,
|
|
delay_rdusedw => delay_rdusedw,
|
|
delay_wrusedw => delay_wrusedw,
|
|
rdsync_delaypipe => READ_SIDE_SYNCHRONIZERS,
|
|
wrsync_delaypipe => WRITE_SIDE_SYNCHRONIZERS,
|
|
intended_device_family => intended_device_family,
|
|
lpm_showahead => lpm_showahead,
|
|
underflow_checking => underflow_checking,
|
|
overflow_checking => overflow_checking,
|
|
use_eab => use_eab,
|
|
add_ram_output_register => add_ram_output_register)
|
|
port map (
|
|
data => data,
|
|
rdclk => rdclk,
|
|
wrclk => wrclk,
|
|
aclr => aclr,
|
|
rdreq => rdreq,
|
|
wrreq => wrreq,
|
|
rdfull => i_rdfull_a,
|
|
wrfull => i_wrfull_a,
|
|
rdempty => i_rdempty_a,
|
|
wrempty => i_wrempty_a,
|
|
rdusedw => i_rdusedw_a,
|
|
wrusedw => i_wrusedw_a,
|
|
q => i_q_a);
|
|
|
|
SYNC: DCFIFO_SYNC
|
|
generic map (
|
|
lpm_width => lpm_width,
|
|
lpm_widthu => lpm_widthu,
|
|
lpm_numwords => lpm_numwords,
|
|
intended_device_family => intended_device_family,
|
|
lpm_showahead => lpm_showahead,
|
|
underflow_checking => underflow_checking,
|
|
overflow_checking => overflow_checking,
|
|
use_eab => use_eab,
|
|
add_ram_output_register => add_ram_output_register)
|
|
port map (
|
|
data => data,
|
|
rdclk => rdclk,
|
|
wrclk => wrclk,
|
|
aclr => aclr,
|
|
rdreq => rdreq,
|
|
wrreq => wrreq,
|
|
rdfull => i_rdfull_s,
|
|
wrfull => i_wrfull_s,
|
|
rdempty => i_rdempty_s,
|
|
wrempty => i_wrempty_s,
|
|
rdusedw => i_rdusedw_s,
|
|
wrusedw => i_wrusedw_s,
|
|
q => i_q_s);
|
|
|
|
LOWLATENCY_FIFO:
|
|
if (USE_LOW_LATENCY_FIFO = true) generate
|
|
|
|
LOWLATENCY : DCFIFO_LOW_LATENCY
|
|
generic map (
|
|
lpm_width => lpm_width,
|
|
lpm_widthu => lpm_widthu,
|
|
lpm_width_r => WIDTH_R,
|
|
lpm_widthu_r => WIDTHU_R,
|
|
lpm_numwords => lpm_numwords,
|
|
delay_rdusedw => delay_rdusedw,
|
|
delay_wrusedw => delay_wrusedw,
|
|
rdsync_delaypipe => LOW_RDSYNC_DELAYPIPE,
|
|
wrsync_delaypipe => LOW_WRSYNC_DELAYPIPE,
|
|
intended_device_family => intended_device_family,
|
|
lpm_showahead => lpm_showahead,
|
|
underflow_checking => underflow_checking,
|
|
overflow_checking => overflow_checking,
|
|
add_usedw_msb_bit => add_usedw_msb_bit,
|
|
read_aclr_synch => read_aclr_synch,
|
|
write_aclr_synch => write_aclr_synch,
|
|
lpm_hint => lpm_hint)
|
|
port map (
|
|
data => data,
|
|
rdclk => rdclk,
|
|
wrclk => wrclk,
|
|
aclr => aclr,
|
|
rdreq => rdreq,
|
|
wrreq => wrreq,
|
|
rdfull => i_rdfull_l,
|
|
wrfull => i_wrfull_l,
|
|
rdempty => i_rdempty_l,
|
|
wrempty => i_wrempty_l,
|
|
rdusedw => i_rdusedw_l,
|
|
wrusedw => i_wrusedw_l,
|
|
q => i_q_l);
|
|
|
|
end generate LOWLATENCY_FIFO;
|
|
|
|
rdfull <= i_rdfull_l when USE_LOW_LATENCY_FIFO = true
|
|
else i_rdfull_s when clocks_are_synchronized = "TRUE"
|
|
else i_rdfull_a;
|
|
wrfull <= i_wrfull_l when USE_LOW_LATENCY_FIFO = true
|
|
else i_wrfull_s when clocks_are_synchronized = "TRUE"
|
|
else i_wrfull_a;
|
|
rdempty <= i_rdempty_l when USE_LOW_LATENCY_FIFO = true
|
|
else i_rdempty_s when clocks_are_synchronized = "TRUE"
|
|
else i_rdempty_a;
|
|
wrempty <= i_wrempty_l when USE_LOW_LATENCY_FIFO = true
|
|
else i_wrempty_s when clocks_are_synchronized = "TRUE"
|
|
else i_wrempty_a;
|
|
rdusedw <= i_rdusedw_l when USE_LOW_LATENCY_FIFO = true
|
|
else i_rdusedw_s when clocks_are_synchronized = "TRUE"
|
|
else i_rdusedw_a;
|
|
wrusedw <= i_wrusedw_l when USE_LOW_LATENCY_FIFO = true
|
|
else i_wrusedw_s when clocks_are_synchronized = "TRUE"
|
|
else i_wrusedw_a;
|
|
q <= i_q_l when USE_LOW_LATENCY_FIFO = true
|
|
else i_q_s when clocks_are_synchronized = "TRUE"
|
|
else i_q_a;
|
|
|
|
|
|
-- PROCESS DECLARATION
|
|
|
|
INITIAL : process
|
|
begin
|
|
if (((wrsync_delaypipe = 0) or (rdsync_delaypipe = 0)) and (clocks_are_synchronized = "FALSE")) then
|
|
if (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM (intended_device_family) or FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM (intended_device_family)) then
|
|
ASSERT FALSE
|
|
REPORT "Number of metastability protection registers is not specified. Based on the parameter value CLOCKS_ARE_SYNCHRONIZED=FALSE, the synchronization register chain length between read and write clock domains will be 2."
|
|
SEVERITY WARNING;
|
|
end if;
|
|
end if;
|
|
wait;
|
|
end process; -- INITIAL process
|
|
|
|
end behavior; -- DCFIFO_MIXED_WIDTHS
|
|
-- END OF ARCHITECTURE
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : dcfifo
|
|
--
|
|
-- Description : Dual clocks FIFO
|
|
--
|
|
-- Limitation :
|
|
--
|
|
-- Results Expected:
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- BEGINNING OF ENTITY
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use work.DCFIFO_MIXED_WIDTHS;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity DCFIFO is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
lpm_width : natural;
|
|
lpm_widthu : natural;
|
|
lpm_numwords : natural;
|
|
delay_rdusedw : natural := 1;
|
|
delay_wrusedw : natural := 1;
|
|
rdsync_delaypipe : natural := 0;
|
|
wrsync_delaypipe : natural := 0;
|
|
intended_device_family : string := "Stratix";
|
|
lpm_showahead : string := "OFF";
|
|
underflow_checking : string := "ON";
|
|
overflow_checking : string := "ON";
|
|
clocks_are_synchronized : string := "FALSE";
|
|
use_eab : string := "ON";
|
|
add_ram_output_register : string := "OFF";
|
|
add_width : natural := 1;
|
|
ram_block_type : string := "AUTO";
|
|
add_usedw_msb_bit : string := "OFF";
|
|
read_aclr_synch : string := "OFF";
|
|
write_aclr_synch : string := "OFF";
|
|
lpm_hint : string := "USE_EAB=ON";
|
|
lpm_type : string := "dcfifo");
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
data : in std_logic_vector(lpm_width-1 downto 0);
|
|
rdclk : in std_logic;
|
|
wrclk : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
rdreq : in std_logic;
|
|
wrreq : in std_logic;
|
|
|
|
-- OUTPUT PORT DECLARATION
|
|
rdfull : out std_logic;
|
|
wrfull : out std_logic;
|
|
rdempty : out std_logic;
|
|
wrempty : out std_logic;
|
|
rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
q : out std_logic_vector(lpm_width-1 downto 0));
|
|
end DCFIFO;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of DCFIFO is
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal i_rdfull : std_logic := '0';
|
|
signal i_wrfull : std_logic := '0';
|
|
signal i_rdempty : std_logic := '1';
|
|
signal i_wrempty : std_logic := '1';
|
|
signal i_rdusedw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_wrusedw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
|
|
signal i_q : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
|
|
|
|
-- COMPONENT DECLARATION
|
|
|
|
component DCFIFO_MIXED_WIDTHS
|
|
generic (
|
|
lpm_width : natural;
|
|
lpm_widthu : natural;
|
|
lpm_width_r : natural;
|
|
lpm_widthu_r : natural;
|
|
lpm_numwords : natural;
|
|
delay_rdusedw : natural;
|
|
delay_wrusedw : natural;
|
|
rdsync_delaypipe : natural;
|
|
wrsync_delaypipe : natural;
|
|
intended_device_family : string;
|
|
lpm_showahead : string;
|
|
underflow_checking : string;
|
|
overflow_checking : string;
|
|
clocks_are_synchronized : string;
|
|
use_eab : string;
|
|
add_ram_output_register : string;
|
|
add_width : natural;
|
|
ram_block_type : string;
|
|
add_usedw_msb_bit : string;
|
|
read_aclr_synch : string;
|
|
write_aclr_synch : string;
|
|
lpm_hint : string );
|
|
port (
|
|
data : in std_logic_vector(lpm_width-1 downto 0);
|
|
rdclk : in std_logic;
|
|
wrclk : in std_logic;
|
|
aclr : in std_logic := '0';
|
|
rdreq : in std_logic;
|
|
wrreq : in std_logic;
|
|
rdfull : out std_logic;
|
|
wrfull : out std_logic;
|
|
rdempty : out std_logic;
|
|
wrempty : out std_logic;
|
|
rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
|
|
q : out std_logic_vector(lpm_width-1 downto 0));
|
|
end component;
|
|
|
|
begin
|
|
-- COMPONENT ASSIGNMENTS
|
|
DCFIFO_MW : DCFIFO_MIXED_WIDTHS
|
|
generic map (
|
|
lpm_width => lpm_width,
|
|
lpm_widthu => lpm_widthu,
|
|
lpm_width_r => lpm_width,
|
|
lpm_widthu_r => lpm_widthu,
|
|
lpm_numwords => lpm_numwords,
|
|
delay_rdusedw => delay_rdusedw,
|
|
delay_wrusedw => delay_wrusedw,
|
|
rdsync_delaypipe => rdsync_delaypipe,
|
|
wrsync_delaypipe => wrsync_delaypipe,
|
|
intended_device_family => intended_device_family,
|
|
lpm_showahead => lpm_showahead,
|
|
underflow_checking => underflow_checking,
|
|
overflow_checking => overflow_checking,
|
|
clocks_are_synchronized => clocks_are_synchronized,
|
|
use_eab => use_eab,
|
|
add_ram_output_register => add_ram_output_register,
|
|
add_width => add_width,
|
|
ram_block_type => ram_block_type,
|
|
add_usedw_msb_bit => add_usedw_msb_bit,
|
|
read_aclr_synch => read_aclr_synch,
|
|
write_aclr_synch => write_aclr_synch,
|
|
lpm_hint => lpm_hint)
|
|
port map (
|
|
data => data,
|
|
rdclk => rdclk,
|
|
wrclk => wrclk,
|
|
aclr => aclr,
|
|
rdreq => rdreq,
|
|
wrreq => wrreq,
|
|
rdfull => i_rdfull,
|
|
wrfull => i_wrfull,
|
|
rdempty => i_rdempty,
|
|
wrempty => i_wrempty,
|
|
rdusedw => i_rdusedw,
|
|
wrusedw => i_wrusedw,
|
|
q => i_q);
|
|
|
|
rdfull <= i_rdfull;
|
|
wrfull <= i_wrfull;
|
|
rdempty <= i_rdempty;
|
|
wrempty <= i_wrempty;
|
|
rdusedw <= i_rdusedw;
|
|
wrusedw <= i_wrusedw;
|
|
q <= i_q;
|
|
|
|
end behavior; -- dcfifo
|
|
-- END OF ARCHITECTURE
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Module Name : altshift_taps
|
|
--
|
|
-- Description : Parameterized shift register with taps megafunction.
|
|
-- Implements a RAM-based shift register for efficient
|
|
-- creation of very large shift registers
|
|
--
|
|
-- Limitation : This megafunction is provided only for backward
|
|
-- compatibility in Cyclone, Stratix, and Stratix GX
|
|
-- designs.
|
|
--
|
|
-- Results expected : Produce output from the end of the shift register
|
|
-- and from the regularly spaced taps along the
|
|
-- shift register.
|
|
--
|
|
--------------------------------------------------------------------------------
|
|
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altshift_taps is
|
|
generic (
|
|
number_of_taps : natural := 4; -- Specifies the number of regularly spaced
|
|
-- taps along the shift register
|
|
tap_distance : natural := 3; -- Specifies the distance between the
|
|
-- regularly spaced taps in clock cycles
|
|
-- This number translates to the number of
|
|
-- RAM words that will be used
|
|
width : natural := 8;
|
|
power_up_state : string := "CLEARED";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altshift_taps";
|
|
intended_device_family : string := "Stratix"
|
|
);
|
|
|
|
port (-- data input to the shifter
|
|
shiftin : in std_logic_vector (width-1 downto 0);
|
|
-- Positive-edge triggered clock
|
|
clock : in std_logic;
|
|
-- Clock enable for the clock port
|
|
clken : in std_logic := '1';
|
|
-- Asynchronous clear port
|
|
aclr : in std_logic := '0';
|
|
-- Output from the end of the shift register
|
|
shiftout : out std_logic_vector (width-1 downto 0);
|
|
-- Output from the regularly spaced taps along the shift register
|
|
taps : out std_logic_vector ((width*number_of_taps)-1 downto 0)
|
|
);
|
|
|
|
end altshift_taps;
|
|
|
|
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavioural of altshift_taps is
|
|
|
|
-- CONSTANT DECLARATION
|
|
constant TOTAL_TAP_DISTANCE : natural := number_of_taps * tap_distance;
|
|
|
|
-- TYPE DECLARATION
|
|
type mxn_array is array (TOTAL_TAP_DISTANCE-1 downto 0) of
|
|
std_logic_vector (width downto 0);
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal contents : mxn_array;
|
|
signal head_pipe : natural := 0;
|
|
signal i : natural := 0;
|
|
|
|
begin
|
|
|
|
-- PROCESS BLOCKS
|
|
SHIFT: process (clock, aclr)
|
|
variable head: natural := 0;
|
|
variable init : boolean := true;
|
|
begin
|
|
if init and (power_up_state = "CLEARED") then
|
|
shiftout <= (others => '0');
|
|
taps <= (others => '0');
|
|
contents <= (others => (others => '0'));
|
|
init := false;
|
|
end if;
|
|
|
|
if (aclr = '1') then
|
|
shiftout <= (others => '0');
|
|
taps <= (others => '0');
|
|
contents <= (others => (others => '0'));
|
|
head := 0;
|
|
head_pipe <= 0;
|
|
elsif (rising_edge(clock)) then
|
|
if (clken = '1') then
|
|
head := head_pipe;
|
|
|
|
contents (head)(width-1 downto 0) <= shiftin;
|
|
shiftout <= contents ((head+1) mod
|
|
TOTAL_TAP_DISTANCE)(width-1 downto 0);
|
|
head := (head+1) mod TOTAL_TAP_DISTANCE;
|
|
|
|
for i in 0 to (number_of_taps-1)
|
|
loop
|
|
taps (((i+1)*width)-1 downto (i*width) ) <=
|
|
contents ((((number_of_taps - i - 1)*tap_distance) + head)
|
|
mod TOTAL_TAP_DISTANCE)(width-1 downto 0);
|
|
end loop;
|
|
|
|
head_pipe <= head;
|
|
end if;
|
|
end if;
|
|
end process shift;
|
|
|
|
|
|
end behavioural; -- altshift_taps
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- Entity Name : a_graycounter
|
|
--
|
|
-- Description : Gray counter with Count-enable, Up/Down, aclr and sclr
|
|
--
|
|
-- Limitation : Sync sigal priority: clk_en (higher),sclr,cnt_en (lower)
|
|
--
|
|
-- Results Expected: q is graycounter output and qbin is normal counter
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
-- BEGINNING OF ENTITY
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
use IEEE.std_logic_unsigned.all;
|
|
|
|
-- ENTITY DECLARATION
|
|
entity A_GRAYCOUNTER is
|
|
-- GENERIC DECLARATION
|
|
generic (
|
|
width : natural;
|
|
pvalue : natural;
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "a_graycounter");
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
-- INPUT PORT DECLARATION
|
|
clock : in std_logic;
|
|
clk_en : in std_logic := '1';
|
|
cnt_en : in std_logic := '1';
|
|
updown : in std_logic := '1';
|
|
aclr : in std_logic := '0';
|
|
sclr : in std_logic := '0';
|
|
-- OUTPUT PORT DECLARATION
|
|
qbin : out std_logic_vector(width-1 downto 0);
|
|
q : out std_logic_vector(width-1 downto 0));
|
|
end A_GRAYCOUNTER;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
-- ARCHITECTURE DECLARATION
|
|
architecture behavior of A_GRAYCOUNTER is
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal cnt : std_logic_vector(width-1 downto 0);
|
|
signal qbin_tmp : std_logic_vector(width-1 downto 0);
|
|
|
|
begin
|
|
-- PROCESS DECLARATION
|
|
-- basic error checking for invalid parameters
|
|
MSG: process
|
|
begin
|
|
if (width <= 0) then
|
|
ASSERT FALSE
|
|
REPORT "Value of WIDTH parameter of a_graycounter must be greater than 0!"
|
|
SEVERITY ERROR;
|
|
end if;
|
|
|
|
wait;
|
|
end process MSG;
|
|
|
|
process(aclr, clock)
|
|
variable init : boolean := true;
|
|
begin
|
|
if (init) then
|
|
-- Initialize to pvalue
|
|
cnt <= conv_std_logic_vector(pvalue, width);
|
|
init := false;
|
|
elsif (aclr'event and (aclr = '1')) then
|
|
cnt <= conv_std_logic_vector(pvalue, width);
|
|
elsif (clock'event and (clock = '1')) then
|
|
if ((aclr = '0') and (clk_en = '1')) then
|
|
if (sclr = '1') then
|
|
cnt <= conv_std_logic_vector(pvalue, width);
|
|
elsif (cnt_en = '1') then
|
|
if (updown = '1') then
|
|
cnt <= cnt + 1;
|
|
else
|
|
cnt <= cnt - 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
qbin_tmp <= cnt;
|
|
process(qbin_tmp)
|
|
variable qbin_rshift : std_logic_vector(width-1 downto 0);
|
|
begin
|
|
if (width > 1) then
|
|
qbin_rshift(width-2 downto 0) := qbin_tmp(width-1 downto 1);
|
|
end if;
|
|
qbin_rshift(width-1) := '0';
|
|
q <= qbin_tmp xor qbin_rshift;
|
|
end process;
|
|
|
|
qbin <= cnt;
|
|
|
|
end behavior; -- a_graycounter
|
|
-- END OF ARCHITECTURE
|
|
|
|
|
|
|
|
|
|
---START_ENTITY_HEADER---------------------------------------------------------
|
|
--
|
|
-- entity Name : altsquare
|
|
--
|
|
-- Description : Parameterized integer square megafunction.
|
|
-- The input data can be signed or unsigned, and the output
|
|
-- can be pipelined.
|
|
--
|
|
-- Limitations : Minimum data width is 1.
|
|
--
|
|
-- Results expected: result - The square of input data.
|
|
--
|
|
---END_ENTITY_HEADER-----------------------------------------------------------
|
|
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.std_logic_arith.all;
|
|
|
|
-- BEGINNING OF ENTITY
|
|
|
|
-- ENTITY DECLARATION
|
|
entity altsquare is
|
|
-- GENERIC DECLARATION
|
|
generic
|
|
(
|
|
data_width : natural;
|
|
result_width : natural;
|
|
pipeline : natural := 0;
|
|
representation : string := "UNSIGNED";
|
|
result_alignment : string := "LSB";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "altsquare"
|
|
);
|
|
-- PORT DECLARATION
|
|
port
|
|
(
|
|
data : in std_logic_vector (data_width - 1 downto 0);
|
|
clock : in std_logic := '0';
|
|
ena : in std_logic := '1';
|
|
aclr : in std_logic := '0';
|
|
result : out std_logic_vector (result_width - 1 downto 0)
|
|
);
|
|
end altsquare;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
architecture altsquare_syn of altsquare is
|
|
|
|
-- TYPE DECLARATION
|
|
-- for storing the pipeline values
|
|
type T_PIPE_ARRAY is array (0 to pipeline) of std_logic_vector(2 * data_width - 1 downto 0);
|
|
|
|
-- SIGNAL DECLARATION
|
|
signal stage_value : T_PIPE_ARRAY;
|
|
signal next_value : std_logic_vector(2 * data_width - 1 downto 0);
|
|
begin
|
|
-- error checking
|
|
assert data_width > 0
|
|
report "Value of data_width parameter must be greater than 0" severity error;
|
|
assert result_width > 0
|
|
report "Value of result_width parameter must be greater than 0" severity error;
|
|
assert representation = "UNSIGNED" or representation = "SIGNED"
|
|
report "Value of representation parameter must be signed or unsigned" severity error;
|
|
|
|
-- PROCESS DECLARATION
|
|
process(clock, aclr, data)
|
|
variable stage_value : T_PIPE_ARRAY;
|
|
begin
|
|
if aclr = '1' and pipeline > 0 then
|
|
stage_value := (others => (others => '0'));
|
|
elsif (clock = '1' and clock'event) or pipeline = 0 then
|
|
if (ena = '1') or (pipeline = 0) then
|
|
if representation = "SIGNED" then
|
|
stage_value(0) := signed(data) * signed(data);
|
|
else
|
|
stage_value(0) := unsigned(data) * unsigned(data);
|
|
end if;
|
|
if pipeline > 0 then
|
|
for i in pipeline downto 1 loop
|
|
stage_value(i) := stage_value(i - 1);
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
next_value <= stage_value(pipeline);
|
|
end process;
|
|
|
|
-- now set the result
|
|
data_shrink_LSB : if (result_width <= 2 * data_width) and (result_alignment = "LSB") generate
|
|
result(result_width - 1 downto 0) <= next_value(result_width - 1 downto 0);
|
|
end generate;
|
|
data_shrink_MSB : if (result_width <= 2 * data_width) and (result_alignment = "MSB") generate
|
|
result(result_width - 1 downto 0) <= next_value((2*data_width)-1 downto (2*data_width)-result_width);
|
|
end generate;
|
|
data_expand : if result_width > 2 * data_width generate
|
|
result(result_width - 1 downto 2* data_width) <= (others => '0');
|
|
result((2 * data_width) - 1 downto 0) <= next_value;
|
|
end generate;
|
|
end altsquare_syn; -- altsquare
|
|
-- END OF ARCHITECTURE
|
|
-- START_FILE_HEADER ----------------------------------------------------------
|
|
--
|
|
-- Filename : altera_std_synchronizer.vhd
|
|
--
|
|
-- Description : Contains the simulation model for the altera_std_synchronizer
|
|
--
|
|
-- Owner : Paul Scheidt
|
|
--
|
|
-- Copyright (C) Altera Corporation 2008, All Rights Reserved
|
|
--
|
|
-- END_FILE_HEADER ------------------------------------------------------------
|
|
--
|
|
-- START_ENTITY_HEADER --------------------------------------------------------
|
|
--
|
|
-- Entity Name : altera_std_synchronizer
|
|
--
|
|
-- Description : Single bit clock domain crossing synchronizer.
|
|
-- Composed of two flip flops connected in series.
|
|
--
|
|
-- Limitations :
|
|
--
|
|
-- END_FILE_HEADER ------------------------------------------------------------
|
|
--
|
|
library ieee ;
|
|
use ieee.std_logic_1164.all;
|
|
use work.all;
|
|
|
|
-- BEGINNING OF ENTITY
|
|
entity altera_std_synchronizer is
|
|
-- GENERIC DECLARATION
|
|
generic (depth : integer := 3); -- must be >= 2
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
clk : in std_logic;
|
|
reset_n : in std_logic;
|
|
din : in std_logic;
|
|
dout : out std_logic
|
|
);
|
|
end altera_std_synchronizer;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
architecture behavioral of altera_std_synchronizer is
|
|
-- SIGNAL DECLARATION
|
|
signal din_s1 : std_logic;
|
|
signal dreg : std_logic_vector(depth-2 downto 0);
|
|
begin
|
|
process (din, clk) begin
|
|
if (clk'event and clk='1') then
|
|
if reset_n='0' then
|
|
din_s1 <= '0';
|
|
else
|
|
din_s1 <= din;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
g1: if depth = 1 generate
|
|
-- normally this is an illegal condition
|
|
dout <= din_s1;
|
|
end generate g1;
|
|
|
|
g2: if depth = 2 generate
|
|
process (din, clk) begin
|
|
if (clk'event and clk='1') then
|
|
if reset_n='0' then
|
|
dout <= '0';
|
|
else
|
|
dout <= din_s1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
end generate g2;
|
|
|
|
g3: if depth >= 3 generate
|
|
process (din, clk) begin
|
|
if (clk'event and clk='1') then
|
|
if reset_n='0' then
|
|
dreg <= (others => '0');
|
|
else
|
|
dreg <= dreg(depth-3 downto 0) & din_s1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
dout <= dreg(depth-2);
|
|
end generate g3;
|
|
|
|
end behavioral;
|
|
-- END OF ARCHITECTURE
|
|
|
|
-- START_FILE_HEADER ----------------------------------------------------------
|
|
--
|
|
-- Filename : altera_std_synchronizer_bundle.vhd
|
|
--
|
|
-- Description : Contains the simulation model for the altera_std_synchronizer_bundle
|
|
--
|
|
-- Owner : Paul Scheidt
|
|
--
|
|
-- Copyright (C) Altera Corporation 2008, All Rights Reserved
|
|
--
|
|
-- END_FILE_HEADER ------------------------------------------------------------
|
|
--
|
|
-- START_ENTITY_HEADER --------------------------------------------------------
|
|
--
|
|
-- Entity Name : altera_std_synchronizer_bundle
|
|
--
|
|
-- Description : Bundle of bit synchronizers.
|
|
-- WARNING: only use this to synchronize a bundle of
|
|
-- *independent* single bit signals or a Gray encoded
|
|
-- bus of signals. Also remember that pulses entering
|
|
-- the synchronizer will be swallowed upon a metastable
|
|
-- condition if the pulse width is shorter than twice
|
|
-- the synchronizing clock period.
|
|
--
|
|
-- Limitations :
|
|
--
|
|
-- END_FILE_HEADER -------------------------------------------------------------
|
|
--
|
|
|
|
library ieee ;
|
|
use ieee.std_logic_1164.all;
|
|
use work.all;
|
|
|
|
-- BEGINNNG OF ENTITY
|
|
entity altera_std_synchronizer_bundle is
|
|
-- GENERIC DECLARATION
|
|
generic ( depth : integer := 3; -- must be >= 2
|
|
width : integer := 1);
|
|
|
|
-- PORT DECLARATION
|
|
port (
|
|
clk : in std_logic;
|
|
reset_n : in std_logic;
|
|
din : in std_logic_vector(width-1 downto 0);
|
|
dout : out std_logic_vector(width-1 downto 0)
|
|
);
|
|
end altera_std_synchronizer_bundle;
|
|
-- END OF ENTITY
|
|
|
|
-- BEGINNING OF ARCHITECTURE
|
|
architecture behavioral of altera_std_synchronizer_bundle is
|
|
-- COMPONENT DECLARATION
|
|
component altera_std_synchronizer
|
|
generic (depth : integer := 3);
|
|
port (
|
|
clk : in std_logic;
|
|
reset_n : in std_logic;
|
|
din : in std_logic;
|
|
dout : out std_logic
|
|
);
|
|
end component;
|
|
begin
|
|
g1: for i in 0 to width-1 generate
|
|
s: altera_std_synchronizer
|
|
generic map (depth => depth)
|
|
port map ( clk => clk,
|
|
reset_n => reset_n,
|
|
din => din(i),
|
|
dout => dout(i)
|
|
);
|
|
end generate g1;
|
|
end behavioral;
|
|
-- END OF ARCHITECTURE
|
|
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_unsigned.all;
|
|
|
|
--synthesis_resources = lut 4 reg 5
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
|
|
ENTITY alt_cal IS
|
|
generic (
|
|
number_of_channels : integer := 1;
|
|
channel_address_width : integer := 1;
|
|
sim_model_mode : string := "TRUE";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "alt_cal"
|
|
);
|
|
PORT
|
|
(
|
|
busy : OUT STD_LOGIC;
|
|
cal_error : OUT STD_LOGIC_VECTOR (number_of_channels - 1 DOWNTO 0);
|
|
clock : IN STD_LOGIC;
|
|
dprio_addr : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_busy : IN STD_LOGIC;
|
|
dprio_datain : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_dataout : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_rden : OUT STD_LOGIC;
|
|
dprio_wren : OUT STD_LOGIC;
|
|
quad_addr : OUT STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
remap_addr : IN STD_LOGIC_VECTOR (11 DOWNTO 0) := (OTHERS => '0');
|
|
reset : IN STD_LOGIC := '0';
|
|
retain_addr : OUT STD_LOGIC;
|
|
start : IN STD_LOGIC := '0';
|
|
transceiver_init : IN STD_LOGIC := '0';
|
|
testbuses : IN STD_LOGIC_VECTOR (4 * number_of_channels - 1 DOWNTO 0) := (OTHERS => '0')
|
|
);
|
|
END alt_cal;
|
|
|
|
ARCHITECTURE RTL OF alt_cal IS
|
|
|
|
ATTRIBUTE synthesis_clearbox : natural;
|
|
ATTRIBUTE synthesis_clearbox OF RTL : ARCHITECTURE IS 1;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE : string;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF RTL : ARCHITECTURE IS "PRESERVE_REGISTER=ON";
|
|
|
|
SIGNAL p0addr_sim : STD_LOGIC_VECTOR(0 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '0')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF p0addr_sim : SIGNAL IS "PRESERVE_REGISTER=ON;POWER_UP_LEVEL=LOW";
|
|
|
|
SIGNAL wire_p0addr_sim_w_lg_w_lg_q4w5w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_p0addr_sim_w_lg_q4w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_reg : STD_LOGIC_VECTOR(3 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '0')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF sim_counter_reg : SIGNAL IS "POWER_UP_LEVEL=LOW";
|
|
SIGNAL first_run : STD_LOGIC_VECTOR(0 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '1')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF first_run : SIGNAL IS "POWER_UP_LEVEL=HIGH";
|
|
|
|
SIGNAL wire_next_scount_num_dataa : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_next_scount_num_datab : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_next_scount_num_result : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_w_lg_reset7w8w9w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_reset7w8w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_sim_counter_and2w3w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_sim_counter_and1w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_w_lg_reset7w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_sim_counter_and2w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL busy_sim : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_activator : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_and : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_next : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL sim_counter_or : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
BEGIN
|
|
|
|
loop0 : FOR i IN 0 TO 3 GENERATE
|
|
wire_w_lg_w_lg_w_lg_reset7w8w9w(i) <= (wire_w_lg_w_lg_reset7w8w(0) AND wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w(i) AND NOT(reset AND first_run(0))) OR (reset AND NOT first_run(0));
|
|
END GENERATE loop0;
|
|
-- wire_w_lg_w_lg_reset7w8w(0) <= wire_w_lg_reset7w(0) AND sim_activator(0);
|
|
wire_w_lg_w_lg_reset7w8w(0) <= (NOT transceiver_init AND NOT start) AND sim_activator(0);
|
|
wire_w_lg_w_lg_sim_counter_and2w3w(0) <= wire_w_lg_sim_counter_and2w(0) AND sim_counter_or(0);
|
|
loop1 : FOR i IN 0 TO 3 GENERATE
|
|
wire_w_lg_sim_counter_and1w(i) <= sim_counter_and(0) AND sim_counter_reg(i);
|
|
END GENERATE loop1;
|
|
wire_w_lg_reset7w(0) <= NOT reset;
|
|
wire_w_lg_sim_counter_and2w(0) <= NOT sim_counter_and(0);
|
|
busy <= busy_sim(0);
|
|
busy_sim(0) <= (wire_w_lg_reset7w(0) AND p0addr_sim(0) AND wire_w_lg_sim_counter_and2w(0));
|
|
cal_error <= (OTHERS => '0');
|
|
dprio_addr <= (OTHERS => '0');
|
|
dprio_dataout <= (OTHERS => '0');
|
|
dprio_rden <= '0';
|
|
dprio_wren <= '0';
|
|
quad_addr <= (OTHERS => '0');
|
|
retain_addr <= '0';
|
|
sim_activator <= p0addr_sim;
|
|
sim_counter_and(0) <= (((sim_counter_reg(0) AND sim_counter_reg(1)) AND sim_counter_reg(2)) AND sim_counter_reg(3));
|
|
sim_counter_next <= wire_next_scount_num_result;
|
|
sim_counter_or(0) <= (((sim_counter_reg(0) OR sim_counter_reg(1)) OR sim_counter_reg(2)) OR sim_counter_reg(3));
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN p0addr_sim <= "1";
|
|
END IF;
|
|
END PROCESS;
|
|
loop2 : FOR i IN 0 TO 3 GENERATE
|
|
wire_p0addr_sim_w_lg_w_lg_q4w5w(i) <= wire_p0addr_sim_w_lg_q4w(0) AND sim_counter_next(i);
|
|
END GENERATE loop2;
|
|
loop3 : FOR i IN 0 TO 3 GENERATE
|
|
wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w(i) <= wire_p0addr_sim_w_lg_w_lg_q4w5w(i) OR wire_w_lg_sim_counter_and1w(i);
|
|
END GENERATE loop3;
|
|
wire_p0addr_sim_w_lg_q4w(0) <= p0addr_sim(0) OR wire_w_lg_w_lg_sim_counter_and2w3w(0);
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN sim_counter_reg <= wire_w_lg_w_lg_w_lg_reset7w8w9w;
|
|
END IF;
|
|
END PROCESS;
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN
|
|
IF (first_run(0) = '1') THEN
|
|
first_run(0) <= (NOT sim_counter_and(0));
|
|
ELSE
|
|
first_run(0) <= '0';
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
wire_next_scount_num_result <= wire_next_scount_num_dataa + wire_next_scount_num_datab;
|
|
wire_next_scount_num_dataa <= sim_counter_reg;
|
|
wire_next_scount_num_datab <= "0001";
|
|
|
|
END RTL; --alt_cal
|
|
--VALID FILE
|
|
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_unsigned.all;
|
|
|
|
--synthesis_resources = lut 4 reg 5
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
|
|
ENTITY alt_cal_mm IS
|
|
generic (
|
|
number_of_channels : integer := 1;
|
|
channel_address_width : integer := 1;
|
|
sim_model_mode : string := "TRUE";
|
|
CAL_PD_WR : string := "00101";
|
|
CAL_RX_RD : string := "00110";
|
|
CAL_RX_WR : string := "00111";
|
|
CH_ADV : string := "01100";
|
|
CH_WAIT : string := "00001";
|
|
DPRIO_READ : string := "01110";
|
|
DPRIO_WAIT : string := "01000";
|
|
DPRIO_WRITE : string := "01111";
|
|
IDLE : string := "00000";
|
|
KICK_DELAY_OC : integer := 10010;
|
|
KICK_PAUSE : integer := 10001;
|
|
KICK_START_RD : string := "01101";
|
|
KICK_START_WR : integer := 10000;
|
|
OFFSETS_PDEN_RD : string := "00011";
|
|
OFFSETS_PDEN_WR : string := "00100";
|
|
sample_length : string := "01100100";
|
|
SAMPLE_TB : string := "01001";
|
|
TEST_INPUT : string := "01010";
|
|
TESTBUS_SET : string := "00010";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "alt_cal_mm"
|
|
);
|
|
PORT
|
|
(
|
|
busy : OUT STD_LOGIC;
|
|
cal_error : OUT STD_LOGIC_VECTOR (number_of_channels - 1 DOWNTO 0);
|
|
clock : IN STD_LOGIC;
|
|
dprio_addr : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_busy : IN STD_LOGIC;
|
|
dprio_datain : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_dataout : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_rden : OUT STD_LOGIC;
|
|
dprio_wren : OUT STD_LOGIC;
|
|
quad_addr : OUT STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
remap_addr : IN STD_LOGIC_VECTOR (11 DOWNTO 0) := (OTHERS => '0');
|
|
reset : IN STD_LOGIC := '0';
|
|
retain_addr : OUT STD_LOGIC;
|
|
start : IN STD_LOGIC := '0';
|
|
transceiver_init : IN STD_LOGIC := '0';
|
|
testbuses : IN STD_LOGIC_VECTOR (4 * number_of_channels - 1 DOWNTO 0) := (OTHERS => '0')
|
|
);
|
|
END alt_cal_mm;
|
|
|
|
ARCHITECTURE RTL OF alt_cal_mm IS
|
|
|
|
ATTRIBUTE synthesis_clearbox : natural;
|
|
ATTRIBUTE synthesis_clearbox OF RTL : ARCHITECTURE IS 1;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE : string;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF RTL : ARCHITECTURE IS "PRESERVE_REGISTER=ON";
|
|
|
|
SIGNAL p0addr_sim : STD_LOGIC_VECTOR(0 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '0')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF p0addr_sim : SIGNAL IS "PRESERVE_REGISTER=ON;POWER_UP_LEVEL=LOW";
|
|
|
|
SIGNAL wire_p0addr_sim_w_lg_w_lg_q4w5w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_p0addr_sim_w_lg_q4w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_reg : STD_LOGIC_VECTOR(3 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '0')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF sim_counter_reg : SIGNAL IS "POWER_UP_LEVEL=LOW";
|
|
SIGNAL first_run : STD_LOGIC_VECTOR(0 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '1')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF first_run : SIGNAL IS "POWER_UP_LEVEL=HIGH";
|
|
|
|
SIGNAL wire_next_scount_num_dataa : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_next_scount_num_datab : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_next_scount_num_result : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_w_lg_reset7w8w9w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_reset7w8w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_sim_counter_and2w3w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_sim_counter_and1w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_w_lg_reset7w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_sim_counter_and2w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL busy_sim : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_activator : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_and : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_next : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL sim_counter_or : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
BEGIN
|
|
|
|
loop0 : FOR i IN 0 TO 3 GENERATE
|
|
wire_w_lg_w_lg_w_lg_reset7w8w9w(i) <= ((NOT start AND NOT transceiver_init) AND wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w(i) AND NOT (reset AND first_run(0))) OR (reset AND NOT first_run(0));
|
|
END GENERATE loop0;
|
|
wire_w_lg_w_lg_reset7w8w(0) <= wire_w_lg_reset7w(0) AND sim_activator(0);
|
|
wire_w_lg_w_lg_sim_counter_and2w3w(0) <= wire_w_lg_sim_counter_and2w(0) AND sim_counter_or(0);
|
|
loop1 : FOR i IN 0 TO 3 GENERATE
|
|
wire_w_lg_sim_counter_and1w(i) <= sim_counter_and(0) AND sim_counter_reg(i);
|
|
END GENERATE loop1;
|
|
wire_w_lg_reset7w(0) <= NOT reset;
|
|
wire_w_lg_sim_counter_and2w(0) <= NOT sim_counter_and(0);
|
|
busy <= busy_sim(0);
|
|
busy_sim(0) <= wire_w_lg_reset7w(0) AND (p0addr_sim(0) AND wire_w_lg_sim_counter_and2w(0));
|
|
cal_error <= (OTHERS => '0');
|
|
dprio_addr <= (OTHERS => '0');
|
|
dprio_dataout <= (OTHERS => '0');
|
|
dprio_rden <= '0';
|
|
dprio_wren <= '0';
|
|
quad_addr <= (OTHERS => '0');
|
|
retain_addr <= '0';
|
|
sim_activator <= p0addr_sim;
|
|
sim_counter_and(0) <= (((sim_counter_reg(0) AND sim_counter_reg(1)) AND sim_counter_reg(2)) AND sim_counter_reg(3));
|
|
sim_counter_next <= wire_next_scount_num_result;
|
|
sim_counter_or(0) <= (((sim_counter_reg(0) OR sim_counter_reg(1)) OR sim_counter_reg(2)) OR sim_counter_reg(3));
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN p0addr_sim <= "1";
|
|
END IF;
|
|
END PROCESS;
|
|
loop2 : FOR i IN 0 TO 3 GENERATE
|
|
wire_p0addr_sim_w_lg_w_lg_q4w5w(i) <= wire_p0addr_sim_w_lg_q4w(0) AND sim_counter_next(i);
|
|
END GENERATE loop2;
|
|
loop3 : FOR i IN 0 TO 3 GENERATE
|
|
wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w(i) <= wire_p0addr_sim_w_lg_w_lg_q4w5w(i) OR wire_w_lg_sim_counter_and1w(i);
|
|
END GENERATE loop3;
|
|
wire_p0addr_sim_w_lg_q4w(0) <= p0addr_sim(0) OR wire_w_lg_w_lg_sim_counter_and2w3w(0);
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN sim_counter_reg <= wire_w_lg_w_lg_w_lg_reset7w8w9w;
|
|
END IF;
|
|
END PROCESS;
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN
|
|
IF (first_run(0) = '1') THEN
|
|
first_run(0) <= (NOT sim_counter_and(0));
|
|
ELSE
|
|
first_run(0) <= '0';
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
wire_next_scount_num_result <= wire_next_scount_num_dataa + wire_next_scount_num_datab;
|
|
wire_next_scount_num_dataa <= sim_counter_reg;
|
|
wire_next_scount_num_datab <= "0001";
|
|
|
|
END RTL; --alt_cal_mm
|
|
--VALID FILE
|
|
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_unsigned.all;
|
|
|
|
--synthesis_resources = lut 4 reg 5
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
|
|
ENTITY alt_cal_c3gxb IS
|
|
generic (
|
|
number_of_channels : integer := 1;
|
|
channel_address_width : integer := 1;
|
|
sim_model_mode : string := "TRUE";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "alt_cal_c3gxb"
|
|
);
|
|
PORT
|
|
(
|
|
busy : OUT STD_LOGIC;
|
|
cal_error : OUT STD_LOGIC_VECTOR (number_of_channels - 1 DOWNTO 0);
|
|
clock : IN STD_LOGIC;
|
|
dprio_addr : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_busy : IN STD_LOGIC;
|
|
dprio_datain : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_dataout : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_rden : OUT STD_LOGIC;
|
|
dprio_wren : OUT STD_LOGIC;
|
|
quad_addr : OUT STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
remap_addr : IN STD_LOGIC_VECTOR (11 DOWNTO 0) := (OTHERS => '0');
|
|
reset : IN STD_LOGIC := '0';
|
|
retain_addr : OUT STD_LOGIC;
|
|
start : IN STD_LOGIC := '0';
|
|
testbuses : IN STD_LOGIC_VECTOR (number_of_channels - 1 DOWNTO 0) := (OTHERS => '0')
|
|
);
|
|
END alt_cal_c3gxb;
|
|
|
|
ARCHITECTURE RTL OF alt_cal_c3gxb IS
|
|
|
|
ATTRIBUTE synthesis_clearbox : natural;
|
|
ATTRIBUTE synthesis_clearbox OF RTL : ARCHITECTURE IS 1;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE : string;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF RTL : ARCHITECTURE IS "PRESERVE_REGISTER=ON";
|
|
|
|
SIGNAL p0addr_sim : STD_LOGIC_VECTOR(0 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '0')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF p0addr_sim : SIGNAL IS "PRESERVE_REGISTER=ON;POWER_UP_LEVEL=LOW";
|
|
|
|
SIGNAL wire_p0addr_sim_w_lg_w_lg_q4w5w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_p0addr_sim_w_lg_q4w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_reg : STD_LOGIC_VECTOR(3 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '0')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF sim_counter_reg : SIGNAL IS "POWER_UP_LEVEL=LOW";
|
|
SIGNAL first_run : STD_LOGIC_VECTOR(0 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '1')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF first_run : SIGNAL IS "POWER_UP_LEVEL=HIGH";
|
|
|
|
SIGNAL wire_next_scount_num_dataa : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_next_scount_num_datab : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_next_scount_num_result : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_w_lg_reset7w8w9w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_reset7w8w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_sim_counter_and2w3w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_sim_counter_and1w : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL wire_w_lg_reset7w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_sim_counter_and2w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL busy_sim : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_activator : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_and : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_next : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
|
SIGNAL sim_counter_or : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
BEGIN
|
|
|
|
loop0 : FOR i IN 0 TO 3 GENERATE
|
|
wire_w_lg_w_lg_w_lg_reset7w8w9w(i) <= (wire_w_lg_w_lg_reset7w8w(0) AND wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w(i) AND NOT (reset AND first_run(0))) OR (reset AND NOT first_run(0));
|
|
END GENERATE loop0;
|
|
wire_w_lg_w_lg_reset7w8w(0) <= (NOT start) AND sim_activator(0);
|
|
wire_w_lg_w_lg_sim_counter_and2w3w(0) <= wire_w_lg_sim_counter_and2w(0) AND sim_counter_or(0);
|
|
loop1 : FOR i IN 0 TO 3 GENERATE
|
|
wire_w_lg_sim_counter_and1w(i) <= sim_counter_and(0) AND sim_counter_reg(i);
|
|
END GENERATE loop1;
|
|
wire_w_lg_reset7w(0) <= NOT reset;
|
|
wire_w_lg_sim_counter_and2w(0) <= NOT sim_counter_and(0);
|
|
busy <= busy_sim(0);
|
|
busy_sim(0) <= (wire_w_lg_reset7w(0) AND p0addr_sim(0) AND wire_w_lg_sim_counter_and2w(0));
|
|
cal_error <= (OTHERS => '0');
|
|
dprio_addr <= (OTHERS => '0');
|
|
dprio_dataout <= (OTHERS => '0');
|
|
dprio_rden <= '0';
|
|
dprio_wren <= '0';
|
|
quad_addr <= (OTHERS => '0');
|
|
retain_addr <= '0';
|
|
sim_activator <= p0addr_sim;
|
|
sim_counter_and(0) <= (((sim_counter_reg(0) AND sim_counter_reg(1)) AND sim_counter_reg(2)) AND sim_counter_reg(3));
|
|
sim_counter_next <= wire_next_scount_num_result;
|
|
sim_counter_or(0) <= (((sim_counter_reg(0) OR sim_counter_reg(1)) OR sim_counter_reg(2)) OR sim_counter_reg(3));
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN p0addr_sim <= "1";
|
|
END IF;
|
|
END PROCESS;
|
|
loop2 : FOR i IN 0 TO 3 GENERATE
|
|
wire_p0addr_sim_w_lg_w_lg_q4w5w(i) <= wire_p0addr_sim_w_lg_q4w(0) AND sim_counter_next(i);
|
|
END GENERATE loop2;
|
|
loop3 : FOR i IN 0 TO 3 GENERATE
|
|
wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w(i) <= wire_p0addr_sim_w_lg_w_lg_q4w5w(i) OR wire_w_lg_sim_counter_and1w(i);
|
|
END GENERATE loop3;
|
|
wire_p0addr_sim_w_lg_q4w(0) <= p0addr_sim(0) OR wire_w_lg_w_lg_sim_counter_and2w3w(0);
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN sim_counter_reg <= wire_w_lg_w_lg_w_lg_reset7w8w9w;
|
|
END IF;
|
|
END PROCESS;
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN
|
|
IF (first_run(0) = '1') THEN
|
|
first_run(0) <= (NOT sim_counter_and(0));
|
|
ELSE
|
|
first_run(0) <= '0';
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
wire_next_scount_num_result <= wire_next_scount_num_dataa + wire_next_scount_num_datab;
|
|
wire_next_scount_num_dataa <= sim_counter_reg;
|
|
wire_next_scount_num_datab <= "0001";
|
|
|
|
END RTL;
|
|
--VALID FILE
|
|
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_unsigned.all;
|
|
|
|
--synthesis_resources = lut 4 reg 5
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
|
|
ENTITY alt_cal_sv IS
|
|
generic (
|
|
number_of_channels : integer := 1;
|
|
channel_address_width : integer := 1;
|
|
sim_model_mode : string := "TRUE";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "alt_cal_sv";
|
|
sample_length : integer := 100;
|
|
pma_base_address : integer := 0
|
|
);
|
|
PORT
|
|
(
|
|
busy : OUT STD_LOGIC;
|
|
clock : IN STD_LOGIC;
|
|
dprio_addr : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_busy : IN STD_LOGIC;
|
|
dprio_datain : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_dataout : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_rden : OUT STD_LOGIC;
|
|
dprio_wren : OUT STD_LOGIC;
|
|
quad_addr : OUT STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
remap_addr : IN STD_LOGIC_VECTOR (11 DOWNTO 0) := (OTHERS => '0');
|
|
reset : IN STD_LOGIC := '0';
|
|
start : IN STD_LOGIC := '0';
|
|
testbuses : IN STD_LOGIC_VECTOR (7 DOWNTO 0) := (OTHERS => '0')
|
|
);
|
|
END alt_cal_sv;
|
|
|
|
ARCHITECTURE RTL OF alt_cal_sv IS
|
|
|
|
ATTRIBUTE synthesis_clearbox : natural;
|
|
ATTRIBUTE synthesis_clearbox OF RTL : ARCHITECTURE IS 1;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE : string;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF RTL : ARCHITECTURE IS "PRESERVE_REGISTER=ON";
|
|
|
|
SIGNAL p0addr_sim : STD_LOGIC_VECTOR(0 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '0')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF p0addr_sim : SIGNAL IS "PRESERVE_REGISTER=ON;POWER_UP_LEVEL=LOW";
|
|
|
|
SIGNAL wire_p0addr_sim_w_lg_w_lg_q4w5w : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_p0addr_sim_w_lg_q4w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_reg : STD_LOGIC_VECTOR(8 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '0')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF sim_counter_reg : SIGNAL IS "POWER_UP_LEVEL=LOW";
|
|
SIGNAL first_run : STD_LOGIC_VECTOR(0 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '1')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF first_run : SIGNAL IS "POWER_UP_LEVEL=HIGH";
|
|
|
|
SIGNAL wire_next_scount_num_dataa : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_next_scount_num_datab : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_next_scount_num_result : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_w_lg_reset7w8w9w : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_reset7w8w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_sim_counter_and2w3w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_sim_counter_and1w : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_w_lg_reset7w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_sim_counter_and2w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL busy_sim : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_activator : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_and : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_next : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL sim_counter_or : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
BEGIN
|
|
|
|
loop0 : FOR i IN 0 TO 8 GENERATE
|
|
wire_w_lg_w_lg_w_lg_reset7w8w9w(i) <= (wire_w_lg_w_lg_reset7w8w(0) AND wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w(i) AND NOT (reset AND first_run(0))) OR (reset AND NOT first_run(0));
|
|
END GENERATE loop0;
|
|
wire_w_lg_w_lg_reset7w8w(0) <= (NOT start) AND sim_activator(0);
|
|
wire_w_lg_w_lg_sim_counter_and2w3w(0) <= wire_w_lg_sim_counter_and2w(0) AND sim_counter_or(0);
|
|
loop1 : FOR i IN 0 TO 8 GENERATE
|
|
wire_w_lg_sim_counter_and1w(i) <= sim_counter_and(0) AND sim_counter_reg(i);
|
|
END GENERATE loop1;
|
|
wire_w_lg_reset7w(0) <= NOT reset;
|
|
wire_w_lg_sim_counter_and2w(0) <= NOT sim_counter_and(0);
|
|
busy <= busy_sim(0);
|
|
busy_sim(0) <= (wire_w_lg_reset7w(0) AND p0addr_sim(0) AND wire_w_lg_sim_counter_and2w(0));
|
|
dprio_addr <= (OTHERS => '0');
|
|
dprio_dataout <= (OTHERS => '0');
|
|
dprio_rden <= '0';
|
|
dprio_wren <= '0';
|
|
quad_addr <= (OTHERS => '0');
|
|
sim_activator <= p0addr_sim;
|
|
sim_counter_and(0) <= (sim_counter_reg(0) AND sim_counter_reg(1) AND sim_counter_reg(2) AND sim_counter_reg(3) AND sim_counter_reg(4) AND sim_counter_reg(5) AND sim_counter_reg(6) AND sim_counter_reg(7) AND sim_counter_reg(8));
|
|
sim_counter_next <= wire_next_scount_num_result;
|
|
sim_counter_or(0) <= (sim_counter_reg(0) OR sim_counter_reg(1) OR sim_counter_reg(2) OR sim_counter_reg(3) OR sim_counter_reg(4) OR sim_counter_reg(5) OR sim_counter_reg(6) OR sim_counter_reg(7) OR sim_counter_reg(8));
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN p0addr_sim <= "1";
|
|
END IF;
|
|
END PROCESS;
|
|
loop2 : FOR i IN 0 TO 8 GENERATE
|
|
wire_p0addr_sim_w_lg_w_lg_q4w5w(i) <= wire_p0addr_sim_w_lg_q4w(0) AND sim_counter_next(i);
|
|
END GENERATE loop2;
|
|
loop3 : FOR i IN 0 TO 8 GENERATE
|
|
wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w(i) <= wire_p0addr_sim_w_lg_w_lg_q4w5w(i) OR wire_w_lg_sim_counter_and1w(i);
|
|
END GENERATE loop3;
|
|
wire_p0addr_sim_w_lg_q4w(0) <= p0addr_sim(0) OR wire_w_lg_w_lg_sim_counter_and2w3w(0);
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN sim_counter_reg <= wire_w_lg_w_lg_w_lg_reset7w8w9w;
|
|
END IF;
|
|
END PROCESS;
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN
|
|
IF (first_run(0) = '1') THEN
|
|
first_run(0) <= (NOT sim_counter_and(0));
|
|
ELSE
|
|
first_run(0) <= '0';
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
wire_next_scount_num_result <= wire_next_scount_num_dataa + wire_next_scount_num_datab;
|
|
wire_next_scount_num_dataa <= sim_counter_reg;
|
|
wire_next_scount_num_datab <= "000000001";
|
|
|
|
END RTL;
|
|
--VALID FILE
|
|
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_unsigned.all;
|
|
|
|
--synthesis_resources = lut 4 reg 5
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
|
|
ENTITY alt_cal_av IS
|
|
generic (
|
|
number_of_channels : integer := 1;
|
|
channel_address_width : integer := 1;
|
|
sim_model_mode : string := "TRUE";
|
|
lpm_hint : string := "UNUSED";
|
|
lpm_type : string := "alt_cal_av";
|
|
sample_length : integer := 100;
|
|
pma_base_address : integer := 0
|
|
);
|
|
PORT
|
|
(
|
|
busy : OUT STD_LOGIC;
|
|
clock : IN STD_LOGIC;
|
|
dprio_addr : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_busy : IN STD_LOGIC;
|
|
dprio_datain : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_dataout : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
|
|
dprio_rden : OUT STD_LOGIC;
|
|
dprio_wren : OUT STD_LOGIC;
|
|
quad_addr : OUT STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
remap_addr : IN STD_LOGIC_VECTOR (11 DOWNTO 0) := (OTHERS => '0');
|
|
reset : IN STD_LOGIC := '0';
|
|
start : IN STD_LOGIC := '0';
|
|
testbuses : IN STD_LOGIC_VECTOR (7 DOWNTO 0) := (OTHERS => '0')
|
|
);
|
|
END alt_cal_av;
|
|
|
|
ARCHITECTURE RTL OF alt_cal_av IS
|
|
|
|
ATTRIBUTE synthesis_clearbox : natural;
|
|
ATTRIBUTE synthesis_clearbox OF RTL : ARCHITECTURE IS 1;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE : string;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF RTL : ARCHITECTURE IS "PRESERVE_REGISTER=ON";
|
|
|
|
SIGNAL p0addr_sim : STD_LOGIC_VECTOR(0 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '0')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF p0addr_sim : SIGNAL IS "PRESERVE_REGISTER=ON;POWER_UP_LEVEL=LOW";
|
|
|
|
SIGNAL wire_p0addr_sim_w_lg_w_lg_q4w5w : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_p0addr_sim_w_lg_q4w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_reg : STD_LOGIC_VECTOR(8 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '0')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF sim_counter_reg : SIGNAL IS "POWER_UP_LEVEL=LOW";
|
|
SIGNAL first_run : STD_LOGIC_VECTOR(0 DOWNTO 0)
|
|
-- synopsys translate_off
|
|
:= (OTHERS => '1')
|
|
-- synopsys translate_on
|
|
;
|
|
ATTRIBUTE ALTERA_ATTRIBUTE OF first_run : SIGNAL IS "POWER_UP_LEVEL=HIGH";
|
|
|
|
SIGNAL wire_next_scount_num_dataa : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_next_scount_num_datab : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_next_scount_num_result : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_w_lg_reset7w8w9w : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_reset7w8w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_w_lg_sim_counter_and2w3w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_sim_counter_and1w : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL wire_w_lg_reset7w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL wire_w_lg_sim_counter_and2w : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL busy_sim : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_activator : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_and : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
SIGNAL sim_counter_next : STD_LOGIC_VECTOR (8 DOWNTO 0);
|
|
SIGNAL sim_counter_or : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
|
BEGIN
|
|
|
|
loop0 : FOR i IN 0 TO 8 GENERATE
|
|
wire_w_lg_w_lg_w_lg_reset7w8w9w(i) <= (wire_w_lg_w_lg_reset7w8w(0) AND wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w(i) AND NOT (reset AND first_run(0))) OR (reset AND NOT first_run(0));
|
|
END GENERATE loop0;
|
|
wire_w_lg_w_lg_reset7w8w(0) <= (NOT start) AND sim_activator(0);
|
|
wire_w_lg_w_lg_sim_counter_and2w3w(0) <= wire_w_lg_sim_counter_and2w(0) AND sim_counter_or(0);
|
|
loop1 : FOR i IN 0 TO 8 GENERATE
|
|
wire_w_lg_sim_counter_and1w(i) <= sim_counter_and(0) AND sim_counter_reg(i);
|
|
END GENERATE loop1;
|
|
wire_w_lg_reset7w(0) <= NOT reset;
|
|
wire_w_lg_sim_counter_and2w(0) <= NOT sim_counter_and(0);
|
|
busy <= busy_sim(0);
|
|
busy_sim(0) <= (wire_w_lg_reset7w(0) AND p0addr_sim(0) AND wire_w_lg_sim_counter_and2w(0));
|
|
dprio_addr <= (OTHERS => '0');
|
|
dprio_dataout <= (OTHERS => '0');
|
|
dprio_rden <= '0';
|
|
dprio_wren <= '0';
|
|
quad_addr <= (OTHERS => '0');
|
|
sim_activator <= p0addr_sim;
|
|
sim_counter_and(0) <= (sim_counter_reg(0) AND sim_counter_reg(1) AND sim_counter_reg(2) AND sim_counter_reg(3) AND sim_counter_reg(4) AND sim_counter_reg(5) AND sim_counter_reg(6) AND sim_counter_reg(7) AND sim_counter_reg(8));
|
|
sim_counter_next <= wire_next_scount_num_result;
|
|
sim_counter_or(0) <= (sim_counter_reg(0) OR sim_counter_reg(1) OR sim_counter_reg(2) OR sim_counter_reg(3) OR sim_counter_reg(4) OR sim_counter_reg(5) OR sim_counter_reg(6) OR sim_counter_reg(7) OR sim_counter_reg(8));
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN p0addr_sim <= "1";
|
|
END IF;
|
|
END PROCESS;
|
|
loop2 : FOR i IN 0 TO 8 GENERATE
|
|
wire_p0addr_sim_w_lg_w_lg_q4w5w(i) <= wire_p0addr_sim_w_lg_q4w(0) AND sim_counter_next(i);
|
|
END GENERATE loop2;
|
|
loop3 : FOR i IN 0 TO 8 GENERATE
|
|
wire_p0addr_sim_w_lg_w_lg_w_lg_q4w5w6w(i) <= wire_p0addr_sim_w_lg_w_lg_q4w5w(i) OR wire_w_lg_sim_counter_and1w(i);
|
|
END GENERATE loop3;
|
|
wire_p0addr_sim_w_lg_q4w(0) <= p0addr_sim(0) OR wire_w_lg_w_lg_sim_counter_and2w3w(0);
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN sim_counter_reg <= wire_w_lg_w_lg_w_lg_reset7w8w9w;
|
|
END IF;
|
|
END PROCESS;
|
|
PROCESS (clock)
|
|
BEGIN
|
|
IF (clock = '1' AND clock'event) THEN
|
|
IF (first_run(0) = '1') THEN
|
|
first_run(0) <= (NOT sim_counter_and(0));
|
|
ELSE
|
|
first_run(0) <= '0';
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
wire_next_scount_num_result <= wire_next_scount_num_dataa + wire_next_scount_num_datab;
|
|
wire_next_scount_num_dataa <= sim_counter_reg;
|
|
wire_next_scount_num_datab <= "000000001";
|
|
|
|
END RTL;
|
|
--VALID FILE
|
|
|
|
-------------------------------------------------------------------
|
|
-- Filename : alt_aeq_s4.vhd
|
|
--
|
|
-- Description : Simulation model for ADCE
|
|
--
|
|
-- Limitation : Currently, only applies for Stratix IV
|
|
--
|
|
-- Copyright (c) Altera Corporation 1997-2008
|
|
-- All rights reserved
|
|
--
|
|
---------------------------------------------------------------------
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
USE ieee.std_logic_unsigned.all;
|
|
|
|
LIBRARY std;
|
|
USE std.textio.all;
|
|
|
|
PACKAGE alt_aeq_s4_func IS
|
|
FUNCTION to_integer (
|
|
val : std_logic) RETURN integer;
|
|
|
|
FUNCTION to_integer (
|
|
val : std_logic_vector) RETURN integer;
|
|
|
|
FUNCTION or_br (
|
|
val : std_logic_vector) RETURN std_logic;
|
|
|
|
END;
|
|
|
|
PACKAGE BODY alt_aeq_s4_func IS
|
|
|
|
FUNCTION to_integer (
|
|
val : std_logic) RETURN integer IS
|
|
|
|
VARIABLE rtn : integer := 0;
|
|
BEGIN
|
|
IF (val = '1') THEN
|
|
rtn := 1;
|
|
ELSE
|
|
rtn := 0;
|
|
END IF;
|
|
RETURN(rtn);
|
|
END to_integer;
|
|
|
|
--
|
|
|
|
FUNCTION to_integer (
|
|
val : std_logic_vector) RETURN integer IS
|
|
|
|
CONSTANT vec : std_logic_vector(val'high-val'low DOWNTO 0) := val;
|
|
VARIABLE rtn : integer := 0;
|
|
BEGIN
|
|
FOR index IN vec'RANGE LOOP
|
|
IF (vec(index) = '1') THEN
|
|
rtn := rtn + (2**index);
|
|
END IF;
|
|
END LOOP;
|
|
RETURN(rtn);
|
|
END to_integer;
|
|
|
|
FUNCTION or_br (
|
|
val : std_logic_vector) RETURN std_logic IS
|
|
|
|
VARIABLE rtn : std_logic := '0';
|
|
BEGIN
|
|
FOR index IN val'RANGE LOOP
|
|
rtn := rtn OR val(index);
|
|
END LOOP;
|
|
RETURN(rtn);
|
|
END or_br;
|
|
|
|
|
|
|
|
END;
|
|
|
|
|
|
--
|
|
|
|
|
|
USE work.alt_aeq_s4_func.all;
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
USE ieee.std_logic_unsigned.all;
|
|
|
|
ENTITY alt_aeq_s4 IS
|
|
GENERIC (
|
|
|
|
show_errors : STRING := "NO";
|
|
radce_hflck : INTEGER := 0;
|
|
radce_lflck : INTEGER := 0;
|
|
use_hw_conv_det : INTEGER := 0;
|
|
|
|
number_of_channels : INTEGER := 5;
|
|
channel_address_width : INTEGER := 3;
|
|
lpm_type : STRING := "alt_aeq_s4";
|
|
lpm_hint : STRING := "UNUSED"
|
|
);
|
|
PORT (
|
|
|
|
reconfig_clk : IN STD_LOGIC;
|
|
aclr : IN STD_LOGIC;
|
|
calibrate : IN STD_LOGIC;
|
|
shutdown : IN STD_LOGIC;
|
|
all_channels : IN STD_LOGIC;
|
|
logical_channel_address : IN STD_LOGIC_VECTOR(channel_address_width - 1 DOWNTO 0);
|
|
remap_address : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
|
|
quad_address : OUT STD_LOGIC_VECTOR(8 DOWNTO 0);
|
|
adce_done : IN STD_LOGIC_VECTOR(number_of_channels - 1 DOWNTO 0);
|
|
busy : OUT STD_LOGIC;
|
|
adce_standby : OUT STD_LOGIC_VECTOR(number_of_channels - 1 DOWNTO 0);
|
|
adce_continuous : IN STD_LOGIC;
|
|
adce_cal_busy : OUT STD_LOGIC;
|
|
|
|
dprio_busy : IN STD_LOGIC;
|
|
dprio_in : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
|
|
dprio_wren : OUT STD_LOGIC;
|
|
dprio_rden : OUT STD_LOGIC;
|
|
dprio_addr : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
|
|
dprio_data : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
|
|
|
|
eqout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
|
|
timeout : OUT STD_LOGIC;
|
|
testbuses : IN STD_LOGIC_VECTOR(7 * number_of_channels - 1 DOWNTO 0);
|
|
testbus_sels : OUT STD_LOGIC_VECTOR(4 * number_of_channels - 1 DOWNTO 0);
|
|
|
|
conv_error : OUT STD_LOGIC_VECTOR(number_of_channels - 1 DOWNTO 0);
|
|
error : OUT STD_LOGIC_VECTOR(number_of_channels - 1 DOWNTO 0)
|
|
);
|
|
END alt_aeq_s4;
|
|
|
|
ARCHITECTURE trans OF alt_aeq_s4 IS
|
|
|
|
SIGNAL busy_counter : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
|
|
-- Declare intermediate signals for referenced outputs
|
|
SIGNAL busy_xhdl0 : STD_LOGIC;
|
|
SIGNAL adce_cal_busy_xhdl0 : STD_LOGIC;
|
|
BEGIN
|
|
-- Drive referenced outputs
|
|
busy <= busy_xhdl0;
|
|
adce_cal_busy <= adce_cal_busy_xhdl0;
|
|
|
|
dprio_addr <= (OTHERS => '0');
|
|
dprio_data <= (OTHERS => '0');
|
|
dprio_rden <= '0';
|
|
dprio_wren <= '0';
|
|
quad_address <= (OTHERS => '0');
|
|
busy_xhdl0 <= (or_br(busy_counter));
|
|
adce_cal_busy_xhdl0 <= (or_br(busy_counter(7 downto 4)));
|
|
timeout <= '0';
|
|
|
|
error <= (OTHERS => '0');
|
|
conv_error <= (OTHERS => '0');
|
|
eqout <= (OTHERS => '0');
|
|
testbus_sels <= (OTHERS => '0');
|
|
|
|
|
|
PROCESS (reconfig_clk)
|
|
BEGIN
|
|
IF (reconfig_clk'EVENT AND reconfig_clk = '1') THEN
|
|
IF (aclr = '1') THEN
|
|
busy_counter <= "00000000";
|
|
adce_standby(to_integer(logical_channel_address)) <= '0';
|
|
ELSIF (calibrate = '1') THEN
|
|
busy_counter <= "11111111";
|
|
adce_standby <= (OTHERS => '0');
|
|
ELSIF (shutdown = '1') THEN
|
|
busy_counter <= "00001111";
|
|
adce_standby(to_integer(logical_channel_address)) <= '1';
|
|
ELSIF (busy_xhdl0 = '1') THEN
|
|
busy_counter <= busy_counter - "00000001";
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
|
|
END trans;
|
|
|
|
|
|
|
|
-------------------------------------------------------------------
|
|
-- Filename : alt_eyemon.vhd
|
|
--
|
|
-- Description : Simulation model for Eye Monitor (EyeQ)
|
|
--
|
|
-- Limitation : Currently, only supported for Stratix IV
|
|
--
|
|
-- Copyright (c) Altera Corporation 1997-2008
|
|
-- All rights reserved
|
|
--
|
|
---------------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
library std;
|
|
use std.textio.all;
|
|
|
|
package alt_eyemon_func is
|
|
|
|
function or_br (
|
|
val : std_logic_vector) return std_logic;
|
|
|
|
FUNCTION to_integer (
|
|
val : bit_vector) RETURN integer;
|
|
|
|
FUNCTION to_integer (
|
|
val : std_logic_vector) RETURN integer;
|
|
|
|
function to_integer (
|
|
val : std_logic) return integer;
|
|
|
|
function to_stdlogic (
|
|
val : in boolean) return std_logic;
|
|
|
|
function to_stdlogicvector (
|
|
val : in integer;
|
|
len : in integer) return std_logic_vector;
|
|
|
|
function to_stdlogicvector (
|
|
val : in boolean;
|
|
len : in integer) return std_logic_vector;
|
|
|
|
end;
|
|
|
|
package body alt_eyemon_func is
|
|
|
|
function to_integer (
|
|
val : bit_vector) return integer is
|
|
|
|
constant vec : bit_vector(val'high-val'low downto 0) := val;
|
|
variable rtn : integer := 0;
|
|
begin
|
|
for index in vec'range loop
|
|
if (vec(index) = '1') then
|
|
rtn := rtn + (2**index);
|
|
end if;
|
|
end loop;
|
|
return(rtn);
|
|
end to_integer;
|
|
|
|
--
|
|
|
|
function to_integer (
|
|
val : std_logic_vector) return integer is
|
|
|
|
constant vec : std_logic_vector(val'high-val'low downto 0) := val;
|
|
variable rtn : integer := 0;
|
|
begin
|
|
for index in vec'range loop
|
|
if (vec(index) = '1') then
|
|
rtn := rtn + (2**index);
|
|
end if;
|
|
end loop;
|
|
return(rtn);
|
|
end to_integer;
|
|
|
|
--
|
|
|
|
function or_br (
|
|
val : std_logic_vector) return std_logic is
|
|
|
|
variable rtn : std_logic := '0';
|
|
begin
|
|
for index in val'range loop
|
|
rtn := rtn or val(index);
|
|
end loop;
|
|
return(rtn);
|
|
end or_br;
|
|
|
|
--
|
|
|
|
function to_integer (
|
|
val : std_logic) return integer is
|
|
|
|
variable rtn : integer := 0;
|
|
begin
|
|
if (val = '1') then
|
|
rtn := 1;
|
|
else
|
|
rtn := 0;
|
|
end if;
|
|
return(rtn);
|
|
end to_integer;
|
|
|
|
--
|
|
|
|
function to_stdlogic (
|
|
val : in boolean) return std_logic is
|
|
begin
|
|
if (val) then
|
|
return('1');
|
|
else
|
|
return('0');
|
|
end if;
|
|
end to_stdlogic;
|
|
|
|
--
|
|
|
|
function to_stdlogicvector (
|
|
val : in integer;
|
|
len : in integer) return std_logic_vector is
|
|
|
|
variable rtn : std_logic_vector(len-1 downto 0) := (others => '0');
|
|
variable num : integer := val;
|
|
variable r : integer;
|
|
begin
|
|
for index in 0 to len-1 loop
|
|
r := num rem 2;
|
|
num := num/2;
|
|
if (r = 1) then
|
|
rtn(index) := '1';
|
|
else
|
|
rtn(index) := '0';
|
|
end if;
|
|
end loop;
|
|
return(rtn);
|
|
end to_stdlogicvector;
|
|
|
|
--
|
|
|
|
function to_stdlogicvector (
|
|
val : in boolean;
|
|
len : in integer) return std_logic_vector is
|
|
|
|
variable rtn : std_logic_vector(len-1 downto 0) := (others => '0');
|
|
begin
|
|
rtn(0) := to_stdlogic(val);
|
|
return(rtn);
|
|
end to_stdlogicvector;
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
--
|
|
|
|
use work.alt_eyemon_func.all;
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
|
|
entity alt_eyemon is
|
|
generic (
|
|
channel_address_width : integer := 3;
|
|
lpm_type : string := "alt_eyemon";
|
|
lpm_hint : string := "UNUSED";
|
|
|
|
avmm_slave_addr_width : integer := 16;
|
|
avmm_slave_rdata_width : integer := 16;
|
|
avmm_slave_wdata_width : integer := 16;
|
|
|
|
avmm_master_addr_width : integer := 16;
|
|
avmm_master_rdata_width : integer := 16;
|
|
avmm_master_wdata_width : integer := 16;
|
|
|
|
dprio_addr_width : integer := 16;
|
|
dprio_data_width : integer := 16;
|
|
ireg_wdaddr_width : integer := 2;
|
|
ireg_chaddr_width : integer := 2;
|
|
ireg_data_width : integer := 16
|
|
|
|
);
|
|
port (
|
|
i_resetn : in std_logic;
|
|
i_avmm_clk : in std_logic;
|
|
|
|
i_avmm_saddress : in std_logic_vector(avmm_slave_addr_width - 1 downto 0);
|
|
i_avmm_sread : in std_logic;
|
|
i_avmm_swrite : in std_logic;
|
|
i_avmm_swritedata : in std_logic_vector(avmm_slave_wdata_width - 1 downto 0);
|
|
o_avmm_sreaddata : out std_logic_vector(avmm_slave_rdata_width - 1 downto 0);
|
|
o_avmm_swaitrequest : out std_logic;
|
|
|
|
i_remap_phase : in std_logic;
|
|
i_remap_address : in std_logic_vector(11 downto 0);
|
|
o_quad_address : out std_logic_vector(8 downto 0);
|
|
o_reconfig_busy : out std_logic;
|
|
|
|
i_dprio_busy : in std_logic;
|
|
i_dprio_in : in std_logic_vector(dprio_data_width - 1 downto 0);
|
|
o_dprio_wren : out std_logic;
|
|
o_dprio_rden : out std_logic;
|
|
o_dprio_addr : out std_logic_vector(dprio_addr_width - 1 downto 0);
|
|
o_dprio_data : out std_logic_vector(dprio_data_width - 1 downto 0)
|
|
);
|
|
end alt_eyemon;
|
|
|
|
architecture trans of alt_eyemon is
|
|
type type_xhdl0 is array (((2 ** channel_address_width) - 1) downto 0) of std_logic_vector(6 downto 0);
|
|
type state_type is (ST_IDLE, ST_WRITE, ST_READ);
|
|
|
|
signal state : state_type := ST_IDLE;
|
|
signal state0q : state_type := ST_IDLE;
|
|
signal reg_read : std_logic;
|
|
signal reg_write : std_logic;
|
|
signal busy_counter : std_logic_vector(5 downto 0) := "000000";
|
|
|
|
signal reg_chaddress : std_logic_vector(channel_address_width - 1 downto 0) := to_stdlogicvector(0, channel_address_width);
|
|
signal reg_chaddress0q : std_logic_vector(channel_address_width - 1 downto 0) := to_stdlogicvector(0, channel_address_width);
|
|
signal reg_data : std_logic_vector(ireg_data_width - 1 downto 0) := to_stdlogicvector(0, ireg_data_width);
|
|
signal reg_data0q : std_logic_vector(ireg_data_width - 1 downto 0) := to_stdlogicvector(0, ireg_data_width);
|
|
signal reg_ctrlstatus : std_logic_vector(ireg_data_width - 1 downto 0) := to_stdlogicvector(0, ireg_data_width);
|
|
signal reg_ctrlstatus0q : std_logic_vector(ireg_data_width - 1 downto 0) := to_stdlogicvector(0, ireg_data_width);
|
|
signal reg_wdaddress : std_logic_vector(ireg_wdaddr_width - 1 downto 0) := to_stdlogicvector(0, ireg_wdaddr_width);
|
|
signal reg_wdaddress0q : std_logic_vector(ireg_wdaddr_width - 1 downto 0) := to_stdlogicvector(0, ireg_wdaddr_width);
|
|
|
|
signal dprio_reg : type_xhdl0;
|
|
signal dprio_reg0q : type_xhdl0;
|
|
|
|
signal invalid_channel_address : std_logic;
|
|
signal invalid_word_address : std_logic;
|
|
signal i : integer;
|
|
-- X-HDL generated signals
|
|
|
|
signal xhdl1 : std_logic;
|
|
signal xhdl2 : std_logic;
|
|
begin
|
|
|
|
o_dprio_wren <= '0';
|
|
o_dprio_rden <= '0';
|
|
o_dprio_addr <= (others => '0');
|
|
o_dprio_data <=(others => '0');
|
|
o_quad_address <= (others => '0');
|
|
o_reconfig_busy <= reg_ctrlstatus0q(15);
|
|
|
|
process (i_avmm_clk)
|
|
begin
|
|
if (i_avmm_clk'event and i_avmm_clk = '1') then
|
|
if ((not(i_resetn)) = '1') then
|
|
state0q <= ST_IDLE;
|
|
else
|
|
state0q <= state;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
process (i_avmm_clk)
|
|
begin
|
|
if (i_avmm_clk'event and i_avmm_clk = '1') then
|
|
if ((not(i_resetn)) = '1') then
|
|
busy_counter <= "000000";
|
|
elsif (((reg_ctrlstatus(0) = '1') and (reg_ctrlstatus0q(0) = '0')) and ((not(reg_ctrlstatus(1))) = '1')) then
|
|
busy_counter <= "111111";
|
|
elsif (((reg_ctrlstatus(0) = '1') and (reg_ctrlstatus0q(0) = '0')) and ((reg_ctrlstatus(1)) = '1')) then
|
|
busy_counter <= "011111";
|
|
elsif ((or_BR(busy_counter)) = '1') then
|
|
busy_counter <= busy_counter - "000001";
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
process (state0q, i_avmm_sread, i_avmm_swrite, reg_ctrlstatus0q)
|
|
begin
|
|
o_avmm_swaitrequest <= '0';
|
|
reg_write <= '0';
|
|
|
|
reg_read <= '0';
|
|
case state0q is
|
|
when ST_WRITE =>
|
|
o_avmm_swaitrequest <= '0';
|
|
state <= ST_IDLE;
|
|
when ST_READ =>
|
|
o_avmm_swaitrequest <= '0';
|
|
reg_read <= '1';
|
|
state <= ST_IDLE;
|
|
when others =>
|
|
if (i_avmm_sread = '1') then
|
|
o_avmm_swaitrequest <= '1';
|
|
reg_read <= '1';
|
|
state <= ST_READ;
|
|
elsif (i_avmm_swrite = '1') then
|
|
o_avmm_swaitrequest <= '1';
|
|
if ((reg_ctrlstatus0q(15)) = '1') then
|
|
reg_write <= '0';
|
|
else
|
|
reg_write <= '1';
|
|
end if;
|
|
state <= ST_WRITE;
|
|
else
|
|
o_avmm_swaitrequest <= '0';
|
|
state <= ST_IDLE;
|
|
end if;
|
|
end case;
|
|
end process;
|
|
|
|
|
|
process (i_avmm_clk)
|
|
begin
|
|
if (i_avmm_clk'event and i_avmm_clk = '1') then
|
|
if ((not(i_resetn)) = '1') then
|
|
reg_chaddress0q <= (others => '0');
|
|
reg_data0q <= (others => '0');
|
|
reg_ctrlstatus0q <= (others => '0');
|
|
reg_wdaddress0q <= (others => '0');
|
|
for i in 0 to ((2 ** channel_address_width)) - 1 loop
|
|
dprio_reg0q(i) <= (others => '0');
|
|
end loop;
|
|
else
|
|
reg_chaddress0q <= reg_chaddress;
|
|
reg_data0q <= reg_data;
|
|
reg_ctrlstatus0q <= reg_ctrlstatus;
|
|
reg_wdaddress0q <= reg_wdaddress;
|
|
for i in 0 to ((2 ** channel_address_width)) - 1 loop
|
|
dprio_reg0q(i) <= dprio_reg(i);
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process (reg_read, i_avmm_saddress, reg_ctrlstatus0q, reg_chaddress0q, reg_wdaddress0q, reg_data0q)
|
|
begin
|
|
if (reg_read = '1') then
|
|
if (i_avmm_saddress (15 downto 0) = "0000000000000000") then
|
|
o_avmm_sreaddata(ireg_data_width - 1 downto 0) <= reg_ctrlstatus0q;
|
|
elsif (i_avmm_saddress (15 downto 0)= "0000000000000001") then
|
|
o_avmm_sreaddata(channel_address_width - 1 downto 0) <= reg_chaddress0q;
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000010") then
|
|
o_avmm_sreaddata(ireg_wdaddr_width - 1 downto 0) <= reg_wdaddress0q;
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000011") then
|
|
o_avmm_sreaddata <= reg_data0q;
|
|
else
|
|
o_avmm_sreaddata <= (others => '0');
|
|
end if;
|
|
else
|
|
o_avmm_sreaddata <= (others => '0');
|
|
end if;
|
|
end process;
|
|
invalid_channel_address <= to_stdlogic((i_remap_address = "111111111111"));
|
|
invalid_word_address <= to_stdlogic((reg_wdaddress0q > "01"));
|
|
|
|
|
|
xhdl1 <= '0' when ((i_avmm_swritedata(14)) = '1') else
|
|
reg_ctrlstatus0q(14);
|
|
xhdl2 <= '0' when ((i_avmm_swritedata(13)) = '1') else
|
|
reg_ctrlstatus0q(13);
|
|
process (reg_chaddress0q, reg_data0q, reg_ctrlstatus0q, reg_wdaddress0q, i, dprio_reg, busy_counter, dprio_reg0q, reg_write, i_avmm_saddress, i_avmm_swritedata, invalid_channel_address, invalid_word_address)
|
|
begin
|
|
reg_chaddress <= reg_chaddress0q;
|
|
reg_data <= reg_data0q;
|
|
reg_ctrlstatus <= reg_ctrlstatus0q;
|
|
reg_wdaddress <= reg_wdaddress0q;
|
|
for i in 0 to ((2 ** channel_address_width)) - 1 loop
|
|
dprio_reg0q(i) <= dprio_reg(i);
|
|
end loop;
|
|
if (busy_counter = "000001") then
|
|
reg_ctrlstatus(15) <= '0';
|
|
reg_ctrlstatus(0) <= '0';
|
|
if ((reg_ctrlstatus0q(1)) = '1') then
|
|
if (reg_wdaddress0q = "00") then
|
|
reg_data(0) <= dprio_reg0q(to_integer(reg_chaddress0q))(0);
|
|
reg_data(15 downto 1) <= "000000000000000";
|
|
elsif (reg_wdaddress0q = "01") then
|
|
reg_data(5 downto 0) <= dprio_reg0q(to_integer(reg_chaddress0q))(6 downto 1);
|
|
reg_data(15 downto 6) <= "0000000000";
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (reg_write = '1') then
|
|
if (i_avmm_saddress = "0000000000000000") then
|
|
reg_ctrlstatus(1) <= i_avmm_swritedata(1);
|
|
if ((i_avmm_swritedata(0)) = '1') then
|
|
if ((invalid_channel_address = '1') or (invalid_word_address = '1')) then
|
|
reg_ctrlstatus(15) <= '0';
|
|
reg_ctrlstatus(14) <= invalid_word_address;
|
|
reg_ctrlstatus(13) <= invalid_channel_address;
|
|
else
|
|
if ((not(i_avmm_swritedata(1))) = '1') then
|
|
if (reg_wdaddress0q = "00") then
|
|
dprio_reg(to_integer(reg_chaddress0q))(0) <= (reg_data0q(0));
|
|
elsif (reg_wdaddress0q = "01") then
|
|
dprio_reg(to_integer(reg_chaddress0q))(6 downto 1) <= (reg_data0q(5 downto 0));
|
|
end if;
|
|
end if;
|
|
reg_ctrlstatus(0) <= '1';
|
|
reg_ctrlstatus(15) <= '1';
|
|
reg_ctrlstatus(14) <= '0';
|
|
reg_ctrlstatus(13) <= '0';
|
|
end if;
|
|
else
|
|
reg_ctrlstatus(15) <= '0';
|
|
reg_ctrlstatus(14) <= xhdl1;
|
|
reg_ctrlstatus(13) <= xhdl2;
|
|
end if;
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000001") then
|
|
if (channel_address_width < 2) then
|
|
reg_chaddress <= i_avmm_swritedata(0 downto 0);
|
|
else
|
|
reg_chaddress <= i_avmm_swritedata(channel_address_width - 1 downto 0);
|
|
end if;
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000010") then
|
|
reg_wdaddress <= i_avmm_swritedata(ireg_wdaddr_width - 1 downto 0);
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000011") then
|
|
reg_data <= i_avmm_swritedata(ireg_data_width - 1 downto 0);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
end trans;
|
|
-------------------------------------------------------------------
|
|
-- Filename : alt_dfe.vhd
|
|
--
|
|
-- Description : Simulation model for DFE
|
|
--
|
|
-- Limitation : Currently, only supported for Stratix IV
|
|
--
|
|
-- Copyright (c) Altera Corporation 1997-2008
|
|
-- All rights reserved
|
|
--
|
|
---------------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
library std;
|
|
use std.textio.all;
|
|
|
|
package alt_dfe_func is
|
|
|
|
function or_br (
|
|
val : std_logic_vector) return std_logic;
|
|
|
|
FUNCTION to_integer (
|
|
val : bit_vector) RETURN integer;
|
|
|
|
FUNCTION to_integer (
|
|
val : std_logic_vector) RETURN integer;
|
|
|
|
function to_integer (
|
|
val : std_logic) return integer;
|
|
|
|
function to_stdlogic (
|
|
val : in boolean) return std_logic;
|
|
|
|
function to_stdlogicvector (
|
|
val : in integer;
|
|
len : in integer) return std_logic_vector;
|
|
|
|
function to_stdlogicvector (
|
|
val : in boolean;
|
|
len : in integer) return std_logic_vector;
|
|
|
|
end;
|
|
|
|
package body alt_dfe_func is
|
|
|
|
function to_integer (
|
|
val : bit_vector) return integer is
|
|
|
|
constant vec : bit_vector(val'high-val'low downto 0) := val;
|
|
variable rtn : integer := 0;
|
|
begin
|
|
for index in vec'range loop
|
|
if (vec(index) = '1') then
|
|
rtn := rtn + (2**index);
|
|
end if;
|
|
end loop;
|
|
return(rtn);
|
|
end to_integer;
|
|
|
|
--
|
|
|
|
function to_integer (
|
|
val : std_logic_vector) return integer is
|
|
|
|
constant vec : std_logic_vector(val'high-val'low downto 0) := val;
|
|
variable rtn : integer := 0;
|
|
begin
|
|
for index in vec'range loop
|
|
if (vec(index) = '1') then
|
|
rtn := rtn + (2**index);
|
|
end if;
|
|
end loop;
|
|
return(rtn);
|
|
end to_integer;
|
|
|
|
--
|
|
|
|
function or_br (
|
|
val : std_logic_vector) return std_logic is
|
|
|
|
variable rtn : std_logic := '0';
|
|
begin
|
|
for index in val'range loop
|
|
rtn := rtn or val(index);
|
|
end loop;
|
|
return(rtn);
|
|
end or_br;
|
|
|
|
--
|
|
|
|
function to_integer (
|
|
val : std_logic) return integer is
|
|
|
|
variable rtn : integer := 0;
|
|
begin
|
|
if (val = '1') then
|
|
rtn := 1;
|
|
else
|
|
rtn := 0;
|
|
end if;
|
|
return(rtn);
|
|
end to_integer;
|
|
|
|
--
|
|
|
|
function to_stdlogic (
|
|
val : in boolean) return std_logic is
|
|
begin
|
|
if (val) then
|
|
return('1');
|
|
else
|
|
return('0');
|
|
end if;
|
|
end to_stdlogic;
|
|
|
|
--
|
|
|
|
function to_stdlogicvector (
|
|
val : in integer;
|
|
len : in integer) return std_logic_vector is
|
|
|
|
variable rtn : std_logic_vector(len-1 downto 0) := (others => '0');
|
|
variable num : integer := val;
|
|
variable r : integer;
|
|
begin
|
|
for index in 0 to len-1 loop
|
|
r := num rem 2;
|
|
num := num/2;
|
|
if (r = 1) then
|
|
rtn(index) := '1';
|
|
else
|
|
rtn(index) := '0';
|
|
end if;
|
|
end loop;
|
|
return(rtn);
|
|
end to_stdlogicvector;
|
|
|
|
--
|
|
|
|
function to_stdlogicvector (
|
|
val : in boolean;
|
|
len : in integer) return std_logic_vector is
|
|
|
|
variable rtn : std_logic_vector(len-1 downto 0) := (others => '0');
|
|
begin
|
|
rtn(0) := to_stdlogic(val);
|
|
return(rtn);
|
|
end to_stdlogicvector;
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
--
|
|
|
|
use work.alt_dfe_func.all;
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
|
|
entity alt_dfe is
|
|
generic (
|
|
channel_address_width : integer := 3;
|
|
lpm_type : string := "alt_dfe";
|
|
lpm_hint : string := "UNUSED";
|
|
|
|
avmm_slave_addr_width : integer := 16;
|
|
avmm_slave_rdata_width : integer := 16;
|
|
avmm_slave_wdata_width : integer := 16;
|
|
|
|
avmm_master_addr_width : integer := 16;
|
|
avmm_master_rdata_width : integer := 16;
|
|
avmm_master_wdata_width : integer := 16;
|
|
|
|
dprio_addr_width : integer := 16;
|
|
dprio_data_width : integer := 16;
|
|
ireg_chaddr_width : integer := 2;
|
|
ireg_wdaddr_width : integer := 2;
|
|
ireg_data_width : integer := 16
|
|
|
|
);
|
|
port (
|
|
i_resetn : in std_logic;
|
|
i_avmm_clk : in std_logic;
|
|
|
|
i_avmm_saddress : in std_logic_vector(avmm_slave_addr_width - 1 downto 0);
|
|
i_avmm_sread : in std_logic;
|
|
i_avmm_swrite : in std_logic;
|
|
i_avmm_swritedata : in std_logic_vector(avmm_slave_wdata_width - 1 downto 0);
|
|
o_avmm_sreaddata : out std_logic_vector(avmm_slave_rdata_width - 1 downto 0);
|
|
o_avmm_swaitrequest : out std_logic;
|
|
|
|
i_remap_address : in std_logic_vector(11 downto 0);
|
|
o_quad_address : out std_logic_vector(8 downto 0);
|
|
o_reconfig_busy : out std_logic;
|
|
|
|
i_dprio_busy : in std_logic;
|
|
i_dprio_in : in std_logic_vector(dprio_data_width - 1 downto 0);
|
|
o_dprio_wren : out std_logic;
|
|
o_dprio_rden : out std_logic;
|
|
o_dprio_addr : out std_logic_vector(dprio_addr_width - 1 downto 0);
|
|
o_dprio_data : out std_logic_vector(dprio_data_width - 1 downto 0)
|
|
);
|
|
end alt_dfe;
|
|
|
|
architecture trans of alt_dfe is
|
|
type type_xhdl0 is array (((2 ** channel_address_width) - 1) downto 0) of std_logic_vector(12 downto 0);
|
|
type state_type is (ST_IDLE, ST_WRITE, ST_READ);
|
|
|
|
signal state : state_type := ST_IDLE;
|
|
signal state0q : state_type := ST_IDLE;
|
|
signal reg_read : std_logic;
|
|
signal reg_write : std_logic;
|
|
signal busy_counter : std_logic_vector(5 downto 0) := "000000";
|
|
|
|
signal reg_chaddress : std_logic_vector(channel_address_width - 1 downto 0) := to_stdlogicvector(0, channel_address_width);
|
|
signal reg_chaddress0q : std_logic_vector(channel_address_width - 1 downto 0) := to_stdlogicvector(0, channel_address_width);
|
|
signal reg_data : std_logic_vector(ireg_data_width - 1 downto 0) := to_stdlogicvector(0, ireg_data_width);
|
|
signal reg_data0q : std_logic_vector(ireg_data_width - 1 downto 0) := to_stdlogicvector(0, ireg_data_width);
|
|
signal reg_ctrlstatus : std_logic_vector(ireg_data_width - 1 downto 0) := to_stdlogicvector(0, ireg_data_width);
|
|
signal reg_ctrlstatus0q : std_logic_vector(ireg_data_width - 1 downto 0) := to_stdlogicvector(0, ireg_data_width);
|
|
signal reg_wdaddress : std_logic_vector(ireg_wdaddr_width - 1 downto 0) := to_stdlogicvector(0, ireg_wdaddr_width);
|
|
signal reg_wdaddress0q : std_logic_vector(ireg_wdaddr_width - 1 downto 0) := to_stdlogicvector(0, ireg_wdaddr_width);
|
|
|
|
signal dprio_reg : type_xhdl0;
|
|
signal dprio_reg0q : type_xhdl0;
|
|
|
|
signal invalid_channel_address : std_logic;
|
|
signal invalid_word_address : std_logic;
|
|
signal i : integer;
|
|
-- X-HDL generated signals
|
|
|
|
signal xhdl1 : std_logic;
|
|
signal xhdl2 : std_logic;
|
|
begin
|
|
|
|
o_dprio_wren <= '0';
|
|
o_dprio_rden <= '0';
|
|
o_dprio_addr <= (others => '0');
|
|
o_dprio_data <= (others => '0');
|
|
o_quad_address <= (others => '0');
|
|
o_reconfig_busy <= reg_ctrlstatus0q(15);
|
|
|
|
process (i_avmm_clk)
|
|
begin
|
|
if (i_avmm_clk'event and i_avmm_clk = '1') then
|
|
if ((not(i_resetn)) = '1') then
|
|
state0q <= ST_IDLE;
|
|
else
|
|
state0q <= state;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
process (i_avmm_clk)
|
|
begin
|
|
if (i_avmm_clk'event and i_avmm_clk = '1') then
|
|
if ((not(i_resetn)) = '1') then
|
|
busy_counter <= (others => '0');
|
|
elsif (((reg_ctrlstatus(0) = '1') and (reg_ctrlstatus0q(0) = '0')) and ((not(reg_ctrlstatus(1))) = '1')) then
|
|
busy_counter <= "111111";
|
|
elsif (((reg_ctrlstatus(0) = '1') and (reg_ctrlstatus0q(0) = '0')) and ((reg_ctrlstatus(1)) = '1')) then
|
|
busy_counter <= "011111";
|
|
elsif ((or_BR(busy_counter)) = '1') then
|
|
busy_counter <= busy_counter - "000001";
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
process (state0q, i_avmm_sread, i_avmm_swrite, reg_ctrlstatus0q)
|
|
begin
|
|
o_avmm_swaitrequest <= '0';
|
|
reg_write <= '0';
|
|
|
|
reg_read <= '0';
|
|
case state0q is
|
|
when ST_WRITE =>
|
|
o_avmm_swaitrequest <= '0';
|
|
state <= ST_IDLE;
|
|
when ST_READ =>
|
|
o_avmm_swaitrequest <= '0';
|
|
reg_read <= '1';
|
|
state <= ST_IDLE;
|
|
when others =>
|
|
if (i_avmm_sread = '1') then
|
|
o_avmm_swaitrequest <= '1';
|
|
reg_read <= '1';
|
|
state <= ST_READ;
|
|
elsif (i_avmm_swrite = '1') then
|
|
o_avmm_swaitrequest <= '1';
|
|
if ((reg_ctrlstatus0q(15)) = '1') then
|
|
reg_write <= '0';
|
|
else
|
|
reg_write <= '1';
|
|
end if;
|
|
state <= ST_WRITE;
|
|
else
|
|
o_avmm_swaitrequest <= '0';
|
|
state <= ST_IDLE;
|
|
end if;
|
|
end case;
|
|
end process;
|
|
|
|
|
|
process (i_avmm_clk)
|
|
begin
|
|
if (i_avmm_clk'event and i_avmm_clk = '1') then
|
|
if ((not(i_resetn)) = '1') then
|
|
reg_chaddress0q <= (others => '0');
|
|
reg_data0q <= (others => '0');
|
|
reg_ctrlstatus0q <= (others => '0');
|
|
reg_wdaddress0q <= (others => '0');
|
|
for i in 0 to ((2 ** channel_address_width)) - 1 loop
|
|
dprio_reg0q(i) <= (others => '0');
|
|
end loop;
|
|
else
|
|
reg_chaddress0q <= reg_chaddress;
|
|
reg_data0q <= reg_data;
|
|
reg_ctrlstatus0q <= reg_ctrlstatus;
|
|
reg_wdaddress0q <= reg_wdaddress;
|
|
for i in 0 to ((2 ** channel_address_width)) - 1 loop
|
|
dprio_reg0q(i) <= dprio_reg(i);
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process (reg_read, i_avmm_saddress, reg_ctrlstatus0q, reg_chaddress0q, reg_wdaddress0q, reg_data0q)
|
|
begin
|
|
if (reg_read = '1') then
|
|
if (i_avmm_saddress(15 downto 0) = "0000000000000000") then
|
|
o_avmm_sreaddata(ireg_data_width - 1 downto 0) <= reg_ctrlstatus0q;
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000001") then
|
|
o_avmm_sreaddata(channel_address_width - 1 downto 0) <= reg_chaddress0q;
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000010") then
|
|
o_avmm_sreaddata(ireg_wdaddr_width - 1 downto 0) <= reg_wdaddress0q;
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000011") then
|
|
o_avmm_sreaddata <= reg_data0q;
|
|
else
|
|
o_avmm_sreaddata <= (others => '0');
|
|
end if;
|
|
else
|
|
o_avmm_sreaddata <= (others => '0');
|
|
end if;
|
|
end process;
|
|
invalid_channel_address <= to_stdlogic((i_remap_address = "111111111111"));
|
|
invalid_word_address <= to_stdlogic((reg_wdaddress0q > "10"));
|
|
|
|
|
|
xhdl1 <= '0' when ((i_avmm_swritedata(14)) = '1') else
|
|
reg_ctrlstatus0q(14);
|
|
xhdl2 <= '0' when ((i_avmm_swritedata(13)) = '1') else
|
|
reg_ctrlstatus0q(13);
|
|
process (reg_chaddress0q, reg_data0q, reg_ctrlstatus0q, reg_wdaddress0q, i, dprio_reg, busy_counter, dprio_reg0q, reg_write, i_avmm_saddress, i_avmm_swritedata, invalid_channel_address, invalid_word_address)
|
|
begin
|
|
reg_chaddress <= reg_chaddress0q;
|
|
reg_data <= reg_data0q;
|
|
reg_ctrlstatus <= reg_ctrlstatus0q;
|
|
reg_wdaddress <= reg_wdaddress0q;
|
|
for i in 0 to ((2 ** channel_address_width)) - 1 loop
|
|
dprio_reg0q(i) <= dprio_reg(i);
|
|
end loop;
|
|
if (busy_counter = "000001") then
|
|
reg_ctrlstatus(15) <= '0';
|
|
reg_ctrlstatus(0) <= '0';
|
|
if ((reg_ctrlstatus0q(1)) = '1') then
|
|
if (reg_wdaddress0q = "00") then
|
|
reg_data(2 downto 0) <= dprio_reg0q(to_integer(reg_chaddress0q))(2 downto 0);
|
|
reg_data(15 downto 3) <= "0000000000000";
|
|
elsif (reg_wdaddress0q = "01") then
|
|
reg_data(3 downto 0) <= dprio_reg0q(to_integer(reg_chaddress0q))(6 downto 3);
|
|
reg_data(15 downto 4) <= "000000000000";
|
|
elsif (reg_wdaddress0q = "10") then
|
|
reg_data(5 downto 0) <= dprio_reg0q(to_integer(reg_chaddress0q))(12 downto 7);
|
|
reg_data(15 downto 6) <= "0000000000";
|
|
end if;
|
|
end if;
|
|
end if;
|
|
if (reg_write = '1') then
|
|
if (i_avmm_saddress(15 downto 0) = "0000000000000000") then
|
|
reg_ctrlstatus(1) <= i_avmm_swritedata(1);
|
|
if ((i_avmm_swritedata(0)) = '1') then
|
|
if ((invalid_channel_address = '1') or (invalid_word_address = '1')) then
|
|
reg_ctrlstatus(15) <= '0';
|
|
reg_ctrlstatus(14) <= invalid_word_address;
|
|
reg_ctrlstatus(13) <= invalid_channel_address;
|
|
else
|
|
if ((not(i_avmm_swritedata(1))) = '1') then
|
|
if (reg_wdaddress0q = "00") then
|
|
dprio_reg(to_integer(reg_chaddress0q))(2 downto 0) <= (reg_data0q(2 downto 0));
|
|
elsif (reg_wdaddress0q = "01") then
|
|
dprio_reg(to_integer(reg_chaddress0q))(6 downto 3) <= (reg_data0q(3 downto 0));
|
|
elsif (reg_wdaddress0q = "10") then
|
|
dprio_reg(to_integer(reg_chaddress0q))(12 downto 7) <= (reg_data0q(5 downto 0));
|
|
end if;
|
|
end if;
|
|
reg_ctrlstatus(0) <= '1';
|
|
reg_ctrlstatus(15) <= '1';
|
|
reg_ctrlstatus(14) <= '0';
|
|
reg_ctrlstatus(13) <= '0';
|
|
end if;
|
|
else
|
|
reg_ctrlstatus(15) <= '0';
|
|
reg_ctrlstatus(14) <= xhdl1;
|
|
reg_ctrlstatus(13) <= xhdl2;
|
|
end if;
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000001") then
|
|
if (channel_address_width < 2) then
|
|
reg_chaddress <= i_avmm_swritedata(0 downto 0);
|
|
else
|
|
reg_chaddress <= i_avmm_swritedata(channel_address_width - 1 downto 0);
|
|
end if;
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000010") then
|
|
reg_wdaddress <= i_avmm_swritedata(ireg_wdaddr_width - 1 downto 0);
|
|
elsif (i_avmm_saddress(15 downto 0) = "0000000000000011") then
|
|
reg_data <= i_avmm_swritedata(ireg_data_width - 1 downto 0);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
end trans;
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
|
|
package SLD_NODE is
|
|
|
|
constant CLK_PERIOD : time := 100 NS; -- the clock period of the system (10Mhz)
|
|
|
|
constant NUM_SELECTION_BITS : natural := 4;
|
|
-- the number of selection bits + 3 to be added to the IR register
|
|
-- in the dummy hub. 3 is the width of
|
|
-- hub instructions
|
|
constant PARAM_ERROR : string := "Invalid parameter specification : SLD_NODE_SIM_ACTION";
|
|
-- error message for invalid parameters
|
|
|
|
constant HEXCON_ERROR : string := "Invalid hexadecimal character : SLD_NODE_SIM_ACTION";
|
|
-- error message for invalid
|
|
-- hexadecimal parameters
|
|
|
|
constant TYPE_ERROR : string := "Invalid Scan type specified : SLD_NODE_SIM_ACTION";
|
|
-- error message for an invalid scan type
|
|
|
|
constant FIRST_TYPE_ERROR : string := "First scan should always be an IR scan. : SLD_NODE_SIM_ACTION";
|
|
-- error message for an invalid first scan type
|
|
|
|
constant LENGTH_ERROR : string := "IR length specified is less than SLD_NODE_IR_WIDTH : SLD_NODE_SIM_ACTION";
|
|
-- error message for an invalid ir length
|
|
|
|
constant ZERO_LENGTH_ERROR : string := "Zero is not a valid length parameter : SLD_NODE_SIM_ACTION";
|
|
-- error message when zero length is given
|
|
|
|
constant V_IR_SCAN_TYPE : std_logic_vector(3 downto 0) := "0001";
|
|
-- ir type signal
|
|
constant V_DR_SCAN_TYPE : std_logic_vector(3 downto 0) := "0010";
|
|
-- dr type signal
|
|
constant JTAG_USR1_INSTR : std_logic_vector(9 downto 0) := "0000001110";
|
|
-- the usr1 instruction for jtag controller
|
|
|
|
-- purpose: handles errors based on the severity level. Can stop simulation and will also display message
|
|
procedure message (
|
|
mess : string; -- string to be displayed
|
|
sev : severity_level); -- severity level of message
|
|
|
|
procedure hexmessage (
|
|
mess : string; -- string to be displayed
|
|
value : character; -- string to be displayed
|
|
sev : severity_level);
|
|
|
|
-- purpose: converts a character to a 4 bit value. All characters beyond F generate a warning and convert to
|
|
-- zero
|
|
function hexToBits (
|
|
constant hexValue : character) -- the charcater to be decoded
|
|
return unsigned;
|
|
|
|
-- purpose: converts a character to an exact number of bits value. All characters beyond 7 generate a warning and convert
|
|
-- to zero
|
|
function hexToExactBits (
|
|
constant hexValue : character; -- the character to be converted
|
|
constant num_bits : natural) -- the number of bits to return
|
|
return unsigned;
|
|
|
|
-- purpose: move JTAG tap into a dr shift state
|
|
procedure goto_dr_shift_state (
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic); -- tms signal
|
|
|
|
-- purpose: shifts usr0 into the jtag tap controller. Assumes tap is in update or rti state.
|
|
procedure jtag_ir_usr0 (
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic); -- tdi signal
|
|
|
|
-- purpose: shifts the usr1 instruction into the jtag tap controller. Works if jtag is in an update state or rti state
|
|
procedure jtag_ir_usr1 (
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic); -- tdi signal
|
|
|
|
|
|
-- purpose: sends a HUB_FORCE_IR_CAPTURE instruction to the hub
|
|
procedure send_force_ir_capture (
|
|
constant ir_width : in integer; -- ir_width - 4
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic); -- tdi signal
|
|
|
|
-- purpose: a dr scan with the passed in value. Assumes we are in udr/uir state
|
|
procedure dr_scan (
|
|
constant length : in natural; -- length of the value
|
|
constant idx_lsb : in natural; -- the index to start reading values from
|
|
constant idx_msb : in natural; -- the index to stop reading at
|
|
constant value : in std_logic_vector; -- the value to be shifted
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic); -- tdi signal
|
|
|
|
-- purpose: virtual dr scan
|
|
procedure v_dr_scan (
|
|
constant length : in natural; -- length of the value
|
|
constant idx_lsb : in natural; -- the index to start reading values from
|
|
constant idx_msb : in natural; -- the index to stop reading at
|
|
constant value : in std_logic_vector; -- the value to be shifted
|
|
signal jtag_usr1 : in std_logic; -- high if jtag is in usr1 state
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic); -- tdi signal
|
|
|
|
-- purpose: virtual ir scan
|
|
procedure v_ir_scan (
|
|
constant length : in natural; -- length of bit stream
|
|
constant idx_lsb : in natural; -- the index to start reading values from
|
|
constant idx_msb : in natural; -- the index to stop reading at
|
|
constant value : in std_logic_vector; -- the value to be shifted out
|
|
constant ir_width : in integer; -- sld_node_ir_width - 4
|
|
signal jtag_usr1 : in std_logic; -- high if jtag is in usr1 state
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic); -- tdi signal
|
|
|
|
|
|
end SLD_NODE;
|
|
|
|
package body SLD_NODE is
|
|
|
|
-- purpose: handles errors based on the severity level. Can stop simulation and will also display message
|
|
procedure message (
|
|
mess : string; -- string to be displayed
|
|
sev : severity_level) is -- severity level of message
|
|
begin -- message
|
|
assert (FALSE) report mess severity sev;
|
|
end message;
|
|
|
|
-- purpose: handles errors based on the severity level. Can stop simulation and will also display message
|
|
procedure hexmessage (
|
|
mess : string; -- string to be displayed
|
|
value : character; -- string to be displayed
|
|
sev : severity_level) is -- severity level of message
|
|
begin -- message
|
|
assert (FALSE) report mess & " Character is : " & value severity sev;
|
|
end hexmessage;
|
|
|
|
|
|
-- purpose: converts a character to a 4 bit value. All characters beyond F generate a warning and convert to
|
|
-- zero
|
|
function hexToBits (
|
|
constant hexValue : character) -- the character to be converted
|
|
return unsigned is
|
|
variable result : unsigned(3 downto 0) := (others => '0');
|
|
-- variable to hold decoded bits
|
|
begin -- hexToBits
|
|
case hexValue is
|
|
when '0' => result := "0000";
|
|
when '1' => result := "0001";
|
|
when '2' => result := "0010";
|
|
when '3' => result := "0011";
|
|
when '4' => result := "0100";
|
|
when '5' => result := "0101";
|
|
when '6' => result := "0110";
|
|
when '7' => result := "0111";
|
|
when '8' => result := "1000";
|
|
when '9' => result := "1001";
|
|
when 'A' => result := "1010";
|
|
when 'a' => result := "1010";
|
|
when 'B' => result := "1011";
|
|
when 'b' => result := "1011";
|
|
when 'C' => result := "1100";
|
|
when 'c' => result := "1100";
|
|
when 'D' => result := "1101";
|
|
when 'd' => result := "1101";
|
|
when 'E' => result := "1110";
|
|
when 'e' => result := "1110";
|
|
when 'F' => result := "1111";
|
|
when 'f' => result := "1111";
|
|
when others =>
|
|
hexmessage(hexcon_error, hexValue, WARNING);
|
|
result := "0000";
|
|
end case;
|
|
return result;
|
|
end hexToBits;
|
|
|
|
-- purpose: converts a character to an exact number of bits value. All characters beyond 7 generate a warning and convert
|
|
-- to zero
|
|
function hexToExactBits (
|
|
constant hexValue : character; -- the character to be converted
|
|
constant num_bits : natural) -- the number of bits to return
|
|
return unsigned is
|
|
variable result : unsigned(3 downto 0) := (others => '0');
|
|
-- variable to hold bits
|
|
begin -- hexToExactBits
|
|
result := hexToBits(hexValue);
|
|
return result(num_bits - 1 downto 0);
|
|
end hexToExactBits;
|
|
|
|
-- purpose: move JTAG tap into a dr shift state
|
|
procedure goto_dr_shift_state (
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic) is -- tms signal
|
|
begin -- goto_dr_shift_state
|
|
-- get into drs state
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- get into cdr state
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- get into sdr state
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end goto_dr_shift_state;
|
|
|
|
-- purpose: move jtag from dr/ir shift state to ir/dr update state
|
|
procedure goto_update_state (
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic) is -- tms signal
|
|
begin -- goto_update_state
|
|
-- get into e1(i/d)r state
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- get into u(i/d)r state
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end goto_update_state;
|
|
|
|
-- purpose: shifts the usr1 instruction into the jtag tap controller. Works if jtag is in an update state or rti state
|
|
procedure jtag_ir_usr1 (
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic) is -- tdi signal
|
|
begin -- jtag_to_usr1
|
|
-- get into drs state
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- get into irs state
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- get into cir state
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- get into sir state
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- shift in data i.e usr1 instruction
|
|
-- usr1 = 0x0E = 0b00 0000 1110
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '1';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '1';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '1';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- done with 1110
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- done with 0000
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '0';
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- done with 00
|
|
-- now in e1ir state
|
|
-- get into uir state
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end jtag_ir_usr1;
|
|
|
|
-- purpose: shifts usr0 into the jtag tap controller. Assumes tap is in update or rti state.
|
|
procedure jtag_ir_usr0 (
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic) is -- tdi signal
|
|
begin -- jtag_ir_usr0
|
|
-- get into drs state
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- get into irs state
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- get into cir state
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- get into sir state
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- shift in data i.e usr0 instruction
|
|
-- usr1 = 0x0E = 0b00 0000 1100
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '1';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '1';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- done with 1100
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- done with 0000
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- done with 00
|
|
-- get into e1ir state
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- get into uir state
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end jtag_ir_usr0;
|
|
|
|
-- purpose: sends a HUB_FORCE_IR_CAPTURE instruction to the hub
|
|
procedure send_force_ir_capture (
|
|
constant ir_width : in integer; -- ir_width - 4
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic) is -- tdi signal
|
|
begin -- send_force_ir_capture
|
|
goto_dr_shift_state(tck, tms);
|
|
-- shift in the instruction
|
|
tdi <= '1';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '1';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- done with 011
|
|
-- fill up for ir width
|
|
for j in 0 to ir_width - 1 loop
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end loop; -- j
|
|
-- one select bit
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
goto_update_state(tck, tms);
|
|
end send_force_ir_capture;
|
|
|
|
-- purpose: a dr scan with the passed in value. Assumes we are in udr/uir state
|
|
procedure dr_scan (
|
|
constant length : in natural; -- length of the value
|
|
constant idx_lsb : in natural; -- the index to start reading values from
|
|
constant idx_msb : in natural; -- the index to stop reading at
|
|
constant value : in std_logic_vector; -- the value to be shifted
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic) is -- tdi signal
|
|
begin -- dr_scan
|
|
goto_dr_shift_state(tck, tms);
|
|
for i in idx_lsb to idx_msb - 1 loop
|
|
tms <= '0';
|
|
tdi <= value(i);
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end loop; -- i
|
|
-- check if we need to pad with zeros
|
|
if ((idx_msb - idx_lsb + 1) < length ) then
|
|
-- clock last value bit
|
|
tdi <= value(idx_msb);
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
-- pad with zeros
|
|
for j in idx_msb - idx_lsb + 1 to length - 2 loop
|
|
tms <= '0';
|
|
tdi <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end loop; -- j
|
|
tdi <= '0';
|
|
else
|
|
tdi <= value(idx_msb);
|
|
end if;
|
|
-- last bit is clocked together with state transition
|
|
goto_update_state(tck, tms);
|
|
end dr_scan;
|
|
|
|
-- purpose: virtual dr scan
|
|
procedure v_dr_scan (
|
|
constant length : in natural; -- length of the value
|
|
constant idx_lsb : in natural; -- the index to start reading values from
|
|
constant idx_msb : in natural; -- the index to stop reading at
|
|
constant value : in std_logic_vector; -- the value to be shifted
|
|
signal jtag_usr1 : in std_logic; -- high if jtag is in usr1 state
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic) is -- tdi signal
|
|
begin -- v_dr_scan
|
|
if (jtag_usr1 = '1') then
|
|
-- shift in usr0 instruction
|
|
jtag_ir_usr0(tck, tms, tdi);
|
|
end if;
|
|
-- shift in the dr value
|
|
dr_scan(length, idx_lsb, idx_msb, value, tck, tms, tdi);
|
|
end v_dr_scan;
|
|
|
|
-- purpose: virtual ir scan
|
|
procedure v_ir_scan (
|
|
constant length : in natural; -- length of bit stream this is ignored
|
|
constant idx_lsb : in natural; -- the index to start reading values from
|
|
constant idx_msb : in natural; -- the index to stop reading at
|
|
constant value : in std_logic_vector; -- the value to be shifted out
|
|
constant ir_width : in integer; -- sld_node_ir_width - 4
|
|
signal jtag_usr1 : in std_logic; -- high if jtag is in usr1 state
|
|
signal tck : out std_logic; -- tck signal
|
|
signal tms : out std_logic; -- tms signal
|
|
signal tdi : out std_logic) is -- tdi signal
|
|
begin -- v_ir_scan
|
|
if (jtag_usr1 = '0' ) then
|
|
-- shift in usr1 instruction
|
|
jtag_ir_usr1(tck, tms, tdi);
|
|
end if;
|
|
-- send capture_ir instructions
|
|
send_force_ir_capture(ir_width, tck, tms, tdi);
|
|
-- shift in the ir value
|
|
goto_dr_shift_state(tck, tms);
|
|
for i in idx_lsb to idx_msb loop
|
|
tms <= '0';
|
|
tdi <= value(i);
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end loop; -- i
|
|
-- pad with zeros if necessary
|
|
for j in idx_msb - idx_lsb + 1 to ir_width + 3 loop
|
|
tms <= '0';
|
|
tdi <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end loop; -- j
|
|
-- last bit is clocked together with state transition
|
|
-- last bit is selection bit. For IR scans this is always 1 implying
|
|
-- node as opposed to hub
|
|
tdi <= '1';
|
|
goto_update_state(tck, tms);
|
|
end v_ir_scan;
|
|
|
|
end SLD_NODE;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-------------------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
use ieee.std_logic_arith.all;
|
|
|
|
use work.sld_node.all;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Entity Name : signal_gen
|
|
--
|
|
-- Description : Simulates customizable actions on a JTAG input
|
|
--
|
|
-- Limitation : See file limitations above
|
|
--
|
|
-- Results Expected :
|
|
--
|
|
--
|
|
-------------------------------------------------------------------------------
|
|
|
|
entity signal_gen is
|
|
|
|
generic (
|
|
sld_node_ir_width : integer; -- ir width for this instance
|
|
sld_node_n_scan : natural; -- the number of scans to be executed
|
|
sld_node_total_length : natural; -- the total length of all scan values
|
|
sld_node_sim_action : string); -- the actions to be simulated.
|
|
port (
|
|
tck : out std_logic; -- jtag clock
|
|
tms : out std_logic; -- tms signal for jtag
|
|
tdi : out std_logic; -- tdi signal to the jtag
|
|
jtag_usr1 : in std_logic; -- high when jtag is in usr1 state
|
|
tdo : in std_logic); -- tdo signal from jtag
|
|
end signal_gen;
|
|
|
|
architecture simModel of signal_gen is
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
type instr is record -- represents a single instruction
|
|
scan_time : time;
|
|
-- the time to wait before executing this instruction
|
|
scan_type : std_logic_vector(3 downto 0);
|
|
-- the type of scan this is
|
|
length : unsigned(31 downto 0);
|
|
-- the bit length of the value to be shifted
|
|
idx_lsb : natural; -- the starting index of value
|
|
idx_msb : natural; -- the starting index of value
|
|
end record;
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- array for instructions
|
|
type scansArray is array (sld_node_n_scan - 1 downto 0) of instr;
|
|
-- the scansArray
|
|
-------------------------------------------------------------------------------
|
|
-------------------------------------------------------------------------------
|
|
-- Parsed string data structure
|
|
type decodedScans is record
|
|
-- decodedScans for this instance of the model
|
|
scans : scansArray; -- the array of instructions
|
|
values : std_logic_vector(sld_node_total_length - 1 downto 0);
|
|
-- the values for all scans
|
|
end record;
|
|
-------------------------------------------------------------------------------
|
|
-- purpose: takes in a string and returns the decoded scans for use by the model
|
|
function decode (
|
|
constant actions : string) -- the string to be decoded
|
|
return decodedScans is
|
|
|
|
type mStates is (STARTSTATE, TIMESTATE, TYPESTATE, LENGTHSTATE, VALUESTATE);
|
|
-- the states of the parsing machine
|
|
|
|
variable decScans : decodedScans;
|
|
-- the variable to store the decoded scans
|
|
variable decValues : std_logic_vector(sld_node_total_length - 1 downto 0);
|
|
-- variable to store decoded values
|
|
variable decScanArray : scansArray; -- variable to store decoded scans
|
|
|
|
variable cState : mStates := STARTSTATE; -- the current state variable
|
|
|
|
variable cTime : unsigned(31 downto 0) := (others => '0');
|
|
-- the current Time being decoded
|
|
|
|
variable cIdx_lsb : natural := 0; -- the current lsb idx for the value array
|
|
variable cIdx_msb : natural := 0; -- the current msb idx for the value array
|
|
|
|
variable cType : std_logic_vector(3 downto 0) := (others => '0');
|
|
-- the current type
|
|
variable scanArrIdx : natural range 0 to sld_node_n_scan := 0; -- the index to the scan array
|
|
-- scanArrIdx is one more than needed to allow for the loop not to crash, since we
|
|
-- increment index at the end of the loop
|
|
variable cLength : unsigned(31 downto 0) := (others => '0');
|
|
-- the current length value
|
|
begin -- decode
|
|
decValues := (others =>'0'); -- initialize all bits to zero
|
|
for i in 2 to actions'length - 1 loop
|
|
case cState is
|
|
when STARTSTATE =>
|
|
if (actions(i) = '(') then
|
|
cState := TIMESTATE;
|
|
end if;
|
|
when TIMESTATE =>
|
|
if (actions(i) = ',') then
|
|
cState := TYPESTATE;
|
|
else
|
|
cTime(31 downto 4) := cTime(27 downto 0);
|
|
cTime(3 downto 0) := hexToBits(actions(i));
|
|
end if;
|
|
when TYPESTATE =>
|
|
if (actions(i) = ',') then
|
|
cState := VALUESTATE;
|
|
else
|
|
cType := std_logic_vector(hexToBits(actions(i)));
|
|
end if;
|
|
when VALUESTATE =>
|
|
if (actions(i) = ',') then
|
|
cState := LENGTHSTATE;
|
|
elsif ((sld_node_total_length - cIdx_lsb) < 4) then
|
|
decValues(sld_node_total_length - 1 downto cIdx_lsb) := std_logic_vector(hexToExactBits(actions(i),sld_node_total_length - cIdx_lsb));
|
|
cIdx_msb := cIdx_msb + sld_node_total_length - cIdx_lsb;
|
|
else
|
|
-- the line below shifts the previous character
|
|
decValues(sld_node_total_length - 1 downto cIdx_lsb + 4) := decValues(sld_node_total_length - 5 downto cIdx_lsb);
|
|
decValues(cIdx_lsb + 3 downto cIdx_lsb) := std_logic_vector(hexToBits(actions(i)));
|
|
cIdx_msb := cIdx_msb + 4;
|
|
end if;
|
|
when LENGTHSTATE =>
|
|
if (actions(i) = ')') then
|
|
-- zero is not a valid length
|
|
if (conv_integer(cLength) = 0) then
|
|
message(ZERO_LENGTH_ERROR,FAILURE);
|
|
end if;
|
|
decScanArray(scanArrIdx).scan_time := CLK_PERIOD * 10000 * conv_integer(cTime);
|
|
decScanArray(scanArrIdx).scan_type := cType;
|
|
decScanArray(scanArrIdx).length := cLength;
|
|
decScanArray(scanArrIdx).idx_lsb := cIdx_lsb;
|
|
-- error checking for cases when actual bit length >
|
|
-- specified length i.e need for truncation
|
|
if (cIdx_lsb + conv_integer(cLength) < cIdx_msb) then
|
|
cIdx_msb := cIdx_lsb + conv_integer(cLength);
|
|
end if;
|
|
decScanArray(scanArrIdx).idx_msb := cIdx_msb - 1;
|
|
cTime := (others => '0');
|
|
cType := (others => '0');
|
|
cLength := (others => '0');
|
|
cIdx_lsb := cIdx_msb;
|
|
scanArrIdx := scanArrIdx + 1 ;
|
|
cState := STARTSTATE;
|
|
else
|
|
cLength(31 downto 4) := cLength(27 downto 0);
|
|
cLength(3 downto 0) := hexToBits(actions(i));
|
|
end if;
|
|
when others => null;
|
|
end case;
|
|
end loop; -- i
|
|
decScans.scans := decScanArray;
|
|
decScans.values := decValues;
|
|
return decScans;
|
|
end decode;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-------------------------------------------------------------------------------
|
|
-- Resets the JTAP controller.
|
|
procedure reset_jtag (
|
|
constant length : in unsigned(31 downto 0); -- the ir-calue to be shifted
|
|
constant idx : in natural;
|
|
-- the index to start reading value from
|
|
constant values : in std_logic_vector(sld_node_total_length - 1 downto 0);
|
|
-- the values to be shifted out
|
|
signal tck : out std_logic; -- the tck signal
|
|
signal tms : out std_logic; -- the tms signal
|
|
signal tdi : out std_logic) is -- the tdi signal
|
|
begin -- ir_scan
|
|
-- get into tlr state
|
|
for i in 0 to 5 loop
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end loop; -- i
|
|
-- get into rti state
|
|
tms <= '0';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
jtag_ir_usr1(tck,tms,tdi);
|
|
end reset_jtag;
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
signal myScans : decodedScans; -- the decoded scan
|
|
|
|
|
|
begin -- simModel
|
|
-- purpose: Resets jtag and then iterates through instructions and performs
|
|
-- actions.
|
|
-- type : combinational
|
|
-- inputs :
|
|
-- outputs: tck,tdi,tms
|
|
simulate : process
|
|
begin -- process simulate
|
|
tck <= '1';
|
|
tdi <= '0';
|
|
tms <= '0';
|
|
myScans <= decode(sld_node_sim_action);
|
|
wait for CLK_PERIOD;
|
|
reset_jtag(myScans.scans(0).length, myScans.scans(0).idx_lsb,myScans.values,tck,tms,tdi);
|
|
-- first instruction needs to be an IR intsruction.
|
|
if (myScans.scans(0).scan_type /= V_IR_SCAN_TYPE) then
|
|
message(FIRST_TYPE_ERROR,FAILURE);
|
|
end if;
|
|
for l in 0 to sld_node_n_scan - 1 loop
|
|
wait for myScans.scans(l).scan_time;
|
|
if (myScans.scans(l).scan_type = V_IR_SCAN_TYPE) then
|
|
v_ir_scan(conv_integer(myScans.scans(l).length),
|
|
myScans.scans(l).idx_lsb, myScans.scans(l).idx_msb, myScans.values,
|
|
sld_node_ir_width - 4,
|
|
jtag_usr1, tck, tms, tdi);
|
|
-- do error checking for when length is not equal to SLD_NODE_IR_WIDTH
|
|
if (conv_integer(myScans.scans(l).length) /= sld_node_ir_width) then
|
|
message(LENGTH_ERROR,WARNING);
|
|
end if;
|
|
elsif (myScans.scans(l).scan_type = V_DR_SCAN_TYPE) then
|
|
v_dr_scan(conv_integer(myScans.scans(l).length),
|
|
myScans.scans(l).idx_lsb, myScans.scans(l).idx_msb, myScans.values,
|
|
jtag_usr1, tck, tms, tdi);
|
|
else
|
|
message(TYPE_ERROR,ERROR);
|
|
end if;
|
|
end loop; -- l
|
|
-- get into tlr state
|
|
for i in 0 to 5 loop
|
|
tms <= '1';
|
|
tck <= '0', '1' after clk_period/2;
|
|
wait for clk_period;
|
|
end loop; -- i
|
|
wait;
|
|
end process simulate;
|
|
|
|
|
|
end simModel;
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
use work.sld_node.all;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Entity Name : jtag_tap_controller
|
|
--
|
|
-- Description : Behavioral model of JTAg tap controller with state signals
|
|
--
|
|
-- Limitation : Can only decode USER1 and USER0 instructions
|
|
--
|
|
-- Results Expected :
|
|
--
|
|
--
|
|
-------------------------------------------------------------------------------
|
|
|
|
entity jtag_tap_controller is
|
|
generic (
|
|
ir_register_width : integer); -- the width of the shift register
|
|
|
|
port (
|
|
tck : in std_logic; -- tck signal from signal_gen
|
|
tms : in std_logic; -- tms signal from signal_gen
|
|
tdi : in std_logic; -- tdi signal from signal_gen
|
|
jtag_tdo : in std_logic; -- tdo signal from hub
|
|
tdo : out std_logic; -- tdo signal to signal_gen
|
|
jtag_tck : out std_logic; -- tck signal from jtag
|
|
jtag_tms : out std_logic; -- tms signal from jtag
|
|
jtag_tdi : out std_logic; -- tdi signal from jtag
|
|
jtag_state_tlr : out std_logic; -- tlr state
|
|
jtag_state_rti : out std_logic; -- rti state
|
|
jtag_state_drs : out std_logic; -- select dr scan state
|
|
jtag_state_cdr : out std_logic; -- capture dr state
|
|
jtag_state_sdr : out std_logic; -- shift dr state
|
|
jtag_state_e1dr : out std_logic; -- exit1 dr state
|
|
jtag_state_pdr : out std_logic; -- pause dr sart
|
|
jtag_state_e2dr : out std_logic; -- exit2 dr state
|
|
jtag_state_udr : out std_logic; -- update dr state
|
|
jtag_state_irs : out std_logic; -- select ir scan state
|
|
jtag_state_cir : out std_logic; -- capture ir state
|
|
jtag_state_sir : out std_logic; -- shift ir state
|
|
jtag_state_e1ir : out std_logic; -- exit1 ir state
|
|
jtag_state_pir : out std_logic; -- pause ir state
|
|
jtag_state_e2ir : out std_logic; -- exit2 ir state
|
|
jtag_state_uir : out std_logic; -- update ir state
|
|
jtag_usr1 : out std_logic); -- jtag has usr1 instruction
|
|
|
|
end jtag_tap_controller;
|
|
|
|
|
|
architecture FSM of jtag_tap_controller is
|
|
|
|
type tap_states is (TLR_ST, RTI_ST, DRS_ST, CDR_ST, SDR_ST, E1DR_ST,
|
|
PDR_ST, E2DR_ST, UDR_ST, IRS_ST, CIR_ST, SIR_ST,
|
|
E1IR_ST, PIR_ST, E2IR_ST, UIR_ST);
|
|
-- the tap states
|
|
|
|
signal nState : tap_states; -- the next state signal
|
|
signal cState : tap_states; -- the current state signal
|
|
signal ir_srl : std_logic_vector(ir_register_width -1 downto 0);
|
|
-- the shift register for the controller
|
|
signal ir_srl_hold : std_logic_vector(ir_register_width -1 downto 0);
|
|
-- the hold register for the controller
|
|
signal jtag_usr1_c : std_logic; -- combinational usr1 signal
|
|
signal jtag_usr1_r : std_logic; -- registered usr1 signal
|
|
signal jtag_e1ir_i : std_logic;
|
|
-- internal signal to tell enable hold part of ir shift register
|
|
signal tdo_i : std_logic; -- internal signal for tdo
|
|
signal tdo_i_c : std_logic;
|
|
-- internal combinational signal for tdo
|
|
signal jtag_reset_i : std_logic;
|
|
-- internal reset signal that goes high when in TLR state
|
|
begin -- FSM
|
|
|
|
-- purpose: state transitions for the FSM
|
|
-- type : combinational
|
|
-- inputs : cState, tms
|
|
-- outputs: nState
|
|
stateTrans: process (cState, tms, jtag_usr1_r, ir_srl_hold)
|
|
begin -- process stateTrans
|
|
nState <= cState;
|
|
jtag_e1ir_i <= '0';
|
|
jtag_state_tlr <= '0';
|
|
jtag_state_rti <= '0';
|
|
jtag_state_drs <= '0';
|
|
jtag_state_cdr <= '0';
|
|
jtag_state_sdr <= '0';
|
|
jtag_state_e1dr <= '0';
|
|
jtag_state_pdr <= '0';
|
|
jtag_state_e2dr <= '0';
|
|
jtag_state_udr <= '0';
|
|
jtag_state_irs <= '0';
|
|
jtag_state_cir <= '0';
|
|
jtag_state_sir <= '0';
|
|
jtag_state_e1ir <= '0';
|
|
jtag_state_pir <= '0';
|
|
jtag_state_e2ir <= '0';
|
|
jtag_state_uir <= '0';
|
|
jtag_reset_i <= '0';
|
|
jtag_usr1_c <= jtag_usr1_r;
|
|
case cState is
|
|
when TLR_ST =>
|
|
if (tms = '0') then
|
|
nState <= RTI_ST;
|
|
jtag_reset_i <= '0';
|
|
else
|
|
jtag_reset_i <= '1';
|
|
end if;
|
|
jtag_state_tlr <= '1';
|
|
jtag_usr1_c <= '0';
|
|
when RTI_ST =>
|
|
if (tms = '1') then
|
|
nState <= DRS_ST;
|
|
end if;
|
|
jtag_state_rti <= '1';
|
|
when DRS_ST =>
|
|
if (tms = '1') then
|
|
nState <= IRS_ST;
|
|
else
|
|
nState <= CDR_ST;
|
|
end if;
|
|
jtag_state_drs <= '1';
|
|
when CDR_ST =>
|
|
if (tms = '1') then
|
|
nState <= E1DR_ST;
|
|
else
|
|
nState <= SDR_ST;
|
|
end if;
|
|
jtag_state_cdr <= '1';
|
|
when SDR_ST =>
|
|
if (tms = '1') then
|
|
nState <= E1DR_ST;
|
|
end if;
|
|
jtag_state_sdr <= '1';
|
|
when E1DR_ST =>
|
|
if (tms = '1') then
|
|
nState <= UDR_ST;
|
|
else
|
|
nState <= PDR_ST;
|
|
end if;
|
|
jtag_state_e1dr <= '1';
|
|
when PDR_ST =>
|
|
if (tms = '1') then
|
|
nState <= E2DR_ST;
|
|
end if;
|
|
jtag_state_pdr <= '1';
|
|
when E2DR_ST =>
|
|
if (tms = '1') then
|
|
nState <= UDR_ST;
|
|
else
|
|
nState <= SDR_ST;
|
|
end if;
|
|
jtag_state_e2dr <= '1';
|
|
when UDR_ST =>
|
|
if (tms = '1') then
|
|
nState <= DRS_ST;
|
|
else
|
|
nState <= RTI_ST;
|
|
end if;
|
|
jtag_state_udr <= '1';
|
|
when IRS_ST =>
|
|
if (tms = '1') then
|
|
nState <= TLR_ST;
|
|
else
|
|
nState <= CIR_ST;
|
|
end if;
|
|
jtag_state_irs <= '1';
|
|
when CIR_ST =>
|
|
if (tms = '1') then
|
|
nState <= E1IR_ST;
|
|
else
|
|
nState <= SIR_ST;
|
|
end if;
|
|
jtag_state_cir <= '1';
|
|
when SIR_ST =>
|
|
if (tms = '1') then
|
|
nState <= E1IR_ST;
|
|
end if;
|
|
jtag_state_sir <= '1';
|
|
when E1IR_ST =>
|
|
if (tms = '1') then
|
|
nState <= UIR_ST;
|
|
else
|
|
nState <= PIR_ST;
|
|
end if;
|
|
jtag_state_e1ir <= '1';
|
|
jtag_e1ir_i <= '1';
|
|
when PIR_ST =>
|
|
if (tms = '1') then
|
|
nState <= E2IR_ST;
|
|
end if;
|
|
jtag_state_pir <= '1';
|
|
when E2IR_ST =>
|
|
if (tms = '1') then
|
|
nState <= UIR_ST;
|
|
else
|
|
nState <= SIR_ST;
|
|
end if;
|
|
jtag_state_e2ir <= '1';
|
|
when UIR_ST =>
|
|
if (tms = '1') then
|
|
nState <= DRS_ST;
|
|
else
|
|
nState <= RTI_ST;
|
|
end if;
|
|
if (ir_srl_hold = JTAG_USR1_INSTR) then
|
|
jtag_usr1_c <= '1';
|
|
else
|
|
jtag_usr1_c <= '0';
|
|
end if;
|
|
jtag_state_uir <= '1';
|
|
when others => null;
|
|
end case;
|
|
end process stateTrans;
|
|
|
|
-- purpose: Regsiter for state machine and shift register
|
|
-- type : sequential
|
|
-- inputs : tck, jtag_reset_i
|
|
-- outputs: cState, sr
|
|
stateReg: process (tck, jtag_reset_i)
|
|
begin -- process stateReg
|
|
if jtag_reset_i = '1' then -- asynchronous reset (active high)
|
|
cState <= TLR_ST;
|
|
ir_srl <= (others =>'0');
|
|
jtag_usr1_r <= '0';
|
|
tdo_i <= '0';
|
|
tdo_i_c <= '0';
|
|
elsif tck'event and tck = '1' then -- rising clock edge
|
|
cState <= nState;
|
|
jtag_usr1_r <= jtag_usr1_c;
|
|
if (cState = CIR_ST) then
|
|
tdo_i_c <= '0'; -- so that we can generate 010101...
|
|
-- during SIR
|
|
elsif (cState = SIR_ST) then
|
|
ir_srl(ir_register_width - 2 downto 0) <= ir_srl(ir_register_width - 1 downto 1);
|
|
ir_srl(ir_register_width - 1) <= tdi;
|
|
tdo_i_c <= not(tdo_i_c);
|
|
tdo_i <= tdo_i_c;
|
|
else
|
|
tdo_i <= jtag_tdo;
|
|
end if;
|
|
end if;
|
|
end process stateReg;
|
|
jtag_usr1 <= jtag_usr1_r;
|
|
tdo <= tdo_i;
|
|
|
|
-- pipe through signals
|
|
jtag_tck <= tck;
|
|
jtag_tdi <= tdi;
|
|
jtag_tms <= tms;
|
|
|
|
-- purpose: hold register of shift register
|
|
-- type : sequential
|
|
-- inputs : tck, jtag_reset_i
|
|
-- outputs: ir_srl_hold
|
|
holdReg: process (tck, jtag_reset_i)
|
|
begin -- process holdReg
|
|
if jtag_reset_i = '1' then -- asynchronous reset (active high)
|
|
ir_srl_hold <= (others => '0');
|
|
elsif tck'event and tck = '0' then -- falling clock edge
|
|
if (jtag_e1ir_i = '1') then
|
|
ir_srl_hold <= ir_srl;
|
|
end if;
|
|
end if;
|
|
end process holdReg;
|
|
end FSM;
|
|
-------------------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.sld_node.all;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Entity Name : dummy_hub
|
|
--
|
|
-- Description : Acts as node and mux between the tap controller and
|
|
-- user design. Generates hub signals
|
|
--
|
|
-- Limitation : Assumes only one node. Ignores user input on tdo and ir_out.
|
|
--
|
|
-- Results Expected :
|
|
--
|
|
--
|
|
------------------------------------------------------------------------------
|
|
|
|
entity dummy_hub is
|
|
|
|
generic (
|
|
sld_node_ir_width : integer); -- the width of the ir registers
|
|
|
|
port (
|
|
jtag_tck : in std_logic; -- tck signal from tap controller
|
|
jtag_tdi : in std_logic; -- tdi signal from tap controller
|
|
jtag_tms : in std_logic; -- tms signal from tap controller
|
|
jtag_usr1 : in std_logic; -- usr1 signal from tap controller
|
|
jtag_state_tlr : in std_logic; -- tlr state signal from tap controller
|
|
jtag_state_rti : in std_logic; -- rti state signal from tap controller
|
|
jtag_state_drs : in std_logic; -- drs state signal from tap controller
|
|
jtag_state_cdr : in std_logic; -- cdr state signal from tap controller
|
|
jtag_state_sdr : in std_logic; -- sdr state signal from tap controller
|
|
jtag_state_e1dr : in std_logic; -- e1dr state signal from tap controller
|
|
jtag_state_pdr : in std_logic; -- pdr state signal from tap controller
|
|
jtag_state_e2dr : in std_logic; -- esdr state signal from tap controller
|
|
jtag_state_udr : in std_logic; -- udr state signal from tap controller
|
|
jtag_state_irs : in std_logic; -- irs state signal from tap controller
|
|
jtag_state_cir : in std_logic; -- cir state signals from tap controller
|
|
jtag_state_sir : in std_logic; -- sir state signal from tap controller
|
|
jtag_state_e1ir : in std_logic; -- e1ir state signal from tap controller
|
|
jtag_state_pir : in std_logic; -- pir state signals from tap controller
|
|
jtag_state_e2ir : in std_logic; -- e2ir state signal from tap controller
|
|
jtag_state_uir : in std_logic; -- uir state signal from tap controller
|
|
dummy_tdo : in std_logic; -- tdo signal from world
|
|
virtual_ir_out : in std_logic_vector(sld_node_ir_width - 1 downto 0);
|
|
-- captures parallel input from
|
|
-- user design
|
|
jtag_tdo : out std_logic; -- tdo signal to tap controller
|
|
dummy_tck : out std_logic; -- tck signal to world
|
|
dummy_tdi : out std_logic; -- tdi signal to world
|
|
dummy_tms : out std_logic; -- tms signal to world
|
|
dummy_state_tlr : out std_logic; -- tlr state signal to world
|
|
dummy_state_rti : out std_logic; -- rti state signal to world
|
|
dummy_state_drs : out std_logic; -- drs state signal to world
|
|
dummy_state_cdr : out std_logic; -- cdr state signal to world
|
|
dummy_state_sdr : out std_logic; -- sdr state signal to world
|
|
dummy_state_e1dr : out std_logic; -- e1dr state signal to the world
|
|
dummy_state_pdr : out std_logic; -- pdr state signal to world
|
|
dummy_state_e2dr : out std_logic; -- e2dr state signal to world
|
|
dummy_state_udr : out std_logic; -- udr state signal to world
|
|
dummy_state_irs : out std_logic; -- irs state signal to world
|
|
dummy_state_cir : out std_logic; -- cir state signal to world
|
|
dummy_state_sir : out std_logic; -- sir state signal to world
|
|
dummy_state_e1ir : out std_logic; -- e1ir state signal to world
|
|
dummy_state_pir : out std_logic; -- pir state signal to world
|
|
dummy_state_e2ir : out std_logic; -- e2ir state signal to world
|
|
dummy_state_uir : out std_logic; -- uir state signal to world
|
|
virtual_state_cdr : out std_logic; -- virtual cdr state signal
|
|
virtual_state_sdr : out std_logic; -- virtual sdr state signal
|
|
virtual_state_e1dr : out std_logic; -- virtual e1dr state signal
|
|
virtual_state_pdr : out std_logic; -- virtula pdr state signal
|
|
virtual_state_e2dr : out std_logic; -- virtual e2dr state signal
|
|
virtual_state_udr : out std_logic; -- virtual udr state signal
|
|
virtual_state_cir : out std_logic; -- virtual cir state signal
|
|
virtual_state_uir : out std_logic; -- virtual uir state signal
|
|
virtual_ir_in : out std_logic_vector(sld_node_ir_width - 1 downto 0));
|
|
-- parallel output to user design
|
|
end dummy_hub;
|
|
|
|
architecture behavior of dummy_hub is
|
|
|
|
constant SLD_NODE_IR_WIDTH_i : integer := sld_node_ir_width + NUM_SELECTION_BITS;
|
|
-- the internal ir_width representation
|
|
signal ir_srl : std_logic_vector(SLD_NODE_IR_WIDTH_i - 1 downto 0);
|
|
-- ir shift register
|
|
signal virtual_ir_in_i : std_logic_vector(SLD_NODE_IR_WIDTH_i - 1 downto 0);
|
|
-- internal hold portion of ir shift register
|
|
signal capture_ir : std_logic; -- signals a force_ir_capture
|
|
begin -- behavior
|
|
|
|
-- purpose: the register for the fsm and other registered data
|
|
-- type : sequential
|
|
-- inputs : tck, trst
|
|
-- outputs:
|
|
stateReg : process (jtag_tck,jtag_state_tlr)
|
|
begin -- process stateReg
|
|
if jtag_state_tlr = '1' then -- asynchronous reset (active high)
|
|
ir_srl <= (others => '0');
|
|
jtag_tdo <= '0';
|
|
dummy_tdi <= '0';
|
|
capture_ir <= '0';
|
|
virtual_ir_in <= (others => '0');
|
|
elsif jtag_tck'event and jtag_tck = '1' then -- rising clock edge
|
|
virtual_ir_in <= virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 2 downto NUM_SELECTION_BITS - 1);
|
|
-- should check for 011 instruction
|
|
-- but we know that it is the only instruction ever sent to the
|
|
-- hub. So all we have to do is check the selection bit, udr and
|
|
-- usr1 state
|
|
if (jtag_state_udr = '1' and ir_srl(SLD_NODE_IR_WIDTH_i - 1) = '0') then
|
|
capture_ir <= jtag_usr1;
|
|
elsif (jtag_state_e1dr = '1') then
|
|
capture_ir <= '0';
|
|
end if;
|
|
|
|
if (jtag_usr1 = '1' and jtag_state_sdr = '1') then
|
|
|
|
ir_srl(SLD_NODE_IR_WIDTH_i - 2 downto 0) <= ir_srl(SLD_NODE_IR_WIDTH_i - 1 downto 1);
|
|
ir_srl(SLD_NODE_IR_WIDTH_i - 1) <= jtag_tdi;
|
|
jtag_tdo <= ir_srl(0);
|
|
|
|
elsif (capture_ir = '1' and jtag_state_cdr = '1') then
|
|
|
|
ir_srl(SLD_NODE_IR_WIDTH_i - 2 downto NUM_SELECTION_BITS - 1) <= virtual_ir_out;
|
|
|
|
elsif (capture_ir = '1' and jtag_state_sdr = '1') then
|
|
|
|
ir_srl(SLD_NODE_IR_WIDTH_i - 2 downto 0) <= ir_srl(SLD_NODE_IR_WIDTH_i - 1 downto 1);
|
|
ir_srl(SLD_NODE_IR_WIDTH_i - 1) <= jtag_tdi;
|
|
jtag_tdo <= ir_srl(0);
|
|
|
|
elsif (jtag_state_sdr = '1') then
|
|
|
|
dummy_tdi <= jtag_tdi;
|
|
jtag_tdo <= dummy_tdo;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
end process stateReg;
|
|
|
|
-- pipe through signals
|
|
dummy_state_tlr <= jtag_state_tlr;
|
|
dummy_state_rti <= jtag_state_rti;
|
|
dummy_state_drs <= jtag_state_drs;
|
|
dummy_state_cdr <= jtag_state_cdr;
|
|
dummy_state_sdr <= jtag_state_sdr;
|
|
dummy_state_e1dr <= jtag_state_e1dr;
|
|
dummy_state_pdr <= jtag_state_pdr;
|
|
dummy_state_e2dr <= jtag_state_e2dr;
|
|
dummy_state_udr <= jtag_state_udr;
|
|
dummy_state_irs <= jtag_state_irs;
|
|
dummy_state_cir <= jtag_state_cir;
|
|
dummy_state_sir <= jtag_state_sir;
|
|
dummy_state_e1ir <= jtag_state_e1ir;
|
|
dummy_state_pir <= jtag_state_pir;
|
|
dummy_state_e2ir <= jtag_state_e2ir;
|
|
dummy_state_uir <= jtag_state_uir;
|
|
dummy_tms <= jtag_tms;
|
|
dummy_tck <= jtag_tck;
|
|
-- virtual signals
|
|
virtual_state_uir <= jtag_usr1 and jtag_state_udr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
|
|
virtual_state_cir <= jtag_usr1 and jtag_state_cdr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
|
|
virtual_state_udr <= not jtag_usr1 and jtag_state_udr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
|
|
virtual_state_e2dr <= not jtag_usr1 and jtag_state_e2dr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
|
|
virtual_state_pdr <= not jtag_usr1 and jtag_state_pdr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
|
|
virtual_state_e1dr <= not jtag_usr1 and jtag_state_e1dr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
|
|
virtual_state_sdr <= not jtag_usr1 and jtag_state_sdr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
|
|
virtual_state_cdr <= not jtag_usr1 and jtag_state_cdr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
|
|
|
|
|
|
-- purpose: captures the shift register during jtag_state_e1dr
|
|
-- type : sequential
|
|
-- inputs : jtag_tck, jtag_state_tlr
|
|
-- outputs: virtual_ir_in
|
|
SHIFT_REG_HOLD : process (jtag_tck, jtag_state_tlr)
|
|
begin -- process SHIFT_REG_HOLD
|
|
if jtag_state_tlr = '1' then -- asynchronous reset (active high)
|
|
virtual_ir_in_i <= (others => '0');
|
|
elsif jtag_tck'event and jtag_tck = '0' then -- falling clock edge
|
|
if (ir_srl(SLD_NODE_IR_WIDTH_i - 1) = '1' and jtag_state_e1dr = '1') then
|
|
virtual_ir_in_i <= ir_srl;
|
|
end if;
|
|
end if;
|
|
end process SHIFT_REG_HOLD;
|
|
|
|
|
|
end behavior;
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
use work.signal_gen;
|
|
use work.jtag_tap_controller;
|
|
use work.dummy_hub;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Entity Name : sld_virtual_jtag
|
|
--
|
|
-- Description : Simulatiom model for SLD_VIRTUAL_JTAG megafunction
|
|
--
|
|
-- Limitation :
|
|
--
|
|
-- Results Expected :
|
|
--
|
|
--
|
|
-------------------------------------------------------------------------------
|
|
|
|
|
|
entity sld_virtual_jtag is
|
|
|
|
generic (
|
|
lpm_type : string := "SLD_VIRTUAL_JTAG";
|
|
-- required by coding standard
|
|
lpm_hint : string := "SLD_VIRTUAL_JTAG"; -- required by coding standard
|
|
sld_auto_instance_index : string := "NO";
|
|
-- Yes of auto index is desired and no otherwise
|
|
sld_instance_index : integer := 0;
|
|
-- Index to be used if SLD_AUTO_INSTANCE_INDEX is no
|
|
sld_ir_width : integer := 1;
|
|
-- the width of the IR register
|
|
sld_sim_n_scan : integer := 0;
|
|
-- the number of scans in the simulation model
|
|
sld_sim_total_length : integer := 0;
|
|
-- the total bit width of all DR scan values
|
|
sld_sim_action : string := "");
|
|
-- the actions to be simulated in a format specified by the documentation
|
|
port (
|
|
tdo : in std_logic := '0'; -- tdo signal into megafunction
|
|
ir_out : in std_logic_vector(sld_ir_width - 1 downto 0) := (others => '0');
|
|
-- parallel ir data into megafunction
|
|
tck : out std_logic; -- tck signal from megafunction
|
|
tdi : out std_logic; -- tdi signal from megafunction
|
|
ir_in : out std_logic_vector(sld_ir_width - 1 downto 0);
|
|
-- paraller ir data from megafunction
|
|
virtual_state_cdr : out std_logic; -- cdr state signal of megafunction
|
|
virtual_state_sdr : out std_logic; -- sdr state signal of megafunction
|
|
virtual_state_e1dr : out std_logic;
|
|
-- e1dr state signal of megafunction
|
|
virtual_state_pdr : out std_logic; -- pdr state signal of megafunction
|
|
virtual_state_e2dr : out std_logic;
|
|
-- e2dr state signal of megafunction
|
|
virtual_state_udr : out std_logic; -- udr state signal of megafunction
|
|
virtual_state_cir : out std_logic; -- cir state signal of megafunction
|
|
virtual_state_uir : out std_logic; -- uir state signal of megafunction
|
|
jtag_state_tlr : out std_logic; -- Test, Logic, Reset state
|
|
jtag_state_rti : out std_logic; -- Run, Test, Idle state
|
|
jtag_state_sdrs : out std_logic; -- Select DR scan state
|
|
jtag_state_cdr : out std_logic; -- capture DR state
|
|
jtag_state_sdr : out std_logic; -- Shift DR state
|
|
jtag_state_e1dr : out std_logic; -- exit 1 dr state
|
|
jtag_state_pdr : out std_logic; -- pause dr state
|
|
jtag_state_e2dr : out std_logic; -- exit 2 dr state
|
|
jtag_state_udr : out std_logic; -- update dr state
|
|
jtag_state_sirs : out std_logic; -- Select IR scan state
|
|
jtag_state_cir : out std_logic; -- capture IR state
|
|
jtag_state_sir : out std_logic; -- shift IR state
|
|
jtag_state_e1ir : out std_logic; -- exit 1 IR state
|
|
jtag_state_pir : out std_logic; -- pause IR state
|
|
jtag_state_e2ir : out std_logic; -- exit 2 IR state
|
|
jtag_state_uir : out std_logic; -- update IR state
|
|
tms : out std_logic); -- tms signal
|
|
end sld_virtual_jtag;
|
|
|
|
architecture structural of sld_virtual_jtag is
|
|
|
|
component signal_gen
|
|
generic (
|
|
sld_node_ir_width : integer;
|
|
sld_node_n_scan : natural;
|
|
sld_node_total_length : natural;
|
|
sld_node_sim_action : string);
|
|
port (
|
|
tck : out std_logic;
|
|
tms : out std_logic;
|
|
tdi : out std_logic;
|
|
jtag_usr1 : in std_logic;
|
|
tdo : in std_logic);
|
|
end component;
|
|
|
|
component jtag_tap_controller
|
|
generic (
|
|
ir_register_width : integer);
|
|
port (
|
|
tck : in std_logic;
|
|
tms : in std_logic;
|
|
tdi : in std_logic;
|
|
jtag_tdo : in std_logic;
|
|
tdo : out std_logic;
|
|
jtag_tck : out std_logic;
|
|
jtag_tms : out std_logic;
|
|
jtag_tdi : out std_logic;
|
|
jtag_state_tlr : out std_logic;
|
|
jtag_state_rti : out std_logic;
|
|
jtag_state_drs : out std_logic;
|
|
jtag_state_cdr : out std_logic;
|
|
jtag_state_sdr : out std_logic;
|
|
jtag_state_e1dr : out std_logic;
|
|
jtag_state_pdr : out std_logic;
|
|
jtag_state_e2dr : out std_logic;
|
|
jtag_state_udr : out std_logic;
|
|
jtag_state_irs : out std_logic;
|
|
jtag_state_cir : out std_logic;
|
|
jtag_state_sir : out std_logic;
|
|
jtag_state_e1ir : out std_logic;
|
|
jtag_state_pir : out std_logic;
|
|
jtag_state_e2ir : out std_logic;
|
|
jtag_state_uir : out std_logic;
|
|
jtag_usr1 : out std_logic);
|
|
end component;
|
|
|
|
component dummy_hub
|
|
generic (
|
|
sld_node_ir_width : integer);
|
|
port (
|
|
jtag_tck : in std_logic;
|
|
jtag_tdi : in std_logic;
|
|
jtag_tms : in std_logic;
|
|
jtag_usr1 : in std_logic;
|
|
jtag_state_tlr : in std_logic;
|
|
jtag_state_rti : in std_logic;
|
|
jtag_state_drs : in std_logic;
|
|
jtag_state_cdr : in std_logic;
|
|
jtag_state_sdr : in std_logic;
|
|
jtag_state_e1dr : in std_logic;
|
|
jtag_state_pdr : in std_logic;
|
|
jtag_state_e2dr : in std_logic;
|
|
jtag_state_udr : in std_logic;
|
|
jtag_state_irs : in std_logic;
|
|
jtag_state_cir : in std_logic;
|
|
jtag_state_sir : in std_logic;
|
|
jtag_state_e1ir : in std_logic;
|
|
jtag_state_pir : in std_logic;
|
|
jtag_state_e2ir : in std_logic;
|
|
jtag_state_uir : in std_logic;
|
|
dummy_tdo : in std_logic;
|
|
virtual_ir_out : in std_logic_vector(sld_node_ir_width - 1 downto 0);
|
|
jtag_tdo : out std_logic;
|
|
dummy_tck : out std_logic;
|
|
dummy_tdi : out std_logic;
|
|
dummy_tms : out std_logic;
|
|
dummy_state_tlr : out std_logic;
|
|
dummy_state_rti : out std_logic;
|
|
dummy_state_drs : out std_logic;
|
|
dummy_state_cdr : out std_logic;
|
|
dummy_state_sdr : out std_logic;
|
|
dummy_state_e1dr : out std_logic;
|
|
dummy_state_pdr : out std_logic;
|
|
dummy_state_e2dr : out std_logic;
|
|
dummy_state_udr : out std_logic;
|
|
dummy_state_irs : out std_logic;
|
|
dummy_state_cir : out std_logic;
|
|
dummy_state_sir : out std_logic;
|
|
dummy_state_e1ir : out std_logic;
|
|
dummy_state_pir : out std_logic;
|
|
dummy_state_e2ir : out std_logic;
|
|
dummy_state_uir : out std_logic;
|
|
virtual_state_cdr : out std_logic;
|
|
virtual_state_sdr : out std_logic;
|
|
virtual_state_e1dr : out std_logic;
|
|
virtual_state_pdr : out std_logic;
|
|
virtual_state_e2dr : out std_logic;
|
|
virtual_state_udr : out std_logic;
|
|
virtual_state_cir : out std_logic;
|
|
virtual_state_uir : out std_logic;
|
|
virtual_ir_in : out std_logic_vector(sld_node_ir_width - 1 downto 0));
|
|
end component;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- internal signals
|
|
signal tck_i : std_logic;
|
|
signal tms_i : std_logic;
|
|
signal tdi_i : std_logic;
|
|
signal tdo_i : std_logic;
|
|
signal jtag_tdo_i : std_logic;
|
|
signal jtag_tck_i : std_logic;
|
|
signal jtag_tms_i : std_logic;
|
|
signal jtag_tdi_i : std_logic;
|
|
signal jtag_state_tlr_i : std_logic;
|
|
signal jtag_state_rti_i : std_logic;
|
|
signal jtag_state_drs_i : std_logic;
|
|
signal jtag_state_cdr_i : std_logic;
|
|
signal jtag_state_sdr_i : std_logic;
|
|
signal jtag_state_e1dr_i : std_logic;
|
|
signal jtag_state_pdr_i : std_logic;
|
|
signal jtag_state_e2dr_i : std_logic;
|
|
signal jtag_state_udr_i : std_logic;
|
|
signal jtag_state_irs_i : std_logic;
|
|
signal jtag_state_cir_i : std_logic;
|
|
signal jtag_state_sir_i : std_logic;
|
|
signal jtag_state_e1ir_i : std_logic;
|
|
signal jtag_state_pir_i : std_logic;
|
|
signal jtag_state_e2ir_i : std_logic;
|
|
signal jtag_state_uir_i : std_logic;
|
|
signal jtag_usr1_i : std_logic;
|
|
|
|
constant ir_register_width : integer := 10; -- the width of the ir shift register
|
|
|
|
|
|
|
|
begin -- structural
|
|
user_input: signal_gen
|
|
generic map (
|
|
sld_node_ir_width => sld_ir_width,
|
|
sld_node_n_scan => sld_sim_n_scan,
|
|
sld_node_total_length => sld_sim_total_length,
|
|
sld_node_sim_action => sld_sim_action)
|
|
port map (
|
|
tck => tck_i,
|
|
tms => tms_i,
|
|
tdi => tdi_i,
|
|
jtag_usr1 => jtag_usr1_i,
|
|
tdo => tdo_i);
|
|
|
|
jtag : jtag_tap_controller
|
|
generic map (
|
|
ir_register_width => ir_register_width)
|
|
port map (
|
|
tck => tck_i,
|
|
tms => tms_i,
|
|
tdi => tdi_i,
|
|
jtag_tdo => jtag_tdo_i,
|
|
tdo => tdo_i,
|
|
jtag_tck => jtag_tck_i,
|
|
jtag_tms => jtag_tms_i,
|
|
jtag_tdi => jtag_tdi_i,
|
|
jtag_state_tlr => jtag_state_tlr_i,
|
|
jtag_state_rti => jtag_state_rti_i,
|
|
jtag_state_drs => jtag_state_drs_i,
|
|
jtag_state_cdr => jtag_state_cdr_i,
|
|
jtag_state_sdr => jtag_state_sdr_i,
|
|
jtag_state_e1dr => jtag_state_e1dr_i,
|
|
jtag_state_pdr => jtag_state_pdr_i,
|
|
jtag_state_e2dr => jtag_state_e2dr_i,
|
|
jtag_state_udr => jtag_state_udr_i,
|
|
jtag_state_irs => jtag_state_irs_i,
|
|
jtag_state_cir => jtag_state_cir_i,
|
|
jtag_state_sir => jtag_state_sir_i,
|
|
jtag_state_e1ir => jtag_state_e1ir_i,
|
|
jtag_state_pir => jtag_state_pir_i,
|
|
jtag_state_e2ir => jtag_state_e2ir_i,
|
|
jtag_state_uir => jtag_state_uir_i,
|
|
jtag_usr1 => jtag_usr1_i);
|
|
|
|
hub: dummy_hub
|
|
generic map (
|
|
sld_node_ir_width => sld_ir_width)
|
|
port map (
|
|
jtag_tck => jtag_tck_i,
|
|
jtag_tdi => jtag_tdi_i,
|
|
jtag_tms => jtag_tms_i,
|
|
jtag_usr1 => jtag_usr1_i,
|
|
jtag_state_tlr => jtag_state_tlr_i,
|
|
jtag_state_rti => jtag_state_rti_i,
|
|
jtag_state_drs => jtag_state_drs_i,
|
|
jtag_state_cdr => jtag_state_cdr_i,
|
|
jtag_state_sdr => jtag_state_sdr_i,
|
|
jtag_state_e1dr => jtag_state_e1dr_i,
|
|
jtag_state_pdr => jtag_state_pdr_i,
|
|
jtag_state_e2dr => jtag_state_e2dr_i,
|
|
jtag_state_udr => jtag_state_udr_i,
|
|
jtag_state_irs => jtag_state_irs_i,
|
|
jtag_state_cir => jtag_state_cir_i,
|
|
jtag_state_sir => jtag_state_sir_i,
|
|
jtag_state_e1ir => jtag_state_e1ir_i,
|
|
jtag_state_pir => jtag_state_pir_i,
|
|
jtag_state_e2ir => jtag_state_e2ir_i,
|
|
jtag_state_uir => jtag_state_uir_i,
|
|
dummy_tdo => tdo,
|
|
virtual_ir_out => ir_out,
|
|
jtag_tdo => jtag_tdo_i,
|
|
dummy_tck => tck,
|
|
dummy_tdi => tdi,
|
|
dummy_tms => tms,
|
|
dummy_state_tlr => jtag_state_tlr,
|
|
dummy_state_rti => jtag_state_rti,
|
|
dummy_state_drs => jtag_state_sdrs,
|
|
dummy_state_cdr => jtag_state_cdr,
|
|
dummy_state_sdr => jtag_state_sdr,
|
|
dummy_state_e1dr => jtag_state_e1dr,
|
|
dummy_state_pdr => jtag_state_pdr,
|
|
dummy_state_e2dr => jtag_state_e2dr,
|
|
dummy_state_udr => jtag_state_udr,
|
|
dummy_state_irs => jtag_state_sirs,
|
|
dummy_state_cir => jtag_state_cir,
|
|
dummy_state_sir => jtag_state_sir,
|
|
dummy_state_e1ir => jtag_state_e1ir,
|
|
dummy_state_pir => jtag_state_pir,
|
|
dummy_state_e2ir => jtag_state_e2ir,
|
|
dummy_state_uir => jtag_state_uir,
|
|
virtual_state_cdr => virtual_state_cdr,
|
|
virtual_state_sdr => virtual_state_sdr,
|
|
virtual_state_e1dr => virtual_state_e1dr,
|
|
virtual_state_pdr => virtual_state_pdr,
|
|
virtual_state_e2dr => virtual_state_e2dr,
|
|
virtual_state_udr => virtual_state_udr,
|
|
virtual_state_cir => virtual_state_cir,
|
|
virtual_state_uir => virtual_state_uir,
|
|
virtual_ir_in => ir_in);
|
|
|
|
end structural;
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.altera_mf_components.all;
|
|
|
|
entity sld_signaltap is
|
|
generic (
|
|
SLD_USE_JTAG_SIGNAL_ADAPTER : natural := 1;
|
|
SLD_CURRENT_RESOURCE_WIDTH : natural := 0;
|
|
SLD_INVERSION_MASK : std_logic_vector := "0";
|
|
SLD_POWER_UP_TRIGGER : natural := 0;
|
|
SLD_ADVANCED_TRIGGER_6 : string := "NONE";
|
|
SLD_ADVANCED_TRIGGER_9 : string := "NONE";
|
|
SLD_ADVANCED_TRIGGER_7 : string := "NONE";
|
|
SLD_HPS_EVENT_ENABLED : natural := 0;
|
|
SLD_STORAGE_QUALIFIER_ADVANCED_CONDITION_ENTITY : string := "basic";
|
|
SLD_STORAGE_QUALIFIER_GAP_RECORD : natural := 0;
|
|
SLD_SECTION_ID : string := "hdl_signaltap_0";
|
|
SLD_INCREMENTAL_ROUTING : natural := 0;
|
|
SLD_STORAGE_QUALIFIER_PIPELINE : natural := 0;
|
|
SLD_TRIGGER_IN_ENABLED : natural := 0;
|
|
SLD_STATE_BITS : natural := 11;
|
|
SLD_HPS_EVENT_ID : natural := 0;
|
|
SLD_CREATE_MONITOR_INTERFACE : natural := 0;
|
|
SLD_STATE_FLOW_USE_GENERATED : natural := 0;
|
|
SLD_INVERSION_MASK_LENGTH : integer := 1;
|
|
SLD_DATA_BITS : natural := 1;
|
|
SLD_BUFFER_FULL_STOP : natural := 1;
|
|
SLD_STORAGE_QUALIFIER_INVERSION_MASK_LENGTH : natural := 0;
|
|
SLD_ATTRIBUTE_MEM_MODE : string := "OFF";
|
|
SLD_STORAGE_QUALIFIER_MODE : string := "OFF";
|
|
SLD_STATE_FLOW_MGR_ENTITY : string := "state_flow_mgr_entity.vhd";
|
|
SLD_HPS_TRIGGER_IN_ENABLED : natural := 0;
|
|
SLD_NODE_CRC_LOWORD : natural := 50132;
|
|
SLD_ADVANCED_TRIGGER_5 : string := "NONE";
|
|
SLD_TRIGGER_BITS : natural := 1;
|
|
SLD_STORAGE_QUALIFIER_BITS : natural := 1;
|
|
SLD_HPS_TRIGGER_OUT_ENABLED : natural := 0;
|
|
SLD_ADVANCED_TRIGGER_10 : string := "NONE";
|
|
SLD_MEM_ADDRESS_BITS : natural := 7;
|
|
SLD_ADVANCED_TRIGGER_ENTITY : string := "basic";
|
|
SLD_ADVANCED_TRIGGER_4 : string := "NONE";
|
|
SLD_ADVANCED_TRIGGER_8 : string := "NONE";
|
|
SLD_TRIGGER_LEVEL : natural := 10;
|
|
SLD_RAM_BLOCK_TYPE : string := "AUTO";
|
|
SLD_ADVANCED_TRIGGER_2 : string := "NONE";
|
|
SLD_ADVANCED_TRIGGER_1 : string := "NONE";
|
|
SLD_DATA_BIT_CNTR_BITS : natural := 4;
|
|
SLD_SAMPLE_DEPTH : natural := 16;
|
|
lpm_type : string := "sld_signaltap";
|
|
SLD_NODE_CRC_BITS : natural := 32;
|
|
SLD_ENABLE_ADVANCED_TRIGGER : natural := 0;
|
|
SLD_SEGMENT_SIZE : natural := 0;
|
|
SLD_NODE_INFO : natural := 0;
|
|
SLD_STORAGE_QUALIFIER_ENABLE_ADVANCED_CONDITION : natural := 0;
|
|
SLD_NODE_CRC_HIWORD : natural := 41394;
|
|
SLD_TRIGGER_LEVEL_PIPELINE : natural := 1;
|
|
SLD_ADVANCED_TRIGGER_3 : string := "NONE"
|
|
);
|
|
port (
|
|
jtag_state_sdr : in std_logic := '0';
|
|
ir_in : in std_logic_vector(SLD_IR_BITS-1 downto 0) := (others => '0');
|
|
acq_trigger_out : out std_logic_vector(SLD_TRIGGER_BITS-1 downto 0);
|
|
gnd : out std_logic;
|
|
jtag_state_cir : in std_logic := '0';
|
|
jtag_state_e2ir : in std_logic := '0';
|
|
jtag_state_pir : in std_logic := '0';
|
|
jtag_state_udr : in std_logic := '0';
|
|
vcc : out std_logic;
|
|
jtag_state_e1dr : in std_logic := '0';
|
|
jtag_state_rti : in std_logic := '0';
|
|
jtag_state_e1ir : in std_logic := '0';
|
|
jtag_state_pdr : in std_logic := '0';
|
|
acq_clk : in std_logic;
|
|
clr : in std_logic := '0';
|
|
trigger_in : in std_logic := '0';
|
|
ir_out : out std_logic_vector(SLD_IR_BITS-1 downto 0);
|
|
jtag_state_sirs : in std_logic := '0';
|
|
jtag_state_cdr : in std_logic := '0';
|
|
jtag_state_sir : in std_logic := '0';
|
|
jtag_state_e2dr : in std_logic := '0';
|
|
tms : in std_logic := '0';
|
|
jtag_state_tlr : in std_logic := '0';
|
|
jtag_state_sdrs : in std_logic := '0';
|
|
tdi : in std_logic := '0';
|
|
jtag_state_uir : in std_logic := '0';
|
|
acq_trigger_in : in std_logic_vector(SLD_TRIGGER_BITS-1 downto 0) := (others => '0');
|
|
trigger_out : out std_logic;
|
|
storage_enable : in std_logic := '0';
|
|
acq_data_out : out std_logic_vector(SLD_DATA_BITS-1 downto 0);
|
|
acq_storage_qualifier_in : in std_logic_vector(SLD_STORAGE_QUALIFIER_BITS-1 downto 0) := (others => '0');
|
|
acq_data_in : in std_logic_vector(SLD_DATA_BITS-1 downto 0) := (others => '0');
|
|
tdo : out std_logic;
|
|
crc : in std_logic_vector(SLD_NODE_CRC_BITS-1 downto 0) := (others => '0');
|
|
clrn : in std_logic := '0';
|
|
raw_tck : in std_logic := '0';
|
|
irq : out std_logic;
|
|
usr1 : in std_logic := '0';
|
|
ena : in std_logic := '0'
|
|
);
|
|
end sld_signaltap;
|
|
|
|
architecture sim_sld_signaltap of sld_signaltap is
|
|
begin
|
|
|
|
end sim_sld_signaltap;
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.altera_mf_components.all;
|
|
|
|
entity altstratixii_oct is
|
|
generic (
|
|
lpm_type : string := "altstratixii_oct"
|
|
);
|
|
port (
|
|
terminationenable : in std_logic;
|
|
terminationclock : in std_logic;
|
|
rdn : in std_logic;
|
|
rup : in std_logic
|
|
);
|
|
end altstratixii_oct;
|
|
|
|
architecture sim_altstratixii_oct of altstratixii_oct is
|
|
begin
|
|
|
|
end sim_altstratixii_oct;
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.altera_mf_components.all;
|
|
|
|
entity altparallel_flash_loader is
|
|
generic (
|
|
flash_data_width : NATURAL := 16;
|
|
dclk_create_delay : NATURAL := 0;
|
|
flash_burst_extra_cycle : NATURAL := 0;
|
|
safe_mode_retry : NATURAL := 1;
|
|
us_unit_counter : NATURAL := 1;
|
|
burst_mode_numonyx : NATURAL := 0;
|
|
burst_mode : NATURAL := 0;
|
|
clk_divisor : NATURAL := 1;
|
|
addr_width : NATURAL := 20;
|
|
tristate_checkbox : NATURAL := 0;
|
|
nflash_mfc : STRING := "NUMONYX";
|
|
safe_mode_revert_addr : NATURAL := 0;
|
|
flash_static_wait_width : NATURAL := 15;
|
|
page_mode : NATURAL := 0;
|
|
flash_ecc_checkbox : NATURAL := 0;
|
|
features_pgm : NATURAL := 1;
|
|
BURST_MODE_LATENCY_COUNT : NATURAL := 4;
|
|
auto_restart : STRING := "OFF";
|
|
page_clk_divisor : NATURAL := 1;
|
|
safe_mode_halt : NATURAL := 0;
|
|
flash_nreset_counter : NATURAL := 1;
|
|
normal_mode : NATURAL := 1;
|
|
safe_mode_revert : NATURAL := 0;
|
|
fifo_size : NATURAL := 16;
|
|
nrb_addr : NATURAL := 65667072;
|
|
nand_size : NATURAL := 67108864;
|
|
dclk_divisor : NATURAL := 1;
|
|
rsu_watchdog_counter : NATURAL := 100000000;
|
|
flash_nreset_checkbox : NATURAL := 0;
|
|
flash_type : STRING := "CFI_FLASH";
|
|
features_cfg : NATURAL := 1;
|
|
burst_mode_intel : NATURAL := 0;
|
|
extra_addr_byte : NATURAL := 0;
|
|
qspi_data_delay : NATURAL := 0;
|
|
option_bits_start_address : NATURAL := 0;
|
|
pfl_rsu_watchdog_enabled : NATURAL := 0;
|
|
qflash_fast_speed : NATURAL := 0;
|
|
enhanced_flash_programming : NATURAL := 0;
|
|
qspi_data_delay_count : NATURAL := 1;
|
|
conf_wait_timer_width : NATURAL := 16;
|
|
lpm_type : STRING := "ALTPARALLEL_FLASH_LOADER";
|
|
n_flash : NATURAL := 1;
|
|
disable_crc_checkbox : NATURAL := 0;
|
|
burst_mode_spansion : NATURAL := 0;
|
|
qflash_mfc : STRING := "ALTERA";
|
|
decompressor_mode : STRING := "NONE";
|
|
conf_data_width : NATURAL := 1
|
|
);
|
|
port (
|
|
flash_nce : out std_logic_vector(n_flash-1 downto 0);
|
|
fpga_data : out std_logic_vector(conf_data_width-1 downto 0);
|
|
fpga_dclk : out std_logic;
|
|
fpga_nstatus : in std_logic := '0';
|
|
flash_ale : out std_logic;
|
|
pfl_clk : in std_logic := '0';
|
|
fpga_nconfig : out std_logic;
|
|
flash_io2 : inout std_logic_vector(n_flash-1 downto 0);
|
|
flash_sck : out std_logic_vector(n_flash-1 downto 0);
|
|
flash_noe : out std_logic;
|
|
flash_nwe : out std_logic;
|
|
pfl_watchdog_error : out std_logic;
|
|
pfl_reset_watchdog : in std_logic := '0';
|
|
fpga_conf_done : in std_logic := '0';
|
|
flash_rdy : in std_logic := '1';
|
|
pfl_flash_access_granted : in std_logic := '0';
|
|
pfl_nreconfigure : in std_logic := '1';
|
|
flash_cle : out std_logic;
|
|
flash_nreset : out std_logic;
|
|
flash_io0 : inout std_logic_vector(n_flash-1 downto 0);
|
|
pfl_nreset : in std_logic := '0';
|
|
flash_data : inout std_logic_vector(flash_data_width-1 downto 0);
|
|
flash_io1 : inout std_logic_vector(n_flash-1 downto 0);
|
|
flash_nadv : out std_logic;
|
|
flash_clk : out std_logic;
|
|
flash_io3 : inout std_logic_vector(n_flash-1 downto 0);
|
|
flash_io : inout std_logic_vector(7 downto 0);
|
|
flash_addr : out std_logic_vector(addr_width-1 downto 0);
|
|
pfl_flash_access_request : out std_logic;
|
|
flash_ncs : out std_logic_vector(n_flash-1 downto 0);
|
|
fpga_pgm : in std_logic_vector(2 downto 0) := (others => '0')
|
|
);
|
|
end altparallel_flash_loader;
|
|
|
|
architecture sim_altparallel_flash_loader of altparallel_flash_loader is
|
|
begin
|
|
|
|
end sim_altparallel_flash_loader;
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.altera_mf_components.all;
|
|
|
|
entity altserial_flash_loader is
|
|
generic (
|
|
enhanced_mode : natural := 0;
|
|
intended_device_family : STRING := "Cyclone";
|
|
enable_shared_access : STRING := "OFF";
|
|
enable_quad_spi_support : natural := 0;
|
|
ncso_width : natural := 1;
|
|
lpm_type : STRING := "ALTSERIAL_FLASH_LOADER"
|
|
);
|
|
port (
|
|
data_in : in std_logic_vector(3 downto 0) := (others => '0');
|
|
noe : in std_logic := '0';
|
|
asmi_access_granted : in std_logic := '1';
|
|
data_out : out std_logic_vector(3 downto 0);
|
|
data_oe : in std_logic_vector(3 downto 0) := (others => '0');
|
|
sdoin : in std_logic := '0';
|
|
asmi_access_request : out std_logic;
|
|
data0out : out std_logic;
|
|
scein : in std_logic_vector(ncso_width-1 downto 0) := (others => '0');
|
|
dclkin : in std_logic := '0'
|
|
);
|
|
end altserial_flash_loader;
|
|
|
|
architecture sim_altserial_flash_loader of altserial_flash_loader is
|
|
begin
|
|
|
|
end sim_altserial_flash_loader;
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.altera_mf_components.all;
|
|
|
|
entity sld_virtual_jtag_basic is
|
|
generic (
|
|
lpm_hint : string := "UNUSED";
|
|
sld_sim_action : string := "UNUSED";
|
|
sld_instance_index : natural := 0;
|
|
sld_ir_width : natural := 1;
|
|
sld_sim_n_scan : natural := 0;
|
|
sld_mfg_id : natural := 0;
|
|
sld_version : natural := 0;
|
|
sld_type_id : natural := 0;
|
|
lpm_type : string := "sld_virtual_jtag_basic";
|
|
sld_auto_instance_index : string := "NO";
|
|
sld_sim_total_length : natural := 0
|
|
);
|
|
port (
|
|
jtag_state_sdr : out std_logic;
|
|
jtag_state_sirs : out std_logic;
|
|
ir_out : in std_logic_vector(sld_ir_width-1 downto 0);
|
|
jtag_state_sir : out std_logic;
|
|
jtag_state_cdr : out std_logic;
|
|
jtag_state_e2dr : out std_logic;
|
|
tms : out std_logic;
|
|
jtag_state_sdrs : out std_logic;
|
|
jtag_state_tlr : out std_logic;
|
|
ir_in : out std_logic_vector(sld_ir_width-1 downto 0);
|
|
virtual_state_sdr : out std_logic;
|
|
tdi : out std_logic;
|
|
jtag_state_uir : out std_logic;
|
|
jtag_state_cir : out std_logic;
|
|
virtual_state_cdr : out std_logic;
|
|
virtual_state_uir : out std_logic;
|
|
virtual_state_e2dr : out std_logic;
|
|
jtag_state_e2ir : out std_logic;
|
|
virtual_state_cir : out std_logic;
|
|
jtag_state_pir : out std_logic;
|
|
jtag_state_udr : out std_logic;
|
|
virtual_state_udr : out std_logic;
|
|
tdo : in std_logic;
|
|
jtag_state_e1dr : out std_logic;
|
|
jtag_state_rti : out std_logic;
|
|
virtual_state_pdr : out std_logic;
|
|
virtual_state_e1dr : out std_logic;
|
|
jtag_state_e1ir : out std_logic;
|
|
jtag_state_pdr : out std_logic;
|
|
tck : out std_logic
|
|
);
|
|
end sld_virtual_jtag_basic;
|
|
|
|
architecture sim_sld_virtual_jtag_basic of sld_virtual_jtag_basic is
|
|
begin
|
|
|
|
end sim_sld_virtual_jtag_basic;
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use work.altera_mf_components.all;
|
|
|
|
entity altsource_probe is
|
|
generic (
|
|
lpm_hint : string := "UNUSED";
|
|
sld_instance_index : natural := 0;
|
|
source_initial_value : string := "0";
|
|
sld_ir_width : natural := 4;
|
|
probe_width : natural := 1;
|
|
source_width : natural := 1;
|
|
instance_id : string := "UNUSED";
|
|
lpm_type : string := "altsource_probe";
|
|
sld_auto_instance_index : string := "YES";
|
|
SLD_NODE_INFO : natural := 4746752;
|
|
enable_metastability : string := "NO"
|
|
);
|
|
port (
|
|
source_clk : in std_logic;
|
|
probe : in std_logic_vector(probe_width-1 downto 0);
|
|
source : out std_logic_vector(source_width-1 downto 0);
|
|
source_ena : in std_logic
|
|
);
|
|
end altsource_probe;
|
|
|
|
architecture sim_altsource_probe of altsource_probe is
|
|
begin
|
|
|
|
end sim_altsource_probe;
|
|
|