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

Subversion Repositories m16c5x

[/] [m16c5x/] [trunk/] [RTL/] [Src/] [P16C5x_ALU.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:     14:53:13 06/15/2013 
// Design Name:     P16C5x-compatible Synthesizable Processor Core
// Module Name:     P16C5x_ALU 
// Project Name:    C:\XProjects\ISE10.1i\M16C5x 
// Target Devices:  RAM-based FPGAs: XC3S50A-xVQ100, XC3S200A-xVQ100 
// Tool versions:   Xilinx ISE 10.1i SP3
//
// Description:
//
//  Module implements the ALU of the P16C5x synthesizable processor core. It has
//  been taken out of the PIC16C5x synthesizable processor core and made into a 
//  separate module. No changes have been made to the ALU code in the process.
//
// Dependencies: 
//
// Revision:
// 
//  1.00    13F15   MAM     Original file creation date.
//
//  1.10    13F23   MAM     Changed order of ALU_Op[10] and ALU_Op[9]. Now the
//                          modules uses ALU_Op[9:0] internally instead of 
//                          {ALU_Op[10], ALU_Op[8:0]} as originally constructed.
//
//  1.20    13J19   MAM     Changed Write Enable/Clock Enable logic to remove
//                          multiplexers and make better use of the built-in
//                          functionality of the logic blocks in the FPGA.
//
//  1.30    13J20   MAM     Removed the internal bit mask ROM, and added an bit
//                          mask input port. Reconfigured Bit Unit to use the
//                          bit mask input port.
// 
// Additional Comments:
//
//  The ALU data output, DO, has been registered to support a higher operating
//  speed when a multi-cycle instruction cycle is used. Parameterization of this
//  may be added in the future, but the current module must be edited to remove
//  the DO register and the un-registered multiplexer, which has been commented
//  out, added back in when single cycle operation is desired.
//
////////////////////////////////////////////////////////////////////////////////
 
module P16C5x_ALU (
    input   Rst,
    input   Clk,
    input   CE,
 
    input   [9:0] ALU_Op,               // ALU Control Word
    input   WE_PSW,                     // Write Enable for {Z, DC, C} from DI
 
    input   [7:0] DI,                   // Data Input
    input   [7:0] KI,                   // Literal Input
    input   [7:0] Msk,                  // Bit Mask Input
 
    output  reg [7:0] DO,               // ALU Output
    output  Z_Tst,                      // ALU Zero Test Output
    output  g,                          // Bit Test Condition
 
    output  reg [7:0] W,                // Working Register 
 
    output  reg Z,                      // Z(ero) ALU Status Output
    output  reg DC,                     // Digit Carry ALU Status Output
    output  reg C                       // Carry Flag ALU Status Output
);
 
////////////////////////////////////////////////////////////////////////////////
//
//  Declarations
//
 
wire    [7:0] A, B, Y;
 
wire    [7:0] X;
wire    C3, C7;
 
wire    [1:0] LU_Op;
reg     [7:0] V;
 
wire    [1:0] S_Sel;
reg     [7:0] S;
 
wire    [7:0] U;
wire    [7:0] T;
 
wire    [1:0] D_Sel;
 
////////////////////////////////////////////////////////////////////////////////
//
//  ALU Implementation - ALU[3:0] are overloaded for the four ALU elements:
//                          Arithmetic Unit, Logic Unit, Shift Unit, and Bit
//                          Processor.
//
//  ALU Operations - Arithmetic, Logic, and Shift Units
//
//  ALU_Op[1:0] = ALU Unit Operation Code
//
//      Arithmetic Unit (AU): 00 => Y = A +  B;
//                            01 => Y = A +  B + 1;
//                            10 => Y = A + ~B     = A - B - 1;
//                            11 => Y = A + ~B + 1 = A - B;
//
//      Logic Unit (LU):      00 => V = ~A;
//                            01 => V =  A & B;
//                            10 => V =  A | B;
//                            11 => V =  A ^ B;
//
//      Shift Unit (SU):      00 => S = W;                // MOVWF
//                            01 => S = {A[3:0], A[7:4]}; // SWAPF
//                            10 => S = {C, A[7:1]};      // RRF
//                            11 => S = {A[6:0], C};      // RLF
//
//  ALU_Op[3:2] = ALU Operand:
//                  A      B
//          00 =>  File    0
//          01 =>  File    W
//          10 => Literal  0
//          11 => Literal  W;
//
//  ALU Operations - Bit Processor (BP)
//
//  ALU_Op[3] = Set: 0 - Clr Selected Bit;
//                   1 - Set Selected Bit;
//
//  ALU_Op[5:4] = Status Flag Update Select
//
//          00 => None
//          01 => C
//          10 => Z
//          11 => Z,DC,C
//
//  ALU_Op[7:6] = ALU Output Data Multiplexer
//
//          00 => AU
//          01 => LU
//          10 => SU
//          11 => BP
//
//  ALU_Op[8]  = Tst: 0 - Normal Operation
//                    1 - Test: INCFSZ/DECFSZ/BTFSC/BTFSS
//
//  ALU_Op[9]  = Write Enable Working Register (W)
//
//  ALU_Op[10] = Indirect Register, INDF, Selected
//
//  ALU_Op[11] = Write Enable File {RAM | Special Function Registers}
//
 
assign C_In  = ALU_Op[0];  // Adder Carry input
assign B_Inv = ALU_Op[1];  // B Bus input invert
assign B_Sel = ALU_Op[2];  // B Bus select
assign A_Sel = ALU_Op[3];  // A Bus select
 
//  AU Input Bus Multiplexers
 
assign A = ((A_Sel) ? KI : DI);
assign B = ((B_Sel) ?  W : 0 );
assign Y = ((B_Inv) ? ~B : B );
 
//  AU Adder
 
assign {C3, X[3:0]} = A[3:0] + Y[3:0] + C_In;
assign {C7, X[7:4]} = A[7:4] + Y[7:4] + C3;
 
//  Logic Unit (LU)
 
assign LU_Op = ALU_Op[1:0];
 
always @(*)
begin
    case (LU_Op)
        2'b00 : V <= ~A;
        2'b01 : V <=  A | B;
        2'b10 : V <=  A & B;
        2'b11 : V <=  A ^ B;
    endcase
end
 
//  Shifter and W Multiplexer
 
assign S_Sel = ALU_Op[1:0];
 
always @(*)
begin
    case (S_Sel)
        2'b00 : S <= B;                  // Pass Working Register (MOVWF)
        2'b01 : S <= {A[3:0], A[7:4]};   // Swap Nibbles (SWAPF)
        2'b10 : S <= {C, A[7:1]};        // Shift Right (RRF)
        2'b11 : S <= {A[6:0], C};        // Shift Left (RLF)
    endcase
end
 
//  Bit Processor
 
assign Set = ALU_Op[3];
assign Tst = ALU_Op[8];
 
assign U = ((Set) ? (DI | Msk) : (DI & ~Msk));
 
assign T = (DI & Msk);
assign g = ((Tst) ? ((Set) ? |T : ~|T) 
                  : 1'b0              );
 
//  Output Data Mux
 
assign D_Sel = ALU_Op[7:6];
 
always @(*)
begin
    case (D_Sel)
        2'b00 : DO <= X;     // Arithmetic Unit Output
        2'b01 : DO <= V;     // Logic Unit Output
        2'b10 : DO <= S;     // Shifter Output
        2'b11 : DO <= U;     // Bit Processor Output
    endcase
end
 
//  Working Register
 
assign WE_W = CE & ALU_Op[9];
 
always @(posedge Clk)
begin
    if(Rst)
        W <= #1 8'b0;
    else if(WE_W)
        W <= #1 DO;
end
 
//  Z Register
 
assign Z_Sel = ALU_Op[5];
assign Z_Tst = ~|DO;
 
assign CE_Z  = CE & (WE_PSW | Z_Sel);
 
always @(posedge Clk)
begin
    if(Rst)
        Z <= #1 1'b0;
    else if(CE_Z)
        Z <= #1 ((WE_PSW) ? DO[2] : Z_Tst); 
end
 
//  Digit Carry (DC) Register
 
assign DC_Sel = ALU_Op[5] & ALU_Op[4];
assign CE_DC  = CE & (WE_PSW | DC_Sel);
 
always @(posedge Clk)
begin
    if(Rst)
        DC <= #1 1'b0;
    else if(CE_DC)
        DC <= #1 ((WE_PSW) ? DO[1] : C3);
end
 
//  Carry (C) Register
 
assign C_Sel = ALU_Op[4];
assign S_Dir = ALU_Op[1] & ALU_Op[0];
assign C_Drv = ((~ALU_Op[7] & ~ALU_Op[6]) ? C7 : ((S_Dir) ? A[7] : A[0]));
 
assign CE_C  = CE & (WE_PSW | C_Sel);
 
always @(posedge Clk)
begin
    if(Rst)
        C <= #1 1'b0;
    else if(CE_C)
        C <= #1 ((WE_PSW) ? DO[0] : C_Drv);
end
 
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.