//******************************************************************** 
// -------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>Copyright Notice<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
// ------------------------------------------------------------------- 
// Author: chenzhizhao
// Date:
// Module name: ts_logic_delay 
// Description: Used in APUG065 and APUG104, 
// 				to generate ts_logic_delay signal for stateio_wrapper module.
//  
//-------------------------------------------------------------------- 
// Revision History : 
//-------------------------------------------------------------------- 
// v1.0: 2026.08.04   / original version 
// v1.1: 2026.08.07   / add logic_osc_div
//
//
//-------------------------------------------------------------------- 
//*******************************************************************/ 

`timescale 1ns / 1ns 

module ts_logic_delay
#(parameter
    DEVICE = "EF5" //"EF2", "EF3L15_45_40_90", "EF3L50_70_A0", "EF4", "EF5"
)(
	output  logic_delay,
    input rstn,
    input stdby,
    input [6:0] div,   // [template:Freq dividing coefficients, divided by 8: div = 7'b111]
    output clko        // [tag:clk]
);  

//generate osc_div_clk
wire osc_div_clk;
wire osc_div_clk_out;

//generate logic_delay
wire [10:0] logic_delay_ff;

//generate logic_osc_div, if users need
reg        clkinven = 0;
reg 	   clkdivrst;
reg  [6:0] divnum;
wire [6:0] div_reg;
wire [6:0] divh;
wire [6:0] divm2;
wire 	   clkreg;
wire       diveqreg0;
wire       diveqreg1;
wire       diveqreg2;
wire       diveqreg3;
wire diveq0 = div_reg[1:0] ==divm2[1:0];
wire diveq1 = div_reg[3:2] ==divm2[3:2];
wire diveq2 = div_reg[5:4] ==divm2[5:4];
wire diveq3 = div_reg[6  ] ==divm2[6  ];
wire       diveqreg;
wire       clkdiv2;
wire [3:0] diva1,diva1_reg;
wire [2:0] diva2,diva2_reg;
wire a1 = diva1_reg==4'b1111;
wire       logic_clko;
wire       div0,div1,div2;
wire       clkdiv3,clko0,clko1;

//generate osc_div_clk
generate
if(DEVICE == "EF5")begin
    EF5_PHY_OSC inst_osc(
        .stdby(1'b1),
        .sel(1'b0),
        .trim()
    );
    EF5_PHY_OSCDIV inst_osc_div(
        .rstn(1'b1),
        .stdby(1'b0),
        .div(7'd0),
        .clko(osc_div_clk)
    );
    EF5_PHY_GCLK u_bufg_oscdiv(.clki(osc_div_clk), .clko(osc_div_clk_out));
    EF5_PHY_GCLK u_bufg_logic_clk(.clki(logic_clko), .clko(clko));
end
else if(DEVICE == "EF3L50_70_A0")begin 
    EF3_PHY_OSC_V2 inst_osc(
        .osc_dis(1'b0),
        .osc(),
        .sel(1'b0),
        .trim()
    );
    EF3_PHY_OSCDIV inst_osc_div(
        .rstn(1'b1),
        .stdby(1'b0),
        .div(7'd0),
        .clko(osc_div_clk)
    );
    EF3_PHY_GCLK u_bufg_oscdiv(.clki(osc_div_clk), .clko(osc_div_clk_out));
    EF3_PHY_GCLK u_bufg_logic_clk(.clki(logic_clko), .clko(clko));
end
else if(DEVICE == "EF3L15_45_40_90")begin 
    EF3_PHY_OSC inst_osc(
        .stdby(1'b1),
        .osc()
    );
    EF3_PHY_OSCDIV inst_osc_div(
        .rstn(1'b1),
        .stdby(1'b0),
        .div(7'd0),
        .clko(osc_div_clk)
    );
    EF3_PHY_GCLK u_bufg_oscdiv(.clki(osc_div_clk), .clko(osc_div_clk_out));
    EF3_PHY_GCLK u_bufg_logic_clk(.clki(logic_clko), .clko(clko));
end
else if(DEVICE == "EF2")begin 
    EF2_PHY_OSC inst_osc(
        .stdby(1'b1),
        .osc()
    );
    EF2_PHY_OSCDIV inst_osc_div(
        .rstn(1'b1),
        .stdby(1'b0),
        .div(7'd0),
        .clko(osc_div_clk)
    );
    EF2_PHY_GCLK u_bufg_oscdiv(.clki(osc_div_clk), .clko(osc_div_clk_out));
    EF2_PHY_GCLK u_bufg_logic_clk(.clki(logic_clko), .clko(clko));
end
else if(DEVICE == "EF4")begin 
    EF4_PHY_OSC inst_osc(
        .osc_dis(1'b0),
        .osc(),
        .sel(1'b0),
        .trim()
    );
    EF4_PHY_OSCDIV inst_osc_div(
        .rstn(1'b1),
        .stdby(1'b0),
        .div(7'd0),
        .clko(osc_div_clk)
    );
    EF4_PHY_GCLK u_bufg_oscdiv(.clki(osc_div_clk), .clko(osc_div_clk_out));
    EF4_PHY_GCLK u_bufg_logic_clk(.clki(logic_clko), .clko(clko));
end
endgenerate

//generate logic_delay
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff0  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(1'b1), 				.q(logic_delay_ff[0])	);
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff1  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(logic_delay_ff[0] ),	.q(logic_delay_ff[1])	);
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff2  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(logic_delay_ff[1] ),	.q(logic_delay_ff[2])	);
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff3  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(logic_delay_ff[2] ),	.q(logic_delay_ff[3])	);
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff4  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(logic_delay_ff[3] ),	.q(logic_delay_ff[4])	);
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff5  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(logic_delay_ff[4] ),	.q(logic_delay_ff[5])	);
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff6  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(logic_delay_ff[5] ),	.q(logic_delay_ff[6])	);
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff7  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(logic_delay_ff[6] ),	.q(logic_delay_ff[7])	);
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff8  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(logic_delay_ff[7] ),	.q(logic_delay_ff[8])	);
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff9  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(logic_delay_ff[8] ),	.q(logic_delay_ff[9])	);
AL_MAP_SEQ #(.GSR("DISABLE")) u_dff10 (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(logic_delay_ff[9] ),	.q(logic_delay_ff[10])	);
assign logic_delay = logic_delay_ff[10];


//generate logic_osc_div, if users need
assign divm2=div-2;
assign divh = (div-1)>>1;
assign diva1[3:0] = (diva1_reg + 1'b1);
assign diva2[2:0] = diva2_reg + a1;
always@(*)begin
    clkdivrst = diveqreg0&diveqreg1&diveqreg2&diveqreg3;
    divnum = {diva2_reg,diva1_reg};
end

AL_MAP_SEQ  u_diva1_dff0  (.ce(1'b1), .clk(osc_div_clk_out), .sr(clkdivrst), .d(diva1[0] ), .q(diva1_reg[0])	);
AL_MAP_SEQ  u_diva1_dff1  (.ce(1'b1), .clk(osc_div_clk_out), .sr(clkdivrst), .d(diva1[1] ), .q(diva1_reg[1])	);
AL_MAP_SEQ  u_diva1_dff2  (.ce(1'b1), .clk(osc_div_clk_out), .sr(clkdivrst), .d(diva1[2] ), .q(diva1_reg[2])	);
AL_MAP_SEQ  u_diva1_dff3  (.ce(1'b1), .clk(osc_div_clk_out), .sr(clkdivrst), .d(diva1[3] ), .q(diva1_reg[3])	);
AL_MAP_SEQ  u_diva2_dff0  (.ce(1'b1), .clk(osc_div_clk_out), .sr(clkdivrst), .d(diva2[0] ), .q(diva2_reg[0])	);
AL_MAP_SEQ  u_diva2_dff1  (.ce(1'b1), .clk(osc_div_clk_out), .sr(clkdivrst), .d(diva2[1] ), .q(diva2_reg[1])	);
AL_MAP_SEQ  u_diva2_dff2  (.ce(1'b1), .clk(osc_div_clk_out), .sr(clkdivrst), .d(diva2[2] ), .q(diva2_reg[2])	);
AL_MAP_SEQ  #(.REGSET("SET")) u_diveq0_dff (.ce(1'b1), .clk(osc_div_clk_out), .sr(stdby|~rstn), .d(div0|diveq0 ), .q(diveqreg0)	);
AL_MAP_SEQ  #(.REGSET("SET")) u_diveq1_dff (.ce(1'b1), .clk(osc_div_clk_out), .sr(stdby|~rstn), .d(div0|diveq1 ), .q(diveqreg1)	);
AL_MAP_SEQ  #(.REGSET("SET")) u_diveq2_dff (.ce(1'b1), .clk(osc_div_clk_out), .sr(stdby|~rstn), .d(div0|diveq2 ), .q(diveqreg2)	);
AL_MAP_SEQ  #(.REGSET("SET")) u_diveq3_dff (.ce(1'b1), .clk(osc_div_clk_out), .sr(stdby|~rstn), .d(div0|diveq3 ), .q(diveqreg3)	);

AL_MAP_SEQ  u_div_dff0  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(divnum[0] ), .q(div_reg[0])	);
AL_MAP_SEQ  u_div_dff1  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(divnum[1] ), .q(div_reg[1])	);
AL_MAP_SEQ  u_div_dff2  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(divnum[2] ), .q(div_reg[2])	);
AL_MAP_SEQ  u_div_dff3  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(divnum[3] ), .q(div_reg[3])	);
AL_MAP_SEQ  u_div_dff4  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(divnum[4] ), .q(div_reg[4])	);
AL_MAP_SEQ  u_div_dff5  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(divnum[5] ), .q(div_reg[5])	);
AL_MAP_SEQ  u_div_dff6  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(divnum[6] ), .q(div_reg[6])	);
AL_MAP_SEQ  u_clk_dff   (.ce(1'b1), .clk(osc_div_clk_out), .sr(clkdivrst), .d(div_reg<=divh), .q(clkreg));
AL_MAP_SEQ  u_clkdiv2   (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(~clkdiv2), .q(clkdiv2));
AL_MAP_SEQ  u_clkdiv30  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(({clko1,clko0}==2'b11 ? 1'b0 : 1'b1)), .q(clko0));
AL_MAP_SEQ  u_clkdiv31  (.ce(1'b1), .clk(osc_div_clk_out), .sr(1'b0), .d(clko0), .q(clko1));
assign clkdiv3 = clko0;
assign div0 = div=='d0;
assign div1 = div=='d1;
assign div2 = div=='d2;
assign divot=~(div0|div1|div2);
assign logic_clko = (div0 & osc_div_clk_out) | (div1 & clkdiv2) | (div2 & clkdiv3) | ( divot & clkreg);

endmodule