⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pic.v

📁 verilog实例 100 多个
💻 V
📖 第 1 页 / 共 5 页
字号:
always @(inst or stacklevel or reset) begin
   if (reset == 1'b1) begin
      pcinsel <= PC_SELECT_RESET_VECTOR;
   end
   else begin
      casex ({inst, stacklevel})
         14'b101?_????_????_??: pcinsel <= PC_SELECT_K;		// GOTO
         14'b1001_????_????_??: pcinsel <= PC_SELECT_K;		// CALL
         14'b1000_????_????_00: pcinsel <= PC_SELECT_STACK1;	// RETLW
         14'b1000_????_????_01: pcinsel <= PC_SELECT_STACK1;	// RETLW
         14'b1000_????_????_10: pcinsel <= PC_SELECT_STACK2;	// RETLW
         14'b1000_????_????_11: pcinsel <= PC_SELECT_STACK2;	// RETLW
         14'b0010_0010_0010_??: pcinsel <= PC_SELECT_DBUS;	// MOVF where f=PC
         default:
            pcinsel <= PC_SELECT_PCPLUS1;
      endcase
   end
end


// Implement STACK1 and STACK2 registers
//
// The Stack registers are only fed from the PC itself!
//
always @(posedge clk) begin
   if (reset) begin
      stack1 <= 9'h000;
   end
   else begin
      // CALL instruction
      if (inst[11:8] == 4'b1001) begin
         case (stacklevel)
            2'b00:
               // No previous CALLs 
               begin
                  stack1 <= pc;
                  $display ("Write to STACK1: %0h", pc);
               end
            2'b01:
               // ONE previous CALL 
               begin
                  stack2 <= pc;
                  $display ("Write to STACK2: %0h", pc);
               end
            2'b10:
               // TWO previous CALLs -- This is illegal on the 16C5X! 
               begin
                  $display ("Too many CALLs!!");
               end
            2'b11: 
               begin
                  $display ("Too many CALLs!!");
               end
         endcase
      end
   end
end

// Write to stacklevel
//
// The stacklevel register keeps track of the current stack depth.  On this
// puny processor, there are only 2 levels (you could fiddle with this and
// increase the stack depth).  There are two stack registers, stack1 and stack2.
// The stack1 register is used first (e.g. the first time a call is performed),
// then stack2.  As CALLs are done, stacklevel increments.  Conversely, as
// RETs are done, stacklevel goes down. 

always @(posedge clk) begin
   if (reset == 1'b1) begin
      stacklevel <= 2'b00;  // On reset, there should be no CALLs in progress
   end
   else begin
      casex ({inst, stacklevel})
         // Call instructions
         14'b1001_????_????_00: stacklevel <= 2'b01;  // Record 1st CALL
         14'b1001_????_????_01: stacklevel <= 2'b10;  // Record 2nd CALL
         14'b1001_????_????_10: stacklevel <= 2'b10;  // Already 2! Ignore
         14'b1001_????_????_11: stacklevel <= 2'b00;  // {shouldn't happen}

         // Return instructions
         14'b1000_????_????_00: stacklevel <= 2'b00;  // {shouldn't happen}
         14'b1000_????_????_01: stacklevel <= 2'b00;  // Go back to no CALL in progress
         14'b1000_????_????_10: stacklevel <= 2'b01;  // Go back to 1 CALL in progress
         14'b1000_????_????_11: stacklevel <= 2'b10;  // {shouldn't happen} sort of like, Go back to 2 calls in progress
         default:
            stacklevel <= stacklevel;
      endcase
   end
end



// ************  EXPANSION  *************************
//
// The following is an example of customization.
//
// Example:  Create a read/write port located at address 7F.  It'll be 8-bits, where
//           the upper 4 bits are outputs and the lower 4 bits are inputs.  
//           Use indirect addressing to access it (INDF/FSR).  Just for fun, let's
//           attach a special loop-back circuit between the outputs and inputs.
//           Let's attach... say... a 4-bit adder.
//

reg [3:0]	special_peripheral_writeable_bits;
reg [3:0]	special_peripheral_readeable_bits;

// Implement the writeable bits.
//
always @(posedge clk) begin
   if (reset) begin
      special_peripheral_writeable_bits <= 4'b0000;
   end
   else begin
      if (fwe & expsel & (fileaddr == EXPADDRESS_LILADDER)) begin
         special_peripheral_writeable_bits <= dbus;
      end
   end
end

// Implement the special peripheral function (the 4-bit adder for this example).
always @(special_peripheral_writeable_bits) begin
   special_peripheral_readeable_bits <= special_peripheral_writeable_bits + 1;
end

// Drive the ebus.  With only one custom address, no more muxing needs to be
// done, but if there are multiple custom circuits, everyone needs to cooperate
// and drive ebus properly.
//
always @(fileaddr or special_peripheral_readeable_bits) begin
   if (fileaddr == EXPADDRESS_LILADDER)
      ebus <= special_peripheral_readeable_bits;
   else
      ebus <= 8'hff;
end

endmodule
// 
// SYNTHETIC PIC 2.0                                          4/23/98
//
//    This is a synthesizable Microchip 16C57 compatible
//    microcontroller.  This core is not intended as a high fidelity model of
//    the PIC, but simply a way to offer a simple processor core to people
//    familiar with the PIC who also have PIC tools.  
//
//    pictest.v  -   top-level testbench (NOT SYNTHESIZABLE)
//    piccpu.v   -   top-level synthesizable module
//    picregs.v  -   register file instantiated under piccpu
//    picalu.v   -   ALU instantiated under piccpu
//    picidec.v  -   Instruction Decoder instantiated under piccpu
//    hex2rom.c  -   C program used to translate MPLAB's INTEL HEX output
//                   into the Verilog $readmemh compatible file
//    test*.asm  -   (note the wildcard..) Several test programs used
//                   to help debug the verilog.  I used MPLAB and the simulator
//                   to develop these programs and get the expected results.
//                   Then, I ran them on Verilog-XL where they appeared to
//                   match.
//
//    Copyright, Tom Coonan, '97.
//    Use freely, but not for resale as is.  You may use this in your
//    own projects as desired.  Just don't try to sell it as is!
//
//
// This is the PIC Instruction Decoder.
//
// The 12-bit PIC instruction must result in a set of control
// signals to the ALU, register write enables and other wires.
// This is purely combinatorial.  This can physically be
// implemented as a ROM, or, in this implementation a Verilog
// casex statement is used to directly synthesize the signals.
// This approach is more portable, and hopefully much reduction
// occurs in the equations.
//
// The Synthetic PIC Manual contains a table that better shows
// all the required signals per instruction.  I basically
// took that table and created the Verilog implementation below.
//

module picidec (
	inst,
	aluasel,
	alubsel,
	aluop,
	wwe,
	fwe,
	zwe,
	cwe,
	bdpol,
	option,
	tris
);

input  [11:0]	inst;

output [1:0]	aluasel;
output [1:0]	alubsel;
output [3:0]	aluop;
output		wwe;
output		fwe;
output		zwe;
output		cwe;
output		bdpol;
output		option;
output		tris;

reg [14:0] decodes;

// For reference, the ALU Op codes are:
//
//   ADD  0000
//   SUB  1000
//   AND  0001
//   OR   0010
//   XOR  0011
//   COM  0100
//   ROR  0101
//   ROL  0110
//   SWAP 0111

assign {	aluasel,	// Select source for ALU A input. 00=W, 01=SBUS, 10=K, 11=BD
		alubsel,	// Select source for ALU B input. 00=W, 01=SBUS, 10=K, 11="1"
		aluop,		// ALU Operation (see comments above for these codes)
		wwe,		// W register Write Enable
		fwe,		// File Register Write Enable
		zwe,		// Status register Z bit update
		cwe,		// Status register Z bit update
		bdpol,		// Polarity on bit decode vector (0=no inversion, 1=invert)
		tris,		// Instruction is an TRIS instruction
		option		// Instruction is an OPTION instruction
	} = decodes;

// This is a large combinatorial decoder.
// I use the casex statement.

always @(inst) begin
	casex (inst)
		// *** Byte-Oriented File Register Operations
		//
		//                                 A  A  ALU  W F Z C B T O
		//                                 L  L   O   W W W W D R P
		//                                 U  U   P   E E E E P I T
		//                                 A  B               O S
		//                                                    L
		12'b0000_0000_0000: decodes <= 15'b00_00_0000_0_0_0_0_0_0_0; // NOP
		12'b0000_001X_XXXX: decodes <= 15'b00_00_0010_0_1_0_0_0_0_0; // MOVWF
		12'b0000_0100_0000: decodes <= 15'b00_00_0011_1_0_1_0_0_0_0; // CLRW
		12'b0000_011X_XXXX: decodes <= 15'b00_00_0011_0_1_1_0_0_0_0; // CLRF
		12'b0000_100X_XXXX: decodes <= 15'b01_00_1000_1_0_1_1_0_0_0; // SUBWF (d=0)
		12'b0000_101X_XXXX: decodes <= 15'b01_00_1000_0_1_1_1_0_0_0; // SUBWF (d=1)
		12'b0000_110X_XXXX: decodes <= 15'b01_11_1000_1_0_1_0_0_0_0; // DECF  (d=0)
		12'b0000_111X_XXXX: decodes <= 15'b01_11_1000_0_1_1_0_0_0_0; // DECF  (d=1)
		12'b0001_000X_XXXX: decodes <= 15'b00_01_0010_1_0_1_0_0_0_0; // IORWF (d=0)
		12'b0001_001X_XXXX: decodes <= 15'b00_01_0010_0_1_1_0_0_0_0; // IORWF (d=1)
		12'b0001_010X_XXXX: decodes <= 15'b00_01_0001_1_0_1_0_0_0_0; // ANDWF (d=0)
		12'b0001_011X_XXXX: decodes <= 15'b00_01_0001_0_1_1_0_0_0_0; // ANDWF (d=1)
		12'b0001_100X_XXXX: decodes <= 15'b00_01_0011_1_0_1_0_0_0_0; // XORWF (d=0)
		12'b0001_101X_XXXX: decodes <= 15'b00_01_0011_0_1_1_0_0_0_0; // XORWF (d=1)
		12'b0001_110X_XXXX: decodes <= 15'b00_01_0000_1_0_1_1_0_0_0; // ADDWF (d=0)
		12'b0001_111X_XXXX: decodes <= 15'b00_01_0000_0_1_1_1_0_0_0; // ADDWF (d=1)
		12'b0010_000X_XXXX: decodes <= 15'b01_01_0010_1_0_1_0_0_0_0; // MOVF  (d=0)
		12'b0010_001X_XXXX: decodes <= 15'b01_01_0010_0_1_1_0_0_0_0; // MOVF  (d=1)
		12'b0010_010X_XXXX: decodes <= 15'b01_01_0100_1_0_1_0_0_0_0; // COMF  (d=0)
		12'b0010_011X_XXXX: decodes <= 15'b01_01_0100_0_1_1_0_0_0_0; // COMF  (d=1)
		12'b0010_100X_XXXX: decodes <= 15'b01_11_0000_1_0_1_0_0_0_0; // INCF  (d=0)
		12'b0010_101X_XXXX: decodes <= 15'b01_11_0000_0_1_1_0_0_0_0; // INCF  (d=1)
		12'b0010_110X_XXXX: decodes <= 15'b01_11_1000_1_0_0_0_0_0_0; // DECFSZ(d=0)
		12'b0010_111X_XXXX: decodes <= 15'b01_11_1000_0_1_0_0_0_0_0; // DECFSZ(d=1)
		12'b0011_000X_XXXX: decodes <= 15'b01_01_0101_1_0_0_1_0_0_0; // RRF   (d=0)
		12'b0011_001X_XXXX: decodes <= 15'b01_01_0101_0_1_0_1_0_0_0; // RRF   (d=1)
		12'b0011_010X_XXXX: decodes <= 15'b01_01_0110_1_0_0_1_0_0_0; // RLF   (d=0)
		12'b0011_011X_XXXX: decodes <= 15'b01_01_0110_0_1_0_1_0_0_0; // RLF   (d=1)
		12'b0011_100X_XXXX: decodes <= 15'b01_01_0111_1_0_0_0_0_0_0; // SWAPF (d=0)
		12'b0011_101X_XXXX: decodes <= 15'b01_01_0111_0_1_0_0_0_0_0; // SWAPF (d=1)
		12'b0011_110X_XXXX: decodes <= 15'b01_11_0000_1_0_0_0_0_0_0; // INCFSZ(d=0)
		12'b0011_111X_XXXX: decodes <= 15'b01_11_0000_0_1_0_0_0_0_0; // INCFSZ(d=1)

		// *** Bit-Oriented File Register Operations
                //
		//                                 A  A  ALU  W F Z C B T O
		//                                 L  L   O   W W W W D R P
		//                                 U  U   P   E E E E P I T
		//                                 A  B               O S
		//                                                    L
		12'b0100_XXXX_XXXX: decodes <= 15'b11_01_0001_0_1_0_0_1_0_0; // BCF
		12'b0101_XXXX_XXXX: decodes <= 15'b11_01_0010_0_1_0_0_0_0_0; // BSF
		12'b0110_XXXX_XXXX: decodes <= 15'b11_01_0001_0_0_0_0_0_0_0; // BTFSC
		12'b0111_XXXX_XXXX: decodes <= 15'b11_01_0001_0_0_0_0_0_0_0; // BTFSS

		// *** Literal and Control Operations
                //
		//                                 A  A  ALU  W F Z C B T O
		//                                 L  L   O   W W W W D R P
		//                                 U  U   P   E E E E P I T
		//                                 A  B               O S
		//                                                    L
		12'b0000_0000_0010: decodes <= 15'b00_00_0010_0_1_0_0_0_0_1; // OPTION
		12'b0000_0000_0011: decodes <= 15'b00_00_0000_0_0_0_0_0_0_0; // SLEEP
		12'b0000_0000_0100: decodes <= 15'b00_00_0000_0_0_0_0_0_0_0; // CLRWDT
		12'b0000_0000_0101: decodes <= 15'b00_00_0000_0_1_0_0_0_1_0; // TRIS 5
		12'b0000_0000_0110: decodes <= 15'b00_00_0010_0_1_0_0_0_1_0; // TRIS 6
		12'b0000_0000_0111: decodes <= 15'b00_00_0010_0_1_0_0_0_1_0; // TRIS 7
                //
		//                                 A  A  ALU  W F Z C B T O
		//                                 L  L   O   W W W W D R P
		//                                 U  U   P   E E E E P I T
		//                                 A  B               O S
		//                                                    L
		12'b1000_XXXX_XXXX: decodes <= 15'b10_10_0010_1_0_0_0_0_0_0; // RETLW
		12'b1001_XXXX_XXXX: decodes <= 15'b10_10_0010_0_0_0_0_0_0_0; // CALL
		12'b101X_XXXX_XXXX: decodes <= 15'b10_10_0010_0_0_0_0_0_0_0; // GOTO
		12'b1100_XXXX_XXXX: decodes <= 15'b10_10_0010_1_0_0_0_0_0_0; // MOVLW
		12'b1101_XXXX_XXXX: decodes <= 15'b00_10_0010_1_0_1_0_0_0_0; // IORLW
		12'b1110_XXXX_XXXX: decodes <= 15'b00_10_0001_1_0_1_0_0_0_0; // ANDLW
		12'b1111_XXXX_XXXX: decodes <= 15'b00_10_0011_1_0_1_0_0_0_0; // XORLW

		default:
			decodes <= 15'b00_00_0000_0_0_0_0_0_0_0;
	endcase
end

endmodule


// 
// SYNTHETIC PIC 2.0                                          4/23/98
//
//    This is a synthesizable Microchip 16C57 compatible
//    microcontroller.  This core is not intended as a high fidelity model of
//    the PIC, but simply a way to offer a simple processor core to people
//    familiar with the PIC who also have PIC tools.  
//
//    pictest.v  -   top-level testbench (NOT SYNTHESIZABLE)
//    piccpu.v   -   top-level synthesizable module
//    picregs.v  -   register file instantiated under piccpu
//    picalu.v   -   ALU instantiated under piccpu
//    picidec.v  -   Instruction Decoder instantiated under piccpu
//    hex2rom.c  -   C program used to translate MPLAB's INTEL HEX output
//                   into the Verilog $readmemh compatible file
//    test*.asm  -   (note the wildcard..) Several test programs used
//                   to help debug the verilog.  I used MPLAB and the simulator
//                   to develop these programs and get the expected results.
//                   Then, I ran them on Verilog-XL where they appeared to
//                   match.
//
//    Copyright, Tom Coonan, '97.
//    Use freely, but not for resale as is.  You may use this in your
//    own projects as desired.  Just don't try to sell it as is!
//
//

//`define DEBUG_SHOWREADS
//`define DEBUG_SHOWWRITES

// Memory Map:
//
// PIC Data Memory addressing is complicated.  See the Data Book for full explanation..
//
// Basically, each BANK contains 32 locations.  The lowest 16 locations in ALL Banks
// are really all mapped to the same bank (bank #0).  The first 8 locations are the Special
// registers like the STATUS and PC registers.  The upper 16 words in each bank, really are
// unique to each bank.  The smallest PIC (16C54) only has the one bank #0.
//
// So, as a programmer, what you get is this.  No matter what bank you are in (FSR[6:5])
// you always have access to your special registers and also to registers 8-15.  You can
// change to a 1 of 4 banks by setting FSR[6:5] and get 4 different sets of registers
// 16-31.
//
// For numbering purposes, I've numbered the registers as if they are one linear memory
// space, just like in the Data Book (see Figure 4-15 "Direct/Indirect Addressing").
// So, the unique 16 registers in bank #1 are named r48 - r63 (I use decimal).  The
// unique registers in bank #3 are therefore r112 - r127.  There is no r111 because,
// remember, the lower 16 registers each each bank are all reall the same registers 0-15.
// 
// Confused?!  The Data Book explains it better than I can.
//
//   bank location 
//     XX 00rrr  -  The special registers are not implemented in this register file.
//     XX 01rrr  -  The 8 common words, just above the Special Regs, same for all Banks
//     00 1rrrr  -  The 16 words unique to Bank #0
//     01 1rrrr  -  The 16 words unique to Bank #1
//     10 1rrrr  -  The 16 words unique to Bank #2
//     11 1rrrr  -  The 16 words unique to Bank #3
//
//  So, 
//     Special Regs are location[4:3] == 00
//     Common Regs are  location[4:3] == 01
//     Words in banks   location[4]   == 1
// 
//
//  I had problems trying to use simple register file declarations that
//  would always, always work right, were synthesizable and allowed
//  me to easily remove locations from the memory space.  SOOOooo... I
//  did the brute force thing and enumerated all the locations..
//
//  Much larger spaces will probably need a RAM and whatever I do would need
//  custom hacking anyway..  I don't see an obvious solution to all this, but
//  welcome suggestions..
//
module picregs (clk, reset, we, re, bank, location, din, dout);

input		clk;
input		reset;
input		we;
input		re;
input  [1:0]	bank;		// Bank 0,1,2,3
input  [4:0]	location;	// Location
input  [7:0]	din;		// Input 
output [7:0]	dout;		// Output 

//parameter	MAX_ADDRESS = 127;

reg [7:0]	dout;

integer index;

// Declare the major busses in and out of each block.
//
reg [7:0]	commonblockout;	// Data Memory common across all banks
reg [7:0]	highblock0out;	// Upper 16 bytes in BANK #0
reg [7:0]	highblock1out;	// Upper 16 bytes in BANK #1
reg [7:0]	highblock2out;	// Upper 16 bytes in BANK #2
reg [7:0]	highblock3out;	// Upper 16 bytes in BANK #3

reg [7:0]	commonblockin;	// Data Memory common across all banks
reg [7:0]	highblock0in;	// Upper 16 bytes in BANK #0
reg [7:0]	highblock1in;	// Upper 16 bytes in BANK #1
reg [7:0]	highblock2in;	// Upper 16 bytes in BANK #2
reg [7:0]	highblock3in;	// Upper 16 bytes in BANK #3

reg		commonblocksel;	// Select
reg		highblock0sel;	// Select
reg		highblock1sel;	// Select
reg		highblock2sel;	// Select
reg		highblock3sel;	// Select
// synopsys translate_off

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -