Quellcode durchsuchen

cores: Replace local 'qspi_master' with 'no2qpimem' submodule

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Sylvain Munaut vor 3 Jahren
Ursprung
Commit
1f6961cb0a

+ 3 - 0
.gitmodules

@@ -16,3 +16,6 @@
 [submodule "cores/no2hyperbus"]
 	path = cores/no2hyperbus
 	url = https://github.com/no2fpga/no2hyperbus.git
+[submodule "cores/no2qpimem"]
+	path = cores/no2qpimem
+	url = https://github.com/no2fpga/no2qpimem.git

+ 1 - 0
cores/no2qpimem

@@ -0,0 +1 @@
+Subproject commit 8596cee5062c2475dd19ecba9ad5cf57b5d67e89

+ 0 - 4
cores/qspi_master/Makefile

@@ -1,4 +0,0 @@
-CORE := qspi_master
-
-NO2BUILD_DIR ?= $(abspath ../../build)
-include $(NO2BUILD_DIR)/core-rules.mk

+ 0 - 16
cores/qspi_master/no2core.mk

@@ -1,16 +0,0 @@
-CORE := qspi_master
-
-DEPS_qspi_master = no2misc no2ice40
-
-RTL_SRCS_qspi_master := $(addprefix rtl/, \
-	qspi_master.v \
-	qspi_phy_ice40_1x.v \
-	qspi_phy_ice40_2x.v \
-	qspi_phy_ice40_4x.v \
-)
-
-TESTBENCHES_qspi_master := \
-	qspi_master_tb \
-	$(NULL)
-
-include $(NO2BUILD_DIR)/core-magic.mk

+ 0 - 760
cores/qspi_master/rtl/qspi_master.v

@@ -1,760 +0,0 @@
-/*
- * qspi_master.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019  Sylvain Munaut <tnt@246tNt.com>
- * All rights reserved.
- *
- * BSD 3-clause, see LICENSE.bsd
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the <organization> nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-`default_nettype none
-
-module qspi_master #(
-	parameter integer CMD_READ  = 16'hEBEB,
-	parameter integer CMD_WRITE = 16'h0202,
-	parameter integer DUMMY_CLK = 6,
-	parameter integer PAUSE_CLK = 3,
-	parameter integer FIFO_DEPTH  = 1,
-	parameter integer N_CS = 2,				/* CS count */
-	parameter integer PHY_SPEED = 1,		/* Speed Factor: 1x 2x 4x */
-	parameter integer PHY_WIDTH = 1,		/* Width Factor: 1x 2x    */
-	parameter integer PHY_DELAY = 6,		/* See PHY doc */
-
-	// auto
-	parameter integer PTW = (PHY_WIDTH * 4 * PHY_SPEED),	/* PHY Total   Width */
-	parameter integer PCW = (            4 * PHY_SPEED),	/* PHY Channel Width */
-	parameter integer PSW = (                PHY_SPEED)		/* PHY Signal  Width */
-)(
-	// PHY interface
-	input  wire [PTW-1:0]  phy_io_i,
-	output reg  [PTW-1:0]  phy_io_o,
-	output reg  [    3:0]  phy_io_oe,
-	output reg  [PSW-1:0]  phy_clk_o,
-	output reg  [N_CS-1:0] phy_cs_o,
-
-	// Memory interface
-	input  wire [ 1:0] mi_addr_cs,
-	input  wire [23:0] mi_addr,
-	input  wire [ 6:0] mi_len,
-	input  wire        mi_rw,		/* 0=Write, 1=Read */
-	input  wire        mi_valid,
-	output wire        mi_ready,
-
-	input  wire [31:0] mi_wdata,
-	output wire        mi_wack,
-	output wire        mi_wlast,
-
-	output wire [31:0] mi_rdata,
-	output wire        mi_rstb,
-	output wire        mi_rlast,
-
-	// Wishbone interface
-	input  wire [ 4:0] wb_addr,
-	input  wire [31:0] wb_wdata,
-	output reg  [31:0] wb_rdata,
-	input  wire        wb_we,
-	input  wire        wb_cyc,
-	output reg         wb_ack,
-
-	// Common
-	input wire clk,
-	input wire rst
-);
-
-	localparam integer STW = 32;				/* Shifter Total Width */
-	localparam integer SCW = STW / PHY_WIDTH;	/* Shifter Channel Width */
-
-
-	// Mapping Helpers
-	// ---------------
-
-	/*
-	 * PHY signal mapping:
-	 * 		phy_io = [ chan_1 | chan_0 ]
-	 * 		chan_i = [ io_3 | io_2 | io_1 | io_0 ]
-	 * 		io_i   = [ t_0 ... t_n ]  (t_0 being the 'first')
-	 *
-	 * Shifter-Out format:
-	 * Shifter-In format:
-	 * 		shift_data = [ chan_1 | chan_0 ]
-	 * 		chan_i_qpi = [ io_3(0) io_2(0) io_1(0) io_0(0) io_3(1) ... ]
-	 * 		chan_i_spi = [ t_0 t_1 ... t_n ]  (t_0 being 'first')
-	 *
-	 * Mem IF data:
-	 * 		mi_{r,w}data = [ b3 | b2 | b1 | b0 ]
-	 *
-	 * 		Data is stored in memory in big-endian (b3 b2 b1 b0)
-	 * 		and in case of multiple channel (b1 b0) in chan 0 and (b3 b2) in chan 1
-	 *
-	 * Wishbone data:
-	 *      spi_xfer: bits are taken in order and shifted out MSB first
-	 *                In case of multiple channel the register is split in 2x16 bits
-	 *      qpi_cmd:  bits are taken in order and shifted out MSB first
-	 *      qpi_read / qpi_data: See Mem IF data mapping
-	 */
-
-
-	function [PTW-1:0] shift2phy_spi;
-		input [STW-1:0] shift;
-		input [PTW-1:0] base;
-		integer chan;
-		begin
-			// Set default value for the signals that don't matter for SPI
-			shift2phy_spi = base;
-
-			// Overwrite only the PHY IO0 line (MOSI)
-			for (chan=0; chan<PHY_WIDTH; chan=chan+1)
-				shift2phy_spi[chan*PCW+:PSW] = shift[((chan+1)*SCW-1)-:PSW];
-		end
-	endfunction
-
-	function [STW-1:0] shift_spi;
-		input [STW-1:0] shift;
-		integer chan;
-		begin
-			for (chan=0; chan<PHY_WIDTH; chan=chan+1)
-				shift_spi[chan*SCW+:SCW] = { shift[chan*SCW+:SCW-PSW], {PSW{1'bx}} };
-		end
-	endfunction
-
-	function [PTW-1:0] shift2phy_qpi_cmd;
-		input [STW-1:0] shift;
-		integer chan, io, t;
-		begin
-			for (chan=0; chan<PHY_WIDTH; chan=chan+1)
-				for (t=0; t<PHY_SPEED; t=t+1)
-					for (io=0; io<4; io=io+1)
-						shift2phy_qpi_cmd[chan*PCW + io*PSW + t] = shift[STW - (4*PHY_SPEED) + t*4 + io];
-		end
-	endfunction
-
-	function [STW-1:0] shift_qpi_cmd;
-		input [STW-1:0] shift;
-		begin
-			shift_qpi_cmd[STW-1:0] = { shift[STW-PCW-1:0], {PCW{1'bx}} };
-		end
-	endfunction
-
-	function [PTW-1:0] shift2phy_qpi_data;
-		input [STW-1:0] shift;
-		integer chan, io, t;
-		begin
-			for (chan=0; chan<PHY_WIDTH; chan=chan+1)
-				for (t=0; t<PHY_SPEED; t=t+1)
-					for (io=0; io<4; io=io+1)
-						shift2phy_qpi_data[chan*PCW + io*PSW + t] = shift[(chan+1)*SCW - (4*PHY_SPEED) + t*4 + io];
-		end
-	endfunction
-
-	function [STW-1:0] shift_qpi_data;
-		input [STW-1:0] shift;
-		integer chan;
-		begin
-			if (SCW == PCW)
-				shift_qpi_data = { STW{1'bx} };
-			else
-				for (chan=0; chan<PHY_WIDTH; chan=chan+1)
-					shift_qpi_data[chan*SCW+:SCW] = { shift[chan*SCW+:SCW-PCW], {PCW{1'bx}} };
-		end
-	endfunction
-
-	function [STW-1:0] phy2shift_spi;
-		input [STW-1:0] prev;
-		input [PTW-1:0] phy;
-		integer chan, t;
-		begin
-			for (chan=0; chan<PHY_WIDTH; chan=chan+1)
-			begin
-				// Shift previous data
-				phy2shift_spi[chan*SCW+PSW+:SCW-PSW] = prev[chan*SCW+:SCW-PSW];
-
-				// Map new data
-				phy2shift_spi[chan*SCW+:PSW] = phy[chan*PCW+PSW+:PSW];
-			end
-		end
-	endfunction
-
-	function [STW-1:0] phy2shift_qpi;
-		input [STW-1:0] prev;
-		input [PTW-1:0] phy;
-		integer chan, t, io;
-		begin
-			for (chan=0; chan<PHY_WIDTH; chan=chan+1)
-			begin
-				// Shift previous data
-				if (PCW != SCW)
-					phy2shift_qpi[chan*SCW+PCW+:SCW-PCW] = prev[chan*SCW+:SCW-PCW];
-
-				// Map new data
-				for (t=0; t<PHY_SPEED; t=t+1)
-					for (io=0; io<4; io=io+1)
-						phy2shift_qpi[chan*SCW + t*4 + io] = phy[chan*PCW + io*PSW + t];
-			end
-		end
-	endfunction
-
-
-	// Signals
-	// -------
-
-	// Wishbone interface
-	wire        wbi_we_csr;
-	wire [31:0] wbi_rd_csr;
-	wire        wbi_rd_rst;
-
-	// Command & Reponse FIFOs
-	wire [35:0] cf_di;
-	reg         cf_wren;
-	wire        cf_full;
-	wire [35:0] cf_do;
-	wire        cf_rden;
-	wire        cf_empty;
-
-	wire [31:0] rf_di;
-	wire        rf_wren_safe;
-	wire        rf_wren;
-	wire        rf_full;
-	wire [31:0] rf_do;
-	wire        rf_rden;
-	wire        rf_empty;
-
-	reg         rf_overflow;
-	reg         rf_overflow_clr;
-	reg         rf_rden_arm;
-
-	// External control
-	reg  [ 1:0] ectl_cs;
-	reg         ectl_req;
-	wire        ectl_grant;
-	wire        ectl_idle;
-
-	// Main state machine
-	localparam
-		ST_IDLE			= 0,
-		ST_CMD_EXEC		= 1,
-		ST_MI_WR_DATA	= 2,
-		ST_MI_RD_DUMMY	= 3,
-		ST_MI_RD_DATA	= 4,
-		ST_FLUSH        = 5,
-		ST_PAUSE		= 6;
-
-	reg [2:0] state;
-	reg [2:0] state_nxt;
-
-	// Xfer counter
-	reg  [ 7:0] xfer_cnt;
-	wire        xfer_last;
-
-	// Pause counter
-	reg  [ 3:0] pause_cnt;
-	wire        pause_last;
-
-	// Memory interface
-	wire [ 7:0] mi_spi_cmd;
-
-	// Shift-Out
-	localparam
-		SO_MODE_SPI			= 2'b00,
-		SO_MODE_QPI_RD		= 2'b01,
-		SO_MODE_QPI_WR		= 2'b10,
-		SO_MODE_QPI_CMD		= 2'b11;
-
-	localparam
-		SO_LD_SRC_WB		= 2'b00,
-		SO_LD_SRC_MI_DATA	= 2'b10,
-		SO_LD_SRC_MI_CMD	= 2'b11;
-
-	localparam
-		SO_DST_NONE			= 2'b00,
-		SO_DST_WB			= 2'b10,
-		SO_DST_MI			= 2'b11;
-
-	wire        so_ld_now;
-	reg         so_ld_valid;
-	reg  [ 1:0] so_ld_mode;
-	reg  [ 1:0] so_ld_dst;
-	reg  [ 5:0] so_ld_cnt;
-	reg  [ 1:0] so_ld_src;
-
-	reg         so_valid;
-	reg  [ 1:0] so_mode;
-	reg  [ 1:0] so_dst;
-	reg  [ 5:0] so_cnt;
-	wire        so_last;
-	reg  [31:0] so_data;
-
-	// Shift-In
-	wire        si_mode_0;
-	wire        si_mode_nm1;
-	reg  [ 1:0] si_dst_1;
-	wire [ 1:0] si_dst_n;
-
-	reg  [31:0] si_data_n;
-
-
-	// Wishbone interface
-	// ------------------
-
-	// Ack
-	always @(posedge clk)
-	begin
-		// Default is direct ack
-		wb_ack <= wb_cyc & ~wb_ack;
-
-		// Block on write to full command fifo
-		if (wb_we & wb_addr[4] & cf_full)
-			wb_ack <= 1'b0;
-
-		// Block on read from empty response fifo if in blocking mode
-		if (~wb_we & (wb_addr == 5'h3) & rf_empty)
-			wb_ack <= 1'b0;
-	end
-
-	// CSR
-	assign wbi_we_csr = wb_ack & wb_we & ~wb_addr[4];
-
-	always @(posedge clk)
-		if (rst)
-			ectl_req <= 1'b0;
-		else if (wbi_we_csr)
-			ectl_req <= (ectl_req & ~wb_wdata[2]) | wb_wdata[1];
-
-	always @(posedge clk)
-		if (wbi_we_csr)
-			ectl_cs <= wb_wdata[5:4];
-
-	assign ectl_idle  = (state == ST_IDLE);
-	assign ectl_grant = (state == ST_CMD_EXEC);
-
-	always @(posedge clk)
-		rf_overflow_clr <= wbi_we_csr & wb_wdata[9];
-
-	assign wbi_rd_csr = {
-		16'h0000,
-		rf_empty, rf_full, rf_overflow, 1'b0,
-		cf_empty, cf_full, 2'b0,
-		2'b00, ectl_cs,
-		1'b0, ectl_grant, ectl_req, ectl_idle
-	};
-
-	// Command FIFO write
-	assign cf_di = { wb_addr[3:0], wb_wdata };
-
-	always @(posedge clk)
-		cf_wren <= wb_cyc & wb_we & ~wb_ack & wb_addr[4] & ~cf_full;
-
-	// Response FIFO read
-	always @(posedge clk)
-		rf_rden_arm <= ~rf_empty & wb_addr[1] & ~wb_we;
-
-	assign rf_rden = wb_ack & rf_rden_arm;
-
-	// Read mux
-	assign wbi_rd_rst = ~wb_cyc | wb_ack;
-
-	always @(posedge clk)
-		if (wbi_rd_rst)
-			wb_rdata <= 32'h0000000;
-		else
-			wb_rdata <= wb_addr[1] ? rf_do : wbi_rd_csr;
-
-	// FIFOs
-	generate
-		if (FIFO_DEPTH > 4) begin
-			// Command
-			fifo_sync_ram #(
-				.DEPTH(FIFO_DEPTH),
-				.WIDTH(36)
-			) cmd_fifo_I (
-				.wr_data(cf_di),
-				.wr_ena(cf_wren),
-				.wr_full(cf_full),
-				.rd_data(cf_do),
-				.rd_ena(cf_rden),
-				.rd_empty(cf_empty),
-				.clk(clk),
-				.rst(rst)
-			);
-
-			// Response
-			fifo_sync_ram #(
-				.DEPTH(FIFO_DEPTH),
-				.WIDTH(32)
-			) rsp_fifo_I (
-				.wr_data(rf_di),
-				.wr_ena(rf_wren_safe),
-				.wr_full(rf_full),
-				.rd_data(rf_do),
-				.rd_ena(rf_rden),
-				.rd_empty(rf_empty),
-				.clk(clk),
-				.rst(rst)
-			);
-		end else begin
-			// Command
-			fifo_sync_shift #(
-				.DEPTH(FIFO_DEPTH),
-				.WIDTH(36)
-			) cmd_fifo_I (
-				.wr_data(cf_di),
-				.wr_ena(cf_wren),
-				.wr_full(cf_full),
-				.rd_data(cf_do),
-				.rd_ena(cf_rden),
-				.rd_empty(cf_empty),
-				.clk(clk),
-				.rst(rst)
-			);
-
-			// Response
-			fifo_sync_shift #(
-				.DEPTH(FIFO_DEPTH),
-				.WIDTH(32)
-			) rsp_fifo_I (
-				.wr_data(rf_di),
-				.wr_ena(rf_wren_safe),
-				.wr_full(rf_full),
-				.rd_data(rf_do),
-				.rd_ena(rf_rden),
-				.rd_empty(rf_empty),
-				.clk(clk),
-				.rst(rst)
-			);
-		end
-	endgenerate
-
-	// Response overflow tracking
-	assign rf_wren_safe = rf_wren & ~rf_full;
-
-	always @(posedge clk)
-		rf_overflow <= (rf_overflow & ~rf_overflow_clr) | (rf_wren & rf_full);
-
-	// Capture responses
-	assign rf_di   = si_data_n;
-	assign rf_wren = (si_dst_n == 2'b01);
-
-
-	// Main Control
-	// ------------
-
-	// State register
-	always @(posedge clk)
-		if (rst)
-			state <= ST_IDLE;
-		else
-			state <= state_nxt;
-
-	// Next-State logic
-	always @(*)
-	begin
-		// Default
-		state_nxt = state;
-
-		// Transitions ?
-		case (state)
-			ST_IDLE:
-				if (mi_valid)
-					state_nxt = mi_rw ? ST_MI_RD_DUMMY : ST_MI_WR_DATA;
-				else if (ectl_req)
-					state_nxt = ST_CMD_EXEC;
-
-			ST_CMD_EXEC:
-				if (~ectl_req & cf_empty)
-					state_nxt = ST_PAUSE;
-
-			ST_MI_WR_DATA:
-				if (xfer_last & so_ld_now)
-					state_nxt = ST_FLUSH;
-
-			ST_MI_RD_DUMMY:
-				if (so_ld_now)
-					state_nxt = ST_MI_RD_DATA;
-
-			ST_MI_RD_DATA:
-				if (xfer_last & so_ld_now)
-					state_nxt = ST_FLUSH;
-
-			ST_FLUSH:
-				if (~so_valid)
-					state_nxt = ST_PAUSE;
-
-			ST_PAUSE:
-				if (pause_last)
-					state_nxt = ST_IDLE;
-		endcase
-	end
-
-	// Xfer counter
-	always @(posedge clk)
-		if (state == ST_IDLE)
-			xfer_cnt <= { 1'b0, mi_len } - 1;
-		else if (((state == ST_MI_WR_DATA) || (state == ST_MI_RD_DATA)) && so_ld_now)
-			xfer_cnt <= xfer_cnt - 1;
-
-	assign xfer_last = xfer_cnt[7];
-
-	// Pause counter
-	always @(posedge clk)
-		if (state == ST_PAUSE)
-			pause_cnt <= pause_cnt - 1;
-		else
-			pause_cnt <= PAUSE_CLK - 2;
-	
-	assign pause_last = pause_cnt[3];
-
-	// SPI command
-	assign mi_spi_cmd = mi_rw ? CMD_READ[8*mi_addr_cs+:8] : CMD_WRITE[8*mi_addr_cs+:8];
-
-	// ROM for command fifo counter
-	(* mem2reg *)
-	reg [5:0] cmd_len_rom[0:15];
-
-	initial
-	begin : rom_cmd_len
-		integer i;
-		for (i=0; i<16; i=i+1)
-			cmd_len_rom[i] = (((i >> 2) & 3) == 0) ?
-				(((i & 3) << 3) - PHY_SPEED + 7) :
-				(((i & 3) << 1) - PHY_SPEED + 1);
-	end
-
-	// Shift control
-		// When to load
-	assign so_ld_now = ~so_valid | so_last;
-
-		// What to load
-	always @(*)
-	begin
-		// Defaults
-		so_ld_valid = 1'b0;
-		so_ld_mode  = 2'bxx;
-		so_ld_dst   = 2'bxx;
-		so_ld_cnt   = 6'bxxxxxx;
-		so_ld_src   = 2'bxx;
-
-		case (state)
-			ST_IDLE: begin
-				so_ld_valid = mi_valid;
-				so_ld_mode  = SO_MODE_QPI_CMD;
-				so_ld_dst   = SO_DST_NONE;
-				so_ld_cnt   = (32 / 4) - PHY_SPEED - 1;
-				so_ld_src   = SO_LD_SRC_MI_CMD;
-			end
-
-			ST_CMD_EXEC: begin
-				so_ld_valid = ~cf_empty;
-				case (cf_do[35:34])
-					2'b00: { so_ld_mode, so_ld_dst } = { SO_MODE_SPI,     SO_DST_WB   };
-					2'b01: { so_ld_mode, so_ld_dst } = { SO_MODE_QPI_RD,  SO_DST_WB   };
-					2'b10: { so_ld_mode, so_ld_dst } = { SO_MODE_QPI_WR,  SO_DST_NONE };
-					2'b11: { so_ld_mode, so_ld_dst } = { SO_MODE_QPI_CMD, SO_DST_NONE };
-				endcase
-				so_ld_cnt   = cmd_len_rom[cf_do[35:32]];
-				so_ld_src   = SO_LD_SRC_WB;
-			end
-
-			ST_MI_WR_DATA: begin
-				so_ld_valid = 1'b1;
-				so_ld_mode  = SO_MODE_QPI_WR;
-				so_ld_dst   = SO_DST_NONE;
-				so_ld_cnt   = (32 / (4 * PHY_WIDTH)) - PHY_SPEED - 1;
-				so_ld_src   = SO_LD_SRC_MI_DATA;
-			end
-
-			ST_MI_RD_DUMMY: begin
-				so_ld_valid = 1'b1;
-				so_ld_mode  = SO_MODE_QPI_RD;
-				so_ld_dst   = SO_DST_NONE;
-				so_ld_cnt   = DUMMY_CLK - PHY_SPEED - 1;
-			end
-
-			ST_MI_RD_DATA: begin
-				so_ld_valid = 1'b1;
-				so_ld_mode  = SO_MODE_QPI_RD;
-				so_ld_dst   = SO_DST_MI;
-				so_ld_cnt	= (32 / (4 * PHY_WIDTH)) - PHY_SPEED - 1;
-			end
-		endcase
-	end
-
-	// Command interface
-	assign cf_rden = (state == ST_CMD_EXEC) & so_ld_now & ~cf_empty;
-
-	// Memory interface
-	assign mi_ready = (state == ST_IDLE);
-
-	assign mi_wack  = (state == ST_MI_WR_DATA) & so_ld_now;
-	assign mi_wlast = xfer_last;
-
-	assign mi_rdata = si_data_n;
-	assign mi_rstb  = si_dst_n[1];
-	assign mi_rlast = si_dst_n[0];
-
-	// Chip select
-	always @(posedge clk)
-		if (rst)
-			phy_cs_o <= { N_CS{1'b1} };
-		else begin
-			case (state)
-				ST_IDLE: begin
-					// Default
-					phy_cs_o <= { N_CS{1'b1} };
-
-					if (mi_valid)
-						phy_cs_o[mi_addr_cs] <= 1'b0;
-					else if (ectl_req)
-						phy_cs_o[ectl_cs] <= 1'b0;
-				end
-
-				ST_FLUSH:
-					if (~so_valid)
-						phy_cs_o <= { N_CS{1'b1} };
-
-				ST_PAUSE:
-					phy_cs_o <= { N_CS{1'b1} };
-			endcase
-		end
-
-
-	// Shift-Out unit
-	// --------------
-
-		//					  Shift								Output
-		// SPI mode			: Each chan shifts PHY_SPEED		Output only defined for MOSI
-		// QPI read			: n/a                               n/a
-		// QPI data mode	: Each chan shifts 4 * PHY_SPEED	Output QPI mode
-		// QPI command mode	: Word shifts 4 * PHY_SPEED         chan[1] replicates chan[0]
-
-	// Validity
-	always @(posedge clk)
-		if (rst)
-			so_valid <= 1'b0;
-		else
-			so_valid <= (so_valid & ~so_last) | (so_ld_now & so_ld_valid);
-
-	// Mode / Read-destination
-	always @(posedge clk)
-		if (so_ld_now) begin
-			so_mode <= so_ld_mode;
-			so_dst  <= so_ld_dst;
-		end
-
-	// Counter
-	always @(posedge clk)
-		if (so_ld_now)
-			so_cnt <= so_ld_cnt;
-		else
-			so_cnt <= so_cnt - PHY_SPEED;
-
-	assign so_last = so_cnt[5];
-
-	// Shift register
-	always @(posedge clk)
-	begin
-		casez ({so_ld_now, so_ld_src, so_mode})
-			{ 1'b0, 2'bzz, SO_MODE_SPI }:		so_data <= shift_spi(so_data);
-			{ 1'b0, 2'bzz, SO_MODE_QPI_WR }:	so_data <= shift_qpi_data(so_data);
-			{ 1'b0, 2'bzz, SO_MODE_QPI_CMD }:	so_data <= shift_qpi_cmd(so_data);
-			{ 1'b1, SO_LD_SRC_WB, 2'bzz }:		so_data <= cf_do[31:0];
-			{ 1'b1, SO_LD_SRC_MI_DATA, 2'bzz }:	so_data <= mi_wdata;
-			{ 1'b1, SO_LD_SRC_MI_CMD, 2'bzz }:	so_data <= { mi_spi_cmd, mi_addr };
-			default:							so_data <= 32'hxxxxxxxx;
-		endcase
-	end
-
-	// IO control
-	always @(*)
-	begin : io_ctrl
-		integer chan, i;
-
-		// Control
-		if (so_valid) begin
-			// Clock
-			if (PHY_SPEED > 1)
-				for (i=0; i<PSW; i=i+1)
-					phy_clk_o[i] = ~so_last | (i >= (PHY_SPEED-1-so_cnt[$clog2(PHY_SPEED)-1:0]));
-			else
-				phy_clk_o <= 1'b1;
-
-			// Output Enable
-			case (so_mode)
-				SO_MODE_SPI:		phy_io_oe = 4'b0001;
-				SO_MODE_QPI_RD:		phy_io_oe = 4'b0000;
-				SO_MODE_QPI_WR:		phy_io_oe = 4'b1111;
-				SO_MODE_QPI_CMD:	phy_io_oe = 4'b1111;
-				default:            phy_io_oe = 4'bxxxx;
-			endcase
-		end else begin
-			// Disable all
-			phy_clk_o <= {PSW{1'b0}};
-			phy_io_oe <= 4'b0000;
-		end
-
-		// Data
-		if (so_mode[0])
-			phy_io_o = shift2phy_qpi_cmd(so_data);
-		else
-			phy_io_o = shift2phy_qpi_data(so_data);
-
-		if (~so_mode[1])
-			phy_io_o = shift2phy_spi(so_data, phy_io_o);
-	end
-
-
-	// Shift-In unit
-	// -------------
-
-	// Capture control
-	assign si_mode_0 = so_mode[0];
-
-	always @(posedge clk)
-	begin
-		// Default destination is 'none'
-		si_dst_1 <= 2'b00;
-
-		// If it's a read, send it somewhere
-		if (so_valid & so_last & ~so_mode[1] & so_dst[1])
-			si_dst_1 <= so_dst[0] ? { 1'b1, (state == ST_FLUSH) } : 2'b01;
-	end
-
-	// Delay for PHY pipeline
-	delay_bit #(PHY_DELAY)    dly_si_mode (si_mode_0, si_mode_nm1, clk);
-	delay_bus #(PHY_DELAY, 2) dly_si_dst  (si_dst_1,  si_dst_n,    clk);
-
-	// Shifter
-	always @(posedge clk)
-	begin
-		// 2 modes:
-		//  0 - SPI shift-in      PHY_SPEED bits at a time per channel
-		//  1 - QPI shift-in  4 * PHY_SPEED bits at a time per channel
-		if (si_mode_nm1)
-			si_data_n <= phy2shift_qpi(si_data_n, phy_io_i);
-		else
-			si_data_n <= phy2shift_spi(si_data_n, phy_io_i);
-	end
-
-endmodule

+ 0 - 118
cores/qspi_master/rtl/qspi_phy_ice40_1x.v

@@ -1,118 +0,0 @@
-/*
- * qspi_phy_ice40_1x.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019  Sylvain Munaut <tnt@246tNt.com>
- * All rights reserved.
- *
- * BSD 3-clause, see LICENSE.bsd
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the <organization> nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-`default_nettype none
-
-module qspi_phy_ice40_1x #(
-	parameter integer N_CS = 2,				/* CS count */
-	parameter integer WITH_CLK = 1,
-	parameter integer NEG_IN = 0,			/* Sample on negative edge */
-
-	// auto
-	parameter integer CL = N_CS ? (N_CS-1) : 0
-)(
-	// Pads
-	inout  wire [ 3:0] pad_io,
-	output wire        pad_clk,
-	output wire [CL:0] pad_cs_n,
-
-	// PHY interface
-	output wire [ 3:0] phy_io_i,
-	input  wire [ 3:0] phy_io_o,
-	input  wire [ 3:0] phy_io_oe,
-	input  wire        phy_clk_o,
-	input  wire [CL:0] phy_cs_o,
-
-	// Clock
-	input  wire clk
-);
-
-	// IOs
-	wire [3:0] phy_io_i_pe;
-	wire [3:0] phy_io_i_ne;
-
-	SB_IO #(
-		.PIN_TYPE(6'b1101_00),
-		.PULLUP(1'b1),
-		.NEG_TRIGGER(1'b0),
-		.IO_STANDARD("SB_LVCMOS")
-	) iob_io_I[3:0] (
-		.PACKAGE_PIN(pad_io),
-		.INPUT_CLK(clk),
-		.OUTPUT_CLK(clk),
-		.OUTPUT_ENABLE(phy_io_oe),
-		.D_OUT_0(phy_io_o),
-		.D_IN_0(phy_io_i_pe),
-		.D_IN_1(phy_io_i_ne)
-	);
-
-	assign phy_io_i = NEG_IN ? phy_io_i_ne : phy_io_i_pe;
-
-	// Clock
-	generate
-		if (WITH_CLK) begin
-			reg clk_active;
-
-			always @(posedge clk)
-				clk_active <= phy_clk_o;
-
-			SB_IO #(
-				.PIN_TYPE(6'b0100_11),
-				.PULLUP(1'b0),
-				.NEG_TRIGGER(1'b0),
-				.IO_STANDARD("SB_LVCMOS")
-			) iob_clk_I (
-				.PACKAGE_PIN(pad_clk),
-				.OUTPUT_CLK(clk),
-				.D_OUT_0(1'b0),
-				.D_OUT_1(clk_active)
-			);
-		end
-	endgenerate
-
-	// Chip select
-	generate
-		if (N_CS)
-			SB_IO #(
-				.PIN_TYPE(6'b0101_11),
-				.PULLUP(1'b0),
-				.NEG_TRIGGER(1'b0),
-				.IO_STANDARD("SB_LVCMOS")
-			) iob_cs_I[N_CS-1:0] (
-				.PACKAGE_PIN(pad_cs_n),
-				.OUTPUT_CLK(clk),
-				.D_OUT_0(phy_cs_o)
-			);
-	endgenerate
-
-endmodule

+ 0 - 156
cores/qspi_master/rtl/qspi_phy_ice40_2x.v

@@ -1,156 +0,0 @@
-/*
- * qspi_phy_ice40_2x.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019  Sylvain Munaut <tnt@246tNt.com>
- * All rights reserved.
- *
- * BSD 3-clause, see LICENSE.bsd
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the <organization> nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-`default_nettype none
-
-module qspi_phy_ice40_2x #(
-	parameter integer N_CS = 2,					/* CS count */
-	parameter integer WITH_CLK = 1,
-
-	// auto
-	parameter integer CL = N_CS ? (N_CS-1) : 0
-)(
-	// Pads
-	inout  wire [ 3:0] pad_io,
-	output wire        pad_clk,
-	output wire [CL:0] pad_cs_n,
-
-	// PHY interface
-	output reg  [ 7:0] phy_io_i,
-	input  wire [ 7:0] phy_io_o,
-	input  wire [ 3:0] phy_io_oe,
-	input  wire [ 1:0] phy_clk_o,
-	input  wire [CL:0] phy_cs_o,
-
-	// Clock
-	input  wire clk_1x,
-	input  wire clk_2x
-);
-
-	// IOs
-	reg  [3:0] phy_io_o_fe;
-	wire [3:0] phy_io_o_re;
-
-	wire [3:0] phy_io_i_pe;
-	wire [3:0] phy_io_i_ne;
-	reg  [3:0] phy_io_i_ne_r;
-
-		// Output edge dispatch
-	assign phy_io_o_re = { phy_io_o[7], phy_io_o[5], phy_io_o[3], phy_io_o[1] };
-
-	always @(posedge clk_1x)
-		phy_io_o_fe <= { phy_io_o[6], phy_io_o[4], phy_io_o[2], phy_io_o[0] };
-
-		// IOB
-	SB_IO #(
-		.PIN_TYPE(6'b1100_00),
-		.PULLUP(1'b1),
-		.NEG_TRIGGER(1'b0),
-		.IO_STANDARD("SB_LVCMOS")
-	) iob_io_I[3:0] (
-		.PACKAGE_PIN(pad_io),
-		.INPUT_CLK(clk_1x),
-		.OUTPUT_CLK(clk_1x),
-		.OUTPUT_ENABLE(phy_io_oe),
-		.D_OUT_0(phy_io_o_re),
-		.D_OUT_1(phy_io_o_fe),
-		.D_IN_0(phy_io_i_pe),
-		.D_IN_1(phy_io_i_ne)
-	);
-
-		// Input edge resync
-	always @(posedge clk_1x)
-		phy_io_i_ne_r <= phy_io_i_ne;
-
-	always @(posedge clk_1x)
-		phy_io_i <= {
-			phy_io_i_ne_r[3], phy_io_i_pe[3],
-			phy_io_i_ne_r[2], phy_io_i_pe[2],
-			phy_io_i_ne_r[1], phy_io_i_pe[1],
-			phy_io_i_ne_r[0], phy_io_i_pe[0]
-		};
-
-	// Clock
-	generate
-		if (WITH_CLK) begin
-			reg [1:0] clk_active;
-			reg       clk_toggle;
-			reg       clk_toggle_r;
-			wire      clk_out;
-
-			// Data is sent by 8 bits always, so we only use
-			// one of the two signals ...
-			always @(posedge clk_1x)
-			begin
-				clk_active <= phy_clk_o;
-				clk_toggle <= ~clk_toggle;
-			end
-
-			always @(posedge clk_2x)
-				clk_toggle_r <= clk_toggle;
-
-			assign clk_out = (clk_toggle == clk_toggle_r) ? clk_active[0] : clk_active[1];
-
-			SB_IO #(
-				.PIN_TYPE(6'b0100_11),
-				.PULLUP(1'b1),
-				.NEG_TRIGGER(1'b0),
-				.IO_STANDARD("SB_LVCMOS")
-			) iob_clk_I (
-				.PACKAGE_PIN(pad_clk),
-				.OUTPUT_CLK(clk_2x),
-				.D_OUT_0(clk_out),
-				.D_OUT_1(1'b0)
-			);
-		end
-	endgenerate
-
-	// Chip select
-	generate
-		// FIXME register CS config ?
-		// Because of potential conflict with IO site, we don't register
-		// the CS signal at all and rely on the fact it's held low a bit longer
-		// than needed by the controller.
-		if (N_CS)
-			SB_IO #(
-				.PIN_TYPE(6'b0110_11),
-				.PULLUP(1'b1),
-				.NEG_TRIGGER(1'b0),
-				.IO_STANDARD("SB_LVCMOS")
-			) iob_cs_I[N_CS-1:0] (
-				.PACKAGE_PIN(pad_cs_n),
-				.D_OUT_0(phy_cs_o)
-			);
-	endgenerate
-
-endmodule

+ 0 - 199
cores/qspi_master/rtl/qspi_phy_ice40_4x.v

@@ -1,199 +0,0 @@
-/*
- * qspi_phy_ice40_4x.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019  Sylvain Munaut <tnt@246tNt.com>
- * All rights reserved.
- *
- * BSD 3-clause, see LICENSE.bsd
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the <organization> nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-`default_nettype none
-
-module qspi_phy_ice40_4x #(
-	parameter integer N_CS = 2,					/* CS count */
-	parameter integer WITH_CLK = 1,
-
-	// auto
-	parameter integer CL = N_CS ? (N_CS-1) : 0
-)(
-	// Pads
-	inout  wire [ 3:0] pad_io,
-	output wire        pad_clk,
-	output wire [CL:0] pad_cs_n,
-
-	// PHY interface
-	output wire [15:0] phy_io_i,
-	input  wire [15:0] phy_io_o,
-	input  wire [ 3:0] phy_io_oe,
-	input  wire [ 3:0] phy_clk_o,
-	input  wire [CL:0] phy_cs_o,
-
-	// Clock
-	input  wire clk_1x,
-	input  wire clk_4x,
-	input  wire clk_sync
-);
-
-	genvar i;
-
-	wire [ 1:0] iob_clk;
-	wire [ 3:0] iob_io_oe;
-	wire [ 3:0] iob_io_o;
-	wire [ 3:0] iob_io_i;
-	reg  [CL:0] iob_cs_o;
-
-
-	// IOs
-	// ---
-
-	// SERDES
-	generate
-
-		for (i=0; i<4; i=i+1)
-		begin : bit
-			wire [1:0] osd_o;
-			wire [1:0] osd_oe;
-
-			ice40_oserdes #(
-				.MODE("DATA"),
-				.SERDES_GRP((i<<4)|2)
-			) osd_oe_I (
-				.d({4{phy_io_oe[i]}}),
-				.q(osd_oe),
-				.sync(clk_sync),
-				.clk_1x(clk_1x),
-				.clk_4x(clk_4x)
-			);
-
-			ice40_oserdes #(
-				.MODE("DATA"),
-				.SERDES_GRP((i<<4))
-			) osd_o_I (
-				.d(phy_io_o[4*i+:4]),
-				.q(osd_o),
-				.sync(clk_sync),
-				.clk_1x(clk_1x),
-				.clk_4x(clk_4x)
-			);
-
-			assign iob_io_oe[i] = osd_oe[0];
-			assign iob_io_o[i]  = osd_o[0];
-
-			ice40_iserdes #(
-				.EDGE_SEL("SINGLE_POS"),
-				.PHASE_SEL("STATIC"),
-				.PHASE(1),
-				.SERDES_GRP((i<<4))
-			) isd_I (
-				.d({1'b0, iob_io_i[i]}),
-				.q(phy_io_i[4*i+:4]),
-				.edge_sel(1'b0),
-				.phase_sel(2'b00),
-				.sync(clk_sync),
-				.clk_1x(clk_1x),
-				.clk_4x(clk_4x)
-			);
-		end
-
-	endgenerate
-
-
-	// IOB
-	SB_IO #(
-		.PIN_TYPE(6'b1101_00),	// Out:SDRwOE, In:DDR
-		.PULLUP(1'b0),
-		.NEG_TRIGGER(1'b0),
-		.IO_STANDARD("SB_LVCMOS")
-	) iob_spi_io_I[3:0] (
-		.PACKAGE_PIN(pad_io),
-		.OUTPUT_ENABLE(iob_io_oe),
-		.D_OUT_0(iob_io_o),
-		.D_IN_0(),
-		.D_IN_1(iob_io_i),
-		.OUTPUT_CLK(clk_4x),
-		.INPUT_CLK(clk_4x)
-	);
-
-
-	// Clock
-	// -----
-
-	generate
-		if (WITH_CLK) begin
-			// SERDES
-			ice40_oserdes #(
-				.MODE("CLK90_4X"),
-				.SERDES_GRP((4 << 4))
-			) osd_clk_I (
-				.d(phy_clk_o),
-				.q(iob_clk),
-				.sync(clk_sync),
-				.clk_1x(clk_1x),
-				.clk_4x(clk_4x)
-			);
-
-			// IOB
-			SB_IO #(
-				.PIN_TYPE(6'b0100_11),	// Out:DDR, In:n/a
-				.PULLUP(1'b0),
-				.NEG_TRIGGER(1'b0),
-				.IO_STANDARD("SB_LVCMOS")
-			) iob_clk_I (
-				.PACKAGE_PIN(pad_clk),
-				.D_OUT_0(iob_clk[0]),
-				.D_OUT_1(iob_clk[1]),
-				.OUTPUT_CLK(clk_4x)
-			);
-		end
-	endgenerate
-
-
-	// Chip select
-	// -----------
-
-	generate
-		if (N_CS) begin
-			// Delay to match serdes delay
-			always @(posedge clk_1x)
-				iob_cs_o <= phy_cs_o;
-
-			// Because of potential conflict with IO site, we don't register
-			// the CS signal at all and rely on the fact it's held low a bit longer
-			// than needed by the controller.
-			SB_IO #(
-				.PIN_TYPE(6'b0110_11),
-				.PULLUP(1'b1),
-				.NEG_TRIGGER(1'b0),
-				.IO_STANDARD("SB_LVCMOS")
-			) iob_spi_cs_I[N_CS-1:0] (
-				.PACKAGE_PIN(pad_cs_n),
-				.D_OUT_0(iob_cs_o)
-			);
-		end
-	endgenerate
-
-endmodule

+ 0 - 256
cores/qspi_master/sim/qspi_master_tb.v

@@ -1,256 +0,0 @@
-/*
- * qspi_master_tb.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2020  Sylvain Munaut <tnt@246tNt.com>
- * All rights reserved.
- *
- * BSD 3-clause, see LICENSE.bsd
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the <organization> nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-`default_nettype none
-`timescale 1ns / 100ps
-
-module qspi_master_tb;
-
-	// Signals
-	// -------
-
-	// Memory interface
-	wire [ 1:0] mi_addr_cs;
-	reg  [23:0] mi_addr;
-	reg  [ 6:0] mi_len;
-	reg         mi_rw;
-	reg         mi_valid;
-	wire        mi_ready;
-
-	reg  [31:0] mi_wdata;
-	wire        mi_wack;
-	wire        mi_wlast;
-
-	wire [31:0] mi_rdata;
-	wire        mi_rstb;
-	wire        mi_rlast;
-
-	// Wishbone interface
-	reg  [31:0] wb_wdata;
-	wire [31:0] wb_rdata;
-	reg  [ 4:0] wb_addr;
-	reg         wb_we;
-	reg         wb_cyc;
-	wire        wb_ack;
-
-	// Clocks / Sync
-	reg  pll_lock = 1'b0;
-	reg  clk = 1'b0;
-	wire rst;
-
-	reg        rst_div;
-	reg  [1:0] clk_div;
-	reg  [3:0] rst_cnt = 4'h8;
-
-
-	// Recording setup
-	// ---------------
-
-	initial begin
-		$dumpfile("qspi_master_tb.vcd");
-		$dumpvars(0,qspi_master_tb);
-	end
-
-
-	// DUT
-	// ---
-
-	qspi_master #(
-		.CMD_READ(16'h3802),
-		.CMD_WRITE(16'hEBEB),
-		.DUMMY_CLK(6),
-		.PAUSE_CLK(9),
-		.FIFO_DEPTH(1),
-		.N_CS(2),
-		.PHY_SPEED(4),
-		.PHY_WIDTH(1),
-		.PHY_DELAY(2)
-	) dut_I (
-		.mi_addr_cs(mi_addr_cs),
-		.mi_addr(mi_addr),
-		.mi_len(mi_len),
-		.mi_rw(mi_rw),
-		.mi_valid(mi_valid),
-		.mi_ready(mi_ready),
-		.mi_wdata(mi_wdata),
-		.mi_wack(mi_wack),
-		.mi_wlast(mi_wlast),
-		.mi_rdata(mi_rdata),
-		.mi_rstb(mi_rstb),
-		.mi_rlast(mi_rlast),
-		.wb_wdata(wb_wdata),
-		.wb_rdata(wb_rdata),
-		.wb_addr(wb_addr),
-		.wb_we(wb_we),
-		.wb_cyc(wb_cyc),
-		.wb_ack(wb_ack),
-		.clk(clk),
-		.rst(rst)
-	);
-
-
-	// Mem interface
-	// -------------
-
-	// Fixed values
-	assign mi_addr_cs = 2'b01;
-
-	always @(posedge clk)
-		if (rst)
-			mi_wdata <= 32'h00010203;
-		else if (mi_wack)
-			mi_wdata <= mi_wdata + 32'h04040404;
-
-
-	// Stimulus
-	// --------
-
-	task wb_write;
-		input [ 4:0] addr;
-		input [31:0] data;
-		begin
-			wb_addr  <= addr;
-			wb_wdata <= data;
-			wb_we    <= 1'b1;
-			wb_cyc   <= 1'b1;
-
-			while (~wb_ack)
-				@(posedge clk);
-
-			wb_addr  <= 4'hx;
-			wb_wdata <= 32'hxxxxxxxx;
-			wb_we    <= 1'bx;
-			wb_cyc   <= 1'b0;
-
-			@(posedge clk);
-		end
-	endtask
-
-	task mi_burst_write;
-		input [23:0] addr;
-		input [ 6:0] len;
-		begin
-			mi_addr  <= addr;
-			mi_len   <= len;
-			mi_rw    <= 1'b0;
-			mi_valid <= 1'b1;
-
-			@(posedge clk);
-			while (~mi_ready)
-				@(posedge clk);
-
-			mi_valid <= 1'b0;
-		end
-	endtask
-
-	task mi_burst_read;
-		input [23:0] addr;
-		input [ 6:0] len;
-		begin
-			mi_addr  <= addr;
-			mi_len   <= len;
-			mi_rw    <= 1'b1;
-			mi_valid <= 1'b1;
-
-			@(posedge clk);
-			while (~mi_ready)
-				@(posedge clk);
-
-			mi_valid <= 1'b0;
-		end
-	endtask
-
-	initial begin
-		// Defaults
-		wb_addr  <= 4'hx;
-		wb_wdata <= 32'hxxxxxxxx;
-		wb_we    <= 1'bx;
-		wb_cyc   <= 1'b0;
-
-		mi_addr  <= 32'hxxxxxxxx;
-		mi_len   <= 7'hx;
-		mi_rw    <= 1'bx;
-		mi_valid <= 1'b0;
-
-		@(negedge rst);
-		@(posedge clk);
-
-		// Switch to command mode
-		wb_write(5'h00, 32'h00000002);
-
-		// Send SPI command
-		wb_write(5'h10, 32'h01234567);	// 8-bit SPI xfer
-
-		#200
-		@(posedge clk);
-		wb_write(5'h13, 32'h9f000000);
-
-		#400
-		@(posedge clk);
-		wb_write(5'h1f, 32'h01234567);	// 32-bit QPI command write
-
-		// Wait
-		#200
-		@(posedge clk);
-
-		// Switch to run-time mode
-		wb_write(5'h00, 32'h00000004);
-
-		// Execute 32 byte burst
-		mi_burst_read (24'h123456, 7'd31);
-		mi_burst_read (24'h002000, 7'd31);
-		mi_burst_write(24'h003000, 7'd31);
-	end
-
-
-	// Clock / Reset
-	// -------------
-
-	// Native clocks
-	initial begin
-		# 200 pll_lock = 1'b1;
-		# 100000 $finish;
-	end
-
-	always #10 clk = ~clk;		// 50   MHz
-
-	// Reset
-	always @(posedge clk or negedge pll_lock)
-		if (~pll_lock)
-			rst_cnt <= 4'h8;
-		else if (rst_cnt[3])
-			rst_cnt <= rst_cnt + 1;
-
-	assign rst = rst_cnt[3];
-
-endmodule

+ 1 - 1
projects/memtest/Makefile

@@ -31,7 +31,7 @@ VIDEO ?= none
 YOSYS_READ_ARGS += -DMEM_$(MEM)=1 -DVIDEO_$(VIDEO)=1
 
 ifeq ($(MEM),spi)
-	PROJ_DEPS += qspi_master
+	PROJ_DEPS += no2qpimem
 endif
 ifeq ($(MEM),hyperram)
 	PROJ_DEPS += no2hyperbus

+ 4 - 4
projects/memtest/rtl/top.v

@@ -185,7 +185,7 @@ module top (
 	wire [ 1:0] phy_cs_o;
 
 	// Controller
-	qspi_master #(
+	qpi_memctrl #(
 		.CMD_READ(16'hEBEB),
 		.CMD_WRITE(16'h0202),
 		.DUMMY_CLK(6),
@@ -226,7 +226,7 @@ module top (
 	// PHY
 	generate
 		if (PHY_SPEED == 1)
-			qspi_phy_ice40_1x #(
+			qpi_phy_ice40_1x #(
 				.N_CS(2),
 				.WITH_CLK(1),
 				.NEG_IN(0)
@@ -243,7 +243,7 @@ module top (
 			);
 
 		else if (PHY_SPEED == 2)
-			qspi_phy_ice40_2x #(
+			qpi_phy_ice40_2x #(
 				.N_CS(2),
 				.WITH_CLK(1),
 			) phy_I (
@@ -260,7 +260,7 @@ module top (
 			);
 
 		else if (PHY_SPEED == 4)
-			qspi_phy_ice40_4x #(
+			qpi_phy_ice40_4x #(
 				.N_CS(2),
 				.WITH_CLK(1),
 			) phy_I (

+ 1 - 1
projects/riscv_doom/Makefile

@@ -1,7 +1,7 @@
 # Project config
 PROJ = riscv_doom
 
-PROJ_DEPS := no2usb no2misc no2ice40 qspi_master mem_cache video
+PROJ_DEPS := no2usb no2misc no2ice40 no2qpimem mem_cache video
 PROJ_RTL_SRCS := $(addprefix rtl/, \
 	vid_top.v \
 	vid_palette.v \

+ 3 - 3
projects/riscv_doom/rtl/top.v

@@ -290,7 +290,7 @@ module top (
 	mem_sim #(
 		.INIT_FILE("firmware.hex"),
 		.AW(20)
-	) qspi_sim (
+	) qpi_sim (
 		.mi_addr  ({mi_addr[22], mi_addr[18:0]}),
 		.mi_len   (mi_len),
 		.mi_rw    (mi_rw),
@@ -309,7 +309,7 @@ module top (
 	assign wb_ack[0] = wb_cyc[0];
 `else
 	// Controller
-	qspi_master #(
+	qpi_memctrl #(
 		.CMD_READ   (16'hEB0B),
 		.CMD_WRITE  (16'h0202),
 		.DUMMY_CLK  (6),
@@ -348,7 +348,7 @@ module top (
 	);
 
 	// PHY
-	qspi_phy_ice40_4x #(
+	qpi_phy_ice40_4x #(
 		.N_CS(2),
 		.WITH_CLK(1)
 	) phy_I (