dakies/OSS_Verilog huggingface dataset:
module ipsxb_seu_rs232_intf
#(
    parameter CLK_DIV_P     = 16'd145    ,
    parameter FIFO_D        = 1024      
)
(
    input               clk                        ,
    input               rst_n                      ,

    input       [31:0]  tx_fifo_wr_data,
    output reg          tx_fifo_wr_data_valid,
    input               tx_fifo_wr_data_req,

    output      [7:0]   rx_fifo_rd_data            ,
    output              rx_fifo_rd_data_valid      ,
    input               rx_fifo_rd_data_req        ,

    output              txd                        ,
    input               rxd
);

wire            clk_en;

wire            tx_fifo_rd_data_req;
wire    [31:0]  tx_fifo_rd_data;
wire            tx_fifo_rd_data_valid;

wire            rx_fifo_wr_data_req;
wire    [7:0]   rx_fifo_wr_data;
reg             rx_fifo_wr_data_valid;

assign rx_fifo_rd_data       = rx_fifo_wr_data;
assign rx_fifo_rd_data_valid = ~rx_fifo_wr_data_valid;

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        rx_fifo_wr_data_valid <= 1'b1;
    else if(rx_fifo_wr_data_req)
        rx_fifo_wr_data_valid <= 1'b0;
    else if(rx_fifo_rd_data_req)
        rx_fifo_wr_data_valid <= 1'b1;
    else;
end

assign tx_fifo_rd_data       = tx_fifo_wr_data;
assign tx_fifo_rd_data_valid = ~tx_fifo_wr_data_valid;

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        tx_fifo_wr_data_valid <= 1'b1;
    else if(tx_fifo_wr_data_req)
        tx_fifo_wr_data_valid <= 1'b0;
    else if(tx_fifo_rd_data_req)
        tx_fifo_wr_data_valid <= 1'b1;
    else;
end

ipsxb_clk_gen_32bit u_ipsxb_clk_gen(
    .clk                        (clk                            ),
    .rst_n                      (rst_n                          ),

    .clk_div                    (CLK_DIV_P                      ),
    .clk_en                     (clk_en                         )
);

ipsxb_seu_uart_tx u_ipsxb_seu_uart_tx(
    .clk                        (clk                            ),
    .clk_en                     (clk_en                         ),
    .rst_n                      (rst_n                          ),

    .tx_fifo_rd_data            (tx_fifo_rd_data                ),
    .tx_fifo_rd_data_valid      (tx_fifo_rd_data_valid          ),
    .tx_fifo_rd_data_req        (tx_fifo_rd_data_req            ),

    .txd                        (txd                            )
);

ipsxb_seu_uart_rx u_ipsxb_seu_uart_rx(
    .clk                        (clk                            ),
    .rst_n                      (rst_n                          ),
    .clk_en                     (clk_en                         ),

    .rx_fifo_wr_data            (rx_fifo_wr_data                ),
    .rx_fifo_wr_data_valid      (rx_fifo_wr_data_valid          ),
    .rx_fifo_wr_data_req        (rx_fifo_wr_data_req            ),

    .rxd_in                     (rxd                            )
);

endmodule
module ipsxb_clk_gen_32bit(
    input           clk,
    input           rst_n,

    input   [15:0]  clk_div,
    output  reg     clk_en  // divided from baud
);

reg     [15:0] cnt;

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        cnt <= 16'b0;
    else if(cnt == (clk_div - 16'd1))
        cnt <= 16'b0;
    else
        cnt <= cnt + 16'b1;
end

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        clk_en <= 1'b0;
    else
        clk_en <= cnt == (clk_div - 16'd1);
end


endmodule //pgr_clk_gen
module ipsxb_seu_uart_rx(
    input              clk                     ,
    input              rst_n                   ,
    input              clk_en                  ,

    output reg  [7:0]  rx_fifo_wr_data         ,
    input              rx_fifo_wr_data_valid   ,
    output wire        rx_fifo_wr_data_req     ,

    input              rxd_in
);

reg  [1:0]   rxd_d               ;
reg  [2:0]   rxd_tmp             ;
reg          rxd_r1              ;
reg          rxd_r2              ;
wire         rxd                 ;
wire         rxd_neg             ;
reg          in_cyc              ;
reg  [3:0]   rx_cnt              ;
reg  [2:0]   cnt                 ;
wire         rx_over             ;
wire         rx_sample           ;
reg          rx_req              ;

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        rxd_d <= 2'b11;
    else
        rxd_d <= {rxd_d[0],rxd_in};
end

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        rxd_tmp <= 3'b111;
    else if(clk_en)
        rxd_tmp <= {rxd_tmp[1:0],rxd_d[1]};
    else;
end

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        rxd_r1 <= 1'b1;
    else if(clk_en)
    begin
        if(rxd_tmp == 3'b111)
            rxd_r1 <= 1'b1;
        else if(rxd_tmp == 3'b000)
            rxd_r1 <= 1'b0;
        else;
    end
end

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        rxd_r2 <= 1'b1;
    else if(clk_en)
        rxd_r2 <= rxd_r1;
end

assign rxd = rxd_r2;
assign rxd_neg = rxd_r2 & ~rxd_r1;

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        in_cyc <= 1'b0;
    else if(clk_en)
    begin
        if(rxd_neg)
            in_cyc <= 1'b1;
        else if(rx_over && rx_sample)
            in_cyc <= 1'b0;
    end
end

assign cnt_down  = cnt == 3'd5;
assign rx_sample = cnt == 3'd2;

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        cnt <= 3'b0;
    else if(clk_en)
    begin
        if(cnt_down)
            cnt <= 3'b0;
        else if(~in_cyc)
            cnt <= 3'b0;
        else
            cnt <= cnt + 3'b1;
    end
end

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
    begin
        rx_fifo_wr_data <= 8'b0;
        rx_cnt <= 4'd9;
    end
    else if(clk_en)
    begin
        if(~in_cyc)
        begin
            rx_fifo_wr_data <= 8'b0;
            rx_cnt <= 4'd9;
        end
        else if(rx_sample)
        begin
            rx_fifo_wr_data <= {rxd,rx_fifo_wr_data[7:1]};
            rx_cnt <= rx_cnt + 4'hf; // rx_cnt = rx_cnt - 1;
        end
    end
end

assign rx_over = rx_cnt == 4'd1;

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        rx_req <= 1'b0;
    else if(clk_en)
    begin
        if(rx_sample && rx_over)
            rx_req <= 1'b1;
    end
    else
        rx_req <= 1'b0;
end

assign rx_fifo_wr_data_req = rx_req && rx_fifo_wr_data_valid;

endmodule
module ipsl_pcie_sync_v1_0 (
    input                  clk,
    input                  rst_n,

    input                  sig_async,
    output reg             sig_synced
);

reg                      sig_async_ff;

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        sig_async_ff <= 1'b0;
    else
        sig_async_ff <= sig_async;
end

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        sig_synced <= 1'b0;
    else
        sig_synced <= sig_async_ff;
end

endmodule
module ipsl_pcie_apb2dbi_v1_0 (
    input                       pclk_div2               ,
    input                       apb_rst_n               ,
    input                       p_sel                   ,
    input           [ 3:0]      p_strb                  ,
    input           [15:0]      p_addr                  , // dbi use [11:2]
    input           [31:0]      p_wdata                 ,
    input                       p_ce                    ,
    input                       p_we                    ,
    output  reg                 p_rdy                   ,
    output  reg     [31:0]      p_rdata                 ,
    output  reg     [31:0]      dbi_addr                ,
    output  reg     [31:0]      dbi_din                 ,
    output  reg                 dbi_cs                  ,
    output  reg                 dbi_cs2                 ,
    output  reg     [ 3:0]      dbi_wr                  ,
    output  reg                 app_dbi_ro_wr_disable   ,
    input                       lbc_dbi_ack             ,
    input           [31:0]      lbc_dbi_dout            ,
    input                       dbi_halt
);

wire        apb_access  ;
wire        dbi_standby ;

assign dbi_standby = !(dbi_cs || lbc_dbi_ack);
assign apb_access = (p_sel && p_ce && !p_rdy);

always @(posedge pclk_div2 or negedge apb_rst_n) begin
    if (!apb_rst_n)
    begin
        app_dbi_ro_wr_disable <= 1'd0;
        dbi_cs2  <= 1'b0;
        dbi_cs   <= 1'b0;
        dbi_addr <= 32'd0;
        dbi_din  <= 32'd0;
    end
    else if (apb_access && dbi_standby)
    begin
        if (p_addr[1])
            app_dbi_ro_wr_disable <= 1'b1;

        if (p_addr[0])
            dbi_cs2 <= 1'b1;
        else
            dbi_cs2 <= 1'b0;

        dbi_cs   <= 1'b1;
        dbi_addr <= {20'd0,p_addr[11:2],2'd0};
        dbi_din  <= p_wdata;

    end
    else if (lbc_dbi_ack)
    begin
        dbi_cs  <= 1'b0;
        dbi_cs2 <= 1'b0;
    end
    else
        app_dbi_ro_wr_disable <= 1'b0;
end

always @(posedge pclk_div2 or negedge apb_rst_n) begin
    if (!apb_rst_n)
        dbi_wr <= 4'd0;
    else if (dbi_standby && apb_access && p_we)
        dbi_wr <= p_strb;
    else
        dbi_wr <= 4'd0;
end

always @(posedge pclk_div2 or negedge apb_rst_n) begin
    if (!apb_rst_n)
    begin
        p_rdy <= 1'b0;
        p_rdata <= 32'd0;
    end
    else if (!dbi_cs && lbc_dbi_ack && p_sel && p_ce)
    begin
        if (!dbi_halt)
            p_rdy <= 1'b1;
        else
            p_rdy <= 1'b0;

        if (!p_we)
            p_rdata <= lbc_dbi_dout;
    end
    else
        p_rdy <= 1'b0;
end

endmodule
module ipsl_pcie_seio_intf_v1_0(
    input               pclk_div2   ,
    input               user_rst_n  ,

    input               sedo_in     ,
    input               sedo_en_in  ,
    output  wire        sedi        ,
    output  reg         sedi_ack
);

    reg     [1:0]   seio_state      ;
    reg     [1:0]   seio_nxt_state  ;
    reg             sedo_in_r       ;
    reg             sedo_in_2r      ;
    reg             sedo_en_r       ;
    reg             sedo_en_2r      ;

    localparam      SEIO_IDLE   = 2'b00;
    localparam      SEIO_BUSY   = 2'b01;
    localparam      SEIO_NACK   = 2'b10;

assign sedi = 1'b0;

//----------------PHASE1
always @(posedge pclk_div2  or negedge user_rst_n)
    if(!user_rst_n)
        seio_state  <= SEIO_IDLE;
    else
        seio_state  <= seio_nxt_state;

//----------------PHASE2
always@(*)
    case(seio_state)
        SEIO_IDLE:begin
            if(sedo_en_2r & sedo_in_r & ~sedo_in_2r)         //WR OP
                seio_nxt_state = SEIO_BUSY;
            else if(sedo_en_2r & ~sedo_in_r & sedo_in_2r)    //RD OP
                seio_nxt_state = SEIO_BUSY;
            else
                seio_nxt_state = SEIO_IDLE;
        end
        SEIO_BUSY:begin
            if(sedo_en_2r & ~sedo_en_r)         //falling edge of sedo_en
                seio_nxt_state = SEIO_NACK;
            else
                seio_nxt_state = SEIO_BUSY;
        end
        SEIO_NACK:begin
            if(sedi_ack)
                seio_nxt_state = SEIO_IDLE;
            else
                seio_nxt_state = SEIO_NACK;
        end
        default:seio_nxt_state = SEIO_IDLE;
    endcase

//------------------------------SEIO Logic
always @(posedge pclk_div2  or negedge user_rst_n)
    if(!user_rst_n)begin
        sedo_in_r   <= 1'b0;
        sedo_in_2r  <= 1'b0;
        sedo_en_r   <= 1'b0;
        sedo_en_2r  <= 1'b0;
    end
    else begin
        sedo_in_r   <= sedo_in;
        sedo_in_2r  <= sedo_in_r;
        sedo_en_r   <= sedo_en_in;
        sedo_en_2r  <= sedo_en_r;
    end

always @(posedge pclk_div2  or negedge user_rst_n)
    if(!user_rst_n)
        sedi_ack    <= 1'b0;
    else if(seio_state == SEIO_NACK)
        sedi_ack    <= ~sedi_ack;           //1 cycle pulse
    else
        sedi_ack    <= 1'b0;

endmodule
module rstn_sync_32bit(
    input          clk,
    input          rst_n,
    output  wire    sync_rst_n
);

reg  rst_n_ff1;
reg  rst_n_ff2;

always@(posedge clk or negedge rst_n)
begin
    if(~rst_n)
    begin
        rst_n_ff1 <= 1'b0;
        rst_n_ff2 <= 1'b0;
    end
    else
    begin
        rst_n_ff1 <= 1;
        rst_n_ff2 <= rst_n_ff1;
    end
end
    
assign sync_rst_n = rst_n_ff2;

endmodule
module pgr_fifo_top_32bit
#(
    parameter D = 16'd1024
)
(
    input               clk,
    input               rst_n,

    input       [7:0]   wr_data,
    input               wr_req,
    output              wr_ready,

    input               rd_req,
    output      [7:0]   rd_data,
    output              rd_valid
);

pgr_prefetch_fifo
#(
    .D                  (D                  ), //should be 2^N
    .W                  (8                  ),
    .TYPE               ("Distributed"      )  // "Distributed" or "DRM"
)
u_prefetch_fifo(
    .clk                (clk                ),
    .rst_n              (rst_n              ),

    .data_in_valid      (wr_req             ),
    .data_in            (wr_data            ),
    .data_in_ready      (wr_ready           ),

    .data_out_ready     (rd_req             ),
    .data_out           (rd_data            ),
    .data_out_valid     (rd_valid           )
);

endmodule //fifo
module pgr_clk_gen_32bit
#(
    parameter   CLK_FREQ    = 8'd50
)
(
    input           clk,
    input           rst_n,
    output  reg     clk_en  // divided from baud
);

reg     [15:0] cnt;

localparam CLK_DIV = (CLK_FREQ * 1000000 + 3 * 115200) / (6 * 115200) - 2;

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        cnt <= 16'b0;
    else if(clk_en)
        cnt <= 16'b0;
    else
        cnt <= cnt + 16'b1;
end

always @(posedge clk or negedge rst_n)
begin
    if(~rst_n)
        clk_en <= 1'b0;
    else
        clk_en <= (cnt == CLK_DIV);
end


endmodule //pgr_clk_gen
module ipsl_pcie_dma_rx_mwr_wr_ctrl #(
    parameter                           ADDR_WIDTH = 4'd9
)(
    input                               clk             ,   //gen1:62.5MHz,gen2:125MHz
    input                               rst_n           ,

    //**********************************************************************
    input                               i_mwr_wr_start  ,
    input           [9:0]               i_mwr_length    ,
    input           [7:0]               i_mwr_dwbe      ,
    input           [127:0]             i_mwr_data      ,
    input           [3:0]               i_mwr_dw_vld    ,
    input           [63:0]              i_mwr_addr      ,
    input           [1:0]               i_bar_hit       ,

    //**********************************************************************
    //ram write control
    output  wire                        o_mwr_wr_en     ,
    output  wire    [ADDR_WIDTH-1:0]    o_mwr_wr_addr   ,
    output  wire    [127:0]             o_mwr_wr_data   ,
    output  wire    [15:0]              o_mwr_wr_be     ,
    output  wire    [1:0]               o_mwr_wr_bar_hit
);

ipsl_pcie_dma_wr_ctrl #(
    .ADDR_WIDTH         (ADDR_WIDTH         )
)
ipsl_pcie_dma_mwr_wr_ctrl
(
    .clk                (clk                ),  //gen1:62.5MHz,gen2:125MHz
    .rst_n              (rst_n              ),

    //**********************************************************************
    .i_wr_start         (i_mwr_wr_start     ),
    .i_length           (i_mwr_length       ),
    .i_dwbe             (i_mwr_dwbe         ),
    .i_data             (i_mwr_data         ),
    .i_dw_vld           (i_mwr_dw_vld       ),
    .i_addr             (i_mwr_addr         ),
    .i_bar_hit          (i_bar_hit          ),

    //**********************************************************************
    //ram write control
    .o_wr_en            (o_mwr_wr_en       ),
    .o_wr_addr          (o_mwr_wr_addr     ),
    .o_wr_data          (o_mwr_wr_data     ),
    .o_wr_be            (o_mwr_wr_be       ),
    .o_wr_bar_hit       (o_mwr_wr_bar_hit  )
);

endmodule
module ipsl_pcie_dma_tx_cpld_rd_ctrl #(
    parameter                           ADDR_WIDTH  = 4'd9
)(
    input                               clk             ,   //gen1:62.5MHz,gen2:125MHz
    input                               rst_n           ,
    //**********************************************************************
    //ram interface
    input                               i_rd_en         ,
    input           [9:0]               i_rd_length     ,
    input           [63:0]              i_rd_addr       ,
    input                               i_cpld_tx_hold  ,
    input                               i_cpld_tlp_tx   ,

    output  wire                        o_gen_tlp_start ,
    output  wire    [127:0]             o_rd_data       ,
    output  wire                        o_last_data     ,
    //ram_rd
    output  wire                        o_bar_rd_clk_en ,
    output  wire    [ADDR_WIDTH-1:0]    o_bar_rd_addr   ,
    input           [127:0]             i_bar_rd_data
);

ipsl_pcie_dma_rd_ctrl #(
    .ADDR_WIDTH             (ADDR_WIDTH             )
)
u_ipsl_pcie_dma_cpld_rd_ctrl
(
    .clk                    (clk                    ),  //gen1:62.5MHz,gen2:125MHz
    .rst_n                  (rst_n                  ),
    //**********************************************************************
    //ram interface
    .i_rd_en                (i_rd_en                ),
    .i_rd_length            (i_rd_length            ),
    .i_rd_addr              (i_rd_addr              ),
    .i_tx_hold              (i_cpld_tx_hold         ),
    .i_tlp_tx               (i_cpld_tlp_tx          ),
    .o_rd_ram_hold          (                       ),//no use
    .o_gen_tlp_start        (o_gen_tlp_start        ),
    .o_rd_data              (o_rd_data              ),
    .o_last_data            (o_last_data            ),
    //ram_rd
    .o_bar_rd_clk_en        (o_bar_rd_clk_en        ),
    .o_bar_rd_addr          (o_bar_rd_addr          ),
    .i_bar_rd_data          (i_bar_rd_data          )
);

endmodule
module ipsl_pcie_reg #(
    parameter    SIG_WIDTH = 8
)(
    input                  clk,

    input       [SIG_WIDTH-1:0] sig,
    output reg  [SIG_WIDTH-1:0] sig_reg
);

always@(posedge clk)
begin
    sig_reg <= sig;
end
endmodule
module ipm_distributed_sdpram_v1_2
    #(
      parameter  ADDR_WIDTH          = 6               ,    //address width   range:4-10
      parameter  DATA_WIDTH          = 64              ,    //data width      range:1-256
      parameter  RST_TYPE            = "ASYNC"         ,    //reset type   "ASYNC" "SYNC"
      parameter  OUT_REG             = 0               ,    //output options :non_register(0)  register(1)
      parameter  INIT_FILE           = "NONE"          ,    //legal value:"NONE" or "initial file name"
      parameter  FILE_FORMAT         = "BIN"                //initial data format : "BIN" or "HEX"
     )
     (
      input   wire [DATA_WIDTH-1:0]       wr_data      ,
      input   wire [ADDR_WIDTH-1:0]       wr_addr      ,
      input   wire [ADDR_WIDTH-1:0]       rd_addr      ,
      input   wire                        wr_clk       ,
      input   wire                        rd_clk       ,
      input   wire                        wr_en        ,
      input   wire                        rst          ,
      output  wire [DATA_WIDTH-1:0]       rd_data
     )/* synthesis syn_ramstyle = "select_ram" */;

wire                                      asyn_rst     ;
wire                                      syn_rst      ;
wire  [DATA_WIDTH-1:0]                    q            ;
reg   [DATA_WIDTH-1:0]                    q_reg        ;

reg   [DATA_WIDTH-1:0]                    mem [2**ADDR_WIDTH-1:0];

//***********************************************************************reset*******************************************************************
assign  asyn_rst  = (RST_TYPE == "ASYNC") ? rst : 0;
assign  syn_rst   = (RST_TYPE == "SYNC" ) ? rst : 0;

//initialize sdpram
generate
    integer i,j;
    if (INIT_FILE != "NONE") begin
        if (FILE_FORMAT == "BIN") begin
            initial begin
                $readmemb(INIT_FILE,mem);
            end
        end
        else if (FILE_FORMAT == "HEX") begin
            initial begin
                $readmemh(INIT_FILE,mem);
            end
        end
    end
    else begin
        initial begin
            for (i=0;i<2**ADDR_WIDTH;i=i+1) begin
                for (j=0;j<DATA_WIDTH;j=j+1) begin
                    mem[i][j] = 1'b0;
                end
            end
        end
    end
endgenerate

//write & read
generate
    always @(posedge wr_clk) begin
        if(wr_en)
            mem[wr_addr] <= wr_data;
    end

    assign q = mem[rd_addr];

    if (RST_TYPE == "ASYNC") begin
        always@(posedge rd_clk or posedge asyn_rst)
        begin
            if(asyn_rst)
                q_reg <= {DATA_WIDTH{1'b0}};
            else
                q_reg <= q;
        end
    end
    else if (RST_TYPE == "SYNC") begin
        always@(posedge rd_clk)
        begin
            if(syn_rst)
                q_reg <= {DATA_WIDTH{1'b0}};
            else
                q_reg <= q;
        end
    end
endgenerate

assign rd_data = (OUT_REG == 1) ? q_reg : q;

endmodule
module pgr_prefetch_fifo
    #( 
       parameter D = 16, //should be 2^N
       parameter W = 8,
       parameter TYPE = "Distributed"  // "Distributed" or "DRM"
     )
    (
      input                     clk,
      input                     rst_n,

      input                     data_in_valid,
      input  [W-1:0]            data_in,
      output                    data_in_ready,

      input                     data_out_ready,
      output [W-1:0]            data_out,
      output                    data_out_valid
    );

//===================================================================
//     Type        |  Latency   |   ADDR_WIDTH   |   Data width
// "Distributed"   |    2       |      4~10      |     1~256
// "DRM"           |    3       |      9~20      |     1~1152
//===================================================================

reg                         fifo_vld;
reg                         rd_en_ff1;
reg  [2:0]                  shift_vld;
reg  [W-1:0]                rd_data_ff1;

wire [W-1:0]                rd_data;
wire                        pop;
wire                        wr_en;
wire                        rd_en;
wire                        empty;
wire                        full;
wire                        rst;

//
assign wr_en = data_in_valid & ~full;
assign data_in_ready = ~full;
assign rst = ~rst_n;

//
localparam DEPTH = (D < 16) ? 16 : D;
assign rd_en = ~empty & data_out_ready;
assign data_out_valid = fifo_vld;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        fifo_vld <= 1'b0;
    else if (rd_en)
        fifo_vld <= 1'b1;
    else
        fifo_vld <= 1'b0;
end

assign data_out = rd_data_ff1;
always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        rd_data_ff1 <= 1'b0;
    else if (rd_en)
        rd_data_ff1 <= rd_data;
end

// distributed_fifo
pgm_distributed_fifo_v1_1
    #(
      .DATA_WIDTH ( W           ),
      .ADDR_WIDTH ( log2(DEPTH) ),
      .OUT_REG    ( 0           ),
      .FIFO_TYPE  ( "SYNC_FIFO" )
     )
    pgm_distributed_fifo_v1_0
    (
    .wr_data        ( data_in  ),
    .wr_en          ( wr_en    ),
    .wr_clk         ( clk      ),
    .full           ( full     ),
    .wr_rst         ( rst      ),
    .almost_full    (          ),
    .wr_water_level (          ),
    .rd_data        ( rd_data  ),
    .rd_en          ( rd_en    ),
    .rd_clk         ( clk      ),
    .empty          ( empty    ),
    .rd_rst         ( rst      ),
    .rd_water_level (          ),
    .almost_empty   (          )
    );

// Log 2
function integer log2;
    input integer dep;
    begin
        log2 = 0;
        while (dep > 1)
        begin
            dep  = dep >> 1;
            log2 = log2 + 1;
        end
    end
endfunction

endmodule
module pgs_pciex4_fifo_v1_2 #(
  parameter  ADDR_WIDTH               = 10            ,  // fifo depth width 4 -- 10
  parameter  DATA_WIDTH               = 32            ,  // write data width 1 -- 256
  parameter  OUT_REG                  = 0
)
(
   input                               clk             ,  // input write clock
   input                               rst_n           ,  // input write reset

   input     [DATA_WIDTH-1 : 0]        wr_data         ,  // input write data
   input                               wr_en           ,  // input write enable 1 active
   output                              full            ,  // output write full  flag 1 active


   output    [DATA_WIDTH-1 : 0]        rd_data         ,  // output read data
   input                               rd_en           ,  // input  read enable
   output                              empty             // output read empty
);

 wire  [ADDR_WIDTH-1 : 0]  wr_addr         ;
 wire  [ADDR_WIDTH-1 : 0]  rd_addr         ;
 wire                      wr_en_tmp       ;
 wire                      rd_en_tmp       ;

assign   wr_en_tmp =  wr_en & (~full);
assign   rd_en_tmp =  rd_en & (~empty);

//instance sdpram
ipm_distributed_sdpram_v1_2_distributed_fifo
#(
 .ADDR_WIDTH(ADDR_WIDTH )  ,    //address width   range:4-10
 .DATA_WIDTH(DATA_WIDTH )  ,    //data width      range:4-256
 .RST_TYPE  ("ASYNC"   )  ,    //reset type   "ASYNC_RESET" "SYNC_RESET"
 .OUT_REG   (OUT_REG    )
 ) ipm_distributed_sdpram_distributed_fifo
 (
  .wr_data  (wr_data    )  ,
  .wr_addr  (wr_addr    )  ,
  .rd_addr  (rd_addr    )  ,
  .wr_clk   (clk        )  ,
  .rd_clk   (clk        )  ,
  .wr_en    (wr_en_tmp  )  ,
  .rst      (~rst_n     )  ,
  .rd_data  (rd_data    )
 );

pgs_pciex4_fifo_ctrl
 #(
  .ADDR_WIDTH       (ADDR_WIDTH      )
  ) pgs_pciex4_fifo_ctrl
  (
  .clk              (clk             ),            //write clock
  .w_en             (wr_en_tmp       ),             //write enable 1 active
  .wr_addr          (wr_addr         ),           //write address          //write reset
  .wfull            (full            ),           //write full flag 1 active
  .r_en             (rd_en_tmp       ),            //read enable 1 active
  .rd_addr          (rd_addr         ),          //read address
  .rst_n            (rst_n           ),         //read reset
  .rempty           (empty           )         //read empty  1 active
);

endmodule //pgs_pciex4_fifo
module pgs_pciex4_fifo_ctrl #(
    parameter  ADDR_WIDTH  = 9     
)
( input                                 clk            , 
  input                                 rst_n          , 
  input                                 w_en           , 
  output reg [ADDR_WIDTH-1 : 0]         wr_addr         ,
  output reg                            wfull          , 
                                                  
  input                                 r_en           , 
  output reg  [ADDR_WIDTH-1 : 0]        rd_addr        , 
  output reg                            rempty           

);

reg [ADDR_WIDTH-1 : 0] fifo_cnt;
 
always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        fifo_cnt <= {ADDR_WIDTH{1'b0}};
    else
        case({w_en, r_en})
           2'b10: fifo_cnt <= fifo_cnt + {{(ADDR_WIDTH-1){1'b0}}, 1'b1};
           2'b01: fifo_cnt <= fifo_cnt - {{(ADDR_WIDTH-1){1'b0}}, 1'b1};
        endcase
end

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        wr_addr <=  {ADDR_WIDTH{1'b0}};
    else if(w_en)
        wr_addr <= wr_addr + {{(ADDR_WIDTH-1){1'b0}}, 1'b1};
end

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        rd_addr <=  {ADDR_WIDTH{1'b0}};
    else if(r_en)
        rd_addr <= rd_addr + {{(ADDR_WIDTH-1){1'b0}}, 1'b1};
end

//FIFO full
always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        wfull <= 1'b0;
    else if ( (fifo_cnt == {{(ADDR_WIDTH-1){1'b1}}, 1'b0}) & w_en & ~r_en )
        wfull <= 1'b1;
    else if (~w_en & r_en)
        wfull <= 1'b0;
end

//FIFO empty
always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        rempty <= 1'b1;
    else if ( (fifo_cnt == {{(ADDR_WIDTH-1){1'b0}}, 1'b1}) & ~w_en & r_en )
        rempty <= 1'b1;
    else if (w_en & ~r_en)
        rempty <= 1'b0;
end

endmodule
module hsst_rst_wtchdg_v1_0 #(
    parameter ACTIVE_HIGH        = 0,  // 0 : active@low, 1 : active@high
    parameter WTCHDG_CNTR1_WIDTH = 10, //(2**(WTCHDG_CNTR1_WIDTH-1)) = 512
    parameter WTCHDG_CNTR2_WIDTH = 10  //watchdog time = (2**(WTCHDG_CNTR2_WIDTH-1))*(2**(WTCHDG_CNTR1_WIDTH-1)) = 256k;
                                       //watchdog reset length = (2**(WTCHDG_CNTR1_WIDTH-1))
)(
    input   wire                             clk,
    input   wire                             rst_n,
    input   wire                             wtchdg_clr,
    input   wire                             wtchdg_in,
    output  reg                              wtchdg_rst_n
);

wire                              wtchdg_in_mux;
reg     [WTCHDG_CNTR1_WIDTH-1:0]  cnt_1;
reg     [WTCHDG_CNTR2_WIDTH-1:0]  cnt_2;

assign wtchdg_in_mux = (ACTIVE_HIGH == 1'b1) ? ~wtchdg_in : wtchdg_in;

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
    begin
        cnt_1 <= {WTCHDG_CNTR1_WIDTH{1'b0}};
    end
    else if(cnt_1[WTCHDG_CNTR1_WIDTH-1] | wtchdg_in_mux | wtchdg_clr)
    begin
        cnt_1 <= {WTCHDG_CNTR1_WIDTH{1'b0}};
    end
    else
    begin
        cnt_1 <= cnt_1 + { {(WTCHDG_CNTR1_WIDTH-1){1'b0}}, 1'b1};
    end
end

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
    begin
        cnt_2 <= {WTCHDG_CNTR2_WIDTH{1'b0}};
    end
    else if(wtchdg_clr | wtchdg_in_mux | (cnt_2[WTCHDG_CNTR2_WIDTH-1] & cnt_2[0]) )
    begin
        cnt_2 <= {WTCHDG_CNTR2_WIDTH{1'b0}};
    end
    else if(cnt_1[WTCHDG_CNTR1_WIDTH-1])
    begin
        cnt_2 <= cnt_2 + { {(WTCHDG_CNTR2_WIDTH-1){1'b0}}, 1'b1};
    end
end

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
    begin
        wtchdg_rst_n <= 1'b1;
    end
    else if(cnt_2[WTCHDG_CNTR2_WIDTH-1])
    begin
        wtchdg_rst_n <= 1'b0;
    end
    else
    begin
        wtchdg_rst_n <= 1'b1;
    end
end

endmodule
module  hsst_rst_cross_sync_v1_0 #(
    parameter RST_CNTR_WIDTH     = 16,
    parameter RST_CNTR_VALUE     = 16'hC000
)(
    // Reset and Clock
    input           clk,
    input           rstn_in,

    output  reg     rstn_out
);

//****************************************************************************//
//                      Internal Signal                                       //
//****************************************************************************//
    reg rs1;
    reg rs2;

    wire                          rstn_inner;
    reg     [3:0]                 rstn_inner_d;
    reg                           rstn_sync;
    reg     [RST_CNTR_WIDTH-1:0]  cnt_rst;

//****************************************************************************//
//                      Sequential and Logic                                  //
//****************************************************************************//
    always@(posedge clk or negedge rstn_in) 
    begin
        if(!rstn_in) 
        begin
            rs1<=0;
            rs2<=0;
        end
        else
        begin
            rs1<=1;
            rs2<=rs1;
        end
    end


    assign rstn_inner = rs2;

    `ifdef IPSL_PCIE_SPEEDUP_SIM
        initial begin
            rstn_inner_d = 4'hf; //CLM reg default value is 1
            rstn_sync    = 1'b1;
            cnt_rst      = {RST_CNTR_WIDTH{1'b1}};
            rstn_out     = 1'b1;
        end
    `endif

    always @(posedge clk or negedge rstn_inner)
    begin
        if (!rstn_inner) begin
            rstn_inner_d <= 4'h0; //CLM reg default value is 1
            rstn_sync    <= 1'b0;
            cnt_rst      <= {RST_CNTR_WIDTH{1'b1}};
            rstn_out     <= 1'b0;
        end
        else begin
            rstn_inner_d <= {rstn_inner_d[2:0], rstn_inner};

            if (rstn_inner_d[3:2] == 2'd0)
                rstn_sync <= 1'b0;
            else
                rstn_sync <= 1'b1;

            if (~rstn_sync) begin
                cnt_rst <= {RST_CNTR_WIDTH{1'b1}};
                rstn_out   <= 1'b0;
            end
            else if (cnt_rst == RST_CNTR_VALUE)
                rstn_out <= 1'b1;
            else begin
                rstn_out <= 1'b0;
                cnt_rst <= cnt_rst + {{(RST_CNTR_WIDTH-1){1'b0}}, 1'b1};
            end
        end
    end
endmodule
module hsst_rst_debounce_v1_0 #(
    parameter RISE_CNTR_WIDTH = 12,
    parameter RISE_CNTR_VALUE = 12'd2048,
    parameter ACTIVE_HIGH     = 1'b0 // 0 : active@low, 1 : active@high
)(
    input  wire                          clk,
    input  wire                          rst_n,
    input  wire                          signal_b,
    output wire                          signal_deb
);

wire                          signal_b_mux;
reg                           signal_b_ff;
reg                           signal_b_neg;
reg                           signal_deb_pre;
reg     [RISE_CNTR_WIDTH-1:0] rise_cnt;

assign signal_b_mux = (ACTIVE_HIGH == 1'b1) ? ~signal_b : signal_b;
always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
    begin
        signal_b_ff  <= 1'b0;
        signal_b_neg <= 1'b0;
    end
    else
    begin
        signal_b_ff  <= signal_b_mux;
        signal_b_neg <= ~signal_b_mux & signal_b_ff;
    end
end

always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        rise_cnt <= {RISE_CNTR_WIDTH{1'b0}};
    else if (signal_b_neg)
        rise_cnt <= {RISE_CNTR_WIDTH{1'b0}};
    else if (rise_cnt == RISE_CNTR_VALUE)
        rise_cnt <= rise_cnt;
    else if (signal_b_mux)
        rise_cnt <= rise_cnt + {{RISE_CNTR_WIDTH-1{1'b0}}, 1'b1};
end

always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        signal_deb_pre <= 1'b0;
    else if (signal_b_neg)
        signal_deb_pre <= 1'b0;
    else if (rise_cnt == RISE_CNTR_VALUE)
        signal_deb_pre <= 1'b1;
end

assign signal_deb = (ACTIVE_HIGH == 1'b1) ? ~signal_deb_pre : signal_deb_pre;

endmodule
module ipml_hsst_rst_wtchdg_v1_0 #(
    parameter ACTIVE_HIGH        = 0,  // 0 : active@low, 1 : active@high
    parameter WTCHDG_CNTR1_WIDTH = 10, //(2**(WTCHDG_CNTR1_WIDTH-1)) = 512
    parameter WTCHDG_CNTR2_WIDTH = 10  //watchdog time = (2**(WTCHDG_CNTR2_WIDTH-1))*(2**(WTCHDG_CNTR1_WIDTH-1)) = 256k;
                                       //watchdog reset length = (2**(WTCHDG_CNTR1_WIDTH-1))
)(
    input   wire                             clk,
    input   wire                             rst_n,
    input   wire                             wtchdg_clr,
    input   wire                             wtchdg_in,
    output  reg                              wtchdg_rst_n,
    output  reg      [1    :0]               wtchdg_st
);

wire                              wtchdg_in_mux;
reg     [WTCHDG_CNTR1_WIDTH-1:0]  cnt_1;
reg     [WTCHDG_CNTR2_WIDTH-1:0]  cnt_2;

assign wtchdg_in_mux = (ACTIVE_HIGH == 1'b1) ? ~wtchdg_in : wtchdg_in;

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
    begin
        cnt_1 <= {WTCHDG_CNTR1_WIDTH{1'b0}};
    end
    else if(cnt_1[WTCHDG_CNTR1_WIDTH-1] | wtchdg_in_mux | wtchdg_clr)
    begin
        cnt_1 <= {WTCHDG_CNTR1_WIDTH{1'b0}};
    end
    else
    begin
        cnt_1 <= cnt_1 + { {(WTCHDG_CNTR1_WIDTH-1){1'b0}}, 1'b1};
    end
end

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
    begin
        cnt_2 <= {WTCHDG_CNTR2_WIDTH{1'b0}};
    end
    else if(wtchdg_clr | wtchdg_in_mux | (cnt_2[WTCHDG_CNTR2_WIDTH-1] & cnt_2[0]) )
    begin
        cnt_2 <= {WTCHDG_CNTR2_WIDTH{1'b0}};
    end
    else if(cnt_1[WTCHDG_CNTR1_WIDTH-1])
    begin
        cnt_2 <= cnt_2 + { {(WTCHDG_CNTR2_WIDTH-1){1'b0}}, 1'b1};
    end
end

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
    begin
        wtchdg_rst_n <= 1'b1;
    end
    else if(cnt_2[WTCHDG_CNTR2_WIDTH-1])
    begin
        wtchdg_rst_n <= 1'b0;
    end
    else
    begin
        wtchdg_rst_n <= 1'b1;
    end
end

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        wtchdg_st <= 2'b0;
    else if(wtchdg_in_mux | wtchdg_clr)
        wtchdg_st <= 2'b0; //Waiting
    else if(cnt_2[WTCHDG_CNTR2_WIDTH-1])
        wtchdg_st <= 2'b10;//Alarming
    else
        wtchdg_st <= 2'b01;//Counting
end

endmodule
module ipml_hsst_rst_debounce_v1_0 #(
    parameter RISE_CNTR_WIDTH = 12,
    parameter RISE_CNTR_VALUE = 12'd2048,
    parameter ACTIVE_HIGH     = 1'b0 // 0 : active@low, 1 : active@high
)(
    input  wire                          clk,
    input  wire                          rst_n,
    input  wire                          signal_b,
    output wire                          signal_deb
);

wire                          signal_b_mux;
reg                           signal_b_ff;
reg                           signal_b_neg;
reg                           signal_deb_pre;
reg     [RISE_CNTR_WIDTH-1:0] rise_cnt;

assign signal_b_mux = (ACTIVE_HIGH == 1'b1) ? ~signal_b : signal_b;
always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
    begin
        signal_b_ff  <= 1'b0;
        signal_b_neg <= 1'b0;
    end
    else
    begin
        signal_b_ff  <= signal_b_mux;
        signal_b_neg <= ~signal_b_mux & signal_b_ff;
    end
end

always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        rise_cnt <= {RISE_CNTR_WIDTH{1'b0}};
    else if (signal_b_neg)
        rise_cnt <= {RISE_CNTR_WIDTH{1'b0}};
    else if (rise_cnt == RISE_CNTR_VALUE)
        rise_cnt <= rise_cnt;
    else if (signal_b_mux)
        rise_cnt <= rise_cnt + {{RISE_CNTR_WIDTH-1{1'b0}}, 1'b1};
end

always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        signal_deb_pre <= 1'b0;
    else if (signal_b_neg)
        signal_deb_pre <= 1'b0;
    else if (rise_cnt == RISE_CNTR_VALUE)
        signal_deb_pre <= 1'b1;
end

assign signal_deb = (ACTIVE_HIGH == 1'b1) ? ~signal_deb_pre : signal_deb_pre;

endmodule
module ipml_hsst_rst_sync_v1_0
    (
     input                  clk,
     input                  rst_n,

     input                  sig_async,
     output reg             sig_synced
    );

//
reg                      sig_async_ff;

//single bit
always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        sig_async_ff <= 1'b0;
    else
        sig_async_ff <= sig_async;
end

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        sig_synced <= 1'b0;
    else
        sig_synced <= sig_async_ff;
end

endmodule
module ipml_reg_fifo_v1_0
    #( 
       parameter W = 8
     )
    (
      input                     clk,
      input                     rst_n,

      input                     data_in_valid,
      input  [W-1:0]            data_in,
      output                    data_in_ready,

      input                     data_out_ready,
      output [W-1:0]            data_out,
      output                    data_out_valid
    );

//
reg  [W-1:0]                data_0;
reg  [W-1:0]                data_1;
reg                         wptr;
reg                         rptr;
reg                         data_valid_0;
reg                         data_valid_1;

wire                        fifo_read;
wire                        fifo_write;

// handshake
assign fifo_write = data_in_ready & data_in_valid;
assign fifo_read  = data_out_valid & data_out_ready;

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        wptr <= 1'b0;
    else if (fifo_write)
        wptr <= ~wptr;
end

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        rptr <= 1'b0;
    else if (fifo_read)
        rptr <= ~rptr;
end

always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        data_0 <= {W{1'b0}};
    else if (fifo_write & ~wptr)
        data_0 <= data_in;
end

always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        data_1 <= {W{1'b0}};
    else if (fifo_write & wptr)
        data_1 <= data_in;
end

// valid
assign data_out_valid = data_valid_0 | data_valid_1;
assign data_in_ready = ~data_valid_0 | ~data_valid_1;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        data_valid_0 <= 1'b0;
    else if (fifo_write & ~wptr)
        data_valid_0 <= 1'b1;
    else if (fifo_read & ~rptr)
        data_valid_0 <= 1'b0;
end

always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        data_valid_1 <= 1'b0;
    else if (fifo_write & wptr)
        data_valid_1 <= 1'b1;
    else if (fifo_read & rptr)
        data_valid_1 <= 1'b0;
end

//
assign data_out = ({W{rptr}} & data_1) | ({W{~rptr}} & data_0);

endmodule
module xor2_gate(
    input       a, b,     // 2-Input
    output      y);       // Output

    // GATE PRIMITIVE
    xor (y, a, b);

endmodule
module xor2_dataflow(
    input       a, b,     // 2-Input
    output      y);       // Output

    // CONTINUOUS ASSIGNMENT STATEMENT
    assign y = a ^ b;

endmodule
module xor2_behavioral(
    input       a, b,     // 2-Input
    output reg  y);       // Output

    // ALWAYS BLOCK with NON-BLOCKING PROCEDURAL ASSIGNMENT STATEMENT
    always @(a or b) begin
        y <= a ^ b;
    end

endmodule
module not1_gate(
    input       a,        // 2-Input
    output      y);       // Output

    // GATE PRIMITIVE
    not (y, a);

endmodule
module not1_dataflow(
    input       a,        // 2-Input
    output      y);       // Output

    // CONTINUOUS ASSIGNMENT STATEMENT
    assign y = ~a;

endmodule
module not1_behavioral(
    input       a,        // 2-Input
    output reg  y);       // Output

    // ALWAYS BLOCK with NON-BLOCKING PROCEDURAL ASSIGNMENT STATEMENT
    always @(a) begin
        y <= ~a;
    end

endmodule
module and2_gate(
    input       a, b,     // 2-Input
    output      y);       // Output

    // GATE PRIMITIVE
    and (y, a, b);

endmodule
module and2_dataflow(
    input       a, b,     // 2-Input
    output      y);       // Output

    // CONTINUOUS ASSIGNMENT STATEMENT
    assign y = a & b;

endmodule
module and2_behavioral(
    input       a, b,     // 2-Input
    output reg  y);       // Output

    // ALWAYS BLOCK with NON-BLOCKING PROCEDURAL ASSIGNMENT STATEMENT
    always @(a or b) begin
        y <= a & b;
    end

endmodule
module nor2_gate(
    input       a, b,     // 2-Input
    output      y);       // Output

    // GATE PRIMITIVE
    nor (y, a, b);

endmodule
module nor2_dataflow(
    input       a, b,     // 2-Input
    output      y);       // Output

    // CONTINUOUS ASSIGNMENT STATEMENT
    assign y = ~(a | b);

endmodule
module nor2_behavioral(
    input       a, b,     // 2-Input
    output reg  y);       // Output

    // ALWAYS BLOCK with NON-BLOCKING PROCEDURAL ASSIGNMENT STATEMENT
    always @(a or b) begin
        y <= ~(a | b);
    end

endmodule
module or2_gate(
    input       a, b,     // 2-Input
    output      y);       // Output

    // GATE PRIMITIVE
    or (y, a, b);

endmodule
module or2_dataflow(
    input       a, b,     // 2-Input
    output      y);       // Output

    // CONTINUOUS ASSIGNMENT STATEMENT
    assign y = a | b;

endmodule
module or2_behavioral(
    input       a, b,     // 2-Input
    output reg  y);       // Output

    // ALWAYS BLOCK with NON-BLOCKING PROCEDURAL ASSIGNMENT STATEMENT
    always @(a or b) begin
        y <= a | b;
    end

endmodule
module nand4_gate(
    input       a, b, c, d,  // 4-Input
    output      y);          // Output

    // GATE PRIMITIVE
    nand (y, a, b, c, d);

endmodule
module nand4_dataflow(
    input       a, b, c, d,  // 4-Input
    output      y);          // Output


    // CONTINUOUS ASSIGNMENT STATEMENT
    assign y = ~(a & b & c & d);

endmodule
module nand4_behavioral(
    input       a, b, c, d,  // 4-Input
    output reg  y);          // Output

    // ALWAYS BLOCK with NON-BLOCKING PROCEDURAL ASSIGNMENT STATEMENT
    always @(a or b or c or d) begin
        y <= ~(a & b & c & d);
    end

endmodule
module sr_latch_gate (
    input       s,          // Inputs
    input       r,          // 
    output      q,          // Output
    output      qbar);      //
    
    // NAND1
    nand (q, s, qbar);

    // NAND2
    nand (qbar, r, q);

endmodule
module sr_latch_dataflow (
    input       s,          // Inputs
    input       r,          // 
    output      q,          // Output
    output      qbar);      //

    // NAND1
    assign q = ~(s & qbar);

    // NAND2
    assign qbar = ~(r & q);

endmodule
module sr_latch_behavioral (
    input       s,          // Inputs
    input       r,          // 
    output reg  q,          // Output
    output      qbar);      //

    always @(*) begin
        case({s,r})
            2'b0_0 : q <= 1'bx;
            2'b0_1 : q <= 1'b1;
            2'b1_0 : q <= 1'b0;
            2'b1_1 : q <= q;
        endcase
    end

endmodule
module D_FLIP_FLOP_POS_EDGE_SYNC_EN_TB ();

    // INPUT PROBES
    reg             EN;
    reg             D;

    // OUTPUT PROBES
    wire            Q_beh, QBAR_beh;

    // FOR TESTING  
    reg             CLK;
    reg [31:0]      VECTORCOUNT, ERRORS;
    reg             QEXPECTED;
    integer         FD, COUNT;
    reg [8*32-1:0]  COMMENT;

    // UNIT UNDER TEST (behavioral)
    d_flip_flop_pos_edge_sync_en_behavioral UUT_d_flip_flop_pos_edge_sync_en_behavioral(
        .clk(CLK),
        .en(EN),
        .d(D),
        .q(Q_beh), .qbar(QBAR_beh)
    );

    // SAVE EVERYTHING FROM TOP TB MODULE IN A DUMP FILE
    initial begin
        $dumpfile("d_flip_flop_pos_edge_sync_en_tb.vcd");
        $dumpvars(0, D_FLIP_FLOP_POS_EDGE_SYNC_EN_TB);
    end

    // CLK PERIOD
    localparam CLKPERIOD = 20;

    // CLK
    always begin
        #(CLKPERIOD/2) CLK = ~CLK;
    end

    // INITIALIZE TESTBENCH
    initial begin

        // OPEN VECTOR FILE - THROW AWAY FIRST LINE
        FD=$fopen("d_flip_flop_pos_edge_sync_en_tb.tv","r");
        COUNT = $fscanf(FD, "%s", COMMENT);
        // $display ("FIRST LINE IS: %s", COMMENT);

        // INIT TESTBENCH
        COUNT = $fscanf(FD, "%s %b %b %b", COMMENT, EN, D, QEXPECTED);
        CLK = 0;
        VECTORCOUNT = 1;
        ERRORS = 0;

        // DISPAY OUTPUT AND MONITOR
        $display();
        $display("TEST START --------------------------------");
        $display();
        $display("                 | TIME(ns) | EN | D |  Q  |");
        $display("                 ---------------------------");
        // $monitor("%4d  %10s | %8d | %d  | %1d |  %1d  |", VECTORCOUNT, COMMENT, $time, EN, D, Q_beh);

    end

    // APPLY TEST VECTORS ON NEG EDGE CLK (ADD DELAY)
    always @(negedge CLK) begin

        // WAIT A BIT (AFTER CHECK)
        #5;

        // GET VECTORS FROM TB FILE
        COUNT = $fscanf(FD, "%s %b %b  %b", COMMENT, EN, D, QEXPECTED);

        // CHECK IF EOF - PRINT SUMMARY, CLOSE VECTOR FILE AND FINISH TB
        if (COUNT == -1) begin
            $fclose(FD);
            $display();
            $display(" VECTORS: %4d", VECTORCOUNT);
            $display("  ERRORS: %4d", ERRORS);
            $display();
            $display("TEST END ----------------------------------");
            $display();
            $finish;
        end

        // GET ANOTHER VECTOR
        VECTORCOUNT = VECTORCOUNT + 1;

    end

    // CHECK TEST VECTORS ON POS EGDE CLK
    always @(posedge CLK) begin

        // WAIT A BIT
        #5;

        // DISPLAY OUTPUT ON POS EDGE CLK
        $display("%4d  %10s | %8d | %d  | %1d |  %1d  |", VECTORCOUNT, COMMENT, $time, EN, D, Q_beh);

        // CHECK EACH VECTOR RESULT
        if (Q_beh !== QEXPECTED) begin
            $display("***ERROR (behavioral) - Expected Q = %b", QEXPECTED);
            ERRORS = ERRORS + 1;
        end

    end   

endmodule
module d_flip_flop_pos_edge_sync_en_behavioral (
    input       clk,        // Clock
    input       en,         // Enable
    input       d,          // Data
    output reg  q,          // Output
    output      qbar);      //

    assign qbar = ~q;

    // D FLIP-FLOP WITH SYNC ENABLE
    always @ (posedge clk) begin
        if (en) begin
            q <= d;
        end else begin
            q <= q;
        end
    end

endmodule
module jk_flip_flop_gate (
    input       clk,        // Clock
    input       j,          // Inputs
    input       k,          // 
    output      q,          // Output
    output      qbar);      //

    // INTERNAL WIRES
    wire        s, r;
  
    // NAND3
    nand (s, j, clk, qbar);

    // NAND4
    nand (r, k, clk, q);

    // SR- LATCH -------------------------------------
    
    // NAND1
    nand (q, s, qbar);

    // NAND2
    nand (qbar, r, q);

endmodule
module jk_flip_flop_dataflow (
    input       clk,        // Clock
    input       j,          // Inputs
    input       k,          // 
    output      q,          // Output
    output      qbar);      //

    // INTERNAL WIRES
    wire        s, r;
  
    // NAND3
    assign s = ~(j & clk & qbar);

    // NAND4
    assign r = ~(k & clk & q);

    // SR- LATCH -------------------------------------
    
    // NAND1
    assign q = ~(s & qbar);

    // NAND2
    assign qbar = ~(r & q);

endmodule