Неизвестное значение во время симуляции Перенос просмотра вперед с помощью CMOS

Я новичок в Verilog.
Мне поручили написать 4-битный CLA с использованием примитивов pmos и nmos.
Я нашел веб-сайт со схемой: Design of VLSI Systems
CLA находится на уровне 6.5.3. Я использую статическую реализацию.
Начав со схемы для провода c4, я разработал еще 3 схемы для расчета значений проводов c1, c2 и c3.
Я вставляю свой код:

module carryCMOS(a, b, c_in, sum, c_out);
    // variables
    input [3:0] a, b;
    input c_in;
    output [3:0] sum;
    output c_out;

    // VDD and GND
    supply1 vdd;
    supply0 gnd;

    // internal wires
    wire g0, g1, g2, g3;
    wire p0, p1, p2, p3;
    wire c1, c2, c3, c4;

    // for wire c4
    wire pw_c41, pw_c42, pw_c43, pw_c44;
    wire nw_c41, nw_c42, nw_c43, nw_c44;

    // for wire c3
    wire pw_c31, pw_c32, pw_c33;
    wire nw_c31, nw_c32, nw_c33;

    // for wire c2
    wire pw_c21, pw_c22;
    wire nw_c21, nw_c22;

    // for wire c1
    wire pw_c11;
    wire nw_c11;

    // carry look ahead formulas
    assign g0 = a[0] & b[0];
    assign g1 = a[1] & b[1];
    assign g2 = a[2] & b[2];
    assign g3 = a[3] & b[3];

    assign p0 = a[0] ^ b[0];
    assign p1 = a[1] ^ b[1];
    assign p2 = a[2] ^ b[2];
    assign p3 = a[3] ^ b[3];

    // c4
    pmos pm1_c4(c4, vdd, p3);
    pmos pm2_c4(c4, pw_c41, p2);
    pmos pm3_c4(c4, pw_c42, p1);
    pmos pm4_c4(c4, pw_c43, p0);
    pmos pm5_c4(pw_c41, vdd, g3);
    pmos pm6_c4(pw_c42, pw_c41, g2);
    pmos pm7_c4(pw_c43, pw_c42, g1);
    pmos pm8_c4(pw_c44, pw_c43, g0);
    pmos pm9_c4(c4, pw_c44, c_in);

    nmos nm1_c4(c4, gnd, g3);
    nmos nm2_c4(c4, nw_c41, g2);
    nmos nm3_c4(c4, nw_c42, g1);
    nmos nm4_c4(c4, nw_c43, g0);
    nmos nm5_c4(nw_c41, gnd, p3);
    nmos nm6_c4(nw_c42, nw_c41, p2);
    nmos nm7_c4(nw_c43, nw_c42, p1);
    nmos nm8_c4(nw_c44, nw_c43, p0);
    nmos nm9_c4(c4, nw_c44, c_in);

    // c3
    pmos pm1_c3(c3, vdd, p2);
    pmos pm2_c3(c3, pw_c31, p1);
    pmos pm3_c3(c3, pw_c32, p0);
    pmos pm4_c3(pw_c31, vdd, g2);
    pmos pm5_c3(pw_c32, pw_c31, g1);
    pmos pm6_c3(pw_c33, pw_c32, g0);
    pmos pm7_c3(c3, pw_c33, c_in);

    nmos nm1_c3(c3, gnd, g2);
    nmos nm2_c3(c3, nw_c31, g1);
    nmos nm3_c3(c3, nw_c32, g0);
    nmos nm4_c3(nw_c31, gnd, p2);
    nmos nm5_c3(nw_c32, nw_c31, p1);
    nmos nm6_c3(nw_c33, nw_c32, p0);
    nmos nm7_c3(c3, nw_c33, c_in);

    // c2
    pmos pm1_c2(c2, vdd, p1);
    pmos pm2_c2(c2, pw_c21, p0);
    pmos pm3_c2(pw_c21, vdd, g1);
    pmos pm4_c2(pw_c22, pw_c21, g0);
    pmos pm5_c2(c2, pw_c22, c_in);

    nmos nm1_c2(c2, gnd, g1);
    nmos nm2_c2(c2, nw_c21, g0);
    nmos nm3_c2(nw_c21, gnd, p1);
    nmos nm4_c2(nw_c22, nw_c21, p0);
    nmos nm5_c2(c2, nw_c22, c_in);

    // c1
    pmos pm1_c1(c1, vdd, p0);
    pmos pm2_c1(pw_c11, vdd, g0);
    pmos pm3_c1(c1, pw_c11, c_in);

    nmos nm1_c1(c1, gnd, g0);
    nmos nm2_c1(nw_c11, gnd, p0);
    nmos nm3_c1(c1, nw_c11, c_in);

    // sum and carry
    assign sum[0] = p0 ^ c_in;
    assign sum[1] = p1 ^ (!c1);
    assign sum[2] = p2 ^ (!c2);
    assign sum[3] = p3 ^ (!c3);

    assign c_out = !c4;

endmodule

module test_carry;
    reg [3:0] in1, in2;
    wire [3:0] out;
    reg c_in;
    wire c_out;
    carryCMOS carry(in1, in2, c_in, out, c_out);

    initial begin
        $dumpfile("carry.vcd");
        in1 = 4'd0;
        in2 = 4'd1;
        assign c_in = 0;
        #20;
        $display("time:%d in1:%d in2:%d c_in:%d out:%d c_out:%d", $time, 
            in1, in2, c_in, out, c_out);
        #20;
        in1 = 4'd7;
        in2 = 4'd8;
        assign c_in = 1;
        #20;
        $display("time:%d in1:%d in2:%d c_in:%d out:%d c_out:%d", $time, 
            in1, in2, c_in, out, c_out);
        #20;
        in1 = 4'd5;
        in2 = 4'd1;
        assign c_in = 1;
        #20;
        $display("time:%d in1:%d in2:%d c_in:%d out:%d c_out:%d", $time, 
            in1, in2, c_in, out, c_out);
        #20;
        in1 = 4'd5;
        in2 = 4'd10;
        assign c_in = 0;
        #20;
        $display("time:%d in1:%d in2:%d c_in:%d out:%d c_out:%d", $time, 
            in1, in2, c_in, out, c_out);
        $dumpvars(0, carry);
    end

endmodule


Проблема, с которой я столкнулся, заключается в том, что при моделировании модели я получаю неизвестное значение суммы для одного из тестовых входных данных.
Моделирование


person DanS    schedule 30.04.2014    source источник
comment
Если вы получаете неизвестный выходной бит, определите, какие транзисторы управляют этим битом, и проверьте значения на их затворах. Повторяйте, пока проблема не станет очевидной.   -  person    schedule 30.04.2014
comment
@JoeHass Я предполагаю, что проблема связана с одним из транзисторов провода c1. Как посмотреть значения на затворах транзисторов? Я использую ModelSim PE Student Edition 10.3.   -  person DanS    schedule 30.04.2014
comment
Извините, я не знаю ModelSim, но должен быть способ посмотреть на внутренние узлы, подключенные к транзисторам, которые составляют c1.   -  person    schedule 30.04.2014
comment
@JoeHass Я получаю высокие значения импеданса на проводах pw_c11 и nw_c11. Может быть, это причина?   -  person DanS    schedule 30.04.2014


Ответы (1)


Проверьте следующие строки:

pmos pm1_c1(c1, vdd, p0);

Значение p0 в момент времени 80 низкое. Поэтому NMOS пытается поднять c1 до высокого уровня.

С другой стороны:

nmos nm1_c1(c1, gnd, g0);

Значение g0 в момент времени 80 высокое. Поэтому NMOS пытается установить низкий уровень c1.

Так как c1 имеет два драйвера значений 1 и 0, его истинное значение неизвестно, т.е. x.

ИЗМЕНИТЬ:

Я не уверен, что этот дизайн правильный. Вы должны преобразовать c1=g0+p0.c0 в список соединений CMOS. Преобразование логического уравнения в список соединений CMOS очень тривиально. Вот несколько хороших ссылок: http://cs.utexas.edu/users/fussell/cs310/lectures/cs310-lecture3.pdf и http://acipo.com/blog/cmos-design-intro

Посмотрев на свой код для C1 более внимательно, вы правильно поняли часть NMOS. Сеть PMOS является двойником NMOS, это означает, что pm1_c1 должен иметь тот же сигнал ворот (т. е. управления), что и nm1_c1. Просто измените его, и это должно решить проблему как минимум для C1!

person Ari    schedule 30.04.2014
comment
Хорошо, я понимаю проблему. Должен ли я объявить временный провод для всех коммутаторов NMOS, а затем как-то объединить результаты? Любые идеи о том, как это исправить? - person DanS; 01.05.2014
comment
@Dan Sorescu: я не уверен, что этот дизайн правильный. Вы должны преобразовать c1=g0+p0.c0 в список соединений CMOS. Преобразование логического уравнения в список соединений CMOS очень тривиально. Вот несколько хороших ссылок: cs.utexas.edu/ users/fussell/cs310/lectures/cs310-lecture3.pdf и acipo.com /блог/cmos-design-intro - person Ari; 01.05.2014
comment
Посмотрев на свой код для C1 более внимательно, вы правильно поняли часть NMOS. Сеть PMOS - это просто двойная сеть NMOS, это означает, что pm1_c1 должен иметь тот же сигнал ворот (т.е. управления), что и nm1_c1. Просто измените его, и это должно решить проблему как минимум для C1! - person Ari; 01.05.2014
comment
Этот сайт оказался полезным. Единственное, что мне нужно добавить, это то, что выход инвертируется, то есть для получения правильного результата для каждого бита суммы значение каждого провода c должно быть инвертировано. Я уже сделал проволоку c1 и c2. Отчитаюсь о результатах своей работы. :-) - person DanS; 02.05.2014
comment
Как сделать ваш комментарий на сайте моим принятым ответом? Спасибо. - person DanS; 03.05.2014
comment
@Don Sorescu: я добавил комментарии к ответу. Вот ссылка с дополнительной информацией о том, как принять ответ: meta.stackexchange.com/a/5235 - person Ari; 03.05.2014
comment
Спасибо за ваши усилия! :-) - person DanS; 03.05.2014