📄 m3s002an.v
字号:
// Receive Engine// Copyright Mentor Graphics Corporation and Licensors 2001// V1.400// This module provides the receive mechanism// for the M16550a UART.// Revision history:// V1.400 - 5 Mar 2001// FIFOE used to avoid a spurious line status interrup (OE)// when the Recieve FIFO is disabled (ECN01450).// V1.300 - 30 Jan 2001 // Removed RxClkEnab from Timeout Counter (ECN01437).// V1.200 - 15 June 1999// Remove unused signals BREAK, CR (ECN 1242)// Changed constants from 2'b0 to 2'b00 to clear lint warning (ECN 1242)// V1.100 - 12 May 1999// Uses single input clock// V1.000 - 26/9/96// Original// Receive state machine// 14 states are required:`define C_RX_IDLE 4'h0`define C_RX_START 4'h1`define C_RX_DATA1 4'h2`define C_RX_DATA2 4'h3`define C_RX_DATA3 4'h4`define C_RX_DATA4 4'h5`define C_RX_DATA5 4'h6`define C_RX_DATA6 4'h7`define C_RX_DATA7 4'h8`define C_RX_DATA8 4'h9`define C_RX_PARITY 4'ha`define C_RX_STOP1 4'hb`define C_RX_CHARX 4'hc`define C_RX_END_BRK 4'hd// Seven bits`define C_RTO 4'b0111module m3s002an ( CLK, MR, RxClkEnab, NRD, PRD, ADD0, ADD5, DA4, DA3, DA2, DA1, PEN, WLS0, WLS1, STB, EPS, SP, SIN, LOOP1, BRKTD, RFD, FOE, FPE, FFE, FBI, FERF, FIFOE, REmpt, RRST, RD, RX, CharEn, DR, FE, OE, PE, BI, ERF, RTO, FRE, PTE, FBRK, RxBlank );input CLK, MR, RxClkEnab, NRD, PRD, ADD0, ADD5;input DA4, DA3, DA2, DA1;input PEN, WLS0, WLS1, STB, EPS, SP;input SIN, LOOP1, BRKTD;input [7:0] RFD;input FOE, FPE, FFE, FBI, FERF;input FIFOE, REmpt, RRST;output [7:0] RD, RX;output CharEn;output DR, FE, OE, PE, BI;output ERF; // At least one error in fifooutput RTO; // Rx character timeoutoutput FRE, PTE, FBRK, RxBlank;reg [7:0] RX, RXD, RD;reg [3:0] StepC, RxState;reg [2:0] RXS;reg [1:0] OESR, PESR, BRKSR, FESR, DRSR, RDSR;reg [5:0] TOC;reg DIN, PTY, FRE, DRD;reg DP, DOE, DBI, DFE, DPE;reg DR, FE, OE, PE, BI, ERF;reg SDIN, RDS, RTO;reg IDLE, RxBlank;reg Step, SRD;reg BRK, FBRK, PTE, CharEn;reg IDR, IFE, IOE, IPE, IBI;reg NoBit6, NoBit7, NoBit8;reg IpFilter;// Input data is either SIN or TX data looped backalways @(LOOP1 or SIN or BRKTD) SDIN = (~LOOP1 & SIN) | (LOOP1 & ~BRKTD);// Input data filter, filters incoming data using a majority// 2 of 3 logic circuit - also resyncs data to RX Clockalways @(posedge CLK or posedge MR) if (MR) RXS[2:0] <= 3'b111; else if (RxClkEnab) begin RXS[0] <= SDIN; RXS[1] <= RXS[0]; RXS[2] <= RXS[1]; endalways @(RXS) IpFilter = (RXS[0] & RXS[1]) | (RXS[0] & RXS[2]) | (RXS[1] & RXS[2]);// Input data selected from input filteralways @(posedge CLK or posedge MR) if (MR) DIN <= 1; else if (RxClkEnab) DIN <= IpFilter;// Receive Step timer - divides the baud rate by 16 to generate// the 'Step' or move onto next bit enable signalalways @(posedge CLK or posedge MR) if (MR) StepC <= 0; else begin if ((RxState == `C_RX_IDLE) & RxClkEnab & ~DIN) StepC <=0; else if (RxClkEnab) StepC <= StepC + 1; end// Step - Count of 7always @(RxClkEnab or StepC) Step = ((StepC == 4'h7) & RxClkEnab);// Decode number of bits required for the characteralways @(WLS0 or WLS1)begin NoBit6 = ~WLS1 & ~WLS0; NoBit7 = ~WLS1; NoBit8 = ~WLS1 | ~WLS0;end// Receive state machine// This controls the whole Receive operationalways @(posedge CLK or posedge MR)begin if (MR) RxState <= `C_RX_IDLE; else if (RxClkEnab) begin case (RxState) `C_RX_IDLE: if (~DIN) RxState <= `C_RX_START; // Detect start bit `C_RX_START: if (Step & ~DIN) RxState <= `C_RX_DATA1; else if (Step) RxState <= `C_RX_IDLE; // If false start stop RX `C_RX_DATA1: if (Step) RxState <= `C_RX_DATA2; `C_RX_DATA2: if (Step) RxState <= `C_RX_DATA3; `C_RX_DATA3: if (Step) RxState <= `C_RX_DATA4; `C_RX_DATA4: if (Step) RxState <= `C_RX_DATA5; `C_RX_DATA5: if (Step) RxState <= `C_RX_DATA6; `C_RX_DATA6: if (NoBit6 | Step) RxState <= `C_RX_DATA7; `C_RX_DATA7: if (NoBit7 | Step) RxState <= `C_RX_DATA8; `C_RX_DATA8: if (NoBit8 | Step) RxState <= `C_RX_PARITY; `C_RX_PARITY: if (~PEN | Step) RxState <= `C_RX_STOP1; `C_RX_STOP1: if (Step) RxState <= `C_RX_CHARX; `C_RX_CHARX: RxState <= `C_RX_END_BRK; `C_RX_END_BRK: if (DIN) RxState <= `C_RX_IDLE; else if (~DIN & BRK) RxState <= `C_RX_START; default: RxState <= `C_RX_IDLE; endcase endend// IDLE is true is BREAK or IDLE condition is metalways @(posedge CLK or posedge MR) if (MR) IDLE <= 1'b0; else if (~FIFOE) IDLE <= 1'b0; else IDLE <= (((RxState == `C_RX_END_BRK) & RxClkEnab) | (IDLE & DIN));// CPU channel read pulse synchronisationalways @(posedge PRD or posedge MR) if (MR) RDS <= 1'b0; else if (ADD0) RDS <= ~RDSR[1];always @(posedge CLK or posedge MR) if (MR) RDSR[1:0] <= 2'b00; else if (RxClkEnab) begin RDSR[0] <= RDS; RDSR[1] <= RDSR[0]; end// Synchronised RBR read signalalways @(RDS or RDSR) SRD = RDS ^ RDSR[1];// Timeout counter//// NOTE. IDLE becomes active at end of received CHARACTER, and inactive// at start of next CHARalways @(posedge CLK or posedge MR) if (MR) TOC <= 0; else if ((~IDLE & ~RTO) | SRD | RRST) // Other reset conditions TOC <= 0; else if (IDLE & ~REmpt & Step & ~RTO) // Waiting and something in fifo TOC <= TOC + 1;// Timeout error flag// indicates 4 character periods have passed//// Default value of 7 = Start bit, 5-data bits and 1 Stop bitalways @(TOC or WLS0 or WLS1 or PEN or STB) RTO = (TOC[5:0] == {(`C_RTO + ({WLS1,WLS0}) + PEN + STB),2'b00});// Receive buffer data multiplexingalways @(posedge CLK)begin case (RxState) `C_RX_IDLE: begin RX[7:0] <= 8'b00000000; PTY <= 1'b0; FRE <= 1'b0; end `C_RX_DATA1: if (Step) RX[0] <= DIN; `C_RX_DATA2: if (Step) RX[1] <= DIN; `C_RX_DATA3: if (Step) RX[2] <= DIN; `C_RX_DATA4: if (Step) RX[3] <= DIN; `C_RX_DATA5: if (Step) RX[4] <= DIN; `C_RX_DATA6: if (Step) RX[5] <= DIN; `C_RX_DATA7: if (Step) RX[6] <= DIN; `C_RX_DATA8: if (Step) RX[7] <= DIN; `C_RX_PARITY: if (Step) PTY <= DIN; `C_RX_STOP1: if (Step) FRE <= ~DIN; // Framing error if DIN not 1 at Framing bit default: begin RX <= RX; PTY <= PTY; FRE <= FRE; end endcaseend// Check parity serially, clearing down after every character RXalways @(posedge CLK or posedge MR) if (MR) DP <= 0; else if (RxState == `C_RX_START) DP <= 0; else if (Step & (RxState != `C_RX_PARITY) & (RxState != `C_RX_STOP1)) DP <= (DIN ^ DP);// Generate parity error, if one has occured:always @(PEN or EPS or PTY or SP or DP) PTE = ~(~PEN | ((EPS ^ PTY) ^ (~(SP | ~DP))));// Monitor for break condition// If RX shift register detectes all 0's for a whole character// period - by being full of 0's then we have a break character// and generate a BI immediately// Break detection reset on return to IDLE statealways @(RX or FRE or PTY) BRK = (RX[7] | RX[6] | RX[5] | RX[4] | RX[3] | RX[2] | RX[1] | RX[0] | ~FRE | PTY);always @(BRK) FBRK = ~BRK;// Generate a signal which says that we are in Character RX state// and BEN is active// Also need to blank LSR Read-back info during CharEn period if not// in FIFO modealways @(RxClkEnab or RxState) CharEn = ((RxState == `C_RX_CHARX) & RxClkEnab);always @(negedge CLK) RxBlank <= (CharEn & ~FIFOE);// RXD Data Holding registeralways @(posedge CLK or posedge MR) if (MR) RXD[7:0] <= 8'b0000000; else if (CharEn) RXD[7:0] <= RX[7:0];// Now for the error and status bits// Start with the Data Ready bit - DRalways @(posedge PRD or posedge MR) if (MR) DRD <= 1'b0; else if (ADD0) DRD <= DRSR[1];always @(posedge CLK or posedge MR) if (MR) DRSR[1:0] <= 2'b00; else if (CharEn) begin DRSR[0] <= ~DRD; DRSR[1] <= DRSR[0]; end else if (RxClkEnab) begin DRSR[1] <= DRSR[0]; DRSR[0] <= DRSR[0]; endalways @(DRD or DRSR) IDR = DRD ^ DRSR[1];// Overrun Error Bitalways @(posedge CLK or posedge MR) if (MR) OESR[1:0] <= 2'b00; else if (CharEn) // if we have new data in the RX shift register if (DR & (FIFOE==0)) // if the RX register is full and the FIFO is disabled // at this point we must use the logic FIFOE==0 since this portion of logic // sets the OE bit whenever the FIFO is disabled // there is a separate logic to detect the OE whenever the FIFO is enabled // this logic can be found in module 8 begin // then set the Overun error bit OESR[0] <= ~DOE; // set the overrun error OESR[1] <= OESR[0]; // set the overrun error end else begin OESR[1] <= OESR[0]; OESR[0] <= OESR[0]; end else if (RxClkEnab) begin OESR[1] <= OESR[0]; OESR[0] <= OESR[0]; endalways @(posedge NRD or posedge MR) if (MR) DOE <= 1'b0; else if (DA1 & ADD5) DOE <= OESR[1];always @(DOE or OESR) IOE = DOE ^ OESR[1];// Parity Error Bitalways @(posedge CLK or posedge MR) if (MR) PESR[1:0] <= 2'b00; else if (CharEn) if (PTE) begin PESR[0] <= ~DPE; PESR[1] <= PESR[0]; end else if (PE) begin PESR[1] <= ~PESR[0]; PESR[0] <= ~PESR[0]; end else begin PESR[1] <= PESR[0]; PESR[0] <= PESR[0]; end else if (RxClkEnab) begin PESR[1] <= PESR[0]; PESR[0] <= PESR[0]; endalways @(posedge NRD or posedge MR) if (MR) DPE <= 1'b0; else if (DA2 & ADD5) DPE <= PESR[1];always @(DPE or PESR) IPE = DPE ^ PESR[1];// Break Indication Bitalways @(posedge CLK or posedge MR) if (MR) BRKSR[1:0] <= 2'b00; else if (CharEn & !BRK) begin BRKSR[0] <= ~DBI; BRKSR[1] <= BRKSR[0]; end else if (RxClkEnab) begin BRKSR[1] <= BRKSR[0]; BRKSR[0] <= BRKSR[0]; endalways @(posedge NRD or posedge MR) if (MR) DBI <= 1'b0; else if (DA4 & ADD5) DBI <= BRKSR[1];always @(DBI or BRKSR) IBI = DBI ^ BRKSR[1];// Framing Error Bitalways @(posedge CLK or posedge MR) if (MR) FESR[1:0] <= 2'b00; else if (CharEn) if (FRE) begin FESR[0] <= ~DFE; FESR[1] <= FESR[0]; end else if (FE) begin FESR[1] <= ~FESR[0]; FESR[0] <= ~FESR[0]; end else begin FESR[1] <= FESR[0]; FESR[0] <= FESR[0]; end else if (RxClkEnab) begin FESR[1] <= FESR[0]; FESR[0] <= FESR[0]; endalways @(posedge NRD or posedge MR) if (MR) DFE <= 1'b0; else if (DA3 & ADD5) DFE <= FESR[1];always @(DFE or FESR) IFE = DFE ^ FESR[1];// Data mux to select between RBR and Rx Fifo// Including error flagsalways @(RFD or RXD or REmpt or IDR or FOE or IOE or FPE or IPE or FFE or IFE or FBI or IBI or FERF or FIFOE) if (FIFOE) begin RD[7:0] = RFD[7:0]; DR = ~REmpt; OE = FOE; PE = FPE; FE = FFE; BI = FBI; ERF = FERF; end else begin RD[7:0] = RXD[7:0]; DR = IDR; OE = IOE; PE = IPE; FE = IFE; BI = IBI; ERF = 1'b0; endendmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -