URL
https://opencores.org/ocsvn/m16c5x/m16c5x/trunk
Subversion Repositories m16c5x
[/] [m16c5x/] [trunk/] [RTL/] [Src/] [M16C5x.v] - Rev 2
Compare with Previous | Blame | View Log
//////////////////////////////////////////////////////////////////////////////// // // Copyright 2013 by Michael A. Morris, dba M. A. Morris & Associates // // All rights reserved. The source code contained herein is publicly released // under the terms and conditions of the GNU Lesser Public License. No part of // this source code may be reproduced or transmitted in any form or by any // means, electronic or mechanical, including photocopying, recording, or any // information storage and retrieval system in violation of the license under // which the source code is released. // // The source code contained herein is free; it may be redistributed and/or // modified in accordance with the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either version 2.1 of // the GNU Lesser General Public License, or any later version. // // The source code contained herein is freely released WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A // PARTICULAR PURPOSE. (Refer to the GNU Lesser General Public License for // more details.) // // A copy of the GNU Lesser General Public License should have been received // along with the source code contained herein; if not, a copy can be obtained // by writing to: // // Free Software Foundation, Inc. // 51 Franklin Street, Fifth Floor // Boston, MA 02110-1301 USA // // Further, no use of this source code is permitted in any form or means // without inclusion of this banner prominently in any derived works. // // Michael A. Morris // Huntsville, AL // //////////////////////////////////////////////////////////////////////////////// `timescale 1ns / 1ps //////////////////////////////////////////////////////////////////////////////// // Company: M. A. Morris & Associates // Engineer: Michael A. Morris // // Create Date: 19:30:58 06/15/2013 // Design Name: Microcomputer Implementation using P16C5x Processor Core // Module Name: M16C5x.v // Project Name: C;\XProjects\ISE10.1i\M16C5x // Target Devices: RAM-based FPGA // Tool versions: Xilinx ISE 10.1i SP3 // // Description: // // This module is a microcomputer implementation using an FPGA-based processor // core based on the P16C5x module. The P16C5x is derived from the released // PIC16C5x core found on GitHUB. The P16C5x differs from that core in that the // TRISA..TRISC registers, and the IO Ports A..C have been removed and replaced // by a number of WE and RE strobes and an IO data bus. // // This modification has been done to demonstrate how the PIC16C5x core can be // adapted to interface to a UART or an SPI Master. By using the P16C5x core, // a microcomputer implementation can be generated for a small FPGA that pro- // vides significant processing capabilities. By using a core like the P16C5x, // standard programming languages and support tools can be used to ease the // development of sophisticated FPGA-based products. // // Dependencies: M16C5x_ClkGen.v // ClkGen.xaw // fedet.v // P16C5x.v // P16C5x_IDec.v // P16C5x_ALU.v // M16C5x_SPI.v // DPSFmnCE.v // SPIxIF.v // M16C5x_UART.v // SSPx_Slv.v // SSP_UART.v // re1ce.v // DPSFmnCE.v // UART_BRG.v // UART_TXSM.v // UART_RXSM.v // UART_RTO.v // UART_INT.v // redet.v // fedet.v // // Revision: // // 0.01 13F15 MAM Initial creation of the M16C5x module. // // 2.20 13G14 MAM Updated all of the module instantiations and the top // module to support the parameterization of the soft- // core microcontroller from the top level: M16C5x. Up- // dated Dependencies section, and set revision to // match the release number on GitHUB. // // 2.30 13G21 MAM Changed UART Clk to operate from the Clk2x output of // DCM. Gives a fixed value for the UART Clk regardless // of the ClkFX output frequency. Adjusted default PS, // Div values to produce 9600 bps as the default. // // 2.40 13J18 MAM Remove CE TFF, and force single cycle operation. // Changed clock edge for internal block RAM from the // rising edge to the falling edge. This allows M16C5x // to function as a single cycle core when operating // from internal block RAM. // // 2.41 13J19 MAM Modified the UART FIFOs to be 64 elements deep. // // Additional Comments: // //////////////////////////////////////////////////////////////////////////////// module M16C5x #( // P16C5x Module Parameter Settings parameter pWDT_Size = 20, // 20 - synthesis; 10 - Simulation parameter pRstVector = 12'h7FF, // Reset Vector Location (PIC16F59) parameter pUserProg = "Src/M16C5x_Tst4.coe", // Tst Pgm file: 4096 x 12 parameter pRAMA_Init = "Src/RAMA.coe", // RAM A initial value file ( 8x8) parameter pRAMB_Init = "Src/RAMB.coe", // RAM B initial value file (64x8) // M16C5x_SPI Module Parameter Settings parameter pSPI_CR_Default = 8'b0_110_00_0_0, // SPI Interface Defaults parameter pSPI_TF_Depth = 4, // Tx FIFO Depth: 2**pTF_Depth parameter pSPI_RF_Depth = 4, // Rx FIFO Depth: 2**pRF_Depth parameter pSPI_TF_Init = "Src/TF_Init.coe", // Tx FIFO Memory Init parameter pSPI_RF_Init = "Src/RF_Init.coe", // Rx FIFO Memory Init // SSP_UART Module Parameter Settings parameter pPS_Default = 4'h0, // see baud rate tables SSP_UART parameter pDiv_Default = 8'hBF, // BR = 9600 @UART_Clk = 29.4912 MHz parameter pRTOChrDlyCnt = 3, // Rcv Time Out Character Dly Count parameter pUART_TF_Depth = 2, // Tx FIFO Depth: 2**(pTF_Depth + 4) parameter pUART_RF_Depth = 2, // Rx FIFO Depth: 2**(pRF_Depth + 4) parameter pUART_TF_Init = "Src/UART_TF.coe", // Tx FIFO Memory Init parameter pUART_RF_Init = "Src/UART_RF.coe" // Rx FIFO Memory Init )( input ClkIn, // External Clk - drives 4x DCM input nMCLR, // Master Clear Input input nT0CKI, // Timer 0 Clk Input input nWDTE, // Watch Dog Timer Enable input PROM_WE, // Temporary Signal to Force Block RAM output TD, // UART TD Output input RD, // UART RD Input output nRTS, // UART Request To Send (active low) Out input nCTS, // UART Clear to Send (active low) Input output DE, // UART RS-485 Driver Enable output [2:0] nCS, // SPI Chip Select (active low) Output output SCK, // SPI Serial Clock output MOSI, // SPI Master Out/Slave In Output input MISO, // SPI Master In/Slave Out Input // Test Signals output [2:0] nCSO, output nWait ); //////////////////////////////////////////////////////////////////////////////// // // Declarations // wire ClkEn; reg [11:0] PROM [4095:0]; // User Program ROM (3x Block RAMs) wire [11:0] PROM_Addrs; // Program Counter from CPU reg [11:0] PROM_DO; // Instruction Register to CPU reg nWDTE_IFD, nT0CKI_IFD; // IOB FFs for external inputs wire WDTE, T0CKI; wire [7:0] IO_DO; // IO Data Output bus reg [7:0] IO_DI; // IO Data Input bus reg [7:0] TRISA, TRISB; // IO Ports reg [7:0] PORTA, PORTB; wire [1:0] CS; // Chip select outputs of the SPI Mstr wire SPI_SCK; // SPI SCK for internal components wire SPI_MOSI, SPI_MISO; wire [7:0] SPI_DO; // Output Data Bus of SPI Master module wire TF_EF, TF_FF, RF_EF, RF_FF; // SPI Module Status Signals wire SSP_MISO; // SSP UART MISO signal wire RTS, CTS; // SSP UART Modem Control Signals wire IRQ; // SSP UART Interrupt Request Signal //////////////////////////////////////////////////////////////////////////////// // // Implementation // // Instantiate the Clk and Reset Generator Module M16C5x_ClkGen ClkGen ( .nRst(nMCLR), .ClkIn(ClkIn), .Clk(Clk), // Clk <= (M/D) x ClkIn .Clk_UART(Clk_UART), // Clk_UART <= 2x ClkIn .BufClkIn(), // RefClk <= Buffered ClkIn .Rst(Rst) ); // Force Single Cycle Operation assign ClkEn = 1; // Register Inputs and connect to CPU always @(posedge Clk) begin if(Rst) begin nWDTE_IFD <= #1 1; nT0CKI_IFD <= #1 1; end else if(ClkEn) begin nWDTE_IFD <= #1 nWDTE; nT0CKI_IFD <= #1 nT0CKI; end end assign WDTE = ~nWDTE_IFD; assign T0CKI = ~nT0CKI_IFD; // Instantiate the P16C5x module P16C5x #( .pRstVector(pRstVector), .pWDT_Size(pWDT_Size), .pRAMA_Init(pRAMA_Init), .pRAMB_Init(pRAMB_Init) ) CPU ( .POR(Rst), .Clk(Clk), .ClkEn(ClkEn), .MCLR(Rst), .T0CKI(T0CKI), .WDTE(WDTE), .PC(PROM_Addrs), .ROM(PROM_DO), .WE_TRISA(WE_TRISA), .WE_TRISB(WE_TRISB), .WE_TRISC(WE_TRISC), .WE_PORTA(WE_PORTA), .WE_PORTB(WE_PORTB), .WE_PORTC(WE_PORTC), .RE_PORTA(RE_PORTA), .RE_PORTB(RE_PORTB), .RE_PORTC(RE_PORTC), .IO_DO(IO_DO), .IO_DI(IO_DI), .Rst(), .OPTION(), .IR(), .dIR(), .ALU_Op(), .KI(), .Msk(), .Err(), .Skip(), .TOS(), .NOS(), .W(), .FA(), .DO(), .DI(), .TMR0(), .FSR(), .STATUS(), .T0CKI_Pls(), .WDTClr(), .WDT(), .WDT_TC(), .WDT_TO(), .PSCntr(), .PSC_Pls() ); //////////////////////////////////////////////////////////////////////////////// // // User Program ROM // initial $readmemh(pUserProg, PROM, 0, 4095); assign WE_PROM = ClkEn & WE_PORTA & PROM_WE; always @(negedge Clk) begin if(Rst) PROM_DO <= #1 0; else if(WE_PROM) PROM[{PORTB[7:0], TRISB[7:4]}] <= #1 {TRISB[3:0], TRISA[7:0]}; else PROM_DO <= #1 PROM[PROM_Addrs]; end //////////////////////////////////////////////////////////////////////////////// // // M16C5x I/O // always @(posedge Clk) begin if(Rst) begin TRISA <= #1 ~0; TRISB <= #1 ~0; // PORTA <= #1 ~0; PORTB <= #1 ~0; end else if(ClkEn) begin TRISA <= #1 ((WE_TRISA) ? IO_DO : TRISA); TRISB <= #1 ((WE_TRISB) ? IO_DO : TRISB); // PORTA <= #1 ((WE_PORTA) ? IO_DO : PORTA); PORTB <= #1 ((WE_PORTB) ? IO_DO : PORTB); end end always @(*) begin casex({RE_PORTA, RE_PORTB, RE_PORTC}) 3'b1xx : IO_DI <= {IRQ, CTS, RTS, DE, RF_FF, RF_EF, TF_FF, TF_EF}; 3'b01x : IO_DI <= PORTB; 3'b001 : IO_DI <= SPI_DO; default : IO_DI <= 0; endcase end //assign TD = ~PORTA[7]; //assign nRTS = ~PORTA[6]; assign nCSO[2] = 1; assign nCSO[1] = 1; assign nCSO[0] = ~CS[0]; assign nWait = ~CS[1]; // Instantiate the M16C5x SPI Interface module assign SPI_MISO = ((CS[1]) ? SSP_MISO : MISO); M16C5x_SPI #( .pCR_Default(pSPI_CR_Default), .pTF_Depth(pSPI_TF_Depth), .pRF_Depth(pSPI_RF_Depth), .pTF_Init(pSPI_TF_Init), .pRF_Init(pSPI_RF_Init) ) SPI ( .Rst(Rst), .Clk(Clk), .ClkEn(ClkEn), .WE_CR(WE_TRISC), .WE_TF(WE_PORTC), .RE_RF(RE_PORTC), .DI(IO_DO), .DO(SPI_DO), .CS(CS[1:0]), .SCK(SCK), .MOSI(SPI_MOSI), .MISO(SPI_MISO), .SS(SS), .TF_FF(TF_FF), .TF_EF(TF_EF), .RF_FF(RF_FF), .RF_EF(RF_EF) ); assign nCS[0] = ~CS[0]; assign nCS[1] = ~CS[1]; assign nCS[2] = 1'b1; assign MOSI = SPI_MOSI; // Instantiate Global Clock Buffer for driving the SPI Clock to internal nodes BUFG BUF1 ( .I(SCK), .O(SPI_SCK) ); // Instantiate UART with an NXP LPC213x/LPC214x SSP-compatible interface assign CTS = ~nCTS; M16C5x_UART #( .pPS_Default(pPS_Default), .pDiv_Default(pDiv_Default), .pRTOChrDlyCnt(pRTOChrDlyCnt), .pTF_Depth(pUART_TF_Depth), .pRF_Depth(pUART_RF_Depth), .pTF_Init(pUART_TF_Init), .pRF_Init(pUART_RF_Init) ) UART ( .Rst(Rst), .Clk_UART(Clk_UART), .SSEL(CS[1]), .SCK(SPI_SCK), .MOSI(SPI_MOSI), .MISO(SSP_MISO), .TxD(TD), .RTS(RTS), .RxD(RD), .CTS(CTS), .DE(DE), .IRQ(IRQ) ); assign nRTS = ~RTS; endmodule