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

Subversion Repositories m32632

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /m32632
    from Rev 8 to Rev 9
    Reverse comparison

Rev 8 → Rev 9

/trunk/rtl/ICACHE_SM.v
0,0 → 1,359
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: ICACHE_SM.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// 1. KOLDETECT Collision Detection Unit
// 2. ICACHE_SM Instruction Cache State Machine
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. KOLDETECT Collision Detection Unit
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module KOLDETECT ( BCLK, BRESET, DRAM_WR, CVALID, ADDR, TAG0, TAG1 , CFG , C_VALID, READ_I, ACC_OK,
NEWCVAL, KOLLISION, STOP_ICRD, RUN_ICRD, KILL, KILLADR, ICTODC, STOP_CINV );
 
input BCLK;
input BRESET;
input DRAM_WR;
input [23:0] CVALID; // Data from master Valid RAM
input [27:4] ADDR;
input [27:12] TAG0,TAG1;
input [1:0] CFG;
input [23:0] C_VALID; // Data from secondary Valid RAM
input READ_I;
input ACC_OK;
input HOLD; // active low
input KDET;
input INVAL_A; // Cache Invalidate All
input ENA_HK; // Enable HOLD and Kohaerenz
output [23:0] NEWCVAL;
output KOLLISION;
output STOP_ICRD;
output RUN_ICRD;
output KILL;
output [11:7] KILLADR;
output [2:0] ICTODC;
output STOP_CINV;
reg [27:4] addr_r;
reg [7:0] maske,clear;
reg do_koll;
reg [2:0] counter;
reg [1:0] wpointer,rpointer;
reg [35:0] adrfifo;
reg [8:0] fifo_q,fifo_c;
reg [1:0] state;
reg pipe;
reg do_kill;
reg dma;
 
wire [7:0] set_0,set_1;
wire match_0,match_1;
wire valid_0,valid_1;
wire found_0,found_1;
wire kolli,dma_kolli;
wire last_match;
wire wr_entry;
wire [23:0] cdaten;
wire [8:0] kaddr;
wire [7:0] new_0,new_1;
wire dma_mode,ic_dma;
wire free,ende;
wire init_b;
 
always @(posedge BCLK) do_koll <= DRAM_WR & CFG[0]; // one cycle pulse, without Cache Enable no col
always @(posedge BCLK) addr_r <= ADDR;
// similar logic like in CA_MATCH
assign set_0 = C_VALID[7:0];
assign set_1 = C_VALID[15:8];
assign valid_0 = set_0[addr_r[6:4]];
assign valid_1 = set_1[addr_r[6:4]];
assign match_0 = ( TAG0 == addr_r[27:12] ); // 4KB
assign match_1 = ( TAG1 == addr_r[27:12] ); // 4KB
assign found_0 = valid_0 & match_0;
assign found_1 = valid_1 & match_1;
assign kolli = (found_0 | found_1) & ~CFG[1] & do_koll; // Action only if ICACHE is not locked
 
assign KOLLISION = (found_0 | found_1) & do_koll; // to Statistik Modul, Register there
 
assign dma_kolli = (found_0 | found_1) & ~CFG[1] & CFG[0];
// the FIFO with 4 entries :
assign init_b = CFG[0] & ~INVAL_A; // initialise if CINV A too
always @(posedge BCLK)
if (!init_b) wpointer <= 2'b00;
else
wpointer <= wpointer + {1'b0,wr_entry};
always @(posedge BCLK)
if (!init_b) rpointer <= 2'b00;
else
rpointer <= rpointer + {1'b0,do_kill};
always @(posedge BCLK)
begin
if (wr_entry && (wpointer == 2'b00)) adrfifo[8:0] <= {addr_r[11:4],found_1};
if (wr_entry && (wpointer == 2'b01)) adrfifo[17:9] <= {addr_r[11:4],found_1};
if (wr_entry && (wpointer == 2'b10)) adrfifo[26:18] <= {addr_r[11:4],found_1};
if (wr_entry && (wpointer == 2'b11)) adrfifo[35:27] <= {addr_r[11:4],found_1};
end
always @(adrfifo or rpointer)
case (rpointer)
2'b00 : fifo_q = adrfifo[8:0];
2'b01 : fifo_q = adrfifo[17:9];
2'b10 : fifo_q = adrfifo[26:18];
2'b11 : fifo_q = adrfifo[35:27];
endcase
always @(adrfifo or wpointer) // for Match of last entry use wpointer
case (wpointer)
2'b01 : fifo_c = adrfifo[8:0];
2'b10 : fifo_c = adrfifo[17:9];
2'b11 : fifo_c = adrfifo[26:18];
2'b00 : fifo_c = adrfifo[35:27];
endcase
// Control
assign last_match = counter[2] & (fifo_c == {addr_r[11:4],found_1}); // if Match with last Entry no
 
assign wr_entry = kolli & ~last_match;
always @(posedge BCLK)
casex ({init_b,wr_entry,do_kill,counter})
6'b0_xx_xxx : counter <= 3'b000;
6'b1_00_xxx : counter <= counter;
6'b1_11_xxx : counter <= counter;
6'b1_10_000 : counter <= 3'b100;
6'b1_10_1xx : counter <= (counter[1:0] == 2'b11) ? 3'b111 : {counter[2],(counter[1:0] + 2'b01)};
6'b1_01_1xx : counter <= (counter[1:0] == 2'b00) ? 3'b000 : {counter[2],(counter[1:0] + 2'b11)};
default : counter <= counter;
endcase
 
// DMA Access
always @(posedge BCLK) dma <= ~HOLD; // there is only one FF for this , from here to DCACHE
// Controlling of ICACHE
assign free = (~READ_I | ACC_OK) & ENA_HK; // switch off if CINV
always @(posedge BCLK) // state[1] state[0]
casex ({BRESET,dma,counter[2],free,ende,STOP_ICRD,dma_mode})
7'b0_xx_xx_xx : state <= 2'b00;
7'b1_00_xx_00 : state <= 2'b00;
7'b1_01_1x_00 : state <= 2'b10; // Start of DCACHE Kohaerenz
7'b1_1x_1x_00 : state <= 2'b11; // Start of DMA
//
7'b1_xx_x0_10 : state <= 2'b10; // without "ende" it stays as is
7'b1_0x_x1_10 : state <= 2'b00; // DMA is not active
7'b1_1x_x1_10 : state <= 2'b11; // to DMA !
//
7'b1_00_xx_11 : state <= 2'b00;
7'b1_01_xx_11 : state <= 2'b10;
7'b1_1x_xx_11 : state <= 2'b11;
default : state <= 2'b00;
endcase
assign STOP_ICRD = state[1]; // used for Multiplexer
assign dma_mode = state[0]; // internal Multiplexer
 
assign STOP_CINV = state[1] & ~ENA_HK; // stops CINV if DMA access or Kohaerenz access
assign ende = (counter[1:0] == 2'b00) & do_kill;
assign ic_dma = STOP_ICRD & dma_mode; // Signal to DCACHE that ICACHE has stoped
always @(posedge BCLK) pipe <= STOP_ICRD;
assign RUN_ICRD = ~(STOP_ICRD | pipe); // Release for IC_READ
always @(posedge BCLK) do_kill <= STOP_ICRD & ~dma_mode & ~do_kill; // Write pulse in Cache Valid R
assign KILL = do_kill | (KDET & dma_kolli);
// Valid Daten prepare : different sources for DMA and DCACHE Kohaerenz
assign cdaten = dma_mode ? C_VALID : CVALID;
assign kaddr = dma_mode ? {addr_r[11:4],found_1} : fifo_q;
assign KILLADR = kaddr[8:4];
always @(kaddr)
case (kaddr[3:1])
3'h0 : clear = 8'hFE;
3'h1 : clear = 8'hFD;
3'h2 : clear = 8'hFB;
3'h3 : clear = 8'hF7;
3'h4 : clear = 8'hEF;
3'h5 : clear = 8'hDF;
3'h6 : clear = 8'hBF;
3'h7 : clear = 8'h7F;
endcase
assign new_0 = kaddr[0] ? cdaten[7:0] : (cdaten[7:0] & clear);
assign new_1 = kaddr[0] ? (cdaten[15:8] & clear) : cdaten[15:8];
 
assign NEWCVAL = {cdaten[23:16],new_1,new_0};
// multiple signals are needed in DCACHE :
assign ICTODC = {dma,ic_dma,~(counter[2:1] == 2'b11)};
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. ICACHE_SM Instruction Cache State Machine
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module ICACHE_SM ( BCLK, BRESET, IO_SPACE, MDONE, IO_READY, MMU_HIT, CA_HIT, READ, PTE_ACC,
USE_CA, PTB_WR, PTB_SEL, USER, PROT_ERROR,
DRAM_ACC, IO_RD, IO_ACC, IC_PREQ, ACC_OK, HIT_ALL, CUPDATE, AUX_DAT, NEW_PTB, PTB_ONE );
 
input BCLK;
input BRESET;
input IO_SPACE;
input MDONE; // Memory Done : Feedback from DRAM Controller, BCLK aligned
input IO_READY;
input MMU_HIT,CA_HIT;
input READ;
input PTE_ACC;
input USE_CA;
input PTB_WR,PTB_SEL;
input USER;
input PROT_ERROR;
output reg DRAM_ACC,IO_RD;
output IO_ACC;
output IC_PREQ;
output ACC_OK;
output HIT_ALL;
output CUPDATE;
output AUX_DAT;
output reg NEW_PTB,PTB_ONE;
reg [3:0] new_state;
reg rd_done;
reg card_flag;
reg rd_rdy;
 
wire io_busy;
wire dram_go;
wire rd_ende;
wire do_ca_rd;
// Cycle : /-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_
// Access : _/-----------------------------------\__
// State Machine : ____/----------------------------\______
// Busy status ...
 
assign rd_ende = CA_HIT | rd_rdy; // CA_HIT only if Cache activ !
 
always @( READ // only READ , global control
or PROT_ERROR // is not allowed !
//
or IO_SPACE // indicates access in the IO_WELT
or io_busy // is already active ?
//
or MMU_HIT // Hit in the MMU , now only a READ can be active
or rd_ende // Cache Hit
or DRAM_ACC // DRAM Access running
//
or PTE_ACC ) // PTE Access running
// #_# #_# #_#
casex ({READ,PROT_ERROR,IO_SPACE,io_busy,MMU_HIT,rd_ende,DRAM_ACC,PTE_ACC})
// MMU Miss : PTE load from memory
8'b10_xx_0xx_0 : new_state = 4'b0100; // start PTE access
// IO-Address selected : external access starts if not already BUSY
8'b10_10_1xx_x : new_state = 4'b0001;
// DRAM Access : Cache Miss at READ
8'b10_0x_100_x : new_state = 4'b1010; // can start directly
default : new_state = 4'b0;
endcase
assign IO_ACC = new_state[0]; // to load the Register for Data and Addr
assign dram_go = new_state[1];
assign IC_PREQ = new_state[2]; // MMU to DCACHE !
assign do_ca_rd = new_state[3];
assign HIT_ALL = MMU_HIT & CA_HIT; // for Update "Last-Set" , MMU_HIT contains ZUGRIFF
always @(posedge BCLK or negedge BRESET)
if (!BRESET) card_flag <= 1'b0;
else card_flag <= (do_ca_rd & ~rd_rdy) | (card_flag & ~MDONE);
assign CUPDATE = card_flag & USE_CA & MDONE; // USE_CA = ~CI & ~LDC;
always @(posedge BCLK) rd_rdy <= card_flag & MDONE;
// The cache RAM can not provide fast enough the data after an Update. In this case a secondary dat
assign AUX_DAT = rd_rdy;
// DRAM Interface :
 
always @(posedge BCLK) if (dram_go) DRAM_ACC <= 1'b1;
else
DRAM_ACC <= DRAM_ACC & ~MDONE & BRESET;
// IO Interface :
always @(posedge BCLK)
begin
if (IO_ACC) IO_RD <= READ; else IO_RD <= IO_RD & ~IO_READY & BRESET;
end
assign io_busy = IO_RD | rd_done; // access is gone in next clock cycle, therefore blocked with "rd
always @(posedge BCLK) rd_done <= READ & IO_READY; // For READ one clock later for data to come thr
// global feedback to opcode fetch unit : you can continue
assign ACC_OK = IO_SPACE ? rd_done : (READ & MMU_HIT & rd_ende);
// PTB1 und PTB0
always @(posedge BCLK) NEW_PTB <= PTB_WR; // to MMU Update Block
always @(posedge BCLK) if (PTB_WR) PTB_ONE <= PTB_SEL;
endmodule
/trunk/rtl/ICACHE.v
0,0 → 1,421
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: ICACHE.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// ICACHE the instruction cache of M32632
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module ICACHE( BCLK, MCLK, MDONE, BRESET, READ_I, IO_READY, PSR_USER, DATA_HOLD, PTB_WR, PTB_SEL, DR
KDET, HOLD, CFG, DRAM_Q, CINVAL, IC_SIGS, IO_Q, IVAR, KOLLI_A, MCR_FLAGS, MMU_DIN, VADR, WADDR
WCTRL, IO_RD, DRAM_ACC, INIT_RUN, PROT_ERROR, ACC_OK, IC_PREQ, KOLLISION, ENA_HK, STOP_CINV,
DRAM_A, IC_DQ, IC_VA, ICTODC, IO_A, ENDRAM );
 
input BCLK;
input MCLK;
input MDONE;
input BRESET;
input READ_I;
input IO_READY;
input PSR_USER;
input DATA_HOLD;
input PTB_WR;
input PTB_SEL;
input DRAM_WR;
input KDET;
input HOLD;
input [1:0] CFG;
input [31:0] DRAM_Q;
input [1:0] CINVAL;
input [1:0] IC_SIGS;
input [31:0] IO_Q;
input [1:0] IVAR;
input [27:4] KOLLI_A;
input [3:0] MCR_FLAGS;
input [23:0] MMU_DIN;
input [31:0] VADR;
input [11:2] WADDR;
input [2:0] WCTRL;
input ENA_HK;
input ENDRAM;
 
output IO_RD;
output DRAM_ACC;
output INIT_RUN;
output PROT_ERROR;
output ACC_OK;
output IC_PREQ;
output KOLLISION;
output STOP_CINV;
output [31:0] IC_DQ;
output [31:12] IC_VA;
output [3:0] ICTODC;
output reg [27:0] DRAM_A;
output reg [31:0] IO_A;
 
reg [31:0] VADR_R;
reg [31:0] CAPDAT;
reg [31:0] DFFE_IOR;
reg HOLD_ON;
reg DFF_HDFF1;
reg DFF_IRD_REG;
 
wire [4:0] A_CV;
wire ACOK;
wire [4:0] ACV;
wire AUX_DAT;
wire CA_HIT;
wire CA_SET;
wire CUPDATE;
wire [23:0] D_CV;
wire HIT_ALL;
wire INIT_CA_RUN;
wire IO_ACC;
wire KILL;
wire NEW_PTB;
wire PTB_ONE;
wire [31:12] RADR;
wire READ;
wire RUN_ICRD;
wire STOP_ICRD;
wire [23:0] UPCD;
wire [23:0] UPDATE_C;
wire [31:0] UPDATE_M;
wire USE_CA;
wire USER;
wire [11:7] V_ADR;
wire WE_CV;
wire WEMV;
wire WRCRAM0;
wire WRCRAM1;
wire WRSET0;
wire WRSET1;
wire WRITE;
wire [11:7] KILLADR;
wire AUX_ALT;
wire VIRT_A;
wire CI;
wire MMU_HIT;
wire LD_DRAM_A;
wire IO_SPACE;
wire LAST_MUX;
wire VIRTUELL;
wire NEW_PTB_RUN;
wire [31:0] SET_DAT;
wire [31:0] ALT_DAT;
wire [31:0] DAT_MV;
wire [3:0] RADR_MV;
wire [3:0] WADR_MV;
wire [23:0] NEWCVAL;
wire KILL_C,KILL_K;
wire RMW;
 
// +++++++++++++++++++ Memories ++++++++++++++++++++
 
reg [31:0] DATA0 [0:1023]; // Data Set 0 : 4 kBytes
reg [31:0] SET_DAT0;
 
reg [31:0] DATA1 [0:1023]; // Data Set 1 : 4 kBytes
reg [31:0] SET_DAT1;
 
reg [15:0] TAGSET_0 [0:255]; // Tag Set for Data Set 0 : 256 entries of 16 bits
reg [15:0] TAG0;
 
reg [15:0] TAGSET_1 [0:255]; // Tag Set for Data Set 1 : 256 entries of 16 bits
reg [15:0] TAG1;
 
reg [23:0] CA_VALID [0:31]; // Valid bits for Data Set 0 and 1 : 32 entries of 24 bits
reg [23:0] CVALID;
 
reg [35:0] MMU_TAGS [0:255]; // Tag Set for MMU : 256 entries of 36 bits
reg [35:0] MMU_Q;
 
reg [31:0] MMU_VALID [0:15]; // Valid bits for MMU Tag Set : 16 entries of 32 bits
reg [31:0] MVALID;
 
reg [15:0] KTAGSET_0 [0:255]; // Kollision Tag Set for Data Set 0 : 256 entries of 16 bits
reg [15:0] KTAG0;
 
reg [15:0] KTAGSET_1 [0:255]; // Kollision Tag Set for Data Set 1 : 256 entries of 16 bits
reg [15:0] KTAG1;
 
reg [23:0] KCA_VALID [0:31]; // Kollision Valid bits for Data Set 0 and 1 : 32 entries of 24 bits
reg [23:0] KCVALID;
 
assign READ = READ_I & ~HOLD_ON & RUN_ICRD;
assign WRITE = 1'b0;
assign RMW = 1'b0;
 
assign ALT_DAT = AUX_ALT ? DFFE_IOR : CAPDAT ;
 
assign RADR = VIRT_A ? MMU_Q[19:0] : VADR_R[31:12] ;
 
assign V_ADR = STOP_ICRD ? KILLADR : VADR[11:7] ;
assign ACV = STOP_ICRD ? KILLADR : A_CV ;
assign UPCD = STOP_ICRD ? NEWCVAL : UPDATE_C ;
 
assign IC_DQ = LAST_MUX ? ALT_DAT : SET_DAT ;
 
assign SET_DAT = CA_SET ? SET_DAT1 : SET_DAT0 ;
 
assign KILL = KILL_C | KILL_K;
 
assign IC_VA = VADR_R[31:12];
 
assign VIRT_A = ~CINVAL[0] & VIRTUELL;
 
assign ACC_OK = HOLD_ON | ACOK;
 
assign USER = ~MCR_FLAGS[3] & PSR_USER;
 
assign AUX_ALT = HOLD_ON | DFF_IRD_REG;
 
assign LAST_MUX = AUX_ALT | AUX_DAT;
 
assign INIT_RUN = NEW_PTB_RUN | INIT_CA_RUN;
 
assign LD_DRAM_A = ~DRAM_ACC | MDONE;
 
assign ICTODC[3] = USER;
 
always @(posedge BCLK) VADR_R <= VADR;
 
always @(posedge BCLK) DFF_IRD_REG <= IO_RD;
 
always @(posedge BCLK) DFF_HDFF1 <= IO_READY;
 
always @(posedge BCLK) if (LD_DRAM_A) DRAM_A[27:0] <= {RADR[27:12],VADR_R[11:2],USE_CA,CA_SET};
 
always @(posedge BCLK) if (IO_ACC) IO_A <= {RADR[31:12],VADR_R[11:0]};
 
always @(posedge BCLK) if (IO_RD) DFFE_IOR <= IO_Q;
 
always @(posedge BCLK or negedge BRESET)
if (!BRESET) HOLD_ON <= 1'b0;
else HOLD_ON <= (DATA_HOLD & DFF_HDFF1) | (HOLD_ON & DATA_HOLD);
 
always @(posedge MCLK) if (WCTRL[2]) CAPDAT <= DRAM_Q;
 
// +++++++++++++++++++++++++ Cache Valid +++++++++++++++++++
 
always @(posedge BCLK) CVALID <= CA_VALID[V_ADR[11:7]];
 
always @(negedge BCLK) if (WE_CV) CA_VALID[ACV] <= D_CV;
 
// +++++++++++++++++++++++++ Tag Set 0 +++++++++++++++++++++
 
always @(posedge BCLK) TAG0 <= TAGSET_0[VADR[11:4]];
 
always @(negedge BCLK) if (WRCRAM0) TAGSET_0[VADR_R[11:4]] <= RADR[27:12];
 
// +++++++++++++++++++++++++ Tag Set 1 +++++++++++++++++++++
 
always @(posedge BCLK) TAG1 <= TAGSET_1[VADR[11:4]];
 
always @(negedge BCLK) if (WRCRAM1) TAGSET_1[VADR_R[11:4]] <= RADR[27:12];
 
// +++++++++++++++++++++++++ Data Set 0 ++++++++++++++++++++
 
always @(posedge BCLK) SET_DAT0 <= DATA0[VADR[11:2]];
always @(posedge MCLK) if (WRSET0) DATA0[WADDR] <= DRAM_Q;
// +++++++++++++++++++++++++ Data Set 1 ++++++++++++++++++++
 
always @(posedge BCLK) SET_DAT1 <= DATA1[VADR[11:2]];
always @(posedge MCLK) if (WRSET1) DATA1[WADDR] <= DRAM_Q;
 
CA_MATCH DCA_COMPARE(
.INVAL_L(CINVAL[0]),
.CI(CI),
.MMU_HIT(MMU_HIT),
.WRITE(WRITE),
.KDET(1'b0),
.ADDR({RADR[27:12],VADR_R[11:4]}),
.CFG(CFG),
.ENDRAM(ENDRAM),
.CVALID(CVALID),
.TAG0(TAG0),
.TAG1(TAG1),
.CA_HIT(CA_HIT),
.CA_SET(CA_SET),
.WB_ACC(),
.USE_CA(USE_CA),
.IOSEL(RADR[31:28]),
.IO_SPACE(IO_SPACE),
.DC_ILO(1'b0),
.KILL(KILL_C),
.UPDATE(UPDATE_C));
DCA_CONTROL DCA_CTRL(
.BCLK(BCLK),
.MCLK(1'b0),
.WRCFG(1'b1),
.BRESET(BRESET),
.CA_SET(CA_SET),
.HIT_ALL(HIT_ALL),
.UPDATE(UPCD),
.VADR_R(VADR_R[11:7]),
.DRAM_ACC(DRAM_ACC),
.CUPDATE(CUPDATE),
.KILL(KILL),
.WRITE(WRITE),
.WCTRL(WCTRL[1:0]),
.INVAL_A(CINVAL[1]),
.DAT_CV(D_CV),
.WADR_CV(A_CV),
.WE_CV(WE_CV),
.INIT_CA_RUN(INIT_CA_RUN),
.WRCRAM0(WRCRAM0),
.WRCRAM1(WRCRAM1),
.WRSET0(WRSET0),
.WRSET1(WRSET1));
 
ICACHE_SM IC_SM(
.BCLK(BCLK),
.BRESET(BRESET),
.IO_SPACE(IO_SPACE),
.READ(READ),
.MDONE(MDONE),
.IO_READY(IO_READY),
.MMU_HIT(MMU_HIT),
.CA_HIT(CA_HIT),
.USE_CA(USE_CA),
.PTB_WR(PTB_WR),
.PTB_SEL(PTB_SEL),
.USER(USER),
.PROT_ERROR(PROT_ERROR),
.PTE_ACC(IC_SIGS[1]),
.ACC_OK(ACOK),
.PTB_ONE(PTB_ONE),
.NEW_PTB(NEW_PTB),
.AUX_DAT(AUX_DAT),
.CUPDATE(CUPDATE),
.IO_RD(IO_RD),
.IO_ACC(IO_ACC),
.DRAM_ACC(DRAM_ACC),
.IC_PREQ(IC_PREQ),
.HIT_ALL(HIT_ALL));
 
// +++++++++++++++++++++++++ Kollision Valid +++++++++++++++
 
always @(posedge BCLK) KCVALID <= KCA_VALID[KOLLI_A[11:7]];
 
always @(negedge BCLK) if (WE_CV) KCA_VALID[ACV] <= D_CV;
 
// +++++++++++++++++++++++++ Kollision Tag Set 0 +++++++++++
 
always @(posedge BCLK) KTAG0 <= KTAGSET_0[KOLLI_A[11:4]];
 
always @(negedge BCLK) if (WRCRAM0) KTAGSET_0[VADR_R[11:4]] <= RADR[27:12];
 
// +++++++++++++++++++++++++ Kollision Tag Set 1 +++++++++++
 
always @(posedge BCLK) KTAG1 <= KTAGSET_1[KOLLI_A[11:4]];
 
always @(negedge BCLK) if (WRCRAM1) KTAGSET_1[VADR_R[11:4]] <= RADR[27:12];
 
KOLDETECT KOLLOGIK(
.DRAM_WR(DRAM_WR),
.BCLK(BCLK),
.READ_I(READ_I),
.ACC_OK(ACC_OK),
.BRESET(BRESET),
.INVAL_A(CINVAL[1]),
.KDET(KDET),
.HOLD(HOLD),
.ENA_HK(ENA_HK),
.STOP_CINV(STOP_CINV),
.ADDR(KOLLI_A),
.C_VALID(KCVALID),
.CFG(CFG),
.CVALID(CVALID),
.TAG0(KTAG0),
.TAG1(KTAG1),
.KOLLISION(KOLLISION),
.STOP_ICRD(STOP_ICRD),
.RUN_ICRD(RUN_ICRD),
.KILL(KILL_K),
.ICTODC(ICTODC[2:0]),
.KILLADR(KILLADR),
.NEWCVAL(NEWCVAL));
 
MMU_MATCH MMU_COMPARE(
.USER(USER),
.READ(READ),
.WRITE(WRITE),
.RMW(RMW),
.IVAR(IVAR),
.MCR_FLAGS(MCR_FLAGS[2:0]),
.MMU_VA(MMU_Q[35:20]),
.MVALID(MVALID),
.VADR_R(VADR_R[31:12]),
.MMU_HIT(MMU_HIT),
.PROT_ERROR(PROT_ERROR),
.VIRTUELL(VIRTUELL),
.CI(CI),
.SEL_PTB1(),
.UPDATE(UPDATE_M));
 
MMU_UP MMU_CTRL(
.NEW_PTB(NEW_PTB),
.IVAR(IVAR[1]),
.BRESET(BRESET),
.PTB1(PTB_ONE),
.BCLK(BCLK),
.WR_MRAM(IC_SIGS[0]),
.MVALID(MVALID),
.UPDATE(UPDATE_M),
.VADR(VADR[19:16]),
.VADR_R(VADR_R[19:16]),
.WE_MV(WEMV),
.NEW_PTB_RUN(NEW_PTB_RUN),
.DAT_MV(DAT_MV),
.RADR_MV(RADR_MV),
.WADR_MV(WADR_MV));
 
// +++++++++++++++++++++++++ MMU Valid +++++++++++++++++++++
 
always @(posedge BCLK) MVALID <= MMU_VALID[RADR_MV];
 
always @(negedge BCLK) if (WEMV) MMU_VALID[WADR_MV] <= DAT_MV;
 
// +++++++++++++++++++++++++ MMU Tags ++++++++++++++++++++++
 
always @(posedge BCLK) MMU_Q <= MMU_TAGS[VADR[19:12]];
 
always @(negedge BCLK) if (IC_SIGS[0]) MMU_TAGS[VADR_R[19:12]] <= {VADR_R[31:20],MMU_DIN[23:0]};
 
endmodule
/trunk/rtl/example_mods.v
0,0 → 1,356
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: example_mods.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// 1. ex_io_bus_ctrl Input/Output Bus controller
// 2. ex_in_reg Input Register
// 3. ex_out_reg Output Register
// 4. ex_boot_rom Boot ROM
// 5. ex_statcou Statistic Counters
// 6. ex_copro Coprocessor
// 7. ex_dram_emul DRAM Emulator
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. ex_io_bus_ctrl Input/Output Bus controller
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module ex_io_bus_ctrl( CLK, RESET_N, RST_N, IO_WR, IO_RD, IO_A, IO_BE, IO_Q, IO_READY,
W_OUT_REG, IN_DAT, BOOT_DAT, STAT_DAT, ENDRAM );
 
input CLK;
input RESET_N;
input IO_WR,IO_RD;
input [31:28] IO_A;
input [3:0] IO_BE;
 
input [31:0] BOOT_DAT;
input [7:0] IN_DAT;
input [31:0] STAT_DAT;
 
output reg [31:0] IO_Q;
output reg RST_N;
output reg ENDRAM;
output IO_READY;
output W_OUT_REG;
 
reg rd_rdy;
reg [3:0] init_cou;
 
always @(posedge CLK) rd_rdy <= IO_RD & ~rd_rdy;
assign IO_READY = IO_WR | rd_rdy;
 
always @(IO_A or BOOT_DAT or IN_DAT or STAT_DAT)
casex({IO_A})
4'b000x : IO_Q = BOOT_DAT; // Boot-ROM
4'b0010 : IO_Q = {24'd0,IN_DAT};
4'b0011 : IO_Q = STAT_DAT;
default : IO_Q = 32'hxxxxxxxx;
endcase
assign W_OUT_REG = IO_WR & (IO_A == 4'h2) & IO_BE[0];
// ++++++++++++++++++++++++++ RESET Signal ++++++++++++++++++++++++++
 
always @(posedge CLK or negedge RESET_N)
if (!RESET_N) init_cou <= 4'h0;
else init_cou <= init_cou + 4'h1;
always @(posedge CLK or negedge RESET_N)
if (!RESET_N) RST_N <= 1'b0;
else
if (init_cou == 4'hF) RST_N <= 1'b1;
// Reading from Boot ROM switches DRAM on! You must read program code - not data.
always @(posedge CLK) ENDRAM <= (ENDRAM | (IO_RD & (IO_A == 4'h1))) & RST_N;
 
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. ex_in_reg Input Register
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module ex_in_reg( CLK, IN_REG, IN_DAT);
 
parameter in_width = 7;
 
input CLK;
input [in_width:0] IN_REG;
 
output reg [in_width:0] IN_DAT;
 
reg [in_width:0] meta_reg;
 
always @(posedge CLK)
begin
meta_reg <= IN_REG;
IN_DAT <= meta_reg;
end
 
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 3. ex_out_reg Output Register
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module ex_out_reg( CLK, W_OUT_REG, DIN, OUT_REG);
 
parameter out_width = 7;
 
input CLK;
input W_OUT_REG;
input [31:0] DIN;
 
output reg [out_width:0] OUT_REG;
 
always @(posedge CLK) if (W_OUT_REG) OUT_REG <= DIN[out_width:0];
endmodule
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 4. ex_boot_rom Boot ROM
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module ex_boot_rom( CLK, ADDR, DATA);
 
input CLK;
input [9:2] ADDR;
 
output reg [31:0] DATA;
 
reg [31:0] BOOT_ROM [0:255]; // 1 kByte
 
initial
begin
$readmemh("boot_rom.txt", BOOT_ROM);
end
always @(posedge CLK) DATA <= BOOT_ROM[ADDR[9:2]];
 
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 5. ex_statcou Statistic Counters
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module ex_statcou( CLK, RST_N, STATSIGS, ADDR, DATA);
 
input CLK;
input RST_N;
input [7:0] STATSIGS;
input [2:0] ADDR;
 
output [31:0] DATA;
 
integer i;
 
reg [31:0] counter [0:7];
 
always @(posedge CLK or negedge RST_N)
for (i=0; i<=7; i=i+1)
if (!RST_N) counter[i] <= 32'd0;
else counter[i] <= counter[i] + {31'd0,STATSIGS[i]};
 
assign DATA = counter[ADDR];
 
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 6. ex_copro Coprocessor
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module ex_copro( CLK, COP_GO, COP_OP, COP_INP, COP_DONE, COP_OUTP);
 
input CLK;
input COP_GO;
input [23:0] COP_OP;
input [127:0] COP_INP;
 
output reg COP_DONE;
output reg [63:0] COP_OUTP;
 
always @(posedge CLK)
COP_OUTP <= COP_OP[8] ? {COP_INP[71:64],COP_INP[79:72],COP_INP[87:80],COP_INP[95:88],32'd0}
: {COP_INP[7:0],COP_INP[15:8],COP_INP[23:16],COP_INP[31:24],COP_INP[71:64],COP_INP[79:72],COP_I
always @(posedge CLK) COP_DONE <= COP_GO;
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 7. ex_dram_emul DRAM Emulator
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module ex_dram_emul ( MCLK, RST_N, IC_ACC, IDRAM_ADR, DC_ACC, DC_WR, DRAM_ADR, DRAM_DI,
IC_MDONE, DC_MDONE, ENWR, WAMUX, WADDR, MEM_Q, IWCTRL, DWCTRL );
 
input MCLK;
input RST_N;
input IC_ACC;
input [27:0] IDRAM_ADR;
input DC_ACC;
input DC_WR;
input [27:0] DRAM_ADR;
input [35:0] DRAM_DI;
 
output reg IC_MDONE;
output reg DC_MDONE;
output ENWR;
output reg WAMUX;
output [11:2] WADDR;
output reg [2:0] IWCTRL;
output reg [2:0] DWCTRL;
 
output reg [31:0] MEM_Q;
 
// +++++++++++++++++++ Memories ++++++++++++++++++++
 
parameter addr_msb = 13; // total memory is 16 kBytes
 
reg [31:0] EDRAM [0:2**(addr_msb-1)-1];
reg [addr_msb+34:0] FIFO [0:15];
 
reg [addr_msb+34:0] fifo_q;
reg [1:0] state;
reg [1:0] nibble,lsb;
reg [addr_msb:4] addr;
reg use_cache;
reg select;
reg [3:0] w_poi,r_poi,r_zeiger;
reg wr_next;
 
wire [7:0] din_0,din_1,din_2,din_3;
wire [addr_msb:2] raddr;
wire frei;
wire start;
wire wr_req;
wire ca_req;
wire write;
 
// +++++++++++++++++++++++++ Datapath +++++++++++++++++++
 
always @(negedge MCLK) if (DC_WR) FIFO[w_poi] <= {DRAM_ADR[addr_msb:2],DRAM_DI};
always @(posedge MCLK or negedge RST_N)
if (!RST_N) w_poi <= 4'd0;
else w_poi <= w_poi + {3'd0,DC_WR};
 
always @(posedge MCLK or negedge RST_N)
if (!RST_N) r_poi <= 4'd0;
else r_poi <= r_poi + {3'd0,write};
 
always @(negedge MCLK or negedge RST_N)
if (!RST_N) r_zeiger <= 4'd0;
else r_zeiger <= r_zeiger + {3'd0,write};
 
always @(posedge MCLK) fifo_q <= FIFO[r_zeiger];
always @(negedge MCLK) MEM_Q <= EDRAM[raddr]; // READ on falling edge
assign din_0 = fifo_q[32] ? fifo_q[7:0] : MEM_Q[7:0];
assign din_1 = fifo_q[33] ? fifo_q[15:8] : MEM_Q[15:8];
assign din_2 = fifo_q[34] ? fifo_q[23:16] : MEM_Q[23:16];
assign din_3 = fifo_q[35] ? fifo_q[31:24] : MEM_Q[31:24];
always @(posedge MCLK) if (write) EDRAM[raddr] <= {din_3,din_2,din_1,din_0}; // WRITE on rising edg
 
// +++++++++++++++++++++++++ Controllogic +++++++++++++++++++
 
assign ca_req = DC_ACC | IC_ACC; // Cache Read Request
assign wr_req = (w_poi != r_poi); // Write Request
assign write = (wr_req & ~ca_req & frei) | wr_next;
always @(posedge MCLK or negedge RST_N)
if (!RST_N) wr_next <= 1'b0;
else wr_next <= write & (w_poi != (r_poi + 4'd1));
always @(posedge MCLK or negedge RST_N)
if (!RST_N) state <= 2'd0;
else
if (frei) state <= (ca_req & ~wr_next) ? 2'b01 : 2'd0;
else state <= state + 2'b01;
assign frei = (state == 2'd0);
assign start = ca_req & frei & ~wr_next;
always @(negedge MCLK)
if (start)
begin
addr <= DC_ACC ? DRAM_ADR[addr_msb:4] : IDRAM_ADR[addr_msb:4];
use_cache <= DC_ACC ? DRAM_ADR[1] : IDRAM_ADR[1];
select <= DC_ACC;
end
always @(negedge MCLK)
if (start) nibble <= DC_ACC ? {DRAM_ADR[3],~DRAM_ADR[2]} : {IDRAM_ADR[3],~IDRAM_ADR[2]};
else
if (state == 2'b01) nibble <= {~nibble[1],1'b0};
else
if (state[1]) nibble <= {nibble[1],~nibble[0]};
 
assign raddr = write ? fifo_q[addr_msb+34:36] : (start ? (DC_ACC ? DRAM_ADR[addr_msb:2] : IDRAM_ADR
always @(negedge MCLK) lsb <= raddr[3:2];
assign ENWR = 1'b1; // always active
always @(posedge MCLK)
begin
WAMUX <= start | ~frei;
DC_MDONE <= select & (state == 2'b01);
DWCTRL[2] <= select & start;
DWCTRL[1] <= select & (start | ~frei) & use_cache;
DWCTRL[0] <= select & ~use_cache;
 
IC_MDONE <= ~select & (state == 2'b10); // must be late to cover all cases
IWCTRL[2] <= ~select & start;
IWCTRL[1] <= ~select & (start | ~frei) & use_cache;
IWCTRL[0] <= ~select & ~use_cache;
end
 
assign WADDR = {addr[11:4],lsb};
endmodule
/trunk/rtl/DP_FPU.v
0,0 → 1,1390
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: DP_FPU.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// 1. PREPDATA Prepare data for the big multiplier
// 2. BCDADDER 4 bit BCD adder
// 3. DFPU_BCD Binary coded decimal (BCD) adder and subtractor
// 4. DFPU_ADDSUB Double precision floating point adder and subtractor
// 5. DFPU_MISC Double precision floating point miscellaneous operations
// 6. DFPU_MUL Double precision floating point multiplier
// 7. DIVI_PREP Prepare data for the divider
// 8. DFPU_DIV The divider for all divide opcodes : double, single and integer
// 9. DP_LOGIK Control logic and result path for different functions
// 10. DP_FPU Top level of long operations datapath
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. PREPDATA Prepare data for the big multiplier
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module PREPDATA ( START, MEI, DFLOAT, BWD, SRC1, SRC2,
MSD_1, MSD_2, LSD_1, LSD_2, LOAD_MSD, LOAD_LSD1, LOAD_LSD2 );
 
input [1:0] START;
input MEI,DFLOAT;
input [1:0] BWD;
input [31:0] SRC1,SRC2;
output [52:32] MSD_1,MSD_2;
output [31:0] LSD_1,LSD_2;
output LOAD_MSD,LOAD_LSD1,LOAD_LSD2;
 
reg [31:0] LSD_1,LSD_2;
assign MSD_1 = MEI ? 21'h0 : {1'b1,SRC1[19:0]};
assign MSD_2 = MEI ? 21'h0 : {1'b1,SRC2[19:0]};
always @(MEI or BWD or SRC1)
casex ({MEI,BWD})
3'b100 : LSD_1 = {24'h000000,SRC1[7:0]};
3'b101 : LSD_1 = {16'h0000,SRC1[15:0]};
default : LSD_1 = SRC1;
endcase
always @(MEI or BWD or SRC2)
casex ({MEI,BWD})
3'b100 : LSD_2 = {24'h000000,SRC2[7:0]};
3'b101 : LSD_2 = {16'h0000,SRC2[15:0]};
default : LSD_2 = SRC2;
endcase
 
assign LOAD_MSD = (START[0] & MEI) | (START[0] & DFLOAT); // 1. step data load at DFLOAT
assign LOAD_LSD1 = (START[0] & MEI) | (START[1] & DFLOAT); // 2. step execute at DFLOAT
assign LOAD_LSD2 = (START[1] & MEI) | (START[1] & DFLOAT); // 2. step execute at DFLOAT
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. BCDADDER 4 bit BCD adder
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module BCDADDER ( A_IN, B_IN, CY_IN, SUBP, OUT, CY_OUT );
 
input [3:0] A_IN,B_IN;
input CY_IN;
input SUBP;
output [3:0] OUT;
output CY_OUT;
wire [4:0] result;
wire over;
assign result = SUBP ? ({1'b0,A_IN} - {1'b0,B_IN} - {4'b0,CY_IN})
: ({1'b0,A_IN} + {1'b0,B_IN} + {4'b0,CY_IN});
 
assign over = result[4] | (result[3] & (result[2] | result[1]));
// if result<0 : -6 if result>9 : -10
assign OUT = result[3:0] - (SUBP ? {1'b0,result[4],result[4],1'b0} : {over,1'b0,over,1'b0});
assign CY_OUT = SUBP ? result[4] : over;
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 3. DFPU_BCD Binary coded decimal (BCD) adder and subtractor
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DFPU_BCD ( BCLK, BRESET, START, DO_BCD, BWD, SRC1, SRC2, CY_IN, SUBP, BCD_Q, CY_OUT, BCD_DONE
 
// Byte : 3 cycles in shortest case REG-REG, Word : 4 cycles and Double : 6 cycles
input BCLK;
input BRESET;
input START; // START[1]
input DO_BCD; // BCD Opcode is valid
input [1:0] BWD;
input [31:0] SRC1,SRC2; // Source , Destination, data is stable during operation
input CY_IN; // comes from PSR
input SUBP; // SUBP = 1 : SUBP , 0 : ADDP
output reg [31:0] BCD_Q;
output reg CY_OUT; // went to PSR if DONE is valid
output BCD_DONE;
reg run_bcd;
reg [1:0] byte_cou;
reg [15:0] datain;
wire [7:0] result;
wire carry,carry_lsd,carry_msd;
// START : _/---\________________
// byte_cou : xxxxxx 0 x 1 x 2 x 3 x
// BCD_DONE : _____/---\____________ if BWD = Byte
always @(posedge BCLK or negedge BRESET)
if (!BRESET) run_bcd <= 1'b0;
else
run_bcd <= (START & DO_BCD) | (run_bcd & (BWD != byte_cou));
always @(posedge BCLK) byte_cou <= START ? 2'd0 : byte_cou + {1'b0,run_bcd};
always @(*)
casex ({START,byte_cou})
3'b1_xx : datain = {SRC1[7:0], SRC2[7:0]};
3'b0_00 : datain = {SRC1[15:8], SRC2[15:8]};
3'b0_01 : datain = {SRC1[23:16],SRC2[23:16]};
3'b0_1x : datain = {SRC1[31:24],SRC2[31:24]};
endcase
assign carry = START ? CY_IN : CY_OUT;
BCDADDER lsd_inst ( .A_IN(datain[3:0]), .B_IN(datain[11:8]), .CY_IN(carry), .SUBP(SUBP),
.OUT(result[3:0]), .CY_OUT(carry_lsd) );
BCDADDER msd_inst ( .A_IN(datain[7:4]), .B_IN(datain[15:12]), .CY_IN(carry_lsd), .SUBP(SUBP),
.OUT(result[7:4]), .CY_OUT(carry_msd) );
always @(posedge BCLK) CY_OUT <= carry_msd;
always @(posedge BCLK) if (START) BCD_Q[7:0] <= result;
always @(posedge BCLK) if (byte_cou == 2'd0) BCD_Q[15:8] <= result;
always @(posedge BCLK) if (byte_cou == 2'd1) BCD_Q[23:16] <= result;
always @(posedge BCLK) if (byte_cou[1]) BCD_Q[31:24] <= result;
assign BCD_DONE = run_bcd & (BWD == byte_cou);
 
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 4. DFPU_ADDSUB Double precision floating point adder and subtractor
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DFPU_ADDSUB ( BCLK, START, SRC1, SRC2, MAN1, MAN2, SRCFLAGS, BWD, SELECT, OUT, IOUT, CMPRES )
 
input BCLK;
input [1:0] START;
input [31:0] SRC1,SRC2; // The input data
input [20:0] MAN1,MAN2;
input [5:0] SRCFLAGS; // NAN, ZERO and SIGN of operands
input [1:0] BWD; // size of integer
input [3:0] SELECT; // upper 2 bits : R.T.F. code
output [69:0] OUT;
output [31:0] IOUT; // result of ROUNDLi/TRUNCLi/FLOORLi = R.T.F.
output [1:0] CMPRES;
 
reg [69:0] outreg;
reg [31:0] IOUT;
 
// MOViL : 2 cycles
// ROUNDLi : 3 cycles (+TRUNC & FLOOR)
// ADD/SUB : 4 cycles
// CMP : 2 cycles
// ++++++++++++++++++++++++++++++++++
// MOViL : 1. Pipeline stage : needs 3 cycles
reg [31:8] movdat;
reg [31:0] movif;
reg sign_movif;
 
always @(BWD or SRC1)
casex({BWD,SRC1[15],SRC1[7]})
4'b00x0 : movdat = 24'h0000_00; // Byte
4'b00x1 : movdat = 24'hFFFF_FF;
4'b010x : movdat = {16'h0000,SRC1[15:8]}; // Word
4'b011x : movdat = {16'hFFFF,SRC1[15:8]};
default : movdat = SRC1[31:8]; // Double
endcase
// This pipeline stage for better timing
always @(posedge BCLK) movif <= movdat[31] ? (32'h0 - {movdat,SRC1[7:0]}) : {movdat,SRC1[7:0]}; //
always @(posedge BCLK) sign_movif <= movdat[31];
// ROUNDLi/TRUNCLi/FLOORLi : 1. pipeline stage : can Opcode-Decoder deliver direct the 64 bit opera
reg ovflag,ovflag2;
reg rovfl;
reg minint;
wire [11:0] rexdiff,rexo;
wire ganzklein; // Flag for 0
assign rexdiff = 12'h41D - {1'b0,SRC1[30:20]}; // 4..0 is the right shift value : like Single FP sa
// ovflag2 at the end of rounding : Check for Overflow
always @(posedge BCLK) rovfl <= (ovflag | ovflag2) & (SELECT[1:0] == 2'b11) & ~minint;
// a large positiv difference is a very small number :
assign ganzklein = (~rexdiff[11] & (rexdiff[10:5] != 6'b0)); // 0 is implicit via SRC1[30:20]=0
// Detection of Overflow
assign rexo = ({1'b0,SRC1[30:20]} - {11'h1FF,~BWD[1]}); // subtract B/W = 3FF , D = 3FE
always @(BWD or rexo) // 0 ist in implicitly
casex (BWD)
2'b00 : ovflag = (~rexo[11] & (rexo[10:3] != 8'h0)); // Exponent 0..7 because -128.4 => -128
2'b01 : ovflag = (~rexo[11] & (rexo[10:4] != 7'h0)); // Exponent 0..15 look above
default : ovflag = (~rexo[11] & (rexo[10:5] != 6'h0)); // but Exponent only 0..30
endcase
always @(posedge BCLK)
if (START[1]) minint <= (SRC1 == 32'hC1E0_0000) & (SRC2 == 32'h0) & BWD[1]; // detection of -2^31
// ++++++++++++++++++++++++++++++++++++
// ADD/SUB : 1. Pipeline Stage : which operand ist bigger ? Exchange if neccessary
// SUB/CMP : SRC2 - SRC1
reg ex_null,ma_null,ex_msb,ma_msb;
reg [10:0] expo1,expo2;
wire [11:0] exdiff,exdiff12;
wire [20:0] madiff;
wire switch,nan,sign,sign1,sign2;
reg [5:0] shift1,shift2;
 
// Pipeline register :
reg [63:0] muxsrc2;
reg [55:3] pipe1; // Nummbers for right shifter
reg [5:0] shift;
reg vorz,addflag;
 
wire [52:0] muxsrc1;
wire [32:0] lowdiff;
assign nan = (SELECT[1:0] == 2'b11) ? SRCFLAGS[1] : (~SELECT[1] & (SRCFLAGS[3] | SRCFLAGS[1])); //
assign exdiff = {1'b0,SRC2[30:20]} - {1'b0,SRC1[30:20]}; // Difference of Exponents
assign madiff = {1'b0,SRC2[19:0]} - {1'b0,SRC1[19:0]}; // Difference of Mantissa
assign exdiff12 = {1'b0,SRC1[30:20]} - {1'b0,SRC2[30:20]}; // Diff. Exponents exchanged
always @(posedge BCLK)
if (START[0])
begin
ex_null <= (exdiff[10:0] == 11'h0);
ma_null <= (madiff[19:0] == 20'h0);
ex_msb <= exdiff[11];
ma_msb <= madiff[20];
shift1 <= (exdiff[10:6] != 5'h0) ? 6'h3F : exdiff[5:0];
shift2 <= (exdiff12[10:6] != 5'h0) ? 6'h3F : exdiff12[5:0];
expo1 <= SRC1[30:20];
expo2 <= SRC2[30:20];
end
assign lowdiff = {1'b0,SRC2} - {1'b0,SRC1}; // LSD compare
assign switch = ex_msb | (ex_null & (ma_msb | (ma_null & lowdiff[32]))); // exchange ?
 
assign muxsrc1 = switch ? {MAN2,SRC2} : {MAN1,SRC1};
 
always @(posedge BCLK) // Pipeline Reg
begin
muxsrc2 <= switch ? {expo1,MAN1,SRC1} : {expo2,MAN2,SRC2}; // Incl. Exponent & "1" of mantissa
pipe1 <= SELECT[1] ? (ganzklein ? 53'd0 : {1'b1,SRC1[19:0],SRC2}) : muxsrc1; // Feeding of R.T.F.
shift <= SELECT[1] ? {1'b0,rexdiff[4:0]} : (switch ? shift2 : shift1);
end
// SRC2 SRC1 : switch = 0 SRC2 SRC1 : switch = 1
// 5 + 3 : +(5 + 3) = 8 3 + 5 : +(5 + 3) = 8 SELECT[0] = 0
// 5 + (-3) : +(5 - 3) = 2 3 + (-5) : -(5 - 3) = -2
// (-5) + 3 : -(5 - 3) = -2 (-3) + 5 : +(5 - 3) = 2
// (-5) + (-3) : -(5 + 3) = -8 (-3) + (-5) : -(5 + 3) = -8
// 5 - 3 : +(5 - 3) = 2 3 - 5 : -(5 - 3) = -2 SELECT[0] = 1
// 5 - (-3) : +(5 + 3) = 8 3 - (-5) : +(5 + 3) = 8
// (-5) - 3 : -(5 + 3) = -8 (-3) - 5 : -(5 + 3) = -8
// (-5) - (-3) : -(5 - 3) = -2 (-3) - (-5) : +(5 - 3) = 2
assign sign1 = SRCFLAGS[4];
assign sign2 = SRCFLAGS[5];
always @(posedge BCLK) // Pipeline Reg
begin
vorz <= switch ? (SELECT[0] ^ sign1) : sign2;
addflag <= ~(SELECT[0] ^ (sign1 ^ sign2));
end
// CMPF : 1. Pipeline Stage : first result : is stored one level higer in Reg
assign CMPRES[1] = ~CMPRES[0] & (switch ? ~sign1 : sign2); // look table above
assign CMPRES[0] = (ex_null & ma_null & (sign1 == sign2) & (lowdiff == 33'h0)) | (SRCFLAGS[2] & SRC
// ++++++++++++++++++++++++++++++++++
// ADD/SUB + ROUND/TRUNC : 2. Step : Barrelshifter to the right -->
wire [55:0] brshifta,brshiftb,brshiftc,brshiftd,brshifte,brshiftf;
// 5..33322222222221111111111 is this picture still correct ? Took over from Single FP
// 5..2109876543210987654321098765432-10
// 1..VVVVVVVVVVVVVVVVVVVVVVVV0000000-00 // last 2 bit for rounding
assign brshifta = shift[5] ? {32'h0, pipe1[55:33], (pipe1[32:3] != 30'h0)} : {pipe1,3'h0};
assign brshiftb = shift[4] ? {16'h0,brshifta[55:17],(brshifta[16:0] != 17'h0)} : brshifta;
assign brshiftc = shift[3] ? { 8'h0, brshiftb[55:9], (brshiftb[8:0] != 9'h0)} : brshiftb;
assign brshiftd = shift[2] ? { 4'h0, brshiftc[55:5], (brshiftc[4:0] != 5'h0)} : brshiftc;
assign brshifte = shift[1] ? { 2'h0, brshiftd[55:3], (brshiftd[2:0] != 3'h0)} : brshiftd;
assign brshiftf = shift[0] ? { 1'b0, brshifte[55:2], (brshifte[1:0] != 2'h0)} : brshifte;
// ++++++++++++++++++++++++++++++++++
// ROUNDLi/TRUNCLi/FLOORLi : 3. Step : round to Integer
reg car_ry;
wire [1:0] inex;
wire [30:0] compl;
wire [31:0] iadder;
wire restbits;
assign restbits = (brshiftf[23:0] != 24'h0);
assign inex = {brshiftf[24],restbits}; // Inexact-Flag-Data transfered to multiplexer at the e
always @(SELECT or sign1 or brshiftf or restbits or inex or ganzklein)
casex (SELECT[3:2])
2'b00 : car_ry = sign1 ^ (((brshiftf[25:24] == 2'b11) & ~restbits) | (inex == 2'b11)); // ROUN
2'b1x : car_ry = sign1 ? (~ganzklein & (inex == 2'b00)) : 1'b0; // +numbers like TRUNCLi, -num
default : car_ry = sign1; // TRUNCLi , simple cut off
endcase
 
assign compl = sign1 ? ~brshiftf[55:25] : brshiftf[55:25];
assign iadder = {sign1,compl} + {31'h0,car_ry};
always @(posedge BCLK) IOUT <= minint ? 32'h8000_0000 : iadder;
 
always @(iadder or BWD or sign1) // special overflow detection i.e. -129 to -255 at Byte
casex (BWD) // or 127.9 -> 128 = error !
2'b00 : ovflag2 = (iadder[8] != iadder[7]); // Byte
2'b01 : ovflag2 = (iadder[16] != iadder[15]); // Word
default : ovflag2 = 1'b0;
endcase
// ++++++++++++++++++++++++++++++++++
// ADD/SUB : 3. Step : Addition or Subtraction
wire [67:0] result;
wire [55:0] blshifti;
wire [12:0] shiftl;
wire shift_32;
wire [65:0] add_q;
// The central adder : the subtraction needs 3 Guard-Bits after LSB for correct rounding
assign result = {1'b0,muxsrc2,3'b000} + (addflag ? {12'h0,brshiftf} : {12'hFFF,~brshiftf}) + {67'd0
assign blshifti = SELECT[1] ? {movif,24'h0} : result[55:0]; // Feeding of MOViL, comes from Registe
 
assign shiftl = SELECT[1] ? 13'h041E : {1'b0,result[67:56]}; // MOViL
assign shift_32 = (blshifti[55:24] == 32'h0);
// In case of ADD the result bypasses the barrelshifter : LSB of exponent has changed
assign add_q = (muxsrc2[53] != result[56]) ? {result[67:3],(result[2:0] != 3'b000)}
: {result[67:56],result[54:2],(result[1:0] != 2'b00)} ;
// ++++++++++++++++++++++++++++++++++
// ADD/SUB : 4. Step : Barrelshifter left for SUB and MOViF :
wire shift_16,shift_8,shift_4,shift_2,shift_1,zero;
wire [1:0] lsb_bl;
wire [55:0] blshifta,blshiftb,blshiftc,blshiftd,blshifte,blshiftf;
wire [12:0] expol;
assign blshifta = shift_32 ? {blshifti[23:0],32'h0} : blshifti;
assign shift_16 = (blshifta[55:40] == 16'h0);
assign blshiftb = shift_16 ? {blshifta[39:0],16'h0} : blshifta;
assign shift_8 = (blshiftb[55:48] == 8'h00);
assign blshiftc = shift_8 ? {blshiftb[47:0],8'h0} : blshiftb;
assign shift_4 = (blshiftc[55:52] == 4'h0);
assign blshiftd = shift_4 ? {blshiftc[51:0],4'h0} : blshiftc;
assign shift_2 = (blshiftd[55:54] == 2'b00);
assign blshifte = shift_2 ? {blshiftd[53:0],2'b0} : blshiftd;
assign shift_1 = ~blshifte[55];
assign blshiftf = shift_1 ? {blshifte[54:0],1'b0} : blshifte;
// Overflow at ROUNDLi/TRUNCLi/FLOORLi is shown in overflow of exponent , SELECT[1] is then 1
assign expol = shiftl - {7'h00,shift_32,shift_16,shift_8,shift_4,shift_2,shift_1};
// Inexact at ROUNDLi/TRUNCLi/FLOORLi : evaluation for all one level higher
assign lsb_bl = (SELECT == 2'b11) ? inex : {blshiftf[2],(blshiftf[1:0] != 2'b0)};
assign zero = (~SELECT[1] & SRCFLAGS[2] & SRCFLAGS[0])
| ((blshifti == 56'h0) & ((~addflag & ~SELECT[1]) | (SELECT[1:0] == 2'b10)));
assign sign = SELECT[1] ? sign_movif : (vorz & ~zero); // sign for MOViL
// 2. Pipeline register for ADD , SUB and MOViL
always @(posedge BCLK)
outreg <= (addflag & ~SELECT[1]) ? {nan,zero,sign,1'b0,add_q}
: {nan,zero,sign,expol,blshiftf[54:3],lsb_bl};
// ++++++++++++++++++++++++++++++++++
assign OUT = {outreg[69:67],(rovfl ? 2'b01 : outreg[66:65]),outreg[64:0]};
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 5. DFPU_MISC Double precision floating point miscellaneous operations
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DFPU_MISC ( BCLK, START, SRC1, SRC2, SRCFLAG, MIMUX, MODE, OUT );
 
input BCLK;
input START;
input [31:0] SRC1,SRC2;
input SRCFLAG;
input MIMUX;
input [3:0] MODE;
output [69:0] OUT;
reg [69:0] OUT;
reg [63:0] daten;
wire [10:0] scalb_l;
wire nan,zero,sign;
wire [12:0] lexpo,sexpo;
wire [69:0] scalb_res,logb_res,fl_lf;
always @(posedge BCLK) if (START) daten <= {(MIMUX ? {daten[31],scalb_l,daten[19:0]}: SRC1),SRC2};
assign nan = MODE[0] ? (daten[62:55] == 8'hFF) : (daten[62:52] == 11'h7FF);
assign zero = MODE[0] ? (daten[62:55] == 8'h00) : (daten[62:52] == 11'h000);
assign sign = daten[63] & ~zero;
assign lexpo = {5'b0,daten[62:55]} + 13'h0380; // -7F + 3FF
assign sexpo = (daten[62:52] > 11'h47E) ? 13'h0FFF
: ((daten[62:52] < 11'h381) ? 13'h0 : {2'b0,{4{daten[62]}},daten[58:52]});
 
assign fl_lf = MODE[0] ? {nan,zero,sign,lexpo,daten[54:32],31'h0} // MOVFL
: {nan,zero,sign,sexpo,daten[51:29],28'h0,daten[29:28],(daten[27:0] != 28'h0)}; // MOVLF
// +++++++++++++++++++++++++++ LOGBf +++++++++++++++++++++++++++++++++++
wire logb_null;
wire [9:0] sel_data,unbiased,shift_l8,shift_l4,shift_l2;
wire [8:0] shift_l;
wire posi_8,posi_4,posi_2,posi_1;
wire [4:0] calc_exp;
wire [6:0] logb_exp;
assign logb_null = MODE[1] ? (daten[62:55] == 8'h7F) : (daten[62:52] == 11'h3FF);
assign sel_data = MODE[1] ? {{3{~daten[62]}},daten[61:55]} : daten[61:52];
assign unbiased = daten[62] ? (sel_data + 10'h001) : ~sel_data;
 
// detection of leading "1"
assign posi_8 = (unbiased[9:2] == 8'h00);
assign shift_l8 = posi_8 ? {unbiased[1:0],8'h00} : unbiased;
assign posi_4 = (shift_l8[9:6] == 4'h0);
assign shift_l4 = posi_4 ? {shift_l8[5:0],4'h0} : shift_l8;
assign posi_2 = (shift_l4[9:8] == 2'b00);
assign shift_l2 = posi_2 ? {shift_l4[7:0],2'b0} : shift_l4;
assign posi_1 = ~shift_l2[9];
assign shift_l = posi_1 ? {shift_l2[7:0],1'b0} : shift_l2[8:0]; // top bit is hidden "1"
assign calc_exp = 5'h08 - {1'b0,posi_8,posi_4,posi_2,posi_1}; // Minimum is "F" = for exponent +/-1
// exponent is set one level higher for F and L
assign logb_exp = MODE[1] ? {{4{~calc_exp[4]}},{3{calc_exp[4]}}} : {~calc_exp[4],{6{calc_exp[4]}}};
assign logb_res = logb_null ? {70'h10_0000_0000_0000_0000} : {2'b00,~daten[62],2'b00,logb_exp,calc_
// ++++++++++++++++++++++++ SCALBf ++++++++++++++++++++++++++++++++++
wire [7:0] scalb_f;
assign scalb_f = SRCFLAG ? 8'h00 : (daten[39:32] + daten[30:23]);
assign scalb_l = SRCFLAG ? 11'h000 : (daten[42:32] + daten[30:20]);
assign scalb_res = MODE[1] ? // no rounding of Single Data
{2'b00,daten[31],5'b0,scalb_f,daten[22:0],daten[28:1],3'b000}
: {2'b00,daten[63],2'b0,daten[62:0],2'b00};
// ++++++++++++++++++++++++ Output ++++++++++++++++++++++++++++++++++++++++++++++++++++++
always @(posedge BCLK) OUT <= MODE[3] ? (MODE[2] ? logb_res : scalb_res) : fl_lf ; // LOGB/SCALB :
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 6. DFPU_MUL Double precision floating point multiplier
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DFPU_MUL ( BCLK, SRC1, SRC2, START, MRESULT, SRCFLAGS, OUT );
 
input BCLK;
input [31:0] SRC1,SRC2;
input START; // that is START[0]
input [105:0] MRESULT;
input [5:0] SRCFLAGS; // NAN and ZERO flags
output [69:0] OUT; // The result
 
reg [69:0] OUT;
reg [12:0] exponent;
wire orlow;
wire [12:0] expoh,expol;
wire [1:0] restlow,resthigh;
wire zero,nan,sign;
assign zero = SRCFLAGS[2] | SRCFLAGS[0]; // one is NULL -> NULL is the result
assign nan = SRCFLAGS[3] | SRCFLAGS[1]; // one is NAN -> error
assign sign = (SRCFLAGS[5] ^ SRCFLAGS[4]) & ~zero;
assign orlow = (MRESULT[50:0] != 51'b0);
assign restlow = {MRESULT[51],orlow};
assign resthigh = {MRESULT[52],(MRESULT[51] | orlow)};
always @(posedge BCLK) if (START) exponent <= {2'b00,SRC1[30:20]} + {2'b00,SRC2[30:20]};
assign expoh = exponent - 13'h03FE;
assign expol = exponent - 13'h03FF; // for MSB if MRESULT=0
always @(posedge BCLK)
OUT <= MRESULT[105] ? {nan,zero,sign,expoh,MRESULT[104:53],resthigh} // 52 Bit Mantissa
: {nan,zero,sign,expol,MRESULT[103:52],restlow};
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 7. DIVI_PREP Prepare data for the divider
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DIVI_PREP (SRC, BWD, NOT_DEI, EXTDATA, DOUT, MSB, NULL, MINUS);
 
input [31:0] SRC;
input [1:0] BWD;
input NOT_DEI;
input EXTDATA;
output [31:0] DOUT;
output [4:0] MSB;
output NULL;
output MINUS;
 
reg [31:0] double;
wire [15:0] test_16;
wire [7:0] test_8;
wire [3:0] test_4;
wire [1:0] test_2;
wire bit_4,bit_3,bit_2,bit_1,bit_0;
wire [1:0] modus;
assign modus = (NOT_DEI | EXTDATA) ? BWD : {(BWD[1] | BWD[0]),1'b1};
always @(modus or SRC or NOT_DEI)
casex (modus)
2'b00 : double = {{24{SRC[7] & NOT_DEI}},SRC[7:0]};
2'b01 : double = {{16{SRC[15] & NOT_DEI}},SRC[15:0]};
2'b1x : double = SRC;
endcase
assign MINUS = double[31] & NOT_DEI;
assign DOUT = ({32{MINUS}} ^ double) + {31'h0,MINUS}; // assign DOUT = MINUS ? (32'd0 - double) : d
// now find most significant set bit : FFS
assign bit_4 = (DOUT[31:16] != 16'h0);
assign test_16 = bit_4 ? DOUT[31:16] : DOUT[15:0];
assign bit_3 = (test_16[15:8] != 8'h0);
assign test_8 = bit_3 ? test_16[15:8] : test_16[7:0];
assign bit_2 = (test_8[7:4] != 4'h0);
assign test_4 = bit_2 ? test_8[7:4] : test_8[3:0];
assign bit_1 = (test_4[3:2] != 2'b0);
assign test_2 = bit_1 ? test_4[3:2] : test_4[1:0];
assign bit_0 = test_2[1];
assign NULL = (test_2 == 2'b00);
assign MSB = {bit_4,bit_3,bit_2,bit_1,bit_0};
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 8. DFPU_DIV The divider for all divide opcodes : double, single and integer
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DFPU_DIV ( BCLK, BRST, START, SRC1, SRC2, MAN1, MAN2, SRCFLAGS, FL, BWD, OPCODE, OUT, DONE, D
 
// This version needs for Double 28+1 cycles if MAN1<MAN2 otherwise 28+2.
// For Single it needs 13+1 cyckes or 13+2.
input BCLK,BRST;
input [3:0] START; // START & recognized Divider Operation
input [31:0] SRC1,SRC2; // input data
input [20:0] MAN1,MAN2;
input [5:0] SRCFLAGS; // NAN and ZERO
input FL;
input [1:0] BWD;
input [2:0] OPCODE; // for all DIVi variants
output [69:0] OUT; // the result
output reg DONE; // Pipeline-Flag
output [63:0] DIVI_OUT; // for Integer Division
output DVZ_TRAP; // Divide by Zero Trap
output [1:0] DEI_OVF; // DEI Overflow
// ++++++++++++++ for Integer Division ++++++++++++++
reg run_divi;
reg divi_pipe1,divi_pipe2,divi_pipe3,divi_pipe4;
reg neg_src1,neg_src2,nul_src2;
reg [4:0] msb_src1;
reg [5:0] msb_src2;
reg [31:0] ivalue,src2_reg,pipe_reg;
reg [4:0] divi_counter;
reg sub_case;
reg negativ;
reg [32:0] divi_result;
reg [63:0] DIVI_OUT;
reg DVZ_TRAP,dvz_pipe;
reg sel_in;
reg [62:0] din_mux;
reg dei_pipe;
reg extdata; // extended data : 2 data packets, only apply to DEI
reg [2:0] addoff;
reg next_msb2;
reg [31:0] dei_result;
reg [1:0] DEI_OVF;
wire [31:0] i_in;
wire [37:0] i_out;
wire [6:0] diff_msb;
wire [5:1] shift_r;
wire [62:0] shift_2;
wire [62:0] shift_4;
wire [62:0] shift_8;
wire [62:0] shift_16;
wire [64:0] shift_32;
wire stop_divi,neg_flag;
wire rest_null,plus_1,ist_null;
wire not_dei;
wire valdata; // Data <> 0 at DEI
// ++++++++++++++ Floating Point & calculation path ++++++++
reg [69:0] OUT;
reg [32:0] save1;
reg runflag;
reg [55:0] dreimal;
reg [56:0] divreg,divsr;
reg [31:0] divreg_ext;
reg [12:0] exponent;
wire load_src1,load_src2;
wire [56:0] sub1,sub2,sub3;
wire [32:0] src_1;
wire [20:0] man_1;
wire [12:0] expoh,expol,offset;
wire restlsb,restlow,resthigh;
wire zero,nan,sign,ende;
wire orlow_s,orlow_d;
wire short;
// +++++++++++++++++++++++++++ Integer Division, DEI +++++++++++++++++++++++++++
 
assign not_dei = OPCODE[2]; // 0 = DEI
always @(posedge BCLK) if (START[3]) extdata <= ~START[1]; // during START[0] for SRC1 not valid
always @(posedge BCLK or negedge BRST)
if (!BRST) run_divi <= 1'b0;
else
run_divi <= (START[3] & ~ist_null) | (~divi_pipe4 & run_divi); // Abort at DVZ Trap
always @(posedge BCLK) divi_pipe1 <= START[3] & ~ist_null; // no start if SRC1 = 0 : DVZ Trap
always @(posedge BCLK) dei_pipe <= divi_pipe1 & extdata;
always @(posedge BCLK) divi_pipe2 <= extdata ? dei_pipe : divi_pipe1;
always @(posedge BCLK) src2_reg <= SRC2;
always @(posedge BCLK) sel_in <= START[3] | divi_pipe1; // two times data for DEI
assign i_in = sel_in ? src2_reg : SRC1;
DIVI_PREP prep_inst ( .SRC(i_in), .BWD(BWD), .NOT_DEI(not_dei), .EXTDATA(extdata | START[0]),
.DOUT(i_out[31:0]), .MSB(i_out[36:32]), .NULL(ist_null), .MINUS(i_out[37]) );
 
always @(posedge BCLK) dvz_pipe <= START[3] & ist_null; // Pulse 1 cycle long
always @(posedge BCLK) DVZ_TRAP <= dvz_pipe; // one cycle later if DEI with extdata
always @(posedge BCLK)
if (START[3])
begin
neg_src1 <= i_out[37];
msb_src1 <= i_out[36:32];
end
always @(posedge BCLK)
if (divi_pipe1)
begin
nul_src2 <= ist_null;
neg_src2 <= i_out[37];
end
 
always @(posedge BCLK) ivalue <= i_out[31:0];
 
// The following is only for DEI :
always @(posedge BCLK) pipe_reg <= {32{extdata}} & ivalue; // Register must be 0 if not used
 
assign valdata = extdata & ~ist_null;
always @(BWD or valdata)
casex (BWD)
2'b00 : addoff = { 1'b0, 1'b0,valdata};
2'b01 : addoff = { 1'b0,valdata, 1'b0};
default : addoff = {valdata, 1'b0, 1'b0};
endcase
always @(posedge BCLK) next_msb2 <= extdata & ist_null & divi_pipe1; // Special case at DEI : MSD =
always @(posedge BCLK)
if (divi_pipe1) msb_src2 <= {addoff[2],(addoff[1:0] | i_out[36:35]),i_out[34:32]};
else
if (next_msb2) msb_src2 <= {1'b0,i_out[36:32]};
// Shifter for Source2
assign diff_msb = {1'b0,msb_src2} - {2'b0,msb_src1};
// negativ shift limited to 0 : Source2=0 calculated without special handling, result always 0
assign shift_r = diff_msb[6] ? 5'd0 : diff_msb[5:1]; // LSB does not count
always @(BWD or extdata or ivalue or pipe_reg)
casex ({BWD,extdata})
3'b0x0 : din_mux = {31'b0,ivalue}; // the normal case for all except DEI
3'b001 : din_mux = {23'b0,pipe_reg,ivalue[7:0]};
3'b011 : din_mux = {15'b0,pipe_reg,ivalue[15:0]};
default : din_mux = {pipe_reg[30:0],ivalue}; // 63 Bit wide
endcase
 
assign shift_2 = shift_r[1] ? din_mux : {din_mux[60:0], 2'b0};
assign shift_4 = shift_r[2] ? shift_2 : {shift_2[58:0], 4'b0};
assign shift_8 = shift_r[3] ? shift_4 : {shift_4[54:0], 8'b0};
assign shift_16 = shift_r[4] ? shift_8 : {shift_8[46:0],16'b0}; // Result is 63 Bit wide
// 65 Bit result because of DEI
assign shift_32 = shift_r[5] ? {1'b0,pipe_reg,ivalue} : {shift_16,2'b00}; // special case DEI : 32
always @(posedge BCLK or negedge BRST) // Flag for rounding, only if DEST <>0
if (!BRST) divi_pipe3 <= 1'b0;
else
divi_pipe3 <= divi_pipe2 | (divi_pipe3 & ~stop_divi);
always @(posedge BCLK)
if (divi_pipe2) divi_counter <= shift_r;
else divi_counter <= divi_counter - {4'b000,~stop_divi}; // should stop at 0
assign stop_divi = (divi_counter == 5'h0); // caclulation ready
always @(posedge BCLK) divi_pipe4 <= divi_pipe3 & stop_divi;
assign neg_flag = neg_src1 ^ neg_src2;
assign rest_null = (divreg[33:2] == 32'h0);
always @(posedge BCLK) sub_case <= neg_flag & ~nul_src2; // little help for MODi opcode
// Result preparation :
// DEST SRC QUO REM / DIV MOD
// +33 +13 : 2 7 / 2 7
// +33 -13 : -2 7 / -3 -6
// -33 +13 : -2 -7 / -3 6
// -33 -13 : 2 -7 / 2 -7
always @(*)
case (OPCODE[1:0])
2'b00 : divi_result = {neg_flag,divsr[31:0]}; // QUO
2'b01 : divi_result = {neg_src2,divreg[33:2]}; // REM
2'b10 : divi_result = {neg_src1,((sub_case & ~rest_null) ? (save1[31:0] - divreg[33:2]) : divreg
2'b11 : divi_result = {neg_flag,divsr[31:0]}; // DIV
endcase
always @(posedge BCLK) negativ <= divi_result[32];
assign plus_1 = (OPCODE[1:0] == 2'b11) ? (negativ & rest_null) : negativ; // Special case Rest=0 at
always @(posedge BCLK)
if (divi_pipe4) DIVI_OUT[63:32] <= not_dei ? (({32{negativ}} ^ divi_result[31:0]) + {31'd0,plus_1}
always @(posedge BCLK) if (divi_pipe4) DIVI_OUT[31:0] <= divreg[33:2];
always @(extdata or BWD or divsr or divreg)
casex ({extdata,BWD})
3'b000 : dei_result = {16'hxxxx,divsr[7:0],divreg[9:2]};
3'b001 : dei_result = {divsr[15:0],divreg[17:2]};
default : dei_result = divsr[31:0];
endcase
// +++++++++++++++++++++++++++ Calculation path for Division ++++++++++++++++++++++++++++
always @(posedge BCLK or negedge BRST)
if (!BRST) runflag <= 1'b0;
else
runflag <= START[2] | (~ende & runflag);
always @(posedge BCLK) DONE <= (ende & runflag) | divi_pipe4;
assign man_1 = (FL | run_divi) ? 21'h0 : MAN1;
assign src_1 = run_divi ? {1'b0,ivalue} : ( FL ? {10'h001,SRC1[22:0]} : {SRC1,1'b0});
assign load_src1 = START[2] | divi_pipe1;
// *2 + *1
always @(posedge BCLK) if (load_src1) dreimal <= {1'b0,man_1,src_1,1'b0} + {2'b00,man_1,src_1}; //
always @(posedge BCLK) if (load_src1) save1 <= src_1;
 
assign sub1 = divreg - {3'b000, man_1,save1 };
assign sub2 = divreg - {2'b00 ,man_1,save1,1'b0};
assign sub3 = divreg - {1'b0, dreimal };
 
assign load_src2 = START[2] | divi_pipe2;
always @(posedge BCLK)
if (load_src2) divreg <= divi_pipe2 ? {23'h0,shift_32[64:32]} : ( FL ? {34'h0_0000_0001,SRC2[22:0]
else
begin
casex ({sub3[56],sub2[56],sub1[56]})
3'b0xx : divreg <= {sub3[54:0],divreg_ext[31:30]};
3'b10x : divreg <= {sub2[54:0],divreg_ext[31:30]};
3'b110 : divreg <= {sub1[54:0],divreg_ext[31:30]};
default : divreg <= {divreg[54:0],divreg_ext[31:30]};
endcase
end
always @(posedge BCLK) // Extension Register for Integer Division
if (load_src2) divreg_ext <= divi_pipe2 ? shift_32[31:0] : 32'd0;
else
divreg_ext <= {divreg_ext[29:0],2'b0};
always @(posedge BCLK)
if (load_src2) divsr <= 57'h0;
else
begin
casex ({sub3[56],sub2[56],sub1[56]})
3'b0xx : divsr <= {divsr[54:0],2'b11};
3'b10x : divsr <= {divsr[54:0],2'b10};
3'b110 : divsr <= {divsr[54:0],2'b01};
default : divsr <= {divsr[54:0],2'b00};
endcase
end
 
// Overflow Detection for DEI : serial calculation
always @(posedge BCLK)
if (load_src2) DEI_OVF[0] <= 1'b0;
else DEI_OVF[0] <= DEI_OVF[0] | (BWD[1] ? |divsr[33:32] : (BWD[0] ? |divsr[17:16] : |divsr[9:8])
always @(posedge BCLK) DEI_OVF[1] <= divi_pipe4; // Timing pulse for OVF inclusiv for DIV and QUO
assign short = (SRCFLAGS[3:0] != 4'h0) & runflag;
assign ende = ((FL ? (divsr[26] | divsr[25]) : (divsr[56] | divsr[55])) & runflag) | short;
 
assign sign = (SRCFLAGS[4] ^ SRCFLAGS[5]) & ~zero;
assign zero = SRCFLAGS[2] & ~SRCFLAGS[0]; // SRC2 = NULL -> NULL as result
assign nan = SRCFLAGS[3] | SRCFLAGS[1] | (SRCFLAGS[2] & SRCFLAGS[0]);
// one of both NAN or both 0 -> invalid Operation
 
assign orlow_d = (divreg[56:27] != 29'b0) & ~zero & ~FL; // is there Rest ? [1:0] are always 0.
assign orlow_s = (divreg[26:2] != 25'b0) & ~zero;
assign restlsb = divsr[0] | orlow_s;
assign restlow = (divsr[1:0] != 2'b00) | orlow_s | orlow_d;
assign resthigh = divsr[2] | restlow;
always @(posedge BCLK) if (START[0]) exponent <= FL ? ({5'b00,SRC2[30:23]} - {5'b00,SRC1[30:23]})
: ({2'b00,SRC2[30:20]} - {2'b00,SRC1[30:20]});
assign offset = FL ? 13'h007E : 13'h03FE;
assign expoh = exponent + {offset[12:1],1'b1}; // Double = 3FF/3FE Single = 7F/7E
assign expol = exponent + offset; // in case of normalizing
always @(posedge BCLK)
if (ende && runflag)
casex ({FL,divsr[26],divsr[56]})
3'b11x : OUT <= {nan,zero,sign,expoh[9:8],expoh[7],expoh[7],expoh[7],expoh[7:0],divsr[25:3],28'b
3'b10x : OUT <= {nan,zero,sign,expol[9:8],expol[7],expol[7],expol[7],expol[7:0],divsr[24:2],28'b
3'b0x1 : OUT <= {nan,zero,sign,expoh,divsr[55:3],resthigh};
3'b0x0 : OUT <= {nan,zero,sign,expol,divsr[54:2],restlow};
endcase
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 9. DP_LOGIK Control logic and result path for different functions
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DP_LOGIK ( BCLK, BRESET, OPCODE, SRC1, SRC2, FSR, START, MRESULT, BWD, FL, MAN1, MAN2, WR_REG
COP_DONE, COP_OP, COP_IN,
DOUT, TT_DP, DP_CMP, OVF_BCD, MEI, DFLOAT, DONE, UP_DP, CLR_LSB, WREN_L, LD_OUT_L, DVZ_TRAP, C
 
// Definition of output word OUT of sub-moduls : the hidden-bit of the mantissa is already gone
//
// N Z S Exponent Mantissa Round
// A E I Double : 13 Bit 52 Bit 2 Bit
// N R G Single : 10 Bit 23 Bit 2 Bit
// O N -mmmm.mmmm.mmmm.mmmm.mmmm.mmm-.-- -m.
// -F-F-F-E.EEEE.EEEE.EEEE-MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.RR
//
// 6 6 6 6 6666 6655 5555 5555 4444 4444 4433 3333 3333 2222 2222 2211 1111 1111 0000 0000 00
// 9 8 7 6 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 10
//
// Single FP delivers the exponent in a way, that it is identical for rounding :
//
// Exponent 61 - 54 => kept
// Bits 64 - 62 are filled with bit 61 , carry should come through
// Exponent 62 => Bit 65 , Overflow
// Exponent 63 => Bit 66 , Underflow
 
input BCLK,BRESET;
input [7:0] OPCODE;
input [31:0] SRC1,SRC2; // the input data
input [20:0] MAN1,MAN2; // the MSB of mantissa
input [8:3] FSR; // Floating Point Status Register
input [1:0] START;
input [105:0] MRESULT; // Result of multiplier
input [1:0] BWD; // Size of integer
input FL;
input WR_REG; // from DECODER
input CY_IN;
input COP_DONE; // Coprozessor Interface
input [23:0] COP_OP;
input [63:0] COP_IN;
 
output [63:0] DOUT;
output [4:0] TT_DP; // Trap-Info to FSR
output [2:0] DP_CMP; // CMPL result
output [3:0] OVF_BCD; // Integer Division Overflow + BCD Carry update
output MEI,DFLOAT;
output DONE,UP_DP;
output CLR_LSB,WREN_L,LD_OUT_L;
output DVZ_TRAP;
output reg COP_GO;
 
reg [63:0] DOUT;
reg CLR_LSB;
reg [2:0] DP_CMP;
reg [5:0] preflags;
reg [5:0] srcflags;
reg [69:0] fpout;
reg [2:0] tt;
reg [6:0] select;
reg [4:0] wctrl;
reg [2:1] sequ;
reg misc_op;
reg misc_mux;
reg car_ry;
reg wr_part2;
reg up_flag;
reg ovf_div;
wire zexp2,zman2,zexp1,zman1,znan1;
wire make_i;
wire scalbl,go_misc;
wire op_cmp;
wire [69:0] mulout,addout,divout,miscout;
wire go_divf,go_divi,divi_ops,div_done;
wire bcd_ops,man_ops;
wire [31:0] i_out;
wire [63:0] divi_out;
wire [66:2] rund,cy_val; // Indexnumber like in xxxout
wire div_zero,overflow,underflow,inexact;
wire [1:0] cmpres;
wire [63:0] fp_out,fp_res;
wire wr_part1;
wire done_i;
wire [31:0] bcd_q;
wire bcd_done;
wire bcd_carry;
wire [1:0] dei_ovf;
wire quo_div;
wire copop;
wire copwr;
// Control of datapath : together with START the Double Unit becomes activ
 
always @(OPCODE or FL)
casex (OPCODE)
8'b1001_000x : select = 7'b00_01010; // 0 1 0 : MOViL
8'b1001_010x : select = 7'b10_11000; // MOVLF
8'b1001_011x : select = 7'b01_11000; // MOVFL
8'b1001_100x : select = 7'b10_01011; // 0 1 1 : ROUNDLi
8'b1001_101x : select = 7'b10_01011; // 0 1 1 : TRUNCLi
8'b1001_111x : select = 7'b10_01011; // 0 1 1 : FLOORLi
8'b1011_0000 : select = 7'bxx_01000; // 0 0 0 : ADDL
8'b1011_0010 : select = 7'bxx_01001; // 0 0 1 : CMPL
8'b1011_0100 : select = 7'bxx_01001; // 0 0 1 : SUBL
8'b1011_1000 : select = 7'b11_01100; // 1 0 1 : DIVf , Default Float for srcflags
8'b1011_1100 : select = 7'bxx_01100; // 1 0 0 : MULL
8'b1011_0110 : select = 7'b11_11000; // SCALBf , Default Float for srcflags
8'b1011_0111 : select = {~FL,FL,5'b11000}; // LOGBf
default : select = 7'b0;
endcase
 
assign MEI = (OPCODE == 8'h79);
assign divi_ops = (OPCODE[7:2] == 6'b0111_11) | (OPCODE == 8'h7B); // QUO/REM/MOD/DIV & DEI
assign go_divf = (OPCODE == 8'hB8) & START[1]; // because of runflag in DIV Unit
assign go_divi = divi_ops & (OPCODE[2] ? START[1] : START[0]); // DEI starts with START[0]
assign bcd_ops = (OPCODE == 8'h6F) | (OPCODE == 8'h6B); // ADDP , SUBP
assign man_ops = (OPCODE == 8'hB1) | (OPCODE == 8'hB5) | (OPCODE == 8'hB9) | (OPCODE == 8'hBD); //
 
assign DFLOAT = (select[3] | copop) & ~FL; // all Double Floating Point Operations for PREPDATA
assign make_i = (select[2:0] == 3'b011) | divi_ops | bcd_ops; // ROUND/TRUNC/FLOOR for output mul
assign op_cmp = (OPCODE == 8'hB2) & ~FL;
always @(posedge BCLK) misc_op <= select[4]; // for OUT-Multiplexer
assign copop = (OPCODE == 8'hDD);
assign copwr = (COP_OP[18:17] == 2'd0) & (COP_OP[13:11] == 3'b111) & (COP_OP[7:5] == 3'b001); // Cu
// very special solution for SCALBL
assign scalbl = START[0] & ~FL & (OPCODE == 8'hB6);
assign go_misc = START[1] | scalbl;
always @(posedge BCLK) misc_mux <= scalbl; // switches at START[1] the input multiplexer
// SRCFLAGS : special handling for operands is done locally
assign zexp2 = (SRC2[30:20] == 11'd0);
assign zman2 = (SRC2[19:0] == 20'd0);
assign zexp1 = (SRC1[30:20] == 11'd0);
assign zman1 = (SRC1[19:0] == 20'd0);
assign znan1 = (SRC1[30:20] == 11'h7FF);
always @(posedge BCLK)
if (START[0])
begin
srcflags[5] <= SRC2[31];
srcflags[4] <= SRC1[31];
preflags <= {(SRC2[30:20] == 11'h7FF),zexp2,zman2,znan1,zexp1,zman1};
end
 
// case Definition : 00 : 0 , if START[i]=0 then there are always 2 long operands
// 01 : 1 Float Operand SCR1
// 10 : 1 Long Operand SRC1+SRC2
// 11 : 2 Float Operands SRC1 , SRC2
always @(posedge BCLK) // NaN
if (START[1])
casex ({START[0],select[6:5]})
3'b0xx : srcflags[3] <= preflags[5] | (preflags[4] & (~preflags[3] | SRC2[31] | ~zexp2 | ~zman
3'b111 : srcflags[3] <= (SRC2[30:23] == 8'hFF) | ((SRC2[30:23] == 8'd0) & ((SRC2[22:20] != 3'd
default : srcflags[3] <= 1'b0;
endcase
always @(posedge BCLK) // Zero : only exponent ! If denormalized => NaN !
if (START[0])
casex ({START[1],select[6:5]})
3'b0xx : srcflags[2] <= zexp2; // L:(SRC1,SRC2) = Zero , SRC1 = MSB
3'b111 : srcflags[2] <= (SRC2[30:23] == 8'd0); // F:SRC2 = Zero
default : srcflags[2] <= 1'b0;
endcase
always @(posedge BCLK) // NaN
if (START[1])
casex ({START[0],select[6:5]})
3'b0xx : srcflags[1] <= preflags[2] | (preflags[1] & (~preflags[0] | SRC1[31] | ~zexp1 | ~zman
3'b1x1 : srcflags[1] <= (SRC1[30:23] == 8'hFF) | ((SRC1[30:23] == 8'd0) & ((SRC1[22:20] != 3'd
3'b110 : srcflags[1] <= znan1 | (zexp1 & (~zman1 | SRC2[31] | ~zexp2 | ~zman2)); // L:(SRC1,SR
default : srcflags[1] <= 1'b0;
endcase
always @(posedge BCLK) // Zero : only exponent ! If denormalized => NaN !
if (START[0])
casex ({START[1],select[6:5]})
3'b0xx : srcflags[0] <= zexp1; // L:(SRC1,SRC2) = Zero , SRC1 = MSB
3'b1x1 : srcflags[0] <= (SRC1[30:23] == 8'd0); // F:SRC1 = Zero
3'b110 : srcflags[0] <= zexp1; // L:(SRC1,SRC2) = Zero , SRC1 = MSB
default : srcflags[0] <= 1'b0;
endcase
 
// The Sub-moduls :
DFPU_ADDSUB as_inst ( .BCLK(BCLK), .START(START), .SRC1(SRC1), .SRC2(SRC2),
.MAN1({~srcflags[0],MAN1[19:0]}), .MAN2({~srcflags[2],MAN2[19:0]}),
.SRCFLAGS(srcflags), .BWD(BWD), .SELECT({OPCODE[2:1],select[1:0]}),
.OUT(addout), .IOUT(i_out), .CMPRES(cmpres) );
DFPU_MUL mul_inst ( .BCLK(BCLK), .SRC1(SRC1), .SRC2(SRC2), .START(START[0]), .MRESULT(MRESULT),
.OUT(mulout), .SRCFLAGS(srcflags) );
DFPU_DIV div_inst ( .BCLK(BCLK), .BRST(BRESET), .START({go_divi,go_divf,START}), .SRC1(SRC1), .SRC2
.MAN1(MAN1), .MAN2(MAN2), .SRCFLAGS(srcflags), .FL(FL), .OUT(divout), .DONE(div_done),
.BWD(BWD), .OPCODE(OPCODE[2:0]), .DIVI_OUT(divi_out), .DVZ_TRAP(DVZ_TRAP), .DEI_OVF(dei_ovf)
 
DFPU_MISC misc_inst ( .BCLK(BCLK), .START(go_misc), .SRC1(SRC1), .SRC2(SRC2), .SRCFLAG(srcflags[2])
.MIMUX(misc_mux), .MODE({OPCODE[5],OPCODE[0],FL,OPCODE[1]}), .OUT(miscout) );
DFPU_BCD bcd_inst ( .BCLK(BCLK), .BRESET(BRESET), .START(START[1]), .DO_BCD(bcd_ops), .BWD(BWD), .S
.CY_IN(CY_IN), .SUBP(~OPCODE[2]), .BCD_Q(bcd_q), .CY_OUT(bcd_carry), .BCD_DONE(bcd_done) );
// FP - path : selection of result and rounding :
 
always @(misc_op or OPCODE or mulout or addout or divout or miscout)
casex ({misc_op,OPCODE[5],OPCODE[3:2]}) //OPCODE[5] only for Flags i.e. NAN
4'b1xxx : fpout = miscout; // for MOVLF,MOVFL,SCALB & LOGB
4'b0110 : fpout = divout;
4'b0111 : fpout = mulout;
default : fpout = addout;
endcase
always @(FSR or fpout) // Calculation of Carry according to rounding mode, fpout[67] = sign bit
casex (FSR[8:7])
2'b00 : car_ry = ((fpout[1:0] == 2'b10) & fpout[2]) | (fpout[1:0] == 2'b11); // round to nearest
2'b10 : car_ry = ~fpout[67] & (fpout[1:0] != 2'b00); // round to positiv infinity
2'b11 : car_ry = fpout[67] & (fpout[1:0] != 2'b00); // round to negativ infinity
default : car_ry = 1'b0; // round to zero
endcase
 
assign cy_val = {35'h0,(FL & car_ry),28'h0,(~FL & car_ry)};
assign rund = {fpout[66:2]} + cy_val;
// Detection of Div-by-0, Overflow, Underflow and Inexact : Epxonent from [66:54] = 13 Bits
assign div_zero = (srcflags[3:0] == 4'h1) & (OPCODE == 8'hB8); // true FPU Divide by Zero
assign overflow = ~rund[66] & (rund[65] | (rund[64:54] == 11'h7FF));
assign underflow = (rund[66] | (rund[65:54] == 12'h0)) & ~fpout[68]; // Zero-Flag
assign inexact = (fpout[1:0] != 2'b00);
always @(fpout or op_cmp or div_zero or overflow or underflow or inexact or FSR)
casex ({fpout[69],op_cmp,div_zero,overflow,FSR[3],underflow,FSR[5],inexact}) // [69] = NAN
8'b1xxxxxxx : tt = 3'b101; // Invalid operation
8'b001xxxxx : tt = 3'b011; // Divide by Zero
8'b0001xxxx : tt = 3'b010; // Overflow
8'b000011xx : tt = 3'b001; // Underflow
8'b00000011 : tt = 3'b110; // Inexact Result
default : tt = 3'b000; // no error
endcase
assign TT_DP = man_ops ? 5'd0 : {(inexact & ~op_cmp),(underflow & ~op_cmp),tt}; // at ABSf/NEGf no
 
assign fp_res = FL ? {fpout[67],rund[61:31],rund[33:2]}
: {fpout[67],rund[64:2]}; // lower 32 bits identical
 
// Underflow special case and get ZERO
assign fp_out = (underflow | fpout[68]) ? 64'h0 : fp_res;
// 63..32 goes to memory if Word or Byte ! Also in ODD Register , 31..0 goes in EVEN Register
// DEI comes without WR_REG information
always @(make_i or copop or MEI or BWD or WR_REG or MRESULT or COP_IN or i_out or fp_out or divi_op
casex ({make_i,copop,MEI,BWD})
5'b00100 : DOUT = {MRESULT[31:8], (WR_REG ? MRESULT[15:8] : MRESULT[7:0]), MRESULT[31:0]}; // L
5'b00101 : DOUT = {MRESULT[31:16],(WR_REG ? MRESULT[31:16] : MRESULT[15:0]),MRESULT[31:0]};
5'b0011x : DOUT = MRESULT[63:0];
5'b01xxx : DOUT = COP_IN; // true alignment in Coprocessor
5'b1xxxx : DOUT = divi_ops ? divi_out : {(bcd_ops ? bcd_q : i_out),fp_out[31:0]}; // MSD is writ
default : DOUT = fp_out;
endcase
always @(posedge BCLK) DP_CMP <= {(srcflags[3] | srcflags[1]),cmpres}; // Only valid if not NaN
// Pipeline Control + Registerfile write control
always @(posedge BCLK or negedge BRESET)
if (!BRESET) sequ <= 2'b00;
else
sequ <= {(sequ[1] & ~DONE),START[1]};
always @(FL or OPCODE or copwr)
casex ({FL,OPCODE}) // WRITE Control : [2] = clr_lsb, [1] = wr_part2, [0] = wr_part1
9'bx_1001_000x : wctrl = 5'b01_111; // MOViL
9'bx_1001_010x : wctrl = 5'b00_010; // MOVLF
9'bx_1001_011x : wctrl = 5'b01_111; // MOVFL
9'bx_1001_100x : wctrl = 5'b00_010; // ROUNDLi - DONE is one cycle earlier for this opcodes
9'bx_1001_101x : wctrl = 5'b00_010; // TRUNCLi
9'bx_1001_111x : wctrl = 5'b00_010; // FLOORLi
9'bx_1011_0000 : wctrl = 5'b01_111; // ADDL
9'bx_1011_0010 : wctrl = 5'b00_000; // CMPL - via LD one cycle later in PSR
9'bx_1011_0100 : wctrl = 5'b01_111; // SUBL
9'b1_1011_1000 : wctrl = 5'b10_001; // DIVF - measured 18 cycles Reg-Reg
9'b0_1011_1000 : wctrl = 5'b10_111; // DIVL - measured 34 cycles Reg-Reg
9'bx_1011_1100 : wctrl = 5'b01_111; // MULL
9'bx_0110_1x11 : wctrl = 5'b10_001; // ADDP,SUBP
9'bx_0111_1001 : wctrl = 5'b00_111; // MEIi
9'bx_0111_1011 : wctrl = 5'b10_111; // DEIi
9'bx_0111_11xx : wctrl = 5'b10_001; // QUOi,REMi,MODi,DIVi
9'b1_1011_011x : wctrl = 5'b00_010; // SCALBF/LOGBF
9'b0_1011_011x : wctrl = 5'b01_111; // SCALBL/LOGBL
9'bx_1101_1101 : wctrl = {4'b10_00,copwr}; // execute coprocessor opcode
default : wctrl = 5'b0;
endcase
 
assign done_i = wctrl[4] ? (div_done | bcd_done | COP_DONE) : ( (wctrl[3] | ~WR_REG) ? sequ[2] : se
assign DONE = ~START[1] & done_i; // DONE is valid for all opcodes
 
assign wr_part1 = DONE & WR_REG & wctrl[0];
always @(posedge BCLK) CLR_LSB <= DONE & WR_REG & wctrl[2];
always @(posedge BCLK) wr_part2 <= DONE & WR_REG & wctrl[1];
assign WREN_L = wr_part1 | wr_part2;
assign LD_OUT_L = DONE & ~WR_REG; // meaning is "Load Out-Reg from Long-Path"
always @(posedge BCLK) up_flag <= DONE & ~wctrl[0]; // DONE one cycle later
assign UP_DP = (select[3] & (wctrl[0] ? DONE : up_flag)) | man_ops; // Update FSR Trap etc. : al
// Overflow Trap for Division : DEI, QUO, DIV
assign quo_div = (OPCODE == 8'h7C) | (OPCODE == 8'h7F);
always @(*)
casex ({OPCODE[2],BWD})
3'b100 : ovf_div = (divi_out[39] & SRC1[7] & SRC2[7] ) & quo_div;
3'b101 : ovf_div = (divi_out[47] & SRC1[15] & SRC2[15]) & quo_div;
3'b11x : ovf_div = (divi_out[63] & SRC1[31] & SRC2[31]) & quo_div;
default : ovf_div = dei_ovf[0] & (OPCODE == 8'h7B); // DEI
endcase
assign OVF_BCD = {dei_ovf[1],ovf_div,bcd_done,bcd_carry}; // to I_PFAD
always @(posedge BCLK) COP_GO <= START[1] & copop;
 
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 10. DP_FPU Top level of long operations datapath
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DP_FPU( BCLK, FL, BRESET, LD_LDQ, WR_REG, BWD, FSR, OPCODE, SRC1, SRC2, START, DONE, UP_DP, W
CLR_LSB, LD_OUT_L, DVZ_TRAP, DP_CMP, DP_OUT, DP_Q, TT_DP, CY_IN, OVF_BCD, COP_GO, COP_OP,
COP_IN, COP_DONE, COP_OUT );
 
input BCLK;
input FL;
input BRESET;
input LD_LDQ;
input WR_REG;
input [1:0] BWD;
input [8:3] FSR;
input [7:0] OPCODE;
input [31:0] SRC1;
input [31:0] SRC2;
input [1:0] START;
input CY_IN;
input COP_DONE;
input [23:0] COP_OP;
input [63:0] COP_IN;
 
output DONE;
output UP_DP;
output WREN_L;
output CLR_LSB;
output LD_OUT_L;
output DVZ_TRAP;
output [2:0] DP_CMP;
output [31:0] DP_OUT;
output [31:0] DP_Q;
output [4:0] TT_DP;
output [3:0] OVF_BCD;
output COP_GO;
output [127:0] COP_OUT;
 
reg [52:0] MDA;
reg [52:0] MDB;
reg [31:0] DP_Q;
reg [31:20] RCOPA,RCOPB;
 
wire [63:0] DOUT;
wire [105:0] MRESULT;
wire MEI;
wire DFLOAT;
wire LOAD_MSD;
wire LOAD_LSD1;
wire LOAD_LSD2;
wire [31:0] LSD_1;
wire [31:0] LSD_2;
wire [52:32] MSD_1;
wire [52:32] MSD_2;
 
 
DP_LOGIK DOUBLE_U(
.FL(FL),
.BRESET(BRESET),
.BCLK(BCLK),
.WR_REG(WR_REG),
.BWD(BWD),
.FSR(FSR),
.MAN1(MDA[52:32]),
.MAN2(MDB[52:32]),
.MRESULT(MRESULT),
.OPCODE(OPCODE),
.SRC1(SRC1),
.SRC2(SRC2),
.START(START),
.MEI(MEI),
.DFLOAT(DFLOAT),
.DONE(DONE),
.UP_DP(UP_DP),
.CLR_LSB(CLR_LSB),
.WREN_L(WREN_L),
.LD_OUT_L(LD_OUT_L),
.DVZ_TRAP(DVZ_TRAP),
.DOUT(DOUT),
.DP_CMP(DP_CMP),
.TT_DP(TT_DP),
.CY_IN(CY_IN),
.OVF_BCD(OVF_BCD),
.COP_DONE(COP_DONE),
.COP_OP(COP_OP),
.COP_IN(COP_IN),
.COP_GO(COP_GO));
 
PREPDATA DP_PREP(
.MEI(MEI),
.DFLOAT(DFLOAT),
.BWD(BWD),
.SRC1(SRC1),
.SRC2(SRC2),
.START(START),
.LOAD_LSD1(LOAD_LSD1),
.LOAD_LSD2(LOAD_LSD2),
.LOAD_MSD(LOAD_MSD),
.LSD_1(LSD_1),
.LSD_2(LSD_2),
.MSD_1(MSD_1),
.MSD_2(MSD_2));
 
assign MRESULT = MDA * MDB; // unsigned multiplier 53 * 53 bits = 106 bits
assign DP_OUT = CLR_LSB ? DP_Q : DOUT[63:32];
always@(posedge BCLK) if (LD_OUT_L || LD_LDQ || WREN_L) DP_Q <= LD_LDQ ? SRC2 : DOUT[31:0];
 
always@(posedge BCLK) if (LOAD_LSD1) MDA[31:0] <= LSD_1;
 
always@(posedge BCLK) if (LOAD_LSD2) MDB[31:0] <= LSD_2;
 
always@(posedge BCLK)
if (LOAD_MSD)
begin
MDA[52:32] <= MSD_1;
MDB[52:32] <= MSD_2;
RCOPA <= SRC1[31:20];
RCOPB <= SRC2[31:20];
end
assign COP_OUT = {RCOPA,MDA[51:32],SRC1,RCOPB,MDB[51:32],SRC2};
 
endmodule
/trunk/rtl/TOP_MISC.v
0,0 → 1,164
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: TOP_MISC.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// 1. IO_SWITCH Switch between ICACHE and DCACHE to IO Path
// 2. MAKE_STAT Generate Statistic Signals
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. IO_SWITCH Switch between ICACHE and DCACHE to IO Path
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module IO_SWITCH ( BCLK, BRESET, I_IOA, D_IOA, I_IORD, D_IORD, D_IOWR, IO_READY, GENSTAT, D_IOBE, IL
IO_A, IO_RD, IO_WR, IO_BE, I_IORDY, D_IORDY, STATUS, ILO );
 
input BCLK,BRESET;
input [31:0] I_IOA,D_IOA;
input I_IORD;
input D_IORD,D_IOWR;
input [3:0] D_IOBE;
input IO_READY;
input [2:0] GENSTAT;
input ILO_SIG;
input [1:0] DCWACC;
output [31:0] IO_A;
output IO_RD,IO_WR;
output [3:0] IO_BE;
output I_IORDY;
output D_IORDY;
output [3:0] STATUS;
output ILO;
reg [3:0] STATUS;
reg [1:0] select;
reg ilo_flag;
wire daten;
wire sel_dp;
wire interrupt;
wire ilo_keep;
assign daten = D_IORD | D_IOWR;
 
// DCACHE has priority.
always @(posedge BCLK or negedge BRESET)
if (!BRESET) select <= 2'b0;
else
casex ({I_IORD,D_IORD,D_IOWR,IO_READY,ilo_keep,select})
7'b000xx_00 : select <= 2'b00;
7'b1000x_00 : select <= 2'b11;
7'bx100x_00 : select <= 2'b10;
7'bxx10x_00 : select <= 2'b10;
// the access has in the same cycle a READY !
7'b1001x_00 : select <= 2'b00;
7'bx101x_00 : select <= 2'b00;
7'bxx11x_00 : select <= 2'b00;
// Datea Access
7'bxxx0x_10 : select <= 2'b10;
7'bxxx11_10 : select <= 2'b10; // keep because of Interlocked
7'bxxx10_10 : select <= 2'b00;
// Instruction Access
7'bxxx0x_11 : select <= 2'b11;
7'bxxx1x_11 : select <= 2'b00;
default : select <= 2'b00;
endcase
assign sel_dp = (select == 2'b10) | ((select == 2'b00) & daten);
assign IO_RD = sel_dp ? D_IORD : I_IORD;
assign IO_WR = sel_dp ? D_IOWR : 1'b0;
assign IO_A = sel_dp ? D_IOA : I_IOA;
assign IO_BE = sel_dp ? D_IOBE : 4'b1111; // Instruction read always 32 Bit
assign D_IORDY = sel_dp & IO_READY;
assign I_IORDY = ~sel_dp & IO_READY;
 
assign interrupt = GENSTAT[1] | GENSTAT[0];
always @(*)
casex ({sel_dp,daten,interrupt,I_IORD})
4'b110x : STATUS = 4'hA; // Daten
4'b111x : STATUS = GENSTAT[1] ? 4'h4 : 4'h6; // Int Ack. : End of Int
4'b0xx1 : STATUS = 4'h8; // Programm
default : STATUS = {3'd0,GENSTAT[2]}; // WAIT or Inactive
endcase
 
// +++++++++++ ILO Control ++++++++++++++++++
always @(posedge BCLK)
if (!ILO_SIG) ilo_flag <= 1'b0; // Flag is set at read and cleared with write
else ilo_flag <= (D_IORD & sel_dp) | DCWACC[0] | ilo_keep;
assign ilo_keep = ilo_flag & ~D_IOWR & ~DCWACC[1];
assign ILO = ILO_SIG & ((D_IORD & sel_dp) | DCWACC[0] | ilo_flag | D_IOWR | DCWACC[1]);
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. MAKE_STAT Generate Statistic Signals
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module MAKE_STAT ( BCLK, READ, DACC_OK, DC_ACC, DPTE_ACC, DC_MDONE, DRAM_WR, IC_READ, IACC_OK, DATA_
IC_ACC, IPTE_ACC, IC_MDONE, KOLLISION, STATSIGS );
 
input BCLK;
input READ,DACC_OK;
input DC_ACC,DPTE_ACC,DC_MDONE;
input DRAM_WR;
input IC_READ,IACC_OK,DATA_HOLD;
input IC_ACC,IPTE_ACC,IC_MDONE;
input KOLLISION;
output reg [7:0] STATSIGS;
 
always @(posedge BCLK)
begin
STATSIGS[7] <= KOLLISION; // 7 : from ICACHE : collisions
STATSIGS[6] <= IPTE_ACC; // 6 : Instruction PTE access
STATSIGS[5] <= IC_ACC & IC_MDONE; // 5 : Instruction Memory read
STATSIGS[4] <= IC_READ & IACC_OK & ~DATA_HOLD; // 4 : Instruction read , can be IO-Port too !
STATSIGS[3] <= DRAM_WR; // 3 : Data write
STATSIGS[2] <= DPTE_ACC; // 2 : Data PTE access
STATSIGS[1] <= DC_ACC & DC_MDONE; // 1 : Data Memory read
STATSIGS[0] <= READ & DACC_OK; // 0 : Data read , can be IO-Port too !
end
endmodule
 
/trunk/rtl/ALIGNER.v
0,0 → 1,354
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: ALIGNER.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// 1. WR_ALINGER alignes write data to cache and external devices
// 2. RD_ALINGER alignes read data for the data path
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. WR_ALINGER alignes write data to cache and external devices
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module WR_ALIGNER ( PACKET, DP_Q, SIZE, WRDATA, ENBYTE );
 
input [3:0] PACKET; // [3:2] Paketnumber , [1:0] Startaddress
input [63:0] DP_Q;
input [1:0] SIZE;
output [31:0] WRDATA;
output [3:0] ENBYTE;
 
reg [3:0] ENBYTE;
reg [7:0] dbyte0,dbyte1,dbyte2,dbyte3;
wire switch;
// Data packet [ B7 ],[ B6 ],[ B5 ],[ B4 ],[ B3 ],[ B2 ],[ B1 ],[ B0 ]
// Address , i.e. 001 : one DWORD
// gives 2 packets : 1. packet [-B6-----B5-----B4-]
// 2. packet, Address + 4 [-B7-]
// Addresse , i.e. 010 : one QWORD
// gives 3 packets : 1. packet [-B1-----B0-]
// 2. packet, Address + 4 [-B5-----B4-----B3-----B2-]
// 3. packet, Address + 8 [-B7-----B6-]
 
// SIZE PACKET ADR : Outputbus
// 00 00 00 x x x B4
// 00 00 01 x x B4 x
// 00 00 10 x B4 x x
// 00 00 11 B4 x x x
 
// 01 00 00 x x B5 B4
// 01 00 01 x B5 B4 x
// 01 00 10 B5 B4 x x
// 01 00 11 B4 x x x
// 01 10 11 x x x B5
 
// 10 00 00 B7 B6 B5 B4
// 10 00 01 B6 B5 B4 x
// 10 10 01 x x x B7
// 10 00 10 B5 B4 x x
// 10 10 10 x x B7 B6
// 10 00 11 B4 x x x
// 10 10 11 x B7 B6 B5
 
// 11 00 00 B3 B2 B1 B0
// 11 10 00 B7 B6 B5 B4
// 11 00 01 B2 B1 B0 x
// 11 01 01 B6 B5 B4 B3
// 11 10 01 x x x B7
// 11 00 10 B1 B0 x x
// 11 01 10 B5 B4 B3 B2
// 11 10 10 x x B7 B6
// 11 00 11 B0 x x x
// 11 01 11 B4 B3 B2 B1
// 11 10 11 x B7 B6 B5
 
assign switch = (SIZE == 2'b11) & (PACKET[3:2] == 2'b00);
always @(DP_Q or switch or PACKET)
case (PACKET[1:0])
2'b00 : dbyte0 = switch ? DP_Q[7:0] : DP_Q[39:32];
2'b01 : dbyte0 = PACKET[3] ? DP_Q[63:56] : DP_Q[31:24];
2'b10 : dbyte0 = PACKET[3] ? DP_Q[55:48] : DP_Q[23:16];
2'b11 : dbyte0 = PACKET[3] ? DP_Q[47:40] : DP_Q[15:8];
endcase
always @(DP_Q or switch or PACKET)
case (PACKET[1:0])
2'b00 : dbyte1 = switch ? DP_Q[15:8] : DP_Q[47:40];
2'b01 : dbyte1 = switch ? DP_Q[7:0] : DP_Q[39:32];
2'b10 : dbyte1 = PACKET[3] ? DP_Q[63:56] : DP_Q[31:24];
2'b11 : dbyte1 = PACKET[3] ? DP_Q[55:48] : DP_Q[23:16];
endcase
always @(DP_Q or switch or PACKET)
case (PACKET[1:0])
2'b00 : dbyte2 = switch ? DP_Q[23:16] : DP_Q[55:48];
2'b01 : dbyte2 = switch ? DP_Q[15:8] : DP_Q[47:40];
2'b10 : dbyte2 = switch ? DP_Q[7:0] : DP_Q[39:32];
2'b11 : dbyte2 = PACKET[3] ? DP_Q[63:56] : DP_Q[31:24];
endcase
 
always @(DP_Q or switch or PACKET)
case (PACKET[1:0])
2'b00 : dbyte3 = switch ? DP_Q[31:24] : DP_Q[63:56];
2'b01 : dbyte3 = switch ? DP_Q[23:16] : DP_Q[55:48];
2'b10 : dbyte3 = switch ? DP_Q[15:8] : DP_Q[47:40];
2'b11 : dbyte3 = switch ? DP_Q[7:0] : DP_Q[39:32];
endcase
assign WRDATA = {dbyte3,dbyte2,dbyte1,dbyte0};
 
always @(SIZE or PACKET)
casex ({SIZE,PACKET})
6'b00_xx_00 : ENBYTE = 4'b0001; // BYTE
6'b00_xx_01 : ENBYTE = 4'b0010;
6'b00_xx_10 : ENBYTE = 4'b0100;
6'b00_xx_11 : ENBYTE = 4'b1000;
//
6'b01_xx_00 : ENBYTE = 4'b0011; // WORD
6'b01_xx_01 : ENBYTE = 4'b0110;
6'b01_xx_10 : ENBYTE = 4'b1100;
6'b01_0x_11 : ENBYTE = 4'b1000;
6'b01_1x_11 : ENBYTE = 4'b0001;
//
6'b11_xx_00 : ENBYTE = 4'b1111; // QWORD
6'b11_00_01 : ENBYTE = 4'b1110;
6'b11_01_01 : ENBYTE = 4'b1111;
6'b11_1x_01 : ENBYTE = 4'b0001;
6'b11_00_10 : ENBYTE = 4'b1100;
6'b11_01_10 : ENBYTE = 4'b1111;
6'b11_1x_10 : ENBYTE = 4'b0011;
6'b11_00_11 : ENBYTE = 4'b1000;
6'b11_01_11 : ENBYTE = 4'b1111;
6'b11_1x_11 : ENBYTE = 4'b0111;
//
6'b10_xx_00 : ENBYTE = 4'b1111; // DWORD
6'b10_0x_01 : ENBYTE = 4'b1110;
6'b10_1x_01 : ENBYTE = 4'b0001;
6'b10_0x_10 : ENBYTE = 4'b1100;
6'b10_1x_10 : ENBYTE = 4'b0011;
6'b10_0x_11 : ENBYTE = 4'b1000;
6'b10_1x_11 : ENBYTE = 4'b0111;
endcase
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. RD_ALINGER alignes read data for the data path
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module RD_ALIGNER ( BCLK, ACC_OK, PACKET, SIZE, REG_OUT, RDDATA, CA_HIT, DP_DI, AUX_QW );
 
input BCLK;
input ACC_OK;
input [3:0] PACKET; // [3:2] Paketnumber , [1:0] Startaddress
input [1:0] SIZE;
input REG_OUT;
input [31:0] RDDATA;
input CA_HIT;
output [31:0] DP_DI;
output reg AUX_QW;
reg [6:0] enable;
reg [7:0] dreg_0,dreg_1,dreg_2,dreg_3,dreg_4,dreg_5,dreg_6;
reg [7:0] out_0,out_1,out_2,out_3;
// RD_ALIGNER principal working : 10 is last packet , 01 is packet in between
 
// Not aligned QWORD : ADR[1:0] = 3 i.e.
// Bytes to datapath : . - . - 4 - 4
// Bytes from memory : 1 - 4 - 3 - .
// ACC_DONE : _______/----\__
// + 1 cycle ____/--
// at the end 2 cycles lost. ACC_DONE informs the Op-Dec that data is available and sent one clock c
// the LSD of QWORD access. (ACC_DONE -> REG_OUT is happening in ADDR_UNIT.)
//
// SIZE PACKET ADR : Output data ACC_OK
// 00 -- 00 x x x B0 Byte 1
// 00 -- 01 x x x B1 1
// 00 -- 10 x x x B2 1
// 00 -- 11 x x x B3 1
 
// 01 00 00 x x B1 B0 Word 1
// 01 00 01 x x B2 B1 1
// 01 00 10 x x B3 B2 1
// 01 00 11 B3 x x x -> Reg : R4 - - - 0
// 01 10 11 x x B0 R4 1
 
// 10 00 00 B3 B2 B1 B0 DWORD 1
// 10 00 01 B3 B2 B1 x -> Reg : R6 R5 R4 - 0
// 10 10 01 B0 R6 R5 R4 1
// 10 00 10 B3 B2 x x -> Reg : R5 R4 - - 0
// 10 10 10 B1 B0 R5 R4 1
// 10 00 11 B3 x x x -> Reg : R4 - - - 0
// 10 10 11 B2 B1 B0 R4 1
 
// 11 00 00 B3 B2 B1 B0 QWORD 1 MSD
// 11 01 00 B3 B2 B1 B0 not out of Reg! 0 LSD
// 11 00 01 B3 B2 B1 x -> Reg : R2 R1 R0 - 0
// 11 01 01 B3 B2 B1 B0 -> Reg : R6 R5 R4 R3 0
// 11 10 01 B0 R6 R5 R4 1 MSD
// next cycle: R3 R2 R1 R0 LSD
// 11 00 10 B3 B2 x x -> Reg : R1 R0 - - 0
// 11 01 10 B3 B2 B1 B0 -> Reg : R5 R4 R3 R2 0
// 11 10 10 B1 B0 R5 R4 1 MSD
// next cycle: R3 R2 R1 R0 LSD
// 11 00 11 B3 x x x -> Reg : R0 - - - 0
// 11 01 11 B3 B2 B1 B0 -> Reg : R4 R3 R2 R1 0
// 11 10 11 B2 B1 B0 R4 1 MSD
// next cycle: R3 R2 R1 R0 LSD
 
// IO_ACCESS QWORD :
// 11 00 00 B3 B2 B1 B0 -> Reg : R3 R2 R1 R0 0
// 11 01 00 R3 R2 R1 R0 -> Reg : R3 R2 R1 R0 1 MSD
// next cycle: R3 R2 R1 R0 LSD
 
always @(ACC_OK or SIZE or PACKET)
casex ({ACC_OK,SIZE,PACKET})
7'b1_xx_0x_00 : enable = 7'b000_1111;
7'b1_01_0x_11 : enable = 7'b001_0000;
7'b1_10_0x_01 : enable = 7'b111_0000;
7'b1_10_0x_10 : enable = 7'b011_0000;
7'b1_10_0x_11 : enable = 7'b001_0000;
7'b1_11_00_01 : enable = 7'b000_0111; // QWORD
7'b1_11_01_01 : enable = 7'b111_1000;
7'b1_11_00_10 : enable = 7'b000_0011;
7'b1_11_01_10 : enable = 7'b011_1100;
7'b1_11_00_11 : enable = 7'b000_0001;
7'b1_11_01_11 : enable = 7'b001_1110;
default : enable = 7'b000_0000;
endcase
// Register for inbetween data: simple multiplexer
 
always @(posedge BCLK)
if (enable[0])
case (PACKET[1:0])
2'b01 : dreg_0 <= RDDATA[15:8];
2'b10 : dreg_0 <= RDDATA[23:16];
2'b11 : dreg_0 <= RDDATA[31:24];
default : dreg_0 <= RDDATA[7:0];
endcase
 
always @(posedge BCLK)
if (enable[1])
case (PACKET[1:0])
2'b01 : dreg_1 <= RDDATA[23:16];
2'b10 : dreg_1 <= RDDATA[31:24];
2'b11 : dreg_1 <= RDDATA[7:0];
default : dreg_1 <= RDDATA[15:8];
endcase
 
always @(posedge BCLK)
if (enable[2])
case (PACKET[1:0])
2'b01 : dreg_2 <= RDDATA[31:24];
2'b10 : dreg_2 <= RDDATA[7:0];
2'b11 : dreg_2 <= RDDATA[15:8];
default : dreg_2 <= RDDATA[23:16];
endcase
 
always @(posedge BCLK)
if (enable[3])
case (PACKET[1:0])
2'b01 : dreg_3 <= RDDATA[7:0];
2'b10 : dreg_3 <= RDDATA[15:8];
2'b11 : dreg_3 <= RDDATA[23:16];
default : dreg_3 <= RDDATA[31:24];
endcase
 
always @(posedge BCLK)
if (enable[4])
case (PACKET[1:0])
2'b01 : dreg_4 <= RDDATA[15:8];
2'b10 : dreg_4 <= RDDATA[23:16];
2'b11 : dreg_4 <= RDDATA[31:24];
default : dreg_4 <= dreg_4;
endcase
 
always @(posedge BCLK) if (enable[5]) dreg_5 <= PACKET[1] ? RDDATA[31:24] : RDDATA[23:16];
always @(posedge BCLK) if (enable[6]) dreg_6 <= RDDATA[31:24];
 
// +++++++++++++++++++++++
always @(SIZE or PACKET or RDDATA or dreg_0 or dreg_4)
casex ({SIZE,PACKET[3],PACKET[1:0]})
5'b0x_0_01 : out_0 = RDDATA[15:8];
5'b0x_0_10 : out_0 = RDDATA[23:16];
5'b00_0_11 : out_0 = RDDATA[31:24];
5'b01_1_11 : out_0 = dreg_4;
5'b1x_1_01 : out_0 = dreg_4;
5'b1x_1_1x : out_0 = dreg_4;
default : out_0 = RDDATA[7:0];
endcase
 
always @(SIZE or PACKET or RDDATA or dreg_1 or dreg_5)
casex ({SIZE,PACKET[3],PACKET[1:0]})
5'b01_0_01 : out_1 = RDDATA[23:16];
5'b01_0_10 : out_1 = RDDATA[31:24];
5'bxx_x_11 : out_1 = RDDATA[7:0];
5'b1x_1_01 : out_1 = dreg_5;
5'b1x_1_10 : out_1 = dreg_5;
default : out_1 = RDDATA[15:8];
endcase
always @(SIZE or PACKET or RDDATA or dreg_2 or dreg_6)
case ({SIZE[1],PACKET[3],PACKET[1:0]})
4'b1_1_01 : out_2 = dreg_6;
4'b1_1_10 : out_2 = RDDATA[7:0];
4'b1_1_11 : out_2 = RDDATA[15:8];
default : out_2 = RDDATA[23:16];
endcase
always @(SIZE or PACKET or RDDATA or dreg_3)
case ({SIZE[1],PACKET[3],PACKET[1:0]})
4'b1_1_01 : out_3 = RDDATA[7:0];
4'b1_1_10 : out_3 = RDDATA[15:8];
4'b1_1_11 : out_3 = RDDATA[23:16];
default : out_3 = RDDATA[31:24];
endcase
assign DP_DI = REG_OUT ? {dreg_3,dreg_2,dreg_1,dreg_0} : {out_3,out_2,out_1,out_0};
// ++++++++++++++++ Special case QWord if cache switched off +++++++++++++++++++
always @(posedge BCLK) AUX_QW <= ACC_OK & ~CA_HIT & (SIZE == 2'b11) & PACKET[3];
endmodule
/trunk/rtl/STEUERUNG.v
0,0 → 1,220
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: STEUERUNG.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// STEUERUNG The control logic of M32632
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module STEUERUNG( BCLK, BRESET, DC_ACC_DONE, ACB_ZERO, DONE, INT_N, NMI_N, DC_ABORT, IC_INIT, DC_INI
IACC_STAT, PROT_ERROR, IC_DIN, PC_NEW, PSR, STRING, TRAPS, IC_READ, DATA_HOLD, LD_DIN, LD_IMME
WREN, WR_REG, GENSTAT, ILO, COP_OP, IC_USER, ACC_FELD, DISP, IC_TEX, IMME_Q, INFO_AU, LD_OUT,
DETOIP, MMU_UPDATE, OPER, PC_ARCHI, PC_ICACHE, RDAA, RDAB, START, WMASKE, WRADR, RWVAL, Y_INIT
ENA_HK, STOP_CINV );
 
input BCLK;
input BRESET;
input DC_ACC_DONE;
input ACB_ZERO;
input DONE;
input INT_N;
input NMI_N;
input DC_ABORT;
input IC_INIT;
input DC_INIT;
input SAVE_PC;
input Y_INIT;
input [8:0] CFG;
input [3:0] IACC_STAT;
input PROT_ERROR;
input [31:0] IC_DIN;
input [31:0] PC_NEW;
input [11:0] PSR;
input [4:0] STRING;
input [5:0] TRAPS;
input STOP_CINV;
 
output IC_READ;
output DATA_HOLD;
output LD_DIN;
output LD_IMME;
output WREN;
output WR_REG;
output [2:0] GENSTAT;
output IC_USER;
output [14:0] ACC_FELD;
output [31:0] DISP;
output [2:0] IC_TEX;
output [31:0] IMME_Q;
output [6:0] INFO_AU;
output [1:0] LD_OUT;
output [12:0] DETOIP;
output [1:0] MMU_UPDATE;
output [10:0] OPER;
output [31:0] PC_ARCHI;
output [31:0] PC_ICACHE;
output [7:0] RDAA;
output [7:0] RDAB;
output [1:0] START;
output [1:0] WMASKE;
output [5:0] WRADR;
output [2:0] RWVAL;
output ENA_HK;
output ILO;
output [23:0] COP_OP;
 
wire [55:0] OPREG;
wire IC_ABORT;
wire INIT_DONE;
wire UNDEF;
wire ILLEGAL;
wire [2:0] ANZ_VAL;
wire [31:0] PC_SAVE;
wire NEW;
wire RESTART;
wire STOP_IC;
wire [1:0] ALSB;
wire [2:0] USED;
wire NEXT_ADR;
wire NEW_PC;
wire NEXT_PCA;
wire LOAD_PC;
wire [31:0] DISP_BR;
 
DECODER BEFEHLS_DEC(
.BCLK(BCLK),
.BRESET(BRESET),
.ACC_DONE(DC_ACC_DONE),
.ACB_ZERO(ACB_ZERO),
.DONE(DONE),
.NMI_N(NMI_N),
.INT_N(INT_N),
.DC_ABORT(DC_ABORT),
.IC_ABORT(IC_ABORT),
.INIT_DONE(INIT_DONE),
.UNDEF(UNDEF),
.ILL(ILLEGAL),
.IC_READ(IC_READ),
.ANZ_VAL(ANZ_VAL),
.CFG(CFG),
.OPREG(OPREG),
.PC_SAVE(PC_SAVE),
.PSR(PSR),
.STRING(STRING),
.TRAPS(TRAPS),
.NEW(NEW),
.WREN(WREN),
.LD_DIN(LD_DIN),
.LD_IMME(LD_IMME),
.NEXT_PCA(NEXT_PCA),
.WR_REG(WR_REG),
.LOAD_PC(LOAD_PC),
.GENSTAT(GENSTAT),
.RESTART(RESTART),
.STOP_IC(STOP_IC),
.ACC_FELD(ACC_FELD),
.DISP(DISP),
.DISP_BR(DISP_BR),
.IMME_Q(IMME_Q),
.INFO_AU(INFO_AU),
.LD_OUT(LD_OUT),
.DETOIP(DETOIP),
.MMU_UPDATE(MMU_UPDATE),
.OPER(OPER),
.RDAA(RDAA),
.RDAB(RDAB),
.START(START),
.USED(USED),
.WMASKE(WMASKE),
.WRADR(WRADR),
.RWVAL(RWVAL),
.ENA_HK(ENA_HK),
.ILO(ILO),
.COP_OP(COP_OP),
.STOP_CINV(STOP_CINV) );
 
ILL_UNDEF CHECKER(
.USER(PSR[8]),
.ANZ_VAL(ANZ_VAL),
.CFG(CFG[3:1]),
.OPREG(OPREG[23:0]),
.ILL(ILLEGAL),
.UNDEF(UNDEF));
 
OPDEC_REG OPC_REG(
.BCLK(BCLK),
.BRESET(BRESET),
.NEW(NEW),
.DC_INIT(DC_INIT),
.IC_INIT(IC_INIT),
.Y_INIT(Y_INIT),
.RESTART(RESTART),
.STOP_IC(STOP_IC),
.ACC_STAT(IACC_STAT),
.PROT_ERROR(PROT_ERROR),
.ALSB(ALSB),
.IC_DIN(IC_DIN),
.USED(USED),
.IC_READ(IC_READ),
.NEXT_ADR(NEXT_ADR),
.DATA_HOLD(DATA_HOLD),
.NEW_PC(NEW_PC),
.ABORT(IC_ABORT),
.INIT_DONE(INIT_DONE),
.ANZ_VAL(ANZ_VAL),
.IC_TEX(IC_TEX),
.OPREG(OPREG));
 
PROG_COUNTER PCS(
.BCLK(BCLK),
.BRESET(BRESET),
.NEXT_ADR(NEXT_ADR),
.NEW_PC(NEW_PC),
.NEXT_PCA(NEXT_PCA),
.NEW(NEW),
.LOAD_PC(LOAD_PC),
.USER(PSR[8]),
.SAVE_PC(SAVE_PC),
.FPU_TRAP(TRAPS[0]),
.ADIVAR(INFO_AU[3]),
.DISP(DISP_BR),
.PC_NEW(PC_NEW),
.USED(USED),
.IC_USER(IC_USER),
.ALSB(ALSB),
.PC_ARCHI(PC_ARCHI),
.PC_ICACHE(PC_ICACHE),
.PC_SAVE(PC_SAVE));
 
endmodule
/trunk/rtl/I_PFAD.v
0,0 → 1,841
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: I_PFAD.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// 1. BITMASK Mask Generator , was a ROM on falling edge in early days
// 2. MULFILTER Filter for Multiplier Input Data
// 3. SIGNMUL Signed Multiplier for Integer Multiplication
// 4. SHIFTER Barrel Shifter for all Shift Opcodes
// 5. FFS_LOGIK Logic for FFS opcode
// 6. SCHALE Enclosure for Adder/Subtractor
// 7. I_PFAD The Integer Datapath
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. BITMASK Mask Generator , was a ROM on falling edge in early days
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module BITMASK (AA, DOUT);
 
// 0 : FFFFFFFF; Masktype 1 , Zero from right
// 1 : FFFFFFFE;
// 2 : FFFFFFFC;
// 3 : FFFFFFF8;
// . : ...
// 32 : 00000001; Masktype 2 , Decoder
// 33 : 00000002;
// 34 : 00000004;
// 35 : 00000008;
// .. : ...
// 64 : 00000001; Masktyte 3 , One from right
// 65 : 00000003;
// 66 : 00000007;
// 67 : 0000000F;
// .. : ...
// 96 : FFFFFFFF; Masktype 4 , like Masktype 3 but AA-1
// 97 : 00000001;
// 98 : 00000003;
// 99 : 00000007;
// .. : ...
 
input [6:0] AA;
output reg [31:0] DOUT;
reg [7:0] dec_bit;
wire [4:0] code;
wire high,low;
assign code = AA[4:0] - {4'd0,&AA[6:5]};
assign high = (AA[6:5] == 2'd0);
assign low = AA[6];
always @(code or high or low)
case (code[2:0])
3'b000 : dec_bit = {{7{high}},1'b1 };
3'b001 : dec_bit = {{6{high}},1'b1, low };
3'b010 : dec_bit = {{5{high}},1'b1,{2{low}}};
3'b011 : dec_bit = {{4{high}},1'b1,{3{low}}};
3'b100 : dec_bit = {{3{high}},1'b1,{4{low}}};
3'b101 : dec_bit = {{2{high}},1'b1,{5{low}}};
3'b110 : dec_bit = { high ,1'b1,{6{low}}};
3'b111 : dec_bit = { 1'b1,{7{low}}};
endcase
 
always @(code or high or low or dec_bit)
case (code[4:3])
2'b00 : DOUT = {{24{high}},dec_bit };
2'b01 : DOUT = {{16{high}},dec_bit,{ 8{low}}};
2'b10 : DOUT = {{ 8{high}},dec_bit,{16{low}}};
2'b11 : DOUT = { dec_bit,{24{low}}};
endcase
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. MULFILTER Filter for Multiplier Input Data
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module MULFILTER (BWD, FLOAT, SRC1, SRC2, DEST1, DEST2);
 
input [1:0] BWD;
input FLOAT;
input [31:0] SRC1,SRC2;
output [31:0] DEST1,DEST2;
 
wire sign1,sign2;
reg [31:0] DEST1,DEST2;
assign sign1 = BWD[0] ? SRC1[15] : SRC1[7];
always @(FLOAT or BWD or SRC1 or sign1)
casex ({FLOAT,BWD,sign1})
4'b0_00_0 : DEST1 = {24'h000000, SRC1[7:0]};
4'b0_00_1 : DEST1 = {24'hFFFFFF, SRC1[7:0]};
4'b0_01_0 : DEST1 = { 16'h0000,SRC1[15:0]};
4'b0_01_1 : DEST1 = { 16'hFFFF,SRC1[15:0]};
4'b1_xx_x : DEST1 = { 9'h001,SRC1[22:0]};
default : DEST1 = SRC1;
endcase
assign sign2 = BWD[0] ? SRC2[15] : SRC2[7];
always @(FLOAT or BWD or SRC2 or sign2)
casex ({FLOAT,BWD,sign2})
4'b0_00_0 : DEST2 = {24'h000000, SRC2[7:0]};
4'b0_00_1 : DEST2 = {24'hFFFFFF, SRC2[7:0]};
4'b0_01_0 : DEST2 = { 16'h0000,SRC2[15:0]};
4'b0_01_1 : DEST2 = { 16'hFFFF,SRC2[15:0]};
4'b1_xx_x : DEST2 = { 9'h001,SRC2[22:0]};
default : DEST2 = SRC2;
endcase
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 3. SIGNMUL Signed Multiplier for Integer Multiplication
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module SIGNMUL (dataa, datab, result);
 
input signed [31:0] dataa,datab;
output signed [63:0] result;
assign result = dataa * datab;
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 4. SHIFTER Barrel Shifter for all Shift Opcodes
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module SHIFTER ( MASKE,ROT,LSH,ASH,SIZE,SH_VAL,SH_DAT,SH_OUT,MASK_SEL);
 
input [31:0] MASKE;
input ROT,LSH,ASH;
input [1:0] SIZE;
input [7:0] SH_VAL;
input [31:0] SH_DAT;
output [31:0] SH_OUT;
output [4:0] MASK_SEL;
 
reg [31:0] sh_dat_in;
wire [31:0] sh_dat_0,sh_dat_1,sh_dat_2,sh_dat_3,sh_dat_4;
wire [4:0] shift;
reg msb;
wire [1:0] mask_code;
reg [31:0] SH_OUT;
reg [4:0] MASK_SEL;
// Inputstage : prepare for ROT opcode :
always @(ROT or SIZE or SH_DAT)
casex ({ROT,SIZE})
3'b100 : sh_dat_in = {SH_DAT[31:16],SH_DAT[7:0],SH_DAT[7:0]}; // Byte copy to left
3'b101 : sh_dat_in = {SH_DAT[15:0],SH_DAT[15:0]}; // Word copy to left
default : sh_dat_in = SH_DAT;
endcase
// Special case for ROT and BYTE : this way less logic
assign shift = (ROT & (SIZE == 2'b00)) ? {2'b11,SH_VAL[2:0]} : SH_VAL[4:0];
// Rotation logic
assign sh_dat_0 = shift[0] ? {sh_dat_in[30:0],sh_dat_in[31]} : sh_dat_in; // Rotation of 1 bit posi
assign sh_dat_1 = shift[1] ? {sh_dat_0[29:0],sh_dat_0[31:30]} : sh_dat_0; // 2
assign sh_dat_2 = shift[2] ? {sh_dat_1[27:0],sh_dat_1[31:28]} : sh_dat_1; // 4
assign sh_dat_3 = shift[3] ? {sh_dat_2[23:0],sh_dat_2[31:24]} : sh_dat_2; // 8
assign sh_dat_4 = shift[4] ? {sh_dat_3[15:0],sh_dat_3[31:16]} : sh_dat_3; // 16
 
// Detection of negativ data
 
always @(SIZE or SH_DAT)
casex (SIZE)
2'b00 : msb = SH_DAT[7]; // Byte
2'b01 : msb = SH_DAT[15]; // Word
default : msb = SH_DAT[31]; // Double = 11
endcase
// needs mask for output data : SH_VAL[7] says negativ number and "right" shift
assign mask_code[1] = ROT | (SH_VAL[7] & ASH & msb);
assign mask_code[0] = ROT | (SH_VAL[7] & ((ASH & ~msb) | LSH));
 
always @(SH_VAL or SIZE)
casex ({SH_VAL[7],SIZE})
3'b100 : MASK_SEL = {2'b00,SH_VAL[2:0]}; // special mask for Byte at right-shift
3'b101 : MASK_SEL = {1'b0,SH_VAL[3:0]}; // special mask for Word at right-shift
default : MASK_SEL = SH_VAL[4:0];
endcase
 
always @(mask_code or sh_dat_4 or MASKE) // top bits of MASKE are "1", lower bits are "0"
casex (mask_code)
2'b00 : SH_OUT = sh_dat_4 & MASKE; // LSH and ASH with positiv shift count
2'b01 : SH_OUT = sh_dat_4 & ~MASKE; // Negativ shift count : LSH or ASH with positiv data
2'b10 : SH_OUT = sh_dat_4 | MASKE; // ASH with negativ shift count and negativ input data
default : SH_OUT = sh_dat_4; // ROT
endcase
 
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 5. FFS_LOGIK Logic for FFS opcode
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module FFS_LOGIK (SRC1, SRC2, BWD, FLAG, DOUT);
 
input [31:0] SRC1;
input [4:0] SRC2;
input [1:0] BWD;
output reg FLAG;
output [4:0] DOUT;
 
reg [6:0] maske;
reg [7:0] byte_1,byte_2;
wire [7:0] byte_0,byte_3;
wire [15:0] mdat_0;
wire [7:0] mdat_1;
wire [3:0] mdat_2;
wire [1:0] mdat_3;
wire [4:0] obits;
always @(*)
case (SRC2[2:0])
3'd0 : maske = 7'h7F;
3'd1 : maske = 7'h7E;
3'd2 : maske = 7'h7C;
3'd3 : maske = 7'h78;
3'd4 : maske = 7'h70;
3'd5 : maske = 7'h60;
3'd6 : maske = 7'h40;
3'd7 : maske = 7'h00;
endcase
assign byte_0 = (SRC2[4:3] == 2'b00) ? {SRC1[7],(SRC1[6:0] & maske)} : 8'h00;
always @(*)
casex (SRC2[4:3])
2'b00 : byte_1 = SRC1[15:8];
2'b01 : byte_1 = {SRC1[15],(SRC1[14:8] & maske)};
2'b1x : byte_1 = 8'h00;
endcase
always @(*)
casex (SRC2[4:3])
2'b0x : byte_2 = SRC1[23:16];
2'b10 : byte_2 = {SRC1[23],(SRC1[22:16] & maske)};
2'b11 : byte_2 = 8'h00;
endcase
assign byte_3 = (SRC2[4:3] == 2'b11) ? {SRC1[31],(SRC1[30:24] & maske)} : SRC1[31:24];
 
assign obits[4] = ({byte_1,byte_0} == 16'h0);
assign mdat_0 = obits[4] ? {byte_3,byte_2} : {byte_1,byte_0}; // 16 Bit
 
assign obits[3] = (mdat_0[7:0] == 8'h0);
assign mdat_1 = obits[3] ? mdat_0[15:8] : mdat_0[7:0];
 
assign obits[2] = (mdat_1[3:0] == 4'h0);
assign mdat_2 = obits[2] ? mdat_1[7:4] : mdat_1[3:0];
assign obits[1] = (mdat_2[1:0] == 2'b0);
assign mdat_3 = obits[1] ? mdat_2[3:2] : mdat_2[1:0];
assign obits[0] = ~mdat_3[0];
always @(BWD or obits or mdat_3)
casex ({BWD,obits[4:3]})
4'b00_x1 : FLAG = 1; // Byte Overflow => nothing found
4'b00_10 : FLAG = 1; // Byte Overflow => nothing found
4'b01_1x : FLAG = 1; // Word Overflow => nothing found
default : FLAG = (mdat_3 == 2'b00);
endcase
 
assign DOUT = FLAG ? 5'h0 : obits;
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 6. SCHALE Enclosure for Adder/Subtractor
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module SCHALE (dataa, datab, cin, add_sub, bwd, result, cout, overflow);
 
input [31:0] dataa,datab;
input cin;
input add_sub; // 1 = Addition , 0 = Subtraction
input [1:0] bwd;
output [31:0] result;
output cout,overflow;
reg [2:0] seldat;
reg overflow;
 
wire [32:0] summe;
assign summe = {1'b0,dataa} + {1'b0,(add_sub ? datab : ~datab)} + {32'd0,cin};
always @(bwd or dataa or datab or summe)
case (bwd)
2'b00 : seldat = {summe[7], dataa[7], datab[7]};
2'b01 : seldat = {summe[15],dataa[15],datab[15]};
default : seldat = {summe[31],dataa[31],datab[31]};
endcase
always @(seldat or add_sub)
case (seldat[1:0])
2'b00 : overflow = add_sub ? seldat[2] : 1'b0;
2'b01 : overflow = add_sub ? 1'b0 : seldat[2];
2'b10 : overflow = add_sub ? 1'b0 : ~seldat[2];
2'b11 : overflow = add_sub ? ~seldat[2] : 1'b0;
endcase
 
assign cout = add_sub ? summe[32] : ~summe[32];
assign result = summe[31:0];
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 7. I_PFAD The Integer Datapath
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module I_PFAD ( BCLK, BRESET, SFP_DAT, FSR, DP_OUT, SRC1, SRC2, BMASKE, ADDR, MRESULT, OPCODE, BWD,
WREN, WRADR, RDAA, DETOIP, BITSEL, OVF_BCD, DISP, RWVFLAG, DSR, I_OUT, PSR, BMCODE, OV_FLAG, ACB
 
input BCLK,BRESET;
input [31:0] SFP_DAT,FSR,DP_OUT;
input [31:0] SRC1,SRC2;
input [31:0] BMASKE;
input [31:0] ADDR;
input [63:0] MRESULT;
input [7:0] OPCODE;
input [1:0] BWD;
input FL;
input [2:0] SP_CMP;
input [2:0] DP_CMP;
input LD_OUT;
input WREN;
input [5:0] WRADR;
input [7:0] RDAA;
input [11:0] DETOIP;
input [2:0] BITSEL;
input [3:0] OVF_BCD;
input [4:0] DISP;
input RWVFLAG;
input [3:0] DSR;
output [31:0] I_OUT;
output [11:0] PSR;
output [6:0] BMCODE; // ROM Address for BITMASK
output reg OV_FLAG;
output ACB_ZERO;
output [4:0] STRING;
reg [31:0] I_OUT;
reg [31:0] pfad_7,pfad_6,pfad_8,pfad_4a;
wire [31:0] pfad_4,pfad_5,pfad_11;
reg [31:0] bwd_daten1,bwd_daten2;
wire [31:0] addsub_q;
 
// +++++++++++++ Global Output Multiplexer ++++++++++++++++++++++++++++
always @(OPCODE or pfad_4 or pfad_5 or pfad_6 or pfad_7 or pfad_8 or DP_OUT or FL or SFP_DAT or FSR
casex (OPCODE[7:3])
5'b0100_x : I_OUT = pfad_4;
5'b0101_x : I_OUT = pfad_5; // String opcodes
5'b0110_x : I_OUT = pfad_6;
5'b0111_x : I_OUT = pfad_7;
5'b1000_x : I_OUT = pfad_8;
5'b1001_0 : I_OUT = DP_OUT; // SP_FPU has higher priority ! LFSR has no output
// SFSR : ROUND,TRUNC,FLOOR Integer Data : SP or DP Block
5'b1001_1 : I_OUT = (OPCODE[2:1] == 2'b10) ? FSR : (FL ? SFP_DAT : DP_OUT);
5'b1011_x : I_OUT = pfad_11;
5'b1101_x : I_OUT = DP_OUT; // Coprocessor
default : I_OUT = 32'hxxxx_xxxx; // don't care
endcase
// ++++++++++++++ PSR Register : I P S U / N Z F V - L T C
// 11 10 9 8 7 6 5 4 3 2 1 0
reg [3:0] psr_high;
reg [7:0] psr_low,psr_new;
reg [11:0] push_psr; // true Register
reg [11:0] calc_psr; // only verilog case
reg [1:0] nl_int;
wire ld_psr_l,ld_psr_h,up_psr;
wire cmp_op,bit_op,ari_op,neg_op,ffs_op,str_op,chk_op,abs_op,rwv_op;
wire [1:0] fp_nz;
wire f_flag,z_flag;
wire [1:0] nl_flags;
wire over_flow,cy_out;
wire ffs_flag; // FLAG result of FFS
wire chk_flag; // FLAG result of CHECK
wire save_psr,pop_psr;
wire [4:0] selbits;
// Bits from DETOIP;
wire cmps_op,ph_match,until,kill_opt,inss_op,exin_cmd,extract,bit_reg,kurz_st,dw_info,acb_reg,t2p
wire bcd_op,bcd_carry;
assign cmps_op = DETOIP[11]; // for CMPS
assign ph_match = DETOIP[10]; // MATCH phase
assign until = DETOIP[9]; // UNITL Flag for String
assign kill_opt = DETOIP[8]; // optimized execution of MOVS/MOVM
assign inss_op = DETOIP[7]; // 1=INSS
assign exin_cmd = DETOIP[6]; // for EXT/INS
assign extract = DETOIP[5] & exin_cmd; // 1=EXT
assign bit_reg = DETOIP[4]; // for Bit opcodes
assign kurz_st = DETOIP[3]; // for MOVM/CMPM
assign dw_info = DETOIP[2]; // at ADJSPi is SP=SRC2 always 32 Bit
assign acb_reg = DETOIP[1]; // suppresses Carry-Set at ACB
assign t2p = DETOIP[0]; // Pulse to Load Trace-Bit to Pending-Trace-Bit
assign bcd_op = OVF_BCD[1]; // ADDPi,SUBPi - from DP_FPU
assign bcd_carry = OVF_BCD[0];
assign ld_psr_l = ((WRADR == 6'h1D) | (WRADR == 6'h10)) & WREN; // Register PSR & UPSR
assign ld_psr_h = (WRADR == 6'h1D) & (BWD != 2'b00) & WREN; // Register PSR
// LD_OUT[1] is coming out of DECODER for this purpose
assign up_psr = bcd_op | ((cmp_op | bit_op | ari_op | neg_op | ffs_op | chk_op) & LD_OUT);
assign cmp_op = (OPCODE == 8'h41) | ((OPCODE == 8'hB2) & (FL ? ~SP_CMP[2] : ~DP_CMP[2])); // CMPi o
assign bit_op = ((OPCODE[7:4] == 4'h6) & ((~OPCODE[3] & OPCODE[1]) | OPCODE[3:0] == 4'hE)) // the
| (OPCODE == 8'h4D) | str_op | rwv_op; // TBIT or CMPS or RDVAL/WRVAL
assign ari_op = (OPCODE[7:4] == 4'h4) & (OPCODE[1:0] == 2'b0) & ~dw_info; // ADDi,ADDCi,SUBi,SUBCi
assign neg_op = (OPCODE[7:4] == 4'h6) & (OPCODE[3] & (OPCODE[1:0] == 2'b0)); // ABSi,NEGi
assign ffs_op = (OPCODE == 8'h85); // FFS
assign chk_op = (OPCODE == 8'h83); // CHECK
assign str_op = (OPCODE[7:4] == 4'h5) & (OPCODE[3:2] == 2'b0) & ~kurz_st; // String-"S" opcodes : F
assign abs_op = (OPCODE == 8'h6C); // ABSi : Carry is not affected !
assign rwv_op = (OPCODE[7:4] == 4'hE) & (OPCODE[3:1] == 3'b0); // RDVAL + WRVAL
always @(bwd_daten1 or bwd_daten2 or addsub_q) // SRC1 > SRC2 ?
case ({bwd_daten2[31],bwd_daten1[31]})
2'b00 : nl_int = {addsub_q[31],addsub_q[31]}; // MSB = N , LSB = L
2'b01 : nl_int = { 1'b0 , 1'b1 };
2'b10 : nl_int = { 1'b1 , 1'b0 };
2'b11 : nl_int = {addsub_q[31],addsub_q[31]};
endcase
assign ACB_ZERO = (addsub_q == 32'h0); // is used for ACBi opcode too
assign f_flag = str_op ? 1'b0 : (rwv_op ? RWVFLAG : (bit_op ? SRC2[selbits] : (acb_reg ? PSR[5] : o
assign fp_nz = FL ? SP_CMP[1:0] : DP_CMP[1:0];
assign z_flag = OPCODE[1] ? fp_nz[0] : ACB_ZERO;
assign nl_flags = OPCODE[1] ? {fp_nz[1],1'b0} : nl_int;
always @(*) // Bits : N Z F V - L T C
casex ({cmp_op,bcd_op,bit_op,(ffs_op | chk_op)})
4'b0000 : psr_new = {PSR[7:6], f_flag,PSR[4:1],((acb_reg | abs_op) ? PSR[0] : cy_out)};
4'b0001 : psr_new = {PSR[7:6],(ffs_op ? ffs_flag : chk_flag),PSR[4:0]}; // FFS or CHECK
4'b001x : psr_new = (cmps_op & str_op) ?
{2'b01, f_flag,PSR[4:3],1'b0,PSR[1:0]} // Init CMPS
: {PSR[7:6], f_flag,PSR[4:0]}; // Bit opcode
4'b01xx : psr_new = {PSR[7:6], 1'b0, PSR[4:1],bcd_carry}; // BCD opcode
4'b1xxx : psr_new = ph_match ?
{PSR[7:6], ~(ACB_ZERO ^ until), PSR[4:0]} // Until/While Option at String-"S" opcodes
: {nl_flags[1],z_flag,PSR[5:3], nl_flags[0],PSR[1:0]}; // CMP f or i
endcase
always @(save_psr or pop_psr or OPCODE or PSR or SRC1)
casex ({save_psr,pop_psr,OPCODE[6],OPCODE[2]})
4'b10xx : calc_psr = PSR & {~OPCODE[0],11'h0ED}; // clear P S U V T and the I-Bit at Interrupt &
4'b11xx : calc_psr = SRC1[27:16];
4'b0x00 : calc_psr = PSR & ~SRC1[11:0]; // BICPSR : Opcode = h32
4'b0x01 : calc_psr = PSR | SRC1[11:0]; // BISPSR h36
default : calc_psr = SRC1[11:0]; // LPR PSR h76
endcase
 
// Special case Exception Handling : Code x'89-x'8F
assign save_psr = (OPCODE[7:3] == 5'b1000_1);
assign pop_psr = (OPCODE[2:0] == 3'b000);
 
always @(posedge BCLK or negedge BRESET) // central memory for PSR low
if (!BRESET) psr_low <= 8'h0;
else
begin
if (ld_psr_l || save_psr) psr_low <= calc_psr[7:0];
else
if (up_psr) psr_low <= psr_new; // the Status result of a normal opcode
end
always @(posedge BCLK or negedge BRESET) // central memory for PSR high
if (!BRESET) psr_high <= 4'h0;
else
begin
if (ld_psr_h || save_psr) psr_high <= calc_psr[11:8]; // only at WORD access
else // t2p : copy T-Bit into P-Bit at the beginning of opcode
if (t2p) psr_high <= {psr_high[3],psr_low[1],psr_high[1:0]};
end
// Register for storage of PSR at Entry of Exception
always @(posedge BCLK) if (save_psr) push_psr <= {PSR[11],(~OPCODE[1] & PSR[10]),PSR[9:0]}; // P-Fl
assign PSR = {psr_high,psr_low};
// ++++++++++++++ Overflow Detection ++++++++++++++++++++++++++++++++++++++
 
reg ovf_mul,ovf_ash;
wire [31:0] shdat;
always @(posedge BCLK or negedge BRESET)
if (!BRESET) OV_FLAG <= 1'b0;
else
if (OVF_BCD[3]) OV_FLAG <= OVF_BCD[2]; // DEI,QUO,DIV
else
if (LD_OUT)
case (OPCODE)
8'h78 : OV_FLAG <= ovf_mul;
8'h61 : OV_FLAG <= ovf_ash;
8'h40 : OV_FLAG <= over_flow & acb_reg; // ADD Opcode at ACB
default : OV_FLAG <= 1'b0;
endcase
always @(BWD or MRESULT)
casex (BWD)
2'b00 : ovf_mul = ~((MRESULT[15:7] == 9'd0) | (MRESULT[15:7] == 9'h1FF));
2'b01 : ovf_mul = ~((MRESULT[31:15] == 17'd0) | (MRESULT[31:15] == 17'h1FFFF));
default : ovf_mul = ~((MRESULT[63:31] == 33'd0) | (MRESULT[63:31] == 33'h1FFFFFFFF));
endcase
always @(BWD or SRC2 or shdat)
casex (BWD)
2'b00 : ovf_ash = (SRC2[7] != shdat[7]);
2'b01 : ovf_ash = (SRC2[15] != shdat[15]);
default : ovf_ash = (SRC2[31] != shdat[31]);
endcase
// ++++++++++++++ Format 4 Opcodes : Basic Integer Opcodes, MOVi is special case +++++++++++++
 
reg cy_in;
reg get_psr,rd_psr,rd_dsr;
wire add_flag;
always @(BWD or SRC1)
casex (BWD)
2'b00 : bwd_daten1 = {{24{SRC1[7]}}, SRC1[7:0]}; // Sign Extension
2'b01 : bwd_daten1 = {{16{SRC1[15]}},SRC1[15:0]};
default : bwd_daten1 = SRC1;
endcase
assign add_flag = ~OPCODE[3] & ~OPCODE[1] & ~OPCODE[0]; // Only ADDi and ADDCi otherwise subtract i
always @(PSR or OPCODE) // more effort due to ABSi und NEGi : Format 6
casex ({OPCODE[5],OPCODE[3:2]})
3'b000 : cy_in = OPCODE[0]; // ADD + CMP
3'b001 : cy_in = PSR[0]; // ADDC
3'b011 : cy_in = ~PSR[0]; // SUBC
default : cy_in = 1'b1; // SUB + ABS + NEG : BORROW must be 1 for normal Adder
endcase
SCHALE addsub_ipfad (.dataa(bwd_daten2), .datab(bwd_daten1), .cin(cy_in), .add_sub(add_flag),
.result(addsub_q), .cout(cy_out), .overflow(over_flow) );
always @(posedge BCLK) get_psr <= (RDAA == 8'h9D) | (RDAA == 8'h90) | (RDAA == 8'h93); // PSR or US
always @(posedge BCLK) rd_psr <= (RDAA[1:0] == 2'b01);
always @(posedge BCLK) rd_dsr <= (RDAA[1:0] == 2'b11);
always @(OPCODE or SRC1 or SRC2 or get_psr or rd_psr or rd_dsr or DSR or PSR or ADDR)
casex (OPCODE[3:1])
3'b001 : pfad_4a = SRC2 & ~SRC1; // BIC
3'bx10 : pfad_4a = get_psr ? {({4{rd_dsr}} & DSR),16'd0,({4{rd_psr}} & PSR[11:8]),({8{~rd_dsr}}
3'b011 : pfad_4a = SRC2 | SRC1; // OR
3'b101 : pfad_4a = SRC2 & SRC1; // AND
3'b111 : pfad_4a = SRC2 ^ SRC1; // XOR
default : pfad_4a = ADDR; // ADDR, comes from ADDR_UNIT
endcase
assign pfad_4 = (OPCODE[1:0] == 2'b00) ? addsub_q : pfad_4a; // ADD,ADDC,SUB,SUBC have extra path
// ++++++++++++++ Format 5 Opcodes : Strings MOVS , CMPS und SKPS +++++++++++++++++++++++++++++++
 
reg [11:0] spointer,dpointer;
reg [9:0] todo;
reg [9:4] todo_reg;
wire [3:0] abzug;
wire mehr,weiter,op_str,no_opt;
assign op_str = (OPCODE[7:3] == 5'b0101_0);
// This logic is for detection if an accelerated MOVS/MOVM inside a page is possible - Backward is
always @(posedge BCLK)
if (op_str)
begin
spointer <= OPCODE[2] ? SRC1[11:0] : (spointer + {8'h00,todo[3:0]}); // Source
dpointer <= OPCODE[2] ? SRC2[11:0] : (dpointer + {8'h00,todo[3:0]}); // Destination
end
assign no_opt = OPCODE[1] | ((spointer[11:3] == 9'h1FF) & (spointer[2:0] != 3'b000))
| kill_opt | ((dpointer[11:3] == 9'h1FF) & (dpointer[2:0] != 3'b000));
assign abzug = OPCODE[0] ? todo_reg[7:4] : 4'h0 ;
assign pfad_5 = SRC1 - {28'h0,abzug};
 
assign mehr = (pfad_5[31:4] != 28'h0);
always @(no_opt or BWD or mehr or pfad_5)
casex ({no_opt,BWD,mehr,pfad_5[3:0]})
8'b000_1xxxx : todo = 10'h388; // Byte
8'b000_01xxx : todo = 10'h388;
8'b000_001xx : todo = 10'h244;
8'b000_0001x : todo = 10'h122;
8'b000_00001 : todo = 10'h011;
//
8'b001_1xxxx : todo = 10'h348; // Word
8'b001_01xxx : todo = 10'h348;
8'b001_001xx : todo = 10'h348;
8'b001_0001x : todo = 10'h224;
8'b001_00001 : todo = 10'h112;
//
8'b01x_1xxxx : todo = 10'h328; // DWord
8'b01x_01xxx : todo = 10'h328;
8'b01x_001xx : todo = 10'h328;
8'b01x_0001x : todo = 10'h328;
8'b01x_00001 : todo = 10'h214;
//
8'b100_xxxxx : todo = 10'h011; // the opcodes CMPS and SKPS work on a single element
8'b101_xxxxx : todo = 10'h112;
8'b11x_xxxxx : todo = 10'h214;
default : todo = 10'hxxx;
endcase
always @(posedge BCLK) if (op_str) todo_reg <= todo[9:4]; // store for next phase 51
assign weiter = mehr | (pfad_5[3:0] != 4'h0);
assign STRING = {1'b0,ACB_ZERO,weiter,( op_str ? todo[9:8] : todo_reg[9:8] )}; // ACB_ZERO is delay
// +++++++++++++ Format 6 opcodes : ADDP + SUBP are done in DP_FPU ++++++++++++++++++++
 
wire rot,ash,lsh,eis_op;
wire [7:0] sh_count;
wire [4:0] shcode; // comes from SHIFTER
reg [4:0] disp_reg; // for EXT/INS
reg [2:0] offs_reg; // for INSS
wire exin_op,exin_op2;
wire [4:0] shval_ei;
wire [7:0] sh_exin;
assign rot = (OPCODE[3:0] == 4'h0);
assign ash = (OPCODE[3:0] == 4'h1);
assign lsh = (OPCODE[3:1] == 3'b010); // 5 is LSH , but 4 is Trap(UND) and is used for right-shift
assign eis_op = (OPCODE == 8'h73) | (OPCODE[7] & ~OPCODE[1] & inss_op); // EXTSi | INSSi at OPCODE=
assign exin_op = exin_cmd & (OPCODE[7:4] == 4'h8); // identifies EXT/INS
assign exin_op2 = (exin_cmd | inss_op) & (OPCODE[7:4] == 4'h6); // identifies LSH
 
always @(posedge BCLK) disp_reg <= DISP; // at EXT the path via ADDR is already used for DEST !!!
always @(posedge BCLK) if (OPCODE[7]) offs_reg <= SRC1[7:5]; // for INSS , OPCODE=80h
// Byte for external Bit source, Double for Register
assign selbits = (bit_reg | eis_op | exin_op) ? (exin_op ? disp_reg : SRC1[4:0]) : {2'b00,BITSEL};
assign shval_ei = inss_op ? {2'b00,offs_reg} : (bit_reg ? SRC1[4:0] : {2'b00,SRC1[2:0]});
assign sh_exin[4:0] = extract ? (5'd0 - shval_ei) : shval_ei; // EXT : right shift, INS : left shi
assign sh_exin[7:5] = (shval_ei == 5'd0) ? 3'b000 : {3{extract}}; // Special case : 0 has no negati
 
// LSH shift by 16 bit to right
assign sh_count = (OPCODE[3:0] == 4'h4) ? 8'hF0 : (exin_op2 ? sh_exin : SRC1[7:0]);
assign BMCODE = (bit_op | eis_op | exin_op) ? {(eis_op | exin_op),(bit_op | exin_op),selbits} : {2'
SHIFTER shift_inst (.MASKE(BMASKE), .ROT(rot), .ASH(ash), .LSH(lsh), .SH_DAT(SRC2), .SH_VAL(sh_cou
.MASK_SEL(shcode), .SIZE(BWD), .SH_OUT(shdat) );
always @(BWD or SRC2 or neg_op or dw_info)
casex ({neg_op,(dw_info | BWD[1]),BWD[0]}) // special case ADJSPi
3'b000 : bwd_daten2 = {{24{SRC2[7]}}, SRC2[7:0]}; // Sign Extension
3'b001 : bwd_daten2 = {{16{SRC2[15]}},SRC2[15:0]};
3'b1xx : bwd_daten2 = 32'h0; // is used for ABSi and NEGi
default : bwd_daten2 = SRC2;
endcase
always @(OPCODE or SRC2 or BMASKE or addsub_q or bwd_daten1 or SRC1 or shdat or DP_OUT)
casex (OPCODE[3:0])
4'b001x : pfad_6 = SRC2 & ~BMASKE; // CBIT & CBITI
4'b011x : pfad_6 = SRC2 | BMASKE; // SBIT & SBITI
4'b1000 : pfad_6 = addsub_q; // NEG
4'b1001 : pfad_6 = {SRC1[31:1],~SRC1[0]}; // NOT
4'b1010 : pfad_6 = SRC1; // Special case 6A : not used normal -> op_lmr !
4'b1100 : pfad_6 = bwd_daten1[31] ? addsub_q : SRC1; // ABS
4'b1101 : pfad_6 = ~SRC1; // COM
4'b1110 : pfad_6 = SRC2 ^ BMASKE; // IBIT
4'b1x11_: pfad_6 = DP_OUT; // ADDP + SUBP
default : pfad_6 = shdat; // Result of Barrelshifter
endcase
// ++++++++++++++ Format 7 : MUL +++++++++++++++++++++++
 
// This Condition-Code Decoder is written twice ... see DECODER
reg sc_bit;
wire sc_negativ,sc_zero,sc_flag,sc_larger,sc_carry_psr;
assign sc_negativ = PSR[7];
assign sc_zero = PSR[6];
assign sc_flag = PSR[5];
assign sc_larger = PSR[2];
assign sc_carry_psr = PSR[0];
always @(SRC1 or sc_zero or sc_carry_psr or sc_larger or sc_negativ or sc_flag)
case (SRC1[3:0])
4'h0 : sc_bit = sc_zero; // EQual
4'h1 : sc_bit = ~sc_zero; // Not Equal
4'h2 : sc_bit = sc_carry_psr; // Carry Set
4'h3 : sc_bit = ~sc_carry_psr; // Carry Clear
4'h4 : sc_bit = sc_larger; // Higher
4'h5 : sc_bit = ~sc_larger; // Lower or Same
4'h6 : sc_bit = sc_negativ; // Greater Than
4'h7 : sc_bit = ~sc_negativ; // Less or Equal
4'h8 : sc_bit = sc_flag; // Flag Set
4'h9 : sc_bit = ~sc_flag; // Flag Clear
4'hA : sc_bit = ~sc_larger & ~sc_zero; // LOwer
4'hB : sc_bit = sc_larger | sc_zero; // Higher or Same
4'hC : sc_bit = ~sc_negativ & ~sc_zero; // Less Than
4'hD : sc_bit = sc_negativ | sc_zero; // Greater or Equal
4'hE : sc_bit = 1'b1; // True
4'hF : sc_bit = 1'b0; // False
endcase
reg [3:0] bytes2anz;
wire [23:0] and_src1;
wire [31:0] movxz_dat;
wire [4:0] kurz_anz;
wire [31:0] ext_sh4,ext_sh2;
assign and_src1 = {{16{BWD[1]}},{8{BWD[0]}}} & SRC1[31:8]; // for MOVZ
assign movxz_dat = (OPCODE[1] ^ OPCODE[0]) ? {and_src1,SRC1[7:0]} : bwd_daten1; // MOVZ.. ?
always @(ADDR or BWD)
casex (BWD[1:0])
2'b00 : bytes2anz = ADDR[3:0];
2'b01 : bytes2anz = {1'b0,ADDR[3:1]};
2'b1x : bytes2anz = {2'b0,ADDR[3:2]};
endcase
assign kurz_anz = {1'b0,bytes2anz} + 5'h01; // count for MOVM/CMPM
assign ext_sh4 = SRC1[7] ? {4'h0,SRC2[31:4]} : SRC2; // EXTSi
assign ext_sh2 = SRC1[6] ? {2'b0,ext_sh4[31:2]} : ext_sh4;
always @(*)
casex (OPCODE[3:0])
4'b0011 : pfad_7 = (SRC1[5] ? {1'b0,ext_sh2[31:1]} : ext_sh2) & BMASKE; // EXTSi
4'b01xx : pfad_7 = movxz_dat; // MOVXBW, MOVZBW, MOVZiD, MOVXiD
4'b1000 : pfad_7 = MRESULT[31:0]; // MULi
4'b1010 : pfad_7 = {27'h0,(kurz_st ? kurz_anz : {4'h0,sc_bit})}; // SCond or start of MOVM/CMPM
default : pfad_7 = DP_OUT; // DIV etc.
endcase
// ++++++++++++++ Format 8 : multiple opcodes +++++++++++++++++++++++
reg chk_p1;
reg [31:0] ins_maske;
wire [4:0] ffs_out;
wire [15:0] low_bou,upp_bou,zeiger,chk_upp,chk_low;
wire flag_up,flag_lo;
FFS_LOGIK ffs_unit (.SRC1(SRC1), .SRC2(SRC2[4:0]), .BWD(BWD), .FLAG(ffs_flag), .DOUT(ffs_out) );
// CHECK : SRC1 are the Bounds
assign low_bou = BWD[0] ? SRC1[31:16] : {{8{SRC1[15]}},SRC1[15:8]};
assign upp_bou = BWD[0] ? SRC1[15:0] : {{8{SRC1[7]}}, SRC1[7:0]};
assign zeiger = BWD[0] ? SRC2[15:0] : {{8{SRC2[7]}}, SRC2[7:0]};
assign chk_upp = upp_bou - zeiger; // F=1 if upp_bou < zeiger
assign chk_low = zeiger - low_bou; // F=1 if zeiger < low_bou
assign flag_up = (upp_bou[15] == zeiger[15]) ? chk_upp[15] : upp_bou[15]; // See NL Definition
assign flag_lo = (low_bou[15] == zeiger[15]) ? chk_low[15] : zeiger[15];
always @(posedge BCLK) chk_p1 <= chk_op & BWD[1]; // CHECKD needs 2 cycles to execute
assign chk_flag = BWD[1] ? (chk_p1 ? (nl_int[1] | psr_low[5]) : nl_int[1]) : (flag_up | flag_lo);
always @(posedge BCLK) ins_maske <= shdat; // expensive solution in terms of LEs !
always @(*)
casex (OPCODE[3:0]) // CVTP (81) has no OPCODE !
4'b000x : pfad_8 = (extract ? SRC2 : 32'hFFFF_FFFF) & BMASKE; // EXT, the other form is for INS
4'b0010 : pfad_8 = (SRC1 & ins_maske) | (SRC2 & ~ins_maske); // INS ins_maske[] ? SRC1[] : SRC2[
4'b0011 : pfad_8 = BWD[1] ? addsub_q : {16'h0,chk_low};
4'b0101 : pfad_8 = {24'hxx_xxxx,3'b000,ffs_out};
default : pfad_8 = {4'hx,push_psr,SRC1[15:0]}; // Opcode x'87-x'8F is used at CXP and therefore
endcase
// ++++++++++++++ Format 11 : Floating-Point Datapath +++++++++++++++++++++++++++++++
 
assign pfad_11 = (OPCODE[1:0] == 2'b01) ?
{((OPCODE[3:2] == 2'b11) ? 1'b0 : (SRC1[31] ^ OPCODE[2])),SRC1[30:0]} // ABSf , NEGf + MOVf
: DP_OUT;
endmodule
/trunk/rtl/STEUER_MISC.v
0,0 → 1,957
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: STEUER_MISC.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// 1. OPDEC_REG Central Instruction Register
// 2. PROG_COUNTER Program Counters
// 3. REG_LIST Register List Evaluation
// 4. ILL_UNDEF Illegal and Undefined Opcodes Detection
// 5. GRUPPE_2 Decoder and State Machine for GRUPPE_2 Opcodes
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. OPDEC_REG Central Instruction Register
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module OPDEC_REG ( BCLK, BRESET, NEW, ACC_STAT, PROT_ERROR, ALSB, USED, IC_DIN, IC_INIT, DC_INIT, Y_
OPREG, ANZ_VAL, IC_READ, NEW_PC, NEXT_ADR, DATA_HOLD, ABORT, IC_TEX, INIT_DONE);
 
input BCLK,BRESET;
input NEW; // a program jump took place
input [3:0] ACC_STAT; // ICACHE signals data is available or Abort
input PROT_ERROR; // comes direct from ICACHE
input [1:0] ALSB; // lower addressbits of access address to ICACHE
input [2:0] USED; // Message from DECODER how many bytes were used
input [31:0] IC_DIN; // ICACHE Data
input IC_INIT,DC_INIT,Y_INIT; // Initialising or new setting is running
input RESTART; // "Break" of Instruction Pipeline - set up new i.e. after load of PSR
input STOP_IC; // For LMR and CINV
output [55:0] OPREG; // this is the Central Opcode Decode Register, length = 7 bytes
output [2:0] ANZ_VAL;
output IC_READ;
output NEW_PC;
output NEXT_ADR;
output DATA_HOLD;
output ABORT;
output [2:0] IC_TEX;
output INIT_DONE;
reg [55:0] OPREG;
reg [2:0] ANZ_VAL;
reg IC_READ;
reg ABORT;
reg abort_flag;
reg [2:0] IC_TEX;
reg [55:0] data_to_ri;
reg old_init;
reg pre_new;
reg new_reg;
reg nseq_flag;
reg stop_init;
wire [2:0] new_anz;
wire new_restart;
wire acc_err,acc_ok,acc_ende;
// ++++++++++++++++++++ Evaluation of ACC_STAT from Instructioncache ++++++++++++++++++++++++++++
// ACC_STAT[3:0] : PROT_ERROR , ABO_LEVEL1 , ABORT , ACC_OK
assign acc_err = ACC_STAT[3] | ACC_STAT[1] | PROT_ERROR;
assign acc_ok = ACC_STAT[0];
always @(posedge BCLK or negedge BRESET) // is kept until DECODER really needs the data !
if (!BRESET) ABORT <= 1'b0;
else ABORT <= (acc_err & ~(new_restart | pre_new)) | (ABORT & ~NEW_PC);
always @(posedge BCLK) if (acc_err) IC_TEX <= (ACC_STAT[3] | PROT_ERROR) ? {nseq_flag,2'b11} : {nse
always @(posedge BCLK) nseq_flag <= NEW_PC | (nseq_flag & ~acc_ok); // for MMU Status Register
 
always @(posedge BCLK) abort_flag <= acc_err;
assign acc_ende = ~IC_READ | acc_ok | abort_flag; // abort_flag one cycle later is ok ! If no ICach
assign new_restart = NEW | RESTART; // They are pulses
// Branch work out : NEW/RESTART notice if access still not ended
always @(posedge BCLK) pre_new <= (new_restart & ~acc_ende) | (pre_new & ~acc_ende & BRESET);
assign NEW_PC = (new_restart | pre_new) & acc_ende; // At the end of access geenerate new address !
// There are 2 "NEW/RESTART" : "new_restart" combinatorical out of DECODER, "pre_new" out of Regist
always @(posedge BCLK) new_reg <= new_restart | pre_new | (new_reg & ~acc_ende & BRESET);
always @(USED or OPREG) // Data first shift to the right
case (USED)
3'b000 : data_to_ri = OPREG;
3'b001 : data_to_ri = { 8'hxx, OPREG[55:8]};
3'b010 : data_to_ri = {16'hxxxx,OPREG[55:16]};
3'b011 : data_to_ri = {24'hxx_xxxx,OPREG[55:24]};
3'b100 : data_to_ri = {32'hxxxx_xxxx,OPREG[55:32]};
3'b101 : data_to_ri = {40'hxx_xxxx_xxxx,OPREG[55:40]};
3'b110 : data_to_ri = {48'hxxxx_xxxx_xxxx,OPREG[55:48]};
3'b111 : data_to_ri = 56'hxx_xxxx_xxxx_xxxx;
endcase
 
assign new_anz = ANZ_VAL - USED;
 
always @(posedge BCLK)
casex ({new_reg,acc_ok,ALSB,new_anz})
7'b1_100_xxx : OPREG <= {24'hxx_xxxx,IC_DIN};
7'b1_101_xxx : OPREG <= {32'hxxxx_xxxx,IC_DIN[31:8]};
7'b1_110_xxx : OPREG <= {40'hxx_xxxx_xxxx,IC_DIN[31:16]};
7'b1_111_xxx : OPREG <= {48'hxxxx_xxxx_xxxx,IC_DIN[31:24]};
7'b0_0xx_xxx : OPREG <= data_to_ri;
7'b0_1xx_000 : OPREG <= {24'hxx_xxxx,IC_DIN};
7'b0_1xx_001 : OPREG <= { 16'hxxxx,IC_DIN, data_to_ri[7:0]};
7'b0_1xx_010 : OPREG <= { 8'hxx,IC_DIN,data_to_ri[15:0]};
7'b0_1xx_011 : OPREG <= { IC_DIN,data_to_ri[23:0]};
7'b0_1xx_1xx : OPREG <= data_to_ri;
endcase
always @(posedge BCLK or negedge BRESET)
if (!BRESET) ANZ_VAL <= 3'b000;
else
casex ({new_restart,new_reg,acc_ok,new_anz[2]})
4'b1x_x_x : ANZ_VAL <= 3'b000; // hard setting to 0
4'b01_0_x : ANZ_VAL <= 3'b000;
4'b01_1_x : ANZ_VAL <= pre_new ? 3'b000 : 3'b100 - {1'b0,ALSB};
4'b00_0_x : ANZ_VAL <= new_anz;
4'b00_1_0 : ANZ_VAL <= new_anz + 3'b100;
4'b00_1_1 : ANZ_VAL <= new_anz;
endcase
assign NEXT_ADR = new_reg ? (acc_ok & ~pre_new) : (acc_ok & ~new_anz[2]); // switches MUX at PC res
 
// Instruction CACHE Control : READ is coming after all INITs are done
always @(posedge BCLK) old_init <= IC_INIT | DC_INIT | Y_INIT;
assign INIT_DONE = old_init & ~IC_INIT & ~DC_INIT;
 
always @(posedge BCLK or negedge BRESET)
if (!BRESET) stop_init <= 1'b0;
else stop_init <= stop_init | IC_READ;
// The INIT_DONE should come after Reset. But it comes too at LMR PTB therefore extra enable after
always @(posedge BCLK or negedge BRESET)
if (!BRESET) IC_READ <= 1'b0;
else IC_READ <= (IC_READ & ~acc_err & ~(STOP_IC & acc_ok)) | NEW_PC | (INIT_DONE & ~stop_init);
// The Opcode-Register can not store the data : keep them in ICACHE at IO-access
assign DATA_HOLD = ~new_restart & ~new_reg & acc_ok & new_anz[2];
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. PROG_COUNTER Program Counters
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module PROG_COUNTER ( BCLK, BRESET, NEW, LOAD_PC, NEW_PC, NEXT_ADR, NEXT_PCA, DISP, PC_NEW, USED, US
ADIVAR, PC_ARCHI, PC_ICACHE, PC_SAVE, ALSB, IC_USER);
 
input BCLK,BRESET;
input NEW;
input LOAD_PC;
input NEW_PC;
input NEXT_ADR;
input NEXT_PCA;
input [31:0] DISP;
input [31:0] PC_NEW;
input [2:0] USED;
input USER;
input SAVE_PC;
input FPU_TRAP;
input ADIVAR;
output [31:0] PC_ARCHI; // goes to Datapath
output [31:0] PC_ICACHE;
output [31:0] PC_SAVE; // is the return address
output [1:0] ALSB;
output IC_USER;
reg [31:0] PC_ARCHI;
reg [31:0] pc_adduse;
reg [31:0] pc_ic_reg;
reg [31:0] fpu_trap_pc;
reg IC_USER;
wire [31:0] branch,pc_jump,next_pc,pc_icache_i;
assign PC_SAVE = pc_adduse + {29'h0,USED};
assign branch = PC_ARCHI + DISP;
assign pc_jump = LOAD_PC ? PC_NEW : branch;
assign next_pc = NEW ? pc_jump : PC_SAVE; // Only at NEW is the DISP correct !
always @(posedge BCLK or negedge BRESET)
if (!BRESET) pc_adduse <= 32'h0;
else
pc_adduse <= next_pc;
// The Architectur - PC : Address mode "Programm Memory"-relativ
// no BRESET because NEXT_PCA is immediately valid
always @(posedge BCLK)
if (FPU_TRAP) PC_ARCHI <= fpu_trap_pc; // go back !
else
if (NEXT_PCA) PC_ARCHI <= pc_adduse;
always @(posedge BCLK) if (SAVE_PC) fpu_trap_pc <= PC_ARCHI; // Special storage for PC for FPU Trap
always @(posedge BCLK or negedge BRESET)
if (!BRESET) pc_ic_reg <= 32'h0;
else
pc_ic_reg <= pc_icache_i;
// NEW is only one cycle long - but in pc_adduse is the PC stored when ACC_OK is not there and ther
// is used to initiate a new access in ICACHE
assign pc_icache_i = NEW_PC ? (NEW ? pc_jump : pc_adduse) : (NEXT_ADR ? ({pc_ic_reg[31:2],2'b00} +
// This MUX is extra for LMR IVAR,... and CINV build in
assign PC_ICACHE = {(ADIVAR ? PC_NEW[31:4] : pc_icache_i[31:4]),pc_icache_i[3:0]};
assign ALSB = pc_ic_reg[1:0]; // for OPDEC_REG
// The IC_USER flag is allowed to switch synchronously with one cycle delay to PC_ICACHE
always @(posedge BCLK or negedge BRESET)
if (!BRESET) IC_USER <= 1'b0;
else
if (NEW_PC) IC_USER <= USER;
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 3. REG_LIST Register List Evaluation
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module REG_LIST ( DIN, IPOS, INIT, OPOS, VALID);
 
// Detects set bits in register list for SAVE/RESTORE & ENTER/EXIT
 
input [7:0] DIN;
input [2:0] IPOS;
input INIT;
output [2:0] OPOS;
output VALID;
reg [7:1] filter;
wire [7:0] mdat_0;
wire [3:0] mdat_1;
wire [1:0] mdat_2;
 
always @(IPOS or DIN)
case (IPOS)
3'd0 : filter = DIN[7:1];
3'd1 : filter = {DIN[7:2],1'b0};
3'd2 : filter = {DIN[7:3],2'b0};
3'd3 : filter = {DIN[7:4],3'b0};
3'd4 : filter = {DIN[7:5],4'b0};
3'd5 : filter = {DIN[7:6],5'b0};
3'd6 : filter = {DIN[7] ,6'b0};
3'd7 : filter = 7'b0;
endcase
assign mdat_0 = INIT ? DIN : {filter,1'b0};
assign OPOS[2] = (mdat_0[3:0] == 4'h0);
assign mdat_1 = OPOS[2] ? mdat_0[7:4] : mdat_0[3:0];
assign OPOS[1] = (mdat_1[1:0] == 2'b00);
assign mdat_2 = OPOS[1] ? mdat_1[3:2] : mdat_1[1:0];
assign OPOS[0] = ~mdat_2[0];
assign VALID = (mdat_2 != 2'b00);
endmodule
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 4. ILL_UNDEF Illegal and Undefined Opcodes Detection
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module ILL_UNDEF (OPREG, ANZ_VAL, USER, CFG, ILL, UNDEF );
 
input [23:0] OPREG;
input [2:0] ANZ_VAL;
input [3:1] CFG; // 3=CUSTOM,2=MMU,1=FPU
input USER;
output reg ILL;
output UNDEF;
 
reg undef_opc;
reg undef_am;
reg undef_im;
wire [2:0] valid;
wire gen12,gen22,gen13,gen23;
wire igen12,igen22,igen13,igen23;
wire lsbes;
parameter udef_amode = 5'b10011; // Undefined Addressing Mode
parameter imode = 5'b10100; // Immediate Addressing Mode
// [2]= minimum 3, [1]= minimum 2, [0]=minimum 1
assign valid = {(ANZ_VAL[2] | (ANZ_VAL[1:0] == 2'b11)),(ANZ_VAL[2:1] != 2'b00),(ANZ_VAL != 3'b000)}
assign lsbes = (OPREG[1:0] == 2'b10); // Tag of all 3 Byte opcodes
// +++++++++++++++++++++++++ Detect illegale opcodes +++++++++++++++++++
always @(OPREG or lsbes or valid or USER)
casex ({valid[2:1],OPREG[13:2],lsbes})
15'bx1_xx_x000_1x10_11_0 : ILL = USER; // SPRi/LPRi DCR
15'bx1_xx_x001_xx10_11_0 : ILL = USER; // SPRi/LPRi BPC/DSR
15'bx1_xx_xx10_xx10_11_0 : ILL = USER; // SPRi/LPRi CAR/CFG/PSR
15'bx1_xx_x101_1x10_11_0 : ILL = USER; // SPRi/LPRi USP
15'bx1_xx_x111_0x10_11_0 : ILL = USER; // SPRi/LPRi INTBASE
15'bx1_xx_x0x1_0111_11_x : ILL = USER & OPREG[0]; // BICPSRW,BISPSRW
15'bx1_00_10xx_0000_11_1 : ILL = USER; // SETCFG - Achtung : is coded as 2 Byte Opcode
15'b1x_00_xxxx_0001_11_1 : ILL = USER; // LMR/SMR/RDVAL/WRVAL
15'b1x_10_01xx_0001_11_1 : ILL = USER; // CINV
default : ILL = 1'b0;
endcase
 
// ++++++++++++++++++++++++ Detect Undefined opcodes +++++++++++++++
always @(OPREG or lsbes or valid or CFG)
casex ({valid,OPREG[13:2],lsbes})
16'bx1x_xx_xxxx_1111_110 : undef_opc = 1'b1; // Format 3 : xxx1
16'bx1x_xx_x100_0111_110 : undef_opc = 1'b1; // Format 3 : 1000
16'b1xx_1x_xxxx_0000_111 : undef_opc = 1'b1; // Format 5 : 1xxx
16'b1xx_01_xxxx_0000_111 : undef_opc = 1'b1; // Format 5 : 01xx
16'b1xx_01_00xx_0100_111 : undef_opc = 1'b1; // Format 6 : 0100
16'b1xx_10_10xx_x100_111 : undef_opc = 1'b1; // Format 6/7 : 1010
16'b1xx_xx_xxxx_x011_111 : undef_opc = ~CFG[1]; // Format 9/11 : FPU Befehle wie MOVif etc. und
16'b1xx_xx_xxxx_1111_111 : undef_opc = ~CFG[1]; // Format 12 : FPU Befehle wie POLYf etc.
16'b1xx_x1_xxxx_0001_111 : undef_opc = 1'b1; // Format 14 : x1xx
16'b1xx_10_00xx_0001_111 : undef_opc = 1'b1; // Format 14 : 1000
16'b1xx_10_1xxx_0001_111 : undef_opc = 1'b1; // Format 14 : 101x
16'b1xx_00_1xxx_0001_111 : undef_opc = ~CFG[2] | ~OPREG[18]; // Format 14 : LMR/SMR
16'b1xx_xx_xxxx_x011_011 : undef_opc = ~CFG[3]; // Format 15.1/15.5 : CUSTOM CCV0, CCAL0 etc.
16'b1xx_xx_xxxx_0001_011 : undef_opc = 1'b1; // Format 15.0 - not yet in, requires HW change
16'b1xx_xx_xxxx_x1x1_011 : undef_opc = 1'b1; // Format 15 : rest
16'b1xx_xx_xxxx_1001_011 : undef_opc = 1'b1; // Format 15.4
// completely undefined :
16'bxx1_xx_xxxx_0111_111 : undef_opc = 1'b1; // Format 10
16'bxx1_xx_xxxx_100x_111 : undef_opc = 1'b1; // Format 13/18
16'bxx1_xx_xxxx_x101_111 : undef_opc = 1'b1; // Format 16/17
16'bxx1_xx_xxxx_xxx0_011 : undef_opc = 1'b1; // Format 19
default : undef_opc = 1'b0;
endcase
 
// 2. Undefined Addressing mode 5'b10011
assign gen12 = (OPREG[15:11] == udef_amode);
assign gen22 = (OPREG[10:6] == udef_amode);
assign gen13 = (OPREG[23:19] == udef_amode);
assign gen23 = (OPREG[18:14] == udef_amode);
always @(OPREG or valid or gen12 or gen22 or gen13 or gen23)
if (valid[2] && (OPREG[7:5] != 3'b000) && (OPREG[3:0] == 4'b1110)) undef_am = gen13 | gen23; // ne
else
undef_am = valid[1] & gen12 & (OPREG[1:0] != 2'b10) & ((OPREG[3:2] != 2'b11) & gen22); // all
// 3. When is Immediate not allowed ?
assign igen12 = (OPREG[15:11] == imode);
assign igen22 = (OPREG[10:6] == imode);
assign igen13 = (OPREG[23:19] == imode);
assign igen23 = (OPREG[18:14] == imode);
always @(*)
casex ({valid[2:1],OPREG[13:2],lsbes})
15'bx1_xxxxxx_x0xx11_0 : undef_im = igen12 & (OPREG[5:4] != 2'b01); // Format 2 : ADDQD,SPR,Sco
15'bx1_xxxxxx_x10111_0 : undef_im = igen12; // Format 2 : ACB,MOVQ
15'bx1_xxxxx0_011111_0 : undef_im = igen12; // Format 3 : CXPD,JUMP,JSR
15'bx1_xxxxxx_xxxxx0_0 : undef_im = igen22; // Format 4
15'bx1_xxxxxx_xxxx01_0 : undef_im = (igen12 & (OPREG[5:4] == 2'b10)) // Format 4 : SRC1 - not AD
|(igen22 & (OPREG[5:4] != 2'b00)); // Format 4 : SRC2 - CMP
15'b1x_xxxxxx_x10011_1 : undef_im = igen23; // Format 6+7
15'b1x_xxx0xx_0x1011_1 : undef_im = igen13 | igen23; // Format 8 EXT,CVTP
15'b1x_xxx0xx_101011_1 : undef_im = igen23; // Format 8 : INS
15'b1x_xxx0xx_111011_1 : undef_im = igen13; // Format 8 : CHECK
15'b1x_xxx1xx_101011_1 : undef_im = igen13 | igen23; // Format 8 MOVUS,MOVSU
15'b1x_xxx1xx_011011_1 : undef_im = igen23; // Format 8 : FFS
15'b1x_xxxxxx_001111_1 : undef_im = igen23; // Format 9
15'b1x_xxxxxx_101111_1 : undef_im = igen23 & (OPREG[13:10] != 4'h2); // Format 10 without CMPf
15'b1x_010xxx_111111_1 : undef_im = igen23; // Format 12 SCALB+LOGB
15'b1x_000xxx_000111_1 : undef_im = igen13; // Format 14 RDVAL+WRVAL
15'b1x_0011xx_000111_1 : undef_im = igen13; // Format 14 SMR
default : undef_im = 1'b0;
endcase
// Final Message :
assign UNDEF = undef_opc | undef_am | undef_im;
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 5. GRUPPE_2 Decoder and State Machine for GRUPPE_2 Opcodes
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module GRUPPE_2 ( BCLK, PHASE_0, OPREG, PHASE, SRC_1, SRC_2, REGA1, REGA2, IRRW1, IRRW2, ADRD1, ADRD
PHRD1, PHRD2, NXRD1, NXRW2, ACCA, OPERA,
STATE_0, STATE_GROUP_50, STATE_GROUP_60 );
 
 
input BCLK,PHASE_0;
input [13:0] OPREG;
input [3:0] PHASE; // nur die 4 LSBs
// Source 1 & 2 Inputs
input [6:0] SRC_1,SRC_2,REGA1,REGA2,IRRW1,IRRW2;
input [18:0] ADRD1,ADRD2,EXR12,EXR22;
input [3:0] PHRD1,PHRD2;
input [3:0] NXRD1,NXRW2;
input [3:0] ACCA; // ACCA = Access type : 0x Register
// [3:2] or [1:0] 10 Memory
// 11 Memory + Index
input [10:0] OPERA;
 
output [66:0] STATE_0;
output [66:0] STATE_GROUP_50,STATE_GROUP_60;
reg [66:0] STATE_GROUP_50,STATE_GROUP_60;
reg [66:0] STATE_0,state_50,state_53,state_54,state_55,state_58,state_59,state_5A;
reg [4:0] op_code,op_reg_reg;
reg [7:0] phsrc1,phsrc2;
reg [5:0] chkreg;
reg [1:0] bwdreg;
reg tbit_flag,size_dw;
reg inss_flag;
wire [18:0] exoffset,re_wr;
wire [10:0] op_kust,op_bwd;
wire [7:0] phchk;
wire [4:0] op_reg;
wire [6:0] src_1l,src_2l;
wire [5:0] dest_2;
wire [3:0] get8b_s,get8b_d;
wire [6:0] rd_reg;
wire [10:0] op_zext;
wire [3:0] imdi;
parameter dont_care = 67'hx_xxxx_xxxx_xxxx_xxxx;
// Address-Field : Size:2 RD WR LDEA FULLACC INDEX:4 SPUPD disp_val:4 POST CLRMSW SRC2SEL:2
parameter addr_nop = 19'h0; // alle Parameter auf 0
parameter disp2ea = 19'bxx_0010_0000_0_0000_0010; // pass DISP
parameter case_op = 19'bxx_0010_1000_0_0000_0001; // SRC1 add to PC_ARCHI
parameter read_byb = 19'b00_1011_11xx_0_0000_0011; // read of SRC2 for Bit opcodes
parameter exr11 = {2'b10 ,4'b1011,4'h0 ,9'h080}; // 2. access External with Mem.-Pointer + 4* Dis
parameter adrcvtp = 19'bxx_0010_0111_0_0000_0000; // for CVTP
parameter addone = 19'bxx_0010_0100_0_0000_0000; // for INDEX : SRC1 + SRC2 , simple Add without Fl
parameter addind = 19'bxx_0010_0100_0_0000_0011; // for INDEX : SRC1 + EA
parameter src_x = 7'hxx;
parameter dest_x = 6'hxx;
parameter imme = {1'b1,6'hxx};
parameter F0 = 7'h20;
parameter F0_h = 7'h21;
parameter w_F0 = 6'h20;
parameter w_F0_h = 6'h21;
parameter temp_l = 6'h3C;
parameter temp_h = 6'h3D; // Second last place for 8B TEMP Register
parameter temp_1 = 6'h3E;
parameter rtmpl = 7'h3C;
parameter rtmph = 7'h3D;
parameter rtmp1 = 7'h3E;
parameter op_mov = {3'bxxx,8'h45};
parameter op_adr = {3'bxxx,8'h49};
parameter op_addl = {3'b0xx,8'hB0};
parameter op_addf = {3'b1xx,8'hB0};
parameter op_mull = {3'b0xx,8'hBC};
parameter op_mulf = {3'b1xx,8'hBC};
parameter op_truf = {3'b101,8'h9A}; // TRUNCFW for SCALBF
parameter op_trul = {3'b001,8'h9A}; // TRUNCLW for SCALBL
parameter op_stpr = {3'b1xx,8'h54}; // Special-Op for String opcodes
parameter op_lsh = {3'b011,8'h65}; // EXT : shift to right : DOUBLE !
parameter op_msk = {3'b011,8'h80}; // reuse of EXT Opcode at INS !
parameter op_mul = {3'b011,8'h78}; // INDEX
parameter op_rwv = {3'bxxx,8'hE0}; // RDVAL+WRVAL
 
always @(OPREG) // whether the Opcode is valid is decided in DECODER !
casex (OPREG) // [13:0]
14'bxx_xxxx_1111_1110 : op_code = {2'b01,OPREG[11:10],OPREG[8]}; // DOT/POLY/SCALB
14'b00_0xxx_0000_1110 : op_code = 5'b1_0000; // MOVS/CMPS
14'b00_11xx_0000_1110 : op_code = 5'b1_0000; // SKPS
14'b00_0xxx_1100_1110 : op_code = 5'b1_0001; // MOVM/CMPM
14'bxx_xx10_0111_11xx : op_code = 5'b1_0010; // JUMP/JSR
14'bxx_x111_0111_11xx : op_code = 5'b1_0011; // CASE
14'bxx_xxxx_xx11_010x : op_code = 5'b1_0100; // TBIT
14'bxx_xxxx_xx11_0111 : op_code = 5'b1_0100; // TBIT
14'b0x_1xxx_0100_1110 : op_code = 5'b1_0100; // CBIT/SBIT
14'b11_10xx_0100_1110 : op_code = 5'b1_0100; // IBIT
14'b00_11xx_1100_1110 : op_code = 5'b1_0101; // EXTS
14'b10_x1xx_1100_1110 : op_code = 5'b1_0111; // DEI/MEI
14'bxx_x0xx_1110_1110 : op_code = 5'b1_1000; // CHECK
14'bxx_x0xx_0010_1110 : op_code = 5'b1_1010; // EXT
14'bxx_x0xx_1010_1110 : op_code = 5'b1_1011; // INS
14'b00_10xx_1100_1110 : op_code = 5'b1_1011; // INSS, the same like INS !
14'bxx_x0xx_0110_1110 : op_code = 5'b1_1100; // CVTP
14'bxx_x1xx_0010_1110 : op_code = 5'b1_1101; // INDEX
14'bxx_x000_0111_11xx : op_code = 5'b1_1110; // CXPD
14'b00_0xxx_0001_1110 : op_code = 5'b1_1111; // RDVAL+WRVAL
default : op_code = 5'b00_xxx;
endcase
always @(posedge BCLK) if (PHASE_0) op_reg_reg <= op_code;
assign op_reg = PHASE_0 ? op_code : op_reg_reg;
always @(PHRD1) // recode of States
casex (PHRD1)
4'h5 : phsrc1 = 8'h51;
4'h6 : phsrc1 = 8'h52;
4'hB : phsrc1 = 8'h53; // ok, is in default ...
default : phsrc1 = 8'h53;
endcase
assign get8b_s = (PHRD1 == 4'hB) ? 4'hC : 4'h0; // Special case 8B Immeadiate, is used in State 53
always @(PHRD2) // recode of States
casex (PHRD2)
4'h5 : phsrc2 = 8'h56;
4'h6 : phsrc2 = 8'h57;
4'hB : phsrc2 = 8'h58; // ok, is in default ...
default : phsrc2 = 8'h58;
endcase
assign get8b_d = (PHRD2 == 4'hB) ? 4'hC : 4'h0; // Special case 8B Immeadiate, is used in State 58
assign src_1l = {SRC_1[6:1],1'b0};
assign src_2l = {SRC_2[6:1],1'b0};
assign dest_2 = SRC_2[5:0];
assign phchk = {7'b0101_010,size_dw}; // Phase 54 or 55
assign op_kust = {1'bx,OPERA[9:8],8'h7A}; // Special-Opcode for MOVM/CMPM
assign op_bwd = {1'bx,OPERA[9:8],8'h45}; // for CASE and Bit opcodes
assign re_wr = {EXR22[18:17],4'b0101,4'h0, 9'h003}; // REUSE Address : Write of rmw , top 2 Bits
 
always @(posedge BCLK) tbit_flag <= ~OPERA[1]; // due to Timing ...
always @(posedge BCLK) size_dw <= OPERA[9];
 
always @(posedge BCLK) if (PHASE_0) chkreg <= {3'b000,OPREG[13:11]}; // for CHECK
assign rd_reg = (PHASE_0) ? {4'b0,OPREG[13:11]} : {1'b0,chkreg}; // for read operation at EXT/INS
always @(posedge BCLK) if (PHASE_0) bwdreg <= OPREG[9:8]; // only for INS/INSS !
assign op_zext = {1'bx,(PHASE_0 ? OPREG[9:8] : bwdreg),8'h76};
always @(posedge BCLK) if (PHASE_0) inss_flag <= OPREG[6]; // Difference INSS to INS
assign imdi = inss_flag ? 4'h8 : 4'hE; // read Immediate or Displacement
assign exoffset = inss_flag ? 19'b10_1011_0000_0_0000_0011 // Read of SRC2 at INSS
: 19'b10_1011_1100_0_0000_0011; // Read of SRC1+Offset at EXT, SRC2+Offset at INS
always @(*)
casex (op_reg)
5'b1_0000 : // MOVS Phase 0 : Entry 1. Pointer "in Page"-test prepare, 2. test for R0=0 , then jum
begin
STATE_0 = { addr_nop,8'h67, 7'h01, 7'h02, 1'b0,dest_x,op_stpr, 2'b00,2'b00,4'h0 }; // String
state_50 = dont_care;
state_53 = dont_care;
state_54 = dont_care;
state_55 = dont_care;
state_58 = dont_care;
state_59 = dont_care;
state_5A = dont_care;
end
5'b1_0001 : // MOVM Phase 0 : Entry with test for R0=0 , then jump to x'C0
begin
STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 };
state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 };
state_53 = { ADRD2, phsrc2,IRRW2, REGA2, 1'b1,temp_h,op_adr, 2'b00,2'b00,NXRW2 };
state_54 = dont_care;
state_55 = dont_care;
state_58 = { disp2ea, 8'h65, src_x, src_x, 1'b1,temp_1,op_adr, 2'b00,2'b00,4'b1110 }; // Read
state_59 = { addr_nop,8'h67, rtmph, rtmp1, 1'b0,dest_x,op_stpr, 2'b00,2'b00,4'h0 }; // String
state_5A = dont_care;
end
5'b1_0010 : // JUMP/JSR
begin
STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 };
state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 };
state_53 = { addr_nop,8'h66, src_x, src_x, 1'b1,temp_h,op_adr, 2'b00,2'b00,4'h0 };
state_54 = dont_care;
state_55 = dont_care;
state_58 = dont_care;
state_59 = dont_care;
state_5A = dont_care;
end
5'b1_1110 : // CXPD
begin
STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 };
state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 };
state_53 = { addr_nop,8'h6B, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_54 = dont_care;
state_55 = dont_care;
state_58 = dont_care;
state_59 = dont_care;
state_5A = dont_care;
end
5'b1_1111 : // RDVAL+WRVAL
begin
STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 };
state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 };
state_53 = { addr_nop,8'h00, src_x, src_x, 1'b0,dest_x,op_rwv, 2'b00,2'b10,4'h0 }; // LD_OU
state_54 = dont_care;
state_55 = dont_care;
state_58 = dont_care;
state_59 = dont_care;
state_5A = dont_care;
end
5'b1_0011 : // CASE
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { case_op, 8'h54, SRC_1, src_x, 1'b0,dest_x,op_bwd, 2'b00,2'b00,4'h0 };
state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; // only
state_53 = { case_op, 8'h54, imme, src_x, 1'b0,dest_x,op_bwd, 2'b00,2'b00,4'h0 };
state_54 = { addr_nop,8'h66, src_x, src_x, 1'b1,temp_h,op_adr, 2'b00,2'b00,4'h0 };
state_55 = dont_care;
state_58 = dont_care;
state_59 = dont_care;
state_5A = dont_care;
end
5'b1_0100 : // all Bit opcodes with Bit in memory. RMW Test in Phase x'59 = Special case, otherwis
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_54 = { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }; // here S
state_55 = dont_care;
state_58 = { read_byb,8'h59, rtmph, src_x, 1'b0,dest_x,op_bwd, 2'b00,2'b00,4'h1 }; // next re
state_59 = tbit_flag ?
{ addr_nop,8'h00, src_x, imme, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h0 } // TBIT end
: { re_wr, 8'h27, src_x, imme, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h1 }; // CBIT/SBIT/IBIT
state_5A = dont_care;
end
5'b1_0101 : // EXTS : BASE Operand => TEMP, calculate address of Destination
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_54 = ACCA[1] ?
{ ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } // here Adr(DEST)
: { addr_nop,8'h59, src_x, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h8 }; // 1 Byte Immedi
state_55 = dont_care;
state_58 = { addr_nop,8'h59, src_x, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h8 }; // 1 Byte
state_59 = ACCA[1] ? // _..M.
{ re_wr, 8'h27, imme, rtmph, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h1 } // result in memory
: { addr_nop,8'h00, imme, rtmph, 1'b1,dest_2,OPERA, 2'b00,2'b00,4'h0 }; // result in Regi
state_5A = dont_care;
end
5'b1_1010 : // EXT : BASE Operand => TEMP, calculate address of Destination
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_53 = { addr_nop,8'h55, src_x, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; // Addr =
state_54 = ACCA[1] ?
( ACCA[3] ?
{addr_nop,8'h5A, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }
:{ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } ) // here Adr(DEST)
: { addr_nop,8'h59, rd_reg,(ACCA[3] ? imme : rtmph),
1'b1,temp_h,op_lsh, 2'b00,2'b00,4'hE }; // Displacement read
state_55 = { exoffset,8'h54, rd_reg,src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h1 }; // Read S
state_58 = { addr_nop,8'h59, rd_reg,rtmph, 1'b1,temp_h,op_lsh, 2'b00,2'b00,4'hE }; // Displac
state_59 = ACCA[1] ? // _..M.
{ re_wr, 8'h27, src_x, rtmph, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h1 } // result in memory
: { addr_nop,8'h00, src_x, rtmph, 1'b1,dest_2,OPERA, 2'b00,2'b00,4'h0 }; // result in Regi
state_5A = { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }; // special
end
5'b1_1011 : // INS/INSS : BASE Operand => TEMP, SRC2 read as Double ! RMW not tested (Phase x'6A)
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 };
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 };
state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 }; // zext(
state_54 = ACCA[1] ?
{ ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } // here Adr(DEST) =
: { addr_nop,8'h5A, SRC_2, src_x, 1'b1,temp_l,op_mov, 2'b00,2'b00,imdi }; // Imme./Disp. r
state_55 = { exoffset,8'h6A, rd_reg,src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h1 }; // Read S
state_58 = { addr_nop,8'h55, src_x, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; //
state_59 = ACCA[1] ? // _..M.
{ re_wr, 8'h27, rtmph, rtmpl, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h1 } // result in memory
: { addr_nop,8'h00, rtmph, rtmpl, 1'b1,dest_2,OPERA, 2'b00,2'b00,4'h0 }; // result in Regi
state_5A = { addr_nop,8'h68, imme, src_x, 1'b1,temp_1,op_msk, 2'b00,2'b00,4'h0 }; // Mask ge
end
5'b1_1101 : // INDEX :
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 };
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 };
state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 }; // zext(
state_54 = ACCA[1] ?
{ ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } // zext(SRC2) => TE
: { addr_nop,8'h55, SRC_2, src_x, 1'b1,temp_l,op_zext, 2'b00,2'b00,4'h0 };
state_55 = { addr_nop,8'h5A, rd_reg,rtmph, 1'b1,temp_h,op_mul, 2'b00,2'b00,4'h0 }; // Multip
state_58 = { addr_nop,8'h55, imme, src_x, 1'b1,temp_l,op_zext, 2'b00,2'b00,4'h0 }; //
state_59 = { addind, 8'h60, rtmpl, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; // Add of
state_5A = { addone, 8'h59, rd_reg,rtmph, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; // Add of
end
5'b1_0111 : // DEI + MEI , both read 8B from DEST ! RMW critical !
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 };
state_54 = ACCA[1] ?
{ ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } // here SRC1 => TE
: { addr_nop,8'h59, rtmph, SRC_2, 1'b0,dest_x,OPERA, 2'b01,2'b00,4'h0 }; // 1. part of Reg
state_55 = dont_care;
state_58 = size_dw ?
{ addr_nop,8'h59, rtmph, imme, 1'b0,dest_x,OPERA, 2'b01,2'b00,4'h0 } // D needs 2 accesse
: { addr_nop,8'h1F, rtmph, imme, 1'b0,dest_x,OPERA, 2'b11,2'b00,4'h0 }; // B+W start at o
state_59 = { addr_nop,8'h1F, src_x, (ACCA[1] ? imme : src_2l), // SRC2 = memory or Reg
~ACCA[1],dest_2,OPERA, 2'b10,2'b00,4'h0 };
state_5A = dont_care;
end
5'b1_1000 : // CHECK
begin
STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; // No Re
state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 };
state_53 = { addr_nop,phchk, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; // No Imm
state_54 = ACCA[1] ?
{ ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }
: ( size_dw ?
{addr_nop,8'h5A, SRC_2, rtmpl, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h0 } // Upper Bound - point
: {addr_nop,8'h00, rtmph, SRC_2, 1'b1,chkreg,OPERA, 2'b00,2'b10,4'h0 } );
state_55 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_l,op_mov, 2'b00,2'b00,4'h0 };
state_58 = size_dw ?
{ addr_nop,8'h59, imme, src_x, 1'b1,temp_1,op_mov, 2'b00,2'b00,4'h0 } // here SRC2 => TEM
: { addr_nop,8'h00, rtmph, imme, 1'b1,chkreg,OPERA, 2'b00,2'b10,4'h0 };
state_59 = { addr_nop,8'h5A, rtmp1, rtmpl, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h0 }; // Upper Bo
state_5A = { addr_nop,8'h00, rtmph, (ACCA[1] ? rtmp1 : SRC_2),
1'b1,chkreg,OPERA, 2'b00,2'b10,4'h0 }; // pointer - Lower Bound
end
5'b1_1100 : // CVTP
begin
STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; // Addre
state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 };
state_53 = { addr_nop,8'h54, src_x, src_x, 1'b1,temp_h,op_adr, 2'b00,2'b00,4'h0 };
state_54 = { adrcvtp, 8'h73, rtmph, rd_reg,1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; // 8*TEMP
state_55 = dont_care;
state_58 = dont_care;
state_59 = dont_care;
state_5A = dont_care;
end
5'b01_000 : // SCALBL : RMW critical !
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_1l,1'b1,temp_h,op_trul, 2'b11,2'b00,4'h0 };
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_1l,1'b1,temp_h,op_trul, 2'b11,2'b00,4'h0 };
state_53 = { addr_nop,8'h55, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,get8b_s };
state_54 = ACCA[1] ?
{ ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_trul, 2'b00,2'b00,NXRW2 }
: { addr_nop,8'h5A, src_x, src_x, 1'b0,temp_h,op_trul, 2'b00,2'b00,4'h0 };
state_55 = { addr_nop,8'h54, rtmph, imme, 1'b1,temp_h,op_trul, 2'b11,2'b00,4'h0 }; // 2. hal
state_58 = { addr_nop,8'h59, rtmph, imme, 1'b0,dest_2,OPERA, 2'b01,2'b00,4'h0 };
state_59 = { addr_nop,8'h1F, src_x, (ACCA[1] ? imme : src_2l),
~ACCA[1],dest_2,OPERA, 2'b10,2'b00,4'h0 };
state_5A = { addr_nop,8'h59, rtmph, SRC_2, 1'b0,dest_2,OPERA, 2'b01,2'b00,4'h0 }; // empty cy
end
5'b01_001 : // SCALBF : RMW critical !
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_truf, 2'b00,2'b00,4'h0 };
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_truf, 2'b00,2'b00,4'h0 };
state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_truf, 2'b00,2'b00,4'h0 };
state_54 = ACCA[1] ?
{ ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }
: { addr_nop,8'h1F, rtmph, SRC_2, 1'b1,dest_2,OPERA, 2'b11,2'b00,4'h0 };
state_55 = dont_care;
state_58 = { addr_nop,8'h1F, rtmph, imme, 1'b0,dest_x,OPERA, 2'b11,2'b00,4'h0 };
state_59 = dont_care;
state_5A = dont_care;
end
5'b01_100 : // POLYL
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, F0_h, 1'b0,temp_h,op_mull, 2'b01,2'b00,4'h0 };
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, F0_h, 1'b0,temp_h,op_mull, 2'b01,2'b00,4'h0 };
state_53 = { addr_nop,8'h54, imme, F0_h, 1'b0,temp_h,op_mull, 2'b01,2'b00,get8b_s };
state_54 = { addr_nop,8'h64, (ACCA[3] ? imme : src_1l),
F0, 1'b1,temp_h,op_mull, 2'b10,2'b00,4'h0 };
state_55 = dont_care;
state_58 = { addr_nop,8'h59, imme, rtmph, 1'b0,dest_x,op_addl, 2'b01,2'b00,get8b_d };
state_59 = { addr_nop,8'h62, (ACCA[1] ? imme : src_2l),
rtmpl, 1'b1,w_F0_h,op_addl, 2'b10,2'b00,4'h0 };
state_5A = dont_care;
end
5'b01_101 : // POLYF
begin
STATE_0 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, F0, 1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 };
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { addr_nop,8'h54, SRC_1, F0, 1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 };
state_53 = { addr_nop,8'h54, imme, F0, 1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 };
state_54 = ACCA[1] ?
{ ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }
: { addr_nop,8'h00, rtmph, SRC_2, 1'b1,w_F0 ,op_addf, 2'b00,2'b00,4'h0 };
state_55 = dont_care;
state_58 = { addr_nop,8'h00, rtmph, imme, 1'b1,w_F0 ,op_addf, 2'b00,2'b00,4'h0 };
state_59 = dont_care;
state_5A = dont_care;
end
5'b01_110 : // DOTL
begin
STATE_0 = (~ACCA[3] & ~ACCA[1]) ? // _R.R.
{ addr_nop,8'h59, SRC_1, SRC_2, 1'b0,dest_x,op_mull, 2'b01,2'b00,4'h0 }
: ( ACCA[3] ? // _M...
{ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: {ADRD2, phsrc2,src_x, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } );
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 };
state_53 = ACCA[1] ? // _..M.
{ addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,get8b_s }
: { addr_nop,8'h59, imme, SRC_2, 1'b0,dest_x,op_mull, 2'b01,2'b00,get8b_s };
state_54 = { addr_nop,8'h55, imme, src_x, 1'b1,temp_l,op_mov, 2'b00,2'b00,4'h0 };
state_55 = { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 };
state_58 = { addr_nop,8'h59, (ACCA[3] ? rtmph : SRC_1), //_M...
imme, 1'b0,dest_x,op_mull, 2'b01,2'b00,get8b_d };
state_59 = { addr_nop,8'h5A, (ACCA[3] ? (ACCA[1] ? rtmpl : imme) : src_1l), (ACCA[1] ? imme :
1'b1,temp_h,op_mull, 2'b10,2'b00,4'h0 };
state_5A = { addr_nop,8'h61, rtmph, F0_h, 1'b0,temp_h,op_mull, 2'b01,2'b00,4'h0 };
end
5'b01_111 : // DOTF
begin
STATE_0 = (~ACCA[3] & ~ACCA[1]) ? // _R.R.
{ addr_nop,8'h63, SRC_1 ,SRC_2 ,1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 } // opera = MULF
: ( ACCA[3] ? // _M...
{ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: {ADRD2, phsrc2,src_x, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } );
state_50 = ACCA[3] ? // _M...
{ ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }
: { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 };
state_53 = ACCA[1] ? // _..M.
{ addr_nop,8'h55, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }
: { addr_nop,8'h63, imme, SRC_2 ,1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 };
state_54 = dont_care;
state_55 = { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 };
state_58 = { addr_nop,8'h63, (ACCA[3] ? rtmph : SRC_1), //_M...
imme, 1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 };
state_59 = dont_care;
state_5A = dont_care;
end
default
begin
STATE_0 = dont_care;
state_50 = dont_care;
state_53 = dont_care;
state_54 = dont_care;
state_55 = dont_care;
state_58 = dont_care;
state_59 = dont_care;
state_5A = dont_care;
end
endcase
always @(*)
casex (PHASE)
4'h0 : STATE_GROUP_50 = state_50;
// Phase 51 : wait for data and Disp2 for External Address mode : part 2 EA = (MOD+4)+4*DISP1
4'h1 : STATE_GROUP_50 = {exr11, 8'h52, src_x,imme , 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'b1111}
// Phase 52 : Memory-Pointer for Memory Relative and last access External
4'h2 : STATE_GROUP_50 = {EXR12, 8'h53, IRRW1,imme , 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'b1111}
4'h3 : STATE_GROUP_50 = state_53;
4'h4 : STATE_GROUP_50 = state_54;
4'h5 : STATE_GROUP_50 = state_55;
// Phase 56 : wait for data and Disp2 for External Address mode : part 2 EA = (MOD+4)+4*DISP1
4'h6 : STATE_GROUP_50 = {exr11, 8'h57, src_x,imme , 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'b1111}
// Phase 57 : Memory-Pointer for Memory Relative and last access External
4'h7 : STATE_GROUP_50 = {EXR22, 8'h58, IRRW2,imme , 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'b1111}
4'h8 : STATE_GROUP_50 = state_58;
4'h9 : STATE_GROUP_50 = state_59;
4'hA : STATE_GROUP_50 = state_5A;
default : STATE_GROUP_50 = dont_care;
endcase
always @(*)
casex (PHASE)
4'h0 : STATE_GROUP_60 = { addr_nop,8'h00, src_x, src_x, 1'b1,chkreg,op_adr, 2'b00,2'b00,4'h0 }
4'h1 : STATE_GROUP_60 = { addr_nop,8'h62, rtmpl, F0, 1'b1,w_F0_h,op_addl, 2'b10,2'b00,4'h0 }
4'h2 : STATE_GROUP_60 = { addr_nop,8'h00, src_x, src_x, 1'b0,w_F0_h,op_addl, 2'b00,2'b00,4'h0 }
4'h3 : STATE_GROUP_60 = { addr_nop,8'h00, rtmph, F0, 1'b1,w_F0, op_addf, 2'b00,2'b00,4'h0 }
4'h4 : STATE_GROUP_60 = ACCA[1] ? // ..M.
{ ADRD2, phsrc2,IRRW2, REGA2, 1'b0,temp_h,op_mull, 2'b00,2'b00,NXRW2 }
: { addr_nop,8'h59, SRC_2, rtmph, 1'b0,temp_h,op_addl, 2'b01,2'b00,4'h0 }; // for POLYL
4'h5 : STATE_GROUP_60 = { addr_nop,8'h59, src_x, src_x, 1'b1,temp_l,op_kust, 2'b00,2'b00,4'h0 }
4'h6 : STATE_GROUP_60 = { addr_nop,8'h01, rtmph, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 };
4'h7 : STATE_GROUP_60 = { addr_nop,8'hC0, (op_reg_reg[0] ? rtmpl : 7'h00), // Jump to Stri
src_x, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h0 }; // LD_OUT set, CMPS F-Flag
// for INS
4'h8 : STATE_GROUP_60 = { addr_nop,8'h69, rd_reg,rtmph, 1'b1,temp_h,op_lsh, 2'b00,2'b00,4'h0 };
4'h9 : STATE_GROUP_60 = { addr_nop,8'h59, rd_reg,rtmp1, 1'b0,dest_x,op_lsh, 2'b00,2'b00,4'h0 };
4'hA : STATE_GROUP_60 = { addr_nop,8'h5A, imme, src_x, 1'b1,temp_l,op_mov, 2'b00,2'b00,imdi };
// for CXPD, this State is decoded explicitly in DECODER
4'hB : STATE_GROUP_60 = { addr_nop,8'h39, imme, src_x, 1'b1,temp_l,op_mov, 2'b00,2'b00,4'h0 };
default : STATE_GROUP_60 = dont_care;
endcase
endmodule
/trunk/rtl/DATENPFAD.v
0,0 → 1,401
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: DATENPFAD.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// DATENPFAD the data path of M32632
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module DATENPFAD( BCLK, BRESET, WREN, IO_READY, LD_DIN, LD_IMME, WR_REG, IC_USER, ACC_FELD, ACC_STAT
IMME_Q, INFO_AU, LD_OUT, DETOIP, MMU_UPDATE, OPER, PC_ARCHI, PC_ICACHE, RDAA, RDAB, START, WMA
WRADR, DONE, Y_INIT, WRITE_OUT, READ_OUT, ZTEST, RMW, ACC_DONE, REG_OUT, PTB_SEL, PTB_WR, ACB_
ABORT, SAVE_PC, CFG, CINV, DP_Q, IVAR, MCR, PACKET, PC_NEW, PSR, SIZE, STRING, TRAPS, VADR, RW
DBG_HIT, DBG_IN, COP_GO, COP_OP, COP_IN, COP_DONE, COP_OUT);
 
input BCLK;
input BRESET;
input WREN; // write enable of the register file
input IO_READY;
input LD_DIN;
input LD_IMME;
input WR_REG; // write signal for the DP_FPU
input IC_USER;
input RWVFLAG;
input [14:0] ACC_FELD;
input [5:0] ACC_STAT;
input [31:0] DIN;
input [31:0] DISP;
input [2:0] IC_TEX;
input [31:0] IMME_Q;
input [6:0] INFO_AU;
input [1:0] LD_OUT;
input [12:0] DETOIP;
input [1:0] MMU_UPDATE;
input [10:0] OPER;
input [31:0] PC_ARCHI;
input [31:0] PC_ICACHE;
input [7:0] RDAA;
input [7:0] RDAB;
input [1:0] START;
input [1:0] WMASKE;
input [5:0] WRADR;
input DBG_HIT;
input COP_DONE;
input [23:0] COP_OP;
input [63:0] COP_IN;
 
output DONE;
output Y_INIT;
output WRITE_OUT;
output READ_OUT;
output ZTEST;
output RMW;
output ACC_DONE;
output REG_OUT;
output PTB_SEL;
output PTB_WR;
output reg ACB_ZERO;
output ABORT;
output SAVE_PC;
output [12:0] CFG;
output [3:0] CINV;
output [63:0] DP_Q;
output [1:0] IVAR;
output [3:0] MCR;
output [3:0] PACKET;
output [31:0] PC_NEW;
output [11:0] PSR;
output [1:0] SIZE;
output [4:0] STRING;
output [5:0] TRAPS;
output [31:0] VADR;
output [40:2] DBG_IN;
output COP_GO;
output [127:0] COP_OUT;
 
reg [31:0] high_dq;
reg [31:0] OUT_I;
reg [31:0] BYDIN; // the bypass register
 
wire [2:0] BITSEL;
wire [1:0] BWD;
wire CLR_LSB;
wire [31:0] ERGEBNIS; // the result bus
wire FL;
wire [31:0] FSR;
wire [63:0] MRESULT;
wire [7:0] OPCODE;
wire SELI_A;
wire SELI_B;
wire [2:0] SP_CMP;
wire [31:0] SRC1; // the bus for the Source 1 operand
wire [31:0] SRC2; // the bus for the Source 2 operand
wire [4:0] TT_DP;
wire TWREN; // active if FPU Trap occurs
wire UP_DP;
wire WRADR_0;
wire WREN_L,WREN_LX;
wire LD_FSR;
wire UP_SP;
wire [4:0] TT_SP;
wire [31:0] addr_i;
wire [2:0] DP_CMP;
wire [31:0] DP_OUT;
wire [31:0] SFP_DAT;
wire ld_out_l;
wire [6:0] BMCODE;
wire [31:0] OUT_A,OUT_B;
wire SP_MUX;
wire [31:0] I_OUT;
wire [31:0] FP_OUT;
wire DOWR;
wire [31:0] DEST1,DEST2;
wire ENWR;
wire [3:0] OVF_BCD;
wire [3:0] DSR;
wire acb_zero_i;
wire [31:0] BMASKE;
 
assign FL = OPER[10];
assign BWD = OPER[9:8];
assign OPCODE = OPER[7:0];
 
assign ERGEBNIS = SP_MUX ? FP_OUT : I_OUT;
 
assign WRADR_0 = WRADR[0] & ~CLR_LSB;
assign ENWR = WREN_L | WREN;
assign DOWR = ENWR & TWREN;
assign WREN_L = WREN_LX & ~TRAPS[0];
 
assign DP_Q[63:32] = high_dq;
 
assign PC_NEW = SRC1;
 
always @(posedge BCLK) if (LD_OUT[1] || WREN) ACB_ZERO <= acb_zero_i;
 
always @(posedge BCLK) if (LD_OUT[1] || ld_out_l) high_dq <= ERGEBNIS;
 
always @(posedge BCLK) if (LD_DIN) OUT_I <= LD_IMME ? IMME_Q : DIN;
 
always @(posedge BCLK) if (RDAA[7]) BYDIN <= ERGEBNIS;
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Register Set 1 => SRC1
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
REGISTER REG_SET_A(
.BCLK(BCLK),
.ENWR(ENWR),
.DOWR(DOWR),
.DIN(ERGEBNIS),
.BYDIN(BYDIN),
.RADR(RDAA),
.WADR({WRADR[5:1],WRADR_0}),
.WMASKE(WMASKE),
.SELI(SELI_A),
.DOUT(OUT_A));
 
assign SRC1 = SELI_A ? OUT_I : OUT_A;
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Register Set 2 => SRC2
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
REGISTER REG_SET_B(
.BCLK(BCLK),
.ENWR(ENWR),
.DOWR(DOWR),
.DIN(ERGEBNIS),
.BYDIN(BYDIN),
.RADR(RDAB),
.WADR({WRADR[5:1],WRADR_0}),
.WMASKE(WMASKE),
.SELI(SELI_B),
.DOUT(OUT_B));
 
assign SRC2 = SELI_B ? OUT_I : OUT_B;
 
MULFILTER M_FILTER(
.FLOAT(OPCODE[2]),
.BWD(BWD),
.SRC1(SRC1),
.SRC2(SRC2),
.DEST1(DEST1),
.DEST2(DEST2));
 
SIGNMUL S_MULTI( // signed multiplier 32 * 32 bits = 64 bits
.dataa(DEST1),
.datab(DEST2),
.result(MRESULT));
BITMASK BITM_U(
.AA(BMCODE),
.DOUT(BMASKE));
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// The integer data path
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
I_PFAD GANZ_U(
.FL(FL),
.BRESET(BRESET),
.BCLK(BCLK),
.WREN(WREN),
.LD_OUT(LD_OUT[1]),
.ADDR(addr_i),
.BITSEL(BITSEL),
.BMASKE(BMASKE),
.BWD(BWD),
.DP_CMP(DP_CMP),
.DP_OUT(DP_OUT),
.FSR(FSR),
.DETOIP(DETOIP[11:0]),
.MRESULT(MRESULT),
.OPCODE(OPCODE),
.RDAA(RDAA),
.SFP_DAT(SFP_DAT),
.SP_CMP(SP_CMP),
.SRC1(SRC1),
.SRC2(SRC2),
.WRADR(WRADR),
.DSR(DSR),
.OV_FLAG(TRAPS[2]),
.ACB_ZERO(acb_zero_i),
.BMCODE(BMCODE),
.I_OUT(I_OUT),
.PSR(PSR),
.STRING(STRING),
.OVF_BCD(OVF_BCD),
.DISP(DISP[4:0]),
.RWVFLAG(RWVFLAG));
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// The address unit
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADDR_UNIT ADDR_U(
.BCLK(BCLK),
.BRESET(BRESET),
.IO_READY(IO_READY),
.READ(ACC_FELD[11]),
.WRITE(ACC_FELD[10]),
.CLRMSW(ACC_FELD[2]),
.FULLACC(ACC_FELD[8]),
.POST(ACC_FELD[3]),
.DISP_OK(INFO_AU[0]),
.LDEA(ACC_FELD[9]),
.NEWACC(ACC_FELD[14]),
.FPU_TRAP(TRAPS[0]),
.ADIVAR(INFO_AU[2]),
.RWVAL_1(INFO_AU[3]),
.ABO_STAT({INFO_AU[1],IC_USER}),
.ACC_STAT(ACC_STAT),
.ASIZE(ACC_FELD[13:12]),
.BWD(BWD),
.DISP(DISP),
.IC_TEX(IC_TEX),
.INDEX(ACC_FELD[7:4]),
.MMU_UPDATE(MMU_UPDATE),
.PC_ARCHI(PC_ARCHI),
.PC_ICACHE(PC_ICACHE),
.SRC1(SRC1),
.SRC2(SRC2),
.SRC2SEL(ACC_FELD[1:0]),
.REG_OUT(REG_OUT),
.ACC_DONE(ACC_DONE),
.READ_OUT(READ_OUT),
.WRITE_OUT(WRITE_OUT),
.ABORT(ABORT),
.ADDR(addr_i),
.BITSEL(BITSEL),
.PACKET(PACKET),
.SIZE(SIZE),
.VADR(VADR),
.ZTEST(ZTEST),
.RMW(RMW),
.OP_RMW(INFO_AU[4]),
.PHASE_17(INFO_AU[5]),
.NO_TRAP(INFO_AU[6]) );
CONFIG_REGS CFG_DBG(
.BCLK(BCLK),
.BRESET(BRESET),
.WREN(WREN),
.LD_OUT(LD_OUT[1]),
.OPCODE(OPCODE),
.SRC1(SRC1),
.WRADR(WRADR),
.PTB_WR(PTB_WR),
.PTB_SEL(PTB_SEL),
.CFG(CFG),
.CINV(CINV),
.IVAR(IVAR),
.Y_INIT(Y_INIT),
.MCR(MCR),
.DBG_TRAPS(TRAPS[5:3]),
.PC_ARCHI(PC_ARCHI),
.DSR(DSR),
.USER(PSR[8]),
.PCMATCH(DETOIP[12]),
.DBG_IN(DBG_IN),
.DBG_HIT(DBG_HIT),
.READ(READ_OUT) );
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// The long operation unit
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DP_FPU DOUBLE_U(
.BCLK(BCLK),
.FL(FL),
.BRESET(BRESET),
.LD_LDQ(LD_OUT[0]),
.WR_REG(WR_REG),
.BWD(BWD),
.FSR(FSR[8:3]),
.OPCODE(OPCODE),
.SRC1(SRC1),
.SRC2(SRC2),
.START(START),
.DONE(DONE),
.UP_DP(UP_DP),
.WREN_L(WREN_LX),
.CLR_LSB(CLR_LSB),
.LD_OUT_L(ld_out_l),
.DVZ_TRAP(TRAPS[1]),
.DP_CMP(DP_CMP),
.DP_OUT(DP_OUT),
.DP_Q(DP_Q[31:0]),
.TT_DP(TT_DP),
.CY_IN(PSR[0]),
.OVF_BCD(OVF_BCD),
.COP_DONE(COP_DONE),
.COP_OP(COP_OP),
.COP_IN(COP_IN),
.COP_GO(COP_GO),
.COP_OUT(COP_OUT));
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// The single precision floating point unit
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SP_FPU SINGLE_U(
.FL(FL),
.BCLK(BCLK),
.BWD(BWD),
.FSR(FSR[8:3]),
.MRESULT(MRESULT[47:0]),
.OPCODE(OPCODE),
.SRC1(SRC1),
.SRC2(SRC2),
.LD_FSR(LD_FSR),
.SP_MUX(SP_MUX),
.UP_SP(UP_SP),
.FP_OUT(FP_OUT),
.I_OUT(SFP_DAT),
.SP_CMP(SP_CMP),
.TT_SP(TT_SP));
 
FP_STAT_REG FPS_REG(
.BCLK(BCLK),
.BRESET(BRESET),
.LFSR(LD_FSR),
.WREN(ENWR),
.WRADR(WRADR[5:4]),
.UP_DP(UP_DP),
.UP_SP(UP_SP & LD_OUT[1]),
.DIN(SRC1[16:0]),
.TT_DP(TT_DP),
.TT_SP(TT_SP),
.FPU_TRAP(TRAPS[0]),
.TWREN(TWREN),
.SAVE_PC(SAVE_PC),
.FSR(FSR));
 
endmodule
/trunk/rtl/CACHE_LOGIK.v
0,0 → 1,781
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: CACHE_LOGIK.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// 1. DEBUG_AE Debug unit for address compare in data cache
// 2. MMU_UP MMU memory update and initalization controller
// 3. DCA_CONTROL Data cache valid memory update and initalization controller
// 4. MMU_MATCH MMU virtual address match detector
// 5. CA_MATCH Cache tag match detector
// 6. DCACHE_SM Data cache state machine
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. DEBUG_AE Debug unit for address compare in data cache
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DEBUG_AE ( DBG_IN, READ, WRITE, USER, VIRTUELL, ACC_OK, VADR_R, MMU_Q, ENBYTE, DBG_HIT );
 
input [40:2] DBG_IN;
input READ,WRITE;
input USER;
input VIRTUELL;
input ACC_OK;
input [31:2] VADR_R;
input [19:0] MMU_Q;
input [3:0] ENBYTE;
output DBG_HIT;
wire sd,ud,crd,cwr,vnp;
wire make;
wire virt_adr,real_adr,page_adr;
wire byte_en;
assign sd = DBG_IN[40];
assign ud = DBG_IN[39];
assign crd = DBG_IN[38];
assign cwr = DBG_IN[37];
assign vnp = DBG_IN[36];
assign make = ((ud & USER) | (sd & ~USER)) // compare USER or SUPERVISOR
& (VIRTUELL == vnp) // compare real or virtual address
& ((cwr & WRITE) | (crd & READ)); // compare READ or WRITE
assign virt_adr = (MMU_Q == DBG_IN[31:12]);
assign real_adr = (VADR_R[31:12] == DBG_IN[31:12]);
assign page_adr = (VADR_R[11:2] == DBG_IN[11:2]);
assign byte_en = |(ENBYTE & DBG_IN[35:32]);
assign DBG_HIT = ACC_OK // all valid
& make // selection is valid
& (VIRTUELL ? virt_adr : real_adr) & page_adr // address
& byte_en; // Byte Enable
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. MMU_UP MMU memory update and initalization controller
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module MMU_UP ( BCLK, BRESET, NEW_PTB, PTB1, IVAR, WR_MRAM, VADR, VADR_R, MVALID, UPDATE,
WE_MV, WADR_MV, RADR_MV, DAT_MV, NEW_PTB_RUN );
 
input BCLK;
input BRESET;
input NEW_PTB; // the MMU memory is cleared. Pulse of one BCLK cycle, Op-Dec is waiting
input PTB1; // which one
input IVAR;
input WR_MRAM; // BCLK : update MRAM and MMU_VAL
input [19:16] VADR,VADR_R; // For update
input [31:0] MVALID,UPDATE;
output WE_MV; // Write Enable MMU Valid
output [3:0] WADR_MV,RADR_MV;
output [31:0] DAT_MV;
output NEW_PTB_RUN;
reg neue_ptb,wr_flag,old_rst,run_over;
reg [3:0] count;
wire [15:0] new_val;
assign WE_MV = wr_flag | WR_MRAM | IVAR; // write on falling edge BCLK
assign RADR_MV = run_over ? count : VADR;
assign WADR_MV = wr_flag ? (count - 4'b0001) : VADR_R;
assign DAT_MV = wr_flag ? {MVALID[31:16],new_val} : UPDATE; // Only the matching entries are clear
 
// [31:16] Address-Space memory, [15:0] Valid memory
assign new_val = neue_ptb ? (PTB1 ? (MVALID[15:0] & ~MVALID[31:16]) : (MVALID[15:0] & MVALID[31:16]
always @(posedge BCLK or negedge BRESET)
if (!BRESET) neue_ptb <= 1'b0;
else neue_ptb <= NEW_PTB | (neue_ptb & run_over);
always @(posedge BCLK) old_rst <= BRESET; // after Reset all will be set to 0
always @(posedge BCLK) run_over <= ((~old_rst | NEW_PTB) | (run_over & (count != 4'hF))) & BRESET;
always @(posedge BCLK) count <= run_over ? count + 4'h1 : 4'h0;
always @(posedge BCLK) wr_flag <= run_over;
 
assign NEW_PTB_RUN = wr_flag; // Info to Op-Dec
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 3. DCA_CONTROL Data cache valid memory update and initalization controller
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DCA_CONTROL ( BCLK, MCLK, BRESET, CUPDATE, DRAM_ACC, CA_SET, HIT_ALL, WRCFG, VADR_R, UPDATE,
WCTRL, KILL, WRCRAM0, WRCRAM1, WE_CV, WADR_CV, DAT_CV, INIT_CA_RUN, WRSET0, WRSET1 );
 
input BCLK;
input MCLK;
input BRESET;
input CUPDATE; // State CUPDATE : Cache is filled from DRAM
input DRAM_ACC;
input CA_SET;
input HIT_ALL; // a complete cache hit !
input WRCFG; // static signal : GND or VDD
input [11:7] VADR_R;
input [23:0] UPDATE;
input INVAL_A;
input WRITE;
input [1:0] WCTRL; // [1] : Read Burst Signal from DRAM controller, MCLK aligned. [0] : Cache inh
input KILL; // valid Ram must be updated because of collision ... or CINV
output WRCRAM0,WRCRAM1;
output WE_CV;
output [4:0] WADR_CV;
output [23:0] DAT_CV;
output INIT_CA_RUN;
output WRSET0,WRSET1;
reg [1:0] state;
reg [4:0] acount;
reg ca_set_d;
 
reg dly_bclk,zero,wr_puls;
reg [2:0] count,refer;
wire countf;
// physical address is stored in TAG-RAM
 
assign WRCRAM0 = (CUPDATE & ~WCTRL[0]) & ~CA_SET;
assign WRCRAM1 = (CUPDATE & ~WCTRL[0]) & CA_SET;
// Load Valid RAM :
assign WE_CV = state[1] | HIT_ALL | (CUPDATE & ~WCTRL[0]) | KILL; // Hit All for "Last" Update
assign WADR_CV = state[1] ? acount : VADR_R;
assign DAT_CV = state[1] ? 24'h0 : UPDATE;
 
// Clear of Cache-Valid RAMs : 32 clocks of BCLK
assign countf = (acount == 5'h1F);
always @(posedge BCLK)
casex ({BRESET,INVAL_A,countf,state[1:0]})
5'b0xx_xx : state <= 2'b01;
5'b1xx_01 : state <= 2'b10; // start counter
5'b10x_00 : state <= 2'b00; // wait ...
5'b11x_00 : state <= 2'b10;
5'b1x0_10 : state <= 2'b10;
5'b1x1_10 : state <= 2'b00;
default : state <= 2'b0;
endcase
always @(posedge BCLK) if (!state[1]) acount <= 5'h0; else acount <= acount + 5'h01;
 
assign INIT_CA_RUN = state[1];
always @(posedge BCLK) if (DRAM_ACC) ca_set_d <= CA_SET;
// WRITE Control in data RAMs
assign WRSET0 = ( ~CA_SET & WRITE & HIT_ALL & wr_puls) | (WCTRL[1] & ~ca_set_d);
assign WRSET1 = ( CA_SET & WRITE & HIT_ALL & wr_puls) | (WCTRL[1] & ca_set_d);
// ++++++++++++ Special circuit for Timing of write pulse for data RAM of data cache +++++++++
always @(negedge MCLK) dly_bclk <= BCLK;
always @(negedge MCLK) zero <= BCLK & ~dly_bclk;
always @(posedge MCLK) if (zero) count <= 3'd0; else count <= count + 3'd1;
// count at zero , ref Wert
// 1 : --- always on 5 : 100 001
// 2 : 001 000 6 : 101 010
// 3 : 010 010 7 : 110 011
// 4 : 011 000 8 : 111 100
always @(posedge MCLK) if (zero) refer <= {(count == 3'd7),((count == 3'd5) | (count[1:0] == 2'b10)
always @(posedge MCLK) wr_puls <= (count == refer) | WRCFG;
endmodule
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 4. MMU_MATCH MMU virtual address match detector
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module MMU_MATCH ( USER, READ, WRITE, RMW, MCR_FLAGS, MVALID, VADR_R, MMU_VA, IVAR,
VIRTUELL, MMU_HIT , UPDATE, PROT_ERROR, CI, SEL_PTB1 );
 
input USER;
input READ;
input WRITE;
input RMW;
input [2:0] MCR_FLAGS;
input [31:0] MVALID;
input [31:12] VADR_R;
input [31:16] MMU_VA;
input [1:0] IVAR; // Invalidate Entry
output VIRTUELL; // only for Adress-Mux
output MMU_HIT;
output [31:0] UPDATE;
output reg PROT_ERROR; // if valid must suppress write in Write Buffer and cache
output CI,SEL_PTB1;
reg [15:0] maske;
 
wire adr_space,as_sorte,match,alles_ok;
wire [15:0] val_bits,as_bits;
wire ena_prot;
wire zugriff;
assign zugriff = READ | WRITE;
always @(VADR_R)
case (VADR_R[15:12])
4'h0 : maske = 16'h0001;
4'h1 : maske = 16'h0002;
4'h2 : maske = 16'h0004;
4'h3 : maske = 16'h0008;
4'h4 : maske = 16'h0010;
4'h5 : maske = 16'h0020;
4'h6 : maske = 16'h0040;
4'h7 : maske = 16'h0080;
4'h8 : maske = 16'h0100;
4'h9 : maske = 16'h0200;
4'hA : maske = 16'h0400;
4'hB : maske = 16'h0800;
4'hC : maske = 16'h1000;
4'hD : maske = 16'h2000;
4'hE : maske = 16'h4000;
4'hF : maske = 16'h8000;
endcase
assign VIRTUELL = USER ? MCR_FLAGS[0] : MCR_FLAGS[1];
assign adr_space = IVAR[1] ? IVAR[0] : (MCR_FLAGS[2] & USER); // adr_space = IVARx ? 1 or 0 : DualS
assign as_sorte = ((MVALID[31:16] & maske) != 16'h0);
assign match = (VADR_R[31:20] == MMU_VA[31:20]) & (adr_space == as_sorte) & ((MVALID[15:0] & maske)
assign alles_ok = match & ( ~WRITE | MMU_VA[17] ) & ~PROT_ERROR; // Modified - Flag : reload the PT
// if MMU_HIT = 0 then there is no Write-Buffer access abd no update of cache !
assign MMU_HIT = zugriff ? ( VIRTUELL ? alles_ok : 1'b1 ) : 1'b0 ; // MMU off : then always HIT
 
assign val_bits = IVAR[1] ? (MVALID[15:0] & (match ? ~maske : 16'hFFFF)) : (MVALID[15:0] | maske);
assign as_bits = IVAR[1] ? MVALID[31:16] : (adr_space ? (MVALID[31:16] | maske) : (MVALID[31:16] &
assign UPDATE = {as_bits,val_bits};
 
assign ena_prot = zugriff & VIRTUELL & match;
// A Protection error must suppress write in WB and cache
always @(ena_prot or MMU_VA or USER or WRITE or RMW)
case ({ena_prot,MMU_VA[19:18]})
3'b100 : PROT_ERROR = USER | WRITE | RMW; // Only Supervisor READ
3'b101 : PROT_ERROR = USER; // no USER access
3'b110 : PROT_ERROR = USER & (WRITE | RMW); // USER only READ
default : PROT_ERROR = 1'b0;
endcase
assign CI = VIRTUELL & MMU_VA[16];
assign SEL_PTB1 = adr_space; // For PTE update
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 5. CA_MATCH Cache tag match detector
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module CA_MATCH ( CVALID, IOSEL, ADDR, TAG0, TAG1, CFG, WRITE, MMU_HIT, CI, INVAL_L, KDET, ENDRAM, D
CA_HIT, CA_SET, UPDATE, IO_SPACE, USE_CA, WB_ACC, KILL );
 
input [23:0] CVALID;
input [3:0] IOSEL;
input [27:4] ADDR;
input [27:12] TAG0,TAG1;
input [1:0] CFG; // LDC , DC
input WRITE;
input MMU_HIT;
input CI;
input INVAL_L; // invalid cache line
input KDET;
input ENDRAM;
input DC_ILO; // CBITI/SBITI special case
output CA_HIT;
output CA_SET; // if no Hit then says SET where to store
output [23:0] UPDATE; // Update Information for CVALID memory
output IO_SPACE;
output USE_CA;
output WB_ACC;
output KILL;
reg [7:0] maske;
wire match_0,match_1;
wire valid_0,valid_1;
wire select;
wire clear;
wire [7:0] update_0,update_1,lastinfo;
wire sel_dram;
always @(ADDR)
case (ADDR[6:4])
3'h0 : maske = 8'h01;
3'h1 : maske = 8'h02;
3'h2 : maske = 8'h04;
3'h3 : maske = 8'h08;
3'h4 : maske = 8'h10;
3'h5 : maske = 8'h20;
3'h6 : maske = 8'h40;
3'h7 : maske = 8'h80;
endcase
assign valid_0 = (( CVALID[7:0] & maske) != 8'h00);
assign valid_1 = ((CVALID[15:8] & maske) != 8'h00);
assign match_0 = ( TAG0 == ADDR[27:12] ); // 4KB
assign match_1 = ( TAG1 == ADDR[27:12] ); // 4KB
 
assign CA_HIT = ((valid_0 & match_0) | (valid_1 & match_1)) & ~DC_ILO & CFG[0];
// which SET is written in cache miss ? If both are valid the last used is not taken
assign select = (valid_1 & valid_0) ? ~((CVALID[23:16] & maske) != 8'h00) : valid_0; // Last-used f
assign CA_SET = CA_HIT ? (valid_1 & match_1) : select;
assign clear = INVAL_L | KDET; // INVAL_L is from CINV
assign update_0 = CA_SET ? CVALID[7:0] : (clear ? (CVALID[7:0] & ~maske) : (CVALID[7:0] | maske));
assign update_1 = CA_SET ? (clear ? (CVALID[15:8] & ~maske) : (CVALID[15:8] | maske)) : CVALID[15:8
assign lastinfo = CA_HIT ? (CA_SET ? (CVALID[23:16] | maske) : (CVALID[23:16] & ~maske)) : CVALID[2
assign UPDATE = {lastinfo,update_1,update_0};
assign KILL = clear & CA_HIT & ~CFG[1]; // only if cache is not locked
assign sel_dram = (IOSEL == 4'b0000) & ENDRAM; // at the moment the first 256 MB of memory
assign IO_SPACE = ~sel_dram; // not DRAM or DRAM ist off
assign USE_CA = ~CI & ~DC_ILO & CFG[0] & ~CFG[1]; // CI ? ILO ? Cache on ? Locked Cache ?
assign WB_ACC = WRITE & MMU_HIT & sel_dram;
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 6. DCACHE_SM Data cache state machine
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DCACHE_SM ( BCLK, BRESET, IO_SPACE, MDONE, IO_READY, MMU_HIT, CA_HIT, READ, WRITE, ZTEST, RMW
USE_CA, PTB_WR, PTB_SEL, SEL_PTB1, CPU_OUT, USER, PROT_ERROR, WB_ACC, ENWR, ADR_EQU, IC_PREQ,
RWVAL, VIRTUELL,
DRAM_ACC, DRAM_WR, IO_ACC, IO_RD, IO_WR, PTE_MUX, PD_MUX, PKEEP, PTE_ADR, PTE_DAT, HIT_ALL, A
ABORT, PROTECT, IACC_STAT, ABO_LEVEL1, WR_MRAM, CUPDATE, AUX_DAT, NEW_PTB, PTB_ONE, MMU_DIN,
KDET, DMA_MUX, HLDA, RWVFLAG, PTE_STAT );
 
input BCLK;
input BRESET;
input IO_SPACE;
input MDONE; // Memory Done : feedback from DRAM Controller, BCLK aligned !
input IO_READY;
input MMU_HIT,CA_HIT;
input READ,WRITE,ZTEST,RMW;
input [31:0] CAPDAT;
input [31:12] VADR_R,IC_VA;
input USE_CA;
input PTB_WR,PTB_SEL;
input SEL_PTB1;
input [27:12] CPU_OUT; // used for PTB0/1
input USER;
input PROT_ERROR;
input WB_ACC;
input ENWR; // Enable WRITE from DRAM
input ADR_EQU;
input IC_PREQ;
input FILLRAM;
input [3:0] ICTODC; // multiple signals from ICACHE, especially DMA
input [1:0] RWVAL; // RDVAL+WRVAL Operation
input VIRTUELL; // for RDVAL/WRVAL
output reg DRAM_ACC,DRAM_WR;
output IO_ACC,IO_RD,IO_WR;
output PTE_MUX,PD_MUX,PKEEP;
output [27:0] PTE_ADR;
output [19:0] PTE_DAT;
output HIT_ALL;
output ACC_OK;
output ABORT,PROTECT;
output [3:1] IACC_STAT;
output ABO_LEVEL1;
output WR_MRAM;
output CUPDATE;
output AUX_DAT;
output reg NEW_PTB;
output reg PTB_ONE;
output [23:0] MMU_DIN;
output [1:0] IC_SIGS;
output KOMUX;
output KDET; // Signal for detection of collision
output DMA_MUX;
output HLDA; // active low
output RWVFLAG; // RDVAL/WRVAL result
output [1:0] PTE_STAT;
reg IO_WR,IO_RD;
reg [1:0] pl_dat;
reg [6:0] new_state;
reg [2:0] cap_dat; // only for analyse of timing
reg mem_done;
reg rd_done;
reg [2:0] pstate;
reg pte_run_wr;
reg [1:0] prot_level1;
reg card_flag;
reg [27:12] ptb0,ptb1;
reg write_ok;
reg icp_acc;
reg pte_modi;
reg [2:0] ko_state;
reg dma_run;
reg dma_kdet;
reg rwv_bit;
reg prot_i;
reg rd_rdy;
wire [27:12] ptb10;
wire [31:12] virtual_adr;
wire io_busy;
wire dram_go;
wire pte_sel;
wire pte_acc;
wire do_ca_rd,pte_go,do_ic_p;
wire valid,valid_a,refer,modi;
wire level1,level2;
wire rd_level2;
wire wr_req;
wire wr_dram;
wire wr_icmram;
wire rd_ende;
wire pte_dat_8;
wire pte_wr_sig;
wire run_dc;
wire kostart;
wire dma;
wire dma_go;
wire zugriff;
wire mmu_hit_i;
wire do_zt;
wire zt_ok;
wire [1:0] acc_level;
wire user_ptw,wr_ptw;
wire pte_puls;
always @(posedge BCLK) cap_dat <= CAPDAT[2:0];
// if USER not virtual then ZTEST is quickly done
assign zugriff = READ | WRITE | (ZTEST & VIRTUELL);
assign mmu_hit_i = MMU_HIT & ~ZTEST;
// WB_ACC is a successful WRITE access, ICTODC[0] is coherent Logik release : >=3 entries in FIFO
assign wr_req = WB_ACC & ((ENWR & ICTODC[0]) | (DRAM_WR & ADR_EQU)); // release done by DRAM signal
 
assign rd_ende = CA_HIT | rd_rdy; // CA_HIT only when Cache activ !
always @( zugriff // READ or WRITE or ZTEST , global control
or PROT_ERROR // must not be
//
or IO_SPACE // access of IO world
or io_busy // is access already running ?
//
or mmu_hit_i // Hit in MMU , now only a READ can happen
or READ
or wr_req
or rd_ende // Cache Hit
//
or DRAM_ACC // DRAM Access : shows an active state
or pte_acc // PTE access is running
//
or IC_PREQ // PTE Request from ICACHE
//
or dma // DMA Request
or dma_run ) // DMA running
// #_# #_# #_# #_#
casex ({zugriff,PROT_ERROR,IO_SPACE,io_busy,mmu_hit_i,READ,wr_req,rd_ende,DRAM_ACC,pte_acc,IC_PREQ
// MMU Miss : PTE load from memory , valid too if WRITE and M=0
13'b10_xx_0xxx_x0_x_x0 : new_state = 7'b0001010; // start PTE access
// IO-Address selected : external access starts if not busy because of WRITE
13'b10_10_1xxx_x0_x_x0 : new_state = 7'b0000001;
// DRAM access : Cache Miss at READ :
13'b10_0x_1100_00_x_x0 : new_state = 7'b0010010;
// DRAM access : WRITE
13'b10_0x_101x_x0_x_x0 : new_state = 7'b0000100;
// PTE Request ICACHE , IO access with WRITE is stored - parallel DRAM access possible
13'b0x_xx_xxxx_x0_1_00 : new_state = 7'b0101010; // no access
13'b10_0x_1101_x0_1_x0 : new_state = 7'b0101010; // if successful READ a PTE access can happen i
// DMA access. Attention : no IO-Write access in background and no ICACHE PTE access !
13'b0x_x0_xxxx_xx_0_10 : new_state = 7'b1000000; // DMA access is started
default : new_state = 7'b0;
endcase
assign IO_ACC = new_state[0]; // to load registers for data, addr und BE, signal one pulse
assign dram_go = new_state[1] | rd_level2 ;
assign wr_dram = new_state[2]; // pulse only
assign pte_go = new_state[3];
assign do_ca_rd = new_state[4];
assign do_ic_p = new_state[5];
assign dma_go = new_state[6];
 
// ZTEST logic is for the special case when a write access is crossing page boundaries
assign do_zt = ZTEST & ~icp_acc;
// 0 is pass , 1 is blocked. RWVAL[0] is 1 if WRVAL. Level 1 can only be blocked, otherwise ABORT o
always @(posedge BCLK) if (mem_done) rwv_bit <= level2 ? ~(cap_dat[2] & (~RWVAL[0] | cap_dat[1])) :
assign RWVFLAG = VIRTUELL & rwv_bit;
assign zt_ok = mem_done & (RWVAL[1] ? (~cap_dat[2] | (RWVAL[0] & ~cap_dat[1]) | level2) // Level 2
: (cap_dat[0] & ~prot_i & level2) ); // "normal" access
 
// PTE access logic, normal state machine
// Updates to the PTEs are normal WRITE request to DRAM, therefore no MDONE at Write
assign modi = ~CAPDAT[8] & WRITE & write_ok & ~icp_acc; // is "1" if the Modified Bit must be set
assign refer = CAPDAT[7] | do_zt; // Assumption "R" Bit is set if RDVAL/WRVAL and page border test
assign valid = (do_zt & RWVAL[1]) ? (cap_dat[2] & (cap_dat[1] | ~RWVAL[0]) & cap_dat[0] & level1)
: (cap_dat[0] & ~prot_i);
always @(posedge BCLK) mem_done <= MDONE & pte_acc;
always @(posedge BCLK or negedge BRESET)
if (!BRESET) pstate <= 3'h0;
else
casex ({pte_go,mem_done,valid,refer,modi,pte_run_wr,pstate})
9'b0x_xxxx_000 : pstate <= 3'd0; // nothing to do
9'b1x_xxxx_000 : pstate <= 3'd4; // start
9'bx0_xxxx_100 : pstate <= 3'd4; // wait for Level 1
9'bx1_0xxx_100 : pstate <= 3'd0; // THAT'S ABORT !
9'bx1_11xx_100 : pstate <= 3'd6; // PTE Level 1 was referenced , next is Level 2
9'bx1_10xx_100 : pstate <= 3'd5; // for writing of modified Level 1 : R=1
9'bxx_xxx0_101 : pstate <= 3'd5; // write must wait
9'bxx_xxx1_101 : pstate <= 3'd6; // one wait cycle
9'bx0_xxxx_110 : pstate <= 3'd6; // wait for Level 2
9'bx1_0xxx_110 : pstate <= 3'd0; // THAT'S ABORT !
9'bx1_10xx_110 : pstate <= 3'd7; // Update neccesary : R=0
9'bx1_110x_110 : pstate <= 3'd0; // all ok - end
9'bx1_111x_110 : pstate <= 3'd7; // Update neccesary : M=0
9'bxx_xxx0_111 : pstate <= 3'd7; // write must wait
9'bxx_xxx1_111 : pstate <= 3'd0; // continues to end of DRAM write
default : pstate <= 3'd0;
endcase
assign pte_acc = pstate[2];
assign level1 = ~pstate[1];
assign level2 = pstate[1];
assign valid_a = (ZTEST & RWVAL[1]) ? (cap_dat[2] & (cap_dat[1] | ~RWVAL[0]) & ~cap_dat[0] & level1
: ~cap_dat[0]; // not do_zt because of icp_acc in ABORT
 
assign ABORT = mem_done & valid_a & ~icp_acc;
assign PROTECT = ((mem_done & prot_i & ~icp_acc) | PROT_ERROR) & ~(ZTEST & RWVAL[1]); // no Protec
 
assign IACC_STAT[1] = mem_done & ~cap_dat[0] & icp_acc;
assign IACC_STAT[2] = level1;
assign IACC_STAT[3] = mem_done & prot_i & icp_acc;
 
assign ABO_LEVEL1 = level1; // is stored in case of ABORT in ADDR_UNIT
assign rd_level2 = (pstate == 3'd5) | (mem_done & (pstate == 3'd4) & refer & valid);
 
assign WR_MRAM = mem_done & (pstate == 3'd6) & valid & ~icp_acc & ~ZTEST;
assign wr_icmram = mem_done & (pstate == 3'd6) & valid & icp_acc;
// Signals to the Instruction Cache
// pte_acc combined with icp_acc for STATISTIK.
assign IC_SIGS = {(pte_acc & icp_acc),wr_icmram};
assign PTE_MUX = pte_go | (pte_acc & ~pstate[1]);
 
assign pte_puls = mem_done & pte_acc & ~pstate[1];
assign PTE_STAT = {(pte_puls & icp_acc),(pte_puls & ~icp_acc)}; // only for statistic
assign PD_MUX = ((pstate == 3'd4) & mem_done & valid & ~refer) // switch data-MUX, write level 1
| ((pstate == 3'd6) & mem_done & valid & (~refer | modi)) // write level 2
| (((pstate == 3'd5) | (pstate == 3'd7)) & ~pte_run_wr);
 
assign pte_wr_sig = ENWR & PD_MUX;
always @(posedge BCLK) pte_run_wr <= pte_wr_sig; // Ok-Signal for pstate State-machine
assign PKEEP = (pstate == 3'd6) | ((pstate == 3'd7) & ~pte_run_wr); // keep the DRAM address
// If there is a PTE still in the data cache it must be deleted. If MMU Bits are set by the pte eng
// READ would deliver wrong data if cache hit. Therefore access of the Tags.
always @(posedge BCLK or negedge BRESET)
if (!BRESET) ko_state <= 3'b000;
else
casex ({kostart,ko_state})
4'b0_000 : ko_state <= 3'b000;
4'b1_000 : ko_state <= 3'b110;
4'bx_110 : ko_state <= 3'b111;
4'bx_111 : ko_state <= 3'b100;
4'bx_100 : ko_state <= 3'b000;
default : ko_state <= 3'b000;
endcase
assign kostart = pte_go | rd_level2;
assign run_dc = ~ko_state[2] & ~dma_run;
assign KOMUX = ko_state[1] | DMA_MUX;
assign KDET = ko_state[0] | dma_kdet;
assign HIT_ALL = MMU_HIT & CA_HIT & run_dc & ~pte_acc; // for Update "Last-Set" , MMU_HIT contains
always @(posedge BCLK or negedge BRESET)
if (!BRESET) card_flag <= 1'b0;
else card_flag <= (do_ca_rd & ~rd_rdy) | (card_flag & ~MDONE);
assign CUPDATE = card_flag & USE_CA & MDONE;
 
always @(posedge BCLK) rd_rdy <= card_flag & MDONE;
// The cache RAM can not provide fast enough the data after an Update. In this case a secondary dat
assign AUX_DAT = rd_rdy;
// DRAM interface :
 
always @(posedge BCLK) DRAM_WR <= wr_dram | pte_wr_sig; // pulse
always @(posedge BCLK) if (dram_go) DRAM_ACC <= 1'b1;
else
DRAM_ACC <= DRAM_ACC & ~MDONE & BRESET;
// IO interface :
always @(posedge BCLK)
begin
if (IO_ACC) IO_RD <= READ; else IO_RD <= IO_RD & ~IO_READY & BRESET;
if (IO_ACC) IO_WR <= WRITE; else IO_WR <= IO_WR & ~IO_READY & BRESET;
end
assign io_busy = IO_RD | IO_WR | rd_done; // access is gone in next clock cycle, therefore blocked
always @(posedge BCLK) rd_done <= IO_RD & IO_READY; // For READ one clock later for data to come th
assign dma = ICTODC[2]; // external request HOLD after FF in ICACHE
always @(posedge BCLK) dma_run <= (dma_go | (dma_run & dma)) & BRESET; // stops the data access unt
assign HLDA = ~(ICTODC[1] & dma_run); // Signal for system that the CPU has stopped accesses
always @(posedge BCLK) dma_kdet <= FILLRAM;
assign DMA_MUX = FILLRAM | dma_kdet;
// global feedback to ADDR_UNIT, early feedback to Op-Dec : you can continue
assign ACC_OK = ZTEST ? (~VIRTUELL | zt_ok)
: (IO_SPACE ? ((IO_ACC & WRITE) | rd_done) : (wr_dram | (READ & MMU_HIT & rd_ende & run_dc))
// PTB1 and PTB0
always @(posedge BCLK) if (PTB_WR && !PTB_SEL) ptb0 <= CPU_OUT[27:12];
always @(posedge BCLK) if (PTB_WR && PTB_SEL) ptb1 <= CPU_OUT[27:12];
always @(posedge BCLK) NEW_PTB <= PTB_WR; // to MMU Update Block
always @(posedge BCLK) if (PTB_WR) PTB_ONE <= PTB_SEL;
assign ptb10 = SEL_PTB1 ? ptb1 : ptb0;
// Address multiplex between ICACHE=1 and DCACHE=0 :
always @(posedge BCLK) if (pte_go) icp_acc <= do_ic_p;
assign pte_sel = pte_go ? do_ic_p : icp_acc;
assign virtual_adr = pte_sel ? IC_VA : VADR_R;
// The 2 Address-LSB's : no full access : USE_CA = 0
assign PTE_ADR = rd_level2 ? {CAPDAT[27:12],virtual_adr[21:12],2'b00} : {ptb10,virtual_adr[31:22],2
// PTE_DAT[8] is used for update of MMU_RAM.
assign pte_dat_8 = (level2 & WRITE & write_ok & ~icp_acc) | CAPDAT[8];
always @(posedge BCLK) pte_modi = pte_dat_8;
assign PTE_DAT = {4'h3,CAPDAT[15:9],pte_modi,1'b1,CAPDAT[6:0]}; // the top 4 bits are Byte-Enable
// The data for the MMU-RAM : 24 Bits , [6]=Cache Inhibit
assign MMU_DIN = {pl_dat,pte_dat_8,CAPDAT[6],CAPDAT[31:12]};
// Protection field
always @(posedge BCLK) if (mem_done && (pstate[2:0] == 3'd4)) prot_level1 <= cap_dat[2:1];
 
always @(prot_level1 or cap_dat)
casex ({prot_level1,cap_dat[2]})
3'b11_x : pl_dat = cap_dat[2:1];
3'b10_1 : pl_dat = 2'b10;
3'b10_0 : pl_dat = cap_dat[2:1];
3'b01_1 : pl_dat = 2'b01;
3'b01_0 : pl_dat = cap_dat[2:1];
3'b00_x : pl_dat = 2'b00;
endcase
always @(USER or pl_dat) // is used if no PTE update is neccesary for M-Bit if writing is not allow
casex ({USER,pl_dat})
3'b1_11 : write_ok = 1'b1;
3'b0_1x : write_ok = 1'b1;
3'b0_01 : write_ok = 1'b1;
default : write_ok = 1'b0;
endcase
assign acc_level = level2 ? pl_dat : cap_dat[2:1];
assign user_ptw = icp_acc ? ICTODC[3] : USER;
assign wr_ptw = ~icp_acc & (WRITE | RMW | (ZTEST & ~RWVAL[1])); // only data cache can write
always @(acc_level or user_ptw or wr_ptw)
case (acc_level)
2'b00 : prot_i = user_ptw | wr_ptw;
2'b01 : prot_i = user_ptw;
2'b10 : prot_i = user_ptw & wr_ptw;
2'b11 : prot_i = 1'b0;
endcase
endmodule
 
/trunk/rtl/example.v
0,0 → 1,209
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: example.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// example Your first system with the M32632 CPU
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module example ( CLK, RESET_N, NMI_N, INT_N, IN_REG, OUT_REG);
 
input CLK;
input RESET_N;
input NMI_N;
input INT_N;
 
input [7:0] IN_REG;
 
output [7:0] OUT_REG;
 
reg nmi_reg,int_reg;
 
wire IC_MDONE;
wire DC_MDONE;
wire ENWR;
wire WAMUX;
wire [11:2] WADDR;
wire [31:0] DRAM_Q;
wire [2:0] IWCTRL;
wire [2:0] DWCTRL;
wire IC_ACC;
wire [27:0] IDRAM_ADR;
wire DC_ACC;
wire DC_WR;
wire [27:0] DRAM_ADR;
wire [35:0] DRAM_DI;
 
wire [31:0] IO_A;
wire [31:0] IO_DI;
wire [3:0] IO_BE;
wire IO_RD;
wire IO_WR;
wire IO_READY;
wire ENDRAM;
wire [31:0] IO_Q;
wire W_OUT_REG;
wire RST_N;
 
wire [31:0] BOOT_DAT;
wire [31:0] STAT_DAT;
wire [7:0] IN_DAT;
 
wire [7:0] STATSIGS;
wire COP_GO;
wire [23:0] COP_OP;
wire [127:0] COP_OUT;
wire COP_DONE;
wire [63:0] COP_IN;
 
M32632 CPU(
// ++++++++++ Basic Signals
.BCLK(CLK),
.MCLK(~CLK),
.WRCFG(1'b1),
.BRESET(RST_N),
.NMI_N(nmi_reg),
.INT_N(int_reg),
.STATUS(),
.ILO(),
.STATSIGS(STATSIGS),
// +++++++++ General Purpose Interface
.IO_WR(IO_WR),
.IO_RD(IO_RD),
.IO_A(IO_A),
.IO_BE(IO_BE),
.IO_DI(IO_DI),
.IO_Q(IO_Q),
.IO_READY(IO_READY),
// +++++++++ DRAM Interface In
.ENDRAM(ENDRAM),
.IC_MDONE(IC_MDONE),
.DC_MDONE(DC_MDONE),
.ENWR(ENWR),
.WAMUX(WAMUX),
.WADDR(WADDR),
.DRAM_Q(DRAM_Q),
.DWCTRL(DWCTRL),
.IWCTRL(IWCTRL),
// +++++++++ DRAM Interface Out
.IC_ACC(IC_ACC),
.IDRAM_ADR(IDRAM_ADR),
.DC_ACC(DC_ACC),
.DC_WR(DC_WR),
.DRAM_ADR(DRAM_ADR),
.DRAM_DI(DRAM_DI),
// ++++++++++ DMA Interface
.HOLD(1'b1),
.HLDA(),
.FILLRAM(1'b0),
.DMA_AA(24'd0),
// ++++++++++ Coprocessor Interface
.COP_GO(COP_GO),
.COP_OP(COP_OP),
.COP_OUT(COP_OUT),
.COP_DONE(COP_DONE),
.COP_IN(COP_IN));
ex_io_bus_ctrl u_bus_ctrl(
.CLK(CLK),
.RESET_N(RESET_N),
.RST_N(RST_N),
.ENDRAM(ENDRAM),
.IO_WR(IO_WR),
.IO_RD(IO_RD),
.IO_A(IO_A[31:28]),
.IO_BE(IO_BE),
.IO_Q(IO_Q),
.IO_READY(IO_READY),
.W_OUT_REG(W_OUT_REG),
.IN_DAT(IN_DAT),
.BOOT_DAT(BOOT_DAT),
.STAT_DAT(STAT_DAT));
 
ex_in_reg u_in_reg(
.CLK(CLK),
.IN_REG(IN_REG),
.IN_DAT(IN_DAT));
ex_out_reg u_out_reg(
.CLK(CLK),
.OUT_REG(OUT_REG),
.W_OUT_REG(W_OUT_REG),
.DIN(IO_DI));
ex_boot_rom u_boot_rom(
.CLK(CLK),
.ADDR(IO_A[9:2]),
.DATA(BOOT_DAT));
 
ex_statcou u_statcou(
.CLK(CLK),
.RST_N(RST_N),
.STATSIGS(STATSIGS),
.ADDR(IO_A[4:2]),
.DATA(STAT_DAT));
 
ex_copro u_copro(
.CLK(CLK),
.COP_GO(COP_GO),
.COP_OP(COP_OP),
.COP_INP(COP_OUT),
.COP_DONE(COP_DONE),
.COP_OUTP(COP_IN));
ex_dram_emul u_dram_emul(
.MCLK(CLK),
.RST_N(RST_N),
.IC_ACC(IC_ACC),
.IDRAM_ADR(IDRAM_ADR),
.DC_ACC(DC_ACC),
.DC_WR(DC_WR),
.DRAM_ADR(DRAM_ADR),
.DRAM_DI(DRAM_DI),
.IC_MDONE(IC_MDONE),
.DC_MDONE(DC_MDONE),
.ENWR(ENWR),
.WAMUX(WAMUX),
.WADDR(WADDR),
.MEM_Q(DRAM_Q),
.DWCTRL(DWCTRL),
.IWCTRL(IWCTRL) );
 
always @(posedge CLK) // recommended to synchronize this signals
begin
nmi_reg <= NMI_N;
int_reg <= INT_N;
end
 
endmodule
/trunk/rtl/M32632.v
0,0 → 1,445
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: M32632.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// M32632 The top level of M32632
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module M32632( BCLK, MCLK, WRCFG, BRESET, NMI_N, INT_N, STATUS, ILO, STATSIGS,
IO_WR, IO_RD, IO_A, IO_BE, IO_DI, IO_Q, IO_READY,
ENDRAM, IC_MDONE, DC_MDONE, ENWR, WAMUX, WADDR, DRAM_Q, DWCTRL, IWCTRL,
IC_ACC, IDRAM_ADR, DC_ACC, DC_WR, DRAM_ADR, DRAM_DI,
HOLD, HLDA, FILLRAM, DMA_AA,
COP_GO, COP_OP, COP_OUT, COP_DONE, COP_IN );
 
// ++++++++++ Basic Signals
input BCLK; // Basic Clock for everything
input MCLK; // Memory Clock, used in Caches
input WRCFG;
input BRESET;
input NMI_N;
input INT_N;
output [3:0] STATUS;
output ILO;
output [7:0] STATSIGS;
// +++++++++ General Purpose Interface
output IO_WR;
output IO_RD;
output [31:0] IO_A;
output [3:0] IO_BE;
output [31:0] IO_DI;
input [31:0] IO_Q;
input IO_READY;
// +++++++++ DRAM Interface In
input ENDRAM;
input IC_MDONE;
input DC_MDONE;
input ENWR;
input WAMUX;
input [11:2] WADDR;
input [31:0] DRAM_Q;
input [2:0] DWCTRL;
input [2:0] IWCTRL;
// +++++++++ DRAM Interface Out
output IC_ACC;
output [27:0] IDRAM_ADR;
output DC_ACC;
output DC_WR;
output [27:0] DRAM_ADR;
output [35:0] DRAM_DI;
// ++++++++++ DMA Interface
input HOLD;
output HLDA;
input FILLRAM;
input [27:4] DMA_AA;
// ++++++++++ Coprocessor Interface
output COP_GO;
output [23:0] COP_OP;
output [127:0] COP_OUT;
input COP_DONE;
input [63:0] COP_IN;
 
wire ACC_DONE;
wire [5:0] ACC_STAT;
wire [12:0] CFG;
wire [3:0] CINV;
wire DATA_HOLD;
wire DC_INIT;
wire Y_INIT;
wire DONE;
wire [63:0] DP_Q;
wire [3:0] IACC_STAT;
wire PROT_ERROR;
wire [2:0] GENSTAT;
wire IC_INIT;
wire IC_PREQ;
wire IC_READ;
wire [1:0] IC_SIGS;
wire IC_USER;
wire [31:12] IC_VA;
wire [3:0] ICTODC;
wire [6:0] INFO_AU;
wire [1:0] IVAR;
wire KDET;
wire [27:4] KOLLI_A;
wire [3:0] MCR;
wire [23:0] MMU_DIN;
wire [11:0] PSR;
wire PTB_SEL;
wire PTB_WR;
wire READ;
wire WRITE;
wire ZTEST;
wire RMW;
wire [2:0] RWVAL;
wire RWVFLAG;
wire [3:0] D_IOBE;
wire D_IORDY;
wire REG_OUT;
wire [3:0] PACKET;
wire [1:0] SIZE;
wire [31:0] VADR;
wire WREN_REG;
wire LD_DIN;
wire LD_IMME;
wire WR_REG;
wire [14:0] ACC_FELD;
wire [31:0] DIN;
wire [31:0] DISP;
wire [2:0] IC_TEX;
wire [31:0] IMME_Q;
wire [1:0] LD_OUT;
wire [12:0] DETOIP;
wire [1:0] MMU_UPDATE;
wire [10:0] OPER;
wire [31:0] PC_ARCHI;
wire [31:0] PC_ICACHE;
wire [7:0] RDAA;
wire [7:0] RDAB;
wire [1:0] START;
wire [1:0] WMASKE;
wire [5:0] WRADR;
wire I_IORDY;
wire ACB_ZERO;
wire DC_ABORT;
wire SAVE_PC;
wire [31:0] IC_DIN;
wire [31:0] PC_NEW;
wire [4:0] STRING;
wire [5:0] TRAPS;
wire I_IORD;
wire D_IOWR;
wire D_IORD;
wire [31:0] D_IOA;
wire [31:0] I_IOA;
wire ENA_HK;
wire STOP_CINV;
wire KOLLISION;
wire ILO_SIG;
wire [1:0] PTE_STAT;
wire DBG_HIT;
wire [40:2] DBG_IN;
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// The Data Cache
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DCACHE ARMS(
.MCLK(MCLK),
.BCLK(BCLK),
.WRCFG(WRCFG),
.BRESET(BRESET),
.PTB_WR(PTB_WR),
.PTB_SEL(PTB_SEL),
.MDONE(DC_MDONE),
.IO_READY(D_IORDY),
.REG_OUT(REG_OUT),
.PSR_USER(INFO_AU[1]),
.WRITE(WRITE),
.READ(READ),
.ZTEST(ZTEST),
.RMW(RMW),
.WAMUX(WAMUX),
.ENWR(ENWR),
.IC_PREQ(IC_PREQ),
.FILLRAM(FILLRAM),
.CFG(CFG[10:9]),
.ENDRAM(ENDRAM),
.CINVAL(CINV[1:0]),
.DMA_AA(DMA_AA),
.DP_Q(DP_Q),
.DRAM_Q(DRAM_Q),
.IC_VA(IC_VA),
.ICTODC(ICTODC),
.IO_Q(IO_Q),
.IVAR(IVAR),
.MCR_FLAGS(MCR),
.PACKET(PACKET),
.SIZE(SIZE),
.VADR(VADR),
.WADDR(WADDR),
.WCTRL(DWCTRL),
.DRAM_ACC(DC_ACC),
.DRAM_WR(DC_WR),
.IO_RD(D_IORD),
.IO_WR(D_IOWR),
.INIT_RUN(DC_INIT),
.KDET(KDET),
.HLDA(HLDA),
.ACC_STAT(ACC_STAT),
.DP_DI(DIN),
.DRAM_A(DRAM_ADR),
.DRAM_DI(DRAM_DI),
.IACC_STAT(IACC_STAT[3:1]),
.IC_SIGS(IC_SIGS),
.IO_A(D_IOA),
.IO_BE(D_IOBE),
.IO_DI(IO_DI),
.PTE_STAT(PTE_STAT),
.DBG_HIT(DBG_HIT),
.DBG_IN(DBG_IN),
.KOLLI_A(KOLLI_A),
.MMU_DIN(MMU_DIN),
.RWVAL(RWVAL),
.RWVFLAG(RWVFLAG));
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// The Datapath
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DATENPFAD STOMACH(
.WREN(WREN_REG),
.BRESET(BRESET),
.BCLK(BCLK),
.IO_READY(D_IORDY),
.LD_DIN(LD_DIN),
.LD_IMME(LD_IMME),
.WR_REG(WR_REG),
.IC_USER(IC_USER),
.ACC_FELD(ACC_FELD),
.ACC_STAT(ACC_STAT),
.DIN(DIN),
.DISP(DISP),
.IC_TEX(IC_TEX),
.IMME_Q(IMME_Q),
.INFO_AU(INFO_AU),
.LD_OUT(LD_OUT),
.DETOIP(DETOIP),
.MMU_UPDATE(MMU_UPDATE),
.OPER(OPER),
.PC_ARCHI(PC_ARCHI),
.PC_ICACHE(PC_ICACHE),
.RDAA(RDAA),
.RDAB(RDAB),
.START(START),
.WMASKE(WMASKE),
.WRADR(WRADR),
.READ_OUT(READ),
.WRITE_OUT(WRITE),
.ZTEST(ZTEST),
.RMW(RMW),
.ACC_DONE(ACC_DONE),
.REG_OUT(REG_OUT),
.Y_INIT(Y_INIT),
.DONE(DONE),
.PTB_WR(PTB_WR),
.PTB_SEL(PTB_SEL),
.ACB_ZERO(ACB_ZERO),
.ABORT(DC_ABORT),
.SAVE_PC(SAVE_PC),
.CFG(CFG),
.CINV(CINV),
.DP_Q(DP_Q),
.IVAR(IVAR),
.MCR(MCR),
.PACKET(PACKET),
.PC_NEW(PC_NEW),
.PSR(PSR),
.SIZE(SIZE),
.STRING(STRING),
.TRAPS(TRAPS),
.VADR(VADR),
.RWVFLAG(RWVFLAG),
.DBG_HIT(DBG_HIT),
.DBG_IN(DBG_IN),
.COP_DONE(COP_DONE),
.COP_OP(COP_OP),
.COP_IN(COP_IN),
.COP_GO(COP_GO),
.COP_OUT(COP_OUT));
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// The Instruction Cache
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ICACHE LEGS(
.MCLK(MCLK),
.BCLK(BCLK),
.BRESET(BRESET),
.PTB_WR(PTB_WR),
.PTB_SEL(PTB_SEL),
.MDONE(IC_MDONE),
.IO_READY(I_IORDY),
.READ_I(IC_READ),
.PSR_USER(IC_USER),
.DATA_HOLD(DATA_HOLD),
.DRAM_WR(DC_WR),
.KDET(KDET),
.HOLD(HOLD),
.CFG(CFG[12:11]),
.ENDRAM(ENDRAM),
.DRAM_Q(DRAM_Q),
.CINVAL(CINV[3:2]),
.IC_SIGS(IC_SIGS),
.IO_Q(IO_Q),
.IVAR(IVAR),
.KOLLI_A(KOLLI_A),
.MCR_FLAGS(MCR),
.MMU_DIN(MMU_DIN),
.VADR(PC_ICACHE),
.WADDR(WADDR),
.WCTRL(IWCTRL),
.DRAM_ACC(IC_ACC),
.IO_RD(I_IORD),
.INIT_RUN(IC_INIT),
.PROT_ERROR(PROT_ERROR),
.ACC_OK(IACC_STAT[0]),
.IC_PREQ(IC_PREQ),
.KOLLISION(KOLLISION),
.DRAM_A(IDRAM_ADR),
.IC_DQ(IC_DIN),
.IC_VA(IC_VA),
.ICTODC(ICTODC),
.ENA_HK(ENA_HK),
.STOP_CINV(STOP_CINV),
.IO_A(I_IOA));
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// The Control Unit
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STEUERUNG BRAIN(
.BCLK(BCLK),
.BRESET(BRESET),
.DC_ACC_DONE(ACC_DONE),
.ACB_ZERO(ACB_ZERO),
.DONE(DONE),
.NMI_N(NMI_N),
.INT_N(INT_N),
.DC_ABORT(DC_ABORT),
.IC_INIT(IC_INIT),
.DC_INIT(DC_INIT),
.Y_INIT(Y_INIT),
.SAVE_PC(SAVE_PC),
.CFG(CFG[8:0]),
.IACC_STAT(IACC_STAT),
.PROT_ERROR(PROT_ERROR),
.IC_DIN(IC_DIN),
.PC_NEW(PC_NEW),
.PSR(PSR),
.STRING(STRING),
.TRAPS(TRAPS),
.IC_READ(IC_READ),
.DATA_HOLD(DATA_HOLD),
.LD_DIN(LD_DIN),
.LD_IMME(LD_IMME),
.WREN(WREN_REG),
.WR_REG(WR_REG),
.GENSTAT(GENSTAT),
.IC_USER(IC_USER),
.ACC_FELD(ACC_FELD),
.DISP(DISP),
.IC_TEX(IC_TEX),
.IMME_Q(IMME_Q),
.INFO_AU(INFO_AU),
.LD_OUT(LD_OUT),
.DETOIP(DETOIP),
.MMU_UPDATE(MMU_UPDATE),
.OPER(OPER),
.PC_ARCHI(PC_ARCHI),
.PC_ICACHE(PC_ICACHE),
.RDAA(RDAA),
.RDAB(RDAB),
.START(START),
.WMASKE(WMASKE),
.WRADR(WRADR),
.ENA_HK(ENA_HK),
.STOP_CINV(STOP_CINV),
.COP_OP(COP_OP),
.ILO(ILO_SIG),
.RWVAL(RWVAL));
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// The Input/Output Interface
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IO_SWITCH ISWITCH(
.I_IORD(I_IORD),
.D_IOWR(D_IOWR),
.IO_READY(IO_READY),
.D_IORD(D_IORD),
.D_IOBE(D_IOBE),
.BRESET(BRESET),
.BCLK(BCLK),
.GENSTAT(GENSTAT),
.D_IOA(D_IOA),
.I_IOA(I_IOA),
.D_IORDY(D_IORDY),
.I_IORDY(I_IORDY),
.IO_RD(IO_RD),
.IO_WR(IO_WR),
.IO_BE(IO_BE),
.ILO_SIG(ILO_SIG),
.ILO(ILO),
.IO_A(IO_A),
.DCWACC({DC_WR,DC_ACC}),
.STATUS(STATUS));
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// The Statistic Signal Generator
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MAKE_STAT MKSTAT(
.BCLK(BCLK),
.READ(READ),
.DACC_OK(ACC_STAT[0]),
.KOLLISION(KOLLISION),
.DC_ACC(DC_ACC),
.DPTE_ACC(PTE_STAT[0]),
.DC_MDONE(DC_MDONE),
.DRAM_WR(DC_WR),
.IC_READ(IC_READ),
.IACC_OK(IACC_STAT[0]),
.IC_ACC(IC_ACC),
.IPTE_ACC(PTE_STAT[1]),
.IC_MDONE(IC_MDONE),
.DATA_HOLD(DATA_HOLD),
.STATSIGS(STATSIGS));
 
endmodule
/trunk/rtl/SP_FPU.v
0,0 → 1,472
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: SP_FPU.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// 1. ADDSUB Adder and Subtractor for 36 bit
// 2. SFPU_ADDSUB Single Precision Floating Point Adder/Subtractor and Converter
// 3. SFPU_MUL Single Precision Floating Point Multiplier
// 4. SP_FPU Top Level of Single Precision Floating Point Unit
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. ADDSUB Adder and Subtractor for 36 bit
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module ADDSUB (dataa, datab, add_sub, result);
 
input [35:0] dataa,datab;
input add_sub; // 1 = Addition , 0 = Subtraction
output [35:0] result;
assign result = dataa + (add_sub ? datab : ~datab) + {35'd0,~add_sub};
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. SFPU_ADDSUB Single Precision Floating Point Adder/Subtractor and Converter
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module SFPU_ADDSUB ( SRC1, SRC2, NZEXP, BWD, SELECT, OUT, IOUT, CMPRES );
 
input [31:0] SRC1,SRC2; // Input data
input [2:1] NZEXP;
input [1:0] BWD; // size of integer
input [3:0] SELECT;
 
output [36:0] OUT; // the result
output [31:0] IOUT; // result of ROUNDFi/TRUNCFi/FLOORFi
output [1:0] CMPRES;
 
// ++++++++++++++++++++++++++++++++++
// MOViF : 1. step
reg [31:8] movdat;
wire [31:0] movif;
 
always @(BWD or SRC1)
casex({BWD,SRC1[15],SRC1[7]})
4'b00x0 : movdat = 24'h0000_00; // Byte
4'b00x1 : movdat = 24'hFFFF_FF;
4'b010x : movdat = {16'h0000,SRC1[15:8]}; // Word
4'b011x : movdat = {16'hFFFF,SRC1[15:8]};
default : movdat = SRC1[31:8]; // Double
endcase
assign movif = movdat[31] ? (32'h0 - {movdat,SRC1[7:0]}) : {movdat,SRC1[7:0]};
// -2^31 is kept
// ROUNDFi/TRUNCFi/FLOORFi : 1. step
reg ovflag,ovflag2;
wire [8:0] rexdiff,rexo;
wire rovfl,minint;
wire ganzklein; // Flag for 0
assign rexdiff = 9'h09D - {1'b0,SRC1[30:23]}; // 4..0 is the right shift value
assign rovfl = (ovflag | ovflag2) & (SELECT[1:0] == 2'b11) & ~minint;
assign ganzklein = (~rexdiff[8] & (rexdiff[7:5] != 3'b000)); // 0 is implicit via SRC1[30:23]=0
// Detection of Overflow
assign rexo = ({1'b0,SRC1[30:23]} - {8'h3F,~BWD[1]}); // subtract B/W = 7F , D = 7E
always @(BWD or rexo)
casex (BWD)
2'b00 : ovflag = (~rexo[8] & (rexo[7:3] != 5'h0)); // Exponent 0..7 because of -128.4 => -128
2'b01 : ovflag = (~rexo[8] & (rexo[7:4] != 4'h0)); // Exponent 0..15 because of -128.4 => -128
default : ovflag = (~rexo[8] & (rexo[7:5] != 3'h0)); // Exponent only 0..30
endcase
assign minint = (SRC1 == 32'hCF00_0000) & BWD[1]; // detection of -2^31
// ++++++++++++++++++++++++++++++++++
// ADD/SUB : 1. step : which operand ist bigger ? if required exchange
// SUB/CMP : SRC2 - SRC1
wire [8:0] exdiff;
wire [23:0] madiff;
wire switch,sign,sign1,sign2;
wire variante;
wire vorz,addflag;
wire [35:0] result_sw,result_nosw;
wire [24:0] value1,value2;
wire [35:0] result;
assign exdiff = {1'b0,SRC2[30:23]} - {1'b0,SRC1[30:23]}; // Difference of Exponents
assign madiff = {1'b0,SRC2[22:0]} - {1'b0,SRC1[22:0]}; // Difference of Mantissas
// if exdiff = 0 the shifter to the right is not needed !
assign variante = (exdiff[8:1] == 8'h00) | (exdiff == 9'h1FF) | SELECT[1]; // MUX at the end, ROUND
// ++++++++++++++++++++++++++ 1. case works on MOViF +++++++++++++++++++++++++++++++++++++++
 
assign switch = exdiff[8] | ((exdiff[7:0] == 8'h0) & madiff[23]); // exchange ?
 
assign value1 = exdiff[0] ? {1'b0,NZEXP[1],SRC1[22:0]} : {NZEXP[1],SRC1[22:0],1'b0};
assign value2 = exdiff[0] ? {1'b0,NZEXP[2],SRC2[22:0]} : {NZEXP[2],SRC2[22:0],1'b0};
// The Subtraction needs 3 Guard-Bits after LSB for rounding ! 36 Bit wide
// 1
ADDSUB addsub_nosw (.dataa({1'b0,SRC2[30:23],NZEXP[2],SRC2[22:0],3'b000}),
.datab({9'h0,value1,2'b0}), .add_sub(addflag),
.result(result_nosw) );
 
ADDSUB addsub_sw (.dataa({1'b0,SRC1[30:23],NZEXP[1],SRC1[22:0],3'b000}),
.datab({9'h0,value2,2'b0}), .add_sub(addflag),
.result(result_sw) );
 
assign result = switch ? result_sw : result_nosw;
// SRC2 SRC1 : switch = 0 SRC2 SRC1 : switch = 1
// 5 + 3 : +(5 + 3) = 8 3 + 5 : +(5 + 3) = 8 SELECT[0] = 0
// 5 + (-3) : +(5 - 3) = 2 3 + (-5) : -(5 - 3) = -2
// (-5) + 3 : -(5 - 3) = -2 (-3) + 5 : +(5 - 3) = 2
// (-5) + (-3) : -(5 + 3) = -8 (-3) + (-5) : -(5 + 3) = -8
// 5 - 3 : +(5 - 3) = 2 3 - 5 : -(5 - 3) = -2 SELECT[0] = 1
// 5 - (-3) : +(5 + 3) = 8 3 - (-5) : +(5 + 3) = 8
// (-5) - 3 : -(5 + 3) = -8 (-3) - 5 : -(5 + 3) = -8
// (-5) - (-3) : -(5 - 3) = -2 (-3) - (-5) : +(5 - 3) = 2
assign sign1 = SRC1[31];
assign sign2 = SRC2[31];
assign vorz = switch ? (SELECT[0] ^ sign1) : sign2;
assign addflag = ~(SELECT[0] ^ (sign1 ^ sign2));
 
// CMPF : 1. step : what happend if Invalid Operand occurs - no Flag update !
assign CMPRES[1] = ~CMPRES[0] & (switch ? ~sign1 : sign2); // see table above : N-Bit=1 if SRC1 >
assign CMPRES[0] = (SRC1 == SRC2) | (~NZEXP[2] & ~NZEXP[1]); // Z-Bit : SRC1=SRC2, +0.0 = -0.0
// ++++++++++++++++++++++++++++++++++
// ADD/SUB : 3. step : prepare of Barrelshifter Left
wire [31:0] blshift;
wire [9:0] shiftl;
wire shift_16;
wire [33:0] add_q;
wire [31:0] muxsrc2;
wire [1:0] inex;
assign blshift = SELECT[1] ? movif : {result[26:0],5'h00}; // Feeding of MOViF
 
assign shiftl = SELECT[1] ? 10'h09E : {1'b0,result[35:27]}; // MOViF
 
assign shift_16 = (blshift[31:16] == 16'h0000);
 
// In case of ADD the result bypasses the Barrelshifter left
assign add_q = (muxsrc2[24] != result[27]) ? {result[35:3],(result[2:0] != 3'b000)}
: {result[35:27],result[25:2],(result[1:0] != 2'b00)} ;
// ++++++++++++++++++++++++++++++++++
// ADD/SUB : 4. step : Barrelshifter left for SUB and MOViF :
wire shift_8,shift_4,shift_2,shift_1,zero;
wire [1:0] lsb_bl;
wire [31:0] blshifta,blshiftb,blshiftc,blshiftd,blshifte;
wire [9:0] expol;
wire [36:0] out_v1;
assign blshifta = shift_16 ? {blshift[15:0],16'h0000} : blshift;
assign shift_8 = (blshifta[31:24] == 8'h00);
assign blshiftb = shift_8 ? {blshifta[23:0],8'h00} : blshifta;
assign shift_4 = (blshiftb[31:28] == 4'h0);
assign blshiftc = shift_4 ? {blshiftb[27:0],4'h0} : blshiftb;
assign shift_2 = (blshiftc[31:30] == 2'b00);
assign blshiftd = shift_2 ? {blshiftc[29:0],2'b00} : blshiftc;
assign shift_1 = ~blshiftd[31];
assign blshifte = shift_1 ? {blshiftd[30:0],1'b0} : blshiftd;
// Overflow at ROUNDFi/TRUNCFi/FLOORFi via overflow in exponent shown, SELECT[1] is then 1 !
assign expol = (shiftl - {5'h00,shift_16,shift_8,shift_4,shift_2,shift_1}) | {1'b0,rovfl,8'h00};
// Inexact at ROUNDFi/TRUNCFi/FLOORFi : evaluation for all one level higher
assign lsb_bl = (SELECT[1:0] == 2'b11) ? inex : {blshifte[7],(blshifte[6:0] != 7'h00)};
assign zero = (~SELECT[1] & ~NZEXP[2] & ~NZEXP[1])
| ((blshift == 32'h0) & ((~addflag & ~SELECT[1]) | (SELECT[1:0] == 2'b10)));
assign sign = SELECT[1] ? movdat[31] : vorz;
assign out_v1 = (addflag & ~SELECT[1]) ? {zero,sign,1'b0,add_q}
: {zero,sign,expol,blshifte[30:8],lsb_bl};
// +++++++++++++++++++++++++ 2. case works on ROUND/TRUNC/FLOOR ++++++++++++++++++++++++++++++++++
 
wire vswitch;
wire [4:0] shift1,shift2;
wire [8:0] exdiff12;
wire [23:0] muxsrc1;
wire [32:9] pipe1; // numbering special for Right Shifter
wire [4:0] shift;
// the difference between SRC1 and SRC2 is bigger/equal 4:1 => no Barrelshifter after ADDSUB neccess
 
assign vswitch = exdiff[8]; // exchange ?
assign shift1 = (exdiff[7:5] != 3'h0) ? 5'h1F : exdiff[4:0];
assign exdiff12 = {1'b0,SRC1[30:23]} - {1'b0,SRC2[30:23]}; // caclulate already
assign shift2 = (exdiff12[7:5] != 3'h0) ? 5'h1F : exdiff12[4:0];
assign muxsrc2 = vswitch ? {SRC1[30:23],1'b1,SRC1[22:0]} : {SRC2[30:23],1'b1,SRC2[22:0]}; // Includ
assign muxsrc1 = vswitch ? {NZEXP[2],SRC2[22:0]} : {NZEXP[1],SRC1[22:0]};
 
assign pipe1 = SELECT[1] ? (ganzklein ? 24'h0 : {NZEXP[1],SRC1[22:0]}) : muxsrc1; // Feeding in R.T
assign shift = SELECT[1] ? rexdiff[4:0] : (vswitch ? shift2 : shift1);
// ++++++++++++++++++++++++++++++++++
// ADD/SUB + ROUND/TRUNC/FLOOR : 2. step : Barrelshifter to right -->
wire [32:0] brshifta,brshiftb,brshiftc,brshiftd;
wire [32:0] brshifte; // last stage
// 33322222222221111111111
// 2109876543210987654321098765432-10
// 1VVVVVVVVVVVVVVVVVVVVVVV0000000-00 // last 2 Bit for rounding
assign brshifta = shift[4] ? {16'h0,pipe1[32:17], (pipe1[16:9] != 8'h00)} : {pipe1,9'h0};
assign brshiftb = shift[3] ? { 8'h0,brshifta[32:9],(brshifta[8:0] != 9'h000)} : brshifta;
assign brshiftc = shift[2] ? { 4'h0,brshiftb[32:5],(brshiftb[4:0] != 5'h00)} : brshiftb;
assign brshiftd = shift[1] ? { 2'h0,brshiftc[32:3],(brshiftc[2:0] != 3'h0)} : brshiftc;
assign brshifte = shift[0] ? { 1'b0,brshiftd[32:2],(brshiftd[1:0] != 2'h0)} : brshiftd;
// ++++++++++++++++++++++++++++++++++
// ROUNDFi/TRUNCFi/FLOORFi : 3. step : round to integer
reg car_ry;
wire [30:0] compl;
wire [31:0] iadder;
assign inex = brshifte[1:0]; // Inexact-Flag-Data via multiplexer at the end
always @(SELECT or sign1 or brshifte or inex or ganzklein)
casex (SELECT[3:2])
2'b00 : car_ry = sign1 ^ ((brshifte[2:0] == 3'b110) | (inex == 2'b11)); // ROUNDLi
2'b1x : car_ry = sign1 ? (~ganzklein & (inex == 2'b00)) : 1'b0; // +numbers like TRUNCLi, -num
default : car_ry = sign1; // TRUNCLi , simple cut
endcase
 
assign compl = sign1 ? ~brshifte[32:2] : brshifte[32:2];
assign iadder = {sign1,compl} + {31'h0,car_ry};
assign IOUT = minint ? 32'h8000_0000 : iadder;
 
always @(iadder or BWD or sign1) // special overflow detection i.e. -129 bis -255 bei Byte
casex (BWD) // or 127.9 -> 128 = Fehler !
2'b00 : ovflag2 = (iadder[8] != iadder[7]); // Byte
2'b01 : ovflag2 = (iadder[16] != iadder[15]); // Word
default : ovflag2 = 1'b0;
endcase
// ++++++++++++++++++++++++++++++++++
// only ADD/SUB : 3. step : Add or Subtract
// the modul ADDSUB integrates the carry from the mantissa : 35 Bit
wire lsb;
wire [35:0] vresult;
wire [7:0] eminus1;
wire [33:0] vadd_q,vsub_q;
wire vzero;
wire [36:0] out_v0;
assign lsb = (brshifte[6:0] != 7'h00);
 
// Adder-Definition : "0"(8 Bit Exponent)"1"(23 Bit Mantissa)"000"
 
ADDSUB addsub_v (.dataa({1'b0,muxsrc2,3'b000}),
.datab({9'h0,brshifte[32:7],lsb}), .add_sub(addflag),
.result(vresult) );
assign eminus1 = muxsrc2[31:24] - 8'h01; // a greater Underflow can not exist, because minimal Expo
 
// Case ADD : Bit 23 : LSB of exponent
assign vadd_q = (muxsrc2[24] != vresult[27]) ? {vresult[35:3],(vresult[2:0] != 3'b000)}
: {vresult[35:27],vresult[25:2],(vresult[1:0] != 2'b00)} ;
 
// Case SUB : Bit 26 : "hidden" MSB of mantissa
assign vsub_q = vresult[26] ? {vresult[35:27], vresult[25:2],(vresult[1:0] != 2'b00)} // like t
: {vresult[35],eminus1,vresult[24:0]} ;
// SELECT[1] has here no meaning
assign vzero = (vresult[26:0] == 27'h0) & ~addflag; // only if "-" can be the result 0
 
assign out_v0 = addflag ? {vzero,vorz,1'b0,vadd_q}
: {vzero,vorz,1'b0,vsub_q} ;
assign OUT = variante ? out_v1 : out_v0; // Last multiplexer
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 3. SFPU_MUL Single Precision Floating Point Multiplier
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module SFPU_MUL ( SRC1, SRC2, MRESULT, NZEXP, OUT);
 
input [31:0] SRC1,SRC2; // only exponent of input data used
input [47:0] MRESULT;
input [2:1] NZEXP; // Flags of input data
output [36:0] OUT; // The result
 
wire [9:0] exponent,expoh,expol;
wire [1:0] restlow,resthigh;
wire zero,sign,orlow;
assign zero = ~NZEXP[2] | ~NZEXP[1]; // one of both NULL -> NULL is the result
assign sign = (SRC1[31] ^ SRC2[31]) & ~zero;
assign orlow = (MRESULT[21:0] != 22'b0);
assign restlow = {MRESULT[22],orlow};
assign resthigh = {MRESULT[23],(MRESULT[22] | orlow)};
assign exponent = {2'b00,SRC1[30:23]} + {2'b00,SRC2[30:23]};
assign expoh = exponent - 10'h07E;
assign expol = exponent - 10'h07F; // for MSB if MRESULT=0
assign OUT = MRESULT[47] ? {zero,sign,expoh,MRESULT[46:24],resthigh}
: {zero,sign,expol,MRESULT[45:23],restlow};
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 4. SP_FPU Top Level of Single Precision Floating Point Unit
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module SP_FPU (BCLK, OPCODE, SRC1, SRC2, FSR, MRESULT, BWD, FL, FP_OUT, I_OUT, TT_SP, SP_CMP, SP_MUX
 
input BCLK; // is not used !
input [7:0] OPCODE;
input [31:0] SRC1,SRC2; // Input data
input [8:3] FSR; // Floating Point Status Register
input [47:0] MRESULT; // Multiplier result
input [1:0] BWD; // Size of integer
input FL;
 
output [31:0] FP_OUT,I_OUT; // The results
output [4:0] TT_SP; // Trap-Type
output [2:0] SP_CMP; // CMPF result
output SP_MUX,LD_FSR,UP_SP;
 
reg [2:0] tt;
reg [3:0] select;
reg car_ry;
 
wire [36:0] mulout,addout,fpout;
wire [2:1] nzexp;
wire [34:2] rund; // Indexnumbers like xxxout
wire overflow,underflow,inexact;
wire op_cmp;
wire nan,nan_1,nan_2;
// Control of datapath
 
always @(OPCODE)
casex (OPCODE)
8'b1011_0000 : select = 4'b1000; // 0 0 0 : ADDF Shifter are reused
8'b1011_0100 : select = 4'b1001; // 0 0 1 : SUBF
8'b1001_000x : select = 4'b1010; // 0 1 0 : MOViF
8'b1001_100x : select = 4'b1011; // 0 1 1 : ROUNDFi
8'b1001_101x : select = 4'b1011; // 0 1 1 : TRUNCFi
8'b1001_111x : select = 4'b1011; // 0 1 1 : FLOORFi
8'b1011_0010 : select = 4'b1001; // 0 0 1 : CMPF
8'b1011_1100 : select = 4'b1100; // 1 x x : MULF
default : select = 4'b0;
endcase
 
assign SP_MUX = select[3] & (select[1:0] != 2'b11) & FL; // Output multiplexer
assign LD_FSR = (OPCODE[7:4] == 4'h9) & (OPCODE[3:1] == 3'b001); // LFSR does only Double (accordin
assign UP_SP = select[3] & FL; // All FPU opcodes of SP_FPU
assign op_cmp = (OPCODE == 8'hB2) & FL;
// SRCFLAGS
assign nzexp[2] = (SRC2[30:23] != 8'd0); // only exponent 0 ,denormalized Number => NAN !
assign nzexp[1] = (SRC1[30:23] != 8'd0); // only exponent 0 ,denormalized Number => NAN !
assign nan_2 = (SRC2[30:23] == 8'hFF) | (~nzexp[2] & (SRC2[22:0] != 23'd0)); // NAN
assign nan_1 = (SRC1[30:23] == 8'hFF) | (~nzexp[1] & (SRC1[22:0] != 23'd0)); // NAN
 
assign nan = (select[1:0] == 2'b11) ? nan_1 : (~select[1] & (nan_2 | nan_1));
// 001 : ADDF,... + 011 : CMPF
SFPU_ADDSUB IADDSUB ( .SRC1(SRC1), .SRC2(SRC2), .NZEXP(nzexp), .BWD(BWD),
.SELECT({OPCODE[2:1],select[1:0]}), .OUT(addout), .IOUT(I_OUT), .CMPRES(SP_CMP[1:0]) );
// 100 : MULF
SFPU_MUL IMUL ( .SRC1(SRC1), .SRC2(SRC2), .MRESULT(MRESULT), .OUT(mulout), .NZEXP(nzexp) );
// FP - Pfad : selection of result and rounding :
 
assign fpout = (OPCODE[5] & OPCODE[3]) ? mulout : addout;
always @(FSR or fpout) // calculate Carry according rounding mode, fpout[35] = sign bit
casex (FSR[8:7])
2'b00 : car_ry = ((fpout[1:0] == 2'b10) & fpout[2]) | (fpout[1:0] == 2'b11); // round to nearest
2'b10 : car_ry = ~fpout[35] & (fpout[1:0] != 2'b00); // round to positiv infinity
2'b11 : car_ry = fpout[35] & (fpout[1:0] != 2'b00); // round to negativ infinity
default : car_ry = 1'b0; // round to zero
endcase
 
assign rund = {fpout[34:2]} + {32'h0,car_ry};
// Detection of Overflow, Underflow and Inexact : epxonent is [34:25] = 10 Bits
assign overflow = ~rund[34] & (rund[33] | (rund[32:25] == 8'hFF));
assign underflow = (rund[34] | (rund[33:25] == 9'h0)) & ~fpout[36]; // Zero-Flag
assign inexact = (fpout[1:0] != 2'b00);
// CMPF can have no other error except NAN
always @(nan or op_cmp or overflow or underflow or inexact or FSR)
casex ({nan,op_cmp,overflow,FSR[3],underflow,FSR[5],inexact})
7'b1xxxxxx : tt = 3'b101; // Invalid operation
7'b001xxxx : tt = 3'b010; // Overflow
7'b00011xx : tt = 3'b001; // Underflow
7'b0000011 : tt = 3'b110; // Inexact Result
default : tt = 3'b000; // no error
endcase
 
assign TT_SP = {(inexact & ~op_cmp),(underflow & ~op_cmp),tt};
assign SP_CMP[2] = nan;
// Underflow Special case and force ZERO
assign FP_OUT = (underflow | fpout[36]) ? 32'd0 : {fpout[35],rund[32:2]};
endmodule
/trunk/rtl/DECODER.v
0,0 → 1,1754
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: DECODER.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// DECODER Instruction Decoding and Flow Control
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module DECODER ( BCLK, BRESET, INT_N, NMI_N, ANZ_VAL, OPREG, CFG, PSR, ACC_DONE, DC_ABORT, IC_ABORT,
PC_SAVE, STRING, INIT_DONE, ILL, UNDEF, TRAPS, IC_READ, STOP_CINV,
GENSTAT, DISP, IMME_Q, DISP_BR, USED, NEW, LOAD_PC, NEXT_PCA, RDAA, RDAB, OPER, START, LD_OUT,
INFO_AU, ACC_FELD, WREN, WRADR, WMASKE, WR_REG, DETOIP, MMU_UPDATE, RESTART, STOP_IC, RWVAL, EN
 
input BCLK,BRESET;
input INT_N,NMI_N; // external inputs
input [2:0] ANZ_VAL;
input [55:0] OPREG; // the OPREG contains the bytes to decode, OPREG[55:32] are don't care
input [8:0] CFG; // CONFIG : many bits are don't-care
input [11:0] PSR;
input ACC_DONE;
input DC_ABORT,IC_ABORT;
input ACB_ZERO;
input DONE;
input [31:0] PC_SAVE;
input [4:0] STRING;
input INIT_DONE;
input ILL,UNDEF;
input [5:0] TRAPS;
input IC_READ;
input STOP_CINV; // not to mix it up with STOP_IC
output [2:0] GENSTAT;
output [31:0] DISP,IMME_Q,DISP_BR; // three main data busses : Displacement, Immediate and Displace
output [2:0] USED;
output NEW;
output LOAD_PC;
output NEXT_PCA;
output [7:0] RDAA,RDAB;
output [10:0] OPER;
output [1:0] START,LD_OUT;
output LD_DIN,LD_IMME;
output [6:0] INFO_AU;
output [14:0] ACC_FELD;
output WREN;
output [5:0] WRADR;
output [1:0] WMASKE;
output reg WR_REG;
output [12:0] DETOIP;
output [1:0] MMU_UPDATE;
output RESTART;
output STOP_IC;
output [2:0] RWVAL;
output ENA_HK;
output reg ILO;
output [23:0] COP_OP;
reg [31:0] DISP,disp_val;
reg [10:0] oper_i;
reg [2:0] USED;
reg [14:0] ACC_FELD;
reg [1:0] ldoreg;
reg wren_i;
reg [5:0] wradr_i;
reg [1:0] wmaske_i;
reg [1:0] START;
reg [23:0] COP_OP;
reg spupd_i;
reg [3:0] disp_sel;
reg [52:0] op1_feld;
reg [47:0] op2_feld;
reg [47:0] op3_feld;
reg [47:0] op_feld_reg;
reg [31:0] imme_i;
reg [2:0] valid;
reg [7:0] phase_reg;
reg [3:0] di_stat; // Displacement Status
reg [3:0] cc_feld;
reg [1:0] ex_br_op;
reg acb_reg;
reg jsr_flag;
reg [8:0] waitop,wait_reg;
reg branch;
reg [3:0] dim_feld;
reg [66:0] new_op;
reg short_op_reg;
reg [15:0] idx_reg;
reg [35:0] gen_src1;
reg [33:0] gen_src2;
reg qw_flag;
reg long_reg;
reg new_spsel;
reg s_user,old_su;
reg [1:0] stack_sel; // Stack select for USER and SUPERVISOR
reg [1:0] s_mod; // Modifier for Stack select
reg upd_info,dw_info;
reg [2:0] rpointer;
reg [5:0] resto; // for RESTORE
reg init_rlist;
reg new_fp;
reg format1;
reg ldpc_phase;
reg reti_flag;
reg no_t2p;
reg iabort,ia_save;
reg mmu_sel;
reg [1:0] nmi_reg;
reg nmi_flag,int_flag;
reg type_nmi;
reg [3:0] exc_vector;
reg phase_exc;
reg [3:0] ovf_pipe;
reg dbg_s,dbg_trap,dbg_en,addr_cmp;
reg ssrc_flag,sdest_flag;
reg op_setcfg,setcfg_lsb;
reg inss_op;
reg exin_cmd,extract; // EXT/INS
reg bit_reg; // Flag for Bit opcodes : Source2 = Reg
reg kurz_st; // Flag for MOVM/CMPM
reg kill_opt; // Flag for optimized MOVS
reg cmps_flag; // Flag for CMPS
reg skps_flag; // Flag for SKPS
reg mt_flag; // Flag for Match and Translate
reg spu_block; // block of SP update at Long operation
reg dia_op,dia_flag; // Flag for DIA
reg m_ussu,m_usel,dc_user; // MOVUS/SU
reg rwval_flag,wrval_flag; // RDVAL/WRVAL
reg cinv_flag; // Flag for CINV
reg [5:0] lmrreg;
reg no_init,a_ivar;
reg index_cmd;
reg stop_d;
reg dc_ilo;
wire PHASE_0;
wire [7:0] phase_ein; // Phase after ABORT has changed the content to 0
wire de_flag,ivec_flag;
wire next;
wire [18:0] new_addr,pop_fp,save_pc;
wire [13:0] new_regs;
wire [7:0] new_ph,ppfp;
wire [7:0] new_nx;
wire op_1byte,op_12byte,op_2byte,op_3byte;
wire jump;
wire short_op,short_def;
wire acb_op,acb_flag;
wire zero,carry_psr,negativ,larger,flag;
wire valid_size;
wire op_ok;
wire stop;
wire [47:0] opc_bits;
wire [47:0] op_feld;
wire [2:0] atys,atyd;
wire [3:0] auop_s,auop_d;
wire long,src2_flag,dest_flag;
wire [6:0] src_1,src_2,src_1l,src_2l;
wire [1:0] src1_le,src2_le;
wire acc1,acc2;
wire spupd;
wire [6:0] saver; // for SAVE
wire [2:0] reg_nr;
wire save_reg;
wire ld_disp,disp_ok;
wire store_pc;
wire do_xor;
wire do_long;
wire [1:0] idx_n,n_idx;
wire idx;
wire [1:0] otype;
wire [10:0] opera,op_str,op_sho;
wire [5:0] dest_r,dest_rl;
wire phase_idx;
wire [15:0] idx_bytes,idx_feld;
wire [3:0] idx_1,idx_2;
wire [4:0] src1_addr,src2_addr;
wire [6:0] usp_1,usp_2;
wire [33:0] tos_oper;
wire [18:0] adrd1,exr11,exr12,adrd2,adwr2,exr22,exw22,re_wr,st_src,st_src2,st_dest,st_len,st_trde,s
wire [7:0] phrd1,phrd2,phwr2;
wire [6:0] rega1,irrw1,rega2,irrw2;
wire [3:0] nxrd1,nxrw2;
wire rmw;
wire [6:0] quei1,quet1; // Registeradr
wire [7:0] endea,goacb,dowait; // Phase
wire [3:0] diacb; // DIMM access
wire qword;
wire [6:0] stack,no_modul,ttstak;
wire [12:0] pop_1;
wire mpoi_1,mpoi_2;
wire [1:0] src1_tos; // the code for REUSE is 2'b11
wire svc_flag,bpt_flag,flag_flag,trac_flag;
wire [3:0] misc_vectors;
wire [2:0] psr_code;
wire exception;
wire interrupt;
wire abort; // DC_ABORT | iabort;
wire abo_int;
wire iabo_fall;
wire abbruch,fpu_trap,dvz_trap;
wire abbruch2;
wire dbg_flag;
wire ovf_op,ovf2_op,ovf_flag;
wire pc_match;
wire no_trap;
wire [10:0] op_psr,op_scp;
wire [30:0] ai_next;
wire set_src,set_dest,clr_sflag;
wire [7:0] rrepa; // Repair Phase of Abort for String opcodes
wire [7:0] ph_str; // working phase String
wire ph_match;
wire t2p;
wire rw_bit,op_ilo;
wire setcfg;
wire string_ende;
wire wlor; // Flag to generate WR_REG signal
wire [5:0] wstr0,wstr1,wstr2;
wire [6:0] rstr0,rstr1,rstr2;
wire rett_exc;
wire chk_rmw;
 
// Variables for 2- and 3-Byte Dekoder :
reg [5:0] hzr_c; // CASE Statement
wire [1:0] hzl_a;
wire [2:0] hzl_b;
wire [5:0] hzr_a,hzr_b,hzr_s;
wire hdx_a;
wire hdo_b;
wire [3:0] hdo_a,hdo_c,hdo_e;
wire [7:0] hdo_d;
wire [1:0] hdl_b,hdl_d,hdl_f,hdl_g,hdl_h;
wire [2:0] hdl_a,hdl_c,hdl_e;
wire [5:0] hdr_a,hdr_b,hdr_c,hdr_d,hdr_e,hdr_f,hdr_g,hdr_m;
wire [66:0] state_0,state_group_50,state_group_60; // for the Gruppe 2 opcodes
// Address field : Size:2 RD WR LDEA FULLACC INDEX:4 SPUPD disp_val:4 POST CLRMSW SRC2SEL:2
parameter addr_nop = 19'b10_0000_0000_0_0000_0000; // all parameter to 0
parameter push_op = 19'b10_0111_0000_1_1010_0000; // i.e. for BSR, ENTER ...
parameter push_ea = 19'b10_0111_0000_1_1010_0011; // SAVE middle
parameter pop_op = 19'b10_1011_0010_1_0000_1000; // RET/RESTORE
parameter adddisp = 19'b10_0010_0000_0_0000_0011; // for RET : reuse of EA
parameter adddispn = 19'b10_0010_0000_0_0000_0000; // for RETT : add Disp to Stack
parameter save_sp = 19'b10_0000_0000_1_0000_0000; // u.a. RET : update of Stack
parameter next_po = 19'b10_1011_0010_1_0000_1011; // RESTORE middle
parameter dispmin = 19'b10_0010_0000_0_0100_0011; // Reuse for ENTER
parameter rmod_rxp = 19'b10_1001_0000_1_0000_0100; // MODUL+0 read : SB , SP Update , therefore no
parameter rmod_rtt = 19'b10_1001_0000_0_0000_0100; // MODUL+0 read : SB , no LDEA
parameter rmod_4 = 19'b10_1011_0000_0_0001_0100; // MODUL+4 read : Link Table Base
parameter rmod_8 = 19'b10_1011_0000_0_0010_0100; // MODUL+8 read : Program Base
parameter rdltab = 19'b10_1010_0000_0_1000_0000; // Link table read - EA Phase
parameter ea_push = 19'b10_0110_0000_0_1010_0011; // CXP : 2. Push EA Phase
parameter ea_min8 = 19'b10_1010_0000_0_1011_0011; // CXP : reuse of MOD+8
parameter pop_ru = 19'b10_1010_0010_0_0000_1011; // RXP : EA Phase MOD POP
parameter rd_icu = 19'b00_1001_0000_0_1100_0010; // Read ICU : Byte of fix address
parameter get_vec = 19'b10_1001_0000_0_01xx_0000; // Read Exception-Vector : Index Exception No.
parameter get_veci = 19'b10_1001_0110_0_0000_0000; // Read Exception-Vector : Index external Interr
parameter load_ea = 19'b10_0010_0000_0_0000_0000; // used for store of TEAR and MSR
parameter save_msr = 19'b10_0010_0001_0_0000_0000; // used for store of TEAR and MSR
parameter ivar_adr = 19'b10_0000_0100_0_0000_0010; // only pass SRC1
parameter st_trans = 19'b00_1001_0100_0_0000_0000; // Translate at String : SRC1 + SRC2 , Byte
parameter src_x = 7'hxx;
parameter dest_x = 6'hxx;
parameter imme = {1'b1,6'hxx};
parameter frame = 7'h18;
parameter ibase = 7'h1E;
parameter modul = 7'h1F;
parameter w_msr = 6'h0A;
parameter w_tear = 6'h0B;
parameter fsr_r = 6'h17; // not defined register for FSR for opcodes LFSR and SFSR
parameter temp_l = 6'h3C;
parameter temp_h = 6'h3D; // second last space for 8B TEMP register
parameter temp_1 = 6'h3E; // Backup for register at String operations
parameter temp_2 = 6'h3F;
parameter rtmpl = 7'h3C;
parameter rtmph = 7'h3D;
parameter rtmp1 = 7'h3E;
parameter rtmp2 = 7'h3F;
parameter op_mov = {3'bxxx,8'h45};
parameter op_adr = {3'bxxx,8'h49};
parameter op_add = 11'h340; // for CXP
parameter op_flip = 11'h364; // for CXP : LSHD -16,Ri
parameter op_lmr = 11'h36A; // for LPR CFG, LMR and CINV
parameter op_wrp = 11'h387; // for CXP : write PSR , used also for Exception processing
parameter op_ldp = 11'h388; // for RETT and RETI : load of PSR from Stack
parameter op_zex = 11'h076; // Zero Extension for ICU Vector - is also used at String Option "T"
parameter op_cop = 8'hDD; // Coprozessor Opcode
// ++++++++++++++++++++++++++ The switch logic for the state machine ++++++++++++++++++++++++++++
always @(ANZ_VAL)
case (ANZ_VAL)
3'd0 : valid = 3'b000;
3'd1 : valid = 3'b001;
3'd2 : valid = 3'b011;
default : valid = 3'b111;
endcase
 
assign next = ( PHASE_0 ? op_ok : // Opcode decoded or Exception processed
// Displacement or Immediate operand and external memory access can happen in parallel
// i.e. addressing mode Memory Relative
( ((~dim_feld[0] | ACC_DONE) & (~dim_feld[3] | di_stat[0])) // ACC_DONE resets dim_feld
// long operation
& ~(long_reg & ~DONE) ) )
// hard break : abort or fpu_trap or dvz_trap or ovf_flag
| abbruch ;
always @(posedge BCLK or negedge BRESET)
if (!BRESET) long_reg <= 1'b0;
else
long_reg <= next ? do_long : long_reg; // START[1]
always @(posedge BCLK or negedge BRESET) // the central phase register
if (!BRESET) phase_reg <= 8'h0;
else
if (next) phase_reg <= new_op[47:40];
always @(*) // next switch of micro program counter
casex ({PHASE_0,op_ok,dim_feld[3],di_stat[0]})
4'b11_xx : USED = {1'b0,~op_1byte,(op_1byte | op_3byte)};
4'b0x_11 : USED = di_stat[3:1];
default : USED = 3'd0;
endcase
// Special phases
assign PHASE_0 = (phase_reg == 8'h00); // During Phase 0 the opcode is decoded
assign NEXT_PCA = PHASE_0 & ~ovf_flag & ~dbg_flag;
// Pulse to transfer from Trace Bit to Pending Trace Bit, only once in the beginning of phase 0
// The priority is such that a TRACE exception is served before an UNDEFINED/ILLEGAL exception
always @(posedge BCLK) no_t2p <= PHASE_0 & ~op_ok;
assign t2p = PHASE_0 & ~no_t2p; // signal to I_PFAD
// ++++++++++++++++++++++++++ global control signals ++++++++++++++++
assign de_flag = CFG[8];
assign ivec_flag = CFG[0];
assign dvz_trap = TRAPS[1];
assign fpu_trap = TRAPS[0];
always @(posedge BCLK) nmi_reg <= {nmi_reg[0],NMI_N}; // one clock sync and than falling edge detec
always @(posedge BCLK or negedge BRESET)
if (!BRESET) nmi_flag <= 1'b0;
else nmi_flag <= (nmi_reg == 2'b10) | (nmi_flag & ~(phase_reg == 8'h82));
always @(posedge BCLK) int_flag <= PSR[11] & ~INT_N; // one clock to synchronise
assign stop = (int_flag | nmi_flag) & PHASE_0 & ~stop_d; // neccesary if FPU_TRAP and INT at t
assign interrupt = (int_flag | nmi_flag) & (~PHASE_0 | stop_d);
always @(posedge BCLK or negedge BRESET)
if (!BRESET) stop_d <= 1'd0;
else stop_d <= stop;
// ++++++++++++++++++++++++++ Exception processing +++++++++++++++
// IC_ABORT is valid if Opcode Decoder cannot continue
assign iabo_fall = IC_ABORT & (PHASE_0 ? ~op_ok : (~di_stat[0] & dim_feld[3]));
always @(posedge BCLK) iabort <= iabo_fall & ~ia_save; // DC_ABORT ist a pulse
always @(posedge BCLK) ia_save <= iabo_fall;
// mmu_sel is used in ADDR_UNIT
always @(posedge BCLK) mmu_sel <= DC_ABORT | (mmu_sel & ~iabort); // 1 = DCACHE , 0 = ICACHE
assign MMU_UPDATE[0] = mmu_sel;
assign abort = DC_ABORT | iabort;
// that is the end of String loops where interrupts are checked : 8'hC7 & 8'hCF
assign string_ende = (phase_reg[7:4] == 4'hC) & (phase_reg[2:0] == 3'b111); // attention : 8'hCF do
 
always @(posedge BCLK) if (PHASE_0 || string_ende) type_nmi <= nmi_flag; // during processing kept
assign svc_flag = (OPREG[7:0] == 8'hE2) & valid[0]; // Vector 5 : 0101 , Illegal Vector 4 : 0100
assign bpt_flag = (OPREG[7:0] == 8'hF2) & valid[0]; // Vector 8 : 1000 , Undefined Vec. 10 : 1010
assign flag_flag = (phase_reg == 8'h89) & flag; // Vector 7 - has an own state
assign trac_flag = t2p & PSR[10]; // Vector 9 : 1001 , PSR[10] = P Bit , Pending Trace
assign ovf_flag = (ovf_pipe[3] & flag) | (ovf_pipe[1] & TRAPS[2]); // Vector 13 : 1101
assign dbg_flag = dbg_trap | (dbg_s & PHASE_0); // Vector 14 : 1110
// abort + dvz_trap during a opcode, fpu_trap + ovf_flag + dbg_flag later
assign abbruch = abort | fpu_trap | dvz_trap | ovf_flag | dbg_flag; // this 5 stop everything
assign abbruch2 = abort | fpu_trap | dvz_trap | ovf_flag; // for exc_vector generation
// forces the next step of state machine (op_ok), generates otype="11" for Trap Service
assign exception = interrupt | svc_flag | bpt_flag | ILL | UNDEF | trac_flag | abbruch;
// a TRACE Exception is done before the opcode execution
assign misc_vectors = trac_flag ? 4'h9 : {(bpt_flag | UNDEF),(svc_flag | ILL),UNDEF,svc_flag}; // t
always @(posedge BCLK)
if (PHASE_0 || abbruch) // ABORTs, fpu_trap, dvz_trap + ovf_flag can happen every time
begin
exc_vector <= abbruch ? (abbruch2 ? {ovf_flag,(dvz_trap | ovf_flag),~ovf_flag,(fpu_trap | ovf_fl
: (interrupt ? {3'b0,nmi_flag} : misc_vectors); // misc_vectors is default
end
else
if (flag_flag) exc_vector <= 4'h7; // FLAG-Trap
else
if (interrupt && string_ende) exc_vector <= {3'b0,nmi_flag};
assign psr_code[2] = ~psr_code[1]; // Absicht : codiert das Sichern des PSR bei Exception-Entr
assign psr_code[1] = abort | ILL | UNDEF | trac_flag; // enable for reseting the P-Bit during write
assign psr_code[0] = (interrupt & ~fpu_trap) | abort; // enable for reseting the I-Bit of new PSR
 
// valid codes are x'89 to x'8F
assign op_psr = {8'b0_00_1000_1,psr_code}; // is used during first clock cylce after exception, is
// Specialitiies : ABORT stores address & flags , the Interrrupts read vectors : all is used in big
assign abo_int = (exc_vector == 4'h2) | (exc_vector[3:1] == 3'b000);
assign ai_next = (exc_vector == 4'h2) ? {load_ea,8'h84,4'h0} : {rd_icu,8'h82,4'h1};
assign save_pc = {7'b10_0010_0,dia_flag,7'b00_0_0000,dia_flag,3'b001}; // Exception : PC_ARCHI => E
assign no_trap = ~fpu_trap & ~ovf_flag & ~dbg_flag; // suppresion of WREN and LD_OUT[1] and ADDR_UN
 
// ++++++++++++++++++++++++++ Overflow Trap ++++++++++++++
always @(posedge BCLK)
if (ovf_flag || !PSR[4]) ovf_pipe <= 4'd0;
else
if (PHASE_0) ovf_pipe <= {ovf_pipe[2],(ovf_op & op_ok),ovf_pipe[0],(ovf2_op & op_ok)}; // V-Bit s
assign ovf_op = ( ((OPREG[6:2] == 5'b000_11) // ADDQi
| (OPREG[3:2] == 2'b00)) & (OPREG[1:0] != 2'b10)) // ADDi,ADDCi,SUBi,SUBCi
| ((OPREG[7:0] == 8'h4E) & OPREG[13] & (OPREG[11:10] == 2'b00)) // NEGi,ABSi
| ((OPREG[7:0] == 8'hEE) & ~OPREG[10]); // CHECKi
 
assign ovf2_op = ((OPREG[6:2] == 5'b100_11) & (OPREG[1:0] != 2'b10)) // ACBi, these overflows have
| ((OPREG[13:10] == 4'h1) & (OPREG[7:0] == 8'h4E)) // ASHi
| ( OPREG[13] & (OPREG[11] == OPREG[10]) & (OPREG[7:0] == 8'hCE)); // MULi,DEIi,QUOi,DIVi
// ++++++++++++++++++++++++++ Debug Trap ++++++++++++++
always @(posedge BCLK or negedge BRESET)
if (!BRESET) dbg_s <= 1'b0;
else dbg_s <= dbg_trap | (dbg_s & ~((exc_vector == 4'hE) & (phase_reg == 8'h81)));
always @(posedge BCLK) dbg_en <= op_ok | ~PHASE_0;
assign pc_match = dbg_en & TRAPS[3] & PHASE_0 & ~exception; // TRAPS[3] is only combinatorical
always @(posedge BCLK) dbg_trap <= (pc_match | (addr_cmp & PHASE_0)) & TRAPS[5]; // TRAPS[5] = Enab
always @(posedge BCLK) addr_cmp <= TRAPS[4] | (addr_cmp & ~PHASE_0); // TRAPS[4] = CAR HIT
// ++++++++++++++++++++++++++ Special case String Abort ++++++++++++++
// Flags cleared if entry and exit of string operation and during Abort sequence, not valid for MO
// special case UNTIL/WHILE : reset if exit (op_feld_reg[17] = 1 = UNTIL)
assign clr_sflag = (phase_reg == 8'hC0) | (phase_reg == 8'hC7) | (phase_reg == 8'hC8) | (phase_
| (((phase_reg == 8'hD7) | (phase_reg == 8'hDF)) & ~(STRING[3] ^ op_feld_reg[17])) ;
assign set_src = (phase_reg == 8'hC1) | (phase_reg == 8'hC9);
assign set_dest = (phase_reg == 8'hC4) | (phase_reg == 8'hCC);
always @(posedge BCLK or negedge BRESET) // R1 is modified
if (!BRESET) ssrc_flag <= 1'b0;
else ssrc_flag <= (set_src & ~kurz_st) | (ssrc_flag & ~clr_sflag);
always @(posedge BCLK or negedge BRESET) // R2 is modified
if (!BRESET) sdest_flag <= 1'b0;
else sdest_flag <= (set_dest & ~kurz_st) | (sdest_flag & ~clr_sflag);
assign rrepa = {7'b1000_011,~sdest_flag}; // R1 and if necessary R2 restore
// ++++++++++++++++++++++++++ The one byte opcodes +++++++++++++++++++
// The one byte opcodes have a special case : one byte opcode but the second byte should be valid t
// Used with SAVE, RESTORE, ENTER and EXIT with their reg list.
// The advantage is that the reg list is store in op_feld_reg.
// [52:34] addressing
// [33:20] register
// [19:18] 1 or 2 Byte opcode
// [17:16] BSR/BR
// [15:8] next phase
// [7:4] START + LD_OUT
// [3:0] operand access : Displacement or Speicher
always @(*) // SVC (E2) and BPT (F2) decode as exception
casex (OPREG[7:0])
8'hxA : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b01,8'h01,4'h0,4'hE}; // Bcc , DISP read
8'h02 : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b10,8'h01,4'h0,4'hE}; // BSR , DISP read
8'h12 : op1_feld = {pop_op , src_x, stack, 2'b01,2'b00,8'h2A,4'h0,4'h1}; // RET , DISP later
8'h22 : op1_feld = {rmod_4 , src_x, modul, 2'b01,2'b00,8'h35,4'h0,4'h1}; // CXP
8'h32 : op1_feld = {pop_op, src_x, stack, 2'b01,2'b00,8'h40,4'h0,4'h1}; // RXP
8'h42 : op1_feld = {pop_op, src_x, stack, 2'b01,2'b00,8'h46,4'h0,4'h1}; // RETT
8'h52 : op1_feld = {rd_icu, src_x, src_x, 2'b01,2'b00,8'h45,4'h0,4'h1}; // RETI
8'h62 : op1_feld = {addr_nop, src_x, src_x, 2'b10,2'b00,8'h30,4'h0,4'h0}; // SAVE
8'h72 : op1_feld = {addr_nop, src_x, src_x, 2'b10,2'b00,8'h32,4'h0,4'h0}; // RESTORE
8'h82 : op1_feld = {push_op , frame, stack, 2'b10,2'b00,8'h2D,4'h2,4'h1}; // ENTER : PUSH FP
8'h92 : op1_feld = {addr_nop, src_x, src_x, 2'b10,2'b00,8'h32,4'h0,4'h0}; // EXIT : POP FP
8'hA2 : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b00,8'h00,4'h0,4'h0}; // NOP
8'hB2 : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b00,8'h88,4'h0,4'h0}; // WAIT
8'hC2 : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b00,8'h88,4'h0,4'h0}; // DIA
8'hD2 : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b00,8'h89,4'h0,4'h0}; // FLAG
default : op1_feld = {19'hxxxxx,14'hxxxx, 2'b00,2'b00,16'hxxxx};
endcase
assign op_1byte = op1_feld[18] & valid[0];
assign op_12byte = op1_feld[19] & (valid[1:0] == 2'b11);
assign new_addr = op1_feld[52:34];
assign new_regs = op1_feld[33:20];
assign new_ph = op1_feld[15:8];
assign new_nx = op1_feld[7:0]; // at Bcond DISP read
assign pop_fp = new_fp ? pop_op : addr_nop;
assign ppfp = new_fp ? 8'h34 : 8'h00;
always @(posedge BCLK)
if (PHASE_0)
begin
ex_br_op <= op1_feld[17:16]; // BSR/BR
cc_feld <= OPREG[7:4];
new_fp <= (OPREG[7:6] == 2'b10); // not decoded complete but is sufficient
reti_flag <= OPREG[4]; // only difference between RETI and RETT is important
dia_op <= OPREG[6]; // only difference between DIA and WAIT is important
end
always @(posedge BCLK) dia_flag <= dia_op & (phase_reg == 8'h88); // special case DIA compared to W
always @(posedge BCLK) // Format 1 opcodes write always DWord to reg, the same is true for Exceptio
if (PHASE_0 || abbruch) format1 <= (valid[0] & (OPREG[3:0] == 4'h2)) | exception;
else
if (flag_flag || (interrupt && string_ende)) format1 <= 1'b1;
// Branch etc. CXP CXPD
assign store_pc = (phase_reg == 8'd1) | (phase_reg == 8'h37) | (phase_reg == 8'h6B); // only save i
assign jump = (ex_br_op[0] & branch) | (acb_reg & ~ACB_ZERO) | ex_br_op[1];
always @(posedge BCLK) ldpc_phase <= (phase_reg == 8'h3E) // PC load at CXP/Traps , all one clock
| (phase_reg == 8'h43) // PC load at RXP
| ((phase_reg == 8'h49) & reti_flag) // PC load at RETI
| (phase_reg == 8'h4E) // PC load at RETT
| (phase_reg == 8'h66) // PC load at JUMP/JSR/CASE
| (phase_reg == 8'h7B); // PC load at DE = Direct Exception
assign NEW = ((phase_reg == 8'd1) & jump & di_stat[0]) | LOAD_PC;
assign LOAD_PC = ((phase_reg == 8'h2B) & di_stat[0]) // only one pulse, but DISP must be ok => di_s
| ldpc_phase;
assign no_modul = de_flag ? {1'b0,dest_x} : {1'b1,modul[5:0]};
assign negativ = PSR[7];
assign zero = PSR[6];
assign flag = PSR[5];
assign larger = PSR[2];
assign carry_psr = PSR[0];
assign rett_exc = ~reti_flag & (phase_reg == 8'h4B); // special case RETT : Stack can change during
always @(posedge BCLK) phase_exc <= (phase_reg == 8'h80); // 1. Exception phase
always @(negedge BCLK) if (PHASE_0 || phase_exc || rett_exc) s_user <= PSR[9]; // Select Bit for St
always @(negedge BCLK)
if (PHASE_0 || phase_exc) s_mod <= {PSR[9],~PSR[9]};
else
if (rett_exc) s_mod <= s_mod | {PSR[9],~PSR[9]}; // Both can be updated
always @(cc_feld or zero or carry_psr or larger or negativ or flag)
case (cc_feld)
4'h0 : branch = zero; // EQual
4'h1 : branch = ~zero; // Not Equal
4'h2 : branch = carry_psr; // Carry Set
4'h3 : branch = ~carry_psr; // Carry Clear
4'h4 : branch = larger; // Higher
4'h5 : branch = ~larger; // Lower or Same
4'h6 : branch = negativ; // Greater Than
4'h7 : branch = ~negativ; // Less or Equal
4'h8 : branch = flag; // Flag Set
4'h9 : branch = ~flag; // Flag Clear
4'hA : branch = ~larger & ~zero; // LOwer
4'hB : branch = larger | zero; // Higher or Same
4'hC : branch = ~negativ & ~zero; // Less Than
4'hD : branch = negativ | zero; // Greater or Equal
4'hE : branch = 1'b1; // True
4'hF : branch = 1'b0; // False
endcase
// +++++++++++++++++++++++ Register List Processing ++++++++++++++++++++++++++++
always @(posedge BCLK) init_rlist <= PHASE_0 | (phase_reg == 8'h2E);
always @(posedge BCLK)
if (PHASE_0) rpointer <= 3'b000;
else
if (ACC_DONE || init_rlist) rpointer <= reg_nr;
REG_LIST scanner ( .DIN(op_feld_reg[22:15]), .INIT(init_rlist), .IPOS(rpointer), .VALID(save_reg),
assign saver = {4'h0,reg_nr};
always @(posedge BCLK) if (ACC_DONE || init_rlist) resto <= {3'h0,~reg_nr}; // EXIT and RESTORE hav
// ++++++++++++++++++++++++++ Processing of Displacement and Immediate Operand ++++++++++++++++++
always @(posedge BCLK or negedge BRESET) // Flag for DISP and IMME access
if (!BRESET) dim_feld[3] <= 1'b0;
else dim_feld[3] <= next ? new_op[3] : ~di_stat[0] & dim_feld[3];
always @(posedge BCLK) if (next) dim_feld[2:1] <= new_op[2:1];
always @(posedge BCLK or negedge BRESET) // Flag for external access
if (!BRESET) dim_feld[0] <= 1'b0;
else dim_feld[0] <= next ? new_op[0] : ~ACC_DONE & dim_feld[0];
// special case QWORD, last term for security
always @(posedge BCLK) qw_flag <= dim_feld[0] & ACC_DONE & (ACC_FELD[13:12] == 2'b11) & ~qw_flag;
assign LD_IMME = (dim_feld[3] & (dim_feld[2:1] != 2'b11)) | short_op | store_pc; // Data multiplexe
assign LD_DIN = (di_stat[0] & dim_feld[3] & (dim_feld[2:1] != 2'b11)) // Enable for DIN Regist
| (ACC_DONE & dim_feld[0]) | qw_flag | short_op | store_pc; // next not possible : i.e. imme
assign ld_disp = (dim_feld[3:1] == 3'b111); // Enable for DISP Register
 
// Signal to ADDR_UNIT , only Displacement critical
assign disp_ok = ld_disp ? di_stat[0] : 1'b1;
always @(dim_feld or OPREG or valid or ANZ_VAL) // Bit 0 is "Data ok", the upper 3 bits are for USE
casex ({dim_feld[2:1],OPREG[7:6]})
4'b00_xx : di_stat = {3'b001,valid[0]};
4'b01_xx : di_stat = {3'b010,(valid[1] & valid[0])};
4'b10_xx : di_stat = {3'b100,ANZ_VAL[2]};
4'b11_0x : di_stat = {3'b001,valid[0]};
4'b11_10 : di_stat = {3'b010,(valid[1] & valid[0])};
4'b11_11 : di_stat = {3'b100,ANZ_VAL[2]};
endcase
 
always @(OPREG)
casex (OPREG[7:6])
2'b0x : disp_val = {{26{OPREG[6]}},OPREG[5:0]};
2'b10 : disp_val = {{19{OPREG[5]}},OPREG[4:0],OPREG[15:8]};
2'b11 : disp_val = {{3{OPREG[5]}},OPREG[4:0],OPREG[15:8],OPREG[23:16],OPREG[31:24]};
endcase
assign DISP_BR = disp_val; // DISP is also used for Bcc opcode
// The generator for DISP : data is used in ADDR_UNIT
always @(*)
casex ({ld_disp,disp_sel}) // disp_sel from new_op
5'b1_00xx : DISP = disp_val;
5'b1_01xx : DISP = 32'h0 - disp_val; // special case for ENTER
5'b1_1xxx : DISP = {disp_val[29:0],2'b00}; // DISP*4 for External Address Mode
5'b0_11xx : DISP = {20'hFFFFF,3'h7,type_nmi,8'h00}; // Interrupt Service Address
5'b0_1000 : DISP = 32'hFFFF_FFFF; // PUSH Byte
5'b0_1001 : DISP = 32'hFFFF_FFFE; // PUSH Word
5'b0_1010 : DISP = 32'hFFFF_FFFC; // PUSH DWord
5'b0_1011 : DISP = 32'hFFFF_FFF8; // PUSH QWord
5'b0_01xx : DISP = {26'h0,exc_vector,2'b00}; // the exception vector as Offset for INTBASE
5'b0_00xx : DISP = {28'h0,disp_sel[1:0],2'b00}; // 0,+4,+8,+12 used with MOD, default is 0
endcase
always @(short_op or dim_feld or OPREG or op_setcfg or setcfg_lsb)
casex ({short_op,dim_feld[2:1]})
3'b000 : imme_i = op_setcfg ? {28'h0000_00F,OPREG[2:0],setcfg_lsb} : {24'hxx_xxxx,OPREG[7:0]};
3'b001 : imme_i = {16'hxxxx,OPREG[7:0],OPREG[15:8]};
3'b01x : imme_i = {OPREG[7:0],OPREG[15:8],OPREG[23:16],OPREG[31:24]};
3'b1xx : imme_i = {{29{OPREG[10]}},OPREG[9:7]}; // for MOVQ etc. only OPREG can be used
endcase
assign IMME_Q = store_pc ? PC_SAVE : imme_i;
// ++++++++++++++ Stack Control +++++++++++++++++
always @(posedge BCLK or negedge BRESET)
if (!BRESET) new_spsel <= 1'b0;
else new_spsel <= spupd | (new_spsel & ~PHASE_0 & ~fpu_trap & ~dvz_trap);
always @(posedge BCLK) upd_info <= PHASE_0 & new_spsel; // one clock cycle earlier a change occurs,
assign do_xor = fpu_trap ? upd_info : (PHASE_0 & new_spsel);
always @(negedge BCLK or negedge BRESET)
if (!BRESET) stack_sel <= 2'b00;
else
if (do_xor) stack_sel <= stack_sel ^ s_mod;
// Special case RETT
always @(posedge BCLK) if (!phase_reg[1]) old_su <= s_user; // is tested in state x'49 and used in
assign ttstak = {1'b0,((old_su == PSR[9]) ^ stack_sel[PSR[9]]),3'b110,PSR[9],1'b1};
// ++++++++++++++ 2 byte opcodes +++++++++++++++++
// Hint : short_op is decoded separatly
// [47:45] Source : [2] TOS=>(SP), [1] Ri => (Ri), [0] 1=access of memory
// [44:42] Destination : like [47:45]
// [41] long opcode [41:39] only for standard sequenz - not Gruppe 2
// [40] src2_flag - Source 2 is read
// [39] dest_flag - a target operand exists
// [38:33] src1_r Register field, no message about Immediate
// [32:27] src2_r Register field
// [26:25] src1_le Length of Source1 - this is used for qword
// [24:23] src2_le Length of Source2 : 00=1/01=2/10=4/11=8 Bytes => WMASKE
// [22:18] src1 field
// [17:13] src2 field
// [12:11] op_type 2 Bit for sort of opcode
// [10] FL : F=1/L=0
// [9:8] original BWD : B=00/W=01/D=11
// [7:0] opcode: operation code
assign valid_size = (OPREG[1:0] != 2'b10) & (valid[1:0] == 2'b11); // valid size + valid OPREG-Byte
assign hzl_a = (OPREG[1:0] == 2'b11) ? 2'b10 : OPREG[1:0]; // length field recoded
assign hzl_b = {1'b0,OPREG[1:0]}; // standard Length field
assign hzr_a = {3'b000,OPREG[13:11]}; // SRC2 or SRC1 regfield
assign hzr_b = {3'b000,OPREG[8:6]}; // SRC2 regfield
assign hzr_s = {((OPREG[15:11] == 5'h17) ^ stack_sel[s_user]),3'b110,s_user,1'b1}; // USER or SUPER
// Special case LPR & SPR regfield:
always @(OPREG or stack_sel or s_user)
casex ({OPREG[10:7]})
4'b1001 : hzr_c = {stack_sel[s_user],3'b110,s_user,1'b1}; // USER or SUPERVISOR Stack
4'b1011 : hzr_c = {stack_sel[1] ,3'b110,1'b1, 1'b1}; // USER Stack
4'b1100 : hzr_c = OPREG[6] ? temp_h : 6'h1C; // CFG special case : LPR : SPR
default : hzr_c = {2'b01,OPREG[10:7]};
endcase
// Unfortunately SETCFG must be implemented : it is transformed to a two byte opcode with one byte
assign setcfg = (OPREG[13:0] == 14'h0B0E) & (valid[1:0] == 2'b11);
 
always @(*)
casex ({setcfg,OPREG[10:2]})
// Short-Op Codes , ACB is an ADD with following jump
10'b0xxxx_x0011 : op2_feld = {6'o11,3'o3,6'hxx,hzr_a,hzl_a,hzl_a,5'h14,OPREG[15:11],2'b00,hzl_b,8'
10'b0xxxx_00111 : op2_feld = {6'o11,3'o2,6'hxx,hzr_a,hzl_a,hzl_a,5'h14,OPREG[15:11],2'b00,hzl_b,8'
10'b0xxxx_01011 : op2_feld = {6'o11,3'o1,hzr_c,hzr_a,hzl_a,hzl_a,5'h00,OPREG[15:11],2'b00,hzl_b,8'
// Scond is moving the SHORT operand in the Integer area as condition field
10'b0xxxx_01111 : op2_feld = {6'o11,3'o1,6'hxx,hzr_a,hzl_a,hzl_a,5'h14,OPREG[15:11],2'b00,hzl_b,8'
10'b0xxxx_10111 : op2_feld = {6'o11,3'o1,6'hxx,hzr_a,hzl_a,hzl_a,5'h14,OPREG[15:11],2'b00,hzl_b,8'
10'b0xxxx_11011 : op2_feld = {6'o11,3'o1,hzr_a,hzr_c,hzl_a,2'b10,OPREG[15:11],5'h00,2'b00,hzl_b,8'
// Format 3 opcodes :
10'b00x10_11111 : op2_feld = {6'o11,3'o1,hzr_a,6'h1D,hzl_a,hzl_a,OPREG[15:11],5'h00,2'b00,hzl_b,4'
10'b0x100_11111 : op2_feld = {6'o61,3'o1,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:11],5'h00,2'b10,hzl_b,4'
10'b01110_11111 : op2_feld = {6'o11,3'o1,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:11],5'h00,2'b10,hzl_b,4'
// Format 4 opcodes : main group
10'b0xxxx_xxxx0 : op2_feld = {6'o11,3'o3,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:6], 2'b00,hzl_b,4'h4,OP
10'b0xxxx_x0001 : op2_feld = {6'o11,3'o2,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:6], 2'b00,hzl_b,4'h4,OP
10'b0xxxx_x0101 : op2_feld = {6'o11,3'o1,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:6], 2'b00,hzl_b,4'h4,OP
10'b0xxxx_x1101 : op2_feld = (OPREG[10:9] == 2'b00) ? // target is Register => standard flow
{6'o11,3'o2,hzr_a,hzr_b,hzl_a,2'bxx,OPREG[15:6], 2'b00,hzl_b,4'h4,OPREG[5:2]} // TBIT
: {6'o14,3'o2,hzr_a,hzr_b,hzl_a,2'b00,OPREG[15:6], 2'b10,hzl_b,4'h4,OPREG[5:2]};
// ADJSPi
10'b01010_11111 : op2_feld = {6'o11,3'o3,hzr_a,hzr_s,hzl_a,2'b10,OPREG[15:11],5'h00,2'b00,hzl_b,8'
// ADDR, length field not valid
10'b0xxxx_x1001 : op2_feld = {6'o61,3'o1,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:6], 2'b00,hzl_b,8'h49};
10'b00000_11111 : op2_feld = {6'o71,3'o1,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:11],5'h00,2'b10,hzl_b,4'
// SETCFG => MOV Befehl , SRC1 is genrated for 32 bit , target is Register temp_h
10'b1xxxx_xxxxx : op2_feld = {40'b001001_001_000000_111101_00_10_10100_00000_00_011, 8'h76};
default : op2_feld = {40'hxx_xxxx_xxxx,4'hA,4'hx};
endcase
assign op_2byte = (valid_size | setcfg) & ~op2_feld[7]; // it must be for sure shown "Invalid Opcod
 
// Special case : the quick opcodes with the exception SPR and LPR
assign short_op = ((~OPREG[5]) | (OPREG[6:4] == 3'b011)) & (OPREG[3:2] == 2'b11) & valid_size & PHA
always @(posedge BCLK) if (PHASE_0) short_op_reg <= short_op;
assign short_def = PHASE_0 ? short_op : short_op_reg; // for the big state machine
assign op_sho = (OPREG[6:4] == 3'b011) ? 11'h07A : op_mov; // Special case Scond at Index as Dest.
// 2. special case ACB
assign acb_op = (OPREG[6:2] == 5'h13) & valid_size;
always @(posedge BCLK) if (PHASE_0) acb_reg <= acb_op;
assign acb_flag = PHASE_0 ? acb_op : acb_reg;
assign goacb = acb_flag ? 8'h28 : 8'h00; // x'28 = 40 , wait jump at REG operation - short-op speci
 
// 3. special case load of PSR and Init-Done opcodes : because of U bit in PSR a restart must follo
// CINV and LMR PTB must wait until Init-Done and than Restart.
// All variants of LPR and BIC/S have an extra cycle due to TRACE operation
always @(OPREG)
casex (OPREG[18:0])
19'bxxx_xxxxx_1101_110_11_xx : waitop = 9'h14C; // LPRi PSR,...
19'bxxx_xxxxx_1100_110_11_xx : waitop = 9'h174; // LPRi CFG,...
19'bxxx_xxxxx_0x10_111_11_xx : waitop = 9'h14C; // BICPSRi/BISPSRi ...
19'bxxxx_x_0010_xx_0000_1110 : waitop = 9'h174; // SETCFG []
19'bxxxx_0_0010_xx_0001_1110 : waitop = 9'h174; // LMR - at the end Restart
19'bxxxx_0_1001_xx_0001_1110 : waitop = 9'h174; // CINV - at the end Restart
default : waitop = 9'h000;
endcase
assign dowait = waitop[7:0]; // is used in Phase 0 if PSR is loaded from Register
always @(posedge BCLK) if (PHASE_0) wait_reg <= waitop;
 
// Here 2. and 3. special case are coming together:
// Phase definition, end over jump for ACB , not used in Phase 0
assign endea = acb_reg ? 8'h01 : (wait_reg[8] ? wait_reg[7:0] : 8'h00);
assign diacb = acb_reg ? 4'hE : 4'h0; // load Disp ?
// special case ADJSPi : SP=SRC2 always 32 Bit
always @(posedge BCLK)
if (PHASE_0) dw_info <= (OPREG[10:2] == 9'b1010_11111);
else dw_info <= dw_info & ~phase_reg[7]; // for security at ABORT
// SETCFG : Flag to transform the Byte Immeadiate operand
always @(posedge BCLK) if (PHASE_0) op_setcfg <= setcfg;
always @(posedge BCLK) if (PHASE_0) setcfg_lsb <= OPREG[15];
always @(posedge BCLK) if (PHASE_0) jsr_flag <= (OPREG[10:2] == 9'b1100_11111); // JSR : for PUSH
always @(posedge BCLK) // Bit opcodes to Register and EXT:SRC1 / INS:SRC2
if (PHASE_0) bit_reg <= ((OPREG[3] ? ((OPREG[7:6] == 2'd0) ? OPREG[23:22] : OPREG[18:17]) : OPREG
always @(posedge BCLK) if (PHASE_0) exin_cmd <= (~OPREG[10] & (OPREG[6:0] == 7'h2E)) & (valid[2:0]
always @(posedge BCLK) if (PHASE_0) extract <= ~OPREG[7];
always @(posedge BCLK) if (PHASE_0) inss_op <= (OPREG[13:10] == 4'h2) & (OPREG[7:0] == 8'hCE) & (va
// ++++++++++++++ 3 byte opcodes +++++++++++++++++
 
// [47:45] Source : [2] TOS=>(SP), [1] Ri => (Ri), [0] 1=access of memory
// [44:42] Destination : like [47:45]
// [41] long opcode [41:39] only for standard sequenz - not Gruppe 2
// [40] src2_flag - Source 2 is read
// [39] dest_flag - a target operand exists
// [38:33] src1_r Register field, no message about Immediate
// [32:27] src2_r Register field
// [26:25] src1_le Length of Source1 - this is used for qword
// [24:23] src2_le Length of Source2 : 00=1/01=2/10=4/11=8 Bytes => WMASKE
// [22:18] src1 field
// [17:13] src2 field
// [12:11] op_type 2 Bit for sort of opcode
// [10] FL : F=1/L=0
// [9:8] original BWD : B=00/W=01/D=11
// [7:0] opcode: operation code
assign hdx_a = OPREG[7] ? OPREG[8] : OPREG[10];
assign hdo_a = OPREG[13:10];
assign hdo_b = ~hdx_a; // long operation if L
assign hdo_c = {1'b0,OPREG[10],OPREG[7:6]}; // Format 8 opcodes
assign hdo_d = {6'b0101_00,OPREG[10],1'b0}; // CMPM/S or MOVM/S : 8'h52 or 8'h50
assign hdo_e = {3'b011,OPREG[10]}; // Special codes for LOGB and SCALB due to DP_OUT datapath
// Definitions of length
assign hdl_a = {1'b0,OPREG[9:8]}; // i size, is used in OPER
assign hdl_b = (OPREG[9:8] == 2'b11) ? 2'b10 : OPREG[9:8]; // recode length field, is used in ACC f
assign hdl_c = OPREG[10:8]; // FL + BWD
assign hdl_d = {1'b1,~hdx_a}; // length FP
assign hdl_e = {OPREG[8],2'bxx}; // BWD don't care
assign hdl_f = (OPREG[18:17] == 2'b00) ? OPREG[9:8] : {OPREG[8],~(OPREG[9] ^ OPREG[8])}; // exclusi
assign hdl_g = {(OPREG[9:8] != 2'b00),(OPREG[9:8] == 2'b00)}; // exclusiv for EXT/EXTS base operand
assign hdl_h = {(OPREG[9:8] != 2'b00),(OPREG[9:8] != 2'b01)}; // exclusiv for CHECK bound operand
// Register definitions
assign hdr_a = {3'b000,OPREG[21:19]}; // SRC1 Integer Register
assign hdr_b = {3'b000,OPREG[16:14]}; // SRC2 Integer Register
assign hdr_c = hdx_a ? {2'b10,OPREG[21:20],1'b0,OPREG[19]} : {2'b10,OPREG[21:19],1'b1};
assign hdr_d = hdx_a ? {2'b10,OPREG[16:15],1'b0,OPREG[14]} : {2'b10,OPREG[16:14],1'b1};
assign hdr_e = OPREG[11] ? {2'b10,OPREG[21:20],1'b0,OPREG[19]} : {2'b10,OPREG[21:19],1'b1};
assign hdr_f = OPREG[11] ? {2'b10,OPREG[16:14],1'b1} : {2'b10,OPREG[16:15],1'b0,OPREG[14]};
assign hdr_g = {3'b000,OPREG[16:15],1'b1}; // exclusiv for DEI
assign hdr_m = {3'b001,OPREG[17:15]}; // MMU Register Index 8-15
always @(*)
casex (OPREG[13:3])
11'b1000_xx_1100x : op3_feld = {6'o11,3'o3,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h
11'b000x_xx_0100x : op3_feld = {6'o11,3'o3,hdr_a,hdr_b, 2'b00,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h
11'b0101_xx_0100x : op3_feld = {6'o11,3'o3,hdr_a,hdr_b, 2'b00,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h
11'b1x0x_xx_0100x : op3_feld = {6'o11,3'o1,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h
11'b010x_xx_1100x : op3_feld = {6'o11,3'o1,hdr_a,hdr_b, hdl_b,2'b01,OPREG[23:14],2'b00,hdl_a,4'h
11'b011x_xx_1100x : op3_feld = {6'o11,3'o1,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b00,hdl_a,4'h
11'b0001_xx_0110x : op3_feld = {6'o11,3'o3,hdr_a,hdr_b, hdl_b,2'b00,OPREG[23:14],2'b00,hdl_a,4'h
// Floating Point opcodes
11'b000x_xx_0011x : op3_feld = {6'o11,hdo_b,2'b01,hdr_a,hdr_d, hdl_b,hdl_d,OPREG[23:14],2'b00,hd
11'b010x_xx_0011x : op3_feld = {6'o11, 3'o5,hdr_e,hdr_f, 2'b11,2'b10,OPREG[23:14],2'b00,hd
11'b011x_xx_0011x : op3_feld = {6'o11, 3'o5,hdr_e,hdr_f, 2'b10,2'b11,OPREG[23:14],2'b00,hd
11'b10xx_xx_0011x : op3_feld = {6'o11,hdo_b,2'b01,hdr_c,hdr_b, hdl_d,hdl_b,OPREG[23:14],2'b00,hd
11'b111x_xx_00111 : op3_feld = {6'o11,hdo_b,2'b01,hdr_c,hdr_b, hdl_d,hdl_b,OPREG[23:14],2'b00,hd
11'b111x_xx_00110 : op3_feld = {6'o11, 3'o5,hdr_c,hdr_b, hdl_d,hdl_b,OPREG[23:14],2'b00,hd
11'b0x00_0x_10111 : op3_feld = {6'o11,hdo_b,2'b11,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hd
11'bxx00_0x_10110 : op3_feld = {6'o11, 3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hd
11'b1000_0x_10111 : op3_feld = {6'o11, 3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hd
11'b1100_0x_10111 : op3_feld = {6'o11,hdo_b,2'b11,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hd
11'b0010_0x_1011x : op3_feld = {6'o11,hdo_b,2'b10,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hd
11'b0001_0x_10111 : op3_feld = {6'o11, 3'o1,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hd
11'bx101_0x_10111 : op3_feld = {6'o11, 3'o1,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hd
11'b001x_11_00111 : op3_feld = {6'o11,3'o1,hdr_a,fsr_r, 2'b10,2'b10,OPREG[23:19],5'b0,2'b00,3'o3
11'b110x_11_00111 : op3_feld = {6'o11,3'o1,fsr_r,hdr_b, 2'b10,2'b10,5'b0,OPREG[18:14],2'b00,3'o3
// MMU opcodes
11'b0010_11_0001x : op3_feld = {6'o11,3'o1,hdr_a,temp_h,2'b10,2'b10,OPREG[23:19],5'b0,2'b00, 3'o
11'b0011_11_0001x : op3_feld = {6'o11,3'o1,hdr_m,hdr_a, 2'b10,2'b10,5'b0,OPREG[23:19],2'b00, 3'o
// String opcodes
11'b000x_xx_0000x : op3_feld = {6'o11,3'o0,6'hxx,6'hxx, 2'bxx,2'b10,OPREG[23:14], 2'b10,hdl_
11'b0011_xx_0000x : op3_feld = {6'o11,3'o0,6'hxx,6'hxx, 2'bxx,2'b10,OPREG[23:14], 2'b10,hdl_
// Custom opcodes
11'bxx01_0x_10110 : op3_feld = {6'o11, 3'o5,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hd
// Integer Divisionen : QUOi REMi DIVi MODi and DEIi + MEIi
11'b11xx_xx_1100x : op3_feld = {6'o11,3'o7,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h
11'b10x1_xx_1100x : op3_feld = {6'o11,3'o7,hdr_a,hdr_g, hdl_b,hdl_f,OPREG[23:14],2'b10,hdl_a,4'h
// Gruppe 2 opcodes
11'b0x11_xx_1010x : op3_feld = {6'o77,3'o1,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b00,hdl_a,8'h
11'b000x_xx_1100x : op3_feld = {6'o66,3'o0,hdr_a,hdr_b, 2'bxx,2'b10,OPREG[23:14],2'b10,hdl_c, hd
11'b001x_0x_1111x : op3_feld = {6'o11,3'o0,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b10,hdl_e,4'h
11'b0101_0x_1111x : op3_feld = {6'o11,3'o5,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'h
11'b0100_0x_1111x : op3_feld = {6'o11,3'o0,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b10,hdl_e,4'h
11'b0011_xx_1100x : op3_feld = {6'o50,3'o0,hdr_a,hdr_b, hdl_g,hdl_b,OPREG[23:14],2'b10,hdl_c,4'h
11'bxxx0_xx_1110x : op3_feld = {6'o71,3'o0,hdr_a,hdr_b, hdl_h,hdl_b,OPREG[23:14],2'b10,hdl_c,4'h
11'b0x1x_xx_0100x : op3_feld = (OPREG[18:17] == 2'b00) ? // target is register => standard flow
{6'o11,3'o3,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b00,hdl_a,4'h6,hdo_a} // SBIT/CBIT
: {6'o14,3'o3,hdr_a,hdr_b, hdl_b,2'b00,OPREG[23:14],2'b10,hdl_a,4'h6,hdo_a};
11'b1110_xx_0100x : op3_feld = (OPREG[18:17] == 2'b00) ? // target is register => standard flow
{6'o11,3'o3,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b00,hdl_a,4'h6,hdo_a} // IBIT
: {6'o14,3'o3,hdr_a,hdr_b, hdl_b,2'b00,OPREG[23:14],2'b10,hdl_a,4'h6,hdo_a};
11'b1x11_xx_0100x : op3_feld = {6'o11,3'o7,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h
11'bxxx0_xx_0010x : op3_feld = {6'o40,3'o0,hdr_a,hdr_b, hdl_g,hdl_b,OPREG[23:14],2'b10,hdl_c,4'h
11'bxxx0_xx_1010x : op3_feld = {6'o14,3'o0,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b10, 3'o3,4'h
11'b0010_xx_1100x : op3_feld = {6'o14,3'o0,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b10, 3'o3,4'h
11'bxxx0_xx_0110x : op3_feld = {6'o61,3'o0,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b10, 3'o3,4'h
11'bxxx1_xx_0010x : op3_feld = {6'o11,3'o0,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b10, 3'o3,8'h
// Gruppe 2 opcodes can have dedicated operation codes. Therefore the operation code definition her
11'b000x_xx_0001x : op3_feld = {6'o70,3'o0,hdr_a,hdr_b, 2'b00,2'b10,OPREG[23:19],5'b0,2'b10,3'o0
11'b1001_11_0001x : op3_feld = {6'o11,3'o1,hdr_a,temp_h,2'b10,2'b10,OPREG[23:19],5'b0,2'b00,3'o3
default : op3_feld = {40'hxx_xxxx_xxxx,4'hA,4'hx};
endcase
assign op_3byte = (valid[2:0] == 3'b111) & (OPREG[2:0] == 3'b110) & (op3_feld[7:4] != 4'hA); // val
// +++++++++++++ Evaluation for 2 and 3 byte opcodes ++++++++++++++++++
 
// for one byte opcodes special treatmant neccessary
assign opc_bits = op_3byte ? op3_feld : op2_feld;
assign op_ok = (op_1byte | op_12byte | op_2byte | op_3byte | exception) & ~stop; // used for comput
 
always @(posedge BCLK) if (PHASE_0) op_feld_reg <= opc_bits;
assign op_feld = PHASE_0 ? opc_bits : op_feld_reg; // constant for all following cycles
 
// Evaluation of op_feld :
 
assign atys = op_feld[47:45]; // [2] : TOS=>(SP), [1] : Ri => (Ri), [0] : 1=access of memory
assign atyd = op_feld[44:42]; // [2] : TOS=>(SP), [1] : Ri => (Ri), [0] : 1=access of memory
assign long = op_feld[41];
assign src2_flag = op_feld[40];
assign dest_flag = op_feld[39];
assign src_1 = {1'b0,op_feld[38:33]};
assign src_2 = {1'b0,op_feld[32:27]};
assign src1_le = op_feld[26:25];
assign src2_le = op_feld[24:23];
assign acc1 = (op_feld[22:21] != 2'b00) | atys[1]; // external access Source1 or "addr" : Reg => (
assign acc2 = (op_feld[17:16] != 2'b00) | atyd[1]; // external access Source2 or "addr" : Reg => (
assign wlor = dest_flag & ~acc2;
assign idx_n = {1'b0,(op_feld[22:20] == 3'b111)} + {1'b0,(op_feld[17:15] == 3'b111)}; // Index : 0
assign idx = (idx_n != 2'b00); // Index is active
assign n_idx = idx_n - 2'b01;
// The field otype is used only in Phase 0
assign otype = exception ? 2'b11 : ((op_1byte | op_12byte) ? 2'b01 : opc_bits[12:11]); // string op
assign opera = op_feld[10:0];
assign dest_r = src_2[5:0];
assign dest_rl = {dest_r[5:1],1'b0};
// +++++++++++++++++++++++++ Coprocessor operations field ++++++++++++++++++++++++++++++
always @(posedge BCLK) if (PHASE_0) COP_OP <= OPREG[23:0];
// +++++++++++++++++++++++++ Special signals for LMR and CINV ++++++++++++++++++++++++++
// op_lmr is constant = parameter
assign STOP_IC = (phase_reg == 8'h74) | (phase_reg == 8'h75);
 
// CINV uses Register x'30 - x'37 : CINV = 110... , LMR = 001... otherwise CFG
always @(posedge BCLK) if (PHASE_0) lmrreg <= op_3byte ? {{2{OPREG[13]}},~OPREG[13],OPREG[17:15]} :
 
always @(posedge BCLK) no_init <= (lmrreg[5:4] == 2'b00) & (lmrreg[3:1] != 3'b110); // LMR waits fo
// a_ivar = "Addresse IVAR0/1"
always @(posedge BCLK) a_ivar <= STOP_IC; // Phase 74 & 75, is used at INFO_AU together with IC_RE
// CINV detection for IC_CACHE
always @(posedge BCLK)
if (PHASE_0) cinv_flag <= OPREG[13] & (OPREG[7:0] == 8'h1E);
else cinv_flag <= cinv_flag & ~phase_reg[7]; // reset at exception
assign ENA_HK = ~(cinv_flag & STOP_IC); // always "1", if CINV then "0"
// +++++++++++++++++++++++++ USER flag for MOVUS & MOVSU ++++++++++++++++++++++++
always @(posedge BCLK)
if (PHASE_0) m_ussu <= (~OPREG[13] & (OPREG[11:10] == 2'b11) & (OPREG[7:0] == 8'hAE));
else m_ussu <= m_ussu & ~phase_reg[7]; // reset at exception
always @(posedge BCLK) if (PHASE_0) m_usel <= OPREG[12];
// +++++++++++++++++++++++++ USER flag for RDVAL & WRVAL ++++++++++++++++++++++++
always @(posedge BCLK)
if (PHASE_0) rwval_flag <= (OPREG[13:11] == 3'd0) & (OPREG[7:0] == 8'h1E);
else rwval_flag <= rwval_flag & ~phase_reg[7]; // reset at exception
always @(posedge BCLK) if (PHASE_0) wrval_flag <= OPREG[10]; // Difference RDVAL=0 and WRVAL=1
// +++++++++++++++++++++++++ Flags for CBIT/I+SBIT/I+IBIT +++++++++++++++++++++++
assign rw_bit = (op_feld_reg[7:4] == 4'd6) & ((~op_feld_reg[3] & op_feld_reg[1]) | (op_feld_reg[3:0
assign op_ilo = rw_bit & op_feld_reg[0]; // Interlocked : CBITI and SBITI
// +++++++++++++++++++++++++++++ Operations for String processing +++++++++++++++++
// Address field : Size:2 RD WR LDEA FULLACC INDEX:4 SPUPD disp_val:4 POST CLRMSW SRC2SEL:2
assign st_src = {STRING[1:0],5'b1010_0,(op_feld_reg[15] & ~kurz_st),STRING[1:0],9'b0_0000_1000}; /
assign st_src2 = {STRING[1:0],5'b1010_0,(op_feld_reg[15] & ~kurz_st),STRING[1:0],9'b0_0000_1011}; /
assign st_dest = {STRING[1:0],5'b0110_0,(op_feld_reg[15] & ~kurz_st),STRING[1:0],9'b0_0000_1011}; /
assign st_trde = {2'b00, 5'b0110_0, op_feld_reg[15], 2'b00, 9'b0_0000_1000}; /
assign st_trs2 = {STRING[1:0],5'b1010_0, op_feld_reg[15], STRING[1:0],9'b0_0000_1000}; /
assign st_len = {STRING[1:0],17'b0000_0000_0_0000_0000}; // length important for qw_flag
// Signals of DETOIP go to I_PFAD
always @(posedge BCLK) if (PHASE_0) kill_opt <= ~OPREG[7] & (OPREG[17:15] != 3'b000); // watch diff
assign ph_match = (phase_reg[7:4] == 4'hD) & (phase_reg[2:0] == 3'd7); // Phase D7 and DF
assign op_str = {op_feld_reg[10:8],6'b0101_00,op_feld_reg[1],1'b1}; // Opcode 8'h51 or 8'h53;
assign op_scp = {op_feld_reg[10:8],8'h41}; // normal CMPi
assign ph_str = {4'hC,op_feld_reg[1],3'b001}; // Phase 8'hC1 (MOVS/M) or 8'hC9 (CMPS/M)
always @(posedge BCLK) kurz_st <= (phase_reg == 8'h65) | (kurz_st & ~PHASE_0); // Flag for MOVM/C
always @(posedge BCLK) if (PHASE_0) cmps_flag <= ~OPREG[7] & (OPREG[11:10] == 2'b01); // Flag for C
always @(posedge BCLK) if (PHASE_0) skps_flag <= ~OPREG[7] & (OPREG[11:10] == 2'b11); // Flag for S
always @(posedge BCLK) if (PHASE_0) mt_flag <= ~OPREG[7] & (OPREG[17] | OPREG[15]); // Flag for Ma
 
assign wstr0 = {{4{kurz_st}},2'b00};
assign wstr1 = {{4{kurz_st}},2'b01};
assign wstr2 = {{4{kurz_st}},2'b10};
assign rstr0 = {1'b0,wstr0};
assign rstr1 = {1'b0,wstr1};
assign rstr2 = {1'b0,wstr2};
// +++++++++++++++++++++++++++++++++++ Index processing +++++++++++++++++++++++++++++++++++++++++
assign phase_idx = (phase_reg == 8'h02) | (phase_reg == 8'h50);
assign idx_bytes = idx_1[2] ? OPREG[15:0] : {OPREG[7:0],OPREG[7:0]}; // here last access of OPREG
always @(posedge BCLK) if (phase_idx) idx_reg <= idx_bytes;
assign idx_feld = (phase_idx) ? idx_bytes : idx_reg;
// +++++++++++++++++++++++++++++++++++ The big state machine ++++++++++++++++++++++++++++++++++++
// Hints :
// 1. At short-op SRC1 is out of memory to use TEMP
// 2. At SRC2 rmw suppresed TOS and changed it to (SP)
// 3. The Long-operation path takes the dest_r address to write if WR_REG activ
// 4. It is ok, that an extra cycle for the read of the index registers is needed - then data could
// Source 1
assign idx_1 = {1'b0,(op_feld[22:20] == 3'b111),op_feld[19:18]};
assign src1_addr = idx_1[2] ? idx_feld[7:3] : op_feld[22:18];
assign stack = {1'b0,stack_sel[s_user],3'b110,s_user,1'b1};
assign usp_1 = src1_addr[0] ? stack : {5'b0_0110,src1_addr[1:0]};
assign src_1l = {src_1[6:1],1'b0};
assign pop_1 = {2'b00,src1_le,9'h108}; // SP update, DISP=0 and POST
assign mpoi_1 = (src1_addr[4:2] == 3'b100) | (src1_addr == 5'h16); // Pointer in memory always DWor
assign auop_s = atys[0] ? 4'b1011 : 4'b0010; // Only make effective address ?
assign src1_tos = (op_feld[22:18] == 5'h17) ? 2'b11 : 2'b00; // Source 1 is true TOS
// Nextfield : 11=DISP read
// Address field : Size:2 RD WR LDEA FULLACC INDEX:4 SPUPD disp_val:4 POST CLRMSW SRC2SEL:2
always @(*)
casex (src1_addr) // RWLF IDX ADDR_F NEUP SRC_REG NEXT
// Special case which is only valid at INDEX or "addr" : REG -> ADDR , DISP=0 : starts immediate
5'b00xxx : gen_src1 = {auop_s, idx_1,9'h000,8'h07,4'h0,src1_addr[2:0],3'b000,atys[0]};
// Register relativ : 0(R0)
5'b01xxx : gen_src1 = {auop_s, idx_1,9'h000,8'h07,4'h0,src1_addr[2:0],3'b111,atys[0]};
// Memory relativ : 0(0(SB))
5'b100xx : gen_src1 = {4'b1011,4'h0, 9'h000,8'h06,usp_1, 4'b1111}; // 1. access always ful
// Immediate
5'b10100 : gen_src1 = (src1_le == 2'b11) ?
{4'h0, 4'h0, 9'h000,8'h0B,src_x, 1'b1,2'b10,1'b0} // load in DWord pieces
: {4'h0, 4'h0, 9'h000,8'h07,src_x, 1'b1,src1_le,1'b0};
5'b10101 : gen_src1 = {auop_s, idx_1,9'h002,8'h07,src_x, 3'b111,atys[0]}; // Absolut Address
5'b10110 : gen_src1 = {4'b1011,4'h0, 9'h014,8'h05,7'h1F, 4'b0001}; // External with MOD Re
5'b10111 : gen_src1 = (idx_1[2] | atys[2]) ? // Access class "addr" ?
{auop_s, idx_1,9'h000,8'h07,stack, 3'b000,atys[0]} // 0(SP) : no TOS flag
: {4'b1011,pop_1, 8'h07,stack, 4'b0001}; // TOS
// Memory Space : 0(SB)
5'b110x0 : gen_src1 = {auop_s, idx_1,9'h000,8'h07,5'b0_0110,src1_addr[1:0],3'b111,atys[0]}; // S
5'b11001 : gen_src1 = {auop_s, idx_1,9'h000,8'h07,stack, 3'b111,atys[0]}; // SP
5'b11011 : gen_src1 = {auop_s, idx_1,9'h001,8'h07,src_x, 3'b111,atys[0]}; // PC relativ
default : gen_src1 = 36'hx_xxxx_xxxx; // don't care
endcase
assign adrd1 = {(mpoi_1 ? 2'b10 : src1_le),gen_src1[35:19]}; // Addressfield : 19 Bits
assign phrd1 = gen_src1[18:11]; // next phase
assign rega1 = gen_src1[10:4]; // Source 1 Register
assign irrw1 = {4'b0,idx_feld[2:0]}; // Index-Register
assign nxrd1 = gen_src1[3:0]; // Memory/Disp/Immediate operation
assign exr11 = {2'b10 ,4'b1011,4'h0 ,9'h080}; // 2. access external with Mem.-Pointer + 4* Disp
assign exr12 = {src1_le,auop_s,idx_1,9'h000}; // for Memory Relative and EXT in last step
// Source 2 resp. Destination
assign rmw = src2_flag & dest_flag;
assign idx_2 = {1'b0,(op_feld[17:15] == 3'b111),op_feld[14:13]}; // 4 bits
assign src2_addr = idx_2[2] ? idx_feld[15:11] : op_feld[17:13];
assign usp_2 = src2_addr[0] ? stack : {5'b0_0110,src2_addr[1:0]};
assign src_2l = {src_2[6:1],1'b0};
assign mpoi_2 = (src2_addr[4:2] == 3'b100) | (src2_addr == 5'h16); // Pointer in memory always DWor
assign auop_d = atyd[0] ? 4'b1011 : 4'b0010; // Only make effective address ?
// The next assessment processes TOS separated for PUSH and POP
assign tos_oper = src2_flag ?
{2'b00,atyd[0],2'b01,atyd[0],2'b00,src2_le,7'b1_0000_10, src1_tos,4'h7,stack,3'b0,atyd[0]}
: {1'b0,atyd[0],3'b001,atyd[0],4'h0, 1'b1,2'b10,src2_le,2'b0,src1_tos,4'h7,stack,3'b0,aty
 
// Nextfield : 11=DISP read
// Address field : Size:2 RD WR LDEA FULLACC INDEX:4 SPUPD disp_val:4 POST CLRMSW SRC2SEL:2
always @(*)
casex (src2_addr) // RW:W RW:R LF IDX ADDR_F NEUP SRC_REG NEXT
// Special case which is only valid at INDEX or "addr" : REG -> ADDR , DISP=0 : starts immediate
5'b00xxx : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h000,4'h7,4'h0,src2_addr[2:0],3'b000,aty
// Register relativ : 0(R0)
5'b01xxx : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h000,4'h7,4'h0,src2_addr[2:0],3'b111,aty
// Memory relativ : 0(0(SB))
5'b100xx : gen_src2 = {2'b10,2'b10,2'b11,4'h0, 9'h000,4'h6,usp_2, 4'b1111}; // 1. access always
// Immediate
5'b10100 : gen_src2 = (src2_le == 2'b11) ?
{2'b00,2'b00,2'b00,4'h0, 9'h000,4'hB,src_x, 1'b1,2'b10,1'b0} // load in DWord pieces
: {2'b00,2'b00,2'b00,4'h0, 9'h000,4'h7,src_x, 1'b1,src2_le,1'b0};
5'b10101 : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h002,4'h7,src_x, 3'b111,atyd[0]}; // Ab
5'b10110 : gen_src2 = {2'b10,2'b10,2'b11,4'h0, 9'h014,4'h5,7'h1F, 4'b0001}; // External with MO
5'b10111 : gen_src2 = (idx_2[2] | rmw | atyd[2]) ?
{1'b0,atyd[0],auop_d, idx_2,7'b0_0000_00,src1_tos,4'h7,stack, 3'b000,atyd[0]} // 0(SP) : TOS
: tos_oper; // TOS : 2 cases for PUSH and POP
// Memory Space
5'b110x0 : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h000,4'h7,5'b0_0110,src2_addr[1:0],3'b11
5'b11001 : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h000,4'h7,stack, 3'b111,atyd[0]};
5'b11011 : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h001,4'h7,src_x, 3'b111,atyd[0]}; // PC
default : gen_src2 = 34'hx_xxxx_xxxx; // don't care
endcase
assign adrd2 = {(mpoi_2 ? 2'b10 : src2_le),gen_src2[31:15]};
assign adwr2 = {(mpoi_2 ? 2'b10 : src2_le),gen_src2[33:32],gen_src2[29:15]};
assign phrd2 = {4'h1,gen_src2[14:11]}; // Phase for Read Source 2
assign phwr2 = {4'h2,gen_src2[14:11]}; // Phase for Write Destination
assign rega2 = gen_src2[10:4];
assign nxrw2 = gen_src2[3:0];
assign irrw2 = {4'b0,idx_feld[10:8]};
assign re_wr = {src2_le,4'b0101,4'h0, 9'h003}; // REUSE Address : Write of rmw
assign exr22 = {src2_le,atyd[0],1'b0,1'b1,atyd[0],idx_2,9'h000}; // for Memory Relative and EXT in
assign exw22 = {src2_le,1'b0,atyd[0],1'b1,atyd[0],idx_2,9'h000}; // for Memory Relative and EXT in
// Special case :
assign quei1 = acc1 ? imme : src_1l; // 8B passing either from register or from extern
// 8B is requested from both operands but only to certain times
assign qword = (phase_reg[7:4] != 4'h0) ? (src2_le == 2'b11) : (src1_le == 2'b11);
assign quet1 = acc1 ? temp_h : src_1; // select source during calculation
// Output data of state machine
// LOAD if PULS if simple
// NEXT -> ENABLE ENABLE out
// [66:48] 19 ADDR : X ; Op-length REUSE RD/WR etc.
// [47:40] 8 new phase X
// [39:33] 7 SRC1 X
// [32:26] 7 SRC2 X
// [25] 1 WREN X
// [24:19] 6 DEST X
// [18:8] 11 OPER X
// [7:6] 2 START X
// [5:4] 2 LD_OUT X
// [3] 1 ID Load X
// [2:1] 2 ID Type X ; 0 = DISP
// [0] 1 MEM Access X
 
// State acc2-src2_flag-dest_flag
// no SRC2 x 0 x
// SRC2=REG 0 1 0 ; CMP+TBIT
// SRC2=REG 0 1 1 ; all else
// SRC2=MEM 1 1 0 ; CMP+TBIT
// SRC2=MEM 1 1 1 ; all else
// Input data for state machine
 
// 8 phase_reg : phase of state machine
// 2 otype : Opcode type
// 1 idx : Index is available : 1 or 2 , only PHASE_0
// 1 short_op : short opcodes like ADDQ
// 1 long : "long" opcode
// 1 qword : 8B access at Source (Exception DEI+MEI)
 
// 1 acc1 : Reg/Extern SRC1
// 1 acc2 : Reg/Extern SRC2
// 1 src2_flag : the 2. operand is being read
// 1 dest_flag : there is a target operand : only CMP and TBIT have none
assign phase_ein = abbruch ? 8'h00 : phase_reg;
always @(*) // "_" "_"
casex ({phase_ein,otype, idx,short_def,long,qword, acc1,acc2,src2_flag,dest_flag})
{8'h00,10'b00_1xxx_xxxx}: // Index must be loaded : phase 2 : in any case load TEMP for Short-Op an
new_op = short_op ? // START LD_OUT
{addr_nop,8'h02, imme, src_x, 1'b1,temp_h, op_sho, 2'b00,2'b10, 1'b1,n_idx,1'b0}
: {addr_nop,8'h02, src_1,src_1l,1'b0,dest_x, opera, 2'b00,~src2_flag,2'b1_1,n_idx,1'b0};
{8'h00,10'b00_01xx_x0xx}: // Short-Op to register, LD_OUT because of CMPQ
new_op = {addr_nop,goacb, imme, src_2,dest_flag,dest_r, opera, 2'b00,2'b10, 4'h0};
{8'h00,10'b00_01xx_x11x}: // Short-Op : external operand read : SRC2 ! Data in TEMP ! Here no Index
new_op = {adrd2, phrd2, imme, rega2, 1'b1,temp_h, op_mov, 2'b00,2'b00, nxrw2};
{8'h00,10'b00_01xx_x10x}: // MOVQ to Mem
new_op = {adwr2, phwr2, imme, rega2, 1'b0,dest_x, opera, 2'b00,2'b10, nxrw2};
{8'h00,10'b00_0000_00xx}: // simple register operation : dest_flag controls WREN, LD_OUT for CMP
new_op = {addr_nop,dowait,src_1,src_2, dest_flag,dest_r,opera, 2'b00,2'b10, 4'h0};
{8'h00,10'b00_0001_00xx}: // "simple" Reg-Op of 8B, phase 8 after 2. DWord , not via LONG-path
new_op = {addr_nop,8'h08, src_1,src_x, 1'b1,dest_r, opera, 2'b00,2'b00, 4'h0};
{8'h00,10'b00_0010_00xx}: // long register operation i.e. DIV - phase 31
new_op = {addr_nop,8'h1F, src_1,src_2, wlor,dest_r, opera, 2'b11,2'b00, 4'h0};
{8'h00,10'b00_0011_001x}: // long register operation with QWORD - phase 26 then wait
new_op = {addr_nop,8'h1A, src_1,src_2, 1'b0,dest_r, opera, 2'b01,2'b00, 4'h0};
{8'h00,10'b00_00xx_1xxx}: // Source 1 in memory - first to read , here no Index
new_op = {adrd1, phrd1, src_x,rega1, 1'b0,dest_x, opera, 2'b00,2'b00, nxrd1};
{8'h00,10'b00_00xx_011x}: // Source 2 in memory - first to read (Source 1 in register)
new_op = {adrd2, phrd2, src_x,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2};
{8'h00,10'b00_0000_0101}: // Source 1 store in Dest : "pass through" for MOV,NEG,ABS
new_op = {adwr2, phwr2, src_1,rega2, 1'b0,dest_x, opera, 2'b00,2'b10, nxrw2};
{8'h00,10'b00_0001_0101}: // Source 1 store in Dest : "pass through" for MOV,NEG,ABS for Long opera
new_op = //(op_feld[17:13] == 5'h17) ? // TOS : special case , first 8B out of Reg and then r
{addr_nop,8'h1C, src_1,src_1l,1'b0,dest_x, opera, 2'b00,2'b11, 4'h0};
{8'h00,10'b00_0010_0101}: // SRC1 -> DEST with short operands
new_op = {addr_nop,8'h1F, src_1,src_x, 1'b0,dest_r, opera, 2'b11,2'b00, 4'h0};
{8'h00,10'b00_0011_0x01}: // SRC1 -> DEST i.e. ROUNDLi
new_op = {addr_nop,8'h1F, src_1,src_1l,wlor,dest_r, opera, 2'b11,2'b00, 4'h0};
 
// Phase 2 : after read of Index nearly everything is repeated from PHASE_0
{8'h02,10'bxx_x1xx_x11x}: // Short-Op : external operand read
new_op = {adrd2, phrd2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2};
{8'h02,10'bxx_x1xx_x101}: // MOVQ to Mem, data is in Out-Register
new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2};
{8'h02,10'bxx_x0xx_1xxx}: // Source 1 in memory - first to read
new_op = {adrd1, phrd1, irrw1,rega1, 1'b0,dest_x, opera, 2'b00,2'b00, nxrd1};
{8'h02,10'bxx_x0xx_011x}: // Source 2 in memory - first to read
new_op = {adrd2, phrd2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2};
{8'h02,10'bxx_x00x_0101}: // Source 1 store in Dest : "pass through" , data is already in Out-Regis
new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2};
{8'h02,10'bxx_x010_0101}: // SRC1 -> DEST with short operands
new_op = {addr_nop,8'h1F, src_1,src_x, 1'b0,dest_x, opera, 2'b11,2'b00, 4'h0};
{8'h02,10'bxx_x011_0101}: // SRC1 -> DEST i.e. ROUNDLi
new_op = {addr_nop,8'h1F, src_1,src_1l,1'b0,dest_x, opera, 2'b11,2'b00, 4'h0};
 
// +++++++++++++++++ SRC1 operand loading +++++++++++++++++++
 
// Phase 5 : wait for data and Disp2 for External addressing : part 2 EA = (MOD+4)+4*DISP1
// next phase fix : 6
{8'h05,10'bxx_xxxx_xxxx}: new_op = {exr11, 8'h06, src_x,imme , 1'b0,dest_x, opera, 2'b00,2'b00,
// Phase 6 : Memory-Pointer for Memory Relative and last access External
// next phase fix : 7 , add Index
{8'h06,10'bxx_xxxx_xxxx}: new_op = {exr12, 8'h07, irrw1,imme , 1'b0,dest_x, opera, 2'b00,2'b00,
 
// Phase 7 : wait for final data , direct from PHASE_0 if TOS without Index
// next phase : if 8B data phase 8 is neccessary
// if SRC2=REG execution started (otherwise store data in TEMP) and PHASE_0
{8'h07,10'bxx_xx00_x0xx}: // into Register , short operation execution , but LD_OUT for PSR Update
new_op = {addr_nop,endea, imme, src_2, dest_flag,dest_r,opera, 2'b00,2'b10, diacb};
{8'h07,10'bxx_xx01_x0xx}: // into Reg but with a step om between for ABSL etc. : phase 8
new_op = {addr_nop,8'h08, imme, src_x, 1'b1,dest_r, opera, 2'b00,2'b00, 4'h0};
{8'h07,10'bxx_xx10_x0xx}: // execute long operation , wait in phase 31
new_op = {addr_nop,8'h1F, imme, src_2, wlor,dest_r, opera, 2'b11,2'b00, 4'h0};
{8'h07,10'bxx_xx11_xx0x}: // execute long operation : 2. operand only Dest , load LSD , phase 24 ,
new_op = {addr_nop,8'h18, imme, src_x, 1'b1,temp_l, op_mov, 2'b01,2'b00, 4'h0};
{8'h07,10'bxx_xx11_x01x}: // lange Operation ausfuehren , LSD laden , phase 25 , warten in phase 31
new_op = {addr_nop,8'h19, imme, src_2, 1'b0,dest_r, opera, 2'b01,2'b00, 4'h0};
{8'h07,10'bxx_xxx0_x11x}: // Data into TEMP , read 2. operand , is there Index ? Yes -> phase 15
new_op = idx_2[2] ?
{addr_nop,8'h0F, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0}
: {adrd2, phrd2, imme, rega2, 1'b1,temp_h, op_mov, 2'b00,2'b00, nxrw2};
{8'h07,10'bxx_xxx1_x11x}: // 8B data in TEMP , step in between then 2. Op read : phase 10 - can onl
new_op = {addr_nop,8'h0A, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0};
{8'h07,10'bxx_xx00_x101}: // something like ABSi , execute and store (LD_OUT)
new_op = idx_2[2] ?
{addr_nop,8'h10, imme, src_x, 1'b0,dest_x, opera, 2'b00,2'b10, 4'h0}
: {adwr2, phwr2, imme, rega2, 1'b0,dest_x, opera, 2'b00,2'b10, nxrw2};
{8'h07,10'bxx_xx01_x101}: // ABS etc. : LSD data over SRC2 in 2. OUT-Reg , MSD data see opcode ABS/
new_op = {addr_nop,8'h09, imme, src_x, 1'b0,dest_x, opera, 2'b00,2'b10, 4'h0};
{8'h07,10'bxx_xx10_x101}: // opcodes like MOVFL
new_op = {addr_nop,8'h1F, imme, src_x, 1'b0,dest_x, opera, 2'b11,2'b00, 4'h0};
 
// Phase 8 : 2. part of 64 bit data : can be reached from PHASE_0 if 8B data
{8'h08,10'bxx_xxxx_xxxx}: new_op = {addr_nop,endea, quei1,src_x, 1'b1,dest_rl, op_mov, 2'b00,2'b00,
// Phase 9 : step in between to get data in OUT-Reg Low , SRC1 is not possible
{8'h09,10'bxx_xxxx_xxxx}: // afterwards to data write
new_op = {addr_nop,8'h10, src_x,imme , 1'b0,dest_x, op_mov, 2'b00,2'b01, 4'h0};
// Phase 10 : LSD data write in TEMP , source can be IMME data to
{8'h0A,10'bxx_xxxx_xxxx}: // 8B , after TEMP there can only be a 2. operand
new_op = idx_2[2] ?
{addr_nop,8'h0F, imme, src_x, 1'b1,temp_l, op_mov, 2'b00,2'b00, 4'h0}
: {adrd2, phrd2, imme, rega2, 1'b1,temp_l, op_mov, 2'b00,2'b00, nxrw2};
 
// Phase 11 : wait for 8B IMME data : switch over at address decoder , qword flag is for sure "1"
{8'h0B,10'bxx_xx0x_x0xx}: // into Reg with step in between for ABSL etc. : phase 12
new_op = {addr_nop,8'h0C, imme, src_x, 1'b1,dest_r, opera, 2'b00,2'b00, 4'b1100};
{8'h0B,10'bxx_xx1x_x01x}: // execute long operation , load LSD , phase 25 , wait in phase 31
new_op = {addr_nop,8'h19, imme, src_2, 1'b0,dest_r, opera, 2'b01,2'b00, 4'b1100};
{8'h0B,10'bxx_xxxx_x11x}: // 8B data into TEMP , step in between then read 2. Op : phase 10 - can o
new_op = {addr_nop,8'h0A, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'b1100};
{8'h0B,10'bxx_xx0x_x10x}: // ABS etc. : LSD data via SRC2 into 2. OUT-Reg , MSD data see opcode ABS
new_op = {addr_nop,8'h09, imme, src_x, 1'b0,dest_x, opera, 2'b00,2'b10, 4'b1100};
{8'h0B,10'bxx_xx1x_xx0x}: // MOVLF with 8B IMME data ? Must be possible, the end in phase 24 like S
new_op = {addr_nop,8'h18, imme, src_x, 1'b1,temp_l, op_mov, 2'b01,2'b00, 4'b1100};
// Phase 12 : wait for 2. part of 64 bit IMME data : after phase 0
{8'h0C,10'bxx_xxxx_xxxx}: new_op = {addr_nop,endea, imme ,src_x, 1'b1,dest_rl, op_mov, 2'b00,2'b00,
 
// Phase 15 : secure in TEMP with Index continue and read 2. operand
{8'h0F,10'bxx_xxxx_xxxx}: new_op = {adrd2, phrd2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00,
// Phase 16 : after LD_OUT continue with Index and store 1. operand
{8'h10,10'bxx_xxxx_xxxx}: new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00,
 
// +++++++++++++++++ SRC2 operand loading : phase SRC1 + 16 +++++++++++++++++++
 
// Phase 21 : wait for data and Disp2 for external addressing : part 2 EA = (MOD+4)+4*DISP1
// next phase fix : 22
{8'h15,10'bxx_xxxx_xxxx}: new_op = {exr11, 8'h16, src_x,imme , 1'b0,dest_x, opera, 2'b00,2'b00,
// Phase 22 : Memory-Pointer for Memory Relative and last access external
// next phase fix : 23 , add Index
{8'h16,10'bxx_xxxx_xxxx}: new_op = {exr22, 8'h17, irrw2,imme , 1'b0,dest_x, opera, 2'b00,2'b00,
 
// Phase 23 : wait for final data , direct from PHASE_0 if TOS without Index
// next phase : if 8B data phase 24 is used
{8'h17,10'bxx_xx0x_xxx1}: // execute short operation and write data into memory , no WREN -> phase
new_op = {re_wr, 8'h27, quet1,imme , 1'b0,dest_r, opera, 2'b00,2'b10, 4'b0001};
{8'h17,10'bxx_xx0x_xxx0}: // execute short operation , no WREN -> phase 0 , CMP(+TBIT)
new_op = {addr_nop,endea, quet1,imme , 1'b0,dest_r, opera, 2'b00,2'b10, diacb};
{8'h17,10'bxx_xx10_xxxx}: // execute long operation , wait in phase 31
new_op = {addr_nop,8'h1F, quet1,imme , wlor,dest_r, opera, 2'b11,2'b00, 4'h0};
{8'h17,10'bxx_xx11_xxxx}: // execute long operation , load LSD in phase 24
new_op = {addr_nop,8'h18, quet1,imme , 1'b0,dest_r, opera, 2'b01,2'b00, 4'h0};
// Phase 24 : load 2. part of 64 bit data : with and without wait - from 28 the phase waits , from
{8'h18,10'bxx_xxxx_0xxx}: // execute long operation , wait in phase 31
new_op = {addr_nop,8'h1F, src_1l,imme, wlor,dest_r, opera, 2'b10,2'b00, 4'h0};
{8'h18,10'bxx_xxxx_1xxx}: // execute long operation , wait in phase 31 , data from TEMP, used also
new_op = {addr_nop,8'h1F, rtmpl,imme, wlor,dest_r, opera, 2'b10,2'b00, 4'h0};
// Phase 25 : load 2. part of 64 bit data : SRC1 from memory and SRC2 from Reg
{8'h19,10'bxx_xxxx_xxxx}: // execute long operation , wait in phase 31
new_op = {addr_nop,8'h1F, imme, src_2l,wlor,dest_r, opera, 2'b10,2'b00, 4'h0};
// Phase 26 : load 2. part of 64 bit data : SRC1 from Reg and SRC2 from Reg
{8'h1A,10'bxx_xxxx_xxxx}: // execute long operation , wait in phase 31
new_op = {addr_nop,8'h1F, src_1l,src_2l,wlor,dest_r, opera, 2'b10,2'b00, 4'h0};
 
// Phase 27 : wait for 8B IMME data : switch over at address decoder , qword flag is for sure "1"
{8'h1B,10'bxx_xxxx_xxxx}: // execute long operation , load LSD in phase 24
new_op = {addr_nop,8'h18, quet1,imme , 1'b0,dest_r, opera, 2'b01,2'b00, 4'b1100};
// +++++++++++++++++ special case ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Phase 28 : TOS with 8B SRC1 operand , no Index ! Jump to phase 39
{8'h1C,10'bxx_xxxx_xxxx}: // store Source 1 in Dest : "pass through" for MOV,NEG,ABS
new_op = {adwr2, phwr2, src_x,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2};
// +++++++++++++++++ close operation : write out DEST , TOS update +++++++++++++++++++
 
// Phase 31 : wait for DONE of long operation
{8'h1F,10'bxx_xxxx_xxx0}: // CMP done -> phase 0
new_op = {addr_nop,8'h00, src_x,src_x, 1'b0,dest_r, opera, 2'b00,2'b10, 4'h0}; // no ACB
{8'h1F,10'bxx_xxxx_x0x1}: // operation closed , data into register
new_op = {addr_nop,8'h00, src_x,src_x, 1'b0,dest_r, opera, 2'b00,2'b00, 4'h0}; // no ACB
{8'h1F,10'bxx_xxxx_x101}: // operation closed , data into memory - first calculate address phase 32
new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_r, opera, 2'b00,2'b00, nxrw2};
{8'h1F,10'bxx_xxxx_x111}: // operation closed , data into memory - address reuse phase 39 ACC_DONE
new_op = {re_wr, 8'h27, src_x,src_x, 1'b0,dest_r, opera, 2'b00,2'b00, 4'b0001};
// Destination address calculate
// Phase 37 : wait for data and Disp2 for External addressing : part 2 EA = (MOD+4)+4*DISP1
// next phase fix : 38
{8'h25,10'bxx_xxxx_xxxx}: new_op = {exr11, 8'h26, src_x,imme , 1'b0,dest_x, opera, 2'b00,2'b00,
// Phase 38 : Memory-Pointer for Memory Relative and letzter Zugriff External
// next phase fix : 39 , add Index and write
{8'h26,10'bxx_xxxx_xxxx}: new_op = {exw22, 8'h27, irrw2,imme , 1'b0,dest_x, opera, 2'b00,2'b00,
 
// Phase 39 : wait for ACC_DONE : consequent numbering : 7+32
{8'h27,10'bxx_xxxx_xxxx}: // now operation closed , only ACB could follow
new_op = {addr_nop,endea, src_x,src_x, 1'b0,dest_x, opera, 2'b00,2'b00, diacb};
// +++++++++++++++ special case : ACB to Reg is to fast ! One wait cycle for ZERO-Flag
{8'h28,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h01,src_x, src_x, 1'b0,dest_x, opera, 2'b00,2'b00,
// +++++++++++++++ The other opcodes are following ++++++++++++++++++
 
{8'h00,10'b01_xxxx_xxxx}: new_op = {new_addr,new_ph,new_regs, 1'b0,dest_x, op_mov, new_nx};
 
// Phase 1 : used for Bcond and ACB :
{8'h01,10'bxx_xxxx_xxxx}: new_op = (ex_br_op[1] | jsr_flag) ? // BSR or JSR ?
{push_op, 8'h27, imme, stack, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'b0001} // wait at end
: {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0};
// Phase 42 : RET : read of PC from Stack and DIN via SRC1 to PC
{8'h2A,10'bxx_xxxx_xxxx}: new_op = {adddisp, 8'h2B, imme, src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00
// Phase 43 : RET : Displacement add to Stack. Attention : "imme" important to keep source constan
{8'h2B,10'bxx_xxxx_xxxx}: new_op = {save_sp, 8'h2C, imme, src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00
// Phase 44 : RET : Update of Stack : fixed phase
{8'h2C,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 45 : ENTER Entry
{8'h2D,10'bxx_xxxx_xxxx}: new_op = {dispmin, 8'h2E, src_x,src_x, 1'b1,temp_l, op_adr, 2'b00,2'b00,
// Phase 46 : ENTER Stack longer
{8'h2E,10'bxx_xxxx_xxxx}: new_op = {save_sp ,8'h31, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 48 : SAVE/ENTER : Init phase , phases 48 & 49 very similar
{8'h30,10'bxx_xxxx_xxxx}: new_op = save_reg ?
{push_op, 8'h31, saver,stack, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'h1} // 1. load SP=>EA
: {addr_nop,8'h00, rtmpl,src_x,new_fp,frame[5:0],op_mov, 2'b00,2'b00, 4'h0}; // At ENTER
// Phase 49 : SAVE/ENTER : at the same time memory access and detection of next Reg
{8'h31,10'bxx_xxxx_xxxx}: new_op = save_reg ?
{push_ea, 8'h31, saver,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'h1} // one more
: {addr_nop,8'h00, rtmpl,src_x,new_fp,frame[5:0],op_mov, 2'b00,2'b00, 4'h0}; // At ENTER
 
// Phase 50 : RESTORE/EXIT Entry
{8'h32,10'bxx_xxxx_xxxx}: new_op = save_reg ?
{pop_op, 8'h33, src_x,stack, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}
: {pop_fp, ppfp, src_x,frame, 1'b0,dest_x, op_mov, 2'b00,2'b00, 3'h0,new_fp};
// Phase 51 : RESTORE/EXIT next reg
{8'h33,10'bxx_xxxx_xxxx}: new_op = save_reg ?
{next_po, 8'h33, imme, src_x, 1'b1,resto, op_mov, 2'b00,2'b00, 4'h1}
: {pop_fp, ppfp, imme, frame, 1'b1,resto, op_mov, 2'b00,2'b00, 3'h0,new_fp};
// Phase 52 : EXIT End
{8'h34,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, imme, src_x, 1'b1,frame[5:0], op_mov, 2'b00,2'b
// Phase 53 : CXP Entry : this opcode needs 12 States and 16 cycles minimum ...
{8'h35,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h36, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00,
// Phase 54 : CXP : Store Address Link table
{8'h36,10'bxx_xxxx_xxxx}: new_op = {rdltab, 8'h37, src_x,rtmph, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 55 : CXP : DISP is worked on, the return address => temp_l
{8'h37,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h38, imme, rtmph, 1'b1,temp_l, op_mov, 2'b00,2'b00,
// Phase 56 : CXP : Access to Link table => Result is MOD-Entry => store in temp_h
{8'h38,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h39, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00,
// Phase 57 : CXP : store and PUSH MOD prepare , Entry from Exception Processing
{8'h39,10'bxx_xxxx_xxxx}: new_op = {push_op, 8'h3A, modul,stack, 1'b0,dest_x, op_wrp, 2'b00,2'b10,
// Phase 58 : CXP : PUSH of MOD ongoing, PUSH PC prepare
{8'h3A,10'bxx_xxxx_xxxx}: new_op = {ea_push, 8'h3B, rtmpl,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b10,
// Phase 59 : CXP : New EA for PC
{8'h3B,10'bxx_xxxx_xxxx}: new_op = {save_sp, 8'h3C, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 60 : CXP : write of PC, calculate of Offset
{8'h3C,10'bxx_xxxx_xxxx}: new_op = {rmod_8, 8'h3D, rtmph,rtmph, 1'b1,temp_l, op_flip,2'b00,2'b00,
// Phase 61 : CXP : read from (MOD:New+8)
{8'h3D,10'bxx_xxxx_xxxx}: new_op = {ea_min8, 8'h3E, imme, rtmpl, 1'b1,temp_l, op_add, 2'b00,2'b00,
// Phase 62 : CXP : EA Phase of SB read , new PC calculated
{8'h3E,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h3F, rtmpl,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 63 : CXP : read of SB , new PC to ICache
{8'h3F,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h2F, imme, src_x, 1'b1,6'h1A, op_mov, 2'b00,2'b00,
// Phase 47 : CXP : Last phase update of MOD prepare
{8'h2F,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, rtmph,src_x, 1'b1,modul[5:0], op_mov, 2'b00,2'b
// Phase 64 : RXP Entry : POP of PC , full Access
{8'h40,10'bxx_xxxx_xxxx}: new_op = {pop_ru, 8'h41, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00,
// Phase 65 : RXP : PC is read, next POP prepare
{8'h41,10'bxx_xxxx_xxxx}: new_op = {adddisp, 8'h42, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 66 : RXP : DISP is addeed to Stack and MOD is read
{8'h42,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h43, imme, src_x, 1'b1,modul[5:0], op_mov, 2'b00,2'b
// Phase 67 : RXP : MOD is new
{8'h43,10'bxx_xxxx_xxxx}: new_op = {rmod_rxp,8'h44, rtmph,modul, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 68 : RXP : wait for SB data, parallel SP update
{8'h44,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, imme, src_x, 1'b1,6'h1A, op_mov, 2'b00,2'b00,
 
// Phase 69 : RETI : read of ICU for End-of-Interrupt Cycle , prepare read PC from Stack
{8'h45,10'bxx_xxxx_xxxx}: new_op = {pop_op, 8'h46, src_x,stack, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 70 : RETI/ RETT Entry : POP of PC , full Access
{8'h46,10'bxx_xxxx_xxxx}: new_op = {pop_ru, 8'h47, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00,
// Phase 71 : RETI/RETT : PC is read, next POP prepare
{8'h47,10'bxx_xxxx_xxxx}: new_op = {save_sp, 8'h48, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 72 : RETI/RETT : DISP is added to Stack , PSR load and MOD is loaded if DE off
{8'h48,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h49, imme, src_x, no_modul, op_ldp, 2'b00,2'b00, 4'
// Phase 73 : RETI/RETT : different paths
{8'h49,10'bxx_xxxx_xxxx}: new_op = de_flag ?
( reti_flag ?
{addr_nop,8'h4A, rtmph,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}
: {addr_nop,8'h4B, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} )
: {rmod_rtt,8'h4B, rtmph,modul, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1};
// Phase 74 : RETI/RETT : one pause cycle if DE on
{8'h4A,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 75 : RETI/RETT : SB read if DE off
{8'h4B,10'bxx_xxxx_xxxx}: new_op = reti_flag ?
{addr_nop,8'h00, imme, src_x, 1'b1,6'h1A, op_mov, 2'b00,2'b00, 4'h0}
: ( de_flag ?
{adddispn,8'h4E, src_x,ttstak,1'b0,dest_x, op_mov, 2'b00,2'b00, 4'hE}
: {adddispn,8'h4E, imme, ttstak,1'b1,6'h1A, op_mov, 2'b00,2'b00, 4'hE} );
// Phase 78 : RETT : SP update
{8'h4E,10'bxx_xxxx_xxxx}: new_op = {save_sp, 8'h4A, rtmph,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
 
// +++++++++++++++ special wait states for PSR and the Cache/MMU system +++++++++++
// Phase 76 : PSR in Word case simple delay of 2 cycles : 1. cycle does nothing
{8'h4C,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h4D, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 77 : PSR in Word case simple delay of 2 cycles : 2. cycle does Restart of instruction pro
{8'h4D,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// Phase 79 : Wait for INIT_DONE from Cachesystem
{8'h4F,10'bxx_xxxx_xxxx}: new_op = (INIT_DONE | no_init) ?
{addr_nop,8'h4D, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}
: {addr_nop,8'h4F, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0};
// +++++++++++++++ Direct Exception procession similar to CXP ++++++++++++++++++++
// Phase 121 : CXP : store and PUSH PSR prepare , Entry of Exception Processing
{8'h79,10'bxx_xxxx_xxxx}: new_op = {push_op, 8'h7A, modul,stack, 1'b0,dest_x, op_wrp, 2'b00,2'b10,
// Phase 122 : CXP : PUSH of PSR running, PUSH PC prepare - MOD like normal Exception-Flow
{8'h7A,10'bxx_xxxx_xxxx}: new_op = {ea_push, 8'h7B, rtmpl,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b10,
// Phase 123 : CXP : New EA for PC , Output of Interrupt-Vector and LOAD_PC generation, continue a
{8'h7B,10'bxx_xxxx_xxxx}: new_op = {save_sp, 8'h4A, rtmph,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// +++++++++++++++ here comes the general Exception Processing ++++++++++++++++++
 
// Phase 0 : Entry with saving of PC_ARCHI and PSR
{8'h00,10'b11_xxxx_xxxx}: new_op = {save_pc, 8'h80, src_x,src_x, 1'b0,dest_x, op_psr, 2'b00,2'b00,
// Phase 128 : different paths to three cases
{8'h80,10'bxx_xxxx_xxxx}: new_op = abo_int ?
{ai_next[30:4], src_x,src_x, 1'b1,temp_l, op_adr, 2'b00,2'b00, ai_next[3:0]}
: {get_vec, 8'h81, src_x,ibase, 1'b1,temp_l, op_adr, 2'b00,2'b00, 4'h1};
// Phase 129 : read of Exception-Vectors and store in TEMP_H , then continue at CXP if DE off
{8'h81,10'bxx_xxxx_xxxx}: new_op = de_flag ?
{addr_nop,8'h79, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0}
: {addr_nop,8'h39, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0};
// Phase 130 : read of Interrupt-Vectors, Zero-Extension of Byte => TEMP_H
{8'h82,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h83, imme, src_x, 1'b1,temp_h, op_zex, 2'b00,2'b00,
// Phase 131 : access of Exception-Vector
{8'h83,10'bxx_xxxx_xxxx}: new_op = (type_nmi | ~ivec_flag) ? // NMI or non-vectored INT ?
{get_vec, 8'h81, src_x,ibase, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}
: {get_veci,8'h81, rtmph,ibase, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1};
// Phase 132 : ABORT : store TEAR
{8'h84,10'bxx_xxxx_xxxx}: new_op = {save_msr,8'h85, src_x,src_x, 1'b1,w_tear, op_adr, 2'b00,2'b00,
// Phase 133 : store MSR
{8'h85,10'bxx_xxxx_xxxx}: new_op = (ssrc_flag | sdest_flag) ?
{addr_nop,rrepa, src_x,src_x, 1'b1,w_msr, op_adr, 2'b00,2'b00, 4'h0}
: {get_vec ,8'h81, src_x,ibase, 1'b1,w_msr, op_adr, 2'b00,2'b00, 4'h1};
// Phase 134 : reload of pointers for string opcodes : R2 Dest
{8'h86,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h87, rtmp1,src_x, 1'b1,6'h02, op_mov, 2'b00,2'b00,
// Phase 135 : reload of pointers for string opcodes : R1 Source
{8'h87,10'bxx_xxxx_xxxx}: new_op = {get_vec ,8'h81, rtmph,ibase, 1'b1,6'h01, op_mov, 2'b00,2'b00,
// +++++++++++++++++ WAIT +++++++++++++++++++++++++++++++++
{8'h88,10'bxx_xxxx_xxxx}: new_op = interrupt ?
{addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} // wait ...
: {addr_nop,8'h88, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; // Loop
// +++++++++++++++++ FLAG +++++++++++++++++++++++++++++++++
{8'h89,10'bxx_xxxx_xxxx}: new_op = flag ?
{save_pc, 8'h80, src_x,src_x, 1'b0,dest_x, op_psr, 2'b00,2'b00, 4'h0} // TRAP
: {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; // continue
// +++++++++++++++++ The Opcodes of Gruppe 2 +++++++++++++++
{8'h00,10'b10_0xxx_xxxx}: new_op = state_0;
// Now the case with Index , the Long Operand is copied to OUT
{8'h00,10'b10_1xxx_xxxx}: new_op = {addr_nop,8'h50, src_1,src_1l,1'b0,dest_x, opera, 2'b00,~src2_f
{8'h5x,10'bxx_xxxx_xxxx}: new_op = state_group_50; // Gruppe 2 Opcodes
{8'h6x,10'bxx_xxxx_xxxx}: new_op = state_group_60; // Gruppe 2 Opcodes
// that is only for CVTP :
{8'h73,10'bxx_xxxx_x0xx}: new_op = {addr_nop,8'h00, src_x,src_x, 1'b1,dest_r, op_adr, 2'b00,2'b00,
{8'h73,10'bxx_xxxx_x1xx}: new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_x, op_adr, 2'b00,2'b10,
// that is only for LMR and CINV :
{8'h74,10'bxx_xxxx_xxxx}: new_op = (IC_READ | STOP_CINV) ?
{ivar_adr,8'h74, rtmph,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} // wait ...
: {ivar_adr,8'h75, rtmph,src_x, 1'b1,lmrreg, op_lmr, 2'b00,2'b00, 4'h0}; // continue
{8'h75,10'bxx_xxxx_xxxx}: new_op = {ivar_adr,8'h4F, rtmph,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00,
// +++++++++++++++++ The String Opcodes +++++++++++++++++++++
// Phase 192 : R0=0 ?
{8'hC0,10'bxx_xxxx_xxxx}: new_op = STRING[2] ? // Is R0<>0 ?
{st_src, ph_str,rstr1,rstr1, ~kurz_st,temp_h, op_mov, 2'b00,2'b00, 4'h0}
: {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0};
// Phase 193 : 1. part read of SRC-Register => EA
{8'hC1,10'bxx_xxxx_xxxx}: new_op = {st_len, 8'hC2, src_x,src_x, 1'b1,wstr1, op_adr, 2'b00,2'b00,
// Phase 194 : memory operation : read
{8'hC2,10'bxx_xxxx_xxxx}: new_op = mt_flag ?
{addr_nop,8'hD3, imme, src_x, 1'b1,temp_2, (op_feld_reg[14] ? op_zex : op_mov),
2'b00,2'b00, 4'h0}
: {load_ea, 8'hC3, imme, rstr2, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'h0};
// Phase 195 : Data in output register and at the same time R2 to EA
{8'hC3,10'bxx_xxxx_xxxx}: new_op = {st_dest, 8'hC4, rstr2,imme, ~kurz_st,temp_1, op_mov, 2'b00,2'b
// Phase 196 : 1. part reuse EA and LSD of 8B data to Out-Register
{8'hC4,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hC5, src_x,src_x, 1'b1,wstr2, op_adr, 2'b00,2'b00,
// Phase 197 : memory operation : write
{8'hC5,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hC7, rstr0,src_x, 1'b1,wstr0, op_str, 2'b00,2'b00,
// Phase 199 : Test for End and Interrupt
{8'hC7,10'bxx_xxxx_xxxx}: new_op = (interrupt & ~kurz_st) ?
{save_pc, 8'h80, src_x,src_x, 1'b0,dest_x, op_psr, 2'b00,2'b00, 4'h0} // Interrupt !
: ( STRING[2] ? // Is R0<>0 ?
{st_src, ph_str,rstr1,rstr1, ~kurz_st,temp_h, op_mov, 2'b00,2'b00, 4'h0}
: {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} );
// String Compare :
// Phase 201 : 1. part read of SRC-Register => EA
{8'hC9,10'bxx_xxxx_xxxx}: new_op = {st_len, 8'hCA, src_x,src_x, 1'b1,wstr1, op_adr, 2'b00,2'b00,
// Phase 202 : memory operation : read
{8'hCA,10'bxx_xxxx_xxxx}: new_op = mt_flag ?
{addr_nop,8'hDB, imme, src_x, 1'b1,temp_2, (op_feld_reg[14] ? op_zex : op_mov),
2'b00,2'b00, 4'h0}
: ( skps_flag ? // SKPS read only String1
{addr_nop,8'hC7, rstr0,src_x, 1'b1,wstr0, op_str, 2'b00,2'b00, 4'h0}
: {load_ea, 8'hCB, imme, rstr2, 1'b1,temp_2, op_mov, 2'b00,2'b00, 4'h0} );
// Phase 203 : Data to output register and at the same time R2 to EA
{8'hCB,10'bxx_xxxx_xxxx}: new_op = {st_src2, 8'hCC, rstr2,src_x, ~kurz_st,temp_1, op_mov, 2'b00,2'b
// Phase 204 : 1. part reuse EA
{8'hCC,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hCD, src_x,src_x, 1'b1,wstr2, op_adr, 2'b00,2'b00,
// Phase 205 : memory operation : read and prepare compare
{8'hCD,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hCE, rtmp2,imme, 1'b0,dest_x, op_scp, 2'b00,2'b10,
// Phase 206 : compare of data
{8'hCE,10'bxx_xxxx_xxxx}: new_op = STRING[3] ? // Elements equal ? Same as ACB_ZERO without delay o
{addr_nop,8'hC7, rstr0,src_x, 1'b1,wstr0, op_str, 2'b00,2'b00, 4'h0}
: ( kurz_st ? // at CMPM direct end
{addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}
: {addr_nop,8'hC8, rtmph,src_x, 1'b1,6'h01, op_mov, 2'b00,2'b00, 4'h0} );
// Phase 200 : reload of R1 at CMPS, prepare reload of R2
{8'hC8,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, rtmp1,src_x, 1'b1,6'h02, op_mov, 2'b00,2'b00,
// String Options Match and Translate for MOVS
// Phase 211 : Test if Translate
{8'hD3,10'bxx_xxxx_xxxx}: new_op = op_feld_reg[14] ? // Translate ? Translate Base is Register 3
{st_trans,8'hD4, rtmp2,7'h03, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}
: {addr_nop,8'hD7, rtmp2,7'h04, 1'b0,dest_x, op_scp, 2'b00,2'b10, 4'h0}; // Match
// Phase 212 : memory operation : read
{8'hD4,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hD5, imme, src_x, 1'b1,temp_2, op_mov, 2'b00,2'b10,
// Phase 213 : Test if Match
{8'hD5,10'bxx_xxxx_xxxx}: new_op = op_feld_reg[16] ? // Match ? Reference Value is Register 4
{addr_nop,8'hD7, rtmp2,7'h04, 1'b0,dest_x, op_scp, 2'b00,2'b10, 4'h0}
: {st_trde, 8'hC4, 7'h02,7'h02, 1'b1,temp_1, op_mov, 2'b00,2'b00, 4'h0}; // back to MOVS
// Phase 215 : Match result evaluation
{8'hD7,10'bxx_xxxx_xxxx}: new_op = (STRING[3] ^ op_feld_reg[17]) ? // Not equal? (op_feld_reg[17] =
{load_ea, 8'hC3, rtmp2,7'h02, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'h0} // back to MOVS
: {addr_nop,8'h00, rtmph,src_x, 1'b1,6'h01, op_mov, 2'b00,2'b00, 4'h0}; // Abort, R1 ba
// String Options Match and Translate for CMPS and SKPS - to many options to get it in one state
// Phase 218 : Test if Translate
{8'hDB,10'bxx_xxxx_xxxx}: new_op = op_feld_reg[14] ? // Translate ? Translate Base is Register 3
{st_trans,8'hDC, rtmp2,7'h03, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}
: {addr_nop,8'hDF, rtmp2,7'h04, 1'b0,dest_x, op_scp, 2'b00,2'b10, 4'h0}; // Match
// Phase 220 : memory operation : read
{8'hDC,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hDD, imme, src_x, 1'b1,temp_2, op_mov, 2'b00,2'b10,
// Phase 221 : Test if Match
{8'hDD,10'bxx_xxxx_xxxx}: new_op = op_feld_reg[16] ? // Match ? Reference value is Register 4
{addr_nop,8'hDF, rtmp2,7'h04, 1'b0,dest_x, op_scp, 2'b00,2'b10, 4'h0}
: ( skps_flag ? // SKPS read only String1
{addr_nop,8'hC7, 7'h00,src_x, 1'b1,6'h00, op_str, 2'b00,2'b00, 4'h0} // back to SKPS
: {st_trs2, 8'hCC, 7'h02,7'h02, 1'b1,temp_1, op_mov, 2'b00,2'b00, 4'h0}); // back to CMP
// Phase 223 : Match result evaluation
{8'hDF,10'bxx_xxxx_xxxx}: new_op = (STRING[3] ^ op_feld_reg[17]) ? // Not equal? (op_feld_reg[17] =
( skps_flag ? // SKPS read only String1
{addr_nop,8'hC7, 7'h00,src_x, 1'b1,6'h00, op_str, 2'b00,2'b00, 4'h0} // back to SKPS
: {st_trs2, 8'hCC, 7'h02,7'h02, 1'b1,temp_1, op_mov, 2'b00,2'b00, 4'h0} ) // back to CMP
: {addr_nop,8'h00, rtmph,src_x, 1'b1,6'h01, op_mov, 2'b00,2'b00, 4'h0}; // Abort, R1 ba
 
default : new_op = 67'hx_xxxx_xxxx_xxxx_xxxx;
endcase
 
// ++++++++++++++++++++++++ Deliver data of state machine ++++++++++++++++++++++++++++
// not all new_op bits are evaluated here ...
always @(posedge BCLK or negedge BRESET)
if (!BRESET) ACC_FELD[11:10] <= 2'b00; // RD WR
else if (next) ACC_FELD[11:10] <= new_op[64:63];
always @(posedge BCLK or negedge BRESET)
if (!BRESET) spupd_i <= 1'b0; // Stack Pointer Update
else if (next) spupd_i <= new_op[56];
always @(posedge BCLK or negedge BRESET)
if (!BRESET) oper_i <= 11'b0;
else if (next) oper_i <= new_op[18:8];
always @(posedge BCLK)
if (next)
begin
ACC_FELD[13:12] <= new_op[66:65]; // ASIZE[1:0]
ACC_FELD[8:0] <= {new_op[61:57],new_op[51:48]}; // FULLACC INDEX[3:0] POST CLRMSW SRC2SEL[1:0]
disp_sel <= new_op[55:52];
wradr_i <= new_op[24:19];
end
always @(posedge BCLK) wmaske_i <= src2_le; // to simple ?
always @(posedge BCLK) index_cmd <= (phase_reg == 8'h60); // that only for INDEX
// WMASKE : SP always 32 Bit, opcodes in Format 1, Reg-Nr. >31 , INDEX opcodes and the CHECK operan
assign WMASKE = {(spupd | format1 | wradr_i[5] | wmaske_i[1] | index_cmd | (oper_i[7:0] == 8'h83)),
assign WRADR = spupd ? {~stack[5],stack[4:0]} : wradr_i;
assign WREN = (spupd | wren_i) & no_trap;
assign OPER = spupd ? op_adr : oper_i;
always @(posedge BCLK) ACC_FELD[14] <= next & (new_op[64] | new_op[63] | new_op[62]); // NEWACC is
always @(posedge BCLK) ACC_FELD[9] <= next & new_op[62]; // LDEA is only one pulse
always @(posedge BCLK) START <= next ? new_op[7:6] : 2'b00;
always @(posedge BCLK) ldoreg <= next ? new_op[5:4] : 2'b00; // [1] = LD_OUT , [0] = LD_LDQ
always @(posedge BCLK) wren_i <= next & new_op[25] & ~new_op[7]; // only if no START[1] from Long-O
assign LD_OUT = {(ldoreg[1] & no_trap),ldoreg[0]}; // [1] = LD_OUT (for CMP too) , [0] = LD_LDQ
assign spupd = spupd_i & ~wren_i & ~ldoreg[1] & ~spu_block; // no Stack Update if OUT Register load
assign do_long = new_op[7]; // START[1] for long_reg
assign RDAA = {next,new_op[39:33]}; // Source 1
assign RDAB = {next,new_op[32:26]}; // Source 2
always @(posedge BCLK) if (next) WR_REG = new_op[25] & new_op[7]; // START[1] : if WR then LONG pat
// special case : example is POLYL F2,TOS
always @(posedge BCLK) spu_block <= DONE & WR_REG;
assign MMU_UPDATE[1] = (phase_reg == 8'h84) | (phase_reg == 8'h85); // serving the MMU at ABORT
// only the real access gets USER Status : important for Memory Relative & External
always @(posedge BCLK) // MOVUS MOVSU RDVAL/WRVAL
if (ACC_FELD[14]) dc_user <= PSR[8] | (m_ussu & (m_usel ? (phase_reg == 8'h07) : (phase_reg == 8'h
else dc_user <= dc_user & ~abort;
always @(posedge BCLK) dc_ilo <= op_ilo & (phase_reg == 8'h59);
always @(posedge BCLK) ILO <= op_ilo & ((phase_reg == 8'h59) | (phase_reg == 8'h27));
assign RWVAL = {dc_ilo,(rwval_flag & (phase_reg == 8'h53)),wrval_flag}; // is used for DCACHE ILO t
// Signals for the I_PATH + Debug
assign DETOIP = {pc_match,cmps_flag,ph_match,op_feld_reg[17],kill_opt,inss_op,exin_cmd,extract,bit_
 
// Signals for the ADDR_UNIT : [5]=RMW Signal
assign chk_rmw = (phase_reg == 8'h17) | (phase_reg == 8'h58) | ((phase_reg == 8'h59) & rw_bit); //
assign INFO_AU = {no_trap,chk_rmw,(op_feld_reg[40:39] == 2'b11),RWVAL[1],(a_ivar & ~IC_READ),dc_use
assign RESTART = (phase_reg == 8'h4D);
 
// Signals to generate external STATUS
assign GENSTAT[2] = (phase_reg == 8'h88); // WAIT Signal
assign GENSTAT[1] = (phase_reg == 8'h82); // Interrupt Acknowlege Cycle
assign GENSTAT[0] = (phase_reg == 8'h45); // End-of-Interrupt Cycle
// ++++++++++++++++++++ Here is the Sub-Modul for the opcodes of Gruppe 2 ++++++++++++++++
GRUPPE_2 reste_ops (.BCLK(BCLK), .PHASE_0(PHASE_0), .OPREG(OPREG[13:0]), .PHASE(phase_ein[3:0]),
.SRC_1(src_1), .SRC_2(src_2), .REGA1(rega1), .REGA2(rega2), .IRRW1(irrw1), .IRRW2(irrw2),
.ADRD1(adrd1), .ADRD2(adrd2), .EXR12(exr12), .EXR22(exr22), .PHRD1(phrd1[3:0]), .PHRD2(phrd2[3
.NXRD1(nxrd1), .NXRW2(nxrw2), .ACCA({acc1,1'b0,acc2,1'b0}), .OPERA(opera),
.STATE_0(state_0), .STATE_GROUP_50(state_group_50), .STATE_GROUP_60(state_group_60) );
endmodule
/trunk/rtl/REGISTERS.v
0,0 → 1,324
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: REGISTERS.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// 1. CONFIG_REGS Configuration and Debug Registers
// 2. FP_STAT_REG Floating Point Status Register
// 3. REGISTER General Purpose Registers
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. CONFIG_REGS Configuration and Debug Registers
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module CONFIG_REGS ( BCLK, BRESET, WREN, LD_OUT, OPCODE, SRC1, WRADR, PC_ARCHI, USER, PCMATCH, DBG_H
CFG, MCR, PTB_WR, PTB_SEL, IVAR, CINV, Y_INIT, DSR, DBG_TRAPS, DBG_IN );
 
input BCLK,BRESET;
input WREN,LD_OUT;
input [7:0] OPCODE;
input [31:0] SRC1;
input [5:0] WRADR;
input [31:0] PC_ARCHI;
input USER;
input PCMATCH;
input DBG_HIT;
input READ;
output [12:0] CFG;
output [3:0] MCR;
output PTB_WR;
output PTB_SEL;
output [1:0] IVAR;
output [3:0] CINV;
output Y_INIT;
output [3:0] DSR;
output [2:0] DBG_TRAPS;
output [40:2] DBG_IN;
reg [3:0] MCR;
reg [12:0] CFG;
reg [1:0] old_cfg;
reg PTB_WR,PTB_SEL;
reg ivarreg;
reg [1:0] ci_all,ci_line;
reg check_y;
 
wire ld_cfg,ld_mcr,do_cinv;
wire init_ic,init_dc;
wire op_ok;
 
assign op_ok = (OPCODE == 8'h6A); // Special Opcode - for security reason
assign ld_cfg = op_ok & (WRADR == 6'h1C) & WREN;
assign ld_mcr = op_ok & (WRADR == 6'd9) & WREN;
assign do_cinv = op_ok & (WRADR[5:4] == 2'b11) & WREN;
// PF is not implemented
always @(posedge BCLK or negedge BRESET)
if (!BRESET) CFG <= 13'h0;
else if (ld_cfg) CFG <= SRC1[12:0];
always @(posedge BCLK or negedge BRESET)
if (!BRESET) MCR <= 4'h0;
else if (ld_mcr) MCR <= SRC1[3:0];
 
always @(posedge BCLK) ivarreg <= op_ok & (WRADR[5:1] == 5'd7) & WREN; // IVAR0/1 = Reg. Nr. 14/15
assign IVAR = {ivarreg,PTB_SEL};
always @(posedge BCLK) PTB_WR <= op_ok & (WRADR[5:1] == 5'd6) & WREN; // PTB0/1 = Reg. Nr. 12/13
always @(posedge BCLK) PTB_SEL <= WRADR[0];
// The Cache content will be invalid if the Enable-Bit is set to 0
always @(posedge BCLK) old_cfg <= {CFG[11],CFG[9]};
// Cache Invalidate : the Flags are coming out of the Short-field which is otherwise used for Regis
always @(posedge BCLK) ci_all <= do_cinv & WRADR[2] ? WRADR[1:0] : 2'b0; // clear all
always @(posedge BCLK) ci_line <= do_cinv & ~WRADR[2] ? WRADR[1:0] : 2'b0; // clear cache line
assign init_ic = old_cfg[1] & (~CFG[11] | ci_all[1]);
assign init_dc = old_cfg[0] & (~CFG[9] | ci_all[0]);
assign CINV = {init_ic,ci_line[1],init_dc,ci_line[0]};
// Y_INIT is neccessary if nothing has changed and therefore no DC/IC_INIT is generated
always @(posedge BCLK) check_y <= ld_cfg | do_cinv;
assign Y_INIT = check_y & ~init_ic & ~init_dc; // goes to register "old_init"
// +++++++++++++ DEBUG Unit +++++++++++++++
 
reg [3:0] DSR;
reg [12:0] dcr;
reg [31:0] bpc;
reg [31:2] car;
wire op_dbg,ld_dcr,ld_bpc,ld_dsr,ld_car;
wire enable;
assign op_dbg = (OPCODE == 8'h76);
assign ld_dcr = op_dbg & (WRADR == 6'h11) & WREN;
assign ld_bpc = op_dbg & (WRADR == 6'h12) & WREN;
assign ld_dsr = op_dbg & (WRADR == 6'h13) & WREN;
assign ld_car = op_dbg & (WRADR == 6'h14) & WREN;
 
assign enable = dcr[12] & (USER ? dcr[10] : dcr[11]); // DEN & (USER ? UD : SD)
always @(posedge BCLK or negedge BRESET)
if (!BRESET) dcr <= 13'd0;
else if (ld_dcr) dcr <= {SRC1[23:19],SRC1[7:0]};
always @(posedge BCLK) if (ld_bpc) bpc <= SRC1;
always @(posedge BCLK) if (ld_car) car <= SRC1[31:2];
// DEN SD DEN UD CAE CRD CAE CWR VNP/CBE CAR
assign DBG_IN = {(dcr[12] & dcr[11]),(dcr[12] & dcr[10]),(dcr[7] & dcr[6]),(dcr[7] & dcr[5]),dcr[4:
always @(posedge BCLK or negedge BRESET)
if (!BRESET) DSR <= 4'd0;
else
if (ld_dsr) DSR <= SRC1[31:28];
else
begin
DSR[3] <= DBG_HIT ? READ : DSR[3];
DSR[2] <= DSR[2] | PCMATCH;
DSR[1] <= DSR[1];
DSR[0] <= DSR[0] | DBG_HIT;
end
 
assign DBG_TRAPS[0] = enable & dcr[9] & (PC_ARCHI == bpc); // dcr[9]=PCE
assign DBG_TRAPS[1] = DBG_HIT; // Compare Adress Hit
assign DBG_TRAPS[2] = dcr[8]; // TR, Trap enable
 
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. FP_STAT_REG Floating Point Status Register
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module FP_STAT_REG ( BCLK, BRESET, LFSR, UP_SP, UP_DP, TT_SP, TT_DP, WREN, WRADR, DIN, FSR, TWREN, F
input BCLK;
input BRESET;
input LFSR; // Load by LFSR opcode
input UP_SP,UP_DP; // update if calculation operation
input [4:0] TT_SP,TT_DP;
input WREN; // for RMB and LFSR
input [5:4] WRADR;
input [16:0] DIN; // Data for LFSR opcode
output [31:0] FSR;
output TWREN;
output reg FPU_TRAP;
output SAVE_PC;
reg [4:3] trap_d;
reg update_d;
reg set_rm_d;
reg [10:0] set_bits;
reg [4:0] flags;
reg rm_bit;
wire load_fsr;
wire update,update_i;
wire [4:0] trap;
wire uflag,iflag,rmflag;
 
assign load_fsr = LFSR & WREN;
assign trap = UP_SP ? TT_SP : TT_DP;
// This signal suppresses write into registers if FPU Trap, timing critical signal !
assign TWREN = ~((UP_SP & (TT_SP[2:0] != 3'b0)) | (UP_DP & (TT_DP[2:0] != 3'b0)));
always @(posedge BCLK or negedge BRESET)
if (!BRESET) FPU_TRAP <= 1'b0;
else FPU_TRAP <= ~FPU_TRAP & ~TWREN; // one pulse of one cycle informs the Opcode Decoder
assign update_i = (UP_SP | UP_DP) & ~FPU_TRAP; // unfortunately one FPU opcode may follow !
always @(posedge BCLK) update_d <= update_i;
always @(posedge BCLK) trap_d <= trap[4:3];
always @(posedge BCLK) set_rm_d <= WREN & (WRADR == 2'b10);
assign update = update_d & ~FPU_TRAP;
// The Flags are set and stay "1"
assign iflag = (update & trap_d[4]) | flags[4]; // Inexact Result
assign uflag = (update & trap_d[3]) | flags[3]; // Underflow
assign rmflag = (set_rm_d & ~FPU_TRAP) | rm_bit; // Register Modify
 
always @(posedge BCLK or negedge BRESET)
if (!BRESET) flags[4:3] <= 2'b0; // Inexact = Bit6, Underflow = Bit4
else
begin
if (load_fsr) flags[4:3] <= {DIN[6],DIN[4]};
else
if (update) flags[4:3] <= {iflag,uflag};
end
always @(posedge BCLK or negedge BRESET)
if (!BRESET) flags[2:0] <= 3'b0; // TT Field = Bit2-0
else
begin
if (load_fsr) flags[2:0] <= DIN[2:0];
else
if (update_i) flags[2:0] <= trap[2:0];
end
always @(posedge BCLK or negedge BRESET)
if (!BRESET) rm_bit <= 1'b0; // Register Modify Bit
else
begin
if (load_fsr) rm_bit <= DIN[16];
else
if (set_rm_d & ~FPU_TRAP) rm_bit <= 1'b1; // in case of TRAP there is no writing to Register
end
always @(posedge BCLK or negedge BRESET)
if (!BRESET) set_bits <= 11'b0; // all other Bits
else
if (load_fsr) set_bits <= {DIN[15:7],DIN[5],DIN[3]};
 
assign FSR = {15'h0,rmflag,set_bits[10:2],iflag,set_bits[1],uflag,set_bits[0],flags[2:0]};
assign SAVE_PC = (UP_SP | UP_DP) & ~FPU_TRAP; // Store the correct PC for FPU Trap
endmodule
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 3. REGISTER General Purpose Registers
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module REGISTER( BCLK, ENWR, DOWR, BYDIN, DIN, RADR, WADR, WMASKE, DOUT, SELI );
 
input BCLK;
input DOWR,ENWR;
input [31:0] BYDIN,DIN;
input [7:0] RADR;
input [5:0] WADR;
input [1:0] WMASKE;
 
output [31:0] DOUT;
output reg SELI;
 
reg [2:0] MX;
 
wire [3:0] BE;
wire eq_rw;
 
// +++++++++++++++++++ Memories ++++++++++++++++++++
 
reg [7:0] REGFILE_D [0:63];
reg [7:0] REGFILE_C [0:63];
reg [7:0] REGFILE_B [0:63];
reg [7:0] REGFILE_A [0:63];
reg [31:0] RF;
 
assign BE = {WMASKE[1],WMASKE[1],(WMASKE[1] | WMASKE[0]),1'b1};
 
assign eq_rw = ENWR & (RADR[5:0] == WADR);
 
always @(posedge BCLK) if (RADR[7]) MX[2:0] <= BE[2:0] & {{3{eq_rw}}};
 
always @(posedge BCLK) if (RADR[7]) SELI <= RADR[6];
 
assign DOUT[31:16] = MX[2] ? BYDIN[31:16] : RF[31:16];
assign DOUT[15:8] = MX[1] ? BYDIN[15:8] : RF[15:8];
assign DOUT[7:0] = MX[0] ? BYDIN[7:0] : RF[7:0];
// ++++++++++++++++ Register File 64 * 32 Bits ++++++++++++
 
always @(posedge BCLK)
if (RADR[7])
begin
RF[31:24] <= REGFILE_D[RADR[5:0]];
RF[23:16] <= REGFILE_C[RADR[5:0]];
RF[15:8] <= REGFILE_B[RADR[5:0]];
RF[7:0] <= REGFILE_A[RADR[5:0]];
end
 
always @(posedge BCLK)
if (DOWR)
begin
if (BE[3]) REGFILE_D[WADR] <= DIN[31:24];
if (BE[2]) REGFILE_C[WADR] <= DIN[23:16];
if (BE[1]) REGFILE_B[WADR] <= DIN[15:8];
if (BE[0]) REGFILE_A[WADR] <= DIN[7:0];
end
 
endmodule
 
/trunk/rtl/DCACHE.v
0,0 → 1,497
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: DCACHE.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// DCACHE the data cache of M32632
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module DCACHE( BCLK, MCLK, WRCFG, MDONE, BRESET, PTB_WR, PTB_SEL, IO_READY, REG_OUT, PSR_USER, WRIT
WAMUX, ENWR, IC_PREQ, FILLRAM, CFG, CINVAL, DMA_AA, DP_Q, DRAM_Q, IC_VA, ICTODC, IO_Q, IVAR, MCR
PACKET, SIZE, VADR, WADDR, WCTRL, IO_RD, IO_WR, DRAM_ACC, DRAM_WR, INIT_RUN, PTE_STAT, KDET, HLD
ACC_STAT, DP_DI, DRAM_A, DRAM_DI, IACC_STAT, IC_SIGS, IO_A, IO_BE, IO_DI, KOLLI_A, MMU_DIN, ZTES
RWVAL, RWVFLAG, DBG_IN, DBG_HIT, ENDRAM );
 
input BCLK;
input MCLK;
input WRCFG;
input MDONE;
input BRESET;
input PTB_WR;
input PTB_SEL;
input IO_READY;
input REG_OUT;
input PSR_USER;
input WRITE;
input READ;
input ZTEST;
input RMW;
input WAMUX;
input ENWR;
input IC_PREQ;
input FILLRAM;
input [1:0] CFG;
input [1:0] CINVAL;
input [27:4] DMA_AA;
input [63:0] DP_Q;
input [31:0] DRAM_Q;
input [31:12] IC_VA;
input [3:0] ICTODC;
input [31:0] IO_Q;
input [1:0] IVAR;
input [3:0] MCR_FLAGS;
input [3:0] PACKET;
input [1:0] SIZE;
input [31:0] VADR;
input [11:2] WADDR;
input [2:0] WCTRL;
input [2:0] RWVAL;
input [40:2] DBG_IN;
input ENDRAM;
 
output IO_RD;
output IO_WR;
output DRAM_ACC;
output DRAM_WR;
output INIT_RUN;
output [1:0] PTE_STAT;
output KDET;
output HLDA;
output RWVFLAG;
output [5:0] ACC_STAT;
output [31:0] DP_DI;
output [3:1] IACC_STAT;
output [1:0] IC_SIGS;
output [27:4] KOLLI_A;
output [23:0] MMU_DIN;
output reg [27:0] DRAM_A;
output reg [35:0] DRAM_DI;
output reg [31:0] IO_A;
output reg [3:0] IO_BE;
output reg [31:0] IO_DI;
output DBG_HIT;
 
reg [31:0] DFFE_IOR;
reg [31:0] CAPDAT;
reg [31:0] VADR_R;
reg AUX_ALT;
reg DFF_QWEXT;
 
wire [27:4] ADDR;
wire ADR_EQU;
wire AUX_DAT;
wire CA_HIT;
wire CA_SET;
wire CUPDATE;
wire DMA_MUX;
wire [3:0] ENBYTE;
wire HIT_ALL;
wire INIT_CA_RUN;
wire IO_ACC;
wire IO_SPACE;
wire KOMUX;
wire MMU_HIT;
wire NEW_PTB;
wire PTB_ONE;
wire [27:0] PTE_ADR;
wire [31:12] RADR;
wire [11:4] TAGA;
wire [23:0] UPDATE_C;
wire [31:0] UPDATE_M;
wire USE_CA;
wire USER;
wire WB_ACC;
wire WEMV;
wire WR_MRAM;
wire [31:0] WRDATA;
wire VIRT_A;
wire PTE_MUX;
wire WE_CV;
wire [23:0] DAT_CV;
wire [4:0] WADR_CV;
wire WRSET0;
wire [3:0] BE_SET;
wire [31:0] DAT_SET;
wire [9:0] A_SET;
wire WRSET1;
wire SEL_PTB1;
wire CI;
wire [27:0] ADR_MX;
wire LD_DRAM_A;
wire VIRTUELL;
wire NEW_PTB_RUN;
wire KILL;
wire LAST_MUX;
wire [31:0] SET_DAT;
wire [31:0] ALT_DAT;
wire [31:0] DAT_MV;
wire [3:0] RADR_MV;
wire [3:0] WADR_MV;
wire [31:0] LAST_DAT;
wire WRCRAM0;
wire WRCRAM1;
wire PROT_ERROR;
wire AUX_QW;
wire PD_MUX;
wire [19:0] PTE_DAT;
wire PKEEP;
 
// +++++++++++++++++++ Memories ++++++++++++++++++++
 
reg [7:0] DATA0_D [0:1023]; // Data Set 0 : 4 kBytes
reg [7:0] DATA0_C [0:1023];
reg [7:0] DATA0_B [0:1023];
reg [7:0] DATA0_A [0:1023];
reg [31:0] SET_DAT0;
 
reg [7:0] DATA1_D [0:1023]; // Data Set 1 : 4 kBytes
reg [7:0] DATA1_C [0:1023];
reg [7:0] DATA1_B [0:1023];
reg [7:0] DATA1_A [0:1023];
reg [31:0] SET_DAT1;
 
reg [15:0] TAGSET_0 [0:255]; // Tag Set for Data Set 0 : 256 entries of 16 bits
reg [15:0] TAG0;
 
reg [15:0] TAGSET_1 [0:255]; // Tag Set for Data Set 1 : 256 entries of 16 bits
reg [15:0] TAG1;
 
reg [23:0] CA_VALID [0:31]; // Valid bits for Data Set 0 and 1 : 32 entries of 24 bits
reg [23:0] CVALID;
 
reg [35:0] MMU_TAGS [0:255]; // Tag Set for MMU : 256 entries of 36 bits
reg [35:0] MMU_Q;
 
reg [31:0] MMU_VALID [0:15]; // Valid bits for MMU Tag Set : 16 entries of 32 bits
reg [31:0] MVALID;
 
assign ADR_EQU = ({RADR[27:12],VADR_R[11:4]} == DRAM_A[27:4]); // Limited to 256 MB
 
assign ALT_DAT = AUX_ALT ? DFFE_IOR : CAPDAT ;
 
assign RADR = VIRT_A ? MMU_Q[19:0] : VADR_R[31:12] ;
 
assign ADR_MX = PTE_MUX ? PTE_ADR : {RADR[27:12],VADR_R[11:2],USE_CA,CA_SET} ;
 
assign KOLLI_A = DMA_MUX ? DMA_AA : DRAM_A[27:4] ;
 
assign SET_DAT = CA_SET ? SET_DAT1 : SET_DAT0 ;
 
assign VIRT_A = ~CINVAL[0] & VIRTUELL;
 
assign USER = ~MCR_FLAGS[3] & PSR_USER;
 
assign DAT_SET = WRITE ? WRDATA : DRAM_Q ;
 
assign BE_SET = ENBYTE | {~WRITE,~WRITE,~WRITE,~WRITE};
 
assign ADDR = KOMUX ? KOLLI_A : {RADR[27:12],VADR_R[11:4]} ;
 
assign A_SET = WAMUX ? WADDR : VADR_R[11:2] ;
 
assign TAGA = KOMUX ? KOLLI_A[11:4] : VADR[11:4] ;
 
assign INIT_RUN = NEW_PTB_RUN | INIT_CA_RUN;
 
assign LAST_MUX = AUX_ALT | AUX_DAT | AUX_QW;
 
assign LAST_DAT = LAST_MUX ? ALT_DAT : SET_DAT ;
 
assign LD_DRAM_A = ~(DRAM_ACC | PKEEP);
 
assign ACC_STAT[4] = IO_ACC;
assign ACC_STAT[5] = CA_HIT;
 
always @(posedge BCLK)
if (IO_ACC)
begin
IO_BE <= ENBYTE;
IO_DI <= WRDATA;
IO_A <= {RADR[31:12],VADR_R[11:0]};
end
 
always @(posedge BCLK) if (LD_DRAM_A) DRAM_A[27:0] <= ADR_MX[27:0];
 
always @(posedge BCLK) if (IO_RD) DFFE_IOR <= IO_Q;
 
always @(posedge BCLK)
begin
DRAM_DI <= {(PD_MUX ? PTE_DAT[19:16] : ENBYTE),WRDATA[31:16],
(PD_MUX ? PTE_DAT[15:0] : WRDATA[15:0])};
AUX_ALT <= DFF_QWEXT | IO_RD;
DFF_QWEXT <= IO_RD & SIZE[0] & SIZE[1];
VADR_R <= VADR;
end
 
always @(posedge MCLK) if (WCTRL[2]) CAPDAT <= DRAM_Q;
 
// +++++++++++++++++++++++++ Cache Valid +++++++++++++++++++
 
always @(posedge BCLK) CVALID <= CA_VALID[TAGA[11:7]];
 
always @(negedge BCLK) if (WE_CV) CA_VALID[WADR_CV] <= DAT_CV;
 
// +++++++++++++++++++++++++ Tag Set 0 +++++++++++++++++++++
 
always @(posedge BCLK) TAG0 <= TAGSET_0[TAGA];
 
always @(negedge BCLK) if (WRCRAM0) TAGSET_0[VADR_R[11:4]] <= RADR[27:12];
 
// +++++++++++++++++++++++++ Tag Set 1 +++++++++++++++++++++
 
always @(posedge BCLK) TAG1 <= TAGSET_1[TAGA];
 
always @(negedge BCLK) if (WRCRAM1) TAGSET_1[VADR_R[11:4]] <= RADR[27:12];
 
// +++++++++++++++++++++++++ Data Set 0 ++++++++++++++++++++
 
always @(posedge BCLK)
begin
SET_DAT0[31:24] <= DATA0_D[VADR[11:2]];
SET_DAT0[23:16] <= DATA0_C[VADR[11:2]];
SET_DAT0[15:8] <= DATA0_B[VADR[11:2]];
SET_DAT0[7:0] <= DATA0_A[VADR[11:2]];
end
always @(posedge MCLK)
if (WRSET0)
begin
if (BE_SET[3]) DATA0_D[A_SET] <= DAT_SET[31:24];
if (BE_SET[2]) DATA0_C[A_SET] <= DAT_SET[23:16];
if (BE_SET[1]) DATA0_B[A_SET] <= DAT_SET[15:8];
if (BE_SET[0]) DATA0_A[A_SET] <= DAT_SET[7:0];
end
// +++++++++++++++++++++++++ Data Set 1 ++++++++++++++++++++
 
always @(posedge BCLK)
begin
SET_DAT1[31:24] <= DATA1_D[VADR[11:2]];
SET_DAT1[23:16] <= DATA1_C[VADR[11:2]];
SET_DAT1[15:8] <= DATA1_B[VADR[11:2]];
SET_DAT1[7:0] <= DATA1_A[VADR[11:2]];
end
always @(posedge MCLK)
if (WRSET1)
begin
if (BE_SET[3]) DATA1_D[A_SET] <= DAT_SET[31:24];
if (BE_SET[2]) DATA1_C[A_SET] <= DAT_SET[23:16];
if (BE_SET[1]) DATA1_B[A_SET] <= DAT_SET[15:8];
if (BE_SET[0]) DATA1_A[A_SET] <= DAT_SET[7:0];
end
 
DCACHE_SM DC_SM(
.BCLK(BCLK),
.BRESET(BRESET),
.VIRTUELL(VIRTUELL),
.IO_SPACE(IO_SPACE),
.MDONE(MDONE),
.MMU_HIT(MMU_HIT),
.CA_HIT(CA_HIT),
.READ(READ),
.WRITE(WRITE),
.ZTEST(ZTEST),
.RMW(RMW),
.USE_CA(USE_CA),
.PTB_WR(PTB_WR),
.PTB_SEL(PTB_SEL),
.SEL_PTB1(SEL_PTB1),
.IO_READY(IO_READY),
.USER(USER),
.PROTECT(ACC_STAT[3]),
.PROT_ERROR(PROT_ERROR),
.ENWR(ENWR),
.WB_ACC(WB_ACC),
.ADR_EQU(ADR_EQU),
.IC_PREQ(IC_PREQ),
.CAPDAT(CAPDAT[31:0]),
.CPU_OUT(DP_Q[59:44]),
.FILLRAM(FILLRAM),
.IC_VA(IC_VA),
.ICTODC(ICTODC),
.VADR_R(VADR_R[31:12]),
.NEW_PTB(NEW_PTB),
.PTB_ONE(PTB_ONE),
.DRAM_ACC(DRAM_ACC),
.DRAM_WR(DRAM_WR),
.IO_ACC(IO_ACC),
.IO_RD(IO_RD),
.IO_WR(IO_WR),
.PTE_STAT(PTE_STAT),
.ABORT(ACC_STAT[1]),
.WR_MRAM(WR_MRAM),
.CUPDATE(CUPDATE),
.AUX_DAT(AUX_DAT),
.PTE_MUX(PTE_MUX),
.ACC_OK(ACC_STAT[0]),
.ABO_LEVEL1(ACC_STAT[2]),
.IACC_STAT(IACC_STAT),
.KOMUX(KOMUX),
.KDET(KDET),
.HIT_ALL(HIT_ALL),
.DMA_MUX(DMA_MUX),
.HLDA(HLDA),
.RWVAL(RWVAL[1:0]),
.RWVFLAG(RWVFLAG),
.IC_SIGS(IC_SIGS),
.MMU_DIN(MMU_DIN),
.PD_MUX(PD_MUX),
.PKEEP(PKEEP),
.PTE_ADR(PTE_ADR),
.PTE_DAT(PTE_DAT));
 
CA_MATCH DCA_COMPARE(
.INVAL_L(CINVAL[0]),
.CI(CI),
.MMU_HIT(MMU_HIT),
.WRITE(WRITE),
.KDET(KDET),
.ADDR(ADDR),
.CFG(CFG),
.ENDRAM(ENDRAM),
.CVALID(CVALID),
.TAG0(TAG0),
.TAG1(TAG1),
.CA_HIT(CA_HIT),
.CA_SET(CA_SET),
.WB_ACC(WB_ACC),
.USE_CA(USE_CA),
.IOSEL(RADR[31:28]),
.IO_SPACE(IO_SPACE),
.KILL(KILL),
.DC_ILO(RWVAL[2]),
.UPDATE(UPDATE_C));
 
DCA_CONTROL DCA_CTRL(
.BCLK(BCLK),
.MCLK(MCLK),
.BRESET(BRESET),
.CA_SET(CA_SET),
.HIT_ALL(HIT_ALL),
.UPDATE(UPDATE_C),
.VADR_R(ADDR[11:7]),
.DRAM_ACC(DRAM_ACC),
.CUPDATE(CUPDATE),
.KILL(KILL),
.WRITE(WRITE),
.WRCFG(WRCFG),
.WCTRL(WCTRL[1:0]),
.INVAL_A(CINVAL[1]),
.DAT_CV(DAT_CV),
.WADR_CV(WADR_CV),
.WE_CV(WE_CV),
.INIT_CA_RUN(INIT_CA_RUN),
.WRCRAM0(WRCRAM0),
.WRCRAM1(WRCRAM1),
.WRSET0(WRSET0),
.WRSET1(WRSET1));
 
MMU_MATCH MMU_COMPARE(
.USER(USER),
.WRITE(WRITE),
.READ(READ),
.RMW(RMW),
.IVAR(IVAR),
.MCR_FLAGS(MCR_FLAGS[2:0]),
.MMU_VA(MMU_Q[35:20]),
.MVALID(MVALID),
.VADR_R(VADR_R[31:12]),
.MMU_HIT(MMU_HIT),
.PROT_ERROR(PROT_ERROR),
.VIRTUELL(VIRTUELL),
.CI(CI),
.SEL_PTB1(SEL_PTB1),
.UPDATE(UPDATE_M));
 
MMU_UP MMU_CTRL(
.BCLK(BCLK),
.BRESET(BRESET),
.NEW_PTB(NEW_PTB),
.IVAR(IVAR[1]),
.PTB1(PTB_ONE),
.WR_MRAM(WR_MRAM),
.MVALID(MVALID),
.UPDATE(UPDATE_M),
.VADR(VADR[19:16]),
.VADR_R(VADR_R[19:16]),
.WE_MV(WEMV),
.NEW_PTB_RUN(NEW_PTB_RUN),
.DAT_MV(DAT_MV),
.RADR_MV(RADR_MV),
.WADR_MV(WADR_MV));
 
// +++++++++++++++++++++++++ MMU Valid +++++++++++++++++++++
 
always @(posedge BCLK) MVALID <= MMU_VALID[RADR_MV];
 
always @(negedge BCLK) if (WEMV) MMU_VALID[WADR_MV] <= DAT_MV;
 
// +++++++++++++++++++++++++ MMU Tags ++++++++++++++++++++++
 
always @(posedge BCLK) MMU_Q <= MMU_TAGS[VADR[19:12]];
 
always @(negedge BCLK) if (WR_MRAM) MMU_TAGS[VADR_R[19:12]] <= {VADR_R[31:20],MMU_DIN[23:0]};
 
RD_ALIGNER RD_ALI(
.BCLK(BCLK),
.ACC_OK(ACC_STAT[0]),
.REG_OUT(REG_OUT),
.PACKET(PACKET),
.RDDATA(LAST_DAT),
.SIZE(SIZE),
.CA_HIT(CA_HIT),
.DP_DI(DP_DI),
.AUX_QW(AUX_QW));
 
WR_ALIGNER WR_ALI(
.DP_Q(DP_Q),
.PACKET(PACKET),
.SIZE(SIZE),
.ENBYTE(ENBYTE),
.WRDATA(WRDATA));
DEBUG_AE DBGAE(
.DBG_IN(DBG_IN),
.READ(READ),
.WRITE(WRITE),
.USER(USER),
.VIRTUELL(VIRTUELL),
.ACC_OK(ACC_STAT[0]),
.VADR_R(VADR_R[31:2]),
.MMU_Q(MMU_Q[19:0]),
.ENBYTE(ENBYTE),
.DBG_HIT(DBG_HIT));
 
endmodule
/trunk/rtl/ADDR_UNIT.v
0,0 → 1,348
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: ADDR_UNIT.v
// Version: 1.0
// Date: 30 May 2015
//
// Copyright (C) 2015 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// ADDR_UNIT generates data access addresses and controls data cache operation
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module ADDR_UNIT ( BCLK, BRESET, READ, WRITE, LDEA, NEWACC, CLRMSW, POST, DISP_OK, FULLACC, SRC2SEL,
DISP, PC_ARCHI, PC_ICACHE, IO_READY, ACC_STAT, MMU_UPDATE, IC_TEX, ABO_STAT, ADIVAR, RWVAL_1,
NO_TRAP, FPU_TRAP, READ_OUT, WRITE_OUT, ZTEST, RMW, VADR, ADDR, SIZE, PACKET, ACC_DONE, ABORT
 
input BCLK,BRESET;
input READ,WRITE,LDEA;
input NEWACC;
input CLRMSW,POST,FULLACC;
input [1:0] SRC2SEL;
input [3:0] INDEX;
input [1:0] ASIZE;
input [31:0] SRC1,SRC2;
input [1:0] BWD;
input [31:0] DISP;
input [31:0] PC_ARCHI,PC_ICACHE;
input DISP_OK;
input IO_READY;
input [5:0] ACC_STAT; // Feedback from data cache about the running access
input [1:0] MMU_UPDATE;
input [2:0] IC_TEX;
input [1:0] ABO_STAT;
input ADIVAR;
input RWVAL_1; // special access for RDVAL + WRVAL
input OP_RMW;
input PHASE_17;
input NO_TRAP;
input FPU_TRAP;
output READ_OUT,WRITE_OUT,ZTEST,RMW;
output [31:0] VADR;
output [31:0] ADDR;
output [1:0] SIZE;
output [3:0] PACKET;
output ACC_DONE;
output ABORT;
output REG_OUT;
output [2:0] BITSEL;
reg [31:0] VADR;
reg READ_OUT,write_reg,ZTEST,RMW;
reg [1:0] SIZE;
reg [3:0] PACKET;
reg [2:0] BITSEL;
reg [31:0] source2;
reg [31:0] index_val;
reg [31:0] vadr_reg;
reg [31:0] ea_reg;
reg [31:0] tos_offset;
reg [31:0] icache_adr;
reg [31:0] sign_ext_src1;
reg [31:12] pg_areg;
reg reg_out_i,next_reg;
reg ld_ea_reg;
reg acc_run,acc_ende,acc_step;
reg qwa_flag;
reg no_done;
reg frueh_ok;
reg io_rdy;
reg ABORT;
reg [1:0] tex_feld;
reg [2:0] u_ddt;
reg pg_op;
reg do_wr;
wire acc_ok,acc_err,io_acc;
wire acc_pass;
wire ca_hit;
wire [31:0] reg_adder;
wire [31:0] next_vadr;
wire [31:0] final_addr;
wire [31:0] pg_addr;
wire [1:0] inc_pack;
wire [3:0] index_sel;
wire ld_ea_i;
wire ea_ok;
wire qw_align;
wire init_acc;
wire in_page;
wire all_ok;
wire fa_out;
wire pg_test;
 
// ++++++++++++++++++++ Decoding ACC_STAT from data cache ++++++++++++++++++++++++++++
// ACC_STAT[5:0] : CA_HIT, IO_ACC, PROT_ERROR , ABO_LEVEL1 , ABORT , ACC_OK
assign ca_hit = ACC_STAT[5];
assign io_acc = ACC_STAT[4];
assign acc_err = ACC_STAT[3] | ACC_STAT[1]; // Abort or Protection Error
assign acc_ok = ACC_STAT[0] & ~pg_op;
assign acc_pass = ACC_STAT[0] & ZTEST;
always @(posedge BCLK) ABORT <= acc_err; // Signal to Steuerung - only a pulse
always @(posedge BCLK) if (acc_err) tex_feld <= ACC_STAT[3] ? 2'b11 : {~ACC_STAT[2],ACC_STAT[2]}; /
always @(posedge BCLK) if (acc_err) u_ddt <= {RMW,ABO_STAT[1],(WRITE_OUT | ZTEST)};
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
always @(SRC2SEL or CLRMSW or SRC2 or PC_ARCHI or ea_reg)
case (SRC2SEL)
2'b00 : source2 = {(CLRMSW ? 16'h0000 : SRC2[31:16]),SRC2[15:0]}; // base reg, External Addressi
2'b01 : source2 = PC_ARCHI; // PC relative
2'b10 : source2 = 32'h0; // Absolute Addressing
2'b11 : source2 = ea_reg; // REUSE : 2. TOS
endcase
assign index_sel = POST ? 4'h0 : INDEX; // Alternative application of Index for POST Adder : POP fr
always @(BWD or SRC1)
casex (BWD)
2'b00 : sign_ext_src1 = {{24{SRC1[7]}}, SRC1[7:0]}; // Byte
2'b01 : sign_ext_src1 = {{16{SRC1[15]}},SRC1[15:0]}; // Word
default : sign_ext_src1 = SRC1;
endcase
always @(index_sel or sign_ext_src1 or SRC1)
casex (index_sel)
 
4'b1_1xx : index_val = {{ 3{sign_ext_src1[31]}},sign_ext_src1[31:3]}; // for Bit Opcodes
4'b0_100 : index_val = SRC1;
4'b0_101 : index_val = {SRC1[30:0],1'b0};
4'b0_110 : index_val = {SRC1[29:0],2'b00};
4'b0_111 : index_val = {SRC1[28:0],3'b000};
default : index_val = 32'h0;
endcase
assign reg_adder = source2 + index_val; // SRC2 allows simple MOV with SRC1
assign final_addr = reg_adder + DISP; // That's the final access address
always @(posedge BCLK) if (LDEA && (index_sel[3:2] == 2'b11)) BITSEL <= SRC1[2:0]; // for Bit Opcod
always @(INDEX) // SP POP Operation & String Backward
case (INDEX[2:0])
3'b000 : tos_offset = 32'h0000_0001;
3'b001 : tos_offset = 32'h0000_0002;
3'b010 : tos_offset = 32'h0000_0004;
3'b011 : tos_offset = 32'h0000_0008;
3'b100 : tos_offset = 32'hFFFF_FFFF;
3'b101 : tos_offset = 32'hFFFF_FFFE;
3'b110 : tos_offset = 32'hFFFF_FFFC;
3'b111 : tos_offset = 32'hFFFF_FFF8;
endcase
always @(posedge BCLK or negedge BRESET)
if (!BRESET) ld_ea_reg <= 1'b0;
else ld_ea_reg <= (LDEA | ld_ea_reg) & ~DISP_OK;
assign ld_ea_i = (LDEA | ld_ea_reg) & DISP_OK;
assign ea_ok = (READ | WRITE | LDEA | ld_ea_reg) & ~FULLACC & DISP_OK;
always @(posedge BCLK) icache_adr <= PC_ICACHE;
// Memory for the calculated address for reuse and Register for POST modified addresses :
always @(posedge BCLK)
if (ld_ea_i)
begin
casex ({MMU_UPDATE[1],INDEX[0],POST})
3'b10x : ea_reg <= MMU_UPDATE[0] ? vadr_reg : icache_adr; // TEAR
3'b11x : ea_reg <= MMU_UPDATE[0] ?
{24'h0000_00,3'b101, u_ddt, tex_feld} // MSR
: {24'h0000_00,3'b100,IC_TEX[2],ABO_STAT[0],1'b0,IC_TEX[1:0]}; // only READ from ICACHE
3'b0x1 : ea_reg <= source2 + tos_offset ;
3'b0x0 : ea_reg <= final_addr;
endcase
end
assign ADDR = ea_reg; // used for ADDR opcode and TOS Addressing
// This pulse stores all parameters of access
assign init_acc = ((FULLACC ? (NEWACC & acc_ende) : acc_ende) | ~acc_run) & DISP_OK & (READ | WRITE
 
assign fa_out = init_acc | ADIVAR; // special case for LMR IVAR,...
always @(fa_out or acc_ok or final_addr or qw_align or pg_op or pg_areg or vadr_reg or next_vadr)
casex ({fa_out,acc_ok})
2'b1x : VADR = {final_addr[31:3],(final_addr[2] | qw_align),final_addr[1:0]};
2'b00 : VADR = pg_op ? {pg_areg,12'h0} : vadr_reg;
2'b01 : VADR = next_vadr;
endcase
 
always @(posedge BCLK)
if (init_acc) vadr_reg <= {final_addr[31:3],(final_addr[2] | qw_align),final_addr[1:0]};
else
if (pg_op && ZTEST && acc_err) vadr_reg <= {pg_areg,12'h0}; // for TEAR !
else
if (acc_ok) vadr_reg <= next_vadr;
assign next_vadr = qwa_flag ? {vadr_reg[31:3],3'b000} : ({vadr_reg[31:2],2'b00} + 32'h0000_0004);
// Logic for Page border WRITE Test
assign pg_addr = final_addr + {29'h0,(ASIZE[1] & ASIZE[0]),ASIZE[1],(ASIZE[1] | ASIZE[0])};
always @(posedge BCLK) if (init_acc) pg_areg <= pg_addr[31:12];
assign pg_test = (final_addr[12] != pg_addr[12]) & ~OP_RMW; // At RMW no Test necessary
always @(posedge BCLK or negedge BRESET)
if (!BRESET) pg_op <= 1'b0;
else
pg_op <= init_acc ? (WRITE & ~RWVAL_1 & pg_test) : (pg_op & ~acc_pass & ~acc_err);
always @(posedge BCLK) do_wr <= pg_op & ZTEST & acc_pass; // All ok, Page exists => continue
always @(posedge BCLK or negedge BRESET)
if (!BRESET) READ_OUT <= 1'b0;
else
READ_OUT <= init_acc ? (READ & ~RWVAL_1) : (READ_OUT & ~acc_ende & ~acc_err);
always @(posedge BCLK or negedge BRESET)
if (!BRESET) write_reg <= 1'b0;
else
write_reg <= (init_acc ? (WRITE & ~RWVAL_1 & ~pg_test) : (write_reg & ~acc_ende & ~acc_err & ~FPU
assign WRITE_OUT = write_reg & ~FPU_TRAP;
 
// Special case for RDVAL and WRVAL
always @(posedge BCLK or negedge BRESET)
if (!BRESET) ZTEST <= 1'b0;
else
ZTEST <= pg_op ? (~ZTEST | (~acc_pass & ~acc_err)) : (init_acc ? RWVAL_1 : (ZTEST & ~acc_ende &
always @(posedge BCLK or negedge BRESET)
if (!BRESET) RMW <= 1'b0;
else
RMW <= init_acc ? (OP_RMW & PHASE_17) : (RMW & ~acc_ende & ~acc_err);
// Special case : first MSD access by aligned QWORD READ
assign qw_align = (final_addr[2:0] == 3'b000) & READ & (ASIZE == 2'b11);
always @(posedge BCLK) if (init_acc) qwa_flag <= qw_align;
always @(posedge BCLK or negedge BRESET) // central flag that shows the ADDR_UNIT is busy
if (!BRESET) acc_run <= 1'b0;
else
acc_run <= init_acc | (acc_run & ~acc_ende & ~acc_err & ~FPU_TRAP);
always @(posedge BCLK) if (init_acc) SIZE <= ASIZE;
 
assign inc_pack = (PACKET[1:0] == 2'b00) ? 2'b10 : {(SIZE[1] ^ SIZE[0]),(SIZE[1] & SIZE[0])};
// Counter for data packets 1 to 3 : special case aligned QWORD : only 2 packets. Additionally star
// special coding (00) -> [01] -> (10) , [01] optional by QWORD and (10) shows always the end
always @(posedge BCLK)
if (init_acc) PACKET <= {2'b00,final_addr[1:0]};
else
if (acc_ok) PACKET <= PACKET + {inc_pack,2'b00};
// This signal is the End signal for the ADDR_UNIT internally.
always @(SIZE or PACKET or acc_ok)
casex ({SIZE,PACKET[3],PACKET[1:0]})
5'b00_x_xx : acc_ende = acc_ok; // Byte
5'b01_0_0x : acc_ende = acc_ok; // Word 1 packet
5'b01_0_10 : acc_ende = acc_ok; // 1 packet
5'b01_1_xx : acc_ende = acc_ok; // 2 packets
5'b10_0_00 : acc_ende = acc_ok; // DWord 1 packet
5'b10_1_xx : acc_ende = acc_ok; // 2 packets
5'b11_1_xx : acc_ende = acc_ok; // QWord at least 2 packets
default : acc_ende = 1'b0;
endcase
assign in_page = (vadr_reg[11:3] != 9'h1FF); // Access inside a page ? During WRITE address is incr
always @(SIZE or vadr_reg or in_page or PACKET)
casex (SIZE)
2'b01 : frueh_ok = (vadr_reg[3:2] != 2'b11); //Word
2'b10 : frueh_ok = (vadr_reg[3:2] != 2'b11); //DWord
2'b11 : frueh_ok = (PACKET[1:0] == 2'b00) ? (~vadr_reg[3] | ~vadr_reg[2]) : ((PACKET[3:2] == 2'b
default : frueh_ok = 1'b1; // Byte don't case
endcase
assign all_ok = SIZE[1] ? (PACKET[1:0] == 2'b00) : (PACKET[1:0] != 2'b11); // for DWord : Word
always @(SIZE or READ_OUT or frueh_ok or PACKET or all_ok or io_acc or acc_ok or qwa_flag or io_rdy
casex ({SIZE,READ_OUT,frueh_ok,PACKET[3],io_acc,all_ok})
7'b00_xxxx_x : acc_step = acc_ok; // Byte, all ok
//
7'b01_xxxx_1 : acc_step = acc_ok; // Word : aligned access , only 1 packet
7'b01_1x1x_0 : acc_step = acc_ok; // READ must wait for all data
7'b01_001x_0 : acc_step = acc_ok; // WRITE Adr. ist not perfect and waits for last packet
7'b01_01xx_0 : acc_step = acc_ok; // WRITE Adr. perfect - acc_step after 1. packet
//
7'b10_xxxx_1 : acc_step = acc_ok; // DWord : aligned access , only 1 packet
7'b10_1x1x_0 : acc_step = acc_ok; // READ must wait for all data
7'b10_001x_0 : acc_step = acc_ok; // WRITE Adr. ist not perfect and waits for last packet
7'b10_01xx_0 : acc_step = acc_ok; // WRITE Adr. perfect - acc_step after 1. packet
// fast QWord READ : there would be a 2. acc_step if not ~PACK...
7'b11_1xxx_x : acc_step = acc_ok & ( (qwa_flag & ~io_rdy & ca_hit) ? ~PACKET[3] : PACKET[3] );
7'b11_0x1x_x : acc_step = acc_ok;
7'b11_0100_x : acc_step = acc_ok; // WRITE Adr. perfect - acc_step after 1. packet if not io_a
default : acc_step = 1'b0;
endcase
// There is a 2. acc_step if packet (10) - this must be suppressed
always @(posedge BCLK or negedge BRESET)
if (!BRESET) no_done <= 1'b0;
else no_done <= (~acc_ende & acc_step) | (no_done & ~(acc_run & acc_ende));
// The final DONE Multiplexer
assign ACC_DONE = acc_run ? (acc_step & ~no_done) : ea_ok;
 
always @(posedge BCLK) reg_out_i <= ~acc_step & BRESET & ((qwa_flag & (io_rdy | ~ca_hit) & acc_ok)
always @(posedge BCLK) io_rdy <= IO_READY & (WRITE_OUT | READ_OUT);
always @(posedge BCLK) next_reg <= (acc_step & ~qwa_flag) & (SIZE == 2'b11);
assign REG_OUT = reg_out_i | next_reg;
endmodule

powered by: WebSVN 2.1.0

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