On 2007-12-06, Timothy Normand Miller wrote:
> Note that all of this is very important.  We need to keep track of
> both the microcode's view of this and the module interface.  They're
> _slightly_ different, because they come from different perspectives
> about what's going on, even though they resolve to the same functions.
>
> [...]

Let me just focus on the memory for the time being.  I haven't done I/O
ports before, so I first of all want to get the approach right.

First, I think the I/O port is best put in a completely separate module
from the HQ, since it's very OGA1 specific.

I attach a sketch without the PCI bits.  It will basically be a big
"case" routing data between a HQ input/output word and multiple external
signals dependent on the I/O address.  Now, I'm uncertain about timing
issues.  The attached sketch registers it's outputs.  My though is that
a more combinatorial I/O unit is infeasible given the big "case".  Here
is how I imagine the timing and data flow:

  * cycle 0
      * The operating mode (store/fetch), address, and optional data is
        computed by the ALU and registered at the end of the cycle.
  * cycle 1
      * The request is now available to the HQ memory stage, and is also
        decoded by the I/O unit if applicable since that's just a
        combinatorial path from the ALU output.
      * For port-write, the I/O unit registers the data on the
        appropriate external port at the end of the cycle.
      * For port-read the I/O unit registers the data from the appropriate
        external port at the end of the cycle.
  * cycle 2
      * For port-read, the HQ memory stage MUXes the data to it's output
        port.  This is further routed to the register file and to the
        appropriate destination for register-forwarding.

Some minor points:

  * Is there anything to gain from arranging the code of the I/O unit
    differently?  E.g. dispatch between {read, write} before address?

  * We could let read-only ports and write-only ports overlap
    (arbitrarily) in the address space and add an input which decides
    whether HQ is reading or writing.  (Given an appropriate
    rearrangement of the port numbers, this is equivalent in terms of
    gate-count of the I/O unit: Just bundle/unbundle the is-reading
    signal with the address signals.)
module oga1hq_io(
    input clock,

    // 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 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 [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

// 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) begin
    // Default output to HQ
    hq_rdata_o <= 0;

    // Default outputs to memory FIFOs
    mem_readreq_enq <= 0;
    mem_readreply_deq <= 0;
    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:     begin
                                    hq_rdata_o <= mem_readreply_data;
                                    mem_readreply_deq <= hq_does_read;
                                end
        MEM_READREPLY_AVAIL:    hq_rdata_o <= mem_readreply_count;

        // Memory Write
        MEM_WRITE_ADDR:         mem_write_addr <= hq_wdata;
        MEM_WRITE_FREE:         hq_rdata_o <= mem_write_free;
        MEM_WRITE_DATA:         begin
                                    mem_write_data <= hq_wdata;
                                    mem_write_enq <= hq_does_write;
                                end

        // TODO: PCI...
    endcase
end
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