URL
https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk
Subversion Repositories openrisc_2011-10-31
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/or1200/rtl
- from Rev 401 to Rev 481
- ↔ Reverse comparison
Rev 401 → Rev 481
/verilog/or1200_defines.v
163,8 → 163,12
//`define OR1200_IC_1W_512B |
//`define OR1200_IC_1W_4KB |
`define OR1200_IC_1W_8KB |
//`define OR1200_IC_1W_16KB |
//`define OR1200_IC_1W_32KB |
//`define OR1200_DC_1W_4KB |
`define OR1200_DC_1W_8KB |
//`define OR1200_DC_1W_16KB |
//`define OR1200_DC_1W_32KB |
|
`endif |
|
360,39 → 364,38
// Implement multiply-and-accumulate |
// |
// By default MAC is implemented. To |
// implement MAC, multiplier needs to be |
// implement MAC, multiplier (non-serial) 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 save area. |
// |
// To implement divide, both multiplier and MAC needs to be implemented. |
// |
`define OR1200_DIV_IMPLEMENTED |
|
// |
// Low power, slower multiplier |
// Serial multiplier. |
// |
// Select between low-power (larger) multiplier |
// and faster multiplier. The actual difference |
// is only AND logic that prevents distribution |
// of operands into the multiplier when instruction |
// in execution is not multiply instruction |
//`define OR1200_MULT_SERIAL |
|
// |
//`define OR1200_LOWPWR_MULT |
// Serial divider. |
// Uncomment to use a serial divider, otherwise will |
// be a generic parallel implementation. |
// |
`define OR1200_DIV_SERIAL |
|
// |
// Implement HW Single Precision FPU |
// |
//`define OR1200_FPU_IMPLEMENTED |
// |
|
|
// |
// Clock ratio RISC clock versus WB clock |
// |
464,8 → 467,8
`define OR1200_ALUOP_SHROT 4'd8 |
`define OR1200_ALUOP_DIV 4'd9 |
`define OR1200_ALUOP_DIVU 4'd10 |
/* Order not specifically defined. */ |
`define OR1200_ALUOP_IMM 4'd11 |
`define OR1200_ALUOP_MULU 4'd11 |
/* Values sent to ALU from decode unit - not strictly defined by ISA */ |
`define OR1200_ALUOP_MOVHI 4'd12 |
`define OR1200_ALUOP_COMP 4'd13 |
`define OR1200_ALUOP_MTSR 4'd14 |
1025,7 → 1028,7
`define OR1200_PIC_IMPLEMENTED |
|
// Define number of interrupt inputs (2-31) |
`define OR1200_PIC_INTS 31 |
`define OR1200_PIC_INTS 20 |
|
// Address offsets of PIC registers inside PIC group |
`define OR1200_PIC_OFS_PICMR 2'd0 |
1220,19 → 1223,23
// Insn cache (IC) |
// |
|
// 3 for 8 bytes, 4 for 16 bytes etc |
`define OR1200_ICLS 4 |
// 4 for 16 byte line, 5 for 32 byte lines. |
`ifdef OR1200_IC_1W_32KB |
`define OR1200_ICLS 5 |
`else |
`define OR1200_ICLS 4 |
`endif |
|
// |
// IC configurations |
// |
`ifdef OR1200_IC_1W_512B |
`define OR1200_ICSIZE 9 // 512 |
`define OR1200_ICINDX `OR1200_ICSIZE-2 // 7 |
`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 8 |
`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 9 |
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 5 |
`define OR1200_ICTAG_W 24 |
`define OR1200_ICSIZE 9 // 512 |
`define OR1200_ICINDX `OR1200_ICSIZE-2 // 7 |
`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 8 |
`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 9 |
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 5 |
`define OR1200_ICTAG_W 24 |
`endif |
`ifdef OR1200_IC_1W_4KB |
`define OR1200_ICSIZE 12 // 4096 |
1250,6 → 1257,22
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 9 |
`define OR1200_ICTAG_W 20 |
`endif |
`ifdef OR1200_IC_1W_16KB |
`define OR1200_ICSIZE 14 // 16384 |
`define OR1200_ICINDX `OR1200_ICSIZE-2 // 12 |
`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 13 |
`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 14 |
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 10 |
`define OR1200_ICTAG_W 19 |
`endif |
`ifdef OR1200_IC_1W_32KB |
`define OR1200_ICSIZE 15 // 32768 |
`define OR1200_ICINDX `OR1200_ICSIZE-2 // 13 |
`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 14 |
`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 14 |
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 10 |
`define OR1200_ICTAG_W 18 |
`endif |
|
|
///////////////////////////////////////////////// |
1257,8 → 1280,12
// Data cache (DC) |
// |
|
// 3 for 8 bytes, 4 for 16 bytes etc |
`define OR1200_DCLS 4 |
// 4 for 16 bytes, 5 for 32 bytes |
`ifdef OR1200_DC_1W_32KB |
`define OR1200_DCLS 5 |
`else |
`define OR1200_DCLS 4 |
`endif |
|
// Define to enable default behavior of cache as write through |
// Turning this off enabled write back statergy |
1298,6 → 1325,22
`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 9 |
`define OR1200_DCTAG_W 20 |
`endif |
`ifdef OR1200_DC_1W_16KB |
`define OR1200_DCSIZE 14 // 16384 |
`define OR1200_DCINDX `OR1200_DCSIZE-2 // 12 |
`define OR1200_DCINDXH `OR1200_DCSIZE-1 // 13 |
`define OR1200_DCTAGL `OR1200_DCINDXH+1 // 14 |
`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 10 |
`define OR1200_DCTAG_W 19 |
`endif |
`ifdef OR1200_DC_1W_32KB |
`define OR1200_DCSIZE 15 // 32768 |
`define OR1200_DCINDX `OR1200_DCSIZE-2 // 13 |
`define OR1200_DCINDXH `OR1200_DCSIZE-1 // 14 |
`define OR1200_DCTAGL `OR1200_DCINDXH+1 // 15 |
`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 10 |
`define OR1200_DCTAG_W 18 |
`endif |
|
|
///////////////////////////////////////////////// |
1721,10 → 1764,18
|
/////////////////////////////////////////////////////////////////////////////// |
// Boot Address Selection // |
// This only changes where the initial reset occurs. EPH setting is still // |
// used to determine where vectors are located. // |
// // |
// Allows a definable boot address, potentially different to the usual reset // |
// vector to allow for power-on code to be run, if desired. // |
// // |
// OR1200_BOOT_ADR should be the 32-bit address of the boot location // |
// OR1200_BOOT_PCREG_DEFAULT should be ((OR1200_BOOT_ADR-4)>>2) // |
// // |
// For default reset behavior uncomment the settings under the "Boot 0x100" // |
// comment below. // |
// // |
/////////////////////////////////////////////////////////////////////////////// |
// Boot from 0xf0000100 |
// Boot from 0xf0000100 |
//`define OR1200_BOOT_PCREG_DEFAULT 30'h3c00003f |
//`define OR1200_BOOT_ADR 32'hf0000100 |
// Boot from 0x100 |
/verilog/or1200_alu.v
195,9 → 195,6
`OR1200_ALUOP_OR : begin |
result = a | b; |
end |
`OR1200_ALUOP_IMM : begin |
result = b; |
end |
`OR1200_ALUOP_MOVHI : begin |
if (macrc_op) begin |
result = mult_mac_result; |
211,7 → 208,8
`OR1200_ALUOP_DIV, |
`OR1200_ALUOP_DIVU, |
`endif |
`OR1200_ALUOP_MUL : begin |
`OR1200_ALUOP_MUL, |
`OR1200_ALUOP_MULU : begin |
result = mult_mac_result; |
end |
`endif |
/verilog/or1200_tt.v
41,49 → 41,6
//// //// |
////////////////////////////////////////////////////////////////////// |
// |
// CVS Revision History |
// |
// $Log: or1200_tt.v,v $ |
// Revision 2.0 2010/06/30 11:00:00 ORSoC |
// No update |
// |
// Revision 1.5 2004/06/08 18:17:36 lampret |
// Non-functional changes. Coding style fixes. |
// |
// Revision 1.4 2002/03/29 15:16:56 lampret |
// Some of the warnings fixed. |
// |
// Revision 1.3 2002/02/12 01:33:47 lampret |
// No longer using async rst as sync reset for the counter. |
// |
// 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/13 10:00:49 lampret |
// Fixed tick timer interrupt reporting by using TTCR[IP] bit. |
// |
// Revision 1.9 2001/11/10 03:43:57 lampret |
// Fixed exceptions. |
// |
// 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: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:23 lampret |
// Development version of RTL. Libraries are missing. |
// |
// |
|
// synopsys translate_off |
`include "timescale.v" |
/verilog/or1200_sprs.v
52,311 → 52,369
`include "or1200_defines.v" |
|
module or1200_sprs( |
// Clk & Rst |
clk, rst, |
// Clk & Rst |
clk, rst, |
|
// Internal CPU interface |
flagforw, flag_we, flag, cyforw, cy_we, carry, |
addrbase, addrofs, dat_i, branch_op, ex_spr_read, ex_spr_write, |
epcr, eear, esr, except_started, |
to_wbmux, epcr_we, eear_we, esr_we, pc_we, sr_we, to_sr, sr, |
spr_dat_cfgr, spr_dat_rf, spr_dat_npc, spr_dat_ppc, spr_dat_mac, |
boot_adr_sel_i, |
|
// Floating point SPR input |
fpcsr, fpcsr_we, spr_dat_fpu, |
// Internal CPU interface |
flagforw, flag_we, flag, cyforw, cy_we, carry, |
addrbase, addrofs, dat_i, branch_op, ex_spr_read, |
ex_spr_write, |
epcr, eear, esr, except_started, |
to_wbmux, epcr_we, eear_we, esr_we, pc_we, sr_we, to_sr, sr, |
spr_dat_cfgr, spr_dat_rf, spr_dat_npc, spr_dat_ppc, |
spr_dat_mac, |
|
boot_adr_sel_i, |
|
// From/to other RISC units |
spr_dat_pic, spr_dat_tt, spr_dat_pm, |
spr_dat_dmmu, spr_dat_immu, spr_dat_du, |
spr_addr, spr_dat_o, spr_cs, spr_we, |
// Floating point SPR input |
fpcsr, fpcsr_we, spr_dat_fpu, |
|
du_addr, du_dat_du, du_read, |
du_write, du_dat_cpu |
// From/to other RISC units |
spr_dat_pic, spr_dat_tt, spr_dat_pm, |
spr_dat_dmmu, spr_dat_immu, spr_dat_du, |
spr_addr, spr_dat_o, spr_cs, spr_we, |
|
); |
du_addr, du_dat_du, du_read, |
du_write, du_dat_cpu |
|
parameter width = `OR1200_OPERAND_WIDTH; |
); |
|
// |
// I/O Ports |
// |
parameter width = `OR1200_OPERAND_WIDTH; |
|
// |
// Internal CPU interface |
// |
input clk; // Clock |
input rst; // Reset |
input flagforw; // From ALU |
input flag_we; // From ALU |
output flag; // SR[F] |
input cyforw; // From ALU |
input cy_we; // From ALU |
output carry; // SR[CY] |
input [width-1:0] addrbase; // SPR base address |
input [15:0] addrofs; // SPR offset |
input [width-1:0] dat_i; // SPR write data |
input ex_spr_read; // l.mfspr in EX |
input ex_spr_write; // l.mtspr in EX |
input [`OR1200_BRANCHOP_WIDTH-1:0] branch_op; // Branch operation |
input [width-1:0] epcr /* verilator public */; // EPCR0 |
input [width-1:0] eear /* verilator public */; // EEAR0 |
input [`OR1200_SR_WIDTH-1:0] esr /* verilator public */; // ESR0 |
input except_started; // Exception was started |
output [width-1:0] to_wbmux; // For l.mfspr |
output epcr_we; // EPCR0 write enable |
output eear_we; // EEAR0 write enable |
output esr_we; // ESR0 write enable |
output pc_we; // PC write enable |
output sr_we; // Write enable SR |
output [`OR1200_SR_WIDTH-1:0] to_sr; // Data to SR |
output [`OR1200_SR_WIDTH-1:0] sr /* verilator public */; // SR |
input [31:0] spr_dat_cfgr; // Data from CFGR |
input [31:0] spr_dat_rf; // Data from RF |
input [31:0] spr_dat_npc; // Data from NPC |
input [31:0] spr_dat_ppc; // Data from PPC |
input [31:0] spr_dat_mac; // Data from MAC |
input boot_adr_sel_i; |
// |
// I/O Ports |
// |
|
input [`OR1200_FPCSR_WIDTH-1:0] fpcsr; // FPCSR |
output fpcsr_we; // Write enable FPCSR |
input [31:0] spr_dat_fpu; // Data from FPU |
// |
// Internal CPU interface |
// |
input clk; // Clock |
input rst; // Reset |
input flagforw; // From ALU |
input flag_we; // From ALU |
output flag; // SR[F] |
input cyforw; // From ALU |
input cy_we; // From ALU |
output carry; // SR[CY] |
input [width-1:0] addrbase; // SPR base address |
input [15:0] addrofs; // SPR offset |
input [width-1:0] dat_i; // SPR write data |
input ex_spr_read; // l.mfspr in EX |
input ex_spr_write; // l.mtspr in EX |
input [`OR1200_BRANCHOP_WIDTH-1:0] branch_op; // Branch operation |
input [width-1:0] epcr /* verilator public */;// EPCR0 |
input [width-1:0] eear /* verilator public */;// EEAR0 |
input [`OR1200_SR_WIDTH-1:0] esr /* verilator public */; // ESR0 |
input except_started; // Exception was started |
output [width-1:0] to_wbmux; // For l.mfspr |
output epcr_we; // EPCR0 write enable |
output eear_we; // EEAR0 write enable |
output esr_we; // ESR0 write enable |
output pc_we; // PC write enable |
output sr_we; // Write enable SR |
output [`OR1200_SR_WIDTH-1:0] to_sr; // Data to SR |
output [`OR1200_SR_WIDTH-1:0] sr /* verilator public */;// SR |
input [31:0] spr_dat_cfgr; // Data from CFGR |
input [31:0] spr_dat_rf; // Data from RF |
input [31:0] spr_dat_npc; // Data from NPC |
input [31:0] spr_dat_ppc; // Data from PPC |
input [31:0] spr_dat_mac; // Data from MAC |
input boot_adr_sel_i; |
|
input [`OR1200_FPCSR_WIDTH-1:0] fpcsr; // FPCSR |
output fpcsr_we; // Write enable FPCSR |
input [31:0] spr_dat_fpu; // Data from FPU |
|
// |
// To/from other RISC units |
// |
input [31:0] spr_dat_pic; // Data from PIC |
input [31:0] spr_dat_tt; // Data from TT |
input [31:0] spr_dat_pm; // Data from PM |
input [31:0] spr_dat_dmmu; // Data from DMMU |
input [31:0] spr_dat_immu; // Data from IMMU |
input [31:0] spr_dat_du; // Data from DU |
output [31:0] spr_addr; // SPR Address |
output [31:0] spr_dat_o; // Data to unit |
output [31:0] spr_cs; // Unit select |
output spr_we; // SPR write enable |
// |
// To/from other RISC units |
// |
input [31:0] spr_dat_pic; // Data from PIC |
input [31:0] spr_dat_tt; // Data from TT |
input [31:0] spr_dat_pm; // Data from PM |
input [31:0] spr_dat_dmmu; // Data from DMMU |
input [31:0] spr_dat_immu; // Data from IMMU |
input [31:0] spr_dat_du; // Data from DU |
output [31:0] spr_addr; // SPR Address |
output [31:0] spr_dat_o; // Data to unit |
output [31:0] spr_cs; // Unit select |
output spr_we; // SPR write enable |
|
// |
// To/from Debug Unit |
// |
input [width-1:0] du_addr; // Address |
input [width-1:0] du_dat_du; // Data from DU to SPRS |
input du_read; // Read qualifier |
input du_write; // Write qualifier |
output [width-1:0] du_dat_cpu; // Data from SPRS to DU |
// |
// To/from Debug Unit |
// |
input [width-1:0] du_addr; // Address |
input [width-1:0] du_dat_du; // Data from DU to SPRS |
input du_read; // Read qualifier |
input du_write; // Write qualifier |
output [width-1:0] du_dat_cpu; // Data from SPRS to DU |
|
// |
// Internal regs & wires |
// |
reg [`OR1200_SR_WIDTH-1:0] sr_reg; // SR |
reg sr_reg_bit_eph; // SR_EPH bit |
reg sr_reg_bit_eph_select; // SR_EPH select |
wire sr_reg_bit_eph_muxed; // SR_EPH muxed bit |
reg [`OR1200_SR_WIDTH-1:0] sr; // SR |
reg [width-1:0] to_wbmux; // For l.mfspr |
wire cfgr_sel; // Select for cfg regs |
wire rf_sel; // Select for RF |
wire npc_sel; // Select for NPC |
wire ppc_sel; // Select for PPC |
wire sr_sel; // Select for SR |
wire epcr_sel; // Select for EPCR0 |
wire eear_sel; // Select for EEAR0 |
wire esr_sel; // Select for ESR0 |
wire fpcsr_sel; // Select for FPCSR |
wire [31:0] sys_data; // Read data from system SPRs |
wire du_access; // Debug unit access |
reg [31:0] unqualified_cs; // Unqualified chip selects |
wire ex_spr_write; // jb |
// |
// Internal regs & wires |
// |
reg [`OR1200_SR_WIDTH-1:0] sr_reg; // SR |
reg sr_reg_bit_eph; // SR_EPH bit |
reg sr_reg_bit_eph_select;// SR_EPH select |
wire sr_reg_bit_eph_muxed;// SR_EPH muxed bit |
reg [`OR1200_SR_WIDTH-1:0] sr; // SR |
reg [width-1:0] to_wbmux; // For l.mfspr |
wire cfgr_sel; // Select for cfg regs |
wire rf_sel; // Select for RF |
wire npc_sel; // Select for NPC |
wire ppc_sel; // Select for PPC |
wire sr_sel; // Select for SR |
wire epcr_sel; // Select for EPCR0 |
wire eear_sel; // Select for EEAR0 |
wire esr_sel; // Select for ESR0 |
wire fpcsr_sel; // Select for FPCSR |
wire [31:0] sys_data;// Read data from system SPRs |
wire du_access;// Debug unit access |
reg [31:0] unqualified_cs; // Unqualified selects |
wire ex_spr_write; // jb |
|
// |
// Decide if it is debug unit access |
// |
assign du_access = du_read | du_write; |
// |
// Decide if it is debug unit access |
// |
assign du_access = du_read | du_write; |
|
// |
// Generate SPR address from base address and offset |
// OR from debug unit address |
// |
assign spr_addr = du_access ? du_addr : (addrbase | {16'h0000, addrofs}); |
// |
// Generate SPR address from base address and offset |
// OR from debug unit address |
// |
assign spr_addr = du_access ? du_addr : (addrbase | {16'h0000, addrofs}); |
|
// |
// SPR is written by debug unit or by l.mtspr |
// |
assign spr_dat_o = du_write ? du_dat_du : dat_i; |
// |
// SPR is written by debug unit or by l.mtspr |
// |
assign spr_dat_o = du_write ? du_dat_du : dat_i; |
|
// |
// debug unit data input: |
// - read of SPRS by debug unit |
// - write into debug unit SPRs by debug unit itself |
// - write into debug unit SPRs by l.mtspr |
// |
assign du_dat_cpu = du_read ? to_wbmux : du_write ? du_dat_du : dat_i; |
// |
// debug unit data input: |
// - read of SPRS by debug unit |
// - write into debug unit SPRs by debug unit itself |
// - write into debug unit SPRs by l.mtspr |
// |
assign du_dat_cpu = du_read ? to_wbmux : du_write ? du_dat_du : dat_i; |
|
// |
// Write into SPRs when DU or l.mtspr |
// |
assign spr_we = du_write | ( ex_spr_write & !du_access ); |
// |
// Write into SPRs when DU or l.mtspr |
// |
assign spr_we = du_write | ( ex_spr_write & !du_access ); |
|
|
// |
// Qualify chip selects |
// |
assign spr_cs = unqualified_cs & {32{du_read | du_write | ex_spr_read | (ex_spr_write & sr[`OR1200_SR_SM])}}; |
// |
// Qualify chip selects |
// |
assign spr_cs = unqualified_cs & {32{du_read | du_write | ex_spr_read | |
(ex_spr_write & sr[`OR1200_SR_SM])}}; |
|
// |
// Decoding of groups |
// |
always @(spr_addr) |
case (spr_addr[`OR1200_SPR_GROUP_BITS]) // synopsys parallel_case |
`OR1200_SPR_GROUP_WIDTH'd00: unqualified_cs = 32'b00000000_00000000_00000000_00000001; |
`OR1200_SPR_GROUP_WIDTH'd01: unqualified_cs = 32'b00000000_00000000_00000000_00000010; |
`OR1200_SPR_GROUP_WIDTH'd02: unqualified_cs = 32'b00000000_00000000_00000000_00000100; |
`OR1200_SPR_GROUP_WIDTH'd03: unqualified_cs = 32'b00000000_00000000_00000000_00001000; |
`OR1200_SPR_GROUP_WIDTH'd04: unqualified_cs = 32'b00000000_00000000_00000000_00010000; |
`OR1200_SPR_GROUP_WIDTH'd05: unqualified_cs = 32'b00000000_00000000_00000000_00100000; |
`OR1200_SPR_GROUP_WIDTH'd06: unqualified_cs = 32'b00000000_00000000_00000000_01000000; |
`OR1200_SPR_GROUP_WIDTH'd07: unqualified_cs = 32'b00000000_00000000_00000000_10000000; |
`OR1200_SPR_GROUP_WIDTH'd08: unqualified_cs = 32'b00000000_00000000_00000001_00000000; |
`OR1200_SPR_GROUP_WIDTH'd09: unqualified_cs = 32'b00000000_00000000_00000010_00000000; |
`OR1200_SPR_GROUP_WIDTH'd10: unqualified_cs = 32'b00000000_00000000_00000100_00000000; |
`OR1200_SPR_GROUP_WIDTH'd11: unqualified_cs = 32'b00000000_00000000_00001000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd12: unqualified_cs = 32'b00000000_00000000_00010000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd13: unqualified_cs = 32'b00000000_00000000_00100000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd14: unqualified_cs = 32'b00000000_00000000_01000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd15: unqualified_cs = 32'b00000000_00000000_10000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd16: unqualified_cs = 32'b00000000_00000001_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd17: unqualified_cs = 32'b00000000_00000010_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd18: unqualified_cs = 32'b00000000_00000100_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd19: unqualified_cs = 32'b00000000_00001000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd20: unqualified_cs = 32'b00000000_00010000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd21: unqualified_cs = 32'b00000000_00100000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd22: unqualified_cs = 32'b00000000_01000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd23: unqualified_cs = 32'b00000000_10000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd24: unqualified_cs = 32'b00000001_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd25: unqualified_cs = 32'b00000010_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd26: unqualified_cs = 32'b00000100_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd27: unqualified_cs = 32'b00001000_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd28: unqualified_cs = 32'b00010000_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd29: unqualified_cs = 32'b00100000_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd30: unqualified_cs = 32'b01000000_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd31: unqualified_cs = 32'b10000000_00000000_00000000_00000000; |
endcase |
// |
// Decoding of groups |
// |
always @(spr_addr) |
case (spr_addr[`OR1200_SPR_GROUP_BITS]) // synopsys parallel_case |
`OR1200_SPR_GROUP_WIDTH'd00: unqualified_cs |
= 32'b00000000_00000000_00000000_00000001; |
`OR1200_SPR_GROUP_WIDTH'd01: unqualified_cs |
= 32'b00000000_00000000_00000000_00000010; |
`OR1200_SPR_GROUP_WIDTH'd02: unqualified_cs |
= 32'b00000000_00000000_00000000_00000100; |
`OR1200_SPR_GROUP_WIDTH'd03: unqualified_cs |
= 32'b00000000_00000000_00000000_00001000; |
`OR1200_SPR_GROUP_WIDTH'd04: unqualified_cs |
= 32'b00000000_00000000_00000000_00010000; |
`OR1200_SPR_GROUP_WIDTH'd05: unqualified_cs |
= 32'b00000000_00000000_00000000_00100000; |
`OR1200_SPR_GROUP_WIDTH'd06: unqualified_cs |
= 32'b00000000_00000000_00000000_01000000; |
`OR1200_SPR_GROUP_WIDTH'd07: unqualified_cs |
= 32'b00000000_00000000_00000000_10000000; |
`OR1200_SPR_GROUP_WIDTH'd08: unqualified_cs |
= 32'b00000000_00000000_00000001_00000000; |
`OR1200_SPR_GROUP_WIDTH'd09: unqualified_cs |
= 32'b00000000_00000000_00000010_00000000; |
`OR1200_SPR_GROUP_WIDTH'd10: unqualified_cs |
= 32'b00000000_00000000_00000100_00000000; |
`OR1200_SPR_GROUP_WIDTH'd11: unqualified_cs |
= 32'b00000000_00000000_00001000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd12: unqualified_cs |
= 32'b00000000_00000000_00010000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd13: unqualified_cs |
= 32'b00000000_00000000_00100000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd14: unqualified_cs |
= 32'b00000000_00000000_01000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd15: unqualified_cs |
= 32'b00000000_00000000_10000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd16: unqualified_cs |
= 32'b00000000_00000001_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd17: unqualified_cs |
= 32'b00000000_00000010_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd18: unqualified_cs |
= 32'b00000000_00000100_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd19: unqualified_cs |
= 32'b00000000_00001000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd20: unqualified_cs |
= 32'b00000000_00010000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd21: unqualified_cs |
= 32'b00000000_00100000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd22: unqualified_cs |
= 32'b00000000_01000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd23: unqualified_cs |
= 32'b00000000_10000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd24: unqualified_cs |
= 32'b00000001_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd25: unqualified_cs |
= 32'b00000010_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd26: unqualified_cs |
= 32'b00000100_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd27: unqualified_cs |
= 32'b00001000_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd28: unqualified_cs |
= 32'b00010000_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd29: unqualified_cs |
= 32'b00100000_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd30: unqualified_cs |
= 32'b01000000_00000000_00000000_00000000; |
`OR1200_SPR_GROUP_WIDTH'd31: unqualified_cs |
= 32'b10000000_00000000_00000000_00000000; |
endcase |
|
// |
// SPRs System Group |
// |
// |
// SPRs System Group |
// |
|
// |
// What to write into SR |
// |
assign to_sr[`OR1200_SR_FO:`OR1200_SR_OV] = |
(except_started) ? sr[`OR1200_SR_FO:`OR1200_SR_OV] : |
(branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_FO:`OR1200_SR_OV] : |
(spr_we && sr_sel) ? {1'b1, spr_dat_o[`OR1200_SR_FO-1:`OR1200_SR_OV]}: |
sr[`OR1200_SR_FO:`OR1200_SR_OV]; |
assign to_sr[`OR1200_SR_TED] = |
(except_started) ? 1'b1 : |
(branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_TED] : |
(spr_we && sr_sel) ? spr_dat_o[`OR1200_SR_TED]: |
sr[`OR1200_SR_TED]; |
assign to_sr[`OR1200_SR_CY] = |
(except_started) ? sr[`OR1200_SR_CY] : |
(branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_CY] : |
cy_we ? cyforw : |
(spr_we && sr_sel) ? spr_dat_o[`OR1200_SR_CY] : |
sr[`OR1200_SR_CY]; |
assign to_sr[`OR1200_SR_F] = |
(except_started) ? sr[`OR1200_SR_F] : |
(branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_F] : |
flag_we ? flagforw : |
(spr_we && sr_sel) ? spr_dat_o[`OR1200_SR_F] : |
sr[`OR1200_SR_F]; |
assign to_sr[`OR1200_SR_CE:`OR1200_SR_SM] = |
(except_started) ? {sr[`OR1200_SR_CE:`OR1200_SR_LEE], 2'b00, sr[`OR1200_SR_ICE:`OR1200_SR_DCE], 3'b001} : |
(branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_CE:`OR1200_SR_SM] : |
(spr_we && sr_sel) ? spr_dat_o[`OR1200_SR_CE:`OR1200_SR_SM]: |
sr[`OR1200_SR_CE:`OR1200_SR_SM]; |
// |
// What to write into SR |
// |
assign to_sr[`OR1200_SR_FO:`OR1200_SR_OV] |
= (except_started) ? sr[`OR1200_SR_FO:`OR1200_SR_OV] : |
(branch_op == `OR1200_BRANCHOP_RFE) ? |
esr[`OR1200_SR_FO:`OR1200_SR_OV] : (spr_we && sr_sel) ? |
{1'b1, spr_dat_o[`OR1200_SR_FO-1:`OR1200_SR_OV]} : |
sr[`OR1200_SR_FO:`OR1200_SR_OV]; |
assign to_sr[`OR1200_SR_TED] |
= (except_started) ? 1'b1 : |
(branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_TED] : |
(spr_we && sr_sel) ? spr_dat_o[`OR1200_SR_TED] : |
sr[`OR1200_SR_TED]; |
|
assign to_sr[`OR1200_SR_CY] |
= (except_started) ? sr[`OR1200_SR_CY] : |
(branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_CY] : |
cy_we ? cyforw : |
(spr_we && sr_sel) ? spr_dat_o[`OR1200_SR_CY] : |
sr[`OR1200_SR_CY]; |
assign to_sr[`OR1200_SR_F] |
= (except_started) ? sr[`OR1200_SR_F] : |
(branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_F] : |
flag_we ? flagforw : |
(spr_we && sr_sel) ? spr_dat_o[`OR1200_SR_F] : |
sr[`OR1200_SR_F]; |
|
assign to_sr[`OR1200_SR_CE:`OR1200_SR_SM] |
= (except_started) ? {sr[`OR1200_SR_CE:`OR1200_SR_LEE], 2'b00, |
sr[`OR1200_SR_ICE:`OR1200_SR_DCE], 3'b001} : |
(branch_op == `OR1200_BRANCHOP_RFE) ? |
esr[`OR1200_SR_CE:`OR1200_SR_SM] : (spr_we && sr_sel) ? |
spr_dat_o[`OR1200_SR_CE:`OR1200_SR_SM] : |
sr[`OR1200_SR_CE:`OR1200_SR_SM]; |
|
// |
// Selects for system SPRs |
// |
assign cfgr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:4] == `OR1200_SPR_CFGR)); |
assign rf_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:5] == `OR1200_SPR_RF)); |
assign npc_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_NPC)); |
assign ppc_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_PPC)); |
assign sr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_SR)); |
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)); |
assign fpcsr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_FPCSR)); |
// |
// Selects for system SPRs |
// |
assign cfgr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && |
(spr_addr[10:4] == `OR1200_SPR_CFGR)); |
assign rf_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && |
(spr_addr[10:5] == `OR1200_SPR_RF)); |
assign npc_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && |
(spr_addr[10:0] == `OR1200_SPR_NPC)); |
assign ppc_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && |
(spr_addr[10:0] == `OR1200_SPR_PPC)); |
assign sr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && |
(spr_addr[10:0] == `OR1200_SPR_SR)); |
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)); |
assign fpcsr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && |
(spr_addr[10:0] == `OR1200_SPR_FPCSR)); |
|
|
// |
// Write enables for system SPRs |
// |
assign sr_we = (spr_we && sr_sel) | (branch_op == `OR1200_BRANCHOP_RFE) | flag_we | cy_we; |
assign pc_we = (du_write && (npc_sel | ppc_sel)); |
assign epcr_we = (spr_we && epcr_sel); |
assign eear_we = (spr_we && eear_sel); |
assign esr_we = (spr_we && esr_sel); |
assign fpcsr_we = (spr_we && fpcsr_sel); |
// |
// Write enables for system SPRs |
// |
assign sr_we = (spr_we && sr_sel) | (branch_op == `OR1200_BRANCHOP_RFE) | |
flag_we | cy_we; |
assign pc_we = (du_write && (npc_sel | ppc_sel)); |
assign epcr_we = (spr_we && epcr_sel); |
assign eear_we = (spr_we && eear_sel); |
assign esr_we = (spr_we && esr_sel); |
assign fpcsr_we = (spr_we && fpcsr_sel); |
|
// |
// Output from system SPRs |
// |
assign sys_data = (spr_dat_cfgr & {32{cfgr_sel}}) | |
(spr_dat_rf & {32{rf_sel}}) | |
(spr_dat_npc & {32{npc_sel}}) | |
(spr_dat_ppc & {32{ppc_sel}}) | |
({{32-`OR1200_SR_WIDTH{1'b0}},sr} & {32{sr_sel}}) | |
(epcr & {32{epcr_sel}}) | |
(eear & {32{eear_sel}}) | |
({{32-`OR1200_FPCSR_WIDTH{1'b0}},fpcsr} & {32{fpcsr_sel}}) | |
({{32-`OR1200_SR_WIDTH{1'b0}},esr} & {32{esr_sel}}); |
// |
// Output from system SPRs |
// |
assign sys_data = (spr_dat_cfgr & {32{cfgr_sel}}) | |
(spr_dat_rf & {32{rf_sel}}) | |
(spr_dat_npc & {32{npc_sel}}) | |
(spr_dat_ppc & {32{ppc_sel}}) | |
({{32-`OR1200_SR_WIDTH{1'b0}},sr} & {32{sr_sel}}) | |
(epcr & {32{epcr_sel}}) | |
(eear & {32{eear_sel}}) | |
({{32-`OR1200_FPCSR_WIDTH{1'b0}},fpcsr} & |
{32{fpcsr_sel}}) | |
({{32-`OR1200_SR_WIDTH{1'b0}},esr} & {32{esr_sel}}); |
|
// |
// Flag alias |
// |
assign flag = sr[`OR1200_SR_F]; |
// |
// Flag alias |
// |
assign flag = sr[`OR1200_SR_F]; |
|
// |
// Carry alias |
// |
assign carry = sr[`OR1200_SR_CY]; |
// |
// Carry alias |
// |
assign carry = sr[`OR1200_SR_CY]; |
|
// |
// Supervision register |
// |
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst == `OR1200_RST_VALUE) |
sr_reg <= {2'h1, `OR1200_SR_EPH_DEF, {`OR1200_SR_WIDTH-4{1'b0}}, 1'b1}; |
else if (except_started) |
sr_reg <= to_sr[`OR1200_SR_WIDTH-1:0]; |
else if (sr_we) |
sr_reg <= to_sr[`OR1200_SR_WIDTH-1:0]; |
// |
// Supervision register |
// |
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst == `OR1200_RST_VALUE) |
sr_reg <= {2'b01, // Fixed one. |
`OR1200_SR_EPH_DEF, {`OR1200_SR_WIDTH-4{1'b0}}, 1'b1}; |
else if (except_started) |
sr_reg <= to_sr[`OR1200_SR_WIDTH-1:0]; |
else if (sr_we) |
sr_reg <= to_sr[`OR1200_SR_WIDTH-1:0]; |
|
// EPH part of Supervision register |
always @(posedge clk or `OR1200_RST_EVENT rst) |
// default value |
if (rst == `OR1200_RST_VALUE) begin |
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 <= 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 <= to_sr[`OR1200_SR_EPH]; |
end |
// EPH part of Supervision register |
always @(posedge clk or `OR1200_RST_EVENT rst) |
// default value |
if (rst == `OR1200_RST_VALUE) begin |
sr_reg_bit_eph <= `OR1200_SR_EPH_DEF; |
// select async. value due to reset state |
sr_reg_bit_eph_select <= 1'b1; |
end |
// selected value (different from default) is written into FF after reset |
// state |
else if (sr_reg_bit_eph_select) begin |
// dynamic value can only be assigned to FF out of reset! |
sr_reg_bit_eph <= boot_adr_sel_i; |
sr_reg_bit_eph_select <= 1'b0; // select FF value |
end |
else if (sr_we) begin |
sr_reg_bit_eph <= to_sr[`OR1200_SR_EPH]; |
end |
|
// select async. value of EPH bit after reset |
assign sr_reg_bit_eph_muxed = (sr_reg_bit_eph_select) ? boot_adr_sel_i : sr_reg_bit_eph; |
// select async. value of EPH bit after reset |
assign sr_reg_bit_eph_muxed = (sr_reg_bit_eph_select) ? |
boot_adr_sel_i : sr_reg_bit_eph; |
|
// EPH part joined together with rest of Supervision register |
always @(sr_reg or sr_reg_bit_eph_muxed) |
sr = {sr_reg[`OR1200_SR_WIDTH-1:`OR1200_SR_WIDTH-2], sr_reg_bit_eph_muxed, sr_reg[`OR1200_SR_WIDTH-4:0]}; |
// EPH part joined together with rest of Supervision register |
always @(sr_reg or sr_reg_bit_eph_muxed) |
sr = {sr_reg[`OR1200_SR_WIDTH-1:`OR1200_SR_WIDTH-2], sr_reg_bit_eph_muxed, |
sr_reg[`OR1200_SR_WIDTH-4:0]}; |
|
`ifdef verilator |
// Function to access various sprs (for Verilator). Have to hide this from |
384,34 → 442,33
endfunction // get_esr |
|
`endif |
|
|
// |
// MTSPR/MFSPR interface |
// |
always @(spr_addr or sys_data or spr_dat_mac or spr_dat_pic or spr_dat_pm or |
spr_dat_fpu or |
spr_dat_dmmu or spr_dat_immu or spr_dat_du or spr_dat_tt) begin |
casez (spr_addr[`OR1200_SPR_GROUP_BITS]) // synopsys parallel_case |
`OR1200_SPR_GROUP_SYS: |
to_wbmux = sys_data; |
`OR1200_SPR_GROUP_TT: |
to_wbmux = spr_dat_tt; |
`OR1200_SPR_GROUP_PIC: |
to_wbmux = spr_dat_pic; |
`OR1200_SPR_GROUP_PM: |
to_wbmux = spr_dat_pm; |
`OR1200_SPR_GROUP_DMMU: |
to_wbmux = spr_dat_dmmu; |
`OR1200_SPR_GROUP_IMMU: |
to_wbmux = spr_dat_immu; |
`OR1200_SPR_GROUP_MAC: |
to_wbmux = spr_dat_mac; |
`OR1200_SPR_GROUP_FPU: |
to_wbmux = spr_dat_fpu; |
default: //`OR1200_SPR_GROUP_DU: |
to_wbmux = spr_dat_du; |
endcase |
end |
// |
// MTSPR/MFSPR interface |
// |
always @(spr_addr or sys_data or spr_dat_mac or spr_dat_pic or spr_dat_pm or |
spr_dat_fpu or |
spr_dat_dmmu or spr_dat_immu or spr_dat_du or spr_dat_tt) begin |
casez (spr_addr[`OR1200_SPR_GROUP_BITS]) // synopsys parallel_case |
`OR1200_SPR_GROUP_SYS: |
to_wbmux = sys_data; |
`OR1200_SPR_GROUP_TT: |
to_wbmux = spr_dat_tt; |
`OR1200_SPR_GROUP_PIC: |
to_wbmux = spr_dat_pic; |
`OR1200_SPR_GROUP_PM: |
to_wbmux = spr_dat_pm; |
`OR1200_SPR_GROUP_DMMU: |
to_wbmux = spr_dat_dmmu; |
`OR1200_SPR_GROUP_IMMU: |
to_wbmux = spr_dat_immu; |
`OR1200_SPR_GROUP_MAC: |
to_wbmux = spr_dat_mac; |
`OR1200_SPR_GROUP_FPU: |
to_wbmux = spr_dat_fpu; |
default: //`OR1200_SPR_GROUP_DU: |
to_wbmux = spr_dat_du; |
endcase |
end |
|
endmodule |
/verilog/or1200_cpu.v
312,7 → 312,7
wire [`OR1200_MACOP_WIDTH-1:0] id_mac_op; |
wire [`OR1200_MACOP_WIDTH-1:0] mac_op; |
wire [31:0] mult_mac_result; |
wire mac_stall; |
wire mult_mac_stall; |
wire [13:0] except_trig; |
wire [13:0] except_stop; |
wire genpc_refetch; |
644,7 → 644,7
.mac_op(mac_op), |
.alu_op(alu_op), |
.result(mult_mac_result), |
.mac_stall_r(mac_stall), |
.mult_mac_stall(mult_mac_stall), |
.spr_cs(spr_cs[`OR1200_SPR_GROUP_MAC]), |
.spr_write(spr_we), |
.spr_addr(spr_addr), |
785,7 → 785,7
.force_dslot_fetch(force_dslot_fetch), |
.abort_ex(abort_ex), |
.du_stall(du_stall), |
.mac_stall(mac_stall), |
.mac_stall(mult_mac_stall), |
.saving_if_insn(saving_if_insn), |
.genpc_freeze(genpc_freeze), |
.if_freeze(if_freeze), |
/verilog/or1200_immu_top.v
3,7 → 3,7
//// OR1200's Instruction 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 IMMU blocks. //// |
40,81 → 40,6
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
// |
// CVS Revision History |
// |
// $Log: or1200_immu_top.v,v $ |
// Revision 2.0 2010/06/30 11:00:00 ORSoC |
// Major update: |
// Structure reordered and bugs fixed. |
// |
// Revision 1.15 2004/06/08 18:17:36 lampret |
// Non-functional changes. Coding style fixes. |
// |
// Revision 1.14 2004/04/05 08:29:57 lampret |
// Merged branch_qmem into main tree. |
// |
// Revision 1.12.4.2 2003/12/09 11:46:48 simons |
// Mbist nameing changed, Artisan ram instance signal names fixed, some synthesis waning fixed. |
// |
// Revision 1.12.4.1 2003/07/08 15:36:37 lampret |
// Added embedded memory QMEM. |
// |
// Revision 1.12 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.11 2002/10/17 20:04:40 lampret |
// Added BIST scan. Special VS RAMs need to be used to implement BIST. |
// |
// Revision 1.10 2002/09/16 03:08:56 lampret |
// Disabled cache inhibit atttribute. |
// |
// Revision 1.9 2002/08/18 19:54:17 lampret |
// Added store buffer. |
// |
// Revision 1.8 2002/08/14 06:23:50 lampret |
// Disabled ITLB translation when 1) doing access to ITLB SPRs or 2) crossing page. This modification was tested only with parts of IMMU test - remaining test cases needs to be run. |
// |
// Revision 1.7 2002/08/12 05:31:30 lampret |
// Delayed external access at page crossing. |
// |
// 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: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.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" |
254,27 → 179,35
always @(`OR1200_RST_EVENT rst or posedge clk) |
// default value |
if (rst == `OR1200_RST_VALUE) begin |
// 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 |
icpu_adr_select <= 1'b1; |
end |
// selected value (different from default) is written into FF after reset state |
// selected value (different from default) is written |
// into FF after reset state |
else if (icpu_adr_select) begin |
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 |
// dynamic value can only be assigned to FF out of reset! |
icpu_adr_default <= icpu_adr_boot; |
// select FF value |
icpu_adr_select <= 1'b0; |
end |
else begin |
icpu_adr_default <= icpu_adr_i; |
end |
|
// select async. value for boot address after reset - PC jumps to the address selected after boot! |
//assign icpu_adr_boot = {(boot_adr_sel_i ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), 12'h100} ; |
// select async. value for boot address after reset - PC jumps to the address |
// selected after boot! |
//assign icpu_adr_boot = {(boot_adr_sel_i ? `OR1200_EXCEPT_EPH1_P : |
// `OR1200_EXCEPT_EPH0_P), 12'h100} ; |
assign icpu_adr_boot = `OR1200_BOOT_ADR; // jb |
|
always @(icpu_adr_boot or icpu_adr_default or icpu_adr_select) |
if (icpu_adr_select) |
icpu_adr_o = icpu_adr_boot ; // async. value is selected due to reset state |
// async. value is selected due to reset state |
icpu_adr_o = icpu_adr_boot ; |
else |
icpu_adr_o = icpu_adr_default ; // FF value is selected 2nd clock after reset state |
// FF value is selected 2nd clock after reset state |
icpu_adr_o = icpu_adr_default ; |
`else |
Unsupported !!! |
`endif |
/verilog/or1200_dc_fsm.v
125,7 → 125,7
// |
reg [31:0] addr_r; |
reg [2:0] state; |
reg [2:0] cnt; |
reg [`OR1200_DCLS-1:0] cnt; |
reg hitmiss_eval; |
reg store; |
reg load; |
150,7 → 150,7
wire tagram_dirty_bit_set; |
wire writethrough; |
wire cache_inhibit_with_eval; |
wire [1:0] next_addr_word; |
wire [(`OR1200_DCLS-1)-2:0] next_addr_word; |
|
// |
// Cache inhibit |
268,8 → 268,9
// 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; |
// 3-bit wire for calculating next word of burst write, depending on |
// line size of data cache. |
assign next_addr_word = addr_r[`OR1200_DCLS-1:2] + 1; |
|
// Address to cache RAM (tag address also derived from this) |
assign dc_addr = |
285,7 → 286,7
// 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; |
{addr_r[31:`OR1200_DCLS], next_addr_word, 2'b00} : addr_r; |
|
`ifdef OR1200_DC_WRITETHROUGH |
`ifdef OR1200_DC_NOSTACKWRITETHROUGH |
342,9 → 343,9
// 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 & |
(cnt==((1 << `OR1200_DCLS) - 4)) & biudata_valid & |
!(dcqmem_we_i & !writethrough)); |
|
|
assign load_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) & |
load & cache_inhibit & biudata_valid; |
|
362,11 → 363,11
always @(posedge clk or `OR1200_RST_EVENT rst) begin |
if (rst == `OR1200_RST_VALUE) begin |
state <= `OR1200_DCFSM_IDLE; |
addr_r <= 32'b0; |
addr_r <= 32'd0; |
hitmiss_eval <= 1'b0; |
store <= 1'b0; |
load <= 1'b0; |
cnt <= 3'd0; |
cnt <= `OR1200_DCLS'd0; |
cache_miss <= 1'b0; |
cache_dirty_needs_writeback <= 1'b0; |
cache_inhibit <= 1'b0; |
430,7 → 431,7
end // else: !if(dirty) |
state <= `OR1200_DCFSM_LOOP2; |
// Set the counter for the burst accesses |
cnt <= `OR1200_DCLS-1; |
cnt <= ((1 << `OR1200_DCLS) - 4); |
end |
else if (// Strobe goes low |
!dcqmem_cycstb_i | |
453,11 → 454,11
state <= `OR1200_DCFSM_IDLE; |
load <= 1'b0; |
store <= 1'b0; |
cnt <= 3'd0; |
cnt <= `OR1200_DCLS'd0; |
end |
if (biudata_valid & (|cnt)) begin |
cnt <= cnt - 3'd1; |
addr_r[3:2] <= addr_r[3:2] + 1'b1; |
cnt <= cnt - 4; |
addr_r[`OR1200_DCLS-1:2] <= addr_r[`OR1200_DCLS-1:2] + 1; |
end |
else if (biudata_valid & !(|cnt)) begin |
state <= `OR1200_DCFSM_LOOP3; |
478,7 → 479,7
// 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; |
cnt <= ((1 << `OR1200_DCLS) - 4); |
// Address of line to be loaded |
addr_r <= lsu_addr; |
cache_dirty_needs_writeback <= 1'b0; |
526,7 → 527,7
`endif |
state <= `OR1200_DCFSM_LOOP2; |
// Set the counter for the burst accesses |
cnt <= `OR1200_DCLS-1; |
cnt <= ((1 << `OR1200_DCLS) - 4); |
end |
else if (cache_spr_block_flush & !dirty) |
begin |
/verilog/or1200_ic_tag.v
48,43 → 48,6
// Minor update: |
// Coding style changed. |
// |
// Revision 1.7 2004/06/08 18:17:36 lampret |
// Non-functional changes. Coding style fixes. |
// |
// Revision 1.6 2004/04/08 11:00:46 simont |
// Add support for 512B instruction cache. |
// |
// Revision 1.5 2004/04/05 08:29:57 lampret |
// Merged branch_qmem into main tree. |
// |
// Revision 1.3.4.1 2003/12/09 11:46:48 simons |
// Mbist nameing changed, Artisan ram instance signal names fixed, some synthesis waning fixed. |
// |
// Revision 1.3 2002/10/24 22:19:04 mohor |
// Signal scanb_eni renamed to scanb_en |
// |
// 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" |
152,30 → 115,11
// |
// Instantiation of TAG RAM block |
// |
`ifdef OR1200_IC_1W_512B |
//or1200_spram_32x24 ic_tag0( |
or1200_spram # |
( |
.aw(5), |
.dw(24) |
.aw(`OR1200_ICTAG), |
.dw(`OR1200_ICTAG_W) |
) |
`endif |
`ifdef OR1200_IC_1W_4KB |
//or1200_spram_256x21 ic_tag0( |
or1200_spram # |
( |
.aw(8), |
.dw(21) |
) |
`endif |
`ifdef OR1200_IC_1W_8KB |
//or1200_spram_512x20 ic_tag0( |
or1200_spram # |
( |
.aw(9), |
.dw(20) |
) |
`endif |
ic_tag0 |
( |
`ifdef OR1200_BIST |
/verilog/or1200_ic_ram.v
48,43 → 48,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/08 11:00:46 simont |
// Add support for 512B instruction cache. |
// |
// 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.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:09 lampret |
// MP3 version. |
// |
// Revision 1.1.1.1 2001/10/06 10:18:36 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:03 lampret |
// Development version of RTL. Libraries are missing. |
// |
// |
|
// synopsys translate_off |
`include "timescale.v" |
142,27 → 105,11
// |
// Instantiation of IC RAM block |
// |
`ifdef OR1200_IC_1W_512B |
or1200_spram # |
( |
.aw(9), |
.aw(`OR1200_ICINDX), |
.dw(32) |
) |
`endif |
`ifdef OR1200_IC_1W_4KB |
or1200_spram # |
( |
.aw(10), |
.dw(32) |
) |
`endif |
`ifdef OR1200_IC_1W_8KB |
or1200_spram # |
( |
.aw(11), |
.dw(32) |
) |
`endif |
ic_ram0 |
( |
`ifdef OR1200_BIST |
/verilog/or1200_wb_biu.v
79,7 → 79,10
|
parameter dw = `OR1200_OPERAND_WIDTH; |
parameter aw = `OR1200_OPERAND_WIDTH; |
|
parameter bl = 4; /* Can currently be either 4 or 8 - the two optional line |
sizes for the OR1200. */ |
|
|
// |
// RISC clock, reset and clock control |
// |
153,7 → 156,7
assign retry_cnt = 1'b0; |
`endif |
`ifdef OR1200_WB_B3 |
reg [1:0] burst_len; // burst counter |
reg [3:0] burst_len; // burst counter |
`endif |
|
reg biu_stb_reg; // WB strobe |
197,14 → 200,14
// |
always @(posedge wb_clk_i or `OR1200_RST_EVENT wb_rst_i) begin |
if (wb_rst_i == `OR1200_RST_VALUE) begin |
burst_len <= 2'h0; |
burst_len <= 0; |
end |
else begin |
// burst counter |
if (wb_fsm_state_cur == wb_fsm_idle) |
burst_len <= 2'h2; |
burst_len <= bl[3:0] - 2; |
else if (wb_stb_o & wb_ack) |
burst_len <= burst_len - 1'b1; |
burst_len <= burst_len - 1; |
end |
end |
|
232,15 → 235,11
!(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_err_i & !wb_rty_i & wb_cti_o == 3'b010 ; |
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; |
282,7 → 281,7
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 |
wb_bte_o <= (bl==8) ? 2'b10 : (bl==4) ? 2'b01 : 2'b00; |
`ifdef OR1200_WB_CAB |
wb_cab_o <= 1'b0; |
`endif |
295,13 → 294,15
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; |
`ifndef OR1200_NO_BURSTS |
wb_cti_o <= wb_cti_nxt; |
wb_bte_o <= 2'b01; // 4-beat wrap burst = constant |
`endif |
wb_bte_o <= (bl==8) ? 2'b10 : (bl==4) ? 2'b01 : 2'b00; |
`ifdef OR1200_WB_CAB |
wb_cab_o <= biu_cab_i; |
`endif |
315,7 → 316,12
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; |
if (bl==4) begin |
wb_adr_o[3:2] <= wb_adr_o[3:2] + 1; |
end |
if (bl==8) begin |
wb_adr_o[4:2] <= wb_adr_o[4:2] + 1; |
end |
end |
`ifdef OR1200_NO_DC |
// dat - write data changed after avery subsequent write access |
/verilog/or1200_ic_top.v
1,6 → 1,6
////////////////////////////////////////////////////////////////////// |
//// //// |
//// OR1200's Data Cache top level //// |
//// OR1200's Instruction Cache top level //// |
//// //// |
//// This file is part of the OpenRISC 1200 project //// |
//// http://opencores.org/project,or1k //// |
51,7 → 51,7
`include "or1200_defines.v" |
|
// |
// Data cache |
// Instruction cache top |
// |
module or1200_ic_top( |
// Rst, clk and clock control |
58,13 → 58,12
clk, rst, |
|
// External i/f |
icbiu_dat_o, icbiu_adr_o, icbiu_cyc_o, icbiu_stb_o, icbiu_we_o, icbiu_sel_o, icbiu_cab_o, |
icbiu_dat_i, icbiu_ack_i, icbiu_err_i, |
icbiu_dat_o, icbiu_adr_o, icbiu_cyc_o, icbiu_stb_o, icbiu_we_o, |
icbiu_sel_o, icbiu_cab_o, icbiu_dat_i, icbiu_ack_i, icbiu_err_i, |
|
// Internal i/f |
ic_en, |
icqmem_adr_i, icqmem_cycstb_i, icqmem_ci_i, |
icqmem_sel_i, icqmem_tag_i, |
icqmem_adr_i, icqmem_cycstb_i, icqmem_ci_i, icqmem_sel_i, icqmem_tag_i, |
icqmem_dat_o, icqmem_ack_o, icqmem_rty_o, icqmem_err_o, icqmem_tag_o, |
|
`ifdef OR1200_BIST |
145,7 → 144,9
wire ictag_we; |
wire [31:0] ic_addr; |
wire icfsm_biu_read; |
/* verilator lint_off UNOPTFLAT */ |
reg tagcomp_miss; |
/* verilator lint_on UNOPTFLAT */ |
wire [`OR1200_ICINDXH:`OR1200_ICLS] ictag_addr; |
wire ictag_en; |
wire ictag_v; |
155,6 → 156,8
wire icfsm_first_miss_err; |
wire icfsm_burst; |
wire icfsm_tag_we; |
reg ic_inv_q; |
|
`ifdef OR1200_BIST |
// |
// RAM BIST |
217,13 → 220,24
assign icqmem_dat_o = icfsm_first_miss_ack | !ic_en ? icbiu_dat_i : from_icram; |
|
// |
// Detect falling edge of IC invalidate signal |
// |
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst==`OR1200_RST_VALUE) |
ic_inv_q <= 1'b0; |
else |
ic_inv_q <= ic_inv; |
|
|
// |
// Tag comparison |
// |
// During line invalidate, ensure it stays the same |
always @(tag or saved_addr or tag_v) begin |
if ((tag != saved_addr[31:`OR1200_ICTAGL]) || !tag_v) |
tagcomp_miss = 1'b1; |
else |
tagcomp_miss = 1'b0; |
if ((tag != saved_addr[31:`OR1200_ICTAGL]) | !tag_v) |
tagcomp_miss = 1'b1; |
else |
tagcomp_miss = 1'b0; |
end |
|
// |
/verilog/or1200_dc_tag.v
107,20 → 107,12
// |
// Instantiation of TAG RAM block |
// |
`ifdef OR1200_DC_1W_4KB |
// Data widths are tag width plus one for valid |
or1200_spram # |
( |
.aw(8), |
.dw(21 + 1) |
.aw(`OR1200_DCTAG), |
.dw(`OR1200_DCTAG_W + 1) |
) |
`endif |
`ifdef OR1200_DC_1W_8KB |
or1200_spram # |
( |
.aw(9), |
.dw(20 + 1) |
) |
`endif |
dc_tag0 |
( |
`ifdef OR1200_BIST |
/verilog/or1200_dc_ram.v
104,20 → 104,11
// |
// Instantiation of RAM block |
// |
`ifdef OR1200_DC_1W_4KB |
or1200_spram_32_bw # |
( |
.aw(10), |
.dw(32) |
.aw(`OR1200_DCINDX), |
.dw(dw) |
) |
`endif |
`ifdef OR1200_DC_1W_8KB |
or1200_spram_32_bw # |
( |
.aw(11), |
.dw(32) |
) |
`endif |
dc_ram |
( |
`ifdef OR1200_BIST |
/verilog/or1200_gmultp2_32x32.v
3,7 → 3,7
//// Generic 32x32 multiplier //// |
//// //// |
//// This file is part of the OpenRISC 1200 project //// |
//// http://www.opencores.org/cores/or1k/ //// |
//// http://www.opencores.org/project,or1k //// |
//// //// |
//// Description //// |
//// Generic 32x32 multiplier with pipeline stages. //// |
47,31 → 47,6
// Revision 2.0 2010/06/30 11:00:00 ORSoC |
// No update |
// |
// Revision 1.2 2002/07/31 02:04:35 lampret |
// MAC now follows software convention (signed multiply instead of unsigned). |
// |
// 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.4 2001/12/04 05:02:35 lampret |
// Added OR1200_GENERIC_MULTP2_32X32 and OR1200_ASIC_MULTP2_32X32 |
// |
// 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: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_mult_mac.v
11,13 → 11,15
//// //// |
//// To Do: //// |
//// - make signed division better, w/o negating the operands //// |
//// - implement non-serial divider that is synthesizable //// |
//// //// |
//// 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 //// |
56,278 → 58,391
`include "or1200_defines.v" |
|
module or1200_mult_mac( |
// Clock and reset |
clk, rst, |
// Clock and reset |
clk, rst, |
|
// Multiplier/MAC interface |
ex_freeze, id_macrc_op, macrc_op, a, b, mac_op, alu_op, result, mac_stall_r, |
// Multiplier/MAC interface |
ex_freeze, id_macrc_op, macrc_op, a, b, mac_op, alu_op, |
result, mult_mac_stall, |
|
// SPR interface |
spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o |
); |
// SPR interface |
spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o |
); |
|
parameter width = `OR1200_OPERAND_WIDTH; |
parameter width = `OR1200_OPERAND_WIDTH; |
|
// |
// I/O |
// |
// |
// I/O |
// |
|
// |
// Clock and reset |
// |
input clk; |
input rst; |
// |
// Clock and reset |
// |
input clk; |
input rst; |
|
// |
// Multiplier/MAC interface |
// |
input ex_freeze; |
input id_macrc_op; |
input macrc_op; |
input [width-1:0] a; |
input [width-1:0] b; |
input [`OR1200_MACOP_WIDTH-1:0] mac_op; |
input [`OR1200_ALUOP_WIDTH-1:0] alu_op; |
output [width-1:0] result; |
output mac_stall_r; |
// |
// Multiplier/MAC interface |
// |
input ex_freeze; |
input id_macrc_op; |
input macrc_op; |
input [width-1:0] a; |
input [width-1:0] b; |
input [`OR1200_MACOP_WIDTH-1:0] mac_op; |
input [`OR1200_ALUOP_WIDTH-1:0] alu_op; |
output [width-1:0] result; |
output mult_mac_stall; |
|
// |
// SPR interface |
// |
input spr_cs; |
input spr_write; |
input [31:0] spr_addr; |
input [31:0] spr_dat_i; |
output [31:0] spr_dat_o; |
// |
// SPR interface |
// |
input spr_cs; |
input spr_write; |
input [31:0] spr_addr; |
input [31:0] spr_dat_i; |
output [31:0] spr_dat_o; |
|
// |
// Internal wires and regs |
// |
// |
// Internal wires and regs |
// |
reg [width-1:0] result; |
`ifdef OR1200_MULT_IMPLEMENTED |
reg [width-1:0] result; |
reg [2*width-1:0] mul_prod_r; |
reg [2*width-1:0] mul_prod_r; |
wire alu_op_smul; |
wire alu_op_umul; |
wire alu_op_mul; |
`ifdef OR1200_MULT_SERIAL |
reg [5:0] serial_mul_cnt; |
reg mul_free; |
`endif |
`else |
wire [width-1:0] result; |
wire [2*width-1:0] mul_prod_r; |
wire [2*width-1:0] mul_prod_r; |
`endif |
wire [2*width-1:0] mul_prod; |
wire [`OR1200_MACOP_WIDTH-1:0] mac_op; |
wire [2*width-1:0] mul_prod; |
wire mul_stall; |
|
wire [`OR1200_MACOP_WIDTH-1:0] mac_op; |
`ifdef OR1200_MAC_IMPLEMENTED |
reg [`OR1200_MACOP_WIDTH-1:0] mac_op_r1; |
reg [`OR1200_MACOP_WIDTH-1:0] mac_op_r2; |
reg [`OR1200_MACOP_WIDTH-1:0] mac_op_r3; |
reg mac_stall_r; |
reg [63:0] mac_r; |
reg [`OR1200_MACOP_WIDTH-1:0] mac_op_r1; |
reg [`OR1200_MACOP_WIDTH-1:0] mac_op_r2; |
reg [`OR1200_MACOP_WIDTH-1:0] mac_op_r3; |
reg mac_stall_r; |
reg [63:0] mac_r; |
`else |
wire [`OR1200_MACOP_WIDTH-1:0] mac_op_r1; |
wire [`OR1200_MACOP_WIDTH-1:0] mac_op_r2; |
wire [`OR1200_MACOP_WIDTH-1:0] mac_op_r3; |
wire mac_stall_r; |
wire [63:0] mac_r; |
wire [`OR1200_MACOP_WIDTH-1:0] mac_op_r1; |
wire [`OR1200_MACOP_WIDTH-1:0] mac_op_r2; |
wire [`OR1200_MACOP_WIDTH-1:0] mac_op_r3; |
wire mac_stall_r; |
wire [63:0] mac_r; |
`endif |
wire [width-1:0] x; |
wire [width-1:0] y; |
wire spr_maclo_we; |
wire spr_machi_we; |
wire alu_op_div_divu; |
wire alu_op_div; |
reg div_free; |
wire [width-1:0] x; |
wire [width-1:0] y; |
wire spr_maclo_we; |
wire spr_machi_we; |
wire alu_op_div; |
wire alu_op_udiv; |
wire alu_op_sdiv; |
reg div_free; |
wire div_stall; |
`ifdef OR1200_DIV_IMPLEMENTED |
wire [width-1:0] div_tmp; |
reg [5:0] div_cntr; |
`ifdef OR1200_DIV_SERIAL |
reg [2*width-1:0] div_quot_r; |
wire [width-1:0] div_tmp; |
reg [5:0] div_cntr; |
`else |
reg [width-1:0] div_quot_r; |
reg [width-1:0] div_quot_generic; |
`endif |
`endif |
|
// |
// Combinatorial logic |
// |
// |
// Combinatorial logic |
// |
`ifdef OR1200_MULT_IMPLEMENTED |
assign alu_op_smul = (alu_op == `OR1200_ALUOP_MUL); |
assign alu_op_umul = (alu_op == `OR1200_ALUOP_MULU); |
assign alu_op_mul = alu_op_smul | alu_op_umul; |
`endif |
`ifdef OR1200_MAC_IMPLEMENTED |
assign spr_maclo_we = spr_cs & spr_write & spr_addr[`OR1200_MAC_ADDR]; |
assign spr_machi_we = spr_cs & spr_write & !spr_addr[`OR1200_MAC_ADDR]; |
assign spr_dat_o = spr_addr[`OR1200_MAC_ADDR] ? mac_r[31:0] : mac_r[63:32]; |
assign spr_maclo_we = spr_cs & spr_write & spr_addr[`OR1200_MAC_ADDR]; |
assign spr_machi_we = spr_cs & spr_write & !spr_addr[`OR1200_MAC_ADDR]; |
assign spr_dat_o = spr_addr[`OR1200_MAC_ADDR] ? mac_r[31:0] : mac_r[63:32]; |
`else |
assign spr_maclo_we = 1'b0; |
assign spr_machi_we = 1'b0; |
assign spr_dat_o = 32'h0000_0000; |
assign spr_maclo_we = 1'b0; |
assign spr_machi_we = 1'b0; |
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; |
`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_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; |
assign alu_op_sdiv = (alu_op == `OR1200_ALUOP_DIV); |
assign alu_op_udiv = (alu_op == `OR1200_ALUOP_DIVU); |
assign alu_op_div = alu_op_sdiv | alu_op_udiv; |
`else |
assign alu_op_div = 1'b0; |
assign alu_op_div_divu = 1'b0; |
assign alu_op_udiv = 1'b0; |
assign alu_op_sdiv = 1'b0; |
assign alu_op_div = 1'b0; |
`endif |
|
`ifdef OR1200_MULT_IMPLEMENTED |
assign x = (alu_op_sdiv | alu_op_smul) & a[31] ? ~a + 32'b1 : |
alu_op_div | alu_op_mul | (|mac_op) ? a : 32'd0; |
assign y = (alu_op_sdiv | alu_op_smul) & b[31] ? ~b + 32'b1 : |
alu_op_div | alu_op_mul | (|mac_op) ? b : 32'd0; |
|
// |
// Select result of current ALU operation to be forwarded |
// to next instruction and to WB stage |
// |
always @* |
casez(alu_op) // synopsys parallel_case |
`ifdef OR1200_DIV_IMPLEMENTED |
`OR1200_ALUOP_DIV: begin |
result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 32'd1 : mul_prod_r[31:0]; |
end |
`OR1200_ALUOP_DIVU, |
`endif |
`OR1200_ALUOP_MUL: begin |
result = mul_prod_r[31:0]; |
end |
default: |
// |
// Select result of current ALU operation to be forwarded |
// to next instruction and to WB stage |
// |
always @* |
casez(alu_op) // synopsys parallel_case |
`ifdef OR1200_DIV_IMPLEMENTED |
`OR1200_ALUOP_DIV: begin |
result = a[31] ^ b[31] ? ~div_quot_r[31:0] + 32'd1 : div_quot_r[31:0]; |
end |
`OR1200_ALUOP_DIVU: begin |
result = div_quot_r[31:0]; |
end |
`endif |
`ifdef OR1200_MULT_IMPLEMENTED |
`OR1200_ALUOP_MUL: begin |
result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 32'd1 : mul_prod_r[31:0]; |
end |
`OR1200_ALUOP_MULU: begin |
result = mul_prod_r[31:0]; |
end |
`endif |
default: |
`ifdef OR1200_MAC_IMPLEMENTED |
`ifdef OR1200_MAC_SHIFTBY |
result = mac_r[`OR1200_MAC_SHIFTBY+31:`OR1200_MAC_SHIFTBY]; |
result = mac_r[`OR1200_MAC_SHIFTBY+31:`OR1200_MAC_SHIFTBY]; |
`else |
result = mac_r[31:0]; |
result = mac_r[31:0]; |
`endif |
endcase |
`else |
result = {width{1'b0}}; |
`endif |
endcase |
|
`ifdef OR1200_MULT_IMPLEMENTED |
`ifdef OR1200_MULT_SERIAL |
|
always @(`OR1200_RST_EVENT rst or posedge clk) |
if (rst == `OR1200_RST_VALUE) begin |
mul_prod_r <= 64'h0000_0000_0000_0000; |
serial_mul_cnt <= 6'd0; |
mul_free <= 1'b1; |
|
end |
else if (|serial_mul_cnt) begin |
serial_mul_cnt <= serial_mul_cnt - 6'd1; |
if (mul_prod_r[0]) |
mul_prod_r[(width*2)-1:width-1] <= mul_prod_r[(width*2)-1:width] + x; |
else |
mul_prod_r[(width*2)-1:width-1] <= {1'b0,mul_prod_r[(width*2)-1: |
width]}; |
mul_prod_r[width-2:0] <= mul_prod_r[width-1:1]; |
|
end |
else if (alu_op_mul && mul_free) begin |
mul_prod_r <= {32'd0, y}; |
mul_free <= 0; |
serial_mul_cnt <= 6'b10_0000; |
end |
else if (!ex_freeze | mul_free) begin |
mul_free <= 1'b1; |
end |
|
assign mul_stall = (|serial_mul_cnt); |
|
`else |
|
// |
// Instantiation of the multiplier |
// |
`ifdef OR1200_ASIC_MULTP2_32X32 |
or1200_amultp2_32x32 or1200_amultp2_32x32( |
.X(x), |
.Y(y), |
.RST(rst), |
.CLK(clk), |
.P(mul_prod) |
); |
`else // OR1200_ASIC_MULTP2_32X32 |
or1200_gmultp2_32x32 or1200_gmultp2_32x32( |
.X(x), |
.Y(y), |
.RST(rst), |
.CLK(clk), |
.P(mul_prod) |
); |
`endif // OR1200_ASIC_MULTP2_32X32 |
`ifdef OR1200_ASIC_MULTP2_32X32 |
or1200_amultp2_32x32 or1200_amultp2_32x32( |
.X(x), |
.Y(y), |
.RST(rst), |
.CLK(clk), |
.P(mul_prod) |
); |
`else // OR1200_ASIC_MULTP2_32X32 |
or1200_gmultp2_32x32 or1200_gmultp2_32x32( |
.X(x), |
.Y(y), |
.RST(rst), |
.CLK(clk), |
.P(mul_prod) |
); |
`endif // OR1200_ASIC_MULTP2_32X32 |
|
// |
// Registered output from the multiplier |
// |
always @(`OR1200_RST_EVENT rst or posedge clk) |
if (rst == `OR1200_RST_VALUE) begin |
mul_prod_r <= 64'h0000_0000_0000_0000; |
end |
else begin |
mul_prod_r <= mul_prod[63:0]; |
end |
|
// |
// Registered output from the multiplier and |
// an optional divider |
// |
always @(`OR1200_RST_EVENT rst or posedge clk) |
if (rst == `OR1200_RST_VALUE) begin |
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_DIV_IMPLEMENTED |
else if (|div_cntr) begin |
if (div_tmp[31]) |
mul_prod_r <= {mul_prod_r[62:0], 1'b0}; |
else |
mul_prod_r <= {div_tmp[30:0], mul_prod_r[31:0], 1'b1}; |
div_cntr <= div_cntr - 6'd1; |
end |
else if (alu_op_div_divu && div_free) begin |
mul_prod_r <= {31'b0, x[31:0], 1'b0}; |
div_cntr <= 6'b10_0000; |
div_free <= 1'b0; |
end |
`endif // OR1200_DIV_IMPLEMENTED |
else if (div_free | !ex_freeze) begin |
mul_prod_r <= mul_prod[63:0]; |
div_free <= 1'b1; |
end |
|
assign mul_stall = 0; |
`endif // !`ifdef OR1200_MULT_SERIAL |
|
`else // OR1200_MULT_IMPLEMENTED |
assign result = {width{1'b0}}; |
assign mul_prod = {2*width{1'b0}}; |
assign mul_prod_r = {2*width{1'b0}}; |
assign mul_prod = {2*width{1'b0}}; |
assign mul_prod_r = {2*width{1'b0}}; |
assign mul_stall = 0; |
`endif // OR1200_MULT_IMPLEMENTED |
|
`ifdef OR1200_MAC_IMPLEMENTED |
// Signal to indicate when we should check for new MAC op |
reg ex_freeze_r; |
// Signal to indicate when we should check for new MAC op |
reg ex_freeze_r; |
|
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst == `OR1200_RST_VALUE) |
ex_freeze_r <= 1'b1; |
else |
ex_freeze_r <= ex_freeze; |
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst == `OR1200_RST_VALUE) |
ex_freeze_r <= 1'b1; |
else |
ex_freeze_r <= ex_freeze; |
|
// |
// Propagation of l.mac opcode, only register it for one cycle |
// |
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst == `OR1200_RST_VALUE) |
mac_op_r1 <= `OR1200_MACOP_WIDTH'b0; |
else |
mac_op_r1 <= !ex_freeze_r ? mac_op : `OR1200_MACOP_WIDTH'b0; |
// |
// Propagation of l.mac opcode, only register it for one cycle |
// |
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst == `OR1200_RST_VALUE) |
mac_op_r1 <= `OR1200_MACOP_WIDTH'b0; |
else |
mac_op_r1 <= !ex_freeze_r ? mac_op : `OR1200_MACOP_WIDTH'b0; |
|
// |
// Propagation of l.mac opcode |
// |
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst == `OR1200_RST_VALUE) |
mac_op_r2 <= `OR1200_MACOP_WIDTH'b0; |
else |
mac_op_r2 <= mac_op_r1; |
// |
// Propagation of l.mac opcode |
// |
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst == `OR1200_RST_VALUE) |
mac_op_r2 <= `OR1200_MACOP_WIDTH'b0; |
else |
mac_op_r2 <= mac_op_r1; |
|
// |
// Propagation of l.mac opcode |
// |
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst == `OR1200_RST_VALUE) |
mac_op_r3 <= `OR1200_MACOP_WIDTH'b0; |
else |
mac_op_r3 <= mac_op_r2; |
// |
// Propagation of l.mac opcode |
// |
always @(posedge clk or `OR1200_RST_EVENT rst) |
if (rst == `OR1200_RST_VALUE) |
mac_op_r3 <= `OR1200_MACOP_WIDTH'b0; |
else |
mac_op_r3 <= mac_op_r2; |
|
// |
// Implementation of MAC |
// |
always @(`OR1200_RST_EVENT rst or posedge clk) |
if (rst == `OR1200_RST_VALUE) |
mac_r <= 64'h0000_0000_0000_0000; |
`ifdef OR1200_MAC_SPR_WE |
else if (spr_maclo_we) |
mac_r[31:0] <= spr_dat_i; |
else if (spr_machi_we) |
mac_r[63:32] <= spr_dat_i; |
`endif |
else if (mac_op_r3 == `OR1200_MACOP_MAC) |
mac_r <= mac_r + mul_prod_r; |
else if (mac_op_r3 == `OR1200_MACOP_MSB) |
mac_r <= mac_r - mul_prod_r; |
else if (macrc_op && !ex_freeze) |
mac_r <= 64'h0000_0000_0000_0000; |
// |
// Implementation of MAC |
// |
always @(`OR1200_RST_EVENT rst or posedge clk) |
if (rst == `OR1200_RST_VALUE) |
mac_r <= 64'h0000_0000_0000_0000; |
`ifdef OR1200_MAC_SPR_WE |
else if (spr_maclo_we) |
mac_r[31:0] <= spr_dat_i; |
else if (spr_machi_we) |
mac_r[63:32] <= spr_dat_i; |
`endif |
else if (mac_op_r3 == `OR1200_MACOP_MAC) |
mac_r <= mac_r + mul_prod_r; |
else if (mac_op_r3 == `OR1200_MACOP_MSB) |
mac_r <= mac_r - mul_prod_r; |
else if (macrc_op && !ex_freeze) |
mac_r <= 64'h0000_0000_0000_0000; |
|
// |
// Stall CPU if l.macrc is in ID and MAC still has to process l.mac instructions |
// in EX stage (e.g. inside multiplier) |
// This stall signal is also used by the divider. |
// |
always @(`OR1200_RST_EVENT rst or posedge clk) |
if (rst == `OR1200_RST_VALUE) |
mac_stall_r <= 1'b0; |
else |
mac_stall_r <= (|mac_op | (|mac_op_r1) | (|mac_op_r2)) & (id_macrc_op | mac_stall_r) |
`ifdef OR1200_DIV_IMPLEMENTED |
| (|div_cntr) |
`endif |
; |
// |
// Stall CPU if l.macrc is in ID and MAC still has to process l.mac |
// instructions in EX stage (e.g. inside multiplier) |
// This stall signal is also used by the divider. |
// |
always @(`OR1200_RST_EVENT rst or posedge clk) |
if (rst == `OR1200_RST_VALUE) |
mac_stall_r <= 1'b0; |
else |
mac_stall_r <= (|mac_op | (|mac_op_r1) | (|mac_op_r2)) & |
(id_macrc_op | mac_stall_r); |
`else // OR1200_MAC_IMPLEMENTED |
assign mac_stall_r = 1'b0; |
assign mac_r = {2*width{1'b0}}; |
assign mac_op_r1 = `OR1200_MACOP_WIDTH'b0; |
assign mac_op_r2 = `OR1200_MACOP_WIDTH'b0; |
assign mac_op_r3 = `OR1200_MACOP_WIDTH'b0; |
assign mac_stall_r = 1'b0; |
assign mac_r = {2*width{1'b0}}; |
assign mac_op_r1 = `OR1200_MACOP_WIDTH'b0; |
assign mac_op_r2 = `OR1200_MACOP_WIDTH'b0; |
assign mac_op_r3 = `OR1200_MACOP_WIDTH'b0; |
`endif // OR1200_MAC_IMPLEMENTED |
|
`ifdef OR1200_DIV_IMPLEMENTED |
|
// |
// Serial division |
// |
`ifdef OR1200_DIV_SERIAL |
assign div_tmp = div_quot_r[63:32] - y; |
always @(`OR1200_RST_EVENT rst or posedge clk) |
if (rst == `OR1200_RST_VALUE) begin |
div_quot_r <= 64'h0000_0000_0000_0000; |
div_free <= 1'b1; |
div_cntr <= 6'b00_0000; |
end |
else if (|div_cntr) begin |
if (div_tmp[31]) |
div_quot_r <= {div_quot_r[62:0], 1'b0}; |
else |
div_quot_r <= {div_tmp[30:0], div_quot_r[31:0], 1'b1}; |
div_cntr <= div_cntr - 6'd1; |
end |
else if (alu_op_div && div_free) begin |
div_quot_r <= {31'b0, x[31:0], 1'b0}; |
div_cntr <= 6'b10_0000; |
div_free <= 1'b0; |
end |
else if (div_free | !ex_freeze) begin |
//div_quot_r <= div_quot[63:0]; |
div_free <= 1'b1; |
end |
|
assign div_stall = (|div_cntr); |
|
|
`else // !`ifdef OR1200_DIV_SERIAL |
|
// Full divider |
// TODO: Perhaps provide module that can be technology dependent. |
always @(`OR1200_RST_EVENT rst or posedge clk) begin |
if (rst == `OR1200_RST_VALUE) begin |
div_quot_r <= 32'd0; |
div_quot_generic <= 32'd0; |
end |
else begin |
if (alu_op_udiv & !(|y)) // unsigned divide by 0 - force to MAX |
div_quot_generic[31:0] <= 32'hffff_ffff; |
else if (alu_op_div) |
div_quot_generic[31:0] <= x / y; |
end |
|
// Add any additional statges of pipelining as required here. Ensure |
// ends with div_quot_r. |
// Then add logic to ensure div_stall stays high for as long as the |
// division should take. |
|
div_quot_r[31:0] <= div_quot_generic; |
|
end |
|
assign div_stall = 0; |
|
`endif |
|
`else // !`ifdef OR1200_DIV_IMPLEMENTED |
|
assign div_stall = 0; |
|
`endif // !`ifdef OR1200_DIV_IMPLEMENTED |
|
|
// |
// Stall output |
// |
assign mult_mac_stall = mac_stall_r | div_stall | mul_stall; |
|
endmodule |
/verilog/or1200_dc_top.v
284,7 → 284,6
// 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 |
/verilog/or1200_ic_fsm.v
58,7 → 58,7
`define OR1200_ICFSM_IFETCH 2'd3 |
|
// |
// Data cache FSM for cache line of 16 bytes (4x singleword) |
// Instruction cache FSM |
// |
|
module or1200_ic_fsm( |
67,9 → 67,13
|
// Internal i/f to top level IC |
ic_en, icqmem_cycstb_i, icqmem_ci_i, |
tagcomp_miss, biudata_valid, biudata_error, start_addr, saved_addr, |
icram_we, biu_read, first_hit_ack, first_miss_ack, first_miss_err, |
burst, tag_we |
tagcomp_miss, |
biudata_valid, biudata_error, |
start_addr, saved_addr, |
icram_we, tag_we, |
biu_read, |
first_hit_ack, first_miss_ack, first_miss_err, |
burst |
); |
|
// |
98,11 → 102,12
// |
reg [31:0] saved_addr_r; |
reg [1:0] state; |
reg [2:0] cnt; |
reg [`OR1200_ICLS-1:0] cnt; |
reg hitmiss_eval; |
reg load; |
reg cache_inhibit; |
|
reg last_eval_miss; // JPB |
|
// |
// Generate of ICRAM write enables |
// |
142,8 → 147,10
saved_addr_r <= 32'b0; |
hitmiss_eval <= 1'b0; |
load <= 1'b0; |
cnt <= 3'b000; |
cnt <= `OR1200_ICLS'd0; |
cache_inhibit <= 1'b0; |
last_eval_miss <= 0; // JPB |
|
end |
else |
case (state) // synopsys parallel_case |
154,12 → 161,13
hitmiss_eval <= 1'b1; |
load <= 1'b1; |
cache_inhibit <= icqmem_ci_i; |
last_eval_miss <= 0; // JPB |
end |
else begin // idle |
hitmiss_eval <= 1'b0; |
load <= 1'b0; |
cache_inhibit <= 1'b0; |
end |
end |
`OR1200_ICFSM_CFETCH: begin // fetch |
|
if (icqmem_cycstb_i & icqmem_ci_i) |
166,8 → 174,7
cache_inhibit <= 1'b1; |
|
if (hitmiss_eval) |
saved_addr_r[31:13] <= start_addr[31:13]; |
|
saved_addr_r[31:`OR1200_ICTAGL] <= start_addr[31:`OR1200_ICTAGL]; |
if ((!ic_en) || |
// fetch aborted (usually caused by IMMU) |
(hitmiss_eval & !icqmem_cycstb_i) || |
179,28 → 186,35
load <= 1'b0; |
cache_inhibit <= 1'b0; |
end // if ((!ic_en) ||... |
// fetch missed, finish current external fetch and refill |
// fetch missed, wait for first fetch and continue filling line |
else if (tagcomp_miss & biudata_valid) begin |
state <= `OR1200_ICFSM_LREFILL3; |
saved_addr_r[3:2] <= saved_addr_r[3:2] + 1'd1; |
saved_addr_r[`OR1200_ICLS-1:2] |
<= saved_addr_r[`OR1200_ICLS-1:2] + 1; |
hitmiss_eval <= 1'b0; |
cnt <= `OR1200_ICLS-2; |
cnt <= ((1 << `OR1200_ICLS) - (2 * 4)); |
cache_inhibit <= 1'b0; |
end |
// fetch aborted (usually caused by exception) |
else if (!icqmem_cycstb_i) begin |
else if (!icqmem_cycstb_i |
& !last_eval_miss // JPB |
) 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 |
// fetch hit, wait in this state for now |
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; |
|
if (hitmiss_eval & !tagcomp_miss) // JPB |
last_eval_miss <= 1; // JPB |
|
end |
`OR1200_ICFSM_LREFILL3 : begin |
// abort because IC has just been turned off |
213,8 → 227,9
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; |
cnt <= cnt - `OR1200_ICLS'd4; |
saved_addr_r[`OR1200_ICLS-1:2] |
<= saved_addr_r[`OR1200_ICLS-1:2] + 1; |
end |
// last fetch of line refill |
else if (biudata_valid) begin |
/verilog/or1200_top.v
432,7 → 432,9
// |
// Instantiation of Instruction WISHBONE BIU |
// |
or1200_wb_biu iwb_biu( |
or1200_wb_biu |
#(.bl((1 << (`OR1200_ICLS-2)))) |
iwb_biu( |
// RISC clk, rst and clock control |
.clk(clk_i), |
.rst(rst_i), |
476,7 → 478,9
// |
// Instantiation of Data WISHBONE BIU |
// |
or1200_wb_biu dwb_biu( |
or1200_wb_biu |
#(.bl((1 << (`OR1200_DCLS-2)))) |
dwb_biu( |
// RISC clk, rst and clock control |
.clk(clk_i), |
.rst(rst_i), |
/verilog/or1200_rfram_generic.v
126,6 → 126,7
reg [dw-1:0] do_a; |
reg [dw-1:0] do_b; |
|
`ifdef verilator |
// Function to access GPRs (for use by Verilator). No need to hide this one |
// from the simulator, since it has an input (as required by IEEE 1364-2001). |
function [31:0] get_gpr; |
151,6 → 152,51
|
endfunction // get_gpr |
|
// Function to access GPRs (for use by Verilator). No need to hide this one |
// from the simulator, since it has an input (as required by IEEE 1364-2001). |
function [31:0] set_gpr; |
// verilator public |
input [aw-1:0] gpr_no; |
input [dw-1:0] value; |
|
mem[gpr_no*32 + 31] = value[31]; |
mem[gpr_no*32 + 30] = value[30]; |
mem[gpr_no*32 + 29] = value[29]; |
mem[gpr_no*32 + 28] = value[28]; |
mem[gpr_no*32 + 27] = value[27]; |
mem[gpr_no*32 + 26] = value[26]; |
mem[gpr_no*32 + 25] = value[25]; |
mem[gpr_no*32 + 24] = value[24]; |
mem[gpr_no*32 + 23] = value[23]; |
mem[gpr_no*32 + 22] = value[22]; |
mem[gpr_no*32 + 21] = value[21]; |
mem[gpr_no*32 + 20] = value[20]; |
mem[gpr_no*32 + 19] = value[19]; |
mem[gpr_no*32 + 18] = value[18]; |
mem[gpr_no*32 + 17] = value[17]; |
mem[gpr_no*32 + 16] = value[16]; |
mem[gpr_no*32 + 15] = value[15]; |
mem[gpr_no*32 + 14] = value[14]; |
mem[gpr_no*32 + 13] = value[13]; |
mem[gpr_no*32 + 12] = value[12]; |
mem[gpr_no*32 + 11] = value[11]; |
mem[gpr_no*32 + 10] = value[10]; |
mem[gpr_no*32 + 9] = value[ 9]; |
mem[gpr_no*32 + 8] = value[ 8]; |
mem[gpr_no*32 + 7] = value[ 7]; |
mem[gpr_no*32 + 6] = value[ 6]; |
mem[gpr_no*32 + 5] = value[ 5]; |
mem[gpr_no*32 + 4] = value[ 4]; |
mem[gpr_no*32 + 3] = value[ 3]; |
mem[gpr_no*32 + 2] = value[ 2]; |
mem[gpr_no*32 + 1] = value[ 1]; |
mem[gpr_no*32 + 0] = value[ 0]; |
|
set_gpr = 0; |
|
endfunction // set_gpr |
`endif // `ifdef verilator |
|
// |
// Write port |
// |
/verilog/or1200_dpram.v
107,6 → 107,15
get_gpr = mem[gpr_no]; |
|
endfunction // get_gpr |
|
task set_gpr; |
// verilator public |
input [aw-1:0] gpr_no; |
input [dw-1:0] value; |
|
mem[gpr_no] = value; |
|
endtask // get_gpr |
|
// |
// Data output drivers |