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