
module tb
(
    input   wire    clk_sys,
    input   wire    rstn,
    input   wire    key,
    input   wire    key2,

    output  wire    data_in_flag,
    output  wire    data_out_flag,
    output  [31:0]  data_out,
    output  [5:0]   page_address,
    output  [31:0]  data_in,
    output          write_en,
    output          read_en,
    output          wr_cycle
);


//test bench state machine
reg [5:0] i;

//define signal
reg write_cmd_reg;
assign write_en = write_cmd_reg;
reg read_cmd_reg;
assign read_en = read_cmd_reg;
reg [31:0] write_flash;
assign data_in = write_flash;//write to flash
reg [5:0]  reg_page_address;
assign page_address = reg_page_address;

//get key failing edge
reg key1_temp1,key1_temp2;
reg key2_temp1,key2_temp2;
wire key1_strt;
wire key2_strt;

always @(posedge wr_cycle or negedge rstn)
begin
    if(~rstn) 
    begin
        key1_temp1 <= 1'b1;
        key1_temp2 <= 1'b1;

        key2_temp1 <= 1'b1;
        key2_temp2 <= 1'b1;
    end
    else 
    begin
        key1_temp1 <= key;
        key1_temp2 <= key1_temp1;

        key2_temp1 <= key2;
        key2_temp2 <= key2_temp1;
    end
end
assign key1_strt = ~key1_temp1 & key1_temp2;
assign key2_strt = ~key2_temp1 & key2_temp2;


reg [31:0] inputdata;
always @(posedge wr_cycle or negedge rstn)
begin
    if(~rstn)
    begin
        i <= 6'd0;
        write_cmd_reg <= 1'b0;
        read_cmd_reg <= 1'b0;
        write_flash <= 32'b0;
        reg_page_address <= 6'd0;
        inputdata <= 32'h00000;
    end
    else 
    begin
        case (i)
        6'd0:
             begin
                reg_page_address <= 6'd1;
                i <= 6'd1;
             end
        6'd1:
            begin
                if(key1_strt)//erase start
                begin
                    write_cmd_reg <= 1'b1;
                    i <= i + 1'b1;
                end
                else if(key2_strt) //read start
                begin
                    read_cmd_reg <= 1'b1;
                    i <= 6'd6;
                end
            end
        6'd2:
            begin
                    write_cmd_reg <= 1'b0;
                    i <= i + 1'b1;
            end
        6'd3:
            begin
                    if(data_in_flag)
                    begin
                        i <= i + 1'b1;
                        write_flash <= inputdata;
                        inputdata <= inputdata + 1'b1;
                    end
            end
        6'd4:
            begin
                    if(inputdata == 32'd64)
                    begin
                        i <= 6'd1;
                    end
                    else
                    begin
                        write_flash <= inputdata;
                        inputdata <= inputdata + 1'b1;
                    end
            end

        6'd6:
            begin
                    read_cmd_reg <= 1'b0;
                    i <= 6'd1;
            end

        endcase
    end
end


wire            clk_10M;
wire            clk_10M_P90;
wire            clk_10M_lock;
///////////////////////////////////////////////////////////////////
Gowin_PLL             u_pll_10M
(
.clkout             (clk_10M), //output clkout
.lock               (clk_10M_lock), //output lock
.clkoutp            (clk_10M_P90), //output clkoutp
.clkin              (clk_sys) //input clkin
);

reg[7:0]        rst_cnt;
wire            rst_n_dly;
always @(posedge clk_sys or negedge rstn)
begin
    if(~rstn)
        rst_cnt <= 'd0;
    else if(~clk_10M_lock)
        rst_cnt <= 'd0;
    else
        rst_cnt <= (rst_cnt==8'hff) ? rst_cnt : rst_cnt + 1'b1;
end

assign rst_n_dly = (rst_cnt==8'hff) ? 1'b1 : 1'b0;

Gowin_Flash_Controller_Top u_gowin_flash_controller_top
(
    .clk_sys(clk_sys), //system clk: 50M
    .clk_10m (clk_10m),
    .clk_10m_p90(clk_10m_p90),

    .rst_n_dly(rst_n_dly),//reset from pll

    .data_in_flag(data_in_flag),
    .data_out_flag(data_out_flag),
    .data_out(data_out),
    .page_address(page_address),
    .data_in(data_in),
    .write_en(write_en),
    .read_en(read_en),
    .wr_cycle(wr_cycle)
);

endmodule