URL
https://opencores.org/ocsvn/ethernet_tri_mode/ethernet_tri_mode/trunk
Subversion Repositories ethernet_tri_mode
[/] [ethernet_tri_mode/] [trunk/] [bench/] [verilog/] [altera_mf.v] - Rev 33
Compare with Previous | Blame | View Log
// 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