📄 cpu.v
字号:
module cpu ( clk, reset, paddr, pdata, portain, portbout, portcout, expdin, expdout, expaddr, expread, expwrite, debugw, debugpc, debuginst, debugstatus);// Basic Core I/O.input clk;input reset;// Program memory interfaceoutput [10:0] paddr;input [11:0] pdata;// Basic I/O Portsinput [7:0] portain;output [7:0] portbout;output [7:0] portcout;// Expansion Interfaceinput [7:0] expdin; // Data from expansion circuits TO the PIC Coreoutput [7:0] expdout; // Data to the expansion circuits FROM the PIC Coreoutput [6:0] expaddr; // File addressoutput expread; // Active high read signal (read FROM expansion circuit)output expwrite; // Active high write signal (write TO expansion circuit)// Debuggingoutput [7:0] debugw;output [10:0] debugpc;output [11:0] debuginst;output [7:0] debugstatus;// Register declarations for outputsreg [10:0] paddr;reg [7:0] portbout;reg [7:0] portcout;reg [7:0] expdout;reg [6:0] expaddr;reg expread;reg expwrite;//// Copyright (c) 1999 Thomas Coonan (tcoonan@mindspring.com)//// This source code is free software; you can redistribute it// and/or modify it in source code form under the terms of the GNU// General Public License as published by the Free Software// Foundation; either version 2 of the License, or (at your option)// any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA//// This should be set to the ROM location where our restart vector is.// As set here, we have 512 words of program space.//parameter RESET_VECTOR = 11'h7FF;parameter INDF_ADDRESS = 3'h0, TMR0_ADDRESS = 3'h1, PCL_ADDRESS = 3'h2, STATUS_ADDRESS = 3'h3, FSR_ADDRESS = 3'h4, PORTA_ADDRESS = 3'h5, PORTB_ADDRESS = 3'h6, PORTC_ADDRESS = 3'h7;// ********* Special internal registers// Instruction Registerreg [11:0] inst;// Program Counterreg [10:0] pc, pc_in;// Stack Registers and Stack "levels" register.reg [ 1:0] stacklevel;reg [10:0] stack1;reg [10:0] stack2;// W Registerreg [ 7:0] w;// The STATUS register (#3) is 8 bits wide, however, we only currently use 2 bits// of it; the C and Z bit.//// bit 0 - C// bit 2 - Z//reg [ 7:0] status;// The FSR register is the pointer register used for Indirect addressing (e.g. using INDF).reg [ 7:0] fsr;// Timer 0reg [ 7:0] tmr0;reg [ 7:0] prescaler;// Option Registerreg [7:0] option;// Tristate Control registers. We do not neccessarily support bidirectional ports, but// will save a place for these registers and the TRIS instruction. Use for debug.reg [7:0] trisa;reg [7:0] trisb;reg [7:0] trisc;// I/O Port registers//reg [7:0] porta; // Input PORTreg [7:0] portb; // Output PORTreg [7:0] portc; // Output PORT// ********** Instruction Related signals ******reg skip; // When HI force a NOP (all zeros) into inst// Derive special sub signals from inst registerwire [ 7:0] k;wire [ 4:0] fsel;wire d;wire [ 2:0] b;// ********** File Address ************//// This is the 7-bit Data Address that includes the lower 5-bit fsel, the// FSR bits and any indirect addressing.// Use this bus to address the Register File as well as all special registers, etc.//reg [6:0] fileaddr;// Address Selectsreg specialsel;reg regfilesel;reg expsel;// ****** Instruction Decoder Outputs **************// Write enable for the actual ZERO and CARRY bits within the status register.// Generated by the Instruction Decoder.//wire [1:0] aluasel;wire [1:0] alubsel;wire [3:0] aluop;wire zwe;wire cwe;wire isoption;wire istris;wire fwe; // High if any "register" is being written to at all.wire wwe; // Write Enable for the W register. Produced by Instruction Decoder.// ************* Internal Busses, mux connections, etc. ********************// Bit decoder bits. reg [7:0] bd; // Final decoder value after any polarity inversion.reg [7:0] bdec; // e.g. "Bit Decoded"wire bdpol; // Polarity bit for the bit test operations.// Data in and out of the and out of the register file//reg [7:0] regfilein; // Input into Register File, is connected to the dbus.wire [7:0] regfileout; // Path leaving the register file, goes to SBUS Muxreg regfilewe; // Write Enablereg regfilere; // Read Enable//// The dbus (Destination Bus) comes out of the ALU. It is available to all// writable registers.//// The sbus (Source Bus) comes from all readable registers as well as the output// of the Register File. It is one of the primary inputs into the ALU muxes.//// The (Expansion Bus) is another potential source. See the 'exp' signals.//reg [7:0] dbus;reg [7:0] sbus;// ALU Signals//reg [7:0] alua;reg [7:0] alub;wire [7:0] aluout;wire alucout;wire aluz;// ALU A and B mux selects.//parameter [1:0] ALUASEL_W = 2'b00, ALUASEL_SBUS = 2'b01, ALUASEL_K = 2'b10, ALUASEL_BD = 2'b11; parameter [1:0] ALUBSEL_W = 2'b00, ALUBSEL_SBUS = 2'b01, ALUBSEL_K = 2'b10, ALUBSEL_1 = 2'b11;// ALU Operation codes.// parameter [3:0] ALUOP_ADD = 4'b0000;parameter [3:0] ALUOP_SUB = 4'b1000;parameter [3:0] ALUOP_AND = 4'b0001;parameter [3:0] ALUOP_OR = 4'b0010;parameter [3:0] ALUOP_XOR = 4'b0011;parameter [3:0] ALUOP_COM = 4'b0100;parameter [3:0] ALUOP_ROR = 4'b0101;parameter [3:0] ALUOP_ROL = 4'b0110;parameter [3:0] ALUOP_SWAP = 4'b0111;// Instantiate each of our subcomponents//regs regs ( .clk (clk), .reset (reset), .we (regfilewe), .re (regfilere), .bank (fileaddr[6:5]), .location (fileaddr[4:0]), .din (regfilein), .dout (regfileout));// Instatiate the ALU.//alu alu ( .op (aluop), .a (alua), .b (alub), .y (aluout), .cin (status[0]), .cout (alucout), .zout (aluz));// Instantiate the Instruction Decoder. This is really just a lookup table.// Given the instruction, generate all the signals we need. //// For example, each instruction implies a specific ALU operation. Some of// these are obvious such as the ADDW uses an ADD alu op. Less obvious is// that a mov instruction uses an OR op which lets us do a simple copy.// // Data has to funnel through the ALU, which sometimes makes for contrived// ALU ops.//wire idecwwe;wire idecfwe;wire ideczwe;wire ideccwe;idec idec ( .inst (inst), .aluasel (aluasel), .alubsel (alubsel), .aluop (aluop), .wwe (idecwwe), .fwe (idecfwe), .zwe (ideczwe), .cwe (ideccwe), .bdpol (bdpol), .option (isoption), .tris (istris));// Wire decoder enables to enables in at this module. I did this because at// one time I had another global 'enable' that was ANDed in, but I removed that.//assign wwe = idecwwe;assign fwe = idecfwe;assign zwe = ideczwe;assign cwe = ideccwe;// *********** Debug ****************assign debugw = w;assign debugpc = pc;assign debuginst = inst;assign debugstatus = status;// *********** REGISTER FILE Addressing ****************//// We implement the following:// - The 5-bit fsel address is within a "BANK" which is 32 bytes.// - The FSR bits 6:5 are the BANK select, so there are 4 BANKS, a // total of 128 bytes. Minus the 8 special registers, that's // really 120 bytes.// - The INDF register is for indirect addressing. Referencing INDF// uses FSR as the pointer. Therefore, using INDF/FSR you address// 7-bits of memory.// We DO NOT currently implement the PAGE for program (e.g. STATUS register// bits 6:5)//// The fsel address *may* be zero in which case, we are to do indirect// addressing, using FSR register as the 8-bit pointer.//// Otherwise, use the 5-bits of FSEL (from the Instruction itself) and // 2 bank bits from the FSR register (bits 6:5).//always @(fsel or fsr or status) begin if (fsel == INDF_ADDRESS) begin // The INDEX register is addressed. There really is no INDEX register. // Use the FSR as an index, e.g. the FSR contents are the fsel. // fileaddr = fsr[6:0]; end else begin // Use FSEL field and status bank select bits // fileaddr = {status[6:5], fsel}; endend// Write Enable to Register File. // Assert this when the general fwe (write enable to *any* register) is true AND Register File// address range is specified.// always @(regfilesel or fwe) regfilewe = regfilesel & fwe;// Read Enable (this if nothing else, helps in debug.)// Assert if Register File address range is specified AND the ALU is actually using some// data off the SBUS.// always @(regfilesel or aluasel or alubsel) regfilere = regfilesel & ((aluasel == ALUASEL_SBUS) | (alubsel == ALUBSEL_SBUS));// *********** Address Decodes **************//// Generate 3 selects: specialsel, regfilesel and expsel//// ** NOTE: Must change this whenever more or few expansion addresses are// added or removed from the memory map. Otherwise, the dbus mux// won't be controlled properly!//always @(fileaddr) begin casex (fileaddr) // synopsys full_case parallel_case // This shouldn't really change. // 7'bXX00XXX: // The SPECIAL Registers are lower 8 addresses, in ALL BANKS begin specialsel = 1'b1; regfilesel = 1'b0; expsel = 1'b0; end // Adjust this case as EXPANSION locations change! // 7'b11111XX: // EXPANSION Registers are the top (4) addresses begin specialsel = 1'b0; regfilesel = 1'b0; expsel = 1'b1; end // Assume everything else must be the Register File.. // default: begin specialsel = 1'b0; regfilesel = 1'b1; expsel = 1'b0; end endcaseend // *********** Expansion Interface **************always @(dbus) expdout = dbus; always @(fileaddr) expaddr = fileaddr;always @(expsel or aluasel or alubsel) expread = expsel & ((aluasel == ALUASEL_SBUS) | (alubsel == ALUBSEL_SBUS));always @(expsel or fwe) expwrite = expsel & fwe;//// *********** SBUS **************// The sbus (Source Bus) is the output of a multiplexor that takes// inputs from the Register File, and all other special registers// and input ports. The Source Bus then, one of the inputs to the ALU// First MUX selects from all the special regsiters//always @(fsel or fsr or tmr0 or pc or status or porta or portb or portc or regfileout or expdin or specialsel or regfilesel or expsel) begin // For our current mix of registers and peripherals, only the first 8 addresses // are "special" registers (e.g. not in the Register File). As more peripheral // registers are added, they must be muxed into this MUX as well. // // We currently prohibit tristates. // // if (specialsel) begin // Special register case (fsel[2:0]) // synopsys parallel_case full_case 3'h0: sbus = fsr; 3'h1: sbus = tmr0; 3'h2: sbus = pc[7:0]; 3'h3: sbus = status; 3'h4: sbus = fsr; 3'h5: sbus = porta; // PORTA is an input-only port 3'h6: sbus = portb; // PORTB is an output-only port 3'h7: sbus = portc; // PORTC is an output-only port endcase end else begin // // Put whatever address equation is neccessary here. Remember to remove unnecessary // memory elements from Register File (regs.v). It'll still work, but they'd be // wasted flip-flops. // if (expsel) begin sbus = expdin; end else begin if (regfilesel) begin // Final Priority is Choose the register file sbus = regfileout; end else begin sbus = 8'h00; end end endend// ************** DBUS ******// The Destination bus is just the output of the ALU.//always @(aluout) dbus = aluout;always @(dbus) regfilein = dbus; // Drive the ROM address bus straight from the PC_IN bus//always @(pc_in) paddr = pc_in;// Define sub-signals out of inst//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -