`timescale 1ns/1ps

module usb_packet_sender_tb();

localparam CLK_PERIOD = 10; // 100MHz clock
localparam SIM_LENGTH = (1e6); // 1ms 
localparam RESET_LENGTH = (1e3); // 1us reset pulse

reg CLOCK;
reg RESET;

initial begin
    CLOCK = 1;
    $dumpfile("usb_packet_sender_tb.vcd");
    $dumpvars(0, usb_packet_sender_tb);


    #(SIM_LENGTH) $finish;
end

initial begin
    RESET = 1;
    #(RESET_LENGTH)
    RESET = 0;
end

always begin
    #(CLK_PERIOD/2) CLOCK = ~CLOCK;
end

reg txact_tb;
reg txpop_tb;
reg pktfin_tb;
reg frame_ready_tb;
reg [7:0] buf_data_tb;
reg [15:0] buf_data_length_tb;

wire [7:0] txdat_tb;
wire txcork_tb;
wire [11:0] txdat_length_tb;
wire buffer_read_clock_tb;
wire [15:0] buffer_address_tb;
wire frame_complete_tb;


reg [7:0] frame_mem[4095:0];
initial begin
    $readmemh("reduced_240x240.hex", frame_mem, 0, 4095);
    buf_data_length_tb = 3853;
end

always @(posedge CLOCK) begin
    buf_data_tb <= frame_mem[buffer_address_tb];
end

reg [11:0] dut_packet_length;
reg done;
integer ii;

initial begin
    // send a single frame
    // lets ask for a few packets before we are ready to send them
    frame_ready_tb = 0;
    txact_tb = 0;
    txpop_tb = 0;
    pktfin_tb = 0;

    #(5*RESET_LENGTH)
    txact_tb = 1;
    #(CLK_PERIOD)
    txact_tb = 0;
    
    #(RESET_LENGTH)
    txact_tb = 1;
    #(CLK_PERIOD)
    txact_tb = 0;

    #(RESET_LENGTH)
    txact_tb = 1;
    #(CLK_PERIOD)
    txact_tb = 0;

    // Those should have been met with a txcork=1
    // Now let's ready up the frame
    #(RESET_LENGTH)
    frame_ready_tb = 1;
    
    done = 0;

    while(~done) begin

        #(RESET_LENGTH)
        txact_tb = 1;
        #(CLK_PERIOD)
        done = txcork_tb;
        dut_packet_length = txdat_length_tb;
        if(~done) begin
            for(ii = 0; ii < dut_packet_length; ii = ii+1) begin
                #(4*CLK_PERIOD)
                txpop_tb = 1;
                #(CLK_PERIOD)
                txpop_tb = 0;
            end
            #(4*CLK_PERIOD)
            pktfin_tb = 1;
            #(CLK_PERIOD)
            pktfin_tb = 0;
            txact_tb = 0;
        end
    end
    frame_ready_tb = 0;
end


video_fifo DUT
(
    .clk(CLOCK),
    .areset(RESET),

    .txact(txact_tb),
    .txpop(txpop_tb),
    .pktfin(pktfin_tb),
    .txdat(txdat_tb),
    .txcork(txcork_tb),
    .txdat_len(txdat_length_tb),

    .video_buffer_data(buf_data_tb),
    .video_frame_length(buf_data_length_tb),
    .frame_ready(frame_ready_tb),
    .buffer_read_clock(buffer_read_clock_tb),
    .buffer_address(buffer_address_tb),
    .frame_complete(frame_complete_tb)
);



endmodule 

