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

📄 risc16f84_clk2x.v

📁 VGA/LCD Corev2.0Specifications
💻 V
📖 第 1 页 / 共 3 页
字号:
wire addr_aux_adr_hi;
wire addr_aux_dat;
wire addr_sram;

     // Other output registers (for removing hazards)
reg  ram_we_reg;         // data-sram write strobe
reg  aux_we_reg;         // AUX write strobe

     // Synchronizers
reg  inte_sync_reg;

     // Signals used in "main_efsm" procedure
     // (Intermediate nodes used for resource sharing.)
wire [7:0] ram_i_node;   // result of reading RAM/Special registers
wire [12:0] inc_pc_node; // value of PC + 1
wire [7:0] mask_node;    // bit mask for logical operations
wire [8:0] add_node;     // result of 8bit addition
wire [4:0] addlow_node;  // result of low-4bit addition
wire temp;               // Placeholder wire
wire dtemp;              // Placeholder wire
wire aluout_zero_node;   // H if ALUOUT = 0
reg  [7:0] aluout;       // result of calculation

reg  writew_node;        // H if destination is W register
reg  writeram_node;      // H if destination is RAM/Special registers
reg  int_node;           // Used in Q4_PP to indicate interrupt condition

//--------------------------------------------------------------------------
// Instantiations
//--------------------------------------------------------------------------


//--------------------------------------------------------------------------
// Functions & Tasks
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------
// Module code
//--------------------------------------------------------------------------

// CPU synchronizers
always @(posedge clk_i)
begin
  if (clk_en_i)  // Global clock enable
  begin
    inte_sync_reg   <= inte;
  end
end

// Decode OPcode    (see pp.54 of PIC16F84 data sheet)
// only 1 signal of the following signals will be '1'
assign inst_call     = (inst_reg[13:11] ==  3'b100           );
assign inst_goto     = (inst_reg[13:11] ==  3'b101           );
assign inst_bcf      = (inst_reg[13:10] ==  4'b0100          );
assign inst_bsf      = (inst_reg[13:10] ==  4'b0101          );
assign inst_btfsc    = (inst_reg[13:10] ==  4'b0110          );
assign inst_btfss    = (inst_reg[13:10] ==  4'b0111          );
assign inst_movlw    = (inst_reg[13:10] ==  4'b1100          );
assign inst_retlw    = (inst_reg[13:10] ==  4'b1101          );
assign inst_sublw    = (inst_reg[13:9]  ==  5'b11110         );
assign inst_addlw    = (inst_reg[13:9]  ==  5'b11111         );
assign inst_iorlw    = (inst_reg[13:8]  ==  6'b111000        );
assign inst_andlw    = (inst_reg[13:8]  ==  6'b111001        );
assign inst_xorlw    = (inst_reg[13:8]  ==  6'b111010        );
assign inst_subwf    = (inst_reg[13:8]  ==  6'b000010        );
assign inst_decf     = (inst_reg[13:8]  ==  6'b000011        );
assign inst_iorwf    = (inst_reg[13:8]  ==  6'b000100        );
assign inst_andwf    = (inst_reg[13:8]  ==  6'b000101        );
assign inst_xorwf    = (inst_reg[13:8]  ==  6'b000110        );
assign inst_addwf    = (inst_reg[13:8]  ==  6'b000111        );
assign inst_movf     = (inst_reg[13:8]  ==  6'b001000        );
assign inst_comf     = (inst_reg[13:8]  ==  6'b001001        );
assign inst_incf     = (inst_reg[13:8]  ==  6'b001010        );
assign inst_decfsz   = (inst_reg[13:8]  ==  6'b001011        );
assign inst_rrf      = (inst_reg[13:8]  ==  6'b001100        );
assign inst_rlf      = (inst_reg[13:8]  ==  6'b001101        );
assign inst_swapf    = (inst_reg[13:8]  ==  6'b001110        );
assign inst_incfsz   = (inst_reg[13:8]  ==  6'b001111        );
assign inst_movwf    = (inst_reg[13:7]  ==  7'b0000001       );
assign inst_clrw     = (inst_reg[13:7]  ==  7'b0000010       );
assign inst_clrf     = (inst_reg[13:7]  ==  7'b0000011       );
assign inst_ret      = (inst_reg[13:0]  == 14'b00000000001000);
assign inst_retfie   = (inst_reg[13:0]  == 14'b00000000001001);
assign inst_sleep    = (inst_reg[13:0]  == 14'b00000001100011);


// Calculate RAM access address (see pp.19 of PIC16F84 data sheet)

    // if "d"=0, indirect addressing is used, so RAM address is BANK+FSR
    // otherwise, RAM address is BANK+"d"
    // (see pp.19 of PIC16F84 data sheet)
assign ram_adr_node = (inst_reg[6:0]==0)?{status_reg[7],fsr_reg[7:0]}:
                               {status_reg[6:5],inst_reg[6:0]};

    // check if this is an access to external RAM or not
assign addr_sram   = (ram_adr_node[6:0] > 7'b0001011); //0CH-7FH,8CH-FFH

    // check if this is an access to special register or not
    // only 1 signal of the following signals will be '1'
assign addr_pcl     = (ram_adr_node[6:0] ==  7'b0000010); // 02H, 82H
assign addr_stat    = (ram_adr_node[6:0] ==  7'b0000011); // 03H, 83H
assign addr_fsr     = (ram_adr_node[6:0] ==  7'b0000100); // 04H, 84H
assign addr_aux_dat = (ram_adr_node[7:0] == 8'b00001000); // 08H
assign addr_pclath  = (ram_adr_node[6:0] ==  7'b0001010); // 0AH, 8AH
assign addr_intcon  = (ram_adr_node[6:0] ==  7'b0001011); // 0BH, 8BH
assign addr_option  = (ram_adr_node[7:0] == 8'b10000001); // 81H
assign addr_aux_adr_lo = (ram_adr_node[7:0] == 8'b00000101); // 05H
assign addr_aux_adr_hi = (ram_adr_node[7:0] == 8'b00000110); // 06H

// construct bit-mask for logical operations and bit tests
assign mask_node = 1 << inst_reg[9:7];

// 1. Intermediate nodes for resource sharing

// 1-2. PC + 1
assign inc_pc_node = pc_reg + 1;

// Tri-state drivers instead of a huge selector...  It produces smaller
// results, and runs faster.
assign ram_i_node = (addr_sram)       ?ram_dat_i:8'bZ;
assign ram_i_node = (addr_pcl)        ?pc_reg[7:0]:8'bZ;
assign ram_i_node = (addr_stat)       ?status_reg:8'bZ;
assign ram_i_node = (addr_fsr)        ?fsr_reg:8'bZ;
assign ram_i_node = (addr_aux_dat)    ?aux_dat_io:8'bZ;
assign ram_i_node = (addr_pclath)     ?{3'b0,pclath_reg}:8'bZ;
assign ram_i_node = (addr_intcon)     ?intcon_reg:8'bZ;
assign ram_i_node = (addr_option)     ?option_reg:8'bZ;
assign ram_i_node = (addr_aux_adr_lo) ?aux_adr_lo_reg:8'bZ;
assign ram_i_node = (addr_aux_adr_hi) ?aux_adr_hi_reg:8'bZ;

// 1-3. Adder (ALU)
// full 8bit-addition, with carry in/out.
assign {add_node,temp}     =    {1'b0,aluinp1_reg,1'b1} 
                              + {1'b0,aluinp2_reg,c_in};
// lower 4bit-addition
assign {addlow_node,dtemp} =    {1'b0,aluinp1_reg[3:0],1'b1} 
                              + {1'b0,aluinp2_reg[3:0],c_in};

// 1-4. Test if aluout = 0
assign aluout_zero_node = (aluout == 0)?1:0;

// 1-5. Determine destination
always @(
            intstart_reg
         or inst_reg
         or inst_movwf
         or inst_bcf
         or inst_bsf
         or inst_clrf
         or inst_movlw
         or inst_addlw
         or inst_sublw
         or inst_andlw
         or inst_iorlw
         or inst_xorlw
         or inst_retlw
         or inst_clrw
         or inst_movf
         or inst_swapf
         or inst_addwf
         or inst_subwf
         or inst_andwf
         or inst_iorwf
         or inst_xorwf
         or inst_decf
         or inst_incf
         or inst_rlf
         or inst_rrf
         or inst_decfsz
         or inst_incfsz
         or inst_comf
         )
begin
  if (intstart_reg)
  begin
    writew_node     <= 0;
    writeram_node   <= 0;
  end
  else if (inst_movwf || inst_bcf || inst_bsf || inst_clrf)
  begin
    writew_node     <= 0;
    writeram_node   <= 1;
  end
  else if (   inst_movlw || inst_addlw || inst_sublw || inst_andlw 
           || inst_iorlw || inst_xorlw || inst_retlw || inst_clrw)
  begin
    writew_node     <= 1;
    writeram_node   <= 0;
  end
  else if (   inst_movf   || inst_swapf || inst_addwf || inst_subwf
           || inst_andwf  || inst_iorwf || inst_xorwf || inst_decf 
           || inst_incf   || inst_rlf   || inst_rrf   || inst_decfsz 
           || inst_incfsz || inst_comf)
  begin
    writew_node     <= ~inst_reg[7];  // ("d" field of fetched instruction)
    writeram_node   <=  inst_reg[7];  // ("d" field of fetched instruction)
  end
  else
  begin
    writew_node     <= 0;
    writeram_node   <= 0;
  end
end // End of determine destination logic


// 2-4-1. Calculation and store result into alu-output register

always @(
            add_node
         or aluinp1_reg
         or aluinp2_reg
         or status_reg
         or inst_reg
         or inst_movwf
         or inst_bcf
         or inst_bsf
         or inst_btfsc
         or inst_btfss
         or inst_clrf
         or inst_movlw
         or inst_addlw
         or inst_sublw
         or inst_andlw
         or inst_iorlw
         or inst_xorlw
         or inst_retlw
         or inst_clrw
         or inst_movf
         or inst_swapf
         or inst_addwf
         or inst_subwf
         or inst_andwf
         or inst_iorwf
         or inst_xorwf
         or inst_decf
         or inst_incf
         or inst_rlf
         or inst_rrf
         or inst_decfsz
         or inst_incfsz
         or inst_comf
         )
begin
  // 2-4-1-1. Set aluout register
          // Rotate left
  if      (inst_rlf) 
          aluout <= {aluinp1_reg[6:0],status_reg[0]};
          // Rotate right
  else if (inst_rrf) 
          aluout  <= {status_reg[0],aluinp1_reg[7:1]};
          // Swap nibbles
  else if (inst_swapf)
          aluout <= {aluinp1_reg[3:0],aluinp1_reg[7:4]};
          // Logical inversion
  else if (inst_comf)
          aluout  <= ~aluinp1_reg;
          // Logical AND, bit clear/bit test
  else if (   inst_andlw || inst_andwf || inst_bcf || inst_btfsc
           || inst_btfss) 
          aluout  <= (aluinp1_reg & aluinp2_reg);
          // Logical OR, bit set
  else if (inst_bsf || inst_iorlw || inst_iorwf)
          aluout  <= (aluinp1_reg | aluinp2_reg);
          // Logical XOR
  else if (inst_xorlw || inst_xorwf)
          aluout  <= (aluinp1_reg ^ aluinp2_reg);
          // Addition, Subtraction, Increment, Decrement
  else if (  inst_addlw || inst_addwf  || inst_sublw || inst_subwf
           || inst_decf || inst_decfsz || inst_incf  || inst_incfsz)
          aluout  <= add_node[7:0];
          // Pass through
  else aluout  <= aluinp1_reg;
end


// MAIN EFSM: description of register value changes in each clock cycle
always @(posedge clk_i)
begin
if (clk_en_i)
begin

  // 2. EFSM body
  case (state_reg)

    // 2-1. Reset state (see pp.14 and pp.42 of PIC16F84 data sheet)
    QRESET_PP :
    begin
      pc_reg          <= 0;     // 0
      status_reg[7:5] <= 3'b0;
      pclath_reg      <= 0;     // 0
      intcon_reg[7:1] <= 7'b0;
      option_reg      <= -1;    // Set to all ones, like vhdl (others => 1)
      aux_adr_lo_reg  <= 0;
      aux_adr_hi_reg  <= 0;
      exec_op_reg     <= 0;
      intclr_reg      <= 1;     // clear int
      intstart_reg    <= 0;
      ram_we_reg      <= 0;

⌨️ 快捷键说明

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