================================ PicoBlaze architecture reference ================================ This is an overview of the architecture and assembly language used for the PicoBlaze-6 and PicoBlaze-3 microcontrollers. Instructions ------------ The following instruction mnemonics are used in the PicoBlaze processors: .. rubric:: PicoBlaze-3 and PicoBlaze-6 =========== =========== =========== =========== =========== `add`_ `addcy`_ `and`_ `call`_ `compare`_ `disable`_ `enable`_ `fetch`_ `input`_ `jump`_ `load`_ `or`_ `output`_ `return`_ `returni`_ `rl`_ `rr`_ `sl0`_ `sl1`_ `sla`_ `slx`_ `sr0`_ `sr1`_ `sra`_ `srx`_ `store`_ `sub`_ `subcy`_ `test`_ `xor`_ =========== =========== =========== =========== =========== .. _inst-pb6: .. rubric:: PicoBlaze-6 only =========== ============ =========== =========== ============== `call@`_ `comparecy`_ `hwbuild`_ `jump@`_ `load&return`_ `outputk`_ `regbank`_ `star`_ `testcy`_ =========== ============ =========== =========== ============== .. rubric:: Common directives =============== =========== =========== =========== =========== `address`_ `constant`_ `namereg`_ `include`_ `inst`_ `default_jump`_ =============== =========== =========== =========== =========== The Xilinx PicoBlaze-3 assembler only supports the ``address``, ``constant``, and ``namereg`` directives. .. rubric:: PicoBlaze-6 directives ========== =========== `string`_ `table`_ ========== =========== The assembler is case insensitive for commands. Uppercase or mixed case mnemonics can also be used. Labels and renamed registers are case sensitive. Instruction formats ------------------- PicoBlaze assembly follows the usual convention of having a single instruction or directive per line. An optional label creates a named reference that can be referred to by other instructions. An optional single line comment can appear at the end prefixed by a ";" character. Basic syntax .. image:: ../images/statement.svg Blank lines are ignored. Labels and comments can be used without an instruction. Instructions generally use the following formats with a few minor exceptions: Register .. image:: ../images/register.svg Immediate .. image:: ../images/immediate.svg Indirect scratchpad / I/O port .. image:: ../images/indirect_sp.svg Indirect jump / call .. image:: ../images/indirect_jump.svg Conditional .. image:: ../images/conditional.svg Outputk .. image:: ../images/outputk.svg The fields have the following meanings: ================== ================================================================================ ```` Instruction mnemonic or directive ```` One of the 16 currently active registers (s0-sF) ```` Constant literal (hex [nn], decimal [nnn'd], binary [nnnnnnnn'b], or char ["c"]) ================== ================================================================================ Literal syntax -------------- The language supports a number of different formats for representing literal values. These are constant numeric and character values that are used as operands to many instructions. Hexadecimal A hex byte is the default format for literal numbers. It is represented by two hex digits with no additional syntactic marker. The :ref:`inst-address` directive takes a special 12-bit hex literal as an address. Decimal Decimal byte values are written in the form ``nnn'd``. Binary Binary byte values are written in the form ``nnnnnnnn'b``. Characters Printable ASCII character literals are written in the form ``"c"``. You can invert the value of a literal by prefixing it with "~". .. code-block:: picoblaze load s0, 50 load s1, ~50 ; Same as 0xAF ; This is useful for inverting mask constants: constant BIT_FIELD_MASK, 31 or s0, BIT_FIELD_MASK ; Set bits in the mask and s0, ~BIT_FIELD_MASK ; Clear bits in the mask There are predefined character constants for the following ASCII control characters: ==== ==== ==== ==== NUL BEL BS HT LF VT CR ESC DEL DCS ST ==== ==== ==== ==== .. code-block:: picoblaze load s0, CR output s0, COM_PORT load s0, LF output s0, COM_PORT There are additional special constants containing the date and time the code was assembled: * timestamp_hours * timestamp_minutes * timestamp_seconds * datestamp_year (two digit year from 00 - 99) * datestamp_month * datestamp_day You can access environment variables by prefixing their name with "%". They must evaluate to a valid PicoBlaze literal. .. code-block:: picoblaze ; You could have a build script generating different images ; for multiple PicoBlaze instances. Their behavior could ; be controlled by an environment variable "PROC_NUM". load s0, %PROC_NUM compare s0, 00 jump Z, proc_0 ; Branch to special code for processor 0 ; Remaining processors here .. note:: The Opbasm command line option ``--define=NAME[=VALUE]`` can be used in conjunction with the m4 preprocesor as another way to :ref:`alter code generation at build time `. Address spaces -------------- The PicoBlaze has a simple architecture that operates on information stored in the following address spaces: Registers A set of 16 8-bit registers. They default to the registers named s0-sF but can be renamed with the :ref:`inst-namereg` directive. The PicoBlaze-3 has a single bank of registers. PicoBlaze-6 has a second bank of 16 (bank B) that can be swapped in or out using the :ref:`inst-regbank` instruction. The default register names are case-insensitive so "SA", "sa", "Sa", and "sA" are all valid and refer to the same register. All register values, flags, and the call stack are initialized to 0 on initial FPGA power up but the registers retain their values on subsequent resets. Your code should not assume registers are cleared after a reset. Instruction memory Instruction words are stored in an isolated memory. It is limited to 1K on PicoBlaze-3 and selectable between 1K, 2K, or 4K on PicoBlaze-6. You can also use smaller memories for instruction storage if you don't need to use the full address space. This memory is implemented outside the PicoBlaze core component and attached to the instruction memory port. Because the PicoBlaze is a Harvard architecture micro, this memory is not directly accessible from within your program. However, a dual ported memory can be implemented to access data stored in instruction memory or to modify instructions through the I/O port interface. Scratchpad memory A small pool of RAM used as a local memory. This is 64 bytes on the PicoBlaze-3 and configurable for 64, 128, or 256 bytes on PicoBlaze-6. This memory is accessed with the `fetch`_ and `store`_ instructions. I/O ports A set of 256 input and 256 output ports are used to interact with external hardware. These ports are accessed with the `input`_ and `output`_ instructions. Additional logic must be provided to decode these ports. Outputk ports The PicoBlaze-6 has a special set of 16 output ports intended for directly driving constant values with minimal overhead. This is accessed with the `outputk`_ instruction. Call stack A hardware call stack is maintained to track return addresses for subroutines and the interrupt handler. You can have a call depth of up to 31 subroutines on PicoBlaze-3 and 30 subroutines on PicoBlaze-6. On PB3 the stack will silently roll over if you exceed the limit. On PB6 it will detect the overflow and generate an internal reset, restarting the program from address 0x000. Flags ----- The PicoBlaze processor has two internal status flags that represent metadata from ALU operations. They are used to evaluate the result of an operation and execute conditional code. These are the the zero "Z" flag and the carry "C" flag. The Z flag is set when the result of an operation is zero and cleared otherwise. The C flag is set when an arithmetic carry or borrow (for subtraction) is generated. As a special case, the C flag is set by the :ref:`inst-test` and :ref:`inst-testcy` instructions to reflect the odd parity of their result. The :ref:`inst-hwbuild` instruction always sets the C flag unconditionally. The most common application of the flags is to execute conditional code after a :ref:`inst-compare` instruction. The table shown for ``compare`` indicates how to interpret the flags for various Boolean comparison operations. Not all comparisons are possible with a single instruction because PicoBlaze can only test one flag at a time. The `return`_ and `jump`_ have a conditional form where the first operand is a flag value of C, NC, Z, or NZ. When it is C or Z whese instructions conditionally return or jump when the respective flag is set. for NC and NZ, the branch is taken when the flag is clear. Interrupts ---------- The PicoBlaze has a single ``interrupt`` input. When interrupts are enabled and this pin transitions high, the normal execution is suspended and the processor jumps to a special interrupt handler routine. This behavior lets your code respond to external events in the FPGA fabric without having to explicitly poll for changes in state. Handling multiple interrupts requires external logic to multiplex them onto the single input provided by the PicoBlaze. The PB3 has a fixed interrupt vector address of 0x3FF which is the last instruction in the 1K instruction memory space. You must insert a `jump`_ instruction here that branches to your ISR code. The PB6 defaults to 0x3FF as its default vector but you can change it to a different address with the ``interrupt_vector`` generic on the ``KCPSM6`` component. This gives you the option to place the vector at the start of your ISR without the need for an extra ``jump``. The ``interrupt`` signal should stay high for at least two clock cycles to guarantee it is seen by the processor. An optional ``interrupt_ack`` output signal is provided to interface with external interrupt generating logic. It notifies you when the processor has started processing the interrupt, at which point it is safe to release the ``interrupt`` input signal. Interrupts are controlled with the `enable`_ and `disable`_ instructions. They take a special dummy operand of "interrupt". A special `returni`_ instruction is used to exit from the ISR and resume normal execution. It takes an operand of "enable" or"disable" to set the new state of the interrupt flag after the return. You cannot use the normal `return`_ instruction to accomplish this since the original interrupt saved the flag and register bank state and only ``returni`` can restore it so that your normal code remains unaffected by the change of execution state. Directives ---------- The following are the assembler directives used by Opbasm. These are special keywords used in place of machine instructions. They do not produce any code directly but are instead used to alter the behavior of the assembler. .. _inst-address: address ~~~~~~~ The ``address`` directive is used to change the address where the next instruction will be assembled to. ===================================== ================= ======================================== Format Example Result ===================================== ================= ======================================== ``address
`` address 3FF The instruction offset is moved to 0x3FF ``address