From e5a0d78e0252a5bd3f16c6db06503bc50db87408 Mon Sep 17 00:00:00 2001 From: NadeemYaseen Date: Fri, 28 Jun 2024 20:29:27 +0000 Subject: [PATCH] Added SIM change files from 1.4.1 --- sim_models/verilog/I_SERDES.v | 58 ++--- sim_models/verilog/O_SERDES.v | 5 +- sim_models/verilog/PLL.v | 422 +++++++++++++++++++--------------- 3 files changed, 268 insertions(+), 217 deletions(-) diff --git a/sim_models/verilog/I_SERDES.v b/sim_models/verilog/I_SERDES.v index e7e5ac4..a9078dd 100644 --- a/sim_models/verilog/I_SERDES.v +++ b/sim_models/verilog/I_SERDES.v @@ -250,7 +250,7 @@ module I_SERDES #( parameter DPA_MODE = "NONE" // Select Dynamic Phase Alignment or Clock Data Recovery (NONE/DPA/CDR) ) ( input D, // Data input (connect to input port, buffer or I_DELAY) - input RX_RST, // Active-low asycnhronous reset + input RST, // Active-low asycnhronous reset input BITSLIP_ADJ, // BITSLIP_ADJ input input EN, // EN input data (input data is low when driven low) input CLK_IN, // Fabric clock input @@ -380,9 +380,9 @@ end // DPA BLOCK // // clk 0 check -always@(posedge clk_0 or negedge RX_RST) +always@(posedge clk_0 or negedge RST) begin - if(!RX_RST) + if(!RST) begin clk0_data_reg<=0; clk0_data_comp<=0; @@ -409,9 +409,9 @@ begin end // clk 90 check -always@(posedge clk_90 or negedge RX_RST) +always@(posedge clk_90 or negedge RST) begin - if(!RX_RST) + if(!RST) begin clk90_data_reg<=0; clk90_data_comp<=0; @@ -438,9 +438,9 @@ begin end // clk 180 check -always@(posedge clk_180 or negedge RX_RST) +always@(posedge clk_180 or negedge RST) begin - if(!RX_RST) + if(!RST) begin clk180_data_reg<=0; clk180_data_comp<=0; @@ -467,9 +467,9 @@ begin end // clk 270 check -always@(posedge clk_270 or negedge RX_RST) +always@(posedge clk_270 or negedge RST) begin - if(!RX_RST) + if(!RST) begin clk270_data_reg<=0; clk270_data_comp<=0; @@ -538,9 +538,9 @@ assign DPA_ERROR= dpa_error; // FOR FAST CLOCK // count cycles after PLL LOCK -always@(posedge PLL_CLK or negedge RX_RST) +always@(posedge PLL_CLK or negedge RST) begin -if(!RX_RST) +if(!RST) pll_lock_count<=0; else if(!PLL_LOCK) pll_lock_count<=0; @@ -551,9 +551,9 @@ else if(PLL_LOCK && pll_lock_count<=255) end // Generate Core CLK And Word Load Enable -always@(posedge PLL_CLK or negedge RX_RST) +always@(posedge PLL_CLK or negedge RST) begin -if(!RX_RST) +if(!RST) begin core_clk<=0; core_clk_count<=0; @@ -577,9 +577,9 @@ end // FOR CDR CLOCK // count cycles after PLL LOCK -always@(posedge cdr_clk or negedge RX_RST) +always@(posedge cdr_clk or negedge RST) begin -if(!RX_RST) +if(!RST) cdr_pll_lock_count<=0; else if(!PLL_LOCK) cdr_pll_lock_count<=0; @@ -589,9 +589,9 @@ else if(PLL_LOCK && cdr_pll_lock_count<=255) end // Generate CDR Core CLK And Word Load Enable -always@(posedge cdr_clk or negedge RX_RST) +always@(posedge cdr_clk or negedge RST) begin -if(!RX_RST) +if(!RST) begin cdr_core_clk<=0; cdr_core_clk_count<=0; @@ -626,12 +626,12 @@ afifo # ( ) afifo_dpa ( .wclk(cdr_clk), -.wr_reset(!RX_RST), +.wr_reset(!RST), .wr(!dpa_fifo_full), .wr_data(dpa_dout), .wr_full(dpa_fifo_full), .rclk(PLL_CLK), -.rd_reset(!RX_RST), +.rd_reset(!RST), .rd(!dpa_fifo_empty), .rd_data(dpa_fifo_dout), .rd_empty(dpa_fifo_empty) @@ -658,9 +658,9 @@ end assign bitslip_adj_pulse = (bitslip_adj_1) && (!bitslip_adj_0); // bitslip counter -always @(posedge bitslip_des_clk or negedge RX_RST) +always @(posedge bitslip_des_clk or negedge RST) begin -if(!RX_RST) +if(!RST) begin bitslip_counter<=0; bitslip_shifter_out<=0; @@ -679,9 +679,9 @@ end end // bit shifter -always @(posedge bitslip_des_clk or negedge RX_RST) +always @(posedge bitslip_des_clk or negedge RST) begin -if(!RX_RST) +if(!RST) bit_shifter<=0; else bit_shifter<={bit_shifter[WIDTH-2:0],bitslip_din}; @@ -703,9 +703,9 @@ case(bitslip_counter) endcase end -always @(posedge bitslip_des_clk or negedge RX_RST) +always @(posedge bitslip_des_clk or negedge RST) begin -if(!RX_RST) +if(!RST) bitslip_dout<=0; else bitslip_dout<=bitslip_shifter_out; @@ -715,9 +715,9 @@ end // DE-SERIALIZER // // SHIFTER+PARALLEL-REGISTER -always@(posedge bitslip_des_clk or negedge RX_RST) +always@(posedge bitslip_des_clk or negedge RST) begin -if(!RX_RST) +if(!RST) begin des_shifter<=0; des_parallel_reg<=0; @@ -738,12 +738,12 @@ afifo # ( ) afifo_inst ( .wclk(bitslip_des_clk), -.wr_reset(!RX_RST), +.wr_reset(!RST), .wr(!des_fifo_full && des_word_load_en), .wr_data(des_parallel_reg), .wr_full(des_fifo_full), .rclk(CLK_IN), -.rd_reset(!RX_RST), +.rd_reset(!RST), .rd(!des_fifo_empty), .rd_data(Q), .rd_empty(des_fifo_empty) diff --git a/sim_models/verilog/O_SERDES.v b/sim_models/verilog/O_SERDES.v index 25ed6e7..b4996c9 100644 --- a/sim_models/verilog/O_SERDES.v +++ b/sim_models/verilog/O_SERDES.v @@ -69,7 +69,7 @@ module O_SERDES #( ) ( input [WIDTH-1:0] D, // D input bus input RST, // Active-low, asynchronous reset - input LOAD_WORD, // Load word input + input DATA_VALID, // Active high data valid signal input CLK_IN, // Fabric clock input input OE_IN, // Output tri-state enable input output OE_OUT, // Output tri-state enable output (conttect to O_BUFT or inferred tri-state signal) @@ -81,7 +81,6 @@ module O_SERDES #( ); - // GBOX CLK GEN reg core_clk=0; reg word_load_en; @@ -194,7 +193,7 @@ module O_SERDES #( fifo_read_en <= 1'b1; end - assign word_load_en_sync = LOAD_WORD && fifo_read_en ; + assign word_load_en_sync = DATA_VALID && fifo_read_en && word_load_en ; // Parallel data register diff --git a/sim_models/verilog/PLL.v b/sim_models/verilog/PLL.v index 05e2828..d3af947 100644 --- a/sim_models/verilog/PLL.v +++ b/sim_models/verilog/PLL.v @@ -1,4 +1,4 @@ -`timescale 1fs/1fs +`timescale 1ps/10fs `celldefine // // PLL simulation model @@ -8,179 +8,221 @@ // module PLL #( + parameter DEV_FAMILY = "VIRGO", // Device Family parameter DIVIDE_CLK_IN_BY_2 = "FALSE", // Enable input divider (TRUE/FALSE) - parameter PLL_MULT = 16, // VCO clock multiplier value (16-1000) + parameter PLL_MULT = 16, // VCO clock multiplier value (16-640) parameter PLL_DIV = 1, // VCO clock divider value (1-63) - parameter PLL_POST_DIV = 2 // VCO clock post-divider value (2,4,6,8,10,12,14,16,18,20,24,28,30,32,36,40,42,48,50,56,60,70,72,84,98) + parameter PLL_MULT_FRAC = 0, // Fraction mode not supported + parameter PLL_POST_DIV = 17 // VCO clock post-divider value (17,18,19,20,21,22,23,34,35,36,37,38,39,51,52,53,54,55,68,69,70,71,85,86,87,102,103,119) ) ( input PLL_EN, // PLL Enable input CLK_IN, // Clock input - output reg CLK_OUT = 1'b0, // Output clock, frequency is CLK_IN_FREQ*PLL_MULT/PLL_DIV/PLL_POST_DIV - output reg CLK_OUT_DIV2 = 1'b0, // CLK_OUT divided by 2 output - output reg CLK_OUT_DIV3 = 1'b0, // CLK_OUT divided by 3 output - output reg CLK_OUT_DIV4 = 1'b0, // CLK_OUT divided by 4 output - output reg SERDES_FAST_CLK = 1'b0, // Gearbox fast clock output - output reg LOCK = 1'b0 // PLL lock signal + output CLK_OUT, // Output clock, frequency is (CLK_IN/PLL_DIV)*(PLL_MULT/(PLL_POST_DIV0*PLL_POST_DIV1)) + output CLK_OUT_DIV2, // CLK_OUT divided by 2 output + output CLK_OUT_DIV3, // CLK_OUT divided by 3 output + output CLK_OUT_DIV4, // CLK_OUT divided by 4 output + output FAST_CLK, // VCO clock output, frequency is (CLK_IN/PLL_DIV)*(PLL_MULT) + output LOCK // PLL lock signal ); -localparam div_input_clk = (DIVIDE_CLK_IN_BY_2=="TRUE") ? 2 : 1; - -localparam clk_in_max_period = (DIVIDE_CLK_IN_BY_2=="TRUE") ? 125000000/2 : 125000000; -localparam clk_in_min_period = (DIVIDE_CLK_IN_BY_2=="TRUE") ? 2000000/2 : 2000000; - -localparam vco_max_period = 1250000; -localparam vco_min_period = 312000; - -time clk_in_period = 0; -time old_clk_in_period = 0; -time clk_in_start; -time vco_period = vco_max_period; - -reg pll_start = 1'b0; -reg vco_clk_start = 1'b0; -reg clk_out_start = 1'b0; -integer vco_count = (PLL_MULT*PLL_DIV*2); -integer div3_count = 1; -reg [3:0] clk_in_count = 4'h0; -reg [3:0] old_clk_in_count = 4'h0; - -always begin - LOCK = 1'b0; - pll_start = 1'b0; - clk_in_period = 0; - clk_in_count = 4'h0; - old_clk_in_count = 4'h0; - vco_period = 1250000; - vco_clk_start = 1'b0; - clk_out_start = 1'b0; - div3_count = 1; - vco_count = (PLL_MULT*PLL_DIV*2); - SERDES_FAST_CLK = 1'b0; - CLK_OUT = 1'b0; - CLK_OUT_DIV2 = 1'b0; - CLK_OUT_DIV3 = 1'b0; - CLK_OUT_DIV4 = 1'b0; - #100; - if (PLL_EN) begin - pll_start = 1'b1; - @(negedge PLL_EN, negedge LOCK); - end else - @(posedge PLL_EN); -end - -always @(posedge pll_start) begin - repeat(9) - @(posedge CLK_IN); - vco_clk_start = 1'b1; - repeat (10) - @(posedge SERDES_FAST_CLK); - @(posedge CLK_IN); - clk_out_start = 1'b1; - repeat (5) - @(posedge CLK_OUT); - LOCK = 1'b1; -end - -always - if (vco_clk_start) begin - if (vco_count==(PLL_MULT*PLL_DIV*2)) begin - SERDES_FAST_CLK = 1'b0; - @(posedge CLK_IN); - vco_count = 1; - end else begin - SERDES_FAST_CLK = ~SERDES_FAST_CLK; - #(vco_period/2); - vco_count = vco_count + 1; - end - end else begin - SERDES_FAST_CLK = 1'b0; - @(posedge CLK_IN); - end +localparam FAST_LOCK = 0; // Reduce lock time -always @(posedge SERDES_FAST_CLK) begin - if (clk_out_start) begin - CLK_OUT = ~CLK_OUT; - repeat ((PLL_POST_DIV/2)-1) - @(posedge SERDES_FAST_CLK); - end else begin - CLK_OUT = 1'b0; - end -end - -always @(posedge CLK_OUT) - CLK_OUT_DIV2 = ~CLK_OUT_DIV2; - -always @(CLK_OUT) - if (div3_count==2) begin - CLK_OUT_DIV3 = ~CLK_OUT_DIV3; - div3_count = 0; - end else - div3_count = div3_count + 1; - -always @(posedge CLK_OUT_DIV2) - CLK_OUT_DIV4 = ~CLK_OUT_DIV4; - -always @(posedge CLK_IN) - if (pll_start) begin - clk_in_start = $realtime; - if (LOCK) - clk_in_count = clk_in_count + 1'b1; - - @(posedge CLK_IN); - if (clk_in_period == 0) - old_clk_in_period = $realtime - clk_in_start; - else - old_clk_in_period = clk_in_period; - - clk_in_period = $realtime - clk_in_start; - vco_period = clk_in_period * div_input_clk * PLL_DIV / PLL_MULT; - clk_in_start = $realtime; - if (LOCK) - clk_in_count = clk_in_count + 1'b1; - if (clk_in_period < clk_in_min_period) begin - $display("Warning at time %t: PLL instance %m input clock, CLK_IN, is too fast.", $realtime); - LOCK = 1'b0; - end - if (clk_in_period > clk_in_max_period) begin - $display("Warning at time %t: PLL instance %m input clock, CLK_IN, is too slow.", $realtime); - LOCK = 1'b0; - end - if ((LOCK==1'b1) && (clk_in_period > old_clk_in_period*1.05) || (clk_in_period < old_clk_in_period*0.95)) begin - $display("Warning at time %t: PLL instance %m input clock, CLK_IN, changed frequency and lost lock.", $realtime); - LOCK = 1'b0; - end - end + localparam real REF_MAX_PERIOD = PLL_MULT_FRAC ? 100000: 200000; //10 MHz or 5 MHz + localparam real REF_MIN_PERIOD = 833.33 ; //1200 MHz + + localparam real VCO_MAX_PERIOD = 62500; //16 MHz + localparam real VCO_MIN_PERIOD = 312.5; //3200 MHz + + + localparam LOCK_TIMER = FAST_LOCK ? 10 : 500; + + logic [ 2:0] PLL_POST_DIV0; + logic [ 2:0] PLL_POST_DIV1; + + assign PLL_POST_DIV0 = PLL_POST_DIV[2:0]; + assign PLL_POST_DIV1 = PLL_POST_DIV[6:4]; +//--------------------------- + real t0 ; + real t1 ; + real ref_period ; + real vco_period ; + real postdiv_period ; + real old_ref_period ; + logic clk_pll ; + logic pllen_rse ; + logic pllstart = 0; + logic pllstart_ff1 = 0; + logic pllstart_ff2 = 0; + logic vcostart = 0; + logic vcostart_ff = 0; + logic lose_lock = 0; + logic clk_out_div2 = 0; + logic clk_out_div3 = 0; + logic clk_out_div4 = 0; + logic clk_vco ; + logic clk_postdiv ; + integer div3_count = 1; + logic [ 5:0] PLL_DIV_ff = 0; + logic [11:0] PLL_MULT_ff = 0; + + logic [$clog2(LOCK_TIMER)-1:0] lock_counter = 0; + + + assign pllen_rse = pllstart==1 && pllstart_ff2==0; + + always @ (posedge CLK_IN) begin + if(PLL_EN) pllstart <= 1; + else pllstart <= 0; + + pllstart_ff1 <= pllstart; + pllstart_ff2 <= pllstart_ff1; + + end + + always @ (posedge CLK_IN) begin + if(pllstart_ff2) vcostart <= 1; + else vcostart <= 0; + + vcostart_ff <= vcostart; + end + + + always @ (posedge CLK_IN) begin + @(posedge CLK_IN) t0 = $realtime; + @(posedge CLK_IN) t1 = $realtime; + ref_period = t1 - t0; + vco_period = DIVIDE_CLK_IN_BY_2=="TRUE" ? (ref_period*PLL_DIV*2)/PLL_MULT : (ref_period*PLL_DIV)/PLL_MULT; + postdiv_period = DIVIDE_CLK_IN_BY_2=="TRUE" ? (ref_period*PLL_DIV*2*PLL_POST_DIV0*PLL_POST_DIV1)/PLL_MULT : (ref_period*PLL_DIV*PLL_POST_DIV0*PLL_POST_DIV1)/PLL_MULT; + end + + always @ (posedge CLK_IN) begin + old_ref_period = ref_period; + end + + initial begin + clk_vco = 0; + forever begin + wait(vcostart_ff) + #(vco_period/2) clk_vco = PLL_EN ? ~clk_vco : '0; + end + end -// Checking for proper CLK_IN and VCO frequencies -always - if (LOCK) begin - #(5*clk_in_period); - if (clk_in_count == old_clk_in_count) begin - $display("Warning at time %t: PLL instance %m input clock, CLK_IN, has stopped.", $realtime); - LOCK = 1'b0; - end else - old_clk_in_count = clk_in_count; - if (vco_periodvco_max_period) begin - $display("\nError at time %t: PLL instance %m VCO clock period %0d fs violates maximum period.\nMust be less than %0d fs.\nTry increasing PLL_MULT or decreasing PLL_DIV values.\n", $realtime, vco_period, vco_max_period); - $stop; - end - end else - @(posedge LOCK); initial begin - - if (int'(1fs) == 1) begin - $display(""); - end - else begin - $display("\n** Error: The timescale for PLL must be set to 1fs/1fs **\n"); - #1 $stop; + clk_postdiv = 0; + forever begin + wait(vcostart_ff) + #(postdiv_period/2) clk_postdiv = PLL_EN ? ~clk_postdiv : '0; end - end + end + + + always @(posedge CLK_IN) begin + PLL_DIV_ff <= PLL_DIV; + PLL_MULT_ff <= PLL_MULT; + end + + always @ (posedge CLK_IN, negedge PLL_EN) begin + if(LOCK==0 & vcostart) lock_counter <= lock_counter + 1; + else if(lose_lock || PLL_EN==0 || PLL_MULT_ff!=PLL_MULT || PLL_DIV_ff!=PLL_DIV ) lock_counter <= 0; + end + + + always @(posedge CLK_OUT, negedge PLL_EN) + if(PLL_EN==0) clk_out_div2 = 1'b0; + else clk_out_div2 = ~clk_out_div2; + + always @(CLK_OUT, negedge PLL_EN) + if(PLL_EN==0) clk_out_div3 = 1'b0; + else begin + if (div3_count==2) begin + clk_out_div3 = ~clk_out_div3; + div3_count = 0; + end else + div3_count = div3_count + 1; + end + + always @(posedge clk_out_div2, negedge PLL_EN) + if(PLL_EN==0) clk_out_div4 = 1'b0; + else clk_out_div4 = ~clk_out_div4; + + + assign CLK_OUT = (PLL_POST_DIV0==1 && PLL_POST_DIV0==1) ? clk_vco : clk_postdiv; + assign CLK_OUT_DIV2 = clk_out_div2; + assign CLK_OUT_DIV3 = clk_out_div3; + assign CLK_OUT_DIV4 = clk_out_div4; + assign FAST_CLK = clk_vco; + assign LOCK = lock_counter >= LOCK_TIMER; + + + + // Checking for proper CLK_IN and VCO frequencies + always @ (posedge CLK_IN) begin + if(pllstart_ff2)begin + if (ref_periodVCO_MAX_PERIOD) begin + $display("\nError at time %t: PLL instance %m REF clock period %0d fs violates maximum period.\nMust be less than %0d fs.\n", $realtime, ref_period, VCO_MAX_PERIOD); + $stop; + end + end + end + + + always @ (posedge CLK_IN) begin + if ((LOCK==1'b1) && (ref_period > old_ref_period*1.05) || (ref_period < old_ref_period*0.95)) begin + $display("Warning at time %t: PLL instance %m input clock, CLK_IN, changed frequency and lost lock. Current value = %0d fs, old value = %d fs.\n", $realtime, ref_period, old_ref_period); + lose_lock = 1; + end + else lose_lock = 0; + end + + always @ (posedge FAST_CLK) begin + if(vcostart_ff) begin + if (vco_periodVCO_MAX_PERIOD) begin + $display("\nError at time %t: PLL instance %m VCO clock period %0d fs violates maximum period.\nMust be less than %0d fs.\nTry increasing PLL_MULT or decreasing PLL_DIV values.\n", $realtime, vco_period, VCO_MAX_PERIOD); + $stop; + end + end + end + + + + // Checking control inputs + always @ (posedge CLK_IN, posedge PLL_EN) begin + if(PLL_EN)begin + if(PLL_POST_DIV0==0)begin + $display("Error at time %t: \n \t PLL instance %m, PLL_POST_DIV0 is equal to zero.\n \t Must be greater than 0", $realtime); + $stop; + end + + else if(PLL_POST_DIV1==0)begin + $display("Error at time %t: \n \t PLL instance %m, PLL_POST_DIV1 is equal to zero.\n \t Must be greater than 0", $realtime); + $stop; + end + + + else if(PLL_POST_DIV1>PLL_POST_DIV0) begin + $display("Error at time %t: PLL_POST_DIV1 > PLL_POST_DIV0\n", $realtime); + $stop; + end + end + end + initial begin + case(DEV_FAMILY) + "VIRGO": begin end + default: begin + $display("\nError: PLL instance %m has parameter DEV_FAMILY set to %s. Valid values are VIRGO\n", DEV_FAMILY); + #1 $stop ; + end + endcase case(DIVIDE_CLK_IN_BY_2) "TRUE" , "FALSE": begin end @@ -190,8 +232,8 @@ always end endcase - if ((PLL_MULT < 16) || (PLL_MULT > 1000)) begin - $display("PLL instance %m PLL_MULT set to incorrect value, %d. Values must be between 16 and 1000.", PLL_MULT); + if ((PLL_MULT < 16) || (PLL_MULT > 640)) begin + $display("PLL instance %m PLL_MULT set to incorrect value, %d. Values must be between 16 and 640.", PLL_MULT); #1 $stop; end @@ -199,34 +241,44 @@ always $display("PLL instance %m PLL_DIV set to incorrect value, %d. Values must be between 1 and 63.", PLL_DIV); #1 $stop; end + case(PLL_MULT_FRAC) + 0: begin end + default: begin + $display("\nError: PLL instance %m has parameter PLL_MULT_FRAC set to %d. Valid values are 0\n", PLL_MULT_FRAC); + #1 $stop ; + end + endcase case(PLL_POST_DIV) - 2 , - 4 , - 6 , - 8 , - 10 , - 12 , - 14 , - 16 , + 17 , 18 , + 19 , 20 , - 24 , - 28 , - 30 , - 32 , + 21 , + 22 , + 23 , + 34 , + 35 , 36 , - 40 , - 42 , - 48 , - 50 , - 56 , - 60 , + 37 , + 38 , + 39 , + 51 , + 52 , + 53 , + 54 , + 55 , + 68 , + 69 , 70 , - 72 , - 84 , - 98: begin end + 71 , + 85 , + 86 , + 87 , + 102 , + 103 , + 119: begin end default: begin - $display("\nError: PLL instance %m has parameter PLL_POST_DIV set to %d. Valid values are 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 24, 28, 30, 32, 36, 40, 42, 48, 50, 56, 60, 70, 72, 84, 98\n", PLL_POST_DIV); + $display("\nError: PLL instance %m has parameter PLL_POST_DIV set to %d. Valid values are 17, 18, 19, 20, 21, 22, 23, 34, 35, 36, 37, 38, 39, 51, 52, 53, 54, 55, 68, 69, 70, 71, 85, 86, 87, 102, 103, 119\n", PLL_POST_DIV); #1 $stop ; end endcase