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

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/or1200/rtl
    from Rev 187 to Rev 258
    Reverse comparison

Rev 187 → Rev 258

/verilog/or1200_spram_1024x8.v
385,9 → 385,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
 
//
// RAM write
394,7 → 394,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_defines.v
124,12 → 124,14
//`define OR1200_XILINX_RAMB4
//`define OR1200_XILINX_RAM32X1D
//`define OR1200_USE_RAM16X1D_FOR_RAM32X1D
`define OR1200_ACTEL
// Generic models should infer RAM blocks at synthesis time (not only effects
// single port ram.)
`define OR1200_GENERIC
 
//
// Do not implement Data cache
//
`define OR1200_NO_DC
//`define OR1200_NO_DC
 
//
// Do not implement Insn cache
161,8 → 163,8
//`define OR1200_IC_1W_512B
//`define OR1200_IC_1W_4KB
`define OR1200_IC_1W_8KB
`define OR1200_DC_1W_4KB
//`define OR1200_DC_1W_8KB
//`define OR1200_DC_1W_4KB
`define OR1200_DC_1W_8KB
 
`endif
 
313,17 → 315,6
//`define OR1200_IMPL_CY
 
//
// Implement optional l.div/l.divu instructions
//
// By default divide instructions are not implemented
// to save area and increase clock frequency. or32 C/C++
// compiler can use soft library for division.
//
// To implement divide, multiplier needs to be implemented.
//
//`define OR1200_IMPL_DIV
 
//
// Implement rotate in the ALU
//
// At the time of writing this, or32
353,7 → 344,7
//
// By default multiplier is implemented
//
//`define OR1200_MULT_IMPLEMENTED
`define OR1200_MULT_IMPLEMENTED
 
//
// Implement multiply-and-accumulate
362,9 → 353,20
// implement MAC, multiplier needs to be
// implemented.
//
//`define OR1200_MAC_IMPLEMENTED
`define OR1200_MAC_IMPLEMENTED
 
//
// Implement optional l.div/l.divu instructions
//
// By default divide instructions are not implemented
// to save area and increase clock frequency. or32 C/C++
// compiler can use soft library for division.
//
// To implement divide, both multiplier and MAC needs to be implemented.
//
`define OR1200_DIV_IMPLEMENTED
 
//
// Low power, slower multiplier
//
// Select between low-power (larger) multiplier
379,6 → 381,16
// Implement HW Single Precision FPU
//
//`define OR1200_FPU_IMPLEMENTED
//
// Select modules for FPU
`ifdef OR1200_FPU_IMPLEMENTED
// FPU arithmetic module (add,sub,mul,div)
`define OR1200_FPU_ARITH_FPU100
// FPU conversion module (int-float,float-int)
`define OR1200_FPU_CONV_USSELMANN
// FPU comparison module
`define OR1200_FPU_COMP_USSELMANN
`endif
 
//
// Clock ratio RISC clock versus WB clock
401,7 → 413,7
// Memory macro w/ two ports (see or1200_tpram_32x32.v)
//`define OR1200_RFRAM_TWOPORT
//
// Memory macro dual port (see or1200_dpram_32x32.v)
// Memory macro dual port (see or1200_dpram.v)
`define OR1200_RFRAM_DUALPORT
 
//
471,6 → 483,11
`define OR1200_ONE_CYCLE 3'd0
`define OR1200_TWO_CYCLES 3'd1
 
// Execution control which will "wait on" a module to finish
`define OR1200_WAIT_ON_WIDTH 2
`define OR1200_WAIT_ON_FPU `OR1200_WAIT_ON_WIDTH'd1
`define OR1200_WAIT_ON_MTSPR `OR1200_WAIT_ON_WIDTH'd2
 
// Operand MUX selects
`define OR1200_SEL_WIDTH 2
`define OR1200_SEL_RF 2'd0
1225,9 → 1242,25
// 3 for 8 bytes, 4 for 16 bytes etc
`define OR1200_DCLS 4
 
// Define to perform store refill (potential performance penalty)
// `define OR1200_DC_STORE_REFILL
// Define to enable default behavior of cache as write through
// Turning this off enabled write back statergy
//
`define OR1200_DC_WRITETHROUGH
 
// Define to enable stores from the stack not doing writethrough.
// EXPERIMENTAL
//`define OR1200_DC_NOSTACKWRITETHROUGH
 
// Data cache SPR definitions
`define OR1200_SPRGRP_DC_ADR_WIDTH 3
// Data cache group SPR addresses
`define OR1200_SPRGRP_DC_DCCR 3'd0 // Not implemented
`define OR1200_SPRGRP_DC_DCBPR 3'd1 // Not implemented
`define OR1200_SPRGRP_DC_DCBFR 3'd2
`define OR1200_SPRGRP_DC_DCBIR 3'd3
`define OR1200_SPRGRP_DC_DCBWR 3'd4 // Not implemented
`define OR1200_SPRGRP_DC_DCBLR 3'd5 // Not implemented
 
//
// DC configurations
//
1248,6 → 1281,7
`define OR1200_DCTAG_W 20
`endif
 
 
/////////////////////////////////////////////////
//
// Store buffer (SB)
1392,7 → 1426,7
`define OR1200_VR_VER_BITS 31:24
 
// VR values
`define OR1200_VR_REV 6'h01
`define OR1200_VR_REV 6'h08
`define OR1200_VR_RES1 10'h000
`define OR1200_VR_CFG 8'h00
`define OR1200_VR_VER 8'h12
1409,7 → 1443,8
`define OR1200_UPR_PMP_BITS 8
`define OR1200_UPR_PICP_BITS 9
`define OR1200_UPR_TTP_BITS 10
`define OR1200_UPR_RES1_BITS 23:11
`define OR1200_UPR_FPP_BITS 11
`define OR1200_UPR_RES1_BITS 23:12
`define OR1200_UPR_CUP_BITS 31:24
 
// UPR values
1434,7 → 1469,11
`else
`define OR1200_UPR_IMP 1'b1
`endif
`define OR1200_UPR_MP 1'b1 // MAC always present
`ifdef OR1200_MAC_IMPLEMENTED
`define OR1200_UPR_MP 1'b1
`else
`define OR1200_UPR_MP 1'b0
`endif
`ifdef OR1200_DU_IMPLEMENTED
`define OR1200_UPR_DUP 1'b1
`else
1456,7 → 1495,12
`else
`define OR1200_UPR_TTP 1'b0
`endif
`define OR1200_UPR_RES1 13'h0000
`ifdef OR1200_FPU_IMPLEMENTED
`define OR1200_UPR_FPP 1'b1
`else
`define OR1200_UPR_FPP 1'b0
`endif
`define OR1200_UPR_RES1 12'h000
`define OR1200_UPR_CUP 8'h00
 
// CPUCFGR fields
1478,7 → 1522,12
`endif
`define OR1200_CPUCFGR_OB32S 1'b1
`define OR1200_CPUCFGR_OB64S 1'b0
`define OR1200_CPUCFGR_OF32S 1'b0
`ifdef OR1200_FPU_IMPLEMENTED
`define OR1200_CPUCFGR_OF32S 1'b1
`else
`define OR1200_CPUCFGR_OF32S 1'b0
`endif
 
`define OR1200_CPUCFGR_OF64S 1'b0
`define OR1200_CPUCFGR_OV64S 1'b0
`define OR1200_CPUCFGR_RES1 22'h000000
1575,13 → 1624,21
`define OR1200_DCCFGR_NCW 3'h0 // 1 cache way
`define OR1200_DCCFGR_NCS (`OR1200_DCTAG) // Num cache sets
`define OR1200_DCCFGR_CBS (`OR1200_DCLS-4) // 16 byte cache block
`define OR1200_DCCFGR_CWS 1'b0 // Write-through strategy
`ifdef OR1200_DC_WRITETHROUGH
`define OR1200_DCCFGR_CWS 1'b0 // Write-through strategy
`else
`define OR1200_DCCFGR_CWS 1'b1 // Write-back strategy
`endif
`define OR1200_DCCFGR_CCRI 1'b1 // Cache control reg impl.
`define OR1200_DCCFGR_CBIRI 1'b1 // Cache block inv reg impl.
`define OR1200_DCCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl.
`define OR1200_DCCFGR_CBLRI 1'b0 // Cache block lock reg not impl.
`define OR1200_DCCFGR_CBFRI 1'b1 // Cache block flush reg impl.
`define OR1200_DCCFGR_CBWBRI 1'b0 // Cache block WB reg not impl.
`ifdef OR1200_DC_WRITETHROUGH
`define OR1200_DCCFGR_CBWBRI 1'b0 // Cache block WB reg not impl.
`else
`define OR1200_DCCFGR_CBWBRI 1'b1 // Cache block WB reg impl.
`endif
`define OR1200_DCCFGR_RES1 17'h00000
`endif
 
1650,8 → 1707,8
// used to determine where vectors are located. //
///////////////////////////////////////////////////////////////////////////////
// Boot from 0xf0000100
`define OR1200_BOOT_PCREG_DEFAULT 30'h3c00003f
`define OR1200_BOOT_ADR 32'hf0000100
//`define OR1200_BOOT_PCREG_DEFAULT 30'h3c00003f
//`define OR1200_BOOT_ADR 32'hf0000100
// Boot from 0x100
// `define OR1200_BOOT_PCREG_DEFAULT 30'h0000003f
// `define OR1200_BOOT_ADR 32'h00000100
`define OR1200_BOOT_PCREG_DEFAULT 30'h0000003f
`define OR1200_BOOT_ADR 32'h00000100
/verilog/or1200_fpu_intfloat_conv.v
0,0 → 1,442
/////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_intfloat_conv ////
//// Only conversion between 32-bit integer and single ////
//// precision floating point format ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// Modified by Julius Baxter, July, 2010 ////
//// julius.baxter@orsoc.se ////
//// ////
//// TODO: Fix bug where 1.0f in round up goes to integer 2 ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
`timescale 1ns / 100ps
 
/*
 
FPU Operations (fpu_op):
========================
 
0 =
1 =
2 =
3 =
4 = int to float
5 = float to int
6 =
7 =
 
Rounding Modes (rmode):
=======================
 
0 = round_nearest_even
1 = round_to_zero
2 = round_up
3 = round_down
 
*/
 
 
module or1200_fpu_intfloat_conv
(
clk, rmode, fpu_op, opa, out, snan, ine, inv,
overflow, underflow, zero
);
input clk;
input [1:0] rmode;
input [2:0] fpu_op;
input [31:0] opa;
output [31:0] out;
output snan;
output ine;
output inv;
output overflow;
output underflow;
output zero;
 
 
parameter INF = 31'h7f800000,
QNAN = 31'h7fc00001,
SNAN = 31'h7f800001;
 
////////////////////////////////////////////////////////////////////////
//
// Local Wires
//
reg zero;
reg [31:0] opa_r; // Input operand registers
reg [31:0] out; // Output register
reg div_by_zero; // Divide by zero output register
wire [7:0] exp_fasu; // Exponent output from EQU block
reg [7:0] exp_r; // Exponent output (registerd)
wire co; // carry output
wire [30:0] out_d; // Intermediate final result output
wire overflow_d, underflow_d;// Overflow/Underflow
reg inf, snan, qnan;// Output Registers for INF, S/QNAN
reg ine; // Output Registers for INE
reg [1:0] rmode_r1, rmode_r2,// Pipeline registers for round mode
rmode_r3;
reg [2:0] fpu_op_r1, fpu_op_r2,// Pipeline registers for fp
// operation
fpu_op_r3;
 
////////////////////////////////////////////////////////////////////////
//
// Input Registers
//
 
always @(posedge clk)
opa_r <= opa;
 
 
always @(posedge clk)
rmode_r1 <= rmode;
 
always @(posedge clk)
rmode_r2 <= rmode_r1;
 
always @(posedge clk)
rmode_r3 <= rmode_r2;
 
always @(posedge clk)
fpu_op_r1 <= fpu_op;
 
always @(posedge clk)
fpu_op_r2 <= fpu_op_r1;
 
always @(posedge clk)
fpu_op_r3 <= fpu_op_r2;
 
////////////////////////////////////////////////////////////////////////
//
// Exceptions block
//
wire inf_d, ind_d, qnan_d, snan_d, opa_nan;
wire opa_00;
wire opa_inf;
wire opa_dn;
 
or1200_fpu_intfloat_conv_except u0
( .clk(clk),
.opa(opa_r),
.opb(),
.inf(inf_d),
.ind(ind_d),
.qnan(qnan_d),
.snan(snan_d),
.opa_nan(opa_nan),
.opb_nan(),
.opa_00(opa_00),
.opb_00(),
.opa_inf(opa_inf),
.opb_inf(),
.opa_dn(opa_dn),
.opb_dn()
);
 
////////////////////////////////////////////////////////////////////////
//
// Pre-Normalize block
// - Adjusts the numbers to equal exponents and sorts them
// - determine result sign
// - determine actual operation to perform (add or sub)
//
 
wire nan_sign_d, result_zero_sign_d;
reg sign_fasu_r;
wire [1:0] exp_ovf;
reg [1:0] exp_ovf_r;
// This is all we need from post-norm module for int-float conversion
reg opa_sign_r;
always @(posedge clk)
opa_sign_r <= opa_r[31];
always @(posedge clk)
sign_fasu_r <= opa_sign_r; //sign_fasu;
 
 
////////////////////////////////////////////////////////////////////////
//
// Normalize Result
//
wire ine_d;
wire inv_d;
wire sign_d;
reg sign;
reg [30:0] opa_r1;
reg [47:0] fract_i2f;
reg opas_r1, opas_r2;
wire f2i_out_sign;
wire [47:0] fract_denorm;
 
always @(posedge clk) // Exponent must be once cycle delayed
case(fpu_op_r2)
//4: exp_r <= 0;
5: exp_r <= opa_r1[30:23];
default: exp_r <= 0;
endcase
 
always @(posedge clk)
opa_r1 <= opa_r[30:0];
always @(posedge clk)
fract_i2f <= (fpu_op_r2==5) ?
(sign_d ? 1-{24'h00, (|opa_r1[30:23]), opa_r1[22:0]}-1 :
{24'h0, (|opa_r1[30:23]), opa_r1[22:0]})
: (sign_d ? 1 - {opa_r1, 17'h01} : {opa_r1, 17'h0});
 
assign fract_denorm = fract_i2f;
always @(posedge clk)
opas_r1 <= opa_r[31];
 
always @(posedge clk)
opas_r2 <= opas_r1;
 
assign sign_d = opa_sign_r; //sign_fasu;
 
always @(posedge clk)
sign <= (rmode_r2==2'h3) ? !sign_d : sign_d;
 
 
// Special case of largest negative integer we can convert to - usually
// gets picked up as invalid, but really it's not, so deal with it as a
// special case.
wire f2i_special_case_no_inv;
assign f2i_special_case_no_inv = (opa == 32'hcf000000);
 
or1200_fpu_post_norm_intfloat_conv u4
(
.clk(clk), // System Clock
.fpu_op(fpu_op_r3), // Floating Point Operation
.opas(opas_r2), // OPA Sign
.sign(sign), // Sign of the result
.rmode(rmode_r3), // Rounding mode
.fract_in(fract_denorm), // Fraction Input
 
.exp_in(exp_r), // Exponent Input
.opa_dn(opa_dn), // Operand A Denormalized
.opa_nan(opa_nan),
.opa_inf(opa_inf),
.opb_dn(), // Operand B Denormalized
.out(out_d), // Normalized output (un-registered)
.ine(ine_d), // Result Inexact output (un-registered)
.inv(inv_d), // Invalid input for f2i operation
.overflow(overflow_d), // Overflow output (un-registered)
.underflow(underflow_d),// Underflow output (un-registered)
.f2i_out_sign(f2i_out_sign) // F2I Output Sign
);
 
////////////////////////////////////////////////////////////////////////
//
// FPU Outputs
//
reg fasu_op_r1, fasu_op_r2;
wire [30:0] out_fixed;
wire output_zero_fasu;
wire overflow_fasu;
wire out_d_00;
wire ine_fasu;
wire underflow_fasu;
 
 
/*
always @(posedge clk)
fasu_op_r1 <= fasu_op;
 
always @(posedge clk)
fasu_op_r2 <= fasu_op_r1;
*/
// Force pre-set values for non numerical output
 
assign out_fixed = ( (qnan_d | snan_d) |
(ind_d /*& !fasu_op_r2*/)) ? QNAN : INF;
 
always @(posedge clk)
out[30:0] <= /*((inf_d & (fpu_op_r3!=3'b101)) | snan_d | qnan_d)
& fpu_op_r3!=3'b100 ? out_fixed :*/ out_d;
 
assign out_d_00 = !(|out_d);
 
 
always @(posedge clk)
out[31] <= (fpu_op_r3==3'b101) ?
f2i_out_sign : sign_fasu_r;
// Exception Outputs
assign ine_fasu = (ine_d | overflow_d | underflow_d) &
!(snan_d | qnan_d | inf_d);
 
always @(posedge clk)
ine <= fpu_op_r3[2] ? ine_d : ine_fasu;
 
assign overflow = overflow_d & !(snan_d | qnan_d | inf_d);
assign underflow = underflow_d & !(inf_d | snan_d | qnan_d);
 
always @(posedge clk)
snan <= snan_d & (fpu_op_r3==3'b101); // Only signal sNaN when ftoi
 
// Status Outputs
assign output_zero_fasu = out_d_00 & !(inf_d | snan_d | qnan_d);
 
always @(posedge clk)
zero <= fpu_op_r3==3'b101 ? out_d_00 & !(snan_d | qnan_d) :
output_zero_fasu ;
assign inv = inv_d & !f2i_special_case_no_inv;
endmodule // or1200_fpu_intfloat_conv
 
 
module or1200_fpu_intfloat_conv_except
(
clk, opa, opb, inf, ind, qnan, snan, opa_nan, opb_nan,
opa_00, opb_00, opa_inf, opb_inf, opa_dn, opb_dn
);
input clk;
input [31:0] opa, opb;
output inf, ind, qnan, snan, opa_nan, opb_nan;
output opa_00, opb_00;
output opa_inf, opb_inf;
output opa_dn;
output opb_dn;
 
////////////////////////////////////////////////////////////////////////
//
// Local Wires and registers
//
 
wire [7:0] expa, expb; // alias to opX exponent
wire [22:0] fracta, fractb; // alias to opX fraction
reg expa_ff, infa_f_r, qnan_r_a, snan_r_a;
reg expb_ff, infb_f_r, qnan_r_b, snan_r_b;
reg inf, ind, qnan, snan; // Output registers
reg opa_nan, opb_nan;
reg expa_00, expb_00, fracta_00, fractb_00;
reg opa_00, opb_00;
reg opa_inf, opb_inf;
reg opa_dn, opb_dn;
 
////////////////////////////////////////////////////////////////////////
//
// Aliases
//
 
assign expa = opa[30:23];
assign expb = opb[30:23];
assign fracta = opa[22:0];
assign fractb = opb[22:0];
 
////////////////////////////////////////////////////////////////////////
//
// Determine if any of the input operators is a INF or NAN or any other
// special number
//
 
always @(posedge clk)
expa_ff <= &expa;
 
always @(posedge clk)
expb_ff <= &expb;
always @(posedge clk)
infa_f_r <= !(|fracta);
 
always @(posedge clk)
infb_f_r <= !(|fractb);
 
always @(posedge clk)
qnan_r_a <= fracta[22];
 
always @(posedge clk)
snan_r_a <= !fracta[22] & |fracta[21:0];
always @(posedge clk)
qnan_r_b <= fractb[22];
 
always @(posedge clk)
snan_r_b <= !fractb[22]; // & |fractb[21:0];
 
always @(posedge clk)
ind <= (expa_ff & infa_f_r); // & (expb_ff & infb_f_r);
 
always @(posedge clk)
inf <= (expa_ff & infa_f_r); // | (expb_ff & infb_f_r);
 
always @(posedge clk)
qnan <= (expa_ff & qnan_r_a); // | (expb_ff & qnan_r_b);
 
always @(posedge clk)
snan <= (expa_ff & snan_r_a); // | (expb_ff & snan_r_b);
 
always @(posedge clk)
opa_nan <= &expa & (|fracta[22:0]);
 
always @(posedge clk)
opb_nan <= &expb & (|fractb[22:0]);
 
always @(posedge clk)
opa_inf <= (expa_ff & infa_f_r);
 
always @(posedge clk)
opb_inf <= (expb_ff & infb_f_r);
 
always @(posedge clk)
expa_00 <= !(|expa);
 
always @(posedge clk)
expb_00 <= !(|expb);
 
always @(posedge clk)
fracta_00 <= !(|fracta);
 
always @(posedge clk)
fractb_00 <= !(|fractb);
 
always @(posedge clk)
opa_00 <= expa_00 & fracta_00;
 
always @(posedge clk)
opb_00 <= expb_00 & fractb_00;
 
always @(posedge clk)
opa_dn <= expa_00;
 
always @(posedge clk)
opb_dn <= expb_00;
 
endmodule // or1200_fpu_intfloat_conv_except
 
 
/verilog/or1200_iwb_biu.v
3,7 → 3,7
//// OR1200's WISHBONE BIU ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Implements WISHBONE interface ////
46,68 → 46,11
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_iwb_biu.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// Major update:
// This module is obsolete.
//
// Revision 1.2 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.1 2003/12/05 00:12:08 lampret
// New wb_biu for iwb interface.
//
// Revision 1.6.4.1 2003/07/08 15:36:37 lampret
// Added embedded memory QMEM.
//
// Revision 1.6 2003/04/07 20:57:46 lampret
// Fixed OR1200_CLKDIV_x_SUPPORTED defines. Fixed order of ifdefs.
//
// Revision 1.5 2002/12/08 08:57:56 lampret
// Added optional support for WB B3 specification (xwb_cti_o, xwb_bte_o). Made xwb_cab_o optional.
//
// Revision 1.4 2002/09/16 03:09:16 lampret
// Fixed a combinational loop.
//
// Revision 1.3 2002/08/12 05:31:37 lampret
// Added optional retry counter for wb_rty_i. Added graceful termination for aborted transfers.
//
// Revision 1.2 2002/07/14 22:17:17 lampret
// Added simple trace buffer [only for Xilinx Virtex target]. Fixed instruction fetch abort when new exception is recognized.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.12 2001/11/22 13:42:51 lampret
// Added wb_cyc_o assignment after it was removed by accident.
//
// Revision 1.11 2001/11/20 21:28:10 lampret
// Added optional sampling of inputs.
//
// Revision 1.10 2001/11/18 11:32:00 lampret
// OR1200_REGISTERED_OUTPUTS can now be enabled.
//
// Revision 1.9 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.8 2001/10/14 13:12:10 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:35 igorm
// no message
//
// Revision 1.3 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.2 2001/07/22 03:31:54 lampret
// Fixed RAM's oen bug. Cache bypass under development.
//
// Revision 1.1 2001/07/20 00:46:23 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
/verilog/or1200_freeze.v
3,7 → 3,7
//// OR1200's Freeze logic ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://www.opencores.org/project,or1k ////
//// ////
//// Description ////
//// Generates all freezes and stalls inside RISC ////
41,65 → 41,11
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_freeze.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// Minor update:
// Bugs fixed.
//
// Revision 1.8 2004/06/08 18:17:36 lampret
// Non-functional changes. Coding style fixes.
//
// Revision 1.7 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.6.4.2 2003/12/05 00:09:49 lampret
// No functional change.
//
// Revision 1.6.4.1 2003/07/08 15:36:37 lampret
// Added embedded memory QMEM.
//
// Revision 1.6 2002/07/31 02:04:35 lampret
// MAC now follows software convention (signed multiply instead of unsigned).
//
// Revision 1.5 2002/07/14 22:17:17 lampret
// Added simple trace buffer [only for Xilinx Virtex target]. Fixed instruction fetch abort when new exception is recognized.
//
// Revision 1.4 2002/03/29 15:16:55 lampret
// Some of the warnings fixed.
//
// Revision 1.3 2002/01/28 01:16:00 lampret
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
//
// Revision 1.2 2002/01/14 06:18:22 lampret
// Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.10 2001/11/13 10:02:21 lampret
// Added 'setpc'. Renamed some signals (except_flushpipe into flushpipe etc)
//
// Revision 1.9 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.8 2001/10/19 23:28:46 lampret
// Fixed some synthesis warnings. Configured with caches and MMUs.
//
// Revision 1.7 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:36 igorm
// no message
//
// Revision 1.2 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.1 2001/07/20 00:46:03 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
115,18 → 61,20
//
// Freeze logic (stalls CPU pipeline, ifetcher etc.)
//
module or1200_freeze(
// Clock and reset
clk, rst,
module or1200_freeze
(
// Clock and reset
clk, rst,
// Internal i/f
multicycle, wait_on, flushpipe, extend_flush, lsu_stall, if_stall,
lsu_unstall, du_stall, mac_stall,
force_dslot_fetch, abort_ex,
genpc_freeze, if_freeze, id_freeze, ex_freeze, wb_freeze, saving_if_insn,
fpu_done, mtspr_done,
icpu_ack_i, icpu_err_i
);
 
// Internal i/f
multicycle, flushpipe, extend_flush, lsu_stall, if_stall,
lsu_unstall, du_stall, mac_stall,
force_dslot_fetch, abort_ex,
genpc_freeze, if_freeze, id_freeze, ex_freeze, wb_freeze, saving_if_insn,
icpu_ack_i, icpu_err_i
);
 
//
// I/O
//
133,6 → 81,7
input clk;
input rst;
input [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;
input [`OR1200_WAIT_ON_WIDTH-1:0] wait_on;
input flushpipe;
input extend_flush;
input lsu_stall;
147,7 → 96,9
output id_freeze;
output ex_freeze;
output wb_freeze;
input saving_if_insn;
input saving_if_insn;
input fpu_done;
input mtspr_done;
input icpu_ack_i;
input icpu_err_i;
 
157,41 → 108,45
wire multicycle_freeze;
reg [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle_cnt;
reg flushpipe_r;
 
reg [`OR1200_WAIT_ON_WIDTH-1:0] waiting_on;
//
// Pipeline freeze
//
// Rules how to create freeze signals:
// 1. Not overwriting pipeline stages:
// Freze signals at the beginning of pipeline (such as if_freeze) can be asserted more
// often than freeze signals at the of pipeline (such as wb_freeze). In other words, wb_freeze must never
// be asserted when ex_freeze is not. ex_freeze must never be asserted when id_freeze is not etc.
// Freeze signals at the beginning of pipeline (such as if_freeze) can be
// asserted more often than freeze signals at the of pipeline (such as
// wb_freeze). In other words, wb_freeze must never be asserted when ex_freeze
// is not. ex_freeze must never be asserted when id_freeze is not etc.
//
// 2. Inserting NOPs in the middle of pipeline only if supported:
// At this time, only ex_freeze (and wb_freeze) can be deassrted when id_freeze (and if_freeze) are asserted.
// At this time, only ex_freeze (and wb_freeze) can be deassrted when id_freeze
// (and if_freeze) are asserted.
// This way NOP is asserted from stage ID into EX stage.
//
//assign genpc_freeze = du_stall | flushpipe_r | lsu_stall;
//assign genpc_freeze = du_stall | flushpipe_r;
 
assign genpc_freeze = (du_stall & !saving_if_insn) | flushpipe_r;
assign if_freeze = id_freeze | extend_flush;
//assign id_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze | force_dslot_fetch) & ~flushpipe | du_stall;
assign id_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze | force_dslot_fetch) | du_stall | mac_stall;
 
assign id_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze
| (|waiting_on) | force_dslot_fetch) | du_stall | mac_stall;
assign ex_freeze = wb_freeze;
//assign wb_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze) & ~flushpipe | du_stall | mac_stall;
assign wb_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze) | du_stall | mac_stall | abort_ex;
 
assign wb_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze
| (|waiting_on)) | du_stall | mac_stall | abort_ex;
 
//
// registered flushpipe
//
always @(posedge clk or posedge rst)
if (rst)
flushpipe_r <= #1 1'b0;
flushpipe_r <= 1'b0;
else if (icpu_ack_i | icpu_err_i)
// else if (!if_stall)
flushpipe_r <= #1 flushpipe;
flushpipe_r <= flushpipe;
else if (!flushpipe)
flushpipe_r <= #1 1'b0;
flushpipe_r <= 1'b0;
//
// Multicycle freeze
203,10 → 158,25
//
always @(posedge clk or posedge rst)
if (rst)
multicycle_cnt <= #1 2'b00;
multicycle_cnt <= 2'b00;
else if (|multicycle_cnt)
multicycle_cnt <= #1 multicycle_cnt - 2'd1;
multicycle_cnt <= multicycle_cnt - 2'd1;
else if (|multicycle & !ex_freeze)
multicycle_cnt <= #1 multicycle;
multicycle_cnt <= multicycle;
 
 
//
// Waiting on generation
//
always @(posedge clk or posedge rst)
if (rst)
waiting_on <= 0;
else if ((waiting_on == `OR1200_WAIT_ON_FPU) & fpu_done)
waiting_on <= 0;
else if ((waiting_on == `OR1200_WAIT_ON_MTSPR) & mtspr_done)
waiting_on <= 0;
else if (!ex_freeze)
waiting_on <= wait_on;
endmodule
/verilog/or1200_alu.v
192,7 → 192,7
end
end
`ifdef OR1200_MULT_IMPLEMENTED
`ifdef OR1200_IMPL_DIV
`ifdef OR1200_DIV_IMPLEMENTED
`OR1200_ALUOP_DIV,
`OR1200_ALUOP_DIVU,
`endif
/verilog/or1200_cfgr.v
52,158 → 52,159
`include "or1200_defines.v"
 
module or1200_cfgr(
// RISC Internal Interface
spr_addr, spr_dat_o
);
// RISC Internal Interface
spr_addr, spr_dat_o
);
 
//
// RISC Internal Interface
//
input [31:0] spr_addr; // SPR Address
output [31:0] spr_dat_o; // SPR Read Data
//
// RISC Internal Interface
//
input [31:0] spr_addr; // SPR Address
output [31:0] spr_dat_o; // SPR Read Data
 
//
// Internal wires & registers
//
reg [31:0] spr_dat_o; // SPR Read Data
//
// Internal wires & registers
//
reg [31:0] spr_dat_o; // SPR Read Data
 
`ifdef OR1200_CFGR_IMPLEMENTED
 
//
// Implementation of VR, UPR and configuration registers
//
always @(spr_addr)
`ifdef OR1200_SYS_FULL_DECODE
if (~|spr_addr[31:4])
`endif
case(spr_addr[3:0]) // synopsys parallel_case
`OR1200_SPRGRP_SYS_VR: begin
spr_dat_o[`OR1200_VR_REV_BITS] = `OR1200_VR_REV;
spr_dat_o[`OR1200_VR_RES1_BITS] = `OR1200_VR_RES1;
spr_dat_o[`OR1200_VR_CFG_BITS] = `OR1200_VR_CFG;
spr_dat_o[`OR1200_VR_VER_BITS] = `OR1200_VR_VER;
end
`OR1200_SPRGRP_SYS_UPR: begin
spr_dat_o[`OR1200_UPR_UP_BITS] = `OR1200_UPR_UP;
spr_dat_o[`OR1200_UPR_DCP_BITS] = `OR1200_UPR_DCP;
spr_dat_o[`OR1200_UPR_ICP_BITS] = `OR1200_UPR_ICP;
spr_dat_o[`OR1200_UPR_DMP_BITS] = `OR1200_UPR_DMP;
spr_dat_o[`OR1200_UPR_IMP_BITS] = `OR1200_UPR_IMP;
spr_dat_o[`OR1200_UPR_MP_BITS] = `OR1200_UPR_MP;
spr_dat_o[`OR1200_UPR_DUP_BITS] = `OR1200_UPR_DUP;
spr_dat_o[`OR1200_UPR_PCUP_BITS] = `OR1200_UPR_PCUP;
spr_dat_o[`OR1200_UPR_PMP_BITS] = `OR1200_UPR_PMP;
spr_dat_o[`OR1200_UPR_PICP_BITS] = `OR1200_UPR_PICP;
spr_dat_o[`OR1200_UPR_TTP_BITS] = `OR1200_UPR_TTP;
spr_dat_o[`OR1200_UPR_RES1_BITS] = `OR1200_UPR_RES1;
spr_dat_o[`OR1200_UPR_CUP_BITS] = `OR1200_UPR_CUP;
end
`OR1200_SPRGRP_SYS_CPUCFGR: begin
spr_dat_o[`OR1200_CPUCFGR_NSGF_BITS] = `OR1200_CPUCFGR_NSGF;
spr_dat_o[`OR1200_CPUCFGR_HGF_BITS] = `OR1200_CPUCFGR_HGF;
spr_dat_o[`OR1200_CPUCFGR_OB32S_BITS] = `OR1200_CPUCFGR_OB32S;
spr_dat_o[`OR1200_CPUCFGR_OB64S_BITS] = `OR1200_CPUCFGR_OB64S;
spr_dat_o[`OR1200_CPUCFGR_OF32S_BITS] = `OR1200_CPUCFGR_OF32S;
spr_dat_o[`OR1200_CPUCFGR_OF64S_BITS] = `OR1200_CPUCFGR_OF64S;
spr_dat_o[`OR1200_CPUCFGR_OV64S_BITS] = `OR1200_CPUCFGR_OV64S;
spr_dat_o[`OR1200_CPUCFGR_RES1_BITS] = `OR1200_CPUCFGR_RES1;
end
`OR1200_SPRGRP_SYS_DMMUCFGR: begin
spr_dat_o[`OR1200_DMMUCFGR_NTW_BITS] = `OR1200_DMMUCFGR_NTW;
spr_dat_o[`OR1200_DMMUCFGR_NTS_BITS] = `OR1200_DMMUCFGR_NTS;
spr_dat_o[`OR1200_DMMUCFGR_NAE_BITS] = `OR1200_DMMUCFGR_NAE;
spr_dat_o[`OR1200_DMMUCFGR_CRI_BITS] = `OR1200_DMMUCFGR_CRI;
spr_dat_o[`OR1200_DMMUCFGR_PRI_BITS] = `OR1200_DMMUCFGR_PRI;
spr_dat_o[`OR1200_DMMUCFGR_TEIRI_BITS] = `OR1200_DMMUCFGR_TEIRI;
spr_dat_o[`OR1200_DMMUCFGR_HTR_BITS] = `OR1200_DMMUCFGR_HTR;
spr_dat_o[`OR1200_DMMUCFGR_RES1_BITS] = `OR1200_DMMUCFGR_RES1;
end
`OR1200_SPRGRP_SYS_IMMUCFGR: begin
spr_dat_o[`OR1200_IMMUCFGR_NTW_BITS] = `OR1200_IMMUCFGR_NTW;
spr_dat_o[`OR1200_IMMUCFGR_NTS_BITS] = `OR1200_IMMUCFGR_NTS;
spr_dat_o[`OR1200_IMMUCFGR_NAE_BITS] = `OR1200_IMMUCFGR_NAE;
spr_dat_o[`OR1200_IMMUCFGR_CRI_BITS] = `OR1200_IMMUCFGR_CRI;
spr_dat_o[`OR1200_IMMUCFGR_PRI_BITS] = `OR1200_IMMUCFGR_PRI;
spr_dat_o[`OR1200_IMMUCFGR_TEIRI_BITS] = `OR1200_IMMUCFGR_TEIRI;
spr_dat_o[`OR1200_IMMUCFGR_HTR_BITS] = `OR1200_IMMUCFGR_HTR;
spr_dat_o[`OR1200_IMMUCFGR_RES1_BITS] = `OR1200_IMMUCFGR_RES1;
end
`OR1200_SPRGRP_SYS_DCCFGR: begin
spr_dat_o[`OR1200_DCCFGR_NCW_BITS] = `OR1200_DCCFGR_NCW;
spr_dat_o[`OR1200_DCCFGR_NCS_BITS] = `OR1200_DCCFGR_NCS;
spr_dat_o[`OR1200_DCCFGR_CBS_BITS] = `OR1200_DCCFGR_CBS;
spr_dat_o[`OR1200_DCCFGR_CWS_BITS] = `OR1200_DCCFGR_CWS;
spr_dat_o[`OR1200_DCCFGR_CCRI_BITS] = `OR1200_DCCFGR_CCRI;
spr_dat_o[`OR1200_DCCFGR_CBIRI_BITS] = `OR1200_DCCFGR_CBIRI;
spr_dat_o[`OR1200_DCCFGR_CBPRI_BITS] = `OR1200_DCCFGR_CBPRI;
spr_dat_o[`OR1200_DCCFGR_CBLRI_BITS] = `OR1200_DCCFGR_CBLRI;
spr_dat_o[`OR1200_DCCFGR_CBFRI_BITS] = `OR1200_DCCFGR_CBFRI;
spr_dat_o[`OR1200_DCCFGR_CBWBRI_BITS] = `OR1200_DCCFGR_CBWBRI;
spr_dat_o[`OR1200_DCCFGR_RES1_BITS] = `OR1200_DCCFGR_RES1;
end
`OR1200_SPRGRP_SYS_ICCFGR: begin
spr_dat_o[`OR1200_ICCFGR_NCW_BITS] = `OR1200_ICCFGR_NCW;
spr_dat_o[`OR1200_ICCFGR_NCS_BITS] = `OR1200_ICCFGR_NCS;
spr_dat_o[`OR1200_ICCFGR_CBS_BITS] = `OR1200_ICCFGR_CBS;
spr_dat_o[`OR1200_ICCFGR_CWS_BITS] = `OR1200_ICCFGR_CWS;
spr_dat_o[`OR1200_ICCFGR_CCRI_BITS] = `OR1200_ICCFGR_CCRI;
spr_dat_o[`OR1200_ICCFGR_CBIRI_BITS] = `OR1200_ICCFGR_CBIRI;
spr_dat_o[`OR1200_ICCFGR_CBPRI_BITS] = `OR1200_ICCFGR_CBPRI;
spr_dat_o[`OR1200_ICCFGR_CBLRI_BITS] = `OR1200_ICCFGR_CBLRI;
spr_dat_o[`OR1200_ICCFGR_CBFRI_BITS] = `OR1200_ICCFGR_CBFRI;
spr_dat_o[`OR1200_ICCFGR_CBWBRI_BITS] = `OR1200_ICCFGR_CBWBRI;
spr_dat_o[`OR1200_ICCFGR_RES1_BITS] = `OR1200_ICCFGR_RES1;
end
`OR1200_SPRGRP_SYS_DCFGR: begin
spr_dat_o[`OR1200_DCFGR_NDP_BITS] = `OR1200_DCFGR_NDP;
spr_dat_o[`OR1200_DCFGR_WPCI_BITS] = `OR1200_DCFGR_WPCI;
spr_dat_o[`OR1200_DCFGR_RES1_BITS] = `OR1200_DCFGR_RES1;
end
default: spr_dat_o = 32'h0000_0000;
endcase
`ifdef OR1200_SYS_FULL_DECODE
else
spr_dat_o = 32'h0000_0000;
`endif
//
// Implementation of VR, UPR and configuration registers
//
always @(spr_addr)
`ifdef OR1200_SYS_FULL_DECODE
if (~|spr_addr[31:4])
`endif
case(spr_addr[3:0]) // synopsys parallel_case
`OR1200_SPRGRP_SYS_VR: begin
spr_dat_o[`OR1200_VR_REV_BITS] = `OR1200_VR_REV;
spr_dat_o[`OR1200_VR_RES1_BITS] = `OR1200_VR_RES1;
spr_dat_o[`OR1200_VR_CFG_BITS] = `OR1200_VR_CFG;
spr_dat_o[`OR1200_VR_VER_BITS] = `OR1200_VR_VER;
end
`OR1200_SPRGRP_SYS_UPR: begin
spr_dat_o[`OR1200_UPR_UP_BITS] = `OR1200_UPR_UP;
spr_dat_o[`OR1200_UPR_DCP_BITS] = `OR1200_UPR_DCP;
spr_dat_o[`OR1200_UPR_ICP_BITS] = `OR1200_UPR_ICP;
spr_dat_o[`OR1200_UPR_DMP_BITS] = `OR1200_UPR_DMP;
spr_dat_o[`OR1200_UPR_IMP_BITS] = `OR1200_UPR_IMP;
spr_dat_o[`OR1200_UPR_MP_BITS] = `OR1200_UPR_MP;
spr_dat_o[`OR1200_UPR_DUP_BITS] = `OR1200_UPR_DUP;
spr_dat_o[`OR1200_UPR_PCUP_BITS] = `OR1200_UPR_PCUP;
spr_dat_o[`OR1200_UPR_PMP_BITS] = `OR1200_UPR_PMP;
spr_dat_o[`OR1200_UPR_PICP_BITS] = `OR1200_UPR_PICP;
spr_dat_o[`OR1200_UPR_TTP_BITS] = `OR1200_UPR_TTP;
spr_dat_o[`OR1200_UPR_FPP_BITS] = `OR1200_UPR_FPP;
spr_dat_o[`OR1200_UPR_RES1_BITS] = `OR1200_UPR_RES1;
spr_dat_o[`OR1200_UPR_CUP_BITS] = `OR1200_UPR_CUP;
end
`OR1200_SPRGRP_SYS_CPUCFGR: begin
spr_dat_o[`OR1200_CPUCFGR_NSGF_BITS] = `OR1200_CPUCFGR_NSGF;
spr_dat_o[`OR1200_CPUCFGR_HGF_BITS] = `OR1200_CPUCFGR_HGF;
spr_dat_o[`OR1200_CPUCFGR_OB32S_BITS] = `OR1200_CPUCFGR_OB32S;
spr_dat_o[`OR1200_CPUCFGR_OB64S_BITS] = `OR1200_CPUCFGR_OB64S;
spr_dat_o[`OR1200_CPUCFGR_OF32S_BITS] = `OR1200_CPUCFGR_OF32S;
spr_dat_o[`OR1200_CPUCFGR_OF64S_BITS] = `OR1200_CPUCFGR_OF64S;
spr_dat_o[`OR1200_CPUCFGR_OV64S_BITS] = `OR1200_CPUCFGR_OV64S;
spr_dat_o[`OR1200_CPUCFGR_RES1_BITS] = `OR1200_CPUCFGR_RES1;
end
`OR1200_SPRGRP_SYS_DMMUCFGR: begin
spr_dat_o[`OR1200_DMMUCFGR_NTW_BITS] = `OR1200_DMMUCFGR_NTW;
spr_dat_o[`OR1200_DMMUCFGR_NTS_BITS] = `OR1200_DMMUCFGR_NTS;
spr_dat_o[`OR1200_DMMUCFGR_NAE_BITS] = `OR1200_DMMUCFGR_NAE;
spr_dat_o[`OR1200_DMMUCFGR_CRI_BITS] = `OR1200_DMMUCFGR_CRI;
spr_dat_o[`OR1200_DMMUCFGR_PRI_BITS] = `OR1200_DMMUCFGR_PRI;
spr_dat_o[`OR1200_DMMUCFGR_TEIRI_BITS] = `OR1200_DMMUCFGR_TEIRI;
spr_dat_o[`OR1200_DMMUCFGR_HTR_BITS] = `OR1200_DMMUCFGR_HTR;
spr_dat_o[`OR1200_DMMUCFGR_RES1_BITS] = `OR1200_DMMUCFGR_RES1;
end
`OR1200_SPRGRP_SYS_IMMUCFGR: begin
spr_dat_o[`OR1200_IMMUCFGR_NTW_BITS] = `OR1200_IMMUCFGR_NTW;
spr_dat_o[`OR1200_IMMUCFGR_NTS_BITS] = `OR1200_IMMUCFGR_NTS;
spr_dat_o[`OR1200_IMMUCFGR_NAE_BITS] = `OR1200_IMMUCFGR_NAE;
spr_dat_o[`OR1200_IMMUCFGR_CRI_BITS] = `OR1200_IMMUCFGR_CRI;
spr_dat_o[`OR1200_IMMUCFGR_PRI_BITS] = `OR1200_IMMUCFGR_PRI;
spr_dat_o[`OR1200_IMMUCFGR_TEIRI_BITS] = `OR1200_IMMUCFGR_TEIRI;
spr_dat_o[`OR1200_IMMUCFGR_HTR_BITS] = `OR1200_IMMUCFGR_HTR;
spr_dat_o[`OR1200_IMMUCFGR_RES1_BITS] = `OR1200_IMMUCFGR_RES1;
end
`OR1200_SPRGRP_SYS_DCCFGR: begin
spr_dat_o[`OR1200_DCCFGR_NCW_BITS] = `OR1200_DCCFGR_NCW;
spr_dat_o[`OR1200_DCCFGR_NCS_BITS] = `OR1200_DCCFGR_NCS;
spr_dat_o[`OR1200_DCCFGR_CBS_BITS] = `OR1200_DCCFGR_CBS;
spr_dat_o[`OR1200_DCCFGR_CWS_BITS] = `OR1200_DCCFGR_CWS;
spr_dat_o[`OR1200_DCCFGR_CCRI_BITS] = `OR1200_DCCFGR_CCRI;
spr_dat_o[`OR1200_DCCFGR_CBIRI_BITS] = `OR1200_DCCFGR_CBIRI;
spr_dat_o[`OR1200_DCCFGR_CBPRI_BITS] = `OR1200_DCCFGR_CBPRI;
spr_dat_o[`OR1200_DCCFGR_CBLRI_BITS] = `OR1200_DCCFGR_CBLRI;
spr_dat_o[`OR1200_DCCFGR_CBFRI_BITS] = `OR1200_DCCFGR_CBFRI;
spr_dat_o[`OR1200_DCCFGR_CBWBRI_BITS] = `OR1200_DCCFGR_CBWBRI;
spr_dat_o[`OR1200_DCCFGR_RES1_BITS] = `OR1200_DCCFGR_RES1;
end
`OR1200_SPRGRP_SYS_ICCFGR: begin
spr_dat_o[`OR1200_ICCFGR_NCW_BITS] = `OR1200_ICCFGR_NCW;
spr_dat_o[`OR1200_ICCFGR_NCS_BITS] = `OR1200_ICCFGR_NCS;
spr_dat_o[`OR1200_ICCFGR_CBS_BITS] = `OR1200_ICCFGR_CBS;
spr_dat_o[`OR1200_ICCFGR_CWS_BITS] = `OR1200_ICCFGR_CWS;
spr_dat_o[`OR1200_ICCFGR_CCRI_BITS] = `OR1200_ICCFGR_CCRI;
spr_dat_o[`OR1200_ICCFGR_CBIRI_BITS] = `OR1200_ICCFGR_CBIRI;
spr_dat_o[`OR1200_ICCFGR_CBPRI_BITS] = `OR1200_ICCFGR_CBPRI;
spr_dat_o[`OR1200_ICCFGR_CBLRI_BITS] = `OR1200_ICCFGR_CBLRI;
spr_dat_o[`OR1200_ICCFGR_CBFRI_BITS] = `OR1200_ICCFGR_CBFRI;
spr_dat_o[`OR1200_ICCFGR_CBWBRI_BITS] = `OR1200_ICCFGR_CBWBRI;
spr_dat_o[`OR1200_ICCFGR_RES1_BITS] = `OR1200_ICCFGR_RES1;
end
`OR1200_SPRGRP_SYS_DCFGR: begin
spr_dat_o[`OR1200_DCFGR_NDP_BITS] = `OR1200_DCFGR_NDP;
spr_dat_o[`OR1200_DCFGR_WPCI_BITS] = `OR1200_DCFGR_WPCI;
spr_dat_o[`OR1200_DCFGR_RES1_BITS] = `OR1200_DCFGR_RES1;
end
default: spr_dat_o = 32'h0000_0000;
endcase
`ifdef OR1200_SYS_FULL_DECODE
else
spr_dat_o = 32'h0000_0000;
`endif
 
`else
 
//
// When configuration registers are not implemented, only
// implement VR and UPR
//
always @(spr_addr)
`ifdef OR1200_SYS_FULL_DECODE
if (spr_addr[31:4] == 28'h0)
`endif
case(spr_addr[3:0])
`OR1200_SPRGRP_SYS_VR: begin
spr_dat_o[`OR1200_VR_REV_BITS] = `OR1200_VR_REV;
spr_dat_o[`OR1200_VR_RES1_BITS] = `OR1200_VR_RES1;
spr_dat_o[`OR1200_VR_CFG_BITS] = `OR1200_VR_CFG;
spr_dat_o[`OR1200_VR_VER_BITS] = `OR1200_VR_VER;
end
`OR1200_SPRGRP_SYS_UPR: begin
spr_dat_o[`OR1200_UPR_UP_BITS] = `OR1200_UPR_UP;
spr_dat_o[`OR1200_UPR_DCP_BITS] = `OR1200_UPR_DCP;
spr_dat_o[`OR1200_UPR_ICP_BITS] = `OR1200_UPR_ICP;
spr_dat_o[`OR1200_UPR_DMP_BITS] = `OR1200_UPR_DMP;
spr_dat_o[`OR1200_UPR_IMP_BITS] = `OR1200_UPR_IMP;
spr_dat_o[`OR1200_UPR_MP_BITS] = `OR1200_UPR_MP;
spr_dat_o[`OR1200_UPR_DUP_BITS] = `OR1200_UPR_DUP;
spr_dat_o[`OR1200_UPR_PCUP_BITS] = `OR1200_UPR_PCUP;
spr_dat_o[`OR1200_UPR_PMP_BITS] = `OR1200_UPR_PMP;
spr_dat_o[`OR1200_UPR_PICP_BITS] = `OR1200_UPR_PICP;
spr_dat_o[`OR1200_UPR_TTP_BITS] = `OR1200_UPR_TTP;
spr_dat_o[`OR1200_UPR_RES1_BITS] = `OR1200_UPR_RES1;
spr_dat_o[`OR1200_UPR_CUP_BITS] = `OR1200_UPR_CUP;
end
default: spr_dat_o = 32'h0000_0000;
endcase
`ifdef OR1200_SYS_FULL_DECODE
else
spr_dat_o = 32'h0000_0000;
`endif
//
// When configuration registers are not implemented, only
// implement VR and UPR
//
always @(spr_addr)
`ifdef OR1200_SYS_FULL_DECODE
if (spr_addr[31:4] == 28'h0)
`endif
case(spr_addr[3:0])
`OR1200_SPRGRP_SYS_VR: begin
spr_dat_o[`OR1200_VR_REV_BITS] = `OR1200_VR_REV;
spr_dat_o[`OR1200_VR_RES1_BITS] = `OR1200_VR_RES1;
spr_dat_o[`OR1200_VR_CFG_BITS] = `OR1200_VR_CFG;
spr_dat_o[`OR1200_VR_VER_BITS] = `OR1200_VR_VER;
end
`OR1200_SPRGRP_SYS_UPR: begin
spr_dat_o[`OR1200_UPR_UP_BITS] = `OR1200_UPR_UP;
spr_dat_o[`OR1200_UPR_DCP_BITS] = `OR1200_UPR_DCP;
spr_dat_o[`OR1200_UPR_ICP_BITS] = `OR1200_UPR_ICP;
spr_dat_o[`OR1200_UPR_DMP_BITS] = `OR1200_UPR_DMP;
spr_dat_o[`OR1200_UPR_IMP_BITS] = `OR1200_UPR_IMP;
spr_dat_o[`OR1200_UPR_MP_BITS] = `OR1200_UPR_MP;
spr_dat_o[`OR1200_UPR_DUP_BITS] = `OR1200_UPR_DUP;
spr_dat_o[`OR1200_UPR_PCUP_BITS] = `OR1200_UPR_PCUP;
spr_dat_o[`OR1200_UPR_PMP_BITS] = `OR1200_UPR_PMP;
spr_dat_o[`OR1200_UPR_PICP_BITS] = `OR1200_UPR_PICP;
spr_dat_o[`OR1200_UPR_TTP_BITS] = `OR1200_UPR_TTP;
spr_dat_o[`OR1200_UPR_RES1_BITS] = `OR1200_UPR_RES1;
spr_dat_o[`OR1200_UPR_CUP_BITS] = `OR1200_UPR_CUP;
end
default: spr_dat_o = 32'h0000_0000;
endcase
`ifdef OR1200_SYS_FULL_DECODE
else
spr_dat_o = 32'h0000_0000;
`endif
 
`endif
 
/verilog/or1200_qmem_top.v
321,98 → 321,98
//
always @(posedge rst or posedge clk)
if (rst) begin
state <= #1 `OR1200_QMEMFSM_IDLE;
qmem_dack <= #1 1'b0;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_IDLE;
qmem_dack <= 1'b0;
qmem_iack <= 1'b0;
end
else case (state) // synopsys parallel_case
`OR1200_QMEMFSM_IDLE: begin
if (qmemdmmu_cycstb_i & daddr_qmem_hit & qmemdcpu_we_i & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_STORE;
qmem_dack <= #1 1'b1;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_STORE;
qmem_dack <= 1'b1;
qmem_iack <= 1'b0;
end
else if (qmemdmmu_cycstb_i & daddr_qmem_hit & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_LOAD;
qmem_dack <= #1 1'b1;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_LOAD;
qmem_dack <= 1'b1;
qmem_iack <= 1'b0;
end
else if (qmemimmu_cycstb_i & iaddr_qmem_hit & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_FETCH;
qmem_iack <= #1 1'b1;
qmem_dack <= #1 1'b0;
state <= `OR1200_QMEMFSM_FETCH;
qmem_iack <= 1'b1;
qmem_dack <= 1'b0;
end
end
`OR1200_QMEMFSM_STORE: begin
if (qmemdmmu_cycstb_i & daddr_qmem_hit & qmemdcpu_we_i & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_STORE;
qmem_dack <= #1 1'b1;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_STORE;
qmem_dack <= 1'b1;
qmem_iack <= 1'b0;
end
else if (qmemdmmu_cycstb_i & daddr_qmem_hit & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_LOAD;
qmem_dack <= #1 1'b1;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_LOAD;
qmem_dack <= 1'b1;
qmem_iack <= 1'b0;
end
else if (qmemimmu_cycstb_i & iaddr_qmem_hit & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_FETCH;
qmem_iack <= #1 1'b1;
qmem_dack <= #1 1'b0;
state <= `OR1200_QMEMFSM_FETCH;
qmem_iack <= 1'b1;
qmem_dack <= 1'b0;
end
else begin
state <= #1 `OR1200_QMEMFSM_IDLE;
qmem_dack <= #1 1'b0;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_IDLE;
qmem_dack <= 1'b0;
qmem_iack <= 1'b0;
end
end
`OR1200_QMEMFSM_LOAD: begin
if (qmemdmmu_cycstb_i & daddr_qmem_hit & qmemdcpu_we_i & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_STORE;
qmem_dack <= #1 1'b1;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_STORE;
qmem_dack <= 1'b1;
qmem_iack <= 1'b0;
end
else if (qmemdmmu_cycstb_i & daddr_qmem_hit & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_LOAD;
qmem_dack <= #1 1'b1;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_LOAD;
qmem_dack <= 1'b1;
qmem_iack <= 1'b0;
end
else if (qmemimmu_cycstb_i & iaddr_qmem_hit & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_FETCH;
qmem_iack <= #1 1'b1;
qmem_dack <= #1 1'b0;
state <= `OR1200_QMEMFSM_FETCH;
qmem_iack <= 1'b1;
qmem_dack <= 1'b0;
end
else begin
state <= #1 `OR1200_QMEMFSM_IDLE;
qmem_dack <= #1 1'b0;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_IDLE;
qmem_dack <= 1'b0;
qmem_iack <= 1'b0;
end
end
`OR1200_QMEMFSM_FETCH: begin
if (qmemdmmu_cycstb_i & daddr_qmem_hit & qmemdcpu_we_i & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_STORE;
qmem_dack <= #1 1'b1;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_STORE;
qmem_dack <= 1'b1;
qmem_iack <= 1'b0;
end
else if (qmemdmmu_cycstb_i & daddr_qmem_hit & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_LOAD;
qmem_dack <= #1 1'b1;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_LOAD;
qmem_dack <= 1'b1;
qmem_iack <= 1'b0;
end
else if (qmemimmu_cycstb_i & iaddr_qmem_hit & qmem_ack) begin
state <= #1 `OR1200_QMEMFSM_FETCH;
qmem_iack <= #1 1'b1;
qmem_dack <= #1 1'b0;
state <= `OR1200_QMEMFSM_FETCH;
qmem_iack <= 1'b1;
qmem_dack <= 1'b0;
end
else begin
state <= #1 `OR1200_QMEMFSM_IDLE;
qmem_dack <= #1 1'b0;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_IDLE;
qmem_dack <= 1'b0;
qmem_iack <= 1'b0;
end
end
default: begin
state <= #1 `OR1200_QMEMFSM_IDLE;
qmem_dack <= #1 1'b0;
qmem_iack <= #1 1'b0;
state <= `OR1200_QMEMFSM_IDLE;
qmem_dack <= 1'b0;
qmem_iack <= 1'b0;
end
endcase
 
/verilog/or1200_spram_2048x32_bw.v
638,9 → 638,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 11'h000;
addr_reg <= 11'h000;
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
//
// RAM write byte 0
647,7 → 647,7
//
always @(posedge clk)
if (ce && we[0])
mem_0[addr] <= #1 di[7:0];
mem_0[addr] <= di[7:0];
//
// RAM write byte 1
654,7 → 654,7
//
always @(posedge clk)
if (ce && we[1])
mem_1[addr] <= #1 di[15:8];
mem_1[addr] <= di[15:8];
//
// RAM write byte 2
661,7 → 661,7
//
always @(posedge clk)
if (ce && we[2])
mem_2[addr] <= #1 di[23:16];
mem_2[addr] <= di[23:16];
//
// RAM write byte 3
668,7 → 668,7
//
always @(posedge clk)
if (ce && we[3])
mem_3[addr] <= #1 di[31:24];
mem_3[addr] <= di[31:24];
 
`endif // !OR1200_XILINX_RAMB16
`endif // !OR1200_XILINX_RAMB4
/verilog/or1200_cpu.v
66,15 → 66,16
id_void, id_insn, ex_void,
ex_insn, ex_freeze, wb_insn, wb_freeze, id_pc, ex_pc, wb_pc, branch_op,
spr_dat_npc, rf_dataw, ex_flushpipe,
du_stall, du_addr, du_dat_du, du_read, du_write, du_except_stop, du_except_trig,
du_dsr, du_dmr1, du_hwbkpt, du_hwbkpt_ls_r, du_dat_cpu, du_lsu_store_dat, du_lsu_load_dat,
du_stall, du_addr, du_dat_du, du_read, du_write, du_except_stop,
du_except_trig, du_dsr, du_dmr1, du_hwbkpt, du_hwbkpt_ls_r, du_dat_cpu,
du_lsu_store_dat, du_lsu_load_dat,
abort_mvspr, abort_ex,
// Data interface
dc_en,
dcpu_adr_o, dcpu_cycstb_o, dcpu_we_o, dcpu_sel_o, dcpu_tag_o, dcpu_dat_o,
dcpu_dat_i, dcpu_ack_i, dcpu_rty_i, dcpu_err_i, dcpu_tag_i,
sb_en, dmmu_en,
dcpu_adr_o, dcpu_cycstb_o, dcpu_we_o, dcpu_sel_o, dcpu_tag_o,
dcpu_dat_o, dcpu_dat_i, dcpu_ack_i, dcpu_rty_i, dcpu_err_i, dcpu_tag_i,
sb_en, dmmu_en, dc_no_writethrough,
 
// SR Interface
boot_adr_sel_i,
84,7 → 85,7
 
// SPR interface
supv, spr_addr, spr_dat_cpu, spr_dat_pic, spr_dat_tt, spr_dat_pm,
spr_dat_dmmu, spr_dat_immu, spr_dat_du, spr_cs, spr_we
spr_dat_dmmu, spr_dat_immu, spr_dat_du, spr_cs, spr_we, mtspr_dc_done
);
 
parameter dw = `OR1200_OPERAND_WIDTH;
167,7 → 168,8
input dcpu_err_i;
input [3:0] dcpu_tag_i;
output dc_en;
 
output dc_no_writethrough;
//
// Data (DMMU) interface
//
196,7 → 198,8
output [dw-1:0] spr_dat_npc;
output [31:0] spr_cs;
output spr_we;
 
input mtspr_dc_done;
//
// Interrupt exceptions
//
245,8 → 248,10
wire [dw-1:0] lsu_dataout;
wire [dw-1:0] sprs_dataout;
wire [dw-1:0] fpu_dataout;
wire fpu_done;
wire [31:0] ex_simm;
wire [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;
wire [`OR1200_WAIT_ON_WIDTH-1:0] wait_on;
wire [`OR1200_EXCEPT_WIDTH-1:0] except_type;
wire [4:0] cust5_op;
wire [5:0] cust5_limm;
276,7 → 281,7
wire [31:0] eear;
wire [`OR1200_SR_WIDTH-1:0] esr;
wire [`OR1200_FPCSR_WIDTH-1:0] fpcsr;
wire fpcsr_we;
wire fpcsr_we;
wire sr_we;
wire [`OR1200_SR_WIDTH-1:0] to_sr;
wire [`OR1200_SR_WIDTH-1:0] sr;
293,7 → 298,8
wire [31:0] spr_dat_npc;
wire [31:0] spr_dat_ppc;
wire [31:0] spr_dat_mac;
wire [31:0] spr_dat_fpu;
wire [31:0] spr_dat_fpu;
wire mtspr_done;
wire force_dslot_fetch;
wire no_more_dslot;
wire ex_void;
336,7 → 342,7
`ifdef OR1200_NO_DC
assign dc_en = 1'b0;
`else
assign dc_en = sr[`OR1200_SR_DCE];
assign dc_en = sr[`OR1200_SR_DCE];
`endif
 
//
387,6 → 393,12
assign flag_we = (flag_we_alu | flag_we_fpu) & ~abort_mvspr;
 
//
// Flag for any MTSPR instructions, that must block execution, to indicate done
//
assign mtspr_done = mtspr_dc_done;
//
// Instantiation of instruction fetch block
//
or1200_genpc or1200_genpc(
492,6 → 504,7
.id_pc(id_pc),
.ex_pc(ex_pc),
.multicycle(multicycle),
.wait_on(wait_on),
.wbforw_valid(wbforw_valid),
.sig_syscall(sig_syscall),
.sig_trap(sig_trap),
506,7 → 519,8
.ex_macrc_op(ex_macrc_op),
.rfe(rfe),
.du_hwbkpt(du_hwbkpt),
.except_illegal(except_illegal)
.except_illegal(except_illegal),
.dc_no_writethrough(dc_no_writethrough)
);
 
//
534,7 → 548,8
.spr_write(spr_we),
.spr_addr(spr_addr),
.spr_dat_i(spr_dat_cpu),
.spr_dat_o(spr_dat_rf)
.spr_dat_o(spr_dat_rf),
.du_read(du_read)
);
 
//
597,12 → 612,13
.b(operand_b),
.fpu_op(fpu_op),
.result(fpu_dataout),
.done(fpu_done),
.flagforw(flagforw_fpu),
.flag_we(flag_we_fpu),
.sig_fp(sig_fp),
.except_started(fpu_except_started),
.except_started(fpu_except_started),
.fpcsr_we(fpcsr_we),
.fpcsr(fpcsr),
.fpcsr(fpcsr),
.spr_cs(spr_cs[`OR1200_SPR_GROUP_FPU]),
.spr_write(spr_we),
.spr_addr(spr_addr),
684,7 → 700,7
.except_started(except_started),
 
.fpcsr(fpcsr),
.fpcsr_we(fpcsr_we),
.fpcsr_we(fpcsr_we),
.spr_dat_fpu(spr_dat_fpu),
.sr_we(sr_we),
755,6 → 771,9
.clk(clk),
.rst(rst),
.multicycle(multicycle),
.wait_on(wait_on),
.fpu_done(fpu_done),
.mtspr_done(mtspr_done),
.flushpipe(wb_flushpipe),
.extend_flush(extend_flush),
.lsu_stall(lsu_stall),
794,7 → 813,7
.sig_immufault(except_immufault),
.sig_tick(sig_tick),
.sig_fp(sig_fp),
.fpcsr_fpee(fpcsr[`OR1200_FPCSR_FPEE]),
.fpcsr_fpee(fpcsr[`OR1200_FPCSR_FPEE]),
.ex_branch_taken(ex_branch_taken),
.icpu_ack_i(icpu_ack_i),
.icpu_err_i(icpu_err_i),
/verilog/or1200_sprs.v
63,7 → 63,7
spr_dat_cfgr, spr_dat_rf, spr_dat_npc, spr_dat_ppc, spr_dat_mac,
boot_adr_sel_i,
// Floating point control register and SPR input
// Floating point SPR input
fpcsr, fpcsr_we, spr_dat_fpu,
 
// From/to other RISC units
288,13 → 288,9
assign epcr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_EPCR));
assign eear_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_EEAR));
assign esr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_ESR));
`ifdef OR1200_FPU_IMPLEMENTED
assign fpcsr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_FPCSR));
`else
assign fpcsr_sel = 0;
`endif
 
 
//
// Write enables for system SPRs
//
303,12 → 299,8
assign epcr_we = (spr_we && epcr_sel);
assign eear_we = (spr_we && eear_sel);
assign esr_we = (spr_we && esr_sel);
`ifdef OR1200_FPU_IMPLEMENTED
assign fpcsr_we = (spr_we && fpcsr_sel);
`else
assign fpcsr_we = 0;
`endif
 
//
// Output from system SPRs
//
319,9 → 311,7
({{32-`OR1200_SR_WIDTH{1'b0}},sr} & {32{sr_sel}}) |
(epcr & {32{epcr_sel}}) |
(eear & {32{eear_sel}}) |
`ifdef OR1200_FPU_IMPLEMENTED
({{32-`OR1200_FPCSR_WIDTH{1'b0}},fpcsr} & {32{fpcsr_sel}}) |
`endif
({{32-`OR1200_SR_WIDTH{1'b0}},esr} & {32{esr_sel}});
 
//
339,26 → 329,26
//
always @(posedge clk or posedge rst)
if (rst)
sr_reg <= #1 {2'h1, `OR1200_SR_EPH_DEF, {`OR1200_SR_WIDTH-4{1'b0}}, 1'b1};
sr_reg <= {2'h1, `OR1200_SR_EPH_DEF, {`OR1200_SR_WIDTH-4{1'b0}}, 1'b1};
else if (except_started)
sr_reg <= #1 to_sr[`OR1200_SR_WIDTH-1:0];
sr_reg <= to_sr[`OR1200_SR_WIDTH-1:0];
else if (sr_we)
sr_reg <= #1 to_sr[`OR1200_SR_WIDTH-1:0];
sr_reg <= to_sr[`OR1200_SR_WIDTH-1:0];
 
// EPH part of Supervision register
always @(posedge clk or posedge rst)
// default value
if (rst) begin
sr_reg_bit_eph <= #1 `OR1200_SR_EPH_DEF;
sr_reg_bit_eph_select <= #1 1'b1; // select async. value due to reset state
sr_reg_bit_eph <= `OR1200_SR_EPH_DEF;
sr_reg_bit_eph_select <= 1'b1; // select async. value due to reset state
end
// selected value (different from default) is written into FF after reset state
else if (sr_reg_bit_eph_select) begin
sr_reg_bit_eph <= #1 boot_adr_sel_i; // dynamic value can only be assigned to FF out of reset!
sr_reg_bit_eph_select <= #1 1'b0; // select FF value
sr_reg_bit_eph <= boot_adr_sel_i; // dynamic value can only be assigned to FF out of reset!
sr_reg_bit_eph_select <= 1'b0; // select FF value
end
else if (sr_we) begin
sr_reg_bit_eph <= #1 to_sr[`OR1200_SR_EPH];
sr_reg_bit_eph <= to_sr[`OR1200_SR_EPH];
end
 
// select async. value of EPH bit after reset
372,9 → 362,7
// MTSPR/MFSPR interface
//
always @(spr_addr or sys_data or spr_dat_mac or spr_dat_pic or spr_dat_pm or
`ifdef OR1200_FPU_IMPLEMENTED
spr_dat_fpu or
`endif
spr_dat_dmmu or spr_dat_immu or spr_dat_du or spr_dat_tt) begin
casex (spr_addr[`OR1200_SPR_GROUP_BITS]) // synopsys parallel_case
`OR1200_SPR_GROUP_SYS:
391,10 → 379,8
to_wbmux = spr_dat_immu;
`OR1200_SPR_GROUP_MAC:
to_wbmux = spr_dat_mac;
`ifdef OR1200_FPU_IMPLEMENTED
`OR1200_SPR_GROUP_FPU:
to_wbmux = spr_dat_fpu;
`endif
default: //`OR1200_SPR_GROUP_DU:
to_wbmux = spr_dat_du;
endcase
/verilog/or1200_tt.v
155,9 → 155,9
if (rst)
ttmr <= 32'b0;
else if (ttmr_sel && spr_write)
ttmr <= #1 spr_dat_i;
ttmr <= spr_dat_i;
else if (ttmr[`OR1200_TT_TTMR_IE])
ttmr[`OR1200_TT_TTMR_IP] <= #1 ttmr[`OR1200_TT_TTMR_IP] | (match & ttmr[`OR1200_TT_TTMR_IE]);
ttmr[`OR1200_TT_TTMR_IP] <= ttmr[`OR1200_TT_TTMR_IP] | (match & ttmr[`OR1200_TT_TTMR_IE]);
`else
assign ttmr = {2'b11, 30'b0}; // TTMR[M] = 0x3
`endif
170,11 → 170,11
if (rst)
ttcr <= 32'b0;
else if (restart)
ttcr <= #1 32'b0;
ttcr <= 32'b0;
else if (ttcr_sel && spr_write)
ttcr <= #1 spr_dat_i;
ttcr <= spr_dat_i;
else if (!stop)
ttcr <= #1 ttcr + 32'd1;
ttcr <= ttcr + 32'd1;
`else
assign ttcr = 32'b0;
`endif
/verilog/or1200_immu_top.v
254,16 → 254,16
always @(posedge rst or posedge clk)
// default value
if (rst) begin
icpu_adr_default <= #1 32'h0000_0100;
icpu_adr_select <= #1 1'b1; // select async. value due to reset state
icpu_adr_default <= 32'h0000_0100;
icpu_adr_select <= 1'b1; // select async. value due to reset state
end
// selected value (different from default) is written into FF after reset state
else if (icpu_adr_select) begin
icpu_adr_default <= #1 icpu_adr_boot; // dynamic value can only be assigned to FF out of reset!
icpu_adr_select <= #1 1'b0; // select FF value
icpu_adr_default <= icpu_adr_boot; // dynamic value can only be assigned to FF out of reset!
icpu_adr_select <= 1'b0; // select FF value
end
else begin
icpu_adr_default <= #1 icpu_adr_i;
icpu_adr_default <= icpu_adr_i;
end
 
// select async. value for boot address after reset - PC jumps to the address selected after boot!
292,9 → 292,9
//
always @(posedge clk or posedge rst)
if (rst)
icpu_vpn_r <= #1 {32-`OR1200_IMMU_PS{1'b0}};
icpu_vpn_r <= {32-`OR1200_IMMU_PS{1'b0}};
else
icpu_vpn_r <= #1 icpu_adr_i[31:`OR1200_IMMU_PS];
icpu_vpn_r <= icpu_adr_i[31:`OR1200_IMMU_PS];
 
`ifdef OR1200_NO_IMMU
 
339,19 → 339,19
//
always @(posedge clk or posedge rst)
if (rst)
dis_spr_access_frst_clk <= #1 1'b0;
dis_spr_access_frst_clk <= 1'b0;
else if (!icpu_rty_o)
dis_spr_access_frst_clk <= #1 1'b0;
dis_spr_access_frst_clk <= 1'b0;
else if (spr_cs)
dis_spr_access_frst_clk <= #1 1'b1;
dis_spr_access_frst_clk <= 1'b1;
 
always @(posedge clk or posedge rst)
if (rst)
dis_spr_access_scnd_clk <= #1 1'b0;
dis_spr_access_scnd_clk <= 1'b0;
else if (!icpu_rty_o)
dis_spr_access_scnd_clk <= #1 1'b0;
dis_spr_access_scnd_clk <= 1'b0;
else if (dis_spr_access_frst_clk)
dis_spr_access_scnd_clk <= #1 1'b1;
dis_spr_access_scnd_clk <= 1'b1;
 
//
// Tags:
379,9 → 379,9
//
always @(posedge clk or posedge rst)
if (rst)
itlb_en_r <= #1 1'b0;
itlb_en_r <= 1'b0;
else
itlb_en_r <= #1 itlb_en & ~itlb_spr_access;
itlb_en_r <= itlb_en & ~itlb_spr_access;
 
//
// ITLB lookup successful
424,9 → 424,9
// so itlb can continue with process during execution of mfspr.
always @(posedge clk or posedge rst)
if (rst)
spr_dat_reg <= #1 32'h0000_0000;
spr_dat_reg <= 32'h0000_0000;
else if (spr_cs & !dis_spr_access_scnd_clk)
spr_dat_reg <= #1 itlb_dat_o;
spr_dat_reg <= itlb_dat_o;
 
assign spr_dat_o = itlb_spr_access ? itlb_dat_o : spr_dat_reg;
 
/verilog/or1200_fpu.v
10,8 → 10,8
//// Interface based on MULT/MAC unit. ////
//// ////
//// To Do: ////
//// - remainder instruction implementation ////
//// - registering in/around compare unit ////
//// - lf.rem.s and lf.madd.s instruction support ////
//// - implement FP SPRs as needed ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius@opencores.org ////
18,7 → 18,7
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG ////
//// Copyright (C) 2009,2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
53,7 → 53,7
clk, rst,
 
// FPU interface
ex_freeze, a, b, fpu_op, result,
ex_freeze, a, b, fpu_op, result, done,
 
// Flag controls
flagforw, flag_we,
61,8 → 61,10
// Exception signal
sig_fp, except_started,
 
// SPR interface
// FPCSR system register
fpcsr_we, fpcsr,
// SPR interface -- currently unused
spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
);
 
86,19 → 88,19
input [width-1:0] b;
input [`OR1200_FPUOP_WIDTH-1:0] fpu_op;
output [width-1:0] result;
 
output done;
//
// Flag signals
//
output flagforw;
output flag_we;
 
//
// FPCSR interface
//
input fpcsr_we;
output [`OR1200_FPCSR_WIDTH-1:0] fpcsr;
output [`OR1200_FPCSR_WIDTH-1:0] fpcsr;
 
//
// Exception signal
125,7 → 127,8
assign flag_we = 0;
assign sig_fp = 0;
assign spr_dat_o = 0;
assign fpcsr = 0;
assign done = 1;
`else
 
132,61 → 135,74
//
// Internals
//
reg [2:0] fpu_op_count;
wire fpu_op_is_arith, fpu_op_is_conv,
fpu_op_is_comp;
wire fpu_op_r_is_arith, fpu_op_r_is_conv,
fpu_op_r_is_comp;
wire fpu_arith_done, fpu_conv_done,
fpu_comp_done;
wire [width-1:0] result_arith, result_conv;
reg [`OR1200_FPUOP_WIDTH:0] fpu_op_r;
reg [`OR1200_FPCSR_WIDTH-1:0] fpcsr_r;
reg fpu_latch_operand;
wire fpu_op_valid;
reg fpu_op_valid_re;
wire fpu_check_op;
wire fpu_latch_op;
wire inf, snan, qnan, ine, overflow,
underflow, zero, div_by_zero;
wire fpu_op_is_comp, fpu_op_r_is_comp;
wire altb, blta, aeqb, cmp_inf, cmp_zero,
wire inf, inv_inf_op_in,snan, snan_in,qnan,
ine, overflow, underflow, zero, dbz,
dbz_in, mul_z_inf, nan_in;
wire altb, blta, aeqb, inf_cmp, zero_cmp,
unordered ;
wire snan_conv, ine_conv, inv_conv,
zero_conv, underflow_conv,
overflow_conv;
wire inv_comp;
reg flag;
 
assign spr_dat_o = 0;
assign fpcsr = fpcsr_r;
assign sig_fp = fpcsr_r[`OR1200_FPCSR_FPEE]
& (|fpcsr_r[`OR1200_FPCSR_WIDTH-1:`OR1200_FPCSR_OVF]);
 
// Top bit indicates FPU instruction
assign fpu_op_valid = fpu_op[`OR1200_FPUOP_WIDTH-1];
 
assign fpu_check_op = !ex_freeze & fpu_op_valid;
// Generate signals to latch fpu_op from decode instruction, then latch
// operands when they appear during execute stage
assign fpu_check_op = (!ex_freeze & fpu_op[`OR1200_FPUOP_WIDTH-1]);
 
assign fpu_op_is_arith = !(|fpu_op[3:2]);
assign fpu_op_is_conv = fpu_op[2] & !fpu_op[3];
assign fpu_op_is_comp = fpu_op[3];
 
assign fpu_op_r_is_comp = fpu_op_r[3];
assign fpu_op_r_is_arith = !(|fpu_op_r[3:2]);
assign fpu_op_r_is_conv = fpu_op_r[2] & !fpu_op_r[3];
assign fpu_op_r_is_comp = fpu_op_r[3];
 
assign fpu_latch_op = fpu_check_op & !fpu_op_is_comp;
assign done = (fpu_op_r_is_arith & fpu_arith_done) |
(fpu_op_r_is_conv & fpu_conv_done) |
(fpu_op_r_is_comp & fpu_comp_done) ;
always @(posedge clk)
fpu_latch_operand <= fpu_check_op & !fpu_op_is_comp;
 
// Register fpu_op on comparisons, clear otherwise, remove top bit
// Register fpu_op (remove FPU op valid bit [7], replace with 0)
always @(posedge clk)
fpu_op_r <= (fpu_check_op & fpu_op_is_comp) ?
{1'b0,fpu_op[`OR1200_FPUOP_WIDTH-2:0]} : !ex_freeze ?
0 : fpu_op_r;
if (fpu_check_op)
fpu_op_r <= {1'b0,fpu_op[`OR1200_FPUOP_WIDTH-2:0]};
 
// Indicate new FPU op
always @(posedge clk or posedge rst)
if (rst)
fpu_op_valid_re <= 0;
else if (fpu_op_valid_re)
fpu_op_valid_re <= 0;
else if (fpu_check_op)
fpu_op_valid_re <= 1;
//
// Counter for each FPU operation
// Loaded at start, counts down
//
always @(posedge clk or posedge rst) begin
if (rst)
fpu_op_count <= 0;
else
if (|fpu_op_count)
fpu_op_count <= fpu_op_count - 1;
else if(fpu_check_op)
fpu_op_count <= 5;
end
 
//
// FPCSR register
// FPCSR system group register implementation
//
always @(posedge clk or posedge rst) begin
if (rst)
195,20 → 211,28
begin
if (fpcsr_we)
fpcsr_r <= b[`OR1200_FPCSR_WIDTH-1:0];
else if (fpu_op_count == 1)
else if (done)
begin
fpcsr_r[`OR1200_FPCSR_OVF] <= overflow;
fpcsr_r[`OR1200_FPCSR_UNF] <= underflow;
fpcsr_r[`OR1200_FPCSR_SNF] <= snan;
fpcsr_r[`OR1200_FPCSR_QNF] <= qnan;
fpcsr_r[`OR1200_FPCSR_ZF] <= zero |
(cmp_zero & fpu_op_r_is_comp);
fpcsr_r[`OR1200_FPCSR_IXF] <= ine;
fpcsr_r[`OR1200_FPCSR_IVF] <= 0; // Not used by this FPU
fpcsr_r[`OR1200_FPCSR_INF] <= inf |
(cmp_inf & fpu_op_r_is_comp);
fpcsr_r[`OR1200_FPCSR_DZF] <= div_by_zero;
end // if (fpu_op_count == 1)
fpcsr_r[`OR1200_FPCSR_OVF] <= (overflow & fpu_op_r_is_arith);
fpcsr_r[`OR1200_FPCSR_UNF] <= (underflow & fpu_op_r_is_arith) |
(underflow_conv & fpu_op_r_is_conv);
fpcsr_r[`OR1200_FPCSR_SNF] <= (snan & fpu_op_r_is_arith)|
(snan_conv & fpu_op_r_is_conv);
fpcsr_r[`OR1200_FPCSR_QNF] <= (qnan & fpu_op_r_is_arith);
fpcsr_r[`OR1200_FPCSR_ZF] <= (zero & fpu_op_r_is_arith) |
(zero_cmp & fpu_op_r_is_comp) |
(zero_conv & fpu_op_r_is_conv);
fpcsr_r[`OR1200_FPCSR_IXF] <= (ine & fpu_op_r_is_arith) |
(ine_conv & fpu_op_r_is_conv);
fpcsr_r[`OR1200_FPCSR_IVF] <=
((snan_in | dbz_in | inv_inf_op_in | mul_z_inf) &
fpu_op_r_is_arith) |
((inv_conv | snan_conv) & fpu_op_r_is_conv) |
(inv_comp & fpu_op_r_is_comp);
fpcsr_r[`OR1200_FPCSR_INF] <= (inf & fpu_op_r_is_arith) |
(inf_cmp & fpu_op_r_is_comp);
fpcsr_r[`OR1200_FPCSR_DZF] <= (dbz & fpu_op_r_is_arith);
end // if (fpu_arith_done | fpu_conv_done)
if (except_started)
fpcsr_r[`OR1200_FPCSR_FPEE] <= 0;
end // else: !if(rst)
217,80 → 241,175
//
// Comparison flag generation
//
always@(posedge clk)
always @*
begin
if (fpu_op_r_is_comp)
begin
case(fpu_op_r)
`OR1200_FPCOP_SFEQ: begin
flag <= aeqb;
// Get rid of top bit - is FPU op valid bit
case({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]})
`OR1200_FPCOP_SFEQ: begin
flag = aeqb;
end
`OR1200_FPCOP_SFNE: begin
flag = !aeqb;
end
`OR1200_FPCOP_SFNE: begin
flag <= !aeqb;
end
`OR1200_FPCOP_SFGT: begin
flag <= blta & !aeqb;
end
`OR1200_FPCOP_SFGE: begin
flag <= blta | aeqb;
end
`OR1200_FPCOP_SFLT: begin
flag <= altb & !aeqb;
end
`OR1200_FPCOP_SFLE: begin
flag <= altb | aeqb;
end
default: begin
flag <= 0;
end
endcase // case (fpu_op_r)
end // if (fpu_op_r_is_comp)
else
flag <= 0;
`OR1200_FPCOP_SFGT: begin
flag = blta & !aeqb;
end
`OR1200_FPCOP_SFGE: begin
flag = blta | aeqb;
end
`OR1200_FPCOP_SFLT: begin
flag = altb & !aeqb;
end
`OR1200_FPCOP_SFLE: begin
flag = altb | aeqb;
end
default: begin
flag = 0;
end
endcase // case (fpu_op_r)
end // always@ (posedge clk)
assign flagforw = flag;
// Determine here where we do the write, ie how much we pipeline the
// comparison
assign flag_we = fpu_op_r_is_comp & (fpu_op_count == 2);
// comparison
assign flag_we = fpu_op_r_is_comp & fpu_comp_done;
 
// FP arithmetic module
fpu fpu0
// MUX for outputs from arith and conversion modules
assign result = fpu_op_r_is_conv ? result_conv : result_arith;
 
//
// Instantiate FPU modules
//
`ifdef OR1200_FPU_ARITH_FPU100
 
// FPU 100 VHDL core from OpenCores.org: http://opencores.org/project,fpu100
// Used only for add,sub,mul,div
or1200_fpu_arith fpu_arith
(
.clk_i(clk),
.opa_i(a),
.opb_i(b),
.fpu_op_i({1'b0,fpu_op_r[1:0]}), // Only bottom 2 bits
.rmode_i(fpcsr_r[`OR1200_FPCSR_RM]),
.output_o(result_arith),
.start_i(fpu_op_valid_re & fpu_op_r_is_arith),
.ready_o(fpu_arith_done),
.ine_o(ine),
.overflow_o(overflow),
.underflow_o(underflow),
.div_zero_o(dbz),
.inf_o(inf),
.zero_o(zero),
.qnan_o(qnan),
.snan_o(snan)
);
 
`endif // `ifdef OR1200_FPU_ARITH_FPU100
// Logic for detection of signaling NaN on input
// signaling NaN: exponent is 8hff, [22] is zero, rest of fract is non-zero
// quiet NaN: exponent is 8hff, [22] is 1
reg a_is_snan, b_is_snan;
reg a_is_qnan, b_is_qnan;
always @(posedge clk)
begin
a_is_snan <= (a[30:23]==8'hff) & !a[22] & (|a[21:0]);
b_is_snan <= (b[30:23]==8'hff) & !b[22] & (|b[21:0]);
a_is_qnan <= (a[30:23]==8'hff) & a[22];
b_is_qnan <= (b[30:23]==8'hff) & b[22];
end
// Signal to indicate there was a signaling NaN on input
assign snan_in = a_is_snan | b_is_snan;
 
// Check for, add with opposite signed infinities, or subtract with
// same signed infinities.
reg a_is_inf, b_is_inf, a_b_sign_xor;
always @(posedge clk)
begin
a_is_inf <= (a[30:23]==8'hff) & !(|a[22:0]);
b_is_inf <= (b[30:23]==8'hff) & !(|a[22:0]);
a_b_sign_xor <= a[31] ^ b[31];
end
assign inv_inf_op_in = (a_is_inf & b_is_inf) &
((a_b_sign_xor &
({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
`OR1200_FPUOP_ADD)) |
(!a_b_sign_xor &
({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
`OR1200_FPUOP_SUB))) ;
// Check if it's 0.0/0.0 to generate invalid signal (ignore sign bit)
reg a_is_zero, b_is_zero;
always @(posedge clk)
begin
a_is_zero <= !(|a[30:0]);
b_is_zero <= !(|b[30:0]);
end
assign dbz_in = ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
`OR1200_FPUOP_DIV) & (a_is_zero & b_is_zero);
assign mul_z_inf = ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
`OR1200_FPUOP_MUL) &
((a_is_zero & b_is_inf) | (b_is_zero & a_is_inf));
assign nan_in = (a_is_snan | b_is_snan | a_is_qnan | b_is_qnan);
 
// 32-bit integer <-> single precision floating point conversion unit
or1200_fpu_intfloat_conv fpu_intfloat_conv
(
.clk(clk),
.clk(clk),
.rmode(fpcsr_r[`OR1200_FPCSR_RM]),
.fpu_op(fpu_op[2:0]),
.opa(a),
.opb(b),
.out(result),
.latch_operand(fpu_latch_operand),
.latch_op(fpu_latch_op),
.inf(inf),
.snan(snan),
.qnan(qnan),
.ine(ine),
.overflow(overflow),
.underflow(underflow),
.zero(zero),
.div_by_zero(div_by_zero)
.fpu_op(fpu_op_r[2:0]),
.opa(a),
.out(result_conv),
.snan(snan_conv),
.ine(ine_conv),
.inv(inv_conv),
.overflow(overflow_conv),
.underflow(underflow_conv),
.zero(zero_conv)
);
 
// FP comparator
fcmp fcmp0
// 5-long shift reg for conversion ready counter
reg [6:0] fpu_conv_shr;
always @(posedge clk)
fpu_conv_shr <= {fpu_conv_shr[5:0],fpu_check_op & fpu_op_is_conv};
assign fpu_conv_done = fpu_conv_shr[6];
 
// Single precision floating point number comparison module
or1200_fpu_fcmp fpu_fcmp
(
.opa(a),
.opb(b),
.unordered(unordered),
// I am convinced the comparison logic is wrong way around in this
// module, simplest to swap them on output -- julius
// module, simplest to swap them on output -- julius
.altb(blta),
.blta(altb),
.aeqb(aeqb),
.inf(cmp_inf),
.zero(cmp_zero));
.inf(inf_cmp),
.zero(zero_cmp));
 
reg fpu_op_valid_re_r;
always @(posedge clk)
fpu_op_valid_re_r <= fpu_op_valid_re;
assign fpu_comp_done = fpu_op_valid_re_r & fpu_op_r_is_comp;
 
// Comparison invalid when sNaN in on an equal comparison, or any NaN
// for any other comparison.
assign inv_comp = (snan_in & ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]}
== `OR1200_FPCOP_SFEQ)) |
(nan_in & ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]}
!= `OR1200_FPCOP_SFEQ));
`endif // !`ifndef OR1200_FPU_IMPLEMENTED
endmodule // or1200_fpu
/verilog/or1200_dc_fsm.v
3,20 → 3,21
//// OR1200's DC FSM ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Data cache state machine ////
//// ////
//// To Do: ////
//// - make it smaller and faster ////
//// - Test error during line read or write ////
//// ////
//// Author(s): ////
//// - Damjan Lampret, lampret@opencores.org ////
//// - Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
//// Copyright (C) 2000, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
41,66 → 42,11
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_dc_fsm.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// Minor update:
// Bugs fixed.
//
// Revision 1.9 2004/06/08 18:17:36 lampret
// Non-functional changes. Coding style fixes.
//
// Revision 1.8 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.7.4.1 2003/07/08 15:36:37 lampret
// Added embedded memory QMEM.
//
// Revision 1.7 2002/03/29 15:16:55 lampret
// Some of the warnings fixed.
//
// Revision 1.6 2002/03/28 19:10:40 lampret
// Optimized cache controller FSM.
//
// Revision 1.1.1.1 2002/03/21 16:55:45 lampret
// First import of the "new" XESS XSV environment.
//
//
// Revision 1.5 2002/02/11 04:33:17 lampret
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
//
// Revision 1.4 2002/02/01 19:56:54 lampret
// Fixed combinational loops.
//
// Revision 1.3 2002/01/28 01:15:59 lampret
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
//
// Revision 1.2 2002/01/14 06:18:22 lampret
// Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.9 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.8 2001/10/19 23:28:46 lampret
// Fixed some synthesis warnings. Configured with caches and MMUs.
//
// Revision 1.7 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:35 igorm
// no message
//
// Revision 1.2 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.1 2001/07/20 00:46:03 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
108,218 → 54,508
`include "or1200_defines.v"
 
`define OR1200_DCFSM_IDLE 3'd0
`define OR1200_DCFSM_CLOAD 3'd1
`define OR1200_DCFSM_LREFILL3 3'd2
`define OR1200_DCFSM_CSTORE 3'd3
`define OR1200_DCFSM_SREFILL4 3'd4
`define OR1200_DCFSM_CLOADSTORE 3'd1
`define OR1200_DCFSM_LOOP2 3'd2
`define OR1200_DCFSM_LOOP3 3'd3
`define OR1200_DCFSM_LOOP4 3'd4
`define OR1200_DCFSM_FLUSH5 3'd5
`define OR1200_DCFSM_INV6 3'd6
`define OR1200_DCFSM_WAITSPRCS7 3'd7
 
 
 
//
// Data cache FSM for cache line of 16 bytes (4x singleword)
//
 
module or1200_dc_fsm(
// Clock and reset
clk, rst,
module or1200_dc_fsm
(
// Clock and reset
clk, rst,
// Internal i/f to top level DC
dc_en, dcqmem_cycstb_i, dcqmem_ci_i, dcqmem_we_i, dcqmem_sel_i,
tagcomp_miss, biudata_valid, biudata_error, lsu_addr,
dcram_we, biu_read, biu_write, biu_do_sel, dcram_di_sel, first_hit_ack,
first_miss_ack, first_miss_err, burst, tag_we, tag_valid, dc_addr,
dc_no_writethrough, tag_dirty, dirty, tag, tag_v, dc_block_flush,
dc_block_writeback, spr_dat_i, mtspr_dc_done, spr_cswe
);
 
// Internal i/f to top level DC
dc_en, dcqmem_cycstb_i, dcqmem_ci_i, dcqmem_we_i, dcqmem_sel_i,
tagcomp_miss, biudata_valid, biudata_error, start_addr, saved_addr,
dcram_we, biu_read, biu_write, biu_sel, first_hit_ack, first_miss_ack, first_miss_err,
burst, tag_we, tag_valid, dc_addr
);
//
// I/O
//
input clk;
input rst;
input dc_en;
input dcqmem_cycstb_i;
input dcqmem_ci_i;
input dcqmem_we_i;
input [3:0] dcqmem_sel_i;
input tagcomp_miss;
input biudata_valid;
input biudata_error;
input [31:0] lsu_addr;
output [3:0] dcram_we;
output biu_read;
output biu_write;
output dcram_di_sel;
output biu_do_sel;
output first_hit_ack;
output first_miss_ack;
output first_miss_err;
output burst;
output tag_we;
output tag_valid;
output [31:0] dc_addr;
input dc_no_writethrough;
output tag_dirty;
input dirty;
input [`OR1200_DCTAG_W-2:0] tag;
input tag_v;
input dc_block_flush;
input dc_block_writeback;
input [31:0] spr_dat_i;
output mtspr_dc_done;
input spr_cswe;
//
// Internal wires and regs
//
reg [31:0] addr_r;
reg [2:0] state;
reg [2:0] cnt;
reg hitmiss_eval;
reg store;
reg load;
reg cache_inhibit;
reg cache_miss;
reg cache_dirty_needs_writeback;
reg did_early_load_ack;
reg cache_spr_block_flush;
reg cache_spr_block_writeback;
reg cache_wb;
wire load_hit_ack;
wire load_miss_ack;
wire load_inhibit_ack;
wire store_hit_ack;
wire store_hit_writethrough_ack;
wire store_miss_writethrough_ack;
wire store_inhibit_ack;
wire store_miss_ack;
wire dcram_we_after_line_load;
wire dcram_we_during_line_load;
wire tagram_we_end_of_loadstore_loop;
wire tagram_dirty_bit_set;
wire writethrough;
wire cache_inhibit_with_eval;
wire [1:0] next_addr_word;
 
//
// I/O
//
input clk;
input rst;
input dc_en;
input dcqmem_cycstb_i;
input dcqmem_ci_i;
input dcqmem_we_i;
input [3:0] dcqmem_sel_i;
input tagcomp_miss;
input biudata_valid;
input biudata_error;
input [31:0] start_addr;
output [31:0] saved_addr;
output [3:0] dcram_we;
output biu_read;
output biu_write;
output biu_sel;
output first_hit_ack;
output first_miss_ack;
output first_miss_err;
output burst;
output tag_we;
output tag_valid;
output [31:0] dc_addr;
//
// Cache inhibit
//
// Indicates whether cache is inhibited, during hitmiss_eval and after
assign cache_inhibit_with_eval = (hitmiss_eval & dcqmem_ci_i) |
(!hitmiss_eval & cache_inhibit);
//
// Generate of DCRAM write enables
//
 
//
// Internal wires and regs
//
reg [31:0] saved_addr_r;
reg [2:0] state;
reg [2:0] cnt;
reg hitmiss_eval;
reg store;
reg load;
reg cache_inhibit;
reg cache_miss;
//wire tagcomp_miss_wide;
wire first_store_hit_ack;
// WE when non-writethrough, and had to wait for a line to load.
assign dcram_we_after_line_load = (state == `OR1200_DCFSM_LOOP3) &
dcqmem_we_i & !cache_dirty_needs_writeback &
!did_early_load_ack;
 
//
// Generate of DCRAM write enables
//
//assign dcram_we = {4{load & biudata_valid & !cache_inhibit}} | {4{first_store_hit_ack}} & dcqmem_sel_i;
assign dcram_we = {4{load & biudata_valid & !cache_inhibit & !hitmiss_eval}} |
{4{first_store_hit_ack}} & dcqmem_sel_i;
//assign tag_we = biu_read & biudata_valid & !cache_inhibit;
assign tag_we = load & (biudata_valid & (!cache_inhibit | !cache_miss) | biudata_error) & !hitmiss_eval |
store & (biudata_valid & cache_inhibit & !cache_miss | biudata_error) & !hitmiss_eval;
assign tag_valid = biudata_valid & !cache_inhibit;
// WE when receiving the data cache line
assign dcram_we_during_line_load = (state == `OR1200_DCFSM_LOOP2) & load &
biudata_valid;
assign dcram_we =(// Write when hit - make sure it is only when hit - could
// maybe be doing write through and don't want to corrupt
// cache lines corresponding to the writethrough addr_r.
({4{store_hit_ack | store_hit_writethrough_ack}} |
// Write after load of line
{4{dcram_we_after_line_load}}) &
dcqmem_sel_i ) |
// Write during load
{4{dcram_we_during_line_load}};
 
//
// BIU read and write
//
//assign biu_read = (hitmiss_eval & tagcomp_miss) | (!hitmiss_eval & load);
//assign biu_read = ((hitmiss_eval & tagcomp_miss) | (!hitmiss_eval & load)) & (dcqmem_cycstb_i | biudata_valid);
assign biu_read = (state == `OR1200_DCFSM_CLOAD) & (hitmiss_eval ? ((tagcomp_miss | dcqmem_ci_i) & dcqmem_cycstb_i) : (cache_miss & !cache_inhibit & biudata_valid | dcqmem_cycstb_i & !biudata_error)) |
(state == `OR1200_DCFSM_LREFILL3) & !(biudata_valid & !cnt) & !biudata_error;
//assign biu_write = store;
//assign biu_write = store & dcqmem_cycstb_i;
assign biu_write = store & dcqmem_cycstb_i;
assign biu_sel = load;
//
// Tag RAM signals
//
// WE to tag RAM when we finish loading a line.
assign tagram_we_end_of_loadstore_loop = ((state==`OR1200_DCFSM_LOOP2) &
biudata_valid & !(|cnt));
`ifndef OR1200_DC_WRITETHROUGH
// No writethrough, so mark a line dirty whenever we write to it
assign tagram_dirty_bit_set = store_hit_ack | store_miss_ack;
 
//assign dc_addr = (biu_read | biu_write) & !hitmiss_eval ? saved_addr : start_addr;
assign dc_addr = (!(load | store) | hitmiss_eval) ? start_addr : saved_addr;
assign saved_addr = saved_addr_r;
// Generate done signal for MTSPR instructions that may block execution
assign mtspr_dc_done = // Either DC disabled or we're not selected, or
!dc_en | !spr_cswe |
// Requested address not valid or writeback and !dirty
((state==`OR1200_DCFSM_FLUSH5) &
(!tag_v | (cache_spr_block_writeback & !dirty))) |
// Writeback or flush is finished
((state==`OR1200_DCFSM_LOOP3) &
(cache_spr_block_flush | cache_spr_block_writeback))|
// Invalidate of clean line finished
((state==`OR1200_DCFSM_INV6) & cache_spr_block_flush);
`else
`ifdef OR1200_DC_NOSTACKWRITETHROUGH
// For dirty bit setting when having writethrough but not for stack
assign tagram_dirty_bit_set = store_hit_ack | store_miss_ack;
`else
// Lines will never be dirty if always writethrough
assign tagram_dirty_bit_set = 0;
`endif
assign mtspr_dc_done = 1'b1;
`endif
 
//
// Assert for cache hit first word ready
// Assert for store cache hit first word ready
// Assert for cache miss first word stored/loaded OK
// Assert for cache miss first word stored/loaded with an error
//
//assign tagcomp_miss_wide = tagcomp_miss | (saved_addr != start_addr);
//assign first_hit_ack = (state == `OR1200_DCFSM_CLOAD) & !tagcomp_miss_wide & !cache_inhibit | first_store_hit_ack;
assign first_hit_ack = (state == `OR1200_DCFSM_CLOAD) & hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i | first_store_hit_ack;
//assign first_store_hit_ack = (state == `OR1200_DCFSM_CSTORE) & !tagcomp_miss_wide & biudata_valid & !cache_inhibit;
assign first_store_hit_ack = (state == `OR1200_DCFSM_CSTORE) & !hitmiss_eval & !cache_miss & biudata_valid & !cache_inhibit;
assign first_miss_ack = ((state == `OR1200_DCFSM_CLOAD) | (state == `OR1200_DCFSM_CSTORE)) & biudata_valid;
assign first_miss_err = ((state == `OR1200_DCFSM_CLOAD) | (state == `OR1200_DCFSM_CSTORE)) & biudata_error;
assign tag_dirty = tagram_dirty_bit_set;
// WE to tag RAM
assign tag_we = tagram_we_end_of_loadstore_loop |
tagram_dirty_bit_set | (state == `OR1200_DCFSM_INV6);
 
//
// Assert burst when doing reload of complete cache line
//
//assign burst = (state == `OR1200_DCFSM_CLOAD) & tagcomp_miss & !cache_inhibit
// | (state == `OR1200_DCFSM_LREFILL3)
//`ifdef OR1200_DC_STORE_REFILL
// | (state == `OR1200_DCFSM_SREFILL4)
//`endif
// ;
assign burst = load & (hitmiss_eval ? !dcqmem_ci_i : !cache_inhibit);
// Valid bit
// Set valid when end of line load, or marking dirty (is still valid)
assign tag_valid = ( tagram_we_end_of_loadstore_loop &
(load | (store & cache_spr_block_writeback)) ) |
tagram_dirty_bit_set;
 
//
// Main DC FSM
//
always @(posedge clk or posedge rst) begin
if (rst) begin
state <= #1 `OR1200_DCFSM_IDLE;
saved_addr_r <= #1 32'b0;
hitmiss_eval <= #1 1'b0;
store <= #1 1'b0;
load <= #1 1'b0;
cnt <= #1 3'b000;
cache_miss <= #1 1'b0;
cache_inhibit <= #1 1'b0;
end
else
 
//
// BIU read and write
//
 
assign biu_read = // Bus read request when:
// 1) Have a miss and not dirty or a load with inhibit
((state == `OR1200_DCFSM_CLOADSTORE) &
(((hitmiss_eval & tagcomp_miss & !dirty &
!(store & writethrough)) |
(load & cache_inhibit_with_eval)) & dcqmem_cycstb_i)) |
// 2) In the loop and loading
((state == `OR1200_DCFSM_LOOP2) & load);
 
assign biu_write = // Bus write request when:
// 1) Have a miss and dirty or store with inhibit
((state == `OR1200_DCFSM_CLOADSTORE) &
(((hitmiss_eval & tagcomp_miss & dirty) |
(store & writethrough)) |
(store & cache_inhibit_with_eval)) & dcqmem_cycstb_i) |
// 2) In the loop and storing
((state == `OR1200_DCFSM_LOOP2) & store);
//
// Select for data to actual cache RAM (from LSU or BIU)
//
// Data to DCRAM - from external bus when loading (from IU when store)
assign dcram_di_sel = load;
// Data to external bus - always from IU except in case of bursting back
// the line to memory. (1 selects DCRAM)
assign biu_do_sel = (state == `OR1200_DCFSM_LOOP2) & store;
 
// 2-bit wire for calculating next word of burst write
assign next_addr_word = addr_r[3:2] + 1;
// Address to cache RAM (tag address also derived from this)
assign dc_addr =
// First check if we've got a block flush or WB op
((dc_block_flush & !cache_spr_block_flush) |
(dc_block_writeback & !cache_spr_block_writeback)) ?
spr_dat_i :
(state==`OR1200_DCFSM_FLUSH5) ? addr_r:
// If no SPR action, then always put out address from LSU
(state==`OR1200_DCFSM_IDLE | hitmiss_eval) ? lsu_addr :
// Next, if in writeback loop, when ACKed must immediately
// output next word address (the RAM address takes a cycle
// to increment, but it's needed immediately for burst)
// otherwise, output our registered address.
(state==`OR1200_DCFSM_LOOP2 & biudata_valid & store ) ?
{addr_r[31:4], next_addr_word, 2'b00} : addr_r;
`ifdef OR1200_DC_WRITETHROUGH
`ifdef OR1200_DC_NOSTACKWRITETHROUGH
assign writethrough = !dc_no_writethrough;
`else
assign writethrough = 1;
`endif
`else
assign writethrough = 0;
`endif
//
// ACK generation for LSU
//
// ACK for when it's a cache hit
assign first_hit_ack = load_hit_ack | store_hit_ack |
store_hit_writethrough_ack |
store_miss_writethrough_ack |
store_inhibit_ack | store_miss_ack ;
 
// ACK for when it's a cache miss - load only, is used in MUX for data back
// LSU straight off external data bus. In
// this was is also used for cache inhibit
// loads.
assign first_miss_ack = load_miss_ack | load_inhibit_ack;
// ACK cache hit on load
assign load_hit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i & load;
// ACK cache hit on store, no writethrough
assign store_hit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i &
store & !writethrough;
// ACK cache hit on store with writethrough
assign store_hit_writethrough_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
!cache_miss & !cache_inhibit &
store & writethrough & biudata_valid;
// ACK cache miss on store with writethrough
assign store_miss_writethrough_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
cache_miss & !cache_inhibit &
store & writethrough & biudata_valid;
// ACK store when cacheinhibit
assign store_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
store & cache_inhibit & biudata_valid;
// Get the _early_ ack on first ACK back from wishbone during load only
// Condition is that we're in the loop - that it's the first ack we get (can
// tell from value of cnt), and we're loading a line to read from it (not
// loading to write to it, in the case of a write without writethrough.)
assign load_miss_ack = ((state== `OR1200_DCFSM_LOOP2) & load &
(cnt==`OR1200_DCLS-1) & biudata_valid &
!(dcqmem_we_i & !writethrough));
 
assign load_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
load & cache_inhibit & biudata_valid;
// This will be case of write through disabled, and had to load a line.
assign store_miss_ack = dcram_we_after_line_load;
assign first_miss_err = biudata_error & dcqmem_cycstb_i;
 
// Signal burst when in the load/store loop. We will always try to burst.
assign burst = (state == `OR1200_DCFSM_LOOP2);
 
//
// Main DC FSM
//
always @(posedge clk or posedge rst) begin
if (rst) begin
state <= `OR1200_DCFSM_IDLE;
addr_r <= 32'b0;
hitmiss_eval <= 1'b0;
store <= 1'b0;
load <= 1'b0;
cnt <= 3'b000;
cache_miss <= 1'b0;
cache_dirty_needs_writeback <= 1'b0;
cache_inhibit <= 1'b0;
did_early_load_ack <= 1'b0;
cache_spr_block_flush <= 1'b0;
cache_spr_block_writeback <= 1'b0;
end
else
case (state) // synopsys parallel_case
`OR1200_DCFSM_IDLE : begin
if (dcqmem_we_i & dc_en & dcqmem_cycstb_i) // store
state <= #1 `OR1200_DCFSM_CSTORE;
else if (!dcqmem_we_i & dc_en & dcqmem_cycstb_i) // store
state <= #1 `OR1200_DCFSM_CLOAD;
cache_inhibit <= #1 1'b0; // not dcqmem_ci_i because it is delayed (due to DTLB)
hitmiss_eval <= #1 dc_en & dcqmem_cycstb_i ;
store <= #1 dc_en & dcqmem_cycstb_i & dcqmem_we_i;
load <= #1 dc_en & dcqmem_cycstb_i & !dcqmem_we_i;
end
`OR1200_DCFSM_CLOAD: begin // load
if (!hitmiss_eval && cache_miss && !cache_inhibit && biudata_valid) begin
state <= #1 `OR1200_DCFSM_LREFILL3;
end
else if (!dcqmem_cycstb_i || !hitmiss_eval && (biudata_valid || biudata_error) || hitmiss_eval && !tagcomp_miss && !dcqmem_ci_i) begin
state <= #1 `OR1200_DCFSM_IDLE;
load <= #1 1'b0;
end
hitmiss_eval <= #1 1'b0;
cnt <= #1 `OR1200_DCLS-2;
if (hitmiss_eval) begin
cache_inhibit <= #1 dcqmem_ci_i;
cache_miss <= #1 tagcomp_miss;
end
if (hitmiss_eval)
saved_addr_r <= #1 start_addr;
else if (biudata_valid)
saved_addr_r[3:2] <= #1 saved_addr_r[3:2] + 1'b1;
end
`OR1200_DCFSM_LREFILL3 : begin
if (!dc_en || biudata_valid && !cnt || biudata_error) begin // finish/abort
state <= #1 `OR1200_DCFSM_IDLE;
load <= #1 1'b0;
end
if (biudata_valid) begin
cnt <= #1 cnt - 1'b1;
saved_addr_r[3:2] <= #1 saved_addr_r[3:2] + 1'b1;
end
end
`OR1200_DCFSM_CSTORE: begin // store
hitmiss_eval <= 1'b0;
if (hitmiss_eval) begin
cache_inhibit <= #1 dcqmem_ci_i;
cache_miss <= #1 tagcomp_miss;
end
if (hitmiss_eval)
saved_addr_r <= #1 start_addr;
`ifdef OR1200_DC_STORE_REFILL
else if (biudata_valid)
saved_addr_r[3:2] <= #1 saved_addr_r[3:2] + 1'b1;
cnt <= #1 `OR1200_DCLS-1;
if (!hitmiss_eval && cache_miss && !cache_inhibit && biudata_valid) begin
state <= #1 `OR1200_DCFSM_SREFILL4;
store <= #1 1'b0;
load <= #1 1'b1;
end
else
`OR1200_DCFSM_IDLE : begin
if (dc_en & (dc_block_flush | dc_block_writeback))
begin
cache_spr_block_flush <= dc_block_flush;
cache_spr_block_writeback <= dc_block_writeback;
hitmiss_eval <= 1'b1;
state <= `OR1200_DCFSM_FLUSH5;
addr_r <= spr_dat_i;
end
else if (dc_en & dcqmem_cycstb_i)
begin
state <= `OR1200_DCFSM_CLOADSTORE;
hitmiss_eval <= 1'b1;
store <= dcqmem_we_i;
load <= !dcqmem_we_i;
end
end // case: `OR1200_DCFSM_IDLE
`OR1200_DCFSM_CLOADSTORE: begin
hitmiss_eval <= 1'b0;
if (hitmiss_eval) begin
cache_inhibit <= dcqmem_ci_i; // Check for cache inhibit here
cache_miss <= tagcomp_miss;
cache_dirty_needs_writeback <= dirty;
addr_r <= lsu_addr;
end
 
// Evaluate any cache line load/stores in first cycle:
//
if (hitmiss_eval & tagcomp_miss & !(store & writethrough) &
!dcqmem_ci_i)
begin
// Miss - first either:
// 1) write back dirty line
if (dirty) begin
// Address for writeback
addr_r <= {tag, lsu_addr[`OR1200_DCINDXH:2],2'd0};
load <= 1'b0;
store <= 1'b1;
`ifdef OR1200_VERBOSE
$display("%t: dcache miss and dirty", $time);
`endif
if (!dcqmem_cycstb_i || !hitmiss_eval && (biudata_error || biudata_valid)) begin
state <= #1 `OR1200_DCFSM_IDLE;
store <= #1 1'b0;
end
`ifdef OR1200_DC_STORE_REFILL
`OR1200_DCFSM_SREFILL4 : begin
if (!dc_en) begin // somebody just turned off DC therefore we abort
cnt <= #1 3'd0; // DC will have to be invalidated before
state <= #1 `OR1200_DCFSM_IDLE; // it can be turned on again
load <= #1 1'b0;
end
else if (biudata_valid && (|cnt)) begin // refill ack, more loads to come
cnt <= #1 cnt - 1'd1;
saved_addr_r[3:2] <= #1 saved_addr_r[3:2] + 1'd1;
end
else if (biudata_valid) begin // last load of line refill
state <= #1 `OR1200_DCFSM_IDLE;
load <= #1 1'b0;
end
end
// 2) load requested line
else begin
addr_r <= lsu_addr;
load <= 1'b1;
store <= 1'b0;
end // else: !if(dirty)
state <= `OR1200_DCFSM_LOOP2;
// Set the counter for the burst accesses
cnt <= `OR1200_DCLS-1;
end
else if (// Strobe goes low
!dcqmem_cycstb_i |
// Cycle finishes
(!hitmiss_eval & (biudata_valid | biudata_error)) |
// Cache hit in first cycle....
(hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i &
// .. and you're not doing a writethrough store..
!(store & writethrough))) begin
state <= `OR1200_DCFSM_IDLE;
load <= 1'b0;
store <= 1'b0;
cache_inhibit <= 1'b0;
cache_dirty_needs_writeback <= 1'b0;
end
end // case: `OR1200_DCFSM_CLOADSTORE
`OR1200_DCFSM_LOOP2 : begin // loop/abort
if (!dc_en| biudata_error) begin
state <= `OR1200_DCFSM_IDLE;
load <= 1'b0;
store <= 1'b0;
cnt <= 1'b0;
end
if (biudata_valid & (|cnt)) begin
cnt <= cnt - 1'b1;
addr_r[3:2] <= addr_r[3:2] + 1'b1;
end
else if (biudata_valid & !(|cnt)) begin
state <= `OR1200_DCFSM_LOOP3;
addr_r <= lsu_addr;
load <= 1'b0;
store <= 1'b0;
end
 
// Track if we did an early ack during a load
if (load_miss_ack)
did_early_load_ack <= 1'b1;
 
end // case: `OR1200_DCFSM_LOOP2
`OR1200_DCFSM_LOOP3: begin // figure out next step
if (cache_dirty_needs_writeback) begin
// Just did store of the dirty line so now load new one
load <= 1'b1;
// Set the counter for the burst accesses
cnt <= `OR1200_DCLS-1;
// Address of line to be loaded
addr_r <= lsu_addr;
cache_dirty_needs_writeback <= 1'b0;
state <= `OR1200_DCFSM_LOOP2;
end // if (cache_dirty_needs_writeback)
else if (cache_spr_block_flush | cache_spr_block_writeback) begin
// Just wrote back the line to memory, we're finished.
cache_spr_block_flush <= 1'b0;
cache_spr_block_writeback <= 1'b0;
state <= `OR1200_DCFSM_WAITSPRCS7;
end
else begin
// Just loaded a new line, finish up
did_early_load_ack <= 1'b0;
state <= `OR1200_DCFSM_LOOP4;
end
end // case: `OR1200_DCFSM_LOOP3
 
`OR1200_DCFSM_LOOP4: begin
state <= `OR1200_DCFSM_IDLE;
end
 
`OR1200_DCFSM_FLUSH5: begin
hitmiss_eval <= 1'b0;
if (hitmiss_eval & !tag_v)
begin
// Not even cached, just ignore
cache_spr_block_flush <= 1'b0;
cache_spr_block_writeback <= 1'b0;
state <= `OR1200_DCFSM_WAITSPRCS7;
end
else if (hitmiss_eval & tag_v)
begin
// Tag is valid - what do we do?
if ((cache_spr_block_flush | cache_spr_block_writeback) &
dirty) begin
// Need to writeback
// Address for writeback (spr_dat_i has already changed so
// use line number from addr_r)
addr_r <= {tag, addr_r[`OR1200_DCINDXH:2],2'd0};
load <= 1'b0;
store <= 1'b1;
`ifdef OR1200_VERBOSE
$display("%t: block flush: dirty block", $time);
`endif
end
state <= `OR1200_DCFSM_LOOP2;
// Set the counter for the burst accesses
cnt <= `OR1200_DCLS-1;
end
else if (cache_spr_block_flush & !dirty)
begin
// Line not dirty, just need to invalidate
state <= `OR1200_DCFSM_INV6;
end // else: !if(dirty)
else if (cache_spr_block_writeback & !dirty)
begin
// Nothing to do - line is valid but not dirty
cache_spr_block_writeback <= 1'b0;
state <= `OR1200_DCFSM_WAITSPRCS7;
end
end // if (hitmiss_eval & tag_v)
end
`OR1200_DCFSM_INV6: begin
cache_spr_block_flush <= 1'b0;
// Wait until SPR CS goes low before going back to idle
if (!spr_cswe)
state <= `OR1200_DCFSM_IDLE;
end
`OR1200_DCFSM_WAITSPRCS7: begin
// Wait until SPR CS goes low before going back to idle
if (!spr_cswe)
state <= `OR1200_DCFSM_IDLE;
end
 
default:
state <= #1 `OR1200_DCFSM_IDLE;
endcase
end
endcase // case (state)
end // always @ (posedge clk or posedge rst)
 
endmodule
/verilog/or1200_fpu_pre_norm_div.v
0,0 → 1,191
//////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_pre_norm_div ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// pre-normalization entity for the division unit ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Original design (FPU100) - ////
//// Jidan Al-eryani, jidan@gmx.net ////
//// - Conv. to Verilog and inclusion in OR1200 - ////
//// Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2006, 2010
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
module or1200_fpu_pre_norm_div
(
clk_i,
opa_i,
opb_i,
exp_10_o,
dvdnd_50_o,
dvsor_27_o
);
 
parameter FP_WIDTH = 32;
parameter MUL_SERIAL = 0; // 0 for parallel multiplier, 1 for serial
parameter MUL_COUNT = 11; //11 for parallel multiplier, 34 for serial
parameter FRAC_WIDTH = 23;
parameter EXP_WIDTH = 8;
parameter ZERO_VECTOR = 31'd0;
parameter INF = 31'b1111111100000000000000000000000;
parameter QNAN = 31'b1111111110000000000000000000000;
parameter SNAN = 31'b1111111100000000000000000000001;
 
input clk_i;
input [FP_WIDTH-1:0] opa_i;
input [FP_WIDTH-1:0] opb_i;
output reg [EXP_WIDTH+1:0] exp_10_o;
output [2*(FRAC_WIDTH+2)-1:0] dvdnd_50_o;
output [FRAC_WIDTH+3:0] dvsor_27_o;
 
wire [EXP_WIDTH-1:0] s_expa;
wire [EXP_WIDTH-1:0] s_expb;
wire [FRAC_WIDTH-1:0] s_fracta;
wire [FRAC_WIDTH-1:0] s_fractb;
wire [2*(FRAC_WIDTH+2)-1:0] s_dvdnd_50_o;
wire [FRAC_WIDTH+3:0] s_dvsor_27_o;
reg [5:0] s_dvd_zeros;
reg [5:0] s_div_zeros;
reg [EXP_WIDTH+1:0] s_exp_10_o;
reg [EXP_WIDTH+1:0] s_expa_in;
reg [EXP_WIDTH+1:0] s_expb_in;
wire s_opa_dn, s_opb_dn;
wire [FRAC_WIDTH:0] s_fracta_24;
wire [FRAC_WIDTH:0] s_fractb_24;
 
assign s_expa = opa_i[30:23];
assign s_expb = opb_i[30:23];
assign s_fracta = opa_i[22:0];
assign s_fractb = opb_i[22:0];
assign dvdnd_50_o = s_dvdnd_50_o;
assign dvsor_27_o = s_dvsor_27_o;
// Output Register
always @(posedge clk_i)
exp_10_o <= s_exp_10_o;
 
assign s_opa_dn = !(|s_expa);
assign s_opb_dn = !(|s_expb);
assign s_fracta_24 = {!s_opa_dn,s_fracta};
assign s_fractb_24 = {!s_opb_dn,s_fractb};
// count leading zeros
//s_dvd_zeros <= count_l_zeros( s_fracta_24 );
always @(s_fracta_24)
casex(s_fracta_24) // synopsys full_case parallel_case
24'b1???????????????????????: s_dvd_zeros <= 0;
24'b01??????????????????????: s_dvd_zeros <= 1;
24'b001?????????????????????: s_dvd_zeros <= 2;
24'b0001????????????????????: s_dvd_zeros <= 3;
24'b00001???????????????????: s_dvd_zeros <= 4;
24'b000001??????????????????: s_dvd_zeros <= 5;
24'b0000001?????????????????: s_dvd_zeros <= 6;
24'b00000001????????????????: s_dvd_zeros <= 7;
24'b000000001???????????????: s_dvd_zeros <= 8;
24'b0000000001??????????????: s_dvd_zeros <= 9;
24'b00000000001?????????????: s_dvd_zeros <= 10;
24'b000000000001????????????: s_dvd_zeros <= 11;
24'b0000000000001???????????: s_dvd_zeros <= 12;
24'b00000000000001??????????: s_dvd_zeros <= 13;
24'b000000000000001?????????: s_dvd_zeros <= 14;
24'b0000000000000001????????: s_dvd_zeros <= 15;
24'b00000000000000001???????: s_dvd_zeros <= 16;
24'b000000000000000001??????: s_dvd_zeros <= 17;
24'b0000000000000000001?????: s_dvd_zeros <= 18;
24'b00000000000000000001????: s_dvd_zeros <= 19;
24'b000000000000000000001???: s_dvd_zeros <= 20;
24'b0000000000000000000001??: s_dvd_zeros <= 21;
24'b00000000000000000000001?: s_dvd_zeros <= 22;
24'b000000000000000000000001: s_dvd_zeros <= 23;
24'b000000000000000000000000: s_dvd_zeros <= 24;
endcase
 
//s_div_zeros <= count_l_zeros( s_fractb_24 );
always @(s_fractb_24)
casex(s_fractb_24) // synopsys full_case parallel_case
24'b1???????????????????????: s_div_zeros <= 0;
24'b01??????????????????????: s_div_zeros <= 1;
24'b001?????????????????????: s_div_zeros <= 2;
24'b0001????????????????????: s_div_zeros <= 3;
24'b00001???????????????????: s_div_zeros <= 4;
24'b000001??????????????????: s_div_zeros <= 5;
24'b0000001?????????????????: s_div_zeros <= 6;
24'b00000001????????????????: s_div_zeros <= 7;
24'b000000001???????????????: s_div_zeros <= 8;
24'b0000000001??????????????: s_div_zeros <= 9;
24'b00000000001?????????????: s_div_zeros <= 10;
24'b000000000001????????????: s_div_zeros <= 11;
24'b0000000000001???????????: s_div_zeros <= 12;
24'b00000000000001??????????: s_div_zeros <= 13;
24'b000000000000001?????????: s_div_zeros <= 14;
24'b0000000000000001????????: s_div_zeros <= 15;
24'b00000000000000001???????: s_div_zeros <= 16;
24'b000000000000000001??????: s_div_zeros <= 17;
24'b0000000000000000001?????: s_div_zeros <= 18;
24'b00000000000000000001????: s_div_zeros <= 19;
24'b000000000000000000001???: s_div_zeros <= 20;
24'b0000000000000000000001??: s_div_zeros <= 21;
24'b00000000000000000000001?: s_div_zeros <= 22;
24'b000000000000000000000001: s_div_zeros <= 23;
24'b000000000000000000000000: s_div_zeros <= 24;
endcase
 
// left-shift the dividend and divisor
wire [FRAC_WIDTH:0] fracta_lshift_intermediate;
wire [FRAC_WIDTH:0] fractb_lshift_intermediate;
assign fracta_lshift_intermediate = s_fracta_24 << s_dvd_zeros;
assign fractb_lshift_intermediate = s_fractb_24 << s_div_zeros;
assign s_dvdnd_50_o = {fracta_lshift_intermediate,26'd0};
assign s_dvsor_27_o = {3'd0,fractb_lshift_intermediate};
always @(posedge clk_i)
begin
// pre-calculate exponent
s_expa_in <= {2'd0,s_expa} + {9'd0,s_opa_dn};
s_expb_in <= {2'd0,s_expb} + {9'd0,s_opb_dn};
s_exp_10_o <= s_expa_in - s_expb_in + 10'b0001111111 -
{4'd0,s_dvd_zeros} + {4'd0,s_div_zeros};
end
 
endmodule // or1200_fpu_pre_norm_div
 
/verilog/or1200_sb.v
3,7 → 3,7
//// OR1200's Store Buffer ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Implements store buffer. ////
41,20 → 41,11
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_sb.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// Minor update:
// Bugs fixed.
//
// Revision 1.2 2002/08/22 02:18:55 lampret
// Store buffer has been tested and it works. BY default it is still disabled until uClinux confirms correct operation on FPGA board.
//
// Revision 1.1 2002/08/18 19:53:08 lampret
// Added store buffer.
//
//
 
// synopsys translate_off
`include "timescale.v"
162,9 → 153,9
if (rst)
sb_en_reg <= 1'b0;
else if (sb_en & ~dcsb_cyc_i)
sb_en_reg <= #1 1'b1; // enable SB when there is no dcsb transfer in progress
sb_en_reg <= 1'b1; // enable SB when there is no dcsb transfer in progress
else if (~sb_en & (~fifo_empty | (fifo_empty & outstanding_store)))
sb_en_reg <= #1 1'b0; // disable SB when there is no pending transfers from SB
sb_en_reg <= 1'b0; // disable SB when there is no pending transfers from SB
 
//
// Store buffer FIFO instantiation
185,11 → 176,11
//
always @(posedge clk or posedge rst)
if (rst)
outstanding_store <= #1 1'b0;
outstanding_store <= 1'b0;
else if (sbbiu_ack_i)
outstanding_store <= #1 1'b0;
outstanding_store <= 1'b0;
else if (sel_sb | fifo_wr)
outstanding_store <= #1 1'b1;
outstanding_store <= 1'b1;
 
//
// fifo_wr_ack
196,11 → 187,11
//
always @(posedge clk or posedge rst)
if (rst)
fifo_wr_ack <= #1 1'b0;
fifo_wr_ack <= 1'b0;
else if (fifo_wr)
fifo_wr_ack <= #1 1'b1;
fifo_wr_ack <= 1'b1;
else
fifo_wr_ack <= #1 1'b0;
fifo_wr_ack <= 1'b0;
 
`else // !OR1200_SB_IMPLEMENTED
 
/verilog/or1200_dpram_32x32.v
311,9 → 311,9
 
always @(posedge clk_a or posedge rst_a)
if (rst_a)
addr_a_r <= #1 5'b00000;
addr_a_r <= 5'b00000;
else if (ce_a)
addr_a_r <= #1 addr_a;
addr_a_r <= addr_a;
 
//
// Block 0
534,9 → 534,9
//
always @(posedge clk_a or posedge rst_a)
if (rst_a)
addr_a_reg <= #1 {aw{1'b0}};
addr_a_reg <= {aw{1'b0}};
else if (ce_a)
addr_a_reg <= #1 addr_a;
addr_a_reg <= addr_a;
 
//
// RAM write
543,7 → 543,7
//
always @(posedge clk_b)
if (ce_b && we_b)
mem[addr_b] <= #1 di_b;
mem[addr_b] <= di_b;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_sb_fifo.v
96,55 → 96,55
 
always @(posedge clk_i or posedge rst_i)
if (rst_i) begin
full_o <= #1 1'b0;
empty_o <= #1 1'b1;
wr_pntr <= #1 {fw{1'b0}};
rd_pntr <= #1 {fw{1'b0}};
cntr <= #1 {fw+2{1'b0}};
dat_o <= #1 {dw{1'b0}};
full_o <= 1'b0;
empty_o <= 1'b1;
wr_pntr <= {fw{1'b0}};
rd_pntr <= {fw{1'b0}};
cntr <= {fw+2{1'b0}};
dat_o <= {dw{1'b0}};
end
else if (wr_i && rd_i) begin // FIFO Read and Write
mem[wr_pntr] <= #1 dat_i;
mem[wr_pntr] <= dat_i;
if (wr_pntr >= fl-1)
wr_pntr <= #1 {fw{1'b0}};
wr_pntr <= {fw{1'b0}};
else
wr_pntr <= #1 wr_pntr + 1'b1;
wr_pntr <= wr_pntr + 1'b1;
if (empty_o) begin
dat_o <= #1 dat_i;
dat_o <= dat_i;
end
else begin
dat_o <= #1 mem[rd_pntr];
dat_o <= mem[rd_pntr];
end
if (rd_pntr >= fl-1)
rd_pntr <= #1 {fw{1'b0}};
rd_pntr <= {fw{1'b0}};
else
rd_pntr <= #1 rd_pntr + 1'b1;
rd_pntr <= rd_pntr + 1'b1;
end
else if (wr_i && !full_o) begin // FIFO Write
mem[wr_pntr] <= #1 dat_i;
cntr <= #1 cntr + 1'b1;
empty_o <= #1 1'b0;
mem[wr_pntr] <= dat_i;
cntr <= cntr + 1'b1;
empty_o <= 1'b0;
if (cntr >= (fl-1)) begin
full_o <= #1 1'b1;
cntr <= #1 fl;
full_o <= 1'b1;
cntr <= fl;
end
if (wr_pntr >= fl-1)
wr_pntr <= #1 {fw{1'b0}};
wr_pntr <= {fw{1'b0}};
else
wr_pntr <= #1 wr_pntr + 1'b1;
wr_pntr <= wr_pntr + 1'b1;
end
else if (rd_i && !empty_o) begin // FIFO Read
dat_o <= #1 mem[rd_pntr];
cntr <= #1 cntr - 1'b1;
full_o <= #1 1'b0;
dat_o <= mem[rd_pntr];
cntr <= cntr - 1'b1;
full_o <= 1'b0;
if (cntr <= 1) begin
empty_o <= #1 1'b1;
cntr <= #1 {fw+2{1'b0}};
empty_o <= 1'b1;
cntr <= {fw+2{1'b0}};
end
if (rd_pntr >= fl-1)
rd_pntr <= #1 {fw{1'b0}};
rd_pntr <= {fw{1'b0}};
else
rd_pntr <= #1 rd_pntr + 1'b1;
rd_pntr <= rd_pntr + 1'b1;
end
 
endmodule
/verilog/or1200_fpu_pre_norm_mul.v
0,0 → 1,107
//////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_pre_norm_mul ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// pre-normalization entity for the multiplication unit ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Original design (FPU100) - ////
//// Jidan Al-eryani, jidan@gmx.net ////
//// - Conv. to Verilog and inclusion in OR1200 - ////
//// Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2006, 2010
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
module or1200_fpu_pre_norm_mul (
clk_i,
opa_i,
opb_i,
exp_10_o,
fracta_24_o,
fractb_24_o
);
 
parameter FP_WIDTH = 32;
parameter MUL_SERIAL = 0; // 0 for parallel multiplier, 1 for serial
parameter MUL_COUNT = 11; //11 for parallel multiplier, 34 for serial
parameter FRAC_WIDTH = 23;
parameter EXP_WIDTH = 8;
parameter ZERO_VECTOR = 31'd0;
parameter INF = 31'b1111111100000000000000000000000;
parameter QNAN = 31'b1111111110000000000000000000000;
parameter SNAN = 31'b1111111100000000000000000000001;
 
 
input clk_i;
input [FP_WIDTH-1:0] opa_i;
input [FP_WIDTH-1:0] opb_i;
output reg [EXP_WIDTH+1:0] exp_10_o;
output [FRAC_WIDTH:0] fracta_24_o;
output [FRAC_WIDTH:0] fractb_24_o;
 
wire [EXP_WIDTH-1:0] s_expa;
wire [EXP_WIDTH-1:0] s_expb;
wire [FRAC_WIDTH-1:0] s_fracta;
wire [FRAC_WIDTH-1:0] s_fractb;
 
wire [EXP_WIDTH+1:0] s_exp_10_o;
wire [EXP_WIDTH+1:0] s_expa_in;
wire [EXP_WIDTH+1:0] s_expb_in;
wire s_opa_dn, s_opb_dn;
 
assign s_expa = opa_i[30:23];
assign s_expb = opb_i[30:23];
assign s_fracta = opa_i[22:0];
assign s_fractb = opb_i[22:0];
// Output Register
always @(posedge clk_i)
exp_10_o <= s_exp_10_o;
// opa or opb is denormalized
assign s_opa_dn = !(|s_expa);
assign s_opb_dn = !(|s_expb);
assign fracta_24_o = {!s_opa_dn, s_fracta};
assign fractb_24_o = {!s_opb_dn, s_fractb};
assign s_expa_in = {2'd0, s_expa} + {9'd0, s_opa_dn};
assign s_expb_in = {2'd0, s_expb} + {9'd0, s_opb_dn};
assign s_exp_10_o = s_expa_in + s_expb_in - 10'b0001111111;
 
endmodule // or1200_fpu_pre_norm_mul
 
 
/verilog/or1200_spram_256x21.v
401,9 → 401,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
 
//
// RAM write
410,7 → 410,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_fpu_post_norm_addsub.v
0,0 → 1,282
//////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_post_norm_addsub ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// post-normalization entity for the addition/subtraction unit ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Original design (FPU100) - ////
//// Jidan Al-eryani, jidan@gmx.net ////
//// - Conv. to Verilog and inclusion in OR1200 - ////
//// Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2006, 2010
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
module or1200_fpu_post_norm_addsub
(
clk_i,
opa_i,
opb_i,
fract_28_i,
exp_i,
sign_i,
fpu_op_i,
rmode_i,
output_o,
ine_o
);
parameter FP_WIDTH = 32;
parameter MUL_SERIAL = 0; // 0 for parallel multiplier, 1 for serial
parameter MUL_COUNT = 11; //11 for parallel multiplier, 34 for serial
parameter FRAC_WIDTH = 23;
parameter EXP_WIDTH = 8;
parameter ZERO_VECTOR = 31'd0;
parameter INF = 31'b1111111100000000000000000000000;
parameter QNAN = 31'b1111111110000000000000000000000;
parameter SNAN = 31'b1111111100000000000000000000001;
 
input clk_i;
input [FP_WIDTH-1:0] opa_i;
input [FP_WIDTH-1:0] opb_i;
input [FRAC_WIDTH+4:0] fract_28_i;
input [EXP_WIDTH-1:0] exp_i;
input sign_i;
input fpu_op_i;
input [1:0] rmode_i;
output reg [FP_WIDTH-1:0] output_o;
output reg ine_o;
wire [FP_WIDTH-1:0] s_opa_i;
wire [FP_WIDTH-1:0] s_opb_i;
wire [FRAC_WIDTH+4:0] s_fract_28_i;
wire [EXP_WIDTH-1:0] s_exp_i;
wire s_sign_i;
wire s_fpu_op_i;
wire [1:0] s_rmode_i;
wire [FP_WIDTH-1:0] s_output_o;
wire s_ine_o;
wire s_overflow;
wire [5:0] s_zeros;
reg [5:0] s_shr1;
reg [5:0] s_shl1;
wire s_shr2, s_carry;
 
wire [9:0] s_exp10;
reg [EXP_WIDTH:0] s_expo9_1;
wire [EXP_WIDTH:0] s_expo9_2;
wire [EXP_WIDTH:0] s_expo9_3;
reg [FRAC_WIDTH+4:0] s_fracto28_1;
wire [FRAC_WIDTH+4:0] s_fracto28_2;
wire [FRAC_WIDTH+4:0] s_fracto28_rnd;
 
wire s_roundup;
wire s_sticky;
wire s_zero_fract;
wire s_lost;
wire s_infa, s_infb;
wire s_nan_in, s_nan_op, s_nan_a, s_nan_b, s_nan_sign;
assign s_opa_i = opa_i;
assign s_opb_i = opb_i;
assign s_fract_28_i = fract_28_i;
assign s_exp_i = exp_i;
assign s_sign_i = sign_i;
assign s_fpu_op_i = fpu_op_i;
assign s_rmode_i = rmode_i;
// Output Register
always @(posedge clk_i)
begin
output_o <= s_output_o;
ine_o <= s_ine_o;
end
//*** Stage 1 ****
// figure out the output exponent and how much the fraction has to be
// shiftd right/left
assign s_carry = s_fract_28_i[27];
 
reg [5:0] lzeroes;
always @(s_fract_28_i)
casex(s_fract_28_i[26:0]) // synopsys full_case parallel_case
27'b1??????????????????????????: lzeroes <= 0;
27'b01?????????????????????????: lzeroes <= 1;
27'b001????????????????????????: lzeroes <= 2;
27'b0001???????????????????????: lzeroes <= 3;
27'b00001??????????????????????: lzeroes <= 4;
27'b000001?????????????????????: lzeroes <= 5;
27'b0000001????????????????????: lzeroes <= 6;
27'b00000001???????????????????: lzeroes <= 7;
27'b000000001??????????????????: lzeroes <= 8;
27'b0000000001?????????????????: lzeroes <= 9;
27'b00000000001????????????????: lzeroes <= 10;
27'b000000000001???????????????: lzeroes <= 11;
27'b0000000000001??????????????: lzeroes <= 12;
27'b00000000000001?????????????: lzeroes <= 13;
27'b000000000000001????????????: lzeroes <= 14;
27'b0000000000000001???????????: lzeroes <= 15;
27'b00000000000000001??????????: lzeroes <= 16;
27'b000000000000000001?????????: lzeroes <= 17;
27'b0000000000000000001????????: lzeroes <= 18;
27'b00000000000000000001???????: lzeroes <= 19;
27'b000000000000000000001??????: lzeroes <= 20;
27'b0000000000000000000001?????: lzeroes <= 21;
27'b00000000000000000000001????: lzeroes <= 22;
27'b000000000000000000000001???: lzeroes <= 23;
27'b0000000000000000000000001??: lzeroes <= 24;
27'b00000000000000000000000001?: lzeroes <= 25;
27'b000000000000000000000000001: lzeroes <= 26;
27'b000000000000000000000000000: lzeroes <= 27;
endcase
 
assign s_zeros = s_fract_28_i[27] ? 0 : lzeroes;
// negative flag & large flag & exp
assign s_exp10 = {2'd0,s_exp_i} + {9'd0,s_carry} - {4'd0,s_zeros};
always @(posedge clk_i)
begin
if (s_exp10[9] | !(|s_exp10))
begin
s_shr1 <= 0;
s_expo9_1 <= 9'd1;
if (|s_exp_i)
s_shl1 <= s_exp_i[5:0] - 6'd1;
else
s_shl1 <= 0;
end
else if (s_exp10[8])
begin
s_shr1 <= 0;
s_shl1 <= 0;
s_expo9_1 <= 9'b011111111;
end
else
begin
s_shr1 <= {5'd0,s_carry};
s_shl1 <= s_zeros;
s_expo9_1 <= s_exp10[8:0];
end // else: !if(s_exp10[8])
end // always @ (posedge clk_i)
//-
// *** Stage 2 ***
// Shifting the fraction and rounding
always @(posedge clk_i)
if (|s_shr1)
s_fracto28_1 <= s_fract_28_i >> s_shr1;
else
s_fracto28_1 <= s_fract_28_i << s_shl1;
assign s_expo9_2 = (s_fracto28_1[27:26]==2'b00) ?
s_expo9_1 - 9'd1 : s_expo9_1;
// round
//check last bit, before and after right-shift
assign s_sticky = s_fracto28_1[0] | (s_fract_28_i[0] & s_fract_28_i[27]);
assign s_roundup = s_rmode_i==2'b00 ?
// round to nearset even
s_fracto28_1[2] & ((s_fracto28_1[1] | s_sticky) |
s_fracto28_1[3]) :
s_rmode_i==2'b10 ?
// round up
(s_fracto28_1[2] | s_fracto28_1[1] | s_sticky) & !s_sign_i:
s_rmode_i==2'b11 ?
// round down
(s_fracto28_1[2] | s_fracto28_1[1] | s_sticky) & s_sign_i :
// round to zero(truncate = no rounding)
0;
assign s_fracto28_rnd = s_roundup ?
s_fracto28_1+28'b0000_0000_0000_0000_0000_0000_1000 :
s_fracto28_1;
// ***Stage 3***
// right-shift after rounding (if necessary)
assign s_shr2 = s_fracto28_rnd[27];
 
assign s_expo9_3 = (s_shr2 & s_expo9_2!=9'b011111111) ?
s_expo9_2 + 9'b000000001 : s_expo9_2;
 
assign s_fracto28_2 = s_shr2 ? {1'b0,s_fracto28_rnd[27:1]} : s_fracto28_rnd;
 
////-
assign s_infa = &s_opa_i[30:23];
assign s_infb = &s_opb_i[30:23];
assign s_nan_a = s_infa & (|s_opa_i[22:0]);
assign s_nan_b = s_infb & (|s_opb_i[22:0]);
assign s_nan_in = s_nan_a | s_nan_b;
 
// inf-inf=Nan
assign s_nan_op = (s_infa & s_infb) &
(s_opa_i[31] ^ (s_fpu_op_i ^ s_opb_i[31]));
assign s_nan_sign = (s_nan_a & s_nan_b) ? s_sign_i :
s_nan_a ?
s_opa_i[31] : s_opb_i[31];
// check if result is inexact;
assign s_lost = (s_shr1[0] & s_fract_28_i[0]) |
(s_shr2 & s_fracto28_rnd[0]) | (|s_fracto28_2[2:0]);
 
assign s_ine_o = (s_lost | s_overflow) & !(s_infa | s_infb);
assign s_overflow = s_expo9_3==9'b011111111 & !(s_infa | s_infb);
 
// '1' if fraction result is zero
assign s_zero_fract = s_zeros==27 & !s_fract_28_i[27];
 
// Generate result
assign s_output_o = (s_nan_in | s_nan_op) ?
{s_nan_sign,QNAN} :
(s_infa | s_infb) | s_overflow ?
{s_sign_i,INF} :
s_zero_fract ?
{s_sign_i,ZERO_VECTOR} :
{s_sign_i,s_expo9_3[7:0],s_fracto28_2[25:3]};
 
endmodule // or1200_fpu_post_norm_addsub
 
 
/verilog/or1200_spram_2048x8.v
411,9 → 411,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
 
//
// RAM write
420,7 → 420,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_fpu_arith.v
0,0 → 1,433
//////////////////////////////////////////////////////////////////////
//// ////
//// OR1200 FPU arith ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Wrapper for floating point arithmetic units. ////
//// ////
//// To Do: ////
//// - lf.rem.s and lf.madd.s instruction support ////
//// ////
//// Author(s): ////
//// - Original design (FPU100) - ////
//// Jidan Al-eryani, jidan@gmx.net ////
//// - Conv. to Verilog and inclusion in OR1200 - ////
//// Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2006, 2010
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
module or1200_fpu_arith
(
clk_i,
opa_i,
opb_i,
fpu_op_i,
rmode_i,
output_o,
start_i,
ready_o,
ine_o,
overflow_o,
underflow_o,
div_zero_o,
inf_o,
zero_o,
qnan_o,
snan_o
);
 
parameter FP_WIDTH = 32;
parameter MUL_SERIAL = 1; // 0 for parallel multiplier, 1 for serial
parameter MUL_COUNT = 34; //11 for parallel multiplier, 34 for serial
parameter FRAC_WIDTH = 23;
parameter EXP_WIDTH = 8;
parameter ZERO_VECTOR = 31'd0;
parameter INF = 31'b1111111100000000000000000000000;
parameter QNAN = 31'b11111111_10000000000000000000000;
parameter SNAN = 31'b11111111_00000000000000000000001;
 
// fpu operations (fpu_op_i):
// ========================
// 000 = add,
// 001 = substract,
// 010 = multiply,
// 011 = divide,
// 100 = square root - DISABLED - JPB
// 101 = unused
// 110 = unused
// 111 = unused
 
// Rounding Mode:
// ==============
// 00 = round to nearest even (default),
// 01 = round to zero,
// 10 = round up,
// 11 = round down
input clk_i;
input [FP_WIDTH-1:0] opa_i;
input [FP_WIDTH-1:0] opb_i;
input [2:0] fpu_op_i;
input [1:0] rmode_i;
input start_i;
output reg ready_o;
output reg [FP_WIDTH-1:0] output_o;
output reg ine_o;
output reg overflow_o;
output reg underflow_o;
output reg div_zero_o;
output reg inf_o;
output reg zero_o;
output reg qnan_o;
output reg snan_o;
 
reg [FP_WIDTH-1:0] s_opa_i;
reg [FP_WIDTH-1:0] s_opb_i;
reg [2:0] s_fpu_op_i;
reg [1:0] s_rmode_i;
reg s_start_i;
reg [5:0] s_count; // Max value of 64
 
reg [FP_WIDTH-1:0] s_output1;
reg [FP_WIDTH-1:0] s_output_o; // Comb
reg s_ine_o;
wire s_overflow_o,
s_underflow_o,
s_div_zero_o,
s_inf_o, s_zero_o, s_qnan_o, s_snan_o;
 
wire s_infa, s_infb;
parameter t_state_waiting = 0,
t_state_busy = 1;
reg s_state;
//// ***Add/Substract units signals***
wire [27:0] prenorm_addsub_fracta_28_o;
wire [27:0] prenorm_addsub_fractb_28_o;
wire [7:0] prenorm_addsub_exp_o;
wire [27:0] addsub_fract_o;
wire addsub_sign_o;
wire [31:0] postnorm_addsub_output_o;
wire postnorm_addsub_ine_o;
//// ***Multiply units signals***
wire [9:0] pre_norm_mul_exp_10;
wire [23:0] pre_norm_mul_fracta_24 ;
wire [23:0] pre_norm_mul_fractb_24 ;
wire [47:0] mul_fract_48;
wire [47:0] mul_24_fract_48;
wire mul_24_sign;
wire [47:0] serial_mul_fract_48;
wire serial_mul_sign;
wire mul_sign;
wire [31:0] post_norm_mul_output ;
wire post_norm_mul_ine;
//// ***Division units signals***
wire [49:0] pre_norm_div_dvdnd;
wire [26:0] pre_norm_div_dvsor;
wire [EXP_WIDTH+1:0] pre_norm_div_exp;
wire [26:0] serial_div_qutnt;
wire [26:0] serial_div_rmndr;
wire serial_div_sign;
wire serial_div_div_zero;
wire [31:0] post_norm_div_output;
wire post_norm_div_ine;
//// ***Square units***
wire [51:0] pre_norm_sqrt_fracta_o;
wire [7:0] pre_norm_sqrt_exp_o;
wire [25:0] sqrt_sqr_o;
wire sqrt_ine_o;
wire [31:0] post_norm_sqrt_output ;
wire post_norm_sqrt_ine_o;
//***Add/Substract units***
or1200_fpu_pre_norm_addsub fpu_prenorm_addsub
(
.clk_i(clk_i) ,
.opa_i(s_opa_i) ,
.opb_i(s_opb_i) ,
.fracta_28_o(prenorm_addsub_fracta_28_o) ,
.fractb_28_o(prenorm_addsub_fractb_28_o) ,
.exp_o(prenorm_addsub_exp_o) );
or1200_fpu_addsub fpu_addsub
(
.clk_i(clk_i) ,
.fpu_op_i(s_fpu_op_i[0]),
.fracta_i(prenorm_addsub_fracta_28_o) ,
.fractb_i(prenorm_addsub_fractb_28_o) ,
.signa_i( s_opa_i[31]),
.signb_i( s_opb_i[31]),
.fract_o(addsub_fract_o) ,
.sign_o(addsub_sign_o) );
or1200_fpu_post_norm_addsub fpu_postnorm_addsub
(
.clk_i(clk_i) ,
.opa_i(s_opa_i) ,
.opb_i(s_opb_i) ,
.fract_28_i(addsub_fract_o) ,
.exp_i(prenorm_addsub_exp_o) ,
.sign_i(addsub_sign_o) ,
.fpu_op_i(s_fpu_op_i[0]),
.rmode_i(s_rmode_i) ,
.output_o(postnorm_addsub_output_o) ,
.ine_o(postnorm_addsub_ine_o)
);
//***Multiply units***
or1200_fpu_pre_norm_mul fpu_pre_norm_mul
(
.clk_i(clk_i),
.opa_i(s_opa_i),
.opb_i(s_opb_i),
.exp_10_o(pre_norm_mul_exp_10),
.fracta_24_o(pre_norm_mul_fracta_24),
.fractb_24_o(pre_norm_mul_fractb_24));
/*
mul_24 i_mul_24
(
.clk_i(clk_i) ,
.fracta_i(pre_norm_mul_fracta_24) ,
.fractb_i(pre_norm_mul_fractb_24) ,
.signa_i(s_opa_i[31]),
.signb_i(s_opb_i[31]),
.start_i(start_i) ,
.fract_o(mul_24_fract_48) ,
.sign_o(mul_24_sign) ,
.ready_o() );
*/
// Serial multiply is default and only one included here
or1200_fpu_mul fpu_mul
(
.clk_i(clk_i) ,
.fracta_i(pre_norm_mul_fracta_24) ,
.fractb_i(pre_norm_mul_fractb_24) ,
.signa_i(s_opa_i[31]),
.signb_i(s_opb_i[31]),
.start_i(s_start_i) ,
.fract_o(serial_mul_fract_48) ,
.sign_o(serial_mul_sign) ,
.ready_o()
);
// Serial or parallel multiplier will be chosen depending on constant
// MUL_SERIAL
assign mul_fract_48 = MUL_SERIAL ? serial_mul_fract_48 : mul_24_fract_48;
assign mul_sign = MUL_SERIAL ? serial_mul_sign : mul_24_sign;
or1200_fpu_post_norm_mul fpu_post_norm_mul
(
.clk_i(clk_i) ,
.opa_i(s_opa_i) ,
.opb_i(s_opb_i) ,
.exp_10_i(pre_norm_mul_exp_10) ,
.fract_48_i(mul_fract_48) , // Parallel multiplier input
.sign_i(mul_sign) , // Parallel multiplier input
.rmode_i(s_rmode_i) ,
.output_o(post_norm_mul_output) ,
.ine_o(post_norm_mul_ine)
);
////***Division units***
or1200_fpu_pre_norm_div fpu_pre_norm_div
(
.clk_i(clk_i) ,
.opa_i(s_opa_i) ,
.opb_i(s_opb_i) ,
.exp_10_o(pre_norm_div_exp) ,
.dvdnd_50_o(pre_norm_div_dvdnd) ,
.dvsor_27_o(pre_norm_div_dvsor) );
or1200_fpu_div fpu_div
(
.clk_i(clk_i) ,
.dvdnd_i(pre_norm_div_dvdnd) ,
.dvsor_i(pre_norm_div_dvsor) ,
.sign_dvd_i(s_opa_i[31]),
.sign_div_i(s_opb_i[31]),
.start_i(s_start_i) ,
.ready_o() ,
.qutnt_o(serial_div_qutnt) ,
.rmndr_o(serial_div_rmndr) ,
.sign_o(serial_div_sign) ,
.div_zero_o(serial_div_div_zero) );
or1200_fpu_post_norm_div fpu_post_norm_div
(
.clk_i(clk_i) ,
.opa_i(s_opa_i) ,
.opb_i(s_opb_i) ,
.qutnt_i(serial_div_qutnt) ,
.rmndr_i(serial_div_rmndr) ,
.exp_10_i(pre_norm_div_exp) ,
.sign_i(serial_div_sign) ,
.rmode_i(s_rmode_i) ,
.output_o(post_norm_div_output) ,
.ine_o(post_norm_div_ine) );
//////////////////////////////////////////////////////////////////-
 
// Input Registers
always @(posedge clk_i)
begin
s_opa_i <= opa_i;
s_opb_i <= opb_i;
s_fpu_op_i <= fpu_op_i;
s_rmode_i <= rmode_i;
s_start_i <= start_i;
end
// Output registers
always @(posedge clk_i)
begin
output_o <= s_output_o;
ine_o <= s_ine_o;
overflow_o <= s_overflow_o;
underflow_o <= s_underflow_o;
div_zero_o <= s_div_zero_o & !s_infa;
inf_o <= s_inf_o;
zero_o <= s_zero_o;
qnan_o <= s_qnan_o;
snan_o <= s_snan_o;
end
 
always @(posedge clk_i)
begin
if (s_start_i) begin
s_state <= t_state_busy;
s_count <= 0;
end
else if (s_state == t_state_busy) begin
// Ready cases
if (((s_count == 6) & ((fpu_op_i==3'd0) | (fpu_op_i==3'd1))) |
((s_count==MUL_COUNT) & (fpu_op_i==3'd2)) |
((s_count==33) & (fpu_op_i==3'd3)))
begin
s_state <= t_state_waiting;
ready_o <= 1;
s_count <= 0;
end
else
s_count <= s_count + 1;
end // if (s_state == t_state_busy)
else begin
s_state <= t_state_waiting;
ready_o <= 0;
end // else: !if(s_state == t_state_busy)
end // else: !if(s_start_i)
//// Output Multiplexer
always @(posedge clk_i)
begin
case(fpu_op_i)
3'd0,
3'd1: begin
s_output1 <= postnorm_addsub_output_o;
s_ine_o <= postnorm_addsub_ine_o;
end
3'd2: begin
s_output1 <= post_norm_mul_output;
s_ine_o <= post_norm_mul_ine;
end
3'd3: begin
s_output1 <= post_norm_div_output;
s_ine_o <= post_norm_div_ine;
end
// 3'd4: begin
// s_output1 <= post_norm_sqrt_output;
// s_ine_o <= post_norm_sqrt_ine_o;
// end
default: begin
s_output1 <= 0;
s_ine_o <= 0;
end
endcase // case (fpu_op_i)
end // always @ (posedge clk_i)
// Infinte exponent
assign s_infa = &s_opa_i[30:23];
assign s_infb = &s_opb_i[30:23];
 
always @*
begin
if (s_rmode_i==2'd0 | s_div_zero_o | s_infa | s_infb | s_qnan_o |
s_qnan_o) // Round to nearest even
s_output_o <= s_output1;
else if (s_rmode_i==2'd1 & (&s_output1[30:23]))
// In round-to-zero: the sum of two non-infinity operands is never
// infinity,even if an overflow occures
s_output_o <= {s_output1[31], 31'b1111111_01111111_11111111_11111111};
else if (s_rmode_i==2'd2 & (&s_output1[31:23]))
// In round-up: the sum of two non-infinity operands is never
// negative infinity,even if an overflow occures
s_output_o <= {32'b11111111_01111111_11111111_11111111};
else if (s_rmode_i==2'd3) begin
if (((s_fpu_op_i==3'd0) | (s_fpu_op_i==3'd1)) & s_zero_o &
(s_opa_i[31] | (s_fpu_op_i[0] ^ s_opb_i[31])))
// In round-down: a-a= -0
s_output_o <= {1'b1,s_output1[30:0]};
else if (s_output1[31:23]==9'b0_11111111)
s_output_o <= 32'b01111111011111111111111111111111;
else
s_output_o <= s_output1;
end
else
s_output_o <= s_output1;
end // always @ *
 
// Exception generation
assign s_underflow_o = (s_output1[30:23]==8'h00) & s_ine_o;
assign s_overflow_o = (s_output1[30:23]==8'hff) & s_ine_o;
assign s_div_zero_o = serial_div_div_zero & fpu_op_i==3'd3;
assign s_inf_o = s_output1[31:23]==8'hff & !(s_qnan_o | s_snan_o);
assign s_zero_o = !(|s_output1[30:0]);
assign s_qnan_o = s_output1[30:0]==QNAN;
assign s_snan_o = s_output1[30:0]==SNAN;
 
endmodule // or1200_fpu_arith
 
 
/verilog/or1200_tpram_32x32.v
389,7 → 389,7
//
always @(posedge clk_a)
if (ce_a && we_a)
mem[addr_a] <= #1 di_a;
mem[addr_a] <= di_a;
 
//
// RAM write
396,7 → 396,7
//
always @(posedge clk_b)
if (ce_b && we_b)
mem[addr_b] <= #1 di_b;
mem[addr_b] <= di_b;
 
//
// RAM read address register
403,9 → 403,9
//
always @(posedge clk_a or posedge rst_a)
if (rst_a)
addr_a_reg <= #1 {aw{1'b0}};
addr_a_reg <= {aw{1'b0}};
else if (ce_a)
addr_a_reg <= #1 addr_a;
addr_a_reg <= addr_a;
 
//
// RAM read address register
412,9 → 412,9
//
always @(posedge clk_b or posedge rst_b)
if (rst_b)
addr_b_reg <= #1 {aw{1'b0}};
addr_b_reg <= {aw{1'b0}};
else if (ce_b)
addr_b_reg <= #1 addr_b;
addr_b_reg <= addr_b;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_fpu_post_norm_div.v
0,0 → 1,283
//////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_post_norm_div ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// post-normalization entity for the division unit ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Original design (FPU100) - ////
//// Jidan Al-eryani, jidan@gmx.net ////
//// - Conv. to Verilog and inclusion in OR1200 - ////
//// Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2006, 2010
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
 
module or1200_fpu_post_norm_div
(
clk_i,
opa_i,
opb_i,
qutnt_i,
rmndr_i,
exp_10_i,
sign_i,
rmode_i,
output_o,
ine_o
);
 
parameter FP_WIDTH = 32;
parameter MUL_SERIAL = 0; // 0 for parallel multiplier, 1 for serial
parameter MUL_COUNT = 11; //11 for parallel multiplier, 34 for serial
parameter FRAC_WIDTH = 23;
parameter EXP_WIDTH = 8;
parameter ZERO_VECTOR = 31'd0;
parameter INF = 31'b1111111100000000000000000000000;
parameter QNAN = 31'b1111111110000000000000000000000;
parameter SNAN = 31'b1111111100000000000000000000001;
input clk_i;
input [FP_WIDTH-1:0] opa_i;
input [FP_WIDTH-1:0] opb_i;
input [FRAC_WIDTH+3:0] qutnt_i;
input [FRAC_WIDTH+3:0] rmndr_i;
input [EXP_WIDTH+1:0] exp_10_i;
input sign_i;
input [1:0] rmode_i;
output reg [FP_WIDTH-1:0] output_o;
output reg ine_o;
// input&output register wires
reg [FP_WIDTH-1:0] s_opa_i;
reg [FP_WIDTH-1:0] s_opb_i;
reg [EXP_WIDTH-1:0] s_expa;
reg [EXP_WIDTH-1:0] s_expb;
reg [FRAC_WIDTH+3:0] s_qutnt_i;
reg [FRAC_WIDTH+3:0] s_rmndr_i;
reg [5:0] s_r_zeros;
reg [EXP_WIDTH+1:0] s_exp_10_i;
reg s_sign_i;
reg [1:0] s_rmode_i;
wire [FP_WIDTH-1:0] s_output_o;
wire s_ine_o, s_overflow;
wire s_opa_dn, s_opb_dn;
wire s_qutdn;
wire [9:0] s_exp_10b;
reg [5:0] s_shr1;
reg [5:0] s_shl1;
wire s_shr2;
reg [8:0] s_expo1;
wire [8:0] s_expo2;
reg [8:0] s_expo3;
reg [26:0] s_fraco1;
wire [24:0] s_frac_rnd;
reg [24:0] s_fraco2;
wire s_guard, s_round, s_sticky, s_roundup;
wire s_lost;
wire s_op_0, s_opab_0, s_opb_0;
wire s_infa, s_infb;
wire s_nan_in, s_nan_op, s_nan_a, s_nan_b;
wire s_inf_result;
always @(posedge clk_i)
begin
s_opa_i <= opa_i;
s_opb_i <= opb_i;
s_expa <= opa_i[30:23];
s_expb <= opb_i[30:23];
s_qutnt_i <= qutnt_i;
s_rmndr_i <= rmndr_i;
s_exp_10_i <= exp_10_i;
s_sign_i <= sign_i;
s_rmode_i <= rmode_i;
end
 
// Output Register
always @(posedge clk_i)
begin
output_o <= s_output_o;
ine_o <= s_ine_o;
end
 
// qutnt_i
// 26 25 3
// | | |
// h fffffffffffffffffffffff grs
 
//*** Stage 1 ****
// figure out the exponent and how far the fraction has to be shifted
// right or left
assign s_opa_dn = !(|s_expa) & (|opa_i[22:0]);
assign s_opb_dn = !(|s_expb) & (|opb_i[22:0]);
assign s_qutdn = !s_qutnt_i[26];
 
assign s_exp_10b = s_exp_10_i - {9'd0,s_qutdn};
wire [9:0] v_shr;
wire [9:0] v_shl;
assign v_shr = (s_exp_10b[9] | !(|s_exp_10b)) ?
(10'd1 - s_exp_10b) - s_qutdn : 0;
assign v_shl = (s_exp_10b[9] | !(|s_exp_10b)) ?
0 :
s_exp_10b[8] ?
0 : {9'd0,s_qutdn};
 
always @(posedge clk_i)
if (s_exp_10b[9] | !(|s_exp_10b))
s_expo1 <= 9'd1;
else
s_expo1 <= s_exp_10b[8:0];
 
always @(posedge clk_i)
s_shr1 <= v_shr[6] ? 6'b111111 : v_shr[5:0];
 
always @(posedge clk_i)
s_shl1 <= v_shl[5:0];
// *** Stage 2 ***
// Shifting the fraction and rounding
// shift the fraction
always @(posedge clk_i)
if (|s_shr1)
s_fraco1 <= s_qutnt_i >> s_shr1;
else
s_fraco1 <= s_qutnt_i << s_shl1;
assign s_expo2 = s_fraco1[26] ? s_expo1 : s_expo1 - 9'd1;
//s_r_zeros <= count_r_zeros(s_qutnt_i);
always @(s_qutnt_i)
casex(s_qutnt_i) // synopsys full_case parallel_case
27'b??????????????????????????1: s_r_zeros <= 0;
27'b?????????????????????????10: s_r_zeros <= 1;
27'b????????????????????????100: s_r_zeros <= 2;
27'b???????????????????????1000: s_r_zeros <= 3;
27'b??????????????????????10000: s_r_zeros <= 4;
27'b?????????????????????100000: s_r_zeros <= 5;
27'b????????????????????1000000: s_r_zeros <= 6;
27'b???????????????????10000000: s_r_zeros <= 7;
27'b??????????????????100000000: s_r_zeros <= 8;
27'b?????????????????1000000000: s_r_zeros <= 9;
27'b????????????????10000000000: s_r_zeros <= 10;
27'b???????????????100000000000: s_r_zeros <= 11;
27'b??????????????1000000000000: s_r_zeros <= 12;
27'b?????????????10000000000000: s_r_zeros <= 13;
27'b????????????100000000000000: s_r_zeros <= 14;
27'b???????????1000000000000000: s_r_zeros <= 15;
27'b??????????10000000000000000: s_r_zeros <= 16;
27'b?????????100000000000000000: s_r_zeros <= 17;
27'b????????1000000000000000000: s_r_zeros <= 18;
27'b???????10000000000000000000: s_r_zeros <= 19;
27'b??????100000000000000000000: s_r_zeros <= 20;
27'b?????1000000000000000000000: s_r_zeros <= 21;
27'b????10000000000000000000000: s_r_zeros <= 22;
27'b???100000000000000000000000: s_r_zeros <= 23;
27'b??1000000000000000000000000: s_r_zeros <= 24;
27'b?10000000000000000000000000: s_r_zeros <= 25;
27'b100000000000000000000000000: s_r_zeros <= 26;
27'b000000000000000000000000000: s_r_zeros <= 27;
endcase // casex (s_qutnt_i)
assign s_lost = (s_shr1+{5'd0,s_shr2}) > s_r_zeros;
// ***Stage 3***
// Rounding
assign s_guard = s_fraco1[2];
assign s_round = s_fraco1[1];
assign s_sticky = s_fraco1[0] | (|s_rmndr_i);
 
assign s_roundup = s_rmode_i==2'b00 ? // round to nearest even
s_guard & ((s_round | s_sticky) | s_fraco1[3]) :
s_rmode_i==2'b10 ? // round up
(s_guard | s_round | s_sticky) & !s_sign_i :
s_rmode_i==2'b11 ? // round down
(s_guard | s_round | s_sticky) & s_sign_i :
0; // round to zero(truncate = no rounding)
 
assign s_frac_rnd = s_roundup ?{1'b0,s_fraco1[26:3]} + 1 :
{1'b0,s_fraco1[26:3]};
assign s_shr2 = s_frac_rnd[24];
 
always @(posedge clk_i)
begin
s_expo3 <= s_shr2 ? s_expo2 + "1" : s_expo2;
s_fraco2 <= s_shr2 ? {1'b0,s_frac_rnd[24:1]} : s_frac_rnd;
end
//
// ***Stage 4****
// Output
assign s_op_0 = !((|s_opa_i[30:0]) & (|s_opb_i[30:0]));
 
assign s_opab_0 = !((|s_opa_i[30:0]) | (|s_opb_i[30:0]));
 
assign s_opb_0 = !(|s_opb_i[30:0]);
assign s_infa = &s_expa;
assign s_infb = &s_expb;
assign s_nan_a = s_infa & (|s_opa_i[22:0]);
assign s_nan_b = s_infb & (|s_opb_i[22:0]);
assign s_nan_in = s_nan_a | s_nan_b;
assign s_nan_op = (s_infa & s_infb) | s_opab_0; // 0 / 0, inf / inf
 
assign s_inf_result = (&s_expo3[7:0]) | s_expo3[8] | s_opb_0;
 
assign s_overflow = s_inf_result & !(s_infa) & !s_opb_0;
assign s_ine_o = !s_op_0 &
(s_lost | (|s_fraco1[2:0]) | s_overflow | (|s_rmndr_i));
assign s_output_o = (s_nan_in | s_nan_op) ?
{s_sign_i,QNAN} :
s_infa | s_overflow | s_inf_result ?
{s_sign_i,INF} :
s_op_0 | s_infb ?
{s_sign_i,ZERO_VECTOR} :
{s_sign_i,s_expo3[7:0],s_fraco2[22:0]};
 
endmodule // or1200_fpu_post_norm_div
 
 
/verilog/or1200_fpu_fcmp.v
0,0 → 1,166
/////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_fcmp ////
//// Single precision Floating Point Compare Unit ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
`timescale 1ns / 100ps
 
 
module or1200_fpu_fcmp(opa, opb, unordered, altb, blta, aeqb, inf, zero);
 
input [31:0] opa, opb;
output unordered;
output altb, blta, aeqb;
output inf, zero;
 
////////////////////////////////////////////////////////////////////////
//
// Local Wire
//
 
reg altb, blta, aeqb;
 
wire signa, signb;
wire [7:0] expa, expb;
wire [22:0] fracta, fractb;
 
wire expa_ff, expb_ff, fracta_00, fractb_00;
wire qnan_a, snan_a, qnan_b, snan_b, opa_inf, opb_inf, inf;
wire qnan, snan, opa_zero, opb_zero;
 
wire exp_eq, exp_gt, exp_lt;
wire fract_eq, fract_gt, fract_lt;
wire all_zero;
 
////////////////////////////////////////////////////////////////////////
//
// Aliases
//
 
assign signa = opa[31];
assign signb = opb[31];
assign expa = opa[30:23];
assign expb = opb[30:23];
assign fracta = opa[22:0];
assign fractb = opb[22:0];
 
////////////////////////////////////////////////////////////////////////
//
// Exception Logic
//
 
assign expa_ff = &expa;
assign expb_ff = &expb;
assign fracta_00 = !(|fracta);
assign fractb_00 = !(|fractb);
 
assign qnan_a = fracta[22];
assign snan_a = !fracta[22] & |fracta[21:0];
assign qnan_b = fractb[22];
assign snan_b = !fractb[22] & |fractb[21:0];
 
assign opa_inf = (expa_ff & fracta_00);
assign opb_inf = (expb_ff & fractb_00);
assign inf = opa_inf | opb_inf;
 
assign qnan = (expa_ff & qnan_a) | (expb_ff & qnan_b);
assign snan = (expa_ff & snan_a) | (expb_ff & snan_b);
assign unordered = qnan | snan;
 
assign opa_zero = !(|expa) & fracta_00;
assign opb_zero = !(|expb) & fractb_00;
assign zero = opa_zero;
 
 
////////////////////////////////////////////////////////////////////////
//
// Comparison Logic
//
 
assign exp_eq = expa == expb;
assign exp_gt = expa > expb;
assign exp_lt = expa < expb;
 
assign fract_eq = fracta == fractb;
assign fract_gt = fracta > fractb;
assign fract_lt = fracta < fractb;
 
assign all_zero = opa_zero & opb_zero;
 
always @( qnan or snan or opa_inf or opb_inf or signa or signb or exp_eq or exp_gt or
exp_lt or fract_eq or fract_gt or fract_lt or all_zero)
 
casex( {qnan, snan, opa_inf, opb_inf, signa, signb, exp_eq, exp_gt, exp_lt, fract_eq, fract_gt, fract_lt, all_zero})
//13'b??_??_??_???_???_?: {altb, blta, aeqb} = 3'b000;
 
13'b1?_??_??_???_???_?: {altb, blta, aeqb} = 3'b000; // qnan
13'b?1_??_??_???_???_?: {altb, blta, aeqb} = 3'b000; // snan
 
13'b00_11_00_???_???_?: {altb, blta, aeqb} = 3'b001; // both op INF comparisson
13'b00_11_01_???_???_?: {altb, blta, aeqb} = 3'b100;
13'b00_11_10_???_???_?: {altb, blta, aeqb} = 3'b010;
13'b00_11_11_???_???_?: {altb, blta, aeqb} = 3'b001;
 
13'b00_10_00_???_???_?: {altb, blta, aeqb} = 3'b100; // opa INF comparisson
13'b00_10_01_???_???_?: {altb, blta, aeqb} = 3'b100;
13'b00_10_10_???_???_?: {altb, blta, aeqb} = 3'b010;
13'b00_10_11_???_???_?: {altb, blta, aeqb} = 3'b010;
 
13'b00_01_00_???_???_?: {altb, blta, aeqb} = 3'b010; // opb INF comparisson
13'b00_01_01_???_???_?: {altb, blta, aeqb} = 3'b100;
13'b00_01_10_???_???_?: {altb, blta, aeqb} = 3'b010;
13'b00_01_11_???_???_?: {altb, blta, aeqb} = 3'b100;
 
13'b00_00_10_???_???_0: {altb, blta, aeqb} = 3'b010; //compare base on sign
13'b00_00_01_???_???_0: {altb, blta, aeqb} = 3'b100; //compare base on sign
 
13'b00_00_??_???_???_1: {altb, blta, aeqb} = 3'b001; //compare base on sign both are zero
 
13'b00_00_00_010_???_?: {altb, blta, aeqb} = 3'b100; // cmp exp, equal sign
13'b00_00_00_001_???_?: {altb, blta, aeqb} = 3'b010;
13'b00_00_11_010_???_?: {altb, blta, aeqb} = 3'b010;
13'b00_00_11_001_???_?: {altb, blta, aeqb} = 3'b100;
 
13'b00_00_00_100_010_?: {altb, blta, aeqb} = 3'b100; // compare fractions, equal sign, equal exp
13'b00_00_00_100_001_?: {altb, blta, aeqb} = 3'b010;
13'b00_00_11_100_010_?: {altb, blta, aeqb} = 3'b010;
13'b00_00_11_100_001_?: {altb, blta, aeqb} = 3'b100;
 
13'b00_00_00_100_100_?: {altb, blta, aeqb} = 3'b001;
13'b00_00_11_100_100_?: {altb, blta, aeqb} = 3'b001;
 
default: {altb, blta, aeqb} = 3'bxxx;
endcase
 
endmodule // or1200_fpu_fcmp
 
/verilog/or1200_lsu.v
3,7 → 3,7
//// OR1200's Load/Store unit ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Interface between CPU and DC. ////
41,7 → 41,6
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_lsu.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
48,40 → 47,6
// Major update:
// Structure reordered and bugs fixed.
//
// Revision 1.5 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.4 2002/03/29 15:16:56 lampret
// Some of the warnings fixed.
//
// Revision 1.3 2002/02/11 04:33:17 lampret
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
//
// Revision 1.2 2002/01/18 07:56:00 lampret
// No more low/high priority interrupts (PICPR removed). Added tick timer exception. Added exception prefix (SR[EPH]). Fixed single-step bug whenreading NPC.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.9 2001/11/30 18:59:47 simons
// *** empty log message ***
//
// Revision 1.8 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.7 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:36 igorm
// no message
//
// Revision 1.2 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.1 2001/07/20 00:46:03 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
167,11 → 132,11
//
always @(posedge clk or posedge rst) begin
if (rst)
ex_lsu_op <= #1 `OR1200_LSUOP_NOP;
ex_lsu_op <= `OR1200_LSUOP_NOP;
else if (!ex_freeze & id_freeze | flushpipe)
ex_lsu_op <= #1 `OR1200_LSUOP_NOP;
ex_lsu_op <= `OR1200_LSUOP_NOP;
else if (!ex_freeze)
ex_lsu_op <= #1 id_lsu_op;
ex_lsu_op <= id_lsu_op;
end
 
//
182,9 → 147,9
 
always @(posedge clk or posedge rst) begin
if (rst)
dcpu_adr_r <= #1 {`OR1200_LSUEA_PRECALC{1'b0}};
dcpu_adr_r <= {`OR1200_LSUEA_PRECALC{1'b0}};
else if (!ex_freeze)
dcpu_adr_r <= #1 id_precalc_sum;
dcpu_adr_r <= id_precalc_sum;
end
 
//
192,11 → 157,11
//
always @(posedge clk or posedge rst) begin
if (rst)
except_align <= #1 1'b0;
except_align <= 1'b0;
else if (!ex_freeze & id_freeze | flushpipe)
except_align <= #1 1'b0;
except_align <= 1'b0;
else if (!ex_freeze)
except_align <= #1 ((id_lsu_op == `OR1200_LSUOP_SH) |
except_align <= ((id_lsu_op == `OR1200_LSUOP_SH) |
(id_lsu_op == `OR1200_LSUOP_LHZ) |
(id_lsu_op == `OR1200_LSUOP_LHS)) & id_precalc_sum[0]
| ((id_lsu_op == `OR1200_LSUOP_SW) |
216,11 → 181,10
//
// External I/F assignments
//
assign dcpu_adr_o[31:`OR1200_LSUEA_PRECALC] = ex_addrbase[31:`OR1200_LSUEA_PRECALC] +
ex_addrofs[31:`OR1200_LSUEA_PRECALC] +
dcpu_adr_r[`OR1200_LSUEA_PRECALC]; // carry
assign dcpu_adr_o[31:`OR1200_LSUEA_PRECALC] = ex_addrbase[31:`OR1200_LSUEA_PRECALC] + ex_addrofs[31:`OR1200_LSUEA_PRECALC] + dcpu_adr_r[`OR1200_LSUEA_PRECALC]; // carry
assign dcpu_adr_o[`OR1200_LSUEA_PRECALC-1:0] = dcpu_adr_r[`OR1200_LSUEA_PRECALC-1:0];
assign dcpu_cycstb_o = du_stall | lsu_unstall | except_align ? 1'b0 : |ex_lsu_op;
assign dcpu_cycstb_o = du_stall | lsu_unstall | except_align ?
1'b0 : |ex_lsu_op;
assign dcpu_we_o = ex_lsu_op[3];
assign dcpu_tag_o = dcpu_cycstb_o ? `OR1200_DTAG_ND : `OR1200_DTAG_IDLE;
always @(ex_lsu_op or dcpu_adr_o)
/verilog/or1200_dmmu_tlb.v
3,7 → 3,7
//// OR1200's Data TLB ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://www.opencores.org/project,or1k ////
//// ////
//// Description ////
//// Instantiation of DTLB. ////
41,7 → 41,6
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_dmmu_tlb.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
48,37 → 47,6
// Minor update:
// Bugs fixed, coding style changed.
//
// Revision 1.7 2004/06/08 18:17:36 lampret
// Non-functional changes. Coding style fixes.
//
// Revision 1.6 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.4.4.1 2003/12/09 11:46:48 simons
// Mbist nameing changed, Artisan ram instance signal names fixed, some synthesis waning fixed.
//
// Revision 1.4 2002/10/17 20:04:40 lampret
// Added BIST scan. Special VS RAMs need to be used to implement BIST.
//
// Revision 1.3 2002/02/11 04:33:17 lampret
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
//
// Revision 1.2 2002/01/28 01:16:00 lampret
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.8 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.7 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:36 igorm
// no message
//
//
 
// synopsys translate_off
`include "timescale.v"
/verilog/or1200_ctrl.v
67,10 → 67,10
wb_insn, id_simm, ex_simm, id_branch_addrtarget, ex_branch_addrtarget, sel_a,
sel_b, id_lsu_op,
cust5_op, cust5_limm, id_pc, ex_pc, du_hwbkpt,
multicycle, wbforw_valid, sig_syscall, sig_trap,
multicycle, wait_on, wbforw_valid, sig_syscall, sig_trap,
force_dslot_fetch, no_more_dslot, id_void, ex_void, ex_spr_read,
ex_spr_write,
id_mac_op, id_macrc_op, ex_macrc_op, rfe, except_illegal
id_mac_op, id_macrc_op, ex_macrc_op, rfe, except_illegal, dc_no_writethrough
);
 
//
103,7 → 103,7
output [`OR1200_MACOP_WIDTH-1:0] mac_op;
output [`OR1200_SHROTOP_WIDTH-1:0] shrot_op;
output [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op;
output [`OR1200_FPUOP_WIDTH-1:0] fpu_op;
output [`OR1200_FPUOP_WIDTH-1:0] fpu_op;
input pc_we;
output [31:0] wb_insn;
output [31:2] id_branch_addrtarget;
113,6 → 113,7
output [`OR1200_LSUOP_WIDTH-1:0] id_lsu_op;
output [`OR1200_COMPOP_WIDTH-1:0] comp_op;
output [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;
output [`OR1200_WAIT_ON_WIDTH-1:0] wait_on;
output [4:0] cust5_op;
output [5:0] cust5_limm;
input [31:0] id_pc;
134,7 → 135,9
output ex_macrc_op;
output rfe;
output except_illegal;
 
output dc_no_writethrough;
//
// Internal wires and regs
//
164,6 → 167,7
reg [`OR1200_LSUOP_WIDTH-1:0] id_lsu_op;
reg [`OR1200_COMPOP_WIDTH-1:0] comp_op;
reg [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;
reg [`OR1200_WAIT_ON_WIDTH-1:0] wait_on;
reg [31:0] id_simm;
reg [31:0] ex_simm;
reg sig_syscall;
177,7 → 181,10
reg spr_read;
reg spr_write;
reg [31:2] ex_branch_addrtarget;
 
`ifdef OR1200_DC_NOSTACKWRITETHROUGH
reg dc_no_writethrough;
`endif
//
// Register file read addresses
//
211,21 → 218,21
//
always @(posedge clk or posedge rst) begin
if (rst) begin
ex_delayslot_nop <= #1 1'b0;
ex_delayslot_dsi <= #1 1'b0;
ex_delayslot_nop <= 1'b0;
ex_delayslot_dsi <= 1'b0;
end
else if (!ex_freeze & !ex_delayslot_dsi & ex_delayslot_nop) begin
ex_delayslot_nop <= #1 id_void;
ex_delayslot_dsi <= #1 !id_void;
ex_delayslot_nop <= id_void;
ex_delayslot_dsi <= !id_void;
end
else if (!ex_freeze & ex_delayslot_dsi & !ex_delayslot_nop) begin
ex_delayslot_nop <= #1 1'b0;
ex_delayslot_dsi <= #1 1'b0;
ex_delayslot_nop <= 1'b0;
ex_delayslot_dsi <= 1'b0;
end
else if (!ex_freeze) begin
ex_delayslot_nop <= #1 id_void && ex_branch_taken && (ex_branch_op != `OR1200_BRANCHOP_NOP) &&
ex_delayslot_nop <= id_void && ex_branch_taken && (ex_branch_op != `OR1200_BRANCHOP_NOP) &&
(ex_branch_op != `OR1200_BRANCHOP_RFE);
ex_delayslot_dsi <= #1 !id_void && ex_branch_taken && (ex_branch_op != `OR1200_BRANCHOP_NOP) &&
ex_delayslot_dsi <= !id_void && ex_branch_taken && (ex_branch_op != `OR1200_BRANCHOP_NOP) &&
(ex_branch_op != `OR1200_BRANCHOP_RFE);
end
end
243,9 → 250,9
//
always @(posedge clk or posedge rst) begin
if (rst)
ex_simm <= #1 32'h0000_0000;
ex_simm <= 32'h0000_0000;
else if (!ex_freeze) begin
ex_simm <= #1 id_simm;
ex_simm <= id_simm;
end
end
 
314,9 → 321,9
// pipeline ID and EX branch target address
always @(posedge clk or posedge rst) begin
if (rst)
ex_branch_addrtarget <= #1 32'h00000000;
ex_branch_addrtarget <= 32'h00000000;
else if (!ex_freeze)
ex_branch_addrtarget <= #1 id_branch_addrtarget;
ex_branch_addrtarget <= id_branch_addrtarget;
end
// not pipelined
//assign ex_branch_addrtarget = {{4{ex_insn[25]}}, ex_insn[25:0]} + ex_pc[31:2];
345,11 → 352,11
`ifdef OR1200_MAC_IMPLEMENTED
always @(posedge clk or posedge rst) begin
if (rst)
ex_macrc_op <= #1 1'b0;
ex_macrc_op <= 1'b0;
else if (!ex_freeze & id_freeze | ex_flushpipe)
ex_macrc_op <= #1 1'b0;
ex_macrc_op <= 1'b0;
else if (!ex_freeze)
ex_macrc_op <= #1 id_macrc_op;
ex_macrc_op <= id_macrc_op;
end
`else
assign ex_macrc_op = 1'b0;
444,35 → 451,53
`OR1200_OR32_MULI:
multicycle = 2'h3;
 
`ifdef OR1200_FPU_IMPLEMENTED
`OR1200_OR32_FLOAT:
multicycle = `OR1200_FPUOP_CYCLES;
`endif
 
// Single cycle instructions
default: begin
multicycle = `OR1200_ONE_CYCLE;
end
end
endcase
end
end // always @ (id_insn)
 
//
// Encode wait_on signal
//
always @(id_insn) begin
case (id_insn[31:26]) // synopsys parallel_case
`ifdef OR1200_FPU_IMPLEMENTED
`OR1200_OR32_FLOAT: begin
wait_on = id_insn[`OR1200_FPUOP_DOUBLE_BIT] ? 0 : `OR1200_WAIT_ON_FPU;
end
`endif
`ifndef OR1200_DC_WRITHROUGH
// l.mtspr
`OR1200_OR32_MTSPR: begin
wait_on = `OR1200_WAIT_ON_MTSPR;
end
`endif
default: begin
wait_on = 0;
end
endcase // case (id_insn[31:26])
end // always @ (id_insn)
//
// Register file write address
//
always @(posedge clk or posedge rst) begin
if (rst)
rf_addrw <= #1 5'd0;
rf_addrw <= 5'd0;
else if (!ex_freeze & id_freeze)
rf_addrw <= #1 5'd00;
rf_addrw <= 5'd00;
else if (!ex_freeze)
case (id_insn[31:26]) // synopsys parallel_case
`OR1200_OR32_JAL, `OR1200_OR32_JALR:
rf_addrw <= #1 5'd09; // link register r9
rf_addrw <= 5'd09; // link register r9
default:
rf_addrw <= #1 id_insn[25:21];
rf_addrw <= id_insn[25:21];
endcase
end
 
481,9 → 506,9
//
always @(posedge clk or posedge rst) begin
if (rst)
wb_rfaddrw <= #1 5'd0;
wb_rfaddrw <= 5'd0;
else if (!wb_freeze)
wb_rfaddrw <= #1 rf_addrw;
wb_rfaddrw <= rf_addrw;
end
 
//
491,11 → 516,11
//
always @(posedge clk or posedge rst) begin
if (rst)
id_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000};
id_insn <= {`OR1200_OR32_NOP, 26'h041_0000};
else if (id_flushpipe)
id_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // NOP -> id_insn[16] must be 1
id_insn <= {`OR1200_OR32_NOP, 26'h041_0000}; // NOP -> id_insn[16] must be 1
else if (!id_freeze) begin
id_insn <= #1 if_insn;
id_insn <= if_insn;
`ifdef OR1200_VERBOSE
// synopsys translate_off
$display("%t: id_insn <= %h", $time, if_insn);
509,11 → 534,11
//
always @(posedge clk or posedge rst) begin
if (rst)
ex_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000};
ex_insn <= {`OR1200_OR32_NOP, 26'h041_0000};
else if (!ex_freeze & id_freeze | ex_flushpipe)
ex_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // NOP -> ex_insn[16] must be 1
ex_insn <= {`OR1200_OR32_NOP, 26'h041_0000}; // NOP -> ex_insn[16] must be 1
else if (!ex_freeze) begin
ex_insn <= #1 id_insn;
ex_insn <= id_insn;
`ifdef OR1200_VERBOSE
// synopsys translate_off
$display("%t: ex_insn <= %h", $time, id_insn);
521,18 → 546,18
`endif
end
end
 
//
// Instruction latch in wb_insn
//
always @(posedge clk or posedge rst) begin
if (rst)
wb_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000};
wb_insn <= {`OR1200_OR32_NOP, 26'h041_0000};
// wb_insn should not be changed by exceptions due to correct
// recording of display_arch_state in the or1200_monitor!
// wb_insn changed by exception is not used elsewhere!
else if (!wb_freeze) begin
wb_insn <= #1 ex_insn;
wb_insn <= ex_insn;
end
end
 
541,77 → 566,77
//
always @(posedge clk or posedge rst) begin
if (rst)
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
else if (!id_freeze) begin
case (if_insn[31:26]) // synopsys parallel_case
 
// j.jalr
`OR1200_OR32_JALR:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
// l.jr
`OR1200_OR32_JR:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
// l.rfe
`OR1200_OR32_RFE:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
// l.mfspr
`OR1200_OR32_MFSPR:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
// l.mtspr
`OR1200_OR32_MTSPR:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
// l.sys, l.brk and all three sync insns
`OR1200_OR32_XSYNC:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
// l.mac/l.msb
`ifdef OR1200_MAC_IMPLEMENTED
`OR1200_OR32_MACMSB:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
`endif
 
// l.sw
`OR1200_OR32_SW:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
// l.sb
`OR1200_OR32_SB:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
// l.sh
`OR1200_OR32_SH:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
// ALU instructions except the one with immediate
`OR1200_OR32_ALU:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
// SFXX instructions
`OR1200_OR32_SFXX:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
 
`ifdef OR1200_OR32_CUST5
// l.cust5 instructions
`OR1200_OR32_CUST5:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
`endif
`ifdef OR1200_FPU_IMPLEMENTED
// FPU instructions
`OR1200_OR32_FLOAT:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
`endif
// l.nop
`OR1200_OR32_NOP:
sel_imm <= #1 1'b0;
sel_imm <= 1'b0;
 
// All instructions with immediates
default: begin
sel_imm <= #1 1'b1;
sel_imm <= 1'b1;
end
endcase
624,9 → 649,9
//
always @(posedge clk or posedge rst) begin
if (rst)
except_illegal <= #1 1'b0;
except_illegal <= 1'b0;
else if (!ex_freeze & id_freeze | ex_flushpipe)
except_illegal <= #1 1'b0;
except_illegal <= 1'b0;
else if (!ex_freeze) begin
case (id_insn[31:26]) // synopsys parallel_case
 
670,18 → 695,18
`OR1200_OR32_CUST5,
`endif
`OR1200_OR32_NOP:
except_illegal <= #1 1'b0;
except_illegal <= 1'b0;
`ifdef OR1200_FPU_IMPLEMENTED
`OR1200_OR32_FLOAT:
// Check it's not a double precision instruction
except_illegal <= #1 id_insn[`OR1200_FPUOP_DOUBLE_BIT];
except_illegal <= id_insn[`OR1200_FPUOP_DOUBLE_BIT];
`endif
 
`OR1200_OR32_ALU:
except_illegal <= #1 1'b0
except_illegal <= 1'b0
 
`ifdef OR1200_MULT_IMPLEMENTED
`ifdef OR1200_IMPL_DIV
`ifdef OR1200_DIV_IMPLEMENTED
`else
| ({1'b0, id_insn[3:0]} == `OR1200_ALUOP_DIV)
| ({1'b0, id_insn[3:0]} == `OR1200_ALUOP_DIVU)
710,7 → 735,7
 
// Illegal and OR1200 unsupported instructions
default:
except_illegal <= #1 1'b1;
except_illegal <= 1'b1;
 
endcase
722,67 → 747,67
//
always @(posedge clk or posedge rst) begin
if (rst)
alu_op <= #1 `OR1200_ALUOP_NOP;
alu_op <= `OR1200_ALUOP_NOP;
else if (!ex_freeze & id_freeze | ex_flushpipe)
alu_op <= #1 `OR1200_ALUOP_NOP;
alu_op <= `OR1200_ALUOP_NOP;
else if (!ex_freeze) begin
case (id_insn[31:26]) // synopsys parallel_case
// l.movhi
`OR1200_OR32_MOVHI:
alu_op <= #1 `OR1200_ALUOP_MOVHI;
alu_op <= `OR1200_ALUOP_MOVHI;
// l.addi
`OR1200_OR32_ADDI:
alu_op <= #1 `OR1200_ALUOP_ADD;
alu_op <= `OR1200_ALUOP_ADD;
// l.addic
`OR1200_OR32_ADDIC:
alu_op <= #1 `OR1200_ALUOP_ADDC;
alu_op <= `OR1200_ALUOP_ADDC;
// l.andi
`OR1200_OR32_ANDI:
alu_op <= #1 `OR1200_ALUOP_AND;
alu_op <= `OR1200_ALUOP_AND;
// l.ori
`OR1200_OR32_ORI:
alu_op <= #1 `OR1200_ALUOP_OR;
alu_op <= `OR1200_ALUOP_OR;
// l.xori
`OR1200_OR32_XORI:
alu_op <= #1 `OR1200_ALUOP_XOR;
alu_op <= `OR1200_ALUOP_XOR;
// l.muli
`ifdef OR1200_MULT_IMPLEMENTED
`OR1200_OR32_MULI:
alu_op <= #1 `OR1200_ALUOP_MUL;
alu_op <= `OR1200_ALUOP_MUL;
`endif
// Shift and rotate insns with immediate
`OR1200_OR32_SH_ROTI:
alu_op <= #1 `OR1200_ALUOP_SHROT;
alu_op <= `OR1200_ALUOP_SHROT;
// SFXX insns with immediate
`OR1200_OR32_SFXXI:
alu_op <= #1 `OR1200_ALUOP_COMP;
alu_op <= `OR1200_ALUOP_COMP;
// ALU instructions except the one with immediate
`OR1200_OR32_ALU:
alu_op <= #1 id_insn[3:0];
alu_op <= id_insn[3:0];
// SFXX instructions
`OR1200_OR32_SFXX:
alu_op <= #1 `OR1200_ALUOP_COMP;
alu_op <= `OR1200_ALUOP_COMP;
 
`ifdef OR1200_OR32_CUST5
// l.cust5 instructions
`OR1200_OR32_CUST5:
alu_op <= #1 `OR1200_ALUOP_CUST5;
alu_op <= `OR1200_ALUOP_CUST5;
`endif
// Default
default: begin
alu_op <= #1 `OR1200_ALUOP_NOP;
alu_op <= `OR1200_ALUOP_NOP;
end
endcase
795,12 → 820,12
//
always @(posedge clk or posedge rst) begin
if (rst) begin
spr_read <= #1 1'b0;
spr_write <= #1 1'b0;
spr_read <= 1'b0;
spr_write <= 1'b0;
end
else if (!ex_freeze & id_freeze | ex_flushpipe) begin
spr_read <= #1 1'b0;
spr_write <= #1 1'b0;
spr_read <= 1'b0;
spr_write <= 1'b0;
end
else if (!ex_freeze) begin
case (id_insn[31:26]) // synopsys parallel_case
807,20 → 832,20
 
// l.mfspr
`OR1200_OR32_MFSPR: begin
spr_read <= #1 1'b1;
spr_write <= #1 1'b0;
spr_read <= 1'b1;
spr_write <= 1'b0;
end
 
// l.mtspr
`OR1200_OR32_MTSPR: begin
spr_read <= #1 1'b0;
spr_write <= #1 1'b1;
spr_read <= 1'b0;
spr_write <= 1'b1;
end
 
// Default
default: begin
spr_read <= #1 1'b0;
spr_write <= #1 1'b0;
spr_read <= 1'b0;
spr_write <= 1'b0;
end
 
endcase
836,15 → 861,15
 
// l.maci
`OR1200_OR32_MACI:
id_mac_op <= #1 `OR1200_MACOP_MAC;
id_mac_op <= `OR1200_MACOP_MAC;
 
// l.mac, l.msb
`OR1200_OR32_MACMSB:
id_mac_op <= #1 id_insn[2:0];
id_mac_op <= id_insn[2:0];
 
// Illegal and OR1200 unsupported instructions
default:
id_mac_op <= #1 `OR1200_MACOP_NOP;
id_mac_op <= `OR1200_MACOP_NOP;
 
endcase
end
851,11 → 876,11
 
always @(posedge clk or posedge rst) begin
if (rst)
ex_mac_op <= #1 `OR1200_MACOP_NOP;
ex_mac_op <= `OR1200_MACOP_NOP;
else if (!ex_freeze & id_freeze | ex_flushpipe)
ex_mac_op <= #1 `OR1200_MACOP_NOP;
ex_mac_op <= `OR1200_MACOP_NOP;
else if (!ex_freeze)
ex_mac_op <= #1 id_mac_op;
ex_mac_op <= id_mac_op;
end
 
assign mac_op = abort_mvspr ? `OR1200_MACOP_NOP : ex_mac_op;
869,11 → 894,11
//
always @(posedge clk or posedge rst) begin
if (rst)
shrot_op <= #1 `OR1200_SHROTOP_NOP;
shrot_op <= `OR1200_SHROTOP_NOP;
else if (!ex_freeze & id_freeze | ex_flushpipe)
shrot_op <= #1 `OR1200_SHROTOP_NOP;
shrot_op <= `OR1200_SHROTOP_NOP;
else if (!ex_freeze) begin
shrot_op <= #1 id_insn[`OR1200_SHROTOP_POS];
shrot_op <= id_insn[`OR1200_SHROTOP_POS];
end
end
 
882,95 → 907,95
//
always @(posedge clk or posedge rst) begin
if (rst)
rfwb_op <= #1 `OR1200_RFWBOP_NOP;
rfwb_op <= `OR1200_RFWBOP_NOP;
else if (!ex_freeze & id_freeze | ex_flushpipe)
rfwb_op <= #1 `OR1200_RFWBOP_NOP;
rfwb_op <= `OR1200_RFWBOP_NOP;
else if (!ex_freeze) begin
case (id_insn[31:26]) // synopsys parallel_case
 
// j.jal
`OR1200_OR32_JAL:
rfwb_op <= #1 {`OR1200_RFWBOP_LR, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_LR, 1'b1};
// j.jalr
`OR1200_OR32_JALR:
rfwb_op <= #1 {`OR1200_RFWBOP_LR, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_LR, 1'b1};
// l.movhi
`OR1200_OR32_MOVHI:
rfwb_op <= #1 {`OR1200_RFWBOP_ALU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
// l.mfspr
`OR1200_OR32_MFSPR:
rfwb_op <= #1 {`OR1200_RFWBOP_SPRS, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_SPRS, 1'b1};
// l.lwz
`OR1200_OR32_LWZ:
rfwb_op <= #1 {`OR1200_RFWBOP_LSU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
// l.lbz
`OR1200_OR32_LBZ:
rfwb_op <= #1 {`OR1200_RFWBOP_LSU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
// l.lbs
`OR1200_OR32_LBS:
rfwb_op <= #1 {`OR1200_RFWBOP_LSU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
// l.lhz
`OR1200_OR32_LHZ:
rfwb_op <= #1 {`OR1200_RFWBOP_LSU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
// l.lhs
`OR1200_OR32_LHS:
rfwb_op <= #1 {`OR1200_RFWBOP_LSU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
// l.addi
`OR1200_OR32_ADDI:
rfwb_op <= #1 {`OR1200_RFWBOP_ALU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
// l.addic
`OR1200_OR32_ADDIC:
rfwb_op <= #1 {`OR1200_RFWBOP_ALU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
// l.andi
`OR1200_OR32_ANDI:
rfwb_op <= #1 {`OR1200_RFWBOP_ALU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
// l.ori
`OR1200_OR32_ORI:
rfwb_op <= #1 {`OR1200_RFWBOP_ALU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
// l.xori
`OR1200_OR32_XORI:
rfwb_op <= #1 {`OR1200_RFWBOP_ALU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
// l.muli
`ifdef OR1200_MULT_IMPLEMENTED
`OR1200_OR32_MULI:
rfwb_op <= #1 {`OR1200_RFWBOP_ALU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
`endif
// Shift and rotate insns with immediate
`OR1200_OR32_SH_ROTI:
rfwb_op <= #1 {`OR1200_RFWBOP_ALU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
// ALU instructions except the one with immediate
`OR1200_OR32_ALU:
rfwb_op <= #1 {`OR1200_RFWBOP_ALU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
 
`ifdef OR1200_OR32_CUST5
// l.cust5 instructions
`OR1200_OR32_CUST5:
rfwb_op <= #1 {`OR1200_RFWBOP_ALU, 1'b1};
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
`endif
`ifdef OR1200_FPU_IMPLEMENTED
// FPU instructions, lf.XXX.s, except sfxx
`OR1200_OR32_FLOAT:
rfwb_op <= #1 {`OR1200_RFWBOP_FPU,!id_insn[3]};
rfwb_op <= {`OR1200_RFWBOP_FPU,!id_insn[3]};
`endif
// Instructions w/o register-file write-back
default:
rfwb_op <= #1 `OR1200_RFWBOP_NOP;
rfwb_op <= `OR1200_RFWBOP_NOP;
 
 
endcase
982,43 → 1007,43
//
always @(posedge clk or posedge rst) begin
if (rst)
id_branch_op <= #1 `OR1200_BRANCHOP_NOP;
id_branch_op <= `OR1200_BRANCHOP_NOP;
else if (id_flushpipe)
id_branch_op <= #1 `OR1200_BRANCHOP_NOP;
id_branch_op <= `OR1200_BRANCHOP_NOP;
else if (!id_freeze) begin
case (if_insn[31:26]) // synopsys parallel_case
 
// l.j
`OR1200_OR32_J:
id_branch_op <= #1 `OR1200_BRANCHOP_J;
id_branch_op <= `OR1200_BRANCHOP_J;
// j.jal
`OR1200_OR32_JAL:
id_branch_op <= #1 `OR1200_BRANCHOP_J;
id_branch_op <= `OR1200_BRANCHOP_J;
// j.jalr
`OR1200_OR32_JALR:
id_branch_op <= #1 `OR1200_BRANCHOP_JR;
id_branch_op <= `OR1200_BRANCHOP_JR;
// l.jr
`OR1200_OR32_JR:
id_branch_op <= #1 `OR1200_BRANCHOP_JR;
id_branch_op <= `OR1200_BRANCHOP_JR;
// l.bnf
`OR1200_OR32_BNF:
id_branch_op <= #1 `OR1200_BRANCHOP_BNF;
id_branch_op <= `OR1200_BRANCHOP_BNF;
// l.bf
`OR1200_OR32_BF:
id_branch_op <= #1 `OR1200_BRANCHOP_BF;
id_branch_op <= `OR1200_BRANCHOP_BF;
// l.rfe
`OR1200_OR32_RFE:
id_branch_op <= #1 `OR1200_BRANCHOP_RFE;
id_branch_op <= `OR1200_BRANCHOP_RFE;
// Non branch instructions
default:
id_branch_op <= #1 `OR1200_BRANCHOP_NOP;
id_branch_op <= `OR1200_BRANCHOP_NOP;
 
endcase
end
1029,11 → 1054,11
//
always @(posedge clk or posedge rst)
if (rst)
ex_branch_op <= #1 `OR1200_BRANCHOP_NOP;
ex_branch_op <= `OR1200_BRANCHOP_NOP;
else if (!ex_freeze & id_freeze | ex_flushpipe)
ex_branch_op <= #1 `OR1200_BRANCHOP_NOP;
ex_branch_op <= `OR1200_BRANCHOP_NOP;
else if (!ex_freeze)
ex_branch_op <= #1 id_branch_op;
ex_branch_op <= id_branch_op;
 
//
// Decode of id_lsu_op
1043,39 → 1068,39
 
// l.lwz
`OR1200_OR32_LWZ:
id_lsu_op <= #1 `OR1200_LSUOP_LWZ;
id_lsu_op <= `OR1200_LSUOP_LWZ;
 
// l.lbz
`OR1200_OR32_LBZ:
id_lsu_op <= #1 `OR1200_LSUOP_LBZ;
id_lsu_op <= `OR1200_LSUOP_LBZ;
 
// l.lbs
`OR1200_OR32_LBS:
id_lsu_op <= #1 `OR1200_LSUOP_LBS;
id_lsu_op <= `OR1200_LSUOP_LBS;
 
// l.lhz
`OR1200_OR32_LHZ:
id_lsu_op <= #1 `OR1200_LSUOP_LHZ;
id_lsu_op <= `OR1200_LSUOP_LHZ;
 
// l.lhs
`OR1200_OR32_LHS:
id_lsu_op <= #1 `OR1200_LSUOP_LHS;
id_lsu_op <= `OR1200_LSUOP_LHS;
 
// l.sw
`OR1200_OR32_SW:
id_lsu_op <= #1 `OR1200_LSUOP_SW;
id_lsu_op <= `OR1200_LSUOP_SW;
 
// l.sb
`OR1200_OR32_SB:
id_lsu_op <= #1 `OR1200_LSUOP_SB;
id_lsu_op <= `OR1200_LSUOP_SB;
 
// l.sh
`OR1200_OR32_SH:
id_lsu_op <= #1 `OR1200_LSUOP_SH;
id_lsu_op <= `OR1200_LSUOP_SH;
 
// Non load/store instructions
default:
id_lsu_op <= #1 `OR1200_LSUOP_NOP;
id_lsu_op <= `OR1200_LSUOP_NOP;
 
endcase
end
1085,11 → 1110,11
//
always @(posedge clk or posedge rst) begin
if (rst) begin
comp_op <= #1 4'd0;
comp_op <= 4'd0;
end else if (!ex_freeze & id_freeze | ex_flushpipe)
comp_op <= #1 4'd0;
comp_op <= 4'd0;
else if (!ex_freeze)
comp_op <= #1 id_insn[24:21];
comp_op <= id_insn[24:21];
end
 
`ifdef OR1200_FPU_IMPLEMENTED
1096,7 → 1121,8
//
// Decode of FPU ops
//
assign fpu_op = {(id_insn[31:26] == `OR1200_OR32_FLOAT), id_insn[`OR1200_FPUOP_WIDTH-2:0]};
assign fpu_op = {(id_insn[31:26] == `OR1200_OR32_FLOAT),
id_insn[`OR1200_FPUOP_WIDTH-2:0]};
`else
assign fpu_op = {`OR1200_FPUOP_WIDTH{1'b0}};
`endif
1107,9 → 1133,9
//
always @(posedge clk or posedge rst) begin
if (rst)
sig_syscall <= #1 1'b0;
sig_syscall <= 1'b0;
else if (!ex_freeze & id_freeze | ex_flushpipe)
sig_syscall <= #1 1'b0;
sig_syscall <= 1'b0;
else if (!ex_freeze) begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
1117,7 → 1143,7
$display("Generating sig_syscall");
// synopsys translate_on
`endif
sig_syscall <= #1 (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b000});
sig_syscall <= (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b000});
end
end
 
1126,9 → 1152,9
//
always @(posedge clk or posedge rst) begin
if (rst)
sig_trap <= #1 1'b0;
sig_trap <= 1'b0;
else if (!ex_freeze & id_freeze | ex_flushpipe)
sig_trap <= #1 1'b0;
sig_trap <= 1'b0;
else if (!ex_freeze) begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
1136,9 → 1162,24
$display("Generating sig_trap");
// synopsys translate_on
`endif
sig_trap <= #1 (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b010})
sig_trap <= (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b010})
| du_hwbkpt;
end
end
 
// Decode destination register address for data cache to check if store ops
// are being done from the stack register (r1) or frame pointer register (r2)
`ifdef OR1200_DC_NOSTACKWRITETHROUGH
always @(posedge clk or posedge rst) begin
if (rst)
dc_no_writethrough <= 0;
else if (!ex_freeze)
dc_no_writethrough <= (id_insn[20:16] == 5'd1) | (id_insn[20:16] == 5'd2);
end
`else
assign dc_no_writethrough = 0;
`endif
endmodule
/verilog/or1200_fpu_post_norm_mul.v
0,0 → 1,370
//////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_post_norm_mul ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// post-normalization entity for the multiplication unit ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Original design (FPU100) - ////
//// Jidan Al-eryani, jidan@gmx.net ////
//// - Conv. to Verilog and inclusion in OR1200 - ////
//// Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2006, 2010
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
module or1200_fpu_post_norm_mul(
clk_i,
opa_i,
opb_i,
exp_10_i,
fract_48_i,
sign_i,
rmode_i,
output_o,
ine_o
);
 
parameter FP_WIDTH = 32;
parameter MUL_SERIAL = 0; // 0 for parallel multiplier, 1 for serial
parameter MUL_COUNT = 11; //11 for parallel multiplier, 34 for serial
parameter FRAC_WIDTH = 23;
parameter EXP_WIDTH = 8;
parameter ZERO_VECTOR = 31'd0;
parameter INF = 31'b1111111100000000000000000000000;
parameter QNAN = 31'b1111111110000000000000000000000;
parameter SNAN = 31'b1111111100000000000000000000001;
 
input clk_i;
input [FP_WIDTH-1:0] opa_i;
input [FP_WIDTH-1:0] opb_i;
input [EXP_WIDTH+1:0] exp_10_i;
input [2*FRAC_WIDTH+1:0] fract_48_i;
input sign_i;
input [1:0] rmode_i;
output reg [FP_WIDTH-1:0] output_o;
output reg ine_o;
 
reg [EXP_WIDTH-1:0] s_expa;
reg [EXP_WIDTH-1:0] s_expb;
reg [EXP_WIDTH+1:0] s_exp_10_i;
reg [2*FRAC_WIDTH+1:0] s_fract_48_i;
reg s_sign_i;
wire [FP_WIDTH-1:0] s_output_o;
wire s_ine_o;
wire s_overflow;
reg [FP_WIDTH-1:0] s_opa_i;
reg [FP_WIDTH-1:0] s_opb_i;
reg [1:0] s_rmode_i;
 
reg [5:0] s_zeros;
wire s_carry;
reg [5:0] s_shr2;
reg [5:0] s_shl2;
reg [8:0] s_expo1;
wire [8:0] s_expo2b;
wire [9:0] s_exp_10a;
wire [9:0] s_exp_10b;
reg [47:0] s_frac2a;
 
wire s_sticky, s_guard, s_round;
wire s_roundup;
reg [24:0] s_frac_rnd;
wire [24:0] s_frac3;
wire s_shr3;
reg [5:0] s_r_zeros;
wire s_lost;
wire s_op_0;
wire [8:0] s_expo3;
 
wire s_infa, s_infb;
wire s_nan_in, s_nan_op, s_nan_a, s_nan_b;
 
// Input Register
always @(posedge clk_i)
begin
s_opa_i <= opa_i;
s_opb_i <= opb_i;
s_expa <= opa_i[30:23];
s_expb <= opb_i[30:23];
s_exp_10_i <= exp_10_i;
s_fract_48_i <= fract_48_i;
s_sign_i <= sign_i;
s_rmode_i <= rmode_i;
end
 
// Output register
always @(posedge clk_i)
begin
output_o <= s_output_o;
ine_o <= s_ine_o;
end
 
//*** Stage 1 ****
// figure out the exponent and howmuch the fraction has to be shiftd
// right/left
assign s_carry = s_fract_48_i[47];
always @(posedge clk_i)
if (!s_fract_48_i[47])
casex(s_fract_48_i[46:1]) // synopsys full_case parallel_case
46'b1?????????????????????????????????????????????: s_zeros <= 0;
46'b01????????????????????????????????????????????: s_zeros <= 1;
46'b001???????????????????????????????????????????: s_zeros <= 2;
46'b0001??????????????????????????????????????????: s_zeros <= 3;
46'b00001?????????????????????????????????????????: s_zeros <= 4;
46'b000001????????????????????????????????????????: s_zeros <= 5;
46'b0000001???????????????????????????????????????: s_zeros <= 6;
46'b00000001??????????????????????????????????????: s_zeros <= 7;
46'b000000001?????????????????????????????????????: s_zeros <= 8;
46'b0000000001????????????????????????????????????: s_zeros <= 9;
46'b00000000001???????????????????????????????????: s_zeros <= 10;
46'b000000000001??????????????????????????????????: s_zeros <= 11;
46'b0000000000001?????????????????????????????????: s_zeros <= 12;
46'b00000000000001????????????????????????????????: s_zeros <= 13;
46'b000000000000001???????????????????????????????: s_zeros <= 14;
46'b0000000000000001??????????????????????????????: s_zeros <= 15;
46'b00000000000000001?????????????????????????????: s_zeros <= 16;
46'b000000000000000001????????????????????????????: s_zeros <= 17;
46'b0000000000000000001???????????????????????????: s_zeros <= 18;
46'b00000000000000000001??????????????????????????: s_zeros <= 19;
46'b000000000000000000001?????????????????????????: s_zeros <= 20;
46'b0000000000000000000001????????????????????????: s_zeros <= 21;
46'b00000000000000000000001???????????????????????: s_zeros <= 22;
46'b000000000000000000000001??????????????????????: s_zeros <= 23;
46'b0000000000000000000000001?????????????????????: s_zeros <= 24;
46'b00000000000000000000000001????????????????????: s_zeros <= 25;
46'b000000000000000000000000001???????????????????: s_zeros <= 26;
46'b0000000000000000000000000001??????????????????: s_zeros <= 27;
46'b00000000000000000000000000001?????????????????: s_zeros <= 28;
46'b000000000000000000000000000001????????????????: s_zeros <= 29;
46'b0000000000000000000000000000001???????????????: s_zeros <= 30;
46'b00000000000000000000000000000001??????????????: s_zeros <= 31;
46'b000000000000000000000000000000001?????????????: s_zeros <= 32;
46'b0000000000000000000000000000000001????????????: s_zeros <= 33;
46'b00000000000000000000000000000000001???????????: s_zeros <= 34;
46'b000000000000000000000000000000000001??????????: s_zeros <= 35;
46'b0000000000000000000000000000000000001?????????: s_zeros <= 36;
46'b00000000000000000000000000000000000001????????: s_zeros <= 37;
46'b000000000000000000000000000000000000001???????: s_zeros <= 38;
46'b0000000000000000000000000000000000000001??????: s_zeros <= 39;
46'b00000000000000000000000000000000000000001?????: s_zeros <= 40;
46'b000000000000000000000000000000000000000001????: s_zeros <= 41;
46'b0000000000000000000000000000000000000000001???: s_zeros <= 42;
46'b00000000000000000000000000000000000000000001??: s_zeros <= 43;
46'b000000000000000000000000000000000000000000001?: s_zeros <= 44;
46'b0000000000000000000000000000000000000000000001: s_zeros <= 45;
46'b0000000000000000000000000000000000000000000000: s_zeros <= 46;
endcase // casex (s_fract_48_i[46:1])
else
s_zeros <= 0;
 
 
always @(posedge clk_i)
casex(s_fract_48_i) // synopsys full_case parallel_case
48'b???????????????????????????????????????????????1: s_r_zeros <= 0;
48'b??????????????????????????????????????????????10: s_r_zeros <= 1;
48'b?????????????????????????????????????????????100: s_r_zeros <= 2;
48'b????????????????????????????????????????????1000: s_r_zeros <= 3;
48'b???????????????????????????????????????????10000: s_r_zeros <= 4;
48'b??????????????????????????????????????????100000: s_r_zeros <= 5;
48'b?????????????????????????????????????????1000000: s_r_zeros <= 6;
48'b????????????????????????????????????????10000000: s_r_zeros <= 7;
48'b???????????????????????????????????????100000000: s_r_zeros <= 8;
48'b??????????????????????????????????????1000000000: s_r_zeros <= 9;
48'b?????????????????????????????????????10000000000: s_r_zeros <= 10;
48'b????????????????????????????????????100000000000: s_r_zeros <= 11;
48'b???????????????????????????????????1000000000000: s_r_zeros <= 12;
48'b??????????????????????????????????10000000000000: s_r_zeros <= 13;
48'b?????????????????????????????????100000000000000: s_r_zeros <= 14;
48'b????????????????????????????????1000000000000000: s_r_zeros <= 15;
48'b???????????????????????????????10000000000000000: s_r_zeros <= 16;
48'b??????????????????????????????100000000000000000: s_r_zeros <= 17;
48'b?????????????????????????????1000000000000000000: s_r_zeros <= 18;
48'b????????????????????????????10000000000000000000: s_r_zeros <= 19;
48'b???????????????????????????100000000000000000000: s_r_zeros <= 20;
48'b??????????????????????????1000000000000000000000: s_r_zeros <= 21;
48'b?????????????????????????10000000000000000000000: s_r_zeros <= 22;
48'b????????????????????????100000000000000000000000: s_r_zeros <= 23;
48'b???????????????????????1000000000000000000000000: s_r_zeros <= 24;
48'b??????????????????????10000000000000000000000000: s_r_zeros <= 25;
48'b?????????????????????100000000000000000000000000: s_r_zeros <= 26;
48'b????????????????????1000000000000000000000000000: s_r_zeros <= 27;
48'b???????????????????10000000000000000000000000000: s_r_zeros <= 28;
48'b??????????????????100000000000000000000000000000: s_r_zeros <= 29;
48'b?????????????????1000000000000000000000000000000: s_r_zeros <= 30;
48'b????????????????10000000000000000000000000000000: s_r_zeros <= 31;
48'b???????????????100000000000000000000000000000000: s_r_zeros <= 32;
48'b??????????????1000000000000000000000000000000000: s_r_zeros <= 33;
48'b?????????????10000000000000000000000000000000000: s_r_zeros <= 34;
48'b????????????100000000000000000000000000000000000: s_r_zeros <= 35;
48'b???????????1000000000000000000000000000000000000: s_r_zeros <= 36;
48'b??????????10000000000000000000000000000000000000: s_r_zeros <= 37;
48'b?????????100000000000000000000000000000000000000: s_r_zeros <= 38;
48'b????????1000000000000000000000000000000000000000: s_r_zeros <= 39;
48'b???????10000000000000000000000000000000000000000: s_r_zeros <= 40;
48'b??????100000000000000000000000000000000000000000: s_r_zeros <= 41;
48'b?????1000000000000000000000000000000000000000000: s_r_zeros <= 42;
48'b????10000000000000000000000000000000000000000000: s_r_zeros <= 43;
48'b???100000000000000000000000000000000000000000000: s_r_zeros <= 44;
48'b??1000000000000000000000000000000000000000000000: s_r_zeros <= 45;
48'b?10000000000000000000000000000000000000000000000: s_r_zeros <= 46;
48'b100000000000000000000000000000000000000000000000: s_r_zeros <= 47;
48'b000000000000000000000000000000000000000000000000: s_r_zeros <= 48;
endcase // casex (s_fract_48_i)
 
assign s_exp_10a = s_exp_10_i + {9'd0,s_carry};
assign s_exp_10b = s_exp_10a - {4'd0,s_zeros};
 
wire [9:0] v_shr1;
wire [9:0] v_shl1;
assign v_shr1 = (s_exp_10a[9] | !(|s_exp_10a)) ?
10'd1 - s_exp_10a + {9'd0,s_carry} :
(s_exp_10b[9] | !(|s_exp_10b)) ?
0 :
s_exp_10b[8] ?
0 : {9'd0,s_carry};
assign v_shl1 = (s_exp_10a[9] | !(|s_exp_10a)) ?
0 :
(s_exp_10b[9] | !(|s_exp_10b)) ?
{4'd0,s_zeros} - s_exp_10a :
s_exp_10b[8] ?
0 : {4'd0,s_zeros};
always @(posedge clk_i)
begin
if ((s_exp_10a[9] | !(|s_exp_10a)))
s_expo1 <= 9'd1;
else if (s_exp_10b[9] | !(|s_exp_10b))
s_expo1 <= 1'd1;
else if (s_exp_10b[8])
s_expo1 <= 9'b011111111;
else
s_expo1 <= s_exp_10b[8:0];
if (v_shr1[6])
s_shr2 <= {6{1'b1}};
else
s_shr2 <= v_shr1[5:0];
 
s_shl2 <= v_shl1[5:0];
end // always @ (posedge clk_i)
// *** Stage 2 ***
// Shifting the fraction and rounding
// shift the fraction
always @(posedge clk_i)
if (|s_shr2)
s_frac2a <= s_fract_48_i >> s_shr2;
else
s_frac2a <= s_fract_48_i << s_shl2;
assign s_expo2b = s_frac2a[46] ? s_expo1 : s_expo1 - 9'd1;
 
// signals if precision was last during the right-shift above
assign s_lost = (s_shr2 + {5'd0,s_shr3}) > s_r_zeros;
// ***Stage 3***
// Rounding
 
// 23
// |
// xx00000000000000000000000grsxxxxxxxxxxxxxxxxxxxx
// guard bit: s_frac2a[23] (LSB of output)
// round bit: s_frac2a[22]
assign s_guard = s_frac2a[22];
assign s_round = s_frac2a[21];
assign s_sticky = (|s_frac2a[20:0]) | s_lost;
assign s_roundup = s_rmode_i==2'b00 ? // round to nearest even
s_guard & ((s_round | s_sticky) | s_frac2a[23]) :
s_rmode_i==2'b10 ? // round up
(s_guard | s_round | s_sticky) & !s_sign_i :
s_rmode_i==2'b11 ? // round down
(s_guard | s_round | s_sticky) & s_sign_i :
0; // round to zero(truncate = no rounding)
always @(posedge clk_i)
if (s_roundup)
s_frac_rnd <= s_frac2a[47:23] + 1;
else
s_frac_rnd <= s_frac2a[47:23];
assign s_shr3 = s_frac_rnd[24];
 
 
assign s_expo3 = (s_shr3 & (s_expo2b!=9'b011111111)) ?
s_expo2b + 1 : s_expo2b;
assign s_frac3 = (s_shr3 & (s_expo2b!=9'b011111111)) ?
{1'b0,s_frac_rnd[24:1]} : s_frac_rnd;
//-***Stage 4****
// Output
assign s_op_0 = !((|s_opa_i[30:0]) & (|s_opb_i[30:0]));
assign s_infa = &s_expa;
assign s_infb = &s_expb;
assign s_nan_a = s_infa & (|s_opa_i[22:0]);
assign s_nan_b = s_infb & (|s_opb_i[22:0]);
assign s_nan_in = s_nan_a | s_nan_b;
assign s_nan_op = (s_infa | s_infb) & s_op_0; // 0 * inf = nan
assign s_overflow = (s_expo3==9'b011111111) & !(s_infa | s_infb);
assign s_ine_o = !s_op_0 & (s_lost | (|s_frac2a[22:0]) | s_overflow);
assign s_output_o = (s_nan_in | s_nan_op) ?
{s_sign_i,QNAN} :
(s_infa | s_infb) | s_overflow ?
{s_sign_i,INF} :
s_r_zeros==48 ?
{s_sign_i,ZERO_VECTOR} :
{s_sign_i,s_expo3[7:0],s_frac3[22:0]};
 
endmodule // or1200_fpu_post_norm_mul
 
/verilog/or1200_rf.v
63,7 → 63,7
id_freeze, addra, addrb, dataa, datab, rda, rdb,
 
// Debug
spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o, du_read
);
 
parameter dw = `OR1200_OPERAND_WIDTH;
110,7 → 110,8
input [31:0] spr_addr;
input [31:0] spr_dat_i;
output [31:0] spr_dat_o;
 
input du_read;
//
// Internal wires and regs
//
125,6 → 126,31
wire rf_enb;
reg rf_we_allow;
 
// Logic to restore output on RFA after debug unit has read out via SPR if.
// Problem was that the incorrect output would be on RFA after debug unit
// had read out - this is bad if that output is relied upon by execute
// stage for next instruction. We simply save the last address for rf A and
// and re-read it whenever the SPR select goes low, so we must remember
// the last address and generate a signal for falling edge of SPR cs.
// -- Julius
// Detect falling edge of SPR select
reg spr_du_cs;
wire spr_cs_fe;
// Track RF A's address each time it's enabled
reg [aw-1:0] addra_last;
 
 
always @(posedge clk)
if (rf_ena & !(spr_cs_fe | (du_read & spr_cs)))
addra_last <= addra;
 
always @(posedge clk)
spr_du_cs <= spr_cs & du_read;
 
assign spr_cs_fe = spr_du_cs & !(spr_cs & du_read);
 
//
// SPR access is valid when spr_cs is asserted and
// SPR address matches GPR addresses
149,7 → 175,8
//
// RF A read address is either from SPRS or normal from CPU control
//
assign rf_addra = (spr_valid & !spr_write) ? spr_addr[4:0] : addra;
assign rf_addra = (spr_valid & !spr_write) ? spr_addr[4:0] :
spr_cs_fe ? addra_last : addra;
 
//
// RF write address is either from SPRS or normal from CPU control
166,21 → 193,22
//
always @(posedge rst or posedge clk)
if (rst)
rf_we_allow <= #1 1'b1;
rf_we_allow <= 1'b1;
else if (~wb_freeze)
rf_we_allow <= #1 ~flushpipe;
rf_we_allow <= ~flushpipe;
 
//assign rf_we = ((spr_valid & spr_write) | (we & ~wb_freeze)) & rf_we_allow & (supv | (|rf_addrw));
assign rf_we = ((spr_valid & spr_write) | (we & ~wb_freeze)) & rf_we_allow;
//assign cy_we_o = cy_we_i && rf_we;
assign cy_we_o = cy_we_i && ~wb_freeze && rf_we_allow;
 
//
// CS RF A asserted when instruction reads operand A and ID stage
// is not stalled
//
//assign rf_ena = rda & ~id_freeze | spr_valid; // probably works with fixed binutils
assign rf_ena = (rda & ~id_freeze) | (spr_valid & !spr_write); // probably works with fixed binutils
assign rf_ena = (rda & ~id_freeze) | (spr_valid & !spr_write) | spr_cs_fe; // probably works with fixed binutils
// assign rf_ena = 1'b1; // does not work with single-stepping
//assign rf_ena = ~id_freeze | spr_valid; // works with broken binutils
 
/verilog/or1200_wb_biu.v
3,7 → 3,7
//// OR1200's WISHBONE BIU ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Implements WISHBONE interface ////
46,7 → 46,6
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_wb_biu.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
53,58 → 52,6
// Major update:
// Structure reordered and bugs fixed.
//
// Revision 1.7 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.6.4.1 2003/07/08 15:36:37 lampret
// Added embedded memory QMEM.
//
// Revision 1.6 2003/04/07 20:57:46 lampret
// Fixed OR1200_CLKDIV_x_SUPPORTED defines. Fixed order of ifdefs.
//
// Revision 1.5 2002/12/08 08:57:56 lampret
// Added optional support for WB B3 specification (xwb_cti_o, xwb_bte_o). Made xwb_cab_o optional.
//
// Revision 1.4 2002/09/16 03:09:16 lampret
// Fixed a combinational loop.
//
// Revision 1.3 2002/08/12 05:31:37 lampret
// Added optional retry counter for wb_rty_i. Added graceful termination for aborted transfers.
//
// Revision 1.2 2002/07/14 22:17:17 lampret
// Added simple trace buffer [only for Xilinx Virtex target]. Fixed instruction fetch abort when new exception is recognized.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.12 2001/11/22 13:42:51 lampret
// Added wb_cyc_o assignment after it was removed by accident.
//
// Revision 1.11 2001/11/20 21:28:10 lampret
// Added optional sampling of inputs.
//
// Revision 1.10 2001/11/18 11:32:00 lampret
// OR1200_REGISTERED_OUTPUTS can now be enabled.
//
// Revision 1.9 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.8 2001/10/14 13:12:10 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:35 igorm
// no message
//
// Revision 1.3 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.2 2001/07/22 03:31:54 lampret
// Fixed RAM's oen bug. Cache bypass under development.
//
// Revision 1.1 2001/07/20 00:46:23 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
112,338 → 59,358
`include "or1200_defines.v"
 
module or1200_wb_biu(
// RISC clock, reset and clock control
clk, rst, clmode,
// RISC clock, reset and clock control
clk, rst, clmode,
 
// WISHBONE interface
wb_clk_i, wb_rst_i, wb_ack_i, wb_err_i, wb_rty_i, wb_dat_i,
wb_cyc_o, wb_adr_o, wb_stb_o, wb_we_o, wb_sel_o, wb_dat_o,
// WISHBONE interface
wb_clk_i, wb_rst_i, wb_ack_i, wb_err_i, wb_rty_i, wb_dat_i,
wb_cyc_o, wb_adr_o, wb_stb_o, wb_we_o, wb_sel_o, wb_dat_o,
`ifdef OR1200_WB_CAB
wb_cab_o,
wb_cab_o,
`endif
`ifdef OR1200_WB_B3
wb_cti_o, wb_bte_o,
wb_cti_o, wb_bte_o,
`endif
 
// Internal RISC bus
biu_dat_i, biu_adr_i, biu_cyc_i, biu_stb_i, biu_we_i, biu_sel_i, biu_cab_i,
biu_dat_o, biu_ack_o, biu_err_o
);
// Internal RISC bus
biu_dat_i, biu_adr_i, biu_cyc_i, biu_stb_i, biu_we_i, biu_sel_i, biu_cab_i,
biu_dat_o, biu_ack_o, biu_err_o
);
 
parameter dw = `OR1200_OPERAND_WIDTH;
parameter aw = `OR1200_OPERAND_WIDTH;
parameter dw = `OR1200_OPERAND_WIDTH;
parameter aw = `OR1200_OPERAND_WIDTH;
 
//
// RISC clock, reset and clock control
//
input clk; // RISC clock
input rst; // RISC reset
input [1:0] clmode; // 00 WB=RISC, 01 WB=RISC/2, 10 N/A, 11 WB=RISC/4
//
// RISC clock, reset and clock control
//
input clk; // RISC clock
input rst; // RISC reset
input [1:0] clmode; // 00 WB=RISC, 01 WB=RISC/2, 10 N/A, 11 WB=RISC/4
 
//
// WISHBONE interface
//
input wb_clk_i; // clock input
input wb_rst_i; // reset input
input wb_ack_i; // normal termination
input wb_err_i; // termination w/ error
input wb_rty_i; // termination w/ retry
input [dw-1:0] wb_dat_i; // input data bus
output wb_cyc_o; // cycle valid output
output [aw-1:0] wb_adr_o; // address bus outputs
output wb_stb_o; // strobe output
output wb_we_o; // indicates write transfer
output [3:0] wb_sel_o; // byte select outputs
output [dw-1:0] wb_dat_o; // output data bus
//
// WISHBONE interface
//
input wb_clk_i; // clock input
input wb_rst_i; // reset input
input wb_ack_i; // normal termination
input wb_err_i; // termination w/ error
input wb_rty_i; // termination w/ retry
input [dw-1:0] wb_dat_i; // input data bus
output wb_cyc_o; // cycle valid output
output [aw-1:0] wb_adr_o; // address bus outputs
output wb_stb_o; // strobe output
output wb_we_o; // indicates write transfer
output [3:0] wb_sel_o; // byte select outputs
output [dw-1:0] wb_dat_o; // output data bus
`ifdef OR1200_WB_CAB
output wb_cab_o; // consecutive address burst
output wb_cab_o; // consecutive address burst
`endif
`ifdef OR1200_WB_B3
output [2:0] wb_cti_o; // cycle type identifier
output [1:0] wb_bte_o; // burst type extension
output [2:0] wb_cti_o; // cycle type identifier
output [1:0] wb_bte_o; // burst type extension
`endif
 
//
// Internal RISC interface
//
input [dw-1:0] biu_dat_i; // input data bus
input [aw-1:0] biu_adr_i; // address bus
input biu_cyc_i; // WB cycle
input biu_stb_i; // WB strobe
input biu_we_i; // WB write enable
input biu_cab_i; // CAB input
input [3:0] biu_sel_i; // byte selects
output [31:0] biu_dat_o; // output data bus
output biu_ack_o; // ack output
output biu_err_o; // err output
//
// Internal RISC interface
//
input [dw-1:0] biu_dat_i; // input data bus
input [aw-1:0] biu_adr_i; // address bus
input biu_cyc_i; // WB cycle
input biu_stb_i; // WB strobe
input biu_we_i; // WB write enable
input biu_cab_i; // CAB input
input [3:0] biu_sel_i; // byte selects
output [31:0] biu_dat_o; // output data bus
output biu_ack_o; // ack output
output biu_err_o; // err output
 
//
// Registers
//
wire wb_ack; // normal termination
reg [aw-1:0] wb_adr_o; // address bus outputs
reg wb_cyc_o; // cycle output
reg wb_stb_o; // strobe output
reg wb_we_o; // indicates write transfer
reg [3:0] wb_sel_o; // byte select outputs
//
// Registers
//
wire wb_ack; // normal termination
reg [aw-1:0] wb_adr_o; // address bus outputs
reg wb_cyc_o; // cycle output
reg wb_stb_o; // strobe output
reg wb_we_o; // indicates write transfer
reg [3:0] wb_sel_o; // byte select outputs
`ifdef OR1200_WB_CAB
reg wb_cab_o; // CAB output
reg wb_cab_o; // CAB output
`endif
`ifdef OR1200_WB_B3
reg [2:0] wb_cti_o; // cycle type identifier
reg [1:0] wb_bte_o; // burst type extension
reg [2:0] wb_cti_o; // cycle type identifier
reg [1:0] wb_bte_o; // burst type extension
`endif
reg [dw-1:0] wb_dat_o; // output data bus
 
`ifdef OR1200_NO_DC
reg [dw-1:0] wb_dat_o; // output data bus
`else
assign wb_dat_o = biu_dat_i; // No register on this - straight from DCRAM
`endif
`ifdef OR1200_WB_RETRY
reg [`OR1200_WB_RETRY-1:0] retry_cnt; // Retry counter
reg [`OR1200_WB_RETRY-1:0] retry_cnt; // Retry counter
`else
wire retry_cnt = 1'b0;
wire retry_cnt;
assign retry_cnt = 1'b0;
`endif
`ifdef OR1200_WB_B3
reg [1:0] burst_len; // burst counter
reg [1:0] burst_len; // burst counter
`endif
 
reg biu_stb_reg; // WB strobe
wire biu_stb; // WB strobe
reg wb_cyc_nxt; // next WB cycle value
reg wb_stb_nxt; // next WB strobe value
reg [2:0] wb_cti_nxt; // next cycle type identifier value
reg biu_stb_reg; // WB strobe
wire biu_stb; // WB strobe
reg wb_cyc_nxt; // next WB cycle value
reg wb_stb_nxt; // next WB strobe value
reg [2:0] wb_cti_nxt; // next cycle type identifier value
 
reg wb_ack_cnt; // WB ack toggle counter
reg wb_err_cnt; // WB err toggle counter
reg wb_rty_cnt; // WB rty toggle counter
reg biu_ack_cnt; // BIU ack toggle counter
reg biu_err_cnt; // BIU err toggle counter
reg biu_rty_cnt; // BIU rty toggle counter
wire biu_rty; // BIU rty indicator
reg wb_ack_cnt; // WB ack toggle counter
reg wb_err_cnt; // WB err toggle counter
reg wb_rty_cnt; // WB rty toggle counter
reg biu_ack_cnt; // BIU ack toggle counter
reg biu_err_cnt; // BIU err toggle counter
reg biu_rty_cnt; // BIU rty toggle counter
wire biu_rty; // BIU rty indicator
 
reg [1:0] wb_fsm_state_cur; // WB FSM - surrent state
reg [1:0] wb_fsm_state_nxt; // WB FSM - next state
wire [1:0] wb_fsm_idle = 2'h0; // WB FSM state - IDLE
wire [1:0] wb_fsm_trans = 2'h1; // WB FSM state - normal TRANSFER
wire [1:0] wb_fsm_last = 2'h2; // EB FSM state - LAST transfer
reg [1:0] wb_fsm_state_cur; // WB FSM - surrent state
reg [1:0] wb_fsm_state_nxt; // WB FSM - next state
wire [1:0] wb_fsm_idle = 2'h0; // WB FSM state - IDLE
wire [1:0] wb_fsm_trans = 2'h1; // WB FSM state - normal TRANSFER
wire [1:0] wb_fsm_last = 2'h2; // EB FSM state - LAST transfer
 
//
// WISHBONE I/F <-> Internal RISC I/F conversion
//
//assign wb_ack = wb_ack_i;
assign wb_ack = wb_ack_i && !wb_err_i && !wb_rty_i;
//
// WISHBONE I/F <-> Internal RISC I/F conversion
//
//assign wb_ack = wb_ack_i;
assign wb_ack = wb_ack_i & !wb_err_i & !wb_rty_i;
 
//
// WB FSM - register part
//
always @(posedge wb_clk_i or posedge wb_rst_i) begin
if (wb_rst_i)
wb_fsm_state_cur <= #1 wb_fsm_idle;
else
wb_fsm_state_cur <= #1 wb_fsm_state_nxt;
end
//
// WB FSM - register part
//
always @(posedge wb_clk_i or posedge wb_rst_i) begin
if (wb_rst_i)
wb_fsm_state_cur <= wb_fsm_idle;
else
wb_fsm_state_cur <= wb_fsm_state_nxt;
end
 
//
// WB burst tength counter
//
always @(posedge wb_clk_i or posedge wb_rst_i) begin
if (wb_rst_i) begin
burst_len <= #1 2'h0;
end
else begin
// burst counter
if (wb_fsm_state_cur == wb_fsm_idle)
burst_len <= #1 2'h2;
else if (wb_stb_o && wb_ack)
burst_len <= #1 burst_len - 1'b1;
end
end
//
// WB burst tength counter
//
always @(posedge wb_clk_i or posedge wb_rst_i) begin
if (wb_rst_i) begin
burst_len <= 2'h0;
end
else begin
// burst counter
if (wb_fsm_state_cur == wb_fsm_idle)
burst_len <= 2'h2;
else if (wb_stb_o & wb_ack)
burst_len <= burst_len - 1'b1;
end
end
 
//
// WB FSM - combinatorial part
//
always @(wb_fsm_state_cur or burst_len or
wb_err_i or wb_rty_i or wb_ack or wb_cti_o or wb_sel_o or wb_stb_o or wb_we_o or
biu_cyc_i or biu_stb or biu_cab_i or biu_sel_i or biu_we_i) begin
// States of WISHBONE Finite State Machine
case(wb_fsm_state_cur)
//
// WB FSM - combinatorial part
//
always @(wb_fsm_state_cur or burst_len or wb_err_i or wb_rty_i or wb_ack or
wb_cti_o or wb_sel_o or wb_stb_o or wb_we_o or biu_cyc_i or
biu_stb or biu_cab_i or biu_sel_i or biu_we_i) begin
// States of WISHBONE Finite State Machine
case(wb_fsm_state_cur)
// IDLE
wb_fsm_idle : begin
wb_cyc_nxt = biu_cyc_i && biu_stb;
wb_stb_nxt = biu_cyc_i && biu_stb;
wb_cti_nxt = {!biu_cab_i, 1'b1, !biu_cab_i};
if (biu_cyc_i && biu_stb)
wb_fsm_state_nxt = wb_fsm_trans;
else
wb_fsm_state_nxt = wb_fsm_idle;
wb_cyc_nxt = biu_cyc_i & biu_stb;
wb_stb_nxt = biu_cyc_i & biu_stb;
wb_cti_nxt = {!biu_cab_i, 1'b1, !biu_cab_i};
if (biu_cyc_i & biu_stb)
wb_fsm_state_nxt = wb_fsm_trans;
else
wb_fsm_state_nxt = wb_fsm_idle;
end
// normal TRANSFER
wb_fsm_trans : begin
wb_cyc_nxt = !wb_stb_o || !wb_err_i && !wb_rty_i && !(wb_ack && wb_cti_o == 3'b111);
wb_stb_nxt = !wb_stb_o || !wb_err_i && !wb_rty_i && !wb_ack || !wb_err_i && !wb_rty_i && wb_cti_o == 3'b010 && !wb_we_o;
wb_cti_nxt[2] = wb_stb_o && wb_ack && burst_len == 'h0 || wb_cti_o[2];
wb_cti_nxt[1] = 1'b1 ;
wb_cti_nxt[0] = wb_stb_o && wb_ack && burst_len == 'h0 || wb_cti_o[0];
//if ((!biu_cyc_i || !biu_stb || !biu_cab_i) && wb_cti_o == 3'b010 || biu_sel_i != wb_sel_o || biu_we_i != wb_we_o)
if ((!biu_cyc_i || !biu_stb || !biu_cab_i || biu_sel_i != wb_sel_o || biu_we_i != wb_we_o) && wb_cti_o == 3'b010)
wb_fsm_state_nxt = wb_fsm_last;
else if ((wb_err_i || wb_rty_i || wb_ack && wb_cti_o == 3'b111) && wb_stb_o)
wb_fsm_state_nxt = wb_fsm_idle;
else
wb_fsm_state_nxt = wb_fsm_trans;
wb_cyc_nxt = !wb_stb_o | !wb_err_i & !wb_rty_i &
!(wb_ack & wb_cti_o == 3'b111);
wb_stb_nxt = !wb_stb_o | !wb_err_i & !wb_rty_i & !wb_ack |
!wb_err_i & !wb_rty_i & wb_cti_o == 3'b010 /*& !wb_we_o -- Removed to add burst write, JPB*/;
wb_cti_nxt[2] = wb_stb_o & wb_ack & burst_len == 'h0 | wb_cti_o[2];
wb_cti_nxt[1] = 1'b1 ;
wb_cti_nxt[0] = wb_stb_o & wb_ack & burst_len == 'h0 | wb_cti_o[0];
//if ((!biu_cyc_i | !biu_stb | !biu_cab_i) & wb_cti_o == 3'b010 |
// biu_sel_i != wb_sel_o | biu_we_i != wb_we_o)
if ((!biu_cyc_i | !biu_stb | !biu_cab_i | biu_sel_i != wb_sel_o |
biu_we_i != wb_we_o) & wb_cti_o == 3'b010)
wb_fsm_state_nxt = wb_fsm_last;
else if ((wb_err_i | wb_rty_i | wb_ack & wb_cti_o==3'b111) &
wb_stb_o)
wb_fsm_state_nxt = wb_fsm_idle;
else
wb_fsm_state_nxt = wb_fsm_trans;
end
// LAST transfer
wb_fsm_last : begin
wb_cyc_nxt = !wb_stb_o || !wb_err_i && !wb_rty_i && !(wb_ack && wb_cti_o == 3'b111);
wb_stb_nxt = !wb_stb_o || !wb_err_i && !wb_rty_i && !(wb_ack && wb_cti_o == 3'b111);
wb_cti_nxt[2] = wb_ack && wb_stb_o || wb_cti_o[2];
wb_cti_nxt[1] = 1'b1 ;
wb_cti_nxt[0] = wb_ack && wb_stb_o || wb_cti_o[0];
if ((wb_err_i || wb_rty_i || wb_ack && wb_cti_o == 3'b111) && wb_stb_o)
wb_fsm_state_nxt = wb_fsm_idle;
else
wb_fsm_state_nxt = wb_fsm_last;
wb_cyc_nxt = !wb_stb_o | !wb_err_i & !wb_rty_i &
!(wb_ack & wb_cti_o == 3'b111);
wb_stb_nxt = !wb_stb_o | !wb_err_i & !wb_rty_i &
!(wb_ack & wb_cti_o == 3'b111);
wb_cti_nxt[2] = wb_ack & wb_stb_o | wb_cti_o[2];
wb_cti_nxt[1] = 1'b1 ;
wb_cti_nxt[0] = wb_ack & wb_stb_o | wb_cti_o[0];
if ((wb_err_i | wb_rty_i | wb_ack & wb_cti_o == 3'b111) & wb_stb_o)
wb_fsm_state_nxt = wb_fsm_idle;
else
wb_fsm_state_nxt = wb_fsm_last;
end
// default state
default:begin
wb_cyc_nxt = 1'bx;
wb_stb_nxt = 1'bx;
wb_cti_nxt = 3'bxxx;
wb_fsm_state_nxt = 2'bxx;
wb_cyc_nxt = 1'bx;
wb_stb_nxt = 1'bx;
wb_cti_nxt = 3'bxxx;
wb_fsm_state_nxt = 2'bxx;
end
endcase
end
endcase
end
 
//
// WB FSM - output signals
//
always @(posedge wb_clk_i or posedge wb_rst_i) begin
if (wb_rst_i) begin
wb_cyc_o <= #1 1'b0;
wb_stb_o <= #1 1'b0;
wb_cti_o <= #1 3'b111;
wb_bte_o <= #1 2'b01; // 4-beat wrap burst = constant
//
// WB FSM - output signals
//
always @(posedge wb_clk_i or posedge wb_rst_i) begin
if (wb_rst_i) begin
wb_cyc_o <= 1'b0;
wb_stb_o <= 1'b0;
wb_cti_o <= 3'b111;
wb_bte_o <= 2'b01; // 4-beat wrap burst = constant
`ifdef OR1200_WB_CAB
wb_cab_o <= #1 1'b0;
wb_cab_o <= 1'b0;
`endif
wb_we_o <= #1 1'b0;
wb_sel_o <= #1 4'hf;
wb_adr_o <= #1 {aw{1'b0}};
wb_dat_o <= #1 {dw{1'b0}};
end
else begin
wb_cyc_o <= #1 wb_cyc_nxt;
// wb_stb_o <= #1 wb_stb_nxt;
if (wb_ack && wb_cti_o == 3'b111)
wb_stb_o <= #1 1'b0;
else
wb_stb_o <= #1 wb_stb_nxt;
wb_cti_o <= #1 wb_cti_nxt;
wb_bte_o <= #1 2'b01; // 4-beat wrap burst = constant
wb_we_o <= 1'b0;
wb_sel_o <= 4'hf;
wb_adr_o <= {aw{1'b0}};
`ifdef OR1200_NO_DC
wb_dat_o <= {dw{1'b0}};
`endif
end
else begin
wb_cyc_o <= wb_cyc_nxt;
// wb_stb_o <= wb_stb_nxt;
if (wb_ack & wb_cti_o == 3'b111)
wb_stb_o <= 1'b0;
else
wb_stb_o <= wb_stb_nxt;
wb_cti_o <= wb_cti_nxt;
wb_bte_o <= 2'b01; // 4-beat wrap burst = constant
`ifdef OR1200_WB_CAB
wb_cab_o <= #1 biu_cab_i;
wb_cab_o <= biu_cab_i;
`endif
// we and sel - set at beginning of access
if (wb_fsm_state_cur == wb_fsm_idle) begin
wb_we_o <= #1 biu_we_i;
wb_sel_o <= #1 biu_sel_i;
end
// adr - set at beginning of access and changed at every termination
if (wb_fsm_state_cur == wb_fsm_idle) begin
wb_adr_o <= #1 biu_adr_i;
end
else if (wb_stb_o && wb_ack) begin
wb_adr_o[3:2] <= #1 wb_adr_o[3:2] + 1'b1;
end
// dat - write data changed after avery subsequent write access
if (!wb_stb_o) begin
wb_dat_o <= #1 biu_dat_i;
end
end
end
// we and sel - set at beginning of access
if (wb_fsm_state_cur == wb_fsm_idle) begin
wb_we_o <= biu_we_i;
wb_sel_o <= biu_sel_i;
end
// adr - set at beginning of access and changed at every termination
if (wb_fsm_state_cur == wb_fsm_idle) begin
wb_adr_o <= biu_adr_i;
end
else if (wb_stb_o & wb_ack) begin
wb_adr_o[3:2] <= wb_adr_o[3:2] + 1'b1;
end
`ifdef OR1200_NO_DC
// dat - write data changed after avery subsequent write access
if (!wb_stb_o) begin
wb_dat_o <= biu_dat_i;
end
`endif
end
end
 
//
// WB & BIU termination toggle counters
//
always @(posedge wb_clk_i or posedge wb_rst_i) begin
if (wb_rst_i) begin
wb_ack_cnt <= #1 1'b0;
wb_err_cnt <= #1 1'b0;
wb_rty_cnt <= #1 1'b0;
end
else begin
// WB ack toggle counter
if (wb_fsm_state_cur == wb_fsm_idle || !clmode)
wb_ack_cnt <= #1 1'b0;
else if (wb_stb_o && wb_ack)
wb_ack_cnt <= #1 !wb_ack_cnt;
// WB err toggle counter
if (wb_fsm_state_cur == wb_fsm_idle || !clmode)
wb_err_cnt <= #1 1'b0;
else if (wb_stb_o && wb_err_i)
wb_err_cnt <= #1 !wb_err_cnt;
// WB rty toggle counter
if (wb_fsm_state_cur == wb_fsm_idle || !clmode)
wb_rty_cnt <= #1 1'b0;
else if (wb_stb_o && wb_rty_i)
wb_rty_cnt <= #1 !wb_rty_cnt;
end
end
//
// WB & BIU termination toggle counters
//
always @(posedge wb_clk_i or posedge wb_rst_i) begin
if (wb_rst_i) begin
wb_ack_cnt <= 1'b0;
wb_err_cnt <= 1'b0;
wb_rty_cnt <= 1'b0;
end
else begin
// WB ack toggle counter
if (wb_fsm_state_cur == wb_fsm_idle | !clmode)
wb_ack_cnt <= 1'b0;
else if (wb_stb_o & wb_ack)
wb_ack_cnt <= !wb_ack_cnt;
// WB err toggle counter
if (wb_fsm_state_cur == wb_fsm_idle | !clmode)
wb_err_cnt <= 1'b0;
else if (wb_stb_o & wb_err_i)
wb_err_cnt <= !wb_err_cnt;
// WB rty toggle counter
if (wb_fsm_state_cur == wb_fsm_idle | !clmode)
wb_rty_cnt <= 1'b0;
else if (wb_stb_o & wb_rty_i)
wb_rty_cnt <= !wb_rty_cnt;
end
end
 
always @(posedge clk or posedge rst) begin
if (rst) begin
biu_stb_reg <= #1 1'b0;
biu_ack_cnt <= #1 1'b0;
biu_err_cnt <= #1 1'b0;
biu_rty_cnt <= #1 1'b0;
always @(posedge clk or posedge rst) begin
if (rst) begin
biu_stb_reg <= 1'b0;
biu_ack_cnt <= 1'b0;
biu_err_cnt <= 1'b0;
biu_rty_cnt <= 1'b0;
`ifdef OR1200_WB_RETRY
retry_cnt <= {`OR1200_WB_RETRY{1'b0}};
retry_cnt <= {`OR1200_WB_RETRY{1'b0}};
`endif
end
else begin
// BIU strobe
if (biu_stb_i && !biu_cab_i && biu_ack_o)
biu_stb_reg <= #1 1'b0;
else
biu_stb_reg <= #1 biu_stb_i;
// BIU ack toggle counter
if (wb_fsm_state_cur == wb_fsm_idle || !clmode)
biu_ack_cnt <= #1 1'b0 ;
else if (biu_ack_o)
biu_ack_cnt <= #1 !biu_ack_cnt ;
// BIU err toggle counter
if (wb_fsm_state_cur == wb_fsm_idle || !clmode)
biu_err_cnt <= #1 1'b0 ;
else if (wb_err_i && biu_err_o)
biu_err_cnt <= #1 !biu_err_cnt ;
// BIU rty toggle counter
if (wb_fsm_state_cur == wb_fsm_idle || !clmode)
biu_rty_cnt <= #1 1'b0 ;
else if (biu_rty)
biu_rty_cnt <= #1 !biu_rty_cnt ;
end
else begin
// BIU strobe
if (biu_stb_i & !biu_cab_i & biu_ack_o)
biu_stb_reg <= 1'b0;
else
biu_stb_reg <= biu_stb_i;
// BIU ack toggle counter
if (wb_fsm_state_cur == wb_fsm_idle | !clmode)
biu_ack_cnt <= 1'b0 ;
else if (biu_ack_o)
biu_ack_cnt <= !biu_ack_cnt ;
// BIU err toggle counter
if (wb_fsm_state_cur == wb_fsm_idle | !clmode)
biu_err_cnt <= 1'b0 ;
else if (wb_err_i & biu_err_o)
biu_err_cnt <= !biu_err_cnt ;
// BIU rty toggle counter
if (wb_fsm_state_cur == wb_fsm_idle | !clmode)
biu_rty_cnt <= 1'b0 ;
else if (biu_rty)
biu_rty_cnt <= !biu_rty_cnt ;
`ifdef OR1200_WB_RETRY
if (biu_ack_o || biu_err_o)
retry_cnt <= #1 {`OR1200_WB_RETRY{1'b0}};
else if (biu_rty)
retry_cnt <= #1 retry_cnt + 1'b1;
if (biu_ack_o | biu_err_o)
retry_cnt <= {`OR1200_WB_RETRY{1'b0}};
else if (biu_rty)
retry_cnt <= retry_cnt + 1'b1;
`endif
end
end
end
end
 
assign biu_stb = biu_stb_i && biu_stb_reg;
assign biu_stb = biu_stb_i & biu_stb_reg;
 
//
// Input BIU data bus
//
assign biu_dat_o = wb_dat_i;
//
// Input BIU data bus
//
assign biu_dat_o = wb_dat_i;
 
//
// Input BIU termination signals
//
assign biu_rty = (wb_fsm_state_cur == wb_fsm_trans) && wb_rty_i && wb_stb_o && (wb_rty_cnt ~^ biu_rty_cnt);
assign biu_ack_o = (wb_fsm_state_cur == wb_fsm_trans) && wb_ack && wb_stb_o && (wb_ack_cnt ~^ biu_ack_cnt);
assign biu_err_o = (wb_fsm_state_cur == wb_fsm_trans) && wb_err_i && wb_stb_o && (wb_err_cnt ~^ biu_err_cnt)
//
// Input BIU termination signals
//
assign biu_rty = (wb_fsm_state_cur == wb_fsm_trans) & wb_rty_i & wb_stb_o & (wb_rty_cnt ~^ biu_rty_cnt);
assign biu_ack_o = (wb_fsm_state_cur == wb_fsm_trans) & wb_ack & wb_stb_o & (wb_ack_cnt ~^ biu_ack_cnt);
assign biu_err_o = (wb_fsm_state_cur == wb_fsm_trans) & wb_err_i & wb_stb_o & (wb_err_cnt ~^ biu_err_cnt)
`ifdef OR1200_WB_RETRY
|| biu_rty && retry_cnt[`OR1200_WB_RETRY-1];
| biu_rty & retry_cnt[`OR1200_WB_RETRY-1];
`else
;
;
`endif
 
 
/verilog/or1200_du.v
143,9 → 143,9
//
always @(posedge clk or posedge rst)
if (rst)
dbg_is_o <= #1 2'b00;
dbg_is_o <= 2'b00;
else if (!ex_freeze & ~((ex_insn[31:26] == `OR1200_OR32_NOP) & ex_insn[16]))
dbg_is_o <= #1 ~dbg_is_o;
dbg_is_o <= ~dbg_is_o;
`ifdef UNUSED
assign dbg_is_o = 2'b00;
`endif
170,12 → 170,12
//
always @(posedge clk or posedge rst) begin
if (rst) begin
dbg_ack <= #1 1'b0;
dbg_ack_o <= #1 1'b0;
dbg_ack <= 1'b0;
dbg_ack_o <= 1'b0;
end
else begin
dbg_ack <= #1 dbg_stb_i; // valid when du_dat_i
dbg_ack_o <= #1 dbg_ack & dbg_stb_i; // valid when dbg_dat_o
dbg_ack <= dbg_stb_i; // valid when du_dat_i
dbg_ack_o <= dbg_ack & dbg_stb_i; // valid when dbg_dat_o
end
end
 
183,7 → 183,7
// Register data output
//
always @(posedge clk)
dbg_dat_o <= #1 du_dat_i;
dbg_dat_o <= du_dat_i;
 
`ifdef OR1200_DU_IMPLEMENTED
 
588,9 → 588,9
//
always @(posedge clk or posedge rst)
if (rst)
dbg_bp_r <= #1 1'b0;
dbg_bp_r <= 1'b0;
else if (!ex_freeze)
dbg_bp_r <= #1 |except_stop
dbg_bp_r <= |except_stop
`ifdef OR1200_DU_DMR1_ST
| ~((ex_insn[31:26] == `OR1200_OR32_NOP) & ex_insn[16]) & dmr1[`OR1200_DU_DMR1_ST]
`endif
599,7 → 599,7
`endif
;
else
dbg_bp_r <= #1 |except_stop;
dbg_bp_r <= |except_stop;
 
//
// Write to DMR1
610,9 → 610,9
dmr1 <= 25'h000_0000;
else if (dmr1_sel && spr_write)
`ifdef OR1200_DU_HWBKPTS
dmr1 <= #1 spr_dat_i[24:0];
dmr1 <= spr_dat_i[24:0];
`else
dmr1 <= #1 {1'b0, spr_dat_i[23:22], 22'h00_0000};
dmr1 <= {1'b0, spr_dat_i[23:22], 22'h00_0000};
`endif
`else
assign dmr1 = 25'h000_0000;
626,7 → 626,7
if (rst)
dmr2 <= 24'h00_0000;
else if (dmr2_sel && spr_write)
dmr2 <= #1 spr_dat_i[23:0];
dmr2 <= spr_dat_i[23:0];
`else
assign dmr2 = 24'h00_0000;
`endif
639,7 → 639,7
if (rst)
dsr <= {`OR1200_DU_DSR_WIDTH{1'b0}};
else if (dsr_sel && spr_write)
dsr <= #1 spr_dat_i[`OR1200_DU_DSR_WIDTH-1:0];
dsr <= spr_dat_i[`OR1200_DU_DSR_WIDTH-1:0];
`else
assign dsr = {`OR1200_DU_DSR_WIDTH{1'b0}};
`endif
652,9 → 652,9
if (rst)
drr <= 14'b0;
else if (drr_sel && spr_write)
drr <= #1 spr_dat_i[13:0];
drr <= spr_dat_i[13:0];
else
drr <= #1 drr | except_stop;
drr <= drr | except_stop;
`else
assign drr = 14'b0;
`endif
667,7 → 667,7
if (rst)
dvr0 <= 32'h0000_0000;
else if (dvr0_sel && spr_write)
dvr0 <= #1 spr_dat_i[31:0];
dvr0 <= spr_dat_i[31:0];
`else
assign dvr0 = 32'h0000_0000;
`endif
680,7 → 680,7
if (rst)
dvr1 <= 32'h0000_0000;
else if (dvr1_sel && spr_write)
dvr1 <= #1 spr_dat_i[31:0];
dvr1 <= spr_dat_i[31:0];
`else
assign dvr1 = 32'h0000_0000;
`endif
693,7 → 693,7
if (rst)
dvr2 <= 32'h0000_0000;
else if (dvr2_sel && spr_write)
dvr2 <= #1 spr_dat_i[31:0];
dvr2 <= spr_dat_i[31:0];
`else
assign dvr2 = 32'h0000_0000;
`endif
706,7 → 706,7
if (rst)
dvr3 <= 32'h0000_0000;
else if (dvr3_sel && spr_write)
dvr3 <= #1 spr_dat_i[31:0];
dvr3 <= spr_dat_i[31:0];
`else
assign dvr3 = 32'h0000_0000;
`endif
719,7 → 719,7
if (rst)
dvr4 <= 32'h0000_0000;
else if (dvr4_sel && spr_write)
dvr4 <= #1 spr_dat_i[31:0];
dvr4 <= spr_dat_i[31:0];
`else
assign dvr4 = 32'h0000_0000;
`endif
732,7 → 732,7
if (rst)
dvr5 <= 32'h0000_0000;
else if (dvr5_sel && spr_write)
dvr5 <= #1 spr_dat_i[31:0];
dvr5 <= spr_dat_i[31:0];
`else
assign dvr5 = 32'h0000_0000;
`endif
745,7 → 745,7
if (rst)
dvr6 <= 32'h0000_0000;
else if (dvr6_sel && spr_write)
dvr6 <= #1 spr_dat_i[31:0];
dvr6 <= spr_dat_i[31:0];
`else
assign dvr6 = 32'h0000_0000;
`endif
758,7 → 758,7
if (rst)
dvr7 <= 32'h0000_0000;
else if (dvr7_sel && spr_write)
dvr7 <= #1 spr_dat_i[31:0];
dvr7 <= spr_dat_i[31:0];
`else
assign dvr7 = 32'h0000_0000;
`endif
771,7 → 771,7
if (rst)
dcr0 <= 8'h00;
else if (dcr0_sel && spr_write)
dcr0 <= #1 spr_dat_i[7:0];
dcr0 <= spr_dat_i[7:0];
`else
assign dcr0 = 8'h00;
`endif
784,7 → 784,7
if (rst)
dcr1 <= 8'h00;
else if (dcr1_sel && spr_write)
dcr1 <= #1 spr_dat_i[7:0];
dcr1 <= spr_dat_i[7:0];
`else
assign dcr1 = 8'h00;
`endif
797,7 → 797,7
if (rst)
dcr2 <= 8'h00;
else if (dcr2_sel && spr_write)
dcr2 <= #1 spr_dat_i[7:0];
dcr2 <= spr_dat_i[7:0];
`else
assign dcr2 = 8'h00;
`endif
810,7 → 810,7
if (rst)
dcr3 <= 8'h00;
else if (dcr3_sel && spr_write)
dcr3 <= #1 spr_dat_i[7:0];
dcr3 <= spr_dat_i[7:0];
`else
assign dcr3 = 8'h00;
`endif
823,7 → 823,7
if (rst)
dcr4 <= 8'h00;
else if (dcr4_sel && spr_write)
dcr4 <= #1 spr_dat_i[7:0];
dcr4 <= spr_dat_i[7:0];
`else
assign dcr4 = 8'h00;
`endif
836,7 → 836,7
if (rst)
dcr5 <= 8'h00;
else if (dcr5_sel && spr_write)
dcr5 <= #1 spr_dat_i[7:0];
dcr5 <= spr_dat_i[7:0];
`else
assign dcr5 = 8'h00;
`endif
849,7 → 849,7
if (rst)
dcr6 <= 8'h00;
else if (dcr6_sel && spr_write)
dcr6 <= #1 spr_dat_i[7:0];
dcr6 <= spr_dat_i[7:0];
`else
assign dcr6 = 8'h00;
`endif
862,7 → 862,7
if (rst)
dcr7 <= 8'h00;
else if (dcr7_sel && spr_write)
dcr7 <= #1 spr_dat_i[7:0];
dcr7 <= spr_dat_i[7:0];
`else
assign dcr7 = 8'h00;
`endif
875,9 → 875,9
if (rst)
dwcr0 <= 32'h0000_0000;
else if (dwcr0_sel && spr_write)
dwcr0 <= #1 spr_dat_i[31:0];
dwcr0 <= spr_dat_i[31:0];
else if (incr_wpcntr0)
dwcr0[`OR1200_DU_DWCR_COUNT] <= #1 dwcr0[`OR1200_DU_DWCR_COUNT] + 16'h0001;
dwcr0[`OR1200_DU_DWCR_COUNT] <= dwcr0[`OR1200_DU_DWCR_COUNT] + 16'h0001;
`else
assign dwcr0 = 32'h0000_0000;
`endif
890,9 → 890,9
if (rst)
dwcr1 <= 32'h0000_0000;
else if (dwcr1_sel && spr_write)
dwcr1 <= #1 spr_dat_i[31:0];
dwcr1 <= spr_dat_i[31:0];
else if (incr_wpcntr1)
dwcr1[`OR1200_DU_DWCR_COUNT] <= #1 dwcr1[`OR1200_DU_DWCR_COUNT] + 16'h0001;
dwcr1[`OR1200_DU_DWCR_COUNT] <= dwcr1[`OR1200_DU_DWCR_COUNT] + 16'h0001;
`else
assign dwcr1 = 32'h0000_0000;
`endif
1622,11 → 1622,11
// Hold du_hwbkpt if ex_freeze is active in order to cause trap exception
always @(posedge clk or posedge rst)
if (rst)
du_hwbkpt_hold <= #1 1'b0;
du_hwbkpt_hold <= 1'b0;
else if (du_hwbkpt & ex_freeze)
du_hwbkpt_hold <= #1 1'b1;
du_hwbkpt_hold <= 1'b1;
else if (!ex_freeze)
du_hwbkpt_hold <= #1 1'b0;
du_hwbkpt_hold <= 1'b0;
 
`ifdef OR1200_DU_TB_IMPLEMENTED
//
1647,9 → 1647,9
//
always @(posedge clk or posedge rst)
if (rst)
tb_wadr <= #1 8'h00;
tb_wadr <= 8'h00;
else if (tb_enw)
tb_wadr <= #1 tb_wadr + 8'd1;
tb_wadr <= tb_wadr + 8'd1;
 
//
// Free running counter (time stamp)
1656,9 → 1656,9
//
always @(posedge clk or posedge rst)
if (rst)
tb_timstmp <= #1 32'h00000000;
tb_timstmp <= 32'h00000000;
else if (!dbg_bp_r)
tb_timstmp <= #1 tb_timstmp + 32'd1;
tb_timstmp <= tb_timstmp + 32'd1;
 
//
// Trace buffer RAMs
/verilog/or1200_pm.v
139,14 → 139,14
if (rst)
{dcge, sme, dme, sdf} <= 7'b0;
else if (pmr_sel && spr_write) begin
sdf <= #1 spr_dat_i[`OR1200_PM_PMR_SDF];
dme <= #1 spr_dat_i[`OR1200_PM_PMR_DME];
sme <= #1 spr_dat_i[`OR1200_PM_PMR_SME];
dcge <= #1 spr_dat_i[`OR1200_PM_PMR_DCGE];
sdf <= spr_dat_i[`OR1200_PM_PMR_SDF];
dme <= spr_dat_i[`OR1200_PM_PMR_DME];
sme <= spr_dat_i[`OR1200_PM_PMR_SME];
dcge <= spr_dat_i[`OR1200_PM_PMR_DCGE];
end
else if (pic_wakeup) begin
dme <= #1 1'b0;
sme <= #1 1'b0;
dme <= 1'b0;
sme <= 1'b0;
end
 
//
/verilog/or1200_ic_top.v
3,7 → 3,7
//// OR1200's Data Cache top level ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Instantiation of all IC blocks. ////
41,64 → 41,9
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_ic_top.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// No update
//
// Revision 1.9 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.7.4.2 2003/12/09 11:46:48 simons
// Mbist nameing changed, Artisan ram instance signal names fixed, some synthesis waning fixed.
//
// Revision 1.7.4.1 2003/07/08 15:36:37 lampret
// Added embedded memory QMEM.
//
// Revision 1.7 2002/10/17 20:04:40 lampret
// Added BIST scan. Special VS RAMs need to be used to implement BIST.
//
// Revision 1.6 2002/03/29 15:16:55 lampret
// Some of the warnings fixed.
//
// Revision 1.5 2002/02/11 04:33:17 lampret
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
//
// Revision 1.4 2002/02/01 19:56:54 lampret
// Fixed combinational loops.
//
// Revision 1.3 2002/01/28 01:16:00 lampret
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
//
// Revision 1.2 2002/01/14 06:18:22 lampret
// Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.10 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from ic.v and ic.v. Fixed CR+LF.
//
// Revision 1.9 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:35 igorm
// no message
//
// Revision 1.4 2001/08/13 03:36:20 lampret
// Added cfg regs. Moved all defines into one defines.v file. More cleanup.
//
// Revision 1.3 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.2 2001/07/22 03:31:53 lampret
// Fixed RAM's oen bug. Cache bypass under development.
//
// Revision 1.1 2001/07/20 00:46:03 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
227,7 → 172,9
assign icbiu_adr_o = ic_addr;
assign ic_inv = spr_cs & spr_write;
assign ictag_we = icfsm_tag_we | ic_inv;
assign ictag_addr = ic_inv ? spr_dat_i[`OR1200_ICINDXH:`OR1200_ICLS] : ic_addr[`OR1200_ICINDXH:`OR1200_ICLS];
assign ictag_addr = ic_inv ?
spr_dat_i[`OR1200_ICINDXH:`OR1200_ICLS] :
ic_addr[`OR1200_ICINDXH:`OR1200_ICLS];
assign ictag_en = ic_inv | ic_en;
assign ictag_v = ~ic_inv;
 
/verilog/or1200_fpu_post_norm_intfloat_conv.v
0,0 → 1,442
/////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_post_norm_intfloat_conv ////
//// Floating Point Post Normalisation Unit ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// Modified by Julius Baxter, July, 2010 ////
//// julius.baxter@orsoc.se ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
 
`timescale 1ns / 100ps
 
module or1200_fpu_post_norm_intfloat_conv
(
clk, fpu_op, opas, sign, rmode, fract_in,
exp_in, opa_dn, opa_nan, opa_inf, opb_dn, out,
ine, inv, overflow, underflow, f2i_out_sign
);
input clk;
input [2:0] fpu_op;
input opas;
input sign;
input [1:0] rmode;
input [47:0] fract_in;
input [7:0] exp_in;
input opa_dn, opb_dn;
input opa_nan, opa_inf;
output [30:0] out;
output ine, inv;
output overflow, underflow;
output f2i_out_sign;
 
////////////////////////////////////////////////////////////////////////
//
// Local Wires and registers
//
 
/*wire*/ reg [22:0] fract_out;
/*wire*/reg [7:0] exp_out;
wire [30:0] out;
wire exp_out1_co, overflow, underflow;
wire [22:0] fract_out_final;
reg [22:0] fract_out_rnd;
wire [8:0] exp_next_mi;
wire dn;
wire exp_rnd_adj;
wire [7:0] exp_out_final;
reg [7:0] exp_out_rnd;
wire op_dn = opa_dn | opb_dn;
wire op_mul = fpu_op[2:0]==3'b010;
wire op_div = fpu_op[2:0]==3'b011;
wire op_i2f = fpu_op[2:0]==3'b100;
wire op_f2i = fpu_op[2:0]==3'b101;
reg [5:0] fi_ldz;
 
wire g, r, s;
wire round, round2, round2a, round2_fasu, round2_fmul;
wire [7:0] exp_out_rnd0, exp_out_rnd1, exp_out_rnd2, exp_out_rnd2a;
wire [22:0] fract_out_rnd0, fract_out_rnd1, fract_out_rnd2,
fract_out_rnd2a;
wire exp_rnd_adj0, exp_rnd_adj2a;
wire r_sign;
wire ovf0, ovf1;
wire [23:0] fract_out_pl1;
wire [7:0] exp_out_pl1, exp_out_mi1;
wire exp_out_00, exp_out_fe, exp_out_ff, exp_in_00,
exp_in_ff;
wire exp_out_final_ff, fract_out_7fffff;
/*wire*/reg [24:0] fract_trunc;
wire [7:0] exp_out1;
wire grs_sel;
wire fract_out_00;
reg fract_in_00;
wire shft_co;
wire [8:0] exp_in_pl1, exp_in_mi1;
wire [47:0] fract_in_shftr;
wire [47:0] fract_in_shftl;
 
wire [7:0] shft2;
wire [7:0] exp_out1_mi1;
 
wire [6:0] fi_ldz_2a;
wire [7:0] fi_ldz_2;
 
wire left_right;
wire [7:0] shift_right;
wire [7:0] shift_left;
wire [7:0] fasu_shift;
 
wire [5:0] fi_ldz_mi1;
wire [5:0] fi_ldz_mi22;
wire [6:0] ldz_all;
 
wire [7:0] f2i_shft;
wire [55:0] exp_f2i_1;
wire f2i_zero, f2i_max;
wire [7:0] f2i_emin;
wire f2i_exp_gt_max ,f2i_exp_lt_min;
wire [7:0] conv_shft;
wire [7:0] exp_i2f, exp_f2i, conv_exp;
wire round2_f2i;
 
////////////////////////////////////////////////////////////////////////
//
// Normalize and Round Logic
//
 
// ---------------------------------------------------------------------
// Count Leading zeros in fraction
 
always @(/*fract_in*/ posedge clk)
casex(fract_in) // synopsys full_case parallel_case
48'b1???????????????????????????????????????????????: fi_ldz <= 1;
48'b01??????????????????????????????????????????????: fi_ldz <= 2;
48'b001?????????????????????????????????????????????: fi_ldz <= 3;
48'b0001????????????????????????????????????????????: fi_ldz <= 4;
48'b00001???????????????????????????????????????????: fi_ldz <= 5;
48'b000001??????????????????????????????????????????: fi_ldz <= 6;
48'b0000001?????????????????????????????????????????: fi_ldz <= 7;
48'b00000001????????????????????????????????????????: fi_ldz <= 8;
48'b000000001???????????????????????????????????????: fi_ldz <= 9;
48'b0000000001??????????????????????????????????????: fi_ldz <= 10;
48'b00000000001?????????????????????????????????????: fi_ldz <= 11;
48'b000000000001????????????????????????????????????: fi_ldz <= 12;
48'b0000000000001???????????????????????????????????: fi_ldz <= 13;
48'b00000000000001??????????????????????????????????: fi_ldz <= 14;
48'b000000000000001?????????????????????????????????: fi_ldz <= 15;
48'b0000000000000001????????????????????????????????: fi_ldz <= 16;
48'b00000000000000001???????????????????????????????: fi_ldz <= 17;
48'b000000000000000001??????????????????????????????: fi_ldz <= 18;
48'b0000000000000000001?????????????????????????????: fi_ldz <= 19;
48'b00000000000000000001????????????????????????????: fi_ldz <= 20;
48'b000000000000000000001???????????????????????????: fi_ldz <= 21;
48'b0000000000000000000001??????????????????????????: fi_ldz <= 22;
48'b00000000000000000000001?????????????????????????: fi_ldz <= 23;
48'b000000000000000000000001????????????????????????: fi_ldz <= 24;
48'b0000000000000000000000001???????????????????????: fi_ldz <= 25;
48'b00000000000000000000000001??????????????????????: fi_ldz <= 26;
48'b000000000000000000000000001?????????????????????: fi_ldz <= 27;
48'b0000000000000000000000000001????????????????????: fi_ldz <= 28;
48'b00000000000000000000000000001???????????????????: fi_ldz <= 29;
48'b000000000000000000000000000001??????????????????: fi_ldz <= 30;
48'b0000000000000000000000000000001?????????????????: fi_ldz <= 31;
48'b00000000000000000000000000000001????????????????: fi_ldz <= 32;
48'b000000000000000000000000000000001???????????????: fi_ldz <= 33;
48'b0000000000000000000000000000000001??????????????: fi_ldz <= 34;
48'b00000000000000000000000000000000001?????????????: fi_ldz <= 35;
48'b000000000000000000000000000000000001????????????: fi_ldz <= 36;
48'b0000000000000000000000000000000000001???????????: fi_ldz <= 37;
48'b00000000000000000000000000000000000001??????????: fi_ldz <= 38;
48'b000000000000000000000000000000000000001?????????: fi_ldz <= 39;
48'b0000000000000000000000000000000000000001????????: fi_ldz <= 40;
48'b00000000000000000000000000000000000000001???????: fi_ldz <= 41;
48'b000000000000000000000000000000000000000001??????: fi_ldz <= 42;
48'b0000000000000000000000000000000000000000001?????: fi_ldz <= 43;
48'b00000000000000000000000000000000000000000001????: fi_ldz <= 44;
48'b000000000000000000000000000000000000000000001???: fi_ldz <= 45;
48'b0000000000000000000000000000000000000000000001??: fi_ldz <= 46;
48'b00000000000000000000000000000000000000000000001?: fi_ldz <= 47;
48'b00000000000000000000000000000000000000000000000?: fi_ldz <= 48;
endcase
 
 
// ---------------------------------------------------------------------
// Normalize
 
wire exp_in_80;
wire rmode_00, rmode_01, rmode_10, rmode_11;
 
// Misc common signals
assign exp_in_ff = &exp_in;
assign exp_in_00 = !(|exp_in);
assign exp_in_80 = exp_in[7] & !(|exp_in[6:0]);
assign exp_out_ff = &exp_out;
assign exp_out_00 = !(|exp_out);
assign exp_out_fe = &exp_out[7:1] & !exp_out[0];
assign exp_out_final_ff = &exp_out_final;
 
assign fract_out_7fffff = &fract_out;
assign fract_out_00 = !(|fract_out);
//assign fract_in_00 = !(|fract_in);
always @(posedge clk)
fract_in_00 <= !(|fract_in);
 
assign rmode_00 = (rmode==2'b00);
assign rmode_01 = (rmode==2'b01);
assign rmode_10 = (rmode==2'b10);
assign rmode_11 = (rmode==2'b11);
 
// Fasu Output will be denormalized ...
assign dn = !op_mul & !op_div &
(exp_in_00 | (exp_next_mi[8] & !fract_in[47]) );
 
// ---------------------------------------------------------------------
// Fraction Normalization
parameter f2i_emax = 8'h9d;
 
// Special Signals for f2i
assign f2i_emin = rmode_00 ? 8'h7e : 8'h7f;
assign f2i_exp_gt_max = (exp_in > f2i_emax);
assign f2i_exp_lt_min = (exp_in < f2i_emin);
// Incremented fraction for rounding
assign fract_out_pl1 = fract_out + 1;
 
/*
assign f2i_zero = (!opas & (exp_in<f2i_emin)) |
(opas & (exp_in>f2i_emax)) |
(opas & (exp_in<f2i_emin) & (fract_in_00 | !rmode_11));
 
assign f2i_max = (!opas & (exp_in>f2i_emax)) |
(opas & (exp_in<f2i_emin) & !fract_in_00 & rmode_11);
*/
// Zero when :
// a) too small exp. and positive sign - result will be 0
// b) too big exp. and negative sign - result will be largest possible -int
// c) -infinity: largest possible -int
// d) -0.0: give positive 0
assign f2i_zero = (
( (f2i_exp_lt_min & (opas & (!rmode_11 | fract_in_00))) |
(f2i_exp_lt_min & !opas) |
(f2i_exp_gt_max & opas) )
& !(&exp_in)
) |
// -inf case
(opa_inf & opas) |
// -0.0 case
(fract_in_00 & exp_in_00);
 
// Maximum :
// a) too big exp and positive sign - result will be maximum int.
// b) rounding negative down and less than minimum expon. for int = -1
// c) +/- NaN or +inf - result will be maximum int
// d) disabled when the -0.0 case comes up
assign f2i_max = (
( ((!opas & f2i_exp_gt_max) |
(f2i_exp_lt_min & !fract_in_00 & rmode_11 & opas))
& !(&exp_in)) |
// Either +/- NaN, or +inf
(opa_nan | (opa_inf & !opas))) &
// .. and NOT -0.0( 0x80000000)
!(opas & fract_in_00 & exp_in_00);
// Claculate various shifting options
assign f2i_shft = exp_in-8'h7d;
 
assign conv_shft = op_f2i ? f2i_shft : {2'h0, fi_ldz};
 
assign fract_in_shftl = (|conv_shft[7:6] | (f2i_zero & op_f2i)) ?
0 : fract_in<<conv_shft[5:0];
 
// Final fraction output
always @(posedge clk)
{fract_out,fract_trunc} <= fract_in_shftl;
 
// ---------------------------------------------------------------------
// Exponent Normalization
 
assign fi_ldz_mi1 = fi_ldz - 1;
assign fi_ldz_mi22 = fi_ldz - 22;
assign exp_out_pl1 = exp_out + 1;
assign exp_out_mi1 = exp_out - 1;
assign exp_in_pl1 = exp_in + 1; // 9 bits - includes carry out
assign exp_in_mi1 = exp_in - 1; // 9 bits - includes carry out
assign exp_out1_mi1 = exp_out1 - 1;
 
assign exp_next_mi = exp_in_pl1 - fi_ldz_mi1; // 9 bits - includes carry out
 
assign {exp_out1_co, exp_out1} = fract_in[47] ? exp_in_pl1 : exp_next_mi;
// Only ever force positive if:
// i) It's a NaN
// ii) It's zero and not -inf
// iii) We've rounded to 0 (both fract and exp out are 0 and not forced)
// Force to 1 (negative) when have negative sign with too big exponent
assign f2i_out_sign = (opas & (exp_in>f2i_emax) & f2i_zero) ?
1 : opa_nan | (f2i_zero & !f2i_max & !(opa_inf & opas))
| (!(|out) & !f2i_zero)
?
0 :opas;
 
assign exp_i2f = fract_in_00 ? (opas ? 8'h9e : 0) : (8'h9e-fi_ldz);
assign exp_f2i_1 = {{8{fract_in[47]}}, fract_in }<<f2i_shft;
assign exp_f2i = f2i_zero ? 0 : f2i_max ? 8'hff : exp_f2i_1[55:48];
assign conv_exp = op_f2i ? exp_f2i : exp_i2f;
 
//assign exp_out = conv_exp;
always @(posedge clk)
exp_out <= conv_exp;
 
assign ldz_all = fi_ldz;
assign fi_ldz_2a = 6'd23 - fi_ldz;
assign fi_ldz_2 = {fi_ldz_2a[6], fi_ldz_2a[6:0]};
 
 
// ---------------------------------------------------------------------
// Round
 
// Extract rounding (GRS) bits
assign g = fract_out[0];
assign r = fract_trunc[24];
assign s = |fract_trunc[23:0];
 
// Round to nearest even
assign round = (g & r) | (r & s) ;
assign {exp_rnd_adj0, fract_out_rnd0} = round ?
fract_out_pl1 : {1'b0, fract_out};
assign exp_out_rnd0 = exp_rnd_adj0 ? exp_out_pl1 : exp_out;
assign ovf0 = exp_out_final_ff & !rmode_01 & !op_f2i;
 
// round to zero
// Added detection of sign and rounding up in case of negative ftoi! - JPB
assign fract_out_rnd1 = (exp_out_ff & !dn & !op_f2i) ?
23'h7fffff :
(op_f2i & (|fract_trunc) & opas) ?
fract_out_pl1[22:0] : fract_out ;
 
assign exp_out_rnd1 = (g & r & s & exp_in_ff) ?
exp_next_mi[7:0] : (exp_out_ff & !op_f2i) ?
exp_in :
(op_f2i & opas & (|fract_trunc) & fract_out_pl1[23]) ?
exp_out_pl1: exp_out;
 
assign ovf1 = exp_out_ff & !dn;
 
// round to +inf (UP) and -inf (DOWN)
assign r_sign = sign;
 
assign round2a = !exp_out_fe | !fract_out_7fffff |
(exp_out_fe & fract_out_7fffff);
 
assign round2_fasu = ((r | s) & !r_sign) & (!exp_out[7] |
(exp_out[7] & round2a));
 
assign round2_f2i = rmode_10 &
(( |fract_in[23:0] & !opas & (exp_in<8'h80 )) |
(|fract_trunc));
assign round2 = op_f2i ? round2_f2i : round2_fasu;
 
assign {exp_rnd_adj2a, fract_out_rnd2a} = round2 ? fract_out_pl1 :
{1'b0, fract_out};
assign exp_out_rnd2a = exp_rnd_adj2a ? exp_out_pl1 : exp_out;
 
assign fract_out_rnd2 = (r_sign & exp_out_ff & !op_div & !dn & !op_f2i) ?
23'h7fffff : fract_out_rnd2a;
assign exp_out_rnd2 = (r_sign & exp_out_ff & !op_f2i) ?
8'hfe : exp_out_rnd2a;
 
 
// Choose rounding mode
always @(rmode or exp_out_rnd0 or exp_out_rnd1 or exp_out_rnd2)
case(rmode) // synopsys full_case parallel_case
0: exp_out_rnd = exp_out_rnd0;
1: exp_out_rnd = exp_out_rnd1;
2,3: exp_out_rnd = exp_out_rnd2;
endcase
 
always @(rmode or fract_out_rnd0 or fract_out_rnd1 or fract_out_rnd2)
case(rmode) // synopsys full_case parallel_case
0: fract_out_rnd = fract_out_rnd0;
1: fract_out_rnd = fract_out_rnd1;
2,3: fract_out_rnd = fract_out_rnd2;
endcase
// ---------------------------------------------------------------------
// Final Output Mux
// Fix Output for denormalized and special numbers
 
assign fract_out_final = ovf0 ? 23'h0 :
(f2i_max & op_f2i) ? 23'h7fffff :
fract_out_rnd;
assign exp_out_final = (f2i_max & op_f2i) ? 8'hff : exp_out_rnd;
 
// ---------------------------------------------------------------------
// Pack Result
assign out = {exp_out_final, fract_out_final};
// ---------------------------------------------------------------------
// Exceptions
assign underflow = (!fract_in[47] & exp_out1_co) & !dn;
assign overflow = ovf0 | ovf1;
wire f2i_ine;
wire exp_in_lt_half = (exp_in<8'h80);
assign f2i_ine = (f2i_zero & !fract_in_00 & !opas) |
(|fract_trunc) |
(f2i_zero & exp_in_lt_half & opas & !fract_in_00) |
(f2i_max & rmode_11 & (exp_in<8'h80));
 
assign ine = op_f2i ? f2i_ine :
op_i2f ? (|fract_trunc) :
((r & !dn) | (s & !dn) );
 
assign inv = op_f2i & (exp_in > f2i_emax);
 
endmodule // or1200_fpu_post_norm_intfloat_conv
 
/verilog/or1200_dc_tag.v
3,7 → 3,7
//// OR1200's DC TAG RAMs ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Instatiation of data cache tag rams. ////
41,44 → 41,11
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_dc_tag.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// Minor update:
// Coding style changed.
//
// Revision 1.5 2004/06/08 18:17:36 lampret
// Non-functional changes. Coding style fixes.
//
// Revision 1.4 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.2.4.1 2003/12/09 11:46:48 simons
// Mbist nameing changed, Artisan ram instance signal names fixed, some synthesis waning fixed.
//
// Revision 1.2 2002/10/17 20:04:40 lampret
// Added BIST scan. Special VS RAMs need to be used to implement BIST.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.8 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.7 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:36 igorm
// no message
//
// Revision 1.2 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.1 2001/07/20 00:46:03 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
95,10 → 62,10
`endif
 
// Internal i/f
addr, en, we, datain, tag_v, tag
addr, en, we, datain, tag_v, tag, dirty
);
 
parameter dw = `OR1200_DCTAG_W;
parameter dw = `OR1200_DCTAG_W+1;
parameter aw = `OR1200_DCTAG;
 
//
111,7 → 78,9
input we;
input [dw-1:0] datain;
output tag_v;
output [dw-2:0] tag;
output [dw-3:0] tag;
output dirty;
 
`ifdef OR1200_BIST
//
142,7 → 111,7
or1200_spram #
(
.aw(8),
.dw(21)
.dw(21 + 1)
)
`endif
`ifdef OR1200_DC_1W_8KB
149,7 → 118,7
or1200_spram #
(
.aw(9),
.dw(20)
.dw(20 + 1)
)
`endif
dc_tag0
165,7 → 134,7
.we(we),
.addr(addr),
.di(datain),
.doq({tag, tag_v})
.doq({tag, tag_v, dirty})
);
`endif
 
/verilog/or1200_spram.v
104,7 → 104,7
//
// Generic RAM's registers and wires
//
`ifdef OR1200_ACTEL
`ifdef OR1200_GENERIC
reg [dw-1:0] mem [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
`else
reg [dw-1:0] mem [(1<<aw)-1:0];
122,7 → 122,7
//
always @(posedge clk)
if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
//
// RAM write
129,6 → 129,6
//
always @(posedge clk)
if (we && ce)
mem[addr] <= #1 di;
mem[addr] <= di;
endmodule // or1200_spram
/verilog/or1200_spram_32x24.v
292,9 → 292,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
 
//
// RAM write
301,7 → 301,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_amultp2_32x32.v
783,7 → 783,7
if (RST)
DOUT_reg <= 1'b0;
else
DOUT_reg <= #1 DIN;
DOUT_reg <= DIN;
end
assign DOUT = DOUT_reg;
endmodule
2359,7 → 2359,7
DBLCADDER_64_64 D (.OPA(INT_SUM[0:63]) , .OPB(INT_CARRY[0:63]) , .CIN (LOGIC_ZERO) , .PHI (PHI) , .SUM(ARESULT[0:63]), .COUT() );
always @(posedge CLK or posedge RST)
if (RST)
RESULT <= #1 64'h0000_0000_0000_0000;
RESULT <= 64'h0000_0000_0000_0000;
else
RESULT <= ARESULT;
endmodule
/verilog/or1200_dc_ram.v
1,10 → 1,9
 
//////////////////////////////////////////////////////////////////////
//// ////
//// OR1200's DC RAMs ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Instatiation of DC RAM blocks. ////
42,7 → 41,6
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_dc_ram.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
49,40 → 47,6
// Minor update:
// Coding style changed.
//
// Revision 1.6 2004/06/08 18:17:36 lampret
// Non-functional changes. Coding style fixes.
//
// Revision 1.5 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.2.4.2 2003/12/10 15:28:28 simons
// Support for ram with byte selects added.
//
// Revision 1.2.4.1 2003/12/09 11:46:48 simons
// Mbist nameing changed, Artisan ram instance signal names fixed, some synthesis waning fixed.
//
// Revision 1.2 2002/10/17 20:04:40 lampret
// Added BIST scan. Special VS RAMs need to be used to implement BIST.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.8 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.7 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:36 igorm
// no message
//
// Revision 1.2 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.1 2001/07/20 00:46:03 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
/verilog/or1200_spram_1024x32.v
514,9 → 514,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
 
//
// RAM write
523,7 → 523,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_spram_64x22.v
393,9 → 393,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
//
// RAM write
402,7 → 402,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_spram_64x24.v
395,9 → 395,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
//
// RAM write
404,7 → 404,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_gmultp2_32x32.v
120,7 → 120,7
if (RST)
p0 <= `OR1200_WW'b0;
else
p0 <= #1 xi * yi;
p0 <= xi * yi;
 
//
// Second multiply stage
129,7 → 129,7
if (RST)
p1 <= `OR1200_WW'b0;
else
p1 <= #1 p0;
p1 <= p0;
 
assign P = p1;
 
/verilog/or1200_dpram_256x32.v
202,9 → 202,9
//
always @(posedge clk_a or posedge rst_a)
if (rst_a)
addr_a_reg <= #1 {aw{1'b0}};
addr_a_reg <= {aw{1'b0}};
else if (ce_a)
addr_a_reg <= #1 addr_a;
addr_a_reg <= addr_a;
 
//
// RAM write
211,7 → 211,7
//
always @(posedge clk_b)
if (ce_b && we_b)
mem[addr_b] <= #1 di_b;
mem[addr_b] <= di_b;
 
`endif // !OR1200_XILINX_RAMB16
`endif // !OR1200_XILINX_RAMB4
/verilog/or1200_spram_2048x32.v
618,9 → 618,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
 
//
// RAM write
627,7 → 627,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_if.v
3,7 → 3,7
//// OR1200's instruction fetch ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://www.opencores.org/project,or1k ////
//// ////
//// Description ////
//// PC, instruction fetch, interface to IC. ////
41,47 → 41,10
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_if.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// Major update:
// Structure reordered and bugs fixed.
//
// Revision 1.5 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.3 2002/03/29 15:16:56 lampret
// Some of the warnings fixed.
//
// Revision 1.2 2002/01/28 01:16:00 lampret
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.10 2001/11/20 18:46:15 simons
// Break point bug fixed
//
// Revision 1.9 2001/11/18 09:58:28 lampret
// Fixed some l.trap typos.
//
// Revision 1.8 2001/11/18 08:36:28 lampret
// For GDB changed single stepping and disabled trap exception.
//
// Revision 1.7 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.6 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:36 igorm
// no message
//
// Revision 1.1 2001/08/09 13:39:33 lampret
// Major clean-up.
//
//
 
// synopsys translate_off
`include "timescale.v"
157,9 → 120,9
 
always @(posedge clk or posedge rst)
if (rst)
if_bypass_reg <= #1 1'b0;
if_bypass_reg <= 1'b0;
else
if_bypass_reg <= #1 if_bypass;
if_bypass_reg <= if_bypass;
 
//
// IF stage insn
177,13 → 140,13
//
always @(posedge clk or posedge rst)
if (rst)
saved <= #1 1'b0;
saved <= 1'b0;
else if (if_flushpipe)
saved <= #1 1'b0;
saved <= 1'b0;
else if (save_insn)
saved <= #1 1'b1;
saved <= 1'b1;
else if (!if_freeze)
saved <= #1 1'b0;
saved <= 1'b0;
 
//
// Store fetched instruction
190,13 → 153,13
//
always @(posedge clk or posedge rst)
if (rst)
insn_saved <= #1 {`OR1200_OR32_NOP, 26'h041_0000};
insn_saved <= {`OR1200_OR32_NOP, 26'h041_0000};
else if (if_flushpipe)
insn_saved <= #1 {`OR1200_OR32_NOP, 26'h041_0000};
insn_saved <= {`OR1200_OR32_NOP, 26'h041_0000};
else if (save_insn)
insn_saved <= #1 icpu_err_i ? {`OR1200_OR32_NOP, 26'h041_0000} : icpu_dat_i;
insn_saved <= icpu_err_i ? {`OR1200_OR32_NOP, 26'h041_0000} : icpu_dat_i;
else if (!if_freeze)
insn_saved <= #1 {`OR1200_OR32_NOP, 26'h041_0000};
insn_saved <= {`OR1200_OR32_NOP, 26'h041_0000};
 
//
// Store fetched instruction's address
203,13 → 166,13
//
always @(posedge clk or posedge rst)
if (rst)
addr_saved <= #1 32'h00000000;
addr_saved <= 32'h00000000;
else if (if_flushpipe)
addr_saved <= #1 32'h00000000;
addr_saved <= 32'h00000000;
else if (save_insn)
addr_saved <= #1 {icpu_adr_i[31:2], 2'b00};
addr_saved <= {icpu_adr_i[31:2], 2'b00};
else if (!if_freeze)
addr_saved <= #1 {icpu_adr_i[31:2], 2'b00};
addr_saved <= {icpu_adr_i[31:2], 2'b00};
 
//
// Store fetched instruction's error tags
216,16 → 179,16
//
always @(posedge clk or posedge rst)
if (rst)
err_saved <= #1 3'b000;
err_saved <= 3'b000;
else if (if_flushpipe)
err_saved <= #1 3'b000;
err_saved <= 3'b000;
else if (save_insn) begin
err_saved[0] <= #1 icpu_err_i & (icpu_tag_i == `OR1200_ITAG_TE);
err_saved[1] <= #1 icpu_err_i & (icpu_tag_i == `OR1200_ITAG_PE);
err_saved[2] <= #1 icpu_err_i & (icpu_tag_i == `OR1200_ITAG_BE);
err_saved[0] <= icpu_err_i & (icpu_tag_i == `OR1200_ITAG_TE);
err_saved[1] <= icpu_err_i & (icpu_tag_i == `OR1200_ITAG_PE);
err_saved[2] <= icpu_err_i & (icpu_tag_i == `OR1200_ITAG_BE);
end
else if (!if_freeze)
err_saved <= #1 3'b000;
err_saved <= 3'b000;
 
 
endmodule
/verilog/or1200_mult_mac.v
1,9 → 1,9
//////////////////////////////////////////////////////////////////////
//// ////
//// OR1200's Top level multiplier and MAC ////
//// OR1200's Top level multiplier, divider and MAC ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Multiplier is 32x32 however multiply instructions only ////
49,31 → 49,6
// Minor update:
// Bugs fixed.
//
// Revision 1.5 2006/04/09 01:32:29 lampret
// See OR1200_MAC_SHIFTBY in or1200_defines.v for explanation of the change. Since now no more 28 bits shift for l.macrc insns however for backward compatbility it is possible to set arbitry number of shifts.
//
// Revision 1.4 2004/06/08 18:17:36 lampret
// Non-functional changes. Coding style fixes.
//
// Revision 1.3 2003/04/24 00:16:07 lampret
// No functional changes. Added defines to disable implementation of multiplier/MAC
//
// Revision 1.2 2002/09/08 05:52:16 lampret
// Added optional l.div/l.divu insns. By default they are disabled.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.3 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.2 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:38 igorm
// no message
//
//
 
// synopsys translate_off
`include "timescale.v"
157,7 → 132,7
wire alu_op_div_divu;
wire alu_op_div;
reg div_free;
`ifdef OR1200_IMPL_DIV
`ifdef OR1200_DIV_IMPLEMENTED
wire [width-1:0] div_tmp;
reg [5:0] div_cntr;
`endif
175,13 → 150,17
assign spr_dat_o = 32'h0000_0000;
`endif
`ifdef OR1200_LOWPWR_MULT
assign x = (alu_op_div & a[31]) ? ~a + 1'b1 : alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? a : 32'h0000_0000;
assign y = (alu_op_div & b[31]) ? ~b + 1'b1 : alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? b : 32'h0000_0000;
assign x = (alu_op_div & a[31]) ? ~a + 1'b1 :
alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ?
a : 32'h0000_0000;
assign y = (alu_op_div & b[31]) ? ~b + 1'b1 :
alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ?
b : 32'h0000_0000;
`else
assign x = alu_op_div & a[31] ? ~a + 32'b1 : a;
assign y = alu_op_div & b[31] ? ~b + 32'b1 : b;
`endif
`ifdef OR1200_IMPL_DIV
`ifdef OR1200_DIV_IMPLEMENTED
assign alu_op_div = (alu_op == `OR1200_ALUOP_DIV);
assign alu_op_div_divu = alu_op_div | (alu_op == `OR1200_ALUOP_DIVU);
assign div_tmp = mul_prod_r[63:32] - y;
197,27 → 176,28
// to next instruction and to WB stage
//
always @(alu_op or mul_prod_r or mac_r or a or b)
casex(alu_op) // synopsys parallel_case
`ifdef OR1200_IMPL_DIV
`OR1200_ALUOP_DIV:
result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 1'b1 : mul_prod_r[31:0];
`OR1200_ALUOP_DIVU,
`endif
`OR1200_ALUOP_MUL: begin
result = mul_prod_r[31:0];
end
default:
`ifdef OR1200_MAC_SHIFTBY
result = mac_r[`OR1200_MAC_SHIFTBY+31:`OR1200_MAC_SHIFTBY];
`else
result = mac_r[31:0];
`endif
endcase
 
//
// Instantiation of the multiplier
//
`ifdef OR1200_ASIC_MULTP2_32X32
casex(alu_op) // synopsys parallel_case
`ifdef OR1200_DIV_IMPLEMENTED
`OR1200_ALUOP_DIV: begin
result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 1'b1 : mul_prod_r[31:0];
end
`OR1200_ALUOP_DIVU,
`endif
`OR1200_ALUOP_MUL: begin
result = mul_prod_r[31:0];
end
default:
`ifdef OR1200_MAC_SHIFTBY
result = mac_r[`OR1200_MAC_SHIFTBY+31:`OR1200_MAC_SHIFTBY];
`else
result = mac_r[31:0];
`endif
endcase
//
// Instantiation of the multiplier
//
`ifdef OR1200_ASIC_MULTP2_32X32
or1200_amultp2_32x32 or1200_amultp2_32x32(
.X(x),
.Y(y),
241,29 → 221,29
//
always @(posedge rst or posedge clk)
if (rst) begin
mul_prod_r <= #1 64'h0000_0000_0000_0000;
div_free <= #1 1'b1;
`ifdef OR1200_IMPL_DIV
div_cntr <= #1 6'b00_0000;
mul_prod_r <= 64'h0000_0000_0000_0000;
div_free <= 1'b1;
`ifdef OR1200_DIV_IMPLEMENTED
div_cntr <= 6'b00_0000;
`endif
end
`ifdef OR1200_IMPL_DIV
`ifdef OR1200_DIV_IMPLEMENTED
else if (|div_cntr) begin
if (div_tmp[31])
mul_prod_r <= #1 {mul_prod_r[62:0], 1'b0};
mul_prod_r <= {mul_prod_r[62:0], 1'b0};
else
mul_prod_r <= #1 {div_tmp[30:0], mul_prod_r[31:0], 1'b1};
div_cntr <= #1 div_cntr - 1'b1;
mul_prod_r <= {div_tmp[30:0], mul_prod_r[31:0], 1'b1};
div_cntr <= div_cntr - 1'b1;
end
else if (alu_op_div_divu && div_free) begin
mul_prod_r <= #1 {31'b0, x[31:0], 1'b0};
div_cntr <= #1 6'b10_0000;
div_free <= #1 1'b0;
mul_prod_r <= {31'b0, x[31:0], 1'b0};
div_cntr <= 6'b10_0000;
div_free <= 1'b0;
end
`endif // OR1200_IMPL_DIV
`endif // OR1200_DIV_IMPLEMENTED
else if (div_free | !ex_freeze) begin
mul_prod_r <= #1 mul_prod[63:0];
div_free <= #1 1'b1;
mul_prod_r <= mul_prod[63:0];
div_free <= 1'b1;
end
 
`else // OR1200_MULT_IMPLEMENTED
279,9 → 259,9
//
always @(posedge clk or posedge rst)
if (rst)
mac_op_r1 <= #1 `OR1200_MACOP_WIDTH'b0;
mac_op_r1 <= `OR1200_MACOP_WIDTH'b0;
else
mac_op_r1 <= #1 mac_op;
mac_op_r1 <= mac_op;
 
//
// Propagation of l.mac opcode
288,9 → 268,9
//
always @(posedge clk or posedge rst)
if (rst)
mac_op_r2 <= #1 `OR1200_MACOP_WIDTH'b0;
mac_op_r2 <= `OR1200_MACOP_WIDTH'b0;
else
mac_op_r2 <= #1 mac_op_r1;
mac_op_r2 <= mac_op_r1;
 
//
// Propagation of l.mac opcode
297,9 → 277,9
//
always @(posedge clk or posedge rst)
if (rst)
mac_op_r3 <= #1 `OR1200_MACOP_WIDTH'b0;
mac_op_r3 <= `OR1200_MACOP_WIDTH'b0;
else
mac_op_r3 <= #1 mac_op_r2;
mac_op_r3 <= mac_op_r2;
 
//
// Implementation of MAC
306,19 → 286,19
//
always @(posedge rst or posedge clk)
if (rst)
mac_r <= #1 64'h0000_0000_0000_0000;
mac_r <= 64'h0000_0000_0000_0000;
`ifdef OR1200_MAC_SPR_WE
else if (spr_maclo_we)
mac_r[31:0] <= #1 spr_dat_i;
mac_r[31:0] <= spr_dat_i;
else if (spr_machi_we)
mac_r[63:32] <= #1 spr_dat_i;
mac_r[63:32] <= spr_dat_i;
`endif
else if (mac_op_r3 == `OR1200_MACOP_MAC)
mac_r <= #1 mac_r + mul_prod_r;
mac_r <= mac_r + mul_prod_r;
else if (mac_op_r3 == `OR1200_MACOP_MSB)
mac_r <= #1 mac_r - mul_prod_r;
mac_r <= mac_r - mul_prod_r;
else if (macrc_op && !ex_freeze)
mac_r <= #1 64'h0000_0000_0000_0000;
mac_r <= 64'h0000_0000_0000_0000;
 
//
// Stall CPU if l.macrc is in ID and MAC still has to process l.mac instructions
327,10 → 307,10
//
always @(posedge rst or posedge clk)
if (rst)
mac_stall_r <= #1 1'b0;
mac_stall_r <= 1'b0;
else
mac_stall_r <= #1 (|mac_op | (|mac_op_r1) | (|mac_op_r2)) & (id_macrc_op | mac_stall_r)
`ifdef OR1200_IMPL_DIV
mac_stall_r <= (|mac_op | (|mac_op_r1) | (|mac_op_r2)) & (id_macrc_op | mac_stall_r)
`ifdef OR1200_DIV_IMPLEMENTED
| (|div_cntr)
`endif
;
/verilog/or1200_wbmux.v
99,12 → 99,12
//
always @(posedge clk or posedge rst) begin
if (rst) begin
muxreg <= #1 32'd0;
muxreg_valid <= #1 1'b0;
muxreg <= 32'd0;
muxreg_valid <= 1'b0;
end
else if (!wb_freeze) begin
muxreg <= #1 muxout;
muxreg_valid <= #1 rfwb_op[0];
muxreg <= muxout;
muxreg_valid <= rfwb_op[0];
end
end
 
/verilog/or1200_dc_top.v
3,20 → 3,21
//// OR1200's Data Cache top level ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Instantiation of all DC blocks. ////
//// ////
//// To Do: ////
//// - make it smaller and faster ////
//// - Test error during line read or write ////
//// ////
//// Author(s): ////
//// - Damjan Lampret, lampret@opencores.org ////
//// - Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
//// Copyright (C) 2000, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
41,7 → 42,6
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_dc_top.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
48,55 → 48,6
// Minor update:
// Bugs fixed.
//
// Revision 1.8 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.6.4.2 2003/12/09 11:46:48 simons
// Mbist nameing changed, Artisan ram instance signal names fixed, some synthesis waning fixed.
//
// Revision 1.6.4.1 2003/07/08 15:36:37 lampret
// Added embedded memory QMEM.
//
// Revision 1.6 2002/10/17 20:04:40 lampret
// Added BIST scan. Special VS RAMs need to be used to implement BIST.
//
// Revision 1.5 2002/08/18 19:54:47 lampret
// Added store buffer.
//
// Revision 1.4 2002/02/11 04:33:17 lampret
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
//
// Revision 1.3 2002/01/28 01:16:00 lampret
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
//
// Revision 1.2 2002/01/14 06:18:22 lampret
// Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.10 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.9 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:35 igorm
// no message
//
// Revision 1.4 2001/08/13 03:36:20 lampret
// Added cfg regs. Moved all defines into one defines.v file. More cleanup.
//
// Revision 1.3 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.2 2001/07/22 03:31:53 lampret
// Fixed RAM's oen bug. Cache bypass under development.
//
// Revision 1.1 2001/07/20 00:46:03 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
111,8 → 62,8
clk, rst,
 
// External i/f
dcsb_dat_o, dcsb_adr_o, dcsb_cyc_o, dcsb_stb_o, dcsb_we_o, dcsb_sel_o, dcsb_cab_o,
dcsb_dat_i, dcsb_ack_i, dcsb_err_i,
dcsb_dat_o, dcsb_adr_o, dcsb_cyc_o, dcsb_stb_o, dcsb_we_o, dcsb_sel_o,
dcsb_cab_o, dcsb_dat_i, dcsb_ack_i, dcsb_err_i,
 
// Internal i/f
dc_en,
119,6 → 70,8
dcqmem_adr_i, dcqmem_cycstb_i, dcqmem_ci_i,
dcqmem_we_i, dcqmem_sel_i, dcqmem_tag_i, dcqmem_dat_i,
dcqmem_dat_o, dcqmem_ack_o, dcqmem_rty_o, dcqmem_err_o, dcqmem_tag_o,
dc_no_writethrough,
 
`ifdef OR1200_BIST
// RAM BIST
126,11 → 79,12
`endif
 
// SPRs
spr_cs, spr_write, spr_dat_i
spr_cs, spr_write, spr_dat_i, spr_addr, mtspr_dc_done
);
 
parameter dw = `OR1200_OPERAND_WIDTH;
 
parameter aw = `OR1200_OPERAND_WIDTH;
//
// I/O
//
172,6 → 126,8
output dcqmem_err_o;
output [3:0] dcqmem_tag_o;
 
input dc_no_writethrough;
`ifdef OR1200_BIST
//
// RAM BIST
187,32 → 143,65
input spr_cs;
input spr_write;
input [31:0] spr_dat_i;
input [aw-1:0] spr_addr;
output mtspr_dc_done;
 
`ifdef OR1200_NO_DC
 
// Bypass cache
 
// IF to external memory
assign dcsb_dat_o = dcqmem_dat_i;
assign dcsb_adr_o = dcqmem_adr_i;
assign dcsb_cyc_o = dcqmem_cycstb_i;
assign dcsb_stb_o = dcqmem_cycstb_i;
assign dcsb_we_o = dcqmem_we_i;
assign dcsb_sel_o = dcqmem_sel_i;
assign dcsb_cab_o = 1'b0;
 
// IF to internal memory
assign dcqmem_dat_o = dcsb_dat_i;
assign dcqmem_ack_o = dcsb_ack_i;
assign dcqmem_err_o = dcsb_err_i;
assign dcqmem_rty_o = ~dcqmem_ack_o;
assign dcqmem_tag_o = dcqmem_err_o ? `OR1200_DTAG_BE : dcqmem_tag_i;
 
assign mtspr_dc_done = 1'b1;
 
`else
//
// Internal wires and regs
//
wire tag_v;
wire [`OR1200_DCTAG_W-2:0] tag;
wire dirty;
wire [dw-1:0] to_dcram;
wire [dw-1:0] from_dcram;
wire [31:0] saved_addr;
wire [3:0] dcram_we;
wire dctag_we;
wire [31:0] dc_addr;
wire dcfsm_biu_read;
wire dcfsm_biu_write;
wire dcfsm_biu_sel;
wire dcfsm_dcram_di_sel;
wire dcfsm_biu_do_sel;
reg tagcomp_miss;
wire [`OR1200_DCINDXH:`OR1200_DCLS] dctag_addr;
wire dctag_en;
wire dctag_v;
wire dc_inv;
wire dctag_v;
wire dctag_dirty;
wire dc_block_invalidate;
wire dc_block_flush;
wire dc_block_writeback;
wire dcfsm_first_hit_ack;
wire dcfsm_first_miss_ack;
wire dcfsm_first_miss_err;
wire dcfsm_burst;
wire dcfsm_tag_we;
wire dcfsm_tag_valid;
wire dcfsm_tag_valid;
wire dcfsm_tag_dirty;
`ifdef OR1200_BIST
//
// RAM BIST
224,32 → 213,56
assign mbist_so_o = mbist_tag_so;
`endif
 
// Address out to external bus - always from FSM
assign dcsb_adr_o = dc_addr;
//
// Simple assignments
// SPR register decodes
//
assign dcsb_adr_o = dc_addr;
assign dc_inv = spr_cs & spr_write;
assign dctag_we = dcfsm_tag_we | dc_inv;
assign dctag_addr = dc_inv ? spr_dat_i[`OR1200_DCINDXH:`OR1200_DCLS] : dc_addr[`OR1200_DCINDXH:`OR1200_DCLS];
assign dctag_en = dc_inv | dc_en;
//assign dctag_v = ~dc_inv;
assign dctag_v = dc_inv ? 1'b0 : dcfsm_tag_valid;
`ifdef OR1200_DC_WRITETHROUGH
assign dc_block_invalidate = spr_cs & spr_write &
((spr_addr[`OR1200_SPRGRP_DC_ADR_WIDTH-1:0]==`OR1200_SPRGRP_DC_DCBIR) |
(spr_addr[`OR1200_SPRGRP_DC_ADR_WIDTH-1:0]==`OR1200_SPRGRP_DC_DCBFR));
assign dc_block_flush = 0;
assign dc_block_writeback = 0;
`else
assign dc_block_invalidate = spr_cs & spr_write &
(spr_addr[`OR1200_SPRGRP_DC_ADR_WIDTH-1:0]==`OR1200_SPRGRP_DC_DCBIR);
assign dc_block_flush = spr_cs & spr_write &
(spr_addr[`OR1200_SPRGRP_DC_ADR_WIDTH-1:0]==`OR1200_SPRGRP_DC_DCBFR);
assign dc_block_writeback = spr_cs & spr_write &
(spr_addr[`OR1200_SPRGRP_DC_ADR_WIDTH-1:0]==`OR1200_SPRGRP_DC_DCBWR);
`endif // !`ifdef OR1200_DC_WRITETHROUGH
assign dctag_we = dcfsm_tag_we | dc_block_invalidate;
assign dctag_addr = dc_block_invalidate ?
spr_dat_i[`OR1200_DCINDXH:`OR1200_DCLS] :
dc_addr[`OR1200_DCINDXH:`OR1200_DCLS];
assign dctag_en = dc_block_invalidate | dc_en;
 
assign dctag_v = dc_block_invalidate ? 1'b0 : dcfsm_tag_valid;
assign dctag_dirty = dc_block_invalidate ? 1'b0 : dcfsm_tag_dirty;
//
// Data to BIU is from DCRAM when DC is enabled or from LSU when
// DC is disabled
// Data to BIU is from DCRAM when bursting lines back into memory
//
assign dcsb_dat_o = dcqmem_dat_i;
assign dcsb_dat_o = dcfsm_biu_do_sel ? from_dcram : dcqmem_dat_i;
 
 
//
// Bypases of the DC when DC is disabled
//
assign dcsb_cyc_o = (dc_en) ? dcfsm_biu_read | dcfsm_biu_write : dcqmem_cycstb_i;
assign dcsb_stb_o = (dc_en) ? dcfsm_biu_read | dcfsm_biu_write : dcqmem_cycstb_i;
assign dcsb_we_o = (dc_en) ? dcfsm_biu_write : dcqmem_we_i;
//assign dcsb_sel_o = (dc_en & dcfsm_biu_read & !dcfsm_biu_write & !dcqmem_ci_i) ? 4'b1111 : dcqmem_sel_i;
assign dcsb_sel_o = (dc_en & dcfsm_burst) ? 4'b1111 : dcqmem_sel_i;
//assign dcsb_cab_o = (dc_en) ? dcsb_cyc_o & dcfsm_burst : 1'b0;
assign dcsb_cyc_o = (dc_en) ?
dcfsm_biu_read | dcfsm_biu_write : dcqmem_cycstb_i;
assign dcsb_stb_o = (dc_en) ?
dcfsm_biu_read | dcfsm_biu_write : dcqmem_cycstb_i;
assign dcsb_we_o = (dc_en) ?
dcfsm_biu_write : dcqmem_we_i;
 
assign dcsb_sel_o = (dc_en & dcfsm_burst) ?
4'b1111 : dcqmem_sel_i;
 
assign dcsb_cab_o = dc_en & dcfsm_burst & dcsb_cyc_o;
assign dcqmem_rty_o = ~dcqmem_ack_o;
assign dcqmem_tag_o = dcqmem_err_o ? `OR1200_DTAG_BE : dcqmem_tag_i;
257,32 → 270,30
//
// DC/LSU normal and error termination
//
assign dcqmem_ack_o = dc_en ? dcfsm_first_hit_ack | dcfsm_first_miss_ack : dcsb_ack_i;
assign dcqmem_ack_o = dc_en ?
dcfsm_first_hit_ack | dcfsm_first_miss_ack : dcsb_ack_i;
assign dcqmem_err_o = dc_en ? dcfsm_first_miss_err : dcsb_err_i;
 
//
// Select between claddr generated by DC FSM and addr[3:2] generated by LSU
//
//assign dc_addr = (dcfsm_biu_read | dcfsm_biu_write) ? saved_addr : dcqmem_adr_i;
 
//
// Select between input data generated by LSU or by BIU
//
//assign to_dcram = (dcfsm_biu_read) ? dcsb_dat_i : dcqmem_dat_i;
assign to_dcram = (dcfsm_biu_sel) ? dcsb_dat_i : dcqmem_dat_i;
assign to_dcram = (dcfsm_dcram_di_sel) ? dcsb_dat_i : dcqmem_dat_i;
 
//
// Select between data generated by DCRAM or passed by BIU
//
assign dcqmem_dat_o = dcfsm_first_miss_ack | !dc_en ? dcsb_dat_i : from_dcram;
//assign dcqmem_dat_o = !dc_en ? dcsb_dat_i : from_dcram;
 
//
// Tag comparison
//
//always @(tag or saved_addr or tag_v) begin
// if ((tag != saved_addr[31:`OR1200_DCTAGL]) || !tag_v)
wire [31:`OR1200_DCTAGL] dcqmem_adr_i_tag;
assign dcqmem_adr_i_tag = dcqmem_adr_i[31:`OR1200_DCTAGL];
always @(tag or dcqmem_adr_i or tag_v) begin
if ((tag != dcqmem_adr_i[31:`OR1200_DCTAGL]) || !tag_v)
if ((tag != dcqmem_adr_i_tag) || !tag_v)
tagcomp_miss = 1'b1;
else
tagcomp_miss = 1'b0;
300,21 → 311,31
.dcqmem_we_i(dcqmem_we_i),
.dcqmem_sel_i(dcqmem_sel_i),
.tagcomp_miss(tagcomp_miss),
.tag(tag),
.tag_v(tag_v),
.dirty(dirty),
.biudata_valid(dcsb_ack_i),
.biudata_error(dcsb_err_i),
.start_addr(dcqmem_adr_i),
.saved_addr(saved_addr),
.lsu_addr(dcqmem_adr_i),
.dcram_we(dcram_we),
.biu_read(dcfsm_biu_read),
.biu_write(dcfsm_biu_write),
.biu_sel(dcfsm_biu_sel),
.dcram_di_sel(dcfsm_dcram_di_sel),
.biu_do_sel(dcfsm_biu_do_sel),
.first_hit_ack(dcfsm_first_hit_ack),
.first_miss_ack(dcfsm_first_miss_ack),
.first_miss_err(dcfsm_first_miss_err),
.burst(dcfsm_burst),
.tag_we(dcfsm_tag_we),
.tag_valid(dcfsm_tag_valid),
.dc_addr(dc_addr)
.tag_valid(dcfsm_tag_valid),
.tag_dirty(dcfsm_tag_dirty),
.dc_addr(dc_addr),
.dc_no_writethrough(dc_no_writethrough),
.dc_block_flush(dc_block_flush),
.dc_block_writeback(dc_block_writeback),
.spr_dat_i(spr_dat_i),
.mtspr_dc_done(mtspr_dc_done),
.spr_cswe(spr_cs & spr_write)
);
 
//
351,9 → 372,11
.addr(dctag_addr),
.en(dctag_en),
.we(dctag_we),
.datain({dc_addr[31:`OR1200_DCTAGL], dctag_v}),
.datain({dc_addr[31:`OR1200_DCTAGL], dctag_v, dctag_dirty}),
.tag_v(tag_v),
.tag(tag)
.tag(tag),
.dirty(dirty)
);
 
`endif // !`ifdef OR1200_NO_DC
endmodule
/verilog/or1200_spram_128x32.v
266,9 → 266,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
 
//
// RAM write
275,7 → 275,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_XILINX_RAMB16
`endif // !OR1200_XILINX_RAMB4
/verilog/or1200_operandmuxes.v
96,15 → 96,15
//
always @(posedge clk or posedge rst) begin
if (rst) begin
operand_a <= #1 32'd0;
saved_a <= #1 1'b0;
operand_a <= 32'd0;
saved_a <= 1'b0;
end else if (!ex_freeze && id_freeze && !saved_a) begin
operand_a <= #1 muxed_a;
saved_a <= #1 1'b1;
operand_a <= muxed_a;
saved_a <= 1'b1;
end else if (!ex_freeze && !saved_a) begin
operand_a <= #1 muxed_a;
operand_a <= muxed_a;
end else if (!ex_freeze && !id_freeze)
saved_a <= #1 1'b0;
saved_a <= 1'b0;
end
 
//
112,15 → 112,15
//
always @(posedge clk or posedge rst) begin
if (rst) begin
operand_b <= #1 32'd0;
saved_b <= #1 1'b0;
operand_b <= 32'd0;
saved_b <= 1'b0;
end else if (!ex_freeze && id_freeze && !saved_b) begin
operand_b <= #1 muxed_b;
saved_b <= #1 1'b1;
operand_b <= muxed_b;
saved_b <= 1'b1;
end else if (!ex_freeze && !saved_b) begin
operand_b <= #1 muxed_b;
operand_b <= muxed_b;
end else if (!ex_freeze && !id_freeze)
saved_b <= #1 1'b0;
saved_b <= 1'b0;
end
 
//
/verilog/or1200_pic.v
3,7 → 3,7
//// OR1200's Programmable Interrupt Controller ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://www.opencores.org/project,or1k ////
//// ////
//// Description ////
//// PIC according to OR1K architectural specification. ////
41,40 → 41,9
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_pic.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// No update
//
// Revision 1.4 2004/06/08 18:17:36 lampret
// Non-functional changes. Coding style fixes.
//
// Revision 1.3 2002/03/29 15:16:56 lampret
// Some of the warnings fixed.
//
// Revision 1.2 2002/01/18 07:56:00 lampret
// No more low/high priority interrupts (PICPR removed). Added tick timer exception. Added exception prefix (SR[EPH]). Fixed single-step bug whenreading NPC.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.8 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.7 2001/10/14 13:12:10 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:36 igorm
// no message
//
// Revision 1.2 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.1 2001/07/20 00:46:21 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
151,7 → 120,7
if (rst)
picmr <= {1'b1, {`OR1200_PIC_INTS-3{1'b0}}};
else if (picmr_sel && spr_write) begin
picmr <= #1 spr_dat_i[`OR1200_PIC_INTS-1:2];
picmr <= spr_dat_i[`OR1200_PIC_INTS-1:2];
end
`else
assign picmr = (`OR1200_PIC_INTS)'b1;
165,9 → 134,9
if (rst)
picsr <= {`OR1200_PIC_INTS{1'b0}};
else if (picsr_sel && spr_write) begin
picsr <= #1 spr_dat_i[`OR1200_PIC_INTS-1:0] | um_ints;
picsr <= spr_dat_i[`OR1200_PIC_INTS-1:0] | um_ints;
end else
picsr <= #1 picsr | um_ints;
picsr <= picsr | um_ints;
`else
assign picsr = pic_int;
`endif
179,20 → 148,20
case (spr_addr[`OR1200_PICOFS_BITS]) // synopsys parallel_case
`ifdef OR1200_PIC_READREGS
`OR1200_PIC_OFS_PICMR: begin
spr_dat_o[`OR1200_PIC_INTS-1:0] = {picmr, 2'b0};
`ifdef OR1200_PIC_UNUSED_ZERO
spr_dat_o[31:`OR1200_PIC_INTS] = {32-`OR1200_PIC_INTS{1'b0}};
spr_dat_o[`OR1200_PIC_INTS-1:0] = {picmr, 2'b11};
`ifdef OR1200_PIC_UNUSED_ZERO
spr_dat_o[31:`OR1200_PIC_INTS] = {32-`OR1200_PIC_INTS{1'b0}};
`endif
end
`endif
end
`endif
default: begin
spr_dat_o[`OR1200_PIC_INTS-1:0] = picsr;
default: begin
spr_dat_o[`OR1200_PIC_INTS-1:0] = picsr;
`ifdef OR1200_PIC_UNUSED_ZERO
spr_dat_o[31:`OR1200_PIC_INTS] = {32-`OR1200_PIC_INTS{1'b0}};
spr_dat_o[31:`OR1200_PIC_INTS] = {32-`OR1200_PIC_INTS{1'b0}};
`endif
end
end
endcase
 
//
// Unmasked interrupts
//
/verilog/or1200_fpu_addsub.v
0,0 → 1,117
//////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_addsub ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// addition/subtraction entity for the addition/subtraction ////
//// unit ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Original design (FPU100) - ////
//// Jidan Al-eryani, jidan@gmx.net ////
//// - Conv. to Verilog and inclusion in OR1200 - ////
//// Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2006, 2010
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
module or1200_fpu_addsub(
clk_i,
fpu_op_i,
fracta_i,
fractb_i,
signa_i,
signb_i,
fract_o,
sign_o);
 
parameter FP_WIDTH = 32;
parameter MUL_SERIAL = 0; // 0 for parallel multiplier, 1 for serial
parameter MUL_COUNT = 11; //11 for parallel multiplier, 34 for serial
parameter FRAC_WIDTH = 23;
parameter EXP_WIDTH = 8;
parameter ZERO_VECTOR = 31'd0;
parameter INF = 31'b1111111100000000000000000000000;
parameter QNAN = 31'b1111111110000000000000000000000;
parameter SNAN = 31'b1111111100000000000000000000001;
input clk_i;
input fpu_op_i;
input [FRAC_WIDTH+4:0] fracta_i;
input [FRAC_WIDTH+4:0] fractb_i;
input signa_i;
input signb_i;
output reg [FRAC_WIDTH+4:0] fract_o;
output reg sign_o;
wire [FRAC_WIDTH+4:0] s_fracta_i;
wire [FRAC_WIDTH+4:0] s_fractb_i;
wire [FRAC_WIDTH+4:0] s_fract_o;
wire s_signa_i, s_signb_i, s_sign_o;
wire s_fpu_op_i;
wire fracta_gt_fractb;
wire s_addop;
assign s_fracta_i = fracta_i;
assign s_fractb_i = fractb_i;
assign s_signa_i = signa_i;
assign s_signb_i = signb_i;
assign s_fpu_op_i = fpu_op_i;
always @(posedge clk_i)
begin
fract_o <= s_fract_o;
sign_o <= s_sign_o;
end
assign fracta_gt_fractb = s_fracta_i > s_fractb_i;
// check if its a subtraction or an addition operation
assign s_addop = ((s_signa_i ^ s_signb_i) & !s_fpu_op_i) |
((s_signa_i ^~ s_signb_i) & s_fpu_op_i);
// sign of result
assign s_sign_o = ((s_fract_o == 28'd0) & !(s_signa_i & s_signb_i)) ? 0 :
(!s_signa_i & (!fracta_gt_fractb & (fpu_op_i^s_signb_i)))|
(s_signa_i & (fracta_gt_fractb | (fpu_op_i^s_signb_i)));
// add/substract
assign s_fract_o = s_addop ?
(fracta_gt_fractb ? s_fracta_i - s_fractb_i :
s_fractb_i - s_fracta_i) :
s_fracta_i + s_fractb_i;
endmodule // or1200_fpu_addsub
 
 
 
/verilog/or1200_fpu_pre_norm_addsub.v
0,0 → 1,199
//////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_pre_norm_addsub ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// pre-normalization entity for the addition/subtraction unit ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Original design (FPU100) - ////
//// Jidan Al-eryani, jidan@gmx.net ////
//// - Conv. to Verilog and inclusion in OR1200 - ////
//// Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2006, 2010
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
module or1200_fpu_pre_norm_addsub (
 
clk_i,
opa_i,
opb_i,
fracta_28_o,
fractb_28_o,
exp_o
);
 
parameter FP_WIDTH = 32;
parameter MUL_SERIAL = 0; // 0 for parallel multiplier, 1 for serial
parameter MUL_COUNT = 11; //11 for parallel multiplier, 34 for serial
parameter FRAC_WIDTH = 23;
parameter EXP_WIDTH = 8;
parameter ZERO_VECTOR = 31'd0;
parameter INF = 31'b1111111100000000000000000000000;
parameter QNAN = 31'b1111111110000000000000000000000;
parameter SNAN = 31'b1111111100000000000000000000001;
 
 
input clk_i;
input [FP_WIDTH-1:0] opa_i;
input [FP_WIDTH-1:0] opb_i;
// carry(1) & hidden(1) & fraction(23) & guard(1) & round(1) & sticky(1)
output reg [FRAC_WIDTH+4:0] fracta_28_o;
output reg [FRAC_WIDTH+4:0] fractb_28_o;
output reg [EXP_WIDTH-1:0] exp_o;
reg [EXP_WIDTH-1 : 0] s_exp_o ;
wire [FRAC_WIDTH+4 : 0] s_fracta_28_o, s_fractb_28_o ;
wire [EXP_WIDTH-1 : 0] s_expa;
wire [EXP_WIDTH-1 : 0] s_expb ;
wire [FRAC_WIDTH-1 : 0] s_fracta;
wire [FRAC_WIDTH-1 : 0] s_fractb ;
wire [FRAC_WIDTH+4 : 0] s_fracta_28;
 
wire [FRAC_WIDTH+4 : 0] s_fractb_28 ;
wire [FRAC_WIDTH+4 : 0] s_fract_sm_28;
wire [FRAC_WIDTH+4 : 0] s_fract_shr_28 ;
reg [EXP_WIDTH-1 : 0] s_exp_diff ;
reg [5 : 0] s_rzeros ;
wire s_expa_eq_expb;
wire s_expa_gt_expb;
wire s_fracta_1;
wire s_fractb_1;
wire s_op_dn,s_opa_dn, s_opb_dn;
wire [1 : 0] s_mux_diff ;
wire s_mux_exp;
wire s_sticky;
 
 
assign s_expa = opa_i[30:23];
assign s_expb = opb_i[30:23];
assign s_fracta = opa_i[22:0];
assign s_fractb = opb_i[22:0];
always @(posedge clk_i)
begin
exp_o <= s_exp_o;
fracta_28_o <= s_fracta_28_o;
fractb_28_o <= s_fractb_28_o;
end
assign s_expa_eq_expb = (s_expa == s_expb);
assign s_expa_gt_expb = (s_expa > s_expb);
// '1' if fraction is not zero
assign s_fracta_1 = |s_fracta;
assign s_fractb_1 = |s_fractb;
// opa or Opb is denormalized
assign s_opa_dn = !(|s_expa);
assign s_opb_dn = !(|s_expb);
assign s_op_dn = s_opa_dn | s_opb_dn;
 
// Output larger exponent
assign s_mux_exp = s_expa_gt_expb;
always @(posedge clk_i)
s_exp_o <= s_mux_exp ? s_expa : s_expb;
// convert to an easy to handle floating-point format
assign s_fracta_28 = s_opa_dn ?
{2'b00, s_fracta, 3'b000} : {2'b01, s_fracta, 3'b000};
assign s_fractb_28 = s_opb_dn ?
{2'b00, s_fractb, 3'b000} : {2'b01, s_fractb, 3'b000};
assign s_mux_diff = {s_expa_gt_expb, s_opa_dn ^ s_opb_dn};
// calculate howmany postions the fraction will be shifted
always @(posedge clk_i)
begin
case(s_mux_diff)
2'b00: s_exp_diff <= s_expb - s_expa;
2'b01: s_exp_diff <= s_expb - (s_expa + 8'd1);
2'b10: s_exp_diff <= s_expa - s_expb;
2'b11: s_exp_diff <= s_expa - (s_expb + 8'd1);
endcase
end
assign s_fract_sm_28 = s_expa_gt_expb ? s_fractb_28 : s_fracta_28;
// shift-right the fraction if necessary
assign s_fract_shr_28 = s_fract_sm_28 >> s_exp_diff;
 
// count the zeros from right to check if result is inexact
always @(s_fract_sm_28)
casex(s_fract_sm_28) // synopsys full_case parallel_case
28'b???????????????????????????1: s_rzeros <= 0;
28'b??????????????????????????10: s_rzeros <= 1;
28'b?????????????????????????100: s_rzeros <= 2;
28'b????????????????????????1000: s_rzeros <= 3;
28'b???????????????????????10000: s_rzeros <= 4;
28'b??????????????????????100000: s_rzeros <= 5;
28'b?????????????????????1000000: s_rzeros <= 6;
28'b????????????????????10000000: s_rzeros <= 7;
28'b???????????????????100000000: s_rzeros <= 8;
28'b??????????????????1000000000: s_rzeros <= 9;
28'b?????????????????10000000000: s_rzeros <= 10;
28'b????????????????100000000000: s_rzeros <= 11;
28'b???????????????1000000000000: s_rzeros <= 12;
28'b??????????????10000000000000: s_rzeros <= 13;
28'b?????????????100000000000000: s_rzeros <= 14;
28'b????????????1000000000000000: s_rzeros <= 15;
28'b???????????10000000000000000: s_rzeros <= 16;
28'b??????????100000000000000000: s_rzeros <= 17;
28'b?????????1000000000000000000: s_rzeros <= 18;
28'b????????10000000000000000000: s_rzeros <= 19;
28'b???????100000000000000000000: s_rzeros <= 20;
28'b??????1000000000000000000000: s_rzeros <= 21;
28'b?????10000000000000000000000: s_rzeros <= 22;
28'b????100000000000000000000000: s_rzeros <= 23;
28'b???1000000000000000000000000: s_rzeros <= 24;
28'b??10000000000000000000000000: s_rzeros <= 25;
28'b?100000000000000000000000000: s_rzeros <= 26;
28'b1000000000000000000000000000: s_rzeros <= 27;
28'b0000000000000000000000000000: s_rzeros <= 28;
endcase // casex (s_fract_sm_28)
assign s_sticky = (s_exp_diff > s_rzeros) & (|s_fract_sm_28);
assign s_fracta_28_o = s_expa_gt_expb ?
s_fracta_28 :
{s_fract_shr_28[27:1],(s_sticky|s_fract_shr_28[0])};
assign s_fractb_28_o = s_expa_gt_expb ?
{s_fract_shr_28[27:1],(s_sticky|s_fract_shr_28[0])} :
s_fractb_28;
 
endmodule // or1200_fpu_pre_norm_addsub
 
 
/verilog/or1200_spram_1024x32_bw.v
534,9 → 534,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 10'h000;
addr_reg <= 10'h000;
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
 
//
// RAM write byte 0
543,7 → 543,7
//
always @(posedge clk)
if (ce && we[0])
mem_0[addr] <= #1 di[7:0];
mem_0[addr] <= di[7:0];
 
//
// RAM write byte 1
550,7 → 550,7
//
always @(posedge clk)
if (ce && we[1])
mem_1[addr] <= #1 di[15:8];
mem_1[addr] <= di[15:8];
 
//
// RAM write byte 2
557,7 → 557,7
//
always @(posedge clk)
if (ce && we[2])
mem_2[addr] <= #1 di[23:16];
mem_2[addr] <= di[23:16];
 
//
// RAM write byte 3
564,7 → 564,7
//
always @(posedge clk)
if (ce && we[3])
mem_3[addr] <= #1 di[31:24];
mem_3[addr] <= di[31:24];
 
 
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_spram_32_bw.v
104,7 → 104,7
//
// Generic RAM's registers and wires
//
`ifdef OR1200_ACTEL
`ifdef OR1200_GENERIC
reg [7:0] mem0 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [7:0] mem1 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [7:0] mem2 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
127,21 → 127,21
//
always @(posedge clk)
if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
//
// RAM write
// RAM write - big endian selection
//
always @(posedge clk)
if (ce) begin
if (we[3])
mem0[addr] <= di[31:24];
if (we[2])
mem1[addr] <= di[23:16];
if (we[1])
mem2[addr] <= di[15:08];
if (we[0])
mem0[addr] <= #1 di[31:24];
if (we[1])
mem1[addr] <= #1 di[23:16];
if (we[2])
mem2[addr] <= #1 di[15:08];
if (we[3])
mem3[addr] <= #1 di[07:00];
mem3[addr] <= di[07:00];
end
endmodule // or1200_spram
/verilog/or1200_dmmu_top.v
3,7 → 3,7
//// OR1200's Data MMU top level ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://www.opencores.org/project,or1k ////
//// ////
//// Description ////
//// Instantiation of all DMMU blocks. ////
41,62 → 41,11
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_dmmu_top.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// Minor update:
// Bugs fixed.
//
// Revision 1.9 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.7.4.2 2003/12/09 11:46:48 simons
// Mbist nameing changed, Artisan ram instance signal names fixed, some synthesis waning fixed.
//
// Revision 1.7.4.1 2003/07/08 15:36:37 lampret
// Added embedded memory QMEM.
//
// Revision 1.7 2002/10/17 20:04:40 lampret
// Added BIST scan. Special VS RAMs need to be used to implement BIST.
//
// Revision 1.6 2002/03/29 15:16:55 lampret
// Some of the warnings fixed.
//
// Revision 1.5 2002/02/14 15:34:02 simons
// Lapsus fixed.
//
// Revision 1.4 2002/02/11 04:33:17 lampret
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
//
// Revision 1.3 2002/01/28 01:16:00 lampret
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
//
// Revision 1.2 2002/01/14 06:18:22 lampret
// Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.6 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.5 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:36 igorm
// no message
//
// Revision 1.1 2001/08/17 08:03:35 lampret
// *** empty log message ***
//
// Revision 1.2 2001/07/22 03:31:53 lampret
// Fixed RAM's oen bug. Cache bypass under development.
//
// Revision 1.1 2001/07/20 00:46:03 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
255,44 → 204,45
assign dcpu_err_o = miss | fault | qmemdmmu_err_i;
 
//
// Assert dtlb_done one clock cycle after new address and dtlb_en must be active.
// Assert dtlb_done one clock cycle after new address and dtlb_en must be active
//
always @(posedge clk or posedge rst)
if (rst)
dtlb_done <= #1 1'b0;
dtlb_done <= 1'b0;
else if (dtlb_en)
dtlb_done <= #1 dcpu_cycstb_i;
dtlb_done <= dcpu_cycstb_i;
else
dtlb_done <= #1 1'b0;
dtlb_done <= 1'b0;
 
//
// Cut transfer if something goes wrong with translation. Also delayed signals because of translation delay.
//
assign qmemdmmu_cycstb_o = (!dc_en & dmmu_en) ? ~(miss | fault) & dtlb_done & dcpu_cycstb_i : ~(miss | fault) & dcpu_cycstb_i;
//assign qmemdmmu_cycstb_o = (dmmu_en) ? ~(miss | fault) & dcpu_cycstb_i : (miss | fault) ? 1'b0 : dcpu_cycstb_i;
// Cut transfer if something goes wrong with translation. Also delayed signals
// because of translation delay.
assign qmemdmmu_cycstb_o = (dc_en & dmmu_en) ?
!(miss | fault) & dtlb_done & dcpu_cycstb_i :
!(miss | fault) & dcpu_cycstb_i;
 
 
//
// Cache Inhibit
//
//assign qmemdmmu_ci_o = dmmu_en ? dtlb_done & dtlb_ci : `OR1200_DMMU_CI;
assign qmemdmmu_ci_o = dmmu_en ? dtlb_ci : `OR1200_DMMU_CI;
 
//
// Register dcpu_adr_i's VPN for use when DMMU is not enabled but PPN is expected to come
// one clock cycle after offset part.
// Register dcpu_adr_i's VPN for use when DMMU is not enabled but PPN is
// expected to come one clock cycle after offset part.
//
always @(posedge clk or posedge rst)
if (rst)
dcpu_vpn_r <= #1 {31-`OR1200_DMMU_PS{1'b0}};
dcpu_vpn_r <= {31-`OR1200_DMMU_PS{1'b0}};
else
dcpu_vpn_r <= #1 dcpu_adr_i[31:`OR1200_DMMU_PS];
dcpu_vpn_r <= dcpu_adr_i[31:`OR1200_DMMU_PS];
 
//
// Physical address is either translated virtual address or
// simply equal when DMMU is disabled
//
// assign qmemdmmu_adr_o = dmmu_en ? {dtlb_ppn, dcpu_adr_i[`OR1200_DMMU_PS-1:0]} : {dcpu_vpn_r, dcpu_adr_i[`OR1200_DMMU_PS-1:0]};
assign qmemdmmu_adr_o = dmmu_en ? {dtlb_ppn, dcpu_adr_i[`OR1200_DMMU_PS-1:0]} : dcpu_adr_i;
assign qmemdmmu_adr_o = dmmu_en ? {dtlb_ppn, dcpu_adr_i[`OR1200_DMMU_PS-1:0]} :
dcpu_adr_i;
 
//
// Output to SPRS unit
303,10 → 253,10
// Page fault exception logic
//
assign fault = dtlb_done &
( (!dcpu_we_i & !supv & !dtlb_ure) // Load in user mode not enabled
|| (!dcpu_we_i & supv & !dtlb_sre) // Load in supv mode not enabled
|| (dcpu_we_i & !supv & !dtlb_uwe) // Store in user mode not enabled
|| (dcpu_we_i & supv & !dtlb_swe) ); // Store in supv mode not enabled
( (!dcpu_we_i & !supv & !dtlb_ure) // Load in user mode not enabled
|| (!dcpu_we_i & supv & !dtlb_sre) // Load in supv mode not enabled
|| (dcpu_we_i & !supv & !dtlb_uwe) // Store in user mode not enabled
|| (dcpu_we_i & supv & !dtlb_swe)); // Store in supv mode not enabled
 
//
// TLB Miss exception logic
/verilog/or1200_spram_64x14.v
378,9 → 378,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
//
// RAM write
387,7 → 387,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_except.v
267,28 → 267,28
 
always @(posedge clk or posedge rst) begin
if (rst) begin
trace_trap <= #1 1'b0 ;
trace_trap <= 1'b0 ;
end
else if (!(trace_trap && !ex_pc_val)) begin
trace_trap <= #1 trace_cond & !dsr_te & !sr_ted ;
trace_trap <= trace_cond & !dsr_te & !sr_ted ;
end
end
 
always @(posedge clk or posedge rst) begin
if (rst) begin
ex_freeze_prev <= #1 1'b0 ;
sr_ted_prev <= #1 1'b0 ;
dsr_te_prev <= #1 1'b0 ;
dmr1_st_prev <= #1 1'b0 ;
dmr1_bt_prev <= #1 1'b0 ;
ex_freeze_prev <= 1'b0 ;
sr_ted_prev <= 1'b0 ;
dsr_te_prev <= 1'b0 ;
dmr1_st_prev <= 1'b0 ;
dmr1_bt_prev <= 1'b0 ;
end
else begin
ex_freeze_prev <= #1 ex_freeze ;
ex_freeze_prev <= ex_freeze ;
if (!ex_freeze_prev || ex_void) begin
sr_ted_prev <= #1 sr [`OR1200_SR_TED ] ;
dsr_te_prev <= #1 du_dsr [`OR1200_DU_DSR_TE ] ;
dmr1_st_prev <= #1 du_dmr1[`OR1200_DU_DMR1_ST] ;
dmr1_bt_prev <= #1 du_dmr1[`OR1200_DU_DMR1_BT] ;
sr_ted_prev <= sr [`OR1200_SR_TED ] ;
dsr_te_prev <= du_dsr [`OR1200_DU_DSR_TE ] ;
dmr1_st_prev <= du_dmr1[`OR1200_DU_DMR1_ST] ;
dmr1_bt_prev <= du_dmr1[`OR1200_DU_DMR1_BT] ;
end
end
end
298,18 → 298,18
//
always @(posedge clk or posedge rst) begin
if (rst) begin
id_pc <= #1 32'd0;
id_pc_val <= #1 1'b0 ;
id_exceptflags <= #1 3'b000;
id_pc <= 32'd0;
id_pc_val <= 1'b0 ;
id_exceptflags <= 3'b000;
end
else if (id_flushpipe) begin
id_pc_val <= #1 1'b0 ;
id_exceptflags <= #1 3'b000;
id_pc_val <= 1'b0 ;
id_exceptflags <= 3'b000;
end
else if (!id_freeze) begin
id_pc <= #1 if_pc;
id_pc_val <= #1 1'b1 ;
id_exceptflags <= #1 { sig_ibuserr, sig_itlbmiss, sig_immufault };
id_pc <= if_pc;
id_pc_val <= 1'b1 ;
id_exceptflags <= { sig_ibuserr, sig_itlbmiss, sig_immufault };
end
end
 
323,11 → 323,11
//
always @(posedge rst or posedge clk)
if (rst)
delayed_iee <= #1 3'b000;
delayed_iee <= 3'b000;
else if (!sr[`OR1200_SR_IEE])
delayed_iee <= #1 3'b000;
delayed_iee <= 3'b000;
else
delayed_iee <= #1 {delayed_iee[1:0], 1'b1};
delayed_iee <= {delayed_iee[1:0], 1'b1};
 
//
// delayed_tee
339,11 → 339,11
//
always @(posedge rst or posedge clk)
if (rst)
delayed_tee <= #1 3'b000;
delayed_tee <= 3'b000;
else if (!sr[`OR1200_SR_TEE])
delayed_tee <= #1 3'b000;
delayed_tee <= 3'b000;
else
delayed_tee <= #1 {delayed_tee[1:0], 1'b1};
delayed_tee <= {delayed_tee[1:0], 1'b1};
 
//
// PC and Exception flags pipelines
350,35 → 350,35
//
always @(posedge clk or posedge rst) begin
if (rst) begin
ex_dslot <= #1 1'b0;
ex_pc <= #1 32'd0;
ex_pc_val <= #1 1'b0 ;
ex_exceptflags <= #1 3'b000;
delayed1_ex_dslot <= #1 1'b0;
delayed2_ex_dslot <= #1 1'b0;
ex_dslot <= 1'b0;
ex_pc <= 32'd0;
ex_pc_val <= 1'b0 ;
ex_exceptflags <= 3'b000;
delayed1_ex_dslot <= 1'b0;
delayed2_ex_dslot <= 1'b0;
end
else if (ex_flushpipe) begin
ex_dslot <= #1 1'b0;
ex_pc_val <= #1 1'b0 ;
ex_exceptflags <= #1 3'b000;
delayed1_ex_dslot <= #1 1'b0;
delayed2_ex_dslot <= #1 1'b0;
ex_dslot <= 1'b0;
ex_pc_val <= 1'b0 ;
ex_exceptflags <= 3'b000;
delayed1_ex_dslot <= 1'b0;
delayed2_ex_dslot <= 1'b0;
end
else if (!ex_freeze & id_freeze) begin
ex_dslot <= #1 1'b0;
ex_pc <= #1 id_pc;
ex_pc_val <= #1 id_pc_val ;
ex_exceptflags <= #1 3'b000;
delayed1_ex_dslot <= #1 ex_dslot;
delayed2_ex_dslot <= #1 delayed1_ex_dslot;
ex_dslot <= 1'b0;
ex_pc <= id_pc;
ex_pc_val <= id_pc_val ;
ex_exceptflags <= 3'b000;
delayed1_ex_dslot <= ex_dslot;
delayed2_ex_dslot <= delayed1_ex_dslot;
end
else if (!ex_freeze) begin
ex_dslot <= #1 ex_branch_taken;
ex_pc <= #1 id_pc;
ex_pc_val <= #1 id_pc_val ;
ex_exceptflags <= #1 id_exceptflags;
delayed1_ex_dslot <= #1 ex_dslot;
delayed2_ex_dslot <= #1 delayed1_ex_dslot;
ex_dslot <= ex_branch_taken;
ex_pc <= id_pc;
ex_pc_val <= id_pc_val ;
ex_exceptflags <= id_exceptflags;
delayed1_ex_dslot <= ex_dslot;
delayed2_ex_dslot <= delayed1_ex_dslot;
end
end
 
387,12 → 387,12
//
always @(posedge clk or posedge rst) begin
if (rst) begin
wb_pc <= #1 32'd0;
dl_pc <= #1 32'd0;
wb_pc <= 32'd0;
dl_pc <= 32'd0;
end
else if (!wb_freeze) begin
wb_pc <= #1 ex_pc;
dl_pc <= #1 wb_pc;
wb_pc <= ex_pc;
dl_pc <= wb_pc;
end
end
 
411,13 → 411,13
//
always @(posedge clk or posedge rst) begin
if (rst) begin
state <= #1 `OR1200_EXCEPTFSM_IDLE;
except_type <= #1 `OR1200_EXCEPT_NONE;
extend_flush <= #1 1'b0;
epcr <= #1 32'b0;
eear <= #1 32'b0;
esr <= #1 {2'h1, {`OR1200_SR_WIDTH-3{1'b0}}, 1'b1};
extend_flush_last <= #1 1'b0;
state <= `OR1200_EXCEPTFSM_IDLE;
except_type <= `OR1200_EXCEPT_NONE;
extend_flush <= 1'b0;
epcr <= 32'b0;
eear <= 32'b0;
esr <= {2'h1, {`OR1200_SR_WIDTH-3{1'b0}}, 1'b1};
extend_flush_last <= 1'b0;
end
else begin
`ifdef OR1200_CASE_DEFAULT
427,27 → 427,27
`endif
`OR1200_EXCEPTFSM_IDLE:
if (except_flushpipe) begin
state <= #1 `OR1200_EXCEPTFSM_FLU1;
extend_flush <= #1 1'b1;
esr <= #1 sr_we ? to_sr : sr;
state <= `OR1200_EXCEPTFSM_FLU1;
extend_flush <= 1'b1;
esr <= sr_we ? to_sr : sr;
casex (except_trig)
`ifdef OR1200_EXCEPT_ITLBMISS
14'b1x_xxxx_xxxx_xxxx: begin
except_type <= #1 `OR1200_EXCEPT_ITLBMISS;
eear <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_ITLBMISS;
eear <= ex_dslot ?
ex_pc : ex_pc;
epcr <= #1 ex_dslot ?
epcr <= ex_dslot ?
wb_pc : ex_pc;
end
`endif
`ifdef OR1200_EXCEPT_IPF
14'b01_xxxx_xxxx_xxxx: begin
except_type <= #1 `OR1200_EXCEPT_IPF;
eear <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_IPF;
eear <= ex_dslot ?
ex_pc : delayed1_ex_dslot ?
id_pc : delayed2_ex_dslot ?
id_pc : id_pc;
epcr <= #1 ex_dslot ?
epcr <= ex_dslot ?
wb_pc : delayed1_ex_dslot ?
id_pc : delayed2_ex_dslot ?
id_pc : id_pc;
455,34 → 455,34
`endif
`ifdef OR1200_EXCEPT_BUSERR
14'b00_1xxx_xxxx_xxxx: begin // Insn. Bus Error
except_type <= #1 `OR1200_EXCEPT_BUSERR;
eear <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_BUSERR;
eear <= ex_dslot ?
wb_pc : ex_pc;
epcr <= #1 ex_dslot ?
epcr <= ex_dslot ?
wb_pc : ex_pc;
end
`endif
`ifdef OR1200_EXCEPT_ILLEGAL
14'b00_01xx_xxxx_xxxx: begin
except_type <= #1 `OR1200_EXCEPT_ILLEGAL;
eear <= #1 ex_pc;
epcr <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_ILLEGAL;
eear <= ex_pc;
epcr <= ex_dslot ?
wb_pc : ex_pc;
end
`endif
`ifdef OR1200_EXCEPT_ALIGN
14'b00_001x_xxxx_xxxx: begin
except_type <= #1 `OR1200_EXCEPT_ALIGN;
eear <= #1 lsu_addr;
epcr <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_ALIGN;
eear <= lsu_addr;
epcr <= ex_dslot ?
wb_pc : ex_pc;
end
`endif
`ifdef OR1200_EXCEPT_DTLBMISS
14'b00_0001_xxxx_xxxx: begin
except_type <= #1 `OR1200_EXCEPT_DTLBMISS;
eear <= #1 lsu_addr;
epcr <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_DTLBMISS;
eear <= lsu_addr;
epcr <= ex_dslot ?
wb_pc : delayed1_ex_dslot ?
dl_pc : ex_pc;
end
489,8 → 489,8
`endif
`ifdef OR1200_EXCEPT_TRAP
14'b00_0000_1xxx_xxxx: begin
except_type <= #1 `OR1200_EXCEPT_TRAP;
epcr <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_TRAP;
epcr <= ex_dslot ?
wb_pc : delayed1_ex_dslot ?
id_pc : ex_pc;
end
497,8 → 497,8
`endif
`ifdef OR1200_EXCEPT_SYSCALL
14'b00_0000_01xx_xxxx: begin
except_type <= #1 `OR1200_EXCEPT_SYSCALL;
epcr <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_SYSCALL;
epcr <= ex_dslot ?
wb_pc : delayed1_ex_dslot ?
id_pc : delayed2_ex_dslot ?
id_pc : id_pc;
506,9 → 506,9
`endif
`ifdef OR1200_EXCEPT_DPF
14'b00_0000_001x_xxxx: begin
except_type <= #1 `OR1200_EXCEPT_DPF;
eear <= #1 lsu_addr;
epcr <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_DPF;
eear <= lsu_addr;
epcr <= ex_dslot ?
wb_pc : delayed1_ex_dslot ?
dl_pc : ex_pc;
end
515,9 → 515,9
`endif
`ifdef OR1200_EXCEPT_BUSERR
14'b00_0000_0001_xxxx: begin // Data Bus Error
except_type <= #1 `OR1200_EXCEPT_BUSERR;
eear <= #1 lsu_addr;
epcr <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_BUSERR;
eear <= lsu_addr;
epcr <= ex_dslot ?
wb_pc : delayed1_ex_dslot ?
dl_pc : ex_pc;
end
524,8 → 524,8
`endif
`ifdef OR1200_EXCEPT_RANGE
14'b00_0000_0000_1xxx: begin
except_type <= #1 `OR1200_EXCEPT_RANGE;
epcr <= #1 ex_dslot ?
except_type <= `OR1200_EXCEPT_RANGE;
epcr <= ex_dslot ?
wb_pc : delayed1_ex_dslot ?
id_pc : delayed2_ex_dslot ?
id_pc : id_pc;
533,60 → 533,60
`endif
`ifdef OR1200_EXCEPT_FLOAT
14'b00_0000_0000_01xx: begin
except_type <= #1 `OR1200_EXCEPT_FLOAT;
epcr <= #1 id_pc;
except_type <= `OR1200_EXCEPT_FLOAT;
epcr <= id_pc;
end
`endif
`ifdef OR1200_EXCEPT_INT
14'b00_0000_0000_001x: begin
except_type <= #1 `OR1200_EXCEPT_INT;
epcr <= #1 id_pc;
except_type <= `OR1200_EXCEPT_INT;
epcr <= id_pc;
end
`endif
`ifdef OR1200_EXCEPT_TICK
14'b00_0000_0000_0001: begin
except_type <= #1 `OR1200_EXCEPT_TICK;
epcr <= #1 id_pc;
except_type <= `OR1200_EXCEPT_TICK;
epcr <= id_pc;
end
`endif
default:
except_type <= #1 `OR1200_EXCEPT_NONE;
except_type <= `OR1200_EXCEPT_NONE;
endcase
end
else if (pc_we) begin
state <= #1 `OR1200_EXCEPTFSM_FLU1;
extend_flush <= #1 1'b1;
state <= `OR1200_EXCEPTFSM_FLU1;
extend_flush <= 1'b1;
end
else begin
if (epcr_we)
epcr <= #1 datain;
epcr <= datain;
if (eear_we)
eear <= #1 datain;
eear <= datain;
if (esr_we)
esr <= #1 {datain[`OR1200_SR_WIDTH-1], 1'b1, datain[`OR1200_SR_WIDTH-3:0]};
esr <= {datain[`OR1200_SR_WIDTH-1], 1'b1, datain[`OR1200_SR_WIDTH-3:0]};
end
`OR1200_EXCEPTFSM_FLU1:
if (icpu_ack_i | icpu_err_i | genpc_freeze)
state <= #1 `OR1200_EXCEPTFSM_FLU2;
state <= `OR1200_EXCEPTFSM_FLU2;
`OR1200_EXCEPTFSM_FLU2:
`ifdef OR1200_EXCEPT_TRAP
if (except_type == `OR1200_EXCEPT_TRAP) begin
state <= #1 `OR1200_EXCEPTFSM_IDLE;
extend_flush <= #1 1'b0;
extend_flush_last <= #1 1'b0;
except_type <= #1 `OR1200_EXCEPT_NONE;
state <= `OR1200_EXCEPTFSM_IDLE;
extend_flush <= 1'b0;
extend_flush_last <= 1'b0;
except_type <= `OR1200_EXCEPT_NONE;
end
else
`endif
state <= #1 `OR1200_EXCEPTFSM_FLU3;
state <= `OR1200_EXCEPTFSM_FLU3;
`OR1200_EXCEPTFSM_FLU3:
begin
state <= #1 `OR1200_EXCEPTFSM_FLU4;
state <= `OR1200_EXCEPTFSM_FLU4;
end
`OR1200_EXCEPTFSM_FLU4: begin
state <= #1 `OR1200_EXCEPTFSM_FLU5;
extend_flush <= #1 1'b0;
extend_flush_last <= #1 1'b0; // damjan
state <= `OR1200_EXCEPTFSM_FLU5;
extend_flush <= 1'b0;
extend_flush_last <= 1'b0; // damjan
end
`ifdef OR1200_CASE_DEFAULT
default: begin
594,9 → 594,9
`OR1200_EXCEPTFSM_FLU5: begin
`endif
if (!if_stall && !id_freeze) begin
state <= #1 `OR1200_EXCEPTFSM_IDLE;
except_type <= #1 `OR1200_EXCEPT_NONE;
extend_flush_last <= #1 1'b0;
state <= `OR1200_EXCEPTFSM_IDLE;
except_type <= `OR1200_EXCEPT_NONE;
extend_flush_last <= 1'b0;
end
end
endcase
/verilog/or1200_genpc.v
140,11 → 140,11
//
always @(posedge clk or posedge rst)
if (rst)
genpc_refetch_r <= #1 1'b0;
genpc_refetch_r <= 1'b0;
else if (genpc_refetch)
genpc_refetch_r <= #1 1'b1;
genpc_refetch_r <= 1'b1;
else
genpc_refetch_r <= #1 1'b0;
genpc_refetch_r <= 1'b0;
 
//
// Async calculation of new PC value. This value is used for addressing the
258,22 → 258,22
always @(posedge clk or posedge rst)
// default value
if (rst) begin
pcreg_default <= #1 `OR1200_BOOT_PCREG_DEFAULT; // jb
pcreg_select <= #1 1'b1;// select async. value due to reset state
pcreg_default <= `OR1200_BOOT_PCREG_DEFAULT; // jb
pcreg_select <= 1'b1;// select async. value due to reset state
end
// selected value (different from default) is written into FF after
// reset state
else if (pcreg_select) begin
// dynamic value can only be assigned to FF out of reset!
pcreg_default <= #1 pcreg_boot[31:2];
pcreg_select <= #1 1'b0; // select FF value
pcreg_default <= pcreg_boot[31:2];
pcreg_select <= 1'b0; // select FF value
end
else if (spr_pc_we) begin
pcreg_default <= #1 spr_dat_i[31:2];
pcreg_default <= spr_dat_i[31:2];
end
else if (no_more_dslot | except_start | !genpc_freeze & !icpu_rty_i
& !genpc_refetch) begin
pcreg_default <= #1 pc[31:2];
pcreg_default <= pc[31:2];
end
 
// select async. value for pcreg after reset - PC jumps to the address selected
/verilog/or1200_fpu_div.v
0,0 → 1,172
//////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_div ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// division entity for the division unit ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Original design (FPU100) - ////
//// Jidan Al-eryani, jidan@gmx.net ////
//// - Conv. to Verilog and inclusion in OR1200 - ////
//// Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2006, 2010
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
module or1200_fpu_div
(
clk_i,
dvdnd_i,
dvsor_i,
sign_dvd_i,
sign_div_i,
start_i,
ready_o,
qutnt_o,
rmndr_o,
sign_o,
div_zero_o
);
 
parameter FP_WIDTH = 32;
parameter MUL_SERIAL = 0; // 0 for parallel multiplier, 1 for serial
parameter MUL_COUNT = 11; //11 for parallel multiplier, 34 for serial
parameter FRAC_WIDTH = 23;
parameter EXP_WIDTH = 8;
parameter ZERO_VECTOR = 31'd0;
parameter INF = 31'b1111111100000000000000000000000;
parameter QNAN = 31'b1111111110000000000000000000000;
parameter SNAN = 31'b1111111100000000000000000000001;
 
 
input clk_i;
input [2*(FRAC_WIDTH+2)-1:0] dvdnd_i;
input [FRAC_WIDTH+3:0] dvsor_i;
input sign_dvd_i;
input sign_div_i;
input start_i;
output ready_o;
output [FRAC_WIDTH+3:0] qutnt_o;
output [FRAC_WIDTH+3:0] rmndr_o;
output sign_o;
output div_zero_o;
parameter t_state_waiting = 1'b0,
t_state_busy = 1'b1;
reg [FRAC_WIDTH+3:0] s_qutnt_o;
reg [FRAC_WIDTH+3:0] s_rmndr_o;
reg [2*(FRAC_WIDTH+2)-1:0] s_dvdnd_i;
reg [FRAC_WIDTH+3:0] s_dvsor_i;
reg s_sign_dvd_i, s_sign_div_i;
wire s_sign_o;
wire s_div_zero_o;
reg s_start_i;
reg s_ready_o;
reg s_state;
reg [4:0] s_count;
reg [FRAC_WIDTH+3:0] s_dvd;
 
// Input Register
always @(posedge clk_i)
begin
s_dvdnd_i <= dvdnd_i;
s_dvsor_i <= dvsor_i;
s_sign_dvd_i<= sign_dvd_i;
s_sign_div_i<= sign_div_i;
s_start_i <= start_i;
end
assign qutnt_o = s_qutnt_o;
assign rmndr_o = s_rmndr_o;
assign sign_o = s_sign_o;
assign ready_o = s_ready_o;
assign div_zero_o = s_div_zero_o;
 
assign s_sign_o = sign_dvd_i ^ sign_div_i;
assign s_div_zero_o = !(|s_dvsor_i) & (|s_dvdnd_i);
 
always @(posedge clk_i)
if (s_start_i)
begin
s_state <= t_state_busy;
s_count <= 26;
end
else if (!(|s_count) & s_state==t_state_busy)
begin
s_state <= t_state_waiting;
s_ready_o <= 1;
s_count <=26;
end
else if (s_state==t_state_busy)
s_count <= s_count - 1;
else
begin
s_state <= t_state_waiting;
s_ready_o <= 0;
end
 
wire [26:0] v_div;
assign v_div = (s_count==26) ? {3'd0,s_dvdnd_i[49:26]} : s_dvd;
wire [26:0] v_div_minus_s_dvsor_i;
assign v_div_minus_s_dvsor_i = v_div - s_dvsor_i;
 
always @(posedge clk_i)
begin
//Reset
if (s_start_i)
begin
s_qutnt_o <= 0;
s_rmndr_o <= 0;
end
else if (s_state==t_state_busy)
begin
 
if (v_div < s_dvsor_i)
begin
s_qutnt_o[s_count] <= 1'b0;
s_dvd <= {v_div[25:0],1'b0};
end
else
begin
s_qutnt_o[s_count] <= 1'b1;
s_dvd <= {v_div_minus_s_dvsor_i[25:0],1'b0};
end
 
s_rmndr_o <= v_div;
 
end // if (s_state==t_state_busy)
end // always @ (posedge clk_i)
 
endmodule // or1200_fpu_div
 
/verilog/or1200_ic_fsm.v
3,7 → 3,7
//// OR1200's IC FSM ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Insn cache state machine ////
41,69 → 41,11
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: or1200_ic_fsm.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// Minor update:
// Bugs fixed.
//
// Revision 1.10 2004/06/08 18:17:36 lampret
// Non-functional changes. Coding style fixes.
//
// Revision 1.9 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.8.4.1 2003/07/08 15:36:37 lampret
// Added embedded memory QMEM.
//
// Revision 1.8 2003/06/06 02:54:47 lampret
// When OR1200_NO_IMMU and OR1200_NO_IC are not both defined or undefined at the same time, results in a IC bug. Fixed.
//
// Revision 1.7 2002/03/29 15:16:55 lampret
// Some of the warnings fixed.
//
// Revision 1.6 2002/03/28 19:10:40 lampret
// Optimized cache controller FSM.
//
// Revision 1.1.1.1 2002/03/21 16:55:45 lampret
// First import of the "new" XESS XSV environment.
//
//
// Revision 1.5 2002/02/11 04:33:17 lampret
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
//
// Revision 1.4 2002/02/01 19:56:54 lampret
// Fixed combinational loops.
//
// Revision 1.3 2002/01/28 01:16:00 lampret
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
//
// Revision 1.2 2002/01/14 06:18:22 lampret
// Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.9 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from ic.v and ic.v. Fixed CR+LF.
//
// Revision 1.8 2001/10/19 23:28:46 lampret
// Fixed some synthesis warnings. Configured with caches and MMUs.
//
// Revision 1.7 2001/10/14 13:12:09 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:35 igorm
// no message
//
// Revision 1.2 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.1 2001/07/20 00:46:03 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
161,117 → 103,130
reg load;
reg cache_inhibit;
 
//
// Generate of ICRAM write enables
//
assign icram_we = {4{biu_read & biudata_valid & !cache_inhibit}};
assign tag_we = biu_read & biudata_valid & !cache_inhibit;
//
// Generate of ICRAM write enables
//
assign icram_we = {4{biu_read & biudata_valid & !cache_inhibit}};
assign tag_we = biu_read & biudata_valid & !cache_inhibit;
 
//
// BIU read and write
//
assign biu_read = (hitmiss_eval & tagcomp_miss) | (!hitmiss_eval & load);
//
// BIU read and write
//
assign biu_read = (hitmiss_eval & tagcomp_miss) | (!hitmiss_eval & load);
 
//assign saved_addr = hitmiss_eval ? start_addr : saved_addr_r;
assign saved_addr = saved_addr_r;
//assign saved_addr = hitmiss_eval ? start_addr : saved_addr_r;
assign saved_addr = saved_addr_r;
 
//
// Assert for cache hit first word ready
// Assert for cache miss first word stored/loaded OK
// Assert for cache miss first word stored/loaded with an error
//
assign first_hit_ack = (state == `OR1200_ICFSM_CFETCH) & hitmiss_eval & !tagcomp_miss & !cache_inhibit;
assign first_miss_ack = (state == `OR1200_ICFSM_CFETCH) & biudata_valid;
assign first_miss_err = (state == `OR1200_ICFSM_CFETCH) & biudata_error;
//
// Assert for cache hit first word ready
// Assert for cache miss first word stored/loaded OK
// Assert for cache miss first word stored/loaded with an error
//
assign first_hit_ack = (state == `OR1200_ICFSM_CFETCH) & hitmiss_eval &
!tagcomp_miss & !cache_inhibit;
assign first_miss_ack = (state == `OR1200_ICFSM_CFETCH) & biudata_valid;
assign first_miss_err = (state == `OR1200_ICFSM_CFETCH) & biudata_error;
 
//
// Assert burst when doing reload of complete cache line
//
assign burst = (state == `OR1200_ICFSM_CFETCH) & tagcomp_miss & !cache_inhibit
| (state == `OR1200_ICFSM_LREFILL3);
//
// Assert burst when doing reload of complete cache line
//
assign burst = (state == `OR1200_ICFSM_CFETCH) & tagcomp_miss &
!cache_inhibit | (state == `OR1200_ICFSM_LREFILL3);
 
//
// Main IC FSM
//
always @(posedge clk or posedge rst) begin
if (rst) begin
state <= #1 `OR1200_ICFSM_IDLE;
saved_addr_r <= #1 32'b0;
hitmiss_eval <= #1 1'b0;
load <= #1 1'b0;
cnt <= #1 3'b000;
cache_inhibit <= #1 1'b0;
end
else
//
// Main IC FSM
//
always @(posedge clk or posedge rst) begin
if (rst) begin
state <= `OR1200_ICFSM_IDLE;
saved_addr_r <= 32'b0;
hitmiss_eval <= 1'b0;
load <= 1'b0;
cnt <= 3'b000;
cache_inhibit <= 1'b0;
end
else
case (state) // synopsys parallel_case
`OR1200_ICFSM_IDLE :
if (ic_en & icqmem_cycstb_i) begin // fetch
state <= #1 `OR1200_ICFSM_CFETCH;
saved_addr_r <= #1 start_addr;
hitmiss_eval <= #1 1'b1;
load <= #1 1'b1;
cache_inhibit <= #1 icqmem_ci_i;
end
else begin // idle
hitmiss_eval <= #1 1'b0;
load <= #1 1'b0;
cache_inhibit <= #1 1'b0;
end
`OR1200_ICFSM_CFETCH: begin // fetch
if (icqmem_cycstb_i & icqmem_ci_i)
cache_inhibit <= #1 1'b1;
if (hitmiss_eval)
saved_addr_r[31:13] <= #1 start_addr[31:13];
if ((!ic_en) ||
(hitmiss_eval & !icqmem_cycstb_i) || // fetch aborted (usually caused by IMMU)
(biudata_error) || // fetch terminated with an error
(cache_inhibit & biudata_valid)) begin // fetch from cache-inhibited page
state <= #1 `OR1200_ICFSM_IDLE;
hitmiss_eval <= #1 1'b0;
load <= #1 1'b0;
cache_inhibit <= #1 1'b0;
end
else if (tagcomp_miss & biudata_valid) begin // fetch missed, finish current external fetch and refill
state <= #1 `OR1200_ICFSM_LREFILL3;
saved_addr_r[3:2] <= #1 saved_addr_r[3:2] + 1'd1;
hitmiss_eval <= #1 1'b0;
cnt <= #1 `OR1200_ICLS-2;
cache_inhibit <= #1 1'b0;
end
else if (!icqmem_cycstb_i) begin // fetch aborted (usually caused by exception)
state <= #1 `OR1200_ICFSM_IDLE;
hitmiss_eval <= #1 1'b0;
load <= #1 1'b0;
cache_inhibit <= #1 1'b0;
end
else if (!tagcomp_miss & !icqmem_ci_i) begin // fetch hit, finish immediately
saved_addr_r <= #1 start_addr;
cache_inhibit <= #1 1'b0;
end
else // fetch in-progress
hitmiss_eval <= #1 1'b0;
end
`OR1200_ICFSM_LREFILL3 : begin
if (!ic_en) begin // abort because IC has just been turned off
state <= #1 `OR1200_ICFSM_IDLE; // invalidate before IC can be turned on
saved_addr_r <= #1 start_addr;
hitmiss_eval <= #1 1'b0;
load <= #1 1'b0;
end
else if (biudata_valid && (|cnt)) begin // refill ack, more fetchs to come
cnt <= #1 cnt - 3'd1;
saved_addr_r[3:2] <= #1 saved_addr_r[3:2] + 1'd1;
end
else if (biudata_valid) begin // last fetch of line refill
state <= #1 `OR1200_ICFSM_IDLE;
saved_addr_r <= #1 start_addr;
hitmiss_eval <= #1 1'b0;
load <= #1 1'b0;
end
end
default:
state <= #1 `OR1200_ICFSM_IDLE;
`OR1200_ICFSM_IDLE :
if (ic_en & icqmem_cycstb_i) begin // fetch
state <= `OR1200_ICFSM_CFETCH;
saved_addr_r <= start_addr;
hitmiss_eval <= 1'b1;
load <= 1'b1;
cache_inhibit <= icqmem_ci_i;
end
else begin // idle
hitmiss_eval <= 1'b0;
load <= 1'b0;
cache_inhibit <= 1'b0;
end
`OR1200_ICFSM_CFETCH: begin // fetch
if (icqmem_cycstb_i & icqmem_ci_i)
cache_inhibit <= 1'b1;
if (hitmiss_eval)
saved_addr_r[31:13] <= start_addr[31:13];
if ((!ic_en) ||
// fetch aborted (usually caused by IMMU)
(hitmiss_eval & !icqmem_cycstb_i) ||
(biudata_error) || // fetch terminated with an error
// fetch from cache-inhibited page
(cache_inhibit & biudata_valid)) begin
state <= `OR1200_ICFSM_IDLE;
hitmiss_eval <= 1'b0;
load <= 1'b0;
cache_inhibit <= 1'b0;
end // if ((!ic_en) ||...
// fetch missed, finish current external fetch and refill
else if (tagcomp_miss & biudata_valid) begin
state <= `OR1200_ICFSM_LREFILL3;
saved_addr_r[3:2] <= saved_addr_r[3:2] + 1'd1;
hitmiss_eval <= 1'b0;
cnt <= `OR1200_ICLS-2;
cache_inhibit <= 1'b0;
end
// fetch aborted (usually caused by exception)
else if (!icqmem_cycstb_i) begin
state <= `OR1200_ICFSM_IDLE;
hitmiss_eval <= 1'b0;
load <= 1'b0;
cache_inhibit <= 1'b0;
end
// fetch hit, finish immediately
else if (!tagcomp_miss & !icqmem_ci_i) begin
saved_addr_r <= start_addr;
cache_inhibit <= 1'b0;
end
else // fetch in-progress
hitmiss_eval <= 1'b0;
end
`OR1200_ICFSM_LREFILL3 : begin
// abort because IC has just been turned off
if (!ic_en) begin
// invalidate before IC can be turned on
state <= `OR1200_ICFSM_IDLE;
saved_addr_r <= start_addr;
hitmiss_eval <= 1'b0;
load <= 1'b0;
end
// refill ack, more fetchs to come
else if (biudata_valid && (|cnt)) begin
cnt <= cnt - 3'd1;
saved_addr_r[3:2] <= saved_addr_r[3:2] + 1'd1;
end
// last fetch of line refill
else if (biudata_valid) begin
state <= `OR1200_ICFSM_IDLE;
saved_addr_r <= start_addr;
hitmiss_eval <= 1'b0;
load <= 1'b0;
end
end
default:
state <= `OR1200_ICFSM_IDLE;
endcase
end
end
 
endmodule
/verilog/or1200_top.v
3,7 → 3,7
//// OR1200 Top Level ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://www.opencores.org/cores/or1k/ ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// OR1200 Top Level ////
48,100 → 48,6
// Major update:
// Structure reordered.
//
// Revision 1.13 2004/06/08 18:17:36 lampret
// Non-functional changes. Coding style fixes.
//
// Revision 1.12 2004/04/05 08:29:57 lampret
// Merged branch_qmem into main tree.
//
// Revision 1.10.4.9 2004/02/11 01:40:11 lampret
// preliminary HW breakpoints support in debug unit (by default disabled). To enable define OR1200_DU_HWBKPTS.
//
// Revision 1.10.4.8 2004/01/17 21:14:14 simons
// Errors fixed.
//
// Revision 1.10.4.7 2004/01/17 19:06:38 simons
// Error fixed.
//
// Revision 1.10.4.6 2004/01/17 18:39:48 simons
// Error fixed.
//
// Revision 1.10.4.5 2004/01/15 06:46:38 markom
// interface to debug changed; no more opselect; stb-ack protocol
//
// Revision 1.10.4.4 2003/12/09 11:46:49 simons
// Mbist nameing changed, Artisan ram instance signal names fixed, some synthesis waning fixed.
//
// Revision 1.10.4.3 2003/12/05 00:08:44 lampret
// Fixed instantiation name.
//
// Revision 1.10.4.2 2003/07/11 01:10:35 lampret
// Added three missing wire declarations. No functional changes.
//
// Revision 1.10.4.1 2003/07/08 15:36:37 lampret
// Added embedded memory QMEM.
//
// Revision 1.10 2002/12/08 08:57:56 lampret
// Added optional support for WB B3 specification (xwb_cti_o, xwb_bte_o). Made xwb_cab_o optional.
//
// Revision 1.9 2002/10/17 20:04:41 lampret
// Added BIST scan. Special VS RAMs need to be used to implement BIST.
//
// Revision 1.8 2002/08/18 19:54:22 lampret
// Added store buffer.
//
// Revision 1.7 2002/07/14 22:17:17 lampret
// Added simple trace buffer [only for Xilinx Virtex target]. Fixed instruction fetch abort when new exception is recognized.
//
// Revision 1.6 2002/03/29 15:16:56 lampret
// Some of the warnings fixed.
//
// Revision 1.5 2002/02/11 04:33:17 lampret
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
//
// Revision 1.4 2002/02/01 19:56:55 lampret
// Fixed combinational loops.
//
// Revision 1.3 2002/01/28 01:16:00 lampret
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
//
// Revision 1.2 2002/01/18 07:56:00 lampret
// No more low/high priority interrupts (PICPR removed). Added tick timer exception. Added exception prefix (SR[EPH]). Fixed single-step bug whenreading NPC.
//
// Revision 1.1 2002/01/03 08:16:15 lampret
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
//
// Revision 1.13 2001/11/23 08:38:51 lampret
// Changed DSR/DRR behavior and exception detection.
//
// Revision 1.12 2001/11/20 00:57:22 lampret
// Fixed width of du_except.
//
// Revision 1.11 2001/11/18 08:36:28 lampret
// For GDB changed single stepping and disabled trap exception.
//
// Revision 1.10 2001/10/21 17:57:16 lampret
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
//
// Revision 1.9 2001/10/14 13:12:10 lampret
// MP3 version.
//
// Revision 1.1.1.1 2001/10/06 10:18:35 igorm
// no message
//
// Revision 1.4 2001/08/13 03:36:20 lampret
// Added cfg regs. Moved all defines into one defines.v file. More cleanup.
//
// Revision 1.3 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.2 2001/07/22 03:31:54 lampret
// Fixed RAM's oen bug. Cache bypass under development.
//
// Revision 1.1 2001/07/20 00:46:21 lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
388,7 → 294,8
wire dcpu_rty_qmem;
wire dcpu_err_dmmu;
wire [3:0] dcpu_tag_dmmu;
 
wire dc_no_writethrough;
//
// IMMU and CPU
//
765,6 → 672,7
.dcpu_rty_i(dcpu_rty_qmem),
.dcpu_err_i(dcpu_err_dmmu),
.dcpu_tag_i(dcpu_tag_dmmu),
.dc_no_writethrough(dc_no_writethrough),
 
// Connection DMMU and CPU internally
.dmmu_en(dmmu_en),
791,7 → 699,8
.spr_dat_du(spr_dat_du),
.spr_dat_npc(spr_dat_npc),
.spr_cs(spr_cs),
.spr_we(spr_we)
.spr_we(spr_we),
.mtspr_dc_done(mtspr_dc_done)
);
 
//
863,10 → 772,14
.dcqmem_err_o(dcqmem_err_dc),
.dcqmem_tag_o(dcqmem_tag_dc),
 
.dc_no_writethrough(dc_no_writethrough),
 
// SPR access
.spr_cs(spr_cs[`OR1200_SPR_GROUP_DC]),
.spr_addr(spr_addr),
.spr_write(spr_we),
.spr_dat_i(spr_dat_cpu),
.mtspr_dc_done(mtspr_dc_done),
 
// DC and BIU
.dcsb_dat_o(dcsb_dat_dc),
/verilog/or1200_spram_512x20.v
411,9 → 411,9
//
always @(posedge clk or posedge rst)
if (rst)
addr_reg <= #1 {aw{1'b0}};
addr_reg <= {aw{1'b0}};
else if (ce)
addr_reg <= #1 addr;
addr_reg <= addr;
 
//
// RAM write
420,7 → 420,7
//
always @(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
mem[addr] <= di;
 
`endif // !OR1200_ALTERA_LPM
`endif // !OR1200_XILINX_RAMB16
/verilog/or1200_rfram_generic.v
156,45 → 156,45
//
always @(posedge clk or posedge rst)
if (rst) begin
mem <= #1 {512'h0, 512'h0};
mem <= {512'h0, 512'h0};
end
else if (ce_w & we_w)
case (addr_w) // synopsys parallel_case
5'd01: mem[32*1+31:32*1] <= #1 di_w;
5'd02: mem[32*2+31:32*2] <= #1 di_w;
5'd03: mem[32*3+31:32*3] <= #1 di_w;
5'd04: mem[32*4+31:32*4] <= #1 di_w;
5'd05: mem[32*5+31:32*5] <= #1 di_w;
5'd06: mem[32*6+31:32*6] <= #1 di_w;
5'd07: mem[32*7+31:32*7] <= #1 di_w;
5'd08: mem[32*8+31:32*8] <= #1 di_w;
5'd09: mem[32*9+31:32*9] <= #1 di_w;
5'd10: mem[32*10+31:32*10] <= #1 di_w;
5'd11: mem[32*11+31:32*11] <= #1 di_w;
5'd12: mem[32*12+31:32*12] <= #1 di_w;
5'd13: mem[32*13+31:32*13] <= #1 di_w;
5'd14: mem[32*14+31:32*14] <= #1 di_w;
5'd15: mem[32*15+31:32*15] <= #1 di_w;
5'd01: mem[32*1+31:32*1] <= di_w;
5'd02: mem[32*2+31:32*2] <= di_w;
5'd03: mem[32*3+31:32*3] <= di_w;
5'd04: mem[32*4+31:32*4] <= di_w;
5'd05: mem[32*5+31:32*5] <= di_w;
5'd06: mem[32*6+31:32*6] <= di_w;
5'd07: mem[32*7+31:32*7] <= di_w;
5'd08: mem[32*8+31:32*8] <= di_w;
5'd09: mem[32*9+31:32*9] <= di_w;
5'd10: mem[32*10+31:32*10] <= di_w;
5'd11: mem[32*11+31:32*11] <= di_w;
5'd12: mem[32*12+31:32*12] <= di_w;
5'd13: mem[32*13+31:32*13] <= di_w;
5'd14: mem[32*14+31:32*14] <= di_w;
5'd15: mem[32*15+31:32*15] <= di_w;
`ifdef OR1200_RFRAM_16REG
`else
5'd16: mem[32*16+31:32*16] <= #1 di_w;
5'd17: mem[32*17+31:32*17] <= #1 di_w;
5'd18: mem[32*18+31:32*18] <= #1 di_w;
5'd19: mem[32*19+31:32*19] <= #1 di_w;
5'd20: mem[32*20+31:32*20] <= #1 di_w;
5'd21: mem[32*21+31:32*21] <= #1 di_w;
5'd22: mem[32*22+31:32*22] <= #1 di_w;
5'd23: mem[32*23+31:32*23] <= #1 di_w;
5'd24: mem[32*24+31:32*24] <= #1 di_w;
5'd25: mem[32*25+31:32*25] <= #1 di_w;
5'd26: mem[32*26+31:32*26] <= #1 di_w;
5'd27: mem[32*27+31:32*27] <= #1 di_w;
5'd28: mem[32*28+31:32*28] <= #1 di_w;
5'd29: mem[32*29+31:32*29] <= #1 di_w;
5'd30: mem[32*30+31:32*30] <= #1 di_w;
5'd31: mem[32*31+31:32*31] <= #1 di_w;
5'd16: mem[32*16+31:32*16] <= di_w;
5'd17: mem[32*17+31:32*17] <= di_w;
5'd18: mem[32*18+31:32*18] <= di_w;
5'd19: mem[32*19+31:32*19] <= di_w;
5'd20: mem[32*20+31:32*20] <= di_w;
5'd21: mem[32*21+31:32*21] <= di_w;
5'd22: mem[32*22+31:32*22] <= di_w;
5'd23: mem[32*23+31:32*23] <= di_w;
5'd24: mem[32*24+31:32*24] <= di_w;
5'd25: mem[32*25+31:32*25] <= di_w;
5'd26: mem[32*26+31:32*26] <= di_w;
5'd27: mem[32*27+31:32*27] <= di_w;
5'd28: mem[32*28+31:32*28] <= di_w;
5'd29: mem[32*29+31:32*29] <= di_w;
5'd30: mem[32*30+31:32*30] <= di_w;
5'd31: mem[32*31+31:32*31] <= di_w;
`endif
default: mem[32*0+31:32*0] <= #1 32'h0000_0000;
default: mem[32*0+31:32*0] <= 32'h0000_0000;
endcase
 
//
202,10 → 202,10
//
always @(posedge clk or posedge rst)
if (rst) begin
intaddr_a <= #1 5'h00;
intaddr_a <= 5'h00;
end
else if (ce_a)
intaddr_a <= #1 addr_a;
intaddr_a <= addr_a;
 
always @(mem or intaddr_a)
case (intaddr_a) // synopsys parallel_case
251,10 → 251,10
//
always @(posedge clk or posedge rst)
if (rst) begin
intaddr_b <= #1 5'h00;
intaddr_b <= 5'h00;
end
else if (ce_b)
intaddr_b <= #1 addr_b;
intaddr_b <= addr_b;
 
always @(mem or intaddr_b)
case (intaddr_b) // synopsys parallel_case
/verilog/or1200_dpram.v
104,22 → 104,7
// verilator public
input [aw-1:0] gpr_no;
 
get_gpr = { mem[gpr_no*32 + 31], mem[gpr_no*32 + 30],
mem[gpr_no*32 + 29], mem[gpr_no*32 + 28],
mem[gpr_no*32 + 27], mem[gpr_no*32 + 26],
mem[gpr_no*32 + 25], mem[gpr_no*32 + 24],
mem[gpr_no*32 + 23], mem[gpr_no*32 + 22],
mem[gpr_no*32 + 21], mem[gpr_no*32 + 20],
mem[gpr_no*32 + 19], mem[gpr_no*32 + 18],
mem[gpr_no*32 + 17], mem[gpr_no*32 + 16],
mem[gpr_no*32 + 15], mem[gpr_no*32 + 14],
mem[gpr_no*32 + 13], mem[gpr_no*32 + 12],
mem[gpr_no*32 + 11], mem[gpr_no*32 + 10],
mem[gpr_no*32 + 9], mem[gpr_no*32 + 8],
mem[gpr_no*32 + 7], mem[gpr_no*32 + 6],
mem[gpr_no*32 + 5], mem[gpr_no*32 + 4],
mem[gpr_no*32 + 3], mem[gpr_no*32 + 2],
mem[gpr_no*32 + 1], mem[gpr_no*32 + 0] };
get_gpr = mem[gpr_no];
endfunction // get_gpr
135,7 → 120,7
//
always @(posedge clk_a)
if (ce_a)
addr_a_reg <= #1 addr_a;
addr_a_reg <= addr_a;
//
// RAM write
142,6 → 127,6
//
always @(posedge clk_b)
if (ce_b & we_b)
mem[addr_b] <= #1 di_b;
mem[addr_b] <= di_b;
endmodule // or1200_dpram
/verilog/or1200_fpu_mul.v
0,0 → 1,170
//////////////////////////////////////////////////////////////////////
//// ////
//// or1200_fpu_mul ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Serial multiplication entity for the multiplication unit ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Original design (FPU100) - ////
//// Jidan Al-eryani, jidan@gmx.net ////
//// - Conv. to Verilog and inclusion in OR1200 - ////
//// Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2006, 2010
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
module or1200_fpu_mul
(
clk_i,
fracta_i,
fractb_i,
signa_i,
signb_i,
start_i,
fract_o,
sign_o,
ready_o
);
 
parameter FP_WIDTH = 32;
parameter MUL_SERIAL = 0; // 0 for parallel multiplier, 1 for serial
parameter MUL_COUNT = 11; //11 for parallel multiplier, 34 for serial
parameter FRAC_WIDTH = 23;
parameter EXP_WIDTH = 8;
parameter ZERO_VECTOR = 31'd0;
parameter INF = 31'b1111111100000000000000000000000;
parameter QNAN = 31'b1111111110000000000000000000000;
parameter SNAN = 31'b1111111100000000000000000000001;
input clk_i;
input [FRAC_WIDTH:0] fracta_i;
input [FRAC_WIDTH:0] fractb_i;
input signa_i;
input signb_i;
input start_i;
output reg [2*FRAC_WIDTH+1:0] fract_o;
output reg sign_o;
output reg ready_o;
parameter t_state_waiting = 1'b0,
t_state_busy = 1'b1;
 
reg [47:0] s_fract_o;
reg [23:0] s_fracta_i;
reg [23:0] s_fractb_i;
reg s_signa_i, s_signb_i;
wire s_sign_o;
reg s_start_i;
reg s_ready_o;
reg s_state;
reg [4:0] s_count;
wire [23:0] s_tem_prod;
 
// Input Register
always @(posedge clk_i)
begin
s_fracta_i <= fracta_i;
s_fractb_i <= fractb_i;
s_signa_i<= signa_i;
s_signb_i<= signb_i;
s_start_i <= start_i;
end
// Output Register
always @(posedge clk_i)
begin
fract_o <= s_fract_o;
sign_o <= s_sign_o;
ready_o <= s_ready_o;
end
 
assign s_sign_o = signa_i ^ signb_i;
 
// FSM
always @(posedge clk_i)
if (s_start_i)
begin
s_state <= t_state_busy;
s_count <= 0;
end
else if (s_count==23)
begin
s_state <= t_state_waiting;
s_ready_o <= 1;
s_count <=0;
end
else if (s_state==t_state_busy)
s_count <= s_count + 1;
else
begin
s_state <= t_state_waiting;
s_ready_o <= 0;
end
assign s_tem_prod[0] = s_fracta_i[0] & s_fractb_i[s_count];
assign s_tem_prod[1] = s_fracta_i[1] & s_fractb_i[s_count];
assign s_tem_prod[2] = s_fracta_i[2] & s_fractb_i[s_count];
assign s_tem_prod[3] = s_fracta_i[3] & s_fractb_i[s_count];
assign s_tem_prod[4] = s_fracta_i[4] & s_fractb_i[s_count];
assign s_tem_prod[5] = s_fracta_i[5] & s_fractb_i[s_count];
assign s_tem_prod[6] = s_fracta_i[6] & s_fractb_i[s_count];
assign s_tem_prod[7] = s_fracta_i[7] & s_fractb_i[s_count];
assign s_tem_prod[8] = s_fracta_i[8] & s_fractb_i[s_count];
assign s_tem_prod[9] = s_fracta_i[9] & s_fractb_i[s_count];
assign s_tem_prod[10] = s_fracta_i[10] & s_fractb_i[s_count];
assign s_tem_prod[11] = s_fracta_i[11] & s_fractb_i[s_count];
assign s_tem_prod[12] = s_fracta_i[12] & s_fractb_i[s_count];
assign s_tem_prod[13] = s_fracta_i[13] & s_fractb_i[s_count];
assign s_tem_prod[14] = s_fracta_i[14] & s_fractb_i[s_count];
assign s_tem_prod[15] = s_fracta_i[15] & s_fractb_i[s_count];
assign s_tem_prod[16] = s_fracta_i[16] & s_fractb_i[s_count];
assign s_tem_prod[17] = s_fracta_i[17] & s_fractb_i[s_count];
assign s_tem_prod[18] = s_fracta_i[18] & s_fractb_i[s_count];
assign s_tem_prod[19] = s_fracta_i[19] & s_fractb_i[s_count];
assign s_tem_prod[20] = s_fracta_i[20] & s_fractb_i[s_count];
assign s_tem_prod[21] = s_fracta_i[21] & s_fractb_i[s_count];
assign s_tem_prod[22] = s_fracta_i[22] & s_fractb_i[s_count];
assign s_tem_prod[23] = s_fracta_i[23] & s_fractb_i[s_count];
wire [47:0] v_prod_shl;
assign v_prod_shl = {24'd0,s_tem_prod} << s_count[4:0];
 
always @(posedge clk_i)
if (s_state==t_state_busy)
begin
if (|s_count)
s_fract_o <= v_prod_shl + s_fract_o;
else
s_fract_o <= v_prod_shl;
end
 
endmodule // or1200_fpu_mul
 

powered by: WebSVN 2.1.0

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