OpenCores
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
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.