-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathncr5380.v
309 lines (261 loc) · 8.22 KB
/
ncr5380.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/* verilator lint_off UNUSED */
/* based on minimigmac by Benjamin Herrenschmidt */
/* Read registers */
`define RREG_CDR 3'h0 /* Current SCSI data */
`define RREG_ICR 3'h1 /* Initiator Command */
`define RREG_MR 3'h2 /* Mode register */
`define RREG_TCR 3'h3 /* Target Command */
`define RREG_CSR 3'h4 /* SCSI bus status */
`define RREG_BSR 3'h5 /* Bus and status */
`define RREG_IDR 3'h6 /* Input data */
`define RREG_RST 3'h7 /* Reset */
/* Write registers */
`define WREG_ODR 3'h0 /* Output data */
`define WREG_ICR 3'h1 /* Initiator Command */
`define WREG_MR 3'h2 /* Mode register */
`define WREG_TCR 3'h3 /* Target Command */
`define WREG_SER 3'h4 /* Select Enable */
`define WREG_DMAS 3'h5 /* Start DMA Send */
`define WREG_DMATR 3'h6 /* Start DMA Target receive */
`define WREG_IDMAR 3'h7 /* Start DMA Initiator receive */
/* MR bit numbers */
`define MR_DMA_MODE 1
`define MR_ARB 0
/* ICR bit numbers */
`define ICR_A_RST 7
`define ICR_TEST_MODE 6
`define ICR_DIFF_ENBL 5
`define ICR_A_ACK 4
`define ICR_A_BSY 3
`define ICR_A_SEL 2
`define ICR_A_ATN 1
`define ICR_A_DATA 0
/* TCR bit numbers */
`define TCR_A_REQ 3
`define TCR_A_MSG 2
`define TCR_A_CD 1
`define TCR_A_IO 0
module ncr5380
(
input clk,
input reset,
/* Bus interface. 3-bit address, to be wired
* appropriately upstream (to A4..A6) plus one
* more bit (A9) wired as dack.
*/
input bus_cs,
input [2:0] bus_rs,
input ior,
input iow,
input dack,
output dreq,
input [7:0] wdata,
output [7:0] rdata,
// connections to io controller
input [DEVS-1:0] img_mounted,
input [31:0] img_size,
output reg [31:0] io_lba,
output [DEVS-1:0] io_rd,
output [DEVS-1:0] io_wr,
input io_ack,
input [8:0] sd_buff_addr,
input [7:0] sd_buff_dout,
output reg [7:0] sd_buff_din,
input sd_buff_wr
);
parameter DEVS = 2;
assign dreq = scsi_req & dma_en;
reg [7:0] mr; /* Mode Register */
reg [7:0] icr; /* Initiator Command Register */
reg [3:0] tcr; /* Target Command Register */
wire [7:0] csr; /* SCSI bus status register */
/* Data in and out latches and associated
* control logic for DMA
*/
reg [7:0] din;
reg [7:0] dout;
reg dma_en;
/* --- Main host-side interface --- */
/* Register & DMA accesses decodes */
reg dma_wr;
reg reg_wr;
reg dma_ack;
wire i_dma_rd = bus_cs & dack & ior;
wire i_dma_wr = bus_cs & dack & iow;
wire i_reg_wr = bus_cs & ~dack & iow;
always @(posedge clk) begin
reg old_dma_rd, old_dma_wr, old_reg_wr;
old_dma_rd <= i_dma_rd;
old_dma_wr <= i_dma_wr;
old_reg_wr <= i_reg_wr;
dma_wr <= 0;
dma_ack <= 0;
reg_wr <= 0;
if(~old_dma_wr & i_dma_wr) dma_wr <= 1;
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
/* System bus reads */
assign rdata = dack ? cur_data :
bus_rs == `RREG_CDR ? cur_data :
bus_rs == `RREG_ICR ? icr_read :
bus_rs == `RREG_MR ? mr :
bus_rs == `RREG_TCR ? { 4'h0, tcr } :
bus_rs == `RREG_CSR ? csr :
bus_rs == `RREG_BSR ? bsr :
bus_rs == `RREG_IDR ? cur_data :
bus_rs == `RREG_RST ? 8'hff :
8'hff;
/* Data out latch (in DMA mode, this is one cycle after we've
* asserted ACK)
*/
always@(posedge clk) if((reg_wr && bus_rs == `WREG_ODR) || dma_wr) dout <= wdata;
/* Current data register. Simplified logic: We loop back the
* output data if we are asserting the bus, else we get the
* input latch
*/
wire [7:0] cur_data = out_en ? dout : din;
/* Logic for "asserting the bus" simplified */
wire out_en = icr[`ICR_A_DATA] | mr[`MR_ARB];
/* ICR read wires */
wire [7:0] icr_read = { icr[`ICR_A_RST],
icr_aip,
icr_la,
icr[`ICR_A_ACK],
icr[`ICR_A_BSY],
icr[`ICR_A_SEL],
icr[`ICR_A_ATN],
icr[`ICR_A_DATA] };
/* ICR write */
always@(posedge clk or posedge reset) begin
if (reset) begin
icr <= 0;
end else if (reg_wr && (bus_rs == `WREG_ICR)) begin
icr <= wdata;
end
end
/* MR write */
always@(posedge clk or posedge reset) begin
if (reset) mr <= 8'b0;
else if (reg_wr && (bus_rs == `WREG_MR)) mr <= wdata;
end
/* TCR write */
always@(posedge clk or posedge reset) begin
if (reset) tcr <= 4'b0;
else if (reg_wr && (bus_rs == `WREG_TCR)) tcr <= wdata[3:0];
end
/* DMA start send & receive registers. We currently ignore
* the direction.
*/
always@(posedge clk or posedge reset) begin
if (reset) begin
dma_en <= 0;
end else begin
if (!mr[`MR_DMA_MODE]) begin
dma_en <= 0;
end else if (reg_wr && (bus_rs == `WREG_DMAS)) begin
dma_en <= 1;
end else if (reg_wr && (bus_rs == `WREG_IDMAR)) begin
dma_en <= 1;
end
end
end
/* CSR (read only). We don't do parity */
assign csr = { scsi_rst, scsi_bsy, scsi_req, scsi_msg,
scsi_cd, scsi_io, scsi_sel, 1'b0 };
/* Bus and Status register */
/* BSR (read only). We don't do a few things... */
wire bsr_eodma = 1'b0; /* We don't do EOP */
wire bsr_dmarq = scsi_req & dma_en;
wire bsr_perr = 1'b0; /* We don't do parity */
wire bsr_irq = 1'b0; /* XXX ? Does MacOS use this ? */
wire bsr_pmatch =
tcr[`TCR_A_MSG] == scsi_msg &&
tcr[`TCR_A_CD ] == scsi_cd &&
tcr[`TCR_A_IO ] == scsi_io;
wire bsr_berr = 1'b0; /* XXX ? Does MacOS use this ? */
wire [7:0] bsr = { bsr_eodma, bsr_dmarq, bsr_perr, bsr_irq,
bsr_pmatch, bsr_berr, scsi_atn, scsi_ack };
/* --- Simulated SCSI Signals --- */
/* BSY logic (simplified arbitration, see notes) */
wire scsi_bsy =
icr[`ICR_A_BSY] |
|target_bsy |
//scsi2_bsy |
//scsi6_bsy |
mr[`MR_ARB];
/* Remains of simplified arbitration logic */
wire icr_aip = mr[`MR_ARB];
wire icr_la = 0;
/* Other ORed SCSI signals */
wire scsi_sel = icr[`ICR_A_SEL];
wire scsi_rst = icr[`ICR_A_RST];
wire scsi_ack = icr[`ICR_A_ACK] | dma_ack;
wire scsi_atn = icr[`ICR_A_ATN];
/* Mux target signals */
reg scsi_cd, scsi_io, scsi_msg, scsi_req;
always begin
integer i;
scsi_cd = 0;
scsi_io = 0;
scsi_msg = 0;
scsi_req = 0;
din = 8'h55;
io_lba = 0;
sd_buff_din = 0;
for (i = 0; i < DEVS; i = i + 1) begin
if (target_bsy[i]) begin
scsi_cd = target_cd[i];
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
// input signals from targets
wire [DEVS-1:0] target_bsy;
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 [7:0] target_buff_din[DEVS];
generate
genvar i;
for (i = 0; i < DEVS; i = i + 1) begin : target
localparam [2:0] ID = 3'd6-i;
// connect a target
scsi #(.ID(ID)) target
(
.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] ),
.din ( dout ),
// connection to io controller to read and write sectors
// to sd card
.img_mounted(img_mounted[i]),
.img_blocks(img_size),
.io_lba ( target_lba[i] ),
.io_rd ( io_rd[i] ),
.io_wr ( io_wr[i] ),
.io_ack ( io_ack & target_bsy[i] ),
.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