URL
https://opencores.org/ocsvn/altor32/altor32/trunk
Subversion Repositories altor32
Compare Revisions
- This comparison shows the changes necessary to convert path
/altor32/trunk/rtl/cpu
- from Rev 32 to Rev 36
- ↔ Reverse comparison
Rev 32 → Rev 36
/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]), |
/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 |
|
/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 |
// |
/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 |
|
/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; |
|
/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 |
/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 |
// |
/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; |
/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 |
/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 |
/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 |
// |
/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 |
// |
/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 |
/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 |
// |
/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 |
// |
/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]}; |
/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 |
// |
/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 |
// |
/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 |