¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Avatar de Usuario
Quest
Mensajes: 900
Registrado: 27 Sep 2015, 00:20

Re: ¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Mensaje por Quest » 18 Oct 2015, 15:38

mcleod_ideafix escribió: Los 115200 bps, en sí, no suponen problema para el Spectrum. Lo que agobiaría al Z80 es que transmitiese a esa velocidad sin parar, un byte después de otro. Si hay alguna forma de decirle que entre un byte y el siguiente pasen X microsegundos o algo así, entonces sí que puede con ello.

¿Qué significa el 3 del final de la cadena AT?

Ah! Se me olvidaba: bueno, lo puedes mirar en el UCF, pero los pines que he usado para TX y RX son el 11 y el 16, que se corresponden con dos pines del conector de expansión, a la derecha, en la fila superior de las tres. Está pensado para que esos tres últimos pines sean por tanto TX, RX y GND
Lo del 3, no se, creo que me colé al copiar pegar. De todos modos no funcionaba ne mi firmware, que es más moderno y sólo atiende al comando AT+IPR=115200 , puesto que el comando anterior quedó deprecated en algún momento.

Al margen del ZX-UNO, de todos modos en cuanto cambio la velocidad en la plaquita, funciona unos segundos, se resetea y se queda brickeada con el led fijo y tengo que refleashear el firmware. Tengo mucho que investigar aún. Podría incluso estar mal mi plaquita. Ya iré informando.

Respecto al UCF, sí, ya lo vi pero como tengo que usar mi UCF propio para la v3, me los he reasignado a los pines 12 y 11 que son los que uso siempre para conexión serie (ya los usaba en el core de NES por ejemplo). Funciona bien conectando el ZX-UNO al PC tal como muestras en el video, funcioona estupendamente.

Bueno, pues sigo con ello.
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA

Avatar de Usuario
mcleod_ideafix
Mensajes: 831
Registrado: 27 Sep 2015, 00:14
Ubicación: Jerez de la Frontera
Contactar:

Re: ¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Mensaje por mcleod_ideafix » 18 Oct 2015, 15:44

Quest escribió:Lo del 3, no se, creo que me colé al copiar pegar. De todos modos no funcionaba ne mi firmware, que es más moderno y sólo atiende al comando AT+IPR=115200 , puesto que el comando anterior quedó deprecated en algún momento.
Ya he mirado: el 3 es para habilitar el control de flujo por hardware, así que no me extraña que se quede colgada la plaquita si no recibe las señales RTS y CTS. Con esas dos señales sí que se podría tener a la plaquita funcionando a 115200 bps, siendo el Spectrum el que controlase cuándo puede enviar más datos y cuándo tiene que esperarse. Es que tal y como está, sin control de flujo y a esa velocidad, el Z80 no da para más.
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA

Avatar de Usuario
Quest
Mensajes: 900
Registrado: 27 Sep 2015, 00:20

Re: ¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Mensaje por Quest » 18 Oct 2015, 15:55

No se quedaba colgada por eso, porque ese comando no llegué a poder usarlo. Entiendo que por defecto no viene con el control de flujo por hardware activado, porque me comunico con ella con el terminal PuTTy y lo tengo desactivado ahí, y funcionaba bien.

Otra cosa, tampoco uséis el comando AT+IPR que he dicho antes, que corrompe la flash (confirmado, y lo acabo de leer en más sitios).

Para firmwares 0.95 o superiores, usar el comando: AT+UART_DEF=9600,8,1,0,0 con los valores deseados, claro. (Si no va probar con AT+UART=9600,8,1,0,0)

Respecto a lo que comentas de RTS y CTS y el spectrum, podemos probar, ya que parece que la plaquita soporta dicho control de flujo. ¿Es sencillo añadirlo al uart del core? Y poder activarlo o desactivarlo fácilmente para hacer pruebas...
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA

Avatar de Usuario
Quest
Mensajes: 900
Registrado: 27 Sep 2015, 00:20

Re: ¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Mensaje por Quest » 18 Oct 2015, 17:12

Bueno, he ido bajando y bajando... hasta que en 1200bps la cosa marcha :)
wifi_uart_zxuno_1200.jpg
wifi_uart_zxuno_1200.jpg (35.95 KiB) Visto 6858 veces
Pero claro, 1200 no es demasiado interesante, sobre todo para cargar TAPs, hace de "spectranet", etc, si queremos que la velocidad de carga sea aceptable.
A ver si llegamos a algún lado con el tema del control de flujo o alguna otra solución, con DMA o lo que sea.
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA

Avatar de Usuario
jepalza
Mensajes: 613
Registrado: 02 Oct 2015, 18:52

Re: ¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Mensaje por jepalza » 19 Oct 2015, 19:13

Acabo de probar un módulo sacado de "fpga4fun", que emula un puerto RS232 a "115200,8,2,n", y funciona (creo) que bien.
He utilizado los pines del puerto de expansión nºs 32 y 36 (J11-P12 y J11-P13) para los Txd y Rxd, y he hecho que, desde el PC, se envíe una pulsación de teclado (en el famoso Hyperterminal, en modo VT100) y que el ZXUNO me responda con el mismo carácter incrementado en uno ("usease", si pulso "1", me devuelve "2") y funciona bien. He probado a enviar un archivo de texto ascii grande, para ver que tal responde a 115200, y con algún fallito, lo ha hecho bien.

si queréis probar (o implementarlo al ZXUNO) este es el código:

MODULO PRINCIPAL

Código: Seleccionar todo

// 115200,8,2,n
module serialGPIO(
    input clk50mhz,
    input RxD,
    output TxD
);

wire RxD_data_ready;
wire [7:0] RxD_data;
reg [7:0] tengodato;

async_receiver RX (
// in
 .clk(clk50mhz),
 .RxD(RxD), // leo desde el PC
// out
 .RxD_data_ready(RxD_data_ready),
 .RxD_data(RxD_data) // cuando tengo 8 bits, saco dato
 );

// el dato obtenido en el receiver, lo envio a TX, sumando +1
always @(posedge clk50mhz) if(RxD_data_ready) tengodato<=RxD_data+1'b1;

async_transmitter TX (
// in
 .clk(clk50mhz),
 .TxD_start(RxD_data_ready),
 .TxD_data(tengodato), // dato recibido por el receiver
// out
 .TxD(TxD) //lo envio de vuelta al PC, pero incrementado +1 como prueba
 );
 
endmodule


MODULO RS232

Código: Seleccionar todo

////////////////////////////////////////////////////////
// RS-232 RX and TX module
// (c) fpga4fun.com & KNJN LLC - 2003 to 2013

// The RS-232 settings are fixed
// TX: 8-bit data, 2 stop, no-parity
// RX: 8-bit data, 1 stop, no-parity (the receiver can accept more stop bits of course)

//`define SIMULATION   // in this mode, TX outputs one bit per clock cycle
                       // and RX receives one bit per clock cycle (for fast simulations)

////////////////////////////////////////////////////////
module async_transmitter(
	input clk,
	input TxD_start,
	input [7:0] TxD_data,
	output TxD,
	output TxD_busy
);

// Assert TxD_start for (at least) one clock cycle to start transmission of TxD_data
// TxD_data is latched so that it doesn't have to stay valid while it is being sent

parameter ClkFrequency = 50000000;	// 50MHz
parameter Baud = 115200;

//generate
//	if(ClkFrequency<Baud*8 && (ClkFrequency % Baud!=0)) ASSERTION_ERROR PARAMETER_OUT_OF_RANGE("Frequency incompatible with requested Baud rate");
//endgenerate

////////////////////////////////
//`ifdef SIMULATION
//wire BitTick = 1'b1;  // output one bit per clock cycle
//`else
wire BitTick;
BaudTickGen #(ClkFrequency, Baud) tickgen(.clk(clk), .enable(TxD_busy), .tick(BitTick));
//`endif

reg [3:0] TxD_state = 0;
wire TxD_ready = (TxD_state==0);
assign TxD_busy = ~TxD_ready;

reg [7:0] TxD_shift = 0;
always @(posedge clk)
begin
	if(TxD_ready & TxD_start)
		TxD_shift <= TxD_data;
	else
	if(TxD_state[3] & BitTick)
		TxD_shift <= (TxD_shift >> 1);

	case(TxD_state)
		4'b0000: if(TxD_start) TxD_state <= 4'b0100;
		4'b0100: if(BitTick) TxD_state <= 4'b1000;  // start bit
		4'b1000: if(BitTick) TxD_state <= 4'b1001;  // bit 0
		4'b1001: if(BitTick) TxD_state <= 4'b1010;  // bit 1
		4'b1010: if(BitTick) TxD_state <= 4'b1011;  // bit 2
		4'b1011: if(BitTick) TxD_state <= 4'b1100;  // bit 3
		4'b1100: if(BitTick) TxD_state <= 4'b1101;  // bit 4
		4'b1101: if(BitTick) TxD_state <= 4'b1110;  // bit 5
		4'b1110: if(BitTick) TxD_state <= 4'b1111;  // bit 6
		4'b1111: if(BitTick) TxD_state <= 4'b0010;  // bit 7
		4'b0010: if(BitTick) TxD_state <= 4'b0011;  // stop1
		4'b0011: if(BitTick) TxD_state <= 4'b0000;  // stop2
		default: if(BitTick) TxD_state <= 4'b0000;
	endcase
end

assign TxD = (TxD_state<4) | (TxD_state[3] & TxD_shift[0]);  // put together the start, data and stop bits
endmodule


////////////////////////////////////////////////////////
module async_receiver(
	input clk,
	input RxD,
	output reg RxD_data_ready = 0,
	output reg [7:0] RxD_data = 0,  // data received, valid only (for one clock cycle) when RxD_data_ready is asserted

	// We also detect if a gap occurs in the received stream of characters
	// That can be useful if multiple characters are sent in burst
	//  so that multiple characters can be treated as a "packet"
	output RxD_idle,  // asserted when no data has been received for a while
	output reg RxD_endofpacket = 0  // asserted for one clock cycle when a packet has been detected (i.e. RxD_idle is going high)
);

parameter ClkFrequency = 50000000; // 50MHz
parameter Baud = 115200;

parameter Oversampling = 8;  // needs to be a power of 2
// we oversample the RxD line at a fixed rate to capture each RxD data bit at the "right" time
// 8 times oversampling by default, use 16 for higher quality reception

//generate
//	if(ClkFrequency<Baud*Oversampling) ASSERTION_ERROR PARAMETER_OUT_OF_RANGE("Frequency too low for current Baud rate and oversampling");
//	if(Oversampling<8 || ((Oversampling & (Oversampling-1))!=0)) ASSERTION_ERROR PARAMETER_OUT_OF_RANGE("Invalid oversampling value");
//endgenerate

////////////////////////////////
reg [3:0] RxD_state = 0;

`ifdef SIMULATION
wire RxD_bit = RxD;
wire sampleNow = 1'b1;  // receive one bit per clock cycle

`else
wire OversamplingTick;
BaudTickGen #(ClkFrequency, Baud, Oversampling) tickgen(.clk(clk), .enable(1'b1), .tick(OversamplingTick));

// synchronize RxD to our clk domain
reg [1:0] RxD_sync = 2'b11;
always @(posedge clk) if(OversamplingTick) RxD_sync <= {RxD_sync[0], RxD};

// and filter it
reg [1:0] Filter_cnt = 2'b11;
reg RxD_bit = 1'b1;

always @(posedge clk)
if(OversamplingTick)
begin
	if(RxD_sync[1]==1'b1 && Filter_cnt!=2'b11) Filter_cnt <= Filter_cnt + 1'd1;
	else 
	if(RxD_sync[1]==1'b0 && Filter_cnt!=2'b00) Filter_cnt <= Filter_cnt - 1'd1;

	if(Filter_cnt==2'b11) RxD_bit <= 1'b1;
	else
	if(Filter_cnt==2'b00) RxD_bit <= 1'b0;
end

// and decide when is the good time to sample the RxD line
function integer log2(input integer v); begin log2=0; while(v>>log2) log2=log2+1; end endfunction
localparam l2o = log2(Oversampling);
reg [l2o-2:0] OversamplingCnt = 0;
always @(posedge clk) if(OversamplingTick) OversamplingCnt <= (RxD_state==0) ? 1'd0 : OversamplingCnt + 1'd1;
wire sampleNow = OversamplingTick && (OversamplingCnt==Oversampling/2-1);
`endif

// now we can accumulate the RxD bits in a shift-register
always @(posedge clk)
case(RxD_state)
	4'b0000: if(~RxD_bit) RxD_state <= `ifdef SIMULATION 4'b1000 `else 4'b0001 `endif;  // start bit found?
	4'b0001: if(sampleNow) RxD_state <= 4'b1000;  // sync start bit to sampleNow
	4'b1000: if(sampleNow) RxD_state <= 4'b1001;  // bit 0
	4'b1001: if(sampleNow) RxD_state <= 4'b1010;  // bit 1
	4'b1010: if(sampleNow) RxD_state <= 4'b1011;  // bit 2
	4'b1011: if(sampleNow) RxD_state <= 4'b1100;  // bit 3
	4'b1100: if(sampleNow) RxD_state <= 4'b1101;  // bit 4
	4'b1101: if(sampleNow) RxD_state <= 4'b1110;  // bit 5
	4'b1110: if(sampleNow) RxD_state <= 4'b1111;  // bit 6
	4'b1111: if(sampleNow) RxD_state <= 4'b0010;  // bit 7
	4'b0010: if(sampleNow) RxD_state <= 4'b0000;  // stop bit
	default: RxD_state <= 4'b0000;
endcase

always @(posedge clk)
if(sampleNow && RxD_state[3]) RxD_data <= {RxD_bit, RxD_data[7:1]};

//reg RxD_data_error = 0;
always @(posedge clk)
begin
	RxD_data_ready <= (sampleNow && RxD_state==4'b0010 && RxD_bit);  // make sure a stop bit is received
	//RxD_data_error <= (sampleNow && RxD_state==4'b0010 && ~RxD_bit);  // error if a stop bit is not received
end

reg [l2o+1:0] GapCnt = 0;
always @(posedge clk) if (RxD_state!=0) GapCnt<=0; else if(OversamplingTick & ~GapCnt[log2(Oversampling)+1]) GapCnt <= GapCnt + 1'h1;
assign RxD_idle = GapCnt[l2o+1];
always @(posedge clk) RxD_endofpacket <= OversamplingTick & ~GapCnt[l2o+1] & &GapCnt[l2o:0];
endmodule

////////////////////////////////////////////////////////
// dummy module used to be able to raise an assertion in Verilog
module ASSERTION_ERROR();
endmodule

////////////////////////////////////////////////////////
module BaudTickGen(
	input clk, enable,
	output tick  // generate a tick at the specified baud rate * oversampling
);
parameter ClkFrequency = 50000000;
parameter Baud = 115200;
parameter Oversampling = 1;

function integer log2(input integer v); begin log2=0; while(v>>log2) log2=log2+1; end endfunction
localparam AccWidth = log2(ClkFrequency/Baud)+8;  // +/- 2% max timing error over a byte
reg [AccWidth:0] Acc = 0;
localparam ShiftLimiter = log2(Baud*Oversampling >> (31-AccWidth));  // this makes sure Inc calculation doesn't overflow
localparam Inc = ((Baud*Oversampling << (AccWidth-ShiftLimiter))+(ClkFrequency>>(ShiftLimiter+1)))/(ClkFrequency>>ShiftLimiter);
always @(posedge clk) if(enable) Acc <= Acc[AccWidth-1:0] + Inc[AccWidth:0]; else Acc <= Inc[AccWidth:0];
assign tick = Acc[AccWidth];
endmodule


PINES

Código: Seleccionar todo

NET "clk50mhz" LOC="P55" | IOSTANDARD = LVCMOS33;
NET "RxD"  LOC="P16" | IOSTANDARD = LVCMOS33; # J11-P12 (ext-32)
NET "TxD"  LOC="P11" | IOSTANDARD = LVCMOS33; # J11-P13 (ext-36)


Al módulo RS232 le he quitado unas líneas de comprobación de datos, por que me da error al sintetizar, y pasaba de volverme loco, para una simple prueba.

De este modo, podemos tener RS232 en el ZXUNO sin hardware externo, que no sea un conversor de niveles PC-ZXUNO (uno de 3.3 a los 12 del PC)

Avatar de Usuario
jepalza
Mensajes: 613
Registrado: 02 Oct 2015, 18:52

Re: ¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Mensaje por jepalza » 19 Oct 2015, 19:21

Perdón, me acabo de dar cuenta, que he contesto a un hilo sobre wifi (lo tenía abierto y no me ha dado cuenta), cuando quería haber abierto uno nuevo.
Si podeís moverlo, y borrar de aquí.... :oops:

Avatar de Usuario
Quest
Mensajes: 900
Registrado: 27 Sep 2015, 00:20

Re: ¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Mensaje por Quest » 19 Oct 2015, 19:23

jepalza escribió: y he hecho que, desde el PC, se envíe una pulsación de teclado (en el famoso Hyperterminal, en modo VT100) y que el ZXUNO me responda con el mismo carácter incrementado en uno ("usease", si pulso "1", me devuelve "2") y funciona bien. He probado a enviar un archivo de texto ascii grande, para ver que tal responde a 115200, y con algún fallito, lo ha hecho bien.
Cuando dices que "el ZXUNO me responda..." ¿Te estás refiriendo al spectrum o simplemente al propio UART implementado en la FPGA al margen del spectrum?

Esta línea me hace sospechar que es lo segundo:

Código: Seleccionar todo

always @(posedge clk50mhz) if(RxD_data_ready) tengodato<=RxD_data+1'b1;
Es que en ese caso, seguimos en las mismas, porque el problema es con el Z80 (no le da al tiempo al pobre a procesar), no con la UART en sí. Por lo que veo no pasas por el Z80, no? (igual estoy equivocado).

Seguramente haga falta hacer algo como lo que comentaba mcleod, de implementar handshaking por hardware (RTS/CTS).
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA

Avatar de Usuario
jepalza
Mensajes: 613
Registrado: 02 Oct 2015, 18:52

Re: ¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Mensaje por jepalza » 19 Oct 2015, 19:31

Si bueno, me refiero a la placa ZXUNO, no al Spectrum. No hay Spectrum en el test que he hecho. Pero es que me he colado de hilo, si puedes leer mi anterior respuesta.
A raíz de las pruebas que hacíais, quería hacer lo propio (ya que no tengo el wifi), pero mediante cable, y publicar los resultados en un hilo nuevo, y me he colado al responder aquí. :oops:

Voy a abrir un hilo nuevo para que quede allí, y este que se quede como simple comentario.

Avatar de Usuario
Quest
Mensajes: 900
Registrado: 27 Sep 2015, 00:20

Re: ¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Mensaje por Quest » 19 Oct 2015, 19:42

Ok, no pasa nada ;) Yo tampoco me había percatado que era un tema al margen.
Ya he visto que has abierto el hilo nuevo. Bueno, podemos dejar el mensaje aquí también, daño no hace a nadie, al contrario :chocala!:
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA

Avatar de Usuario
mcleod_ideafix
Mensajes: 831
Registrado: 27 Sep 2015, 00:14
Ubicación: Jerez de la Frontera
Contactar:

Re: ¿Qué os parece esto para añadir wifi con muy poquitas líneas en el conector de expansión?

Mensaje por mcleod_ideafix » 20 Oct 2015, 00:19

Los 115200 bps no son el problema, ya que la UART que tenemos en el ZX-Uno es una UART hardware, no una implementación por bit-banging como tiene el Spectrum 128K.

El problema es cuando el transmisor envía datos sin pausa entre ellos. Entonces es cuando no hay tiempo para que el Z80 procese un dato. La solución es tan antigua como el RS232, y es usar handshaking por hardware. Si en el módulo wifi está bien implementado, vereis como no perdemos ni un byte a 115200. Será el Z80 el que dicte la tasa real de transferencia. La secuencia cuando el módulo wifi transmite y el ZX-Uno recibe queda así:

- El módulo UART del ZX-Uno aserta la línea CTS si el registro de recepción está vacío (esto es, si el Z80 leyó el byte que había ahí y no ha llegado ninguno nuevo)
- El módulo wifi tiene conectada esta señal a su señal RTS, y la toma como vía libre para enviar datos. Empieza a enviar un dato.
- Cuando el dato llega al ZX-Uno, éste lo meve al registro de recepción y deaserta la línea CTS. El módulo wifi ve por tanto que su línea RTS baja, parando la transmisión.
- Eones de tiempo más tarde, el Z80 ve que hay un dato nuevo en la UART y lo lee. En ese momento, CTS vuelve a activarse permitiendo que el móduilo wifi transmita otro dato.

La secuencia contraria, ZX-Uno transmite y wifi recibe es tal que así: la línea RTS del ZX-Uno se conecta a la señal CTS de la wifi.
- El Z80 primero comprueba que el registo de transmisión está vacío. Si es así, escribe un nuevo dato.
- El dato se queda en el registro de transmisión hasta que la UART detecta que su señal RTS se activa (porque la wifi ha activado su CTS). Cuando esto ocurre, se transmite por RS232 el dato, y se marca el registro de transmisión como vacío.

(en realidad estas cosas las tengo que repasar bien porque,según donde lea, el significado de RTS y CTS se intercambia. Otra cosa que tampoco tengo claro son los niveles lógicos. No sé si para activar RTS, o CTS, la señal debe ponerse a 1 o a 0.
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA

Responder