At this time, I have only a couple of comments. I prefix my comments with "--".
module spi_controller(
clock,
reset_, // async negative reset
// Read/write interface
busy, // Is the machine busy working on a read request?
addr, // Read or write address of 32-bit word
write_data, // Data to be written
write_bytes, // Byte enables of write data
read_data, // Data to be read
read_out_valid, // Does data in holding buffer correspond with read addr?
do_read, // Start a read
do_write, // Start a write
// SPI interface
SI,
SO,
CE_,
SCK,
// config
read_cmd, // 8-bit command code for read
read_dummy_byte, // Do I throw away 8 bits when reading?
write_cmd // 8-bit command code to write byte
);
input clock, reset_;
output busy;
input [23:2] addr;
input [31:0] write_data;
input [3:0] write_bytes;
output [31:0] read_data;
output read_out_valid;
input do_read, do_write;
input SO;
output SI, CE_, SCK;
input [7:0] read_cmd, write_cmd;
input read_dummy_byte;
reg CE_, SI;
reg SCK;
reg [39:0] ck_out_data;
reg [31:0] ck_in_data;
reg [6:0] bit_counter;
reg enable_read;
reg busy;
-- Don't forget to replace this with a DDR FF
always @(posedge clock) SCK <= 0;
always @(negedge clock) SCK <= !CE_;
wire [1:0] low_addr;
assign low_addr[1] = !(write_bytes[3] || write_bytes[2]);
assign low_addr[0] = !(write_bytes[3] || write_bytes[1]);
assign read_data = ck_in_data;
always @(negedge clock) begin
if (enable_read)
ck_in_data <= {ck_in_data[30:0], SO};
end
-- Don't forget to assign read_out_valid
always @(posedge clock or negedge reset_) begin
// $display("cyc%d %x %x", bit_counter, ck_out_data, ck_in_data);
if (reset_ == 0) begin
CE_ <= 1;
enable_read <= 0;
bit_counter <= 0;
end else begin
if (bit_counter == 0) begin
if (do_write) begin
{SI, ck_out_data}
<= {write_cmd, addr, low_addr, write_data[7:0], 1'b0};
-- Don't forget to use Howard's code to grab the right byte.
bit_counter <= 40;
CE_ <= 0;
-- This may work, but the diagrams show CE going low a cycle earlier.
What you may want to do is set CE_ low here, then on the next cycle is
when the first valid data comes out. Align clock appropriately.
busy <= 1;
end
else if (do_read) begin
{SI, ck_out_data} <= {read_cmd, addr, 11'b0};
bit_counter <= 63; // It might be 32+31
CE_ <= 0; // right time or one cycle later??
enable_read <= 1;
busy <= 1;
end else begin
CE_ <= 1;
enable_read <= 0;
busy <= 0;
-- Often what I do is have busy go low one cycle early. The idea is
that the counter (whatever it is you're using to control your loop)
never reaches zero if there are back-to-back requests. There are
other ways to achieve the same effect, and it may not be necessary
here. In fact, I'm wondering if we really need a busy signal. When a
read request signal arrives, and it's a miss, we go off and fetch.
Otherwise, we do nothing. The complication arises in that we (a) set
the address on a miss, but (b) don't want to say the data is valid
until it's all arrived. I guess we need an internal busy signal that
goes away when the last data bit is stored, allowing read_valid to be
asserted. If the busy signal goes away one cycle early, and there is
a pipeline delay for read_valid, then it'll go high at the earliest
possible valid time.
end
end else begin
{SI, ck_out_data} <= {ck_out_data, 1'b0};
bit_counter <= bit_counter - 1;
busy <= 1;
-- Not that it matters, but there's no need to keep setting busy to
the same value it's already at. If it's set to a value on every
cycle, then there's more logic on the D input to the flipflop. If
it's not, then there's less logic on D and then some logic is attached
to the write-enable for the FF. The result is potentially fewer
levels of logic. But that doesn't matter here since we're not
performance critical.
end
end
end
endmodule
-- We might want to alter the design to read, say, 64 bits at once.
If reads are sequential, it'll be a slight performance boost. If
reads are random, it'll be a significant penalty. Actually, we
generally want to avoid reading PROMs anyhow, so maybe this
optimization is not helpful.
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)