📄 m3s004an.v
字号:
// Interrupt Enable and Priority Encoder// Copyright Mentor Graphics Corporation and Licensors 1999// V1.500// This module provides the interrupt enable register and priority encoding// for the M16550a UART.// Revision history:// V1.500 - 29 September 1999// Remove signal THold1 from this module as superflous (ECN 1267)// V1.400 - 9 September 1999// THREmA updated to avoid spurious interrupt when IER written// V1.300 - 15 June 1999// Removed unused inputs DA4, DA5 (ECN 1242)// V1.200 - 12 May 1999// FIFO threshold levels decoded in FIFO controller// V1.100 - 23 September 1997// Modified to make the functionality of txrdy match the real part more closely// V1.000 - 26/9/96// Originalmodule m3s004an ( CLK, MR, NWR, NRD, RD, ADD0, ADD1, ADD2, DI, DR, BI, FE, PE, OE, RTO, DDCD, TERI, DDSR, DCTS, THRE, DA1, DA2, LoadTxBuff, FIFOE, IFIFOE, DMA, IDMA, TFull, RHold1, RxAboveTrig, TSRE, TEmpt, Delta_TRST, RRST, IRQ, IIR, IER, TXRdy, RXRdy );input CLK, MR, NWR, NRD, RD, ADD0, ADD1, ADD2;input [3:0] DI;input DR, BI, FE, PE, OE, RTO; input DDCD, TERI, DDSR, DCTS, THRE;input DA1, DA2, LoadTxBuff, FIFOE, IFIFOE;input DMA, IDMA, TFull, RHold1;input RxAboveTrig;input TSRE, TEmpt, Delta_TRST, RRST;output [3:0] IIR, IER;output IRQ, TXRdy, RXRdy;reg [3:0] IIR, IER;reg IRQ, EnabRxBuff, EnabTxBuff, EnabLnStat, EnabMdStat;reg THREmA, THREmB, THREmC, THREmD, THREmE, THREmF;reg DREmptyA, DREmptyB;reg TXRdy, RXRdy;reg RHold, THold;reg DMA0_SEL, DMA0_TXRdy;reg FIFOE_DEL, Delta_FIFOE;reg DMA0_TXRdySamp;reg Delta_DMA0_TXRdy;reg RTOSync, TriggerSync;reg THREm1, THREm2, THREmI;reg Trigger, DREmpty;reg Prior1, Prior2, Prior2TO, Prior3, Prior4;reg RTO_Pulse, Trigger_Pulse;// Interrupt enable register// CPU timing domainalways @(posedge NWR or posedge MR) if (MR) IER <= 0; else begin if (ADD1) IER <= DI; end// Resynchronise with TX & RX timing domainalways @(posedge MR or posedge CLK) if (MR) begin EnabRxBuff <= 0; EnabTxBuff <= 0; EnabLnStat <= 0; EnabMdStat <= 0; end else begin EnabRxBuff <= IER[0]; EnabTxBuff <= IER[1]; EnabLnStat <= IER[2]; EnabMdStat <= IER[3]; end// Signal HOLD indicates TX fifo will be emptied on next read// or RBR will be emptied on next read// Used for THRE INTRalways @(FIFOE) if (FIFOE) THold = 1'b0; else THold = 1'b1;// Signal HOLD indicates RX fifo will be emptied on next read// or RBR will be emptied on next read// Used by RXRdy pinalways @(FIFOE or RHold1) if (FIFOE) RHold = RHold1; else RHold = 1'b0;// Generate a delta version of FIFOE, since this will generate a TX interrupt// because FIFOE changing resets FIFO and makes it go emptyalways @(posedge CLK) FIFOE_DEL <= FIFOE;always @ (FIFOE_DEL or FIFOE) Delta_FIFOE <= FIFOE ^ FIFOE_DEL;// Explanation for Interrupt Scheme//// This section generates the Transmit Holding Register Empty (THRE) Interrupt.// The interrupt is made up from the FIFO THRE Interrupt (TFEI) and the 450 Mode THRE Interrupt (THREmI)//// Generating (TFEI)://// A Transmit FIFO Empty Interrupt is generated by any one of the following occuring:// 1) The Transmitter FIFO emptys itself (Rising edge on DMA0_TXRdy) // and the FIFO is enabled (FIFOE = '1')// 2) The FIFO is enabled, if it had been disabled before (Rising edge on FIFOE), // 3) The THRE interrupt is enabled, even if it was already enabled,// the FIFO is enabled (FIFOE = '1') and the Transmitter FIFO is empty (DMA0_TXRdy = '1')// 4) The Transmit FIFO is reset.//// The interrupt is cleared by any of the following occuring:// 1) The Transmit Holding Register is written to.// 2) The Interrupt Ident Register is Read. //// The interrupt is gated on and off with:// 1) The THRE Interrupt bit in the Interrrupt Enable Register (EnabTxBuff ='1/0')////// Generating (THREmI)://// A Transmit Holding Register Empty Interrupt is generated by any one of the following occuring:// 1) The THRE interrupt is enabled, even if it was already enabled,// the FIFO is disabled and the THR is empty (THRE = '1')// 2) The last character in the THR starts to be transmitted (rising edge of LoadTxBuff) and// the FIFO is disabled.// 3) The FIFO is disabled if it had been enabled before.//// The interrupt is cleared by any of the following occuring:// 1) The Transmit Holding Register is written to.// 2) The Interrupt Ident Regsiter is Read. //// The interrupt is gated on and off with:// 1) the THRE Interrupt bit in the Interrrupt Enable Register (EnabTxBuff ='1/0')// Transmit Holding Register Empty Interrupt generation// NB There are at least 3 timing domains here - take care!//// Start with Holding register empty which is cleared by a write to // the TX register, or a read from the IID register. It is set by a // write to IER if THRE = 1// No synchronisation, since NWR and NRD do not occur togetheralways @(posedge NWR or posedge MR) if (MR) THREmA <= 0; else if (ADD0 & THREm1) THREmA <= THREmB; // Reset loop if THREm1 is active else if (ADD1 & DI[1] & THRE) THREmA <= ~THREmB; // Set loop if a write to IER and THRE activealways @(posedge NRD or posedge MR) if (MR) THREmB <= 0; else if (ADD2 & ~DA2 & DA1) THREmB <= THREmA; // Clear down THRE if a read from IIRalways @(THREmA or THREmB) THREm1 = THREmA ^ THREmB;// Next source of THRE is if TX holding register becomes empty. This is// cleared by a write to register 0 or a read from the IIR// Synchronisation required since mixture of CPU and TX clock time domainsalways @(posedge CLK or posedge MR) if (MR) THREmC <= 0; else if ((LoadTxBuff & THold & ~FIFOE) | (Delta_FIFOE) | (Delta_TRST) | (Delta_DMA0_TXRdy & FIFOE)) THREmC <= ~THREmD; else if (~THREm2) THREmC <= THREmD;always @(negedge NWR or posedge MR) if (MR) THREmD <= 0; else if (ADD0) THREmD <= THREmC;always @(posedge CLK or posedge MR) if (MR) THREmE <= 0; else if ((LoadTxBuff & THold & ~FIFOE) | (Delta_FIFOE) | (Delta_TRST) | (Delta_DMA0_TXRdy & FIFOE)) THREmE <= ~THREmF; else if (~THREm2) THREmE <= THREmF;always @(posedge NRD or posedge MR) if (MR) THREmF <= 0; else if (ADD2 & ~DA2 & DA1) THREmF <= THREmE;always @(THREmC or THREmD or THREmE or THREmF) THREm2 = ((THREmC ^ THREmD) & (THREmE ^ THREmF));always @(THREm1 or THREm2) THREmI = THREm1 | THREm2;// Trigger level interrupt generationalways @(FIFOE or RxAboveTrig) Trigger = FIFOE & RxAboveTrig;// Interrupt Priority Generationalways @(EnabLnStat or BI or FE or PE or OE or EnabRxBuff or DR or FIFOE or Trigger or RTO or EnabTxBuff or THREmI or EnabMdStat or DDCD or TERI or DDSR or DCTS)begin Prior1 = EnabLnStat & (BI | FE | PE | OE); // RX Error 1st Priority Prior2 = EnabRxBuff & ((DR & ~FIFOE) | Trigger); // Data RX 2nd Priority Prior2TO = EnabRxBuff & RTO; // Rx FIFO time out 2nd Priority Prior3 = EnabTxBuff & THREmI; // TX Buffer empty 3rd Priority Prior4 = EnabMdStat & (DDCD | TERI | DDSR | DCTS); // Modem status line changes 4th Priorityend// Generate interrupt requestalways @(Prior1 or Prior2 or Prior3 or Prior4 or Prior2TO) IRQ = Prior1 | Prior2 | Prior3 | Prior4 | Prior2TO;// Generate interrupt status bitsalways @(Prior1 or Prior2 or Prior3 or Prior2TO or Prior4)begin if (Prior1) IIR = 4'h6; else if (Prior2TO) IIR = 4'hC; else if (Prior2) IIR = 4'h4; else if (Prior3) IIR = 4'h2; else if (Prior4) IIR = 4'h0; else IIR = 4'h1;end// DMA access pin TXRdy//// DMA Mode 0 - Device behaviour is as follows://// Demand transfer - if THR or FIFO written to once// TXRdy goes inactive (Logic 1), and becomes active// when the TX SR is empty (TSRE active). If written// to more than one location TXRdy becomes active when// the FIFO is empty - i.e. before the TX SR is emptyalways @(posedge NWR or posedge MR) if (MR) DMA0_SEL <= 1'b0; else if (ADD0) DMA0_SEL <= TEmpt; else if (ADD2 & ((DI[0] ^ IFIFOE) | DI[2])) DMA0_SEL <= 1'b0; always @(TEmpt or DMA0_SEL or TSRE or FIFOE or THRE) if (FIFOE) begin if (DMA0_SEL) DMA0_TXRdy = TSRE; else DMA0_TXRdy = TEmpt; end else DMA0_TXRdy = THRE;// Generate Delta version of DMA0_TXRdyalways @(posedge CLK or posedge MR) if (MR) DMA0_TXRdySamp <= 1'b0; else DMA0_TXRdySamp <= DMA0_TXRdy; always @(DMA0_TXRdy or DMA0_TXRdySamp) Delta_DMA0_TXRdy = (DMA0_TXRdy & ~DMA0_TXRdySamp);// If DMA Mode 1 (only possible in 16550A mode) -// Burst mode transfers - Therefore TXRdy goes // inactive when the FIFO is full, and becomes// active when the FIFO is empty.always @(FIFOE or DMA or TFull or DMA0_TXRdy) if (FIFOE & DMA) TXRdy = TFull; else TXRdy = ~DMA0_TXRdy;// DMA access pin RXRdy// As in DMA mode different signals control the// status of the pin two flip flops are required// to control it.always @(FIFOE or DMA or DREmpty or DR) if (FIFOE & DMA) RXRdy = DREmpty; else RXRdy = ~DR;// Create a pulse when positive edge on RTOalways @(posedge CLK or posedge MR) if (MR) RTOSync <= 1'b0; else RTOSync <= RTO;always @(RTO or RTOSync) RTO_Pulse = RTO & ~RTOSync;// Create a pulse when positive edge on Triggeralways @(posedge CLK or posedge MR) if (MR) TriggerSync <= 1'b0; else TriggerSync <= Trigger;always @(Trigger or TriggerSync) Trigger_Pulse = Trigger & ~TriggerSync;always @(posedge CLK or posedge MR) if (MR) DREmptyA <= 1'b0; else if (~DMA | RRST) DREmptyA <= DREmptyB; else if (Trigger_Pulse | RTO_Pulse) DREmptyA <= ~DREmptyB;always @(posedge RD or posedge MR) if (MR) DREmptyB <= 1'b0; else if (~IDMA) DREmptyB <= 1'b0; else if (ADD0 & RHold) DREmptyB <= DREmptyA;// RXRdy DMA mode flagalways @(DREmptyA or DREmptyB) DREmpty = ~(DREmptyA ^ DREmptyB);endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -