// Glue logic for the MP3 decoder // Stephen Early // XXX XXX XXX // WARNING: This has never been tested // It probably contains typos and thinkos // XXX XXX XXX // XXX I'm in the middle of adding an interrupt for switch state changes // at the moment - it's not there yet. // Memory map for hardware: // we decode for A19=1 and A16=0, using /CE3 as an enable signal // so all our addresses are 0x38xxxx // External devices - we just decode // X00X 0X01 FIFO data write // X00X 0X10 LCD1 control / busy // X00X 1X10 LCD1 data // X00X 0X11 LCD2 control / busy // X00X 1X11 LCD2 data // X01X yyyy External serial ports // Internal devices - we latch // X10X XX00 LEDs out 1 // X10X XX01 LEDs out 2 // X10X XX10 Switches in 1 // X10X XX11 Switches in 2 // X11X XX00 FPGA control 1 // X11X XX01 FPGA control 2 // X11X XX10 FPGA status 1 // X11X XX11 FPGA status 2 // Control register bits: // 0: reset fifo-to-serial circuit // 1: FIFO reset // 2: MP3 decoder reset // 3: // 4: interrupt enable 0 // 5: interrupt enable 1 // 6: interrupt enable 2 // 7: interrupt enable 3 // Top-level module defining the chip module mp3glue(clk, a19, a16, a6, a5, a3, a1, a0, databus, extint, ce3, xpsen, xwr, bustransgate, bustransdir, lcde1, lcde2, lcdreg, serial_sel, serial_int1, serial_int2, fifo_data, fifo_ef, fifo_hf, fifo_ff, fifo_rd, fifo_wr, fifo_reset, mp3_sdi, mp3_sck, mp3_bit_en, mp3_data_req, mp3_reset, switch, leds ); input clk; // A 1MHz clock // Processor interface input a19, a16, a6, a5, a3, a1, a0; input ce3; inout [7:0] databus; output extint, bustransgate, bustransdir; input xpsen, xwr; // FIFO interface input fifo_ef, fifo_hf, fifo_ff; input [7:0] fifo_data; output fifo_rd, fifo_wr, fifo_reset; // MP3 decoder interface output mp3_sdi, mp3_sck, mp3_bit_en, mp3_reset; input mp3_data_req; // LCD interfaces // inout [7:0] lcddata; let's use an external bus transceiver output lcde1, lcde2, lcdreg; // Serial port interface output serial_sel; input serial_int1, serial_int2; // Random bits of hardware input [7:0] switch; output [7:0] leds; // Convenient alias wire rd = !xpsen; wire wr = !xwr; // Address decoding wire fifoen; wire [1:0] lcden; wire [1:0] leden; wire [1:0] switchen; wire [1:0] controlen; wire [1:0] statusen; wire serialen; // Internal registers wire [7:0] config; wire [7:0] status; // Interrupt handling wire [3:0] interrupt; wire switch_change; // -------------------------------------------------------------------------- // Interrupt processing intproc interrupt_processor(extint, interrupt, config[7:4]); assign interrupt[0] = !fifo_hf; assign interrupt[1] = !serial_int1; assign interrupt[2] = !serial_int2; assign interrupt[3] = switch_change; // Address decoding addrdec decode(a19, a16, a6, a5, a3, a1, a0, ce3, fifoen, lcden, leden, switchen, controlen, statusen, serialen); // FIFO and MP3 control assign fifo_wr = !(fifoen && wr); fifo_to_serial serialise(fifo_data, fifo_rd, fifo_ef, mp3_sdi, mp3_sck, mp3_bit_en, mp3_data_req, status[0], clk, config[0]); assign fifo_reset=config[1]; assign mp3_reset=config[2]; assign status[1]=fifo_ef; assign status[2]=fifo_hf; assign status[3]=fifo_ff; // Serial expansion interface // serial interrupt processing dealt with above assign serial_sel = !serialen; // the LCD interface lcdif lcds(a3, rd, wr, lcden, lcde1, lcde2, bustransdir, lcdreg, bustransgate); // Status reading tris8 status0(databus, status, statusen[0] & rd); // remember to assign unused status bits assign status[7:4]=status[3:0]; // Switches state reading switchproc switch0(databus, switch, switchen[0] & rd, clk, switch_change); // LEDs register led0(databus, leds, leden[0] & wr); tris8 led0_rb(databus, leds, leden[0] & rd); // Config register config0(databus, config, controlen[0] & wr); tris8 config0_rb(databus, config, controlen[0] & rd); endmodule // Address decoding. Produces active-HIGH enable signals; use along with // rd or wr (which are active low) module addrdec(a19, a16, a6, a5, a3, a1, a0, ce3, fifoen, lcden, leden, switchen, controlen, statusen, serialen); input a19, a16, a6, a5, a3, a1, a0, ce3; output fifoen; output [1:0] lcden; output [1:0] leden; output [1:0] switchen; output [1:0] controlen; output [1:0] statusen; output serialen; wire sel, extsel, intsel; assign sel=!ce3 && a19 && !a16; assign extsel=sel && !a6 && !a5; // for LCDs and FIFO assign intsel=sel && a6; // internal registers assign fifoen = extsel && !a3 && !a1 && a0; assign lcden[0] = extsel && a1 && !a0; assign lcden[1] = extsel && a1 && a0; assign serialen = sel && !a6 && a5; assign leden[0] = intsel && !a5 && !a1 && !a0; assign leden[1] = intsel && !a5 && !a1 && a0; assign switchen[0] = intsel && !a5 && a1 && !a0; assign switchen[1] = intsel && !a5 && a1 && a0; assign controlen[0] = intsel && a5 && !a1 && !a0; assign controlen[1] = intsel && a5 && !a1 && a0; assign statusen[0] = intsel && a5 && a1 && !a0; assign statusen[1] = intsel && a5 && a1 && a0; endmodule module switchproc(databus, switch, enable, sclk, change); inout [7:0] databus; input [7:0] switch; input enable; input sclk; output change; wire [7:0] dswitch; debounce sw0(switch[0], dswitch[0], sclk); debounce sw1(switch[1], dswitch[1], sclk); debounce sw2(switch[2], dswitch[2], sclk); debounce sw3(switch[3], dswitch[3], sclk); debounce sw4(switch[4], dswitch[4], sclk); debounce sw5(switch[5], dswitch[5], sclk); debounce sw6(switch[6], dswitch[6], sclk); debounce sw7(switch[7], dswitch[7], sclk); tris8 switch0(databus, dswitch, enable); assign change=0; // XXX not implemented endmodule // Interrupt processor. Sources are active-high level sensitive. // Mask is set high to enable. module intproc(extint, source, mask); output extint; input [3:0] source; input [3:0] mask; assign extint = |(source & mask); endmodule module register(databus, contents, write); input [7:0] databus; output [7:0] contents; input write; reg [7:0] contents; always @(posedge write) contents <= databus; endmodule module debounce(switch, out, clk); input switch, clk; output out; reg [5:0] samples; reg out, oldout; always @(posedge clk) begin samples <= { samples[4:0],switch }; if (samples[5:2] == 6'b1111) out <= 1; if (samples[5:2] == 6'b0000) out <= 0; end endmodule module lcdif(a3, rd, wr, lcden, lcde1, lcde2, lcdrw, lcdreg, lcdtransgate); input a3, rd, wr; input [1:0] lcden; output lcde1, lcde2, lcdrw, lcdreg, lcdtransgate; assign lcdrw = !wr; assign lcdreg = a3; assign lcde1 = lcden[0] & (rd || wr); assign lcde2 = lcden[1] & (rd || wr); assign lcdtransgate = !(lcde1 || lcde2); // bustrans8 lcdbus(databus,lcddata,lcdrw,(lcde1||lcde2)); endmodule