Load out_reg at the right time
[AtosmChip.git] / pokey.v
blob68c7360bbc247011397b03c6e7037362a68886aa
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 input rst_i;
192 input clk_i;
193 input adr_i;
194 input dat_i;
195 input we_i;
196 input stb_i;
197 input key_code, key_pressed, key_shift, key_break;
199 output dat_o;
200 output ack_o;
201 output irq;
202 output audout;
204 wire rst_i, clk_i;
205 wire [3:0] adr_i;
206 wire [7:0] dat_i;
207 wire we_i;
208 wire stb_i;
209 wire [7:0] key_code;
210 wire key_pressed, key_shift, key_break;
211 reg last_key_pressed, last_key_break;
213 wire ack_o;
214 reg [7:0] dat_o;
216 wire [5:0] audout = audout0 + audout1 + audout2 + audout3;
218 wire rst = (rst_bits == 0);
219 wire start_timer;
221 reg irq;
223 parameter [2:0] IRQ_BREAK = 7;
224 parameter [2:0] IRQ_KEY = 6;
225 parameter [2:0] IRQ_SERIN = 5;
226 parameter [2:0] IRQ_SEROUT = 4;
227 parameter [2:0] IRQ_SERFIN = 3;
228 parameter [2:0] IRQ_TIMER4 = 2;
229 parameter [2:0] IRQ_TIMER2 = 1;
230 parameter [2:0] IRQ_TIMER1 = 1;
232 reg [7:0] irqen;
233 reg [7:0] irqst;
235 // SKCTL bits.
236 reg [1:0] rst_bits;
238 // AUDCTL bits.
239 reg poly9;
240 reg fast_ch0;
241 reg fast_ch2;
242 reg ch01;
243 reg ch23;
244 reg fi02;
245 reg fi13;
246 reg base15;
248 reg [3:0] audf_we;
249 reg [3:0] audc_we;
250 wire [3:0] start;
251 wire [3:0] cnt_en;
252 wire [31:0] ctr_out;
253 wire [3:0] borrow;
255 wire poly4, poly5, poly17;
256 reg [3:1] poly4_shift, poly5_shift, poly17_shift;
257 wire base;
259 wire [3:0] audout0, audout1, audout2, audout3;
261 integer i, irq_i;
263 wire [7:0] random;
265 assign ack_o = stb_i;
267 always @ (adr_i or random)
268 if (adr_i == 'h9)
269 // KBCODE
270 dat_o = key_code;
271 else if (adr_i == 'ha)
272 // RANDOM
273 dat_o = random;
274 else if (adr_i == 'hd)
275 // TODO: SERIN
276 dat_o = 'hff;
277 else if (adr_i == 'he)
278 // IRQST
279 dat_o = ~(irqst & irqen);
280 else if (adr_i == 'hf)
281 // SKSTAT
282 dat_o = {1'b1, // no framing error
283 1'b1, // no keyboard overrun
284 1'b1, // no serial data input over-run
285 1'b1, // serial input pad
286 ~key_shift,
287 ~key_pressed,
288 1'b1, // serial input shift register busy
289 1'b1}; // not used
290 else
291 dat_o = 'hff;
293 always @ (we_i or stb_i or adr_i) begin
294 for (i = 0; i < 4; i = i + 1)
295 audf_we[i] = (adr_i == (i << 1));
296 for (i = 0; i < 4; i = i + 1)
297 audc_we[i] = (adr_i == ((i << 1) + 1));
300 assign start_timer = (we_i && stb_i && adr_i == 9);
302 always @ (posedge clk_i)
303 if (we_i && stb_i && adr_i == 8) begin
304 poly9 <= dat_i[7];
305 fast_ch0 <= dat_i[6];
306 fast_ch2 <= dat_i[5];
307 ch01 <= dat_i[4];
308 ch23 <= dat_i[3];
309 fi02 <= dat_i[2];
310 fi13 <= dat_i[1];
311 base15 <= dat_i[0];
314 // SKRES
315 always @ (posedge clk_i)
316 if (we_i && stb_i && adr_i == 'ha) begin
317 // TODO: reset SKSTAT[7:5] if they are implemented
320 // SEROUT
321 always @ (posedge clk_i)
322 if (we_i && stb_i && adr_i == 'hd) begin
323 // TODO: serial output
326 // IRQEN
327 always @ (posedge clk_i)
328 if (we_i && stb_i && adr_i == 'he)
329 irqen <= dat_i;
331 always @ (posedge clk_i)
332 if (we_i && stb_i && adr_i == 'hf) begin
333 rst_bits <= dat_i[1:0];
334 // TODO: rest of the bits.
337 always @ (posedge clk_i) begin
338 last_key_pressed <= key_pressed;
339 last_key_break <= key_break;
342 always @ (posedge clk_i)
343 // IRQ_SERFIN has no latch.
344 irqst <= irqen & ({irqst[7:4], 1'b0, irqst[2:0]} |
345 {key_break && !last_key_break,
346 key_pressed && !last_key_pressed,
347 3'b000, borrow[3], borrow[1:0]});
349 always @ (irqst) begin
350 irq = 0;
351 for (i = 0; i < 8; i = i + 1)
352 irq = irq || irqst[i];
355 pokey_basefreq u_base(rst, clk_i, base15, base);
357 pokey_poly4 u_poly4(rst, clk_i, poly4);
358 pokey_poly5 u_poly5(rst, clk_i, poly5);
359 pokey_poly17 u_poly17(rst, clk_i, poly9, poly17, random);
361 always @ (posedge clk_i) begin
362 poly4_shift <= {poly4_shift[2:1], poly4};
363 poly5_shift <= {poly5_shift[2:1], poly5};
364 poly17_shift <= {poly17_shift[2:1], poly17};
367 assign cnt_en[0] = fast_ch0 ? 1 : base;
368 assign cnt_en[1] = ch01 ? borrow[0] : base;
369 assign cnt_en[2] = fast_ch2 ? 1 : base;
370 assign cnt_en[3] = ch23 ? borrow[2] : base;
372 assign start[0] = start_timer | (ch01 ? borrow[1] : borrow[0]);
373 assign start[1] = start_timer | borrow[1];
374 assign start[2] = start_timer | (ch23 ? borrow[3] : borrow[2]);
375 assign start[3] = start_timer | borrow[3];
377 // TODO: clean it up after removing the array of instances
378 // (remove assignments above)
379 // TODO: do we need ctr_out?
380 pokey_counter u_ctr0(clk_i, dat_i,
381 audf_we[0], start[0], cnt_en[0],
382 ctr_out[7:0], borrow[0]);
383 pokey_counter u_ctr1(clk_i, dat_i,
384 audf_we[1], start[1], cnt_en[1],
385 ctr_out[15:8], borrow[1]);
386 pokey_counter u_ctr2(clk_i, dat_i,
387 audf_we[2], start[2], cnt_en[2],
388 ctr_out[23:16], borrow[2]);
389 pokey_counter u_ctr3(clk_i, dat_i,
390 audf_we[3], start[3], cnt_en[3],
391 ctr_out[31:24], borrow[3]);
392 pokey_audout u_audout0(start_timer, clk_i, dat_i,
393 audc_we[0],
394 poly4, poly5, poly17,
395 borrow[0], fi02, borrow[2],
396 audout0);
397 pokey_audout u_audout1(start_timer, clk_i, dat_i,
398 audc_we[1],
399 poly4_shift[1], poly5_shift[1], poly17_shift[1],
400 borrow[1], fi13, borrow[3],
401 audout1);
402 pokey_audout u_audout2(start_timer, clk_i, dat_i,
403 audc_we[2],
404 poly4_shift[2], poly5_shift[2], poly17_shift[2],
405 borrow[2], 0, 0,
406 audout2);
407 pokey_audout u_audout3(start_timer, clk_i, dat_i,
408 audc_we[3],
409 poly4_shift[3], poly5_shift[3], poly17_shift[3],
410 borrow[3], 0, 0,
411 audout3);
412 endmodule