`default_nettype none // VERSION 1.2 /* * PJH 1/29/06 * * io is the top-level module for switch, LED, VGA, PS/2 and memory * input and output. All inputs from and outputs to pins are ports in * this module. * * The expansion board module was added and moderately tested by * Andrew and I, and we believe it is working properly. I put the PS2 * module in quickly and tried to use it in a state machine, but it * did not work. This module should be tested using ModelSim to ensure * that the PS2 module is connected properly. * * AJL JLD 25 Feb 2006 * Sorted out the issues with the keyboard and expansion boards. See * comments in processor.v and dio4.v for details. */ module p37x_processor(/*Clock inputs from FPGA pins*/ CLK_100MHz, CLK_32MHz, RST_BTN_IN, GLOBAL_WE_BTN_IN, GLOBAL_WE_SWITCH_IN, GLOBAL_RST_LED_OUT, GLOBAL_WE_LED_OUT, DEBUG_SWITCH_IN, /*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, LDGND, /*PS2 ports*/ PS2KEYBOARD_DATA, PS2KEYBOARD_CLK); input CLK_100MHz; // System clock input CLK_32MHz; // SystemACE clock input RST_BTN_IN; // Right push button input GLOBAL_WE_BTN_IN; // Down push button input GLOBAL_WE_SWITCH_IN; // left-most FPGA switch (3) input [2:0] DEBUG_SWITCH_IN; // other FPGA switches (2-0) output GLOBAL_RST_LED_OUT; // Lit when GLOBAL_RST is high output GLOBAL_WE_LED_OUT; // Lit when GLOBAL_WE is high //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 output LDGND; //ground, must always be 1 assign LDGND = 1'b1; //PS/2 Keyboard: inout PS2KEYBOARD_DATA; inout PS2KEYBOARD_CLK; wire debug_reg_we; wire [15:0] debug_reg_data_in; // CLOCK MANAGEMENT wire GLOBAL_WE; //global we, toggled to build a single-step clock // wire sys_clk; //clock for processor wire pixel_clk; //clock for VGA wire ps2_clk; //clock for PS/2 wire exp_clk; //clock for expansion board wire dcm_reset_1; //digital clock manager reset signal wire dcm_reset_2; //digital clock manager reset signal wire GLOBAL_RST; //global reset signal wire proc_clk; //the processor clock, same as memory clock //Currently, the pixel clock is formed by dividing the 100MHz clock by //4 using CLKDV, and the system clock (for the pipeline, etc.) is the same //as the input clock (from CLKFX). If the pixel clock needs to be changed, //it may not be possible to do it using CLKDV (i.e. not an integer or .5 //factor of the 100MHz clock); you may have to switch the pixel clock to //CLKFX and the system clock to CLKDV. dcm_two #(2, 2, 4) dcm_inst_1(.CLK_IN( CLK_100MHz ), .CLKDV_OUT( pixel_clk ), //100 MHz / 4 = 25 MHz // .CLKFX_OUT( sys_clk ), //100 MHz / 2 * 2 = 100 MHz .RESET( dcm_reset_1 )); dcm_two #(2, 2, 16) dcm_inst_2(.CLK_IN( CLK_32MHz ), .CLKDV_OUT( ps2_clk ), //32 MHz / 16 = 2 MHz .CLKFX_OUT( exp_clk ), //32 MHz / 2 * 2 = 32 MHz .RESET( dcm_reset_2 )); assign proc_clk = exp_clk; /* Generate "single-step clock" by one-pulsing the global write-enable. The one-pulse circuitry cleans up the signal edges for us. */ wire global_we_pulse; one_pulse clk_pulse(.clk( proc_clk ), .rst( dcm_reset_1 | dcm_reset_2 ), .btn( ~GLOBAL_WE_BTN_IN ), // FPGA buttons are active-low .pulse_out( global_we_pulse )); /* Clean up trailing edges of the GLOBAL_WE switch input */ wire global_we_switch; Nbit_reg #(1, 0) gwe_cleaner(.in( ~GLOBAL_WE_SWITCH_IN ), // FPGA switches are active-low .out( global_we_switch ), .clk( proc_clk ), .we( 1'b1 ), .gwe( 1'b1 ), .rst( GLOBAL_RST )); /* Because our memory requires a posedge even to *read*, doing a load requires 1 posedge for the PC, 1 for the memory, and 1 for the register file. So we have the gwe high for 1 out of 4 processor cycles, which cuts the effective clock rate by 4 (in the same manner as the manual pulse does), but keeps the system clock going so that the memory (which isn't governed by gwe) can perform the read. */ wire alt_out; count #(2) global_we_count(.clk( proc_clk ), .out( alt_out )); or( GLOBAL_WE, global_we_pulse, (alt_out & global_we_switch) ); /* Clean up the edges of the manual reset signal. Only the trailing edge should really matter, though.*/ wire rst_btn; Nbit_reg #(1, 0) reset_cleaner(.in( ~RST_BTN_IN ), // FPGA buttons are active-low .out( rst_btn ), .clk( proc_clk ), .we( 1'b1 ), .gwe( 1'b1 ), .rst( dcm_reset_1 | dcm_reset_2 )); or( GLOBAL_RST, dcm_reset_1, dcm_reset_2, rst_btn ); assign GLOBAL_RST_LED_OUT = ~GLOBAL_RST; // FPGA LEDs are active-low assign GLOBAL_WE_LED_OUT = ~GLOBAL_WE; // ---------- " ----------- // MEMORY // memory interface wire d_we, d_re, i_re; wire [15:0] i_addr; wire [15:0] i_out; wire [15:0] d_addr; wire [15:0] d_in; wire [15:0] d_out; // PROCESSOR sc_datapath proc_inst(.CLK( proc_clk ), .RST( GLOBAL_RST ), .GLOBAL_WE( GLOBAL_WE ), .IMEM_ADDR( i_addr ), .IMEM_OUT( i_out ), .IMEM_RE( i_re ), .DMEM_ADDR( d_addr ), .DMEM_IN( d_in ), .DMEM_OUT( d_out ), .DMEM_WE( d_we ), .DMEM_RE( d_re ), // testbench wires .REGFILE_WE( debug_reg_we ), .REGFILE_DATA_IN( debug_reg_data_in )); // MEMORY memory_with_devices mem_inst (/*Memory interface*/ .IMEM_ADDR( i_addr ), .IMEM_OUT( i_out ), .IMEM_RE( i_re ), .DMEM_WE( d_we ), .DMEM_RE( d_re ), .DMEM_ADDR( d_addr ), .DMEM_IN( d_in ), .DMEM_OUT( d_out ), /*clock/reset signals*/ .sys_clk( proc_clk ), .proc_clk( proc_clk ), .pixel_clk( pixel_clk ), .ps2_clk( ps2_clk ), .exp_clk( exp_clk ), .GLOBAL_RST( GLOBAL_RST ), .GLOBAL_WE( GLOBAL_WE ), // Everything below is an I/O pin connection /*VGA ports*/ .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 ), /*Expansion board ports*/ .SWIN( SWIN ), .BTNIN( BTNIN ), .COUT( COUT ), .AOUT( AOUT ), .LDOUT( LDOUT ), /* debug signals */ .debug_mode_select( ~DEBUG_SWITCH_IN ), .debug_pc_out( i_addr ), .debug_imem_out( i_out ), .debug_reg_data_in( debug_reg_data_in ), .debug_reg_we( debug_reg_we ), .debug_dmem_addr( d_addr ), .debug_dmem_out( d_out ), .debug_dmem_in( d_in ), .debug_dmem_we( d_we ), /*PS2 port*/ .PS2KEYBOARD_DATA( PS2KEYBOARD_DATA ), .PS2KEYBOARD_CLK( PS2KEYBOARD_CLK )); endmodule