📄 uart_reg.v
字号:
//////////////////////////////////////////////////////////////////////////////////////////////////----------------------------------------------------------------------//// Copyright (c) 2002-2003 CAST, inc.//// Please review the terms of the license agreement before using this// file. If you are not an authorized user, please destroy this source// code file and notify CAST immediately that you inadvertently received// an unauthorized copy.//----------------------------------------------------------------------//// Project : H16550 UART//// File : uart_reg.v//// Dependencies : none //// Model Type : Synthesizable Core//// Description : h16550 uart_reg//// Designer : JU//// QA Engineer : JH//// Creation Date : 02-January-2002//// Last Update : 20-June-2003//// Version : 2.0V//// History : 1.1 - 02/18/02 VHDL Release// 1.2 - 04/16/02 Performance (size) improved// 2.0 - 06/20/03 Use prevrdlsr to control the lsreg10// renamed registers to uart_reg// Add thrint5////----------------------------------------------------------------------`timescale 1 ns/1 psmodule uart_reg (clk, wr, mr, rd, write_thr, write_dlr, write_dmr, ena_ier, ena_lcr, ena_mcr, ena_sr, read_msr, read_iir, prevrdlsr, ctsn, dsrn, dcdn, rin, sin, lsreg_b0, lsreg11, lsreg_b2, lsreg_b3, lsreg_b4, lsreg51, lsreg_b7, temt, fcreg11, fcreg21, thrint, sout_org, d, thrint4, thrint5, sin_org, rtsn, dtrn, out1n, out2n, sout, dmreg, dlreg, iereg, lcreg, lsreg, mcreg, msreg, fcreg, sreg); `include "h16550_params.v" input clk; // System Clock input wr; // Write Enable input mr; // Master Reset input rd; // Read Enable input write_thr; // Write Transmitter holding register enable input write_dlr; // Write LSB divisor register enable input write_dmr; // Write MSB divisor register enable input ena_ier; // Interrupt Enable register enable input ena_lcr; // Line control register enable input ena_mcr; // Modem control register enable input ena_sr; // Scratch pad register enable input read_msr; // Read Modem status register enable input read_iir; // Read interrupt status register enable input prevrdlsr; // previous lsr read controller input ctsn; // Clear To Send Enable input dsrn; // Data Set Ready input dcdn; // Data Carrier Detect input rin; // Ring indicator input sin; // Serial Input input lsreg_b0; // Line Status register bit 0 input lsreg11; // Line Status register bit1 enable input lsreg_b2; // Line Status register bit 2 input lsreg_b3; // Line Status register bit 3 input lsreg_b4; // Line Status register bit 4 input lsreg51; // Line Status register bit 5 enable1 input lsreg_b7; // Line Status register bit 7 input temt; // Transmitter Fifo Empty input fcreg11; // Fifo Control register bit 1 enable1 input fcreg21; // Fifo Control register bit 2 enable1 input thrint; // Transmitter Holding Register interrupt input sout_org; // Internal Serial output signal input[DATA_WIDTH - 1:0] d; // Data input bus output thrint4; // Transmitter Holding Register interrupt enable4 wire thrint4; output thrint5; // Transmitter Holding Register interrupt enable5 wire thrint5; output sin_org; // Internal Serial input signal reg sin_org; output rtsn; // Request To send reg rtsn; output dtrn; // Data terminal ready reg dtrn; output out1n; // Ouput 1 reg out1n; output out2n; // Ouput 2 reg out2n; output sout; // Serial output reg sout; output[DATA_WIDTH - 1:0] dmreg; // MSB divisor register reg[DATA_WIDTH - 1:0] dmreg; output[DATA_WIDTH - 1:0] dlreg; // LSB divisor register reg[DATA_WIDTH - 1:0] dlreg; output[3:0] iereg; // Interrupt Enable register reg[3:0] iereg; output[DATA_WIDTH - 1:0] lcreg; // Line control register reg[DATA_WIDTH - 1:0] lcreg; output[DATA_WIDTH - 1:0] lsreg; // Line status register wire[DATA_WIDTH - 1:0] lsreg; output[4:0] mcreg; // Modem control register wire[4:0] mcreg; output[DATA_WIDTH - 1:0] msreg; // Modem status register reg[DATA_WIDTH - 1:0] msreg; output[5:0] fcreg; // Fifo Control register wire[5:0] fcreg; output[DATA_WIDTH - 1:0] sreg; reg[DATA_WIDTH - 1:0] sreg; reg cts_org; reg dsr_org; reg ri_org; reg dcd_org; reg prev_cts; reg prev_dsr; reg prev_ri; reg prev_dcd; reg lsreg10; reg lsreg50; reg fcreg20; reg fcreg10; reg lsreg02; reg[5:0] fcreg_int; wire[DATA_WIDTH - 1:0] lsreg_int; reg[4:0] mcreg_int; reg thrint4_int; reg thrint5_int; assign fcreg = fcreg_int ; assign mcreg = mcreg_int ; assign lsreg = lsreg_int ; assign thrint4 = thrint4_int ; assign thrint5 = thrint5_int ; assign lsreg_int[0] = lsreg02 ^ lsreg_b0 ; assign lsreg_int[1] = lsreg10 ^ lsreg11 ; assign lsreg_int[2] = lsreg_b2 ; assign lsreg_int[3] = lsreg_b3 ; assign lsreg_int[4] = lsreg_b4 ; assign lsreg_int[5] = ~(lsreg50 ^ lsreg51) ; assign lsreg_int[6] = temt ; assign lsreg_int[7] = lsreg_b7 ; always @(fcreg10 or fcreg11) begin fcreg_int[1] = fcreg10 ^ fcreg11 ; end always @(fcreg20 or fcreg21) begin fcreg_int[2] = fcreg20 ^ fcreg21 ; end //------------------------ // Local loopback feature //------------------------ always @(mcreg_int or sout_org or sin or ctsn or dsrn or rin or dcdn) begin if ((mcreg_int[4]) == 1'b1) begin // LOOP sout <= 1'b1 ; sin_org <= sout_org ; msreg[4] <= mcreg_int[1] ; msreg[5] <= mcreg_int[0] ; msreg[6] <= mcreg_int[2] ; msreg[7] <= mcreg_int[3] ; rtsn <= 1'b1 ; dtrn <= 1'b1 ; out1n <= 1'b1 ; out2n <= 1'b1 ; dsr_org <= ~mcreg_int[0] ; cts_org <= ~mcreg_int[1] ; ri_org <= ~mcreg_int[2] ; dcd_org <= ~mcreg_int[3] ; end else begin sout <= sout_org ; sin_org <= sin ; msreg[4] <= ~ctsn ; msreg[5] <= ~dsrn ; msreg[6] <= ~rin ; msreg[7] <= ~dcdn ; rtsn <= ~mcreg_int[1] ; dtrn <= ~mcreg_int[0] ; out1n <= ~mcreg_int[2] ; out2n <= ~mcreg_int[3] ; dsr_org <= dsrn ; cts_org <= ctsn ; ri_org <= rin ; dcd_org <= dcdn ; end end //--------------------------- // Interrupt enable register //--------------------------- always @(posedge mr or negedge wr) begin if (mr == 1'b1) begin iereg <= {4{1'b0}} ; end else begin if (ena_ier == 1'b1) begin iereg <= d[3:0] ; end end end //----------------------- // Line control register //----------------------- always @(posedge mr or negedge wr) begin if (mr == 1'b1) begin lcreg <= {1{1'b0}} ; end else begin if (ena_lcr == 1'b1) begin lcreg <= d ; end end end //-------------------------------------- // LINE STATUS register bit 1 resetting //-------------------------------------- always @(posedge mr or posedge clk) begin if (mr == 1'b1) begin lsreg10 <= 1'b0 ; end else begin if (prevrdlsr == 1'b1 & rd == 1'b0 & (fcreg_int[1]) == 1'b0) begin lsreg10 <= lsreg11 ; end end end //-------------------------------------- // LINE STATUS register bit 5 resetting //-------------------------------------- always @(posedge mr or negedge wr) begin if (mr == 1'b1) begin lsreg50 <= 1'b0 ; end else begin if (write_thr == 1'b1 & (lsreg_int[5]) == 1'b1) begin lsreg50 <= ~lsreg50 ; end end end //---------------------------- // MODEM control register //---------------------------- always @(posedge mr or negedge wr) begin if (mr == 1'b1) begin mcreg_int <= {5{1'b0}} ; end else begin if (ena_mcr == 1'b1) begin mcreg_int <= d[4:0] ; end end end //------------------ // Scratch register //------------------ always @(posedge mr or negedge wr) begin if (mr == 1'b1) begin sreg <= {1{1'b0}} ; end else begin if (ena_sr == 1'b1) begin sreg <= d ; end end end //---------------------------- // Divisor latch LSB register //---------------------------- always @(posedge mr or negedge wr) begin if (mr == 1'b1) begin dlreg <= 8'b00000001 ; end else begin if (write_dlr == 1'b1) begin dlreg <= d ; end end end //---------------------------- // Divisor latch MSB register //---------------------------- always @(posedge mr or negedge wr) begin if (mr == 1'b1) begin dmreg <= 8'b00000000 ; end else begin if (write_dmr == 1'b1) begin dmreg <= d ; end end end //---------------------------------------------------------------------- // Interrupt is enabled in the middle of interrupt (lsreg(5) = 1) will // cause interrupt //---------------------------------------------------------------------- always @(posedge mr or posedge clk) begin if (mr == 1'b1) begin thrint5_int <= 1'b0 ; end else begin if (ena_ier == 1'b1 & wr == 1'b1) begin if ((d[1]) == 1'b1 & thrint == 1'b0 & (lsreg_int[5]) == 1'b1) begin thrint5_int <= ~(thrint5_int) ; end end end end //----------------------- // FIFO control register //----------------------- always @(posedge mr or negedge wr) begin if (mr == 1'b1) begin fcreg_int[5:3] <= 3'b000 ; fcreg_int[0] <= 1'b0 ; fcreg20 <= 1'b0 ; fcreg10 <= 1'b0 ; thrint4_int <= 1'b0 ; lsreg02 <= 1'b0 ; end else begin if (read_iir == 1'b1) begin if ((d[0]) == 1'b1) begin fcreg_int[5:4] <= d[DATA_WIDTH - 1:6] ; fcreg_int[3] <= d[3] ; fcreg_int[0] <= d[0] ; // changing 16450 mode to FIFO mode will // cause THRE (transmitter fifo empty) interrupt if ((fcreg_int[0]) == 1'b0 & thrint == 1'b0) begin thrint4_int <= ~(thrint4_int) ; end if ((d[2]) == 1'b1 & (fcreg_int[2]) == 1'b0) begin fcreg20 <= ~fcreg20 ; end if ((d[1]) == 1'b1 & (fcreg_int[1]) == 1'b0) begin fcreg10 <= ~fcreg10 ; end end else begin fcreg_int[5:3] <= 3'b000 ; fcreg_int[0] <= 1'b0 ; // changing FIFO mode to 16450 mode will // cause THRE interrupt if ((fcreg_int[0]) == 1'b1 & thrint == 1'b0) begin thrint4_int <= ~(thrint4_int) ; end if ((fcreg_int[0]) == 1'b1 & lsreg_b0 == 1'b1) begin lsreg02 <= ~(lsreg02) ; end if ((fcreg_int[2]) == 1'b1) begin fcreg20 <= ~fcreg20 ; end if ((fcreg_int[1]) == 1'b1) begin fcreg10 <= ~fcreg10 ; end end end end end always @(posedge clk) begin prev_dsr <= dsr_org ; prev_cts <= cts_org ; prev_ri <= ri_org ; prev_dcd <= dcd_org ; end //------------------------------- // Indicate change in CTS signal //------------------------------- always @(posedge mr or posedge clk) begin if (mr == 1'b1) begin msreg[0] <= 1'b0 ; end else begin if ((cts_org == 1'b1 & prev_cts == 1'b0) | (cts_org == 1'b0 & prev_cts == 1'b1)) begin msreg[0] <= 1'b1 ; end else if (read_msr == 1'b1) begin msreg[0] <= 1'b0 ; end end end //------------------------------- // Indicate change in DSR signal //------------------------------- always @(posedge mr or posedge clk) begin if (mr == 1'b1) begin msreg[1] <= 1'b0 ; end else begin if ((dsr_org == 1'b1 & prev_dsr == 1'b0) | (dsr_org == 1'b0 & prev_dsr == 1'b1)) begin msreg[1] <= 1'b1 ; end else if (read_msr == 1'b1) begin msreg[1] <= 1'b0 ; end end end //------------------------------- // Indicate change in DCD signal //------------------------------- always @(posedge mr or posedge clk) begin if (mr == 1'b1) begin msreg[3] <= 1'b0 ; end else begin if ((dcd_org == 1'b1 & prev_dcd == 1'b0) | (dcd_org == 1'b0 & prev_dcd == 1'b1)) begin msreg[3] <= 1'b1 ; end else if (read_msr == 1'b1) begin msreg[3] <= 1'b0 ; end end end //----------------------------------- // Indicate rising edge in RI signal //----------------------------------- always @(posedge mr or posedge clk) begin if (mr == 1'b1) begin msreg[2] <= 1'b0 ; end else begin if (ri_org == 1'b1 & prev_ri == 1'b0) begin msreg[2] <= 1'b1 ; end else if (read_msr == 1'b1) begin msreg[2] <= 1'b0 ; end end end endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -