Реализация логических вентилей Nor Flip Flop в Go

Я пытаюсь реализовать следующую логику схемы без триггера в Go и испытываю некоторые трудности с объявлениями переменных:

введите описание изображения здесь

Моя цель - смоделировать логические вентили и схемы так, как если бы они работали физически. Я реализовал функцию для ворот nor [func nor ()] и самого триггера [func norFlipFlop ()]. Проблема, с которой я столкнулся, заключается в объявлении out0 и out1, поскольку они зависят друг от друга. Как видно ниже, out0 определяется как nor (a1, out1), а out1 определяется как nor (out0, a0). Это, очевидно, вызывает ошибку компиляции, поскольку out1 еще не инициализирован и не определен, когда определен out0. Есть ли способ заставить эту логику работать, максимально приближая ее к логике физической схемы?

func nor(a int, b int) int {
    if a + b == 0 {
        return 1
    } else {
        return 0
    }
}   

func norFlipFlop(a1 int, a0 int) (int, int) {
    out0 := nor(a1, out1)
    out1 := nor(out0, a0)
    return out1, out0
}

func main() {
    out1, out0 := norFlipFlip(1, 1)
    out := fmt.Sprint(out1, out0)
    fmt.Println(out)
}

person RogueKnight    schedule 23.05.2020    source источник
comment
По какой причине вы используете int, а не bool?   -  person Andrew W. Phillips    schedule 23.05.2020
comment
Нисколько. Это была чистая оплошность, и я, вероятно, собираюсь преобразовать ее в код для использования bools. Я считаю, что это приведет к тем же проблемам из-за зависимостей.   -  person RogueKnight    schedule 23.05.2020


Ответы (1)


Во-первых, триггер сохраняет состояние, поэтому вам нужно какое-то значение, чтобы сохранить это состояние. Кроме того, помимо условия (обычно избегаемого на оборудовании), когда A0 и A1 равны 0 (ложь), а Out0 и Out1 оба равны 1 (истина), выходы (Out0 и Out1) обычно дополняют друг друга и фактически являются триггером. хранит только одно логическое значение, поэтому вы можете просто использовать bool. Обычно вы «пульсируете» входы, чтобы установить (сделать истинным) или сбросить (сделать ложным) значение триггера. Например:

package main

import "fmt"

type flipFlop bool

func (ff flipFlop)GetOut0() bool {
    return bool(ff)
}

func (ff flipFlop)GetOut1() bool {
    return !bool(ff)
}

func (ff *flipFlop)PulseA0() {
    *ff = true
}

func (ff *flipFlop)PulseA1() {
    *ff = false
}

func main() {
    var ff flipFlop
    ff.PulseA0()
    fmt.Println(ff.GetOut0(), ff.GetOut1())
    ff.PulseA1()
    fmt.Println(ff.GetOut0(), ff.GetOut1())
}

Если вы хотите более точно моделировать оборудование, вам необходимо отслеживать его состояния. Может быть, примерно так:

package main

import "fmt"

type flipFlop struct {
    A0, A1 bool
    out0, out1 bool
}

func nor(a, b bool) bool { return !(a || b) }

func (ff *flipFlop)Eval() {
    // Evaluate the circuit until it is stable
    for {
        prev0, prev1 := ff.out0, ff.out1
        ff.out0 = nor(ff.A1, ff.out1)
        ff.out1 = nor(ff.A0, ff.out0)
        if ff.out0 == prev0 && ff.out1 == prev1 {
            break // flip flop is stable
        }
    }
}

func main() {
    var ff flipFlop
    fmt.Println(ff)

    // Pulse a0
    ff.A0 = true
    ff.Eval()
    fmt.Println(ff)
    ff.A0 = false
    ff.Eval()
    fmt.Println(ff)

    // Pulse a1
    ff.A1 = true
    ff.Eval()
    fmt.Println(ff)
    ff.A1 = false
    ff.Eval()
    fmt.Println(ff)
}

Надеюсь, это поможет (кстати, я не инженер-электронщик :).

person Andrew W. Phillips    schedule 23.05.2020
comment
Это действительно полезно, и я очень ценю это! Позвольте мне поиграться с этим и расскажу, как это происходит. - person RogueKnight; 23.05.2020
comment
Мне удалось заставить его работать с вашим решением. Спасибо за помощь! Я занимаюсь имитацией простого 8-битного процессора, который я проектировал на Go. Я, вероятно, открою исходный код и поделюсь им, как только у меня будет больше работать. Я очень ценю помощь! Спасибо! - person RogueKnight; 24.05.2020