Home     Contact     Projects     Experiments     Circuits     Theory     BLOG     PIC Tutorials     Time for Science     RSS     Terms of services     Privacy policy  
   
 Home      Projects     Experiments     Circuits     Theory     BLOG     PIC Tutorials     Time for Science   



Instruction Cycle Duration and Calculated Delays

What is the relationship between the oscillator frequency of the PIC and the instruction cycle duration? In this page we will discuss about this very important subject.




4 pulses = 1 operation

When designing a PIC project, the first thing to consider is the oscillation clock source and frequency of the PIC. In later chapters we will discuss the different clock sources. Until then, the only thing you need to know is that the no matter which input is selected (internal oscillator or external XTAL / RC circuit), we will refer to this input generally as "Clock Input", and the pulses from the Clock Input as "Clock Pulses".

The PIC will internally divide the clock input frequency by 4, in order to execute the program instructions. We will name these 4 pulses Q1 through Q4. The Program Counter (more info about the Program Counter) will be increased on every Q1. During these 4 clock pulses, the PIC will fetch the instruction that the updated Program Counter indicates, and simultaneously it will execute the instruction that was fetched during the PREVIOUS Q1-Q4 pulses! This is something that you will probably will never have to deal with, and that will never cause you any further frustration more than understanding how the PIC works. So, look at the following timing chart:





It is clear that the PC (Program Counter) is increased ONCE every 4 clock pulses. This means that every 4 clock cycles, an instruction is executed. But you may also notice, that, for example, in order to execute the instruction in PC position = n+1, the PIC will need 8 clock pulses! During the first 4 pulses, it will fetch the instruction, and during the other 4 pulses it will execute it. This means that the PC will be increased 2 times, but only one instruction will be executed, right? WRONG! This would only happen during the very first instruction that the PIC will execute immediately after the power on. Due to the fact that during Q1-Q4 the PIC does 2 jobs simultaneously (fetch new instruction and execute previous instruction), on every PC increment (4 Clock Pulses) one instruction is executed, or better say that on every PC increment, on operation is carried out.




4 pulses = 1 operation, 1 operation = 1 instruction execution???

The sub-title is of course a rhetorical question. Unfortunately, not all instructions are executed in a single operation (4 clock pulses). There are two categories of instructions that require 2 instruction executions in order to be fulfilled. The first category and most straight-forward to understand contains all the instructions that have a conditional branch. These are the BTFSS, BTFSC, DECSZ and INCSZ (more info for the instructions here). But how is a conditional branch handled from the PIC? Let's see an example with BTFSS instruction:



          BSF Zero    ;We set the Zero Flag
          BTFSS Zero  ;If Zero is SET, then SKIP the next instruction
          {AN INSTRUCTION}


What will happen? On the first instruction, we SET the Zero flag. On the next instruction, we check if the Zero flag is set. The BTFSS means Skip If Set, thus, the following instruction will NOT be executed, as the Zero flag is SET. As a matter of fact, the PIC will NOT jump the following instruction. Instead, it will temporarily convert it into the NOP and will be executed as NOP. In this case, the BTFSS instruction must be calculated as a 2-Cycles instruction, and the instruction that follows the BTFSS must NOT be taken into account! Now look at the following example:



          BCF Zero    ;We set the Zero Flag
          BTFSS Zero  ;If Zero is SET, then SKIP the next instruction
          {AN INSTRUCTION}


This example is the same as the previous one, but now we have CLEAR the Zero flag. The instructions that follows the BTFSS instruction will be executed normally! In this case, the BTFSS instruction must be calculated as an 1-Cycle instruction, and the following instruction must be taken into account accordingly. In other words, the conditional branching instructions may need 1 or 2 instructions cycles to be executed, according to the condition result. This is something that you need to pay attention when calculating the instruction cycles required for a subroutine.

The second category with instructions that needs more than 1 cycle to be executed, contains all the instructions that will force the PC to change. These are the GOTO instruction, the CALL and the RETURN (including RETLW and RETFIE). But why does this happen? Well, if you have read and understood the first paragraph (4 pulses = 1 operation), then it will be easy to understand why. In this paragraph i explained that during the very first instruction execution of the program immediately after a power-on, the PIC will require 2 instruction cycles. That is true, but not complete. Whenever the PC is forced (with a GOTO/CALL/RETURN instruction) to change. the PIC will need 2 cycles to execute this instruction. And why is that? Suppose we have this part of code to examine:



          BSF Zero
          MOVLW 0xFF
          GOTO Label_1
          MOVLW b'01010101'
          .
          .
          .
Label_1   MOVWF PORTA
          .
          .
          .



When the PC is on the "MOVLW 0xFF" instruction (line 2), the PIC will execute the "BSF Zero" instruction and will load the "MOVLW 0xFF". On the next instruction cycle, the PC will indicate the "GOTO Label_1" instruction. The PIC will execute the "MOVLW 0xFF" and will fetch the "GOTO Label_1". Here is the interesting part. On the next instruction execution, the PC will indicate the "MOVLW b'01010101'" instruction, and the PIC will execute the "GOTO Label_1" instruction and will fetch the "MOVLW b'01010101'" instruction. On the next instruction cycle, the PC will indicate the instruction right after Label_1, as instructed before from the "GOTO Label_1" instruction. But it will NOT execute the already-fetched instruction, as it is the instruction right after the "GOTO Label_1"! That would be wrong! So, the execution is omitted! The execution of the instructions is then carried out normally by increasing the PC, fetching the new instruction and executing the "MOVWF PORTA" instruction. This execution-cancellation that follows the GOTO command is the reason why such commands requires 2 instruction cycles to be fulfilled.

The following table indicates the cycles required from each instruction to be executed:

Instruction Cycles
BTFSS 1 or 2
BTFSC 1 or 2
INCFSZ 1 or 2
DECFSZ 1 or 2
GOTO Always 2
CALL Always 2
RETURN Always 2
RETLW Always 2
RETFIE Always 2

All other will require 1 instruction cycle to be executed.




An example - Calculate an 1 mSec delay subroutine

Let's make a real-life example subroutine. This subroutine, will generate an 1 mSec delay. The PIC operates with a 4 MHz clock input. This means that each instruction cycle is executed with 1MHz frequency, in other words, once every 1uSec. So, we need to call a subroutine that will execute 1000 instructions, in order to achieve the 1 mSec delay. Look at the following subroutine:




Delay_1_mSec
          MOVLW d'250'
Delay_Loop
          ADDLW 0xFF       ; Decrease W by 1
          BTFSS Zero       ; Is the Zero flag Set?
          GOTO Delay_Loop  ; - NO. Goto back
          
          RETURN


The Delay_Loop is composed by 3 instructions, the "ADDLW 0xFF" with 1 cycle duration, the "BTFSS Zero" with 1 cycle duration (as long as W is not 0), and the "GOTO Delay_Loop" with 2 cycles duration. Adding them we have 4 cycles. This loop will be executed 250 times, as the W has the decimal value "250". So, 250 x 4 = 1000! This loop will generate 1000 uSec (that is 1 mSec) delay on each CALL.

Here comes some further considerations. The overall delay of the subroutine will NOT be 1000 cycles exactly. It will be precisely 1002 cycles. First of all, we need to add the "MOVLW d'250'" that has 1 cycle length. The loop has 4 cycles overall delay, EXCEPT the last time it loops, that the W wil lbe zero and the "GOTO Delay_Loop" will be replaced with a "NOP" instruction. It will then have 3 cycles overall delay. So, the loop has exactly 249 x 4 + 3 cycles, that is 999 cycles. And finally, we need to add 2 cycles for the return instruction. So we have, 1 + 999 + 2 = 1002 cycles. If someone measures also the 2 cycles from the "CALL Delay_1_mSec" instruction, we have a total of 1004 cycles. How can we fix this? Very easy. I will call the loop (that has 4 cycles duration) one time less:




Delay_1_mSec
          MOVLW d'249'
Delay_Loop
          ADDLW 0xFF       ; Decrease W by 1
          BTFSS Zero       ; Is the Zero flag Set?
          GOTO Delay_Loop  ; - NO. Goto back
          
          RETURN


Now we have: 248 x 4 + 3 = 995 cycles from the loop, +1 from the "MOVLW d'249'" = 996, +2 from the "RETURN" = 998, +2 from the "CALL Delay_1_mSec", this makes it exactly 1000 instructions!







Confirm your knowledge

There is an online test to check your knowledge on this page. You may reveal the test with the following button:






Previous page ---- Next page



Go back to the book contents

Go to the discussion forum of this book





 

Comments

  Name

  Email (shall not be published)

  Website

Notify me of new posts via email


Write your comments below:
BEFORE you post a comment:You are welcome to comment for corrections and suggestions on this page. But if you have questions please use the forum instead to post it. Thank you.


      

  • At 17 October 2014, 18:12:07 user Fung wrote:   [reply @ Fung]
    • @Giorgos Lazaridis I am surprised that you still remember me! :)
      Referring to your explanation, it should be applicable to other instructions, right? I wrote some IF-statements which would be executed in interrupt and they must be balanced (same execution time for true or false), for example:

      if(abc){ //check if "abc" is set
      timerA ;
      timerB=0;
      def=1; //set bit "def"
      }
      else{Delay_us(3);} //otherwise 3us delay

      Assume "timerA" and "timerB" are unsigned short (8-bit), "abc" and "def" are bit flags in a register "ABCD", if this code is compiled under 4MHz configuration:

      True-side in asm
      INCF timerA,1
      CLRF timerB
      BSF ABCD,1 ;assume "def" at bit 1

      False-side in asm
      NOP
      NOP
      NOP

      The execution time in both sides should be the same, 1us for increment timerA, 1us for clearing timerB and 1us for setting "def".

      However if it is compiled under 20MHz configuration, the False-side "Delay_us(3)" would produce 15 NOP's or something equivalent to produce 3us. For the True-side, is it 600ns instead?


  • At 17 October 2014, 17:14:13 user Giorgos Lazaridis wrote:   [reply @ Giorgos Lazaridis]
    • @Fung Fung long time haven't seen you and as i see you are going well into microcontrollers! GJ! So, Here is how to calculate. Each instructions (say a NOP) reauires 4 clock ticks. So start your calculations always by dividing the clock by 4. At 4MHz calculate the delay as if it was 1MHz. Then convert the frequency (Hertz) to period (Sec) by inverting:
      1MHz = 1.000.000Hz = 1/1.000.000 Sec = 0.000001 Sec = 1uSec
      at 20MHz calculate for 20/4 = 5MHz
      5MHz = 5.000.000Hz = 1/5.000.000 Sec = 0.0000002 Sec = 0.2uSec

      So, with 4MHz each instruction delays 1uSec. At 20MHz each instruction delays 0.2uSec. To achieve 1uSec at 20MHz you need 5 instructions, hence 5 times NOP...


  • At 17 October 2014, 16:29:25 user Fung wrote:   [reply @ Fung]
    • I am little bit confused about NOP's...

      In most of the examples they use 4MHz as MCU clock, so an NOP is expected to be 1 microsecond.

      I use C to write PIC programs, for a one microsecond delay it can be written as "Delay_us(1)". However when it is compiled, reading the output asm file...

      Under 4MHz:
      NOP ;1us

      Under 20MHz:
      NOP
      NOP
      NOP
      NOP
      NOP

      Is that mean each NOP runs for 200ns under 20MHz clock?


  • At 4 June 2013, 9:24:13 user Kenny wrote:   [reply @ Kenny]
    • Nice information! But the following is confusing to the reader:
      "But you may also notice, that, for example, in order to execute the instruction in PC position = n 1, the PIC will need 8 clock pulses!"
      It is confusing because it was already mentioned that an instruction is executed in 4 pulses. And then, all of a sudden, you start talking about executing an instruction in 8 pulses. This is conflicting information, and confusing.


  • At 15 July 2011, 19:32:52 user Kammenos wrote:   [reply @ Kammenos]
    • @rovasi yes you are correct, it can be compensated this way


  • At 14 July 2011, 11:30:12 user rovasi wrote:   [reply @ rovasi]
    • Hello, according to my knowledge you need to add an NOP after
      GOTO instruction to compensate the time when the GOTO instruction
      is skiped


  • At 17 October 2010, 8:15:49 user Kammenos wrote:   [reply @ Kammenos]
    • correct.


  • At 16 October 2010, 11:33:12 user BC Pang wrote:   [reply @ BC Pang]
    • Hello,

      I think you can not decrease W by "sublw 0x01" because "sublw" always substracts w from literal.

      Maybe you should "addlw 0xFF" to decrease W.

      Best Regards.
     






    No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise without the prior written permission of the author.

    Read the Disclaimer


    All trademarks used are properties of their respective owners.
    Copyright © 2007-2009 Lazaridis Giorgos.
    All rights reserved.






     HOT in heaven!


  • Disclaimer
  • Book Contents
  • Discussion forum

  • Basics
  • What will you need
  • Choosing the right PIC
  • The MPLAB
  • Getting familiar with the MPLAB environment
  • Creating a new project
  • Open and close projects
  • Creating new files and including them in the project
  • Your very first assembly program
  • Compile a program and transfer to the PIC
  • Section 1: Beginner's theory
  • Memory Organization
  • The Data Memory Organization
  • The Program Memory Organization
  • The instructions
  • General knowledge about instructions
  • Value Loading Instructions
  • Program Flow Instructions
  • Mathematic Instructions
  • Logic Function Instructions
  • Bit Orientated Instructions
  • Byte Orientated Instructions
  • Miscellaneous Instructions
  • The Basic Special Function Registers
  • The Status Register
  • The Option_Reg Register
  • The TRIS and PORT registers
  • Beginner's PIC Tutorials
  • How to use our PIC Tutorials
  • A Pushbutton turning an LED on and off
  • A Simple LED Flasher
  • Interfacing Multiple Switches - The internal Pull-Up resistors
  • An LED Sequencer
  • Interface a Single 7seg Digit
  • Interface Multiple 7seg Digits
  • A 3-digits Decimal Counter
  • A Clever Button
  • Section 2: Intermediate theory
  • Instruction Cycle Duration and Calculated Delays
  • The Timer Modules - Timer0
  • The Timer Modules - Timer1
  • The Timer Modules-Timer2



  • NEW in heaven!



    New Theory: AC electric motor working principle






     Contact     Forum     Projects     Experiments     Circuits     Theory     BLOG     PIC Tutorials     Time for Science     RSS   

    Site design: Giorgos Lazaridis
    © Copyright 2008
    Please read the Terms of services and the Privacy policy