dakies/OSS_Verilog huggingface dataset:
module aq_hpcp_event(
  cp0_hpcp_icg_en,
  cpurst_b,
  eventx_clk_en,
  eventx_value,
  eventx_wen,
  forever_cpuclk,
  hpcp_wdata,
  pad_yy_icg_scan_en
);

// &Ports; @17
input           cp0_hpcp_icg_en;   
input           cpurst_b;          
input           eventx_clk_en;     
input           eventx_wen;        
input           forever_cpuclk;    
input   [63:0]  hpcp_wdata;        
input           pad_yy_icg_scan_en; 
output  [63:0]  eventx_value;      

// &Regs; @18
reg     [5 :0]  value;             

// &Wires @19
wire            cp0_hpcp_icg_en;   
wire            cpurst_b;          
wire            eventx_clk;        
wire            eventx_clk_en;     
wire    [63:0]  eventx_value;      
wire            eventx_wen;        
wire            forever_cpuclk;    
wire    [63:0]  hpcp_wdata;        
wire            pad_yy_icg_scan_en; 
wire            value_mask;        


//define total counter num
parameter HPMCNT_NUM   = 42;
parameter HPMEVT_WIDTH = 6;

// &Force("bus","hpcp_wdata",63,0); @25
//==========================================================
//                 Instance of Gated Cell  
//========================================================== 
// &Instance("gated_clk_cell", "x_gated_clk"); @29
gated_clk_cell  x_gated_clk (
  .clk_in             (forever_cpuclk    ),
  .clk_out            (eventx_clk        ),
  .external_en        (1'b0              ),
  .global_en          (1'b1              ),
  .local_en           (eventx_clk_en     ),
  .module_en          (cp0_hpcp_icg_en   ),
  .pad_yy_icg_scan_en (pad_yy_icg_scan_en)
);

// &Connect(.clk_in      (forever_cpuclk), @30
//          .external_en (1'b0), @31
//          .global_en   (1'b1), @32
//          .module_en   (cp0_hpcp_icg_en), @33
//          .local_en    (eventx_clk_en), @34
//          .clk_out     (eventx_clk)); @35

//==========================================================
//                 Implementation of counter  
//==========================================================
always @(posedge eventx_clk or negedge cpurst_b)
begin
  if(!cpurst_b)
    value[HPMEVT_WIDTH-1:0] <= {HPMEVT_WIDTH{1'b0}};
  else if(eventx_wen)
    value[HPMEVT_WIDTH-1:0] <= hpcp_wdata[HPMEVT_WIDTH-1:0] & {HPMEVT_WIDTH{value_mask}} ;
  else
    value[HPMEVT_WIDTH-1:0] <= value[HPMEVT_WIDTH-1:0];
end

assign value_mask = (!(|hpcp_wdata[63:HPMEVT_WIDTH])) 
                 && (hpcp_wdata[HPMEVT_WIDTH-1:0] <= HPMCNT_NUM);

//output
assign eventx_value[63:0] = {{64-HPMEVT_WIDTH{1'b0}},value[HPMEVT_WIDTH-1:0]};

// &ModuleEnd; @56
endmodule
module aq_hpcp_cntinten_reg(
  cntinten_wen_x,
  cntinten_x,
  cpurst_b,
  hpcp_clk,
  hpcp_wdata_x
);

// &Ports; @23
input        cntinten_wen_x; 
input        cpurst_b;      
input        hpcp_clk;      
input        hpcp_wdata_x;  
output       cntinten_x;    

// &Regs; @24
reg          cntinten_x;    

// &Wires @25
wire         cntinten_wen_x; 
wire         cpurst_b;      
wire         hpcp_clk;      
wire         hpcp_wdata_x;  


always @(posedge hpcp_clk or negedge cpurst_b)
begin
  if(!cpurst_b)
      cntinten_x <= 1'b0;
  else if(cntinten_wen_x) 
      cntinten_x <= hpcp_wdata_x;
  else
      cntinten_x <= cntinten_x;
end

// &Force("output","cntinten_x"); @37
// &ModuleEnd; @38
endmodule
module aq_hpcp_cntof_reg(
  cntof_wen_x,
  cntof_x,
  counter_overflow_x,
  cpurst_b,
  hpcp_clk,
  hpcp_wdata_x
);

// &Ports; @23
input        cntof_wen_x;       
input        counter_overflow_x; 
input        cpurst_b;          
input        hpcp_clk;          
input        hpcp_wdata_x;      
output       cntof_x;           

// &Regs; @24
reg          cntof_x;           

// &Wires @25
wire         cntof_wen_x;       
wire         counter_overflow_x; 
wire         cpurst_b;          
wire         hpcp_clk;          
wire         hpcp_wdata_x;      


always @(posedge hpcp_clk or negedge cpurst_b)
begin
  if(!cpurst_b)
      cntof_x <= 1'b0;
  else if(cntof_wen_x) 
      cntof_x <= hpcp_wdata_x;
  else
      cntof_x <= cntof_x | counter_overflow_x;
end

// &Force("output","cntof_x"); @37
// &ModuleEnd; @38
endmodule
module fpga_ram(
  PortAClk,
  PortAAddr,
  PortADataIn,
  PortAWriteEnable,
//  PortAChipEnable,
  PortADataOut
);

parameter  DATAWIDTH = 2;
parameter  ADDRWIDTH = 2;

input                     PortAClk;
input   [(ADDRWIDTH-1):0] PortAAddr;
input   [(DATAWIDTH-1):0] PortADataIn;
input                     PortAWriteEnable;
//input                     PortAChipEnable;
output  [(DATAWIDTH-1):0] PortADataOut; 

parameter  MEMDEPTH = 2**(ADDRWIDTH);

reg [(DATAWIDTH-1):0] mem [(MEMDEPTH-1):0] /* synthesis syn_ramstyle = "no_rw_check" */;
reg [(DATAWIDTH-1):0] PortADataOut;

always @(posedge PortAClk)
begin
  if(PortAWriteEnable)
  begin
    mem[PortAAddr]  <= PortADataIn;
    PortADataOut    <= PortADataIn;
  end
  else
  begin
    PortADataOut    <= mem[PortAAddr];
  end
end

//wire [(DATAWIDTH-1):0] tt;
//assign t = mem[PortAAddr];
//always @(posedge PortAClk)
//begin
//  if(PortAWriteEnable)
//  begin
//    PortADataOut    <= PortADataIn;
//  end
//  else
//  begin
//    PortADataOut    <= mem[PortAAddr];
//  end
//end

endmodule
module_en,
  local_en,
  external_en,
  pad_yy_icg_scan_en,
  clk_out
);

input  clk_in;
input  global_en;
input  module_en;
input  local_en;
input  external_en;
input  pad_yy_icg_scan_en;
output clk_out;

wire   clk_en_bf_latch;
wire   SE;

assign clk_en_bf_latch = (global_en && (module_en || local_en)) || external_en ;

// SE driven from primary input, held constant
assign SE       = pad_yy_icg_scan_en;

`ifdef TDT_GATED_CELL  
tdt_gated_cell x_tdt_gated_cell(
  .clk_in        (clk_in),
  .external_en   (clk_en_bf_latch),
  .SE            (SE),
  .clk_out       (clk_out)
  );
//`ifdef TDT_SMIC
//  `ifdef TDT_PROCESS55LL
//HVT_CLKLANQHDV8 x_gated_clk_cell(
//.CK(clk_in),
//  `endif
//.TE(SE),
//.E(clk_en_bf_latch),
//.Q(clk_out));
//`endif
//`ifdef TDT_TSMC
//  `ifdef TDT_PROCESS40LP
//CKLNQD1BWP x_gated_clk_cell(
//.CP(clk_in),
//.TE(SE),
//.E(clk_en_bf_latch),
//.Q(clk_out));
//  `endif
//  `ifdef TDT_PROCESS28HPC
//    CKLNQD8BWP35P140  x_gated_clk_cell (
//                .CP     (clk_in),
//                .TE     (SE),
//                .E      (clk_en_bf_latch),
//                .Q      (clk_out)
//                );
//  `endif
//`endif
//`ifdef TDT_GSMC
//  `ifdef TDT_PROCESS130
//CLKGTPHD8X x_gated_clk_cell(
//.CK(clk_in),
//  `endif
//.TE(SE),
//.E(clk_en_bf_latch),
//.Z(clk_out));
//`endif
//
//`ifdef TDT_UMC
//  `ifdef TDT_PROCESS28HDE
//    PREICG_X4B_A9PP140ZTR_C30 x_gated_clk_cell (
//    .CK(clk_in),
//    .SE(SE),
//    .E(clk_en_bf_latch),
//    .ECK(clk_out)
//  );
//    `endif 
//   `ifdef TDT_PROCESS22HDE
//    PREICG_X4B_A9PP140ZTS_C30 x_gated_clk_cell (
//    .CK(clk_in),
//    .SE(SE),
//    .E(clk_en_bf_latch),
//    .ECK(clk_out)
//  );
//  
//  `endif
//`endif
`else
//STN_CKGTPLT_V5_1  x_gated_clk_cell (
//  .CK           (clk_in),
//  .SE               (SE),
//  .EN      (clk_en_bf_latch),
//  .Q          (clk_out)
//);
assign clk_out = clk_in;
`endif


endmodule
module tdt_dmi_rst_top(
  sys_apb_clk,
  sys_apb_rst_b,
  pad_yy_scan_mode,
  pad_yy_scan_rst_b,
  sync_sys_apb_rst_b
                    );

  input sys_apb_clk;
  input sys_apb_rst_b;
  input pad_yy_scan_mode;
  input pad_yy_scan_rst_b;
  output sync_sys_apb_rst_b;

  wire sync_sys_apb_rst_b;
  wire async_apb_rst_b;
  reg sys_apb_rst_ff_1st;

assign async_apb_rst_b = sys_apb_rst_b;

always @(posedge sys_apb_clk or negedge async_apb_rst_b)
begin
  if (!async_apb_rst_b)
    sys_apb_rst_ff_1st <= 1'b0;
  else
    sys_apb_rst_ff_1st <= 1'b1;
end

assign sync_sys_apb_rst_b = pad_yy_scan_mode ? pad_yy_scan_rst_b : sys_apb_rst_ff_1st;

endmodule
module tdt_dtm_io(      
    input          pad_dtm_jtag2_sel,         
    input          pad_dtm_tap_en,        
    input          pad_dtm_tdi,           
    input          pad_dtm_tms_i,  
    output         dtm_pad_tdo,           
    output         dtm_pad_tdo_en,        
    output         dtm_pad_tms_o,         
    output         dtm_pad_tms_oe,        
    input          chain_io_tdo,             
    input          ctrl_io_tdo_en,              
    input          ctrl_io_tms_oe,                          
    output         io_chain_tdi,             
    output         io_ctrl_tap_en
);

    assign io_ctrl_tap_en = pad_dtm_tap_en;
    assign io_chain_tdi   = pad_dtm_jtag2_sel ? pad_dtm_tms_i : pad_dtm_tdi;
    assign dtm_pad_tdo    = chain_io_tdo;
    assign dtm_pad_tms_o  = chain_io_tdo;
    assign dtm_pad_tdo_en = ctrl_io_tdo_en;
    assign dtm_pad_tms_oe = ctrl_io_tms_oe;

endmodule
module tdt_dm_sync_dff #(
    parameter    SYNC_NUM = 2
)(
    input        dst_clk,
    input        dst_rst_b,
    input        src_in,
    output       dst_out
);

reg  [SYNC_NUM-1:0] sync_ff;

always @ (posedge dst_clk or negedge dst_rst_b) begin
    if (!dst_rst_b)
        sync_ff[SYNC_NUM-1:0] <= {SYNC_NUM{1'b0}};
    else 
        sync_ff[SYNC_NUM-1:0] <= {sync_ff[SYNC_NUM-2:0], src_in};
end

assign dst_out = sync_ff[SYNC_NUM-1];

endmodule
module tdt_dm_pulse_sync #(
    parameter   SYNC_NUM = 2
)(
    input       src_clk,
    input       dst_clk,
    input       src_rst_b,
    input       dst_rst_b,
    input       src_pulse,
    output      dst_pulse
);
    reg         src_pulse_2_lvl;
    wire        dst_lvl; 
    reg         dst_lvl_d;
    wire        dst_lvl_src;
    reg         dst_lvl_src_d;
    wire        dst_pulse_2_src;

    always @ (posedge src_clk or negedge src_rst_b) begin
        if(!src_rst_b)
            dst_lvl_src_d <= 1'b0;
        else 
            dst_lvl_src_d <= dst_lvl_src;        
    end

    assign dst_pulse_2_src = dst_lvl_src & ~dst_lvl_src_d;


    always @ (posedge src_clk or negedge src_rst_b) begin
        if(!src_rst_b)
            src_pulse_2_lvl <= 1'b0;
        else if (dst_pulse_2_src)
            src_pulse_2_lvl <= 1'b0;    
        else if (src_pulse)
            src_pulse_2_lvl <= 1'b1;

            //src_pulse_2_lvl <= ~src_pulse_2_lvl;
    end

    tdt_dm_sync_dff #(
        .SYNC_NUM    (SYNC_NUM)
    ) x_tdt_dm_sync_dff (
        .dst_clk     (dst_clk),
        .dst_rst_b   (dst_rst_b),
        .src_in      (src_pulse_2_lvl),
        .dst_out     (dst_lvl)
    );

    tdt_dm_sync_dff #(
        .SYNC_NUM    (SYNC_NUM)
    ) x_tdt_dm_sync_dff_back (
        .dst_clk     (src_clk),
        .dst_rst_b   (src_rst_b),
        .src_in      (dst_lvl),
        .dst_out     (dst_lvl_src)
    );

    always @ (posedge dst_clk or negedge dst_rst_b) begin
        if(!dst_rst_b)
            dst_lvl_d <= 1'b0;
        else
            dst_lvl_d <= dst_lvl;
    end

    assign dst_pulse = dst_lvl & ~dst_lvl_d;

endmodule
module tdt_dmi_pulse_sync #(
    parameter   SYNC_NUM = 2
)(
    input       src_clk,
    input       dst_clk,
    input       src_rst_b,
    input       dst_rst_b,
    input       src_pulse,
    output      dst_pulse
);
    reg         src_pulse_2_lvl;
    wire        dst_lvl; 
    reg         dst_lvl_d;
    wire        dst_lvl_src;
    reg         dst_lvl_src_d;
    wire        dst_pulse_2_src;

    always @ (posedge src_clk or negedge src_rst_b) begin
        if(!src_rst_b)
            dst_lvl_src_d <= 1'b0;
        else 
            dst_lvl_src_d <= dst_lvl_src;        
    end

    assign dst_pulse_2_src = dst_lvl_src & ~dst_lvl_src_d;


    always @ (posedge src_clk or negedge src_rst_b) begin
        if(!src_rst_b)
            src_pulse_2_lvl <= 1'b0;
        else if (dst_pulse_2_src)
            src_pulse_2_lvl <= 1'b0;    
        else if (src_pulse)
            src_pulse_2_lvl <= 1'b1;

            //src_pulse_2_lvl <= ~src_pulse_2_lvl;
    end

    tdt_dmi_sync_dff #(
        .SYNC_NUM    (SYNC_NUM)
    ) x_tdt_dmi_sync_dff (
        .dst_clk     (dst_clk),
        .dst_rst_b   (dst_rst_b),
        .src_in      (src_pulse_2_lvl),
        .dst_out     (dst_lvl)
    );

    tdt_dmi_sync_dff #(
        .SYNC_NUM    (SYNC_NUM)
    ) x_tdt_dmi_sync_dff_back (
        .dst_clk     (src_clk),
        .dst_rst_b   (src_rst_b),
        .src_in      (dst_lvl),
        .dst_out     (dst_lvl_src)
    );

    always @ (posedge dst_clk or negedge dst_rst_b) begin
        if(!dst_rst_b)
            dst_lvl_d <= 1'b0;
        else
            dst_lvl_d <= dst_lvl;
    end

    assign dst_pulse = dst_lvl & ~dst_lvl_d;

endmodule
module tdt_dmi_sync_dff #(
    parameter    SYNC_NUM = 2
)(
    input        dst_clk,
    input        dst_rst_b,
    input        src_in,
    output       dst_out
);

reg  [SYNC_NUM-1:0] sync_ff;

always @ (posedge dst_clk or negedge dst_rst_b) begin
    if (!dst_rst_b)
        sync_ff[SYNC_NUM-1:0] <= {SYNC_NUM{1'b0}};
    else 
        sync_ff[SYNC_NUM-1:0] <= {sync_ff[SYNC_NUM-2:0], src_in};
end

assign dst_out = sync_ff[SYNC_NUM-1];

endmodule
module aq_prio(
  clk,
  rst_b,
  valid,
  clr,
  sel
);
parameter NUM =2;

input            clk;
input            rst_b;
input  [NUM-1:0] valid;
input            clr;
output [NUM-1:0] sel;

reg    [NUM-1:0] prio [NUM-1:0];
reg    [NUM-1:0] unused [NUM-1:0];
wire   [NUM-1:0] sel;
wire   [NUM-1:0] clr_bus;

assign clr_bus[NUM-1:0] = {NUM{clr}} & sel[NUM-1:0];

genvar i;
generate
for(i=0; i<NUM; i=i+1) begin:PRIO_MATRIX_GEN
always@(posedge clk or negedge rst_b)
begin
  if (!rst_b)
    {prio[i][NUM-1:0], unused[i][NUM-1:0]} <= {{NUM{1'b0}}, {NUM{1'b1}}} << i;
  else if(|clr_bus[NUM-1:0]) begin
    prio[i][NUM-1:0] <= (clr_bus[NUM-1:0] == ({{(NUM-1){1'b0}},1'b1}<<i)) 
                      ? ~clr_bus[NUM-1:0] 
                      : prio[i][NUM-1:0] &~clr_bus[NUM-1:0];
  end
end
end
endgenerate

generate
for(i=0; i<NUM; i=i+1) begin: SEL_GEN
assign sel[i] = valid[i] && !(|(valid[NUM-1:0] & prio[i][NUM-1:0]));
end
endgenerate

endmodule
module aq_dcache_dirty_array(
  cp0_lsu_icg_en,
  dirty_cen,
  dirty_clk_en,
  dirty_din,
  dirty_dout,
  dirty_gwen,
  dirty_idx,
  dirty_wen,
  forever_cpuclk,
  pad_yy_icg_scan_en
);

// &Ports; @21
input           cp0_lsu_icg_en;    
input           dirty_cen;         
input           dirty_clk_en;      
input   [7 :0]  dirty_din;         
input           dirty_gwen;        
input   [13:0]  dirty_idx;         
input   [7 :0]  dirty_wen;         
input           forever_cpuclk;    
input           pad_yy_icg_scan_en; 
output  [7 :0]  dirty_dout;        

// &Regs; @22

// &Wires; @23
wire            cp0_lsu_icg_en;    
wire            dirty_cen;         
wire            dirty_clk;         
wire            dirty_clk_en;      
wire    [7 :0]  dirty_din;         
wire    [7 :0]  dirty_dout;        
wire            dirty_gwen;        
wire    [13:0]  dirty_idx;         
wire    [7 :0]  dirty_wen;         
wire            forever_cpuclk;    
wire            pad_yy_icg_scan_en; 


// &Force("bus", "dirty_idx",13,0); @25

//==========================================================
//                 Instance of Gated Cell
//==========================================================
// &Instance("gated_clk_cell","x_dcache_dirty_gated_clk"); @30
gated_clk_cell  x_dcache_dirty_gated_clk (
  .clk_in             (forever_cpuclk    ),
  .clk_out            (dirty_clk         ),
  .external_en        (1'b0              ),
  .global_en          (1'b1              ),
  .local_en           (dirty_clk_en      ),
  .module_en          (cp0_lsu_icg_en    ),
  .pad_yy_icg_scan_en (pad_yy_icg_scan_en)
);

// &Connect( @31
//   .clk_in               (forever_cpuclk      ), @32
//   .clk_out              (dirty_clk           ), @33
//   .external_en          (1'b0                ), @34
//   .global_en            (1'b1                ), @35
//   .local_en             (dirty_clk_en        ), @36
//   .module_en            (cp0_lsu_icg_en      ) @37
// ); @38

//==========================================================
//              Instance dcache array
//==========================================================
// &Instance("aq_spsram_32x8","x_aq_spsram_32x8"); @44
// &Instance("aq_spsram_64x8","x_aq_spsram_64x8"); @47
// &Instance("aq_spsram_128x8","x_aq_spsram_128x8"); @50
aq_spsram_128x8  x_aq_spsram_128x8 (
  .A               (dirty_idx[12:6]),
  .CEN             (dirty_cen      ),
  .CLK             (dirty_clk      ),
  .D               (dirty_din      ),
  .GWEN            (dirty_gwen     ),
  .Q               (dirty_dout     ),
  .WEN             (dirty_wen      )
);

// &Instance("aq_spsram_256x8","x_aq_spsram_256x8");  @53
// &Connect( @55
//   .A              (dirty_idx[`D_DATA_INDEX_WIDTH+2:6]), @56
//   .CEN            (dirty_cen            ), @57
//   .CLK            (dirty_clk            ), @58
//   .GWEN           (dirty_gwen           ), @59
//   .D              (dirty_din            ), @60
//   .Q              (dirty_dout           ), @61
//   .WEN            (dirty_wen            ) @62
// ); @63

// &ModuleEnd; @65
endmodule
module booth_code_54_bit(
  A,
  code,
  h,
  product,
  sn
);

// &Ports; @22
input   [53:0]  A;      
input   [2 :0]  code;   
output  [1 :0]  h;      
output  [53:0]  product; 
output          sn;     

// &Regs; @23
reg     [1 :0]  h;      
reg     [53:0]  product; 
reg             sn;     

// &Wires; @24
wire    [53:0]  A;      
wire    [2 :0]  code;   


parameter SRC_WIDTH = 54;

// &CombBeg; @28
always @( code[2:0]
       or A[53:0])
begin
case(code[2:0])
3'b000 : product[SRC_WIDTH-1:0] =    {SRC_WIDTH{1'b0}};
3'b001 : product[SRC_WIDTH-1:0] =  {A[SRC_WIDTH-1:0]};
3'b010 : product[SRC_WIDTH-1:0] =  {A[SRC_WIDTH-1:0]};
3'b011 : product[SRC_WIDTH-1:0] =  {A[SRC_WIDTH-2:0],1'b0};
3'b100 : product[SRC_WIDTH-1:0] = {~A[SRC_WIDTH-2:0],1'b0};
3'b101 : product[SRC_WIDTH-1:0] = {~A[SRC_WIDTH-1:0]};
3'b110 : product[SRC_WIDTH-1:0] = {~A[SRC_WIDTH-1:0]};
3'b111 : product[SRC_WIDTH-1:0] =    {SRC_WIDTH{1'b0}};
default: product[SRC_WIDTH-1:0] =    {SRC_WIDTH{1'bx}};
endcase
// &CombEnd; @40
end

// &CombBeg; @42
always @( code[2:0]
       or A[53])
begin
case(code[2:0])
3'b000 : sn =  1'b1;
3'b001 : sn = ~A[SRC_WIDTH-1];
3'b010 : sn = ~A[SRC_WIDTH-1];
3'b011 : sn = ~A[SRC_WIDTH-1];
3'b100 : sn =  A[SRC_WIDTH-1];
3'b101 : sn =  A[SRC_WIDTH-1];
3'b110 : sn =  A[SRC_WIDTH-1];
3'b111 : sn =  1'b1;
default: sn =  1'bx;
endcase
// &CombEnd; @54
end

// &CombBeg; @56
always @( code[2:0])
begin
case(code[2:0])
3'b000 : h[1:0] = 2'b00;
3'b001 : h[1:0] = 2'b00;
3'b010 : h[1:0] = 2'b00;
3'b011 : h[1:0] = 2'b00;
3'b100 : h[1:0] = 2'b10;
3'b101 : h[1:0] = 2'b01;
3'b110 : h[1:0] = 2'b01;
3'b111 : h[1:0] = 2'b00;
default: h[1:0] = {2{1'bx}};
endcase
// &CombEnd; @68
end

// &ModuleEnd; @70
endmodule
module adder_sat(
    input wire [4:0] a, // unsigned
    input wire [3:0] b, // signed
    output wire [3:0] c // unsigned
);

    //wire [4:0] a_ext = {1'b0, a};
    wire [4:0] a_ext = a;
    wire [4:0] b_ext = {b[3], b};
    wire [4:0] add = a_ext + b_ext;
    assign c = add[4] ? (b[3] ? (4'h0) : (4'hF)) : (add[3:0]);

endmodule
module adder_sat_8(
    input wire [7:0] a, // unsigned
    input wire [7:0] b, // signed
    output wire [7:0] c // unsigned
);

    wire [8:0] a_ext = {1'b0, a};
    wire [8:0] b_ext = {b[7], b};
    wire [8:0] add = a_ext + b_ext;
    assign c = add[8] ? (b[7] ? (8'h00) : (8'hFF)) : (add[7:0]);

endmodule
module clamp_signed #(
    parameter INPUT_BITS = 11,
    parameter OUTPUT_BITS = 9
) (
    input wire [INPUT_BITS-1:0] in,
    output wire [OUTPUT_BITS-1:0] out
);

    localparam BIT_DIFF = INPUT_BITS - OUTPUT_BITS;

    wire underflow = in[INPUT_BITS-1] &&
            (in[INPUT_BITS-2:OUTPUT_BITS-1] != {BIT_DIFF{1'b1}});
    wire overflow = !in[INPUT_BITS-1] &&
            (in[INPUT_BITS-2:OUTPUT_BITS-1] != {BIT_DIFF{1'b0}});

    assign out =
        underflow ? {1'b1, {(OUTPUT_BITS-1){1'b0}}} :
        overflow ? {1'b0, {(OUTPUT_BITS-1){1'b1}}} :
        {in[INPUT_BITS-1], in[OUTPUT_BITS-2:0]};

endmodule
module wvfmlut(
    input wire clk,
    // Write port
    input wire we,
    input wire [11:0] addr,
    input wire [7:0] din,
    // Read port A
    input wire [13:0] addra,
    output wire [1:0] douta,
    // Read port B
    input wire [13:0] addrb,
    output wire [1:0] doutb
);

    wire [7:0] bram_douta;
    wire [7:0] bram_doutb;

    bramdp #(
        .ABITS(12),
        .DBITS(8),
        .INITIALIZE(1),
        .INIT_FILE("default_waveform.mem")
    ) bramdp0 (
        .clka(clk),
        .wea(we),
        .addra(we ? addr : addra[13:2]),
        .dina(din),
        .douta(bram_douta),
        .clkb(clk),
        .web(1'b0),
        .addrb(addrb[13:2]),
        .dinb(8'b0),
        .doutb(bram_doutb)
    );

    assign douta =
        (addra[1:0] == 2'd0) ? bram_douta[1:0] :
        (addra[1:0] == 2'd1) ? bram_douta[3:2] :
        (addra[1:0] == 2'd2) ? bram_douta[5:4] :
        (addra[1:0] == 2'd3) ? bram_douta[7:6] : 2'bx;

    assign doutb =
        (addrb[1:0] == 2'd0) ? bram_doutb[1:0] :
        (addrb[1:0] == 2'd1) ? bram_doutb[3:2] :
        (addrb[1:0] == 2'd2) ? bram_doutb[5:4] :
        (addrb[1:0] == 2'd3) ? bram_doutb[7:6] : 2'bx;

endmodule
module rgb2y(
    input wire [5:0] r,
    input wire [5:0] g,
    input wire [5:0] b,
    output wire [7:0] y
    );

    // Pretty much overkill.
    // Could just use simple shifter to save some DSP blocks.
    wire [13:0] r_mult = {8'd0, r} * 14'd77;
    wire [13:0] g_mult = {8'd0, g} * 14'd150;
    wire [13:0] b_mult = {8'd0, b} * 14'd29;

    wire [13:0] acc = r_mult + g_mult + b_mult;

    assign y = acc[13:6];

endmodule
module clk_div(
    input i,
    output reg o = 0
    );

    parameter WIDTH = 15, DIV = 1000;
    
    reg [WIDTH - 1:0] counter = 0;
    
    always @(posedge i)
    begin
        if (counter == (DIV / 2 - 1)) begin
            o <= ~o;
            counter <= 0;
        end
        else
            counter <= counter + 1'b1;
    end
endmodule
module bramdp #(
    parameter ABITS = 12,
    parameter DBITS = 8,
    parameter INITIALIZE = 0,
    parameter INIT_FILE = ""
) (
    input wire clka,
    input wire wea,
    input wire [ABITS-1:0] addra,
    input wire [DBITS-1:0] dina,
    output reg [DBITS-1:0] douta,
    input wire clkb,
    input wire web,
    input wire [ABITS-1:0] addrb,
    input wire [DBITS-1:0] dinb,
    output reg [DBITS-1:0] doutb
);

    localparam DEPTH = 1 << ABITS;
    reg [DBITS-1:0] mem [0:DEPTH-1];

    always @(posedge clka) begin
        if (wea)
            mem[addra] <= dina;
        else
            douta <= mem[addra];
    end

    always @(posedge clkb) begin
        if (web)
            mem[addrb] <= dinb;
        else
            doutb <= mem[addrb];
    end

    generate
        if (INITIALIZE == 1) begin: gen_bram_init
            initial begin
                $readmemh(INIT_FILE, mem);
            end
        end
    endgenerate

endmodule
module blue_noise_dithering #(
    parameter OUTPUT_BITS = 1 // 1 or 4
) (
    input wire                      clk,
    input wire [31:0]               vin,
    output reg [OUTPUT_BITS*4-1:0]  vout,
    input wire [3:0]                x_pos,
    input wire [5:0]                y_pos
);

    // Noise attenuation, in bits
    localparam NOISE_ATTEN = (OUTPUT_BITS == 1) ? 'd0 : 'd4;

    wire [OUTPUT_BITS*4-1:0] vo_dithered;
    /* verilator lint_off UNUSEDSIGNAL */
    // Lower 4 bits are not used in 4bpp mode
    wire [7:0] b0, b1, b2, b3;
    // Lower 4 bits are not used
    wire [7:0] c0, c1, c2, c3;
    /* verilator lint_on UNUSEDSIGNAL */

    wire [9:0] addr_hi = {y_pos, x_pos};

    bramdp #(
        .ABITS(12),
        .DBITS(8),
        .INITIALIZE(1),
        .INIT_FILE("noise.mem")
    ) bramdp0 (
        .clka(clk),
        .wea(1'b0),
        .addra({addr_hi, 2'd0}),
        .dina(8'b0),
        .douta(b0),
        .clkb(clk),
        .web(1'b0),
        .addrb({addr_hi, 2'd1}),
        .dinb(8'b0),
        .doutb(b1)
    );

    bramdp #(
        .ABITS(12),
        .DBITS(8),
        .INITIALIZE(1),
        .INIT_FILE("noise.mem")
    ) bramdp1 (
        .clka(clk),
        .wea(1'b0),
        .addra({addr_hi, 2'd2}),
        .dina(8'b0),
        .douta(b2),
        .clkb(clk),
        .web(1'b0),
        .addrb({addr_hi, 2'd3}),
        .dinb(8'b0),
        .doutb(b3)
    );

    wire [7:0] a0 = vin[31:24];
    wire [7:0] a1 = vin[23:16];
    wire [7:0] a2 = vin[15:8];
    wire [7:0] a3 = vin[7:0];

    adder_sat_8 adder_sat0 (a0, {{NOISE_ATTEN{b0[7]}}, b0[7:NOISE_ATTEN]}, c0);
    adder_sat_8 adder_sat1 (a1, {{NOISE_ATTEN{b1[7]}}, b1[7:NOISE_ATTEN]}, c1);
    adder_sat_8 adder_sat2 (a2, {{NOISE_ATTEN{b2[7]}}, b2[7:NOISE_ATTEN]}, c2);
    adder_sat_8 adder_sat3 (a3, {{NOISE_ATTEN{b3[7]}}, b3[7:NOISE_ATTEN]}, c3);
    assign vo_dithered = {
        c0[7-:OUTPUT_BITS],
        c1[7-:OUTPUT_BITS],
        c2[7-:OUTPUT_BITS],
        c3[7-:OUTPUT_BITS]
    };

    always @(posedge clk) begin
        vout <= vo_dithered;
    end

endmodule
module degamma(
    input wire [5:0] in,
    output reg [7:0] out
);

    // Should only use 8 LUT6s.
    always @(in) begin
        case (in)
        6'd0: out = 8'd0;
        6'd1: out = 8'd0;
        6'd2: out = 8'd0;
        6'd3: out = 8'd0;
        6'd4: out = 8'd1;
        6'd5: out = 8'd1;
        6'd6: out = 8'd1;
        6'd7: out = 8'd2;
        6'd8: out = 8'd3;
        6'd9: out = 8'd4;
        6'd10: out = 8'd4;
        6'd11: out = 8'd5;
        6'd12: out = 8'd7;
        6'd13: out = 8'd8;
        6'd14: out = 8'd9;
        6'd15: out = 8'd11;
        6'd16: out = 8'd13;
        6'd17: out = 8'd14;
        6'd18: out = 8'd16;
        6'd19: out = 8'd18;
        6'd20: out = 8'd20;
        6'd21: out = 8'd23;
        6'd22: out = 8'd25;
        6'd23: out = 8'd28;
        6'd24: out = 8'd31;
        6'd25: out = 8'd33;
        6'd26: out = 8'd36;
        6'd27: out = 8'd40;
        6'd28: out = 8'd43;
        6'd29: out = 8'd46;
        6'd30: out = 8'd50;
        6'd31: out = 8'd54;
        6'd32: out = 8'd57;
        6'd33: out = 8'd61;
        6'd34: out = 8'd66;
        6'd35: out = 8'd70;
        6'd36: out = 8'd74;
        6'd37: out = 8'd79;
        6'd38: out = 8'd84;
        6'd39: out = 8'd89;
        6'd40: out = 8'd94;
        6'd41: out = 8'd99;
        6'd42: out = 8'd105;
        6'd43: out = 8'd110;
        6'd44: out = 8'd116;
        6'd45: out = 8'd122;
        6'd46: out = 8'd128;
        6'd47: out = 8'd134;
        6'd48: out = 8'd140;
        6'd49: out = 8'd147;
        6'd50: out = 8'd153;
        6'd51: out = 8'd160;
        6'd52: out = 8'd167;
        6'd53: out = 8'd174;
        6'd54: out = 8'd182;
        6'd55: out = 8'd189;
        6'd56: out = 8'd197;
        6'd57: out = 8'd205;
        6'd58: out = 8'd213;
        6'd59: out = 8'd221;
        6'd60: out = 8'd229;
        6'd61: out = 8'd238;
        6'd62: out = 8'd246;
        6'd63: out = 8'd255;
        endcase
    end

endmodule
module sysclock(
    // Clock in ports
    input  wire clk_in,
    // Clock out ports
    output wire clk_ddr,
    output wire clk_sys,
    // Status and control signals
    input  wire reset,
    output wire locked
 );

    wire clk_in_buffered;

    // Input buffering
    //------------------------------------
    IBUFG clkin1_buf (
        .O (clk_in_buffered),
        .I (clk_in)
    );

    // Clocking primitive
    //------------------------------------

    // Instantiation of the DCM primitive
    //    * Unused inputs are tied off
    //    * Unused outputs are labeled unused
    wire        psdone_unused;
    wire        locked_int;
    wire [7:0]  status_int;
    wire clkfb;
    wire clk0;
    wire clkfx;

    DCM_SP #(
        .CLKDV_DIVIDE          (2.000),
        .CLKFX_DIVIDE          (2),
        .CLKFX_MULTIPLY        (20),
        .CLKIN_DIVIDE_BY_2     ("FALSE"),
        .CLKIN_PERIOD          (30.0),
        .CLKOUT_PHASE_SHIFT    ("NONE"),
        .CLK_FEEDBACK          ("1X"),
        .DESKEW_ADJUST         ("SYSTEM_SYNCHRONOUS"),
        .PHASE_SHIFT           (0),
        .STARTUP_WAIT          ("FALSE")
    )
    dcm_sp_inst (
        // Input clock
        .CLKIN                 (clk_in_buffered),
        .CLKFB                 (clkfb),
        // Output clocks
        .CLK0                  (clk0),
        .CLK90                 (),
        .CLK180                (),
        .CLK270                (),
        .CLK2X                 (),
        .CLK2X180              (),
        .CLKFX                 (clkfx),
        .CLKFX180              (),
        .CLKDV                 (),
        // Ports for dynamic phase shift
        .PSCLK                 (1'b0),
        .PSEN                  (1'b0),
        .PSINCDEC              (1'b0),
        .PSDONE                (),
        // Other control and status signals
        .LOCKED                (locked_int),
        .STATUS                (status_int),

        .RST                   (reset),
        // Unused pin- tie low
        .DSSEN                 (1'b0)
    );

    assign locked = locked_int;

    // Output buffering
    //-----------------------------------
    BUFG clkf_buf (
        .O (clkfb),
        .I (clk0)
    );

    // MIG generates its own BUFG, no needs for buffering here
    BUFG clkddr_buf (
        .O (clk_ddr),
        .I (clkfx)
    );

    // System runs at input clock (33MHz)
    assign clk_sys = clkfb;

endmodule
module vin_colormixer(
    input  wire         clk,
    input  wire         in_vsync,
    input  wire         in_hsync,
    input  wire [47:0]  in_color,
    input  wire         in_valid,
    output reg  [15:0]  out_color,
    output reg          out_valid
);

    wire [5:0] r_even = in_color[47:42];
    wire [5:0] g_even = in_color[39:34];
    wire [5:0] b_even = in_color[31:26];
    wire [5:0] r_odd = in_color[23:18];
    wire [5:0] g_odd = in_color[15:10];
    wire [5:0] b_odd = in_color[7:2];

    wire [7:0] y_odd;
    wire [7:0] y_even;

    // Processing for mono
    rgb2y rgb2y_odd (.r(r_odd), .g(g_odd), .b(b_odd), .y(y_odd));
    rgb2y rgb2y_even (.r(r_even), .g(g_even), .b(b_even), .y(y_even));
//    `else
//        // Processing for DES
//        reg [1:0] c_cnt_x;
//        reg [1:0] c_cnt_y;
//        reg hs_last;
//        reg first_line;
//        always @(posedge clk) begin
//            hs_last <= in_hsync;
//            if (!hs_last && in_hsync) begin
//                if (in_vsync) begin
//                    c_cnt_y <= 2'd1;
//                    c_cnt_x <= 2'd0;
//                    first_line <= 1'b1;
//                end
//                else if (!first_line) begin
//                    c_cnt_x <= c_cnt_y;
//                    if (c_cnt_y == 2'd2) begin
//                        c_cnt_y <= 2'd0;
//                    end
//                    else begin
//                        c_cnt_y <= c_cnt_y + 1;
//                    end
//                end
//            end
//            else if (in_valid) begin
//                first_line <= 1'b0;
//                if (c_cnt_x == 2'd2) begin
//                    c_cnt_x <= 2'd0;
//                end
//                else begin
//                    c_cnt_x <= c_cnt_x + 1;
//                end
//            end
//        end
//        assign y_odd[7:2] = (c_cnt_x == 2'd0) ? (b_odd) :
//                (c_cnt_x == 2'd1) ? (r_odd) : (g_odd);
//        assign y_even[7:2] = (c_cnt_x == 2'd0) ? (r_even) :
//                (c_cnt_x == 2'd1) ? (g_even) : (b_even);
//        assign y_odd[1:0] = y_odd[7:6];
//        assign y_even[1:0] = y_even[7:6];
//    `endif

    always @(posedge clk) begin
        out_valid <= in_valid;
        out_color = {y_even, y_odd};
    end

endmodule
module fpdlink_serdes_in(rstin, rst, cp, cn, dp, dn, gclk, halfgclk, dout);
    
    // Possible values:
    // 3: 18bpp single channel
    // 4: 24bpp single channel
    // 6: 18bpp dual channel
    // 8: 24bpp dual channel
    parameter integer LANES = 6;
    parameter CLK_INVERT = 1'b0;
    parameter CH_INVERT = 6'b000000;
    
    input  wire                 rstin;
    output wire                 rst;
    input  wire                 cp;
    input  wire                 cn;
    input  wire [LANES-1:0]     dp;
    input  wire [LANES-1:0]     dn;
    output wire                 gclk;   // Fabric clock, at pixel clock rate
    output wire                 halfgclk; // Unbuffered half rate fabric clock
    output wire [LANES*7-1:0]   dout;   // Data output
    
    wire             cal_m;     // Master IODELAY calibration enable
    wire             cal_s;     // Slave IODELAY calibration enable
    wire             iod_rst;   // IODELAY reset input
    wire [LANES-1:0] inc;       // IODELAY increment counter
    wire [LANES-1:0] ce;        // IODELAY clock enable input
    wire [LANES-1:0] busy;      // Slave IODELAY sync/ cal finish output
    wire [LANES-1:0] valid;     // Master ISERDES phase detector valid output
    wire [LANES-1:0] incdec;    // Master ISERDES phase detector result output

    // SerDes block clock, 7x CLK lane frequency
    wire ioclk;
    // SerDes block strobe
    wire serdes_strobe;
    // SerDes block bit slip enable
    wire bitslip;

    fpdlink_serdes_clkin #(
        .INVERT(CLK_INVERT)
    ) fpdlink_serdes_clkin (
        .rstin(rstin),
        .rst(rst),
        .clk_p(cp),
        .clk_n(cn),
        .ioclk(ioclk),
        .serdes_strobe(serdes_strobe),
        .gclk(gclk),
        .halfgclk(halfgclk),
        .bitslip(bitslip)
    );
    
    genvar i;
    generate
    for (i = 0; i < LANES; i = i + 1)
    begin
        wire [6:0] serdes_dout;
        fpdlink_serdes_datain fpdlink_serdes_datain (
            // Clock and reset
            .gclk(gclk),
            .rst(rst),
            // Serdes interface
            .dat_p(dp[i]),
            .dat_n(dn[i]),
            .ioclk(ioclk),
            .serdes_strobe(serdes_strobe),
            .bitslip(bitslip),
            .dout(serdes_dout),
            // Phase detector interface
            .cal_m(cal_m),
            .cal_s(cal_s),
            .iod_rst(iod_rst),
            .inc(inc[i]),
            .ce(ce[i]),
            .busy(busy[i]),
            .valid(valid[i]),
            .incdec(incdec[i])
        );
        assign dout[(LANES - 1 - i)*7+6 -: 7] =
            CH_INVERT[i] ? ~serdes_dout : serdes_dout;
    end
    endgenerate
    
    // FPD link probably doesn't have enough transitions for PD to work
    phase_detector #(
        .D(LANES)
    )
    phase_detector (
        .use_phase_detector(1'b1),
        .busy(busy),
        .valid(valid),    
        .inc_dec(incdec),    
        .reset(rst),    
        .gclk(gclk),        
        .debug_in(2'b00),        
        .cal_master(cal_m),
        .cal_slave(cal_s),    
        .rst_out(iod_rst),
        .ce(ce),
        .inc(inc),
        .debug()
    );

endmodule
module vin_fpdlink #(
    parameter integer LANES = 6,
    parameter CLK_INVERT = 1'b0,
    parameter CH_INVERT = 6'b000000
) (
    input  wire         rst,
    input  wire         fpdlink_cp,
    input  wire         fpdlink_cn,
    input  wire [2:0]   fpdlink_odd_p,
    input  wire [2:0]   fpdlink_odd_n,
    input  wire [2:0]   fpdlink_even_p,
    input  wire [2:0]   fpdlink_even_n,
    output wire         v_vsync,
    output wire         v_hsync,
    output wire         v_pclk,
    output wire         v_de,
    output wire [47:0]  v_pixel, // 2 pixels per clock, RGB888
    output wire         v_halfpclk,
    output wire         v_valid
);

    wire gclk;
    wire [41:0] fpdlink_din_unreg;
    reg [41:0] fpdlink_din;
    wire vi_rst;

    fpdlink_serdes_in #(
        .LANES(LANES),
        .CLK_INVERT(CLK_INVERT),
        .CH_INVERT(CH_INVERT)
    ) fpdlink_serdes_in (
        .rstin(rst),
        .rst(vi_rst),
        .cp(fpdlink_cp),
        .cn(fpdlink_cn),
        .dp({fpdlink_odd_p, fpdlink_even_p}),
        .dn({fpdlink_odd_n, fpdlink_even_n}),
        .gclk(gclk),
        .halfgclk(v_halfpclk),
        .dout(fpdlink_din_unreg)
    );

    always @(posedge v_pclk) begin
        fpdlink_din <= fpdlink_din_unreg;
    end
    
    wire [5:0] r_odd = fpdlink_din[40:35];
    wire [5:0] g_odd = {fpdlink_din[32:28], fpdlink_din[41]};
    wire [5:0] b_odd = {fpdlink_din[24:21], fpdlink_din[34:33]};
    wire [5:0] r_even = fpdlink_din[19:14];
    wire [5:0] g_even = {fpdlink_din[11:7], fpdlink_din[20]};
    wire [5:0] b_even = {fpdlink_din[3:0], fpdlink_din[13:12]};

    wire vsync = fpdlink_din[26];
    reg last_vsync;
    reg [3:0] fcnt;
    reg vsync_masking;
    // Ignore first 5 frames  
    always @(posedge v_pclk) begin
        if (vi_rst) begin
            fcnt <= 0;
            vsync_masking <= 1'b0;
            last_vsync <= 1'b0;
        end
        else begin
            last_vsync <= vsync;
            if (!last_vsync && vsync) begin
                if (fcnt < 5) begin
                    fcnt <= fcnt + 1;
                    vsync_masking <= 1'b0;
                end
                else begin
                    vsync_masking <= 1'b1;
                end
            end
        end
    end
    
    assign v_pclk = gclk;
    assign v_vsync = vsync & vsync_masking;
    assign v_hsync = fpdlink_din[25];
    assign v_de = fpdlink_din[27];
    assign v_pixel = {
        r_even, 2'b0,
        g_even, 2'b0,
        b_even, 2'b0,
        r_odd, 2'b0,
        g_odd, 2'b0,
        b_odd, 2'b0
    };

    assign v_valid = !vi_rst;
    
endmodule
module vin_dvi(
    input  wire         rst,
    output wire         rst_out,
    input  wire         dvi_cp,
    input  wire         dvi_cn,
    input  wire [2:0]   dvi_dp,
    input  wire [2:0]   dvi_dn,
    output reg          v_vsync,
    output reg          v_hsync,
    output reg          v_pclk,
    output reg          v_de,
    output wire [15:0]  v_pixel,
    output wire         dbg_pclk,
    output wire         dbg_hsync,
    output wire         dbg_vsync,
    output wire         dbg_de,
    output wire         dbg_pll_lck
);

    wire pclk, hsync, vsync, de;
    wire [7:0] red, green, blue;

    dvi_serdes_in dvi_serdes_in(
        .rstin(rst),
        .rst(rst_out),
        .dvi_cp(dvi_cp),
        .dvi_cn(dvi_cn),
        .dvi_dp(dvi_dp),
        .dvi_dn(dvi_dn),
        .pclk(pclk),
        .hsync(hsync),
        .vsync(vsync),
        .de(de),
        .red(red),
        .green(green),
        .blue(blue),
        .dbg_pll_lck(dbg_pll_lck)
    );

    wire [17:0] rgb666 = {red[7:2], green[7:2], blue[7:2]};
    reg [35:0] pixel_rgb;
    reg [1:0] ignore;
    wire ignored = ignore != 'd0;
    reg [17:0] pixbuf;
    reg last_de, last_vsync;
    always @(posedge pclk or posedge rst_out) begin
        if (rst_out) begin
            v_pclk <= 1'b0;
            v_de <= 1'b0;
            ignore <= 2'd3; // ignore first few frames
        end
        else begin
            if (vsync && !last_vsync && (ignore != 'd0)) begin
                ignore <= ignore - 'd1;
            end

            if ((de && !last_de) || v_pclk) begin
                // re-sync when de is first high
                pixbuf <= rgb666;
                v_pclk <= 1'b0;
            end
            else begin
                v_pclk <= 1'b1;
                v_de <= de && !ignored;
                pixel_rgb <= {pixbuf, rgb666};
                v_hsync <= hsync && !ignored;
                v_vsync <= vsync && !ignored;
            end
            
            last_de <= de;
            last_vsync <= vsync;
        end
    end

    rgb2y rgb2y_odd (
        .r(pixel_rgb[17:12]),
        .g(pixel_rgb[11:6]),
        .b(pixel_rgb[5:0]),
        .y(v_pixel[7:0])
    );

    rgb2y rgb2y_even (
        .r(pixel_rgb[35:30]),
        .g(pixel_rgb[29:24]),
        .b(pixel_rgb[23:18]),
        .y(v_pixel[15:8])
    );
    
    assign dbg_pclk = pclk;
    assign dbg_hsync = hsync;
    assign dbg_vsync = vsync;
    assign dbg_de = de;

endmodule
module DRAM16XN #(parameter data_width = 20)
                 (
                  DATA_IN,
                  ADDRESS,
                  ADDRESS_DP,
                  WRITE_EN,
                  CLK,
                  O_DATA_OUT,
                  O_DATA_OUT_DP);

input [data_width-1:0]DATA_IN;
input [3:0] ADDRESS;
input [3:0] ADDRESS_DP;
input WRITE_EN;
input CLK;

output [data_width-1:0]O_DATA_OUT_DP;
output [data_width-1:0]O_DATA_OUT;

genvar i;
generate
  for(i = 0 ; i < data_width ; i = i + 1) begin : dram16s
    RAM16X1D i_RAM16X1D_U(  
      .D(DATA_IN[i]),        //insert input signal
      .WE(WRITE_EN),         //insert Write Enable signal
      .WCLK(CLK),            //insert Write Clock signal
      .A0(ADDRESS[0]),       //insert Address 0 signal port SPO
      .A1(ADDRESS[1]),       //insert Address 1 signal port SPO
      .A2(ADDRESS[2]),       //insert Address 2 signal port SPO
      .A3(ADDRESS[3]),       //insert Address 3 signal port SPO
      .DPRA0(ADDRESS_DP[0]), //insert Address 0 signal dual port DPO
      .DPRA1(ADDRESS_DP[1]), //insert Address 1 signal dual port DPO
      .DPRA2(ADDRESS_DP[2]), //insert Address 2 signal dual port DPO
      .DPRA3(ADDRESS_DP[3]), //insert Address 3 signal dual port DPO
      .SPO(O_DATA_OUT[i]),   //insert output signal SPO
      .DPO(O_DATA_OUT_DP[i]) //insert output signal DPO
    );
  end
endgenerate

endmodule
module core
    #(parameter LOCAL_MEMORY_SIZE = 2048)
    
    (input        clk,
    input         reset,
    input         core_enable,
    output        core_request,
    output [15:0] memory_addr,
    output        memory_wren,
    output        memory_rden,
    output [15:0] memory_write_val,
    input  [15:0] memory_read_val);

    localparam LOCAL_MEM_ADDR_WIDTH = $clog2(LOCAL_MEMORY_SIZE);

    wire[15:0] iaddr;
    wire[15:0] idata;
    wire[15:0] daddr;
    wire[15:0] ddata_out;
    wire[15:0] local_mem_q;
    wire dwrite_en;
    wire dread_en;
    wire local_memory_select;
    reg local_memory_select_l;  // last cycle was local memory access
    wire device_memory_access;
    wire[15:0] data_to_pipeline;
    wire stall_pipeline;
    wire local_memory_write;
    
    assign local_memory_select = daddr[15:14] == 2'b00; // Bottom 16k words
    assign local_memory_write = dwrite_en && local_memory_select;

    assign core_request = !local_memory_select && (dwrite_en || dread_en);
    
    assign memory_wren = !local_memory_select && dwrite_en;
    assign memory_rden = !local_memory_select && dread_en;
    assign memory_addr = daddr;
    assign memory_write_val = ddata_out;

    // This is delayed by one cycle
    assign data_to_pipeline = local_memory_select_l ? local_mem_q : memory_read_val;

    // The first 16 words in the local address space are a small boot ROM.
    // This is emulated by initializing memory with that program (coreboot.hex)
    dpsram 
`ifdef FEATURE_FPGA
    #(LOCAL_MEMORY_SIZE, 16, LOCAL_MEM_ADDR_WIDTH, 1, `CORE_BOOT_PATH) 
`else
    #(LOCAL_MEMORY_SIZE, 16, LOCAL_MEM_ADDR_WIDTH) 
`endif
    local_memory(
        .clk(clk),
        // Instruction Port
        .addr_a(iaddr[LOCAL_MEM_ADDR_WIDTH - 1:0]), 
        .q_a(idata),
        .we_a(1'b0),
        .data_a(16'd0),
        // Data Port
        .addr_b(daddr[LOCAL_MEM_ADDR_WIDTH - 1:0]),
        .q_b(local_mem_q),
        .we_b(local_memory_write),
        .data_b(ddata_out));

    assign stall_pipeline = !core_enable && (dread_en || dwrite_en) 
        && !local_memory_select;

    pipeline pipeline(
        .clk(clk),
        .reset(reset),
        .iaddr(iaddr),
        .idata(idata),
        .daddr(daddr),
        .ddata_out(ddata_out),
        .ddata_in(data_to_pipeline),
        .dwrite_en(dwrite_en),
        .dread_en(dread_en),
        .stall(stall_pipeline));

    always @(posedge reset, posedge clk)
    begin
        if (reset)
            local_memory_select_l <= 0;
        else
            local_memory_select_l <= local_memory_select;
    end
endmodule
module arbiter
    #(parameter NUM_ENTRIES = 4)

    (input                          clk,
    input                           reset,
    input[NUM_ENTRIES - 1:0]        request,
    output reg[NUM_ENTRIES - 1:0]   grant_oh);

    reg[NUM_ENTRIES - 1:0] base;
    wire[NUM_ENTRIES * 2 - 1:0] double_request = { request, request };
    wire[NUM_ENTRIES * 2 - 1:0] double_grant = double_request 
        & ~(double_request - base);
    wire[NUM_ENTRIES - 1:0] grant_nxt = double_grant[NUM_ENTRIES * 2 - 1:NUM_ENTRIES] 
        | double_grant[NUM_ENTRIES - 1:0];

    always @(posedge clk, posedge reset)
    begin
        if (reset)
        begin
            base <= 1;
            grant_oh <= 0;
        end
        else 
        begin
            if (grant_nxt != 0)
                base <= { grant_nxt[NUM_ENTRIES - 2:0], grant_nxt[NUM_ENTRIES - 1] }; // Rotate left

            grant_oh <= grant_nxt;
        end
    end
endmodule
module avsdpll (
   output reg  CLK,
   input  wire VCO_IN,
   input  wire ENb_CP,
   input  wire ENb_VCO,
   input  wire REF
);
   real period, lastedge, refpd;

   initial begin
      lastedge = 0.0;
      period = 25.0; // 25ns period = 40MHz
      CLK <= 0;
   end

  // Toggle clock at rate determined by period
   always @(CLK or ENb_VCO) begin
      if (ENb_VCO == 1'b1) begin
         #(period / 2.0);
         CLK <= (CLK === 1'b0);
      end
      else if (ENb_VCO == 1'b0) begin
         CLK <= 1'b0;
      end 
      else begin
         CLK <= 1'bx;
      end
   end
   
   // Update period on every reference rising edge
   always @(posedge REF) begin
      if (lastedge > 0.0) begin
         refpd = $realtime - lastedge;
         // Adjust period towards 1/8 the reference period
         //period = (0.99 * period) + (0.01 * (refpd / 8.0));
         period =  (refpd / 8.0) ;
      end
      lastedge = $realtime;
   end
endmodule
module vsdbabysoc (
   output wire OUT,
   //
   input  wire reset,
   //
   input  wire VCO_IN,
   input  wire ENb_CP,
   input  wire ENb_VCO,
   input  wire REF,
   //
   // input  wire VREFL,
   input  wire VREFH
);

   wire CLK;
   wire [9:0] RV_TO_DAC;

   rvmyth core (
      .OUT(RV_TO_DAC),
      .CLK(CLK),
      .reset(reset)
   );

   avsdpll pll (
      .CLK(CLK),
      .VCO_IN(VCO_IN),
      .ENb_CP(ENb_CP),
      .ENb_VCO(ENb_VCO),
      .REF(REF)
   );

   avsddac dac (
      .OUT(OUT),
      .D(RV_TO_DAC),
      // .VREFL(VREFL),
      .VREFH(VREFH)
   );
   
endmodule
module testbench;
wire [9:0] OUT;
reg CLK;
reg reset;

supply0 vgnd;
supply1 vpwr;

rvmyth uut 
(
    .OUT(OUT),
`ifdef USE_POWER_PINS
    .VGND(vgnd),
    .VPWR(vpwr),
`endif
    .CLK (CLK),
    .reset (reset)
);

localparam CLK_PERIOD = 25;
always #(CLK_PERIOD/2) CLK=~CLK;

initial begin
    $dumpfile("post_routing_sim.vcd");
    $dumpvars(0, testbench);
end

initial begin
    CLK = 1'h0;
    reset = 1'h0;
    #(CLK_PERIOD) reset = 1'h1;
    #(CLK_PERIOD * 3) reset = 1'h0;
    #(CLK_PERIOD * 3000) $finish;
end

endmodule
module top (
    input clk,
	input key,
    output elvds_p,
    output elvds_n
);

reg [24:0] ctr_q;
wire [24:0] ctr_d;
wire i_tick;
wire w_ddr;

// Sequential code (flip-flop)
always @(posedge clk)
    ctr_q <= ctr_d;

// Combinational code (boolean logic)
assign ctr_d = ctr_q + 1'b1;
assign i_tick = |ctr_q[24:23];

ODDR oddr_0(
	.D0(1'b0),
	.D1(1'b1),
	.CLK(i_tick),
	.Q0(w_ddr),
	.Q1(),
	.TX()
);

ELVDS_TBUF diff_buf(
		.OEN(~key),
        .O(elvds_p),
        .OB(elvds_n),
        .I(w_ddr)
    );

endmodule
module top (
    input clk,
    output elvds_p,
    output elvds_n,
	input key
);

reg [24:0] ctr_q;
wire [24:0] ctr_d;
wire i_tick;

// Sequential code (flip-flop)
always @(posedge clk)
    ctr_q <= ctr_d;

// Combinational code (boolean logic)
assign ctr_d = ctr_q + 1'b1;
assign i_tick = |ctr_q[24:23];

ELVDS_TBUF diff_buf(
		.OEN(~key),
        .O(elvds_p),
        .OB(elvds_n),
        .I(i_tick)
    );

endmodule
module top(input wire clk, output wire [5:0]led, input wire rst, input wire key);
	wire gnd;
	assign gnd = 1'b0;
	wire dummy;
	reg [5:0] fdiv;
	reg [5:0] idiv;
	reg [5:0] odiv;
    Gowin_PLLVR rpll_0(
        .clkout(led[0]),
        .clkin(clk),
		.lock_o(led[1]),
		.reset(gnd),
		.reset_p(gnd),
		.clkfb(gnd),
		.clkoutd_o(led[2]),
		.fdiv(fdiv),
		.idiv(idiv),
		.odiv(6'b111100) // 8
        );

    Gowin_PLLVR rpll_1(
        .clkout(led[3]),
        .clkin(clk),
		.lock_o(led[4]),
		.reset(gnd),
		.reset_p(gnd),
		.clkfb(gnd),
		.clkoutd_o(led[5]),
		.fdiv(~6'd9),
		.idiv(~6'd2),
		.odiv(6'b111100) // 8
        );

	// dynamic
	always @ (posedge clk) begin
		if (key) begin
			fdiv <= ~6'd12;
			idiv <= ~6'd5;
			odiv <= 6'b111000; // 16
		end else begin
			fdiv <= ~6'd9;
			idiv <= ~6'd2;
			odiv <= ~6'b111100; // 8
		end
	end
endmodule