2 // Copyright (C) 2008 Tomasz Malesinski <tmal@mimuw.edu.pl>
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.
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
,
22 input freq_ld
, start
, cnt_en
;
28 wire freq_ld
, start
, cnt_en
;
33 assign borrow
= (out
== 0);
35 always @ (posedge clk_i
)
41 always @ (posedge clk_i
)
47 module pokey_basefreq(rst
, clk_i
, base15
, out
);
48 input rst
, clk_i
, base15
;
51 wire rst
, clk_i
, base15
;
52 wire out
= (div57
== 0) && (!base15 || div4
== 0);
57 always @ (posedge clk_i
)
61 end else if (div57
== 56) begin
68 module pokey_poly4(rst
, clk_i
, out
);
77 always @ (posedge clk_i
)
79 shift
<= {shift
[2:0], 1'b0};
81 shift
<= {shift
[2:0], shift
[3] ~^ shift
[2]};
84 module pokey_poly5(rst
, clk_i
, out
);
93 always @ (posedge clk_i
)
95 shift
<= {shift
[3:0], 1'b0};
97 shift
<= {shift
[3:0], shift
[4] ~^ shift
[2]};
100 module pokey_poly17(rst
, clk_i
, short
, out
, random
);
101 input rst
, clk_i
, short
;
105 wire out
= shift
[16];
106 wire [7:0] random
= shift
[16:9];
109 wire new_bit
= shift
[16] ~^ shift
[11];
112 // last_short is used to reset the shortened shift register when
113 // shwitching from long to short.
114 always @ (posedge clk_i
)
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
};
123 module pokey_audout(rst
, clk_i
, dat_i
,
125 poly4
, poly5
, poly17
,
126 in
, filter_en
, filter_in
,
128 input rst
, clk_i
, dat_i
;
130 input poly4
, poly5
, poly17
;
131 input in
, filter_en
, filter_in
;
138 wire poly4
, poly5
, poly17
;
139 wire in
, filter_en
, filter_in
;
141 wire [3:0] out
= (ch_out | vol_only
) ? vol
: 0;
151 wire change
= in
& (no_poly5 | poly5
);
152 wire ch_out
= filter_en ? filter_reg ^ nf
: nf
;
154 always @ (posedge clk_i
)
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
)
174 always @ (posedge clk_i
)
175 if (!filter_en || rst
)
181 module pokey(rst_i
, clk_i
,
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
);
199 input key_code
, key_pressed
, key_shift
, key_break
;
200 input serout_ack_i
, serin
, serin_rdy_i
;
206 output serout
, serout_rdy_o
, serin_ack_o
;
214 wire key_pressed
, key_shift
, key_break
;
215 reg last_key_pressed
, last_key_break
;
220 wire [5:0] audout
= audout0
+ audout1
+ audout2
+ audout3
;
224 reg last_serin_rdy_i
;
229 reg last_serout_ack_i
;
231 wire rst
= (rst_bits
== 0);
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;
268 wire poly4
, poly5
, poly17
;
269 reg [3:1] poly4_shift
, poly5_shift
, poly17_shift
;
272 wire [3:0] audout0
, audout1
, audout2
, audout3
;
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
)
285 else if (adr_i
== 'ha
)
288 else if (adr_i
== 'hd
)
291 else if (adr_i
== 'he
)
293 dat_o
= ~(irqst
& irqen
);
294 else if (adr_i
== 'hf
)
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
302 1'b1, // serial input shift register busy
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
319 fast_ch0
<= dat_i
[6];
320 fast_ch2
<= dat_i
[5];
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
;
338 else if (stb_i
&& !we_i
&& adr_i
== 'hd
&& serin_rdy_i
)
340 else if (!serin_rdy_i
)
345 always @ (posedge clk_i
) begin
346 last_serout_ack_i
<= serout_ack_i
;
349 else if (we_i
&& stb_i
&& adr_i
== 'hd
) begin
352 end else if (serout_ack_i
)
357 always @ (posedge clk_i
)
358 if (we_i
&& stb_i
&& adr_i
== 'he
)
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
,
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
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
,
428 poly4
, poly5
, poly17
,
429 borrow
[0], fi02
, borrow
[2],
431 pokey_audout
u_audout1(start_timer
, clk_i
, dat_i
,
433 poly4_shift
[1], poly5_shift
[1], poly17_shift
[1],
434 borrow
[1], fi13
, borrow
[3],
436 pokey_audout
u_audout2(start_timer
, clk_i
, dat_i
,
438 poly4_shift
[2], poly5_shift
[2], poly17_shift
[2],
441 pokey_audout
u_audout3(start_timer
, clk_i
, dat_i
,
443 poly4_shift
[3], poly5_shift
[3], poly17_shift
[3],