Exemplo n.º 1
0
 def visit_Subst(self, node):
     left = self.visit(node.left)
     right = self.visit(node.right)
     ldelay = vast.DelayStatement(self.visit(
         node.ldelay)) if node.ldelay else None
     rdelay = vast.DelayStatement(self.visit(
         node.rdelay)) if node.rdelay else None
     lvalue = vast.Lvalue(left)
     rvalue = vast.Rvalue(right)
     return vast.BlockingSubstitution(lvalue, rvalue, ldelay, rdelay)
Exemplo n.º 2
0
def lower_fsm(fsm: FSM):
    assert fsm.start_state == 0, "Starting state is not 0"
    zero = vast.IntConst(0)
    all_registers = [
        Register("a", 8),
        Register("b", 8),
        Register("tmp", 8),
        Register("_cond", 1),
    ]
    register_defs = [
        vast.Reg(
            reg.name,
            vast.Width(vast.IntConst(reg.width -
                                     1), zero) if reg.width - 1 != 0 else None)
        for reg in all_registers
    ]

    ports = vast.Portlist([
        vast.Ioport(vast.Input('clk')),
        # XXX(rachit): AST can't represent `output reg done`
        # so assign to a local register and use a wire.
        vast.Ioport(vast.Output('done')),
    ])
    done_state = max(fsm.actions.keys()) + 1
    done_reg = vast.Reg('done_out')
    hook_up_done = vast.Assign(
        vast.Lvalue(vast.Identifier('done')),
        vast.Rvalue(vast.Identifier('done_out')),
    )

    # Register to store the FSM state.
    fsm_reg_size = int(math.ceil(math.log2(done_state))) + 1
    fsm_reg = vast.Reg(name="fsm_reg",
                       width=vast.Width(vast.IntConst(fsm_reg_size - 1), zero))

    # Define all the registers.
    reg_decl = register_defs + [fsm_reg]

    # Define the initial process
    inits = vast.Initial(
        vast.Block([
            vast.BlockingSubstitution(
                vast.Lvalue(vast.Identifier(reg.name)),
                vast.Rvalue(vast.IntConst(0)),
            ) for reg in reg_decl
        ]))

    # Default case, assigns to the done register.
    done = vast.IntConst(done_state)
    default_case = vast.Case(cond=None,
                             statement=vast.Block([
                                 vast.NonblockingSubstitution(
                                     vast.Lvalue(vast.Identifier(reg.name)),
                                     vast.Rvalue(vast.Identifier(reg.name)),
                                 ) for reg in reg_decl
                             ] + [
                                 vast.NonblockingSubstitution(
                                     vast.Lvalue(vast.Identifier('done_out')),
                                     vast.Rvalue(vast.IntConst(1)))
                             ]))

    # Generate Case conditions for each transition.
    cases = [
        vast.Case([vast.IntConst(cond_val)],
                  lower_action(fsm_reg, done, action))
        for (cond_val, action) in fsm.actions.items()
    ]
    case_statement = vast.CaseStatement(comp=vast.Identifier(fsm_reg.name),
                                        caselist=cases + [default_case])
    always_ff = vast.Always(
        vast.SensList([vast.Sens(vast.Identifier('clk'), 'posedge')]),
        vast.Block([case_statement]))

    return vast.ModuleDef(name="main",
                          paramlist=vast.Paramlist([]),
                          portlist=ports,
                          items=reg_decl +
                          [done_reg, hook_up_done, inits, always_ff])