OpenCores
URL https://opencores.org/ocsvn/m16c5x/m16c5x/trunk

Subversion Repositories m16c5x

[/] [m16c5x/] [trunk/] [RTL/] [Src/] [M16C5x.txt] - Rev 3

Go to most recent revision | 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.
//
// 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 = 0,           // Tx FIFO Depth: 2**(pTF_Depth + 4)
    parameter pUART_RF_Depth = 3,           // 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
//

reg     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)
                );

//  Generate Clock Enable (Clk/2)

always @(posedge Clk or posedge Rst) ClkEn <= #1 ((Rst) ? 0 : ~ClkEn);

//  Register Inputs and connect to CPU

always @(posedge Clk) nWDTE_IFD  <= #1 ((Rst) ? 1 : nWDTE );
always @(posedge Clk) nT0CKI_IFD <= #1 ((Rst) ? 1 : nT0CKI);

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(),
            .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 @(posedge 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

//always @(posedge <clock>) begin
//    if (<enableA>) begin
//        if (<write_enableA>)
//            <ram_name>[<addressA>] <= <input_dataA>;
//        <output_dataA> <= <ram_name>[<addressA>];
//    end
//    if (<enableB>)
//        <output_dataB> <= <ram_name>[<addressB>];
//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

Go to most recent revision | 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.