mirror of
https://github.com/MiSTer-devel/MacPlus_MiSTer.git
synced 2024-11-27 02:49:32 +00:00
Update SCSI.
This commit is contained in:
parent
ea9c50291c
commit
e4ca3f4533
14
MacPlus.sv
14
MacPlus.sv
@ -266,13 +266,13 @@ end
|
|||||||
// the status register is controlled by the on screen display (OSD)
|
// the status register is controlled by the on screen display (OSD)
|
||||||
wire [31:0] status;
|
wire [31:0] status;
|
||||||
wire [1:0] buttons;
|
wire [1:0] buttons;
|
||||||
wire [31:0] sd_lba[2];
|
wire [31:0] sd_lba;
|
||||||
wire [1:0] sd_rd;
|
wire [1:0] sd_rd;
|
||||||
wire [1:0] sd_wr;
|
wire [1:0] sd_wr;
|
||||||
wire [1:0] sd_ack;
|
wire [1:0] sd_ack;
|
||||||
wire [7:0] sd_buff_addr;
|
wire [7:0] sd_buff_addr;
|
||||||
wire [15:0] sd_buff_dout;
|
wire [15:0] sd_buff_dout;
|
||||||
wire [15:0] sd_buff_din[2];
|
wire [15:0] sd_buff_din;
|
||||||
wire sd_buff_wr;
|
wire sd_buff_wr;
|
||||||
wire [1:0] img_mounted;
|
wire [1:0] img_mounted;
|
||||||
wire [31:0] img_size;
|
wire [31:0] img_size;
|
||||||
@ -297,14 +297,14 @@ hps_io #(.CONF_STR(CONF_STR), .VDNUM(2), .WIDE(1)) hps_io
|
|||||||
.buttons(buttons),
|
.buttons(buttons),
|
||||||
.status(status),
|
.status(status),
|
||||||
|
|
||||||
.sd_lba(sd_lba),
|
.sd_lba('{sd_lba,sd_lba}),
|
||||||
.sd_rd(sd_rd),
|
.sd_rd(sd_rd),
|
||||||
.sd_wr(sd_wr),
|
.sd_wr(sd_wr),
|
||||||
.sd_ack(sd_ack),
|
.sd_ack(sd_ack),
|
||||||
|
|
||||||
.sd_buff_addr(sd_buff_addr),
|
.sd_buff_addr(sd_buff_addr),
|
||||||
.sd_buff_dout(sd_buff_dout),
|
.sd_buff_dout(sd_buff_dout),
|
||||||
.sd_buff_din(sd_buff_din),
|
.sd_buff_din('{sd_buff_din,sd_buff_din}),
|
||||||
.sd_buff_wr(sd_buff_wr),
|
.sd_buff_wr(sd_buff_wr),
|
||||||
|
|
||||||
.img_mounted(img_mounted),
|
.img_mounted(img_mounted),
|
||||||
@ -687,16 +687,14 @@ dataController_top dc0
|
|||||||
// block device interface for scsi disk
|
// block device interface for scsi disk
|
||||||
.img_mounted(img_mounted),
|
.img_mounted(img_mounted),
|
||||||
.img_size(img_size),
|
.img_size(img_size),
|
||||||
.io_lba0(sd_lba[0]),
|
.io_lba(sd_lba),
|
||||||
.io_lba1(sd_lba[1]),
|
|
||||||
.io_rd(sd_rd),
|
.io_rd(sd_rd),
|
||||||
.io_wr(sd_wr),
|
.io_wr(sd_wr),
|
||||||
.io_ack(sd_ack),
|
.io_ack(sd_ack),
|
||||||
|
|
||||||
.sd_buff_addr(sd_buff_addr),
|
.sd_buff_addr(sd_buff_addr),
|
||||||
.sd_buff_dout(sd_buff_dout),
|
.sd_buff_dout(sd_buff_dout),
|
||||||
.sd_buff_din0(sd_buff_din[0]),
|
.sd_buff_din(sd_buff_din),
|
||||||
.sd_buff_din1(sd_buff_din[1]),
|
|
||||||
.sd_buff_wr(sd_buff_wr)
|
.sd_buff_wr(sd_buff_wr)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -81,15 +81,13 @@ module dataController_top(
|
|||||||
// connections to io controller
|
// connections to io controller
|
||||||
input [1:0] img_mounted,
|
input [1:0] img_mounted,
|
||||||
input [31:0] img_size,
|
input [31:0] img_size,
|
||||||
output [31:0] io_lba0,
|
output [31:0] io_lba,
|
||||||
output [31:0] io_lba1,
|
|
||||||
output [1:0] io_rd,
|
output [1:0] io_rd,
|
||||||
output [1:0] io_wr,
|
output [1:0] io_wr,
|
||||||
input [1:0] io_ack,
|
input [1:0] io_ack,
|
||||||
input [7:0] sd_buff_addr,
|
input [7:0] sd_buff_addr,
|
||||||
input [15:0] sd_buff_dout,
|
input [15:0] sd_buff_dout,
|
||||||
output [15:0] sd_buff_din0,
|
output [15:0] sd_buff_din,
|
||||||
output [15:0] sd_buff_din1,
|
|
||||||
input sd_buff_wr
|
input sd_buff_wr
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -169,11 +167,11 @@ module dataController_top(
|
|||||||
// SCSI
|
// SCSI
|
||||||
ncr5380 scsi(
|
ncr5380 scsi(
|
||||||
.clk(clk32),
|
.clk(clk32),
|
||||||
.ce(clk8_en_p),
|
|
||||||
.reset(!_cpuReset),
|
.reset(!_cpuReset),
|
||||||
.bus_cs(selectSCSI),
|
.bus_cs(selectSCSI),
|
||||||
.bus_we(!_cpuRW),
|
|
||||||
.bus_rs(cpuAddrRegMid),
|
.bus_rs(cpuAddrRegMid),
|
||||||
|
.ior(!_cpuUDS),
|
||||||
|
.iow(!_cpuLDS),
|
||||||
.dack(cpuAddrRegHi[0]), // A9
|
.dack(cpuAddrRegHi[0]), // A9
|
||||||
.wdata(cpuDataIn[15:8]),
|
.wdata(cpuDataIn[15:8]),
|
||||||
.rdata(scsiDataOut),
|
.rdata(scsiDataOut),
|
||||||
@ -181,16 +179,14 @@ module dataController_top(
|
|||||||
// connections to io controller
|
// connections to io controller
|
||||||
.img_mounted( img_mounted ),
|
.img_mounted( img_mounted ),
|
||||||
.img_size( img_size ),
|
.img_size( img_size ),
|
||||||
.io_lba0 ( io_lba0 ),
|
.io_lba ( io_lba ),
|
||||||
.io_lba1 ( io_lba1 ),
|
|
||||||
.io_rd ( io_rd ),
|
.io_rd ( io_rd ),
|
||||||
.io_wr ( io_wr ),
|
.io_wr ( io_wr ),
|
||||||
.io_ack ( io_ack ),
|
.io_ack ( io_ack ),
|
||||||
|
|
||||||
.sd_buff_addr(sd_buff_addr),
|
.sd_buff_addr(sd_buff_addr),
|
||||||
.sd_buff_dout(sd_buff_dout),
|
.sd_buff_dout(sd_buff_dout),
|
||||||
.sd_buff_din0(sd_buff_din0),
|
.sd_buff_din(sd_buff_din),
|
||||||
.sd_buff_din1(sd_buff_din1),
|
|
||||||
.sd_buff_wr(sd_buff_wr)
|
.sd_buff_wr(sd_buff_wr)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -215,7 +215,8 @@ module floppy
|
|||||||
|
|
||||||
wire lstrbEdge = lstrb == 1'b0 && lstrbPrev == 1'b1;
|
wire lstrbEdge = lstrb == 1'b0 && lstrbPrev == 1'b1;
|
||||||
|
|
||||||
assign readData = (driveReadAddr == `DRIVE_REG_RDDATA0 || driveReadAddr == `DRIVE_REG_RDDATA1) ? diskDataIn :
|
assign readData = _enable ? 8'hFF :
|
||||||
|
(driveReadAddr == `DRIVE_REG_RDDATA0 || driveReadAddr == `DRIVE_REG_RDDATA1) ? diskDataIn :
|
||||||
{ driveRegsAsRead[driveReadAddr], 7'h00 };
|
{ driveRegsAsRead[driveReadAddr], 7'h00 };
|
||||||
|
|
||||||
// write drive registers
|
// write drive registers
|
||||||
|
239
rtl/ncr5380.v
239
rtl/ncr5380.v
@ -45,38 +45,38 @@
|
|||||||
module ncr5380
|
module ncr5380
|
||||||
(
|
(
|
||||||
input clk,
|
input clk,
|
||||||
input ce,
|
|
||||||
|
|
||||||
input reset,
|
input reset,
|
||||||
|
|
||||||
/* Bus interface. 3-bit address, to be wired
|
/* Bus interface. 3-bit address, to be wired
|
||||||
* appropriately upstream (to A4..A6) plus one
|
* appropriately upstream (to A4..A6) plus one
|
||||||
* more bit (A9) wired as dack.
|
* more bit (A9) wired as dack.
|
||||||
*/
|
*/
|
||||||
input bus_cs,
|
input bus_cs,
|
||||||
input bus_we,
|
|
||||||
input [2:0] bus_rs,
|
input [2:0] bus_rs,
|
||||||
input dack,
|
input ior,
|
||||||
|
input iow,
|
||||||
|
input dack,
|
||||||
|
output dreq,
|
||||||
input [7:0] wdata,
|
input [7:0] wdata,
|
||||||
output [7:0] rdata,
|
output [7:0] rdata,
|
||||||
|
|
||||||
|
|
||||||
// connections to io controller
|
// connections to io controller
|
||||||
input [1:0] img_mounted,
|
input [DEVS-1:0] img_mounted,
|
||||||
input [31:0] img_size,
|
input [31:0] img_size,
|
||||||
|
|
||||||
output [31:0] io_lba0,
|
output reg [31:0] io_lba,
|
||||||
output [31:0] io_lba1,
|
output [DEVS-1:0] io_rd,
|
||||||
output [1:0] io_rd,
|
output [DEVS-1:0] io_wr,
|
||||||
output [1:0] io_wr,
|
input [DEVS-1:0] io_ack,
|
||||||
input [1:0] io_ack,
|
|
||||||
|
|
||||||
input [7:0] sd_buff_addr,
|
input [7:0] sd_buff_addr,
|
||||||
input [15:0] sd_buff_dout,
|
input [15:0] sd_buff_dout,
|
||||||
output [15:0] sd_buff_din0,
|
output reg [15:0] sd_buff_din,
|
||||||
output [15:0] sd_buff_din1,
|
input sd_buff_wr
|
||||||
input sd_buff_wr
|
|
||||||
);
|
);
|
||||||
|
parameter DEVS = 2;
|
||||||
|
|
||||||
|
assign dreq = scsi_req & dma_en;
|
||||||
|
|
||||||
reg [7:0] mr; /* Mode Register */
|
reg [7:0] mr; /* Mode Register */
|
||||||
reg [7:0] icr; /* Initiator Command Register */
|
reg [7:0] icr; /* Initiator Command Register */
|
||||||
@ -86,21 +86,20 @@ module ncr5380
|
|||||||
/* Data in and out latches and associated
|
/* Data in and out latches and associated
|
||||||
* control logic for DMA
|
* control logic for DMA
|
||||||
*/
|
*/
|
||||||
wire [7:0] din;
|
reg [7:0] din;
|
||||||
reg [7:0] dout;
|
reg [7:0] dout;
|
||||||
reg dphase;
|
|
||||||
reg dma_en;
|
reg dma_en;
|
||||||
|
|
||||||
/* --- Main host-side interface --- */
|
/* --- Main host-side interface --- */
|
||||||
|
|
||||||
/* Register & DMA accesses decodes */
|
/* Register & DMA accesses decodes */
|
||||||
reg dma_rd;
|
|
||||||
reg dma_wr;
|
reg dma_wr;
|
||||||
reg reg_wr;
|
reg reg_wr;
|
||||||
|
reg dma_ack;
|
||||||
|
|
||||||
wire i_dma_rd = bus_cs & dack & ~bus_we;
|
wire i_dma_rd = bus_cs & dack & ior;
|
||||||
wire i_dma_wr = bus_cs & dack & bus_we;
|
wire i_dma_wr = bus_cs & dack & iow;
|
||||||
wire i_reg_wr = bus_cs & ~dack & bus_we;
|
wire i_reg_wr = bus_cs & ~dack & iow;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
reg old_dma_rd, old_dma_wr, old_reg_wr;
|
reg old_dma_rd, old_dma_wr, old_reg_wr;
|
||||||
@ -109,13 +108,13 @@ module ncr5380
|
|||||||
old_dma_wr <= i_dma_wr;
|
old_dma_wr <= i_dma_wr;
|
||||||
old_reg_wr <= i_reg_wr;
|
old_reg_wr <= i_reg_wr;
|
||||||
|
|
||||||
dma_rd <= 0;
|
|
||||||
dma_wr <= 0;
|
dma_wr <= 0;
|
||||||
|
dma_ack <= 0;
|
||||||
reg_wr <= 0;
|
reg_wr <= 0;
|
||||||
|
|
||||||
if(~old_dma_wr & i_dma_wr) dma_wr <= 1;
|
if(~old_dma_wr & i_dma_wr) dma_wr <= 1;
|
||||||
else if(~old_dma_rd & i_dma_rd) dma_rd <= 1;
|
if(~old_reg_wr & i_reg_wr) reg_wr <= 1;
|
||||||
else if(~old_reg_wr & i_reg_wr) reg_wr <= 1;
|
if((old_dma_wr & ~i_dma_wr) | (old_dma_rd & ~i_dma_rd)) dma_ack <= dma_en;
|
||||||
end
|
end
|
||||||
|
|
||||||
/* System bus reads */
|
/* System bus reads */
|
||||||
@ -130,31 +129,6 @@ module ncr5380
|
|||||||
bus_rs == `RREG_RST ? 8'hff :
|
bus_rs == `RREG_RST ? 8'hff :
|
||||||
8'hff;
|
8'hff;
|
||||||
|
|
||||||
/* DMA handhsaking logic. Two phase logic, in phase 0
|
|
||||||
* DRQ follows SCSI _REQ until we see DACK. In phase 1
|
|
||||||
* we just wait for SCSI _REQ to go down and go back to
|
|
||||||
* phase 0. We assert SCSI _ACK in phase 1.
|
|
||||||
*/
|
|
||||||
always@(posedge clk or posedge reset) begin
|
|
||||||
if (reset) begin
|
|
||||||
dphase <= 0;
|
|
||||||
end else begin
|
|
||||||
if (!dma_en) begin
|
|
||||||
dphase <= 0;
|
|
||||||
end else if (dphase == 0) begin
|
|
||||||
/* Be careful to do that in bus phase 1,
|
|
||||||
* not phase 0, or we would incorrectly
|
|
||||||
* assert bus_hold and lock up the system
|
|
||||||
*/
|
|
||||||
if ((dma_rd || dma_wr) && scsi_req) begin
|
|
||||||
dphase <= 1;
|
|
||||||
end
|
|
||||||
end else if (!scsi_req) begin
|
|
||||||
dphase <= 0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
/* Data out latch (in DMA mode, this is one cycle after we've
|
/* Data out latch (in DMA mode, this is one cycle after we've
|
||||||
* asserted ACK)
|
* asserted ACK)
|
||||||
*/
|
*/
|
||||||
@ -241,119 +215,94 @@ module ncr5380
|
|||||||
/* BSY logic (simplified arbitration, see notes) */
|
/* BSY logic (simplified arbitration, see notes) */
|
||||||
wire scsi_bsy =
|
wire scsi_bsy =
|
||||||
icr[`ICR_A_BSY] |
|
icr[`ICR_A_BSY] |
|
||||||
scsi2_bsy |
|
|target_bsy |
|
||||||
scsi6_bsy |
|
//scsi2_bsy |
|
||||||
|
//scsi6_bsy |
|
||||||
mr[`MR_ARB];
|
mr[`MR_ARB];
|
||||||
|
|
||||||
/* Remains of simplified arbitration logic */
|
/* Remains of simplified arbitration logic */
|
||||||
wire icr_aip = mr[`MR_ARB];
|
wire icr_aip = mr[`MR_ARB];
|
||||||
wire icr_la = 0;
|
wire icr_la = 0;
|
||||||
|
|
||||||
reg dma_ack;
|
|
||||||
always @(posedge clk) if(ce) dma_ack <= dphase;
|
|
||||||
|
|
||||||
/* Other ORed SCSI signals */
|
/* Other ORed SCSI signals */
|
||||||
wire scsi_sel = icr[`ICR_A_SEL];
|
wire scsi_sel = icr[`ICR_A_SEL];
|
||||||
wire scsi_rst = icr[`ICR_A_RST];
|
wire scsi_rst = icr[`ICR_A_RST];
|
||||||
wire scsi_ack = icr[`ICR_A_ACK] | dma_ack;
|
wire scsi_ack = icr[`ICR_A_ACK] | dma_ack;
|
||||||
wire scsi_atn = icr[`ICR_A_ATN];
|
wire scsi_atn = icr[`ICR_A_ATN];
|
||||||
/*
|
|
||||||
wire scsi_cd = scsi2_cd;
|
|
||||||
wire scsi_io = scsi2_io;
|
|
||||||
wire scsi_msg = scsi2_msg;
|
|
||||||
wire scsi_req = scsi2_req;
|
|
||||||
|
|
||||||
assign din = scsi2_dout;
|
/* Mux target signals */
|
||||||
|
reg scsi_cd, scsi_io, scsi_msg, scsi_req;
|
||||||
|
|
||||||
assign io_lba = io_lba_2;
|
always begin
|
||||||
assign sd_buff_din = sd_buff_din_2;
|
integer i;
|
||||||
*/
|
scsi_cd = 0;
|
||||||
/* Other trivial lines set by target */
|
scsi_io = 0;
|
||||||
|
scsi_msg = 0;
|
||||||
|
scsi_req = 0;
|
||||||
|
din = 8'h55;
|
||||||
|
io_lba = 0;
|
||||||
|
sd_buff_din = 0;
|
||||||
|
|
||||||
wire scsi_cd = (scsi2_bsy) ? scsi2_cd : scsi6_cd;
|
for (i = 0; i < DEVS; i = i + 1) begin
|
||||||
wire scsi_io = (scsi2_bsy) ? scsi2_io : scsi6_io;
|
if (target_bsy[i]) begin
|
||||||
wire scsi_msg = (scsi2_bsy) ? scsi2_msg : scsi6_msg;
|
scsi_cd = target_cd[i];
|
||||||
wire scsi_req = (scsi2_bsy) ? scsi2_req : scsi6_req;
|
scsi_io = target_io[i];
|
||||||
|
scsi_msg = target_msg[i];
|
||||||
|
scsi_req = target_req[i];
|
||||||
|
din = target_dout[i];
|
||||||
|
io_lba = target_lba[i];
|
||||||
|
sd_buff_din = target_buff_din[i];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
assign din = scsi2_bsy ? scsi2_dout :
|
// input signals from targets
|
||||||
scsi6_bsy ? scsi6_dout :
|
wire [DEVS-1:0] target_bsy;
|
||||||
8'h55;
|
wire [DEVS-1:0] target_msg;
|
||||||
|
wire [DEVS-1:0] target_io;
|
||||||
|
wire [DEVS-1:0] target_cd;
|
||||||
|
wire [DEVS-1:0] target_req;
|
||||||
|
wire [7:0] target_dout[DEVS];
|
||||||
|
wire [31:0] target_lba[DEVS];
|
||||||
|
wire [15:0] target_buff_din[DEVS];
|
||||||
|
|
||||||
// input signals from target 2
|
generate
|
||||||
wire scsi2_bsy, scsi2_msg, scsi2_io, scsi2_cd, scsi2_req;
|
genvar i;
|
||||||
wire [7:0] scsi2_dout;
|
for (i = 0; i < DEVS; i = i + 1) begin : target
|
||||||
|
// connect a target
|
||||||
|
scsi #(.ID(3'd6 - i[2:0])) target
|
||||||
|
(
|
||||||
|
.clk ( clk ),
|
||||||
|
.rst ( scsi_rst ),
|
||||||
|
.sel ( scsi_sel ),
|
||||||
|
.atn ( scsi_atn ),
|
||||||
|
|
||||||
// connect a target
|
.ack ( scsi_ack ),
|
||||||
scsi #(.ID(2)) scsi2
|
|
||||||
(
|
|
||||||
.clk ( clk ),
|
|
||||||
.rst ( scsi_rst ),
|
|
||||||
.sel ( scsi_sel ),
|
|
||||||
.atn ( scsi_atn ),
|
|
||||||
|
|
||||||
.ack ( scsi_ack ),
|
.bsy ( target_bsy[i] ),
|
||||||
|
.msg ( target_msg[i] ),
|
||||||
|
.cd ( target_cd[i] ),
|
||||||
|
.io ( target_io[i] ),
|
||||||
|
.req ( target_req[i] ),
|
||||||
|
.dout ( target_dout[i] ),
|
||||||
|
|
||||||
.bsy ( scsi2_bsy ),
|
.din ( dout ),
|
||||||
.msg ( scsi2_msg ),
|
|
||||||
.cd ( scsi2_cd ),
|
|
||||||
.io ( scsi2_io ),
|
|
||||||
.req ( scsi2_req ),
|
|
||||||
.dout ( scsi2_dout ),
|
|
||||||
|
|
||||||
.din ( dout ),
|
// connection to io controller to read and write sectors
|
||||||
|
// to sd card
|
||||||
// connection to io controller to read and write sectors
|
.img_mounted(img_mounted[i]),
|
||||||
// to sd card
|
.img_blocks(img_size),
|
||||||
.img_mounted(img_mounted[1]),
|
.io_lba ( target_lba[i] ),
|
||||||
.img_blocks(img_size[31:9]),
|
.io_rd ( io_rd[i] ),
|
||||||
.io_lba ( io_lba1 ),
|
.io_wr ( io_wr[i] ),
|
||||||
.io_rd ( io_rd[1] ),
|
.io_ack ( io_ack[i] & target_bsy[i] ),
|
||||||
.io_wr ( io_wr[1] ),
|
|
||||||
.io_ack ( io_ack[1] ),
|
|
||||||
|
|
||||||
.sd_buff_addr( sd_buff_addr ),
|
|
||||||
.sd_buff_dout( sd_buff_dout ),
|
|
||||||
.sd_buff_din( sd_buff_din1 ),
|
|
||||||
.sd_buff_wr( sd_buff_wr )
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// input signals from target 6
|
|
||||||
wire scsi6_bsy, scsi6_msg, scsi6_io, scsi6_cd, scsi6_req;
|
|
||||||
wire [7:0] scsi6_dout;
|
|
||||||
|
|
||||||
scsi #(.ID(6)) scsi6
|
|
||||||
(
|
|
||||||
.clk ( clk ) , // input clk
|
|
||||||
.rst ( scsi_rst ) , // input rst
|
|
||||||
.sel ( scsi_sel ) , // input sel
|
|
||||||
.atn ( scsi_atn ) , // input atn
|
|
||||||
|
|
||||||
.ack ( scsi_ack ) , // input ack
|
|
||||||
|
|
||||||
.bsy ( scsi6_bsy ) , // output bsy
|
|
||||||
.msg ( scsi6_msg ) , // output msg
|
|
||||||
.cd ( scsi6_cd ) , // output cd
|
|
||||||
.io ( scsi6_io ) , // output io
|
|
||||||
.req ( scsi6_req ) , // output req
|
|
||||||
.dout ( scsi6_dout ) , // output [7:0] dout
|
|
||||||
|
|
||||||
.din ( dout ) , // input [7:0] din
|
|
||||||
|
|
||||||
// connection to io controller to read and write sectors
|
|
||||||
// to sd card
|
|
||||||
.img_mounted( img_mounted[0] ),
|
|
||||||
.img_blocks( img_size[31:9] ),
|
|
||||||
.io_lba ( io_lba0 ) , // output [31:0] io_lba
|
|
||||||
.io_rd ( io_rd[0] ) , // output io_rd
|
|
||||||
.io_wr ( io_wr[0] ) , // output io_wr
|
|
||||||
.io_ack ( io_ack[0] ) , // input io_ack
|
|
||||||
|
|
||||||
.sd_buff_addr( sd_buff_addr ) , // input [8:0] sd_buff_addr
|
|
||||||
.sd_buff_dout( sd_buff_dout ) , // input [7:0] sd_buff_dout
|
|
||||||
.sd_buff_din( sd_buff_din0 ) , // output [7:0] sd_buff_din
|
|
||||||
.sd_buff_wr( sd_buff_wr ) // input sd_buff_wr
|
|
||||||
);
|
|
||||||
|
|
||||||
|
.sd_buff_addr( sd_buff_addr ),
|
||||||
|
.sd_buff_dout( sd_buff_dout ),
|
||||||
|
.sd_buff_din( target_buff_din[i] ),
|
||||||
|
.sd_buff_wr( sd_buff_wr & target_bsy[i] )
|
||||||
|
);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
262
rtl/scsi.v
262
rtl/scsi.v
@ -1,5 +1,4 @@
|
|||||||
/* verilator lint_off UNUSED */
|
/* verilator lint_off UNUSED */
|
||||||
/* verilator lint_off SYNCASYNCNET */
|
|
||||||
|
|
||||||
// scsi.v
|
// scsi.v
|
||||||
// implements a target only scsi device
|
// implements a target only scsi device
|
||||||
@ -26,45 +25,73 @@ module scsi
|
|||||||
|
|
||||||
// interface to io controller
|
// interface to io controller
|
||||||
input img_mounted,
|
input img_mounted,
|
||||||
input [23:0] img_blocks,
|
input [31:0] img_blocks,
|
||||||
output [31:0] io_lba,
|
output [31:0] io_lba,
|
||||||
output reg io_rd,
|
output reg io_rd,
|
||||||
output reg io_wr,
|
output reg io_wr,
|
||||||
input io_ack,
|
input io_ack,
|
||||||
|
|
||||||
input [7:0] sd_buff_addr,
|
input [7:0] sd_buff_addr,
|
||||||
input [15:0] sd_buff_dout,
|
input [15:0] sd_buff_dout,
|
||||||
output reg [15:0] sd_buff_din,
|
output [15:0] sd_buff_din,
|
||||||
input sd_buff_wr
|
input sd_buff_wr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// SCSI device id
|
// SCSI device id
|
||||||
parameter [7:0] ID = 0;
|
parameter [2:0] ID = 0;
|
||||||
|
|
||||||
`define PHASE_IDLE 3'd0
|
localparam PHASE_IDLE = 3'd0;
|
||||||
`define PHASE_CMD_IN 3'd1
|
localparam PHASE_CMD_IN = 3'd1;
|
||||||
`define PHASE_DATA_OUT 3'd2
|
localparam PHASE_DATA_OUT = 3'd2;
|
||||||
`define PHASE_DATA_IN 3'd3
|
localparam PHASE_DATA_IN = 3'd3;
|
||||||
`define PHASE_STATUS_OUT 3'd4
|
localparam PHASE_STATUS_OUT = 3'd4;
|
||||||
`define PHASE_MESSAGE_OUT 3'd5
|
localparam PHASE_MESSAGE_OUT = 3'd5;
|
||||||
reg [2:0] phase;
|
reg [2:0] phase;
|
||||||
|
|
||||||
// ---------------- buffer read engine -----------------------
|
// ------------ sector buffer IO controller read/write -----------------------
|
||||||
// the buffer itself. Can hold one sector
|
// the buffer itself. Can hold two sectors
|
||||||
reg [7:0] buffer_out0 [256];
|
reg sd_buff_sel;
|
||||||
always @(posedge clk) sd_buff_din[7:0] <= buffer_out0[sd_buff_addr];
|
|
||||||
|
|
||||||
reg [7:0] buffer_out1 [256];
|
wire [7:0] buffer0_dout;
|
||||||
always @(posedge clk) sd_buff_din[15:8] <= buffer_out1[sd_buff_addr];
|
scsi_dpram buffer0
|
||||||
|
(
|
||||||
|
.clock(clk),
|
||||||
|
|
||||||
// ---------------- buffer write engine ----------------------
|
.address_a({sd_buff_sel, sd_buff_addr}),
|
||||||
// the buffer itself. Can hold one sector
|
.data_a(sd_buff_dout[7:0]),
|
||||||
reg [7:0] buffer_in0 [256];
|
.wren_a(sd_buff_wr),
|
||||||
always @(posedge clk) if(sd_buff_wr & io_ack) buffer_in0[sd_buff_addr] <= sd_buff_dout[7:0];
|
.q_a(sd_buff_din[7:0]),
|
||||||
|
|
||||||
reg [7:0] buffer_in1 [256];
|
.address_b(data_cnt[9:1]),
|
||||||
always @(posedge clk) if(sd_buff_wr & io_ack) buffer_in1[sd_buff_addr] <= sd_buff_dout[15:8];
|
.data_b(din),
|
||||||
|
.wren_b(buffer0_wr),
|
||||||
|
.q_b(buffer0_dout)
|
||||||
|
);
|
||||||
|
|
||||||
|
wire [7:0] buffer1_dout;
|
||||||
|
scsi_dpram buffer1
|
||||||
|
(
|
||||||
|
.clock(clk),
|
||||||
|
|
||||||
|
.address_a({sd_buff_sel, sd_buff_addr}),
|
||||||
|
.data_a(sd_buff_dout[15:8]),
|
||||||
|
.wren_a(sd_buff_wr),
|
||||||
|
.q_a(sd_buff_din[15:8]),
|
||||||
|
|
||||||
|
.address_b(data_cnt[9:1]),
|
||||||
|
.data_b(din),
|
||||||
|
.wren_b(buffer1_wr),
|
||||||
|
.q_b(buffer1_dout)
|
||||||
|
);
|
||||||
|
|
||||||
|
reg old_io_ack;
|
||||||
|
always @(posedge clk) begin
|
||||||
|
old_io_ack <= io_ack;
|
||||||
|
if (phase == PHASE_IDLE)
|
||||||
|
sd_buff_sel <= 0;
|
||||||
|
else
|
||||||
|
if (old_io_ack & ~io_ack) sd_buff_sel <= !sd_buff_sel;
|
||||||
|
end
|
||||||
|
|
||||||
// -----------------------------------------------------------
|
// -----------------------------------------------------------
|
||||||
|
|
||||||
@ -77,20 +104,25 @@ reg [7:0] status;
|
|||||||
`define MSG_CMD_COMPLETE 8'h00
|
`define MSG_CMD_COMPLETE 8'h00
|
||||||
|
|
||||||
// drive scsi signals according to phase
|
// drive scsi signals according to phase
|
||||||
assign msg = (phase == `PHASE_MESSAGE_OUT);
|
assign msg = (phase == PHASE_MESSAGE_OUT);
|
||||||
assign cd = (phase == `PHASE_CMD_IN) || (phase == `PHASE_STATUS_OUT) || (phase == `PHASE_MESSAGE_OUT);
|
assign cd = (phase == PHASE_CMD_IN) || (phase == PHASE_STATUS_OUT) || (phase == PHASE_MESSAGE_OUT);
|
||||||
assign io = (phase == `PHASE_DATA_OUT) || (phase == `PHASE_STATUS_OUT) || (phase == `PHASE_MESSAGE_OUT);
|
assign io = (phase == PHASE_DATA_OUT) || (phase == PHASE_STATUS_OUT) || (phase == PHASE_MESSAGE_OUT);
|
||||||
assign req = (phase != `PHASE_IDLE) && !ack && !io_rd && !io_wr && !io_ack;
|
|
||||||
assign bsy = (phase != `PHASE_IDLE);
|
|
||||||
|
|
||||||
assign dout = (phase == `PHASE_STATUS_OUT)?status:
|
wire io_busy = (phase == PHASE_DATA_OUT && (io_rd | io_ack) && data_cnt[9] == sd_buff_sel) ||
|
||||||
(phase == `PHASE_MESSAGE_OUT)?`MSG_CMD_COMPLETE:
|
(phase == PHASE_DATA_IN && (io_wr | io_ack) && data_cnt[9] == sd_buff_sel) ||
|
||||||
(phase == `PHASE_DATA_OUT)?cmd_dout:
|
(phase != PHASE_DATA_OUT && phase != PHASE_DATA_IN && (io_rd | io_wr | io_ack));
|
||||||
|
assign req = (phase != PHASE_IDLE) && !ack && !io_busy;
|
||||||
|
|
||||||
|
assign bsy = (phase != PHASE_IDLE);
|
||||||
|
|
||||||
|
assign dout = (phase == PHASE_STATUS_OUT)?status:
|
||||||
|
(phase == PHASE_MESSAGE_OUT)?`MSG_CMD_COMPLETE:
|
||||||
|
(phase == PHASE_DATA_OUT)?cmd_dout:
|
||||||
8'h00;
|
8'h00;
|
||||||
|
|
||||||
// de-multiplex different data sources
|
// de-multiplex different data sources
|
||||||
wire [7:0] cmd_dout =
|
wire [7:0] cmd_dout =
|
||||||
cmd_read?buffer_dout:
|
cmd_read?(data_cnt[0] ? buffer1_dout : buffer0_dout):
|
||||||
cmd_inquiry?inquiry_dout:
|
cmd_inquiry?inquiry_dout:
|
||||||
cmd_read_capacity?read_capacity_dout:
|
cmd_read_capacity?read_capacity_dout:
|
||||||
cmd_mode_sense?mode_sense_dout:
|
cmd_mode_sense?mode_sense_dout:
|
||||||
@ -112,23 +144,30 @@ wire [7:0] inquiry_dout =
|
|||||||
|
|
||||||
(data_cnt == 32'd26)?"S":(data_cnt == 32'd27)?"T":
|
(data_cnt == 32'd26)?"S":(data_cnt == 32'd27)?"T":
|
||||||
(data_cnt == 32'd28)?"2":(data_cnt == 32'd29)?"2":
|
(data_cnt == 32'd28)?"2":(data_cnt == 32'd29)?"2":
|
||||||
(data_cnt == 32'd30)?"5":(data_cnt == 32'd31)?"N" + ID: // TESTING. ElectronAsh.
|
(data_cnt == 32'd30)?"5":(data_cnt == 32'd31)?"N" + {5'd0, ID}: // TESTING. ElectronAsh.
|
||||||
8'h00;
|
8'h00;
|
||||||
|
|
||||||
// output of read capacity command
|
// output of read capacity command
|
||||||
//wire [31:0] capacity = 32'd41056; // 40960 + 96 blocks = 20MB
|
//wire [31:0] capacity = 32'd41056; // 40960 + 96 blocks = 20MB
|
||||||
//wire [31:0] capacity = 32'd1024096; // 1024000 + 96 blocks = 500MB
|
//wire [31:0] capacity = 32'd1024096; // 1024000 + 96 blocks = 500MB
|
||||||
reg [31:0] capacity;
|
reg [31:0] capacity;
|
||||||
|
reg mounted = 0;
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (img_mounted) capacity <= img_blocks + 8'd96;
|
if (img_mounted) begin
|
||||||
|
if (|img_blocks) begin
|
||||||
|
capacity <= img_blocks;
|
||||||
|
$display("Image mounted on target %d, size: %d", ID, img_blocks);
|
||||||
|
mounted <= 1;
|
||||||
|
end else
|
||||||
|
mounted <= 0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
wire [31:0] capacity_m1 = capacity - 32'd1;
|
|
||||||
wire [7:0] read_capacity_dout =
|
wire [7:0] read_capacity_dout =
|
||||||
(data_cnt == 32'd0 )?capacity_m1[31:24]:
|
(data_cnt == 32'd0 )?capacity[31:24]:
|
||||||
(data_cnt == 32'd1 )?capacity_m1[23:16]:
|
(data_cnt == 32'd1 )?capacity[23:16]:
|
||||||
(data_cnt == 32'd2 )?capacity_m1[15:8]:
|
(data_cnt == 32'd2 )?capacity[15:8]:
|
||||||
(data_cnt == 32'd3 )?capacity_m1[7:0]:
|
(data_cnt == 32'd3 )?capacity[7:0]:
|
||||||
(data_cnt == 32'd6 )?8'd2: // 512 bytes per sector
|
(data_cnt == 32'd6 )?8'd2: // 512 bytes per sector
|
||||||
8'h00;
|
8'h00;
|
||||||
|
|
||||||
@ -140,40 +179,44 @@ wire [7:0] mode_sense_dout =
|
|||||||
(data_cnt == 32'd10 )?8'd2:
|
(data_cnt == 32'd10 )?8'd2:
|
||||||
8'h00;
|
8'h00;
|
||||||
|
|
||||||
// clock data out of buffer to allow for embedded ram
|
|
||||||
reg [7:0] buffer_dout;
|
|
||||||
always @(posedge clk) buffer_dout <= data_cnt[0] ? buffer_in1[data_cnt[8:1]] : buffer_in0[data_cnt[8:1]];
|
|
||||||
|
|
||||||
// buffer to store incoming commands
|
// buffer to store incoming commands
|
||||||
reg [3:0] cmd_cnt;
|
reg [3:0] cmd_cnt;
|
||||||
reg [7:0] cmd [9:0];
|
reg [7:0] cmd [9:0];
|
||||||
|
|
||||||
/* ----------------------- request data from/to io controller ----------------------- */
|
/* ----------------------- request data from/to io controller ----------------------- */
|
||||||
|
|
||||||
// base address of current block. Subtract one when writing since the writing happens
|
assign io_lba = lba;
|
||||||
// after a block has been transferred and data_cnt has thus already been increased by 512
|
|
||||||
assign io_lba = lba + { 9'd0, data_cnt[31:9] } -
|
// generate an io_rd signal whenever the first byte of a 512 byte block is required
|
||||||
(cmd_write ? 32'd1 : 32'd0);
|
// start fetching the next sector when the 20th byte is read, and it's not the last sector
|
||||||
|
wire req_rd = ((phase == PHASE_DATA_OUT) && cmd_read && (data_cnt == 0 || (data_cnt[8:0] == 9'd20 && data_cnt[31:9] != ({7'd0, tlen} - 1'd1))) && !data_complete);
|
||||||
|
|
||||||
|
// generate an io_wr signal whenever a 512 byte block has been received or when the status
|
||||||
|
// phase of a write command has been reached
|
||||||
|
wire req_wr = ((((phase == PHASE_DATA_IN) && (data_cnt[8:0] == 0) && (data_cnt != 0)) || (phase == PHASE_STATUS_OUT)) && cmd_write);
|
||||||
|
|
||||||
wire req_rd = ((phase == `PHASE_DATA_OUT) && cmd_read && (data_cnt[8:0] == 0) && !data_complete);
|
|
||||||
wire req_wr = ((((phase == `PHASE_DATA_IN) && (data_cnt[8:0] == 0) && (data_cnt != 0)) || (phase == `PHASE_STATUS_OUT)) && cmd_write);
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
reg old_rd, old_wr;
|
reg old_rd, old_wr;
|
||||||
|
reg wr_pending, rd_pending;
|
||||||
|
|
||||||
old_rd <= req_rd;
|
old_rd <= req_rd;
|
||||||
old_wr <= req_wr;
|
old_wr <= req_wr;
|
||||||
|
if(~old_rd & req_rd) rd_pending <= 1;
|
||||||
|
if(~old_wr & req_wr) wr_pending <= 1;
|
||||||
|
|
||||||
if(io_ack) begin
|
if(io_ack) begin
|
||||||
io_rd <= 1'b0;
|
io_rd <= 1'b0;
|
||||||
io_wr <= 1'b0;
|
io_wr <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
// generate an io_rd signal whenever the first byte of a 512 byte block is required and io_wr whenever
|
if (rd_pending && !io_rd) begin
|
||||||
// the last byte of a 512 byte block has been revceived
|
io_rd <= 1;
|
||||||
if(~old_rd & req_rd) io_rd <= 1;
|
rd_pending <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
// generate an io_wr signal whenever a 512 byte block has been received or when the status
|
if (wr_pending && !io_wr) begin
|
||||||
// phase of a write command has been reached
|
io_wr <= 1;
|
||||||
if(~old_wr & req_wr) io_wr <= 1;
|
wr_pending <= 0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -187,21 +230,25 @@ always @(posedge clk) begin
|
|||||||
stb_adv <= (old_ack & ~ack); // on falling edge
|
stb_adv <= (old_ack & ~ack); // on falling edge
|
||||||
end
|
end
|
||||||
|
|
||||||
|
reg buffer0_wr, buffer1_wr;
|
||||||
|
|
||||||
// store data on rising edge of ack, ...
|
// store data on rising edge of ack, ...
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
|
buffer0_wr <= 0;
|
||||||
|
buffer1_wr <= 0;
|
||||||
if(stb_ack) begin
|
if(stb_ack) begin
|
||||||
if(phase == `PHASE_CMD_IN) cmd[cmd_cnt] <= din;
|
if(phase == PHASE_CMD_IN) cmd[cmd_cnt] <= din;
|
||||||
if(phase == `PHASE_DATA_IN) begin
|
if(phase == PHASE_DATA_IN) begin
|
||||||
if(data_cnt[0]) buffer_out1[data_cnt[8:1]] <= din;
|
buffer0_wr <= ~data_cnt[0];
|
||||||
else buffer_out0[data_cnt[8:1]] <= din;
|
buffer1_wr <= data_cnt[0];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// ... advance counter on falling edge
|
// ... advance counter on falling edge
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if(phase == `PHASE_IDLE) cmd_cnt <= 4'd0;
|
if(phase == PHASE_IDLE) cmd_cnt <= 4'd0;
|
||||||
else if(stb_adv && (phase == `PHASE_CMD_IN) && (cmd_cnt != 15)) cmd_cnt <= cmd_cnt + 4'd1;
|
else if(stb_adv && (phase == PHASE_CMD_IN) && (cmd_cnt != 15)) cmd_cnt <= cmd_cnt + 4'd1;
|
||||||
end
|
end
|
||||||
|
|
||||||
// count data bytes. don't increase counter while we are waiting for data from
|
// count data bytes. don't increase counter while we are waiting for data from
|
||||||
@ -221,7 +268,7 @@ wire [31:0] data_len =
|
|||||||
{ 16'd0, tlen }; // inquiry etc have length in bytes
|
{ 16'd0, tlen }; // inquiry etc have length in bytes
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if((phase != `PHASE_DATA_OUT) && (phase != `PHASE_DATA_IN) && (phase != `PHASE_STATUS_OUT) && (phase != `PHASE_MESSAGE_OUT)) begin
|
if((phase != PHASE_DATA_OUT) && (phase != PHASE_DATA_IN) && (phase != PHASE_STATUS_OUT) && (phase != PHASE_MESSAGE_OUT)) begin
|
||||||
data_cnt <= 0;
|
data_cnt <= 0;
|
||||||
data_complete <= 0;
|
data_complete <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
@ -235,14 +282,14 @@ end
|
|||||||
// check whether status byte has been sent
|
// check whether status byte has been sent
|
||||||
reg status_sent;
|
reg status_sent;
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if(phase != `PHASE_STATUS_OUT) status_sent <= 0;
|
if(phase != PHASE_STATUS_OUT) status_sent <= 0;
|
||||||
else if(stb_adv) status_sent <= 1;
|
else if(stb_adv) status_sent <= 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
// check whether message byte has been sent
|
// check whether message byte has been sent
|
||||||
reg message_sent;
|
reg message_sent;
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if(phase != `PHASE_MESSAGE_OUT) message_sent <= 0;
|
if(phase != PHASE_MESSAGE_OUT) message_sent <= 0;
|
||||||
else if(stb_adv) message_sent <= 1;
|
else if(stb_adv) message_sent <= 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -273,18 +320,21 @@ wire cmd_test_unit_ready = (op_code == 8'h00);
|
|||||||
wire cmd_read_capacity = (op_code == 8'h25);
|
wire cmd_read_capacity = (op_code == 8'h25);
|
||||||
wire cmd_read_buffer = (op_code == 8'h3b); // fake
|
wire cmd_read_buffer = (op_code == 8'h3b); // fake
|
||||||
wire cmd_write_buffer = (op_code == 8'h3c); // fake
|
wire cmd_write_buffer = (op_code == 8'h3c); // fake
|
||||||
|
wire cmd_verify6 = (op_code == 8'h13); // fake
|
||||||
|
wire cmd_verify10 = (op_code == 8'h2f); // fake
|
||||||
|
|
||||||
// valid command in buffer? TODO: check for valid command parameters
|
// valid command in buffer? TODO: check for valid command parameters
|
||||||
wire cmd_ok = cmd_read || cmd_write || cmd_inquiry || cmd_test_unit_ready ||
|
wire cmd_ok = cmd_read || cmd_write || cmd_inquiry || cmd_test_unit_ready ||
|
||||||
cmd_read_capacity || cmd_mode_select || cmd_format || cmd_mode_sense ||
|
cmd_read_capacity || cmd_mode_select || cmd_format || cmd_mode_sense ||
|
||||||
cmd_read_buffer | cmd_write_buffer;
|
cmd_read_buffer || cmd_write_buffer || cmd_verify6 || cmd_verify10;
|
||||||
|
|
||||||
// latch parameters once command is complete
|
// latch parameters once command is complete
|
||||||
reg [31:0] lba;
|
reg [31:0] lba;
|
||||||
reg [15:0] tlen;
|
reg [15:0] tlen;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if(cmd_cpl && (phase == `PHASE_CMD_IN)) begin
|
if (old_io_ack & ~io_ack) lba <= lba + 1'd1;
|
||||||
|
if(cmd_cpl && (phase == PHASE_CMD_IN)) begin
|
||||||
lba <= cmd6_cpl?{11'd0, lba6}:lba10;
|
lba <= cmd6_cpl?{11'd0, lba6}:lba10;
|
||||||
tlen <= cmd6_cpl?{7'd0, tlen6}:tlen10;
|
tlen <= cmd6_cpl?{7'd0, tlen6}:tlen10;
|
||||||
end
|
end
|
||||||
@ -304,16 +354,17 @@ wire [15:0] tlen10 = { cmd[7], cmd[8] };
|
|||||||
// on the rising edge
|
// on the rising edge
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if(rst) begin
|
if(rst) begin
|
||||||
phase <= `PHASE_IDLE;
|
phase <= PHASE_IDLE;
|
||||||
end else begin
|
end else begin
|
||||||
if(phase == `PHASE_IDLE) begin
|
if(phase == PHASE_IDLE) begin
|
||||||
if(sel && din[ID]) // own id on bus during selection?
|
if(sel && din[ID] && mounted) // own id on bus during selection?
|
||||||
phase <= `PHASE_CMD_IN;
|
phase <= PHASE_CMD_IN;
|
||||||
end
|
end
|
||||||
|
|
||||||
else if(phase == `PHASE_CMD_IN) begin
|
else if(phase == PHASE_CMD_IN) begin
|
||||||
// check if a full command is in the buffer
|
// check if a full command is in the buffer
|
||||||
if(cmd_cpl) begin
|
if(cmd_cpl) begin
|
||||||
|
$display("New command on target %d: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", ID, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], cmd[9]);
|
||||||
// is this a supported and valid command?
|
// is this a supported and valid command?
|
||||||
if(cmd_ok) begin
|
if(cmd_ok) begin
|
||||||
// yes, continue
|
// yes, continue
|
||||||
@ -322,39 +373,76 @@ always @(posedge clk) begin
|
|||||||
// continue according to command
|
// continue according to command
|
||||||
|
|
||||||
// these commands return data
|
// these commands return data
|
||||||
if(cmd_read || cmd_inquiry || cmd_read_capacity || cmd_mode_sense || cmd_read_buffer) phase <= `PHASE_DATA_OUT;
|
if(cmd_read || cmd_inquiry || cmd_read_capacity || cmd_mode_sense || cmd_read_buffer) phase <= PHASE_DATA_OUT;
|
||||||
// these commands receive dataa
|
// these commands receive dataa
|
||||||
else if(cmd_write || cmd_mode_select || cmd_write_buffer) phase <= `PHASE_DATA_IN;
|
else if(cmd_write || cmd_mode_select || cmd_write_buffer) phase <= PHASE_DATA_IN;
|
||||||
// and all other valid commands are just "ok"
|
// and all other valid commands are just "ok"
|
||||||
else phase <= `PHASE_STATUS_OUT;
|
else phase <= PHASE_STATUS_OUT;
|
||||||
end else begin
|
end else begin
|
||||||
// no, report failure
|
// no, report failure
|
||||||
status <= `STATUS_CHECK_CONDITION;
|
status <= `STATUS_CHECK_CONDITION;
|
||||||
phase <= `PHASE_STATUS_OUT;
|
phase <= PHASE_STATUS_OUT;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
else if(phase == `PHASE_DATA_OUT) begin
|
else if(phase == PHASE_DATA_OUT) begin
|
||||||
if(data_complete) phase <= `PHASE_STATUS_OUT;
|
if(data_complete) phase <= PHASE_STATUS_OUT;
|
||||||
end
|
end
|
||||||
|
|
||||||
else if(phase == `PHASE_DATA_IN) begin
|
else if(phase == PHASE_DATA_IN) begin
|
||||||
if(data_complete) phase <= `PHASE_STATUS_OUT;
|
if(data_complete) phase <= PHASE_STATUS_OUT;
|
||||||
end
|
end
|
||||||
|
|
||||||
else if(phase == `PHASE_STATUS_OUT) begin
|
else if(phase == PHASE_STATUS_OUT) begin
|
||||||
if(status_sent) phase <= `PHASE_MESSAGE_OUT;
|
if(status_sent) phase <= PHASE_MESSAGE_OUT;
|
||||||
end
|
end
|
||||||
|
|
||||||
else if(phase == `PHASE_MESSAGE_OUT) begin
|
else if(phase == PHASE_MESSAGE_OUT) begin
|
||||||
if(message_sent) phase <= `PHASE_IDLE;
|
if(message_sent) phase <= PHASE_IDLE;
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
phase <= `PHASE_IDLE; // should never happen
|
phase <= PHASE_IDLE; // should never happen
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module scsi_dpram #(parameter DATAWIDTH=8, ADDRWIDTH=9)
|
||||||
|
(
|
||||||
|
input clock,
|
||||||
|
|
||||||
|
input [ADDRWIDTH-1:0] address_a,
|
||||||
|
input [DATAWIDTH-1:0] data_a,
|
||||||
|
input wren_a,
|
||||||
|
output reg [DATAWIDTH-1:0] q_a,
|
||||||
|
|
||||||
|
input [ADDRWIDTH-1:0] address_b,
|
||||||
|
input [DATAWIDTH-1:0] data_b,
|
||||||
|
input wren_b,
|
||||||
|
output reg [DATAWIDTH-1:0] q_b
|
||||||
|
);
|
||||||
|
|
||||||
|
reg [DATAWIDTH-1:0] ram[0:(1<<ADDRWIDTH)-1];
|
||||||
|
|
||||||
|
always @(posedge clock) begin
|
||||||
|
if(wren_a) begin
|
||||||
|
ram[address_a] <= data_a;
|
||||||
|
q_a <= data_a;
|
||||||
|
end else begin
|
||||||
|
q_a <= ram[address_a];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clock) begin
|
||||||
|
if(wren_b) begin
|
||||||
|
ram[address_b] <= data_b;
|
||||||
|
q_b <= data_b;
|
||||||
|
end else begin
|
||||||
|
q_b <= ram[address_b];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
Loading…
Reference in New Issue
Block a user