1
0
mirror of git://projects.qi-hardware.com/nn-usb-fpga.git synced 2024-12-12 22:03:45 +02:00
nn-usb-fpga/cap_keyboard/logic/UART/uart.v
2010-11-30 19:26:56 -05:00

1319 lines
31 KiB
Verilog

`timescale 1ns / 1ps
/******************************************************************************/
/* SIDSA */
/******************************************************************************/
/* HSDT100 ARM PERIPHERALS */
/* */
/* MODULE: UART */
/* */
/* FILE: UART_PC.v VERSION:3.0 DATE: 19-I-98 */
/******************************************************************************/
module UART (reset, CLK, data_in, data_out, add, nRW, CS,
RxD, TxD, nIRQ, CD, RI, DSR, CTS, DTR, RTS);
input reset; // Reset (H)
input CLK; // System clock
input [7:0] data_in; // Input Data Bus
input [2:0] add; // Address Bus
input nRW; // Read_ / Write from ARM
input CS; // UART Chip Select
input RxD; // Receiver Data Line
input CD; // Carrier Detect
input RI; // Ring Indicator
input DSR; // Data Send Ready
input CTS; // Clear To Send
output RTS; // Request To Send
output DTR; // Data Terminal Ready
output TxD; // Transmiter Data Line
output nIRQ; // Interrupt Request Output to ARM
output [7:0] data_out; // Output Data Bus
// Variables
//.............................................................
wire [7:0] dato_rx; // Dato recibido
wire [7:0] dato_tx; // Dato para transmitir
wire err_paridad; // Error de paridad (H)
wire err_frame; // Error de trama (H)
wire err_overrun; // Error de rebosamiento (H)
wire error; // Error (OR de los anteriores)
wire rx_lleno; // Dato disponible
wire tx_empty; // Transmisor vacio
wire txt_empty; // Transmisor completamente vacio
wire borrar_rdy; // Borrar dato_rdy tras leer DATO_RX
wire borrar_err; // Borrar err_over tras leer STATUS_RX
wire carga; // Senal carga
wire carga_div; // Senal carga cte_div
wire clkl; // Frecuencia de reloj dividida
wire clkls; // Reloj de muestreo sincronizado (el nivel
// alto dura un periodo de reloj)
wire RxDs; // Senal RxD sincronizada y limpia
wire sample; // Impulso de muestreo de la senal RxDs
wire samples; // Impulso de muestreo de RxDs conformado
wire load_shift;
wire carga_IER; // senal carga IER
wire carga_MCR; // senal carga MCR
wire carga_LCR; // senal carga LCR
wire carga_MSR; // senal carga MSR (para codificacion delta)
wire carga_ISR; // senal carga ISR
wire [1:0] WordLength; // CONFIGURACIONES UART
wire Stop;
wire ParityEnable;
wire Parity;
wire ParityForced;
wire Break;
wire BaudSelect;
wire modem_int;
wire [7:0] modem;
wire [3:0] ISR;
wire [7:0] LSR;
wire [7:0] LCR;
wire [3:0] IER;
//.............................................................
// The default comunication speed is 115200 (clk = 50MHz); divide the clock if you want another speed
// The Minimun Clk frequency is 50Mz
// 50000000/115200 = 434 => 16 X 27 = 432
pc_if_arm_pc if_arm1 (reset, CLK, data_in, data_out, add, nRW, CS,
borrar_rdy, borrar_err,
carga, carga_div_low, carga_div_high,
carga_IER, carga_MCR,
carga_LCR, carga_MSR, carga_ISR,
BaudSelect, dato_rx, modem, ISR, LSR, LCR);
pc_div27 div27(reset, CLK, 1'b1, clk_pres);
pc_div_ms div_ms1 (reset, CLK, clk_pres,data_in, carga_div_low, carga_div_high, clkl);
pc_pulso pulso1(reset, CLK, clkl, clkls);
pc_div16 div161(reset, CLK, clkls, clktx);
pc_ifrxd ifrxd1(reset, CLK, clkls, RxD, RxDs);
pc_muestreo muestreo1(reset, CLK, rx_lleno, clkls, RxDs, sample);
pc_pulso pulso2(reset, CLK, sample, samples);
pc_buffrx_pc buffrx1(reset, CLK, RxDs, samples, rx_lleno, dato_rx, err_paridad,
err_frame, ParityEnable, Parity, ParityForced);
pc_ctrl_rx ctrl_rx1(reset, CLK, samples, rx_lleno);
pc_dato_rdy dato_rdy1(reset, CLK, rx_lleno, borrar_rdy, borrar_err, dato_rdy,
err_overrun);
pc_pulso pulso3(reset, CLK, clktx, clktxs);
pc_bufftx bufftx1 (reset, CLK, carga, load_shift, clktxs, data_in, TxD,
ParityEnable, Parity, ParityForced);
pc_ctrl_tx_pc ctrl_tx1 (reset, CLK, carga, clktxs, load_shift, tx_empty,
txt_empty);
//pc_modem m1(reset, CLK, carga_MCR, carga_MSR, data_in, modem,
// CD, RI, DSR, CTS, DTR, RTS, modem_int);
pc_ier ier1(reset, CLK, carga_IER, data_in, dato_rdy, tx_empty, modem_int, nIRQ, IER);
pc_lcr lcr1(reset, CLK, LCR, carga_LCR, data_in,
WordLength, Stop, ParityEnable, Parity,
ParityForced, Break, BaudSelect);
pc_isr isr1(reset, CLK, carga_ISR,
err_paridad, err_frame, err_overrun,
dato_rdy, tx_empty, txt_empty, modem_int,
ISR, LSR, IER);
endmodule
//............................................................
// BUFFER RECEIVER
//
//............................................................
module pc_buffrx_pc (reset, CLK, RxDs, samples, fin_rx, datorx,
err_paridad, err_frame,
ParityEnable, Parity, ParityForced);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input RxDs; // Linea RxD limpia
input samples; // Impulso de muestreo de RxDs conformado
input fin_rx; // Indicador (L) de recepcion en curso
output [7:0] datorx; // Dato recibido
output err_paridad; // Error de paridad (H)
output err_frame; // Error en el bit de parada (H)
input ParityEnable; // Habilitacion de paridad
input Parity; // Paridad
input ParityForced; // Valor de paridad forzada.
// Variables
//.............................................................
reg [9:0] bufrx; // Registro serie-paralelo del Receptor
// bufrx[7:0]=dato, bufrx[8]=paridad
// bufrx[9]=parada
reg [7:0] datorx; // Dato recibido
reg err_paridad; // Error de paridad (H)
reg err_frame; // Error en el bit de parada (H)
wire iparity;
//.............................................................
// Si el numero de 1s es par, iparity =1
assign iparity = bufrx[8] ^ bufrx[7] ^ bufrx[6]
^ bufrx[5] ^ bufrx[4] ^ bufrx[3]
^ bufrx[2] ^ bufrx[1] ^ bufrx[0];
always @(posedge CLK or posedge reset)
begin
if (reset)
begin
bufrx <= 0;
datorx <= 0;
err_paridad <= 0;
err_frame <= 0;
end
else casex ({fin_rx, samples})
2'bx1: begin
bufrx <= bufrx >> 1;
bufrx[9] <= RxDs;
end
2'b1x: begin
datorx <= bufrx[7:0];
casex ({ParityForced, Parity, ParityEnable})
3'bxx0: err_paridad <= 0; // No parity
3'b001: err_paridad <= ~iparity; // ODD parity
3'b011: err_paridad <= iparity; // EVEN parity
3'b101: err_paridad <= 1; // forced parity
3'b111: err_paridad <= 0; // forced parity
endcase
err_frame <= !bufrx[9];
end
endcase
end
endmodule
//............................................................
// BUFFER TRANSMITER
//............................................................
module pc_bufftx (reset, CLK, carga, load_shift, enable, datotx, TxD,
ParityEnable, Parity, ParityForced);
input reset; // Reset (H). Lo pone a UNOS.
input CLK; // Reloj del sistema
input carga; // Carga (H) nuevo dato
input load_shift; // Carga(H)/Desplaza(L) dato en reg P-S
input enable; // Habilitacion (H) del reg P-S
input [7:0] datotx; // Dato para transmitir
output TxD; // Salida
input ParityEnable; // Habilitacion de paridad
input Parity; // Paridad
input ParityForced; // Valor de paridad forzada.
// Variables
//.............................................................
reg [7:0] dato_tx; // Registro del dato para transmitir
reg [10:0] buftx; // Registro paralelo-serie del Transmisor
// buftx[8:1]=dato, buftx[9]=paridad
// buftx[0]=arranque, parada
wire TxD; // Salida
wire iparity; // Evaluacion de la paridad
//.............................................................
// iparity is 1 when number of ones is odd.
assign iparity = dato_tx[7] ^ dato_tx[6]
^ dato_tx[5] ^ dato_tx[4]
^ dato_tx[3] ^ dato_tx[2]
^ dato_tx[1] ^ dato_tx[0];
always @(posedge CLK or posedge reset)
begin
if (reset)
begin
dato_tx <= 0;
buftx[10:0] <= 11'h7FF;
end
else casex ({load_shift, enable, carga})
3'bxx1: begin
dato_tx <= datotx;
end
3'b01x: begin
buftx[9:0] <= buftx[10:1];
buftx[10] <= 1;
end
3'b11x: begin
buftx[8:1] <= dato_tx;
buftx[0] <= 0;
casex ({ParityForced, Parity, ParityEnable})
3'bxx0: buftx[9] <= 1; // No parity
3'b001: buftx[9] <= ~iparity; // ODD parity
3'b011: buftx[9] <= iparity; // EVEN parity
3'b101: buftx[9] <= 1; // forced parity
3'b111: buftx[9] <= 0; // forced parity
endcase
end
endcase
end
assign TxD = buftx[0];
endmodule
//............................................................
// RECEIVER CONTROL
//............................................................
module pc_ctrl_rx (reset, CLK, samples, rx_lleno);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input samples; // Impulso de muestreo de RxDs conformado
output rx_lleno; // Indica (H) final de la recepcion de un caracter
// Variables
//.............................................................
reg rx_lleno; // Indica (H) final de la recepcion de un caracter
reg [3:0] cont_rx;// Contador de bits recibidos
//.............................................................
always @(posedge CLK or posedge reset)
begin
if (reset)
begin
rx_lleno <= 0;
cont_rx <= 0;
end
else if (samples)
begin
cont_rx <= cont_rx + 1;
if (cont_rx==10)
begin
rx_lleno <= 1;
cont_rx <= 0;
end
else
rx_lleno <= 0;
end
else
rx_lleno <= 0;
end
endmodule
//............................................................
// TRANSMMITER CONTROL
//............................................................
module pc_ctrl_tx_pc (reset, CLK, carga, enable, load_shift,
tx_empty, txt_empty);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input carga; // Carga (H) de un nuevo dato
input enable; // Habilitacion (H)
output load_shift; // Carga(H)/Desplaza(L) en reg P-S
output tx_empty; // Indica (H) TX vacio (PP)
output txt_empty; // Indica (H) TX totalmente vacio (PP y PS)
// Variables
//.............................................................
wire load_shift; // Carga(H)/Desplaza(L) en reg P-S
reg tx_empty; // Indica (H) buffer de tx vacio (PP)
wire txt_empty; // Indica (H) TX vacio (PP y PS)
reg tx_on; // Indica (H) transmision activa
reg [3:0] cont_tx; // Contador de bits transmitidos
//.............................................................
always @(posedge CLK or posedge reset)
begin
if (reset)
begin
tx_empty <= 1;
tx_on <= 0;
cont_tx <= 0;
end
else begin
casex ({carga, load_shift})
2'b00: tx_empty <= tx_empty;
2'b01: tx_empty <= 1;
2'b1x: tx_empty <= 0;
endcase
if (enable)
if(tx_on) begin
cont_tx <= cont_tx + 1;
if (cont_tx==10) begin
cont_tx <= 0;
tx_on <= 0;
end
else
tx_on <= 1;
end
else if(load_shift)
tx_on <= 1;
end
end
assign load_shift = (cont_tx == 0) & enable & !tx_empty & !tx_on;
assign txt_empty = tx_empty & !tx_on;
endmodule
//............................................................
// ERROR AND READY CONTROL
//
//............................................................
module pc_dato_rdy (reset, CLK, rx_lleno, borrar_rdy, borrar_err,
dato_rdy, err_overrun);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input rx_lleno; // Indica dato completo en el receptor
input borrar_rdy; // Indica lectura de DATO_RX
input borrar_err; // Indica lectura de STATUS_RX
output dato_rdy; // Indica (H) final de la recepcion de un caracter
output err_overrun; // Error de rebosamiento
// Variables
//.............................................................
reg dato_rdy;// Indica (H) final de la recepcion de un caracter
reg err_overrun; // Error de rebosamiento
//.............................................................
always @(posedge CLK or posedge reset)
begin
if (reset)
begin
dato_rdy <= 0;
err_overrun <= 0;
end
else begin
if (rx_lleno)
dato_rdy <= 1;
else if (borrar_rdy)
dato_rdy <= 0;
if (rx_lleno & dato_rdy)
err_overrun <= 1;
else if(borrar_err)
err_overrun <= 0;
end
end
endmodule
//............................................................
// DIVIDER BY 27
//............................................................
module pc_div27 (reset, CLK, clk_in, clk_out);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input clk_in; // Frecuencia de entrada
output clk_out; // Frecuencia de salida
// Variables
//.............................................................
reg [5:0] div27; // Registro para dividir la frecuencia de
// muestreo y obtener la de transmision
always @(posedge CLK or posedge reset)
begin
if (reset)
div27 <= 0;
else if (clk_in)
if (div27==26)
div27 <= 0;
else
div27 <= div27 + 1;
end
assign clk_out = (div27==26)?1:0;
endmodule
//............................................................
// DIVIDER BY 16
//............................................................
module pc_div16 (reset, CLK, clk_in, clk_out);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input clk_in; // Frecuencia de entrada
output clk_out; // Frecuencia de salida
// Variables
//.............................................................
reg [3:0] div16; // Registro para dividir la frecuencia de
// muestreo y obtener la de transmision
always @(posedge CLK or posedge reset)
begin
if (reset)
div16 <= 0;
else if (clk_in)
if (div16==15)
div16 <= 0;
else
div16 <= div16 + 1;
end
assign clk_out = (div16==15)?1:0;
endmodule
//............................................................
// PROGRAMMABLE DIVIDER
//............................................................
module pc_div_ms (reset, CLK, clkin, cte_div, carga_div_low, carga_div_high, clk_out);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input clkin; // Reloj escalado
input [7:0] cte_div;// Frecuencia de entrada
input carga_div_low; // Senal carga de la cte_div
input carga_div_high; // Senal carga de la cte_div
output clk_out;// Frecuencia de salida
// Variables
//.............................................................
reg [15:0] div; // Contador del divisor
reg [15:0] k_div; // Factor de division
reg clk_out;// Frecuencia de salida
always @(posedge CLK or posedge reset)
begin
if (reset)
begin
div <= 0;
k_div <= 1;
end
else begin
if (carga_div_low)
k_div[7:0] <= cte_div;
if (carga_div_high)
k_div[15:8] <= cte_div;
if (carga_div_low | carga_div_high) div<=0;
if (div==k_div) begin
div <= 0;
clk_out <= 1;
end
else begin
if (clkin)
begin
div <= div + 1;
clk_out <= 0;
end
end
end
end
endmodule
module pc_ier (reset, CLK, carga_IER, data_in, dato_rdy, tx_empty, modem_int, nIRQ, IER);
input reset;
input CLK;
input carga_IER;
input [7:0] data_in;
input dato_rdy;
input tx_empty;
input modem_int;
output nIRQ; // Data Terminal Ready
output [3:0] IER;
reg [3:0] IER;
assign nIRQ= ~|(IER & {modem_int, dato_rdy, tx_empty, dato_rdy});
always @(posedge CLK)
begin
if (reset)
begin
IER<=4'b0;
end
else
if (carga_IER)
begin
IER<=data_in[3:0];
end
end
endmodule
//............................................................
// ARM INTERFACE
//............................................................
// ADD nRW FUNCTION
// 000 0 Rx Register.
// 000 1 TX Register. If enabled, LSB Divisor Latch.
//
// 001 0 NA
// 001 1 Interrupt Enable Register. If enabled, MSB Divisor Latch.
//
// 010 0 Interrupt Status Register.
// 010 1 FIFO Control Register (Not Implemented).
//
// 011 0 NA
// 011 1 Line Control Register
//
// 100 0 NA
// 100 1 Modem Control Register
//
//
// 101 0 Line Status Register
// 101 1 NA
//
// 110 0 Modem Status Register
// 110 1 NA
//
// 111 01 Scratch Pad Register
//
module pc_if_arm_pc (reset, CLK, data_in, data_out, add, nRW, CS,
borrar_rdy, borrar_err, carga, carga_div_low, carga_div_high,
carga_IER, carga_MCR, carga_LCR, carga_MSR, carga_ISR,
BaudSelect, dato_rx, modem, ISR, LSR, LCR);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input [7:0] data_in; // Bus de datos de entrada
output [7:0] data_out; // Bus de datos de salida
input [2:0] add; // Bus de direcciones
input nRW; // senal de lectura del ARM
input CS; // senal de seleccion de la UART
input [7:0] dato_rx; // Dato recibido
output borrar_rdy; // Borrar dato_rdy tras leer DATO_RX
output borrar_err; // Borrar err_over tras leer STATUS_RX
output carga; // Senal carga
output carga_div_low; // Senal carga de la cte_div (byte bajo)
output carga_div_high; // Senal carga de la cte_div (byte alto)
output carga_IER; // senal carga IER
output carga_MCR; // senal carga MCR
output carga_LCR; // senal carga LCR
output carga_MSR; // senal carga MSR (para codificacion delta)
output carga_ISR; // senal carga de ISR
input BaudSelect; // seleccion de modo de acceso
input [7:0] modem; // modem bus
input [3:0] ISR; // Interrupt Status Register
input [7:0] LSR; // Line Status Register
input [7:0] LCR; // Line Control Register
// Variables
//.............................................................
reg [7:0] data_out; // Bus de datos de salida
reg carga; // Senal carga
reg carga_div_low; // Senal carga de la cte_div (byte bajo)
reg carga_div_high; // Senal carga de la cte_div (byte alto)
reg carga_IER; // senal carga IER
reg carga_MCR; // senal carga MCR
reg carga_LCR; // senal carga LCR
reg carga_MSR; // senal lectura del MSR (para puesta a 0)
reg carga_ISR; // senal recarga del ISR
reg borrar_rdy; // Borrar dato_rdy tras leer DATO_RX
reg borrar_err; // Borrar err_over tras leer STATUS_RX
reg [7:0] dato_tx; // Dato para transmitir
//.............................................................
always @(nRW or CS or add or dato_rx or LSR or ISR or LCR or modem or BaudSelect)
if (CS)
begin
casex ({nRW, add})
6'b0000: begin //Lectura de DATO_RX
data_out <= dato_rx;
borrar_rdy <= 1;
borrar_err <= 0;
carga <= 0;
carga_div_low <= 0;
carga_div_high <= 0;
carga_IER <= 0;
carga_MCR <= 0;
carga_LCR <= 0;
carga_MSR <= 0;
carga_ISR <= 0;
end
6'b1000: begin //Escritura Baud_Rate
if (BaudSelect)
begin
carga_div_low <= 1;
carga <= 0;
end
else //Escritura de DATO_TX
begin
carga_div_low <= 0;
carga <= 1;
end
carga_div_high <= 0;
carga_IER <= 0;
carga_MCR <= 0;
carga_LCR <= 0;
carga_MSR <= 0;
carga_ISR <= 0;
data_out <= dato_rx;
borrar_rdy <= 0;
borrar_err <= 0;
end
6'b1001: begin //Escritura Baud_Rate
if (BaudSelect)
begin
carga_div_high <= 1;
carga_IER <= 0;
end
else //Escritura de IER
begin
carga_div_high <= 0;
carga_IER <= 1;
end
carga <= 0;
carga_div_low <= 0;
carga_MCR <= 0;
carga_LCR <= 0;
carga_MSR <= 0;
carga_ISR <= 0;
data_out <= dato_rx;
borrar_rdy <= 0;
borrar_err <= 0;
end
6'b0010: begin //Lectura ISR
carga <= 0;
carga_div_low <= 0;
carga_div_high <= 0;
data_out <= ISR;
carga_IER <= 0;
carga_MCR <= 0;
carga_LCR <= 0;
carga_MSR <= 0;
carga_ISR <= 1;
borrar_rdy <= 0;
borrar_err <= 0;
end
6'b1010: begin //Escritura FCR (no implementado)
carga <= 0;
carga_div_low <= 0;
carga_div_high <= 0;
carga_IER <= 0;
carga_MCR <= 0;
carga_LCR <= 0;
carga_MSR <= 0;
carga_ISR <= 0;
data_out <= dato_rx;
borrar_rdy <= 0;
borrar_err <= 0;
end
6'b0011: begin //Lectura LCR
carga <= 0;
carga_div_low <= 0;
carga_div_high <= 0;
carga_IER <= 0;
carga_MCR <= 0;
carga_LCR <= 0;
carga_MSR <= 0;
carga_ISR <= 0;
data_out <= LCR;
borrar_rdy <= 0;
borrar_err <= 0;
end
6'b1011: begin //Escritura LCR
carga <= 0;
carga_div_low <= 0;
carga_div_high <= 0;
carga_IER <= 0;
carga_MCR <= 0;
carga_LCR <= 1;
carga_MSR <= 0;
carga_ISR <= 0;
data_out <= dato_rx;
borrar_rdy <= 0;
borrar_err <= 0;
end
6'b1100: begin //Escritura de MCR
carga <= 0;
carga_div_low <= 0;
carga_div_high <= 0;
carga_IER <= 0;
carga_MCR <= 1;
carga_LCR <= 0;
carga_MSR <= 0;
carga_ISR <= 0;
data_out <= dato_rx;
borrar_rdy <= 0;
borrar_err <= 0;
end
6'b0101: begin //Lectura del LSR
carga<=0;
carga_div_low<=0;
carga_div_high<=0;
carga_IER<=0;
carga_MCR<=0;
carga_LCR<=0;
carga_MSR<=0;
carga_ISR<=0;
data_out <= LSR;
borrar_rdy <= 0;
borrar_err <= 0;
end
6'b0110: begin //Lectura del MSR
carga<=0;
carga_div_low<=0;
carga_div_high<=0;
carga_IER<=0;
carga_MCR<=0;
carga_LCR<=0;
carga_MSR<=1;
carga_ISR<=0;
data_out <= modem;
borrar_rdy <= 0;
borrar_err <= 0;
end
/*
6'b0111: begin
carga<=0;
carga_div_low<=0;
carga_div_high<=0;
carga_IER<=0;
carga_MCR<=0;
carga_LCR<=0;
carga_ISR<=0;
data_out <= dato_rx;
borrar_rdy <= 0;
borrar_err <= 0;
end
6'b1111: begin
carga<=0;
carga_div_low<=0;
carga_div_high<=0;
carga_IER<=0;
carga_MCR<=0;
carga_LCR<=0;
carga_ISR<=0;
data_out <= dato_rx;
borrar_rdy <= 0;
borrar_err <= 0;
end
*/
default:
begin
carga<=0;
carga_div_low<=0;
carga_div_high<=0;
carga_IER<=0;
carga_MCR<=0;
carga_LCR<=0;
carga_MSR<=0;
carga_ISR<=0;
data_out <= dato_rx;
borrar_rdy <= 0;
borrar_err <= 0;
end
endcase
end
else
begin
carga<=0;
carga_div_low<=0;
carga_div_high<=0;
carga_IER<=0;
carga_MCR<=0;
carga_LCR<=0;
carga_MSR<=0;
carga_ISR<=0;
data_out <= dato_rx;
borrar_rdy <= 0;
borrar_err <= 0;
end
endmodule
//............................................................
// RxD INTERFACE
//............................................................
module pc_ifrxd (reset, CLK, clkms, RxD, RxDs);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input clkms; // Reloj de muestreo sincronizado (el nivel
// alto dura un periodo de reloj)
input RxD; // Linea de recepcion de datos
output RxDs; // RxD sincronizada y limpia
// Variables
//.............................................................
reg [2:0] ifrxd; // Registro interfaz de la linea RxD
//.............................................................
always @(posedge CLK or posedge reset)
begin
if (reset)
ifrxd <= 3'b111;
else if (clkms)
begin
if ((ifrxd[0]==ifrxd[2]) & (ifrxd[0]!=ifrxd[1]))
ifrxd[2] <= ifrxd[0];
else
ifrxd[2] <= ifrxd[1];
ifrxd[1] <= ifrxd[0];
ifrxd[0] <= RxD;
end
end
assign RxDs = ifrxd[2];
endmodule
module pc_isr (reset, CLK,
carga_ISR,
err_paridad, err_frame, err_overrun,
dato_rdy, tx_empty, txt_empty, modem_int,
ISR, LSR, IER);
input reset;
input CLK;
input carga_ISR;
input err_paridad;
input err_frame;
input err_overrun;
input dato_rdy;
input tx_empty;
input txt_empty;
input modem_int;
output [3:0] ISR; // Interrupt Status Register
output [7:0] LSR; // Line Status Register
input [3:0] IER; // Interrupt Enable Register
reg [3:0] ISR;
reg [3:0] ISRt;
reg mask_error;
reg mask_dato_rdy;
reg mask_err_overrun;
reg mask_tx_empty;
reg mask_modem_int;
reg carga_ISRd;
reg aux1;
wire error, errorm, dato_rdym, err_overrunm, tx_emptym, modem_intm;
assign errorm= error & mask_error & IER[1];
assign dato_rdym= dato_rdy & mask_dato_rdy & IER[0];
assign err_overrunm= err_overrun & mask_err_overrun;
assign tx_emptym= tx_empty & mask_tx_empty & IER[1];
assign modem_intm= modem_int & mask_modem_int & IER[3];
always @(errorm or dato_rdym or tx_emptym or err_overrunm or modem_intm)
begin
if (errorm) ISRt=4'b0110;
else if (dato_rdym) ISRt=4'b0100;
//else if (err_overrunm) ISRt=4'b1100;
else if (tx_emptym) ISRt=4'b0010;
else if (modem_intm) ISRt=4'b0000;
else ISRt=4'b0001;
end
assign error = err_paridad | err_frame | err_overrun;
assign LSR = {error, txt_empty, tx_empty, 1'b0, err_frame, err_paridad, err_overrun, dato_rdy};
always @(posedge CLK)
begin
if (reset)
begin
ISR<=4'b0001;
mask_error<=1;
mask_dato_rdy<=1;
mask_err_overrun<=1;
mask_tx_empty<=1;
mask_modem_int<=1;
carga_ISRd<=0;
aux1<=1'b0;
end
else
begin
if (mask_error)
begin
if ((ISR==4'b0110) & carga_ISRd) mask_error<=0;
end
else
if (error) mask_error<=1;
if (mask_dato_rdy)
begin
if ((ISR==4'b0100) & carga_ISRd) mask_dato_rdy<=0;
end
else
if (dato_rdy) mask_dato_rdy<=1;
if (mask_err_overrun)
begin
if ((ISR==4'b1100) & carga_ISRd) mask_err_overrun<=0;
end
else
if (err_overrun) mask_err_overrun<=1;
if (mask_tx_empty)
begin
if ((ISR==4'b0010) & carga_ISRd) mask_tx_empty<=0;
end
else
if (tx_empty) mask_tx_empty<=1;
if (mask_modem_int)
begin
if ((ISR==4'b0000) & carga_ISRd) mask_modem_int<=0;
end
else
if (modem_int) mask_modem_int<=1;
ISR<=ISRt;
aux1<=carga_ISR; //Espera a que se deseleccione el carga_ISR para modificar mascaras.
if (~carga_ISR)
begin
carga_ISRd<=aux1;
aux1<=1'b0;
end
end
end
endmodule
module pc_lcr (reset, CLK, LCR,
carga_LCR,
data_in,
WordLength, Stop, ParityEnable, Parity,
ParityForced, Break, BaudSelect);
input reset;
input CLK;
output [7:0] LCR;
input carga_LCR;
input [7:0] data_in;
output [1:0] WordLength;
output Stop;
output ParityEnable;
output Parity;
output ParityForced;
output Break;
output BaudSelect;
reg [7:0] LCR;
assign WordLength={LCR[1],LCR[0]};
assign Stop=LCR[2];
assign ParityEnable=LCR[3];
assign Parity=LCR[4];
assign ParityForced=LCR[5];
assign Break=LCR[6];
assign BaudSelect=LCR[7];
always @(posedge CLK)
begin
if (reset)
begin
LCR<=8'b0; //Ver hoja de datos de ST16C552.
//Esta es la situacion en reset.
end
else
if (carga_LCR)
begin
LCR<=data_in;
end
end
endmodule
//module pc_modem(reset, CLK,
// carga_MCR, carga_MSR,
// data_in, modem,
// CD, RI, DSR, CTS, DTR, RTS, modem_int);
//
//input reset;
//input CLK;
//input carga_MCR;
//input carga_MSR;
//input [7:0] data_in;
//output [7:0] modem;
//input CD; // Carrier Detect
//input RI; // Ring Indicator
//input DSR; // Data Send Ready
//input CTS; // Clear To Send
//output RTS; // Request To Send
//output DTR; // Data Terminal Ready
//output modem_int;
//
//reg RTS;
//reg DTR;
//
//reg dCD, sCD;
//reg dRI, sRI;
//reg dDSR, sDSR;
//reg dCTS, sCTS;
//wire [7:0] modem;
//reg modem_int;
//
//
//assign modem ={~sCD, ~sRI, ~sDSR, ~sCTS,
// dCD ^ sCD, dRI ^ sRI, dDSR ^ sDSR, dCTS ^ sCTS};
//
//
//always @(posedge CLK)
//begin
// if (reset)
// begin
// dCD<=1; sCD<=1;
// dRI<=1; sRI<=1;
// dDSR<=1; sDSR<=1;
// dCTS<=1; sCTS<=1;
// DTR<=1;
// RTS<=1;
// modem_int<=0;
// end
// else
// begin
// sCD<=~CD;
// sRI<=~RI;
// sDSR<=~DSR;
// sCTS<=~CTS;
//
// modem_int<=modem_int | (|modem[3:0]);
//
// if (carga_MCR)
// begin
// RTS<=~data_in[0];
// DTR<=~data_in[1];
// end
//
// else
// if (carga_MSR)
// begin
// dCD<=~CD;
// dRI<=~RI;
// dDSR<=~DSR;
// dCTS<=~CTS;
// modem_int<=0; //Limpieza de la interrupcion
// end
//
//
// end
//
//end
//
//
//
//
//endmodule
//
//............................................................
// RxDs SAMPLER
//............................................................
module pc_muestreo (reset, CLK, rst_muestreo, clkms, RxDs, sample);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input rst_muestreo; // Reset (H) del circuito de muestreo
input clkms; // Reloj de muestreo sincronizado (el nivel
// alto dura un periodo de reloj)
input RxDs; // Senal RxD sincronizada y limpia
output sample; // Impulso de muestreo de la senal RxDs
// Variables
//.............................................................
reg [3:0] cont_m; // Contador del circuito de muestreo
reg flag_rx;// Indicador de recepcion en curso
reg sample; // Impulso de muestreo de la senal RxDs
//.............................................................
always @(posedge CLK or posedge reset)
begin
if (reset)
begin
cont_m <= 4'b0000;
sample <= 0;
flag_rx <= 0;
end
else if (rst_muestreo)
begin
cont_m <= 4'b0000;
sample <= 0;
flag_rx <= 0;
end
else if (clkms)
if ( (flag_rx==0) & (RxDs==0) ) // Arranque
flag_rx <= 1; // Recepcion en curso
else if (flag_rx)
begin
cont_m <= cont_m + 1;
if (cont_m==4'b0110)
sample <= 1;
else
sample <= 0;
end
end
endmodule
//............................................................
// TIMING CONTROL
//............................................................
module pc_pulso (reset, CLK, dato_asyn, dato_syn);
input reset; // Reset (H)
input CLK; // Reloj del sistema
input dato_asyn; // Entrada de dato asincrona
output dato_syn; // Salida de dato conformada
// Variables
//.............................................................
reg dff; // Registro del sincronizador
always @(posedge CLK or posedge reset)
begin
if (reset)
dff <= 0;
else
dff <= dato_asyn;
end
assign dato_syn = !dff & dato_asyn;
endmodule