Декодер Verilog 4x16 выводит неверные данные

Я реализовал декодер 4x16, используя Verilog вместе с его тестом. Для каждого случая декодер должен вывести 16-разрядную цифру, в которой только один из битов имеет высоту. Я не могу получить все желаемые результаты при запуске программы. Вот код для декодера и теста, а также вывод на консоль:

4x16 декодер:

module Decoder4x16 (input [3:0] select, input enable, output reg [16:0] out);

always @(select, enable)
begin

    if(enable == 1'b0)
        out = 16'b0000000000000000;
    else if(enable == 1'b1)
        if(select == 4'b0000)
            out <= 16'b0000000000000001;
        else if(select == 4'b0001)
            out <= 16'b0000000000000010;
        else if(select == 4'b0010)
            out <= 16'b0000000000000100;
        else if(select == 4'b0011)
            out <= 16'b0000000000001000;
        else if(select == 4'b0100)
            out <= 16'b0000000000010000;
        else if(select == 4'b0101)
            out <= 16'b0000000000100000;
        else if(select == 4'b0110)
            out <= 16'b0000000001000000;
        else if(select == 4'b0111)
            out <= 16'b0000000010000000;
        else if(select == 4'b1000)
            out <= 16'b0000000100000000;
        else if(select == 4'b1001)
            out <= 16'b0000001000000000;
        else if(select == 4'b1010)
            out <= 16'b0000010000000000;
        else if(select == 4'b1011)
            out <= 16'b0000100000000000;
        else if(select == 4'b1100)
            out <= 16'b0001000000000000;
        else if(select == 4'b1101)
            out <= 16'b0010000000000000;
        else if(select == 4'b111)
            out <= 16'b0100000000000000;
        else if(select == 4'b1111)
            out <= 16'b1000000000000000;
    end

endmodule

Тестовое задание:

module Decoder4x16_test;

reg [3:0] select;
reg enable;
wire [16:0] out;

parameter sim_time = 2800;

Decoder4x16 decoder(select, enable, out);
initial #sim_time $finish;
initial
begin
    select = 4'b0000;
    enable = 1'b0;

    repeat(16) #10 begin
        enable = 1'b1;
        #85 $display("select = %b \t out = %b", select, out);
        select = select + 4'b0001;
    end
end
endmodule

Когда я запускаю программу, она выводит правильный вывод до тех пор, пока не достигнет контрольного примера, где ввод равен 1101. После этого декодер выводит неправильное значение, которое предполагается отображать. Вот вывод:

select = 0000    out = 00000000000000001
select = 0001    out = 00000000000000010
select = 0010    out = 00000000000000100
select = 0011    out = 00000000000001000
select = 0100    out = 00000000000010000
select = 0101    out = 00000000000100000
select = 0110    out = 00000000001000000
select = 0111    out = 00000000010000000
select = 1000    out = 00000000100000000
select = 1001    out = 00000001000000000
select = 1010    out = 00000010000000000
select = 1011    out = 00000100000000000
select = 1100    out = 00001000000000000
select = 1101    out = 00010000000000000
select = 1110    out = 00010000000000000
select = 1111    out = 01000000000000000

2 ответа

Попробуйте этот простой код,

module Decoder4x16 (input [3:0] select, 
                    input enable, 
                    output wire [16:0] out);

assign out = {17{enable}} & (1'b1 << select);

endmodule

Синтезировал в ИСЕ тоже.

Вот, out это reg это означает, что он содержит значение, которое ему присвоено. Здесь нет else if условие для select=4'b1110, Так, out содержит или сохраняет свое предыдущее значение, которое было от select=4'b1101, То есть, out держит значение 00010000000000000 который отображается.

Итак, добавьте else if условие для select=4'b1110 и код работает нормально.

  else if(select == 4'b1110)
            out <= 16'b0100000000000000;

Более того, декодер является чисто комбинационной схемой. При создании любой комбинационной логики, использование блокирующих назначений(=) является предпочтительным. Итак, используйте следующий синтаксис.

  else if(select == 4'b1110)
            out = 16'b0100000000000000; // blocking

Еще одна вещь, чтобы просто разработать, использовать always@(*) вместо ручного списка чувствительности. Это поможет уменьшить путаницу в списках чувствительности.

Другие вопросы по тегам