diff options
author | jcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5> | 2008-09-08 01:00:12 +0000 |
---|---|---|
committer | jcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5> | 2008-09-08 01:00:12 +0000 |
commit | 61f2f0214c5999ea42a368a4fc99f03d8eb28d1e (patch) | |
tree | e7e24a9adc05ff1422fe3ada9926a51634741b47 /opencores/ethernet_tri_mode | |
download | uhd-61f2f0214c5999ea42a368a4fc99f03d8eb28d1e.tar.gz uhd-61f2f0214c5999ea42a368a4fc99f03d8eb28d1e.tar.bz2 uhd-61f2f0214c5999ea42a368a4fc99f03d8eb28d1e.zip |
Merged r9433:9527 from features/gr-usrp2 into trunk. Adds usrp2 and gr-usrp2 top-level components. Trunk passes distcheck with mb-gcc installed, but currently not without them. The key issue is that when mb-gcc is not installed, the build system skips over the usrp2/firmware directory, and the firmware include files don't get put into the dist tarball. But we can't do the usual DIST_SUBDIRS method as the firmware is a subpackage.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@9528 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'opencores/ethernet_tri_mode')
174 files changed, 44979 insertions, 0 deletions
diff --git a/opencores/ethernet_tri_mode/CVS/Entries b/opencores/ethernet_tri_mode/CVS/Entries new file mode 100644 index 000000000..c8bbf235a --- /dev/null +++ b/opencores/ethernet_tri_mode/CVS/Entries @@ -0,0 +1,6 @@ +/start.tcl/1.3/Sun May 28 05:00:17 2006// +D/bench//// +D/doc//// +D/rtl//// +D/sim//// +D/syn//// diff --git a/opencores/ethernet_tri_mode/CVS/Repository b/opencores/ethernet_tri_mode/CVS/Repository new file mode 100644 index 000000000..7c0a8c1d5 --- /dev/null +++ b/opencores/ethernet_tri_mode/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode diff --git a/opencores/ethernet_tri_mode/CVS/Root b/opencores/ethernet_tri_mode/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/CVS/Template b/opencores/ethernet_tri_mode/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/CVS/Template diff --git a/opencores/ethernet_tri_mode/bench/CVS/Entries b/opencores/ethernet_tri_mode/bench/CVS/Entries new file mode 100644 index 000000000..428c5622d --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/CVS/Entries @@ -0,0 +1 @@ +D/verilog//// diff --git a/opencores/ethernet_tri_mode/bench/CVS/Repository b/opencores/ethernet_tri_mode/bench/CVS/Repository new file mode 100644 index 000000000..f7aa7ea63 --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/bench diff --git a/opencores/ethernet_tri_mode/bench/CVS/Root b/opencores/ethernet_tri_mode/bench/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/bench/CVS/Template b/opencores/ethernet_tri_mode/bench/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/CVS/Template diff --git a/opencores/ethernet_tri_mode/bench/verilog/CVS/Entries b/opencores/ethernet_tri_mode/bench/verilog/CVS/Entries new file mode 100644 index 000000000..21ad451b1 --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/verilog/CVS/Entries @@ -0,0 +1,7 @@ +/Phy_sim.v/1.3/Fri Nov 17 17:53:07 2006// +/User_int_sim.v/1.3/Fri Nov 17 17:53:07 2006// +/altera_mf.v/1.1/Thu Jan 19 14:07:50 2006// +/host_sim.v/1.1/Thu Jan 19 14:07:51 2006// +/reg_int_sim.v/1.1/Tue Dec 13 12:54:38 2005// +/tb_top.v/1.3/Thu Jan 19 14:07:51 2006// +D diff --git a/opencores/ethernet_tri_mode/bench/verilog/CVS/Repository b/opencores/ethernet_tri_mode/bench/verilog/CVS/Repository new file mode 100644 index 000000000..614471f33 --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/verilog/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/bench/verilog diff --git a/opencores/ethernet_tri_mode/bench/verilog/CVS/Root b/opencores/ethernet_tri_mode/bench/verilog/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/verilog/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/bench/verilog/CVS/Template b/opencores/ethernet_tri_mode/bench/verilog/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/verilog/CVS/Template diff --git a/opencores/ethernet_tri_mode/bench/verilog/Phy_sim.v b/opencores/ethernet_tri_mode/bench/verilog/Phy_sim.v new file mode 100644 index 000000000..37bf364f9 --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/verilog/Phy_sim.v @@ -0,0 +1,102 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Phy_sim.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: Phy_sim.v,v $ +// Revision 1.3 2006/11/17 17:53:07 maverickist +// no message +// +// Revision 1.2 2006/01/19 14:07:50 maverickist +// verification is complete. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +`timescale 1ns/100ps + +module Phy_sim (input Gtx_clk ,//used only in GMII mode + output Rx_clk , + output Tx_clk ,//used only in MII mode + input Tx_er , + input Tx_en , + input [7:0] Txd , + output Rx_er , + output Rx_dv , + output [7:0] Rxd , + output Crs , + output Col , + input [2:0] Speed + ); + + // //////////////////////////////////////////////////////////////////// + // this file used to simulate Phy. + // generate clk and loop the Tx data to Rx data + // full duplex mode can be verified on loop mode. + // //////////////////////////////////////////////////////////////////// + // //////////////////////////////////////////////////////////////////// + // internal signals + // //////////////////////////////////////////////////////////////////// + reg Clk_25m ;//used for 100 Mbps mode + reg Clk_2_5m ;//used for 10 Mbps mode + //wire Rx_clk ; + //wire Tx_clk ;//used only in MII mode + // //////////////////////////////////////////////////////////////////// + always + begin + #20 Clk_25m=0; + #20 Clk_25m=1; + end + + always + begin + #200 Clk_2_5m=0; + #200 Clk_2_5m=1; + end + + assign Rx_clk=Speed[2]?Gtx_clk:Speed[1]?Clk_25m:Speed[0]?Clk_2_5m:0; + assign Tx_clk=Speed[2]?Gtx_clk:Speed[1]?Clk_25m:Speed[0]?Clk_2_5m:0; + + assign Rx_dv =Tx_en ; + assign Rxd =Txd ; + assign Rx_er =0 ; + assign Crs =Tx_en ; + assign Col =0 ; + +endmodule // Phy_sim diff --git a/opencores/ethernet_tri_mode/bench/verilog/User_int_sim.v b/opencores/ethernet_tri_mode/bench/verilog/User_int_sim.v new file mode 100644 index 000000000..90c79b3dd --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/verilog/User_int_sim.v @@ -0,0 +1,148 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// User_input_sim.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: User_int_sim.v,v $ +// Revision 1.3 2006/11/17 17:53:07 maverickist +// no message +// +// Revision 1.2 2006/01/19 14:07:50 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/13 12:15:35 Administrator +// no message +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module User_int_sim (Reset , + Clk_user , + CPU_init_end , + //user inputerface , + Rx_mac_ra , + Rx_mac_rd , + Rx_mac_data , + Rx_mac_BE , + Rx_mac_pa , + Rx_mac_sop , + Rx_mac_eop , + //user inputerface , + Tx_mac_wa , + Tx_mac_wr , + Tx_mac_data , + Tx_mac_BE , + Tx_mac_sop , + Tx_mac_eop + ); + + input Reset ; + input Clk_user ; + input CPU_init_end ; + //user inputerface + input Rx_mac_ra ; + output Rx_mac_rd ; + input [31:0] Rx_mac_data ; + input [1:0] Rx_mac_BE ; + input Rx_mac_pa ; + input Rx_mac_sop ; + input Rx_mac_eop ; + //user inputerface + input Tx_mac_wa ; + output Tx_mac_wr ; + output [31:0] Tx_mac_data ; + output [1:0] Tx_mac_BE ;//big endian + output Tx_mac_sop ; + output Tx_mac_eop ; + + // //////////////////////////////////////////////////////////////////// + // inputernal signals + // //////////////////////////////////////////////////////////////////// + reg [4:0] operation; + reg [31:0] data; + reg Rx_mac_rd; + reg Start_tran; + // //////////////////////////////////////////////////////////////////// + //generate Tx user data + // //////////////////////////////////////////////////////////////////// + initial + begin + operation =0; + data =0; + end + + always @ (posedge Clk_user or posedge Reset) + if (Reset) + Start_tran <=0; + else if (Tx_mac_eop&&!Tx_mac_wa) + Start_tran <=0; + else if (Tx_mac_wa) + Start_tran <=1; + + always @ (posedge Clk_user) + if (Tx_mac_wa&&CPU_init_end) + $ip_32W_gen("../data/config.ini",operation,data); + else + begin + operation <=0; + data <=0; + end + + assign Tx_mac_data =data; + assign Tx_mac_wr =operation[4]; + assign Tx_mac_sop =operation[3]; + assign Tx_mac_eop =operation[2]; + assign Tx_mac_BE =operation[1:0]; + ////////////////////////////////////////////////////////////////////// + //verify Rx user data + ////////////////////////////////////////////////////////////////////// + always @ (posedge Clk_user or posedge Reset) + if (Reset) + Rx_mac_rd <=0; + else if(Rx_mac_ra) + Rx_mac_rd <=1; + else + Rx_mac_rd <=0; + + always @ (posedge Clk_user ) + if (Rx_mac_pa) + $ip_32W_check( Rx_mac_data, + {Rx_mac_sop,Rx_mac_eop,Rx_mac_eop?Rx_mac_BE:2'b0}); + +endmodule // User_int_sim diff --git a/opencores/ethernet_tri_mode/bench/verilog/altera_mf.v b/opencores/ethernet_tri_mode/bench/verilog/altera_mf.v new file mode 100644 index 000000000..fffc46ff0 --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/verilog/altera_mf.v @@ -0,0 +1,34538 @@ +// Copyright (C) 1991-2005 Altera Corporation +// 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 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, 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 5.1 Build 176 10/26/2005 + + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : ALTERA_MF_MEMORY_INITIALIZATION +// +// Description : Common function to read intel-hex format data file with +// extension .hex and creates the equivalent verilog format +// data file with extension .ver. +// +// Limitation : Supports only record type '00'(data record), '01'(end of +// file record) and '02'(extended segment address record). +// +// Results expected: Creates the verilog format data file with extension .ver +// and return the name of the file. +// +//END_MODULE_NAME-------------------------------------------------------------- + + +`timescale 1 ps / 1 ps +module lcell (in, out); + input in; + output out; + + assign out = in; +endmodule + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +`define TRUE 1 +`define FALSE 0 +`define NULL 0 +`define EOF -1 +`define MAX_BUFFER_SZ 2048 +`define MAX_NAME_SZ 128 +`define COLON ":" +`define NEWLINE "\n" +`define CARRIAGE_RETURN 8'h0D +`define SPACE " " +`define OFFSET 9 +`define H10 8'h10 +`define AWORD 8 +`define MASK15 32'h000000FF +`define EXT_STR "ver" + +// MODULE DECLARATION +module ALTERA_MF_MEMORY_INITIALIZATION; + + +/****************************************************************/ +/* Read in Intel-hex format data to verilog format data. */ +/* Intel-hex format :nnaaaaattddddcc */ +/****************************************************************/ +task convert_hex2ver; + input[`MAX_NAME_SZ*8 : 1] in_file; + input width; + output [`MAX_NAME_SZ*8 : 1] out_file; + reg [`MAX_NAME_SZ*8 : 1] in_file; + reg [`MAX_NAME_SZ*8 : 1] out_file; + reg [8:1] c; + reg [3:0] hex, tmp_char; + + integer width; + integer ifp, ofp, r, r2; + integer i, j, k, m, n; + integer done; + integer error_status; + integer first_rec; + integer last_rec; + + integer off_addr, nn, aaaa, tt, cc, aah, aal, dd, sum ; + integer line_no; + +begin +`ifdef NO_PLI +`else + `ifdef USE_RIF + `else + done = `FALSE; + error_status = `FALSE; + first_rec = `FALSE; + last_rec = `FALSE; + + off_addr= 0; + nn= 0; + aaaa= 0; + tt= 0; + cc= 0; + aah= 0; + aal= 0; + dd= 0; + sum = 0; + line_no = 1; + c = 0; + hex = 0; + + if((in_file[4*8 : 1] == ".dat") || (in_file[4*8 : 1] == ".DAT")) + out_file = in_file; + else + begin + ifp = $fopen(in_file, "r"); + if (ifp == `NULL) + begin + $display("ERROR: cannot read %0s.", in_file); + done = `TRUE; + end + + out_file = in_file; + + if((out_file[4*8 : 1] == ".hex") || (out_file[4*8 : 1] == ".HEX")) + out_file[3*8 : 1] = `EXT_STR; + else + begin + $display("ERROR: Invalid input file name %0s. Expecting file with .hex extension and Intel-hex data format.", in_file); + done = `TRUE; + end + + ofp = $fopen(out_file, "w"); + if (ofp == `NULL) + begin + $display("ERROR : cannot write %0s.", out_file); + done = `TRUE; + end + + while((!done) && (!error_status)) + begin : READER + + r = $fgetc(ifp); + + if (r == `EOF) + begin + if(!first_rec) + begin + error_status = `TRUE; + $display("WARNING: %0s, Intel-hex data file is empty.", in_file); + end + else if(!last_rec) + begin + error_status = `TRUE; + $display("ERROR: %0s, line %0d, Missing the last record.", in_file, line_no); + end + end + else if (r == `COLON) + begin + first_rec = `TRUE; + nn= 0; + aaaa= 0; + tt= 0; + cc= 0; + aah= 0; + aal= 0; + dd= 0; + sum = 0; + + // get record length bytes + for (i = 0; i < 2; i = i+1) + begin + r = $fgetc(ifp); + + if ((r >= "0") && (r <= "9")) + nn = (nn * 16) + (r - 'h30); + else if ((r >= "A") && (r <= "F")) + nn = (nn * 16) + 10 + (r - 'h41); + else if ((r >= "a") && (r <= "f")) + nn = (nn * 16) + 10 + (r - 'h61); + else + begin + error_status = `TRUE; + $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no); + done = `TRUE; + disable READER; + end + end + + // get address bytes + for (i = 0; i < 4; i = i+1) + begin + r = $fgetc(ifp); + + if ((r >= "0") && (r <= "9")) + hex = (r - 'h30); + else if ((r >= "A") && (r <= "F")) + hex = 10 + (r - 'h41); + else if ((r >= "a") && (r <= "f")) + hex = 10 + (r - 'h61); + else + begin + error_status = `TRUE; + $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no); + done = `TRUE; + disable READER; + end + + aaaa = (aaaa * 16) + hex; + + if (i < 2) + aal = (aal * 16) + hex; + else + aah = (aah * 16) + hex; + end + + // get record type bytes + for (i = 0; i < 2; i = i+1) + begin + r = $fgetc(ifp); + + if ((r >= "0") && (r <= "9")) + tt = (tt * 16) + (r - 'h30); + else if ((r >= "A") && (r <= "F")) + tt = (tt * 16) + 10 + (r - 'h41); + else if ((r >= "a") && (r <= "f")) + tt = (tt * 16) + 10 + (r - 'h61); + else + begin + error_status = `TRUE; + $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no); + done = `TRUE; + disable READER; + end + end + + if((tt == 2) && (nn != 2) ) + begin + error_status = `TRUE; + $display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no); + end + else + begin + + // get the sum of all the bytes for record length, address and record types + sum = nn + aah + aal + tt ; + + // check the record type + case(tt) + // normal_record + 8'h00 : + begin + first_rec = `TRUE; + i = 0; + k = width / `AWORD; + if ((width % `AWORD) != 0) + k = k + 1; + + // k = no. of bytes per entry. + while (i < nn) + begin + $fdisplay(ofp,"@%0h", (aaaa + off_addr)); + for (j = 1; j <= k; j = j +1) + begin + if ((k - j +1) > nn) + begin + for(m = 1; m <= 2; m= m+1) + begin + if((((k-j)*8) + ((3-m)*4) - width) < 4) + $fwrite(ofp, "0"); + end + end + else + begin + // get the data bytes + for(m = 1; m <= 2; m= m+1) + begin + r = $fgetc(ifp); + + if ((r >= "0") && (r <= "9")) + hex = (r - 'h30); + else if ((r >= "A") && (r <= "F")) + hex = 10 + (r - 'h41); + else if ((r >= "a") && (r <= "f")) + hex = 10 + (r - 'h61); + else + begin + error_status = `TRUE; + $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no); + done = `TRUE; + disable READER; + end + + if((((k-j)*8) + ((3-m)*4) - width) < 4) + $fwrite(ofp, "%h", hex); + dd = (dd * 16) + hex; + + if(m % 2 == 0) + begin + sum = sum + dd; + dd = 0; + end + end + end + end + $fwrite(ofp, "\n"); + + i = i + k; + aaaa = aaaa + 1; + end // end of while (i < nn) + end + // last record + 8'h01: + begin + last_rec = `TRUE; + done = `TRUE; + end + // address base record + 8'h02: + begin + off_addr= 0; + + // get the extended segment address record + for(i = 1; i <= (nn*2); i= i+1) + begin + r = $fgetc(ifp); + + if ((r >= "0") && (r <= "9")) + hex = (r - 'h30); + else if ((r >= "A") && (r <= "F")) + hex = 10 + (r - 'h41); + else if ((r >= "a") && (r <= "f")) + hex = 10 + (r - 'h61); + else + begin + error_status = `TRUE; + $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no); + done = `TRUE; + disable READER; + end + + off_addr = (off_addr * `H10) + hex; + dd = (dd * 16) + hex; + + if(i % 2 == 0) + begin + sum = sum + dd; + dd = 0; + end + end + + off_addr = off_addr * `H10; + end + default: + begin + error_status = `TRUE; + $display("ERROR: %0s, line %0d, Unknown record type.", in_file, line_no); + end + endcase + + // get the checksum bytes + for (i = 0; i < 2; i = i+1) + begin + r = $fgetc(ifp); + + if ((r >= "0") && (r <= "9")) + cc = (cc * 16) + (r - 'h30); + else if ((r >= "A") && (r <= "F")) + cc = 10 + (cc * 16) + (r - 'h41); + else if ((r >= "a") && (r <= "f")) + cc = 10 + (cc * 16) + (r - 'h61); + else + begin + error_status = `TRUE; + $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no); + done = `TRUE; + disable READER; + end + end + + // Perform check sum. + if(((~sum+1)& `MASK15) != cc) + begin + error_status = `TRUE; + $display("ERROR: %0s, line %0d, Invalid checksum.", in_file, line_no); + end + end + end + else if ((r == `NEWLINE) || (r == `CARRIAGE_RETURN)) + begin + line_no = line_no +1; + end + else if (r == `SPACE) + begin + // continue to next character; + end + else + begin + error_status = `TRUE; + $display("ERROR:%0s, line %0d, Invalid INTEL HEX record.", in_file, line_no); + done = `TRUE; + end + end + $fclose(ifp); + $fclose(ofp); + end + `endif +`endif +end +endtask // convert_hex2ver + +endmodule // ALTERA_MF_MEMORY_INITIALIZATION + + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : ALTERA_DEVICE_FAMILIES +// +// Description : Common Altera device families comparison +// +// Limitation : +// +// Results expected: +// +//END_MODULE_NAME-------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module ALTERA_DEVICE_FAMILIES; + +function IS_FAMILY_ACEX1K; + input[8*20:1] device; + reg is_acex1k; +begin + if ((device == "ACEX1K") || (device == "acex1k") || (device == "ACEX 1K") || (device == "acex 1k")) + is_acex1k = 1; + else + is_acex1k = 0; + + IS_FAMILY_ACEX1K = is_acex1k; +end +endfunction //IS_FAMILY_ACEX1K + +function IS_FAMILY_APEX20K; + input[8*20:1] device; + reg is_apex20k; +begin + if ((device == "APEX20K") || (device == "apex20k") || (device == "APEX 20K") || (device == "apex 20k") || (device == "RAPHAEL") || (device == "raphael")) + is_apex20k = 1; + else + is_apex20k = 0; + + IS_FAMILY_APEX20K = is_apex20k; +end +endfunction //IS_FAMILY_APEX20K + +function IS_FAMILY_APEX20KC; + input[8*20:1] device; + reg is_apex20kc; +begin + if ((device == "APEX20KC") || (device == "apex20kc") || (device == "APEX 20KC") || (device == "apex 20kc")) + is_apex20kc = 1; + else + is_apex20kc = 0; + + IS_FAMILY_APEX20KC = is_apex20kc; +end +endfunction //IS_FAMILY_APEX20KC + +function IS_FAMILY_APEX20KE; + input[8*20:1] device; + reg is_apex20ke; +begin + if ((device == "APEX20KE") || (device == "apex20ke") || (device == "APEX 20KE") || (device == "apex 20ke")) + is_apex20ke = 1; + else + is_apex20ke = 0; + + IS_FAMILY_APEX20KE = is_apex20ke; +end +endfunction //IS_FAMILY_APEX20KE + +function IS_FAMILY_APEXII; + input[8*20:1] device; + reg is_apexii; +begin + if ((device == "APEX II") || (device == "apex ii") || (device == "APEXII") || (device == "apexii") || (device == "APEX 20KF") || (device == "apex 20kf") || (device == "APEX20KF") || (device == "apex20kf")) + is_apexii = 1; + else + is_apexii = 0; + + IS_FAMILY_APEXII = is_apexii; +end +endfunction //IS_FAMILY_APEXII + +function IS_FAMILY_EXCALIBUR_ARM; + input[8*20:1] device; + reg is_excalibur_arm; +begin + if ((device == "EXCALIBUR_ARM") || (device == "excalibur_arm") || (device == "Excalibur ARM") || (device == "EXCALIBUR ARM") || (device == "excalibur arm") || (device == "ARM-BASED EXCALIBUR") || (device == "arm-based excalibur") || (device == "ARM_BASED_EXCALIBUR") || (device == "arm_based_excalibur")) + is_excalibur_arm = 1; + else + is_excalibur_arm = 0; + + IS_FAMILY_EXCALIBUR_ARM = is_excalibur_arm; +end +endfunction //IS_FAMILY_EXCALIBUR_ARM + +function IS_FAMILY_FLEX10KE; + input[8*20:1] device; + reg is_flex10ke; +begin + if ((device == "FLEX10KE") || (device == "flex10ke") || (device == "FLEX 10KE") || (device == "flex 10ke")) + is_flex10ke = 1; + else + is_flex10ke = 0; + + IS_FAMILY_FLEX10KE = is_flex10ke; +end +endfunction //IS_FAMILY_FLEX10KE + +function IS_FAMILY_MERCURY; + input[8*20:1] device; + reg is_mercury; +begin + if ((device == "Mercury") || (device == "MERCURY") || (device == "mercury") || (device == "DALI") || (device == "dali")) + is_mercury = 1; + else + is_mercury = 0; + + IS_FAMILY_MERCURY = is_mercury; +end +endfunction //IS_FAMILY_MERCURY + +function IS_FAMILY_STRATIX; + input[8*20:1] device; + reg is_stratix; +begin + if ((device == "Stratix") || (device == "STRATIX") || (device == "stratix") || (device == "Yeager") || (device == "YEAGER") || (device == "yeager")) + is_stratix = 1; + else + is_stratix = 0; + + IS_FAMILY_STRATIX = is_stratix; +end +endfunction //IS_FAMILY_STRATIX + +function IS_FAMILY_STRATIXGX; + input[8*20:1] device; + reg is_stratixgx; +begin + if ((device == "Stratix GX") || (device == "STRATIX GX") || (device == "stratix gx") || (device == "Stratix-GX") || (device == "STRATIX-GX") || (device == "stratix-gx") || (device == "StratixGX") || (device == "STRATIXGX") || (device == "stratixgx") || (device == "Aurora") || (device == "AURORA") || (device == "aurora")) + is_stratixgx = 1; + else + is_stratixgx = 0; + + IS_FAMILY_STRATIXGX = is_stratixgx; +end +endfunction //IS_FAMILY_STRATIXGX + +function IS_FAMILY_CYCLONE; + input[8*20:1] device; + reg is_cyclone; +begin + if ((device == "Cyclone") || (device == "CYCLONE") || (device == "cyclone") || (device == "ACEX2K") || (device == "acex2k") || (device == "ACEX 2K") || (device == "acex 2k") || (device == "Tornado") || (device == "TORNADO") || (device == "tornado")) + is_cyclone = 1; + else + is_cyclone = 0; + + IS_FAMILY_CYCLONE = is_cyclone; +end +endfunction //IS_FAMILY_CYCLONE + +function IS_FAMILY_MAXII; + input[8*20:1] device; + reg is_maxii; +begin + if ((device == "MAX II") || (device == "max ii") || (device == "MAXII") || (device == "maxii") || (device == "Tsunami") || (device == "TSUNAMI") || (device == "tsunami")) + is_maxii = 1; + else + is_maxii = 0; + + IS_FAMILY_MAXII = is_maxii; +end +endfunction //IS_FAMILY_MAXII + +function IS_FAMILY_HARDCOPYSTRATIX; + input[8*20:1] device; + reg is_hardcopystratix; +begin + if ((device == "HardCopy Stratix") || (device == "HARDCOPY STRATIX") || (device == "hardcopy stratix") || (device == "Stratix HC") || (device == "STRATIX HC") || (device == "stratix hc") || (device == "StratixHC") || (device == "STRATIXHC") || (device == "stratixhc") || (device == "HardcopyStratix") || (device == "HARDCOPYSTRATIX") || (device == "hardcopystratix")) + is_hardcopystratix = 1; + else + is_hardcopystratix = 0; + + IS_FAMILY_HARDCOPYSTRATIX = is_hardcopystratix; +end +endfunction //IS_FAMILY_HARDCOPYSTRATIX + +function IS_FAMILY_STRATIXII; + input[8*20:1] device; + reg is_stratixii; +begin + if ((device == "Stratix II") || (device == "STRATIX II") || (device == "stratix ii") || (device == "StratixII") || (device == "STRATIXII") || (device == "stratixii") || (device == "Armstrong") || (device == "ARMSTRONG") || (device == "armstrong")) + is_stratixii = 1; + else + is_stratixii = 0; + + IS_FAMILY_STRATIXII = is_stratixii; +end +endfunction //IS_FAMILY_STRATIXII + +function IS_FAMILY_STRATIXIIGX; + input[8*20:1] device; + reg is_stratixiigx; +begin + if ((device == "Stratix II GX") || (device == "STRATIX II GX") || (device == "stratix ii gx") || (device == "StratixIIGX") || (device == "STRATIXIIGX") || (device == "stratixiigx")) + is_stratixiigx = 1; + else + is_stratixiigx = 0; + + IS_FAMILY_STRATIXIIGX = is_stratixiigx; +end +endfunction //IS_FAMILY_STRATIXIIGX + +function IS_FAMILY_CYCLONEII; + input[8*20:1] device; + reg is_cycloneii; +begin + if ((device == "Cyclone II") || (device == "CYCLONE II") || (device == "cyclone ii") || (device == "Cycloneii") || (device == "CYCLONEII") || (device == "cycloneii") || (device == "Magellan") || (device == "MAGELLAN") || (device == "magellan")) + is_cycloneii = 1; + else + is_cycloneii = 0; + + IS_FAMILY_CYCLONEII = is_cycloneii; +end +endfunction //IS_FAMILY_CYCLONEII + +function IS_FAMILY_HARDCOPYII; + input[8*20:1] device; + reg is_hardcopyii; +begin + if ((device == "HardCopy II") || (device == "HARDCOPY II") || (device == "hardcopy ii") || (device == "HardCopyII") || (device == "HARDCOPYII") || (device == "hardcopyii") || (device == "Fusion") || (device == "FUSION") || (device == "fusion")) + is_hardcopyii = 1; + else + is_hardcopyii = 0; + + IS_FAMILY_HARDCOPYII = is_hardcopyii; +end +endfunction //IS_FAMILY_HARDCOPYII + +function FEATURE_FAMILY_STRATIXGX; + input[8*20:1] device; + reg var_family_stratixgx; +begin + if (IS_FAMILY_STRATIXGX(device) ) + var_family_stratixgx = 1; + else + var_family_stratixgx = 0; + + FEATURE_FAMILY_STRATIXGX = var_family_stratixgx; +end +endfunction //FEATURE_FAMILY_STRATIXGX + +function FEATURE_FAMILY_CYCLONE; + input[8*20:1] device; + reg var_family_cyclone; +begin + if (IS_FAMILY_CYCLONE(device) ) + var_family_cyclone = 1; + else + var_family_cyclone = 0; + + FEATURE_FAMILY_CYCLONE = var_family_cyclone; +end +endfunction //FEATURE_FAMILY_CYCLONE + +function FEATURE_FAMILY_STRATIXII; + input[8*20:1] device; + reg var_family_stratixii; +begin + if (IS_FAMILY_STRATIXII(device) || IS_FAMILY_HARDCOPYII(device) || IS_FAMILY_STRATIXIIGX(device) ) + var_family_stratixii = 1; + else + var_family_stratixii = 0; + + FEATURE_FAMILY_STRATIXII = var_family_stratixii; +end +endfunction //FEATURE_FAMILY_STRATIXII + +function FEATURE_FAMILY_STRATIX_HC; + input[8*20:1] device; + reg var_family_stratix_hc; +begin + if (IS_FAMILY_HARDCOPYSTRATIX(device) ) + var_family_stratix_hc = 1; + else + var_family_stratix_hc = 0; + + FEATURE_FAMILY_STRATIX_HC = var_family_stratix_hc; +end +endfunction //FEATURE_FAMILY_STRATIX_HC + +function FEATURE_FAMILY_STRATIX; + input[8*20:1] device; + reg var_family_stratix; +begin + if (IS_FAMILY_STRATIX(device) || FEATURE_FAMILY_STRATIX_HC(device) || FEATURE_FAMILY_STRATIXGX(device) || FEATURE_FAMILY_CYCLONE(device) || FEATURE_FAMILY_STRATIXII(device) || FEATURE_FAMILY_MAXII(device) || FEATURE_FAMILY_CYCLONEII(device) ) + var_family_stratix = 1; + else + var_family_stratix = 0; + + FEATURE_FAMILY_STRATIX = var_family_stratix; +end +endfunction //FEATURE_FAMILY_STRATIX + +function FEATURE_FAMILY_MAXII; + input[8*20:1] device; + reg var_family_maxii; +begin + if (IS_FAMILY_MAXII(device) ) + var_family_maxii = 1; + else + var_family_maxii = 0; + + FEATURE_FAMILY_MAXII = var_family_maxii; +end +endfunction //FEATURE_FAMILY_MAXII + +function FEATURE_FAMILY_CYCLONEII; + input[8*20:1] device; + reg var_family_cycloneii; +begin + if (IS_FAMILY_CYCLONEII(device) ) + var_family_cycloneii = 1; + else + var_family_cycloneii = 0; + + FEATURE_FAMILY_CYCLONEII = var_family_cycloneii; +end +endfunction //FEATURE_FAMILY_CYCLONEII + +function FEATURE_FAMILY_HAS_MEGARAM; + input[8*20:1] device; + reg var_family_has_megaram; +begin + if (IS_FAMILY_STRATIX(device) || FEATURE_FAMILY_STRATIX_HC(device) || IS_FAMILY_STRATIXGX(device) || FEATURE_FAMILY_STRATIXII(device) ) + var_family_has_megaram = 1; + else + var_family_has_megaram = 0; + + FEATURE_FAMILY_HAS_MEGARAM = var_family_has_megaram; +end +endfunction //FEATURE_FAMILY_HAS_MEGARAM + +function FEATURE_FAMILY_HAS_M512; + input[8*20:1] device; + reg var_family_has_m512; +begin + if (IS_FAMILY_STRATIX(device) || FEATURE_FAMILY_STRATIX_HC(device) || IS_FAMILY_STRATIXGX(device) || IS_FAMILY_STRATIXII(device) || IS_FAMILY_STRATIXIIGX(device) ) + var_family_has_m512 = 1; + else + var_family_has_m512 = 0; + + FEATURE_FAMILY_HAS_M512 = var_family_has_m512; +end +endfunction //FEATURE_FAMILY_HAS_M512 + +function FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM; + input[8*20:1] device; + reg var_family_has_stratixii_style_ram; +begin + if (FEATURE_FAMILY_STRATIXII(device) || FEATURE_FAMILY_CYCLONEII(device) ) + var_family_has_stratixii_style_ram = 1; + else + var_family_has_stratixii_style_ram = 0; + + FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM = var_family_has_stratixii_style_ram; +end +endfunction //FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM + +function FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO; + input[8*20:1] device; + reg var_family_has_inverted_output_ddio; +begin + if (FEATURE_FAMILY_CYCLONEII(device) ) + var_family_has_inverted_output_ddio = 1; + else + var_family_has_inverted_output_ddio = 0; + + FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO = var_family_has_inverted_output_ddio; +end +endfunction //FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO + +function IS_VALID_FAMILY; + input[8*20:1] device; + reg is_valid; +begin + if (((device == "ACEX1K") || (device == "acex1k") || (device == "ACEX 1K") || (device == "acex 1k")) + || ((device == "APEX20K") || (device == "apex20k") || (device == "APEX 20K") || (device == "apex 20k") || (device == "RAPHAEL") || (device == "raphael")) + || ((device == "APEX20KC") || (device == "apex20kc") || (device == "APEX 20KC") || (device == "apex 20kc")) + || ((device == "APEX20KE") || (device == "apex20ke") || (device == "APEX 20KE") || (device == "apex 20ke")) + || ((device == "APEX II") || (device == "apex ii") || (device == "APEXII") || (device == "apexii") || (device == "APEX 20KF") || (device == "apex 20kf") || (device == "APEX20KF") || (device == "apex20kf")) + || ((device == "EXCALIBUR_ARM") || (device == "excalibur_arm") || (device == "Excalibur ARM") || (device == "EXCALIBUR ARM") || (device == "excalibur arm") || (device == "ARM-BASED EXCALIBUR") || (device == "arm-based excalibur") || (device == "ARM_BASED_EXCALIBUR") || (device == "arm_based_excalibur")) + || ((device == "FLEX10KE") || (device == "flex10ke") || (device == "FLEX 10KE") || (device == "flex 10ke")) + || ((device == "FLEX10K") || (device == "flex10k") || (device == "FLEX 10K") || (device == "flex 10k")) + || ((device == "FLEX10KA") || (device == "flex10ka") || (device == "FLEX 10KA") || (device == "flex 10ka")) + || ((device == "FLEX6000") || (device == "flex6000") || (device == "FLEX 6000") || (device == "flex 6000") || (device == "FLEX6K") || (device == "flex6k")) + || ((device == "MAX7000B") || (device == "max7000b") || (device == "MAX 7000B") || (device == "max 7000b")) + || ((device == "MAX7000AE") || (device == "max7000ae") || (device == "MAX 7000AE") || (device == "max 7000ae")) + || ((device == "MAX3000A") || (device == "max3000a") || (device == "MAX 3000A") || (device == "max 3000a")) + || ((device == "MAX7000S") || (device == "max7000s") || (device == "MAX 7000S") || (device == "max 7000s")) + || ((device == "MAX7000A") || (device == "max7000a") || (device == "MAX 7000A") || (device == "max 7000a")) + || ((device == "Mercury") || (device == "MERCURY") || (device == "mercury") || (device == "DALI") || (device == "dali")) + || ((device == "Stratix") || (device == "STRATIX") || (device == "stratix") || (device == "Yeager") || (device == "YEAGER") || (device == "yeager")) + || ((device == "Stratix GX") || (device == "STRATIX GX") || (device == "stratix gx") || (device == "Stratix-GX") || (device == "STRATIX-GX") || (device == "stratix-gx") || (device == "StratixGX") || (device == "STRATIXGX") || (device == "stratixgx") || (device == "Aurora") || (device == "AURORA") || (device == "aurora")) + || ((device == "Cyclone") || (device == "CYCLONE") || (device == "cyclone") || (device == "ACEX2K") || (device == "acex2k") || (device == "ACEX 2K") || (device == "acex 2k") || (device == "Tornado") || (device == "TORNADO") || (device == "tornado")) + || ((device == "MAX II") || (device == "max ii") || (device == "MAXII") || (device == "maxii") || (device == "Tsunami") || (device == "TSUNAMI") || (device == "tsunami")) + || ((device == "HardCopy Stratix") || (device == "HARDCOPY STRATIX") || (device == "hardcopy stratix") || (device == "Stratix HC") || (device == "STRATIX HC") || (device == "stratix hc") || (device == "StratixHC") || (device == "STRATIXHC") || (device == "stratixhc") || (device == "HardcopyStratix") || (device == "HARDCOPYSTRATIX") || (device == "hardcopystratix")) + || ((device == "Stratix II") || (device == "STRATIX II") || (device == "stratix ii") || (device == "StratixII") || (device == "STRATIXII") || (device == "stratixii") || (device == "Armstrong") || (device == "ARMSTRONG") || (device == "armstrong")) + || ((device == "Stratix II GX") || (device == "STRATIX II GX") || (device == "stratix ii gx") || (device == "StratixIIGX") || (device == "STRATIXIIGX") || (device == "stratixiigx")) + || ((device == "Cyclone II") || (device == "CYCLONE II") || (device == "cyclone ii") || (device == "Cycloneii") || (device == "CYCLONEII") || (device == "cycloneii") || (device == "Magellan") || (device == "MAGELLAN") || (device == "magellan")) + || ((device == "HardCopy II") || (device == "HARDCOPY II") || (device == "hardcopy ii") || (device == "HardCopyII") || (device == "HARDCOPYII") || (device == "hardcopyii") || (device == "Fusion") || (device == "FUSION") || (device == "fusion"))) + is_valid = 1; + else + is_valid = 0; + + IS_VALID_FAMILY = is_valid; +end +endfunction // IS_VALID_FAMILY + + +endmodule // ALTERA_DEVICE_FAMILIES + +/////////////////////////////////////////////////////////////////////////////// +// +// STRATIX_PLL and STRATIXII_PLL +// +/////////////////////////////////////////////////////////////////////////////// + +// DFFP +`timescale 1ps / 1ps +module dffp ( Q, CLK, ENA, D, CLRN, PRN ); + input D; + input CLK; + input CLRN; + input PRN; + input ENA; + output Q; + + + tri1 PRN, CLRN, ENA; + reg Q; + + always @ (posedge CLK or negedge CLRN or negedge PRN ) + if (PRN == 1'b0) Q = 1; + else if (CLRN == 1'b0) Q = 0; + else if ((CLK == 1) & (ENA == 1'b1)) Q = D; + endmodule + + +/////////////////////////////////////////////////////////////////////////////// +// +// Module Name : stx_m_cntr +// +// Description : Simulation model for the M counter. This is the +// loop feedback counter for the Stratix PLL. +// +/////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ps / 1 ps +module stx_m_cntr (clk, + reset, + cout, + initial_value, + modulus, + time_delay); + + // INPUT PORTS + input clk; + input reset; + input [31:0] initial_value; + input [31:0] modulus; + input [31:0] time_delay; + + // OUTPUT PORTS + output cout; + + // INTERNAL VARIABLES AND NETS + integer count; + reg tmp_cout; + reg first_rising_edge; + reg clk_last_value; + reg cout_tmp; + + initial + begin + count = 1; + first_rising_edge = 1; + clk_last_value = 0; + end + + always @(reset or clk) + begin + if (reset) + begin + count = 1; + tmp_cout = 0; + first_rising_edge = 1; + end + else begin + if (clk == 1 && clk_last_value !== clk && first_rising_edge) + begin + first_rising_edge = 0; + tmp_cout = clk; + end + else if (first_rising_edge == 0) + begin + if (count < modulus) + count = count + 1; + else + begin + count = 1; + tmp_cout = ~tmp_cout; + end + end + end + clk_last_value = clk; + + cout_tmp <= #(time_delay) tmp_cout; + end + + and (cout, cout_tmp, 1'b1); + +endmodule // stx_m_cntr + +/////////////////////////////////////////////////////////////////////////////// +// +// Module Name : stx_n_cntr +// +// Description : Simulation model for the N counter. This is the +// input clock divide counter for the Stratix PLL. +// +/////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ps / 1 ps +module stx_n_cntr (clk, + reset, + cout, + modulus, + time_delay); + + // INPUT PORTS + input clk; + input reset; + input [31:0] modulus; + input [31:0] time_delay; + + // OUTPUT PORTS + output cout; + + // INTERNAL VARIABLES AND NETS + integer count; + reg tmp_cout; + reg first_rising_edge; + reg clk_last_value; + reg clk_last_valid_value; + reg cout_tmp; + + initial + begin + count = 1; + first_rising_edge = 1; + clk_last_value = 0; + end + + always @(reset or clk) + begin + if (reset) + begin + count = 1; + tmp_cout = 0; + first_rising_edge = 1; + end + else begin + if (clk_last_value !== clk) + begin + if (clk === 1'bx) + begin + $display("Warning : Invalid transition to 'X' detected on Stratix PLL input clk. This edge will be ignored."); + $display("Time: %0t Instance: %m", $time); + end + else if ((clk === 1'b1) && first_rising_edge) + begin + first_rising_edge = 0; + tmp_cout = clk; + end + else if ((first_rising_edge == 0) && (clk_last_valid_value !== clk)) + begin + if (count < modulus) + count = count + 1; + else + begin + count = 1; + tmp_cout = ~tmp_cout; + end + end + end + end + clk_last_value = clk; + if (clk !== 1'bx) + clk_last_valid_value = clk; + + cout_tmp <= #(time_delay) tmp_cout; + end + + and (cout, cout_tmp, 1'b1); + +endmodule // stx_n_cntr + +/////////////////////////////////////////////////////////////////////////////// +// +// Module 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. +// +/////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ps / 1 ps +module stx_scale_cntr (clk, + reset, + cout, + high, + low, + initial_value, + mode, + time_delay, + ph_tap); + + // INPUT PORTS + input clk; + input reset; + input [31:0] high; + input [31:0] low; + input [31:0] initial_value; + input [8*6:1] mode; + input [31:0] time_delay; + input [31:0] ph_tap; + + // OUTPUT PORTS + output cout; + + // INTERNAL VARIABLES AND NETS + reg tmp_cout; + reg first_rising_edge; + reg clk_last_value; + reg init; + integer count; + integer output_shift_count; + reg cout_tmp; + reg [31:0] high_reg; + reg [31:0] low_reg; + reg high_cnt_xfer_done; + + initial + begin + count = 1; + first_rising_edge = 0; + tmp_cout = 0; + output_shift_count = 0; + high_cnt_xfer_done = 0; + end + + always @(clk or reset) + begin + if (init !== 1'b1) + begin + high_reg = high; + low_reg = low; + clk_last_value = 0; + init = 1'b1; + end + if (reset) + begin + count = 1; + output_shift_count = 0; + tmp_cout = 0; + first_rising_edge = 0; + end + else if (clk_last_value !== clk) + begin + if (mode == "off") + tmp_cout = 0; + else if (mode == "bypass") + tmp_cout = clk; + else if (first_rising_edge == 0) + begin + if (clk == 1) + begin + output_shift_count = output_shift_count + 1; + if (output_shift_count == initial_value) + begin + tmp_cout = clk; + first_rising_edge = 1; + end + end + end + else if (output_shift_count < initial_value) + begin + if (clk == 1) + output_shift_count = output_shift_count + 1; + end + else + begin + count = count + 1; + if (mode == "even" && (count == (high_reg*2) + 1)) + begin + tmp_cout = 0; + if (high_cnt_xfer_done === 1'b1) + begin + low_reg = low; + high_cnt_xfer_done = 0; + end + end + else if (mode == "odd" && (count == (high_reg*2))) + begin + tmp_cout = 0; + if (high_cnt_xfer_done === 1'b1) + begin + low_reg = low; + high_cnt_xfer_done = 0; + end + end + else if (count == (high_reg + low_reg)*2 + 1) + begin + tmp_cout = 1; + count = 1; // reset count + if (high_reg != high) + begin + high_reg = high; + high_cnt_xfer_done = 1; + end + end + end + end + clk_last_value = clk; + cout_tmp <= #(time_delay) tmp_cout; + end + + and (cout, cout_tmp, 1'b1); + +endmodule // stx_scale_cntr + +/////////////////////////////////////////////////////////////////////////////// +// +// Module 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. +// +/////////////////////////////////////////////////////////////////////////////// + +`timescale 1ps / 1ps +module MF_pll_reg (q, + clk, + ena, + d, + clrn, + prn); + + // INPUT PORTS + input d; + input clk; + input clrn; + input prn; + input ena; + + // OUTPUT PORTS + output q; + + // INTERNAL VARIABLES + reg q; + + // DEFAULT VALUES THRO' PULLUPs + tri1 prn, clrn, ena; + + initial q = 0; + + always @ (posedge clk or negedge clrn or negedge prn ) + begin + if (prn == 1'b0) + q <= 1; + else if (clrn == 1'b0) + q <= 0; + else if ((clk == 1) & (ena == 1'b1)) + q <= d; + end + +endmodule // MF_pll_reg + +////////////////////////////////////////////////////////////////////////////// +// +// Module 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. +// +////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ps/1 ps +`define WORD_LENGTH 18 + +module MF_stratix_pll (inclk, + fbin, + ena, + clkswitch, + areset, + pfdena, + clkena, + extclkena, + scanclk, + scanaclr, + scandata, + clk, + extclk, + clkbad, + activeclock, + locked, + clkloss, + scandataout, + // lvds mode specific ports + comparator, + enable0, + enable1); + + parameter operation_mode = "normal"; + parameter qualify_conf_done = "off"; + parameter compensate_clock = "clk0"; + parameter pll_type = "auto"; + parameter scan_chain = "long"; + + parameter clk0_multiply_by = 1; + parameter clk0_divide_by = 1; + parameter clk0_phase_shift = 0; + parameter clk0_time_delay = 0; + parameter clk0_duty_cycle = 50; + + parameter clk1_multiply_by = 1; + parameter clk1_divide_by = 1; + parameter clk1_phase_shift = 0; + parameter clk1_time_delay = 0; + parameter clk1_duty_cycle = 50; + + parameter clk2_multiply_by = 1; + parameter clk2_divide_by = 1; + parameter clk2_phase_shift = 0; + parameter clk2_time_delay = 0; + parameter clk2_duty_cycle = 50; + + parameter clk3_multiply_by = 1; + parameter clk3_divide_by = 1; + parameter clk3_phase_shift = 0; + parameter clk3_time_delay = 0; + parameter clk3_duty_cycle = 50; + + parameter clk4_multiply_by = 1; + parameter clk4_divide_by = 1; + parameter clk4_phase_shift = 0; + parameter clk4_time_delay = 0; + parameter clk4_duty_cycle = 50; + + parameter clk5_multiply_by = 1; + parameter clk5_divide_by = 1; + parameter clk5_phase_shift = 0; + parameter clk5_time_delay = 0; + parameter clk5_duty_cycle = 50; + + parameter extclk0_multiply_by = 1; + parameter extclk0_divide_by = 1; + parameter extclk0_phase_shift = 0; + parameter extclk0_time_delay = 0; + parameter extclk0_duty_cycle = 50; + + parameter extclk1_multiply_by = 1; + parameter extclk1_divide_by = 1; + parameter extclk1_phase_shift = 0; + parameter extclk1_time_delay = 0; + parameter extclk1_duty_cycle = 50; + + parameter extclk2_multiply_by = 1; + parameter extclk2_divide_by = 1; + parameter extclk2_phase_shift = 0; + parameter extclk2_time_delay = 0; + parameter extclk2_duty_cycle = 50; + + parameter extclk3_multiply_by = 1; + parameter extclk3_divide_by = 1; + parameter extclk3_phase_shift = 0; + parameter extclk3_time_delay = 0; + parameter extclk3_duty_cycle = 50; + + parameter primary_clock = "inclk0"; + parameter inclk0_input_frequency = 10000; + parameter inclk1_input_frequency = 10000; + parameter gate_lock_signal = "no"; + parameter gate_lock_counter = 1; + parameter valid_lock_multiplier = 5; + parameter invalid_lock_multiplier = 5; + + parameter switch_over_on_lossclk = "off"; + parameter switch_over_on_gated_lock = "off"; + parameter switch_over_counter = 1; + parameter enable_switch_over_counter = "off"; + parameter feedback_source = "e0"; + parameter bandwidth = 0; + parameter bandwidth_type = "auto"; + parameter down_spread = "0.0"; + parameter spread_frequency = 0; + parameter common_rx_tx = "off"; + parameter rx_outclock_resource = "auto"; + parameter use_vco_bypass = "false"; + parameter use_dc_coupling = "false"; + + parameter pfd_min = 0; + parameter pfd_max = 0; + parameter vco_min = 0; + parameter vco_max = 0; + parameter vco_center = 0; + + // ADVANCED USE PARAMETERS + parameter m_initial = 1; + parameter m = 1; + parameter n = 1; + parameter m2 = 1; + parameter n2 = 1; + parameter ss = 0; + + parameter l0_high = 1; + parameter l0_low = 1; + parameter l0_initial = 1; + parameter l0_mode = "bypass"; + parameter l0_ph = 0; + parameter l0_time_delay = 0; + + parameter l1_high = 1; + parameter l1_low = 1; + parameter l1_initial = 1; + parameter l1_mode = "bypass"; + parameter l1_ph = 0; + parameter l1_time_delay = 0; + + parameter g0_high = 1; + parameter g0_low = 1; + parameter g0_initial = 1; + parameter g0_mode = "bypass"; + parameter g0_ph = 0; + parameter g0_time_delay = 0; + + parameter g1_high = 1; + parameter g1_low = 1; + parameter g1_initial = 1; + parameter g1_mode = "bypass"; + parameter g1_ph = 0; + parameter g1_time_delay = 0; + + parameter g2_high = 1; + parameter g2_low = 1; + parameter g2_initial = 1; + parameter g2_mode = "bypass"; + parameter g2_ph = 0; + parameter g2_time_delay = 0; + + parameter g3_high = 1; + parameter g3_low = 1; + parameter g3_initial = 1; + parameter g3_mode = "bypass"; + parameter g3_ph = 0; + parameter g3_time_delay = 0; + + parameter e0_high = 1; + parameter e0_low = 1; + parameter e0_initial = 1; + parameter e0_mode = "bypass"; + parameter e0_ph = 0; + parameter e0_time_delay = 0; + + parameter e1_high = 1; + parameter e1_low = 1; + parameter e1_initial = 1; + parameter e1_mode = "bypass"; + parameter e1_ph = 0; + parameter e1_time_delay = 0; + + parameter e2_high = 1; + parameter e2_low = 1; + parameter e2_initial = 1; + parameter e2_mode = "bypass"; + parameter e2_ph = 0; + parameter e2_time_delay = 0; + + parameter e3_high = 1; + parameter e3_low = 1; + parameter e3_initial = 1; + parameter e3_mode = "bypass"; + parameter e3_ph = 0; + parameter e3_time_delay = 0; + + parameter m_ph = 0; + parameter m_time_delay = 0; + parameter n_time_delay = 0; + + parameter extclk0_counter = "e0"; + parameter extclk1_counter = "e1"; + parameter extclk2_counter = "e2"; + parameter extclk3_counter = "e3"; + + parameter clk0_counter = "g0"; + parameter clk1_counter = "g1"; + parameter clk2_counter = "g2"; + parameter clk3_counter = "g3"; + parameter clk4_counter = "l0"; + parameter clk5_counter = "l1"; + + // LVDS mode parameters + parameter enable0_counter = "l0"; + parameter enable1_counter = "l0"; + + parameter charge_pump_current = 0; + parameter loop_filter_r = "1.0"; + parameter loop_filter_c = 1; + + parameter pll_compensation_delay = 0; + parameter simulation_type = "timing"; + + //parameter for stratix lvds + parameter clk0_phase_shift_num = 0; + parameter clk1_phase_shift_num = 0; + parameter clk2_phase_shift_num = 0; + + parameter skip_vco = "off"; + + parameter clk0_use_even_counter_mode = "off"; + parameter clk1_use_even_counter_mode = "off"; + parameter clk2_use_even_counter_mode = "off"; + parameter clk3_use_even_counter_mode = "off"; + parameter clk4_use_even_counter_mode = "off"; + parameter clk5_use_even_counter_mode = "off"; + parameter extclk0_use_even_counter_mode = "off"; + parameter extclk1_use_even_counter_mode = "off"; + parameter extclk2_use_even_counter_mode = "off"; + parameter extclk3_use_even_counter_mode = "off"; + + parameter clk0_use_even_counter_value = "off"; + parameter clk1_use_even_counter_value = "off"; + parameter clk2_use_even_counter_value = "off"; + parameter clk3_use_even_counter_value = "off"; + parameter clk4_use_even_counter_value = "off"; + parameter clk5_use_even_counter_value = "off"; + parameter extclk0_use_even_counter_value = "off"; + parameter extclk1_use_even_counter_value = "off"; + parameter extclk2_use_even_counter_value = "off"; + parameter extclk3_use_even_counter_value = "off"; + + // INPUT PORTS + input [1:0] inclk; + input fbin; + input ena; + input clkswitch; + input areset; + input pfdena; + input [5:0] clkena; + input [3:0] extclkena; + input scanclk; + input scanaclr; + input scandata; + // lvds specific input ports + input comparator; + + // OUTPUT PORTS + output [5:0] clk; + output [3:0] extclk; + output [1:0] clkbad; + output activeclock; + output locked; + output clkloss; + output scandataout; + // lvds specific output ports + output enable0; + output enable1; + + // BUFFER INPUTS + wire inclk0_ipd; + wire inclk1_ipd; + wire ena_ipd; + wire fbin_ipd; + wire areset_ipd; + wire pfdena_ipd; + wire clkena0_ipd; + wire clkena1_ipd; + wire clkena2_ipd; + wire clkena3_ipd; + wire clkena4_ipd; + wire clkena5_ipd; + wire extclkena0_ipd; + wire extclkena1_ipd; + wire extclkena2_ipd; + wire extclkena3_ipd; + wire scanclk_ipd; + wire scanaclr_ipd; + wire scandata_ipd; + wire comparator_ipd; + wire clkswitch_ipd; + + buf (inclk0_ipd, inclk[0]); + buf (inclk1_ipd, inclk[1]); + buf (ena_ipd, ena); + buf (fbin_ipd, fbin); + buf (areset_ipd, areset); + buf (pfdena_ipd, pfdena); + buf (clkena0_ipd, clkena[0]); + buf (clkena1_ipd, clkena[1]); + buf (clkena2_ipd, clkena[2]); + buf (clkena3_ipd, clkena[3]); + buf (clkena4_ipd, clkena[4]); + buf (clkena5_ipd, clkena[5]); + buf (extclkena0_ipd, extclkena[0]); + buf (extclkena1_ipd, extclkena[1]); + buf (extclkena2_ipd, extclkena[2]); + buf (extclkena3_ipd, extclkena[3]); + buf (scanclk_ipd, scanclk); + buf (scanaclr_ipd, scanaclr); + buf (scandata_ipd, scandata); + buf (comparator_ipd, comparator); + buf (clkswitch_ipd, clkswitch); + + // INTERNAL VARIABLES AND NETS + integer scan_chain_length; + integer i; + integer j; + integer k; + integer l_index; + integer gate_count; + integer egpp_offset; + integer sched_time; + integer delay_chain; + integer low; + integer high; + integer initial_delay; + integer fbk_phase; + integer fbk_delay; + integer phase_shift[0:7]; + integer last_phase_shift[0:7]; + + integer m_times_vco_period; + integer new_m_times_vco_period; + integer refclk_period; + integer fbclk_period; + integer primary_clock_frequency; + integer high_time; + integer low_time; + integer my_rem; + integer tmp_rem; + integer rem; + integer tmp_vco_per; + integer vco_per; + integer offset; + integer temp_offset; + integer cycles_to_lock; + integer cycles_to_unlock; + integer l0_count; + integer l1_count; + integer loop_xplier; + integer loop_initial; + integer loop_ph; + integer loop_time_delay; + integer cycle_to_adjust; + integer total_pull_back; + integer pull_back_M; + integer pull_back_ext_cntr; + + time fbclk_time; + time first_fbclk_time; + time refclk_time; + time scanaclr_rising_time; + time scanaclr_falling_time; + + reg got_first_refclk; + reg got_second_refclk; + reg got_first_fbclk; + reg refclk_last_value; + reg fbclk_last_value; + reg inclk_last_value; + reg pll_is_locked; + reg pll_about_to_lock; + reg locked_tmp; + reg l0_got_first_rising_edge; + reg l1_got_first_rising_edge; + reg vco_l0_last_value; + reg vco_l1_last_value; + reg areset_ipd_last_value; + reg ena_ipd_last_value; + reg pfdena_ipd_last_value; + reg inclk_out_of_range; + reg schedule_vco_last_value; + + reg gate_out; + reg vco_val; + + reg [31:0] m_initial_val; + reg [31:0] m_val; + reg [31:0] m_val_tmp; + reg [31:0] m2_val; + reg [31:0] n_val; + reg [31:0] n_val_tmp; + reg [31:0] n2_val; + reg [31:0] m_time_delay_val; + reg [31:0] n_time_delay_val; + reg [31:0] m_delay; + reg [8*6:1] m_mode_val; + reg [8*6:1] m2_mode_val; + reg [8*6:1] n_mode_val; + reg [8*6:1] n2_mode_val; + reg [31:0] l0_high_val; + reg [31:0] l0_low_val; + reg [31:0] l0_initial_val; + reg [31:0] l0_time_delay_val; + reg [8*6:1] l0_mode_val; + reg [31:0] l1_high_val; + reg [31:0] l1_low_val; + reg [31:0] l1_initial_val; + reg [31:0] l1_time_delay_val; + reg [8*6:1] l1_mode_val; + + reg [31:0] g0_high_val; + reg [31:0] g0_low_val; + reg [31:0] g0_initial_val; + reg [31:0] g0_time_delay_val; + reg [8*6:1] g0_mode_val; + + reg [31:0] g1_high_val; + reg [31:0] g1_low_val; + reg [31:0] g1_initial_val; + reg [31:0] g1_time_delay_val; + reg [8*6:1] g1_mode_val; + + reg [31:0] g2_high_val; + reg [31:0] g2_low_val; + reg [31:0] g2_initial_val; + reg [31:0] g2_time_delay_val; + reg [8*6:1] g2_mode_val; + + reg [31:0] g3_high_val; + reg [31:0] g3_low_val; + reg [31:0] g3_initial_val; + reg [31:0] g3_time_delay_val; + reg [8*6:1] g3_mode_val; + + reg [31:0] e0_high_val; + reg [31:0] e0_low_val; + reg [31:0] e0_initial_val; + reg [31:0] e0_time_delay_val; + reg [8*6:1] e0_mode_val; + + reg [31:0] e1_high_val; + reg [31:0] e1_low_val; + reg [31:0] e1_initial_val; + reg [31:0] e1_time_delay_val; + reg [8*6:1] e1_mode_val; + + reg [31:0] e2_high_val; + reg [31:0] e2_low_val; + reg [31:0] e2_initial_val; + reg [31:0] e2_time_delay_val; + reg [8*6:1] e2_mode_val; + + reg [31:0] e3_high_val; + reg [31:0] e3_low_val; + reg [31:0] e3_initial_val; + reg [31:0] e3_time_delay_val; + reg [8*6:1] e3_mode_val; + + reg scanclk_last_value; + reg scanaclr_last_value; + reg transfer; + reg transfer_enable; + reg [288:0] scan_data; + reg schedule_vco; + reg schedule_offset; + reg stop_vco; + reg inclk_n; + + reg [7:0] vco_out; + wire inclk_l0; + wire inclk_l1; + wire inclk_m; + wire clk0_tmp; + wire clk1_tmp; + wire clk2_tmp; + wire clk3_tmp; + wire clk4_tmp; + wire clk5_tmp; + wire extclk0_tmp; + wire extclk1_tmp; + wire extclk2_tmp; + wire extclk3_tmp; + wire nce_l0; + wire nce_l1; + wire nce_temp; + + reg vco_l0; + reg vco_l1; + + wire clk0; + wire clk1; + wire clk2; + wire clk3; + wire clk4; + wire clk5; + wire extclk0; + wire extclk1; + wire extclk2; + wire extclk3; + wire ena0; + wire ena1; + wire ena2; + wire ena3; + wire ena4; + wire ena5; + wire extena0; + wire extena1; + wire extena2; + wire extena3; + wire refclk; + wire fbclk; + wire l0_clk; + wire l1_clk; + wire g0_clk; + wire g1_clk; + wire g2_clk; + wire g3_clk; + wire e0_clk; + wire e1_clk; + wire e2_clk; + wire e3_clk; + wire dffa_out; + wire dffb_out; + wire dffc_out; + wire dffd_out; + wire lvds_dffb_clk; + wire lvds_dffc_clk; + wire lvds_dffd_clk; + + reg first_schedule; + + wire enable0_tmp; + wire enable1_tmp; + wire enable_0; + wire enable_1; + reg l0_tmp; + reg l1_tmp; + + reg vco_period_was_phase_adjusted; + reg phase_adjust_was_scheduled; + + // for external feedback mode + + reg [31:0] ext_fbk_cntr_high; + reg [31:0] ext_fbk_cntr_low; + reg [31:0] ext_fbk_cntr_modulus; + reg [31:0] ext_fbk_cntr_delay; + reg [8*2:1] ext_fbk_cntr; + reg [8*6:1] ext_fbk_cntr_mode; + integer ext_fbk_cntr_ph; + integer ext_fbk_cntr_initial; + + wire inclk_e0; + wire inclk_e1; + wire inclk_e2; + wire inclk_e3; + wire [31:0] cntr_e0_initial; + wire [31:0] cntr_e1_initial; + wire [31:0] cntr_e2_initial; + wire [31:0] cntr_e3_initial; + wire [31:0] cntr_e0_delay; + wire [31:0] cntr_e1_delay; + wire [31:0] cntr_e2_delay; + wire [31:0] cntr_e3_delay; + reg [31:0] ext_fbk_delay; + + // variables for clk_switch + reg clk0_is_bad; + reg clk1_is_bad; + reg inclk0_last_value; + reg inclk1_last_value; + reg other_clock_value; + reg other_clock_last_value; + reg primary_clk_is_bad; + reg current_clk_is_bad; + reg external_switch; + reg [8*6:1] current_clock; + reg active_clock; + reg clkloss_tmp; + reg got_curr_clk_falling_edge_after_clkswitch; + reg active_clk_was_switched; + + integer clk0_count; + integer clk1_count; + integer switch_over_count; + + reg scandataout_tmp; + integer quiet_time; + reg pll_in_quiet_period; + time start_quiet_time; + reg quiet_period_violation; + reg reconfig_err; + reg scanclr_violation; + reg scanclr_clk_violation; + reg got_first_scanclk_after_scanclr_inactive_edge; + reg error; + + reg no_warn; + + // internal parameters + parameter EGPP_SCAN_CHAIN = 289; + parameter GPP_SCAN_CHAIN = 193; + parameter TRST = 5000; + parameter TRSTCLK = 5000; + + // internal variables for scaling of multiply_by and divide_by values + integer i_clk0_mult_by; + integer i_clk0_div_by; + integer i_clk1_mult_by; + integer i_clk1_div_by; + integer i_clk2_mult_by; + integer i_clk2_div_by; + integer i_clk3_mult_by; + integer i_clk3_div_by; + integer i_clk4_mult_by; + integer i_clk4_div_by; + integer i_clk5_mult_by; + integer i_clk5_div_by; + integer i_extclk0_mult_by; + integer i_extclk0_div_by; + integer i_extclk1_mult_by; + integer i_extclk1_div_by; + integer i_extclk2_mult_by; + integer i_extclk2_div_by; + integer i_extclk3_mult_by; + integer i_extclk3_div_by; + integer max_d_value; + integer new_multiplier; + + // internal variables for storing the phase shift number.(used in lvds mode only) + integer i_clk0_phase_shift; + integer i_clk1_phase_shift; + integer i_clk2_phase_shift; + + // user to advanced internal signals + + integer i_m_initial; + integer i_m; + integer i_n; + integer i_m2; + integer i_n2; + integer i_ss; + integer i_l0_high; + integer i_l1_high; + integer i_g0_high; + integer i_g1_high; + integer i_g2_high; + integer i_g3_high; + integer i_e0_high; + integer i_e1_high; + integer i_e2_high; + integer i_e3_high; + integer i_l0_low; + integer i_l1_low; + integer i_g0_low; + integer i_g1_low; + integer i_g2_low; + integer i_g3_low; + integer i_e0_low; + integer i_e1_low; + integer i_e2_low; + integer i_e3_low; + integer i_l0_initial; + integer i_l1_initial; + integer i_g0_initial; + integer i_g1_initial; + integer i_g2_initial; + integer i_g3_initial; + integer i_e0_initial; + integer i_e1_initial; + integer i_e2_initial; + integer i_e3_initial; + reg [8*6:1] i_l0_mode; + reg [8*6:1] i_l1_mode; + reg [8*6:1] i_g0_mode; + reg [8*6:1] i_g1_mode; + reg [8*6:1] i_g2_mode; + reg [8*6:1] i_g3_mode; + reg [8*6:1] i_e0_mode; + reg [8*6:1] i_e1_mode; + reg [8*6:1] i_e2_mode; + reg [8*6:1] i_e3_mode; + integer i_vco_min; + integer i_vco_max; + integer i_vco_center; + integer i_pfd_min; + integer i_pfd_max; + integer i_l0_ph; + integer i_l1_ph; + integer i_g0_ph; + integer i_g1_ph; + integer i_g2_ph; + integer i_g3_ph; + integer i_e0_ph; + integer i_e1_ph; + integer i_e2_ph; + integer i_e3_ph; + integer i_m_ph; + integer m_ph_val; + integer i_l0_time_delay; + integer i_l1_time_delay; + integer i_g0_time_delay; + integer i_g1_time_delay; + integer i_g2_time_delay; + integer i_g3_time_delay; + integer i_e0_time_delay; + integer i_e1_time_delay; + integer i_e2_time_delay; + integer i_e3_time_delay; + integer i_m_time_delay; + integer i_n_time_delay; + integer i_extclk3_counter; + integer i_extclk2_counter; + integer i_extclk1_counter; + integer i_extclk0_counter; + integer i_clk5_counter; + integer i_clk4_counter; + integer i_clk3_counter; + integer i_clk2_counter; + integer i_clk1_counter; + integer i_clk0_counter; + integer i_charge_pump_current; + integer i_loop_filter_r; + integer max_neg_abs; + integer output_count; + integer new_divisor; + + // uppercase to lowercase parameter values + reg [8*`WORD_LENGTH:1] l_operation_mode; + reg [8*`WORD_LENGTH:1] l_pll_type; + reg [8*`WORD_LENGTH:1] l_qualify_conf_done; + reg [8*`WORD_LENGTH:1] l_compensate_clock; + reg [8*`WORD_LENGTH:1] l_scan_chain; + reg [8*`WORD_LENGTH:1] l_primary_clock; + reg [8*`WORD_LENGTH:1] l_gate_lock_signal; + reg [8*`WORD_LENGTH:1] l_switch_over_on_lossclk; + reg [8*`WORD_LENGTH:1] l_switch_over_on_gated_lock; + reg [8*`WORD_LENGTH:1] l_enable_switch_over_counter; + reg [8*`WORD_LENGTH:1] l_feedback_source; + reg [8*`WORD_LENGTH:1] l_bandwidth_type; + reg [8*`WORD_LENGTH:1] l_simulation_type; + reg [8*`WORD_LENGTH:1] l_enable0_counter; + reg [8*`WORD_LENGTH:1] l_enable1_counter; + + reg init; + + specify + endspecify + + // finds the closest integer fraction of a given pair of numerator and denominator. + task find_simple_integer_fraction; + input numerator; + input denominator; + input max_denom; + output fraction_num; + output fraction_div; + parameter max_iter = 20; + + integer numerator; + integer denominator; + integer max_denom; + integer fraction_num; + integer fraction_div; + + integer quotient_array[max_iter-1:0]; + integer int_loop_iter; + integer int_quot; + integer m_value; + integer d_value; + integer old_m_value; + integer swap; + + integer loop_iter; + integer num; + integer den; + integer i_max_iter; + + begin + loop_iter = 0; + num = numerator; + den = denominator; + i_max_iter = max_iter; + + while (loop_iter < i_max_iter) + begin + int_quot = num / den; + quotient_array[loop_iter] = int_quot; + num = num - (den*int_quot); + loop_iter=loop_iter+1; + + if ((num == 0) || (max_denom != -1) || (loop_iter == i_max_iter)) + begin + // 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) + begin + m_value = (2*num/den); + end + // calculate the fraction numerator and denominator at this stage + for (int_loop_iter = loop_iter-1; int_loop_iter >= 0; int_loop_iter=int_loop_iter-1) + begin + if (m_value == 0) + begin + m_value = quotient_array[int_loop_iter]; + d_value = 1; + end + else + begin + old_m_value = m_value; + m_value = quotient_array[int_loop_iter]*m_value + d_value; + d_value = old_m_value; + end + end + // if the denominator is less than the maximum denom_value or if there is no restriction save it + if ((d_value <= max_denom) || (max_denom == -1)) + begin + fraction_num = m_value; + fraction_div = d_value; + end + // end the loop if the denomitor has overflown or the numerator is zero (no remainder during this round) + if (((d_value > max_denom) && (max_denom != -1)) || (num == 0)) + begin + i_max_iter = loop_iter; + end + end + // swap the numerator and denominator for the next round + swap = den; + den = num; + num = swap; + end + end + endtask // find_simple_integer_fraction + +// get the absolute value + function integer abs; + input value; + integer value; + begin + if (value < 0) + abs = value * -1; + else abs = value; + end + endfunction + + // find twice the period of the slowest clock + function integer slowest_clk; + input L0, L1, G0, G1, G2, G3, E0, E1, E2, E3, scan_chain, refclk, m_mod; + integer L0, L1, G0, G1, G2, G3, E0, E1, E2, E3; + reg [8*5:1] scan_chain; + integer refclk; + reg [31:0] m_mod; + integer max_modulus; + begin + if (L0 > L1) + max_modulus = L0; + else + max_modulus = L1; + if (G0 > max_modulus) + max_modulus = G0; + if (G1 > max_modulus) + max_modulus = G1; + if (G2 > max_modulus) + max_modulus = G2; + if (G3 > max_modulus) + max_modulus = G3; + if (scan_chain == "long") + begin + if (E0 > max_modulus) + max_modulus = E0; + if (E1 > max_modulus) + max_modulus = E1; + if (E2 > max_modulus) + max_modulus = E2; + if (E3 > max_modulus) + max_modulus = E3; + end + + slowest_clk = ((refclk/m_mod) * max_modulus *2); + end + endfunction + + // count the number of digits in the given integer + function integer count_digit; + input X; + integer X; + integer count, result; + begin + count = 0; + result = X; + while (result != 0) + begin + result = (result / 10); + count = count + 1; + end + + count_digit = count; + end + endfunction + + // reduce the given huge number(X) to Y significant digits + function integer scale_num; + input X, Y; + integer X, Y; + integer count; + integer fac_ten, lc; + begin + fac_ten = 1; + count = count_digit(X); + + for (lc = 0; lc < (count-Y); lc = lc + 1) + fac_ten = fac_ten * 10; + + scale_num = (X / fac_ten); + end + endfunction + + // find the greatest common denominator of X and Y + function integer gcd; + input X,Y; + integer X,Y; + integer L, S, R, G; + begin + if (X < Y) // find which is smaller. + begin + S = X; + L = Y; + end + else + begin + S = Y; + L = X; + end + + R = S; + while ( R > 1) + begin + S = L; + L = R; + R = S % L; // divide bigger number by smaller. + // remainder becomes smaller number. + end + if (R == 0) // if evenly divisible then L is gcd else it is 1. + G = L; + else + G = R; + gcd = G; + end + endfunction + + // find the least common multiple of A1 to A10 + function integer lcm; + input A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P; + integer A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P; + integer M1, M2, M3, M4, M5 , M6, M7, M8, M9, R; + 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) + R = 10; + else if ((M9 <= 10) && (M9 >= 3)) + R = 4 * M9; + else if (M9 > 1000) + R = scale_num(M9,3); + else + R = M9; + lcm = R; + end + endfunction + + // find the factor of division of the output clock frequency + // compared to the VCO + function integer output_counter_value; + input clk_divide, clk_mult, M, N; + integer clk_divide, clk_mult, M, N; + integer R; + begin + R = (clk_divide * M)/(clk_mult * N); + output_counter_value = R; + end + endfunction + + // find the mode of each of the PLL counters - bypass, even or odd + function [8*6:1] counter_mode; + input duty_cycle; + input output_counter_value; + integer duty_cycle; + integer output_counter_value; + integer half_cycle_high; + reg [8*6:1] R; + begin + half_cycle_high = (2*duty_cycle*output_counter_value)/100; + if (output_counter_value == 1) + R = "bypass"; + else if ((half_cycle_high % 2) == 0) + R = "even"; + else + R = "odd"; + counter_mode = R; + end + endfunction + + // find the number of VCO clock cycles to hold the output clock high + function integer counter_high; + input output_counter_value, duty_cycle; + integer output_counter_value, duty_cycle; + integer half_cycle_high; + integer tmp_counter_high; + integer mode; + begin + half_cycle_high = (2*duty_cycle*output_counter_value)/100; + mode = ((half_cycle_high % 2) == 0); + tmp_counter_high = half_cycle_high/2; + counter_high = tmp_counter_high + !mode; + end + endfunction + + // find the number of VCO clock cycles to hold the output clock low + function integer counter_low; + input output_counter_value, duty_cycle; + integer output_counter_value, duty_cycle, counter_h; + integer half_cycle_high; + integer mode; + integer tmp_counter_high; + begin + half_cycle_high = (2*duty_cycle*output_counter_value)/100; + mode = ((half_cycle_high % 2) == 0); + tmp_counter_high = half_cycle_high/2; + counter_h = tmp_counter_high + !mode; + counter_low = output_counter_value - counter_h; + end + endfunction + + // find the smallest time delay amongst t1 to t10 + function integer mintimedelay; + input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; + integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; + integer m1,m2,m3,m4,m5,m6,m7,m8,m9; + begin + if (t1 < t2) + m1 = t1; + else + m1 = t2; + if (m1 < t3) + m2 = m1; + else + m2 = t3; + if (m2 < t4) + m3 = m2; + else + m3 = t4; + if (m3 < t5) + m4 = m3; + else + m4 = t5; + if (m4 < t6) + m5 = m4; + else + m5 = t6; + if (m5 < t7) + m6 = m5; + else + m6 = t7; + if (m6 < t8) + m7 = m6; + else + m7 = t8; + if (m7 < t9) + m8 = m7; + else + m8 = t9; + if (m8 < t10) + m9 = m8; + else + m9 = t10; + if (m9 > 0) + mintimedelay = m9; + else + mintimedelay = 0; + end + endfunction + + // find the numerically largest negative number, and return its absolute value + function integer maxnegabs; + input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; + integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; + integer m1,m2,m3,m4,m5,m6,m7,m8,m9; + begin + if (t1 < t2) m1 = t1; else m1 = t2; + if (m1 < t3) m2 = m1; else m2 = t3; + if (m2 < t4) m3 = m2; else m3 = t4; + if (m3 < t5) m4 = m3; else m4 = t5; + if (m4 < t6) m5 = m4; else m5 = t6; + if (m5 < t7) m6 = m5; else m6 = t7; + if (m6 < t8) m7 = m6; else m7 = t8; + if (m7 < t9) m8 = m7; else m8 = t9; + if (m8 < t10) m9 = m8; else m9 = t10; + maxnegabs = (m9 < 0) ? 0 - m9 : 0; + end + endfunction + + // adjust the given tap_phase by adding the largest negative number (ph_base) + function integer ph_adjust; + input tap_phase, ph_base; + integer tap_phase, ph_base; + begin + ph_adjust = tap_phase + ph_base; + end + endfunction + + // find the actual time delay for each PLL counter + function integer counter_time_delay; + input clk_time_delay, m_time_delay, n_time_delay; + integer clk_time_delay, m_time_delay, n_time_delay; + begin + counter_time_delay = clk_time_delay + m_time_delay - n_time_delay; + end + endfunction + + // find the number of VCO clock cycles to wait initially before the first + // rising edge of the output clock + function integer counter_initial; + input tap_phase, m, n; + integer tap_phase, m, n, phase; + begin + if (tap_phase < 0) tap_phase = 0 - tap_phase; + // adding 0.5 for rounding correction (required in order to round + // to the nearest integer instead of truncating) + phase = ((tap_phase * m) / (360 * n)) + 0.5; + counter_initial = phase; + end + endfunction + + // find which VCO phase tap to align the rising edge of the output clock to + function integer counter_ph; + input tap_phase; + input m,n; + integer m,n, phase; + integer tap_phase; + begin + // adding 0.5 for rounding correction + phase = (tap_phase * m / n) + 0.5; + counter_ph = (phase % 360)/45; + end + endfunction + + // convert the given string to length 6 by padding with spaces + function [8*6:1] translate_string; + input mode; + reg [8*6:1] new_mode; + begin + if (mode == "bypass") + new_mode = "bypass"; + else if (mode == "even") + new_mode = " even"; + else if (mode == "odd") + new_mode = " odd"; + + translate_string = new_mode; + end + endfunction + + // convert string to integer with sign + function integer str2int; + input [8*16:1] s; + + reg [8*16:1] reg_s; + reg [8:1] digit; + reg [8:1] tmp; + integer m, magnitude; + integer sign; + + begin + sign = 1; + magnitude = 0; + reg_s = s; + for (m=1; m<=16; m=m+1) + begin + tmp = reg_s[128:121]; + digit = tmp & 8'b00001111; + reg_s = reg_s << 8; + // Accumulate ascii digits 0-9 only. + if ((tmp>=48) && (tmp<=57)) + magnitude = (magnitude * 10) + digit; + if (tmp == 45) + sign = -1; // Found a '-' character, i.e. number is negative. + end + str2int = sign*magnitude; + end + endfunction + + // this is for stratix lvds only + // convert phase delay to integer + function integer get_int_phase_shift; + input [8*16:1] s; + input i_phase_shift; + integer i_phase_shift; + + begin + if (i_phase_shift != 0) + begin + get_int_phase_shift = i_phase_shift; + end + else + begin + get_int_phase_shift = str2int(s); + end + end + endfunction + + // calculate the given phase shift (in ps) in terms of degrees + function integer get_phase_degree; + input phase_shift; + integer phase_shift, result; + begin + result = (phase_shift * 360) / inclk0_input_frequency; + // this is to round up the calculation result + if ( result > 0 ) + result = result + 1; + else if ( result < 0 ) + result = result - 1; + else + result = 0; + + // assign the rounded up result + get_phase_degree = result; + end + endfunction + + // convert uppercase parameter values to lowercase + // assumes that the maximum character length of a parameter is 18 + function [8*`WORD_LENGTH:1] alpha_tolower; + input [8*`WORD_LENGTH:1] given_string; + + reg [8*`WORD_LENGTH:1] return_string; + reg [8*`WORD_LENGTH:1] reg_string; + reg [8:1] tmp; + reg [8:1] conv_char; + integer byte_count; + begin + return_string = " "; // initialise strings to spaces + conv_char = " "; + reg_string = given_string; + for (byte_count = `WORD_LENGTH; byte_count >= 1; byte_count = byte_count - 1) + begin + tmp = reg_string[8*`WORD_LENGTH:(8*(`WORD_LENGTH-1)+1)]; + reg_string = reg_string << 8; + if ((tmp >= 65) && (tmp <= 90)) // ASCII number of 'A' is 65, 'Z' is 90 + begin + conv_char = tmp + 32; // 32 is the difference in the position of 'A' and 'a' in the ASCII char set + return_string = {return_string, conv_char}; + end + else + return_string = {return_string, tmp}; + end + + alpha_tolower = return_string; + end + endfunction + + initial + begin + // convert string parameter values from uppercase to lowercase, + // as expected in this model + l_operation_mode = alpha_tolower(operation_mode); + l_pll_type = alpha_tolower(pll_type); + l_qualify_conf_done = alpha_tolower(qualify_conf_done); + l_compensate_clock = alpha_tolower(compensate_clock); + l_scan_chain = alpha_tolower(scan_chain); + l_primary_clock = alpha_tolower(primary_clock); + l_gate_lock_signal = alpha_tolower(gate_lock_signal); + l_switch_over_on_lossclk = alpha_tolower(switch_over_on_lossclk); + l_switch_over_on_gated_lock = alpha_tolower(switch_over_on_gated_lock); + l_enable_switch_over_counter = alpha_tolower(enable_switch_over_counter); + l_feedback_source = alpha_tolower(feedback_source); + l_bandwidth_type = alpha_tolower(bandwidth_type); + l_simulation_type = alpha_tolower(simulation_type); + l_enable0_counter = alpha_tolower(enable0_counter); + l_enable1_counter = alpha_tolower(enable1_counter); + + if (m == 0) + begin + // 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); + + // convert user parameters to advanced + i_n = 1; + if (l_pll_type == "lvds") + 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); + 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 (l_pll_type == "lvds") + 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); + + + 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 (l_pll_type == "lvds") + begin + i_l0_high = i_g0_high; + i_l1_high = i_g0_high; + end + else + begin + 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 + 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 (l_pll_type == "lvds") + 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); + 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 (l_pll_type == "lvds") + begin + i_l0_low = i_g0_low; + i_l1_low = i_g0_low; + end + else + begin + 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 + 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); + + if (l_pll_type == "flvds") + begin + // 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 = (clk0_phase_shift_num * new_multiplier); + i_clk1_phase_shift = (clk1_phase_shift_num * new_multiplier); + i_clk2_phase_shift = (clk2_phase_shift_num * new_multiplier); + end + else + begin + i_clk0_phase_shift = get_int_phase_shift(clk0_phase_shift, clk0_phase_shift_num); + i_clk1_phase_shift = get_int_phase_shift(clk1_phase_shift, clk1_phase_shift_num); + i_clk2_phase_shift = get_int_phase_shift(clk2_phase_shift, clk2_phase_shift_num); + end + + 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)); + if (l_pll_type == "lvds") + i_g0_initial = counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n); + else + i_g0_initial = counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n); + + i_g1_initial = counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n); + i_g2_initial = counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n); + i_g3_initial = counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs)), i_m, i_n); + if (l_pll_type == "lvds") + begin + i_l0_initial = i_g0_initial; + i_l1_initial = i_g0_initial; + end + else + begin + i_l0_initial = counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs)), i_m, i_n); + i_l1_initial = counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs)), i_m, i_n); + end + i_e0_initial = counter_initial(get_phase_degree(ph_adjust(str2int(extclk0_phase_shift), max_neg_abs)), i_m, i_n); + i_e1_initial = counter_initial(get_phase_degree(ph_adjust(str2int(extclk1_phase_shift), max_neg_abs)), i_m, i_n); + i_e2_initial = counter_initial(get_phase_degree(ph_adjust(str2int(extclk2_phase_shift), max_neg_abs)), i_m, i_n); + i_e3_initial = counter_initial(get_phase_degree(ph_adjust(str2int(extclk3_phase_shift), max_neg_abs)), i_m, i_n); + if (l_pll_type == "lvds") + 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)); + 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 (l_pll_type == "lvds") + begin + i_l0_mode = "bypass"; + i_l1_mode = "bypass"; + end + else + begin + 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 + 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)); + i_m_ph = counter_ph(get_phase_degree(max_neg_abs), i_m, i_n); + i_m_initial = counter_initial(get_phase_degree(max_neg_abs), i_m, i_n); + if (l_pll_type == "lvds") + i_g0_ph = counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n); + else + i_g0_ph = counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n); + + i_g1_ph = counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n); + i_g2_ph = counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n); + i_g3_ph = counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs)), i_m, i_n); + if (l_pll_type == "lvds") + begin + i_l0_ph = i_g0_ph; + i_l1_ph = i_g0_ph; + end + else + begin + i_l0_ph = counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs)), i_m, i_n); + i_l1_ph = counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs)), i_m, i_n); + end + i_e0_ph = counter_ph(get_phase_degree(ph_adjust(str2int(extclk0_phase_shift),max_neg_abs)), i_m, i_n); + i_e1_ph = counter_ph(get_phase_degree(ph_adjust(str2int(extclk1_phase_shift),max_neg_abs)), i_m, i_n); + i_e2_ph = counter_ph(get_phase_degree(ph_adjust(str2int(extclk2_phase_shift),max_neg_abs)), i_m, i_n); + i_e3_ph = counter_ph(get_phase_degree(ph_adjust(str2int(extclk3_phase_shift),max_neg_abs)), i_m, i_n); + + if (l_pll_type == "lvds") + 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); + 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 (l_pll_type == "lvds") + begin + i_l0_time_delay = i_g0_time_delay; + i_l1_time_delay = i_g0_time_delay; + end + else + begin + 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 + 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); + i_extclk3_counter = "e3" ; + i_extclk2_counter = "e2" ; + i_extclk1_counter = "e1" ; + i_extclk0_counter = "e0" ; + i_clk5_counter = "l1" ; + i_clk4_counter = "l0" ; + i_clk3_counter = "g3" ; + i_clk2_counter = "g2" ; + i_clk1_counter = "g1" ; + + if (l_pll_type == "lvds") + begin + l_enable0_counter = "l0"; + l_enable1_counter = "l1"; + i_clk0_counter = "l0" ; + end + else + i_clk0_counter = "g0" ; + + // in external feedback mode, need to adjust M value to take + // into consideration the external feedback counter value + if (l_operation_mode == "external_feedback") + begin + // if there is a negative phase shift, m_initial can only be 1 + if (max_neg_abs > 0) + i_m_initial = 1; + + if (l_feedback_source == "extclk0") + begin + if (i_e0_mode == "bypass") + output_count = 1; + else + output_count = i_e0_high + i_e0_low; + end + else if (l_feedback_source == "extclk1") + begin + if (i_e1_mode == "bypass") + output_count = 1; + else + output_count = i_e1_high + i_e1_low; + end + else if (l_feedback_source == "extclk2") + begin + if (i_e2_mode == "bypass") + output_count = 1; + else + output_count = i_e2_high + i_e2_low; + end + else if (l_feedback_source == "extclk3") + begin + if (i_e3_mode == "bypass") + output_count = 1; + else + output_count = i_e3_high + i_e3_low; + end + else // default to e0 + begin + if (i_e0_mode == "bypass") + output_count = 1; + else + output_count = i_e0_high + i_e0_low; + end + + if (i_m > output_count) + i_m = i_m / output_count; + else + begin + new_divisor = gcd(i_m, output_count); + i_m = i_m / new_divisor; + i_n = output_count / new_divisor; + end + end + + end + else + begin // m != 0 + + i_n = n; + i_m = m; + 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 = alpha_tolower(l0_mode); + i_l1_mode = alpha_tolower(l1_mode); + i_g0_mode = alpha_tolower(g0_mode); + i_g1_mode = alpha_tolower(g1_mode); + i_g2_mode = alpha_tolower(g2_mode); + i_g3_mode = alpha_tolower(g3_mode); + i_e0_mode = alpha_tolower(e0_mode); + i_e1_mode = alpha_tolower(e1_mode); + i_e2_mode = alpha_tolower(e2_mode); + i_e3_mode = alpha_tolower(e3_mode); + 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_m_ph = m_ph; // default + i_m_initial = m_initial; + 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_time_delay = m_time_delay; + i_n_time_delay = n_time_delay; + i_extclk3_counter = alpha_tolower(extclk3_counter); + i_extclk2_counter = alpha_tolower(extclk2_counter); + i_extclk1_counter = alpha_tolower(extclk1_counter); + i_extclk0_counter = alpha_tolower(extclk0_counter); + i_clk5_counter = alpha_tolower(clk5_counter); + i_clk4_counter = alpha_tolower(clk4_counter); + i_clk3_counter = alpha_tolower(clk3_counter); + i_clk2_counter = alpha_tolower(clk2_counter); + i_clk1_counter = alpha_tolower(clk1_counter); + i_clk0_counter = alpha_tolower(clk0_counter); + + end // user to advanced conversion + + // set the scan_chain length + if (l_scan_chain == "long") + scan_chain_length = EGPP_SCAN_CHAIN; + else if (l_scan_chain == "short") + scan_chain_length = GPP_SCAN_CHAIN; + + if (l_primary_clock == "inclk0") + begin + refclk_period = inclk0_input_frequency * i_n; + primary_clock_frequency = inclk0_input_frequency; + end + else if (l_primary_clock == "inclk1") + begin + refclk_period = inclk1_input_frequency * i_n; + primary_clock_frequency = inclk1_input_frequency; + end + + m_times_vco_period = refclk_period; + new_m_times_vco_period = refclk_period; + + fbclk_period = 0; + high_time = 0; + low_time = 0; + schedule_vco = 0; + schedule_offset = 1; + vco_out[7:0] = 8'b0; + fbclk_last_value = 0; + offset = 0; + temp_offset = 0; + got_first_refclk = 0; + got_first_fbclk = 0; + fbclk_time = 0; + first_fbclk_time = 0; + refclk_time = 0; + first_schedule = 1; + sched_time = 0; + vco_val = 0; + l0_got_first_rising_edge = 0; + l1_got_first_rising_edge = 0; + vco_l0_last_value = 0; + l0_count = 1; + l1_count = 1; + l0_tmp = 0; + l1_tmp = 0; + gate_count = 0; + gate_out = 0; + initial_delay = 0; + fbk_phase = 0; + for (i = 0; i <= 7; i = i + 1) + begin + phase_shift[i] = 0; + last_phase_shift[i] = 0; + end + fbk_delay = 0; + inclk_n = 0; + cycle_to_adjust = 0; + m_delay = 0; + vco_l0 = 0; + vco_l1 = 0; + total_pull_back = 0; + pull_back_M = 0; + pull_back_ext_cntr = 0; + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 0; + ena_ipd_last_value = 0; + inclk_out_of_range = 0; + scandataout_tmp = 0; + schedule_vco_last_value = 0; + + // set initial values for counter parameters + m_initial_val = i_m_initial; + m_val = i_m; + m_time_delay_val = i_m_time_delay; + n_val = i_n; + n_time_delay_val = i_n_time_delay; + m_ph_val = i_m_ph; + + m2_val = m2; + n2_val = n2; + + if (m_val == 1) + m_mode_val = "bypass"; + if (m2_val == 1) + m2_mode_val = "bypass"; + if (n_val == 1) + n_mode_val = "bypass"; + if (n2_val == 1) + n2_mode_val = "bypass"; + + if (skip_vco == "on") + begin + m_val = 1; + m_initial_val = 1; + m_time_delay_val = 0; + m_ph_val = 0; + end + + l0_high_val = i_l0_high; + l0_low_val = i_l0_low; + l0_initial_val = i_l0_initial; + l0_mode_val = i_l0_mode; + l0_time_delay_val = i_l0_time_delay; + + l1_high_val = i_l1_high; + l1_low_val = i_l1_low; + l1_initial_val = i_l1_initial; + l1_mode_val = i_l1_mode; + l1_time_delay_val = i_l1_time_delay; + + g0_high_val = i_g0_high; + g0_low_val = i_g0_low; + g0_initial_val = i_g0_initial; + g0_mode_val = i_g0_mode; + g0_time_delay_val = i_g0_time_delay; + + g1_high_val = i_g1_high; + g1_low_val = i_g1_low; + g1_initial_val = i_g1_initial; + g1_mode_val = i_g1_mode; + g1_time_delay_val = i_g1_time_delay; + + g2_high_val = i_g2_high; + g2_low_val = i_g2_low; + g2_initial_val = i_g2_initial; + g2_mode_val = i_g2_mode; + g2_time_delay_val = i_g2_time_delay; + + g3_high_val = i_g3_high; + g3_low_val = i_g3_low; + g3_initial_val = i_g3_initial; + g3_mode_val = i_g3_mode; + g3_time_delay_val = i_g3_time_delay; + + e0_high_val = i_e0_high; + e0_low_val = i_e0_low; + e0_initial_val = i_e0_initial; + e0_mode_val = i_e0_mode; + e0_time_delay_val = i_e0_time_delay; + + e1_high_val = i_e1_high; + e1_low_val = i_e1_low; + e1_initial_val = i_e1_initial; + e1_mode_val = i_e1_mode; + e1_time_delay_val = i_e1_time_delay; + + e2_high_val = i_e2_high; + e2_low_val = i_e2_low; + e2_initial_val = i_e2_initial; + e2_mode_val = i_e2_mode; + e2_time_delay_val = i_e2_time_delay; + + e3_high_val = i_e3_high; + e3_low_val = i_e3_low; + e3_initial_val = i_e3_initial; + e3_mode_val = i_e3_mode; + e3_time_delay_val = i_e3_time_delay; + + i = 0; + j = 0; + inclk_last_value = 0; + + ext_fbk_cntr_ph = 0; + ext_fbk_cntr_initial = 1; + + // initialize clkswitch variables + + clk0_is_bad = 0; + clk1_is_bad = 0; + inclk0_last_value = 0; + inclk1_last_value = 0; + other_clock_value = 0; + other_clock_last_value = 0; + primary_clk_is_bad = 0; + current_clk_is_bad = 0; + external_switch = 0; + current_clock = l_primary_clock; + if (l_primary_clock == "inclk0") + active_clock = 0; + else + active_clock = 1; + clkloss_tmp = 0; + got_curr_clk_falling_edge_after_clkswitch = 0; + clk0_count = 0; + clk1_count = 0; + switch_over_count = 0; + active_clk_was_switched = 0; + + // initialize quiet_time + quiet_time = slowest_clk ( l0_high_val+l0_low_val, + l1_high_val+l1_low_val, + g0_high_val+g0_low_val, + g1_high_val+g1_low_val, + g2_high_val+g2_low_val, + g3_high_val+g3_low_val, + e0_high_val+e0_low_val, + e1_high_val+e1_low_val, + e2_high_val+e2_low_val, + e3_high_val+e3_low_val, + l_scan_chain, + refclk_period, m_val); + pll_in_quiet_period = 0; + start_quiet_time = 0; + quiet_period_violation = 0; + reconfig_err = 0; + scanclr_violation = 0; + scanclr_clk_violation = 0; + got_first_scanclk_after_scanclr_inactive_edge = 0; + error = 0; + scanaclr_rising_time = 0; + scanaclr_falling_time = 0; + + // VCO feedback loop settings for external feedback mode + // first find which ext counter is used for feedback + + if (l_operation_mode == "external_feedback") + begin + if (l_feedback_source == "extclk0") + begin + if (i_extclk0_counter == "e0") + ext_fbk_cntr = "e0"; + else if (i_extclk0_counter == "e1") + ext_fbk_cntr = "e1"; + else if (i_extclk0_counter == "e2") + ext_fbk_cntr = "e2"; + else if (i_extclk0_counter == "e3") + ext_fbk_cntr = "e3"; + else ext_fbk_cntr = "e0"; + end + else if (l_feedback_source == "extclk1") + begin + if (i_extclk1_counter == "e0") + ext_fbk_cntr = "e0"; + else if (i_extclk1_counter == "e1") + ext_fbk_cntr = "e1"; + else if (i_extclk1_counter == "e2") + ext_fbk_cntr = "e2"; + else if (i_extclk1_counter == "e3") + ext_fbk_cntr = "e3"; + else ext_fbk_cntr = "e0"; + end + else if (l_feedback_source == "extclk2") + begin + if (i_extclk2_counter == "e0") + ext_fbk_cntr = "e0"; + else if (i_extclk2_counter == "e1") + ext_fbk_cntr = "e1"; + else if (i_extclk2_counter == "e2") + ext_fbk_cntr = "e2"; + else if (i_extclk2_counter == "e3") + ext_fbk_cntr = "e3"; + else ext_fbk_cntr = "e0"; + end + else if (l_feedback_source == "extclk3") + begin + if (i_extclk3_counter == "e0") + ext_fbk_cntr = "e0"; + else if (i_extclk3_counter == "e1") + ext_fbk_cntr = "e1"; + else if (i_extclk3_counter == "e2") + ext_fbk_cntr = "e2"; + else if (i_extclk3_counter == "e3") + ext_fbk_cntr = "e3"; + else ext_fbk_cntr = "e0"; + end + + // now save this counter's parameters + if (ext_fbk_cntr == "e0") + begin + ext_fbk_cntr_high = e0_high_val; + ext_fbk_cntr_low = e0_low_val; + ext_fbk_cntr_ph = i_e0_ph; + ext_fbk_cntr_initial = i_e0_initial; + ext_fbk_cntr_delay = e0_time_delay_val; + ext_fbk_cntr_mode = e0_mode_val; + end + else if (ext_fbk_cntr == "e1") + begin + ext_fbk_cntr_high = e1_high_val; + ext_fbk_cntr_low = e1_low_val; + ext_fbk_cntr_ph = i_e1_ph; + ext_fbk_cntr_initial = i_e1_initial; + ext_fbk_cntr_delay = e1_time_delay_val; + ext_fbk_cntr_mode = e1_mode_val; + end + else if (ext_fbk_cntr == "e2") + begin + ext_fbk_cntr_high = e2_high_val; + ext_fbk_cntr_low = e2_low_val; + ext_fbk_cntr_ph = i_e2_ph; + ext_fbk_cntr_initial = i_e2_initial; + ext_fbk_cntr_delay = e2_time_delay_val; + ext_fbk_cntr_mode = e2_mode_val; + end + else if (ext_fbk_cntr == "e3") + begin + ext_fbk_cntr_high = e3_high_val; + ext_fbk_cntr_low = e3_low_val; + ext_fbk_cntr_ph = i_e3_ph; + ext_fbk_cntr_initial = i_e3_initial; + ext_fbk_cntr_delay = e3_time_delay_val; + ext_fbk_cntr_mode = e3_mode_val; + end + + if (ext_fbk_cntr_mode == "bypass") + ext_fbk_cntr_modulus = 1; + else + ext_fbk_cntr_modulus = ext_fbk_cntr_high + ext_fbk_cntr_low; + end + + l_index = 1; + stop_vco = 0; + cycles_to_lock = 0; + cycles_to_unlock = 0; + if (l_pll_type == "fast") + locked_tmp = 1; + else + locked_tmp = 0; + pll_is_locked = 0; + pll_about_to_lock = 0; + + no_warn = 0; + m_val_tmp = m_val; + n_val_tmp = n_val; + end + + assign inclk_m = l_operation_mode == "external_feedback" ? (l_feedback_source == "extclk0" ? extclk0_tmp : + l_feedback_source == "extclk1" ? extclk1_tmp : + l_feedback_source == "extclk2" ? extclk2_tmp : + l_feedback_source == "extclk3" ? extclk3_tmp : 'b0) : + vco_out[m_ph_val]; + + stx_m_cntr m1 (.clk(inclk_m), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(fbclk), + .initial_value(m_initial_val), + .modulus(m_val), + .time_delay(m_delay)); + + always @(clkswitch_ipd) + begin + if (clkswitch_ipd == 1'b1) + external_switch = 1; + clkloss_tmp <= clkswitch_ipd; + end + + always @(inclk0_ipd or inclk1_ipd) + begin + // save the inclk event value + if (inclk0_ipd !== inclk0_last_value) + begin + if (current_clock !== "inclk0") + other_clock_value = inclk0_ipd; + end + if (inclk1_ipd !== inclk1_last_value) + begin + if (current_clock !== "inclk1") + other_clock_value = inclk1_ipd; + end + + // check if either input clk is bad + if (inclk0_ipd === 1'b1 && inclk0_ipd !== inclk0_last_value) + begin + clk0_count = clk0_count + 1; + clk0_is_bad = 0; + if (current_clock == "inclk0") + current_clk_is_bad = 0; + clk1_count = 0; + if (clk0_count > 2) + begin + // no event on other clk for 2 cycles + clk1_is_bad = 1; + if (current_clock == "inclk1") + current_clk_is_bad = 1; + end + end + if (inclk1_ipd === 1'b1 && inclk1_ipd !== inclk1_last_value) + begin + clk1_count = clk1_count + 1; + clk1_is_bad = 0; + if (current_clock == "inclk1") + current_clk_is_bad = 0; + clk0_count = 0; + if (clk1_count > 2) + begin + // no event on other clk for 2 cycles + clk0_is_bad = 1; + if (current_clock == "inclk0") + current_clk_is_bad = 1; + end + end + + // check if the bad clk is the primary clock + if (((l_primary_clock == "inclk0") && (clk0_is_bad == 1'b1)) || ((l_primary_clock == "inclk1") && (clk1_is_bad == 1'b1))) + primary_clk_is_bad = 1; + else + primary_clk_is_bad = 0; + + // actual switching + if ((inclk0_ipd !== inclk0_last_value) && (current_clock == "inclk0")) + begin + if (external_switch == 1'b1) + begin + if (!got_curr_clk_falling_edge_after_clkswitch) + begin + if (inclk0_ipd === 1'b0) + got_curr_clk_falling_edge_after_clkswitch = 1; + inclk_n = inclk0_ipd; + end + end + else inclk_n = inclk0_ipd; + end + if ((inclk1_ipd !== inclk1_last_value) && (current_clock == "inclk1")) + begin + if (external_switch == 1'b1) + begin + if (!got_curr_clk_falling_edge_after_clkswitch) + begin + if (inclk1_ipd === 1'b0) + got_curr_clk_falling_edge_after_clkswitch = 1; + inclk_n = inclk1_ipd; + end + end + else inclk_n = inclk1_ipd; + end + if ((other_clock_value == 1'b1) && (other_clock_value != other_clock_last_value) && (l_switch_over_on_lossclk == "on") && (l_enable_switch_over_counter == "on") && primary_clk_is_bad) + switch_over_count = switch_over_count + 1; + if ((other_clock_value == 1'b0) && (other_clock_value != other_clock_last_value)) + begin + if ((external_switch && (got_curr_clk_falling_edge_after_clkswitch || current_clk_is_bad)) || (l_switch_over_on_lossclk == "on" && primary_clk_is_bad && ((l_enable_switch_over_counter == "off" || switch_over_count == switch_over_counter)))) + begin + got_curr_clk_falling_edge_after_clkswitch = 0; + if (current_clock == "inclk0") + begin + current_clock = "inclk1"; + end + else + begin + current_clock = "inclk0"; + end + active_clock = ~active_clock; + active_clk_was_switched = 1; + switch_over_count = 0; + external_switch = 0; + current_clk_is_bad = 0; + end + end + + if (l_switch_over_on_lossclk == "on" && (clkswitch_ipd != 1'b1)) + begin + if (primary_clk_is_bad) + clkloss_tmp = 1; + else + clkloss_tmp = 0; + end + + inclk0_last_value = inclk0_ipd; + inclk1_last_value = inclk1_ipd; + other_clock_last_value = other_clock_value; + + end + + and (clkbad[0], clk0_is_bad, 1'b1); + and (clkbad[1], clk1_is_bad, 1'b1); + and (activeclock, active_clock, 1'b1); + and (clkloss, clkloss_tmp, 1'b1); + + stx_n_cntr n1 ( .clk(inclk_n), + .reset(areset_ipd), + .cout(refclk), + .modulus(n_val), + .time_delay(n_time_delay_val)); + + stx_scale_cntr l0 ( .clk(vco_out[i_l0_ph]), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(l0_clk), + .high(l0_high_val), + .low(l0_low_val), + .initial_value(l0_initial_val), + .mode(l0_mode_val), + .time_delay(l0_time_delay_val), + .ph_tap(i_l0_ph)); + + stx_scale_cntr l1 ( .clk(vco_out[i_l1_ph]), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(l1_clk), + .high(l1_high_val), + .low(l1_low_val), + .initial_value(l1_initial_val), + .mode(l1_mode_val), + .time_delay(l1_time_delay_val), + .ph_tap(i_l1_ph)); + + stx_scale_cntr g0 ( .clk(vco_out[i_g0_ph]), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(g0_clk), + .high(g0_high_val), + .low(g0_low_val), + .initial_value(g0_initial_val), + .mode(g0_mode_val), + .time_delay(g0_time_delay_val), + .ph_tap(i_g0_ph)); + + MF_pll_reg lvds_dffa ( .d(comparator_ipd), + .clrn(1'b1), + .prn(1'b1), + .ena(1'b1), + .clk(g0_clk), + .q(dffa_out)); + + MF_pll_reg lvds_dffb ( .d(dffa_out), + .clrn(1'b1), + .prn(1'b1), + .ena(1'b1), + .clk(lvds_dffb_clk), + .q(dffb_out)); + + assign lvds_dffb_clk = (l_enable0_counter == "l0") ? l0_clk : (l_enable0_counter == "l1") ? l1_clk : 1'b0; + + MF_pll_reg lvds_dffc ( .d(dffb_out), + .clrn(1'b1), + .prn(1'b1), + .ena(1'b1), + .clk(lvds_dffc_clk), + .q(dffc_out)); + + assign lvds_dffc_clk = (l_enable0_counter == "l0") ? l0_clk : (l_enable0_counter == "l1") ? l1_clk : 1'b0; + + assign nce_temp = ~dffc_out && dffb_out; + + MF_pll_reg lvds_dffd ( .d(nce_temp), + .clrn(1'b1), + .prn(1'b1), + .ena(1'b1), + .clk(~lvds_dffd_clk), + .q(dffd_out)); + + assign lvds_dffd_clk = (l_enable0_counter == "l0") ? l0_clk : (l_enable0_counter == "l1") ? l1_clk : 1'b0; + + assign nce_l0 = (l_enable0_counter == "l0") ? dffd_out : 'b0; + assign nce_l1 = (l_enable0_counter == "l1") ? dffd_out : 'b0; + + stx_scale_cntr g1 ( .clk(vco_out[i_g1_ph]), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(g1_clk), + .high(g1_high_val), + .low(g1_low_val), + .initial_value(g1_initial_val), + .mode(g1_mode_val), + .time_delay(g1_time_delay_val), + .ph_tap(i_g1_ph)); + + stx_scale_cntr g2 ( .clk(vco_out[i_g2_ph]), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(g2_clk), + .high(g2_high_val), + .low(g2_low_val), + .initial_value(g2_initial_val), + .mode(g2_mode_val), + .time_delay(g2_time_delay_val), + .ph_tap(i_g2_ph)); + + stx_scale_cntr g3 ( .clk(vco_out[i_g3_ph]), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(g3_clk), + .high(g3_high_val), + .low(g3_low_val), + .initial_value(g3_initial_val), + .mode(g3_mode_val), + .time_delay(g3_time_delay_val), + .ph_tap(i_g3_ph)); + assign cntr_e0_initial = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e0") ? 1 : e0_initial_val; + assign cntr_e0_delay = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e0") ? ext_fbk_delay : e0_time_delay_val; + + stx_scale_cntr e0 ( .clk(vco_out[i_e0_ph]), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(e0_clk), + .high(e0_high_val), + .low(e0_low_val), + .initial_value(cntr_e0_initial), + .mode(e0_mode_val), + .time_delay(cntr_e0_delay), + .ph_tap(i_e0_ph)); + + assign cntr_e1_initial = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e1") ? 1 : e1_initial_val; + assign cntr_e1_delay = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e1") ? ext_fbk_delay : e1_time_delay_val; + stx_scale_cntr e1 ( .clk(vco_out[i_e1_ph]), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(e1_clk), + .high(e1_high_val), + .low(e1_low_val), + .initial_value(cntr_e1_initial), + .mode(e1_mode_val), + .time_delay(cntr_e1_delay), + .ph_tap(i_e1_ph)); + + assign cntr_e2_initial = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e2") ? 1 : e2_initial_val; + assign cntr_e2_delay = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e2") ? ext_fbk_delay : e2_time_delay_val; + stx_scale_cntr e2 ( .clk(vco_out[i_e2_ph]), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(e2_clk), + .high(e2_high_val), + .low(e2_low_val), + .initial_value(cntr_e2_initial), + .mode(e2_mode_val), + .time_delay(cntr_e2_delay), + .ph_tap(i_e2_ph)); + + assign cntr_e3_initial = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e3") ? 1 : e3_initial_val; + assign cntr_e3_delay = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e3") ? ext_fbk_delay : e3_time_delay_val; + stx_scale_cntr e3 ( .clk(vco_out[i_e3_ph]), + .reset(areset_ipd || (!ena_ipd) || stop_vco), + .cout(e3_clk), + .high(e3_high_val), + .low(e3_low_val), + .initial_value(cntr_e3_initial), + .mode(e3_mode_val), + .time_delay(cntr_e3_delay), + .ph_tap(i_e3_ph)); + + + always @(vco_out[i_l0_ph] or posedge areset_ipd or negedge ena_ipd or stop_vco) + begin + if ((areset_ipd == 1'b1) || (ena_ipd == 1'b0) || (stop_vco == 1'b1)) + begin + l0_count = 1; + l0_got_first_rising_edge = 0; + end + else begin + if (nce_l0 == 1'b0) + begin + if (l0_got_first_rising_edge == 1'b0) + begin + if (vco_out[i_l0_ph] == 1'b1 && vco_out[i_l0_ph] != vco_l0_last_value) + l0_got_first_rising_edge = 1; + end + else if (vco_out[i_l0_ph] != vco_l0_last_value) + begin + l0_count = l0_count + 1; + if (l0_count == (l0_high_val + l0_low_val) * 2) + l0_count = 1; + end + end + if (vco_out[i_l0_ph] == 1'b0 && vco_out[i_l0_ph] != vco_l0_last_value) + begin + if (l0_count == 1) + begin + l0_tmp = 1; + l0_got_first_rising_edge = 0; + end + else l0_tmp = 0; + end + end + vco_l0_last_value = vco_out[i_l0_ph]; + end + + always @(vco_out[i_l1_ph] or posedge areset_ipd or negedge ena_ipd or stop_vco) + begin + if (areset_ipd == 1'b1 || ena_ipd == 1'b0 || stop_vco == 1'b1) + begin + l1_count = 1; + l1_got_first_rising_edge = 0; + end + else begin + if (nce_l1 == 1'b0) + begin + if (l1_got_first_rising_edge == 1'b0) + begin + if (vco_out[i_l1_ph] == 1'b1 && vco_out[i_l1_ph] != vco_l1_last_value) + l1_got_first_rising_edge = 1; + end + else if (vco_out[i_l1_ph] != vco_l1_last_value) + begin + l1_count = l1_count + 1; + if (l1_count == (l1_high_val + l1_low_val) * 2) + l1_count = 1; + end + end + if (vco_out[i_l1_ph] == 1'b0 && vco_out[i_l1_ph] != vco_l1_last_value) + begin + if (l1_count == 1) + begin + l1_tmp = 1; + l1_got_first_rising_edge = 0; + end + else l1_tmp = 0; + end + end + vco_l1_last_value = vco_out[i_l1_ph]; + end + + assign enable0_tmp = (l_enable0_counter == "l0") ? l0_tmp : l1_tmp; + assign enable1_tmp = (l_enable1_counter == "l0") ? l0_tmp : l1_tmp; + + always @ (inclk_n or ena_ipd or areset_ipd) + begin + if (areset_ipd == 'b1) + begin + gate_count = 0; + gate_out = 0; + end + else if (inclk_n == 'b1 && inclk_last_value != inclk_n) + if (ena_ipd == 'b1) + begin + gate_count = gate_count + 1; + if (gate_count == gate_lock_counter) + gate_out = 1; + end + inclk_last_value = inclk_n; + end + + assign locked = (l_gate_lock_signal == "yes") ? gate_out && locked_tmp : locked_tmp; + + always @ (scanclk_ipd or scanaclr_ipd) + begin + if (scanaclr_ipd === 1'b1 && scanaclr_last_value === 1'b0) + scanaclr_rising_time = $time; + else if (scanaclr_ipd === 1'b0 && scanaclr_last_value === 1'b1) + begin + scanaclr_falling_time = $time; + // check for scanaclr active pulse width + if ($time - scanaclr_rising_time < TRST) + begin + scanclr_violation = 1; + $display ("Warning : Detected SCANACLR ACTIVE pulse width violation. Required is 5000 ps, actual is %0t. Reconfiguration may not work.", $time - scanaclr_rising_time); + $display ("Time: %0t Instance: %m", $time); + end + else begin + scanclr_violation = 0; + for (i = 0; i <= scan_chain_length; i = i + 1) + scan_data[i] = 0; + end + got_first_scanclk_after_scanclr_inactive_edge = 0; + end + else if ((scanclk_ipd === 'b1 && scanclk_last_value !== scanclk_ipd) && (got_first_scanclk_after_scanclr_inactive_edge === 1'b0) && ($time - scanaclr_falling_time < TRSTCLK)) + begin + scanclr_clk_violation = 1; + $display ("Warning : Detected SCANACLR INACTIVE time violation before rising edge of SCANCLK. Required is 5000 ps, actual is %0t. Reconfiguration may not work.", $time - scanaclr_falling_time); + $display ("Time: %0t Instance: %m", $time); + got_first_scanclk_after_scanclr_inactive_edge = 1; + end + else if (scanclk_ipd == 'b1 && scanclk_last_value != scanclk_ipd && scanaclr_ipd === 1'b0) + begin + if (pll_in_quiet_period && ($time - start_quiet_time < quiet_time)) + begin + $display("Time: %0t", $time, " Warning : Detected transition on SCANCLK during quiet time. PLL may not function correctly."); + quiet_period_violation = 1; + end + else begin + pll_in_quiet_period = 0; + for (j = scan_chain_length-1; j >= 1; j = j - 1) + begin + scan_data[j] = scan_data[j - 1]; + end + scan_data[0] = scandata_ipd; + end + if (got_first_scanclk_after_scanclr_inactive_edge === 1'b0) + begin + got_first_scanclk_after_scanclr_inactive_edge = 1; + scanclr_clk_violation = 0; + end + end + else if (scanclk_ipd === 1'b0 && scanclk_last_value !== scanclk_ipd && scanaclr_ipd === 1'b0) + begin + if (pll_in_quiet_period && ($time - start_quiet_time < quiet_time)) + begin + $display("Time: %0t", $time, " Warning : Detected transition on SCANCLK during quiet time. PLL may not function correctly."); + quiet_period_violation = 1; + end + else if (scan_data[scan_chain_length-1] == 1'b1) + begin + pll_in_quiet_period = 1; + quiet_period_violation = 0; + reconfig_err = 0; + start_quiet_time = $time; + // initiate transfer + scandataout_tmp <= 1'b1; + quiet_time = slowest_clk ( l0_high_val+l0_low_val, + l1_high_val+l1_low_val, + g0_high_val+g0_low_val, + g1_high_val+g1_low_val, + g2_high_val+g2_low_val, + g3_high_val+g3_low_val, + e0_high_val+e0_low_val, + e1_high_val+e1_low_val, + e2_high_val+e2_low_val, + e3_high_val+e3_low_val, + l_scan_chain, + refclk_period, m_val); + transfer <= 1; + end + end + scanclk_last_value = scanclk_ipd; + scanaclr_last_value = scanaclr_ipd; + end + + always @(scandataout_tmp) + begin + if (scandataout_tmp == 1'b1) + scandataout_tmp <= #(quiet_time) 1'b0; + end + + always @(posedge transfer) + begin + if (transfer == 1'b1) + begin + $display("NOTE : Reconfiguring PLL"); + $display ("Time: %0t Instance: %m", $time); + if (l_scan_chain == "long") + begin + // cntr e3 + error = 0; + if (scan_data[273] == 1'b1) + begin + e3_mode_val = "bypass"; + if (scan_data[283] == 1'b1) + begin + e3_mode_val = "off"; + $display("Warning : The specified bit settings will turn OFF the E3 counter. It cannot be turned on unless the part is re-initialized."); + end + end + else if (scan_data[283] == 1'b1) + e3_mode_val = "odd"; + else + e3_mode_val = "even"; + // before reading delay bits, clear e3_time_delay_val + e3_time_delay_val = 32'b0; + e3_time_delay_val = scan_data[287:284]; + e3_time_delay_val = e3_time_delay_val * 250; + if (e3_time_delay_val > 3000) + e3_time_delay_val = 3000; + e3_high_val[8:0] <= scan_data[272:264]; + e3_low_val[8:0] <= scan_data[282:274]; + if (scan_data[272:264] == 9'b000000000) + e3_high_val[9:0] <= 10'b1000000000; + if (scan_data[282:274] == 9'b000000000) + e3_low_val[9:0] <= 10'b1000000000; + + if (ext_fbk_cntr == "e3") + begin + ext_fbk_cntr_high = e3_high_val; + ext_fbk_cntr_low = e3_low_val; + ext_fbk_cntr_delay = e3_time_delay_val; + ext_fbk_cntr_mode = e3_mode_val; + end + + // cntr e2 + if (scan_data[249] == 1'b1) + begin + e2_mode_val = "bypass"; + if (scan_data[259] == 1'b1) + begin + e2_mode_val = "off"; + $display("Warning : The specified bit settings will turn OFF the E2 counter. It cannot be turned on unless the part is re-initialized."); + end + end + else if (scan_data[259] == 1'b1) + e2_mode_val = "odd"; + else + e2_mode_val = "even"; + e2_time_delay_val = 32'b0; + e2_time_delay_val = scan_data[263:260]; + e2_time_delay_val = e2_time_delay_val * 250; + if (e2_time_delay_val > 3000) + e2_time_delay_val = 3000; + e2_high_val[8:0] <= scan_data[248:240]; + e2_low_val[8:0] <= scan_data[258:250]; + if (scan_data[248:240] == 9'b000000000) + e2_high_val[9:0] <= 10'b1000000000; + if (scan_data[258:250] == 9'b000000000) + e2_low_val[9:0] <= 10'b1000000000; + + if (ext_fbk_cntr == "e2") + begin + ext_fbk_cntr_high = e2_high_val; + ext_fbk_cntr_low = e2_low_val; + ext_fbk_cntr_delay = e2_time_delay_val; + ext_fbk_cntr_mode = e2_mode_val; + end + + // cntr e1 + if (scan_data[225] == 1'b1) + begin + e1_mode_val = "bypass"; + if (scan_data[235] == 1'b1) + begin + e1_mode_val = "off"; + $display("Warning : The specified bit settings will turn OFF the E1 counter. It cannot be turned on unless the part is re-initialized."); + end + end + else if (scan_data[235] == 1'b1) + e1_mode_val = "odd"; + else + e1_mode_val = "even"; + e1_time_delay_val = 32'b0; + e1_time_delay_val = scan_data[239:236]; + e1_time_delay_val = e1_time_delay_val * 250; + if (e1_time_delay_val > 3000) + e1_time_delay_val = 3000; + e1_high_val[8:0] <= scan_data[224:216]; + e1_low_val[8:0] <= scan_data[234:226]; + if (scan_data[224:216] == 9'b000000000) + e1_high_val[9:0] <= 10'b1000000000; + if (scan_data[234:226] == 9'b000000000) + e1_low_val[9:0] <= 10'b1000000000; + + if (ext_fbk_cntr == "e1") + begin + ext_fbk_cntr_high = e1_high_val; + ext_fbk_cntr_low = e1_low_val; + ext_fbk_cntr_delay = e1_time_delay_val; + ext_fbk_cntr_mode = e1_mode_val; + end + + // cntr e0 + if (scan_data[201] == 1'b1) + begin + e0_mode_val = "bypass"; + if (scan_data[211] == 1'b1) + begin + e0_mode_val = "off"; + $display("Warning : The specified bit settings will turn OFF the E0 counter. It cannot be turned on unless the part is re-initialized."); + end + end + else if (scan_data[211] == 1'b1) + e0_mode_val = "odd"; + else + e0_mode_val = "even"; + e0_time_delay_val = 32'b0; + e0_time_delay_val = scan_data[215:212]; + e0_time_delay_val = e0_time_delay_val * 250; + if (e0_time_delay_val > 3000) + e0_time_delay_val = 3000; + e0_high_val[8:0] <= scan_data[200:192]; + e0_low_val[8:0] <= scan_data[210:202]; + if (scan_data[200:192] == 9'b000000000) + e0_high_val[9:0] <= 10'b1000000000; + if (scan_data[210:202] == 9'b000000000) + e0_low_val[9:0] <= 10'b1000000000; + + if (ext_fbk_cntr == "e0") + begin + ext_fbk_cntr_high = e0_high_val; + ext_fbk_cntr_low = e0_low_val; + ext_fbk_cntr_delay = e0_time_delay_val; + ext_fbk_cntr_mode = e0_mode_val; + end + end + + // cntr l1 + if (scan_data[177] == 1'b1) + begin + l1_mode_val = "bypass"; + if (scan_data[187] == 1'b1) + begin + l1_mode_val = "off"; + $display("Warning : The specified bit settings will turn OFF the L1 counter. It cannot be turned on unless the part is re-initialized."); + end + end + else if (scan_data[187] == 1'b1) + l1_mode_val = "odd"; + else + l1_mode_val = "even"; + l1_time_delay_val = 32'b0; + l1_time_delay_val = scan_data[191:188]; + l1_time_delay_val = l1_time_delay_val * 250; + if (l1_time_delay_val > 3000) + l1_time_delay_val = 3000; + l1_high_val[8:0] <= scan_data[176:168]; + l1_low_val[8:0] <= scan_data[186:178]; + if (scan_data[176:168] == 9'b000000000) + l1_high_val[9:0] <= 10'b1000000000; + if (scan_data[186:178] == 9'b000000000) + l1_low_val[9:0] <= 10'b1000000000; + + // cntr l0 + if (scan_data[153] == 1'b1) + begin + l0_mode_val = "bypass"; + if (scan_data[163] == 1'b1) + begin + l0_mode_val = "off"; + $display("Warning : The specified bit settings will turn OFF the L0 counter. It cannot be turned on unless the part is re-initialized."); + end + end + else if (scan_data[163] == 1'b1) + l0_mode_val = "odd"; + else + l0_mode_val = "even"; + l0_time_delay_val = 32'b0; + l0_time_delay_val = scan_data[167:164]; + l0_time_delay_val = l0_time_delay_val * 250; + if (l0_time_delay_val > 3000) + l0_time_delay_val = 3000; + l0_high_val[8:0] <= scan_data[152:144]; + l0_low_val[8:0] <= scan_data[162:154]; + if (scan_data[152:144] == 9'b000000000) + l0_high_val[9:0] <= 10'b1000000000; + if (scan_data[162:154] == 9'b000000000) + l0_low_val[9:0] <= 10'b1000000000; + + // cntr g3 + if (scan_data[129] == 1'b1) + begin + g3_mode_val = "bypass"; + if (scan_data[139] == 1'b1) + begin + g3_mode_val = "off"; + $display("Warning : The specified bit settings will turn OFF the G3 counter. It cannot be turned on unless the part is re-initialized."); + end + end + else if (scan_data[139] == 1'b1) + g3_mode_val = "odd"; + else + g3_mode_val = "even"; + g3_time_delay_val = 32'b0; + g3_time_delay_val = scan_data[143:140]; + g3_time_delay_val = g3_time_delay_val * 250; + if (g3_time_delay_val > 3000) + g3_time_delay_val = 3000; + g3_high_val[8:0] <= scan_data[128:120]; + g3_low_val[8:0] <= scan_data[138:130]; + if (scan_data[128:120] == 9'b000000000) + g3_high_val[9:0] <= 10'b1000000000; + if (scan_data[138:130] == 9'b000000000) + g3_low_val[9:0] <= 10'b1000000000; + + // cntr g2 + if (scan_data[105] == 1'b1) + begin + g2_mode_val = "bypass"; + if (scan_data[115] == 1'b1) + begin + g2_mode_val = "off"; + $display("Warning : The specified bit settings will turn OFF the G2 counter. It cannot be turned on unless the part is re-initialized."); + end + end + else if (scan_data[115] == 1'b1) + g2_mode_val = "odd"; + else + g2_mode_val = "even"; + g2_time_delay_val = 32'b0; + g2_time_delay_val = scan_data[119:116]; + g2_time_delay_val = g2_time_delay_val * 250; + if (g2_time_delay_val > 3000) + g2_time_delay_val = 3000; + g2_high_val[8:0] <= scan_data[104:96]; + g2_low_val[8:0] <= scan_data[114:106]; + if (scan_data[104:96] == 9'b000000000) + g2_high_val[9:0] <= 10'b1000000000; + if (scan_data[114:106] == 9'b000000000) + g2_low_val[9:0] <= 10'b1000000000; + + // cntr g1 + if (scan_data[81] == 1'b1) + begin + g1_mode_val = "bypass"; + if (scan_data[91] == 1'b1) + begin + g1_mode_val = "off"; + $display("Warning : The specified bit settings will turn OFF the G1 counter. It cannot be turned on unless the part is re-initialized."); + end + end + else if (scan_data[91] == 1'b1) + g1_mode_val = "odd"; + else + g1_mode_val = "even"; + g1_time_delay_val = 32'b0; + g1_time_delay_val = scan_data[95:92]; + g1_time_delay_val = g1_time_delay_val * 250; + if (g1_time_delay_val > 3000) + g1_time_delay_val = 3000; + g1_high_val[8:0] <= scan_data[80:72]; + g1_low_val[8:0] <= scan_data[90:82]; + if (scan_data[80:72] == 9'b000000000) + g1_high_val[9:0] <= 10'b1000000000; + if (scan_data[90:82] == 9'b000000000) + g1_low_val[9:0] <= 10'b1000000000; + + // cntr g0 + if (scan_data[57] == 1'b1) + begin + g0_mode_val = "bypass"; + if (scan_data[67] == 1'b1) + begin + g0_mode_val = "off"; + $display("Warning : The specified bit settings will turn OFF the G0 counter. It cannot be turned on unless the part is re-initialized."); + end + end + else if (scan_data[67] == 1'b1) + g0_mode_val = "odd"; + else + g0_mode_val = "even"; + g0_time_delay_val = 32'b0; + g0_time_delay_val = scan_data[71:68]; + g0_time_delay_val = g0_time_delay_val * 250; + if (g0_time_delay_val > 3000) + g0_time_delay_val = 3000; + g0_high_val[8:0] <= scan_data[56:48]; + g0_low_val[8:0] <= scan_data[66:58]; + if (scan_data[56:48] == 9'b000000000) + g0_high_val[9:0] <= 10'b1000000000; + if (scan_data[66:58] == 9'b000000000) + g0_low_val[9:0] <= 10'b1000000000; + + // cntr M + error = 0; + m_val_tmp[8:0] = scan_data[32:24]; + if (scan_data[33] !== 1'b1) + begin + if (m_val_tmp[8:0] == 9'b000000001) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Illegal 1 value for M counter. Instead, the M counter should be BYPASSED. Reconfiguration may not work."); + end + else if (m_val_tmp[8:0] == 9'b000000000) + m_val_tmp[9:0] = 10'b1000000000; + if (error == 1'b0) + begin + if (m_mode_val === "bypass") + $display ("Warning : M counter switched from BYPASS mode to enabled (M modulus = %d). PLL may lose lock.", m_val_tmp[9:0]); + else + $display("PLL reconfigured with : M modulus = %d ", m_val_tmp[9:0]); + m_mode_val = ""; + end + end + else if (scan_data[33] == 1'b1) + begin + if (scan_data[24] !== 1'b0) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Illegal value for counter M 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."); + end + else begin + if (m_mode_val !== "bypass") + $display ("Warning : M counter switched from enabled to BYPASS mode. PLL may lose lock."); + m_val_tmp[9:0] = 10'b0000000001; + m_mode_val = "bypass"; + $display("PLL reconfigured with : M modulus = %d ", m_val_tmp[9:0]); + end + end + + if (skip_vco == "on") + m_val_tmp[9:0] = 10'b0000000001; + + // cntr M2 + if (ss > 0) + begin + error = 0; + m2_val[8:0] = scan_data[42:34]; + if (scan_data[43] !== 1'b1) + begin + if (m2_val[8:0] == 9'b000000001) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Illegal 1 value for M2 counter. Instead, the M2 counter should be BYPASSED. Reconfiguration may not work."); + end + else if (m2_val[8:0] == 9'b000000000) + m2_val[9:0] = 10'b1000000000; + if (error == 1'b0) + begin + if (m2_mode_val === "bypass") + $display ("Warning : M2 counter switched from BYPASS mode to enabled (M2 modulus = %d). Pll may lose lock.", m2_val[9:0]); + else + $display(" M2 modulus = %d ", m2_val[9:0]); + m2_mode_val = ""; + end + end + else if (scan_data[43] == 1'b1) + begin + if (scan_data[34] !== 1'b0) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Illegal value for counter M2 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."); + end + else begin + if (m2_mode_val !== "bypass") + $display ("Warning : M2 counter switched from enabled to BYPASS mode. PLL may lose lock."); + m2_val[9:0] = 10'b0000000001; + m2_mode_val = "bypass"; + $display(" M2 modulus = %d ", m2_val[9:0]); + end + end + if (m_mode_val != m2_mode_val) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Incompatible modes for M1/M2 counters. Either both should be BYASSED or both NON-BYPASSED. Reconfiguration may not work."); + end + end + + m_time_delay_val = 32'b0; + m_time_delay_val = scan_data[47:44]; + m_time_delay_val = m_time_delay_val * 250; + if (m_time_delay_val > 3000) + m_time_delay_val = 3000; + if (skip_vco == "on") + m_time_delay_val = 32'b0; + $display(" M time delay = %0d", m_time_delay_val); + + // cntr N + error = 0; + n_val_tmp[8:0] = scan_data[8:0]; + if (scan_data[9] !== 1'b1) + begin + if (n_val_tmp[8:0] == 9'b000000001) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Illegal 1 value for N counter. Instead, the N counter should be BYPASSED. Reconfiguration may not work."); + end + else if (n_val_tmp[8:0] == 9'b000000000) + n_val_tmp[9:0] = 10'b1000000000; + if (error == 1'b0) + begin + if (n_mode_val === "bypass") + $display ("Warning : N counter switched from BYPASS mode to enabled (N modulus = %d). PLL may lose lock.", n_val_tmp[9:0]); + else + $display(" N modulus = %d ", n_val_tmp[9:0]); + n_mode_val = ""; + end + end + else if (scan_data[9] == 1'b1) // bypass + begin + if (scan_data[0] !== 1'b0) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Illegal value for counter N 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."); + end + else begin + if (n_mode_val !== "bypass") + $display ("Warning : N counter switched from enabled to BYPASS mode. PLL may lose lock."); + n_val_tmp[9:0] = 10'b0000000001; + n_mode_val = "bypass"; + $display(" N modulus = %d ", n_val_tmp[9:0]); + end + end + + // cntr N2 + if (ss > 0) + begin + error = 0; + n2_val[8:0] = scan_data[18:10]; + if (scan_data[19] !== 1'b1) + begin + if (n2_val[8:0] == 9'b000000001) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Illegal 1 value for N2 counter. Instead, the N2 counter should be BYPASSED. Reconfiguration may not work."); + end + else if (n2_val[8:0] == 9'b000000000) + n2_val = 10'b1000000000; + if (error == 1'b0) + begin + if (n2_mode_val === "bypass") + $display ("Warning : N2 counter switched from BYPASS mode to enabled (N2 modulus = %d). PLL may lose lock.", n2_val[9:0]); + else + $display(" N2 modulus = %d ", n2_val[9:0]); + n2_mode_val = ""; + end + end + else if (scan_data[19] == 1'b1) // bypass + begin + if (scan_data[10] !== 1'b0) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Illegal value for counter N2 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."); + end + else begin + if (n2_mode_val !== "bypass") + $display ("Warning : N2 counter switched from enabled to BYPASS mode. PLL may lose lock."); + n2_val[9:0] = 10'b0000000001; + n2_mode_val = "bypass"; + $display(" N2 modulus = %d ", n2_val[9:0]); + end + end + if (n_mode_val != n2_mode_val) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Incompatible modes for N1/N2 counters. Either both should be BYASSED or both NON-BYPASSED."); + end + end // ss > 0 + + n_time_delay_val = 32'b0; + n_time_delay_val = scan_data[23:20]; + n_time_delay_val = n_time_delay_val * 250; + if (n_time_delay_val > 3000) + n_time_delay_val = 3000; + $display(" N time delay = %0d", n_time_delay_val); + + transfer <= 0; + // clear the scan_chain + for (i = 0; i <= scan_chain_length; i = i + 1) + scan_data[i] = 0; + end + end + + always @(negedge transfer) + begin + if (l_scan_chain == "long") + begin + $display(" E3 high = %d, E3 low = %d, E3 mode = %s, E3 time delay = %0d", e3_high_val[9:0], e3_low_val[9:0], e3_mode_val, e3_time_delay_val); + $display(" E2 high = %d, E2 low = %d, E2 mode = %s, E2 time delay = %0d", e2_high_val[9:0], e2_low_val[9:0], e2_mode_val, e2_time_delay_val); + $display(" E1 high = %d, E1 low = %d, E1 mode = %s, E1 time delay = %0d", e1_high_val[9:0], e1_low_val[9:0], e1_mode_val, e1_time_delay_val); + $display(" E0 high = %d, E0 low = %d, E0 mode = %s, E0 time delay = %0d", e0_high_val[9:0], e0_low_val[9:0], e0_mode_val, e0_time_delay_val); + end + $display(" L1 high = %d, L1 low = %d, L1 mode = %s, L1 time delay = %0d", l1_high_val[9:0], l1_low_val[9:0], l1_mode_val, l1_time_delay_val); + $display(" L0 high = %d, L0 low = %d, L0 mode = %s, L0 time delay = %0d", l0_high_val[9:0], l0_low_val[9:0], l0_mode_val, l0_time_delay_val); + $display(" G3 high = %d, G3 low = %d, G3 mode = %s, G3 time delay = %0d", g3_high_val[9:0], g3_low_val[9:0], g3_mode_val, g3_time_delay_val); + $display(" G2 high = %d, G2 low = %d, G2 mode = %s, G2 time delay = %0d", g2_high_val[9:0], g2_low_val[9:0], g2_mode_val, g2_time_delay_val); + $display(" G1 high = %d, G1 low = %d, G1 mode = %s, G1 time delay = %0d", g1_high_val[9:0], g1_low_val[9:0], g1_mode_val, g1_time_delay_val); + $display(" G0 high = %d, G0 low = %d, G0 mode = %s, G0 time delay = %0d", g0_high_val[9:0], g0_low_val[9:0], g0_mode_val, g0_time_delay_val); + end + +always @(schedule_vco or areset_ipd or ena_ipd) +begin + sched_time = 0; + + for (i = 0; i <= 7; i=i+1) + last_phase_shift[i] = phase_shift[i]; + + cycle_to_adjust = 0; + l_index = 1; + m_times_vco_period = new_m_times_vco_period; + + // give appropriate messages + // if areset was asserted + if (areset_ipd == 1'b1 && areset_ipd_last_value !== areset_ipd) + begin + $display (" Note : Stratix PLL was reset"); + $display ("Time: %0t Instance: %m", $time); + end + + // if ena was deasserted + if (ena_ipd == 1'b0 && ena_ipd_last_value !== ena_ipd) + begin + $display (" Note : Stratix PLL was disabled"); + $display ("Time: %0t Instance: %m", $time); + end + + // illegal value on areset_ipd + if (areset_ipd === 1'bx && (areset_ipd_last_value === 1'b0 || areset_ipd_last_value === 1'b1)) + begin + $display("Warning : Illegal value 'X' detected on ARESET input"); + $display ("Time: %0t Instance: %m", $time); + end + + if ((schedule_vco !== schedule_vco_last_value) && (areset_ipd == 1'b1 || ena_ipd == 1'b0 || stop_vco == 1'b1)) + begin + + // drop VCO taps to 0 + for (i = 0; i <= 7; i=i+1) + begin + for (j = 0; j <= last_phase_shift[i] + 1; j=j+1) + vco_out[i] <= #(j) 1'b0; + phase_shift[i] = 0; + last_phase_shift[i] = 0; + end + + // reset lock parameters + locked_tmp = 0; + if (l_pll_type == "fast") + locked_tmp = 1; + pll_is_locked = 0; + pll_about_to_lock = 0; + cycles_to_lock = 0; + cycles_to_unlock = 0; + + got_first_refclk = 0; + got_second_refclk = 0; + refclk_time = 0; + got_first_fbclk = 0; + fbclk_time = 0; + first_fbclk_time = 0; + fbclk_period = 0; + + first_schedule = 1; + schedule_offset = 1; + vco_val = 0; + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 0; + + // reset enable0 and enable1 counter parameters +// l0_count = 1; +// l1_count = 1; +// l0_got_first_rising_edge = 0; +// l1_got_first_rising_edge = 0; + + end else if (ena_ipd === 1'b1 && areset_ipd === 1'b0 && stop_vco === 1'b0) + begin + + // else note areset deassert time + // note it as refclk_time to prevent false triggering + // of stop_vco after areset + if (areset_ipd === 1'b0 && areset_ipd_last_value === 1'b1) + begin + refclk_time = $time; + end + + // calculate loop_xplier : this will be different from m_val in ext. fbk mode + loop_xplier = m_val; + loop_initial = i_m_initial - 1; + loop_ph = i_m_ph; + loop_time_delay = m_time_delay_val; + + if (l_operation_mode == "external_feedback") + begin + if (ext_fbk_cntr_mode == "bypass") + ext_fbk_cntr_modulus = 1; + else + ext_fbk_cntr_modulus = ext_fbk_cntr_high + ext_fbk_cntr_low; + + loop_xplier = m_val * (ext_fbk_cntr_modulus); + loop_ph = ext_fbk_cntr_ph; + loop_initial = ext_fbk_cntr_initial - 1 + ((i_m_initial - 1) * (ext_fbk_cntr_modulus)); + loop_time_delay = m_time_delay_val + ext_fbk_cntr_delay; + end + + // convert initial value to delay + initial_delay = (loop_initial * m_times_vco_period)/loop_xplier; + + // convert loop ph_tap to delay + rem = m_times_vco_period % loop_xplier; + vco_per = m_times_vco_period/loop_xplier; + if (rem != 0) + vco_per = vco_per + 1; + fbk_phase = (loop_ph * vco_per)/8; + + if (l_operation_mode == "external_feedback") + begin + pull_back_ext_cntr = ext_fbk_cntr_delay + (ext_fbk_cntr_initial - 1) * (m_times_vco_period/loop_xplier) + fbk_phase; + + while (pull_back_ext_cntr > refclk_period) + pull_back_ext_cntr = pull_back_ext_cntr - refclk_period; + + pull_back_M = m_time_delay_val + (i_m_initial - 1) * (ext_fbk_cntr_modulus) * (m_times_vco_period/loop_xplier); + + while (pull_back_M > refclk_period) + pull_back_M = pull_back_M - refclk_period; + end + else begin + pull_back_ext_cntr = 0; + pull_back_M = initial_delay + m_time_delay_val + fbk_phase; + end + + total_pull_back = pull_back_M + pull_back_ext_cntr; + if (l_simulation_type == "timing") + total_pull_back = total_pull_back + pll_compensation_delay; + + while (total_pull_back > refclk_period) + total_pull_back = total_pull_back - refclk_period; + + if (total_pull_back > 0) + offset = refclk_period - total_pull_back; + + if (l_operation_mode == "external_feedback") + begin + fbk_delay = pull_back_M; + if (l_simulation_type == "timing") + fbk_delay = fbk_delay + pll_compensation_delay; + + ext_fbk_delay = pull_back_ext_cntr - fbk_phase; + end + else begin + fbk_delay = total_pull_back - fbk_phase; + if (fbk_delay < 0) + begin + offset = offset - fbk_phase; + fbk_delay = total_pull_back; + end + end + + // assign m_delay + m_delay = fbk_delay; + + for (i = 1; i <= loop_xplier; i=i+1) + begin + // adjust cycles + tmp_vco_per = m_times_vco_period/loop_xplier; + if (rem != 0 && l_index <= rem) + begin + tmp_rem = (loop_xplier * l_index) % rem; + cycle_to_adjust = (loop_xplier * l_index) / rem; + if (tmp_rem != 0) + cycle_to_adjust = cycle_to_adjust + 1; + end + if (cycle_to_adjust == i) + begin + tmp_vco_per = tmp_vco_per + 1; + l_index = l_index + 1; + end + + // calculate high and low periods + high_time = tmp_vco_per/2; + if (tmp_vco_per % 2 != 0) + high_time = high_time + 1; + low_time = tmp_vco_per - high_time; + + // schedule the rising and falling egdes + for (j=0; j<=1; j=j+1) + begin + vco_val = ~vco_val; + if (vco_val == 1'b0) + sched_time = sched_time + high_time; + else + sched_time = sched_time + low_time; + + // add offset + if (schedule_offset == 1'b1) + begin + sched_time = sched_time + offset; + schedule_offset = 0; + end + + // schedule taps with appropriate phase shifts + for (k = 0; k <= 7; k=k+1) + begin + phase_shift[k] = (k*tmp_vco_per)/8; + if (first_schedule) + vco_out[k] <= #(sched_time + phase_shift[k]) vco_val; + else + vco_out[k] <= #(sched_time + last_phase_shift[k]) vco_val; + end + end + end + if (first_schedule) + begin + vco_val = ~vco_val; + if (vco_val == 1'b0) + sched_time = sched_time + high_time; + else + sched_time = sched_time + low_time; + for (k = 0; k <= 7; k=k+1) + begin + phase_shift[k] = (k*tmp_vco_per)/8; + vco_out[k] <= #(sched_time+phase_shift[k]) vco_val; + end + first_schedule = 0; + end + + // this may no longer be required + + schedule_vco <= #(sched_time) ~schedule_vco; + if (vco_period_was_phase_adjusted) + begin + m_times_vco_period = refclk_period; + new_m_times_vco_period = refclk_period; + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 1; + + tmp_vco_per = m_times_vco_period/loop_xplier; + for (k = 0; k <= 7; k=k+1) + phase_shift[k] = (k*tmp_vco_per)/8; + end + end + + areset_ipd_last_value = areset_ipd; + ena_ipd_last_value = ena_ipd; + schedule_vco_last_value = schedule_vco; + +end + +always @(pfdena_ipd) +begin + if (pfdena_ipd === 1'b0) + begin + locked_tmp = 1'bx; + pll_is_locked = 0; + cycles_to_lock = 0; + $display (" Note : PFDENA was deasserted"); + $display ("Time: %0t Instance: %m", $time); + end + else if (pfdena_ipd === 1'b1 && pfdena_ipd_last_value === 1'b0) + begin + // PFD was disabled, now enabled again + got_first_refclk = 0; + got_second_refclk = 0; + refclk_time = $time; + end + pfdena_ipd_last_value = pfdena_ipd; +end + +always @(negedge refclk) +begin + refclk_last_value = refclk; +end + +always @(negedge fbclk) +begin + fbclk_last_value = fbclk; +end + +always @(posedge refclk or posedge fbclk) +begin + if (refclk == 1'b1 && refclk_last_value !== refclk && areset_ipd === 1'b0) + begin + n_val <= n_val_tmp; + if (! got_first_refclk) + begin + got_first_refclk = 1; + end else + begin + got_second_refclk = 1; + refclk_period = $time - refclk_time; + + // check if incoming freq. will cause VCO range to be + // exceeded + if ( (vco_max != 0 && vco_min != 0) && (skip_vco == "off") && (pfdena_ipd === 1'b1) && + ((refclk_period/loop_xplier > vco_max) || + (refclk_period/loop_xplier < vco_min)) ) + begin + if (pll_is_locked == 1'b1) + begin + $display ("Warning : Input clock freq. is not within VCO range. PLL may lose lock"); + $display ("Time: %0t Instance: %m", $time); + if (inclk_out_of_range === 1'b1) + begin + // unlock + pll_is_locked = 0; + locked_tmp = 0; + if (l_pll_type == "fast") + locked_tmp = 1; + pll_about_to_lock = 0; + cycles_to_lock = 0; + $display ("Note : Stratix PLL lost lock"); + $display ("Time: %0t Instance: %m", $time); + first_schedule = 1; + schedule_offset = 1; + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 0; + end + end + else begin + if (no_warn == 0) + begin + $display ("Warning : Input clock freq. is not within VCO range. PLL may not lock"); + $display ("Time: %0t Instance: %m", $time); + no_warn = 1; + end + end + inclk_out_of_range = 1; + end + else if ( vco_min == 0 && vco_max == 0 && pll_type == "cdr") + begin + if (refclk_period != primary_clock_frequency) + begin + if (no_warn == 0) + begin + $display("Warning : Incoming clock period %d for Stratix PLL does not match the specified inclock period %d. ALTGXB simulation may not function correctly.", refclk_period, primary_clock_frequency); + $display ("Time: %0t Instance: %m", $time); + no_warn = 1; + end + end + end + else begin + inclk_out_of_range = 0; + end + + end + if (stop_vco == 1'b1) + begin + stop_vco = 0; + schedule_vco = ~schedule_vco; + end + refclk_time = $time; + end + + if (fbclk == 1'b1 && fbclk_last_value !== fbclk) + begin + m_val <= m_val_tmp; + if (!got_first_fbclk) + begin + got_first_fbclk = 1; + first_fbclk_time = $time; + end + else + fbclk_period = $time - fbclk_time; + + // need refclk_period here, so initialized to proper value above + if ( ( ($time - refclk_time > 1.5 * refclk_period) && pfdena_ipd === 1'b1 && pll_is_locked == 1'b1) || ( ($time - refclk_time > 5 * refclk_period) && pfdena_ipd === 1'b1) ) + begin + stop_vco = 1; + // reset + got_first_refclk = 0; + got_first_fbclk = 0; + got_second_refclk = 0; + if (pll_is_locked == 1'b1) + begin + pll_is_locked = 0; + locked_tmp = 0; + if (l_pll_type == "fast") + locked_tmp = 1; + $display ("Note : Stratix PLL lost lock due to loss of input clock"); + $display ("Time: %0t Instance: %m", $time); + end + pll_about_to_lock = 0; + cycles_to_lock = 0; + cycles_to_unlock = 0; + first_schedule = 1; + end + fbclk_time = $time; + end + + if (got_second_refclk && pfdena_ipd === 1'b1 && (!inclk_out_of_range)) + begin + // now we know actual incoming period +// if (abs(refclk_period - fbclk_period) > 2) +// begin +// new_m_times_vco_period = refclk_period; +// end +// else if (abs(fbclk_time - refclk_time) <= 2 || (refclk_period - abs(fbclk_time - refclk_time) <= 2)) + if (abs(fbclk_time - refclk_time) <= 5 || (got_first_fbclk && abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5)) + begin + // considered in phase + if (cycles_to_lock == valid_lock_multiplier - 1) + pll_about_to_lock <= 1; + if (cycles_to_lock == valid_lock_multiplier) + begin + if (pll_is_locked === 1'b0) + begin + $display (" Note : Stratix PLL locked to incoming clock"); + $display ("Time: %0t Instance: %m", $time); + end + pll_is_locked = 1; + locked_tmp = 1; + if (l_pll_type == "fast") + locked_tmp = 0; + end + // increment lock counter only if the second part of the above + // time check is NOT true + if (!(abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5)) + begin + cycles_to_lock = cycles_to_lock + 1; + end + + // adjust m_times_vco_period + new_m_times_vco_period = refclk_period; + + end else + begin + // if locked, begin unlock + if (pll_is_locked) + begin + cycles_to_unlock = cycles_to_unlock + 1; + if (cycles_to_unlock == invalid_lock_multiplier) + begin + pll_is_locked = 0; + locked_tmp = 0; + if (l_pll_type == "fast") + locked_tmp = 1; + pll_about_to_lock = 0; + cycles_to_lock = 0; + $display ("Note : Stratix PLL lost lock"); + $display ("Time: %0t Instance: %m", $time); + first_schedule = 1; + schedule_offset = 1; + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 0; + end + end + if (abs(refclk_period - fbclk_period) <= 2) + begin + // frequency is still good + if ($time == fbclk_time && (!phase_adjust_was_scheduled)) + begin + if (abs(fbclk_time - refclk_time) > refclk_period/2) + begin + if (abs(fbclk_time - refclk_time) > 1.5 * refclk_period) + begin + // input clock may have stopped : do nothing + end + else begin + new_m_times_vco_period = m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time)); + vco_period_was_phase_adjusted = 1; + end + end else + begin + new_m_times_vco_period = m_times_vco_period - abs(fbclk_time - refclk_time); + vco_period_was_phase_adjusted = 1; + end + end + end else + begin + new_m_times_vco_period = refclk_period; + phase_adjust_was_scheduled = 0; + end + end + end + + if (quiet_period_violation == 1'b1 || reconfig_err == 1'b1 || scanclr_violation == 1'b1 || scanclr_clk_violation == 1'b1) + begin + locked_tmp = 0; + if (l_pll_type == "fast") + locked_tmp = 1; + end + + refclk_last_value = refclk; + fbclk_last_value = fbclk; +end + + assign clk0_tmp = i_clk0_counter == "l0" ? l0_clk : i_clk0_counter == "l1" ? l1_clk : i_clk0_counter == "g0" ? g0_clk : i_clk0_counter == "g1" ? g1_clk : i_clk0_counter == "g2" ? g2_clk : i_clk0_counter == "g3" ? g3_clk : 'b0; + + assign clk0 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk0_tmp : 'bx; + + dffp ena0_reg ( .D(clkena0_ipd), + .CLRN(1'b1), + .PRN(1'b1), + .ENA(1'b1), + .CLK(!clk0_tmp), + .Q(ena0)); + + assign clk1_tmp = i_clk1_counter == "l0" ? l0_clk : i_clk1_counter == "l1" ? l1_clk : i_clk1_counter == "g0" ? g0_clk : i_clk1_counter == "g1" ? g1_clk : i_clk1_counter == "g2" ? g2_clk : i_clk1_counter == "g3" ? g3_clk : 'b0; + + assign clk1 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk1_tmp : 'bx; + + dffp ena1_reg ( .D(clkena1_ipd), + .CLRN(1'b1), + .PRN(1'b1), + .ENA(1'b1), + .CLK(!clk1_tmp), + .Q(ena1)); + + assign clk2_tmp = i_clk2_counter == "l0" ? l0_clk : i_clk2_counter == "l1" ? l1_clk : i_clk2_counter == "g0" ? g0_clk : i_clk2_counter == "g1" ? g1_clk : i_clk2_counter == "g2" ? g2_clk : i_clk2_counter == "g3" ? g3_clk : 'b0; + + assign clk2 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk2_tmp : 'bx; + + dffp ena2_reg ( .D(clkena2_ipd), + .CLRN(1'b1), + .PRN(1'b1), + .ENA(1'b1), + .CLK(!clk2_tmp), + .Q(ena2)); + + assign clk3_tmp = i_clk3_counter == "l0" ? l0_clk : i_clk3_counter == "l1" ? l1_clk : i_clk3_counter == "g0" ? g0_clk : i_clk3_counter == "g1" ? g1_clk : i_clk3_counter == "g2" ? g2_clk : i_clk3_counter == "g3" ? g3_clk : 'b0; + + assign clk3 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk3_tmp : 'bx; + + dffp ena3_reg ( .D(clkena3_ipd), + .CLRN(1'b1), + .PRN(1'b1), + .ENA(1'b1), + .CLK(!clk3_tmp), + .Q(ena3)); + + assign clk4_tmp = i_clk4_counter == "l0" ? l0_clk : i_clk4_counter == "l1" ? l1_clk : i_clk4_counter == "g0" ? g0_clk : i_clk4_counter == "g1" ? g1_clk : i_clk4_counter == "g2" ? g2_clk : i_clk4_counter == "g3" ? g3_clk : 'b0; + + assign clk4 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk4_tmp : 'bx; + + dffp ena4_reg ( .D(clkena4_ipd), + .CLRN(1'b1), + .PRN(1'b1), + .ENA(1'b1), + .CLK(!clk4_tmp), + .Q(ena4)); + + assign clk5_tmp = i_clk5_counter == "l0" ? l0_clk : i_clk5_counter == "l1" ? l1_clk : i_clk5_counter == "g0" ? g0_clk : i_clk5_counter == "g1" ? g1_clk : i_clk5_counter == "g2" ? g2_clk : i_clk5_counter == "g3" ? g3_clk : 'b0; + + assign clk5 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk5_tmp : 'bx; + + dffp ena5_reg ( .D(clkena5_ipd), + .CLRN(1'b1), + .PRN(1'b1), + .ENA(1'b1), + .CLK(!clk5_tmp), + .Q(ena5)); + + assign extclk0_tmp = i_extclk0_counter == "e0" ? e0_clk : i_extclk0_counter == "e1" ? e1_clk : i_extclk0_counter == "e2" ? e2_clk : i_extclk0_counter == "e3" ? e3_clk : i_extclk0_counter == "g0" ? g0_clk : 'b0; + + assign extclk0 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? extclk0_tmp : 'bx; + + dffp extena0_reg ( .D(extclkena0_ipd), + .CLRN(1'b1), + .PRN(1'b1), + .ENA(1'b1), + .CLK(!extclk0_tmp), + .Q(extena0)); + + assign extclk1_tmp = i_extclk1_counter == "e0" ? e0_clk : i_extclk1_counter == "e1" ? e1_clk : i_extclk1_counter == "e2" ? e2_clk : i_extclk1_counter == "e3" ? e3_clk : i_extclk1_counter == "g0" ? g0_clk : 'b0; + + assign extclk1 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? extclk1_tmp : 'bx; + + dffp extena1_reg ( .D(extclkena1_ipd), + .CLRN(1'b1), + .PRN(1'b1), + .ENA(1'b1), + .CLK(!extclk1_tmp), + .Q(extena1)); + + assign extclk2_tmp = i_extclk2_counter == "e0" ? e0_clk : i_extclk2_counter == "e1" ? e1_clk : i_extclk2_counter == "e2" ? e2_clk : i_extclk2_counter == "e3" ? e3_clk : i_extclk2_counter == "g0" ? g0_clk : 'b0; + + assign extclk2 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? extclk2_tmp : 'bx; + + dffp extena2_reg ( .D(extclkena2_ipd), + .CLRN(1'b1), + .PRN(1'b1), + .ENA(1'b1), + .CLK(!extclk2_tmp), + .Q(extena2)); + + assign extclk3_tmp = i_extclk3_counter == "e0" ? e0_clk : i_extclk3_counter == "e1" ? e1_clk : i_extclk3_counter == "e2" ? e2_clk : i_extclk3_counter == "e3" ? e3_clk : i_extclk3_counter == "g0" ? g0_clk : 'b0; + + assign extclk3 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? extclk3_tmp : 'bx; + + dffp extena3_reg ( .D(extclkena3_ipd), + .CLRN(1'b1), + .PRN(1'b1), + .ENA(1'b1), + .CLK(!extclk3_tmp), + .Q(extena3)); + + assign enable_0 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || pll_about_to_lock == 1'b1 ? enable0_tmp : 'bx; + assign enable_1 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || pll_about_to_lock == 1'b1 ? enable1_tmp : 'bx; + + // ACCELERATE OUTPUTS + and (clk[0], ena0, clk0); + and (clk[1], ena1, clk1); + and (clk[2], ena2, clk2); + and (clk[3], ena3, clk3); + and (clk[4], ena4, clk4); + and (clk[5], ena5, clk5); + + and (extclk[0], extena0, extclk0); + and (extclk[1], extena1, extclk1); + and (extclk[2], extena2, extclk2); + and (extclk[3], extena3, extclk3); + + and (enable0, 1'b1, enable_0); + and (enable1, 1'b1, enable_1); + + and (scandataout, 1'b1, scandataout_tmp); + +endmodule // MF_stratix_pll + +/////////////////////////////////////////////////////////////////////////////// +// +// Module Name : arm_m_cntr +// +// Description : Simulation model for the M counter. This is the +// loop feedback counter for the StratixII PLL. +// +/////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ps / 1 ps +module arm_m_cntr ( clk, + reset, + cout, + initial_value, + modulus, + time_delay); + + // INPUT PORTS + input clk; + input reset; + input [31:0] initial_value; + input [31:0] modulus; + input [31:0] time_delay; + + // OUTPUT PORTS + output cout; + + // INTERNAL VARIABLES AND NETS + integer count; + reg tmp_cout; + reg first_rising_edge; + reg clk_last_value; + reg cout_tmp; + + initial + begin + count = 1; + first_rising_edge = 1; + clk_last_value = 0; + end + + always @(reset or clk) + begin + if (reset) + begin + count = 1; + tmp_cout = 0; + first_rising_edge = 1; + cout_tmp <= tmp_cout; + end + else begin + if (clk == 1 && clk_last_value !== clk && first_rising_edge) + begin + first_rising_edge = 0; + tmp_cout = clk; + cout_tmp <= #(time_delay) tmp_cout; + end + else if (first_rising_edge == 0) + begin + if (count < modulus) + count = count + 1; + else + begin + count = 1; + tmp_cout = ~tmp_cout; + cout_tmp <= #(time_delay) tmp_cout; + end + end + end + clk_last_value = clk; + +// cout_tmp <= #(time_delay) tmp_cout; + end + + and (cout, cout_tmp, 1'b1); + +endmodule // arm_m_cntr + +/////////////////////////////////////////////////////////////////////////////// +// +// Module Name : arm_n_cntr +// +// Description : Simulation model for the N counter. This is the +// input clock divide counter for the StratixII PLL. +// +/////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ps / 1 ps +module arm_n_cntr ( clk, + reset, + cout, + modulus); + + // INPUT PORTS + input clk; + input reset; + input [31:0] modulus; + + // OUTPUT PORTS + output cout; + + // INTERNAL VARIABLES AND NETS + integer count; + reg tmp_cout; + reg first_rising_edge; + reg clk_last_value; + reg cout_tmp; + + initial + begin + count = 1; + first_rising_edge = 1; + clk_last_value = 0; + end + + always @(reset or clk) + begin + if (reset) + begin + count = 1; + tmp_cout = 0; + first_rising_edge = 1; + end + else begin + if (clk == 1 && clk_last_value !== clk && first_rising_edge) + begin + first_rising_edge = 0; + tmp_cout = clk; + end + else if (first_rising_edge == 0) + begin + if (count < modulus) + count = count + 1; + else + begin + count = 1; + tmp_cout = ~tmp_cout; + end + end + end + clk_last_value = clk; + + end + + assign cout = tmp_cout; + +endmodule // arm_n_cntr + +/////////////////////////////////////////////////////////////////////////////// +// +// Module 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. +// +/////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ps / 1 ps +module arm_scale_cntr ( clk, + reset, + cout, + high, + low, + initial_value, + mode, + ph_tap); + + // INPUT PORTS + input clk; + input reset; + input [31:0] high; + input [31:0] low; + input [31:0] initial_value; + input [8*6:1] mode; + input [31:0] ph_tap; + + // OUTPUT PORTS + output cout; + + // INTERNAL VARIABLES AND NETS + reg tmp_cout; + reg first_rising_edge; + reg clk_last_value; + reg init; + integer count; + integer output_shift_count; + reg cout_tmp; + + initial + begin + count = 1; + first_rising_edge = 0; + tmp_cout = 0; + output_shift_count = 1; + end + + always @(clk or reset) + begin + if (init !== 1'b1) + begin + clk_last_value = 0; + init = 1'b1; + end + if (reset) + begin + count = 1; + output_shift_count = 1; + tmp_cout = 0; + first_rising_edge = 0; + end + else if (clk_last_value !== clk) + begin + if (mode == " off") + tmp_cout = 0; + else if (mode == "bypass") + begin + tmp_cout = clk; + first_rising_edge = 1; + end + else if (first_rising_edge == 0) + begin + if (clk == 1) + begin + if (output_shift_count == initial_value) + begin + tmp_cout = clk; + first_rising_edge = 1; + end + else + output_shift_count = output_shift_count + 1; + end + end + else if (output_shift_count < initial_value) + begin + if (clk == 1) + output_shift_count = output_shift_count + 1; + end + else + begin + count = count + 1; + if (mode == " even" && (count == (high*2) + 1)) + tmp_cout = 0; + else if (mode == " odd" && (count == (high*2))) + tmp_cout = 0; + else if (count == (high + low)*2 + 1) + begin + tmp_cout = 1; + count = 1; // reset count + end + end + end + clk_last_value = clk; + cout_tmp <= tmp_cout; + end + + and (cout, cout_tmp, 1'b1); + +endmodule // arm_scale_cntr + + +////////////////////////////////////////////////////////////////////////////// +// +// Module Name : MF_stratixii_pll +// +// Description : Behavioral model for StratixII pll. +// +// 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. +// +////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ps/1 ps +`define WORD_LENGTH 18 + +module MF_stratixii_pll (inclk, + fbin, + ena, + clkswitch, + areset, + pfdena, + scanclk, + scanread, + scanwrite, + scandata, + testin, + clk, + clkbad, + activeclock, + locked, + clkloss, + scandataout, + scandone, + enable0, + enable1, + testupout, + testdownout, + sclkout + ); + + parameter operation_mode = "normal"; + parameter pll_type = "auto"; + parameter compensate_clock = "clk0"; + parameter feedback_source = "clk0"; + parameter qualify_conf_done = "off"; + + parameter test_input_comp_delay_chain_bits = 0; + parameter test_feedback_comp_delay_chain_bits = 0; + + parameter inclk0_input_frequency = 10000; + parameter inclk1_input_frequency = 10000; + + parameter gate_lock_signal = "no"; + parameter gate_lock_counter = 1; + parameter self_reset_on_gated_loss_lock = "off"; + parameter valid_lock_multiplier = 1; + parameter invalid_lock_multiplier = 5; + + parameter switch_over_type = "auto"; + parameter switch_over_on_lossclk = "off"; + parameter switch_over_on_gated_lock = "off"; + parameter switch_over_counter = 1; + parameter enable_switch_over_counter = "on"; + + parameter bandwidth = 0; + parameter bandwidth_type = "auto"; + parameter down_spread = "0.0"; + parameter spread_frequency = 0; + parameter common_rx_tx = "off"; + parameter rx_outclock_resource = "auto"; + parameter use_dc_coupling = "false"; + + parameter clk0_output_frequency = 0; + parameter clk0_multiply_by = 1; + parameter clk0_divide_by = 1; + parameter clk0_phase_shift = "0"; + parameter clk0_duty_cycle = 50; + + parameter clk1_output_frequency = 0; + parameter clk1_multiply_by = 1; + parameter clk1_divide_by = 1; + parameter clk1_phase_shift = "0"; + parameter clk1_duty_cycle = 50; + + parameter clk2_output_frequency = 0; + parameter clk2_multiply_by = 1; + parameter clk2_divide_by = 1; + parameter clk2_phase_shift = "0"; + parameter clk2_duty_cycle = 50; + + parameter clk3_output_frequency = 0; + parameter clk3_multiply_by = 1; + parameter clk3_divide_by = 1; + parameter clk3_phase_shift = "0"; + parameter clk3_duty_cycle = 50; + + parameter clk4_output_frequency = 0; + parameter clk4_multiply_by = 1; + parameter clk4_divide_by = 1; + parameter clk4_phase_shift = "0"; + parameter clk4_duty_cycle = 50; + + parameter clk5_output_frequency = 0; + parameter clk5_multiply_by = 1; + parameter clk5_divide_by = 1; + parameter clk5_phase_shift = "0"; + parameter clk5_duty_cycle = 50; + + parameter pfd_min = 0; + parameter pfd_max = 0; + parameter vco_min = 0; + parameter vco_max = 0; + parameter vco_center = 0; + + // ADVANCED USE PARAMETERS + parameter m_initial = 1; + parameter m = 1; + parameter n = 1; + parameter m2 = 1; + parameter n2 = 1; + parameter ss = 0; + + parameter c0_high = 1; + parameter c0_low = 1; + parameter c0_initial = 1; + parameter c0_mode = "bypass"; + parameter c0_ph = 0; + + parameter c1_high = 1; + parameter c1_low = 1; + parameter c1_initial = 1; + parameter c1_mode = "bypass"; + parameter c1_ph = 0; + + parameter c2_high = 1; + parameter c2_low = 1; + parameter c2_initial = 1; + parameter c2_mode = "bypass"; + parameter c2_ph = 0; + + parameter c3_high = 1; + parameter c3_low = 1; + parameter c3_initial = 1; + parameter c3_mode = "bypass"; + parameter c3_ph = 0; + + parameter c4_high = 1; + parameter c4_low = 1; + parameter c4_initial = 1; + parameter c4_mode = "bypass"; + parameter c4_ph = 0; + + parameter c5_high = 1; + parameter c5_low = 1; + parameter c5_initial = 1; + parameter c5_mode = "bypass"; + parameter c5_ph = 0; + + parameter m_ph = 0; + + parameter clk0_counter = "c0"; + parameter clk1_counter = "c1"; + parameter clk2_counter = "c2"; + parameter clk3_counter = "c3"; + parameter clk4_counter = "c4"; + parameter clk5_counter = "c5"; + + parameter c1_use_casc_in = "off"; + parameter c2_use_casc_in = "off"; + parameter c3_use_casc_in = "off"; + parameter c4_use_casc_in = "off"; + parameter c5_use_casc_in = "off"; + + parameter m_test_source = 5; + parameter c0_test_source = 5; + parameter c1_test_source = 5; + parameter c2_test_source = 5; + parameter c3_test_source = 5; + parameter c4_test_source = 5; + parameter c5_test_source = 5; + + // LVDS mode parameters + parameter enable0_counter = "c0"; + parameter enable1_counter = "c1"; + parameter sclkout0_phase_shift = "0"; + parameter sclkout1_phase_shift = "0"; + + parameter vco_multiply_by = 0; + parameter vco_divide_by = 0; + parameter vco_post_scale = 1; + + parameter charge_pump_current = 0; + parameter loop_filter_r = "1.0"; + parameter loop_filter_c = 1; + + parameter pll_compensation_delay = 0; + parameter simulation_type = "functional"; + + //parameter for stratixii lvds + parameter clk0_phase_shift_num = 0; + parameter clk1_phase_shift_num = 0; + parameter clk2_phase_shift_num = 0; + + parameter clk0_use_even_counter_mode = "off"; + parameter clk1_use_even_counter_mode = "off"; + parameter clk2_use_even_counter_mode = "off"; + parameter clk3_use_even_counter_mode = "off"; + parameter clk4_use_even_counter_mode = "off"; + parameter clk5_use_even_counter_mode = "off"; + + parameter clk0_use_even_counter_value = "off"; + parameter clk1_use_even_counter_value = "off"; + parameter clk2_use_even_counter_value = "off"; + parameter clk3_use_even_counter_value = "off"; + parameter clk4_use_even_counter_value = "off"; + parameter clk5_use_even_counter_value = "off"; + + // INPUT PORTS + input [1:0] inclk; + input fbin; + input ena; + input clkswitch; + input areset; + input pfdena; + input scanclk; + input scanread; + input scanwrite; + input scandata; + input [3:0] testin; + + // OUTPUT PORTS + output [5:0] clk; + output [1:0] clkbad; + output activeclock; + output locked; + output clkloss; + output scandataout; + output scandone; + // lvds specific output ports + output enable0; + output enable1; + output [1:0] sclkout; + // test ports + output testupout; + output testdownout; + + // BUFFER INPUTS + wire inclk0_ipd; + wire inclk1_ipd; + wire ena_ipd; + wire fbin_ipd; + wire clkswitch_ipd; + wire areset_ipd; + wire pfdena_ipd; + wire scanclk_ipd; + wire scanread_ipd; + wire scanwrite_ipd; + wire scandata_ipd; + buf (inclk0_ipd, inclk[0]); + buf (inclk1_ipd, inclk[1]); + buf (ena_ipd, ena); + buf (fbin_ipd, fbin); + buf (clkswitch_ipd, clkswitch); + buf (areset_ipd, areset); + buf (pfdena_ipd, pfdena); + buf (scanclk_ipd, scanclk); + buf (scanread_ipd, scanread); + buf (scanwrite_ipd, scanwrite); + buf (scandata_ipd, scandata); + + + // INTERNAL VARIABLES AND NETS + integer scan_chain_length; + integer i; + integer j; + integer k; + integer x; + integer y; + integer l_index; + integer gate_count; + integer egpp_offset; + integer sched_time; + integer delay_chain; + integer low; + integer high; + integer initial_delay; + integer fbk_phase; + integer fbk_delay; + integer phase_shift[0:7]; + integer last_phase_shift[0:7]; + + integer m_times_vco_period; + integer new_m_times_vco_period; + integer refclk_period; + integer fbclk_period; + integer high_time; + integer low_time; + integer my_rem; + integer tmp_rem; + integer rem; + integer tmp_vco_per; + integer vco_per; + integer offset; + integer temp_offset; + integer cycles_to_lock; + integer cycles_to_unlock; + integer c0_count; + integer c0_initial_count; + integer c1_count; + integer c1_initial_count; + integer loop_xplier; + integer loop_initial; + integer loop_ph; + integer cycle_to_adjust; + integer total_pull_back; + integer pull_back_M; + + time fbclk_time; + time first_fbclk_time; + time refclk_time; + + reg got_first_refclk; + reg got_second_refclk; + reg got_first_fbclk; + reg refclk_last_value; + reg fbclk_last_value; + reg inclk_last_value; + reg pll_is_locked; + reg pll_about_to_lock; + reg locked_tmp; + reg c0_got_first_rising_edge; + reg c1_got_first_rising_edge; + reg vco_c0_last_value; + reg vco_c1_last_value; + reg areset_ipd_last_value; + reg ena_ipd_last_value; + reg pfdena_ipd_last_value; + reg inclk_out_of_range; + reg schedule_vco_last_value; + + reg gate_out; + reg vco_val; + + reg [31:0] m_initial_val; + reg [31:0] m_val[0:1]; + reg [31:0] n_val[0:1]; + reg [31:0] m_delay; + reg [8*6:1] m_mode_val[0:1]; + reg [8*6:1] n_mode_val[0:1]; + + reg [31:0] c_high_val[0:5]; + reg [31:0] c_low_val[0:5]; + reg [8*6:1] c_mode_val[0:5]; + reg [31:0] c_initial_val[0:5]; + integer c_ph_val[0:5]; + + // temporary registers for reprogramming + integer c_ph_val_tmp[0:5]; + reg [31:0] c_high_val_tmp[0:5]; + reg [31:0] c_low_val_tmp[0:5]; + reg [8*6:1] c_mode_val_tmp[0:5]; + + // hold registers for reprogramming + integer c_ph_val_hold[0:5]; + reg [31:0] c_high_val_hold[0:5]; + reg [31:0] c_low_val_hold[0:5]; + reg [8*6:1] c_mode_val_hold[0:5]; + + // old values + reg [31:0] m_val_old[0:1]; + reg [31:0] m_val_tmp[0:1]; + reg [31:0] n_val_old[0:1]; + reg [8*6:1] m_mode_val_old[0:1]; + reg [8*6:1] n_mode_val_old[0:1]; + reg [31:0] c_high_val_old[0:5]; + reg [31:0] c_low_val_old[0:5]; + reg [8*6:1] c_mode_val_old[0:5]; + integer c_ph_val_old[0:5]; + integer m_ph_val_old; + integer m_ph_val_tmp; + + integer cp_curr_old; + integer cp_curr_val; + integer lfc_old; + integer lfc_val; + reg [9*8:1] lfr_val; + reg [9*8:1] lfr_old; + + reg [31:0] m_hi; + reg [31:0] m_lo; + + // ph tap orig values (POF) + integer c_ph_val_orig[0:5]; + integer m_ph_val_orig; + + reg schedule_vco; + reg stop_vco; + reg inclk_n; + + reg [7:0] vco_out; + reg [7:0] vco_out_last_value; + wire inclk_c0; + wire inclk_c1; + wire inclk_c2; + wire inclk_c3; + wire inclk_c4; + wire inclk_c5; + reg inclk_c0_from_vco; + reg inclk_c1_from_vco; + reg inclk_c2_from_vco; + reg inclk_c3_from_vco; + reg inclk_c4_from_vco; + reg inclk_c5_from_vco; + reg inclk_m_from_vco; + reg inclk_sclkout0_from_vco; + reg inclk_sclkout1_from_vco; + + wire inclk_m; + wire clk0_tmp; + wire clk1_tmp; + wire clk2_tmp; + wire clk3_tmp; + wire clk4_tmp; + wire clk5_tmp; + wire ena_pll; + wire n_cntr_inclk; + reg sclkout0_tmp; + reg sclkout1_tmp; + + reg vco_c0; + reg vco_c1; + + wire clk0; + wire clk1; + wire clk2; + wire clk3; + wire clk4; + wire clk5; + wire sclkout0; + wire sclkout1; + + wire c0_clk; + wire c1_clk; + wire c2_clk; + wire c3_clk; + wire c4_clk; + wire c5_clk; + + reg first_schedule; + + wire enable0_tmp; + wire enable1_tmp; + wire enable_0; + wire enable_1; + reg c0_tmp; + reg c1_tmp; + + reg vco_period_was_phase_adjusted; + reg phase_adjust_was_scheduled; + + wire refclk; + wire fbclk; + + wire pllena_reg; + wire test_mode_inclk; + + // for external feedback mode + + reg [31:0] ext_fbk_cntr_high; + reg [31:0] ext_fbk_cntr_low; + reg [31:0] ext_fbk_cntr_modulus; + reg [8*2:1] ext_fbk_cntr; + reg [8*6:1] ext_fbk_cntr_mode; + integer ext_fbk_cntr_ph; + integer ext_fbk_cntr_initial; + integer ext_fbk_cntr_index; + + // variables for clk_switch + reg clk0_is_bad; + reg clk1_is_bad; + reg inclk0_last_value; + reg inclk1_last_value; + reg other_clock_value; + reg other_clock_last_value; + reg primary_clk_is_bad; + reg current_clk_is_bad; + reg external_switch; + reg [8*6:1] current_clock; + reg active_clock; + reg clkloss_tmp; + reg got_curr_clk_falling_edge_after_clkswitch; + + integer clk0_count; + integer clk1_count; + integer switch_over_count; + + wire scandataout_tmp; + reg scandone_tmp; + reg scandone_tmp_last_value; + integer quiet_time; + integer slowest_clk_old; + integer slowest_clk_new; + + reg reconfig_err; + reg error; + time scanclk_last_rising_edge; + time scanread_active_edge; + reg got_first_scanclk; + reg got_first_gated_scanclk; + reg gated_scanclk; + integer scanclk_period; + reg scanclk_last_value; + reg scanread_reg; + reg scanwrite_reg; + reg scanwrite_enabled; + reg scanwrite_last_value; + reg [173:0] scan_data; + reg [173:0] tmp_scan_data; + reg c0_rising_edge_transfer_done; + reg c1_rising_edge_transfer_done; + reg c2_rising_edge_transfer_done; + reg c3_rising_edge_transfer_done; + reg c4_rising_edge_transfer_done; + reg c5_rising_edge_transfer_done; + reg scanread_setup_violation; + integer index; + integer scanclk_cycles; + reg d_msg; + + integer num_output_cntrs; + reg no_warn; + + // INTERNAL PARAMETERS + parameter GPP_SCAN_CHAIN = 174; + parameter FAST_SCAN_CHAIN = 75; + // primary clk is always inclk0 + parameter primary_clock = "inclk0"; + + // internal variables for scaling of multiply_by and divide_by values + integer i_clk0_mult_by; + integer i_clk0_div_by; + integer i_clk1_mult_by; + integer i_clk1_div_by; + integer i_clk2_mult_by; + integer i_clk2_div_by; + integer i_clk3_mult_by; + integer i_clk3_div_by; + integer i_clk4_mult_by; + integer i_clk4_div_by; + integer i_clk5_mult_by; + integer i_clk5_div_by; + integer max_d_value; + integer new_multiplier; + + // internal variables for storing the phase shift number.(used in lvds mode only) + integer i_clk0_phase_shift; + integer i_clk1_phase_shift; + integer i_clk2_phase_shift; + + // user to advanced internal signals + + integer i_m_initial; + integer i_m; + integer i_n; + integer i_m2; + integer i_n2; + integer i_ss; + integer i_c_high[0:5]; + integer i_c_low[0:5]; + integer i_c_initial[0:5]; + integer i_c_ph[0:5]; + reg [8*6:1] i_c_mode[0:5]; + + integer i_vco_min; + integer i_vco_max; + integer i_vco_center; + integer i_pfd_min; + integer i_pfd_max; + integer i_m_ph; + integer m_ph_val; + reg [8*2:1] i_clk5_counter; + reg [8*2:1] i_clk4_counter; + reg [8*2:1] i_clk3_counter; + reg [8*2:1] i_clk2_counter; + reg [8*2:1] i_clk1_counter; + reg [8*2:1] i_clk0_counter; + integer i_charge_pump_current; + integer i_loop_filter_r; + integer max_neg_abs; + integer output_count; + integer new_divisor; + + integer loop_filter_c_arr[0:3]; + integer fpll_loop_filter_c_arr[0:3]; + integer charge_pump_curr_arr[0:15]; + reg [9*8:1] loop_filter_r_arr[0:39]; + + reg pll_in_test_mode; + reg pll_is_in_reset; + + // uppercase to lowercase parameter values + reg [8*`WORD_LENGTH:1] l_operation_mode; + reg [8*`WORD_LENGTH:1] l_pll_type; + reg [8*`WORD_LENGTH:1] l_qualify_conf_done; + reg [8*`WORD_LENGTH:1] l_compensate_clock; + reg [8*`WORD_LENGTH:1] l_scan_chain; + reg [8*`WORD_LENGTH:1] l_primary_clock; + reg [8*`WORD_LENGTH:1] l_gate_lock_signal; + reg [8*`WORD_LENGTH:1] l_switch_over_on_lossclk; + reg [8*`WORD_LENGTH:1] l_switch_over_type; + reg [8*`WORD_LENGTH:1] l_switch_over_on_gated_lock; + reg [8*`WORD_LENGTH:1] l_enable_switch_over_counter; + reg [8*`WORD_LENGTH:1] l_feedback_source; + reg [8*`WORD_LENGTH:1] l_bandwidth_type; + reg [8*`WORD_LENGTH:1] l_simulation_type; + reg [8*`WORD_LENGTH:1] l_enable0_counter; + reg [8*`WORD_LENGTH:1] l_enable1_counter; + + reg init; + + + // finds the closest integer fraction of a given pair of numerator and denominator. + task find_simple_integer_fraction; + input numerator; + input denominator; + input max_denom; + output fraction_num; + output fraction_div; + parameter max_iter = 20; + + integer numerator; + integer denominator; + integer max_denom; + integer fraction_num; + integer fraction_div; + + integer quotient_array[max_iter-1:0]; + integer int_loop_iter; + integer int_quot; + integer m_value; + integer d_value; + integer old_m_value; + integer swap; + + integer loop_iter; + integer num; + integer den; + integer i_max_iter; + + begin + loop_iter = 0; + num = numerator; + den = denominator; + i_max_iter = max_iter; + + while (loop_iter < i_max_iter) + begin + int_quot = num / den; + quotient_array[loop_iter] = int_quot; + num = num - (den*int_quot); + loop_iter=loop_iter+1; + + if ((num == 0) || (max_denom != -1) || (loop_iter == i_max_iter)) + begin + // 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) + begin + m_value = (2*num/den); + end + // calculate the fraction numerator and denominator at this stage + for (int_loop_iter = loop_iter-1; int_loop_iter >= 0; int_loop_iter=int_loop_iter-1) + begin + if (m_value == 0) + begin + m_value = quotient_array[int_loop_iter]; + d_value = 1; + end + else + begin + old_m_value = m_value; + m_value = quotient_array[int_loop_iter]*m_value + d_value; + d_value = old_m_value; + end + end + // if the denominator is less than the maximum denom_value or if there is no restriction save it + if ((d_value <= max_denom) || (max_denom == -1)) + begin + fraction_num = m_value; + fraction_div = d_value; + end + // end the loop if the denomitor has overflown or the numerator is zero (no remainder during this round) + if (((d_value > max_denom) && (max_denom != -1)) || (num == 0)) + begin + i_max_iter = loop_iter; + end + end + // swap the numerator and denominator for the next round + swap = den; + den = num; + num = swap; + end + end + endtask // find_simple_integer_fraction + + // get the absolute value + function integer abs; + input value; + integer value; + begin + if (value < 0) + abs = value * -1; + else abs = value; + end + endfunction + + // find twice the period of the slowest clock + function integer slowest_clk; + input C0, C0_mode, C1, C1_mode, C2, C2_mode, C3, C3_mode, C4, C4_mode, C5, C5_mode, refclk, m_mod; + integer C0, C1, C2, C3, C4, C5; + reg [8*6:1] C0_mode, C1_mode, C2_mode, C3_mode, C4_mode, C5_mode; + integer refclk; + reg [31:0] m_mod; + integer max_modulus; + begin + max_modulus = 1; + if (C0_mode != "bypass" && C0_mode != " off") + max_modulus = C0; + if (C1 > max_modulus && C1_mode != "bypass" && C1_mode != " off") + max_modulus = C1; + if (C2 > max_modulus && C2_mode != "bypass" && C2_mode != " off") + max_modulus = C2; + if (C3 > max_modulus && C3_mode != "bypass" && C3_mode != " off") + max_modulus = C3; + if (C4 > max_modulus && C4_mode != "bypass" && C4_mode != " off") + max_modulus = C4; + if (C5 > max_modulus && C5_mode != "bypass" && C5_mode != " off") + max_modulus = C5; + + slowest_clk = (refclk * max_modulus *2 / m_mod); + end + endfunction + + // count the number of digits in the given integer + function integer count_digit; + input X; + integer X; + integer count, result; + begin + count = 0; + result = X; + while (result != 0) + begin + result = (result / 10); + count = count + 1; + end + + count_digit = count; + end + endfunction + + // reduce the given huge number(X) to Y significant digits + function integer scale_num; + input X, Y; + integer X, Y; + integer count; + integer fac_ten, lc; + begin + fac_ten = 1; + count = count_digit(X); + + for (lc = 0; lc < (count-Y); lc = lc + 1) + fac_ten = fac_ten * 10; + + scale_num = (X / fac_ten); + end + endfunction + + // find the greatest common denominator of X and Y + function integer gcd; + input X,Y; + integer X,Y; + integer L, S, R, G; + begin + if (X < Y) // find which is smaller. + begin + S = X; + L = Y; + end + else + begin + S = Y; + L = X; + end + + R = S; + while ( R > 1) + begin + S = L; + L = R; + R = S % L; // divide bigger number by smaller. + // remainder becomes smaller number. + end + if (R == 0) // if evenly divisible then L is gcd else it is 1. + G = L; + else + G = R; + gcd = G; + end + endfunction + + // find the least common multiple of A1 to A10 + function integer lcm; + input A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P; + integer A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P; + integer M1, M2, M3, M4, M5 , M6, M7, M8, M9, R; + 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) + R = 10; + else if ((M9 <= 10) && (M9 >= 3)) + R = 4 * M9; + else if (M9 > 1000) + R = scale_num(M9, 3); + else + R = M9; + lcm = R; + end + endfunction + + // find the factor of division of the output clock frequency + // compared to the VCO + function integer output_counter_value; + input clk_divide, clk_mult, M, N; + integer clk_divide, clk_mult, M, N; + integer R; + begin + R = (clk_divide * M)/(clk_mult * N); + output_counter_value = R; + end + endfunction + + // find the mode of each of the PLL counters - bypass, even or odd + function [8*6:1] counter_mode; + input duty_cycle; + input output_counter_value; + integer duty_cycle; + integer output_counter_value; + integer half_cycle_high; + reg [8*6:1] R; + begin + half_cycle_high = (2*duty_cycle*output_counter_value)/100; + if (output_counter_value == 1) + R = "bypass"; + else if ((half_cycle_high % 2) == 0) + R = " even"; + else + R = " odd"; + counter_mode = R; + end + endfunction + + // find the number of VCO clock cycles to hold the output clock high + function integer counter_high; + input output_counter_value, duty_cycle; + integer output_counter_value, duty_cycle; + integer half_cycle_high; + integer tmp_counter_high; + integer mode; + begin + half_cycle_high = (2*duty_cycle*output_counter_value)/100; + mode = ((half_cycle_high % 2) == 0); + tmp_counter_high = half_cycle_high/2; + counter_high = tmp_counter_high + !mode; + end + endfunction + + // find the number of VCO clock cycles to hold the output clock low + function integer counter_low; + input output_counter_value, duty_cycle; + integer output_counter_value, duty_cycle, counter_h; + integer half_cycle_high; + integer mode; + integer tmp_counter_high; + begin + half_cycle_high = (2*duty_cycle*output_counter_value)/100; + mode = ((half_cycle_high % 2) == 0); + tmp_counter_high = half_cycle_high/2; + counter_h = tmp_counter_high + !mode; + counter_low = output_counter_value - counter_h; + end + endfunction + + // find the smallest time delay amongst t1 to t10 + function integer mintimedelay; + input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; + integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; + integer m1,m2,m3,m4,m5,m6,m7,m8,m9; + begin + if (t1 < t2) + m1 = t1; + else + m1 = t2; + if (m1 < t3) + m2 = m1; + else + m2 = t3; + if (m2 < t4) + m3 = m2; + else + m3 = t4; + if (m3 < t5) + m4 = m3; + else + m4 = t5; + if (m4 < t6) + m5 = m4; + else + m5 = t6; + if (m5 < t7) + m6 = m5; + else + m6 = t7; + if (m6 < t8) + m7 = m6; + else + m7 = t8; + if (m7 < t9) + m8 = m7; + else + m8 = t9; + if (m8 < t10) + m9 = m8; + else + m9 = t10; + if (m9 > 0) + mintimedelay = m9; + else + mintimedelay = 0; + end + endfunction + + // find the numerically largest negative number, and return its absolute value + function integer maxnegabs; + input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; + integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; + integer m1,m2,m3,m4,m5,m6,m7,m8,m9; + begin + if (t1 < t2) m1 = t1; else m1 = t2; + if (m1 < t3) m2 = m1; else m2 = t3; + if (m2 < t4) m3 = m2; else m3 = t4; + if (m3 < t5) m4 = m3; else m4 = t5; + if (m4 < t6) m5 = m4; else m5 = t6; + if (m5 < t7) m6 = m5; else m6 = t7; + if (m6 < t8) m7 = m6; else m7 = t8; + if (m7 < t9) m8 = m7; else m8 = t9; + if (m8 < t10) m9 = m8; else m9 = t10; + maxnegabs = (m9 < 0) ? 0 - m9 : 0; + end + endfunction + + // adjust the given tap_phase by adding the largest negative number (ph_base) + function integer ph_adjust; + input tap_phase, ph_base; + integer tap_phase, ph_base; + begin + ph_adjust = tap_phase + ph_base; + end + endfunction + + // find the number of VCO clock cycles to wait initially before the first + // rising edge of the output clock + function integer counter_initial; + input tap_phase, m, n; + integer tap_phase, m, n, phase; + begin + if (tap_phase < 0) tap_phase = 0 - tap_phase; + // adding 0.5 for rounding correction (required in order to round + // to the nearest integer instead of truncating) + phase = ((tap_phase * m) / (360 * n)) + 0.5; + counter_initial = phase; + end + endfunction + + // find which VCO phase tap to align the rising edge of the output clock to + function integer counter_ph; + input tap_phase; + input m,n; + integer m,n, phase; + integer tap_phase; + begin + // adding 0.5 for rounding correction + phase = (tap_phase * m / n) + 0.5; + counter_ph = (phase % 360)/45; + end + endfunction + + // convert the given string to length 6 by padding with spaces + function [8*6:1] translate_string; + input [8*6:1] mode; + reg [8*6:1] new_mode; + begin + if (mode == "bypass") + new_mode = "bypass"; + else if (mode == "even") + new_mode = " even"; + else if (mode == "odd") + new_mode = " odd"; + + translate_string = new_mode; + end + endfunction + + // convert string to integer with sign + function integer str2int; + input [8*16:1] s; + + reg [8*16:1] reg_s; + reg [8:1] digit; + reg [8:1] tmp; + integer m, magnitude; + integer sign; + + begin + sign = 1; + magnitude = 0; + reg_s = s; + for (m=1; m<=16; m=m+1) + begin + tmp = reg_s[128:121]; + digit = tmp & 8'b00001111; + reg_s = reg_s << 8; + // Accumulate ascii digits 0-9 only. + if ((tmp>=48) && (tmp<=57)) + magnitude = (magnitude * 10) + digit; + if (tmp == 45) + sign = -1; // Found a '-' character, i.e. number is negative. + end + str2int = sign*magnitude; + end + endfunction + + // this is for stratixii lvds only + // convert phase delay to integer + function integer get_int_phase_shift; + input [8*16:1] s; + input i_phase_shift; + integer i_phase_shift; + + begin + if (i_phase_shift != 0) + begin + get_int_phase_shift = i_phase_shift; + end + else + begin + get_int_phase_shift = str2int(s); + end + end + endfunction + + // calculate the given phase shift (in ps) in terms of degrees + function integer get_phase_degree; + input phase_shift; + integer phase_shift, result; + begin + result = (phase_shift * 360) / inclk0_input_frequency; + // this is to round up the calculation result + if ( result > 0 ) + result = result + 1; + else if ( result < 0 ) + result = result - 1; + else + result = 0; + + // assign the rounded up result + get_phase_degree = result; + end + endfunction + + // convert uppercase parameter values to lowercase + // assumes that the maximum character length of a parameter is 18 + function [8*`WORD_LENGTH:1] alpha_tolower; + input [8*`WORD_LENGTH:1] given_string; + + reg [8*`WORD_LENGTH:1] return_string; + reg [8*`WORD_LENGTH:1] reg_string; + reg [8:1] tmp; + reg [8:1] conv_char; + integer byte_count; + begin + return_string = " "; // initialise strings to spaces + conv_char = " "; + reg_string = given_string; + for (byte_count = `WORD_LENGTH; byte_count >= 1; byte_count = byte_count - 1) + begin + tmp = reg_string[8*`WORD_LENGTH:(8*(`WORD_LENGTH-1)+1)]; + reg_string = reg_string << 8; + if ((tmp >= 65) && (tmp <= 90)) // ASCII number of 'A' is 65, 'Z' is 90 + begin + conv_char = tmp + 32; // 32 is the difference in the position of 'A' and 'a' in the ASCII char set + return_string = {return_string, conv_char}; + end + else + return_string = {return_string, tmp}; + end + + alpha_tolower = return_string; + end + endfunction + + function integer display_msg; + input [8*2:1] cntr_name; + input msg_code; + integer msg_code; + begin + if (msg_code == 1) + $display ("Warning : %s counter switched from BYPASS mode to enabled. PLL may lose lock.", cntr_name); + else if (msg_code == 2) + $display ("Warning : Illegal 1 value for %s counter. Instead, the %s counter should be BYPASSED. Reconfiguration may not work.", cntr_name, cntr_name); + else if (msg_code == 3) + $display ("Warning : Illegal value for counter %s 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.", cntr_name); + else if (msg_code == 4) + $display ("Warning : %s counter switched from enabled to BYPASS mode. PLL may lose lock.", cntr_name); + + display_msg = 1; + end + endfunction + + initial + begin + + // convert string parameter values from uppercase to lowercase, + // as expected in this model + l_operation_mode = alpha_tolower(operation_mode); + l_pll_type = alpha_tolower(pll_type); + l_qualify_conf_done = alpha_tolower(qualify_conf_done); + l_compensate_clock = alpha_tolower(compensate_clock); + l_primary_clock = alpha_tolower(primary_clock); + l_gate_lock_signal = alpha_tolower(gate_lock_signal); + l_switch_over_on_lossclk = alpha_tolower(switch_over_on_lossclk); + l_switch_over_on_gated_lock = alpha_tolower(switch_over_on_gated_lock); + l_enable_switch_over_counter = alpha_tolower(enable_switch_over_counter); + l_switch_over_type = alpha_tolower(switch_over_type); + l_feedback_source = alpha_tolower(feedback_source); + l_bandwidth_type = alpha_tolower(bandwidth_type); + l_simulation_type = alpha_tolower(simulation_type); + l_enable0_counter = alpha_tolower(enable0_counter); + l_enable1_counter = alpha_tolower(enable1_counter); + + // initialize charge_pump_current, and loop_filter tables + loop_filter_c_arr[0] = 57; + loop_filter_c_arr[1] = 16; + loop_filter_c_arr[2] = 36; + loop_filter_c_arr[3] = 5; + + fpll_loop_filter_c_arr[0] = 18; + fpll_loop_filter_c_arr[1] = 13; + fpll_loop_filter_c_arr[2] = 8; + fpll_loop_filter_c_arr[3] = 2; + + charge_pump_curr_arr[0] = 6; + charge_pump_curr_arr[1] = 12; + charge_pump_curr_arr[2] = 30; + charge_pump_curr_arr[3] = 36; + charge_pump_curr_arr[4] = 52; + charge_pump_curr_arr[5] = 57; + charge_pump_curr_arr[6] = 72; + charge_pump_curr_arr[7] = 77; + charge_pump_curr_arr[8] = 92; + charge_pump_curr_arr[9] = 96; + charge_pump_curr_arr[10] = 110; + charge_pump_curr_arr[11] = 114; + charge_pump_curr_arr[12] = 127; + charge_pump_curr_arr[13] = 131; + charge_pump_curr_arr[14] = 144; + charge_pump_curr_arr[15] = 148; + + loop_filter_r_arr[0] = " 1.000000"; + loop_filter_r_arr[1] = " 1.500000"; + loop_filter_r_arr[2] = " 2.000000"; + loop_filter_r_arr[3] = " 2.500000"; + loop_filter_r_arr[4] = " 3.000000"; + loop_filter_r_arr[5] = " 3.500000"; + loop_filter_r_arr[6] = " 4.000000"; + loop_filter_r_arr[7] = " 4.500000"; + loop_filter_r_arr[8] = " 5.000000"; + loop_filter_r_arr[9] = " 5.500000"; + loop_filter_r_arr[10] = " 6.000000"; + loop_filter_r_arr[11] = " 6.500000"; + loop_filter_r_arr[12] = " 7.000000"; + loop_filter_r_arr[13] = " 7.500000"; + loop_filter_r_arr[14] = " 8.000000"; + loop_filter_r_arr[15] = " 8.500000"; + loop_filter_r_arr[16] = " 9.000000"; + loop_filter_r_arr[17] = " 9.500000"; + loop_filter_r_arr[18] = "10.000000"; + loop_filter_r_arr[19] = "10.500000"; + loop_filter_r_arr[20] = "11.000000"; + loop_filter_r_arr[21] = "11.500000"; + loop_filter_r_arr[22] = "12.000000"; + loop_filter_r_arr[23] = "12.500000"; + loop_filter_r_arr[24] = "13.000000"; + loop_filter_r_arr[25] = "13.500000"; + loop_filter_r_arr[26] = "14.000000"; + loop_filter_r_arr[27] = "14.500000"; + loop_filter_r_arr[28] = "15.000000"; + loop_filter_r_arr[29] = "15.500000"; + loop_filter_r_arr[30] = "16.000000"; + loop_filter_r_arr[31] = "16.500000"; + loop_filter_r_arr[32] = "17.000000"; + loop_filter_r_arr[33] = "17.500000"; + loop_filter_r_arr[34] = "18.000000"; + loop_filter_r_arr[35] = "18.500000"; + loop_filter_r_arr[36] = "19.000000"; + loop_filter_r_arr[37] = "19.500000"; + loop_filter_r_arr[38] = "20.000000"; + loop_filter_r_arr[39] = "20.500000"; + + if (m == 0) + begin + i_clk5_counter = "c5" ; + i_clk4_counter = "c4" ; + i_clk3_counter = "c3" ; + i_clk2_counter = "c2" ; + i_clk1_counter = "c1" ; + i_clk0_counter = "c0" ; + end + else begin + i_clk5_counter = alpha_tolower(clk5_counter); + i_clk4_counter = alpha_tolower(clk4_counter); + i_clk3_counter = alpha_tolower(clk3_counter); + i_clk2_counter = alpha_tolower(clk2_counter); + i_clk1_counter = alpha_tolower(clk1_counter); + i_clk0_counter = alpha_tolower(clk0_counter); + end + + // VCO feedback loop settings for external feedback mode + // first find which counter is used for feedback + if (l_operation_mode == "external_feedback") + begin + if (l_feedback_source == "clk0") + ext_fbk_cntr = i_clk0_counter; + else if (l_feedback_source == "clk1") + ext_fbk_cntr = i_clk1_counter; + else if (l_feedback_source == "clk2") + ext_fbk_cntr = i_clk2_counter; + else if (l_feedback_source == "clk3") + ext_fbk_cntr = i_clk3_counter; + else if (l_feedback_source == "clk4") + ext_fbk_cntr = i_clk4_counter; + else if (l_feedback_source == "clk5") + ext_fbk_cntr = i_clk5_counter; + else ext_fbk_cntr = "c0"; + + if (ext_fbk_cntr == "c0") + ext_fbk_cntr_index = 0; + else if (ext_fbk_cntr == "c1") + ext_fbk_cntr_index = 1; + else if (ext_fbk_cntr == "c2") + ext_fbk_cntr_index = 2; + else if (ext_fbk_cntr == "c3") + ext_fbk_cntr_index = 3; + else if (ext_fbk_cntr == "c4") + ext_fbk_cntr_index = 4; + else if (ext_fbk_cntr == "c5") + ext_fbk_cntr_index = 5; + end + + if (m == 0) + begin + + // 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); + + // convert user parameters to advanced + if (((l_pll_type == "fast") || (l_pll_type == "lvds")) && (vco_multiply_by != 0) && (vco_divide_by != 0)) + begin + i_n = vco_divide_by; + i_m = vco_multiply_by; + end + else begin + 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 + + 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); + + if (l_pll_type == "flvds") + begin + // 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 = (clk0_phase_shift_num * new_multiplier); + i_clk1_phase_shift = (clk1_phase_shift_num * new_multiplier); + i_clk2_phase_shift = (clk2_phase_shift_num * new_multiplier); + end + else + begin + i_clk0_phase_shift = get_int_phase_shift(clk0_phase_shift, clk0_phase_shift_num); + i_clk1_phase_shift = get_int_phase_shift(clk1_phase_shift, clk1_phase_shift_num); + i_clk2_phase_shift = get_int_phase_shift(clk2_phase_shift, clk2_phase_shift_num); + end + + 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_c_initial[0] = counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n); + i_c_initial[1] = counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n); + i_c_initial[2] = counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n); + i_c_initial[3] = counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs)), i_m, i_n); + i_c_initial[4] = counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs)), i_m, i_n); + i_c_initial[5] = counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs)), 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_m_ph = counter_ph(get_phase_degree(max_neg_abs), i_m, i_n); + i_m_initial = counter_initial(get_phase_degree(max_neg_abs), i_m, i_n); + + i_c_ph[0] = counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n); + i_c_ph[1] = counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n); + i_c_ph[2] = counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n); + i_c_ph[3] = counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs)), i_m, i_n); + i_c_ph[4] = counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs)), i_m, i_n); + i_c_ph[5] = counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs)), i_m, i_n); + + // in external feedback mode, need to adjust M value to take + // into consideration the external feedback counter value + if (l_operation_mode == "external_feedback") + begin + // if there is a negative phase shift, m_initial can only be 1 + if (max_neg_abs > 0) + i_m_initial = 1; + + if (i_c_mode[ext_fbk_cntr_index] == "bypass") + output_count = 1; + else + output_count = i_c_high[ext_fbk_cntr_index] + i_c_low[ext_fbk_cntr_index]; + + if (i_m > output_count) + i_m = i_m / output_count; + else + begin + new_divisor = gcd(i_m, output_count); + i_m = i_m / new_divisor; + i_n = output_count / new_divisor; + end + end + + end + else + begin // m != 0 + + i_n = n; + i_m = m; + 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(alpha_tolower(c0_mode)); + i_c_mode[1] = translate_string(alpha_tolower(c1_mode)); + i_c_mode[2] = translate_string(alpha_tolower(c2_mode)); + i_c_mode[3] = translate_string(alpha_tolower(c3_mode)); + i_c_mode[4] = translate_string(alpha_tolower(c4_mode)); + i_c_mode[5] = translate_string(alpha_tolower(c5_mode)); + 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_m_ph = m_ph; // default + i_m_initial = m_initial; + + end // user to advanced conversion + + refclk_period = inclk0_input_frequency * i_n; + + m_times_vco_period = refclk_period; + new_m_times_vco_period = refclk_period; + + fbclk_period = 0; + high_time = 0; + low_time = 0; + schedule_vco = 0; + vco_out[7:0] = 8'b0; + fbclk_last_value = 0; + offset = 0; + temp_offset = 0; + got_first_refclk = 0; + got_first_fbclk = 0; + fbclk_time = 0; + first_fbclk_time = 0; + refclk_time = 0; + first_schedule = 1; + sched_time = 0; + vco_val = 0; + c0_got_first_rising_edge = 0; + c1_got_first_rising_edge = 0; + vco_c0_last_value = 0; + c0_count = 2; + c0_initial_count = 1; + c1_count = 2; + c1_initial_count = 1; + c0_tmp = 0; + c1_tmp = 0; + gate_count = 0; + gate_out = 0; + initial_delay = 0; + fbk_phase = 0; + for (i = 0; i <= 7; i = i + 1) + begin + phase_shift[i] = 0; + last_phase_shift[i] = 0; + end + fbk_delay = 0; + inclk_n = 0; + cycle_to_adjust = 0; + m_delay = 0; + vco_c0 = 0; + vco_c1 = 0; + total_pull_back = 0; + pull_back_M = 0; + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 0; + ena_ipd_last_value = 0; + inclk_out_of_range = 0; + scandone_tmp = 0; + schedule_vco_last_value = 0; + + // set initial values for counter parameters + m_initial_val = i_m_initial; + m_val[0] = i_m; + n_val[0] = i_n; + m_ph_val = i_m_ph; + m_ph_val_orig = i_m_ph; + m_ph_val_tmp = i_m_ph; + m_val_tmp[0] = i_m; + + m_val[1] = m2; + n_val[1] = n2; + + if (m_val[0] == 1) + m_mode_val[0] = "bypass"; + else m_mode_val[0] = ""; + if (m_val[1] == 1) + m_mode_val[1] = "bypass"; + if (n_val[0] == 1) + n_mode_val[0] = "bypass"; + if (n_val[1] == 1) + n_mode_val[1] = "bypass"; + + for (i = 0; i < 6; i=i+1) + begin + c_high_val[i] = i_c_high[i]; + c_low_val[i] = i_c_low[i]; + c_initial_val[i] = i_c_initial[i]; + c_mode_val[i] = i_c_mode[i]; + c_ph_val[i] = i_c_ph[i]; + c_high_val_tmp[i] = i_c_high[i]; + c_low_val_tmp[i] = i_c_low[i]; + if (c_mode_val[i] == "bypass") + begin + if (l_pll_type == "fast" || l_pll_type == "lvds") + begin + c_high_val[i] = 5'b10000; + c_low_val[i] = 5'b10000; + c_high_val_tmp[i] = 5'b10000; + c_low_val_tmp[i] = 5'b10000; + end + else begin + c_high_val[i] = 9'b100000000; + c_low_val[i] = 9'b100000000; + c_high_val_tmp[i] = 9'b100000000; + c_low_val_tmp[i] = 9'b100000000; + end + end + + 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 + + lfc_val = loop_filter_c; + lfr_val = loop_filter_r; + cp_curr_val = charge_pump_current; + + i = 0; + j = 0; + inclk_last_value = 0; + + ext_fbk_cntr_ph = 0; + ext_fbk_cntr_initial = 1; + + // initialize clkswitch variables + + clk0_is_bad = 0; + clk1_is_bad = 0; + inclk0_last_value = 0; + inclk1_last_value = 0; + other_clock_value = 0; + other_clock_last_value = 0; + primary_clk_is_bad = 0; + current_clk_is_bad = 0; + external_switch = 0; + current_clock = l_primary_clock; + active_clock = 0; // primary_clk is always inclk0 + if (l_pll_type == "fast") + l_switch_over_type = "manual"; + + if (l_switch_over_type == "manual" && clkswitch_ipd === 1'b1) + begin + current_clock = "inclk1"; + active_clock = 1; + end + clkloss_tmp = 0; + got_curr_clk_falling_edge_after_clkswitch = 0; + clk0_count = 0; + clk1_count = 0; + switch_over_count = 0; + + // initialize reconfiguration variables + // quiet_time + quiet_time = 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], + refclk_period, m_val[0]); + reconfig_err = 0; + error = 0; + scanread_active_edge = 0; + if ((l_pll_type == "fast") || (l_pll_type == "lvds")) + begin + scan_chain_length = FAST_SCAN_CHAIN; + num_output_cntrs = 4; + end + else + begin + scan_chain_length = GPP_SCAN_CHAIN; + num_output_cntrs = 6; + end + scanread_reg = 0; + scanwrite_reg = 0; + scanwrite_enabled = 0; + c0_rising_edge_transfer_done = 0; + c1_rising_edge_transfer_done = 0; + c2_rising_edge_transfer_done = 0; + c3_rising_edge_transfer_done = 0; + c4_rising_edge_transfer_done = 0; + c5_rising_edge_transfer_done = 0; + got_first_scanclk = 0; + got_first_gated_scanclk = 0; + gated_scanclk = 1; + scanread_setup_violation = 0; + index = 0; + + // initialize the scan_chain contents + // CP/LF bits + scan_data[11:0] = 12'b0; + for (i = 0; i <= 3; i = i + 1) + begin + if ((l_pll_type == "fast") || (l_pll_type == "lvds")) + begin + if (fpll_loop_filter_c_arr[i] == loop_filter_c) + scan_data[11:10] = i; + end + else begin + if (loop_filter_c_arr[i] == loop_filter_c) + scan_data[11:10] = i; + end + end + for (i = 0; i <= 15; i = i + 1) + begin + if (charge_pump_curr_arr[i] == charge_pump_current) + scan_data[3:0] = i; + end + for (i = 0; i <= 39; i = i + 1) + begin + if (loop_filter_r_arr[i] == loop_filter_r) + begin + if ((i >= 16) && (i <= 23)) + scan_data[9:4] = i+8; + else if ((i >= 24) && (i <= 31)) + scan_data[9:4] = i+16; + else if (i >= 32) + scan_data[9:4] = i+24; + else + scan_data[9:4] = i; + end + end + + if (l_pll_type == "fast" || l_pll_type == "lvds") + begin + scan_data[21:12] = 10'b0; // M, C3-C0 ph + // C0-C3 high + scan_data[25:22] = c_high_val[0]; + scan_data[35:32] = c_high_val[1]; + scan_data[45:42] = c_high_val[2]; + scan_data[55:52] = c_high_val[3]; + // C0-C3 low + scan_data[30:27] = c_low_val[0]; + scan_data[40:37] = c_low_val[1]; + scan_data[50:47] = c_low_val[2]; + scan_data[60:57] = c_low_val[3]; + // C0-C3 mode + for (i = 0; i < 4; i = i + 1) + begin + if (c_mode_val[i] == " off" || c_mode_val[i] == "bypass") + begin + scan_data[26 + (10*i)] = 1; + if (c_mode_val[i] == " off") + scan_data[31 + (10*i)] = 1; + else + scan_data[31 + (10*i)] = 0; + end + else begin + scan_data[26 + (10*i)] = 0; + if (c_mode_val[i] == " odd") + scan_data[31 + (10*i)] = 1; + else + scan_data[31 + (10*i)] = 0; + end + end + // M + if (m_mode_val[0] == "bypass") + begin + scan_data[66] = 1; + scan_data[71] = 0; + scan_data[65:62] = 4'b0; + scan_data[70:67] = 4'b0; + end + else begin + scan_data[66] = 0; // set BYPASS bit to 0 + scan_data[70:67] = m_val[0]/2; // set M low + if (m_val[0] % 2 == 0) + begin + // M is an even no. : set M high = low, + // set odd/even bit to 0 + scan_data[65:62] = scan_data[70:67]; + scan_data[71] = 0; + end + else begin // M is odd : M high = low + 1 + scan_data[65:62] = (m_val[0]/2) + 1; + scan_data[71] = 1; + end + end + // N + scan_data[73:72] = n_val[0]; + if (n_mode_val[0] == "bypass") + begin + scan_data[74] = 1; + scan_data[73:72] = 2'b0; + end + end + else begin // PLL type is enhanced/auto + scan_data[25:12] = 14'b0; + + // C5-C0 high + scan_data[33:26] = c_high_val[5]; + scan_data[51:44] = c_high_val[4]; + scan_data[69:62] = c_high_val[3]; + scan_data[87:80] = c_high_val[2]; + scan_data[105:98] = c_high_val[1]; + scan_data[123:116] = c_high_val[0]; + // C5-C0 low + scan_data[42:35] = c_low_val[5]; + scan_data[60:53] = c_low_val[4]; + scan_data[78:71] = c_low_val[3]; + scan_data[96:89] = c_low_val[2]; + scan_data[114:107] = c_low_val[1]; + scan_data[132:125] = c_low_val[0]; + + for (i = 5; i >= 0; i = i - 1) + begin + if (c_mode_val[i] == " off" || c_mode_val[i] == "bypass") + begin + scan_data[124 - (18*i)] = 1; + if (c_mode_val[i] == " off") + scan_data[133 - (18*i)] = 1; + else + scan_data[133 - (18*i)] = 0; + end + else begin + scan_data[124 - (18*i)] = 0; + if (c_mode_val[i] == " odd") + scan_data[133 - (18*i)] = 1; + else + scan_data[133 - (18*i)] = 0; + end + end + + scan_data[142:134] = m_val[0]; + scan_data[143] = 0; + scan_data[152:144] = m_val[1]; + scan_data[153] = 0; + if (m_mode_val[0] == "bypass") + begin + scan_data[143] = 1; + scan_data[142:134] = 9'b0; + end + if (m_mode_val[1] == "bypass") + begin + scan_data[153] = 1; + scan_data[152:144] = 9'b0; + end + + scan_data[162:154] = n_val[0]; + scan_data[172:164] = n_val[1]; + if (n_mode_val[0] == "bypass") + begin + scan_data[163] = 1; + scan_data[162:154] = 9'b0; + end + if (n_mode_val[1] == "bypass") + begin + scan_data[173] = 1; + scan_data[172:164] = 9'b0; + end + end + + // now save this counter's parameters + 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]; + + if (ext_fbk_cntr_mode == "bypass") + ext_fbk_cntr_modulus = 1; + else + ext_fbk_cntr_modulus = ext_fbk_cntr_high + ext_fbk_cntr_low; + + l_index = 1; + stop_vco = 0; + cycles_to_lock = 0; + cycles_to_unlock = 0; + locked_tmp = 0; + pll_is_locked = 0; + pll_about_to_lock = 0; + no_warn = 1'b0; + + // check if pll is in test mode + if (m_test_source != 5 || c0_test_source != 5 || c1_test_source != 5 || c2_test_source != 5 || c3_test_source != 5 || c4_test_source != 5 || c5_test_source != 5) + pll_in_test_mode = 1'b1; + else + pll_in_test_mode = 1'b0; + + + pll_is_in_reset = 0; + end + + always @(clkswitch_ipd) + begin + if (clkswitch_ipd === 1'b1 && l_switch_over_type == "auto") + external_switch = 1; + else if (l_switch_over_type == "manual") + begin + if (clkswitch_ipd === 1'b1) + begin + current_clock = "inclk1"; + active_clock = 1; + inclk_n = inclk1_ipd; + end + else if (clkswitch_ipd === 1'b0) + begin + current_clock = "inclk0"; + active_clock = 0; + inclk_n = inclk0_ipd; + end + end + end + + always @(inclk0_ipd or inclk1_ipd) + begin + // save the inclk event value + if (inclk0_ipd !== inclk0_last_value) + begin + if (current_clock !== "inclk0") + other_clock_value = inclk0_ipd; + end + if (inclk1_ipd !== inclk1_last_value) + begin + if (current_clock !== "inclk1") + other_clock_value = inclk1_ipd; + end + + // check if either input clk is bad + if (inclk0_ipd === 1'b1 && inclk0_ipd !== inclk0_last_value) + begin + clk0_count = clk0_count + 1; + clk0_is_bad = 0; + clk1_count = 0; + if (clk0_count > 2) + begin + // no event on other clk for 2 cycles + clk1_is_bad = 1; + if (current_clock == "inclk1") + current_clk_is_bad = 1; + end + end + if (inclk1_ipd === 1'b1 && inclk1_ipd !== inclk1_last_value) + begin + clk1_count = clk1_count + 1; + clk1_is_bad = 0; + clk0_count = 0; + if (clk1_count > 2) + begin + // no event on other clk for 2 cycles + clk0_is_bad = 1; + if (current_clock == "inclk0") + current_clk_is_bad = 1; + end + end + + // check if the bad clk is the primary clock, which is always clk0 + if (clk0_is_bad == 1'b1) + primary_clk_is_bad = 1; + else + primary_clk_is_bad = 0; + + // actual switching -- manual switch + if ((inclk0_ipd !== inclk0_last_value) && current_clock == "inclk0") + begin + if (external_switch == 1'b1) + begin + if (!got_curr_clk_falling_edge_after_clkswitch) + begin + if (inclk0_ipd === 1'b0) + got_curr_clk_falling_edge_after_clkswitch = 1; + inclk_n = inclk0_ipd; + end + end + else inclk_n = inclk0_ipd; + end + if ((inclk1_ipd !== inclk1_last_value) && current_clock == "inclk1") + begin + if (external_switch == 1'b1) + begin + if (!got_curr_clk_falling_edge_after_clkswitch) + begin + if (inclk1_ipd === 1'b0) + got_curr_clk_falling_edge_after_clkswitch = 1; + inclk_n = inclk1_ipd; + end + end + else inclk_n = inclk1_ipd; + end + + // actual switching -- automatic switch + if ((other_clock_value == 1'b1) && (other_clock_value != other_clock_last_value) && (l_switch_over_on_lossclk == "on") && l_enable_switch_over_counter == "on" && primary_clk_is_bad) + switch_over_count = switch_over_count + 1; + + if ((other_clock_value == 1'b0) && (other_clock_value != other_clock_last_value)) + begin + if ((external_switch && (got_curr_clk_falling_edge_after_clkswitch || current_clk_is_bad)) || (l_switch_over_on_lossclk == "on" && primary_clk_is_bad && l_pll_type !== "fast" && l_pll_type !== "lvds" && ((l_enable_switch_over_counter == "off" || switch_over_count == switch_over_counter)))) + begin + got_curr_clk_falling_edge_after_clkswitch = 0; + if (current_clock == "inclk0") + current_clock = "inclk1"; + else + current_clock = "inclk0"; + active_clock = ~active_clock; + switch_over_count = 0; + external_switch = 0; + current_clk_is_bad = 0; + end + end + + if (l_switch_over_on_lossclk == "on" && (clkswitch_ipd != 1'b1)) + begin + if (primary_clk_is_bad) + clkloss_tmp = 1; + else + clkloss_tmp = 0; + end + else clkloss_tmp = clkswitch_ipd; + + inclk0_last_value = inclk0_ipd; + inclk1_last_value = inclk1_ipd; + other_clock_last_value = other_clock_value; + + end + + and (clkbad[0], clk0_is_bad, 1'b1); + and (clkbad[1], clk1_is_bad, 1'b1); + and (activeclock, active_clock, 1'b1); + and (clkloss, clkloss_tmp, 1'b1); + + MF_pll_reg ena_reg ( .clk(!inclk_n), + .ena(1'b1), + .d(ena_ipd), + .clrn(1'b1), + .prn(1'b1), + .q(pllena_reg)); + + and (test_mode_inclk, inclk_n, pllena_reg); + assign n_cntr_inclk = (pll_in_test_mode === 1'b1) ? test_mode_inclk : inclk_n; + assign ena_pll = (pll_in_test_mode === 1'b1) ? pllena_reg : ena_ipd; + + assign inclk_m = (m_test_source == 0) ? n_cntr_inclk : l_operation_mode == "external_feedback" ? (l_feedback_source == "clk0" ? clk0_tmp : + l_feedback_source == "clk1" ? clk1_tmp : + l_feedback_source == "clk2" ? clk2_tmp : + l_feedback_source == "clk3" ? clk3_tmp : + l_feedback_source == "clk4" ? clk4_tmp : + l_feedback_source == "clk5" ? clk5_tmp : 'b0) : + inclk_m_from_vco; + + + arm_m_cntr m1 (.clk(inclk_m), + .reset(areset_ipd || (!ena_pll) || stop_vco), + .cout(fbclk), + .initial_value(m_initial_val), + .modulus(m_val[0]), + .time_delay(m_delay)); + + arm_n_cntr n1 (.clk(n_cntr_inclk), + .reset(areset_ipd), + .cout(refclk), + .modulus(n_val[0])); + + + + always @(vco_out) + begin + // check which VCO TAP has event + for (x = 0; x <= 7; x = x + 1) + begin + if (vco_out[x] !== vco_out_last_value[x]) + begin + if (c_ph_val[0] == x) + begin + inclk_c0_from_vco <= vco_out[x]; + if (enable0_counter == "c0") + inclk_sclkout0_from_vco <= vco_out[x]; + if (enable1_counter == "c0") + inclk_sclkout1_from_vco <= vco_out[x]; + end + if (c_ph_val[1] == x) + begin + inclk_c1_from_vco <= vco_out[x]; + if (enable0_counter == "c1") + inclk_sclkout0_from_vco <= vco_out[x]; + if (enable1_counter == "c1") + inclk_sclkout1_from_vco <= vco_out[x]; + end + if (c_ph_val[2] == x) + inclk_c2_from_vco <= vco_out[x]; + if (c_ph_val[3] == x) + inclk_c3_from_vco <= vco_out[x]; + if (c_ph_val[4] == x) + inclk_c4_from_vco <= vco_out[x]; + if (c_ph_val[5] == x) + inclk_c5_from_vco <= vco_out[x]; + if (m_ph_val == x) + inclk_m_from_vco <= vco_out[x]; + end + end + if (scanwrite_enabled === 1'b1) + begin + for (x = 0; x <= 7; x = x + 1) + begin + if ((vco_out[x] === 1'b0) && (vco_out[x] !== vco_out_last_value[x])) + begin + for (y = 0; y <= 5; y = y + 1) + begin + if (c_ph_val[y] == x) + c_ph_val[y] <= c_ph_val_tmp[y]; + end + if (m_ph_val == x) + m_ph_val <= m_ph_val_tmp; + end + end + end + + // reset all counter phase tap values to POF programmed values + if (areset_ipd === 1'b1) + begin + m_ph_val <= m_ph_val_orig; + m_ph_val_tmp <= m_ph_val_orig; + for (i=0; i<= 5; i=i+1) + begin + c_ph_val[i] <= c_ph_val_orig[i]; + c_ph_val_tmp[i] <= c_ph_val_orig[i]; + end + end + + vco_out_last_value = vco_out; + end + + always @(inclk_sclkout0_from_vco) + begin + sclkout0_tmp <= inclk_sclkout0_from_vco; + end + always @(inclk_sclkout1_from_vco) + begin + sclkout1_tmp <= inclk_sclkout1_from_vco; + end + + assign inclk_c0 = (c0_test_source == 0) ? n_cntr_inclk : (c0_test_source == 1) ? refclk : inclk_c0_from_vco; + + arm_scale_cntr c0 (.clk(inclk_c0), + .reset(areset_ipd || (!ena_pll) || stop_vco), + .cout(c0_clk), + .high(c_high_val[0]), + .low(c_low_val[0]), + .initial_value(c_initial_val[0]), + .mode(c_mode_val[0]), + .ph_tap(c_ph_val[0])); + + always @(posedge c0_clk) + begin + if (scanwrite_enabled == 1'b1) + begin + c_high_val_hold[0] <= c_high_val_tmp[0]; + c_mode_val_hold[0] <= c_mode_val_tmp[0]; + c_high_val[0] <= c_high_val_hold[0]; + c_mode_val[0] <= c_mode_val_hold[0]; + c0_rising_edge_transfer_done = 1; + end + end + always @(negedge c0_clk) + begin + if (c0_rising_edge_transfer_done) + begin + c_low_val_hold[0] <= c_low_val_tmp[0]; + c_low_val[0] <= c_low_val_hold[0]; + end + end + + assign inclk_c1 = (c1_test_source == 0) ? n_cntr_inclk : (c1_test_source == 2) ? fbclk : (c1_use_casc_in == "on") ? c0_clk : inclk_c1_from_vco; + + arm_scale_cntr c1 (.clk(inclk_c1), + .reset(areset_ipd || (!ena_pll) || stop_vco), + .cout(c1_clk), + .high(c_high_val[1]), + .low(c_low_val[1]), + .initial_value(c_initial_val[1]), + .mode(c_mode_val[1]), + .ph_tap(c_ph_val[1])); + + always @(posedge c1_clk) + begin + if (scanwrite_enabled == 1'b1) + begin + c_high_val_hold[1] <= c_high_val_tmp[1]; + c_mode_val_hold[1] <= c_mode_val_tmp[1]; + c_high_val[1] <= c_high_val_hold[1]; + c_mode_val[1] <= c_mode_val_hold[1]; + c1_rising_edge_transfer_done = 1; + end + end + always @(negedge c1_clk) + begin + if (c1_rising_edge_transfer_done) + begin + c_low_val_hold[1] <= c_low_val_tmp[1]; + c_low_val[1] <= c_low_val_hold[1]; + end + end + + assign inclk_c2 = (c2_test_source == 0) ? n_cntr_inclk : (c2_use_casc_in == "on") ? c1_clk : inclk_c2_from_vco; + + arm_scale_cntr c2 (.clk(inclk_c2), + .reset(areset_ipd || (!ena_pll) || stop_vco), + .cout(c2_clk), + .high(c_high_val[2]), + .low(c_low_val[2]), + .initial_value(c_initial_val[2]), + .mode(c_mode_val[2]), + .ph_tap(c_ph_val[2])); + + always @(posedge c2_clk) + begin + if (scanwrite_enabled == 1'b1) + begin + c_high_val_hold[2] <= c_high_val_tmp[2]; + c_mode_val_hold[2] <= c_mode_val_tmp[2]; + c_high_val[2] <= c_high_val_hold[2]; + c_mode_val[2] <= c_mode_val_hold[2]; + c2_rising_edge_transfer_done = 1; + end + end + always @(negedge c2_clk) + begin + if (c2_rising_edge_transfer_done) + begin + c_low_val_hold[2] <= c_low_val_tmp[2]; + c_low_val[2] <= c_low_val_hold[2]; + end + end + + assign inclk_c3 = (c3_test_source == 0) ? n_cntr_inclk : (c3_use_casc_in == "on") ? c2_clk : inclk_c3_from_vco; + arm_scale_cntr c3 (.clk(inclk_c3), + .reset(areset_ipd || (!ena_pll) || stop_vco), + .cout(c3_clk), + .high(c_high_val[3]), + .low(c_low_val[3]), + .initial_value(c_initial_val[3]), + .mode(c_mode_val[3]), + .ph_tap(c_ph_val[3])); + + always @(posedge c3_clk) + begin + if (scanwrite_enabled == 1'b1) + begin + c_high_val_hold[3] <= c_high_val_tmp[3]; + c_mode_val_hold[3] <= c_mode_val_tmp[3]; + c_high_val[3] <= c_high_val_hold[3]; + c_mode_val[3] <= c_mode_val_hold[3]; + c3_rising_edge_transfer_done = 1; + end + end + always @(negedge c3_clk) + begin + if (c3_rising_edge_transfer_done) + begin + c_low_val_hold[3] <= c_low_val_tmp[3]; + c_low_val[3] <= c_low_val_hold[3]; + end + end + + assign inclk_c4 = (c4_test_source == 0) ? n_cntr_inclk : (c4_use_casc_in == "on") ? c3_clk : inclk_c4_from_vco; + arm_scale_cntr c4 (.clk(inclk_c4), + .reset(areset_ipd || (!ena_pll) || stop_vco), + .cout(c4_clk), + .high(c_high_val[4]), + .low(c_low_val[4]), + .initial_value(c_initial_val[4]), + .mode(c_mode_val[4]), + .ph_tap(c_ph_val[4])); + + always @(posedge c4_clk) + begin + if (scanwrite_enabled == 1'b1) + begin + c_high_val_hold[4] <= c_high_val_tmp[4]; + c_mode_val_hold[4] <= c_mode_val_tmp[4]; + c_high_val[4] <= c_high_val_hold[4]; + c_mode_val[4] <= c_mode_val_hold[4]; + c4_rising_edge_transfer_done = 1; + end + end + always @(negedge c4_clk) + begin + if (c4_rising_edge_transfer_done) + begin + c_low_val_hold[4] <= c_low_val_tmp[4]; + c_low_val[4] <= c_low_val_hold[4]; + end + end + + assign inclk_c5 = (c5_test_source == 0) ? n_cntr_inclk : (c5_use_casc_in == "on") ? c4_clk : inclk_c5_from_vco; + arm_scale_cntr c5 (.clk(inclk_c5), + .reset(areset_ipd || (!ena_pll) || stop_vco), + .cout(c5_clk), + .high(c_high_val[5]), + .low(c_low_val[5]), + .initial_value(c_initial_val[5]), + .mode(c_mode_val[5]), + .ph_tap(c_ph_val[5])); + + always @(posedge c5_clk) + begin + if (scanwrite_enabled == 1'b1) + begin + c_high_val_hold[5] <= c_high_val_tmp[5]; + c_mode_val_hold[5] <= c_mode_val_tmp[5]; + c_high_val[5] <= c_high_val_hold[5]; + c_mode_val[5] <= c_mode_val_hold[5]; + c5_rising_edge_transfer_done = 1; + end + end + always @(negedge c5_clk) + begin + if (c5_rising_edge_transfer_done) + begin + c_low_val_hold[5] <= c_low_val_tmp[5]; + c_low_val[5] <= c_low_val_hold[5]; + end + end + + always @(vco_out[c_ph_val[0]] or posedge areset_ipd or negedge ena_pll or stop_vco) + begin + if (areset_ipd == 1'b1 || ena_pll == 1'b0 || stop_vco == 1'b1) + begin + c0_count = 2; + c0_initial_count = 1; + c0_got_first_rising_edge = 0; + + end + else begin + if (c0_got_first_rising_edge == 1'b0) + begin + if (vco_out[c_ph_val[0]] == 1'b1 && vco_out[c_ph_val[0]] != vco_c0_last_value) + begin + if (c0_initial_count == c_initial_val[0]) + c0_got_first_rising_edge = 1; + else + c0_initial_count = c0_initial_count + 1; + end + end + else if (vco_out[c_ph_val[0]] != vco_c0_last_value) + begin + c0_count = c0_count + 1; + if (c0_count == (c_high_val[0] + c_low_val[0]) * 2) + c0_count = 1; + end + if (vco_out[c_ph_val[0]] == 1'b0 && vco_out[c_ph_val[0]] != vco_c0_last_value) + begin + if (c0_count == 1) + begin + c0_tmp = 1; + c0_got_first_rising_edge = 0; + end + else c0_tmp = 0; + end + end + vco_c0_last_value = vco_out[c_ph_val[0]]; + end + + always @(vco_out[c_ph_val[1]] or posedge areset_ipd or negedge ena_pll or stop_vco) + begin + if (areset_ipd == 1'b1 || ena_pll == 1'b0 || stop_vco == 1'b1) + begin + c1_count = 2; + c1_initial_count = 1; + c1_got_first_rising_edge = 0; + end + else begin + if (c1_got_first_rising_edge == 1'b0) + begin + if (vco_out[c_ph_val[1]] == 1'b1 && vco_out[c_ph_val[1]] != vco_c1_last_value) + begin + if (c1_initial_count == c_initial_val[1]) + c1_got_first_rising_edge = 1; + else + c1_initial_count = c1_initial_count + 1; + end + end + else if (vco_out[c_ph_val[1]] != vco_c1_last_value) + begin + c1_count = c1_count + 1; + if (c1_count == (c_high_val[1] + c_low_val[1]) * 2) + c1_count = 1; + end + if (vco_out[c_ph_val[1]] == 1'b0 && vco_out[c_ph_val[1]] != vco_c1_last_value) + begin + if (c1_count == 1) + begin + c1_tmp = 1; + c1_got_first_rising_edge = 0; + end + else c1_tmp = 0; + end + end + vco_c1_last_value = vco_out[c_ph_val[1]]; + end + + assign enable0_tmp = (l_enable0_counter == "c0") ? c0_tmp : c1_tmp; + assign enable1_tmp = (l_enable1_counter == "c0") ? c0_tmp : c1_tmp; + + always @ (inclk_n or ena_pll or areset_ipd) + begin + if (areset_ipd == 1'b1 || ena_pll == 1'b0) + begin + gate_count = 0; + gate_out = 0; + end + else if (inclk_n == 'b1 && inclk_last_value != inclk_n) + begin + gate_count = gate_count + 1; + if (gate_count == gate_lock_counter) + gate_out = 1; + end + inclk_last_value = inclk_n; + end + + assign locked = (l_gate_lock_signal == "yes") ? gate_out && locked_tmp : locked_tmp; + + always @(posedge scanread_ipd) + begin + scanread_active_edge = $time; + end + + always @ (scanclk_ipd) + begin + if (scanclk_ipd === 1'b0 && scanclk_last_value === 1'b1) + begin + // enable scanwrite on falling edge + scanwrite_enabled <= scanwrite_reg; + end + if (scanread_reg === 1'b1) + gated_scanclk <= scanclk_ipd && scanread_reg; + else + gated_scanclk <= 1'b1; + if (scanclk_ipd === 1'b1 && scanclk_last_value === 1'b0) + begin + // register scanread and scanwrite + scanread_reg <= scanread_ipd; + scanwrite_reg <= scanwrite_ipd; + + if (got_first_scanclk) + scanclk_period = $time - scanclk_last_rising_edge; + else begin + got_first_scanclk = 1; + end + // reset got_first_scanclk on falling edge of scanread_reg + if (scanread_ipd == 1'b0 && scanread_reg == 1'b1) + begin + got_first_scanclk = 0; + got_first_gated_scanclk = 0; + end + + scanclk_last_rising_edge = $time; + end + scanclk_last_value = scanclk_ipd; + end + + always @(posedge gated_scanclk) + begin + if ($time > 0) + begin + if (!got_first_gated_scanclk) + begin + got_first_gated_scanclk = 1; +// if ($time - scanread_active_edge < scanclk_period) +// begin +// scanread_setup_violation = 1; +// $display("Warning : SCANREAD must go high at least one cycle before SCANDATA is read in."); +// $display ("Time: %0t Instance: %m", $time); +// end + end + for (j = scan_chain_length-1; j >= 1; j = j - 1) + begin + scan_data[j] = scan_data[j - 1]; + end + scan_data[0] <= scandata_ipd; + end + end + + assign scandataout_tmp = (l_pll_type == "fast" || l_pll_type == "lvds") ? scan_data[FAST_SCAN_CHAIN-1] : scan_data[GPP_SCAN_CHAIN-1]; + + always @(posedge scandone_tmp) + begin + if (reconfig_err == 1'b0) + begin + $display("NOTE : PLL Reprogramming completed with the following values (Values in parantheses are original values) : "); + $display ("Time: %0t Instance: %m", $time); + + $display(" N modulus = %0d (%0d) ", n_val[0], n_val_old[0]); + $display(" M modulus = %0d (%0d) ", m_val[0], m_val_old[0]); + $display(" M ph_tap = %0d (%0d) ", m_ph_val, m_ph_val_old); + if (ss > 0) + begin + $display(" M2 modulus = %0d (%0d) ", m_val[1], m_val_old[1]); + $display(" N2 modulus = %0d (%0d) ", n_val[1], n_val_old[1]); + end + + for (i = 0; i < num_output_cntrs; i=i+1) + begin + $display(" C%0d high = %0d (%0d), C%0d low = %0d (%0d), C%0d mode = %s (%s), C%0d phase tap = %0d (%0d)", i, c_high_val[i], c_high_val_old[i], i, c_low_val_tmp[i], c_low_val_old[i], i, c_mode_val[i], c_mode_val_old[i], i, c_ph_val[i], c_ph_val_old[i]); + end + + // display Charge pump and loop filter values + $display (" Charge Pump Current (uA) = %0d (%0d) ", cp_curr_val, cp_curr_old); + $display (" Loop Filter Capacitor (pF) = %0d (%0d) ", lfc_val, lfc_old); + $display (" Loop Filter Resistor (Kohm) = %s (%s) ", lfr_val, lfr_old); + end + else begin + $display("Warning : Errors were encountered during PLL reprogramming. Please refer to error/warning messages above."); + $display ("Time: %0t Instance: %m", $time); + end + end + + always @(scanwrite_enabled) + begin + if (scanwrite_enabled === 1'b0 && scanwrite_last_value === 1'b1) + begin + // falling edge : deassert scandone + scandone_tmp <= #(1.5*scanclk_period) 1'b0; + // reset counter transfer flags + c0_rising_edge_transfer_done = 0; + c1_rising_edge_transfer_done = 0; + c2_rising_edge_transfer_done = 0; + c3_rising_edge_transfer_done = 0; + c4_rising_edge_transfer_done = 0; + c5_rising_edge_transfer_done = 0; + end + if (scanwrite_enabled === 1'b1 && scanwrite_last_value !== scanwrite_enabled) + begin + + $display ("NOTE : PLL Reprogramming initiated ...."); + $display ("Time: %0t Instance: %m", $time); + + error = 0; + reconfig_err = 0; + scanread_setup_violation = 0; + + // make temp. copy of scan_data for processing + tmp_scan_data = scan_data; + + // save old values + cp_curr_old = cp_curr_val; + lfc_old = lfc_val; + lfr_old = lfr_val; + + // CP + // Bits 0-3 : all values are legal + cp_curr_val = charge_pump_curr_arr[scan_data[3:0]]; + + // LF Resistance : bits 4-9 + // values from 010000 - 010111, 100000 - 100111, + // 110000- 110111 are illegal + if (((tmp_scan_data[9:4] >= 6'b010000) && (tmp_scan_data[9:4] <= 6'b010111)) || + ((tmp_scan_data[9:4] >= 6'b100000) && (tmp_scan_data[9:4] <= 6'b100111)) || + ((tmp_scan_data[9:4] >= 6'b110000) && (tmp_scan_data[9:4] <= 6'b110111))) + begin + $display ("Illegal bit settings for Loop Filter Resistance. Legal bit values range from 000000 to 001111, 011000 to 011111, 101000 to 101111 and 111000 to 111111. Reconfiguration may not work."); + reconfig_err = 1; + end + else begin + i = scan_data[9:4]; + if (i >= 56 ) + i = i - 24; + else if ((i >= 40) && (i <= 47)) + i = i - 16; + else if ((i >= 24) && (i <= 31)) + i = i - 8; + lfr_val = loop_filter_r_arr[i]; + end + + // LF Capacitance : bits 10,11 : all values are legal + if ((l_pll_type == "fast") || (l_pll_type == "lvds")) + lfc_val = fpll_loop_filter_c_arr[scan_data[11:10]]; + else + lfc_val = loop_filter_c_arr[scan_data[11:10]]; + + // save old values for display info. + for (i=0; i<=1; i=i+1) + begin + m_val_old[i] = m_val[i]; + n_val_old[i] = n_val[i]; + m_mode_val_old[i] = m_mode_val[i]; + n_mode_val_old[i] = n_mode_val[i]; + end + m_ph_val_old = m_ph_val; + for (i=0; i<=5; i=i+1) + begin + c_high_val_old[i] = c_high_val[i]; + c_low_val_old[i] = c_low_val[i]; + c_ph_val_old[i] = c_ph_val[i]; + c_mode_val_old[i] = c_mode_val[i]; + end + + // first the M counter phase : bit order same for fast and GPP + if (scan_data[12] == 1'b0) + begin + // do nothing + end + else if (scan_data[12] === 1'b1 && scan_data[13] === 1'b1) + begin + m_ph_val_tmp = m_ph_val_tmp + 1; + if (m_ph_val_tmp > 7) + m_ph_val_tmp = 0; + end + else if (scan_data[12] === 1'b1 && scan_data[13] === 1'b0) + begin + m_ph_val_tmp = m_ph_val_tmp - 1; + if (m_ph_val_tmp < 0) + m_ph_val_tmp = 7; + end + else begin + $display ("Warning : Illegal bit settings for M counter phase tap. Reconfiguration may not work."); + reconfig_err = 1; + end + + // read the fast PLL bits. + if (l_pll_type == "fast" || l_pll_type == "lvds") + begin + // C3-C0 phase bits + for (i = 3; i >= 0; i=i-1) + begin + if (tmp_scan_data[14] == 1'b0) + begin + // do nothing + end + else if (tmp_scan_data[14] === 1'b1) + begin + if (tmp_scan_data[15] === 1'b1) + begin + c_ph_val_tmp[i] = c_ph_val_tmp[i] + 1; + if (c_ph_val_tmp[i] > 7) + c_ph_val_tmp[i] = 0; + end + else if (tmp_scan_data[15] === 1'b0) + begin + c_ph_val_tmp[i] = c_ph_val_tmp[i] - 1; + if (c_ph_val_tmp[i] < 0) + c_ph_val_tmp[i] = 7; + end + end + tmp_scan_data = tmp_scan_data >> 2; + end + // C0-C3 counter moduli + tmp_scan_data = scan_data; + for (i = 0; i < 4; i=i+1) + begin + if (tmp_scan_data[26] == 1'b1) + begin + c_mode_val_tmp[i] = "bypass"; + if (tmp_scan_data[31] === 1'b1) + begin + c_mode_val_tmp[i] = " off"; + $display("Warning : The specified bit settings will turn OFF the C%0d counter. It cannot be turned on unless the part is re-initialized.", i); + end + end + else if (tmp_scan_data[31] == 1'b1) + c_mode_val_tmp[i] = " odd"; + else + c_mode_val_tmp[i] = " even"; + if (tmp_scan_data[25:22] === 4'b0000) + c_high_val_tmp[i] = 5'b10000; + else + c_high_val_tmp[i] = tmp_scan_data[25:22]; + if (tmp_scan_data[30:27] === 4'b0000) + c_low_val_tmp[i] = 5'b10000; + else + c_low_val_tmp[i] = tmp_scan_data[30:27]; + + tmp_scan_data = tmp_scan_data >> 10; + end + // M + error = 0; + // some temporary storage + if (scan_data[65:62] == 4'b0000) + m_hi = 5'b10000; + else + m_hi = scan_data[65:62]; + + if (scan_data[70:67] == 4'b0000) + m_lo = 5'b10000; + else + m_lo = scan_data[70:67]; + + m_val_tmp[0] = m_hi + m_lo; + if (scan_data[66] === 1'b1) + begin + if (scan_data[71] === 1'b1) + begin + // this will turn off the M counter : error + reconfig_err = 1; + error = 1; + $display ("The specified bit settings will turn OFF the M counter. This is illegal. Reconfiguration may not work."); + end + else begin + // M counter is being bypassed + if (m_mode_val[0] !== "bypass") + begin + // Mode is switched : give warning + d_msg = display_msg(" M", 4); + end + m_val_tmp[0] = 32'b1; + m_mode_val[0] = "bypass"; + end + end + else begin + if (m_mode_val[0] === "bypass") + begin + // Mode is switched : give warning + d_msg = display_msg(" M", 1); + end + m_mode_val[0] = ""; + if (scan_data[71] === 1'b1) + begin + // odd : check for duty cycle, if not 50% -- error + if (m_hi - m_lo !== 1) + begin + reconfig_err = 1; + $display ("Warning : The M counter of the StratixII 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"); + end + end + else begin // even mode + if (m_hi !== m_lo) + begin + reconfig_err = 1; + $display ("Warning : The M counter of the StratixII 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"); + end + end + end + + // N + error = 0; + n_val[0] = scan_data[73:72]; + if (scan_data[74] !== 1'b1) + begin + if (scan_data[73:72] == 2'b01) + begin + reconfig_err = 1; + error = 1; + // Cntr value is illegal : give warning + d_msg = display_msg(" N", 2); + end + else if (scan_data[73:72] == 2'b00) + n_val[0] = 3'b100; + if (error == 1'b0) + begin + if (n_mode_val[0] === "bypass") + begin + // Mode is switched : give warning + d_msg = display_msg(" N", 1); + end + n_mode_val[0] = ""; + end + end + else if (scan_data[74] == 1'b1) // bypass + begin + if (scan_data[72] !== 1'b0) + begin + reconfig_err = 1; + error = 1; + // Cntr value is illegal : give warning + d_msg = display_msg(" N", 3); + end + else begin + if (n_mode_val[0] != "bypass") + begin + // Mode is switched : give warning + d_msg = display_msg(" N", 4); + end + n_val[0] = 2'b01; + n_mode_val[0] = "bypass"; + end + end + end + else begin // pll type is auto or enhanced + for (i = 0; i < 6; i=i+1) + begin + if (tmp_scan_data[124] == 1'b1) + begin + c_mode_val_tmp[i] = "bypass"; + if (tmp_scan_data[133] === 1'b1) + begin + c_mode_val_tmp[i] = " off"; + $display("Warning : The specified bit settings will turn OFF the C%0d counter. It cannot be turned on unless the part is re-initialized.", i); + end + end + else if (tmp_scan_data[133] == 1'b1) + c_mode_val_tmp[i] = " odd"; + else + c_mode_val_tmp[i] = " even"; + if (tmp_scan_data[123:116] === 8'b00000000) + c_high_val_tmp[i] = 9'b100000000; + else + c_high_val_tmp[i] = tmp_scan_data[123:116]; + if (tmp_scan_data[132:125] === 8'b00000000) + c_low_val_tmp[i] = 9'b100000000; + else + c_low_val_tmp[i] = tmp_scan_data[132:125]; + + tmp_scan_data = tmp_scan_data << 18; + end + + // the phase_taps + tmp_scan_data = scan_data; + for (i = 0; i < 6; i=i+1) + begin + if (tmp_scan_data[14] == 1'b0) + begin + // do nothing + end + else if (tmp_scan_data[14] === 1'b1) + begin + if (tmp_scan_data[15] === 1'b1) + begin + c_ph_val_tmp[i] = c_ph_val_tmp[i] + 1; + if (c_ph_val_tmp[i] > 7) + c_ph_val_tmp[i] = 0; + end + else if (tmp_scan_data[15] === 1'b0) + begin + c_ph_val_tmp[i] = c_ph_val_tmp[i] - 1; + if (c_ph_val_tmp[i] < 0) + c_ph_val_tmp[i] = 7; + end + end + tmp_scan_data = tmp_scan_data >> 2; + end + 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_mode = c_mode_val[ext_fbk_cntr_index]; + + // cntrs M/M2 + tmp_scan_data = scan_data; + for (i=0; i<2; i=i+1) + begin + if (i == 0 || (i == 1 && ss > 0)) + begin + error = 0; + m_val_tmp[i] = tmp_scan_data[142:134]; + if (tmp_scan_data[143] !== 1'b1) + begin + if (tmp_scan_data[142:134] == 9'b000000001) + begin + reconfig_err = 1; + error = 1; + // Cntr value is illegal : give warning + if (i == 0) + d_msg = display_msg(" M", 2); + else + d_msg = display_msg("M2", 2); + end + else if (tmp_scan_data[142:134] == 9'b000000000) + m_val_tmp[i] = 10'b1000000000; + if (error == 1'b0) + begin + if (m_mode_val[i] === "bypass") + begin + // Mode is switched : give warning + if (i == 0) + d_msg = display_msg(" M", 1); + else + d_msg = display_msg("M2", 1); + end + m_mode_val[i] = ""; + end + end + else if (tmp_scan_data[143] == 1'b1) + begin + if (tmp_scan_data[134] !== 1'b0) + begin + reconfig_err = 1; + error = 1; + // Cntr value is illegal : give warning + if (i == 0) + d_msg = display_msg(" M", 3); + else + d_msg = display_msg("M2", 3); + end + else begin + if (m_mode_val[i] !== "bypass") + begin + // Mode is switched: give warning + if (i == 0) + d_msg = display_msg(" M", 4); + else + d_msg = display_msg("M2", 4); + end + m_val_tmp[i] = 10'b0000000001; + m_mode_val[i] = "bypass"; + end + end + end + tmp_scan_data = tmp_scan_data >> 10; + end + if (ss > 0) + begin + if (m_mode_val[0] != m_mode_val[1]) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Incompatible modes for M/M2 counters. Either both should be BYASSED or both NON-BYPASSED. Reconfiguration may not work."); + end + end + + // cntrs N/N2 + tmp_scan_data = scan_data; + for (i=0; i<2; i=i+1) + begin + if (i == 0 || (i == 1 && ss > 0)) + begin + error = 0; + n_val[i] = tmp_scan_data[162:154]; + if (tmp_scan_data[163] !== 1'b1) + begin + if (tmp_scan_data[162:154] == 9'b000000001) + begin + reconfig_err = 1; + error = 1; + // Cntr value is illegal : give warning + if (i == 0) + d_msg = display_msg(" N", 2); + else + d_msg = display_msg("N2", 2); + end + else if (tmp_scan_data[162:154] == 9'b000000000) + n_val[i] = 10'b1000000000; + if (error == 1'b0) + begin + if (n_mode_val[i] === "bypass") + begin + // Mode is switched : give warning + if (i == 0) + d_msg = display_msg(" N", 1); + else + d_msg = display_msg("N2", 1); + end + n_mode_val[i] = ""; + end + end + else if (tmp_scan_data[163] == 1'b1) // bypass + begin + if (tmp_scan_data[154] !== 1'b0) + begin + reconfig_err = 1; + error = 1; + // Cntr value is illegal : give warning + if (i == 0) + d_msg = display_msg(" N", 3); + else + d_msg = display_msg("N2", 3); + end + else begin + if (n_mode_val[i] != "bypass") + begin + // Mode is switched : give warning + if (i == 0) + d_msg = display_msg(" N", 4); + else + d_msg = display_msg("N2", 4); + end + n_val[i] = 10'b0000000001; + n_mode_val[i] = "bypass"; + end + end + end + tmp_scan_data = tmp_scan_data >> 10; + end + if (ss > 0) + begin + if (n_mode_val[0] != n_mode_val[1]) + begin + reconfig_err = 1; + error = 1; + $display ("Warning : Incompatible modes for N/N2 counters. Either both should be BYASSED or both NON-BYPASSED. Reconfiguration may not work."); + end + end + end + + 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], + refclk_period, m_val[0]); + + slowest_clk_new = slowest_clk ( c_high_val_tmp[0]+c_low_val[0], c_mode_val_tmp[0], + c_high_val_tmp[1]+c_low_val[1], c_mode_val_tmp[1], + c_high_val_tmp[2]+c_low_val[2], c_mode_val_tmp[2], + c_high_val_tmp[3]+c_low_val[3], c_mode_val_tmp[3], + c_high_val_tmp[4]+c_low_val[4], c_mode_val_tmp[4], + c_high_val_tmp[5]+c_low_val[5], c_mode_val_tmp[5], + refclk_period, m_val[0]); + + quiet_time = (slowest_clk_new > slowest_clk_old) ? slowest_clk_new : slowest_clk_old; + + // get quiet time in terms of scanclk cycles + my_rem = quiet_time % scanclk_period; + scanclk_cycles = quiet_time/scanclk_period; + if (my_rem != 0) + scanclk_cycles = scanclk_cycles + 1; + + scandone_tmp <= #((scanclk_cycles+0.5) * scanclk_period) 1'b1; + end + + scanwrite_last_value = scanwrite_enabled; + end + + always @(schedule_vco or areset_ipd or ena_pll) + begin + sched_time = 0; + + for (i = 0; i <= 7; i=i+1) + last_phase_shift[i] = phase_shift[i]; + + cycle_to_adjust = 0; + l_index = 1; + m_times_vco_period = new_m_times_vco_period; + + // give appropriate messages + // if areset was asserted + if (areset_ipd === 1'b1 && areset_ipd_last_value !== areset_ipd) + begin + $display (" Note : PLL was reset"); + $display ("Time: %0t Instance: %m", $time); + // reset lock parameters + locked_tmp = 0; + pll_is_locked = 0; + pll_about_to_lock = 0; + cycles_to_lock = 0; + cycles_to_unlock = 0; + end + + // if ena was deasserted + if (ena_pll == 1'b0 && ena_ipd_last_value !== ena_pll) + begin + $display (" Note : PLL was disabled"); + $display ("Time: %0t Instance: %m", $time); + end + + // illegal value on areset_ipd + if (areset_ipd === 1'bx && (areset_ipd_last_value === 1'b0 || areset_ipd_last_value === 1'b1)) + begin + $display("Warning : Illegal value 'X' detected on ARESET input"); + $display ("Time: %0t Instance: %m", $time); + end + + if ((schedule_vco !== schedule_vco_last_value) && (areset_ipd == 1'b1 || ena_pll == 1'b0 || stop_vco == 1'b1)) + begin + + if (areset_ipd === 1'b1) + pll_is_in_reset = 1; + + // drop VCO taps to 0 + for (i = 0; i <= 7; i=i+1) + begin + for (j = 0; j <= last_phase_shift[i] + 1; j=j+1) + vco_out[i] <= #(j) 1'b0; + phase_shift[i] = 0; + last_phase_shift[i] = 0; + end + + // reset lock parameters + locked_tmp = 0; + pll_is_locked = 0; + pll_about_to_lock = 0; + cycles_to_lock = 0; + cycles_to_unlock = 0; + + got_first_refclk = 0; + got_second_refclk = 0; + refclk_time = 0; + got_first_fbclk = 0; + fbclk_time = 0; + first_fbclk_time = 0; + fbclk_period = 0; + + first_schedule = 1; + vco_val = 0; + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 0; + + // reset all counter phase tap values to POF programmed values + m_ph_val = m_ph_val_orig; + for (i=0; i<= 5; i=i+1) + c_ph_val[i] = c_ph_val_orig[i]; + + end else if (ena_pll === 1'b1 && areset_ipd === 1'b0 && stop_vco === 1'b0) + begin + // else note areset deassert time + // note it as refclk_time to prevent false triggering + // of stop_vco after areset + if (areset_ipd === 1'b0 && areset_ipd_last_value === 1'b1 && pll_is_in_reset === 1'b1) + begin + refclk_time = $time; + pll_is_in_reset = 0; + end + + // calculate loop_xplier : this will be different from m_val in ext. fbk mode + loop_xplier = m_val[0]; + loop_initial = i_m_initial - 1; + loop_ph = m_ph_val; + + if (l_operation_mode == "external_feedback") + begin + if (ext_fbk_cntr_mode == "bypass") + ext_fbk_cntr_modulus = 1; + else + ext_fbk_cntr_modulus = ext_fbk_cntr_high + ext_fbk_cntr_low; + + loop_xplier = m_val[0] * (ext_fbk_cntr_modulus); + loop_ph = ext_fbk_cntr_ph; + loop_initial = ext_fbk_cntr_initial - 1 + ((i_m_initial - 1) * ext_fbk_cntr_modulus); + end + + // convert initial value to delay + initial_delay = (loop_initial * m_times_vco_period)/loop_xplier; + + // convert loop ph_tap to delay + rem = m_times_vco_period % loop_xplier; + vco_per = m_times_vco_period/loop_xplier; + if (rem != 0) + vco_per = vco_per + 1; + fbk_phase = (loop_ph * vco_per)/8; + + if (l_operation_mode == "external_feedback") + begin + pull_back_M = (i_m_initial - 1) * (ext_fbk_cntr_modulus) * (m_times_vco_period/loop_xplier); + + while (pull_back_M > refclk_period) + pull_back_M = pull_back_M - refclk_period; + end + else begin + pull_back_M = initial_delay + fbk_phase; + end + + total_pull_back = pull_back_M; + if (l_simulation_type == "timing") + total_pull_back = total_pull_back + pll_compensation_delay; + + while (total_pull_back > refclk_period) + total_pull_back = total_pull_back - refclk_period; + + if (total_pull_back > 0) + offset = refclk_period - total_pull_back; + else + offset = 0; + + if (l_operation_mode == "external_feedback") + begin + fbk_delay = pull_back_M; + if (l_simulation_type == "timing") + fbk_delay = fbk_delay + pll_compensation_delay; + end + else begin + fbk_delay = total_pull_back - fbk_phase; + if (fbk_delay < 0) + begin + offset = offset - fbk_phase; + fbk_delay = total_pull_back; + end + end + + // assign m_delay + m_delay = fbk_delay; + + for (i = 1; i <= loop_xplier; i=i+1) + begin + // adjust cycles + tmp_vco_per = m_times_vco_period/loop_xplier; + if (rem != 0 && l_index <= rem) + begin + tmp_rem = (loop_xplier * l_index) % rem; + cycle_to_adjust = (loop_xplier * l_index) / rem; + if (tmp_rem != 0) + cycle_to_adjust = cycle_to_adjust + 1; + end + if (cycle_to_adjust == i) + begin + tmp_vco_per = tmp_vco_per + 1; + l_index = l_index + 1; + end + + // calculate high and low periods + high_time = tmp_vco_per/2; + if (tmp_vco_per % 2 != 0) + high_time = high_time + 1; + low_time = tmp_vco_per - high_time; + + // schedule the rising and falling egdes + for (j=0; j<=1; j=j+1) + begin + vco_val = ~vco_val; + if (vco_val == 1'b0) + sched_time = sched_time + high_time; + else + sched_time = sched_time + low_time; + + // schedule taps with appropriate phase shifts + for (k = 0; k <= 7; k=k+1) + begin + phase_shift[k] = (k*tmp_vco_per)/8; + if (first_schedule) + vco_out[k] <= #(sched_time + phase_shift[k]) vco_val; + else + vco_out[k] <= #(sched_time + last_phase_shift[k]) vco_val; + end + end + end + if (first_schedule) + begin + vco_val = ~vco_val; + if (vco_val == 1'b0) + sched_time = sched_time + high_time; + else + sched_time = sched_time + low_time; + for (k = 0; k <= 7; k=k+1) + begin + phase_shift[k] = (k*tmp_vco_per)/8; + vco_out[k] <= #(sched_time+phase_shift[k]) vco_val; + end + first_schedule = 0; + end + + schedule_vco <= #(sched_time) ~schedule_vco; + if (vco_period_was_phase_adjusted) + begin + m_times_vco_period = refclk_period; + new_m_times_vco_period = refclk_period; + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 1; + + tmp_vco_per = m_times_vco_period/loop_xplier; + for (k = 0; k <= 7; k=k+1) + phase_shift[k] = (k*tmp_vco_per)/8; + end + end + + areset_ipd_last_value = areset_ipd; + ena_ipd_last_value = ena_pll; + schedule_vco_last_value = schedule_vco; + + end + + always @(pfdena_ipd) + begin + if (pfdena_ipd === 1'b0) + begin + if (pll_is_locked) + locked_tmp = 1'bx; + pll_is_locked = 0; + cycles_to_lock = 0; + $display (" Note : PFDENA was deasserted"); + $display ("Time: %0t Instance: %m", $time); + end + else if (pfdena_ipd === 1'b1 && pfdena_ipd_last_value === 1'b0) + begin + // PFD was disabled, now enabled again + got_first_refclk = 0; + got_second_refclk = 0; + refclk_time = $time; + end + pfdena_ipd_last_value = pfdena_ipd; + end + + always @(negedge refclk or negedge fbclk) + begin + refclk_last_value = refclk; + fbclk_last_value = fbclk; + end + + always @(posedge refclk or posedge fbclk) + begin + if (refclk == 1'b1 && refclk_last_value !== refclk && areset_ipd === 1'b0) + begin + if (! got_first_refclk) + begin + got_first_refclk = 1; + end else + begin + got_second_refclk = 1; + refclk_period = $time - refclk_time; + + // check if incoming freq. will cause VCO range to be + // exceeded + if ((vco_max != 0 && vco_min != 0) && (pfdena_ipd === 1'b1) && + ((refclk_period/loop_xplier > vco_max) || + (refclk_period/loop_xplier < vco_min)) ) + begin + if (pll_is_locked == 1'b1) + begin + $display ("Warning : Input clock freq. is not within VCO range. PLL may lose lock"); + $display ("Time: %0t Instance: %m", $time); + if (inclk_out_of_range === 1'b1) + begin + // unlock + pll_is_locked = 0; + locked_tmp = 0; + pll_about_to_lock = 0; + cycles_to_lock = 0; + $display ("Note : PLL lost lock"); + $display ("Time: %0t Instance: %m", $time); + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 0; + end + end + else begin + if (no_warn == 1'b0) + begin + $display ("Warning : Input clock freq. is not within VCO range. PLL may not lock"); + $display ("Time: %0t Instance: %m", $time); + no_warn = 1'b1; + end + end + inclk_out_of_range = 1; + end + else begin + inclk_out_of_range = 0; + end + + end + if (stop_vco == 1'b1) + begin + stop_vco = 0; + schedule_vco = ~schedule_vco; + end + refclk_time = $time; + end + + if (fbclk == 1'b1 && fbclk_last_value !== fbclk) + begin + if (scanwrite_enabled === 1'b1) + begin + m_val[0] <= m_val_tmp[0]; + m_val[1] <= m_val_tmp[1]; + end + if (!got_first_fbclk) + begin + got_first_fbclk = 1; + first_fbclk_time = $time; + end + else + fbclk_period = $time - fbclk_time; + + // need refclk_period here, so initialized to proper value above + if ( ( ($time - refclk_time > 1.5 * refclk_period) && pfdena_ipd === 1'b1 && pll_is_locked === 1'b1) || ( ($time - refclk_time > 5 * refclk_period) && pfdena_ipd === 1'b1) ) + begin + stop_vco = 1; + // reset + got_first_refclk = 0; + got_first_fbclk = 0; + got_second_refclk = 0; + if (pll_is_locked == 1'b1) + begin + pll_is_locked = 0; + locked_tmp = 0; + $display ("Note : PLL lost lock due to loss of input clock"); + $display ("Time: %0t Instance: %m", $time); + end + pll_about_to_lock = 0; + cycles_to_lock = 0; + cycles_to_unlock = 0; + first_schedule = 1; + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 0; + end + fbclk_time = $time; + end + + if (got_second_refclk && pfdena_ipd === 1'b1 && (!inclk_out_of_range)) + begin + // now we know actual incoming period + if (abs(fbclk_time - refclk_time) <= 5 || (got_first_fbclk && abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5)) + begin + // considered in phase + if (cycles_to_lock == valid_lock_multiplier - 1) + pll_about_to_lock <= 1; + if (cycles_to_lock == valid_lock_multiplier) + begin + if (pll_is_locked === 1'b0) + begin + $display (" Note : PLL locked to incoming clock"); + $display ("Time: %0t Instance: %m", $time); + end + pll_is_locked = 1; + locked_tmp = 1; + cycles_to_unlock = 0; + end + // increment lock counter only if the second part of the above + // time check is not true + if (!(abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5)) + begin + cycles_to_lock = cycles_to_lock + 1; + end + + // adjust m_times_vco_period + new_m_times_vco_period = refclk_period; + + end else + begin + // if locked, begin unlock + if (pll_is_locked) + begin + cycles_to_unlock = cycles_to_unlock + 1; + if (cycles_to_unlock == invalid_lock_multiplier) + begin + pll_is_locked = 0; + locked_tmp = 0; + pll_about_to_lock = 0; + cycles_to_lock = 0; + $display ("Note : PLL lost lock"); + $display ("Time: %0t Instance: %m", $time); + vco_period_was_phase_adjusted = 0; + phase_adjust_was_scheduled = 0; + end + end + if (abs(refclk_period - fbclk_period) <= 2) + begin + // frequency is still good + if ($time == fbclk_time && (!phase_adjust_was_scheduled)) + begin + if (abs(fbclk_time - refclk_time) > refclk_period/2) + begin + new_m_times_vco_period = m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time)); + vco_period_was_phase_adjusted = 1; + end else + begin + new_m_times_vco_period = m_times_vco_period - abs(fbclk_time - refclk_time); + vco_period_was_phase_adjusted = 1; + end + end + end else + begin + new_m_times_vco_period = refclk_period; + phase_adjust_was_scheduled = 0; + end + end + end + + if (reconfig_err == 1'b1) + begin + locked_tmp = 0; + end + + refclk_last_value = refclk; + fbclk_last_value = fbclk; + end + + assign clk0_tmp = i_clk0_counter == "c0" ? c0_clk : i_clk0_counter == "c1" ? c1_clk : i_clk0_counter == "c2" ? c2_clk : i_clk0_counter == "c3" ? c3_clk : i_clk0_counter == "c4" ? c4_clk : i_clk0_counter == "c5" ? c5_clk : 'b0; + + assign clk0 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk0_tmp : 'bx; + + + assign clk1_tmp = i_clk1_counter == "c0" ? c0_clk : i_clk1_counter == "c1" ? c1_clk : i_clk1_counter == "c2" ? c2_clk : i_clk1_counter == "c3" ? c3_clk : i_clk1_counter == "c4" ? c4_clk : i_clk1_counter == "c5" ? c5_clk : 'b0; + + assign clk1 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk1_tmp : 'bx; + + + assign clk2_tmp = i_clk2_counter == "c0" ? c0_clk : i_clk2_counter == "c1" ? c1_clk : i_clk2_counter == "c2" ? c2_clk : i_clk2_counter == "c3" ? c3_clk : i_clk2_counter == "c4" ? c4_clk : i_clk2_counter == "c5" ? c5_clk : 'b0; + + assign clk2 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk2_tmp : 'bx; + + + assign clk3_tmp = i_clk3_counter == "c0" ? c0_clk : i_clk3_counter == "c1" ? c1_clk : i_clk3_counter == "c2" ? c2_clk : i_clk3_counter == "c3" ? c3_clk : i_clk3_counter == "c4" ? c4_clk : i_clk3_counter == "c5" ? c5_clk : 'b0; + + assign clk3 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk3_tmp : 'bx; + + + assign clk4_tmp = i_clk4_counter == "c0" ? c0_clk : i_clk4_counter == "c1" ? c1_clk : i_clk4_counter == "c2" ? c2_clk : i_clk4_counter == "c3" ? c3_clk : i_clk4_counter == "c4" ? c4_clk : i_clk4_counter == "c5" ? c5_clk : 'b0; + + assign clk4 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk4_tmp : 'bx; + + + assign clk5_tmp = i_clk5_counter == "c0" ? c0_clk : i_clk5_counter == "c1" ? c1_clk : i_clk5_counter == "c2" ? c2_clk : i_clk5_counter == "c3" ? c3_clk : i_clk5_counter == "c4" ? c4_clk : i_clk5_counter == "c5" ? c5_clk : 'b0; + + assign clk5 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk5_tmp : 'bx; + + assign sclkout0 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode == 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? sclkout0_tmp : 1'bx; + + assign sclkout1 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode == 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? sclkout1_tmp : 1'bx; + + assign enable_0 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode == 1'b1) || pll_about_to_lock == 1'b1 ? enable0_tmp : 'bx; + assign enable_1 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode == 1'b1) || pll_about_to_lock == 1'b1 ? enable1_tmp : 'bx; + + + // ACCELERATE OUTPUTS + and (clk[0], 1'b1, clk0); + and (clk[1], 1'b1, clk1); + and (clk[2], 1'b1, clk2); + and (clk[3], 1'b1, clk3); + and (clk[4], 1'b1, clk4); + and (clk[5], 1'b1, clk5); + + and (sclkout[0], 1'b1, sclkout0); + and (sclkout[1], 1'b1, sclkout1); + + and (enable0, 1'b1, enable_0); + and (enable1, 1'b1, enable_1); + + and (scandataout, 1'b1, scandataout_tmp); + and (scandone, 1'b1, scandone_tmp); + +endmodule // MF_stratixii_pll + +// START MODULE NAME ----------------------------------------------------------- +// +// Module 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 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 inidicate 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. + +//END MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1ps + +// MODULE DECLARATION +module altpll ( + inclk, // input reference clock - up to 2 can be used + fbin, // external feedback input port + pllena, // PLL enable signal + clkswitch, // switch between inclk0 and inclk1 + areset, // asynchronous reset + pfdena, // enable the Phase Frequency Detector (PFD) + clkena, // enable clk0 to clk5 clock outputs + extclkena, // enable extclk0 to extclk3 clock outputs + scanclk, // clock for the serial scan chain + scanaclr, // asynchronous clear the serial scan chain + scanread, // determines when the scan chain can read in data from the scandata port + scanwrite, // determines when the scan chain can write out data into pll + scandata, // data for the scan chain + clk, // internal clock outputs (feeds the core) + extclk, // external clock outputs (feeds pins) + clkbad, // indicates if inclk0/inclk1 has gone bad + enable0, // load enable pulse 0 for lvds + enable1, // load enable pulse l for lvds + activeclock, // indicates which input clock is being used + clkloss, // indicates when clock switchover initiates + locked, // indicates when the PLL locks onto the input clock + scandataout, // data output of the serial scan chain + scandone, // indicates when pll reconfiguration is complete + sclkout0, // serial clock output 0 for lvds + sclkout1 // serial clock output 1 for lvds +); + +// GLOBAL PARAMETER DECLARATION +parameter intended_device_family = "Stratix" ; +parameter operation_mode = "NORMAL" ; +parameter pll_type = "AUTO" ; +parameter qualify_conf_done = "OFF" ; +parameter compensate_clock = "CLK0" ; +parameter scan_chain = "LONG"; +parameter primary_clock = "inclk0"; +parameter inclk0_input_frequency = 1000; +parameter inclk1_input_frequency = 0; +parameter gate_lock_signal = "NO"; +parameter gate_lock_counter = 0; +parameter lock_high = 1; +parameter lock_low = 5; +parameter valid_lock_multiplier = 1; +parameter invalid_lock_multiplier = 5; +parameter switch_over_type = "AUTO"; +parameter switch_over_on_lossclk = "OFF" ; +parameter switch_over_on_gated_lock = "OFF" ; +parameter enable_switch_over_counter = "OFF"; +parameter switch_over_counter = 0; +parameter feedback_source = "EXTCLK0" ; +parameter bandwidth = 0; +parameter bandwidth_type = "UNUSED"; +parameter lpm_hint = "UNUSED"; +parameter spread_frequency = 0; +parameter down_spread = "0.0"; +parameter self_reset_on_gated_loss_lock = "OFF"; + +// simulation-only parameters +parameter simulation_type = "functional"; +parameter source_is_pll = "off"; + +parameter skip_vco = "off"; + +// internal clock specifications +parameter clk5_multiply_by = 1; +parameter clk4_multiply_by = 1; +parameter clk3_multiply_by = 1; +parameter clk2_multiply_by = 1; +parameter clk1_multiply_by = 1; +parameter clk0_multiply_by = 1; +parameter clk5_divide_by = 1; +parameter clk4_divide_by = 1; +parameter clk3_divide_by = 1; +parameter clk2_divide_by = 1; +parameter clk1_divide_by = 1; +parameter clk0_divide_by = 1; +parameter clk5_phase_shift = "0"; +parameter clk4_phase_shift = "0"; +parameter clk3_phase_shift = "0"; +parameter clk2_phase_shift = "0"; +parameter clk1_phase_shift = "0"; +parameter clk0_phase_shift = "0"; + +parameter clk5_time_delay = "0"; // For stratix pll use only +parameter clk4_time_delay = "0"; // For stratix pll use only +parameter clk3_time_delay = "0"; // For stratix pll use only +parameter clk2_time_delay = "0"; // For stratix pll use only +parameter clk1_time_delay = "0"; // For stratix pll use only +parameter clk0_time_delay = "0"; // For stratix pll use only +parameter clk5_duty_cycle = 50; +parameter clk4_duty_cycle = 50; +parameter clk3_duty_cycle = 50; +parameter clk2_duty_cycle = 50; +parameter clk1_duty_cycle = 50; +parameter clk0_duty_cycle = 50; + +parameter clk2_output_frequency = 0; +parameter clk1_output_frequency = 0; +parameter clk0_output_frequency = 0; + +// external clock specifications (for stratix pll use only) +parameter extclk3_multiply_by = 1; +parameter extclk2_multiply_by = 1; +parameter extclk1_multiply_by = 1; +parameter extclk0_multiply_by = 1; +parameter extclk3_divide_by = 1; +parameter extclk2_divide_by = 1; +parameter extclk1_divide_by = 1; +parameter extclk0_divide_by = 1; +parameter extclk3_phase_shift = "0"; +parameter extclk2_phase_shift = "0"; +parameter extclk1_phase_shift = "0"; +parameter extclk0_phase_shift = "0"; +parameter extclk3_time_delay = "0"; +parameter extclk2_time_delay = "0"; +parameter extclk1_time_delay = "0"; +parameter extclk0_time_delay = "0"; +parameter extclk3_duty_cycle = 50; +parameter extclk2_duty_cycle = 50; +parameter extclk1_duty_cycle = 50; +parameter extclk0_duty_cycle = 50; + +// The following 4 parameters are for Stratix II pll in lvds mode only +parameter vco_multiply_by = 0; +parameter vco_divide_by = 0; +parameter sclkout0_phase_shift = "0"; +parameter sclkout1_phase_shift = "0"; + +// advanced user parameters +parameter vco_min = 0; +parameter vco_max = 0; +parameter vco_center = 0; +parameter pfd_min = 0; +parameter pfd_max = 0; +parameter m_initial = 1; +parameter m = 0; // m must default to 0 in order for altpll to calculate advanced parameters for itself +parameter n = 1; +parameter m2 = 1; +parameter n2 = 1; +parameter ss = 0; +parameter l0_high = 1; +parameter l1_high = 1; +parameter g0_high = 1; +parameter g1_high = 1; +parameter g2_high = 1; +parameter g3_high = 1; +parameter e0_high = 1; +parameter e1_high = 1; +parameter e2_high = 1; +parameter e3_high = 1; +parameter l0_low = 1; +parameter l1_low = 1; +parameter g0_low = 1; +parameter g1_low = 1; +parameter g2_low = 1; +parameter g3_low = 1; +parameter e0_low = 1; +parameter e1_low = 1; +parameter e2_low = 1; +parameter e3_low = 1; +parameter l0_initial = 1; +parameter l1_initial = 1; +parameter g0_initial = 1; +parameter g1_initial = 1; +parameter g2_initial = 1; +parameter g3_initial = 1; +parameter e0_initial = 1; +parameter e1_initial = 1; +parameter e2_initial = 1; +parameter e3_initial = 1; +parameter l0_mode = "bypass"; +parameter l1_mode = "bypass"; +parameter g0_mode = "bypass"; +parameter g1_mode = "bypass"; +parameter g2_mode = "bypass"; +parameter g3_mode = "bypass"; +parameter e0_mode = "bypass"; +parameter e1_mode = "bypass"; +parameter e2_mode = "bypass"; +parameter e3_mode = "bypass"; +parameter l0_ph = 0; +parameter l1_ph = 0; +parameter g0_ph = 0; +parameter g1_ph = 0; +parameter g2_ph = 0; +parameter g3_ph = 0; +parameter e0_ph = 0; +parameter e1_ph = 0; +parameter e2_ph = 0; +parameter e3_ph = 0; +parameter m_ph = 0; +parameter l0_time_delay = 0; +parameter l1_time_delay = 0; +parameter g0_time_delay = 0; +parameter g1_time_delay = 0; +parameter g2_time_delay = 0; +parameter g3_time_delay = 0; +parameter e0_time_delay = 0; +parameter e1_time_delay = 0; +parameter e2_time_delay = 0; +parameter e3_time_delay = 0; +parameter m_time_delay = 0; +parameter n_time_delay = 0; +parameter extclk3_counter = "e3" ; +parameter extclk2_counter = "e2" ; +parameter extclk1_counter = "e1" ; +parameter extclk0_counter = "e0" ; +parameter clk5_counter = "l1" ; +parameter clk4_counter = "l0" ; +parameter clk3_counter = "g3" ; +parameter clk2_counter = "g2" ; +parameter clk1_counter = "g1" ; +parameter clk0_counter = "g0" ; +parameter enable0_counter = "l0"; +parameter enable1_counter = "l0"; +parameter charge_pump_current = 2; +parameter loop_filter_r = "1.0"; +parameter loop_filter_c = 5; +parameter vco_post_scale = 0; +parameter lpm_type = "altpll"; + +// The following parameter are used to define the connectivity for some of the input +// and output ports. +parameter port_clkena0 = "PORT_CONNECTIVITY"; +parameter port_clkena1 = "PORT_CONNECTIVITY"; +parameter port_clkena2 = "PORT_CONNECTIVITY"; +parameter port_clkena3 = "PORT_CONNECTIVITY"; +parameter port_clkena4 = "PORT_CONNECTIVITY"; +parameter port_clkena5 = "PORT_CONNECTIVITY"; +parameter port_extclkena0 = "PORT_CONNECTIVITY"; +parameter port_extclkena1 = "PORT_CONNECTIVITY"; +parameter port_extclkena2 = "PORT_CONNECTIVITY"; +parameter port_extclkena3 = "PORT_CONNECTIVITY"; +parameter port_extclk0 = "PORT_CONNECTIVITY"; +parameter port_extclk1 = "PORT_CONNECTIVITY"; +parameter port_extclk2 = "PORT_CONNECTIVITY"; +parameter port_extclk3 = "PORT_CONNECTIVITY"; +parameter port_clk0 = "PORT_CONNECTIVITY"; +parameter port_clk1 = "PORT_CONNECTIVITY"; +parameter port_clk2 = "PORT_CONNECTIVITY"; +parameter port_clk3 = "PORT_CONNECTIVITY"; +parameter port_clk4 = "PORT_CONNECTIVITY"; +parameter port_clk5 = "PORT_CONNECTIVITY"; +parameter port_scandata = "PORT_CONNECTIVITY"; +parameter port_scandataout = "PORT_CONNECTIVITY"; +parameter port_scandone = "PORT_CONNECTIVITY"; +parameter port_sclkout1 = "PORT_CONNECTIVITY"; +parameter port_sclkout0 = "PORT_CONNECTIVITY"; +parameter port_clkbad0 = "PORT_CONNECTIVITY"; +parameter port_clkbad1 = "PORT_CONNECTIVITY"; +parameter port_activeclock = "PORT_CONNECTIVITY"; +parameter port_clkloss = "PORT_CONNECTIVITY"; +parameter port_inclk1 = "PORT_CONNECTIVITY"; +parameter port_inclk0 = "PORT_CONNECTIVITY"; +parameter port_fbin = "PORT_CONNECTIVITY"; +parameter port_pllena = "PORT_CONNECTIVITY"; +parameter port_clkswitch = "PORT_CONNECTIVITY"; +parameter port_areset = "PORT_CONNECTIVITY"; +parameter port_pfdena = "PORT_CONNECTIVITY"; +parameter port_scanclk = "PORT_CONNECTIVITY"; +parameter port_scanaclr = "PORT_CONNECTIVITY"; +parameter port_scanread = "PORT_CONNECTIVITY"; +parameter port_scanwrite = "PORT_CONNECTIVITY"; +parameter port_enable0 = "PORT_CONNECTIVITY"; +parameter port_enable1 = "PORT_CONNECTIVITY"; + +//For Stratixii pll use only +parameter c0_high = 1; +parameter c1_high = 1; +parameter c2_high = 1; +parameter c3_high = 1; +parameter c4_high = 1; +parameter c5_high = 1; +parameter c0_low = 1; +parameter c1_low = 1; +parameter c2_low = 1; +parameter c3_low = 1; +parameter c4_low = 1; +parameter c5_low = 1; +parameter c0_initial = 1; +parameter c1_initial = 1; +parameter c2_initial = 1; +parameter c3_initial = 1; +parameter c4_initial = 1; +parameter c5_initial = 1; +parameter c0_mode = "bypass"; +parameter c1_mode = "bypass"; +parameter c2_mode = "bypass"; +parameter c3_mode = "bypass"; +parameter c4_mode = "bypass"; +parameter c5_mode = "bypass"; +parameter c0_ph = 0; +parameter c1_ph = 0; +parameter c2_ph = 0; +parameter c3_ph = 0; +parameter c4_ph = 0; +parameter c5_ph = 0; +parameter c1_use_casc_in = "off"; +parameter c2_use_casc_in = "off"; +parameter c3_use_casc_in = "off"; +parameter c4_use_casc_in = "off"; +parameter c5_use_casc_in = "off"; +parameter m_test_source = 5; +parameter c0_test_source = 5; +parameter c1_test_source = 5; +parameter c2_test_source = 5; +parameter c3_test_source = 5; +parameter c4_test_source = 5; +parameter c5_test_source = 5; + +// INPUT PORT DECLARATION +input [1:0] inclk; +input fbin; +input pllena; +input clkswitch; +input areset; +input pfdena; +input [5:0] clkena; +input [3:0] extclkena; +input scanclk; +input scanaclr; +input scanread; +input scanwrite; +input scandata; + +// OUTPUT PORT DECLARATION +output [5:0] clk; +output [3:0] extclk; +output [1:0] clkbad; +output activeclock; +output enable0; +output enable1; +output clkloss; +output locked; +output scandataout; +output scandone; +output sclkout0; +output sclkout1; + +// pullups +tri1 fbin_pullup; +tri1 ena_pullup; +tri1 pfdena_pullup; +tri1 [5:0] clkena_pullup; +tri1 [3:0] extclkena_pullup; + +// pulldowns +tri0 [1:0] inclk_pulldown; +tri0 clkswitch_pulldown; +tri0 areset_pulldown; +tri0 scanclk_pulldown; +tri0 scanclr_pulldown; +tri0 scanread_pulldown; +tri0 scanwrite_pulldown; +tri0 scandata_pulldown; +tri0 comparator_pulldown; + +// 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. +wire locked_tmp; +wire [1:0] stratix_inclk; +wire stratix_fbin; +wire stratix_ena; +wire stratix_clkswitch; +wire stratix_areset; +wire stratix_pfdena; +wire [5:0] stratix_clkena; +wire [3:0] stratix_extclkena; +wire stratix_scanclk; +wire stratix_scanclr; +wire stratix_scandata; +wire [5:0] stratix_clk; +wire [3:0] stratix_extclk; +wire [1:0] stratix_clkbad; +wire stratix_activeclock; +wire stratix_locked; +wire stratix_clkloss; +wire stratix_scandataout; +wire stratix_enable0; +wire stratix_enable1; + +wire [1:0] stratixii_inclk; +wire stratixii_fbin; +wire stratixii_ena; +wire stratixii_clkswitch; +wire stratixii_areset; +wire stratixii_pfdena; +wire stratixii_scanread; +wire stratixii_scanwrite; +wire stratixii_scanclk; +wire stratixii_scandata; +wire stratixii_scandone; +wire [5:0] stratixii_clk; +wire [1:0] stratixii_clkbad; +wire stratixii_activeclock; +wire stratixii_locked; +wire stratixii_clkloss; +wire stratixii_scandataout; +wire stratixii_enable0; +wire stratixii_enable1; +wire stratixii_sclkout0; +wire stratixii_sclkout1; + +wire[5:0] clk_wire; +wire[1:0] clkbad_wire; +wire activeclock_wire; +wire clkloss_wire; +wire scandataout_wire; +wire scandone_wire; +wire sclkout0_wire; +wire sclkout1_wire; + +ALTERA_DEVICE_FAMILIES dev (); + +// INITIAL BLOCK +initial +begin + + // Begin of parameter checking + + if (clk5_multiply_by <= 0) + begin + $display("ERROR: The clk5_multiply_by must be greater than 0"); + $stop; + end + + if (clk4_multiply_by <= 0) + begin + $display("ERROR: The clk4_multiply_by must be greater than 0"); + $stop; + end + + if (clk3_multiply_by <= 0) + begin + $display("ERROR: The clk3_multiply_by must be greater than 0"); + $stop; + end + + + if (clk2_multiply_by <= 0) + begin + $display("ERROR: The clk2_multiply_by must be greater than 0"); + $stop; + end + + if (clk1_multiply_by <= 0) + begin + $display("ERROR: The clk1_multiply_by must be greater than 0"); + $stop; + end + + if (clk0_multiply_by <= 0) + begin + $display("ERROR: The clk0_multiply_by must be greater than 0"); + $stop; + end + + if (clk5_divide_by <= 0) + begin + $display("ERROR: The clk5_divide_by must be greater than 0"); + $stop; + end + + + if (clk4_divide_by <= 0) + begin + $display("ERROR: The clk4_divide_by must be greater than 0"); + $stop; + end + + + if (clk3_divide_by <= 0) + begin + $display("ERROR: The clk3_divide_by must be greater than 0"); + $stop; + end + + + if (clk2_divide_by <= 0) + begin + $display("ERROR: The clk2_divide_by must be greater than 0"); + $stop; + end + + + if (clk1_divide_by <= 0) + begin + $display("ERROR: The clk1_divide_by must be greater than 0"); + $stop; + end + + + if (clk0_divide_by <= 0) + begin + $display("ERROR: The clk0_divide_by must be greater than 0"); + $stop; + end + + if (extclk3_multiply_by <= 0) + begin + $display("ERROR: The extclk3_multiply_by must be greater than 0"); + $stop; + end + + if (extclk2_multiply_by <= 0) + begin + $display("ERROR: The extclk2_multiply_by must be greater than 0"); + $stop; + end + + if (extclk1_multiply_by <= 0) + begin + $display("ERROR: The extclk1_multiply_by must be greater than 0"); + $stop; + end + + if (extclk0_multiply_by <= 0) + begin + $display("ERROR: The extclk0_multiply_by must be greater than 0"); + $stop; + end + + + if (extclk3_divide_by <= 0) + begin + $display("ERROR: The extclk3_divide_by must be greater than 0"); + $stop; + end + + + if (extclk2_divide_by <= 0) + begin + $display("ERROR: The extclk2_divide_by must be greater than 0"); + $stop; + end + + + if (extclk1_divide_by <= 0) + begin + $display("ERROR: The extclk1_divide_by must be greater than 0"); + $stop; + end + + + if (extclk0_divide_by <= 0) + begin + $display("ERROR: The extclk0_divide_by must be greater than 0"); + $stop; + end + + if (!((primary_clock == "inclk0") || (primary_clock == "INCLK0") || + (primary_clock == "inclk1") || (primary_clock == "INCLK1"))) + begin + $display("ERROR: The primary clock is set to an illegal value"); + $stop; + end + + if (dev.IS_VALID_FAMILY(intended_device_family) == 0) + begin + $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family); + $stop; + end + // End of parameter checking + +end + +// COMPONENT INSTANTIATION +MF_stratix_pll pll0 +( + .inclk (stratix_inclk), + .fbin (stratix_fbin), + .ena (stratix_ena), + .clkswitch (stratix_clkswitch), + .areset (stratix_areset), + .pfdena (stratix_pfdena), + .clkena (stratix_clkena), + .extclkena (stratix_extclkena), + .scanclk (stratix_scanclk), + .scanaclr (stratix_scanclr), + .scandata (stratix_scandata), + .comparator(), + .clk (stratix_clk), + .extclk (stratix_extclk), + .clkbad (stratix_clkbad), + .activeclock (stratix_activeclock), + .locked (locked_tmp), + .clkloss (stratix_clkloss), + .scandataout (stratix_scandataout), + .enable0 (stratix_enable0), + .enable1 (stratix_enable1) +); + defparam + pll0.operation_mode = operation_mode, + pll0.pll_type = pll_type, + pll0.qualify_conf_done = qualify_conf_done, + pll0.compensate_clock = compensate_clock, + pll0.scan_chain = scan_chain, + pll0.primary_clock = primary_clock, + pll0.inclk0_input_frequency = inclk0_input_frequency, + pll0.inclk1_input_frequency = inclk1_input_frequency, + pll0.gate_lock_signal = gate_lock_signal, + pll0.gate_lock_counter = gate_lock_counter, + pll0.valid_lock_multiplier = valid_lock_multiplier, + pll0.invalid_lock_multiplier = invalid_lock_multiplier, + pll0.switch_over_on_lossclk = switch_over_on_lossclk, + pll0.switch_over_on_gated_lock = switch_over_on_gated_lock, + pll0.enable_switch_over_counter = enable_switch_over_counter, + pll0.switch_over_counter = switch_over_counter, + pll0.feedback_source = feedback_source, + pll0.bandwidth = bandwidth, + pll0.bandwidth_type = bandwidth_type, + pll0.spread_frequency = spread_frequency, + pll0.down_spread = down_spread, + pll0.simulation_type = simulation_type, + pll0.skip_vco = skip_vco, + + // internal clock specifications + pll0.clk5_multiply_by = clk5_multiply_by, + pll0.clk4_multiply_by = clk4_multiply_by, + pll0.clk3_multiply_by = clk3_multiply_by, + pll0.clk2_multiply_by = clk2_multiply_by, + pll0.clk1_multiply_by = clk1_multiply_by, + pll0.clk0_multiply_by = clk0_multiply_by, + pll0.clk5_divide_by = clk5_divide_by, + pll0.clk4_divide_by = clk4_divide_by, + pll0.clk3_divide_by = clk3_divide_by, + pll0.clk2_divide_by = clk2_divide_by, + pll0.clk1_divide_by = clk1_divide_by, + pll0.clk0_divide_by = clk0_divide_by, + pll0.clk5_phase_shift = clk5_phase_shift, + pll0.clk4_phase_shift = clk4_phase_shift, + pll0.clk3_phase_shift = clk3_phase_shift, + pll0.clk2_phase_shift = clk2_phase_shift, + pll0.clk1_phase_shift = clk1_phase_shift, + pll0.clk0_phase_shift = clk0_phase_shift, + pll0.clk5_time_delay = clk5_time_delay, + pll0.clk4_time_delay = clk4_time_delay, + pll0.clk3_time_delay = clk3_time_delay, + pll0.clk2_time_delay = clk2_time_delay, + pll0.clk1_time_delay = clk1_time_delay, + pll0.clk0_time_delay = clk0_time_delay, + pll0.clk5_duty_cycle = clk5_duty_cycle, + pll0.clk4_duty_cycle = clk4_duty_cycle, + pll0.clk3_duty_cycle = clk3_duty_cycle, + pll0.clk2_duty_cycle = clk2_duty_cycle, + pll0.clk1_duty_cycle = clk1_duty_cycle, + pll0.clk0_duty_cycle = clk0_duty_cycle, + + // external clock specifications + pll0.extclk3_multiply_by = extclk3_multiply_by, + pll0.extclk2_multiply_by = extclk2_multiply_by, + pll0.extclk1_multiply_by = extclk1_multiply_by, + pll0.extclk0_multiply_by = extclk0_multiply_by, + pll0.extclk3_divide_by = extclk3_divide_by, + pll0.extclk2_divide_by = extclk2_divide_by, + pll0.extclk1_divide_by = extclk1_divide_by, + pll0.extclk0_divide_by = extclk0_divide_by, + pll0.extclk3_phase_shift = extclk3_phase_shift, + pll0.extclk2_phase_shift = extclk2_phase_shift, + pll0.extclk1_phase_shift = extclk1_phase_shift, + pll0.extclk0_phase_shift = extclk0_phase_shift, + pll0.extclk3_time_delay = extclk3_time_delay, + pll0.extclk2_time_delay = extclk2_time_delay, + pll0.extclk1_time_delay = extclk1_time_delay, + pll0.extclk0_time_delay = extclk0_time_delay, + pll0.extclk3_duty_cycle = extclk3_duty_cycle, + pll0.extclk2_duty_cycle = extclk2_duty_cycle, + pll0.extclk1_duty_cycle = extclk1_duty_cycle, + pll0.extclk0_duty_cycle = extclk0_duty_cycle, + + // advanced parameters + pll0.vco_min = vco_min, + pll0.vco_max = vco_max, + pll0.vco_center = vco_center, + pll0.pfd_min = pfd_min, + pll0.pfd_max = pfd_max, + pll0.m_initial = m_initial, + pll0.m = m, + pll0.n = n, + pll0.m2 = m2, + pll0.n2 = n2, + pll0.ss = ss, + pll0.l0_high = l0_high, + pll0.l1_high = l1_high, + pll0.g0_high = g0_high, + pll0.g1_high = g1_high, + pll0.g2_high = g2_high, + pll0.g3_high = g3_high, + pll0.e0_high = e0_high, + pll0.e1_high = e1_high, + pll0.e2_high = e2_high, + pll0.e3_high = e3_high, + pll0.l0_low = l0_low, + pll0.l1_low = l1_low, + pll0.g0_low = g0_low, + pll0.g1_low = g1_low, + pll0.g2_low = g2_low, + pll0.g3_low = g3_low, + pll0.e0_low = e0_low, + pll0.e1_low = e1_low, + pll0.e2_low = e2_low, + pll0.e3_low = e3_low, + pll0.l0_initial = l0_initial, + pll0.l1_initial = l1_initial, + pll0.g0_initial = g0_initial, + pll0.g1_initial = g1_initial, + pll0.g2_initial = g2_initial, + pll0.g3_initial = g3_initial, + pll0.e0_initial = e0_initial, + pll0.e1_initial = e1_initial, + pll0.e2_initial = e2_initial, + pll0.e3_initial = e3_initial, + pll0.l0_mode = l0_mode, + pll0.l1_mode = l1_mode, + pll0.g0_mode = g0_mode, + pll0.g1_mode = g1_mode, + pll0.g2_mode = g2_mode, + pll0.g3_mode = g3_mode, + pll0.e0_mode = e0_mode, + pll0.e1_mode = e1_mode, + pll0.e2_mode = e2_mode, + pll0.e3_mode = e3_mode, + pll0.l0_ph = l0_ph, + pll0.l1_ph = l1_ph, + pll0.g0_ph = g0_ph, + pll0.g1_ph = g1_ph, + pll0.g2_ph = g2_ph, + pll0.g3_ph = g3_ph, + pll0.e0_ph = e0_ph, + pll0.e1_ph = e1_ph, + pll0.e2_ph = e2_ph, + pll0.e3_ph = e3_ph, + pll0.m_ph = m_ph, + pll0.l0_time_delay = l0_time_delay, + pll0.l1_time_delay = l1_time_delay, + pll0.g0_time_delay = g0_time_delay, + pll0.g1_time_delay = g1_time_delay, + pll0.g2_time_delay = g2_time_delay, + pll0.g3_time_delay = g3_time_delay, + pll0.e0_time_delay = e0_time_delay, + pll0.e1_time_delay = e1_time_delay, + pll0.e2_time_delay = e2_time_delay, + pll0.e3_time_delay = e3_time_delay, + pll0.m_time_delay = m_time_delay, + pll0.n_time_delay = n_time_delay, + pll0.extclk3_counter = extclk3_counter, + pll0.extclk2_counter = extclk2_counter, + pll0.extclk1_counter = extclk1_counter, + pll0.extclk0_counter = extclk0_counter, + pll0.clk5_counter = clk5_counter, + pll0.clk4_counter = clk4_counter, + pll0.clk3_counter = clk3_counter, + pll0.clk2_counter = clk2_counter, + pll0.clk1_counter = clk1_counter, + pll0.clk0_counter = clk0_counter, + pll0.enable0_counter = enable0_counter, + pll0.enable1_counter = enable1_counter, + pll0.charge_pump_current = charge_pump_current, + pll0.loop_filter_r = loop_filter_r, + pll0.loop_filter_c = loop_filter_c; + +MF_stratixii_pll pll1 +( + .inclk (stratixii_inclk), + .fbin (stratixii_fbin), + .ena (stratixii_ena), + .clkswitch (stratixii_clkswitch), + .areset (stratixii_areset), + .pfdena (stratixii_pfdena), + .scanclk (stratixii_scanclk), + .scanread (stratixii_scanread), + .scanwrite (stratixii_scanwrite), + .scandata (stratixii_scandata), + .testin(), + .scandone (stratixii_scandone), + .clk (stratixii_clk), + .clkbad (stratixii_clkbad), + .activeclock (stratixii_activeclock), + .locked (stratixii_locked), + .clkloss (stratixii_clkloss), + .scandataout (stratixii_scandataout), + .enable0 (stratixii_enable0), + .enable1 (stratixii_enable1), + .testupout (), + .testdownout (), + .sclkout({stratixii_sclkout1, stratixii_sclkout0}) +); + defparam + pll1.operation_mode = operation_mode, + pll1.pll_type = pll_type, + pll1.qualify_conf_done = qualify_conf_done, + pll1.compensate_clock = compensate_clock, + pll1.inclk0_input_frequency = inclk0_input_frequency, + pll1.inclk1_input_frequency = inclk1_input_frequency, + pll1.gate_lock_signal = gate_lock_signal, + pll1.gate_lock_counter = gate_lock_counter, + pll1.valid_lock_multiplier = valid_lock_multiplier, + pll1.invalid_lock_multiplier = invalid_lock_multiplier, + pll1.switch_over_type = switch_over_type, + pll1.switch_over_on_lossclk = switch_over_on_lossclk, + pll1.switch_over_on_gated_lock = switch_over_on_gated_lock, + pll1.enable_switch_over_counter = enable_switch_over_counter, + pll1.switch_over_counter = switch_over_counter, + pll1.feedback_source = (feedback_source == "EXTCLK0") ? "CLK0" : feedback_source, + pll1.bandwidth = bandwidth, + pll1.bandwidth_type = bandwidth_type, + pll1.spread_frequency = spread_frequency, + pll1.down_spread = down_spread, + pll1.self_reset_on_gated_loss_lock = self_reset_on_gated_loss_lock, + pll1.simulation_type = simulation_type, + + // internal clock specifications + pll1.clk5_multiply_by = clk5_multiply_by, + pll1.clk4_multiply_by = clk4_multiply_by, + pll1.clk3_multiply_by = clk3_multiply_by, + pll1.clk2_multiply_by = clk2_multiply_by, + pll1.clk1_multiply_by = clk1_multiply_by, + pll1.clk0_multiply_by = clk0_multiply_by, + pll1.clk5_divide_by = clk5_divide_by, + pll1.clk4_divide_by = clk4_divide_by, + pll1.clk3_divide_by = clk3_divide_by, + pll1.clk2_divide_by = clk2_divide_by, + pll1.clk1_divide_by = clk1_divide_by, + pll1.clk0_divide_by = clk0_divide_by, + pll1.clk5_phase_shift = clk5_phase_shift, + pll1.clk4_phase_shift = clk4_phase_shift, + pll1.clk3_phase_shift = clk3_phase_shift, + pll1.clk2_phase_shift = clk2_phase_shift, + pll1.clk1_phase_shift = clk1_phase_shift, + pll1.clk0_phase_shift = clk0_phase_shift, + pll1.clk5_duty_cycle = clk5_duty_cycle, + pll1.clk4_duty_cycle = clk4_duty_cycle, + pll1.clk3_duty_cycle = clk3_duty_cycle, + pll1.clk2_duty_cycle = clk2_duty_cycle, + pll1.clk1_duty_cycle = clk1_duty_cycle, + pll1.clk0_duty_cycle = clk0_duty_cycle, + pll1.vco_multiply_by = vco_multiply_by, + pll1.vco_divide_by = vco_divide_by, + pll1.clk2_output_frequency = clk2_output_frequency, + pll1.clk1_output_frequency = clk1_output_frequency, + pll1.clk0_output_frequency = clk0_output_frequency, + + // advanced parameters + pll1.vco_min = vco_min, + pll1.vco_max = vco_max, + pll1.vco_center = vco_center, + pll1.pfd_min = pfd_min, + pll1.pfd_max = pfd_max, + pll1.m_initial = m_initial, + pll1.m = m, + pll1.n = n, + pll1.m2 = m2, + pll1.n2 = n2, + pll1.ss = ss, + pll1.c0_high = c0_high, + pll1.c1_high = c1_high, + pll1.c2_high = c2_high, + pll1.c3_high = c3_high, + pll1.c4_high = c4_high, + pll1.c5_high = c5_high, + pll1.c0_low = c0_low, + pll1.c1_low = c1_low, + pll1.c2_low = c2_low, + pll1.c3_low = c3_low, + pll1.c4_low = c4_low, + pll1.c5_low = c5_low, + pll1.c0_initial = c0_initial, + pll1.c1_initial = c1_initial, + pll1.c2_initial = c2_initial, + pll1.c3_initial = c3_initial, + pll1.c4_initial = c4_initial, + pll1.c5_initial = c5_initial, + pll1.c0_mode = c0_mode, + pll1.c1_mode = c1_mode, + pll1.c2_mode = c2_mode, + pll1.c3_mode = c3_mode, + pll1.c4_mode = c4_mode, + pll1.c5_mode = c5_mode, + pll1.c0_ph = c0_ph, + pll1.c1_ph = c1_ph, + pll1.c2_ph = c2_ph, + pll1.c3_ph = c3_ph, + pll1.c4_ph = c4_ph, + pll1.c5_ph = c5_ph, + pll1.m_ph = m_ph, + pll1.c1_use_casc_in = c1_use_casc_in, + pll1.c2_use_casc_in = c2_use_casc_in, + pll1.c3_use_casc_in = c3_use_casc_in, + pll1.c4_use_casc_in = c4_use_casc_in, + pll1.c5_use_casc_in = c5_use_casc_in, + pll1.clk5_counter = (clk5_counter == "l1") ? "c5" : clk5_counter, + pll1.clk4_counter = (clk4_counter == "l0") ? "c4" : clk4_counter, + pll1.clk3_counter = (clk3_counter == "g3") ? "c3" : clk3_counter, + pll1.clk2_counter = (clk2_counter == "g2") ? "c2" : clk2_counter, + pll1.clk1_counter = (clk1_counter == "g1") ? "c1" : clk1_counter, + pll1.clk0_counter = (clk0_counter == "g0") ? "c0" : clk0_counter, + pll1.enable0_counter = (enable0_counter == "l0") ? "c0" : enable0_counter, + pll1.enable1_counter = (enable1_counter == "l0") ? "c1" : enable1_counter, + pll1.charge_pump_current = charge_pump_current, + pll1.loop_filter_r = loop_filter_r, + pll1.loop_filter_c = loop_filter_c, + pll1.m_test_source = m_test_source, + pll1.c0_test_source = c0_test_source, + pll1.c1_test_source = c1_test_source, + pll1.c2_test_source = c2_test_source, + pll1.c3_test_source = c3_test_source, + pll1.c4_test_source = c4_test_source, + pll1.c5_test_source = c5_test_source; + +// CONTINOUS ASSIGNMENT +assign fbin_pullup = ((port_fbin == "PORT_CONNECTIVITY") || + (port_fbin == "PORT_USED")) ? fbin : 1'b1; +assign ena_pullup = ((port_pllena == "PORT_CONNECTIVITY") || + (port_pllena == "PORT_USED")) ? pllena : 1'b1; +assign pfdena_pullup = ((port_pfdena == "PORT_CONNECTIVITY") || + (port_pfdena == "PORT_USED")) ? pfdena : 1'b1; +assign clkena_pullup[0] = (!((pll_type == "fast") || (pll_type == "FAST")) || + (port_clkena0 == "PORT_USED")) && + (port_clkena0 != "PORT_UNUSED") ? clkena[0] : 1'b1; +assign clkena_pullup[1] = (!((pll_type == "fast") || (pll_type == "FAST")) || + (port_clkena1 == "PORT_USED")) && + (port_clkena1 != "PORT_UNUSED") ? clkena[1] : 1'b1; +assign clkena_pullup[2] = (!((pll_type == "fast") || (pll_type == "FAST")) || + (port_clkena2 == "PORT_USED")) && + (port_clkena2 != "PORT_UNUSED") ? clkena[2] : 1'b1; +assign clkena_pullup[3] = (!((pll_type == "fast") || (pll_type == "FAST")) || + (port_clkena3 == "PORT_USED")) && + (port_clkena3 != "PORT_UNUSED") ? clkena[3] : 1'b1; +assign clkena_pullup[4] = (!((pll_type == "fast") || (pll_type == "FAST")) || + (port_clkena4 == "PORT_USED")) && + (port_clkena4 != "PORT_UNUSED") ? clkena[4] : 1'b1; +assign clkena_pullup[5] = (!((pll_type == "fast") || (pll_type == "FAST")) || + (port_clkena5 == "PORT_USED")) && + (port_clkena5 != "PORT_UNUSED") ? clkena[5] : 1'b1; + +assign extclkena_pullup[0] = (!((pll_type == "fast") || (pll_type == "FAST")) || + (port_extclkena0 == "PORT_USED")) && + (port_extclkena0 != "PORT_UNUSED") ? extclkena[0] : 1'b1; +assign extclkena_pullup[1] = (!((pll_type == "fast") || (pll_type == "FAST")) || + (port_extclkena1 == "PORT_USED")) && + (port_extclkena1 != "PORT_UNUSED") ? extclkena[1] : 1'b1; +assign extclkena_pullup[2] = (!((pll_type == "fast") || (pll_type == "FAST")) || + (port_extclkena2 == "PORT_USED")) && + (port_extclkena2 != "PORT_UNUSED") ? extclkena[2] : 1'b1; +assign extclkena_pullup[3] = (!((pll_type == "fast") || (pll_type == "FAST")) || + (port_extclkena3 == "PORT_USED")) && + (port_extclkena3 != "PORT_UNUSED") ? extclkena[3] : 1'b1; +assign scanclk_pulldown = scanclk; +assign scanread_pulldown = ((port_scanread == "PORT_CONNECTIVITY") || + (port_scanread == "PORT_USED")) ? scanread : 1'b0; +assign scanwrite_pulldown = ((port_scanwrite == "PORT_CONNECTIVITY") || + (port_scanwrite == "PORT_USED")) ? scanwrite : 1'b0; +assign scandata_pulldown = ((port_scandata == "PORT_CONNECTIVITY") || + (port_scandata == "PORT_USED")) ? scandata : 1'b0; +assign inclk_pulldown = inclk; +assign clkswitch_pulldown = ((port_clkswitch == "PORT_CONNECTIVITY") || + (port_clkswitch == "PORT_USED")) ? clkswitch : 1'b0; +assign areset_pulldown = ((port_areset == "PORT_CONNECTIVITY") || + (port_areset == "PORT_USED")) ? areset : 1'b0; +assign scanclr_pulldown = ((port_scanaclr == "PORT_CONNECTIVITY") || + (port_scanaclr == "PORT_USED")) ? scanaclr : 1'b0; + +assign stratix_inclk = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? inclk_pulldown : {2{1'b0}}; +assign stratix_fbin = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? fbin_pullup : 1'b0; +assign stratix_ena = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? ena_pullup : 1'b0; +assign stratix_clkswitch = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? clkswitch_pulldown : 1'b0; +assign stratix_areset = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? areset_pulldown : 1'b0; +assign stratix_pfdena = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? pfdena_pullup : 1'b1; +assign stratix_clkena = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? clkena_pullup : {5{1'b0}}; +assign stratix_extclkena = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? extclkena_pullup : {3{1'b0}}; +assign stratix_scanclk = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? scanclk_pulldown : 1'b0; +assign stratix_scanclr = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? scanclr_pulldown : 1'b0; +assign stratix_scandata = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) && + !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? scandata_pulldown : 1'b0; +assign stratixii_inclk = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? inclk_pulldown : {2{1'b0}}; +assign stratixii_fbin = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? fbin_pullup : 1'b0; +assign stratixii_ena = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? ena_pullup : 1'b0; +assign stratixii_clkswitch = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? clkswitch_pulldown : 1'b0; +assign stratixii_areset = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? areset_pulldown : 1'b0; +assign stratixii_pfdena = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? pfdena_pullup : 1'b1; +assign stratixii_scanread = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? scanread_pulldown : 1'b0; +assign stratixii_scanwrite = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? scanwrite_pulldown : 1'b0; +assign stratixii_scanclk = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? scanclk_pulldown : 1'b0; +assign stratixii_scandata = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? scandata_pulldown : 1'b0; +assign scandone_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_scandone : 1'b0; +assign scandone = (port_scandone != "PORT_UNUSED") ? scandone_wire : 1'b0; +assign clk_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_clk : + (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? {3'b0, stratixii_clk[2:0]} : stratix_clk; +assign clk[0] = (port_clk0 != "PORT_UNUSED") ? clk_wire[0] : 1'b0; +assign clk[1] = (port_clk1 != "PORT_UNUSED") ? clk_wire[1] : 1'b0; +assign clk[2] = (port_clk2 != "PORT_UNUSED") ? clk_wire[2] : 1'b0; +assign clk[3] = (port_clk3 != "PORT_UNUSED") ? clk_wire[3] : 1'b0; +assign clk[4] = (port_clk4 != "PORT_UNUSED") ? clk_wire[4] : 1'b0; +assign clk[5] = (port_clk5 != "PORT_UNUSED") ? clk_wire[5] : 1'b0; +assign extclk[0] = (port_extclk0 != "PORT_UNUSED") ? stratix_extclk[0] : 1'b0; +assign extclk[1] = (port_extclk1 != "PORT_UNUSED") ? stratix_extclk[1] : 1'b0; +assign extclk[2] = (port_extclk2 != "PORT_UNUSED") ? stratix_extclk[2] : 1'b0; +assign extclk[3] = (port_extclk3 != "PORT_UNUSED") ? stratix_extclk[3] : 1'b0; +assign clkbad_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_clkbad : + (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 2'b0 : stratix_clkbad; +assign clkbad[0] = (port_clkbad0 != "PORT_UNUSED") ? clkbad_wire[0] : 1'b0; +assign clkbad[1] = (port_clkbad1 != "PORT_UNUSED") ? clkbad_wire[1] : 1'b0; +assign activeclock_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_activeclock : + (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 1'b0 : stratix_activeclock; +assign activeclock = (port_activeclock != "PORT_UNUSED") ? activeclock_wire : 1'b0; +assign locked = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? stratixii_locked : stratix_locked; +assign stratix_locked = ((pll_type == "fast") || (pll_type == "FAST")) ? (!locked_tmp) : locked_tmp; +assign clkloss_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_clkloss : + (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 1'b0 : stratix_clkloss; +assign clkloss = (port_clkloss != "PORT_UNUSED") ? clkloss_wire : 1'b0; +assign scandataout_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_scandataout : + (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 1'b0 : stratix_scandataout; +assign scandataout = (port_scandataout != "PORT_UNUSED") ? scandataout_wire : 1'b0; +assign enable0 = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_enable0 : + (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 1'b0 : stratix_enable0; +assign enable1 = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_enable1 : + (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 1'b0 : stratix_enable1; +assign sclkout0_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_sclkout0 : 1'b0; +assign sclkout0 = (port_sclkout0 != "PORT_UNUSED") ? sclkout0_wire : 1'b0; +assign sclkout1_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_sclkout1 : 1'b0; +assign sclkout1 = (port_sclkout1 != "PORT_UNUSED") ? sclkout1_wire : 1'b0; +endmodule //altpll + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module 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_MODULE_NAME-------------------------------------------------------------- + +// BEGINNING OF MODULE + +`timescale 1 ps / 1 ps + +module altaccumulate (cin, data, add_sub, clock, sload, clken, sign_data, aclr, + result, cout, overflow); + + parameter width_in = 4; // Required + parameter width_out = 8; // Required + parameter lpm_representation = "UNSIGNED"; + parameter extra_latency = 0; + parameter use_wys = "ON"; + parameter lpm_hint = "UNUSED"; + parameter lpm_type = "altaccumulate"; + + // INPUT PORT DECLARATION + input cin; + input [width_in-1:0] data; // Required port + input add_sub; // Default = 1 + input clock; // Required port + input sload; // Default = 0 + input clken; // Default = 1 + input sign_data; // Default = 0 + input aclr; // Default = 0 + + // OUTPUT PORT DECLARATION + output [width_out-1:0] result; //Required port + output cout; + output overflow; + + // INTERNAL REGISTERS DECLARATION + reg [width_out:0] temp_sum; + reg overflow; + reg overflow_int; + reg cout_int; + reg cout_delayed; + + reg [width_out-1:0] result; + reg [width_out+1:0] result_int; + reg [(width_out - width_in) : 0] zeropad; + + reg borrow; + reg cin_int; + + reg [width_out-1:0] fb_int; + reg [width_out -1:0] data_int; + + reg [width_out+1:0] result_pipe [extra_latency:0]; + reg [width_out+1:0] result_full; + reg [width_out+1:0] result_full2; + + reg a; + + // INTERNAL WIRE DECLARATION + wire [width_out:0] temp_sum_wire; + wire cout; + wire cout_int_wire; + wire cout_delayed_wire; + wire overflow_int_wire; + wire [width_out+1:0] result_int_wire; + + // INTERNAL TRI DECLARATION + + tri0 aclr_int; + tri0 sign_data_int; + tri0 sload_int; + + tri1 clken_int; + tri1 add_sub_int; + + // LOCAL INTEGER DECLARATION + integer head; + integer i; + + // INITIAL CONSTRUCT BLOCK + initial + begin + + // Checking for invalid parameters + if( width_in <= 0 ) + begin + $display("Error! Value of width_in parameter must be greater than 0."); + $stop; + end + + if( width_out <= 0 ) + begin + $display("Error! Value of width_out parameter must be greater than 0."); + $stop; + end + + if( extra_latency > width_out ) + begin + $display("Info: Value of extra_latency parameter should be lower than width_out parameter for better performance/utilization."); + end + + if( width_in > width_out ) + begin + $display("Error! Value of width_in parameter should be lower than or equal to width_out."); + $stop; + end + + result = 0; + cout_delayed = 0; + overflow = 0; + head = 0; + result_int = 0; + for (i = 0; i <= extra_latency; i = i +1) + begin + result_pipe [i] = 0; + end + end + + // ALWAYS CONSTRUCT BLOCK + always @(posedge clock or posedge aclr_int) + begin + + if (aclr_int == 1) + begin + result_int = 0; + result = 0; + overflow = 0; + cout_delayed = 0; + for (i = 0; i <= extra_latency; i = i +1) + begin + result_pipe [i] = 0; + end + + end + else + begin + if (clken_int == 1) + begin + //get result from output register + if (extra_latency > 0) + begin + result_pipe [head] = { + result_int [width_out+1], + {cout_int_wire, result_int [width_out-1:0]} + }; + + head = (head + 1) % (extra_latency); + + result_full = result_pipe [head]; + cout_delayed = result_full [width_out]; + result = result_full [width_out-1:0]; + overflow = result_full [width_out+1]; + end + else + begin + result = temp_sum_wire; + overflow = overflow_int_wire; + end + + result_int = {overflow_int_wire, {cout_int_wire, temp_sum_wire [width_out-1:0]}}; + end + end + end + + + always @ (data or cin or add_sub_int or sign_data_int or + result_int_wire [width_out -1:0] or sload_int) + begin + + if ((lpm_representation == "SIGNED") || (sign_data_int == 1)) + begin + zeropad = (data [width_in-1] ==0) ? 0 : -1; + end + else + begin + zeropad = 0; + end + + fb_int = (sload_int == 1'b1) ? 0 : result_int_wire [width_out-1:0]; + data_int = {zeropad, data}; + + if ((add_sub_int == 1) || (sload_int == 1)) + begin + cin_int = ((sload_int == 1'b1) ? 0 : ((cin === 1'bz) ? 0 : cin)); + temp_sum = fb_int + data_int + cin_int; + cout_int = temp_sum [width_out]; + end + else + begin + cin_int = (cin === 1'bz) ? 1 : cin; + borrow = ~cin_int; + + temp_sum = fb_int - data_int - borrow; + + result_full2 = data_int + borrow; + cout_int = (fb_int >= result_full2) ? 1 : 0; + end + + if ((lpm_representation == "SIGNED") || (sign_data_int == 1)) + begin + a = (data [width_in-1] ~^ fb_int [width_out-1]) ^ (~add_sub_int); + overflow_int = a & (fb_int [width_out-1] ^ temp_sum[width_out-1]); + end + else + begin + overflow_int = (add_sub_int == 1) ? cout_int : ~cout_int; + end + + if (sload_int == 1) + begin + cout_int = !add_sub_int; + overflow_int = 0; + end + + end + + // CONTINOUS ASSIGNMENT + + // Get the input data and control signals. + assign sign_data_int = sign_data; + assign sload_int = sload; + assign add_sub_int = add_sub; + + assign clken_int = clken; + assign aclr_int = aclr; + assign result_int_wire = result_int; + assign temp_sum_wire = temp_sum; + assign cout_int_wire = cout_int; + assign overflow_int_wire = overflow_int; + assign cout = (extra_latency == 0) ? cout_int_wire : cout_delayed_wire; + assign cout_delayed_wire = cout_delayed; + +endmodule // End of altaccumulate + +// END OF MODULE + +//-------------------------------------------------------------------------- +// Module Name : altmult_accum +// +// Description : a*b + x (MAC) +// +// Limitation : Stratix DSP block +// +// Results expected : signed & unsigned, maximum of 3 pipelines(latency) each. +// +//-------------------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +module altmult_accum ( dataa, + datab, + scanina, + scaninb, + sourcea, + sourceb, + accum_sload_upper_data, + addnsub, + accum_sload, + signa, + signb, + clock0, + clock1, + clock2, + clock3, + ena0, + ena1, + ena2, + ena3, + aclr0, + aclr1, + aclr2, + aclr3, + result, + overflow, + scanouta, + scanoutb, + mult_round, + mult_saturation, + accum_round, + accum_saturation, + mult_is_saturated, + accum_is_saturated); + + // --------------------- + // PARAMETER DECLARATION + // --------------------- + parameter width_a = 2; + parameter width_b = 2; + parameter width_result = 5; + parameter input_reg_a = "CLOCK0"; + parameter input_aclr_a = "ACLR3"; + parameter input_reg_b = "CLOCK0"; + parameter input_aclr_b = "ACLR3"; + parameter port_addnsub = "PORT_CONNECTIVITY"; + parameter addnsub_reg = "CLOCK0"; + parameter addnsub_aclr = "ACLR3"; + parameter addnsub_pipeline_reg = "CLOCK0"; + parameter addnsub_pipeline_aclr = "ACLR3"; + parameter accum_direction = "ADD"; + parameter accum_sload_reg = "CLOCK0"; + parameter accum_sload_aclr = "ACLR3"; + parameter accum_sload_pipeline_reg = "CLOCK0"; + parameter accum_sload_pipeline_aclr = "ACLR3"; + parameter representation_a = "UNSIGNED"; + parameter port_signa = "PORT_CONNECTIVITY"; + parameter sign_reg_a = "CLOCK0"; + parameter sign_aclr_a = "ACLR3"; + parameter sign_pipeline_reg_a = "CLOCK0"; + parameter sign_pipeline_aclr_a = "ACLR3"; + parameter port_signb = "PORT_CONNECTIVITY"; + parameter representation_b = "UNSIGNED"; + parameter sign_reg_b = "CLOCK0"; + parameter sign_aclr_b = "ACLR3"; + parameter sign_pipeline_reg_b = "CLOCK0"; + parameter sign_pipeline_aclr_b = "ACLR3"; + parameter multiplier_reg = "CLOCK0"; + parameter multiplier_aclr = "ACLR3"; + parameter output_reg = "CLOCK0"; + parameter output_aclr = "ACLR3"; + parameter lpm_type = "altmult_accum"; + parameter lpm_hint = "UNUSED"; + + parameter extra_multiplier_latency = 0; + parameter extra_accumulator_latency = 0; + parameter dedicated_multiplier_circuitry = "AUTO"; + parameter dsp_block_balancing = "AUTO"; + parameter intended_device_family = "Stratix"; + + // StratixII related parameter + parameter accum_round_aclr = "ACLR3"; + parameter accum_round_pipeline_aclr = "ACLR3"; + parameter accum_round_pipeline_reg = "CLOCK0"; + parameter accum_round_reg = "CLOCK0"; + parameter accum_saturation_aclr = "ACLR3"; + parameter accum_saturation_pipeline_aclr = "ACLR3"; + parameter accum_saturation_pipeline_reg = "CLOCK0"; + parameter accum_saturation_reg = "CLOCK0"; + parameter accum_sload_upper_data_aclr = "ACLR3"; + parameter accum_sload_upper_data_pipeline_aclr = "ACLR3"; + parameter accum_sload_upper_data_pipeline_reg = "CLOCK0"; + parameter accum_sload_upper_data_reg = "CLOCK0"; + parameter mult_round_aclr = "ACLR3"; + parameter mult_round_reg = "CLOCK0"; + parameter mult_saturation_aclr = "ACLR3"; + parameter mult_saturation_reg = "CLOCK0"; + + parameter input_source_a = "DATAA"; + parameter input_source_b = "DATAB"; + parameter width_upper_data = 1; + parameter multiplier_rounding = "NO"; + parameter multiplier_saturation = "NO"; + parameter accumulator_rounding = "NO"; + parameter accumulator_saturation = "NO"; + parameter port_mult_is_saturated = "UNUSED"; + parameter port_accum_is_saturated = "UNUSED"; + + // ----------------------- + // Local parameters + // ----------------------- + parameter int_width_a = ((multiplier_saturation == "NO") && (multiplier_rounding == "NO") && (accumulator_saturation == "NO") && (accumulator_rounding == "NO")) ? width_a : 18; + parameter int_width_b = ((multiplier_saturation == "NO") && (multiplier_rounding == "NO") && (accumulator_saturation == "NO") && (accumulator_rounding == "NO")) ? width_b : 18; + parameter int_width_result = ((multiplier_saturation == "NO") && (multiplier_rounding == "NO") && (accumulator_saturation == "NO") && (accumulator_rounding == "NO")) ? width_result : 52; + parameter int_extra_width = ((multiplier_saturation == "NO") && (multiplier_rounding == "NO") && (accumulator_saturation == "NO") && (accumulator_rounding == "NO")) ? 0 : (int_width_a + int_width_b - width_a - width_b); + parameter diff_width_a = (int_width_a > width_a) ? int_width_a - width_a : 1; + parameter diff_width_b = (int_width_b > width_b) ? int_width_b - width_b : 1; + parameter sat_for_ini = ((multiplier_saturation == "NO") && (accumulator_saturation == "NO")) ? 0 : (int_width_a + int_width_b - 34); + parameter mult_round_for_ini = ((multiplier_rounding == "NO")? 0 : (int_width_a + int_width_b - 18)); + parameter bits_to_round = (((multiplier_rounding == "NO") && (accumulator_rounding == "NO"))? 0 : int_width_a + int_width_b - 18); + parameter sload_for_limit = (width_result < width_upper_data)? width_result + int_extra_width : width_upper_data ; + parameter accum_sat_for_limit = ((accumulator_saturation == "NO")? int_width_result - 1 : int_width_a + int_width_b - 33 ); + // ---------------- + // PORT DECLARATION + // ---------------- + + // data input ports + input [width_a -1 : 0] dataa; + input [width_b -1 : 0] datab; + input [width_a -1 : 0] scanina; + input [width_b -1 : 0] scaninb; + input sourcea; + input sourceb; + input [width_result -1 : width_result - width_upper_data] accum_sload_upper_data; + + // control signals + input addnsub; + input accum_sload; + input signa; + input signb; + + // clock ports + input clock0; + input clock1; + input clock2; + input clock3; + + // clock enable ports + input ena0; + input ena1; + input ena2; + input ena3; + + // clear ports + input aclr0; + input aclr1; + input aclr2; + input aclr3; + + // round and saturate ports + input mult_round; + input mult_saturation; + input accum_round; + input accum_saturation; + + // output ports + output [width_result -1 : 0] result; + output overflow; + output [width_a -1 : 0] scanouta; + output [width_b -1 : 0] scanoutb; + + output mult_is_saturated; + output accum_is_saturated; + + + // --------------- + // REG DECLARATION + // --------------- + reg [width_result -1 : 0] result; + + reg [int_width_result -1 : 0] mult_res_out; + reg [int_width_result : 0] temp_sum; + + + reg [width_result + 1 : 0] result_pipe [extra_accumulator_latency : 0]; + reg [width_result + 1 : 0] result_full ; + + reg [int_width_result - 1 : 0] result_int; + + reg [int_width_a - 1 : 0] mult_a_reg; + reg [int_width_a - 1 : 0] mult_a_int; + reg [int_width_a + int_width_b - 1 : 0] mult_res; + reg [int_width_a + int_width_b - 1 : 0] temp_mult_1; + reg [int_width_a + int_width_b - 1 : 0] temp_mult; + + + reg [int_width_b -1 :0] mult_b_reg; + reg [int_width_b -1 :0] mult_b_int; + + reg [5 + int_width_a + int_width_b + width_upper_data : 0] mult_pipe [extra_multiplier_latency:0]; + reg [5 + int_width_a + int_width_b + width_upper_data : 0] mult_full; + + reg [width_upper_data - 1 : 0] sload_upper_data_reg; + + reg [width_result - width_upper_data -1 + 4 : 0] lower_bits; + + reg mult_signed_out; + reg [width_upper_data - 1 : 0] sload_upper_data_pipe_reg; + + + reg zero_acc_reg; + reg zero_acc_pipe_reg; + reg sign_a_reg; + reg sign_a_pipe_reg; + reg sign_b_reg; + reg sign_b_pipe_reg; + reg addsub_reg; + reg addsub_pipe_reg; + + reg mult_signed; + reg temp_mult_signed; + reg neg_a; + reg neg_b; + + reg overflow_int; + reg cout_int; + reg overflow_tmp_int; + + reg overflow; + + reg [int_width_a + int_width_b -1 : 0] mult_round_out; + reg mult_saturate_overflow; + reg [int_width_a + int_width_b -1 : 0] mult_saturate_out; + reg [int_width_a + int_width_b -1 : 0] mult_result; + reg [int_width_a + int_width_b -1 : 0] mult_final_out; + + reg [int_width_result -1 : 0] accum_round_out; + reg accum_saturate_overflow; + reg [int_width_result -1 : 0] accum_saturate_out; + reg [int_width_result -1 : 0] accum_result; + reg [int_width_result -1 : 0] accum_final_out; + + tri0 mult_is_saturated_latent; + reg mult_is_saturated_int; + reg mult_is_saturated_reg; + + reg accum_is_saturated_latent; + reg [extra_accumulator_latency : 0] accum_saturate_pipe; + reg [extra_accumulator_latency : 0] mult_is_saturated_pipe; + + reg mult_round_tmp; + reg mult_saturation_tmp; + reg accum_round_tmp1; + reg accum_round_tmp2; + reg accum_saturation_tmp1; + reg accum_saturation_tmp2; + + reg [int_width_result - int_width_a - int_width_b + 2 - 1 : 0] accum_result_sign_bits; + + // ------------------- + // INTEGER DECLARATION + // ------------------- + integer head_result; + integer i; + integer i2; + integer i3; + integer i4; + integer head_mult; + integer flag; + + + //----------------- + // TRI DECLARATION + //----------------- + + + // Tri wire for clear signal + + tri0 input_a_wire_clr; + tri0 input_b_wire_clr; + + tri0 addsub_wire_clr; + tri0 addsub_pipe_wire_clr; + + tri0 zero_wire_clr; + tri0 zero_pipe_wire_clr; + + tri0 sign_a_wire_clr; + tri0 sign_pipe_a_wire_clr; + + tri0 sign_b_wire_clr; + tri0 sign_pipe_b_wire_clr; + + tri0 multiplier_wire_clr; + tri0 mult_pipe_wire_clr; + + tri0 output_wire_clr; + + tri0 mult_round_wire_clr; + tri0 mult_saturation_wire_clr; + + tri0 accum_round_wire_clr; + tri0 accum_round_pipe_wire_clr; + + tri0 accum_saturation_wire_clr; + tri0 accum_saturation_pipe_wire_clr; + + tri0 accum_sload_upper_data_wire_clr; + tri0 accum_sload_upper_data_pipe_wire_clr; + + + // Tri wire for enable signal + + tri1 input_a_wire_en; + tri1 input_b_wire_en; + + tri1 addsub_wire_en; + tri1 addsub_pipe_wire_en; + + tri1 zero_wire_en; + tri1 zero_pipe_wire_en; + + tri1 sign_a_wire_en; + tri1 sign_pipe_a_wire_en; + + tri1 sign_b_wire_en; + tri1 sign_pipe_b_wire_en; + + tri1 multiplier_wire_en; + tri1 mult_pipe_wire_en; + + tri1 output_wire_en; + + tri1 mult_round_wire_en; + tri1 mult_saturation_wire_en; + + tri1 accum_round_wire_en; + tri1 accum_round_pipe_wire_en; + + tri1 accum_saturation_wire_en; + tri1 accum_saturation_pipe_wire_en; + + tri1 accum_sload_upper_data_wire_en; + tri1 accum_sload_upper_data_pipe_wire_en; + + // ------------------------ + // SUPPLY WIRE DECLARATION + // ------------------------ + + supply0 [int_width_a + int_width_b - 1 : 0] temp_mult_zero; + + + // ---------------- + // WIRE DECLARATION + // ---------------- + + // Wire for Clock signals + + wire input_a_wire_clk; + wire input_b_wire_clk; + + wire addsub_wire_clk; + wire addsub_pipe_wire_clk; + + wire zero_wire_clk; + wire zero_pipe_wire_clk; + + wire sign_a_wire_clk; + wire sign_pipe_a_wire_clk; + + wire sign_b_wire_clk; + wire sign_pipe_b_wire_clk; + + wire multiplier_wire_clk; + wire mult_pipe_wire_clk; + + wire output_wire_clk; + + wire [width_a -1 : 0] scanouta; + wire [int_width_a + int_width_b -1 : 0] mult_out_latent; + wire [width_b -1 : 0] scanoutb; + + wire addsub_int; + wire sign_a_int; + wire sign_b_int; + + wire zero_acc_int; + wire sign_a_reg_int; + wire sign_b_reg_int; + + wire addsub_latent; + wire zeroacc_latent; + wire signa_latent; + wire signb_latent; + wire mult_signed_latent; + + wire [width_upper_data - 1 : 0] sload_upper_data_latent; + reg [int_width_result - 1 : 0] sload_upper_data_pipe_wire; + + wire [int_width_a -1 :0] mult_a_wire; + wire [int_width_b -1 :0] mult_b_wire; + wire [width_upper_data - 1 : 0] sload_upper_data_wire; + wire [int_width_a -1 : 0] mult_a_tmp; + wire [int_width_b -1 : 0] mult_b_tmp; + + wire zero_acc_wire; + wire zero_acc_pipe_wire; + + wire sign_a_wire; + wire sign_a_pipe_wire; + wire sign_b_wire; + wire sign_b_pipe_wire; + + wire addsub_wire; + wire addsub_pipe_wire; + + wire mult_round_int; + wire mult_round_wire_clk; + wire mult_saturation_int; + wire mult_saturation_wire_clk; + + wire accum_round_tmp1_wire; + wire accum_round_wire_clk; + wire accum_round_int; + wire accum_round_pipe_wire_clk; + + wire accum_saturation_tmp1_wire; + wire accum_saturation_wire_clk; + wire accum_saturation_int; + wire accum_saturation_pipe_wire_clk; + + wire accum_sload_upper_data_wire_clk; + wire accum_sload_upper_data_pipe_wire_clk; + wire [width_result -1 : width_result - width_upper_data] accum_sload_upper_data_int; + + tri0 mult_is_saturated_wire; + + // ------------------------ + // COMPONENT INSTANTIATIONS + // ------------------------ + ALTERA_DEVICE_FAMILIES dev (); + + + // -------------------- + // ASSIGNMENT STATEMENTS + // -------------------- + + + assign addsub_int = (port_addnsub == "PORT_USED") ? addsub_pipe_wire : + (port_addnsub == "PORT_UNUSED") ? ((accum_direction == "ADD") ? 1 : 0) : + ((addnsub ===1'bz) || + (addsub_wire_clk ===1'bz) || + (addsub_pipe_wire_clk ===1'bz)) ? + ((accum_direction == "ADD") ? 1 : 0) : addsub_pipe_wire; + + assign sign_a_int = (port_signa == "PORT_USED") ? sign_a_pipe_wire : + (port_signa == "PORT_UNUSED") ? ((representation_a == "SIGNED") ? 1 : 0) : + ((signa ===1'bz) || + (sign_a_wire_clk ===1'bz) || + (sign_pipe_a_wire_clk ===1'bz)) ? + ((representation_a == "SIGNED") ? 1 : 0) : sign_a_pipe_wire; + + assign sign_b_int = (port_signb == "PORT_USED") ? sign_b_pipe_wire : + (port_signb == "PORT_UNUSED") ? ((representation_b == "SIGNED") ? 1 : 0) : + ((signb ===1'bz) || + (sign_b_wire_clk ===1'bz) || + (sign_pipe_b_wire_clk ===1'bz)) ? + ((representation_b == "SIGNED") ? 1 : 0) : sign_b_pipe_wire; + + + + assign sign_a_reg_int = (port_signa == "PORT_USED") ? sign_a_wire : + (port_signa == "PORT_UNUSED") ? ((representation_a == "SIGNED") ? 1 : 0) : + ((signa ===1'bz) || + (sign_a_wire_clk ===1'bz) || + (sign_pipe_a_wire_clk ===1'bz)) ? + ((representation_a == "SIGNED") ? 1 : 0) : sign_a_wire; + + assign sign_b_reg_int = (port_signb == "PORT_USED") ? sign_b_wire : + (port_signb == "PORT_UNUSED") ? ((representation_b == "SIGNED") ? 1 : 0) : + ((signb ===1'bz) || + (sign_b_wire_clk ===1'bz) || + (sign_pipe_b_wire_clk ===1'bz)) ? + ((representation_b == "SIGNED") ? 1 : 0) : sign_b_wire; + + assign zero_acc_int = ((accum_sload ===1'bz) || + (zero_wire_clk===1'bz) || + (zero_pipe_wire_clk===1'bz)) ? + 0 : zero_acc_pipe_wire; + + assign accum_sload_upper_data_int = ((accum_sload_upper_data === {width_upper_data{1'bz}}) || + (accum_sload_upper_data_wire_clk === 1'bz) || + (accum_sload_upper_data_pipe_wire_clk === 1'bz)) ? + {width_upper_data{1'b0}} : accum_sload_upper_data; + + assign scanouta = mult_a_wire[int_width_a - 1 : int_width_a - width_a]; + assign scanoutb = mult_b_wire[int_width_b - 1 : int_width_b - width_b]; + + assign {addsub_latent, zeroacc_latent, signa_latent, signb_latent, mult_signed_latent, mult_out_latent, sload_upper_data_latent, mult_is_saturated_latent} = (extra_multiplier_latency > 0) ? + mult_full : {addsub_wire, zero_acc_wire, sign_a_wire, sign_b_wire, temp_mult_signed, mult_final_out, sload_upper_data_wire, mult_saturate_overflow}; + + assign mult_is_saturated = (port_mult_is_saturated != "UNUSED") ? mult_is_saturated_int : 0; + assign accum_is_saturated = (port_accum_is_saturated != "UNUSED") ? accum_is_saturated_latent : 0; + + + // --------------------------------------------------------------------------------- + // Initialization block where all the internal signals and registers are initialized + // --------------------------------------------------------------------------------- + initial + begin + + // Checking for invalid parameters, in case Wizard is bypassed (hand-modified). + + if ((dedicated_multiplier_circuitry != "AUTO") && + (dedicated_multiplier_circuitry != "YES") && + (dedicated_multiplier_circuitry != "NO")) + begin + $display("Error: The DEDICATED_MULTIPLIER_CIRCUITRY parameter is set to an illegal value."); + $stop; + end + if (width_a <= 0) + begin + $display("Error: width_a must be greater than 0."); + $stop; + end + if (width_b <= 0) + begin + $display("Error: width_b must be greater than 0."); + $stop; + end + if (width_result <= 0) + begin + $display("Error: width_result must be greater than 0."); + $stop; + end + + if (( (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && + (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) ) + && (input_source_a != "DATAA")) + begin + $display("Error: The input source for port A are limited to input dataa."); + $stop; + end + + if (( (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && + (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) ) + && (input_source_b != "DATAB")) + begin + $display("Error: The input source for port B are limited to input datab."); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (multiplier_rounding != "NO")) + begin + $display("Error: There is no rounding feature for %s device.", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (accumulator_rounding != "NO")) + begin + $display("Error: There is no rounding feature for %s device.", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (multiplier_saturation != "NO")) + begin + $display("Error: There is no saturation feature for %s device.", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (accumulator_saturation != "NO")) + begin + $display("Error: There is no saturation feature for %s device.", intended_device_family); + $stop; + end + + + temp_sum = 0; + head_result = 0; + head_mult = 0; + overflow_int = 0; + mult_a_reg = 0; + mult_b_reg = 0; + flag = 0; + + zero_acc_reg = 0; + zero_acc_pipe_reg = 0; + sload_upper_data_reg = 0; + lower_bits = 0; + sload_upper_data_pipe_reg = 0; + + sign_a_reg = (signa ===1'bz) ? ((representation_a == "SIGNED") ? 1 : 0) : 0; + sign_a_pipe_reg = (signa ===1'bz) ? ((representation_a == "SIGNED") ? 1 : 0) : 0; + sign_b_reg = (signb ===1'bz) ? ((representation_b == "SIGNED") ? 1 : 0) : 0; + sign_b_pipe_reg = (signb ===1'bz) ? ((representation_b == "SIGNED") ? 1 : 0) : 0; + addsub_reg = (addnsub ===1'bz) ? ((accum_direction == "ADD") ? 1 : 0) : 0; + addsub_pipe_reg = (addnsub ===1'bz) ? ((accum_direction == "ADD") ? 1 : 0) : 0; + + result_int = 0; + result = 0; + overflow = 0; + mult_full = 0; + mult_res_out = 0; + mult_signed_out = 0; + mult_res = 0; + + mult_is_saturated_int = 0; + mult_is_saturated_reg = 0; + mult_saturation_tmp = 0; + mult_saturate_overflow = 0; + + accum_result = 0; + accum_saturate_overflow = 0; + accum_is_saturated_latent = 0; + + for (i=0; i<=extra_accumulator_latency; i=i+1) + begin + result_pipe [i] = 0; + accum_saturate_pipe[i] = 0; + mult_is_saturated_pipe[i] = 0; + end + + for (i=0; i<= extra_multiplier_latency; i=i+1) + begin + mult_pipe [i] = 0; + end + + end + + + // --------------------------------------------------------- + // This block updates the internal clock signals accordingly + // every time the global clock signal changes state + // --------------------------------------------------------- + + assign input_a_wire_clk = (input_reg_a == "CLOCK0")? clock0: + (input_reg_a == "UNREGISTERED")? 0: + (input_reg_a == "CLOCK1")? clock1: + (input_reg_a == "CLOCK2")? clock2: + (input_reg_a == "CLOCK3")? clock3:0; + + assign input_b_wire_clk = (input_reg_b == "CLOCK0")? clock0: + (input_reg_b == "UNREGISTERED")? 0: + (input_reg_b == "CLOCK1")? clock1: + (input_reg_b == "CLOCK2")? clock2: + (input_reg_b == "CLOCK3")? clock3:0; + + + assign addsub_wire_clk = (addnsub_reg == "CLOCK0")? clock0: + (addnsub_reg == "UNREGISTERED")? 0: + (addnsub_reg == "CLOCK1")? clock1: + (addnsub_reg == "CLOCK2")? clock2: + (addnsub_reg == "CLOCK3")? clock3:0; + + + assign addsub_pipe_wire_clk = (addnsub_pipeline_reg == "CLOCK0")? clock0: + (addnsub_pipeline_reg == "UNREGISTERED")? 0: + (addnsub_pipeline_reg == "CLOCK1")? clock1: + (addnsub_pipeline_reg == "CLOCK2")? clock2: + (addnsub_pipeline_reg == "CLOCK3")? clock3:0; + + + assign zero_wire_clk = (accum_sload_reg == "CLOCK0")? clock0: + (accum_sload_reg == "UNREGISTERED")? 0: + (accum_sload_reg == "CLOCK1")? clock1: + (accum_sload_reg == "CLOCK2")? clock2: + (accum_sload_reg == "CLOCK3")? clock3:0; + + assign accum_sload_upper_data_wire_clk = (accum_sload_upper_data_reg == "CLOCK0")? clock0: + (accum_sload_upper_data_reg == "UNREGISTERED")? 0: + (accum_sload_upper_data_reg == "CLOCK1")? clock1: + (accum_sload_upper_data_reg == "CLOCK2")? clock2: + (accum_sload_upper_data_reg == "CLOCK3")? clock3:0; + + assign zero_pipe_wire_clk = (accum_sload_pipeline_reg == "CLOCK0")? clock0: + (accum_sload_pipeline_reg == "UNREGISTERED")? 0: + (accum_sload_pipeline_reg == "CLOCK1")? clock1: + (accum_sload_pipeline_reg == "CLOCK2")? clock2: + (accum_sload_pipeline_reg == "CLOCK3")? clock3:0; + + assign accum_sload_upper_data_pipe_wire_clk = (accum_sload_upper_data_pipeline_reg == "CLOCK0")? clock0: + (accum_sload_upper_data_pipeline_reg == "UNREGISTERED")? 0: + (accum_sload_upper_data_pipeline_reg == "CLOCK1")? clock1: + (accum_sload_upper_data_pipeline_reg == "CLOCK2")? clock2: + (accum_sload_upper_data_pipeline_reg == "CLOCK3")? clock3:0; + + assign sign_a_wire_clk =(sign_reg_a == "CLOCK0")? clock0: + (sign_reg_a == "UNREGISTERED")? 0: + (sign_reg_a == "CLOCK1")? clock1: + (sign_reg_a == "CLOCK2")? clock2: + (sign_reg_a == "CLOCK3")? clock3:0; + + + assign sign_b_wire_clk =(sign_reg_b == "CLOCK0")? clock0: + (sign_reg_b == "UNREGISTERED")? 0: + (sign_reg_b == "CLOCK1")? clock1: + (sign_reg_b == "CLOCK2")? clock2: + (sign_reg_b == "CLOCK3")? clock3:0; + + + + assign sign_pipe_a_wire_clk = (sign_pipeline_reg_a == "CLOCK0")? clock0: + (sign_pipeline_reg_a == "UNREGISTERED")? 0: + (sign_pipeline_reg_a == "CLOCK1")? clock1: + (sign_pipeline_reg_a == "CLOCK2")? clock2: + (sign_pipeline_reg_a == "CLOCK3")? clock3:0; + + + assign sign_pipe_b_wire_clk = (sign_pipeline_reg_b == "CLOCK0")? clock0: + (sign_pipeline_reg_b == "UNREGISTERED")? 0: + (sign_pipeline_reg_b == "CLOCK1")? clock1: + (sign_pipeline_reg_b == "CLOCK2")? clock2: + (sign_pipeline_reg_b == "CLOCK3")? clock3:0; + + + assign multiplier_wire_clk =(multiplier_reg == "CLOCK0")? clock0: + (multiplier_reg == "UNREGISTERED")? 0: + (multiplier_reg == "CLOCK1")? clock1: + (multiplier_reg == "CLOCK2")? clock2: + (multiplier_reg == "CLOCK3")? clock3:0; + + assign output_wire_clk = (output_reg == "CLOCK0")? clock0: + (output_reg == "UNREGISTERED")? 0: + (output_reg == "CLOCK1")? clock1: + (output_reg == "CLOCK2")? clock2: + (output_reg == "CLOCK3")? clock3:0; + + + assign mult_pipe_wire_clk = (multiplier_reg == "UNREGISTERED")? clock0: + multiplier_wire_clk; + + assign mult_round_wire_clk =(mult_round_reg == "CLOCK0")? clock0: + (mult_round_reg == "UNREGISTERED")? 0: + (mult_round_reg == "CLOCK1")? clock1: + (mult_round_reg == "CLOCK2")? clock2: + (mult_round_reg == "CLOCK3")? clock3:0; + + assign mult_saturation_wire_clk = (mult_saturation_reg == "CLOCK0")? clock0: + (mult_saturation_reg == "UNREGISTERED")? 0: + (mult_saturation_reg == "CLOCK1")? clock1: + (mult_saturation_reg == "CLOCK2")? clock2: + (mult_saturation_reg == "CLOCK3")? clock3:0; + + assign accum_round_wire_clk = (accum_round_reg == "CLOCK0")? clock0: + (accum_round_reg == "UNREGISTERED")? 0: + (accum_round_reg == "CLOCK1")? clock1: + (accum_round_reg == "CLOCK2")? clock2: + (accum_round_reg == "CLOCK3")? clock3:0; + + assign accum_round_pipe_wire_clk = (accum_round_pipeline_reg == "CLOCK0")? clock0: + (accum_round_pipeline_reg == "UNREGISTERED")? 0: + (accum_round_pipeline_reg == "CLOCK1")? clock1: + (accum_round_pipeline_reg == "CLOCK2")? clock2: + (accum_round_pipeline_reg == "CLOCK3")? clock3:0; + + assign accum_saturation_wire_clk = (accum_saturation_reg == "CLOCK0")? clock0: + (accum_saturation_reg == "UNREGISTERED")? 0: + (accum_saturation_reg == "CLOCK1")? clock1: + (accum_saturation_reg == "CLOCK2")? clock2: + (accum_saturation_reg == "CLOCK3")? clock3:0; + + assign accum_saturation_pipe_wire_clk = (accum_saturation_pipeline_reg == "CLOCK0")? clock0: + (accum_saturation_pipeline_reg == "UNREGISTERED")? 0: + (accum_saturation_pipeline_reg == "CLOCK1")? clock1: + (accum_saturation_pipeline_reg == "CLOCK2")? clock2: + (accum_saturation_pipeline_reg == "CLOCK3")? clock3:0; + + + // ---------------------------------------------------------------- + // This block updates the internal clock enable signals accordingly + // every time the global clock enable signal changes state + // ---------------------------------------------------------------- + + + + assign input_a_wire_en =(input_reg_a == "CLOCK0")? ena0: + (input_reg_a == "UNREGISTERED")? 1: + (input_reg_a == "CLOCK1")? ena1: + (input_reg_a == "CLOCK2")? ena2: + (input_reg_a == "CLOCK3")? ena3:1; + + assign input_b_wire_en =(input_reg_b == "CLOCK0")? ena0: + (input_reg_b == "UNREGISTERED")? 1: + (input_reg_b == "CLOCK1")? ena1: + (input_reg_b == "CLOCK2")? ena2: + (input_reg_b == "CLOCK3")? ena3:1; + + + assign addsub_wire_en = (addnsub_reg == "CLOCK0")? ena0: + (addnsub_reg == "UNREGISTERED")? 1: + (addnsub_reg == "CLOCK1")? ena1: + (addnsub_reg == "CLOCK2")? ena2: + (addnsub_reg == "CLOCK3")? ena3:1; + + + assign addsub_pipe_wire_en =(addnsub_pipeline_reg == "CLOCK0")? ena0: + (addnsub_pipeline_reg == "UNREGISTERED")? 1: + (addnsub_pipeline_reg == "CLOCK1")? ena1: + (addnsub_pipeline_reg == "CLOCK2")? ena2: + (addnsub_pipeline_reg == "CLOCK3")? ena3:1; + + + assign zero_wire_en = (accum_sload_reg == "CLOCK0")? ena0: + (accum_sload_reg == "UNREGISTERED")? 1: + (accum_sload_reg == "CLOCK1")? ena1: + (accum_sload_reg == "CLOCK2")? ena2: + (accum_sload_reg == "CLOCK3")? ena3:1; + + assign accum_sload_upper_data_wire_en = (accum_sload_upper_data_reg == "CLOCK0")? ena0: + (accum_sload_upper_data_reg == "UNREGISTERED")? 1: + (accum_sload_upper_data_reg == "CLOCK1")? ena1: + (accum_sload_upper_data_reg == "CLOCK2")? ena2: + (accum_sload_upper_data_reg == "CLOCK3")? ena3:1; + + assign zero_pipe_wire_en = (accum_sload_pipeline_reg == "CLOCK0")? ena0: + (accum_sload_pipeline_reg == "UNREGISTERED")? 1: + (accum_sload_pipeline_reg == "CLOCK1")? ena1: + (accum_sload_pipeline_reg == "CLOCK2")? ena2: + (accum_sload_pipeline_reg == "CLOCK3")? ena3:1; + + assign accum_sload_upper_data_pipe_wire_en = (accum_sload_upper_data_pipeline_reg == "CLOCK0")? ena0: + (accum_sload_upper_data_pipeline_reg == "UNREGISTERED")? 1: + (accum_sload_upper_data_pipeline_reg == "CLOCK1")? ena1: + (accum_sload_upper_data_pipeline_reg == "CLOCK2")? ena2: + (accum_sload_upper_data_pipeline_reg == "CLOCK3")? ena3:1; + + assign sign_a_wire_en = (sign_reg_a == "CLOCK0")? ena0: + (sign_reg_a == "UNREGISTERED")? 1: + (sign_reg_a == "CLOCK1")? ena1: + (sign_reg_a == "CLOCK2")? ena2: + (sign_reg_a == "CLOCK3")? ena3:1; + + + assign sign_b_wire_en = (sign_reg_b == "CLOCK0")? ena0: + (sign_reg_b == "UNREGISTERED")? 1: + (sign_reg_b == "CLOCK1")? ena1: + (sign_reg_b == "CLOCK2")? ena2: + (sign_reg_b == "CLOCK3")? ena3:1; + + + + assign sign_pipe_a_wire_en = (sign_pipeline_reg_a == "CLOCK0")? ena0: + (sign_pipeline_reg_a == "UNREGISTERED")? 1: + (sign_pipeline_reg_a == "CLOCK1")? ena1: + (sign_pipeline_reg_a == "CLOCK2")? ena2: + (sign_pipeline_reg_a == "CLOCK3")? ena3:1; + + + assign sign_pipe_b_wire_en = (sign_pipeline_reg_b == "CLOCK0")? ena0: + (sign_pipeline_reg_b == "UNREGISTERED")? 1: + (sign_pipeline_reg_b == "CLOCK1")? ena1: + (sign_pipeline_reg_b == "CLOCK2")? ena2: + (sign_pipeline_reg_b == "CLOCK3")? ena3:1; + + + assign multiplier_wire_en = (multiplier_reg == "CLOCK0")? ena0: + (multiplier_reg == "UNREGISTERED")? 1: + (multiplier_reg == "CLOCK1")? ena1: + (multiplier_reg == "CLOCK2")? ena2: + (multiplier_reg == "CLOCK3")? ena3:1; + + assign output_wire_en = (output_reg == "CLOCK0")? ena0: + (output_reg == "UNREGISTERED")? 1: + (output_reg == "CLOCK1")? ena1: + (output_reg == "CLOCK2")? ena2: + (output_reg == "CLOCK3")? ena3:1; + + + assign mult_pipe_wire_en = (multiplier_reg == "UNREGISTERED")? ena0: + multiplier_wire_en; + + + assign mult_round_wire_en = (mult_round_reg == "CLOCK0")? ena0: + (mult_round_reg == "UNREGISTERED")? 1: + (mult_round_reg == "CLOCK1")? ena1: + (mult_round_reg == "CLOCK2")? ena2: + (mult_round_reg == "CLOCK3")? ena3:1; + + + assign mult_saturation_wire_en = (mult_saturation_reg == "CLOCK0")? ena0: + (mult_saturation_reg == "UNREGISTERED")? 1: + (mult_saturation_reg == "CLOCK1")? ena1: + (mult_saturation_reg == "CLOCK2")? ena2: + (mult_saturation_reg == "CLOCK3")? ena3:1; + + assign accum_round_wire_en = (accum_round_reg == "CLOCK0")? ena0: + (accum_round_reg == "UNREGISTERED")? 1: + (accum_round_reg == "CLOCK1")? ena1: + (accum_round_reg == "CLOCK2")? ena2: + (accum_round_reg == "CLOCK3")? ena3:1; + + assign accum_round_pipe_wire_en = (accum_round_pipeline_reg == "CLOCK0")? ena0: + (accum_round_pipeline_reg == "UNREGISTERED")? 1: + (accum_round_pipeline_reg == "CLOCK1")? ena1: + (accum_round_pipeline_reg == "CLOCK2")? ena2: + (accum_round_pipeline_reg == "CLOCK3")? ena3:1; + + assign accum_saturation_wire_en = (accum_saturation_reg == "CLOCK0")? ena0: + (accum_saturation_reg == "UNREGISTERED")? 1: + (accum_saturation_reg == "CLOCK1")? ena1: + (accum_saturation_reg == "CLOCK2")? ena2: + (accum_saturation_reg == "CLOCK3")? ena3:1; + + assign accum_saturation_pipe_wire_en = (accum_saturation_pipeline_reg == "CLOCK0")? ena0: + (accum_saturation_pipeline_reg == "UNREGISTERED")? 1: + (accum_saturation_pipeline_reg == "CLOCK1")? ena1: + (accum_saturation_pipeline_reg == "CLOCK2")? ena2: + (accum_saturation_pipeline_reg == "CLOCK3")? ena3:1; + + // --------------------------------------------------------- + // This block updates the internal clear signals accordingly + // every time the global clear signal changes state + // --------------------------------------------------------- + + assign input_a_wire_clr =(input_aclr_a == "ACLR3")? aclr3: + (input_aclr_a == "UNUSED")? 0: + (input_aclr_a == "ACLR0")? aclr0: + (input_aclr_a == "ACLR1")? aclr1: + (input_aclr_a == "ACLR2")? aclr2: 0; + + assign input_b_wire_clr = (input_aclr_b == "ACLR3")? aclr3: + (input_aclr_b == "UNUSED")? 0: + (input_aclr_b == "ACLR0")? aclr0: + (input_aclr_b == "ACLR1")? aclr1: + (input_aclr_b == "ACLR2")? aclr2: 0; + + + assign addsub_wire_clr =(addnsub_aclr == "ACLR3")? aclr3: + (addnsub_aclr == "UNUSED")? 0: + (addnsub_aclr == "ACLR0")? aclr0: + (addnsub_aclr == "ACLR1")? aclr1: + (addnsub_aclr == "ACLR2")? aclr2: 0; + + + assign addsub_pipe_wire_clr = (addnsub_pipeline_aclr == "ACLR3")? aclr3: + (addnsub_pipeline_aclr == "UNUSED")? 0: + (addnsub_pipeline_aclr == "ACLR0")? aclr0: + (addnsub_pipeline_aclr == "ACLR1")? aclr1: + (addnsub_pipeline_aclr == "ACLR2")? aclr2: 0; + + + assign zero_wire_clr = (accum_sload_aclr == "ACLR3")? aclr3: + (accum_sload_aclr == "UNUSED")? 0: + (accum_sload_aclr == "ACLR0")? aclr0: + (accum_sload_aclr == "ACLR1")? aclr1: + (accum_sload_aclr == "ACLR2")? aclr2: 0; + + assign accum_sload_upper_data_wire_clr = (accum_sload_upper_data_aclr == "ACLR3")? aclr3: + (accum_sload_upper_data_aclr == "UNUSED")? 0: + (accum_sload_upper_data_aclr == "ACLR0")? aclr0: + (accum_sload_upper_data_aclr == "ACLR1")? aclr1: + (accum_sload_upper_data_aclr == "ACLR2")? aclr2: 0; + + assign zero_pipe_wire_clr = (accum_sload_pipeline_aclr == "ACLR3")? aclr3: + (accum_sload_pipeline_aclr == "UNUSED")? 0: + (accum_sload_pipeline_aclr == "ACLR0")? aclr0: + (accum_sload_pipeline_aclr == "ACLR1")? aclr1: + (accum_sload_pipeline_aclr == "ACLR2")? aclr2: 0; + + assign accum_sload_upper_data_pipe_wire_clr = (accum_sload_upper_data_pipeline_aclr == "ACLR3")? aclr3: + (accum_sload_upper_data_pipeline_aclr == "UNUSED")? 0: + (accum_sload_upper_data_pipeline_aclr == "ACLR0")? aclr0: + (accum_sload_upper_data_pipeline_aclr == "ACLR1")? aclr1: + (accum_sload_upper_data_pipeline_aclr == "ACLR2")? aclr2: 0; + + assign sign_a_wire_clr =(sign_aclr_a == "ACLR3")? aclr3: + (sign_aclr_a == "UNUSED")? 0: + (sign_aclr_a == "ACLR0")? aclr0: + (sign_aclr_a == "ACLR1")? aclr1: + (sign_aclr_a == "ACLR2")? aclr2: 0; + + + assign sign_b_wire_clr = (sign_aclr_b == "ACLR3")? aclr3: + (sign_aclr_b == "UNUSED")? 0: + (sign_aclr_b == "ACLR0")? aclr0: + (sign_aclr_b == "ACLR1")? aclr1: + (sign_aclr_b == "ACLR2")? aclr2: 0; + + + + + assign sign_pipe_a_wire_clr = (sign_pipeline_aclr_a == "ACLR3")? aclr3: + (sign_pipeline_aclr_a == "UNUSED")? 0: + (sign_pipeline_aclr_a == "ACLR0")? aclr0: + (sign_pipeline_aclr_a == "ACLR1")? aclr1: + (sign_pipeline_aclr_a == "ACLR2")? aclr2: 0; + + + assign sign_pipe_b_wire_clr = (sign_pipeline_aclr_b == "ACLR3")? aclr3: + (sign_pipeline_aclr_b == "UNUSED")? 0: + (sign_pipeline_aclr_b == "ACLR0")? aclr0: + (sign_pipeline_aclr_b == "ACLR1")? aclr1: + (sign_pipeline_aclr_b == "ACLR2")? aclr2: 0; + + + assign multiplier_wire_clr = (multiplier_aclr == "ACLR3")? aclr3: + (multiplier_aclr == "UNUSED")? 0: + (multiplier_aclr == "ACLR0")? aclr0: + (multiplier_aclr == "ACLR1")? aclr1: + (multiplier_aclr == "ACLR2")? aclr2: 0; + + assign output_wire_clr =(output_aclr == "ACLR3")? aclr3: + (output_aclr == "UNUSED")? 0: + (output_aclr == "ACLR0")? aclr0: + (output_aclr == "ACLR1")? aclr1: + (output_aclr == "ACLR2")? aclr2: 0; + + + assign mult_pipe_wire_clr = (multiplier_reg == "UNREGISTERED")? aclr0: + multiplier_wire_clr; + + assign mult_round_wire_clr = (mult_round_aclr == "ACLR3")? aclr3: + (mult_round_aclr == "UNUSED")? 0: + (mult_round_aclr == "ACLR0")? aclr0: + (mult_round_aclr == "ACLR1")? aclr1: + (mult_round_aclr == "ACLR2")? aclr2: 0; + + assign mult_saturation_wire_clr = (mult_saturation_aclr == "ACLR3")? aclr3: + (mult_saturation_aclr == "UNUSED")? 0: + (mult_saturation_aclr == "ACLR0")? aclr0: + (mult_saturation_aclr == "ACLR1")? aclr1: + (mult_saturation_aclr == "ACLR2")? aclr2: 0; + + assign accum_round_wire_clr = (accum_round_aclr == "ACLR3")? aclr3: + (accum_round_aclr == "UNUSED")? 0: + (accum_round_aclr == "ACLR0")? aclr0: + (accum_round_aclr == "ACLR1")? aclr1: + (accum_round_aclr == "ACLR2")? aclr2: 0; + + assign accum_round_pipe_wire_clr = (accum_round_pipeline_aclr == "ACLR3")? aclr3: + (accum_round_pipeline_aclr == "UNUSED")? 0: + (accum_round_pipeline_aclr == "ACLR0")? aclr0: + (accum_round_pipeline_aclr == "ACLR1")? aclr1: + (accum_round_pipeline_aclr == "ACLR2")? aclr2: 0; + + assign accum_saturation_wire_clr = (accum_saturation_aclr == "ACLR3")? aclr3: + (accum_saturation_aclr == "UNUSED")? 0: + (accum_saturation_aclr == "ACLR0")? aclr0: + (accum_saturation_aclr == "ACLR1")? aclr1: + (accum_saturation_aclr == "ACLR2")? aclr2: 0; + + assign accum_saturation_pipe_wire_clr = (accum_saturation_pipeline_aclr == "ACLR3")? aclr3: + (accum_saturation_pipeline_aclr == "UNUSED")? 0: + (accum_saturation_pipeline_aclr == "ACLR0")? aclr0: + (accum_saturation_pipeline_aclr == "ACLR1")? aclr1: + (accum_saturation_pipeline_aclr == "ACLR2")? aclr2: 0; + + // ------------------------------------------------------------------------ + // This block contains 1 register and 1 combinatorial block (to set mult_a) + // Signal Registered : dataa + // + // Register is controlled by posedge input_wire_a_clk + // Register has an asynchronous clear signal, input_reg_a_wire_clr + // NOTE : The combinatorial block will be executed if + // input_reg_a is unregistered and dataa changes value + // ------------------------------------------------------------------------ + assign mult_a_wire = (input_reg_a == "UNREGISTERED")? mult_a_tmp : mult_a_reg; + + assign mult_a_tmp = (int_width_a == width_a) ? ((input_source_a == "DATAA")? dataa : + (input_source_a == "SCANA")? scanina : + (sourcea == 1)? scanina : dataa) + : ((input_source_a == "DATAA")? {dataa, {(diff_width_a){1'b0}}} : + (input_source_a == "SCANA")? {scanina, {(diff_width_a){1'b0}}} : + (sourcea == 1)? {scanina, {(diff_width_a){1'b0}}} : {dataa, {(diff_width_a){1'b0}}}); + + always @(posedge input_a_wire_clk or posedge input_a_wire_clr) + begin + if (input_a_wire_clr == 1) + mult_a_reg <= 0; + else if ((input_a_wire_clk == 1) && (input_a_wire_en == 1)) + begin + if (input_source_a == "DATAA") + mult_a_reg <= (int_width_a == width_a) ? dataa : {dataa, {(diff_width_a){1'b0}}}; + else if (input_source_a == "SCANA") + mult_a_reg <= (int_width_a == width_a) ? scanina : {scanina,{(diff_width_a){1'b0}}}; + else if (input_source_a == "VARIABLE") + begin + if (sourcea == 1) + mult_a_reg <= (int_width_a == width_a) ? scanina : {scanina, {(diff_width_a){1'b0}}}; + else + mult_a_reg <= (int_width_a == width_a) ? dataa : {dataa, {(diff_width_a){1'b0}}}; + end + end + end + + + // ------------------------------------------------------------------------ + // This block contains 1 register and 1 combinatorial block (to set mult_b) + // Signal Registered : datab + // + // Register is controlled by posedge input_wire_b_clk + // Register has an asynchronous clear signal, input_reg_b_wire_clr + // NOTE : The combinatorial block will be executed if + // input_reg_b is unregistered and datab changes value + // ------------------------------------------------------------------------ + assign mult_b_wire = (input_reg_b == "UNREGISTERED")? mult_b_tmp : mult_b_reg; + assign mult_b_tmp = (int_width_b == width_b) ? ((input_source_b == "DATAB")? datab : + (input_source_b == "SCANB")? scaninb : + (sourceb == 1)? scaninb : datab) + : ((input_source_b == "DATAB")? {datab, {(diff_width_b){1'b0}}} : + (input_source_b == "SCANB")? {scaninb, {(diff_width_b){1'b0}}} : + (sourceb == 1)? {scaninb, {(diff_width_b){1'b0}}} : {datab, {(diff_width_b){1'b0}}}); + + always @(posedge input_b_wire_clk or posedge input_b_wire_clr ) + begin + if (input_b_wire_clr == 1) + mult_b_reg <= 0; + else if ((input_b_wire_clk == 1) && (input_b_wire_en == 1)) + begin + if (input_source_b == "DATAB") + mult_b_reg <= (int_width_b == width_b) ? datab : {datab, {(diff_width_b){1'b0}}}; + else if (input_source_b == "SCANB") + mult_b_reg <= (int_width_b == width_b) ? scaninb : {scaninb, {(diff_width_b){1'b0}}}; + else if (input_source_b == "VARIABLE") + begin + if (sourceb == 1) + mult_b_reg <= (int_width_b == width_b) ? scaninb : {scaninb, {(diff_width_b){1'b0}}}; + else + mult_b_reg <= (int_width_b == width_b) ? datab : {datab, {(diff_width_b){1'b0}}}; + end + end + end + + + // ----------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set addnsub_reg) + // Signal Registered : addnsub + // + // Register is controlled by posedge addsub_wire_clk + // Register has an asynchronous clear signal, addsub_wire_clr + // NOTE : The combinatorial block will be executed if + // addnsub_reg is unregistered and addnsub changes value + // ----------------------------------------------------------------------------- + assign addsub_wire = ((addnsub_reg == "UNREGISTERED") )? addnsub : addsub_reg; + + always @(posedge addsub_wire_clk or posedge addsub_wire_clr) + begin + if (addsub_wire_clr == 1) + addsub_reg <= 0; + else if ((addsub_wire_clk == 1) && (addsub_wire_en == 1)) + addsub_reg <= addnsub; + end + + + // ----------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set addsub_pipe) + // Signal Registered : addsub_latent + // + // Register is controlled by posedge addsub_pipe_wire_clk + // Register has an asynchronous clear signal, addsub_pipe_wire_clr + // NOTE : The combinatorial block will be executed if + // addsub_pipeline_reg is unregistered and addsub_latent changes value + // ----------------------------------------------------------------------------- + assign addsub_pipe_wire = (addnsub_pipeline_reg == "UNREGISTERED")?addsub_latent : addsub_pipe_reg; + + always @(posedge addsub_pipe_wire_clk or posedge addsub_pipe_wire_clr ) + begin + if (addsub_pipe_wire_clr == 1) + addsub_pipe_reg <= 0; + else if ((addsub_pipe_wire_clk == 1) && (addsub_pipe_wire_en == 1)) + addsub_pipe_reg <= addsub_latent; + + end + + + // ------------------------------------------------------------------------------ + // This block contains 1 register and 1 combinatorial block (to set zero_acc_reg) + // Signal Registered : accum_sload + // + // Register is controlled by posedge zero_wire_clk + // Register has an asynchronous clear signal, zero_wire_clr + // NOTE : The combinatorial block will be executed if + // accum_sload_reg is unregistered and accum_sload changes value + // ------------------------------------------------------------------------------ + assign zero_acc_wire = (accum_sload_reg == "UNREGISTERED")?accum_sload : zero_acc_reg; + + always @(posedge zero_wire_clk or posedge zero_wire_clr) + begin + if (zero_wire_clr == 1) + begin + zero_acc_reg <= 0; + end + else if ((zero_wire_clk == 1) && (zero_wire_en == 1)) + begin + zero_acc_reg <= accum_sload; + end + end + + assign sload_upper_data_wire = (accum_sload_upper_data_reg == "UNREGISTERED")? accum_sload_upper_data_int : sload_upper_data_reg; + + + always @(posedge accum_sload_upper_data_wire_clk or posedge accum_sload_upper_data_wire_clr) + begin + if (accum_sload_upper_data_wire_clr == 1) + begin + sload_upper_data_reg <= 0; + end + else if ((accum_sload_upper_data_wire_clk == 1) && (accum_sload_upper_data_wire_en == 1)) + begin + sload_upper_data_reg <= accum_sload_upper_data_int; + end + end + + // -------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set zero_acc_pipe) + // Signal Registered : zeroacc_latent + // + // Register is controlled by posedge zero_pipe_wire_clk + // Register has an asynchronous clear signal, zero_pipe_wire_clr + // NOTE : The combinatorial block will be executed if + // accum_sload_pipeline_reg is unregistered and zeroacc_latent changes value + // -------------------------------------------------------------------------------- + assign zero_acc_pipe_wire = (accum_sload_pipeline_reg == "UNREGISTERED")?zeroacc_latent : zero_acc_pipe_reg; + + always @(posedge zero_pipe_wire_clk or posedge zero_pipe_wire_clr) + begin + if (zero_pipe_wire_clr == 1) + begin + zero_acc_pipe_reg <= 0; + end + else if ((zero_pipe_wire_clk == 1) && (zero_pipe_wire_en == 1)) + begin + zero_acc_pipe_reg <= zeroacc_latent; + end + + end + + + always @(posedge accum_sload_upper_data_pipe_wire_clk or posedge accum_sload_upper_data_pipe_wire_clr) + begin + if (accum_sload_upper_data_pipe_wire_clr == 1) + begin + sload_upper_data_pipe_reg <= 0; + end + else if ((accum_sload_upper_data_pipe_wire_clk == 1) && (accum_sload_upper_data_pipe_wire_en == 1)) + begin + sload_upper_data_pipe_reg <= sload_upper_data_latent; + end + + end + + always @(sload_upper_data_latent or sload_upper_data_pipe_reg or sign_a_int or sign_b_int ) + begin + if (accum_sload_upper_data_pipeline_reg == "UNREGISTERED") + begin + if(int_width_result > width_result) + begin + + if(sign_a_int | sign_b_int) + begin + sload_upper_data_pipe_wire[int_width_result - 1 : 0] = {int_width_result{sload_upper_data_latent[width_upper_data-1]}}; + end + else + begin + sload_upper_data_pipe_wire[int_width_result - 1 : 0] = {int_width_result{1'b0}}; + end + + if(width_result > width_upper_data) + begin + for(i4 = 0; i4 < width_result - width_upper_data + int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : width_result - width_upper_data + int_extra_width] = sload_upper_data_latent; + end + else if(width_result == width_upper_data) + begin + for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + sload_upper_data_pipe_wire[width_result - 1 + int_extra_width: 0 + int_extra_width] = sload_upper_data_latent; + end + else + begin + for(i4 = int_extra_width; i4 < sload_for_limit; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = sload_upper_data_latent[i4]; + end + for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + end + end + else + begin + if(width_result > width_upper_data) + begin + for(i4 = 0; i4 < width_result - width_upper_data + int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : width_result - width_upper_data + int_extra_width] = sload_upper_data_latent; + end + else if(width_result == width_upper_data) + begin + for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : 0 + int_extra_width] = sload_upper_data_latent; + end + else + begin + for(i4 = int_extra_width; i4 < sload_for_limit; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = sload_upper_data_latent[i4]; + end + for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + end + end + end + else + begin + if(int_width_result > width_result) + begin + + if(sign_a_int | sign_b_int) + begin + sload_upper_data_pipe_wire[int_width_result - 1 : 0] = {int_width_result{sload_upper_data_pipe_reg[width_upper_data-1]}}; + end + else + begin + sload_upper_data_pipe_wire[int_width_result - 1 : 0] = {int_width_result{1'b0}}; + end + + if(width_result > width_upper_data) + begin + for(i4 = 0; i4 < width_result - width_upper_data + int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : width_result - width_upper_data + int_extra_width] = sload_upper_data_pipe_reg; + end + else if(width_result == width_upper_data) + begin + for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + sload_upper_data_pipe_wire[width_result - 1 + int_extra_width: 0 + int_extra_width] = sload_upper_data_pipe_reg; + end + else + begin + for(i4 = int_extra_width; i4 < sload_for_limit; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = sload_upper_data_pipe_reg[i4]; + end + for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + end + end + else + begin + if(width_result > width_upper_data) + begin + for(i4 = 0; i4 < width_result - width_upper_data + int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : width_result - width_upper_data + int_extra_width] = sload_upper_data_pipe_reg; + end + else if(width_result == width_upper_data) + begin + for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : 0 + int_extra_width] = sload_upper_data_pipe_reg; + end + else + begin + for(i4 = int_extra_width; i4 < sload_for_limit; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = sload_upper_data_pipe_reg[i4]; + end + for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1) + begin + sload_upper_data_pipe_wire[i4] = 1'b0; + end + end + end + end + end + + // ---------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set sign_a_reg) + // Signal Registered : signa + // + // Register is controlled by posedge sign_a_wire_clk + // Register has an asynchronous clear signal, sign_a_wire_clr + // NOTE : The combinatorial block will be executed if + // sign_reg_a is unregistered and signa changes value + // ---------------------------------------------------------------------------- + assign sign_a_wire = (sign_reg_a == "UNREGISTERED")? signa : sign_a_reg; + + always @(posedge sign_a_wire_clk or posedge sign_a_wire_clr) + begin + if (sign_a_wire_clr == 1) + sign_a_reg <= 0; + else if ((sign_a_wire_clk == 1) && (sign_a_wire_en == 1)) + sign_a_reg <= signa; + end + + + // ----------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set sign_a_pipe) + // Signal Registered : signa_latent + // + // Register is controlled by posedge sign_pipe_a_wire_clk + // Register has an asynchronous clear signal, sign_pipe_a_wire_clr + // NOTE : The combinatorial block will be executed if + // sign_pipeline_reg_a is unregistered and signa_latent changes value + // ----------------------------------------------------------------------------- + assign sign_a_pipe_wire = (sign_pipeline_reg_a == "UNREGISTERED")? signa_latent : sign_a_pipe_reg; + + always @(posedge sign_pipe_a_wire_clk or posedge sign_pipe_a_wire_clr) + begin + if (sign_pipe_a_wire_clr == 1) + sign_a_pipe_reg <= 0; + else if ((sign_pipe_a_wire_clk == 1) && (sign_pipe_a_wire_en == 1)) + sign_a_pipe_reg <= signa_latent; + end + + + // ---------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set sign_b_reg) + // Signal Registered : signb + // + // Register is controlled by posedge sign_b_wire_clk + // Register has an asynchronous clear signal, sign_b_wire_clr + // NOTE : The combinatorial block will be executed if + // sign_reg_b is unregistered and signb changes value + // ---------------------------------------------------------------------------- + assign sign_b_wire = (sign_reg_b == "UNREGISTERED") ? signb : sign_b_reg; + + always @(posedge sign_b_wire_clk or posedge sign_b_wire_clr) + begin + if (sign_b_wire_clr == 1) + sign_b_reg <= 0; + else if ((sign_b_wire_clk == 1) && (sign_b_wire_en == 1)) + sign_b_reg <= signb; + end + + + // ----------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set sign_b_pipe) + // Signal Registered : signb_latent + // + // Register is controlled by posedge sign_pipe_b_wire_clk + // Register has an asynchronous clear signal, sign_pipe_b_wire_clr + // NOTE : The combinatorial block will be executed if + // sign_pipeline_reg_b is unregistered and signb_latent changes value + // ----------------------------------------------------------------------------- + assign sign_b_pipe_wire = (sign_pipeline_reg_b == "UNREGISTERED" )? signb_latent : sign_b_pipe_reg; + + always @(posedge sign_pipe_b_wire_clk or posedge sign_pipe_b_wire_clr ) + begin + if (sign_pipe_b_wire_clr == 1) + sign_b_pipe_reg <= 0; + else if ((sign_pipe_b_wire_clk == 1) && (sign_pipe_b_wire_en == 1)) + sign_b_pipe_reg <= signb_latent; + + end + + // ---------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult_round) + // Signal Registered : mult_round + // + // Register is controlled by posedge mult_round_wire_clk + // Register has an asynchronous clear signal, mult_round_wire_clr + // NOTE : The combinatorial block will be executed if + // mult_round_reg is unregistered and mult_round changes value + // ---------------------------------------------------------------------------- + + assign mult_round_int = (mult_round_reg == "UNREGISTERED")? mult_round : mult_round_tmp; + + always @(posedge mult_round_wire_clk or posedge mult_round_wire_clr) + begin + if (mult_round_wire_clr == 1) + mult_round_tmp <= 0; + else if ((mult_round_wire_clk == 1) && (mult_round_wire_en == 1)) + mult_round_tmp <= mult_round; + end + + // ---------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult_saturation) + // Signal Registered : mult_saturation + // + // Register is controlled by posedge mult_saturation_wire_clk + // Register has an asynchronous clear signal, mult_saturation_wire_clr + // NOTE : The combinatorial block will be executed if + // mult_saturation_reg is unregistered and mult_saturation changes value + // ---------------------------------------------------------------------------- + + assign mult_saturation_int = (mult_saturation_reg == "UNREGISTERED")? mult_saturation : mult_saturation_tmp; + + always @(posedge mult_saturation_wire_clk or posedge mult_saturation_wire_clr) + begin + if (mult_saturation_wire_clr == 1) + mult_saturation_tmp <= 0; + else if ((mult_saturation_wire_clk == 1) && (mult_saturation_wire_en == 1)) + mult_saturation_tmp <= mult_saturation; + end + + // ---------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set accum_round) + // Signal Registered : accum_round + // + // Register is controlled by posedge accum_round_wire_clk + // Register has an asynchronous clear signal, accum_round_wire_clr + // NOTE : The combinatorial block will be executed if + // accum_round_reg is unregistered and accum_round changes value + // ---------------------------------------------------------------------------- + + assign accum_round_tmp1_wire = (accum_round_reg == "UNREGISTERED")? accum_round : accum_round_tmp1; + + always @(posedge accum_round_wire_clk or posedge accum_round_wire_clr) + begin + if (accum_round_wire_clr == 1) + accum_round_tmp1 <= 0; + else if ((accum_round_wire_clk == 1) && (accum_round_wire_en == 1)) + accum_round_tmp1 <= accum_round; + end + + // ---------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set accum_round_tmp1) + // Signal Registered : accum_round_tmp1 + // + // Register is controlled by posedge accum_round_pipe_wire_clk + // Register has an asynchronous clear signal, accum_round_pipe_wire_clr + // NOTE : The combinatorial block will be executed if + // accum_round_pipeline_reg is unregistered and accum_round_tmp1_wire changes value + // ---------------------------------------------------------------------------- + + assign accum_round_int = (accum_round_pipeline_reg == "UNREGISTERED")? accum_round_tmp1_wire : accum_round_tmp2; + + always @(posedge accum_round_pipe_wire_clk or posedge accum_round_pipe_wire_clr) + begin + if (accum_round_pipe_wire_clr == 1) + accum_round_tmp2 <= 0; + else if ((accum_round_pipe_wire_clk == 1) && (accum_round_pipe_wire_en == 1)) + accum_round_tmp2 <= accum_round_tmp1_wire; + end + + + // ---------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set accum_saturation) + // Signal Registered : accum_saturation + // + // Register is controlled by posedge accum_saturation_wire_clk + // Register has an asynchronous clear signal, accum_saturation_wire_clr + // NOTE : The combinatorial block will be executed if + // accum_saturation_reg is unregistered and accum_saturation changes value + // ---------------------------------------------------------------------------- + + assign accum_saturation_tmp1_wire = (accum_saturation_reg == "UNREGISTERED")? accum_saturation : accum_saturation_tmp1; + + always @(posedge accum_saturation_wire_clk or posedge accum_saturation_wire_clr) + begin + if (accum_saturation_wire_clr == 1) + accum_saturation_tmp1 <= 0; + else if ((accum_saturation_wire_clk == 1) && (accum_saturation_wire_en == 1)) + accum_saturation_tmp1 <= accum_saturation; + end + + // ---------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set accum_saturation_tmp1) + // Signal Registered : accum_saturation_tmp1 + // + // Register is controlled by posedge accum_saturation_pipe_wire_clk + // Register has an asynchronous clear signal, accum_saturation_pipe_wire_clr + // NOTE : The combinatorial block will be executed if + // accum_saturation_pipeline_reg is unregistered and accum_saturation_tmp1_wire changes value + // ---------------------------------------------------------------------------- + + assign accum_saturation_int = (accum_saturation_pipeline_reg == "UNREGISTERED")? accum_saturation_tmp1_wire : accum_saturation_tmp2; + + always @(posedge accum_saturation_pipe_wire_clk or posedge accum_saturation_pipe_wire_clr) + begin + if (accum_saturation_pipe_wire_clr == 1) + accum_saturation_tmp2 <= 0; + else if ((accum_saturation_pipe_wire_clk == 1) && (accum_saturation_pipe_wire_en == 1)) + accum_saturation_tmp2 <= accum_saturation_tmp1_wire; + end + + + // ------------------------------------------------------------------------------------------------------ + // This block checks if the two numbers to be multiplied (mult_a/mult_b) is to be interpreted + // as a negative number or not. If so, then two's complement is performed. + // The numbers are then multipled + // The sign of the result (positive or negative) is determined based on the sign of the two input numbers + // ------------------------------------------------------------------------------------------------------ + + always @(mult_a_wire or mult_b_wire or sign_a_reg_int or sign_b_reg_int or temp_mult_zero) + begin + neg_a = mult_a_wire [int_width_a-1] & (sign_a_reg_int); + neg_b = mult_b_wire [int_width_b-1] & (sign_b_reg_int); + + mult_a_int = (neg_a == 1) ? ~mult_a_wire + 1 : mult_a_wire; + mult_b_int = (neg_b == 1) ? ~mult_b_wire + 1 : mult_b_wire; + + temp_mult_1 = mult_a_int * mult_b_int; + temp_mult_signed = sign_a_reg_int | sign_b_reg_int; + temp_mult = (neg_a ^ neg_b) ? (temp_mult_zero - temp_mult_1) : temp_mult_1; + + end + + always @(temp_mult or mult_saturation_int or mult_round_int) + begin + + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 1) + begin + // StratixII rounding support + + // This is based on both input is in Q1.15 format + + if ((multiplier_rounding == "YES") || + ((multiplier_rounding == "VARIABLE") && (mult_round_int == 1))) + begin + mult_round_out = temp_mult + ( 1 << (bits_to_round)); + + end + else + begin + mult_round_out = temp_mult; + end + + // StratixII saturation support + + if ((multiplier_saturation == "YES") || + (( multiplier_saturation == "VARIABLE") && (mult_saturation_int == 1))) + begin + mult_saturate_overflow = (mult_round_out[int_width_a + int_width_b - 1] == 0 && mult_round_out[int_width_a + int_width_b - 2] == 1); + if (mult_saturate_overflow == 0) + begin + mult_saturate_out = mult_round_out; + end + else + begin + for (i = (int_width_a + int_width_b - 1); i >= (int_width_a + int_width_b - 2); i = i - 1) + begin + mult_saturate_out[i] = mult_round_out[int_width_a + int_width_b - 1]; + end + + for (i = (int_width_a + int_width_b - 3); i >= 0; i = i - 1) + begin + mult_saturate_out[i] = ~mult_round_out[int_width_a + int_width_b - 1]; + end + + for (i= sat_for_ini; i >=0; i = i - 1) + begin + mult_saturate_out[i] = 1'b0; + end + + end + end + else + begin + mult_saturate_out = mult_round_out; + mult_saturate_overflow = 0; + end + + if ((multiplier_rounding == "YES") || + ((multiplier_rounding == "VARIABLE") && (mult_round_int == 1))) + begin + mult_result = mult_saturate_out; + + for (i = mult_round_for_ini; i >= 0; i = i - 1) + begin + mult_result[i] = 1'b0; + end + end + else + begin + mult_result = mult_saturate_out; + end + end + + mult_final_out = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) ? + temp_mult : mult_result; + + end + + + // --------------------------------------------------------------------------------------- + // This block contains 2 register (to set mult_res and mult_signed) + // Signals Registered : mult_out_latent, mult_signed_latent + // + // Both the registers are controlled by the same clock signal, posedge multiplier_wire_clk + // Both registers share the same clock enable signal multipler_wire_en + // Both registers have the same asynchronous signal, posedge multiplier_wire_clr + // --------------------------------------------------------------------------------------- + assign mult_is_saturated_wire = (multiplier_reg == "UNREGISTERED")? mult_is_saturated_latent : mult_is_saturated_reg; + + always @(posedge multiplier_wire_clk or posedge multiplier_wire_clr) + begin + if (multiplier_wire_clr == 1) + begin + mult_res <=0; + mult_signed <=0; + mult_is_saturated_reg <=0; + end + else if ((multiplier_wire_clk == 1) && (multiplier_wire_en == 1)) + begin + mult_res <= mult_out_latent; + mult_signed <= mult_signed_latent; + mult_is_saturated_reg <= mult_is_saturated_latent; + end + end + + + // -------------------------------------------------------------------- + // This block contains 1 register (to set mult_full) + // Signal Registered : mult_pipe + // + // Register is controlled by posedge mult_pipe_wire_clk + // Register also has an asynchronous clear signal posedge mult_pipe_wire_clr + // -------------------------------------------------------------------- + always @(posedge mult_pipe_wire_clk or posedge mult_pipe_wire_clr ) + begin + if (mult_pipe_wire_clr ==1) + begin + // clear the pipeline + for (i2=0; i2<=extra_multiplier_latency; i2=i2+1) + begin + mult_pipe [i2] = 0; + end + mult_full = 0; + end + else if ((mult_pipe_wire_clk == 1) && (mult_pipe_wire_en == 1)) + begin + mult_pipe [head_mult] = {addsub_wire, zero_acc_wire, sign_a_wire, sign_b_wire, temp_mult_signed, mult_final_out, sload_upper_data_wire, mult_saturate_overflow}; + head_mult = (head_mult +1) % (extra_multiplier_latency); + mult_full = mult_pipe[head_mult]; + end + end + + + // ------------------------------------------------------------- + // This is the main process block that performs the accumulation + // ------------------------------------------------------------- + always @(posedge output_wire_clk or posedge output_wire_clr) + begin + if (output_wire_clr == 1) + begin + temp_sum = 0; + accum_result = 0; + + result_int = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) ? + temp_sum[int_width_result -1 : 0] : accum_result; + + overflow_int = 0; + accum_saturate_overflow = 0; + mult_is_saturated_int = 0; + for (i3=0; i3<=extra_accumulator_latency; i3=i3+1) + begin + result_pipe [i3] = 0; + accum_saturate_pipe[i3] = 0; + mult_is_saturated_pipe[i3] = 0; + end + + flag = ~flag; + + end + else if (output_wire_clk ==1) + begin + + if (output_wire_en ==1) + begin + if (extra_accumulator_latency == 0) + begin + mult_is_saturated_int = mult_is_saturated_wire; + end + + if (multiplier_reg == "UNREGISTERED") + begin + mult_res_out = {{int_width_result - int_width_a - int_width_b {(sign_a_int | sign_b_int) & mult_out_latent [int_width_a+int_width_b -1]}}, mult_out_latent}; + mult_signed_out = (sign_a_int | sign_b_int); + end + else + begin + mult_res_out = {{int_width_result - int_width_a - int_width_b {(sign_a_int | sign_b_int) & mult_res [int_width_a+int_width_b -1]}}, mult_res}; + mult_signed_out = (sign_a_int | sign_b_int); + end + + if (addsub_int) + begin + //add + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0 && + dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) + begin + temp_sum = ( (zero_acc_int==0) ? result_int : 0) + mult_res_out; + end + else + begin + temp_sum = ( (zero_acc_int==0) ? result_int : sload_upper_data_pipe_wire) + mult_res_out; + end + + cout_int = temp_sum [int_width_result]; + end + else + begin + //subtract + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0 && + dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) + begin + temp_sum = ( (zero_acc_int==0) ? result_int : 0) - (mult_res_out); + cout_int = (( (zero_acc_int==0) ? result_int : 0) >= mult_res_out) ? 1 : 0; + end + else + begin + temp_sum = ( (zero_acc_int==0) ? result_int : sload_upper_data_pipe_wire) - mult_res_out; + cout_int = (( (zero_acc_int==0) ? result_int : sload_upper_data_pipe_wire) >= mult_res_out) ? 1 : 0; + end + end + + //compute overflow + if ((mult_signed_out==1) && (mult_res_out != 0)) + begin + if (zero_acc_int == 0) + begin + overflow_tmp_int = (mult_res_out [int_width_a+int_width_b -1] ~^ result_int [int_width_result-1]) ^ (~addsub_int); + overflow_int = overflow_tmp_int & (result_int [int_width_result -1] ^ temp_sum[int_width_result -1]); + end + else + begin + overflow_tmp_int = (mult_res_out [int_width_a+int_width_b -1] ~^ sload_upper_data_pipe_wire [int_width_result-1]) ^ (~addsub_int); + overflow_int = overflow_tmp_int & (sload_upper_data_pipe_wire [int_width_result -1] ^ temp_sum[int_width_result -1]); + end + end + else + begin + overflow_int = (addsub_int ==1)? cout_int : ~cout_int; + end + + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 1) + begin + // StratixII rounding support + + // This is based on both input is in Q1.15 format + + if ((accumulator_rounding == "YES") || + ((accumulator_rounding == "VARIABLE") && (accum_round_int == 1))) + begin + accum_round_out = temp_sum[int_width_result -1 : 0] + ( 1 << (bits_to_round)); + end + else + begin + accum_round_out = temp_sum[int_width_result - 1 : 0]; + end + + // StratixII saturation support + + if ((accumulator_saturation == "YES") || + ((accumulator_saturation == "VARIABLE") && (accum_saturation_int == 1))) + begin + accum_result_sign_bits = accum_round_out[int_width_result-1 : int_width_a + int_width_b - 2]; + + if ( (((&accum_result_sign_bits) | (|accum_result_sign_bits) | (^accum_result_sign_bits)) == 0) || + (((&accum_result_sign_bits) & (|accum_result_sign_bits) & !(^accum_result_sign_bits)) == 1)) + begin + accum_saturate_overflow = 1'b0; + end + else + begin + accum_saturate_overflow = 1'b1; + end + + if (accum_saturate_overflow == 0) + begin + accum_saturate_out = accum_round_out; + end + else + begin + + for (i = (int_width_result - 1); i >= (int_width_a + int_width_b - 2); i = i - 1) + begin + accum_saturate_out[i] = accum_round_out[int_width_result-1]; + end + + + for (i = (int_width_a + int_width_b - 3); i >= accum_sat_for_limit; i = i - 1) + begin + accum_saturate_out[i] = ~accum_round_out[int_width_result -1]; + end + + for (i = sat_for_ini; i >= 0; i = i - 1) + begin + accum_saturate_out[i] = 1'b0; + end + + end + end + else + begin + accum_saturate_out = accum_round_out; + accum_saturate_overflow = 0; + end + + if ((accumulator_rounding == "YES") || + ((accumulator_rounding == "VARIABLE") && (accum_round_int == 1))) + begin + accum_result = accum_saturate_out; + + for (i = bits_to_round; i >= 0; i = i - 1) + begin + accum_result[i] = 1'b0; + end + end + else + begin + accum_result = accum_saturate_out; + end + end + + result_int = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) ? + temp_sum[int_width_result -1 : 0] : accum_result; + + flag = ~flag; + end + + end + end + + always @ (posedge flag or negedge flag) + begin + if (extra_accumulator_latency == 0) + begin + result = result_int[width_result - 1 + int_extra_width : int_extra_width]; + overflow = overflow_int; + accum_is_saturated_latent = accum_saturate_overflow; + end + else + begin + result_pipe [head_result] = {overflow_int, result_int[width_result - 1 + int_extra_width : int_extra_width]}; + //mult_is_saturated_pipe[head_result] = mult_is_saturated_wire; + accum_saturate_pipe[head_result] = accum_saturate_overflow; + head_result = (head_result +1) % (extra_accumulator_latency + 1); + result_full = result_pipe[head_result]; + result = result_full [width_result-1:0]; + overflow = result_full [width_result]; + mult_is_saturated_int = mult_is_saturated_wire; + accum_is_saturated_latent = accum_saturate_pipe[head_result]; + end + + end + +endmodule // end of ALTMULT_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. +// +//-------------------------------------------------------------------------- +`timescale 1 ps / 1 ps + +module altmult_add ( dataa, + datab, + scanina, + scaninb, + sourcea, + sourceb, + clock3, + clock2, + clock1, + clock0, + aclr3, + aclr2, + aclr1, + aclr0, + ena3, + ena2, + ena1, + ena0, + signa, + signb, + addnsub1, + addnsub3, + result, + scanouta, + scanoutb, + mult01_round, + mult23_round, + mult01_saturation, + mult23_saturation, + addnsub1_round, + addnsub3_round, + mult0_is_saturated, + mult1_is_saturated, + mult2_is_saturated, + mult3_is_saturated); + + // --------------------- + // PARAMETER DECLARATION + // --------------------- + + parameter width_a = 1; + parameter width_b = 1; + parameter width_result = 3; + parameter number_of_multipliers = 1; + parameter lpm_type = "altmult_add"; + parameter lpm_hint = "UNUSED"; + + // A inputs + + parameter multiplier1_direction = "UNUSED"; + parameter multiplier3_direction = "UNUSED"; + + parameter input_register_a0 = "CLOCK0"; + parameter input_aclr_a0 = "ACLR3"; + parameter input_source_a0 = "DATAA"; + + parameter input_register_a1 = "CLOCK0"; + parameter input_aclr_a1 = "ACLR3"; + parameter input_source_a1 = "DATAA"; + + parameter input_register_a2 = "CLOCK0"; + parameter input_aclr_a2 = "ACLR3"; + parameter input_source_a2 = "DATAA"; + + parameter input_register_a3 = "CLOCK0"; + parameter input_aclr_a3 = "ACLR3"; + parameter input_source_a3 = "DATAA"; + + parameter port_signa = "PORT_CONNECTIVITY"; + parameter representation_a = "UNUSED"; + parameter signed_register_a = "CLOCK0"; + parameter signed_aclr_a = "ACLR3"; + parameter signed_pipeline_register_a = "CLOCK0"; + parameter signed_pipeline_aclr_a = "ACLR3"; + + // B inputs + + parameter input_register_b0 = "CLOCK0"; + parameter input_aclr_b0 = "ACLR3"; + parameter input_source_b0 = "DATAB"; + + parameter input_register_b1 = "CLOCK0"; + parameter input_aclr_b1 = "ACLR3"; + parameter input_source_b1 = "DATAB"; + + parameter input_register_b2 = "CLOCK0"; + parameter input_aclr_b2 = "ACLR3"; + parameter input_source_b2 = "DATAB"; + + parameter input_register_b3 = "CLOCK0"; + parameter input_aclr_b3 = "ACLR3"; + parameter input_source_b3 = "DATAB"; + + parameter port_signb = "PORT_CONNECTIVITY"; + parameter representation_b = "UNUSED"; + parameter signed_register_b = "CLOCK0"; + parameter signed_aclr_b = "ACLR3"; + parameter signed_pipeline_register_b = "CLOCK0"; + parameter signed_pipeline_aclr_b = "ACLR3"; + + // multiplier parameters + + parameter multiplier_register0 = "CLOCK0"; + parameter multiplier_aclr0 = "ACLR3"; + parameter multiplier_register1 = "CLOCK0"; + parameter multiplier_aclr1 = "ACLR3"; + parameter multiplier_register2 = "CLOCK0"; + parameter multiplier_aclr2 = "ACLR3"; + parameter multiplier_register3 = "CLOCK0"; + parameter multiplier_aclr3 = "ACLR3"; + + parameter port_addnsub1 = "PORT_CONNECTIVITY"; + parameter addnsub_multiplier_register1 = "CLOCK0"; + parameter addnsub_multiplier_aclr1 = "ACLR3"; + parameter addnsub_multiplier_pipeline_register1 = "CLOCK0"; + parameter addnsub_multiplier_pipeline_aclr1 = "ACLR3"; + + parameter port_addnsub3 = "PORT_CONNECTIVITY"; + parameter addnsub_multiplier_register3 = "CLOCK0"; + parameter addnsub_multiplier_aclr3 = "ACLR3"; + parameter addnsub_multiplier_pipeline_register3 = "CLOCK0"; + parameter addnsub_multiplier_pipeline_aclr3 = "ACLR3"; + + parameter addnsub1_round_aclr = "ACLR3"; + parameter addnsub1_round_pipeline_aclr = "ACLR3"; + parameter addnsub1_round_register = "CLOCK0"; + parameter addnsub1_round_pipeline_register = "CLOCK0"; + parameter addnsub3_round_aclr = "ACLR3"; + parameter addnsub3_round_pipeline_aclr = "ACLR3"; + parameter addnsub3_round_register = "CLOCK0"; + parameter addnsub3_round_pipeline_register = "CLOCK0"; + + parameter mult01_round_aclr = "ACLR3"; + parameter mult01_round_register = "CLOCK0"; + parameter mult01_saturation_register = "CLOCK0"; + parameter mult01_saturation_aclr = "ACLR3"; + parameter mult23_round_register = "CLOCK0"; + parameter mult23_round_aclr = "ACLR3"; + parameter mult23_saturation_register = "CLOCK0"; + parameter mult23_saturation_aclr = "ACLR3"; + + // StratixII parameters + parameter multiplier01_rounding = "NO"; + parameter multiplier01_saturation = "NO"; + parameter multiplier23_rounding = "NO"; + parameter multiplier23_saturation = "NO"; + parameter adder1_rounding = "NO"; + parameter adder3_rounding = "NO"; + parameter port_mult0_is_saturated = "UNUSED"; + parameter port_mult1_is_saturated = "UNUSED"; + parameter port_mult2_is_saturated = "UNUSED"; + parameter port_mult3_is_saturated = "UNUSED"; + + // output parameters + + parameter output_register = "CLOCK0"; + parameter output_aclr = "ACLR0"; + + // general setting parameters + + parameter extra_latency = 0; + parameter dedicated_multiplier_circuitry = "AUTO"; + parameter dsp_block_balancing = "AUTO"; + parameter intended_device_family = "Stratix"; + + // ---------------- + // PORT DECLARATION + // ---------------- + + // data input ports + input [number_of_multipliers * width_a -1 : 0] dataa; + input [number_of_multipliers * width_b -1 : 0] datab; + + input [width_a -1 : 0] scanina; + input [width_b -1 : 0] scaninb; + + input [number_of_multipliers -1 : 0] sourcea; + input [number_of_multipliers -1 : 0] sourceb; + + // clock ports + input clock3; + input clock2; + input clock1; + input clock0; + + // clear ports + input aclr3; + input aclr2; + input aclr1; + input aclr0; + + // clock enable ports + input ena3; + input ena2; + input ena1; + input ena0; + + // control signals + input signa; + input signb; + input addnsub1; + input addnsub3; + + // StratixII only input ports + input mult01_round; + input mult23_round; + input mult01_saturation; + input mult23_saturation; + input addnsub1_round; + input addnsub3_round; + + + // output ports + output [width_result -1 : 0] result; + output [width_a -1 : 0] scanouta; + output [width_b -1 : 0] scanoutb; + + // StratixII only output ports + output mult0_is_saturated; + output mult1_is_saturated; + output mult2_is_saturated; + output mult3_is_saturated; + + // ----------------------------------- + // Parameters internally used + // ----------------------------------- + // Represent the internal used width_a + parameter int_width_a = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") && + (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? width_a: + (width_a < 18)? 18 : width_a); + // Represent the internal used width_b + parameter int_width_b = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") && + (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? width_b: + (width_b < 18)? 18 : width_b); + + //Represent the internally used width_result + parameter int_width_result = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") && + (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? width_result: + (width_result > (int_width_a + int_width_b))? width_result + width_result - int_width_a - int_width_b: + int_width_a + int_width_b); + + // Represent the internally used width_result + parameter int_mult_diff_bit = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") && + (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? 0: + (int_width_a - width_a + int_width_b - width_b)); + + parameter sat_ini_value = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO"))? 3: + int_width_a + int_width_b - 3); + + // ----------------------------------- + // Constants internally used + // ----------------------------------- + // Represent the number of bits needed to be rounded in multiplier where the + // value 17 here refers to the 2 sign bits and the 15 wanted bits for rounding + `define MULT_ROUND_BITS (((multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? 1 : (int_width_a + int_width_b) - 17) + + // Represent the number of bits needed to be rounded in adder where the + // value 18 here refers to the 3 sign bits and the 15 wanted bits for rounding. + `define ADDER_ROUND_BITS (((multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? 1 :(int_width_a + int_width_b) - 17) + + + + // --------------- + // REG DECLARATION + // --------------- + + reg [int_width_result :0] temp_sum; + reg [int_width_result : 0] mult_res_ext; + reg [int_width_result : 0] temp_sum_reg; + + reg [4 * int_width_a -1 : 0] mult_a_reg; + reg [4 * int_width_b -1 : 0] mult_b_reg; + + + reg [(int_width_a + int_width_b) -1:0] mult_res_0; + reg [(int_width_a + int_width_b) -1:0] mult_res_1; + reg [(int_width_a + int_width_b) -1:0] mult_res_2; + reg [(int_width_a + int_width_b) -1:0] mult_res_3; + + + reg [4 * (int_width_a + int_width_b) -1:0] mult_res_reg; + reg [(int_width_a + int_width_b - 1) :0] mult_res_temp; + + + reg sign_a_pipe_reg; + reg sign_a_reg; + reg sign_b_pipe_reg; + reg sign_b_reg; + + reg addsub1_reg; + reg addsub1_pipe_reg; + + reg addsub3_reg; + reg addsub3_pipe_reg; + + + // StratixII features related internal reg type + + reg [(int_width_a + int_width_b + 3) -1 : 0] mult0_round_out; + reg [(int_width_a + int_width_b + 3) -1 : 0] mult0_saturate_out; + reg [(int_width_a + int_width_b + 3) -1 : 0] mult0_result; + reg mult0_saturate_overflow; + reg mult0_saturate_overflow_stat; + + reg [(int_width_a + int_width_b + 3) -1 : 0] mult1_round_out; + reg [(int_width_a + int_width_b + 3) -1 : 0] mult1_saturate_out; + reg [(int_width_a + int_width_b) -1 : 0] mult1_result; + reg mult1_saturate_overflow; + reg mult1_saturate_overflow_stat; + + reg [(int_width_a + int_width_b + 3) -1 : 0] mult2_round_out; + reg [(int_width_a + int_width_b + 3) -1 : 0] mult2_saturate_out; + reg [(int_width_a + int_width_b) -1 : 0] mult2_result; + reg mult2_saturate_overflow; + reg mult2_saturate_overflow_stat; + + reg [(int_width_a + int_width_b + 3) -1 : 0] mult3_round_out; + reg [(int_width_a + int_width_b + 3) -1 : 0] mult3_saturate_out; + reg [(int_width_a + int_width_b) -1 : 0] mult3_result; + reg mult3_saturate_overflow; + reg mult3_saturate_overflow_stat; + + reg mult01_round_reg; + reg mult01_saturate_reg; + reg mult23_round_reg; + reg mult23_saturate_reg; + reg [3 : 0] mult_saturate_overflow_reg; + reg [3 : 0] mult_saturate_overflow_pipe_reg; + + reg [int_width_result : 0] adder1_round_out; + reg [int_width_result : 0] adder1_result; + reg addnsub1_round_reg; + reg addnsub1_round_pipe_reg; + + reg [int_width_result : 0] adder3_round_out; + reg [int_width_result : 0] adder3_result; + reg addnsub3_round_reg; + reg addnsub3_round_pipe_reg; + + reg zero_pad; + + //----------------- + // TRI DECLARATION + //----------------- + tri0 signa_z; + tri0 signb_z; + tri1 addnsub1_z; + tri1 addnsub3_z; + tri0 [4 * int_width_a -1 : 0] dataa_int; + tri0 [4 * int_width_b -1 : 0] datab_int; + tri0 [4 * int_width_a -1 : 0] new_dataa_int; + tri0 [4 * int_width_b -1 : 0] new_datab_int; + reg [4 * int_width_a -1 : 0] dataa_reg; + reg [4 * int_width_b -1 : 0] datab_reg; + tri0 [int_width_a - 1 : 0] scanina_z; + tri0 [int_width_b - 1 : 0] scaninb_z; + + // Tri wire for clear signal + tri0 input_reg_a0_wire_clr; + tri0 input_reg_a1_wire_clr; + tri0 input_reg_a2_wire_clr; + tri0 input_reg_a3_wire_clr; + + tri0 input_reg_b0_wire_clr; + tri0 input_reg_b1_wire_clr; + tri0 input_reg_b2_wire_clr; + tri0 input_reg_b3_wire_clr; + + tri0 sign_reg_a_wire_clr; + tri0 sign_pipe_a_wire_clr; + + tri0 sign_reg_b_wire_clr; + tri0 sign_pipe_b_wire_clr; + + tri0 addsub1_reg_wire_clr; + tri0 addsub1_pipe_wire_clr; + + tri0 addsub3_reg_wire_clr; + tri0 addsub3_pipe_wire_clr; + + tri0 multiplier_reg0_wire_clr; + tri0 multiplier_reg1_wire_clr; + tri0 multiplier_reg2_wire_clr; + tri0 multiplier_reg3_wire_clr; + + tri0 addnsub1_round_wire_clr; + tri0 addnsub1_round_pipe_wire_clr; + + tri0 addnsub3_round_wire_clr; + tri0 addnsub3_round_pipe_wire_clr; + + tri0 mult01_round_wire_clr; + tri0 mult01_saturate_wire_clr; + + tri0 mult23_round_wire_clr; + tri0 mult23_saturate_wire_clr; + + tri0 output_reg_wire_clr; + + tri0 [3 : 0] sourcea_wire; + tri0 [3 : 0] sourceb_wire; + + + + // Tri wire for enable signal + + tri1 input_reg_a0_wire_en; + tri1 input_reg_a1_wire_en; + tri1 input_reg_a2_wire_en; + tri1 input_reg_a3_wire_en; + + tri1 input_reg_b0_wire_en; + tri1 input_reg_b1_wire_en; + tri1 input_reg_b2_wire_en; + tri1 input_reg_b3_wire_en; + + + tri1 sign_reg_a_wire_en; + tri1 sign_pipe_a_wire_en; + + tri1 sign_reg_b_wire_en; + tri1 sign_pipe_b_wire_en; + + tri1 addsub1_reg_wire_en; + tri1 addsub1_pipe_wire_en; + + tri1 addsub3_reg_wire_en; + tri1 addsub3_pipe_wire_en; + + tri1 multiplier_reg0_wire_en; + tri1 multiplier_reg1_wire_en; + tri1 multiplier_reg2_wire_en; + tri1 multiplier_reg3_wire_en; + + tri1 addnsub1_round_wire_en; + tri1 addnsub1_round_pipe_wire_en; + + tri1 addnsub3_round_wire_en; + tri1 addnsub3_round_pipe_wire_en; + + tri1 mult01_round_wire_en; + tri1 mult01_saturate_wire_en; + + tri1 mult23_round_wire_en; + tri1 mult23_saturate_wire_en; + + tri1 output_reg_wire_en; + + + + + + // ---------------- + // WIRE DECLARATION + // ---------------- + + // Wire for Clock signals + wire input_reg_a0_wire_clk; + wire input_reg_a1_wire_clk; + wire input_reg_a2_wire_clk; + wire input_reg_a3_wire_clk; + + wire input_reg_b0_wire_clk; + wire input_reg_b1_wire_clk; + wire input_reg_b2_wire_clk; + wire input_reg_b3_wire_clk; + + wire sign_reg_a_wire_clk; + wire sign_pipe_a_wire_clk; + + wire sign_reg_b_wire_clk; + wire sign_pipe_b_wire_clk; + + wire addsub1_reg_wire_clk; + wire addsub1_pipe_wire_clk; + + wire addsub3_reg_wire_clk; + wire addsub3_pipe_wire_clk; + + wire multiplier_reg0_wire_clk; + wire multiplier_reg1_wire_clk; + wire multiplier_reg2_wire_clk; + wire multiplier_reg3_wire_clk; + + wire output_reg_wire_clk; + + wire addnsub1_round_wire_clk; + wire addnsub1_round_pipe_wire_clk; + wire addnsub1_round_wire; + wire addnsub1_round_pipe_wire; + wire addnsub1_round_pre; + wire addnsub3_round_wire_clk; + wire addnsub3_round_pipe_wire_clk; + wire addnsub3_round_wire; + wire addnsub3_round_pipe_wire; + wire addnsub3_round_pre; + + wire mult01_round_wire_clk; + wire mult01_saturate_wire_clk; + wire mult23_round_wire_clk; + wire mult23_saturate_wire_clk; + wire mult01_round_pre; + wire mult01_saturate_pre; + wire mult01_round_wire; + wire mult01_saturate_wire; + wire mult23_round_pre; + wire mult23_saturate_pre; + wire mult23_round_wire; + wire mult23_saturate_wire; + wire [3 : 0] mult_is_saturate_vec; + wire [3 : 0] mult_saturate_overflow_vec; + + wire [4 * int_width_a -1 : 0] mult_a_pre; + wire [4 * int_width_b -1 : 0] mult_b_pre; + + wire [int_width_a -1 : 0] scanouta; + wire [int_width_b -1 : 0] scanoutb; + + wire sign_a_int; + wire sign_b_int; + + wire addsub1_int; + wire addsub3_int; + + wire [4 * int_width_a -1 : 0] mult_a_wire; + wire [4 * int_width_b -1 : 0] mult_b_wire; + wire [4 * (int_width_a + int_width_b) -1:0] mult_res_wire; + wire sign_a_pipe_wire; + wire sign_a_wire; + wire sign_b_pipe_wire; + wire sign_b_wire; + wire addsub1_wire; + wire addsub1_pipe_wire; + wire addsub3_wire; + wire addsub3_pipe_wire; + + wire [int_width_a -1 : 0] i_scanina; + wire [int_width_b -1 : 0] i_scaninb; + + wire [(int_width_result - 1): 0] output_reg_wire_result; + wire [31:0] head_result_wire; + reg [(int_width_result - 1): 0] output_laten_result; + reg [(int_width_result - 1): 0] result_pipe [extra_latency : 0]; + reg [31:0] head_result; + integer head_result_int; + + + // ------------------- + // INTEGER DECLARATION + // ------------------- + integer num_bit_mult0; + integer num_bit_mult1; + integer num_bit_mult2; + integer num_bit_mult3; + integer j; + integer num_mult; + integer num_stor; + + + + // ------------------------ + // COMPONENT INSTANTIATIONS + // ------------------------ + ALTERA_DEVICE_FAMILIES dev (); + + + // ----------------------------------------------------------------------------- + // This block checks if the two numbers to be multiplied (mult_a/mult_b) is to + // be interpreted as a negative number or not. If so, then two's complement is + // performed. + // The numbers are then multipled. The sign of the result (positive or negative) + // is determined based on the sign of the two input numbers + // ------------------------------------------------------------------------------ + + function [(int_width_a + int_width_b - 1):0] do_multiply; + input [32 : 0] multiplier; + input signa_wire; + input signb_wire; + begin:MULTIPLY + + reg [int_width_a + int_width_b -1 :0] temp_mult_zero; + reg [int_width_a + int_width_b -1 :0] temp_mult; + reg [int_width_a -1 :0] op_a; + reg [int_width_b -1 :0] op_b; + reg [int_width_a -1 :0] op_a_int; + reg [int_width_b -1 :0] op_b_int; + reg neg_a; + reg neg_b; + reg temp_mult_signed; + + temp_mult_zero = 0; + temp_mult = 0; + + op_a = mult_a_wire >> (multiplier * int_width_a); + op_b = mult_b_wire >> (multiplier * int_width_b); + + neg_a = op_a[int_width_a-1] & (signa_wire); + neg_b = op_b[int_width_b-1] & (signb_wire); + + op_a_int = (neg_a == 1) ? (~op_a + 1) : op_a; + op_b_int = (neg_b == 1) ? (~op_b + 1) : op_b; + + temp_mult = op_a_int * op_b_int; + temp_mult = (neg_a ^ neg_b) ? (temp_mult_zero - temp_mult) : temp_mult; + + do_multiply = temp_mult; + end + endfunction + + + + + // -------------------------------------------------------------- + // initialization block of all the internal signals and registers + // -------------------------------------------------------------- + initial + begin + + // Checking for invalid parameters, in case Wizard is bypassed (hand-modified). + if (number_of_multipliers > 4) + begin + $display("Altmult_add does not currently support NUMBER_OF_MULTIPLIERS > 4"); + $stop; + end + if (number_of_multipliers <= 0) + begin + $display("NUMBER_OF_MULTIPLIERS must be greater than 0."); + $stop; + end + + + if (width_a <= 0) + begin + $display("Error: width_a must be greater than 0."); + $stop; + end + if (width_b <= 0) + begin + $display("Error: width_b must be greater than 0."); + $stop; + end + if (width_result <= 0) + begin + $display("Error: width_result must be greater than 0."); + $stop; + end + + if ((input_source_a0 != "DATAA") && + (input_source_a0 != "SCANA") && + (input_source_a0 != "VARIABLE")) + begin + $display("Error: The INPUT_SOURCE_A0 parameter is set to an illegal value."); + $stop; + end + + if ((input_source_a1 != "DATAA") && + (input_source_a1 != "SCANA") && + (input_source_a1 != "VARIABLE")) + begin + $display("Error: The INPUT_SOURCE_A1 parameter is set to an illegal value."); + $stop; + end + + if ((input_source_a2 != "DATAA") && + (input_source_a2 != "SCANA") && + (input_source_a2 != "VARIABLE")) + begin + $display("Error: The INPUT_SOURCE_A2 parameter is set to an illegal value."); + $stop; + end + + if ((input_source_a3 != "DATAA") && + (input_source_a3 != "SCANA") && + (input_source_a3 != "VARIABLE")) + begin + $display("Error: The INPUT_SOURCE_A3 parameter is set to an illegal value."); + $stop; + end + + if ((input_source_b0 != "DATAB") && + (input_source_b0 != "SCANB") && + (input_source_b0 != "VARIABLE")) + begin + $display("Error: The INPUT_SOURCE_B0 parameter is set to an illegal value."); + $stop; + end + + if ((input_source_b1 != "DATAB") && + (input_source_b1 != "SCANB") && + (input_source_b1 != "VARIABLE")) + begin + $display("Error: The INPUT_SOURCE_B1 parameter is set to an illegal value."); + $stop; + end + + if ((input_source_b2 != "DATAB") && + (input_source_b2 != "SCANB") && + (input_source_b2 != "VARIABLE")) + begin + $display("Error: The INPUT_SOURCE_B2 parameter is set to an illegal value."); + $stop; + end + + if ((input_source_b3 != "DATAB") && + (input_source_b3 != "SCANB") && + (input_source_b3 != "VARIABLE")) + begin + $display("Error: The INPUT_SOURCE_B3 parameter is set to an illegal value."); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) && + (input_source_a0 == "VARIABLE")) + begin + $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) && + (input_source_a1 == "VARIABLE")) + begin + $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) && + (input_source_a2 == "VARIABLE")) + begin + $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) && + (input_source_a3 == "VARIABLE")) + begin + $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) && + (input_source_b0 == "VARIABLE")) + begin + $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) && + (input_source_b1 == "VARIABLE")) + begin + $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) && + (input_source_b2 == "VARIABLE")) + begin + $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) && + (input_source_b3 == "VARIABLE")) + begin + $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family); + $stop; + end + + if ((dedicated_multiplier_circuitry != "AUTO") && + (dedicated_multiplier_circuitry != "YES") && + (dedicated_multiplier_circuitry != "NO")) + begin + $display("Error: The DEDICATED_MULTIPLIER_CIRCUITRY parameter is set to an illegal value."); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && + ((multiplier01_rounding == "YES") || (multiplier23_rounding == "YES") || + (multiplier01_rounding == "VARIABLE") || (multiplier23_rounding == "VARIABLE"))) + begin + $display("Error: Rounding for multiplier is not supported in %s device family", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && + ((adder1_rounding == "YES") || (adder3_rounding == "YES") || + (adder1_rounding == "VARIABLE") || (adder3_rounding == "VARIABLE"))) + begin + $display("Error: Rounding for adder is not supported in %s device family", intended_device_family); + $stop; + end + + if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && + ((multiplier01_saturation == "YES") || (multiplier23_saturation == "YES") || + (multiplier01_saturation == "VARIABLE") || (multiplier23_saturation == "VARIABLE"))) + begin + $display("Error: Saturation for multiplier is not supported in %s device family", intended_device_family); + $stop; + end + + if ((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") && + (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO")) + begin + if (int_width_result != width_result) + begin + $display ("Error: Internal parameter setting of int_width_result is illegal"); + $stop; + end + + if (int_mult_diff_bit != 0) + begin + $display ("Error: Internal parameter setting of int_mult_diff_bit is illegal"); + $stop; + end + + end + else + begin + if (((width_a < 18) && (int_width_a != 18)) || + ((width_a >= 18) && (int_width_a != width_a))) + begin + $display ("Error: Internal parameter setting of int_width_a is illegal"); + $stop; + end + + + if (((width_b < 18) && (int_width_b != 18)) || + ((width_b >= 18) && (int_width_b != width_b))) + begin + $display ("Error: Internal parameter setting of int_width_b is illegal"); + $stop; + end + + + if (int_width_result > (int_width_a + int_width_b)) + begin + if (int_width_result != (width_result + width_result - int_width_a - int_width_b)) + begin + $display ("Error: Internal parameter setting for int_width_result is illegal"); + $stop; + end + end + else + if (int_width_result != (int_width_a + int_width_b)) + begin + $display ("Error: Internal parameter setting for int_width_result is illegal"); + $stop; + end + + if (int_mult_diff_bit != (int_width_a - width_a + int_width_b - width_b)) + begin + $display ("Error: Internal parameter setting of int_mult_diff_bit is illegal"); + $stop; + end + end + + + + temp_sum_reg = 0; + + mult_a_reg = 0; + mult_b_reg = 0; + mult_res_reg = 0; + + sign_a_reg = ((port_signa == "PORT_CONNECTIVITY")? + (representation_a != "UNUSED" ? (representation_a == "SIGNED" ? 1 : 0) : 0) : + (port_signa == "PORT_USED")? 0 : + (port_signa == "PORT_UNUSED")? (representation_a == "SIGNED" ? 1 : 0) : 0); + + sign_a_pipe_reg = ((port_signa == "PORT_CONNECTIVITY")? + (representation_a != "UNUSED" ? (representation_a == "SIGNED" ? 1 : 0) : 0) : + (port_signa == "PORT_USED")? 0 : + (port_signa == "PORT_UNUSED")? (representation_a == "SIGNED" ? 1 : 0) : 0); + + sign_b_reg = ((port_signb == "PORT_CONNECTIVITY")? + (representation_b != "UNUSED" ? (representation_b == "SIGNED" ? 1 : 0) : 0) : + (port_signb == "PORT_USED")? 0 : + (port_signb == "PORT_UNUSED")? (representation_b == "SIGNED" ? 1 : 0) : 0); + + sign_b_pipe_reg = ((port_signb == "PORT_CONNECTIVITY")? + (representation_b != "UNUSED" ? (representation_b == "SIGNED" ? 1 : 0) : 0) : + (port_signb == "PORT_USED")? 0 : + (port_signb == "PORT_UNUSED")? (representation_b == "SIGNED" ? 1 : 0) : 0); + + addsub1_reg = ((port_addnsub1 == "PORT_CONNECTIVITY")? + (multiplier1_direction != "UNUSED" ? (multiplier1_direction == "ADD" ? 1 : 0) : 0) : + (port_addnsub1 == "PORT_USED")? 0 : + (port_addnsub1 == "PORT_UNUSED")? (multiplier1_direction == "ADD" ? 1 : 0) : 0); + + addsub1_pipe_reg = addsub1_reg; + + addsub3_reg = ((port_addnsub3 == "PORT_CONNECTIVITY")? + (multiplier3_direction != "UNUSED" ? (multiplier3_direction == "ADD" ? 1 : 0) : 0) : + (port_addnsub3 == "PORT_USED")? 0 : + (port_addnsub3 == "PORT_UNUSED")? (multiplier3_direction == "ADD" ? 1 : 0) : 0); + + addsub3_pipe_reg = addsub3_reg; + + // StratixII related reg type initialization + + mult0_round_out = 0; + mult0_saturate_out = 0; + mult0_result = 0; + mult0_saturate_overflow = 0; + + mult1_round_out = 0; + mult1_saturate_out = 0; + mult1_result = 0; + mult1_saturate_overflow = 0; + + mult_saturate_overflow_reg [3] = 0; + mult_saturate_overflow_reg [2] = 0; + mult_saturate_overflow_reg [1] = 0; + mult_saturate_overflow_reg [0] = 0; + + mult_saturate_overflow_pipe_reg [3] = 0; + mult_saturate_overflow_pipe_reg [2] = 0; + mult_saturate_overflow_pipe_reg [1] = 0; + mult_saturate_overflow_pipe_reg [0] = 0; + zero_pad = 0; + head_result = 0; + + for ( num_stor = extra_latency; num_stor >= 0; num_stor = num_stor - 1 ) + begin + result_pipe[num_stor] = {int_width_result{1'b0}}; + end + + end // end initialization block + + assign signa_z = signa; + assign signb_z = signb; + assign addnsub1_z = addnsub1; + assign addnsub3_z = addnsub3; + assign scanina_z[width_a - 1 : 0] = scanina[width_a - 1 : 0]; + assign scaninb_z[width_b - 1 : 0] = scaninb[width_b - 1 : 0]; + + always @(dataa or datab) + begin + dataa_reg[(number_of_multipliers * width_a) - 1:0] = dataa[(number_of_multipliers* width_a) -1:0]; + datab_reg[(number_of_multipliers * width_b) - 1: 0] = datab[(number_of_multipliers * width_b) - 1:0]; + end + + assign new_dataa_int[int_width_a - 1:int_width_a - width_a] = (number_of_multipliers >= 1) ? dataa_reg[width_a - 1:0]: {width_a{1'b0}}; + + assign new_dataa_int[(2 * int_width_a) - 1: (2 * int_width_a) - width_a] = (number_of_multipliers >= 2)? dataa_reg[(2 * width_a) - 1: width_a] : {width_a{1'b0}}; + + assign new_dataa_int[(3 * int_width_a) - 1: (3 * int_width_a) - width_a] = (number_of_multipliers >= 3)? dataa_reg[(3 * width_a) - 1:(2 * width_a)] : {width_a{1'b0}}; + + assign new_dataa_int[(4 * int_width_a) - 1: (4 * int_width_a) - width_a] = (number_of_multipliers >= 4) ? dataa_reg[(4 * width_a) - 1:(3 * width_a)] : {width_a{1'b0}}; + + assign new_datab_int[int_width_b - 1:int_width_b - width_b] = (number_of_multipliers >= 1) ? datab_reg[width_b - 1:0]: {width_b{1'b0}}; + + assign new_datab_int[(2 * int_width_b) - 1: (2 * int_width_b) - width_b] = (number_of_multipliers >= 2)? datab_reg[(2 * width_b) - 1:width_b]:{width_b{1'b0}}; + + assign new_datab_int[(3 * int_width_b) - 1: (3 * int_width_b) - width_b] = (number_of_multipliers >= 3)? datab_reg[(3 * width_b) - 1:(2 * width_b)] : {width_b{1'b0}}; + + assign new_datab_int[(4 * int_width_b) - 1: (4 * int_width_b) - width_b] = (number_of_multipliers >= 4) ? datab_reg[(4 * width_b) - 1:(3 * width_b)] : {width_b{1'b0}}; + + + + assign dataa_int[number_of_multipliers * int_width_a-1:0] = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") && + (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? dataa[number_of_multipliers * width_a - 1:0]: + (width_a < 18)? new_dataa_int[number_of_multipliers * int_width_a-1:0] : dataa[number_of_multipliers * width_a - 1:0]); + + assign datab_int[number_of_multipliers * int_width_b-1:0] = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") && + (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? datab[number_of_multipliers * width_b - 1:0]: + (width_b < 18)? new_datab_int[number_of_multipliers * int_width_b - 1:0] : datab[number_of_multipliers * width_b - 1:0]); + + + assign addnsub1_round_pre = addnsub1_round; + assign addnsub3_round_pre = addnsub3_round; + assign mult01_round_pre = mult01_round; + assign mult01_saturate_pre = mult01_saturation; + assign mult23_round_pre = mult23_round; + assign mult23_saturate_pre = mult23_saturation; + + // --------------------------------------------------------- + // This block updates the output port for each multiplier's + // saturation port only if port_mult0_is_saturated is set to used + // --------------------------------------------------------- + + + assign mult0_is_saturated = (port_mult0_is_saturated == "UNUSED")? 1'bz: + (port_mult0_is_saturated == "USED")? mult_is_saturate_vec[0]: 1'bz; + + assign mult1_is_saturated = (port_mult1_is_saturated == "UNUSED")? 1'bz: + (port_mult1_is_saturated == "USED")? mult_is_saturate_vec[1]: 1'bz; + + assign mult2_is_saturated = (port_mult2_is_saturated == "UNUSED")? 1'bz: + (port_mult2_is_saturated == "USED")? mult_is_saturate_vec[2]: 1'bz; + + assign mult3_is_saturated = (port_mult3_is_saturated == "UNUSED")? 1'bz: + (port_mult3_is_saturated == "USED")? mult_is_saturate_vec[3]: 1'bz; + + assign sourcea_wire[number_of_multipliers - 1 : 0] = sourcea[number_of_multipliers - 1 : 0]; + + assign sourceb_wire[number_of_multipliers - 1 : 0] = sourceb[number_of_multipliers - 1 : 0]; + + + + // --------------------------------------------------------- + // This block updates the internal clock signals accordingly + // every time the global clock signal changes state + // --------------------------------------------------------- + + assign input_reg_a0_wire_clk = (input_register_a0 == "CLOCK0")? clock0: + (input_register_a0 == "UNREGISTERED")? 0: + (input_register_a0 == "CLOCK1")? clock1: + (input_register_a0 == "CLOCK2")? clock2: + (input_register_a0 == "CLOCK3")? clock3: 0; + + + assign input_reg_a1_wire_clk = (input_register_a1 == "CLOCK0")? clock0: + (input_register_a1 == "UNREGISTERED")? 0: + (input_register_a1 == "CLOCK1")? clock1: + (input_register_a1 == "CLOCK2")? clock2: + (input_register_a1 == "CLOCK3")? clock3: 0; + + + assign input_reg_a2_wire_clk = (input_register_a2 == "CLOCK0")? clock0: + (input_register_a2 == "UNREGISTERED")? 0: + (input_register_a2 == "CLOCK1")? clock1: + (input_register_a2 == "CLOCK2")? clock2: + (input_register_a2 == "CLOCK3")? clock3: 0; + + + + assign input_reg_a3_wire_clk = (input_register_a3 == "CLOCK0")? clock0: + (input_register_a3 == "UNREGISTERED")? 0: + (input_register_a3 == "CLOCK1")? clock1: + (input_register_a3 == "CLOCK2")? clock2: + (input_register_a3 == "CLOCK3")? clock3: 0; + + + assign input_reg_b0_wire_clk = (input_register_b0 == "CLOCK0")? clock0: + (input_register_b0 == "UNREGISTERED")? 0: + (input_register_b0 == "CLOCK1")? clock1: + (input_register_b0 == "CLOCK2")? clock2: + (input_register_b0 == "CLOCK3")? clock3: 0; + + + assign input_reg_b1_wire_clk = (input_register_b1 == "CLOCK0")? clock0: + (input_register_b1 == "UNREGISTERED")? 0: + (input_register_b1 == "CLOCK1")? clock1: + (input_register_b1 == "CLOCK2")? clock2: + (input_register_b1 == "CLOCK3")? clock3: 0; + + + assign input_reg_b2_wire_clk = (input_register_b2 == "CLOCK0")? clock0: + (input_register_b2 == "UNREGISTERED")? 0: + (input_register_b2 == "CLOCK1")? clock1: + (input_register_b2 == "CLOCK2")? clock2: + (input_register_b2 == "CLOCK3")? clock3: 0; + + + assign input_reg_b3_wire_clk = (input_register_b3 == "CLOCK0")? clock0: + (input_register_b3 == "UNREGISTERED")? 0: + (input_register_b3 == "CLOCK1")? clock1: + (input_register_b3 == "CLOCK2")? clock2: + (input_register_b3 == "CLOCK3")? clock3: 0; + + + assign addsub1_reg_wire_clk = (addnsub_multiplier_register1 == "CLOCK0")? clock0: + (addnsub_multiplier_register1 == "UNREGISTERED")? 0: + (addnsub_multiplier_register1 == "CLOCK1")? clock1: + (addnsub_multiplier_register1 == "CLOCK2")? clock2: + (addnsub_multiplier_register1 == "CLOCK3")? clock3: 0; + + + assign addsub1_pipe_wire_clk = (addnsub_multiplier_pipeline_register1 == "CLOCK0")? clock0: + (addnsub_multiplier_pipeline_register1 == "UNREGISTERED")? 0: + (addnsub_multiplier_pipeline_register1 == "CLOCK1")? clock1: + (addnsub_multiplier_pipeline_register1 == "CLOCK2")? clock2: + (addnsub_multiplier_pipeline_register1 == "CLOCK3")? clock3: 0; + + + + assign addsub3_reg_wire_clk = (addnsub_multiplier_register3 == "CLOCK0")? clock0: + (addnsub_multiplier_register3 == "UNREGISTERED")? 0: + (addnsub_multiplier_register3 == "CLOCK1")? clock1: + (addnsub_multiplier_register3 == "CLOCK2")? clock2: + (addnsub_multiplier_register3 == "CLOCK3")? clock3: 0; + + + + assign addsub3_pipe_wire_clk = (addnsub_multiplier_pipeline_register3 == "CLOCK0")? clock0: + (addnsub_multiplier_pipeline_register3 == "UNREGISTERED")? 0: + (addnsub_multiplier_pipeline_register3 == "CLOCK1")? clock1: + (addnsub_multiplier_pipeline_register3 == "CLOCK2")? clock2: + (addnsub_multiplier_pipeline_register3 == "CLOCK3")? clock3: 0; + + + + + assign sign_reg_a_wire_clk = (signed_register_a == "CLOCK0")? clock0: + (signed_register_a == "UNREGISTERED")? 0: + (signed_register_a == "CLOCK1")? clock1: + (signed_register_a == "CLOCK2")? clock2: + (signed_register_a == "CLOCK3")? clock3: 0; + + + + assign sign_pipe_a_wire_clk = (signed_pipeline_register_a == "CLOCK0")? clock0: + (signed_pipeline_register_a == "UNREGISTERED")? 0: + (signed_pipeline_register_a == "CLOCK1")? clock1: + (signed_pipeline_register_a == "CLOCK2")? clock2: + (signed_pipeline_register_a == "CLOCK3")? clock3: 0; + + + + assign sign_reg_b_wire_clk = (signed_register_b == "CLOCK0")? clock0: + (signed_register_b == "UNREGISTERED")? 0: + (signed_register_b == "CLOCK1")? clock1: + (signed_register_b == "CLOCK2")? clock2: + (signed_register_b == "CLOCK3")? clock3: 0; + + + + assign sign_pipe_b_wire_clk = (signed_pipeline_register_b == "CLOCK0")? clock0: + (signed_pipeline_register_b == "UNREGISTERED")? 0: + (signed_pipeline_register_b == "CLOCK1")? clock1: + (signed_pipeline_register_b == "CLOCK2")? clock2: + (signed_pipeline_register_b == "CLOCK3")? clock3: 0; + + + + assign multiplier_reg0_wire_clk = (multiplier_register0 == "CLOCK0")? clock0: + (multiplier_register0 == "UNREGISTERED")? 0: + (multiplier_register0 == "CLOCK1")? clock1: + (multiplier_register0 == "CLOCK2")? clock2: + (multiplier_register0 == "CLOCK3")? clock3: 0; + + + + assign multiplier_reg1_wire_clk = (multiplier_register1 == "CLOCK0")? clock0: + (multiplier_register1 == "UNREGISTERED")? 0: + (multiplier_register1 == "CLOCK1")? clock1: + (multiplier_register1 == "CLOCK2")? clock2: + (multiplier_register1 == "CLOCK3")? clock3: 0; + + + assign multiplier_reg2_wire_clk = (multiplier_register2 == "CLOCK0")? clock0: + (multiplier_register2 == "UNREGISTERED")? 0: + (multiplier_register2 == "CLOCK1")? clock1: + (multiplier_register2 == "CLOCK2")? clock2: + (multiplier_register2 == "CLOCK3")? clock3: 0; + + + + assign multiplier_reg3_wire_clk = (multiplier_register3 == "CLOCK0")? clock0: + (multiplier_register3 == "UNREGISTERED")? 0: + (multiplier_register3 == "CLOCK1")? clock1: + (multiplier_register3 == "CLOCK2")? clock2: + (multiplier_register3 == "CLOCK3")? clock3: 0; + + + + assign output_reg_wire_clk = (output_register == "CLOCK0")? clock0: + (output_register == "UNREGISTERED")? 0: + (output_register == "CLOCK1")? clock1: + (output_register == "CLOCK2")? clock2: + (output_register == "CLOCK3")? clock3: 0; + + + assign addnsub1_round_wire_clk = (addnsub1_round_register == "CLOCK0")? clock0: + (addnsub1_round_register == "UNREGISTERED")? 0: + (addnsub1_round_register == "CLOCK1")? clock1: + (addnsub1_round_register == "CLOCK2")? clock2: + (addnsub1_round_register == "CLOCK3")? clock3: 0; + + + assign addnsub1_round_pipe_wire_clk = (addnsub1_round_pipeline_register == "CLOCK0")? clock0: + (addnsub1_round_pipeline_register == "UNREGISTERED")? 0: + (addnsub1_round_pipeline_register == "CLOCK1")? clock1: + (addnsub1_round_pipeline_register == "CLOCK2")? clock2: + (addnsub1_round_pipeline_register == "CLOCK3")? clock3: 0; + + + assign addnsub3_round_wire_clk = (addnsub3_round_register == "CLOCK0")? clock0: + (addnsub3_round_register == "UNREGISTERED")? 0: + (addnsub3_round_register == "CLOCK1")? clock1: + (addnsub3_round_register == "CLOCK2")? clock2: + (addnsub3_round_register == "CLOCK3")? clock3: 0; + + assign addnsub3_round_pipe_wire_clk = (addnsub3_round_pipeline_register == "CLOCK0")? clock0: + (addnsub3_round_pipeline_register == "UNREGISTERED")? 0: + (addnsub3_round_pipeline_register == "CLOCK1")? clock1: + (addnsub3_round_pipeline_register == "CLOCK2")? clock2: + (addnsub3_round_pipeline_register == "CLOCK3")? clock3: 0; + + assign mult01_round_wire_clk = (mult01_round_register == "CLOCK0")? clock0: + (mult01_round_register == "UNREGISTERED")? 0: + (mult01_round_register == "CLOCK1")? clock1: + (mult01_round_register == "CLOCK2")? clock2: + (mult01_round_register == "CLOCK3")? clock3: 0; + + + assign mult01_saturate_wire_clk = (mult01_saturation_register == "CLOCK0")? clock0: + (mult01_saturation_register == "UNREGISTERED")? 0: + (mult01_saturation_register == "CLOCK1")? clock1: + (mult01_saturation_register == "CLOCK2")? clock2: + (mult01_saturation_register == "CLOCK3")? clock3: 0; + + + assign mult23_round_wire_clk = (mult23_round_register == "CLOCK0")? clock0: + (mult23_round_register == "UNREGISTERED")? 0: + (mult23_round_register == "CLOCK1")? clock1: + (mult23_round_register == "CLOCK2")? clock2: + (mult23_round_register == "CLOCK3")? clock3: 0; + + assign mult23_saturate_wire_clk = (mult23_saturation_register == "CLOCK0")? clock0: + (mult23_saturation_register == "UNREGISTERED")? 0: + (mult23_saturation_register == "CLOCK1")? clock1: + (mult23_saturation_register == "CLOCK2")? clock2: + (mult23_saturation_register == "CLOCK3")? clock3: 0; + + + + // ---------------------------------------------------------------- + // This block updates the internal clock enable signals accordingly + // every time the global clock enable signal changes state + // ---------------------------------------------------------------- + + + assign input_reg_a0_wire_en = (input_register_a0 == "CLOCK0")? ena0: + (input_register_a0 == "UNREGISTERED")? 1: + (input_register_a0 == "CLOCK1")? ena1: + (input_register_a0 == "CLOCK2")? ena2: + (input_register_a0 == "CLOCK3")? ena3: 1; + + + + assign input_reg_a1_wire_en = (input_register_a1 == "CLOCK0")? ena0: + (input_register_a1 == "UNREGISTERED")? 1: + (input_register_a1 == "CLOCK1")? ena1: + (input_register_a1 == "CLOCK2")? ena2: + (input_register_a1 == "CLOCK3")? ena3: 1; + + + assign input_reg_a2_wire_en = (input_register_a2 == "CLOCK0")? ena0: + (input_register_a2 == "UNREGISTERED")? 1: + (input_register_a2 == "CLOCK1")? ena1: + (input_register_a2 == "CLOCK2")? ena2: + (input_register_a2 == "CLOCK3")? ena3: 1; + + + assign input_reg_a3_wire_en = (input_register_a3 == "CLOCK0")? ena0: + (input_register_a3 == "UNREGISTERED")? 1: + (input_register_a3 == "CLOCK1")? ena1: + (input_register_a3 == "CLOCK2")? ena2: + (input_register_a3 == "CLOCK3")? ena3: 1; + + + assign input_reg_b0_wire_en = (input_register_b0 == "CLOCK0")? ena0: + (input_register_b0 == "UNREGISTERED")? 1: + (input_register_b0 == "CLOCK1")? ena1: + (input_register_b0 == "CLOCK2")? ena2: + (input_register_b0 == "CLOCK3")? ena3: 1; + + + + assign input_reg_b1_wire_en = (input_register_b1 == "CLOCK0")? ena0: + (input_register_b1 == "UNREGISTERED")? 1: + (input_register_b1 == "CLOCK1")? ena1: + (input_register_b1 == "CLOCK2")? ena2: + (input_register_b1 == "CLOCK3")? ena3: 1; + + + assign input_reg_b2_wire_en = (input_register_b2 == "CLOCK0")? ena0: + (input_register_b2 == "UNREGISTERED")? 1: + (input_register_b2 == "CLOCK1")? ena1: + (input_register_b2 == "CLOCK2")? ena2: + (input_register_b2 == "CLOCK3")? ena3: 1; + + assign input_reg_b3_wire_en = (input_register_b3 == "CLOCK0")? ena0: + (input_register_b3 == "UNREGISTERED")? 1: + (input_register_b3 == "CLOCK1")? ena1: + (input_register_b3 == "CLOCK2")? ena2: + (input_register_b3 == "CLOCK3")? ena3: 1; + + + assign addsub1_reg_wire_en = (addnsub_multiplier_register1 == "CLOCK0")? ena0: + (addnsub_multiplier_register1 == "UNREGISTERED")? 1: + (addnsub_multiplier_register1 == "CLOCK1")? ena1: + (addnsub_multiplier_register1 == "CLOCK2")? ena2: + (addnsub_multiplier_register1 == "CLOCK3")? ena3: 1; + + + + assign addsub1_pipe_wire_en = (addnsub_multiplier_pipeline_register1 == "CLOCK0")? ena0: + (addnsub_multiplier_pipeline_register1 == "UNREGISTERED")? 1: + (addnsub_multiplier_pipeline_register1 == "CLOCK1")? ena1: + (addnsub_multiplier_pipeline_register1 == "CLOCK2")? ena2: + (addnsub_multiplier_pipeline_register1 == "CLOCK3")? ena3: 1; + + + assign addsub3_reg_wire_en = (addnsub_multiplier_register3 == "CLOCK0")? ena0: + (addnsub_multiplier_register3 == "UNREGISTERED")? 1: + (addnsub_multiplier_register3 == "CLOCK1")? ena1: + (addnsub_multiplier_register3 == "CLOCK2")? ena2: + (addnsub_multiplier_register3 == "CLOCK3")? ena3: 1; + + + + assign addsub3_pipe_wire_en = (addnsub_multiplier_pipeline_register3 == "CLOCK0")? ena0: + (addnsub_multiplier_pipeline_register3 == "UNREGISTERED")? 1: + (addnsub_multiplier_pipeline_register3 == "CLOCK1")? ena1: + (addnsub_multiplier_pipeline_register3 == "CLOCK2")? ena2: + (addnsub_multiplier_pipeline_register3 == "CLOCK3")? ena3: 1; + + + + assign sign_reg_a_wire_en = (signed_register_a == "CLOCK0")? ena0: + (signed_register_a == "UNREGISTERED")? 1: + (signed_register_a == "CLOCK1")? ena1: + (signed_register_a == "CLOCK2")? ena2: + (signed_register_a == "CLOCK3")? ena3: 1; + + + + assign sign_pipe_a_wire_en = (signed_pipeline_register_a == "CLOCK0")? ena0: + (signed_pipeline_register_a == "UNREGISTERED")? 1: + (signed_pipeline_register_a == "CLOCK1")? ena1: + (signed_pipeline_register_a == "CLOCK2")? ena2: + (signed_pipeline_register_a == "CLOCK3")? ena3: 1; + + + + assign sign_reg_b_wire_en = (signed_register_b == "CLOCK0")? ena0: + (signed_register_b == "UNREGISTERED")? 1: + (signed_register_b == "CLOCK1")? ena1: + (signed_register_b == "CLOCK2")? ena2: + (signed_register_b == "CLOCK3")? ena3: 1; + + + + assign sign_pipe_b_wire_en = (signed_pipeline_register_b == "CLOCK0")? ena0: + (signed_pipeline_register_b == "UNREGISTERED")? 1: + (signed_pipeline_register_b == "CLOCK1")? ena1: + (signed_pipeline_register_b == "CLOCK2")? ena2: + (signed_pipeline_register_b == "CLOCK3")? ena3: 1; + + + + assign multiplier_reg0_wire_en = (multiplier_register0 == "CLOCK0")? ena0: + (multiplier_register0 == "UNREGISTERED")? 1: + (multiplier_register0 == "CLOCK1")? ena1: + (multiplier_register0 == "CLOCK2")? ena2: + (multiplier_register0 == "CLOCK3")? ena3: 1; + + + + assign multiplier_reg1_wire_en = (multiplier_register1 == "CLOCK0")? ena0: + (multiplier_register1 == "UNREGISTERED")? 1: + (multiplier_register1 == "CLOCK1")? ena1: + (multiplier_register1 == "CLOCK2")? ena2: + (multiplier_register1 == "CLOCK3")? ena3: 1; + + + assign multiplier_reg2_wire_en = (multiplier_register2 == "CLOCK0")? ena0: + (multiplier_register2 == "UNREGISTERED")? 1: + (multiplier_register2 == "CLOCK1")? ena1: + (multiplier_register2 == "CLOCK2")? ena2: + (multiplier_register2 == "CLOCK3")? ena3: 1; + + + + assign multiplier_reg3_wire_en = (multiplier_register3 == "CLOCK0")? ena0: + (multiplier_register3 == "UNREGISTERED")? 1: + (multiplier_register3 == "CLOCK1")? ena1: + (multiplier_register3 == "CLOCK2")? ena2: + (multiplier_register3 == "CLOCK3")? ena3: 1; + + + + assign output_reg_wire_en = (output_register == "CLOCK0")? ena0: + (output_register == "UNREGISTERED")? 1: + (output_register == "CLOCK1")? ena1: + (output_register == "CLOCK2")? ena2: + (output_register == "CLOCK3")? ena3: 1; + + + assign addnsub1_round_wire_en = (addnsub1_round_register == "CLOCK0")? ena0: + (addnsub1_round_register == "UNREGISTERED")? 1: + (addnsub1_round_register == "CLOCK1")? ena1: + (addnsub1_round_register == "CLOCK2")? ena2: + (addnsub1_round_register == "CLOCK3")? ena3: 1; + + + assign addnsub1_round_pipe_wire_en = (addnsub1_round_pipeline_register == "CLOCK0")? ena0: + (addnsub1_round_pipeline_register == "UNREGISTERED")? 1: + (addnsub1_round_pipeline_register == "CLOCK1")? ena1: + (addnsub1_round_pipeline_register == "CLOCK2")? ena2: + (addnsub1_round_pipeline_register == "CLOCK3")? ena3: 1; + + + assign addnsub3_round_wire_en = (addnsub3_round_register == "CLOCK0")? ena0: + (addnsub3_round_register == "UNREGISTERED")? 1: + (addnsub3_round_register == "CLOCK1")? ena1: + (addnsub3_round_register == "CLOCK2")? ena2: + (addnsub3_round_register == "CLOCK3")? ena3: 1; + + + assign addnsub3_round_pipe_wire_en = (addnsub3_round_pipeline_register == "CLOCK0")? ena0: + (addnsub3_round_pipeline_register == "UNREGISTERED")? 1: + (addnsub3_round_pipeline_register == "CLOCK1")? ena1: + (addnsub3_round_pipeline_register == "CLOCK2")? ena2: + (addnsub3_round_pipeline_register == "CLOCK3")? ena3: 1; + + + assign mult01_round_wire_en = (mult01_round_register == "CLOCK0")? ena0: + (mult01_round_register == "UNREGISTERED")? 1: + (mult01_round_register == "CLOCK1")? ena1: + (mult01_round_register == "CLOCK2")? ena2: + (mult01_round_register == "CLOCK3")? ena3: 1; + + + assign mult01_saturate_wire_en = (mult01_saturation_register == "CLOCK0")? ena0: + (mult01_saturation_register == "UNREGISTERED")? 1: + (mult01_saturation_register == "CLOCK1")? ena1: + (mult01_saturation_register == "CLOCK2")? ena2: + (mult01_saturation_register == "CLOCK3")? ena3: 1; + + + assign mult23_round_wire_en = (mult23_round_register == "CLOCK0")? ena0: + (mult23_round_register == "UNREGISTERED")? 1: + (mult23_round_register == "CLOCK1")? ena1: + (mult23_round_register == "CLOCK2")? ena2: + (mult23_round_register == "CLOCK3")? ena3: 1; + + + assign mult23_saturate_wire_en = (mult23_saturation_register == "CLOCK0")? ena0: + (mult23_saturation_register == "UNREGISTERED")? 1: + (mult23_saturation_register == "CLOCK1")? ena1: + (mult23_saturation_register == "CLOCK2")? ena2: + (mult23_saturation_register == "CLOCK3")? ena3: 1; + + + // --------------------------------------------------------- + // This block updates the internal clear signals accordingly + // every time the global clear signal changes state + // --------------------------------------------------------- + + assign input_reg_a0_wire_clr = (input_aclr_a0 == "ACLR3")? aclr3: + (input_aclr_a0 == "UNREGISTERED")? 0: + (input_aclr_a0 == "ACLR0")? aclr0: + (input_aclr_a0 == "ACLR1")? aclr1: + (input_aclr_a0 == "ACLR2")? aclr2: 0; + + + + assign input_reg_a1_wire_clr = (input_aclr_a1 == "ACLR3")? aclr3: + (input_aclr_a1 == "UNREGISTERED")? 0: + (input_aclr_a1 == "ACLR0")? aclr0: + (input_aclr_a1 == "ACLR1")? aclr1: + (input_aclr_a1 == "ACLR2")? aclr2: 0; + + + assign input_reg_a2_wire_clr = (input_aclr_a2 == "ACLR3")? aclr3: + (input_aclr_a2 == "UNREGISTERED")? 0: + (input_aclr_a2 == "ACLR0")? aclr0: + (input_aclr_a2 == "ACLR1")? aclr1: + (input_aclr_a2 == "ACLR2")? aclr2: 0; + + + + assign input_reg_a3_wire_clr = (input_aclr_a3 == "ACLR3")? aclr3: + (input_aclr_a3 == "UNREGISTERED")? 0: + (input_aclr_a3 == "ACLR0")? aclr0: + (input_aclr_a3 == "ACLR1")? aclr1: + (input_aclr_a3 == "ACLR2")? aclr2: 0; + + + assign input_reg_b0_wire_clr = (input_aclr_b0 == "ACLR3")? aclr3: + (input_aclr_b0 == "UNREGISTERED")? 0: + (input_aclr_b0 == "ACLR0")? aclr0: + (input_aclr_b0 == "ACLR1")? aclr1: + (input_aclr_b0 == "ACLR2")? aclr2: 0; + + + assign input_reg_b1_wire_clr = (input_aclr_b1 == "ACLR3")? aclr3: + (input_aclr_b1 == "UNREGISTERED")? 0: + (input_aclr_b1 == "ACLR0")? aclr0: + (input_aclr_b1 == "ACLR1")? aclr1: + (input_aclr_b1 == "ACLR2")? aclr2: 0; + + + assign input_reg_b2_wire_clr = (input_aclr_b2 == "ACLR3")? aclr3: + (input_aclr_b2 == "UNREGISTERED")? 0: + (input_aclr_b2 == "ACLR0")? aclr0: + (input_aclr_b2 == "ACLR1")? aclr1: + (input_aclr_b2 == "ACLR2")? aclr2: 0; + + + + assign input_reg_b3_wire_clr = (input_aclr_b3 == "ACLR3")? aclr3: + (input_aclr_b3 == "UNREGISTERED")? 0: + (input_aclr_b3 == "ACLR0")? aclr0: + (input_aclr_b3 == "ACLR1")? aclr1: + (input_aclr_b3 == "ACLR2")? aclr2: 0; + + + + + assign addsub1_reg_wire_clr = (addnsub_multiplier_aclr1 == "ACLR3")? aclr3: + (addnsub_multiplier_aclr1 == "UNREGISTERED")? 0: + (addnsub_multiplier_aclr1 == "ACLR0")? aclr0: + (addnsub_multiplier_aclr1 == "ACLR1")? aclr1: + (addnsub_multiplier_aclr1 == "ACLR2")? aclr2: 0; + + + + assign addsub1_pipe_wire_clr = (addnsub_multiplier_pipeline_aclr1 == "ACLR3")? aclr3: + (addnsub_multiplier_pipeline_aclr1 == "UNREGISTERED")? 0: + (addnsub_multiplier_pipeline_aclr1 == "ACLR0")? aclr0: + (addnsub_multiplier_pipeline_aclr1 == "ACLR1")? aclr1: + (addnsub_multiplier_pipeline_aclr1 == "ACLR2")? aclr2: 0; + + + + + assign addsub3_reg_wire_clr = (addnsub_multiplier_aclr3 == "ACLR3")? aclr3: + (addnsub_multiplier_aclr3 == "UNREGISTERED")? 0: + (addnsub_multiplier_aclr3 == "ACLR0")? aclr0: + (addnsub_multiplier_aclr3 == "ACLR1")? aclr1: + (addnsub_multiplier_aclr3 == "ACLR2")? aclr2: 0; + + + + assign addsub3_pipe_wire_clr = (addnsub_multiplier_pipeline_aclr3 == "ACLR3")? aclr3: + (addnsub_multiplier_pipeline_aclr3 == "UNREGISTERED")? 0: + (addnsub_multiplier_pipeline_aclr3 == "ACLR0")? aclr0: + (addnsub_multiplier_pipeline_aclr3 == "ACLR1")? aclr1: + (addnsub_multiplier_pipeline_aclr3 == "ACLR2")? aclr2: 0; + + + + + assign sign_reg_a_wire_clr = (signed_aclr_a == "ACLR3")? aclr3: + (signed_aclr_a == "UNREGISTERED")? 0: + (signed_aclr_a == "ACLR0")? aclr0: + (signed_aclr_a == "ACLR1")? aclr1: + (signed_aclr_a == "ACLR2")? aclr2: 0; + + + + assign sign_pipe_a_wire_clr = (signed_pipeline_aclr_a == "ACLR3")? aclr3: + (signed_pipeline_aclr_a == "UNREGISTERED")? 0: + (signed_pipeline_aclr_a == "ACLR0")? aclr0: + (signed_pipeline_aclr_a == "ACLR1")? aclr1: + (signed_pipeline_aclr_a == "ACLR2")? aclr2: 0; + + + + assign sign_reg_b_wire_clr = (signed_aclr_b == "ACLR3")? aclr3: + (signed_aclr_b == "UNREGISTERED")? 0: + (signed_aclr_b == "ACLR0")? aclr0: + (signed_aclr_b == "ACLR1")? aclr1: + (signed_aclr_b == "ACLR2")? aclr2: 0; + + + + assign sign_pipe_b_wire_clr = (signed_pipeline_aclr_b == "ACLR3")? aclr3: + (signed_pipeline_aclr_b == "UNREGISTERED")? 0: + (signed_pipeline_aclr_b == "ACLR0")? aclr0: + (signed_pipeline_aclr_b == "ACLR1")? aclr1: + (signed_pipeline_aclr_b == "ACLR2")? aclr2: 0; + + + + + assign multiplier_reg0_wire_clr = (multiplier_aclr0 == "ACLR3")? aclr3: + (multiplier_aclr0 == "UNREGISTERED")? 0: + (multiplier_aclr0 == "ACLR0")? aclr0: + (multiplier_aclr0 == "ACLR1")? aclr1: + (multiplier_aclr0 == "ACLR2")? aclr2: 0; + + + + assign multiplier_reg1_wire_clr = (multiplier_aclr1 == "ACLR3")? aclr3: + (multiplier_aclr1 == "UNREGISTERED")? 0: + (multiplier_aclr1 == "ACLR0")? aclr0: + (multiplier_aclr1 == "ACLR1")? aclr1: + (multiplier_aclr1 == "ACLR2")? aclr2: 0; + + + + assign multiplier_reg2_wire_clr = (multiplier_aclr2 == "ACLR3")? aclr3: + (multiplier_aclr2 == "UNREGISTERED")? 0: + (multiplier_aclr2 == "ACLR0")? aclr0: + (multiplier_aclr2 == "ACLR1")? aclr1: + (multiplier_aclr2 == "ACLR2")? aclr2: 0; + + + + + assign multiplier_reg3_wire_clr = (multiplier_aclr3 == "ACLR3")? aclr3: + (multiplier_aclr3 == "UNREGISTERED")? 0: + (multiplier_aclr3 == "ACLR0")? aclr0: + (multiplier_aclr3 == "ACLR1")? aclr1: + (multiplier_aclr3 == "ACLR2")? aclr2: 0; + + + + + assign output_reg_wire_clr = (output_aclr == "ACLR3")? aclr3: + (output_aclr == "UNREGISTERED")? 0: + (output_aclr == "ACLR0")? aclr0: + (output_aclr == "ACLR1")? aclr1: + (output_aclr == "ACLR2")? aclr2: 0; + + + + assign addnsub1_round_wire_clr = (addnsub1_round_aclr == "ACLR3")? aclr3: + (addnsub1_round_register == "UNREGISTERED")? 0: + (addnsub1_round_aclr == "ACLR0")? aclr0: + (addnsub1_round_aclr == "ACLR1")? aclr1: + (addnsub1_round_aclr == "ACLR2")? aclr2: 0; + + + + assign addnsub1_round_pipe_wire_clr = (addnsub1_round_pipeline_aclr == "ACLR3")? aclr3: + (addnsub1_round_pipeline_register == "UNREGISTERED")? 0: + (addnsub1_round_pipeline_aclr == "ACLR0")? aclr0: + (addnsub1_round_pipeline_aclr == "ACLR1")? aclr1: + (addnsub1_round_pipeline_aclr == "ACLR2")? aclr2: 0; + + + + assign addnsub3_round_wire_clr = (addnsub3_round_aclr == "ACLR3")? aclr3: + (addnsub3_round_register == "UNREGISTERED")? 0: + (addnsub3_round_aclr == "ACLR0")? aclr0: + (addnsub3_round_aclr == "ACLR1")? aclr1: + (addnsub3_round_aclr == "ACLR2")? aclr2: 0; + + + + assign addnsub3_round_pipe_wire_clr = (addnsub3_round_pipeline_aclr == "ACLR3")? aclr3: + (addnsub3_round_pipeline_register == "UNREGISTERED")? 0: + (addnsub3_round_pipeline_aclr == "ACLR0")? aclr0: + (addnsub3_round_pipeline_aclr == "ACLR1")? aclr1: + (addnsub3_round_pipeline_aclr == "ACLR2")? aclr2: 0; + + + + assign mult01_round_wire_clr = (mult01_round_aclr == "ACLR3")? aclr3: + (mult01_round_register == "UNREGISTERED")? 0: + (mult01_round_aclr == "ACLR0")? aclr0: + (mult01_round_aclr == "ACLR1")? aclr1: + (mult01_round_aclr == "ACLR2")? aclr2: 0; + + + + assign mult01_saturate_wire_clr = (mult01_saturation_aclr == "ACLR3")? aclr3: + (mult01_saturation_register == "UNREGISTERED")? 0: + (mult01_saturation_aclr == "ACLR0")? aclr0: + (mult01_saturation_aclr == "ACLR1")? aclr1: + (mult01_saturation_aclr == "ACLR2")? aclr2: 0; + + + + assign mult23_round_wire_clr = (mult23_round_aclr == "ACLR3")? aclr3: + (mult23_round_register == "UNREGISTERED")? 0: + (mult23_round_aclr == "ACLR0")? aclr0: + (mult23_round_aclr == "ACLR1")? aclr1: + (mult23_round_aclr == "ACLR2")? aclr2: 0; + + + + assign mult23_saturate_wire_clr = (mult23_saturation_aclr == "ACLR3")? aclr3: + (mult23_saturation_register == "UNREGISTERED")? 0: + (mult23_saturation_aclr == "ACLR0")? aclr0: + (mult23_saturation_aclr == "ACLR1")? aclr1: + (mult23_saturation_aclr == "ACLR2")? aclr2: 0; + + + + // ------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult_a[int_width_a-1:0]) + // Signal Registered : mult_a_pre[int_width_a-1:0] + // + // Register is controlled by posedge input_reg_a0_wire_clk + // Register has a clock enable input_reg_a0_wire_en + // Register has an asynchronous clear signal, input_reg_a0_wire_clr + // NOTE : The combinatorial block will be executed if + // input_register_a0 is unregistered and mult_a_pre[int_width_a-1:0] changes value + // ------------------------------------------------------------------------------------- + assign mult_a_wire[int_width_a-1:0] = (input_register_a0 == "UNREGISTERED")? + mult_a_pre[int_width_a-1:0]: mult_a_reg[int_width_a-1:0]; + always @(posedge input_reg_a0_wire_clk or posedge input_reg_a0_wire_clr) + begin + if (input_reg_a0_wire_clr == 1) + mult_a_reg[int_width_a-1:0] <= 0; + else if ((input_reg_a0_wire_clk === 1'b1) && (input_reg_a0_wire_en == 1)) + mult_a_reg[int_width_a-1:0] <= mult_a_pre[int_width_a-1:0]; + end + + + // ----------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult_a[(2*int_width_a)-1:int_width_a]) + // Signal Registered : mult_a_pre[(2*int_width_a)-1:int_width_a] + // + // Register is controlled by posedge input_reg_a1_wire_clk + // Register has a clock enable input_reg_a1_wire_en + // Register has an asynchronous clear signal, input_reg_a1_wire_clr + // NOTE : The combinatorial block will be executed if + // input_register_a1 is unregistered and mult_a_pre[(2*int_width_a)-1:int_width_a] changes value + // ----------------------------------------------------------------------------------------------- + + assign mult_a_wire[(2*int_width_a)-1:int_width_a] = (input_register_a1 == "UNREGISTERED")? + mult_a_pre[(2*int_width_a)-1:int_width_a]: mult_a_reg[(2*int_width_a)-1:int_width_a]; + + always @(posedge input_reg_a1_wire_clk or posedge input_reg_a1_wire_clr) + + begin + if (input_reg_a1_wire_clr == 1) + mult_a_reg[(2*int_width_a)-1:int_width_a] <= 0; + else if ((input_reg_a1_wire_clk == 1) && (input_reg_a1_wire_en == 1)) + mult_a_reg[(2*int_width_a)-1:int_width_a] <= mult_a_pre[(2*int_width_a)-1:int_width_a]; + end + + + // ------------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult_a[(3*int_width_a)-1:2*int_width_a]) + // Signal Registered : mult_a_pre[(3*int_width_a)-1:2*int_width_a] + // + // Register is controlled by posedge input_reg_a2_wire_clk + // Register has a clock enable input_reg_a2_wire_en + // Register has an asynchronous clear signal, input_reg_a2_wire_clr + // NOTE : The combinatorial block will be executed if + // input_register_a2 is unregistered and mult_a_pre[(3*int_width_a)-1:2*int_width_a] changes value + // ------------------------------------------------------------------------------------------------- + assign mult_a_wire[(3*int_width_a)-1 : 2*int_width_a ] = (input_register_a2 == "UNREGISTERED")? + mult_a_pre[(3*int_width_a)-1 : 2*int_width_a]: mult_a_reg[(3*int_width_a)-1 : 2*int_width_a ]; + + + always @(posedge input_reg_a2_wire_clk or posedge input_reg_a2_wire_clr) + begin + if (input_reg_a2_wire_clr == 1) + mult_a_reg[(3*int_width_a)-1 : 2*int_width_a ] <= 0; + else if ((input_reg_a2_wire_clk == 1) && (input_reg_a2_wire_en == 1)) + mult_a_reg[(3*int_width_a)-1 : 2*int_width_a ] <= mult_a_pre[(3*int_width_a)-1 : 2*int_width_a]; + end + + + // ------------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult_a[(4*int_width_a)-1:3*int_width_a]) + // Signal Registered : mult_a_pre[(4*int_width_a)-1:3*int_width_a] + // + // Register is controlled by posedge input_reg_a3_wire_clk + // Register has a clock enable input_reg_a3_wire_en + // Register has an asynchronous clear signal, input_reg_a3_wire_clr + // NOTE : The combinatorial block will be executed if + // input_register_a3 is unregistered and mult_a_pre[(4*int_width_a)-1:3*int_width_a] changes value + // ------------------------------------------------------------------------------------------------- + assign mult_a_wire[(4*int_width_a)-1 : 3*int_width_a ] = (input_register_a3 == "UNREGISTERED")? + mult_a_pre[(4*int_width_a)-1:3*int_width_a]: mult_a_reg[(4*int_width_a)-1:3*int_width_a]; + + always @(posedge input_reg_a3_wire_clk or posedge input_reg_a3_wire_clr) + begin + if (input_reg_a3_wire_clr == 1) + mult_a_reg[(4*int_width_a)-1 : 3*int_width_a ] <= 0; + else if ((input_reg_a3_wire_clk == 1) && (input_reg_a3_wire_en == 1)) + mult_a_reg[(4*int_width_a)-1 : 3*int_width_a ] <= mult_a_pre[(4*int_width_a)-1:3*int_width_a]; + + end + + + // ------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult_b[int_width_b-1:0]) + // Signal Registered : mult_b_pre[int_width_b-1:0] + // + // Register is controlled by posedge input_reg_b0_wire_clk + // Register has a clock enable input_reg_b0_wire_en + // Register has an asynchronous clear signal, input_reg_b0_wire_clr + // NOTE : The combinatorial block will be executed if + // input_register_b0 is unregistered and mult_b_pre[int_width_b-1:0] changes value + // ------------------------------------------------------------------------------------- + + assign mult_b_wire[int_width_b-1:0] = (input_register_b0 == "UNREGISTERED")? + mult_b_pre[int_width_b-1:0]: mult_b_reg[int_width_b-1:0]; + + always @(posedge input_reg_b0_wire_clk or posedge input_reg_b0_wire_clr) + begin + if (input_reg_b0_wire_clr == 1) + mult_b_reg[int_width_b-1:0] <= 0; + else if ((input_reg_b0_wire_clk == 1) && (input_reg_b0_wire_en == 1)) + mult_b_reg[int_width_b-1:0] <= mult_b_pre[int_width_b-1:0]; + end + + + // ----------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult_b[(2*int_width_b)-1:int_width_b]) + // Signal Registered : mult_b_pre[(2*int_width_b)-1:int_width_b] + // + // Register is controlled by posedge input_reg_a1_wire_clk + // Register has a clock enable input_reg_b1_wire_en + // Register has an asynchronous clear signal, input_reg_b1_wire_clr + // NOTE : The combinatorial block will be executed if + // input_register_b1 is unregistered and mult_b_pre[(2*int_width_b)-1:int_width_b] changes value + // ----------------------------------------------------------------------------------------------- + assign mult_b_wire[(2*int_width_b)-1:int_width_b] = (input_register_b1 == "UNREGISTERED")? + mult_b_pre[(2*int_width_b)-1:int_width_b]: mult_b_reg[(2*int_width_b)-1:int_width_b]; + + + + always @(posedge input_reg_b1_wire_clk or posedge input_reg_b1_wire_clr) + begin + if (input_reg_b1_wire_clr == 1) + mult_b_reg[(2*int_width_b)-1:int_width_b] <= 0; + else if ((input_reg_b1_wire_clk == 1) && (input_reg_b1_wire_en == 1)) + mult_b_reg[(2*int_width_b)-1:int_width_b] <= mult_b_pre[(2*int_width_b)-1:int_width_b]; + + end + + + // ------------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult_b[(3*int_width_b)-1:2*int_width_b]) + // Signal Registered : mult_b_pre[(3*int_width_b)-1:2*int_width_b] + // + // Register is controlled by posedge input_reg_b2_wire_clk + // Register has a clock enable input_reg_b2_wire_en + // Register has an asynchronous clear signal, input_reg_b2_wire_clr + // NOTE : The combinatorial block will be executed if + // input_register_b2 is unregistered and mult_b_pre[(3*int_width_b)-1:2*int_width_b] changes value + // ------------------------------------------------------------------------------------------------- + assign mult_b_wire[(3*int_width_b)-1:2*int_width_b] = (input_register_b2 == "UNREGISTERED")? + mult_b_pre[(3*int_width_b)-1:2*int_width_b]: mult_b_reg[(3*int_width_b)-1:2*int_width_b]; + + + always @(posedge input_reg_b2_wire_clk or posedge input_reg_b2_wire_clr) + begin + if (input_reg_b2_wire_clr == 1) + mult_b_reg[(3*int_width_b)-1:2*int_width_b] <= 0; + else if ((input_reg_b2_wire_clk == 1) && (input_reg_b2_wire_en == 1)) + mult_b_reg[(3*int_width_b)-1:2*int_width_b] <= mult_b_pre[(3*int_width_b)-1:2*int_width_b]; + + end + + + // ------------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult_b[(4*int_width_b)-1:3*int_width_b]) + // Signal Registered : mult_b_pre[(4*int_width_b)-1:3*int_width_b] + // + // Register is controlled by posedge input_reg_b3_wire_clk + // Register has a clock enable input_reg_b3_wire_en + // Register has an asynchronous clear signal, input_reg_b3_wire_clr + // NOTE : The combinatorial block will be executed if + // input_register_b3 is unregistered and mult_b_pre[(4*int_width_b)-1:3*int_width_b] changes value + // ------------------------------------------------------------------------------------------------- + assign mult_b_wire[(4*int_width_b)-1:3*int_width_b] = (input_register_b3 == "UNREGISTERED")? + mult_b_pre[(4*int_width_b)-1:3*int_width_b]: mult_b_reg[(4*int_width_b)-1:3*int_width_b]; + + + always @(posedge input_reg_b3_wire_clk or posedge input_reg_b3_wire_clr) + begin + if (input_reg_b3_wire_clr == 1) + mult_b_reg[(4*int_width_b)-1 : 3*int_width_b ] <= 0; + else if ((input_reg_b3_wire_clk == 1) && (input_reg_b3_wire_en == 1)) + mult_b_reg[(4*int_width_b)-1:3*int_width_b] <= mult_b_pre[(4*int_width_b)-1:3*int_width_b]; + + end + + // ------------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult01_round_wire) + // Signal Registered : mult01_round_pre + // + // Register is controlled by posedge mult01_round_wire_clk + // Register has a clock enable mult01_round_wire_en + // Register has an asynchronous clear signal, mult01_round_wire_clr + // NOTE : The combinatorial block will be executed if + // mult01_round_register is unregistered and mult01_round changes value + // ------------------------------------------------------------------------------------------------- + assign mult01_round_wire = (mult01_round_register == "UNREGISTERED")? + mult01_round_pre : mult01_round_reg; + + always @(posedge mult01_round_wire_clk or posedge mult01_round_wire_clr) + begin + if (mult01_round_wire_clr == 1) + mult01_round_reg <= 0; + else if ((mult01_round_wire_clk == 1) && (mult01_round_wire_en == 1)) + mult01_round_reg <= mult01_round_pre; + + end + + // ------------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult01_saturate_wire) + // Signal Registered : mult01_saturation_pre + // + // Register is controlled by posedge mult01_saturate_wire_clk + // Register has a clock enable mult01_saturate_wire_en + // Register has an asynchronous clear signal, mult01_saturate_wire_clr + // NOTE : The combinatorial block will be executed if + // mult01_saturation_register is unregistered and mult01_saturate_pre changes value + // ------------------------------------------------------------------------------------------------- + assign mult01_saturate_wire = (mult01_saturation_register == "UNREGISTERED")? + mult01_saturate_pre : mult01_saturate_reg; + + always @(posedge mult01_saturate_wire_clk or posedge mult01_saturate_wire_clr) + begin + if (mult01_saturate_wire_clr == 1) + mult01_saturate_reg <= 0; + else if ((mult01_saturate_wire_clk == 1) && (mult01_saturate_wire_en == 1)) + mult01_saturate_reg <= mult01_saturate_pre; + + end + + // ------------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult23_round_wire) + // Signal Registered : mult23_round_pre + // + // Register is controlled by posedge mult23_round_wire_clk + // Register has a clock enable mult23_round_wire_en + // Register has an asynchronous clear signal, mult23_round_wire_clr + // NOTE : The combinatorial block will be executed if + // mult23_round_register is unregistered and mult23_round_pre changes value + // ------------------------------------------------------------------------------------------------- + assign mult23_round_wire = (mult23_round_register == "UNREGISTERED")? + mult23_round_pre : mult23_round_reg; + + always @(posedge mult23_round_wire_clk or posedge mult23_round_wire_clr) + begin + if (mult23_round_wire_clr == 1) + mult23_round_reg <= 0; + else if ((mult23_round_wire_clk == 1) && (mult23_round_wire_en == 1)) + mult23_round_reg <= mult23_round_pre; + + end + + // ------------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set mult23_saturate_wire) + // Signal Registered : mult23_round_pre + // + // Register is controlled by posedge mult23_saturate_wire_clk + // Register has a clock enable mult23_saturate_wire_en + // Register has an asynchronous clear signal, mult23_saturate_wire_clr + // NOTE : The combinatorial block will be executed if + // mult23_saturation_register is unregistered and mult23_saturation_pre changes value + // ------------------------------------------------------------------------------------------------- + assign mult23_saturate_wire = (mult23_saturation_register == "UNREGISTERED")? + mult23_saturate_pre : mult23_saturate_reg; + + always @(posedge mult23_saturate_wire_clk or posedge mult23_saturate_wire_clr) + begin + if (mult23_saturate_wire_clr == 1) + mult23_saturate_reg <= 0; + else if ((mult23_saturate_wire_clk == 1) && (mult23_saturate_wire_en == 1)) + mult23_saturate_reg <= mult23_saturate_pre; + + end + + // --------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set addnsub1_round_wire) + // Signal Registered : addnsub1_round_pre + // + // Register is controlled by posedge addnsub1_round_wire_clk + // Register has a clock enable addnsub1_round_wire_en + // Register has an asynchronous clear signal, addnsub1_round_wire_clr + // NOTE : The combinatorial block will be executed if + // addnsub1_round_register is unregistered and addnsub1_round_pre changes value + // --------------------------------------------------------------------------------- + assign addnsub1_round_wire = (addnsub1_round_register=="UNREGISTERED")? + addnsub1_round_pre : addnsub1_round_reg; + + always @(posedge addnsub1_round_wire_clk or posedge addnsub1_round_wire_clr) + begin + if (addnsub1_round_wire_clr == 1) + addnsub1_round_reg <= 0; + else if ((addnsub1_round_wire_clk == 1) && (addnsub1_round_wire_en == 1)) + addnsub1_round_reg <= addnsub1_round_pre; + end + + // --------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set addnsub1_round_pipe_wire) + // Signal Registered : addnsub1_round_wire + // + // Register is controlled by posedge addnsub1_round_pipe_wire_clk + // Register has a clock enable addnsub1_round_pipe_wire_en + // Register has an asynchronous clear signal, addnsub1_round_wire_clr + // NOTE : The combinatorial block will be executed if + // addnsub1_round_pipeline_register is unregistered and addnsub1_round_wire changes value + // --------------------------------------------------------------------------------- + assign addnsub1_round_pipe_wire = (addnsub1_round_pipeline_register=="UNREGISTERED")? + addnsub1_round_wire : addnsub1_round_pipe_reg; + + always @(posedge addnsub1_round_pipe_wire_clk or posedge addnsub1_round_pipe_wire_clr) + begin + if (addnsub1_round_pipe_wire_clr == 1) + addnsub1_round_pipe_reg <= 0; + else if ((addnsub1_round_pipe_wire_clk == 1) && (addnsub1_round_pipe_wire_en == 1)) + addnsub1_round_pipe_reg <= addnsub1_round_wire; + end + + // --------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set addnsub3_round_wire) + // Signal Registered : addnsub3_round_pre + // + // Register is controlled by posedge addnsub3_round_wire_clk + // Register has a clock enable addnsub3_round_wire_en + // Register has an asynchronous clear signal, addnsub3_round_wire_clr + // NOTE : The combinatorial block will be executed if + // addnsub3_round_register is unregistered and addnsub3_round_pre changes value + // --------------------------------------------------------------------------------- + assign addnsub3_round_wire = (addnsub3_round_register=="UNREGISTERED")? + addnsub3_round_pre : addnsub3_round_reg; + + always @(posedge addnsub3_round_wire_clk or posedge addnsub3_round_wire_clr) + begin + if (addnsub3_round_wire_clr == 1) + addnsub3_round_reg <= 0; + else if ((addnsub3_round_wire_clk == 1) && (addnsub3_round_wire_en == 1)) + addnsub3_round_reg <= addnsub3_round_pre; + end + + // --------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set addnsub3_round_pipe_wire) + // Signal Registered : addnsub3_round_wire + // + // Register is controlled by posedge addnsub3_round_pipe_wire_clk + // Register has a clock enable addnsub3_round_pipe_wire_en + // Register has an asynchronous clear signal, addnsub3_round_wire_clr + // NOTE : The combinatorial block will be executed if + // addnsub3_round_pipeline_register is unregistered and addnsub3_round_wire changes value + // --------------------------------------------------------------------------------- + assign addnsub3_round_pipe_wire = (addnsub3_round_pipeline_register=="UNREGISTERED")? + addnsub3_round_wire : addnsub3_round_pipe_reg; + + always @(posedge addnsub3_round_pipe_wire_clk or posedge addnsub3_round_pipe_wire_clr) + begin + if (addnsub3_round_pipe_wire_clr == 1) + addnsub3_round_pipe_reg <= 0; + else if ((addnsub3_round_pipe_wire_clk == 1) && (addnsub3_round_pipe_wire_en == 1)) + addnsub3_round_pipe_reg <= addnsub3_round_wire; + end + + + // --------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set addsub1_reg) + // Signal Registered : addsub1_int + // + // Register is controlled by posedge addsub1_reg_wire_clk + // Register has a clock enable addsub1_reg_wire_en + // Register has an asynchronous clear signal, addsub1_reg_wire_clr + // NOTE : The combinatorial block will be executed if + // addnsub_multiplier_register1 is unregistered and addsub1_int changes value + // --------------------------------------------------------------------------------- + assign addsub1_wire = (addnsub_multiplier_register1=="UNREGISTERED")? addsub1_int : addsub1_reg; + + always @(posedge addsub1_reg_wire_clk or posedge addsub1_reg_wire_clr) + begin + if ((addsub1_reg_wire_clr == 1) && (multiplier1_direction == "UNUSED")) + addsub1_reg <= 0; + else if ((addsub1_reg_wire_clk == 1) && (addsub1_reg_wire_en == 1)) + addsub1_reg <= addsub1_int; + end + + + // ------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set addsub1_pipe) + // Signal Registered : addsub1_reg + // + // Register is controlled by posedge addsub1_pipe_wire_clk + // Register has a clock enable addsub1_pipe_wire_en + // Register has an asynchronous clear signal, addsub1_pipe_wire_clr + // NOTE : The combinatorial block will be executed if + // addnsub_multiplier_pipeline_register1 is unregistered and addsub1_reg changes value + // ------------------------------------------------------------------------------------------ + + assign addsub1_pipe_wire = (addnsub_multiplier_pipeline_register1 == "UNREGISTERED")? + addsub1_wire : addsub1_pipe_reg; + always @(posedge addsub1_pipe_wire_clk or posedge addsub1_pipe_wire_clr) + begin + if ((addsub1_pipe_wire_clr == 1) && (multiplier1_direction == "UNUSED")) + addsub1_pipe_reg <= 0; + else if ((addsub1_pipe_wire_clk == 1) && (addsub1_pipe_wire_en == 1)) + addsub1_pipe_reg <= addsub1_wire; + end + + + // --------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set addsub3_reg) + // Signal Registered : addsub3_int + // + // Register is controlled by posedge addsub3_reg_wire_clk + // Register has a clock enable addsub3_reg_wire_en + // Register has an asynchronous clear signal, addsub3_reg_wire_clr + // NOTE : The combinatorial block will be executed if + // addnsub_multiplier_register3 is unregistered and addsub3_int changes value + // --------------------------------------------------------------------------------- + assign addsub3_wire = (addnsub_multiplier_register3=="UNREGISTERED")? + addsub3_int : addsub3_reg; + + + always @(posedge addsub3_reg_wire_clk or posedge addsub3_reg_wire_clr) + begin + if ((addsub3_reg_wire_clr == 1) && (multiplier3_direction == "UNUSED")) + addsub3_reg <= 0; + else if ((addsub3_reg_wire_clk == 1) && (addsub3_reg_wire_en == 1)) + addsub3_reg <= addsub3_int; + end + + + // ------------------------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set addsub3_pipe) + // Signal Registered : addsub3_reg + // + // Register is controlled by posedge addsub3_pipe_wire_clk + // Register has a clock enable addsub3_pipe_wire_en + // Register has an asynchronous clear signal, addsub3_pipe_wire_clr + // NOTE : The combinatorial block will be executed if + // addnsub_multiplier_pipeline_register3 is unregistered and addsub3_reg changes value + // ------------------------------------------------------------------------------------------ + assign addsub3_pipe_wire = (addnsub_multiplier_pipeline_register3 == "UNREGISTERED")? + addsub3_wire : addsub3_pipe_reg; + + always @(posedge addsub3_pipe_wire_clk or posedge addsub3_pipe_wire_clr) + begin + if ((addsub3_pipe_wire_clr == 1) && (multiplier3_direction == "UNUSED")) + addsub3_pipe_reg <= 0; + else if ((addsub3_pipe_wire_clk == 1) && (addsub3_pipe_wire_en == 1)) + addsub3_pipe_reg <= addsub3_wire; + end + + + // ---------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set sign_a_reg) + // Signal Registered : sign_a_int + // + // Register is controlled by posedge sign_reg_a_wire_clk + // Register has a clock enable sign_reg_a_wire_en + // Register has an asynchronous clear signal, sign_reg_a_wire_clr + // NOTE : The combinatorial block will be executed if + // signed_register_a is unregistered and sign_a_int changes value + // ---------------------------------------------------------------------------- + + assign sign_a_wire = (signed_register_a == "UNREGISTERED")? sign_a_int : sign_a_reg; + always @(posedge sign_reg_a_wire_clk or posedge sign_reg_a_wire_clr) + begin + if ((sign_reg_a_wire_clr == 1) && (representation_a == "UNUSED")) + sign_a_reg <= 0; + else if ((sign_reg_a_wire_clk == 1) && (sign_reg_a_wire_en == 1)) + sign_a_reg <= sign_a_int; + end + + + // ------------------------------------------------------------------------------ + // This block contains 1 register and 1 combinatorial block (to set sign_a_pipe) + // Signal Registered : sign_a_reg + // + // Register is controlled by posedge sign_pipe_a_wire_clk + // Register has a clock enable sign_pipe_a_wire_en + // Register has an asynchronous clear signal, sign_pipe_a_wire_clr + // NOTE : The combinatorial block will be executed if + // signed_pipeline_register_a is unregistered and sign_a_reg changes value + // ------------------------------------------------------------------------------ + + assign sign_a_pipe_wire = (signed_pipeline_register_a == "UNREGISTERED")? sign_a_wire : sign_a_pipe_reg; + always @(posedge sign_pipe_a_wire_clk or posedge sign_pipe_a_wire_clr) + begin + if ((sign_pipe_a_wire_clr == 1) && (representation_a == "UNUSED")) + sign_a_pipe_reg <= 0; + else if ((sign_pipe_a_wire_clk == 1) && (sign_pipe_a_wire_en == 1)) + sign_a_pipe_reg <= sign_a_wire; + end + + + // ---------------------------------------------------------------------------- + // This block contains 1 register and 1 combinatorial block (to set sign_b_reg) + // Signal Registered : sign_b_int + // + // Register is controlled by posedge sign_reg_b_wire_clk + // Register has a clock enable sign_reg_b_wire_en + // Register has an asynchronous clear signal, sign_reg_b_wire_clr + // NOTE : The combinatorial block will be executed if + // signed_register_b is unregistered and sign_b_int changes value + // ---------------------------------------------------------------------------- + + assign sign_b_wire = (signed_register_b == "UNREGISTERED")? sign_b_int : sign_b_reg; + + always @(posedge sign_reg_b_wire_clk or posedge sign_reg_b_wire_clr) + begin + if ((sign_reg_b_wire_clr == 1) && (representation_b == "UNUSED")) + sign_b_reg <= 0; + else if ((sign_reg_b_wire_clk == 1) && (sign_reg_b_wire_en == 1)) + sign_b_reg <= sign_b_int; + + end + + + // ------------------------------------------------------------------------------ + // This block contains 1 register and 1 combinatorial block (to set sign_b_pipe) + // Signal Registered : sign_b_reg + // + // Register is controlled by posedge sign_pipe_b_wire_clk + // Register has a clock enable sign_pipe_b_wire_en + // Register has an asynchronous clear signal, sign_pipe_b_wire_clr + // NOTE : The combinatorial block will be executed if + // signed_pipeline_register_b is unregistered and sign_b_reg changes value + // ------------------------------------------------------------------------------ + assign sign_b_pipe_wire = (signed_pipeline_register_b == "UNREGISTERED")? sign_b_wire : sign_b_pipe_reg; + always @(posedge sign_pipe_b_wire_clk or posedge sign_pipe_b_wire_clr) + + begin + if ((sign_pipe_b_wire_clr == 1) && (representation_b == "UNUSED")) + sign_b_pipe_reg <= 0; + else if ((sign_pipe_b_wire_clk == 1) && (sign_pipe_b_wire_en == 1)) + sign_b_pipe_reg <= sign_b_wire; + + end + + + // -------------------------------------------------------- + // This block basically calls the task do_multiply() to set + // the value of mult_res_0[(int_width_a + int_width_b) -1 :0] + // + // If multiplier_register0 is registered, the call of the task + // will be triggered by a posedge multiplier_reg0_wire_clk. + // It also has an asynchronous clear signal multiplier_reg0_wire_clr + // + // If multiplier_register0 is unregistered, a change of value + // in either mult_a[int_width_a-1:0], mult_b[int_width_a-1:0], + // sign_a_reg or sign_b_reg will trigger the task call. + // -------------------------------------------------------- + assign mult_res_wire[(int_width_a + int_width_b - 1) :0] = (multiplier_register0 == "UNREGISTERED")? + mult0_result[(int_width_a + int_width_b - 1) :0] : + mult_res_reg[(int_width_a + int_width_b - 1) :0]; + + assign mult_saturate_overflow_vec[0] = (multiplier_register0 == "UNREGISTERED")? + mult0_saturate_overflow : mult_saturate_overflow_reg[0]; + + + // This always block is to perform the rounding and saturation operations (StratixII only) + always @(mult_res_0 or mult01_round_wire or mult01_saturate_wire) + begin + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) + begin + // ------------------------------------------------------- + // Stratix II Rounding support + // This block basically carries out the rounding for the + // mult_res_0. The equation to get the mult0_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 ((multiplier01_rounding == "YES") || + ((multiplier01_rounding == "VARIABLE") && (mult01_round_wire == 1))) + begin + mult0_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_0[(int_width_a + int_width_b) -1 :0] + ( 1 << (`MULT_ROUND_BITS - 1)); + end + else + begin + mult0_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_0[(int_width_a + int_width_b) -1 :0]; + end + + mult0_round_out[((int_width_a + int_width_b) + 2) : (int_width_a + int_width_b)] = {2{1'b0}}; + + // ------------------------------------------------------- + // Stratix II Saturation support + // This carries out the saturation for mult0_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 ((multiplier01_saturation == "YES") || + (( multiplier01_saturation == "VARIABLE") && (mult01_saturate_wire == 1))) + begin + + mult0_saturate_overflow_stat = (~mult0_round_out[int_width_a + int_width_b - 1]) && mult0_round_out[int_width_a + int_width_b - 2]; + + if (mult0_saturate_overflow_stat == 0) + begin + mult0_saturate_out = mult0_round_out; + mult0_saturate_overflow = mult0_round_out[0]; + end + else + begin + + // We are doing Q2.31 saturation + for (num_bit_mult0 = (int_width_a + int_width_b - 1); num_bit_mult0 >= (int_width_a + int_width_b - 2); num_bit_mult0 = num_bit_mult0 - 1) + begin + mult0_saturate_out[num_bit_mult0] = mult0_round_out[int_width_a + int_width_b - 1]; + end + + for (num_bit_mult0 = sat_ini_value; num_bit_mult0 >= 3; num_bit_mult0 = num_bit_mult0 - 1) + begin + mult0_saturate_out[num_bit_mult0] = ~mult0_round_out[int_width_a + int_width_b - 1]; + end + + mult0_saturate_out[2 : 0] = mult0_round_out[2:0]; + + mult0_saturate_overflow = mult0_saturate_overflow_stat; + end + end + else + begin + mult0_saturate_out = mult0_round_out; + mult0_saturate_overflow = 1'b0; + end + + if ((multiplier01_rounding == "YES") || + ((multiplier01_rounding == "VARIABLE") && (mult01_round_wire == 1))) + begin + + for (num_bit_mult0 = (`MULT_ROUND_BITS - 1); num_bit_mult0 >= 0; num_bit_mult0 = num_bit_mult0 - 1) + begin + mult0_saturate_out[num_bit_mult0] = 1'b0; + end + + end + end + end + + always @(mult0_saturate_out or mult_res_0) + begin + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) + begin + mult0_result <= mult0_saturate_out[(int_width_a + int_width_b) -1 :0]; + end + else + begin + mult0_result <= mult_res_0; + end + + end + + + + always @(posedge multiplier_reg0_wire_clk or posedge multiplier_reg0_wire_clr) + begin + if (multiplier_reg0_wire_clr == 1) + begin + mult_res_reg[(int_width_a + int_width_b) -1 :0] <= 0; + mult_saturate_overflow_reg[0] <= 0; + end + else if ((multiplier_reg0_wire_clk == 1) && (multiplier_reg0_wire_en == 1)) + begin + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) + mult_res_reg[(int_width_a + int_width_b) - 1 : 0] <= mult_res_0[(int_width_a + int_width_b) -1 :0]; + else + begin + mult_res_reg[(int_width_a + int_width_b - 1) : 0] <= mult0_result; + mult_saturate_overflow_reg[0] <= mult0_saturate_overflow; + end + end + end + + + + always @(mult_a_wire[(int_width_a *1) -1 : (int_width_a*0)] or mult_b_wire[(int_width_b *1) -1 : (int_width_b *0)] or + sign_a_wire or sign_b_wire) + begin + mult_res_0 = do_multiply (0, sign_a_wire, sign_b_wire); + end + + + + + // ------------------------------------------------------------------------ + // This block basically calls the task do_multiply() to set the value of + // mult_res_1[(int_width_a + int_width_b) -1 :0] + // + // If multiplier_register1 is registered, the call of the task + // will be triggered by a posedge multiplier_reg1_wire_clk. + // It also has an asynchronous clear signal multiplier_reg1_wire_clr + // + // If multiplier_register1 is unregistered, a change of value + // in either mult_a[(2*int_width_a)-1:int_width_a], mult_b[(2*int_width_a)-1:int_width_a], + // sign_a_reg or sign_b_reg will trigger the task call. + // ----------------------------------------------------------------------- + + assign mult_res_wire[(((int_width_a + int_width_b) *2) - 1) : (int_width_a + int_width_b)] = (multiplier_register1 == "UNREGISTERED")? + mult1_result[(int_width_a + int_width_b - 1) : 0]: + mult_res_reg[((int_width_a + int_width_b) *2) - 1: (int_width_a + int_width_b)]; + + assign mult_saturate_overflow_vec[1] = (multiplier_register1 == "UNREGISTERED")? + mult1_saturate_overflow : mult_saturate_overflow_reg[1]; + + + // This always block is to perform the rounding and saturation operations (StratixII only) + always @(mult_res_1 or mult01_round_wire or mult01_saturate_wire) + begin + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) + begin + // ------------------------------------------------------- + // Stratix II Rounding support + // This block basically carries out the rounding for the + // mult_res_1. The equation to get the mult1_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 ((multiplier01_rounding == "YES") || + ((multiplier01_rounding == "VARIABLE") && (mult01_round_wire == 1))) + begin + mult1_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_1[(int_width_a + int_width_b) -1 :0] + ( 1 << (`MULT_ROUND_BITS - 1)); + end + else + begin + mult1_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_1[(int_width_a + int_width_b) -1 :0]; + end + + mult1_round_out[((int_width_a + int_width_b) + 2) : (int_width_a + int_width_b)] = {2{1'b0}}; + + + // ------------------------------------------------------- + // Stratix II Saturation support + // This carries out the saturation for mult1_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 ((multiplier01_saturation == "YES") || + (( multiplier01_saturation == "VARIABLE") && (mult01_saturate_wire == 1))) + begin + mult1_saturate_overflow_stat = (~mult1_round_out[int_width_a + int_width_b - 1]) && mult1_round_out[int_width_a + int_width_b - 2]; + + if (mult1_saturate_overflow_stat == 0) + begin + mult1_saturate_out = mult1_round_out; + mult1_saturate_overflow = mult1_round_out[0]; + end + else + begin + // We are doing Q2.31 saturation. Thus we would insert additional bit + // for the LSB + for (num_bit_mult1 = (int_width_a + int_width_b - 1); num_bit_mult1 >= (int_width_a + int_width_b - 2); num_bit_mult1 = num_bit_mult1 - 1) + begin + mult1_saturate_out[num_bit_mult1] = mult1_round_out[int_width_a + int_width_b - 1]; + end + + for (num_bit_mult1 = sat_ini_value; num_bit_mult1 >= 3; num_bit_mult1 = num_bit_mult1 - 1) + begin + mult1_saturate_out[num_bit_mult1] = ~mult1_round_out[int_width_a + int_width_b - 1]; + end + + mult1_saturate_out[2:0] = mult1_round_out[2:0]; + mult1_saturate_overflow = mult1_saturate_overflow_stat; + end + end + else + begin + mult1_saturate_out = mult1_round_out; + mult1_saturate_overflow = 1'b0; + end + + if ((multiplier01_rounding == "YES") || + ((multiplier01_rounding == "VARIABLE") && (mult01_round_wire == 1))) + begin + + for (num_bit_mult1 = (`MULT_ROUND_BITS - 1); num_bit_mult1 >= 0; num_bit_mult1 = num_bit_mult1 - 1) + begin + mult1_saturate_out[num_bit_mult1] = 1'b0; + end + + end + end + end + + always @(mult1_saturate_out or mult_res_1) + begin + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) + begin + mult1_result <= mult1_saturate_out[(int_width_a + int_width_b) -1 :0]; + end + else + begin + mult1_result <= mult_res_1; + end + end + + + always @(posedge multiplier_reg1_wire_clk or posedge multiplier_reg1_wire_clr) + begin + if (multiplier_reg1_wire_clr == 1) + begin + mult_res_reg[((int_width_a + int_width_b) *2) -1 : (int_width_a + int_width_b)] <= 0; + mult_saturate_overflow_reg[1] <= 0; + end + else if ((multiplier_reg1_wire_clk == 1) && (multiplier_reg1_wire_en == 1)) + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) + mult_res_reg[((int_width_a + int_width_b) *2) -1 : (int_width_a + int_width_b)] <= + mult_res_1[(int_width_a + int_width_b) -1 :0]; + else + begin + mult_res_reg[((int_width_a + int_width_b) *2) -1 : (int_width_a + int_width_b)] <= mult1_result; + mult_saturate_overflow_reg[1] <= mult1_saturate_overflow; + end + end + + + always @(mult_a_wire[(int_width_a *2) -1 : (int_width_a*1)] or mult_b_wire[(int_width_b *2) -1 : (int_width_b *1)] or + sign_a_wire or sign_b_wire) + begin + + mult_res_1 = do_multiply (1, sign_a_wire, sign_b_wire); + end + + + + + + // ---------------------------------------------------------------------------- + // This block basically calls the task do_multiply() to set the value of + // mult_res_2[(int_width_a + int_width_b) -1 :0] + // + // If multiplier_register2 is registered, the call of the task + // will be triggered by a posedge multiplier_reg2_wire_clk. + // It also has an asynchronous clear signal multiplier_reg2_wire_clr + // + // If multiplier_register2 is unregistered, a change of value + // in either mult_a[(3*int_width_a)-1:2*int_width_a], mult_b[(3*int_width_a)-1:2*int_width_a], + // sign_a_reg or sign_b_reg will trigger the task call. + // --------------------------------------------------------------------------- + + assign mult_res_wire[((int_width_a + int_width_b) *3) -1 : (2*(int_width_a + int_width_b))] = (multiplier_register2 == "UNREGISTERED")? + mult2_result[(int_width_a + int_width_b) -1 :0] : + mult_res_reg[((int_width_a + int_width_b) *3) -1 : (2*(int_width_a + int_width_b))]; + + assign mult_saturate_overflow_vec[2] = (multiplier_register2 == "UNREGISTERED")? + mult2_saturate_overflow : mult_saturate_overflow_reg[2]; + + // This always block is to perform the rounding and saturation operations (StratixII only) + always @(mult_res_2 or mult23_round_wire or mult23_saturate_wire) + begin + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) + begin + // ------------------------------------------------------- + // Stratix II Rounding support + // This block basically carries out the rounding for the + // mult_res_2. The equation to get the mult2_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 ((multiplier23_rounding == "YES") || + ((multiplier23_rounding == "VARIABLE") && (mult23_round_wire == 1))) + begin + mult2_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_2[(int_width_a + int_width_b) -1 :0] + ( 1 << (`MULT_ROUND_BITS - 1)); + end + else + begin + mult2_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_2[(int_width_a + int_width_b) -1 :0]; + end + + mult2_round_out[((int_width_a + int_width_b) + 2) : (int_width_a + int_width_b)] = {2{1'b0}}; + + // ------------------------------------------------------- + // Stratix II Saturation support + // This carries out the saturation for mult2_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 ((multiplier23_saturation == "YES") || + (( multiplier23_saturation == "VARIABLE") && (mult23_saturate_wire == 1))) + begin + mult2_saturate_overflow_stat = (~mult2_round_out[int_width_a + int_width_b - 1]) && mult2_round_out[int_width_a + int_width_b - 2]; + + if (mult2_saturate_overflow_stat == 0) + begin + mult2_saturate_out = mult2_round_out; + mult2_saturate_overflow = mult2_round_out[0]; + end + else + begin + // We are doing Q2.31 saturation. Thus we would insert additional bit + // for the LSB + for (num_bit_mult2 = (int_width_a + int_width_b - 1); num_bit_mult2 >= (int_width_a + int_width_b - 2); num_bit_mult2 = num_bit_mult2 - 1) + begin + mult2_saturate_out[num_bit_mult2] = mult2_round_out[int_width_a + int_width_b - 1]; + end + + for (num_bit_mult2 = sat_ini_value; num_bit_mult2 >= 3; num_bit_mult2 = num_bit_mult2 - 1) + begin + mult2_saturate_out[num_bit_mult2] = ~mult2_round_out[int_width_a + int_width_b - 1]; + end + + mult2_saturate_out[2:0] = mult2_round_out[2:0]; + mult2_saturate_overflow = mult2_saturate_overflow_stat; + end + end + else + begin + mult2_saturate_out = mult2_round_out; + mult2_saturate_overflow = 1'b0; + end + + if ((multiplier23_rounding == "YES") || + ((multiplier23_rounding == "VARIABLE") && (mult23_round_wire == 1))) + begin + + for (num_bit_mult2 = (`MULT_ROUND_BITS - 1); num_bit_mult2 >= 0; num_bit_mult2 = num_bit_mult2 - 1) + begin + mult2_saturate_out[num_bit_mult2] = 1'b0; + end + + end + end + end + + always @(mult2_saturate_out or mult_res_2) + begin + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) + begin + mult2_result <= mult2_saturate_out[(int_width_a + int_width_b) -1 :0]; + end + else + begin + mult2_result <= mult_res_2; + end + end + + + always @(posedge multiplier_reg2_wire_clk or posedge multiplier_reg2_wire_clr) + begin + if (multiplier_reg2_wire_clr == 1) + begin + mult_res_reg[((int_width_a + int_width_b) *3) -1 : (2*(int_width_a + int_width_b))] <= 0; + mult_saturate_overflow_reg[2] <= 0; + end + else if ((multiplier_reg2_wire_clk == 1) && (multiplier_reg2_wire_en == 1)) + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) + mult_res_reg[((int_width_a + int_width_b) *3) -1 : (2*(int_width_a + int_width_b))] <= + mult_res_2[(int_width_a + int_width_b) -1 :0]; + else + begin + mult_res_reg[((int_width_a + int_width_b) *3) -1 : (2*(int_width_a + int_width_b))] <= mult2_result; + mult_saturate_overflow_reg[2] <= mult2_saturate_overflow; + end + end + + always @(mult_a_wire[(int_width_a *3) -1 : (int_width_a*2)] or mult_b_wire[(int_width_b *3) -1 : (int_width_b *2)] or + sign_a_wire or sign_b_wire) + begin + mult_res_2 = do_multiply (2, sign_a_wire, sign_b_wire); + end + + + + + // ---------------------------------------------------------------------------- + // This block basically calls the task do_multiply() to set the value of + // mult_res_3[(int_width_a + int_width_b) -1 :0] + // + // If multiplier_register3 is registered, the call of the task + // will be triggered by a posedge multiplier_reg3_wire_clk. + // It also has an asynchronous clear signal multiplier_reg3_wire_clr + // + // If multiplier_register3 is unregistered, a change of value + // in either mult_a[(4*int_width_a)-1:3*int_width_a], mult_b[(4*int_width_a)-1:3*int_width_a], + // sign_a_reg or sign_b_reg will trigger the task call. + // --------------------------------------------------------------------------- + + assign mult_res_wire[((int_width_a + int_width_b) *4) -1 : 3*(int_width_a + int_width_b)] = (multiplier_register3 == "UNREGISTERED")? + mult3_result[(int_width_a + int_width_b) -1 :0] : + mult_res_reg[((int_width_a + int_width_b) *4) -1 : 3*(int_width_a + int_width_b)]; + + assign mult_saturate_overflow_vec[3] = (multiplier_register3 == "UNREGISTERED")? + mult3_saturate_overflow : mult_saturate_overflow_reg[3]; + + // This always block is to perform the rounding and saturation operations (StratixII only) + always @(mult_res_3 or mult23_round_wire or mult23_saturate_wire) + begin + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) + begin + // ------------------------------------------------------- + // Stratix II Rounding support + // This block basically carries out the rounding for the + // mult_res_3. The equation to get the mult3_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 ((multiplier23_rounding == "YES") || + ((multiplier23_rounding == "VARIABLE") && (mult23_round_wire == 1))) + begin + mult3_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_3[(int_width_a + int_width_b) -1 :0] + ( 1 << (`MULT_ROUND_BITS - 1)); + end + else + begin + mult3_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_3[(int_width_a + int_width_b) -1 :0]; + end + + mult3_round_out[((int_width_a + int_width_b) + 2) : (int_width_a + int_width_b)] = {2{1'b0}}; + + // ------------------------------------------------------- + // Stratix II Saturation support + // This carries out the saturation for mult3_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 ((multiplier23_saturation == "YES") || + (( multiplier23_saturation == "VARIABLE") && (mult23_saturate_wire == 1))) + begin + mult3_saturate_overflow_stat = (~mult3_round_out[int_width_a + int_width_b - 1]) && mult3_round_out[int_width_a + int_width_b - 2]; + + if (mult3_saturate_overflow_stat == 0) + begin + mult3_saturate_out = mult3_round_out; + mult3_saturate_overflow = mult3_round_out[0]; + end + else + begin + // We are doing Q2.31 saturation. Thus we would make sure the 3 LSB bits isn't reset + for (num_bit_mult3 = (int_width_a + int_width_b -1); num_bit_mult3 >= (int_width_a + int_width_b - 2); num_bit_mult3 = num_bit_mult3 - 1) + begin + mult3_saturate_out[num_bit_mult3] = mult3_round_out[int_width_a + int_width_b - 1]; + end + + for (num_bit_mult3 = sat_ini_value; num_bit_mult3 >= 3; num_bit_mult3 = num_bit_mult3 - 1) + begin + mult3_saturate_out[num_bit_mult3] = ~mult3_round_out[int_width_a + int_width_b - 1]; + end + + mult3_saturate_out[2:0] = mult3_round_out[2:0]; + mult3_saturate_overflow = mult3_saturate_overflow_stat; + end + end + else + begin + mult3_saturate_out = mult3_round_out; + mult3_saturate_overflow = 1'b0; + end + + if ((multiplier23_rounding == "YES") || + ((multiplier23_rounding == "VARIABLE") && (mult23_round_wire == 1))) + begin + + for (num_bit_mult3 = (`MULT_ROUND_BITS - 1); num_bit_mult3 >= 0; num_bit_mult3 = num_bit_mult3 - 1) + begin + mult3_saturate_out[num_bit_mult3] = 1'b0; + end + + end + end + end + + always @(mult3_saturate_out or mult_res_3) + begin + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) + begin + mult3_result <= mult3_saturate_out[(int_width_a + int_width_b) -1 :0]; + end + else + begin + mult3_result <= mult_res_3; + end + end + + + always @(posedge multiplier_reg3_wire_clk or posedge multiplier_reg3_wire_clr) + begin + if (multiplier_reg3_wire_clr == 1) + begin + mult_res_reg[((int_width_a + int_width_b) *4) -1 : (3*(int_width_a + int_width_b))] <= 0; + mult_saturate_overflow_reg[3] <= 0; + end + else if ((multiplier_reg3_wire_clk == 1) && (multiplier_reg3_wire_en == 1)) + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) + mult_res_reg[((int_width_a + int_width_b) *4) -1 : (3*(int_width_a + int_width_b))] <= + mult_res_3[(int_width_a + int_width_b) -1 :0]; + else + begin + mult_res_reg[((int_width_a + int_width_b) *4) -1: 3*(int_width_a + int_width_b)] <= mult3_result; + mult_saturate_overflow_reg[3] <= mult3_saturate_overflow; + end + + end + + + + + always @(mult_a_wire[(int_width_a *4) -1 : (int_width_a*3)] or mult_b_wire[(int_width_b *4) -1 : (int_width_b *3)] or + sign_a_wire or sign_b_wire) + begin + mult_res_3 = do_multiply (3, sign_a_wire, sign_b_wire); + end + + + //------------------------------ + // Continuous assign statements + //------------------------------ + + // Clock in all the A input registers + assign i_scanina = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0)? + dataa_int[int_width_a-1:0] : scanina_z; + + assign mult_a_pre[int_width_a-1:0] = (input_source_a0 == "DATAA")? dataa_int[int_width_a-1:0] : + (input_source_a0 == "SCANA")? i_scanina : + (sourcea_wire[0] == 1)? scanina_z : dataa_int[int_width_a-1:0]; + + assign mult_a_pre[(2*int_width_a)-1:int_width_a] = (input_source_a1 == "DATAA") ? dataa_int[(2*int_width_a)-1:int_width_a] : + (input_source_a1 == "SCANA")? mult_a_wire[int_width_a-1:0] : + (sourcea_wire[1] == 1)? mult_a_wire[int_width_a-1:0] : dataa_int[(2*int_width_a)-1:int_width_a]; + + assign mult_a_pre[(3*int_width_a)-1:2*int_width_a] = (input_source_a2 == "DATAA") ? dataa_int[(3*int_width_a)-1:2*int_width_a] : + (input_source_a2 == "SCANA")? mult_a_wire[(2*int_width_a)-1:int_width_a] : + (sourcea_wire[2] == 1)? mult_a_wire[(2*int_width_a)-1:int_width_a] : dataa_int[(3*int_width_a)-1:2*int_width_a]; + + assign mult_a_pre[(4*int_width_a)-1:3*int_width_a] = (input_source_a3 == "DATAA") ? dataa_int[(4*int_width_a)-1:3*int_width_a] : + (input_source_a3 == "SCANA")? mult_a_wire[(3*int_width_a)-1:2*int_width_a] : + (sourcea_wire[3] == 1)? mult_a_wire[(3*int_width_a)-1:2*int_width_a] : dataa_int[(4*int_width_a)-1:3*int_width_a]; + + assign scanouta = mult_a_wire[(number_of_multipliers * int_width_a)-1 : ((number_of_multipliers-1) * int_width_a) + (int_width_a - width_a)]; + assign scanoutb = mult_b_wire[(number_of_multipliers * int_width_b)-1 : ((number_of_multipliers-1) * int_width_b) + (int_width_b - width_b)]; + + // Clock in all the B input registers + assign i_scaninb = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0)? + datab_int[int_width_b-1:0] : scaninb_z; + + assign mult_b_pre[int_width_b-1:0] = (input_source_b0 == "DATAB")? datab_int[int_width_b-1:0] : + (input_source_b0 == "SCANB")? i_scaninb : + (sourceb_wire[0] == 1)? scaninb_z : datab_int[int_width_b-1:0]; + + assign mult_b_pre[(2*int_width_b)-1:int_width_b] = (input_source_b1 == "DATAB") ? datab_int[(2*int_width_b)-1 : int_width_b ]: + (input_source_b1 == "SCANB")? mult_b_wire[int_width_b -1 : 0] : + (sourceb_wire[1] == 1)? mult_b_wire[int_width_b -1 : 0] : datab_int[(2*int_width_b)-1 : int_width_b ]; + + assign mult_b_pre[(3*int_width_b)-1:2*int_width_b] = (input_source_b2 == "DATAB") ? datab_int[(3*int_width_b)-1:2*int_width_b] : + (input_source_b2 == "SCANB")? mult_b_wire[(2*int_width_b)-1:int_width_b] : + (sourceb_wire[2] == 1)? mult_b_wire[(2*int_width_b)-1:int_width_b] : datab_int[(3*int_width_b)-1:2*int_width_b]; + + assign mult_b_pre[(4*int_width_b)-1:3*int_width_b] = (input_source_b3 == "DATAB") ? datab_int[(4*int_width_b)-1:3*int_width_b] : + (input_source_b3 == "SCANB")? mult_b_wire[(3*int_width_b)-1:2*int_width_b] : + (sourceb_wire[3] == 1)? mult_b_wire[(3*int_width_b)-1:2*int_width_b] : datab_int[(4*int_width_b)-1:3*int_width_b]; + + // clock in all the control signals + assign addsub1_int = ((port_addnsub1 == "PORT_CONNECTIVITY")? + ((multiplier1_direction != "UNUSED")? (multiplier1_direction == "ADD" ? 1 : 0) : addnsub1_z) : + ((port_addnsub1 == "PORT_USED")? addnsub1_z : + (port_addnsub1 == "PORT_UNUSED")? (multiplier1_direction == "ADD" ? 1 : 0) : addnsub1_z)); + + assign addsub3_int = ((port_addnsub3 == "PORT_CONNECTIVITY")? + ((multiplier3_direction != "UNUSED") ? (multiplier3_direction == "ADD" ? 1 : 0) : addnsub3_z) : + ((port_addnsub3 == "PORT_USED")? addnsub3_z : + (port_addnsub3 == "PORT_UNUSED")? (multiplier3_direction == "ADD" ? 1 : 0) : addnsub3_z)); + + assign sign_a_int = ((port_signa == "PORT_CONNECTIVITY")? + ((representation_a != "UNUSED") ? (representation_a == "SIGNED" ? 1 : 0) : signa_z) : + (port_signa == "PORT_USED")? signa_z : + (port_signa == "PORT_UNUSED")? (representation_a == "SIGNED" ? 1 : 0) : signa_z); + + assign sign_b_int = ((port_signb == "PORT_CONNECTIVITY")? + ((representation_b != "UNUSED") ? (representation_b == "SIGNED" ? 1 : 0) : signb_z) : + (port_signb == "PORT_USED")? signb_z : + (port_signb == "PORT_UNUSED")? (representation_b == "SIGNED" ? 1 : 0) : signb_z); + + + + // ----------------------------------------------------------------- + // This is the main block that performs the addition and subtraction + // ----------------------------------------------------------------- + + assign result = (output_register == "UNREGISTERED")? + temp_sum[width_result - 1 + int_mult_diff_bit : int_mult_diff_bit]: temp_sum_reg[width_result - 1 + int_mult_diff_bit:int_mult_diff_bit]; + + assign mult_is_saturate_vec = (output_register == "UNREGISTERED")? + mult_saturate_overflow_vec: mult_saturate_overflow_pipe_reg; + + always @(posedge output_reg_wire_clk or posedge output_reg_wire_clr) + begin + if (output_reg_wire_clr == 1) + begin + temp_sum_reg <= {(int_width_result + 1){1'b0}}; + + for ( num_stor = extra_latency; num_stor >= 0; num_stor = num_stor - 1 ) + begin + result_pipe[num_stor] <= {int_width_result{1'b0}}; + end + + mult_saturate_overflow_pipe_reg <= {4{1'b0}}; + + head_result <= 0; + end + else if ((output_reg_wire_clk ==1) && (output_reg_wire_en ==1)) + begin + + if (extra_latency == 0) + begin + temp_sum_reg[int_width_result-1 :0] <= temp_sum[int_width_result-1 :0]; + end + else + begin + result_pipe [head_result] <= temp_sum[int_width_result-1 :0]; + head_result <= (head_result +1) % (extra_latency + 1); + end + mult_saturate_overflow_pipe_reg <= mult_saturate_overflow_vec; + end + + end + + assign head_result_wire = head_result[31:0]; + + always @(head_result_wire or result_pipe[head_result_wire]) + begin + if (extra_latency != 0) + temp_sum_reg[int_width_result-1 :0] <= result_pipe[head_result_wire]; + end + + always @(mult_res_wire [4 * (int_width_a + int_width_b) -1:0] or + addsub1_pipe_wire or addsub3_pipe_wire or + sign_a_pipe_wire or sign_b_pipe_wire or addnsub1_round_pipe_wire or + addnsub3_round_pipe_wire) + begin + temp_sum =0; + for (num_mult = 0; num_mult < number_of_multipliers; num_mult = num_mult +1) + begin + + mult_res_temp = mult_res_wire >> (num_mult * (int_width_a + int_width_b)); + mult_res_ext = ((int_width_result > (int_width_a + int_width_b))? + {{(int_width_result - int_width_a - int_width_b) + {mult_res_temp [int_width_a + int_width_b - 1] & + (sign_a_pipe_wire | sign_b_pipe_wire)}}, mult_res_temp}:mult_res_temp); + + if (num_mult == 1) + begin + if (addsub1_pipe_wire) + temp_sum = temp_sum + mult_res_ext; + else + temp_sum = temp_sum - mult_res_ext; + + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 1) + begin + // ------------------------------------------------------- + // Stratix II Rounding support + // This block basically carries out the rounding for the + // temp_sum. The equation to get the roundout for adder1 and + // adder3 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 ((adder1_rounding == "YES") || + ((adder1_rounding == "VARIABLE") && (addnsub1_round_pipe_wire == 1))) + begin + adder1_round_out = temp_sum + ( 1 << (`ADDER_ROUND_BITS - 1)); + + for (j = (`ADDER_ROUND_BITS - 1); j >= 0; j = j - 1) + begin + adder1_round_out[j] = 1'b0; + end + + end + else + begin + adder1_round_out = temp_sum; + end + + adder1_result = adder1_round_out; + end + + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) + begin + temp_sum = adder1_result; + end + + end + else if (num_mult == 3) + begin + if (addsub3_pipe_wire) + temp_sum = temp_sum + mult_res_ext; + else + temp_sum = temp_sum - mult_res_ext; + + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 1) + begin + // StratixII rounding support + // Please see the description for rounding support in adder1 + + if ((adder3_rounding == "YES") || + ((adder3_rounding == "VARIABLE") && (addnsub3_round_pipe_wire == 1))) + begin + + adder3_round_out = temp_sum + ( 1 << (`ADDER_ROUND_BITS - 1)); + + for (j = (`ADDER_ROUND_BITS - 1); j >= 0; j = j - 1) + begin + adder3_round_out[j] = 1'b0; + end + + end + else + begin + adder3_round_out = temp_sum; + end + + adder3_result = adder3_round_out; + end + + if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) + begin + temp_sum = adder3_result; + end + + end + else + begin + temp_sum = temp_sum + mult_res_ext; + end + end + + end + + +endmodule // end of ALTMULT_ADD + + +//START_MODULE_NAME------------------------------------------------------------- +// +// Module Name : altfp_mult +// +// Description : Parameterized floating point multiplier megafunction. +// This module implements IEEE-754 Compliant Floating Poing +// Multiplier.It supports Single Precision, Single Extended +// Precision and Double Precision floating point +// multiplication. +// +// Limitation : Fixed clock latency with 4 clock cycle delay. +// +// Results expected: result of multiplication and the result's status bits +// +//END_MODULE_NAME--------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +module altfp_mult ( + clock, // Clock input to the multiplier.(Required) + clk_en, // Clock enable for the multiplier. + aclr, // Asynchronous clear for the multiplier. + dataa, // Data input to the multiplier.(Required) + datab, // Data input to the multiplier.(Required) + result, // Multiplier output port.(Required) + overflow, // Overflow port for the multiplier. + underflow, // Underflow port for the multiplier. + zero, // Zero port for the multiplier. + denormal, // Denormal port for the multiplier. + indefinite, // Indefinite port for the multiplier. + nan // Nan port for the multiplier. +); + +// GLOBAL PARAMETER DECLARATION + // Specifies the value of the exponent, Minimum = 8, Maximum = 31 + parameter width_exp = 8; + // Specifies the value of the mantissa, Minimum = 23, Maximum = 52 + parameter width_man = 23; + // Specifies whether to use dedicated multiplier circuitry. + parameter dedicated_multiplier_circuitry = "AUTO"; + parameter reduced_functionality = "NO"; + parameter pipeline = 5; + parameter lpm_hint = "UNUSED"; + parameter lpm_type = "altfp_mult"; + +// LOCAL PARAMETER DECLARATION + //clock latency + parameter LATENCY = pipeline -1; + // Sum of mantissa's width and exponent's width + parameter WIDTH_MAN_EXP = width_exp + width_man; + +// INPUT PORT DECLARATION + input [WIDTH_MAN_EXP : 0] dataa; + input [WIDTH_MAN_EXP : 0] datab; + input clock; + input clk_en; + input aclr; + +// OUTPUT PORT DECLARATION + output [WIDTH_MAN_EXP : 0] result; + output overflow; + output underflow; + output zero; + output denormal; + output indefinite; + output nan; + +// INTERNAL REGISTERS DECLARATION + reg[width_man : 0] mant_dataa; + reg[width_man : 0] mant_datab; + reg[(2 * width_man) + 1 : 0] mant_result; + reg cout; + reg zero_mant_dataa; + reg zero_mant_datab; + reg zero_dataa; + reg zero_datab; + reg inf_dataa; + reg inf_datab; + reg nan_dataa; + reg nan_datab; + reg den_dataa; + reg den_datab; + reg no_multiply; + reg mant_result_msb; + reg no_rounding; + reg sticky_bit; + reg round_bit; + reg guard_bit; + reg carry; + reg[WIDTH_MAN_EXP : 0] result_pipe[LATENCY : 0]; + reg[LATENCY : 0] overflow_pipe; + reg[LATENCY : 0] underflow_pipe; + reg[LATENCY : 0] zero_pipe; + reg[LATENCY : 0] denormal_pipe; + reg[LATENCY : 0] indefinite_pipe; + reg[LATENCY : 0] nan_pipe; + reg[WIDTH_MAN_EXP : 0] temp_result; + reg overflow_bit; + reg underflow_bit; + reg zero_bit; + reg denormal_bit; + reg indefinite_bit; + reg nan_bit; + +// INTERNAL TRI DECLARATION + tri1 clk_en; + tri0 aclr; + +// LOCAL INTEGER DECLARATION + integer exp_dataa; + integer exp_datab; + integer exp_result; + + // loop counter + integer i0; + integer i1; + integer i2; + integer i3; + integer i4; + integer i5; + +// TASK DECLARATION + + // Add up two bits to get the result(<mantissa of datab> + <temporary result + // of mantissa's multiplication>) + //Also output the carry bit. + task add_bits; + // Value to be added to the temporary result of mantissa's multiplication. + input [width_man : 0] val1; + // temporary result of mantissa's multiplication. + inout [(2 * width_man) + 1 : 0] temp_mant_result; + output cout; // carry out bit + + reg co; // temporary storage to store the carry out bit + + begin + co = 1'b0; + for(i0 = 0; i0 <= width_man; i0 = i0 + 1) + begin + // if the carry out bit from the previous bit addition is 1'b0 + if (co == 1'b0) + begin + if (val1[i0] != temp_mant_result[i0 + width_man + 1]) + begin + temp_mant_result[i0 + width_man + 1] = 1'b1; + end + else + begin + co = val1[i0] & temp_mant_result[i0 + width_man + 1]; + temp_mant_result[i0 + width_man + 1] = 1'b0; + end + end + else // if (co == 1'b1) + begin + co = val1[i0] | temp_mant_result[i0 + width_man + 1]; + if (val1[i0] != temp_mant_result[i0 + width_man + 1]) + begin + temp_mant_result[i0 + width_man + 1] = 1'b0; + end + else + begin + temp_mant_result[i0 + width_man + 1] = 1'b1; + end + end + end // end of for loop + cout = co; + end + endtask // add_bits + +// FUNCTON DECLARATION + + // Check whether the all the bits from index <index1> to <index2> is 1'b1 + // Return 1'b1 if true, otherwise return 1'b0 + function bit_all_0; + input [(2 * width_man) + 1: 0] val; + input index1; + integer index1; + input index2; + integer index2; + + reg all_0; //temporary storage to indicate whether all the currently + // checked bits are 1'b0 + begin + begin : LOOP_1 + all_0 = 1'b1; + for (i1 = index1; i1 <= index2; i1 = i1 + 1) + begin + if ((val[i1]) == 1'b1) + begin + all_0 = 1'b0; + disable LOOP_1; //break the loop to stop checking + end + end + end + bit_all_0 = all_0; + end + endfunction // bit_all_0 + + // Calculate the exponential value (<base_number> power of <exponent_number>) + function integer exponential_value; + input base_number; + input exponent_number; + integer base_number; + integer exponent_number; + integer value; // temporary storage to store the exponential value + + begin + value = 1; + for (i2 = 0; i2 < exponent_number; i2 = i2 + 1) + begin + value = base_number * value; + end + exponential_value = value; + end + endfunction // exponential_value + +// INITIAL CONSTRUCT BLOCK + initial + begin : INITIALIZATION + for(i3 = LATENCY; i3 >= 0; i3 = i3 - 1) + begin + result_pipe[i3] = 0; + overflow_pipe[i3] = 1'b0; + underflow_pipe[i3] = 1'b0; + zero_pipe[i3] = 1'b0; + denormal_pipe[i3] = 1'b0; + indefinite_pipe[i3] = 1'b0; + nan_pipe[i3] = 1'b0; + end + // Check for illegal mode setting + if (WIDTH_MAN_EXP >= 64) + begin + $display("ERROR: The sum of width_exp(%d) and width_man(%d) must be less 64!", width_exp, width_man); + $finish; + end + if (width_exp < 8) + begin + $display("ERROR: width_exp(%d) must be at least 8!", width_exp); + $finish; + end + if (width_man < 23) + begin + $display("ERROR: width_man(%d) must be at least 23!", width_man); + $finish; + end + if (~((width_exp >= 11) || ((width_exp == 8) && (width_man == 23)))) + begin + $display("ERROR: Found width_exp(%d) inside the range of Single Precision. width_exp must be 8 and width_man must be 23 for Single Presicion!", width_exp); + $finish; + end + if (~((width_man >= 31) || ((width_exp == 8) && (width_man == 23)))) + begin + $display("ERROR: Found width_man(%d) inside the range of Single Precision. width_exp must be 8 and width_man must be 23 for Single Presicion!", width_man); + $finish; + end + if (width_exp >= width_man) + begin + $display("ERROR: width_exp(%d) must be less than width_man(%d)!", width_exp, width_man); + $finish; + end + if ((pipeline != 5) && (pipeline != 6)) + begin + $display("ERROR: The legal value for PIPELINE is 5 or 6!"); + $finish; + end + + if ((reduced_functionality != "NO") && (reduced_functionality != "YES")) + begin + $display("ERROR: reduced_functionality value must be \"YES\" or \"NO\"!"); + $finish; + end + + if (reduced_functionality != "NO") + begin + $display("Info: The Clearbox support is available for reduced functionality Floating Point Multiplier."); + end + end // INITIALIZATION + +// ALWAYS CONSTRUCT BLOCK + + // multiplication + always @(dataa or datab) + begin : MULTIPLY_FP + temp_result = {(WIDTH_MAN_EXP + 1){1'b0}}; + overflow_bit = 1'b0; + underflow_bit = 1'b0; + zero_bit = 1'b0; + denormal_bit = 1'b0; + indefinite_bit = 1'b0; + nan_bit = 1'b0; + mant_result = {((2 * width_man) + 2){1'b0}}; + exp_dataa = 0; + exp_datab = 0; + // Set the exponential value + exp_dataa = dataa[width_exp + width_man -1:width_man]; + exp_datab = datab[width_exp + width_man -1:width_man]; + + zero_mant_dataa = 1'b1; + // Check whether the mantissa for dataa is zero + begin : LOOP_3 + for (i4 = 0; i4 <= width_man - 1; i4 = i4 + 1) + begin + if ((dataa[i4]) == 1'b1) + begin + zero_mant_dataa = 1'b0; + disable LOOP_3; + end + end + end // LOOP_3 + zero_mant_datab = 1'b1; + // Check whether the mantissa for datab is zero + begin : LOOP_4 + for (i4 = 0; i4 <= width_man -1; i4 = i4 + 1) + begin + if ((datab[i4]) == 1'b1) + begin + zero_mant_datab = 1'b0; + disable LOOP_4; + end + end + end // LOOP_4 + zero_dataa = 1'b0; + den_dataa = 1'b0; + inf_dataa = 1'b0; + nan_dataa = 1'b0; + // Check whether dataa is special input + if (exp_dataa == 0) + begin + if ((zero_mant_dataa == 1'b1) + || (reduced_functionality != "NO")) + begin + zero_dataa = 1'b1; // dataa is zero + end + else + begin + den_dataa = 1'b1; // dataa is denormalized + end + end + else if (exp_dataa == (exponential_value(2, width_exp) - 1)) + begin + if (zero_mant_dataa == 1'b1) + begin + inf_dataa = 1'b1; // dataa is infinity + end + else + begin + nan_dataa = 1'b1; // dataa is Nan + end + end + zero_datab = 1'b0; + den_datab = 1'b0; + inf_datab = 1'b0; + nan_datab = 1'b0; + // Check whether datab is special input + if (exp_datab == 0) + begin + if ((zero_mant_datab == 1'b1) + || (reduced_functionality != "NO")) + begin + zero_datab = 1'b1; // datab is zero + end + else + begin + den_datab = 1'b1; // datab is denormalized + end + end + else if (exp_datab == (exponential_value(2, width_exp) - 1)) + begin + if (zero_mant_datab == 1'b1) + begin + inf_datab = 1'b1; // datab is infinity + end + else + begin + nan_datab = 1'b1; // datab is Nan + end + end + no_multiply = 1'b0; + // Set status flag if special input exists + if (nan_dataa || nan_datab || (inf_dataa && zero_datab) || + (inf_datab && zero_dataa)) + begin + nan_bit = 1'b1; // NaN + for (i4 = width_man - 1; i4 <= WIDTH_MAN_EXP - 1; i4 = i4 + 1) + begin + temp_result[i4] = 1'b1; + end + no_multiply = 1'b1; // no multiplication is needed. + end + else if (zero_dataa) + begin + zero_bit = 1'b1; // Zero + temp_result[WIDTH_MAN_EXP : 0] = 0; + no_multiply = 1'b1; + end + else if (zero_datab) + begin + zero_bit = 1'b1; // Zero + temp_result[WIDTH_MAN_EXP : 0] = 0; + no_multiply = 1'b1; + end + else if (inf_dataa) + begin + overflow_bit = 1'b1; // Overflow + temp_result[WIDTH_MAN_EXP : 0] = dataa; + no_multiply = 1'b1; + end + else if (inf_datab) + begin + overflow_bit = 1'b1; // Overflow + temp_result[WIDTH_MAN_EXP : 0] = datab; + no_multiply = 1'b1; + end + // if multiplication needed + if (no_multiply == 1'b0) + begin + // Perform exponent operation + exp_result = exp_dataa + exp_datab - (exponential_value(2, width_exp -1) -1); + // First operand for multiplication + mant_dataa[width_man : 0] = {1'b1, dataa[width_man -1 : 0]}; + // Second operand for multiplication + mant_datab[width_man : 0] = {1'b1, datab[width_man -1 : 0]}; + // Multiply the mantissas using add and shift algorithm + for (i4 = 0; i4 <= width_man; i4 = i4 + 1) + begin + cout = 1'b0; + if ((mant_dataa[i4]) == 1'b1) + begin + add_bits(mant_datab, mant_result, cout); + end + mant_result = mant_result >> 1; + mant_result[2*width_man + 1] = cout; + end + sticky_bit = 1'b0; + mant_result_msb = mant_result[2*width_man + 1]; + // Normalize the Result + if (mant_result_msb == 1'b1) + begin + sticky_bit = mant_result[0]; // Needed for rounding operation. + mant_result = mant_result >> 1; + exp_result = exp_result + 1; + end + round_bit = mant_result[width_man - 1]; + guard_bit = mant_result[width_man]; + no_rounding = 1'b0; + // Check whether should perform rounding or not + if (round_bit == 1'b0) + begin + no_rounding = 1'b1; // No rounding is needed + end + else + begin + if (reduced_functionality == "NO") + begin + for(i4 = 0; i4 <= width_man - 2; i4 = i4 + 1) + begin + sticky_bit = sticky_bit | mant_result[i4]; + end + end + else + begin + sticky_bit = (mant_result[width_man - 2] & + mant_result_msb); + end + if ((sticky_bit == 1'b0) && (guard_bit == 1'b0)) + begin + no_rounding = 1'b1; + end + end + // Perform rounding + if (no_rounding == 1'b0) + begin + carry = 1'b1; + for(i4 = width_man; i4 <= 2 * width_man + 1; i4 = i4 + 1) + begin + if (carry == 1'b1) + begin + if (mant_result[i4] == 1'b0) + begin + mant_result[i4] = 1'b1; + carry = 1'b0; + end + else + begin + mant_result[i4] = 1'b0; + end + end + end + // 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[(2 * width_man) + 1] == 1'b1) + begin + mant_result = mant_result >> 1; + exp_result = exp_result + 1; + end + end + // Normalize the Result + if ((!bit_all_0(mant_result, 0, (2 * width_man) + 1)) && + (mant_result[2 * width_man] == 1'b0)) + begin + while ((mant_result[2 * width_man] == 1'b0) && + (exp_result != 0)) + begin + mant_result = mant_result << 1; + exp_result = exp_result - 1; + end + end + else if ((exp_result < 0) && (exp_result >= -(2*width_man))) + begin + while(exp_result != 0) + begin + mant_result = mant_result >> 1; + exp_result = exp_result + 1; + end + end + // Set status flag "indefinite" if normal * denormal + // (ignore other status port since we dont care the output + if (den_dataa || den_datab) + begin + indefinite_bit = 1'b1; // Indefinite + end + else if (exp_result >= (exponential_value(2, width_exp) -1)) + begin + overflow_bit = 1'b1; // Overflow + end + else if (exp_result < 0) + begin + underflow_bit = 1'b1; // Underflow + zero_bit = 1'b1; // Zero + end + else if (exp_result == 0) + begin + underflow_bit = 1'b1; // Underflow + + if (bit_all_0(mant_result, width_man + 1, 2 * width_man)) + begin + zero_bit = 1'b1; // Zero + end + else + begin + denormal_bit = 1'b1; // Denormal + end + end + // Get result's mantissa + if (exp_result < 0) // Result underflow + begin + for(i4 = 0; i4 <= width_man - 1; i4 = i4 + 1) + begin + temp_result[i4] = 1'b0; + end + end + else if (exp_result == 0) // Denormalized result + begin + if (reduced_functionality == "NO") + begin + temp_result[width_man - 1 : 0] = mant_result[2 * width_man : width_man + 1]; + end + else + begin + temp_result[width_man - 1 : 0] = 0; + end + end + // Result overflow + else if (exp_result >= exponential_value(2, width_exp) -1) + begin + temp_result[width_man - 1 : 0] = {width_man{1'b0}}; + end + else // Normalized result + begin + temp_result[width_man - 1 : 0] = mant_result[(2 * width_man - 1) : width_man]; + end + // Get result's exponent + if (exp_result == 0) + begin + for(i4 = width_man; i4 <= WIDTH_MAN_EXP - 1; i4 = i4 + 1) + begin + temp_result[i4] = 1'b0; + end + end + else if (exp_result >= (exponential_value(2, width_exp) -1)) + begin + for(i4 = width_man; i4 <= WIDTH_MAN_EXP - 1; i4 = i4 + 1) + begin + temp_result[i4] = 1'b1; + end + end + else + begin + // Convert integer to binary bits + for(i4 = width_man; i4 <= WIDTH_MAN_EXP - 1; i4 = i4 + 1) + begin + if ((exp_result % 2) == 1) + begin + temp_result[i4] = 1'b1; + end + else + begin + temp_result[i4] = 1'b0; + end + exp_result = exp_result / 2; + end + end + end // end of if (no_multiply == 1'b0) + // Get result's sign bit + temp_result[WIDTH_MAN_EXP] = dataa[WIDTH_MAN_EXP] ^ datab[WIDTH_MAN_EXP]; + + end // MULTIPLY_FP + + // Pipelining registers. + always @(posedge clock or posedge aclr) + begin : PIPELINE_REGS + if (aclr == 1'b1) + begin + for (i5 = LATENCY; i5 >= 0; i5 = i5 - 1) + begin + result_pipe[i5] <= {WIDTH_MAN_EXP{1'b0}}; + overflow_pipe[i5] <= 1'b0; + underflow_pipe[i5] <= 1'b0; + zero_pipe[i5] <= 1'b1; + denormal_pipe[i5] <= 1'b0; + indefinite_pipe[i5] <= 1'b0; + nan_pipe[i5] <= 1'b0; + end + // clear all the output ports to 1'b0 + end + else if (clk_en == 1'b1) + begin + result_pipe[0] <= temp_result; + overflow_pipe[0] <= overflow_bit; + underflow_pipe[0] <= underflow_bit; + zero_pipe[0] <= zero_bit; + denormal_pipe[0] <= denormal_bit; + indefinite_pipe[0] <= indefinite_bit; + nan_pipe[0] <= nan_bit; + + // Create latency for the output result + for(i5=LATENCY; i5 >= 1; i5 = i5 - 1) + begin + result_pipe[i5] <= result_pipe[i5 - 1]; + overflow_pipe[i5] <= overflow_pipe[i5 - 1]; + underflow_pipe[i5] <= underflow_pipe[i5 - 1]; + zero_pipe[i5] <= zero_pipe[i5 - 1]; + denormal_pipe[i5] <= denormal_pipe[i5 - 1]; + indefinite_pipe[i5] <= indefinite_pipe[i5 - 1]; + nan_pipe[i5] <= nan_pipe[i5 - 1]; + end + end + end // PIPELINE_REGS + +assign result = result_pipe[LATENCY]; +assign overflow = overflow_pipe[LATENCY]; +assign underflow = underflow_pipe[LATENCY]; +assign zero = (reduced_functionality == "NO") ? zero_pipe[LATENCY] : 1'b0; +assign denormal = (reduced_functionality == "NO") ? denormal_pipe[LATENCY] : 1'b0; +assign indefinite = (reduced_functionality == "NO") ? indefinite_pipe[LATENCY] : 1'b0; +assign nan = nan_pipe[LATENCY]; + +endmodule //altfp_mult + +// END OF MODULE + +//START_MODULE_NAME------------------------------------------------------------- +// +// Module 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). +// +// Limitation : The radical is assumed to be unsigned integer. +// +// Results expected: Square root of the radical and the remainder. +// +//END_MODULE_NAME--------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +module altsqrt ( + radical, // Input port for the radical + clk, // Clock port + ena, // Clock enable port + aclr, // Asynchronous clear port + q, // Output port for returning the square root of the radical. + remainder // Output port for returning the remainder of the square root. +); + +// GLOBAL PARAMETER DECLARATION + parameter q_port_width = 1; // The width of the q port + parameter r_port_width = 1; // The width of the remainder port + parameter width = 1; // The width of the radical + parameter pipeline = 0; // The latency for the output + parameter lpm_hint= "UNUSED"; + parameter lpm_type = "altsqrt"; + +// INPUT PORT DECLARATION + input [width - 1 : 0] radical; + input clk; + input ena; + input aclr; + +// OUTPUT PORT DECLARATION + output [q_port_width - 1 : 0] q; + output [r_port_width - 1 : 0] remainder; + +// INTERNAL REGISTERS DECLARATION + reg[q_port_width - 1 : 0] q_temp; + reg[q_port_width - 1 : 0] q_pipeline[(pipeline +1) : 0]; + reg[r_port_width - 1 : 0] r_temp; + reg[r_port_width - 1 : 0] remainder_pipeline[(pipeline +1) : 0]; + +// INTERNAL TRI DECLARATION + tri1 clk; + tri1 ena; + tri0 aclr; + +// LOCAL INTEGER DECLARATION + integer value1; + integer value2; + integer index; + integer q_index; + integer q_value_temp; + integer r_value_temp; + integer i1; + integer pipe_ptr; + + +// INITIAL CONSTRUCT BLOCK + initial + begin : INITIALIZE + // Check for illegal mode + if(width < 1) + begin + $display("width (%d) must be greater than 0.(ERROR)", width); + $finish; + end + pipe_ptr = 0; + end // INITIALIZE + +// ALWAYS CONSTRUCT BLOCK + + // 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 + always @(radical) + begin : SQUARE_ROOT + // Reset variables + value1 = 0; + value2 = 0; + q_index = (width - 1) / 2; + q_value_temp = 0; + r_value_temp = 0; + q_temp = {q_port_width{1'b0}}; + r_temp = {r_port_width{1'b0}}; + + // 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 % 2) == 1) + begin + index = width + 1; + value1 = 0; + value2 = (radical[index - 2] === 1'b1) ? 1'b1 : 1'b0; + end + else if (width > 1) + begin + // 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". + index = width; + value1 = (radical[index - 1] === 1'b1) ? 1'b1 : 1'b0; + value2 = (radical[index - 2] === 1'b1) ? 1'b1 : 1'b0; + end + + // For every iteration + for(index = index - 2; index >= 0; index = index - 2) + begin + // Get the remainder value by shifting in the next 2 bits + // of the radical into the remainder + r_value_temp = (r_value_temp * 4) + (2 * value1) + value2; + + // if remainder >= (4*q + 1) + if (r_value_temp >= ((4 * q_value_temp) + 1)) + begin + // remainder = remainder - (4*q + 1) + r_value_temp = r_value_temp - (4 * q_value_temp) - 1; + // q = 2*q + 1 + q_value_temp = (2 * q_value_temp) + 1; + // set the q[q_index] = 1 + q_temp[q_index] = 1'b1; + end + else // if remainder < (4*q + 1) + begin + // q = 2*q + q_value_temp = 2 * q_value_temp; + // set the q[q_index] = 0 + q_temp[q_index] = 1'b0; + end + + // if not the last iteration, get the next 2 bits of the radical + if(index >= 2) + begin + value1 = (radical[index - 1] === 1'b1)? 1: 0; + value2 = (radical[index - 2] === 1'b1)? 1: 0; + end + + // Reduce the current index of q by 1 + q_index = q_index - 1; + + end + + // Get the binary bits of the remainder by converting integer to + // binary bits + r_temp = r_value_temp; + end + + // store the result to a pipeline(to create the latency) + always @(posedge clk or posedge aclr) + begin + if (aclr) // clear the pipeline for result to 0 + begin + for (i1 = 0; i1 < (pipeline + 1); i1 = i1 + 1) + begin + q_pipeline[i1] <= 0; + remainder_pipeline[i1] <= 0; + end + end + else if (ena == 1) + begin + remainder_pipeline[pipe_ptr] <= r_temp; + q_pipeline[pipe_ptr] <= q_temp; + + if (pipeline > 1) + pipe_ptr <= (pipe_ptr + 1) % pipeline; + end + end + +// CONTINOUS ASSIGNMENT + assign q = (pipeline > 0) ? q_pipeline[pipe_ptr] : q_temp; + assign remainder = (pipeline > 0) ? remainder_pipeline[pipe_ptr] : r_temp; + +endmodule //altsqrt +// END OF MODULE + +// START MODULE NAME ----------------------------------------------------------- +// +// Module 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. +// Applicable to APEX, Mercury and FLEX10KE device families +// only. +// +// Expected results : Up to 4 clock outputs (clock0, clock1, clock2, clock_ext). +// clock2 and clock_ext are for Mercury devices only. +// locked output indicates when PLL locks. +// +//END MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module altclklock ( + inclock, // input reference clock + inclocken, // PLL enable signal + fbin, // feedback input for the PLL + clock0, // output clock 0 + clock1, // output clock 1 + clock2, // output clock 2 (for Mercury only) + clock_ext, // external output clock (for Mercury only) + locked // PLL lock signal +); + +// GLOBAL PARAMETER DECLARATION +parameter inclock_period = 10000; // units in ps +parameter inclock_settings = "UNUSED"; +parameter valid_lock_cycles = 5; +parameter invalid_lock_cycles = 5; +parameter valid_lock_multiplier = 5; +parameter invalid_lock_multiplier = 5; +parameter operation_mode = "NORMAL"; +parameter clock0_boost = 1; +parameter clock0_divide = 1; +parameter clock0_settings = "UNUSED"; +parameter clock0_time_delay = "0"; +parameter clock1_boost = 1; +parameter clock1_divide = 1; +parameter clock1_settings = "UNUSED"; +parameter clock1_time_delay = "0"; +parameter clock2_boost = 1; +parameter clock2_divide = 1; +parameter clock2_settings = "UNUSED"; +parameter clock2_time_delay = "0"; +parameter clock_ext_boost = 1; +parameter clock_ext_divide = 1; +parameter clock_ext_settings = "UNUSED"; +parameter clock_ext_time_delay = "0"; +parameter outclock_phase_shift = 0; // units in ps +parameter intended_device_family = "APEX20KE"; +parameter lpm_type = "altclklock"; +parameter lpm_hint = "UNUSED"; + +// INPUT PORT DECLARATION +input inclock; +input inclocken; +input fbin; + +// OUTPUT PORT DECLARATION +output clock0; +output clock1; +output clock2; +output clock_ext; +output locked; + +// INTERNAL VARIABLE/REGISTER DECLARATION +reg clock0; +reg clock1; +reg clock2; +reg clock_ext; + +reg start_outclk; +reg clk0_tmp; +reg clk1_tmp; +reg clk2_tmp; +reg extclk_tmp; +reg pll_lock; +reg clk_last_value; +reg violation; +reg clk_check; +reg [1:0] next_clk_check; + +reg init; + +real pll_last_rising_edge; +real pll_last_falling_edge; +real actual_clk_cycle; +real expected_clk_cycle; +real pll_duty_cycle; +real inclk_period; +real expected_next_clk_edge; +integer pll_rising_edge_count; +integer stop_lock_count; +integer start_lock_count; +integer clk_per_tolerance; + +time clk0_phase_delay; +time clk1_phase_delay; +time clk2_phase_delay; +time extclk_phase_delay; + +ALTERA_DEVICE_FAMILIES dev (); + +// variables for clock synchronizing +time last_synchronizing_rising_edge_for_clk0; +time last_synchronizing_rising_edge_for_clk1; +time last_synchronizing_rising_edge_for_clk2; +time last_synchronizing_rising_edge_for_extclk; +time clk0_synchronizing_period; +time clk1_synchronizing_period; +time clk2_synchronizing_period; +time extclk_synchronizing_period; +integer input_cycles_per_clk0; +integer input_cycles_per_clk1; +integer input_cycles_per_clk2; +integer input_cycles_per_extclk; +integer clk0_cycles_per_sync_period; +integer clk1_cycles_per_sync_period; +integer clk2_cycles_per_sync_period; +integer extclk_cycles_per_sync_period; +integer input_cycle_count_to_sync0; +integer input_cycle_count_to_sync1; +integer input_cycle_count_to_sync2; +integer input_cycle_count_to_sync_extclk; + +// variables for shedule_clk0-2, clk_ext +reg schedule_clk0; +reg schedule_clk1; +reg schedule_clk2; +reg schedule_extclk; +reg output_value0; +reg output_value1; +reg output_value2; +reg output_value_ext; +time sched_time0; +time sched_time1; +time sched_time2; +time sched_time_ext; +integer rem0; +integer rem1; +integer rem2; +integer rem_ext; +integer tmp_rem0; +integer tmp_rem1; +integer tmp_rem2; +integer tmp_rem_ext; +integer clk_cnt0; +integer clk_cnt1; +integer clk_cnt2; +integer clk_cnt_ext; +integer cyc0; +integer cyc1; +integer cyc2; +integer cyc_ext; +integer inc0; +integer inc1; +integer inc2; +integer inc_ext; +integer cycle_to_adjust0; +integer cycle_to_adjust1; +integer cycle_to_adjust2; +integer cycle_to_adjust_ext; +time tmp_per0; +time tmp_per1; +time tmp_per2; +time tmp_per_ext; +time ori_per0; +time ori_per1; +time ori_per2; +time ori_per_ext; +time high_time0; +time high_time1; +time high_time2; +time high_time_ext; +time low_time0; +time low_time1; +time low_time2; +time low_time_ext; + +// Default inclocken and fbin ports to 1 if unused +tri1 inclocken_int; +tri1 fbin_int; + +assign inclocken_int = inclocken; +assign fbin_int = fbin; + +// +// function time_delay - converts time_delay in string format to integer, and +// add result to outclock_phase_shift +// +function time time_delay; +input [8*16:1] s; + +reg [8*16:1] reg_s; +reg [8:1] digit; +reg [8:1] tmp; +integer m; +integer outclock_phase_shift_adj; +integer sign; + +begin + // initialize variables + sign = 1; + outclock_phase_shift_adj = 0; + reg_s = s; + + for (m = 1; m <= 16; m = m + 1) + begin + tmp = reg_s[128:121]; + digit = tmp & 8'b00001111; + reg_s = reg_s << 8; + // Accumulate ascii digits 0-9 only. + if ((tmp >= 48) && (tmp <= 57)) + outclock_phase_shift_adj = outclock_phase_shift_adj * 10 + digit; + if (tmp == 45) + sign = -1; // Found a '-' character, i.e. number is negative. + end + + // add outclock_phase_shift to time delay + outclock_phase_shift_adj = (sign*outclock_phase_shift_adj) + outclock_phase_shift; + + // adjust phase shift so that its value is between 0 and 1 full + // inclock_period + while (outclock_phase_shift_adj < 0) + outclock_phase_shift_adj = outclock_phase_shift_adj + inclock_period; + while (outclock_phase_shift_adj >= inclock_period) + outclock_phase_shift_adj = outclock_phase_shift_adj - inclock_period; + + // assign result + time_delay = outclock_phase_shift_adj; +end +endfunction + +// INITIAL BLOCK +initial +begin + + // check for invalid parameters + if (inclock_period <= 0) + begin + $display("ERROR: The period of the input clock (inclock_period) must be greater than 0"); + $stop; + end + + if ((clock0_boost <= 0) || (clock0_divide <= 0) + || (clock1_boost <= 0) || (clock1_divide <= 0) + || (clock2_boost <= 0) || (clock2_divide <= 0) + || (clock_ext_boost <= 0) || (clock_ext_divide <= 0)) + begin + if ((clock0_boost <= 0) || (clock0_divide <= 0)) + begin + $display("ERROR: The multiplication and division factors for clock0 must be greater than 0."); + end + + if ((clock1_boost <= 0) || (clock1_divide <= 0)) + begin + $display("ERROR: The multiplication and division factors for clock1 must be greater than 0."); + end + + if ((clock2_boost <= 0) || (clock2_divide <= 0)) + begin + $display("ERROR: The multiplication and division factors for clock2 must be greater than 0."); + end + + if ((clock_ext_boost <= 0) || (clock_ext_divide <= 0)) + begin + $display("ERROR: The multiplication and division factors for clock_ext must be greater than 0."); + end + $stop; + end + + if ((!dev.IS_FAMILY_FLEX10KE(intended_device_family)) + && (!dev.IS_FAMILY_ACEX1K(intended_device_family)) + && (!dev.IS_FAMILY_APEX20K(intended_device_family)) + && (!dev.IS_FAMILY_APEX20KE(intended_device_family)) + && (!dev.IS_FAMILY_APEX20KC(intended_device_family)) + && (!dev.IS_FAMILY_EXCALIBUR_ARM(intended_device_family)) + && (!dev.IS_FAMILY_APEXII(intended_device_family)) + && (!dev.IS_FAMILY_MERCURY(intended_device_family))) + begin + $display("WARNING: Device family specified by the intended_device_family parameter, %s, may not be supported by altclklock", intended_device_family); + end + + stop_lock_count = 0; + violation = 0; + + // clock synchronizing variables + last_synchronizing_rising_edge_for_clk0 = 0; + last_synchronizing_rising_edge_for_clk1 = 0; + last_synchronizing_rising_edge_for_clk2 = 0; + last_synchronizing_rising_edge_for_extclk = 0; + clk0_synchronizing_period = 0; + clk1_synchronizing_period = 0; + clk2_synchronizing_period = 0; + extclk_synchronizing_period = 0; + input_cycles_per_clk0 = clock0_divide; + input_cycles_per_clk1 = clock1_divide; + input_cycles_per_clk2 = clock2_divide; + input_cycles_per_extclk = clock_ext_divide; + clk0_cycles_per_sync_period = clock0_boost; + clk1_cycles_per_sync_period = clock1_boost; + clk2_cycles_per_sync_period = clock2_boost; + extclk_cycles_per_sync_period = clock_ext_boost; + 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; + inc0 = 1; + inc1 = 1; + inc2 = 1; + inc_ext = 1; + cycle_to_adjust0 = 0; + cycle_to_adjust1 = 0; + cycle_to_adjust2 = 0; + cycle_to_adjust_ext = 0; + + if ((clock0_boost % clock0_divide) == 0) + begin + clk0_cycles_per_sync_period = clock0_boost / clock0_divide; + input_cycles_per_clk0 = 1; + end + + if ((clock1_boost % clock1_divide) == 0) + begin + clk1_cycles_per_sync_period = clock1_boost / clock1_divide; + input_cycles_per_clk1 = 1; + end + + if ((clock2_boost % clock2_divide) == 0) + begin + clk2_cycles_per_sync_period = clock2_boost / clock2_divide; + input_cycles_per_clk2 = 1; + end + + if ((clock_ext_boost % clock_ext_divide) == 0) + begin + extclk_cycles_per_sync_period = clock_ext_boost / clock_ext_divide; + input_cycles_per_extclk = 1; + end + + // convert time delays from string to integer + clk0_phase_delay = time_delay(clock0_time_delay); + clk1_phase_delay = time_delay(clock1_time_delay); + clk2_phase_delay = time_delay(clock2_time_delay); + extclk_phase_delay = time_delay(clock_ext_time_delay); + + // 2.5% tolerance of input clock period variation + if(dev.IS_FAMILY_MERCURY(intended_device_family)) + clk_per_tolerance = 0.025 * inclock_period; + else + clk_per_tolerance = 0.1 * inclock_period; +end + +always @(next_clk_check) +begin + if (next_clk_check == 1) + begin + if ((clk_check === 1'b1) || (clk_check === 1'b0)) + #((inclk_period+clk_per_tolerance)/2) clk_check = ~clk_check; + else + #((inclk_period+clk_per_tolerance)/2) clk_check = 1'b1; + end + else if (next_clk_check == 2) + begin + if ((clk_check === 1'b1) || (clk_check === 1'b0)) + #(expected_next_clk_edge - $realtime) clk_check = ~clk_check; + else + #(expected_next_clk_edge - $realtime) clk_check = 1'b1; + end + next_clk_check = 0; +end + +always @(inclock or inclocken_int or clk_check) +begin + + if(init !== 1'b1) + begin + start_lock_count = 0; + pll_rising_edge_count = 0; + pll_last_rising_edge = 0; + pll_last_falling_edge = 0; + pll_lock = 0; + init = 1'b1; + end + + if (inclocken_int == 1'b0) + begin + pll_lock = 0; + pll_rising_edge_count = 0; + end + else if ((inclock == 1'b1) && (clk_last_value !== inclock)) + begin + if (pll_lock === 1) + next_clk_check = 1; + + if (pll_rising_edge_count == 0) // this is first rising edge + begin + inclk_period = inclock_period; + pll_duty_cycle = inclk_period/2; + start_outclk = 0; + end + else if (pll_rising_edge_count == 1) // this is second rising edge + begin + expected_clk_cycle = inclk_period; + actual_clk_cycle = $realtime - pll_last_rising_edge; + if (actual_clk_cycle < (expected_clk_cycle - clk_per_tolerance) || + actual_clk_cycle > (expected_clk_cycle + clk_per_tolerance)) + begin + $display($realtime, "ps Warning: Inclock_Period Violation"); + violation = 1; + if (locked == 1'b1) + begin + stop_lock_count = stop_lock_count + 1; + if ((locked == 1'b1) && (stop_lock_count == invalid_lock_cycles)) + begin + pll_lock = 0; + $display ($realtime, "ps Warning: altclklock out of lock."); + + if(dev.IS_FAMILY_APEX20KE(intended_device_family) || dev.IS_FAMILY_APEX20KC(intended_device_family) || dev.IS_FAMILY_EXCALIBUR_ARM(intended_device_family)) + start_lock_count = 0; + else + start_lock_count = 1; + + stop_lock_count = 0; + clk0_tmp = 1'bx; + clk1_tmp = 1'bx; + clk2_tmp = 1'bx; + extclk_tmp = 1'bx; + end + end + else begin + start_lock_count = 1; + end + end + else + begin + if (($realtime - pll_last_falling_edge) < (pll_duty_cycle - clk_per_tolerance/2) || + ($realtime - pll_last_falling_edge) > (pll_duty_cycle + clk_per_tolerance/2)) + begin + $display($realtime, "ps Warning: Duty Cycle Violation"); + violation = 1; + end + else + violation = 0; + end + end + else if (($realtime - pll_last_rising_edge) < (expected_clk_cycle - clk_per_tolerance) || + ($realtime - pll_last_rising_edge) > (expected_clk_cycle + clk_per_tolerance)) + begin + $display($realtime, "ps Warning: Cycle Violation"); + violation = 1; + if (locked == 1'b1) + begin + stop_lock_count = stop_lock_count + 1; + if (stop_lock_count == invalid_lock_cycles) + begin + pll_lock = 0; + $display ($realtime, "ps Warning: altclklock out of lock."); + + if(dev.IS_FAMILY_APEX20KE(intended_device_family) || dev.IS_FAMILY_APEX20KC(intended_device_family) || dev.IS_FAMILY_EXCALIBUR_ARM(intended_device_family)) + start_lock_count = 0; + else + start_lock_count = 1; + + stop_lock_count = 0; + clk0_tmp = 1'bx; + clk1_tmp = 1'bx; + clk2_tmp = 1'bx; + extclk_tmp = 1'bx; + end + end + else + begin + start_lock_count = 1; + end + end + else + begin + violation = 0; + actual_clk_cycle = $realtime - pll_last_rising_edge; + end + pll_last_rising_edge = $realtime; + pll_rising_edge_count = pll_rising_edge_count + 1; + if (!violation) + begin + if (pll_lock == 1'b1) + begin + input_cycle_count_to_sync0 = input_cycle_count_to_sync0 + 1; + if (input_cycle_count_to_sync0 == input_cycles_per_clk0) + begin + clk0_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk0; + last_synchronizing_rising_edge_for_clk0 = $realtime; + schedule_clk0 = 1; + input_cycle_count_to_sync0 = 0; + end + input_cycle_count_to_sync1 = input_cycle_count_to_sync1 + 1; + if (input_cycle_count_to_sync1 == input_cycles_per_clk1) + begin + clk1_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk1; + last_synchronizing_rising_edge_for_clk1 = $realtime; + schedule_clk1 = 1; + input_cycle_count_to_sync1 = 0; + end + input_cycle_count_to_sync2 = input_cycle_count_to_sync2 + 1; + if (input_cycle_count_to_sync2 == input_cycles_per_clk2) + begin + clk2_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk2; + last_synchronizing_rising_edge_for_clk2 = $realtime; + schedule_clk2 = 1; + input_cycle_count_to_sync2 = 0; + end + input_cycle_count_to_sync_extclk = input_cycle_count_to_sync_extclk + 1; + if (input_cycle_count_to_sync_extclk == input_cycles_per_extclk) + begin + extclk_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_extclk; + last_synchronizing_rising_edge_for_extclk = $realtime; + schedule_extclk = 1; + input_cycle_count_to_sync_extclk = 0; + end + end + else + begin + if (!dev.IS_FAMILY_APEXII(intended_device_family) || (pll_rising_edge_count-1 > 0)) + begin + start_lock_count = start_lock_count + 1; + if (start_lock_count >= valid_lock_cycles) + begin + pll_lock = 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 = actual_clk_cycle * input_cycles_per_clk0; + clk1_synchronizing_period = actual_clk_cycle * input_cycles_per_clk1; + clk2_synchronizing_period = actual_clk_cycle * input_cycles_per_clk2; + extclk_synchronizing_period = actual_clk_cycle * input_cycles_per_extclk; + last_synchronizing_rising_edge_for_clk0 = $realtime; + last_synchronizing_rising_edge_for_clk1 = $realtime; + last_synchronizing_rising_edge_for_clk2 = $realtime; + last_synchronizing_rising_edge_for_extclk = $realtime; + schedule_clk0 = 1; + schedule_clk1 = 1; + schedule_clk2 = 1; + schedule_extclk = 1; + end + end + end + end + else + if(dev.IS_FAMILY_APEXII(intended_device_family)) + start_lock_count = 0; + else + start_lock_count = 1; + end + else if ((inclock == 1'b0) && (clk_last_value !== inclock)) + begin + if (pll_lock == 1) + begin + next_clk_check = 1; + if (($realtime - pll_last_rising_edge) < (pll_duty_cycle - clk_per_tolerance/2) || + ($realtime - pll_last_rising_edge) > (pll_duty_cycle + clk_per_tolerance/2)) + begin + $display($realtime, "ps Warning: Duty Cycle Violation"); + violation = 1; + if (locked == 1'b1) + begin + stop_lock_count = stop_lock_count + 1; + if (stop_lock_count == invalid_lock_cycles) + begin + pll_lock = 0; + $display ($realtime, "ps Warning: altclklock out of lock."); + + if(dev.IS_FAMILY_APEX20KE(intended_device_family) || dev.IS_FAMILY_APEX20KC(intended_device_family) || dev.IS_FAMILY_EXCALIBUR_ARM(intended_device_family)) + start_lock_count = 0; + else + start_lock_count = 1; + + stop_lock_count = 0; + clk0_tmp = 1'bx; + clk1_tmp = 1'bx; + clk2_tmp = 1'bx; + extclk_tmp = 1'bx; + end + end + end + else + violation = 0; + end + else if (!dev.IS_FAMILY_APEXII(intended_device_family) || (pll_rising_edge_count > 0)) + start_lock_count = start_lock_count + 1; + pll_last_falling_edge = $realtime; + end + else if (pll_lock == 1) + begin + if (inclock == 1'b1) + expected_next_clk_edge = pll_last_rising_edge + (inclk_period+clk_per_tolerance)/2; + else if (inclock == 'b0) + expected_next_clk_edge = pll_last_falling_edge + (inclk_period+clk_per_tolerance)/2; + else + expected_next_clk_edge = 0; + violation = 0; + if ($realtime < expected_next_clk_edge) + next_clk_check = 2; + else if ($realtime == expected_next_clk_edge) + next_clk_check = 1; + else + begin + $display($realtime, "ps Warning: Inclock_Period Violation"); + violation = 1; + + if (locked == 1'b1) + begin + stop_lock_count = stop_lock_count + 1; + expected_next_clk_edge = $realtime + (inclk_period/2); + if (stop_lock_count == invalid_lock_cycles) + begin + pll_lock = 0; + $display ($realtime, "ps Warning: altclklock out of lock."); + + if(dev.IS_FAMILY_APEX20KE(intended_device_family) || dev.IS_FAMILY_APEX20KC(intended_device_family) || dev.IS_FAMILY_EXCALIBUR_ARM(intended_device_family)) + start_lock_count = 0; + else + start_lock_count = 1; + + stop_lock_count = 0; + clk0_tmp = 1'bx; + clk1_tmp = 1'bx; + clk2_tmp = 1'bx; + extclk_tmp = 1'bx; + end + else + next_clk_check = 2; + end + end + end + clk_last_value = inclock; +end + +// clock0 output +always @(posedge schedule_clk0) +begin + // initialise variables + inc0 = 1; + cycle_to_adjust0 = 0; + output_value0 = 1'b1; + sched_time0 = 0; + rem0 = clk0_synchronizing_period % clk0_cycles_per_sync_period; + ori_per0 = clk0_synchronizing_period / clk0_cycles_per_sync_period; + + // schedule <clk0_cycles_per_sync_period> number of clock0 cycles in this + // loop - in order to synchronize the output clock always to the input clock + // to get rid of clock drift for cases where the input clock period is + // not evenly divisible + for (clk_cnt0 = 1; clk_cnt0 <= clk0_cycles_per_sync_period; + clk_cnt0 = clk_cnt0 + 1) + begin + tmp_per0 = ori_per0; + if ((rem0 != 0) && (inc0 <= rem0)) + begin + tmp_rem0 = (clk0_cycles_per_sync_period * inc0) % rem0; + cycle_to_adjust0 = (clk0_cycles_per_sync_period * inc0) / rem0; + if (tmp_rem0 != 0) + cycle_to_adjust0 = cycle_to_adjust0 + 1; + end + + // if this cycle is the one to adjust the output clock period, then + // increment the period by 1 unit + if (cycle_to_adjust0 == clk_cnt0) + begin + tmp_per0 = tmp_per0 + 1; + inc0 = inc0 + 1; + end + + // adjust the high and low cycle period + high_time0 = tmp_per0 / 2; + if ((tmp_per0 % 2) != 0) + high_time0 = high_time0 + 1; + + low_time0 = tmp_per0 - high_time0; + + // schedule the high and low cycle of 1 output clock period + for (cyc0 = 0; cyc0 <= 1; cyc0 = cyc0 + 1) + begin + // Avoid glitch in vcs when high_time0 and low_time0 is 0 + // (due to clk0_synchronizing_period is 0) + if (clk0_synchronizing_period != 0) + clk0_tmp = #(sched_time0) output_value0; + else + clk0_tmp = #(sched_time0) 1'b0; + output_value0 = ~output_value0; + if (output_value0 == 1'b0) + begin + sched_time0 = high_time0; + end + else if (output_value0 == 1'b1) + begin + sched_time0 = low_time0; + end + end + end + + // drop the schedule_clk0 to 0 so that the "always@(inclock)" block can + // trigger this block again when the correct time comes + schedule_clk0 = #1 1'b0; +end + +always @(clk0_tmp) +begin + if (clk0_phase_delay == 0) + clock0 <= clk0_tmp; + else + clock0 <= #(clk0_phase_delay) clk0_tmp; +end + +// clock1 output +always @(posedge schedule_clk1) +begin + // initialize variables + inc1 = 1; + cycle_to_adjust1 = 0; + output_value1 = 1'b1; + sched_time1 = 0; + rem1 = clk1_synchronizing_period % clk1_cycles_per_sync_period; + ori_per1 = clk1_synchronizing_period / clk1_cycles_per_sync_period; + + // schedule <clk1_cycles_per_sync_period> number of clock1 cycles in this + // loop - in order to synchronize the output clock always to the input clock, + // to get rid of clock drift for cases where the input clock period is + // not evenly divisible + for (clk_cnt1 = 1; clk_cnt1 <= clk1_cycles_per_sync_period; + clk_cnt1 = clk_cnt1 + 1) + begin + tmp_per1 = ori_per1; + if ((rem1 != 0) && (inc1 <= rem1)) + begin + tmp_rem1 = (clk1_cycles_per_sync_period * inc1) % rem1; + cycle_to_adjust1 = (clk1_cycles_per_sync_period * inc1) / rem1; + if (tmp_rem1 != 0) + cycle_to_adjust1 = cycle_to_adjust1 + 1; + end + + // if this cycle is the one to adjust the output clock period, then + // increment the period by 1 unit + if (cycle_to_adjust1 == clk_cnt1) + begin + tmp_per1 = tmp_per1 + 1; + inc1 = inc1 + 1; + end + + // adjust the high and low cycle period + high_time1 = tmp_per1 / 2; + if ((tmp_per1 % 2) != 0) + high_time1 = high_time1 + 1; + + low_time1 = tmp_per1 - high_time1; + + // schedule the high and low cycle of 1 output clock period + for (cyc1 = 0; cyc1 <= 1; cyc1 = cyc1 + 1) + begin + // Avoid glitch in vcs when high_time1 and low_time1 is 0 + // (due to clk1_synchronizing_period is 0) + if (clk1_synchronizing_period != 0) + clk1_tmp = #(sched_time1) output_value1; + else + clk1_tmp = #(sched_time1) 1'b0; + output_value1 = ~output_value1; + if (output_value1 == 1'b0) + sched_time1 = high_time1; + else if (output_value1 == 1'b1) + sched_time1 = low_time1; + end + end + // drop the schedule_clk1 to 0 so that the "always@(inclock)" block can + // trigger this block again when the correct time comes + schedule_clk1 = #1 1'b0; +end + +always @(clk1_tmp) +begin + if (clk1_phase_delay == 0) + clock1 <= clk1_tmp; + else + clock1 <= #(clk1_phase_delay) clk1_tmp; +end + +// clock2 output +always @(posedge schedule_clk2) +begin + // clock2 is only available for Mercury + if (dev.IS_FAMILY_MERCURY(intended_device_family)) + begin + // initialize variables + inc2 = 1; + cycle_to_adjust2 = 0; + output_value2 = 1'b1; + sched_time2 = 0; + rem2 = clk2_synchronizing_period % clk2_cycles_per_sync_period; + ori_per2 = clk2_synchronizing_period / clk2_cycles_per_sync_period; + + // schedule <clk2_cycles_per_sync_period> number of clock2 cycles in this + // loop - in order to synchronize the output clock always to the input clock, + // to get rid of clock drift for cases where the input clock period is + // not evenly divisible + for (clk_cnt2 = 1; clk_cnt2 <= clk2_cycles_per_sync_period; + clk_cnt2 = clk_cnt2 + 1) + begin + tmp_per2 = ori_per2; + if ((rem2 != 0) && (inc2 <= rem2)) + begin + tmp_rem2 = (clk2_cycles_per_sync_period * inc2) % rem2; + cycle_to_adjust2 = (clk2_cycles_per_sync_period * inc2) / rem2; + if (tmp_rem2 != 0) + cycle_to_adjust2 = cycle_to_adjust2 + 1; + end + + // if this cycle is the one to adjust the output clock period, then + // increment the period by 1 unit + if (cycle_to_adjust2 == clk_cnt2) + begin + tmp_per2 = tmp_per2 + 1; + inc2 = inc2 + 1; + end + + // adjust the high and low cycle period + high_time2 = tmp_per2 / 2; + if ((tmp_per2 % 2) != 0) + high_time2 = high_time2 + 1; + + low_time2 = tmp_per2 - high_time2; + + // schedule the high and low cycle of 1 output clock period + for (cyc2 = 0; cyc2 <= 1; cyc2 = cyc2 + 1) + begin + // Avoid glitch in vcs when high_time2 and low_time2 is 0 + // (due to clk2_synchronizing_period is 0) + if (clk2_synchronizing_period != 0) + clk2_tmp = #(sched_time2) output_value2; + else + clk2_tmp = #(sched_time2) 1'b0; + output_value2 = ~output_value2; + if (output_value2 == 1'b0) + sched_time2 = high_time2; + else if (output_value2 == 1'b1) + sched_time2 = low_time2; + end + end + // drop the schedule_clk2 to 0 so that the "always@(inclock)" block can + // trigger this block again when the correct time comes + schedule_clk2 = #1 1'b0; + end +end + +always @(clk2_tmp) +begin + if (clk2_phase_delay == 0) + clock2 <= clk2_tmp; + else + clock2 <= #(clk2_phase_delay) clk2_tmp; +end + +// clock_ext output +always @(posedge schedule_extclk) +begin + // clock_ext is only available for Mercury + if (dev.IS_FAMILY_MERCURY(intended_device_family)) + begin + // initialize variables + inc_ext = 1; + cycle_to_adjust_ext = 0; + output_value_ext = 1'b1; + sched_time_ext = 0; + rem_ext = extclk_synchronizing_period % extclk_cycles_per_sync_period; + ori_per_ext = extclk_synchronizing_period/extclk_cycles_per_sync_period; + + // schedule <extclk_cycles_per_sync_period> number of clock_ext cycles in this + // loop - in order to synchronize the output clock always to the input clock, + // to get rid of clock drift for cases where the input clock period is + // not evenly divisible + for (clk_cnt_ext = 1; clk_cnt_ext <= extclk_cycles_per_sync_period; + clk_cnt_ext = clk_cnt_ext + 1) + begin + tmp_per_ext = ori_per_ext; + if ((rem_ext != 0) && (inc_ext <= rem_ext)) + begin + tmp_rem_ext = (extclk_cycles_per_sync_period * inc_ext) % rem_ext; + cycle_to_adjust_ext = (extclk_cycles_per_sync_period * inc_ext) / rem_ext; + if (tmp_rem_ext != 0) + cycle_to_adjust_ext = cycle_to_adjust_ext + 1; + end + + // if this cycle is the one to adjust the output clock period, then + // increment the period by 1 unit + if (cycle_to_adjust_ext == clk_cnt_ext) + begin + tmp_per_ext = tmp_per_ext + 1; + inc_ext = inc_ext + 1; + end + + // adjust the high and low cycle period + high_time_ext = tmp_per_ext/2; + if ((tmp_per_ext % 2) != 0) + high_time_ext = high_time_ext + 1; + + low_time_ext = tmp_per_ext - high_time_ext; + + // schedule the high and low cycle of 1 output clock period + for (cyc_ext = 0; cyc_ext <= 1; cyc_ext = cyc_ext + 1) + begin + // Avoid glitch in vcs when high_time_ext and low_time_ext is 0 + // (due to extclk_synchronizing_period is 0) + if (extclk_synchronizing_period != 0) + extclk_tmp = #(sched_time_ext) output_value_ext; + else + extclk_tmp = #(sched_time_ext) 1'b0; + output_value_ext = ~output_value_ext; + if (output_value_ext == 1'b0) + sched_time_ext = high_time_ext; + else if (output_value_ext == 1'b1) + sched_time_ext = low_time_ext; + end + end + // drop the schedule_extclk to 0 so that the "always@(inclock)" block + // can trigger this block again when the correct time comes + schedule_extclk = #1 1'b0; + end +end + +always @(extclk_tmp) +begin + if (extclk_phase_delay == 0) + clock_ext <= extclk_tmp; + else + clock_ext <= #(extclk_phase_delay) extclk_tmp; +end + +// ACCELERATE OUTPUTS +buf (locked, pll_lock); + +endmodule // altclklock +// END OF MODULE ALTCLKLOCK + +// START MODULE NAME ----------------------------------------------------------- +// +// Module Name : ALTDDIO_IN +// +// Description : Double Data Rate (DDR) input behavioural model. Receives +// data on both edges of the reference clock. +// +// Limitations : Not available for FLEX, MAX, APEX20K and APEX20KE 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 MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module altddio_in ( + datain, // required port, DDR input data + inclock, // required port, input reference clock to sample data by + inclocken, // enable data clock + aset, // asynchronous set + aclr, // asynchronous clear + dataout_h, // data sampled at the rising edge of inclock + dataout_l // data sampled at the falling edge of inclock +); + +// GLOBAL PARAMETER DECLARATION +parameter width = 1; // required parameter +parameter power_up_high = "OFF"; +parameter invert_input_clocks = "OFF"; +parameter intended_device_family = "MERCURY"; +parameter lpm_type = "altddio_in"; +parameter lpm_hint = "UNUSED"; + +// INPUT PORT DECLARATION +input [width-1:0] datain; +input inclock; +input inclocken; +input aset; +input aclr; + +// OUTPUT PORT DECLARATION +output [width-1:0] dataout_h; +output [width-1:0] dataout_l; + +// REGISTER AND VARIABLE DECLARATION +reg [width-1:0] dataout_h_tmp; +reg [width-1:0] dataout_l_tmp; +reg [width-1:0] datain_latched; + +ALTERA_DEVICE_FAMILIES dev (); + +// pulldown/pullup +tri0 aset; // default aset to 0 +tri0 aclr; // default aclr to 0 +tri1 inclocken; // default inclocken to 1 + +// INITIAL BLOCK +initial +begin + + // Begin of parameter checking + if (width <= 0) + begin + $display("ERROR: The width parameter must be greater than 0"); + $stop; + end + + if (dev.IS_VALID_FAMILY(intended_device_family) == 0) + begin + $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family); + $stop; + end + + if (!(dev.IS_FAMILY_MERCURY(intended_device_family) || + dev.IS_FAMILY_APEXII(intended_device_family) || + dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family) || + dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family))) + begin + $display("ERROR: Megafunction altddio_out is not supported in %s.", intended_device_family); + $stop; + end + // End of parameter checking + + // if power_up_high parameter is turned on, registers power up + // to '1', otherwise '0' + dataout_h_tmp = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}}; + dataout_l_tmp = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}}; + datain_latched = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}}; +end + +// input reference clock, sample data +always @ (posedge inclock or posedge aclr or posedge aset) +begin + if (aclr) + begin + dataout_h_tmp <= {width{1'b0}}; + dataout_l_tmp <= {width{1'b0}}; + end + else if (aset) + begin + dataout_h_tmp <= {width{1'b1}}; + dataout_l_tmp <= {width{1'b1}}; + end + // if not being set or cleared + else if (inclocken == 1'b1) + begin + if (invert_input_clocks == "ON") + datain_latched <= datain; + else + begin + dataout_h_tmp <= datain; + dataout_l_tmp <= datain_latched; + end + end +end + +always @ (negedge inclock or posedge aclr or posedge aset) +begin + if (aclr) + begin + datain_latched <= {width{1'b0}}; + end + else if (aset) + begin + datain_latched <= {width{1'b1}}; + end + // if not being set or cleared + else + begin + if (dev.IS_FAMILY_APEXII(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family) || + dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)) + begin + if (inclocken == 1'b1) + if (invert_input_clocks == "ON") + begin + dataout_h_tmp <= datain; + dataout_l_tmp <= datain_latched; + end + else + datain_latched <= datain; + + end + else if (dev.IS_FAMILY_MERCURY(intended_device_family)) + begin + if (invert_input_clocks == "ON") + begin + dataout_h_tmp <= datain; + dataout_l_tmp <= datain_latched; + end + else + datain_latched <= datain; + end + else + begin + if (invert_input_clocks == "ON") + begin + dataout_h_tmp <= datain; + dataout_l_tmp <= datain_latched; + end + else + datain_latched <= datain; + end + end +end + +// assign registers to output ports +assign dataout_l = dataout_l_tmp; +assign dataout_h = dataout_h_tmp; + +endmodule // altddio_in +// END MODULE ALTDDIO_IN + +// START MODULE NAME ----------------------------------------------------------- +// +// Module Name : ALTDDIO_OUT +// +// Description : Double Data Rate (DDR) output behavioural model. +// Transmits data on both edges of the reference clock. +// +// Limitations : Not available for FLEX, MAX, APEX20K and APEX20KE device +// families. +// +// Expected results : Double data rate output on dataout. +// +//END MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module altddio_out ( + datain_h, // required port, data input for the rising edge of outclock + datain_l, // required port, data input for the falling edge of outclock + outclock, // required port, input reference clock to output data by + outclocken, // clock enable signal for outclock + aset, // asynchronous set + aclr, // asynchronous clear + oe, // output enable for dataout + dataout // DDR data output +); + +// GLOBAL PARAMETER DECLARATION +parameter width = 1; // required parameter +parameter power_up_high = "OFF"; +parameter oe_reg = "UNUSED"; +parameter extend_oe_disable = "UNUSED"; +parameter intended_device_family = "MERCURY"; +parameter invert_output = "OFF"; +parameter lpm_type = "altddio_out"; +parameter lpm_hint = "UNUSED"; + +// INPUT PORT DECLARATION +input [width-1:0] datain_h; +input [width-1:0] datain_l; +input outclock; +input outclocken; +input aset; +input aclr; +input oe; + +// OUTPUT PORT DECLARATION +output [width-1:0] dataout; + +// REGISTER, NET AND VARIABLE DECLARATION +wire apexii_oe; +wire output_enable; +reg oe_rgd; +reg oe_reg_ext; +reg [width-1:0] dataout; +reg [width-1:0] dataout_h; +reg [width-1:0] dataout_l; +reg [width-1:0] dataout_tmp; + +ALTERA_DEVICE_FAMILIES dev (); + +// pulldown/pullup +tri0 aset; // default aset to 0 +tri0 aclr; // default aclr to 0 +tri1 outclocken; // default outclocken to 1 +tri1 oe; // default oe to 1 + +// INITIAL BLOCK +initial +begin + // Begin of parameter checking + if (width <= 0) + begin + $display("ERROR: The width parameter must be greater than 0"); + $stop; + end + + if (dev.IS_VALID_FAMILY(intended_device_family) == 0) + begin + $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family); + $stop; + end + + if (!(dev.IS_FAMILY_MERCURY(intended_device_family) || + dev.IS_FAMILY_APEXII(intended_device_family) || + dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family) || + dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family))) + begin + $display("ERROR: Megafunction altddio_out is not supported in %s.", intended_device_family); + $stop; + end + // End of parameter checking + + // if power_up_high parameter is turned on, registers power up to '1' + // else to '0' + dataout_h = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}}; + dataout_l = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}}; + dataout_tmp = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}}; + + if (power_up_high == "ON") + begin + oe_rgd = 1'b1; + oe_reg_ext = 1'b1; + end + else + begin + oe_rgd = 1'b0; + oe_reg_ext = 1'b0; + end +end + + +// input reference clock +always @ (posedge outclock or posedge aclr or posedge aset) +begin + if (aclr) + begin + dataout_h <= {width{1'b0}}; + dataout_l <= {width{1'b0}}; + dataout_tmp <= {width{1'b0}}; + + oe_rgd <= 1'b0; + end + else if (aset) + begin + dataout_h <= {width{1'b1}}; + dataout_l <= {width{1'b1}}; + dataout_tmp <= {width{1'b1}}; + + oe_rgd <= 1'b1; + end + // if clock is enabled + else if (outclocken == 1'b1) + begin + dataout_h <= datain_h; + dataout_l <= datain_l; + dataout_tmp <= datain_h; + + // register the output enable signal + oe_rgd <= oe; + end + else + dataout_tmp <= dataout_h; + +end + +// input reference clock +always @ (negedge outclock or posedge aclr or posedge aset) +begin + if (aclr) + begin + oe_reg_ext <= 1'b0; + end + else if (aset) + begin + oe_reg_ext <= 1'b1; + end + // if not being set or cleared + else + begin + // if clock is enabled + if (outclocken == 1'b1) + begin + // additional register for output enable signal + oe_reg_ext <= oe_rgd; + end + + dataout_tmp <= dataout_l; + end +end + +// data output +always @(dataout_tmp or output_enable) +begin + // if output is enabled + if (output_enable == 1'b1) + begin + if (dev.FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO(intended_device_family) && + (invert_output == "ON")) + dataout = ~dataout_tmp; + else + dataout = dataout_tmp; + end + else // output is disabled + dataout = {width{1'bZ}}; +end + +// output enable signal +// Mercury does not support extend_oe_disable and oe_reg parameters +assign output_enable = (dev.IS_FAMILY_APEXII(intended_device_family) || + dev.IS_FAMILY_STRATIX(intended_device_family)|| + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family) || + dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)) + ? apexii_oe + : oe; + +assign apexii_oe = (extend_oe_disable == "ON") + ? (oe_reg_ext & oe_rgd) + : ((oe_reg == "REGISTERED") && (extend_oe_disable != "ON")) + ? oe_rgd + : oe; + +endmodule // altddio_out +// END MODULE ALTDDIO_OUT + +// START MODULE NAME ----------------------------------------------------------- +// +// Module 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 FLEX, MAX, APEX20K and APEX20KE 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 MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module altddio_bidir ( + datain_h, // required port, input data to be output of padio port at the + // rising edge of outclock + datain_l, // required port, input data to be output of padio port at the + // falling edge of outclock + inclock, // required port, input reference clock to sample data by + inclocken, // inclock enable + outclock, // required port, input reference clock to register data output + outclocken, // outclock enable + aset, // asynchronour set + aclr, // asynchronous clear + oe, // output enable for padio port + dataout_h, // data sampled from the padio port at the rising edge of inclock + dataout_l, // data sampled from the padio port at the falling edge of + // inclock + combout, // combinatorial output directly fed by padio + dqsundelayedout, // undelayed DQS signal to the PLD core + padio // bidirectional DDR port +); + +// GLOBAL PARAMETER DECLARATION +parameter width = 1; // required parameter +parameter power_up_high = "OFF"; +parameter oe_reg = "UNUSED"; +parameter extend_oe_disable = "UNUSED"; +parameter implement_input_in_lcell = "UNUSED"; +parameter invert_output = "OFF"; +parameter intended_device_family = "MERCURY"; +parameter lpm_type = "altddio_bidir"; +parameter lpm_hint = "UNUSED"; + +// INPUT PORT DECLARATION +input [width-1:0] datain_h; +input [width-1:0] datain_l; +input inclock; +input inclocken; +input outclock; +input outclocken; +input aset; +input aclr; +input oe; + +// OUTPUT PORT DECLARATION +output [width-1:0] dataout_h; +output [width-1:0] dataout_l; +output [width-1:0] combout; +output [width-1:0] dqsundelayedout; +// BIDIRECTIONAL PORT DECLARATION +inout [width-1:0] padio; + +// pulldown/pullup +tri0 inclock; +tri0 aset; +tri0 aclr; +tri1 outclocken; +tri1 inclocken; +tri1 oe; + +// INITIAL BLOCK +initial +begin + + // Begin of parameter checking + if (width <= 0) + begin + $display("ERROR: The width parameter must be greater than 0"); + $stop; + end + // End of parameter checking + +end + +// COMPONENT INSTANTIATION +// ALTDDIO_IN +altddio_in u1 ( + .datain(padio), + .inclock(inclock), + .inclocken(inclocken), + .aset(aset), + .aclr(aclr), + .dataout_h(dataout_h), + .dataout_l(dataout_l) +); +defparam u1.width = width, + u1.intended_device_family = intended_device_family, + u1.power_up_high = power_up_high; + +// ALTDDIO_OUT +altddio_out u2 ( + .datain_h(datain_h), + .datain_l(datain_l), + .outclock(outclock), + .oe(oe), + .outclocken(outclocken), + .aset(aset), + .aclr(aclr), + .dataout(padio) +); +defparam u2.width = width, + u2.power_up_high = power_up_high, + u2.intended_device_family = intended_device_family, + u2.oe_reg = oe_reg, + u2.extend_oe_disable = extend_oe_disable, + u2.invert_output = invert_output; + +// padio feeds combout port directly +assign combout = padio; +assign dqsundelayedout = padio; +endmodule // altddio_bidir +// END MODULE ALTDDIO_BIDIR + +// START MODULE NAME ----------------------------------------------------------- +// +// Module Name : HSSI_PLL +// +// Description : This is the Phase Locked Loop (PLL) model used by altcdr_rx +// and altcdr_tx. Simple PLL model with 1 clock input (clk) and +// 2 clock outputs (clk0 & clk1). +// +// Limitations : Only capable of multiplying and dividing the input clock +// frequency. There is no support for phase shifts, uneven duty +// cycles or other fancy PLL features, since the Mercury CDR +// does not need these features. +// +// Expected results : 2 output clocks - clk0 and clk1. Locked output indicates +// when the PLL locks. +// +//END MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module hssi_pll ( + clk, // input clock + areset, // asynchronous reset + clk0, // output clock0 + clk1, // output clock1 + locked // PLL lock signal +); + +// GLOBAL PARAMETER DECLARATION +parameter clk0_multiply_by = 1; +parameter clk1_divide_by = 1; +parameter input_frequency = 1000; // period in ps + +// INPUT PORT DECLARATION +input clk; +input areset; + +// OUTPUT PORT DECLARATION +output clk0; +output clk1; +output locked; + +// INTERNAL SIGNAL/REGISTER DECLARATION +reg start_outclk; +reg clk0_tmp; +reg clk1_tmp; +reg clk0; +reg clk1; +reg pll_lock; +reg clk_last_value; +reg violation; +reg clk_check; +reg [1:0] next_clk_check; +wire clk_in; + +// INTERNAL VARIABLE DECLARATION +real pll_last_rising_edge; +real pll_last_falling_edge; +real actual_clk_cycle; +real expected_clk_cycle; +real pll_duty_cycle; +real inclk_period; +real clk0_period; +real clk1_period; +real expected_next_clk_edge; + +integer pll_rising_edge_count; +integer stop_lock_count; +integer start_lock_count; +integer first_clk0_cycle; +integer first_clk1_cycle; +integer lock_on_rise; +integer lock_on_fall; +integer clk_per_tolerance; +integer lock_low; +integer lock_high; + +// variables for clock synchronizing +integer last_synchronizing_rising_edge_for_clk0; +integer last_synchronizing_rising_edge_for_clk1; +integer clk0_synchronizing_period; +integer clk1_synchronizing_period; +reg schedule_clk0; +reg schedule_clk1; +reg output_value0; +reg output_value1; + +integer input_cycles_per_clk0; +integer input_cycles_per_clk1; +integer clk0_cycles_per_sync_period; +integer clk1_cycles_per_sync_period; +integer input_cycle_count_to_sync0; +integer input_cycle_count_to_sync1; + +integer sched_time0; +integer sched_time1; +integer rem0; +integer rem1; +integer tmp_rem0; +integer tmp_rem1; +integer i0; +integer i1; +integer j0; +integer j1; +integer l0; +integer l1; +integer cycle_to_adjust0; +integer cycle_to_adjust1; +integer tmp_per0; +integer tmp_per1; +integer high_time0; +integer high_time1; +integer low_time0; +integer low_time1; + +buf (clk_in, clk); + +initial +begin + pll_rising_edge_count = 0; + pll_lock = 1'b0; + stop_lock_count = 0; + start_lock_count = 0; + clk_last_value = clk_in; + first_clk0_cycle = 1; + first_clk1_cycle = 1; + violation = 0; + lock_on_rise = 0; + lock_on_fall = 0; + pll_last_rising_edge = 0; + pll_last_falling_edge = 0; + lock_low = 2; + lock_high = 2; + clk_check = 0; + + last_synchronizing_rising_edge_for_clk0 = 0; + last_synchronizing_rising_edge_for_clk1 = 0; + clk0_synchronizing_period = 0; + clk1_synchronizing_period = 0; + schedule_clk0 = 0; + schedule_clk1 = 0; + input_cycles_per_clk0 = 1; + input_cycles_per_clk1 = clk1_divide_by; + clk0_cycles_per_sync_period = clk0_multiply_by; + clk1_cycles_per_sync_period = clk0_multiply_by; + input_cycle_count_to_sync0 = 0; + input_cycle_count_to_sync1 = 0; + l0 = 1; + l1 = 1; + cycle_to_adjust0 = 0; + cycle_to_adjust1 = 0; +end + +// trigger input clock checking for the purpose of detecting an input clock that +// has flatlined or that violates the specified input frequency or 50% duty +// cycle - with tolerance +always @(next_clk_check) +begin + if (next_clk_check == 1) + begin + #((inclk_period+clk_per_tolerance)/2) clk_check = ~clk_check; + end + else if (next_clk_check == 2) + begin + #(expected_next_clk_edge - $realtime) clk_check = ~clk_check; + end + next_clk_check = 0; +end + +// same as initial block +// reset all variables, registers and signals on positive edge of areset +always @(posedge areset) +begin + pll_rising_edge_count = 0; + pll_lock = 1'b0; + stop_lock_count = 0; + start_lock_count = 1; + clk_last_value = 0; + first_clk0_cycle = 1; + first_clk1_cycle = 1; + clk0_tmp = 1'bx; + clk1_tmp = 1'bx; + violation = 0; + lock_on_rise = 0; + lock_on_fall = 0; + pll_last_rising_edge = 0; + pll_last_falling_edge = 0; + lock_low = 1; + lock_high = 2; +end + +// on change of input clock or clock check trigger, +// monitor for duty cycle/input frequency violation +// schedule clk0 and clk1 output, handles the PLL locking +always @(clk_in or clk_check) +begin + if (areset !== 1'b1) + begin + // rising edge of the clock + if ((clk_in === 1'b1) && (clk_last_value !== clk_in)) + begin + if (pll_lock === 1'b1) + next_clk_check = 1; + if (pll_rising_edge_count == 0) // this is first rising edge + begin + inclk_period = input_frequency; + pll_duty_cycle = inclk_period/2; + clk_per_tolerance = 0.025 * inclk_period; + + clk0_period = inclk_period / clk0_multiply_by; + clk1_period = inclk_period / clk0_multiply_by * clk1_divide_by; + start_outclk = 0; + pll_last_rising_edge = $realtime; + end + else if (pll_rising_edge_count == 1) // this is second rising edge + begin + expected_clk_cycle = inclk_period; + actual_clk_cycle = $realtime - pll_last_rising_edge; + + // input frequency violation check + if (actual_clk_cycle < (expected_clk_cycle - clk_per_tolerance) || + actual_clk_cycle > (expected_clk_cycle + clk_per_tolerance)) + begin + $display($realtime, "Warning: Input frequency Violation"); + violation = 1; + if (locked === 1'b1) + begin + stop_lock_count = stop_lock_count + 1; + // PLL breaks its lock + if ((locked === 1'b1) && (stop_lock_count == lock_low)) + begin + pll_lock = 1'b0; + start_lock_count = 1; + stop_lock_count = 0; + clk0_tmp = 1'bx; + clk1_tmp = 1'bx; + end + end + end + else + begin + // Duty cycle violation check + if (($realtime - pll_last_falling_edge) < (pll_duty_cycle - (clk_per_tolerance/2)) || + ($realtime - pll_last_falling_edge) > (pll_duty_cycle + (clk_per_tolerance/2))) + begin + $display($realtime, "Warning: Duty Cycle Violation"); + violation = 1; + end + else + violation = 0; + end + end + // input frequency violation check + else if (($realtime - pll_last_rising_edge) < (expected_clk_cycle - clk_per_tolerance) || + ($realtime - pll_last_rising_edge) > (expected_clk_cycle + clk_per_tolerance)) + begin + $display($realtime, "Warning: Cycle Violation"); + violation = 1; + if (locked === 1'b1) + begin + stop_lock_count = stop_lock_count + 1; + // PLL breaks its lock + if (stop_lock_count == lock_low) + begin + pll_lock = 1'b0; + start_lock_count = 1; + stop_lock_count = 0; + clk0_tmp = 1'bx; + clk1_tmp = 1'bx; + end + end + end + else begin + violation = 0; + actual_clk_cycle = $realtime - pll_last_rising_edge; + end + pll_last_rising_edge = $realtime; + pll_rising_edge_count = pll_rising_edge_count + 1; + + // if no violation is detected, schedule clk0 and clk1 + if (!violation) + begin + if (pll_lock === 1'b1) + begin + input_cycle_count_to_sync0 = input_cycle_count_to_sync0 + 1; + if (input_cycle_count_to_sync0 == input_cycles_per_clk0) + begin + clk0_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk0; + last_synchronizing_rising_edge_for_clk0 = $realtime; + schedule_clk0 = 1; + input_cycle_count_to_sync0 = 0; + end + + input_cycle_count_to_sync1 = input_cycle_count_to_sync1 + 1; + if (input_cycle_count_to_sync1 == input_cycles_per_clk1) + begin + clk1_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk1; + last_synchronizing_rising_edge_for_clk1 = $realtime; + schedule_clk1 = 1; + input_cycle_count_to_sync1 = 0; + end + end + else begin + start_lock_count = start_lock_count + 1; + if (start_lock_count >= (lock_high + 1)) + begin + pll_lock = 1'b1; + input_cycle_count_to_sync0 = 0; + input_cycle_count_to_sync1 = 0; + lock_on_rise = 1; + if (last_synchronizing_rising_edge_for_clk0 == 0) + begin + clk0_synchronizing_period = actual_clk_cycle; + end + else + clk0_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk0; + + if (last_synchronizing_rising_edge_for_clk1 == 0) + clk1_synchronizing_period = actual_clk_cycle * clk1_divide_by; + else + clk1_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk1; + + last_synchronizing_rising_edge_for_clk0 = $realtime; + last_synchronizing_rising_edge_for_clk1 = $realtime; + schedule_clk0 = 1; + schedule_clk1 = 1; + end + end + end + else + start_lock_count = 1; + end + // falling edge of input clock + else if ((clk_in === 1'b0) && (clk_last_value !== clk_in)) + begin + if (pll_lock === 1'b1) + begin + next_clk_check = 1; + if (($realtime - pll_last_rising_edge) < (pll_duty_cycle - (clk_per_tolerance/2)) || + ($realtime - pll_last_rising_edge) > (pll_duty_cycle + (clk_per_tolerance/2))) + begin + $display($realtime, "Warning: Duty Cycle Violation"); + violation = 1; + if (locked === 1'b1) + begin + stop_lock_count = stop_lock_count + 1; + if (stop_lock_count == lock_low) + begin + pll_lock = 1'b0; + start_lock_count = 1; + stop_lock_count = 0; + clk0_tmp = 1'bx; + clk1_tmp = 1'bx; + end + end + end + else + violation = 0; + end + else + start_lock_count = start_lock_count + 1; + + pll_last_falling_edge = $realtime; + end + else if (pll_lock === 1'b1) // perform clock check + begin + if (clk_in === 1'b1) + expected_next_clk_edge = pll_last_rising_edge + ((inclk_period+clk_per_tolerance)/2); + else if (clk_in === 1'b0) + expected_next_clk_edge = pll_last_falling_edge + ((inclk_period+clk_per_tolerance)/2); + else + expected_next_clk_edge = 0; + + violation = 0; + if ($realtime < expected_next_clk_edge) + next_clk_check = 2; + else if ($realtime == expected_next_clk_edge) + next_clk_check = 1; + else + begin + $display($realtime, "Warning: Input frequency Violation"); + violation = 1; + if (locked === 1'b1) + begin + stop_lock_count = stop_lock_count + 1; + expected_next_clk_edge = $realtime + (inclk_period/2); + // PLL breaks its lock + if (stop_lock_count == lock_low) + begin + pll_lock = 1'b0; + start_lock_count = 1; + stop_lock_count = 0; + clk0_tmp = 1'bx; + clk1_tmp = 1'bx; + end + else + next_clk_check = 2; + end + end + end + clk_last_value = clk_in; + end +end + +// schedule clk0 output +always @(posedge schedule_clk0) +begin + l0 = 1; + cycle_to_adjust0 = 0; + output_value0 = 1'b1; + sched_time0 = 0; + rem0 = clk0_synchronizing_period % clk0_cycles_per_sync_period; + for (i0 = 1; i0 <= clk0_cycles_per_sync_period; i0 = i0 + 1) + begin + tmp_per0 = clk0_synchronizing_period/clk0_cycles_per_sync_period; + if (rem0 != 0 && l0 <= rem0) + begin + tmp_rem0 = (clk0_cycles_per_sync_period * l0) % rem0; + cycle_to_adjust0 = (clk0_cycles_per_sync_period * l0) / rem0; + if (tmp_rem0 != 0) + cycle_to_adjust0 = cycle_to_adjust0 + 1; + end + if (cycle_to_adjust0 == i0) + begin + tmp_per0 = tmp_per0 + 1; + l0 = l0 + 1; + end + high_time0 = tmp_per0/2; + if (tmp_per0 % 2 != 0) + high_time0 = high_time0 + 1; + low_time0 = tmp_per0 - high_time0; + for (j0 = 0; j0 <= 1; j0 = j0 + 1) + begin + clk0_tmp = #(sched_time0) output_value0; + output_value0 = ~output_value0; + if (output_value0 === 1'b0) + sched_time0 = high_time0; + else if (output_value0 === 1'b1) + sched_time0 = low_time0; + end + end + schedule_clk0 = #1 1'b0; +end + +always @(clk0_tmp) +begin + clk0 <= clk0_tmp; +end + +// schedule clk1 output +always @(posedge schedule_clk1) +begin + l1 = 1; + cycle_to_adjust1 = 0; + output_value1 = 1'b1; + sched_time1 = 0; + rem1 = clk1_synchronizing_period % clk1_cycles_per_sync_period; + for (i1 = 1; i1 <= clk1_cycles_per_sync_period; i1 = i1 + 1) + begin + tmp_per1 = clk1_synchronizing_period/clk1_cycles_per_sync_period; + if (rem1 != 0 && l1 <= rem1) + begin + tmp_rem1 = (clk1_cycles_per_sync_period * l1) % rem1; + cycle_to_adjust1 = (clk1_cycles_per_sync_period * l1) / rem1; + if (tmp_rem1 != 0) + cycle_to_adjust1 = cycle_to_adjust1 + 1; + end + if (cycle_to_adjust1 == i1) + begin + tmp_per1 = tmp_per1 + 1; + l1 = l1 + 1; + end + high_time1 = tmp_per1/2; + if (tmp_per1 % 2 != 0) + high_time1 = high_time1 + 1; + low_time1 = tmp_per1 - high_time1; + for (j1 = 0; j1 <= 1; j1 = j1 + 1) + begin + clk1_tmp = #(sched_time1) output_value1; + output_value1 = ~output_value1; + if (output_value1 === 1'b0) + sched_time1 = high_time1; + else if (output_value1 === 1'b1) + sched_time1 = low_time1; + end + end + schedule_clk1 <= #1 1'b0; +end + +always @(clk1_tmp) +begin + clk1 <= clk1_tmp; +end + +buf (locked, pll_lock); + +endmodule // hssi_pll + + +// START MODULE NAME ----------------------------------------------------------- +// +// Module Name : MF_RAM7X20_SYN +// +// Description : This is the RAM model used by HSSI_FIFO for writing and reading +// into the FIFO +// +// Limitations : Reading from the RAM is address-triggered, +// writing is clock-triggered +// RAM depth is fixed to 7, maximum width is 20 +// +// Expected results : data output from the RAM +// +//END MODULE NAME -------------------------------------------------------------- + +`timescale 1ps / 1ps + +module MF_ram7x20_syn ( + wclk, // write clock + rst_l, // active low asynchronous reset + addr_wr, // write address + addr_rd, // read address + data_in, // data input to the RAM + we, // write enable + re, // read enable + data_out // data output from the RAM +); + +// GLOBAL PARAMETER DECLARATION +parameter ram_width = 20; + +// INPUT PORT DECLARATION +input wclk; +input rst_l; // active low +input [2:0] addr_wr; +input [2:0] addr_rd; +input [19:0] data_in; +input we; +input re; + +// OUTPUT PORT DECLARATION +output [19:0] data_out; + +// INTERNAL REGISTER/SIGNAL DECLARATION +reg [ram_width-1:0] data_out_i; +reg [ram_width-1:0] ram_array_d_0, ram_array_d_1, ram_array_d_2, + ram_array_d_3, ram_array_d_4, ram_array_d_5, + ram_array_d_6, + ram_array_q_0, ram_array_q_1, ram_array_q_2, + ram_array_q_3, ram_array_q_4, ram_array_q_5, + ram_array_q_6; +wire [ram_width-1:0] data_reg_0, data_reg_1, data_reg_2, + data_reg_3, data_reg_4, data_reg_5, data_reg_6; + +// Modelling the read port +// Assuming address triggered operation only +assign + data_reg_0 = ( addr_wr == 3'b000 ) ? data_in : ram_array_q_0, + data_reg_1 = ( addr_wr == 3'b001 ) ? data_in : ram_array_q_1, + data_reg_2 = ( addr_wr == 3'b010 ) ? data_in : ram_array_q_2, + data_reg_3 = ( addr_wr == 3'b011 ) ? data_in : ram_array_q_3, + data_reg_4 = ( addr_wr == 3'b100 ) ? data_in : ram_array_q_4, + data_reg_5 = ( addr_wr == 3'b101 ) ? data_in : ram_array_q_5, + data_reg_6 = ( addr_wr == 3'b110 ) ? data_in : ram_array_q_6; + +assign data_out = re ? data_out_i : 20'b0; + +always @(ram_array_q_0 or ram_array_q_1 or + ram_array_q_2 or ram_array_q_3 or + ram_array_q_4 or ram_array_q_5 or + ram_array_q_6 or addr_rd or we or addr_wr) +begin + case ( addr_rd ) + 3'b000 : data_out_i = ram_array_q_0; + 3'b001 : data_out_i = ram_array_q_1; + 3'b010 : data_out_i = ram_array_q_2; + 3'b011 : data_out_i = ram_array_q_3; + 3'b100 : data_out_i = ram_array_q_4; + 3'b101 : data_out_i = ram_array_q_5; + 3'b110 : data_out_i = ram_array_q_6; + default: data_out_i = data_out_i; + endcase +end + +// Modelling the write port +always @(posedge wclk or negedge rst_l) +begin + if(~rst_l) // reset + begin + ram_array_q_0 <= 0; + ram_array_q_1 <= 0; + ram_array_q_2 <= 0; + ram_array_q_3 <= 0; + ram_array_q_4 <= 0; + ram_array_q_5 <= 0; + ram_array_q_6 <= 0; + end + else + begin + ram_array_q_0 <= ram_array_d_0; + ram_array_q_1 <= ram_array_d_1; + ram_array_q_2 <= ram_array_d_2; + ram_array_q_3 <= ram_array_d_3; + ram_array_q_4 <= ram_array_d_4; + ram_array_q_5 <= ram_array_d_5; + ram_array_q_6 <= ram_array_d_6; + end +end + +always @(we or + data_reg_0 or data_reg_1 or + data_reg_2 or data_reg_3 or + data_reg_4 or data_reg_5 or + data_reg_6 or + ram_array_q_0 or ram_array_q_1 or + ram_array_q_2 or ram_array_q_3 or + ram_array_q_4 or ram_array_q_5 or + ram_array_q_6) + begin + if (we) // write enabled + begin + ram_array_d_0 <= data_reg_0; + ram_array_d_1 <= data_reg_1; + ram_array_d_2 <= data_reg_2; + ram_array_d_3 <= data_reg_3; + ram_array_d_4 <= data_reg_4; + ram_array_d_5 <= data_reg_5; + ram_array_d_6 <= data_reg_6; + end + else + begin + ram_array_d_0 <= ram_array_q_0; + ram_array_d_1 <= ram_array_q_1; + ram_array_d_2 <= ram_array_q_2; + ram_array_d_3 <= ram_array_q_3; + ram_array_d_4 <= ram_array_q_4; + ram_array_d_5 <= ram_array_q_5; + ram_array_d_6 <= ram_array_q_6; + end +end + +endmodule // MF_ram7x20_syn + + +// START MODULE NAME ----------------------------------------------------------- +// +// Module Name : HSSI_FIFO +// +// Description : The FIFO model used by altcdr_rx and altcdr_tx to synchronize +// data between 2 clock domains +// +// Limitations : FIFO depth is limited to 7 words only, +// the overflow and empty signals are active low in this model +// +// Expected results : data read from the FIFO, empty and overflow signals +// (active low) to indicate when FIFO is empty or full +// +//END MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1 ps +`define CNTBIT 3 // 3 bit counter for FIFO read/write addresses + +module hssi_fifo ( + datain, // data input to the FIFO + clk0, // FIFO write clock + clk1, // FIFO read clock + we, // FIFO write enable + re, // FIFO read enable + reset, // FIFO asynchronous reset + dataout, // data output from the FIFO + empty, // active low FIFO empty signal + overflow // active low FIFO full signal +); + +// GLOBAL PARAMETER DECLARATION +parameter channel_width = 1; + +// INPUT PORT DECLARATION +input [channel_width-1:0] datain; +input clk0; +input clk1; +input we; +input re; +input reset; + +// OUTPUT PORT DECLARATION +output [channel_width-1:0] dataout; +output empty; +output overflow; + +// INTERNAL REGISTER/SIGNAL DECLARATION +wire [19:0] ram_dataout; +wire [19:0] data_out; +reg [19:0] ram_datain; +reg [19:0] dataout_tmp; +wire clk0_in; +wire clk1_in; +wire we_in; +wire re_in; +wire reset_in; + +// The following are for asynchronous fifo use +reg [`CNTBIT-1:0] wrPtr0; // write pointer synchronizer +reg [`CNTBIT-1:0] wrPtr1; // write pointer synchronizer +reg [`CNTBIT-1:0] wrPtr2; // write pointer synchronizer +reg [`CNTBIT-1:0] wrPtr,rdPtr; // writer pointer, read pointer +reg [`CNTBIT-1:0] wrAddr; // writer address +reg [`CNTBIT-1:0] preRdPtr,preRdPtr1,preRdPtr2; +wire [`CNTBIT-1:0] rdAddr = rdPtr; // read address +reg ram_we; // we for ram + +// Empty/Full checking +wire fullFlag = (wrPtr0 == preRdPtr2)? 1 : 0; +wire emptyFlag = (rdPtr == wrPtr2 && fullFlag == 'b0)? 1: 0; +wire overflow_tmp_b; +wire empty_tmp_b = !emptyFlag; + +// pullup/pulldown +tri1 we, re; +tri0 reset; + +integer i; + +buf (clk0_in, clk0); +buf (clk1_in, clk1); +buf (we_in, we); +buf (re_in, re); +buf (reset_in, reset); + +assign overflow_tmp_b = (reset_in)? 1'b0 : !fullFlag; + +// instantiate the 7x20 RAM for reading and writing data +MF_ram7x20_syn ram_7x20_syn( + .wclk (clk0_in), + .rst_l (!reset_in), + .addr_wr (wrAddr), + .addr_rd (rdAddr), + .data_in (ram_datain), + .we (ram_we), + .re (re && empty_tmp_b), + .data_out (ram_dataout) +); +defparam ram_7x20_syn.ram_width = channel_width; + +// initialize the FIFO read and write pointers +initial +begin + dataout_tmp = 20'b0; + for (i = 0; i < `CNTBIT; i = i + 1) + begin + wrPtr0[i] = 1'b0; + wrPtr1[i] = 1'b0; + wrPtr2[i] = 1'b0; + wrPtr[i] = 1'b0; + rdPtr[i] = 1'b0; + preRdPtr[i] = 1'b0; + preRdPtr1[i] = 1'b0; + preRdPtr2[i] = 1'b0; + end + preRdPtr1 = 6; + preRdPtr2 = 6; +end + +// output data on postive edge of read clock (clk1) +always @(posedge clk1_in or posedge reset_in ) +begin + if (reset_in === 1'b1) + dataout_tmp <= 0; + else if ((re_in === 1'b1) && (empty_tmp_b === 1'b1)) + dataout_tmp <= ram_dataout; // memory output latch + else + dataout_tmp <= dataout_tmp; +end + +// Update the write pointer and send input data to the RAM +// Delay the write pointer update until we have given the RAM the +// write strobe. This prevents the not empty flag from going true +// before the data actually makes it safely into the RAM +always @(posedge clk0_in or posedge reset_in) +begin + if(reset_in === 1'b1) // reset + begin + wrAddr <= 0; + ram_datain <= 20'b0; + wrPtr0 <= 0; + end + else if ((we_in === 1'b1) && (overflow_tmp_b === 1'b1)) + begin + ram_datain <= datain; + wrAddr <= wrPtr0; // wrLow for memory + wrPtr0 <= wrPtr0 + 1; + if (wrPtr0 == 6) + wrPtr0 <= 0; + end + else + begin + wrAddr <= wrAddr; + ram_datain <= ram_datain; + wrPtr0 <= wrPtr0; + end +end + +// write pointer +always @(posedge clk0_in or posedge reset_in) +begin + if(reset_in === 1'b1) + wrPtr <= 0; + else + wrPtr <= wrPtr0; +end + +// write enable +always @(posedge clk0_in or posedge reset_in) +begin + if (reset_in === 1'b1) + ram_we <= 1'b0; + else if ((we_in === 1'b1) && (overflow_tmp_b === 1'b1)) + ram_we <= 1'b1; + else + ram_we <= 1'b0; +end + +// update read pointer +always @(posedge clk1_in or posedge reset_in) +begin + if(reset_in === 1'b1) + begin + rdPtr <= 0; + preRdPtr <= 0; + end + else if ((re_in === 1'b1) && (empty_tmp_b === 1'b1)) + begin + rdPtr <= rdPtr + 1; + if (rdPtr == 6) + rdPtr <= 0; + preRdPtr <= rdPtr; + end +end + +// the following lines are for async. fifo. +always @(posedge clk1_in or posedge reset_in) +begin + if (reset_in === 1'b1) + begin + wrPtr1 <= 0; + wrPtr2 <= 0; + end + else + begin + wrPtr1 <= wrPtr; // sync. wrPtr to read clock + wrPtr2 <= wrPtr1; + end +end + +always @(posedge clk0_in or posedge reset_in) +begin + if (reset_in === 1'b1) + begin + preRdPtr1 <= 6; + preRdPtr2 <= 6; + end + else + begin + preRdPtr1 <= preRdPtr; // sync. RdPtr to write clock + preRdPtr2 <= preRdPtr1; + end +end + +assign dataout = dataout_tmp; + +and (empty, empty_tmp_b, 1'b1); +and (overflow, overflow_tmp_b, 1'b1); + +endmodule // hssi_fifo + + +// START MODULE NAME ----------------------------------------------------------- +// +// Module Name : HSSI_RX +// +// Description : This is the receiver model used by altcdr_rx. Performs +// deserialization of input data. +// +// Limitations : Assumes that the clock is already perfectly synchronized to the +// incoming data +// +// Expected results: data output from the deserializer, slow clock (clkout) +// generated by the RX, run length violation flag (rlv), and +// locked output to indicate when the RX has failed to lock +// onto the input data signal (not simulated) +// +//END MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +module hssi_rx ( + clk, // fast clock + coreclk, // slow (core) clock + datain, // data input to the RX + areset, // asynchronous reset + feedback,// data feedback port + fbkcntl, // feedback control port + dataout, // data output from the RX + clkout, // slow clock generated by the RX + rlv, // run length violation flag + locked // RX lost of lock indicator +); + +// GLOBAL PARAMETER DECLARATION +parameter channel_width = 1; +parameter operation_mode = "CDR"; +parameter run_length = 1; + +// INPUT PORT DECLARATION +input clk; +input coreclk; +input datain; +input areset; +input feedback; +input fbkcntl; + +// OUTPUT PORT DECLARATION +output [channel_width-1:0] dataout; +output clkout; +output rlv; +output locked; + +// INTERNAL VARIABLE/SIGNAL/REGISTER DECLARATION +integer i; +integer clk_count; +integer rlv_count; +reg clk_last_value; +reg coreclk_last_value; +reg clkout_last_value; +reg [channel_width-1:0] deser_data_arr; +reg clkout_tmp; +reg rlv_tmp; +reg locked_tmp; +reg rlv_flag; +reg rlv_set; +reg [19:0] dataout_tmp; +reg datain_in; +reg last_datain; +reg data_changed; +wire [19:0] data_out; +wire clk_in; +wire coreclk_in; +wire datain_buf; +wire fbin_in; +wire fbena_in; +wire areset_in; + +// pulldown +tri0 areset, feedback, fbkcntl; + +buf (clk_in, clk); +buf (coreclk_in, coreclk); +buf (datain_buf, datain); +buf (fbin_in, feedback); +buf (fbena_in, fbkcntl); +buf (areset_in, areset); + +initial +begin + i = 0; + rlv_count = 0; + clk_count = channel_width; + clk_last_value = 0; + coreclk_last_value = 0; + clkout_tmp = 1'b0; + rlv_tmp = 1'b0; + rlv_flag = 1'b0; + rlv_set = 1'b0; + locked_tmp = 1'b0; + dataout_tmp = 20'b0; + last_datain = 1'bx; + data_changed = 1'b0; +end + +// deserialize incoming data, generate clkout and check for run length violation +always @(clk_in or coreclk_in or areset_in or fbena_in) +begin + if (areset_in === 1'b1) // reset + begin + rlv_set = 1'b0; + dataout_tmp = 20'b0; + clkout_tmp = 1'b0; + rlv_tmp = 1'b0; + rlv_flag = 1'b0; + last_datain = 1'bx; + rlv_count = 0; + data_changed = 1'b0; + clk_count = channel_width; + for (i = channel_width - 1; i >= 0; i = i - 1) + deser_data_arr[i] = 1'b0; + end + else + begin + if (fbena_in === 1'b1) + datain_in = fbin_in; + else + datain_in = datain_buf; + if ((clk_in === 1'b1) && (clk_last_value !== clk_in)) + begin + if (clk_count == channel_width) + begin + clk_count = 0; + clkout_tmp = !clkout_last_value; + end + else if (clk_count == (channel_width+1)/2) + clkout_tmp = !clkout_last_value; + else if (clk_count < channel_width) + clkout_tmp = clkout_last_value; + clk_count = clk_count + 1; + + //rlv (run length violation) checking + if (operation_mode == "CDR") + begin + if (last_datain !== datain_in) + begin + data_changed = 1'b1; + last_datain = datain_in; + end + else // data not changed - increment rlv_count + begin + rlv_count = rlv_count + 1; + data_changed = 1'b0; + end + + if (rlv_count > run_length) + begin + rlv_flag = 1'b1; + rlv_set = 1'b1; + end + else + rlv_set = 1'b0; + + if (data_changed) + rlv_count = 1; + end + end + if ((coreclk_in === 1'b1) && (coreclk_last_value !== coreclk_in)) + begin + // output the rlv status with the rising edge of the coreclk + if (operation_mode == "CDR") + begin + if (rlv_flag === 1'b1) + begin + rlv_tmp = 1'b1; + if (rlv_set === 1'b0) + rlv_flag = 1'b0; + end + else + rlv_tmp = 1'b0; + end + end + + // deserialize the data + if ((clk_in === 1'b0) && (clk_last_value !== clk_in)) + begin + if ((clk_count == 3)) + dataout_tmp[channel_width-1:0] = deser_data_arr; + + for (i = channel_width - 1; i >= 1; i = i - 1) + deser_data_arr[i] = deser_data_arr[i-1]; + + deser_data_arr[0] = datain_in; + end + end + clk_last_value = clk_in; + coreclk_last_value = coreclk_in; + clkout_last_value = clkout_tmp; +end + +assign dataout = dataout_tmp; + +and (rlv, rlv_tmp, 1'b1); +and (locked, locked_tmp, 1'b1); +and (clkout, clkout_tmp, 1'b1); + +endmodule // hssi_rx + +// START MODULE NAME ----------------------------------------------------------- +// +// Module Name : HSSI_TX +// +// Description : The transmitter module used by altcdr_tx. Performs +// serialization of output data. +// +// Limitations : +// +// Expected results : Serial data output (dataout) and generated slow clock +// (clkout) +// +//END MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module hssi_tx ( + clk, // fast clock + datain, // parallel input data + areset, // asynchronous reset + dataout, // serial data output + clkout // generated clock +); + +// GLOBAL PARAMETER DECLARATION +parameter channel_width = 1; + +// INPUT PORT DECLARATION +input clk; +input [channel_width-1:0] datain; +input areset; + +// OUTPUT PORT DECLARATION +output dataout; +output clkout; + +// INTERNAL VARIABLE/REGISTER DECLARATION +integer i; +integer fast_clk_count; +reg clk_in_last_value; +reg dataout_tmp; +reg clkout_last_value; +reg clkout_tmp; +reg [19:0] indata; +reg [19:0] regdata; +wire clk_in; +wire areset_in; + +buf (clk_in, clk); +buf (areset_in, areset); + +initial +begin + i = 0; + fast_clk_count = channel_width; + clk_in_last_value = 0; + dataout_tmp = 1'b0; + clkout_last_value = 0; + clkout_tmp = 0; +end + +always @(clk_in or areset_in) +begin + // reset logic + if (areset_in == 1'b1) + begin + dataout_tmp = 1'b0; + clkout_tmp = 1'b0; + fast_clk_count = channel_width; + for (i = channel_width-1; i >= 0; i = i - 1) // resets register + indata[i] = 1'b0; + for (i = channel_width-1; i >= 0; i = i - 1) // resets register + regdata[i] = 1'b0; + end + else // serialize incoming parallel data and generate slow clock + begin + // rising edge of fast clock + if ((clk_in === 1'b1) && (clk_in_last_value !== clk_in)) + begin + // slow clock generation + if (fast_clk_count == channel_width) + begin + fast_clk_count = 0; + clkout_tmp = !clkout_last_value; + end + else if (fast_clk_count == (channel_width+1)/2) + clkout_tmp = !clkout_last_value; + else if (fast_clk_count < channel_width) + clkout_tmp = clkout_last_value; + + fast_clk_count = fast_clk_count + 1; + + // 3rd rising edge, start to shift out + if (fast_clk_count == 3) + begin + for (i = channel_width-1; i >= 0; i = i - 1) + regdata[i] = indata[i]; + end + + // send the MSB of regdata out + dataout_tmp = regdata[channel_width-1]; + // shift data up + for (i = channel_width-1; i > 0; i = i - 1) + regdata[i] = regdata[i-1]; + end + // falling edge of fast clock + if ((clk_in === 1'b0) && (clk_in_last_value !== clk_in)) + begin + if (fast_clk_count == 3) // loading at the 3rd falling edge + begin + indata = datain; + end + end + end + clk_in_last_value = clk_in; + clkout_last_value = clkout_tmp; +end + +and (dataout, dataout_tmp, 1'b1); +and (clkout, clkout_tmp, 1'b1); + +endmodule // hssi_tx + +// START MODULE NAME ----------------------------------------------------------- +// +// Module Name : ALTCDR_RX +// +// Description : Clock Data Recovery (CDR) Receiver behavioral model. Consists +// of CDR receiver for deserialization, a Phase Locked Loop (PLL) +// and FIFO. +// +// Limitations : Available for the Mercury device family only +// +// Expected results : Deserialized data output (rx_out), recovered global data +// clock (rx_outclock), PLL lock signal, RX lost of lock signal, +// RX run length violation signal, RX FIFO full and empty +// signals (active high), recovered clock per channel +// (rx_rec_clk) +// +//END MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module altcdr_rx ( + rx_in, // required port, data input + rx_inclock, // required port, input reference clock + rx_coreclock, // required port, core clock + rx_aclr, // asynchronous reset for the RX and FIFO + rx_pll_aclr, // asynchronous reset for the PLL + rx_fifo_rden, // FIFO read enable + rx_out, // data output + rx_outclock, // global clock recovered from channel 0 + rx_pll_locked,// PLL lock signal + rx_locklost, // RX lock of lost wrt input data + rx_rlv, // data run length violation flag + rx_full, // FIFO full signal + rx_empty, // FIFO empty signal + rx_rec_clk // recovered clock from each channel +); + +// GLOBAL PARAMETER DECLARATION +parameter number_of_channels = 1; +parameter deserialization_factor = 3; // Valid deserialization_factor +parameter inclock_period = 20000; // 20000ps = 50MHz +parameter inclock_boost = 1; +parameter run_length = 62; // default based on SONET requirements +parameter bypass_fifo = "OFF"; +parameter intended_device_family = "MERCURY"; +parameter lpm_type = "altcdr_rx"; +parameter lpm_hint = "UNUSED"; + +// Constant Declaration + +parameter RUN_LENGTH_MAX = 62; // Mercury Max.Run Length + + +// INPUT PORT DECLARATION +input [number_of_channels-1:0] rx_in; +input rx_inclock; +input rx_coreclock; +input rx_aclr; +input rx_pll_aclr; +input [number_of_channels-1:0] rx_fifo_rden; + +// OUTPUT PORT DECLARATION +output [deserialization_factor*number_of_channels-1:0] rx_out; +output rx_outclock; +output rx_pll_locked; +output [number_of_channels-1:0] rx_locklost; +output [number_of_channels-1:0] rx_rlv; +output [number_of_channels-1:0] rx_full; +output [number_of_channels-1:0] rx_empty; +output [number_of_channels-1:0] rx_rec_clk; + +// INTERNAL SIGNAL/VARIABLE DECLARATION +wire w_rx_inclk0; +wire [17:0] i_rx_full; +wire [17:0] i_rx_empty; +wire [17:0] i_rx_locked; +wire [17:0] w_rx_clkout; +wire [17:0] i_rx_rlv; +wire i_pll_locked; +wire [deserialization_factor-1:0] w_rx_out00; +wire [deserialization_factor-1:0] w_rx_out01; +wire [deserialization_factor-1:0] w_rx_out02; +wire [deserialization_factor-1:0] w_rx_out03; +wire [deserialization_factor-1:0] w_rx_out04; +wire [deserialization_factor-1:0] w_rx_out05; +wire [deserialization_factor-1:0] w_rx_out06; +wire [deserialization_factor-1:0] w_rx_out07; +wire [deserialization_factor-1:0] w_rx_out08; +wire [deserialization_factor-1:0] w_rx_out09; +wire [deserialization_factor-1:0] w_rx_out10; +wire [deserialization_factor-1:0] w_rx_out11; +wire [deserialization_factor-1:0] w_rx_out12; +wire [deserialization_factor-1:0] w_rx_out13; +wire [deserialization_factor-1:0] w_rx_out14; +wire [deserialization_factor-1:0] w_rx_out15; +wire [deserialization_factor-1:0] w_rx_out16; +wire [deserialization_factor-1:0] w_rx_out17; +wire [deserialization_factor-1:0] i_fifo_out00; +wire [deserialization_factor-1:0] i_fifo_out01; +wire [deserialization_factor-1:0] i_fifo_out02; +wire [deserialization_factor-1:0] i_fifo_out03; +wire [deserialization_factor-1:0] i_fifo_out04; +wire [deserialization_factor-1:0] i_fifo_out05; +wire [deserialization_factor-1:0] i_fifo_out06; +wire [deserialization_factor-1:0] i_fifo_out07; +wire [deserialization_factor-1:0] i_fifo_out08; +wire [deserialization_factor-1:0] i_fifo_out09; +wire [deserialization_factor-1:0] i_fifo_out10; +wire [deserialization_factor-1:0] i_fifo_out11; +wire [deserialization_factor-1:0] i_fifo_out12; +wire [deserialization_factor-1:0] i_fifo_out13; +wire [deserialization_factor-1:0] i_fifo_out14; +wire [deserialization_factor-1:0] i_fifo_out15; +wire [deserialization_factor-1:0] i_fifo_out16; +wire [deserialization_factor-1:0] i_fifo_out17; + +tri0 [17:0] i_rx_in; +wire [deserialization_factor*18-1:0] i_rx_out; +wire [deserialization_factor*18-1:0] i_w_rx_out; + +supply0 gnd; +supply1 vcc; + +integer i; + +// pullup/pulldown +// Default values for inputs +tri0 rx_aclr_pulldown, rx_aclr; +tri0 rx_pll_aclr_pulldown, rx_pll_aclr; +tri1 [17:0] rx_fifo_rden_pullup; + +// INITIAL BLOCK +initial +begin + + // Begin of parameter checking + if (number_of_channels <= 0) + begin + $display("ERROR: The number_of_channels parameter must be greater than 0"); + $stop; + end + + if (run_length > RUN_LENGTH_MAX) + begin + $display("ERROR: The run_length parameter must be greater than %d", RUN_LENGTH_MAX); + $stop; + end + + if (!(((deserialization_factor >= 3 ) && (deserialization_factor <= 12)) || + (deserialization_factor == 14) || (deserialization_factor == 16) || + (deserialization_factor == 18) || (deserialization_factor == 20))) + begin + $display("ERROR: Illegal value for deserialization_factor parameter (%d) -- value ", deserialization_factor); + $display(" must be in the range 3 to 12, inclusive, or must be one of 14, 16, 18, or 20"); + $stop; + end + + + // End of parameter checking + +end + + +assign rx_aclr_pulldown = rx_aclr; +assign rx_pll_aclr_pulldown = rx_pll_aclr; +assign rx_fifo_rden_pullup = rx_fifo_rden; + + //----------------------------------------------------------------------- + // Instantiate the HSSI_RX to deserialize data - maximum of 18 channels + hssi_rx rx00 ( + .datain (i_rx_in[00]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[00]), + .dataout (w_rx_out00), .clkout (w_rx_clkout[00]), .rlv (i_rx_rlv[00]) ); + defparam + rx00.channel_width = deserialization_factor, + rx00.operation_mode = "CDR", + rx00.run_length = run_length; + + hssi_rx rx01 ( + .datain (i_rx_in[01]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[01]), + .dataout (w_rx_out01), .clkout (w_rx_clkout[01]), .rlv (i_rx_rlv[01]) ); + defparam + rx01.channel_width = deserialization_factor, + rx01.operation_mode = "CDR", + rx01.run_length = run_length; + + hssi_rx rx02 ( + .datain (i_rx_in[02]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[02]), + .dataout (w_rx_out02), .clkout (w_rx_clkout[02]), .rlv (i_rx_rlv[02]) ); + defparam + rx02.channel_width = deserialization_factor, + rx02.operation_mode = "CDR", + rx02.run_length = run_length; + + hssi_rx rx03 ( + .datain (i_rx_in[03]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[03]), + .dataout (w_rx_out03), .clkout (w_rx_clkout[03]), .rlv (i_rx_rlv[03]) ); + defparam + rx03.channel_width = deserialization_factor, + rx03.operation_mode = "CDR", + rx03.run_length = run_length; + + hssi_rx rx04 ( + .datain (i_rx_in[04]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[04]), + .dataout (w_rx_out04), .clkout (w_rx_clkout[04]), .rlv (i_rx_rlv[04]) ); + defparam + rx04.channel_width = deserialization_factor, + rx04.operation_mode = "CDR", + rx04.run_length = run_length; + + hssi_rx rx05 ( + .datain (i_rx_in[05]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[05]), + .dataout (w_rx_out05), .clkout (w_rx_clkout[05]), .rlv (i_rx_rlv[05]) ); + defparam + rx05.channel_width = deserialization_factor, + rx05.operation_mode = "CDR", + rx05.run_length = run_length; + + hssi_rx rx06 ( + .datain (i_rx_in[06]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[06]), + .dataout (w_rx_out06), .clkout (w_rx_clkout[06]), .rlv (i_rx_rlv[06]) ); + defparam + rx06.channel_width = deserialization_factor, + rx06.operation_mode = "CDR", + rx06.run_length = run_length; + + hssi_rx rx07 ( + .datain (i_rx_in[07]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[07]), + .dataout (w_rx_out07), .clkout (w_rx_clkout[07]), .rlv (i_rx_rlv[07]) ); + defparam + rx07.channel_width = deserialization_factor, + rx07.operation_mode = "CDR", + rx07.run_length = run_length; + + hssi_rx rx08 ( + .datain (i_rx_in[08]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[08]), + .dataout (w_rx_out08), .clkout (w_rx_clkout[08]), .rlv (i_rx_rlv[08]) ); + defparam + rx08.channel_width = deserialization_factor, + rx08.operation_mode = "CDR", + rx08.run_length = run_length; + + hssi_rx rx09 ( + .datain (i_rx_in[09]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[09]), + .dataout (w_rx_out09), .clkout (w_rx_clkout[09]), .rlv (i_rx_rlv[09]) ); + defparam + rx09.channel_width = deserialization_factor, + rx09.operation_mode = "CDR", + rx09.run_length = run_length; + + hssi_rx rx10 ( + .datain (i_rx_in[10]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[10]), + .dataout (w_rx_out10), .clkout (w_rx_clkout[10]), .rlv (i_rx_rlv[10]) ); + defparam + rx10.channel_width = deserialization_factor, + rx10.operation_mode = "CDR", + rx10.run_length = run_length; + + hssi_rx rx11 ( + .datain (i_rx_in[11]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[11]), + .dataout (w_rx_out11), .clkout (w_rx_clkout[11]), .rlv (i_rx_rlv[11]) ); + defparam + rx11.channel_width = deserialization_factor, + rx11.operation_mode = "CDR", + rx11.run_length = run_length; + + hssi_rx rx12 ( + .datain (i_rx_in[12]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[12]), + .dataout (w_rx_out12), .clkout (w_rx_clkout[12]), .rlv (i_rx_rlv[12]) ); + defparam + rx12.channel_width = deserialization_factor, + rx12.operation_mode = "CDR", + rx12.run_length = run_length; + + hssi_rx rx13 ( + .datain (i_rx_in[13]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[13]), + .dataout (w_rx_out13), .clkout (w_rx_clkout[13]), .rlv (i_rx_rlv[13]) ); + defparam + rx13.channel_width = deserialization_factor, + rx13.operation_mode = "CDR", + rx13.run_length = run_length; + + hssi_rx rx14 ( + .datain (i_rx_in[14]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[14]), + .dataout (w_rx_out14), .clkout (w_rx_clkout[14]), .rlv (i_rx_rlv[14]) ); + defparam + rx14.channel_width = deserialization_factor, + rx14.operation_mode = "CDR", + rx14.run_length = run_length; + + hssi_rx rx15 ( + .datain (i_rx_in[15]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[15]), + .dataout (w_rx_out15), .clkout (w_rx_clkout[15]), .rlv (i_rx_rlv[15]) ); + defparam + rx15.channel_width = deserialization_factor, + rx15.operation_mode = "CDR", + rx15.run_length = run_length; + + hssi_rx rx16 ( + .datain (i_rx_in[16]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[16]), + .dataout (w_rx_out16), .clkout (w_rx_clkout[16]), .rlv (i_rx_rlv[16]) ); + defparam + rx16.channel_width = deserialization_factor, + rx16.operation_mode = "CDR", + rx16.run_length = run_length; + + hssi_rx rx17 ( + .datain (i_rx_in[17]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown), + .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock), + .locked (i_rx_locked[17]), + .dataout (w_rx_out17), .clkout (w_rx_clkout[17]), .rlv (i_rx_rlv[17]) ); + defparam + rx17.channel_width = deserialization_factor, + rx17.operation_mode = "CDR", + rx17.run_length = run_length; + + + //---------------------------------------------------------- + // Instantiate HSSI_PLL - use the same PLL for all channels + + hssi_pll pll ( + .clk (rx_inclock), .areset (rx_pll_aclr_pulldown), + .clk0 (w_rx_inclk0), .clk1 (), .locked (i_pll_locked) ); + defparam + pll.clk0_multiply_by = inclock_boost, + pll.input_frequency = inclock_period; + + //---------------------------------------------------------- + // Instantiate HSSI_FIFOs + + hssi_fifo fifo00 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[00]), + .clk0 (w_rx_clkout[00]), .datain (w_rx_out00), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[00]), .empty (i_rx_empty[00]), + .dataout (i_fifo_out00) ); + defparam + fifo00.channel_width = deserialization_factor; + + hssi_fifo fifo01 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[01]), + .clk0 (w_rx_clkout[01]), .datain (w_rx_out01), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[01]), .empty (i_rx_empty[01]), + .dataout (i_fifo_out01) ); + defparam + fifo01.channel_width = deserialization_factor; + + hssi_fifo fifo02 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[02]), + .clk0 (w_rx_clkout[02]), .datain (w_rx_out02), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[02]), .empty (i_rx_empty[02]), + .dataout (i_fifo_out02) ); + defparam + fifo02.channel_width = deserialization_factor; + + hssi_fifo fifo03 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[03]), + .clk0 (w_rx_clkout[03]), .datain (w_rx_out03), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[03]), .empty (i_rx_empty[03]), + .dataout (i_fifo_out03) ); + defparam + fifo03.channel_width = deserialization_factor; + + hssi_fifo fifo04 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[04]), + .clk0 (w_rx_clkout[04]), .datain (w_rx_out04), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[04]), .empty (i_rx_empty[04]), + .dataout (i_fifo_out04) ); + defparam + fifo04.channel_width = deserialization_factor; + + hssi_fifo fifo05 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[05]), + .clk0 (w_rx_clkout[05]), .datain (w_rx_out05), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[05]), .empty (i_rx_empty[05]), + .dataout (i_fifo_out05) ); + defparam + fifo05.channel_width = deserialization_factor; + + hssi_fifo fifo06 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[06]), + .clk0 (w_rx_clkout[06]), .datain (w_rx_out06), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[06]), .empty (i_rx_empty[06]), + .dataout (i_fifo_out06) ); + defparam + fifo06.channel_width = deserialization_factor; + + hssi_fifo fifo07 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[07]), + .clk0 (w_rx_clkout[07]), .datain (w_rx_out07), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[07]), .empty (i_rx_empty[07]), + .dataout (i_fifo_out07) ); + defparam + fifo07.channel_width = deserialization_factor; + + hssi_fifo fifo08 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[08]), + .clk0 (w_rx_clkout[08]), .datain (w_rx_out08), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[08]), .empty (i_rx_empty[08]), + .dataout (i_fifo_out08) ); + defparam + fifo08.channel_width = deserialization_factor; + + hssi_fifo fifo09 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[09]), + .clk0 (w_rx_clkout[09]), .datain (w_rx_out09), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[09]), .empty (i_rx_empty[09]), + .dataout (i_fifo_out09) ); + defparam + fifo09.channel_width = deserialization_factor; + + hssi_fifo fifo10 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[10]), + .clk0 (w_rx_clkout[10]), .datain (w_rx_out10), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[10]), .empty (i_rx_empty[10]), + .dataout (i_fifo_out10) ); + defparam + fifo10.channel_width = deserialization_factor; + + hssi_fifo fifo11 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[11]), + .clk0 (w_rx_clkout[11]), .datain (w_rx_out11), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[11]), .empty (i_rx_empty[11]), + .dataout (i_fifo_out11) ); + defparam + fifo11.channel_width = deserialization_factor; + + hssi_fifo fifo12 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[12]), + .clk0 (w_rx_clkout[12]), .datain (w_rx_out12), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[12]), .empty (i_rx_empty[12]), + .dataout (i_fifo_out12) ); + defparam + fifo12.channel_width = deserialization_factor; + + hssi_fifo fifo13 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[13]), + .clk0 (w_rx_clkout[13]), .datain (w_rx_out13), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[13]), .empty (i_rx_empty[13]), + .dataout (i_fifo_out13) ); + defparam + fifo13.channel_width = deserialization_factor; + + hssi_fifo fifo14 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[14]), + .clk0 (w_rx_clkout[14]), .datain (w_rx_out14), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[14]), .empty (i_rx_empty[14]), + .dataout (i_fifo_out14) ); + defparam + fifo14.channel_width = deserialization_factor; + + hssi_fifo fifo15 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[15]), + .clk0 (w_rx_clkout[15]), .datain (w_rx_out15), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[15]), .empty (i_rx_empty[15]), + .dataout (i_fifo_out15) ); + defparam + fifo15.channel_width = deserialization_factor; + + hssi_fifo fifo16 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[16]), + .clk0 (w_rx_clkout[16]), .datain (w_rx_out16), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[16]), .empty (i_rx_empty[16]), + .dataout (i_fifo_out16) ); + defparam + fifo16.channel_width = deserialization_factor; + + hssi_fifo fifo17 ( + .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[17]), + .clk0 (w_rx_clkout[17]), .datain (w_rx_out17), + .we (vcc), .reset (rx_aclr_pulldown), + .overflow (i_rx_full[17]), .empty (i_rx_empty[17]), + .dataout (i_fifo_out17) ); + defparam + fifo17.channel_width = deserialization_factor; + + +//-------------------------- +// Inputs +assign i_rx_in[number_of_channels - 1 : 0] = rx_in[number_of_channels - 1 : 0]; + +//-------------------------- +// Outputs +// assign FIFO outputs to i_rx_out wire - for the case when FIFO is not bypassed +assign i_rx_out[01*deserialization_factor-1:00*deserialization_factor] + = i_fifo_out00; +assign i_rx_out[02*deserialization_factor-1:01*deserialization_factor] + = i_fifo_out01; +assign i_rx_out[03*deserialization_factor-1:02*deserialization_factor] + = i_fifo_out02; +assign i_rx_out[04*deserialization_factor-1:03*deserialization_factor] + = i_fifo_out03; +assign i_rx_out[05*deserialization_factor-1:04*deserialization_factor] + = i_fifo_out04; +assign i_rx_out[06*deserialization_factor-1:05*deserialization_factor] + = i_fifo_out05; +assign i_rx_out[07*deserialization_factor-1:06*deserialization_factor] + = i_fifo_out06; +assign i_rx_out[08*deserialization_factor-1:07*deserialization_factor] + = i_fifo_out07; +assign i_rx_out[09*deserialization_factor-1:08*deserialization_factor] + = i_fifo_out08; +assign i_rx_out[10*deserialization_factor-1:09*deserialization_factor] + = i_fifo_out09; +assign i_rx_out[11*deserialization_factor-1:10*deserialization_factor] + = i_fifo_out10; +assign i_rx_out[12*deserialization_factor-1:11*deserialization_factor] + = i_fifo_out11; +assign i_rx_out[13*deserialization_factor-1:12*deserialization_factor] + = i_fifo_out12; +assign i_rx_out[14*deserialization_factor-1:13*deserialization_factor] + = i_fifo_out13; +assign i_rx_out[15*deserialization_factor-1:14*deserialization_factor] + = i_fifo_out14; +assign i_rx_out[16*deserialization_factor-1:15*deserialization_factor] + = i_fifo_out15; +assign i_rx_out[17*deserialization_factor-1:16*deserialization_factor] + = i_fifo_out16; +assign i_rx_out[18*deserialization_factor-1:17*deserialization_factor] + = i_fifo_out17; + +// assign RX outputs to i_w_rx_out wire - for the case when FIFO is bypassed +assign i_w_rx_out[01*deserialization_factor-1:00*deserialization_factor] + = w_rx_out00; +assign i_w_rx_out[02*deserialization_factor-1:01*deserialization_factor] + = w_rx_out01; +assign i_w_rx_out[03*deserialization_factor-1:02*deserialization_factor] + = w_rx_out02; +assign i_w_rx_out[04*deserialization_factor-1:03*deserialization_factor] + = w_rx_out03; +assign i_w_rx_out[05*deserialization_factor-1:04*deserialization_factor] + = w_rx_out04; +assign i_w_rx_out[06*deserialization_factor-1:05*deserialization_factor] + = w_rx_out05; +assign i_w_rx_out[07*deserialization_factor-1:06*deserialization_factor] + = w_rx_out06; +assign i_w_rx_out[08*deserialization_factor-1:07*deserialization_factor] + = w_rx_out07; +assign i_w_rx_out[09*deserialization_factor-1:08*deserialization_factor] + = w_rx_out08; +assign i_w_rx_out[10*deserialization_factor-1:09*deserialization_factor] + = w_rx_out09; +assign i_w_rx_out[11*deserialization_factor-1:10*deserialization_factor] + = w_rx_out10; +assign i_w_rx_out[12*deserialization_factor-1:11*deserialization_factor] + = w_rx_out11; +assign i_w_rx_out[13*deserialization_factor-1:12*deserialization_factor] + = w_rx_out12; +assign i_w_rx_out[14*deserialization_factor-1:13*deserialization_factor] + = w_rx_out13; +assign i_w_rx_out[15*deserialization_factor-1:14*deserialization_factor] + = w_rx_out14; +assign i_w_rx_out[16*deserialization_factor-1:15*deserialization_factor] + = w_rx_out15; +assign i_w_rx_out[17*deserialization_factor-1:16*deserialization_factor] + = w_rx_out16; +assign i_w_rx_out[18*deserialization_factor-1:17*deserialization_factor] + = w_rx_out17; + +// assign the correct signals to the output ports +assign rx_out = (deserialization_factor == 1) ? rx_in : + (bypass_fifo == "OFF") ? i_rx_out[deserialization_factor*number_of_channels-1:0] : i_w_rx_out; +assign rx_outclock = (deserialization_factor > 1) ? w_rx_clkout[00] : rx_inclock; +assign rx_locklost = (deserialization_factor > 1) ? i_rx_locked[number_of_channels-1:0] : {(number_of_channels){1'b1}}; +assign rx_full = (deserialization_factor == 1) ? 0 : + (bypass_fifo == "OFF") ? ~ i_rx_full[number_of_channels-1:0] : {number_of_channels{1'bX}}; +assign rx_empty = (deserialization_factor == 1) ? 0 : + (bypass_fifo == "OFF") ? ~ i_rx_empty[number_of_channels-1:0] : {number_of_channels{1'bX}}; +assign rx_rlv = (deserialization_factor > 1) ? i_rx_rlv : 0; +assign rx_pll_locked = i_pll_locked; +assign rx_rec_clk = w_rx_clkout; + +endmodule // altcdr_rx + +// START MODULE NAME ----------------------------------------------------------- +// +// Module Name : ALTCDR_TX +// +// Description : The Clock Data Recovery (CDR) transmitter behavioral +// model. Consists of CDR transmitter for serialization, +// a PLL and FIFO. +// +// Limitations : Available for the Mercury device family only +// +// Expected results : Serial data output (tx_out), generated slow clock +// (tx_clkout), FIFO full signal (tx_full), FIFO empty signal +// (tx_empty), PLL lock signal (tx_pll_locked) +// +//END MODULE NAME -------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module altcdr_tx ( + tx_in, // required port, parallel data input + tx_inclock, // required port, input reference clock + tx_coreclock, // required port, input core clock + tx_aclr, // asynchronous clear for TX and FIFO + tx_pll_aclr, // asynchronous clear for the PLL + tx_fifo_wren, // write enable for the FIFO + tx_out, // serial data output + tx_outclock, // generated slow clock + tx_pll_locked, // PLL lock signal + tx_full, // FIFO full indicator + tx_empty // FIFO empty indicator +); + +// GLOBAL PARAMETER DECLARATION +parameter number_of_channels = 1; +parameter deserialization_factor = 3; // Valid deserialization_factor +parameter inclock_period = 0; // units in ps +parameter inclock_boost = 1; +parameter bypass_fifo = "OFF"; +parameter intended_device_family = "MERCURY"; +parameter lpm_type = "altcdr_tx"; +parameter lpm_hint = "UNUSED"; + +// LOCAL PARAMETER DECLARATION +parameter MAX_DATA_WIDTH = deserialization_factor - 1; + +// INPUT PORT DECLARATION +input [deserialization_factor*number_of_channels-1:0] tx_in; +input tx_inclock; +input tx_coreclock; +input tx_aclr; +input tx_pll_aclr; +input [number_of_channels-1:0] tx_fifo_wren; + +// OUTPUT PORT DECLARATION +output [number_of_channels-1:0] tx_out; +output tx_outclock; +output tx_pll_locked; +output [number_of_channels-1:0] tx_full; +output [number_of_channels-1:0] tx_empty; + +// Default values for inputs -- pullup/pulldown +tri0 tx_aclr_pulldown; +tri0 tx_pll_aclr_pulldown; +tri1 [17:0] tx_fifo_wren_pullup; + +// INTERNAL VARIABLE/REGISTER DECLARATION +wire w_tx_clk; +wire w_tx_clk1; +wire i_tx_pll_locked; +wire [17:0] i_tx_full; +wire [17:0] i_tx_empty; +wire [17:0] w_tx_out; +wire [17:0] w_tx_clkout; +wire [MAX_DATA_WIDTH:0] txin00; +wire [MAX_DATA_WIDTH:0] txin01; +wire [MAX_DATA_WIDTH:0] txin02; +wire [MAX_DATA_WIDTH:0] txin03; +wire [MAX_DATA_WIDTH:0] txin04; +wire [MAX_DATA_WIDTH:0] txin05; +wire [MAX_DATA_WIDTH:0] txin06; +wire [MAX_DATA_WIDTH:0] txin07; +wire [MAX_DATA_WIDTH:0] txin08; +wire [MAX_DATA_WIDTH:0] txin09; +wire [MAX_DATA_WIDTH:0] txin10; +wire [MAX_DATA_WIDTH:0] txin11; +wire [MAX_DATA_WIDTH:0] txin12; +wire [MAX_DATA_WIDTH:0] txin13; +wire [MAX_DATA_WIDTH:0] txin14; +wire [MAX_DATA_WIDTH:0] txin15; +wire [MAX_DATA_WIDTH:0] txin16; +wire [MAX_DATA_WIDTH:0] txin17; +wire [MAX_DATA_WIDTH:0] i_fifo_out00; +wire [MAX_DATA_WIDTH:0] i_fifo_out01; +wire [MAX_DATA_WIDTH:0] i_fifo_out02; +wire [MAX_DATA_WIDTH:0] i_fifo_out03; +wire [MAX_DATA_WIDTH:0] i_fifo_out04; +wire [MAX_DATA_WIDTH:0] i_fifo_out05; +wire [MAX_DATA_WIDTH:0] i_fifo_out06; +wire [MAX_DATA_WIDTH:0] i_fifo_out07; +wire [MAX_DATA_WIDTH:0] i_fifo_out08; +wire [MAX_DATA_WIDTH:0] i_fifo_out09; +wire [MAX_DATA_WIDTH:0] i_fifo_out10; +wire [MAX_DATA_WIDTH:0] i_fifo_out11; +wire [MAX_DATA_WIDTH:0] i_fifo_out12; +wire [MAX_DATA_WIDTH:0] i_fifo_out13; +wire [MAX_DATA_WIDTH:0] i_fifo_out14; +wire [MAX_DATA_WIDTH:0] i_fifo_out15; +wire [MAX_DATA_WIDTH:0] i_fifo_out16; +wire [MAX_DATA_WIDTH:0] i_fifo_out17; +wire [MAX_DATA_WIDTH:0] i_tx_in00; +wire [MAX_DATA_WIDTH:0] i_tx_in01; +wire [MAX_DATA_WIDTH:0] i_tx_in02; +wire [MAX_DATA_WIDTH:0] i_tx_in03; +wire [MAX_DATA_WIDTH:0] i_tx_in04; +wire [MAX_DATA_WIDTH:0] i_tx_in05; +wire [MAX_DATA_WIDTH:0] i_tx_in06; +wire [MAX_DATA_WIDTH:0] i_tx_in07; +wire [MAX_DATA_WIDTH:0] i_tx_in08; +wire [MAX_DATA_WIDTH:0] i_tx_in09; +wire [MAX_DATA_WIDTH:0] i_tx_in10; +wire [MAX_DATA_WIDTH:0] i_tx_in11; +wire [MAX_DATA_WIDTH:0] i_tx_in12; +wire [MAX_DATA_WIDTH:0] i_tx_in13; +wire [MAX_DATA_WIDTH:0] i_tx_in14; +wire [MAX_DATA_WIDTH:0] i_tx_in15; +wire [MAX_DATA_WIDTH:0] i_tx_in16; +wire [MAX_DATA_WIDTH:0] i_tx_in17; +wire [359:0] tx_in_int; // 360 = 18 channels * 20 bits (18=maximum number of channels, 20=maximum channel width) + +// INITIAL BLOCK +initial +begin + + // Begin of parameter checking + if (number_of_channels <= 0) + begin + $display("ERROR: The number_of_channels parameter must be greater than 0"); + $stop; + end + + if (!(((deserialization_factor >= 3 ) && (deserialization_factor <= 12)) || + (deserialization_factor == 14) || (deserialization_factor == 16) || + (deserialization_factor == 18) || (deserialization_factor == 20))) + begin + $display("ERROR: Illegal value for deserialization_factor parameter (%d) -- value ", deserialization_factor); + $display(" must be in the range 3 to 12, inclusive, or must be one of 14, 16, 18, or 20"); + $stop; + end + + + // End of parameter checking + +end + + + +assign tx_aclr_pulldown = tx_aclr; +assign tx_pll_aclr_pulldown = tx_pll_aclr; +assign tx_fifo_wren_pullup = tx_fifo_wren; + +// COMPONENT INSTANTIATION + + //------------------------------------------------------------- + // Instantiate HSSI_TX - maximum of 18 channels + hssi_tx tx00 ( + .datain (txin00), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[00]), .clkout (w_tx_clkout[00]) ); + defparam + tx00.channel_width = deserialization_factor; + + hssi_tx tx01 ( + .datain (txin01), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[01]), .clkout (w_tx_clkout[01]) ); + defparam + tx01.channel_width = deserialization_factor; + + hssi_tx tx02 ( + .datain (txin02), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[02]), .clkout (w_tx_clkout[02]) ); + defparam + tx02.channel_width = deserialization_factor; + + hssi_tx tx03 ( + .datain (txin03), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[03]), .clkout (w_tx_clkout[03]) ); + defparam + tx03.channel_width = deserialization_factor; + + hssi_tx tx04 ( + .datain (txin04), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[04]), .clkout (w_tx_clkout[04]) ); + defparam + tx04.channel_width = deserialization_factor; + + hssi_tx tx05 ( + .datain (txin05), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[05]), .clkout (w_tx_clkout[05]) ); + defparam + tx05.channel_width = deserialization_factor; + + hssi_tx tx06 ( + .datain (txin06), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[06]), .clkout (w_tx_clkout[06]) ); + defparam + tx06.channel_width = deserialization_factor; + + hssi_tx tx07 ( + .datain (txin07), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[07]), .clkout (w_tx_clkout[07]) ); + defparam + tx07.channel_width = deserialization_factor; + + hssi_tx tx08 ( + .datain (txin08), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[08]), .clkout (w_tx_clkout[08]) ); + defparam + tx08.channel_width = deserialization_factor; + + hssi_tx tx09 ( + .datain (txin09), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[09]), .clkout (w_tx_clkout[09]) ); + defparam + tx09.channel_width = deserialization_factor; + + hssi_tx tx10 ( + .datain (txin10), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[10]), .clkout (w_tx_clkout[10]) ); + defparam + tx10.channel_width = deserialization_factor; + + hssi_tx tx11 ( + .datain (txin11), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[11]), .clkout (w_tx_clkout[11]) ); + defparam + tx11.channel_width = deserialization_factor; + + hssi_tx tx12 ( + .datain (txin12), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[12]), .clkout (w_tx_clkout[12]) ); + defparam + tx12.channel_width = deserialization_factor; + + hssi_tx tx13 ( + .datain (txin13), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[13]), .clkout (w_tx_clkout[13]) ); + defparam + tx13.channel_width = deserialization_factor; + + hssi_tx tx14 ( + .datain (txin14), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[14]), .clkout (w_tx_clkout[14]) ); + defparam + tx14.channel_width = deserialization_factor; + + hssi_tx tx15 ( + .datain (txin15), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[15]), .clkout (w_tx_clkout[15]) ); + defparam + tx15.channel_width = deserialization_factor; + + hssi_tx tx16 ( + .datain (txin16), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[16]), .clkout (w_tx_clkout[16]) ); + defparam + tx16.channel_width = deserialization_factor; + + hssi_tx tx17 ( + .datain (txin17), .clk (w_tx_clk), .areset (tx_aclr_pulldown), + .dataout (w_tx_out[17]), .clkout (w_tx_clkout[17]) ); + defparam + tx17.channel_width = deserialization_factor; + + + //--------------------------------------------------------- + // Instantiate HSSI_PLL - use the same PLL for all channels + + hssi_pll pll0 ( + .clk (tx_inclock), .areset (tx_pll_aclr_pulldown), + .clk0 (w_tx_clk), .clk1 (w_tx_clk1), .locked (i_tx_pll_locked) ); + defparam + pll0.clk0_multiply_by = inclock_boost, + pll0.input_frequency = inclock_period; + + + //-------------------------------------------------------- + // Instantiate HSSI_FIFO - maximum of 18 channels + + hssi_fifo fifo00 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[00]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[00]), .datain (i_tx_in00), + .overflow (i_tx_full[00]), .empty (i_tx_empty[00]), + .dataout (i_fifo_out00) ); + defparam + fifo00.channel_width = deserialization_factor; + + hssi_fifo fifo01 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[01]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[01]), .datain (i_tx_in01), + .overflow (i_tx_full[01]), .empty (i_tx_empty[01]), + .dataout (i_fifo_out01) ); + defparam + fifo01.channel_width = deserialization_factor; + + hssi_fifo fifo02 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[02]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[02]), .datain (i_tx_in02), + .overflow (i_tx_full[02]), .empty (i_tx_empty[02]), + .dataout (i_fifo_out02) ); + defparam + fifo02.channel_width = deserialization_factor; + + hssi_fifo fifo03 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[03]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[03]), .datain (i_tx_in03), + .overflow (i_tx_full[03]), .empty (i_tx_empty[03]), + .dataout (i_fifo_out03) ); + defparam + fifo03.channel_width = deserialization_factor; + + hssi_fifo fifo04 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[04]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[04]), .datain (i_tx_in04), + .overflow (i_tx_full[04]), .empty (i_tx_empty[04]), + .dataout (i_fifo_out04) ); + defparam + fifo04.channel_width = deserialization_factor; + + hssi_fifo fifo05 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[05]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[05]), .datain (i_tx_in05), + .overflow (i_tx_full[05]), .empty (i_tx_empty[05]), + .dataout (i_fifo_out05) ); + defparam + fifo05.channel_width = deserialization_factor; + + hssi_fifo fifo06 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[06]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[06]), .datain (i_tx_in06), + .overflow (i_tx_full[06]), .empty (i_tx_empty[06]), + .dataout (i_fifo_out06) ); + defparam + fifo06.channel_width = deserialization_factor; + + hssi_fifo fifo07 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[07]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[07]), .datain (i_tx_in07), + .overflow (i_tx_full[07]), .empty (i_tx_empty[07]), + .dataout (i_fifo_out07) ); + defparam + fifo07.channel_width = deserialization_factor; + + hssi_fifo fifo08 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[08]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[08]), .datain (i_tx_in08), + .overflow (i_tx_full[08]), .empty (i_tx_empty[08]), + .dataout (i_fifo_out08) ); + defparam + fifo08.channel_width = deserialization_factor; + + hssi_fifo fifo09 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[09]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[09]), .datain (i_tx_in09), + .overflow (i_tx_full[09]), .empty (i_tx_empty[09]), + .dataout (i_fifo_out09) ); + defparam + fifo09.channel_width = deserialization_factor; + + hssi_fifo fifo10 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[10]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[10]), .datain (i_tx_in10), + .overflow (i_tx_full[10]), .empty (i_tx_empty[10]), + .dataout (i_fifo_out10) ); + defparam + fifo10.channel_width = deserialization_factor; + + hssi_fifo fifo11 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[11]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[11]), .datain (i_tx_in11), + .overflow (i_tx_full[11]), .empty (i_tx_empty[11]), + .dataout (i_fifo_out11) ); + defparam + fifo11.channel_width = deserialization_factor; + + hssi_fifo fifo12 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[12]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[12]), .datain (i_tx_in12), + .overflow (i_tx_full[12]), .empty (i_tx_empty[12]), + .dataout (i_fifo_out12) ); + defparam + fifo12.channel_width = deserialization_factor; + + hssi_fifo fifo13 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[13]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[13]), .datain (i_tx_in13), + .overflow (i_tx_full[13]), .empty (i_tx_empty[13]), + .dataout (i_fifo_out13) ); + defparam + fifo13.channel_width = deserialization_factor; + + hssi_fifo fifo14 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[14]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[14]), .datain (i_tx_in14), + .overflow (i_tx_full[14]), .empty (i_tx_empty[14]), + .dataout (i_fifo_out14) ); + defparam + fifo14.channel_width = deserialization_factor; + + hssi_fifo fifo15 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[15]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[15]), .datain (i_tx_in15), + .overflow (i_tx_full[15]), .empty (i_tx_empty[15]), + .dataout (i_fifo_out15) ); + defparam + fifo15.channel_width = deserialization_factor; + + hssi_fifo fifo16 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[16]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[16]), .datain (i_tx_in16), + .overflow (i_tx_full[16]), .empty (i_tx_empty[16]), + .dataout (i_fifo_out16) ); + defparam + fifo16.channel_width = deserialization_factor; + + hssi_fifo fifo17 ( + .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[17]), + .reset (tx_aclr_pulldown), .re (1'b1), + .clk1 (w_tx_clkout[17]), .datain (i_tx_in17), + .overflow (i_tx_full[17]), .empty (i_tx_empty[17]), + .dataout (i_fifo_out17) ); + defparam + fifo17.channel_width = deserialization_factor; + + + //-------------------------- + // Inputs + + assign tx_in_int[deserialization_factor*number_of_channels-1: 0] = + tx_in[deserialization_factor*number_of_channels-1:0]; + + assign i_tx_in00 = + tx_in_int[(01*deserialization_factor)-1:00*deserialization_factor]; + assign i_tx_in01 = + tx_in_int[(02*deserialization_factor)-1:01*deserialization_factor]; + assign i_tx_in02 = + tx_in_int[(03*deserialization_factor)-1:02*deserialization_factor]; + assign i_tx_in03 = + tx_in_int[(04*deserialization_factor)-1:03*deserialization_factor]; + assign i_tx_in04 = + tx_in_int[(05*deserialization_factor)-1:04*deserialization_factor]; + assign i_tx_in05 = + tx_in_int[(06*deserialization_factor)-1:05*deserialization_factor]; + assign i_tx_in06 = + tx_in_int[(07*deserialization_factor)-1:06*deserialization_factor]; + assign i_tx_in07 = + tx_in_int[(08*deserialization_factor)-1:07*deserialization_factor]; + assign i_tx_in08 = + tx_in_int[(09*deserialization_factor)-1:08*deserialization_factor]; + assign i_tx_in09 = + tx_in_int[(10*deserialization_factor)-1:09*deserialization_factor]; + assign i_tx_in10 = + tx_in_int[(11*deserialization_factor)-1:10*deserialization_factor]; + assign i_tx_in11 = + tx_in_int[(12*deserialization_factor)-1:11*deserialization_factor]; + assign i_tx_in12 = + tx_in_int[(13*deserialization_factor)-1:12*deserialization_factor]; + assign i_tx_in13 = + tx_in_int[(14*deserialization_factor)-1:13*deserialization_factor]; + assign i_tx_in14 = + tx_in_int[(15*deserialization_factor)-1:14*deserialization_factor]; + assign i_tx_in15 = + tx_in_int[(16*deserialization_factor)-1:15*deserialization_factor]; + assign i_tx_in16 = + tx_in_int[(17*deserialization_factor)-1:16*deserialization_factor]; + assign i_tx_in17 = + tx_in_int[(18*deserialization_factor)-1:17*deserialization_factor]; + + +//------------------------------------------------------------------ +// select the input for hssi_tx - from FIFO or from data input directly +assign txin00 = (bypass_fifo == "OFF") ? i_fifo_out00 : i_tx_in00; +assign txin01 = (bypass_fifo == "OFF") ? i_fifo_out01 : i_tx_in01; +assign txin02 = (bypass_fifo == "OFF") ? i_fifo_out02 : i_tx_in02; +assign txin03 = (bypass_fifo == "OFF") ? i_fifo_out03 : i_tx_in03; +assign txin04 = (bypass_fifo == "OFF") ? i_fifo_out04 : i_tx_in04; +assign txin05 = (bypass_fifo == "OFF") ? i_fifo_out05 : i_tx_in05; +assign txin06 = (bypass_fifo == "OFF") ? i_fifo_out06 : i_tx_in06; +assign txin07 = (bypass_fifo == "OFF") ? i_fifo_out07 : i_tx_in07; +assign txin08 = (bypass_fifo == "OFF") ? i_fifo_out08 : i_tx_in08; +assign txin09 = (bypass_fifo == "OFF") ? i_fifo_out09 : i_tx_in09; +assign txin10 = (bypass_fifo == "OFF") ? i_fifo_out10 : i_tx_in10; +assign txin11 = (bypass_fifo == "OFF") ? i_fifo_out11 : i_tx_in11; +assign txin12 = (bypass_fifo == "OFF") ? i_fifo_out12 : i_tx_in12; +assign txin13 = (bypass_fifo == "OFF") ? i_fifo_out13 : i_tx_in13; +assign txin14 = (bypass_fifo == "OFF") ? i_fifo_out14 : i_tx_in14; +assign txin15 = (bypass_fifo == "OFF") ? i_fifo_out15 : i_tx_in15; +assign txin16 = (bypass_fifo == "OFF") ? i_fifo_out16 : i_tx_in16; +assign txin17 = (bypass_fifo == "OFF") ? i_fifo_out17 : i_tx_in17; + +//----------------------------------------------- +// assign the correct signals to the output ports + +assign tx_out = (deserialization_factor > 1) ? + w_tx_out[number_of_channels-1:0] + : tx_in; + +assign tx_outclock = (deserialization_factor > 1) ? + w_tx_clkout[00] + : tx_inclock; + +assign tx_full = (deserialization_factor == 1) ? + 0 + : (bypass_fifo == "OFF") ? + ~i_tx_full[number_of_channels-1:0] + : {number_of_channels{1'bX}}; + +assign tx_empty = (deserialization_factor == 1) ? + 0 + : (bypass_fifo == "OFF") ? + ~i_tx_empty[number_of_channels-1:0] + : {number_of_channels{1'bX}}; + +assign tx_pll_locked = i_tx_pll_locked; + +endmodule // altcdr_tx + +//START_MODULE_NAME---------------------------------------------------- +// +// Module 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 +// +// Limitation : Only available for APEX20KE, APEXII, MERCURY, STRATIX, +// STRATIX GX, Stratix II, Cyclone and Cyclone II families. +// +// Results expected: output clock, deserialized output data and pll locked +// signal. +// +//END_MODULE_NAME---------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module altlvds_rx ( + rx_in, + rx_inclock, + rx_enable, + rx_deskew, + rx_pll_enable, + rx_data_align, + rx_reset, + rx_dpll_reset, + rx_dpll_hold, + rx_dpll_enable, + rx_fifo_reset, + rx_channel_data_align, + rx_cda_reset, + rx_coreclk, + pll_areset, + rx_out, + rx_outclock, + rx_locked, + rx_dpa_locked, + rx_cda_max +); + +// GLOBAL PARAMETER DECLARATION + parameter number_of_channels = 1; + parameter deserialization_factor = 4; + parameter registered_output = "ON"; + parameter inclock_period = 10000; + parameter inclock_boost = deserialization_factor; + parameter cds_mode = "UNUSED"; + parameter intended_device_family = "APEX20KE"; + parameter input_data_rate =0; + parameter inclock_data_alignment = "EDGE_ALIGNED"; + parameter registered_data_align_input = "ON"; + parameter common_rx_tx_pll = "ON"; + parameter enable_dpa_mode = "OFF"; + parameter enable_dpa_fifo = "ON"; + parameter use_dpll_rawperror = "OFF"; + parameter use_coreclock_input = "OFF"; + parameter dpll_lock_count = 0; + parameter dpll_lock_window = 0; + parameter outclock_resource = "AUTO"; + parameter data_align_rollover = deserialization_factor; + parameter lose_lock_on_one_change ="OFF" ; + parameter reset_fifo_at_first_lock ="ON" ; + parameter use_external_pll = "OFF"; + parameter implement_in_les = "OFF"; + parameter port_rx_data_align = "PORT_CONNECTIVITY"; + parameter lpm_hint = "UNUSED"; + parameter lpm_type = "altlvds_rx"; + + // Specifies whether the source of the input clock is from a PLL + parameter clk_src_is_pll = "off"; + +// LOCAL PARAMETER DECLARATION + + // A APEX20KE type of LVDS? + parameter APEX20KE_RX_STYLE = ((intended_device_family == "APEX20KE") || + (intended_device_family == "APEX20KC") || + (intended_device_family == "EXCALIBUR_ARM") || + (intended_device_family == "EXCALIBUR_MIPS")) + ? 1 : 0; + + // A APEXII type of LVDS? + parameter APEXII_RX_STYLE = ((intended_device_family == "APEXII") || + (intended_device_family == "APEX II")) + ? 1 : 0; + + // A MERCURY type of LVDS? + parameter MERCURY_RX_STYLE = ((intended_device_family == "MERCURY") || + (intended_device_family == "Mercury")) + ? 1 : 0; + + // A STRATIX type of LVDS? + parameter STRATIX_RX_STYLE = (((intended_device_family == "Stratix") || + (intended_device_family == "STRATIX") || + (intended_device_family == "HardCopy Stratix") || + (intended_device_family == "HARDCOPY STRATIX") || + (intended_device_family == "hardcopy stratix") || + (intended_device_family == "HardcopyStratix") || + (intended_device_family == "HARDCOPYSTRATIX") || + (intended_device_family == "hardcopystratix")) || + (((intended_device_family == "STRATIXGX") || + (intended_device_family == "STRATIX-GX") || + (intended_device_family == "Stratix GX")) && + (enable_dpa_mode == "OFF"))) + ? 1 : 0; + + // A STRATIXGX DPA type of LVDS? + parameter STRATIXGX_DPA_RX_STYLE = + (((intended_device_family == "STRATIXGX") || + (intended_device_family == "STRATIX-GX") || + (intended_device_family == "Stratix GX")) && + (enable_dpa_mode == "ON")) + ? 1 : 0; + + // A STRATIX II type of LVDS? + parameter STRATIXII_RX_STYLE = ((intended_device_family == "Stratix II") || + (intended_device_family == "StratixII") || + (intended_device_family == "HardCopy II") || + (intended_device_family == "HardCopyII") || + (intended_device_family == "HARDCOPY II") || + (intended_device_family == "HARDCOPYII") || + (intended_device_family == "hardcopy ii") || + (intended_device_family == "hardcopyii") || + (intended_device_family == "Stratix II GX") || + (intended_device_family == "STRATIX II GX") || + (intended_device_family == "stratix ii gx") || + (intended_device_family == "StratixIIGX") || + (intended_device_family == "STRATIXIIGX") || + (intended_device_family == "stratixiigx")) + ? 1 : 0; + + // A Cyclone type of LVDS? + parameter CYCLONE_RX_STYLE = ((intended_device_family == "Cyclone") || + (intended_device_family == "CYCLONE") || + (intended_device_family == "cyclone")) + ? 1 : 0; + + // A Cyclone II type of LVDS? + parameter CYCLONEII_RX_STYLE = ((intended_device_family == "Cyclone II") || + (intended_device_family == "CYCLONE II") || + (intended_device_family == "cyclone ii") || + (intended_device_family == "Cycloneii") || + (intended_device_family == "CYCLONEII") || + (intended_device_family == "cycloneii")) + ? 1 : 0; + + // Is the device family has flexible LVDS? + parameter FAMILY_HAS_FLEXIBLE_LVDS = ((CYCLONE_RX_STYLE == 1) || + (CYCLONEII_RX_STYLE == 1) || + (((STRATIX_RX_STYLE == 1) || + (STRATIXII_RX_STYLE == 1)) && + (implement_in_les == "ON"))) + ? 1 : 0; + + // Is the family has Stratix style PLL + parameter FAMILY_HAS_STRATIX_STYLE_PLL = ((STRATIX_RX_STYLE == 1) || + (STRATIXGX_DPA_RX_STYLE == 1) || + (CYCLONE_RX_STYLE == 1)) + ? 1 : 0; + + // Is the family has Stratix style PLL + parameter FAMILY_HAS_STRATIXII_STYLE_PLL = ((STRATIXII_RX_STYLE == 1) || + (CYCLONEII_RX_STYLE == 1)) + ? 1 : 0; + + // Parameter to check whether the selected lvds trasmitter use hold register + // or not + parameter RX_NEED_HOLD_REG = (((APEX20KE_RX_STYLE == 1) && + (deserialization_factor == 4 )) || + ((APEXII_RX_STYLE == 1) && + (deserialization_factor == 4)) || + ((MERCURY_RX_STYLE == 1) && + (deserialization_factor > 2) && + (deserialization_factor < 7))) + ? 1 : 0; + + // calculate clock boost for device family other than STRATIX, STRATIX GX + // and STRATIX II + parameter INT_CLOCK_BOOST = (APEX20KE_RX_STYLE == 1) + ? deserialization_factor : + ( (inclock_boost == 0) + ? deserialization_factor + : inclock_boost); + + // M value for stratix/stratix II/Cyclone/Cyclone II PLL + parameter PLL_M_VALUE = (((input_data_rate * inclock_period) + + (5 * 100000)) / 1000000); + + // D value for Stratix/Stratix II/Cyclone/Cyclone II PLL + parameter PLL_D_VALUE = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? ((input_data_rate !=0) && (inclock_period !=0) + ? 2 + : 1) + : 1; + + // calculate clock boost for STRATIX, STRATIX GX and STRATIX II + parameter STRATIX_INCLOCK_BOOST = ((input_data_rate !=0) && + (inclock_period !=0)) + ? PLL_M_VALUE : + ((inclock_boost == 0) + ? deserialization_factor + : inclock_boost); + + // phase_shift delay. Add 0.5 to the calculated result to round up result to + // the nearest integer. + parameter PHASE_SHIFT = + (inclock_data_alignment == "EDGE_ALIGNED") + ? 0 : + (inclock_data_alignment == "CENTER_ALIGNED") + ? (0.5 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 : + (inclock_data_alignment == "45_DEGREES") + ? (0.125 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 : + (inclock_data_alignment == "90_DEGREES") + ? (0.25 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 : + (inclock_data_alignment == "135_DEGREES") + ? (0.375 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 : + (inclock_data_alignment == "180_DEGREES") + ? (0.5 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 : + (inclock_data_alignment == "225_DEGREES") + ? (0.625 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 : + (inclock_data_alignment == "270_DEGREES") + ? (0.75 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 : + (inclock_data_alignment == "315_DEGREES") + ? (0.875 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 + : 0; + + // parameter for Stratix II inclock phase shift. + parameter STXII_PHASE_SHIFT = PHASE_SHIFT - + (0.5 * inclock_period / STRATIX_INCLOCK_BOOST); + + parameter REGISTER_WIDTH = deserialization_factor * number_of_channels; + + // input clock period for PLL. + parameter CLOCK_PERIOD = (deserialization_factor > 2) + ? inclock_period + : 10000; + +// INPUT PORT DECLARATION + input [number_of_channels -1 :0] rx_in; + input rx_inclock; + input rx_enable; + input rx_deskew; + input rx_pll_enable; + input rx_data_align; + input [number_of_channels -1 :0] rx_reset; + input [number_of_channels -1 :0] rx_dpll_reset; + input [number_of_channels -1 :0] rx_dpll_hold; + input [number_of_channels -1 :0] rx_dpll_enable; + input [number_of_channels -1 :0] rx_fifo_reset; + input [number_of_channels -1 :0] rx_channel_data_align; + input [number_of_channels -1 :0] rx_cda_reset; + input [number_of_channels -1 :0] rx_coreclk; + input pll_areset; + +// OUTPUT PORT DECLARATION + output [REGISTER_WIDTH -1: 0] rx_out; + output rx_outclock; + output rx_locked; + output [number_of_channels -1: 0] rx_dpa_locked; + output [number_of_channels -1: 0] rx_cda_max; + + +// INTERNAL REGISTERS DECLARATION + reg [REGISTER_WIDTH -1 : 0] pattern; + reg [REGISTER_WIDTH -1 : 0] rx_shift_reg; + reg [REGISTER_WIDTH -1 : 0] rx_parallel_load_reg; + reg [REGISTER_WIDTH -1 : 0] rx_out_reg; + reg [REGISTER_WIDTH -1 : 0] rx_out_hold; + reg [number_of_channels-1 : 0] deskew_done; + reg calibrate; + reg fb; + reg rx_mercury_slow_clock; + reg [deserialization_factor-1 : 0] temp; + reg [9 : 0] deskew_pattern; + reg [number_of_channels -1 : 0] rx_reg_clk_pre; + reg rx_data_align_reg; + + // for x2 mode (deserialization_factor = 2) + reg [REGISTER_WIDTH -1 : 0] rx_ddio_in; + reg [number_of_channels -1 : 0] rx_in_latched; + +// INTERNAL WIRE DECLARATION + wire [REGISTER_WIDTH -1 : 0] rx_out_int; + wire [REGISTER_WIDTH -1 : 0] stratix_dataout; + wire [REGISTER_WIDTH -1 : 0] stratixgx_dataout; + wire [REGISTER_WIDTH -1 : 0] stratixii_dataout; + wire [REGISTER_WIDTH -1 : 0] flvds_dataout; + wire [number_of_channels -1 : 0] stratixgx_dpa_locked; + wire [number_of_channels -1 : 0] stratixii_dpa_locked; + wire rx_fastclk; + wire rx_slowclk; + wire rx_locked_int; + wire rx_outclk_int; + wire rx_hold_clk; + wire rx_data_align_clk; + wire [number_of_channels -1 : 0] rx_reg_clk; + wire altclklock_inclock; + wire altclklock_fastclk; + wire altclklock_slowclk; + wire altclklock_locked; + wire[1:0] stratix_pll_inclock; + wire[1:0] stratixii_pll_inclock; + wire[5:0] stratix_pll_outclock; + wire[5:0] stratixii_pll_outclock; + wire stratix_pll_enable; + wire stratixii_pll_enable; + wire stratix_pll_areset; + wire stratixii_pll_areset; + wire stratixii_sclkout0; + wire stratixii_sclkout1; + wire stratix_locked; + wire stratixii_locked; + wire stratix_enable0; + wire stratix_enable1; + wire stratixii_enable0; + wire stratixii_enable1; + wire unused_clk2; + wire unused_clk_ext; + wire stratix_fastclk; + wire stratix_slowclk; + wire stratixgx_fastclk; + wire stratixgx_slowclk; + wire[number_of_channels -1 :0] stratixgx_coreclk; + wire stratixii_fastclk; + wire stratixii_enable; + wire flvds_fastclk; + wire flvds_slowclk; + wire flvds_syncclk; + wire rx_data_align_int; + wire rx_data_align_pulldown; + wire[number_of_channels -1 :0] rx_channel_data_align_int; + +// INTERNAL TRI DECLARATION + tri0 rx_deskew; + tri1 rx_pll_enable; + tri0[number_of_channels -1 :0] rx_reset; + tri0[number_of_channels -1 :0] rx_dpll_reset; + tri0[number_of_channels -1 :0] rx_dpll_hold; + tri1[number_of_channels -1 :0] rx_dpll_enable; + tri0[number_of_channels -1 :0] rx_fifo_reset; + tri0[number_of_channels -1 :0] rx_cda_reset; + tri0[number_of_channels -1 :0] rx_coreclk; + tri0 pll_areset; + +// LOCAL INTEGER DECLARATION + integer count [number_of_channels-1 : 0]; + integer sample; + integer i; + integer i1; + integer i2; + integer i3; + integer i4; + integer i5; + integer j; + integer j1; + integer x; + integer posedge_count; + integer negedge_count; + integer rxin_cnt; + integer start_data; + integer check_deskew_pattern; + +// COMPONENT INSTANTIATIONS + ALTERA_DEVICE_FAMILIES dev (); + +// FUNCTION DECLARATIONS + + // check whether the same pattern is found in the given input data + // for a particular channel. + function pattern_match; + input input_data, deskrew_pattern, dfactor, channel_num; + integer dfactor, channel_num; + reg[(20*10)-1 : 0] input_data; + reg[9 : 0] deskrew_pattern; + reg[9 : 0] input_pattern; + integer i; + begin + + pattern_match = 1; + + for (i = 0; i < deserialization_factor; i = i + 1) + begin + if(input_data[dfactor*channel_num +i] !== deskrew_pattern[i]) + begin + pattern_match = 0; + end + end + end + endfunction // pattern_match + +// INITIAL CONSTRUCT BLOCK + initial + begin : INITIALIZATION + fb = 1'b1; + rxin_cnt = 0; + negedge_count = 0; + posedge_count = 0; + start_data = 0; + rx_data_align_reg = 1'b0; + rx_mercury_slow_clock = 1'b0; + calibrate = 0; + deskew_done = {number_of_channels{1'b1}}; + rx_in_latched = {number_of_channels{1'b0}}; + + for (i = 0; i < number_of_channels; i = i + 1) + count[i] = 0; + + rx_out_reg = {REGISTER_WIDTH{1'b0}}; + rx_out_hold = {REGISTER_WIDTH{1'b0}}; + rx_shift_reg = {REGISTER_WIDTH{1'b0}}; + rx_parallel_load_reg = {REGISTER_WIDTH{1'b0}}; + rx_ddio_in = {REGISTER_WIDTH{1'b0}}; + + // Check for illegal mode settings + if ((APEX20KE_RX_STYLE == 1) && (deserialization_factor != 1) && + (deserialization_factor != 4) && (deserialization_factor != 7) && + (deserialization_factor != 8)) + begin + $display ($time, "ps Error: APEX20KE does not support the specified deserialization factor!"); + $finish; + end + else if ((MERCURY_RX_STYLE == 1) && + (deserialization_factor != 1) && (deserialization_factor != 2) && + (((deserialization_factor > 12) && (deserialization_factor != 14) && + (deserialization_factor != 16) && (deserialization_factor != 18) && + (deserialization_factor != 20)) || (deserialization_factor<3))) + begin + $display ($time, "ps Error: MERCURY does not support the specified deserialization factor!"); + $finish; + end + else if ((APEXII_RX_STYLE == 1) && + ((deserialization_factor > 10) || (deserialization_factor < 4)) && + (deserialization_factor != 1) && (deserialization_factor != 2)) + begin + $display ($time, "ps Error: APEXII does not support the specified deserialization factor!"); + $finish; + end + else if ((STRATIX_RX_STYLE == 1) && + (deserialization_factor != 1) && (deserialization_factor != 2) && + ((deserialization_factor > 10) || (deserialization_factor < 4))) + begin + $display ($time, "ps Error: STRATIX or STRATIXGX in non DPA mode does not support the specified deserialization factor!"); + $finish; + end + else if ((STRATIXGX_DPA_RX_STYLE == 1) && (deserialization_factor != 8) && (deserialization_factor != 10)) + begin + $display ($time, "ps Error: STRATIXGX in DPA mode does not support the specified deserialization factor!"); + $finish; + end + + if ((STRATIXII_RX_STYLE == 1) && + (deserialization_factor > 10)) + begin + $display ($time, "ps Error: STRATIX II does not support the specified deserialization factor!"); + $finish; + end + + if ((STRATIXII_RX_STYLE == 1) && + (data_align_rollover > 11)) + begin + $display ($time, "ps Error: STRATIX II does not support data align rollover values > 11 !"); + $finish; + end + + if (CYCLONE_RX_STYLE == 1) + begin + if ((use_external_pll == "ON") && + (deserialization_factor != 1) && (deserialization_factor != 2) && + (deserialization_factor != 4) && (deserialization_factor != 6) && + (deserialization_factor != 8) && (deserialization_factor != 10)) + begin + $display ($time, "ps Error: Cyclone does not support the specified deserialization factor when use_external_pll is 'ON'!"); + $finish; + end + else if ((deserialization_factor > 10) || (deserialization_factor == 3)) + begin + $display ($time, "ps Error: Cyclone does not support the specified deserialization factor when use_external_pll is 'OFF'!"); + $finish; + end + end + + if (CYCLONEII_RX_STYLE == 1) + begin + if ((use_external_pll == "ON") && + (deserialization_factor != 1) && (deserialization_factor != 2) && + (deserialization_factor != 4) && (deserialization_factor != 6) && + (deserialization_factor != 8) && (deserialization_factor != 10)) + begin + $display ($time, "ps Error: Cyclone II does not support the specified deserialization factor when use_external_pll is 'ON'!"); + $finish; + end + else if ((deserialization_factor > 10) || (deserialization_factor == 3)) + begin + $display ($time, "ps Error: Cyclone II does not support the specified deserialization factor when use_external_pll is 'OFF'!"); + $finish; + end + end + + if (dev.IS_VALID_FAMILY(intended_device_family) == 0) + begin + $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family); + $finish; + end + + // Initialise calibration pattern variables. Only for APEX20KE and APEXII + if ((APEX20KE_RX_STYLE == 1) && + ((deserialization_factor == 4) || (deserialization_factor == 7) || + (deserialization_factor == 8))) + begin + check_deskew_pattern = 1; + case (deserialization_factor) + 8: deskew_pattern[7:0] = 8'b00111100; + 7: deskew_pattern[6:0] = 7'b0011100; + 4: deskew_pattern[3:0] = 4'b1100; + default ; + endcase + end + else + if (((APEXII_RX_STYLE == 1)) && (deserialization_factor <= 10) && + (deserialization_factor >= 4)) + begin + check_deskew_pattern = 1; + if (cds_mode == "SINGLE_BIT") + begin + case (deserialization_factor) + 10: deskew_pattern[9:0] = 10'b0000011111; + 9: deskew_pattern[8:0] = 9'b000001111; + 8: deskew_pattern[7:0] = 8'b00001111; + 7: deskew_pattern[6:0] = 7'b0000111; + 6: deskew_pattern[5:0] = 6'b000111; + 5: deskew_pattern[4:0] = 5'b00011; + 4: deskew_pattern[3:0] = 4'b0011; + default ; + endcase + end + else + begin + case (deserialization_factor) + 10: deskew_pattern[9:0] = 10'b0101010101; + 9: deskew_pattern[8:0] = 9'b010101010; + 8: deskew_pattern[7:0] = 8'b01010101; + 7: deskew_pattern[6:0] = 7'b0101010; + 6: deskew_pattern[5:0] = 6'b010101; + 5: deskew_pattern[4:0] = 5'b01010; + 4: deskew_pattern[3:0] = 4'b0101; + default ; + endcase + end + end + else check_deskew_pattern = 0; + + end //INITIALIZATION + + // NCSIM will only assigns 1'bZ to unconnected port at time 0fs + 1 + initial #0 + begin + if ((STRATIXII_RX_STYLE == 1) && + (rx_channel_data_align === {number_of_channels{1'bZ}}) && + (rx_data_align !== 1'bZ)) + begin + $display("Warning : Data alignment on Stratix II 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."); + end + end + +// COMPONENT INSTANTIATIONS + + // pll for device families other than Stratix, Stratix GX and Stratix II + altclklock u0 ( + .inclock(altclklock_inclock), + .inclocken(rx_pll_enable), + .fbin(fb), + .clock0(altclklock_fastclk), + .clock1(altclklock_slowclk), + .clock2(unused_clk2), + .clock_ext(unused_clk_ext), + .locked(altclklock_locked)); + + defparam + u0.inclock_period = CLOCK_PERIOD, + u0.clock0_boost = INT_CLOCK_BOOST, + u0.clock1_boost = INT_CLOCK_BOOST, + u0.clock1_divide = deserialization_factor, + u0.valid_lock_cycles = (APEXII_RX_STYLE == 1) ? 1 : + (MERCURY_RX_STYLE == 1) ? 3 : 5, + u0.intended_device_family = ((APEX20KE_RX_STYLE == 1 ) || + (APEXII_RX_STYLE == 1 ) || + (MERCURY_RX_STYLE == 1 )) + ? intended_device_family + : "APEX20KE"; + + // pll for Stratix and Stratix GX + MF_stratix_pll u1 ( + .inclk(stratix_pll_inclock), // Required + .ena(stratix_pll_enable), + .areset(stratix_pll_areset), + .clkena(6'b111111), + .clk (stratix_pll_outclock), + .locked(stratix_locked), + .fbin(1'b1), + .clkswitch(1'b0), + .pfdena(1'b1), + .extclkena(4'b0), + .scanclk(1'b0), + .scanaclr(1'b0), + .scandata(1'b0), + .comparator(rx_data_align_int), + .extclk(), + .clkbad(), + .enable0(stratix_enable0), + .enable1(stratix_enable1), + .activeclock(), + .clkloss(), + .scandataout()); + + defparam + u1.pll_type = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? "flvds" + : "lvds", + u1.inclk0_input_frequency = CLOCK_PERIOD, + u1.inclk1_input_frequency = CLOCK_PERIOD, + u1.valid_lock_multiplier = 1, + u1.clk0_multiply_by = STRATIX_INCLOCK_BOOST, + u1.clk0_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PLL_D_VALUE + : 1, + u1.clk1_multiply_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (deserialization_factor%2 == 1) + ? STRATIX_INCLOCK_BOOST + : 1, + u1.clk1_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (deserialization_factor%2 == 1) + ? PLL_D_VALUE*deserialization_factor + : 1, + u1.clk2_multiply_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (deserialization_factor%2 == 1) + ? STRATIX_INCLOCK_BOOST *2 + : STRATIX_INCLOCK_BOOST, + u1.clk2_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? ((deserialization_factor%2 == 0) + ? PLL_D_VALUE*deserialization_factor/2 + : PLL_D_VALUE*deserialization_factor) + : deserialization_factor, + u1.clk0_phase_shift_num = PHASE_SHIFT, + u1.clk1_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (deserialization_factor%2 == 1) + ? PHASE_SHIFT + : 1, + u1.clk2_phase_shift_num = PHASE_SHIFT, + u1.simulation_type = "functional", + u1.m = 0; + + + // pll for Stratix II + MF_stratixii_pll u2 ( + .inclk(stratixii_pll_inclock), // Required + .ena(stratixii_pll_enable), + .areset(stratixii_pll_areset), + .clk (stratixii_pll_outclock ), + .locked(stratixii_locked), + .fbin(1'b1), + .clkswitch(1'b0), + .pfdena(1'b1), + .scanclk(1'b0), + .scanread(1'b0), + .scanwrite(1'b0), + .scandata(1'b0), + .testin(4'b0), + .clkbad(), + .enable0(stratixii_enable0), + .enable1(stratixii_enable1), + .activeclock(), + .clkloss(), + .scandataout(), + .scandone(), + .sclkout({stratixii_sclkout1, stratixii_sclkout0}), + .testupout(), + .testdownout()); + + defparam + u2.pll_type = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? "flvds" + : "lvds", + u2.vco_multiply_by = STRATIX_INCLOCK_BOOST, + u2.vco_divide_by = 1, + u2.inclk0_input_frequency = CLOCK_PERIOD, + u2.inclk1_input_frequency = CLOCK_PERIOD, + u2.clk0_multiply_by = STRATIX_INCLOCK_BOOST, + u2.clk0_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PLL_D_VALUE + : deserialization_factor, + u2.clk1_multiply_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (deserialization_factor%2 == 1) + ? STRATIX_INCLOCK_BOOST + : 1, + u2.clk1_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (deserialization_factor%2 == 1) + ? PLL_D_VALUE*deserialization_factor + : 1, + u2.clk2_multiply_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (deserialization_factor%2 == 1) + ? STRATIX_INCLOCK_BOOST *2 + : STRATIX_INCLOCK_BOOST, + u2.clk2_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? ((deserialization_factor%2 == 0) + ? PLL_D_VALUE*deserialization_factor/2 + : PLL_D_VALUE*deserialization_factor) + : deserialization_factor, + u2.clk0_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PHASE_SHIFT + : STXII_PHASE_SHIFT, + u2.clk1_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (deserialization_factor%2 == 1) + ? PHASE_SHIFT + : 1, + u2.clk2_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PHASE_SHIFT + : STXII_PHASE_SHIFT, + u2.sclkout0_phase_shift = STXII_PHASE_SHIFT, + u2.simulation_type = "functional", + u2.m = 0; + + + // Stratix lvds receiver + stratix_lvds_rx u3 ( + .rx_in(rx_in), + .rx_fastclk(stratix_fastclk), + .rx_enable0(stratix_enable0), + .rx_enable1(stratix_enable1), + .rx_out(stratix_dataout)); + + defparam + u3.number_of_channels = number_of_channels, + u3.deserialization_factor = deserialization_factor; + + // Stratixgx lvds receiver with DPA mode + stratixgx_dpa_lvds_rx u4 ( + .rx_in(rx_in), + .rx_fastclk(stratixgx_fastclk), + .rx_slowclk(stratixgx_slowclk), + .rx_coreclk(stratixgx_coreclk), + .rx_locked(stratix_locked), + .rx_reset(rx_reset), + .rx_dpll_reset(rx_dpll_reset), + .rx_channel_data_align(rx_channel_data_align_int), + .rx_out(stratixgx_dataout), + .rx_dpa_locked(stratixgx_dpa_locked)); + + defparam + u4.number_of_channels = number_of_channels, + u4.deserialization_factor = deserialization_factor, + u4.use_coreclock_input = use_coreclock_input, + u4.enable_dpa_fifo = enable_dpa_fifo, + u4.registered_output = registered_output; + + + // Stratix II lvds receiver + stratixii_lvds_rx u5 ( + .rx_in(rx_in), + .rx_reset(rx_reset), + .rx_fastclk(stratixii_fastclk), + .rx_enable(stratixii_enable), + .rx_locked(stratixii_locked), + .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_int), + .rx_cda_reset(rx_cda_reset), + .rx_out(stratixii_dataout), + .rx_dpa_locked(stratixii_dpa_locked), + .rx_cda_max(rx_cda_max)); + + defparam + u5.number_of_channels = number_of_channels, + u5.deserialization_factor = deserialization_factor, + u5.enable_dpa_mode = enable_dpa_mode, + u5.data_align_rollover = data_align_rollover, + u5.lose_lock_on_one_change = lose_lock_on_one_change, + u5.reset_fifo_at_first_lock = reset_fifo_at_first_lock; + + // flexible lvds receiver + flexible_lvds_rx u6 ( + .rx_in(rx_in), + .rx_fastclk(flvds_fastclk), + .rx_slowclk(flvds_slowclk), + .rx_syncclk(flvds_syncclk), + .rx_locked(rx_locked_int), + .rx_out(flvds_dataout)); + + defparam + u6.number_of_channels = number_of_channels, + u6.deserialization_factor = deserialization_factor, + u6.use_extra_ddio_register = (CYCLONE_RX_STYLE == 1) || + (CYCLONEII_RX_STYLE == 1) ? "YES" : "NO", + u6.use_extra_pll_clk = (CYCLONE_RX_STYLE == 1) || + (CYCLONEII_RX_STYLE == 1) ? "NO" : "YES"; + + + +// ALWAYS CONSTRUCT BLOCK + + // For x2 mode. Data input is sampled in both the rising edge and falling + // edge of input clock. + always @(posedge rx_inclock) + begin : DDIO_IN + if (deserialization_factor == 2) + begin + for (i1 = 0; i1 <= number_of_channels-1; i1 = i1+1) + begin + rx_ddio_in[(i1*2)+1] <= rx_in[i1]; + rx_ddio_in[(i1*2)] <= rx_in_latched[i1]; + end + end + end // DDIO_IN + + always @(negedge rx_inclock) + begin : DDIO_IN_LATCH + if ((deserialization_factor == 2) && ($time > 0)) + begin + rx_in_latched <= rx_in; + end + end // DDIO_IN_LATCH + + // Activate calibration mode + always @ (posedge rx_deskew) + begin : CALIBRATION + deskew_done <= {number_of_channels{1'b0}}; + calibrate <= 1'b1; + end // CALIBRATION + + // slow clock + always @ (posedge rx_slowclk) + begin : SLOW_CLOCK + negedge_count <= 0; + + // In order to assure that the circuit is capturing data accurately + // the user must calibrate the LVDS data channels by asserting a + // deskew signal and applying the appropriate calibration value for + // 3 clock cycles to deskew the channel after 3 clock cycles. + if (check_deskew_pattern == 1) + begin + if (calibrate == 1'b1) + begin + for (j = 0; j <= number_of_channels-1; j = j+1) + begin + if (pattern_match(pattern, deskew_pattern[deserialization_factor-1:0], deserialization_factor, j) || + (pattern_match(pattern, ~deskew_pattern[deserialization_factor-1:0], deserialization_factor, j) && + (APEXII_RX_STYLE == 1) && + (cds_mode == "MULTIPLE_BIT"))) + begin + count[j] <= count[j] + 1; + + if (count[j] >= 2) + deskew_done[j] <= 1'b1; + + end + else + count[j] <= 0; + + end + end + end + + if (rx_deskew == 0) + calibrate <= 1'b0; + + end // SLOW_CLOCK + + // Fast clock (on falling edge) + always @ (negedge rx_fastclk) + begin : FAST_CLOCK_NEGEDGE + if(rx_locked_int == 1) + begin + + negedge_count <= negedge_count + 1; + + // For APEX and Mercury families, load data on the + // 3rd negative edge of the fast clock + if (negedge_count == 2) + begin + + if (rx_deskew == 0) + rx_parallel_load_reg <= rx_shift_reg; + + sample <= 1; + + for (i4= 0; i4 < number_of_channels; i4 = i4+1) + begin + if (deskew_done[i4] == 1) + begin + if(APEXII_RX_STYLE == 1) + begin + for (x=deserialization_factor-1; x >0; x=x-1) + rx_shift_reg[x + (i4 * deserialization_factor)] <= rx_shift_reg [x-1 + (i4 * deserialization_factor)]; + rx_shift_reg[i4 * deserialization_factor] <= rx_in[i4]; + end + else + // Data gets shifted into MSB first + rx_shift_reg[(i4+1)*deserialization_factor-1] <= rx_in[i4]; + end + else + begin + if(APEXII_RX_STYLE == 1) + begin + for (x=deserialization_factor-1; x >0; x=x-1) + pattern[x + (i4 * deserialization_factor)] <= pattern [x-1 + (i4 * deserialization_factor)]; + pattern[i4 * deserialization_factor] <= rx_in[i4]; + end + else + pattern[(i4+1)*deserialization_factor-1] <= rx_in[i4]; + rx_shift_reg[(i4+1)*deserialization_factor-1] <= 'bx; + end + end + + end + else + begin + // Loading input data to shift register + sample <= (sample + 1) % deserialization_factor; + + for (i4= 0; i4 < number_of_channels; i4 = i4+1) + begin + if (deskew_done[i4] == 1) + begin + if(APEXII_RX_STYLE == 1) + begin + for (x=deserialization_factor-1; x >0; x=x-1) + rx_shift_reg[x + (i4 * deserialization_factor)] <= rx_shift_reg [x-1 + (i4 * deserialization_factor)]; + rx_shift_reg[i4 * deserialization_factor] <= rx_in[i4]; + end + else + // Data gets shifted into MSB first + rx_shift_reg[(i4+1)*deserialization_factor-sample-1] <= rx_in[i4]; + end + else + begin + if(APEXII_RX_STYLE == 1) + begin + for (x=deserialization_factor-1; x >0; x=x-1) + pattern[x + (i4 * deserialization_factor)] <= pattern [x-1 + (i4 * deserialization_factor)]; + pattern[i4 * deserialization_factor] <= rx_in[i4]; + end + else + pattern[(i4+1)*deserialization_factor-sample-1] <= rx_in[i4]; + rx_shift_reg[(i4+1)*deserialization_factor-sample-1] <= 'bx; + end + end + end + end + end + + // Fast clock (on rising edge) + always @ (posedge rx_fastclk) + begin : FAST_CLOCK_POSEDGE + if(rx_locked_int == 1) + begin + if (deserialization_factor > 2) + begin + posedge_count <= (posedge_count+1) % deserialization_factor; + + // Generating slow clock for MERCURY + if (posedge_count % ((deserialization_factor+1)/2) == 0) + begin + rx_mercury_slow_clock <= ~rx_mercury_slow_clock; + end + end + end + end // FAST_CLOCK + + // synchronization register + always @ (posedge rx_reg_clk) + begin : SYNC_REGISTER + rx_out_reg <= rx_out_int; + end // SYNC_REGISTER + + // hold register + always @ (negedge rx_hold_clk) + begin : HOLD_REGISTER + if (deserialization_factor > 1) + begin + rx_out_hold <= rx_parallel_load_reg; + end + end // HOLD_REGISTER + + // Registering rx_data_align signal for stratix II lvds_rx. + always @ (posedge rx_data_align_clk) + begin + rx_data_align_reg <= rx_data_align_pulldown; + end + +// CONTINOUS ASSIGNMENT + assign rx_out = (STRATIXGX_DPA_RX_STYLE == 1) + ? stratixgx_dataout : + (registered_output == "ON") + ? rx_out_reg + : rx_out_int; + + assign rx_out_int = (deserialization_factor == 1) + ? rx_in : + (deserialization_factor == 2) + ? rx_ddio_in : + (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? flvds_dataout : + (STRATIX_RX_STYLE == 1) + ? stratix_dataout : + (STRATIXII_RX_STYLE == 1) + ? stratixii_dataout : + (RX_NEED_HOLD_REG == 1) + ? rx_out_hold + : rx_parallel_load_reg; + + assign rx_reg_clk = (use_external_pll == "ON") + ? rx_inclock + : {number_of_channels{rx_outclk_int}}; + + assign rx_hold_clk = rx_outclk_int; + + assign rx_outclock = rx_outclk_int; + + assign rx_outclk_int = (deserialization_factor <= 2) + ? rx_inclock : + (MERCURY_RX_STYLE == 1) + ? rx_mercury_slow_clock + : rx_slowclk; + + assign rx_slowclk = ((STRATIX_RX_STYLE == 1) || + (STRATIXGX_DPA_RX_STYLE == 1) || + (CYCLONE_RX_STYLE == 1)) + ? stratix_pll_outclock[2] : + ((STRATIXII_RX_STYLE == 1) || + (CYCLONEII_RX_STYLE == 1)) + ? stratixii_pll_outclock[2] + : altclklock_slowclk; + + assign rx_fastclk = altclklock_fastclk; + + assign rx_locked = (deserialization_factor > 2) + ? rx_locked_int + : 1'b1; + + assign rx_locked_int = ((STRATIX_RX_STYLE == 1) || + (STRATIXGX_DPA_RX_STYLE == 1) || + (CYCLONE_RX_STYLE == 1)) + ? stratix_locked : + ((STRATIXII_RX_STYLE == 1) || + (CYCLONEII_RX_STYLE == 1)) + ? stratixii_locked + : altclklock_locked; + + assign rx_dpa_locked = (STRATIXGX_DPA_RX_STYLE == 1) + ? stratixgx_dpa_locked : + (STRATIXII_RX_STYLE == 1) + ? stratixii_dpa_locked + : {number_of_channels{1'b1}}; + + assign rx_data_align_pulldown = (port_rx_data_align == "PORT_USED") + ? rx_data_align : + (port_rx_data_align == "PORT_UNUSED") + ? 1'b0 : + (rx_data_align !== 1'bz) + ? rx_data_align : + 1'b0; + + assign rx_data_align_int = (registered_data_align_input == "ON") + ? rx_data_align_reg + : rx_data_align_pulldown; + + assign rx_channel_data_align_int = + (rx_channel_data_align !== {number_of_channels{1'bZ}}) + ? rx_channel_data_align : + (STRATIXII_RX_STYLE == 1) + ? {number_of_channels{rx_data_align_int}} + : {number_of_channels{1'b0}}; + + assign rx_data_align_clk = ((STRATIX_RX_STYLE == 1) || + (STRATIXGX_DPA_RX_STYLE == 1)) + ? stratix_pll_outclock[2] : + (STRATIXII_RX_STYLE == 1) + ? stratixii_pll_outclock[2] + : 1'b0; + + assign altclklock_inclock = (APEX20KE_RX_STYLE == 1) || + (APEXII_RX_STYLE == 1) || + (MERCURY_RX_STYLE == 1) + ? rx_inclock + : 1'b0; + + assign stratix_pll_inclock[1:0] = (FAMILY_HAS_STRATIX_STYLE_PLL == 1) + ? {1'b0, rx_inclock} + : {2{1'b0}}; + + assign stratix_pll_enable = (FAMILY_HAS_STRATIX_STYLE_PLL == 1) + ? rx_pll_enable + : 1'b0; + + assign stratix_pll_areset = (FAMILY_HAS_STRATIX_STYLE_PLL == 1) + ? pll_areset + : 1'b0; + + assign stratix_fastclk = (STRATIX_RX_STYLE == 1) && (implement_in_les == "OFF") + ? stratix_pll_outclock[0] + : 1'b0; + + assign stratix_slowclk = (STRATIX_RX_STYLE == 1) && (implement_in_les == "OFF") + ? stratix_pll_outclock[2] + : 1'b0; + + assign stratixgx_fastclk = (STRATIXGX_DPA_RX_STYLE == 1) && (implement_in_les == "OFF") + ? stratix_pll_outclock[0] + : 1'b0; + + assign stratixgx_slowclk = (STRATIXGX_DPA_RX_STYLE == 1) && (implement_in_les == "OFF") + ? stratix_pll_outclock[2] + : 1'b0; + + assign stratixgx_coreclk = (STRATIXGX_DPA_RX_STYLE == 1) && (implement_in_les == "OFF") + ? rx_coreclk + : {number_of_channels{1'b0}}; + + assign stratixii_pll_inclock[1:0] = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1) + ? {1'b0, rx_inclock} + : {2{1'b0}}; + + assign stratixii_pll_enable = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1) + ? rx_pll_enable + : 1'b0; + + assign stratixii_pll_areset = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1) + ? pll_areset + : 1'b0; + assign stratixii_fastclk = (STRATIXII_RX_STYLE == 0) && (implement_in_les == "OFF") + ? 1'b0 : + (use_external_pll == "ON") + ? rx_inclock + : stratixii_sclkout0; + + assign stratixii_enable = (STRATIXII_RX_STYLE == 0) && (implement_in_les == "OFF") + ? 1'b0 : + (use_external_pll == "ON") + ? rx_enable + : stratixii_enable0; + + assign flvds_fastclk = ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIX_STYLE_PLL == 1)) + ? ((use_external_pll == "ON") + ? rx_inclock + : stratix_pll_outclock[0]) : + ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)) + ? ((use_external_pll == "ON") + ? rx_inclock + : stratixii_pll_outclock[0]) + : 1'b0; + + assign flvds_slowclk = ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIX_STYLE_PLL == 1)) + ? ((use_external_pll == "ON") + ? 1'b0 + : stratix_pll_outclock[2]) : + ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)) + ? ((use_external_pll == "ON") + ? 1'b0 + : stratixii_pll_outclock[2]) + : 1'b0; + + assign flvds_syncclk = ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIX_STYLE_PLL == 1)) + ? ((use_external_pll == "ON") + ? 1'b0 + : stratix_pll_outclock[1]) : + ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)) + ? ((use_external_pll == "ON") + ? 1'b0 + : stratixii_pll_outclock[1]) + : 1'b0; + +endmodule // altlvds_rx +// END OF MODULE + +//START_MODULE_NAME---------------------------------------------------- +// +// Module Name : stratix_lvds_rx +// +// Description : Stratix lvds receiver +// +// Limitation : Only available to Stratix and stratix GX (NON DPA mode) +// families. +// +// Results expected: Deserialized output data. +// +//END_MODULE_NAME---------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module stratix_lvds_rx ( + rx_in, // input serial data + rx_fastclk, // fast clock from pll + rx_enable0, + rx_enable1, + rx_out // deserialized output data +); + +// GLOBAL PARAMETER DECLARATION + parameter number_of_channels = 1; + parameter deserialization_factor = 4; + +// LOCAL PARAMETER DECLARATION + parameter REGISTER_WIDTH = deserialization_factor*number_of_channels; + +// INPUT PORT DECLARATION + input [number_of_channels -1 :0] rx_in; + input rx_fastclk; + input rx_enable0; + input rx_enable1; + +// OUTPUT PORT DECLARATION + output [REGISTER_WIDTH -1: 0] rx_out; + +// INTERNAL REGISTERS DECLARATION + reg [REGISTER_WIDTH -1 : 0] rx_shift_reg; + reg [REGISTER_WIDTH -1 : 0] rx_parallel_load_reg; + reg [REGISTER_WIDTH -1 : 0] rx_out_hold; + reg enable0_reg; + reg enable0_reg1; + reg enable0_neg; + reg enable1_reg; + +// INTERNAL WIRE DECLARATION + wire rx_hold_clk; + +// LOCAL INTEGER DECLARATION + integer i1; + integer x; + +// INITIAL CONSTRUCT BLOCK + initial + begin : INITIALIZATION + rx_shift_reg = {REGISTER_WIDTH{1'b0}}; + rx_parallel_load_reg = {REGISTER_WIDTH{1'b0}}; + rx_out_hold = {REGISTER_WIDTH{1'b0}}; + end //INITIALIZATION + +// ALWAYS CONSTRUCT BLOCK + + // registering load enable signal + always @ (posedge rx_fastclk) + begin : LOAD_ENABLE + enable0_reg1 <= enable0_reg; + enable0_reg <= rx_enable0; + enable1_reg <= rx_enable1; + end // LOAD_ENABLE + + // Fast clock (on falling edge) + always @ (negedge rx_fastclk) + begin : NEGEDGE_FAST_CLOCK + + // load data when the registered load enable signal is high + if (enable0_neg == 1) + rx_parallel_load_reg <= rx_shift_reg; + + // Loading input data to shift register + for (i1= 0; i1 < number_of_channels; i1 = i1+1) + begin + for (x=deserialization_factor-1; x >0; x=x-1) + rx_shift_reg[x + (i1 * deserialization_factor)] <= rx_shift_reg [x-1 + (i1 * deserialization_factor)]; + rx_shift_reg[i1 * deserialization_factor] <= rx_in[i1]; + end + + enable0_neg <= enable0_reg1; + + end // NEGEDGE_FAST_CLOCK + + // Holding register + always @ (posedge rx_hold_clk) + begin : HOLD_REGISTER + rx_out_hold <= rx_parallel_load_reg; + end // HOLD_REGISTER + +// CONTINOUS ASSIGNMENT + assign rx_out = rx_out_hold; + assign rx_hold_clk = enable1_reg; + + +endmodule // stratix_lvds_rx +// END OF MODULE + +//START_MODULE_NAME---------------------------------------------------- +// +// Module Name : stratixgx_dpa_lvds_rx +// +// Description : Stratix GX lvds receiver. +// +// Limitation : Only available in Stratix GX families. +// +// Results expected: Deserialized output data and dpa locked signal. +// +//END_MODULE_NAME---------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module stratixgx_dpa_lvds_rx ( + rx_in, + rx_fastclk, + rx_slowclk, + rx_locked, + rx_coreclk, + rx_reset, + rx_dpll_reset, + rx_channel_data_align, + rx_out, + rx_dpa_locked +); + +// GLOBAL PARAMETER DECLARATION + parameter number_of_channels = 1; + parameter deserialization_factor = 4; + parameter use_coreclock_input = "OFF"; + parameter enable_dpa_fifo = "ON"; + parameter registered_output = "ON"; + +// LOCAL PARAMETER DECLARATION + parameter REGISTER_WIDTH = deserialization_factor*number_of_channels; + +// INPUT PORT DECLARATION + input [number_of_channels -1 :0] rx_in; + input rx_fastclk; + input rx_slowclk; + input rx_locked; + input [number_of_channels -1 :0] rx_coreclk; + input [number_of_channels -1 :0] rx_reset; + input [number_of_channels -1 :0] rx_dpll_reset; + input [number_of_channels -1 :0] rx_channel_data_align; + +// OUTPUT PORT DECLARATION + output [REGISTER_WIDTH -1: 0] rx_out; + output [number_of_channels -1: 0] rx_dpa_locked; + +// INTERNAL REGISTERS DECLARATION + + reg [REGISTER_WIDTH -1 : 0] rx_shift_reg; + reg [REGISTER_WIDTH -1 : 0] rx_parallel_load_reg; + reg [number_of_channels -1 : 0] rx_in_reg; + reg [number_of_channels -1 : 0] dpa_in; + reg [number_of_channels -1 : 0] retime_data; + + reg [REGISTER_WIDTH -1 : 0] ram_array0; + reg [REGISTER_WIDTH -1 : 0] ram_array1; + reg [REGISTER_WIDTH -1 : 0] ram_array2; + reg [REGISTER_WIDTH -1 : 0] ram_array3; + reg [2 : 0] wrPtr [number_of_channels -1 : 0]; + reg [2 : 0] rdPtr [number_of_channels -1 : 0]; + reg [3 : 0] bitslip_count [number_of_channels -1 : 0]; + reg [3 : 0] bitslip_count_pre [number_of_channels -1 : 0]; + + reg [REGISTER_WIDTH -1 : 0] rxpdat2; + reg [REGISTER_WIDTH -1 : 0] rxpdat3; + reg [REGISTER_WIDTH -1 : 0] rxpdatout; + reg [REGISTER_WIDTH -1 : 0] fifo_data_out; + reg [REGISTER_WIDTH -1 : 0] rx_out_reg; + reg [number_of_channels -1 : 0] dpagclk_pre; + reg [number_of_channels -1 : 0] rx_channel_data_align_pre; + reg [number_of_channels -1 : 0] fifo_write_clk_pre; + reg [number_of_channels -1 : 0] clkout_tmp; + reg [number_of_channels -1 : 0] sync_reset; + +// INTERNAL WIRE DECLARATION + wire [number_of_channels -1:0] dpagclk; + wire[number_of_channels -1:0] fifo_write_clk; + wire [REGISTER_WIDTH -1 : 0] rx_out_int; + wire [REGISTER_WIDTH -1 : 0] serdes_data_out; + wire [REGISTER_WIDTH -1 : 0] fifo_data_in; + wire [REGISTER_WIDTH -1 : 0] rxpdat1; + +// INTERNAL TRI DECLARATION + tri0[number_of_channels -1 :0] rx_reset; + tri0[number_of_channels -1 :0] rx_dpll_reset; + tri0[number_of_channels -1 :0] rx_channel_data_align; + tri0[number_of_channels -1 :0] rx_coreclk; + +// LOCAL INTEGER DECLARATION + integer i; + integer i0; + integer i1; + integer i2; + integer i3; + integer i4; + integer i5; + integer i6; + integer i7; + integer i8; + integer j; + integer j1; + integer j2; + integer j3; + integer k; + integer x; + integer negedge_count; + + integer fastclk_posedge_count [number_of_channels -1: 0]; + integer fastclk_negedge_count [number_of_channels - 1 : 0]; + integer bitslip_count_reg [number_of_channels -1: 0]; + + +// COMPONENT INSTANTIATIONS +// ALTERA_DEVICE_FAMILIES dev (); + +// INITIAL CONSTRUCT BLOCK + initial + begin : INITIALIZATION + rxpdat2 = {REGISTER_WIDTH{1'b0}}; + rxpdat3 = {REGISTER_WIDTH{1'b0}}; + rxpdatout = {REGISTER_WIDTH{1'b0}}; + rx_out_reg = {REGISTER_WIDTH{1'b0}}; + + ram_array0 = {REGISTER_WIDTH{1'b0}}; + ram_array1 = {REGISTER_WIDTH{1'b0}}; + ram_array2 = {REGISTER_WIDTH{1'b0}}; + ram_array3 = {REGISTER_WIDTH{1'b0}}; + + rx_in_reg = {number_of_channels{1'b0}}; + dpa_in = {number_of_channels{1'b0}}; + retime_data = {number_of_channels{1'b0}}; + + rx_channel_data_align_pre = {number_of_channels{1'b0}}; + clkout_tmp = {number_of_channels{1'b0}}; + sync_reset = {number_of_channels{1'b0}}; + + rx_shift_reg = {REGISTER_WIDTH{1'b0}}; + rx_parallel_load_reg = {REGISTER_WIDTH{1'b0}}; + fifo_data_out = {REGISTER_WIDTH{1'b0}}; + + for (i = 0; i < number_of_channels; i = i + 1) + begin + wrPtr[i] = 0; + rdPtr[i] = 2; + bitslip_count[i] = 0; + bitslip_count_reg[i] = 0; + fastclk_posedge_count[i] = 0; + fastclk_negedge_count[i] = 0; + end + + end //INITIALIZATION + + +// ALWAYS CONSTRUCT BLOCK + + //deserializer logic + always @ (posedge dpagclk) + begin : DPA_SERDES_SLOWCLK + + for(i0 = 0; i0 <=number_of_channels -1; i0=i0+1) + begin + if ((dpagclk[i0] == 1'b1) && (dpagclk_pre[i0] == 1'b0)) + begin + + if ((rx_reset[i0] == 1'b1) || (rx_dpll_reset[i0] == 1'b1)) + sync_reset[i0] <= 1'b1; + else + sync_reset[i0] <= 1'b0; + + // add 1 ps delay to ensure that when the rising edge of + // global clock(core clock) happens at the same time of falling + // edge of fast clock, the count for the next falling edge of + // fast clock is start at 1. + fastclk_negedge_count[i0] <= #1 0; + end + end + end // DPA_SERDES_SLOW_CLOCK + + + always @ (posedge rx_fastclk) + begin : DPA_SERDES_POSEDGE_FASTCLK + for(i1 = 0; i1 <=number_of_channels -1; i1=i1+1) + begin + if (fastclk_negedge_count[i1] == 2) + rx_parallel_load_reg <= rx_shift_reg; + + if (sync_reset[i1] == 1'b1) + begin + fastclk_posedge_count[i1] <= 0; + clkout_tmp[i1] <= 1'b0; + end + else + begin + if (fastclk_posedge_count[i1] % (deserialization_factor / 2) == 0) + begin + fastclk_posedge_count[i1] <= 1; + clkout_tmp[i1] <= !clkout_tmp[i1]; + end + + fastclk_posedge_count[i1] <= (fastclk_posedge_count[i1] + 1) % deserialization_factor; + end + end + end // DPA_SERDES_POSEDGE_FAST_CLOCK + + always @ (negedge rx_fastclk) + begin : DPA_SERDES_NEGEDGE_FAST_CLOCK + if (rx_fastclk == 1'b0) + begin + for (i2 = 0; i2 <= number_of_channels -1; i2 = i2+1) + begin + // Data gets shifted into MSB first. + for (x=deserialization_factor-1; x > 0; x=x-1) + rx_shift_reg[x + (i2 * deserialization_factor)] <= rx_shift_reg [x-1 + (i2 * deserialization_factor)]; + + rx_shift_reg[i2 * deserialization_factor] <= retime_data[i2]; + retime_data <= rx_in; + + fastclk_negedge_count[i2] <= (fastclk_negedge_count[i2] + 1) ; + end + end + end // DPA_SERDES_NEGEDGE_FAST_CLOCK + + //phase compensation FIFO + always @ (posedge fifo_write_clk) + begin : DPA_FIFO_WRITE_CLOCK + if ((enable_dpa_fifo == "ON") && (rx_locked == 1'b1)) + begin + for (i3 = 0; i3 <= number_of_channels-1; i3 = i3+1) + begin + if(sync_reset[i3] == 1'b1) + wrPtr[i3] <= 0; + else if ((fifo_write_clk[i3] == 1'b1) && (fifo_write_clk_pre[i3] == 1'b0)) + begin + case (wrPtr[i3]) + 3'b000: + for (j = i3*deserialization_factor; j <= (i3+1)*deserialization_factor -1; j=j+1) + ram_array0[j] <= fifo_data_in[j]; + + 3'b001: + for (j = i3*deserialization_factor; j <= (i3+1)*deserialization_factor -1; j=j+1) + ram_array1[j] <= fifo_data_in[j]; + 3'b010: + for (j = i3*deserialization_factor; j <= (i3+1)*deserialization_factor -1; j=j+1) + ram_array2[j] <= fifo_data_in[j]; + 3'b011: + for (j = i3*deserialization_factor; j <= (i3+1)*deserialization_factor -1; j=j+1) + ram_array3[j] <= fifo_data_in[j]; + default: + $display ("Error! Invalid wrPtr value."); + endcase + wrPtr[i3] <= (wrPtr[i3] + 1) % 4; + end + end + end + end // DPA_FIFO_WRITE_CLOCK + + always @ (negedge fifo_write_clk) + begin + for (i6 = 0; i6 <= number_of_channels-1; i6 = i6+1) + begin + if (fifo_write_clk[i6] == 1'b0) + fifo_write_clk_pre[i6] <= fifo_write_clk[i6]; + end + end + + always @ (posedge dpagclk) + begin : DPA_FIFO_SLOW_CLOCK + + if((enable_dpa_fifo == "ON") ) + begin + for (i4 = 0; i4 <= number_of_channels-1; i4 = i4+1) + begin + if ((dpagclk[i4] == 1'b1) && (dpagclk_pre[i4] == 1'b0)) + begin + if ((rx_reset[i4] == 1'b1) || (rx_dpll_reset[i4] == 1'b1) || (sync_reset[i4] == 1'b1)) + begin + for (j1 = i4*deserialization_factor; j1 <= (i4+1)*deserialization_factor -1; j1=j1+1) + begin + fifo_data_out[j1] <= 1'b0; + ram_array0[j1] <= 1'b0; + ram_array1[j1] <= 1'b0; + ram_array2[j1] <= 1'b0; + ram_array3[j1] <= 1'b0; + end + + wrPtr[i4] <= 0; + rdPtr[i4] <= 2; + end + else + begin + case (rdPtr[i4]) + 3'b000: + for (j1 = i4*deserialization_factor; j1 <= (i4+1)*deserialization_factor -1; j1=j1+1) + fifo_data_out[j1] <= ram_array0[j1]; + 3'b001: + for (j1 = i4*deserialization_factor; j1 <= (i4+1)*deserialization_factor -1; j1=j1+1) + fifo_data_out[j1] <= ram_array1[j1]; + 3'b010: + for (j1 = i4*deserialization_factor; j1 <= (i4+1)*deserialization_factor -1; j1=j1+1) + fifo_data_out[j1] <= ram_array2[j1]; + 3'b011: + for (j1 = i4*deserialization_factor; j1 <= (i4+1)*deserialization_factor -1; j1=j1+1) + fifo_data_out[j1] <= ram_array3[j1]; + default: + $display ("Error! Invalid rdPtr value."); + endcase + + rdPtr[i4] <= (rdPtr[i4] + 1) % 4; + end + end + end + end + end // DPA_FIFO_SLOW_CLOCK + + + //bit-slipping logic + always @ (posedge dpagclk) + begin : DPA_BIT_SLIP + + for (i5 = 0; i5 <= number_of_channels-1; i5 = i5 + 1) + begin + if ((dpagclk[i5] == 1'b1) && (dpagclk_pre[i5] == 1'b0)) + begin + if ((sync_reset[i5] == 1'b1) || (rx_reset[i5] == 1'b1) || + (rx_dpll_reset[i5] == 1'b1)) + begin + for(j2 = deserialization_factor*i5; j2 <= deserialization_factor*(i5+1) -1; j2=j2+1) + begin + rxpdat2[j2] <= 1'b0; + rxpdat3[j2] <= 1'b0; + rxpdatout[j2] <= 1'b0; + end + bitslip_count[i5] <= 0; + bitslip_count_reg[i5] <= 0; + end + else + begin + if ((rx_channel_data_align[i5] == 1'b1) && (rx_channel_data_align_pre[i5] == 1'b0)) + bitslip_count[i5] <= (bitslip_count[i5] + 1) % deserialization_factor; + + bitslip_count_reg[i5] <= bitslip_count[i5]; + + rxpdat2 <= rxpdat1; + rxpdat3 <= rxpdat2; + + for(j2 = deserialization_factor*i5 + bitslip_count_reg[i5]; j2 <= deserialization_factor*(i5+1) -1; j2=j2+1) + rxpdatout[j2] <= rxpdat3[j2-bitslip_count_reg[i5]]; + + for(j2 = deserialization_factor*i5 ; j2 <= deserialization_factor*i5 + bitslip_count_reg[i5] -1; j2=j2+1) + rxpdatout[j2] <= rxpdat2[j2+ deserialization_factor -bitslip_count_reg[i5]]; + end + rx_channel_data_align_pre[i5] <= rx_channel_data_align[i5]; + end + end + end // DPA_BIT_SLIP + + // synchronization register + always @ (posedge dpagclk) + begin : SYNC_REGISTER + for (i8 = 0; i8 < number_of_channels; i8 = i8+1) + begin + if ((dpagclk[i8] == 1'b1) && (dpagclk_pre[i8] == 1'b0)) + begin + for (j3 = 0; j3 < deserialization_factor; j3 = j3+1) + rx_out_reg[i8*deserialization_factor + j3] <= rxpdatout[i8*deserialization_factor + j3]; + end + end + end // SYNC_REGISTER + + // store previous value of the global clocks + always @ (dpagclk) + begin + dpagclk_pre <= dpagclk; + end + + // CONTINOUS ASSIGNMENT + assign dpagclk = (use_coreclock_input == "ON") ? rx_coreclk : {number_of_channels{rx_slowclk}}; + assign rxpdat1 = (enable_dpa_fifo == "ON") ? fifo_data_out : serdes_data_out; + assign serdes_data_out = rx_parallel_load_reg; + assign fifo_data_in = serdes_data_out; + assign fifo_write_clk = clkout_tmp; + assign rx_dpa_locked = {number_of_channels {1'b1}}; + assign rx_out = (registered_output == "ON") ? rx_out_reg : rxpdatout; + + +endmodule // stratixgx_dpa_lvds_rx +// END OF MODULE + +//START_MODULE_NAME------------------------------------------------------------- +// +// Module 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_MODULE_NAME--------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module stratixii_lvds_rx ( + rx_in, + rx_reset, + rx_fastclk, + rx_enable, + rx_locked, + rx_dpll_reset, + rx_dpll_hold, + rx_dpll_enable, + rx_fifo_reset, + rx_channel_data_align, + rx_cda_reset, + rx_out, + rx_dpa_locked, + rx_cda_max +); + +// GLOBAL PARAMETER DECLARATION + parameter number_of_channels = 1; + parameter deserialization_factor = 4; + parameter enable_dpa_mode = "OFF"; + parameter data_align_rollover = deserialization_factor; + parameter lose_lock_on_one_change = "OFF"; + parameter reset_fifo_at_first_lock = "ON"; + +// LOCAL PARAMETER DECLARATION + parameter REGISTER_WIDTH = deserialization_factor*number_of_channels; + parameter MUX_WIDTH = 12; + parameter RAM_WIDTH = 6; + +// INPUT PORT DECLARATION + input [number_of_channels -1 :0] rx_in; + input rx_fastclk; + input rx_enable; + input rx_locked; + input [number_of_channels -1 :0] rx_reset; + input [number_of_channels -1 :0] rx_dpll_reset; + input [number_of_channels -1 :0] rx_dpll_hold; + input [number_of_channels -1 :0] rx_dpll_enable; + input [number_of_channels -1 :0] rx_fifo_reset; + input [number_of_channels -1 :0] rx_channel_data_align; + input [number_of_channels -1 :0] rx_cda_reset; + +// OUTPUT PORT DECLARATION + output [REGISTER_WIDTH -1: 0] rx_out; + output [number_of_channels -1: 0] rx_dpa_locked; + output [number_of_channels -1: 0] rx_cda_max; + + +// INTERNAL REGISTERS DECLARATION + + reg [REGISTER_WIDTH -1 : 0] rx_shift_reg; + reg [REGISTER_WIDTH -1 : 0] rx_parallel_load_reg; + reg [number_of_channels -1 : 0] rx_in_reg; + reg [number_of_channels -1 : 0] fifo_in_sync_reg; + reg [number_of_channels -1 : 0] fifo_out_sync_reg; + reg [number_of_channels -1 : 0] bitslip_mux_out; + reg [number_of_channels -1 : 0] dpa_in; + reg [number_of_channels -1 : 0] retime_data; + reg [number_of_channels -1 : 0] dpll_lock; + reg [number_of_channels -1 : 0] dpll_first_lock; + reg [number_of_channels -1 : 0] rx_channel_data_align_pre; + reg [number_of_channels -1 : 0] write_side_sync_reset; + reg [number_of_channels -1 : 0] read_side_sync_reset; + + reg ram_array [(RAM_WIDTH*number_of_channels) -1 : 0]; + reg [2 : 0] wrPtr [number_of_channels -1 : 0]; + reg [2 : 0] rdPtr [number_of_channels -1 : 0]; + reg [3 : 0] bitslip_count [number_of_channels -1 : 0]; + reg [number_of_channels -1 : 0] start_corrupt_bits; + reg [1 : 0] num_corrupt_bits [number_of_channels -1 : 0]; + reg [number_of_channels -1 : 0] rx_cda_max; + reg [(MUX_WIDTH*number_of_channels) -1 : 0] shift_reg_chain; + reg enable0_reg; + +// INTERNAL WIRE DECLARATION + wire fifo_write_clk; + wire fifo_read_clk; + wire [number_of_channels -1 : 0] dpa_fifo_in; + wire [number_of_channels -1 : 0] dpa_fifo_out; + wire rx_in_reg_clk; + wire rx_bload; + +// INTERNAL TRI DECLARATION + tri0[number_of_channels -1 :0] rx_reset; + tri0[number_of_channels -1 :0] rx_dpll_reset; + tri0[number_of_channels -1 :0] rx_dpll_hold; + tri1[number_of_channels -1 :0] rx_dpll_enable; + tri0[number_of_channels -1 :0] rx_fifo_reset; + tri0[number_of_channels -1 :0] rx_channel_data_align; + tri0[number_of_channels -1 :0] rx_cda_reset; + +// LOCAL INTEGER DECLARATION + integer i; + integer i1; + integer i2; + integer i3; + integer i4; + integer i5; + integer i6; + integer i7; + integer i8; + integer j; + integer j1; + integer j2; + integer j3; + integer j4; + integer x; + integer dpll_clk_count[number_of_channels -1: 0]; + +// INITIAL CONSTRUCT BLOCK + initial + begin : INITIALIZATION + enable0_reg=0; + + for (i = 0; i < number_of_channels; i = i + 1) + begin + rx_in_reg[i] = 1'b0; + rx_cda_max[i] = 1'b0; + fifo_in_sync_reg[i] = 1'b0; + fifo_out_sync_reg[i] = 1'b0; + bitslip_mux_out[i] = 1'b0; + dpa_in[i] = 1'b0; + retime_data[i] = 1'b0; + wrPtr[i] = 0; + rdPtr[i] = 3; + bitslip_count[i] = 0; + dpll_clk_count[i] = 0; + dpll_lock[i] = 1'b0; + dpll_first_lock[i] = 1'b0; + start_corrupt_bits[i] = 0; + num_corrupt_bits[i] = 0; + + for (j = 0; j < RAM_WIDTH; j = j + 1) + ram_array[(i*RAM_WIDTH) + j] = 1'b0; + + for (j = 0; j < MUX_WIDTH; j = j + 1) + shift_reg_chain[(i*MUX_WIDTH) + j] = 1'b0; + end + + for (i = 0; i < REGISTER_WIDTH; i = i + 1) + begin + rx_shift_reg[i] = 0; + rx_parallel_load_reg[i] = 0; + end + + + end //INITIALIZATION + +// ALWAYS CONSTRUCT BLOCK + + // Fast clock (on rising edge) + always @ (posedge rx_fastclk) + begin : STRATIXII_DESER + if (rx_bload == 1) + rx_parallel_load_reg <= rx_shift_reg; + + for (i1 = 0; i1 < number_of_channels; i1 = i1+1) + begin + for (x=deserialization_factor-1; x >0; x=x-1) + rx_shift_reg[x + (i1 * deserialization_factor)] <= rx_shift_reg [x-1 + (i1 * deserialization_factor)]; + + rx_shift_reg[i1 * deserialization_factor] <= bitslip_mux_out[i1]; + end + + // Registering enable0 signal + enable0_reg <= rx_enable; + end // STRATIXII_DESER + + // input synchronization register + always @ (posedge rx_in_reg_clk) + begin : IN_SYNC_REGISTER + rx_in_reg <= rx_in; + end // IN_SYNC_REGISTER + + // Stratix II bitslip logic + always @ (posedge rx_cda_reset) + begin + for (i2 = 0; i2 <= number_of_channels-1; i2 = i2 + 1) + begin + if (rx_cda_reset[i2] == 1'b1) + begin + // reset the bitslipping circuitry. + bitslip_count[i2] <= 0; + rx_cda_max[i2] <= 1'b0; + end + end + end + + always @ (posedge rx_fastclk) + begin : STRATIXII_BITSLIP + for (i3 = 0; i3 <= number_of_channels-1; i3 = i3 + 1) + begin + if (rx_cda_reset[i3] !== 1'b1) + begin + if ((rx_channel_data_align[i3] === 1'b1) && + (rx_channel_data_align_pre[i3] === 1'b0)) + begin + // slipped data byte is corrupted. + start_corrupt_bits[i3] <= 1; + num_corrupt_bits[i3] <= 1; + + // Rollover has occurred. Serial data stream is reset back to 0 latency. + if (bitslip_count[i3] == data_align_rollover) + begin + bitslip_count[i3] <= 0; + rx_cda_max[i3] <= 1'b0; + end + else + begin + // increase the bit slip count. + bitslip_count[i3] <= bitslip_count[i3] + 1; + + // if maximum of bitslip limit has been reach, set rx_cda_max to high. + // Rollover will occur on the next bit slip. + if (bitslip_count[i3] == data_align_rollover - 1) + rx_cda_max[i3] <= 1'b1; + end + end + else if ((rx_channel_data_align[i3] === 1'b0) && + (rx_channel_data_align_pre[i3] === 1'b1)) + begin + start_corrupt_bits[i3] <= 0; + num_corrupt_bits[i3] <= 0; + end + end + + if (start_corrupt_bits[i3] == 1'b1) + begin + if (num_corrupt_bits[i3]+1 == 3) + start_corrupt_bits[i3] <= 0; + else + num_corrupt_bits[i3] <= num_corrupt_bits[i3] + 1; + end + + // load serial data stream into the shift register chain. + if ((enable_dpa_mode == "ON") && (rx_dpll_enable[i3] == 1'b1)) + shift_reg_chain[(i3*MUX_WIDTH) + 0] <= dpa_fifo_out[i3]; + else + shift_reg_chain[(i3*MUX_WIDTH) + 0] <= rx_in_reg[i3]; + + // propagate the serial data stream through the bitslip register chain. + for (j1 = 0; j1 < data_align_rollover; j1 = j1 + 1) + shift_reg_chain[(i3*MUX_WIDTH) + j1 + 1] <= shift_reg_chain[(i3*MUX_WIDTH) + j1]; + + // set the output to 'X' for 3 fast clock cycles after receiving the bitslip signal. + if (((rx_channel_data_align[i3] === 1'b1) && (rx_channel_data_align_pre[i3] === 1'b0)) || + ((start_corrupt_bits[i3] == 1'b1) && (num_corrupt_bits[i3] < 3) && + (rx_channel_data_align[i3] === 1'b1))) + bitslip_mux_out[i3] <= 1'bx; + else + bitslip_mux_out[i3] <= shift_reg_chain[(i3*MUX_WIDTH) + bitslip_count[i3]]; + + rx_channel_data_align_pre[i3] <= rx_channel_data_align[i3]; + end + end //STRATIXII_BITSLIP + + // Stratix II Phase Compensation FIFO + always @ (posedge fifo_write_clk or posedge rx_reset or posedge rx_fifo_reset) + begin : STRATIXII_DPA_FIFO_WRITE + for (i4 = 0; i4 <= number_of_channels-1; i4 = i4 + 1) + begin + if ((rx_reset[i4] == 1'b1) || (rx_fifo_reset[i4] == 1'b1) || + ((reset_fifo_at_first_lock == "ON") && + (dpll_first_lock[i4] == 1'b0))) + begin + wrPtr[i4] <= 0; + for (j2 = 0; j2 < RAM_WIDTH; j2 = j2 + 1) + ram_array[(i4*RAM_WIDTH) + j2] <= 1'b0; + fifo_in_sync_reg[i4] <= 1'b0; + write_side_sync_reset[i4] <= 1'b1; + end + else + begin + if (write_side_sync_reset[i4] <= 1'b0) + begin + wrPtr[i4] <= wrPtr[i4] + 1; + fifo_in_sync_reg[i4] <= dpa_fifo_in[i4]; + ram_array[(i4*RAM_WIDTH) + wrPtr[i4]] <= fifo_in_sync_reg[i4]; + if (wrPtr[i4] == 5) + wrPtr[i4] <= 0; + end + write_side_sync_reset[i4] <= 1'b0; + end + end + end //STRATIXII_DPA_FIFO_WRITE + + // Stratix II Phase Compensation FIFO + always @ (posedge fifo_read_clk or posedge rx_reset or posedge rx_fifo_reset) + begin : STRATIXII_DPA_FIFO_READ + for (i5 = 0; i5 <= number_of_channels-1; i5 = i5 + 1) + begin + if ((rx_reset[i5] == 1'b1) || (rx_fifo_reset[i5] == 1'b1) || + ((reset_fifo_at_first_lock == "ON") && + (dpll_first_lock[i5] == 1'b0))) + begin + rdPtr[i5] <= 3; + fifo_out_sync_reg[i5] <= 1'b0; + read_side_sync_reset[i5] <= 1'b1; + end + else + begin + if (read_side_sync_reset[i5] == 1'b0) + begin + rdPtr[i5] <= rdPtr[i5] + 1; + fifo_out_sync_reg[i5] <= ram_array[(i5*RAM_WIDTH) + rdPtr[i5]]; + if (rdPtr[i5] == 5) + rdPtr[i5] <= 0; + end + read_side_sync_reset[i5] <= 1'b0; + end + end + end //STRATIXII_DPA_FIFO_READ + + // Stratix II DPA Block + always @ (posedge rx_fastclk or posedge rx_reset) + begin : STRATIXII_DPA_BLOCK + for (i6 = 0; i6 <= number_of_channels-1; i6 = i6 + 1) + begin + if (rx_reset[i6] == 1'b1) + begin + dpll_clk_count[i6] <= 0; + dpll_lock[i6] <= 1'b0; + end + else + begin + dpll_clk_count[i6] <= dpll_clk_count[i6] + 1; + + if (dpll_clk_count[i6] == 2) + begin + dpll_lock[i6] <= 1'b1; + dpll_first_lock[i6] <= 1'b1; + end + end + end + end //STRATIXII_DPA_BLOCK + + always @ (posedge rx_fastclk) + begin + dpa_in <= rx_in; + retime_data <= dpa_in; + end + + + // CONTINOUS ASSIGNMENT + assign rx_out = rx_parallel_load_reg; + assign dpa_fifo_in = retime_data; + assign dpa_fifo_out = fifo_out_sync_reg; + assign fifo_write_clk = rx_fastclk; + assign fifo_read_clk = rx_fastclk; + assign rx_in_reg_clk = rx_fastclk; + assign rx_dpa_locked = dpll_lock; + assign rx_bload = enable0_reg; + +endmodule // stratixii_lvds_rx +// END OF MODULE + +//START_MODULE_NAME---------------------------------------------------- +// +// Module Name : flexible_lvds_rx +// +// Description : flexible lvds receiver +// +// Limitation : Only available to Cyclone and Cyclone II +// families. +// +// Results expected: Deserialized output data. +// +//END_MODULE_NAME---------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module flexible_lvds_rx ( + rx_in, // input serial data + rx_fastclk, // fast clock from PLL + rx_slowclk, // slow clock from PLL + rx_syncclk, // sync clock from PLL + rx_locked, // lock signal from PLL + rx_out // deserialized output data +); + +// GLOBAL PARAMETER DECLARATION + parameter number_of_channels = 1; + parameter deserialization_factor = 4; + parameter use_extra_ddio_register = "YES"; + parameter use_extra_pll_clk = "NO"; + +// LOCAL PARAMETER DECLARATION + parameter REGISTER_WIDTH = deserialization_factor*number_of_channels; + +// INPUT PORT DECLARATION + input [number_of_channels -1 :0] rx_in; + input rx_fastclk; + input rx_slowclk; + input rx_syncclk; + input rx_locked; + +// OUTPUT PORT DECLARATION + output [REGISTER_WIDTH -1: 0] rx_out; + +// INTERNAL REGISTERS DECLARATION + reg [REGISTER_WIDTH -1 : 0] rx_shift_reg; + reg [REGISTER_WIDTH -1 : 0] rx_shift_reg1; + reg [REGISTER_WIDTH -1 : 0] rx_shift_reg2; + reg [REGISTER_WIDTH -1 : 0] rx_sync_reg1; + reg [REGISTER_WIDTH -1 : 0] rx_sync_reg2; + reg [REGISTER_WIDTH -1 : 0] rx_sync_reg1_buf1; + reg [REGISTER_WIDTH -1 : 0] rx_sync_reg1_buf1_pipe; + reg [REGISTER_WIDTH -1 : 0] rx_sync_reg2_buf1; + reg [REGISTER_WIDTH -1 : 0] rx_sync_reg1_buf2; + reg [REGISTER_WIDTH -1 : 0] rx_sync_reg1_buf2_pipe; + reg [REGISTER_WIDTH -1 : 0] rx_sync_reg2_buf2; + reg [REGISTER_WIDTH -1 : 0] rx_out_odd; + reg [REGISTER_WIDTH -1 : 0] rx_out_odd_mode; + reg [number_of_channels -1 :0] ddio_h_reg; + reg [number_of_channels -1 :0] ddio_l_reg; + reg [number_of_channels -1 :0] datain_h_reg; + reg [number_of_channels -1 :0] datain_l_reg; + reg [number_of_channels -1 :0] datain_l_latch; + reg select_bit; + reg sync_clock; + +// INTERNAL WIRE DECLARATION + wire [REGISTER_WIDTH -1 : 0] rx_out; + +// LOCAL INTEGER DECLARATION + integer i; + integer x; + +// INITIAL CONSTRUCT BLOCK + initial + begin : INITIALIZATION + + rx_shift_reg = {REGISTER_WIDTH{1'b0}}; + rx_shift_reg1 = {REGISTER_WIDTH{1'b0}}; + rx_shift_reg2 = {REGISTER_WIDTH{1'b0}}; + rx_sync_reg1 = {REGISTER_WIDTH{1'b0}}; + rx_sync_reg2 = {REGISTER_WIDTH{1'b0}}; + rx_sync_reg1_buf1 = {REGISTER_WIDTH{1'b0}}; + rx_sync_reg1_buf1_pipe = {REGISTER_WIDTH{1'b0}}; + rx_sync_reg2_buf1 = {REGISTER_WIDTH{1'b0}}; + rx_sync_reg1_buf2 = {REGISTER_WIDTH{1'b0}}; + rx_sync_reg1_buf2_pipe = {REGISTER_WIDTH{1'b0}}; + rx_sync_reg2_buf2 = {REGISTER_WIDTH{1'b0}}; + rx_out_odd = {REGISTER_WIDTH{1'b0}}; + rx_out_odd_mode = {REGISTER_WIDTH{1'b0}}; + ddio_h_reg = {number_of_channels{1'b0}}; + ddio_l_reg = {number_of_channels{1'b0}}; + datain_h_reg = {number_of_channels{1'b0}}; + datain_l_reg = {number_of_channels{1'b0}}; + datain_l_latch = {number_of_channels{1'b0}}; + + select_bit = 1'b0; + sync_clock = 1'b0; + end //INITIALIZATION + + +// ALWAYS CONSTRUCT BLOCK + + // 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. + always @(posedge rx_fastclk) + begin : DDIO_IN + if (use_extra_ddio_register == "YES") + begin + ddio_h_reg <= rx_in; + datain_h_reg <= ddio_h_reg; + end + else + datain_h_reg <= rx_in; + + datain_l_reg <= datain_l_latch; + end // DDIO_IN + + always @(negedge rx_fastclk) + begin : DDIO_IN_LATCH + if (use_extra_ddio_register == "YES") + begin + ddio_l_reg <= rx_in; + datain_l_latch <= ddio_l_reg; + end + else + datain_l_latch <= rx_in; + end // DDIO_IN_LATCH + + // Loading input data to shift register + always @ (posedge rx_fastclk) + begin : SHIFTREG + + // Implementation for even deserialization factor. + if ((deserialization_factor % 2) == 0) + begin + for (i= 0; i < number_of_channels; i = i+1) + begin + for (x=deserialization_factor-1; x >1; x=x-1) + rx_shift_reg[x + (i * deserialization_factor)] <= + rx_shift_reg [x-2 + (i * deserialization_factor)]; + + rx_shift_reg[i * deserialization_factor] <= datain_h_reg[i]; + rx_shift_reg[(i * deserialization_factor)+1] <= datain_l_reg[i]; + end + end + else // Implementation for odd deserialization factor. + begin + for (i= 0; i < number_of_channels; i = i+1) + begin + for (x=deserialization_factor-1; x >1; x=x-1) + begin + 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 + rx_shift_reg1[i * deserialization_factor] <= datain_h_reg[i]; + rx_shift_reg1[(i * deserialization_factor)+1] <= datain_l_reg[i]; + 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 + end + end // SHIFTREG + + always @ (posedge rx_slowclk) + begin : BIT_SELECT + rx_sync_reg1 <= rx_shift_reg1; + rx_sync_reg2 <= rx_shift_reg2; + rx_sync_reg1_buf2_pipe <= rx_sync_reg1_buf2; + + if (rx_locked == 1'b1) + begin + sync_clock <= ~sync_clock; + select_bit <= ~select_bit; + end + + if(use_extra_pll_clk == "NO") + begin + if (select_bit) + rx_out_odd_mode <= rx_sync_reg1_buf1_pipe; + else + rx_out_odd_mode <= rx_sync_reg2_buf1; + end + else + begin + if (select_bit) + rx_out_odd_mode <= rx_sync_reg1_buf2_pipe; + else + rx_out_odd_mode <= rx_sync_reg2_buf2; + end + + rx_out_odd <= rx_out_odd_mode; + end // BIT_SELECT + + always @ (posedge sync_clock) + begin : SYNC_REG + rx_sync_reg1_buf1 <= rx_sync_reg1; + rx_sync_reg2_buf1 <= rx_sync_reg2; + rx_sync_reg1_buf1_pipe <= rx_sync_reg1_buf1; + end // SYNC_REG + + always @ (posedge rx_syncclk) + begin : SYNC_REG2 + rx_sync_reg1_buf2 <= rx_sync_reg1; + rx_sync_reg2_buf2 <= rx_sync_reg2; + end // SYNC_REG2 + +// CONTINOUS ASSIGNMENT + assign rx_out = ((deserialization_factor % 2) == 0) ? rx_shift_reg : + rx_out_odd; +endmodule // flexible_lvds_rx +// END OF MODULE + + +//START_MODULE_NAME-------------------------------------------------------------- +// +// Module 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 + +// Limitation : Only available for APEX20KE, APEXII, MERCURY, STRATIX, +// STRATIX GX, STRATIX II, CYCLONE and CYCLONEII families. +// +// Results expected: Output clock, serialized output data and pll locked signal. +// +//END_MODULE_NAME---------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +module altlvds_tx ( + tx_in, + tx_inclock, + tx_enable, + sync_inclock, + tx_pll_enable, + pll_areset, + + tx_out, + tx_outclock, + tx_coreclock, + tx_locked +); + + +// GLOBAL PARAMETER DECLARATION + + // No. of LVDS channels (required) + parameter number_of_channels = 1; + + // No. of bits per channel (required) + parameter deserialization_factor = 4; + + // Indicates whether the tx_in[] and tx_outclock ports should be registered. + parameter registered_input = "ON"; + + // "ON" means that sync_inclock is also used + // (not used for Stratix and Stratix GX devices.) + parameter multi_clock = "OFF"; + + // The period of the input clock in ps (Required) + parameter inclock_period = 10000; + + // Specifies the period of the tx_outclock port as + // [INCLOCK_PERIOD * OUTCLOCK_DIVIDE_BY] + parameter outclock_divide_by = deserialization_factor; + + // The effective clock period to sample output data + parameter inclock_boost = deserialization_factor; + + // Aligns the Most Significant Bit(MSB) to the falling edge of the clock + // instead of the rising edge. (only for APEX II devices) + parameter center_align_msb = "OFF"; + + // The device family to be used. + parameter intended_device_family = "APEX20KE"; + + // Data rate out of the PLL. (required and only for Stratix and + // Stratix GX devices) + parameter output_data_rate = 0; + + // The alignment of the input data with respect to the tx_inclock port. + // (required and only for Stratix and Stratix GX devices) + parameter inclock_data_alignment = "EDGE_ALIGNED"; + + // The alignment of the output data with respect to the tx_outclock port. + // (required and only for Stratix and Stratix GX devices) + parameter outclock_alignment = "EDGE_ALIGNED"; + + // Specifies whether the compiler uses the same PLL for both the LVDS + // receiver and the LVDS transmitter + parameter common_rx_tx_pll = "ON"; + + parameter outclock_resource = "AUTO"; + parameter use_external_pll = "OFF"; + parameter implement_in_les = "OFF"; + parameter preemphasis_setting = 0; + parameter vod_setting = 0; + parameter differential_drive = 0; + + parameter lpm_type = "altlvds_tx"; + parameter lpm_hint = "UNUSED"; + + // Specifies whether the source of the input clock is from a PLL + parameter clk_src_is_pll = "off"; + + +// LOCAL PARAMETER DECLARATION + + // A APEX20KE type of LVDS? + parameter APEX20KE_TX_STYLE = (intended_device_family == "APEX20KE") || + (intended_device_family == "EXCALIBUR_ARM") || + (intended_device_family == "EXCALIBUR_MIPS") || + (intended_device_family == "APEX20KC") + ? 1 : 0; + + // A APEXII type of LVDS? + parameter APEXII_TX_STYLE = (intended_device_family == "APEXII") || + (intended_device_family == "APEX II") + ? 1 : 0; + + // A MERCURY type of LVDS? + parameter MERCURY_TX_STYLE = (intended_device_family == "MERCURY") || + (intended_device_family == "Mercury") + ? 1 : 0; + + // A STRATIX type of LVDS? + parameter STRATIX_TX_STYLE = (intended_device_family == "Stratix") || + (intended_device_family == "STRATIX") || + (intended_device_family == "STRATIXGX") || + (intended_device_family == "STRATIX-GX") || + (intended_device_family == "Stratix GX") || + (intended_device_family == "HardCopy Stratix") || + (intended_device_family == "HARDCOPY STRATIX") || + (intended_device_family == "hardcopy stratix") || + (intended_device_family == "HardcopyStratix") || + (intended_device_family == "HARDCOPYSTRATIX") || + (intended_device_family == "hardcopystratix") + ? 1 : 0; + + // A STRATIXII type of LVDS? + parameter STRATIXII_TX_STYLE = ((intended_device_family == "Stratix II") || + (intended_device_family == "StratixII") || + (intended_device_family == "HardCopy II") || + (intended_device_family == "HardCopyII") || + (intended_device_family == "HARDCOPY II") || + (intended_device_family == "HARDCOPYII") || + (intended_device_family == "hardcopy ii") || + (intended_device_family == "hardcopyii") || + (intended_device_family == "Stratix II GX") || + (intended_device_family == "STRATIX II GX") || + (intended_device_family == "stratix ii gx") || + (intended_device_family == "StratixIIGX") || + (intended_device_family == "STRATIXIIGX") || + (intended_device_family == "stratixiigx")) + ? 1 : 0; + + // A Cyclone type of LVDS? + parameter CYCLONE_TX_STYLE = ((intended_device_family == "Cyclone") || + (intended_device_family == "CYCLONE") || + (intended_device_family == "cyclone")) + ? 1 : 0; + + // A Cyclone II type of LVDS? + parameter CYCLONEII_TX_STYLE = ((intended_device_family == "Cyclone II") || + (intended_device_family == "CYCLONE II") || + (intended_device_family == "cyclone ii") || + (intended_device_family == "Cycloneii") || + (intended_device_family == "CYCLONEII") || + (intended_device_family == "cycloneii")) + ? 1 : 0; + + // Is the device family has flexible LVDS? +parameter FAMILY_HAS_FLEXIBLE_LVDS = ((CYCLONE_TX_STYLE == 1) || + (CYCLONEII_TX_STYLE == 1) || + (((STRATIX_TX_STYLE == 1) || (STRATIXII_TX_STYLE == 1)) && + (implement_in_les == "ON"))) + ? 1 : 0; + + // Is the family has Stratix style PLL + parameter FAMILY_HAS_STRATIX_STYLE_PLL = ((STRATIX_TX_STYLE == 1) || + (CYCLONE_TX_STYLE == 1)) + ? 1 : 0; + + // Is the family has Stratix style PLL + parameter FAMILY_HAS_STRATIXII_STYLE_PLL = ((STRATIXII_TX_STYLE == 1) || + (CYCLONEII_TX_STYLE == 1)) + ? 1 : 0; + + // Parameter to check whether the selected lvds trasmitter use + // holding register or not. + parameter TX_NEED_HOLD = (((APEX20KE_TX_STYLE == 1) && + (deserialization_factor >= 7)) || + ((APEXII_TX_STYLE == 1) && + (deserialization_factor >= 5)) || + ((MERCURY_TX_STYLE == 1) && + (deserialization_factor >= 7))) + ? 1 : 0; + + // calculate clock boost for device family other than STRATIX and STRATIX GX + parameter INT_CLOCK_BOOST = (APEX20KE_TX_STYLE == 1) + ? deserialization_factor : + ((inclock_boost == 0) + ? deserialization_factor + : inclock_boost); + + // M value for Stratix/Stratix II/Cyclone/Cyclone II PLL + parameter PLL_M_VALUE = (((output_data_rate * inclock_period) + + (5 * 100000)) / 1000000); + + // D value for Stratix/Stratix II/Cyclone/Cyclone II PLL + parameter PLL_D_VALUE = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? ((output_data_rate !=0) && (inclock_period !=0) + ? 2 + : 1) + : 1; + + // calculate clock boost for STRATIX, STRATIX GX and STRATIX II + parameter STRATIX_INCLOCK_BOOST = + ((output_data_rate !=0) && (inclock_period !=0)) + ? PLL_M_VALUE : + ((inclock_boost == 0) + ? deserialization_factor + : inclock_boost); + + // parameter for inclock phase shift. Add 0.5 to the calculated result to + // round up result to the nearest integer. + // CENTER_ALIGNED means 180 degrees + parameter PHASE_INCLOCK = (inclock_data_alignment == "EDGE_ALIGNED")? + 0 : + (inclock_data_alignment == "CENTER_ALIGNED") ? + (0.5 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5: + (inclock_data_alignment == "45_DEGREES") ? + (0.125 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5: + (inclock_data_alignment == "90_DEGREES") ? + (0.25 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5: + (inclock_data_alignment == "135_DEGREES") ? + (0.375 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5: + (inclock_data_alignment == "180_DEGREES") ? + (0.5 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5: + (inclock_data_alignment == "225_DEGREES") ? + (0.625 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5: + (inclock_data_alignment == "270_DEGREES") ? + (0.75 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5: + (inclock_data_alignment == "315_DEGREES") ? + (0.875 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5: 0; + + // parameter for Stratix II inclock phase shift. + parameter STXII_PHASE_INCLOCK = PHASE_INCLOCK - (0.5 * inclock_period / STRATIX_INCLOCK_BOOST); + + // parameter for outclock phase shift. Add 0.5 to the calculated result to + // round up result to the nearest integer. + parameter PHASE_OUTCLOCK = (outclock_alignment == "EDGE_ALIGNED") ? + 0: + (outclock_alignment == "CENTER_ALIGNED") ? + ((0.5 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5): + (outclock_alignment == "45_DEGREES") ? + ((0.125 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5): + (outclock_alignment == "90_DEGREES") ? + ((0.25 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5): + (outclock_alignment == "135_DEGREES") ? + ((0.375 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5): + (outclock_alignment == "180_DEGREES") ? + ((0.5 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5): + (outclock_alignment == "225_DEGREES") ? + ((0.625 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5): + (outclock_alignment == "270_DEGREES") ? + ((0.75 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5): + (outclock_alignment == "315_DEGREES") ? + ((0.875 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5): 0; + + // parameter for Stratix and Stratix GX outclock phase shift. + // Add 0.5 to the calculated result to round up result to the nearest integer. + parameter STX_PHASE_OUTCLOCK = ((outclock_divide_by == 1) || + (outclock_alignment == "45_DEGREES") || + (outclock_alignment == "90_DEGREES") || + (outclock_alignment == "135_DEGREES")) ? + PHASE_OUTCLOCK + PHASE_INCLOCK: + ((outclock_alignment == "180_DEGREES") || + (outclock_alignment == "CENTER_ALIGNED")) ? + PHASE_INCLOCK : + (outclock_alignment == "225_DEGREES") ? + ((0.125 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5 + PHASE_INCLOCK): + (outclock_alignment == "270_DEGREES") ? + ((0.25 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5 + PHASE_INCLOCK): + (outclock_alignment == "315_DEGREES") ? + ((0.375 * inclock_period / STRATIX_INCLOCK_BOOST) + + 0.5 + PHASE_INCLOCK): PHASE_INCLOCK; + + // parameter for Stratix II outclock phase shift. + parameter STXII_PHASE_OUTCLOCK = STX_PHASE_OUTCLOCK - (0.5 * inclock_period / STRATIX_INCLOCK_BOOST); + + parameter REGISTER_WIDTH = deserialization_factor * number_of_channels; + + // input clock period for PLL. + parameter CLOCK_PERIOD = (deserialization_factor > 2) ? inclock_period : 10000; + + +// INPUT PORT DECLARATION + + // Input data (required) + input [REGISTER_WIDTH -1 : 0] tx_in; + + // Input clock (required) + input tx_inclock; + + input tx_enable; + + // Optional clock for input registers (Required if "multi_clock" parameters + // is turned on) + input sync_inclock; + + // Enable control for the LVDS PLL + input tx_pll_enable; + + // Asynchronously resets all counters to initial values (only for Stratix + // and Stratix GX devices) + input pll_areset; + + + +// OUTPUT PORT DECLARATION + + // Serialized data signal(required) + output [number_of_channels-1 :0] tx_out; + + // External reference clock + output tx_outclock; + + // Output clock used to feed non-peripheral logic. + // Only available for Mercury, Stratix, and Stratix GX devices only. + output tx_coreclock; + + // Gives the status of the LVDS PLL + // (when the PLL is locked, this signal is VCC. GND otherwise) + output tx_locked; + + +// INTERNAL REGISTERS DECLARATION + + reg [REGISTER_WIDTH -1 : 0] tx_hold_reg; + reg [REGISTER_WIDTH -1 : 0] tx_in_reg; + reg [REGISTER_WIDTH -1 : 0] tx_shift_reg; + reg [REGISTER_WIDTH -1 : 0] tx_parallel_load_reg; + reg tx_mercury_core_clock; + reg fb; + reg [number_of_channels-1 :0] tx_out_apex; + reg [number_of_channels-1 :0] tx_out_stratix; + reg [number_of_channels-1 :0] tx_ddio_out; + reg [number_of_channels-1 :0] dataout_l; + reg [number_of_channels-1 :0] dataout_h; + reg enable0_reg1; + reg enable0_reg2; + reg enable0_neg; + reg tx_fastclk_pre; + reg [9 : 0] stx_phase_shift_txdata; + reg [9 : 0] phase_shift_txdata; + + +// INTERNAL WIRE DECLARATION + + wire [REGISTER_WIDTH -1 : 0] tx_in_int; + wire tx_fastclk; + wire tx_slowclk; + wire tx_reg_clk; + wire tx_hold_clk; + wire tx_coreclock_int; + wire tx_locked_int; + wire unused_clk_ext; + wire [2:0] altclklock_clk; + wire altclklock_locked; + wire altclklock_inclock; + wire altclklock_clkena; + wire [1:0] stratix_pll_inclock; + wire [1:0] stratixii_pll_inclock; + wire [5:0] stratix_pll_outclock; + wire [5:0] stratixii_pll_outclock; + wire stratix_pll_enable; + wire stratixii_pll_enable; + wire stratix_pll_areset; + wire stratixii_pll_areset; + wire stratix_locked; + wire stratixii_locked; + wire stratix_enable0; + wire stratixii_enable0; + wire stratix_enable1; + wire stratixii_enable1; + wire stratix_outclock; + wire stratixii_outclock; + wire stratixii_sclkout0; + wire stratixii_sclkout1; + wire stratix_inclock; + wire stratix_enable; + wire stratixii_inclock; + wire stratixii_enable; + wire flvds_fastclk; + wire flvds_slowclk; + wire flvds_regclk; + wire[number_of_channels-1 :0] flvds_dataout; + +// INTERNAL TRI DECLARATION + + tri1 tx_enable; + tri0 sync_inclock; + tri1 tx_pll_enable; + tri0 pll_areset; + +// LOCAL INTEGER DECLARATION + + integer count; + integer i; + integer i1; + integer i2; + integer posedge_count; + integer negedge_count; + integer shift_data; + +// LOCAL TIME DECLARATION + + time tx_out_delay; + +// COMPONENT INSTANTIATIONS + ALTERA_DEVICE_FAMILIES dev (); + +// INITIAL CONSTRUCT BLOCK + + initial + begin : INITIALIZATION + tx_in_reg = {REGISTER_WIDTH{1'b0}}; + tx_hold_reg = {REGISTER_WIDTH{1'b0}}; + tx_parallel_load_reg = {REGISTER_WIDTH{1'b0}}; + tx_shift_reg = {REGISTER_WIDTH{1'b0}}; + + tx_out_apex = {number_of_channels{1'b0}}; + tx_out_stratix = {number_of_channels{1'b0}}; + tx_ddio_out = {number_of_channels{1'b0}}; + dataout_l = {number_of_channels{1'b0}}; + dataout_h = {number_of_channels{1'b0}}; + + fb = 'b1; + count = 0; + shift_data = 0; + negedge_count = 0; + posedge_count = 0; + + tx_out_delay = inclock_period/(deserialization_factor*2); + + // Input data needed by stratix_tx_outclk in order to generate the tx_outclock. + stx_phase_shift_txdata = 0; + if (outclock_divide_by > 1) + begin + if (deserialization_factor == 4) + begin + if ( outclock_divide_by == 2) + stx_phase_shift_txdata[3:0] = 4'b1010; + else if (outclock_divide_by == 4) + stx_phase_shift_txdata[3:0] = 4'b0011; + end + else if (deserialization_factor == 8) + begin + if (outclock_divide_by == 2) + stx_phase_shift_txdata[7:0] = 8'b10101010; + else if (outclock_divide_by == 4) + stx_phase_shift_txdata[7:0] = 8'b00110011; + else if (outclock_divide_by == 8) + stx_phase_shift_txdata[7:0] = 8'b11000011; + end + else if (deserialization_factor == 10) + begin + if (outclock_divide_by == 2) + stx_phase_shift_txdata[9:0] = 10'b1010101010; + else if (outclock_divide_by == 10) + stx_phase_shift_txdata[9:0] = 10'b1110000011; + end + else if (deserialization_factor == 7) + if (outclock_divide_by == 7) + stx_phase_shift_txdata[6:0] = 7'b1100011; + end + + // Input data needed by stratixii_tx_outclk in order to generate the tx_outclock. + phase_shift_txdata = 0; + if (outclock_divide_by > 1) + begin + if (deserialization_factor == 4) + begin + if ( outclock_divide_by == 2) + phase_shift_txdata[3:0] = 4'b1010; + else if (outclock_divide_by == 4) + phase_shift_txdata[3:0] = 4'b1100; + end + else if (deserialization_factor == 6) + begin + if (outclock_divide_by == 2) + phase_shift_txdata[5:0] = 6'b101010; + else if (outclock_divide_by == 6) + phase_shift_txdata[5:0] = 6'b111000; + end + else if (deserialization_factor == 8) + begin + if (outclock_divide_by == 2) + phase_shift_txdata[7:0] = 8'b10101010; + else if (outclock_divide_by == 4) + phase_shift_txdata[7:0] = 8'b11001100; + else if (outclock_divide_by == 8) + phase_shift_txdata[7:0] = 8'b11110000; + end + else if (deserialization_factor == 10) + begin + if (outclock_divide_by == 2) + phase_shift_txdata[9:0] = 10'b1010101010; + else if (outclock_divide_by == 10) + phase_shift_txdata[9:0] = 10'b1111100000; + end + else if (deserialization_factor == 7) + if (outclock_divide_by == 7) + phase_shift_txdata[6:0] = 7'b1111000; + end + + // Check for illegal mode settings + if ((APEX20KE_TX_STYLE == 1) && (deserialization_factor != 1) && + (deserialization_factor != 4) && (deserialization_factor != 7) && + (deserialization_factor != 8)) + begin + $display ($time, "ps Error: APEX20KE does not support the specified deserialization factor!"); + $finish; + end + else if ((MERCURY_TX_STYLE == 1) && + (deserialization_factor != 1) && (deserialization_factor != 2) && + (((deserialization_factor > 12) && + (deserialization_factor != 14) && + (deserialization_factor != 16) && + (deserialization_factor != 18) && + (deserialization_factor != 20)) ||(deserialization_factor < 3))) + begin + $display ($time, "ps Error: MERCURY does not support the specified deserialization factor!"); + $finish; + end + else if (((APEXII_TX_STYLE == 1)) && + ((deserialization_factor > 10) || (deserialization_factor < 4)) && + (deserialization_factor != 1) && (deserialization_factor != 2)) + begin + $display ($time, "ps Error: APEXII does not support the specified deserialization factor!"); + $finish; + end + else if ((STRATIX_TX_STYLE == 1) && + (deserialization_factor != 1) && (deserialization_factor != 2) && + ((deserialization_factor > 10) || (deserialization_factor < 4))) + begin + $display ($time, "ps Error: STRATIX does not support the specified deserialization factor!"); + $finish; + end + else if ((STRATIXII_TX_STYLE == 1) && + (deserialization_factor > 10)) + begin + $display ($time, "ps Error: STRATIX II does not support the specified deserialization factor!"); + $finish; + end + + if (CYCLONE_TX_STYLE == 1) + begin + if ((use_external_pll == "ON") && + (deserialization_factor != 1) && (deserialization_factor != 2) && + (deserialization_factor != 4) && (deserialization_factor != 6) && + (deserialization_factor != 8) && (deserialization_factor != 10)) + begin + $display ($time, "ps Error: Cyclone does not support the specified deserialization factor when use_external_pll is 'ON'!"); + $finish; + end + else if ((deserialization_factor > 10) || (deserialization_factor == 3)) + begin + $display ($time, "ps Error: Cyclone does not support the specified deserialization factor when use_external_pll is 'OFF'!"); + $finish; + end + end + + if (CYCLONEII_TX_STYLE == 1) + begin + if ((use_external_pll == "ON") && + (deserialization_factor != 1) && (deserialization_factor != 2) && + (deserialization_factor != 4) && (deserialization_factor != 6) && + (deserialization_factor != 8) && (deserialization_factor != 10)) + begin + $display ($time, "ps Error: Cyclone II does not support the specified deserialization factor when use_external_pll is 'ON'!"); + $finish; + end + else if ((deserialization_factor > 10) || (deserialization_factor == 3)) + begin + $display ($time, "ps Error: Cyclone II does not support the specified deserialization factor when use_external_pll is 'OFF'!"); + $finish; + end + end + + if (dev.IS_VALID_FAMILY(intended_device_family) == 0) + begin + $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family); + $finish; + end + + if (dev.IS_VALID_FAMILY(intended_device_family) == 0) + begin + $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family); + $finish; + end + + end // INITIALIZATION + + +// COMPONENT INSTANTIATIONS + + // PLL for device family other than Stratix, Stratix GX and Stratix II + altclklock u0 ( + .inclock(altclklock_inclock), // Required + .inclocken(altclklock_clkena), + .fbin(fb), + .clock0(altclklock_clk[0]), + .clock1(altclklock_clk[1]), + .clock2(altclklock_clk[2]), + .clock_ext(unused_clk_ext), + .locked(altclklock_locked)); + + defparam + u0.inclock_period = CLOCK_PERIOD, + u0.clock0_boost = INT_CLOCK_BOOST, + u0.clock1_boost = INT_CLOCK_BOOST, + u0.clock1_divide = deserialization_factor, + u0.clock2_boost = (MERCURY_TX_STYLE == 1) ? + INT_CLOCK_BOOST : 1, + u0.clock2_divide = (MERCURY_TX_STYLE == 1) ? + outclock_divide_by : 1, + u0.valid_lock_cycles = (APEXII_TX_STYLE == 1) ? 1 : + (MERCURY_TX_STYLE == 1) ? 3 : 5, + u0.intended_device_family = ((APEX20KE_TX_STYLE == 1 ) || + (APEXII_TX_STYLE == 1 ) || + (MERCURY_TX_STYLE == 1 )) + ? intended_device_family + : "APEX20KE"; + + + // PLL for Stratix and Stratix GX + MF_stratix_pll u1 ( + .inclk(stratix_pll_inclock), // Required + .ena(stratix_pll_enable), + .areset(stratix_pll_areset), + .clkena(6'b111111), + .clk (stratix_pll_outclock), + .locked(stratix_locked), + .fbin(1'b1), + .clkswitch(1'b0), + .pfdena(1'b1), + .extclkena(4'b0), + .scanclk(1'b0), + .scanaclr(1'b0), + .scandata(1'b0), + .comparator(1'b0), + .extclk(), + .clkbad(), + .enable0(stratix_enable0), + .enable1(stratix_enable1), + .activeclock(), + .clkloss(), + .scandataout() ); + + defparam + u1.primary_clock = "inclk0", + u1.pll_type = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? "flvds" + : "lvds", + u1.inclk0_input_frequency = CLOCK_PERIOD, + u1.valid_lock_multiplier = 1, + u1.clk0_multiply_by = STRATIX_INCLOCK_BOOST, + u1.clk0_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PLL_D_VALUE + : 1, + u1.clk0_phase_shift_num = PHASE_INCLOCK, + u1.clk1_multiply_by = STRATIX_INCLOCK_BOOST, + u1.clk1_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PLL_D_VALUE*outclock_divide_by + : 1, + u1.clk1_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PHASE_OUTCLOCK + : STX_PHASE_OUTCLOCK, + u1.clk2_multiply_by = STRATIX_INCLOCK_BOOST, + u1.clk2_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? ((deserialization_factor%2 == 0) + ? PLL_D_VALUE*deserialization_factor/2 + : PLL_D_VALUE*deserialization_factor) + : deserialization_factor, + u1.clk2_phase_shift_num = PHASE_INCLOCK, + u1.simulation_type = "functional", + u1.m = 0; + + // PLL for Stratix II + MF_stratixii_pll u2 ( + .inclk(stratixii_pll_inclock), // Required + .ena(stratixii_pll_enable), + .areset(stratixii_pll_areset), + .clk (stratixii_pll_outclock ), + .locked(stratixii_locked), + .fbin(1'b1), + .clkswitch(1'b0), + .pfdena(1'b1), + .scanclk(1'b0), + .scanread(1'b0), + .scanwrite(1'b0), + .scandata(1'b0), + .testin(4'b0), + .clkbad(), + .enable0(stratixii_enable0), + .enable1(stratixii_enable1), + .activeclock(), + .clkloss(), + .scandataout(), + .scandone(), + .sclkout({stratixii_sclkout1, stratixii_sclkout0}), + .testupout(), + .testdownout()); + + defparam + u2.primary_clock = "inclk0", + u2.pll_type = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? "flvds" + : "lvds", + u2.vco_multiply_by = STRATIX_INCLOCK_BOOST, + u2.vco_divide_by = 1, + u2.inclk0_input_frequency = CLOCK_PERIOD, + u2.clk0_multiply_by = STRATIX_INCLOCK_BOOST, + u2.clk0_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PLL_D_VALUE + : deserialization_factor, + u2.clk0_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PHASE_INCLOCK + : STXII_PHASE_INCLOCK, + u2.clk1_multiply_by = STRATIX_INCLOCK_BOOST, + u2.clk1_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PLL_D_VALUE*outclock_divide_by + : deserialization_factor, + u2.clk1_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PHASE_OUTCLOCK + : STXII_PHASE_OUTCLOCK, + u2.clk2_multiply_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? STRATIX_INCLOCK_BOOST + : 1, + u2.clk2_divide_by = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? ((deserialization_factor%2 == 0) + ? PLL_D_VALUE*deserialization_factor/2 + : PLL_D_VALUE*deserialization_factor) + : 1, + u2.clk2_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? PHASE_INCLOCK + : 1, + u2.sclkout0_phase_shift = STXII_PHASE_INCLOCK, + u2.sclkout1_phase_shift = STXII_PHASE_OUTCLOCK, + u2.simulation_type = "functional", + u2.m = 0; + + + // This module produces output clock for Stratix and Stratix GX. + stratix_tx_outclk u3 ( + .tx_in(stx_phase_shift_txdata), + .tx_fastclk(stratix_inclock), + .tx_enable(stratix_enable), + .tx_out(stratix_outclock)); + defparam + u3.deserialization_factor = deserialization_factor, + u3.bypass_serializer = (outclock_divide_by == 1) ? + "TRUE" : "'FALSE", + u3.use_falling_clock_edge = ((outclock_alignment == "180_DEGREES") || + (outclock_alignment == "CENTER_ALIGNED") || + (outclock_alignment == "225_DEGREES") || + (outclock_alignment == "270_DEGREES") || + (outclock_alignment == "315_DEGREES")) ? + "TRUE" : "FALSE"; + + + // This module produces output clock for StratixII. + stratixii_tx_outclk u4 ( + .tx_in(phase_shift_txdata), + .tx_fastclk(stratixii_inclock), + .tx_enable(stratixii_enable), + .tx_out(stratixii_outclock)); + + defparam + u4.deserialization_factor = deserialization_factor, + u4.bypass_serializer = (outclock_divide_by == 1) ? + "TRUE" : "'FALSE", + u4.use_falling_clock_edge = ((outclock_alignment == "180_DEGREES") || + (outclock_alignment == "CENTER_ALIGNED") || + (outclock_alignment == "225_DEGREES") || + (outclock_alignment == "270_DEGREES") || + (outclock_alignment == "315_DEGREES")) ? + "TRUE" : "FALSE"; + + // This module produces output clock for StratixII. + flexible_lvds_tx u5 ( + .tx_in(tx_in), + .tx_fastclk(flvds_fastclk), + .tx_slowclk(flvds_slowclk), + .tx_regclk(flvds_regclk), + .tx_locked(tx_locked_int), + .tx_out(flvds_dataout)); + + defparam + u5.number_of_channels = number_of_channels, + u5.deserialization_factor = deserialization_factor, + u5.registered_input = registered_input; + +// ALWAYS CONSTRUCT BLOCK + + // For x2 mode. For each data channel, input data are separated into 2 data + // stream which will be transmitted on different edge of input clock. + always @ (posedge tx_inclock) + begin : DDIO_OUT_RECEIVE + if (deserialization_factor == 2) + begin + for (i1 = 0; i1 < number_of_channels; i1 = i1 +1) + begin + dataout_l[i1] <= tx_in_int[i1*2]; + dataout_h[i1] <= tx_in_int[i1*2+1]; + end + end + end // DDIO_OUT_RECEIVE + + // Fast Clock + always @ (posedge tx_fastclk) + begin : FAST_CLOCK_POS + if (deserialization_factor > 2) + begin + + // registering load enable signal + enable0_reg2 <= enable0_reg1; + enable0_reg1 <= (use_external_pll == "ON") ? tx_enable : + (STRATIX_TX_STYLE == 1) ? stratix_enable0 : + stratixii_enable0; + + if ((STRATIX_TX_STYLE == 0) && (STRATIXII_TX_STYLE == 0)) + begin + posedge_count <= (posedge_count+1) % deserialization_factor; + if (posedge_count == 2) + begin + // register incoming data on the third edge + tx_shift_reg <= tx_parallel_load_reg; + count <= 2; + for (i = 0; i < number_of_channels; i = i +1) + // Data in MSB gets shifted out first. + // NB: This happens 1/2clk cycle later for APEXII (MSB + // only) when center_align_msb is ON. + begin + if ((i == number_of_channels-1) && + ((APEXII_TX_STYLE == 1)) && + (center_align_msb == "ON")) + begin + tx_out_apex[i] <= #tx_out_delay + tx_parallel_load_reg[(i+1)*deserialization_factor - 1]; + end + else + begin + tx_out_apex[i] <= tx_parallel_load_reg[(i+1)*deserialization_factor - 1]; + end + end + + end + else + begin + count <= count + 1; + for (i = 0; i < number_of_channels; i = i +1) + // Data in MSB gets shifted out first. + // NB: This happens 1/2clk cycle later for APEXII (MSB + // only) when center_align_msb is ON. + begin + if ((i == number_of_channels-1) && + ((APEXII_TX_STYLE == 1)) && + (center_align_msb == "ON")) + begin + tx_out_apex[i] <= #tx_out_delay + tx_shift_reg[(i+1)*deserialization_factor - count]; + end + else + begin + tx_out_apex[i] <= tx_shift_reg[(i+1)*deserialization_factor - count]; + end + end + end + + // Mercury core clock is assymmetrical for odd deserialization + // factor values. + if (posedge_count == ((deserialization_factor+1)/2+1)) + begin + tx_mercury_core_clock <= ~tx_mercury_core_clock; + end + end + else + begin + if(((STRATIX_TX_STYLE == 1) && (enable0_neg == 1)) || + ((STRATIXII_TX_STYLE == 1) && (enable0_reg1 == 1))) + begin + tx_shift_reg <= tx_parallel_load_reg; + count <= 2; + + for (i = 0; i < number_of_channels; i = i +1) + begin + tx_out_stratix[i] <= tx_parallel_load_reg[(i+1)*deserialization_factor - 1]; + end + end + else + begin + count <= (count % deserialization_factor) + 1; + for (i = 0; i < number_of_channels; i = i +1) + begin + tx_out_stratix[i] <= tx_shift_reg[(i+1)*deserialization_factor - count]; + end + end + + // Loading data to parallel load register for Stratix and + // Stratix GX + if (((STRATIX_TX_STYLE == 1) && (stratix_enable0 == 1)) || + (STRATIXII_TX_STYLE == 1)) + begin + tx_parallel_load_reg <= tx_in_int; + end + end + end + end // FAST_CLOCK_POS + + always @ (negedge tx_fastclk) + begin : FAST_CLOCK_NEG + if (deserialization_factor > 2) + begin + // registering load enable signal + enable0_neg <= enable0_reg2; + + negedge_count <= negedge_count + 1; + + // Loading data to parallel load register for non-STRATIX family + if ((negedge_count == 2) && (STRATIX_TX_STYLE == 0) && + (STRATIXII_TX_STYLE == 0) && + (tx_locked_int == 1)) + begin + if (TX_NEED_HOLD == 1) + begin + tx_parallel_load_reg <= tx_hold_reg; + end + else + begin + tx_parallel_load_reg <= tx_in_int; + end + end + end + end // FAST_CLOCK_NEG + + // Slow Clock + always @ (posedge tx_slowclk) + begin : SLOW_CLOCK + negedge_count <= 0; + tx_mercury_core_clock <= tx_slowclk; + end // SLOW_CLOCK + + // synchronization register + always @ (posedge tx_reg_clk) + begin : SYNC_REGISTER + tx_in_reg <= #5 tx_in; + end // SYNC_REGISTER + + // hold register + always @ (negedge tx_hold_clk) + begin : HOLD_REGISTER + if (deserialization_factor > 1) + begin + tx_hold_reg <= tx_in_int; + end + end // HOLD_REGISTER + + + // CONTINOUS ASSIGNMENT + assign tx_out = (deserialization_factor == 1) + ? tx_in_int : + (deserialization_factor == 2) + ? ((tx_inclock == 1) ? dataout_h : dataout_l) : + (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? flvds_dataout : + ((STRATIX_TX_STYLE == 1) || (STRATIXII_TX_STYLE == 1)) + ? tx_out_stratix + : tx_out_apex; + + assign tx_in_int = (registered_input != "OFF") + ? tx_in_reg + : tx_in; + + assign tx_reg_clk = ((STRATIX_TX_STYLE == 1) || + (((STRATIXII_TX_STYLE == 1) || + (CYCLONE_TX_STYLE == 1) || + (CYCLONEII_TX_STYLE == 1)) && + (use_external_pll == "OFF"))) + ? ((registered_input == "TX_CLKIN") + ? tx_inclock + : tx_coreclock_int) : + (((registered_input == "ON") && + (multi_clock == "ON")) + ? sync_inclock + : tx_inclock); + + assign tx_hold_clk = (multi_clock == "ON") + ? sync_inclock : + ((MERCURY_TX_STYLE == 1) + ? tx_coreclock_int + : tx_inclock); + + assign tx_outclock = (deserialization_factor < 3) + ? tx_inclock : + ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIX_STYLE_PLL == 1)) + ? stratix_pll_outclock[1] : + ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)) + ? stratixii_pll_outclock[1] : + (STRATIX_TX_STYLE == 1) + ? stratix_outclock : + (STRATIXII_TX_STYLE == 1) + ? stratixii_outclock : + (MERCURY_TX_STYLE == 1) + ? altclklock_clk[2] : + (APEXII_TX_STYLE == 1) + ? tx_inclock + : tx_slowclk; + + assign tx_coreclock = tx_coreclock_int; + + assign tx_coreclock_int = (deserialization_factor < 3) + ? 1'b0 : + (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? flvds_slowclk : + (((deserialization_factor % 2) != 0) && + (MERCURY_TX_STYLE == 1)) + ? tx_mercury_core_clock + : tx_slowclk; + + assign tx_locked = (deserialization_factor > 2) + ? tx_locked_int + : 1'b1; + + assign tx_locked_int = ((STRATIX_TX_STYLE == 1) || + (CYCLONE_TX_STYLE == 1)) + ? stratix_locked : + ((STRATIXII_TX_STYLE == 1) || + (CYCLONEII_TX_STYLE == 1)) + ? stratixii_locked + : altclklock_locked; + + assign tx_fastclk = ((deserialization_factor < 3) || + (FAMILY_HAS_FLEXIBLE_LVDS == 1)) + ? 1'b0 : + (use_external_pll == "ON") + ? tx_inclock : + (STRATIX_TX_STYLE == 1) + ? stratix_pll_outclock[0] : + (STRATIXII_TX_STYLE == 1) + ? stratixii_sclkout0 + : altclklock_clk[0]; + + assign tx_slowclk = ((use_external_pll == "ON") || + (FAMILY_HAS_FLEXIBLE_LVDS == 1)) + ? 1'b0 : + (STRATIX_TX_STYLE == 1) + ? stratix_pll_outclock[2] : + (STRATIXII_TX_STYLE == 1) + ? stratixii_pll_outclock[0] + : altclklock_clk[1]; + + assign altclklock_inclock = ((STRATIX_TX_STYLE == 1) || + (STRATIXII_TX_STYLE == 1) || + (FAMILY_HAS_FLEXIBLE_LVDS == 1)) + ? 0 + : tx_inclock; + + assign altclklock_clkena = ((FAMILY_HAS_STRATIX_STYLE_PLL == 1) || + (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)) + ? 0 + : tx_pll_enable; + + assign stratix_pll_inclock[1:0] = (FAMILY_HAS_STRATIX_STYLE_PLL == 1) + ? {1'b0, tx_inclock} + : 2'b00; + + assign stratixii_pll_inclock[1:0] = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1) + ? {1'b0, tx_inclock} + : 2'b00; + + assign stratix_pll_enable = (FAMILY_HAS_STRATIX_STYLE_PLL == 1) + ? tx_pll_enable + : 1'b0; + + assign stratixii_pll_enable = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1) + ? tx_pll_enable + : 1'b0; + + assign stratix_pll_areset = (FAMILY_HAS_STRATIX_STYLE_PLL == 1) + ? pll_areset + : 1'b0; + + assign stratixii_pll_areset = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1) + ? pll_areset + : 1'b0; + + assign stratix_inclock = ((STRATIX_TX_STYLE == 1) && + (implement_in_les == "OFF")) + ? stratix_pll_outclock[1] + : 1'b0; + + assign stratix_enable = ((STRATIX_TX_STYLE == 1) && + (implement_in_les == "OFF")) + ? stratix_enable1 + : 1'b0; + + assign stratixii_inclock = ((STRATIXII_TX_STYLE == 1) && + (implement_in_les == "OFF")) + ? ((use_external_pll == "ON") + ? tx_inclock + : stratixii_sclkout1) + : 1'b0; + + assign stratixii_enable = ((STRATIXII_TX_STYLE == 1) && + (implement_in_les == "OFF")) + ? ((use_external_pll == "ON") + ? tx_enable + : stratixii_enable1) + : 1'b0; + + assign flvds_fastclk = ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIX_STYLE_PLL == 1)) + ? ((use_external_pll == "ON") + ? tx_inclock + : stratix_pll_outclock[0]) : + ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)) + ? ((use_external_pll == "ON") + ? tx_inclock + : stratixii_pll_outclock[0]) + : 1'b0; + + assign flvds_slowclk = ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIX_STYLE_PLL == 1)) + ? ((use_external_pll == "ON") + ? 1'b0 + : stratix_pll_outclock[2]) : + ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && + (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)) + ? ((use_external_pll == "ON") + ? 1'b0 + : stratixii_pll_outclock[2]) + : 1'b0; + + assign flvds_regclk = (FAMILY_HAS_FLEXIBLE_LVDS == 1) + ? tx_reg_clk + : 1'b0; + +endmodule // altlvds_tx +// END OF MODULE + + +//START_MODULE_NAME-------------------------------------------------------------- +// +// Module Name : stratix_tx_outclk + +// Description : This module is used to generate the tx_outclock for Stratix +// family. + +// Limitation : Only available STRATIX family. +// +// Results expected: Output clock. +// +//END_MODULE_NAME---------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +module stratix_tx_outclk ( + tx_in, + tx_fastclk, + tx_enable, + tx_out +); + +// GLOBAL PARAMETER DECLARATION + // No. of bits per channel (required) + parameter deserialization_factor = 4; + parameter bypass_serializer = "FALSE"; + parameter use_falling_clock_edge = "FALSE"; + +// INPUT PORT DECLARATION + // Input data (required) + input [9 : 0] tx_in; + // Input clock (required) + input tx_fastclk; + input tx_enable; + +// OUTPUT PORT DECLARATION + // Serialized data signal(required) + output tx_out; + +// INTERNAL REGISTERS DECLARATION + reg [deserialization_factor -1 : 0] tx_shift_reg; + reg [deserialization_factor -1 : 0] tx_parallel_load_reg; + reg tx_out_neg; + reg enable1_reg0; + reg enable1_reg1; + reg enable1_reg2; + +// INTERNAL TRI DECLARATION + tri1 tx_enable; + +// LOCAL INTEGER DECLARATION + integer x; + +// INITIAL CONSTRUCT BLOCK + + initial + begin : INITIALIZATION + tx_parallel_load_reg = {deserialization_factor{1'b0}}; + tx_shift_reg = {deserialization_factor{1'b0}}; + end // INITIALIZATION + +// ALWAYS CONSTRUCT BLOCK + + // registering load enable signal + always @ (posedge tx_fastclk) + begin : LOAD_ENABLE_POS + if (tx_fastclk === 1'b1) + begin + enable1_reg1 <= enable1_reg0; + enable1_reg0 <= tx_enable; + end + end // LOAD_ENABLE_POS + + always @ (negedge tx_fastclk) + begin : LOAD_ENABLE_NEG + enable1_reg2 <= enable1_reg1; + end // LOAD_ENABLE_NEG + + // Fast Clock + always @ (posedge tx_fastclk) + begin : POSEDGE_FAST_CLOCK + if (enable1_reg2 == 1'b1) + tx_shift_reg <= tx_parallel_load_reg; + else// Shift data from shift register to tx_out + begin + for (x=deserialization_factor-1; x >0; x=x-1) + tx_shift_reg[x] <= tx_shift_reg [x-1]; + end + + tx_parallel_load_reg <= tx_in[deserialization_factor-1 : 0]; + end // POSEDGE_FAST_CLOCK + + always @ (negedge tx_fastclk) + begin : NEGEDGE_FAST_CLOCK + tx_out_neg <= tx_shift_reg[deserialization_factor-1]; + end // NEGEDGE_FAST_CLOCK + +// CONTINUOUS ASSIGNMENT + assign tx_out = (bypass_serializer == "TRUE") ? tx_fastclk : + (use_falling_clock_edge == "TRUE") ? tx_out_neg : + tx_shift_reg[deserialization_factor-1]; + +endmodule // stratix_tx_outclk +// END OF MODULE + +//START_MODULE_NAME-------------------------------------------------------------- +// +// Module Name : stratixii_tx_outclk + +// Description : This module is used to generate the tx_outclock for StratixII +// family. + +// Limitation : Only available STRATIX II family. +// +// Results expected: Output clock. +// +//END_MODULE_NAME---------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +module stratixii_tx_outclk ( + tx_in, + tx_fastclk, + tx_enable, + tx_out +); + +// GLOBAL PARAMETER DECLARATION + // No. of bits per channel (required) + parameter deserialization_factor = 4; + parameter bypass_serializer = "FALSE"; + parameter use_falling_clock_edge = "FALSE"; + +// INPUT PORT DECLARATION + // Input data (required) + input [9 : 0] tx_in; + // Input clock (required) + input tx_fastclk; + input tx_enable; + +// OUTPUT PORT DECLARATION + // Serialized data signal(required) + output tx_out; + +// INTERNAL REGISTERS DECLARATION + reg [deserialization_factor -1 : 0] tx_shift_reg; + reg [deserialization_factor -1 : 0] tx_parallel_load_reg; + reg tx_out_reg; + reg tx_out_neg; + reg enable1_reg; + +// INTERNAL TRI DECLARATION + tri1 tx_enable; + +// LOCAL INTEGER DECLARATION + integer i1; + integer i2; + integer x; + +// INITIAL CONSTRUCT BLOCK + + initial + begin : INITIALIZATION + tx_parallel_load_reg = {deserialization_factor{1'b0}}; + tx_shift_reg = {deserialization_factor{1'b0}}; + + enable1_reg = 0; + + end // INITIALIZATION + +// ALWAYS CONSTRUCT BLOCK + + // Fast Clock + always @ (posedge tx_fastclk) + begin : POSEDGE_FAST_CLOCK + // registering enable1 signal + enable1_reg <= tx_enable; + + if (enable1_reg == 1'b1) + tx_shift_reg <= tx_parallel_load_reg; + else// Shift data from shift register to tx_out + begin + for (x=deserialization_factor-1; x >0; x=x-1) + tx_shift_reg[x] <= tx_shift_reg [x-1]; + end + + tx_parallel_load_reg <= tx_in[deserialization_factor-1 : 0]; + end // POSEDGE_FAST_CLOCK + + always @ (negedge tx_fastclk) + begin : NEGEDGE_FAST_CLOCK + tx_out_neg <= tx_shift_reg[deserialization_factor-1]; + end // NEGEDGE_FAST_CLOCK + +// CONTINUOUS ASSIGNMENT + assign tx_out = (bypass_serializer == "TRUE") ? tx_fastclk : + (use_falling_clock_edge == "TRUE") ? tx_out_neg : + tx_shift_reg[deserialization_factor-1]; + +endmodule // stratixii_tx_outclk +// END OF MODULE + + +//START_MODULE_NAME---------------------------------------------------- +// +// Module Name : flexible_lvds_tx +// +// Description : flexible lvds transmitter +// +// Limitation : Only available to Cyclone and Cyclone II +// families. +// +// Results expected: Serialized output data. +// +//END_MODULE_NAME---------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module flexible_lvds_tx ( + tx_in, // input serial data + tx_fastclk, // fast clock from pll + tx_slowclk, // slow clock from pll + tx_regclk, // clock for registering input data + tx_locked, // locked signal from PLL + tx_out // deserialized output data +); + +// GLOBAL PARAMETER DECLARATION + parameter number_of_channels = 1; + parameter deserialization_factor = 4; + parameter registered_input = "ON"; + +// LOCAL PARAMETER DECLARATION + parameter REGISTER_WIDTH = deserialization_factor*number_of_channels; + parameter DOUBLE_DESER = deserialization_factor*2; + +// INPUT PORT DECLARATION + input [REGISTER_WIDTH -1: 0] tx_in; + input tx_fastclk; + input tx_slowclk; + input tx_regclk; + input tx_locked; + +// OUTPUT PORT DECLARATION + output [number_of_channels -1 :0] tx_out; + +// INTERNAL REGISTERS DECLARATION + reg [REGISTER_WIDTH -1 : 0] tx_reg; + reg [(REGISTER_WIDTH*2) -1 : 0] tx_reg2; + reg [REGISTER_WIDTH -1 : 0] tx_shift_reg; + reg [(REGISTER_WIDTH*2) -1 : 0] tx_shift_reg2; + reg [REGISTER_WIDTH -1 :0] h_sync_a; + reg [(REGISTER_WIDTH*2) -1 :0] sync_b_reg; + reg [number_of_channels -1 :0] dataout_h; + reg [number_of_channels -1 :0] dataout_l; + reg [number_of_channels -1 :0] dataout_tmp; + reg [number_of_channels -1 :0] tx_ddio_out; + +// INTERNAL WIRE DECLARATION + wire [REGISTER_WIDTH -1 : 0] tx_in_int; + wire [(REGISTER_WIDTH*2) -1 : 0] tx_in_int2; + + +// LOCAL INTEGER DECLARATION + integer i1; + integer i2; + integer i3; + integer x; + integer x2; + integer loadcnt; + +// INITIAL CONSTRUCT BLOCK + initial + begin : INITIALIZATION + tx_reg = {REGISTER_WIDTH{1'b0}}; + tx_reg2 = {(REGISTER_WIDTH*2){1'b0}}; + + tx_shift_reg = {REGISTER_WIDTH{1'b0}}; + tx_shift_reg2 = {(REGISTER_WIDTH*2){1'b0}}; + + dataout_h = {number_of_channels{1'b0}}; + dataout_l = {number_of_channels{1'b0}}; + dataout_tmp = {number_of_channels{1'b0}}; + tx_ddio_out = {number_of_channels{1'b0}}; + + h_sync_a = {REGISTER_WIDTH{1'b0}}; + sync_b_reg = {(REGISTER_WIDTH*2){1'b0}}; + + loadcnt = 0; + end //INITIALIZATION + + +// ALWAYS CONSTRUCT BLOCK + + // For each data channel, input data are separated into 2 data + // stream which will be transmitted on different edge of input clock. + always @ (posedge tx_fastclk) + begin : DDIO_OUT_POS + if ((deserialization_factor % 2) == 0) + begin + for (i1 = 0; i1 < number_of_channels; i1 = i1 +1) + begin + dataout_h[i1] <= tx_shift_reg[(i1+1)*deserialization_factor-1]; + dataout_l[i1] <= tx_shift_reg[(i1+1)*deserialization_factor-2]; + dataout_tmp[i1] <= tx_shift_reg[(i1+1)*deserialization_factor-1]; + end + end + else + begin + for (i1 = 0; i1 < number_of_channels; i1 = i1 +1) + begin + dataout_h[i1] <= tx_shift_reg2[(i1+1)*DOUBLE_DESER-1]; + dataout_l[i1] <= tx_shift_reg2[(i1+1)*DOUBLE_DESER-2]; + dataout_tmp[i1] <= tx_shift_reg2[(i1+1)*DOUBLE_DESER-1]; + end + end + end // DDIO_OUT_POS + + always @ (negedge tx_fastclk) + begin : DDIO_OUT_NEG + dataout_tmp <= dataout_l; + end // DDIO_OUT_NEG + + // Loading input data to shift register + always @ (posedge tx_fastclk) + begin : SHIFTREG + + // if(tx_locked == 1'b1) + begin + // Implementation for even deserialization factor. + if ((deserialization_factor % 2) == 0) + begin + loadcnt <= (loadcnt + 1) % (deserialization_factor/2); + + if(loadcnt == 0) + tx_shift_reg <= tx_in_int; + else + begin + for (i2= 0; i2 < number_of_channels; i2 = i2+1) + begin + for (x=deserialization_factor-1; x >1; x=x-1) + tx_shift_reg[x + (i2 * deserialization_factor)] <= + tx_shift_reg [x-2 + (i2 * deserialization_factor)]; + end + end + end + else // Implementation for odd deserialization factor. + begin + loadcnt <= (loadcnt + 1) % deserialization_factor; + + if(loadcnt == 0) + tx_shift_reg2 <= tx_in_int2; + else + begin + for (i2= 0; i2 < number_of_channels; i2 = i2+1) + begin + for (x=DOUBLE_DESER-1; x >1; x=x-1) + tx_shift_reg2[x + (i2 * DOUBLE_DESER)] <= + tx_shift_reg2 [x-2 + (i2 * DOUBLE_DESER)]; + end + end + end + end + end // SHIFTREG + + // loading data to synchronization register + always @ (posedge tx_slowclk) + begin : SYNC_REG_POS + h_sync_a <= tx_in; + end // SYNC_REG_POS + + always @ (negedge tx_slowclk) + begin : SYNC_REG_NEG + + for (i3= 0; i3 < number_of_channels; i3 = i3+1) + begin + for (x2=0; x2 < deserialization_factor; x2=x2+1) + begin + sync_b_reg[x2 + (((i3 * 2) + 1) * deserialization_factor)] <= + h_sync_a[x2 + (i3 * deserialization_factor)]; + sync_b_reg[x2 + (i3 * DOUBLE_DESER)] <= + tx_in[x2 + (i3 * deserialization_factor)]; + end + end + end // SYNC_REG_NEG + + // loading data to input register + always @ (posedge tx_regclk) + begin : IN_REG + if ((deserialization_factor % 2) == 0) + tx_reg <= tx_in; + else + tx_reg2 <= sync_b_reg; + end // IN_REG + +// CONTINOUS ASSIGNMENT + assign tx_in_int = (registered_input == "OFF") ? tx_in : tx_reg; + assign tx_in_int2 = (registered_input == "OFF") ? sync_b_reg : tx_reg2; + assign tx_out = dataout_tmp; + + +endmodule // flexible_lvds_tx +// END OF MODULE + + +//START_MODULE_NAME---------------------------------------------------- +// +// Module Name : altcam +// +// Description : Content-addressable memory (CAM) Megafunction. The +// data contained in a CAM is a set of patterns that can be searched in a +// single-clock cycle. The altcam megafunction allows each stored pattern +// bit to be specified as a binary "1" bit, binary "0" bit, or a don't care bit. +// Comparing a stored pattern bit that is specified as don't care with its +// corresponding input pattern bit will always result in a match. +// +// Limitation : Input patterns cannot contain don't care bits. +// +// Results expected: If the input pattern given to the CAM matches one +// of the patterns stored in the CAM, the address of the matching stored +// pattern is generated. +// +//END_MODULE_NAME---------------------------------------------------- + +`timescale 1 ps / 1 ps + + +module altcam (pattern, wrx, wrxused, wrdelete, wraddress, wren, + inclock, inclocken, inaclr, outclock, + outclocken, outaclr, mstart, mnext, maddress, mbits, mfound, mcount, + rdbusy, wrbusy); + + parameter width = 1; + parameter widthad = 1; + parameter numwords = 1; + parameter lpm_file = "UNUSED"; + parameter lpm_filex = "UNUSED"; + parameter lpm_hint = "UNUSED"; + parameter match_mode = "MULTIPLE"; + parameter output_reg = "UNREGISTERED"; + parameter output_aclr = "ON"; + parameter pattern_reg = "INCLOCK"; + parameter pattern_aclr = "ON"; + parameter wraddress_aclr = "ON"; + parameter wrx_reg = "INCLOCK"; + parameter wrx_aclr = "ON"; + parameter wrcontrol_aclr = "ON"; + parameter use_eab = "ON"; + parameter lpm_type = "altcam"; + + // Input ports + input [width-1 : 0] pattern; // Required port + input [width-1 : 0] wrx; + input wrxused; + input wrdelete; + input [widthad-1 : 0] wraddress; + input wren; + input inclock; // Required port + input inclocken; + input inaclr; + input outclock; + input outclocken; + input outaclr; + input mstart; + input mnext; + + // Output ports + output [widthad-1 : 0] maddress; + output [numwords-1 : 0] mbits; + output mfound; + output [widthad-1 : 0] mcount; + output rdbusy; + output wrbusy; + + // Nets + tri1 wrxused_pullup; + tri1 inclocken_pullup; + tri1 outclocken_pullup; + tri0 wrdelete_pulldown; + tri0 inaclr_pulldown; + wire [width-1 : 0] pattern_int; + wire [width-1 : 0] wrx_int; + wire wrxused_int; + wire outclock_int; + wire outaclr_int; + wire rdbusy_delayed; + + // Registers + reg [width-1 : 0] pattern_rgd; + reg [width-1 : 0] wrx_rgd; + reg wrxused_rgd; + reg [widthad-1 : 0] wraddress_rgd; + reg wren_rgd; + reg wrdelete_rgd; + reg [widthad-1 : 0] maddress_rgd; + reg [widthad-1 : 0] maddress_int; + reg [numwords-1 : 0] mbits_rgd; + reg [numwords-1 : 0] mbits_int; + reg mfound_rgd; + reg mfound_int; + reg [widthad-1 : 0] mcount_rgd; + reg [widthad-1 : 0] mcount_int; + reg wrbusy_int; + reg rdbusy_int; + + // CAM registers + reg [width-1 : 0] cam_array [numwords-1 : 0]; + reg [width-1 : 0] x_array [numwords-1 : 0]; + + // Read control registers + reg first_read_clock; + reg get_first_match; + reg get_next_match; + reg mstart_rgd1; + reg mstart_rgd2; + reg first_read_in_write; + + // Write control registers + reg write_start; + reg write_start_rgd; + reg write_start_1; + reg write_incomplete; + reg write0; + reg write1; + reg writex; + reg write0_done; + reg write1_done; + reg writex_done; + + // Variables + reg [8*256:1] cam_initf; + reg [8*256:1] cam_initx; + reg [width-1 : 0] word_0; + reg [width-1 : 0] word_1; + reg [widthad-1 : 0] address_0; + reg [widthad-1 : 0] address_1; + reg [numwords-1 : 0] numwords_0; + integer count; + integer index; + integer i, j, k, addr; + integer next_search; + reg restart_read; + reg reset_read; + reg mstart_used; + reg [width-1:0] ipattern; + reg [widthad-1:0] iwraddress; + reg [width-1:0] iwrx; + reg iwren; + reg iwrxused; + reg [numwords-1 : 0] mbits_tmp; + + function read_cam_array; + input [widthad-1 : 0] i; + input [width-1 : 0] j; + begin: READ_CAM + reg [width-1 : 0] tmp; + tmp = cam_array[i]; + read_cam_array = tmp[j]; + end // end READ_CAM + endfunction // end of read_cam_array + + task write_cam_array; + input [widthad-1 : 0] i; + input [width-1 : 0] j; + input value; + begin: WRITE_CAM + reg [width-1 : 0] tmp; + tmp = cam_array[i]; + tmp[j] = value; + cam_array[i] = tmp; + end // end of WRITE_CAM + endtask // end of write_cam_array + + function read_x_array; + input [widthad-1 : 0] i; + input [width-1 : 0] j; + begin: READ_X + reg [width-1 : 0] tmp; + tmp = x_array[i]; + read_x_array = tmp[j]; + end // end of READ_X + endfunction // end of read_x_array + + task write_x_array; + input [widthad-1 : 0] i; + input [width-1 : 0] j; + input value; + begin: WRITE_X + reg [width-1 : 0] tmp; + tmp = x_array[i]; + tmp[j] = value; + x_array[i] = tmp; + end // end of WRITE_X + endtask // end of write_x_array + + ALTERA_MF_MEMORY_INITIALIZATION mem (); + + initial + begin + + // Checking for invalid parameters + if( width <= 0 ) + begin + $display("Error! Value of width parameter must be greater than 0."); + $stop; + end + + if( widthad <= 0 ) + begin + $display("Error! Value of widthad parameter must be greater than 0."); + $stop; + end + + if( (match_mode != "SINGLE") && (match_mode != "MULTIPLE") && (match_mode != "FAST_MULTIPLE") ) + begin + $display("Error! Illegal value for match_mode parameter. The value must be SINGLE, MULTIPLE (the default), or FAST_MULTIPLE."); + $stop; + end + + for (i=0; i<width; i=i+1) + word_1[i] = 1'b1; + for (i=0; i<width; i=i+1) + word_0[i] = 1'b0; + for (i=0; i<widthad; i=i+1) + begin + address_0[i] = 1'b0; + address_1[i] = 1'b1; + end + for (i=0; i<numwords; i=i+1) + numwords_0[i] = 1'b0; + + mbits_int = numwords_0; + mbits_rgd = numwords_0; + mfound_int = 1'b0; + mfound_rgd = 1'b0; + mcount_int = address_0; + mcount_rgd = address_0; + maddress_rgd = address_0; + wraddress_rgd = address_0; + pattern_rgd = word_0; + wrx_rgd = word_0; + wren_rgd = 1'b0; + wrdelete_rgd = 1'b0; + wrxused_rgd = 1'b0; + first_read_clock = 1'b0; + get_first_match = 1'b0; + wrbusy_int = 1'b0; + rdbusy_int = 1'b0; + write_start = 1'b0; + write_start_rgd = 1'b0; + write_start_1 = 1'b0; + mstart_rgd1 = 1'b0; + mstart_rgd2 = 1'b0; + write_incomplete = 1'b0; + write0 = 1'b1; + write1 = 1'b0; + writex = 1'b0; + write0_done = 1'b0; + write1_done = 1'b0; + writex_done = 1'b0; + next_search = 0; + restart_read = 1'b0; + reset_read = 1'b1; + + // + // word_1[] and word_0[] have to be initialized before + // using it in the code below. + // + if (lpm_file == "UNUSED") + // no memory initialization file + // Initialize cam to never match. + for (i=0; i<numwords; i=i+1) + begin + cam_array[i] = word_1; + x_array[i] = word_1; + end + else if (lpm_filex == "UNUSED") + begin + // only lpm_file is used, lpm_filex is not used + // read in the lpm_file and allow matching all bits +`ifdef NO_PLI + $readmemh(lpm_file, cam_array); +`else + `ifdef USE_RIF + $readmemh(lpm_file, cam_array); + `else + mem.convert_hex2ver(lpm_file, width, cam_initf); + $readmemh(cam_initf, cam_array); + `endif +`endif + for (i = 0; i < numwords; i=i+1) + x_array[i] = word_0; + end + else + begin + // both lpm_file and lpm_filex are used. + // Initialize cam using both files. +`ifdef NO_PLI + $readmemh(lpm_file, cam_array); +`else + `ifdef USE_RIF + $readmemh(lpm_file, cam_array); + `else + mem.convert_hex2ver(lpm_file, width, cam_initf); + $readmemh(cam_initf, cam_array); + `endif +`endif +`ifdef NO_PLI + $readmemh(lpm_filex, x_array); +`else + `ifdef USE_RIF + $readmemh(lpm_filex, x_array); + `else + mem.convert_hex2ver(lpm_filex, width, cam_initx); + $readmemh(cam_initx, x_array); + `endif +`endif + end + + if (match_mode != "SINGLE") + begin + maddress_int = address_1; + end + else + begin + maddress_int = address_0; + end + + if ((match_mode == "FAST_MULTIPLE") && (mstart !== 1'b0) && (mstart !== 1'b1)) + begin + // mstart and mnext are not used. + mstart_used = 1'b0; + get_next_match = 1'b1; + end + else + begin + mstart_used = 1'b1; + get_next_match = 1'b0; + end + end + + always @ (wren_rgd) + begin + if ((wren_rgd == 1'b0) && (write_incomplete == 1'b1)) + $display ("Insufficient write cycle time, write maybe invalid! "); + end + + always @ (pattern_int) + begin + if (write_incomplete == 1'b1) + $display( "Insufficient pattern hold time, write maybe invalid! "); + end + + always @ (wraddress_rgd) + begin + if (write_incomplete == 1'b1) + $display( "Insufficient address hold time, write maybe invalid! "); + end + + always @ (wrdelete_rgd) + begin + if ((wrdelete_rgd == 1'b0) && (write_incomplete == 1'b1)) + $display( "Insufficient delete cycle time, delete failed! "); + end + + always @ (wrdelete_rgd) + begin + if ((wrdelete_rgd == 1'b1) && (write_incomplete == 1'b1)) + $display( "Insufficient write cycle time, write maybe invalid! "); + end + + always @ (wrxused_int) + begin + if ((write_incomplete == 1'b1) && (wrdelete_rgd == 1'b0)) + $display( "wrxused reg changed during write! "); + end + + always @ (mstart_rgd1) + begin + if ((write_incomplete == 1'b1) && (mstart_rgd1 == 1'b1)) + $display( "Incorrect read attempt during write! "); + end + + always @ (pattern_int) + begin + if (rdbusy_delayed == 1'b1) + $display( "Insufficient read time, read failed! "); + else if ((rdbusy_delayed == 1'b0) && (mnext == 1'b1)) + $display( "Illegal pattern change during read, read failed! "); + end + + always @ (mstart) + begin + if (mstart_used == 1'b0) + begin + // Implies fast multiple mode with mstart and mnext + get_next_match = 1'b0; + end + mstart_used = 1'b1; + end + + // Start: Async clear inclock registers + always @ (posedge inaclr_pulldown) + begin + if (inaclr_pulldown == 1'b1) + begin + if (mstart_used == 1'b1) + begin + reset_read = 1'b1; + end + first_read_clock <= 1'b0; + get_first_match <= 1'b0; + if (pattern_aclr == "ON") + begin + pattern_rgd <= word_0; + end + if (wrx_aclr == "ON") + begin + wrx_rgd <= word_0; + wrxused_rgd <= 1'b0; + end + if (wraddress_aclr == "ON") + begin + wraddress_rgd <= word_0; + end + if (wrcontrol_aclr == "ON") + begin + wren_rgd <= 1'b0; + write0_done <= 1'b0; + write1_done <= 1'b0; + writex_done <= 1'b0; + end + if (pattern_aclr == "ON") + begin + mbits_int <= numwords_0; + mcount_int <= word_0; + mfound_int <= 1'b0; + if (match_mode == "SINGLE") + begin + maddress_int <= address_0; + end + else + begin + maddress_int <= address_1; + end + end + if ((output_reg == "INCLOCK") && (output_aclr == "OFF")) + begin + maddress_rgd <= address_0; + mbits_rgd <= numwords_0; + mfound_rgd <= 1'b0; + mcount_rgd <= address_0; + end + end + end + // End: Async clear inclock registers + + ///////////////////////////////////////// + // Evaluate ALTCAM reading and writing + ///////////////////////////////////////// + // Start: Read and Write to CAM + always @ (inclock) // read_write + begin + ipattern = pattern; + iwrx = wrx; + iwraddress = wraddress; + iwren = wren; + if (wrx === {width{1'bz}}) + begin + iwrxused = 1'b0; // must be unconnected + end + else + begin + iwrxused = wrxused_pullup; + end + + if (inaclr_pulldown == 1'b1) + begin + if (mstart_used == 1'b1) + begin + reset_read = 1'b1; + end + first_read_clock <= 1'b0; + get_first_match <= 1'b0; + if (pattern_aclr == "ON") + begin + ipattern = word_0; + end + if (wrx_aclr == "ON") + begin + iwrx = word_0; + iwrxused = 1'b0; + end + if (wraddress_aclr == "ON") + begin + iwraddress = word_0; + end + if (wrcontrol_aclr == "ON") + begin + iwren = 1'b0; + end + if (pattern_aclr == "ON") + begin + mbits_int <= numwords_0; + mcount_int <= word_0; + mfound_int <= 1'b0; + if (match_mode == "SINGLE") + begin + maddress_int <= address_0; + end + else + begin + maddress_int <= address_1; + end + end + end + + if (inclocken_pullup == 1'b1) + begin + if (inclock == 1'b1) + begin // positive inclock edge + pattern_rgd <= ipattern; + wrx_rgd <= iwrx; + wrxused_rgd <= iwrxused; + wraddress_rgd <= iwraddress; + wren_rgd <= iwren; + + write_start_rgd <= write_start; + write_incomplete <= wrbusy_int; + mstart_rgd1 <= mstart; + mstart_rgd2 <= mstart_rgd1; + wrdelete_rgd <= wrdelete_pulldown; + + if (iwren == 1'b0) + begin + write0_done <= 1'b0; + write1_done <= 1'b0; + writex_done <= 1'b0; + //////////////////// + // CAM READ MODES // + //////////////////// + // If pattern changed || mstart asserted again) begin restart + // read cycle. + if (((match_mode == "FAST_MULTIPLE") && (mstart_used == 1'b0) && (reset_read==1'b1)) || + ((mstart == 1'b1) && (mstart_rgd1 == 1'b0)) || + ((ipattern != pattern_rgd) && (reset_read==1'b0))) + begin + restart_read = 1'b1; + reset_read = 1'b0; + get_first_match <= 1'b0; + end + else + begin + restart_read = 1'b0; + end + ///////////////////////// + // FAST MULTIPLE: READ // + ///////////////////////// + if (match_mode == "FAST_MULTIPLE") + begin + if ((get_first_match == 1'b1) && (restart_read == 1'b0)) + begin + if (get_next_match == 1'b1) + begin // start of next read cycle + index = next_search; + begin: MADDR_FM0 for (i=index; i<numwords; i=i+1) + begin: MWORD_FM0 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + next_search = i+1; + j = width; + i = numwords; + end + end + else + begin + j = width; + end + end // MWORD_FM0 + end // MADDR_FM0 + if (index == next_search) + begin // no more matches + mfound_int <= 1'b0; + maddress_int <= address_1; + end + else + begin + maddress_int <= (next_search-1); + end + end + end + else + begin // start of new read cycle + count = 0; + mbits_tmp = numwords_0; + begin: MADDR_FM1 for (i=0; i<numwords; i=i+1) + begin: MWORD_FM1 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || // match pattern bit or + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) // don't care bit + begin + if (j == width-1) // last bit of word + begin + if ((count == 0) && (reset_read == 1'b0) && (restart_read == 1'b1)) + begin + mfound_int <= 1'b1; + maddress_int <= i; + get_first_match <= 1'b1; + next_search = i+1; + end + mbits_tmp[i] = 1'b1; // set the match word + count = count + 1; // count the matched word + end + end + else // Never match bit + begin + j = width; + end + end // MWORD_FM1 + end // MADDR_FM1 + mcount_int <= count; + mbits_int <= mbits_tmp; + if ((count == 0) || (reset_read == 1'b1)) + begin // no matches + mfound_int <= 1'b0; + maddress_int <= address_1; + end + end // end of initial read cycle + end // end of FAST MULTIPLE + + //////////////////// + // MULTIPLE: READ // + //////////////////// + if (match_mode == "MULTIPLE") + begin + if ((get_first_match == 1'b1) && (restart_read == 1'b0)) + begin + if (get_next_match == 1'b1) + begin // start of next read cycle + index = next_search; + begin: MADDR_MM0 for (i=index; i<numwords; i=i+1) + begin: MWORD_MM0 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + next_search = i+1; + j = width; + i = numwords; + end + end + else + begin + j = width; + end + end // MWORD_MM0 + end // MADDR_MM0 + if (index == next_search) + begin + mfound_int <= 1'b0; + maddress_int <= address_1; + end + else + begin + maddress_int <= (next_search-1); + end + end + end + else + begin // start of 1st match + count = 0; + if (reset_read==1'b0) + begin // Not in reset state + if (first_read_clock == 1'b0) + begin + // 1st cycle: match with even && write to even + first_read_clock <= 1'b1; + maddress_int <= address_1; + mfound_int <= 1'b0; + mbits_tmp = mbits_int; + begin: MADDR_MM1 for (i=0; i<numwords; i=i+1) + if ( (i % 2)==0 ) + begin + if (mbits_int[i] == 1'b1) + begin + count = count + 1; + end + begin: MWORD_MM1 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i+1] = 1'b1; + count = count + 1; + end + end + else + begin + mbits_tmp[i+1] = 1'b0; + j = width; + end + end // MWORD_MM1 + end + end // MADDR_MM1 + end + else + begin // 2nd read cycle + // 2nd cycle: do match + first_read_clock <= 1'b0; + mbits_tmp = numwords_0; + begin: MADDR_MM2 for (i=0; i<numwords; i=i+1) + begin: MWORD_MM2 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + if (count == 0) + begin + next_search = i+1; + end + mbits_tmp[i] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // MWORD_MM2 + end // MADDR_MM2 + if (count == 0) + begin // no matches + maddress_int <= address_1; + mfound_int <= 1'b0; + end + else + begin + get_first_match <= 1'b1; + mfound_int <= 1'b1; + maddress_int <= (next_search-1); + end + end + end + else + begin // In reset state + // Match with even but write to odd + maddress_int <= address_1; + mfound_int <= 1'b0; + mbits_tmp = numwords_0; + begin: MADDR_MM3 for (i=0; i<numwords; i=i+1) + if ( (i % 2)==0 ) + begin + begin: MWORD_MM3 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i+1] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // MWORD_MM3 + end + end // MADDR_MM3 + end // end of reset state + mcount_int <= count; + mbits_int <= mbits_tmp; + end // end of initial read cycle + end // end of MULTIPLE + + ////////////////// + // SINGLE: READ // + ////////////////// + if (match_mode == "SINGLE") + begin + mbits_tmp = numwords_0; + index = 0; + count = 0; + begin: MADDR_SM0 for (i=0; i<numwords; i=i+1) + begin: MWORD_SM0 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i] = 1'b1; + index = i; + count = 1; + j = width; + i = numwords; + end + end + else + begin + j = width; + end + end // MWORD_SM0 + end // MADDR_SM0 + mcount_int <= count; + mbits_int <= mbits_tmp; + if (count == 0) + begin + maddress_int <= address_0; + mfound_int <= 1'b0; + end + else + begin + mfound_int <= 1'b1; + maddress_int <= index; + end + end // end of SINGLE + end + else + begin // if wren == 1'b1 + ////////////////////// + // READ AFTER WRITE // + ////////////////////// + // Writing to CAM so reset read cycle. + get_first_match <= 1'b0; + first_read_clock <= 1'b0; + restart_read = 1'b0; + if (mstart_used == 1'b1) + begin + reset_read = 1'b1; + end + ///////////////////////////////////// + // FAST MULTIPLE: READ AFTER WRITE // + ///////////////////////////////////// + if (match_mode == "FAST_MULTIPLE") + begin + mfound_int <= 1'b0; + maddress_int <= address_1; + count = 0; + mbits_tmp = numwords_0; + if ((writex == 1'b1) && (iwrxused == 1'b1)) + begin + begin: WADDR_FM0 for (i=0; i<numwords; i=i+1) + begin: WWORD_FM0 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == (ipattern[j] ^ iwrx[j]))) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_FM0 + end // WADDR_FM0 + end + else + begin + begin: WADDR_FM1 for (i=0; i<numwords; i=i+1) + begin: WWORD_FM1 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_FM1 + end // WADDR_FM1 + end + mcount_int <= count; + mbits_int <= mbits_tmp; + end // end of FAST MULTIPLE + + //////////////////////////////// + // MULTIPLE: READ AFTER WRITE // + //////////////////////////////// + if ((match_mode == "MULTIPLE")) + begin + mfound_int <= 1'b0; + maddress_int <= address_1; + mbits_tmp = numwords_0; + if ((writex == 1'b1) && (iwrxused == 1'b1)) + begin + mcount_int <= 0; + end + else + begin + if (first_read_in_write == 1'b0) + begin + // Read even addresses but they appear on the odd locations + // of mbits. + count = 0; + begin: WADDR_MM0 for (i=0; i<numwords; i=i+1) + if ((i % 2) == 0) + begin + if (mbits_int[i] == 1'b1) + begin // counting previous even address matches + count = count + 1; + end + begin: WWORD_MM0 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i+1] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_MM0 + end + end // WADDR_MM0 + end + else + begin + // Read odd addresses. + count = 0; + begin: WADDR_MM1 for (i=numwords-1; i>=0; i=i-1) + if ((i % 2) == 1 ) + begin + mbits_tmp[i-1] = mbits_tmp[i]; + end + else + begin + begin: WWORD_MM1 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_MM1 + end + end // WADDR_MM1 + end + mcount_int <= count; + mbits_int <= mbits_tmp; + end + end // end of MULTIPLE + + ////////////////////////////// + // SINGLE: READ AFTER WRITE // + ////////////////////////////// + if (match_mode == "SINGLE") + begin + mbits_tmp = numwords_0; + index = 0; + count = 0; + if ((writex == 1'b1) && (iwrxused == 1'b1)) + begin + begin: WADDR_SM0 for (i=0; i<numwords; i=i+1) + begin: WWORD_SM0 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == (ipattern[j] ^ iwrx[j]))) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i] = 1'b1; + index = i; + count = 1; + j = width; + i = numwords; + end + end + else + begin + j = width; + end + end // WWORD_SM0 + end // WADDR_SM0 + end + else + begin + begin: WADDR_SM1 for (i=0; i<numwords; i=i+1) + begin: WWORD_SM1 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i] = 1'b1; + index = i; + count = 1; + j = width; + i = numwords; + end + end + else + begin + j = width; + end + end // WWORD_SM1 + end // WADDR_SM1 + end + mcount_int <= count; + mbits_int <= mbits_tmp; + if (count == 0) + begin + mfound_int <= 1'b0; + maddress_int <= address_0; + end + else + begin + mfound_int <= 1'b1; + maddress_int <= index; + end + end // end of SINGLE + end // end of wren == 1'b1 + end // end of inclock == 1'b1 + else + begin // if (inclock negedge + // We write to the CAM on the low cycle of inclock + // when wren_rgd==1'b1. + if (pattern_reg == "UNREGISTERED") ipattern = pattern; + else ipattern = pattern_rgd; + if ((wren_rgd==1'b1) && (inclock==1'b0)) + begin + addr = wraddress_rgd; + ///////////////////// + // CAM WRITE MODES // + ///////////////////// + if (wrdelete_rgd == 1'b0) + begin + if ((wrxused_int == 1'b1) && (wrx !== {width{1'bz}})) + begin + /////////////////// + // 3 CYCLE WRITE // + /////////////////// + ///////////////// + // WRITE_ZEROS // + ///////////////// + if (write0 == 1'b1) + begin + for (i =0; i<width; i=i+1 ) + begin + if (ipattern[i] == 1'b0) + begin + // "0" ==> "0" + if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0)) + begin // "0" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b0); + // "1" ==> "X" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0)) + begin // "1" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "X" ==> "X" + end + else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1)) + begin // "X" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "U" ==> "0" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1)) + begin // "U" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b0); + end + end else if (ipattern[i] == 1'b1) + begin + // "0" ==> "X" + if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0)) + begin // "0" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "1" ==> "1" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0)) + begin // "1" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b0); + // "X" ==> "X" + end + else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1)) + begin // "X" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "U" ==> "1" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1)) + begin // "U" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b0); + end + end + end + write0_done <= 1'b1; + write1_done <= 1'b0; + writex_done <= 1'b0; + end + //////////////// + // WRITE_ONES // + //////////////// + if (write1 == 1'b1) + begin + for (i =0; i<width; i=i+1) + begin + if (ipattern[i] == 1'b0) + begin + // "0" ==> "0" + if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0)) + begin // "0" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b0); + // "1" ==> "U" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0)) + begin // "1" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b1); + // "X" ==> "0" + end + else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1)) + begin // "X" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b0); + // "U" ==> "U" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1)) + begin // "U" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b1); + end + end + else if (ipattern[i] == 1'b1) + begin + // "0" ==> "U" + if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0)) + begin // "0" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b1); + // "1" ==> "1" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0)) + begin // "1" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b0); + // "X" ==> "1" + end + else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1)) + begin // "X" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b0); + // "U" ==> "U" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1)) + begin // "U" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b1); + end + end + end + write0_done <= 1'b0; + write1_done <= 1'b1; + writex_done <= 1'b0; + end + ///////////// + // WRITE_X // + ///////////// + if (writex == 1'b1) + begin + for (i =0; i<width; i=i+1) + begin + if ((ipattern[i] ^ wrx_int[i]) == 1'b0) + begin + // "0" ==> "0" + if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0)) + begin // "0" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b0); + // "1" ==> "X" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0)) + begin // "1" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "X" ==> "X" + end + else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1)) + begin // "X" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "U" ==> "0" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1)) + begin // "U" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b0); + end + end + else if ((ipattern[i] ^ wrx_int[i]) == 1'b1) + begin + // "0" ==> "X" + if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0)) + begin // "0" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "1" ==> "1" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0)) + begin // "1" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b0); + // "X" ==> "X" + end + else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1)) + begin // "X" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "U" ==> "1" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1)) + begin // "U" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b0); + end + end + end + writex_done <= 1'b1; + write0_done <= 1'b0; + write1_done <= 1'b0; + end + if (wrbusy_int == 1'b1) + begin + write_start_1 <= 1'b1; + write_start <= write_start_1; + end + else + begin + write_start_1 <= 1'b0; + write_start <= 1'b0; + end + end + else + begin // 2 Cycle write + /////////////////// + // 2 CYCLE WRITE // + /////////////////// + ///////////////// + // WRITE_ZEROS // + ///////////////// + if (write0 == 1'b1) + begin + for (i =0; i<width; i=i+1) + begin + if (ipattern[i] == 1'b0) + begin + // "0" ==> "0" + if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0)) + begin // "0" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b0); + // "1" ==> "X" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0)) + begin // "1" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "X" ==> "X" + end + else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1)) + begin // "X" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "U" ==> "0" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1)) + begin // "U" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b0); + end + end + else if (ipattern[i] == 1'b1) + begin + // "0" ==> "X" + if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0)) + begin // "0" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "1" ==> "1" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0)) + begin // "1" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b0); + // "X" ==> "X" + end + else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1)) + begin // "X" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b1); + // "U" ==> "1" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1)) + begin // "U" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b0); + end + end + end + write0_done <= 1'b1; + write1_done <= 1'b0; + writex_done <= 1'b0; + end + //////////////// + // WRITE_ONES // + //////////////// + if (write1 == 1'b1) + begin + for (i =0; i<width; i=i+1) + begin + if (ipattern[i] == 1'b0) + begin + // "0" ==> "0" + if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0)) + begin // "0" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b0); + // "1" ==> "U" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0)) + begin // "1" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b1); + // "X" ==> "0" + end + else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1)) + begin // "X" + write_cam_array(addr,i,1'b0); + write_x_array(addr,i,1'b0); + // "U" ==> "U" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1)) + begin // "U" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b1); + end + end + else if (ipattern[i] == 1'b1) + begin + // "0" ==> "U" + if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0)) + begin // "0" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b1); + // "1" ==> "1" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0)) + begin // "1" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b0); + // "X" ==> "1" + end + else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1)) + begin // "X" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b0); + // "U" ==> "U" + end + else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1)) + begin // "U" + write_cam_array(addr,i,1'b1); + write_x_array(addr,i,1'b1); + end + end + end + write0_done <= 1'b0; + write1_done <= 1'b1; + writex_done <= 1'b0; + end + + if (wrbusy_int == 1'b1) + begin + write_start <= 1'b1; + end + else + begin + write_start <= 1'b0; + end + end // wrxused_int + end + else + begin // if (wrdelete == 1'b1) begin + //////////////////// + // 2 CYCLE DELETE // + //////////////////// + // Delete is a 2-cycle write + //////////////// + // WRITE_ONES // + //////////////// + if (write0 == 1'b1) + begin + for (i =0; i<width; i=i+1) + begin + write_cam_array(addr,i,1'b1); + end + write0_done <= 1'b1; + write1_done <= 1'b0; + writex_done <= 1'b0; + end + ///////////// + // WRITE_X // + ///////////// + if (write1 == 1'b1) + begin + for (i =0; i<width; i=i+1) + begin + write_x_array(addr,i,1'b1); + end + write1_done <= 1'b1; + write0_done <= 1'b0; + writex_done <= 1'b0; + end + if (wrbusy_int == 1'b1) + begin + write_start <= 1'b1; + end + else + begin + write_start <= 1'b0; + end + end // wrdelete + + ////////////////////////////////////// + // FAST MULTIPLE: READ DURING WRITE // + ////////////////////////////////////// + // Now we need to update mbits, mcount during the write. + if (match_mode == "FAST_MULTIPLE") + begin + mfound_int <= 1'b0; + maddress_int <= address_1; + count = 0; + mbits_tmp = numwords_0; + if ((writex == 1'b1) && (wrxused_int == 1'b1)) + begin + begin: WADDR_FM2 for (i=0; i<numwords; i=i+1) + begin: WWORD_FM2 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == (ipattern[j] ^ wrx_int[j]))) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + if ((count == 0) && (mstart_used == 1'b0)) + begin + mfound_int <= 1'b1; + maddress_int <= i; + end + mbits_tmp[i] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_FM2 + end // WADDR_FM2 + end + else + begin + begin: WADDR_FM3 for (i=0; i<numwords; i=i+1) + begin: WWORD_FM3 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + if ((count == 0) && (mstart_used == 1'b0)) + begin + mfound_int <= 1'b1; + maddress_int <= i; + end + mbits_tmp[i] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_FM3 + end // WADDR_FM3 + end + mcount_int <= count; + mbits_int <= mbits_tmp; + end // end of FAST MULTIPLE + + ///////////////////////////////// + // MULTIPLE: READ DURING WRITE // + ///////////////////////////////// + if ((match_mode == "MULTIPLE")) + begin + mfound_int <= 1'b0; + maddress_int <= address_1; + mbits_tmp = numwords_0; + if ((writex == 1'b1) && (iwrxused == 1'b1)) + begin + mcount_int <= 0; + first_read_in_write <= 1'b0; + end + else + begin + if (first_read_in_write == 1'b0) + begin + first_read_in_write <= 1'b1; + // Read even addresses but they appear on the odd locations + // of mbits. + count = 0; + begin: WADDR_MM2 for (i=0; i<numwords; i=i+1) + if ((i % 2) == 0) + begin + if (mbits_int[i] == 1'b1) + begin // counting previous even address matches + count = count + 1; + end + + begin: WWORD_MM2 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i+1] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_MM2 + end + end // WADDR_MM2 + end + else + begin + first_read_in_write <= 1'b0; + // Read odd addresses. + count = 0; + begin: WADDR_MM3 for (i=numwords-1; i>=0; i=i-1) + if ((i % 2) == 1 ) + begin + mbits_tmp[i-1] = mbits_tmp[i]; + end + else + begin + begin: WWORD_MM3 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_MM3 + end + end // WADDR_MM3 + end + mcount_int <= count; + mbits_int <= mbits_tmp; + end + end // end of MULTIPLE + + /////////////////////////////// + // SINGLE: READ DURING WRITE // + /////////////////////////////// + if (match_mode == "SINGLE") + begin + mbits_tmp = numwords_0; + index = 0; + count = 0; + if ((writex == 1'b1) && (wrxused_int == 1'b1)) + begin + begin: WADDR_SM2 for (i=0; i<numwords; i=i+1) + begin: WWORD_SM2 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == (ipattern[j] ^ wrx_int[j]))) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i] = 1'b1; + index = i; + count = 1; + j = width; + i = numwords; + end + end + else + begin + j = width; + end + end // WWORD_SM2 + end // WADDR_SM2 + end + else + begin + begin: WADDR_SM3 for (i=0; i<numwords; i=i+1) + begin: WWORD_SM3 for (j=0; j<width; j=j+1) + if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) || + ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[i] = 1'b1; + index = i; + count = 1; + j = width; + i = numwords; + end + end + else + begin + j = width; + end + end // WWORD_SM3 + end // WADDR_SM3 + end + mcount_int <= count; + mbits_int <= mbits_tmp; + if (count == 0) + begin + mfound_int <= 1'b0; + maddress_int <= address_0; + end + else + begin + mfound_int <= 1'b1; + maddress_int <= index; + end + end // end of SINGLE + end + else + begin // End of Write + if (write_start == 1'b1) + begin + // this should be a second write cycle but due to write violation, + // we have to reset write_start + write_start <= 1'b0; + end + end // End of Write + end // end of inclock edges + end // end of inclock event + end // read_write; + // End: Read and Write to CAM + + // Start: Change in pattern + always @ (pattern) + begin + // Only updating mbits, mcount, mfound && maddress if + // the pattern input in unregistered, wren_rgd==1'b0 && the pattern + // pattern changes. + if (pattern_reg=="UNREGISTERED") + begin + if (wren_rgd==1'b0) + begin + //////////////////////////////////////// + // FAST MULTIPLE: READ ON NEW PATTERN // + //////////////////////////////////////// + if (match_mode == "FAST_MULTIPLE") + begin + count = 0; + mbits_tmp = numwords_0; + begin: MADDR_FM2 for (k=0; k<numwords; k=k+1) + begin: MWORD_FM2 for (j=0; j<width; j=j+1) + if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) || + ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0))) + begin + if (j == width-1) + begin + if ((count == 0) && (reset_read == 1'b0)) + begin + mfound_int <= 1'b1; + maddress_int <= k; + end + mbits_tmp[k] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // MWORD_FM2 + end // MADDR_FM2 + mcount_int <= count; + mbits_int <= mbits_tmp; + if ((count == 0) || (reset_read == 1'b1)) + begin + mfound_int <= 1'b0; + maddress_int <= address_1; + end + end // end of FAST MULTIPLE + + /////////////////////////////////// + // MULTIPLE: READ ON NEW PATTERN // + /////////////////////////////////// + if (match_mode == "MULTIPLE") + begin + count = 0; + mbits_tmp = mbits_int; + if (reset_read == 1'b1) + begin + begin: MADDR_MM4 for (k=0; k<numwords; k=k+1) + if ( (k % 2)==0 ) + begin + begin: MWORD_MM4 for (j=0; j<width; j=j+1) + if ((((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) || + ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0)))) + begin + if (j == width-1) + begin + mbits_tmp[k+1] = 1'b1; + count = count + 1; + end + end + else + begin + mbits_tmp[k+1] = 1'b0; + j = width; + end + end // MWORD_MM4 + end + end // MADDR_MM4 + end + else + begin + // Match odd addresses && write to odd + begin: MADDR_MM5 for (k=0; k<numwords; k=k+1) + if ( (k % 2)==1 ) + begin + begin: MWORD_MM5 for (j=0; j<width; j=j+1) + if ((((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) || + ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0)))) + begin + if (j == width-1) + begin + mbits_tmp[k] = 1'b1; + if (count == 0) + begin + maddress_int <= k; + end + count = count + 1; + end + end + else + begin + mbits_tmp[k] = 1'b0; + j = width; + end + end // MWORD_MM5 + end + else + begin + if (mbits_tmp[k] == 1'b1) + begin + if (count == 0) + begin + maddress_int <= k; + end + count = count + 1; + end + end + end // MADDR_MM5 + if (count > 0) + begin + mfound_int <= 1'b1; + end + else + begin + mfound_int <= 1'b0; + maddress_int <= word_1; + end + end + mcount_int <= count; + mbits_int <= mbits_tmp; + end + + ///////////////////////////////// + // SINGLE: READ ON NEW PATTERN // + ///////////////////////////////// + if (match_mode == "SINGLE") + begin + mbits_tmp = numwords_0; + index = 0; + count = 0; + begin: MADDR_SM1 for (k=0; k<numwords; k=k+1) + begin: MWORD_SM1 for (j=0; j<width; j=j+1) + if ((((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) || + ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0)))) + begin + if (j == width-1) + begin + mbits_tmp[k] = 1'b1; + count = 1; + index = k; + j = width; + k = numwords; + end + end + else + begin + j = width; + end + end // MWORD_SM1 + end // MADDR_SM1 + mcount_int <= count; + mbits_int <= mbits_tmp; + if (count == 0) + begin + maddress_int <= address_0; + mfound_int <= 1'b0; + end + else + begin + mfound_int <= 1'b1; + maddress_int <= index; + end + end // end of SINGLE + end // end of read on pattern change + else + begin // write on pattern change + // We write to the CAM on the low cycle of inclock + // when wren_rgd==1'b1 and pattern changes. + if ((wren_rgd==1'b1) && (inclock==1'b0)) + begin + addr = wraddress_rgd; + ///////////////////// + // CAM WRITE MODES // + ///////////////////// + if (wrdelete_rgd == 1'b0) + begin + if ((wrxused_int == 1'b1) && (wrx !== {width{1'bz}})) + begin + /////////////////// + // 3 CYCLE WRITE // + /////////////////// + ///////////////// + // WRITE_ZEROS // + ///////////////// + if (write0_done == 1'b1) + begin + for (k =0; k<width; k=k+1 ) + begin + if (pattern[k] == 1'b0) + begin + // "0" ==> "0" + if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0)) + begin // "0" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b0); + // "1" ==> "X" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0)) + begin // "1" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "X" ==> "X" + end + else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1)) + begin // "X" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "U" ==> "0" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1)) + begin // "U" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b0); + end + end + else if (pattern[k] == 1'b1) + begin + // "0" ==> "X" + if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0)) + begin // "0" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "1" ==> "1" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0)) + begin // "1" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b0); + // "X" ==> "X" + end + else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1)) + begin // "X" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "U" ==> "1" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1)) + begin // "U" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b0); + end + end + end + end + //////////////// + // WRITE_ONES // + //////////////// + if (write1_done == 1'b1) + begin + for (k =0; k<width; k=k+1) + begin + if (pattern[k] == 1'b0) + begin + // "0" ==> "0" + if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0)) + begin // "0" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b0); + // "1" ==> "U" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0)) + begin // "1" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b1); + // "X" ==> "0" + end + else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1)) + begin // "X" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b0); + // "U" ==> "U" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1)) + begin // "U" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b1); + end + end + else if (pattern[k] == 1'b1) + begin + // "0" ==> "U" + if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0)) + begin // "0" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b1); + // "1" ==> "1" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0)) + begin // "1" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b0); + // "X" ==> "1" + end + else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1)) + begin // "X" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b0); + // "U" ==> "U" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1)) + begin // "U" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b1); + end + end + end + end + ///////////// + // WRITE_X // + ///////////// + if (writex_done == 1'b1) + begin + for (k =0; k<width; k=k+1) + begin + if ((pattern[k] ^ wrx_int[k]) == 1'b0) + begin + // "0" ==> "0" + if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0)) + begin // "0" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b0); + // "1" ==> "X" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0)) + begin // "1" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "X" ==> "X" + end + else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1)) + begin // "X" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "U" ==> "0" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1)) + begin // "U" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b0); + end + end + else if ((pattern[k] ^ wrx_int[k]) == 1'b1) + begin + // "0" ==> "X" + if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0)) + begin // "0" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "1" ==> "1" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0)) + begin // "1" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b0); + // "X" ==> "X" + end + else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1)) + begin // "X" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "U" ==> "1" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1)) + begin // "U" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b0); + end + end + end + end + end + else + begin // 2 Cycle write + /////////////////// + // 2 CYCLE WRITE // + /////////////////// + ///////////////// + // WRITE_ZEROS // + ///////////////// + if (write0_done == 1'b1) + begin + for (k =0; k<width; k=k+1) + begin + if (pattern[k] == 1'b0) + begin + // "0" ==> "0" + if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0)) + begin // "0" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b0); + // "1" ==> "X" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0)) + begin // "1" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "X" ==> "X" + end + else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1)) + begin // "X" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "U" ==> "0" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1)) + begin // "U" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b0); + end + end + else if (pattern[k] == 1'b1) + begin + // "0" ==> "X" + if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0)) + begin // "0" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "1" ==> "1" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0)) + begin // "1" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b0); + // "X" ==> "X" + end + else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1)) + begin // "X" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b1); + // "U" ==> "1" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1)) + begin // "U" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b0); + end + end + end + end + //////////////// + // WRITE_ONES // + //////////////// + if (write1_done == 1'b1) + begin + for (k =0; k<width; k=k+1) + begin + if (pattern[k] == 1'b0) + begin + // "0" ==> "0" + if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0)) + begin // "0" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b0); + // "1" ==> "U" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0)) + begin // "1" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b1); + // "X" ==> "0" + end + else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1)) + begin // "X" + write_cam_array(addr,k,1'b0); + write_x_array(addr,k,1'b0); + // "U" ==> "U" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1)) + begin // "U" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b1); + end + end + else if (pattern[k] == 1'b1) + begin + // "0" ==> "U" + if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0)) + begin // "0" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b1); + // "1" ==> "1" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0)) + begin // "1" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b0); + // "X" ==> "1" + end + else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1)) + begin // "X" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b0); + // "U" ==> "U" + end + else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1)) + begin // "U" + write_cam_array(addr,k,1'b1); + write_x_array(addr,k,1'b1); + end + end + end + end + end // wrxused_int + end + else + begin // if (wrdelete == 1'b1) begin + //////////////////// + // 2 CYCLE DELETE // + //////////////////// + // Delete is a 2-cycle write + //////////////// + // WRITE_ONES // + //////////////// + if (write0_done == 1'b1) + begin + for (k =0; k<width; k=k+1) + begin + write_cam_array(addr,k,1'b1); + end + end + ///////////// + // WRITE_X // + ///////////// + if (write1_done == 1'b1) + begin + for (k =0; k<width; k=k+1) + begin + write_x_array(addr,k,1'b1); + end + end + end // wrdelete + + ////////////////////////////////////// + // FAST MULTIPLE: READ DURING WRITE // + ////////////////////////////////////// + // Now we need to update mbits, mcount during the write. + if (match_mode == "FAST_MULTIPLE") + begin + mfound_int <= 1'b0; + maddress_int <= address_1; + count = 0; + mbits_tmp = numwords_0; + if ((writex_done == 1'b1) && (wrxused_int == 1'b1)) + begin + begin: WADDR_FM_2 for (k=0; k<numwords; k=k+1) + begin: WWORD_FM_2 for (j=0; j<width; j=j+1) + if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == (pattern[j] ^ wrx_int[j]))) || + ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0))) + begin + if (j == width-1) + begin + if ((count == 0) && (mstart_used == 1'b0)) + begin + mfound_int <= 1'b1; + maddress_int <= k; + end + mbits_tmp[k] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_FM_2 + end // WADDR_FM_2 + end + else + begin + begin: WADDR_FM_3 for (k=0; k<numwords; k=k+1) + begin: WWORD_FM_3 for (j=0; j<width; j=j+1) + if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) || + ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0))) + begin + if (j == width-1) + begin + if ((count == 0) && (mstart_used == 1'b0)) + begin + mfound_int <= 1'b1; + maddress_int <= k; + end + mbits_tmp[k] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_FM_3 + end // WADDR_FM_3 + end + mcount_int <= count; + mbits_int <= mbits_tmp; + end // end of FAST MULTIPLE + + ///////////////////////////////// + // MULTIPLE: READ DURING WRITE // + ///////////////////////////////// + if ((match_mode == "MULTIPLE")) + begin + mfound_int <= 1'b0; + maddress_int <= address_1; + mbits_tmp = numwords_0; + if ((writex_done == 1'b1) && (iwrxused == 1'b1)) + begin + mcount_int <= 0; + first_read_in_write <= 1'b0; + end + else + begin + if (first_read_in_write == 1'b0) + begin + first_read_in_write <= 1'b1; + // Read even addresses but they appear on the odd locations + // of mbits. + count = 0; + begin: WADDR_MM_2 for (k=0; k<numwords; k=k+1) + if ((k % 2) == 0) + begin + if (mbits_int[k] == 1'b1) + begin // counting previous even address matches + count = count + 1; + end + begin: WWORD_MM_2 for (j=0; j<width; j=j+1) + if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) || + ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[k+1] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_MM_2 + end + end // WADDR_MM_2 + end + else + begin + first_read_in_write <= 1'b0; + // Read odd addresses. + count = 0; + begin: WADDR_MM_3 for (k=numwords-1; k>=0; k=k-1) + if ((k % 2) == 1 ) + begin + mbits_tmp[k-1] = mbits_tmp[k]; + end + else + begin + begin: WWORD_MM_3 for (j=0; j<width; j=j+1) + if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) || + ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[k] = 1'b1; + count = count + 1; + end + end + else + begin + j = width; + end + end // WWORD_MM_3 + end + end // WADDR_MM_3 + end + mcount_int <= count; + mbits_int <= mbits_tmp; + end + end // end of MULTIPLE + + /////////////////////////////// + // SINGLE: READ DURING WRITE // + /////////////////////////////// + if (match_mode == "SINGLE") + begin + mbits_tmp = numwords_0; + index = 0; + count = 0; + if ((writex_done == 1'b1) && (wrxused_int == 1'b1)) + begin + begin: WADDR_SM_2 for (k=0; k<numwords; k=k+1) + begin: WWORD_SM_2 for (j=0; j<width; j=j+1) + if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == (pattern[j] ^ wrx_int[j]))) || + ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[k] = 1'b1; + index = k; + count = 1; + j = width; + k = numwords; + end + end + else + begin + j = width; + end + end // WWORD_SM_2 + end // WADDR_SM_2 + end + else + begin + begin: WADDR_SM_3 for (k=0; k<numwords; k=k+1) + begin: WWORD_SM_3 for (j=0; j<width; j=j+1) + if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) || + ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0))) + begin + if (j == width-1) + begin + mbits_tmp[k] = 1'b1; + index = k; + count = 1; + j = width; + k = numwords; + end + end + else + begin + j = width; + end + end // WWORD_SM_3 + end // WADDR_SM_3 + end + mcount_int <= count; + mbits_int <= mbits_tmp; + if (count == 0) + begin + mfound_int <= 1'b0; + maddress_int <= address_0; + end + else + begin + mfound_int <= 1'b1; + maddress_int <= index; + end + end // end of SINGLE + end // End of wren_rgd==1 + end // end of Write on pattern change + end // end of pattern change + end + // End: Change in pattern + + // Begin: Write Busy Control + always @ (posedge wren_rgd) + begin + wrbusy_int <= 1'b1; + end + + always @ (negedge wren_rgd) + begin + wrbusy_int <= 1'b0; + end + + always @ (wraddress_rgd) + begin + if (wren_rgd == 1'b1) + wrbusy_int <= 1'b1; + end + + always @ (posedge write_start_rgd) + begin + wrbusy_int <= 1'b0; + end + + always @ (negedge write_start_rgd) + begin + if (wren_rgd == 1'b1) + wrbusy_int <= 1'b1; + end + // End: Write Busy Control + + // Begin: Registered Outputs + always @ (posedge outclock or posedge outaclr) + begin + if (output_reg == "OUTCLOCK") + begin + if ((outaclr == 1'b1) && (output_aclr == "ON" )) + begin + maddress_rgd <= address_0; + mbits_rgd <= numwords_0; + mfound_rgd <= 1'b0; + mcount_rgd <= address_0; + end + else if (outclocken_pullup == 1'b1) + begin + maddress_rgd <= maddress_int; + mbits_rgd <= mbits_int; + mfound_rgd <= mfound_int; + mcount_rgd <= mcount_int; + end + end + end + + always @ (posedge outaclr or posedge inclock) + begin + if (output_reg == "INCLOCK") + begin + if (output_aclr == "ON" ) + begin + if (outaclr == 1'b1) + begin + maddress_rgd <= address_0; + mbits_rgd <= numwords_0; + mfound_rgd <= 1'b0; + mcount_rgd <= address_0; + end + else if (inclocken_pullup == 1'b1) + begin + maddress_rgd <= maddress_int; + mbits_rgd <= mbits_int; + mfound_rgd <= mfound_int; + mcount_rgd <= mcount_int; + end + end + else if ((inclocken_pullup == 1'b1) && (inaclr_pulldown != 1'b1)) + begin + maddress_rgd <= maddress_int; + mbits_rgd <= mbits_int; + mfound_rgd <= mfound_int; + mcount_rgd <= mcount_int; + end + end + end + // End: Registered Outputs + + // Begin: Write Control + always @ (posedge wrbusy_int) + begin + write0 <= 1'b1; + write1 <= 1'b0; + writex <= 1'b0; + end + + always @ (negedge wrbusy_int) + begin + write0 <= 1'b0; + end + + always @ (posedge write0_done) + begin + write1 <= 1'b1; + if ((wrxused_int == 1'b1) && (wrx !== {width{1'bz}})) write0 <= 1'b0; + end + + always @ (posedge write1_done) + begin + if ((wrxused_int == 1'b1) && (wrx !== {width{1'bz}} )) writex <= 1'b1; + else writex <= 1'b0; + write1 <= 1'b0; + end + + always @ (posedge writex_done) + begin + write0 <= 1'b0; + write1 <= 1'b0; + writex <= 1'b0; + end + + // Begin: Read Control + always @ (posedge mstart_rgd1) + begin + if ((match_mode == "SINGLE") || (match_mode == "FAST_MULTIPLE")) rdbusy_int <= 1'b0; + else rdbusy_int <= 1'b1; + end + + always @ (posedge mstart_rgd2) + begin + rdbusy_int <= 1'b0; + end + + always @ (posedge mnext) + begin + if (get_first_match == 1'b1) get_next_match <= 1'b1; + end + + always @ (negedge mnext) + begin + get_next_match <= 1'b0; + end + // End: Read Control + + // Evaluate parameters + assign pattern_int = (pattern_reg == "UNREGISTERED") ? pattern : pattern_rgd; + assign wrx_int = (wrx_reg == "UNREGISTERED" ) ? wrx : wrx_rgd; + assign wrxused_int = (wrx_reg == "UNREGISTERED") ? wrxused_pullup : wrxused_rgd; + assign maddress = (output_reg == "UNREGISTERED") ? maddress_int : maddress_rgd; + assign mbits = (output_reg == "UNREGISTERED") ? mbits_int : mbits_rgd; + assign mfound = (output_reg == "UNREGISTERED") ? mfound_int : mfound_rgd; + assign mcount = (output_reg == "UNREGISTERED") ? mcount_int : mcount_rgd; + assign wrbusy = wrbusy_int; + assign rdbusy = rdbusy_int; + assign outclock_int = (output_reg == "OUTCLOCK") ? outclock : inclock; + assign outaclr_int = (output_reg == "OUTCLOCK") ? outaclr : inaclr_pulldown; + assign wrxused_pullup = wrxused; + assign inclocken_pullup = inclocken; + assign outclocken_pullup = outclocken; + assign wrdelete_pulldown = wrdelete; + assign inaclr_pulldown = inaclr; + + assign # 2 rdbusy_delayed = rdbusy_int; + +endmodule // end of altcam + +//-------------------------------------------------------------------------- +// 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 (separate Read and Write) +// behaviour +// +//-------------------------------------------------------------------------- +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module altdpram (wren, data, wraddress, inclock, inclocken, rden, rdaddress, + outclock, outclocken, aclr, q); + +// PARAMETER DECLARATION + parameter width = 1; + parameter widthad = 1; + parameter numwords = 0; + parameter lpm_file = "UNUSED"; + parameter lpm_hint = "USE_EAB=ON"; + parameter use_eab = "ON"; + parameter lpm_type = "altdpram"; + parameter indata_reg = "INCLOCK"; + parameter indata_aclr = "ON"; + parameter wraddress_reg = "INCLOCK"; + parameter wraddress_aclr = "ON"; + parameter wrcontrol_reg = "INCLOCK"; + parameter wrcontrol_aclr = "ON"; + parameter rdaddress_reg = "OUTCLOCK"; + parameter rdaddress_aclr = "ON"; + parameter rdcontrol_reg = "OUTCLOCK"; + parameter rdcontrol_aclr = "ON"; + parameter outdata_reg = "UNREGISTERED"; + parameter outdata_aclr = "ON"; + parameter maximum_depth = 2048; + parameter intended_device_family = "APEX20KE"; + parameter write_at_low_clock = ((wrcontrol_reg == "INCLOCK") && + (((lpm_hint == "USE_EAB=ON") || (lpm_hint == "UNUSED")) && + (use_eab == "ON"))) ? + 1 : 0; + parameter rden_low_output_0 = ((intended_device_family == "APEX20K") && + (((lpm_hint == "USE_EAB=ON") || (lpm_hint == "UNUSED")) && + (use_eab == "ON"))) ? + 1 : 0; + +// INPUT PORT DECLARATION + input wren; // Write enable input + input [width-1:0] data; // Data input to the memory + input [widthad-1:0] wraddress; // Write address input to the memory + input inclock; // Input or write clock + input inclocken; // Clock enable for inclock + input rden; // Read enable input. Disable reading when low + input [widthad-1:0] rdaddress; // Write address input to the memory + input outclock; // Output or read clock + input outclocken; // Clock enable for outclock + input aclr; // Asynchronous clear input + +// OUTPUT PORT DECLARATION + output [width-1:0] q; // Data output from the memory + +// INTERNAL SIGNAL/REGISTER DECLARATION + reg [width-1:0] mem_data [0:(1<<widthad)-1]; + reg [8*256:1] ram_initf; + reg [width-1:0] data_write_at_high; + reg [width-1:0] data_write_at_low; + reg [widthad-1:0] wraddress_at_high; + reg [widthad-1:0] wraddress_at_low; + reg [width-1:0] mem_output; + reg [width-1:0] mem_output_at_outclock; + reg [widthad-1:0] rdaddress_at_inclock; + reg [widthad-1:0] rdaddress_at_outclock; + reg wren_at_high; + reg wren_at_low; + reg rden_at_inclock; + reg rden_at_outclock; + +// INTERNAL WIRE DECLARATION + wire aclr_on_wraddress; + wire aclr_on_wrcontrol; + wire aclr_on_rdaddress; + wire aclr_on_rdcontrol; + wire aclr_on_indata; + wire aclr_on_outdata; + wire [width-1:0] data_tmp; + wire [width-1:0] previous_read_data; + wire [width-1:0] new_read_data; + wire [widthad-1:0] wraddress_tmp; + wire [widthad-1:0] rdaddress_tmp; + wire wren_tmp; + wire rden_tmp; + +// INTERNAL TRI DECLARATION + tri0 inclock; + tri1 inclocken; + tri0 outclock; + tri1 outclocken; + tri1 rden; + tri0 aclr; + +// LOCAL INTEGER DECLARATION + integer i; + integer i_numwords; + +// COMPONENT INSTANTIATIONS + ALTERA_MF_MEMORY_INITIALIZATION mem (); + +// INITIAL CONSTRUCT BLOCK + initial + begin + // Check for invalid parameters + if (width <= 0) + begin + $display("Error! width parameter must be greater than 0."); + $stop; + end + if (widthad <= 0) + begin + $display("Error! widthad parameter must be greater than 0."); + $stop; + end + + // Initialize mem_data + i_numwords = (numwords) ? numwords : 1<<widthad; + if (lpm_file == "UNUSED") + for (i=0; i<i_numwords; i=i+1) + mem_data[i] = 0; + else + begin +`ifdef NO_PLI + $readmemh(lpm_file, mem_data); +`else + `ifdef USE_RIF + $readmemh(lpm_file, mem_data); + `else + mem.convert_hex2ver(lpm_file, width, ram_initf); + $readmemh(ram_initf, mem_data); + `endif +`endif + end + + // Power-up conditions + mem_output = 0; + mem_output_at_outclock = 0; + data_write_at_high = 0; + data_write_at_low = 0; + rdaddress_at_inclock = 0; + rdaddress_at_outclock = 0; + rden_at_outclock = 1; + rden_at_inclock = 1; + end + + +// ALWAYS CONSTRUCT BLOCKS + + // Set up logics that respond to the postive edge of inclock + // some logics may be affected by Asynchronous Clear + always @(posedge inclock) + begin + if ((aclr == 1) && (indata_aclr == "ON") && (indata_reg != "UNREGISTERED") ) + data_write_at_high <= 0; + else if (inclocken == 1) + data_write_at_high <= data; + + if ((aclr == 1) && (wraddress_aclr == "ON") && (wraddress_reg != "UNREGISTERED") ) + wraddress_at_high <= 0; + else if (inclocken == 1) + wraddress_at_high <= wraddress; + + if ((aclr == 1) && (wrcontrol_aclr == "ON") && (wrcontrol_reg != "UNREGISTERED") ) + wren_at_high <= 0; + else if (inclocken == 1) + wren_at_high <= wren; + + if ((aclr == 1) && (rdaddress_aclr == "ON") && (rdaddress_reg != "UNREGISTERED") ) + rdaddress_at_inclock <= 0; + else if (inclocken == 1) + rdaddress_at_inclock <= rdaddress; + + if ((aclr == 1) && (rdcontrol_aclr == "ON") && (rdcontrol_reg != "UNREGISTERED") ) + rden_at_inclock <= 0; + else if (inclocken == 1) + rden_at_inclock <= rden; + end + + // Set up logics that respond to the negative edge of inclock + // some logics may be affected by Asynchronous Clear + always @(negedge inclock) + begin + if ((aclr == 1) && (indata_aclr == "ON") && (indata_reg != "UNREGISTERED") ) + data_write_at_low <= 0; + else if (inclocken == 1) + data_write_at_low <= data_write_at_high; + + if ((aclr == 1) && (wraddress_aclr == "ON") && (wraddress_reg != "UNREGISTERED") ) + wraddress_at_low <= 0; + else if (inclocken == 1) + wraddress_at_low <= wraddress_at_high; + + if ((aclr == 1) && (wrcontrol_aclr == "ON") && (wrcontrol_reg != "UNREGISTERED") ) + wren_at_low <= 0; + else if (inclocken == 1) + wren_at_low <= wren_at_high; + end + + // Set up logics that respond to the positive edge of outclock + // some logics may be affected by Asynchronous Clear + always @(posedge outclock) + begin + if ((aclr == 1) && (rdaddress_aclr == "ON") && (rdaddress_reg != "UNREGISTERED") ) + rdaddress_at_outclock <= 0; + else if (outclocken == 1) + rdaddress_at_outclock <= rdaddress; + + if ((aclr == 1) && (rdcontrol_aclr == "ON") && (rdcontrol_reg != "UNREGISTERED") ) + rden_at_outclock <= 0; + else if (outclocken == 1) + rden_at_outclock <= rden; + + if ((aclr == 1) && (outdata_aclr == "ON") && (outdata_reg != "UNREGISTERED") ) + mem_output_at_outclock <= 0; + else if (outclocken == 1) + mem_output_at_outclock <= mem_output; + end + + // Asynchronous Logic + // Update memory with the latest data + always @(data_tmp or wraddress_tmp or wren_tmp) + begin + if (wren_tmp == 1) + mem_data[wraddress_tmp] <= data_tmp; + end + + always @(new_read_data) + begin + mem_output <= new_read_data; + end + +// CONTINUOUS ASSIGNMENT + + // The following circuits will select for appropriate connections based on + // the given parameter values + + assign aclr_on_wraddress = ((wraddress_aclr == "ON") ? + aclr + : 0); + + assign aclr_on_wrcontrol = ((wrcontrol_aclr == "ON") ? + aclr + : 0); + + assign aclr_on_rdaddress = ((rdaddress_aclr == "ON") ? + aclr + : 0); + + assign aclr_on_rdcontrol = ((rdcontrol_aclr == "ON") ? + aclr + : 0); + + assign aclr_on_indata = ((indata_aclr == "ON") ? + aclr + : 0); + + assign aclr_on_outdata = ((outdata_aclr == "ON") ? + aclr + : 0); + + assign data_tmp = ((indata_reg == "INCLOCK") ? + (write_at_low_clock ? + ((aclr_on_indata == 1) ? + 0 + : data_write_at_low) + : ((aclr_on_indata == 1) ? + 0 + : data_write_at_high)) + : data); + + assign wraddress_tmp = ((wraddress_reg == "INCLOCK") ? + (write_at_low_clock ? + ((aclr_on_wraddress == 1) ? + 0 + : wraddress_at_low) + : ((aclr_on_wraddress == 1) ? + 0 + : wraddress_at_high)) + : wraddress); + + assign wren_tmp = ((wrcontrol_reg == "INCLOCK") ? + (write_at_low_clock ? + ((aclr_on_wrcontrol == 1) ? + 0 + : wren_at_low) + : ((aclr_on_wrcontrol == 1) ? + 0 + :wren_at_high)) + : wren); + + assign rdaddress_tmp = ((rdaddress_reg == "INCLOCK") ? + ((aclr_on_rdaddress == 1) ? + 0 + : rdaddress_at_inclock) + : ((rdaddress_reg == "OUTCLOCK") ? + ((aclr_on_rdaddress == 1) ? + 0 + : rdaddress_at_outclock) + : rdaddress)); + + assign rden_tmp = ((rdcontrol_reg == "INCLOCK") ? + ((aclr_on_rdcontrol == 1) ? + 0 + : rden_at_inclock) + : ((rdcontrol_reg == "OUTCLOCK") ? + ((aclr_on_rdcontrol == 1) ? + 0 + : rden_at_outclock) + : rden)); + + assign previous_read_data = mem_output; + + assign new_read_data = ((rden_tmp == 1) ? + mem_data[rdaddress_tmp] + : ((rden_low_output_0) ? + 0 + : previous_read_data)); + + assign q = ((outdata_reg == "OUTCLOCK")? + ((aclr_on_outdata == 1) ? + 0 + :mem_output_at_outclock) + : mem_output); + +endmodule // altdpram + +// START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : ALTSYNCRAM +// +// Description : Synchronous ram model for Stratix series family +// +// Limitation : +// +// END_MODULE_NAME-------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +// BEGINNING OF MODULE + +// MODULE DECLARATION + +module altsyncram ( + wren_a, + wren_b, + rden_b, + data_a, + data_b, + address_a, + address_b, + clock0, + clock1, + clocken0, + clocken1, + aclr0, + aclr1, + byteena_a, + byteena_b, + addressstall_a, + addressstall_b, + q_a, + q_b + ); + +// GLOBAL PARAMETER DECLARATION + + // PORT A PARAMETERS + parameter width_a = 1; + parameter widthad_a = 1; + parameter numwords_a = 0; + parameter outdata_reg_a = "UNREGISTERED"; + parameter address_aclr_a = "NONE"; + parameter outdata_aclr_a = "NONE"; + parameter indata_aclr_a = "NONE"; + parameter wrcontrol_aclr_a = "NONE"; + parameter byteena_aclr_a = "NONE"; + parameter width_byteena_a = 1; + + // PORT B PARAMETERS + parameter width_b = 1; + parameter widthad_b = 1; + parameter numwords_b = 0; + parameter rdcontrol_reg_b = "CLOCK1"; + parameter address_reg_b = "CLOCK1"; + parameter outdata_reg_b = "UNREGISTERED"; + parameter outdata_aclr_b = "NONE"; + parameter rdcontrol_aclr_b = "NONE"; + parameter indata_reg_b = "CLOCK1"; + parameter wrcontrol_wraddress_reg_b = "CLOCK1"; + parameter byteena_reg_b = "CLOCK1"; + parameter indata_aclr_b = "NONE"; + parameter wrcontrol_aclr_b = "NONE"; + parameter address_aclr_b = "NONE"; + parameter byteena_aclr_b = "NONE"; + parameter width_byteena_b = 1; + + // STRATIX II RELATED PARAMETERS + parameter clock_enable_input_a = "NORMAL"; + parameter clock_enable_output_a = "NORMAL"; + parameter clock_enable_input_b = "NORMAL"; + parameter clock_enable_output_b = "NORMAL"; + + // GLOBAL PARAMETERS + parameter operation_mode = "BIDIR_DUAL_PORT"; + parameter byte_size = 8; + parameter read_during_write_mode_mixed_ports = "DONT_CARE"; + parameter ram_block_type = "AUTO"; + parameter init_file = "UNUSED"; + parameter init_file_layout = "UNUSED"; + parameter maximum_depth = 0; + parameter intended_device_family = "Stratix"; + + parameter lpm_hint = "UNUSED"; + parameter lpm_type = "altsyncram"; + + parameter cread_during_write_mode_mixed_ports = + ((read_during_write_mode_mixed_ports == "DONT_CARE") || + (read_during_write_mode_mixed_ports == "UNUSED"))? "DONT_CARE": + read_during_write_mode_mixed_ports; + + parameter implement_in_les = "OFF"; + + parameter power_up_uninitialized = "FALSE"; + + // Internal parameters + parameter is_bidir_and_wrcontrol_addb_clk0 = (((operation_mode == "BIDIR_DUAL_PORT") && (wrcontrol_wraddress_reg_b == "CLOCK0"))? + 1 : 0); + parameter is_bidir_and_wrcontrol_addb_clk1 = (((operation_mode == "BIDIR_DUAL_PORT") && (wrcontrol_wraddress_reg_b == "CLOCK1"))? + 1 : 0); + + parameter megaram_or_mram = (((ram_block_type == "M-RAM") || (ram_block_type == "MEGARAM"))? 1: 0); + + parameter check_simultaneous_read_write = ((megaram_or_mram || + ((cread_during_write_mode_mixed_ports == "DONT_CARE") && + (ram_block_type == "AUTO")))? 1 : 0); + parameter dual_port_addreg_b_clk0 = (((operation_mode == "DUAL_PORT") && (address_reg_b == "CLOCK0"))? 1: 0); + + parameter dual_port_addreg_b_clk1 = (((operation_mode == "DUAL_PORT") && (address_reg_b == "CLOCK1"))? 1: 0); + + +// INPUT PORT DECLARATION + + input wren_a; // Port A write/read enable input + input wren_b; // Port B write enable input + input rden_b; // Port B read enable input + input [width_a-1:0] data_a; // Port A data input + input [width_b-1:0] data_b; // Port B data input + input [widthad_a-1:0] address_a; // Port A address input + input [widthad_b-1:0] address_b; // Port B address input + + // clock inputs on both ports and here are their usage + // Port A -- 1. all input registers must be clocked by clock0. + // 2. output register can be clocked by either clock0, clock1 or none. + // Port B -- 1. all input registered must be clocked by either clock0 or clock1. + // 2. output register can be clocked by either clock0, clock1 or none. + input clock0; + input clock1; + + // clock enable inputs and here are their usage + // clocken0 -- can only be used for enabling clock0. + // clocken1 -- can only be used for enabling clock1. + input clocken0; + input clocken1; + + // clear inputs on both ports and here are their usage + // 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 clear0, clear1 or none. + // 2. output register can be cleared by either clear0, clear1 or none. + input aclr0; + input aclr1; + + input [width_byteena_a-1:0] byteena_a; // Port A byte enable input + input [width_byteena_b-1:0] byteena_b; // Port B byte enable input + + // Stratix II related ports + input addressstall_a; + input addressstall_b; + + + +// OUTPUT PORT DECLARATION + + output [width_a-1:0] q_a; // Port A output + output [width_b-1:0] q_b; // Port B output + +// INTERNAL REGISTERS DECLARATION + + reg [width_a-1:0] mem_data [0:(1<<widthad_a)-1]; + reg [width_b-1:0] mem_data_b [0:(1<<widthad_b)-1]; + reg [width_a-1:0] i_data_reg_a; + reg [width_a-1:0] temp_wa; + reg [width_a-1:0] temp_wa2; + reg [width_a-1:0] temp_wa2b; + reg [width_b-1:0] i_data_reg_b; + reg [width_b-1:0] temp_wb; + reg [width_b-1:0] temp_wb2; + reg temp; + reg [width_a-1:0] i_q_reg_a; + reg [width_a-1:0] i_q_tmp_a; + reg [width_a-1:0] i_q_tmp2_a; + reg [width_b-1:0] i_q_reg_b; + reg [width_b-1:0] i_q_tmp_b; + reg [width_b-1:0] i_q_tmp2_b; + reg [width_a-1:0] i_byteena_mask_reg_a; + reg [width_b-1:0] i_byteena_mask_reg_b; + reg [widthad_a-1:0] i_address_reg_a; + reg [widthad_b-1:0] i_address_reg_b; + + + reg [width_a-1:0] i_byteena_mask_reg_a_tmp; + reg [width_b-1:0] i_byteena_mask_reg_b_tmp; + reg [width_a-1:0] i_byteena_mask_reg_a_out; + reg [width_b-1:0] i_byteena_mask_reg_b_out; + reg [width_a-1:0] i_byteena_mask_reg_a_x; + reg [width_b-1:0] i_byteena_mask_reg_b_x; + + reg [8*256:1] ram_initf; + reg i_wren_reg_a; + reg i_wren_reg_b; + reg i_rden_reg_b; + reg i_read_flag_a; + reg i_read_flag_b; + reg i_write_flag_a; + reg i_write_flag_b; + reg good_to_go_a; + reg good_to_go_b; + reg [31:0] file_desc; + reg init_file_b_port; + reg i_nmram_write_a; + reg i_nmram_write_b; + + reg [width_a - 1: 0] wa_mult_x; + reg [width_a - 1: 0] wa_mult_x_ii; + reg [width_a - 1: 0] wa_mult_x_iii; + reg [widthad_a + width_a - 1:0] add_reg_a_mult_wa; + reg [widthad_b + width_b -1:0] add_reg_b_mult_wb; + reg [widthad_a + width_a - 1:0] add_reg_a_mult_wa_pl_wa; + reg [widthad_b + width_b -1:0] add_reg_b_mult_wb_pl_wb; + + +// INTERNAL WIRE DECLARATIONS + + wire i_indata_aclr_a; + wire i_address_aclr_a; + wire i_wrcontrol_aclr_a; + wire i_indata_aclr_b; + wire i_address_aclr_b; + wire i_wrcontrol_aclr_b; + wire i_outdata_aclr_a; + wire i_outdata_aclr_b; + wire i_rdcontrol_aclr_b; + wire i_byteena_aclr_a; + wire i_byteena_aclr_b; + wire i_outdata_clk_a; + wire i_outdata_clken_a; + wire i_outdata_clk_b; + wire i_outdata_clken_b; + wire i_clocken0; + wire i_clocken1; + wire i_clocken0_b; + +// INTERNAL TRI DECLARATION + + tri0 wren_a; + tri0 wren_b; + tri1 rden_b; + tri1 clock0; + tri1 clock1; + tri1 clocken0; + tri1 clocken1; + tri0 aclr0; + tri0 aclr1; + tri0 addressstall_a; + tri0 addressstall_b; + tri1 [width_byteena_a-1:0] i_byteena_a; + tri1 [width_byteena_b-1:0] i_byteena_b; + + +// LOCAL INTEGER DECLARATION + + integer i_numwords_a; + integer i_numwords_b; + integer i_aclr_flag_a; + integer i_aclr_flag_b; + integer i_q_tmp2_a_idx; + + // for loop iterators + integer i; + integer i2; + integer i3; + integer i4; + integer i5; + integer j; + integer j2; + integer k; + integer k2; + integer k3; + integer k4; + + // For temporary calculation + integer i_div_wa; + integer j_plus_i2; + integer j2_plus_i5; + integer j_plus_i2_div_a; + integer j2_plus_i5_div_a; + + // ------------------------ + // COMPONENT INSTANTIATIONS + // ------------------------ + ALTERA_DEVICE_FAMILIES dev (); + ALTERA_MF_MEMORY_INITIALIZATION mem (); + + +// INITIAL CONSTRUCT BLOCK + + initial + begin + + i_numwords_a = (numwords_a != 0) ? numwords_a : (1 << widthad_a); + i_numwords_b = (numwords_b != 0) ? numwords_b : (1 << widthad_b); + + // Parameter Checking + if ((operation_mode != "BIDIR_DUAL_PORT") && (operation_mode != "SINGLE_PORT") && + (operation_mode != "DUAL_PORT") && (operation_mode != "ROM")) + begin + $display("Error: Not a valid operation mode."); + $finish; + end + + if ((ram_block_type != "M4K") && (ram_block_type != "M512") && + (ram_block_type != "M-RAM") && (ram_block_type != "MEGARAM") && + (ram_block_type != "AUTO")) + begin + $display("Error: RAM_BLOCK_TYPE HAS AN INVALID VALUE. IT CAN ONLY BE M512, M4K, M-RAM OR AUTO"); + $finish; + end + + if ((cread_during_write_mode_mixed_ports != "DONT_CARE") && + (cread_during_write_mode_mixed_ports != "OLD_DATA")) + begin + $display("Error: INVALID VALUE FOR READ_DURING_WRITE_MODE_MIXED_PORTS PARAMETER. IT HAS TO BE OLD_DATA OR DONT_CARE"); + $finish; + end + + if (ram_block_type == "LARGE" && init_file != "UNUSED") + begin + $display("Error: M-RAM block type doesn't support the use of an initialization file"); + $finish; + end + + if ((byte_size != 8) && (byte_size != 9) && (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0)) + begin + $display("Error: BYTE SIZE HAS TO BE EITHER 8 or 9"); + $finish; + end + + if ((byte_size != 8) && (byte_size != 9) && (byte_size != 1) && + (byte_size != 2) && (byte_size != 4) && (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 1)) + begin + $display("Error: BYTE SIZE has to be either 1, 2, 4, 8 or 9"); + $finish; + end + + if (width_a <= 0) + begin + $display("Error: Invalid value for WIDTH_A parameter"); + $finish; + end + + if ((width_b <= 0) && + ((operation_mode != "SINGLE_PORT") || (operation_mode != "ROM"))) + begin + $display("Error: Invalid value for WIDTH_B parameter"); + $finish; + end + + if (widthad_a <= 0) + begin + $display("Error: Invalid value for WIDTHAD_A parameter"); + $finish; + end + + if ((width_b <= 0) && + ((operation_mode != "SINGLE_PORT") || (operation_mode != "ROM"))) + begin + $display("Error: Invalid value for WIDTHAD_B parameter"); + $finish; + end + + if ((operation_mode == "ROM") && + ((ram_block_type == "M-RAM") || (ram_block_type == "MEGARAM"))) + begin + $display("Error: ROM mode does not support ram_block_type = M-RAM"); + $finish; + end + + if (((wrcontrol_aclr_a != "NONE") && (wrcontrol_aclr_a != "UNUSED")) && (ram_block_type == "M512") && (operation_mode == "SINGLE_PORT")) + begin + $display("Error: Wren_a cannot have clear in single port mode for M512 block"); + $finish; + end + + if ((operation_mode == "DUAL_PORT") && (i_numwords_a * width_a != i_numwords_b * width_b)) + begin + $display("Error: Total number of bits of port A and port B should be the same for dual port mode"); + $finish; + end + + if (((rdcontrol_aclr_b != "NONE") && (rdcontrol_aclr_b != "UNUSED")) && (ram_block_type == "M512") && (operation_mode == "DUAL_PORT")) + begin + $display("Error: rden_b cannot have clear in simple dual port mode for M512 block"); + $finish; + end + + if ((operation_mode == "BIDIR_DUAL_PORT") && (i_numwords_a * width_a != i_numwords_b * width_b)) + begin + $display("Error: Total number of bits of port A and port B should be the same for bidir dual port mode"); + $finish; + end + + if ((operation_mode == "BIDIR_DUAL_PORT") && (ram_block_type == "M512")) + begin + $display("Error: M512 block type doesn't support bidir dual mode"); + $finish; + end + + if (((ram_block_type == "M-RAM") || (ram_block_type == "MEGARAM")) && + (cread_during_write_mode_mixed_ports == "OLD_DATA")) + begin + $display("Error: M-RAM doesn't support OLD_DATA value for READ_DURING_WRITE_MODE_MIXED_PORTS parameter"); + $finish; + end + + if ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) == 0) && (clock_enable_input_a == "BYPASS")) + begin + $display("Error: BYPASS value for CLOCK_ENABLE_INPUT_A is not supported in %s device family", intended_device_family); + $finish; + end + + if ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) == 0) && (clock_enable_output_a == "BYPASS")) + begin + $display("Error: BYPASS value for CLOCK_ENABLE_OUTPUT_A is not supported in %s device family", intended_device_family); + $finish; + end + + if ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) == 0) && (clock_enable_input_b == "BYPASS")) + begin + $display("Error: BYPASS value for CLOCK_ENABLE_INPUT_B is not supported in %s device family", intended_device_family); + $finish; + end + + if ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) == 0) && (clock_enable_output_b == "BYPASS")) + begin + $display("Error: BYPASS value for CLOCK_ENABLE_OUTPUT_B is not supported in %s device family", intended_device_family); + $finish; + end + + if ((implement_in_les != "OFF") && (implement_in_les != "ON")) + begin + $display("Error: Illegal value for implement_in_les parameter"); + $finish; + end + + if (((dev.FEATURE_FAMILY_HAS_M512(intended_device_family)) == 0) && (ram_block_type == "M512")) + begin + $display("Error: M512 value for ram_block_type parameter is not supported in %s device family", intended_device_family); + $finish; + end + + if (((dev.FEATURE_FAMILY_HAS_MEGARAM(intended_device_family)) == 0) && (ram_block_type == "MEGARAM")) + begin + $display("Error: MEGARAM value for ram_block_type parameter is not supported in %s device family", intended_device_family); + $finish; + end + + // ***************************************** + // legal operations for all operation modes: + // | PORT A | PORT B | + // | RD WR | RD WR | + // BDP | x x | x x | + // DP | x | x | + // SP | x x | | + // ROM | x | | + // ***************************************** + + + // Initialize mem_data + + if ((init_file == "UNUSED") || (init_file == "")) + begin + if (operation_mode == "ROM") + $display("Error! altsyncram needs data file for memory initialization.\n"); + else + begin + if ((check_simultaneous_read_write || + (dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) == 1) || + (dev.IS_FAMILY_HARDCOPYII(intended_device_family) == 1) || + (power_up_uninitialized == "TRUE") ) && (implement_in_les == "OFF") ) + begin + wa_mult_x = {width_a{1'bx}}; + for (i = 0; i < (1 << widthad_a); i = i + 1) + mem_data[i] = wa_mult_x; + end + else + for (i = 0; i < (1 << widthad_a); i = i + 1) + mem_data[i] = 0; + end + end + + else // Memory initialization file is used + begin + if (check_simultaneous_read_write || + (((dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) == 1) || + (dev.IS_FAMILY_HARDCOPYII(intended_device_family) == 1) || (power_up_uninitialized == "TRUE")) && + (operation_mode != "ROM"))) + begin + wa_mult_x = {width_a{1'bx}}; + for (i = 0; i < (1 << widthad_a); i = i + 1) + mem_data[i] = wa_mult_x; + end + else + begin + wa_mult_x = {width_a{1'b0}}; + for (i = 0; i < (1 << widthad_a); i = i + 1) + mem_data[i] = wa_mult_x; + end + + init_file_b_port = 0; + + if ((init_file_layout != "PORT_A") && + (init_file_layout != "PORT_B")) + begin + if (operation_mode == "DUAL_PORT") + init_file_b_port = 1; + else + init_file_b_port = 0; + end + else + begin + if (init_file_layout == "PORT_A") + init_file_b_port = 0; + else if (init_file_layout == "PORT_B") + init_file_b_port = 1; + end + + if (init_file_b_port) + begin + `ifdef NO_PLI + $readmemh(init_file, mem_data_b); + `else + `ifdef USE_RIF + $readmemh(init_file, mem_data_b); + `else + mem.convert_hex2ver(init_file, width_b, ram_initf); + $readmemh(ram_initf, mem_data_b); + `endif + `endif + + for (i = 0; i < (i_numwords_b * width_b); i = i + 1) + begin + temp_wb = mem_data_b[i / width_b]; + i_div_wa = i / width_a; + temp_wa = mem_data[i_div_wa]; + temp_wa[i % width_a] = temp_wb[i % width_b]; + mem_data[i_div_wa] = temp_wa; + end + end + else + begin + `ifdef NO_PLI + $readmemh(init_file, mem_data); + `else + `ifdef USE_RIF + $readmemh(init_file, mem_data); + `else + mem.convert_hex2ver(init_file, width_a, ram_initf); + $readmemh(ram_initf, mem_data); + `endif + `endif + end + end + i_nmram_write_a = 0; + i_nmram_write_b = 0; + + i_aclr_flag_a = 0; + i_aclr_flag_b = 0; + + // Initialize internal registers/signals + i_data_reg_a = ~0; + i_data_reg_b = ~0; + i_address_reg_a = 0; + i_address_reg_b = 0; + i_wren_reg_a = 0; + i_wren_reg_b = 0; + i_rden_reg_b = 1; + i_read_flag_a = 0; + i_read_flag_b = 0; + i_write_flag_a = 0; + i_write_flag_b = 0; + i_byteena_mask_reg_a = ~0; + i_byteena_mask_reg_b = ~0; + i_byteena_mask_reg_a_x = 0; + i_byteena_mask_reg_b_x = 0; + + if (check_simultaneous_read_write) + begin + i_q_tmp_a = {width_a{1'bx}}; + i_q_tmp_b = {width_b{1'bx}}; + i_q_tmp2_a = {width_a{1'bx}}; + i_q_tmp2_b = {width_b{1'bx}}; + i_q_reg_a = {width_a{1'bx}}; + i_q_reg_b = {width_b{1'bx}}; + end + else + begin + i_q_tmp_a = 0; + i_q_tmp_b = 0; + i_q_tmp2_a = 0; + i_q_tmp2_b = 0; + i_q_reg_a = 0; + i_q_reg_b = 0; + end + + good_to_go_a = 0; + good_to_go_b = 0; + + end + +// SIGNAL ASSIGNMENT + + // Clock signal assignment + + // port a clock assignments: + assign i_outdata_clk_a = (outdata_reg_a == "CLOCK1") ? + clock1 : ((outdata_reg_a == "CLOCK0") ? + clock0 : 1'b0); + // port b clock assignments: + assign i_outdata_clk_b = (outdata_reg_b == "CLOCK1") ? + clock1 : ((outdata_reg_b == "CLOCK0") ? + clock0 : 1'b0); + + // Clock enable signal assignment + + // port a clock enable assignments: + assign i_outdata_clken_a = (clock_enable_output_a == "BYPASS") ? + 1'b1 : (outdata_reg_a == "CLOCK1") ? + clocken1 : ((outdata_reg_a == "CLOCK0") ? + clocken0 : 1'b1); + // port b clock enable assignments: + assign i_outdata_clken_b = (clock_enable_output_b == "BYPASS") ? + 1'b1 : (outdata_reg_b == "CLOCK0") ? + clocken0 : ((outdata_reg_b == "CLOCK1") ? + clocken1 : 1'b1); + + + + assign i_clocken0 = (clock_enable_input_a == "BYPASS") ? + 1'b1 : clocken0; + + assign i_clocken0_b = (clock_enable_input_b == "BYPASS") ? + 1'b1 : clocken0; + + assign i_clocken1 = (clock_enable_input_b == "BYPASS") ? + 1'b1 : clocken1; + + + + // Async clear signal assignment + + // port a clear assigments: + assign i_indata_aclr_a = (indata_aclr_a == "CLEAR0") ? aclr0 : 1'b0; + assign i_address_aclr_a = (address_aclr_a == "CLEAR0") ? aclr0 : 1'b0; + assign i_wrcontrol_aclr_a = (wrcontrol_aclr_a == "CLEAR0") ? aclr0 : 1'b0; + assign i_byteena_aclr_a = (byteena_aclr_a == "CLEAR0") ? + aclr0 : ((byteena_aclr_a == "CLEAR1") ? + aclr1 : 1'b0); + assign i_outdata_aclr_a = (outdata_aclr_a == "CLEAR0") ? + aclr0 : ((outdata_aclr_a == "CLEAR1") ? + aclr1 : 1'b0); + // port b clear assignments: + assign i_indata_aclr_b = (indata_aclr_b == "CLEAR0") ? + aclr0 : ((indata_aclr_b == "CLEAR1") ? + aclr1 : 1'b0); + assign i_address_aclr_b = (address_aclr_b == "CLEAR0") ? + aclr0 : ((address_aclr_b == "CLEAR1") ? + aclr1 : 1'b0); + assign i_wrcontrol_aclr_b = (wrcontrol_aclr_b == "CLEAR0") ? + aclr0 : ((wrcontrol_aclr_b == "CLEAR1") ? + aclr1 : 1'b0); + assign i_rdcontrol_aclr_b = (rdcontrol_aclr_b == "CLEAR0") ? + aclr0 : ((rdcontrol_aclr_b == "CLEAR1") ? + aclr1 : 1'b0); + assign i_byteena_aclr_b = (byteena_aclr_b == "CLEAR0") ? + aclr0 : ((byteena_aclr_b == "CLEAR1") ? + aclr1 : 1'b0); + assign i_outdata_aclr_b = (outdata_aclr_b == "CLEAR0") ? + aclr0 : ((outdata_aclr_b == "CLEAR1") ? + aclr1 : 1'b0); + + assign i_byteena_a = byteena_a; + assign i_byteena_b = byteena_b; + + + + + // Port A inputs registered : indata, address, byeteena, wren + // Aclr status flags get updated here for M-RAM ram_block_type + + always @(posedge clock0) + begin + if ((!i_clocken0) && (operation_mode != "ROM")) + i_nmram_write_a <= 1'b0; + + if ((!i_clocken0) && (is_bidir_and_wrcontrol_addb_clk0)) + i_nmram_write_b <= 1'b0; + + if (i_clocken0) + begin + + // Port A inputs + + if (i_indata_aclr_a) + i_data_reg_a <= 0; + else + i_data_reg_a <= data_a; + + if (i_address_aclr_a) + i_address_reg_a <= 0; + else if (!addressstall_a) + i_address_reg_a <= address_a; + + if (i_byteena_aclr_a) + begin + i_byteena_mask_reg_a <= ~0; + i_byteena_mask_reg_a_out <= 0; + i_byteena_mask_reg_a_x <= 0; + end + else + begin + + if (width_byteena_a == 1) + begin + i_byteena_mask_reg_a <= {width_a{i_byteena_a[0]}}; + i_byteena_mask_reg_a_out <= (i_byteena_a[0])? {width_a{1'b0}} : {width_a{1'bx}}; + i_byteena_mask_reg_a_x <= ((i_byteena_a[0]) || (i_byteena_a[0] == 1'b0))? {width_a{1'b0}} : {width_a{1'bx}}; + end + else + for (k = 0; k < width_a; k = k+1) + begin + i_byteena_mask_reg_a[k] <= i_byteena_a[k/byte_size]; + i_byteena_mask_reg_a_out[k] <= (i_byteena_a[k/byte_size])? 1'b0: 1'bx; + i_byteena_mask_reg_a_x[k] <= ((i_byteena_a[k/byte_size]) || (i_byteena_a[k/byte_size] == 1'b0))? 1'b0: 1'bx; + end + + end + + if (i_wrcontrol_aclr_a) + i_wren_reg_a <= 0; + else + begin + i_wren_reg_a <= wren_a; + if (operation_mode != "ROM") + i_nmram_write_a <= 1'b1; + end + + + if (megaram_or_mram) + begin + if (wren_a) + i_write_flag_a <= ~ i_write_flag_a; + end + + good_to_go_a <= 1; + + i_read_flag_a <= ~ i_read_flag_a; + + end + + if (i_clocken0_b) + begin + + // Port B inputs + + if (indata_reg_b == "CLOCK0") + begin + if (i_indata_aclr_b) + i_data_reg_b <= 0; + else + i_data_reg_b <= data_b; + end + + + if (is_bidir_and_wrcontrol_addb_clk0) + begin + + if (i_wrcontrol_aclr_b) + i_wren_reg_b <= 0; + else + begin + i_wren_reg_b <= wren_b; + i_nmram_write_b <= 1'b1; + end + + if (i_address_aclr_b) + i_address_reg_b <= 0; + else if (!addressstall_b) + i_address_reg_b <= address_b; + + if (i_byteena_aclr_b) + begin + i_byteena_mask_reg_b <= ~0; + i_byteena_mask_reg_b_out <= 0; + i_byteena_mask_reg_b_x <= 0; + end + else + begin + + if (width_byteena_b == 1) + begin + i_byteena_mask_reg_b <= {width_b{i_byteena_b[0]}}; + i_byteena_mask_reg_b_out <= (i_byteena_b[0])? {width_b{1'b0}} : {width_b{1'bx}}; + i_byteena_mask_reg_b_x <= ((i_byteena_b[0]) || (i_byteena_b[0] == 1'b0))? {width_b{1'b0}} : {width_b{1'bx}}; + end + else + for (k2 = 0; k2 < width_b; k2 = k2 + 1) + begin + i_byteena_mask_reg_b[k2] <= i_byteena_b[k2/byte_size]; + i_byteena_mask_reg_b_out[k2] <= (i_byteena_b[k2/byte_size])? 1'b0 : 1'bx; + i_byteena_mask_reg_b_x[k2] <= ((i_byteena_b[k2/byte_size]) || (i_byteena_b[k2/byte_size] == 1'b0))? 1'b0 : 1'bx; + end + + end + + + if (megaram_or_mram) + begin + if (wren_b) + i_write_flag_b <= ~ i_write_flag_b; + end + i_read_flag_b <= ~i_read_flag_b; + good_to_go_b <= 1; + + end + else if (dual_port_addreg_b_clk0) + begin + if (i_rdcontrol_aclr_b) + i_rden_reg_b <= ~0; + else + i_rden_reg_b <= rden_b; + + if (i_address_aclr_b) + i_address_reg_b <= 0; + else if (!addressstall_b) + i_address_reg_b <= address_b; + + + i_read_flag_b <= ~i_read_flag_b; + good_to_go_b <= 1; + + end + end + + end + + + always @(negedge clock0) + begin + + if (!megaram_or_mram) + begin + if (i_nmram_write_a == 1'b1) + begin + i_write_flag_a <= ~ i_write_flag_a; + end + + + if (is_bidir_and_wrcontrol_addb_clk0) + begin + if (i_nmram_write_b == 1'b1) + i_write_flag_b <= ~ i_write_flag_b; + end + end + end + + + + always @(posedge clock1) + begin + + + if ((!i_clocken1) && (is_bidir_and_wrcontrol_addb_clk1)) + i_nmram_write_b <= 1'b0; + + if (i_clocken1) + begin + + // Port B inputs + + if (indata_reg_b == "CLOCK1") + begin + if (i_indata_aclr_b) + i_data_reg_b <= 0; + else + i_data_reg_b <= data_b; + end + + + if (is_bidir_and_wrcontrol_addb_clk1) + begin + if (i_wrcontrol_aclr_b) + i_wren_reg_b <= 0; + else + begin + i_wren_reg_b <= wren_b; + i_nmram_write_b <= 1'b1; + end + + if (i_address_aclr_b) + i_address_reg_b <= 0; + else if (!addressstall_b) + i_address_reg_b <= address_b; + + if (i_byteena_aclr_b) + begin + i_byteena_mask_reg_b <= ~0; + i_byteena_mask_reg_b_out <= 0; + i_byteena_mask_reg_b_x <= 0; + end + else + begin + if (width_byteena_b == 1) + begin + i_byteena_mask_reg_b <= {width_b{i_byteena_b[0]}}; + i_byteena_mask_reg_b_out <= (i_byteena_b[0])? {width_b{1'b0}} : {width_b{1'bx}}; + i_byteena_mask_reg_b_x <= ((i_byteena_b[0]) || (i_byteena_b[0] == 1'b0))? {width_b{1'b0}} : {width_b{1'bx}}; + end + else + for (k2 = 0; k2 < width_b; k2 = k2 + 1) + begin + i_byteena_mask_reg_b[k2] <= i_byteena_b[k2/byte_size]; + i_byteena_mask_reg_b_out[k2] <= (i_byteena_b[k2/byte_size])? 1'b0 : 1'bx; + i_byteena_mask_reg_b_x[k2] <= ((i_byteena_b[k2/byte_size]) || (i_byteena_b[k2/byte_size] == 1'b0))? 1'b0 : 1'bx; + end + + end + + + if (megaram_or_mram) + begin + if (wren_b) + i_write_flag_b <= ~ i_write_flag_b; + end + + i_read_flag_b <= ~i_read_flag_b; + good_to_go_b <= 1; + + end + else if (dual_port_addreg_b_clk1) + begin + + if (i_rdcontrol_aclr_b) + begin + i_rden_reg_b <= ~0; + end + else + begin + i_rden_reg_b <= rden_b; + end + + if (i_address_aclr_b) + i_address_reg_b <= 0; + else if (!addressstall_b) + i_address_reg_b <= address_b; + + i_read_flag_b <= ~i_read_flag_b; + good_to_go_b <= 1; + + end + end + end + + always @(negedge clock1) + begin + + if (!megaram_or_mram) + begin + + if (is_bidir_and_wrcontrol_addb_clk1) + begin + if (i_nmram_write_b == 1'b1) + i_write_flag_b <= ~ i_write_flag_b; + end + end + end + + + // Port A writting ------------------------------------------------------------- + + always @(posedge i_write_flag_a or negedge i_write_flag_a) + begin + if ((operation_mode == "BIDIR_DUAL_PORT") || + (operation_mode == "DUAL_PORT") || + (operation_mode == "SINGLE_PORT")) + begin + + if (i_wren_reg_a) + begin + if (i_indata_aclr_a) + begin + if (i_data_reg_a != 0) + begin + mem_data[i_address_reg_a] = {width_a{1'bx}}; + i_aclr_flag_a = 1; + end + end + else if (i_byteena_aclr_a) + begin + if (i_byteena_mask_reg_a != {width_a{1'b1}}) + begin + mem_data[i_address_reg_a] = {width_a{1'bx}}; + i_aclr_flag_a = 1; + end + end + else if (i_address_aclr_a) + begin + if (i_address_reg_a != 0) + begin + wa_mult_x_ii = {width_a{1'bx}}; + for (i4 = 0; i4 < i_numwords_a; i4 = i4 + 1) + mem_data[i4] = wa_mult_x_ii; + i_aclr_flag_a = 1; + end + end + + if (i_aclr_flag_a == 0) + begin + mem_data[i_address_reg_a] = ((i_data_reg_a & i_byteena_mask_reg_a) | + (mem_data[i_address_reg_a] & ~i_byteena_mask_reg_a)) ^ i_byteena_mask_reg_a_x; + end + + i_aclr_flag_a = 0; + + + end + end + end // Port A writting ---------------------------------------------------- + + + // Port B writting ----------------------------------------------------------- + + always @(posedge i_write_flag_b or negedge i_write_flag_b) + begin + if (operation_mode == "BIDIR_DUAL_PORT") + begin + + if (i_wren_reg_b) + begin + // RAM content is following width_a + // if Port B is of different width, need to make some adjustments + + if (i_indata_aclr_b) + begin + if (i_data_reg_b != 0) + begin + + if (width_a == width_b) + mem_data[i_address_reg_b] = {width_b{1'bx}}; + else + begin + j = i_address_reg_b * width_b; + for (i2 = 0; i2 < width_b; i2 = i2+1) + begin + j_plus_i2 = j + i2; + temp_wa = mem_data[j_plus_i2 / width_a]; + temp_wa[j_plus_i2 % width_a] = {1'bx}; + mem_data[j_plus_i2 / width_a] = temp_wa; + end + end + i_aclr_flag_b = 1; + end + end + else if (i_byteena_aclr_b) + begin + if (i_byteena_mask_reg_b != {width_b{1'b1}}) + begin + + if (width_a == width_b) + mem_data[i_address_reg_b] = {width_b{1'bx}}; + else + begin + j = i_address_reg_b * width_b; + for (i2 = 0; i2 < width_b; i2 = i2+1) + begin + j_plus_i2 = j + i2; + j_plus_i2_div_a = j_plus_i2 / width_a; + temp_wa = mem_data[j_plus_i2_div_a]; + temp_wa[j_plus_i2 % width_a] = {1'bx}; + mem_data[j_plus_i2_div_a] = temp_wa; + end + end + i_aclr_flag_b = 1; + end + end + else if (i_address_aclr_b) + begin + if (i_address_reg_b != 0) + begin + + wa_mult_x_iii = {width_a{1'bx}}; + for (i2 = 0; i2 < i_numwords_a; i2 = i2 + 1) + begin + mem_data[i2] = wa_mult_x_iii; + end + i_aclr_flag_b = 1; + end + end + + if (i_aclr_flag_b == 0) + begin + + if (width_a == width_b) + mem_data[i_address_reg_b] = ((i_data_reg_b & i_byteena_mask_reg_b) | + (mem_data[i_address_reg_b] & ~i_byteena_mask_reg_b)) ^ i_byteena_mask_reg_b_x; + else + begin + j = i_address_reg_b * width_b; + for (i2 = 0; i2 < width_b; i2 = i2+1) + begin + j_plus_i2 = j + i2; + j_plus_i2_div_a = j_plus_i2 / width_a; + temp_wa = mem_data[j_plus_i2_div_a]; + + temp_wa[j_plus_i2 % width_a] = ((i_data_reg_b[i2] & + i_byteena_mask_reg_b[i2]) | + (temp_wa[j_plus_i2 % width_a] & + ~i_byteena_mask_reg_b[i2])) ^ i_byteena_mask_reg_b_x[i2]; + mem_data[j_plus_i2_div_a] = temp_wa; + end + end + end + + i_aclr_flag_b = 0; + + end + + end + end + + + // Port A reading + + always @(posedge i_read_flag_a or negedge i_read_flag_a) + begin + if ((operation_mode == "BIDIR_DUAL_PORT") || + (operation_mode == "SINGLE_PORT") || + (operation_mode == "ROM")) + begin + if (~good_to_go_a) + begin + + if ((check_simultaneous_read_write) && (operation_mode != "ROM")) + i_q_tmp2_a = {width_a{1'bx}}; + else + i_q_tmp2_a = 0; + end + else + begin + // read from RAM content + i_q_tmp2_a = mem_data[i_address_reg_a]; + + if (is_bidir_and_wrcontrol_addb_clk0) + begin + + if (check_simultaneous_read_write) + + // B write, A read + if (i_wren_reg_b & ~i_wren_reg_a) + begin + add_reg_a_mult_wa = i_address_reg_a * width_a; + add_reg_b_mult_wb = i_address_reg_b * width_b; + add_reg_a_mult_wa_pl_wa = add_reg_a_mult_wa + width_a; + add_reg_b_mult_wb_pl_wb = add_reg_b_mult_wb + width_b; + + if ( + ((add_reg_a_mult_wa >= + add_reg_b_mult_wb) && + (add_reg_a_mult_wa <= + (add_reg_b_mult_wb_pl_wb - 1))) + + || + + (((add_reg_a_mult_wa_pl_wa - 1) >= + add_reg_b_mult_wb) && + ((add_reg_a_mult_wa_pl_wa - 1) <= + (add_reg_b_mult_wb_pl_wb - 1))) + ) + for (i3 = add_reg_a_mult_wa; + i3 < add_reg_a_mult_wa_pl_wa; + i3 = i3 + 1) + begin + if ((i3 >= add_reg_b_mult_wb) && + (i3 <= (add_reg_b_mult_wb_pl_wb - 1))) + begin + i_q_tmp2_a_idx = (i3 - add_reg_a_mult_wa); + i_q_tmp2_a[i_q_tmp2_a_idx] = 1'bx; + end + end + + end + end + end + end + end + + + // assigning the correct output values for i_q_tmp_a (non-registered output) + always @(i_q_tmp2_a or i_wren_reg_a or i_data_reg_a or + i_address_reg_a or i_byteena_mask_reg_a_out) + begin + + if (i_wren_reg_a) + begin + i_q_tmp_a <= i_data_reg_a ^ i_byteena_mask_reg_a_out; + + end + else + i_q_tmp_a <= i_q_tmp2_a; + + end + + + // Port A outdata output registered + always @(posedge i_outdata_clk_a or posedge i_outdata_aclr_a) + begin + if (i_outdata_aclr_a) + i_q_reg_a <= 0; + else if (i_outdata_clken_a) + i_q_reg_a <= i_q_tmp_a; + end + + + // Port A : assigning the correct output values for q_a + assign q_a = (operation_mode == "DUAL_PORT") ? + {width_a{1'b0}} : (((outdata_reg_a == "CLOCK0") || + (outdata_reg_a == "CLOCK1")) ? + i_q_reg_a : i_q_tmp_a); + + + // Port B reading + always @(posedge i_read_flag_b or negedge i_read_flag_b) + begin + if ((operation_mode == "BIDIR_DUAL_PORT") || + (operation_mode == "DUAL_PORT")) + begin + if (~good_to_go_b) + begin + + if (check_simultaneous_read_write) + i_q_tmp2_b = {width_b{1'bx}}; + else + i_q_tmp2_b = 0; + end + else + begin + if (i_rden_reg_b) + begin + //If width_a is equal to b, no address calculation is needed + if (width_a == width_b) + begin + if (check_simultaneous_read_write) + begin + if ((rdcontrol_reg_b == "CLOCK0") || + (wrcontrol_wraddress_reg_b == "CLOCK0")) + begin + // A write, B read + if (i_wren_reg_a & ~i_wren_reg_b) + begin + // if A write to the same Ram address B is reading from + if (i_address_reg_b == i_address_reg_a) + temp_wb = {width_b{1'bx}}; + else + temp_wb = mem_data[i_address_reg_b]; + + end + else + temp_wb = mem_data[i_address_reg_b]; + end + else + temp_wb = mem_data[i_address_reg_b]; + end + else + temp_wb = mem_data[i_address_reg_b]; + + end + else + begin + j2 = i_address_reg_b * width_b; + + if (check_simultaneous_read_write) + begin + if ((rdcontrol_reg_b == "CLOCK0") || + (wrcontrol_wraddress_reg_b == "CLOCK0")) + begin + // A write, B read + if (i_wren_reg_a & ~i_wren_reg_b) + begin + + for (i5=0; i5<width_b; i5=i5+1) + begin + j2_plus_i5 = j2 + i5; + j2_plus_i5_div_a = j2_plus_i5 / width_a; + temp_wa2b = mem_data[j2_plus_i5_div_a]; + // if A write to the same Ram address B is reading from + if (j2_plus_i5_div_a == i_address_reg_a) + temp_wa2b = {width_a{1'bx}}; + + temp_wb[i5] = temp_wa2b[j2_plus_i5 % width_a]; + end + end + else + for (i5=0; i5<width_b; i5=i5+1) + begin + j2_plus_i5 = j2 + i5; + temp_wa2b = mem_data[j2_plus_i5 / width_a]; + temp_wb[i5] = temp_wa2b[j2_plus_i5 % width_a]; + end + end + else + for (i5=0; i5<width_b; i5=i5+1) + begin + j2_plus_i5 = j2 + i5; + temp_wa2b = mem_data[j2_plus_i5 / width_a]; + temp_wb[i5] = temp_wa2b[j2_plus_i5 % width_a]; + end + end + else + begin + for (i5=0; i5<width_b; i5=i5+1) + begin + j2_plus_i5 = j2 + i5; + temp_wa2b = mem_data[j2_plus_i5 / width_a]; + temp_wb[i5] = temp_wa2b[j2_plus_i5 % width_a]; + end + end + + end + //end of width_a != width_b + + i_q_tmp2_b = temp_wb; + + end + end + end + end + + + // assigning the correct output values for i_q_tmp_b (non-registered output) + always @(i_q_tmp2_b or i_wren_reg_b or i_data_reg_b or + i_address_reg_b or i_byteena_mask_reg_b_out or i_rden_reg_b) + begin + + if (operation_mode == "BIDIR_DUAL_PORT") + begin + if (i_wren_reg_b) + begin + i_q_tmp_b <= i_data_reg_b ^ i_byteena_mask_reg_b_out; + + end + else + i_q_tmp_b <= i_q_tmp2_b; + end + else if (operation_mode == "DUAL_PORT") + begin + if (i_rden_reg_b) + i_q_tmp_b <= i_q_tmp2_b; + end + end + + + // Port B outdata output registered + always @(posedge i_outdata_clk_b or posedge i_outdata_aclr_b) + begin + if (i_outdata_aclr_b) + i_q_reg_b <= 0; + else if (i_outdata_clken_b) + i_q_reg_b <= i_q_tmp_b; + end + + + // Port B : assigning the correct output values for q_b + assign q_b = ((operation_mode == "SINGLE_PORT") || + (operation_mode == "ROM")) ? + {width_b{1'b0}} : (((outdata_reg_b == "CLOCK0") || + (outdata_reg_b == "CLOCK1")) ? + i_q_reg_b : i_q_tmp_b); + +endmodule // ALTSYNCRAM + +// END OF MODULE + +//-----------------------------------------------------------------------------+ +// 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. +// +// For Apex Families, +// Uses one embedded cell per data output bit for +// Embedded System Block (ESB): APEX 20K, APEX II, +// ARM-based Excalibur and Mercury devices or +// Embedded Array Block (EAB): ACEX 1K and FLEX 10KE family; +// +// However, in FLEX 6000, 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[]. +// +//-----------------------------------------------------------------------------+ + +`timescale 1 ps / 1 ps +`define DEV_APEX20KE "APEX20KE" +`define DEV_APEX20K "APEX20K" + +module alt3pram (wren, data, wraddress, inclock, inclocken, + rden_a, rden_b, rdaddress_a, rdaddress_b, + outclock, outclocken, aclr, qa, qb); + + // --------------------- + // PARAMETER DECLARATION + // --------------------- + + parameter width = 1; // data[], qa[] and qb[] + parameter widthad = 1; // rdaddress_a,rdaddress_b,wraddress + parameter numwords = 0; // words stored in memory + parameter lpm_file = "UNUSED"; // name of hex file + parameter lpm_hint = "USE_EAB=ON"; // non-LPM parameters (Altera) + parameter indata_reg = "UNREGISTERED";// clock used by data[] port + parameter indata_aclr = "ON"; // aclr affects data[]? + parameter write_reg = "UNREGISTERED";// clock used by wraddress & wren + parameter write_aclr = "ON"; // aclr affects wraddress? + parameter rdaddress_reg_a = "UNREGISTERED";// clock used by readdress_a + parameter rdaddress_aclr_a = "ON"; // aclr affects rdaddress_a? + parameter rdcontrol_reg_a = "UNREGISTERED";// clock used by rden_a + parameter rdcontrol_aclr_a = "ON"; // aclr affects rden_a? + parameter rdaddress_reg_b = "UNREGISTERED";// clock used by readdress_b + parameter rdaddress_aclr_b = "ON"; // aclr affects rdaddress_b? + parameter rdcontrol_reg_b = "UNREGISTERED";// clock used by rden_b + parameter rdcontrol_aclr_b = "ON"; // aclr affects rden_b? + parameter outdata_reg_a = "UNREGISTERED";// clock used by qa[] + parameter outdata_aclr_a = "ON"; // aclr affects qa[]? + parameter outdata_reg_b = "UNREGISTERED";// clock used by qb[] + parameter outdata_aclr_b = "ON"; // aclr affects qb[]? + parameter intended_device_family = `DEV_APEX20KE; + parameter ram_block_type = "AUTO"; // ram block type to be used + parameter maximum_depth = 0; // maximum segmented value of the RAM + parameter lpm_type = "alt3pram"; + + // ------------- + // 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. + parameter write_at_low_clock = ((write_reg == "INCLOCK") && + (lpm_hint == "USE_EAB=ON")) ? 1 : 0; + + // The read ports will not hold any value (zero) if rden is low. This + // behavior only apply to memory constructed using EAB/ESB, but not LCs. + parameter rden_low_output_0 = ((intended_device_family == `DEV_APEX20K) && + (lpm_hint == "USE_EAB=ON")) ? 1 : 0; + + // Local Parameter declaration to cater for Stratix II family specific for disabling aclr involved parameter + // to be coincide with megawizard option + parameter indata_aclr_int = (intended_device_family == "Stratix II") ? "OFF" : indata_aclr; + parameter write_aclr_int = (intended_device_family == "Stratix II") ? "OFF" : write_aclr; + parameter rdaddress_aclr_a_int = (intended_device_family == "Stratix II") ? "OFF" : rdaddress_aclr_a; + parameter rdcontrol_aclr_a_int = (intended_device_family == "Stratix II") ? "OFF" : rdcontrol_aclr_a; + parameter rdaddress_aclr_b_int = (intended_device_family == "Stratix II") ? "OFF" : rdaddress_aclr_b; + parameter rdcontrol_aclr_b_int = (intended_device_family == "Stratix II") ? "OFF" : rdcontrol_aclr_b; + + // ---------------- + // PORT DECLARATION + // ---------------- + + // data input ports + input [width-1:0] data; + + // control signals + input [widthad-1:0] wraddress; + input [widthad-1:0] rdaddress_a; + input [widthad-1:0] rdaddress_b; + + input wren; + input rden_a; + input rden_b; + + // clock ports + input inclock; + input outclock; + + // clock enable ports + input inclocken; + input outclocken; + + // clear ports + input aclr; + + // OUTPUT PORTS + output [width-1:0] qa; + output [width-1:0] qb; + + // --------------- + // REG DECLARATION + // --------------- + reg [width-1:0] mem_data [(1<<widthad)-1:0]; + wire [width-1:0] i_data_reg; + wire [width-1:0] i_data_tmp; + reg [width-1:0] i_qa_reg; + reg [width-1:0] i_qa_tmp; + reg [width-1:0] i_qb_reg; + reg [width-1:0] i_qb_tmp; + + wire [width-1:0] i_qa_stratix; // qa signal for Stratix families + wire [width-1:0] i_qb_stratix; // qa signal for Stratix families + + reg [width-1:0] i_data_hi; + reg [width-1:0] i_data_lo; + + wire [widthad-1:0] i_wraddress_reg; + wire [widthad-1:0] i_wraddress_tmp; + + reg [widthad-1:0] i_wraddress_hi; + reg [widthad-1:0] i_wraddress_lo; + + reg [widthad-1:0] i_rdaddress_reg_a; + reg [widthad-1:0] i_rdaddress_reg_a_dly; + wire [widthad-1:0] i_rdaddress_tmp_a; + + reg [widthad-1:0] i_rdaddress_reg_b; + reg [widthad-1:0] i_rdaddress_reg_b_dly; + wire [widthad-1:0] i_rdaddress_tmp_b; + + wire i_wren_reg; + wire i_wren_tmp; + reg i_rden_reg_a; + wire i_rden_tmp_a; + reg i_rden_reg_b; + wire i_rden_tmp_b; + + reg i_wren_hi; + reg i_wren_lo; + + reg [8*256:1] ram_initf; // max RAM size (Apex20KE) 8*256=2048 + + wire i_stratix_inclock; // inclock signal for Stratix families + wire i_stratix_outclock; // inclock signal for Stratix families + + wire i_apex_inclock; // inclock signal for non-Stratix families + wire i_apex_outclock; // inclock signal for non-Stratix families + + // ------------------- + // INTEGER DECLARATION + // ------------------- + integer i; + integer i_numwords; + integer new_data; + integer tmp_new_data; + + + // -------------------------------- + // Tri-State and Buffer DECLARATION + // -------------------------------- + tri0 inclock; + tri1 inclocken; + tri0 outclock; + tri1 outclocken; + tri0 wren; + tri1 rden_a; + tri1 rden_b; + tri0 aclr; + + // ------------------------ + // COMPONENT INSTANTIATIONS + // ------------------------ + ALTERA_DEVICE_FAMILIES dev (); + ALTERA_MF_MEMORY_INITIALIZATION mem (); + + // 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. + + altsyncram u0 ( + .wren_a(wren), + .wren_b(), + .rden_b(rden_a), + .data_a(data), + .data_b(), + .address_a(wraddress), + .address_b(rdaddress_a), + .clock0(i_stratix_inclock), + .clock1(i_stratix_outclock), + .clocken0(inclocken), + .clocken1(outclocken), + .aclr0(aclr), + .aclr1(), + .byteena_a(), + .byteena_b(), + .addressstall_a(), + .addressstall_b(), + .q_a(), + .q_b(i_qa_stratix)); + + defparam + u0.width_a = width, + u0.widthad_a = widthad, + u0.numwords_a = (numwords == 0) ? (1<<widthad) : numwords, + u0.address_aclr_a = (write_aclr_int == "ON") ? "CLEAR0" : "NONE", + u0.indata_aclr_a = (indata_aclr_int == "ON") ? "CLEAR0" : "NONE", + u0.wrcontrol_aclr_a = (write_aclr_int == "ON") ? "CLEAR0" : "NONE", + + u0.width_b = width, + u0.widthad_b = widthad, + u0.numwords_b = (numwords == 0) ? (1<<widthad) : numwords, + u0.rdcontrol_reg_b = (rdcontrol_reg_a == "INCLOCK") ? "CLOCK0" : + (rdcontrol_reg_a == "OUTCLOCK") ? "CLOCK1" : + "UNUSED", + u0.address_reg_b = (rdaddress_reg_a == "INCLOCK") ? "CLOCK0" : + (rdaddress_reg_a == "OUTCLOCK") ? "CLOCK1" : + "UNUSED", + u0.outdata_reg_b = (outdata_reg_a == "INCLOCK") ? "CLOCK0" : + (outdata_reg_a == "OUTCLOCK") ? "CLOCK1" : + "UNREGISTERED", + u0.outdata_aclr_b = (outdata_aclr_a == "ON") ? "CLEAR0" : "NONE", + u0.rdcontrol_aclr_b = (rdcontrol_aclr_a_int == "ON") ? "CLEAR0" : "NONE", + u0.address_aclr_b = (rdaddress_aclr_a_int == "ON") ? "CLEAR0" : "NONE", + + u0.operation_mode = "DUAL_PORT", + u0.read_during_write_mode_mixed_ports = (ram_block_type == "AUTO") ? "OLD_DATA" : + "DONT_CARE", + u0.ram_block_type = ram_block_type, + u0.init_file = lpm_file, + u0.init_file_layout = "PORT_B", + u0.maximum_depth = maximum_depth, + u0.intended_device_family = intended_device_family; + + altsyncram u1 ( + .wren_a(wren), + .wren_b(), + .rden_b(rden_b), + .data_a(data), + .data_b(), + .address_a(wraddress), + .address_b(rdaddress_b), + .clock0(i_stratix_inclock), + .clock1(i_stratix_outclock), + .clocken0(inclocken), + .clocken1(outclocken), + .aclr0(aclr), + .aclr1(aclr), + .byteena_a(), + .byteena_b(), + .addressstall_a(), + .addressstall_b(), + .q_a(), + .q_b(i_qb_stratix)); + + defparam + u1.width_a = width, + u1.widthad_a = widthad, + u1.numwords_a = numwords, + u1.address_aclr_a = (write_aclr_int == "ON") ? "CLEAR0" : "NONE", + u1.indata_aclr_a = (indata_aclr_int == "ON") ? "CLEAR0" : "NONE", + u1.wrcontrol_aclr_a = (write_aclr_int == "ON") ? "CLEAR0" : "NONE", + + u1.width_b = width, + u1.widthad_b = widthad, + u1.numwords_b = numwords, + u1.rdcontrol_reg_b = (rdcontrol_reg_b == "INCLOCK") ? "CLOCK0" : + (rdcontrol_reg_b == "OUTCLOCK") ? "CLOCK1" : + "UNUSED", + u1.address_reg_b = (rdaddress_reg_b == "INCLOCK") ? "CLOCK0" : + (rdaddress_reg_b == "OUTCLOCK") ? "CLOCK1" : + "UNUSED", + u1.outdata_reg_b = (outdata_reg_b == "INCLOCK") ? "CLOCK0" : + (outdata_reg_b == "OUTCLOCK") ? "CLOCK1" : + "UNREGISTERED", + u1.outdata_aclr_b = (outdata_aclr_b == "ON") ? "CLEAR0" : "NONE", + u1.rdcontrol_aclr_b = (rdcontrol_aclr_b_int == "ON") ? "CLEAR0" : "NONE", + u1.address_aclr_b = (rdaddress_aclr_b_int == "ON") ? "CLEAR0" : "NONE", + + u1.operation_mode = "DUAL_PORT", + u1.read_during_write_mode_mixed_ports = (ram_block_type == "AUTO") ? "OLD_DATA" : + "DONT_CARE", + u1.ram_block_type = ram_block_type, + u1.init_file = lpm_file, + u1.init_file_layout = "PORT_B", + u1.maximum_depth = maximum_depth, + u1.intended_device_family = intended_device_family; + + // ----------------------------------------------------------- + // Initialization block for all internal signals and registers + // ----------------------------------------------------------- + initial + begin + // Check for invalid parameters + if (width <= 0) + begin + $display("Error: width parameter must be greater than 0."); + $stop; + end + + if (widthad <= 0) + begin + $display("Error: widthad parameter must be greater than 0."); + $stop; + end + + // Initialize mem_data to '0' if no RAM init file is specified + i_numwords = (numwords) ? numwords : 1<<widthad; + if (lpm_file == "UNUSED") + if (write_reg == "UNREGISTERED") + for (i=0; i<i_numwords; i=i+1) + mem_data[i] = {width{1'bx}}; + else + for (i=0; i<i_numwords; i=i+1) + mem_data[i] = 0; + else + begin +`ifdef NO_PLI + $readmemh(lpm_file, mem_data); +`else + `ifdef USE_RIF + $readmemh(lpm_file, mem_data); + `else + mem.convert_hex2ver(lpm_file, width, ram_initf); + $readmemh(ram_initf, mem_data); + `endif +`endif + end + + // Initialize registers + i_data_hi = 0; + i_data_lo = 0; + i_rdaddress_reg_a = 0; + i_rdaddress_reg_b = 0; + i_rdaddress_reg_a_dly = 0; + i_rdaddress_reg_b_dly = 0; + i_qa_reg = 0; + i_qb_reg = 0; + + // Initialize integer + new_data = 0; + tmp_new_data = 0; + end + + // ------------------------ + // ALWAYS CONSTRUCT BLOCK + // ------------------------ + + // The following always blocks are used to implement the alt3pram behavior for + // device families other than Stratix/Stratix II/Stratix GX and Cyclone. + + //========= + // Clocks + //========= + + // 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 + always @(posedge i_apex_inclock) + begin + if (indata_reg == "INCLOCK") + begin + if ((aclr == 1) && (indata_aclr_int == "ON")) + i_data_hi <= 0; + else if (inclocken == 1) + i_data_hi <= data; + end + + if (write_reg == "INCLOCK") + begin + if ((aclr == 1) && (write_aclr_int == "ON")) + begin + i_wraddress_hi <= 0; + i_wren_hi <= 0; + end + else if (inclocken == 1) + begin + i_wraddress_hi <= wraddress; + i_wren_hi <= wren; + end + end + + if (rdaddress_reg_a == "INCLOCK") + begin + if ((aclr == 1) && (rdaddress_aclr_a_int == "ON")) + i_rdaddress_reg_a <= 0; + else if (inclocken == 1) + i_rdaddress_reg_a <= rdaddress_a; + end + + if (rdcontrol_reg_a == "INCLOCK") + begin + if ((aclr == 1) && (rdcontrol_aclr_a_int == "ON")) + i_rden_reg_a <= 0; + else if (inclocken == 1) + i_rden_reg_a <= rden_a; + end + + if (rdaddress_reg_b == "INCLOCK") + begin + if ((aclr == 1) && (rdaddress_aclr_b_int == "ON")) + i_rdaddress_reg_b <= 0; + else if (inclocken == 1) + i_rdaddress_reg_b <= rdaddress_b; + end + + if (rdcontrol_reg_b == "INCLOCK") + begin + if ((aclr == 1) && (rdcontrol_aclr_b_int == "ON")) + i_rden_reg_b <= 0; + else if (inclocken == 1) + i_rden_reg_b <= rden_b; + end + end // End of always block: @(posedge inclock) + + + // 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. + always @(negedge i_apex_inclock) + begin + if (indata_reg == "INCLOCK") + begin + if ((aclr == 1) && (indata_aclr_int == "ON")) + i_data_lo <= 0; + else + i_data_lo <= i_data_hi; + end + + if (write_reg == "INCLOCK") + begin + if ((aclr == 1) && (write_aclr_int == "ON")) + begin + i_wraddress_lo <= 0; + i_wren_lo <= 0; + end + else + begin + i_wraddress_lo <= i_wraddress_hi; + i_wren_lo <= i_wren_hi; + end + end + end // End of always block: @(negedge inclock) + + + // 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. + always @(posedge i_apex_outclock) + begin + if (outdata_reg_a == "OUTCLOCK") + begin + if ((aclr == 1) && (outdata_aclr_a == "ON")) + i_qa_reg <= 0; + else if (outclocken == 1) + i_qa_reg <= i_qa_tmp; + end + + if (outdata_reg_b == "OUTCLOCK") + begin + if ((aclr == 1) && (outdata_aclr_b == "ON")) + i_qb_reg <= 0; + else if (outclocken == 1) + i_qb_reg <= i_qb_tmp; + end + + if (rdaddress_reg_a == "OUTCLOCK") + begin + if ((aclr == 1) && (rdaddress_aclr_a_int == "ON")) + i_rdaddress_reg_a <= 0; + else if (outclocken == 1) + i_rdaddress_reg_a <= rdaddress_a; + end + + if (rdcontrol_reg_a == "OUTCLOCK") + begin + if ((aclr == 1) && (rdcontrol_aclr_a_int == "ON")) + i_rden_reg_a <= 0; + else if (outclocken == 1) + i_rden_reg_a <= rden_a; + end + + if (rdaddress_reg_b == "OUTCLOCK") + begin + if ((aclr == 1) && (rdaddress_aclr_b_int == "ON")) + i_rdaddress_reg_b <= 0; + else if (outclocken == 1) + i_rdaddress_reg_b <= rdaddress_b; + end + + if (rdcontrol_reg_b == "OUTCLOCK") + begin + if ((aclr == 1) && (rdcontrol_aclr_b_int == "ON")) + i_rden_reg_b <= 0; + else if (outclocken == 1) + i_rden_reg_b <= rden_b; + end + end // End of always block: @(posedge outclock) + + always @(i_rdaddress_reg_a) + begin + i_rdaddress_reg_a_dly <= i_rdaddress_reg_a; + end + + always @(i_rdaddress_reg_b) + begin + i_rdaddress_reg_b_dly <= i_rdaddress_reg_b; + end + + //========= + // Memory + //========= + + always @(i_data_tmp or i_wren_tmp or i_wraddress_tmp) + begin + new_data <= 1; + end + + always @(posedge new_data or negedge new_data) + begin + if (new_data == 1) + begin + // + // This is where data is being write to the internal memory: mem_data[] + // + if (i_wren_tmp == 1) + begin + mem_data[i_wraddress_tmp] <= i_data_tmp; + end + + tmp_new_data <= ~tmp_new_data; + + end + end + + always @(tmp_new_data) + begin + + new_data <= 0; + end + + // 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 (i_qa_tmp or i_qb_tmp) + // Note: i_q*_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 i_q*_tmp will need to be latched to i_q*_reg + // through outclock before it is fed to the output port q* (qa or qb). + + always @(posedge new_data or negedge new_data or + posedge i_rden_tmp_a or negedge i_rden_tmp_a or + i_rdaddress_tmp_a) + begin + + if (i_rden_tmp_a == 1) + i_qa_tmp <= mem_data[i_rdaddress_tmp_a]; + else if (rden_low_output_0 == 1) + i_qa_tmp <= 0; + + end + + always @(posedge new_data or negedge new_data or + posedge i_rden_tmp_b or negedge i_rden_tmp_b or + i_rdaddress_tmp_b) + begin + + if (i_rden_tmp_b == 1) + i_qb_tmp <= mem_data[i_rdaddress_tmp_b]; + else if (rden_low_output_0 == 1) + i_qb_tmp <= 0; + + end + + + //======= + // Sync + //======= + + assign i_wraddress_reg = ((aclr == 1) && (write_aclr_int == "ON")) ? + 0 : (write_at_low_clock ? + i_wraddress_lo : i_wraddress_hi); + + assign i_wren_reg = ((aclr == 1) && (write_aclr_int == "ON")) ? + 0 : ((write_at_low_clock) ? + i_wren_lo : i_wren_hi); + + assign i_data_reg = ((aclr == 1) && (indata_aclr_int == "ON")) ? + 0 : ((write_at_low_clock) ? + i_data_lo : i_data_hi); + + assign i_wraddress_tmp = ((aclr == 1) && (write_aclr_int == "ON")) ? + 0 : ((write_reg == "INCLOCK") ? + i_wraddress_reg : wraddress); + + assign i_rdaddress_tmp_a = ((aclr == 1) && (rdaddress_aclr_a_int == "ON")) ? + 0 : (((rdaddress_reg_a == "INCLOCK") || + (rdaddress_reg_a == "OUTCLOCK")) ? + i_rdaddress_reg_a_dly : rdaddress_a); + + assign i_rdaddress_tmp_b = ((aclr == 1) && (rdaddress_aclr_b_int == "ON")) ? + 0 : (((rdaddress_reg_b == "INCLOCK") || + (rdaddress_reg_b == "OUTCLOCK")) ? + i_rdaddress_reg_b_dly : rdaddress_b); + + assign i_wren_tmp = ((aclr == 1) && (write_aclr_int == "ON")) ? + 0 : ((write_reg == "INCLOCK") ? + i_wren_reg : wren); + + assign i_rden_tmp_a = ((aclr == 1) && (rdcontrol_aclr_a_int == "ON")) ? + 0 : (((rdcontrol_reg_a == "INCLOCK") || + (rdcontrol_reg_a == "OUTCLOCK")) ? + i_rden_reg_a : rden_a); + + assign i_rden_tmp_b = ((aclr == 1) && (rdcontrol_aclr_b_int == "ON")) ? + 0 : (((rdcontrol_reg_b == "INCLOCK") || + (rdcontrol_reg_b == "OUTCLOCK")) ? + i_rden_reg_b : rden_b); + + assign i_data_tmp = ((aclr == 1) && (indata_aclr_int == "ON")) ? + 0 : ((indata_reg == "INCLOCK") ? + i_data_reg : data); + + assign qa = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 1) || + (dev.IS_FAMILY_STRATIXII(intended_device_family) == 1) || + (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 1) || + (dev.IS_FAMILY_CYCLONE(intended_device_family) == 1)) ? + i_qa_stratix : + (((aclr == 1) && (outdata_aclr_a == "ON")) ? + 0 : ((outdata_reg_a == "OUTCLOCK") ? + i_qa_reg : i_qa_tmp)); + + assign qb = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 1) || + (dev.IS_FAMILY_STRATIXII(intended_device_family) == 1) || + (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 1) || + (dev.IS_FAMILY_CYCLONE(intended_device_family) == 1)) ? + i_qb_stratix : + (((aclr == 1) && (outdata_aclr_b == "ON")) ? + 0 : ((outdata_reg_b == "OUTCLOCK") ? + i_qb_reg : i_qb_tmp)); + + assign i_apex_inclock = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 0) && + (dev.IS_FAMILY_STRATIXII(intended_device_family) == 0) && + (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 0) && + (dev.IS_FAMILY_CYCLONE(intended_device_family) == 0)) ? + inclock : 1'b0; + + assign i_apex_outclock = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 0) && + (dev.IS_FAMILY_STRATIXII(intended_device_family) == 0) && + (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 0) && + (dev.IS_FAMILY_CYCLONE(intended_device_family) == 0)) ? + outclock : 1'b0; + + assign i_stratix_inclock = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 1) || + (dev.IS_FAMILY_STRATIXII(intended_device_family) == 1) || + (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 1) || + (dev.IS_FAMILY_CYCLONE(intended_device_family) == 1)) ? + inclock : 1'b0; + + assign i_stratix_outclock = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 1) || + (dev.IS_FAMILY_STRATIXII(intended_device_family) == 1) || + (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 1) || + (dev.IS_FAMILY_CYCLONE(intended_device_family) == 1)) ? + outclock : 1'b0; + + +endmodule // end of ALT3PRAM + +// START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : ALTQPRAM +// +// Description : Asynchronous quad ports memory or memory with synchronous +// inputs and/or outputs +// +// Limitation : +// +// Results expected : [Synchronous Write to Memory (all inputs registered)] +// inclock inclocken wren Function +// X L L No change +// not H H No change +// posedge L X No change +// posedge H H Memory content updated +// +// [Synchronous Read from Memory] +// inclock inclocken rden Function +// X L L No change +// not H H No change +// posedge L X No change. +// posedge H H Memory content showed +// at the output port +// +// [Asynchronous Memory Operations] +// wren Function +// L No change +// H Memory content updated +// Memory content showed +// at the output port +// +// END_MODULE_NAME-------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +// BEGINNING OF MODULE + +// MODULE DECLARATION + +module altqpram ( + wren_a, + wren_b, + data_a, + data_b, + wraddress_a, + wraddress_b, + inclock_a, + inclock_b, + inclocken_a, + inclocken_b, + rden_a, + rden_b, + rdaddress_a, + rdaddress_b, + outclock_a, + outclock_b, + outclocken_a, + outclocken_b, + inaclr_a, + inaclr_b, + outaclr_a, + outaclr_b, + q_a, + q_b + ); + +// GLOBAL PARAMETER DECLARATION + + parameter operation_mode = "QUAD_PORT"; + + // Port A write parameters + parameter width_write_a = 1; + parameter widthad_write_a = 1; + parameter numwords_write_a = 0; + parameter indata_reg_a = "INCLOCK_A"; + parameter indata_aclr_a = "INACLR_A"; + parameter wrcontrol_wraddress_reg_a = "INCLOCK_A"; + parameter wrcontrol_aclr_a = "INACLR_A"; + parameter wraddress_aclr_a = "INACLR_A"; + + // Port B write parameters + parameter width_write_b = 1; + parameter widthad_write_b = 1; + parameter numwords_write_b = 0; + parameter indata_reg_b = "INCLOCK_B"; + parameter indata_aclr_b = "INACLR_B"; + parameter wrcontrol_wraddress_reg_b = "INCLOCK_B"; + parameter wrcontrol_aclr_b = "INACLR_B"; + parameter wraddress_aclr_b = "INACLR_B"; + + // Port A read parameters + parameter width_read_a = 1; + parameter widthad_read_a = 1; + parameter numwords_read_a = 0; + parameter rdcontrol_reg_a = "OUTCLOCK_A"; + parameter rdcontrol_aclr_a = "OUTACLR_A"; + parameter rdaddress_reg_a = "OUTCLOCK_A"; + parameter rdaddress_aclr_a = "OUTACLR_A"; + parameter outdata_reg_a = "UNREGISTERED"; + parameter outdata_aclr_a = "OUTACLR_A"; + + // Port B read parameters + parameter width_read_b = 1; + parameter widthad_read_b = 1; + parameter numwords_read_b = 0; + parameter rdcontrol_reg_b = "OUTCLOCK_B"; + parameter rdcontrol_aclr_b = "OUTACLR_B"; + parameter rdaddress_reg_b = "OUTCLOCK_B"; + parameter rdaddress_aclr_b = "OUTACLR_B"; + parameter outdata_reg_b = "UNREGISTERED"; + parameter outdata_aclr_b = "OUTACLR_B"; + + parameter init_file = "UNUSED"; + parameter lpm_hint = "UNUSED"; + parameter lpm_type = "altqpram"; + +// INPUT PORT DECLARATION + + input wren_a; + input wren_b; + input rden_a; + input rden_b; + input [width_write_a - 1 : 0] data_a; + input [width_write_b - 1 : 0] data_b; + input [widthad_write_a - 1 : 0] wraddress_a; + input [widthad_write_b - 1 : 0] wraddress_b; + input inclock_a; + input inclock_b; + input inclocken_a; + input inclocken_b; + input [widthad_read_a - 1 : 0] rdaddress_a; + input [widthad_read_b - 1 : 0] rdaddress_b; + input outclock_a; + input outclock_b; + input outclocken_a; + input outclocken_b; + input inaclr_a; + input inaclr_b; + input outaclr_a; + input outaclr_b; + +// OUTPUT PORT DECLARATION + + output [width_read_a - 1 : 0] q_a; + output [width_read_b - 1 : 0] q_b; + +// INTERNAL REGISTERS DECLARATION + + reg [width_read_a - 1 : 0] mem_data [0 : (1 << widthad_read_a) - 1]; + reg [width_write_a - 1 : 0] mem_data_w [0 : (1 << widthad_write_a) - 1]; + reg [width_write_a - 1 : 0] i_data_reg_a; + reg [width_write_a - 1 : 0] i_data_tmp_a; + reg [width_write_a - 1 : 0] i_data2_a; + reg [width_write_a - 1 : 0] temp_wa; + reg [width_write_a - 1 : 0] temp_wa2; + reg [width_write_a - 1 : 0] temp_wa3; + reg [width_write_b - 1 : 0] i_data_reg_b; + reg [width_write_b - 1 : 0] i_data_tmp_b; + reg [width_write_b - 1 : 0] i_data2_b; + reg [width_write_a - 1 : 0] i_data_hi_a; + reg [width_write_a - 1 : 0] i_data_lo_a; + reg [width_write_b - 1 : 0] i_data_hi_b; + reg [width_write_b - 1 : 0] i_data_lo_b; + reg [width_read_a - 1 : 0] i_q_reg_a; + reg [width_read_a - 1 : 0] i_q_tmp_a; + reg [width_read_a - 1 : 0] temp_ra; + reg [width_read_a - 1 : 0] temp_ra2; + reg [width_read_a - 1 : 0] temp_ra3; + reg [width_read_a - 1 : 0] temp_ra4; + reg [width_read_b - 1 : 0] i_q_reg_b; + reg [width_read_b - 1 : 0] i_q_tmp_b; + reg [widthad_write_a - 1 : 0] i_wraddress_reg_a; + reg [widthad_write_a - 1 : 0] i_wraddress_tmp_a; + reg [widthad_write_a - 1 : 0] i_wraddress2_a; + reg [widthad_write_b - 1 : 0] i_wraddress_reg_b; + reg [widthad_write_b - 1 : 0] i_wraddress_tmp_b; + reg [widthad_write_b - 1 : 0] i_wraddress2_b; + reg [widthad_write_a - 1 : 0] i_wraddress_hi_a; + reg [widthad_write_a - 1 : 0] i_wraddress_lo_a; + reg [widthad_write_b - 1 : 0] i_wraddress_hi_b; + reg [widthad_write_b - 1 : 0] i_wraddress_lo_b; + reg [widthad_read_a - 1 : 0] i_rdaddress_reg_a; + reg [widthad_read_a - 1 : 0] i_rdaddress_tmp_a; + reg [widthad_read_b - 1 : 0] i_rdaddress_reg_b; + reg [widthad_read_b - 1 : 0] i_rdaddress_tmp_b; + reg [8*256 : 1] ram_initf; + reg i_wren_reg_a; + reg i_wren_tmp_a; + reg i_wren2_a; + reg i_rden_reg_a; + reg i_rden_tmp_a; + reg i_wren_reg_b; + reg i_wren_tmp_b; + reg i_wren2_b; + reg i_rden_reg_b; + reg i_rden_tmp_b; + reg i_wren_hi_a; + reg i_wren_lo_a; + reg i_wren_hi_b; + reg i_wren_lo_b; + reg mem_updated; + reg clk_a_trigger; + reg clk_b_trigger; + reg write_at_low_clock_a; + reg write_at_low_clock_b; + + + wire i_indata_aclr_a; + wire i_wraddress_aclr_a; + wire i_wrcontrol_aclr_a; + wire i_outdata_aclr_a; + wire i_rdaddress_aclr_a; + wire i_rdcontrol_aclr_a; + wire i_indata_aclr_b; + wire i_wraddress_aclr_b; + wire i_wrcontrol_aclr_b; + wire i_outdata_aclr_b; + wire i_rdaddress_aclr_b; + wire i_rdcontrol_aclr_b; + + +// LOCAL INTEGER DECLARATION + + integer i_numwords_read_a; + integer i_numwords_read_b; + integer i_numwords_write_a; + integer i_numwords_write_b; + integer write_ratio; + integer read_ratio; + integer read_write_ratio; + integer i; + integer i2; + integer i3; + integer i4; + integer j; + integer j2; + integer j3; + integer j4; + + integer ja; + integer jb; + integer Pa; + integer Pa1; + integer Pa2; + integer Pb; + integer Pb1; + integer Pb2; + + integer simultaneous_write; + +// INTERNAL TRI DECLARATION + + tri0 wren_a; + tri0 wren_b; + tri1 rden_a; + tri1 rden_b; + tri0 inclock_a; + tri0 inclock_b; + tri0 outclock_a; + tri0 outclock_b; + tri1 inclocken_a; + tri1 inclocken_b; + tri1 outclocken_a; + tri1 outclocken_b; + tri0 inaclr_a; + tri0 inaclr_b; + tri0 outaclr_a; + tri0 outaclr_b; + +// INTERNAL WIRE + + wire i_wren_a; + wire i_wren_b; + wire i_rden_a; + wire i_rden_b; + wire i_inclock_a; + wire i_inclock_b; + wire i_inclocken_a; + wire i_inclocken_b; + wire i_outclock_a; + wire i_outclock_b; + wire i_outclocken_a; + wire i_outclocken_b; + wire i_inaclr_a; + wire i_inaclr_b; + wire i_outaclr_a; + wire i_outaclr_b; + +// INTERNAL BUF + + buf (i_wren_a, wren_a); + buf (i_wren_b, wren_b); + buf (i_rden_a, rden_a); + buf (i_rden_b, rden_b); + buf (i_inclock_a, inclock_a); + buf (i_inclock_b, inclock_b); + buf (i_inclocken_a, inclocken_a); + buf (i_inclocken_b, inclocken_b); + buf (i_outclock_a, outclock_a); + buf (i_outclock_b, outclock_b); + buf (i_outclocken_a, outclocken_a); + buf (i_outclocken_b, outclocken_b); + buf (i_inaclr_a, inaclr_a); + buf (i_inaclr_b, inaclr_b); + buf (i_outaclr_a, outaclr_a); + buf (i_outaclr_b, outaclr_b); + + +// COMPONENT INSTANTIATIONS + ALTERA_MF_MEMORY_INITIALIZATION mem (); + +// INITIAL CONSTRUCT BLOCK + + initial + begin + + // Check for invalid parameters + + if ((operation_mode != "QUAD_PORT") && (operation_mode != "BIDIR_DUAL_PORT") && + (operation_mode != "DUAL_PORT") && (operation_mode != "SINGLE_PORT") && + (operation_mode != "ROM")) + begin + $display("Error! operation_mode parameter is invalid."); + $stop; + end + + if ((width_write_a <= 0) && (operation_mode != "ROM")) + begin + $display("Error! width_write_a parameter must be greater than 0."); + $stop; + end + + if ((width_write_b <= 0) && ((operation_mode == "QUAD_PORT") || (operation_mode == "BIDIR_DUAL_PORT"))) + begin + $display("Error! width_write_b parameter must be greater than 0."); + $stop; + end + + if ((widthad_write_a <= 0) && (operation_mode != "ROM")) + begin + $display("Error! widthad_write_a parameter must be greater than 0."); + $stop; + end + + if ((widthad_write_b <= 0) && ((operation_mode == "QUAD_PORT") || (operation_mode == "BIDIR_DUAL_PORT"))) + begin + $display("Error! widthad_write_b parameter must be greater than 0."); + $stop; + end + + if ((width_read_a <= 0) && ((operation_mode == "QUAD_PORT") || (operation_mode == "DUAL_PORT"))) + begin + $display("Error! width_read_a parameter must be greater than 0."); + $stop; + end + + if ((width_read_b <= 0) && (operation_mode == "QUAD_PORT")) + begin + $display("Error! width_read_b parameter must be greater than 0."); + $stop; + end + + if ((widthad_read_a <= 0) && ((operation_mode == "QUAD_PORT") || (operation_mode == "DUAL_PORT"))) + begin + $display("Error! widthad_read_a parameter must be greater than 0."); + $stop; + end + + if ((widthad_read_b <= 0) && (operation_mode == "QUAD_PORT")) + begin + $display("Error! widthad_read_b parameter must be greater than 0."); + $stop; + end + + if (((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "SINGLE_PORT")) && (width_read_a != width_write_a)) + begin + $display("Error! width_read_a must equal width_write_a."); + $stop; + end + + if ((operation_mode == "BIDIR_DUAL_PORT") && (width_read_b != width_write_b)) + begin + $display("Error! width_read_b must equal width_write_b."); + $stop; + end + + i_numwords_read_a = (numwords_read_a) ? numwords_read_a : (1 << widthad_read_a); + i_numwords_read_b = (numwords_read_b) ? numwords_read_b : (1 << widthad_read_b); + i_numwords_write_a =(numwords_write_a) ? + numwords_write_a : (1 << widthad_write_a); + i_numwords_write_b =(numwords_write_b) ? + numwords_write_b : (1 << widthad_write_b); + + if ((width_read_a*i_numwords_read_a != width_write_a*i_numwords_write_a) && + ((operation_mode == "QUAD_PORT") || (operation_mode == "DUAL_PORT"))) + begin + $display("Error! RAM size for port A is inconsistant."); + $stop; + end + + if ((operation_mode == "QUAD_PORT") || (operation_mode == "BIDIR_DUAL_PORT")) + begin + if ((width_read_b * i_numwords_read_b) != (width_write_b * i_numwords_write_b)) + begin + $display("Error! RAM size for port B is inconsistant."); + $stop; + end + + if (width_read_a*i_numwords_read_a != width_read_b*i_numwords_read_b) + begin + $display("Error! RAM size between port A and port B is inconsistant."); + $stop; + end + end + + read_ratio = (width_read_a > width_read_b) ? + (width_read_a / width_read_b) + : (width_read_b / width_read_a); + write_ratio = (width_write_a > width_write_b) ? + (width_write_a / width_write_b) + : (width_write_b / width_write_a); + read_write_ratio = (width_read_a > width_write_a) ? + (width_read_a / width_write_a) + : (width_write_a / width_read_a); + + // reset unused ratios to avoid incorrect checking + if ((operation_mode != "QUAD_PORT") || (operation_mode != "BIDIR_DUAL_MODE")) + begin + read_ratio = 1; + write_ratio = 1; + end + + if (((read_ratio != 1) && (read_ratio != 2) && (read_ratio != 4) && + (read_ratio != 8) && (read_ratio != 16)) || + ((write_ratio != 1) && (write_ratio != 2) && (write_ratio != 4) && + (write_ratio != 8) && (write_ratio != 16)) || + ((read_write_ratio != 1) && (read_write_ratio != 2) && + (read_write_ratio != 4) && (read_write_ratio != 8) && + (read_write_ratio != 16))) + begin + $display("Error! RAM size for port A and / or port B is invalid."); + $stop; + end + + // Initialize mem_data + if ((init_file == "UNUSED") || (init_file == "")) + begin + if (operation_mode == "ROM") + begin + $display("Error! altqpram needs data file for memory initialization.\n"); + $stop; + end + else if ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "SINGLE_PORT")) + for (i = 0; i < i_numwords_write_a; i = i + 1) + mem_data_w[i] = 0; + else // if QP or DP mode + for (i = 0; i < i_numwords_read_a; i = i + 1) + mem_data[i] = 0; + end + else + begin + if ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "SINGLE_PORT")) + begin +`ifdef NO_PLI + $readmemh(init_file, mem_data_w); +`else + `ifdef USE_RIF + $readmemh(init_file, mem_data_w); + `else + mem.convert_hex2ver(init_file, width_write_a, ram_initf); + $readmemh(ram_initf, mem_data_w); + `endif +`endif + end + else // if ROM, QP or DP mode + begin +`ifdef NO_PLI + $readmemh(init_file, mem_data); +`else + `ifdef USE_RIF + $readmemh(init_file, mem_data); + `else + mem.convert_hex2ver(init_file, width_read_a, ram_initf); + $readmemh(ram_initf, mem_data); + `endif +`endif + end + end + + mem_updated <= 0; + write_at_low_clock_a <= (wrcontrol_wraddress_reg_a != "UNREGISTERED") ? + 1 : 0; + write_at_low_clock_b <= (wrcontrol_wraddress_reg_b != "UNREGISTERED") ? + 1 : 0; + + // Initialize registers + i_data_reg_a <= 0; + i_data_tmp_a <= 0; + i_data_reg_b <= 0; + i_data_tmp_b <= 0; + i_data_hi_a <= 0; + i_data_lo_a <= 0; + i_data_hi_b <= 0; + i_data_lo_b <= 0; + i_wraddress_reg_a <= 0; + i_wraddress_tmp_a <= 0; + i_wraddress_reg_b <= 0; + i_wraddress_tmp_b <= 0; + i_wraddress_reg_b <= 0; + i_wraddress_tmp_b <= 0; + i_wraddress_hi_a <= 0; + i_wraddress_lo_a <= 0; + i_wraddress_hi_b <= 0; + i_wraddress_lo_b <= 0; + i_rdaddress_reg_a <= 0; + i_rdaddress_tmp_a <= 0; + i_rdaddress_reg_b <= 0; + i_rdaddress_tmp_b <= 0; + i_wren_reg_a <= 0; + i_wren_tmp_a <= 0; + i_wren_hi_a <= 0; + i_wren_lo_a <= 0; + i_rden_reg_a <= 0; + i_rden_tmp_a <= 0; + i_wren_reg_b <= 0; + i_wren_tmp_b <= 0; + i_wren_hi_b <= 0; + i_wren_lo_b <= 0; + i_rden_reg_b <= 0; + i_rden_tmp_b <= 0; + i_q_reg_a <= 0; + i_q_tmp_a <= 0; + i_q_reg_b <= 0; + i_q_tmp_b <= 0; + + i_data2_a <= 0; + i_wren2_a <= 0; + i_wraddress2_a <= 0; + i_data2_b <= 0; + i_wren2_b <= 0; + i_wraddress2_b <= 0; + clk_a_trigger <= 0; + clk_b_trigger <= 0; + end + + + assign i_indata_aclr_a = (indata_aclr_a == "INACLR_A") ? + i_inaclr_a : 0; + + assign i_wraddress_aclr_a = (wraddress_aclr_a == "INACLR_A") ? + i_inaclr_a : 0; + + assign i_wrcontrol_aclr_a = (wrcontrol_aclr_a == "INACLR_A") ? + i_inaclr_a : 0; + + assign i_outdata_aclr_a = ((outdata_aclr_a == "INACLR_A") ? i_inaclr_a : + ((outdata_aclr_a == "OUTACLR_A") ? i_outaclr_a : 0)); + + assign i_rdaddress_aclr_a = ((rdaddress_aclr_a == "INACLR_A") ? i_inaclr_a : + ((rdaddress_aclr_a == "OUTACLR_A") ? i_outaclr_a : 0)); + + assign i_rdcontrol_aclr_a = ((rdcontrol_aclr_a == "INACLR_A") ? i_inaclr_a : + ((rdcontrol_aclr_a == "OUTACLR_A") ? i_outaclr_a : 0)); + + assign i_indata_aclr_b = (indata_aclr_b == "INACLR_B") ? + i_inaclr_b : 0; + + assign i_wraddress_aclr_b = (wraddress_aclr_b == "INACLR_B") ? + i_inaclr_b : 0; + + assign i_wrcontrol_aclr_b = (wrcontrol_aclr_b == "INACLR_B") ? + i_inaclr_b : 0; + + assign i_outdata_aclr_b = ((outdata_aclr_b == "INACLR_B") ? i_inaclr_b : + ((outdata_aclr_b == "OUTACLR_B") ? i_outaclr_b : 0)); + + assign i_rdaddress_aclr_b = ((rdaddress_aclr_b == "INACLR_B") ? i_inaclr_b : + ((rdaddress_aclr_b == "OUTACLR_B") ? i_outaclr_b : 0)); + + assign i_rdcontrol_aclr_b = ((rdcontrol_aclr_b == "INACLR_B") ? i_inaclr_b : + ((rdcontrol_aclr_b == "OUTACLR_B") ? i_outaclr_b : 0)); + + + + // This always block is to handle registered inputs and output for port A + always @(posedge i_inclock_a) + begin + if (i_indata_aclr_a === 1) + i_data_hi_a <= 0; + else if (i_inclocken_a == 1) + i_data_hi_a <= data_a; + + if (i_wraddress_aclr_a === 1) + i_wraddress_hi_a <= 0; + else if (i_inclocken_a == 1) + i_wraddress_hi_a <= wraddress_a; + + if (i_wrcontrol_aclr_a === 1) + i_wren_hi_a <= 0; + else if (i_inclocken_a == 1) + i_wren_hi_a <= i_wren_a; + + if (outdata_reg_a == "INCLOCK_A") + begin + if (i_outdata_aclr_a === 1) + i_q_reg_a <= 0; + else if (i_inclocken_a == 1) + i_q_reg_a <= i_q_tmp_a; + end + + if (rdaddress_reg_a == "INCLOCK_A") + begin + if (i_rdaddress_aclr_a === 1) + i_rdaddress_reg_a <= 0; + else if (i_inclocken_a == 1) + i_rdaddress_reg_a <= rdaddress_a; + end + + if (rdcontrol_reg_a == "INCLOCK_A") + begin + if (i_rdcontrol_aclr_a === 1) + i_rden_reg_a <= 0; + else if (i_inclocken_a == 1) + i_rden_reg_a <= i_rden_a; + end + end + + // This always block is to handle registered inputs and output for port B + always @(posedge i_inclock_b) + begin + if (i_indata_aclr_b === 1) + i_data_hi_b <= 0; + else if (i_inclocken_b == 1) + i_data_hi_b <= data_b; + + if (i_wraddress_aclr_b === 1) + i_wraddress_hi_b <= 0; + else if (i_inclocken_b == 1) + i_wraddress_hi_b <= wraddress_b; + + if (i_wrcontrol_aclr_b === 1) + i_wren_hi_b <= 0; + else if (i_inclocken_b == 1) + i_wren_hi_b <= i_wren_b; + + if (outdata_reg_b == "INCLOCK_B") + begin + if (i_outdata_aclr_b === 1) + i_q_reg_b <= 0; + else if (i_inclocken_b == 1) + i_q_reg_b <= i_q_tmp_b; + end + + if (rdaddress_reg_b == "INCLOCK_B") + begin + if (i_rdaddress_aclr_b === 1) + i_rdaddress_reg_b <= 0; + else if (i_inclocken_b == 1) + i_rdaddress_reg_b <= rdaddress_b; + end + + if (rdcontrol_reg_b == "INCLOCK_B") + begin + if (i_rdcontrol_aclr_b === 1) + i_rden_reg_b <= 0; + else if (i_inclocken_b == 1) + i_rden_reg_b <= i_rden_b; + end + end + + + // This always block is to handle registered inputs for port A + // for negative clock edge + always @(negedge i_inclock_a) + begin + if (i_indata_aclr_a) + i_data_lo_a <= 0; + else + i_data_lo_a <= i_data_hi_a; + + if (i_wraddress_aclr_a) + i_wraddress_lo_a <= 0; + else + i_wraddress_lo_a <= i_wraddress_hi_a; + + if (i_wrcontrol_aclr_a) + i_wren_lo_a <= 0; + else + i_wren_lo_a <= i_wren_hi_a; + + clk_a_trigger <= 1; + end + + + // This process is to handle registered inputs for port B + // for negative clock edge + always @(negedge i_inclock_b) + begin + if (i_indata_aclr_b) + i_data_lo_b <= 0; + else + i_data_lo_b <= i_data_hi_b; + + if (i_wraddress_aclr_b) + i_wraddress_lo_b <= 0; + else + i_wraddress_lo_b <= i_wraddress_hi_b; + + if (i_wrcontrol_aclr_b) + i_wren_lo_b <= 0; + else + i_wren_lo_b <= i_wren_hi_b; + + clk_b_trigger <= 1; + end + + + // This process is to handle registered outputs for port A + always @(posedge i_outclock_a) + begin + if (outdata_reg_a == "OUTCLOCK_A") + begin + if (i_outdata_aclr_a) + i_q_reg_a <= 0; + else if (i_outclocken_a == 1) + i_q_reg_a <= i_q_tmp_a; + end + + if (rdaddress_reg_a == "OUTCLOCK_A") + begin + if (i_rdaddress_aclr_a) + i_rdaddress_reg_a <= 0; + else if (i_outclocken_a == 1) + i_rdaddress_reg_a <= rdaddress_a; + end + + if (rdcontrol_reg_a == "OUTCLOCK_A") + begin + if (i_rdcontrol_aclr_a) + i_rden_reg_a <= 0; + else if (i_outclocken_a == 1) + i_rden_reg_a <= i_rden_a; + end + end + + + // This process is to handle registered outputs for port B + always @(posedge i_outclock_b) + begin + if (outdata_reg_b == "OUTCLOCK_B") + begin + if (i_outdata_aclr_b) + i_q_reg_b <= 0; + else if (i_outclocken_b == 1) + i_q_reg_b <= i_q_tmp_b; + end + + if (rdaddress_reg_b == "OUTCLOCK_B") + begin + if (i_rdaddress_aclr_b) + i_rdaddress_reg_b <= 0; + else if (i_outclocken_b == 1) + i_rdaddress_reg_b <= rdaddress_b; + end + + if (rdcontrol_reg_b == "OUTCLOCK_B") + begin + if (i_rdcontrol_aclr_b) + i_rden_reg_b <= 0; + else if (i_outclocken_b == 1) + i_rden_reg_b <= i_rden_b; + end + end + + + // This always block is to update the memory contents with 'X' when both ports intend to + // write at the same location + always @(i_data_tmp_a or i_wren_tmp_a or i_wraddress_tmp_a or i_data_tmp_b or + i_wren_tmp_b or i_wraddress_tmp_b or write_at_low_clock_a or write_at_low_clock_b or + i_inclock_a or i_inclock_b) + begin + + if ((write_at_low_clock_a ==1) && (write_at_low_clock_b == 1)) + begin + if ((clk_a_trigger ==1) && (clk_b_trigger ==1)) + simultaneous_write = 1; + else + simultaneous_write = 0; + end + else + simultaneous_write = 1; + + if ((i_wren_tmp_a == 1) && (i_wren_tmp_b == 1 ) && + (i_inclock_a == 0 ) && (i_inclock_b == 0 ) && + (simultaneous_write == 1) && + ((operation_mode == "QUAD_PORT") || (operation_mode == "BIDIR_DUAL_PORT"))) + begin + simultaneous_write = 0; + + if (operation_mode == "BIDIR_DUAL_PORT") + begin + for (jb = 0; jb < width_write_b; jb = jb + 1) + begin + Pa = ((i_wraddress_tmp_a * width_write_a) + jb) % width_write_a; + Pb = ((i_wraddress_tmp_b * width_write_b) + jb) / width_write_a; + + if ((i_wraddress_tmp_a == Pb) && (Pa < width_write_a)) + begin + temp_wa3 = mem_data_w[i_wraddress_tmp_a]; + temp_wa3[Pa] = 1'bx; + mem_data_w[i_wraddress_tmp_a] = temp_wa3; + simultaneous_write = 1; + end + end + end + else // QP mode + begin + for (ja = 0; ja < width_write_a; ja = ja + 1) + begin + for (jb = 0; jb < width_write_b; jb = jb + 1) + begin + Pa1 = ((i_wraddress_tmp_a * width_write_a) + ja) / width_read_a; + Pa2 = ((i_wraddress_tmp_a * width_write_a) + ja) % width_read_a; + Pb1 = ((i_wraddress_tmp_b * width_write_b) + jb) / width_read_a; + Pb2 = ((i_wraddress_tmp_b * width_write_b) + jb) % width_read_a; + + if ((Pa1 == Pb1) && (Pa2 == Pb2)) + begin + temp_ra4 = mem_data[Pa1]; + temp_ra4[Pa2] = 1'b X; + mem_data[Pa1] = temp_ra4; + simultaneous_write = 1; + end + end + end + end + end + else + simultaneous_write = 0; + + if (simultaneous_write == 1) + mem_updated = ~mem_updated; + else + begin + i_data2_a = i_data_tmp_a; + i_wren2_a = i_wren_tmp_a; + i_wraddress2_a = i_wraddress_tmp_a; + i_data2_b = i_data_tmp_b; + i_wren2_b = i_wren_tmp_b; + i_wraddress2_b = i_wraddress_tmp_b; + end + + clk_a_trigger = 0; + clk_b_trigger = 0; + end + + + // This always block is to update the memory contents by port A + always @(i_data2_a or i_wren2_a or i_wraddress2_a or i_wraddress_lo_a or i_wren_lo_a or i_inclock_a) + begin + j4 = i_wraddress2_a * width_write_a; + + if ((i_wren2_a == 1) && (i_inclock_a == 0) && + (operation_mode != "ROM")) + begin + if ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "SINGLE_PORT")) + mem_data_w[i_wraddress2_a] = i_data2_a; + else // QP or DP mode + for (i4 = 0; i4 < width_write_a; i4 = i4 + 1) + begin + temp_ra3 = mem_data[(j4+i4)/width_read_a]; + temp_ra3[(j4+i4)%width_read_a] = i_data2_a[i4]; + mem_data[(j4+i4)/width_read_a] = temp_ra3; + end + + mem_updated = ~mem_updated; + end + end + + + // This always block is to update the memory contents by port B + always @(i_data2_b or i_wren2_b or i_wraddress2_b or i_wraddress_lo_b or i_wren_lo_b or i_inclock_b) + begin + j3 = i_wraddress2_b * width_write_b; + + if ((i_wren2_b == 1) && (i_inclock_b == 0) && + ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "QUAD_PORT"))) + begin + if (operation_mode == "BIDIR_DUAL_PORT") + for (i3 = 0; i3 < width_write_b; i3 = i3 + 1) + begin + temp_wa2 = mem_data_w[(j3+i3)/width_write_a]; + temp_wa2[(j3+i3)%width_write_a] = i_data2_b[i3]; + mem_data_w[(j3+i3)/width_write_a] = temp_wa2; + end + else // QP mode + for (i3 = 0; i3 < width_write_b; i3 = i3 + 1) + begin + temp_ra2 = mem_data[(j3+i3)/width_read_a]; + temp_ra2[(j3+i3)%width_read_a] = i_data2_b[i3]; + mem_data[(j3+i3)/width_read_a] = temp_ra2; + end + + mem_updated = ~mem_updated; + end + end + + + // This always block is to read the memory content for port A + always @(posedge i_rden_tmp_a or negedge i_rden_tmp_a or + i_rdaddress_tmp_a or + i_wraddress_tmp_a or mem_updated) + begin + if ((operation_mode == "DUAL_PORT") || (operation_mode == "QUAD_PORT")) + begin + if (i_rden_tmp_a == 1) + i_q_tmp_a = mem_data[i_rdaddress_tmp_a]; + end + else if ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "SINGLE_PORT")) + i_q_tmp_a = mem_data_w[i_wraddress_tmp_a]; + else if (operation_mode == "ROM") + i_q_tmp_a = mem_data[i_rdaddress_tmp_a]; + end + + // This always block is to read the memory content for port A + always @(posedge i_rden_tmp_b or negedge i_rden_tmp_b or + i_rdaddress_tmp_b or + i_wraddress_tmp_b or + mem_updated) + begin + if (operation_mode == "QUAD_PORT") + begin + j2 = i_rdaddress_tmp_b * width_read_b; + if (i_rden_tmp_b == 1) + for (i2 = 0; i2 < width_read_b; i2 = i2 + 1) + begin + temp_ra = mem_data[(j2+i2)/width_read_a]; + i_q_tmp_b[i2] = temp_ra[(j2+i2)%width_read_a]; + end + end + else if (operation_mode == "BIDIR_DUAL_PORT") + begin + j2 = i_wraddress_tmp_b * width_write_b; + for (i2=0; i2<width_write_b; i2=i2+1) + begin + temp_wa = mem_data_w[(j2+i2)/width_write_a]; + i_q_tmp_b[i2] = temp_wa[(j2+i2)%width_write_a]; + end + end + end + + + // This always block is to determine actual registered write address from port A + // to memory block + always @(i_wraddress_hi_a or i_wraddress_lo_a or + posedge i_wraddress_aclr_a or negedge i_wraddress_aclr_a) + begin + if ((operation_mode == "QUAD_PORT") || (operation_mode == "DUAL_PORT")) + i_wraddress_reg_a <= (i_wraddress_aclr_a) ? + 0 : ((write_at_low_clock_a) ? + i_wraddress_lo_a : i_wraddress_hi_a); + else + i_wraddress_reg_a <= (i_wraddress_aclr_a) ? + 0 : i_wraddress_hi_a; + end + + + // This always block is to determine actual registered write control from port A + // to memory block + always @(i_wren_hi_a or i_wren_lo_a or + posedge i_wraddress_aclr_a or negedge i_wraddress_aclr_a) + begin + if (operation_mode != "BIDIR_DUAL_PORT") + i_wren_reg_a <= (i_wrcontrol_aclr_a) ? 0 : + ((write_at_low_clock_a) ? + i_wren_lo_a : i_wren_hi_a); + else + i_wren_reg_a <= (i_wrcontrol_aclr_a) ? + 0 : i_wren_hi_a; + + end + + + // This always block is to determine actual registered write data from port A + // to memory block + always @(i_data_hi_a or i_data_lo_a or + posedge i_indata_aclr_a or negedge i_indata_aclr_a) + begin + i_data_reg_a <= (i_indata_aclr_a) ? 0 : + ((write_at_low_clock_a) ? + i_data_lo_a : i_data_hi_a); + end + + + // This always block is to determine actual registered write address from port B + // to memory block + always @(i_wraddress_hi_b or i_wraddress_lo_b or + posedge i_wraddress_aclr_b or negedge i_wraddress_aclr_b) + begin + if ((operation_mode == "QUAD_PORT") || (operation_mode == "DUAL_PORT")) + i_wraddress_reg_b <= (i_wraddress_aclr_b) ? 0 : + ((write_at_low_clock_b) ? + i_wraddress_lo_b : i_wraddress_hi_b); + else + i_wraddress_reg_b <= (i_wraddress_aclr_b) ? + 0 : i_wraddress_hi_b; + end + + + // This always block is to determine actual registered write control from port B + // to memory block + always @(i_wren_hi_b or i_wren_lo_b or + posedge i_wraddress_aclr_b or negedge i_wraddress_aclr_b) + begin + if (operation_mode != "BIDIR_DUAL_PORT") + i_wren_reg_b <= (i_wrcontrol_aclr_b) ? 0 : + ((write_at_low_clock_b) ? + i_wren_lo_b : i_wren_hi_b); + else + i_wren_reg_b <= (i_wrcontrol_aclr_b) ? + 0 : i_wren_hi_b; + + end + + + // This always block is to determine actual registered write data from port B + // to memory block + always @(i_data_hi_b or i_data_lo_b or + posedge i_indata_aclr_b or negedge i_indata_aclr_b) + begin + i_data_reg_b <= (i_indata_aclr_b) ? 0 : + ((write_at_low_clock_b) ? + i_data_lo_b : i_data_hi_b); + end + + + // This always block is to determine actual write address from port A + // to memory block + always @(wraddress_a or i_wraddress_reg_a or i_wraddress_aclr_a) + begin + i_wraddress_tmp_a <= (i_wraddress_aclr_a) ? 0 : + ((wrcontrol_wraddress_reg_a == "INCLOCK_A") ? + i_wraddress_reg_a : wraddress_a); + end + + + // This always block is to determine actual write address from port B + // to memory block + always @(wraddress_b or i_wraddress_reg_b or i_wraddress_aclr_b) + begin + i_wraddress_tmp_b <= (i_wraddress_aclr_b) ? 0 : + ((wrcontrol_wraddress_reg_b == "INCLOCK_B") ? + i_wraddress_reg_b : wraddress_b); + end + + + // This always block is to determine actual read address from port A + // to memory block + always @(rdaddress_a or i_rdaddress_reg_a or i_rdaddress_aclr_a) + begin + i_rdaddress_tmp_a <= (i_rdaddress_aclr_a) ? 0 : + ((rdaddress_reg_a != "UNREGISTERED") ? + i_rdaddress_reg_a : rdaddress_a); + end + + + // This always block is to determine actual read address from port B + // to memory block + always @(rdaddress_b or i_rdaddress_reg_b or i_rdaddress_aclr_b) + begin + i_rdaddress_tmp_b <= (i_rdaddress_aclr_b) ? 0 : + ((rdaddress_reg_b != "UNREGISTERED") ? + i_rdaddress_reg_b : rdaddress_b); + end + + + // This always block is to determine actual write control from port A + // to memory block + always @(i_wren_a or i_wren_reg_a or i_wrcontrol_aclr_a) + begin + i_wren_tmp_a <= (i_wrcontrol_aclr_a) ? 0 : + ((wrcontrol_wraddress_reg_a == "INCLOCK_A") ? + i_wren_reg_a : i_wren_a); + end + + + // This always block is to determine actual write control from port B + // to memory block + always @(i_wren_b or i_wren_reg_b or i_wrcontrol_aclr_b) + begin + i_wren_tmp_b <= (i_wrcontrol_aclr_b) ? 0 : + ((wrcontrol_wraddress_reg_b == "INCLOCK_B") ? + i_wren_reg_b : i_wren_b); + end + + + // This always block is to determine actual read control from port A + // to memory block + always @(i_rden_a or i_rden_reg_a or i_rdcontrol_aclr_a) + begin + i_rden_tmp_a <= (i_rdcontrol_aclr_a) ? 0 : + ((rdcontrol_reg_a != "UNREGISTERED") ? + i_rden_reg_a : i_rden_a); + end + + + // This always block is to determine actual read control from port B + // to memory block + always @(i_rden_b or i_rden_reg_b or i_rdcontrol_aclr_b) + begin + i_rden_tmp_b <= (i_rdcontrol_aclr_b) ? 0 : + ((rdcontrol_reg_b != "UNREGISTERED") ? + i_rden_reg_b : i_rden_b); + end + + // This always block is to determine actual write data from port A + // to memory block + always @(data_a or i_data_reg_a or i_indata_aclr_a) + begin + i_data_tmp_a <= (i_indata_aclr_a) ? 0 : + ((indata_reg_a == "INCLOCK_A") ? + i_data_reg_a : data_a); + end + + + // This always block is to determine actual write data from port B + // to memory block + always @(data_b or i_data_reg_b or i_indata_aclr_b) + begin + i_data_tmp_b <= (i_indata_aclr_b) ? 0 : + ((indata_reg_b == "INCLOCK_B") ? + i_data_reg_b : data_b); + end + + +// SIGNAL ASSIGNMENT + + // Port A output + assign q_a = (i_outdata_aclr_a) ? 0 : + ((outdata_reg_a != "UNREGISTERED") ? i_q_reg_a : i_q_tmp_a); + + // Port B output + assign q_b = ((operation_mode != "BIDIR_DUAL_PORT") && (operation_mode != "QUAD_PORT")) ? 0 : + (i_outdata_aclr_b) ? 0 : + ((outdata_reg_b != "UNREGISTERED") ? i_q_reg_b : i_q_tmp_b); + +endmodule // ALTQPRAM + +// END OF MODULE + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module 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_MODULE_NAME-------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +module parallel_add ( + data, + clock, + aclr, + clken, + result); + + parameter width = 4; // Required + parameter size = 2; // Required + parameter widthr = 4; // Required + parameter shift = 0; + parameter msw_subtract = "NO"; // or "YES" + parameter representation = "UNSIGNED"; + parameter pipeline = 0; + parameter result_alignment = "LSB"; // or "MSB" + parameter lpm_type = "parallel_add"; + parameter lpm_hint = "UNUSED"; + + // 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. + `define max_precision (width+size+shift*(size-1)+30) // Result will not overflow this size + + // INPUT PORT DECLARATION + input [width*size-1:0] data; // Required port + input clock; // Required port + input aclr; // Default = 0 + input clken; // Default = 1 + + // OUTPUT PORT DECLARATION + output [widthr-1:0] result; //Required port + + // INTERNAL REGISTER DECLARATION + reg imsb_align; + reg [width-1:0] idata_word; + reg [`max_precision-1:0] idata_extended; + reg [`max_precision-1:0] tmp_result; + reg [widthr-1:0] resultpipe [(pipeline +1):0]; + + // INTERNAL TRI DECLARATION + tri1 clken_int; + + // INTERNAL WIRE DECLARATION + wire [widthr-1:0] aligned_result; + + // LOCAL INTEGER DECLARATION + integer ni; + integer best_result_width; + integer pipe_ptr; + + // Note: The recommended value for WIDTHR parameter, + // the width of addition result, for full + // precision is: + // -- + // ((2^WIDTH)-1) * (2^(SIZE*SHIFT)-1) + // WIDTHR = CEIL(LOG2(-----------------------------------)) + // (2^SHIFT)-1 + // + // Use CALC_PADD_WIDTHR(WIDTH, SIZE, SHIFT): + // 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))); + function integer ceil_log2; + input [`max_precision-1:0] input_num; + integer i; + reg [`max_precision-1:0] try_result; + begin + i = 0; + try_result = 1; + while ((try_result << i) < input_num && i < `max_precision) + i = i + 1; + ceil_log2 = i; + end + endfunction + + // INITIALIZATION + initial + begin + if (widthr > `max_precision) + $display ("Error! WIDTHR must not exceed WIDTH+SIZE+SHIFT*(SIZE-1)."); + if (size < 2) + $display ("Error! SIZE must be greater than 1."); + + if (shift == 0) + begin + best_result_width = width; + if (size > 1) + best_result_width = best_result_width + ceil_log2(size); + end + else + best_result_width = ceil_log2( ((1<<width)-1) * ((1 << (size*shift))-1) + / ((1 << shift)-1)); + + imsb_align = (result_alignment == "MSB" && widthr < best_result_width) ? 1 : 0; + + // Clear the pipeline array + for (ni=0; ni< pipeline +1; ni=ni+1) + resultpipe[ni] = 0; + pipe_ptr = 0; + end + + // MODEL + always @(data) + begin + tmp_result = 0; + // Loop over each input data word, and add to the total + for (ni=0; ni<size; ni=ni+1) + begin + // Get input word to add to total + idata_word = (data >> (ni * width)); + + // If signed and negative, pad MSB with ones to sign extend the input data + if ((representation != "UNSIGNED") && (idata_word[width-1] == 1'b1)) + idata_extended = ({{(`max_precision-width-2){1'b1}}, idata_word} << (shift*ni)); + else + idata_extended = (idata_word << (shift*ni)); // zero padding is automatic + + // Add to total + if ((msw_subtract == "YES") && (ni == (size-1))) + tmp_result = tmp_result - idata_extended; + else + tmp_result = tmp_result + idata_extended; + end + end + + // Pipeline model + always @(posedge clock or posedge aclr) + begin + if (aclr == 1'b1) + begin + // Clear the pipeline array + for (ni=0; ni< (pipeline +1); ni=ni+1) + resultpipe[ni] <= 0; + pipe_ptr <= 0; + end + else if (clken_int == 1'b1) + begin + resultpipe[pipe_ptr] <= aligned_result; + if (pipeline > 1) + pipe_ptr <= (pipe_ptr + 1) % pipeline; + end + end + + // Check if output needs MSB alignment + assign aligned_result = (imsb_align == 1) + ? (tmp_result >> (best_result_width-widthr)) + : tmp_result; + assign clken_int = clken; + assign result = (pipeline > 0) ? resultpipe[pipe_ptr] : aligned_result; +endmodule // end of PARALLEL_ADD +// END OF MODULE +//START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : scfifo +// +// Description : Single Clock FIFO +// +// Limitation : USE_EAB=OFF is not supported +// +// Results expected: +// +//END_MODULE_NAME-------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module scfifo ( data, + clock, + wrreq, + rdreq, + aclr, + sclr, + q, + usedw, + full, + empty, + almost_full, + almost_empty); + +// GLOBAL PARAMETER DECLARATION + parameter lpm_width = 1; + parameter lpm_widthu = 1; + parameter lpm_numwords = 2; + parameter lpm_showahead = "OFF"; + parameter lpm_type = "scfifo"; + parameter lpm_hint = "USE_EAB=ON"; + parameter intended_device_family = "APEX20KE"; + parameter underflow_checking = "ON"; + parameter overflow_checking = "ON"; + parameter allow_rwcycle_when_full = "OFF"; + parameter use_eab = "ON"; + parameter add_ram_output_register = "OFF"; + parameter almost_full_value = 0; + parameter almost_empty_value = 0; + parameter maximum_depth = 0; + parameter showahead_area = ((lpm_showahead == "ON") && (add_ram_output_register == "OFF")); + parameter showahead_speed = ((lpm_showahead == "ON") && (add_ram_output_register == "ON")); + parameter legacy_speed = ((lpm_showahead == "OFF") && (add_ram_output_register == "ON")); + +// INPUT PORT DECLARATION + input [lpm_width-1:0] data; + input clock; + input wrreq; + input rdreq; + input aclr; + input sclr; + +// OUTPUT PORT DECLARATION + output [lpm_width-1:0] q; + output [lpm_widthu-1:0] usedw; + output full; + output empty; + output almost_full; + output almost_empty; + +// INTERNAL REGISTERS DECLARATION + reg [lpm_width-1:0] mem_data [(1<<lpm_widthu):0]; + reg [lpm_widthu-1:0] count_id; + reg [lpm_widthu-1:0] read_id; + reg [lpm_widthu-1:0] write_id; + + reg valid_rreq; + reg valid_wreq; + reg write_flag; + reg full_flag; + reg empty_flag; + reg almost_full_flag; + reg almost_empty_flag; + reg [lpm_width-1:0] tmp_q; + reg stratix_family; + reg set_q_to_x; + + reg [lpm_widthu-1:0] write_latency1; + reg [lpm_widthu-1:0] write_latency2; + reg [lpm_widthu-1:0] write_latency3; + integer wrt_count; + + reg empty_latency1; + reg empty_latency2; + + reg [(1<<lpm_widthu)-1:0] data_ready; + reg [(1<<lpm_widthu)-1:0] data_shown; + +// INTERNAL TRI DECLARATION + tri0 aclr; + +// LOCAL INTEGER DECLARATION + integer i; + +// COMPONENT INSTANTIATIONS + ALTERA_DEVICE_FAMILIES dev (); + +// INITIAL CONSTRUCT BLOCK + initial + begin + + stratix_family = ( dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)); + + if (lpm_width <= 0) + $display ("Error! LPM_WIDTH must be greater than 0."); + if (lpm_numwords <= 1) + $display ("Error! LPM_NUMWORDS must be greater than or equal to 2."); + if ((lpm_widthu !=1) && (lpm_numwords > (1 << lpm_widthu))) + $display ("Error! LPM_NUMWORDS must equal to the ceiling of log2(LPM_WIDTHU)."); + if (lpm_numwords <= (1 << (lpm_widthu - 1))) + $display ("Error! LPM_WIDTHU is too big for the specified LPM_NUMWORDS."); + if (dev.IS_VALID_FAMILY(intended_device_family) == 0) + $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family); + if((add_ram_output_register != "ON") && (add_ram_output_register != "OFF")) + $display ("Error! add_ram_output_register must be ON or OFF."); + + for (i = 0; i < (1<<lpm_widthu); i = i + 1) + begin + if (dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)) + begin + if ((add_ram_output_register == "ON") || (use_eab == "OFF")) + mem_data[i] <= {lpm_width{1'b0}}; + else + mem_data[i] <= {lpm_width{1'bx}}; + end + else + mem_data[i] <= {lpm_width{1'b0}}; + end + + if (dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.FEATURE_FAMILY_STRATIXII(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family) || + dev.IS_FAMILY_CYCLONEII(intended_device_family)) + begin + if ((add_ram_output_register == "ON") || (use_eab == "OFF")) + tmp_q <= {lpm_width{1'b0}}; + else + tmp_q <= {lpm_width{1'bx}}; + end + else + tmp_q <= {lpm_width{1'b0}}; + + write_flag <= 1'b0; + count_id <= 0; + read_id <= 0; + write_id <= 0; + full_flag <= 1'b0; + empty_flag <= 1'b1; + empty_latency1 <= 1'b1; + empty_latency2 <= 1'b1; + set_q_to_x <= 1'b0; + wrt_count <= 0; + + if (almost_full_value == 0) + almost_full_flag <= 1'b1; + else + almost_full_flag <= 1'b0; + + if (almost_empty_value == 0) + almost_empty_flag <= 1'b0; + else + almost_empty_flag <= 1'b1; + end + +// ALWAYS CONSTRUCT BLOCK + always @(rdreq or empty_flag) + begin + if (underflow_checking == "OFF") + valid_rreq <= rdreq; + else + valid_rreq <= rdreq && ~empty_flag; + end + + always @(wrreq or rdreq or full_flag) + begin + if (overflow_checking == "OFF") + valid_wreq <= wrreq; + else if (allow_rwcycle_when_full == "ON") + valid_wreq <= wrreq && (!full_flag || rdreq); + else + valid_wreq <= wrreq && !full_flag; + end + + always @(posedge clock or posedge aclr) + begin + if (aclr) + begin + if ((lpm_showahead == "ON") && (use_eab == "ON")) + begin + tmp_q <= {lpm_width{1'bX}}; + end + else + begin + if (!stratix_family) + begin + tmp_q <= {lpm_width{1'b0}}; + end + else + tmp_q <= {lpm_width{1'bX}}; + end + + read_id <= 0; + count_id <= 0; + full_flag <= 1'b0; + empty_flag <= 1'b1; + empty_latency1 <= 1'b1; + empty_latency2 <= 1'b1; + set_q_to_x <= 1'b0; + wrt_count <= 0; + + if (almost_full_value > 0) + almost_full_flag <= 1'b0; + if (almost_empty_value > 0) + almost_empty_flag <= 1'b1; + + write_id <= 0; + + if ((use_eab == "ON") && (stratix_family) && ((showahead_speed) || (showahead_area) || (legacy_speed))) + begin + write_latency1 <= 1'bx; + write_latency2 <= 1'bx; + data_shown <= {lpm_width{1'b0}}; + tmp_q <= {lpm_width{1'bX}}; + end + end + else + begin + if (sclr) + begin + tmp_q <= {lpm_width{1'bX}}; + + read_id <= 0; + count_id <= 0; + full_flag <= 1'b0; + empty_flag <= 1'b1; + empty_latency1 <= 1'b1; + empty_latency2 <= 1'b1; + set_q_to_x <= 1'b0; + wrt_count <= 0; + + if (almost_full_value > 0) + almost_full_flag <= 1'b0; + if (almost_empty_value > 0) + almost_empty_flag <= 1'b1; + + if (!stratix_family) + begin + if (valid_wreq) + begin + write_flag <= 1'b1; + end + else + write_id <= 0; + end + else + begin + write_id <= 0; + end + + if ((use_eab == "ON") && (stratix_family) && ((showahead_speed) || (showahead_area) || (legacy_speed))) + begin + write_latency1 <= 1'bx; + write_latency2 <= 1'bx; + data_shown <= {lpm_width{1'b0}}; + tmp_q <= {lpm_width{1'bX}}; + end + end + else + begin + // WRITE operation + if (valid_wreq) + begin + if ((overflow_checking == "OFF" && full_flag && !valid_rreq) || set_q_to_x) + begin + tmp_q <= {lpm_width{1'bX}}; + set_q_to_x <= 1'b1; + end + else + begin + mem_data[write_id] <= data; + write_flag <= 1'b1; + + if (!((use_eab == "ON") && stratix_family && (showahead_speed || showahead_area || legacy_speed))) + begin + empty_flag <= 1'b0; + end + else + begin + empty_latency1 <= 1'b0; + end + + if (!valid_rreq) + wrt_count <= wrt_count + 1; + + if (!valid_rreq) + begin + if (count_id >= (1 << lpm_widthu) - 1) + count_id <= 0; + else + count_id <= count_id + 1; + end + else + begin + if (allow_rwcycle_when_full == "OFF") + full_flag <= 1'b0; + end + + if (!(stratix_family) || (stratix_family && !(showahead_speed || showahead_area || legacy_speed))) + begin + if (!valid_rreq) + if ((count_id == lpm_numwords - 1) && (empty_flag == 1'b0)) + full_flag <= 1'b1; + end + else + begin + if (!valid_rreq) + if (count_id == lpm_numwords - 1) + full_flag <= 1'b1; + end + + if (lpm_showahead == "ON") + begin + if ((use_eab == "ON") && stratix_family && (showahead_speed || showahead_area)) + begin + write_latency1 <= write_id; + data_shown[write_id] <= 1'b1; + data_ready[write_id] <= 1'bx; + end + else + begin + if ((use_eab == "OFF") && stratix_family && (count_id == 0)) + begin + tmp_q <= data; + end + else + begin + if ((!empty_flag) && (!valid_rreq)) + begin + tmp_q <= mem_data[read_id]; + end + end + end + end + else + begin + if ((use_eab == "ON") && stratix_family && legacy_speed) + begin + write_latency1 <= write_id; + data_shown[write_id] <= 1'b1; + data_ready[write_id] <= 1'bx; + end + end + end + end + //READ operation + if (valid_rreq) + begin + if (!(set_q_to_x)) + begin + if (!valid_wreq) + wrt_count <= wrt_count - 1; + + if (!valid_wreq) + begin + full_flag <= 1'b0; + + if (count_id <= 0) + count_id <= ((1 << lpm_widthu) - 1); + else + count_id <= count_id - 1; + end + + if ((use_eab == "ON") && stratix_family && (showahead_speed || showahead_area || legacy_speed)) + begin + if ((wrt_count == 1 && valid_rreq && !valid_wreq) || ((wrt_count == 1 ) && valid_wreq && valid_rreq)) + begin + empty_flag <= 1'b1; + end + else + begin + if (showahead_speed) + begin + if (data_shown[write_latency2] == 1'b0) + begin + empty_flag <= 1'b1; + end + end + else if (showahead_area || legacy_speed) + begin + if (data_shown[write_latency1] == 1'b0) + begin + empty_flag <= 1'b1; + end + end + end + end + else + begin + if (!valid_wreq) + begin + if ((count_id == 1) && !(full_flag)) + empty_flag <= 1'b1; + end + end + + if (empty_flag) + begin + tmp_q <= {lpm_width{1'bX}}; + end + else if (read_id >= ((1<<lpm_widthu) - 1)) + begin + if (lpm_showahead == "ON") + begin + if ((use_eab == "ON") && stratix_family && (showahead_speed || showahead_area)) + begin + if (showahead_speed) + begin + if ((write_latency2 == 0) || (data_ready[0] == 1'b1)) + begin + if (data_shown[0] == 1'b1) + begin + tmp_q <= mem_data[0]; + data_shown[0] <= 1'b0; + data_ready[0] <= 1'b0; + end + end + end + else + begin + if ((count_id == 1) && !(full_flag)) + begin + tmp_q <= {lpm_width{1'bX}}; + end + else if ((write_latency1 == 0) || (data_ready[0] == 1'b1)) + begin + if (data_shown[0] == 1'b1) + begin + tmp_q <= mem_data[0]; + data_shown[0] <= 1'b0; + data_ready[0] <= 1'b0; + end + end + end + end + else + begin + if ((count_id == 1) && !(full_flag)) + tmp_q <= {lpm_width{1'bX}}; + else + tmp_q <= mem_data[0]; + end + end + else + begin + if ((use_eab == "ON") && stratix_family && legacy_speed) + begin + if ((write_latency1 == read_id) || (data_ready[read_id] == 1'b1)) + begin + if (data_shown[read_id] == 1'b1) + begin + tmp_q <= mem_data[read_id]; + data_shown[read_id] <= 1'b0; + data_ready[read_id] <= 1'b0; + end + end + else + begin + tmp_q <= {lpm_width{1'bX}}; + end + end + else + tmp_q <= mem_data[read_id]; + end + + read_id <= 0; + end // end if (read_id >= ((1<<lpm_widthu) - 1)) + else + begin + if (lpm_showahead == "ON") + begin + if ((use_eab == "ON") && stratix_family && (showahead_speed || showahead_area)) + begin + if (showahead_speed) + begin + if ((write_latency2 == read_id+1) || (data_ready[read_id+1] == 1'b1)) + begin + if (data_shown[read_id+1] == 1'b1) + begin + tmp_q <= mem_data[read_id + 1]; + data_shown[read_id+1] <= 1'b0; + data_ready[read_id+1] <= 1'b0; + end + end + end + else + begin + if ((count_id == 1) && !(full_flag)) + begin + tmp_q <= {lpm_width{1'bX}}; + end + else if ((write_latency1 == read_id+1) || (data_ready[read_id+1] == 1'b1)) + begin + if (data_shown[read_id+1] == 1'b1) + begin + tmp_q <= mem_data[read_id + 1]; + data_shown[read_id+1] <= 1'b0; + data_ready[read_id+1] <= 1'b0; + end + end + end + end + else + begin + if ((count_id == 1) && !(full_flag)) + begin + if ((use_eab == "OFF") && stratix_family) + begin + if (valid_wreq) + begin + tmp_q <= data; + end + else + begin + tmp_q <= {lpm_width{1'bX}}; + end + end + else + begin + tmp_q <= {lpm_width{1'bX}}; + end + end + else + tmp_q <= mem_data[read_id + 1]; + end + end + else + begin + if ((use_eab == "ON") && stratix_family && legacy_speed) + begin + if ((write_latency1 == read_id) || (data_ready[read_id] == 1'b1)) + begin + if (data_shown[read_id] == 1'b1) + begin + tmp_q <= mem_data[read_id]; + data_shown[read_id] <= 1'b0; + data_ready[read_id] <= 1'b0; + end + end + else + begin + tmp_q <= {lpm_width{1'bX}}; + end + end + else + tmp_q <= mem_data[read_id]; + end + + read_id <= read_id + 1; + end + end + end + + if (almost_full_value == 0) + almost_full_flag <= 1'b1; + else if (lpm_numwords > almost_full_value) + begin + if (almost_full_flag) + begin + if ((count_id == almost_full_value) && !wrreq && rdreq) + almost_full_flag <= 1'b0; + end + else + begin + if ((almost_full_value == 1) && (count_id == 0) && wrreq) + almost_full_flag <= 1'b1; + else if ((almost_full_value > 1) && (count_id == almost_full_value - 1) + && wrreq && !rdreq) + almost_full_flag <= 1'b1; + end + end + + if (almost_empty_value == 0) + almost_empty_flag <= 1'b0; + else if (lpm_numwords > almost_empty_value) + begin + if (almost_empty_flag) + begin + if ((almost_empty_value == 1) && (count_id == 0) && wrreq) + almost_empty_flag <= 1'b0; + else if ((almost_empty_value > 1) && (count_id == almost_empty_value - 1) + && wrreq && !rdreq) + almost_empty_flag <= 1'b0; + end + else + begin + if ((count_id == almost_empty_value) && !wrreq && rdreq) + almost_empty_flag <= 1'b1; + end + end + end + + if ((use_eab == "ON") && stratix_family) + begin + if (showahead_speed) + begin + write_latency2 <= write_latency1; + write_latency3 <= write_latency2; + if (write_latency3 !== write_latency2) + data_ready[write_latency2] <= 1'b1; + + empty_latency2 <= empty_latency1; + + if (data_shown[write_latency2]==1'b1) + begin + if ((read_id == write_latency2) || aclr || sclr) + begin + if (!(aclr === 1'b1) && !(sclr === 1'b1)) + begin + if (write_latency2 !== 1'bx) + begin + tmp_q <= mem_data[write_latency2]; + data_shown[write_latency2] <= 1'b0; + data_ready[write_latency2] <= 1'b0; + + if (!valid_rreq) + empty_flag <= empty_latency2; + end + end + end + end + end + else if (showahead_area) + begin + write_latency2 <= write_latency1; + if (write_latency2 !== write_latency1) + data_ready[write_latency1] <= 1'b1; + + if (data_shown[write_latency1]==1'b1) + begin + if ((read_id == write_latency1) || aclr || sclr) + begin + if (!(aclr === 1'b1) && !(sclr === 1'b1)) + begin + if (write_latency1 !== 1'bx) + begin + tmp_q <= mem_data[write_latency1]; + data_shown[write_latency1] <= 1'b0; + data_ready[write_latency1] <= 1'b0; + + if (!valid_rreq) + begin + empty_flag <= empty_latency1; + end + end + end + end + end + end + else + begin + if (legacy_speed) + begin + write_latency2 <= write_latency1; + if (write_latency2 !== write_latency1) + data_ready[write_latency1] <= 1'b1; + + empty_flag <= empty_latency1; + + if ((wrt_count == 1 && !valid_wreq && valid_rreq) || aclr || sclr) + begin + empty_flag <= 1'b1; + empty_latency1 <= 1'b1; + end + else + begin + if ((wrt_count == 1) && valid_wreq && valid_rreq) + begin + empty_flag <= 1'b1; + end + end + end + end + end + end + end + + always @(negedge clock) + begin + if (write_flag) + begin + write_flag <= 1'b0; + + if (sclr || aclr || (write_id >= ((1 << lpm_widthu) - 1))) + write_id <= 0; + else + write_id <= write_id + 1; + end + + if (!(stratix_family)) + begin + if (!empty) + begin + if ((lpm_showahead == "ON") && ($time > 0)) + tmp_q <= mem_data[read_id]; + end + end + end + + always @(full_flag) + begin + if (lpm_numwords == almost_full_value) + if (full_flag) + almost_full_flag <= 1'b1; + else + almost_full_flag <= 1'b0; + + if (lpm_numwords == almost_empty_value) + if (full_flag) + almost_empty_flag <= 1'b0; + else + almost_empty_flag <= 1'b1; + end + +// CONTINOUS ASSIGNMENT + assign q = tmp_q; + assign full = full_flag; + assign empty = empty_flag; + assign usedw = count_id; + assign almost_full = almost_full_flag; + assign almost_empty = almost_empty_flag; + +endmodule // scfifo +// END OF MODULE + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : dcfifo_dffpipe +// +// Description : Dual Clocks FIFO +// +// Limitation : +// +// Results expected: +// +//END_MODULE_NAME-------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module dcfifo_dffpipe ( d, clock, aclr, + q); + +// GLOBAL PARAMETER DECLARATION + parameter lpm_delay = 1; + parameter lpm_width = 64; + +// INPUT PORT DECLARATION + input [lpm_width-1:0] d; + input clock; + input aclr; + +// OUTPUT PORT DECLARATION + output [lpm_width-1:0] q; + +// INTERNAL REGISTERS DECLARATION + reg [lpm_width-1:0] dffpipe [lpm_delay:0]; + reg [lpm_width-1:0] q; + +// LOCAL INTEGER DECLARATION + integer delay, i; + +// INITIAL CONSTRUCT BLOCK + initial + begin + delay <= lpm_delay - 1; + for (i = 0; i < lpm_delay; i = i + 1) + dffpipe[i] <= 0; + q <= 0; + end + +// ALWAYS CONSTRUCT BLOCK + always @(posedge clock or posedge aclr) + begin + if (aclr) + begin + for (i = 0; i < lpm_delay; i = i + 1) + dffpipe[i] <= 0; + q <= 0; + end + else + begin + if ((lpm_delay > 0) && ($time > 0)) + begin + if (delay > 0) + begin + for (i = delay; i > 0; i = i - 1) + dffpipe[i] <= dffpipe[i - 1]; + q <= dffpipe[delay - 1]; + end + else + q <= d; + + dffpipe[0] <= d; + end + end + end // @(posedge aclr or posedge clock) + + always @(d) + begin + if (lpm_delay == 0) + q <= d; + end // @(d) + +endmodule // dcfifo_dffpipe +// END OF MODULE + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : dcfifo_fefifo +// +// Description : Dual Clock FIFO +// +// Limitation : +// +// Results expected: +// +//END_MODULE_NAME-------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module dcfifo_fefifo ( usedw_in, wreq, rreq, clock, aclr, + empty, full); + +// GLOBAL PARAMETER DECLARATION + parameter lpm_widthad = 1; + parameter lpm_numwords = 1; + parameter underflow_checking = "ON"; + parameter overflow_checking = "ON"; + parameter lpm_mode = "READ"; + +// INPUT PORT DECLARATION + input [lpm_widthad-1:0] usedw_in; + input wreq, rreq; + input clock; + input aclr; + +// OUTPUT PORT DECLARATION + output empty, full; + +// INTERNAL REGISTERS DECLARATION + reg [1:0] sm_empty; + reg lrreq; + reg i_empty, i_full; + +// LOCAL INTEGER DECLARATION + integer almostfull; + +// INITIAL CONSTRUCT BLOCK + initial + begin + if ((lpm_mode != "READ") && (lpm_mode != "WRITE")) + $display ("Error! LPM_MODE must be READ or WRITE."); + if ((underflow_checking != "ON") && (underflow_checking != "OFF")) + $display ("Error! UNDERFLOW_CHECKING must be ON or OFF."); + if ((overflow_checking != "ON") && (overflow_checking != "OFF")) + $display ("Error! OVERFLOW_CHECKING must be ON or OFF."); + + sm_empty <= 2'b00; + i_empty <= 1'b1; + i_full <= 1'b0; + + if (lpm_numwords >= 3) + almostfull <= lpm_numwords - 3; + else + almostfull <= 0; + end + +// ALWAYS CONSTRUCT BLOCK + always @(posedge aclr) + begin + sm_empty <= 2'b00; + i_empty <= 1'b1; + i_full <= 1'b0; + lrreq <= 1'b0; + end // @(posedge aclr) + + always @(posedge clock) + begin + if (underflow_checking == "OFF") + lrreq <= rreq; + else + lrreq <= rreq && ~i_empty; + + if (~aclr && $time > 0) + begin + if (lpm_mode == "READ") + begin + casex (sm_empty) + // state_empty + 2'b00: + if (usedw_in != 0) + sm_empty <= 2'b01; + // state_non_empty + 2'b01: + if (rreq && (((usedw_in == 1) && !lrreq) || ((usedw_in == 2) && lrreq))) + sm_empty <= 2'b10; + // state_emptywait + 2'b10: + if (usedw_in > 1) + sm_empty <= 2'b01; + else + sm_empty <= 2'b00; + default: + $display ("Error! Invalid sm_empty state in read mode."); + endcase + end // if (lpm_mode == "READ") + else if (lpm_mode == "WRITE") + begin + casex (sm_empty) + // state_empty + 2'b00: + if (wreq) + sm_empty <= 2'b01; + // state_one + 2'b01: + if (!wreq) + sm_empty <= 2'b11; + // state_non_empty + 2'b11: + if (wreq) + sm_empty <= 2'b01; + else if (usedw_in == 0) + sm_empty <= 2'b00; + default: + $display ("Error! Invalid sm_empty state in write mode."); + endcase + end // if (lpm_mode == "WRITE") + + if (~aclr && (usedw_in >= almostfull) && ($time > 0)) + i_full <= 1'b1; + else + i_full <= 1'b0; + end // if (~aclr && $time > 0) + end // @(posedge clock) + + always @(sm_empty) + begin + i_empty <= !sm_empty[0]; + end + // @(sm_empty) + +// CONTINOUS ASSIGNMENT + assign empty = i_empty; + assign full = i_full; +endmodule // dcfifo_fefifo +// END OF MODULE + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : dcfifo_async +// +// Description : Asynchronous Dual Clocks FIFO +// +// Limitation : +// +// Results expected: +// +//END_MODULE_NAME-------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module dcfifo_async (data, rdclk, wrclk, aclr, rdreq, wrreq, + rdfull, wrfull, rdempty, wrempty, rdusedw, wrusedw, q); + +// GLOBAL PARAMETER DECLARATION + parameter lpm_width = 1; + parameter lpm_widthu = 1; + parameter lpm_numwords = 2; + parameter delay_rdusedw = 1; + parameter delay_wrusedw = 1; + parameter rdsync_delaypipe = 3; + parameter wrsync_delaypipe = 3; + parameter intended_device_family = "APEX20KE"; + parameter lpm_showahead = "OFF"; + parameter underflow_checking = "ON"; + parameter overflow_checking = "ON"; + parameter use_eab = "ON"; + parameter add_ram_output_register = "OFF"; + +// INPUT PORT DECLARATION + input [lpm_width-1:0] data; + input rdclk; + input wrclk; + input aclr; + input wrreq; + input rdreq; + +// OUTPUT PORT DECLARATION + output rdfull; + output wrfull; + output rdempty; + output wrempty; + output [lpm_widthu-1:0] rdusedw; + output [lpm_widthu-1:0] wrusedw; + output [lpm_width-1:0] q; + +// INTERNAL REGISTERS DECLARATION + reg [lpm_width-1:0] mem_data [(1<<lpm_widthu)-1:0]; + reg [lpm_width-1:0] mem_data2 [(1<<lpm_widthu)-1:0]; + reg data_ready [(1<<lpm_widthu)-1:0]; + reg [2:0] data_delay_count [(1<<lpm_widthu)-1:0]; + reg [lpm_width-1:0] i_data_tmp; + reg [lpm_widthu-1:0] i_rdptr; + reg [lpm_widthu-1:0] i_wrptr; + reg [lpm_widthu-1:0] i_wrptr_tmp; + reg i_rden; + reg i_wren; + reg i_rdenclock; + reg i_wren_tmp; + reg i_showahead_flag; + reg i_showahead_flag1; + reg i_showahead_flag2; + reg i_showahead_flag3; + reg [lpm_widthu-1:0] i_wr_udwn; + reg [lpm_widthu-1:0] i_rd_udwn; + reg [lpm_widthu:0] i_rdusedw; + reg [lpm_widthu-1:0] i_wrusedw; + reg [lpm_width-1:0] i_q_tmp; + +// INTERNAL WIRE DECLARATION + wire w_rdempty; + wire w_wrempty; + wire w_rdfull; + wire w_wrfull; + wire [lpm_widthu-1:0] w_rdptrrg; + wire [lpm_widthu-1:0] w_wrdelaycycle; + wire [lpm_widthu-1:0] w_ws_nbrp; + wire [lpm_widthu-1:0] w_rs_nbwp; + wire [lpm_widthu-1:0] w_ws_dbrp; + wire [lpm_widthu-1:0] w_rs_dbwp; + wire [lpm_widthu-1:0] w_rd_dbuw; + wire [lpm_widthu-1:0] w_wr_dbuw; + wire [lpm_widthu-1:0] w_rdusedw; + wire [lpm_widthu-1:0] w_wrusedw; + +// INTERNAL TRI DECLARATION + tri0 aclr; + +// LOCAL INTEGER DECLARATION + integer i; + integer j; + integer k; + +// COMPONENT INSTANTIATION + ALTERA_DEVICE_FAMILIES dev (); + +// INITIAL CONSTRUCT BLOCK + initial + begin + if((lpm_showahead != "ON") && (lpm_showahead != "OFF")) + $display ("Error! lpm_showahead must be ON or OFF."); + if((underflow_checking != "ON") && (underflow_checking != "OFF")) + $display ("Error! underflow_checking must be ON or OFF."); + if((overflow_checking != "ON") && (overflow_checking != "OFF")) + $display ("Error! overflow_checking must be ON or OFF."); + if((use_eab != "ON") && (use_eab != "OFF")) + $display ("Error! use_eab must be ON or OFF."); + if((add_ram_output_register != "ON") && (add_ram_output_register != "OFF")) + $display ("Error! add_ram_output_register must be ON or OFF."); + if (dev.IS_VALID_FAMILY(intended_device_family) == 0) + $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family); + + for (i = 0; i < (1 << lpm_widthu); i = i + 1) + begin + mem_data[i] <= 0; + mem_data2[i] <= 0; + data_ready[i] <= 1'b0; + data_delay_count[i] <= 0; + end + + if ((add_ram_output_register == "OFF") && + (dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family))) + begin + for (i = 0; i < (1 << lpm_widthu); i = i + 1) + begin + mem_data2[i] <= {lpm_width{1'bx}}; + end + end + else + begin + for (i = 0; i < (1 << lpm_widthu); i = i + 1) + begin + mem_data2[i] <= 0; + end + end + + i_data_tmp <= 0; + i_rdptr <= 0; + i_wrptr <= 0; + i_wrptr_tmp <= 0; + i_wren_tmp <= 0; + i_wr_udwn <= 0; + i_rd_udwn <= 0; + i_rdusedw <= 0; + i_wrusedw <= 0; + i_q_tmp <= 0; + end + +// COMPONENT INSTANTIATIONS + // Delays & DFF Pipes + dcfifo_dffpipe DP_RDPTR_D ( + .d (i_rdptr), + .clock (i_rdenclock), + .aclr (aclr), + .q (w_rdptrrg)); + dcfifo_dffpipe DP_WRPTR_D ( + .d (i_wrptr), + .clock (wrclk), + .aclr (aclr), + .q (w_wrdelaycycle)); + defparam + DP_RDPTR_D.lpm_delay = 0, + DP_RDPTR_D.lpm_width = lpm_widthu, + DP_WRPTR_D.lpm_delay = 1, + DP_WRPTR_D.lpm_width = lpm_widthu; + + dcfifo_dffpipe DP_WS_NBRP ( + .d (w_rdptrrg), + .clock (wrclk), + .aclr (aclr), + .q (w_ws_nbrp)); + dcfifo_dffpipe DP_RS_NBWP ( + .d (w_wrdelaycycle), + .clock (rdclk), + .aclr (aclr), + .q (w_rs_nbwp)); + dcfifo_dffpipe DP_WS_DBRP ( + .d (w_ws_nbrp), + .clock (wrclk), + .aclr (aclr), + .q (w_ws_dbrp)); + dcfifo_dffpipe DP_RS_DBWP ( + .d (w_rs_nbwp), + .clock (rdclk), + .aclr (aclr), + .q (w_rs_dbwp)); + defparam + DP_WS_NBRP.lpm_delay = wrsync_delaypipe, + DP_WS_NBRP.lpm_width = lpm_widthu, + DP_RS_NBWP.lpm_delay = rdsync_delaypipe, + DP_RS_NBWP.lpm_width = lpm_widthu, + DP_WS_DBRP.lpm_delay = 1, // gray_delaypipe + DP_WS_DBRP.lpm_width = lpm_widthu, + DP_RS_DBWP.lpm_delay = 1, // gray_delaypipe + DP_RS_DBWP.lpm_width = lpm_widthu; + + dcfifo_dffpipe DP_WRUSEDW ( + .d (i_wr_udwn), + .clock (wrclk), + .aclr (aclr), + .q (w_wrusedw)); + dcfifo_dffpipe DP_RDUSEDW ( + .d (i_rd_udwn), + .clock (rdclk), + .aclr (aclr), + .q (w_rdusedw)); + dcfifo_dffpipe DP_WR_DBUW ( + .d (i_wr_udwn), + .clock (wrclk), + .aclr (aclr), + .q (w_wr_dbuw)); + dcfifo_dffpipe DP_RD_DBUW ( + .d (i_rd_udwn), + .clock (rdclk), + .aclr (aclr), + .q (w_rd_dbuw)); + defparam + DP_WRUSEDW.lpm_delay = delay_wrusedw, + DP_WRUSEDW.lpm_width = lpm_widthu, + DP_RDUSEDW.lpm_delay = delay_rdusedw, + DP_RDUSEDW.lpm_width = lpm_widthu, + DP_WR_DBUW.lpm_delay = 1, // wrusedw_delaypipe + DP_WR_DBUW.lpm_width = lpm_widthu, + DP_RD_DBUW.lpm_delay = 1, // rdusedw_delaypipe + DP_RD_DBUW.lpm_width = lpm_widthu; + + // Empty/Full + dcfifo_fefifo WR_FE ( + .usedw_in (w_wr_dbuw), + .wreq (wrreq), + .rreq (rdreq), + .clock (wrclk), + .aclr (aclr), + .empty (w_wrempty), + .full (w_wrfull)); + dcfifo_fefifo RD_FE ( + .usedw_in (w_rd_dbuw), + .rreq (rdreq), + .wreq(wrreq), + .clock (rdclk), + .aclr (aclr), + .empty (w_rdempty), + .full (w_rdfull)); + defparam + WR_FE.lpm_widthad = lpm_widthu, + WR_FE.lpm_numwords = lpm_numwords, + WR_FE.underflow_checking = underflow_checking, + WR_FE.overflow_checking = overflow_checking, + WR_FE.lpm_mode = "WRITE", + RD_FE.lpm_widthad = lpm_widthu, + RD_FE.lpm_numwords = lpm_numwords, + RD_FE.underflow_checking = underflow_checking, + RD_FE.overflow_checking = overflow_checking, + RD_FE.lpm_mode = "READ"; + +// ALWAYS CONSTRUCT BLOCK + always @(posedge aclr) + begin + i_rdptr <= 0; + i_wrptr <= 0; + if (!(dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family)) || + (use_eab == "OFF")) + begin + if (lpm_showahead == "ON") + i_q_tmp <= mem_data[0]; + else + i_q_tmp <= 0; + end + else if ((add_ram_output_register == "ON") && + (dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family))) + begin + if (lpm_showahead == "OFF") + i_q_tmp <= 0; + else + begin + i_q_tmp <= {lpm_width{1'bx}}; + + for (j = 0; j < (1<<lpm_widthu); j = j + 1) + begin + data_ready[i_wrptr_tmp] <= 1'b0; + data_delay_count[k] <= 0; + end + end + end + end // @(posedge aclr) + + // FIFOram + always @(rdreq or w_rdempty) + begin + if (underflow_checking == "OFF") + i_rden <= rdreq; + else + i_rden <= rdreq && !w_rdempty; + end // @(rdreq or w_rdempty) + + always @(wrreq or w_wrfull) + begin + if (overflow_checking == "OFF") + i_wren <= wrreq; + else + i_wren <= wrreq && !w_wrfull; + end // @(wrreq or w_wrfull) + + always @(posedge wrclk) + begin + if (aclr && (!(dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family)) || + (add_ram_output_register == "ON") || (use_eab == "OFF"))) + begin + i_data_tmp <= 0; + i_wrptr_tmp <= 0; + i_wren_tmp <= 0; + end + else if (wrclk && ($time > 0)) + begin + i_data_tmp <= data; + i_wrptr_tmp <= i_wrptr; + i_wren_tmp <= i_wren; + + if (i_wren) + begin + if (~aclr && ((i_wrptr < (1<<lpm_widthu)-1) || (overflow_checking == "OFF"))) + i_wrptr <= i_wrptr + 1; + else + i_wrptr <= 0; + + if (use_eab == "OFF") + begin + mem_data[i_wrptr] <= data; + + if (lpm_showahead == "ON") + i_showahead_flag3 <= 1'b1; + end + end + end + end // @(posedge wrclk) + + always @(negedge wrclk) + begin + if ((~wrclk && (use_eab == "ON")) && ($time > 0)) + begin + if (i_wren_tmp) + begin + mem_data[i_wrptr_tmp] <= i_data_tmp; + data_ready[i_wrptr_tmp] <= 1'b0; + end + + if ((lpm_showahead == "ON") && + (!(dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family)))) + i_showahead_flag3 <= 1'b1; + end + end // @(negedge wrclk) + + always @(posedge rdclk) + begin + + if (rdclk && ($time > 0)) + begin + if ((lpm_showahead == "ON") && (add_ram_output_register == "ON") && + (dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family))) + begin + for (k = 0; k < (1<<lpm_widthu); k = k + 1) + begin + if (data_ready[k] == 1'b0) + data_delay_count[k] <= data_delay_count[k] + 1; + + if (data_delay_count[k] == (rdsync_delaypipe+2)) + begin + data_ready[k] = 1'b1; + data_delay_count[k] <= 0; + end + end + + if (~aclr) + begin + i_showahead_flag3 <= 1'b1; + end + end + + end + + if (aclr && (!(dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family)) || + (use_eab == "OFF"))) + begin + if (lpm_showahead == "ON") + i_q_tmp <= mem_data[0]; + else + i_q_tmp <= 0; + end + else if (aclr && (add_ram_output_register == "ON") && + (dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family))) + begin + if (lpm_showahead == "ON") + i_q_tmp <= {lpm_width{1'bx}}; + else + i_q_tmp <= 0; + end + else if (rdclk && i_rden && ($time > 0)) + begin + if (~aclr && ((i_rdptr < (1<<lpm_widthu)-1) || (underflow_checking == "OFF"))) + i_rdptr <= i_rdptr + 1; + else + i_rdptr <= 0; + + if (lpm_showahead == "ON") + i_showahead_flag3 <= 1'b1; + else + i_q_tmp <= mem_data[i_rdptr]; + end + end // @(posedge rdclk) + + always @(i_showahead_flag3) + begin + i_showahead_flag2 <= i_showahead_flag3; + end + + always @(i_showahead_flag2) + begin + i_showahead_flag1 <= i_showahead_flag2; + end + + always @(i_showahead_flag1) + begin + i_showahead_flag <= i_showahead_flag1; + end + + + always @(posedge i_showahead_flag) + begin + if ((lpm_showahead == "ON") && (add_ram_output_register == "ON") && + (dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family))) + begin + if (w_rdempty == 1'b0) + begin + if (data_ready[i_rdptr] == 1'b1) + begin + i_q_tmp <= mem_data[i_rdptr]; + mem_data2[i_rdptr] <= mem_data[i_rdptr]; + end + else + i_q_tmp <= mem_data2[i_rdptr]; + end + end + else + i_q_tmp <= mem_data[i_rdptr]; + i_showahead_flag3 <= 1'b0; + end // @(posedge i_showahead_flag) + + // Delays & DFF Pipes + always @(negedge rdclk) + begin + i_rdenclock <= 0; + end // @(negedge rdclk) + + always @(posedge rdclk) + begin + if (i_rden) + i_rdenclock <= 1; + end // @(posedge rdclk) + + always @(i_wrptr or w_ws_dbrp) + begin + i_wr_udwn <= i_wrptr - w_ws_dbrp; + end // @(i_wrptr or w_ws_dbrp) + + always @(i_rdptr or w_rs_dbwp) + begin + i_rd_udwn <= w_rs_dbwp - i_rdptr; + end // @(i_rdptr or w_rs_dbwp) + +// CONTINOUS ASSIGNMENT + assign q = i_q_tmp; + assign wrfull = w_wrfull; + assign rdfull = w_rdfull; + assign wrempty = w_wrempty; + assign rdempty = w_rdempty; + assign wrusedw = w_wrusedw; + assign rdusedw = w_rdusedw; + +endmodule // dcfifo_async +// END OF MODULE + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : dcfifo_sync +// +// Description : Synchronous Dual Clock FIFO +// +// Limitation : +// +// Results expected: +// +//END_MODULE_NAME-------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module dcfifo_sync (data, rdclk, wrclk, aclr, rdreq, wrreq, + rdfull, wrfull, rdempty, wrempty, rdusedw, wrusedw, q); + +// GLOBAL PARAMETER DECLARATION + parameter lpm_width = 1; + parameter lpm_widthu = 1; + parameter lpm_numwords = 2; + parameter intended_device_family = "APEX20KE"; + parameter lpm_showahead = "OFF"; + parameter underflow_checking = "ON"; + parameter overflow_checking = "ON"; + parameter use_eab = "ON"; + parameter add_ram_output_register = "OFF"; + +// INPUT PORT DECLARATION + input [lpm_width-1:0] data; + input rdclk; + input wrclk; + input aclr; + input rdreq; + input wrreq; + +// OUTPUT PORT DECLARATION + output rdfull; + output wrfull; + output rdempty; + output wrempty; + output [lpm_widthu-1:0] rdusedw; + output [lpm_widthu-1:0] wrusedw; + output [lpm_width-1:0] q; + +// INTERNAL REGISTERS DECLARATION + reg [lpm_width-1:0] mem_data [(1<<lpm_widthu)-1:0]; + reg [lpm_width-1:0] i_data_tmp; + reg [lpm_widthu:0] i_rdptr; + reg [lpm_widthu:0] i_wrptr; + reg [lpm_widthu-1:0] i_wrptr_tmp; + reg i_rden; + reg i_wren; + reg i_wren_tmp; + reg i_showahead_flag; + reg i_showahead_flag2; + reg i_rdempty; + reg i_wrempty; + reg i_rdfull; + reg i_wrfull; + reg [lpm_widthu:0] i_rdusedw; + reg [lpm_widthu:0] i_wrusedw; + reg [lpm_width-1:0] i_q_tmp; + +// INTERNAL WIRE DECLARATION + wire [lpm_widthu:0] w_rdptr_s; + wire [lpm_widthu:0] w_wrptr_s; + wire [lpm_widthu:0] w_wrptr_r; + +// LOCAL INTEGER DECLARATION + integer cnt_mod; + integer i; + +// COMPONENT INSTANTIATION + ALTERA_DEVICE_FAMILIES dev (); + +// INITIAL CONSTRUCT BLOCK + initial + begin + if ((lpm_showahead != "ON") && (lpm_showahead != "OFF")) + $display ("Error! LPM_SHOWAHEAD must be ON or OFF."); + if ((underflow_checking != "ON") && (underflow_checking != "OFF")) + $display ("Error! UNDERFLOW_CHECKING must be ON or OFF."); + if ((overflow_checking != "ON") && (overflow_checking != "OFF")) + $display ("Error! OVERFLOW_CHECKING must be ON or OFF."); + if ((use_eab != "ON") && (use_eab != "OFF")) + $display ("Error! USE_EAB must be ON or OFF."); + if (lpm_numwords > (1 << lpm_widthu)) + $display ("Error! LPM_NUMWORDS must be less than or equal to 2**LPM_WIDTHU."); + if((add_ram_output_register != "ON") && (add_ram_output_register != "OFF")) + $display ("Error! add_ram_output_register must be ON or OFF."); + if (dev.IS_VALID_FAMILY(intended_device_family) == 0) + $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family); + + for (i = 0; i < (1 << lpm_widthu); i = i + 1) + mem_data[i] <= 0; + i_data_tmp <= 0; + i_rdptr <= 0; + i_wrptr <= 0; + i_wrptr_tmp <= 0; + i_wren_tmp <= 0; + + i_rdempty <= 1; + i_wrempty <= 1; + i_rdfull <= 0; + i_wrfull <= 0; + i_rdusedw <= 0; + i_wrusedw <= 0; + i_q_tmp <= 0; + + if (lpm_numwords == (1 << lpm_widthu)) + cnt_mod <= 1 << (lpm_widthu + 1); + else + cnt_mod <= 1 << lpm_widthu; + end + +// COMPONENT INSTANTIATIONS + dcfifo_dffpipe RDPTR_D ( + .d (i_rdptr), + .clock (wrclk), + .aclr (aclr), + .q (w_rdptr_s)); + dcfifo_dffpipe WRPTR_D ( + .d (i_wrptr), + .clock (wrclk), + .aclr (aclr), + .q (w_wrptr_r)); + dcfifo_dffpipe WRPTR_E ( + .d (w_wrptr_r), + .clock (rdclk), + .aclr (aclr), + .q (w_wrptr_s)); + defparam + RDPTR_D.lpm_delay = 1, + RDPTR_D.lpm_width = lpm_widthu + 1, + WRPTR_D.lpm_delay = 1, + WRPTR_D.lpm_width = lpm_widthu + 1, + WRPTR_E.lpm_delay = 1, + WRPTR_E.lpm_width = lpm_widthu + 1; + +// ALWAYS CONSTRUCT BLOCK + always @(posedge aclr) + begin + i_rdptr <= 0; + i_wrptr <= 0; + if (!(dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family)) || + ((add_ram_output_register == "ON") && (use_eab == "OFF"))) + if (lpm_showahead == "ON") + i_q_tmp <= mem_data[0]; + else + i_q_tmp <= 0; + end // @(posedge aclr) + + // FIFOram + always @(rdreq or i_rdempty) + begin + if (underflow_checking == "OFF") + i_rden <= rdreq; + else + i_rden <= rdreq && !i_rdempty; + end // @(rdreq or i_rdempty) + + always @(wrreq or i_wrfull) + begin + if (overflow_checking == "OFF") + i_wren <= wrreq; + else + i_wren <= wrreq && !i_wrfull; + end // @(wrreq or i_wrfull) + + always @(posedge wrclk) + begin + if (aclr && (!(dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family)) || + ((add_ram_output_register == "ON") && (use_eab == "OFF")))) + begin + i_data_tmp <= 0; + i_wrptr_tmp <= 0; + i_wren_tmp <= 0; + end + else if (wrclk && ($time > 0)) + begin + i_data_tmp <= data; + i_wrptr_tmp <= i_wrptr[lpm_widthu-1:0]; + i_wren_tmp <= i_wren; + + if (i_wren) + begin + if (~aclr && (i_wrptr < cnt_mod - 1)) + i_wrptr <= i_wrptr + 1; + else + i_wrptr <= 0; + + if (use_eab == "OFF") + begin + mem_data[i_wrptr[lpm_widthu-1:0]] <= data; + + if (lpm_showahead == "ON") + i_showahead_flag2 <= 1'b1; + end + end + end + end // @(posedge wrclk) + + always @(negedge wrclk) + begin + if ((~wrclk && (use_eab == "ON")) && ($time > 0)) + begin + if (i_wren_tmp) + begin + mem_data[i_wrptr_tmp] <= i_data_tmp; + end + + if ((lpm_showahead == "ON") && + (!( dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family)))) + i_showahead_flag2 <= 1'b1; + end + end // @(negedge wrclk) + + always @(posedge rdclk) + begin + if (aclr && (!(dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family)) || + ((add_ram_output_register == "ON") && (use_eab == "OFF")))) + begin + if (lpm_showahead == "ON") + i_q_tmp <= mem_data[0]; + else + i_q_tmp <= 0; + end + else if (rdclk && i_rden && ($time > 0)) + begin + if (~aclr && (i_rdptr < cnt_mod - 1)) + i_rdptr <= i_rdptr + 1; + else + i_rdptr <= 0; + + if ((lpm_showahead == "ON") && (!((use_eab == "ON") && + (dev.IS_FAMILY_STRATIX(intended_device_family) || + dev.IS_FAMILY_STRATIXGX(intended_device_family) || + dev.IS_FAMILY_CYCLONE(intended_device_family))))) + i_showahead_flag2 <= 1'b1; + else + i_q_tmp <= mem_data[i_rdptr[lpm_widthu-1:0]]; + end + end // @(rdclk) + + always @(posedge i_showahead_flag) + begin + i_q_tmp <= mem_data[i_rdptr[lpm_widthu-1:0]]; + i_showahead_flag2 <= 1'b0; + end // @(posedge i_showahead_flag) + + always @(i_showahead_flag2) + begin + i_showahead_flag <= i_showahead_flag2; + end // @(i_showahead_flag2) + + // Usedw, Empty, Full + always @(i_rdptr or w_wrptr_s or cnt_mod) + begin + if (w_wrptr_s >= i_rdptr) + i_rdusedw <= w_wrptr_s - i_rdptr; + else + i_rdusedw <= w_wrptr_s + cnt_mod - i_rdptr; + end // @(i_rdptr or w_wrptr_s) + + always @(i_wrptr or w_rdptr_s or cnt_mod) + begin + if (i_wrptr >= w_rdptr_s) + i_wrusedw <= i_wrptr - w_rdptr_s; + else + i_wrusedw <= i_wrptr + cnt_mod - w_rdptr_s; + end // @(i_wrptr or w_rdptr_s) + + always @(i_rdusedw) + begin + if (i_rdusedw == 0) + i_rdempty <= 1; + else + i_rdempty <= 0; + + if (((lpm_numwords == (1 << lpm_widthu)) && i_rdusedw[lpm_widthu]) || + ((lpm_numwords < (1 << lpm_widthu)) && (i_rdusedw == lpm_numwords))) + i_rdfull <= 1; + else + i_rdfull <= 0; + end // @(i_rdusedw) + + always @(i_wrusedw) + begin + if (i_wrusedw == 0) + i_wrempty <= 1; + else + i_wrempty <= 0; + + if (((lpm_numwords == (1 << lpm_widthu)) && i_wrusedw[lpm_widthu]) || + ((lpm_numwords < (1 << lpm_widthu)) && (i_wrusedw == lpm_numwords))) + i_wrfull <= 1; + else + i_wrfull <= 0; + end // @(i_wrusedw) + +// CONTINOUS ASSIGNMENT + assign rdempty = i_rdempty; + assign wrempty = i_wrempty; + assign rdfull = i_rdfull; + assign wrfull = i_wrfull; + assign wrusedw = i_wrusedw[lpm_widthu-1:0]; + assign rdusedw = i_rdusedw[lpm_widthu-1:0]; + assign q = i_q_tmp; + +endmodule // dcfifo_sync +// END OF MODULE + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : dcfifo_low_latency +// +// Description : Dual Clocks FIFO with lowest latency. This fifo implements +// the fifo behavior for Stratix II, Cyclone II and Stratix +// showahead area mode (LPM_SHOWAHEAD=ON, ADD_RAM_OUTPUT_REGISTER=OFF) +// +// Limitation : +// +// Results expected: +// +//END_MODULE_NAME-------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module dcfifo_low_latency (data, rdclk, wrclk, aclr, rdreq, wrreq, + rdfull, wrfull, rdempty, wrempty, rdusedw, wrusedw, q); + +// GLOBAL PARAMETER DECLARATION + parameter lpm_width = 1; + parameter lpm_widthu = 1; + parameter lpm_numwords = 2; + parameter delay_rdusedw = 2; + parameter delay_wrusedw = 2; + parameter rdsync_delaypipe = 1; + parameter wrsync_delaypipe = 1; + parameter intended_device_family = "Stratix"; + parameter lpm_showahead = "OFF"; + parameter underflow_checking = "ON"; + parameter overflow_checking = "ON"; + +input [lpm_width-1:0] data; + input rdclk; + input wrclk; + input aclr; + input rdreq; + input wrreq; + +// OUTPUT PORT DECLARATION + output rdfull; + output wrfull; + output rdempty; + output wrempty; + output [lpm_widthu-1:0] rdusedw; + output [lpm_widthu-1:0] wrusedw; + output [lpm_width-1:0] q; + +// INTERNAL REGISTERS DECLARATION + reg [lpm_width-1:0] mem_data [(1<<lpm_widthu)-1:0]; + reg [lpm_width-1:0] i_data_tmp; + reg [lpm_widthu-1:0] i_rdptr_g; + reg [lpm_widthu-1:0] i_wrptr_g; + reg [lpm_widthu-1:0] i_wrptr_g_tmp; + reg [lpm_widthu-1:0] i_wrptr_g1; + reg [lpm_widthu-1:0] i_rdptr_g1p; + reg [lpm_widthu-1:0] i_delayed_wrptr_g; + + reg i_rden; + reg i_wren; + reg i_wren_tmp; + reg i_rdempty; + reg i_wrempty; + reg i_rdempty_rreg; + reg i_rdfull; + reg i_wrfull; + reg i_wrfull_wreg; + reg [lpm_widthu-1:0] i_rdusedw_tmp; + reg [lpm_widthu-1:0] i_wrusedw_tmp; + reg [lpm_width-1:0] i_q; + reg i_q_is_registered; + +// INTERNAL WIRE DECLARATION + wire [lpm_widthu-1:0] i_rs_dgwp; + wire [lpm_widthu-1:0] i_ws_dgrp; + wire [lpm_widthu-1:0] i_rdusedw; + wire [lpm_widthu-1:0] i_wrusedw; + +// INTERNAL TRI DECLARATION + tri0 aclr; + +// LOCAL INTEGER DECLARATION + integer cnt_mod; + integer i; + +// COMPONENT INSTANTIATION + ALTERA_DEVICE_FAMILIES dev (); + +// INITIAL CONSTRUCT BLOCK + initial + begin + if ((lpm_showahead != "ON") && (lpm_showahead != "OFF")) + $display ("Error! LPM_SHOWAHEAD must be ON or OFF."); + if ((underflow_checking != "ON") && (underflow_checking != "OFF")) + $display ("Error! UNDERFLOW_CHECKING must be ON or OFF."); + if ((overflow_checking != "ON") && (overflow_checking != "OFF")) + $display ("Error! OVERFLOW_CHECKING must be ON or OFF."); + if (lpm_numwords > (1 << lpm_widthu)) + $display ("Error! LPM_NUMWORDS must be less than or equal to 2**LPM_WIDTHU."); + if (dev.IS_VALID_FAMILY(intended_device_family) == 0) + $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family); + + for (i = 0; i < (1 << lpm_widthu); i = i + 1) + mem_data[i] <= {lpm_width{1'bx}}; + i_data_tmp <= 0; + i_wren_tmp <= 0; + i_rdptr_g <= 0; + i_rdptr_g1p <= 1; + i_wrptr_g <= 0; + i_wrptr_g_tmp <= 0; + i_wrptr_g1 <= 1; + i_delayed_wrptr_g <= 0; + i_rdempty <= 1; + i_wrempty <= 1; + i_rdempty_rreg <= 1; + i_rdfull <= 0; + i_wrfull <= 0; + i_wrfull_wreg <= 0; + i_q <= {lpm_width{1'bx}}; + + if (lpm_numwords == (1 << lpm_widthu)) + cnt_mod <= 1 << (lpm_widthu + 1); + else + cnt_mod <= 1 << lpm_widthu; + + if ((lpm_showahead == "OFF") && + ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) || + (dev.IS_FAMILY_CYCLONEII(intended_device_family)))) + i_q_is_registered <= 1'b1; + else + i_q_is_registered <= 1'b0; + end + +// COMPONENT INSTANTIATIONS + dcfifo_dffpipe DP_WS_DGRP ( + .d (i_rdptr_g), + .clock (wrclk), + .aclr (aclr), + .q (i_ws_dgrp)); + defparam + DP_WS_DGRP.lpm_delay = wrsync_delaypipe, + DP_WS_DGRP.lpm_width = lpm_widthu; + + dcfifo_dffpipe DP_RS_DGWP ( + .d (i_delayed_wrptr_g), + .clock (rdclk), + .aclr (aclr), + .q (i_rs_dgwp)); + defparam + DP_RS_DGWP.lpm_delay = rdsync_delaypipe, + DP_RS_DGWP.lpm_width = lpm_widthu; + + dcfifo_dffpipe DP_RDUSEDW ( + .d (i_rdusedw_tmp), + .clock (rdclk), + .aclr (aclr), + .q (i_rdusedw)); + dcfifo_dffpipe DP_WRUSEDW ( + .d (i_wrusedw_tmp), + .clock (wrclk), + .aclr (aclr), + .q (i_wrusedw)); + defparam + DP_RDUSEDW.lpm_delay = (delay_rdusedw > 2) ? 2 : delay_rdusedw, + DP_RDUSEDW.lpm_width = lpm_widthu, + DP_WRUSEDW.lpm_delay = (delay_wrusedw > 2) ? 2 : delay_wrusedw, + DP_WRUSEDW.lpm_width = lpm_widthu; + +// ALWAYS CONSTRUCT BLOCK + always @(posedge aclr) + begin + i_data_tmp <= 0; + i_wren_tmp <= 0; + i_rdptr_g <= 0; + i_rdptr_g1p <= 1; + i_wrptr_g <= 0; + i_wrptr_g_tmp <= 0; + i_wrptr_g1 <= 1; + i_delayed_wrptr_g <= 0; + i_rdempty <= 1; + i_wrempty <= 1; + i_rdempty_rreg <= 1; + i_rdfull <= 0; + i_wrfull <= 0; + i_wrfull_wreg <= 0; + if(i_q_is_registered) + i_q <= 0; + end // @(posedge aclr) + + // FIFOram + always @(rdreq or i_rdempty) + begin + if (underflow_checking == "OFF") + i_rden <= rdreq; + else + i_rden <= rdreq && !i_rdempty; + end // @(rdreq or i_rdempty) + + always @(wrreq or i_wrfull) + begin + if (overflow_checking == "OFF") + i_wren <= wrreq; + else + i_wren <= wrreq && !i_wrfull; + end // @(wrreq or i_wrfull) + + always @(posedge wrclk) + begin + i_data_tmp <= data; + i_wrptr_g_tmp <= i_wrptr_g; + i_wren_tmp <= i_wren; + + if (~aclr && ($time > 0)) + begin + if (i_wren) + begin + if (i_wrptr_g1 < cnt_mod - 1) + i_wrptr_g1 <= i_wrptr_g1 + 1; + else + i_wrptr_g1 <= 0; + + i_wrptr_g <= i_wrptr_g1; + end + i_delayed_wrptr_g <= i_wrptr_g; + end + end // @(wrclk) + + always @(negedge wrclk) + begin + if (i_wren_tmp && ($time > 0)) + mem_data[i_wrptr_g_tmp] <= i_data_tmp; + + end // @(wrclk) + + always @(posedge rdclk) + begin + if(~aclr) + begin + if (i_rden && ($time > 0)) + begin + if (i_rdptr_g1p < cnt_mod - 1) + i_rdptr_g1p <= i_rdptr_g1p + 1; + else + i_rdptr_g1p <= 0; + + i_rdptr_g <= i_rdptr_g1p; + end + end + end + + always @(posedge rdclk) + begin + if ((! i_q_is_registered) && ($time > 0)) + begin + if (i_rdempty == 1'b1) + i_q <= mem_data[i_rdptr_g]; + else if (i_rden) + i_q <= mem_data[i_rdptr_g1p]; + end + else if (~aclr && i_rden && ($time > 0)) + i_q <= mem_data[i_rdptr_g]; + end + + // Usedw, Empty, Full + always @(i_wrptr_g or i_ws_dgrp or cnt_mod) + begin + if (i_wrptr_g < i_ws_dgrp) + i_wrusedw_tmp <= cnt_mod + i_wrptr_g - i_ws_dgrp; + else + i_wrusedw_tmp <= i_wrptr_g - i_ws_dgrp; + end // @(i_wrptr_g or i_ws_dgrp) + + always @(i_rdptr_g or i_rs_dgwp or cnt_mod) + begin + if (i_rs_dgwp < i_rdptr_g) + i_rdusedw_tmp <= cnt_mod + i_rs_dgwp - i_rdptr_g; + else + i_rdusedw_tmp <= i_rs_dgwp - i_rdptr_g; + end // @(i_wrptr_g or i_rs_dgwp) + + always @(i_wrptr_g1 or i_ws_dgrp) + begin + if (i_wrptr_g1 == i_ws_dgrp) + i_wrfull <= 1; + else + i_wrfull <= 0; + end // @(i_wrptr_g1 or i_ws_dgrp) + + always @(i_rdptr_g or i_rs_dgwp) + begin + if (i_rdptr_g == i_rs_dgwp) + i_rdempty <= 1; + else + i_rdempty <= 0; + end // @(i_rdptr_g or i_rs_dgwp) + + always @(posedge rdclk) + begin + i_rdfull <= i_wrfull_wreg; + i_rdempty_rreg <= i_rdempty; + end // @(posedge rdclk) + + always @(posedge wrclk) + begin + i_wrempty <= i_rdempty_rreg; + i_wrfull_wreg <= i_wrfull; + end // @(posedge wrclk) + +// CONTINOUS ASSIGNMENT + assign rdempty = i_rdempty; + assign wrempty = i_wrempty; + assign rdfull = i_rdfull; + assign wrfull = i_wrfull; + assign wrusedw = i_wrusedw[lpm_widthu-1:0]; + assign rdusedw = i_rdusedw[lpm_widthu-1:0]; + assign q = i_q; + +endmodule // dcfifo_low_latency +// END OF MODULE + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module Name : dcfifo +// +// Description : Dual Clocks FIFO +// +// Limitation : +// +// Results expected: +// +//END_MODULE_NAME-------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module dcfifo ( data, rdclk, wrclk, aclr, rdreq, wrreq, + rdfull, wrfull, rdempty, wrempty, rdusedw, wrusedw, q); + +// GLOBAL PARAMETER DECLARATION + parameter lpm_width = 1; + parameter lpm_widthu = 1; + parameter lpm_numwords = 2; + parameter delay_rdusedw = 1; + parameter delay_wrusedw = 1; + parameter rdsync_delaypipe = 3; + parameter wrsync_delaypipe = 3; + parameter intended_device_family = "APEX20KE"; + parameter lpm_showahead = "OFF"; + parameter underflow_checking = "ON"; + parameter overflow_checking = "ON"; + parameter clocks_are_synchronized = "FALSE"; + parameter use_eab = "ON"; + parameter add_ram_output_register = "OFF"; + parameter add_width = 1; + parameter lpm_hint = "USE_EAB=ON"; + parameter lpm_type = "dcfifo"; + +// INPUT PORT DECLARATION + input [lpm_width-1:0] data; + input rdclk; + input wrclk; + input aclr; + input rdreq; + input wrreq; + +// OUTPUT PORT DECLARATION + output rdfull; + output wrfull; + output rdempty; + output wrempty; + output [lpm_widthu-1:0] rdusedw; + output [lpm_widthu-1:0] wrusedw; + output [lpm_width-1:0] q; + +// INTERNAL WIRE DECLARATION + wire w_rdfull_s; + wire w_wrfull_s; + wire w_rdempty_s; + wire w_wrempty_s; + wire w_rdfull_a; + wire w_wrfull_a; + wire w_rdempty_a; + wire w_wrempty_a; + wire w_rdfull_l; + wire w_wrfull_l; + wire w_rdempty_l; + wire w_wrempty_l; + wire [lpm_widthu-1:0] w_rdusedw_s; + wire [lpm_widthu-1:0] w_wrusedw_s; + wire [lpm_widthu-1:0] w_rdusedw_a; + wire [lpm_widthu-1:0] w_wrusedw_a; + wire [lpm_widthu-1:0] w_rdusedw_l; + wire [lpm_widthu-1:0] w_wrusedw_l; + wire [lpm_width-1:0] w_q_s; + wire [lpm_width-1:0] w_q_a; + wire [lpm_width-1:0] w_q_l; + +// INTERNAL TRI DECLARATION + tri0 aclr; + +// COMPONENT INSTANTIATIONS + ALTERA_DEVICE_FAMILIES dev (); + + dcfifo_sync SYNC ( + .data (data), + .rdclk (rdclk), + .wrclk (wrclk), + .aclr (aclr), + .rdreq (rdreq), + .wrreq (wrreq), + .rdfull (w_rdfull_s), + .wrfull (w_wrfull_s), + .rdempty (w_rdempty_s), + .wrempty (w_wrempty_s), + .rdusedw (w_rdusedw_s), + .wrusedw (w_wrusedw_s), + .q (w_q_s)); + defparam + SYNC.lpm_width = lpm_width, + SYNC.lpm_widthu = lpm_widthu, + SYNC.lpm_numwords = lpm_numwords, + SYNC.intended_device_family = intended_device_family, + SYNC.lpm_showahead = lpm_showahead, + SYNC.underflow_checking = underflow_checking, + SYNC.overflow_checking = overflow_checking, + SYNC.use_eab = use_eab, + SYNC.add_ram_output_register = add_ram_output_register; + + dcfifo_async ASYNC ( + .data (data), + .rdclk (rdclk), + .wrclk (wrclk), + .aclr (aclr), + .rdreq (rdreq), + .wrreq (wrreq), + .rdfull (w_rdfull_a), + .wrfull (w_wrfull_a), + .rdempty (w_rdempty_a), + .wrempty (w_wrempty_a), + .rdusedw (w_rdusedw_a), + .wrusedw (w_wrusedw_a), + .q (w_q_a) ); + defparam + ASYNC.lpm_width = lpm_width, + ASYNC.lpm_widthu = lpm_widthu, + ASYNC.lpm_numwords = lpm_numwords, + ASYNC.delay_rdusedw = delay_rdusedw, + ASYNC.delay_wrusedw = delay_wrusedw, + ASYNC.rdsync_delaypipe = rdsync_delaypipe, + ASYNC.wrsync_delaypipe = wrsync_delaypipe, + ASYNC.intended_device_family = intended_device_family, + ASYNC.lpm_showahead = lpm_showahead, + ASYNC.underflow_checking = underflow_checking, + ASYNC.overflow_checking = overflow_checking, + ASYNC.use_eab = use_eab, + ASYNC.add_ram_output_register = add_ram_output_register; + + dcfifo_low_latency LOWLATENCY ( + .data (data), + .rdclk (rdclk), + .wrclk (wrclk), + .aclr (aclr), + .rdreq (rdreq), + .wrreq (wrreq), + .rdfull (w_rdfull_l), + .wrfull (w_wrfull_l), + .rdempty (w_rdempty_l), + .wrempty (w_wrempty_l), + .rdusedw (w_rdusedw_l), + .wrusedw (w_wrusedw_l), + .q (w_q_l) ); + defparam + LOWLATENCY.lpm_width = lpm_width, + LOWLATENCY.lpm_widthu = lpm_widthu, + LOWLATENCY.lpm_numwords = lpm_numwords, + LOWLATENCY.delay_rdusedw = delay_rdusedw, + LOWLATENCY.delay_wrusedw = delay_wrusedw, + LOWLATENCY.rdsync_delaypipe = (rdsync_delaypipe > 3 ? rdsync_delaypipe - 2 : 1), + LOWLATENCY.wrsync_delaypipe = (wrsync_delaypipe > 3 ? wrsync_delaypipe - 2 : 1), + LOWLATENCY.intended_device_family = intended_device_family, + LOWLATENCY.lpm_showahead = lpm_showahead, + LOWLATENCY.underflow_checking = underflow_checking, + LOWLATENCY.overflow_checking = overflow_checking; + +// CONTINOUS ASSIGNMENT + assign rdfull = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) || + (dev.FEATURE_FAMILY_STRATIX(intended_device_family) && + (lpm_showahead == "ON") && + (add_ram_output_register == "OFF"))) && + (use_eab == "ON")) ? w_rdfull_l : + (clocks_are_synchronized == "TRUE") ? w_rdfull_s : w_rdfull_a; + + assign wrfull = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) || + (dev.FEATURE_FAMILY_STRATIX(intended_device_family) && + (lpm_showahead == "ON") && + (add_ram_output_register == "OFF"))) && + (use_eab == "ON")) ? w_wrfull_l : + (clocks_are_synchronized == "TRUE") ? w_wrfull_s : w_wrfull_a; + + assign rdempty = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) || + (dev.FEATURE_FAMILY_STRATIX(intended_device_family) && + (lpm_showahead == "ON") && + (add_ram_output_register == "OFF"))) && + (use_eab == "ON")) ? w_rdempty_l : + (clocks_are_synchronized == "TRUE") ? w_rdempty_s : w_rdempty_a; + + assign wrempty = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) || + (dev.FEATURE_FAMILY_STRATIX(intended_device_family) && + (lpm_showahead == "ON") && + (add_ram_output_register == "OFF"))) && + (use_eab == "ON")) ? w_wrempty_l : + (clocks_are_synchronized == "TRUE") ? w_wrempty_s : w_wrempty_a; + + assign rdusedw = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) || + (dev.FEATURE_FAMILY_STRATIX(intended_device_family) && + (lpm_showahead == "ON") && + (add_ram_output_register == "OFF"))) && + (use_eab == "ON")) ? w_rdusedw_l : + (clocks_are_synchronized == "TRUE") ? w_rdusedw_s : w_rdusedw_a; + + assign wrusedw = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) || + (dev.FEATURE_FAMILY_STRATIX(intended_device_family) && + (lpm_showahead == "ON") && + (add_ram_output_register == "OFF"))) && + (use_eab == "ON")) ? w_wrusedw_l : + (clocks_are_synchronized == "TRUE") ? w_wrusedw_s : w_wrusedw_a; + + assign q = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) || + (dev.FEATURE_FAMILY_STRATIX(intended_device_family) && + (lpm_showahead == "ON") && + (add_ram_output_register == "OFF"))) && + (use_eab == "ON")) ? w_q_l : + (clocks_are_synchronized == "TRUE") ? w_q_s : w_q_a; + +endmodule // dcfifo +// END OF MODULE + +//-------------------------------------------------------------------------- +// 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. +// +//-------------------------------------------------------------------------- +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module altshift_taps (shiftin, clock, clken, shiftout, taps); + +// PARAMETER DECLARATION + parameter number_of_taps = 4; // Specifies the number of regularly spaced + // taps along the shift register + parameter tap_distance = 3; // Specifies the distance between the + // regularly spaced taps in clock cycles + // This number translates to the number of + // memory words that will be needed + parameter width = 8; // Specifies the width of the input pattern + parameter power_up_state = "CLEARED"; + parameter lpm_type = "altshift_taps"; + parameter lpm_hint = "UNUSED"; + + // Following parameters are used as constant + parameter RAM_WIDTH = width * number_of_taps; + parameter TOTAL_TAP_DISTANCE = number_of_taps * tap_distance; + +// INPUT PORT DECLARATION + input [width-1:0] shiftin; // Data input to the shifter + input clock; // Positive-edge triggered clock + input clken; // Clock enable for the clock port + +// OUTPUT PORT DECLARATION + output [width-1:0] shiftout; // Output from the end of the shift + // register + output [RAM_WIDTH-1:0] taps; // Output from the regularly spaced taps + // along the shift register + +// INTERNAL REGISTERS DECLARATION + reg [width-1:0] shiftout; + reg [RAM_WIDTH-1:0] taps; + reg [width-1:0] shiftout_tmp; + reg [RAM_WIDTH-1:0] taps_tmp; + reg [width-1:0] contents [0:TOTAL_TAP_DISTANCE-1]; + +// LOCAL INTEGER DECLARATION + integer head; // pointer to memory + integer i; // for loop index + integer j; // for loop index + integer k; // for loop index + integer place; + +// TRI STATE DECLARATION + tri1 clken; + +// INITIAL CONSTRUCT BLOCK + initial + begin + head = 0; + if (power_up_state == "CLEARED") + begin + shiftout = 0; + shiftout_tmp = 0; + for (i = 0; i < TOTAL_TAP_DISTANCE; i = i + 1) + begin + contents [i] = 0; + end + for (j = 0; j < RAM_WIDTH; j = j + 1) + begin + taps [j] = 0; + taps_tmp [j] = 0; + end + end + end + +// ALWAYS CONSTRUCT BLOCK + always @(posedge clock) + begin + if (clken == 1'b1) + begin + contents[head] = shiftin; + head = (head + 1) % TOTAL_TAP_DISTANCE; + shiftout_tmp = contents[head]; + + taps_tmp = 0; + + for (k=0; k < number_of_taps; k=k+1) + begin + place = (((number_of_taps - k - 1) * tap_distance) + head ) % + TOTAL_TAP_DISTANCE; + taps_tmp = taps_tmp | (contents[place] << (k * width)); + end + end + end + + always @(shiftout_tmp) + begin + shiftout <= shiftout_tmp; + end + + always @(taps_tmp) + begin + taps <= taps_tmp; + end + +endmodule // altshift_taps + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module 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_MODULE_NAME-------------------------------------------------------------- + +// BEGINNING OF MODULE +`timescale 1 ps / 1 ps + +// MODULE DECLARATION +module a_graycounter (clock, cnt_en, clk_en, updown, aclr, sclr, + q, qbin); +// GLOBAL PARAMETER DECLARATION + parameter width = 3; + parameter pvalue = 0; + parameter lpm_hint = "UNUSED"; + parameter lpm_type = "a_graycounter"; + +// INPUT PORT DECLARATION + input clock; + input cnt_en; + input clk_en; + input updown; + input aclr; + input sclr; + +// OUTPUT PORT DECLARATION + output [width-1:0] q; + output [width-1:0] qbin; + +// INTERNAL REGISTERS DECLARATION + reg [width-1:0] cnt; + +// INTERNAL TRI DECLARATION + tri1 clk_en; + tri1 cnt_en; + tri1 updown; + tri0 aclr; + tri0 sclr; + +// LOCAL INTEGER DECLARATION + +// COMPONENT INSTANTIATIONS + +// INITIAL CONSTRUCT BLOCK + initial + begin + if (width <= 0) + $display ("Error! WIDTH of a_greycounter must be greater than 0."); + + cnt <= pvalue; + end + +// ALWAYS CONSTRUCT BLOCK + always @(posedge aclr or posedge clock) + begin + if (aclr) + cnt <= pvalue; + else + begin + if (clk_en) + begin + if (sclr) + cnt <= pvalue; + else if (cnt_en) + begin + if (updown == 1) + cnt <= cnt + 1; + else + cnt <= cnt - 1; + end + end + end + end + +// CONTINOUS ASSIGNMENT + assign qbin = cnt; + assign q = cnt ^ (cnt >>1); + +endmodule // a_graycounter +// END OF MODULE + + +//-------------------------------------------------------------------------- +// alt_exc_dpram +//-------------------------------------------------------------------------- +// +`timescale 1 ps / 1 ps +module alt_exc_dpram (portadatain, + portadataout, + portaaddr, + portawe, + portaena, + portaclk, + portbdatain, + portbdataout, + portbaddr, + portbwe, + portbena, + portbclk + ); + + // default parameters + parameter operation_mode = "SINGLE_PORT" ; + parameter addrwidth = 14 ; + parameter width = 32 ; + parameter depth = 16384 ; + parameter ramblock = 65535 ; + parameter output_mode = "UNREG" ; + parameter lpm_file = "NONE" ; + parameter lpm_type = "alt_exc_dpram"; + parameter lpm_hint = "UNUSED"; + + // size of memory array + + reg [width-1:0] dpram_content[depth-1:0]; + + // input/output signals + + input portawe , + portbwe , + portaena , + portbena , + portaclk , + portbclk ; + + input [width-1:0] portadatain ; + input [width-1:0] portbdatain ; + + input [addrwidth-1:0] portaaddr ; + input [addrwidth-1:0] portbaddr ; + + output [width-1:0] portadataout , + portbdataout ; + + // internal signals/registers + + reg portaclk_in_last ; + reg portbclk_in_last ; + + wire portaclk_in ; + wire portbclk_in ; + wire portawe_in ; + wire portbwe_in ; + wire portaena_in ; + wire portbena_in ; + + wire [width-1:0] portadatain_in ; + wire [width-1:0] portbdatain_in ; + wire [width-1:0] portadatain_tmp ; + wire [width-1:0] portbdatain_tmp ; + + wire [addrwidth-1:0] portaaddr_in ; + wire [addrwidth-1:0] portbaddr_in ; + + reg [width-1:0] portadataout_tmp ; + reg [width-1:0] portbdataout_tmp ; + reg [width-1:0] portadataout_reg ; + reg [width-1:0] portbdataout_reg ; + reg [width-1:0] portadataout_reg_out ; + reg [width-1:0] portbdataout_reg_out ; + wire [width-1:0] portadataout_tmp2 ; + wire [width-1:0] portbdataout_tmp2 ; + + reg portawe_latched ; + reg portbwe_latched ; + reg [addrwidth-1:0] portaaddr_latched ; + reg [addrwidth-1:0] portbaddr_latched ; + + // assign to internal signals + + assign portadatain_in = portadatain; + assign portaaddr_in = portaaddr; + assign portaena_in = portaena; + assign portaclk_in = portaclk; + assign portawe_in = portawe; + + assign portbdatain_in = portbdatain; + assign portbaddr_in = portbaddr; + assign portbena_in = portbena; + assign portbclk_in = portbclk; + assign portbwe_in = portbwe; + + + // Dual Port Contention Port A address = Port B address + // + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // | Port A | Port B | A Data In | B Data In | A Data Out | B Data Out | Memory State | + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // | read | read | DA | DB | memory | memory | no change | + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // | write | read | DA | DB | unknown | unknown | memory <= DA | + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // | read | write | DA | DB | unknown | unknown | memory <= DB | + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // | write | write | DA | DB | unknown | unknown | memory <= unknown | + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // + // Dual Port Contention Port A address != Port B address + // + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // | Port A | Port B | A Data In | B Data In | A Data Out | B Data Out | Memory State | + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // | read | read | DA | DB | mem[A_addr] | mem[B_Addr] | no change | + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // | write | read | DA | DB | unknown | mem[B_Addr] | mem[A_Addr] <= DA | + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // | read | write | DA | DB | mem[A_addr] | unknown | mem[B_Addr] <= DB | + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // | write | write | DA | DB | unknown | unknown | mem[A_Addr] <= DA | + // | | | | | | | mem[B_Addr] <= DB | + // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+ + // + // NB: Output state is always unknown when writing. + + + initial + begin + // Initialise dpram memory contents from file (if filename specified). + if (lpm_file != "NONE" && lpm_file != "none") $readmemh(lpm_file, dpram_content); + + portaclk_in_last = 0; + portbclk_in_last = 0; + end + + always @(portaclk_in) + begin + if (portaclk_in != 0 && portaclk_in_last == 0) // rising edge port a clock + begin + + portawe_latched = portawe_in ; + portaaddr_latched = portaaddr_in ; + + if (portawe_latched == 'b0) + begin + + // reading A + + if (portaaddr_latched == portbaddr_latched && portbwe_latched != 'b0) + begin + + // B simultaneously writing to same address (effect of B write to memory handled below) + + portadataout_reg = portadataout_tmp; + portadataout_tmp = 'bx; + + end + else + begin + + // B reading from same address, or reading/writing to different address. + + portadataout_reg = portadataout_tmp; + portadataout_tmp = dpram_content[portaaddr_latched]; + + end + end + + else + + // writing to A + + begin + if (portaaddr_latched == portbaddr_latched && portawe_latched != 'b0 && portbwe_latched != 'b0) + begin + + // A and B simultaneously writing to same address + + portadataout_reg = portadataout_tmp ; + dpram_content[portaaddr_latched] = 'bx ; + portadataout_tmp = 'bx ; + + end + else + begin + + // B reading from same address or reading/writing to different address + + portadataout_reg = portadataout_tmp; + dpram_content[portaaddr_latched] = portadatain_tmp ; + portadataout_tmp = 'bx ; + + end + end // writing to A + end // rising edge port a clock + portaclk_in_last = portaclk_in; + end // portaclk_in change event + + always @(portbclk_in) + begin + if (portbclk_in != 0 && portbclk_in_last == 0 && (operation_mode == "DUAL_PORT" || operation_mode == "dual_port")) // rising edge port b clock + begin + + portbwe_latched = portbwe_in ; + portbaddr_latched = portbaddr_in ; + + if (portbwe_latched == 'b0) + begin + + // reading B + + if (portbaddr_latched == portaaddr_latched && portawe_latched != 'b0) + begin + + // A simultaneously writing to same address (effect of A write to memory handled above) + + portbdataout_reg = portbdataout_tmp; + portbdataout_tmp = 'bx; + + end + else + begin + + // A reading from same address, or reading/writing to different address. + + portbdataout_reg = portbdataout_tmp; + portbdataout_tmp = dpram_content[portbaddr_latched]; + + end + end + else + + // writing to B + + begin + if (portbaddr_latched == portaaddr_latched && portbwe_latched != 'b0 && portawe_latched != 'b0) + begin + + // B and A simultaneously writing to same address + + portbdataout_reg = portbdataout_tmp ; + dpram_content[portbaddr_latched] = 'bx ; + portbdataout_tmp = 'bx ; + + end + else + begin + + // A reading from same address or reading/writing to different address + + portbdataout_reg = portbdataout_tmp; + dpram_content[portbaddr_latched] = portbdatain_tmp ; + portbdataout_tmp = 'bx ; + + end + end // writing to B + end // rising edge port B clock + + portbclk_in_last = portbclk_in; + + end // portbclk_in change event + + // registered Port A output enabled ? + + always @(portaena_in or portadataout_reg) + begin + if (output_mode == "REG" || output_mode == "reg") + if ( portaena_in == 1'b1 ) + portadataout_reg_out = portadataout_reg ; + end + + // registered Port B output enabled ? + + always @(portbena_in or portbdataout_reg) + begin + if (output_mode == "REG" || output_mode == "reg") + if ( portbena_in == 1'b1 ) + portbdataout_reg_out = portbdataout_reg ; + end + + // Registered or Unregistered mode ? + + assign portadataout_tmp2 = (output_mode == "REG" || output_mode == "reg") ? portadataout_reg_out[width-1:0] : portadataout_tmp[width-1:0]; + assign portbdataout_tmp2 = (output_mode == "REG" || output_mode == "reg") ? portbdataout_reg_out[width-1:0] : portbdataout_tmp[width-1:0]; + + assign portadatain_tmp[width-1:0] = portadatain; + assign portbdatain_tmp[width-1:0] = portbdatain; + + assign portadataout = portadataout_tmp2; + assign portbdataout = portbdataout_tmp2; + + +endmodule // alt_exc_dpram + +//-------------------------------------------------------------------------- +// Altera UP Core +//-------------------------------------------------------------------------- +// +`timescale 1 ps / 1 ps + +module alt_exc_upcore ( + intpld, intuart, inttimer0, inttimer1, intcommtx, intcommrx, intproctimer, intprocbridge, + debugrq, debugext0, debugext1, debugiebrkpt, debugdewpt, debugextin, debugack, + debugrng0, debugrng1, debugextout, + + slavehclk, + slavehwrite, slavehreadyi, slavehselreg, slavehsel, slavehmastlock, slavehaddr, + slavehwdata, slavehtrans, slavehsize, slavehburst, slavehreadyo, slavebuserrint, + slavehrdata, slavehresp, + + masterhclk, + masterhrdata, masterhresp, masterhwrite, masterhlock, masterhbusreq, masterhaddr, + masterhwdata, masterhtrans, masterhsize, masterhready, masterhburst, masterhgrant, + + lockreqdp0, lockreqdp1, + lockgrantdp0, lockgrantdp1, + + ebiack, ebiwen, ebioen, ebiclk, ebibe, ebicsn, ebiaddr, ebidq, + + uarttxd, uartrtsn, uartdtrn, uartctsn, uartdsrn, uartrxd, uartdcdn, + uartrin, + + sdramclk, sdramclkn, sdramclke, sdramwen, sdramcasn, sdramrasn, sdramdqm, + sdramaddr, sdramdq, sdramdqs, sdramcsn, + + + intextpin, traceclk, tracesync, tracepipestat, tracepkt, clk_ref, intnmi, perreset, + npor, nreset, gpi, gpo + ); + + parameter processor = "ARM"; + parameter source = ""; + parameter sdram_width = 32; + parameter sdramdqm_width = 4; + parameter gpio_width = 4; + parameter lpm_type = "alt_exc_upcore"; + parameter lpm_hint = "UNUSED"; + +// AHB2 Master and Slave bridges +// Interupt, debug and trace ports +// DP Ram locks + + input slavehclk, masterhclk; + + input slavehwrite, slavehreadyi, slavehselreg, slavehsel, + slavehmastlock, masterhready, masterhgrant; + + input lockreqdp0, lockreqdp1, + debugrq, debugext0, debugext1, debugiebrkpt, debugdewpt; + + input [31:0] slavehaddr, slavehwdata, masterhrdata; + input [1:0] slavehtrans, slavehsize, masterhresp; + input [3:0] debugextin; + input [5:0] intpld; + input [2:0] slavehburst; + + output masterhwrite, masterhlock, masterhbusreq, slavehreadyo, slavebuserrint, + intuart, inttimer0, inttimer1, intcommtx, intcommrx, + debugack, debugrng0, debugrng1, + lockgrantdp0, lockgrantdp1; + + output [31:0] masterhaddr, masterhwdata, slavehrdata; + output [1:0] masterhtrans, masterhsize, slavehresp; + output [2:0] masterhburst; + output [3:0] debugextout; + +// Shared IO connections +// EBI Expansion bus +// SDRAM interface +// UART and trace port + + input ebiack; + output ebiwen, ebioen, ebiclk; + output [1:0] ebibe; + output [3:0] ebicsn; + output [24:0] ebiaddr; + inout [15:0] ebidq; + + input uartctsn, uartdsrn, uartrxd; + output uarttxd, uartrtsn, uartdtrn; + inout uartdcdn, uartrin; + + output sdramclk, sdramclkn, sdramclke, + sdramwen, sdramcasn, sdramrasn; + output [1:0] sdramcsn; + output [sdramdqm_width-1:0] sdramdqm; + output [14:0] sdramaddr; + + inout [sdram_width-1:0] sdramdq; + inout [sdramdqm_width-1:0] sdramdqs; + + input intextpin; + output traceclk, tracesync; + output [2:0] tracepipestat; + output [15:0] tracepkt; + + input clk_ref, npor; + inout nreset; + output intproctimer, intprocbridge; + output perreset; + input intnmi; + input [gpio_width-1:0] gpi; + output [gpio_width-1:0] gpo; + + +///////////////////////////////////////////////////////////////////////////////////////////////// +// AHB Constants +///////////////////////////////////////////////////////////////////////////////////////////////// + +// responses (HRESP) +`define H_OKAY 2'b00 +`define H_ERROR 2'b01 +`define H_RETRY 2'b10 +`define H_SPLIT 2'b11 + +// transcation types (HTRANS) +`define H_IDLE 2'b00 +`define H_BUSY 2'b01 +`define H_NONSEQ 2'b10 +`define H_SEQ 2'b11 + +// burst mode (HBURST) +`define H_SINGLE 3'b000 +`define H_INCR 3'b001 +`define H_WRAP4 3'b010 +`define H_INCR4 3'b011 +`define H_WRAP8 3'b100 +`define H_INCR8 3'b101 +`define H_WRAP16 3'b110 +`define H_INCR16 3'b111 + +// transaction sizes (HSIZE 8,16,32 bits -- larger sizes not supported) +`define H_BYTE 2'b00 +`define H_HWORD 2'b01 +`define H_WORD 2'b10 + +///////////////////////////////////////////////////////////////////////////////////////////////// +// slave port +///////////////////////////////////////////////////////////////////////////////////////////////// + + wire slavehclk_in; + wire slavehwrite_in, slavehreadyi_in, slavehselreg_in, slavehsel_in, + slavehmastlock_in; + wire [31:0] slavehaddr_in, slavehwdata_in; + wire [1:0] slavehtrans_in, slavehsize_in; + wire [2:0] slavehburst_in; + wire slavehreadyo_out, slavebuserrint_out; + wire [31:0] slavehrdata_out; + wire [1:0] slavehresp_out; + +// + assign slavehclk_in = slavehclk ; + assign slavehwrite_in = slavehwrite ; + assign slavehreadyi_in = slavehreadyi ; + assign slavehselreg_in = slavehselreg ; + assign slavehsel_in = slavehsel ; + assign slavehmastlock_in = slavehmastlock; + + assign slavehaddr_in = slavehaddr; + + assign slavehwdata_in = slavehwdata; + + assign slavehtrans_in = slavehtrans; + assign slavehsize_in = slavehsize; + assign slavehburst_in = slavehburst; + +// + assign slavehreadyo = slavehreadyo_out; + assign slavebuserrint= slavebuserrint_out; + + assign slavehrdata = slavehrdata_out; + assign slavehresp = slavehresp_out; + +///////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////// + +// outputs + reg slavehreadyo_out_r ; + reg [1:0] slavehresp_out_r ; + + assign slavehreadyo_out = slavehreadyo_out_r ; + assign slavehresp_out = slavehresp_out_r ; + + +// record of address and control information (latched on address phase) + reg [31:0] startReg; // start address for burst + reg [31:0] addrReg; + reg [1:0] transReg; + reg [1:0] sizeReg; + reg writeReg; + reg [2:0] burstReg; + reg selReg; + reg [7:0] waitReg; + +// Implement 6 banks of 256K = (1.5MB of address space) +// /////////////////////////////////////////////////////////////////// + reg [79:0] memCfg[0:5]; // slavememory.cfg.dat + reg [31:0] memStart[0:5]; + reg [31:0] memEnd[0:5]; + reg [7:0] memWaitStart[0:5]; + reg [7:0] memWait[0:5]; + reg [31:0] memMapA[0:65535]; // slavememory.0.dat + reg [31:0] memMapB[0:65535]; + reg [31:0] memMapC[0:65535]; + reg [31:0] memMapD[0:65535]; + reg [31:0] memMapE[0:65535]; + reg [31:0] memMapF[0:65535]; // slavememory.5.dat + + reg [2:0] memBank; + reg [79:0] temp; + + integer output_file ; + + initial begin + +// Open the results file + output_file = $fopen("output.dat") ; + if ( !output_file ) + $display("ERROR: Cannot open Output File") ; + + +// Initialise memory banks from config and map files +////////////////////////////////////////////////////////////////////// + temp=80'h00000000_00000000_00_00; + for (memBank=0;memBank<6;memBank=memBank+1) + begin + memCfg[memBank]=temp; + end + +// 79..48 start address +// 47..16 end address +// 15...8 wait states on first access +// 7...0 wait states per cycle + $readmemh("slavememory.cfg.dat", memCfg); + for (memBank=0;memBank<6;memBank=memBank+1) + begin + temp=memCfg[memBank]; + memStart[memBank] =temp[79:48]; + memEnd[memBank] =temp[47:16]; + memWaitStart[memBank] =temp[15:8]; + memWait[memBank] =temp[7:0]; + end + + if (memStart[0]!=memEnd[0]) $readmemh("slavememory.0.dat", memMapA); + if (memStart[1]!=memEnd[1]) $readmemh("slavememory.1.dat", memMapB); + if (memStart[2]!=memEnd[2]) $readmemh("slavememory.2.dat", memMapC); + if (memStart[3]!=memEnd[3]) $readmemh("slavememory.3.dat", memMapD); + if (memStart[4]!=memEnd[4]) $readmemh("slavememory.4.dat", memMapE); + if (memStart[5]!=memEnd[5]) $readmemh("slavememory.5.dat", memMapF); +////////////////////////////////////////////////////////////////////// + + addrReg=0; + transReg=`H_IDLE; + sizeReg=`H_WORD; + writeReg=0; + burstReg=`H_NONSEQ; + selReg=0; + + slavehresp_out_r=`H_OKAY; + end + + +// select signal + wire sel = slavehsel_in & slavehreadyi_in; + +// determine if the transaction includes an operation / a "busy" + wire doWork = selReg & ((transReg==`H_NONSEQ || transReg==`H_SEQ) ? 1'b1 : 1'b0); + wire doBusyWork = selReg & ( transReg==`H_BUSY ? 1'b1 : 1'b0); + + +// BURST MODE SUPPORT +/////////////////////////////////////////////////////////////////////////////// +// +// If we are in burst mode we'll compute our own address and control settings +// based on the spec. +// +// compute values SEQuential (burst) transfers + wire seqTrans = ( selReg & + ( doWork | doBusyWork) & + ( (slavehtrans_in==`H_SEQ || slavehtrans_in==`H_BUSY) ) ? 1'b1 : 1'b0 ); + + +// mask to determine which bits are retained from the start address + wire [31:0] wrapmask; + assign wrapmask = + ( burstReg==`H_WRAP4 ? {32{1'b1}} << 2: // all but 2 + ( burstReg==`H_WRAP8 ? {32{1'b1}} << 3: // all but 3 + ( burstReg==`H_WRAP16 ? {32{1'b1}} << 4: // all but 4 + {32{1'b0}} ) )); // none + wire [31:0] wrapmask_w; + assign wrapmask_w = // correct for word size + ( sizeReg==`H_WORD ? wrapmask<<2 : + ( sizeReg==`H_HWORD ? wrapmask<<1 : + /* H_BYTE */ wrapmask )); + + wire [31:0] seqPlusAddr; // work out the next sequential address + assign seqPlusAddr = + ( burstReg == `H_SINGLE) ? addrReg : + addrReg + ( sizeReg==`H_BYTE ? 1 : + ( sizeReg==`H_HWORD ? 2 : + ( sizeReg==`H_WORD ? 4 : 0) ) ) ; + + wire [31:0] seqAddr; // apply the mask to wrap at boundaries + assign seqAddr = (slavehtrans_in==`H_BUSY) ? addrReg : + ( (startReg&wrapmask_w) | (seqPlusAddr&~wrapmask_w)); + +// +// if this is a sequential transaction only sample HTRANS + wire [31:0] startNext; + wire [31:0] addrNext; + wire [1:0] transNext; + wire [1:0] sizeNext; + wire [2:0] burstNext; + wire writeNext; + + assign startNext = seqTrans ? startReg : slavehaddr_in; + assign addrNext = seqTrans ? seqAddr : slavehaddr_in; + assign transNext = slavehtrans_in; + assign sizeNext = seqTrans ? sizeReg : slavehsize_in; + assign burstNext = seqTrans ? burstReg : slavehburst_in; + assign writeNext = seqTrans ? writeReg : slavehwrite_in; + + +// Latch the control data if we are selected +/////////////////////////////////////////////////////////////////////////////////// + always @ (posedge slavehclk_in) + begin +// if readin is low another device is wait stating its +// data phase and hence extending our address phase + if (slavehreadyi_in) + begin + selReg <= sel; + if (sel) // latch the control data + begin + startReg <= startNext; + addrReg <= addrNext; + transReg <= transNext; + sizeReg <= sizeNext; + writeReg <= writeNext; + burstReg <= burstNext; + end + else + begin + startReg <= 0; + addrReg <= 0; + transReg <= `H_IDLE; + sizeReg <= `H_WORD; + writeReg <= 0; + burstReg <= `H_SINGLE; + end + end + end + + +// Implment memory banks +/////////////////////////////////////////////////////////////////////////////////// +// bank selects + wire bankA = ( addrReg>=memStart[0] && addrReg<=memEnd[0] && memStart[0]!=memEnd[0]) ? 1'b1 : 1'b0; + wire bankB = ( addrReg>=memStart[1] && addrReg<=memEnd[1] && memStart[1]!=memEnd[1]) ? 1'b1 : 1'b0; + wire bankC = ( addrReg>=memStart[2] && addrReg<=memEnd[2] && memStart[2]!=memEnd[2]) ? 1'b1 : 1'b0; + wire bankD = ( addrReg>=memStart[3] && addrReg<=memEnd[3] && memStart[3]!=memEnd[3]) ? 1'b1 : 1'b0; + wire bankE = ( addrReg>=memStart[4] && addrReg<=memEnd[4] && memStart[4]!=memEnd[4]) ? 1'b1 : 1'b0; + wire bankF = ( addrReg>=memStart[5] && addrReg<=memEnd[5] && memStart[5]!=memEnd[5]) ? 1'b1 : 1'b0; + +// byte offset into bank //word offset into bank + wire [31:0] offsetA = addrReg-memStart[0]; wire [15:0] wordA = offsetA[17:2]; + wire [31:0] offsetB = addrReg-memStart[1]; wire [15:0] wordB = offsetB[17:2]; + wire [31:0] offsetC = addrReg-memStart[2]; wire [15:0] wordC = offsetC[17:2]; + wire [31:0] offsetD = addrReg-memStart[3]; wire [15:0] wordD = offsetD[17:2]; + wire [31:0] offsetE = addrReg-memStart[4]; wire [15:0] wordE = offsetE[17:2]; + wire [31:0] offsetF = addrReg-memStart[5]; wire [15:0] wordF = offsetF[17:2]; + +// current data + wire [31:0] dataA = memMapA[wordA]; + wire [31:0] dataB = memMapB[wordB]; + wire [31:0] dataC = memMapC[wordC]; + wire [31:0] dataD = memMapD[wordD]; + wire [31:0] dataE = memMapE[wordE]; + wire [31:0] dataF = memMapF[wordF]; + + reg [31:0] currentVal; + always @(dataA or dataB or dataC or dataD or dataE or dataF or + bankA or bankB or bankC or bankD or bankE or bankF ) + begin + if (bankA) currentVal=dataA; + else if (bankB) currentVal=dataB; + else if (bankC) currentVal=dataC; + else if (bankD) currentVal=dataD; + else if (bankE) currentVal=dataE; + else if (bankF) currentVal=dataF; + end + + +// byte enables + wire be0 = (sizeReg==`H_WORD || + (sizeReg==`H_HWORD && addrReg[1]==1'b0) || + (sizeReg==`H_BYTE && addrReg[1:0]==2'b00) ) ? 1'b1 : 1'b0; + wire be1 = (sizeReg==`H_WORD || + (sizeReg==`H_HWORD && addrReg[1]==1'b0) || + (sizeReg==`H_BYTE && addrReg[1:0]==2'b01) ) ? 1'b1 : 1'b0; + wire be2 = (sizeReg==`H_WORD || + (sizeReg==`H_HWORD && addrReg[1]==1'b1) || + (sizeReg==`H_BYTE && addrReg[1:0]==2'b10) ) ? 1'b1 : 1'b0; + wire be3 = (sizeReg==`H_WORD || + (sizeReg==`H_HWORD && addrReg[1]==1'b1) || + (sizeReg==`H_BYTE && addrReg[1:0]==2'b11) ) ? 1'b1 : 1'b0; + + wire [31:0] readDataMask = {be3 ? 8'hFF : 8'h00, + be2 ? 8'hFF : 8'h00, + be1 ? 8'hFF : 8'h00, + be0 ? 8'hFF : 8'h00 }; + + + +// wait state generation +/////////////////////////////////////////////////////////////////////////////////// + + reg s_addr_latch; // address latched this cycle + reg [7:0] waitStart; + reg [7:0] waitSeq; + + initial begin + s_addr_latch=1'b0; + waitReg=8'h00; + end + + always @(bankA or bankB or bankC or bankD or bankE or bankF ) + begin + if (bankA) waitStart = memWaitStart[0]; + else if (bankB) waitStart = memWaitStart[1]; + else if (bankC) waitStart = memWaitStart[2]; + else if (bankD) waitStart = memWaitStart[3]; + else if (bankE) waitStart = memWaitStart[4]; + else if (bankF) waitStart = memWaitStart[5]; + end + + always @(bankA or bankB or bankC or bankD or bankE or bankF ) + begin + if (bankA) waitSeq = memWait[0]; + else if (bankB) waitSeq = memWait[1]; + else if (bankC) waitSeq = memWait[2]; + else if (bankD) waitSeq = memWait[3]; + else if (bankE) waitSeq = memWait[4]; + else if (bankF) waitSeq = memWait[5]; + end + + +// +// wait if +// first beat and memWaitStart and addr has just been latched +// or +// first beat and waitReg (more than 1 wait state) +// or +// seq beat and waitReg +// else ready +// + + always @(posedge slavehclk_in) + s_addr_latch <= slavehreadyi_in & slavehsel_in; + + always @(doWork or transReg or waitReg or waitStart or s_addr_latch) + begin + if ( doWork & (transReg==`H_NONSEQ) & (waitStart!=8'h00) & s_addr_latch ) + begin + slavehreadyo_out_r = 1'b0; + // $fdisplay(output_file, "SLAVE: wait on first" ); + end + else if ( doWork & (transReg==`H_NONSEQ) & waitReg!=8'h00 ) + begin + slavehreadyo_out_r = 1'b0; + // $fdisplay(output_file, "SLAVE: wait" ); + end + else if (doWork & (transReg==`H_SEQ) & (waitReg!=8'h00)) + begin + slavehreadyo_out_r = 1'b0; + // $fdisplay(output_file, "SLAVE: wait" ); + end + else + slavehreadyo_out_r = 1'b1; + end + + +// if we are waiting (waitReg>0) and not in a busy decrement the counter +// otherwise get the new value from memWait of memWaitStart according to +// the transaction type + + wire [7:0] waitStartNext; + assign waitStartNext = ( waitStart>8'h01 ? (waitStart-1) : 8'h00); + + always @ (posedge slavehclk_in) + waitReg<= (waitReg!=8'h00 & ~doBusyWork) ? (waitReg - 1'b1) : + ( doWork & (transReg==`H_NONSEQ) & (waitStart!=8'h00) & s_addr_latch ? waitStartNext : + ( seqTrans ? waitSeq : 8'h00 )); + + +// read data +/////////////////////////////////////////////////////////////////////////////////// + assign slavehrdata_out =(doWork & ~writeReg & slavehreadyo_out_r) ? + (readDataMask & currentVal) : {32{1'b0}}; + + + +// record writes in memory banks + report on screen +/////////////////////////////////////////////////////////////////////////////////// + reg [31:0] memWord; // the word to be updated / read + always @ (posedge slavehclk_in) + begin + if (doWork & slavehreadyo_out_r) + begin + memWord = currentVal; + if (writeReg) + begin + if (be0) memWord[7:0] =slavehwdata_in[7:0] ; + if (be1) memWord[15:8] =slavehwdata_in[15:8] ; + if (be2) memWord[23:16] =slavehwdata_in[23:16]; + if (be3) memWord[31:24] =slavehwdata_in[31:24]; + + if (bankA) memMapA[wordA] = memWord; + if (bankB) memMapB[wordB] = memWord; + if (bankC) memMapC[wordC] = memWord; + if (bankD) memMapD[wordD] = memWord; + if (bankE) memMapE[wordE] = memWord; + if (bankF) memMapF[wordF] = memWord; + end + if (output_file) + $fdisplay(output_file, + "SLAVE: addr=[%h] %s data=[%h] %s", + addrReg, + writeReg ? "WRITE" : "READ", + writeReg ? slavehwdata_in : slavehrdata_out , + sizeReg==`H_BYTE ? "BYTE" : + ( sizeReg==`H_HWORD ? "HALF WORD" : "WORD" ) ); + else + $display( + "SLAVE: addr=[%h] %s data=[%h] %s", + addrReg, + writeReg ? "WRITE" : "READ", + writeReg ? slavehwdata_in : slavehrdata_out , + sizeReg==`H_BYTE ? "BYTE" : + ( sizeReg==`H_HWORD ? "HALF WORD" : "WORD" ) ); + + end + end + +///////////////////////////////////////////////////////////////////////////////////////////////// +// Master Port transactor +///////////////////////////////////////////////////////////////////////////////////////////////// + +// timing data - setup and holds +//////////////////////////////// + wire masterhclk_in; + wire masterhready_in, masterhgrant_in; + wire [31:0] masterhrdata_in; + wire [1:0] masterhresp_in; + wire masterhwrite_out, masterhlock_out, masterhbusreq_out; + wire [31:0] masterhaddr_out, masterhwdata_out; + wire [1:0] masterhtrans_out, masterhsize_out; + wire [2:0] masterhburst_out; + +// + assign masterhclk_in = masterhclk; + assign masterhready_in = masterhready; + assign masterhgrant_in = masterhgrant; + + assign masterhrdata_in = masterhrdata; + assign masterhresp_in = masterhresp; + +// + assign masterhwrite = masterhwrite_out; + assign masterhlock = masterhlock_out; + assign masterhbusreq = masterhbusreq_out; + + assign masterhtrans = masterhtrans_out; + assign masterhsize = masterhsize_out; + assign masterhburst = masterhburst_out; + + assign masterhaddr = masterhaddr_out; + assign masterhwdata = masterhwdata_out; + + + ///////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////// + + // Transaction Record Format + // 255..254 spare + // 253..252 response + // 251..220 read data + // 219 go busy + // 218..217 spare + // 216..208 number of beats in sequential transaction + // 207..176 start address of transaction + // 175..144 expected data + // 143..128 transaction number + // ------------------------------------- following field read from command file + // 127..112 spare + // 111..109 spare + // 108 bus command (0 => inactive) + // 107.. 76 address + // 75.. 73 spare + // 72 write + // 71.. 40 write data / expected read data + // 39.. 37 spare + // 36 lock (not implemented) + // 35.. 33 spare + // 32 check expected data (not implemented) + // 31.. 30 spare + // 29.. 28 transaction type + // 27.. 23 spare + // 21.. 20 burst type + // 19.. 18 spare + // 17.. 16 size + // 15.. 00 repeat count + + // register outputs + reg [31:0] masterhaddr_out_r; + reg [31:0] masterhwdata_out_r; + reg [2:0] masterhburst_out_r; + reg [1:0] masterhtrans_out_r; + reg masterhwrite_out_r; + + assign masterhaddr_out = masterhaddr_out_r; + assign masterhwdata_out = masterhwdata_out_r; + assign masterhburst_out = masterhburst_out_r; + assign masterhtrans_out = masterhtrans_out_r; + assign masterhwrite_out = masterhwrite_out_r; + + reg [2:0] masterhsize_outl; // the transactor implements the full 3 bit size + assign masterhsize_out=masterhsize_outl[1:0]; // field but upCore only uses 2 + + + // //////////////////////////////////////////////////////////////////////////////////////////// + // + reg [128:0] transactions[1:65535]; // space for NUMTRANS transactions + reg [128:0] tmp_transaction; + reg [8:0] tmp_beats, tmp_num; + + // Transaction records + reg [255:0] n_trans; // next + reg [255:0] c_trans; // control / address phase + reg [255:0] d_trans; // data phase + reg [255:0] retry_trans; // retrying + reg [255:0] r_trans; // reporting + + reg [255:0] i_trans; // IDLE Transaction + + reg [15:0] trans_num; // the current control phase transaction + reg [31:0] resp_data; + +/*---------------------------------------------------------------------------- +Control signals for master transactor +----------------------------------------------------------------------------*/ + reg reset; + wire start = n_trans[108]; + wire stop = 1'b0; + wire continue_after_error = 1'b1; + wire generate_data = 1'b0; + wire [1:0] insert_busy = 2'b00; + wire go_busy = n_trans[219]; + wire [8:0] beats = n_trans[216:208]; // 511 beats max + wire [2:0] burst = n_trans[23:20]; + wire [2:0] size = n_trans[18:16]; + wire write = n_trans[72]; + wire [31:0] start_address = n_trans[207:176]; + wire [31:0] data = n_trans[71:40]; + + +/*---------------------------------------------------------------------------- +Transactor state and responses +----------------------------------------------------------------------------*/ + reg [2:0] original_burst; + reg masterhgrant_in_r; + reg [1:0] busy_states; + reg [1:0] busy_counter; + reg [9:0] init_wrap_mask, wrap_mask; + reg [7:0] masterhaddr_out_r_inc, init_wrap_boundary_bit; + reg [10:0] init_next_masterhaddr_out_r, wrap_boundary_bit; + reg [9:0] next_masterhaddr_out_r; + wire break_wrap; + + reg address_bus_owned, data_bus_owned; + reg add_go, data_go; + reg reading, writing; + reg first_beat, need_retry, wrap, replay_wrap; + reg new_grant; + wire first_masterhtrans_out_r; + wire addr_ack; + wire data_ack; + +/*---------------------------------------------------------------------------- +Initialisation +----------------------------------------------------------------------------*/ + initial + begin + i_trans ={256{1'b0}}; // set up a null transaction record + i_trans[143:128]=16'hFFFF; + i_trans[29:28] =`H_IDLE; + + d_trans=i_trans; // fill pipe with null's + c_trans=i_trans; + r_trans=i_trans; + // initialise the transactions database + tmp_transaction={128{1'b0}}; + + // we're using the bus functional language so load the commands + // from a file + for (trans_num=1;trans_num<65535;trans_num=trans_num+1) + begin + transactions[trans_num]=tmp_transaction; + end + $readmemh("mastercommands.dat", transactions); + + tmp_num = 9'b000000000; + tmp_beats = 9'b000000000; + trans_num=16'h0000; + + n_trans=i_trans; + n_trans[2]=1'b1; // repeat 4 + + reset=0; // reset the transactor on start + #10 reset=1; + #20 reset=0; + + end + + + +/*---------------------------------------------------------------------------- + Report completed transactions + + We could mask and shift the received data for HALFWORD and BYTE + transactions but we won't. + ----------------------------------------------------------------------------*/ + // received data + /**** + wire [31:0] r_r_data = r_trans[72]==1'b1 ? r_trans[71:40] : r_trans[251:220]; + wire [31:0] e_r_data = r_trans[175:144]; + wire [31:0] mr_r_data, me_r_data; // byte lane masked recovered and expected + + mr_r_data = r_trans[17:16] == `H_WORD ? r_r_data : + (r_trans[17:16] == `H_HWORD ? + { 16'h0000, (r_trans[77]==1'b1 ? r_r_data[31:16] : r_r_data[15:0]) } : + // byte + { 24'h000000, ( r_trans[77:76]==2'b00 ? r_r_data[7:0] : + r_trans[77:76]==2'b01 ? r_r_data[15:8] : + r_trans[77:76]==2'b10 ? r_r_data[23:16] : + r_r_data[31:24]) } ); + + r_rdata = r_trans[17:16] == `H_WORD ? r_e_data : + (r_trans[17:16] == `H_HWORD ? + { 16'h0000, (r_trans[77]==1'b1 ? r_e_data[31:16] : r_e_data[15:0]) } : + // byte + { 24'h000000, ( r_trans[77:76]==2'b00 ? r_e_data[7:0] : + r_trans[77:76]==2'b01 ? r_e_data[15:8] : + r_trans[77:76]==2'b10 ? r_e_data[23:16] : + r_e_data[31:24]) } ); + ****/ + always @(posedge masterhclk_in) + begin + if (r_trans[108]==1'b1) // r_trans contains a valid transaction + begin + + if (output_file) + $fdisplay(output_file, + "MASTER: trans=[%d] addr=[%h] %s data=[%h] expected=[%h] %s %s", + r_trans[143:128], + r_trans[107:76], + r_trans[72]==1'b1 ? "WRITE" : "READ", + r_trans[72]==1'b1 ? r_trans[71:40] : r_trans[251:220], + r_trans[175:144], + r_trans[17:16]==`H_BYTE ? "BYTE" : + ( r_trans[17:16]==`H_HWORD ? "HALF WORD" : "WORD" ), + r_trans[253:252]==`H_OKAY ? "OKAY" : "ERROR" ); + else + $display( + "MASTER: trans=[%d] addr=[%h] %s data=[%h] expected=[%h] %s %s", + r_trans[143:128], + r_trans[107:76], + r_trans[72]==1'b1 ? "WRITE" : "READ", + r_trans[72]==1'b1 ? r_trans[71:40] : r_trans[251:220], + r_trans[175:144], + r_trans[17:16]==`H_BYTE ? "BYTE" : + ( r_trans[17:16]==`H_HWORD ? "HALF WORD" : "WORD" ), + r_trans[253:252]==`H_OKAY ? "OKAY" : "ERROR" ); + + end + end + + + + + +/*---------------------------------------------------------------------------- +Get Next Transaction +----------------------------------------------------------------------------*/ + reg [216:208] tmp_repeats; + always + begin + + while ( trans_num<16'hFFFF) + begin + + if (n_trans[15:0]==16'h0000) + begin + // get the next record + trans_num = trans_num+1; + + tmp_transaction = transactions[trans_num]; + + n_trans[175:144]<= tmp_transaction[71:40]; // expected data + n_trans[143:128]<= trans_num; + n_trans[127:0] <= tmp_transaction; + + + // check for a BUSY + n_trans[219] <= tmp_transaction[29:28]==`H_BUSY ? 1'b1 : 1'b0; + + // update the start address + if (tmp_transaction[29:28]!=`H_SEQ&&tmp_transaction[29:28]!=`H_BUSY) + begin + n_trans[207:176] <= tmp_transaction[107:76]; // start address + end + + + // compute the number of beats in burst + if (tmp_transaction[23:20]!=`H_SINGLE && tmp_transaction[29:28]==`H_NONSEQ) + begin + tmp_beats=9'b0_0000_0001; + tmp_repeats[216:208]=9'b0_0000_0001; + + // get the transaction from the database + tmp_transaction=transactions[trans_num+tmp_beats]; + + while (tmp_transaction[29:28]==`H_SEQ||tmp_transaction[29:28]==`H_BUSY) + begin + tmp_repeats[216:208]=tmp_repeats[216:208]+tmp_transaction[15:0]+1; + tmp_beats=tmp_beats+1; + + // get the transaction from the database + tmp_transaction = transactions[trans_num+tmp_beats]; + + end + n_trans[216:208]<=tmp_repeats[216:208]; + end + + + end + else + begin + n_trans[15:0]<=n_trans[15:0]-1; + end // i + + // wait for the current transaction to be accepted + @(posedge masterhclk_in); + while (~(addr_ack|data_ack) && n_trans[108]) + @(posedge masterhclk_in); + + end // while transactions in buffer + if (output_file) $fclose(output_file) ; + $finish(2); + end + + + + + +/*---------------------------------------------------------------------------- +Compute burst length + +add_go_r prevents a newly loaded length being decremented by the last data +beat of the previous transaction. +----------------------------------------------------------------------------*/ + reg [8:0] length; + reg add_go_r; + always @(posedge masterhclk_in) + if (masterhready_in) + add_go_r <= add_go; + + always @(posedge masterhclk_in or posedge reset) + if (reset) + length <= 5'h0; + else if (add_go) + case (burst) + `H_SINGLE: length <= 9'h1; + `H_INCR: length <= beats; + `H_WRAP4, + `H_INCR4: length <= 9'h4; + `H_WRAP8, + `H_INCR8: length <= 9'h8; + `H_WRAP16, + `H_INCR16: length <= 9'h10; + endcase + else if ((reading | writing) & masterhready_in & ~add_go_r & ((masterhresp_in == `H_OKAY) | (masterhresp_in == `H_ERROR))) + length <= length - (|length); + + reg [8:0] address_length; + always @(posedge masterhclk_in or posedge reset) + if (reset) + address_length <= 5'h0; + else if (add_go) + case (burst) + `H_SINGLE: address_length <= 9'h1; + `H_INCR: address_length <= beats; + `H_WRAP4, + `H_INCR4: address_length <= 9'h4; + `H_WRAP8, + `H_INCR8: address_length <= 9'h8; + `H_WRAP16, + `H_INCR16: address_length <= 9'h10; + endcase + else if (data_bus_owned & ~masterhready_in & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT))) + address_length <= address_length + 9'h1; + else if (address_bus_owned & masterhready_in & ~(|busy_states) & (masterhtrans_out_r != `H_IDLE)) + address_length <= address_length - (|address_length); + else if (address_bus_owned & masterhready_in & (|busy_states) & (masterhtrans_out_r == `H_BUSY) & ~(|busy_counter)) + address_length <= address_length - (|address_length); + +/*---------------------------------------------------------------------------- +Bus request state machine + +Bus request machine follows the principle that the arbiter will generally +only re-assign bus grants at the end of a burst transaction. For defined +bursts masterhbusreq_out is removed as soon as we masterhave started the transaction. +Undefined (INCR) bursts will masterhold masterhbusreq_out asserted until the last beat of the +transaction. + +Locked transactions must always assert masterhlock_out for at least one cycle before +the address to be locked to allow the arbiter to see the lock. In practice, +this means inserting an idle cycle. + +Have to be careful using burst and beats from the control word. As soon as +the master address phase masterhas finished and the addr_ack is asserted the +testbench can change the control word. So don't use them after the initial +request. Use the ahb outputs instead which will tell us what sort of +transaction we're doing. +----------------------------------------------------------------------------*/ + reg [2:0] req_state; + parameter req_idle = 3'b000, + req_first = 3'b001, + req_wait = 3'b101, + req_masterhold = 3'b011, + req_using = 3'b010, + req_again = 3'b111; + assign masterhbusreq_out = start + | (req_state == req_first) + | (req_state == req_wait) + | (req_state == req_masterhold) + | (req_state == req_again); + + wire single_beat = (burst == `H_SINGLE) + | (burst == `H_INCR) & (beats == 9'b1); + + reg single_beat_r; + always @(posedge masterhclk_in) + if (addr_ack) + // save single_beat for use after it may masterhave changed + single_beat_r = single_beat; + + wire last_beat = address_bus_owned & masterhready_in & (address_length <= 9'b1); + wire retry = data_bus_owned & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT)); + wire error = data_bus_owned & masterhready_in & (masterhresp_in == `H_ERROR); + +/*---------------------------------------------------------------------------- +Bus request machine masterhas five states: +req_idle: masterhbusreq_out negated. Wmasterhen we want to do something we jump to req_first. +The last beat may get a retry response in which case we jump to +req_again. +req_first: masterhbusreq_out asserted. Wait masterhere for masterhgrant_in and until the transaction +starts. If granted and it's an undefined and not a single beat then +jump to req_masterhold. Else if it's a single beat jump to req_idle. +Otherwise jump to req_using. +req_masterhold: masterhbusreq_out asserted. Hold masterhbusreq_out asserted until last beat of an +undefined. If there's a new request then we jump to req_first, +otherwise back to req_idle. If we lose masterhgrant_in in this state then we +just stay masterhere with masterhbusreq_out asserted until the transaction can be +finished. Also masterhold in this state if retry is asserted to reduce the +chance of releaseing the bus and masterhaving to re-request it to complete +a transaction. +req_using: masterhbusreq_out negated. Wait masterhere for last beat of defined length +transaction. If there's a new request then we jump to req_first, +otherwise back to req_idle. If a posted write is errored before the +last beat or a transaction is retried or we lose masterhgrant_in then we jump +to req_again. +req_again: masterhbusreq_out asserted for completion of transaction interrupted by loss +of masterhgrant_in. Wait masterhere for masterhgrant_in and until the transaction starts then +jump to req_using if first_beat is asserted or req_masterhold if not. +*** We may see a new address toggle whilst in this state. +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in or posedge reset) + if (reset) + req_state <= req_idle; + else + case (req_state) + req_idle: + + if (retry) + req_state <= req_again; + else if (start) + req_state <= req_first; + + else + req_state <= req_idle; + + req_first: + if (retry) + req_state <= req_again; + else if (~masterhgrant_in & ~((masterhtrans_out_r == `H_NONSEQ) & masterhready_in)) + req_state <= req_first; + else if ((masterhtrans_out_r == `H_NONSEQ) & masterhready_in) + begin + if (add_go) + req_state <= req_first; + else if ((burst == `H_INCR) & ~single_beat) + req_state <= req_masterhold; + else if (single_beat) + req_state <= req_idle; + else + req_state <= req_using; + end + else + req_state <= req_wait; + + req_wait: + if (retry) + req_state <= req_again; + else if (~masterhgrant_in & ~((masterhtrans_out_r == `H_NONSEQ) & masterhready_in)) + req_state <= req_first; + else if (masterhgrant_in & ~((masterhtrans_out_r == `H_NONSEQ) & masterhready_in)) + req_state <= req_wait; + else if (add_go) + req_state <= req_first; + else if ((burst == `H_INCR) & ~single_beat) + req_state <= req_masterhold; + else if (single_beat_r) + req_state <= req_idle; + else + req_state <= req_using; + + req_masterhold: + if (error & ~continue_after_error) + req_state <= req_idle; + else if (~masterhgrant_in & (address_length > 9'b1) + | retry) + req_state <= req_again; + else if (last_beat) + begin + if (start) + req_state <= req_first; + else + req_state <= req_idle; + end + else if (add_go) + req_state <= req_first; + else + req_state <= req_masterhold; + + req_using: + if (error & ~continue_after_error) + req_state <= req_idle; + else if (last_beat) + begin + if (start) + req_state <= req_first; + else + req_state <= req_idle; + end + else if (~masterhgrant_in & (address_length > 9'b1) + | retry) + req_state <= req_again; + else + req_state <= req_using; + + req_again: + if (error & ~continue_after_error) + req_state <= req_idle; + else if ((~data_bus_owned + | data_bus_owned & (masterhresp_in == `H_OKAY)) + & address_bus_owned & (masterhtrans_out_r == `H_IDLE) & masterhready_in & ~masterhlock_out) + req_state <= req_idle; + else if (~masterhgrant_in & (address_length > 9'b1) + | ~((masterhtrans_out_r == `H_NONSEQ) & masterhready_in)) + req_state <= req_again; + else if (last_beat | (masterhburst_out_r == `H_SINGLE) + | (masterhburst_out_r == `H_INCR) & single_beat_r) + req_state <= req_idle; + else if (first_beat) + req_state <= req_using; + else + req_state <= req_masterhold; + + default: req_state <= req_idle; + endcase + +/*---------------------------------------------------------------------------- +Address acknowledge + +Signals when an address masterhas been transferred and a new one may be presented +for the next transaction. +----------------------------------------------------------------------------*/ + assign addr_ack = add_go; + +/*---------------------------------------------------------------------------- +Data acknowledge + +Signals when an address masterhas been transferred and a new one may be presented +for the next transaction. +----------------------------------------------------------------------------*/ + assign data_ack = data_go; + +/*---------------------------------------------------------------------------- +Bus ownership + +Data bus ownership follows address by one cycle +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in or posedge reset) + if (reset) + begin + address_bus_owned <= 1'b0; + data_bus_owned <= 1'b0; + end + else if (masterhready_in) + begin + address_bus_owned <= masterhgrant_in; + data_bus_owned <= address_bus_owned; + end + +/*---------------------------------------------------------------------------- +add_go enables the address phase for a new transaction (not the continuation +of a retried transaction or a transaction during which we lose the bus). + +It asserts immediately on address request if we're not actively using the bus +and not waiting for it to be re-granted to complete a previous transaction, +the (masterhtrans_out_r == `IDLE) term ensuring it only asserts for one clock. +----------------------------------------------------------------------------*/ + always @(start or masterhbusreq_out or masterhgrant_in or masterhready_in or reading + or writing or masterhtrans_out_r or req_state or length or reset) + if (start & masterhbusreq_out & masterhgrant_in & masterhready_in & ~reading & ~writing + & (masterhtrans_out_r == `H_IDLE) & (req_state != req_again) & ~reset) + add_go <= 1'b1; + else if (start & masterhbusreq_out & masterhgrant_in & masterhready_in & (length < 9'h2) & ~retry + & (masterhtrans_out_r != `H_BUSY) & (masterhtrans_out_r != `H_NONSEQ) & ~reset) + add_go <= 1'b1; + else + add_go <= 1'b0; + + +/*---------------------------------------------------------------------------- +data_go indicates the completion of the data phase for a transaction + +Like add_go it asserts when the master takes control of the address lines to +start a transaction. +It also asserts on all the accepted data beats of a burst except the last. +----------------------------------------------------------------------------*/ + wire trans_end = data_bus_owned & (reading | writing) & + masterhready_in & (masterhresp_in == `H_OKAY || masterhresp_in == `H_ERROR); + + always @(start or masterhbusreq_out or masterhgrant_in or masterhready_in or reading + or writing or masterhtrans_out_r or req_state or length or reset + or need_retry or trans_end ) + if (start & masterhbusreq_out & masterhgrant_in & masterhready_in & ~reading & ~writing + & (masterhtrans_out_r == `H_IDLE) & (req_state != req_again) & ~reset & ~need_retry) + data_go <= 1'b1; + else if (start & masterhbusreq_out & masterhgrant_in & masterhready_in & (address_length > 9'h1) & ~retry + & ~reset & (~need_retry|trans_end)) + data_go <= 1'b1; + else + data_go <= 1'b0; + + +/*---------------------------------------------------------------------------- +masterhwrite_out_r + +Updated on any clock that starts a new transaction +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in or posedge reset) + if (reset) + masterhwrite_out_r <= 1'b0; + else if (addr_ack) + masterhwrite_out_r <= write; + +/*---------------------------------------------------------------------------- +Transaction size + +Updated on any clock that starts a new transaction +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in or posedge reset) + if (reset) + masterhsize_outl <= 3'b0; + else if (addr_ack) + masterhsize_outl <= size; + +/*---------------------------------------------------------------------------- +Busy counter + +Insert BUSY states into burst transactions. + +Capture control word. Load counter on every active phase and decrement to +zero. +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in or posedge reset) + if (reset) + busy_states <= 1'b0; + else if (addr_ack) + busy_states <= insert_busy; + + always @(posedge masterhclk_in or posedge reset) + if (reset) + busy_counter <= 1'b0; + else if ((masterhtrans_out_r == `H_NONSEQ) | (masterhtrans_out_r == `H_SEQ)) + busy_counter <= busy_states - 1; + else + busy_counter <= busy_counter - (|busy_counter); + +/*---------------------------------------------------------------------------- +first_masterhtrans_out_r is asserted to enable the first beat of a transaction, which is +always NONSEQ: +- The first beat of a new transaction (addr_ack). +- To restart a transaction that was interrupted by loss of masterhgrant_in if we +receive a new masterhgrant_in whilst in req_again or req_masterhold states. +- To restart a transaction after a RETRY response. +- To restart a transaction after a SPLIT response. +pwd +- Break an undefined `INCR replay of a retried or split wrapping burst at +the wrap address boundary. +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in) + masterhgrant_in_r <= masterhgrant_in; + + wire masterhgrant_in_leading_edge = masterhgrant_in & ~masterhgrant_in_r; + + always @(posedge masterhclk_in or posedge reset) + if (reset) + new_grant <= 1'b0; + else if (masterhgrant_in_leading_edge & ~first_masterhtrans_out_r) + new_grant <= 1'b1; + else if (first_masterhtrans_out_r | ~masterhgrant_in) + new_grant <= 1'b0; + + assign first_masterhtrans_out_r = addr_ack + | (masterhgrant_in_leading_edge | masterhgrant_in & new_grant) & masterhready_in & ~masterhwrite_out_r + & ((req_state == req_masterhold) | (req_state == req_again)) + | (masterhgrant_in_leading_edge | masterhgrant_in & new_grant) & masterhready_in & masterhwrite_out_r + & ((req_state == req_masterhold) | (req_state == req_again)) + | data_bus_owned & masterhready_in & (masterhresp_in == `H_RETRY) + | data_bus_owned & masterhready_in & (masterhresp_in == `H_SPLIT) + | address_bus_owned & masterhready_in & ~first_beat + & break_wrap & (length > 9'b1); + +/*---------------------------------------------------------------------------- +The only time masterhtrans_out_r changes when masterhready_in is negated is during reset or after +the first cycle of a two-cyle error response. Otherwise, masterhtrans_out_r can only +change when masterhgrant_in and masterhready_in are asserted. +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in or posedge reset) + if (reset) + masterhtrans_out_r <= `H_IDLE; + else if (data_bus_owned & ~masterhready_in & (masterhresp_in != `H_OKAY) + & ~continue_after_error) // ERROR'ed transactions cancelled + masterhtrans_out_r <= `H_IDLE; + else if (data_bus_owned & ~masterhready_in & (masterhresp_in != `H_OKAY) & (masterhresp_in != `H_ERROR) + & continue_after_error) // ERROR'ed transactions not cancelled + masterhtrans_out_r <= `H_IDLE; + else if (masterhgrant_in & masterhready_in) + case (masterhtrans_out_r) + `H_IDLE: + if (first_masterhtrans_out_r) + masterhtrans_out_r <= `H_NONSEQ; + else + masterhtrans_out_r <= `H_IDLE; + `H_NONSEQ,`H_SEQ: + if (first_masterhtrans_out_r) + masterhtrans_out_r <= `H_NONSEQ; + else if ((masterhburst_out_r == `H_SINGLE) | (address_length <= 9'h1)) + // Last beat + masterhtrans_out_r <= `H_IDLE; + else if (go_busy) // (|busy_states) + masterhtrans_out_r <= `H_BUSY; + else + masterhtrans_out_r <= `H_SEQ; + + `H_BUSY: + if (first_masterhtrans_out_r) + masterhtrans_out_r <= `H_NONSEQ; + else if (go_busy) //(|busy_counter) + masterhtrans_out_r <= `H_BUSY; + else + masterhtrans_out_r <= `H_SEQ; + endcase + else if (masterhready_in & ~masterhgrant_in) + masterhtrans_out_r <= `H_IDLE; + +/*---------------------------------------------------------------------------- +One of reading or writing is asserted during any data beat for which we are +actively using the bus. +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in or posedge reset) + if (reset) + begin + reading <= 1'b0; + writing <= 1'b0; + end + else if (masterhready_in) + begin + reading <= ~masterhwrite_out_r & address_bus_owned + & (masterhtrans_out_r != `H_IDLE) & (masterhtrans_out_r != `H_BUSY); + writing <= masterhwrite_out_r & address_bus_owned + & (masterhtrans_out_r != `H_IDLE) & (masterhtrans_out_r != `H_BUSY); + end + +/*---------------------------------------------------------------------------- +Burst size + +first_beat is used to keep masterhburst_out_r unchanged when the first beat is to be +replayed. It alse controls the bus request. A transaction that is split or +retried on any other beat will be replayed as INCR and masterhbusreq_out must be masterheld +asserted. + +Tmasterhis means that a defined length read that us interrupted mid-burst will +complete as an undefined INCR and may pre-fetch past the end of the defined +length (unless, of course, no_prefetch is asserted). +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in or posedge reset) + if (reset) + first_beat <= 1'b0; + else if (addr_ack) + first_beat <= 1'b1; + else if (data_bus_owned & (reading | writing) & masterhready_in & (masterhresp_in == `H_OKAY)) + first_beat <= 1'b0; + + always @(posedge masterhclk_in or posedge reset) + if (reset) + masterhburst_out_r <= 3'b0; + else if (addr_ack) + masterhburst_out_r <= burst; + else if (first_masterhtrans_out_r & ~first_beat) + masterhburst_out_r <= `H_INCR; + +/*---------------------------------------------------------------------------- +need_retry +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in or posedge reset) + if (reset) + need_retry <= 1'b0; + else if (data_bus_owned & ~masterhready_in & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT))) + need_retry <= 1'b1; + else if (data_bus_owned & masterhready_in & (reading | writing) + & ((masterhresp_in == `H_OKAY) | (masterhresp_in == `H_ERROR))) + need_retry <= 1'b0; + + always @(posedge masterhclk_in or posedge reset) + if (reset) + wrap <= 1'b0; + else if (addr_ack) + wrap <= (burst == `H_WRAP4) | (burst == `H_WRAP8) + | (burst == `H_WRAP16); + + always @(posedge masterhclk_in or posedge reset) + if (reset) + original_burst <= 3'b0; + else if (addr_ack) + original_burst <= burst; + + always @(posedge masterhclk_in or posedge reset) + if (reset) + replay_wrap <= 3'b0; + else if (addr_ack) + replay_wrap <= 3'b0; + else if (data_bus_owned & ~masterhready_in & wrap & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT))) + replay_wrap <= 3'b1; + +/*---------------------------------------------------------------------------- +Compute wrap mask + +Used to modify next_masterhaddr_out_r during wrapping bursts. First case statement forms +a mask based on the transfer size. Tmasterhis is then shifted left with '1's +inserted to form the final mask. E.g. masterhsize_outl == word (3'b010) wrapped at a +four beat boundary results in wrap_mask set to 10'b0000001111 allowing the +four lsbs of the address to increment and wrap addressing sixteen bytes in +total. +----------------------------------------------------------------------------*/ + always @(masterhsize_outl) + case (masterhsize_outl) + 3'b000: init_wrap_mask <= 10'b0; + 3'b001: init_wrap_mask <= 10'b1; + 3'b010: init_wrap_mask <= 10'b11; + 3'b011: init_wrap_mask <= 10'b111; + 3'b100: init_wrap_mask <= 10'b1111; + 3'b101: init_wrap_mask <= 10'b11111; + 3'b110: init_wrap_mask <= 10'b111111; + 3'b111: init_wrap_mask <= 10'b1111111; + endcase + + always @(original_burst or init_wrap_mask) + case (original_burst) + `H_WRAP4: wrap_mask <= {init_wrap_mask[7:0], 2'b11}; + `H_WRAP8: wrap_mask <= {init_wrap_mask[6:0], 3'b111}; + `H_WRAP16: wrap_mask <= {init_wrap_mask[5:0], 4'b1111}; + default: wrap_mask <= 10'b0; + endcase + + always @(masterhsize_outl) + case (masterhsize_outl) + 3'b000: init_wrap_boundary_bit <= 8'b1; + 3'b001: init_wrap_boundary_bit <= 8'b10; + 3'b010: init_wrap_boundary_bit <= 8'b100; + 3'b011: init_wrap_boundary_bit <= 8'b1000; + 3'b100: init_wrap_boundary_bit <= 8'b10000; + 3'b101: init_wrap_boundary_bit <= 8'b100000; + 3'b110: init_wrap_boundary_bit <= 8'b1000000; + 3'b111: init_wrap_boundary_bit <= 8'b10000000; + endcase + + always @(original_burst or init_wrap_boundary_bit) + case (original_burst) + `H_WRAP4: wrap_boundary_bit <= {init_wrap_boundary_bit, 2'b0}; + `H_WRAP8: wrap_boundary_bit <= {init_wrap_boundary_bit, 3'b0}; + `H_WRAP16:wrap_boundary_bit <= {init_wrap_boundary_bit[6:0], 4'b0}; + default: wrap_boundary_bit <= 11'b0; + endcase + +/*---------------------------------------------------------------------------- +Compute address increment + +Tmasterhis code allows for all possibilities by inferring a 3-to-8 decoder on the +transfer size. AHB spec is unclear masterhow a burst with a transfer size greater +than the bus width should be masterhandled. +----------------------------------------------------------------------------*/ + always @(masterhsize_outl) + begin + masterhaddr_out_r_inc <= 10'b0; + masterhaddr_out_r_inc[masterhsize_outl] <= 1'b1; + end + +/*---------------------------------------------------------------------------- +Compute next address + +Next address is based on the increment computed from the transfer size, and +the burst type, which may tell us to wrap. Wrapping is achieved by preserving +some of the upper bits through use of wrap_mask. + +If beat n is retried, we're already putting out the address for beat n+1 so +we need to decrement. +----------------------------------------------------------------------------*/ + always @(data_bus_owned or masterhresp_in or masterhready_in or masterhaddr_out_r or masterhaddr_out_r_inc) + if (data_bus_owned & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT))) + init_next_masterhaddr_out_r <= {1'b0, masterhaddr_out_r[9:0]} - masterhaddr_out_r_inc; + else + init_next_masterhaddr_out_r <= {1'b0, masterhaddr_out_r[9:0]} + masterhaddr_out_r_inc; + + always @(original_burst or wrap_mask or init_next_masterhaddr_out_r or masterhaddr_out_r) + if ((original_burst == `H_WRAP4) | (original_burst == `H_WRAP8) + | (original_burst == `H_WRAP16)) + next_masterhaddr_out_r <= wrap_mask & init_next_masterhaddr_out_r | ~wrap_mask & masterhaddr_out_r; + else + next_masterhaddr_out_r <= init_next_masterhaddr_out_r; + + assign break_wrap = replay_wrap & ((|(init_next_masterhaddr_out_r & wrap_boundary_bit)) + ^ (|(masterhaddr_out_r[10:0] & wrap_boundary_bit))); + +/*---------------------------------------------------------------------------- +Address Generation + +AHB address has to track the changing address during bursts. next_masterhaddr_out_r +computes the next address. + +NOTE: It is incumbent upon the command file not to attempt a transaction that +would cross a 1Kbyte address boundary. + +Address is normally updated after each address phase. It is also updated +during the second cycle of a two cycle retry or split response to rewind the +address and allow the transaction to be replayed. +----------------------------------------------------------------------------*/ + always @(posedge masterhclk_in or posedge reset) + if (reset) + masterhaddr_out_r <= 32'b0; + else if (addr_ack) + masterhaddr_out_r <= start_address; + else if (data_bus_owned & masterhready_in & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT))) + masterhaddr_out_r[9:0] <= next_masterhaddr_out_r; + else if (address_bus_owned & masterhready_in + & ((masterhtrans_out_r == `H_NONSEQ) | (masterhtrans_out_r == `H_SEQ))) + masterhaddr_out_r[9:0] <= next_masterhaddr_out_r; + +/*---------------------------------------------------------------------------- +Write Data + +If generate_data is negated then initial data is taken from data input. If +generate_data is asserted then data is generated from the address offset to +match that expected by the checkers. + +The expected data and the transaction number follow the write data. + +At the end of a burst data is set to x so we can ensure nothing is relying on +invalid data. +----------------------------------------------------------------------------*/ + + reg [31:0] masterhwdata_out_r_pipe; + reg [31:0] masterhwdata_out_r_retry; + + always @(posedge masterhclk_in) + if (data_bus_owned & ~masterhready_in & (masterhresp_in==`H_RETRY||masterhresp_in==`H_SPLIT)) + begin + masterhwdata_out_r_retry <= masterhwdata_out_r; + end + else if (addr_ack || data_ack) + masterhwdata_out_r_pipe <= data; + + + wire [7:0] addr_offset = {masterhaddr_out_r[7:2], 2'b0}; + + always @(posedge masterhclk_in or posedge reset) + if (reset) + masterhwdata_out_r <= {32{1'b0}}; + else if (~address_bus_owned & masterhready_in) + masterhwdata_out_r <= {32{1'b0}}; + else if (masterhready_in & ~generate_data) + begin + if (address_bus_owned & masterhwrite_out_r & need_retry & ~trans_end) + masterhwdata_out_r <= masterhwdata_out_r_retry; + else if (address_bus_owned & masterhwrite_out_r & (masterhtrans_out_r == `H_NONSEQ)) + masterhwdata_out_r <= masterhwdata_out_r_pipe; + else if ((length == 9'b0)) + masterhwdata_out_r <= {32{1'b0}}; + else if (address_bus_owned & masterhwrite_out_r & (masterhtrans_out_r == `H_SEQ)) + masterhwdata_out_r <= masterhwdata_out_r_pipe; + else + masterhwdata_out_r <= {32{1'b0}}; + end + else if (masterhready_in & generate_data) + begin + if (address_bus_owned & masterhwrite_out_r & (masterhtrans_out_r == `H_NONSEQ)) + masterhwdata_out_r <= {addr_offset, addr_offset, addr_offset, addr_offset}; + else if ((length == 9'b0)) + masterhwdata_out_r <= {32{1'b0}}; + else if (address_bus_owned & masterhwrite_out_r & (masterhtrans_out_r == `H_SEQ)) + masterhwdata_out_r <= {addr_offset, addr_offset, addr_offset, addr_offset}; + end + +/*---------------------------------------------------------------------------- +Transaction Details + +The transactor pipeline consists of four stages + +n_trans - the next transaction from the store +c_trans - the current control / address stage transaction +d_trans - the data stage transaction +rTrans - the completed stage for reporting + + +c_trans is updated from n_trans when a new transaction begins or from d_trans in +the case of split/retry +----------------------------------------------------------------------------*/ + + always @(posedge masterhclk_in) + if (data_bus_owned & ~masterhready_in & (masterhresp_in==`H_RETRY||masterhresp_in==`H_SPLIT)) + begin +// c_trans<=d_trans; // RETRY/SPLIT causes transaction to be replayed + retry_trans<=d_trans; + end + else if (addr_ack || data_ack) + begin + c_trans<=n_trans; + end + + always @(posedge masterhclk_in or posedge reset) + if (address_bus_owned & masterhready_in & ~reset & (~need_retry|trans_end) ) + begin + d_trans <= c_trans; + d_trans[107:76] <= masterhaddr_out_r; + d_trans[72] <= masterhwrite_out_r; + d_trans[36] <= masterhlock_out; + d_trans[29:28] <= masterhtrans_out_r; + d_trans[21:20] <= masterhburst_out_r; + d_trans[18:16] <= masterhsize_out; + end + else if (address_bus_owned & masterhready_in & ~reset & need_retry ) + begin + d_trans <= retry_trans; + d_trans[107:76] <= masterhaddr_out_r; + d_trans[72] <= masterhwrite_out_r; + d_trans[36] <= masterhlock_out; + d_trans[29:28] <= masterhtrans_out_r; + d_trans[21:20] <= masterhburst_out_r; + d_trans[18:16] <= masterhsize_out; + end + else if ( ( ~address_bus_owned & masterhready_in) | reset) + d_trans<= i_trans; + + + always @(posedge masterhclk_in) + if (trans_end & ~need_retry) + begin + r_trans[253:252]<=masterhresp_in; + r_trans[251:220]<=masterhrdata_in; + r_trans[219:0] <=d_trans[219:0]; + end + else if (trans_end & need_retry) + begin + r_trans[253:252]<=masterhresp_in; + r_trans[251:220]<=masterhrdata_in; + r_trans[219:0] <=retry_trans[219:0]; + end + else + r_trans<=i_trans; + + +/*---------------------------------------------------------------------------- +masterhlock_out +----------------------------------------------------------------------------*/ + assign masterhlock_out = 1'b0; +/*---------------------------------------------------------------------------- +----------------------------------------------------------------------------*/ +endmodule // alt_exc_upcore + +//START_MODULE_NAME------------------------------------------------------------ +// +// Module 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_MODULE_NAME-------------------------------------------------------------- + +`timescale 1 ps / 1 ps + +module altsquare ( + data, + clock, + ena, + aclr, + result +); + +// GLOBAL PARAMETER DECLARATION + parameter data_width = 1; + parameter result_width = 1; + parameter pipeline = 0; + parameter representation = "UNSIGNED"; + parameter lpm_hint = "UNUSED"; + parameter lpm_type = "altsquare"; + + // INPUT PORT DECLARATION + input [data_width - 1 : 0] data; + input clock; + input ena; + input aclr; + + // OUTPUT PORT DECLARATION + output [result_width - 1 : 0] result; + + // INTERNAL REGISTER DECLARATION + reg [result_width - 1 : 0]stage_values[pipeline : 0]; + reg [data_width - 1 : 0] pos_data_value; + + // LOCAL INTEGER DECLARATION + integer i; + + // INTERNAL WIRE DECLARATION + wire i_clock; + wire i_aclr; + wire i_clken; +// INTERNAL TRI DECLARATION + tri0 aclr; + tri1 clock; + tri1 clken; + + buf (i_clock, clock); + buf (i_aclr, aclr); + buf (i_clken, ena); + + + // INITIAL CONSTRUCT BLOCK + initial + begin : INITIALIZE + if(data_width < 1) + begin + $display("data_width (%d) must be greater than 0.(ERROR)\n", data_width); + $finish; + end + if(result_width < 1) + begin + $display("result_width (%d) must be greater than 0.(ERROR)\n", result_width); + $finish; + end + end // INITIALIZE + + // ALWAYS CONSTRUCT BLOCK + always @(data or i_aclr) + begin + if (i_aclr) // clear the pipeline + for (i = 0; i <= pipeline; i = i + 1) + stage_values[i] = 'b0; + else + begin + if ((representation == "SIGNED") && (data[data_width - 1] == 1)) + pos_data_value = (~data) + 1; + else + pos_data_value = data; + + stage_values[pipeline] = pos_data_value * pos_data_value; + end + end + + // Pipeline model + always @(posedge i_clock) + begin + if (!i_aclr && i_clken == 1) + begin + for(i = 0; i < pipeline; i = i + 1) + stage_values[i] <= stage_values[i + 1]; + end + end + + // CONTINOUS ASSIGNMENT + assign result = stage_values[0]; +endmodule // altsquare +// END OF MODULE + +module sld_signaltap ( + ir_in, + update, + acq_trigger_out, + acq_data_in, + jtag_state_udr, + shift, + trigger_in, + trigger_out, + jtag_state_cdr, + acq_trigger_in, + usr1, + clrn, + jtag_state_uir, + rti, + jtag_state_e1dr, + ena, + tdi, + crc, + irq, + tdo, + jtag_state_sdr); + + parameter SLD_NODE_CRC_LOWORD = 50132; + parameter SLD_RAM_BLOCK_TYPE = "AUTO"; + parameter SLD_ADVANCED_TRIGGER_ENTITY = "basic"; + parameter SLD_ADVANCED_TRIGGER_1 = "NONE"; + parameter SLD_MEM_ADDRESS_BITS = 7; + parameter SLD_TRIGGER_BITS = 8; + parameter SLD_ADVANCED_TRIGGER_2 = "NONE"; + parameter SLD_TRIGGER_LEVEL = 1; + parameter SLD_ADVANCED_TRIGGER_3 = "NONE"; + parameter SLD_ADVANCED_TRIGGER_4 = "NONE"; + parameter SLD_ADVANCED_TRIGGER_5 = "NONE"; + parameter SLD_ADVANCED_TRIGGER_6 = "NONE"; + parameter SLD_ENABLE_ADVANCED_TRIGGER = 0; + parameter SLD_NODE_CRC_HIWORD = 41394; + parameter SLD_ADVANCED_TRIGGER_7 = "NONE"; + parameter SLD_TRIGGER_LEVEL_PIPELINE = 1; + parameter SLD_ADVANCED_TRIGGER_8 = "NONE"; + parameter SLD_ADVANCED_TRIGGER_9 = "NONE"; + parameter SLD_INCREMENTAL_ROUTING = 0; + parameter SLD_ADVANCED_TRIGGER_10 = "NONE"; + parameter SLD_TRIGGER_IN_ENABLED = 1; + parameter SLD_NODE_CRC_BITS = 32; + parameter SLD_SAMPLE_DEPTH = 128; + parameter SLD_DATA_BIT_CNTR_BITS = 4; + parameter SLD_DATA_BITS = 8; + + parameter ELA_STATUS_BITS = 3; + parameter MAX_NUMBER_OF_BITS_FOR_TRIGGERS = 4; + parameter SLD_IR_BITS = ELA_STATUS_BITS + MAX_NUMBER_OF_BITS_FOR_TRIGGERS; + + input [SLD_IR_BITS-1:0] ir_in; + input update; + output [SLD_TRIGGER_BITS-1:0] acq_trigger_out; + input [SLD_DATA_BITS-1:0] acq_data_in; + input jtag_state_udr; + input shift; + input trigger_in; + output trigger_out; + input jtag_state_cdr; + input [SLD_TRIGGER_BITS-1:0] acq_trigger_in; + input usr1; + input clrn; + input jtag_state_uir; + input rti; + input jtag_state_e1dr; + input ena; + input tdi; + input [SLD_NODE_CRC_BITS-1:0] crc; + output irq; + output tdo; + input jtag_state_sdr; + +endmodule //sld_signaltap + +module altstratixii_oct ( + rup, + terminationclock, + terminationenable, + rdn); + + parameter lpm_type = "altstratixii_oct"; + + + input rup; + input terminationclock; + input terminationenable; + input rdn; + +endmodule //altstratixii_oct + diff --git a/opencores/ethernet_tri_mode/bench/verilog/host_sim.v b/opencores/ethernet_tri_mode/bench/verilog/host_sim.v new file mode 100644 index 000000000..45c25d756 --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/verilog/host_sim.v @@ -0,0 +1,77 @@ + +module host_sim + (input Reset , + input Clk_reg , + output reg CSB , + output reg WRB , + output reg CPU_init_end , + output reg [15:0] CD_in , + input [15:0] CD_out , + output reg [7:0] CA + ); + + //////////////////////////////////////// + task CPU_init; + begin + CA =0; + CD_in =0; + WRB =1; + CSB =1; + end + endtask + + //////////////////////////////////////// + task CPU_wr; + input[6:0] Addr; + input[15:0] Data; + begin + CA ={Addr,1'b0}; + CD_in =Data; + WRB =0; + CSB =0; + #20; + CA =0; + CD_in =0; + WRB =1; + CSB =1; + #20; + end + endtask + ///////////////////////////////////////// + task CPU_rd; + input[6:0] Addr; + begin + CA ={Addr,1'b0}; + WRB =1; + CSB =0; + #20; + CA =0; + WRB =1; + CSB =1; + #20; + end + endtask + ///////////////////////////////////////// + + integer i; + + reg [31:0] CPU_data [255:0]; + reg [7:0] write_times; + reg [7:0] write_add; + reg [15:0] write_data; + + initial + begin + CPU_init; + CPU_init_end=0; + $readmemh("../data/CPU.vec",CPU_data); + {write_times,write_add,write_data}=CPU_data[0]; + #90 ; + for (i=0;i<write_times;i=i+1) + begin + {write_times,write_add,write_data}=CPU_data[i]; + CPU_wr(write_add[6:0],write_data); + end + CPU_init_end=1; + end +endmodule // host_sim diff --git a/opencores/ethernet_tri_mode/bench/verilog/reg_int_sim.v b/opencores/ethernet_tri_mode/bench/verilog/reg_int_sim.v new file mode 100644 index 000000000..9894129a6 --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/verilog/reg_int_sim.v @@ -0,0 +1,135 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// reg_int_sim.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: reg_int_sim.v,v $ +// Revision 1.1 2005/12/13 12:54:38 maverickist +// first simulation passed +// + +module reg_int_sim ( +input Reset , +input Clk_reg , + //Tx host interface +output [4:0] Tx_Hwmark , +output [4:0] Tx_Lwmark , +output pause_frame_send_en , +output [15:0] pause_quanta_set , +output MAC_tx_add_en , +output FullDuplex , +output [3:0] MaxRetry , +output [5:0] IFGset , +output [7:0] MAC_tx_add_prom_data , +output [2:0] MAC_tx_add_prom_add , +output MAC_tx_add_prom_wr , +output tx_pause_en , +output xoff_cpu , +output xon_cpu , + //Rx host interface +output MAC_rx_add_chk_en , +output [7:0] MAC_rx_add_prom_data , +output [2:0] MAC_rx_add_prom_add , +output MAC_rx_add_prom_wr , +output broadcast_filter_en , +output [15:0] broadcast_MAX , +output RX_APPEND_CRC , +output CRC_chk_en , +output [5:0] RX_IFG_SET , +output [15:0] RX_MAX_LENGTH ,// 1518 +output [6:0] RX_MIN_LENGTH ,// 64 + //RMON host interface +output [5:0] CPU_rd_addr , +output CPU_rd_apply , +input CPU_rd_grant , +input [31:0] CPU_rd_dout , + //Phy int host interface +output Line_loop_en , +output [2:0] Speed , + //MII to CPU +output [7:0] Divider ,// Divider for the host clock +output [15:0] CtrlData ,// Control Data (to be written to the PHY reg.) +output [4:0] Rgad ,// Register Address (within the PHY) +output [4:0] Fiad ,// PHY Address +output NoPre ,// No Preamble (no 32-bit preamble) +output WCtrlData ,// Write Control Data operation +output RStat ,// Read Status operation +output ScanStat ,// Scan Status operation +input Busy ,// Busy Signal +input LinkFail ,// Link Integrity Signal +input Nvalid ,// Invalid Status (qualifier for the valid scan result) +input [15:0] Prsd ,// Read Status Data (data read from the PHY) +input WCtrlDataStart ,// This signals resets the WCTRLDATA bit in the MIIM Command register +input RStatStart ,// This signal resets the RSTAT BIT in the MIIM Command register +input UpdateMIIRX_DATAReg ,// Updates MII RX_DATA register with read data +); + + assign Tx_Hwmark =5'h1e; + assign Tx_Lwmark =5'h19; + assign pause_frame_send_en =0; + assign pause_quanta_set =0; + assign MAC_tx_add_en =0; + assign FullDuplex =1; + assign MaxRetry =2; + assign IFGset =10; + assign MAC_tx_add_prom_data =0; + assign MAC_tx_add_prom_add =0; + assign MAC_tx_add_prom_wr =0; + assign tx_pause_en =0; + assign xoff_cpu =0; + assign xon_cpu =0; + + assign MAC_rx_add_chk_en =0; + assign MAC_rx_add_prom_data =0; + assign MAC_rx_add_prom_add =0; + assign MAC_rx_add_prom_wr =0; + assign broadcast_filter_en =0; + assign broadcast_MAX =10; + assign RX_APPEND_CRC =0; + assign CRC_chk_en =1; + assign RX_IFG_SET =10; + assign RX_MAX_LENGTH =1518; + assign RX_MIN_LENGTH =64; + + assign CPU_rd_addr =0; + assign CPU_rd_apply =0; + + assign Line_loop_en =0; + assign Speed =3'b001; + +endmodule // reg_int_sim diff --git a/opencores/ethernet_tri_mode/bench/verilog/tb_top.v b/opencores/ethernet_tri_mode/bench/verilog/tb_top.v new file mode 100644 index 000000000..fdce18900 --- /dev/null +++ b/opencores/ethernet_tri_mode/bench/verilog/tb_top.v @@ -0,0 +1,230 @@ +`timescale 1 ns/100ps +////////////////////////////////////////////////////////////////////// +//// //// +//// tb_top.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: tb_top.v,v $ +// Revision 1.3 2006/01/19 14:07:51 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:13 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module tb_top (); + // ****************************************************************************** + //internal signals + // ****************************************************************************** + //system signals + + reg Reset ; + reg Clk_125M ; + reg Clk_user ; + reg Clk_reg ; + //user interface + wire Rx_mac_ra ; + wire Rx_mac_rd ; + wire [31:0] Rx_mac_data ; + wire [1:0] Rx_mac_BE ; + wire Rx_mac_pa ; + wire Rx_mac_sop ; + wire Rx_mac_eop ; + //user interface + wire Tx_mac_wa ; + wire Tx_mac_wr ; + wire [31:0] Tx_mac_data ; + wire [1:0] Tx_mac_BE ;//big endian + wire Tx_mac_sop ; + wire Tx_mac_eop ; + //Phy interface + //Phy interface + wire Gtx_clk ;//used only in GMII mode + wire Rx_clk ; + wire Tx_clk ;//used only in MII mode + wire Tx_er ; + wire Tx_en ; + wire [7:0] Txd ; + wire Rx_er ; + wire Rx_dv ; + wire [7:0] Rxd ; + wire Crs ; + wire Col ; + wire CSB ; + wire WRB ; + wire [15:0] CD_in ; + wire [15:0] CD_out ; + wire [7:0] CA ; + //Phy int host interface + wire Line_loop_en ; + wire [2:0] Speed ; + //mii + wire Mdio ;// MII Management Data In + wire Mdc ;// MII Management Data Clock + wire CPU_init_end ; + // ****************************************************************************** + //internal signals + // ****************************************************************************** + + initial + begin + Reset =1; + #20 Reset =0; + end + always + begin + #4 Clk_125M=0; + #4 Clk_125M=1; + end + + always + begin + #5 Clk_user=0; + #5 Clk_user=1; + end + + always + begin + #10 Clk_reg=0; + #10 Clk_reg=1; + end + +// initial + // begin + //$shm_open("tb_top.shm",,900000000,); +// $shm_probe("AS"); + // end + + MAC_top + U_MAC_top(//system signals (//system signals ), + .Reset (Reset ), + .Clk_125M (Clk_125M ), + .Clk_user (Clk_user ), + .Clk_reg (Clk_reg ), + .Speed (Speed ), + //user interface (//user interface ), + .Rx_mac_ra (Rx_mac_ra ), + .Rx_mac_rd (Rx_mac_rd ), + .Rx_mac_data (Rx_mac_data ), + .Rx_mac_BE (Rx_mac_BE ), + .Rx_mac_pa (Rx_mac_pa ), + .Rx_mac_sop (Rx_mac_sop ), + .Rx_mac_eop (Rx_mac_eop ), + //user interface (//user interface ), + .Tx_mac_wa (Tx_mac_wa ), + .Tx_mac_wr (Tx_mac_wr ), + .Tx_mac_data (Tx_mac_data ), + .Tx_mac_BE (Tx_mac_BE ), + .Tx_mac_sop (Tx_mac_sop ), + .Tx_mac_eop (Tx_mac_eop ), + //Phy interface (//Phy interface ), + //Phy interface (//Phy interface ), + .Gtx_clk (Gtx_clk ), + .Rx_clk (Rx_clk ), + .Tx_clk (Tx_clk ), + .Tx_er (Tx_er ), + .Tx_en (Tx_en ), + .Txd (Txd ), + .Rx_er (Rx_er ), + .Rx_dv (Rx_dv ), + .Rxd (Rxd ), + .Crs (Crs ), + .Col (Col ), + //host interface + .CSB (CSB ), + .WRB (WRB ), + .CD_in (CD_in ), + .CD_out (CD_out ), + .CA (CA ), + //MII interface signals (//MII interface signals ), + .Mdio (Mdio ), + .Mdc (Mdc ) + ); + + Phy_sim + U_Phy_sim (.Gtx_clk (Gtx_clk ), + .Rx_clk (Rx_clk ), + .Tx_clk (Tx_clk ), + .Tx_er (Tx_er ), + .Tx_en (Tx_en ), + .Txd (Txd ), + .Rx_er (Rx_er ), + .Rx_dv (Rx_dv ), + .Rxd (Rxd ), + .Crs (Crs ), + .Col (Col ), + .Speed (Speed ) + ); + + User_int_sim + U_User_int_sim(.Reset (Reset ), + .Clk_user (Clk_user ), + .CPU_init_end (CPU_init_end ), + //user inputerface (//user inputerface ), + .Rx_mac_ra (Rx_mac_ra ), + .Rx_mac_rd (Rx_mac_rd ), + .Rx_mac_data (Rx_mac_data ), + .Rx_mac_BE (Rx_mac_BE ), + .Rx_mac_pa (Rx_mac_pa ), + .Rx_mac_sop (Rx_mac_sop ), + .Rx_mac_eop (Rx_mac_eop ), + //user inputerface (//user inputerface ), + .Tx_mac_wa (Tx_mac_wa ), + .Tx_mac_wr (Tx_mac_wr ), + .Tx_mac_data (Tx_mac_data ), + .Tx_mac_BE (Tx_mac_BE ), + .Tx_mac_sop (Tx_mac_sop ), + .Tx_mac_eop (Tx_mac_eop ) + ); + + host_sim + U_host_sim(.Reset (Reset ), + .Clk_reg (Clk_reg ), + .CSB (CSB ), + .WRB (WRB ), + .CD_in (CD_in ), + .CD_out (CD_out ), + .CPU_init_end (CPU_init_end ), + .CA (CA ) + ); + +endmodule // tb_top diff --git a/opencores/ethernet_tri_mode/cmdfile b/opencores/ethernet_tri_mode/cmdfile new file mode 100644 index 000000000..a56b8b900 --- /dev/null +++ b/opencores/ethernet_tri_mode/cmdfile @@ -0,0 +1,7 @@ +-y rtl/verilog +-y rtl/verilog/TECH +-y rtl/verilog/MAC_tx +-y rtl/verilog/MAC_rx +-y rtl/verilog/RMON +-y rtl/verilog/miim ++incdir+rtl/verilog diff --git a/opencores/ethernet_tri_mode/doc/CVS/Entries b/opencores/ethernet_tri_mode/doc/CVS/Entries new file mode 100644 index 000000000..48fb2f5ff --- /dev/null +++ b/opencores/ethernet_tri_mode/doc/CVS/Entries @@ -0,0 +1,3 @@ +/Tri-mode_Ethernet_MAC_Specifications.pdf/1.1/Wed Jan 25 12:08:33 2006/-kb/ +/Tri-mode_Ethernet_MAC_Verification_plan.pdf/1.1/Thu Jan 19 14:24:14 2006/-kb/ +D diff --git a/opencores/ethernet_tri_mode/doc/CVS/Repository b/opencores/ethernet_tri_mode/doc/CVS/Repository new file mode 100644 index 000000000..3d4be542f --- /dev/null +++ b/opencores/ethernet_tri_mode/doc/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/doc diff --git a/opencores/ethernet_tri_mode/doc/CVS/Root b/opencores/ethernet_tri_mode/doc/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/doc/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/doc/CVS/Template b/opencores/ethernet_tri_mode/doc/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/doc/CVS/Template diff --git a/opencores/ethernet_tri_mode/doc/Tri-mode_Ethernet_MAC_Specifications.pdf b/opencores/ethernet_tri_mode/doc/Tri-mode_Ethernet_MAC_Specifications.pdf Binary files differnew file mode 100644 index 000000000..06daff9f5 --- /dev/null +++ b/opencores/ethernet_tri_mode/doc/Tri-mode_Ethernet_MAC_Specifications.pdf diff --git a/opencores/ethernet_tri_mode/doc/Tri-mode_Ethernet_MAC_Verification_plan.pdf b/opencores/ethernet_tri_mode/doc/Tri-mode_Ethernet_MAC_Verification_plan.pdf Binary files differnew file mode 100644 index 000000000..b68e7a764 --- /dev/null +++ b/opencores/ethernet_tri_mode/doc/Tri-mode_Ethernet_MAC_Verification_plan.pdf diff --git a/opencores/ethernet_tri_mode/rtl/CVS/Entries b/opencores/ethernet_tri_mode/rtl/CVS/Entries new file mode 100644 index 000000000..428c5622d --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/CVS/Entries @@ -0,0 +1 @@ +D/verilog//// diff --git a/opencores/ethernet_tri_mode/rtl/CVS/Repository b/opencores/ethernet_tri_mode/rtl/CVS/Repository new file mode 100644 index 000000000..d904089e2 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/rtl diff --git a/opencores/ethernet_tri_mode/rtl/CVS/Root b/opencores/ethernet_tri_mode/rtl/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/rtl/CVS/Template b/opencores/ethernet_tri_mode/rtl/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/CVS/Template diff --git a/opencores/ethernet_tri_mode/rtl/verilog/CVS/Entries b/opencores/ethernet_tri_mode/rtl/verilog/CVS/Entries new file mode 100644 index 000000000..3f044b135 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/CVS/Entries @@ -0,0 +1,14 @@ +/Clk_ctrl.v/1.3/Thu Jan 19 14:07:52 2006// +/MAC_rx.v/1.4/Fri Nov 17 17:53:07 2006// +/MAC_tx.v/1.4/Fri Nov 17 17:53:07 2006// +/Phy_int.v/1.3/Thu Jan 19 14:07:53 2006// +/RMON.v/1.4/Sun Jun 25 04:58:56 2006// +/eth_miim.v/1.3/Thu Jan 19 14:07:53 2006// +/reg_int.v/1.4/Fri Nov 17 17:53:07 2006// +D/MAC_rx//// +D/MAC_tx//// +D/RMON//// +D/TECH//// +D/miim//// +/MAC_top.v/1.3/Tue May 1 07:30:08 2007// +/header.v/1.1/Tue May 1 07:35:45 2007// diff --git a/opencores/ethernet_tri_mode/rtl/verilog/CVS/Repository b/opencores/ethernet_tri_mode/rtl/verilog/CVS/Repository new file mode 100644 index 000000000..157eb42bc --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/rtl/verilog diff --git a/opencores/ethernet_tri_mode/rtl/verilog/CVS/Root b/opencores/ethernet_tri_mode/rtl/verilog/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/rtl/verilog/CVS/Template b/opencores/ethernet_tri_mode/rtl/verilog/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/CVS/Template diff --git a/opencores/ethernet_tri_mode/rtl/verilog/Clk_ctrl.v b/opencores/ethernet_tri_mode/rtl/verilog/Clk_ctrl.v new file mode 100644 index 000000000..853c4007d --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/Clk_ctrl.v @@ -0,0 +1,127 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Clk_ctrl.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: Clk_ctrl.v,v $ +// Revision 1.3 2006/01/19 14:07:52 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:13 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module Clk_ctrl( +Reset , +Clk_125M , +//host interface, +Speed , +//Phy interface , +Gtx_clk , +Rx_clk , +Tx_clk , +//interface clk , +MAC_tx_clk , +MAC_rx_clk , +MAC_tx_clk_div , +MAC_rx_clk_div +); +input Reset ; +input Clk_125M ; + //host interface +input [2:0] Speed ; + //Phy interface +output Gtx_clk ;//used only in GMII mode +input Rx_clk ; +input Tx_clk ;//used only in MII mode + //interface clk signals +output MAC_tx_clk ; +output MAC_rx_clk ; +output MAC_tx_clk_div ; +output MAC_rx_clk_div ; + + +//****************************************************************************** +//internal signals +//****************************************************************************** +wire Rx_clk_div2 ; +wire Tx_clk_div2 ; +//****************************************************************************** +// +//****************************************************************************** +assign Gtx_clk =Clk_125M ; +assign MAC_rx_clk =Rx_clk ; + +clkdiv2 U_0_CLK_DIV2( +.Reset (Reset ), +.IN (Rx_clk ), +.OUT (Rx_clk_div2 ) +); + +clkdiv2 U_1_CLK_DIV2( +.Reset (Reset ), +.IN (Tx_clk ), +.OUT (Tx_clk_div2 ) +); + +CLK_SWITCH U_0_CLK_SWITCH( +.IN_0 (Rx_clk_div2 ), +.IN_1 (Rx_clk ), +.SW (Speed[2] ), +.OUT (MAC_rx_clk_div ) +); + +CLK_SWITCH U_1_CLK_SWITCH( +.IN_0 (Tx_clk ), +.IN_1 (Clk_125M ), +.SW (Speed[2] ), +.OUT (MAC_tx_clk ) +); + + +CLK_SWITCH U_2_CLK_SWITCH( +.IN_0 (Tx_clk_div2 ), +.IN_1 (Clk_125M ), +.SW (Speed[2] ), +.OUT (MAC_tx_clk_div ) +); +endmodule diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx.v new file mode 100644 index 000000000..4120d9f70 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx.v @@ -0,0 +1,230 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_rx.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_rx.v,v $ +// Revision 1.4 2006/11/17 17:53:07 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:52 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:13 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// +module MAC_rx ( +input Reset , +input Clk_user, +input Clk , + //RMII interface +input MCrs_dv , +input [7:0] MRxD , +input MRxErr , + //flow_control signals +output [15:0] pause_quanta , +output pause_quanta_val , + //user interface +output Rx_mac_ra , +input Rx_mac_rd , +output [31:0] Rx_mac_data , +output [1:0] Rx_mac_BE , +output Rx_mac_pa , +output Rx_mac_sop , +output Rx_mac_eop , + //CPU +input MAC_rx_add_chk_en , +input [7:0] MAC_add_prom_data , +input [2:0] MAC_add_prom_add , +input MAC_add_prom_wr , +input broadcast_filter_en , +input [15:0] broadcast_bucket_depth , +input [15:0] broadcast_bucket_interval , +input RX_APPEND_CRC, +input [4:0] Rx_Hwmark , +input [4:0] Rx_Lwmark , +input CRC_chk_en , +input [5:0] RX_IFG_SET , +input [15:0] RX_MAX_LENGTH ,// 1518 +input [6:0] RX_MIN_LENGTH ,// 64 + //RMON interface +output [15:0] Rx_pkt_length_rmon , +output Rx_apply_rmon , +output [2:0] Rx_pkt_err_type_rmon , +output [2:0] Rx_pkt_type_rmon +); +//****************************************************************************** +//internal signals +//****************************************************************************** + //CRC_chk interface +wire CRC_en ; +wire CRC_init; +wire CRC_err ; + //MAC_rx_add_chk interface +wire MAC_add_en ; +wire MAC_rx_add_chk_err ; + //broadcast_filter +wire broadcast_ptr ; +wire broadcast_drop ; + //flow_control signals +//wire [15:0] pause_quanta ; +//wire pause_quanta_val ; + //MAC_rx_ctrl interface +wire [7:0] Fifo_data ; +wire Fifo_data_en ; +wire Fifo_full ; +wire Fifo_data_err ; +wire Fifo_data_end ; +//****************************************************************************** +//instantiation +//****************************************************************************** + + +MAC_rx_ctrl U_MAC_rx_ctrl( +.Reset (Reset ), +.Clk (Clk ), + //RMII interface ( //RMII interface ), +.MCrs_dv (MCrs_dv ), +.MRxD (MRxD ), +.MRxErr (MRxErr ), + //CRC_chk interface (//CRC_chk interface ), +.CRC_en (CRC_en ), +.CRC_init (CRC_init ), +.CRC_err (CRC_err ), + //MAC_rx_add_chk interface (//MAC_rx_add_chk interface), +.MAC_add_en (MAC_add_en ), +.MAC_rx_add_chk_err (MAC_rx_add_chk_err ), + //broadcast_filter (//broadcast_filter ), +.broadcast_ptr (broadcast_ptr ), +.broadcast_drop (broadcast_drop ), + //flow_control signals (//flow_control signals ), +.pause_quanta (pause_quanta ), +.pause_quanta_val (pause_quanta_val ), + //MAC_rx_FF interface (//MAC_rx_FF interface ), +.Fifo_data (Fifo_data ), +.Fifo_data_en (Fifo_data_en ), +.Fifo_data_err (Fifo_data_err ), +.Fifo_data_end (Fifo_data_end ), +.Fifo_full (Fifo_full ), + //RMON interface (//RMON interface ), +.Rx_pkt_type_rmon (Rx_pkt_type_rmon ), +.Rx_pkt_length_rmon (Rx_pkt_length_rmon ), +.Rx_apply_rmon (Rx_apply_rmon ), +.Rx_pkt_err_type_rmon (Rx_pkt_err_type_rmon ), + //CPU (//CPU ), +.RX_IFG_SET (RX_IFG_SET ), +.RX_MAX_LENGTH (RX_MAX_LENGTH ), +.RX_MIN_LENGTH (RX_MIN_LENGTH ) +); + +MAC_rx_FF #(.MAC_RX_FF_DEPTH(9)) + U_MAC_rx_FF (.Reset (Reset ), + .Clk_MAC (Clk ), + .Clk_SYS (Clk_user ), + //MAC_rx_ctrl interface (//MAC_rx_ctrl interface ), + .Fifo_data (Fifo_data ), + .Fifo_data_en (Fifo_data_en ), + .Fifo_full (Fifo_full ), + .Fifo_data_err (Fifo_data_err ), + .Fifo_data_end (Fifo_data_end ), + //CPU (//CPU ), + .Rx_Hwmark (Rx_Hwmark ), + .Rx_Lwmark (Rx_Lwmark ), + .RX_APPEND_CRC (RX_APPEND_CRC ), + //user interface (//user interface ), + .Rx_mac_ra (Rx_mac_ra ), + .Rx_mac_rd (Rx_mac_rd ), + .Rx_mac_data (Rx_mac_data ), + .Rx_mac_BE (Rx_mac_BE ), + .Rx_mac_sop (Rx_mac_sop ), + .Rx_mac_pa (Rx_mac_pa ), + .Rx_mac_eop (Rx_mac_eop ) + ); + +`ifdef MAC_BROADCAST_FILTER_EN +Broadcast_filter U_Broadcast_filter( +.Reset (Reset ), +.Clk (Clk ), + //MAC_rx_ctrl (//MAC_rx_ctrl ), +.broadcast_ptr (broadcast_ptr ), +.broadcast_drop (broadcast_drop ), + //FromCPU (//FromCPU ), +.broadcast_filter_en (broadcast_filter_en ), +.broadcast_bucket_depth (broadcast_bucket_depth ), +.broadcast_bucket_interval (broadcast_bucket_interval ) +); +`else +assign broadcast_drop=0; +`endif + +CRC_chk U_CRC_chk( +.Reset (Reset ), +.Clk (Clk ), +.CRC_data (Fifo_data ), +.CRC_init (CRC_init ), +.CRC_en (CRC_en ), + //From CPU (//From CPU ), +.CRC_chk_en (CRC_chk_en ), +.CRC_err (CRC_err ) +); + +`ifdef MAC_TARGET_CHECK_EN +MAC_rx_add_chk U_MAC_rx_add_chk( +.Reset (Reset ), +.Clk (Clk ), +.Init (CRC_init ), +.data (Fifo_data ), +.MAC_add_en (MAC_add_en ), +.MAC_rx_add_chk_err (MAC_rx_add_chk_err ), + //From CPU (//From CPU ), +.MAC_rx_add_chk_en (MAC_rx_add_chk_en ), +.MAC_add_prom_data (MAC_add_prom_data ), +.MAC_add_prom_add (MAC_add_prom_add ), +.MAC_add_prom_wr (MAC_add_prom_wr ) +); +`else +assign MAC_rx_add_chk_err=0; +`endif + + + +endmodule diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/Broadcast_filter.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/Broadcast_filter.v new file mode 100644 index 000000000..143720a64 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/Broadcast_filter.v @@ -0,0 +1,107 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Broadcast_filter.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: Broadcast_filter.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:16 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module Broadcast_filter ( +Reset , +Clk , +//MAC_rx_ctrl , +broadcast_ptr , +broadcast_drop , +//FromCPU , +broadcast_filter_en , +broadcast_bucket_depth , +broadcast_bucket_interval +); +input Reset ; +input Clk ; + //MAC_rx_ctrl +input broadcast_ptr ; +output broadcast_drop ; + //FromCPU ; +input broadcast_filter_en ; +input [15:0] broadcast_bucket_depth ; +input [15:0] broadcast_bucket_interval ; + +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [15:0] time_counter ; +reg [15:0] broadcast_counter ; +reg broadcast_drop ; +//****************************************************************************** +// +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + time_counter <=0; + else if (time_counter==broadcast_bucket_interval) + time_counter <=0; + else + time_counter <=time_counter+1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + broadcast_counter <=0; + else if (time_counter==broadcast_bucket_interval) + broadcast_counter <=0; + else if (broadcast_ptr&&broadcast_counter!=broadcast_bucket_depth) + broadcast_counter <=broadcast_counter+1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + broadcast_drop <=0; + else if(broadcast_filter_en&&broadcast_counter==broadcast_bucket_depth) + broadcast_drop <=1; + else + broadcast_drop <=0; + +endmodule
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CRC_chk.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CRC_chk.v new file mode 100644 index 000000000..b90240ce6 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CRC_chk.v @@ -0,0 +1,129 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// CRC_chk.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CRC_chk.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:16 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module CRC_chk( +Reset , +Clk , +CRC_data , +CRC_init , +CRC_en , +//From CPU +CRC_chk_en , +CRC_err +); +input Reset ; +input Clk ; +input[7:0] CRC_data ; +input CRC_init ; +input CRC_en ; + //From CPU +input CRC_chk_en ; +output CRC_err ; +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [31:0] CRC_reg; +wire[31:0] Next_CRC; +//****************************************************************************** +//input data width is 8bit, and the first bit is bit[0] +function[31:0] NextCRC; + input[7:0] D; + input[31:0] C; + reg[31:0] NewCRC; + begin + NewCRC[0]=C[24]^C[30]^D[1]^D[7]; + NewCRC[1]=C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[2]=C[26]^D[5]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[3]=C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[4]=C[28]^D[3]^C[27]^D[4]^C[26]^D[5]^C[24]^C[30]^D[1]^D[7]; + NewCRC[5]=C[29]^D[2]^C[28]^D[3]^C[27]^D[4]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[6]=C[30]^D[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[7]=C[31]^D[0]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7]; + NewCRC[8]=C[0]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7]; + NewCRC[9]=C[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6]; + NewCRC[10]=C[2]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7]; + NewCRC[11]=C[3]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7]; + NewCRC[12]=C[4]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[13]=C[5]^C[30]^D[1]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[14]=C[6]^C[31]^D[0]^C[30]^D[1]^C[28]^D[3]^C[27]^D[4]^C[26]^D[5]; + NewCRC[15]=C[7]^C[31]^D[0]^C[29]^D[2]^C[28]^D[3]^C[27]^D[4]; + NewCRC[16]=C[8]^C[29]^D[2]^C[28]^D[3]^C[24]^D[7]; + NewCRC[17]=C[9]^C[30]^D[1]^C[29]^D[2]^C[25]^D[6]; + NewCRC[18]=C[10]^C[31]^D[0]^C[30]^D[1]^C[26]^D[5]; + NewCRC[19]=C[11]^C[31]^D[0]^C[27]^D[4]; + NewCRC[20]=C[12]^C[28]^D[3]; + NewCRC[21]=C[13]^C[29]^D[2]; + NewCRC[22]=C[14]^C[24]^D[7]; + NewCRC[23]=C[15]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[24]=C[16]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[25]=C[17]^C[27]^D[4]^C[26]^D[5]; + NewCRC[26]=C[18]^C[28]^D[3]^C[27]^D[4]^C[24]^C[30]^D[1]^D[7]; + NewCRC[27]=C[19]^C[29]^D[2]^C[28]^D[3]^C[25]^C[31]^D[0]^D[6]; + NewCRC[28]=C[20]^C[30]^D[1]^C[29]^D[2]^C[26]^D[5]; + NewCRC[29]=C[21]^C[31]^D[0]^C[30]^D[1]^C[27]^D[4]; + NewCRC[30]=C[22]^C[31]^D[0]^C[28]^D[3]; + NewCRC[31]=C[23]^C[29]^D[2]; + NextCRC=NewCRC; + end + endfunction + +always @ (posedge Clk or posedge Reset) + if (Reset) + CRC_reg <=32'hffffffff; + else if (CRC_init) + CRC_reg <=32'hffffffff; + else if (CRC_en) + CRC_reg <=NextCRC(CRC_data,CRC_reg); + +assign CRC_err = CRC_chk_en&(CRC_reg[31:0] != 32'hc704dd7b); + +endmodule
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Entries b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Entries new file mode 100644 index 000000000..d90cf273e --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Entries @@ -0,0 +1,6 @@ +/Broadcast_filter.v/1.3/Thu Jan 19 14:07:54 2006// +/CRC_chk.v/1.3/Thu Jan 19 14:07:54 2006// +/MAC_rx_FF.v/1.5/Sun Jun 25 04:58:56 2006// +/MAC_rx_add_chk.v/1.3/Thu Jan 19 14:07:54 2006// +/MAC_rx_ctrl.v/1.4/Sun Jun 25 04:58:56 2006// +D diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Repository b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Repository new file mode 100644 index 000000000..eed695850 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/rtl/verilog/MAC_rx diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Root b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Template b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/CVS/Template diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/MAC_rx_FF.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/MAC_rx_FF.v new file mode 100644 index 000000000..5b5c98ec8 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/MAC_rx_FF.v @@ -0,0 +1,659 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_rx_FF.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_rx_FF.v,v $ +// Revision 1.5 2006/06/25 04:58:56 maverickist +// no message +// +// Revision 1.4 2006/05/28 05:09:20 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.3 2005/12/16 06:44:16 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.2 2005/12/13 12:15:37 Administrator +// no message +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module MAC_rx_FF + #(parameter MAC_RX_FF_DEPTH = 9) + (Reset,Clk_MAC,Clk_SYS, + //MAC_rx_ctrl interface + Fifo_data,Fifo_data_en,Fifo_full,Fifo_data_err,Fifo_data_end, + //CPU + Rx_Hwmark,Rx_Lwmark,RX_APPEND_CRC, + //user interface + Rx_mac_ra,Rx_mac_rd,Rx_mac_data,Rx_mac_BE,Rx_mac_sop,Rx_mac_pa,Rx_mac_eop); + + input Reset; + input Clk_MAC ; + input Clk_SYS ; + //MAC_rx_ctrl interface + input [7:0] Fifo_data ; + input Fifo_data_en ; + output Fifo_full ; + input Fifo_data_err ; + input Fifo_data_end ; + //CPU + input RX_APPEND_CRC ; + input [4:0] Rx_Hwmark ; + input [4:0] Rx_Lwmark ; + //user interface + output Rx_mac_ra ;// + input Rx_mac_rd ; + output [31:0] Rx_mac_data ; + output [1:0] Rx_mac_BE ; + output Rx_mac_pa ; + output Rx_mac_sop ; + output Rx_mac_eop ; + + // ****************************************************************************** + //internal signals + // ****************************************************************************** + parameter State_byte3 =4'd0; + parameter State_byte2 =4'd1; + parameter State_byte1 =4'd2; + parameter State_byte0 =4'd3; + parameter State_be0 =4'd4; + parameter State_be3 =4'd5; + parameter State_be2 =4'd6; + parameter State_be1 =4'd7; + parameter State_err_end =4'd8; + parameter State_idle =4'd9; + + parameter SYS_read =3'd0; + parameter SYS_pause =3'd1; + parameter SYS_wait_end =3'd2; + parameter SYS_idle =3'd3; + parameter FF_emtpy_err =3'd4; + + reg [MAC_RX_FF_DEPTH-1:0] Add_wr; + reg [MAC_RX_FF_DEPTH-1:0] Add_wr_ungray; + reg [MAC_RX_FF_DEPTH-1:0] Add_wr_gray; + reg [MAC_RX_FF_DEPTH-1:0] Add_wr_gray_dl1; + reg [MAC_RX_FF_DEPTH-1:0] Add_wr_reg; + + reg [MAC_RX_FF_DEPTH-1:0] Add_rd; + reg [MAC_RX_FF_DEPTH-1:0] Add_rd_gray; + reg [MAC_RX_FF_DEPTH-1:0] Add_rd_gray_dl1; + reg [MAC_RX_FF_DEPTH-1:0] Add_rd_ungray; + reg [35:0] Din; + reg [35:0] Din_tmp; + reg [35:0] Din_tmp_reg; + wire [35:0] Dout; + reg Wr_en; + reg Wr_en_tmp; + reg Wr_en_ptr; + wire [MAC_RX_FF_DEPTH-1:0] Add_wr_pluse; + wire [MAC_RX_FF_DEPTH-1:0] Add_wr_pluse4; + wire [MAC_RX_FF_DEPTH-1:0] Add_wr_pluse3; + wire [MAC_RX_FF_DEPTH-1:0] Add_wr_pluse2; + reg Full; + reg Almost_full; + reg Empty /* synthesis syn_keep=1 */; + reg [3:0] Current_state /* synthesis syn_keep=1 */; + reg [3:0] Next_state; + reg [7:0] Fifo_data_byte0; + reg [7:0] Fifo_data_byte1; + reg [7:0] Fifo_data_byte2; + reg [7:0] Fifo_data_byte3; + reg Fifo_data_en_dl1; + reg [7:0] Fifo_data_dl1; + reg Rx_mac_sop_tmp ; + reg Rx_mac_sop ; + reg Rx_mac_ra ; + reg Rx_mac_pa ; + + + + reg [2:0] Current_state_SYS /* synthesis syn_keep=1 */; + reg [2:0] Next_state_SYS ; + reg [5:0] Packet_number_inFF /* synthesis syn_keep=1 */; + reg Packet_number_sub ; + wire Packet_number_add_edge; + reg Packet_number_add_dl1; + reg Packet_number_add_dl2; + reg Packet_number_add ; + reg Packet_number_add_tmp ; + reg Packet_number_add_tmp_dl1; + reg Packet_number_add_tmp_dl2; + + reg Rx_mac_sop_tmp_dl1; + reg [35:0] Dout_dl1; + reg [4:0] Fifo_data_count; + reg Rx_mac_pa_tmp ; + reg Add_wr_jump_tmp ; + reg Add_wr_jump_tmp_pl1 ; + reg Add_wr_jump ; + reg Add_wr_jump_rd_pl1 ; + reg [4:0] Rx_Hwmark_pl ; + reg [4:0] Rx_Lwmark_pl ; + integer i ; + + // ****************************************************************************** + //domain Clk_MAC,write data to dprom.a-port for write + // ****************************************************************************** + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Current_state <=State_idle; + else + Current_state <=Next_state; + + always @(Current_state or Fifo_data_en or Fifo_data_err or Fifo_data_end) + case (Current_state) + State_idle: + if (Fifo_data_en) + Next_state =State_byte3; + else + Next_state =Current_state; + State_byte3: + if (Fifo_data_en) + Next_state =State_byte2; + else if (Fifo_data_err) + Next_state =State_err_end; + else if (Fifo_data_end) + Next_state =State_be1; + else + Next_state =Current_state; + State_byte2: + if (Fifo_data_en) + Next_state =State_byte1; + else if (Fifo_data_err) + Next_state =State_err_end; + else if (Fifo_data_end) + Next_state =State_be2; + else + Next_state =Current_state; + State_byte1: + if (Fifo_data_en) + Next_state =State_byte0; + else if (Fifo_data_err) + Next_state =State_err_end; + else if (Fifo_data_end) + Next_state =State_be3; + else + Next_state =Current_state; + State_byte0: + if (Fifo_data_en) + Next_state =State_byte3; + else if (Fifo_data_err) + Next_state =State_err_end; + else if (Fifo_data_end) + Next_state =State_be0; + else + Next_state =Current_state; + State_be1: + Next_state =State_idle; + State_be2: + Next_state =State_idle; + State_be3: + Next_state =State_idle; + State_be0: + Next_state =State_idle; + State_err_end: + Next_state =State_idle; + default: + Next_state =State_idle; + endcase + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_wr_reg <=0; + else if (Current_state==State_idle) + Add_wr_reg <=Add_wr; + + always @ (posedge Reset or posedge Clk_MAC) + if (Reset) + Add_wr_gray <=0; + else + begin + Add_wr_gray[MAC_RX_FF_DEPTH-1] <=Add_wr[MAC_RX_FF_DEPTH-1]; + for (i=MAC_RX_FF_DEPTH-2;i>=0;i=i-1) + Add_wr_gray[i] <=Add_wr[i+1]^Add_wr[i]; + end + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_gray_dl1 <=0; + else + Add_rd_gray_dl1 <=Add_rd_gray; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_ungray =0; + else + begin + Add_rd_ungray[MAC_RX_FF_DEPTH-1] =Add_rd_gray_dl1[MAC_RX_FF_DEPTH-1]; + for (i=MAC_RX_FF_DEPTH-2;i>=0;i=i-1) + Add_rd_ungray[i] =Add_rd_ungray[i+1]^Add_rd_gray_dl1[i]; + end + assign Add_wr_pluse=Add_wr+1; + assign Add_wr_pluse4=Add_wr+4; + assign Add_wr_pluse3=Add_wr+3; + assign Add_wr_pluse2=Add_wr+2; + + + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Full <=0; + else if (Add_wr_pluse==Add_rd_ungray) + Full <=1; + else + Full <=0; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Almost_full <=0; + else if (Add_wr_pluse4==Add_rd_ungray|| + Add_wr_pluse3==Add_rd_ungray|| + Add_wr_pluse2==Add_rd_ungray|| + Add_wr_pluse==Add_rd_ungray + ) + Almost_full <=1; + else + Almost_full <=0; + + assign Fifo_full =Almost_full; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_wr <=0; + else if (Current_state==State_err_end) + Add_wr <=Add_wr_reg; + else if (Wr_en&&!Full) + Add_wr <=Add_wr +1; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_wr_jump_tmp <=0; + else if (Current_state==State_err_end) + Add_wr_jump_tmp <=1; + else + Add_wr_jump_tmp <=0; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_wr_jump_tmp_pl1 <=0; + else + Add_wr_jump_tmp_pl1 <=Add_wr_jump_tmp; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_wr_jump <=0; + else if (Current_state==State_err_end) + Add_wr_jump <=1; + else if (Add_wr_jump_tmp_pl1) + Add_wr_jump <=0; + + // + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_data_en_dl1 <=0; + else + Fifo_data_en_dl1 <=Fifo_data_en; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_data_dl1 <=0; + else + Fifo_data_dl1 <=Fifo_data; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_data_byte3 <=0; + else if (Current_state==State_byte3&&Fifo_data_en_dl1) + Fifo_data_byte3 <=Fifo_data_dl1; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_data_byte2 <=0; + else if (Current_state==State_byte2&&Fifo_data_en_dl1) + Fifo_data_byte2 <=Fifo_data_dl1; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_data_byte1 <=0; + else if (Current_state==State_byte1&&Fifo_data_en_dl1) + Fifo_data_byte1 <=Fifo_data_dl1; + + always @ (* ) + case (Current_state) + State_be0: + Din_tmp ={4'b1000,Fifo_data_byte3,Fifo_data_byte2,Fifo_data_byte1,Fifo_data_dl1}; + State_be1: + Din_tmp ={4'b1001,Fifo_data_byte3,24'h0}; + State_be2: + Din_tmp ={4'b1010,Fifo_data_byte3,Fifo_data_byte2,16'h0}; + State_be3: + Din_tmp ={4'b1011,Fifo_data_byte3,Fifo_data_byte2,Fifo_data_byte1,8'h0}; + default: + Din_tmp ={4'b0000,Fifo_data_byte3,Fifo_data_byte2,Fifo_data_byte1,Fifo_data_dl1}; + endcase + + always @ (*) + if (Current_state==State_be0||Current_state==State_be1|| + Current_state==State_be2||Current_state==State_be3|| + (Current_state==State_byte0&&Fifo_data_en)) + Wr_en_tmp =1; + else + Wr_en_tmp =0; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Din_tmp_reg <=0; + else if(Wr_en_tmp) + Din_tmp_reg <=Din_tmp; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Wr_en_ptr <=0; + else if(Current_state==State_idle) + Wr_en_ptr <=0; + else if(Wr_en_tmp) + Wr_en_ptr <=1; + + //if not append FCS,delay one cycle write data and Wr_en signal to drop FCS + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + begin + Wr_en <=0; + Din <=0; + end + else if(RX_APPEND_CRC) + begin + Wr_en <=Wr_en_tmp; + Din <=Din_tmp; + end + else + begin + Wr_en <=Wr_en_tmp&&Wr_en_ptr; + Din <={Din_tmp[35:32],Din_tmp_reg[31:0]}; + end + + //this signal for read side to handle the packet number in fifo + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Packet_number_add_tmp <=0; + else if (Current_state==State_be0||Current_state==State_be1|| + Current_state==State_be2||Current_state==State_be3) + Packet_number_add_tmp <=1; + else + Packet_number_add_tmp <=0; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + begin + Packet_number_add_tmp_dl1 <=0; + Packet_number_add_tmp_dl2 <=0; + end + else + begin + Packet_number_add_tmp_dl1 <=Packet_number_add_tmp; + Packet_number_add_tmp_dl2 <=Packet_number_add_tmp_dl1; + end + + //Packet_number_add delay to Din[35] is needed to make sure the data have been wroten to ram. + //expand to two cycles long almost=16 ns + //if the Clk_SYS period less than 16 ns ,this signal need to expand to 3 or more clock cycles + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Packet_number_add <=0; + else if (Packet_number_add_tmp_dl1||Packet_number_add_tmp_dl2) + Packet_number_add <=1; + else + Packet_number_add <=0; + + // ****************************************************************************** + // domain Clk_SYS,read data from dprom.b-port for read + // ****************************************************************************** + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Current_state_SYS <=SYS_idle; + else + Current_state_SYS <=Next_state_SYS; + + always @ (Current_state_SYS or Rx_mac_rd or Rx_mac_ra or Dout or Empty) + case (Current_state_SYS) + SYS_idle: + if (Rx_mac_rd&&Rx_mac_ra&&!Empty) + Next_state_SYS =SYS_read; + else if(Rx_mac_rd&&Rx_mac_ra&&Empty) + Next_state_SYS =FF_emtpy_err; + else + Next_state_SYS =Current_state_SYS; + SYS_read: + if (!Rx_mac_rd) + Next_state_SYS =SYS_pause; + else if (Dout[35]) + Next_state_SYS =SYS_wait_end; + else if (Empty) + Next_state_SYS =FF_emtpy_err; + else + Next_state_SYS =Current_state_SYS; + SYS_pause: + if (Rx_mac_rd) + Next_state_SYS =SYS_read; + else + Next_state_SYS =Current_state_SYS; + FF_emtpy_err: + if (!Empty) + Next_state_SYS =SYS_read; + else + Next_state_SYS =Current_state_SYS; + SYS_wait_end: + if (!Rx_mac_rd) + Next_state_SYS =SYS_idle; + else + Next_state_SYS =Current_state_SYS; + default: + Next_state_SYS =SYS_idle; + endcase // case(Current_state_SYS) + + //gen Rx_mac_ra + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Packet_number_add_dl1 <=0; + Packet_number_add_dl2 <=0; + end + else + begin + Packet_number_add_dl1 <=Packet_number_add; + Packet_number_add_dl2 <=Packet_number_add_dl1; + end + assign Packet_number_add_edge=Packet_number_add_dl1&!Packet_number_add_dl2; + + always @ (Current_state_SYS or Next_state_SYS) + if (Current_state_SYS==SYS_read&&Next_state_SYS==SYS_wait_end) + Packet_number_sub =1; + else + Packet_number_sub =0; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Packet_number_inFF <=0; + else if (Packet_number_add_edge&&!Packet_number_sub) + Packet_number_inFF <=Packet_number_inFF + 1; + else if (!Packet_number_add_edge&&Packet_number_sub&&Packet_number_inFF!=0) + Packet_number_inFF <=Packet_number_inFF - 1; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Fifo_data_count <=0; + else + Fifo_data_count <=Add_wr_ungray[MAC_RX_FF_DEPTH-1:MAC_RX_FF_DEPTH-5]-Add_rd[MAC_RX_FF_DEPTH-1:MAC_RX_FF_DEPTH-5]; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Rx_Hwmark_pl <=0; + Rx_Lwmark_pl <=0; + end + else + begin + Rx_Hwmark_pl <=Rx_Hwmark; + Rx_Lwmark_pl <=Rx_Lwmark; + end + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Rx_mac_ra <=0; + else if (Packet_number_inFF==0&&Fifo_data_count<=Rx_Lwmark_pl) + Rx_mac_ra <=0; + else if (Packet_number_inFF>=1||Fifo_data_count>=Rx_Hwmark_pl) + Rx_mac_ra <=1; + + + //control Add_rd signal; + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_rd <=0; + else if (Current_state_SYS==SYS_read&&!Dout[35]) + Add_rd <=Add_rd + 1; + + // + always @ (posedge Reset or posedge Clk_SYS) + if (Reset) + Add_rd_gray <=0; + else + begin + Add_rd_gray[MAC_RX_FF_DEPTH-1] <=Add_rd[MAC_RX_FF_DEPTH-1]; + for (i=MAC_RX_FF_DEPTH-2;i>=0;i=i-1) + Add_rd_gray[i] <=Add_rd[i+1]^Add_rd[i]; + end + // + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_wr_gray_dl1 <=0; + else + Add_wr_gray_dl1 <=Add_wr_gray; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_wr_jump_rd_pl1 <=0; + else + Add_wr_jump_rd_pl1 <=Add_wr_jump; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_wr_ungray =0; + else if (!Add_wr_jump_rd_pl1) + begin + Add_wr_ungray[MAC_RX_FF_DEPTH-1] =Add_wr_gray_dl1[MAC_RX_FF_DEPTH-1]; + for (i=MAC_RX_FF_DEPTH-2;i>=0;i=i-1) + Add_wr_ungray[i] =Add_wr_ungray[i+1]^Add_wr_gray_dl1[i]; + end + //empty signal gen + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Empty <=1; + else if (Add_rd==Add_wr_ungray) + Empty <=1; + else + Empty <=0; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Dout_dl1 <=0; + else + Dout_dl1 <=Dout; + + assign Rx_mac_data =Dout_dl1[31:0]; + assign Rx_mac_BE =Dout_dl1[33:32]; + assign Rx_mac_eop =Dout_dl1[35]; + + //aligned to Addr_rd + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Rx_mac_pa_tmp <=0; + else if (Current_state_SYS==SYS_read&&!Dout[35]) + Rx_mac_pa_tmp <=1; + else + Rx_mac_pa_tmp <=0; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Rx_mac_pa <=0; + else + Rx_mac_pa <=Rx_mac_pa_tmp; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Rx_mac_sop_tmp <=0; + else if (Current_state_SYS==SYS_idle&&Next_state_SYS==SYS_read) + Rx_mac_sop_tmp <=1; + else + Rx_mac_sop_tmp <=0; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Rx_mac_sop_tmp_dl1 <=0; + Rx_mac_sop <=0; + end + else + begin + Rx_mac_sop_tmp_dl1 <=Rx_mac_sop_tmp; + Rx_mac_sop <=Rx_mac_sop_tmp_dl1; + end + + //****************************************************************************** + + duram #(36,MAC_RX_FF_DEPTH) + U_duram(.data_a (Din ), + .wren_a (Wr_en ), + .address_a (Add_wr ), + .address_b (Add_rd ), + .clock_a (Clk_MAC ), + .clock_b (Clk_SYS ), + .q_b (Dout )); + +endmodule // MAC_rx_FF diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/MAC_rx_add_chk.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/MAC_rx_add_chk.v new file mode 100644 index 000000000..1019779e7 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/MAC_rx_add_chk.v @@ -0,0 +1,156 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_rx_add_chk.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/wr_en/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_rx_add_chk.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:17 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module MAC_rx_add_chk ( +Reset , +Clk , +Init , +data , +MAC_add_en , +MAC_rx_add_chk_err , +//From CPU +MAC_rx_add_chk_en , +MAC_add_prom_data , +MAC_add_prom_add , +MAC_add_prom_wr + +); +input Reset ; +input Clk ; +input Init ; +input [7:0] data ; +input MAC_add_en ; +output MAC_rx_add_chk_err ; + //From CPU +input MAC_rx_add_chk_en ; +input [7:0] MAC_add_prom_data ; +input [2:0] MAC_add_prom_add ; +input MAC_add_prom_wr ; + +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [2:0] addr_rd; +wire[2:0] addr_wr; +wire[7:0] din; +wire[7:0] dout; +wire wr_en; + +reg MAC_rx_add_chk_err; +reg MAC_add_prom_wr_dl1; +reg MAC_add_prom_wr_dl2; +reg [7:0] data_dl1 ; +reg MAC_add_en_dl1 ; +//****************************************************************************** +//write data from cpu to prom +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + data_dl1 <=0; + MAC_add_en_dl1 <=0; + end + else + begin + data_dl1 <=data; + MAC_add_en_dl1 <=MAC_add_en; + end + +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + MAC_add_prom_wr_dl1 <=0; + MAC_add_prom_wr_dl2 <=0; + end + else + begin + MAC_add_prom_wr_dl1 <=MAC_add_prom_wr; + MAC_add_prom_wr_dl2 <=MAC_add_prom_wr_dl1; + end + +assign wr_en =MAC_add_prom_wr_dl1&!MAC_add_prom_wr_dl2; +assign addr_wr =MAC_add_prom_add; +assign din =MAC_add_prom_data; + +//****************************************************************************** +//mac add verify +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + addr_rd <=0; + else if (Init) + addr_rd <=0; + else if (MAC_add_en) + addr_rd <=addr_rd + 1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + MAC_rx_add_chk_err <=0; + else if (Init) + MAC_rx_add_chk_err <=0; + else if (MAC_rx_add_chk_en&&MAC_add_en_dl1&&dout!=data_dl1) + MAC_rx_add_chk_err <=1; + + +//****************************************************************************** +//a port for read ,b port for write . +//****************************************************************************** +duram #(8,3,"M512","DUAL_PORT") U_duram( +.data_a (din ), +.wren_a (wr_en ), +.address_a (addr_wr ), +.address_b (addr_rd ), +.clock_a (Clk ), +.clock_b (Clk ), +.q_b (dout )); + +endmodule diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/MAC_rx_ctrl.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/MAC_rx_ctrl.v new file mode 100644 index 000000000..247014986 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_rx/MAC_rx_ctrl.v @@ -0,0 +1,536 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_rx_ctrl.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_rx_ctrl.v,v $ +// Revision 1.4 2006/06/25 04:58:56 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.3 2005/12/16 06:44:17 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.2 2005/12/13 12:15:37 Administrator +// no message +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module MAC_rx_ctrl ( +Reset , +Clk , +//RMII interface +MCrs_dv , // +MRxD , // +MRxErr , // +//CRC_chk interface +CRC_en , +CRC_init , +CRC_err , +//MAC_rx_add_chk interface +MAC_add_en , +MAC_rx_add_chk_err , +//broadcast_filter +broadcast_ptr , +broadcast_drop , +//flow_control signals +pause_quanta , +pause_quanta_val , +//MAC_rx_FF interface +Fifo_data , +Fifo_data_en , +Fifo_data_err , +Fifo_data_end , +Fifo_full , +//RMON interface +Rx_pkt_type_rmon , +Rx_pkt_length_rmon , +Rx_apply_rmon , +Rx_pkt_err_type_rmon , +//CPU +RX_IFG_SET , +RX_MAX_LENGTH, +RX_MIN_LENGTH +); + +input Reset ; +input Clk ; + //RMII interface +input MCrs_dv ; +input [7:0] MRxD ; +input MRxErr ; + //CRC_chk interface +output CRC_en ; +output CRC_init; +input CRC_err ; + //MAC_rx_add_chk interface +output MAC_add_en ; +input MAC_rx_add_chk_err ; + //broadcast_filter +output broadcast_ptr ; +input broadcast_drop ; + //flow_control signals +output [15:0] pause_quanta ; +output pause_quanta_val ; + //MAC_rx_FF interface +output [7:0] Fifo_data ; +output Fifo_data_en ; +output Fifo_data_err ; +output Fifo_data_end ; +input Fifo_full; + //RMON interface +output [15:0] Rx_pkt_length_rmon ; +output Rx_apply_rmon ; +output [2:0] Rx_pkt_err_type_rmon ; +output [2:0] Rx_pkt_type_rmon ; + //CPU +input [5:0] RX_IFG_SET ; +input [15:0] RX_MAX_LENGTH ;// 1518 +input [6:0] RX_MIN_LENGTH ;// 64 + +//****************************************************************************** +//internal signals +//****************************************************************************** +parameter State_idle =4'd00; +parameter State_preamble =4'd01; +parameter State_SFD =4'd02; +parameter State_data =4'd03; +parameter State_checkCRC =4'd04; +parameter State_OkEnd =4'd07; +parameter State_drop =4'd08; +parameter State_ErrEnd =4'd09; +parameter State_CRCErrEnd =4'd10; +parameter State_FFFullDrop =4'd11; +parameter State_FFFullErrEnd =4'd12; +parameter State_IFG =4'd13; + +parameter Pause_idle =4'd0; +parameter Pause_pre_syn =4'd1; +parameter Pause_quanta_hi =4'd2; +parameter Pause_quanta_lo =4'd3; +parameter Pause_syn =4'd4; + +reg [3:0] Current_state /* synthesis syn_keep=1 */; +reg [3:0] Next_state; +reg [3:0] Pause_current /* synthesis syn_keep=1 */; +reg [3:0] Pause_next; +reg [5:0] IFG_counter; +reg Crs_dv ; +reg [7:0] RxD ; +reg [7:0] RxD_dl1 ; +reg RxErr ; +reg [15:0] Frame_length_counter; +reg Too_long; +reg Too_short; +reg Fifo_data_en; +reg Fifo_data_end; +reg Fifo_data_err; +reg CRC_en; +reg CRC_init; +reg Rx_apply_rmon; +reg Rx_apply_rmon_tmp; +reg Rx_apply_rmon_tmp_pl1; +reg [2:0] Rx_pkt_err_type_rmon; +reg MAC_add_en; +reg [2:0] Rx_pkt_type_rmon; +reg [7:0] pause_quanta_h ; +reg [15:0] pause_quanta ; +reg pause_quanta_val ; +reg pause_quanta_val_tmp; +reg pause_frame_ptr ; +reg broadcast_ptr ; +//****************************************************************************** +//delay signals +//****************************************************************************** + +always @ (posedge Reset or posedge Clk) + if (Reset) + begin + Crs_dv <=0; + RxD <=0; + RxErr <=0; + end + else + begin + Crs_dv <=MCrs_dv ; + RxD <=MRxD ; + RxErr <=MRxErr ; + end + +always @ (posedge Reset or posedge Clk) + if (Reset) + RxD_dl1 <=0; + else + RxD_dl1 <=RxD; + +//****************************************************************************** +//State_machine +//****************************************************************************** + +always @ (posedge Reset or posedge Clk) + if (Reset) + Current_state <=State_idle; + else + Current_state <=Next_state; + +always @ (*) + case (Current_state) + State_idle: + if (Crs_dv&&RxD==8'h55) + Next_state =State_preamble; + else + Next_state =Current_state; + State_preamble: + if (!Crs_dv) + Next_state =State_ErrEnd; + else if (RxErr) + Next_state =State_drop; + else if (RxD==8'hd5) + Next_state =State_SFD; + else if (RxD==8'h55) + Next_state =Current_state; + else + Next_state =State_drop; + State_SFD: + if (!Crs_dv) + Next_state =State_ErrEnd; + else if (RxErr) + Next_state =State_drop; + else + Next_state =State_data; + State_data: + if (!Crs_dv&&!Too_short&&!Too_long) + Next_state =State_checkCRC; + else if (!Crs_dv&&(Too_short||Too_long)) + Next_state =State_ErrEnd; + else if (Fifo_full) + Next_state =State_FFFullErrEnd; + else if (RxErr||MAC_rx_add_chk_err||Too_long||broadcast_drop) + Next_state =State_drop; + else + Next_state =State_data; + State_checkCRC: + if (CRC_err) + Next_state =State_CRCErrEnd; + else + Next_state =State_OkEnd; + State_drop: + if (!Crs_dv) + Next_state =State_ErrEnd; + else + Next_state =Current_state; + State_OkEnd: + Next_state =State_IFG; + State_ErrEnd: + Next_state =State_IFG; + + State_CRCErrEnd: + Next_state =State_IFG; + State_FFFullDrop: + if (!Crs_dv) + Next_state =State_IFG; + else + Next_state =Current_state; + State_FFFullErrEnd: + Next_state =State_FFFullDrop; + State_IFG: + if (IFG_counter==RX_IFG_SET-4) //remove some additional time + Next_state =State_idle; + else + Next_state =Current_state; + + default: + Next_state =State_idle; + endcase + + +always @ (posedge Reset or posedge Clk) + if (Reset) + IFG_counter <=0; + else if (Current_state!=State_IFG) + IFG_counter <=0; + else + IFG_counter <=IFG_counter + 1; +//****************************************************************************** +//gen fifo interface signals +//****************************************************************************** + +assign Fifo_data =RxD_dl1; + +always @(Current_state) + if (Current_state==State_data) + Fifo_data_en =1; + else + Fifo_data_en =0; + +always @(Current_state) + if (Current_state==State_ErrEnd||Current_state==State_OkEnd + ||Current_state==State_CRCErrEnd||Current_state==State_FFFullErrEnd) + Fifo_data_end =1; + else + Fifo_data_end =0; + +always @(Current_state) + if (Current_state==State_ErrEnd||Current_state==State_CRCErrEnd||Current_state==State_FFFullErrEnd) + Fifo_data_err =1; + else + Fifo_data_err =0; + +//****************************************************************************** +//CRC_chk interface +//****************************************************************************** + +always @(Current_state) + if (Current_state==State_data) + CRC_en =1; + else + CRC_en =0; + +always @(Current_state) + if (Current_state==State_SFD) + CRC_init =1; + else + CRC_init =0; + +//****************************************************************************** +//gen rmon signals +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + Frame_length_counter <=0; + else if (Current_state==State_SFD) + Frame_length_counter <=1; + else if (Current_state==State_data) + Frame_length_counter <=Frame_length_counter+ 1'b1; + +always @ (Frame_length_counter or RX_MIN_LENGTH) + if (Frame_length_counter<RX_MIN_LENGTH) + Too_short =1; + else + Too_short =0; + +always @ (*) + if (Frame_length_counter>RX_MAX_LENGTH) + Too_long =1; + else + Too_long =0; + +assign Rx_pkt_length_rmon=Frame_length_counter-1'b1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Rx_apply_rmon_tmp <=0; + else if (Current_state==State_OkEnd||Current_state==State_ErrEnd + ||Current_state==State_CRCErrEnd||Current_state==State_FFFullErrEnd) + Rx_apply_rmon_tmp <=1; + else + Rx_apply_rmon_tmp <=0; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Rx_apply_rmon_tmp_pl1 <=0; + else + Rx_apply_rmon_tmp_pl1 <=Rx_apply_rmon_tmp; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Rx_apply_rmon <=0; + else if (Current_state==State_OkEnd||Current_state==State_ErrEnd + ||Current_state==State_CRCErrEnd||Current_state==State_FFFullErrEnd) + Rx_apply_rmon <=1; + else if (Rx_apply_rmon_tmp_pl1) + Rx_apply_rmon <=0; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Rx_pkt_err_type_rmon <=0; + else if (Current_state==State_CRCErrEnd) + Rx_pkt_err_type_rmon <=3'b001 ;// + else if (Current_state==State_FFFullErrEnd) + Rx_pkt_err_type_rmon <=3'b010 ;// + else if (Current_state==State_ErrEnd) + Rx_pkt_err_type_rmon <=3'b011 ;// + else if(Current_state==State_OkEnd) + Rx_pkt_err_type_rmon <=3'b100 ; + + + +always @ (posedge Clk or posedge Reset) + if (Reset) + Rx_pkt_type_rmon <=0; + else if (Current_state==State_OkEnd&&pause_frame_ptr) + Rx_pkt_type_rmon <=3'b100 ;// + else if(Current_state==State_SFD&&Next_state==State_data) + Rx_pkt_type_rmon <={1'b0,MRxD[7:6]}; + +always @ (posedge Clk or posedge Reset) + if (Reset) + broadcast_ptr <=0; + else if(Current_state==State_IFG) + broadcast_ptr <=0; + else if(Current_state==State_SFD&&Next_state==State_data&&MRxD[7:6]==2'b11) + broadcast_ptr <=1; + + + +//****************************************************************************** +//MAC add checker signals +//****************************************************************************** +always @ (Frame_length_counter or Fifo_data_en) + if(Frame_length_counter>=1&&Frame_length_counter<=6) + MAC_add_en <=Fifo_data_en; + else + MAC_add_en <=0; + +//****************************************************************************** +//flow control signals +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + Pause_current <=Pause_idle; + else + Pause_current <=Pause_next; + +always @ (*) + case (Pause_current) + Pause_idle : + if(Current_state==State_SFD) + Pause_next =Pause_pre_syn; + else + Pause_next =Pause_current; + Pause_pre_syn: + case (Frame_length_counter) + 16'd1: if (RxD_dl1==8'h01) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd2: if (RxD_dl1==8'h80) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd3: if (RxD_dl1==8'hc2) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd4: if (RxD_dl1==8'h00) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd5: if (RxD_dl1==8'h00) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd6: if (RxD_dl1==8'h01) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd13: if (RxD_dl1==8'h88) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd14: if (RxD_dl1==8'h08) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd15: if (RxD_dl1==8'h00) + Pause_next =Pause_current; + else + Pause_next =Pause_idle; + 16'd16: if (RxD_dl1==8'h01) + Pause_next =Pause_quanta_hi; + else + Pause_next =Pause_idle; + default: Pause_next =Pause_current; + endcase + Pause_quanta_hi : + Pause_next =Pause_quanta_lo; + Pause_quanta_lo : + Pause_next =Pause_syn; + Pause_syn : + if (Current_state==State_IFG) + Pause_next =Pause_idle; + else + Pause_next =Pause_current; + default + Pause_next =Pause_idle; + endcase + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta_h <=0; + else if(Pause_current==Pause_quanta_hi) + pause_quanta_h <=RxD_dl1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta <=0; + else if(Pause_current==Pause_quanta_lo) + pause_quanta <={pause_quanta_h,RxD_dl1}; + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta_val_tmp <=0; + else if(Current_state==State_OkEnd&&Pause_current==Pause_syn) + pause_quanta_val_tmp <=1; + else + pause_quanta_val_tmp <=0; + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta_val <=0; + else if(Current_state==State_OkEnd&&Pause_current==Pause_syn||pause_quanta_val_tmp) + pause_quanta_val <=1; + else + pause_quanta_val <=0; + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_frame_ptr <=0; + else if(Pause_current==Pause_syn) + pause_frame_ptr <=1; + else + pause_frame_ptr <=0; + +endmodule + +
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_top.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_top.v new file mode 100644 index 000000000..c1b211540 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_top.v @@ -0,0 +1,430 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_top.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_top.v,v $ +// Revision 1.3 2006/01/19 14:07:52 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:13 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module MAC_top( + //system signals +input Reset , +input Clk_125M , +input Clk_user , +input Clk_reg , +output [2:0] Speed , + //user interface +output Rx_mac_ra , +input Rx_mac_rd , +output [31:0] Rx_mac_data , +output [1:0] Rx_mac_BE , +output Rx_mac_pa , +output Rx_mac_sop , +output Rx_mac_eop , + //user interface +output Tx_mac_wa , +input Tx_mac_wr , +input [31:0] Tx_mac_data , +input [1:0] Tx_mac_BE ,//big endian +input Tx_mac_sop , +input Tx_mac_eop , + //Phy interface + //Phy interface +output Gtx_clk ,//used only in GMII mode +input Rx_clk , +input Tx_clk ,//used only in MII mode +output Tx_er , +output Tx_en , +output [7:0] Txd , +input Rx_er , +input Rx_dv , +input [7:0] Rxd , +input Crs , +input Col , + //host interface +input CSB , +input WRB , +input [15:0] CD_in , +output [15:0] CD_out , +input [7:0] CA , + //mdx +inout Mdio ,// MII Management Data In +output Mdc // MII Management Data Clock + +); +//****************************************************************************** +//internal signals +//****************************************************************************** + //RMON interface +wire [15:0] Rx_pkt_length_rmon ; +wire Rx_apply_rmon ; +wire [2:0] Rx_pkt_err_type_rmon ; +wire [2:0] Rx_pkt_type_rmon ; +wire [2:0] Tx_pkt_type_rmon ; +wire [15:0] Tx_pkt_length_rmon ; +wire Tx_apply_rmon ; +wire [2:0] Tx_pkt_err_type_rmon ; + //PHY interface +wire MCrs_dv ; +wire [7:0] MRxD ; +wire MRxErr ; + //flow_control signals +wire [15:0] pause_quanta ; +wire pause_quanta_val ; + //PHY interface +wire [7:0] MTxD ; +wire MTxEn ; +wire MCRS ; + //interface clk signals +wire MAC_tx_clk ; +wire MAC_rx_clk ; +wire MAC_tx_clk_div ; +wire MAC_rx_clk_div ; + //reg signals +wire [4:0] Tx_Hwmark ; +wire [4:0] Tx_Lwmark ; +wire pause_frame_send_en ; +wire [15:0] pause_quanta_set ; +wire MAC_tx_add_en ; +wire FullDuplex ; +wire [3:0] MaxRetry ; +wire [5:0] IFGset ; +wire [7:0] MAC_tx_add_prom_data ; +wire [2:0] MAC_tx_add_prom_add ; +wire MAC_tx_add_prom_wr ; +wire tx_pause_en ; +wire xoff_cpu ; +wire xon_cpu ; + //Rx host interface +wire MAC_rx_add_chk_en ; +wire [7:0] MAC_rx_add_prom_data ; +wire [2:0] MAC_rx_add_prom_add ; +wire MAC_rx_add_prom_wr ; +wire broadcast_filter_en ; +wire [15:0] broadcast_MAX ; +wire RX_APPEND_CRC ; +wire [4:0] Rx_Hwmark ; +wire [4:0] Rx_Lwmark ; +wire CRC_chk_en ; +wire [5:0] RX_IFG_SET ; +wire [15:0] RX_MAX_LENGTH ; +wire [6:0] RX_MIN_LENGTH ; + //RMON host interface +wire [5:0] CPU_rd_addr ; +wire CPU_rd_apply ; +wire CPU_rd_grant ; +wire [31:0] CPU_rd_dout ; + //Phy int host interface +wire Line_loop_en ; + //MII to CPU +wire [7:0] Divider ; +wire [15:0] CtrlData ; +wire [4:0] Rgad ; +wire [4:0] Fiad ; +wire NoPre ; +wire WCtrlData ; +wire RStat ; +wire ScanStat ; +wire Busy ; +wire LinkFail ; +wire Nvalid ; +wire [15:0] Prsd ; +wire WCtrlDataStart ; +wire RStatStart ; +wire UpdateMIIRX_DATAReg ; +wire [15:0] broadcast_bucket_depth ; +wire [15:0] broadcast_bucket_interval ; + +//****************************************************************************** +//internal signals +//****************************************************************************** +MAC_rx U_MAC_rx( +.Reset (Reset ), +.Clk_user (Clk_user ), +.Clk (MAC_rx_clk_div ), + //RMII interface (//PHY interface ), +.MCrs_dv (MCrs_dv ), +.MRxD (MRxD ), +.MRxErr (MRxErr ), + //flow_control signals (//flow_control signals ), +.pause_quanta (pause_quanta ), +.pause_quanta_val (pause_quanta_val ), + //user interface (//user interface ), +.Rx_mac_ra (Rx_mac_ra ), +.Rx_mac_rd (Rx_mac_rd ), +.Rx_mac_data (Rx_mac_data ), +.Rx_mac_BE (Rx_mac_BE ), +.Rx_mac_pa (Rx_mac_pa ), +.Rx_mac_sop (Rx_mac_sop ), +.Rx_mac_eop (Rx_mac_eop ), + //CPU (//CPU ), +.MAC_rx_add_chk_en (MAC_rx_add_chk_en ), +.MAC_add_prom_data (MAC_rx_add_prom_data ), +.MAC_add_prom_add (MAC_rx_add_prom_add ), +.MAC_add_prom_wr (MAC_rx_add_prom_wr ), +.broadcast_filter_en (broadcast_filter_en ), +.broadcast_bucket_depth (broadcast_bucket_depth ), +.broadcast_bucket_interval (broadcast_bucket_interval ), +.RX_APPEND_CRC (RX_APPEND_CRC ), +.Rx_Hwmark (Rx_Hwmark ), +.Rx_Lwmark (Rx_Lwmark ), +.CRC_chk_en (CRC_chk_en ), +.RX_IFG_SET (RX_IFG_SET ), +.RX_MAX_LENGTH (RX_MAX_LENGTH ), +.RX_MIN_LENGTH (RX_MIN_LENGTH ), + //RMON interface (//RMON interface ), +.Rx_pkt_length_rmon (Rx_pkt_length_rmon ), +.Rx_apply_rmon (Rx_apply_rmon ), +.Rx_pkt_err_type_rmon (Rx_pkt_err_type_rmon ), +.Rx_pkt_type_rmon (Rx_pkt_type_rmon ) +); + +MAC_tx U_MAC_tx( +.Reset (Reset ), +.Clk (MAC_tx_clk_div ), +.Clk_user (Clk_user ), + //PHY interface (//PHY interface ), +.TxD (MTxD ), +.TxEn (MTxEn ), +.CRS (MCRS ), + //RMON (//RMON ), +.Tx_pkt_type_rmon (Tx_pkt_type_rmon ), +.Tx_pkt_length_rmon (Tx_pkt_length_rmon ), +.Tx_apply_rmon (Tx_apply_rmon ), +.Tx_pkt_err_type_rmon (Tx_pkt_err_type_rmon ), + //user interface (//user interface ), +.Tx_mac_wa (Tx_mac_wa ), +.Tx_mac_wr (Tx_mac_wr ), +.Tx_mac_data (Tx_mac_data ), +.Tx_mac_BE (Tx_mac_BE ), +.Tx_mac_sop (Tx_mac_sop ), +.Tx_mac_eop (Tx_mac_eop ), + //host interface (//host interface ), +.Tx_Hwmark (Tx_Hwmark ), +.Tx_Lwmark (Tx_Lwmark ), +.pause_frame_send_en (pause_frame_send_en ), +.pause_quanta_set (pause_quanta_set ), +.MAC_tx_add_en (MAC_tx_add_en ), +.FullDuplex (FullDuplex ), +.MaxRetry (MaxRetry ), +.IFGset (IFGset ), +.MAC_add_prom_data (MAC_tx_add_prom_data ), +.MAC_add_prom_add (MAC_tx_add_prom_add ), +.MAC_add_prom_wr (MAC_tx_add_prom_wr ), +.tx_pause_en (tx_pause_en ), +.xoff_cpu (xoff_cpu ), +.xon_cpu (xon_cpu ), + //MAC_rx_flow (//MAC_rx_flow ), +.pause_quanta (pause_quanta ), +.pause_quanta_val (pause_quanta_val ) +); + +RMON U_RMON( +.Clk (Clk_reg ), +.Reset (Reset ), + //Tx_RMON (//Tx_RMON ), +.Tx_pkt_type_rmon (Tx_pkt_type_rmon ), +.Tx_pkt_length_rmon (Tx_pkt_length_rmon ), +.Tx_apply_rmon (Tx_apply_rmon ), +.Tx_pkt_err_type_rmon (Tx_pkt_err_type_rmon ), + //Tx_RMON (//Tx_RMON ), +.Rx_pkt_type_rmon (Rx_pkt_type_rmon ), +.Rx_pkt_length_rmon (Rx_pkt_length_rmon ), +.Rx_apply_rmon (Rx_apply_rmon ), +.Rx_pkt_err_type_rmon (Rx_pkt_err_type_rmon ), + //CPU (//CPU ), +.CPU_rd_addr (CPU_rd_addr ), +.CPU_rd_apply (CPU_rd_apply ), +.CPU_rd_grant (CPU_rd_grant ), +.CPU_rd_dout (CPU_rd_dout ) +); + +Phy_int U_Phy_int( +.Reset (Reset ), +.MAC_rx_clk (MAC_rx_clk ), +.MAC_tx_clk (MAC_tx_clk ), + //Rx interface (//Rx interface ), +.MCrs_dv (MCrs_dv ), +.MRxD (MRxD ), +.MRxErr (MRxErr ), + //Tx interface (//Tx interface ), +.MTxD (MTxD ), +.MTxEn (MTxEn ), +.MCRS (MCRS ), + //Phy interface (//Phy interface ), +.Tx_er (Tx_er ), +.Tx_en (Tx_en ), +.Txd (Txd ), +.Rx_er (Rx_er ), +.Rx_dv (Rx_dv ), +.Rxd (Rxd ), +.Crs (Crs ), +.Col (Col ), + //host interface (//host interface ), +.Line_loop_en (Line_loop_en ), +.Speed (Speed ) +); + +Clk_ctrl U_Clk_ctrl( +.Reset (Reset ), +.Clk_125M (Clk_125M ), + //host interface (//host interface ), +.Speed (Speed ), + //Phy interface (//Phy interface ), +.Gtx_clk (Gtx_clk ), +.Rx_clk (Rx_clk ), +.Tx_clk (Tx_clk ), + //interface clk (//interface clk ), +.MAC_tx_clk (MAC_tx_clk ), +.MAC_rx_clk (MAC_rx_clk ), +.MAC_tx_clk_div (MAC_tx_clk_div ), +.MAC_rx_clk_div (MAC_rx_clk_div ) +); + +eth_miim U_eth_miim( +.Clk (Clk_reg ), +.Reset (Reset ), +.Divider (Divider ), +.NoPre (NoPre ), +.CtrlData (CtrlData ), +.Rgad (Rgad ), +.Fiad (Fiad ), +.WCtrlData (WCtrlData ), +.RStat (RStat ), +.ScanStat (ScanStat ), +.Mdio (Mdio ), +.Mdc (Mdc ), +.Busy (Busy ), +.Prsd (Prsd ), +.LinkFail (LinkFail ), +.Nvalid (Nvalid ), +.WCtrlDataStart (WCtrlDataStart ), +.RStatStart (RStatStart ), +.UpdateMIIRX_DATAReg (UpdateMIIRX_DATAReg )); + +reg_int U_reg_int( +.Reset (Reset ), +.Clk_reg (Clk_reg ), +.CSB (CSB ), +.WRB (WRB ), +.CD_in (CD_in ), +.CD_out (CD_out ), +.CA (CA ), + //Tx host interface (//Tx host interface ), +.Tx_Hwmark (Tx_Hwmark ), +.Tx_Lwmark (Tx_Lwmark ), +.pause_frame_send_en (pause_frame_send_en ), +.pause_quanta_set (pause_quanta_set ), +.MAC_tx_add_en (MAC_tx_add_en ), +.FullDuplex (FullDuplex ), +.MaxRetry (MaxRetry ), +.IFGset (IFGset ), +.MAC_tx_add_prom_data (MAC_tx_add_prom_data ), +.MAC_tx_add_prom_add (MAC_tx_add_prom_add ), +.MAC_tx_add_prom_wr (MAC_tx_add_prom_wr ), +.tx_pause_en (tx_pause_en ), +.xoff_cpu (xoff_cpu ), +.xon_cpu (xon_cpu ), + //Rx host interface (//Rx host interface ), +.MAC_rx_add_chk_en (MAC_rx_add_chk_en ), +.MAC_rx_add_prom_data (MAC_rx_add_prom_data ), +.MAC_rx_add_prom_add (MAC_rx_add_prom_add ), +.MAC_rx_add_prom_wr (MAC_rx_add_prom_wr ), +.broadcast_filter_en (broadcast_filter_en ), +.broadcast_bucket_depth (broadcast_bucket_depth ), +.broadcast_bucket_interval (broadcast_bucket_interval ), +.RX_APPEND_CRC (RX_APPEND_CRC ), +.Rx_Hwmark (Rx_Hwmark ), +.Rx_Lwmark (Rx_Lwmark ), +.CRC_chk_en (CRC_chk_en ), +.RX_IFG_SET (RX_IFG_SET ), +.RX_MAX_LENGTH (RX_MAX_LENGTH ), +.RX_MIN_LENGTH (RX_MIN_LENGTH ), + //RMON host interface (//RMON host interface ), +.CPU_rd_addr (CPU_rd_addr ), +.CPU_rd_apply (CPU_rd_apply ), +.CPU_rd_grant (CPU_rd_grant ), +.CPU_rd_dout (CPU_rd_dout ), + //Phy int host interface (//Phy int host interface ), +.Line_loop_en (Line_loop_en ), +.Speed (Speed ), + //MII to CPU (//MII to CPU ), +.Divider (Divider ), +.CtrlData (CtrlData ), +.Rgad (Rgad ), +.Fiad (Fiad ), +.NoPre (NoPre ), +.WCtrlData (WCtrlData ), +.RStat (RStat ), +.ScanStat (ScanStat ), +.Busy (Busy ), +.LinkFail (LinkFail ), +.Nvalid (Nvalid ), +.Prsd (Prsd ), +.WCtrlDataStart (WCtrlDataStart ), +.RStatStart (RStatStart ), +.UpdateMIIRX_DATAReg (UpdateMIIRX_DATAReg ) +); + +endmodule + + + + + + + + + + + + + + + + + diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx.v new file mode 100644 index 000000000..f5e605bc0 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx.v @@ -0,0 +1,266 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_tx.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_tx.v,v $ +// Revision 1.4 2006/11/17 17:53:07 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:53 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:14 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// +module MAC_tx( +input Reset , +input Clk , +input Clk_user , + //PHY interface +output [7:0] TxD , +output TxEn , +input CRS , + //RMON +output [2:0] Tx_pkt_type_rmon , +output [15:0] Tx_pkt_length_rmon , +output Tx_apply_rmon , +output [2:0] Tx_pkt_err_type_rmon, + //user interface +output Tx_mac_wa , +input Tx_mac_wr , +input [31:0] Tx_mac_data , +input [1:0] Tx_mac_BE ,//big endian +input Tx_mac_sop , +input Tx_mac_eop , + //host interface +input [4:0] Tx_Hwmark , +input [4:0] Tx_Lwmark , +input pause_frame_send_en , +input [15:0] pause_quanta_set , +input MAC_tx_add_en , +input FullDuplex , +input [3:0] MaxRetry , +input [5:0] IFGset , +input [7:0] MAC_add_prom_data , +input [2:0] MAC_add_prom_add , +input MAC_add_prom_wr , +input tx_pause_en , +input xoff_cpu , +input xon_cpu , + //MAC_rx_flow , +input [15:0] pause_quanta , +input pause_quanta_val +); +//****************************************************************************** +//internal signals +//****************************************************************************** + //CRC_gen Interface +wire CRC_init ; +wire[7:0] Frame_data ; +wire Data_en ; +wire CRC_rd ; +wire CRC_end ; +wire[7:0] CRC_out ; + //Ramdon_gen interface +wire Random_init ; +wire[3:0] RetryCnt ; +wire Random_time_meet ;//levle hight indicate random time passed away + //flow control +wire pause_apply ; +wire pause_quanta_sub ; +wire xoff_gen ; +wire xoff_gen_complete ; +wire xon_gen ; +wire xon_gen_complete ; + //MAC_rx_FF +wire[7:0] Fifo_data ; +wire Fifo_rd ; +wire Fifo_eop ; +wire Fifo_da ; +wire Fifo_rd_finish ; +wire Fifo_rd_retry ; +wire Fifo_ra ; +wire Fifo_data_err_empty ; +wire Fifo_data_err_full ; + //MAC_tx_addr_add +wire MAC_tx_addr_init ; +wire MAC_tx_addr_rd ; +wire[7:0] MAC_tx_addr_data ; + +//****************************************************************************** +//instantiation +//****************************************************************************** +MAC_tx_ctrl U_MAC_tx_ctrl( +.Reset (Reset ), +.Clk (Clk ), + //CRC_gen Interface (//CRC_gen Interface ), +.CRC_init (CRC_init ), +.Frame_data (Frame_data ), +.Data_en (Data_en ), +.CRC_rd (CRC_rd ), +.CRC_end (CRC_end ), +.CRC_out (CRC_out ), + //Random_gen interfac (//Random_gen interfac ), +.Random_init (Random_init ), +.RetryCnt (RetryCnt ), +.Random_time_meet (Random_time_meet ), + //flow control (//flow control ), +.pause_apply (pause_apply ), +.pause_quanta_sub (pause_quanta_sub ), +.xoff_gen (xoff_gen ), +.xoff_gen_complete (xoff_gen_complete ), +.xon_gen (xon_gen ), +.xon_gen_complete (xon_gen_complete ), + //MAC_tx_FF (//MAC_tx_FF ), +.Fifo_data (Fifo_data ), +.Fifo_rd (Fifo_rd ), +.Fifo_eop (Fifo_eop ), +.Fifo_da (Fifo_da ), +.Fifo_rd_finish (Fifo_rd_finish ), +.Fifo_rd_retry (Fifo_rd_retry ), +.Fifo_ra (Fifo_ra ), +.Fifo_data_err_empty (Fifo_data_err_empty ), +.Fifo_data_err_full (Fifo_data_err_full ), + //RMII (//RMII ), +.TxD (TxD ), +.TxEn (TxEn ), +.CRS (CRS ), + //MAC_tx_addr_add (//MAC_tx_addr_add ), +.MAC_tx_addr_rd (MAC_tx_addr_rd ), +.MAC_tx_addr_data (MAC_tx_addr_data ), +.MAC_tx_addr_init (MAC_tx_addr_init ), + //RMON (//RMON ), +.Tx_pkt_type_rmon (Tx_pkt_type_rmon ), +.Tx_pkt_length_rmon (Tx_pkt_length_rmon ), +.Tx_apply_rmon (Tx_apply_rmon ), +.Tx_pkt_err_type_rmon (Tx_pkt_err_type_rmon ), + //CPU (//CPU ), +.pause_frame_send_en (pause_frame_send_en ), +.pause_quanta_set (pause_quanta_set ), +.MAC_tx_add_en (MAC_tx_add_en ), +.FullDuplex (FullDuplex ), +.MaxRetry (MaxRetry ), +.IFGset (IFGset ) +); + +CRC_gen U_CRC_gen( +.Reset (Reset ), +.Clk (Clk ), +.Init (CRC_init ), +.Frame_data (Frame_data ), +.Data_en (Data_en ), +.CRC_rd (CRC_rd ), +.CRC_out (CRC_out ), +.CRC_end (CRC_end ) +); + +flow_ctrl U_flow_ctrl( +.Reset (Reset ), +.Clk (Clk ), + //host processor (//host processor ), +.tx_pause_en (tx_pause_en ), +.xoff_cpu (xoff_cpu ), +.xon_cpu (xon_cpu ), + //MAC_rx_flow (//MAC_rx_flow ), +.pause_quanta (pause_quanta ), +.pause_quanta_val (pause_quanta_val ), + //MAC_tx_ctrl (//MAC_tx_ctrl ), +.pause_apply (pause_apply ), +.pause_quanta_sub (pause_quanta_sub ), +.xoff_gen (xoff_gen ), +.xoff_gen_complete (xoff_gen_complete ), +.xon_gen (xon_gen ), +.xon_gen_complete (xon_gen_complete ) +); + +`ifdef MAC_SOURCE_REPLACE_EN +MAC_tx_addr_add U_MAC_tx_addr_add( +.Reset (Reset ), +.Clk (Clk ), +.MAC_tx_addr_rd (MAC_tx_addr_rd ), +.MAC_tx_addr_init (MAC_tx_addr_init ), +.MAC_tx_addr_data (MAC_tx_addr_data ), + //CPU (//CPU ), +.MAC_add_prom_data (MAC_add_prom_data ), +.MAC_add_prom_add (MAC_add_prom_add ), +.MAC_add_prom_wr (MAC_add_prom_wr ) +); +`else +assign MAC_tx_addr_data=0; +`endif +MAC_tx_FF #(.MAC_TX_FF_DEPTH(9)) + U_MAC_tx_FF(.Reset (Reset ), + .Clk_MAC (Clk ), + .Clk_SYS (Clk_user ), + //MAC_rx_ctrl interf (//MAC_rx_ctrl interf ), + .Fifo_data (Fifo_data ), + .Fifo_rd (Fifo_rd ), + .Fifo_rd_finish (Fifo_rd_finish ), + .Fifo_rd_retry (Fifo_rd_retry ), + .Fifo_eop (Fifo_eop ), + .Fifo_da (Fifo_da ), + .Fifo_ra (Fifo_ra ), + .Fifo_data_err_empty (Fifo_data_err_empty ), + .Fifo_data_err_full (Fifo_data_err_full ), + //user interface (//user interface ), + .Tx_mac_wa (Tx_mac_wa ), + .Tx_mac_wr (Tx_mac_wr ), + .Tx_mac_data (Tx_mac_data ), + .Tx_mac_BE (Tx_mac_BE ), + .Tx_mac_sop (Tx_mac_sop ), + .Tx_mac_eop (Tx_mac_eop ), + //host interface (//host interface ), + .FullDuplex (FullDuplex ), + .Tx_Hwmark (Tx_Hwmark ), + .Tx_Lwmark (Tx_Lwmark ) + ); + +random_gen U_random_gen( +.Reset (Reset ), +.Clk (Clk ), +.Init (Random_init ), +.RetryCnt (RetryCnt ), +.Random_time_meet (Random_time_meet ) +); + +endmodule diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CRC_gen.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CRC_gen.v new file mode 100644 index 000000000..c3b6b0800 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CRC_gen.v @@ -0,0 +1,168 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// CRC_gen.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CRC_gen.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:17 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module CRC_gen ( +Reset , +Clk , +Init , +Frame_data , +Data_en , +CRC_rd , +CRC_end , +CRC_out + +); +input Reset ; +input Clk ; +input Init ; +input [7:0] Frame_data ; +input Data_en ; +input CRC_rd ; +output [7:0] CRC_out ; +output CRC_end ; + +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [7:0] CRC_out ; +reg [31:0] CRC_reg; +reg CRC_end; +reg [3:0] Counter; +//****************************************************************************** +//****************************************************************************** +//input data width is 8bit, and the first bit is bit[0] +function[31:0] NextCRC; + input[7:0] D; + input[31:0] C; + reg[31:0] NewCRC; + begin + NewCRC[0]=C[24]^C[30]^D[1]^D[7]; + NewCRC[1]=C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[2]=C[26]^D[5]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[3]=C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[4]=C[28]^D[3]^C[27]^D[4]^C[26]^D[5]^C[24]^C[30]^D[1]^D[7]; + NewCRC[5]=C[29]^D[2]^C[28]^D[3]^C[27]^D[4]^C[25]^C[31]^D[0]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[6]=C[30]^D[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[7]=C[31]^D[0]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7]; + NewCRC[8]=C[0]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7]; + NewCRC[9]=C[1]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6]; + NewCRC[10]=C[2]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[24]^D[7]; + NewCRC[11]=C[3]^C[28]^D[3]^C[27]^D[4]^C[25]^D[6]^C[24]^D[7]; + NewCRC[12]=C[4]^C[29]^D[2]^C[28]^D[3]^C[26]^D[5]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[13]=C[5]^C[30]^D[1]^C[29]^D[2]^C[27]^D[4]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[14]=C[6]^C[31]^D[0]^C[30]^D[1]^C[28]^D[3]^C[27]^D[4]^C[26]^D[5]; + NewCRC[15]=C[7]^C[31]^D[0]^C[29]^D[2]^C[28]^D[3]^C[27]^D[4]; + NewCRC[16]=C[8]^C[29]^D[2]^C[28]^D[3]^C[24]^D[7]; + NewCRC[17]=C[9]^C[30]^D[1]^C[29]^D[2]^C[25]^D[6]; + NewCRC[18]=C[10]^C[31]^D[0]^C[30]^D[1]^C[26]^D[5]; + NewCRC[19]=C[11]^C[31]^D[0]^C[27]^D[4]; + NewCRC[20]=C[12]^C[28]^D[3]; + NewCRC[21]=C[13]^C[29]^D[2]; + NewCRC[22]=C[14]^C[24]^D[7]; + NewCRC[23]=C[15]^C[25]^D[6]^C[24]^C[30]^D[1]^D[7]; + NewCRC[24]=C[16]^C[26]^D[5]^C[25]^C[31]^D[0]^D[6]; + NewCRC[25]=C[17]^C[27]^D[4]^C[26]^D[5]; + NewCRC[26]=C[18]^C[28]^D[3]^C[27]^D[4]^C[24]^C[30]^D[1]^D[7]; + NewCRC[27]=C[19]^C[29]^D[2]^C[28]^D[3]^C[25]^C[31]^D[0]^D[6]; + NewCRC[28]=C[20]^C[30]^D[1]^C[29]^D[2]^C[26]^D[5]; + NewCRC[29]=C[21]^C[31]^D[0]^C[30]^D[1]^C[27]^D[4]; + NewCRC[30]=C[22]^C[31]^D[0]^C[28]^D[3]; + NewCRC[31]=C[23]^C[29]^D[2]; + NextCRC=NewCRC; + end + endfunction +//****************************************************************************** + +always @ (posedge Clk or posedge Reset) + if (Reset) + CRC_reg <=32'hffffffff; + else if (Init) + CRC_reg <=32'hffffffff; + else if (Data_en) + CRC_reg <=NextCRC(Frame_data,CRC_reg); + else if (CRC_rd) + CRC_reg <={CRC_reg[23:0],8'hff}; + +always @ (CRC_rd or CRC_reg) + if (CRC_rd) + CRC_out <=~{ + CRC_reg[24], + CRC_reg[25], + CRC_reg[26], + CRC_reg[27], + CRC_reg[28], + CRC_reg[29], + CRC_reg[30], + CRC_reg[31] + }; + else + CRC_out <=0; + +//caculate CRC out length ,4 cycles +//CRC_end aligned to last CRC checksum data +always @(posedge Clk or posedge Reset) + if (Reset) + Counter <=0; + else if (!CRC_rd) + Counter <=0; + else + Counter <=Counter + 1; + +always @ (Counter) + if (Counter==3) + CRC_end=1; + else + CRC_end=0; + +endmodule + + diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Entries b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Entries new file mode 100644 index 000000000..58f964cb8 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Entries @@ -0,0 +1,7 @@ +/CRC_gen.v/1.3/Thu Jan 19 14:07:54 2006// +/MAC_tx_addr_add.v/1.3/Thu Jan 19 14:07:54 2006// +/flow_ctrl.v/1.3/Thu Jan 19 14:07:54 2006// +/MAC_tx_FF.v/1.5/Tue May 1 07:35:17 2007// +/MAC_tx_Ctrl.v/1.4/Wed May 2 06:49:15 2007// +/Ramdon_gen.v/1.3/Wed May 2 06:49:15 2007// +D diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Repository b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Repository new file mode 100644 index 000000000..3f5abe3c5 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/rtl/verilog/MAC_tx diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Root b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Template b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/CVS/Template diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/MAC_tx_FF.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/MAC_tx_FF.v new file mode 100644 index 000000000..b13c06621 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/MAC_tx_FF.v @@ -0,0 +1,745 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_tx_FF.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_tx_FF.v,v $ +// Revision 1.5 2006/06/25 04:58:56 maverickist +// no message +// +// Revision 1.4 2006/05/28 05:09:20 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.3 2005/12/16 06:44:18 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.2 2005/12/13 12:15:39 Administrator +// no message +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module MAC_tx_FF + #(parameter MAC_TX_FF_DEPTH = 9) + (Reset , + Clk_MAC , + Clk_SYS , + //MAC_rx_ctrl interface + Fifo_data , + Fifo_rd , + Fifo_rd_finish , + Fifo_rd_retry , + Fifo_eop , + Fifo_da , + Fifo_ra , + Fifo_data_err_empty , + Fifo_data_err_full , + //user interface + Tx_mac_wa , + Tx_mac_wr , + Tx_mac_data , + Tx_mac_BE , + Tx_mac_sop , + Tx_mac_eop , + //host interface + FullDuplex , + Tx_Hwmark , + Tx_Lwmark); + + input Reset ; + input Clk_MAC ; + input Clk_SYS ; + //MAC_tx_ctrl + output [7:0] Fifo_data ; + input Fifo_rd ; + input Fifo_rd_finish ; + input Fifo_rd_retry ; + output Fifo_eop ; + output Fifo_da ; + output Fifo_ra ; + output Fifo_data_err_empty ; + output Fifo_data_err_full ; + //user interface + output Tx_mac_wa ; + input Tx_mac_wr ; + input [31:0] Tx_mac_data ; + input [1:0] Tx_mac_BE ;//big endian + input Tx_mac_sop ; + input Tx_mac_eop ; + //host interface + input FullDuplex ; + input [4:0] Tx_Hwmark ; + input [4:0] Tx_Lwmark ; + // ****************************************************************************** + //internal signals + // ****************************************************************************** + parameter MAC_byte3 =4'd00; + parameter MAC_byte2 =4'd01; + parameter MAC_byte1 =4'd02; + parameter MAC_byte0 =4'd03; + parameter MAC_wait_finish =4'd04; + parameter MAC_retry =4'd08; + parameter MAC_idle =4'd09; + parameter MAC_FFEmpty =4'd10; + parameter MAC_FFEmpty_drop =4'd11; + parameter MAC_pkt_sub =4'd12; + parameter MAC_FF_Err =4'd13; + + reg [3:0] Current_state_MAC /* synthesis syn_preserve =1 */ ; + reg [3:0] Current_state_MAC_reg /* synthesis syn_preserve =1 */ ; + reg [3:0] Next_state_MAC ; + + parameter SYS_idle =4'd0; + parameter SYS_WaitSop =4'd1; + parameter SYS_SOP =4'd2; + parameter SYS_MOP =4'd3; + parameter SYS_DROP =4'd4; + parameter SYS_EOP_ok =4'd5; + parameter SYS_FFEmpty =4'd6; + parameter SYS_EOP_err =4'd7; + parameter SYS_SOP_err =4'd8; + + reg [3:0] Current_state_SYS /* synthesis syn_preserve =1 */; + reg [3:0] Next_state_SYS; + + reg [MAC_TX_FF_DEPTH-1:0] Add_wr ; + reg [MAC_TX_FF_DEPTH-1:0] Add_wr_ungray ; + reg [MAC_TX_FF_DEPTH-1:0] Add_wr_gray ; + reg [MAC_TX_FF_DEPTH-1:0] Add_wr_gray_dl1 ; + wire [MAC_TX_FF_DEPTH-1:0] Add_wr_gray_tmp ; + + reg [MAC_TX_FF_DEPTH-1:0] Add_rd ; + reg [MAC_TX_FF_DEPTH-1:0] Add_rd_reg ; + reg [MAC_TX_FF_DEPTH-1:0] Add_rd_gray ; + reg [MAC_TX_FF_DEPTH-1:0] Add_rd_gray_dl1 ; + wire [MAC_TX_FF_DEPTH-1:0] Add_rd_gray_tmp ; + reg [MAC_TX_FF_DEPTH-1:0] Add_rd_ungray ; + wire [35:0] Din ; + wire [35:0] Dout ; + reg Wr_en ; + wire [MAC_TX_FF_DEPTH-1:0] Add_wr_pluse ; + wire [MAC_TX_FF_DEPTH-1:0] Add_wr_pluse_pluse; + wire [MAC_TX_FF_DEPTH-1:0] Add_rd_pluse ; + reg [MAC_TX_FF_DEPTH-1:0] Add_rd_reg_dl1 ; + reg Full /* synthesis syn_keep=1 */; + reg AlmostFull /* synthesis syn_keep=1 */; + reg Empty /* synthesis syn_keep=1 */; + + reg Tx_mac_wa ; + reg Tx_mac_wr_dl1 ; + reg [31:0] Tx_mac_data_dl1 ; + reg [1:0] Tx_mac_BE_dl1 ; + reg Tx_mac_sop_dl1 ; + reg Tx_mac_eop_dl1 ; + reg FF_FullErr ; + wire [1:0] Dout_BE ; + wire Dout_eop ; + wire Dout_err ; + wire [31:0] Dout_data ; + reg [35:0] Dout_reg /* synthesis syn_preserve=1 */; + reg Packet_number_sub_dl1 ; + reg Packet_number_sub_dl2 ; + reg Packet_number_sub_edge /* synthesis syn_preserve=1 */; + reg Packet_number_add /* synthesis syn_preserve=1 */; + reg [4:0] Fifo_data_count ; + reg Fifo_ra /* synthesis syn_keep=1 */; + reg [7:0] Fifo_data ; + reg Fifo_da ; + reg Fifo_data_err_empty /* synthesis syn_preserve=1 */; + reg Fifo_eop ; + reg Fifo_rd_dl1 ; + reg Fifo_ra_tmp ; + reg [5:0] Packet_number_inFF /* synthesis syn_keep=1 */; + reg [5:0] Packet_number_inFF_reg /* synthesis syn_preserve=1 */; + reg Pkt_sub_apply_tmp ; + reg Pkt_sub_apply ; + reg Add_rd_reg_rdy_tmp ; + reg Add_rd_reg_rdy ; + reg Add_rd_reg_rdy_dl1 ; + reg Add_rd_reg_rdy_dl2 ; + reg [4:0] Tx_Hwmark_pl ; + reg [4:0] Tx_Lwmark_pl ; + reg Add_rd_jump_tmp ; + reg Add_rd_jump_tmp_pl1 ; + reg Add_rd_jump ; + reg Add_rd_jump_wr_pl1 ; + + integer i ; + + // ****************************************************************************** + //write data to from FF . + //domain Clk_SYS + // ****************************************************************************** + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Current_state_SYS <=SYS_idle; + else + Current_state_SYS <=Next_state_SYS; + + always @ (Current_state_SYS or Tx_mac_wr or Tx_mac_sop or Full or AlmostFull + or Tx_mac_eop ) + case (Current_state_SYS) + SYS_idle: + if (Tx_mac_wr&&Tx_mac_sop&&!Full) + Next_state_SYS =SYS_SOP; + else + Next_state_SYS =Current_state_SYS ; + SYS_SOP: + Next_state_SYS =SYS_MOP; + SYS_MOP: + if (AlmostFull) + Next_state_SYS =SYS_DROP; + else if (Tx_mac_wr&&Tx_mac_sop) + Next_state_SYS =SYS_SOP_err; + else if (Tx_mac_wr&&Tx_mac_eop) + Next_state_SYS =SYS_EOP_ok; + else + Next_state_SYS =Current_state_SYS ; + SYS_EOP_ok: + if (Tx_mac_wr&&Tx_mac_sop) + Next_state_SYS =SYS_SOP; + else + Next_state_SYS =SYS_idle; + SYS_EOP_err: + if (Tx_mac_wr&&Tx_mac_sop) + Next_state_SYS =SYS_SOP; + else + Next_state_SYS =SYS_idle; + SYS_SOP_err: + Next_state_SYS =SYS_DROP; + SYS_DROP: //FIFO overflow + if (Tx_mac_wr&&Tx_mac_eop) + Next_state_SYS =SYS_EOP_err; + else + Next_state_SYS =Current_state_SYS ; + default: + Next_state_SYS =SYS_idle; + endcase + + //delay signals + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Tx_mac_wr_dl1 <=0; + Tx_mac_data_dl1 <=0; + Tx_mac_BE_dl1 <=0; + Tx_mac_sop_dl1 <=0; + Tx_mac_eop_dl1 <=0; + end + else + begin + Tx_mac_wr_dl1 <=Tx_mac_wr ; + Tx_mac_data_dl1 <=Tx_mac_data ; + Tx_mac_BE_dl1 <=Tx_mac_BE ; + Tx_mac_sop_dl1 <=Tx_mac_sop ; + Tx_mac_eop_dl1 <=Tx_mac_eop ; + end + + always @(Current_state_SYS) + if (Current_state_SYS==SYS_EOP_err) + FF_FullErr =1; + else + FF_FullErr =0; + + reg Tx_mac_eop_gen; + + always @(Current_state_SYS) + if (Current_state_SYS==SYS_EOP_err||Current_state_SYS==SYS_EOP_ok) + Tx_mac_eop_gen =1; + else + Tx_mac_eop_gen =0; + + assign Din={Tx_mac_eop_gen,FF_FullErr,Tx_mac_BE_dl1,Tx_mac_data_dl1}; + + always @(Current_state_SYS or Tx_mac_wr_dl1) + if ((Current_state_SYS==SYS_SOP||Current_state_SYS==SYS_EOP_ok|| + Current_state_SYS==SYS_MOP||Current_state_SYS==SYS_EOP_err)&&Tx_mac_wr_dl1) + Wr_en = 1; + else + Wr_en = 0; + + + always @ (posedge Reset or posedge Clk_SYS) + if (Reset) + Add_wr_gray <=0; + else + begin + Add_wr_gray[MAC_TX_FF_DEPTH-1] <=Add_wr[MAC_TX_FF_DEPTH-1]; + for (i=MAC_TX_FF_DEPTH-2;i>=0;i=i-1) + Add_wr_gray[i] <=Add_wr[i+1]^Add_wr[i]; + end + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_rd_gray_dl1 <=0; + else + Add_rd_gray_dl1 <=Add_rd_gray; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_rd_jump_wr_pl1 <=0; + else + Add_rd_jump_wr_pl1 <=Add_rd_jump; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_rd_ungray =0; + else if (!Add_rd_jump_wr_pl1) + begin + Add_rd_ungray[MAC_TX_FF_DEPTH-1] =Add_rd_gray_dl1[MAC_TX_FF_DEPTH-1]; + for (i=MAC_TX_FF_DEPTH-2;i>=0;i=i-1) + Add_rd_ungray[i] =Add_rd_ungray[i+1]^Add_rd_gray_dl1[i]; + end + assign Add_wr_pluse =Add_wr+1; + assign Add_wr_pluse_pluse =Add_wr+4; + + always @ (Add_wr_pluse or Add_rd_ungray) + if (Add_wr_pluse==Add_rd_ungray) + Full =1; + else + Full =0; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + AlmostFull <=0; + else if (Add_wr_pluse_pluse==Add_rd_ungray) + AlmostFull <=1; + else + AlmostFull <=0; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_wr <= 0; + else if (Wr_en&&!Full) + Add_wr <= Add_wr +1; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Packet_number_sub_dl1 <=0; + Packet_number_sub_dl2 <=0; + end + else + begin + Packet_number_sub_dl1 <=Pkt_sub_apply; + Packet_number_sub_dl2 <=Packet_number_sub_dl1; + end + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Packet_number_sub_edge <=0; + else if (Packet_number_sub_dl1&!Packet_number_sub_dl2) + Packet_number_sub_edge <=1; + else + Packet_number_sub_edge <=0; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Packet_number_add <=0; + else if (Current_state_SYS==SYS_EOP_ok||Current_state_SYS==SYS_EOP_err) + Packet_number_add <=1; + else + Packet_number_add <=0; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Packet_number_inFF <=0; + else if (Packet_number_add&&!Packet_number_sub_edge) + Packet_number_inFF <=Packet_number_inFF + 1'b1; + else if (!Packet_number_add&&Packet_number_sub_edge) + Packet_number_inFF <=Packet_number_inFF - 1'b1; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Packet_number_inFF_reg <=0; + else + Packet_number_inFF_reg <=Packet_number_inFF; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Add_rd_reg_rdy_dl1 <=0; + Add_rd_reg_rdy_dl2 <=0; + end + else + begin + Add_rd_reg_rdy_dl1 <=Add_rd_reg_rdy; + Add_rd_reg_rdy_dl2 <=Add_rd_reg_rdy_dl1; + end + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Add_rd_reg_dl1 <=0; + else if (Add_rd_reg_rdy_dl1&!Add_rd_reg_rdy_dl2) + Add_rd_reg_dl1 <=Add_rd_reg; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Fifo_data_count <=0; + else if (FullDuplex) + Fifo_data_count <=Add_wr[MAC_TX_FF_DEPTH-1:MAC_TX_FF_DEPTH-5]-Add_rd_ungray[MAC_TX_FF_DEPTH-1:MAC_TX_FF_DEPTH-5]; + else + Fifo_data_count <=Add_wr[MAC_TX_FF_DEPTH-1:MAC_TX_FF_DEPTH-5]-Add_rd_reg_dl1[MAC_TX_FF_DEPTH-1:MAC_TX_FF_DEPTH-5]; //for half duplex backoff requirement + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Fifo_ra_tmp <=0; + else if (Packet_number_inFF_reg>=1||Fifo_data_count>=Tx_Lwmark) + Fifo_ra_tmp <=1; + else + Fifo_ra_tmp <=0; + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + begin + Tx_Hwmark_pl <=0; + Tx_Lwmark_pl <=0; + end + else + begin + Tx_Hwmark_pl <=Tx_Hwmark; + Tx_Lwmark_pl <=Tx_Lwmark; + end + + always @ (posedge Clk_SYS or posedge Reset) + if (Reset) + Tx_mac_wa <=0; + else if (Fifo_data_count>=Tx_Hwmark_pl) + Tx_mac_wa <=0; + else if (Fifo_data_count<Tx_Lwmark_pl) + Tx_mac_wa <=1; + + // ****************************************************************************** + // rd data to from FF . + // domain Clk_MAC + // ****************************************************************************** + + reg[35:0] Dout_dl1; + reg Dout_reg_en /* synthesis syn_keep=1 */; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Dout_dl1 <=0; + else + Dout_dl1 <=Dout; + + always @ (Current_state_MAC or Next_state_MAC) + if ((Current_state_MAC==MAC_idle||Current_state_MAC==MAC_byte0)&&Next_state_MAC==MAC_byte3) + Dout_reg_en =1; + else + Dout_reg_en =0; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Dout_reg <=0; + else if (Dout_reg_en) + Dout_reg <=Dout_dl1; + + assign {Dout_eop,Dout_err,Dout_BE,Dout_data}=Dout_reg; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Current_state_MAC <=MAC_idle; + else + Current_state_MAC <=Next_state_MAC; + + always @ (Current_state_MAC or Fifo_rd or Dout_BE or Dout_eop or Fifo_rd_retry + or Fifo_rd_finish or Empty or Fifo_rd or Fifo_eop) + case (Current_state_MAC) + MAC_idle: + if (Empty&&Fifo_rd) + Next_state_MAC=MAC_FF_Err; + else if (Fifo_rd) + Next_state_MAC=MAC_byte3; + else + Next_state_MAC=Current_state_MAC; + MAC_byte3: + if (Fifo_rd_retry) + Next_state_MAC=MAC_retry; + else if (Fifo_eop) + Next_state_MAC=MAC_wait_finish; + else if (Fifo_rd&&!Fifo_eop) + Next_state_MAC=MAC_byte2; + else + Next_state_MAC=Current_state_MAC; + MAC_byte2: + if (Fifo_rd_retry) + Next_state_MAC=MAC_retry; + else if (Fifo_eop) + Next_state_MAC=MAC_wait_finish; + else if (Fifo_rd&&!Fifo_eop) + Next_state_MAC=MAC_byte1; + else + Next_state_MAC=Current_state_MAC; + MAC_byte1: + if (Fifo_rd_retry) + Next_state_MAC=MAC_retry; + else if (Fifo_eop) + Next_state_MAC=MAC_wait_finish; + else if (Fifo_rd&&!Fifo_eop) + Next_state_MAC=MAC_byte0; + else + Next_state_MAC=Current_state_MAC; + MAC_byte0: + if (Empty&&Fifo_rd&&!Fifo_eop) + Next_state_MAC=MAC_FFEmpty; + else if (Fifo_rd_retry) + Next_state_MAC=MAC_retry; + else if (Fifo_eop) + Next_state_MAC=MAC_wait_finish; + else if (Fifo_rd&&!Fifo_eop) + Next_state_MAC=MAC_byte3; + else + Next_state_MAC=Current_state_MAC; + MAC_retry: + Next_state_MAC=MAC_idle; + MAC_wait_finish: + if (Fifo_rd_finish) + Next_state_MAC=MAC_pkt_sub; + else + Next_state_MAC=Current_state_MAC; + MAC_pkt_sub: + Next_state_MAC=MAC_idle; + MAC_FFEmpty: + if (!Empty) + Next_state_MAC=MAC_byte3; + else + Next_state_MAC=Current_state_MAC; + MAC_FF_Err: //stopped state-machine need change + Next_state_MAC=Current_state_MAC; + default + Next_state_MAC=MAC_idle; + endcase + + always @ (posedge Reset or posedge Clk_MAC) + if (Reset) + Add_rd_gray <=0; + else + begin + Add_rd_gray[MAC_TX_FF_DEPTH-1] <=Add_rd[MAC_TX_FF_DEPTH-1]; + for (i=MAC_TX_FF_DEPTH-2;i>=0;i=i-1) + Add_rd_gray[i] <=Add_rd[i+1]^Add_rd[i]; + end + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_wr_gray_dl1 <=0; + else + Add_wr_gray_dl1 <=Add_wr_gray; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_wr_ungray =0; + else + begin + Add_wr_ungray[MAC_TX_FF_DEPTH-1] =Add_wr_gray_dl1[MAC_TX_FF_DEPTH-1]; + for (i=MAC_TX_FF_DEPTH-2;i>=0;i=i-1) + Add_wr_ungray[i] =Add_wr_ungray[i+1]^Add_wr_gray_dl1[i]; + end + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Empty <=1; + else if (Add_rd==Add_wr_ungray) + Empty <=1; + else + Empty <=0; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_ra <=0; + else + Fifo_ra <=Fifo_ra_tmp; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Pkt_sub_apply_tmp <=0; + else if (Current_state_MAC==MAC_pkt_sub) + Pkt_sub_apply_tmp <=1; + else + Pkt_sub_apply_tmp <=0; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Pkt_sub_apply <=0; + else if ((Current_state_MAC==MAC_pkt_sub)||Pkt_sub_apply_tmp) + Pkt_sub_apply <=1; + else + Pkt_sub_apply <=0; + + //reg Add_rd for collison retry + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_reg <=0; + else if (Fifo_rd_finish) + Add_rd_reg <=Add_rd; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_reg_rdy_tmp <=0; + else if (Fifo_rd_finish) + Add_rd_reg_rdy_tmp <=1; + else + Add_rd_reg_rdy_tmp <=0; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_reg_rdy <=0; + else if (Fifo_rd_finish||Add_rd_reg_rdy_tmp) + Add_rd_reg_rdy <=1; + else + Add_rd_reg_rdy <=0; + + reg Add_rd_add /* synthesis syn_keep=1 */; + + always @ (Current_state_MAC or Next_state_MAC) + if ((Current_state_MAC==MAC_idle||Current_state_MAC==MAC_byte0)&&Next_state_MAC==MAC_byte3) + Add_rd_add =1; + else + Add_rd_add =0; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd <=0; + else if (Current_state_MAC==MAC_retry) + Add_rd <= Add_rd_reg; + else if (Add_rd_add) + Add_rd <= Add_rd + 1; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_jump_tmp <=0; + else if (Current_state_MAC==MAC_retry) + Add_rd_jump_tmp <=1; + else + Add_rd_jump_tmp <=0; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_jump_tmp_pl1 <=0; + else + Add_rd_jump_tmp_pl1 <=Add_rd_jump_tmp; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Add_rd_jump <=0; + else if (Current_state_MAC==MAC_retry) + Add_rd_jump <=1; + else if (Add_rd_jump_tmp_pl1) + Add_rd_jump <=0; + + //gen Fifo_data + always @ (Dout_data or Current_state_MAC) + case (Current_state_MAC) + MAC_byte3: + Fifo_data =Dout_data[31:24]; + MAC_byte2: + Fifo_data =Dout_data[23:16]; + MAC_byte1: + Fifo_data =Dout_data[15:8]; + MAC_byte0: + Fifo_data =Dout_data[7:0]; + default: + Fifo_data =0; + endcase + + //gen Fifo_da + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_rd_dl1 <=0; + else + Fifo_rd_dl1 <=Fifo_rd; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_da <=0; + else if ((Current_state_MAC==MAC_byte0||Current_state_MAC==MAC_byte1|| + Current_state_MAC==MAC_byte2||Current_state_MAC==MAC_byte3)&&Fifo_rd&&!Fifo_eop) + Fifo_da <=1; + else + Fifo_da <=0; + + //gen Fifo_data_err_empty + assign Fifo_data_err_full=Dout_err; + //gen Fifo_data_err_empty + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Current_state_MAC_reg <=0; + else + Current_state_MAC_reg <=Current_state_MAC; + + always @ (posedge Clk_MAC or posedge Reset) + if (Reset) + Fifo_data_err_empty <=0; + else if (Current_state_MAC_reg==MAC_FFEmpty) + Fifo_data_err_empty <=1; + else + Fifo_data_err_empty <=0; + + always @ (posedge Clk_MAC) + if (Current_state_MAC_reg==MAC_FF_Err) + begin + $finish(2); + $display("mac_tx_FF meet error status at time :%t",$time); + end + + //gen Fifo_eop aligned to last valid data byte¡£ + always @ (Current_state_MAC or Dout_eop) + if (((Current_state_MAC==MAC_byte0&&Dout_BE==2'b00|| + Current_state_MAC==MAC_byte1&&Dout_BE==2'b11|| + Current_state_MAC==MAC_byte2&&Dout_BE==2'b10|| + Current_state_MAC==MAC_byte3&&Dout_BE==2'b01)&&Dout_eop)) + Fifo_eop =1; + else + Fifo_eop =0; + //****************************************************************************** + duram #(36,MAC_TX_FF_DEPTH) + U_duram(.data_a (Din ), + .wren_a (Wr_en ), + .address_a (Add_wr ), + .address_b (Add_rd ), + .clock_a (Clk_SYS ), + .clock_b (Clk_MAC ), + .q_b (Dout )); + +endmodule // MAC_tx_FF diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/MAC_tx_addr_add.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/MAC_tx_addr_add.v new file mode 100644 index 000000000..fa6cd4c2e --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/MAC_tx_addr_add.v @@ -0,0 +1,128 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_tx_addr_add.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/wr_en/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_tx_addr_add.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:18 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module MAC_tx_addr_add ( +Reset , +Clk , +MAC_tx_addr_init , +MAC_tx_addr_rd , +MAC_tx_addr_data , +//CPU , +MAC_add_prom_data , +MAC_add_prom_add , +MAC_add_prom_wr +); + +input Reset ; +input Clk ; +input MAC_tx_addr_rd ; +input MAC_tx_addr_init ; +output [7:0] MAC_tx_addr_data ; + //CPU ; +input [7:0] MAC_add_prom_data ; +input [2:0] MAC_add_prom_add ; +input MAC_add_prom_wr ; + +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [2:0] add_rd; +wire[2:0] add_wr; +wire[7:0] din; +wire[7:0] dout; +wire wr_en; +reg MAC_add_prom_wr_dl1; +reg MAC_add_prom_wr_dl2; +//****************************************************************************** +//write data from cpu to prom +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + MAC_add_prom_wr_dl1 <=0; + MAC_add_prom_wr_dl2 <=0; + end + else + begin + MAC_add_prom_wr_dl1 <=MAC_add_prom_wr; + MAC_add_prom_wr_dl2 <=MAC_add_prom_wr_dl1; + end +assign # 2 wr_en =MAC_add_prom_wr_dl1&!MAC_add_prom_wr_dl2; +assign # 2 add_wr =MAC_add_prom_add; +assign # 2 din =MAC_add_prom_data; + +//****************************************************************************** +//read data from cpu to prom +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + add_rd <=0; + else if (MAC_tx_addr_init) + add_rd <=0; + else if (MAC_tx_addr_rd) + add_rd <=add_rd + 1; +assign MAC_tx_addr_data=dout; +//****************************************************************************** +//b port for read ,a port for write . +//****************************************************************************** +duram #(8,3,"M512","DUAL_PORT") U_duram( +.data_a (din ), +.wren_a (wr_en ), +.address_a (add_wr ), +.address_b (add_rd ), +.clock_a (Clk ), +.clock_b (Clk ), +.q_b (dout )); + + +endmodule + diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/MAC_tx_ctrl.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/MAC_tx_ctrl.v new file mode 100644 index 000000000..5412bd13f --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/MAC_tx_ctrl.v @@ -0,0 +1,646 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// MAC_tx_ctrl.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: MAC_tx_Ctrl.v,v $ +// Revision 1.4 2006/06/25 04:58:56 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.3 2005/12/16 06:44:17 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.2 2005/12/13 12:15:38 Administrator +// no message +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module MAC_tx_ctrl ( +Reset , +Clk , +//CRC_gen Interface +CRC_init , +Frame_data , +Data_en , +CRC_rd , +CRC_end , +CRC_out , +//Ramdon_gen interfac +Random_init , +RetryCnt , +Random_time_meet , +//flow control +pause_apply , +pause_quanta_sub , +xoff_gen , +xoff_gen_complete , +xon_gen , +xon_gen_complete , +//MAC_tx_FF +Fifo_data , +Fifo_rd , +Fifo_eop , +Fifo_da , +Fifo_rd_finish , +Fifo_rd_retry , +Fifo_ra , +Fifo_data_err_empty , +Fifo_data_err_full , +//RMII +TxD , +TxEn , +CRS , +//MAC_tx_addr_add +MAC_tx_addr_rd , +MAC_tx_addr_data , +MAC_tx_addr_init , +//RMON +Tx_pkt_type_rmon , +Tx_pkt_length_rmon , +Tx_apply_rmon , +Tx_pkt_err_type_rmon, +//CPU +pause_frame_send_en , +pause_quanta_set , +MAC_tx_add_en , +FullDuplex , +MaxRetry , +IFGset +); + +input Reset ; +input Clk ; + //CRC_gen Interface +output CRC_init ; +output [7:0] Frame_data ; +output Data_en ; +output CRC_rd ; +input CRC_end ; +input [7:0] CRC_out ; + //Ramdon_gen interface +output Random_init ; +output [3:0] RetryCnt ; +input Random_time_meet ;//levle hight indicate random time passed away + //flow control +input pause_apply ; +output pause_quanta_sub ; +input xoff_gen ; +output xoff_gen_complete ; +input xon_gen ; +output xon_gen_complete ; + //MAC_rx_FF +input [7:0] Fifo_data ; +output Fifo_rd ; +input Fifo_eop ; +input Fifo_da ; +output Fifo_rd_finish ; +output Fifo_rd_retry ; +input Fifo_ra ; +input Fifo_data_err_empty ; +input Fifo_data_err_full ; + //RMII +output [7:0] TxD ; +output TxEn ; +input CRS ; + //MAC_tx_addr_add +output MAC_tx_addr_init ; +output MAC_tx_addr_rd ; +input [7:0] MAC_tx_addr_data ; + //RMON +output [2:0] Tx_pkt_type_rmon ; +output [15:0] Tx_pkt_length_rmon ; +output Tx_apply_rmon ; +output [2:0] Tx_pkt_err_type_rmon; + //CPU +input pause_frame_send_en ; +input [15:0] pause_quanta_set ; +input MAC_tx_add_en ; +input FullDuplex ; +input [3:0] MaxRetry ; +input [5:0] IFGset ; +//****************************************************************************** +//internal signals +//****************************************************************************** +parameter StateIdle =4'd00; +parameter StatePreamble =4'd01; +parameter StateSFD =4'd02; +parameter StateData =4'd03; +parameter StatePause =4'd04; +parameter StatePAD =4'd05; +parameter StateFCS =4'd06; +parameter StateIFG =4'd07; +parameter StateJam =4'd08; +parameter StateBackOff =4'd09; +parameter StateJamDrop =4'd10; +parameter StateFFEmptyDrop =4'd11; +parameter StateSwitchNext =4'd12; +parameter StateDefer =4'd13; +parameter StateSendPauseFrame =4'd14; + +reg [3:0] Current_state /*synthesis syn_keep=1 */; +reg [3:0] Next_state; +reg [5:0] IFG_counter; +reg [4:0] Preamble_counter;// +reg [7:0] TxD_tmp ; +reg TxEn_tmp ; +reg [15:0] Tx_pkt_length_rmon ; +reg Tx_apply_rmon ; +reg Tx_apply_rmon_tmp ; +reg Tx_apply_rmon_tmp_pl1; +reg [2:0] Tx_pkt_err_type_rmon; +reg [3:0] RetryCnt ; +reg Random_init ; +reg Fifo_rd_finish ; +reg Fifo_rd_retry ; +reg [7:0] TxD ; +reg TxEn ; +reg CRC_init ; +reg Data_en ; +reg CRC_rd ; +reg Fifo_rd ; +reg MAC_tx_addr_rd ; +reg MAC_header_slot ; +reg MAC_header_slot_tmp ; +reg [2:0] Tx_pkt_type_rmon ; +wire Collision ; +reg MAC_tx_addr_init ; +reg Src_MAC_ptr ; +reg [7:0] IPLengthCounter ;//for pad append +reg [1:0] PADCounter ; +reg [7:0] JamCounter ; +reg PktDrpEvenPtr ; +reg [7:0] pause_counter ; +reg pause_quanta_sub ; +reg pause_frame_send_en_dl1 ; +reg [15:0] pause_quanta_set_dl1 ; +reg xoff_gen_complete ; +reg xon_gen_complete ; +//****************************************************************************** +//boundery signal processing +//****************************************************************************** +always @(posedge Clk or posedge Reset) + if (Reset) + begin + pause_frame_send_en_dl1 <=0; + pause_quanta_set_dl1 <=0; + end + else + begin + pause_frame_send_en_dl1 <=pause_frame_send_en ; + pause_quanta_set_dl1 <=pause_quanta_set ; + end +//****************************************************************************** +//state machine +//****************************************************************************** +assign Collision=TxEn&CRS; + +always @(posedge Clk or posedge Reset) + if (Reset) + pause_counter <=0; + else if (Current_state!=StatePause) + pause_counter <=0; + else + pause_counter <=pause_counter+1; + +always @(posedge Clk or posedge Reset) + if (Reset) + IPLengthCounter <=0; + else if (Current_state==StateDefer) + IPLengthCounter <=0; + else if (IPLengthCounter!=8'hff&&(Current_state==StateData||Current_state==StateSendPauseFrame||Current_state==StatePAD)) + IPLengthCounter <=IPLengthCounter+1; + +always @(posedge Clk or posedge Reset) + if (Reset) + PADCounter <=0; + else if (Current_state!=StatePAD) + PADCounter <=0; + else + PADCounter <=PADCounter+1; + +always @(posedge Clk or posedge Reset) + if (Reset) + Current_state <=StateDefer; + else + Current_state <=Next_state; + +always @ (*) + case (Current_state) + StateDefer: + if ((FullDuplex)||(!FullDuplex&&!CRS)) + Next_state=StateIFG; + else + Next_state=Current_state; + StateIFG: + if (!FullDuplex&&CRS) + Next_state=StateDefer; + else if ((FullDuplex&&IFG_counter==IFGset-4)||(!FullDuplex&&!CRS&&IFG_counter==IFGset-4))//remove some additional time + Next_state=StateIdle; + else + Next_state=Current_state; + StateIdle: + if (!FullDuplex&&CRS) + Next_state=StateDefer; + else if (pause_apply) + Next_state=StatePause; + else if ((FullDuplex&&Fifo_ra)||(!FullDuplex&&!CRS&&Fifo_ra)||(pause_frame_send_en_dl1&&(xoff_gen||xon_gen))) + Next_state=StatePreamble; + else + Next_state=Current_state; + StatePause: + if (pause_counter==512/8) + Next_state=StateDefer; + else + Next_state=Current_state; + StatePreamble: + if (!FullDuplex&&Collision) + Next_state=StateJam; + else if ((FullDuplex&&Preamble_counter==6)||(!FullDuplex&&!Collision&&Preamble_counter==6)) + Next_state=StateSFD; + else + Next_state=Current_state; + StateSFD: + if (!FullDuplex&&Collision) + Next_state=StateJam; + else if (pause_frame_send_en_dl1&&(xoff_gen||xon_gen)) + Next_state=StateSendPauseFrame; + else + Next_state=StateData; + StateSendPauseFrame: + if (IPLengthCounter==17) + Next_state=StatePAD; + else + Next_state=Current_state; + StateData: + if (!FullDuplex&&Collision) + Next_state=StateJam; + else if (Fifo_data_err_empty) + Next_state=StateFFEmptyDrop; + else if (Fifo_eop&&IPLengthCounter>=59)//IP+MAC+TYPE=60 ,start from 0 + Next_state=StateFCS; + else if (Fifo_eop) + Next_state=StatePAD; + else + Next_state=StateData; + StatePAD: + if (!FullDuplex&&Collision) + Next_state=StateJam; + else if (IPLengthCounter>=59) + Next_state=StateFCS; + else + Next_state=Current_state; + StateJam: + if (RetryCnt<=MaxRetry&&JamCounter==16) + Next_state=StateBackOff; + else if (RetryCnt>MaxRetry) + Next_state=StateJamDrop; + else + Next_state=Current_state; + StateBackOff: + if (Random_time_meet) + Next_state =StateDefer; + else + Next_state =Current_state; + StateFCS: + if (!FullDuplex&&Collision) + Next_state =StateJam; + else if (CRC_end) + Next_state =StateSwitchNext; + else + Next_state =Current_state; + StateFFEmptyDrop: + if (Fifo_eop) + Next_state =StateSwitchNext; + else + Next_state =Current_state; + StateJamDrop: + if (Fifo_eop) + Next_state =StateSwitchNext; + else + Next_state =Current_state; + StateSwitchNext: + Next_state =StateDefer; + default: + Next_state =StateDefer; + endcase + + + +always @ (posedge Clk or posedge Reset) + if (Reset) + JamCounter <=0; + else if (Current_state!=StateJam) + JamCounter <=0; + else if (Current_state==StateJam) + JamCounter <=JamCounter+1; + + +always @ (posedge Clk or posedge Reset) + if (Reset) + RetryCnt <=0; + else if (Current_state==StateSwitchNext) + RetryCnt <=0; + else if (Current_state==StateJam&&Next_state==StateBackOff) + RetryCnt <=RetryCnt + 1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + IFG_counter <=0; + else if (Current_state!=StateIFG) + IFG_counter <=0; + else + IFG_counter <=IFG_counter + 1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Preamble_counter <=0; + else if (Current_state!=StatePreamble) + Preamble_counter <=0; + else + Preamble_counter <=Preamble_counter+ 1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + PktDrpEvenPtr <=0; + else if(Current_state==StateJamDrop||Current_state==StateFFEmptyDrop) + PktDrpEvenPtr <=~PktDrpEvenPtr; +//****************************************************************************** +//generate output signals +//****************************************************************************** +//CRC related +always @(Current_state) + if (Current_state==StateSFD) + CRC_init =1; + else + CRC_init =0; + +assign Frame_data=TxD_tmp; + +always @(Current_state) + if (Current_state==StateData||Current_state==StateSendPauseFrame||Current_state==StatePAD) + Data_en =1; + else + Data_en =0; + +always @(Current_state) + if (Current_state==StateFCS) + CRC_rd =1; + else + CRC_rd =0; + +//Ramdon_gen interface +always @(Current_state or Next_state) + if (Current_state==StateJam&&Next_state==StateBackOff) + Random_init =1; + else + Random_init =0; + +//MAC_rx_FF +//data have one cycle delay after fifo read signals +always @ (*) + if (Current_state==StateData || + Current_state==StateSFD&&!(pause_frame_send_en_dl1&&(xoff_gen||xon_gen)) || + Current_state==StateJamDrop&&PktDrpEvenPtr|| + Current_state==StateFFEmptyDrop&&PktDrpEvenPtr ) + Fifo_rd =1; + else + Fifo_rd =0; + +always @ (Current_state) + if (Current_state==StateSwitchNext) + Fifo_rd_finish =1; + else + Fifo_rd_finish =0; + +always @ (Current_state) + if (Current_state==StateJam) + Fifo_rd_retry =1; + else + Fifo_rd_retry =0; +//RMII +always @(Current_state) + if (Current_state==StatePreamble||Current_state==StateSFD|| + Current_state==StateData||Current_state==StateSendPauseFrame|| + Current_state==StateFCS||Current_state==StatePAD||Current_state==StateJam) + TxEn_tmp =1; + else + TxEn_tmp =0; + +//gen txd data +always @(*) + case (Current_state) + StatePreamble: + TxD_tmp =8'h55; + StateSFD: + TxD_tmp =8'hd5; + StateData: + if (Src_MAC_ptr&&MAC_tx_add_en) + TxD_tmp =MAC_tx_addr_data; + else + TxD_tmp =Fifo_data; + StateSendPauseFrame: + if (Src_MAC_ptr&&MAC_tx_add_en) + TxD_tmp =MAC_tx_addr_data; + else + case (IPLengthCounter) + 7'd0: TxD_tmp =8'h01; + 7'd1: TxD_tmp =8'h80; + 7'd2: TxD_tmp =8'hc2; + 7'd3: TxD_tmp =8'h00; + 7'd4: TxD_tmp =8'h00; + 7'd5: TxD_tmp =8'h01; + 7'd12: TxD_tmp =8'h88;//type + 7'd13: TxD_tmp =8'h08;// + 7'd14: TxD_tmp =8'h00;//opcode + 7'd15: TxD_tmp =8'h01; + 7'd16: TxD_tmp =xon_gen?8'b0:pause_quanta_set_dl1[15:8]; + 7'd17: TxD_tmp =xon_gen?8'b0:pause_quanta_set_dl1[7:0]; +// 7'd60: TxD_tmp =8'h26; +// 7'd61: TxD_tmp =8'h6b; +// 7'd62: TxD_tmp =8'hae; +// 7'd63: TxD_tmp =8'h0a; + default:TxD_tmp =0; + endcase + + StatePAD: + TxD_tmp =8'h00; + StateJam: + TxD_tmp =8'h01; //jam sequence + StateFCS: + TxD_tmp =CRC_out; + default: + TxD_tmp =2'b0; + endcase +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + TxD <=0; + TxEn <=0; + end + else + begin + TxD <=TxD_tmp; + TxEn <=TxEn_tmp; + end +//RMON + + +always @ (posedge Clk or posedge Reset) + if (Reset) + Tx_pkt_length_rmon <=0; + else if (Current_state==StateSFD) + Tx_pkt_length_rmon <=0; + else if (Current_state==StateData||Current_state==StateSendPauseFrame||Current_state==StatePAD||Current_state==StateFCS) + Tx_pkt_length_rmon <=Tx_pkt_length_rmon+1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Tx_apply_rmon_tmp <=0; + else if ((Fifo_eop&&Current_state==StateJamDrop)|| + (Fifo_eop&&Current_state==StateFFEmptyDrop)|| + CRC_end) + Tx_apply_rmon_tmp <=1; + else + Tx_apply_rmon_tmp <=0; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Tx_apply_rmon_tmp_pl1 <=0; + else + Tx_apply_rmon_tmp_pl1 <=Tx_apply_rmon_tmp; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Tx_apply_rmon <=0; + else if ((Fifo_eop&&Current_state==StateJamDrop)|| + (Fifo_eop&&Current_state==StateFFEmptyDrop)|| + CRC_end) + Tx_apply_rmon <=1; + else if (Tx_apply_rmon_tmp_pl1) + Tx_apply_rmon <=0; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Tx_pkt_err_type_rmon <=0; + else if(Fifo_eop&&Current_state==StateJamDrop) + Tx_pkt_err_type_rmon <=3'b001;// + else if(Fifo_eop&&Current_state==StateFFEmptyDrop) + Tx_pkt_err_type_rmon <=3'b010;//underflow + else if(Fifo_eop&&Fifo_data_err_full) + Tx_pkt_err_type_rmon <=3'b011;//overflow + else if(CRC_end) + Tx_pkt_err_type_rmon <=3'b100;//normal + +always @ (posedge Clk or posedge Reset) + if (Reset) + MAC_header_slot_tmp <=0; + else if(Current_state==StateSFD&&Next_state==StateData) + MAC_header_slot_tmp <=1; + else + MAC_header_slot_tmp <=0; + +always @ (posedge Clk or posedge Reset) + if (Reset) + MAC_header_slot <=0; + else + MAC_header_slot <=MAC_header_slot_tmp; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Tx_pkt_type_rmon <=0; + else if (Current_state==StateSendPauseFrame) + Tx_pkt_type_rmon <=3'b100; + else if(MAC_header_slot) + Tx_pkt_type_rmon <={1'b0,TxD[7:6]}; + + +always @(Tx_pkt_length_rmon) + if (Tx_pkt_length_rmon>=6&&Tx_pkt_length_rmon<=11) + Src_MAC_ptr =1; + else + Src_MAC_ptr =0; + +//MAC_tx_addr_add +always @ (posedge Clk or posedge Reset) + if (Reset) + MAC_tx_addr_rd <=0; + else if ((Tx_pkt_length_rmon>=4&&Tx_pkt_length_rmon<=9)&&(MAC_tx_add_en||Current_state==StateSendPauseFrame)) + MAC_tx_addr_rd <=1; + else + MAC_tx_addr_rd <=0; + +always @ (Tx_pkt_length_rmon or Fifo_rd) + if ((Tx_pkt_length_rmon==3)&&Fifo_rd) + MAC_tx_addr_init=1; + else + MAC_tx_addr_init=0; + +//flow control +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta_sub <=0; + else if(pause_counter==512/8) + pause_quanta_sub <=1; + else + pause_quanta_sub <=0; + + +always @ (posedge Clk or posedge Reset) + if (Reset) + xoff_gen_complete <=0; + else if(Current_state==StateDefer&&xoff_gen) + xoff_gen_complete <=1; + else + xoff_gen_complete <=0; + + +always @ (posedge Clk or posedge Reset) + if (Reset) + xon_gen_complete <=0; + else if(Current_state==StateDefer&&xon_gen) + xon_gen_complete <=1; + else + xon_gen_complete <=0; + +endmodule diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/flow_ctrl.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/flow_ctrl.v new file mode 100644 index 000000000..76534e65c --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/flow_ctrl.v @@ -0,0 +1,203 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// flow_ctrl.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: flow_ctrl.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:19 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module flow_ctrl +( +Reset , +Clk , +//host processor , +tx_pause_en , +xoff_cpu , +xon_cpu , +//MAC_rx_flow , +pause_quanta , +pause_quanta_val , +//MAC_tx_ctrl , +pause_apply , +pause_quanta_sub , +xoff_gen , +xoff_gen_complete , +xon_gen , +xon_gen_complete + +); + +input Reset ; +input Clk ; + //host processor ; +input tx_pause_en ; +input xoff_cpu ; +input xon_cpu ; + //MAC_rx_flow ; +input [15:0] pause_quanta ; +input pause_quanta_val ; + //MAC_tx_ctrl ; +output pause_apply ; +input pause_quanta_sub ; +output xoff_gen ; +input xoff_gen_complete ; +output xon_gen ; +input xon_gen_complete ; + +//****************************************************************************** +//internal signals +//****************************************************************************** +reg xoff_cpu_dl1 ; +reg xoff_cpu_dl2 ; +reg xon_cpu_dl1 ; +reg xon_cpu_dl2 ; +reg [15:0] pause_quanta_dl1 ; +reg pause_quanta_val_dl1 ; +reg pause_quanta_val_dl2 ; +reg pause_apply ; +reg xoff_gen ; +reg xon_gen ; +reg [15:0] pause_quanta_counter ; +reg tx_pause_en_dl1 ; +reg tx_pause_en_dl2 ; +//****************************************************************************** +//boundery signal processing +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + xoff_cpu_dl1 <=0; + xoff_cpu_dl2 <=0; + end + else + begin + xoff_cpu_dl1 <=xoff_cpu; + xoff_cpu_dl2 <=xoff_cpu_dl1; + end + +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + xon_cpu_dl1 <=0; + xon_cpu_dl2 <=0; + end + else + begin + xon_cpu_dl1 <=xon_cpu; + xon_cpu_dl2 <=xon_cpu_dl1; + end + +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + pause_quanta_dl1 <=0; + end + else + begin + pause_quanta_dl1 <=pause_quanta; + end + +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + pause_quanta_val_dl1 <=0; + pause_quanta_val_dl2 <=0; + end + else + begin + pause_quanta_val_dl1 <=pause_quanta_val; + pause_quanta_val_dl2 <=pause_quanta_val_dl1; + end + +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + tx_pause_en_dl1 <=0; + tx_pause_en_dl2 <=0; + end + else + begin + tx_pause_en_dl1 <=tx_pause_en; + tx_pause_en_dl2 <=tx_pause_en_dl1; + end + +//****************************************************************************** +//gen output signals +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + xoff_gen <=0; + else if (xoff_gen_complete) + xoff_gen <=0; + else if (xoff_cpu_dl1&&!xoff_cpu_dl2) + xoff_gen <=1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + xon_gen <=0; + else if (xon_gen_complete) + xon_gen <=0; + else if (xon_cpu_dl1&&!xon_cpu_dl2) + xon_gen <=1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_quanta_counter <=0; + else if(pause_quanta_val_dl1&&!pause_quanta_val_dl2) + pause_quanta_counter <=pause_quanta_dl1; + else if(pause_quanta_sub&&pause_quanta_counter!=0) + pause_quanta_counter <=pause_quanta_counter-1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + pause_apply <=0; + else if(pause_quanta_counter==0) + pause_apply <=0; + else if (tx_pause_en_dl2) + pause_apply <=1; + +endmodule
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/random_gen.v b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/random_gen.v new file mode 100644 index 000000000..ba344693b --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/MAC_tx/random_gen.v @@ -0,0 +1,123 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// random_gen.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: Ramdon_gen.v,v $ +// Revision 1.3 2006/01/19 14:07:54 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:19 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// + +module random_gen( +Reset , +Clk , +Init , +RetryCnt , +Random_time_meet +); +input Reset ; +input Clk ; +input Init ; +input [3:0] RetryCnt ; +output Random_time_meet; + +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [9:0] Random_sequence ; +reg [9:0] Random ; +reg [9:0] Random_counter ; +reg [7:0] Slot_time_counter; //256*2=512bit=1 slot time +reg Random_time_meet; + +//****************************************************************************** +always @ (posedge Clk or posedge Reset) + if (Reset) + Random_sequence <=0; + else + Random_sequence <={Random_sequence[8:0],~(Random_sequence[2]^Random_sequence[9])}; + +always @ (RetryCnt or Random_sequence) + case (RetryCnt) + 4'h0 : Random={9'b0,Random_sequence[0]}; + 4'h1 : Random={8'b0,Random_sequence[1:0]}; + 4'h2 : Random={7'b0,Random_sequence[2:0]}; + 4'h3 : Random={6'b0,Random_sequence[3:0]}; + 4'h4 : Random={5'b0,Random_sequence[4:0]}; + 4'h5 : Random={4'b0,Random_sequence[5:0]}; + 4'h6 : Random={3'b0,Random_sequence[6:0]}; + 4'h7 : Random={2'b0,Random_sequence[7:0]}; + 4'h8 : Random={1'b0,Random_sequence[8:0]}; + 4'h9 : Random={ Random_sequence[9:0]}; + default : Random={ Random_sequence[9:0]}; + endcase + +always @ (posedge Clk or posedge Reset) + if (Reset) + Slot_time_counter <=0; + else if(Init) + Slot_time_counter <=0; + else if(!Random_time_meet) + Slot_time_counter <=Slot_time_counter+1; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Random_counter <=0; + else if (Init) + Random_counter <=Random; + else if (Random_counter!=0&&Slot_time_counter==255) + Random_counter <=Random_counter -1 ; + +always @ (posedge Clk or posedge Reset) + if (Reset) + Random_time_meet <=1; + else if (Init) + Random_time_meet <=0; + else if (Random_counter==0) + Random_time_meet <=1; + +endmodule + + diff --git a/opencores/ethernet_tri_mode/rtl/verilog/Phy_int.v b/opencores/ethernet_tri_mode/rtl/verilog/Phy_int.v new file mode 100644 index 000000000..7e0090f54 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/Phy_int.v @@ -0,0 +1,227 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Phy_int.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: Phy_int.v,v $ +// Revision 1.3 2006/01/19 14:07:53 maverickist +// verification is complete. +// +// Revision 1.3 2005/12/16 06:44:14 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.2 2005/12/13 12:15:36 Administrator +// no message +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module Phy_int ( +Reset , +MAC_rx_clk , +MAC_tx_clk , +//Rx interface , +MCrs_dv , +MRxD , +MRxErr , +//Tx interface , +MTxD , +MTxEn , +MCRS , +//Phy interface , +Tx_er , +Tx_en , +Txd , +Rx_er , +Rx_dv , +Rxd , +Crs , +Col , +//host interface , +Line_loop_en , +Speed + +); +input Reset ; +input MAC_rx_clk ; +input MAC_tx_clk ; + //Rx interface +output MCrs_dv ; +output [7:0] MRxD ; +output MRxErr ; + //Tx interface +input [7:0] MTxD ; +input MTxEn ; +output MCRS ; + //Phy interface +output Tx_er ; +output Tx_en ; +output [7:0] Txd ; +input Rx_er ; +input Rx_dv ; +input [7:0] Rxd ; +input Crs ; +input Col ; + //host interface +input Line_loop_en ; +input [2:0] Speed ; +//****************************************************************************** +//internal signals +//****************************************************************************** +reg [7:0] MTxD_dl1 ; +reg MTxEn_dl1 ; +reg Tx_odd_data_ptr ; +reg Rx_odd_data_ptr ; +reg Tx_en ; +reg [7:0] Txd ; +reg MCrs_dv ; +reg [7:0] MRxD ; +reg Rx_er_dl1 ; +reg Rx_dv_dl1 ; +reg Rx_dv_dl2 ; +reg [7:0] Rxd_dl1 ; +reg [7:0] Rxd_dl2 ; +reg Crs_dl1 ; +reg Col_dl1 ; +//****************************************************************************** +//Tx control +//****************************************************************************** +//reg boundery signals +always @ (posedge MAC_tx_clk or posedge Reset) + if (Reset) + begin + MTxD_dl1 <=0; + MTxEn_dl1 <=0; + end + else + begin + MTxD_dl1 <=MTxD ; + MTxEn_dl1 <=MTxEn ; + end + +always @ (posedge MAC_tx_clk or posedge Reset) + if (Reset) + Tx_odd_data_ptr <=0; + else if (!MTxD_dl1) + Tx_odd_data_ptr <=0; + else + Tx_odd_data_ptr <=!Tx_odd_data_ptr; + + +always @ (posedge MAC_tx_clk or posedge Reset) + if (Reset) + Txd <=0; + else if(Speed[2]&&MTxEn_dl1) + Txd <=MTxD_dl1; + else if(MTxEn_dl1&&!Tx_odd_data_ptr) + Txd <={4'b0,MTxD_dl1[3:0]}; + else if(MTxEn_dl1&&Tx_odd_data_ptr) + Txd <={4'b0,MTxD_dl1[7:4]}; + else + Txd <=0; + +always @ (posedge MAC_tx_clk or posedge Reset) + if (Reset) + Tx_en <=0; + else if(MTxEn_dl1) + Tx_en <=1; + else + Tx_en <=0; + +assign Tx_er=0; + +//****************************************************************************** +//Rx control +//****************************************************************************** +//reg boundery signals +always @ (posedge MAC_rx_clk or posedge Reset) + if (Reset) + begin + Rx_er_dl1 <=0; + Rx_dv_dl1 <=0; + Rx_dv_dl2 <=0 ; + Rxd_dl1 <=0; + Rxd_dl2 <=0; + Crs_dl1 <=0; + Col_dl1 <=0; + end + else + begin + Rx_er_dl1 <=Rx_er ; + Rx_dv_dl1 <=Rx_dv ; + Rx_dv_dl2 <=Rx_dv_dl1 ; + Rxd_dl1 <=Rxd ; + Rxd_dl2 <=Rxd_dl1 ; + Crs_dl1 <=Crs ; + Col_dl1 <=Col ; + end + +assign MRxErr =Rx_er_dl1 ; +assign MCRS =Crs_dl1 ; + +always @ (posedge MAC_rx_clk or posedge Reset) + if (Reset) + MCrs_dv <=0; + else if(Line_loop_en) + MCrs_dv <=Tx_en; + else if(Rx_dv_dl2) + MCrs_dv <=1; + else + MCrs_dv <=0; + +always @ (posedge MAC_rx_clk or posedge Reset) + if (Reset) + Rx_odd_data_ptr <=0; + else if (!Rx_dv_dl1) + Rx_odd_data_ptr <=0; + else + Rx_odd_data_ptr <=!Rx_odd_data_ptr; + +always @ (posedge MAC_rx_clk or posedge Reset) + if (Reset) + MRxD <=0; + else if(Line_loop_en) + MRxD <=Txd; + else if(Speed[2]&&Rx_dv_dl2) + MRxD <=Rxd_dl2; + else if(Rx_dv_dl1&&Rx_odd_data_ptr) + MRxD <={Rxd_dl1[3:0],Rxd_dl2[3:0]}; + +endmodule
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/rtl/verilog/RMON.v b/opencores/ethernet_tri_mode/rtl/verilog/RMON.v new file mode 100644 index 000000000..c7821a97d --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/RMON.v @@ -0,0 +1,180 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// RMON.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: RMON.v,v $ +// Revision 1.4 2006/06/25 04:58:56 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:53 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:16 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + +module RMON + (Clk , + Reset , + //Tx_RMON + Tx_pkt_type_rmon , + Tx_pkt_length_rmon , + Tx_apply_rmon , + Tx_pkt_err_type_rmon, + //Tx_RMON + Rx_pkt_type_rmon , + Rx_pkt_length_rmon , + Rx_apply_rmon , + Rx_pkt_err_type_rmon, + //CPU + CPU_rd_addr , + CPU_rd_apply , + CPU_rd_grant , + CPU_rd_dout + ); + + input Clk ; + input Reset ; + //Tx_RMON + input [2:0] Tx_pkt_type_rmon ; + input [15:0] Tx_pkt_length_rmon ; + input Tx_apply_rmon ; + input [2:0] Tx_pkt_err_type_rmon; + //Tx_RMON + input [2:0] Rx_pkt_type_rmon ; + input [15:0] Rx_pkt_length_rmon ; + input Rx_apply_rmon ; + input [2:0] Rx_pkt_err_type_rmon; + //CPU + input [5:0] CPU_rd_addr ; + input CPU_rd_apply ; + output CPU_rd_grant ; + output [31:0] CPU_rd_dout ; + + // ****************************************************************************** + //interface signals + // ****************************************************************************** + wire Reg_apply_0 ; + wire [4:0] Reg_addr_0 ; + wire [15:0] Reg_data_0 ; + wire Reg_next_0 ; + wire Reg_apply_1 ; + wire [4:0] Reg_addr_1 ; + wire [15:0] Reg_data_1 ; + wire Reg_next_1 ; + wire [5:0] Addra ; + wire [31:0] Dina ; + wire [31:0] Douta ; + wire Wea ; + + // ****************************************************************************** + + RMON_addr_gen + U_0_Rx_RMON_addr_gen(.Clk (Clk ), + .Reset (Reset ), + //RMON (//RMON ), + // .Pkt_type_rmon (Rx_pkt_type_rmon ), + .Pkt_length_rmon (Rx_pkt_length_rmon ), + .Apply_rmon (Rx_apply_rmon ), + .Pkt_err_type_rmon (Rx_pkt_err_type_rmon ), + //Rmon_ctrl (//Rmon_ctrl ), + .Reg_apply (Reg_apply_0 ), + .Reg_addr (Reg_addr_0 ), + .Reg_data (Reg_data_0 ), + .Reg_next (Reg_next_0 ), + //CPU (//CPU ), + .Reg_drop_apply ( )); + + RMON_addr_gen + U_0_Tx_RMON_addr_gen(.Clk (Clk ), + .Reset (Reset ), + //RMON (//RMON ), + .Pkt_type_rmon (Tx_pkt_type_rmon ), + .Pkt_length_rmon (Tx_pkt_length_rmon ), + .Apply_rmon (Tx_apply_rmon ), + .Pkt_err_type_rmon (Tx_pkt_err_type_rmon ), + //Rmon_ctrl (//Rmon_ctrl ), + .Reg_apply (Reg_apply_1 ), + .Reg_addr (Reg_addr_1 ), + .Reg_data (Reg_data_1 ), + .Reg_next (Reg_next_1 ), + //CPU (//CPU ), + .Reg_drop_apply ( )); + + RMON_ctrl + U_RMON_ctrl(.Clk (Clk ), + .Reset (Reset ), + //RMON_CTRL (//RMON_CTRL ), + .Reg_apply_0 (Reg_apply_0 ), + .Reg_addr_0 (Reg_addr_0 ), + .Reg_data_0 (Reg_data_0 ), + .Reg_next_0 (Reg_next_0 ), + .Reg_apply_1 (Reg_apply_1 ), + .Reg_addr_1 (Reg_addr_1 ), + .Reg_data_1 (Reg_data_1 ), + .Reg_next_1 (Reg_next_1 ), + //dual-port ram (//dual-port ram ), + .Addra (Addra ), + .Dina (Dina ), + .Douta (Douta ), + .Wea (Wea ), + //CPU (//CPU ), + .CPU_rd_addr (CPU_rd_addr ), + .CPU_rd_apply (CPU_rd_apply ), + .CPU_rd_grant (CPU_rd_grant ), + .CPU_rd_dout (CPU_rd_dout ) + ); + + RMON_dpram + U_Rx_RMON_dpram(.Reset (Reset ), + .Clk (Clk ), + //port-a for Rmon (//port-a for Rmon ), + .Addra (Addra ), + .Dina (Dina ), + .Douta ( ), + .Wea (Wea ), + //port-b for CPU (//port-b for CPU ), + .Addrb (Addra ), + .Doutb (Douta )); + +endmodule // RMON diff --git a/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Entries b/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Entries new file mode 100644 index 000000000..5df4f14a1 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Entries @@ -0,0 +1,4 @@ +/RMON_addr_gen.v/1.4/Sun Jun 25 04:58:57 2006// +/RMON_ctrl.v/1.4/Sun Jun 25 04:58:57 2006// +/RMON_dpram.v/1.2/Thu Jan 19 14:07:55 2006// +D diff --git a/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Repository b/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Repository new file mode 100644 index 000000000..788bf5c9c --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/rtl/verilog/RMON diff --git a/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Root b/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Template b/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/RMON/CVS/Template diff --git a/opencores/ethernet_tri_mode/rtl/verilog/RMON/RMON_addr_gen.v b/opencores/ethernet_tri_mode/rtl/verilog/RMON/RMON_addr_gen.v new file mode 100644 index 000000000..0a3b00cf9 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/RMON/RMON_addr_gen.v @@ -0,0 +1,295 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// RMON_addr_gen.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: RMON_addr_gen.v,v $ +// Revision 1.4 2006/06/25 04:58:57 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:55 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:19 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +module RMON_addr_gen( +Clk , +Reset , +//RMON +Pkt_type_rmon , +Pkt_length_rmon , +Apply_rmon ,//pluse signal looks like eop +Pkt_err_type_rmon , +// +Reg_apply , +Reg_addr , +Reg_data , +Reg_next , +//CPU +Reg_drop_apply +); +input Clk ; +input Reset ; + //RMON +input [2:0] Pkt_type_rmon ; +input [15:0] Pkt_length_rmon ; +input Apply_rmon ;//pluse signal looks like eop +input [2:0] Pkt_err_type_rmon ; + //RMON_ctrl +output Reg_apply ; +output [4:0] Reg_addr ; +output [15:0] Reg_data ; +input Reg_next ; + //CPU +output Reg_drop_apply ; + +//****************************************************************************** +//internal signals +//****************************************************************************** +parameter StateIdle =4'd0; +parameter StatePktLength =4'd1; +parameter StatePktNumber =4'd2; +parameter StatePktType =4'd3; +parameter StatePktRange =4'd4; + +reg [3:0] CurrentState /* synthesys syn_keep=1 */; +reg [3:0] NextState; + +reg [2:0] PktTypeReg ; +reg [15:0] PktLengthReg ; +reg [2:0] PktErrTypeReg ; + +reg Reg_apply ; +reg [4:0] Reg_addr ; +reg [15:0] Reg_data ; +reg Reg_drop_apply ; +//****************************************************************************** +//register boundery signals + +//****************************************************************************** +reg Apply_rmon_dl1; +reg Apply_rmon_dl2; +reg Apply_rmon_pulse; +reg [2:0] Pkt_type_rmon_dl1 ; +reg [15:0] Pkt_length_rmon_dl1 ; +reg [2:0] Pkt_err_type_rmon_dl1 ; + +always @(posedge Clk or posedge Reset) + if (Reset) + begin + Pkt_type_rmon_dl1 <=0; + Pkt_length_rmon_dl1 <=0; + Pkt_err_type_rmon_dl1 <=0; + end + else + begin + Pkt_type_rmon_dl1 <=Pkt_type_rmon ; + Pkt_length_rmon_dl1 <=Pkt_length_rmon ; + Pkt_err_type_rmon_dl1 <=Pkt_err_type_rmon ; + end + +always @(posedge Clk or posedge Reset) + if (Reset) + begin + Apply_rmon_dl1 <=0; + Apply_rmon_dl2 <=0; + end + else + begin + Apply_rmon_dl1 <=Apply_rmon; + Apply_rmon_dl2 <=Apply_rmon_dl1; + end + +always @(Apply_rmon_dl1 or Apply_rmon_dl2) + if (Apply_rmon_dl1&!Apply_rmon_dl2) + Apply_rmon_pulse =1; + else + Apply_rmon_pulse =0; + + + +always @(posedge Clk or posedge Reset) + if (Reset) + begin + PktTypeReg <=0; + PktLengthReg <=0; + PktErrTypeReg <=0; + end + else if (Apply_rmon_pulse&&CurrentState==StateIdle) + begin + PktTypeReg <=Pkt_type_rmon_dl1 ; + PktLengthReg <=Pkt_length_rmon_dl1 ; + PktErrTypeReg <=Pkt_err_type_rmon_dl1 ; + end + + +//****************************************************************************** +//State Machine +//****************************************************************************** +always @(posedge Clk or posedge Reset) + if (Reset) + CurrentState <=StateIdle; + else + CurrentState <=NextState; + +always @(CurrentState or Apply_rmon_pulse or Reg_next) + case (CurrentState) + StateIdle: + if (Apply_rmon_pulse) + NextState =StatePktLength; + else + NextState =StateIdle; + StatePktLength: + if (Reg_next) + NextState =StatePktNumber; + else + NextState =CurrentState; + StatePktNumber: + if (Reg_next) + NextState =StatePktType; + else + NextState =CurrentState; + StatePktType: + if (Reg_next) + NextState =StatePktRange; + else + NextState =CurrentState; + StatePktRange: + if (Reg_next) + NextState =StateIdle; + else + NextState =CurrentState; + default: + NextState =StateIdle; + endcase + +//****************************************************************************** +//gen output signals +//****************************************************************************** +//Reg_apply +always @ (CurrentState) + if (CurrentState==StatePktLength||CurrentState==StatePktNumber|| + CurrentState==StatePktType||CurrentState==StatePktRange) + Reg_apply =1; + else + Reg_apply =0; + +//Reg_addr +always @ (posedge Clk or posedge Reset) + if (Reset) + Reg_addr <=0; + else case (CurrentState) + StatePktLength: + Reg_addr <=5'd00; + StatePktNumber: + Reg_addr <=5'd01; + StatePktType: + case(PktTypeReg) + 3'b011: + Reg_addr <=5'd02; //broadcast + 3'b001: + Reg_addr <=5'd03; //multicast + 3'b100: + Reg_addr <=5'd16; //pause frame + default: + Reg_addr <=5'd04; //unicast + endcase + StatePktRange: + case(PktErrTypeReg) + 3'b001: + Reg_addr <=5'd05; + 3'b010: + Reg_addr <=5'd06; + 3'b011: + Reg_addr <=5'd07; + 3'b100: + if (PktLengthReg<64) + Reg_addr <=5'd08; + else if (PktLengthReg==64) + Reg_addr <=5'd09; + else if (PktLengthReg<128) + Reg_addr <=5'd10; + else if (PktLengthReg<256) + Reg_addr <=5'd11; + else if (PktLengthReg<512) + Reg_addr <=5'd12; + else if (PktLengthReg<1024) + Reg_addr <=5'd13; + else if (PktLengthReg<1519) + Reg_addr <=5'd14; + else + Reg_addr <=5'd15; + default: + Reg_addr <=5'd05; + endcase + default: + Reg_addr <=5'd05; + endcase + +//Reg_data +always @ (CurrentState or PktLengthReg) + case (CurrentState) + StatePktLength: + Reg_data =PktLengthReg; + StatePktNumber: + Reg_data =1; + StatePktType: + Reg_data =1; + StatePktRange: + Reg_data =1; + default: + Reg_data =0; + endcase + +//Reg_drop_apply +always @ (posedge Clk or posedge Reset) + if (Reset) + Reg_drop_apply <=0; + else if (CurrentState!=StateIdle&&Apply_rmon_pulse) + Reg_drop_apply <=1; + else + Reg_drop_apply <=0; + + +endmodule + diff --git a/opencores/ethernet_tri_mode/rtl/verilog/RMON/RMON_ctrl.v b/opencores/ethernet_tri_mode/rtl/verilog/RMON/RMON_ctrl.v new file mode 100644 index 000000000..02ecab3fd --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/RMON/RMON_ctrl.v @@ -0,0 +1,290 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// RMON_ctrl.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: RMON_ctrl.v,v $ +// Revision 1.4 2006/06/25 04:58:57 maverickist +// no message +// +// Revision 1.3 2006/01/19 14:07:55 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:19 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +module RMON_ctrl ( +Clk , +Reset , +//RMON_CTRL +Reg_apply_0 , +Reg_addr_0 , +Reg_data_0 , +Reg_next_0 , +Reg_apply_1 , +Reg_addr_1 , +Reg_data_1 , +Reg_next_1 , +//dual-port ram +Addra , +Dina , +Douta , +Wea , +//CPU +CPU_rd_addr , +CPU_rd_apply , +CPU_rd_grant , +CPU_rd_dout + +); +input Clk ; +input Reset ; + //RMON_CTRL +input Reg_apply_0 ; +input [4:0] Reg_addr_0 ; +input [15:0] Reg_data_0 ; +output Reg_next_0 ; +input Reg_apply_1 ; +input [4:0] Reg_addr_1 ; +input [15:0] Reg_data_1 ; +output Reg_next_1 ; + //dual-port ram + //port-a for Rmon +output [5:0] Addra ; +output [31:0] Dina ; +input [31:0] Douta ; +output Wea ; + //CPU +input [5:0] CPU_rd_addr ; +input CPU_rd_apply ; +output CPU_rd_grant ; +output [31:0] CPU_rd_dout ; + + + + +//****************************************************************************** +//internal signals +//****************************************************************************** + +parameter StateCPU =4'd00; +parameter StateMAC0 =4'd01; +parameter StateMAC1 =4'd02; + + +reg [3:0] CurrentState /* synthesys syn_keep=1 */; +reg [3:0] NextState; +reg [3:0] CurrentState_reg; + +reg [4:0] StepCounter; +reg [31:0] DoutaReg; +reg [5:0] Addra ; +reg [31:0] Dina; +reg Reg_next_0 ; +reg Reg_next_1 ; +reg Write; +reg Read; +reg Pipeline; +reg [31:0] CPU_rd_dout ; +reg CPU_rd_apply_reg ; +//****************************************************************************** +//State Machine +//****************************************************************************** + +always @(posedge Clk or posedge Reset) + if (Reset) + CurrentState <=StateMAC0; + else + CurrentState <=NextState; + +always @(posedge Clk or posedge Reset) + if (Reset) + CurrentState_reg <=StateMAC0; + else if(CurrentState!=StateCPU) + CurrentState_reg <=CurrentState; + +always @(CurrentState or CPU_rd_apply_reg or Reg_apply_0 or CurrentState_reg + or Reg_apply_1 + or StepCounter + ) + case(CurrentState) + StateMAC0: + if(!Reg_apply_0&&CPU_rd_apply_reg) + NextState =StateCPU; + else if(!Reg_apply_0) + NextState =StateMAC1; + else + NextState =CurrentState; + StateMAC1: + if(!Reg_apply_1&&CPU_rd_apply_reg) + NextState =StateCPU; + else if(!Reg_apply_1) + NextState =StateMAC0; + else + NextState =CurrentState; + StateCPU: + if (StepCounter==3) + case (CurrentState_reg) + StateMAC0 :NextState =StateMAC0 ; + StateMAC1 :NextState =StateMAC1 ; + default :NextState =StateMAC0; + endcase + else + NextState =CurrentState; + + default: + NextState =StateMAC0; + endcase + + + +always @(posedge Clk or posedge Reset) + if (Reset) + StepCounter <=0; + else if(NextState!=CurrentState) + StepCounter <=0; + else if (StepCounter!=4'hf) + StepCounter <=StepCounter + 1; + +//****************************************************************************** +//temp signals +//****************************************************************************** +always @(StepCounter) + if( StepCounter==1||StepCounter==4|| + StepCounter==7||StepCounter==10) + Read =1; + else + Read =0; + +always @(StepCounter or CurrentState) + if( StepCounter==2||StepCounter==5|| + StepCounter==8||StepCounter==11) + Pipeline =1; + else + Pipeline =0; + +always @(StepCounter or CurrentState) + if( StepCounter==3||StepCounter==6|| + StepCounter==9||StepCounter==12) + Write =1; + else + Write =0; + +always @(posedge Clk or posedge Reset) + if (Reset) + DoutaReg <=0; + else if (Read) + DoutaReg <=Douta; + + +//****************************************************************************** +//gen output signals +//****************************************************************************** +//Addra +always @(*) + case(CurrentState) + StateMAC0 : Addra={1'd0 ,Reg_addr_0 }; + StateMAC1 : Addra={1'd1 ,Reg_addr_1 }; + StateCPU: Addra=CPU_rd_addr; + default: Addra=0; + endcase + +//Dina +always @(posedge Clk or posedge Reset) + if (Reset) + Dina <=0; + else + case(CurrentState) + StateMAC0 : Dina<=Douta+Reg_data_0 ; + StateMAC1 : Dina<=Douta+Reg_data_1 ; + StateCPU: Dina<=0; + default: Dina<=0; + endcase + +assign Wea =Write; +//Reg_next +always @(CurrentState or Pipeline) + if(CurrentState==StateMAC0) + Reg_next_0 =Pipeline; + else + Reg_next_0 =0; + +always @(CurrentState or Pipeline) + if(CurrentState==StateMAC1) + Reg_next_1 =Pipeline; + else + Reg_next_1 =0; + + +//CPU_rd_grant +reg CPU_rd_apply_dl1; +reg CPU_rd_apply_dl2; +//rising edge +always @ (posedge Clk or posedge Reset) + if (Reset) + begin + CPU_rd_apply_dl1 <=0; + CPU_rd_apply_dl2 <=0; + end + else + begin + CPU_rd_apply_dl1 <=CPU_rd_apply; + CPU_rd_apply_dl2 <=CPU_rd_apply_dl1; + end + +always @ (posedge Clk or posedge Reset) + if (Reset) + CPU_rd_apply_reg <=0; + else if (CPU_rd_apply_dl1&!CPU_rd_apply_dl2) + CPU_rd_apply_reg <=1; + else if (CurrentState==StateCPU&&Write) + CPU_rd_apply_reg <=0; + +assign CPU_rd_grant =!CPU_rd_apply_reg; + +always @ (posedge Clk or posedge Reset) + if (Reset) + CPU_rd_dout <=0; + else if (Pipeline&&CurrentState==StateCPU) + CPU_rd_dout <=Douta; + +endmodule diff --git a/opencores/ethernet_tri_mode/rtl/verilog/RMON/RMON_dpram.v b/opencores/ethernet_tri_mode/rtl/verilog/RMON/RMON_dpram.v new file mode 100644 index 000000000..4b58512c3 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/RMON/RMON_dpram.v @@ -0,0 +1,46 @@ +module RMON_dpram + (Reset , + Clk , + //port-a for Rmon + Addra, + Dina, + Douta, + Wea, + //port-b for CPU + Addrb, + Doutb + ); + + input Reset ; + input Clk ; + //port-a for Rmon + input [5:0] Addra; + input [31:0] Dina; + output [31:0] Douta; + input Wea; + //port-b for CPU + input [5:0] Addrb; + output [31:0] Doutb; + // ****************************************************************************** + //internal signals + // ****************************************************************************** + + wire Clka; + wire Clkb; + assign Clka=Clk; + assign #2 Clkb=Clk; + // ****************************************************************************** + + duram #(32,6) + U_duram(.data_a (Dina ), + .data_b (32'b0 ), + .wren_a (Wea ), + .wren_b (1'b0 ), + .address_a (Addra ), + .address_b (Addrb ), + .clock_a (Clka ), + .clock_b (Clkb ), + .q_a (Douta ), + .q_b (Doutb )); + +endmodule // RMON_dpram diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/CLK_SWITCH.v b/opencores/ethernet_tri_mode/rtl/verilog/TECH/CLK_SWITCH.v new file mode 100644 index 000000000..d18d719f5 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/CLK_SWITCH.v @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// CLK_SWITCH.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CLK_SWITCH.v,v $ +// Revision 1.3 2006/01/19 14:07:56 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:20 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + + +////////////////////////////////////////////////////////////////////// +// This file can only used for simulation . +// You need to replace it with your own element according to technology +////////////////////////////////////////////////////////////////////// +module CLK_SWITCH ( +input IN_0, +input IN_1, +input SW , +output OUT + +); + +assign OUT=SW?IN_1:IN_0; + +endmodule
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Entries b/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Entries new file mode 100644 index 000000000..25cf148b0 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Entries @@ -0,0 +1,5 @@ +/CLK_SWITCH.v/1.3/Thu Jan 19 14:07:56 2006// +D/altera//// +D/xilinx//// +/duram.v/1.2/Wed May 2 02:54:45 2007// +/CLK_DIV2.v/1.3/Wed May 2 06:49:15 2007// diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Repository b/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Repository new file mode 100644 index 000000000..3c7177d25 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/rtl/verilog/TECH diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Root b/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Template b/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/CVS/Template diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CLK_DIV2.v b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CLK_DIV2.v new file mode 100644 index 000000000..ce94e2de7 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CLK_DIV2.v @@ -0,0 +1,74 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// CLK_DIV2.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CLK_DIV2.v,v $ +// Revision 1.1 2006/10/22 16:12:24 maverickist +// no message +// +// Revision 1.1 2006/06/22 09:01:41 Administrator +// no message +// +// Revision 1.2 2005/12/16 06:44:20 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + + +////////////////////////////////////////////////////////////////////// +// This file can only used for simulation . +// You need to replace it with your own element according to technology +////////////////////////////////////////////////////////////////////// + +module CLK_DIV2 ( +input Reset, +input IN, +output reg OUT +); + +always @ (posedge IN or posedge Reset) + if (Reset) + OUT <=0; + else + OUT <=!OUT; + +endmodule
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CLK_SWITCH.v b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CLK_SWITCH.v new file mode 100644 index 000000000..4e1a5d355 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CLK_SWITCH.v @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// CLK_SWITCH.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CLK_SWITCH.v,v $ +// Revision 1.1 2006/10/22 16:12:24 maverickist +// no message +// +// Revision 1.1 2006/06/22 09:01:41 Administrator +// no message +// +// Revision 1.2 2005/12/16 06:44:20 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + + +////////////////////////////////////////////////////////////////////// +// This file can only used for simulation . +// You need to replace it with your own element according to technology +////////////////////////////////////////////////////////////////////// +module CLK_SWITCH ( +input IN_0, +input IN_1, +input SW , +output OUT + +); + +assign OUT=SW?IN_1:IN_0; + +endmodule
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Entries b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Entries new file mode 100644 index 000000000..426ef42e1 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Entries @@ -0,0 +1,4 @@ +/CLK_DIV2.v/1.1/Sun Oct 22 16:12:24 2006// +/CLK_SWITCH.v/1.1/Sun Oct 22 16:12:24 2006// +/duram.v/1.1/Sun Oct 22 16:12:24 2006// +D diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Repository b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Repository new file mode 100644 index 000000000..25356ea54 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/rtl/verilog/TECH/altera diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Root b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Template b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/CVS/Template diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/duram.v b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/duram.v new file mode 100644 index 000000000..b653beddd --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/altera/duram.v @@ -0,0 +1,87 @@ +module duram( +data_a, +data_b, +wren_a, +wren_b, +address_a, +address_b, +clock_a, +clock_b, +q_a, +q_b); //synthesis syn_black_box + +parameter DATA_WIDTH = 32; +parameter ADDR_WIDTH = 5; +parameter BLK_RAM_TYPE = "AUTO"; +parameter DURAM_MODE = "BIDIR_DUAL_PORT"; +parameter ADDR_DEPTH = 2**ADDR_WIDTH; + + + +input [DATA_WIDTH -1:0] data_a; +input wren_a; +input [ADDR_WIDTH -1:0] address_a; +input clock_a; +output [DATA_WIDTH -1:0] q_a; +input [DATA_WIDTH -1:0] data_b; +input wren_b; +input [ADDR_WIDTH -1:0] address_b; +input clock_b; +output [DATA_WIDTH -1:0] q_b; + + + +altsyncram U_altsyncram ( +.wren_a (wren_a), +.wren_b (wren_b), +.data_a (data_a), +.data_b (data_b), +.address_a (address_a), +.address_b (address_b), +.clock0 (clock_a), +.clock1 (clock_b), +.q_a (q_a), +.q_b (q_b), +// synopsys translate_off +.aclr0 (), +.aclr1 (), +.addressstall_a (), +.addressstall_b (), +.byteena_a (), +.byteena_b (), +.clocken0 (), +.clocken1 (), +.rden_b () +// synopsys translate_on +); + defparam + U_altsyncram.intended_device_family = "Stratix", + U_altsyncram.ram_block_type = BLK_RAM_TYPE, + U_altsyncram.operation_mode = DURAM_MODE, + U_altsyncram.width_a = DATA_WIDTH, + U_altsyncram.widthad_a = ADDR_WIDTH, +// U_altsyncram.numwords_a = 256, + U_altsyncram.width_b = DATA_WIDTH, + U_altsyncram.widthad_b = ADDR_WIDTH, +// U_altsyncram.numwords_b = 256, + U_altsyncram.lpm_type = "altsyncram", + U_altsyncram.width_byteena_a = 1, + U_altsyncram.width_byteena_b = 1, + U_altsyncram.outdata_reg_a = "UNREGISTERED", + U_altsyncram.outdata_aclr_a = "NONE", + U_altsyncram.outdata_reg_b = "UNREGISTERED", + U_altsyncram.indata_aclr_a = "NONE", + U_altsyncram.wrcontrol_aclr_a = "NONE", + U_altsyncram.address_aclr_a = "NONE", + U_altsyncram.indata_reg_b = "CLOCK1", + U_altsyncram.address_reg_b = "CLOCK1", + U_altsyncram.wrcontrol_wraddress_reg_b = "CLOCK1", + U_altsyncram.indata_aclr_b = "NONE", + U_altsyncram.wrcontrol_aclr_b = "NONE", + U_altsyncram.address_aclr_b = "NONE", + U_altsyncram.outdata_aclr_b = "NONE", + U_altsyncram.power_up_uninitialized = "FALSE"; + +endmodule + + diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/clkdiv2.v b/opencores/ethernet_tri_mode/rtl/verilog/TECH/clkdiv2.v new file mode 100644 index 000000000..00b2712af --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/clkdiv2.v @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// CLK_DIV2.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CLK_DIV2.v,v $ +// Revision 1.3 2006/01/19 14:07:56 maverickist +// verification is complete. +// +// Revision 1.2 2005/12/16 06:44:20 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + + +////////////////////////////////////////////////////////////////////// +// This file can only used for simulation . +// You need to replace it with your own element according to technology +////////////////////////////////////////////////////////////////////// + +module clkdiv2 ( +input Reset, +input IN, +output reg OUT +); + +always @ (posedge IN or posedge Reset) + if (Reset) + OUT <=0; + else + OUT <=!OUT; + +endmodule diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/duram.v b/opencores/ethernet_tri_mode/rtl/verilog/TECH/duram.v new file mode 100644 index 000000000..f831932be --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/duram.v @@ -0,0 +1,103 @@ + + +module duram + (data_a, + data_b, + wren_a, + wren_b, + address_a, + address_b, + clock_a, + clock_b, + q_a, + q_b); + + parameter DATA_WIDTH = 32; + parameter ADDR_WIDTH = 5; + parameter ADDR_DEPTH = 1<<ADDR_WIDTH; + + input [DATA_WIDTH-1:0] data_a; + input wren_a; + input [ADDR_WIDTH-1:0] address_a; + input clock_a; + output reg [DATA_WIDTH-1:0] q_a; + + input [DATA_WIDTH-1:0] data_b; + input wren_b; + input [ADDR_WIDTH-1:0] address_b; + input clock_b; + output reg [DATA_WIDTH-1:0] q_b; + + reg [DATA_WIDTH-1:0] ram [0:ADDR_DEPTH-1]; + + always @(posedge clock_a) + begin + if(wren_a) + ram[address_a] <= data_a; + q_a <= ram[address_a]; + end + + always @(posedge clock_b) + begin + if(wren_b) + ram[address_b] <= data_b; + q_b <= ram[address_b]; + end + +endmodule // duram + +/* + altsyncram + U_altsyncram (.wren_a (wren_a), + .wren_b (wren_b), + .data_a (data_a), + .data_b (data_b), + .address_a (address_a), + .address_b (address_b), + .clock0 (clock_a), + .clock1 (clock_b), + .q_a (q_a), + .q_b (q_b), + // synopsys translate_off + .aclr0 (), + .aclr1 (), + .addressstall_a (), + .addressstall_b (), + .byteena_a (), + .byteena_b (), + .clocken0 (), + .clocken1 (), + .rden_b () + // synopsys translate_on + ); + + //parameter BLK_RAM_TYPE = "AUTO"; + //parameter DURAM_MODE = "BIDIR_DUAL_PORT"; + + defparam + U_altsyncram.intended_device_family = "Stratix", + U_altsyncram.ram_block_type = BLK_RAM_TYPE, + U_altsyncram.operation_mode = DURAM_MODE, + U_altsyncram.width_a = DATA_WIDTH, + U_altsyncram.widthad_a = ADDR_WIDTH, + U_altsyncram.width_b = DATA_WIDTH, + U_altsyncram.widthad_b = ADDR_WIDTH, + U_altsyncram.lpm_type = "altsyncram", + U_altsyncram.width_byteena_a = 1, + U_altsyncram.width_byteena_b = 1, + U_altsyncram.outdata_reg_a = "UNREGISTERED", + U_altsyncram.outdata_aclr_a = "NONE", + U_altsyncram.outdata_reg_b = "UNREGISTERED", + U_altsyncram.indata_aclr_a = "NONE", + U_altsyncram.wrcontrol_aclr_a = "NONE", + U_altsyncram.address_aclr_a = "NONE", + U_altsyncram.indata_reg_b = "CLOCK1", + U_altsyncram.address_reg_b = "CLOCK1", + U_altsyncram.wrcontrol_wraddress_reg_b = "CLOCK1", + U_altsyncram.indata_aclr_b = "NONE", + U_altsyncram.wrcontrol_aclr_b = "NONE", + U_altsyncram.address_aclr_b = "NONE", + U_altsyncram.outdata_aclr_b = "NONE", + U_altsyncram.power_up_uninitialized = "FALSE"; + + */ diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CLK_DIV2.v b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CLK_DIV2.v new file mode 100644 index 000000000..48efbd73e --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CLK_DIV2.v @@ -0,0 +1,74 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// CLK_DIV2.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CLK_DIV2.v,v $ +// Revision 1.1 2006/10/22 16:12:25 maverickist +// no message +// +// Revision 1.1 2006/06/22 09:01:42 Administrator +// no message +// +// Revision 1.2 2005/12/16 06:44:20 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + + +////////////////////////////////////////////////////////////////////// +// This file can only used for simulation . +// You need to replace it with your own element according to technology +////////////////////////////////////////////////////////////////////// + +module CLK_DIV2 ( +input Reset, +input IN, +output reg OUT +); + +always @ (posedge IN or posedge Reset) + if (Reset) + OUT <=0; + else + OUT <=!OUT; + +endmodule
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CLK_SWITCH.v b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CLK_SWITCH.v new file mode 100644 index 000000000..0399b9f80 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CLK_SWITCH.v @@ -0,0 +1,77 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// CLK_SWITCH.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode///// +//// //// +//// Author(s): //// +//// - Jon Gao (gaojon@yahoo.com) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: CLK_SWITCH.v,v $ +// Revision 1.1 2006/10/22 16:12:25 maverickist +// no message +// +// Revision 1.1 2006/06/22 09:01:42 Administrator +// no message +// +// Revision 1.2 2005/12/16 06:44:20 Administrator +// replaced tab with space. +// passed 9.6k length frame test. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// + + +////////////////////////////////////////////////////////////////////// +// This file can only used for simulation . +// You need to replace it with your own element according to technology +////////////////////////////////////////////////////////////////////// +module CLK_SWITCH ( +input IN_0, +input IN_1, +input SW , +output OUT + +); + +BUFGMUX U_BUFGMUX ( +.O (OUT ), +.I0 (IN_0 ), +.I1 (IN_1 ), +.S (SW )); + +//assign OUT=SW?IN_1:IN_0; + +endmodule
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Entries b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Entries new file mode 100644 index 000000000..0ffe83400 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Entries @@ -0,0 +1,4 @@ +/CLK_DIV2.v/1.1/Sun Oct 22 16:12:25 2006// +/CLK_SWITCH.v/1.1/Sun Oct 22 16:12:25 2006// +/duram.v/1.1/Sun Oct 22 16:12:25 2006// +D diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Repository b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Repository new file mode 100644 index 000000000..e74a686d0 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/rtl/verilog/TECH/xilinx diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Root b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Template b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/CVS/Template diff --git a/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/duram.v b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/duram.v new file mode 100644 index 000000000..f2577b600 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/TECH/xilinx/duram.v @@ -0,0 +1,60 @@ +module duram( +data_a, +data_b, +wren_a, +wren_b, +address_a, +address_b, +clock_a, +clock_b, +q_a, +q_b); + +parameter DATA_WIDTH = 36; +parameter ADDR_WIDTH = 9; +parameter BLK_RAM_TYPE = "AUTO"; +parameter ADDR_DEPTH = 2**ADDR_WIDTH; + + + +input [DATA_WIDTH -1:0] data_a; +input wren_a; +input [ADDR_WIDTH -1:0] address_a; +input clock_a; +output [DATA_WIDTH -1:0] q_a; +input [DATA_WIDTH -1:0] data_b; +input wren_b; +input [ADDR_WIDTH -1:0] address_b; +input clock_b; +output [DATA_WIDTH -1:0] q_b; + +wire [35:0] do_b; +wire [35:0] din_a; + +assign din_a =data_a; +assign q_b =do_b; + + +RAMB16_S36_S36 U_RAMB16_S36_S36 ( +.DOA ( ), +.DOB (do_b[31:0] ), +.DOPA ( ), +.DOPB (do_b[35:32] ), +.ADDRA (address_a ), +.ADDRB (address_b ), +.CLKA (clock_a ), +.CLKB (clock_b ), +.DIA (din_a[31:0] ), +.DIB ( ), +.DIPA (din_a[35:32] ), +.DIPB ( ), +.ENA (1'b1 ), +.ENB (1'b1 ), +.SSRA (1'b0 ), +.SSRB (1'b0 ), +.WEA (wren_a ), +.WEB (1'b0 )); + +endmodule + + diff --git a/opencores/ethernet_tri_mode/rtl/verilog/cmdfile b/opencores/ethernet_tri_mode/rtl/verilog/cmdfile new file mode 100644 index 000000000..a3bcd9d30 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/cmdfile @@ -0,0 +1,7 @@ +-y . +-y TECH +-y MAC_tx +-y MAC_rx +-y RMON +-y miim ++incdir+rtl/verilog diff --git a/opencores/ethernet_tri_mode/rtl/verilog/eth_miim.v b/opencores/ethernet_tri_mode/rtl/verilog/eth_miim.v new file mode 100644 index 000000000..fa1866c97 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/eth_miim.v @@ -0,0 +1,475 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_miim.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_miim.v,v $ +// Revision 1.3 2006/01/19 14:07:53 maverickist +// verification is complete. +// +// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator +// no message +// +// Revision 1.4 2005/08/16 12:07:57 Administrator +// no message +// +// Revision 1.3 2005/05/19 07:04:29 Administrator +// no message +// +// Revision 1.2 2005/04/27 15:58:46 Administrator +// no message +// +// Revision 1.1.1.1 2004/12/15 06:38:54 Administrator +// no message +// +// Revision 1.5 2003/05/16 10:08:27 mohor +// Busy was set 2 cycles too late. Reported by Dennis Scott. +// +// Revision 1.4 2002/08/14 18:32:10 mohor +// - Busy signal was not set on time when scan status operation was performed +// and clock was divided with more than 2. +// - Nvalid remains valid two more clocks (was previously cleared too soon). +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.2 2001/08/02 09:25:31 mohor +// Unconnected signals are now connected. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:56 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +`timescale 1ns/10ps + + +module eth_miim +( + Clk, + Reset, + Divider, + NoPre, + CtrlData, + Rgad, + Fiad, + WCtrlData, + RStat, + ScanStat, + Mdio, + Mdc, + Busy, + Prsd, + LinkFail, + Nvalid, + WCtrlDataStart, + RStatStart, + UpdateMIIRX_DATAReg +); + + + +input Clk; // Host Clock +input Reset; // General Reset +input [7:0] Divider; // Divider for the host clock +input [15:0] CtrlData; // Control Data (to be written to the PHY reg.) +input [4:0] Rgad; // Register Address (within the PHY) +input [4:0] Fiad; // PHY Address +input NoPre; // No Preamble (no 32-bit preamble) +input WCtrlData; // Write Control Data operation +input RStat; // Read Status operation +input ScanStat; // Scan Status operation +inout Mdio; // MII Management Data In + +output Mdc; // MII Management Data Clock + +output Busy; // Busy Signal +output LinkFail; // Link Integrity Signal +output Nvalid; // Invalid Status (qualifier for the valid scan result) + +output [15:0] Prsd; // Read Status Data (data read from the PHY) + +output WCtrlDataStart; // This signals resets the WCTRLDATA bit in the MIIM Command register +output RStatStart; // This signal resets the RSTAT BIT in the MIIM Command register +output UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data + +parameter Tp = 1; + + +reg Nvalid; +reg EndBusy_d; // Pre-end Busy signal +reg EndBusy; // End Busy signal (stops the operation in progress) + +reg WCtrlData_q1; // Write Control Data operation delayed 1 Clk cycle +reg WCtrlData_q2; // Write Control Data operation delayed 2 Clk cycles +reg WCtrlData_q3; // Write Control Data operation delayed 3 Clk cycles +reg WCtrlDataStart; // Start Write Control Data Command (positive edge detected) +reg WCtrlDataStart_q; +reg WCtrlDataStart_q1; // Start Write Control Data Command delayed 1 Mdc cycle +reg WCtrlDataStart_q2; // Start Write Control Data Command delayed 2 Mdc cycles + +reg RStat_q1; // Read Status operation delayed 1 Clk cycle +reg RStat_q2; // Read Status operation delayed 2 Clk cycles +reg RStat_q3; // Read Status operation delayed 3 Clk cycles +reg RStatStart; // Start Read Status Command (positive edge detected) +reg RStatStart_q1; // Start Read Status Command delayed 1 Mdc cycle +reg RStatStart_q2; // Start Read Status Command delayed 2 Mdc cycles + +reg ScanStat_q1; // Scan Status operation delayed 1 cycle +reg ScanStat_q2; // Scan Status operation delayed 2 cycles +reg SyncStatMdcEn; // Scan Status operation delayed at least cycles and synchronized to MdcEn + +wire WriteDataOp; // Write Data Operation (positive edge detected) +wire ReadStatusOp; // Read Status Operation (positive edge detected) +wire ScanStatusOp; // Scan Status Operation (positive edge detected) +wire StartOp; // Start Operation (start of any of the preceding operations) +wire EndOp; // End of Operation + +reg InProgress; // Operation in progress +reg InProgress_q1; // Operation in progress delayed 1 Mdc cycle +reg InProgress_q2; // Operation in progress delayed 2 Mdc cycles +reg InProgress_q3; // Operation in progress delayed 3 Mdc cycles + +reg WriteOp; // Write Operation Latch (When asserted, write operation is in progress) +reg [6:0] BitCounter; // Bit Counter + + +wire MdcFrame; // Frame window for limiting the Mdc +wire [3:0] ByteSelect; // Byte Select defines which byte (preamble, data, operation, etc.) is loaded and shifted through the shift register. +wire MdcEn; // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc rises. +wire ShiftedBit; // This bit is output of the shift register and is connected to the Mdo signal + + +wire LatchByte1_d2; +wire LatchByte0_d2; +reg LatchByte1_d; +reg LatchByte0_d; +reg [1:0] LatchByte; // Latch Byte selects which part of Read Status Data is updated from the shift register + +reg UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data + +wire Mdo; // MII Management Data Output +wire MdoEn; // MII Management Data Output Enable +wire Mdi; + +assign Mdi=Mdio; +assign Mdio=MdoEn?Mdo:1'bz; + + + +// Generation of the EndBusy signal. It is used for ending the MII Management operation. +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + EndBusy_d <= #Tp 1'b0; + EndBusy <= #Tp 1'b0; + end + else + begin + EndBusy_d <= #Tp ~InProgress_q2 & InProgress_q3; + EndBusy <= #Tp EndBusy_d; + end +end + + +// Update MII RX_DATA register +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + UpdateMIIRX_DATAReg <= #Tp 0; + else + if(EndBusy & ~WCtrlDataStart_q) + UpdateMIIRX_DATAReg <= #Tp 1; + else + UpdateMIIRX_DATAReg <= #Tp 0; +end + + + +// Generation of the delayed signals used for positive edge triggering. +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + WCtrlData_q1 <= #Tp 1'b0; + WCtrlData_q2 <= #Tp 1'b0; + WCtrlData_q3 <= #Tp 1'b0; + + RStat_q1 <= #Tp 1'b0; + RStat_q2 <= #Tp 1'b0; + RStat_q3 <= #Tp 1'b0; + + ScanStat_q1 <= #Tp 1'b0; + ScanStat_q2 <= #Tp 1'b0; + SyncStatMdcEn <= #Tp 1'b0; + end + else + begin + WCtrlData_q1 <= #Tp WCtrlData; + WCtrlData_q2 <= #Tp WCtrlData_q1; + WCtrlData_q3 <= #Tp WCtrlData_q2; + + RStat_q1 <= #Tp RStat; + RStat_q2 <= #Tp RStat_q1; + RStat_q3 <= #Tp RStat_q2; + + ScanStat_q1 <= #Tp ScanStat; + ScanStat_q2 <= #Tp ScanStat_q1; + if(MdcEn) + SyncStatMdcEn <= #Tp ScanStat_q2; + end +end + + +// Generation of the Start Commands (Write Control Data or Read Status) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + WCtrlDataStart <= #Tp 1'b0; + WCtrlDataStart_q <= #Tp 1'b0; + RStatStart <= #Tp 1'b0; + end + else + begin + if(EndBusy) + begin + WCtrlDataStart <= #Tp 1'b0; + RStatStart <= #Tp 1'b0; + end + else + begin + if(WCtrlData_q2 & ~WCtrlData_q3) + WCtrlDataStart <= #Tp 1'b1; + if(RStat_q2 & ~RStat_q3) + RStatStart <= #Tp 1'b1; + WCtrlDataStart_q <= #Tp WCtrlDataStart; + end + end +end + + +// Generation of the Nvalid signal (indicates when the status is invalid) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + Nvalid <= #Tp 1'b0; + else + begin + if(~InProgress_q2 & InProgress_q3) + begin + Nvalid <= #Tp 1'b0; + end + else + begin + if(ScanStat_q2 & ~SyncStatMdcEn) + Nvalid <= #Tp 1'b1; + end + end +end + +// Signals used for the generation of the Operation signals (positive edge) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + WCtrlDataStart_q1 <= #Tp 1'b0; + WCtrlDataStart_q2 <= #Tp 1'b0; + + RStatStart_q1 <= #Tp 1'b0; + RStatStart_q2 <= #Tp 1'b0; + + InProgress_q1 <= #Tp 1'b0; + InProgress_q2 <= #Tp 1'b0; + InProgress_q3 <= #Tp 1'b0; + + LatchByte0_d <= #Tp 1'b0; + LatchByte1_d <= #Tp 1'b0; + + LatchByte <= #Tp 2'b00; + end + else + begin + if(MdcEn) + begin + WCtrlDataStart_q1 <= #Tp WCtrlDataStart; + WCtrlDataStart_q2 <= #Tp WCtrlDataStart_q1; + + RStatStart_q1 <= #Tp RStatStart; + RStatStart_q2 <= #Tp RStatStart_q1; + + LatchByte[0] <= #Tp LatchByte0_d; + LatchByte[1] <= #Tp LatchByte1_d; + + LatchByte0_d <= #Tp LatchByte0_d2; + LatchByte1_d <= #Tp LatchByte1_d2; + + InProgress_q1 <= #Tp InProgress; + InProgress_q2 <= #Tp InProgress_q1; + InProgress_q3 <= #Tp InProgress_q2; + end + end +end + + +// Generation of the Operation signals +assign WriteDataOp = WCtrlDataStart_q1 & ~WCtrlDataStart_q2; +assign ReadStatusOp = RStatStart_q1 & ~RStatStart_q2; +assign ScanStatusOp = SyncStatMdcEn & ~InProgress & ~InProgress_q1 & ~InProgress_q2; +assign StartOp = WriteDataOp | ReadStatusOp | ScanStatusOp; + +// Busy +reg Busy; +always @ (posedge Clk or posedge Reset) + if (Reset) + Busy <=0; + else if(WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid) + Busy <=1; + else + Busy <=0; + +//assign Busy = WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid; + + +// Generation of the InProgress signal (indicates when an operation is in progress) +// Generation of the WriteOp signal (indicates when a write is in progress) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + InProgress <= #Tp 1'b0; + WriteOp <= #Tp 1'b0; + end + else + begin + if(MdcEn) + begin + if(StartOp) + begin + if(~InProgress) + WriteOp <= #Tp WriteDataOp; + InProgress <= #Tp 1'b1; + end + else + begin + if(EndOp) + begin + InProgress <= #Tp 1'b0; + WriteOp <= #Tp 1'b0; + end + end + end + end +end + + + +// Bit Counter counts from 0 to 63 (from 32 to 63 when NoPre is asserted) +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + BitCounter[6:0] <= #Tp 7'h0; + else + begin + if(MdcEn) + begin + if(InProgress) + begin + if(NoPre & ( BitCounter == 7'h0 )) + BitCounter[6:0] <= #Tp 7'h21; + else + BitCounter[6:0] <= #Tp BitCounter[6:0] + 1'b1; + end + else + BitCounter[6:0] <= #Tp 7'h0; + end + end +end + + +// Operation ends when the Bit Counter reaches 63 +assign EndOp = BitCounter==63; + +assign ByteSelect[0] = InProgress & ((NoPre & (BitCounter == 7'h0)) | (~NoPre & (BitCounter == 7'h20))); +assign ByteSelect[1] = InProgress & (BitCounter == 7'h28); +assign ByteSelect[2] = InProgress & WriteOp & (BitCounter == 7'h30); +assign ByteSelect[3] = InProgress & WriteOp & (BitCounter == 7'h38); + + +// Latch Byte selects which part of Read Status Data is updated from the shift register +assign LatchByte1_d2 = InProgress & ~WriteOp & BitCounter == 7'h37; +assign LatchByte0_d2 = InProgress & ~WriteOp & BitCounter == 7'h3F; + + +// Connecting the Clock Generator Module +eth_clockgen clkgen(.Clk(Clk), .Reset(Reset), .Divider(Divider[7:0]), .MdcEn(MdcEn), .MdcEn_n(MdcEn_n), .Mdc(Mdc) + ); + +// Connecting the Shift Register Module +eth_shiftreg shftrg(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .Mdi(Mdi), .Fiad(Fiad), .Rgad(Rgad), + .CtrlData(CtrlData), .WriteOp(WriteOp), .ByteSelect(ByteSelect), .LatchByte(LatchByte), + .ShiftedBit(ShiftedBit), .Prsd(Prsd), .LinkFail(LinkFail) + ); + +// Connecting the Output Control Module +eth_outputcontrol outctrl(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .InProgress(InProgress), + .ShiftedBit(ShiftedBit), .BitCounter(BitCounter), .WriteOp(WriteOp), .NoPre(NoPre), + .Mdo(Mdo), .MdoEn(MdoEn) + ); + +endmodule diff --git a/opencores/ethernet_tri_mode/rtl/verilog/eth_wrapper.v b/opencores/ethernet_tri_mode/rtl/verilog/eth_wrapper.v new file mode 100644 index 000000000..2e4985d98 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/eth_wrapper.v @@ -0,0 +1,103 @@ +module eth_wrapper + (//system signals + input Reset , + input Clk_125M , + input Clk_user , + input Clk_reg , + output [2:0] Speed , + //Phy interface + output Gtx_clk ,//used only in GMII mode + input Rx_clk , + input Tx_clk ,//used only in MII mode + output Tx_er , + output Tx_en , + output [7:0] Txd , + input Rx_er , + input Rx_dv , + input [7:0] Rxd , + input Crs , + input Col , + //mdx + inout Mdio ,// MII Management Data In + output Mdc , // MII Management Data Clock + + // Our interfaces to outside + // Write FIFO Interface + output [31:0] wr_dat_o, + output wr_write_o, + output wr_done_o, + input wr_ready_i, + input wr_full_i, + + // Read FIFO Interface + input [31:0] rd_dat_i, + output rd_read_o, + output rd_done_o, + input rd_ready_i, + input rd_empty_i, + + // Wishbone + input [31:0] wb_dat_i, + output [31:0] wb_dat_o, + input [15:0] wb_adr_i, + input wb_stb_i, + input wb_we_i, + output wb_ack_o + ); + + MAC_top MAC_top + (//system signals + .Reset (Reset), + .Clk_125M (Clk_125M), + .Clk_user (Clk_user), + .Clk_reg (Clk_reg), + .Speed (Speed), // 2:0 + + // RX interface + .Rx_mac_ra (), + .Rx_mac_rd (), + .Rx_mac_data (), + .Rx_mac_BE (), + .Rx_mac_pa (), + .Rx_mac_sop (), + .Rx_mac_eop (), + + //TX interface + .Tx_mac_wa (), + .Tx_mac_wr (), + .Tx_mac_data (), + .Tx_mac_BE (),//big endian + .Tx_mac_sop (), + .Tx_mac_eop (), + + //Phy interface + .Gtx_clk (Gtx_clk),//used only in GMII mode + .Rx_clk (Rx_clk), + .Tx_clk (Tx_clk),//used only in MII mode + .Tx_er (Tx_er), + .Tx_en (Tx_en), + .Txd (Txd), + .Rx_er (Rx_er), + .Rx_dv (Rx_dv), + .Rxd (Rxd), + .Crs (Crs), + .Col (Col), + + //host interface + .CSB (wb_stb_i), + .WRB (wb_we_i & wb_stb_i), + .CD_in (wb_dat_i[15:0]), + .CD_out (wb_dat_o[15:0]), + .CA (wb_adr_i[8:1]), + + //mdx + .Mdio (Mdio),// MII Management Data In + .Mdc (Mdc) // MII Management Data Clock + + ); + + assign wb_dat_o[31:16] = wb_dat_o[15:0]; + assign wb_ack_o = wb_stb_i; + +endmodule // eth_wrapper + diff --git a/opencores/ethernet_tri_mode/rtl/verilog/header.v b/opencores/ethernet_tri_mode/rtl/verilog/header.v new file mode 100644 index 000000000..2fb225294 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/header.v @@ -0,0 +1,5 @@ + `define MAC_SOURCE_REPLACE_EN 1 + `define MAC_TARGET_CHECK_EN 1 + `define MAC_BROADCAST_FILTER_EN 1 +`define MAC_TX_FF_DEPTH 9 +`define MAC_RX_FF_DEPTH 9 diff --git a/opencores/ethernet_tri_mode/rtl/verilog/mac_tb.v b/opencores/ethernet_tri_mode/rtl/verilog/mac_tb.v new file mode 100644 index 000000000..d10508801 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/mac_tb.v @@ -0,0 +1,55 @@ +module mac_tb(); + +MAC_top MAC_top + (//system signals + .Reset (), + .Clk_125M (), + .Clk_user (), + .Clk_reg (), + .Speed (), // 2:0 + + // RX interface + .Rx_mac_ra (), + .Rx_mac_rd (), + .Rx_mac_data (), + .Rx_mac_BE (), + .Rx_mac_pa (), + .Rx_mac_sop (), + .Rx_mac_eop (), + + //TX interface + .Tx_mac_wa (), + .Tx_mac_wr (), + .Tx_mac_data (), + .Tx_mac_BE (),//big endian + .Tx_mac_sop (), + .Tx_mac_eop (), + + //Phy interface + .Gtx_clk (),//used only in GMII mode + .Rx_clk (), + .Tx_clk (),//used only in MII mode + .Tx_er (), + .Tx_en (), + .Txd (), + .Rx_er (), + .Rx_dv (), + .Rxd (), + .Crs (), + .Col (), + + //host interface + .CSB (), + .WRB (), + .CD_in (), + .CD_out (), + .CA (), + + //mdx + .Mdio (),// MII Management Data In + .Mdc () // MII Management Data Clock + + ); + + +endmodule // mac_tb diff --git a/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Entries b/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Entries new file mode 100644 index 000000000..6f451480f --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Entries @@ -0,0 +1,5 @@ +/eth_clockgen.v/1.2/Tue Dec 13 12:54:49 2005// +/eth_outputcontrol.v/1.2/Tue Dec 13 12:54:49 2005// +/eth_shiftreg.v/1.2/Tue Dec 13 12:54:49 2005// +/timescale.v/1.2/Tue Dec 13 12:54:49 2005// +D diff --git a/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Repository b/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Repository new file mode 100644 index 000000000..5935f07f9 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/rtl/verilog/miim diff --git a/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Root b/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Template b/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/miim/CVS/Template diff --git a/opencores/ethernet_tri_mode/rtl/verilog/miim/eth_clockgen.v b/opencores/ethernet_tri_mode/rtl/verilog/miim/eth_clockgen.v new file mode 100644 index 000000000..37399f5d6 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/miim/eth_clockgen.v @@ -0,0 +1,142 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_clockgen.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_clockgen.v,v $ +// Revision 1.2 2005/12/13 12:54:49 maverickist +// first simulation passed +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +// Revision 1.2 2005/04/27 15:58:45 Administrator +// no message +// +// Revision 1.1.1.1 2004/12/15 06:38:54 Administrator +// no message +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:55 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +module eth_clockgen(Clk, Reset, Divider, MdcEn, MdcEn_n, Mdc); + + parameter Tp=1; + + input Clk; // Input clock (Host clock) + input Reset; // Reset signal + input [7:0] Divider; // Divider (input clock will be divided by the Divider[7:0]) + + output Mdc; // Output clock + output MdcEn; // Enable signal is asserted for one Clk period before Mdc rises. + output MdcEn_n; // Enable signal is asserted for one Clk period before Mdc falls. + + reg Mdc; + reg [7:0] Counter; + + wire CountEq0; + wire [7:0] CounterPreset; + wire [7:0] TempDivider; + + + assign TempDivider[7:0] = (Divider[7:0]<2)? 8'h02 : Divider[7:0]; // If smaller than 2 + assign CounterPreset[7:0] = (TempDivider[7:0]>>1) -1; // We are counting half of period + + + // Counter counts half period + always @ (posedge Clk or posedge Reset) + begin + if(Reset) + Counter[7:0] <= #Tp 8'h1; + else + begin + if(CountEq0) + begin + Counter[7:0] <= #Tp CounterPreset[7:0]; + end + else + Counter[7:0] <= #Tp Counter - 8'h1; + end + end + + + // Mdc is asserted every other half period + always @ (posedge Clk or posedge Reset) + begin + if(Reset) + Mdc <= #Tp 1'b0; + else + begin + if(CountEq0) + Mdc <= #Tp ~Mdc; + end + end + + + assign CountEq0 = Counter == 8'h0; + assign MdcEn = CountEq0 & ~Mdc; + assign MdcEn_n = CountEq0 & Mdc; + +endmodule // eth_clockgen + + + diff --git a/opencores/ethernet_tri_mode/rtl/verilog/miim/eth_outputcontrol.v b/opencores/ethernet_tri_mode/rtl/verilog/miim/eth_outputcontrol.v new file mode 100644 index 000000000..9c45b088e --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/miim/eth_outputcontrol.v @@ -0,0 +1,162 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_outputcontrol.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_outputcontrol.v,v $ +// Revision 1.2 2005/12/13 12:54:49 maverickist +// first simulation passed +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +// Revision 1.2 2005/04/27 15:58:46 Administrator +// no message +// +// Revision 1.1.1.1 2004/12/15 06:38:54 Administrator +// no message +// +// Revision 1.4 2002/07/09 20:11:59 mohor +// Comment removed. +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:56 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +`timescale 1ns/10ps + +module eth_outputcontrol(Clk, Reset, InProgress, ShiftedBit, BitCounter, WriteOp, NoPre, MdcEn_n, Mdo, MdoEn); + +parameter Tp = 1; + +input Clk; // Host Clock +input Reset; // General Reset +input WriteOp; // Write Operation Latch (When asserted, write operation is in progress) +input NoPre; // No Preamble (no 32-bit preamble) +input InProgress; // Operation in progress +input ShiftedBit; // This bit is output of the shift register and is connected to the Mdo signal +input [6:0] BitCounter; // Bit Counter +input MdcEn_n; // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc falls. + +output Mdo; // MII Management Data Output +output MdoEn; // MII Management Data Output Enable + +wire SerialEn; + +reg MdoEn_2d; +reg MdoEn_d; +reg MdoEn; + +reg Mdo_2d; +reg Mdo_d; +reg Mdo; // MII Management Data Output + + + +// Generation of the Serial Enable signal (enables the serialization of the data) +assign SerialEn = WriteOp & InProgress & ( BitCounter>31 | ( ( BitCounter == 0 ) & NoPre ) ) + | ~WriteOp & InProgress & (( BitCounter>31 & BitCounter<46 ) | ( ( BitCounter == 0 ) & NoPre )); + + +// Generation of the MdoEn signal +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + MdoEn_2d <= #Tp 1'b0; + MdoEn_d <= #Tp 1'b0; + MdoEn <= #Tp 1'b0; + end + else + begin + if(MdcEn_n) + begin + MdoEn_2d <= #Tp SerialEn | InProgress & BitCounter<32; + MdoEn_d <= #Tp MdoEn_2d; + MdoEn <= #Tp MdoEn_d; + end + end +end + + +// Generation of the Mdo signal. +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + Mdo_2d <= #Tp 1'b0; + Mdo_d <= #Tp 1'b0; + Mdo <= #Tp 1'b0; + end + else + begin + if(MdcEn_n) + begin + Mdo_2d <= #Tp ~SerialEn & BitCounter<32; + Mdo_d <= #Tp ShiftedBit | Mdo_2d; + Mdo <= #Tp Mdo_d; + end + end +end + + + +endmodule diff --git a/opencores/ethernet_tri_mode/rtl/verilog/miim/eth_shiftreg.v b/opencores/ethernet_tri_mode/rtl/verilog/miim/eth_shiftreg.v new file mode 100644 index 000000000..a11ead1d0 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/miim/eth_shiftreg.v @@ -0,0 +1,164 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// eth_shiftreg.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: eth_shiftreg.v,v $ +// Revision 1.2 2005/12/13 12:54:49 maverickist +// first simulation passed +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +// Revision 1.2 2005/04/27 15:58:47 Administrator +// no message +// +// Revision 1.1.1.1 2004/12/15 06:38:54 Administrator +// no message +// +// Revision 1.5 2002/08/14 18:16:59 mohor +// LinkFail signal was not latching appropriate bit. +// +// Revision 1.4 2002/03/02 21:06:01 mohor +// LinkFail signal was not latching appropriate bit. +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 08:43:51 mohor +// eth_timescale.v changed to timescale.v This is done because of the +// simulation of the few cores in a one joined project. +// +// Revision 1.1 2001/08/06 14:44:29 mohor +// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex). +// Include files fixed to contain no path. +// File names and module names changed ta have a eth_ prologue in the name. +// File eth_timescale.v is used to define timescale +// All pin names on the top module are changed to contain _I, _O or _OE at the end. +// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O +// and Mdo_OE. The bidirectional signal must be created on the top level. This +// is done due to the ASIC tools. +// +// Revision 1.1 2001/07/30 21:23:42 mohor +// Directory structure changed. Files checked and joind together. +// +// Revision 1.3 2001/06/01 22:28:56 mohor +// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated. +// +// + +`timescale 1ns/10ps + + +module eth_shiftreg(Clk, Reset, MdcEn_n, Mdi, Fiad, Rgad, CtrlData, WriteOp, ByteSelect, + LatchByte, ShiftedBit, Prsd, LinkFail); + + +parameter Tp=1; + +input Clk; // Input clock (Host clock) +input Reset; // Reset signal +input MdcEn_n; // Enable signal is asserted for one Clk period before Mdc falls. +input Mdi; // MII input data +input [4:0] Fiad; // PHY address +input [4:0] Rgad; // Register address (within the selected PHY) +input [15:0]CtrlData; // Control data (data to be written to the PHY) +input WriteOp; // The current operation is a PHY register write operation +input [3:0] ByteSelect; // Byte select +input [1:0] LatchByte; // Byte select for latching (read operation) + +output ShiftedBit; // Bit shifted out of the shift register +output[15:0]Prsd; // Read Status Data (data read from the PHY) +output LinkFail; // Link Integrity Signal + +reg [7:0] ShiftReg; // Shift register for shifting the data in and out +reg [15:0]Prsd; +reg LinkFail; + + + + +// ShiftReg[7:0] :: Shift Register Data +always @ (posedge Clk or posedge Reset) +begin + if(Reset) + begin + ShiftReg[7:0] <= #Tp 8'h0; + Prsd[15:0] <= #Tp 16'h0; + LinkFail <= #Tp 1'b0; + end + else + begin + if(MdcEn_n) + begin + if(|ByteSelect) + begin + case (ByteSelect[3:0]) + 4'h1 : ShiftReg[7:0] <= #Tp {2'b01, ~WriteOp, WriteOp, Fiad[4:1]}; + 4'h2 : ShiftReg[7:0] <= #Tp {Fiad[0], Rgad[4:0], 2'b10}; + 4'h4 : ShiftReg[7:0] <= #Tp CtrlData[15:8]; + 4'h8 : ShiftReg[7:0] <= #Tp CtrlData[7:0]; + default : ShiftReg[7:0] <= #Tp 8'h0; + endcase + end + else + begin + ShiftReg[7:0] <= #Tp {ShiftReg[6:0], Mdi}; + if(LatchByte[0]) + begin + Prsd[7:0] <= #Tp {ShiftReg[6:0], Mdi}; + if(Rgad == 5'h01) + LinkFail <= #Tp ~ShiftReg[1]; // this is bit [2], because it is not shifted yet + end + else + begin + if(LatchByte[1]) + Prsd[15:8] <= #Tp {ShiftReg[6:0], Mdi}; + end + end + end + end +end + + +assign ShiftedBit = ShiftReg[7]; + + +endmodule diff --git a/opencores/ethernet_tri_mode/rtl/verilog/miim/timescale.v b/opencores/ethernet_tri_mode/rtl/verilog/miim/timescale.v new file mode 100644 index 000000000..4517d8970 --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/miim/timescale.v @@ -0,0 +1,62 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// timescale.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/projects/ethmac/ //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: timescale.v,v $ +// Revision 1.2 2005/12/13 12:54:49 maverickist +// first simulation passed +// +// Revision 1.1.1.1 2005/12/13 01:51:45 Administrator +// no message +// +// Revision 1.1.1.1 2004/12/15 06:38:54 Administrator +// no message +// +// Revision 1.3 2002/01/23 10:28:16 mohor +// Link in the header changed. +// +// Revision 1.2 2001/10/19 11:36:31 mohor +// Log file added. +// +// +// + +`timescale 1ns / 1ns diff --git a/opencores/ethernet_tri_mode/rtl/verilog/reg_int.v b/opencores/ethernet_tri_mode/rtl/verilog/reg_int.v new file mode 100644 index 000000000..cbb67a98a --- /dev/null +++ b/opencores/ethernet_tri_mode/rtl/verilog/reg_int.v @@ -0,0 +1,179 @@ +module reg_int ( +input Reset , +input Clk_reg , +input CSB , +input WRB , +input [15:0] CD_in , +output reg [15:0] CD_out , +input [7:0] CA , + //Tx host interface +output [4:0] Tx_Hwmark , +output [4:0] Tx_Lwmark , +output pause_frame_send_en , +output [15:0] pause_quanta_set , +output MAC_tx_add_en , +output FullDuplex , +output [3:0] MaxRetry , +output [5:0] IFGset , +output [7:0] MAC_tx_add_prom_data , +output [2:0] MAC_tx_add_prom_add , +output MAC_tx_add_prom_wr , +output tx_pause_en , +output xoff_cpu , +output xon_cpu , + //Rx host interface +output MAC_rx_add_chk_en , +output [7:0] MAC_rx_add_prom_data , +output [2:0] MAC_rx_add_prom_add , +output MAC_rx_add_prom_wr , +output broadcast_filter_en , +output [15:0] broadcast_bucket_depth , +output [15:0] broadcast_bucket_interval , +output RX_APPEND_CRC , +output [4:0] Rx_Hwmark , +output [4:0] Rx_Lwmark , +output CRC_chk_en , +output [5:0] RX_IFG_SET , +output [15:0] RX_MAX_LENGTH ,// 1518 +output [6:0] RX_MIN_LENGTH ,// 64 + //RMON host interface +output [5:0] CPU_rd_addr , +output CPU_rd_apply , +input CPU_rd_grant , +input [31:0] CPU_rd_dout , + //Phy int host interface +output Line_loop_en , +output [2:0] Speed , + //MII to CPU +output [7:0] Divider ,// Divider for the host clock +output [15:0] CtrlData ,// Control Data (to be written to the PHY reg.) +output [4:0] Rgad ,// Register Address (within the PHY) +output [4:0] Fiad ,// PHY Address +output NoPre ,// No Preamble (no 32-bit preamble) +output WCtrlData ,// Write Control Data operation +output RStat ,// Read Status operation +output ScanStat ,// Scan Status operation +input Busy ,// Busy Signal +input LinkFail ,// Link Integrity Signal +input Nvalid ,// Invalid Status (qualifier for the valid scan result) +input [15:0] Prsd ,// Read Status Data (data read from the PHY) +input WCtrlDataStart ,// This signals resets the WCTRLDATA bit in the MIIM Command register +input RStatStart ,// This signal resets the RSTAT BIT in the MIIM Command register +input UpdateMIIRX_DATAReg // Updates MII RX_DATA register with read data +); + + RegCPUData U_0_000(Tx_Hwmark ,7'd000,16'h0009,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_001(Tx_Lwmark ,7'd001,16'h0008,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_002(pause_frame_send_en ,7'd002,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_003(pause_quanta_set ,7'd003,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_004(IFGset ,7'd004,16'h000c,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_005(FullDuplex ,7'd005,16'h0001,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_006(MaxRetry ,7'd006,16'h0002,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_007(MAC_tx_add_en ,7'd007,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_008(MAC_tx_add_prom_data ,7'd008,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_009(MAC_tx_add_prom_add ,7'd009,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_010(MAC_tx_add_prom_wr ,7'd010,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_011(tx_pause_en ,7'd011,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_012(xoff_cpu ,7'd012,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_013(xon_cpu ,7'd013,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_014(MAC_rx_add_chk_en ,7'd014,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_015(MAC_rx_add_prom_data ,7'd015,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_016(MAC_rx_add_prom_add ,7'd016,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_017(MAC_rx_add_prom_wr ,7'd017,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_018(broadcast_filter_en ,7'd018,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_019(broadcast_bucket_depth ,7'd019,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_020(broadcast_bucket_interval,7'd020,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_021(RX_APPEND_CRC ,7'd021,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_022(Rx_Hwmark ,7'd022,16'h001a,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_023(Rx_Lwmark ,7'd023,16'h0010,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_024(CRC_chk_en ,7'd024,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_025(RX_IFG_SET ,7'd025,16'h000c,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_026(RX_MAX_LENGTH ,7'd026,16'h2710,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_027(RX_MIN_LENGTH ,7'd027,16'h0040,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_028(CPU_rd_addr ,7'd028,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_029(CPU_rd_apply ,7'd029,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); +// RegCPUData U_0_030(CPU_rd_grant ,7'd030,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); +// RegCPUData U_0_031(CPU_rd_dout_l ,7'd031,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); +// RegCPUData U_0_032(CPU_rd_dout_h ,7'd032,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_033(Line_loop_en ,7'd033,16'h0000,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + RegCPUData U_0_034(Speed ,7'd034,16'h0004,Reset,Clk_reg,!WRB,CSB,CA,CD_in); + +always @ (posedge Clk_reg or posedge Reset) + if (Reset) + CD_out <=0; + else if (!CSB&&WRB) + case (CA[7:1]) + 7'd00: CD_out<=Tx_Hwmark ; + 7'd01: CD_out<=Tx_Lwmark ; + 7'd02: CD_out<=pause_frame_send_en ; + 7'd03: CD_out<=pause_quanta_set ; + 7'd04: CD_out<=IFGset ; + 7'd05: CD_out<=FullDuplex ; + 7'd06: CD_out<=MaxRetry ; + 7'd07: CD_out<=MAC_tx_add_en ; + 7'd08: CD_out<=MAC_tx_add_prom_data ; + 7'd09: CD_out<=MAC_tx_add_prom_add ; + 7'd10: CD_out<=MAC_tx_add_prom_wr ; + 7'd11: CD_out<=tx_pause_en ; + 7'd12: CD_out<=xoff_cpu ; + 7'd13: CD_out<=xon_cpu ; + 7'd14: CD_out<=MAC_rx_add_chk_en ; + 7'd15: CD_out<=MAC_rx_add_prom_data ; + 7'd16: CD_out<=MAC_rx_add_prom_add ; + 7'd17: CD_out<=MAC_rx_add_prom_wr ; + 7'd18: CD_out<=broadcast_filter_en ; + 7'd19: CD_out<=broadcast_bucket_depth ; + 7'd20: CD_out<=broadcast_bucket_interval ; + 7'd21: CD_out<=RX_APPEND_CRC ; + 7'd22: CD_out<=Rx_Hwmark ; + 7'd23: CD_out<=Rx_Lwmark ; + 7'd24: CD_out<=CRC_chk_en ; + 7'd25: CD_out<=RX_IFG_SET ; + 7'd26: CD_out<=RX_MAX_LENGTH ; + 7'd27: CD_out<=RX_MIN_LENGTH ; + 7'd28: CD_out<=CPU_rd_addr ; + 7'd29: CD_out<=CPU_rd_apply ; + 7'd30: CD_out<=CPU_rd_grant ; + 7'd31: CD_out<=CPU_rd_dout[15:0] ; + 7'd32: CD_out<=CPU_rd_dout[31:16] ; + 7'd33: CD_out<=Line_loop_en ; + 7'd34: CD_out<=Speed ; + default: CD_out<=0 ; + endcase + else + CD_out<=0 ; + +endmodule + +module RegCPUData( +RegOut, +CA_reg_set, +RegInit, + +Reset, +Clk, +CWR_pulse, +CCSB, +CA_reg, +CD_in_reg +); +output[15:0] RegOut; +input[6:0] CA_reg_set; +input[15:0] RegInit; +// +input Reset; +input Clk; +input CWR_pulse; +input CCSB; +input[7:0] CA_reg; +input[15:0] CD_in_reg; +// +reg[15:0] RegOut; + +always @(posedge Reset or posedge Clk) + if(Reset) + RegOut <=RegInit; + else if (CWR_pulse && !CCSB && CA_reg[7:1] ==CA_reg_set[6:0]) + RegOut <=CD_in_reg; + +endmodule diff --git a/opencores/ethernet_tri_mode/sim/CVS/Entries b/opencores/ethernet_tri_mode/sim/CVS/Entries new file mode 100644 index 000000000..9487498ad --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/CVS/Entries @@ -0,0 +1 @@ +D/rtl_sim//// diff --git a/opencores/ethernet_tri_mode/sim/CVS/Repository b/opencores/ethernet_tri_mode/sim/CVS/Repository new file mode 100644 index 000000000..cd76b9556 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/sim diff --git a/opencores/ethernet_tri_mode/sim/CVS/Root b/opencores/ethernet_tri_mode/sim/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/sim/CVS/Template b/opencores/ethernet_tri_mode/sim/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/CVS/Template diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Entries b/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Entries new file mode 100644 index 000000000..110ed0af2 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Entries @@ -0,0 +1 @@ +D/ncsim_sim//// diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Repository b/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Repository new file mode 100644 index 000000000..930bcb3d9 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/sim/rtl_sim diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Root b/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Template b/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/CVS/Template diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Entries b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Entries new file mode 100644 index 000000000..08bef4ec9 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Entries @@ -0,0 +1,6 @@ +D/bin//// +D/data//// +D/log//// +D/out//// +D/run//// +D/script//// diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Repository b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Repository new file mode 100644 index 000000000..06f0c5682 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/sim/rtl_sim/ncsim_sim diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Root b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Template b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/CVS/Template diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Entries b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Entries new file mode 100644 index 000000000..75c10e887 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Entries @@ -0,0 +1,12 @@ +/cds.lib/1.2/Thu Jan 19 14:07:56 2006// +/com.nc/1.2/Fri Jan 20 12:18:05 2006// +/config.ini/1.1/Tue Dec 13 12:54:51 2005// +/hdl.var/1.1/Tue Dec 13 12:54:51 2005// +/ip_32W_check.dll/1.1/Thu Jan 19 14:07:56 2006/-kb/ +/ip_32W_check_vpi.dll/1.1/Tue Dec 13 12:54:51 2005/-kb/ +/ip_32W_gen.dll/1.1/Thu Jan 19 14:07:56 2006/-kb/ +/ip_32W_gen_vpi.dll/1.1/Tue Dec 13 12:54:51 2005/-kb/ +/sim.nc/1.3/Fri Jan 20 12:18:05 2006// +/sim_only.nc/1.1/Thu Jan 19 14:07:56 2006// +/vlog.list/1.2/Thu Jan 19 14:07:56 2006// +D diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Repository b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Repository new file mode 100644 index 000000000..f3861d090 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Root b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Template b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/CVS/Template diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/cds.lib b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/cds.lib new file mode 100644 index 000000000..c8b8c7c85 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/cds.lib @@ -0,0 +1,2 @@ +DEFINE work ./worknc + diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/com.nc b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/com.nc new file mode 100644 index 000000000..566452b80 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/com.nc @@ -0,0 +1,36 @@ +if test -d worknc +then +echo worknc is ready +else +mkdir worknc +echo worknc is created +fi + +ncvlog -f vlog.list -logfile ../log/ncvlog.log + +if test $? -ne 0 +then +echo compiling err occured... +exit 1 +fi + +ncelab work.tb_top -NEVERWARN -loadvpi ip_32W_gen:PLI_register -loadvpi ip_32W_check:PLI_register -snapshot work:snap -timescale 1ns/1ps -message -access +rw -logfile ../log/ncelab.log + +if test $? -ne 0 +then +echo ncelab err occured... +exit 1 +fi + +if test -f ../log/.sim_failed +then + echo "../log/.sim_failed log file has been removed!" + rm ../log/.sim_failed +fi + +if test -f ../log/sim_succeed +then + echo "../log/sim_succeed log file has been removed!" + rm ../log/sim_succeed +fi + diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/config.ini b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/config.ini new file mode 100644 index 000000000..cbcc5a0d8 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/config.ini @@ -0,0 +1,3 @@ +46,1500,1,0 + +#Pkt_begin_length,Pkt_end_length,Pkt_number,Random_en diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/hdl.var b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/hdl.var new file mode 100644 index 000000000..1899fceae --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/hdl.var @@ -0,0 +1 @@ +DEFINE WORK work diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_check.dll b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_check.dll Binary files differnew file mode 100644 index 000000000..675f2fed2 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_check.dll diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_check_vpi.dll b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_check_vpi.dll Binary files differnew file mode 100644 index 000000000..1b905b7e4 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_check_vpi.dll diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_gen.dll b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_gen.dll Binary files differnew file mode 100644 index 000000000..9afbaed18 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_gen.dll diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_gen_vpi.dll b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_gen_vpi.dll Binary files differnew file mode 100644 index 000000000..04d3b84a8 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/ip_32W_gen_vpi.dll diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/sim.nc b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/sim.nc new file mode 100644 index 000000000..6d38346af --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/sim.nc @@ -0,0 +1,37 @@ +if test -d worknc +then +echo worknc is ready +else +mkdir worknc +echo worknc is created +fi + +ncvlog -f vlog.list -logfile ../log/ncvlog.log + +if test $? -ne 0 +then +echo compiling err occured... +exit 1 +fi + +ncelab work.tb_top -NEVERWARN -loadvpi ip_32W_gen:PLI_register -loadvpi ip_32W_check:PLI_register -snapshot work:snap -timescale 1ns/1ps -message -access +rw -logfile ../log/ncelab.log + +if test $? -ne 0 +then +echo ncelab err occured... +exit 1 +fi + +if test -f ../log/.sim_failed +then + echo "../log/.sim_failed log file has been removed!" + rm ../log/.sim_failed +fi + +if test -f ../log/sim_succeed +then + echo "../log/sim_succeed log file has been removed!" + rm ../log/sim_succeed +fi + +ncsim work:snap $1 -UNBUFFERED -logfile ../log/ncsim.log -NOKEY diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/sim_only.nc b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/sim_only.nc new file mode 100644 index 000000000..feae8e7d8 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/sim_only.nc @@ -0,0 +1,13 @@ +if test -f ../log/.sim_failed +then + echo "../log/.sim_failed log file has been removed!" + rm ../log/.sim_failed +fi + +if test -f ../log/sim_succeed +then + echo "../log/sim_succeed log file has been removed!" + rm ../log/sim_succeed +fi + +ncsim work:snap $1 -UNBUFFERED -logfile ../log/ncsim.log -NOKEY diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/vlog.list b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/vlog.list new file mode 100644 index 000000000..a937c8438 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/bin/vlog.list @@ -0,0 +1,41 @@ +../../../../rtl/verilog/header.v + +../../../../rtl/verilog/TECH/CLK_SWITCH.v +../../../../rtl/verilog/TECH/CLK_DIV2.v +../../../../rtl/verilog/TECH/duram.v + +../../../../rtl/verilog/MAC_tx/MAC_tx_FF.v +../../../../rtl/verilog/MAC_tx/Ramdon_gen.v +../../../../rtl/verilog/MAC_tx/CRC_gen.v +../../../../rtl/verilog/MAC_tx/MAC_tx_addr_add.v +../../../../rtl/verilog/MAC_tx/MAC_tx_Ctrl.v +../../../../rtl/verilog/MAC_tx/flow_ctrl.v + +../../../../rtl/verilog/MAC_rx/CRC_chk.v +../../../../rtl/verilog/MAC_rx/MAC_rx_add_chk.v +../../../../rtl/verilog/MAC_rx/MAC_rx_FF.v +../../../../rtl/verilog/MAC_rx/MAC_rx_ctrl.v +../../../../rtl/verilog/MAC_rx/Broadcast_filter.v + +../../../../rtl/verilog/miim/eth_clockgen.v +../../../../rtl/verilog/miim/eth_outputcontrol.v +../../../../rtl/verilog/miim/eth_shiftreg.v + +../../../../rtl/verilog/RMON/RMON_addr_gen.v +../../../../rtl/verilog/RMON/RMON_ctrl.v +../../../../rtl/verilog/RMON/RMON_dpram.v + +../../../../rtl/verilog/RMON.v +../../../../rtl/verilog/MAC_rx.v +../../../../rtl/verilog/MAC_tx.v +../../../../rtl/verilog/eth_miim.v +../../../../rtl/verilog/MAC_top.v +../../../../rtl/verilog/Phy_int.v +../../../../rtl/verilog/Clk_ctrl.v +../../../../rtl/verilog/Reg_int.v + +../../../../bench/verilog/altera_mf.v +../../../../bench/verilog/Phy_sim.v +../../../../bench/verilog/User_int_sim.v +../../../../bench/verilog/host_sim.v +../../../../bench/verilog/tb_top.v diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/1000Mbps_duplex.vec b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/1000Mbps_duplex.vec new file mode 100644 index 000000000..364183597 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/1000Mbps_duplex.vec @@ -0,0 +1 @@ +01200004 diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/100Mbps_duplex.vec b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/100Mbps_duplex.vec new file mode 100644 index 000000000..b4f602f88 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/100Mbps_duplex.vec @@ -0,0 +1 @@ +01200002 diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/10Mbps_duplex.vec b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/10Mbps_duplex.vec new file mode 100644 index 000000000..a3b941871 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/10Mbps_duplex.vec @@ -0,0 +1 @@ +01200001 diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/46-50.ini b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/46-50.ini new file mode 100644 index 000000000..313b49c77 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/46-50.ini @@ -0,0 +1 @@ +46,50,1,0 diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CPU.vec b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CPU.vec new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CPU.vec diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Entries b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Entries new file mode 100644 index 000000000..0df4c0792 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Entries @@ -0,0 +1,11 @@ +/1000Mbps_duplex.vec/1.1/Thu Jan 19 14:07:57 2006// +/100Mbps_duplex.vec/1.1/Thu Jan 19 14:07:57 2006// +/10Mbps_duplex.vec/1.1/Thu Jan 19 14:07:57 2006// +/46-50.ini/1.1/Thu Jan 19 14:07:57 2006// +/CPU.vec/1.1/Thu Jan 19 14:07:57 2006// +/batch.dat/1.1/Thu Jan 19 14:07:57 2006// +/config.ini/1.2/Sun Jun 25 04:58:57 2006// +/flow_ctrl.vec/1.1/Thu Jan 19 14:07:57 2006// +/source_mac_replace.vec/1.1/Thu Jan 19 14:07:57 2006// +/target_mac_check.vec/1.1/Thu Jan 19 14:07:57 2006// +D diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Repository b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Repository new file mode 100644 index 000000000..cc9effe3f --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Root b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Template b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/CVS/Template diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/batch.dat b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/batch.dat new file mode 100644 index 000000000..a37f5040a --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/batch.dat @@ -0,0 +1,3 @@ +{1000Mbps mode 46-80 length packet testcase} 46-50.ini 1000Mbps_duplex.vec +{100 Mbps mode 46-50 length packet testcase} 46-50.ini 100Mbps_duplex.vec +{10 Mbps mode 46-50 length packet testcase} 46-50.ini 10Mbps_duplex.vec diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/config.ini b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/config.ini new file mode 100644 index 000000000..cd64f1692 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/config.ini @@ -0,0 +1 @@ +46,1500,1,0,0 diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/flow_ctrl.vec b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/flow_ctrl.vec new file mode 100644 index 000000000..978689ab0 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/flow_ctrl.vec @@ -0,0 +1,4 @@ +04020001 +0403000a +040b000a +040c0001 diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/source_mac_replace.vec b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/source_mac_replace.vec new file mode 100644 index 000000000..f1f498941 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/source_mac_replace.vec @@ -0,0 +1,24 @@ +12070001 +12080030 +120a0001 +180a0000 +18080031 +18090001 +180a0001 +180a0000 +18080032 +18090002 +180a0001 +180a0000 +18080033 +18090003 +180a0001 +180a0000 +18080034 +18090004 +180a0001 +180a0000 +18080035 +18090005 +180a0001 +180a0000 diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/target_mac_check.vec b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/target_mac_check.vec new file mode 100644 index 000000000..71401b15c --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/data/target_mac_check.vec @@ -0,0 +1,25 @@ +190e0001 +190f0010 +19100000 +19110001 +19110000 +190f0011 +19100001 +19110001 +19110000 +190f0012 +19100002 +19110001 +19110000 +190f0013 +19100003 +19110001 +19110000 +190f0014 +19100004 +19110001 +19110000 +190f0016 +19100005 +19110001 +19110000
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Entries b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Entries new file mode 100644 index 000000000..85b414b74 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Entries @@ -0,0 +1,2 @@ +/ncsim.log/1.3/Fri Nov 17 17:53:07 2006// +D diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Repository b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Repository new file mode 100644 index 000000000..060990863 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Root b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Template b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/CVS/Template diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/ncsim.log b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/ncsim.log new file mode 100644 index 000000000..c2ede5380 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/log/ncsim.log @@ -0,0 +1,245 @@ +ncsim: 05.00-p001: (c) Copyright 1995-2003 Cadence Design Systems, Inc. +////////////////////////////////////////////////////////////////////// +//// +//// $ip_32W_gen is used to generate stimulus with 32bit +//// width ip packet data flow. +//// The only parameter is config.ini file that is used to +//// control the generated packet data flow. +//// +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +//// StartOfSim callback printing info +////////////////////////////////////////////////////////////////////// +ncsim> run + +the NO. 0001 IP Length is:0046 CRC-32check OK! +the NO. 0002 IP Length is:0047 CRC-32check OK! +the NO. 0003 IP Length is:0048 CRC-32check OK! +the NO. 0004 IP Length is:0049 CRC-32check OK! +the NO. 0005 IP Length is:0050 CRC-32check OK! +the NO. 0006 IP Length is:0051 CRC-32check OK! +the NO. 0007 IP Length is:0052 CRC-32check OK! +the NO. 0008 IP Length is:0053 CRC-32check OK! +the NO. 0009 IP Length is:0054 CRC-32check OK! +the NO. 000a IP Length is:0055 CRC-32check OK! +the NO. 000b IP Length is:0056 CRC-32check OK! +the NO. 000c IP Length is:0057 CRC-32check OK! +the NO. 000d IP Length is:0058 CRC-32check OK! +the NO. 000e IP Length is:0059 CRC-32check OK! +the NO. 000f IP Length is:0060 CRC-32check OK! +the NO. 0010 IP Length is:0061 CRC-32check OK! +the NO. 0011 IP Length is:0062 CRC-32check OK! +the NO. 0012 IP Length is:0063 CRC-32check OK! +the NO. 0013 IP Length is:0064 CRC-32check OK! +the NO. 0014 IP Length is:0065 CRC-32check OK! +the NO. 0015 IP Length is:0066 CRC-32check OK! +the NO. 0016 IP Length is:0067 CRC-32check OK! +the NO. 0017 IP Length is:0068 CRC-32check OK! +the NO. 0018 IP Length is:0069 CRC-32check OK! +the NO. 0019 IP Length is:0070 CRC-32check OK! +the NO. 001a IP Length is:0071 CRC-32check OK! +the NO. 001b IP Length is:0072 CRC-32check OK! +the NO. 001c IP Length is:0073 CRC-32check OK! +the NO. 001d IP Length is:0074 CRC-32check OK! +the NO. 001e IP Length is:0075 CRC-32check OK! +the NO. 001f IP Length is:0076 CRC-32check OK! +the NO. 0020 IP Length is:0077 CRC-32check OK! +the NO. 0021 IP Length is:0078 CRC-32check OK! +the NO. 0022 IP Length is:0079 CRC-32check OK! +the NO. 0023 IP Length is:0080 CRC-32check OK! +the NO. 0024 IP Length is:0081 CRC-32check OK! +the NO. 0025 IP Length is:0082 CRC-32check OK! +the NO. 0026 IP Length is:0083 CRC-32check OK! +the NO. 0027 IP Length is:0084 CRC-32check OK! +the NO. 0028 IP Length is:0085 CRC-32check OK! +the NO. 0029 IP Length is:0086 CRC-32check OK! +the NO. 002a IP Length is:0087 CRC-32check OK! +the NO. 002b IP Length is:0088 CRC-32check OK! +the NO. 002c IP Length is:0089 CRC-32check OK! +the NO. 002d IP Length is:0090 CRC-32check OK! +the NO. 002e IP Length is:0091 CRC-32check OK! +the NO. 002f IP Length is:0092 CRC-32check OK! +the NO. 0030 IP Length is:0093 CRC-32check OK! +the NO. 0031 IP Length is:0094 CRC-32check OK! +the NO. 0032 IP Length is:0095 CRC-32check OK! +the NO. 0033 IP Length is:0096 CRC-32check OK! +the NO. 0034 IP Length is:0097 CRC-32check OK! +the NO. 0035 IP Length is:0098 CRC-32check OK! +the NO. 0036 IP Length is:0099 CRC-32check OK! +the NO. 0037 IP Length is:0100 CRC-32check OK! +the NO. 0038 IP Length is:0101 CRC-32check OK! +the NO. 0039 IP Length is:0102 CRC-32check OK! +the NO. 003a IP Length is:0103 CRC-32check OK! +the NO. 003b IP Length is:0104 CRC-32check OK! +the NO. 003c IP Length is:0105 CRC-32check OK! +the NO. 003d IP Length is:0106 CRC-32check OK! +the NO. 003e IP Length is:0107 CRC-32check OK! +the NO. 003f IP Length is:0108 CRC-32check OK! +the NO. 0040 IP Length is:0109 CRC-32check OK! +the NO. 0041 IP Length is:0110 CRC-32check OK! +the NO. 0042 IP Length is:0111 CRC-32check OK! +the NO. 0043 IP Length is:0112 CRC-32check OK! +the NO. 0044 IP Length is:0113 CRC-32check OK! +the NO. 0045 IP Length is:0114 CRC-32check OK! +the NO. 0046 IP Length is:0115 CRC-32check OK! +the NO. 0047 IP Length is:0116 CRC-32check OK! +the NO. 0048 IP Length is:0117 CRC-32check OK! +the NO. 0049 IP Length is:0118 CRC-32check OK! +the NO. 004a IP Length is:0119 CRC-32check OK! +the NO. 004b IP Length is:0120 CRC-32check OK! +the NO. 004c IP Length is:0121 CRC-32check OK! +the NO. 004d IP Length is:0122 CRC-32check OK! +the NO. 004e IP Length is:0123 CRC-32check OK! +the NO. 004f IP Length is:0124 CRC-32check OK! +the NO. 0050 IP Length is:0125 CRC-32check OK! +the NO. 0051 IP Length is:0126 CRC-32check OK! +the NO. 0052 IP Length is:0127 CRC-32check OK! +the NO. 0053 IP Length is:0128 CRC-32check OK! +the NO. 0054 IP Length is:0129 CRC-32check OK! +the NO. 0055 IP Length is:0130 CRC-32check OK! +the NO. 0056 IP Length is:0131 CRC-32check OK! +the NO. 0057 IP Length is:0132 CRC-32check OK! +the NO. 0058 IP Length is:0133 CRC-32check OK! +the NO. 0059 IP Length is:0134 CRC-32check OK! +the NO. 005a IP Length is:0135 CRC-32check OK! +the NO. 005b IP Length is:0136 CRC-32check OK! +the NO. 005c IP Length is:0137 CRC-32check OK! +the NO. 005d IP Length is:0138 CRC-32check OK! +the NO. 005e IP Length is:0139 CRC-32check OK! +the NO. 005f IP Length is:0140 CRC-32check OK! +the NO. 0060 IP Length is:0141 CRC-32check OK! +the NO. 0061 IP Length is:0142 CRC-32check OK! +the NO. 0062 IP Length is:0143 CRC-32check OK! +the NO. 0063 IP Length is:0144 CRC-32check OK! +the NO. 0064 IP Length is:0145 CRC-32check OK! +the NO. 0065 IP Length is:0146 CRC-32check OK! +the NO. 0066 IP Length is:0147 CRC-32check OK! +the NO. 0067 IP Length is:0148 CRC-32check OK! +the NO. 0068 IP Length is:0149 CRC-32check OK! +the NO. 0069 IP Length is:0150 CRC-32check OK! +the NO. 006a IP Length is:0151 CRC-32check OK! +the NO. 006b IP Length is:0152 CRC-32check OK! +the NO. 006c IP Length is:0153 CRC-32check OK! +the NO. 006d IP Length is:0154 CRC-32check OK! +the NO. 006e IP Length is:0155 CRC-32check OK! +the NO. 006f IP Length is:0156 CRC-32check OK! +the NO. 0070 IP Length is:0157 CRC-32check OK! +the NO. 0071 IP Length is:0158 CRC-32check OK! +the NO. 0072 IP Length is:0159 CRC-32check OK! +the NO. 0073 IP Length is:0160 CRC-32check OK! +the NO. 0074 IP Length is:0161 CRC-32check OK! +the NO. 0075 IP Length is:0162 CRC-32check OK! +the NO. 0076 IP Length is:0163 CRC-32check OK! +the NO. 0077 IP Length is:0164 CRC-32check OK! +the NO. 0078 IP Length is:0165 CRC-32check OK! +the NO. 0079 IP Length is:0166 CRC-32check OK! +the NO. 007a IP Length is:0167 CRC-32check OK! +the NO. 007b IP Length is:0168 CRC-32check OK! +the NO. 007c IP Length is:0169 CRC-32check OK! +the NO. 007d IP Length is:0170 CRC-32check OK! +the NO. 007e IP Length is:0171 CRC-32check OK! +the NO. 007f IP Length is:0172 CRC-32check OK! +the NO. 0080 IP Length is:0173 CRC-32check OK! +the NO. 0081 IP Length is:0174 CRC-32check OK! +the NO. 0082 IP Length is:0175 CRC-32check OK! +the NO. 0083 IP Length is:0176 CRC-32check OK! +the NO. 0084 IP Length is:0177 CRC-32check OK! +the NO. 0085 IP Length is:0178 CRC-32check OK! +the NO. 0086 IP Length is:0179 CRC-32check OK! +the NO. 0087 IP Length is:0180 CRC-32check OK! +the NO. 0088 IP Length is:0181 CRC-32check OK! +the NO. 0089 IP Length is:0182 CRC-32check OK! +the NO. 008a IP Length is:0183 CRC-32check OK! +the NO. 008b IP Length is:0184 CRC-32check OK! +the NO. 008c IP Length is:0185 CRC-32check OK! +the NO. 008d IP Length is:0186 CRC-32check OK! +the NO. 008e IP Length is:0187 CRC-32check OK! +the NO. 008f IP Length is:0188 CRC-32check OK! +the NO. 0090 IP Length is:0189 CRC-32check OK! +the NO. 0091 IP Length is:0190 CRC-32check OK! +the NO. 0092 IP Length is:0191 CRC-32check OK! +the NO. 0093 IP Length is:0192 CRC-32check OK! +the NO. 0094 IP Length is:0193 CRC-32check OK! +the NO. 0095 IP Length is:0194 CRC-32check OK! +the NO. 0096 IP Length is:0195 CRC-32check OK! +the NO. 0097 IP Length is:0196 CRC-32check OK! +the NO. 0098 IP Length is:0197 CRC-32check OK! +the NO. 0099 IP Length is:0198 CRC-32check OK! +the NO. 009a IP Length is:0199 CRC-32check OK! +the NO. 009b IP Length is:0200 CRC-32check OK! +the NO. 009c IP Length is:0201 CRC-32check OK! +the NO. 009d IP Length is:0202 CRC-32check OK! +the NO. 009e IP Length is:0203 CRC-32check OK! +the NO. 009f IP Length is:0204 CRC-32check OK! +the NO. 00a0 IP Length is:0205 CRC-32check OK! +the NO. 00a1 IP Length is:0206 CRC-32check OK! +the NO. 00a2 IP Length is:0207 CRC-32check OK! +the NO. 00a3 IP Length is:0208 CRC-32check OK! +the NO. 00a4 IP Length is:0209 CRC-32check OK! +the NO. 00a5 IP Length is:0210 CRC-32check OK! +the NO. 00a6 IP Length is:0211 CRC-32check OK! +the NO. 00a7 IP Length is:0212 CRC-32check OK! +the NO. 00a8 IP Length is:0213 CRC-32check OK! +the NO. 00a9 IP Length is:0214 CRC-32check OK! +the NO. 00aa IP Length is:0215 CRC-32check OK! +the NO. 00ab IP Length is:0216 CRC-32check OK! +the NO. 00ac IP Length is:0217 CRC-32check OK! +the NO. 00ad IP Length is:0218 CRC-32check OK! +the NO. 00ae IP Length is:0219 CRC-32check OK! +the NO. 00af IP Length is:0220 CRC-32check OK! +the NO. 00b0 IP Length is:0221 CRC-32check OK! +the NO. 00b1 IP Length is:0222 CRC-32check OK! +the NO. 00b2 IP Length is:0223 CRC-32check OK! +the NO. 00b3 IP Length is:0224 CRC-32check OK! +the NO. 00b4 IP Length is:0225 CRC-32check OK! +the NO. 00b5 IP Length is:0226 CRC-32check OK! +the NO. 00b6 IP Length is:0227 CRC-32check OK! +the NO. 00b7 IP Length is:0228 CRC-32check OK! +the NO. 00b8 IP Length is:0229 CRC-32check OK! +the NO. 00b9 IP Length is:0230 CRC-32check OK! +the NO. 00ba IP Length is:0231 CRC-32check OK! +the NO. 00bb IP Length is:0232 CRC-32check OK! +the NO. 00bc IP Length is:0233 CRC-32check OK! +the NO. 00bd IP Length is:0234 CRC-32check OK! +the NO. 00be IP Length is:0235 CRC-32check OK! +the NO. 00bf IP Length is:0236 CRC-32check OK! +the NO. 00c0 IP Length is:0237 CRC-32check OK! +the NO. 00c1 IP Length is:0238 CRC-32check OK! +the NO. 00c2 IP Length is:0239 CRC-32check OK! +the NO. 00c3 IP Length is:0240 CRC-32check OK! +the NO. 00c4 IP Length is:0241 CRC-32check OK! +the NO. 00c5 IP Length is:0242 CRC-32check OK! +the NO. 00c6 IP Length is:0243 CRC-32check OK! +the NO. 00c7 IP Length is:0244 CRC-32check OK! +the NO. 00c8 IP Length is:0245 CRC-32check OK! +the NO. 00c9 IP Length is:0246 CRC-32check OK! +the NO. 00ca IP Length is:0247 CRC-32check OK! +the NO. 00cb IP Length is:0248 CRC-32check OK! +the NO. 00cc IP Length is:0249 CRC-32check OK! +the NO. 00cd IP Length is:0250 CRC-32check OK! +the NO. 00ce IP Length is:0251 CRC-32check OK! +the NO. 00cf IP Length is:0252 CRC-32check OK! +the NO. 00d0 IP Length is:0253 CRC-32check OK! +the NO. 00d1 IP Length is:0254 CRC-32check OK! +the NO. 00d2 IP Length is:0255 CRC-32check OK! +the NO. 00d3 IP Length is:0256 CRC-32check OK! +the NO. 00d4 IP Length is:0257 CRC-32check OK! +the NO. 00d5 IP Length is:0258 CRC-32check OK! +the NO. 00d6 IP Length is:0259 CRC-32check OK! +the NO. 00d7 IP Length is:0260 CRC-32check OK! +the NO. 00d8 IP Length is:0261 CRC-32check OK! +the NO. 00d9 IP Length is:0262 CRC-32check OK! +the NO. 00da IP Length is:0263 CRC-32check OK! +the NO. 00db IP Length is:0264 CRC-32check OK! +the NO. 00dc IP Length is:0265 CRC-32check OK! +the NO. 00dd IP Length is:0266 CRC-32check OK! +the NO. 00de IP Length is:0267 CRC-32check OK! +the NO. 00df IP Length is:0268 CRC-32check OK! +the NO. 00e0 IP Length is:0269 CRC-32check OK! +the NO. 00e1 IP Length is:0270 CRC-32check OK! +the NO. 00e2 IP Length is:0271 CRC-32check OK! +the NO. 00e3 IP Length is:0272 CRC-32check OK! +the NO. 00e4 IP Length is:0273 CRC-32check OK! +the NO. 00e5 IP Length is:0274 CRC-32check OK! +the NO. 00e6 IP Length is:0275 CRC-32check OK!Simulation interrupted at 367372 NS + 0 +ncsim> exit diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Entries b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Entries new file mode 100644 index 000000000..178481050 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Entries @@ -0,0 +1 @@ +D diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Repository b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Repository new file mode 100644 index 000000000..46dd9edc2 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Root b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Template b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/out/CVS/Template diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Entries b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Entries new file mode 100644 index 000000000..178481050 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Entries @@ -0,0 +1 @@ +D diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Repository b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Repository new file mode 100644 index 000000000..90f699204 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Root b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Template b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/run/CVS/Template diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Entries b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Entries new file mode 100644 index 000000000..4ca22003b --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Entries @@ -0,0 +1,9 @@ +/batch_mode.tcl/1.2/Thu Apr 6 13:12:05 2006// +/filesel.tcl/1.1/Thu Jan 19 16:18:28 2006// +/run.tcl/1.1/Thu Jan 19 16:18:28 2006// +/run_proc.tcl/1.2/Thu Apr 6 13:12:05 2006// +/set_reg_data.tcl/1.3/Thu Apr 6 13:12:05 2006// +/set_stimulus.tcl/1.2/Thu Apr 6 13:12:05 2006// +/start_verify.tcl/1.2/Thu Apr 6 13:12:05 2006// +/user_lib.tcl/1.2/Thu Apr 6 13:12:05 2006// +D diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Repository b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Repository new file mode 100644 index 000000000..7e86a1503 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Root b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Template b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/CVS/Template diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/batch_mode.tcl b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/batch_mode.tcl new file mode 100644 index 000000000..9185aded4 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/batch_mode.tcl @@ -0,0 +1,148 @@ +proc batch_mode {} { +variable i +variable index empty +variable batch_data +set namelist \ +{- Description Stimulus RegVector} +############################################################################### + toplevel .b + wm title .b "Setting Reg Data" + focus .b + frame .b.f100 + + set lth1 20 + set lth2 15 + set lth3 15 + cd ../data + if {[catch {open batch.dat r} fileid]} { + break + } else { + set batch_data {} + gets $fileid line + while {[eof $fileid]==0} { + lappend batch_data $line + if {[string length [lindex $line 0]] > $lth1 } { + set lth1 [string length [lindex $line 0]] + } + if {[string length [lindex $line 1]] > $lth2 } { + set lth2 [string length [lindex $line 1]] + } + if {[string length [lindex $line 2]] > $lth3 } { + set lth3 [string length [lindex $line 2]] + } + gets $fileid line + } + close $fileid + } + + label .b.f100.l1 -text [lindex $namelist 0] -fg blue -width 5 + label .b.f100.l2 -text [lindex $namelist 1] -fg blue -width [expr $lth1 +5] + label .b.f100.l3 -text [lindex $namelist 2] -fg blue -width [expr $lth2 +5] + label .b.f100.l4 -text [lindex $namelist 3] -fg blue -width [expr $lth3 +5] + pack .b.f100 + pack .b.f100.l1 .b.f100.l2 .b.f100.l3 .b.f100.l4 -side left + + set i 0 + foreach line $batch_data { + frame .b.f$i + set tmp [expr $i+1] + checkbutton .b.f$i.c -variable check$i -text $tmp -width 5 + label .b.f$i.l1 -text [lindex $line 0] -width $lth1 + button .b.f$i.b1 -text "Change" -width 5 -command [list ChangeDescript .b.f$i.l1 $i 0] + label .b.f$i.l2 -text [lindex $line 1] -width $lth2 + button .b.f$i.b2 -text "Change" -width 5 -command [list ChangeLabel .b.f$i.l2 $i 1] + label .b.f$i.l3 -text [lindex $line 2] -width $lth3 + button .b.f$i.b3 -text "Change" -width 5 -command [list ChangeLabel .b.f$i.l3 $i 2] + pack .b.f$i + pack .b.f$i.c .b.f$i.l1 .b.f$i.b1 .b.f$i.l2 .b.f$i.b2 .b.f$i.l3 .b.f$i.b3 -side left + incr i + } + + + frame .b.f102 + button .b.f102.b1 -text "Start Verify" -width 10 + button .b.f102.b2 -text "Save" -width 10 -command {save_batch_data} + button .b.f102.b3 -text "Exit" -width 10 -command {destroy .b} + pack .b.f102 + pack .b.f102.b1 .b.f102.b2 .b.f102.b3 -side left + bind .b.f102.b1 <ButtonPress> {create_index $i} + bind .b.f102.b1 <ButtonRelease> {start_verify 1 $index} +} + +proc create_index {i} { + global index + set index empty + set sim_times 0 + save_batch_data + for {set c 0} {$c < $i} {incr c} { + upvar 1 check$c tmp + if {$tmp==1 && $sim_times==0} { + set index $c + incr sim_times + } elseif {$tmp==1} { + lappend index $c + incr sim_times + } + } +} + +proc ChangeLabel {target_label y x} { + global batch_data + global fileselect + fileselect + tkwait window .fileSelectWindow + if {$fileselect(canceled)==1} { + return + } elseif {$fileselect(selectedfile)==""} { + warning_message "file have not been selected!" + } else { + $target_label config -text $fileselect(selectedfile) + set line [lindex $batch_data $y] + set line [lreplace $line $x $x $fileselect(selectedfile)] + set batch_data [lreplace $batch_data $y $y $line] + } +} + +proc save_batch_data {} { + global batch_data + if {[catch {open batch.dat w} fileid]} { + break + } else { + foreach line $batch_data { + puts $fileid $line + } + close $fileid + } +} + +proc ChangeDescript {target_label y x} { + global batch_data + variable value + variable target + variable newy + variable newx + toplevel .tmp + focus .tmp + set target $target_label + set newy $y + set newx $x + entry .tmp.en -width 20 -textvariable value + button .tmp.b -width 5 -text "Apply" -command {destroy .tmp} + button .tmp.b1 -width 5 -text "quit" + bind .tmp.b <ButtonPress> {ChangeDescriptApply $target $newy $newx $value} + + + pack .tmp.en .tmp.b +} + +proc ChangeDescriptApply {target_label y x value} { + global batch_data + if {$value==""} { + warning_message "Description can not be empty" + } else { + $target_label config -text $value + set line [lindex $batch_data $y] + set line [lreplace $line 0 0 $value] + set batch_data [lreplace $batch_data $y $y $line] + } +}
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/filesel.tcl b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/filesel.tcl new file mode 100644 index 000000000..c300a4403 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/filesel.tcl @@ -0,0 +1,325 @@ +# +# fileselect.tcl -- +# simple file selector. +# +# Mario Jorge Silva msilva@cs.Berkeley.EDU +# University of California Berkeley Ph: +1(510)642-8248 +# Computer Science Division, 571 Evans Hall Fax: +1(510)642-5775 +# Berkeley CA 94720 +# + +# Layout: +# +# file: +----+ +# ____________________ | OK | +# +----+ +# +# +------------------+ Cancel +# | .. |S +# | file1 |c +# | file2 |r +# | |b +# | filen |a +# | |r +# +------------------+ +# currrent-directory +# +# Copyright 1993 Regents of the University of California +# Permission to use, copy, modify, and distribute this +# software and its documentation for any purpose and without +# fee is hereby granted, provided that this copyright +# notice appears in all copies. The University of California +# makes no representations about the suitability of this +# software for any purpose. It is provided "as is" without +# express or implied warranty. +# + +# Copyright 1996 + +# Slight modifications to and adoption to Tk4.0 were made to this +# fileselectionbox code by Lakshmi Sastry, Rutherford Appleton Laboratory, +# chilton, Didcot, OXON, OX11 0QX, UK. + +# You can now type in a non-existing file name as well. This file name is +# returned for the application to open a new file to write to + +# AGOCG Tcl/Tk Cookbook +# Authors + +# Lakshmi Sastry +# Computing and Information Systems Department +# Rutherford Appleton Laboratory, Chilton, Didcot. OX11 0QX +# lakshmi.sastry@rl.ac.uk + +# and + +# Venkat VSS Sastry +# Department of Applied Mathematics and Operational Research +# Cranfield University, RMCS Shrivenham, Swindon, SN6 8LA +# sastry@rmcs.cran.ac.uk + +# Permission to use, copy, modify, and distribute this +# software and its documentation for any purpose and without +# fee is hereby granted, provided that this copyright +# notice appears in all copies. + +# The authors, RAL, RMCS Shrivenham, Cranfield University and AGOCG +# make no representations about the suitability of this +# software for any purpose. It is provided "as is" without +# express or implied warranty. Likewise they accept no responsibility +# whatsoever for any public domain software modules used (which are +# hereby acknowledged) in this software + + +# names starting with "fileselect" are reserved by this module +# no other names used. + +# use the "option" command for further configuration + +option add *Listbox*font \ + "-*-helvetica-medium-r-normal-*-12-*-*-*-p-*-iso8859-1" startupFile +option add *Entry*font \ + "-*-helvetica-medium-r-normal-*-12-*-*-*-p-*-iso8859-1" startupFile +option add *Label*font \ + "-*-helvetica-medium-r-normal-*-12-*-*-*-p-*-iso8859-1" startupFile + + +# this is the default proc called when "OK" is pressed +# to indicate yours, give it as the first arg to "fileselect" + +proc fileselect.default.cmd {f} { +global fileselect +set fileselect(selectedfile) $f +set fileselect(canceled) 0 +#puts stderr "selected file $f" + +} + + +# this is the default proc called when error is detected +# indicate your own pro as an argument to fileselect + +proc fileselect.default.errorHandler {errorMessage} { + puts stdout "error: $errorMessage" + catch { cd ~ } +} + +# this is the proc that creates the file selector box + +proc fileselect { + {cmd fileselect.default.cmd} + {purpose "Open file:"} + {w .fileSelectWindow} + {errorHandler fileselect.default.errorHandler}} { + + catch {destroy $w} + + toplevel $w + grab $w + wm title $w "Select File" + + + # path independent names for the widgets + global fileselect + global selected + set fileselect(entry) $w.file.eframe.entry + set fileselect(list) $w.file.sframe.list + set fileselect(scroll) $w.file.sframe.scroll + set fileselect(ok) $w.bframe.okframe.ok + set fileselect(cancel) $w.bframe.cancel + set fileselect(dirlabel) $w.file.dirlabel + + # widgets + frame $w.file -bd 10 + frame $w.bframe -bd 10 + pack append $w \ + $w.file {left filly} \ + $w.bframe {left expand frame n} + + frame $w.file.eframe + frame $w.file.sframe + label $w.file.dirlabel -anchor e -width 24 -text [pwd] + + pack append $w.file \ + $w.file.eframe {top frame w} \ + $w.file.sframe {top fillx} \ + $w.file.dirlabel {top frame w} + + + label $w.file.eframe.label -anchor w -width 24 -text $purpose + entry $w.file.eframe.entry -relief sunken + + pack append $w.file.eframe \ + $w.file.eframe.label {top expand frame w} \ + $w.file.eframe.entry {top fillx frame w} + + + scrollbar $w.file.sframe.yscroll -relief sunken \ + -command "$w.file.sframe.list yview" + listbox $w.file.sframe.list -relief sunken -selectmode single \ + -yscroll "$w.file.sframe.yscroll set" + #$fileselect(list) configure -selectmode single + pack append $w.file.sframe \ + $w.file.sframe.yscroll {right filly} \ + $w.file.sframe.list {left expand fill} + + # buttons + frame $w.bframe.okframe -borderwidth 2 -relief sunken + + button $w.bframe.okframe.ok -text OK -relief raised -padx 10 \ + -command "fileselect.ok.cmd $w $cmd $errorHandler" + + button $w.bframe.cancel -text cancel -relief raised -padx 10 \ + -command "fileselect.cancel.cmd $w" + pack append $w.bframe.okframe $w.bframe.okframe.ok {padx 10 pady 10} + + pack append $w.bframe $w.bframe.okframe {expand padx 20 pady 20}\ + $w.bframe.cancel {top} + + # Fill the listbox with a list of the files in the directory (run + # the "/bin/ls" command to get that information). + # to not display the "." files, remove the -a option and fileselect + # will still work + + $fileselect(list) insert end ".." + foreach i [exec ls -a [pwd]] { + if {[string compare $i "."] != 0 && \ + [string compare $i ".."] != 0 } { + $fileselect(list) insert end $i + } + } + + # Set up bindings for the browser. + bind $fileselect(entry) <Return> {eval $fileselect(ok) invoke} + bind $fileselect(entry) <Control-c> {eval $fileselect(cancel) invoke} + + bind $fileselect(list) <Button-1> { + # puts stderr "button 1 release" + set x [$fileselect(list) curselection] + $fileselect(entry) delete 0 end + $fileselect(entry) insert 0 [%W get [%W nearest %y]] + } + + bind $fileselect(list) <Key> { + set x [$fileselect(list) curselection] + $fileselect(entry) delete 0 end + $fileselect(entry) insert 0 [%W get [%W nearest %y]] + } + + bind $fileselect(list) <Double-ButtonPress-1> { + # puts stderr "double button 1" + set x [$fileselect(list) curselection] + $fileselect(entry) delete 0 end + $fileselect(entry) insert 0 [%W get [%W nearest %y]] + $fileselect(ok) invoke + } + + bind $fileselect(list) <Return> { + set x [$fileselect(list) curselection] + $fileselect(entry) delete 0 end + $fileselect(entry) insert 0 [%W get [%W nearest %y]] + $fileselect(ok) invoke + } + + # set kbd focus to entry widget + + focus $fileselect(entry) + +} + + +# auxiliary button procedures + +proc fileselect.cancel.cmd {w} { + # puts stderr "Cancel" + global fileselect + set fileselect(canceled) 1 + destroy $w +} + +proc fileselect.ok.cmd {w cmd errorHandler} { + global fileselect + global selected + set selected [$fileselect(entry) get] + # some nasty file names may cause "file isdirectory" to return an error + set sts [catch { + file isdirectory $selected + } errorMessage ] + + if { $sts != 0 } then { + $errorHandler $errorMessage + destroy $w + return + + } + + # clean the text entry and prepare the list + $fileselect(entry) delete 0 end + $fileselect(list) delete 0 end + $fileselect(list) insert end ".." + + # perform globbing on the selection. + # If globing returns an error (no match) check if a non-null name is + # entered. If name string is non-empty return it as a new file name + # else give an error message. + # If resulting list length > 1, put the list on the file listbox and return + # If globing expands to a list of filenames in multiple directories, + # the indicated regexp is invalid and the error handler is called instead. +set globlist 0 + + set sts [catch { + set globlist [glob [list $selected]] + } errorMessage ] + + if { $sts != 0 } then { + if { [llength $globlist] == 1 } { + destroy $w + $cmd $selected + return + } else { + + $errorHandler $errorMessage + destroy $w + return + + } + + + } + + if {[llength $globlist] > 1} { + if {[regexp "/" $globlist] != 0} { + $errorHandler [list "Invalid regular expression, " $selected, "."] + destroy $w + return + } + foreach i $globlist { + if {[string compare $i "."] != 0 && \ + [string compare $i ".."] != 0} { + $fileselect(list) insert end $i + } + } + return + } + + # selection may be a directory. Expand it. + + if {[file isdirectory $selected] != 0} { + cd $selected + set dir [pwd] + $fileselect(dirlabel) configure -text $dir + + foreach i [exec ls -a $dir] { + if {[string compare $i "."] != 0 && \ + [string compare $i ".."] != 0} { + $fileselect(list) insert end $i + } + } + return + } + + destroy $w + $cmd $selected + +} + diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/run.tcl b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/run.tcl new file mode 100644 index 000000000..ac8a307db --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/run.tcl @@ -0,0 +1,26 @@ +source user_lib.tcl +source set_stimulus.tcl +source set_reg_data.tcl +source start_verify.tcl +source batch_mode.tcl +source filesel.tcl + + +wm title . "main" +frame .frame +button .frame.b1 -width 20 -text "set_stimulus" +button .frame.b2 -width 20 -text "set_cpu_data" +button .frame.b3 -width 20 -text "start_verify" +button .frame.b4 -width 20 -text "batch_mode" +button .frame.b40 -width 20 -text "exit" + +bind .frame.b1 <Button-1> {set_stimulus} +bind .frame.b2 <Button-1> {set_reg_data} +bind .frame.b3 <Button-1> {start_verify 0 empty} +bind .frame.b4 <Button-1> {batch_mode} +bind .frame.b40 <Button-1> {exit} + + +pack .frame .frame.b1 .frame.b2 .frame.b3 .frame.b4 .frame.b40 + +
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/run_proc.tcl b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/run_proc.tcl new file mode 100644 index 000000000..294cb2c72 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/run_proc.tcl @@ -0,0 +1,27 @@ +proc run_proc {} { +source user_lib.tcl +source set_stimulus.tcl +source set_reg_data.tcl +source start_verify.tcl +source batch_mode.tcl +source filesel.tcl + +toplevel .frame +focus .frame +wm title .frame "main" +button .frame.b1 -width 20 -text "set_stimulus" +button .frame.b2 -width 20 -text "set_cpu_data" +button .frame.b3 -width 20 -text "start_verify" +button .frame.b4 -width 20 -text "batch_mode" +button .frame.b40 -width 20 -text "exit" -command {cd ../../../../ ;destroy .frame} + +bind .frame.b1 <Button-1> {set_stimulus} +bind .frame.b2 <Button-1> {set_reg_data} +bind .frame.b3 <Button-1> {start_verify 0 empty} +bind .frame.b4 <Button-1> {batch_mode} + + + +pack .frame.b1 .frame.b2 .frame.b3 .frame.b4 .frame.b40 + +}
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/set_reg_data.tcl b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/set_reg_data.tcl new file mode 100644 index 000000000..b4bfae35d --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/set_reg_data.tcl @@ -0,0 +1,192 @@ +proc set_reg_data {} { +variable help_strings +variable RegVector +variable datalist +set help_strings { +Set Reg Data: + The verifcation system will config DUT(Design Under Test) +with those data automatically at startup time. You must read +the tri-mode thernet spec-doc before setting the REG.Only the +correct configuration can make sitmulation continue.} + +set namelist { +RegName Address default Data} +set datalist { + +{Tx_Hwmark 0 0x001e 0x001e} +{Tx_Lwmark 1 0x0019 0x0019} +{pause_frame_send_en 2 0x0000 0x0000} +{pause_quanta_set 3 0x0000 0x0000} +{IFGset 4 0x001e 0x001e} +{FullDuplex 5 0x0001 0x0001} +{MaxRetry 6 0x0002 0x0002} +{MAC_tx_add_en 7 0x0000 0x0000} +{MAC_tx_add_prom_data 8 0x0000 0x0000} +{MAC_tx_add_prom_add 9 0x0000 0x0000} +{MAC_tx_add_prom_wr 10 0x0000 0x0000} +{tx_pause_en 11 0x0000 0x0000} +{xoff_cpu 12 0x0000 0x0000} +{xon_cpu 13 0x0000 0x0000} +{MAC_rx_add_chk_en 14 0x0000 0x0000} +{MAC_rx_add_prom_data 15 0x0000 0x0000} +{MAC_rx_add_prom_add 16 0x0000 0x0000} +{MAC_rx_add_prom_wr 17 0x0000 0x0000} +{broadcast_filter_en 18 0x0000 0x0000} +{broadcast_bucket_depth 19 0x0000 0x0000} +{broadcast_bucket_interval 20 0x0000 0x0000} +{RX_APPEND_CRC 21 0x0000 0x0000} +{Rx_Hwmark 22 0x001a 0x001a} +{Rx_Lwmark 23 0x0010 0x0010} +{CRC_chk_en 24 0x0000 0x0000} +{RX_IFG_SET 25 0x001e 0x001e} +{RX_MAX_LENGTH 26 0x2710 0x2710} +{RX_MIN_LENGTH 27 0x0040 0x0040} +{CPU_rd_addr 28 0x0000 0x0000} +{CPU_rd_apply 29 0x0000 0x0000} +{Line_loop_en 33 0x0000 0x0000} +{Speed 34 0x0004 0x0004} +} + +cd ../data + + if {[catch {open CPU.vec r} fileid]} { + set RegVector {} + } else { + set RegVector {} + gets $fileid line + while {[eof $fileid]==0} { + scan $line "%02x%02x%04x" counter addr NewValue + set y [search_add $addr] + if {$y!=-1} { + set x [lindex $datalist $y] + set x [lreplace $x 3 3 [format "0x%04x" $NewValue]] + set datalist [lreplace $datalist $y $y $x] + lappend RegVector "$y $NewValue" + } + gets $fileid line + } + close $fileid + + } + +toplevel .p +wm title .p "Setting Reg Data" +focus .p +frame .p.f1 +frame .p.f2 +pack .p.f1 .p.f2 -side top + +frame .p.f1.f1 +frame .p.f1.f2 +frame .p.f1.f3 +frame .p.f1.f4 +frame .p.f1.f5 +pack .p.f1.f1 .p.f1.f2 .p.f1.f3 .p.f1.f4 .p.f1.f5 -side left + +label .p.f1.f1.l100 -text [lindex $namelist 0] -fg blue +label .p.f1.f2.l100 -text [lindex $namelist 1] -fg blue -width 10 +label .p.f1.f3.l100 -text [lindex $namelist 2] -fg blue -width 5 +label .p.f1.f4.l100 -text [lindex $namelist 3] -fg blue -width 10 + +pack .p.f1.f1.l100 .p.f1.f2.l100 .p.f1.f3.l100 .p.f1.f4.l100 + +for {set i 0} {$i < [llength $datalist]} {incr i} { + label .p.f1.f1.l$i -text [lindex [lindex $datalist $i] 0] + label .p.f1.f2.l$i -text [lindex [lindex $datalist $i] 1] + label .p.f1.f3.l$i -text [lindex [lindex $datalist $i] 2] + entry .p.f1.f4.en$i -width 10 + .p.f1.f4.en$i insert 0 [lindex [lindex $datalist $i] 3] + if {[lindex [lindex $datalist $i] 2] !=[lindex [lindex $datalist $i] 3]} { + .p.f1.f4.en$i config -fg red + } + pack .p.f1.f1.l$i .p.f1.f2.l$i .p.f1.f3.l$i .p.f1.f4.en$i + bind .p.f1.f4.en$i <FocusOut> [list CheckModify .p.f1.f4.en$i $i ] +} + + +button .p.f2.b1 -text "Save" -width 10 -command {WriteVect CPU.vec} +button .p.f2.b2 -text "SaveAs" -width 10 -command {WriteVect [reg_save_as]} +button .p.f2.b3 -text "Exit" -width 10 -command {destroy .p} +button .p.f2.b4 -text "Help" -width 10 -command {print_help $help_strings} +pack .p.f2.b1 .p.f2.b2 .p.f2.b3 .p.f2.b4 -side left +bind .p.f2.b1 <ButtonPress> {focus .p} + + +} + +proc CheckModify {target_en index} { + global RegVector + global datalist + set data [$target_en get] + set NewValue "$index $data" + + + if {[info exists RegVector]} { + set counter [llength $RegVector] + for {set c 0} {$c<$counter} {incr c} { + if {[lindex [lindex $RegVector $c] 0]== $index} { + if {[lindex [lindex $datalist $index] 2]==$data} { + $target_en config -fg black + set RegVector [lreplace $RegVector $c $c] + } else { + set RegVector [lreplace $RegVector $c $c $NewValue] + } + return + } + } + } + if {[lindex [lindex $datalist $index] 3]==$data} { + return + } else { + $target_en config -fg red + set RegVector [lappend RegVector $NewValue] + } +} + +proc WriteVect {filename} { + global RegVector + global datalist + if {[info exists RegVector]} { + set counter [llength $RegVector] + if {[catch {open $filename w} fileid]} { + puts {failed to open vector file "$filename"} + destrop .p + } else { + for {set i 0} {$i < $counter} {incr i} { + set addr [lindex [lindex $datalist [lindex [lindex $RegVector $i] 0]] 1] + set NewValue [lindex [lindex $RegVector $i] 1] + puts $fileid [format "%02x%02x%04x" $counter $addr $NewValue] + } + close $fileid + unset RegVector + destroy .p + } + } else { + destroy .p + } +} + +proc reg_save_as {} { + global fileselect + fileselect + tkwait window .fileSelectWindow + if {$fileselect(canceled)==1} { + return + } elseif {$fileselect(selectedfile)==""} { + warning_message "file have not been selected!" + } else { + return $fileselect(selectedfile) + } +} + +proc search_add {addr} { + global datalist + set n 0 + foreach line $datalist { + if {[lindex $line 1]==$addr} { + return $n + } + incr n + } + return -1 +}
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/set_stimulus.tcl b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/set_stimulus.tcl new file mode 100644 index 000000000..2bc42d7b5 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/set_stimulus.tcl @@ -0,0 +1,101 @@ +proc set_stimulus {} { + toplevel .stimulus + focus .stimulus + wm title .stimulus "Setting Stimulus Prameters" + + variable StartLength + variable EndLength + variable PacketNumber + variable Random + variable Broadcast + variable help_string + +set help_string { +Set Stimulus Help: + You can select to generate packet with sequential packet length or +random packet length. If you choise random packet length, the length of +generated packet will be a random value between the "Packet begin length" +to the "Packet end length". "Total Gen Packet number"is used to set the +number of packet will be generated as stimulus + As well, you can select "sequence" mode . The first Packet will be +generated with "Packet begin length",and the next Packet length will be +"Packet begin length" pluse one untile the packet length reach the value +of "Packet end length". Packet in each length will be generated according +to the value of "Packet number per length" } + + + if {[catch {open ../data/config.ini r} fileid]} { + set StartLength 46 + set EndLength 60 + set PacketNumber 1 + set Random 0 + set Broadcast 0 + } \ + else { + gets $fileid content + scan $content "%d,%d,%d,%d,%d" StartLength EndLength PacketNumber Random Broadcast + close $fileid + } + + frame .stimulus.f1 + label .stimulus.f1.lb -text "Packet begin length:" + entry .stimulus.f1.en -textvariable StartLength + pack .stimulus.f1 -fill x + pack .stimulus.f1.en .stimulus.f1.lb -side right + + frame .stimulus.f2 + label .stimulus.f2.lb -text "Packet end length:" + entry .stimulus.f2.en -textvariable EndLength + pack .stimulus.f2 -fill x + pack .stimulus.f2.en .stimulus.f2.lb -side right + + + frame .stimulus.f3 + label .stimulus.f3.lb -text "Packet number per length:" + entry .stimulus.f3.en -textvariable PacketNumber + pack .stimulus.f3 -fill x + pack .stimulus.f3.en .stimulus.f3.lb -side right + + frame .stimulus.f4 + radiobutton .stimulus.f4.1 -text "Sequence" -variable Random -value 0 \ + -command {.stimulus.f3.lb config -text "Packet number per length:"} + radiobutton .stimulus.f4.2 -text "Random" -variable Random -value 1 \ + -command {.stimulus.f3.lb config -text "Total Gen Packet number:"} + pack .stimulus.f4 -fill x + pack .stimulus.f4.1 .stimulus.f4.2 -side right + + frame .stimulus.f5 + checkbutton .stimulus.f5.1 -text "Broadcast" -variable Broadcast + pack .stimulus.f5 -fill x + pack .stimulus.f5.1 -side right + + frame .stimulus.f20 + button .stimulus.f20.1 -text "Save" -width 10 \ + -command { set fileid [open ../data/config.ini w 0600] + puts $fileid "$StartLength,$EndLength,$PacketNumber,$Random,$Broadcast" + close $fileid + destroy .stimulus + } + button .stimulus.f20.2 -text "Save as" -command {sti_save_as $StartLength $EndLength $PacketNumber $Random $Broadcast} -width 10 + button .stimulus.f20.3 -text "Cancel" -command {destroy .stimulus} -width 10 + button .stimulus.f20.4 -text "Help" -width 10 -command {print_help $help_string} + pack .stimulus.f20 -fill x + pack .stimulus.f20.1 .stimulus.f20.2 .stimulus.f20.3 .stimulus.f20.4 -side left +} + +proc sti_save_as {StartLength EndLength PacketNumber Random Broadcast} { + global fileselect + cd ../data + fileselect + tkwait window .fileSelectWindow + if {$fileselect(canceled)==1} { + return + } elseif {$fileselect(selectedfile)==""} { + warning_message "file have not been selected!" + } else { + set fileid [open $fileselect(selectedfile) w 0600] + puts $fileid "$StartLength,$EndLength,$PacketNumber,$Random,$Broadcast" + close $fileid + destroy .stimulus + } +}
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/start_verify.tcl b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/start_verify.tcl new file mode 100644 index 000000000..3209e6309 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/start_verify.tcl @@ -0,0 +1,127 @@ +proc start_verify {batch index} { +variable compiling +variable simulate_times +variable test_case_number +variable batch_data {} +variable batchmode +variable piple +############################################################################### + set batchmode $batch + toplevel .l + focus .l + wm title .l "Simulation Log" + frame .l.f1 + frame .l.f2 + pack .l.f1 .l.f2 -side top + + text .l.f1.t1 -width 80 -height 40 -yscrollcommand {.l.f1.scroll set} + + scrollbar .l.f1.scroll -command {.l.f1.t1 yview} + button .l.f2.b1 -text "Exit" -command {destroy .l} -width 10 + button .l.f2.b2 -text "Stop" -command {Stop_sim} -width 10 + pack .l.f1.scroll -side right -fill y + pack .l.f1.t1 + pack .l.f2.b1 .l.f2.b2 -side left + + set output_win .l.f1.t1 + set simulate_times 0 + set test_case_number [lindex $index 0] + cd ../bin + set compiling 1 + if {$batch==0} { + Run "bash sim.nc " $output_win + } elseif {[catch {open ../data/batch.dat r} fileid]} { + $output_win insert end "Failed open ../data/batch.dat file\n" + } elseif {[lindex $index 0] == "empty"} { + $output_win insert end "Not any test case was selected\n" + } else { + set i 0 + gets $fileid line + while {[eof $fileid]==0} { + lappend batch_data $line + gets $fileid line + incr i + } + $output_win insert end "Verifcation Started\n" + $output_win insert end "Starting Compiling Source file and libs......\n" + Run "bash com.nc" $output_win + close $fileid + } +} + +proc Run {command output_win} { + global piple + if [catch {open "|$command |& cat "} piple] { + $output_win insert end $piple\n + } else { + fileevent $piple readable [list Log $piple $output_win] + } +} + +proc Log {piple output_win} { + global compiling + global batchmode + set saparator "###################################################################\n" + if {[eof $piple]} { + if {$batchmode==0} { + $output_win insert end $saparator + $output_win insert end "end of Simulation....\n" + $output_win insert end $saparator + } elseif {$compiling==1} { + $output_win insert end $saparator + $output_win insert end "end of Compiling....\n" + $output_win insert end $saparator + $output_win insert end "\n \n \n" + set compiling 0 + sim_next_case + } else { + $output_win insert end $saparator + $output_win insert end "end of Testcase....\n" + $output_win insert end $saparator + $output_win insert end "\n \n \n" + sim_next_case + } + close $piple + } else { + gets $piple line + $output_win insert end $line\n + $output_win see end + } +} + +proc sim_next_case {} { + global test_case_number + global simulate_times + global batch_data + global index + set saparator "###################################################################\n" + set output_win .l.f1.t1 + set test_case_number [lindex $index $simulate_times] + if {$simulate_times < [llength $index]} { + set line [lindex $batch_data $test_case_number] + set source_sti [lindex $line 1] + set source_reg [lindex $line 2] + + if {$simulate_times==0 ||[file exists "../log/.sim_succeed"]} { + exec cp "../data/$source_sti" "../data/config.ini" + exec cp "../data/$source_reg" "../data/CPU.vec" + + $output_win insert end $saparator + $output_win insert end "starting test case :[lindex $line 0]....\n" + $output_win insert end $saparator + $output_win insert end "\n \n \n" + incr simulate_times + Run "bash sim_only.nc" $output_win + } else { + $output_win insert end "test_case :[lindex $line 0] simulation failed!!\n" + } + + } else { + $output_win insert end "All test_case passed simulation Successfully!!\n" + } +} + +proc Stop_sim {} { + global piple + catch {close $piple} +}
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/user_lib.tcl b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/user_lib.tcl new file mode 100644 index 000000000..14b4302b8 --- /dev/null +++ b/opencores/ethernet_tri_mode/sim/rtl_sim/ncsim_sim/script/user_lib.tcl @@ -0,0 +1,17 @@ +proc print_help {help_string} { + toplevel .help + frame .help.1 + message .help.1.1 -text $help_string -width 10c + frame .help.2 + button .help.2.1 -text "exit" -command {destroy .help} -width 10 + pack .help.1 .help.2 .help.1.1 .help.2.1 +} + +proc warning_message {warning_string} { + toplevel .warning + frame .warning.1 + message .warning.1.1 -text $warning_string -width 10c + frame .warning.2 + button .warning.2.1 -text "exit" -command {destroy .warning} -width 10 + pack .warning.1 .warning.2 .warning.1.1 .warning.2.1 +}
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/start.tcl b/opencores/ethernet_tri_mode/start.tcl new file mode 100644 index 000000000..42d11c15b --- /dev/null +++ b/opencores/ethernet_tri_mode/start.tcl @@ -0,0 +1,180 @@ +variable MAC_SOURCE_REPLACE_EN +variable MAC_TARGET_CHECK_EN +variable MAC_BROADCAST_FILTER_EN +variable MAC_TX_FF_DEPTH +variable MAC_RX_FF_DEPTH +variable header_data + +source sim/rtl_sim/ncsim_sim/script/run_proc.tcl + +frame .f1 +frame .f2 +text .f1.t1 -width 60 -height 20 +button .f2.b1 -text "Quit" -width 5 -command {exit} +button .f2.b2 -text "Next" -width 5 -command {module_conf} + +pack .f1 .f2 +pack .f1.t1 +pack .f2.b1 .f2.b2 -side left + +set strings \ +{Hi guys, + Thanks for your interest about this tri-speed ethernet MAC controller. +Since this project was created at 25-Nov-2005,I put almost all my free time +on this project.I am exhausted for this two month's extra work.If you think +this project is useful,let me know that and i will feel much better. + + To increase the flexibility, some optional modules can be removed from +the design to reduce area. + + Any problem or bug report please contact me by email: + gaojon@yahoo.com + + + + + + + jon + 18-Jan-2006 +} + +.f1.t1 insert end $strings + +proc module_conf {} { + global MAC_SOURCE_REPLACE_EN + global MAC_TARGET_CHECK_EN + global MAC_BROADCAST_FILTER_EN + global MAC_TX_FF_DEPTH + global MAC_RX_FF_DEPTH + global header_data + + if {[catch {open ./rtl/verilog/header.v r} fileid]} { + puts "Failed open ./rtl/verilog/header.v file\n" + } else { + gets $fileid line + if {[lindex $line 0]=="//"} { + set line [lreplace $line 0 0] + set MAC_SOURCE_REPLACE_EN 0 + } else { + set MAC_SOURCE_REPLACE_EN 1 + } + lappend header_data $line + gets $fileid line + if {[lindex $line 0]=="//"} { + set line [lreplace $line 0 0] + set MAC_TARGET_CHECK_EN 0 + } else { + set MAC_TARGET_CHECK_EN 1 + } + lappend header_data $line + gets $fileid line + if {[lindex $line 0]=="//"} { + set line [lreplace $line 0 0] + set MAC_BROADCAST_FILTER_EN 0 + } else { + set MAC_BROADCAST_FILTER_EN 1 + } + lappend header_data $line + gets $fileid line + set MAC_TX_FF_DEPTH [lindex $line 2] + lappend header_data $line + gets $fileid line + set MAC_RX_FF_DEPTH [lindex $line 2] + lappend header_data $line + close $fileid + } + + destroy .f1 .f2 + frame .f1 + frame .f2 + frame .f1.f1 + frame .f1.f2 + frame .f1.f3 + frame .f1.f4 + frame .f1.f5 + frame .f1.f6 + + pack .f1 .f2 + pack .f1.f1 .f1.f2 .f1.f3 .f1.f4 .f1.f5 .f1.f6 + label .f1.f1.lb -text "enable source MAC replace module" -width 30 + checkbutton .f1.f1.cb -variable MAC_SOURCE_REPLACE_EN + label .f1.f2.lb -text "enable target MAC check module " -width 30 + checkbutton .f1.f2.cb -variable MAC_TARGET_CHECK_EN + label .f1.f3.lb -text "enable broadcast packet filter module" -width 30 + checkbutton .f1.f3.cb -variable MAC_BROADCAST_FILTER_EN + + label .f1.f4.lb -text "MAC_TX_FF_DEPTH" -width 30 + entry .f1.f4.en -textvariable MAC_TX_FF_DEPTH -width 5 + label .f1.f5.lb -text "MAC_RX_FF_DEPTH" -width 30 + entry .f1.f5.en -textvariable MAC_RX_FF_DEPTH -width 5 + + button .f2.b1 -width 10 -text "Save" -command {save_header} + button .f2.b2 -width 10 -text "Verify" -command {run_sim} + button .f2.b4 -width 10 -text "Exit" -command {exit} + + pack .f1.f1.cb .f1.f1.lb -side right + pack .f1.f2.cb .f1.f2.lb -side right + pack .f1.f3.cb .f1.f3.lb -side right + pack .f1.f4.en .f1.f4.lb -side right + pack .f1.f5.en .f1.f5.lb -side right + + pack .f2.b1 .f2.b2 .f2.b4 -side left + +} + +proc save_header {} { + global MAC_SOURCE_REPLACE_EN + global MAC_TARGET_CHECK_EN + global MAC_BROADCAST_FILTER_EN + global MAC_TX_FF_DEPTH + global MAC_RX_FF_DEPTH + global header_data + if {[catch {open ./rtl/verilog/header.v w} fileid]} { + puts "Failed open ./rtl/verilog/header.v file\n" + } else { + set line [lindex $header_data 0] + if {$MAC_SOURCE_REPLACE_EN==0} { + set line [linsert $line 0 "//"] + } + puts $fileid $line + + set line [lindex $header_data 1] + if {$MAC_TARGET_CHECK_EN==0} { + set line [linsert $line 0 "//"] + } + puts $fileid $line + + set line [lindex $header_data 2] + if {$MAC_BROADCAST_FILTER_EN==0} { + set line [linsert $line 0 "//"] + } + puts $fileid $line + + set line [lindex $header_data 3] + set line [lreplace $line 2 2 $MAC_TX_FF_DEPTH] + puts $fileid $line + + set line [lindex $header_data 4] + set line [lreplace $line 2 2 $MAC_RX_FF_DEPTH] + puts $fileid $line + + close $fileid + } + +} + +proc start_verify {} { + cd sim/rtl_sim/ncsim_sim/script + vish run.tcl +} + +proc start_syn {} { + cd syn + synplify_pro syn.prj +} + +proc run_sim {} { + cd sim/rtl_sim/ncsim_sim/script/ + run_proc +}
\ No newline at end of file diff --git a/opencores/ethernet_tri_mode/syn/CVS/Entries b/opencores/ethernet_tri_mode/syn/CVS/Entries new file mode 100644 index 000000000..b6b97bde6 --- /dev/null +++ b/opencores/ethernet_tri_mode/syn/CVS/Entries @@ -0,0 +1,4 @@ +/syn.prj/1.2/Thu Jan 19 14:07:57 2006// +/syn_altrea.prj/1.1/Sun Jun 25 05:09:02 2006// +/syn_xilinx.prj/1.1/Sun Jun 25 05:09:02 2006// +D diff --git a/opencores/ethernet_tri_mode/syn/CVS/Repository b/opencores/ethernet_tri_mode/syn/CVS/Repository new file mode 100644 index 000000000..300767cae --- /dev/null +++ b/opencores/ethernet_tri_mode/syn/CVS/Repository @@ -0,0 +1 @@ +ethernet_tri_mode/syn diff --git a/opencores/ethernet_tri_mode/syn/CVS/Root b/opencores/ethernet_tri_mode/syn/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/ethernet_tri_mode/syn/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/ethernet_tri_mode/syn/CVS/Template b/opencores/ethernet_tri_mode/syn/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/ethernet_tri_mode/syn/CVS/Template diff --git a/opencores/ethernet_tri_mode/syn/syn.prj b/opencores/ethernet_tri_mode/syn/syn.prj new file mode 100644 index 000000000..568a7a4ed --- /dev/null +++ b/opencores/ethernet_tri_mode/syn/syn.prj @@ -0,0 +1,86 @@ +#-- Synplicity, Inc. +#-- Version Synplify 8.1 +#-- Project file D:\root\home\ethernet_tri_mode\syn\syn.prj +#-- Written on Thu Jan 19 20:25:55 2006 + + +#add_file options +add_file -verilog "../rtl/verilog/header.v" +add_file -verilog "../rtl/verilog/MAC_tx/MAC_tx_FF.v" +add_file -verilog "../rtl/verilog/MAC_tx/Ramdon_gen.v" +add_file -verilog "../rtl/verilog/MAC_tx/CRC_gen.v" +add_file -verilog "../rtl/verilog/MAC_tx/MAC_tx_addr_add.v" +add_file -verilog "../rtl/verilog/MAC_tx/MAC_tx_Ctrl.v" +add_file -verilog "../rtl/verilog/MAC_tx/flow_ctrl.v" +add_file -verilog "../rtl/verilog/MAC_rx/CRC_chk.v" +add_file -verilog "../rtl/verilog/MAC_rx/MAC_rx_add_chk.v" +add_file -verilog "../rtl/verilog/MAC_rx/MAC_rx_FF.v" +add_file -verilog "../rtl/verilog/MAC_rx/MAC_rx_ctrl.v" +add_file -verilog "../rtl/verilog/RMON/RMON_addr_gen.v" +add_file -verilog "../rtl/verilog/RMON/RMON_ctrl.v" +add_file -verilog "../rtl/verilog/RMON/RMON_dpram.v" +add_file -verilog "../rtl/verilog/MAC_rx/Broadcast_filter.v" +add_file -verilog "../rtl/verilog/TECH/duram.v" +add_file -verilog "../rtl/verilog/RMON.v" +add_file -verilog "../rtl/verilog/MAC_rx.v" +add_file -verilog "../rtl/verilog/MAC_tx.v" +add_file -verilog "../rtl/verilog/miim/eth_clockgen.v" +add_file -verilog "../rtl/verilog/miim/eth_outputcontrol.v" +add_file -verilog "../rtl/verilog/miim/eth_shiftreg.v" +add_file -verilog "../rtl/verilog/miim/timescale.v" +add_file -verilog "../rtl/verilog/TECH/CLK_SWITCH.v" +add_file -verilog "../rtl/verilog/TECH/CLK_DIV2.v" +add_file -verilog "../rtl/verilog/eth_miim.v" +add_file -verilog "../rtl/verilog/Clk_ctrl.v" +add_file -verilog "../rtl/verilog/Phy_int.v" +add_file -verilog "../rtl/verilog/Reg_int.v" +add_file -verilog "../rtl/verilog/MAC_top.v" + + +#implementation: "syn" +impl -add syn + +#device options +set_option -technology STRATIX +set_option -part EP1S10 +set_option -package FC780 +set_option -speed_grade -5 + +#compilation/mapping options +set_option -default_enum_encoding onehot +set_option -symbolic_fsm_compiler 0 +set_option -resource_sharing 1 +set_option -use_fsm_explorer 0 + +#map options +set_option -frequency auto +set_option -run_prop_extract 0 +set_option -fanout_limit 500 +set_option -disable_io_insertion 0 +set_option -pipe 1 +set_option -update_models_cp 0 +set_option -retiming 0 +set_option -verification_mode 0 +set_option -fixgatedclocks 0 +set_option -no_sequential_opt 0 + +#simulation options +set_option -write_verilog 1 +set_option -write_vhdl 0 + +#automatic place and route (vendor) options +set_option -write_apr_constraint 0 + +#set result format/file last +project -result_file "./MAC_top.vqm" + +# +#implementation attributes + +set_option -vlog_std v2001 +set_option -project_relative_includes 1 + +#par_1 attributes +set_option -job par_1 -add par +set_option -job par_1 -option run_backannotation 0 +impl -active "syn" diff --git a/opencores/ethernet_tri_mode/syn/syn_altrea.prj b/opencores/ethernet_tri_mode/syn/syn_altrea.prj new file mode 100644 index 000000000..e227ea672 --- /dev/null +++ b/opencores/ethernet_tri_mode/syn/syn_altrea.prj @@ -0,0 +1,91 @@ +#-- Synplicity, Inc. +#-- Version Synplify Pro 8.1 +#-- Project file D:\root\home\ethernet_tri_mode\syn\syn_altrea.prj +#-- Written on Sun Jun 25 09:40:49 2006 + + +#add_file options +add_file -verilog "../rtl/verilog/header.v" +add_file -verilog "../rtl/verilog/MAC_tx/MAC_tx_FF.v" +add_file -verilog "../rtl/verilog/MAC_tx/Ramdon_gen.v" +add_file -verilog "../rtl/verilog/MAC_tx/CRC_gen.v" +add_file -verilog "../rtl/verilog/MAC_tx/MAC_tx_addr_add.v" +add_file -verilog "../rtl/verilog/MAC_tx/MAC_tx_Ctrl.v" +add_file -verilog "../rtl/verilog/MAC_tx/flow_ctrl.v" +add_file -verilog "../rtl/verilog/MAC_rx/CRC_chk.v" +add_file -verilog "../rtl/verilog/MAC_rx/MAC_rx_add_chk.v" +add_file -verilog "../rtl/verilog/MAC_rx/MAC_rx_FF.v" +add_file -verilog "../rtl/verilog/MAC_rx/MAC_rx_ctrl.v" +add_file -verilog "../rtl/verilog/RMON/RMON_addr_gen.v" +add_file -verilog "../rtl/verilog/RMON/RMON_ctrl.v" +add_file -verilog "../rtl/verilog/RMON/RMON_dpram.v" +add_file -verilog "../rtl/verilog/MAC_rx/Broadcast_filter.v" +add_file -verilog "../rtl/verilog/RMON.v" +add_file -verilog "../rtl/verilog/MAC_rx.v" +add_file -verilog "../rtl/verilog/MAC_tx.v" +add_file -verilog "../rtl/verilog/miim/eth_clockgen.v" +add_file -verilog "../rtl/verilog/miim/eth_outputcontrol.v" +add_file -verilog "../rtl/verilog/miim/eth_shiftreg.v" +add_file -verilog "../rtl/verilog/miim/timescale.v" +add_file -verilog "../rtl/verilog/TECH/altera/duram.v" +add_file -verilog "../rtl/verilog/TECH/altera/CLK_SWITCH.v" +add_file -verilog "../rtl/verilog/TECH/altera/CLK_DIV2.v" +add_file -verilog "../rtl/verilog/eth_miim.v" +add_file -verilog "../rtl/verilog/Clk_ctrl.v" +add_file -verilog "../rtl/verilog/Phy_int.v" +add_file -verilog "../rtl/verilog/Reg_int.v" +add_file -verilog "../rtl/verilog/MAC_top.v" + + +#implementation: "syn" +impl -add syn + +#device options +set_option -technology STRATIX +set_option -part EP1S30 +set_option -package FC780 +set_option -speed_grade -5 + +#compilation/mapping options +set_option -default_enum_encoding onehot +set_option -symbolic_fsm_compiler 0 +set_option -resource_sharing 1 +set_option -use_fsm_explorer 0 +set_option -top_module "MAC_top" + +#map options +set_option -frequency auto +set_option -run_prop_extract 0 +set_option -fanout_limit 500 +set_option -disable_io_insertion 0 +set_option -pipe 1 +set_option -update_models_cp 0 +set_option -retiming 0 +set_option -verification_mode 0 +set_option -fixgatedclocks 0 +set_option -no_sequential_opt 0 + +#simulation options +set_option -write_verilog 1 +set_option -write_vhdl 0 + +#VIF options +set_option -write_vif 1 + +#automatic place and route (vendor) options +set_option -write_apr_constraint 0 + +#set result format/file last +project -result_file "./MAC_top.vqm" + +# +#implementation attributes + +set_option -vlog_std v2001 +set_option -dup 0 +set_option -project_relative_includes 1 + +#par_1 attributes +set_option -job par_1 -add par +set_option -job par_1 -option run_backannotation 0 +impl -active "syn" diff --git a/opencores/ethernet_tri_mode/syn/syn_xilinx.prj b/opencores/ethernet_tri_mode/syn/syn_xilinx.prj new file mode 100644 index 000000000..94435b4b1 --- /dev/null +++ b/opencores/ethernet_tri_mode/syn/syn_xilinx.prj @@ -0,0 +1,92 @@ +#-- Synplicity, Inc. +#-- Version Synplify Pro 8.1 +#-- Project file D:\root\home\ethernet_tri_mode\syn\syn_xilinx.prj +#-- Written on Sun Jun 25 09:43:29 2006 + + +#add_file options +add_file -verilog "../rtl/verilog/header.v" +add_file -verilog "../rtl/verilog/MAC_tx/MAC_tx_FF.v" +add_file -verilog "../rtl/verilog/MAC_tx/Ramdon_gen.v" +add_file -verilog "../rtl/verilog/MAC_tx/CRC_gen.v" +add_file -verilog "../rtl/verilog/MAC_tx/MAC_tx_addr_add.v" +add_file -verilog "../rtl/verilog/MAC_tx/MAC_tx_Ctrl.v" +add_file -verilog "../rtl/verilog/MAC_tx/flow_ctrl.v" +add_file -verilog "../rtl/verilog/MAC_rx/CRC_chk.v" +add_file -verilog "../rtl/verilog/MAC_rx/MAC_rx_add_chk.v" +add_file -verilog "../rtl/verilog/MAC_rx/MAC_rx_FF.v" +add_file -verilog "../rtl/verilog/MAC_rx/MAC_rx_ctrl.v" +add_file -verilog "../rtl/verilog/RMON/RMON_addr_gen.v" +add_file -verilog "../rtl/verilog/RMON/RMON_ctrl.v" +add_file -verilog "../rtl/verilog/RMON/RMON_dpram.v" +add_file -verilog "../rtl/verilog/MAC_rx/Broadcast_filter.v" +add_file -verilog "../rtl/verilog/RMON.v" +add_file -verilog "../rtl/verilog/MAC_rx.v" +add_file -verilog "../rtl/verilog/MAC_tx.v" +add_file -verilog "../rtl/verilog/miim/eth_clockgen.v" +add_file -verilog "../rtl/verilog/miim/eth_outputcontrol.v" +add_file -verilog "../rtl/verilog/miim/eth_shiftreg.v" +add_file -verilog "../rtl/verilog/miim/timescale.v" +add_file -verilog "../rtl/verilog/TECH/xilinx/duram.v" +add_file -verilog "../rtl/verilog/TECH/xilinx/CLK_SWITCH.v" +add_file -verilog "../rtl/verilog/TECH/xilinx/CLK_DIV2.v" +add_file -verilog "../rtl/verilog/eth_miim.v" +add_file -verilog "../rtl/verilog/Clk_ctrl.v" +add_file -verilog "../rtl/verilog/Phy_int.v" +add_file -verilog "../rtl/verilog/Reg_int.v" +add_file -verilog "../rtl/verilog/MAC_top.v" + + +#implementation: "syn" +impl -add syn + +#device options +set_option -technology VIRTEX4 +set_option -part XC4VLX40 +set_option -package FF668 +set_option -speed_grade -10 + +#compilation/mapping options +set_option -default_enum_encoding onehot +set_option -symbolic_fsm_compiler 0 +set_option -resource_sharing 1 +set_option -use_fsm_explorer 0 +set_option -top_module "MAC_top" + +#map options +set_option -frequency auto +set_option -run_prop_extract 0 +set_option -fanout_limit 10000 +set_option -disable_io_insertion 0 +set_option -pipe 1 +set_option -update_models_cp 0 +set_option -verification_mode 0 +set_option -fixgatedclocks 0 +set_option -modular 0 +set_option -retiming 0 +set_option -no_sequential_opt 0 + +#simulation options +set_option -write_verilog 0 +set_option -write_vhdl 0 + +#VIF options +set_option -write_vif 0 + +#automatic place and route (vendor) options +set_option -write_apr_constraint 0 + +#set result format/file last +project -result_file "./MAC_top.edf" + +# +#implementation attributes + +set_option -vlog_std v2001 +set_option -dup 0 +set_option -project_relative_includes 1 + +#par_1 attributes +set_option -job par_1 -add par +set_option -job par_1 -option run_backannotation 0 +impl -active "syn" |