Implementação de um shift register em VHDL

shift register

Shift registers são elementos comuns em sistemas digitais utilizados para os mais diversos fins, como por exemplo: conversão de dados serial-paralelo e vice-versa; geração de atrasos; contadores e etc.

 

Um shift register nada mais é do que um array de flip-flops conectados em um mesmo clock de forma que a cada pulso de clock a entrada de um flip-flop recebe o valor da saída de seu anterior. Desta forma a cada pulso de clock o flip-flop n+1 recebe o valor de n. A Figura 1 retirada da wikipedia retrata o circuito.

 

 

shift register
Figura 1. Shift register de 4 bits

 

 

Vamos representar este comportamento em VHDL, para isto vamos descrever o comportamento do circuito da Figura 1 em VHDL, como entrada temos o data_in representado pelo sinal dado_entrada e como saída o Q4(dado_registrado(3)) é o nosso dado_saida.

 

 

 

 

Nosso registrador de 4 bits está representado pelo dado_registrado e somente o último bit deste registrador é enviado para a saída. Como podemos ver a cada pulso de clock o valor do flip-flop recebe o valor de seu antecessor, sendo assim são necessários 4 pulsos de clock para que o valor de entrada passe por todos os flip-flops e vá para a saída como mostra a simulação na Figura 2.

 

shift register
Figura 2. Funcionamento do Shift Register

 

 

 

Outra forma de se implementar o mesmo shift register utilizando menos linhas o que é muito útil quando se tem um maior número de bits (imagine só escrever 512 linhas para um shift register de 512 bits) é alterar o process da seguinte forma:

 

 

 

O funcionamento é idêntico, todos os flip-flops recebem os valores dos seus anteriores a cada pulso de clock. Neste caso os bits 3 2 1 vão receber os bits 2 1 0 e o 0 será atualizado. (mesmo comportamento)

 

Este código também pode ser utilizado como um conversor serial-paralelo, a cada 4 pulsos de clock você tem uma palavra paralela de 4 bits em um registrador. Incrivelmente simples, não?

 

No caso de um contador em anel basta ligar a saída do ultimo flip-flop a entrada do primeiro e fazer com que no reset um dos flip-flops assuma o valor de '1'. Teremos a sequência infinita de {0001}, {0010}, {0100}, {1000}, {0001} ...

 

O testbench utilizado neste post caso queiram se divertir:

 

 

Deixe um comentário

9 Comentários em "Implementação de um shift register em VHDL"

Notificar
avatar
Ordenar por:   recentes | antigos | mais votados
Sandro Dutra
Membro
Sandro Dutra

Acho que seria interessante um curso por partes sobre VHDL ou Verilog com exemplos, estou precisando de um desses... Aliás, aproveitando a deixa, vocês que são mais experientes nessa questão, qual livro/site indicariam para iniciar o estudo?

André Castelan
Visitante
André Castelan

Olá Sandro fiz alguns posts sobre o básico de VHDL : http://www.embarcados.com.br/vhdl-basico-parte-1-entidade/ http://www.embarcados.com.br/vhdl-basico-parte-2-arquitetura/ e estou com turmas abertas para o treinamento em FPGA aos sábados junto com a Macnica DHW: http://www.embarcados.com.br/treinamentofpga/ , como livro gosto de indicar os do Pong. Chu. Para VHDL Este : RTL Hardware Design Using VHDL por Pong. P Chu

Fiz um post sobre alguns livros que li recentemente no meu antigo blog - http://www.andrecastelan.com.br/2013/08/livros-em-fpga.html

Sandro Dutra
Membro
Sandro Dutra

Opa, obrigado André! Vai ser muito útil no meu aprendizado.

Walter Gallegos
Membro
Walter Gallegos

Ola André, apenas um aporte para a coletividade

O processo

process(sys_clk,sys_rst)
begin
if (sys_rst = '1') then
dado_registrado <= "0000";
elsif rising_edge(sys_clk) then
dado_registrado(0) <= dado_entrada;
dado_registrado(3 downto 1) <= dado_registrado(2 downto 0);
end if;
end process;

Pode ser simplificado usando o operador de concatenação.

ShiftReg : PROCESS(sys_clk,sys_rst)
BEGIN
IF (sys_rst = '1') THEN
dado_registrado <= "0000";
ELSE rising_edge(sys_clk) THEN
dado_registrado(3 downto 1) <= dado_registrado(2 downto 0) & dado_entrada;
END IF;
END PROCESS ShiftReg;

Além disto acho seria bom você comentar o uso do RESET neste casso.
Quem esta iniciando em VHDL poderia não conhecer os efeitos colaterais.

Atenciosamente
Walter

André Castelan
Visitante
André Castelan

Verdade Walter, obrigado! Quis deixar como coloquei para ficar mais didático mas a sua solução é mais elegante. e no caso seria (3 downto 0) recebendo o 2 downto 0 & dado entrada

Fiz um post sobre esquemas de reset aqui: http://www.embarcados.com.br/arquiteturaresetfpga/ que discute o exemplo do reset assíncrono utilizado neste post.

abs

Walter Gallegos
Membro
Walter Gallegos

Opps, meu erro !!

Esqueci de apagar os índices no exemplo, porem bom para ver quem esta atento ao código...

Quanto ao RESET eu falava dos efeitos colaterais nos recursos usados na FPGA,
Depende da arquitetura da FPGA e da ferramenta

SIGNAL dado_registrado : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000"; -- Depende da ferramenta pode ser ignorado na implementação.

ShiftReg : PROCESS(sys_clk)
BEGIN
IF rising_edge(sys_clk) THEN
dado_registrado <= dado_registrado(2 downto 0) & dado_entrada;
END IF;
END PROCESS ShiftReg;

Se a arquitetura da FPGA aceita esse ShiftReg seria implementado em LUT sem usar FF passando de consumir 4 FF para 0 FF.

Abraços,
Walter

André Castelan
Visitante
André Castelan

Ah sim, inicialização de sinais desta forma serve tão somente para simulação e não para síntese.

E também é verdade que dependendo da arquitetura de FPGA ele usaria uma estrutura do próprio FPGA e não gastaria lógica/memória. Se não me engano, na Xilinx, essa codificação sem reset faria isto.

Ótimas observações Walter! Obrigado

abs

Walter Gallegos
Membro
Walter Gallegos

Correto, um VHDL genérico, mais a implementação depende da ferramenta e da arquitetura no casso da Xilinx não usaria FF.

Apenas para complementar

SIGNAL dado_registrado : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";

No casso do XST ( Sínteses Xilinx ) seria aceito para simulação e sínteses.

Abraços,
Walter

André Castelan
Visitante
André Castelan

Obrigado pelos comentários!
Abs

wpDiscuz