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 36 to Rev 35
    Reverse comparison

Rev 36 → Rev 35

/rtl/cpu_lite/altor32_regfile_sim.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu_lite/altor32_regfile_xil.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu_lite/altor32_lite.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
120,14 → 120,6
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;
 
182,15 → 174,7
 
// Carry
.c_o(alu_carry_out),
.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)
.c_update_o(alu_carry_update)
);
 
// Writeback result
294,7 → 278,7
 
// Sub instructions
alu_op_r = {r_opcode[9:6],r_opcode[3:0]};
sfxx_op_r = {5'b00,r_opcode[31:21]} & `INST_OR32_SFMASK;
sfxx_op_r = {5'b00,r_opcode[31:21]};
shift_op_r = r_opcode[7:6];
 
// Branch target
371,18 → 355,30
wire inst_sfxx_w = (inst_r == `INST_OR32_SFXX);
wire inst_sfxxi_w = (inst_r == `INST_OR32_SFXXI);
 
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_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_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_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_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
 
689,10 → 685,6
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;
952,22 → 944,6
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,
992,39 → 968,107
//-----------------------------------------------------------------
// 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_sfges_w: // l.sfges
compare_result_r = compare_gts_w | compare_equal_w;
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_sfgeu_w: // l.sfgeu
compare_result_r = compare_gt_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_sfgts_w: // l.sfgts
compare_result_r = compare_gts_w;
compare_lts_r = less_than_signed(compare_a_r, compare_b_r);
 
inst_sfgtu_w: // l.sfgtu
compare_result_r = compare_gt_w;
if (compare_a_r < compare_b_r)
compare_lt_r = 1'b1;
else
compare_lt_r = 1'b0;
 
inst_sfles_w: // l.sfles
compare_result_r = compare_lts_w | compare_equal_w;
// Greater than (signed)
compare_gts_r = ~(compare_lts_r | compare_equal_r);
 
inst_sfleu_w: // l.sfleu
compare_result_r = compare_lt_w | compare_equal_w;
if (compare_a_r > compare_b_r)
compare_gt_r = 1'b1;
else
compare_gt_r = 1'b0;
end
 
inst_sflts_w: // l.sflts
compare_result_r = compare_lts_w;
always @ *
begin
compare_result_r = 1'b0;
 
inst_sfltu_w: // l.sfltu
compare_result_r = compare_lt_w;
case (1'b1)
inst_sfeq_w, // l.sfeq
inst_sfeqi_w: // l.sfeqi
compare_result_r = compare_equal_r;
 
inst_sfne_w: // l.sfne
compare_result_r = ~compare_equal_w;
inst_sfges_w, // l.sfges
inst_sfgesi_w: // l.sfgesi
compare_result_r = compare_gts_r | compare_equal_r;
 
default: // l.sfeq
compare_result_r = compare_equal_w;
endcase
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
end
 
//-----------------------------------------------------------------
1146,15 → 1190,25
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.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// 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 reg [31:0] reg_rs_o /*verilator public*/,
output reg [31:0] reg_rt_o /*verilator public*/,
output [31:0] reg_rs_o /*verilator public*/,
output [31:0] reg_rt_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
64,11 → 64,14
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
wire clk_delayed;
reg 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.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu_lite/altor32.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu_lite/altor32_alu.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
39,7 → 39,6
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_funcs.v"
 
//-----------------------------------------------------------------
// Module - ALU
59,15 → 58,7
 
// Carry
output reg c_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*/
output reg c_update_o /*verilator public*/
);
 
//-----------------------------------------------------------------
215,30 → 206,4
 
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.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
48,7 → 48,6
`define ALU_AND 4'b0111
`define ALU_OR 4'b1000
`define ALU_XOR 4'b1001
`define ALU_COMPARE 4'b1010
 
//-----------------------------------------------------------------
// ALU Instructions
107,17 → 106,26
//-----------------------------------------------------------------
`define INST_OR32_SFXX 8'h39
`define INST_OR32_SFXXI 8'h2F
`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
`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
 
//-----------------------------------------------------------------
// Misc Instructions
/rtl/cpu/altor32_dcache.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
91,8 → 91,6
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
// |--------------| | | | | | | | | | | | | | | | |
// +--------------------+ +-------------------+ +-----------+
135,7 → 133,6
reg [31:0] req_data;
 
reg req_flush;
reg req_init;
reg flush_single;
 
wire [31:0] line_address;
163,7 → 160,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 | flush_i;
assign stall_o = (state != STATE_IDLE) | req_flush;
 
wire valid = tag_data_out[CACHE_TAG_VALID_BIT];
wire dirty = tag_data_out[CACHE_TAG_DIRTY_BIT];
179,13 → 176,10
 
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
218,16 → 212,13
next_state_r = STATE_WRITE;
end
//-----------------------------------------
// WRITE
// WRITE - Wait for write-thru to complete
//-----------------------------------------
STATE_WRITE :
begin
// 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 hit
if (valid & addr_hit)
next_state_r = STATE_WAIT2;
// Cache dirty
else if (valid & dirty)
next_state_r = STATE_EVICTING;
352,7 → 343,7
STATE_FLUSH3 :
begin
// Dirty line? Evict line first
if (dirty && ~req_init)
if (dirty)
next_state_r = STATE_FLUSH4;
// Not dirty? Just invalidate
else
408,7 → 399,7
 
case (state)
//-----------------------------------------
// WRITE
// WRITE - Wait for write-thru to complete
//-----------------------------------------
STATE_WRITE :
begin
416,12 → 407,9
if (valid & addr_hit)
begin
// Mark line as dirty
if (~dirty)
begin
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
tag_wr <= 1'b1;
end
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
tag_wr <= 1'b1;
end
// Cache miss / cache line doesn't require write back
else if (~valid | ~dirty)
511,9 → 499,9
STATE_FLUSH3 :
begin
// Not dirty? Just invalidate
if (~dirty | req_init)
if (~dirty)
begin
tag_data_in <= 16'b0;
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_wr <= 1'b1;
end
527,7 → 515,7
if (done)
begin
// Invalidate line
tag_data_in <= 16'b0;
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b0;
tag_wr <= 1'b1;
551,8 → 539,7
req_ack <= 1'b0;
req_wr <= 4'h0;
req_rd <= 1'b0;
req_flush <= 1'b1;
req_init <= FLUSH_INITIAL;
req_flush <= 1'b0;
end
else
begin
620,7 → 607,6
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
651,17 → 637,17
 
case (state)
//-----------------------------------------
// IDLE
// WRITE - Wait for write-thru to complete
//-----------------------------------------
STATE_IDLE:
begin
// Write (cacheable)
if (stb_i & we_i & cacheable & ~(flush_i | req_flush))
STATE_WRITE :
begin
// Cache hit
if (valid & addr_hit)
begin
// Early write which is gated on line match
cache_data_w <= data_i;
cache_wr <= sel_i;
end
// Update line already in cache
cache_data_w <= req_data;
cache_wr <= req_wr;
end
end
//-----------------------------------------
// UPDATE - Update fetched cache line
729,7 → 715,7
end
end
//-----------------------------------------
// WRITE
// WRITE - Wait for write-thru to complete
//-----------------------------------------
STATE_WRITE :
begin
963,7 → 949,7
.aadr_i(cache_address),
.adat_o(cache_data_r[7:0]),
.adat_i(cache_data_w[7:0]),
.awr_i(cache_wr[0] & cache_wr_enable),
.awr_i(cache_wr[0]),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
983,7 → 969,7
.aadr_i(cache_address),
.adat_o(cache_data_r[15:8]),
.adat_i(cache_data_w[15:8]),
.awr_i(cache_wr[1] & cache_wr_enable),
.awr_i(cache_wr[1]),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
1003,7 → 989,7
.aadr_i(cache_address),
.adat_o(cache_data_r[23:16]),
.adat_i(cache_data_w[23:16]),
.awr_i(cache_wr[2] & cache_wr_enable),
.awr_i(cache_wr[2]),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
1023,7 → 1009,7
.aadr_i(cache_address),
.adat_o(cache_data_r[31:24]),
.adat_i(cache_data_w[31:24]),
.awr_i(cache_wr[3] & cache_wr_enable),
.awr_i(cache_wr[3]),
.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.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
53,9 → 53,6
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*/,
140,3 → 137,4
assign wbm_cti_o = 3'b111;
 
endmodule
 
/rtl/cpu/altor32_icache.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
55,6 → 55,10
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*/,
108,9 → 112,9
 
// Data memory read / write
wire [CACHE_DWIDTH-1:0] cache_address_rd;
wire [CACHE_DWIDTH-1:0] cache_address_wr;
reg [CACHE_DWIDTH-1:0] cache_address_wr;
reg [31:0] cache_data_in;
wire cache_wr;
reg cache_wr;
 
// Word currently being fetched within a line
reg [CACHE_LINE_SIZE_WIDTH-3:0] mem_fetch_word;
133,7 → 137,8
parameter STATE_CHECK = 0;
parameter STATE_FETCH = 1;
parameter STATE_WAIT = 2;
parameter STATE_FLUSH = 3;
parameter STATE_WAIT2 = 3;
parameter STATE_FLUSH = 4;
reg [3:0] state;
 
// Tag address from input PC or flopped version of it
145,15 → 150,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
wire miss = (!tag_data_out[CACHE_TAG_VALID_BIT] ||
assign miss_o = (!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;
 
// Cache output valid
assign valid_o = !miss_o && !busy_o;
 
// Stall the CPU if cache state machine is not idle!
wire busy = (state == STATE_CHECK & ~read_while_busy) ? 1'b0 : 1'b1;
assign busy_o = (state == STATE_CHECK & ~read_while_busy) ? 1'b0 : 1'b1;
 
// Cache output valid
assign valid_o = !miss && !busy;
 
// Final word to fetch from memory
wire mem_fetch_final_word = (mem_fetch_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}});
 
161,7 → 166,7
wire flush_final_line = (flush_addr == {CACHE_LINE_ADDR_WIDTH{1'b0}});
 
// Is this a cache miss?
wire cache_miss = (miss && // Tag lookup failed
wire cache_miss = (miss_o && // 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
211,11 → 216,17
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:
;
345,6 → 356,36
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 )
477,11 → 518,8
begin
// Fetch current PC line again
if (flush_final_line)
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}}};
begin
wbm_addr_o <= {pc_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
// Incrementing linear burst
wbm_cti_o <= 3'b010;
633,14 → 671,9
.bclk_i(clk_i),
.badr_i(cache_address_wr),
.bdat_o(/*open*/),
.bdat_i(wbm_dat_i),
.bdat_i(cache_data_in),
.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.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
85,7 → 85,6
parameter ENABLE_ICACHE = "ENABLED";
parameter ENABLE_DCACHE = "DISABLED";
parameter SUPPORT_32REGS = "ENABLED";
parameter PIPELINED_FETCH = "ENABLED";
 
//-----------------------------------------------------------------
// Registers / Wires
136,7 → 135,9
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;
175,6 → 176,10
.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),
199,7 → 204,6
.pc_i(icache_pc),
.instruction_o(icache_inst),
.valid_o(icache_valid),
.invalidate_i(icache_invalidate),
// Instruction memory
.wbm_addr_o(imem_addr_o),
216,8 → 220,7
// Instruction Fetch
altor32_fetch
#(
.BOOT_VECTOR(BOOT_VECTOR),
.PIPELINED_FETCH(PIPELINED_FETCH)
.BOOT_VECTOR(BOOT_VECTOR)
)
u_fetch
(
354,6 → 357,7
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_dcache_mem_if.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_exec.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
39,6 → 39,11
//`define CONF_CORE_TRACE
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - Instruction Execute
//-----------------------------------------------------------------
module altor32_exec
108,12 → 113,6
);
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_funcs.v"
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter BOOT_VECTOR = 32'h00000000;
126,6 → 125,7
// 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,21 → 155,12
// 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;
 
222,15 → 213,7
 
// Carry
.c_o(alu_carry_out),
.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)
.c_update_o(alu_carry_update)
);
 
// Load result forwarding
323,9 → 306,6
.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)
);
355,7 → 335,7
 
// Sub instructions
alu_op_r = {opcode_i[9:6],opcode_i[3:0]};
sfxx_op_r = {5'b00,opcode_i[31:21]} & `INST_OR32_SFMASK;
sfxx_op_r = {5'b00,opcode_i[31:21]};
shift_op_r = opcode_i[7:6];
 
// Branch target
380,9 → 360,7
shift_imm_r = {26'b00,opcode_i[5:0]};
 
// MTSPR/MFSPR operand
// 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]});
mxspr_uint16_r = (ra_value_resolved[15:0] | {5'b00000,opcode_i[10:0]});
end
 
//-----------------------------------------------------------------
397,8 → 375,6
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
434,18 → 410,30
wire inst_sfxx_w = (inst_r == `INST_OR32_SFXX);
wire inst_sfxxi_w = (inst_r == `INST_OR32_SFXXI);
 
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_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_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_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_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
 
464,8 → 452,7
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 |
(operand_resolved & (inst_mfspr_w | inst_mtspr_w)))
else if (resolve_failed | load_stall)
stall_inst_r = 1'b1;
end
 
489,10 → 476,6
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;
519,6 → 502,9
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
643,14 → 629,8
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;
754,22 → 734,6
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;
783,137 → 747,110
end
 
//-----------------------------------------------------------------
// Comparisons (from ALU outputs)
// Comparisons
//-----------------------------------------------------------------
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;
 
reg [31:0] compare_a_r;
reg [31:0] compare_b_r;
always @ *
begin
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;
compare_a_r = reg_ra_r;
compare_b_r = reg_rb_r;
 
// Valid instruction
if (execute_inst_r && ~stall_inst_r)
begin
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
 
case (1'b1)
inst_sfges_w: // l.sfges
inst_sfges_r = 1'b1;
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
inst_sfgeu_r = 1'b1;
compare_lts_r = less_than_signed(compare_a_r, compare_b_r);
 
inst_sfgts_w: // l.sfgts
inst_sfgts_r = 1'b1;
if (compare_a_r < compare_b_r)
compare_lt_r = 1'b1;
else
compare_lt_r = 1'b0;
 
inst_sfgtu_w: // l.sfgtu
inst_sfgtu_r = 1'b1;
// Greater than (signed)
compare_gts_r = ~(compare_lts_r | compare_equal_r);
 
inst_sfles_w: // l.sfles
inst_sfles_r = 1'b1;
if (compare_a_r > compare_b_r)
compare_gt_r = 1'b1;
else
compare_gt_r = 1'b0;
end
 
inst_sfleu_w: // l.sfleu
inst_sfleu_r = 1'b1;
always @ *
begin
compare_result_r = 1'b0;
 
inst_sflts_w: // l.sflts
inst_sflts_r = 1'b1;
case (1'b1)
inst_sfeq_w, // l.sfeq
inst_sfeqi_w: // l.sfeqi
compare_result_r = compare_equal_r;
 
inst_sfltu_w: // l.sfltu
inst_sfltu_r = 1'b1;
inst_sfges_w, // l.sfges
inst_sfgesi_w: // l.sfgesi
compare_result_r = compare_gts_r | compare_equal_r;
 
inst_sfne_w: // l.sfne
inst_sfne_r = 1'b1;
inst_sfgeu_w, // l.sfgeu
inst_sfgeui_w: // l.sfgeui
compare_result_r = compare_gt_r | compare_equal_r;
 
default:
;
endcase
end
end
inst_sfgts_w, // l.sfgts
inst_sfgtsi_w: // l.sfgtsi
compare_result_r = compare_gts_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_sfgtu_w, // l.sfgtu
inst_sfgtui_w: // l.sfgtui
compare_result_r = compare_gt_r;
 
always @ *
begin
case (1'b1)
inst_sfges_q: // l.sfges
compare_result_r = compare_gts_w | compare_equal_w;
inst_sfles_w, // l.sfles
inst_sflesi_w: // l.sflesi
compare_result_r = compare_lts_r | compare_equal_r;
 
inst_sfgeu_q: // l.sfgeu
compare_result_r = compare_gt_w | compare_equal_w;
inst_sfleu_w, // l.sfleu
 
inst_sfgts_q: // l.sfgts
compare_result_r = compare_gts_w;
inst_sfleui_w: // l.sfleui
compare_result_r = compare_lt_r | compare_equal_r;
 
inst_sfgtu_q: // l.sfgtu
compare_result_r = compare_gt_w;
inst_sflts_w, // l.sflts
 
inst_sfles_q: // l.sfles
compare_result_r = compare_lts_w | compare_equal_w;
inst_sfltsi_w: // l.sfltsi
compare_result_r = compare_lts_r;
 
inst_sfleu_q: // l.sfleu
compare_result_r = compare_lt_w | compare_equal_w;
inst_sfltu_w, // l.sfltu
 
inst_sflts_q: // l.sflts
compare_result_r = compare_lts_w;
inst_sfltui_w: // l.sfltui
compare_result_r = compare_lt_r;
 
inst_sfltu_q: // l.sfltu
compare_result_r = compare_lt_w;
inst_sfne_w, // l.sfne
 
inst_sfne_q: // l.sfne
compare_result_r = ~compare_equal_w;
 
default: // l.sfeq
compare_result_r = compare_equal_w;
inst_sfnei_w: // l.sfnei
compare_result_r = ~compare_equal_r;
default:
;
endcase
end
 
953,10 → 890,10
 
case (1'b1)
inst_bf_w: // l.bf
branch_r = next_sr_r[`OR32_SR_F];
branch_r = r_sr[`OR32_SR_F];
 
inst_bnf_w: // l.bnf
branch_r = ~next_sr_r[`OR32_SR_F];
branch_r = ~r_sr[`OR32_SR_F];
 
inst_j_w: // l.j
branch_r = 1'b1;
1023,7 → 960,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,
1052,15 → 989,25
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;
1109,7 → 1056,7
//---------------------------------------------------------------
// Valid instruction
//---------------------------------------------------------------
else
else if (~invalid_inst_r)
begin
// Update ALU input flops
r_e_alu_func <= alu_func_r;
1137,9 → 1084,13
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
1148,7 → 1099,7
r_e_opcode_pc <= opcode_pc_i;
end
// Valid instruction
else
else if (~invalid_inst_r)
begin
// Store opcode
r_e_opcode <= opcode_i;
1339,7 → 1290,6
 
if (dmem_ack_i)
dmem_cyc_o <= 1'b0;
 
r_mem_access <= 1'b0;
d_mem_load <= r_mem_access & r_mem_load;
 
1350,7 → 1300,7
//---------------------------------------------------------------
// Valid instruction
//---------------------------------------------------------------
if (execute_inst_r & ~stall_inst_r)
if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
begin
// Branch and link (Rd = LR/R9)
if (branch_link_r)
1513,7 → 1463,7
//---------------------------------------------------------------
// Valid instruction
//---------------------------------------------------------------
if (execute_inst_r & ~stall_inst_r)
if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
begin
case (1'b1)
inst_mtspr_w: // l.mtspr
1558,7 → 1508,7
//---------------------------------------------------------------
// Valid instruction
//---------------------------------------------------------------
if (execute_inst_r & ~stall_inst_r)
if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
begin
 
case (1'b1)
1592,7 → 1542,7
 
assign branch_pc_o = r_pc_branch;
assign branch_o = r_pc_fetch;
assign stall_o = stall_inst_r;
assign stall_o = r_stall;
 
assign opcode_o = r_e_opcode;
 
1602,6 → 1552,8
assign mult_o = 1'b0;
assign mult_res_o = 32'b0;
 
`include "altor32_funcs.v"
 
//-------------------------------------------------------------------
// Hooks for debug
//-------------------------------------------------------------------
1624,7 → 1576,7
endfunction
function [0:0] get_reg_valid;
// verilator public
get_reg_valid = ~(resolve_failed | load_stall | ~opcode_valid_i);
get_reg_valid = ~(resolve_failed | load_stall);
endfunction
function [4:0] get_reg_ra;
// verilator public
/rtl/cpu/altor32_regfile_sim.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_defs.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
48,7 → 48,6
`define ALU_AND 4'b0111
`define ALU_OR 4'b1000
`define ALU_XOR 4'b1001
`define ALU_COMPARE 4'b1010
 
//-----------------------------------------------------------------
// ALU Instructions
107,17 → 106,26
//-----------------------------------------------------------------
`define INST_OR32_SFXX 8'h39
`define INST_OR32_SFXXI 8'h2F
`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
`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
 
//-----------------------------------------------------------------
// Misc Instructions
125,7 → 133,6
`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.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_ram_dp.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_writeback.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_regfile_alt.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// 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 reg [31:0] reg_rs_o /*verilator public*/,
output reg [31:0] reg_rt_o /*verilator public*/,
output [31:0] reg_rs_o /*verilator public*/,
output [31:0] reg_rt_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
64,11 → 64,14
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
wire clk_delayed;
reg 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.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
82,9 → 82,6
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*/
);
98,7 → 95,6
result_ra_o = ra_regval_i;
result_rb_o = rb_regval_i;
stall_o = 1'b0;
resolved_o = 1'b0;
 
//---------------------------------------------------------------
// RA - Hazard detection & forwarding
129,7 → 125,6
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
147,7 → 142,6
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
184,7 → 178,6
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);
203,8 → 196,6
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.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_alu.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
36,6 → 36,11
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - ALU
//-----------------------------------------------------------------
module altor32_alu
53,24 → 58,10
 
// Carry
output reg c_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*/
output reg c_update_o /*verilator public*/
);
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_funcs.v"
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [31:0] result;
215,30 → 206,4
 
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_lfu.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_fetch.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
35,6 → 35,8
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//`define CONF_FETCH_DEBUG
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
51,7 → 53,7
 
// Instruction Fetch
output fetch_o /*verilator public*/,
output reg [31:0] pc_o /*verilator public*/,
output [31:0] pc_o /*verilator public*/,
input [31:0] data_i /*verilator public*/,
input data_valid_i/*verilator public*/,
 
76,19 → 78,21
//-----------------------------------------------------------------
parameter BOOT_VECTOR = 32'h00000000;
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
parameter PIPELINED_FETCH = "DISABLED";
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [31:0] r_pc;
reg r_rd;
reg [31:0] r_pc;
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
//-------------------------------------------------------------------
wire [31:0] next_pc = r_pc + 32'd4;
reg [31:0] v_pc;
 
always @ (posedge clk_i or posedge rst_i)
begin
98,7 → 102,7
d_pc <= BOOT_VECTOR + `VECTOR_RESET;
r_rd <= 1'b1;
end
else if (~stall_i)
else
begin
r_rd <= 1'b0;
d_pc <= pc_o;
108,94 → 112,65
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 (next_pc[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}})
if (v_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 <= next_pc;
r_pc <= v_pc;
end
end
end
 
//-------------------------------------------------------------------
// Assignments
// Pipeline storage of last PC/opcode passed to exec stage
//-------------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i)
begin
r_last_opcode <= 32'b0;
r_last_pc <= 32'b0;
r_last_valid <= 1'b0;
 
// Instruction Fetch
always @ *
begin
// 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
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
end
 
assign fetch_o = branch_i ? 1'b1 : r_rd;
 
//-------------------------------------------------------------------
// Opcode output (retiming)
// Assignments
//-------------------------------------------------------------------
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;
 
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;
// 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;
 
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
//-------------------------------------------------------------------
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
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);
 
//-------------------------------------------------------------------
// 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.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
/rtl/cpu/altor32_lsu.v
1,9 → 1,9
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.1
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2014
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
36,6 → 36,11
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module: Load / Store Unit
//-----------------------------------------------------------------
module altor32_lsu
69,12 → 74,6
output reg stall_o /*verilator public*/
);
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_funcs.v"
 
//-------------------------------------------------------------------
// Outstanding memory access logic
//-------------------------------------------------------------------
155,4 → 154,6
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.