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)