OpenCores
URL https://opencores.org/ocsvn/risc16f84/risc16f84/trunk

Subversion Repositories risc16f84

[/] [risc16f84/] [trunk/] [risc16f84_clk2x.v] - Diff between revs 10 and 12

Show entire file | Details | Blame | View Log

Rev 10 Rev 12
Line 148... Line 148...
//                  fix of 03/05/02.  The fix of 03/05/02 correctly generated the
//                  fix of 03/05/02.  The fix of 03/05/02 correctly generated the
//                  C bit for subtraction of zero, but unfortunately it introduced
//                  C bit for subtraction of zero, but unfortunately it introduced
//                  an error such that all subtraction results were off by 1.
//                  an error such that all subtraction results were off by 1.
//                  Obviously, this was unacceptable, and I think it has been fixed
//                  Obviously, this was unacceptable, and I think it has been fixed
//                  by the new signals "c_subtract_zero" and "c_dig_subtract_zero"
//                  by the new signals "c_subtract_zero" and "c_dig_subtract_zero"
// Update: 10/24/05 Added code patches to fix interrupt bug and status flag updates
//
//                  when using literal value of 0x03.  These bugs were reported by
// Update: 23 june 2014 (Stanislav Corboot)
//                  an opencores.org user.  Added three "disable_status_x" signals.
//
//                  Modified file still needs to be tested.
//                  - Bug fixed: interrupt handler executed one and the same
// Update: 06/29/13 This project is now CC-BY licensed.  See risc16f84_license.txt
//                    instruction twice - before interruption and after it.
//                  for details.
//                  - Bug fixed: incorrect behavior of the zero flag after LITERAL
 
//                    instructions (xxxLW) if operand was equal 0x03 and if result
 
//                    equal zero.
 
//                    Example:
 
//                      movlw 0x03
 
//                      xorlw 0x03 -> WREG=0x00, ZF=0 - ERROR!
 
//                      or
 
//                      movlw 0xFD
 
//                      addlw 0x03 -> WREG=0x00, ZF=0 - ERROR!
 
//                      or
 
//                      movlw 0x00
 
//                      andlw 0x03 -> WREG=0x00, ZF=0 - ERROR!
 
//                      etc.
//
//
// Description
// Description
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// This logic module implements a small RISC microcontroller, with functions
// This logic module implements a small RISC microcontroller, with functions
// and instruction set very similar to those of the Microchip 16F84 chip.
// and instruction set very similar to those of the Microchip 16F84 chip.
Line 346... Line 358...
reg  writeram_node;       // H if destination is RAM/Special registers
reg  writeram_node;       // H if destination is RAM/Special registers
reg  c_subtract_zero;     // High for special case of C bit, when subtracting zero
reg  c_subtract_zero;     // High for special case of C bit, when subtracting zero
reg  c_dig_subtract_zero; // High for special case of C bit, when subtracting zero
reg  c_dig_subtract_zero; // High for special case of C bit, when subtracting zero
 
 
wire next_exec_stall;
wire next_exec_stall;
     // Three signals used to disable status flag updates.  Fixes bug when literal 0x03 is used.
 
wire disable_status_z;
 
wire disable_status_c;
 
wire disable_status_dc;
 
 
 
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// Instantiations
// Instantiations
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
 
 
Line 443... Line 451...
assign addr_aux_adr_hi = (ram_adr_node[7:0] == 8'b00000110); // 06H
assign addr_aux_adr_hi = (ram_adr_node[7:0] == 8'b00000110); // 06H
 
 
// construct bit-mask for logical operations and bit tests
// construct bit-mask for logical operations and bit tests
assign mask_node = 1 << inst_reg[9:7];
assign mask_node = 1 << inst_reg[9:7];
 
 
// disable write access for status flags
 
assign disable_status_z  = (inst_addwf || inst_andwf || inst_clrf  ||
 
                            inst_clrw  || inst_comf  || inst_decf  ||
 
                            inst_incf  || inst_iorwf || inst_movf  ||
 
                            inst_subwf || inst_xorwf || inst_addlw ||
 
                            inst_andlw || inst_iorlw || inst_iorlw ||
 
                            inst_sublw || inst_xorlw) ? 1:0;
 
assign disable_status_c  = (inst_addwf || inst_subwf || inst_rlf   ||
 
                            inst_rrf   || inst_addlw || inst_sublw ) ? 1:0;
 
assign disable_status_dc = (inst_addwf || inst_subwf || inst_addlw ||
 
                            inst_sublw ) ? 1:0;
 
 
 
 
 
// Create the exec_stall signal, based on the contents of the currently
// Create the exec_stall signal, based on the contents of the currently
// executing instruction (inst_reg).  next_exec_stall reflects the state
// executing instruction (inst_reg).  next_exec_stall reflects the state
// to assign to exec_stall following the conclusion of the next Q4 state.
// to assign to exec_stall following the conclusion of the next Q4 state.
// All of these instructions cause an execution stall in the next cycle
// All of these instructions cause an execution stall in the next cycle
// because they modify the program counter, and a new value is presented
// because they modify the program counter, and a new value is presented
Line 721... Line 716...
  end  // End of reset assignments
  end  // End of reset assignments
  else if (~exec_stall_reg && clk_en_i)
  else if (~exec_stall_reg && clk_en_i)
  begin   // Execution ceases during a stall cycle.
  begin   // Execution ceases during a stall cycle.
    if (state_reg == Q2_PP) // 2-3. Q2 cycle
    if (state_reg == Q2_PP) // 2-3. Q2 cycle
    begin
    begin
 
     if( ~int_condition ) // Bug fixed
 
     begin
      // 2-3-1. Read data-RAM and store values to alu-input regs
      // 2-3-1. Read data-RAM and store values to alu-input regs
      // 2-3-1-1. Set aluinp1 register (source #1)
      // 2-3-1-1. Set aluinp1 register (source #1)
      if (   inst_movf   || inst_swapf || inst_addwf || inst_subwf
      if (   inst_movf   || inst_swapf || inst_addwf || inst_subwf
          || inst_andwf  || inst_iorwf || inst_xorwf || inst_decf
          || inst_andwf  || inst_iorwf || inst_xorwf || inst_decf
          || inst_incf   || inst_rlf   || inst_rrf   || inst_bcf
          || inst_incf   || inst_rlf   || inst_rrf   || inst_bcf
Line 771... Line 768...
      // It is not known to me (John Clayton) whether any glitches would
      // It is not known to me (John Clayton) whether any glitches would
      // really occur.  It might be possible to generate these signals
      // really occur.  It might be possible to generate these signals
      // using combinational logic only, without using registers!
      // using combinational logic only, without using registers!
      ram_we_reg <= (writeram_node && addr_sram);
      ram_we_reg <= (writeram_node && addr_sram);
      aux_we_reg <= (writeram_node && addr_aux_dat);
      aux_we_reg <= (writeram_node && addr_aux_dat);
 
     end  // Bug fixed
    end   // End of Q2 state
    end   // End of Q2 state
 
 
    //---------------------------------------------------------------------
    //---------------------------------------------------------------------
 
 
    else if (state_reg == QINT_PP) // Interrupt execution (instead of Q4_PP)
    else if (state_reg == QINT_PP) // Interrupt execution (instead of Q4_PP)
Line 821... Line 819...
      // 2-5-2. Store calculation result into destination, 
      // 2-5-2. Store calculation result into destination, 
      // 2-5-2-1. Set W register
      // 2-5-2-1. Set W register
 
 
      if (writew_node) w_reg   <= aluout;    // write W reg
      if (writew_node) w_reg   <= aluout;    // write W reg
 
 
 
 
      // 2-5-2-2. Set data RAM/special registers,
      // 2-5-2-2. Set data RAM/special registers,
      if (writeram_node)
      if (writeram_node)
      begin
      begin
        if (addr_stat)
        if (addr_stat)
        begin
        begin
          status_reg[7:5] <= aluout[7:5];      // write IRP,RP1,RP0
          status_reg[7:5] <= aluout[7:5];      // write IRP,RP1,RP0
          // status(4),status(3)...unwritable, see below (/PD,/T0 part)
          // status(4),status(3)...unwritable, see below (/PD,/T0 part)
          if( ~disable_status_c ) status_reg[0] <= aluout[0]; // write C
          status_reg[1:0] <= aluout[1:0];      // write DC,C
          if( ~disable_status_dc ) status_reg[1] <= aluout[1]; // write DC
 
        end
        end
        if (addr_fsr)         fsr_reg <= aluout;       // write FSR
        if (addr_fsr)         fsr_reg <= aluout;       // write FSR
        if (addr_pclath)   pclath_reg <= aluout[4:0];  // write PCLATH
        if (addr_pclath)   pclath_reg <= aluout[4:0];  // write PCLATH
        if (addr_intcon) intcon_reg <= aluout;         // write INTCON
        if (addr_intcon) intcon_reg <= aluout;         // write INTCON
        if (addr_aux_adr_lo) aux_adr_lo_reg <= aluout; // write AUX low
        if (addr_aux_adr_lo) aux_adr_lo_reg <= aluout; // write AUX low
        if (addr_aux_adr_hi) aux_adr_hi_reg <= aluout; // write AUX high
        if (addr_aux_adr_hi) aux_adr_hi_reg <= aluout; // write AUX high
      end
      end
 
 
      // 2-5-2-3. Set/clear Z flag.
      // 2-5-2-3. Set/clear Z flag.
      if (addr_stat && ~disable_status_z) status_reg[2] <= aluout[2];
      if (addr_stat && !writew_node) status_reg[2] <= aluout[2]; // (dest. is Z flag) // Bug fixed
      else if (   inst_addlw || inst_addwf || inst_andlw || inst_andwf
      else if (   inst_addlw || inst_addwf || inst_andlw || inst_andwf
               || inst_clrf  || inst_clrw  || inst_comf  || inst_decf
               || inst_clrf  || inst_clrw  || inst_comf  || inst_decf
               || inst_incf  || inst_movf  || inst_sublw || inst_subwf
               || inst_incf  || inst_movf  || inst_sublw || inst_subwf
               || inst_xorlw || inst_xorwf || inst_iorlw || inst_iorwf )
               || inst_xorlw || inst_xorwf || inst_iorlw || inst_iorwf )
              status_reg[2] <= aluout_zero_node; // Z=1 if result == 0
              status_reg[2] <= aluout_zero_node; // Z=1 if result == 0
Line 942... Line 938...
  else if (clk_en_i && intrise && intcon_reg[4]) inte_sync_reg <= 1;
  else if (clk_en_i && intrise && intcon_reg[4]) inte_sync_reg <= 1;
end
end
 
 
// Issue an interrupt when the interrupt is present.
// Issue an interrupt when the interrupt is present.
// Also, do not issue an interrupt when there is a stall cycle coming!
// Also, do not issue an interrupt when there is a stall cycle coming!
assign int_condition = (inte_sync_reg && ~exec_stall_reg && ~next_exec_stall && intcon_reg[7]);
assign int_condition = (inte_sync_reg && ~exec_stall_reg && intcon_reg[7]);
                               // Interrupt must be pending
                               // Interrupt must be pending
                               // Next processor cycle must not be a stall
                               // Next processor cycle must not be a stall
                               // GIE bit must be set to issue interrupt
                               // GIE bit must be set to issue interrupt
 
 
// Circuit's output signals
// Circuit's output signals

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.