External Wishbone bus and serial input/output registers
[AtosmChip.git] / pokey.v
blobe7e3d33ed7b1cd3cf47d2ff5d1048547646f0012
1 // Atosm Chip
2 // Copyright (C) 2008 Tomasz Malesinski <tmal@mimuw.edu.pl>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 module pokey_counter(clk_i, dat_i,
19 freq_ld, start, cnt_en,
20 out, borrow);
21 input clk_i, dat_i;
22 input freq_ld, start, cnt_en;
24 output out, borrow;
26 wire clk_i;
27 wire [7:0] dat_i;
28 wire freq_ld, start, cnt_en;
30 reg [7:0] freq, out;
31 wire borrow;
33 assign borrow = (out == 0);
35 always @ (posedge clk_i)
36 if (start)
37 out <= freq;
38 else if (cnt_en)
39 out <= out - 1;
41 always @ (posedge clk_i)
42 if (freq_ld)
43 freq <= dat_i;
45 endmodule
47 module pokey_basefreq(rst, clk_i, base15, out);
48 input rst, clk_i, base15;
49 output out;
51 wire rst, clk_i, base15;
52 wire out = (div57 == 0) && (!base15 || div4 == 0);
54 reg [5:0] div57;
55 reg [1:0] div4;
57 always @ (posedge clk_i)
58 if (rst) begin
59 div57 <= 0;
60 div4 <= 0;
61 end else if (div57 == 56) begin
62 div57 <= 0;
63 div4 <= div4 + 1;
64 end else
65 div57 <= div57 + 1;
66 endmodule
68 module pokey_poly4(rst, clk_i, out);
69 input rst, clk_i;
70 output out;
72 wire rst, clk_i;
73 wire out = shift[3];
75 reg [3:0] shift;
77 always @ (posedge clk_i)
78 if (rst)
79 shift <= {shift[2:0], 1'b0};
80 else
81 shift <= {shift[2:0], shift[3] ~^ shift[2]};
82 endmodule
84 module pokey_poly5(rst, clk_i, out);
85 input rst, clk_i;
86 output out;
88 wire rst, clk_i;
89 wire out = shift[4];
91 reg [4:0] shift;
93 always @ (posedge clk_i)
94 if (rst)
95 shift <= {shift[3:0], 1'b0};
96 else
97 shift <= {shift[3:0], shift[4] ~^ shift[2]};
98 endmodule
100 module pokey_poly17(rst, clk_i, short, out, random);
101 input rst, clk_i, short;
102 output out, random;
104 wire rst, clk_i;
105 wire out = shift[16];
106 wire [7:0] random = shift[16:9];
108 reg [16:0] shift;
109 wire new_bit = shift[16] ~^ shift[11];
110 reg last_short;
112 // last_short is used to reset the shortened shift register when
113 // shwitching from long to short.
114 always @ (posedge clk_i)
115 last_short <= short;
117 always @ (posedge clk_i)
118 shift <= {shift[15:8],
119 (short ? new_bit : shift[7]) & ~rst & (last_short | ~short),
120 shift[6:0], new_bit};
121 endmodule
123 module pokey_audout(rst, clk_i, dat_i,
124 audc_we,
125 poly4, poly5, poly17,
126 in, filter_en, filter_in,
127 out);
128 input rst, clk_i, dat_i;
129 input audc_we;
130 input poly4, poly5, poly17;
131 input in, filter_en, filter_in;
133 output out;
135 wire rst, clk_i;
136 wire [7:0] dat_i;
137 wire audc_we;
138 wire poly4, poly5, poly17;
139 wire in, filter_en, filter_in;
141 wire [3:0] out = (ch_out | vol_only) ? vol : 0;
143 reg [3:0] vol;
144 reg vol_only;
145 reg no_poly5;
146 reg poly4_sel;
147 reg no_poly17_4;
149 reg nf, filter_reg;
151 wire change = in & (no_poly5 | poly5);
152 wire ch_out = filter_en ? filter_reg ^ nf : nf;
154 always @ (posedge clk_i)
155 if (audc_we) begin
156 vol <= dat_i[3:0];
157 vol_only <= dat_i[4];
158 no_poly5 <= dat_i[7];
159 poly4_sel <= dat_i[6];
160 no_poly17_4 <= dat_i[5];
163 always @ (posedge clk_i)
164 if (rst)
165 nf <= 0;
166 else if (change)
167 if (no_poly17_4)
168 nf <= ~nf;
169 else if (poly4_sel)
170 nf <= poly4;
171 else
172 nf <= poly17;
174 always @ (posedge clk_i)
175 if (!filter_en || rst)
176 filter_reg <= 0;
177 else if (filter_in)
178 filter_reg <= nf;
179 endmodule
181 module pokey(rst_i, clk_i,
182 adr_i,
183 dat_i,
184 dat_o,
185 we_i,
186 stb_i,
187 ack_o,
188 irq,
189 audout,
190 key_code, key_pressed, key_shift, key_break,
191 serout, serout_rdy_o, serout_ack_i,
192 serin, serin_rdy_i, serin_ack_o);
193 input rst_i;
194 input clk_i;
195 input adr_i;
196 input dat_i;
197 input we_i;
198 input stb_i;
199 input key_code, key_pressed, key_shift, key_break;
200 input serout_ack_i, serin, serin_rdy_i;
202 output dat_o;
203 output ack_o;
204 output irq;
205 output audout;
206 output serout, serout_rdy_o, serin_ack_o;
208 wire rst_i, clk_i;
209 wire [3:0] adr_i;
210 wire [7:0] dat_i;
211 wire we_i;
212 wire stb_i;
213 wire [7:0] key_code;
214 wire key_pressed, key_shift, key_break;
215 reg last_key_pressed, last_key_break;
217 wire ack_o;
218 reg [7:0] dat_o;
220 wire [5:0] audout = audout0 + audout1 + audout2 + audout3;
222 wire [7:0] serin;
223 wire serin_rdy_i;
224 reg last_serin_rdy_i;
225 reg serin_ack_o;
226 reg [7:0] serout;
227 reg serout_rdy_o;
228 wire serout_ack_i;
229 reg last_serout_ack_i;
231 wire rst = (rst_bits == 0);
232 wire start_timer;
234 reg irq;
236 parameter [2:0] IRQ_BREAK = 7;
237 parameter [2:0] IRQ_KEY = 6;
238 parameter [2:0] IRQ_SERIN = 5;
239 parameter [2:0] IRQ_SEROUT = 4;
240 parameter [2:0] IRQ_SERFIN = 3;
241 parameter [2:0] IRQ_TIMER4 = 2;
242 parameter [2:0] IRQ_TIMER2 = 1;
243 parameter [2:0] IRQ_TIMER1 = 1;
245 reg [7:0] irqen;
246 reg [7:0] irqst;
248 // SKCTL bits.
249 reg [1:0] rst_bits;
251 // AUDCTL bits.
252 reg poly9;
253 reg fast_ch0;
254 reg fast_ch2;
255 reg ch01;
256 reg ch23;
257 reg fi02;
258 reg fi13;
259 reg base15;
261 reg [3:0] audf_we;
262 reg [3:0] audc_we;
263 wire [3:0] start;
264 wire [3:0] cnt_en;
265 wire [31:0] ctr_out;
266 wire [3:0] borrow;
268 wire poly4, poly5, poly17;
269 reg [3:1] poly4_shift, poly5_shift, poly17_shift;
270 wire base;
272 wire [3:0] audout0, audout1, audout2, audout3;
274 integer i, irq_i;
276 wire [7:0] random;
278 assign ack_o = stb_i;
280 always @ (adr_i or key_code or random or serin or irqst or irqen or
281 key_shift or key_pressed)
282 if (adr_i == 'h9)
283 // KBCODE
284 dat_o = key_code;
285 else if (adr_i == 'ha)
286 // RANDOM
287 dat_o = random;
288 else if (adr_i == 'hd)
289 // SERIN
290 dat_o = serin;
291 else if (adr_i == 'he)
292 // IRQST
293 dat_o = ~(irqst & irqen);
294 else if (adr_i == 'hf)
295 // SKSTAT
296 dat_o = {1'b1, // no framing error
297 1'b1, // no keyboard overrun
298 1'b1, // no serial data input over-run
299 1'b1, // serial input pad
300 ~key_shift,
301 ~key_pressed,
302 1'b1, // serial input shift register busy
303 1'b1}; // not used
304 else
305 dat_o = 'hff;
307 always @ (we_i or stb_i or adr_i) begin
308 for (i = 0; i < 4; i = i + 1)
309 audf_we[i] = (adr_i == (i << 1));
310 for (i = 0; i < 4; i = i + 1)
311 audc_we[i] = (adr_i == ((i << 1) + 1));
314 assign start_timer = (we_i && stb_i && adr_i == 9);
316 always @ (posedge clk_i)
317 if (we_i && stb_i && adr_i == 8) begin
318 poly9 <= dat_i[7];
319 fast_ch0 <= dat_i[6];
320 fast_ch2 <= dat_i[5];
321 ch01 <= dat_i[4];
322 ch23 <= dat_i[3];
323 fi02 <= dat_i[2];
324 fi13 <= dat_i[1];
325 base15 <= dat_i[0];
328 // SKRES
329 always @ (posedge clk_i)
330 if (we_i && stb_i && adr_i == 'ha) begin
331 // TODO: reset SKSTAT[7:5] if they are implemented
334 always @ (posedge clk_i) begin
335 last_serin_rdy_i <= serin_rdy_i;
336 if (rst)
337 serin_ack_o <= 0;
338 else if (stb_i && !we_i && adr_i == 'hd && serin_rdy_i)
339 serin_ack_o <= 1;
340 else if (!serin_rdy_i)
341 serin_ack_o <= 0;
344 // SEROUT
345 always @ (posedge clk_i) begin
346 last_serout_ack_i <= serout_ack_i;
347 if (rst)
348 serout_rdy_o <= 0;
349 else if (we_i && stb_i && adr_i == 'hd) begin
350 serout <= dat_i;
351 serout_rdy_o <= 1;
352 end else if (serout_ack_i)
353 serout_rdy_o <= 0;
356 // IRQEN
357 always @ (posedge clk_i)
358 if (we_i && stb_i && adr_i == 'he)
359 irqen <= dat_i;
361 always @ (posedge clk_i)
362 if (we_i && stb_i && adr_i == 'hf) begin
363 rst_bits <= dat_i[1:0];
364 // TODO: rest of the bits.
367 always @ (posedge clk_i) begin
368 last_key_pressed <= key_pressed;
369 last_key_break <= key_break;
372 always @ (posedge clk_i)
373 // IRQ_SERFIN has no latch.
374 irqst <= irqen & ({irqst[7:4],
375 !serout_ack_i && !serout_rdy_o,
376 irqst[2:0]} |
377 {key_break && !last_key_break,
378 key_pressed && !last_key_pressed,
379 serin_rdy_i && !last_serin_rdy_i,
380 serout_ack_i && !last_serout_ack_i,
381 1'b0, borrow[3], borrow[1:0]});
383 always @ (irqst) begin
384 irq = 0;
385 for (i = 0; i < 8; i = i + 1)
386 irq = irq || irqst[i];
389 pokey_basefreq u_base(rst, clk_i, base15, base);
391 pokey_poly4 u_poly4(rst, clk_i, poly4);
392 pokey_poly5 u_poly5(rst, clk_i, poly5);
393 pokey_poly17 u_poly17(rst, clk_i, poly9, poly17, random);
395 always @ (posedge clk_i) begin
396 poly4_shift <= {poly4_shift[2:1], poly4};
397 poly5_shift <= {poly5_shift[2:1], poly5};
398 poly17_shift <= {poly17_shift[2:1], poly17};
401 assign cnt_en[0] = fast_ch0 ? 1 : base;
402 assign cnt_en[1] = ch01 ? borrow[0] : base;
403 assign cnt_en[2] = fast_ch2 ? 1 : base;
404 assign cnt_en[3] = ch23 ? borrow[2] : base;
406 assign start[0] = start_timer | (ch01 ? borrow[1] : borrow[0]);
407 assign start[1] = start_timer | borrow[1];
408 assign start[2] = start_timer | (ch23 ? borrow[3] : borrow[2]);
409 assign start[3] = start_timer | borrow[3];
411 // TODO: clean it up after removing the array of instances
412 // (remove assignments above)
413 // TODO: do we need ctr_out?
414 pokey_counter u_ctr0(clk_i, dat_i,
415 audf_we[0], start[0], cnt_en[0],
416 ctr_out[7:0], borrow[0]);
417 pokey_counter u_ctr1(clk_i, dat_i,
418 audf_we[1], start[1], cnt_en[1],
419 ctr_out[15:8], borrow[1]);
420 pokey_counter u_ctr2(clk_i, dat_i,
421 audf_we[2], start[2], cnt_en[2],
422 ctr_out[23:16], borrow[2]);
423 pokey_counter u_ctr3(clk_i, dat_i,
424 audf_we[3], start[3], cnt_en[3],
425 ctr_out[31:24], borrow[3]);
426 pokey_audout u_audout0(start_timer, clk_i, dat_i,
427 audc_we[0],
428 poly4, poly5, poly17,
429 borrow[0], fi02, borrow[2],
430 audout0);
431 pokey_audout u_audout1(start_timer, clk_i, dat_i,
432 audc_we[1],
433 poly4_shift[1], poly5_shift[1], poly17_shift[1],
434 borrow[1], fi13, borrow[3],
435 audout1);
436 pokey_audout u_audout2(start_timer, clk_i, dat_i,
437 audc_we[2],
438 poly4_shift[2], poly5_shift[2], poly17_shift[2],
439 borrow[2], 0, 0,
440 audout2);
441 pokey_audout u_audout3(start_timer, clk_i, dat_i,
442 audc_we[3],
443 poly4_shift[3], poly5_shift[3], poly17_shift[3],
444 borrow[3], 0, 0,
445 audout3);
446 endmodule