//`default_nettype none // VERSION 1.1 /* The memory module (including memory-mapped I/O devices) */ module memory_with_devices(/*Memory interface*/ IMEM_ADDR, IMEM_OUT, DMEM_WE, DMEM_ADDR, DMEM_IN, DMEM_OUT, /* clocks for our various io devices */ sys_clk, proc_clk, pixel_clk, ps2_clk, exp_clk, GLOBAL_RST, GLOBAL_WE, /* debug signals */ debug_mode_select, debug_pc_out, debug_imem_out, debug_reg_data_in, debug_reg_we, debug_dmem_addr, debug_dmem_out, debug_dmem_in, debug_dmem_we, // Everything below is an I/O pin connection /*VGA ports*/ VGA_OUT_PIXEL_CLOCK, VGA_COMP_SYNCH, VGA_OUT_BLANK_Z, VGA_HSYNCH, VGA_VSYNCH, VGA_OUT_RED, VGA_OUT_GREEN, VGA_OUT_BLUE, /*Expansion board ports*/ SWIN, BTNIN, COUT, AOUT, LDOUT, /*PS2 port*/ PS2KEYBOARD_DATA, PS2KEYBOARD_CLK); //Memory interface: input [15:0] IMEM_ADDR; input [15:0] DMEM_ADDR; input DMEM_WE; input [15:0] DMEM_IN; output [15:0] IMEM_OUT; output [15:0] DMEM_OUT; //Clocks/Reset input sys_clk; // general system clock - used for most of memory input proc_clk; // processor clock input pixel_clk; // drives video display input ps2_clk; // drives PS/2 keyboard driver input exp_clk; // drives expansion board 7-segs input GLOBAL_RST; // global reset input GLOBAL_WE; // global we //VGA: output VGA_OUT_PIXEL_CLOCK; // pixel clock for the video DAC output VGA_COMP_SYNCH; // composite sync for the video DAC output VGA_OUT_BLANK_Z; // composite blanking for the video DAC output VGA_HSYNCH; // horizontal sync for the VGA output connector output VGA_VSYNCH; // vertical sync for the VGA output connector output [7:0] VGA_OUT_RED; // RED DAC data output [7:0] VGA_OUT_GREEN; // GREEN DAC data output [7:0] VGA_OUT_BLUE; // BLUE DAC data //Expansion board: input [7:0] SWIN; //switches input [4:0] BTNIN; //buttons output [6:0] COUT; //7-segment display cathodes output [3:0] AOUT; //7-segment display anodes output [7:0] LDOUT; //LEDs //PS/2 Keyboard: inout PS2KEYBOARD_DATA; inout PS2KEYBOARD_CLK; input [2:0] debug_mode_select; input debug_reg_we, debug_dmem_we; input [15:0] debug_pc_out, debug_imem_out, debug_reg_data_in; input [15:0] debug_dmem_addr, debug_dmem_out, debug_dmem_in; wire [15:0] idmem_d_out; wire [13:0] vga_addr; wire [15:0] vga_data; wire [15:0] dio4_read_data; wire [10:0] enabled; wire [15:0] device_d_out; wire [15:0] ps2_read_data; wire [15:0] timer_read_data; //The memory for bit-mapped video and other I/O. Port a is a read-only //port for the VGA video. Port b is a read-write port for memory-mapped //I/O data. The addresses used in the memory are only 14 bits because the //most-significant bits are always 11. Port b is accessed in the memory //stage of a pipeline; memory-mapped I/O is implemented by executing loads //and stores to I/O memory. bram bram_inst ( .addra(IMEM_ADDR), .addrb(DMEM_ADDR), .addrc({2'b11, vga_addr}), .clka(sys_clk), .clkc(pixel_clk), //VGA clock .dinb(DMEM_IN), .douta(IMEM_OUT), .doutb(idmem_d_out), .doutc(vga_data), //VGA data out .web(DMEM_WE & GLOBAL_WE)); //vga_controller handles the VGA signals. vga_controller vga_cntrl_inst( .PIXEL_CLK(~pixel_clk), .RESET(GLOBAL_RST), .VGA_OUT_PIXEL_CLOCK(VGA_OUT_PIXEL_CLOCK), .VGA_COMP_SYNCH(VGA_COMP_SYNCH), .VGA_OUT_BLANK_Z(VGA_OUT_BLANK_Z), .VGA_HSYNCH(VGA_HSYNCH), .VGA_VSYNCH(VGA_VSYNCH), .VGA_OUT_RED(VGA_OUT_RED), .VGA_OUT_GREEN(VGA_OUT_GREEN), .VGA_OUT_BLUE(VGA_OUT_BLUE), .VGA_ADDR(vga_addr), .VGA_DATA(vga_data[14:0])); //Select DMEM_OUT from idmem or from io, depending on most-significant //two bits if DMEM_ADDR. If DMEM_ADDR[15:14] is 11, then select device_d_out; //otherwise, use idmem_d_out. wire sel_d_out; and (sel_d_out, DMEM_ADDR[15], DMEM_ADDR[14]); // try latching the device select and device out for a cycle wire [15:0] later_device_d_out; wire later_sel_d_out; Nbit_reg #(16) device_d_out_reg (device_d_out, later_device_d_out, proc_clk, 1'b1, 1'b1, GLOBAL_RST); Nbit_reg #(1) sel_d_out_reg (sel_d_out, later_sel_d_out, proc_clk, 1'b1, 1'b1, GLOBAL_RST); mux_Nbit_2to1 #(16) mux_d_out ( .sel(later_sel_d_out), .a(idmem_d_out), .b(later_device_d_out), .out(DMEM_OUT)); //MEMORY-MAPPED I/O: //C000-FDFF: video memory // (really, only C000-FBFF is used, but reserve up to FDFF for // compatibility with P37X simulator) //FE00-FFFF: other I/O memory //FE00: keyboard status register //FE02: keyboard data register //FE03: expansion seven-segment display //FE04: expansion board LEDs //FE05: expansion board switches/buttons //FE06: user LEDs (D7-10) //FE07: user switches (SW7)/buttons (SW2-6) //FE08: timer status register //FE0A: timer interval register //Select which I/O device to read/write from, depending on DMEM_ADDR assign enabled = DMEM_ADDR == 16'hFE00 ? 11'b00000000001 : // keyboard status register (READ ONLY) DMEM_ADDR == 16'hFE02 ? 11'b00000000100 : // keyboard data register (READ ONLY) DMEM_ADDR == 16'hFE03 ? 11'b00000001000 : // extension board LEDs DMEM_ADDR == 16'hFE04 ? 11'b00000010000 : // extension board Seven Segment Cathodes DMEM_ADDR == 16'hFE05 ? 11'b00000100000 : // extension board buttons and switches (READ ONLY) DMEM_ADDR == 16'hFE06 ? 11'b00001000000 : // currently no connected device DMEM_ADDR == 16'hFE07 ? 11'b00010000000 : // currently no connected device DMEM_ADDR == 16'hFE08 ? 11'b10000000000 : // timer (status) register DMEM_ADDR == 16'hFE0A ? 11'b00100000000 : // timer interval register 11'b00000000000 ; //Select which I/O device to read/write from, depending on DMEM_ADDR assign device_d_out = DMEM_ADDR == 16'hFE00 ? ps2_read_data : // keyboard status register (READ ONLY) DMEM_ADDR == 16'hFE02 ? ps2_read_data : // keyboard data register (READ ONLY) DMEM_ADDR == 16'hFE03 ? dio4_read_data : // extension board LEDs DMEM_ADDR == 16'hFE04 ? dio4_read_data : // extension board Seven Segment Cathodes DMEM_ADDR == 16'hFE05 ? dio4_read_data : // extension board buttons and switches (READ ONLY) DMEM_ADDR == 16'hFE06 ? 16'h0000 : // currently no connected device DMEM_ADDR == 16'hFE07 ? 16'h0000 : // currently no connected device DMEM_ADDR == 16'hFE08 ? timer_read_data : // timer (status) register DMEM_ADDR == 16'hFE0A ? timer_read_data : // timer interval register idmem_d_out; //The expansion board controller: di04 dio4_inst(.SEV_SEG_CLK(exp_clk), //I [0] 32 MHz clock input .SWIN(SWIN), //I [7:0] toggle switch inputs .BTNIN(BTNIN), //I [4:0] push-button inputs .COUT(COUT), //O [6:0] seven-segment cathode pins .AOUT(AOUT), //O [3:0] seven-segment anode pins .LDOUT(LDOUT), //O [7:0] LED pins .reg_clk(sys_clk), .rst(GLOBAL_RST), .we(DMEM_WE), .gwe(GLOBAL_WE), .lights_data(DMEM_IN), .data_select(enabled[5:3]), .read_data(dio4_read_data), /* debug signals */ .debug_mode_select(debug_mode_select), .debug_pc_out(debug_pc_out), .debug_imem_out(debug_imem_out), .debug_reg_data_in(debug_reg_data_in), .debug_reg_we(debug_reg_we), .debug_dmem_addr(debug_dmem_addr), .debug_dmem_out(debug_dmem_out), .debug_dmem_in(debug_dmem_in), .debug_dmem_we(debug_dmem_we)); //The PS/2 keyboard controller ps2_kbd ps2_kbd_inst(.select(enabled[2]), // chooses between KBSR (0) and KBDR (1) .out(ps2_read_data), // output: KBSR or KBDR .reset(GLOBAL_RST), // global reset // no write-enable signals, as the keyboard is a read-only device // I/O pin connections .SYSTEM_CLOCK(sys_clk), .CLOCK_2MHz(ps2_clk), .PS2KEYBOARD_DATA(PS2KEYBOARD_DATA), .PS2KEYBOARD_CLK(PS2KEYBOARD_CLK)); //The timer device timer_device timer_inst(.selectStatus( enabled[10] ), .selectInterval( enabled[8] ), .in( DMEM_IN ), // value to write to interval register .out( timer_read_data ), // output of interval or status register .we( DMEM_WE ), // whether we're reading or writing the TMI .gwe( GLOBAL_WE ), .reset( GLOBAL_RST ), // global reset // I/O pin connections .SYSTEM_CLOCK( proc_clk )); endmodule