OpenCores
URL https://opencores.org/ocsvn/qspiflash/qspiflash/trunk

Subversion Repositories qspiflash

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /qspiflash/trunk
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/rtl/wbqspiflash.v
0,0 → 1,1087
//
//
// Filename: wbspiflash.v
//
// Project: FPGA library development (Basys3 development board)
//
// Purpose: Access a Quad SPI flash via a WISHBONE interface. This
// includes both read and write (and erase) commands to the SPI
// flash. All read/write commands are accomplished using the
// high speed (4-bit) interface. Further, the device will be
// left/kept in the 4-bit read interface mode between accesses,
// for a minimum read latency.
//
// Wishbone Registers (See Basys3 Wishbone HTML page):
// 0: local config(r) / erase commands(w) / deep power down cmds / etc.
// R: (Write in Progress), (dirty-block), (spi_port_busy), 1'b0, 9'h00,
// { last_erased_sector, 14'h00 } if (WIP)
// else { current_sector_being_erased, 14'h00 }
// current if write in progress, last if written
// W: (1'b1 to erase), (12'h ignored), next_erased_block, 14'h ignored)
// 1: Read ID (read only)
// 2: Status register (R(/w?)), reads update the WIP bit ...
// (19 bits): Data (R/w, but expect writes to take a while)
//
//
// Creator: Dan Gisselquist
// Gisselquist Tecnology, LLC
//
// Copyright: 2015
//
//
`define WBQSPI_RESET 0
`define WBQSPI_RESET_WEN 1
`define WBQSPI_IDLE 2
`define WBQSPI_RDIDLE 3 // Idle, but in fast read mode
`define WBQSPI_WBDECODE 4
`define WBQSPI_WAIT_WIP_CLEAR 5
`define WBQSPI_CHECK_WIP_CLEAR 6
`define WBQSPI_CHECK_WIP_DONE 7
`define WBQSPI_WEN 8
`define WBQSPI_PP 9 // Program page
`define WBQSPI_QPP 10 // Program page, 4 bit mode
`define WBQSPI_WR_DATA 11
`define WBQSPI_WR_BUS_CYCLE 12
`define WBQSPI_RD_DUMMY 13
`define WBQSPI_QRD_ADDRESS 14
`define WBQSPI_QRD_DUMMY 15
`define WBQSPI_READ_CMD 16
`define WBQSPI_READ_DATA 17
`define WBQSPI_WAIT_TIL_RDIDLE 18
`define WBQSPI_READ_ID_CMD 19
`define WBQSPI_READ_ID 20
`define WBQSPI_READ_STATUS 21
`define WBQSPI_READ_CONFIG 22
`define WBQSPI_WRITE_STATUS 23
`define WBQSPI_WRITE_CONFIG 24
`define WBQSPI_ERASE_WEN 25
`define WBQSPI_ERASE_CMD 26
`define WBQSPI_ERASE_BLOCK 27
`define WBQSPI_CLEAR_STATUS 28
`define WBQSPI_IDLE_CHECK_WIP 29
`define WBQSPI_WAIT_TIL_IDLE 30
 
module wbqspiflash(i_clk_100mhz,
// Internal wishbone connections
i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb, i_wb_we,
i_wb_addr, i_wb_data,
// Wishbone return values
o_wb_ack, o_wb_stall, o_wb_data,
// Quad Spi connections to the external device
o_qspi_sck, o_qspi_cs_n, o_qspi_mod, o_qspi_dat, i_qspi_dat,
o_interrupt,
// Info for a wbscope
o_debug);
input i_clk_100mhz;
// Wishbone, inputs first
input i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb, i_wb_we;
input [19:0] i_wb_addr;
input [31:0] i_wb_data;
// then outputs
output reg o_wb_ack;
output reg o_wb_stall;
output reg [31:0] o_wb_data;
// Quad SPI control wires
output wire o_qspi_sck, o_qspi_cs_n;
output wire [1:0] o_qspi_mod;
output wire [3:0] o_qspi_dat;
input [3:0] i_qspi_dat;
// Interrupt line
output reg o_interrupt;
// Debug/scope
output wire [31:0] o_debug;
 
reg spi_wr, spi_hold, spi_spd, spi_dir;
reg [31:0] spi_in;
reg [1:0] spi_len;
wire [31:0] spi_out;
wire spi_valid, spi_busy;
wire [22:0] spi_dbg;
llqspi lldriver(i_clk_100mhz,
spi_wr, spi_hold, spi_in, spi_len, spi_spd, spi_dir,
spi_out, spi_valid, spi_busy,
o_qspi_sck, o_qspi_cs_n, o_qspi_mod, o_qspi_dat,
i_qspi_dat,
spi_dbg);
 
// Erase status tracking
reg write_in_progress, write_protect;
reg [5:0] erased_sector;
reg dirty_sector;
initial begin
write_in_progress = 1'b0;
erased_sector = 6'h00;
dirty_sector = 1'b1;
write_protect = 1'b1;
end
 
reg [7:0] last_status;
reg quad_mode_enabled;
reg spif_cmd;
reg [19:0] spif_addr;
reg [31:0] spif_data;
reg [5:0] state;
reg [5:0] spif_return;
reg spif_ctrl, spif_req;
wire [5:0] spif_sector;
assign spif_sector = spif_addr[19:14];
 
assign o_debug = { spi_wr, spi_spd, spi_hold, state, spi_dbg };
 
initial state = `WBQSPI_RESET;
initial o_wb_ack = 1'b0;
initial o_wb_stall = 1'b1;
initial spi_wr = 1'b0;
initial spi_len = 2'b00;
initial quad_mode_enabled = 1'b0;
initial o_interrupt = 1'b0;
always @(posedge i_clk_100mhz)
if (state == `WBQSPI_RESET)
begin
// From a reset, we should
// Enable the Quad I/O mode
// Disable the Write protection bits in the status register
// Chip should already be up and running, so we can start
// immediately ....
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
spi_hold <= 1'b0;
spi_spd <= 1'b0;
spi_dir <= 1'b0;
last_status <= 8'h00;
if (spi_len < 2'b11)
spi_len <= spi_len + 1;
state <= `WBQSPI_IDLE;
spif_req <= 1'b0;
/*
// This next bit of logic is confusing ...
// I wish to enable quad SPI mode automatically. However, this is
// a configuration register thing, so once written it never needs to
// be adjusted again. Further, some bits within the configuration
// register cannot be undone, and my inkling might be to set those.
// Finally, the configuration register affects the control of the
// block protect registers in the status register. So ...
// let's just leave these registers alone, or command them from the
// UART-wishbone interface.
else if (~spi_busy)
begin
spi_wr <= 1'b1;
spi_len <= 2'b00; // 1 byte
spi_in <= { 8'h06, 24'h000 };
end
end else if (state == `WBQSPI_RESET_WEN)
begin
spi_wr <= 1'b0;
if ((~spi_busy)&&(~spi_wr)&&(o_qspi_cs_n))
begin
spi_wr <= 1'b1;
spi_spd <= 1'b0;
spi_len <= 2'b10; // 3 bytes
// Command, status, config, then don't care
spi_in <= { 8'h01, 8'h00, 8'h0b, 8'h00 };
spi_dir <= 1'b0;
quad_mode_enabled <= 1'b1;
state <= `WBQSPI_WAIT_TIL_IDLE;
write_in_progress <= 1'b1;
end
*/
end else if (state == `WBQSPI_IDLE)
begin
o_interrupt <= 1'b0;
o_wb_stall <= 1'b0;
o_wb_ack <= 1'b0;
spif_cmd <= i_wb_we;
spif_addr <= i_wb_addr;
spif_data <= i_wb_data;
spif_ctrl <= (i_wb_ctrl_stb)&&(~i_wb_data_stb);
spif_req <= (i_wb_ctrl_stb)||(i_wb_data_stb);
spi_wr <= 1'b0; // Keep the port idle, unless told otherwise
spi_hold <= 1'b0;
spi_spd <= 1'b0;
spi_dir <= 1'b0; // Write (for now, 'cause of cmd)
// Data register access
if ((i_wb_data_stb)&&(i_wb_cyc))
begin
 
if (i_wb_we) // Request to write a page
begin
if((~write_protect)&&(~write_in_progress))
begin // 00
spi_wr <= 1'b1;
spi_len <= 2'b00; // 8 bits
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_WEN;
 
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end else if (write_protect)
begin // whether or not write-in_progress ...
// Do nothing on a write protect
// violation
//
o_wb_ack <= 1'b1;
o_wb_stall <= 1'b0;
end else begin // write is in progress, wait
// for it to complete
state <= `WBQSPI_WAIT_WIP_CLEAR;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
end else if (~write_in_progress)
begin // Read access, normal mode(s)
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
spi_wr <= 1'b1; // Write cmd to device
if (quad_mode_enabled)
begin
spi_in <= { 8'heb, 2'b00, i_wb_addr[19:0], 2'b00 };
state <= `WBQSPI_QRD_ADDRESS;
spi_len <= 2'b00; // single byte, cmd only
end else begin
spi_in <= { 8'h0b, 2'b00, i_wb_addr[19:0], 2'b00 };
state <= `WBQSPI_RD_DUMMY;
spi_len <= 2'b11; // cmd+addr,32bits
end
end else begin
// A write is in progress ... need to stall
// the bus until the write is complete.
state <= `WBQSPI_WAIT_WIP_CLEAR;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)&&(i_wb_we))
begin
o_wb_stall <= 1'b1;
case(i_wb_addr[1:0])
2'b00: begin // Erase command register
write_protect <= ~i_wb_data[28];
o_wb_stall <= 1'b0;
 
if((i_wb_data[31])&&(~write_in_progress))
begin
// Command an erase--ack it immediately
 
o_wb_ack <= 1'b1;
o_wb_stall <= 1'b0;
 
if ((i_wb_data[31])&&(~write_protect))
begin
spi_wr <= 1'b1;
spi_len <= 2'b00;
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_ERASE_CMD;
o_wb_stall <= 1'b1;
end
end else if (i_wb_data[31])
begin
state <= `WBQSPI_WAIT_WIP_CLEAR;
o_wb_ack <= 1'b1;
o_wb_stall <= 1'b1;
end else
o_wb_ack <= 1'b1;
o_wb_stall <= 1'b0;
end
2'b01: begin
// Write the configuration register
o_wb_ack <= 1'b1;
o_wb_stall <= 1'b1;
 
// Need to send a write enable command first
spi_wr <= 1'b1;
spi_len <= 2'b00; // 8 bits
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_WRITE_CONFIG;
end
2'b10: begin
// Write the status register
o_wb_ack <= 1'b1; // Ack immediately
o_wb_stall <= 1'b1; // Stall other cmds
// Need to send a write enable command first
spi_wr <= 1'b1;
spi_len <= 2'b00; // 8 bits
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_WRITE_STATUS;
end
2'b11: begin // Write the ID register??? makes no sense
o_wb_ack <= 1'b1;
o_wb_stall <= 1'b0;
end
endcase
end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)) // &&(~i_wb_we))
begin
case(i_wb_addr[1:0])
2'b00: begin // Read local register
if (write_in_progress) // Read status
begin// register, is write still in progress?
state <= `WBQSPI_READ_STATUS;
spi_wr <= 1'b1;
spi_len <= 2'b01;// 8 bits out, 8 bits in
spi_in <= { 8'h05, 24'h00};
 
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end else begin // Return w/o talking to device
o_wb_ack <= 1'b1;
o_wb_stall <= 1'b0;
o_wb_data <= { write_in_progress,
dirty_sector, spi_busy,
~write_protect,
quad_mode_enabled,
7'h00,
erased_sector, 14'h000 };
end end
2'b01: begin // Read configuration register
state <= `WBQSPI_READ_CONFIG;
spi_wr <= 1'b1;
spi_len <= 2'b01;
spi_in <= { 8'h35, 24'h00};
 
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
2'b10: begin // Read status register
state <= `WBQSPI_READ_STATUS;
spi_wr <= 1'b1;
spi_len <= 2'b01; // 8 bits out, 8 bits in
spi_in <= { 8'h05, 24'h00};
 
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
2'b11: begin // Read ID register
state <= `WBQSPI_READ_ID_CMD;
spi_wr <= 1'b1;
spi_len <= 2'b00;
spi_in <= { 8'h9f, 24'h00};
 
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
endcase
end else if ((~i_wb_cyc)&&(write_in_progress))
begin
state <= `WBQSPI_IDLE_CHECK_WIP;
spi_wr <= 1'b1;
spi_len <= 2'b01; // 8 bits out, 8 bits in
spi_in <= { 8'h05, 24'h00};
 
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
end else if (state == `WBQSPI_RDIDLE)
begin
spi_wr <= 1'b0;
o_wb_stall <= 1'b0;
o_wb_ack <= 1'b0;
spif_cmd <= i_wb_we;
spif_addr <= i_wb_addr;
spif_data <= i_wb_data;
spif_ctrl <= (i_wb_ctrl_stb)&&(~i_wb_data_stb);
spif_req <= (i_wb_ctrl_stb)||(i_wb_data_stb);
spi_hold <= 1'b0;
spi_spd<= 1'b1;
spi_dir <= 1'b0; // Write (for now)
if ((i_wb_cyc)&&(i_wb_data_stb)&&(~i_wb_we))
begin // Continue our read ... send the new address / mode
o_wb_stall <= 1'b1;
spi_wr <= 1'b1;
spi_len <= 2'b10;
spi_in <= { 2'h0, i_wb_addr[19:0], 2'h0, 8'ha0 };
state <= `WBQSPI_QRD_DUMMY;
end else if((i_wb_cyc)&&(i_wb_ctrl_stb)&&(~i_wb_we)&&(i_wb_addr[1:0] == 2'b00))
begin
// A local read that doesn't touch the device, so leave
// the device in its current state
o_wb_stall <= 1'b0;
o_wb_ack <= 1'b1;
o_wb_data <= { write_in_progress,
dirty_sector, spi_busy,
~write_protect,
quad_mode_enabled,
7'h00,
erased_sector, 14'h000 };
end else if((i_wb_cyc)&&((i_wb_ctrl_stb)||(i_wb_data_stb)))
begin // Need to release the device from quad mode for all else
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
spi_wr <= 1'b1;
spi_len <= 2'b11;
spi_in <= 32'h00;
state <= `WBQSPI_WBDECODE;
end
end else if (state == `WBQSPI_WBDECODE)
begin
// We were in quad SPI read mode, and had to get out.
// Now we've got a command (not data read) to read and
// execute. Accomplish what we would've done while in the
// IDLE state here, save only that we don't have to worry
// about data reads, and we need to operate on a stored
// version of the bus command
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spi_wr <= 1'b0; // Keep the port idle, unless told otherwise
spi_hold <= 1'b0;
spi_spd <= 1'b0;
spi_dir <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((~spi_busy)&&(o_qspi_cs_n)&&(~spi_wr)) // only in full idle ...
begin
// Data register access
if (~spif_ctrl)
begin
if (spif_cmd) // Request to write a page
begin
if((~write_protect)&&(~write_in_progress))
begin // 00
spi_wr <= 1'b1;
spi_len <= 2'b00; // 8 bits
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_WEN;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end else if (write_protect)
begin // whether or not write-in_progress ...
// Do nothing on a write protect
// violation
//
o_wb_ack <= spif_req;
o_wb_stall <= 1'b0;
state <= `WBQSPI_IDLE;
end else begin // write is in progress, wait
// for it to complete
state <= `WBQSPI_WAIT_WIP_CLEAR;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
// end else if (~write_in_progress) // always true
// but ... we wouldn't get here on a normal read access
end else begin
// Something's wrong, we should never get here
// Attempt to go to idle to recover
state <= `WBQSPI_IDLE;
end
end else if ((spif_ctrl)&&(spif_cmd))
begin
o_wb_stall <= 1'b1;
case(spif_addr[1:0])
2'b00: begin // Erase command register
o_wb_ack <= spif_req;
o_wb_stall <= 1'b0;
state <= `WBQSPI_IDLE;
write_protect <= ~spif_data[28];
// Are we commanding an erase?
// We're in read mode, writes cannot
// be in progress, so ...
if (spif_data[31]) // Command an erase
begin
// Since we're not going back
// to IDLE, we must stall the
// bus here
o_wb_stall <= 1'b1;
spi_wr <= 1'b1;
spi_len <= 2'b00;
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_ERASE_CMD;
end end
2'b01: begin
// Write the configuration register
o_wb_ack <= spif_req;
o_wb_stall <= 1'b1;
 
// Need to send a write enable command first
spi_wr <= 1'b1;
spi_len <= 2'b00; // 8 bits
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_WRITE_CONFIG;
end
2'b10: begin
// Write the status register
o_wb_ack <= spif_req; // Ack immediately
o_wb_stall <= 1'b1; // Stall other cmds
// Need to send a write enable command first
spi_wr <= 1'b1;
spi_len <= 2'b00; // 8 bits
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_WRITE_STATUS;
end
2'b11: begin // Write the ID register??? makes no sense
o_wb_ack <= spif_req;
o_wb_stall <= 1'b0;
state <= `WBQSPI_IDLE;
end
endcase
end else begin // on (~spif_we)
case(spif_addr[1:0])
2'b00: begin // Read local register
// Nonsense case--would've done this
// already
state <= `WBQSPI_IDLE;
o_wb_ack <= spif_req;
o_wb_stall <= 1'b0;
end
2'b01: begin // Read configuration register
state <= `WBQSPI_READ_CONFIG;
spi_wr <= 1'b1;
spi_len <= 2'b01;
spi_in <= { 8'h35, 24'h00};
 
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
2'b10: begin // Read status register
state <= `WBQSPI_READ_STATUS;
spi_wr <= 1'b1;
spi_len <= 2'b01; // 8 bits out, 8 bits in
spi_in <= { 8'h05, 24'h00};
 
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
2'b11: begin // Read ID register
state <= `WBQSPI_READ_ID_CMD;
spi_wr <= 1'b1;
spi_len <= 2'b00;
spi_in <= { 8'h9f, 24'h00};
 
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
endcase
end
end
end else if (state == `WBQSPI_WAIT_WIP_CLEAR)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spi_wr <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if (~spi_busy)
begin
spi_wr <= 1'b1;
spi_in <= { 8'h05, 24'h0000 };
spi_hold <= 1'b1;
spi_len <= 2'b01; // 16 bits write, so we can read 8
state <= `WBQSPI_CHECK_WIP_CLEAR;
spi_spd <= 1'b0; // Slow speed
spi_dir <= 1'b0;
end
end else if (state == `WBQSPI_CHECK_WIP_CLEAR)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
// Repeat as often as necessary until we are clear
spi_wr <= 1'b1;
spi_in <= 32'h0000; // Values here are actually irrelevant
spi_hold <= 1'b1;
spi_len <= 2'b00; // One byte at a time
spi_spd <= 1'b0; // Slow speed
spi_dir <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((spi_valid)&&(~spi_out[0]))
begin
state <= `WBQSPI_CHECK_WIP_DONE;
spi_wr <= 1'b0;
spi_hold <= 1'b0;
write_in_progress <= 1'b0;
last_status <= spi_out[7:0];
end
end else if (state == `WBQSPI_CHECK_WIP_DONE)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
// Let's let the SPI port come back to a full idle,
// and the chip select line go low before continuing
spi_wr <= 1'b0;
spi_len <= 2'b00;
spi_hold <= 1'b0;
spi_spd <= 1'b0; // Slow speed
spi_dir <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((o_qspi_cs_n)&&(~spi_busy)) // Chip select line is high, we can continue
begin
spi_wr <= 1'b0;
spi_hold <= 1'b0;
 
casez({ spif_cmd, spif_ctrl, spif_addr[1:0] })
4'b00??: begin // Read data from ... somewhere
spi_wr <= 1'b1; // Write cmd to device
if (quad_mode_enabled)
begin
spi_in <= { 8'heb, 2'b00, spif_addr[19:0], 2'b00 };
state <= `WBQSPI_QRD_DUMMY;
end else begin
spi_in <= { 8'h0b, 2'b00, spif_addr[19:0], 2'b00 };
state <= `WBQSPI_RD_DUMMY;
end end
4'b10??: begin // Write data to ... anywhere
spi_wr <= 1'b1;
spi_len <= 2'b00; // 8 bits
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_WEN;
end
4'b0110: begin // Read status register
state <= `WBQSPI_READ_STATUS;
spi_wr <= 1'b1;
spi_len <= 2'b01; // 8 bits out, 8 bits in
spi_in <= { 8'h05, 24'h00};
end
4'b0111: begin
state <= `WBQSPI_READ_ID_CMD;
spi_wr <= 1'b1;
spi_len <= 2'b00;
spi_in <= { 8'h9f, 24'h00};
end
default: begin //
o_wb_stall <= 1'b1;
o_wb_ack <= spif_req;
state <= `WBQSPI_WAIT_TIL_IDLE;
end
endcase
// spif_cmd <= i_wb_we;
// spif_addr <= i_wb_addr;
// spif_data <= i_wb_data;
// spif_ctrl <= (i_wb_ctrl_stb)&&(~i_wb_data_stb);
// spi_wr <= 1'b0; // Keep the port idle, unless told otherwise
end
end else if (state == `WBQSPI_WEN)
begin // We came here after issuing a write enable command
spi_wr <= 1'b0;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
spif_req<= (spif_req) && (i_wb_cyc);
if ((~spi_busy)&&(o_qspi_cs_n)&&(~spi_wr)) // Let's come to a full stop
// state <= (quad_mode_enabled)?`WBQSPI_QPP:`WBQSPI_PP;
state <= `WBQSPI_PP;
end else if (state == `WBQSPI_PP)
begin // We come here under a full stop / full port idle mode
// Issue our command immediately
spi_wr <= 1'b1;
spi_in <= { 8'h02, 2'h0, spif_addr, 2'b00 };
spi_len <= 2'b11;
spi_hold <= 1'b1;
spi_spd <= 1'b0;
spi_dir <= 1'b0; // Writing
spif_req<= (spif_req) && (i_wb_cyc);
 
// Once we get busy, move on
if (spi_busy)
state <= `WBQSPI_WR_DATA;
if (spif_sector == erased_sector)
dirty_sector <= 1'b1;
end else if (state == `WBQSPI_QPP)
begin // We come here under a full stop / full port idle mode
// Issue our command immediately
spi_wr <= 1'b1;
spi_in <= { 8'h32, 2'h0, spif_addr, 2'b00 };
spi_len <= 2'b11;
spi_hold <= 1'b1;
spi_spd <= 1'b0;
spi_dir <= 1'b0; // Writing
spif_req<= (spif_req) && (i_wb_cyc);
 
// Once we get busy, move on
if (spi_busy)
begin
// spi_wr is irrelevant here ...
// Set the speed value once, but wait til we get busy
// to do so.
spi_spd <= 1'b1;
state <= `WBQSPI_WR_DATA;
end
if (spif_sector == erased_sector)
dirty_sector <= 1'b1;
end else if (state == `WBQSPI_WR_DATA)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spi_wr <= 1'b1; // write without waiting
spi_in <= {
spif_data[ 7: 0],
spif_data[15: 8],
spif_data[23:16],
spif_data[31:24] };
spi_len <= 2'b11; // Write 4 bytes
spi_hold <= 1'b1;
if (~spi_busy)
begin
o_wb_ack <= spif_req; // Ack when command given
state <= `WBQSPI_WR_BUS_CYCLE;
end
spif_req<= (spif_req) && (i_wb_cyc);
end else if (state == `WBQSPI_WR_BUS_CYCLE)
begin
o_wb_ack <= 1'b0; // Turn off our ack and stall flags
o_wb_stall <= 1'b1;
spi_wr <= 1'b0;
spi_hold <= 1'b1;
write_in_progress <= 1'b1;
spif_req<= (spif_req) && (i_wb_cyc);
if (~i_wb_cyc)
begin
state <= `WBQSPI_WAIT_TIL_IDLE;
spi_hold <= 1'b0;
end else if (spi_wr)
begin // Give the SPI a chance to get busy on the last write
// Do nothing here.
end else if ((i_wb_data_stb)&&(i_wb_we)
&&(i_wb_addr == (spif_addr+1))
&&(i_wb_addr[19:6]==spif_addr[19:6]))
begin
spif_cmd <= 1'b1;
spif_data <= i_wb_data;
spif_addr <= i_wb_addr;
spif_ctrl <= 1'b0;
spif_req<= 1'b1;
// We'll keep the bus stalled on this request
// for a while
state <= `WBQSPI_WR_DATA;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b0;
end else if ((i_wb_data_stb|i_wb_ctrl_stb)&&(~o_wb_ack)) // Writing out of bounds
begin
spi_hold <= 1'b0;
spi_wr <= 1'b0;
state <= `WBQSPI_WAIT_TIL_IDLE;
end // Otherwise we stay here
end else if (state == `WBQSPI_RD_DUMMY)
begin
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
 
spi_wr <= 1'b1; // Non-stop
// Need to read one byte of dummy data,
// just to consume 8 clocks
spi_in <= { 8'h00, 24'h00 };
spi_len <= 2'b00; // Read 8 bits
spi_spd <= 1'b0;
spi_hold <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((~spi_busy)&&(~o_qspi_cs_n))
// Our command was accepted
state <= `WBQSPI_READ_CMD;
end else if (state == `WBQSPI_QRD_ADDRESS)
begin
// We come in here immediately upon issuing a QRD read
// command (8-bits), but we have to pause to give the
// address (24-bits) and mode (8-bits) in quad speed.
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
 
spi_wr <= 1'b1; // Non-stop
spi_in <= { 2'b0, spif_addr, 2'b0, 8'ha0 };
spi_len <= 2'b11; // Write all 32 bits bits
spi_spd <= 1'b1;
spi_dir <= 1'b0; // Still writing
spi_hold <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((~spi_busy)&&(spi_spd))
// Our command was accepted
state <= `WBQSPI_QRD_DUMMY;
end else if (state == `WBQSPI_QRD_DUMMY)
begin
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
 
spi_wr <= 1'b1; // Non-stop
spi_in <= { 8'ha0, 24'h00 }; // Mode byte, then 2 bytes dummy
spi_len <= 2'b10; // Write 8 bits
spi_spd <= 1'b1;
spi_dir <= 1'b0; // Still writing
spi_hold <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((~spi_busy)&&(spi_in[31:28] == 4'ha))
// Our command was accepted
state <= `WBQSPI_READ_CMD;
end else if (state == `WBQSPI_READ_CMD)
begin // Issue our first command to read 32 bits.
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
 
spi_wr <= 1'b1;
spi_in <= { 8'hff, 24'h00 }; // Empty
spi_len <= 2'b11; // Read 32 bits
spi_dir <= 1'b1; // Now reading
spi_hold <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((spi_valid)&&(spi_len == 2'b11))
state <= `WBQSPI_READ_DATA;
end else if (state == `WBQSPI_READ_DATA)
begin
// Pipelined read support
spi_wr <=((i_wb_cyc)&&(i_wb_data_stb)&&(~i_wb_we)&&(i_wb_addr== (spif_addr+1)));
// spi_wr <= 1'b0; // No pipelined read support
spi_in <= 32'h00;
spi_len <= 2'b11;
// Don't adjust the speed here, it was set in the setup
spi_dir <= 1'b1; // Now we get to read
spi_hold <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((spi_valid)&&(~spi_in[31]))
begin // Single pulse acknowledge and write data out
o_wb_ack <= spif_req;
o_wb_stall <= (~spi_wr);
// adjust endian-ness to match the PC
o_wb_data <= { spi_out[7:0], spi_out[15:8],
spi_out[23:16], spi_out[31:24] };
state <= (spi_wr)?`WBQSPI_READ_DATA
: ((spi_spd) ? `WBQSPI_WAIT_TIL_RDIDLE : `WBQSPI_WAIT_TIL_IDLE);
spif_req <= spi_wr;
if (spi_wr)
spif_addr <= i_wb_addr;
end else begin
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end
end else if (state == `WBQSPI_WAIT_TIL_RDIDLE)
begin // Wait 'til idle, but then go to fast read idle instead of full
spi_wr <= 1'b0; // idle
spi_hold <= 1'b0;
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spif_req <= 1'b0;
if ((~spi_busy)&&(o_qspi_cs_n)&&(~spi_wr)) // Wait for a full
begin // clearing of the SPI port before moving on
state <= `WBQSPI_RDIDLE;
o_wb_stall <= 1'b0;
o_wb_ack <= 1'b0;// Shouldn't be acking anything here
end
end else if (state == `WBQSPI_READ_ID_CMD)
begin // We came into here immediately after issuing a 0x9f command
// Now we need to read 32 bits of data. Result should be
// 0x0102154d (8'h manufacture ID, 16'h device ID, followed
// by the number of extended bytes available 8'h4d).
o_wb_ack <= 1'b0;
o_wb_stall<= 1'b1;
 
spi_wr <= 1'b1; // No data to send, but need four bytes, since
spi_len <= 2'b11; // 32 bits of data are ... useful
spi_in <= 32'h00; // Irrelevant
spi_spd <= 1'b0; // Slow speed
spi_dir <= 1'b1; // Reading
spi_hold <= 1'b0;
spif_req <= (spif_req) && (i_wb_cyc);
if ((~spi_busy)&&(~o_qspi_cs_n)&&(spi_len == 2'b11))
// Our command was accepted, now go read the result
state <= `WBQSPI_READ_ID;
end else if (state == `WBQSPI_READ_ID)
begin
o_wb_ack <= 1'b0; // Assuming we're still waiting
o_wb_stall <= 1'b1;
 
spi_wr <= 1'b0; // No more writes, we'ev already written the cmd
spi_hold <= 1'b0;
spif_req <= (spif_req) && (i_wb_cyc);
 
// Here, we just wait until the result comes back
// The problem is, the result may be the previous result.
// So we use spi_len as an indicator
spi_len <= 2'b00;
if((spi_valid)&&(spi_len==2'b00))
begin // Put the results out as soon as possible
o_wb_data <= spi_out[31:0];
o_wb_ack <= spif_req;
spif_req <= 1'b0;
end else if ((~spi_busy)&&(~o_qspi_cs_n))
begin
state <= `WBQSPI_IDLE;
o_wb_stall <= 1'b0;
end
end else if (state == `WBQSPI_READ_STATUS)
begin // We enter after the command has been given, for now just
// read and return
spi_wr <= 1'b0;
o_wb_ack <= 1'b0;
spi_hold <= 1'b0;
spif_req <= (spif_req) && (i_wb_cyc);
if (spi_valid)
begin
o_wb_ack <= spif_req;
o_wb_stall <= 1'b1;
spif_req <= 1'b0;
last_status <= spi_out[7:0];
write_in_progress <= spi_out[0];
if (spif_addr[1:0] == 2'b00) // Local read, checking
begin // status, 'cause we're writing
o_wb_data <= { spi_out[0],
dirty_sector, spi_busy,
~write_protect,
quad_mode_enabled,
7'h00,
erased_sector, 14'h000 };
end else begin
o_wb_data <= { 24'h00, spi_out[7:0] };
end
end
 
if ((~spi_busy)&&(~spi_wr))
state <= `WBQSPI_IDLE;
end else if (state == `WBQSPI_READ_CONFIG)
begin // We enter after the command has been given, for now just
// read and return
spi_wr <= 1'b0;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
spi_hold <= 1'b0;
spif_req <= (spif_req) && (i_wb_cyc);
 
if (spi_valid)
begin
o_wb_data <= { 24'h00, spi_out[7:0] };
quad_mode_enabled <= spi_out[1];
end
 
if ((~spi_busy)&&(~spi_wr))
begin
state <= `WBQSPI_IDLE;
o_wb_ack <= spif_req;
o_wb_stall <= 1'b0;
spif_req <= 1'b0;
end
end else if (state == `WBQSPI_WRITE_CONFIG)
begin // We enter immediately after commanding a WEN
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
 
spi_len <= 2'b10;
spi_in <= { 8'h01, last_status, spif_data[7:0], 8'h00 };
spi_wr <= 1'b0;
spi_hold <= 1'b0;
spif_req <= (spif_req) && (i_wb_cyc);
if ((~spi_busy)&&(~spi_wr))
begin
spi_wr <= 1'b1;
state <= `WBQSPI_WAIT_TIL_IDLE;
write_in_progress <= 1'b1;
quad_mode_enabled <= spif_data[1];
end
end else if (state == `WBQSPI_WRITE_STATUS)
begin // We enter immediately after commanding a WEN
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
 
spi_len <= 2'b01;
spi_in <= { 8'h01, spif_data[7:0], 16'h00 };
// last_status <= i_wb_data[7:0]; // We'll read this in a moment
spi_wr <= 1'b0;
spi_hold <= 1'b0;
spif_req <= (spif_req) && (i_wb_cyc);
if ((~spi_busy)&&(~spi_wr))
begin
spi_wr <= 1'b1;
last_status <= spif_data[7:0];
write_in_progress <= 1'b1;
if(((last_status[6])||(last_status[5]))
&&((~spif_data[6])&&(~spif_data[5])))
state <= `WBQSPI_CLEAR_STATUS;
else
state <= `WBQSPI_WAIT_TIL_IDLE;
end
end else if (state == `WBQSPI_ERASE_CMD)
begin // Know that WIP is clear on entry, WEN has just been commanded
spi_wr <= 1'b0;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
spi_hold <= 1'b0;
spi_spd <= 1'b0;
spi_dir <= 1'b0;
spif_req <= (spif_req) && (i_wb_cyc);
 
// Here's the erase command
spi_in <= { 8'hd8, 2'h0, spif_data[19:14], 14'h000, 2'b00 };
spi_len <= 2'b11; // 32 bit write
// together with setting our copy of the WIP bit
write_in_progress <= 1'b1;
// keeping track of which sector we just erased
erased_sector <= spif_data[19:14];
// and marking this erase sector as no longer dirty
dirty_sector <= 1'b0;
 
// Wait for a full stop before issuing this command
if ((~spi_busy)&&(~spi_wr)&&(o_qspi_cs_n))
begin // When our command is accepted, move to the next state
spi_wr <= 1'b1;
state <= `WBQSPI_ERASE_BLOCK;
end
end else if (state == `WBQSPI_ERASE_BLOCK)
begin
spi_wr <= 1'b0;
spi_hold <= 1'b0;
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spif_req <= (spif_req) && (i_wb_cyc);
// When the port clears, we can head back to idle
if ((~spi_busy)&&(~spi_wr))
begin
o_wb_ack <= spif_req;
state <= `WBQSPI_IDLE;
end
end else if (state == `WBQSPI_CLEAR_STATUS)
begin // Issue a clear status command
spi_wr <= 1'b1;
spi_hold <= 1'b0;
spi_len <= 2'b00; // 8 bit command
spi_in <= { 8'h30, 24'h00 };
spi_spd <= 1'b0;
spi_dir <= 1'b0;
last_status[6:5] <= 2'b00;
spif_req <= (spif_req) && (i_wb_cyc);
if ((spi_wr)&&(~spi_busy))
state <= `WBQSPI_WAIT_TIL_IDLE;
end else if (state == `WBQSPI_IDLE_CHECK_WIP)
begin // We are now in read status register mode
 
// No bus commands have (yet) been given
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spif_req <= (spif_req) && (i_wb_cyc);
 
// Stay in this mode unless/until we get a command, or
// the write is over
spi_wr <= (((~i_wb_cyc)||((~i_wb_data_stb)&&(~i_wb_ctrl_stb)))
&&(write_in_progress));
spi_len <= 2'b00; // 8 bit reads
spi_spd <= 1'b0; // SPI, not quad
spi_dir <= 1'b1; // Read
if (spi_valid)
begin
write_in_progress <= spi_out[0];
if ((~spi_out[0])&&(write_in_progress))
o_interrupt <= 1'b1;
end else
o_interrupt <= 1'b0;
 
if ((~spi_wr)&&(~spi_busy)&&(o_qspi_cs_n))
begin // We can now go to idle and process a command
o_wb_stall <= 1'b0;
o_wb_ack <= 1'b0;
state <= `WBQSPI_IDLE;
end
end else // if (state == `WBQSPI_WAIT_TIL_IDLE) or anything else
begin
spi_wr <= 1'b0;
spi_hold <= 1'b0;
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spif_req <= 1'b0;
if ((~spi_busy)&&(o_qspi_cs_n)&&(~spi_wr)) // Wait for a full
begin // clearing of the SPI port before moving on
state <= `WBQSPI_IDLE;
o_wb_stall <= 1'b0;
o_wb_ack <= 1'b0; // Shouldn't be acking anything here
end
end
 
endmodule
/rtl/llqspi.v
0,0 → 1,339
//
//
// Filename: llqspi.v
//
// Project: FPGA library development (Basys-3 development board)
//
// Purpose: Reads/writes a word (user selectable number of bytes) of data
// to/from a Quad SPI port. The port is understood to be
// a normal SPI port unless the driver requests four bit mode.
// When not in use, unlike our previous SPI work, no bits will
// toggle.
//
// Creator: Dan Gisselquist
// Gisselquist Tecnology, LLC
//
// Copyright: 2015
//
//
`define QSPI_IDLE 0
`define QSPI_START 1
`define QSPI_BITS 2
`define QSPI_READY 3
`define QSPI_STOP 4
`define QSPI_STOP_B 5
 
// Modes
`define QSPI_MOD_SPI 2'b00
`define QSPI_MOD_QOUT 2'b10
`define QSPI_MOD_QIN 2'b11
 
module llqspi(i_clk,
// Module interface
i_wr, i_hold, i_word, i_len, i_spd, i_dir,
o_word, o_valid, o_busy,
// QSPI interface
o_sck, o_cs_n, o_mod, o_dat, i_dat,
// Wbscope interface
o_dbg);
input i_clk;
// Chip interface
// Can send info
// i_dir = 1, i_spd = 0, i_hold = 0, i_wr = 1,
// i_word = { 1'b0, 32'info to send },
// i_len = # of bytes in word-1
input i_wr, i_hold;
input [31:0] i_word;
input [1:0] i_len; // 0=>8bits, 1=>16 bits, 2=>24 bits, 3=>32 bits
input i_spd; // 0 -> normal QPI, 1 -> QSPI
input i_dir; // 0 -> read, 1 -> write to SPI
output reg [31:0] o_word;
output reg o_valid, o_busy;
// Interface with the QSPI lines
output reg o_sck;
output reg o_cs_n;
output reg [1:0] o_mod;
output reg [3:0] o_dat;
input [3:0] i_dat;
output wire [22:0] o_dbg;
 
assign o_dbg = { state, spi_len, // 3+6+ 14
o_busy, o_valid, o_cs_n, o_sck, o_mod, o_dat, i_dat };
 
// Timing:
//
// Tick Clk BSY/WR CS_n BIT/MO STATE
// 0 1 0/0 1 -
// 1 1 0/1 1 -
// 2 1 1/0 0 - QSPI_START
// 3 0 1/0 0 - QSPI_START
// 4 0 1/0 0 0 QSPI_BITS
// 5 1 1/0 0 0 QSPI_BITS
// 6 0 1/0 0 1 QSPI_BITS
// 7 1 1/0 0 1 QSPI_BITS
// 8 0 1/0 0 2 QSPI_BITS
// 9 1 1/0 0 2 QSPI_BITS
// 10 0 1/0 0 3 QSPI_BITS
// 11 1 1/0 0 3 QSPI_BITS
// 12 0 1/0 0 4 QSPI_BITS
// 13 1 1/0 0 4 QSPI_BITS
// 14 0 1/0 0 5 QSPI_BITS
// 15 1 1/0 0 5 QSPI_BITS
// 16 0 1/0 0 6 QSPI_BITS
// 17 1 1/1 0 6 QSPI_BITS
// 18 0 1/1 0 7 QSPI_READY
// 19 1 0/1 0 7 QSPI_READY
// 20 0 1/0/V 0 8 QSPI_BITS
// 21 1 1/0 0 8 QSPI_BITS
// 22 0 1/0 0 9 QSPI_BITS
// 23 1 1/0 0 9 QSPI_BITS
// 24 0 1/0 0 10 QSPI_BITS
// 25 1 1/0 0 10 QSPI_BITS
// 26 0 1/0 0 11 QSPI_BITS
// 27 1 1/0 0 11 QSPI_BITS
// 28 0 1/0 0 12 QSPI_BITS
// 29 1 1/0 0 12 QSPI_BITS
// 30 0 1/0 0 13 QSPI_BITS
// 31 1 1/0 0 13 QSPI_BITS
// 32 0 1/0 0 14 QSPI_BITS
// 33 1 1/0 0 14 QSPI_BITS
// 34 0 1/0 0 15 QSPI_READY
// 35 1 1/0 0 15 QSPI_READY
// 36 1 1/0/V 0 - QSPI_STOP
// 37 1 1/0 0 - QSPI_STOPB
// 38 1 1/0 1 - QSPI_IDLE
// 39 1 0/0 1 -
// Now, let's switch from single bit to quad mode
// 40 1 0/0 1 - QSPI_IDLE
// 41 1 0/1 1 - QSPI_IDLE
// 42 1 1/0 0 - QSPI_START
// 43 0 1/0 0 - QSPI_START
// 44 0 1/0 0 0 QSPI_BITS
// 45 1 1/0 0 0 QSPI_BITS
// 46 0 1/0 0 1 QSPI_BITS
// 47 1 1/0 0 1 QSPI_BITS
// 48 0 1/0 0 2 QSPI_BITS
// 49 1 1/0 0 2 QSPI_BITS
// 50 0 1/0 0 3 QSPI_BITS
// 51 1 1/0 0 3 QSPI_BITS
// 52 0 1/0 0 4 QSPI_BITS
// 53 1 1/0 0 4 QSPI_BITS
// 54 0 1/0 0 5 QSPI_BITS
// 55 1 1/0 0 5 QSPI_BITS
// 56 0 1/0 0 6 QSPI_BITS
// 57 1 1/1/QR 0 6 QSPI_BITS
// 58 0 1/1/QR 0 7 QSPI_READY
// 59 1 0/1/QR 0 7 QSPI_READY
// 60 0 1/0/?/V 0 8-11 QSPI_BITS
// 61 1 1/0/? 0 8-11 QSPI_BITS
// 62 0 1/0/? 0 12-15 QSPI_BITS
// 63 1 1/0/? 0 12-15 QSPI_BITS
// 64 1 1/0/?/V 0 - QSPI_STOP
// 65 1 1/0/? 0 - QSPI_STOPB
// 66 1 1/0/? 1 - QSPI_IDLE
// 67 1 0/0 1 - QSPI_IDLE
// Now let's try something entirely in Quad read mode, from the
// beginning
// 68 1 0/1/QR 1 - QSPI_IDLE
// 69 1 1/0 0 - QSPI_START
// 70 0 1/0 0 - QSPI_START
// 71 0 1/0 0 0-3 QSPI_BITS
// 72 1 1/0 0 0-3 QSPI_BITS
// 73 0 1/1/QR 0 4-7 QSPI_BITS
// 74 1 0/1/QR 0 4-7 QSPI_BITS
// 75 0 1/?/?/V 0 8-11 QSPI_BITS
// 76 1 1/?/? 0 8-11 QSPI_BITS
// 77 0 1/1/QR 0 12-15 QSPI_BITS
// 78 1 0/1/QR 0 12-15 QSPI_BITS
// 79 0 1/?/?/V 0 16-19 QSPI_BITS
// 80 1 1/0 0 16-19 QSPI_BITS
// 81 0 1/0 0 20-23 QSPI_BITS
// 82 1 1/0 0 20-23 QSPI_BITS
// 83 1 1/0/V 0 - QSPI_STOP
// 84 1 1/0 0 - QSPI_STOPB
// 85 1 1/0 1 - QSPI_IDLE
// 86 1 0/0 1 - QSPI_IDLE
 
wire i_miso;
assign i_miso = i_dat[1];
 
reg r_spd, r_dir;
reg [5:0] spi_len;
reg [31:0] r_word;
reg [30:0] r_input;
reg [2:0] state;
initial state = `QSPI_IDLE;
initial o_sck = 1'b1;
initial o_cs_n = 1'b1;
initial o_dat = 4'hd;
initial o_valid = 1'b0;
initial o_busy = 1'b0;
initial r_input = 31'h000;
always @(posedge i_clk)
if ((state == `QSPI_IDLE)&&(o_sck))
begin
o_cs_n <= 1'b1;
o_valid <= 1'b0;
o_busy <= 1'b0;
o_mod <= `QSPI_MOD_SPI;
if (i_wr)
begin
r_word <= i_word;
state <= `QSPI_START;
r_spd <= i_spd;
r_dir <= i_dir;
spi_len<= { 1'b0, i_len, 3'b000 } + 6'h8;
o_cs_n <= 1'b0;
o_busy <= 1'b1;
o_sck <= 1'b1;
end
end else if (state == `QSPI_START)
begin // We come in here with sck high, stay here 'til sck is low
o_sck <= 1'b0;
if (o_sck == 1'b0)
begin
state <= `QSPI_BITS;
spi_len<= spi_len - ( (r_spd)? 6'h4 : 6'h1 );
if (r_spd)
r_word <= { r_word[27:0], 4'h0 };
else
r_word <= { r_word[30:0], 1'b0 };
end
o_mod <= (r_spd) ? { 1'b1, r_dir } : `QSPI_MOD_SPI;
o_cs_n <= 1'b0;
o_busy <= 1'b1;
o_valid <= 1'b0;
if (r_spd)
begin
o_dat <= r_word[31:28];
// r_word <= { r_word[27:0], 4'h0 };
end else begin
o_dat <= { 3'b110, r_word[31] };
// r_word <= { r_word[30:0], 1'b0 };
end
end else if (~o_sck)
begin
o_sck <= 1'b1;
o_busy <= ((state != `QSPI_READY)||(~i_wr));
o_valid <= 1'b0;
end else if (state == `QSPI_BITS)
begin
// Should enter into here with at least a spi_len
// of one, perhaps more
o_sck <= 1'b0;
o_busy <= 1'b1;
if (r_spd)
begin
o_dat <= r_word[31:28];
r_word <= { r_word[27:0], 4'h0 };
spi_len <= spi_len - 6'h4;
if (spi_len == 6'h4)
state <= `QSPI_READY;
end else begin
o_dat <= { 3'b110, r_word[31] };
r_word <= { r_word[30:0], 1'b0 };
spi_len <= spi_len - 6'h1;
if (spi_len == 6'h1)
state <= `QSPI_READY;
end
 
o_valid <= 1'b0;
if (~o_mod[1])
r_input <= { r_input[29:0], i_miso };
else if (o_mod[1])
r_input <= { r_input[26:0], i_dat };
end else if (state == `QSPI_READY)
begin
o_valid <= 1'b0;
o_cs_n <= 1'b0;
o_busy <= 1'b1;
// This is the state on the last clock (both low and
// high clocks) of the data. Data is valid during
// this state. Here we chose to either STOP or
// continue and transmit more.
o_sck <= (i_hold); // Stay here on hold, no clocks
if((~o_busy)&&(i_wr))// Acknowledge a new request
begin
state <= `QSPI_BITS;
o_busy <= 1'b1;
o_sck <= 1'b0;
 
// Read the new request off the bus
r_spd <= i_spd;
r_dir <= i_dir;
// Set up the first bits on the bus
o_mod <= (i_spd) ? { 1'b1, i_dir } : `QSPI_MOD_SPI;
if (i_spd)
begin
o_dat <= i_word[31:28];
r_word <= { i_word[27:0], 4'h0 };
// spi_len <= spi_len - 4;
spi_len<= { 1'b0, i_len, 3'b000 } + 6'h8
- 6'h4;
end else begin
o_dat <= { 3'b110, i_word[31] };
r_word <= { i_word[30:0], 1'b0 };
spi_len<= { 1'b0, i_len, 3'b000 } + 6'h8
- 6'h1;
end
 
// Read a bit upon any transition
o_valid <= 1'b1;
if (~o_mod[1])
begin
r_input <= { r_input[29:0], i_miso };
o_word <= { r_input[30:0], i_miso };
end else if (o_mod[1])
begin
r_input <= { r_input[26:0], i_dat };
o_word <= { r_input[27:0], i_dat };
end
end else if (i_hold)
begin // Stay here, holding the clock high, if the user
// has more data, but it isn't ready yet.
o_busy <= 1'b0;
end else begin
o_sck <= 1'b1;
state <= `QSPI_STOP;
 
// Read a bit upon any transition
o_valid <= 1'b1;
if (~o_mod[1])
begin
r_input <= { r_input[29:0], i_miso };
o_word <= { r_input[30:0], i_miso };
end else if (o_mod[1])
begin
r_input <= { r_input[26:0], i_dat };
o_word <= { r_input[27:0], i_dat };
end
end
end else if (state == `QSPI_STOP)
begin
o_sck <= 1'b1; // Stop the clock
o_valid <= 1'b0; // Output may have just been valid, but no more
o_busy <= 1'b1; // Still busy till port is clear
state <= `QSPI_STOP_B;
o_mod <= `QSPI_MOD_SPI;
end else if (state == `QSPI_STOP_B)
begin
o_cs_n <= 1'b1;
o_sck <= 1'b1;
// Do I need this????
// spi_len <= 3; // Minimum CS high time before next cmd
state <= `QSPI_IDLE;
o_valid <= 1'b0;
o_busy <= 1'b1;
o_mod <= `QSPI_MOD_SPI;
end else begin // Invalid states, should never get here
state <= `QSPI_STOP;
o_valid <= 1'b0;
o_busy <= 1'b1;
o_cs_n <= 1'b1;
o_sck <= 1'b1;
o_mod <= `QSPI_MOD_SPI;
o_dat <= 4'hd;
end
 
endmodule
 
/doc/spec.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
doc/spec.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/src/gpl-3.0.tex =================================================================== --- doc/src/gpl-3.0.tex (nonexistent) +++ doc/src/gpl-3.0.tex (revision 2) @@ -0,0 +1,719 @@ +\documentclass[11pt]{article} + +\title{GNU GENERAL PUBLIC LICENSE} +\date{Version 3, 29 June 2007} + +\begin{document} +\maketitle + +\begin{center} +{\parindent 0in + +Copyright \copyright\ 2007 Free Software Foundation, Inc. \texttt{http://fsf.org/} + +\bigskip +Everyone is permitted to copy and distribute verbatim copies of this + +license document, but changing it is not allowed.} + +\end{center} + +\renewcommand{\abstractname}{Preamble} +\begin{abstract} +The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + +Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. +\end{abstract} + +\begin{center} +{\Large \sc Terms and Conditions} +\end{center} + + +\begin{enumerate} + +\addtocounter{enumi}{-1} + +\item Definitions. + +``This License'' refers to version 3 of the GNU General Public License. + +``Copyright'' also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +``The Program'' refers to any copyrightable work licensed under this +License. Each licensee is addressed as ``you''. ``Licensees'' and +``recipients'' may be individuals or organizations. + +To ``modify'' a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a ``modified version'' of the +earlier work or a work ``based on'' the earlier work. + +A ``covered work'' means either the unmodified Program or a work based +on the Program. + +To ``propagate'' a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To ``convey'' a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays ``Appropriate Legal Notices'' +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +\item Source Code. + +The ``source code'' for a work means the preferred form of the work +for making modifications to it. ``Object code'' means any non-source +form of a work. + +A ``Standard Interface'' means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The ``System Libraries'' of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +``Major Component'', in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The ``Corresponding Source'' for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +The Corresponding Source for a work in source code form is that +same work. + +\item Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +\item Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +\item Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +\item Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + \begin{enumerate} + \item The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + \item The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + ``keep intact all notices''. + + \item You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + \item If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. +\end{enumerate} +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +``aggregate'' if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +\item Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + \begin{enumerate} + \item Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + \item Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + \item Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + \item Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + \item Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + \end{enumerate} + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A ``User Product'' is either (1) a ``consumer product'', which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, ``normally used'' refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +``Installation Information'' for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +\item Additional Terms. + +``Additional permissions'' are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + \begin{enumerate} + \item Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + \item Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + \item Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + \item Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + \item Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + \item Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + \end{enumerate} + +All other non-permissive additional terms are considered ``further +restrictions'' within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +\item Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +\item Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +\item Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An ``entity transaction'' is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +\item Patents. + +A ``contributor'' is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's ``contributor version''. + +A contributor's ``essential patent claims'' are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, ``control'' includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a ``patent license'' is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To ``grant'' such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. ``Knowingly relying'' means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is ``discriminatory'' if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +\item No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +\item Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +\item Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License ``or any later version'' applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +\item Disclaimer of Warranty. + +\begin{sloppypar} + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY + APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE + COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE + RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. + SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL + NECESSARY SERVICING, REPAIR OR CORRECTION. +\end{sloppypar} + +\item Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES + AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL + DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM + (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED + INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE + OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH + HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES. + +\item Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +\begin{center} +{\Large\sc End of Terms and Conditions} + +\bigskip +How to Apply These Terms to Your New Programs +\end{center} + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the ``copyright'' line and a pointer to where the full notice is found. + +{\footnotesize +\begin{verbatim} + + +Copyright (C) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +\end{verbatim} +} + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +{\footnotesize +\begin{verbatim} + Copyright (C) + +This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +This is free software, and you are welcome to redistribute it +under certain conditions; type `show c' for details. +\end{verbatim} +} + +The hypothetical commands {\tt show w} and {\tt show c} should show +the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an ``about box''. + +You should also get your employer (if you work as a programmer) or +school, if any, to sign a ``copyright disclaimer'' for the program, if +necessary. For more information on this, and how to apply and follow +the GNU GPL, see \texttt{http://www.gnu.org/licenses/}. + +The GNU General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use +the GNU Lesser General Public License instead of this License. But +first, please read \texttt{http://www.gnu.org/philosophy/why-not-lgpl.html}. + +\end{enumerate} + +\end{document} Index: doc/src/GT.eps =================================================================== --- doc/src/GT.eps (nonexistent) +++ doc/src/GT.eps (revision 2) @@ -0,0 +1,94 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 504 288 +%%Creator: Gisselquist Technology LLC +%%Title: Gisselquist Technology Logo +%%CreationDate: 11 Mar 2014 +%%EndComments +%%BeginProlog +/black { 0 setgray } def +/white { 1 setgray } def +/height { 288 } def +/lw { height 8 div } def +%%EndProlog +% %%Page: 1 + +false { % A bounding box + 0 setlinewidth + newpath + 0 0 moveto + 0 height lineto + 1.625 height mul lw add 0 rlineto + 0 height neg rlineto + closepath stroke +} if + +true { % The "G" + newpath + height 2 div 1.25 mul height moveto + height 2 div height 4 div sub height lineto + 0 height 3 4 div mul lineto + 0 height 4 div lineto + height 4 div 0 lineto + height 3 4 div mul 0 lineto + height height 4 div lineto + height height 2 div lineto + % + height lw sub height 2 div lineto + height lw sub height 4 div lw 2 div add lineto + height 3 4 div mul lw 2 div sub lw lineto + height 4 div lw 2 div add lw lineto + lw height 4 div lw 2 div add lineto + lw height 3 4 div mul lw 2 div sub lineto + height 4 div lw 2 div add height lw sub lineto + height 2 div 1.25 mul height lw sub lineto + closepath fill + newpath + height 2 div height 2 div moveto + height 2 div 0 rlineto + 0 height 2 div neg rlineto + lw neg 0 rlineto + 0 height 2 div lw sub rlineto + height 2 div height 2 div lw sub lineto + closepath fill +} if + +height 2 div 1.25 mul lw add 0 translate +false { + newpath + 0 height moveto + height 0 rlineto + 0 lw neg rlineto + height lw sub 2 div neg 0 rlineto + 0 height lw sub neg rlineto + lw neg 0 rlineto + 0 height lw sub rlineto + height lw sub 2 div neg 0 rlineto + 0 lw rlineto + closepath fill +} if + +true { % The "T" of "GT". + newpath + 0 height moveto + height lw add 2 div 0 rlineto + 0 height neg rlineto + lw neg 0 rlineto + 0 height lw sub rlineto + height lw sub 2 div neg 0 rlineto + closepath fill + + % The right half of the top of the "T" + newpath + % (height + lw)/2 + lw + height lw add 2 div lw add height moveto + % height - (above) = height - height/2 - 3/2 lw = height/2-3/2lw + height 3 lw mul sub 2 div 0 rlineto + 0 lw neg rlineto + height 3 lw mul sub 2 div neg 0 rlineto + closepath fill +} if + + +grestore +showpage +%%EOF Index: doc/src/gqtekspec.cls =================================================================== --- doc/src/gqtekspec.cls (nonexistent) +++ doc/src/gqtekspec.cls (revision 2) @@ -0,0 +1,296 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/ +% +% Copyright (C) 2015, Gisselquist Technology, LLC +% +% This template is free software: you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by the +% Free Software Foundation, either version 3 of the License, or (at your +% option) any later version. +% +% This template is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +% for more details. +% +% You should have received a copy of the GNU General Public License along +% with this program. If not, see for a copy. +% +% License: GPL, v3, as defined and found on www.gnu.org, +% http://www.gnu.org/licenses/gpl.html +% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesClass{gqtekspec}[2015/03/03 v0.1 -- Gisselquist Technology Specification] +\typeout{by Dan Gisselquist} +\LoadClassWithOptions{report} +\usepackage{datetime} +\usepackage{graphicx} +\usepackage[dvips]{pstricks} +\usepackage{hhline} +\usepackage{colortbl} +\newdateformat{headerdate}{\THEYEAR/\twodigit{\THEMONTH}/\twodigit{\THEDAY}} +\setlength{\hoffset}{0.25in} +\setlength{\voffset}{-0.5in} +\setlength{\marginparwidth}{0in} +\setlength{\marginparsep}{0in} +\setlength{\textwidth}{6in} +\setlength{\oddsidemargin}{0in} + +% ************************************** +% * APPENDIX * +% ************************************** +% +\newcommand\appfl@g{\appendixname} %used to test \@chapapp +% +% \renewcommand\appendix{\par\clearpage + % \setcounter{chapter}{0}% + % \setcounter{section}{0}% + % \renewcommand\@chapapp{\appendixname}% + % \renewcommand\thechapter{\Alph{chapter}} + % \if@nosectnum\else + % \renewcommand\thesection{\Alph{chapter}.\arabic{section}} + % \fi +% } + + +% FIGURE +% redefine the @caption command to put a period after the figure or +% table number in the lof and lot tables +\long\def\@caption#1[#2]#3{\par\addcontentsline{\csname + ext@#1\endcsname}{#1}{\protect\numberline{\csname + the#1\endcsname.}{\ignorespaces #2}}\begingroup + \@parboxrestore + \normalsize + \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par + \endgroup} + +% **************************************** +% * TABLE OF CONTENTS, ETC. * +% **************************************** + +\renewcommand\contentsname{Contents} +\renewcommand\listfigurename{Figures} +\renewcommand\listtablename{Tables} + +\newif\if@toc \@tocfalse +\renewcommand\tableofcontents{% + \begingroup% temporarily set if@toc so that \@schapter will not + % put Table of Contents in the table of contents. + \@toctrue + \chapter*{\contentsname} + \endgroup + \thispagestyle{gqtekspecplain} + + \baselineskip=10pt plus .5pt minus .5pt + + {\raggedleft Page \par\vskip-\parskip} + \@starttoc{toc}% + \baselineskip=\normalbaselineskip + } + +\def\l@appendix{\pagebreak[3] + \vskip 1.0em plus 1pt % space above appendix line + \@dottedtocline{0}{0em}{8em}} + +\def\l@chapter{\pagebreak[3] + \vskip 1.0em plus 1pt % space above appendix line + \@dottedtocline{0}{0em}{4em}} + +% \if@nosectnum\else + % \renewcommand\l@section{\@dottedtocline{1}{5.5em}{2.4em}} + % \renewcommand\l@subsection{\@dottedtocline{2}{8.5em}{3.2em}} + % \renewcommand\l@subsubsection{\@dottedtocline{3}{11em}{4.1em}} + % \renewcommand\l@paragraph{\@dottedtocline{4}{13.5em}{5em}} + % \renewcommand\l@subparagraph{\@dottedtocline{5}{16em}{6em}} +% \fi + +% LIST OF FIGURES +% +\def\listoffigures{% + \begingroup + \chapter*{\listfigurename}% + \endgroup + \thispagestyle{gqtekspecplain}% + + \baselineskip=10pt plus .5pt minus .5pt% + + {\hbox to \hsize{Figure\hfil Page} \par\vskip-\parskip}% + + \rule[2mm]{\textwidth}{0.5mm}\par + + \@starttoc{lof}% + \baselineskip=\normalbaselineskip}% + +\def\l@figure{\@dottedtocline{1}{1em}{4.0em}} + +% LIST OF TABLES +% +\def\listoftables{% + \begingroup + \chapter*{\listtablename}% + \endgroup + \thispagestyle{gqtekspecplain}% + \baselineskip=10pt plus .5pt minus .5pt% + {\hbox to \hsize{Table\hfil Page} \par\vskip-\parskip}% + + % Added line underneath headings, 20 Jun 01, Capt Todd Hale. + \rule[2mm]{\textwidth}{0.5mm}\par + + \@starttoc{lot}% + \baselineskip=\normalbaselineskip}% + +\let\l@table\l@figure + +% **************************************** +% * PAGE STYLES * +% **************************************** +% +\def\ps@gqtekspectoc{% + \let\@mkboth\@gobbletwo + \def \@oddhead{} + \def \@oddfoot{\rm + \hfil\raisebox{-9pt}{\thepage}\hfil\thispagestyle{gqtekspectocn}} + \let \@evenhead\@oddhead \let \@evenfoot\@oddfoot} +\def\ps@gqtekspectocn{\let\@mkboth\@gobbletwo + \def \@oddhead{\rm \hfil\raisebox{10pt}{Page}} + \def \@oddfoot{\rm + \hfil\raisebox{-9pt}{\thepage}\hfil\thispagestyle{gqtekspectocn}} + \let \@evenhead\@oddhead \let \@evenfoot\@oddfoot} + +\def\ps@gqtekspeclof{\let\@mkboth\@gobbletwo + \def \@oddhead{} + \def \@oddfoot{\rm + \hfil\raisebox{-9pt}{\thepage}\hfil\thispagestyle{gqtekspeclofn}} + \let \@evenhead\@oddhead \let \@evenfoot\@oddfoot} +\def\ps@gqtekspeclofn{\let\@mkboth\@gobbletwo + \def \@oddhead{\rm + \parbox{\textwidth}{\raisebox{0pt}{Figure}\hfil\raisebox{0pt}{Page} % + \raisebox{20pt}{\rule[10pt]{\textwidth}{0.5mm}} }} + + \def \@oddfoot{\rm + \hfil\raisebox{-9pt}{\thepage}\hfil\thispagestyle{gqtekspeclofn}} + \let \@evenhead\@oddhead \let \@evenfoot\@oddfoot} + +\def\ps@gqtekspeclot{\let\@mkboth\@gobbletwo + \def \@oddhead{} + \def \@oddfoot{\rm + \hfil\raisebox{-9pt}{\thepage}\hfil\thispagestyle{gqtekspeclotn}} + \let \@evenhead\@oddhead \let \@evenfoot\@oddfoot} +\def\ps@gqtekspeclotn{\let\@mkboth\@gobbletwo + \def \@oddhead{\rm + \parbox{\textwidth}{\raisebox{0pt}{Table}\hfil\raisebox{0pt}{Page} % + \raisebox{20pt}{\rule[10pt]{\textwidth}{0.5mm}} }} + + \def \@oddfoot{\rm + \hfil\raisebox{-9pt}{\thepage}\hfil\thispagestyle{gqtekspeclotn}} + \let \@evenhead\@oddhead \let \@evenfoot\@oddfoot} + +\def\ps@gqtekspecplain{\let\@mkboth\@gobbletwo + \def \@oddhead{\rput(0,-2pt){\psline(0,0)(\textwidth,0)}\rm \hbox to 1in{\includegraphics[height=0.8\headheight]{GT.eps} Gisselquist Technology, LLC}\hfil\hbox{\@title}\hfil\hbox to 1in{\hfil\headerdate\@date}} + \def \@oddfoot{\rput(0,9pt){\psline(0,0)(\textwidth,0)}\rm \hbox to 1in{www.opencores.com\hfil}\hfil\hbox{\r@vision}\hfil\hbox to 1in{\hfil{\thepage}}} + \let \@evenhead\@oddhead \let \@evenfoot\@oddfoot} + +% \def\author#1{\def\auth@r{#1}} +% \def\title#1{\def\ti@tle{#1}} + +\def\logo{\begin{pspicture}(0,0)(5.67in,0.75in) + \rput[lb](0.05in,0.10in){\includegraphics[height=0.75in]{GT.eps}} + \rput[lb](1.15in,0.05in){\scalebox{1.8}{\parbox{2.0in}{Gisselquist\\Technology, LLC}}} + \end{pspicture}} +% TITLEPAGE +% +\def\titlepage{\setcounter{page}{1} + \typeout{^^JTitle Page.} + \thispagestyle{empty} + \leftline{\rput(0,0){\psline(0,0)(\textwidth,0)}\hfill} + \vskip 2\baselineskip + \logo\hfil % Original is 3.91 in x 1.26 in, let's match V thus + \vskip 2\baselineskip + \vspace*{10pt}\vfil + \begin{minipage}{\textwidth}\raggedleft + \ifproject{\Huge\bfseries\MakeUppercase\@project} \\\fi + \vspace*{15pt} + {\Huge\bfseries\MakeUppercase\@title} \\ + \vskip 10\baselineskip + \Large \@author \\ + \ifemail{\Large \@email}\\\fi + \vskip 6\baselineskip + \Large \usdate\@date \\ + \end{minipage} + % \baselineskip 22.5pt\large\rm\MakeUppercase\ti@tle + \vspace*{30pt} + \vfil + \newpage\baselineskip=\normalbaselineskip} + +\newenvironment{license}{\clearpage\typeout{^^JLicense Page.}\ \vfill\noindent}% + {\vfill\newpage} +% **************************************** +% * CHAPTER DEFINITIONS * +% **************************************** +% +\renewcommand\chapter{\if@openright\cleardoublepage\else\clearpage\fi + \thispagestyle{gqtekspecplain}% + \global\@topnum\z@ + \@afterindentfalse + \secdef\@chapter\@schapter} +\renewcommand\@makechapterhead[1]{% + \hbox to \textwidth{\hfil\scalebox{1.8}{\Huge\bfseries \thechapter.}}\vskip 10\p@ + \hbox to \textwidth{\rput(0,0){\psline[linewidth=0.04in](0,0)(\textwidth,0)}}\vskip \p@ + \hbox to \textwidth{\rput(0,0){\psline[linewidth=0.04in](0,0)(\textwidth,0)}}\vskip 10\p@ + \hbox to \textwidth{\hfill\scalebox{1.8}{\huge\bfseries #1}}% + \par\nobreak\vskip 40\p@} +\renewcommand\@makeschapterhead[1]{% + \hbox to \textwidth{\hfill\scalebox{1.8}{\huge\bfseries #1}}% + \par\nobreak\vskip 40\p@} +% **************************************** +% * INITIALIZATION * +% **************************************** +% +% Default initializations + +\ps@gqtekspecplain % 'gqtekspecplain' page style with lowered page nos. +\onecolumn % Single-column. +\pagenumbering{roman} % the first chapter will change pagenumbering + % to arabic +\setcounter{page}{1} % in case a titlepage is not requested + % otherwise titlepage sets page to 1 since the + % flyleaf is not counted as a page +\widowpenalty 10000 % completely discourage widow lines +\clubpenalty 10000 % completely discourage club (orphan) lines +\raggedbottom % don't force alignment of bottom of pages + +\date{\today} +\newif\ifproject\projectfalse +\def\project#1{\projecttrue\gdef\@project{#1}} +\def\@project{} +\newif\ifemail\emailfalse +\def\email#1{\emailtrue\gdef\@email{#1}} +\def\@email{} +\def\revision#1{\gdef\r@vision{#1}} +\def\r@vision{} +\def\at{\makeatletter @\makeatother} +\newdateformat{theyear}{\THEYEAR} +\newenvironment{revisionhistory}{\clearpage\typeout{^^JRevision History.}% + \hbox to \textwidth{\hfil\scalebox{1.8}{\large\bfseries Revision History}}\vskip 10\p@\noindent% + \begin{tabular}{|p{0.5in}|p{1in}|p{1in}|p{2.875in}|}\hline + \rowcolor[gray]{0.8} Rev. & Date & Author & Description\\\hline\hline} + {\end{tabular}\clearpage} +\newenvironment{clocklist}{\begin{tabular}{|p{0.75in}|p{0.5in}|l|l|p{2.875in}|}\hline + \rowcolor[gray]{0.85} Name & Source & \multicolumn{2}{l|}{Rates (MHz)} & Description \\\hhline{~|~|-|-|~}% + \rowcolor[gray]{0.85} & & Max & Min & \\\hline\hline}% + {\end{tabular}} +\newenvironment{reglist}{\begin{tabular}{|p{0.75in}|p{0.5in}|p{0.5in}|p{0.5in}|p{2.875in}|}\hline + \rowcolor[gray]{0.85} Name & Address & Width & Access & Description \\\hline\hline}% + {\end{tabular}} +\newenvironment{bitlist}{\begin{tabular}{|p{0.5in}|p{0.5in}|p{3.875in}|}\hline + \rowcolor[gray]{0.85} Bit \# & Access & Description \\\hline\hline}% + {\end{tabular}} +\newenvironment{portlist}{\begin{tabular}{|p{0.75in}|p{0.5in}|p{0.75in}|p{3.375in}|}\hline + \rowcolor[gray]{0.85} Port & Width & Direction & Description \\\hline\hline}% + {\end{tabular}} +\newenvironment{wishboneds}{\begin{tabular}{|p{2.5in}|p{2.5in}|}\hline + \rowcolor[gray]{0.85} Description & Specification \\\hline\hline}% + {\end{tabular}} +\newenvironment{preface}{\chapter*{Preface}}{\par\bigskip\bigskip\leftline{\hfill\@author}} +\endinput Index: doc/src/spec.tex =================================================================== --- doc/src/spec.tex (nonexistent) +++ doc/src/spec.tex (revision 2) @@ -0,0 +1,654 @@ +\documentclass{gqtekspec} +\project{Quad SPI Flash Controller} +\title{Specification} +\author{Dan Gisselquist, Ph.D.} +\email{dgisselq\at opencores.org} +\revision{Rev.~0.1} +\begin{document} +\pagestyle{gqtekspecplain} +\titlepage +\begin{license} +Copyright (C) \theyear\today, Gisselquist Technology, LLC + +This project is free software (firmware): you can redistribute it and/or +modify it under the terms of the GNU General Public License as published +by the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see \hbox{} for a copy. +\end{license} +\begin{revisionhistory} +0.1 & 5/13/2015 & Gisselquist & First Draft \\\hline +\end{revisionhistory} +% Revision History +% Table of Contents, named Contents +\tableofcontents +\listoffigures +\listoftables +\begin{preface} +The genesis of this project was a desire to communicate with and program an +FPGA board without the need for any proprietary tools. This includes Xilinx +JTAG cables, or other proprietary loading capabilities such as Digilent's +Adept program. As a result, all interactions with the board need to take +place using open source tools, and the board must be able to reprogram itself. +\end{preface} + +\chapter{Introduction} +\pagenumbering{arabic} +\setcounter{page}{1} + +The Quad SPI Flash controller handles all necessary queries and accesses to +and from a SPI Flash device that has been augmented with an additional +two data lines and enabled with a mode allowing all four data lines to +work together in the same direction at the same time. Since the interface +was derived from a SPI interface, most of the interaction takes place using +normal SPI protocols and only some commands work at the higher four bits +at a time speed. + +This particular controller attempts to mask the underlying operation of the +SPI device behind a wishbone interface, to make it so that reads and writes +are as simple as using the wishbone interface. However, the difference +between erasing (turning bits from '0' to '1') and programming (turning bits +from '1' to '0') breaks this model somewhat. Therefore, reads from the +device act like normal wishbone reads, writes program the device and +sort of work with the wishbone, while erase commands require another register +to control. Please read the Operations chapter for a detailed description +of how to perform these relevant operations. + +This controller implements the interface for the Quad SPI flash found on the +Basys-3 board built by Digilent, Inc. Some portions of the interface may +be specific to the Spansion S25FL032P chip used on this board, and the +100~MHz system clock found on the board, although there is no reason the +controller needs to be limited to this architecture. It just happens to be +the one I have been designing to and for. + +For a description of how the internals of this core work, feel free to browse +through the Architecture chapter. + +The registers that control this core are discussed in the Registers chapter. + +As required, you can find a wishbone datasheet in Chapt.~\ref{chap:wishbone}. + +The final pertinent information for implementing this core is found in the +I/O Ports chapter, Chapt.~\ref{chap:ioports}. + +As always, write me if you have any questions or problems. + +\chapter{Architecture}\label{chap:arch} + +As built, the core consists of only two components: the wishbone quad SPI +flash controller, {\tt wbqspiflash}, and the lower level quad SPI driver, +{\tt llqspi}. The controller issues high level read/write commands to the +lower level driver, which actually implements the Quad SPI protocol. + +Pictorally, this looks something like Fig.~\ref{fig:arch}. +\begin{figure}\begin{center}\begin{pspicture}(-2in,0)(2in,3.5in) +\rput(0,2.5in){ + \rput(-0.9in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}(-0.92in,0.5in){\tt i\_wb\_cyc} + \rput(-0.7in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}(-0.72in,0.5in){\tt i\_wb\_data\_stb} + \rput(-0.5in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}(-0.52in,0.5in){\tt i\_wb\_ctrl\_stb} + \rput(-0.3in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}(-0.32in,0.5in){\tt i\_wb\_we} + \rput(-0.1in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}(-0.12in,0.5in){\tt i\_wb\_addr} + \rput( 0.1in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}( 0.08in,0.5in){\tt i\_wb\_data} + % + \rput( 0.5in,0){\psline{<-}(0,1in)(0,0in)} + \rput[b]{90}( 0.48in,0.5in){\tt o\_wb\_ack} + \rput( 0.7in,0){\psline{<-}(0,1in)(0,0in)} + \rput[b]{90}( 0.68in,0.5in){\tt o\_wb\_stall} + \rput( 0.9in,0){\psline{<-}(0,1in)(0,0in)} + \rput[b]{90}( 0.88in,0.5in){\tt o\_wb\_data}} +\rput(0,2.0in){% + \rput(0,0){\psframe(-1.2in,0)(1.2in,0.5in)} + \rput(0,0.25in){\tt wbqspiflash}} +\rput(0,1.0in){ + \rput(-0.9in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}(-0.92in,0.5in){\tt spi\_wr} + \rput(-0.7in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}(-0.72in,0.5in){\tt spi\_hold} + \rput(-0.5in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}(-0.52in,0.5in){\tt spi\_in} + \rput(-0.3in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}(-0.32in,0.5in){\tt spi\_len} + \rput(-0.1in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}(-0.12in,0.5in){\tt spi\_spd} + \rput( 0.1in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}( 0.08in,0.5in){\tt spi\_dir} + % \rput(-0.9in,0){\psline{->}(0,1in)(0,0in)} + % \rput[b]{90}(-0.92in,0.5in){\tt i\_wb\_cyc} + \rput( 0.5in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}( 0.48in,0.5in){\tt spi\_out} + \rput( 0.7in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}( 0.68in,0.5in){\tt spi\_valid} + \rput( 0.9in,0){\psline{->}(0,1in)(0,0in)} + \rput[b]{90}( 0.88in,0.5in){\tt spi\_busy}} +\rput(0,0.5in){ + \rput(0,0){\psframe(-1.25in,0)(1.25in,0.5in)} + \rput(0,0.25in){\tt llqspi}} + \rput(0,0){\psline{<->}(-0.3in,0.5in)(-0.3in,0) + \psline{<->}(-0.1in,0.5in)(-0.1in,0) + \psline{<->}(0.1in,0.5in)(0.1in,0) + \psline{<->}(0.3in,0.5in)(0.3in,0)} + \rput[l](0.4in,0.25in){Quad SPI I/O lines} +\end{pspicture}\end{center} +\caption{Architecture Diagram}\label{fig:arch} +\end{figure} +This is also what you will find if you browse through the code. + +While it isn't relevant for operating the device, a quick description of these +internal wires may be educational. The lower level device is commanded by +asserting a {\tt spi\_wr} signal when the device is not busy (i.e. {\tt +spi\_busy} is low). The actual command given depends upon the other +signals. {\tt spi\_len} is a two bit value indicating whether this is an +8 bit (2'b00), 16 bit (2'b01), 24 bit (2'b10), or 32 bit (2'b11) transaction. +The data to be sent out the port is placed into {\tt spi\_in}. + +Further, to support Quad I/O, {\tt spi\_spd} can be set to one to use all four +bits. In this case, {\tt spi\_dir} must also be set to either 1'b0 for +writing, or 1'b1 to read from the four bits. + +When data is valid from the lower level driver, the {\tt spi\_valid} line +will go high and {\tt spi\_out} will contain the data with the most recently +read bits in the lower bits. Further, when the device is idle, {\tt spi\_busy} +will go low, where it may then read another command. + +Sadly, this simple interface as originally designed doesn't work on a +device where transactions can be longer than 32~bits. To support these +longer transactions, the lower level driver checks the {\tt spi\_wr} line +before it finishes any transaction. If the line is high, the lower level +driver will deassert {\tt spi\_busy} for one cycle while reading the command +from the controller on the previous cycle. Further, the controller can also +assert the {\tt spi\_hold} line which will stop the clock to the device +and force everything to wait for further instructions. + +This hold line interface was necessary to deal with a slow wishbone bus that +was writing to the device, but that didn't have it's next data line ready. +Thus, by holding the {\tt i\_wb\_cyc} line high, a write could take many +clocks and the flash would simply wait for it. (I was commanding the device +via a serial port, so writes could take {\em many} clock cycles for each +word to come through, i.e. 1,500 clocks or so per word and that's at high +speed.) + +The upper level component, the controller {\tt wbqspiflash}, is little more +than a glorified state machine that interacts with the wishbone bus. +From it's idle state, it can handle any command, whether data or control, +and issue appropriate commands to the lower level driver. From any other +state, it will stall the bus until it comes back to idle--with a few exceptions. +Subsequent data reads, while reading data, will keep the device reading. +Subsequent data writes, while in program mode, will keep filling the devices +buffer before starting the write. In other respects, the device will just +stall the bus until it comes back to idle. + +While they aren't used in this design, the wishbone error and retry signals +would've made a lot of sense here. Specifically, it should be an error to +read from the device while it is in the middle of an erase or program command. +Instead, this core stalls the bus--trying to do good for everyone. Perhaps +a later, updated, implementation will make better use of these signals instead +of stalling. For now, this core just stalls the bus. + +Perhaps the best takeaway from this architecture section is that the varying +pieces of complexity have each been separated from each other. There's a +lower level driver that handles actually toggling the lines to the port, +while the higher level driver maintains the state machine controlling which +commands need to be issued and when. + +\chapter{Operation}\label{chap:ops} +This implementation attempts to encapsulate (hide) the details of the chip +from the user, so that the user does not need to know about the various +subcommands going to and from the chip. The original goal was to make the +chip act like any other read/write memory, however the difference between +erasing and programming the chip made this impossible. Therefore a separate +register is given to erase any given sector, while reads and writes may proceed +(almost) as normal. + +The wishbone bus that this controller works with, however, is a 32--bit +bus. Address one on the bus addresses a completely different 32--bit word +from address zero or address two. Bus select lines are not implemented, +all operations are 32--bit. Further, the device is little--endian, meaning +that the low order byte is the first byte that will be or is stored on the +flash. + +\section{High Level} +From a high level perspective, this core provides read/write access to the +device either via the wishbone (read and program), or through a control +register found on the wishbone (the EREG). Programming the device consists of +first erasing the region of interest. This will set all the bits to '1' in +that region. After erasing the region, the region can then be programmed, +setting some of the '1' bits to '0's. When neither erase nor program +operation is going on, the device may be read. The section will describe +each of those operations in detail. + +To erase a sector of the device, two writes are required to the EREG register. +The first write turns off the write protect bit, whereas the second write +commands the erase itself. The first write should equal \hbox{0x1000\_0000}, +the second should be any address within the sector to be erased together +with setting the high bit of the register or \hbox{0x8000\_0000} plus the +address. After this second write, the controller will issue a write--enable +command to the device, followed by a sector erase command. In summary, +\begin{enumerate} +\item Disable write protect by writing \hbox{\tt 0x1000\_0000} to the EREG + register +\item Command the erase by writing \hbox{\tt 0x8000\_0000} plus the device + address to the EREG register. (Remember, this is the {\em word + address} of interest, not the {\em byte address}.) +\end{enumerate} + +While the device is erasing, the controller will idle while checking the +status register over and over again. Should you wish to read from the EREG +during this time, the high order bit of the EREG register will be set. +Once the erase is complete, this bit will clear, the interrupt line will +be strobed high, and other operations may take then place on the part. Any +attempt to perform another operation on the part prior to that time will stall +the bus until the erase is complete. + +Once an area has been erased, it may then be programmed. To program the device, +first disable the write protect by writing a {\tt 0x1000\_0000} to the EREG +register. After that, you may then write to the area in question whatever +values you wish to program. One 256~byte (64~bus word) page may be programmed +at a time. Pages start on even boundaries, such as addresses {\tt 0x040}, +{\tt 0x080}, {\tt 0x0100}, etc. To program a whole page at a time, write the +64~words of the page to the controller without dropping the {\tt i\_wb\_cyc} +line. Attempts to write more than 64~words will stall the bus, as will +attempts to write more than one page. Writes of less than a page work as well. +In summary, +\begin{enumerate} +\item Disable the write protect by writing a {\tt 0x1000\_0000} to the EREG + register. +\item Write the page of interest to the data memory of the device. + + The first address should start at the beginning of a page (bottom six + bits zero), and end at the end of the page (bottom six bits one, top + bits identical). Writes of less than a page are okay. Writes crossing + page boundaries will stall the device. +\end{enumerate} + +While the device is programming a page, the controller will idle while +checking the status register as it did during an erase. During this idle, +both the EREG register and the device status register may be queried. Once +the status register drops the write in progress line, the top level bit of +the EREG register will be cleared and the interrupt line strobed. Prior to this +time, any other bus operation will stall the bus until the write completes. + +Reads are simple, you just read from the device and the device does everything +you expect. Reads may be pipelined. Further, if the device is ever commanded +to read the configuration register, revealing that the quad SPI mode is +enabled, then reads will take place four bits at a time from the bus. +In general, it will take 72 device clocks (at 50~MHz) to read the first word +from memory, and 32 for every pipelined word read thereafter provided that +the reads are in memory order. Likewise, in quad SPI mode, it will +instead take 28 device clocks to read the first word, and 8 device clocks +to read every word thereafter again provided that the subsequent pipelined +reads are in memory order. + +The Quad SPI device provides for a special mode following a read, where the +next read may start immediately in Quad I/O mode following a 12~clock +setup. This controller leaves the device in this mode following any initial +read. Therefore, back to back reads as part of separate bus cycles will only +take 20~clocks to read the first word, and 8~clocks per word thereafter. +Other commands, however, such as erasing, writing, reading from the status, +configuration, or ID registers, will take require a 32~device clock operation +before entering. + +\section{Low Level} + +At a lower level, this core implements the following Quad SPI commands: +\begin{enumerate} +\item FAST\_READ, when a read is requested and Quad mode has not been enabled. +\item QIOR, or quad I/O high performance read mode. This is the default read + command when Quad mode has been enabled, and it leaves the device + in the Quad I/O High Performance Read mode, ready for a faster second + read command. +\item RDID, or Read identification +\item WREN, or Write Enable, is issued prior to any erase, program, or + write register (i.e. configuration or status) command. + This detail is hidden from the user. +\item RDSR, or read status register, is issued any time the user attempts + to read from the status register. Further, following an erase or a + write command, the device is left reading this register over and over + again until the write completes. +\item RCR, or read configuration, is issued any time a request is made to + read from the configuration register. Following such a read, the + quad I/O may be enabled for the device, if it is enabled in this + register. +\item WRR, or write registers, is issued upon any write to the status or + configuration registers. To separate the two, the last value read + from the status register is written to the status register when + writing the configuration register. +\item PP, or page program, is issued to program the device in serial mode + whenever programming is desired and the quad I/O has not been enabled. +\item QPP, or quad page program, is used to program the device whenever + a write is requested and quad I/O mode has been enabled. +\item SE, or sector erase, is the only type of erase this core supports. +\item CLSR, or Clear Status Register, is issued any time the last status + register had the bits {\tt P\_ERR} or {\tt E\_ERR} set and the + write to the status register attempts to clear one of these. This + command is then issued following the WRR command. +\end{enumerate} + +\chapter{Registers}\label{chap:regs} + +This implementation supports four control registers. These are the EREG +register, the configuration register, the status register, and the device ID, +as shown and listed in Table.~\ref{tbl:reglist}. +\begin{table}[htbp] +\begin{center} +\begin{reglist} +EREG & 0 & 32 & R/W & An overall control register, providing instant status + from the device and controlling erase commands.\\\hline +Config & 1 & 8 & R/W & The devices configuration register.\\\hline +Status & 2 & 8 & R/W & The devices status register.\\\hline +ID & 3 & 16 & R & Reads the 16-bit ID from the device.\\\hline +\end{reglist} +\caption{List of Registers}\label{tbl:reglist} +\end{center}\end{table} + +\section{EREG Register} +The EREG register was designed to be a replacement for all of the device +registers, leaving all the other registers a part of a lower level access +used only in debugging the device. This would've been the case, save that +one may need to set bit one of the configuration register to enter high +speed mode. + +The bits associated with this register are listed in Tbl.~\ref{tbl:eregbits}. + +\begin{table}[htbp] +\begin{center} +\begin{bitlist} +31 & R/W & Write in Progress/Erase. On a read, this bit will be high if any + write or erase operation is in progress, zero otherwise. To erase + a sector, set this bit to a one. Otherwise, writes should keep this + register at zero.\\\hline +30 & R & Dirty bit. The sector referenced has been written to since it + was erased. This bit is meaningless between startup and the first + erase, but valid afterwards.\\\hline +29 & R & Busy bit. This bit returns a one any time the lower level Quad + SPI core is active. However, to read this register, the lower level + core must be inactive, so this register should always read zero. + \\\hline +28 & R/W & Disable write protect. Set this to a one to disable the write + protect mode, or to a zero to re--enable write protect on this chip. + Note that this register is not self--clearing. Therefore, write + protection may still be disabled following an erase or a write. + Clear this manually when you wish to re--enable write protection. + \\\hline +27 & R & Returns a one if the device is in high speed (4-bit I/O) mode. + To set the device into high speed mode, set bit~1 of the configuration + register.\\\hline +20--26 & R & Always return zero.\\\hline +14--19 & R/W & The sector address bits of the last sector erased. If the + erase line bit is set while writing this register, these bits + will be set as well with the sector being erased.\\\hline +0--13 & R & Always return zero.\\\hline +\end{bitlist} +\caption{EREG bit definitions}\label{tbl:eregbits} +\end{center}\end{table} + +In general, only three bits and an address are of interest here. + +The first bit of interest is bit 27, which will tell you if you are in Quad--I/O +mode. The device will automatically start up in SPI serial mode. Upon +reading the configuration register, it will transition to Quad--I/O mode if +the QUAD bit is set. Likewise, if the bit is written to the configuration +register it will transition to Quad--I/O mode. + +While this may seem kind of strange, I have found this setup useful. It allows +me to debug commands that might work in serial mode but not quad I/O mode, +and it allows me to explicitly switch to Quad I/O mode. Further, writes to the +configuration register are non--volatile and in some cases permanent. +Therefore, it doesn't make sense that a controller should perform such a write +without first being told to do so. Therefore, this bit is set upon +noticing that the QUAD bit is set in the configuration register. + +The second bit of interest is the write protect disable bit. Write a '1' +to this bit before any erase or program operation, and a '0' to this bit +otherwise. This allows you to make sure that accidental bus writes to the +wrong address won't reprogram your flash (which they would do otherwise). + +The final bit of interest is the write in progress slash erase bit. On read, +this bit mirrors the WIP bit in the status register. It will be a one during +any ongoing erase or programming operation, and clear otherwise. Further, +to erase a sector, disable the write protect and then set this bit to a one +while simultaneously writing the sector of interest to the device. + +The last item of interest in this register is the sector address of interest. +This was placed in bits 14--19 so that any address within the sector +would work. Thus, to erase a sector, write the sector address, together with +an erase bit, to this register. + +\section{Config Register} + +The Quad Flash device also has a non--volatile configuration register, as +shown in Tbl.~\ref{tbl:confbits}. Writes to this register are program events, +which will stall subsequent bus operations until the write in progress bit +of either the status or EREG registers clears. Note that some bits, once +written, cannot be cleared such as the BPNV bit. + +Writes to this register are not truly independent of the status register, +as the Write Registers (WRR) command writes the status register before the +configuration register. Therefore, the core implements this by writing the +status register with the last value that was read by the core, or zero +if the status register has yet to be read by the core. Following the +status register write, the new value for the configuration register is +written. +\begin{table}[htbp]\begin{center} +\begin{bitlist} +8--31 & R & Always return zero.\\\hline +6--7 & R & Not used.\\\hline +5 & R/W & TBPROT. Configures the start of block protection. See device + documentation for more information. (Default 0)\\\hline +4 & R/W & Do not use. (Default 0)\\\hline +3 & R/W & BPNV, configures BP2--0 bits in the status register. If this bit + is set to 1, these bits are volatile, if set to '0' (default) the + bits are non--volatile. {\em Note that once this bit has been set, + it cannot be cleared!}\\\hline +2 & R/W & TBPARM. Configures the parameter sector location. See device + documentation for more detailed information. (Default 0)\\\hline +1 & R/W & QUAD. Set to '1' to place the device into Quad I/O (4--bit) mode, + '0' to leave in dual or serial I/O mode. (This core does not support + dual I/O mode.) (Most programmers will set this to '1'.)\\\hline +0 & R/W & FREEZE. Set to '1' to lock bits BP2--0 in the status register, zero + otherwise. (Default 0).\\\hline + \\\hline +\end{bitlist} +\caption{Configuration bit definitions}\label{tbl:confbits} +\end{center}\end{table} + +Further information on this register is available in the device data sheet. + +\section{Status Register} +The definitions of the bits in the status register are shown in +Tbl.~\ref{tbl:statbits}. For operating this core, only the write in progress +bit is relevant. All other bits should be set to zero. + +\begin{table}[htbp] +\begin{center} +\begin{bitlist} +8--31 & R & Always return zero.\\\hline +7 & R/W & Status register write disable. This setting is irrelevant in the + current core configuration, since the W\#/ACC line is always kept + high.\\\hline +6 & R/W & P\_ERR. The device will set this to a one if a programming error + has occurred. Writes with either P\_ERR or E\_ERR cleared will + clear this bit.\\\hline +5 & R/W & E\_ERR. The device will set this to a one if an erase error has + occurred, zero otherwise. Writes clearing either P\_ERR or E\_ERR + will clear this bit. + \\\hline +2--4 & R/W & Block protect bits. This core assumes these bits are zero. + See device documentation for other possible settings.\\\hline +1 & R & Write Enable Latch. This bit is handled internally by the core, + being set before any program or erase operation and cleared by + the operation itself. Therefore, reads should always read this + line as low.\\\hline +0 & R & Write in Progress. This bit, when one, indicates that an erase or + program operation is in progress. It will be cleared upon completion. + \\\hline +\end{bitlist} +\caption{Status bit definitions}\label{tbl:statbits} +\end{center}\end{table} + +\section{Device ID} + +Reading from the Device ID register causes the core controller to issue +a RDID {\tt 0x9f} command. The bytes returned are first the manufacture +ID of the part ({\tt 0x01} for this part), followed by the device ID +({\tt 0x0215} for this part), followed by the number of extended bytes that +may be read ({\tt 0x4D} for this part). This controller provides no means +of reading these extended bytes. (See Tab.~\ref{tbl:idbits}) + +\begin{table}[htbp]\begin{center} +\begin{bitlist} +0--31 & R & Always reads {\tt 0x0102154d}.\\\hline +\end{bitlist} +\caption{Read ID bit definitions}\label{tbl:idbits} +\end{center}\end{table} + +\chapter{Wishbone Datasheet}\label{chap:wishbone} +Tbl.~\ref{tbl:wishbone} is required by the wishbone specification, and so +it is included here. +\begin{table}[htbp] +\begin{center} +\begin{wishboneds} +Revision level of wishbone & WB B4 spec \\\hline +Type of interface & Slave, (Block) Read/Write \\\hline +Port size & 32--bit \\\hline +Port granulity & 32--bit \\\hline +Maximum Operand Size & 32--bit \\\hline +Data transfer ordering & Little Endian \\\hline +Clock constraints & Must be 100~MHz or slower \\\hline +Signal Names & \begin{tabular}{ll} + Signal Name & Wishbone Equivalent \\\hline + {\tt i\_clk\_100mhz} & {\tt CLK\_I} \\ + {\tt i\_wb\_cyc} & {\tt CYC\_I} \\ + {\tt i\_wb\_ctrl\_stb} & {\tt STB\_I} \\ + {\tt i\_wb\_data\_stb} & {\tt STB\_I} \\ + {\tt i\_wb\_we} & {\tt WE\_I} \\ + {\tt i\_wb\_data} & {\tt DAT\_I} \\ + {\tt o\_wb\_ack} & {\tt ACK\_O} \\ + {\tt o\_wb\_stall} & {\tt STALL\_O} \\ + {\tt o\_wb\_data} & {\tt DAT\_O} + \end{tabular}\\\hline +\end{wishboneds} +\caption{Wishbone Datasheet for the Quad SPI Flash controller}\label{tbl:wishbone} +\end{center}\end{table} + +\chapter{Clocks}\label{chap:clocks} + +This core is based upon the Basys--3 design. The Basys--3 development board +contains one external 100~MHz clock. This clock is divided by two to create +the 50~MHz clock used to drive the device. According to the data sheet, +it should be possible to run this core at up to 160~MHz, however I have not +tested it at such speeds. See Table.~\ref{tbl:clocks}. +\begin{table}[htbp] +\begin{center} +\begin{clocklist} +i\_clk\_100mhz & External & 160 & & System clock.\\\hline +\end{clocklist} +\caption{List of Clocks}\label{tbl:clocks} +\end{center}\end{table} + +\chapter{I/O Ports}\label{chap:ioports} +There are two interfaces that this device supports: a wishbone interface, and +the interface to the Quad--SPI flash itself. Both of these have their own +section in the I/O port list. For the purpose of this table, the wishbone +interface is listed in Tbl.~\ref{tbl:iowishbone}, and the Quad SPI flash +interface is listed in Tbl.~\ref{tbl:ioqspi}. The two lines that don't really +fit this classification are found in Tbl.~\ref{tbl:ioother}. +\begin{table}[htbp] +\begin{center} +\begin{portlist} +i\_wb\_cyc & 1 & Input & Wishbone bus cycle wire.\\\hline +i\_wb\_data\_stb & 1 & Input & Wishbone strobe, when the access is to the data + memory.\\\hline +i\_wb\_ctrl\_stb & 1 & Input & Wishbone strobe, for when the access is to + one of control registers.\\\hline +i\_wb\_we & 1 & Input & Wishbone write enable, indicating a write interaction + to the bus.\\\hline +i\_wb\_addr & 19 & Input & Wishbone address. When accessing control registers, + only the bottom two bits are relevant all other bits are + ignored.\\\hline +i\_wb\_data & 32 & Input & Wishbone bus data register.\\\hline +o\_wb\_ack & 1 & Output & Return value acknowledging a wishbone write, or + signifying valid data in the case of a wishbone read request. + \\\hline +o\_wb\_stall & 1 & Output & Indicates the device is not yet ready for another + wishbone access, effectively stalling the bus.\\\hline +o\_wb\_data & 32 & Output & Wishbone data bus, returning data values read + from the interface.\\\hline +\end{portlist} +\caption{Wishbone I/O Ports}\label{tbl:iowishbone} +\end{center}\end{table} + +While this core is wishbone compatible, there was one necessary change to +the wishbone interface to make this possible. That was the split of the +strobe line into two separate lines. The first strobe line, the data strobe, +is used when the access is to data memory--such as a read or write (program) +access. The second strobe line, the control strobe, is for reads and writes +to one of the four control registers. By splitting these strobe lines, +the wishbone interconnect designer may place the control registers in a +separate location of wishbone address space from the flash memory. It is +an error for both strobe lines to be on at the same time. + +With respect to the Quad SPI interface itself, one piece of glue logic +is necessary to tie the Quad SPI flash I/O to the in/out port at the top +level of the device. Specifically, these two lines must be added somewhere: +\begin{tabbing} +assign {\tt io\_qspi\_dat} = \= (\~{\tt qspi\_mod[1]})?(\{2'b11,1'bz,{\tt qspi\_dat[0]}\}) \hbox{\em // Serial mode} \\ + \> :(({\tt qspi\_bmod[0]})?(4'bzzzz):({\tt qspi\_dat[3:0]})); + \hbox{\em // Quad mode} +\end{tabbing} +These provide the transition between the input and output ports used by this +core, and the bi--directional inout ports used by the actual part. Further, +because the two additional lines are defined to be ones during serial I/O +mode, the hold and write protect lines are effectively eliminated in this +design in favor of faster speed I/O (i.e., Quad I/O). + +\begin{table}[htbp] +\begin{center} +\begin{portlist} +o\_qspi\_sck & 1 & Output & Serial clock output to the device. This pin + will be either inactive, or it will toggle at 50~MHz.\\\hline +o\_qpsi\_cs\_n & 1 & Output & Chip enable, active low. This will be + set low at the beginning of any interaction with the chip, + and will be held low throughout the interaction.\\\hline +o\_qspi\_mod & 2 & Output & Two mode lines for the top level to control + how the output data lines interact with the device. See the text + for how to use these lines.\\\hline +o\_qspi\_dat & 4 & Output & Four output lines, the least of which is the + old SPI MOSI line. When selected by the o\_qspi\_mod, this output + becomes the command for all 4 QSPI I/O lines.\\\hline +i\_qspi\_dat & 4 & Input & The four input lines from the device, of which + line one, {\tt i\_qspi\_dat[1]}, is the old MISO line.\\\hline +\end{portlist} +\caption{List of Quad--SPI Flash I/O ports}\label{tbl:ioqspi} +\end{center}\end{table} + +Finally, the clock line is not specific to the wishbone bus, and the interrupt +line is not specific to any of the above. These have been separated out here. +\begin{table}[htbp] +\begin{center} +\begin{portlist} +i\_clk\_100mhz & 1 & Input & The 100~MHz clock driving all interactions.\\\hline +o\_interrupt & 1 & Output & An strobed interrupt line indicating the end of + any erase or write transaction. This line will be high for exactly + one clock cycle, indicating that the core is again available for + commanding.\\\hline +\end{portlist} +\caption{Other I/O Ports}\label{tbl:ioother} +\end{center}\end{table} +% Appendices +% Index +\end{document} + + Index: doc/S25FL032P_00.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: doc/S25FL032P_00.pdf =================================================================== --- doc/S25FL032P_00.pdf (nonexistent) +++ doc/S25FL032P_00.pdf (revision 2)
doc/S25FL032P_00.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/gpl-3.0.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: doc/gpl-3.0.pdf =================================================================== --- doc/gpl-3.0.pdf (nonexistent) +++ doc/gpl-3.0.pdf (revision 2)
doc/gpl-3.0.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/Makefile =================================================================== --- doc/Makefile (nonexistent) +++ doc/Makefile (revision 2) @@ -0,0 +1,20 @@ +all: gpl-3.0.pdf spec.pdf +DSRC := src + +gpl-3.0.pdf: $(DSRC)/gpl-3.0.tex + latex $(DSRC)/gpl-3.0.tex + latex $(DSRC)/gpl-3.0.tex + dvips -q -z -t letter -P pdf -o gpl-3.0.ps gpl-3.0.dvi + ps2pdf -dAutoRotatePages=/All gpl-3.0.ps gpl-3.0.pdf + rm gpl-3.0.dvi gpl-3.0.log gpl-3.0.aux gpl-3.0.ps + +spec.pdf: $(DSRC)/spec.tex $(DSRC)/gqtekspec.cls $(DSRC)/GT.eps + cd $(DSRC)/; latex spec.tex + cd $(DSRC)/; latex spec.tex + dvips -q -z -t letter -P pdf -o spec.ps $(DSRC)/spec.dvi + ps2pdf -dAutoRotatePages=/All spec.ps spec.pdf + rm $(DSRC)/spec.dvi $(DSRC)/spec.log + rm $(DSRC)/spec.aux $(DSRC)/spec.toc + rm $(DSRC)/spec.lof $(DSRC)/spec.lot + rm spec.ps +

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.