# Natural method for expressing horizontal microcode?

**URL:** <https://discourse.myhdl.org/t/natural-method-for-expressing-horizontal-microcode/469>\
**Category:** Support\
**Created:** [August 19, 2021, 11:07am UTC](https://discourse.myhdl.org/t/natural-method-for-expressing-horizontal-microcode/469 "2021-08-19T11:07:54Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Barleymow](https://avatars.discourse-cdn.com/v4/letter/b/a698b9/32.png) [@Barleymow](https://discourse.myhdl.org/u/Barleymow)\
**Post date:** [August 19, 2021, 11:07am UTC](https://discourse.myhdl.org/t/natural-method-for-expressing-horizontal-microcode/469/1 "2021-08-19T11:07:54Z")

</div>

Second noob question: is there a natural way, in python or myhdl, to represent a horizontal microcode ROM?

For example, is there a simple/natural way to concatenate enums for representation in each line of the the ROM (e.g. as an intbv) and then, when a line is read, to extract the individual enum fields as separate micro-opcodes for different functional elements?

---

<div class="post-metadata">

**Author:** ![josyb](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/josyb/32/5_2.png) [@josyb](https://discourse.myhdl.org/u/josyb)\
**Post date:** [August 20, 2021, 10:01pm UTC](https://discourse.myhdl.org/t/natural-method-for-expressing-horizontal-microcode/469/2 "2021-08-20T22:01:27Z")

</div>

> [@Barleymow](#):
>
> a horizontal microcode ROM

I had to look that up 🙂 ([Microprogramming](https://inst.eecs.berkeley.edu/~cs150/fa05/CLD_Supplement/chapter12/chapter12.doc5.html))  
I have done only a few simple _sequencers_ until now.  
Can you elaborate a bit more?

Regards,  
Josy

---

<div class="post-metadata">

**Author:** ![Barleymow](https://avatars.discourse-cdn.com/v4/letter/b/a698b9/32.png) [@Barleymow](https://discourse.myhdl.org/u/Barleymow)\
**Post date:** [August 21, 2021, 2:06pm UTC](https://discourse.myhdl.org/t/natural-method-for-expressing-horizontal-microcode/469/3 "2021-08-21T14:06:36Z")

</div>

Here’s a link to the [wikipedia article](https://en.wikipedia.org/wiki/Microcode), which covers horizontal and vertical microcode. In horizontal microcode the control word is a set of (usually) fixed-width fields, each of which controls a different functional block in a processor, e.g. ALU operations, status flag control, operand selection and so on. For design and debugging it’s preferable to express these operations in a human readable form (see below), which can then be compiled into the memory contents. If each field is specified using an enumerated type this should help detect errors.

However, once the control word is read from the memory, it would then be helpful to unpack the enumerations for use in each separate block.

Perhaps I’m arguing myself into modelling each line of the ROM as a list of enums, or as an object with particular enum elements, and then maybe using something else to generate a binary output for synthesis.

```auto
@block
def microcode(addr, dout):
    data = (
            ...
            mc(ABUS_REG_A, BBUS_MDR, ALU_OP_ADD, Z_FLAG_ALU...)
            ...
            )

    @always_comb
    def read_logic():
        dout.next = data[int(addr)]

    return read_logic

```

---

<div class="post-metadata">

**Author:** ![josyb](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/josyb/32/5_2.png) [@josyb](https://discourse.myhdl.org/u/josyb)\
**Post date:** [August 22, 2021, 7:40pm UTC](https://discourse.myhdl.org/t/natural-method-for-expressing-horizontal-microcode/469/4 "2021-08-22T19:40:03Z")

</div>

I have used `IntEnum` to represent that kind:

```auto
class FpOpcode(IntEnum):
    ''' a very simple-opcode machine '''
    # load immediate 8-bit value
    LDC = 0 # clears upper 24 bits
    LDI = 1 # shifts right 8 bits, then adds the 8-bit value in upper 8bits
    # register file access
    LDR = 2
    STR = 3
    # input/output
    LDO = 4
    STO = 5
    # feeding/reading the ALU
    STA = 6
    LDA = 7
    # branching, 10 bit address
    BRA = 8
    CALL = 9
    RET = 10
    # Avalon MM bus access
    LDM = 11
    STM = 12

class FpConditionCode(IntEnum):
    ''' as used in Xilinx FP IP '''
    EQ = 0x01
    Lt = 0x02
    LE = 0x03
    Gt = 0x04
    GE = 0x05
    Ne = 0x06
    NAN = 0x08
    # our extensions
    Zr = 0x0b
    NZ = 0x0c
    Always = 0x0f

...
        opcode = Signal(intbv(0)[4:])
        conditioncode = Signal(intbv(0)[4:])

...
            opcode.next = rom.RomBus.ReadData[18:14]
            conditioncode.next = rom.RomBus.ReadData[14:10]

...

                elif opcode == FpOpcode.BRA:
                    if conditioncode == FpConditionCode.Zr:
                        if accu == 0:
                            smn.next = fpsequencer_states.BRANCH
                            pcbranch.next = 1
                        else:
                            pcinc.next = 1

```

I (re-)wrote a small assembler to generate the rom-code

---

<div class="post-metadata">

**Author:** ![Barleymow](https://avatars.discourse-cdn.com/v4/letter/b/a698b9/32.png) [@Barleymow](https://discourse.myhdl.org/u/Barleymow)\
**Post date:** [August 23, 2021, 9:34am UTC](https://discourse.myhdl.org/t/natural-method-for-expressing-horizontal-microcode/469/5 "2021-08-23T09:34:34Z")

</div>

Thanks josyb. I don’t know much about IntEnum. I’ll take a look.
