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

Subversion Repositories altor32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /altor32/trunk
    from Rev 35 to Rev 36
    Reverse comparison

Rev 35 → Rev 36

/rtl/cpu_lite/altor32_regfile_sim.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu_lite/altor32_regfile_xil.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu_lite/altor32_lite.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
120,6 → 120,14
wire alu_carry_out;
wire alu_carry_update;
 
// ALU Comparisons
wire compare_equal_w;
wire compare_gts_w;
wire compare_gt_w;
wire compare_lts_w;
wire compare_lt_w;
wire alu_flag_update;
 
// ALU operation selection
reg [3:0] r_e_alu_func;
 
174,7 → 182,15
 
// Carry
.c_o(alu_carry_out),
.c_update_o(alu_carry_update)
.c_update_o(alu_carry_update),
 
// Comparisons
.equal_o(compare_equal_w),
.greater_than_signed_o(compare_gts_w),
.greater_than_o(compare_gt_w),
.less_than_signed_o(compare_lts_w),
.less_than_o(compare_lt_w),
.flag_update_o(alu_flag_update)
);
 
// Writeback result
278,7 → 294,7
 
// Sub instructions
alu_op_r = {r_opcode[9:6],r_opcode[3:0]};
sfxx_op_r = {5'b00,r_opcode[31:21]};
sfxx_op_r = {5'b00,r_opcode[31:21]} & `INST_OR32_SFMASK;
shift_op_r = r_opcode[7:6];
 
// Branch target
355,30 → 371,18
wire inst_sfxx_w = (inst_r == `INST_OR32_SFXX);
wire inst_sfxxi_w = (inst_r == `INST_OR32_SFXXI);
 
wire inst_sfeq_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFEQ); // l.sfeq
wire inst_sfges_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGES); // l.sfges
wire inst_sfeq_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFEQ); // l.sfeq
wire inst_sfges_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGES); // l.sfges
 
wire inst_sfgeu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGEU); // l.sfgeu
wire inst_sfgts_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGTS); // l.sfgts
wire inst_sfgtu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGTU); // l.sfgtu
wire inst_sfles_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLES); // l.sfles
wire inst_sfleu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLEU); // l.sfleu
wire inst_sflts_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLTS); // l.sflts
wire inst_sfltu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLTU); // l.sfltu
wire inst_sfne_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFNE); // l.sfne
wire inst_sfgeu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGEU); // l.sfgeu
wire inst_sfgts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTS); // l.sfgts
wire inst_sfgtu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTU); // l.sfgtu
wire inst_sfles_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLES); // l.sfles
wire inst_sfleu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLEU); // l.sfleu
wire inst_sflts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTS); // l.sflts
wire inst_sfltu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTU); // l.sfltu
wire inst_sfne_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFNE); // l.sfne
 
wire inst_sfeqi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFEQI); // l.sfeqi
wire inst_sfgesi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGESI); // l.sfgesi
wire inst_sfgeui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGEUI); // l.sfgeui
wire inst_sfgtsi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGTSI); // l.sfgtsi
wire inst_sfgtui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGTUI); // l.sfgtui
wire inst_sflesi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLESI); // l.sflesi
 
wire inst_sfleui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLEUI); // l.sfleui
wire inst_sfltsi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLTSI); // l.sfltsi
wire inst_sfltui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLTUI); // l.sfltui
wire inst_sfnei_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFNEI); // l.sfnei
 
wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_SYS); // l.sys
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_TRAP); // l.trap
 
685,6 → 689,10
begin
next_sr_r = r_sr;
 
// Update SR.F
if (alu_flag_update)
next_sr_r[`OR32_SR_F] = compare_result_r;
 
// Latch carry if updated
if (alu_carry_update)
next_sr_r[`OR32_SR_CY] = alu_carry_out;
944,6 → 952,22
write_rd_r = 1'b1;
end
 
// l.sf*i
inst_sfxxi_w:
begin
alu_func_r = `ALU_COMPARE;
alu_input_a_r = reg_ra_r;
alu_input_b_r = int32_r;
end
 
// l.sf*
inst_sfxx_w:
begin
alu_func_r = `ALU_COMPARE;
alu_input_a_r = reg_ra_r;
alu_input_b_r = reg_rb_r;
end
 
// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
inst_lbs_w,
inst_lhs_w,
968,107 → 992,39
//-----------------------------------------------------------------
// Comparisons
//-----------------------------------------------------------------
 
reg [31:0] compare_a_r;
reg [31:0] compare_b_r;
always @ *
begin
compare_a_r = reg_ra_r;
compare_b_r = reg_rb_r;
 
case (1'b1)
inst_sfeqi_w, // l.sfeqi
inst_sfgesi_w, // l.sfgesi
inst_sfgeui_w, // l.sfgeui
inst_sfgtsi_w, // l.sfgtsi
inst_sfgtui_w, // l.sfgtui
inst_sflesi_w, // l.sflesi
inst_sfleui_w, // l.sfleui
inst_sfltsi_w, // l.sfltsi
inst_sfltui_w, // l.sfltui
inst_sfnei_w: // l.sfnei
compare_b_r = int32_r;
default:
;
endcase
end
inst_sfges_w: // l.sfges
compare_result_r = compare_gts_w | compare_equal_w;
 
reg compare_equal_r;
reg compare_gts_r;
reg compare_gt_r;
reg compare_lts_r;
reg compare_lt_r;
always @ *
begin
if (compare_a_r == compare_b_r)
compare_equal_r = 1'b1;
else
compare_equal_r = 1'b0;
inst_sfgeu_w: // l.sfgeu
compare_result_r = compare_gt_w | compare_equal_w;
 
compare_lts_r = less_than_signed(compare_a_r, compare_b_r);
inst_sfgts_w: // l.sfgts
compare_result_r = compare_gts_w;
 
if (compare_a_r < compare_b_r)
compare_lt_r = 1'b1;
else
compare_lt_r = 1'b0;
inst_sfgtu_w: // l.sfgtu
compare_result_r = compare_gt_w;
 
// Greater than (signed)
compare_gts_r = ~(compare_lts_r | compare_equal_r);
inst_sfles_w: // l.sfles
compare_result_r = compare_lts_w | compare_equal_w;
 
if (compare_a_r > compare_b_r)
compare_gt_r = 1'b1;
else
compare_gt_r = 1'b0;
end
inst_sfleu_w: // l.sfleu
compare_result_r = compare_lt_w | compare_equal_w;
 
always @ *
begin
compare_result_r = 1'b0;
inst_sflts_w: // l.sflts
compare_result_r = compare_lts_w;
 
case (1'b1)
inst_sfeq_w, // l.sfeq
inst_sfeqi_w: // l.sfeqi
compare_result_r = compare_equal_r;
inst_sfltu_w: // l.sfltu
compare_result_r = compare_lt_w;
 
inst_sfges_w, // l.sfges
inst_sfgesi_w: // l.sfgesi
compare_result_r = compare_gts_r | compare_equal_r;
inst_sfne_w: // l.sfne
compare_result_r = ~compare_equal_w;
 
inst_sfgeu_w, // l.sfgeu
inst_sfgeui_w: // l.sfgeui
compare_result_r = compare_gt_r | compare_equal_r;
 
inst_sfgts_w, // l.sfgts
inst_sfgtsi_w: // l.sfgtsi
compare_result_r = compare_gts_r;
 
inst_sfgtu_w, // l.sfgtu
inst_sfgtui_w: // l.sfgtui
compare_result_r = compare_gt_r;
 
inst_sfles_w, // l.sfles
inst_sflesi_w: // l.sflesi
compare_result_r = compare_lts_r | compare_equal_r;
 
inst_sfleu_w, // l.sfleu
inst_sfleui_w: // l.sfleui
compare_result_r = compare_lt_r | compare_equal_r;
 
inst_sflts_w, // l.sflts
inst_sfltsi_w: // l.sfltsi
compare_result_r = compare_lts_r;
 
inst_sfltu_w, // l.sfltu
inst_sfltui_w: // l.sfltui
compare_result_r = compare_lt_r;
 
inst_sfne_w, // l.sfne
inst_sfnei_w: // l.sfnei
compare_result_r = ~compare_equal_r;
 
default:
;
endcase
default: // l.sfeq
compare_result_r = compare_equal_w;
endcase
end
 
//-----------------------------------------------------------------
1190,25 → 1146,15
inst_srai_w,
inst_srli_w,
inst_sfeq_w,
inst_sfeqi_w,
inst_sfges_w,
inst_sfgesi_w,
inst_sfgeu_w,
inst_sfgeui_w,
inst_sfgts_w,
inst_sfgtsi_w,
inst_sfgtu_w,
inst_sfgtui_w,
inst_sfles_w,
inst_sflesi_w,
inst_sfleu_w,
inst_sfleui_w,
inst_sflts_w,
inst_sfltsi_w,
inst_sfltu_w,
inst_sfltui_w,
inst_sfne_w,
inst_sfnei_w,
inst_sys_w,
inst_trap_w:
invalid_inst_r = 1'b0;
/rtl/cpu_lite/altor32_regfile_alt.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
51,8 → 51,8
input [4:0] rs_i /*verilator public*/,
input [4:0] rt_i /*verilator public*/,
input [4:0] rd_i /*verilator public*/,
output [31:0] reg_rs_o /*verilator public*/,
output [31:0] reg_rt_o /*verilator public*/,
output reg [31:0] reg_rs_o /*verilator public*/,
output reg [31:0] reg_rt_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
64,14 → 64,11
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg clk_delayed;
wire clk_delayed;
wire [31:0] data_out1;
wire [31:0] data_out2;
reg write_enable;
 
reg [31:0] reg_rs_o;
reg [31:0] reg_rt_o;
 
reg [4:0] addr_reg;
reg [31:0] data_reg;
 
/rtl/cpu_lite/altor32_funcs.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu_lite/altor32.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu_lite/altor32_alu.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
39,6 → 39,7
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_funcs.v"
 
//-----------------------------------------------------------------
// Module - ALU
58,7 → 59,15
 
// Carry
output reg c_o /*verilator public*/,
output reg c_update_o /*verilator public*/
output reg c_update_o /*verilator public*/,
 
// Comparison
output reg equal_o /*verilator public*/,
output reg greater_than_signed_o /*verilator public*/,
output reg greater_than_o /*verilator public*/,
output reg less_than_signed_o /*verilator public*/,
output reg less_than_o /*verilator public*/,
output flag_update_o /*verilator public*/
);
 
//-----------------------------------------------------------------
206,4 → 215,30
 
assign p_o = result;
 
//-----------------------------------------------------------------
// Comparisons
//-----------------------------------------------------------------
always @ *
begin
if (a_i == b_i)
equal_o = 1'b1;
else
equal_o = 1'b0;
 
if (a_i < b_i)
less_than_o = 1'b1;
else
less_than_o = 1'b0;
 
if (a_i > b_i)
greater_than_o = 1'b1;
else
greater_than_o = 1'b0;
 
less_than_signed_o = less_than_signed(a_i, b_i);
greater_than_signed_o = ~(less_than_signed_o | equal_o);
end
 
assign flag_update_o = (op_i == `ALU_COMPARE);
 
endmodule
/rtl/cpu_lite/altor32_defs.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
48,6 → 48,7
`define ALU_AND 4'b0111
`define ALU_OR 4'b1000
`define ALU_XOR 4'b1001
`define ALU_COMPARE 4'b1010
 
//-----------------------------------------------------------------
// ALU Instructions
106,26 → 107,17
//-----------------------------------------------------------------
`define INST_OR32_SFXX 8'h39
`define INST_OR32_SFXXI 8'h2F
`define INST_OR32_SFEQ 16'h0720
`define INST_OR32_SFEQI 16'h05E0
`define INST_OR32_SFGES 16'h072B
`define INST_OR32_SFGESI 16'h05EB
`define INST_OR32_SFGEU 16'h0723
`define INST_OR32_SFGEUI 16'h05E3
`define INST_OR32_SFGTS 16'h072A
`define INST_OR32_SFGTSI 16'h05EA
`define INST_OR32_SFGTU 16'h0722
`define INST_OR32_SFGTUI 16'h05E2
`define INST_OR32_SFLES 16'h072D
`define INST_OR32_SFLESI 16'h05ED
`define INST_OR32_SFLEU 16'h0725
`define INST_OR32_SFLEUI 16'h05E5
`define INST_OR32_SFLTS 16'h072C
`define INST_OR32_SFLTSI 16'h05EC
`define INST_OR32_SFLTU 16'h0724
`define INST_OR32_SFLTUI 16'h05E4
`define INST_OR32_SFNE 16'h0721
`define INST_OR32_SFNEI 16'h05E1
`define INST_OR32_SFMASK 16'hFD3F
`define INST_OR32_SFEQ 16'h0520
`define INST_OR32_SFGES 16'h052B
`define INST_OR32_SFGEU 16'h0523
`define INST_OR32_SFGTS 16'h052A
`define INST_OR32_SFGTU 16'h0522
`define INST_OR32_SFLES 16'h052D
`define INST_OR32_SFLEU 16'h0525
`define INST_OR32_SFLTS 16'h052C
`define INST_OR32_SFLTU 16'h0524
`define INST_OR32_SFNE 16'h0521
 
//-----------------------------------------------------------------
// Misc Instructions
/rtl/cpu/altor32_dcache.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
91,6 → 91,8
parameter ADDR_NO_CACHE_BIT = 25;
parameter ADDR_CACHE_BYPASS_BIT = 31;
 
parameter FLUSH_INITIAL = 0;
 
// 31 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
// |--------------| | | | | | | | | | | | | | | | |
// +--------------------+ +-------------------+ +-----------+
133,6 → 135,7
reg [31:0] req_data;
 
reg req_flush;
reg req_init;
reg flush_single;
 
wire [31:0] line_address;
160,7 → 163,7
assign cache_address = {tag_entry, muxed_address[CACHE_LINE_SIZE_WIDTH-1:2]};
 
assign data_o = (state == STATE_SINGLE_READY) ? data_r : cache_data_r;
assign stall_o = (state != STATE_IDLE) | req_flush;
assign stall_o = (state != STATE_IDLE) | req_flush | flush_i;
 
wire valid = tag_data_out[CACHE_TAG_VALID_BIT];
wire dirty = tag_data_out[CACHE_TAG_DIRTY_BIT];
176,10 → 179,13
 
assign ack_o = ack | hit;
 
assign line_address[31:CACHE_TAG_ADDR_HIGH+1] = {(31-CACHE_TAG_ADDR_HIGH){1'b0}};
assign line_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] = tag_entry;
assign line_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] = tag_data_out[13:0];
assign line_address[CACHE_LINE_SIZE_WIDTH-1:0] = {CACHE_LINE_SIZE_WIDTH{1'b0}};
 
// Only allow cache write when same line present in the write state
wire cache_wr_enable = (state == STATE_WRITE) ? valid & addr_hit : 1'b1;
 
//-----------------------------------------------------------------
// Next State Logic
212,13 → 218,16
next_state_r = STATE_WRITE;
end
//-----------------------------------------
// WRITE - Wait for write-thru to complete
// WRITE
//-----------------------------------------
STATE_WRITE :
begin
// Cache hit
if (valid & addr_hit)
next_state_r = STATE_WAIT2;
// Cache hit (line already dirty)
if (valid & addr_hit & dirty)
next_state_r = STATE_IDLE;
// Cache hit, make line dirty
else if (valid & addr_hit & ~dirty)
next_state_r = STATE_WAIT2;
// Cache dirty
else if (valid & dirty)
next_state_r = STATE_EVICTING;
343,7 → 352,7
STATE_FLUSH3 :
begin
// Dirty line? Evict line first
if (dirty)
if (dirty && ~req_init)
next_state_r = STATE_FLUSH4;
// Not dirty? Just invalidate
else
399,7 → 408,7
 
case (state)
//-----------------------------------------
// WRITE - Wait for write-thru to complete
// WRITE
//-----------------------------------------
STATE_WRITE :
begin
407,9 → 416,12
if (valid & addr_hit)
begin
// Mark line as dirty
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
tag_wr <= 1'b1;
if (~dirty)
begin
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
tag_wr <= 1'b1;
end
end
// Cache miss / cache line doesn't require write back
else if (~valid | ~dirty)
499,9 → 511,9
STATE_FLUSH3 :
begin
// Not dirty? Just invalidate
if (~dirty)
if (~dirty | req_init)
begin
tag_data_in <= tag_data_out;
tag_data_in <= 16'b0;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_wr <= 1'b1;
end
515,7 → 527,7
if (done)
begin
// Invalidate line
tag_data_in <= tag_data_out;
tag_data_in <= 16'b0;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b0;
tag_wr <= 1'b1;
539,7 → 551,8
req_ack <= 1'b0;
req_wr <= 4'h0;
req_rd <= 1'b0;
req_flush <= 1'b0;
req_flush <= 1'b1;
req_init <= FLUSH_INITIAL;
end
else
begin
607,6 → 620,7
if (req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] == {CACHE_LINE_ADDR_WIDTH{1'b1}})
begin
req_ack <= 1'b0;
req_init <= 1'b0;
end
else
begin
637,17 → 651,17
 
case (state)
//-----------------------------------------
// WRITE - Wait for write-thru to complete
// IDLE
//-----------------------------------------
STATE_WRITE :
begin
// Cache hit
if (valid & addr_hit)
STATE_IDLE:
begin
// Write (cacheable)
if (stb_i & we_i & cacheable & ~(flush_i | req_flush))
begin
// Update line already in cache
cache_data_w <= req_data;
cache_wr <= req_wr;
end
// Early write which is gated on line match
cache_data_w <= data_i;
cache_wr <= sel_i;
end
end
//-----------------------------------------
// UPDATE - Update fetched cache line
715,7 → 729,7
end
end
//-----------------------------------------
// WRITE - Wait for write-thru to complete
// WRITE
//-----------------------------------------
STATE_WRITE :
begin
949,7 → 963,7
.aadr_i(cache_address),
.adat_o(cache_data_r[7:0]),
.adat_i(cache_data_w[7:0]),
.awr_i(cache_wr[0]),
.awr_i(cache_wr[0] & cache_wr_enable),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
969,7 → 983,7
.aadr_i(cache_address),
.adat_o(cache_data_r[15:8]),
.adat_i(cache_data_w[15:8]),
.awr_i(cache_wr[1]),
.awr_i(cache_wr[1] & cache_wr_enable),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
989,7 → 1003,7
.aadr_i(cache_address),
.adat_o(cache_data_r[23:16]),
.adat_i(cache_data_w[23:16]),
.awr_i(cache_wr[2]),
.awr_i(cache_wr[2] & cache_wr_enable),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
1009,7 → 1023,7
.aadr_i(cache_address),
.adat_o(cache_data_r[31:24]),
.adat_i(cache_data_w[31:24]),
.awr_i(cache_wr[3]),
.awr_i(cache_wr[3] & cache_wr_enable),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
/rtl/cpu/altor32_noicache.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
53,6 → 53,9
input [31:0] pc_i /*verilator public*/,
output [31:0] instruction_o /*verilator public*/,
output valid_o /*verilator public*/,
 
// Invalidate (not used)
input invalidate_i /*verilator public*/,
// Memory interface
output reg [31:0] wbm_addr_o /*verilator public*/,
137,4 → 140,3
assign wbm_cti_o = 3'b111;
 
endmodule
 
/rtl/cpu/altor32_writeback.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_icache.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
55,10 → 55,6
output valid_o /*verilator public*/,
input invalidate_i /*verilator public*/,
 
// Status
output miss_o /*verilator public*/,
output busy_o /*verilator public*/,
 
// Memory interface
output reg [31:0] wbm_addr_o /*verilator public*/,
input [31:0] wbm_dat_i /*verilator public*/,
112,9 → 108,9
 
// Data memory read / write
wire [CACHE_DWIDTH-1:0] cache_address_rd;
reg [CACHE_DWIDTH-1:0] cache_address_wr;
wire [CACHE_DWIDTH-1:0] cache_address_wr;
reg [31:0] cache_data_in;
reg cache_wr;
wire cache_wr;
 
// Word currently being fetched within a line
reg [CACHE_LINE_SIZE_WIDTH-3:0] mem_fetch_word;
137,8 → 133,7
parameter STATE_CHECK = 0;
parameter STATE_FETCH = 1;
parameter STATE_WAIT = 2;
parameter STATE_WAIT2 = 3;
parameter STATE_FLUSH = 4;
parameter STATE_FLUSH = 3;
reg [3:0] state;
 
// Tag address from input PC or flopped version of it
150,15 → 145,15
assign cache_address_rd = pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:2];
 
// Cache miss output if requested PC is not in the tag memory
assign miss_o = (!tag_data_out[CACHE_TAG_VALID_BIT] ||
wire miss = (!tag_data_out[CACHE_TAG_VALID_BIT] ||
(last_pc[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] != tag_data_out[14:0])) ? 1'b1: 1'b0;
 
// Stall the CPU if cache state machine is not idle!
wire busy = (state == STATE_CHECK & ~read_while_busy) ? 1'b0 : 1'b1;
 
// Cache output valid
assign valid_o = !miss_o && !busy_o;
assign valid_o = !miss && !busy;
 
// Stall the CPU if cache state machine is not idle!
assign busy_o = (state == STATE_CHECK & ~read_while_busy) ? 1'b0 : 1'b1;
 
// Final word to fetch from memory
wire mem_fetch_final_word = (mem_fetch_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}});
 
166,7 → 161,7
wire flush_final_line = (flush_addr == {CACHE_LINE_ADDR_WIDTH{1'b0}});
 
// Is this a cache miss?
wire cache_miss = (miss_o && // Tag lookup failed
wire cache_miss = (miss && // Tag lookup failed
!initial_fetch && // NOT initial fetch after reset
!rd_i && // NOT new read request cycle
!read_while_busy && // NOT pending read whilst busy
216,17 → 211,11
next_state_r = STATE_FETCH;
else
next_state_r = STATE_FLUSH;
end
end
//-----------------------------------------
// WAIT - Wait cycle
//-----------------------------------------
STATE_WAIT :
// Allow extra wait state to handle write & read collision
next_state_r = STATE_WAIT2;
//-----------------------------------------
// WAIT2 - Wait cycle
//-----------------------------------------
STATE_WAIT2 :
next_state_r = STATE_CHECK;
default:
;
356,36 → 345,6
end
 
//-----------------------------------------------------------------
// Cache Data Write
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
cache_address_wr<= {CACHE_DWIDTH{1'b0}};
cache_data_in <= 32'h00000000;
cache_wr <= 1'b0;
end
else
begin
cache_wr <= 1'b0;
 
// FETCH - Fetch row from memory
if (state == STATE_FETCH)
begin
// Data ready from memory?
if (wbm_ack_i)
begin
// Write data into cache
cache_address_wr <= {miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH], mem_resp_idx};
cache_data_in <= wbm_dat_i;
cache_wr <= 1'b1;
end
end
end
end
 
//-----------------------------------------------------------------
// Flush Logic
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
518,8 → 477,11
begin
// Fetch current PC line again
if (flush_final_line)
begin
wbm_addr_o <= {pc_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
begin
if (read_while_busy)
wbm_addr_o <= {miss_pc[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
else
wbm_addr_o <= {pc_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
// Incrementing linear burst
wbm_cti_o <= 3'b010;
671,9 → 633,14
.bclk_i(clk_i),
.badr_i(cache_address_wr),
.bdat_o(/*open*/),
.bdat_i(cache_data_in),
.bdat_i(wbm_dat_i),
.bwr_i(cache_wr)
);
 
// Write to cache on wishbone response
assign cache_address_wr = {miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH], mem_resp_idx};
 
assign cache_wr = (state == STATE_FETCH) & wbm_ack_i;
 
endmodule
 
/rtl/cpu/altor32_regfile_alt.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
51,8 → 51,8
input [4:0] rs_i /*verilator public*/,
input [4:0] rt_i /*verilator public*/,
input [4:0] rd_i /*verilator public*/,
output [31:0] reg_rs_o /*verilator public*/,
output [31:0] reg_rt_o /*verilator public*/,
output reg [31:0] reg_rs_o /*verilator public*/,
output reg [31:0] reg_rt_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
64,14 → 64,11
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg clk_delayed;
wire clk_delayed;
wire [31:0] data_out1;
wire [31:0] data_out2;
reg write_enable;
 
reg [31:0] reg_rs_o;
reg [31:0] reg_rt_o;
 
reg [4:0] addr_reg;
reg [31:0] data_reg;
 
/rtl/cpu/altor32_dfu.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
82,6 → 82,9
output reg [31:0] result_ra_o /*verilator public*/,
output reg [31:0] result_rb_o /*verilator public*/,
 
// Result required resolving
output reg resolved_o /*verilator public*/,
 
// Stall due to failed resolve
output reg stall_o /*verilator public*/
);
95,6 → 98,7
result_ra_o = ra_regval_i;
result_rb_o = rb_regval_i;
stall_o = 1'b0;
resolved_o = 1'b0;
 
//---------------------------------------------------------------
// RA - Hazard detection & forwarding
125,6 → 129,7
else
begin
result_ra_o = result_ex_i;
resolved_o = 1'b1;
`ifdef CONF_CORE_DEBUG
$display(" rA[%d] forwarded 0x%08x (PC-4)", ra_i, result_ra_o);
`endif
142,6 → 147,7
else
result_ra_o = result_wb_i;
 
resolved_o = 1'b1;
`ifdef CONF_CORE_DEBUG
$display(" rA[%d] forwarded 0x%08x (PC-8)", ra_i, result_ra_o);
`endif
178,6 → 184,7
else
begin
result_rb_o = result_ex_i;
resolved_o = 1'b1;
 
`ifdef CONF_CORE_DEBUG
$display(" rB[%d] forwarded 0x%08x (PC-4)", rb_i, result_rb_o);
196,6 → 203,8
else
result_rb_o = result_wb_i;
 
resolved_o = 1'b1;
 
`ifdef CONF_CORE_DEBUG
$display(" rB[%d] forwarded 0x%08x (PC-8)", rb_i, result_rb_o);
`endif
/rtl/cpu/altor32_funcs.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
85,6 → 85,7
parameter ENABLE_ICACHE = "ENABLED";
parameter ENABLE_DCACHE = "DISABLED";
parameter SUPPORT_32REGS = "ENABLED";
parameter PIPELINED_FETCH = "ENABLED";
 
//-----------------------------------------------------------------
// Registers / Wires
135,9 → 136,7
wire icache_rd;
wire [31:0] icache_pc;
wire [31:0] icache_inst;
wire icache_miss;
wire icache_valid;
wire icache_busy;
wire icache_invalidate;
 
wire [31:0] dcache_addr;
176,10 → 175,6
.valid_o(icache_valid),
.invalidate_i(icache_invalidate),
// Status
.miss_o(icache_miss),
.busy_o(icache_busy),
// Instruction memory
.wbm_addr_o(imem_addr_o),
.wbm_dat_i(imem_dat_i),
204,6 → 199,7
.pc_i(icache_pc),
.instruction_o(icache_inst),
.valid_o(icache_valid),
.invalidate_i(icache_invalidate),
// Instruction memory
.wbm_addr_o(imem_addr_o),
220,7 → 216,8
// Instruction Fetch
altor32_fetch
#(
.BOOT_VECTOR(BOOT_VECTOR)
.BOOT_VECTOR(BOOT_VECTOR),
.PIPELINED_FETCH(PIPELINED_FETCH)
)
u_fetch
(
357,7 → 354,6
end
else
begin: NO_DCACHE
 
// No data cache
assign dmem_addr_o = {dcache_addr[31:2], 2'b00};
assign dmem_dat_o = dcache_data_o;
/rtl/cpu/altor32_alu.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
36,11 → 36,6
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - ALU
//-----------------------------------------------------------------
module altor32_alu
58,10 → 53,24
 
// Carry
output reg c_o /*verilator public*/,
output reg c_update_o /*verilator public*/
output reg c_update_o /*verilator public*/,
 
// Comparison
output reg equal_o /*verilator public*/,
output reg greater_than_signed_o /*verilator public*/,
output reg greater_than_o /*verilator public*/,
output reg less_than_signed_o /*verilator public*/,
output reg less_than_o /*verilator public*/,
output flag_update_o /*verilator public*/
);
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_funcs.v"
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [31:0] result;
206,4 → 215,30
 
assign p_o = result;
 
//-----------------------------------------------------------------
// Comparisons
//-----------------------------------------------------------------
always @ *
begin
if (a_i == b_i)
equal_o = 1'b1;
else
equal_o = 1'b0;
 
if (a_i < b_i)
less_than_o = 1'b1;
else
less_than_o = 1'b0;
 
if (a_i > b_i)
greater_than_o = 1'b1;
else
greater_than_o = 1'b0;
 
less_than_signed_o = less_than_signed(a_i, b_i);
greater_than_signed_o = ~(less_than_signed_o | equal_o);
end
 
assign flag_update_o = (op_i == `ALU_COMPARE);
 
endmodule
/rtl/cpu/altor32_defs.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
48,6 → 48,7
`define ALU_AND 4'b0111
`define ALU_OR 4'b1000
`define ALU_XOR 4'b1001
`define ALU_COMPARE 4'b1010
 
//-----------------------------------------------------------------
// ALU Instructions
106,26 → 107,17
//-----------------------------------------------------------------
`define INST_OR32_SFXX 8'h39
`define INST_OR32_SFXXI 8'h2F
`define INST_OR32_SFEQ 16'h0720
`define INST_OR32_SFEQI 16'h05E0
`define INST_OR32_SFGES 16'h072B
`define INST_OR32_SFGESI 16'h05EB
`define INST_OR32_SFGEU 16'h0723
`define INST_OR32_SFGEUI 16'h05E3
`define INST_OR32_SFGTS 16'h072A
`define INST_OR32_SFGTSI 16'h05EA
`define INST_OR32_SFGTU 16'h0722
`define INST_OR32_SFGTUI 16'h05E2
`define INST_OR32_SFLES 16'h072D
`define INST_OR32_SFLESI 16'h05ED
`define INST_OR32_SFLEU 16'h0725
`define INST_OR32_SFLEUI 16'h05E5
`define INST_OR32_SFLTS 16'h072C
`define INST_OR32_SFLTSI 16'h05EC
`define INST_OR32_SFLTU 16'h0724
`define INST_OR32_SFLTUI 16'h05E4
`define INST_OR32_SFNE 16'h0721
`define INST_OR32_SFNEI 16'h05E1
`define INST_OR32_SFMASK 16'hFD3F
`define INST_OR32_SFEQ 16'h0520
`define INST_OR32_SFGES 16'h052B
`define INST_OR32_SFGEU 16'h0523
`define INST_OR32_SFGTS 16'h052A
`define INST_OR32_SFGTU 16'h0522
`define INST_OR32_SFLES 16'h052D
`define INST_OR32_SFLEU 16'h0525
`define INST_OR32_SFLTS 16'h052C
`define INST_OR32_SFLTU 16'h0524
`define INST_OR32_SFNE 16'h0521
 
//-----------------------------------------------------------------
// Misc Instructions
133,6 → 125,7
`define INST_OR32_MISC 8'h08
`define INST_OR32_SYS 8'h20
`define INST_OR32_TRAP 8'h21
`define INST_OR32_CUST1 8'h1C
 
`define INST_OR32_BUBBLE 8'h3F
`define OPCODE_INST_BUBBLE 32'hFC000000
/rtl/cpu/altor32_ram_sp.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_dcache_mem_if.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_exec.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
39,11 → 39,6
//`define CONF_CORE_TRACE
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - Instruction Execute
//-----------------------------------------------------------------
module altor32_exec
113,6 → 108,12
);
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_funcs.v"
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter BOOT_VECTOR = 32'h00000000;
125,7 → 126,6
// Branch PC
reg [31:0] r_pc_branch;
reg r_pc_fetch;
reg r_stall;
 
// Exception saved program counter
reg [31:0] r_epc;
155,12 → 155,21
// Resolved RA/RB register contents
wire [31:0] ra_value_resolved;
wire [31:0] rb_value_resolved;
wire operand_resolved;
wire resolve_failed;
 
// ALU Carry
wire alu_carry_out;
wire alu_carry_update;
wire alu_flag_update;
 
// ALU Comparisons
wire compare_equal_w;
wire compare_gts_w;
wire compare_gt_w;
wire compare_lts_w;
wire compare_lt_w;
 
// ALU operation selection
reg [3:0] r_e_alu_func;
 
213,7 → 222,15
 
// Carry
.c_o(alu_carry_out),
.c_update_o(alu_carry_update)
.c_update_o(alu_carry_update),
 
// Comparisons
.equal_o(compare_equal_w),
.greater_than_signed_o(compare_gts_w),
.greater_than_o(compare_gt_w),
.less_than_signed_o(compare_lts_w),
.less_than_o(compare_lt_w),
.flag_update_o(alu_flag_update)
);
 
// Load result forwarding
306,6 → 323,9
.result_ra_o(ra_value_resolved),
.result_rb_o(rb_value_resolved),
 
// Operands required forwarding
.resolved_o(operand_resolved),
 
// Stall due to failed resolve
.stall_o(resolve_failed)
);
335,7 → 355,7
 
// Sub instructions
alu_op_r = {opcode_i[9:6],opcode_i[3:0]};
sfxx_op_r = {5'b00,opcode_i[31:21]};
sfxx_op_r = {5'b00,opcode_i[31:21]} & `INST_OR32_SFMASK;
shift_op_r = opcode_i[7:6];
 
// Branch target
360,7 → 380,9
shift_imm_r = {26'b00,opcode_i[5:0]};
 
// MTSPR/MFSPR operand
mxspr_uint16_r = (ra_value_resolved[15:0] | {5'b00000,opcode_i[10:0]});
// NOTE: Use unresolved register value and stall pipeline if required.
// This is to improve timing.
mxspr_uint16_r = (reg_ra_value_i[15:0] | {5'b00000,opcode_i[10:0]});
end
 
//-----------------------------------------------------------------
375,6 → 397,8
wire inst_srl_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SRL); // l.srl
wire inst_sub_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SUB); // l.sub
wire inst_xor_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_XOR); // l.xor
wire inst_mul_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_MUL); // l.mul
wire inst_mulu_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_MULU); // l.mulu
 
wire inst_addi_w = (inst_r == `INST_OR32_ADDI); // l.addi
wire inst_andi_w = (inst_r == `INST_OR32_ANDI); // l.andi
410,30 → 434,18
wire inst_sfxx_w = (inst_r == `INST_OR32_SFXX);
wire inst_sfxxi_w = (inst_r == `INST_OR32_SFXXI);
 
wire inst_sfeq_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFEQ); // l.sfeq
wire inst_sfges_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGES); // l.sfges
wire inst_sfeq_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFEQ); // l.sfeq
wire inst_sfges_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGES); // l.sfges
 
wire inst_sfgeu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGEU); // l.sfgeu
wire inst_sfgts_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGTS); // l.sfgts
wire inst_sfgtu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGTU); // l.sfgtu
wire inst_sfles_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLES); // l.sfles
wire inst_sfleu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLEU); // l.sfleu
wire inst_sflts_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLTS); // l.sflts
wire inst_sfltu_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLTU); // l.sfltu
wire inst_sfne_w = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFNE); // l.sfne
wire inst_sfgeu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGEU); // l.sfgeu
wire inst_sfgts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTS); // l.sfgts
wire inst_sfgtu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTU); // l.sfgtu
wire inst_sfles_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLES); // l.sfles
wire inst_sfleu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLEU); // l.sfleu
wire inst_sflts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTS); // l.sflts
wire inst_sfltu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTU); // l.sfltu
wire inst_sfne_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFNE); // l.sfne
 
wire inst_sfeqi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFEQI); // l.sfeqi
wire inst_sfgesi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGESI); // l.sfgesi
wire inst_sfgeui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGEUI); // l.sfgeui
wire inst_sfgtsi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGTSI); // l.sfgtsi
wire inst_sfgtui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGTUI); // l.sfgtui
wire inst_sflesi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLESI); // l.sflesi
 
wire inst_sfleui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLEUI); // l.sfleui
wire inst_sfltsi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLTSI); // l.sfltsi
wire inst_sfltui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLTUI); // l.sfltui
wire inst_sfnei_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFNEI); // l.sfnei
 
wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (opcode_i[31:24] == `INST_OR32_SYS); // l.sys
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (opcode_i[31:24] == `INST_OR32_TRAP); // l.trap
 
452,7 → 464,8
if (~opcode_valid_i | r_pc_fetch)
execute_inst_r = 1'b0;
// Valid instruction, but load result / operand not ready
else if (resolve_failed | load_stall)
else if (resolve_failed | load_stall |
(operand_resolved & (inst_mfspr_w | inst_mtspr_w)))
stall_inst_r = 1'b1;
end
 
476,6 → 489,10
begin
next_sr_r = r_sr;
 
// Update SR.F
if (alu_flag_update)
next_sr_r[`OR32_SR_F] = compare_result_r;
 
// Latch carry if updated
if (alu_carry_update)
next_sr_r[`OR32_SR_CY] = alu_carry_out;
502,9 → 519,6
end
inst_rfe_w:
next_sr_r = r_esr;
inst_sfxx_w,
inst_sfxxi_w:
next_sr_r[`OR32_SR_F] = compare_result_r;
default:
;
endcase
629,8 → 643,14
alu_input_a_r = reg_ra_r;
alu_input_b_r = reg_rb_r;
write_rd_r = 1'b1;
end
end
 
inst_mul_w, // l.mul
inst_mulu_w: // l.mulu
begin
write_rd_r = 1'b1;
end
 
inst_addi_w: // l.addi
begin
alu_func_r = `ALU_ADD;
734,6 → 754,22
inst_lwz_w:
write_rd_r = 1'b1;
 
// l.sf*i
inst_sfxxi_w:
begin
alu_func_r = `ALU_COMPARE;
alu_input_a_r = reg_ra_r;
alu_input_b_r = int32_r;
end
 
// l.sf*
inst_sfxx_w:
begin
alu_func_r = `ALU_COMPARE;
alu_input_a_r = reg_ra_r;
alu_input_b_r = reg_rb_r;
end
 
inst_xori_w: // l.xori
begin
alu_func_r = `ALU_XOR;
747,110 → 783,137
end
 
//-----------------------------------------------------------------
// Comparisons
// Comparisons (from ALU outputs)
//-----------------------------------------------------------------
reg [31:0] compare_a_r;
reg [31:0] compare_b_r;
reg inst_sfges_r;
reg inst_sfgeu_r;
reg inst_sfgts_r;
reg inst_sfgtu_r;
reg inst_sfles_r;
reg inst_sfleu_r;
reg inst_sflts_r;
reg inst_sfltu_r;
reg inst_sfne_r;
reg inst_sfges_q;
reg inst_sfgeu_q;
reg inst_sfgts_q;
reg inst_sfgtu_q;
reg inst_sfles_q;
reg inst_sfleu_q;
reg inst_sflts_q;
reg inst_sfltu_q;
reg inst_sfne_q;
 
always @ *
begin
compare_a_r = reg_ra_r;
compare_b_r = reg_rb_r;
inst_sfges_r = 1'b0;
inst_sfgeu_r = 1'b0;
inst_sfgts_r = 1'b0;
inst_sfgtu_r = 1'b0;
inst_sfles_r = 1'b0;
inst_sfleu_r = 1'b0;
inst_sflts_r = 1'b0;
inst_sfltu_r = 1'b0;
inst_sfne_r = 1'b0;
 
case (1'b1)
inst_sfeqi_w, // l.sfeqi
inst_sfgesi_w, // l.sfgesi
inst_sfgeui_w, // l.sfgeui
inst_sfgtsi_w, // l.sfgtsi
inst_sfgtui_w, // l.sfgtui
inst_sflesi_w, // l.sflesi
inst_sfleui_w, // l.sfleui
inst_sfltsi_w, // l.sfltsi
inst_sfltui_w, // l.sfltui
inst_sfnei_w: // l.sfnei
compare_b_r = int32_r;
default:
;
endcase
end
// Valid instruction
if (execute_inst_r && ~stall_inst_r)
begin
 
reg compare_equal_r;
reg compare_gts_r;
reg compare_gt_r;
reg compare_lts_r;
reg compare_lt_r;
always @ *
begin
if (compare_a_r == compare_b_r)
compare_equal_r = 1'b1;
else
compare_equal_r = 1'b0;
case (1'b1)
inst_sfges_w: // l.sfges
inst_sfges_r = 1'b1;
 
compare_lts_r = less_than_signed(compare_a_r, compare_b_r);
inst_sfgeu_w: // l.sfgeu
inst_sfgeu_r = 1'b1;
 
if (compare_a_r < compare_b_r)
compare_lt_r = 1'b1;
else
compare_lt_r = 1'b0;
inst_sfgts_w: // l.sfgts
inst_sfgts_r = 1'b1;
 
// Greater than (signed)
compare_gts_r = ~(compare_lts_r | compare_equal_r);
inst_sfgtu_w: // l.sfgtu
inst_sfgtu_r = 1'b1;
 
if (compare_a_r > compare_b_r)
compare_gt_r = 1'b1;
else
compare_gt_r = 1'b0;
end
inst_sfles_w: // l.sfles
inst_sfles_r = 1'b1;
 
always @ *
begin
compare_result_r = 1'b0;
inst_sfleu_w: // l.sfleu
inst_sfleu_r = 1'b1;
 
case (1'b1)
inst_sfeq_w, // l.sfeq
inst_sfeqi_w: // l.sfeqi
compare_result_r = compare_equal_r;
inst_sflts_w: // l.sflts
inst_sflts_r = 1'b1;
 
inst_sfges_w, // l.sfges
inst_sfgesi_w: // l.sfgesi
compare_result_r = compare_gts_r | compare_equal_r;
inst_sfltu_w: // l.sfltu
inst_sfltu_r = 1'b1;
 
inst_sfgeu_w, // l.sfgeu
inst_sfgeui_w: // l.sfgeui
compare_result_r = compare_gt_r | compare_equal_r;
inst_sfne_w: // l.sfne
inst_sfne_r = 1'b1;
 
inst_sfgts_w, // l.sfgts
inst_sfgtsi_w: // l.sfgtsi
compare_result_r = compare_gts_r;
default:
;
endcase
end
end
 
inst_sfgtu_w, // l.sfgtu
inst_sfgtui_w: // l.sfgtui
compare_result_r = compare_gt_r;
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i == 1'b1)
begin
inst_sfges_q <= 1'b0;
inst_sfgeu_q <= 1'b0;
inst_sfgts_q <= 1'b0;
inst_sfgtu_q <= 1'b0;
inst_sfles_q <= 1'b0;
inst_sfleu_q <= 1'b0;
inst_sflts_q <= 1'b0;
inst_sfltu_q <= 1'b0;
inst_sfne_q <= 1'b0;
end
else
begin
inst_sfges_q <= inst_sfges_r;
inst_sfgeu_q <= inst_sfgeu_r;
inst_sfgts_q <= inst_sfgts_r;
inst_sfgtu_q <= inst_sfgtu_r;
inst_sfles_q <= inst_sfles_r;
inst_sfleu_q <= inst_sfleu_r;
inst_sflts_q <= inst_sflts_r;
inst_sfltu_q <= inst_sfltu_r;
inst_sfne_q <= inst_sfne_r;
end
end
 
inst_sfles_w, // l.sfles
inst_sflesi_w: // l.sflesi
compare_result_r = compare_lts_r | compare_equal_r;
always @ *
begin
case (1'b1)
inst_sfges_q: // l.sfges
compare_result_r = compare_gts_w | compare_equal_w;
 
inst_sfleu_w, // l.sfleu
inst_sfgeu_q: // l.sfgeu
compare_result_r = compare_gt_w | compare_equal_w;
 
inst_sfleui_w: // l.sfleui
compare_result_r = compare_lt_r | compare_equal_r;
inst_sfgts_q: // l.sfgts
compare_result_r = compare_gts_w;
 
inst_sflts_w, // l.sflts
inst_sfgtu_q: // l.sfgtu
compare_result_r = compare_gt_w;
 
inst_sfltsi_w: // l.sfltsi
compare_result_r = compare_lts_r;
inst_sfles_q: // l.sfles
compare_result_r = compare_lts_w | compare_equal_w;
 
inst_sfltu_w, // l.sfltu
inst_sfleu_q: // l.sfleu
compare_result_r = compare_lt_w | compare_equal_w;
 
inst_sfltui_w: // l.sfltui
compare_result_r = compare_lt_r;
inst_sflts_q: // l.sflts
compare_result_r = compare_lts_w;
 
inst_sfne_w, // l.sfne
inst_sfltu_q: // l.sfltu
compare_result_r = compare_lt_w;
 
inst_sfnei_w: // l.sfnei
compare_result_r = ~compare_equal_r;
default:
;
inst_sfne_q: // l.sfne
compare_result_r = ~compare_equal_w;
 
default: // l.sfeq
compare_result_r = compare_equal_w;
endcase
end
 
890,10 → 953,10
 
case (1'b1)
inst_bf_w: // l.bf
branch_r = r_sr[`OR32_SR_F];
branch_r = next_sr_r[`OR32_SR_F];
 
inst_bnf_w: // l.bnf
branch_r = ~r_sr[`OR32_SR_F];
branch_r = ~next_sr_r[`OR32_SR_F];
 
inst_j_w: // l.j
branch_r = 1'b1;
960,7 → 1023,7
inst_sra_w,
inst_srl_w,
inst_sub_w,
inst_xor_w,
inst_xor_w,
inst_addi_w,
inst_andi_w,
inst_bf_w,
989,25 → 1052,15
inst_srai_w,
inst_srli_w,
inst_sfeq_w,
inst_sfeqi_w,
inst_sfges_w,
inst_sfgesi_w,
inst_sfgeu_w,
inst_sfgeui_w,
inst_sfgts_w,
inst_sfgtsi_w,
inst_sfgtu_w,
inst_sfgtui_w,
inst_sfles_w,
inst_sflesi_w,
inst_sfleu_w,
inst_sfleui_w,
inst_sflts_w,
inst_sfltsi_w,
inst_sfltu_w,
inst_sfltui_w,
inst_sfne_w,
inst_sfnei_w,
inst_sys_w,
inst_trap_w:
invalid_inst_r = 1'b0;
1056,7 → 1109,7
//---------------------------------------------------------------
// Valid instruction
//---------------------------------------------------------------
else if (~invalid_inst_r)
else
begin
// Update ALU input flops
r_e_alu_func <= alu_func_r;
1084,13 → 1137,9
begin
r_e_opcode <= 32'h00000000;
r_e_opcode_pc <= 32'h00000000;
 
r_stall <= 1'b0;
end
else
begin
r_stall <= stall_inst_r;
 
// Instruction not ready
if (~execute_inst_r | stall_inst_r)
begin
1099,7 → 1148,7
r_e_opcode_pc <= opcode_pc_i;
end
// Valid instruction
else if (~invalid_inst_r)
else
begin
// Store opcode
r_e_opcode <= opcode_i;
1290,6 → 1339,7
 
if (dmem_ack_i)
dmem_cyc_o <= 1'b0;
 
r_mem_access <= 1'b0;
d_mem_load <= r_mem_access & r_mem_load;
 
1300,7 → 1350,7
//---------------------------------------------------------------
// Valid instruction
//---------------------------------------------------------------
if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
if (execute_inst_r & ~stall_inst_r)
begin
// Branch and link (Rd = LR/R9)
if (branch_link_r)
1463,7 → 1513,7
//---------------------------------------------------------------
// Valid instruction
//---------------------------------------------------------------
if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
if (execute_inst_r & ~stall_inst_r)
begin
case (1'b1)
inst_mtspr_w: // l.mtspr
1508,7 → 1558,7
//---------------------------------------------------------------
// Valid instruction
//---------------------------------------------------------------
if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
if (execute_inst_r & ~stall_inst_r)
begin
 
case (1'b1)
1542,7 → 1592,7
 
assign branch_pc_o = r_pc_branch;
assign branch_o = r_pc_fetch;
assign stall_o = r_stall;
assign stall_o = stall_inst_r;
 
assign opcode_o = r_e_opcode;
 
1552,8 → 1602,6
assign mult_o = 1'b0;
assign mult_res_o = 32'b0;
 
`include "altor32_funcs.v"
 
//-------------------------------------------------------------------
// Hooks for debug
//-------------------------------------------------------------------
1576,7 → 1624,7
endfunction
function [0:0] get_reg_valid;
// verilator public
get_reg_valid = ~(resolve_failed | load_stall);
get_reg_valid = ~(resolve_failed | load_stall | ~opcode_valid_i);
endfunction
function [4:0] get_reg_ra;
// verilator public
/rtl/cpu/altor32_regfile_sim.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_lfu.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_fetch.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
35,8 → 35,6
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//`define CONF_FETCH_DEBUG
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
53,7 → 51,7
 
// Instruction Fetch
output fetch_o /*verilator public*/,
output [31:0] pc_o /*verilator public*/,
output reg [31:0] pc_o /*verilator public*/,
input [31:0] data_i /*verilator public*/,
input data_valid_i/*verilator public*/,
 
78,21 → 76,19
//-----------------------------------------------------------------
parameter BOOT_VECTOR = 32'h00000000;
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
parameter PIPELINED_FETCH = "DISABLED";
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg r_rd;
reg [31:0] r_pc;
reg r_rd;
reg [31:0] r_last_opcode;
reg [31:0] r_last_pc;
reg r_last_valid;
reg [31:0] d_pc;
 
//-------------------------------------------------------------------
// Next PC state machine
//-------------------------------------------------------------------
reg [31:0] v_pc;
wire [31:0] next_pc = r_pc + 32'd4;
 
always @ (posedge clk_i or posedge rst_i)
begin
102,7 → 98,7
d_pc <= BOOT_VECTOR + `VECTOR_RESET;
r_rd <= 1'b1;
end
else
else if (~stall_i)
begin
r_rd <= 1'b0;
d_pc <= pc_o;
112,65 → 108,94
begin
r_pc <= branch_pc_i + 4;
end
// Stall - rollback to previous PC + 4
else if (stall_i)
begin
r_pc <= d_pc + 4;
end
// Normal sequential execution (and instruction is ready)
else if (data_valid_i)
begin
v_pc = r_pc + 4;
 
// New cache line?
if (v_pc[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}})
if (next_pc[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}})
begin
// Start fetch of next line
r_rd <= 1'b1;
end
 
r_pc <= v_pc;
r_pc <= next_pc;
end
end
end
 
//-------------------------------------------------------------------
// Pipeline storage of last PC/opcode passed to exec stage
// Assignments
//-------------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
 
// Instruction Fetch
always @ *
begin
if (rst_i)
begin
r_last_opcode <= 32'b0;
r_last_pc <= 32'b0;
r_last_valid <= 1'b0;
 
end
else
begin
// Record last valid instruction passed to exec stage
if (!stall_i | !data_valid_i)
begin
r_last_pc <= opcode_pc_o;
r_last_opcode <= opcode_o;
r_last_valid <= opcode_valid_o;
end
end
// Stall, revert to last requested PC
if (stall_i)
pc_o = d_pc;
else if (branch_i)
pc_o = branch_pc_i;
else if (~data_valid_i)
pc_o = d_pc;
else
pc_o = r_pc;
end
 
assign fetch_o = branch_i ? 1'b1 : r_rd;
 
//-------------------------------------------------------------------
// Assignments
// Opcode output (retiming)
//-------------------------------------------------------------------
generate
if (PIPELINED_FETCH == "ENABLED")
begin: FETCH_FLOPS
reg [31:0] r_opcode;
reg [31:0] r_opcode_pc;
reg r_opcode_valid;
reg r_branch;
 
// Instruction Fetch
assign pc_o = stall_i ? d_pc : (branch_i ? branch_pc_i : (~data_valid_i ? d_pc : r_pc));
assign fetch_o = branch_i ? 1'b1 : r_rd;
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i)
begin
r_opcode <= 32'b0;
r_opcode_pc <= 32'b0;
r_opcode_valid <= 1'b0;
r_branch <= 1'b0;
end
else
begin
r_branch <= branch_i;
 
if (~stall_i)
begin
r_opcode_pc <= d_pc;
r_opcode <= data_i;
r_opcode_valid <= (data_valid_i & !branch_i);
end
end
end
 
// Opcode output
assign opcode_valid_o = r_opcode_valid & ~branch_i & ~r_branch;
assign opcode_o = r_opcode;
assign opcode_pc_o = r_opcode_pc;
end
//-------------------------------------------------------------------
// Opcode output
assign opcode_valid_o = stall_i ? r_last_valid : (data_valid_i & !branch_i);
assign opcode_o = stall_i ? r_last_opcode : (opcode_valid_o ? data_i : 32'b0);
assign opcode_pc_o = stall_i ? r_last_pc : (opcode_valid_o ? d_pc : 32'b0);
//-------------------------------------------------------------------
else
begin : NO_FETCH_FLOPS
// Opcode output
assign opcode_valid_o = (data_valid_i & !branch_i);
assign opcode_o = data_i;
assign opcode_pc_o = d_pc;
end
endgenerate
 
//-------------------------------------------------------------------
// Opcode output
//-------------------------------------------------------------------
// If simulation, RA = 03 if NOP instruction
`ifdef SIMULATION
wire [7:0] v_fetch_inst = {2'b00, opcode_o[31:26]};
/rtl/cpu/altor32_regfile_xil.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_ram_dp.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_lsu.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// V2.1
// Ultra-Embedded.com
// Copyright 2011 - 2013
// Copyright 2011 - 2014
//
// Email: admin@ultra-embedded.com
//
36,11 → 36,6
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module: Load / Store Unit
//-----------------------------------------------------------------
module altor32_lsu
74,6 → 69,12
output reg stall_o /*verilator public*/
);
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_funcs.v"
 
//-------------------------------------------------------------------
// Outstanding memory access logic
//-------------------------------------------------------------------
154,6 → 155,4
end
end
 
`include "altor32_funcs.v"
 
endmodule

powered by: WebSVN 2.1.0

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