Petter,

I had some more caffeine and looked over your oga1hq_io.v file.  It's
exactly what I had in mind and nicely organized.  Excellent job!

There were a few minor tweaks I made.  I'm sure I didn't get
everything, and you'll want to diff it yourself in case I neglect to
mention some change I made.  Also, I was thinking about what you said
about making the address spaces overlap.  Some passive reads and
writes might be combined, but without a clear signal as to whether a
read or write is going on, we could cause problems.  For instance, if
the programmer assumes that the address port won't be altered by
anything else, some read to the corresponding address could put
garbage into that register, causing bugs.  It may be best to keep the
address separate.  Having separate read/write flags would do the same,
but that's no different from using an additional address bit.

I added reset logic.  The dequeue signal has to come out a cycle
earlier (its assertion causes the next data to appear on the next
cycle).  I put in some perhaps unnecessary checks against full for
writes; see the comment.    I added byte enable flags for writes.  I
added auto-increment for write addresses.  (Hmmm... a side-effect we
have to document carefully!)

Here's the altered code:






module oga1hq_io(
    input clock,
    input reset_,

    // HQ interface
    input hq_select,                    // Address is within our range.
    input [5:0] hq_addr,
    input [31:0] hq_wdata,
    output reg [31:0] hq_rdata_o,

    // Memory read request queue
    input [3:0] mem_readreq_free,  // Available req entries, used by microcode
    output reg [6:0] mem_readreq_count, // Part of the request
    output reg [24:0] mem_readreq_addr, // Address of first req
    output reg mem_readreq_enq,         // Enqueue into request queue
    input mem_readreq_full,             // read the fifo interface doc!

    // Memory read return queue
    input [31:0] mem_readreply_data,
    input mem_readreply_valid,
    input [6:0] mem_readreply_count,   // How many read words in queue
    output reg mem_readreply_deq,

    // Memory write requests
    input mem_write_full,
    output reg mem_write_enq,
    output reg [24:0] mem_write_addr,
    output reg [3:0] mem_write_bytes,
    output reg [31:0] mem_write_data,
    input [6:0] mem_write_free  // number of requests that can be queued

    // TODO: PCI...
);

parameter MEM_READREQ_FREE = 0;         // in, free slots in command pipe
parameter MEM_READREQ_COUNT = 1;        // out, number of words to read
parameter MEM_READREQ_ADDR_TRIG = 2;    // out, first addres to read
parameter MEM_READREPLY_DATA = 3;       // in, data stream from memory
parameter MEM_READREPLY_AVAIL = 4;      // in, number of words in FIFO

parameter MEM_WRITE_ADDR = 5;           // out, start address
parameter MEM_WRITE_FREE = 6;           // in, free slots in ouput FIFO
parameter MEM_WRITE_DATA = 7;           // out, data stream to memory
parameter MEM_WRITE_BYTES = 8;          // byte enable flags

// If read and write ports does not overlap, we can ban operations with the
// wrong direction.
wire hq_does_read = hq_select;
wire hq_does_write = hq_select;

always @(posedge clock or negedge reset_) begin
    if (!reset_) begin
        hq_rdata_o <= 0;
        mem_readreq_enq <= 0;
        mem_readreply_deq <= 0;
        mem_write_enq <= 0;
    end else begin
        // Default outputs to memory FIFOs
        // Note:  These checks against full are probably not necessary
        // What they do is allow us to enqueue one more than the free
        // count.  I'm not sure if we care about that.
        if (!mem_readreq_full) mem_readreq_enq <= 0;
        mem_readreply_deq <= 0;
        if (!mem_write_full) mem_write_enq <= 0;

        // Defaults outputs to PCI FIFOs
        // TODO: PCI...

        case (hq_addr)
            // Memory Read
            MEM_READREQ_FREE:       hq_rdata_o <= mem_readreq_free;
            MEM_READREQ_COUNT:      mem_readreq_count <= hq_wdata;
            MEM_READREQ_ADDR_TRIG:  begin
                                        mem_readreq_addr <= hq_wdata;
                                        mem_readreq_enq <= hq_does_write;
                                    end
            MEM_READREPLY_DATA:     hq_rdata_o <= mem_readreply_data;
            MEM_READREPLY_AVAIL:    hq_rdata_o <= mem_readreply_count;

            // Memory Write
            MEM_WRITE_ADDR:         begin
                                        mem_write_addr <= hq_wdata;
                                        // Default to all bytes
                                        mem_write_bytes <= 4'b1111;
                                    end
            MEM_WRITE_FREE:         hq_rdata_o <= mem_write_free;
            MEM_WRITE_DATA:         begin
                                        mem_write_data <= hq_wdata;
                                        mem_write_enq <= hq_does_write;
                                        // Auto-advance to next address
                                        mem_write_addr <= mem_write_addr+1;
                                    end
            MEM_WRITE_BYTES:        mem_write_bytes <= hq_wdata;

            // TODO: PCI...
        endcase
    end
end

// Dequeue signal
assign mem_readreply_deq = (hq_addr == MEM_READREPLY_DATA) && hq_does_read;

endmodule
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to