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

Subversion Repositories m32632

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /m32632/trunk/rtl
    from Rev 16 to Rev 23
    Reverse comparison

Rev 16 → Rev 23

/ICACHE_SM.v
3,11 → 3,12
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: ICACHE_SM.v
// Version: 1.0
// Date: 30 May 2015
// Filename: ICACHE_SM.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
71,7 → 72,7
output STOP_CINV;
reg [27:4] addr_r;
reg [7:0] maske,clear;
reg [7:0] clear;
reg do_koll;
reg [2:0] counter;
reg [1:0] wpointer,rpointer;
/ICACHE.v
3,11 → 3,12
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: ICACHE.v
// Version: 1.0
// Date: 30 May 2015
// Filename: ICACHE.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
37,7 → 38,7
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module ICACHE( BCLK, MCLK, MDONE, BRESET, READ_I, IO_READY, PSR_USER, DATA_HOLD, PTB_WR, PTB_SEL, DRAM_WR,
module ICACHE( BCLK, MCLK, DRAMSZ, MDONE, BRESET, READ_I, IO_READY, PSR_USER, DATA_HOLD, PTB_WR, PTB_SEL, DRAM_WR,
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 );
44,6 → 45,7
 
input BCLK;
input MCLK;
input [2:0] DRAMSZ;
input MDONE;
input BRESET;
input READ_I;
155,8 → 157,7
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;
wire [23:0] CVALID;
 
reg [35:0] MMU_TAGS [0:255]; // Tag Set for MMU : 256 entries of 36 bits
reg [35:0] MMU_Q;
170,8 → 171,7
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;
wire [23:0] KCVALID;
 
assign READ = READ_I & ~HOLD_ON & RUN_ICRD;
assign WRITE = 1'b0;
229,10 → 229,14
 
// +++++++++++++++++++++++++ Cache Valid +++++++++++++++++++
 
always @(posedge BCLK) CVALID <= CA_VALID[V_ADR[11:7]];
NEU_VALID VALID_RAM(
.BCLK(BCLK),
.VALIN(D_CV),
.WADR(ACV),
.WREN(WE_CV),
.RADR(V_ADR[11:7]),
.VALOUT(CVALID) );
 
always @(negedge BCLK) if (WE_CV) CA_VALID[ACV] <= D_CV;
 
// +++++++++++++++++++++++++ Tag Set 0 +++++++++++++++++++++
 
always @(posedge BCLK) TAG0 <= TAGSET_0[VADR[11:4]];
263,7 → 267,7
.MMU_HIT(MMU_HIT),
.WRITE(WRITE),
.KDET(1'b0),
.ADDR({RADR[27:12],VADR_R[11:4]}),
.ADDR({RADR[31:12],VADR_R[11:4]}),
.CFG(CFG),
.ENDRAM(ENDRAM),
.CVALID(CVALID),
273,7 → 277,7
.CA_SET(CA_SET),
.WB_ACC(),
.USE_CA(USE_CA),
.IOSEL(RADR[31:28]),
.DRAMSZ(DRAMSZ),
.IO_SPACE(IO_SPACE),
.DC_ILO(1'b0),
.KILL(KILL_C),
331,10 → 335,14
 
// +++++++++++++++++++++++++ Kollision Valid +++++++++++++++
 
always @(posedge BCLK) KCVALID <= KCA_VALID[KOLLI_A[11:7]];
NEU_VALID KOL_VAL(
.BCLK(BCLK),
.VALIN(D_CV),
.WADR(ACV),
.WREN(WE_CV),
.RADR(KOLLI_A[11:7]),
.VALOUT(KCVALID) );
 
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]];
/DP_FPU.v
3,11 → 3,12
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: DP_FPU.v
// Version: 1.0
// Date: 30 May 2015
// Filename: DP_FPU.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
39,10 → 40,11
// 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
// 7. SCANDIG Scan digit for leading one
// 8. DIVI_PREP Prepare data for the divider
// 9. DFPU_DIV The divider for all divide opcodes : double, single and integer
// 10. DP_LOGIK Control logic and result path for different functions
// 11. DP_FPU Top level of long operations datapath
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
102,16 → 104,32
output [3:0] OUT;
output CY_OUT;
reg [4:0] data;
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});
always @(B_IN)
case (B_IN)
4'h0 : data = 5'h00;
4'h1 : data = 5'h1F;
4'h2 : data = 5'h1E;
4'h3 : data = 5'h1D;
4'h4 : data = 5'h1C;
4'h5 : data = 5'h1B;
4'h6 : data = 5'h1A;
4'h7 : data = 5'h19;
4'h8 : data = 5'h18;
4'h9 : data = 5'h17;
default : data = 5'hxx;
endcase
 
assign result = {1'b0,A_IN} + (SUBP ? data : {1'b0,B_IN}) + {{4{SUBP & CY_IN}},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
151,16 → 169,16
always @(posedge BCLK or negedge BRESET)
if (!BRESET) run_bcd <= 1'b0;
else
run_bcd <= (START & DO_BCD) | (run_bcd & (BWD != byte_cou));
run_bcd <= (START & DO_BCD & (BWD != 2'd0)) | (run_bcd & (BWD != byte_cou));
always @(posedge BCLK) byte_cou <= START ? 2'd0 : byte_cou + {1'b0,run_bcd};
always @(posedge BCLK) byte_cou <= START ? 2'd1 : 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]};
3'b0_0x : datain = {SRC1[15:8], SRC2[15:8]};
3'b0_10 : datain = {SRC1[23:16],SRC2[23:16]};
3'b0_11 : datain = {SRC1[31:24],SRC2[31:24]};
endcase
assign carry = START ? CY_IN : CY_OUT;
174,11 → 192,11
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;
always @(posedge BCLK) if (~byte_cou[1]) BCD_Q[15:8] <= result;
always @(posedge BCLK) if (byte_cou == 2'd2) BCD_Q[23:16] <= result;
always @(posedge BCLK) if (byte_cou == 2'd3) BCD_Q[31:24] <= result;
assign BCD_DONE = run_bcd & (BWD == byte_cou);
assign BCD_DONE = (START & DO_BCD & (BWD == 2'd0)) | (run_bcd & (BWD == byte_cou));
 
endmodule
 
212,21 → 230,19
// ++++++++++++++++++++++++++++++++++
// MOViL : 1. Pipeline stage : needs 3 cycles
reg [31:8] movdat;
reg [31:0] 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
casex(BWD)
2'b00 : movdat = {{24{SRC1[7]}}, SRC1[7:0]}; // Byte
2'b01 : movdat = {{16{SRC1[15]}},SRC1[15:0]}; // Word
default : movdat = SRC1[31:0]; // Double
endcase
// This pipeline stage for better timing
always @(posedge BCLK) movif <= movdat[31] ? (32'h0 - {movdat,SRC1[7:0]}) : {movdat,SRC1[7:0]}; // -2^31 is kept !
always @(posedge BCLK) movif <= ({32{movdat[31]}} ^ movdat) + {31'h0,movdat[31]}; // -2^31 is kept !
always @(posedge BCLK) sign_movif <= movdat[31];
272,8 → 288,9
 
// Pipeline register :
reg [63:0] muxsrc2;
reg [55:3] pipe1; // Nummbers for right shifter
reg [5:0] shift;
wire [55:3] pipe1; // Nummbers for right shifter
wire [5:0] shift;
reg [2:0] pshift;
reg vorz,addflag;
 
wire [52:0] muxsrc1;
304,13 → 321,15
 
assign muxsrc1 = switch ? {MAN2,SRC2} : {MAN1,SRC1};
 
assign pipe1 = SELECT[1] ? (ganzklein ? 53'd0 : {1'b1,SRC1[19:0],SRC2}) : muxsrc1; // feeding of R.T.F.
assign shift = SELECT[1] ? {1'b0,rexdiff[4:0]} : (switch ? shift2 : shift1);
 
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);
muxsrc2 <= switch ? {expo1,MAN1,SRC1} : {expo2,MAN2,SRC2}; // Incl. Exponent & "1" of mantisse
pshift <= shift[2:0];
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
338,18 → 357,20
// ++++++++++++++++++++++++++++++++++
// ADD/SUB + ROUND/TRUNC : 2. Step : Barrelshifter to the right -->
wire [55:0] brshifta,brshiftb,brshiftc,brshiftd,brshifte,brshiftf;
wire [55:0] brshifta,brshiftb,brshiftd,brshifte,brshiftf;
reg [55:0] brshiftc;
// 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;
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;
always @(posedge BCLK)
brshiftc <= shift[3] ? { 8'h0, brshiftb[55:9], (brshiftb[8:0] != 9'h0)} : brshiftb;
assign brshiftd = pshift[2] ? { 4'h0, brshiftc[55:5], (brshiftc[4:0] != 5'h0)} : brshiftc;
assign brshifte = pshift[1] ? { 2'h0, brshiftd[55:3], (brshiftd[2:0] != 3'h0)} : brshiftd;
assign brshiftf = pshift[0] ? { 1'b0, brshifte[55:2], (brshifte[1:0] != 2'h0)} : brshifte;
// ++++++++++++++++++++++++++++++++++
// ROUNDLi/TRUNCLi/FLOORLi : 3. Step : round to Integer
356,8 → 377,7
reg car_ry;
wire [1:0] inex;
wire [30:0] compl;
wire [31:0] iadder;
wire [32:0] iadder;
wire restbits;
assign restbits = (brshiftf[23:0] != 24'h0);
370,17 → 390,15
default : car_ry = sign1; // TRUNCLi , simple cut off
endcase
 
assign compl = sign1 ? ~brshiftf[55:25] : brshiftf[55:25];
assign iadder = (sign1 ? {2'b11,~brshiftf[55:25]} : {2'b0,brshiftf[55:25]}) + {32'h0,car_ry};
assign iadder = {sign1,compl} + {31'h0,car_ry};
always @(posedge BCLK) IOUT <= minint ? 32'h8000_0000 : iadder;
always @(posedge BCLK) IOUT <= minint ? 32'h8000_0000 : iadder[31:0];
 
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;
default : ovflag2 = (iadder[32] != iadder[31]); // Double
endcase
// ++++++++++++++++++++++++++++++++++
452,13 → 470,13
// 5. DFPU_MISC Double precision floating point miscellaneous operations
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DFPU_MISC ( BCLK, START, SRC1, SRC2, SRCFLAG, MIMUX, MODE, OUT );
module DFPU_MISC ( BCLK, START, SRC1, SRC2, MAN2, SRCFLAGS, MODE, OUT );
 
input BCLK;
input START;
input [1:0] START;
input [31:0] SRC1,SRC2;
input SRCFLAG;
input MIMUX;
input [19:0] MAN2;
input [5:0] SRCFLAGS;
input [3:0] MODE;
output [69:0] OUT;
465,16 → 483,14
reg [69:0] OUT;
reg [63:0] daten;
wire [10:0] scalb_l;
wire nan,zero,sign;
wire 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};
always @(posedge BCLK) if (START[1]) daten <= {SRC1,SRC2};
assign sign = daten[63];
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;
// +++++++++++++++++++++++++++ MOVFL and MOVLF +++++++++++++++++++++++++++++++++++
assign lexpo = {5'b0,daten[62:55]} + 13'h0380; // -7F + 3FF
481,12 → 497,11
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
assign fl_lf = MODE[0] ? {SRCFLAGS[1:0],sign,lexpo,daten[54:32],31'h0} // MOVFL
: {SRCFLAGS[1:0],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;
493,8 → 508,6
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;
 
513,18 → 526,49
// 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_exp[3:0],shift_l,45'h0};
assign logb_res = {SRCFLAGS[1],1'b0,~daten[62],2'b00,logb_exp,calc_exp[3:0],shift_l,45'h0};
// ++++++++++++++++++++++++ SCALBf ++++++++++++++++++++++++++++++++++
wire [7:0] scalb_f;
reg [3:0] rshift;
reg [10:0] shf_r0,dexpo; // dexpo = Exponent Destination
reg huge;
reg svorz,dvorz;
assign scalb_f = SRCFLAG ? 8'h00 : (daten[39:32] + daten[30:23]);
assign scalb_l = SRCFLAG ? 11'h000 : (daten[42:32] + daten[30:20]);
wire [10:0] shf_r1,shf_r2,shf_r4,shf_r8;
wire [12:0] addexp,newexp,finexp;
wire nan;
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};
always @(posedge BCLK) // 2**0,9.. is transformed to 2**0 = 1 -> no change at SRC2
if (START[0])
begin
shf_r0 <= ( SRC1[30] | ((SRC1[29:23] == 7'h7F) & (MODE[1] | (SRC1[22:20] == 3'd7))) ) ?
(MODE[1] ? {4'd1,SRC1[22:16]} : {1'b1,SRC1[19:10]}) : 11'd0;
rshift <= MODE[1] ? 4'd6 - SRC1[26:23] : 4'd9 - SRC1[23:20];
huge <= MODE[1] ? ( SRC1[30] & ((SRC1[29:26] != 4'd0) | (SRC1[25:23] == 3'h7)) ) // >406 in Double Style
: ( SRC1[30] & ((SRC1[29:24] != 6'd0) | (SRC1[23] & (SRC1[22] | SRC1[21]))) ); // >409
svorz <= SRC1[31];
dvorz <= SRC2[31];
dexpo <= MODE[1] ? {3'd0,SRC2[30:23]} : SRC2[30:20];
end
 
assign shf_r1 = rshift[0] ? {1'b0,shf_r0[10:1]} : shf_r0; // a mini-TRUNC of 11 Bits
assign shf_r2 = rshift[1] ? {2'd0,shf_r1[10:2]} : shf_r1;
assign shf_r4 = rshift[2] ? {4'd0,shf_r2[10:4]} : shf_r2;
assign shf_r8 = rshift[3] ? {8'd0,shf_r4[10:8]} : shf_r4;
 
assign addexp = svorz ? {2'd0,dexpo} - {2'd0,shf_r8} : {2'd0,dexpo} + {2'd0,shf_r8};
assign newexp = MODE[1] ? {addexp[9:8],{3{addexp[7]}},addexp[7:0]} : addexp[12:0];
assign finexp = SRCFLAGS[2] ? {3'd0,newexp[9:0]} // never an Overflow if SRC2 = 0.0 !
: {(huge ? {svorz,1'b1} : newexp[12:11]),newexp[10:0]}; // Overflow or Underflow
assign nan = SRCFLAGS[3] | SRCFLAGS[1];
assign scalb_res = MODE[1] ? // Mantisse doesn't change !
{nan,SRCFLAGS[2],daten[31],finexp,daten[22:0],daten[28:0],2'b00}
: {nan,SRCFLAGS[2],dvorz,finexp,MAN2,daten[31:0],2'b00};
// ++++++++++++++++++++++++ Output ++++++++++++++++++++++++++++++++++++++++++++++++++++++
575,9 → 619,25
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 7. DIVI_PREP Prepare data for the divider
// 7. SCANDIG Scan digit for leading one
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module SCANDIG (DIN, MBIT, LBIT, NONZ);
 
input [3:0] DIN;
output MBIT,LBIT,NONZ;
assign MBIT = DIN[3] | DIN[2]; // 1xxx = 11
assign LBIT = DIN[3] | (DIN[3:1] == 3'b001); // 01xx = 10
assign NONZ = (DIN != 4'd0); // 001x = 01
endmodule
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 8. DIVI_PREP Prepare data for the divider
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DIVI_PREP (SRC, BWD, NOT_DEI, EXTDATA, DOUT, MSB, NULL, MINUS);
 
input [31:0] SRC;
591,13 → 651,10
output MINUS;
 
reg [31:0] double;
reg [2:0] select;
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;
wire [7:0] mbits,lbits,dnonz;
assign modus = (NOT_DEI | EXTDATA) ? BWD : {(BWD[1] | BWD[0]),1'b1};
614,24 → 671,36
// 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);
SCANDIG digit_0 (.DIN(DOUT[3:0]), .MBIT(mbits[0]), .LBIT(lbits[0]), .NONZ(dnonz[0]) );
SCANDIG digit_1 (.DIN(DOUT[7:4]), .MBIT(mbits[1]), .LBIT(lbits[1]), .NONZ(dnonz[1]) );
SCANDIG digit_2 (.DIN(DOUT[11:8]), .MBIT(mbits[2]), .LBIT(lbits[2]), .NONZ(dnonz[2]) );
SCANDIG digit_3 (.DIN(DOUT[15:12]), .MBIT(mbits[3]), .LBIT(lbits[3]), .NONZ(dnonz[3]) );
SCANDIG digit_4 (.DIN(DOUT[19:16]), .MBIT(mbits[4]), .LBIT(lbits[4]), .NONZ(dnonz[4]) );
SCANDIG digit_5 (.DIN(DOUT[23:20]), .MBIT(mbits[5]), .LBIT(lbits[5]), .NONZ(dnonz[5]) );
SCANDIG digit_6 (.DIN(DOUT[27:24]), .MBIT(mbits[6]), .LBIT(lbits[6]), .NONZ(dnonz[6]) );
SCANDIG digit_7 (.DIN(DOUT[31:28]), .MBIT(mbits[7]), .LBIT(lbits[7]), .NONZ(dnonz[7]) );
 
always @(dnonz)
casex (dnonz[7:1])
7'b1xxx_xxx : select = 3'b111;
7'b01xx_xxx : select = 3'b110;
7'b001x_xxx : select = 3'b101;
7'b0001_xxx : select = 3'b100;
7'b0000_1xx : select = 3'b011;
7'b0000_01x : select = 3'b010;
7'b0000_001 : select = 3'b001;
default : select = 3'b000;
endcase
assign MSB = {bit_4,bit_3,bit_2,bit_1,bit_0};
assign NULL = (dnonz == 8'd0);
assign MSB = {select,mbits[select],lbits[select]};
endmodule
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 8. DFPU_DIV The divider for all divide opcodes : double, single and integer
// 9. 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, DIVI_OUT, DVZ_TRAP, DEI_OVF );
935,12 → 1004,12
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 9. DP_LOGIK Control logic and result path for different functions
// 10. 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, CY_IN,
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, COP_GO );
DOUT, TT_DP, DP_CMP, OVF_BCD, MEI, DFLOAT, DONE, UP_DP, CLR_LSB, WREN_L, DVZ_TRAP, COP_GO );
 
// Definition of output word OUT of sub-moduls : the hidden-bit of the mantissa is already gone
//
980,31 → 1049,29
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 DONE,UP_DP,WREN_L;
output reg CLR_LSB;
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 [7:0] select;
reg [5:0] wctrl;
reg [2:1] sequ;
reg misc_op;
reg misc_mux;
reg car_ry;
reg wr_part2;
reg up_flag;
reg ovf_div;
reg late_bcd_done;
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;
1017,6 → 1084,7
wire [63:0] fp_out,fp_res;
wire wr_part1;
wire done_i;
wire later;
wire [31:0] bcd_q;
wire bcd_done;
wire bcd_carry;
1029,20 → 1097,20
 
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;
8'b1001_000x : select = {5'b0000_0, ~FL ,2'b10}; // 0 1 0 : MOViL
8'b1001_010x : select = {5'b0001_1, 1'b1,2'b00}; // MOVLF
8'b1001_011x : select = {5'b0011_1, 1'b1,2'b00}; // MOVFL
8'b1001_100x : select = {5'b0001_0, ~FL ,2'b11}; // 0 1 1 : ROUNDLi
8'b1001_101x : select = {5'b0001_0, ~FL ,2'b11}; // 0 1 1 : TRUNCLi
8'b1001_111x : select = {5'b0001_0, ~FL ,2'b11}; // 0 1 1 : FLOORLi
8'b1011_0000 : select = {5'b1010_0, ~FL ,2'b00}; // 0 0 0 : ADDL Es werden Shifter wiederverwendet...
8'b1011_0010 : select = {5'b1010_0, ~FL ,2'b01}; // 0 0 1 : CMPL
8'b1011_0100 : select = {5'b1010_0, ~FL ,2'b01}; // 0 0 1 : SUBL
8'b1011_1000 : select = {1'b1,FL,1'b1,FL,1'b0,1'b1,2'b00}; // 1 0 1 : DIVf , Default Float fuer srcflags
8'b1011_1100 : select = {5'b1010_0, ~FL ,2'b00}; // 1 0 0 : MULL
8'b1011_0110 : select = {1'b1,FL,1'b1,FL,1'b1,1'b1,2'b00}; // SCALBf
8'b1011_0111 : select = {2'b00,FL,2'b1_1, 1'b1,2'b00}; // LOGBf
default : select = 8'b0;
endcase
 
assign MEI = (OPCODE == 8'h79);
1049,23 → 1117,18
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 bcd_ops = (OPCODE == 8'h71) | (OPCODE == 8'h70); // ADDP , SUBP
assign man_ops = (OPCODE == 8'hB1) | (OPCODE == 8'hB5) | (OPCODE == 8'hB9) | (OPCODE == 8'hBD); // MOVf,NEGf,XXXf,ABSf
 
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 multiplexer
assign DFLOAT = (select[2] | copop) & ~FL; // all Double Floating Point Operations for PREPDATA
assign make_i = (select[1:0] == 2'b11) | divi_ops | bcd_ops; // ROUND/TRUNC/FLOOR for output multiplexer
assign op_cmp = (OPCODE == 8'hB2) & ~FL;
always @(posedge BCLK) misc_op <= select[4]; // for OUT-Multiplexer
always @(posedge BCLK) misc_op <= select[3]; // 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); // Custom Convert
// 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);
1089,42 → 1152,42
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 | ~zman2));
3'b111 : srcflags[3] <= (SRC2[30:23] == 8'hFF) | ((SRC2[30:23] == 8'd0) & ((SRC2[22:20] != 3'd0) | ~zman2)); // F:SRC2 = NaN
default : srcflags[3] <= 1'b0;
case (select[7:6])
2'b10 : srcflags[3] <= preflags[5] | (preflags[4] & (~preflags[3] | SRC2[31] | ~zexp2 | ~zman2));
2'b11 : srcflags[3] <= (SRC2[30:23] == 8'hFF) | ((SRC2[30:23] == 8'd0) & ((SRC2[22:20] != 3'd0) | ~zman2)); // F:SRC2 = NaN
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;
if (START[1])
case (select[7:6])
2'b10 : srcflags[2] <= preflags[4]; // L:SRC2 = Zero , 2*SRC2
2'b11 : 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 | ~zman1));
3'b1x1 : srcflags[1] <= (SRC1[30:23] == 8'hFF) | ((SRC1[30:23] == 8'd0) & ((SRC1[22:20] != 3'd0) | ~zman1)); // F:SRC1 = NaN
3'b110 : srcflags[1] <= znan1 | (zexp1 & (~zman1 | SRC2[31] | ~zexp2 | ~zman2)); // L:(SRC1,SRC2) = NaN , SRC1 = MSB
default : srcflags[1] <= 1'b0;
case (select[5:4])
2'b01 : srcflags[1] <= znan1 | (zexp1 & (~zman1 | SRC2[31] | ~zexp2 | ~zman2)); // L:(SRC1,SRC2) = NaN , SRC1 = MSB
2'b10 : srcflags[1] <= preflags[2] | (preflags[1] & (~preflags[0] | SRC1[31] | ~zexp1 | ~zman1));
2'b11 : srcflags[1] <= (SRC1[30:23] == 8'hFF) | ((SRC1[30:23] == 8'd0) & ((SRC1[22:20] != 3'd0) | ~zman1)); // F:SRC1 = NaN
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;
if (START[1])
case (select[5:4])
2'b01 : srcflags[0] <= zexp1; // L:(SRC1,SRC2) = Zero , SRC1 = MSB, Special Case ROUNDL,etc.
2'b10 : srcflags[0] <= preflags[1]; // L:SRC1 = Zero , 2*SRC1
2'b11 : srcflags[0] <= (SRC1[30:23] == 8'd0); // F:SRC1 = Zero
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]}),
.MAN1({~preflags[1],MAN1[19:0]}), .MAN2({~preflags[4],MAN2[19:0]}),
.SRCFLAGS(srcflags), .BWD(BWD), .SELECT({OPCODE[2:1],select[1:0]}),
.OUT(addout), .IOUT(i_out), .CMPRES(cmpres) );
1135,11 → 1198,11
.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_MISC misc_inst ( .BCLK(BCLK), .START(START), .SRC1(SRC1), .SRC2(SRC2), .MAN2(MAN2[19:0]), .SRCFLAGS(srcflags),
.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), .SRC1(SRC1), .SRC2(SRC2),
.CY_IN(CY_IN), .SUBP(~OPCODE[2]), .BCD_Q(bcd_q), .CY_OUT(bcd_carry), .BCD_DONE(bcd_done) );
.CY_IN(CY_IN), .SUBP(~OPCODE[0]), .BCD_Q(bcd_q), .CY_OUT(bcd_carry), .BCD_DONE(bcd_done) );
// FP - path : selection of result and rounding :
 
1164,7 → 1227,7
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 div_zero = (srcflags[3:0] == 4'h1) & ((OPCODE == 8'hB8) | (OPCODE == 8'hB7)); // true FPU Divide by Zero also for LOGBf
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);
1206,34 → 1269,43
always @(posedge BCLK or negedge BRESET)
if (!BRESET) sequ <= 2'b00;
else
sequ <= {(sequ[1] & ~DONE),START[1]};
sequ <= {(sequ[1] & ~DONE),(START[1] & ~wctrl[5])};
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;
9'b0_1001_000x : wctrl = 6'b001_111; // MOViL
9'b1_1001_000x : wctrl = 6'b100_010; // MOViF <= SFPU
9'bx_1001_010x : wctrl = 6'b000_010; // MOVLF
9'bx_1001_011x : wctrl = 6'b001_111; // MOVFL
9'b0_1001_100x : wctrl = 6'b000_010; // ROUNDLi
9'b0_1001_101x : wctrl = 6'b000_010; // TRUNCLi
9'b0_1001_111x : wctrl = 6'b000_010; // FLOORLi
9'b1_1001_100x : wctrl = 6'b100_010; // ROUNDFi
9'b1_1001_101x : wctrl = 6'b100_010; // TRUNCFi
9'b1_1001_111x : wctrl = 6'b100_010; // FLOORFi
9'b0_1011_0000 : wctrl = 6'b001_111; // ADDL
9'b1_1011_0000 : wctrl = 6'b100_010; // ADDF <= SFPU
9'b0_1011_0010 : wctrl = 6'b000_000; // CMPL
9'b1_1011_0010 : wctrl = 6'b100_000; // CMPF
9'b0_1011_0100 : wctrl = 6'b001_111; // SUBL
9'b1_1011_0100 : wctrl = 6'b100_010; // SUBF <= SFPU
9'b1_1011_1000 : wctrl = 6'b010_001; // DIVF - measured 18 clocks Reg-Reg
9'b0_1011_1000 : wctrl = 6'b010_111; // DIVL - measured 34 clocks Reg-Reg
9'b0_1011_1100 : wctrl = 6'b001_111; // MULL
9'b1_1011_1100 : wctrl = 6'b100_010; // MULF <= SFPU
9'bx_0111_000x : wctrl = 6'b100_010; // ADDP,SUBP
9'bx_0111_1001 : wctrl = 6'b000_111; // MEIi
9'bx_0111_1011 : wctrl = 6'b010_111; // DEIi
9'bx_0111_11xx : wctrl = 6'b010_001; // QUOi,REMi,MODi,DIVi
9'b1_1011_011x : wctrl = 6'b000_010; // SCALBF/LOGBF
9'b0_1011_011x : wctrl = 6'b001_111; // SCALBL/LOGBL
9'bx_1101_1101 : wctrl = {5'b010_00,copwr}; // Coprocessor opcode
default : wctrl = 6'b00;
endcase
 
assign done_i = wctrl[4] ? (div_done | bcd_done | COP_DONE) : ( (wctrl[3] | ~WR_REG) ? sequ[2] : sequ[1] );
assign DONE = ~START[1] & done_i; // DONE is valid for all opcodes
assign later = wctrl[3] & WR_REG; // if DEST = Reg and 64 bit of data then DONE comes 1 clock later
assign done_i = wctrl[4] ? (div_done | COP_DONE) : ( later ? sequ[2] : sequ[1] );
assign DONE = wctrl[5] ? (bcd_ops ? bcd_done : START[1]) : ~START[1] & done_i; // DONE is valid for all opcodes
 
assign wr_part1 = DONE & WR_REG & wctrl[0];
1241,10 → 1313,9
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. : all FPU opcodes of DP_FPU
always @(posedge BCLK) up_flag <= DONE & ~later; // DONE one cycle later
assign UP_DP = (select[2] & (later ? DONE : up_flag)) | man_ops; // Update FSR Trap etc. : all FPU opcodes of DP_FPU
// Overflow Trap for Division : DEI, QUO, DIV
assign quo_div = (OPCODE == 8'h7C) | (OPCODE == 8'h7F);
1256,7 → 1327,9
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) late_bcd_done <= bcd_done; // parallel to data write
 
assign OVF_BCD = {dei_ovf[1],ovf_div,late_bcd_done,bcd_carry}; // to I_PFAD
always @(posedge BCLK) COP_GO <= START[1] & copop;
 
1264,17 → 1337,16
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 10. DP_FPU Top level of long operations datapath
// 11. 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, WREN_L,
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 );
module DP_FPU( BCLK, FL, BRESET, LD_OUT, WR_REG, BWD, FSR, OPCODE, SRC1, SRC2, START, CY_IN, COP_DONE, COP_OP, COP_IN,
DONE, UP_DP, WREN_L, CLR_LSB, DVZ_TRAP, DP_CMP, DP_OUT, DP_Q, TT_DP, OVF_BCD, COP_GO, COP_OUT );
 
input BCLK;
input FL;
input BRESET;
input LD_LDQ;
input [1:0] LD_OUT;
input WR_REG;
input [1:0] BWD;
input [8:3] FSR;
1291,7 → 1363,6
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;
1339,7 → 1410,6
.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),
1370,7 → 1440,7
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 (LD_OUT[1] || LD_OUT[0] || WREN_L) DP_Q <= LD_OUT[0] ? SRC2 : DOUT[31:0];
 
always@(posedge BCLK) if (LOAD_LSD1) MDA[31:0] <= LSD_1;
 
/TOP_MISC.v
3,11 → 3,12
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: TOP_MISC.v
// Version: 1.0
// Date: 30 May 2015
// Filename: TOP_MISC.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
/ALIGNER.v
3,11 → 3,12
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: ALIGNER.v
// Version: 1.0
// Date: 30 May 2015
// Filename: ALIGNER.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
/STEUERUNG.v
3,11 → 3,12
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: STEUERUNG.v
// Version: 1.0
// Date: 30 May 2015
// Filename: STEUERUNG.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
162,7 → 163,8
.ENA_HK(ENA_HK),
.ILO(ILO),
.COP_OP(COP_OP),
.STOP_CINV(STOP_CINV) );
.STOP_CINV(STOP_CINV),
.PHOUT());
 
ILL_UNDEF CHECKER(
.USER(PSR[8]),
/I_PFAD.v
3,11 → 3,11
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: I_PFAD.v
// Version: 1.2 bug fix
// Version: 1.1 bug fix release of 7 November 2015
// History: 1.0 first release of 30 Mai 2015
// Date: 4 February 2016
// Filename: I_PFAD.v
// Version: 2.0
// History: 1.1 bug fix of 7 November 2015
// 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2016 Udo Moeller
//
122,31 → 122,22
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;
always @(FLOAT or BWD or SRC1)
casex ({FLOAT,BWD})
3'b0_00 : DEST1 = {{24{SRC1[7]}}, SRC1[7:0]};
3'b0_01 : DEST1 = {{16{SRC1[15]}},SRC1[15:0]};
3'b1_xx : 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;
always @(FLOAT or BWD or SRC2)
casex ({FLOAT,BWD})
3'b0_00 : DEST2 = {{24{SRC2[7]}}, SRC2[7:0]};
3'b0_01 : DEST2 = {{16{SRC2[15]}},SRC2[15:0]};
3'b1_xx : DEST2 = { 9'h001,SRC2[22:0]};
default : DEST2 = SRC2;
endcase
endmodule
260,7 → 251,6
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 @(*)
302,17 → 292,15
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[1] = (mdat_2[1:0] == 2'b00);
assign obits[0] = ~((mdat_2[2:1] == 2'b10) | mdat_2[0]);
assign obits[0] = ~mdat_3[0];
always @(BWD or obits or mdat_3)
always @(BWD or obits or mdat_2)
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);
default : FLAG = (mdat_2 == 4'b0000);
endcase
 
assign DOUT = FLAG ? 5'h0 : obits;
706,7 → 694,7
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 shift
assign sh_exin[4:0] = ({5{extract}} ^ shval_ei) + {4'd0,extract}; // EXT : right shift, INS : left shift
assign sh_exin[7:5] = (shval_ei == 5'd0) ? 3'b000 : {3{extract}}; // Special case : 0 has no negativ sign !
 
// LSH shift by 16 bit to right
734,8 → 722,7
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
4'b111x : pfad_6 = SRC2 ^ BMASKE; // IBIT
default : pfad_6 = shdat; // Result of Barrelshifter
endcase
/STEUER_MISC.v
3,10 → 3,10
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: STEUER_MISC.v
// Version: 1.1 bug fix
// History: 1.0 first release of 30 Mai 2015
// Date: 21 January 2016
// Filename: STEUER_MISC.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2016 Udo Moeller
//
212,7 → 212,7
reg [31:0] fpu_trap_pc;
reg IC_USER;
wire [31:0] branch,pc_jump,next_pc,pc_icache_i;
wire [31:0] branch,pc_jump,pc_icache_i;
assign PC_SAVE = pc_adduse + {29'h0,USED};
assign branch = PC_ARCHI + DISP;
219,12 → 219,10
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;
pc_adduse <= NEW ? pc_jump : PC_SAVE; // Only at NEW is the DISP correct !
// The Architectur - PC : Address mode "Programm Memory"-relativ
// no BRESET because NEXT_PCA is immediately valid
275,7 → 273,6
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)
292,10 → 289,9
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);
assign OPOS[1] = (mdat_1[1:0] == 2'b00);
assign OPOS[0] = ~((mdat_1[2:1] == 2'b10) | mdat_1[0]);
assign VALID = (mdat_1 != 4'b0000);
endmodule
497,8 → 493,6
parameter op_addf = {3'b11x,8'hB0};
parameter op_mull = {3'b01x,8'hBC};
parameter op_mulf = {3'b11x,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'b11x,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 !
507,7 → 501,7
 
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'bxx_xxxx_1111_1110 : op_code = {3'b011,OPREG[10],OPREG[8]}; // DOT/POLY
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
554,7 → 548,7
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],~SRC_2[0]}; // needed only for DEI/MEI
assign src_2l = {SRC_2[6:1],~SRC_2[0]}; // used only for DEI and MEI
assign dest_2 = SRC_2[5:0];
assign phchk = {7'b0101_010,size_dw}; // Phase 54 or 55
564,8 → 558,8
assign re_wr = {EXR22[18:17],4'b0101,4'h0, 9'h003}; // REUSE Address : Write of rmw , top 2 Bits contain size
 
always @(posedge BCLK) if (PHASE_0) ext_tos <= (OPREG[18:14] == 5'h17); // if TOS
assign rexwr = {EXR22[18:17],4'b0101,4'h0, ext_tos, 8'h03}; // REUSE Addresse : Write von rmw , only for EXT and EXTS !
always @(posedge BCLK) if (PHASE_0) ext_tos <= (OPREG[18:14] == 5'h17); // TOS Address mode
assign rexwr = {EXR22[18:17],4'b0101,4'h0, ext_tos, 8'h03}; // REUSE Address : Write of rmw , only for EXT and EXTS
always @(posedge BCLK) tbit_flag <= ~OPERA[1]; // due to Timing ...
always @(posedge BCLK) size_dw <= OPERA[9];
794,41 → 788,6
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. half of external SRC1
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 cycle for TRUNC => TEMP !
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...
850,16 → 809,16
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 };
: { addr_nop,8'h55, SRC_1, F0, 1'b0,dest_x,op_mulf, 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, 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 };
: { addr_nop,8'h55, SRC_1, F0, 1'b0,dest_x,op_mulf, 2'b11,2'b00,4'h0 };
state_53 = { addr_nop,8'h55, imme, F0, 1'b0,dest_x,op_mulf, 2'b11,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 };
: { addr_nop,8'h6E, rtmph, SRC_2, 1'b0,dest_x,op_addf, 2'b11,2'b00,4'h0 };
state_55 = { addr_nop,8'h54, src_x, src_x, 1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 };
state_58 = { addr_nop,8'h6E, rtmph, imme, 1'b0,dest_x,op_addf, 2'b11,2'b00,4'h0 };
state_59 = dont_care;
state_5A = dont_care;
end
887,7 → 846,7
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
{ addr_nop,8'h63, SRC_1 ,SRC_2 ,1'b0,dest_x,op_mulf, 2'b11,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 } );
896,11 → 855,11
: { 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 };
: { addr_nop,8'h63, imme, SRC_2 ,1'b0,dest_x,op_mulf, 2'b11,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 };
imme, 1'b0,dest_x,op_mulf, 2'b11,2'b00,4'h0 };
state_59 = dont_care;
state_5A = dont_care;
end
942,7 → 901,9
4'h0 : STATE_GROUP_60 = { addr_nop,8'h00, src_x, src_x, 1'b1,chkreg,op_adr, 2'b00,2'b00,4'h0 }; // for INDEX
4'h1 : STATE_GROUP_60 = { addr_nop,8'h62, rtmpl, F0, 1'b1,w_F0_h,op_addl, 2'b10,2'b00,4'h0 }; // for DOTL
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 }; // for DOTL & POLYL !
4'h3 : STATE_GROUP_60 = { addr_nop,8'h00, rtmph, F0, 1'b1,w_F0, op_addf, 2'b00,2'b00,4'h0 }; // for DOTF
4'h3 : STATE_GROUP_60 = { addr_nop,8'h6F, src_x, src_x, 1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 }; // for DOTF
4'hF : STATE_GROUP_60 = { addr_nop,8'h6E, rtmph, F0, 1'b0,dest_x,op_addf, 2'b11,2'b00,4'h0 };
4'hE : STATE_GROUP_60 = { addr_nop,8'h00, src_x, src_x, 1'b1,w_F0, op_addf, 2'b00,2'b00,4'h0 }; // for DOTF & POLYF
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
/DATENPFAD.v
3,12 → 3,13
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: DATENPFAD.v
// Version: 1.1 bug fix
// History: 1.0 first release of 30 Mai 2015
// Date: 7 October 2015
// Filename: DATENPFAD.v
// Version: 2.0
// History: 1.1 bug fix of 7 October 2015
// 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
107,8 → 108,9
output [127:0] COP_OUT;
 
reg [31:0] high_dq;
reg [31:0] OUT_I;
reg [31:0] IMMREG,MEMREG;
reg [31:0] BYDIN; // the bypass register
reg LDIMR;
 
wire [2:0] BITSEL;
wire [1:0] BWD;
123,6 → 125,7
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 [31:0] OUT_I;
wire [4:0] TT_DP;
wire TWREN; // active if FPU Trap occurs
wire UP_DP;
135,7 → 138,6
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;
155,7 → 157,7
 
assign ERGEBNIS = SP_MUX ? FP_OUT : I_OUT;
 
assign WRADR_0 = WRADR[0] & ~CLR_LSB;
assign WRADR_0 = WRADR[0] ^ CLR_LSB;
assign ENWR = WREN_L | WREN;
assign DOWR = ENWR & TWREN;
167,9 → 169,17
 
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_OUT[1]) high_dq <= ERGEBNIS;
 
always @(posedge BCLK) if (LD_DIN) OUT_I <= LD_IMME ? IMME_Q : DIN;
always @(posedge BCLK)
if (LD_DIN)
begin
IMMREG <= IMME_Q;
MEMREG <= DIN;
LDIMR <= LD_IMME;
end
assign OUT_I = LDIMR ? IMMREG : MEMREG; // old solution had the multiplexor before the register
 
always @(posedge BCLK) if (RDAA[7]) BYDIN <= ERGEBNIS;
 
339,7 → 349,7
.BCLK(BCLK),
.FL(FL),
.BRESET(BRESET),
.LD_LDQ(LD_OUT[0]),
.LD_OUT(LD_OUT),
.WR_REG(WR_REG),
.BWD(BWD),
.FSR(FSR[8:3]),
351,7 → 361,6
.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),
383,7 → 392,8
.FP_OUT(FP_OUT),
.I_OUT(SFP_DAT),
.SP_CMP(SP_CMP),
.TT_SP(TT_SP));
.TT_SP(TT_SP),
.START(START[1]) );
 
FP_STAT_REG FPS_REG(
.BCLK(BCLK),
392,7 → 402,7
.WREN(ENWR),
.WRADR(WRADR[5:4]),
.UP_DP(UP_DP),
.UP_SP(UP_SP & LD_OUT[1]),
.UP_SP(UP_SP),
.DIN(SRC1[16:0]),
.TT_DP(TT_DP),
.TT_SP(TT_SP),
/CACHE_LOGIK.v
3,12 → 3,13
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: CACHE_LOGIK.v
// Version: 1.1 bug fix
// History: 1.0 first release of 30 Mai 2015
// Date: 7 October 2015
// Filename: CACHE_LOGIK.v
// Version: 2.0
// History: 1.1 bug fix of 7 October 2015
// 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
34,20 → 35,52
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 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. NEU_VALID Cache Valid RAM
// 2. DEBUG_AE Debug unit for address compare in data cache
// 3. MMU_UP MMU memory update and initalization controller
// 4. DCA_CONTROL Data cache valid memory update and initalization controller
// 5. MMU_MATCH MMU virtual address match detector
// 6. CA_MATCH Cache tag match detector
// 7. FILTCMP Address Filter and Comparator
// 8. DCACHE_SM Data cache state machine
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 1. DEBUG_AE Debug unit for address compare in data cache
// 1. NEU_VALID Cache Valid RAM
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module NEU_VALID ( BCLK, VALIN, WADR, WREN, RADR, VALOUT );
 
input BCLK;
input [23:0] VALIN;
input [4:0] WADR;
input WREN;
input [4:0] RADR;
output [23:0] VALOUT;
reg [23:0] cvalid [0:31]; // Valid bits for Data Set 0 and 1 : 32 entries of 24 bits
reg [23:0] ramout;
reg [23:0] valhold;
reg gleich;
 
always @(posedge BCLK) ramout <= cvalid[RADR];
always @(posedge BCLK) if (WREN) cvalid[WADR] <= VALIN;
always @(posedge BCLK) valhold <= VALIN;
always @(posedge BCLK) gleich <= WREN & (RADR == WADR);
assign VALOUT = gleich ? valhold : ramout;
endmodule
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. 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;
92,7 → 125,7
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2. MMU_UP MMU memory update and initalization controller
// 3. MMU_UP MMU memory update and initalization controller
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module MMU_UP ( BCLK, BRESET, NEW_PTB, PTB1, IVAR, WR_MRAM, VADR, VADR_R, MVALID, UPDATE,
143,7 → 176,7
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 3. DCA_CONTROL Data cache valid memory update and initalization controller
// 4. 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, INVAL_A, WRITE,
180,10 → 213,12
wire countf;
always @(posedge BCLK) if (DRAM_ACC) ca_set_d <= CA_SET; // Store for whole access
 
// physical address is stored in TAG-RAM
 
assign WRCRAM0 = (CUPDATE & ~WCTRL[0]) & ~CA_SET;
assign WRCRAM1 = (CUPDATE & ~WCTRL[0]) & CA_SET;
assign WRCRAM0 = (CUPDATE & ~WCTRL[0]) & ~ca_set_d;
assign WRCRAM1 = (CUPDATE & ~WCTRL[0]) & ca_set_d;
// Load Valid RAM :
210,8 → 245,6
 
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);
237,7 → 270,7
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 4. MMU_MATCH MMU virtual address match detector
// 5. MMU_MATCH MMU virtual address match detector
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module MMU_MATCH ( USER, READ, WRITE, RMW, MCR_FLAGS, MVALID, VADR_R, MMU_VA, IVAR,
298,7 → 331,7
assign alles_ok = match & ( ~WRITE | MMU_VA[17] ) & ~PROT_ERROR; // Modified - Flag : reload the PTE
// if MMU_HIT = 0 then there is no Write-Buffer access abd no update of cache !
// if MMU_HIT = 0 then there is no Write-Buffer access and 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);
324,15 → 357,15
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 5. CA_MATCH Cache tag match detector
// 6. CA_MATCH Cache tag match detector
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module CA_MATCH ( CVALID, IOSEL, ADDR, TAG0, TAG1, CFG, WRITE, MMU_HIT, CI, INVAL_L, KDET, ENDRAM, DC_ILO,
module CA_MATCH ( CVALID, DRAMSZ, ADDR, TAG0, TAG1, CFG, WRITE, MMU_HIT, CI, INVAL_L, KDET, ENDRAM, DC_ILO,
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 [2:0] DRAMSZ;
input [31:4] ADDR;
input [27:12] TAG0,TAG1;
input [1:0] CFG; // LDC , DC
input WRITE;
352,6 → 385,7
output KILL;
reg [7:0] maske;
reg [4:0] szmaske;
wire match_0,match_1;
wire valid_0,valid_1;
358,7 → 392,7
wire select;
wire clear;
wire [7:0] update_0,update_1,lastinfo;
wire sel_dram;
wire sel_dram,filter;
always @(ADDR)
case (ADDR[6:4])
396,8 → 430,18
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
always @(DRAMSZ) // Size of DRAM
casex (DRAMSZ)
3'b00x : szmaske = 5'h1F; // 8 MB 32016 Second Processor
// 3'b001 reserved for Ceres III
3'b01x : szmaske = 5'h10; // 128 MB MCUBE
default : szmaske = 5'h00; // 256 MB NetBSD
endcase
assign filter = ((ADDR[27:23] & szmaske) == 5'd0);
assign sel_dram = (ADDR[31:28] == 4'd0) & filter & ENDRAM;
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;
405,11 → 449,48
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 6. DCACHE_SM Data cache state machine
// 7. FILTCMP Address Filter and Comparator
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module FILTCMP ( DRAMSZ, RADR, DRAM_A, ADR_EQU, TAGDAT );
 
input [2:0] DRAMSZ;
input [27:4] RADR,DRAM_A;
output ADR_EQU;
output reg [27:12] TAGDAT;
 
reg [27:23] adram;
always @(DRAMSZ or RADR)
casex (DRAMSZ)
3'b00x : TAGDAT = {5'd0,RADR[22:12]}; // 8 MB
3'bx10 : TAGDAT = {3'd0,RADR[24:12]}; // 32 MB
3'bx11 : TAGDAT = {2'd0,RADR[25:12]}; // 64 MB
3'b100 : TAGDAT = {1'd0,RADR[26:12]}; // 128 MB
3'b101 : TAGDAT = RADR[27:12] ; // 256 MB
endcase
always @(DRAMSZ or DRAM_A) // The address comparator is only used in the data cache.
casex (DRAMSZ)
3'b00x : adram = 5'd0; // 8 MB
3'bx10 : adram = {3'd0,DRAM_A[24:23]}; // 32 MB
3'bx11 : adram = {2'd0,DRAM_A[25:23]}; // 64 MB
3'b100 : adram = {1'd0,DRAM_A[26:23]}; // 128 MB
3'b101 : adram = DRAM_A[27:23] ; // 256 MB
endcase
 
assign ADR_EQU = {TAGDAT,RADR[11:4]} == {adram,DRAM_A[22:4]};
 
endmodule
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 8. DCACHE_SM Data cache state machine
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module DCACHE_SM ( BCLK, BRESET, IO_SPACE, MDONE, IO_READY, MMU_HIT, CA_HIT, READ, WRITE, ZTEST, RMW, CAPDAT, VADR_R, IC_VA,
USE_CA, PTB_WR, PTB_SEL, SEL_PTB1, CPU_OUT, USER, PROT_ERROR, WB_ACC, ENWR, ADR_EQU, IC_PREQ, FILLRAM, ICTODC,
USE_CA, PTB_WR, PTB_SEL, SEL_PTB1, CPU_OUT, USER, PROT_ERROR, WB_ACC, ENWR, ADR_EQU, IC_PREQ, DMA_CHK, ICTODC,
RWVAL, VIRTUELL, QWATWO,
DRAM_ACC, DRAM_WR, IO_ACC, IO_RD, IO_WR, PTE_MUX, PD_MUX, PKEEP, PTE_ADR, PTE_DAT, HIT_ALL, ACC_OK,
ABORT, PROTECT, IACC_STAT, ABO_LEVEL1, WR_MRAM, CUPDATE, AUX_DAT, NEW_PTB, PTB_ONE, MMU_DIN, IC_SIGS, KOMUX,
434,7 → 515,7
input ENWR; // Enable WRITE from DRAM
input ADR_EQU;
input IC_PREQ;
input FILLRAM;
input DMA_CHK;
input [3:0] ICTODC; // multiple signals from ICACHE, especially DMA
input [1:0] RWVAL; // RDVAL+WRVAL Operation
input VIRTUELL; // for RDVAL/WRVAL
553,10 → 634,10
// 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'b0x_xx_xxxx_x0_1_x0 : 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 in parallel
// 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
13'b0x_x0_xxxx_x0_0_10 : new_state = 7'b1000000; // DMA access is started
default : new_state = 7'b0;
endcase
710,8 → 791,8
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;
always @(posedge BCLK) dma_kdet <= DMA_CHK;
assign DMA_MUX = DMA_CHK | dma_kdet;
// global feedback to ADDR_UNIT, early feedback to Op-Dec : you can continue
/example.v
3,11 → 3,12
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: example.v
// Version: 1.0
// Date: 30 May 2015
// Filename: example.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
33,10 → 34,334
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Modules contained in this file:
// example Your first system with the M32632 CPU
// 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
// 8. example Your first system with the M32632 CPU
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 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_INP[87:80],COP_INP[95:88]};
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 edge
 
// +++++++++++++++++++++++++ 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[addr_msb:2]) : {addr,nibble});
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
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 8. example Your first system with the M32632 CPU
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module example ( CLK, RESET_N, NMI_N, INT_N, IN_REG, OUT_REG);
 
input CLK;
87,11 → 412,25
wire COP_DONE;
wire [63:0] COP_IN;
 
// DMA
wire dmai;
wire zero;
wire run;
wire HLDA;
wire FILLR;
reg HOLD;
reg [4:0] counter;
reg [27:3] MEM_REG;
reg [31:0] timer;
reg incm;
wire [31:0] stat;
 
M32632 CPU(
// ++++++++++ Basic Signals
.BCLK(CLK),
.MCLK(~CLK),
.WRCFG(1'b1),
.DRAMSZ(3'd4),
.BRESET(RST_N),
.NMI_N(nmi_reg),
.INT_N(int_reg),
124,10 → 463,10
.DRAM_ADR(DRAM_ADR),
.DRAM_DI(DRAM_DI),
// ++++++++++ DMA Interface
.HOLD(1'b1),
.HLDA(),
.FILLRAM(1'b0),
.DMA_AA(24'd0),
.HOLD(HOLD),
.HLDA(HLDA),
.DMA_CHK(FILLR),
.DMA_AA(MEM_REG[27:4]),
// ++++++++++ Coprocessor Interface
.COP_GO(COP_GO),
.COP_OP(COP_OP),
172,7 → 511,7
.RST_N(RST_N),
.STATSIGS(STATSIGS),
.ADDR(IO_A[4:2]),
.DATA(STAT_DAT));
.DATA(stat));
 
ex_copro u_copro(
.CLK(CLK),
206,4 → 545,32
int_reg <= INT_N;
end
 
// DMA Test :
assign dmai = IO_WR & (IO_A[31:28] == 4'h4);
assign zero = (counter == 5'd0);
assign run = ~HLDA & ~zero;
always @(posedge CLK) HOLD <= zero;
always @(posedge CLK) incm <= run;
assign FILLR = incm & ~MEM_REG[3];
always @(posedge CLK or negedge RST_N)
if (!RST_N) counter <= 5'd0;
else
begin
if (dmai) counter <= {IO_DI[3:0],1'b0};
else counter <= counter + {{5{run}}};
end
 
always @(posedge CLK)
if (dmai) MEM_REG <= {IO_DI[27:4],1'b0};
else MEM_REG <= MEM_REG + {24'd0,incm};
always @(posedge CLK or negedge RST_N)
if (!RST_N) timer <= 32'd0;
else timer <= timer + 32'd1;
assign STAT_DAT = IO_A[8] ? timer : stat;
endmodule
/M32632.v
3,12 → 3,13
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: M32632.v
// Version: 1.1 bug fix
// History: 1.0 first release of 30 Mai 2015
// Date: 7 October 2015
// Filename: M32632.v
// Version: 2.0
// History: 1.1 bug fix of 7 October 2015
// 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
38,11 → 39,11
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module M32632( BCLK, MCLK, WRCFG, BRESET, NMI_N, INT_N, STATUS, ILO, STATSIGS,
module M32632( BCLK, MCLK, WRCFG, DRAMSZ, 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,
HOLD, HLDA, DMA_CHK, DMA_AA,
COP_GO, COP_OP, COP_OUT, COP_DONE, COP_IN );
 
// ++++++++++ Basic Signals
49,6 → 50,7
input BCLK; // Basic Clock for everything
input MCLK; // Memory Clock, used in Caches
input WRCFG;
input [2:0] DRAMSZ;
input BRESET;
input NMI_N;
input INT_N;
83,7 → 85,7
// ++++++++++ DMA Interface
input HOLD;
output HLDA;
input FILLRAM;
input DMA_CHK;
input [27:4] DMA_AA;
// ++++++++++ Coprocessor Interface
output COP_GO;
181,6 → 183,7
.MCLK(MCLK),
.BCLK(BCLK),
.WRCFG(WRCFG),
.DRAMSZ(DRAMSZ),
.BRESET(BRESET),
.PTB_WR(PTB_WR),
.PTB_SEL(PTB_SEL),
196,7 → 199,7
.WAMUX(WAMUX),
.ENWR(ENWR),
.IC_PREQ(IC_PREQ),
.FILLRAM(FILLRAM),
.DMA_CHK(DMA_CHK),
.CFG(CFG[10:9]),
.ENDRAM(ENDRAM),
.CINVAL(CINV[1:0]),
308,6 → 311,7
ICACHE LEGS(
.MCLK(MCLK),
.BCLK(BCLK),
.DRAMSZ(DRAMSZ),
.BRESET(BRESET),
.PTB_WR(PTB_WR),
.PTB_SEL(PTB_SEL),
/SP_FPU.v
3,11 → 3,12
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: SP_FPU.v
// Version: 1.0
// Date: 30 May 2015
// Filename: SP_FPU.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
32,6 → 33,8
//
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Testversion mit Pipeline Register in SFPU_ADDSUB **************
//
// Modules contained in this file:
// 1. ADDSUB Adder and Subtractor for 36 bit
// 2. SFPU_ADDSUB Single Precision Floating Point Adder/Subtractor and Converter
60,33 → 63,32
// 2. SFPU_ADDSUB Single Precision Floating Point Adder/Subtractor and Converter
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module SFPU_ADDSUB ( SRC1, SRC2, NZEXP, BWD, SELECT, OUT, IOUT, CMPRES );
module SFPU_ADDSUB ( BCLK, SRC1, SRC2, NZEXP, BWD, SELECT, OUT, IOUT, CMPRES );
 
input BCLK;
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;
output [36:0] OUT; // the result
output reg [31:0] IOUT; // result of ROUNDFi/TRUNCFi/FLOORFi
output reg [1:0] CMPRES;
 
// ++++++++++++++++++++++++++++++++++
// MOViF : 1. step
reg [31:8] movdat;
reg [31:0] 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
casex(BWD)
2'b00 : movdat = {{24{SRC1[7]}}, SRC1[7:0]}; // Byte
2'b01 : movdat = {{16{SRC1[15]}},SRC1[15:0]}; // Word
default : movdat = SRC1[31:0]; // Double
endcase
assign movif = movdat[31] ? (32'h0 - {movdat,SRC1[7:0]}) : {movdat,SRC1[7:0]};
assign movif = ({32{movdat[31]}} ^ movdat) + {31'h0,movdat[31]};
// -2^31 is kept
// ROUNDFi/TRUNCFi/FLOORFi : 1. step
93,11 → 95,12
reg ovflag,ovflag2;
wire [8:0] rexdiff,rexo;
wire rovfl,minint;
reg rovfl;
wire 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;
always @(posedge BCLK) 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
118,19 → 121,18
wire [8:0] exdiff;
wire [23:0] madiff;
wire switch,sign,sign1,sign2;
wire variante;
wire switch,sign1,sign2;
reg variante;
wire vorz,addflag;
wire [35:0] result_sw,result_nosw;
wire [35:0] result,result_sw,result_nosw;
wire [24:0] value1,value2;
wire cmp_res;
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/TRUNC/MOViF uses case 1
// if exdiff = 0 the shifter to the right is not needed ! MUX at the end, ROUND/TRUNC/MOViF uses case 1
always @(posedge BCLK) variante <= (exdiff[8:1] == 8'h00) | (exdiff == 9'h1FF) | SELECT[1];
// ++++++++++++++++++++++++++ 1. case works on MOViF +++++++++++++++++++++++++++++++++++++++
 
169,62 → 171,72
 
// 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 > SRC2
assign CMPRES[0] = (SRC1 == SRC2) | (~NZEXP[2] & ~NZEXP[1]); // Z-Bit : SRC1=SRC2, +0.0 = -0.0
assign cmp_res = (SRC1 == SRC2) | (~NZEXP[2] & ~NZEXP[1]); // Z-Bit : SRC1=SRC2, +0.0 = -0.0
always @(posedge BCLK) CMPRES <= {(~cmp_res & (switch ? ~sign1 : sign2)),cmp_res}; // see table above : N-Bit=1 if SRC1 > SRC2
 
// ++++++++++++++++++++++++++++++++++
// ADD/SUB : 3. step : prepare of Barrelshifter Left
wire [31:0] blshift;
wire [9:0] shiftl;
reg [9:0] shiftl;
wire shift_16;
wire [33:0] add_q;
reg [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
always @(posedge BCLK) 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)} ;
always @(posedge BCLK) 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 shift_8,shift_4,shift_2,shift_1;
wire [1:0] lsb_bl;
wire [31:0] blshifta,blshiftb,blshiftc,blshiftd,blshifte;
wire [31:0] blshifta,blshiftc,blshiftd,blshifte;
reg [31:0] blshiftb;
wire [9:0] expol;
wire [36:0] out_v1;
reg [1:0] rinex;
reg zero,sign,select_v1;
reg [4:3] pshift;
assign blshifta = shift_16 ? {blshift[15:0],16'h0000} : blshift;
assign blshifta = shift_16 ? {blshift[15:0],16'd0} : blshift;
assign shift_8 = (blshifta[31:24] == 8'h00);
assign blshiftb = shift_8 ? {blshifta[23:0],8'h00} : blshifta;
always @(posedge BCLK)
blshiftb <= shift_8 ? {blshifta[23:0],8'd0} : blshifta;
assign shift_4 = (blshiftb[31:28] == 4'h0);
assign blshiftc = shift_4 ? {blshiftb[27:0],4'h0} : blshiftb;
assign blshiftc = shift_4 ? {blshiftb[27:0],4'd0} : blshiftb;
assign shift_2 = (blshiftc[31:30] == 2'b00);
assign blshiftd = shift_2 ? {blshiftc[29:0],2'b00} : blshiftc;
assign blshiftd = shift_2 ? {blshiftc[29:0],2'd0} : blshiftc;
assign shift_1 = ~blshiftd[31];
assign blshifte = shift_1 ? {blshiftd[30:0],1'b0} : blshiftd;
assign blshifte = shift_1 ? {blshiftd[30:0],1'b0} : blshiftd;
always @(posedge BCLK) pshift <= {shift_16,shift_8};
 
// 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};
assign expol = (shiftl - {5'h00,pshift,shift_4,shift_2,shift_1}) | {1'b0,rovfl,8'd0};
always @(posedge BCLK) rinex <= inex;
// 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 lsb_bl = (SELECT[1:0] == 2'b11) ? rinex : {blshifte[7],(blshifte[6:0] != 7'd0)};
assign zero = (~SELECT[1] & ~NZEXP[2] & ~NZEXP[1])
| ((blshift == 32'h0) & ((~addflag & ~SELECT[1]) | (SELECT[1:0] == 2'b10)));
always @(posedge BCLK) 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;
always @(posedge BCLK) 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};
always @(posedge BCLK) select_v1 <= addflag & ~SELECT[1];
assign out_v1 = select_v1 ? {zero,sign,1'b0,add_q}
: {zero,sign,expol,blshifte[30:8],lsb_bl};
// +++++++++++++++++++++++++ 2. case works on ROUND/TRUNC/FLOOR ++++++++++++++++++++++++++++++++++
 
wire vswitch;
269,8 → 281,7
// ROUNDFi/TRUNCFi/FLOORFi : 3. step : round to integer
reg car_ry;
wire [30:0] compl;
wire [31:0] iadder;
wire [32:0] iadder;
assign inex = brshifte[1:0]; // Inexact-Flag-Data via multiplexer at the end
281,17 → 292,15
default : car_ry = sign1; // TRUNCLi , simple cut
endcase
 
assign compl = sign1 ? ~brshifte[32:2] : brshifte[32:2];
assign iadder = (sign1 ? {2'b11,~brshifte[32:2]} : {2'b0,brshifte[32:2]}) + {32'h0,car_ry};
assign iadder = {sign1,compl} + {31'h0,car_ry};
assign IOUT = minint ? 32'h8000_0000 : iadder;
always @(posedge BCLK) IOUT <= minint ? 32'h8000_0000 : iadder[31:0];
 
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;
default : ovflag2 = (iadder[32] != iadder[31]); // Double
endcase
// ++++++++++++++++++++++++++++++++++
303,7 → 312,7
wire [7:0] eminus1;
wire [33:0] vadd_q,vsub_q;
wire vzero;
wire [36:0] out_v0;
reg [36:0] out_v0;
assign lsb = (brshifte[6:0] != 7'h00);
 
324,10 → 333,10
: {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 vzero = (vresult[26:0] == 27'h0); // only if "-" can be the result 0
 
assign out_v0 = addflag ? {vzero,vorz,1'b0,vadd_q}
: {vzero,vorz,1'b0,vsub_q} ;
always @(posedge BCLK) out_v0 <= addflag ? { 1'b0,vorz,1'b0,vadd_q}
: {vzero,vorz,1'b0,vsub_q} ;
assign OUT = variante ? out_v1 : out_v0; // Last multiplexer
338,13 → 347,14
// 3. SFPU_MUL Single Precision Floating Point Multiplier
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module SFPU_MUL ( SRC1, SRC2, MRESULT, NZEXP, OUT);
module SFPU_MUL ( BCLK, SRC1, SRC2, MRESULT, NZEXP, OUT);
 
input BCLK;
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
output reg [36:0] OUT; // The result
 
wire [9:0] exponent,expoh,expol;
wire [1:0] restlow,resthigh;
361,8 → 371,8
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};
always @(posedge BCLK) OUT <= MRESULT[47] ? {zero,sign,expoh,MRESULT[46:24],resthigh}
: {zero,sign,expol,MRESULT[45:23],restlow};
endmodule
 
371,9 → 381,10
// 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, LD_FSR, UP_SP);
module SP_FPU (BCLK, START, OPCODE, SRC1, SRC2, FSR, MRESULT, BWD, FL, FP_OUT, I_OUT, TT_SP, SP_CMP, SP_MUX, LD_FSR, UP_SP);
 
input BCLK; // is not used !
input START;
input [7:0] OPCODE;
input [31:0] SRC1,SRC2; // Input data
input [8:3] FSR; // Floating Point Status Register
384,10 → 395,12
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;
output SP_MUX,LD_FSR;
output reg UP_SP;
 
reg [2:0] tt;
reg [3:0] select;
reg nan;
reg car_ry;
 
wire [36:0] mulout,addout,fpout;
395,7 → 408,7
wire [34:2] rund; // Indexnumbers like xxxout
wire overflow,underflow,inexact;
wire op_cmp;
wire nan,nan_1,nan_2;
wire nan_1,nan_2;
// Control of datapath
 
415,7 → 428,7
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 (according datasheet NS32016)
assign UP_SP = select[3] & FL; // All FPU opcodes of SP_FPU
always @(posedge BCLK) UP_SP = select[3] & FL & START; // All FPU opcodes of SP_FPU, all are using 2 Clock
assign op_cmp = (OPCODE == 8'hB2) & FL;
// SRCFLAGS
425,14 → 438,14
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));
always @(posedge BCLK) 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),
SFPU_ADDSUB IADDSUB ( .BCLK(BCLK), .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) );
SFPU_MUL IMUL ( .BCLK(BCLK), .SRC1(SRC1), .SRC2(SRC2), .MRESULT(MRESULT), .OUT(mulout), .NZEXP(nzexp) );
// FP - Pfad : selection of result and rounding :
 
/DECODER.v
3,10 → 3,10
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: DECODER.v
// Version: 1.1 bug fix
// History: 1.0 first release of 30 Mai 2015
// Date: 21 January 2016
// Filename: DECODER.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2016 Udo Moeller
//
41,7 → 41,8
module DECODER ( BCLK, BRESET, INT_N, NMI_N, ANZ_VAL, OPREG, CFG, PSR, ACC_DONE, DC_ABORT, IC_ABORT, ACB_ZERO, DONE,
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, LD_DIN, LD_IMME,
INFO_AU, ACC_FELD, WREN, WRADR, WMASKE, WR_REG, DETOIP, MMU_UPDATE, RESTART, STOP_IC, RWVAL, ENA_HK, ILO, COP_OP );
INFO_AU, ACC_FELD, WREN, WRADR, WMASKE, WR_REG, DETOIP, MMU_UPDATE, RESTART, STOP_IC, RWVAL, ENA_HK, ILO, COP_OP,
PHOUT );
 
input BCLK,BRESET;
input INT_N,NMI_N; // external inputs
85,6 → 86,7
output ENA_HK;
output reg ILO;
output [23:0] COP_OP;
output [7:0] PHOUT; // for Debug purposes, phase_reg output
reg [31:0] DISP,disp_val;
reg [10:0] oper_i;
94,7 → 96,7
reg wren_i;
reg [5:0] wradr_i;
reg [1:0] wmaske_i;
reg [1:0] START;
reg [1:0] start_i;
reg [23:0] COP_OP;
reg spupd_i;
reg [3:0] disp_sel;
174,6 → 176,8
wire op_1byte,op_12byte,op_2byte,op_3byte;
wire jump;
wire short_op,short_def;
wire opt_imme;
wire [7:0] opti_byte;
wire acb_op,acb_flag;
wire zero,carry_psr,negativ,larger,flag;
wire valid_size;
255,7 → 259,6
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;
346,9 → 349,11
else
if (next) phase_reg <= new_op[47:40];
assign PHOUT = phase_reg; // only to debug
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'b11_xx : USED = {1'b0,~op_1byte,(op_1byte | op_3byte)} + {2'd0,opt_imme};
4'b0x_11 : USED = di_stat[3:1];
default : USED = 3'd0;
endcase
530,8 → 535,8
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 op_1byte = op1_feld[18] & valid[0];
assign op_12byte = op1_feld[19] & valid[1];
assign new_addr = op1_feld[52:34];
assign new_regs = op1_feld[33:20];
650,10 → 655,10
always @(dim_feld or OPREG or valid or ANZ_VAL) // Bit 0 is "Data ok", the upper 3 bits are for USED
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'b01_xx : di_stat = {3'b010,valid[1]};
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_10 : di_stat = {3'b010,valid[1]};
4'b11_11 : di_stat = {3'b100,ANZ_VAL[2]};
endcase
 
681,12 → 686,12
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)
always @(*)
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
3'b1xx : imme_i = opt_imme ? {24'hxxxx_xx,opti_byte} : {{29{OPREG[10]}},OPREG[9:7]}; // for MOVQ etc. only OPREG can be used
endcase
assign IMME_Q = store_pc ? PC_SAVE : imme_i;
730,7 → 735,7
// [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-Bytes
assign valid_size = (OPREG[1:0] != 2'b10) & valid[1]; // valid size + valid OPREG-Bytes
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
747,7 → 752,7
endcase
// Unfortunately SETCFG must be implemented : it is transformed to a two byte opcode with one byte IMM operand
assign setcfg = (OPREG[13:0] == 14'h0B0E) & (valid[1:0] == 2'b11);
assign setcfg = (OPREG[13:0] == 14'h0B0E) & valid[1];
 
always @(*)
casex ({setcfg,OPREG[10:2]})
783,7 → 788,7
assign op_2byte = (valid_size | setcfg) & ~op2_feld[7]; // it must be for sure shown "Invalid Opcode"
 
// 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 & PHASE_0;
assign short_op = ((((~OPREG[5]) | (OPREG[6:4] == 3'b011)) & (OPREG[3:2] == 2'b11) & valid_size) | opt_imme) & PHASE_0;
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. , used only in Phase 0
828,9 → 833,9
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[10:9]) == 2'b00);
always @(posedge BCLK) if (PHASE_0) exin_cmd <= (~OPREG[10] & (OPREG[6:0] == 7'h2E)) & (valid[2:0] == 3'b111);
always @(posedge BCLK) if (PHASE_0) exin_cmd <= (~OPREG[10] & (OPREG[6:0] == 7'h2E)) & valid[2];
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) & (valid[2:0] == 3'b111); // INSS
always @(posedge BCLK) if (PHASE_0) inss_op <= (OPREG[13:10] == 4'h2) & (OPREG[7:0] == 8'hCE) & valid[2]; // INSS
// ++++++++++++++ 3 byte opcodes +++++++++++++++++
 
852,7 → 857,6
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
872,7 → 876,7
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],~OPREG[14]}; // exclusiv for DEI/MEI
assign hdr_g = {3'b000,OPREG[16:15],~OPREG[14]}; // exclusiv for DEI and MEI
assign hdr_m = {3'b001,OPREG[17:15]}; // MMU Register Index 8-15
always @(*)
885,21 → 889,21
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'h7,hdo_a}; // MOVX/ZiD
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'h8,hdo_c}; // FFSi
// 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,hdl_c,4'h9,hdo_a}; // MOVif
11'b010x_xx_0011x : op3_feld = {6'o11, 3'o5,hdr_e,hdr_f, 2'b11,2'b10,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // MOVLF
11'b011x_xx_0011x : op3_feld = {6'o11, 3'o5,hdr_e,hdr_f, 2'b10,2'b11,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // MOVFL
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,hdl_c,4'h9,hdo_a}; // ROUNDi,TRUNCi
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,hdl_c,4'h9,hdo_a}; // FLOORi
11'b111x_xx_00110 : op3_feld = {6'o11, 3'o5,hdr_c,hdr_b, hdl_d,hdl_b,OPREG[23:14],2'b00,hdl_c,op_cop}; // SEARCH
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,hdl_e,4'hB,hdo_a}; // ADDf,SUBf
11'bxx00_0x_10110 : op3_feld = {6'o11, 3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,op_cop}; // Coprocessor
11'b1000_0x_10111 : op3_feld = {6'o11, 3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // DIVf
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,hdl_e,4'hB,hdo_a}; // MULf
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,hdl_e,4'hB,hdo_a}; // CMPf
11'b0001_0x_10111 : op3_feld = {6'o11, 3'o1,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // MOVf
11'bx101_0x_10111 : op3_feld = {6'o11, 3'o1,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // NEGf,ABSf
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,8'h92}; // LFSR
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,8'h9C}; // SFSR
11'b000x_xx_0011x : op3_feld = {6'o11,3'o5,hdr_a,hdr_d, hdl_b,hdl_d,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // MOVif
11'b010x_xx_0011x : op3_feld = {6'o11,3'o5,hdr_e,hdr_f, 2'b11,2'b10,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // MOVLF
11'b011x_xx_0011x : op3_feld = {6'o11,3'o5,hdr_e,hdr_f, 2'b10,2'b11,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // MOVFL
11'b10xx_xx_0011x : op3_feld = {6'o11,3'o5,hdr_c,hdr_b, hdl_d,hdl_b,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // ROUNDi,TRUNCi
11'b111x_xx_00111 : op3_feld = {6'o11,3'o5,hdr_c,hdr_b, hdl_d,hdl_b,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // FLOORi
11'b111x_xx_00110 : op3_feld = {6'o11,3'o5,hdr_c,hdr_b, hdl_d,hdl_b,OPREG[23:14],2'b00,hdl_c,op_cop}; // SEARCH
11'b0x00_0x_10111 : op3_feld = {6'o11,3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // ADDf,SUBf
11'bxx00_0x_10110 : op3_feld = {6'o11,3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,op_cop}; // Coprocessor
11'b1000_0x_10111 : op3_feld = {6'o11,3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // DIVf
11'b1100_0x_10111 : op3_feld = {6'o11,3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // MULf
11'b0010_0x_1011x : op3_feld = {6'o11,3'o6,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // CMPf
11'b0001_0x_10111 : op3_feld = {6'o11,3'o1,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // MOVf
11'bx101_0x_10111 : op3_feld = {6'o11,3'o1,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // NEGf,ABSf
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,8'h92}; // LFSR
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,8'h9C}; // SFSR
// 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'o3,8'h45}; // LMR
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'o3,8'h45}; // SMR
907,7 → 911,7
11'b000x_xx_0000x : op3_feld = {6'o11,3'o0,6'hxx,6'hxx, 2'bxx,2'b10,OPREG[23:14], 2'b10,hdl_c,hdo_d}; // MOVS,CMPS
11'b0011_xx_0000x : op3_feld = {6'o11,3'o0,6'hxx,6'hxx, 2'bxx,2'b10,OPREG[23:14], 2'b10,hdl_c,hdo_d}; // SKPS
// 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,hdl_e,op_cop};
11'bxx01_0x_10110 : op3_feld = {6'o11,3'o5,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,op_cop};
// 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'h7,hdo_a};
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'h7,hdo_a}; // DEI/MEI
916,7 → 920,7
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, hdo_d}; // MOVM/CMPM
11'b001x_0x_1111x : op3_feld = {6'o11,3'o2,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b10,hdl_e,4'hC,hdo_a}; // DOTf,POLYf
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'hB,hdo_e}; // LOGB
11'b0100_0x_1111x : op3_feld = {6'o11,3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b10,hdl_e,4'hB,hdo_e}; // SCALB
11'b0100_0x_1111x : op3_feld = {6'o11,3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_e}; // SCALB
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'h7,hdo_a}; // EXTS
11'bxxx0_xx_1110x : op3_feld = {6'o71,3'o2,hdr_a,hdr_b, hdl_h,hdl_b,OPREG[23:14],2'b10,hdl_c,4'h8,hdo_c}; // CHECK
11'b0x1x_xx_0100x : op3_feld = (OPREG[18:17] == 2'b00) ? // target is register => standard flow
925,7 → 929,7
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'h6,hdo_a}; // ADDP,SUBP
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'h7,3'd0,OPREG[12]}; // ADDP,SUBP
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'h8,hdo_c}; // EXT
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'h8,hdo_c}; // INS
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'h8,hdo_a}; // INSS
938,7 → 942,7
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); // valid for all incl. CUSTOM
assign op_3byte = valid[2] & (OPREG[2:0] == 3'b110) & (op3_feld[7:4] != 4'hA); // valid for all incl. CUSTOM
// +++++++++++++ Evaluation for 2 and 3 byte opcodes ++++++++++++++++++
 
977,6 → 981,20
assign dest_r = src_2[5:0];
assign dest_rl = {dest_r[5:1],1'b0};
// ++++++++++++++++++++++++++++ Immediate Optimization +++++++++++++++++++++++++++++++++++
// 3 Byte Immediate
assign opt_imme = (valid[2] & (OPREG[1:0] == 2'd0) & (OPREG[15:11] == 5'b10100) &
// ADD,ADDC,SUB,SUBC,BIC,OR,AND,XOR CMP MOV
( ((OPREG[10:8] != 3'b111) & (~OPREG[2] | (OPREG[5:2] == 4'h1) | (OPREG[5:2] == 4'h5))) // not ADDR und TBIT
|((OPREG[6:2] == 5'b11111) & (OPREG[8:7] == 2'b10) & (OPREG[10:9] != 2'b11)))) // BICPSR,BISPSR,ADJSP and ~CASE
// 4 not Scaled Index Immediate
| (ANZ_VAL[2] & (OPREG[18:16] != 3'b111) & (OPREG[23:19] == 5'b10100) &
( ((OPREG[7:0] == 8'h4E) & ~OPREG[13] & ~OPREG[11]) // ROT,ASH,LSH but not NEG,NOT,ABS,COM
|((OPREG[7:0] == 8'hCE) & (OPREG[13:12] == 2'b01) & (OPREG[9:8] == 2'd0)))); // MOVX/ZBi
 
assign opti_byte = (OPREG[1:0] == 2'b10) ? OPREG[31:24] : OPREG[23:16];
// +++++++++++++++++++++++++ Coprocessor operations field ++++++++++++++++++++++++++++++
always @(posedge BCLK) if (PHASE_0) COP_OP <= OPREG[23:0];
1376,9 → 1394,9
{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+x
new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_r, opera, 2'b00,2'b00, nxrw2};
new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_r, opera, 2'b00,2'b10, 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};
new_op = {re_wr, 8'h27, src_x,src_x, 1'b0,dest_r, opera, 2'b00,2'b10, 4'b0001};
// Destination address calculate
// Phase 37 : wait for data and Disp2 for External addressing : part 2 EA = (MOD+4)+4*DISP1
1695,14 → 1713,15
assign WMASKE = {(spupd | format1 | wradr_i[5] | wmaske_i[1] | index_cmd | (oper_i[7:0] == 8'h83)),wmaske_i[0]};
assign WRADR = spupd ? {~stack[5],stack[4:0]} : wradr_i;
assign WREN = (spupd | wren_i) & no_trap;
assign START = no_trap ? start_i : 2'b0;
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 important
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-Op
always @(posedge BCLK) start_i <= 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-Op
assign LD_OUT = {(ldoreg[1] & no_trap),ldoreg[0]}; // [1] = LD_OUT (for CMP too) , [0] = LD_LDQ
/REGISTERS.v
3,11 → 3,12
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: REGISTERS.v
// Version: 1.0
// Date: 30 May 2015
// Filename: REGISTERS.v
// Version: 2.0
// History: 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
275,30 → 276,29
output [31:0] DOUT;
output reg SELI;
 
reg [2:0] MX;
reg [2:0] mx;
 
wire [3:0] BE;
wire [2: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 [15:0] REGFILE_C [0:63]; // Byte 3 and 2 , Verilog allows no "Byte Write" in wider memories !!!
reg [7:0] REGFILE_B [0:63]; // Byte 1
reg [7:0] REGFILE_A [0:63]; // Byte 0
reg [31:0] RF;
 
assign BE = {WMASKE[1],WMASKE[1],(WMASKE[1] | WMASKE[0]),1'b1};
assign be = {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]) 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];
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 ++++++++++++
 
305,8 → 305,7
always @(posedge BCLK)
if (RADR[7])
begin
RF[31:24] <= REGFILE_D[RADR[5:0]];
RF[23:16] <= REGFILE_C[RADR[5:0]];
RF[31:16] <= REGFILE_C[RADR[5:0]];
RF[15:8] <= REGFILE_B[RADR[5:0]];
RF[7:0] <= REGFILE_A[RADR[5:0]];
end
314,10 → 313,9
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];
if (be[2]) REGFILE_C[WADR] <= DIN[31:16];
if (be[1]) REGFILE_B[WADR] <= DIN[15:8];
if (be[0]) REGFILE_A[WADR] <= DIN[7:0];
end
 
endmodule
/DCACHE.v
3,12 → 3,13
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: DCACHE.v
// Version: 1.1 bug fix
// History: 1.0 first release of 30 Mai 2015
// Date: 7 October 2015
// Filename: DCACHE.v
// Version: 2.0
// History: 1.1 bug fix of 7 October 2015
// 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
38,15 → 39,16
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module DCACHE( BCLK, MCLK, WRCFG, MDONE, BRESET, PTB_WR, PTB_SEL, IO_READY, REG_OUT, PSR_USER, WRITE, READ, RMW, QWATWO,
WAMUX, ENWR, IC_PREQ, FILLRAM, CFG, CINVAL, DMA_AA, DP_Q, DRAM_Q, IC_VA, ICTODC, IO_Q, IVAR, MCR_FLAGS,
PACKET, SIZE, VADR, WADDR, WCTRL, IO_RD, IO_WR, DRAM_ACC, DRAM_WR, INIT_RUN, PTE_STAT, KDET, HLDA,
ACC_STAT, DP_DI, DRAM_A, DRAM_DI, IACC_STAT, IC_SIGS, IO_A, IO_BE, IO_DI, KOLLI_A, MMU_DIN, ZTEST,
module DCACHE( BCLK, MCLK, WRCFG, DRAMSZ, MDONE, BRESET, PTB_WR, PTB_SEL, IO_READY, REG_OUT, PSR_USER, WRITE, READ, RMW,
QWATWO, WAMUX, ENWR, IC_PREQ, DMA_CHK, CFG, CINVAL, DMA_AA, DP_Q, DRAM_Q, IC_VA, ICTODC, IO_Q, IVAR,
MCR_FLAGS, PACKET, SIZE, VADR, WADDR, WCTRL, IO_RD, IO_WR, DRAM_ACC, DRAM_WR, INIT_RUN, PTE_STAT, KDET,
HLDA, ACC_STAT, DP_DI, DRAM_A, DRAM_DI, IACC_STAT, IC_SIGS, IO_A, IO_BE, IO_DI, KOLLI_A, MMU_DIN, ZTEST,
RWVAL, RWVFLAG, DBG_IN, DBG_HIT, ENDRAM );
 
input BCLK;
input MCLK;
input WRCFG;
input [2:0] DRAMSZ;
input MDONE;
input BRESET;
input PTB_WR;
62,7 → 64,7
input WAMUX;
input ENWR;
input IC_PREQ;
input FILLRAM;
input DMA_CHK;
input [1:0] CFG;
input [1:0] CINVAL;
input [27:4] DMA_AA;
189,8 → 191,7
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;
wire [23:0] CVALID;
 
reg [35:0] MMU_TAGS [0:255]; // Tag Set for MMU : 256 entries of 36 bits
reg [35:0] MMU_Q;
260,10 → 261,14
 
// +++++++++++++++++++++++++ Cache Valid +++++++++++++++++++
 
always @(posedge BCLK) CVALID <= CA_VALID[TAGA[11:7]];
NEU_VALID VALID_RAM(
.BCLK(BCLK),
.VALIN(DAT_CV),
.WADR(WADR_CV),
.WREN(WE_CV),
.RADR(TAGA[11:7]),
.VALOUT(CVALID) );
 
always @(negedge BCLK) if (WE_CV) CA_VALID[WADR_CV] <= DAT_CV;
 
// +++++++++++++++++++++++++ Tag Set 0 +++++++++++++++++++++
 
always @(posedge BCLK) TAG0 <= TAGSET_0[TAGA];
341,7 → 346,7
.IC_PREQ(IC_PREQ),
.CAPDAT(CAPDAT[31:0]),
.CPU_OUT(DP_Q[59:44]),
.FILLRAM(FILLRAM),
.DMA_CHK(DMA_CHK),
.IC_VA(IC_VA),
.ICTODC(ICTODC),
.VADR_R(VADR_R[31:12]),
381,7 → 386,7
.MMU_HIT(MMU_HIT),
.WRITE(WRITE),
.KDET(KDET),
.ADDR(ADDR),
.ADDR({RADR[31:28],ADDR}),
.CFG(CFG),
.ENDRAM(ENDRAM),
.CVALID(CVALID),
391,7 → 396,7
.CA_SET(CA_SET),
.WB_ACC(WB_ACC),
.USE_CA(USE_CA),
.IOSEL(RADR[31:28]),
.DRAMSZ(DRAMSZ),
.IO_SPACE(IO_SPACE),
.KILL(KILL),
.DC_ILO(RWVAL[2]),
/ADDR_UNIT.v
3,13 → 3,13
// This file is part of the M32632 project
// http://opencores.org/project,m32632
//
// Filename: ADDR_UNIT.v
// Version: 1.2 bug fix
// History: 1.1 bug fix release of 7 October 2015
// 1.0 first release of 30 Mai 2015
// Date: 8 March 2016
// Filename: ADDR_UNIT.v
// Version: 2.0
// History: 1.1 bug fix of 7 October 2015
// 1.0 first release of 30 Mai 2015
// Date: 14 August 2016
//
// Copyright (C) 2015 Udo Moeller
// Copyright (C) 2016 Udo Moeller
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
159,7 → 159,7
always @(index_sel or sign_ext_src1 or SRC1)
casex (index_sel)
4'b1_0xx : index_val = sign_ext_src1; // f�r CASE
 
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};
320,13 → 320,13
//
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_0x1x_0 : acc_step = acc_ok; // WRITE Adr. is not perfect and waits for last packet
7'b01_0100_0 : acc_step = acc_ok; // WRITE Adr. perfect - acc_step after 1. packet if not io_acc
7'b01_0x1x_0 : acc_step = acc_ok; // WRITE Adr. ist not perfect and waits for last packet
7'b01_0100_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_0x1x_0 : acc_step = acc_ok; // WRITE Adr. is not perfect and waits for last packet
7'b10_0100_0 : acc_step = acc_ok; // WRITE Adr. perfect - acc_step after 1. packet if not io_acc
7'b10_0x1x_0 : acc_step = acc_ok; // WRITE Adr. ist not perfect and waits for last packet
7'b10_0100_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;

powered by: WebSVN 2.1.0

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