SIPO (последовательный вход и параллельный выход) FSM в Verilog - PullRequest
0 голосов
/ 18 июня 2020

Я хочу написать преобразование последовательного интерфейса в параллельный в Verilog, и я не могу понять, что не так с моим кодом. Он не синтезируется, и даже ISE не показывает, в чем проблема. Кто-нибудь может мне помочь?

Думаю, проблема связана со вторым блоком Always. Часть:

if (STATE == TRANSMIT)
                    PAR_OUT[COUNTER] = SER_IN;

кажется мне неправильной, но я не могу понять, что изменить или протестировать.

module SIPO(
     input SER_IN,
     input RST,
     input CLK,
     input LOAD,
     output reg READY,
     output reg [7:0] PAR_OUT
    );

parameter IDLE = 2'b00, START = 2'b01, TRANSMIT = 2'b10, STOP = 2'b11;
reg [1:0] STATE;
reg [2:0] COUNTER;

always @ ( posedge CLK or negedge RST)
    if (~RST)
    begin
        STATE <= IDLE;
        READY <= 1;
        COUNTER <= 0;   
    end
    else
    begin
        if (STATE == IDLE)
        begin
            READY <= 1;
            COUNTER <= 0;
            if (LOAD)
            begin
                STATE <= START;
            end
            else
                STATE <= IDLE;
        end
        else
            if (STATE == START)
                STATE <= TRANSMIT;
            else
                if (STATE == TRANSMIT)
                    begin
                        COUNTER <= COUNTER + 1;
                        if (COUNTER == 7)
                            STATE <= STOP;
                    end
                else
                    begin
                        STATE <= IDLE;
                        READY <= 1;
                    end     
    end

always @( * )
    begin
        if (STATE == IDLE)
            PAR_OUT = 1;
        else
            if (STATE == START)
                PAR_OUT = 0;
            else
                if (STATE == TRANSMIT)
                    PAR_OUT[COUNTER] = SER_IN;
                else
                    PAR_OUT = 1;        
    end 

endmodule

1 Ответ

0 голосов
/ 19 июня 2020

Думаю, ваши подозрения относительно PAR_OUT[COUNTER] верны. Когда я синтезирую ваш код на edaplayground с помощью Yosys, он выводит защелки для PAR_OUT, что вам, вероятно, не нужно.

PAR_OUT имеет ширину 8 бит, но вы назначаете только 1 из 8 бит одновременно в состоянии TRANSMIT, что означает, что остальные 7 бит сохраняют свое состояние. Например, если COUNTER = 3, то назначается только PAR_OUT[3].

Я перекодировал ваш комбинированный лог c, упростив его с помощью оператора case, чтобы сделать проблему более очевидной (это должен быть функционально эквивалентным вашему if/else коду):

always @* begin
    case (STATE)
        TRANSMIT: PAR_OUT[COUNTER] = SER_IN;    // Assign to only 1 bit <---
        START   : PAR_OUT = 8'h00;              // Assign to all 8 bits
        default : PAR_OUT = 8'h01;              // Assign to all 8 bits
    endcase
end

Если вы можете позволить себе задержку в один цикл, вы можете использовать последовательные logi c для PAR_OUT, например регистр сдвига.

...