[Verilog] dúvida sobre variavel declarada como REG e OUT

Linguagem descritiva de hardware

Moderadores: 51, guest2003

[Verilog] dúvida sobre variavel declarada como REG e OUT

Mensagempor andre_luis » 05 Fev 2015 08:01

Pessoal,


Estou estudando Verilog a fundo, e já começaram a surgir algumas dúvidas, certamente triviais pra alguns, mas aqui vai:

O programa abaixo, baixei do seguinte site Introduction to Verilog - UPC - Departament de Ciències de, e na página 25 do PDF, no exemplo copiado abaixo, eu não consegui entender o porquê de terem declarado a variável Zot além de out, também como reg sob o pretexto de ser usado numa lista de sensitividade de um bloco always, mas não vi essa variavel sendo usada além de apenas como saída.

Código: Selecionar todos
module my_fsm (clk, rst, start, skip3, wait3, Zot);
   input clk, rst, start, skip3, wait3;
   output [2:0] Zot; // Zot is declared reg so that it can
   reg [2:0] Zot; // be assigned in an always block.
   parameter state0=0, state1=1, state2=2, state3=3;
   reg [1:0] state, nxt_st;

   always @ (state or start or skip3 or wait3)
   begin : next_state_logic //Name of always procedure.
      case (state)
            state0: begin
               if (start) nxt_st = state1;
               else nxt_st = state0;
               end
            state1: begin
               nxt_st = state2;
               end
            state2: begin
               if (skip3) nxt_st = state0;
               else nxt_st = state3;
               end
            state3: begin
               if (wait3) nxt_st = state3;
               else nxt_st = state0;
         end
         default: nxt_st = state0;
      endcase // default is optional since all 4 cases are
   end // covered specifically. Good practice says uses it.
   
   always @(posedge clk or posedge rst)
      begin : register_generation
         if (rst) state = state0;
         else state = nxt_st;
      end
   
   always @(state) begin : output_logic
      case (state)
         state0: Zot = 3’b000;
         state1: Zot = 3’b101;
         state2: Zot = 3’b111;
         state3: Zot = 3’b001;
         default: Zot = 3’b000;// default avoids latches
      endcase
   end
endmodule


Teria sido isso desnecessário, ou tem algo que me escapou ?
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: [Verilog] dúvida sobre variavel declarada como REG e OUT

Mensagempor pbernardi » 05 Fev 2015 09:46

Ele entra como saída (pun intended) aqui:

Código: Selecionar todos
   always @(state) begin : output_logic
      case (state)
         state0: Zot = 3’b000;
         state1: Zot = 3’b101;
         state2: Zot = 3’b111;
         state3: Zot = 3’b001;
         default: Zot = 3’b000;// default avoids latches
      endcase
   end


Mas acho esse código bem mal feito. Uma coisa que faço (e sempre vi todo mundo fazendo) por definição, é sempre usar o operador <= para registradores. É uma regra simples que evita latches e tudo mais: = é operador para wire (pode ser usado dentro (a = b) ou fora de always(assign a = b)), e <= é operador de reg (sempre usado dentro do always).

Mas além disso, há outros problemas concentuais: esse always@(state) e always @ (state or start or skip3 or wait3) dá margem para a ferramenta de síntese usar essas entradas como um clock. Claro, é algo aceito pela sintaxe, mas de um modo geral eu sempre tento colocar clocks no always. Do modo que está feito, o sintetizador pode entender que existem vários domínios de clocks diferentes e fica tudo muito pior para sincronizar.

Isso aqui também: always @(posedge clk or posedge rst), gera um reset assíncrono. De um modo geral, o melhor e se usar resets síncronos ( always @(posedge clk) ) ou até mesmo tirar o reset (economiza lógica, só use quando necessário).

A fírula que o cara fez pra mudar o state foi lindo (sqn) também. Putz, é quase um contador de 0 a 3, para passar de estado é só incrementar.

Resumindo, parece que foi um cara que faz software que escreveu isso. O cara fez um tipo de firula pra ficar mais bonito, mas prejudica o hardware.
Editado pela última vez por pbernardi em 05 Fev 2015 10:04, em um total de 1 vez.
But to us there is but one God, plus or minus one - Corinthians 8:6±2. (xkcd.com)
pbernardi
Word
 
Mensagens: 707
Registrado em: 12 Out 2006 19:01
Localização: Curitiba-PR

Re: [Verilog] dúvida sobre variavel declarada como REG e OUT

Mensagempor msamsoniuk » 05 Fev 2015 10:01

o estilo do codigo parece um mix de VHDL e codigo antigo... isso chega a sintetizar?

eu escreveria esse codigo da seguinte forma:

Código: Selecionar todos
module my_fsm (
   input clk,
   input rst,
   input start,
   input skip3,
   input wait3,
   output reg [2:0] Zot
);
   parameter state0=0, state1=1, state2=2, state3=3;
   reg [1:0] nxt_st;
   wire [1:0] state = nxt_st;

   always @ (posedge clk)
   begin :
      if(rst)
         nxt_st <= state0;
      else
      case (state)
            state0: begin
               if (start) nxt_st <= state1;
               else nxt_st <= state0;
               end
            state1: begin
               nxt_st <= state2;
               end
            state2: begin
               if (skip3) nxt_st <= state0;
               else nxt_st <= state3;
               end
            state3: begin
               if (wait3) nxt_st <= state3;
               else nxt_st <= state0;
         end
         default: nxt_st <= state0;
      endcase

      case (state)
         state0: Zot <= 3’b000;
         state1: Zot <= 3’b101;
         state2: Zot <= 3’b111;
         state3: Zot <= 3’b001;
      endcase
   end
endmodule


primeira coisa eh o rst na lista de sensibilidade com posedge: isso gera reset assincrono e aumenta a incerteza na sintese. melhor usar um reset sincrono. e claro, lah na entrada do reset, passar em um par de flip-flops para limpar meta-estabilidade gerada pela ativacao assincrona do reset:

Código: Selecionar todos
input ires;

reg iresx;
reg res;

always(@posedge clk)
begin
  iresx <= ires;
  res <= iresx;
end


note que a declaracao dos in e out eu fiz de forma mais direta com uma sintaxe mais moderna e clara. no output, eu coloquei um registro... em geral registra-se as saidas, pensando no seguinte contexto:

modulo1 -> modulo2

eh como se fosse um pipeline:

estagio1 -> estagio2

dentro do modulo, pode pensar q tambem tem um pipeline: nxt_st muda clock a clock e zot tambem, com a diferenca de um clock entre eles. originalmente eles fizeram state como registro... isso varia. em essencia nao precisa, pq provavelmente na sintese o nxt_st vai virar um flip-flop por estado e vai ser algo estavel.

dah para fazer state como um registro, daih eh como se colocasse um pipeline no meio: nxt_st comuta, daih state recebe nxt_st no proximo clock e Zot comuta no proximo clock. na simulacao vc ve os atrasos. o clock deve melhorar, pq a decisao de nxt_st e Zot ficam em pipelines diferentes:

Código: Selecionar todos
module my_fsm (
   input clk,
   input rst,
   input start,
   input skip3,
   input wait3,
   output reg [2:0] Zot
);
   parameter state0=0, state1=1, state2=2, state3=3;
   reg [1:0] nxt_st;
   reg [1:0] state;

   always @ (posedge clk)
   begin :
      if(rst)
         nxt_st <= state0;
      else
      case (state)
            state0: begin
               if (start) nxt_st <= state1;
               else nxt_st <= state0;
               end
            state1: begin
               nxt_st <= state2;
               end
            state2: begin
               if (skip3) nxt_st <= state0;
               else nxt_st <= state3;
               end
            state3: begin
               if (wait3) nxt_st <= state3;
               else nxt_st <= state0;
         end
         default: nxt_st <= state0;
      endcase

      state <= nxt_st;

      case (state)
         state0: Zot <= 3’b000;
         state1: Zot <= 3’b101;
         state2: Zot <= 3’b111;
         state3: Zot <= 3’b001;
      endcase
   end
endmodule


por isso eh bom testar direto na ferramenta do fabricante, ele jah sintetiza e vc confere o resultado em termos de performance.

se a velocidade necessaria eh menor, arrisca fazer de boa em um unico pipeline tb, gastando menos flip-flops:

Código: Selecionar todos
module my_fsm (
   input clk,
   input rst,
   input start,
   input skip3,
   input wait3,
   output [2:0] Zot
);
   parameter state0=0, state1=1, state2=2, state3=3;
   reg [1:0] nxt_st;
   wire [1:0] state;

   always @ (posedge clk)
   begin :
      if(rst)
         nxt_st <= state0;
      else
      case (state)
            state0: begin
               if (start) nxt_st <= state1;
               else nxt_st <= state0;
               end
            state1: begin
               nxt_st <= state2;
               end
            state2: begin
               if (skip3) nxt_st <= state0;
               else nxt_st <= state3;
               end
            state3: begin
               if (wait3) nxt_st <= state3;
               else nxt_st <= state0;
         end
         default: nxt_st <= state0;
      endcase
  end
  assign state = nxt_st;

  assign Zot =
         state0 ? 3’b000 :
         state1 ? 3’b101 :
         state2 ? 3’b111 :
                      3’b001;

endmodule
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Re: [Verilog] dúvida sobre variavel declarada como REG e OUT

Mensagempor pbernardi » 05 Fev 2015 10:55

msamsoniuk escreveu:o estilo do codigo parece um mix de VHDL e codigo antigo... isso chega a sintetizar?


Agora que vc falou, essa mix dos operadores <= e = é típico de quem vem de VHDL mesmo. Em VHDL ele tem operadores semelhantes (:= e <= se não me engano) mas por não declarar registros e wires separados, nunca sabem quando usam qual operador. :roll:
But to us there is but one God, plus or minus one - Corinthians 8:6±2. (xkcd.com)
pbernardi
Word
 
Mensagens: 707
Registrado em: 12 Out 2006 19:01
Localização: Curitiba-PR

Re: [Verilog] dúvida sobre variavel declarada como REG e OUT

Mensagempor andre_luis » 05 Fev 2015 12:30

Valeu pessoal,



Tem certos códigos que mesmo pra um leigo, soa como algo que foi escrito alí na hora, durante a edição do tutorial. Algumas coisas que voces comentaram, em princípio parece mesmo confuso no programa. Por exemplo, eu também teria preferido apenas uma variável no always, e se for o caso tentar colocar o restante das variáveis dentro do bloco, ou mesmo criar outro bloco em separado para as outras variáveis. Também o uso do "=", fico na dúvida em saber em que circunstancias seria recomendado seu uso, ao invéz do "<=" ( já que também prefiro tornar a coisa o mais sincrono possível, pra ajudar a tornar previsível ).

pbernardi escreveu:Ele entra como saída (pun intended)

Mas, sobre a questão do Zout, acho que não ficou ainda claro pra mim; Isso significa que sempre que uma variável for uma saída, precisa declarar também sempre como reg, seria isso ?

msamsoniuk escreveu:melhor usar um reset sincrono. e claro, lah na entrada do reset, passar em um par de flip-flops para limpar meta-estabilidade gerada pela ativacao assincrona do reset:


Esse maçete de tornar o resset sincrono não tinha visto antes, parece interessante apesar de "atrazar" a sua atuação no periodo de 1 clock, rsrsrs. Nesse caso, se o utilizasse dentro do bloco anterior, seria factível, ou esse tipo de construção com várias entradas na lista de sensibilidade seria uma prática não recomendada ?
always @( posedge clk or posedge iresx )

pbernardi escreveu:A fírula que o cara fez pra mudar o state foi lindo (sqn) também. Putz, é quase um contador de 0 a 3, para passar de estado é só incrementar


Poisé, e o que eu mais achei estranho é o fato de além de ter usado state como entrada de 2 always, sendo também saída em um deles. Posso estar enganado, mas poderia estar criando latches, já que usou o "=".

Nesse caso, pra ir aprimorando o aprendizado, voces recomendariam eu pegar esse código por exemplo e ir compilando fazendo pequenas alterações e vendo o resultado final na lógica RTL ? Digo, esse seria o caminho pra ir se familizarizando ?


Valeu.
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: [Verilog] dúvida sobre variavel declarada como REG e OUT

Mensagempor pbernardi » 05 Fev 2015 13:09

andre_teprom escreveu:
pbernardi escreveu:Ele entra como saída (pun intended)

Mas, sobre a questão do Zout, acho que não ficou ainda claro pra mim; Isso significa que sempre que uma variável for uma saída, precisa declarar também sempre como reg, seria isso ?


Não ncessariamente. Você quer um "output reg" se quiser uma saída síncrona. Se for um sinal normal, como um clock, por exemplo, você vai ter uma saída normal tipo wire.

Mas é muito comum usar saídas síncronas. Isso indica que você está usando circuito internos síncronos, o que é bom.

andre_teprom escreveu:
msamsoniuk escreveu:melhor usar um reset sincrono. e claro, lah na entrada do reset, passar em um par de flip-flops para limpar meta-estabilidade gerada pela ativacao assincrona do reset:


Esse maçete de tornar o resset sincrono não tinha visto antes, parece interessante apesar de "atrazar" a sua atuação no periodo de 1 clock, rsrsrs. Nesse caso, se o utilizasse dentro do bloco anterior, seria factível, ou esse tipo de construção com várias entradas na lista de sensibilidade seria uma prática não recomendada ?
always @( posedge clk or posedge iresx )


O recomendado é: use o mínimo de domínio de clocks possível. Só use mais de um clock se for realmente necessário. As vezes você precisa usar dois clocks, não tem jeito (por exemplo, em dual-port rams trabalhando com dois clocks diferentes). Mas fora as excessões, use apenas cloks na frente dos always.

Isso acontece porque ao construir um flip-flop, você tem basicamente CLK, EN, RST, entrada e saída. A entrada de CLK do flip-flop geralmente é otimizada para ter conexões com linhas de GCLK internas. Ao usar um CLK com um sinal qualquer, você pode atrapalhar o roteamento interno, e até dar problemas depois para "juntar" os diversos domínios de "clocks".

Em relação ao reset, ele geralmente entra no pino RST do flip-flop, que é síncrono. Se você usar um reset assíncrono, a ferramenta geralmente vai tentar fazer uma lógica com dois flip-flops, uma no domínio do clock e outra no domínio do reset, sendo que ele tem lógica prontra para o reset. Ou seja, você está desperdiçando lógica.

andre_teprom escreveu:
pbernardi escreveu:A fírula que o cara fez pra mudar o state foi lindo (sqn) também. Putz, é quase um contador de 0 a 3, para passar de estado é só incrementar


Poisé, e o que eu mais achei estranho é o fato de além de ter usado state como entrada de 2 always, sendo também saída em um deles. Posso estar enganado, mas poderia estar criando latches, já que usou o "=".

Nesse caso, pra ir aprimorando o aprendizado, voces recomendariam eu pegar esse código por exemplo e ir compilando fazendo pequenas alterações e vendo o resultado final na lógica RTL ? Digo, esse seria o caminho pra ir se familizarizando ?

Valeu.


Bom, acho que a primeira coisa é colocar tudo dentro de um domínio de clock só: dá pra fazer a mesma coisa apenas usando:

Código: Selecionar todos
always@(posedge clk)
begin
  ...
end


E pra todo o resto dá pra usar case ou mesmo if-else. Ou melhor ainda, os operadores "?" e ":", esses são os que fica mais fácil de entender o que está acontecendo no ponto de vista do hardware.
But to us there is but one God, plus or minus one - Corinthians 8:6±2. (xkcd.com)
pbernardi
Word
 
Mensagens: 707
Registrado em: 12 Out 2006 19:01
Localização: Curitiba-PR

Re: [Verilog] dúvida sobre variavel declarada como REG e OUT

Mensagempor msamsoniuk » 05 Fev 2015 13:20

sobre o output reg, ateh eh algo que me comentaram hoje, da FPGA gerar ruido nos sinais... quando vc tem um sinal de saida que depende de valores de entrada, tipo:

module(input clk, output out)
begin
...
assing out = state==1 ? 1 : state==2 ? 1 : 0;
end

ele vai atribuir out = 1 se state for 1 ou 2. soh que quando state muda de 1 para 2, o valor interno 01 nao comuta direto para 10. as linhas nunca sao perfeitamente paralelas, entao vai ocorrer uma comutacao 01 -> 11 -> 10 ou 01 -> 00 -> 10, dependendo de qual flip-flop comuta antes. portanto a linha out ali, q eh uma logica combinacional, vai refletir esse estado intermediario, dando um glitch rapido quando ele passa pelo estado 0 ou 3.

a solucao, para prevenir isso, seria colocar um output reg out:

module(input clk, output reg out)
begin
...
always@(posedge clk)
out <= state==1 ? 1 : state==2 ? 1 : 0;
end

assim o estado pode comutar como 01 -> 11 -> 10 ou 01 -> 00 -> 10, mas independente disso estara sempre estavel em 01 ou 10 na amostragem de clock e out ficara perfeitamente estavel e sem ruidos.

claro, isso eh essencial apenas em sinais que vao para fora da FPGA. para sinais internos, pode nao ser realmente importante isso. eventualmente, se a logica comecar a ficar muito complexa, isso implica em tempo. daih registrar as saidas entre modulos melhora a performance geral.
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Re: [Verilog] dúvida sobre variavel declarada como REG e OUT

Mensagempor msamsoniuk » 05 Fev 2015 13:26

sobre o = ou <=. vc pode adotar como regra o seguinte...

- logica sequencial: gera flip-flop, propaga a saida a cada borda de clock

Código: Selecionar todos
reg algo = 0; // sempre eh bom colocar um valor inicial, facilita a simulacao

always@(posedge CLK)
begin
  algo <= logica combinacional
end


o cara declarado como reg vai ser sempre atribuido com <= dentro de um always@(posedge clk).

- logica combinacional: gera wire, propaga a saida "instantaneamente"

Código: Selecionar todos
wire algo;

assign algo = logica combinacional aqui


o cara declarado como wire vai ser sempre atribuido com = dentro de um assign. dah para usar um always, mas deixa mais confuso.
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04


Voltar para Verilog, VHDL, SystemC ( PLAs, CPLDs, FPGAs, etc... )

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 0 visitantes

x