Domanda

Sono molto nuovo al linguaggio HDL. Ho una domanda su come programmare un registro a scorrimento. (So ??spostamento i per l'altra direzione). Perché l'uso wire[N-1:0] r_next libro? ciò che è inconveniente della mia implementazione? grazie

il mio primo tentativo è la seguente

module lesson04#(parameter N=8)(
    input wire clk, reset,
    input wire data,
    output wire out
);

reg [N-1: 0] r_reg;


always @(posedge clk or negedge reset)
begin
    if(!reset)
         r_reg =0;
    else 
        r_reg[0]=data;
        r_reg = r_reg<<1;
end

assign out =r_reg[N-1];
endmodule 

ma il libro dà:

module lesson04#(parameter N=8)(
    input wire clk, reset,
    input wire data,
    output wire out
);

reg [N-1: 0] r_reg;
wire[N-1:0] r_next;

always @(posedge clk or negedge reset)
begin
    if(!reset)
         r_reg =0;
    else 
        r_reg <= r_next;
end

assign r_next= {data, r_reg[N-1:1]};
assign out =r_reg[N-1];
endmodule
È stato utile?

Soluzione

Prima di tutto, non dimenticate il vostro begin-ends intorno sezioni di codice:

else begin
     r_reg[0]=data;
     r_reg = r_reg<<1;
end

Senza questo, solo r_reg[0]=data sarà nella clausola else della dichiarazione if. Questo funzionerà, ma è considerato un cattivo stile a causa delle dichiarazioni di blocco in una descrizione logica sequenziale ...

In secondo luogo, per la modellazione blocchi sequenziali, uso non bloccante assegnazioni (<=) o calcoli può 'cadere attraverso' (google non bloccante contro il blocco per maggiori informazioni). Il vostro esempio può benissimo lavoro (avete provato in un simulatore?), Ma se le cose si fanno più complicate e più variabili sono aggiunte le cose possono rompersi.

always @(posedge clk or negedge reset)
begin
    if(!reset)
         r_reg <= 0;
    else begin // This is horrible! Don't write code like this!
        r_reg[0] = data;     // blocking
        r_reg <= r_reg<<1;   // non-blocking
    end
end

Per la ragione sopra, a volte è consigliabile che la logica combo è separato dalla logica sequenziale in modo che si può scrivere non bloccante assegnazioni ai registri in blocchi sequenziali, e il blocco in blocchi combo e non hanno mai preoccuparsi di programmazione.

Per il codice in questo modo, è necessario calcolare quanto l'uscita successiva deve essere utilizzato allo stato attuale, da qui il bus r_next nella risposta. Credo che tende ad aiutare la sintesi strumento troppo se tutti i flip-flop sono separati dai circostante logica combinata in questo modo.

Inoltre, se il reset è attivo basso (cioè LOW azzera) dovrebbe essere chiamato come tale, ad esempio resetb o reset_n.

Altri suggerimenti

L'implementazione produce un'uscita molto diverso dal libro di. Si dovrebbe provare questo a te stesso con la costruzione di un semplice banco di prova per guidare i vostri input ed eseguire una simulazione. Vedrete che i turni di uscita del libro i dati di input da un singolo ciclo di clock, mentre i tuoi spostamenti in uscita i dati di input da otto cicli di clock.

Tra l'altro si è rientrato tuo blocco always, sono portato a credere che non è quello che volevi. Questo è come il tuo blocco si comporta davvero:

always @(posedge clk or negedge reset)
begin
    if(!reset) begin
         r_reg =0;
    end else begin
        r_reg[0]=data;
    end
    r_reg = r_reg<<1;
end

Io uso sempre esplicitamente le parole chiave begin/end a dichiarazioni if/else per evitare questa confusione.

Il modo in cui simula, r_reg è sempre 0 perché si clobber l'assegnazione 1 ° (r_reg[0]=data;) con il 2 ° (r_reg = r_reg<<1;). Un'altra differenza è che le assegna libro data al MSB del registro a scorrimento, ma si assegna alla LSB.

Se si utilizza decenti strumenti linting e di sintesi, si sarebbe probabilmente ottenere un sacco di avvertimenti per il codice. Ciò avvisare l'utente di apportare alcune modifiche.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top