A ver si me aclaro con este tema, ya que hace tiempo que lo voy sorteando pero no acabo de aclararme.
Alguien me puede explicar cómo se simula el valor de una entrada en un pin inout. Si se asigna a pelo bien da error cuando lo intentas simular, bien no te hace ni caso.
Yo sorteo el tema utilizando force, pero creo que no es una buena práctica.
Simulación de pines inout desde un testbench
- mcleod_ideafix
- Site Admin
- Mensajes: 80
- Registrado: 14 Ago 2018, 01:15
Re: Simulación de pines inout desde un testbench
¿Puedes poner un código de ejemplo de lo que te gustaría poder simular? ¿Y en qué lenguaje? Porque lo has puesto en el foro de ISE, pero creo que tu pregunta va más encaminada a cómo se simula en Verilog, no es eso?wilco2009 escribió: ↑18 Ago 2018, 16:24A ver si me aclaro con este tema, ya que hace tiempo que lo voy sorteando pero no acabo de aclararme.
Alguien me puede explicar cómo se simula el valor de una entrada en un pin inout. Si se asigna a pelo bien da error cuando lo intentas simular, bien no te hace ni caso.
Yo sorteo el tema utilizando force, pero creo que no es una buena práctica.
Re: Simulación de pines inout desde un testbench
Efectivamente la pregunta está mal situada. Debería moverse al foro de Verilog.
Tenemos un interface como el de abajo, en el que una CPLD está conectada por un lado a todos los pines de una SRAM paralela, por el otro al bus del sistema y por último a un puerto SPI de un microcontrolador.
El microcontrolador puede leer o escribir datos en la SRAM a través del puerto SPI pasando por la CPLD que los convierte a paralelo y que es la que conecta con la SRAM.
El problema viene cuando quiero simular los datos que vienen desde la SRAM hacia la CPLD. Si no hago nada, la entrada es 8'bzzzzzzzz, ya que la entrada es un inout con la siguiente definición:
Si declaro RAM_Data como wire [7:0] me da un error al assignarla (como es lógico), pero si la declaro como reg [7:0] me da error cuando intento arrancar la simulación diciendo "non-net variable can't be connected to inout port RAM_Data".
Por lo que me veo obligado a utilizar wire y asignar con force.
¿No hay alternativa, o esta es la manera natural de hacerlo?
Tenemos un interface como el de abajo, en el que una CPLD está conectada por un lado a todos los pines de una SRAM paralela, por el otro al bus del sistema y por último a un puerto SPI de un microcontrolador.
Código: Seleccionar todo
wire [7:0] RAM_Data;
PSRAMArduino uut (
.Enable_Arduino(Enable_Arduino),
.Arduino_Data_out_Bit(Arduino_Data_out_Bit),
.Arduino_Data_in_Bit(Arduino_Data_in_Bit),
.Arduino_Clk(Arduino_Clk),
.Arduino_download(Arduino_download),
.Arduino_upload(Arduino_upload),
.RAM_Addr(RAM_Addr),
.RAM_Data(RAM_Data),
.RAM_WR(RAM_WR),
.RAM_OE(RAM_OE),
.RAM_CS(RAM_CS),
.Computer_Addr(Computer_Addr),
.Computer_Data(Computer_Data),
.Computer_WR(Computer_WR),
.Computer_OE(Computer_OE),
.Computer_CS(Computer_CS),
.nReset(nReset)
);
El problema viene cuando quiero simular los datos que vienen desde la SRAM hacia la CPLD. Si no hago nada, la entrada es 8'bzzzzzzzz, ya que la entrada es un inout con la siguiente definición:
Código: Seleccionar todo
assign RAM_Data = (Enable_Arduino==1'b0) && (Arduino_WR==1'b0)? Computer_Data:
8'bzzzzzzzz;
Por lo que me veo obligado a utilizar wire y asignar con force.
¿No hay alternativa, o esta es la manera natural de hacerlo?
Código: Seleccionar todo
#10;
force RAM_Data = 8'b11101010;
#10;
Arduino_download = 1;
#10;
for (i=0;i<=15;i=i+1)
begin
Arduino_Clk = !Arduino_Clk;
#10;
end
- mcleod_ideafix
- Site Admin
- Mensajes: 80
- Registrado: 14 Ago 2018, 01:15
Re: Simulación de pines inout desde un testbench
Entonces, lo que tú quieres es un módulo que permita simular una RAM, tal como una 62256 (creo que es la que usas, no?) de 32K x 8, y con pines de entrada/salida, de forma que la puedas incorporar a tu simulación, no?
A ver si esto te vale:
En tu testbench, conecta esta RAM a tu controlador tal y como lo harías en el circuito real, y arranca la simulación. Ten en cuenta que al principio, lo que leas de la RAM será todo XXXXXXXX porque no habrá valor definido. Si por la razón que sea quieres inicializar toda la RAM a 0, justo después del reg [7:0] ram [0:32767] pon esto:
A ver si esto te vale:
Código: Seleccionar todo
module ram_62256 (
input wire [14:0] a,
input wire cs_n,
input wire oe_n,
input wire we_n,
inout wire [7:0] d
);
reg [7:0] ram[0:32767];
assign d = (cs_n == 1'b0 && oe_n == 1'b0 && we_n == 1'b1)? ram[a] : 8'hZZ;
always @* begin
if (cs_n == 1'b0 && we_n == 1'b0)
ram[a] = d;
end
endmodule
Código: Seleccionar todo
integer i;
initial begin
for (i=0;i<32768;i=i+1)
ram[i] = 8'h00;
end
- mcleod_ideafix
- Site Admin
- Mensajes: 80
- Registrado: 14 Ago 2018, 01:15
Re: Simulación de pines inout desde un testbench
Un ejemplo de testbench para esta RAM (imitando un poco la forma en la que el la ROM del ZX Spectrum chequea la RAM al principio):
https://www.edaplayground.com/x/2yv9
Fíjate que el truco está en que aquello a lo que conectes un puerto inout sea siempre un wire, y nunca un reg, y que este wire (dato, en el ejemplo) tenga siempre un valor (con assign). En este caso, ese valor es o bien un dato que proviene de un registro (dato_escrito), cuando queremos escribir, o bien "alta impedancia" cuando lo que queremos es leer. En este último caso, leeríamos directamente desde el wire al que conectas el puerto (dato)
Testbench:
https://www.edaplayground.com/x/2yv9
Fíjate que el truco está en que aquello a lo que conectes un puerto inout sea siempre un wire, y nunca un reg, y que este wire (dato, en el ejemplo) tenga siempre un valor (con assign). En este caso, ese valor es o bien un dato que proviene de un registro (dato_escrito), cuando queremos escribir, o bien "alta impedancia" cuando lo que queremos es leer. En este último caso, leeríamos directamente desde el wire al que conectas el puerto (dato)
Testbench:
Código: Seleccionar todo
module test_ram;
reg [14:0] direccion;
wire [7:0] dato;
reg we_n = 1'b1;
reg oe_n = 1'b1;
reg [7:0] dato_leido, dato_escrito;
assign dato = (we_n == 1'b0)? dato_escrito : 8'hZZ;
ram_62256 la_ram (
.a(direccion),
.cs_n(1'b0),
.oe_n(oe_n),
.we_n(we_n),
.d(dato)
);
initial begin
direccion = 0;
we_n = 1;
oe_n = 1;
dato_escrito = 8'h80;
// Paso 1: guardamos el valor 80h en toda la memoria
repeat (32768) begin
#10; // un poco de tiempo para que el dato esté estable
we_n = 0;
#10; // otro poco de tiempo para que se escriba el dato
we_n = 1;
direccion = direccion + 1;
end
direccion = 0;
we_n = 1;
oe_n = 1;
// Paso 2: leemos el valor guardado, restamos 1, y volvemos a guardar
repeat (32768) begin
oe_n = 0;
#10; // un poco de tiempo para que el dato esté estable
dato_leido = dato;
#10; // otro poco de tiempo para que se escriba el registro dato_leido
oe_n = 1;
dato_escrito = dato_leido + 8'hFF; // restamos 1
#10; // un poco de tiempo para que el dato esté estable
we_n = 0;
#10; // otro poco de tiempo para que se escriba el dato
we_n = 1;
direccion = direccion + 1;
end
direccion = 0;
we_n = 1;
oe_n = 0;
// Paso 3: comprobar que en todas las celdas el valor es 7Fh
repeat (32768) begin
#10; // un poco de tiempo para que el dato esté estable
dato_leido = dato;
#10; // otro poco de tiempo para que se escriba el registro dato_leido
if (dato_leido != 8'h7F) begin
$display ("Error en direccion %h. Leido: %h\n", direccion, dato_leido);
$finish;
end
direccion = direccion + 1;
end
$display ("Todo correcto!\n");
$finish;
end
endmodule