sporniket / amaranth-stuff

My collection of reusable code written using the amaranth hdl
GNU Lesser General Public License v3.0
1 stars 0 forks source link

[epic] a design of a micro sequencer #60

Open sporniket opened 8 months ago

sporniket commented 8 months ago

Overview

A micro sequencer is a programmable unit that outputs a set of signals by following a program. As such, it implements an execution loop that involves :

in pseudo code :

let program_counter = 0
let ok = true
let feedbacks = [] // a collection of input

// utility -- assess whether the program_counter must be set
function requiresFlowControl(instruction, feedbacks) {
  if (/* some conditions are met*/) {
    return true
  } else {
    return false
  }
}

// utility -- extract the next value of program_counter from the given instruction
function decodeFlowControl(instruction) {
  return /*a value to be the new program counter*/
}

while(ok) {
  let next_instruction = Program.fetch(program_counter)
  Output.update(next_instruction)
  Input.update(feedbacks)
  if(requiresFlowControl(next_instruction, feedbacks)) {
    program_counter = decodeFlowControl(next_instruction)
  } else { 
    program_counter = program_counter + 1
  }
} 
sporniket commented 8 months ago

Principles of the design

The micro sequencer will be designed as the collaboration of several actors in a looping chain :

Thus the chain of collaboration is : uCounteruProgramuDecoderuSynchronizeruCounter ⇒ ...

Power on startup

In order to boot the chain of collaboration, there will be a Start Unit : uStart will wait a little time at power on reset, then tell uProgram to fetch the first instruction (uCounter starts at 0), initiating the chain.

Watchdog

The chain MAY be stuck when uSynchronizer is waiting for a given feedback before sending instruction to uCounter and that feedbacks is late. A Watchdog Unit, uWatcher will monitor uSynchronizer at the sign of uDecoder. If uSynchronizer is taking too much time, uWatcher interrupt it and instruct uCounter to jump to an error routine. The error routine MAY be changed by the decoder following a specific instruction.

sporniket commented 7 months ago

Shortcuts ideas

The nominal chain of collaboration is : uCounter ⇒ uProgram ⇒ uDecoder ⇒ uSynchronizer ⇒ uCounter ⇒ ...

Meaning that two micro-instructions are at least 4 cycles apart.

When there is no branching, the counter could already be incremented, and the program unit could then already output the next micro-instruction, so that the decoder can consume it any time.

The happy case would then be :

Clock This micro-instruction Next micro-instruction
0 uCounter→uProgram
1 uProgram→uDecoder uCounter++→uCounter
2 uDecoder→uSynchronizer uCounter→uProgram
3 uSynchronizer→uCounter uProgram→uDecoder
4 uDecoder→uSynchronizer

Meaning that two micro instructions may be only 2 cycles aparts when there is no branching.

The uCounter may always update to the next value (uCounter + 1) after the cycle where it notify uProgram to latch the value.

Then one cycle later, it notifies uProgram to fetch the next micro-instruction.

Then it is up to uDecoder to assess whether there is branching (conditionnal or unconditionnal) or waiting (requires uSynchronizer). When there is no branching nor waiting, uDecoder MUST notify uProgram that it is ready.

The flow becomes more complex. (to come)