61 / 63 · Conceito
Pipeline com parada e backpressure
Calcule ready por estágio para evitar perda, duplicação e recálculo durante paradas e movimentações simultâneas.
As aulas podem ser lidas gratuitamente. Inscreva-se para salvar o progresso.
Se o receptor não puder aceitar sempre
Conhecimentos prévios: buffer ready/validHandshake Contrato que confirma uma transferência quando valid do transmissor e ready do receptor valem 1 na mesma borda. Inclui as regras para manter os dados durante a espera. Saiba mais de uma posição e alinhamento de dados em pipelinesPipeline Estrutura que divide o cálculo em estágios separados por registradores para processar várias entradas de forma sobreposta. Dados, valid e controles devem permanecer alinhados entre os estágios. Saiba mais.
Adicionar out_ready a um pipeline de velocidade fixa e bloquear apenas sua saída não basta. Se o último estágio ficar cheio e parar, os anteriores também não podem ser sobrescritos. É preciso projetar o backpressureBackpressure Mecanismo pelo qual o receptor indica que temporariamente não pode aceitar dados e interrompe o fluxo. Durante a parada, os dados ainda não transferidos devem ser preservados. Saiba mais, que propaga o pedido de parada em direção à entrada.
Representaremos cada um dos dois estágios por um dado e um bit valid. O segundo pode receber um novo valor se estiver vazio ou se puder entregar a saída atual. A mesma regra se aplica ao primeiro.
O in_ready externo é r1. Mesmo com r2=0, o primeiro estágio pode aceitar uma entrada se estiver vazio. Assim, o espaço disponível é aproveitado mesmo quando a saída está parada.
Atualizar cada estágio somente quando houver permissão para avançar
O exemplo abaixo calcula y=2(x+1) para um x unsignedunsigned Interpretação de uma sequência de bits como inteiro não negativo. Com n bits, o intervalo é de 0 a 2^n−1; pode diferir da interpretação signed dos mesmos bits. Saiba mais de 8 bits. O primeiro estágio armazena x+1 em 9 bits; o segundo desloca um bit para a esquerda e produz 10 bits. O resultado 512 da entrada máxima 255 é representado exatamente.
module stallable_pipeline (
input logic clk, rst,
input logic in_valid,
output logic in_ready,
input logic [7:0] in_data,
output logic out_valid,
input logic out_ready,
output logic [9:0] out_data
);
logic v1, v2, r1, r2;
logic [8:0] d1;
logic [9:0] d2;
assign r2 = !v2 || out_ready;
assign r1 = !v1 || r2;
assign in_ready = r1;
assign out_valid = v2;
assign out_data = d2;
always_ff @(posedge clk) begin
if (rst) begin
v1 <= 1'b0;
v2 <= 1'b0;
end else begin
if (r2) begin
v2 <= v1;
if (v1) d2 <= {d1, 1'b0};
end
if (r1) begin
v1 <= in_valid;
if (in_valid) d1 <= {1'b0, in_data} + 9'd1;
end
end
end
endmoduleAs atribuições são não bloqueantesAtribuição não bloqueante Atribuição escrita com <= em RTL sequencial. Avalia o lado direito e agenda a atualização, permitindo que os registradores da mesma borda calculem a partir do estado anterior. Saiba mais: o segundo estágio recebe o d1 anterior, não aquele calculado na mesma borda. Se r1=0, v1 e d1 são mantidos; se r2=0, v2 e d2 são mantidos. Preservar apenas valid enquanto os dados continuam mudando é incorreto.
Acompanhar o comportamento com os dois estágios cheios
Suponha que o segundo estágio contenha o resultado de A, o primeiro contenha o valor intermediário de B e C espere na entrada.
| out_ready | in_ready | Ação na borda |
|---|---|---|
| 0 | 0 | Mantém A e B; não aceita C |
| 0 | 0 | Mantém A e B; não aceita C |
| 1 | 1 | Entrega A, move B para o segundo estágio e aceita C |
O transmissor mantém C e in_valid até C ser aceito. Se considerar que enviou C na primeira borda de parada e apresentar o dado seguinte, C será perdido.
Cada coluna mostra os valores imediatamente antes da borda de subidaBorda de subida Instante em que o clock passa de 0 para 1. É diferente do nível alto, que abrange todo o intervalo com CLK=1. Saiba mais. Inicialmente, A ocupa o último estágio, B o primeiro e C espera na entrada. Em E2, A é entregue e C é aceito; antes de E3, a saída já contém B.
Ver os dados da forma de onda
| Sinal | Forma de onda | Valores do barramento |
|---|---|---|
| borda | 2345 | E0 → E1 → E2 → E3 |
| out_ready | 0.1. | |
| out_valid | 1... | |
| out_data | 2..3 | A → B |
| in_valid | 1... | |
| in_ready | 0.1. | |
| in_data | 2..3 | C → D |
Leis de conservação a verificar
Sejam Nin as entradas aceitas e Nout as saídas entregues desde o reset. A quantidade armazenada satisfaz a relação abaixo, sem contar transferências na borda de reset.
Uma contagem correta pode esconder a entrega de A duas vezes e a perda de B. Confira também valores e ordem usando uma fila de referência. Varie independentemente valid de entrada e ready de saída e inclua paradas longas, processamento contínuo e esvaziamento por reset.
O caminho de ready também tem restrições temporais
Ao encadear muitos estágios, o caminho combinacional inverso, como r2→r1, fica mais longo. Atrasar ready com um registrador pode exigir espaço extra para as entradas cuja aceitação já havia sido anunciada durante esse atraso. Inserir um flip-flop em ready sem considerar o armazenamento e o protocolo não é uma otimização temporal segura.
Experimente
Temos v1=0, v2=1 e out_ready=0. Uma entrada com in_valid=1 pode ser aceita? Se out_ready continuar em 0 no ciclo seguinte, outras entradas poderão continuar sendo aceitas?
Ler a explicação
Inicialmente r2=0, mas r1=1, portanto é possível aceitar um elemento e preencher o primeiro estágio. Após a borda, v1=v2=1 implica r1=r2=0 e nenhuma outra entrada pode ser aceita. Essa distinção permite aproveitar as duas posições de armazenamento.