pi_ioc.v
6.78 KB
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
// pi_ioc.v v1 Frank Berndt
// pi io bus controller;
// :set tabstop=4
module pi_ioc (
sysclk, reset,
io_in, io_ena, io_out, io_oe, io_ale,
io_ior, io_iow, io_cs, io_dmarq, io_dmack, io_intr,
flc_breq, flc_bgnt, flc_bre, flc_brd, flc_out,
but_req, but_val,
ide_conf, ide_stall,
ide_acc, ide_req, ide_addr, ide_write, ide_rack, ide_do, ide_di,
ide_intr
);
// module io ports;
input sysclk; // system clock;
input reset; // controller and system reset;
// generic ide bus interface;
input [15:0] io_in; // io bus input data;
output io_ena; // io input register clock enable;
output [15:0] io_out; // io bus output data;
output [1:0] io_oe; // io bus output enables;
output io_ale; // io address latch enable;
output io_ior; // io read pulse;
output io_iow; // io write pulse;
output [3:0] io_cs; // io pio chip selects;
input io_dmarq; // io dma request;
output io_dmack; // io dma acknowledge;
input io_intr; // io device interrupt;
// flash controller interface;
input flc_breq; // flash bus request;
output flc_bgnt; // flash bus grant;
input flc_bre; // flash bus read enable;
input flc_brd; // flash bus read;
input [15:0] flc_out; // flash output data;
// si button interface;
input but_req; // request button sample;
output but_val; // button sample valid;
// io controller interface;
input [30:0] ide_conf; // ide timing config;
output ide_stall; // ide pio in progress;
input ide_acc; // ide access granted;
input ide_req; // ide pio request;
input [18:1] ide_addr; // ide bus address;
input ide_write; // ide pio write;
output ide_rack; // ide read acknowledge;
input [31:0] ide_do; // ide pio write data;
output [15:0] ide_di; // ide pio read data;
output ide_intr; // ide interrupt;
// ide bus arbiter interface;
reg ide_breq; // ide bus request;
wire ide_bgnt; // ide bus grant;
reg ide_bre; // ide bus read enable;
reg ide_brd; // ide bus read;
wire [15:0] ide_out; // ide output data;
// io bus arbiter;
// fixed priority arbitration;
// requestor keeps request active for duration of bus cycle;
// requestor is responsible for bus cycle timing;
// 000=idle, 001=flash, 010=button port, 100=ide;
reg but_breq; // pending button request;
reg [2:0] io_arb; // arbitration winner;
wire io_arb_dis; // disable io arbiter;
wire io_arb_en; // enable io arbiter;
always @(posedge sysclk)
begin
if(reset)
io_arb <= 3'd0;
else if(io_arb_en) begin
io_arb[0] <= flc_breq;
io_arb[1] <= ~flc_breq & but_breq;
io_arb[2] <= ~flc_breq & ~but_breq & ide_breq;
end
end
assign io_arb_dis = |(io_arb & { ide_breq, but_breq, flc_breq });
assign io_arb_en = ~io_arb_dis;
assign flc_bgnt = io_arb[0];
assign ide_bgnt = io_arb[2];
// button sampling;
// request from si is single pulse;
// arbitrate io bus and return valid to si;
// give io hardware two clocks to put data on io bus;
reg [1:0] but_pipe; // button cycle pipe;
wire but_cs; // chip select for butteon read;
wire but_bre; // button io read enable;
always @(posedge sysclk)
begin
but_breq <= ~reset & ~but_pipe[1] & (but_breq | but_req);
but_pipe <= { but_pipe[0], io_arb[1] };
end
assign but_cs = but_pipe[0] & but_breq;
assign but_bre = but_pipe[1] & io_arb[1];
assign but_val = but_pipe[0] & ~io_arb[1];
// io bus output enable control;
// drive out 0 when idle, turn around for reads;
// this saves board pull resistors;
// button sampler always reads;
// disable outputs during pin reset to sample id;
wire [1:0] io_rdis; // byte lane read diables;
assign io_rdis[1] = reset | io_arb[1] | ide_brd | (io_arb[0] & flc_brd);
assign io_rdis[0] = reset | io_arb[1] | ide_brd;
// io bus write data mux;
// flash and ide are the only units that write;
// direct output to registers in pad layer;
assign io_out = ({16{io_arb[0]}} & flc_out) | ({16{io_arb[2]}} & ide_out);
assign io_oe = ~io_rdis;
assign io_ena = reset | (io_arb[0] & flc_bre) | but_bre | ide_bre;
// ide bus controller;
// request io bus for ide pio;
// must keep request active for duration of cycle;
// must latch io address and write flag;
// ignore requests when cycle controller is still busy;
wire ide_val; // allowed ide request;
wire ide_bclr; // done with ide bus cycle;
wire ide_tend; // pio cycle end time;
reg [18:1] ide_baddr; // ide bus address;
reg ide_bwr; // ide bus write;
reg [15:0] ide_wdata; // ide write data;
assign ide_val = ide_req & ide_acc & ~ide_breq;
assign ide_bclr = reset | ide_tend;
assign ide_stall = ide_breq;
always @(posedge sysclk)
begin
ide_breq <= ~ide_bclr & (ide_breq | ide_val);
if(ide_val) begin
ide_baddr <= ide_addr;
ide_bwr <= ide_write;
end
if(ide_val & ide_write)
ide_wdata <= ide_addr[1]? ide_do[15:0] : ide_do[31:16];
end
// ide bus cycle control;
// cycle is started after io bus arbiter granted bus to ide;
// ide_sm increments, state is triggered from decodes;
reg [5:0] ide_sm; // state machine;
wire ide_trwa; // ior/iow assertion time;
wire ide_trwd; // ior/iow deassertion time;
reg ide_iow; // io write pulse;
reg ide_ior; // io read pulse;
reg [1:0] ide_gp; // ide grant pipe;
always @(posedge sysclk)
begin
ide_sm <= {6{ide_bgnt}} & (ide_sm + 1);
ide_iow <= ide_bgnt & ide_bwr & ~ide_trwd & (ide_iow | ide_trwa);
ide_ior <= ide_bgnt & ~ide_bwr & ~ide_trwd & (ide_ior | ide_trwa);
ide_gp <= { ide_bgnt & ide_gp[0], ide_bgnt };
end
assign ide_trwa = (ide_sm == { 1'b0, ide_conf[4:0] });
assign ide_trwd = (ide_sm == { 1'b0, ide_conf[9:5] });
assign ide_tend = (ide_sm == ide_conf[15:10]);
assign io_ale = ide_bgnt & (ide_sm == 6'd0);
assign io_iow = ide_iow;
assign io_ior = ide_ior;
assign io_cs[0] = (ide_bgnt & (ide_baddr[18:17] == 2'd0));
assign io_cs[1] = (ide_bgnt & (ide_baddr[18:17] == 2'd1));
assign io_cs[2] = (ide_bgnt & (ide_baddr[18:17] == 2'd2)) | but_cs;
assign io_cs[3] = (ide_bgnt & (ide_baddr[18:17] == 2'd3));
// ide write data mux;
// select address or write data;
assign ide_out = ide_gp[1]? ide_wdata : ide_baddr[16:1];
// turn bus around for ide reads;
// sample read data at ior deassertion time;
// must store ide read data due to cbus read request latency;
wire ide_rden; // read data enable;
assign ide_rden = ide_gp[1] & ~ide_bwr & ide_trwd;
assign ide_di = io_in;
always @(posedge sysclk)
begin
ide_brd <= ide_bgnt & ide_gp[0] & ~ide_bwr;
ide_bre <= ide_rden;
end
// ack ide reads;
// when access is disabled, then ack immediatedly;
// when busy and read request, then ack immediatedly;
// else, ack as soon as read data is available;
reg ide_rack; // ide read ack;
always @(posedge sysclk)
begin
ide_rack <= (~ide_acc & ide_req & ~ide_write)
| (ide_req & ide_breq & ~ide_write)
| ide_rden;
end
// ide interrupt handling;
assign ide_intr = io_intr;
// XXX
assign io_dmack = 0;
endmodule