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

📄 pic.v

📁 verilog实例 100 多个
💻 V
📖 第 1 页 / 共 5 页
字号:
         end
      default:  // Anything else must be in the Register File
         begin
            specialsel	<= 1'b0;
            regfilesel	<= 1'b1;
            expsel	<= 1'b0;
         end
   endcase
end
  
// *********** 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 ebus
         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 (picregs.v).  It'll still work, but they'd be
      // wasted flip-flops.
      //
      if (expsel) begin
         sbus <= ebus;
      end
      else begin
         if (regfilesel) begin
            // Final Priority is Choose the register file
            sbus <= regfileout;
         end
         else begin
            sbus <= 8'h00;
         end
      end
   end
end

// ************** 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
//
always @(pc)
   paddr = pc;


// Define sub-signals out of inst
//
assign k =     inst[7:0];
assign fsel  = inst[4:0];
assign longk = inst[8:0];
assign d     = inst[5];
assign b     = inst[7:5];

// Bit Decoder.
//
// Simply take the 3-bit b field in the PIC instruction and create the
// expanded 8-bit decoder field, which is used as a mask.
//


always @(b) begin
   case (b)
      3'b000: bdec <= 8'b00000001;
      3'b001: bdec <= 8'b00000010;
      3'b010: bdec <= 8'b00000100;
      3'b011: bdec <= 8'b00001000;
      3'b100: bdec <= 8'b00010000;
      3'b101: bdec <= 8'b00100000;
      3'b110: bdec <= 8'b01000000;
      3'b111: bdec <= 8'b10000000;
   endcase
end

always @(bdec or bdpol)
   bd <= bdec ^ bdpol;

// Instruction regsiter usually get the ROM data as its input, but
// sometimes for branching, the skip signal must cause a NOP.
//
always @(posedge clk) begin
   if (reset) begin
      inst <= 12'h000;
   end
   else begin
      if (skip == 1'b1) begin
         inst <= 12'b000000000000; // FORCE NOP
      end
      else begin
         inst <= pdata;
      end
   end
end

// SKIP signal.
//
// We want to insert the NOP instruction for the following conditions:
//    GOTO,CALL and RETLW instructions (All have inst[11:10] = 2'b10
//    BTFSS instruction when aluz is HI  (
//    BTFSC instruction when aluz is LO
//
always @(inst or aluz) begin
   casex ({inst, aluz})
      13'b10??_????_????_?:    // A GOTO, CALL or RETLW instructions
         skip <= 1'b1;
         
      13'b0110_????_????_1:    // BTFSC instruction and aluz == 1
         skip <= 1'b1;
	
      13'b0111_????_????_0:    // BTFSS instruction and aluz == 0
         skip <= 1'b1;
      
      13'b0010_11??_????_1:    // DECFSZ instruction and aluz == 1
         skip <= 1'b1;
	
      13'b0011_11??_????_1:    // INCFSZ instruction and aluz == 1
         skip <= 1'b1;
	
      default:
         skip <= 1'b0;
   endcase
end

// 4:1 Data MUX into alua
//
//
always @(aluasel or w or sbus or k or bd) begin
   case (aluasel)
      2'b00: alua <= w;
      2'b01: alua <= sbus;
      2'b10: alua <= k;
      2'b11: alua <= bd;
   endcase
end

// 4:1 Data MUX into alub
//
//
always @(alubsel or w or sbus or k) begin
   case (alubsel)
      2'b00: alub <= w;
      2'b01: alub <= sbus;
      2'b10: alub <= k;
      2'b11: alub <= 8'b00000001;
   endcase
end

// W Register
always @(posedge clk) begin
   if (reset) begin
      w <= 8'h00;
   end
   else begin
      if (wwe) begin
         w <= dbus;
      end
   end   
end

// ************ Writes to various Special Registers (fsel between 0 and 7)

// INDF Register (Register #0)
//
//    Not a real register.  This is the Indirect Addressing mode register.
//    See the regfileaddr logic.

// TMR0 Register (Register #1)
//
//    Timer0 is currently only a free-running timer clocked by the main system clock.
//
always @(posedge clk) begin
   if (reset) begin
      tmr0 <= 8'h00;
   end
   else begin
      // See if the status register is actually being written to
      if (fwe & specialsel & (fsel == TMR0_ADDRESS)) begin
         // Yes, so just update the register from the dbus
         tmr0 <= dbus;
      end
      else begin
         // Mask off the prescaler value based on desired divide ratio.
         // Whenever this is zero, then that is our divided pulse.  Increment
         // the final timer value when it's zero.
         //
         case (option[2:0]) // synopsys parallel_case full_case
            3'b000: if (~|(prescaler & 8'b00000001)) tmr0 <= tmr0 + 1;
            3'b001: if (~|(prescaler & 8'b00000011)) tmr0 <= tmr0 + 1;
            3'b010: if (~|(prescaler & 8'b00000111)) tmr0 <= tmr0 + 1;
            3'b011: if (~|(prescaler & 8'b00001111)) tmr0 <= tmr0 + 1;
            3'b100: if (~|(prescaler & 8'b00011111)) tmr0 <= tmr0 + 1;
            3'b101: if (~|(prescaler & 8'b00111111)) tmr0 <= tmr0 + 1;
            3'b110: if (~|(prescaler & 8'b01111111)) tmr0 <= tmr0 + 1;
            3'b111: if (~|(prescaler & 8'b11111111)) tmr0 <= tmr0 + 1;
         endcase            
      end
   end
end

// The prescaler is always counting from 00 to FF
always @(posedge clk) begin
   if (reset) begin
      prescaler <= 8'h00;
   end
   else begin
      // See if the status register is actually being written to
      prescaler <= prescaler + 1;
   end
end


// PCL Register (Register #2)
//
//    PC Lower 8 bits.  This is handled in the PC section below...


// STATUS Register (Register #3)
//
always @(posedge clk) begin
   if (reset) begin
      status <= 8'h00;
   end
   else begin
      // See if the status register is actually being written to
      if (fwe & specialsel & (fsel == STATUS_ADDRESS)) begin
         // Yes, so just update the register from the dbus
         status <= dbus;
      end
      else begin
         // Update status register on a bit-by-bit basis.
         //
         // For the carry and zero flags, each instruction has its own rule as
         // to whether to update this flag or not.  The instruction decoder is
         // providing us with an enable for C and Z.  Use this to decide whether
         // to retain the existing value, or update with the new alu status output.
         //
         status <= {
            status[7],			// BIT 7: Undefined.. (maybe use for debugging)
            status[6],			// BIT 6: Program Page, HI bit
            status[5],			// BIT 5: Program Page, LO bit
            status[4],			// BIT 4: Time Out bit (not implemented at this time)
            status[3],			// BIT 3: Power Down bit (not implemented at this time)
            (zwe) ? aluz : status[2],	// BIT 2: Z
            status[1],			// BIT 1: DC
            (cwe) ? alucout : status[0]	// BIT 0: C
         };
      end
   end
end

// FSR Register  (Register #4)
//            
always @(posedge clk) begin
   if (reset) begin
      fsr <= 8'h00;
   end
   else begin
      // See if the status register is actually being written to
      if (fwe & specialsel & (fsel == FSR_ADDRESS)) begin
         fsr <= dbus;
      end
   end
end

// OPTION Register
//
// The special OPTION instruction should move W into the OPTION register.
always @(posedge clk) begin
   if (reset) begin
      option <= 8'h00;
   end
   else begin
      if (isoption)
         option <= dbus;
   end   
end

// PORTA Input Port   (Register #5)
//
// Register anything on the module's porta input on every single clock.
//
always @(posedge clk) begin
   if (reset) begin
      porta <= 8'h00;
   end
   else begin
      porta <= portain;
   end   
end

// PORTB Output Port  (Register #6)
always @(posedge clk) begin
   if (reset) begin
      portb <= 8'h00;
   end
   else begin
      if (fwe & specialsel & (fsel == PORTB_ADDRESS) & ~istris) begin
         portb <= dbus;
      end
   end   
end

// Connect the output ports to the register output.
always @(portb)
   portbout <= portb;
   
// PORTC Output Port  (Register #7)
always @(posedge clk) begin
   if (reset) begin
      portc <= 8'h00;
   end
   else begin
      if (fwe & specialsel & (fsel == PORTC_ADDRESS) & ~istris) begin
         portc <= dbus;
      end
   end   
end

// Connect the output ports to the register output.
always @(portc)
   portcout <= portc;
 
// TRIS Registers
always @(posedge clk) begin
   if (reset) begin
      trisa <= 8'hff; // Default is to tristate them
   end
   else begin
      if (fwe & specialsel & (fsel == PORTA_ADDRESS) & istris) begin
         trisa <= dbus;
      end
   end   
end

always @(posedge clk) begin
   if (reset) begin
      trisb <= 8'hff; // Default is to tristate them
   end
   else begin
      if (fwe & specialsel & (fsel == PORTB_ADDRESS) & istris) begin
         trisb <= dbus;
      end
   end   
end

always @(posedge clk) begin
   if (reset) begin
      trisc <= 8'hff; // Default is to tristate them
   end
   else begin
      if (fwe & specialsel & (fsel == PORTC_ADDRESS) & istris) begin
         trisc <= dbus;
      end
   end   
end
  

// ********** PC AND STACK *************************
//
// There are 4 ways to change the PC.  They are:
//    GOTO  101k_kkkk_kkkk
//    CALL  1001_kkkk_kkkk
//    RETLW 1000_kkkk_kkkk
//    MOVF  0010_0010_0010  (e.g. a write to reg #2)
//
// Remember that the skip instructions work by inserting
// a NOP instruction or not into program stream and don't
// change the PC.
//

// We need pc + 1 in several places, so lets define this incrementor and
// its output signal it in one place so that we never get redundant adders.
//
always @(pc)
   pcplus1 <= pc + 1;
   
parameter	PC_SELECT_PCPLUS1	= 3'b000,
		PC_SELECT_K             = 3'b001,
		PC_SELECT_STACK1        = 3'b010,
		PC_SELECT_STACK2        = 3'b011,
		PC_SELECT_DBUS          = 3'b100,
		PC_SELECT_RESET_VECTOR  = 3'b101;

// 8:1 Data MUX into PC 
always @(posedge clk) begin
   case (pcinsel) // synopsys parallel_case full_case
      3'b000:  pc <= pcplus1;
      3'b001:  pc <= k;
      3'b010:  pc <= stack1;
      3'b011:  pc <= stack2;
      3'b100:  pc <= dbus;
      3'b101:  pc <= RESET_VECTOR;
      
      // Don't really carry about these...
      3'b110:  pc <= pc;
      3'b111:  pc <= pc;
   endcase
end

// Select for the MUX going into the PC.
//
//

⌨️ 快捷键说明

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