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