Página 1 de 1

testbench em VHDL para bus inout

MensagemEnviado: 11 Jan 2014 19:20
por chrdcv
Saudações pessoal!

Estou descrevendo um circuito em VHDL em que quatro cartões SAM são lidos e escritos (não simultaneamente) através de um barramento correspondente (EPLD_SAM_DIO_IO[0...3]), mediante a seleção de escrita/leitura dada por sam_dio[0...3], onde os dados de escrita e leitura de um dos cartões selecionado será "copiado" para a UART, através da saída de transmissão de dados: "uart_xmit" e entrada: "uart-recv".

O circuito funciona como um bridge entre a UART e o pino de dados do cartão. O trecho abaixo exibe a descrição. Conforme podem notar, os pinos EPLD_SAM_DIO(0...3) são os pinos de escrita e leitura no cartão (conectado à EPLD), uart_xmit é a saída de transmissão da UART, uart_recv é entrada de recepção da UART. sam_dio(0...3) correspondem as seleções do cartão a ser interfaceado, bem como se será escrita ou leitura.

Realizei a descrição primeiramente utilizando o GHDL e depois o Quartus. A síntese foi feita no Quartus sem maiores problemas ou warnings, mas fazer o testbench, não consigo simular corretamente o comportamento de entrada/saída do pino EPLD_SAM_DIO_IO(0...3). Somente um caso funciona.

Alguém teria uma dica?

Código: Selecionar todos
 uart_xmit <= EPLD_SAM_DIO_IO(0) when sam_dio(0) = '0' and
                                         sam_dio(1) = '1' and
                                         sam_dio(2) = '1' and
                                         sam_dio(3) = '1' else
                 EPLD_SAM_DIO_IO(1) when sam_dio(0) = '1' and
                                         sam_dio(1) = '0' and
                                         sam_dio(2) = '1' and
                                         sam_dio(3) = '1' else
                 EPLD_SAM_DIO_IO(2) when sam_dio(0) = '1' and
                                         sam_dio(1) = '1' and
                                         sam_dio(2) = '0' and
                                         sam_dio(3) = '1' else
                 EPLD_SAM_DIO_IO(3) when sam_dio(0) = '1' and
                                         sam_dio(1) = '1' and
                                         sam_dio(2) = '1' and
                                         sam_dio(3) = '0' else '1';

        EPLD_SAM_DIO_IO(0) <= EPLD_UART_RECV_I when sam_dio(0) = '1' and
                                                   sam_dio(1) = '0' and
                                                sam_dio(2) = '0' and
                                                sam_dio(3) = '0' else 'Z';

        EPLD_SAM_DIO_IO(1) <= EPLD_UART_RECV_I when sam_dio(0) = '0' and
                                                   sam_dio(1) = '1' and
                                                sam_dio(2) = '0' and
                                                sam_dio(3) = '0' else 'Z';

        EPLD_SAM_DIO_IO(2) <= EPLD_UART_RECV_I when sam_dio(0) = '0' and
                                                   sam_dio(1) = '0' and
                                                sam_dio(2) = '1' and
                                                sam_dio(3) = '0' else 'Z';

        EPLD_SAM_DIO_IO(3) <= EPLD_UART_RECV_I when sam_dio(0) = '0' and
                                                   sam_dio(1) = '0' and
                                                sam_dio(2) = '0' and
                                                sam_dio(3) = '1' else 'Z';

Re: testbench em VHDL para bus inout

MensagemEnviado: 11 Jan 2014 20:12
por andre_luis
Já faz uma década que não mexo com VHDL, mas pra facilitar na investigação, coloquei numa linha os comandos que pertencem á mesma condição.
Então, exatamente que sequencias abaixo não estão sendo executadas quando deveriam ?


EPLD_SAM_DIO_IO(0) when sam_dio(0) = '0' and sam_dio(1) = '1' and sam_dio(2) = '1' and sam_dio(3) = '1' else
EPLD_SAM_DIO_IO(1) when sam_dio(0) = '1' and sam_dio(1) = '0' and sam_dio(2) = '1' and sam_dio(3) = '1' else
EPLD_SAM_DIO_IO(2) when sam_dio(0) = '1' and sam_dio(1) = '1' and sam_dio(2) = '0' and sam_dio(3) = '1' else
EPLD_SAM_DIO_IO(3) when sam_dio(0) = '1' and sam_dio(1) = '1' and sam_dio(2) = '1' and sam_dio(3) = '0' else '1';

EPLD_SAM_DIO_IO(0) <= EPLD_UART_RECV_I when sam_dio(0) = '1' and sam_dio(1) = '0' and sam_dio(2) = '0' and sam_dio(3) = '0' else 'Z';
EPLD_SAM_DIO_IO(1) <= EPLD_UART_RECV_I when sam_dio(0) = '0' and sam_dio(1) = '1' and sam_dio(2) = '0' and sam_dio(3) = '0' else 'Z';
EPLD_SAM_DIO_IO(2) <= EPLD_UART_RECV_I when sam_dio(0) = '0' and sam_dio(1) = '0' and sam_dio(2) = '1' and sam_dio(3) = '0' else 'Z';
EPLD_SAM_DIO_IO(3) <= EPLD_UART_RECV_I when sam_dio(0) = '0' and sam_dio(1) = '0' and sam_dio(2) = '0' and sam_dio(3) = '1' else 'Z';



Obs.: Tive de retirar a formatação CODE porque o texto não cabia em cada linha da mensagem.


+++

Re: testbench em VHDL para bus inout

MensagemEnviado: 13 Jan 2014 11:06
por chrdcv
André, obrigado pelo teu interesse e atenção ao identar o código para melhor leitura e interpretação!

Como mencionado no post inicial, eu não tenho problema com a descrição passada nem com a síntese efetuada pelo Quartus; meu problema encontra-se na escrita de um testbench que simule o comportamento do barramento: EPLD_SAM_DIO_IO(0...3) ora como entrada, ora como saída, dependendo da configuração dada por sam_dio(0...3).

Att.
chrdcv

Re: testbench em VHDL para bus inout

MensagemEnviado: 14 Jan 2014 06:46
por andre_luis
Rabisca uma idéia do que precisa num diagrama.
Em princípio não deveria ser tão complicado, pois afinal parece ser uma espécie de buffer bidirecional controlado por um mux.

Não seria algo tipo assim ?

Código: Selecionar todos
EPLD_SAM_DIO_IO(0) = '0' ;
EPLD_SAM_DIO_IO(1) = '0' ;
EPLD_SAM_DIO_IO(2) = '0' ;
EPLD_SAM_DIO_IO(3) = '0' ;

wait for 10 ns;

sam_dio(0) = '0' ;
sam_dio(1) = '1' ;
sam_dio(2) = '1' ;
sam_dio(3) = '1' ;

wait for 10 ns;


Pra testar por exemplo escrita do valor da EPLD_SAM_DIO_IO(0) no uart_xmit...

+++

Re: testbench em VHDL para bus inout

MensagemEnviado: 14 Jan 2014 12:01
por chrdcv
André, mais uma vez obrigado pelo suporte!

Notei que uma mensagem que tu postou simplesmente "sumiu"; certamente devido a migração do servidor do fórum.

Ontem, alterei um pouco a descrição para ficar mais "enxuta", observei novamente o que foi gerado pela síntese (RTL) e pude perceber que ao invés do uso de portas lógicas, multiplexadores foram utilizados (certamente devido ao uso do std_logc_vector (3 downto 0) para comparação).

Código: Selecionar todos
uart_xmit <= EPLD_SAM_DIO_IO(0) when sam_dio_sel = "0111" else
                 EPLD_SAM_DIO_IO(1) when sam_dio_sel = "1011" else
                 EPLD_SAM_DIO_IO(2) when sam_dio_sel = "1101" else
                 EPLD_SAM_DIO_IO(3) when sam_dio_sel = "1110" else '1';

EPLD_SAM_DIO_IO(0) <= EPLD_UART_RECV_I when sam_dio_sel = "1000" else 'Z';
EPLD_SAM_DIO_IO(1) <= EPLD_UART_RECV_I when sam_dio_sel = "0100" else 'Z';
EPLD_SAM_DIO_IO(2) <= EPLD_UART_RECV_I when sam_dio_sel = "0010" else 'Z';
EPLD_SAM_DIO_IO(3) <= EPLD_UART_RECV_I when sam_dio_sel = "0001" else 'Z';


Estou alterando umas partes do testbench, vou ver se posto algo esclarecedor ainda hoje ou amanhã...

chrdcv

Re: testbench em VHDL para bus inout

MensagemEnviado: 14 Jan 2014 22:27
por msamsoniuk
tem um truque em VHDL que facilita 1000% a sua vida: aprender verilog! hahaha (:

Imagem

http://www.asic-world.com/verilog/verilog_one_day.html

Re: testbench em VHDL para bus inout

MensagemEnviado: 15 Jan 2014 10:30
por chrdcv
Putz, devia ter escutado vc em outros posts...

Mas como faço um testbench em verilog para simular um bus de I/O?

Re: testbench em VHDL para bus inout

MensagemEnviado: 15 Jan 2014 12:19
por msamsoniuk
chrdcv escreveu:Putz, devia ter escutado vc em outros posts...

Mas como faço um testbench em verilog para simular um bus de I/O?


eu nao entendi exatamente o que vc precisa, mas imagino que eh algo relacionado com um bus bi-direcional neh... bom, segue um exemplo que faz R/W em uma memoria interna 256 bytes:

Código: Selecionar todos
// memoria 256 bytes, leitura assincrona, escrita sincrona com WR=1
module ble(input CLK, input WR, input [7:0] ADDR, inout [7:0] DATA);
  reg [7:0] MEM [0:255];

  assign DATA = WR ? MEMO : '8bzzzz_zzzz;

  always@(posedge CLK)
  begin
    if(WR) // write
      MEM[ADDR] <= DATA;
  end

endmodule

// teste para o modulo bleh
module bleh_test
  reg CLK = 0;
  reg [8:0] STATE = 0;

  integer i;
  initial
  begin
    for(i=0;i!=100000;i=i+1) // 100 mil passos de simulacao
    begin
      #30 CLK = 0; // clock de 60 nanosegundos
      #30 CLK = 1;
    end
  end

  always@(posedge CLK)
  begin
    STATE <= STATE+1; // tipica maquina de estado incremental
  end

  wire WR = STATE[8];
  wire [7:0] DATA = WR ? STATE[7:0] : 4'bzzzz;
  wire [7:0] ADDR = STATE[7:0];

  bleh bleh0(CLK,WR,ADDR,DATA); // aqui eh onde instancia o modulo a ser testado

endmodule


o teste eh bem simples, basicamente ele grava e le alternadamente todos os 256 enderecos. note que eu costumo usar o initial apenas para gerar CLK e faco o resto sintetizavel (normalmente eu construo o sistema inteiro nos meus testes, entao fazer tudo sintetizavel significa que eu posso reaproveitar partes no futuro)... nao precisa, mas eh eh bom para acostumar a sempre fazer sintetizavel. bom, durante a escrita (STATE[8]==1), ele grava como dado o mesmo valor do endereco e faz isso para os 256 enderecos. mas eh possivel mudar isso na definicao do wire DATA, por exemplo, no lugar de STATE[7:0] usar ~STATE[7:0] vai gravar o inverso. o importante eh observar a consistencia de WR fora e dentro do modulo, pq os lados precisam entrar em tri-state alternadamente, conforme o barramento alterna de input para output e vice-versa.

ah! eu nao testei o codigo... depois eu testo para ver se tem algum bug! (:

Re: testbench em VHDL para bus inout

MensagemEnviado: 15 Jan 2014 17:57
por andre_luis
chrdcv escreveu:...Mas como faço um testbench em verilog para simular um bus de I/O?


O que eu havia entendido no título e na primeira postagem é que a linguagem usada é o VHDL, e não o Verilog.
Bom, o que eu faria seria algo assim ( em VHDL ) :

Código: Selecionar todos
stimulus : process is
begin

-- teste do recebimento
-----------------------
EPLD_SAM_DIO_IO(0) <= "00000000"          ;  -- carrega valor 0 em EPLD_SAM_DIO_IO(0)
sam_dio_sel <= "0111" ; wait for 10 ns    ;  -- uart_xmit recebe o EPLD_SAM_DIO_IO(0)

EPLD_SAM_DIO_IO(1) <= "00000001"          ;  -- carrega valor 1 em EPLD_SAM_DIO_IO(1)
sam_dio_sel <= "1011" ; wait for 10 ns    ;  -- uart_xmit recebe o EPLD_SAM_DIO_IO(2)

EPLD_SAM_DIO_IO(2) <= "00000010"          ;  -- carrega valor 2 em EPLD_SAM_DIO_IO(2)
sam_dio_sel <= "1101" ; wait for 10 ns    ;  -- uart_xmit recebe o EPLD_SAM_DIO_IO(3)

EPLD_SAM_DIO_IO(3) <= "00000011"          ;  -- carrega valor 3 em EPLD_SAM_DIO_IO(3)
sam_dio_sel <= "1110" ; wait for 10 ns    ;  -- uart_xmit recebe o EPLD_SAM_DIO_IO(4)

wait for 10 ns                            ;  -- delay adicional p/a destacar na simulacao

-- teste do envio
-----------------
EPLD_UART_RECV_I   <= "00000100"          ;  -- carrega valor 4 em EPLD_UART_RECV_I
sam_dio_sel(0) <= "1000" ; wait for 10 ns ;  -- EPLD_SAM_DIO_IO(0) recebe o valor de uart_recv

EPLD_UART_RECV_I   <= "00000101"          ;  -- carrega valor 5 em EPLD_UART_RECV_I
sam_dio_sel(1) <= "0100" ; wait for 10 ns ;  -- EPLD_SAM_DIO_IO(1) recebe o valor de uart_recv

EPLD_UART_RECV_I   <= "00000110"          ;  -- carrega valor 6 em EPLD_UART_RECV_I
sam_dio_sel(2) <= "0010" ; wait for 10 ns ;  -- EPLD_SAM_DIO_IO(2) recebe o valor de uart_recv

EPLD_UART_RECV_I   <= "00000111"          ;  -- carrega valor 7 em EPLD_UART_RECV_I
sam_dio_sel(3) <= "0001" ; wait for 10 ns ;  -- EPLD_SAM_DIO_IO(3) recebe o valor de uart_recv

wait for 10 ns                            ;  -- delay adicional p/a destacar na simulacao

wait                                      ;
end process stimulus   


Como uma colher de chá, segue também um rascunho do que entendi do seu circuito:

VHDL.png


+++

Re: testbench em VHDL para bus inout

MensagemEnviado: 15 Jan 2014 20:05
por msamsoniuk
eh q ele perguntou como faria para simular um bus de IO bi-direcional em verilog e eu daih montei um exemplo para ele ver. eu nao arrisquei montar o circuito dele pq achei que era um fragmento combinacional e que havia muito mais circuitos em volta... por exemplo, em verilog os buffers de IO podem ser tipo wire (input, output e inout) ou reg (output), q jah sao referencias a elementos low-level, mas em VHDL o buraco eh mais embaixo e eu sempre vi os caras referenciando explicitamente buffers de IO, pq a logica usa um tipo diferente dos tipos de IO... enfim, se a logica for apenas aquilo, ficaria isso aqui:

Código: Selecionar todos
module chrdcv(input UART_RECV, output UART_XMIT, input [3:0] SAM_DIO_SEL, inout [3:0] EPLD_SAM_DIO_IO)

  assign UART_XMIT  =
                                        SAM_DIO_SEL==4'b0111 ? EPLD_SAM_DIO_IO[0] :
                                        SAM_DIO_SEL==4'b1011 ? EPLD_SAM_DIO_IO[1] :
                                        SAM_DIO_SEL==4'b1101 ? EPLD_SAM_DIO_IO[2] :
                                        SAM_DIO_SEL==4'b1101 ? EPLD_SAM_DIO_IO[3] :
                                         1'b1;

  assign EPLD_SAM_DIO_IO[0] <= SAM_DIO_SEL==4'b0100 ? UART_RECV : 1'bz;
  assign EPLD_SAM_DIO_IO[1] <= SAM_DIO_SEL==4'b0100 ? UART_RECV : 1'bz;
  assign EPLD_SAM_DIO_IO[2] <= SAM_DIO_SEL==4'b0010 ? UART_RECV : 1'bz;
  assign EPLD_SAM_DIO_IO[3] <= SAM_DIO_SEL==4'b0001 ? UART_RECV : 1'bz;

endmodule

module test_chrdcv;

  reg [3:0] SAM_DIO_SEL;
  reg [3:0] EPLD_SAM_IO_REG = 0;

  integer i;

  initial
  begin
    for(i=0;i!=10000;i=i+1)
      EPLD_SAM_IO_REG <= EPLD_SAM_IO_REG + 1;
  end

  wire UART_XMIT;
  wire UART_RECV = EPLD_SAM_IO_REG[0];
  wire [3:0] EPLD_SAM_DIO_IO = SAM_DIO_SEL[3]==1?EPLD_SAM_IO_REG:4'bzzzz;

  chrdcv chrdcv0(UART_RECV, UART_XMIT, SAM_DIO_SEL, EPLD_SAM_DIO_IO);

endmodule


enfim, alguma coisa assim. nao fica muito diferente de VHDL, mas deve ser o dialeto... eu particularmente tentaria fazer algo mais compacto:

Código: Selecionar todos
module chrdcv(input UART_RECV, output UART_XMIT, input RXSEL, input [1:0] SAM_DIO_SEL, inout [3:0] EPLD_SAM_DIO_IO)

  assign UART_XMIT  = RXSEL==1 ? EPLD_SAM_DIO_IO[SAM_DIO_SEL] : 1'b1;
  assign EPLD_SAM_DIO_IO <= RXSEL==0 ? (UART_RECV<<SAM_DIO_SEL) : 4'bzzzz;

endmodule


mas vendo apenas uma parte da logica fica dificil entender pq foi feito de determinada forma e se daria certo de outra.

Re: testbench em VHDL para bus inout

MensagemEnviado: 15 Jan 2014 20:41
por andre_luis
msamsoniuk escreveu:...mas vendo apenas uma parte da logica fica dificil entender pq foi feito de determinada forma e se daria certo de outra.


Também pensei assim, mas depois caiu a ficha e lembrei que ele estava querendo apenas um testbench dos sinais externos.
Desse modo, dá pra atentar somente ás informações de fora da caixa-preta, como os sinais de controle e as entradas e saídas...


+++