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 31 to Rev 32
    Reverse comparison

Rev 31 → Rev 32

/rtl/soc/dmem_mux3.v
1,3 → 1,39
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module:
5,40 → 41,50
module dmem_mux3
(
// Outputs
out0_addr_o,
out0_data_o,
out0_data_i,
out0_wr_o,
out0_rd_o,
out0_burst_o,
out0_ack_i,
out0_accept_i,
out1_addr_o,
out1_data_o,
out1_data_i,
out1_wr_o,
out1_rd_o,
out1_burst_o,
out1_ack_i,
out1_accept_i,
out2_addr_o,
out2_data_o,
out2_data_i,
out2_wr_o,
out2_rd_o,
out2_burst_o,
out2_ack_i,
out2_accept_i,
output reg [31:0] out0_addr_o,
output reg [31:0] out0_data_o,
input [31:0] out0_data_i,
output reg [3:0] out0_sel_o,
output reg out0_we_o,
output reg out0_stb_o,
output reg out0_cyc_o,
output reg [2:0] out0_cti_o,
input out0_ack_i,
input out0_stall_i,
 
output reg [31:0] out1_addr_o,
output reg [31:0] out1_data_o,
input [31:0] out1_data_i,
output reg [3:0] out1_sel_o,
output reg out1_we_o,
output reg out1_stb_o,
output reg out1_cyc_o,
output reg [2:0] out1_cti_o,
input out1_ack_i,
input out1_stall_i,
 
output reg [31:0] out2_addr_o,
output reg [31:0] out2_data_o,
input [31:0] out2_data_i,
output reg [3:0] out2_sel_o,
output reg out2_we_o,
output reg out2_stb_o,
output reg out2_cyc_o,
output reg [2:0] out2_cti_o,
input out2_ack_i,
input out2_stall_i,
 
// Input
mem_addr_i,
mem_data_i,
mem_data_o,
mem_burst_i,
mem_wr_i,
mem_rd_i,
mem_ack_o,
mem_accept_o
input [31:0] mem_addr_i,
input [31:0] mem_data_i,
output reg[31:0] mem_data_o,
input [3:0] mem_sel_i,
input mem_we_i,
input mem_stb_i,
input mem_cyc_i,
input [2:0] mem_cti_i,
output reg mem_ack_o,
output reg mem_stall_o
);
 
//-----------------------------------------------------------------
47,87 → 93,32
parameter ADDR_MUX_START = 28;
 
//-----------------------------------------------------------------
// I/O
// Request
//-----------------------------------------------------------------
input [31:0] mem_addr_i /*verilator public*/;
input [31:0] mem_data_i /*verilator public*/;
output [31:0] mem_data_o /*verilator public*/;
input [3:0] mem_wr_i /*verilator public*/;
input mem_rd_i /*verilator public*/;
input mem_burst_i /*verilator public*/;
output mem_ack_o /*verilator public*/;
output mem_accept_o /*verilator public*/;
output [31:0] out0_addr_o /*verilator public*/;
output [31:0] out0_data_o /*verilator public*/;
input [31:0] out0_data_i /*verilator public*/;
output [3:0] out0_wr_o /*verilator public*/;
output out0_rd_o /*verilator public*/;
output out0_burst_o /*verilator public*/;
input out0_ack_i /*verilator public*/;
input out0_accept_i /*verilator public*/;
output [31:0] out1_addr_o /*verilator public*/;
output [31:0] out1_data_o /*verilator public*/;
input [31:0] out1_data_i /*verilator public*/;
output [3:0] out1_wr_o /*verilator public*/;
output out1_rd_o /*verilator public*/;
output out1_burst_o /*verilator public*/;
input out1_ack_i /*verilator public*/;
input out1_accept_i /*verilator public*/;
output [31:0] out2_addr_o /*verilator public*/;
output [31:0] out2_data_o /*verilator public*/;
input [31:0] out2_data_i /*verilator public*/;
output [3:0] out2_wr_o /*verilator public*/;
output out2_rd_o /*verilator public*/;
output out2_burst_o /*verilator public*/;
input out2_ack_i /*verilator public*/;
input out2_accept_i /*verilator public*/;
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
 
// Output Signals
reg mem_ack_o;
reg mem_accept_o;
reg [31:0] mem_data_o;
 
reg [31:0] out0_addr_o;
reg [31:0] out0_data_o;
reg [3:0] out0_wr_o;
reg out0_rd_o;
reg out0_burst_o;
reg [31:0] out1_addr_o;
reg [31:0] out1_data_o;
reg [3:0] out1_wr_o;
reg out1_rd_o;
reg out1_burst_o;
reg [31:0] out2_addr_o;
reg [31:0] out2_data_o;
reg [3:0] out2_wr_o;
reg out2_rd_o;
reg out2_burst_o;
 
//-----------------------------------------------------------------
// Memory Map
//-----------------------------------------------------------------
always @ (mem_addr_i or mem_wr_i or mem_rd_i or mem_data_i or mem_burst_i)
always @ *
begin
 
out0_addr_o = 32'h00000000;
out0_wr_o = 4'b0000;
out0_rd_o = 1'b0;
out0_data_o = 32'h00000000;
out0_burst_o = 1'b0;
out0_sel_o = 4'b0000;
out0_we_o = 1'b0;
out0_stb_o = 1'b0;
out0_cyc_o = 1'b0;
out0_cti_o = 3'b0;
out1_addr_o = 32'h00000000;
out1_wr_o = 4'b0000;
out1_rd_o = 1'b0;
out1_data_o = 32'h00000000;
out1_burst_o = 1'b0;
out1_sel_o = 4'b0000;
out1_we_o = 1'b0;
out1_stb_o = 1'b0;
out1_cyc_o = 1'b0;
out1_cti_o = 3'b0;
out2_addr_o = 32'h00000000;
out2_wr_o = 4'b0000;
out2_rd_o = 1'b0;
out2_data_o = 32'h00000000;
out2_burst_o = 1'b0;
out2_sel_o = 4'b0000;
out2_we_o = 1'b0;
out2_stb_o = 1'b0;
out2_cyc_o = 1'b0;
out2_cti_o = 3'b0;
 
case (mem_addr_i[ADDR_MUX_START+2-1:ADDR_MUX_START])
 
134,26 → 125,32
2'd0:
begin
out0_addr_o = mem_addr_i;
out0_wr_o = mem_wr_i;
out0_rd_o = mem_rd_i;
out0_data_o = mem_data_i;
out0_burst_o = mem_burst_i;
out0_sel_o = mem_sel_i;
out0_we_o = mem_we_i;
out0_stb_o = mem_stb_i;
out0_cyc_o = mem_cyc_i;
out0_cti_o = mem_cti_i;
end
2'd1:
begin
out1_addr_o = mem_addr_i;
out1_wr_o = mem_wr_i;
out1_rd_o = mem_rd_i;
out1_data_o = mem_data_i;
out1_burst_o = mem_burst_i;
out1_sel_o = mem_sel_i;
out1_we_o = mem_we_i;
out1_stb_o = mem_stb_i;
out1_cyc_o = mem_cyc_i;
out1_cti_o = mem_cti_i;
end
2'd2:
begin
out2_addr_o = mem_addr_i;
out2_wr_o = mem_wr_i;
out2_rd_o = mem_rd_i;
out2_data_o = mem_data_i;
out2_burst_o = mem_burst_i;
out2_sel_o = mem_sel_i;
out2_we_o = mem_we_i;
out2_stb_o = mem_stb_i;
out2_cyc_o = mem_cyc_i;
out2_cti_o = mem_cti_i;
end
 
default :
162,7 → 159,7
end
 
//-----------------------------------------------------------------
// Read Port
// Response
//-----------------------------------------------------------------
always @ *
begin
171,19 → 168,19
2'd0:
begin
mem_data_o = out0_data_i;
mem_accept_o = out0_accept_i;
mem_stall_o = out0_stall_i;
mem_ack_o = out0_ack_i;
end
2'd1:
begin
mem_data_o = out1_data_i;
mem_accept_o = out1_accept_i;
mem_stall_o = out1_stall_i;
mem_ack_o = out1_ack_i;
end
2'd2:
begin
mem_data_o = out2_data_i;
mem_accept_o = out2_accept_i;
mem_stall_o = out2_stall_i;
mem_ack_o = out2_ack_i;
end
 
190,7 → 187,7
default :
begin
mem_data_o = 32'h00000000;
mem_accept_o = 1'b0;
mem_stall_o = 1'b0;
mem_ack_o = 1'b0;
end
endcase
/rtl/soc/soc.v
1,3 → 1,39
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module:
10,20 → 46,13
ext_intr_i,
intr_o,
 
 
 
 
 
 
 
 
 
// Memory interface
io_addr_i,
io_data_i,
io_data_o,
io_wr_i,
io_rd_i
io_we_i,
io_stb_i,
io_ack_o
);
 
//-----------------------------------------------------------------
30,9 → 59,6
// Params
//-----------------------------------------------------------------
parameter [31:0] CLK_KHZ = 12288;
parameter [31:0] UART_BAUD = 115200;
parameter [31:0] SPI_FLASH_CLK_KHZ = (12288/2);
parameter SD_CLK_KHZ = 8000;
parameter [31:0] EXTERNAL_INTERRUPTS = 1;
parameter SYSTICK_INTR_MS = 1;
parameter ENABLE_SYSTICK_TIMER = "ENABLED";
46,37 → 72,22
input [(EXTERNAL_INTERRUPTS - 1):0] ext_intr_i /*verilator public*/;
output intr_o /*verilator public*/;
 
 
// Memory Port
input [31:0] io_addr_i /*verilator public*/;
input [31:0] io_data_i /*verilator public*/;
output [31:0] io_data_o /*verilator public*/;
input [3:0] io_wr_i /*verilator public*/;
input io_rd_i /*verilator public*/;
input io_we_i /*verilator public*/;
input io_stb_i /*verilator public*/;
output io_ack_o /*verilator public*/;
 
 
 
 
 
 
 
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
 
 
 
 
 
 
 
 
wire [7:0] timer_addr;
wire [31:0] timer_data_o;
wire [31:0] timer_data_i;
wire [3:0] timer_wr;
wire timer_rd;
wire timer_we;
wire timer_stb;
wire timer_intr_systick;
wire timer_intr_hires;
 
83,8 → 94,8
wire [7:0] intr_addr;
wire [31:0] intr_data_o;
wire [31:0] intr_data_i;
wire [3:0] intr_wr;
wire intr_rd;
wire intr_we;
wire intr_stb;
 
//-----------------------------------------------------------------
// Peripheral Interconnect
101,8 → 112,9
.io_addr_i(io_addr_i),
.io_data_i(io_data_i),
.io_data_o(io_data_o),
.io_wr_i(io_wr_i),
.io_rd_i(io_rd_i),
.io_we_i(io_we_i),
.io_stb_i(io_stb_i),
.io_ack_o(io_ack_o),
 
// Peripherals
// Unused = 0x12000000 - 0x120000FF
109,88 → 121,60
.periph0_addr_o(/*open*/),
.periph0_data_o(/*open*/),
.periph0_data_i(32'h00000000),
.periph0_wr_o(/*open*/),
.periph0_rd_o(/*open*/),
.periph0_we_o(/*open*/),
.periph0_stb_o(/*open*/),
 
// Timer = 0x12000100 - 0x120001FF
.periph1_addr_o(timer_addr),
.periph1_data_o(timer_data_o),
.periph1_data_i(timer_data_i),
.periph1_wr_o(timer_wr),
.periph1_rd_o(timer_rd),
.periph1_we_o(timer_we),
.periph1_stb_o(timer_stb),
 
// Interrupt Controller = 0x12000200 - 0x120002FF
.periph2_addr_o(intr_addr),
.periph2_data_o(intr_data_o),
.periph2_data_i(intr_data_i),
.periph2_wr_o(intr_wr),
.periph2_rd_o(intr_rd),
.periph2_we_o(intr_we),
.periph2_stb_o(intr_stb),
 
// Unused = 0x12000300 - 0x120003FF
.periph3_addr_o(/*open*/),
.periph3_data_o(/*open*/),
.periph3_data_i(32'h00000000),
.periph3_wr_o(/*open*/),
.periph3_rd_o(/*open*/),
.periph3_we_o(/*open*/),
.periph3_stb_o(/*open*/),
 
// Unused = 0x12000400 - 0x120004FF
.periph4_addr_o(/*open*/),
.periph4_data_o(/*open*/),
.periph4_data_i(32'h00000000),
.periph4_wr_o(/*open*/),
.periph4_rd_o(/*open*/),
.periph4_we_o(/*open*/),
.periph4_stb_o(/*open*/),
 
// Unused = 0x12000500 - 0x120005FF
.periph5_addr_o(/*open*/),
.periph5_data_o(/*open*/),
.periph5_data_i(32'h00000000),
.periph5_wr_o(/*open*/),
.periph5_rd_o(/*open*/),
.periph5_we_o(/*open*/),
.periph5_stb_o(/*open*/),
 
// Unused = 0x12000600 - 0x120006FF
.periph6_addr_o(/*open*/),
.periph6_data_o(/*open*/),
.periph6_data_i(32'h00000000),
.periph6_wr_o(/*open*/),
.periph6_rd_o(/*open*/),
.periph6_we_o(/*open*/),
.periph6_stb_o(/*open*/),
 
// Unused = 0x12000700 - 0x120007FF
.periph7_addr_o(/*open*/),
.periph7_data_o(/*open*/),
.periph7_data_i(32'h00000000),
.periph7_wr_o(/*open*/),
.periph7_rd_o(/*open*/)
.periph7_we_o(/*open*/),
.periph7_stb_o(/*open*/)
);
 
//-----------------------------------------------------------------
// Memory master arbiter
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// UART
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// GPIO
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// SPI Flash Master
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// DMA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// SD
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Generic Register
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Timer
//-----------------------------------------------------------------
timer_periph
209,8 → 193,8
.addr_i(timer_addr),
.data_o(timer_data_i),
.data_i(timer_data_o),
.wr_i(timer_wr),
.rd_i(timer_rd)
.we_i(timer_we),
.stb_i(timer_stb)
);
 
//-----------------------------------------------------------------
244,8 → 228,8
.addr_i(intr_addr),
.data_o(intr_data_i),
.data_i(intr_data_o),
.wr_i(intr_wr),
.rd_i(intr_rd)
.we_i(intr_we),
.stb_i(intr_stb)
);
 
//-------------------------------------------------------------------
/rtl/soc/cpu_if.v
1,3 → 1,39
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module:
5,126 → 41,92
module cpu_if
(
// General - Clocking & Reset
clk_i,
rst_i,
input clk_i,
input rst_i,
 
// Instruction Memory 0 (0x10000000 - 0x10FFFFFF)
imem0_addr_o,
imem0_rd_o,
imem0_burst_o,
imem0_data_in_i,
imem0_accept_i,
imem0_ack_i,
output [31:0] imem0_addr_o,
input [31:0] imem0_data_i,
output [3:0] imem0_sel_o,
output imem0_stb_o,
output imem0_cyc_o,
output [2:0] imem0_cti_o,
input imem0_ack_i,
input imem0_stall_i,
 
// Data Memory 0 (0x10000000 - 0x10FFFFFF)
dmem0_addr_o,
dmem0_data_o,
dmem0_data_i,
dmem0_wr_o,
dmem0_rd_o,
dmem0_burst_o,
dmem0_accept_i,
dmem0_ack_i,
output [31:0] dmem0_addr_o,
output [31:0] dmem0_data_o,
input [31:0] dmem0_data_i,
output [3:0] dmem0_sel_o,
output dmem0_we_o,
output dmem0_stb_o,
output dmem0_cyc_o,
output [2:0] dmem0_cti_o,
input dmem0_ack_i,
input dmem0_stall_i,
 
// Data Memory 1 (0x11000000 - 0x11FFFFFF)
dmem1_addr_o,
dmem1_data_o,
dmem1_data_i,
dmem1_wr_o,
dmem1_rd_o,
dmem1_burst_o,
dmem1_accept_i,
dmem1_ack_i,
output [31:0] dmem1_addr_o,
output [31:0] dmem1_data_o,
input [31:0] dmem1_data_i,
output [3:0] dmem1_sel_o,
output dmem1_we_o,
output dmem1_stb_o,
output dmem1_cyc_o,
output [2:0] dmem1_cti_o,
input dmem1_ack_i,
input dmem1_stall_i,
 
// Data Memory 2 (0x12000000 - 0x12FFFFFF)
dmem2_addr_o,
dmem2_data_o,
dmem2_data_i,
dmem2_wr_o,
dmem2_rd_o,
dmem2_burst_o,
dmem2_accept_i,
dmem2_ack_i,
output [31:0] dmem2_addr_o,
output [31:0] dmem2_data_o,
input [31:0] dmem2_data_i,
output [3:0] dmem2_sel_o,
output dmem2_we_o,
output dmem2_stb_o,
output dmem2_cyc_o,
output [2:0] dmem2_cti_o,
input dmem2_ack_i,
input dmem2_stall_i,
 
fault_o,
break_o,
intr_i,
nmi_i
output fault_o,
output break_o,
input intr_i,
input nmi_i
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter [31:0] CLK_KHZ = 12288;
parameter CLK_KHZ = 12288;
parameter ENABLE_ICACHE = "ENABLED";
parameter ENABLE_DCACHE = "DISABLED";
parameter ENABLE_DCACHE = "ENABLED";
parameter BOOT_VECTOR = 0;
parameter ISR_VECTOR = 0;
parameter REGISTER_FILE_TYPE = "SIMULATION";
 
//-----------------------------------------------------------------
// I/O
//-----------------------------------------------------------------
input clk_i /*verilator public*/;
input rst_i /*verilator public*/;
 
// Instruction Memory 0 (0x10000000 - 0x10FFFFFF)
output [31:0] imem0_addr_o /*verilator public*/;
output imem0_rd_o /*verilator public*/;
output imem0_burst_o /*verilator public*/;
input [31:0] imem0_data_in_i /*verilator public*/;
input imem0_accept_i /*verilator public*/;
input imem0_ack_i /*verilator public*/;
 
// Data Memory 0 (0x10000000 - 0x10FFFFFF)
output [31:0] dmem0_addr_o /*verilator public*/;
output [31:0] dmem0_data_o /*verilator public*/;
input [31:0] dmem0_data_i /*verilator public*/;
output [3:0] dmem0_wr_o /*verilator public*/;
output dmem0_rd_o /*verilator public*/;
output dmem0_burst_o /*verilator public*/;
input dmem0_accept_i /*verilator public*/;
input dmem0_ack_i /*verilator public*/;
// Data Memory 1 (0x11000000 - 0x11FFFFFF)
output [31:0] dmem1_addr_o /*verilator public*/;
output [31:0] dmem1_data_o /*verilator public*/;
input [31:0] dmem1_data_i /*verilator public*/;
output [3:0] dmem1_wr_o /*verilator public*/;
output dmem1_rd_o /*verilator public*/;
output dmem1_burst_o /*verilator public*/;
input dmem1_accept_i /*verilator public*/;
input dmem1_ack_i /*verilator public*/;
// Data Memory 2 (0x12000000 - 0x12FFFFFF)
output [31:0] dmem2_addr_o /*verilator public*/;
output [31:0] dmem2_data_o /*verilator public*/;
input [31:0] dmem2_data_i /*verilator public*/;
output [3:0] dmem2_wr_o /*verilator public*/;
output dmem2_rd_o /*verilator public*/;
output dmem2_burst_o /*verilator public*/;
input dmem2_accept_i /*verilator public*/;
input dmem2_ack_i /*verilator public*/;
 
output fault_o /*verilator public*/;
output break_o /*verilator public*/;
input nmi_i /*verilator public*/;
input intr_i /*verilator public*/;
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
wire [31:0] cpu_address;
wire [3:0] cpu_wr;
wire cpu_rd;
wire cpu_burst;
wire [31:0] cpu_data_w;
wire [31:0] cpu_data_r;
wire cpu_accept;
wire cpu_ack;
wire [31:0] dmem_addr;
wire [31:0] dmem_data_w;
wire [31:0] dmem_data_r;
wire [3:0] dmem_sel;
wire [2:0] dmem_cti;
wire dmem_cyc;
wire dmem_we;
wire dmem_stb;
wire dmem_stall;
wire dmem_ack;
wire [31:0] imem_address;
wire [31:0] imem_data;
wire imem_rd;
wire imem_burst;
wire [2:0] imem_cti;
wire imem_cyc;
wire imem_stb;
wire imem_stall;
wire imem_ack;
wire imem_accept;
 
//-----------------------------------------------------------------
// CPU core
151,21 → 153,24
// Instruction memory
.imem_addr_o(imem_address),
.imem_rd_o(imem_rd),
.imem_burst_o(imem_burst),
.imem_data_in_i(imem_data),
.imem_accept_i(imem_accept),
.imem_ack_i(imem_ack),
.imem_dat_i(imem_data),
.imem_cti_o(imem_cti),
.imem_cyc_o(imem_cyc),
.imem_stb_o(imem_stb),
.imem_stall_i(imem_stall),
.imem_ack_i(imem_ack),
// Data memory
.dmem_addr_o(cpu_address),
.dmem_data_out_o(cpu_data_w),
.dmem_data_in_i(cpu_data_r),
.dmem_wr_o(cpu_wr),
.dmem_rd_o(cpu_rd),
.dmem_burst_o(cpu_burst),
.dmem_accept_i(cpu_accept),
.dmem_ack_i(cpu_ack)
.dmem_addr_o(dmem_addr),
.dmem_dat_o(dmem_data_w),
.dmem_dat_i(dmem_data_r),
.dmem_sel_o(dmem_sel),
.dmem_cti_o(dmem_cti),
.dmem_cyc_o(dmem_cyc),
.dmem_we_o(dmem_we),
.dmem_stb_o(dmem_stb),
.dmem_stall_i(dmem_stall),
.dmem_ack_i(dmem_ack)
);
 
//-----------------------------------------------------------------
173,10 → 178,12
//-----------------------------------------------------------------
 
assign imem0_addr_o = imem_address;
assign imem0_rd_o = imem_rd;
assign imem0_burst_o = imem_burst;
assign imem_data = imem0_data_in_i;
assign imem_accept = imem0_accept_i;
assign imem0_sel_o = 4'b1111;
assign imem0_stb_o = imem_stb;
assign imem0_cyc_o = imem_cyc;
assign imem0_cti_o = imem_cti;
assign imem_data = imem0_data_i;
assign imem_stall = imem0_stall_i;
assign imem_ack = imem0_ack_i;
 
 
194,39 → 201,49
.out0_addr_o(dmem0_addr_o),
.out0_data_o(dmem0_data_o),
.out0_data_i(dmem0_data_i),
.out0_wr_o(dmem0_wr_o),
.out0_rd_o(dmem0_rd_o),
.out0_burst_o(dmem0_burst_o),
.out0_sel_o(dmem0_sel_o),
.out0_we_o(dmem0_we_o),
.out0_stb_o(dmem0_stb_o),
.out0_cyc_o(dmem0_cyc_o),
.out0_cti_o(dmem0_cti_o),
.out0_ack_i(dmem0_ack_i),
.out0_accept_i(dmem0_accept_i),
.out0_stall_i(dmem0_stall_i),
 
// 0x11000000 - 0x11FFFFFF
.out1_addr_o(dmem1_addr_o),
.out1_data_o(dmem1_data_o),
.out1_data_i(dmem1_data_i),
.out1_wr_o(dmem1_wr_o),
.out1_rd_o(dmem1_rd_o),
.out1_burst_o(dmem1_burst_o),
.out1_sel_o(dmem1_sel_o),
.out1_we_o(dmem1_we_o),
.out1_stb_o(dmem1_stb_o),
.out1_cyc_o(dmem1_cyc_o),
.out1_cti_o(dmem1_cti_o),
.out1_ack_i(dmem1_ack_i),
.out1_accept_i(dmem1_accept_i),
.out1_stall_i(dmem1_stall_i),
 
// 0x12000000 - 0x12FFFFFF
.out2_addr_o(dmem2_addr_o),
.out2_data_o(dmem2_data_o),
.out2_data_i(dmem2_data_i),
.out2_wr_o(dmem2_wr_o),
.out2_rd_o(dmem2_rd_o),
.out2_burst_o(dmem2_burst_o),
.out2_sel_o(dmem2_sel_o),
.out2_we_o(dmem2_we_o),
.out2_stb_o(dmem2_stb_o),
.out2_cyc_o(dmem2_cyc_o),
.out2_cti_o(dmem2_cti_o),
.out2_ack_i(dmem2_ack_i),
.out2_accept_i(dmem2_accept_i),
.out2_stall_i(dmem2_stall_i),
 
// Input - CPU core bus
.mem_addr_i(cpu_address),
.mem_data_i(cpu_data_w),
.mem_data_o(cpu_data_r),
.mem_wr_i(cpu_wr),
.mem_rd_i(cpu_rd),
.mem_burst_i(cpu_burst),
.mem_ack_o(cpu_ack),
.mem_accept_o(cpu_accept)
.mem_addr_i(dmem_addr),
.mem_data_i(dmem_data_w),
.mem_data_o(dmem_data_r),
.mem_sel_i(dmem_sel),
.mem_we_i(dmem_we),
.mem_stb_i(dmem_stb),
.mem_cyc_i(dmem_cyc),
.mem_cti_i(dmem_cti),
.mem_ack_o(dmem_ack),
.mem_stall_o(dmem_stall)
);
 
endmodule
/rtl/soc/soc_pif8.v
1,3 → 1,39
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module:
5,190 → 41,109
module soc_pif8
(
// General - Clocking & Reset
clk_i,
rst_i,
input clk_i,
input rst_i,
 
// Peripherals
periph0_addr_o,
periph0_data_o,
periph0_data_i,
periph0_wr_o,
periph0_rd_o,
periph1_addr_o,
periph1_data_o,
periph1_data_i,
periph1_wr_o,
periph1_rd_o,
periph2_addr_o,
periph2_data_o,
periph2_data_i,
periph2_wr_o,
periph2_rd_o,
periph3_addr_o,
periph3_data_o,
periph3_data_i,
periph3_wr_o,
periph3_rd_o,
periph4_addr_o,
periph4_data_o,
periph4_data_i,
periph4_wr_o,
periph4_rd_o,
periph5_addr_o,
periph5_data_o,
periph5_data_i,
periph5_wr_o,
periph5_rd_o,
periph6_addr_o,
periph6_data_o,
periph6_data_i,
periph6_wr_o,
periph6_rd_o,
periph7_addr_o,
periph7_data_o,
periph7_data_i,
periph7_wr_o,
periph7_rd_o,
output [7:0] periph0_addr_o,
output [31:0] periph0_data_o,
input [31:0] periph0_data_i,
output reg periph0_we_o,
output reg periph0_stb_o,
 
// I/O bus
io_addr_i,
io_data_i,
io_data_o,
io_wr_i,
io_rd_i
);
output [7:0] periph1_addr_o,
output [31:0] periph1_data_o,
input [31:0] periph1_data_i,
output reg periph1_we_o,
output reg periph1_stb_o,
 
//-----------------------------------------------------------------
// I/O
//-----------------------------------------------------------------
input clk_i /*verilator public*/;
input rst_i /*verilator public*/;
output [7:0] periph2_addr_o,
output [31:0] periph2_data_o,
input [31:0] periph2_data_i,
output reg periph2_we_o,
output reg periph2_stb_o,
 
input [31:0] io_addr_i /*verilator public*/;
output [31:0] io_data_o /*verilator public*/;
input [31:0] io_data_i /*verilator public*/;
input [3:0] io_wr_i /*verilator public*/;
input io_rd_i /*verilator public*/;
output [7:0] periph3_addr_o,
output [31:0] periph3_data_o,
input [31:0] periph3_data_i,
output reg periph3_we_o,
output reg periph3_stb_o,
 
output [7:0] periph0_addr_o /*verilator public*/;
output [31:0] periph0_data_o /*verilator public*/;
input [31:0] periph0_data_i /*verilator public*/;
output [3:0] periph0_wr_o /*verilator public*/;
output periph0_rd_o /*verilator public*/;
output [7:0] periph1_addr_o /*verilator public*/;
output [31:0] periph1_data_o /*verilator public*/;
input [31:0] periph1_data_i /*verilator public*/;
output [3:0] periph1_wr_o /*verilator public*/;
output periph1_rd_o /*verilator public*/;
output [7:0] periph2_addr_o /*verilator public*/;
output [31:0] periph2_data_o /*verilator public*/;
input [31:0] periph2_data_i /*verilator public*/;
output [3:0] periph2_wr_o /*verilator public*/;
output periph2_rd_o /*verilator public*/;
output [7:0] periph3_addr_o /*verilator public*/;
output [31:0] periph3_data_o /*verilator public*/;
input [31:0] periph3_data_i /*verilator public*/;
output [3:0] periph3_wr_o /*verilator public*/;
output periph3_rd_o /*verilator public*/;
output [7:0] periph4_addr_o /*verilator public*/;
output [31:0] periph4_data_o /*verilator public*/;
input [31:0] periph4_data_i /*verilator public*/;
output [3:0] periph4_wr_o /*verilator public*/;
output periph4_rd_o /*verilator public*/;
output [7:0] periph5_addr_o /*verilator public*/;
output [31:0] periph5_data_o /*verilator public*/;
input [31:0] periph5_data_i /*verilator public*/;
output [3:0] periph5_wr_o /*verilator public*/;
output periph5_rd_o /*verilator public*/;
output [7:0] periph6_addr_o /*verilator public*/;
output [31:0] periph6_data_o /*verilator public*/;
input [31:0] periph6_data_i /*verilator public*/;
output [3:0] periph6_wr_o /*verilator public*/;
output periph6_rd_o /*verilator public*/;
output [7:0] periph7_addr_o /*verilator public*/;
output [31:0] periph7_data_o /*verilator public*/;
input [31:0] periph7_data_i /*verilator public*/;
output [3:0] periph7_wr_o /*verilator public*/;
output periph7_rd_o /*verilator public*/;
output [7:0] periph4_addr_o,
output [31:0] periph4_data_o,
input [31:0] periph4_data_i,
output reg periph4_we_o,
output reg periph4_stb_o,
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [3:0] r_mem_sel;
output [7:0] periph5_addr_o,
output [31:0] periph5_data_o,
input [31:0] periph5_data_i,
output reg periph5_we_o,
output reg periph5_stb_o,
 
reg [31:0] io_data_o;
output [7:0] periph6_addr_o,
output [31:0] periph6_data_o,
input [31:0] periph6_data_i,
output reg periph6_we_o,
output reg periph6_stb_o,
 
reg [7:0] periph0_addr_o;
reg [31:0] periph0_data_o;
reg [3:0] periph0_wr_o;
reg periph0_rd_o;
reg [7:0] periph1_addr_o;
reg [31:0] periph1_data_o;
reg [3:0] periph1_wr_o;
reg periph1_rd_o;
reg [7:0] periph2_addr_o;
reg [31:0] periph2_data_o;
reg [3:0] periph2_wr_o;
reg periph2_rd_o;
reg [7:0] periph3_addr_o;
reg [31:0] periph3_data_o;
reg [3:0] periph3_wr_o;
reg periph3_rd_o;
reg [7:0] periph4_addr_o;
reg [31:0] periph4_data_o;
reg [3:0] periph4_wr_o;
reg periph4_rd_o;
reg [7:0] periph5_addr_o;
reg [31:0] periph5_data_o;
reg [3:0] periph5_wr_o;
reg periph5_rd_o;
reg [7:0] periph6_addr_o;
reg [31:0] periph6_data_o;
reg [3:0] periph6_wr_o;
reg periph6_rd_o;
reg [7:0] periph7_addr_o;
reg [31:0] periph7_data_o;
reg [3:0] periph7_wr_o;
reg periph7_rd_o;
output [7:0] periph7_addr_o,
output [31:0] periph7_data_o,
input [31:0] periph7_data_i,
output reg periph7_we_o,
output reg periph7_stb_o,
 
// I/O bus
input [31:0] io_addr_i,
input [31:0] io_data_i,
output reg [31:0] io_data_o,
input io_we_i,
input io_stb_i,
output reg io_ack_o
);
 
//-----------------------------------------------------------------
// Memory Map
//-----------------------------------------------------------------
always @ (io_addr_i or io_wr_i or io_rd_i or io_data_i)
 
// Route data / address to all peripherals
assign periph0_addr_o = io_addr_i[7:0];
assign periph0_data_o = io_data_i;
assign periph1_addr_o = io_addr_i[7:0];
assign periph1_data_o = io_data_i;
assign periph2_addr_o = io_addr_i[7:0];
assign periph2_data_o = io_data_i;
assign periph3_addr_o = io_addr_i[7:0];
assign periph3_data_o = io_data_i;
assign periph4_addr_o = io_addr_i[7:0];
assign periph4_data_o = io_data_i;
assign periph5_addr_o = io_addr_i[7:0];
assign periph5_data_o = io_data_i;
assign periph6_addr_o = io_addr_i[7:0];
assign periph6_data_o = io_data_i;
assign periph7_addr_o = io_addr_i[7:0];
assign periph7_data_o = io_data_i;
 
// Select correct target
always @ *
begin
 
periph0_addr_o = 8'h00;
periph0_wr_o = 4'b0000;
periph0_rd_o = 1'b0;
periph0_data_o = 32'h00000000;
periph1_addr_o = 8'h00;
periph1_wr_o = 4'b0000;
periph1_rd_o = 1'b0;
periph1_data_o = 32'h00000000;
periph2_addr_o = 8'h00;
periph2_wr_o = 4'b0000;
periph2_rd_o = 1'b0;
periph2_data_o = 32'h00000000;
periph3_addr_o = 8'h00;
periph3_wr_o = 4'b0000;
periph3_rd_o = 1'b0;
periph3_data_o = 32'h00000000;
periph4_addr_o = 8'h00;
periph4_wr_o = 4'b0000;
periph4_rd_o = 1'b0;
periph4_data_o = 32'h00000000;
periph5_addr_o = 8'h00;
periph5_wr_o = 4'b0000;
periph5_rd_o = 1'b0;
periph5_data_o = 32'h00000000;
periph6_addr_o = 8'h00;
periph6_wr_o = 4'b0000;
periph6_rd_o = 1'b0;
periph6_data_o = 32'h00000000;
periph7_addr_o = 8'h00;
periph7_wr_o = 4'b0000;
periph7_rd_o = 1'b0;
periph7_data_o = 32'h00000000;
periph0_we_o = 1'b0;
periph0_stb_o = 1'b0;
periph1_we_o = 1'b0;
periph1_stb_o = 1'b0;
periph2_we_o = 1'b0;
periph2_stb_o = 1'b0;
periph3_we_o = 1'b0;
periph3_stb_o = 1'b0;
periph4_we_o = 1'b0;
periph4_stb_o = 1'b0;
periph5_we_o = 1'b0;
periph5_stb_o = 1'b0;
periph6_we_o = 1'b0;
periph6_stb_o = 1'b0;
periph7_we_o = 1'b0;
periph7_stb_o = 1'b0;
 
// Decode 4-bit peripheral select
case (io_addr_i[11:8])
196,66 → 151,50
// Peripheral 0
4'd 0 :
begin
periph0_addr_o = io_addr_i[7:0];
periph0_wr_o = io_wr_i;
periph0_rd_o = io_rd_i;
periph0_data_o = io_data_i;
periph0_we_o = io_we_i;
periph0_stb_o = io_stb_i;
end
// Peripheral 1
4'd 1 :
begin
periph1_addr_o = io_addr_i[7:0];
periph1_wr_o = io_wr_i;
periph1_rd_o = io_rd_i;
periph1_data_o = io_data_i;
periph1_we_o = io_we_i;
periph1_stb_o = io_stb_i;
end
// Peripheral 2
4'd 2 :
begin
periph2_addr_o = io_addr_i[7:0];
periph2_wr_o = io_wr_i;
periph2_rd_o = io_rd_i;
periph2_data_o = io_data_i;
periph2_we_o = io_we_i;
periph2_stb_o = io_stb_i;
end
// Peripheral 3
4'd 3 :
begin
periph3_addr_o = io_addr_i[7:0];
periph3_wr_o = io_wr_i;
periph3_rd_o = io_rd_i;
periph3_data_o = io_data_i;
periph3_we_o = io_we_i;
periph3_stb_o = io_stb_i;
end
// Peripheral 4
4'd 4 :
begin
periph4_addr_o = io_addr_i[7:0];
periph4_wr_o = io_wr_i;
periph4_rd_o = io_rd_i;
periph4_data_o = io_data_i;
periph4_we_o = io_we_i;
periph4_stb_o = io_stb_i;
end
// Peripheral 5
4'd 5 :
begin
periph5_addr_o = io_addr_i[7:0];
periph5_wr_o = io_wr_i;
periph5_rd_o = io_rd_i;
periph5_data_o = io_data_i;
periph5_we_o = io_we_i;
periph5_stb_o = io_stb_i;
end
// Peripheral 6
4'd 6 :
begin
periph6_addr_o = io_addr_i[7:0];
periph6_wr_o = io_wr_i;
periph6_rd_o = io_rd_i;
periph6_data_o = io_data_i;
periph6_we_o = io_we_i;
periph6_stb_o = io_stb_i;
end
// Peripheral 7
4'd 7 :
begin
periph7_addr_o = io_addr_i[7:0];
periph7_wr_o = io_wr_i;
periph7_rd_o = io_rd_i;
periph7_data_o = io_data_i;
periph7_we_o = io_we_i;
periph7_stb_o = io_stb_i;
end
 
default :
266,67 → 205,42
//-----------------------------------------------------------------
// Read Port
//-----------------------------------------------------------------
always @ *
always @ (posedge clk_i or posedge rst_i)
begin
case (r_mem_sel)
 
// Peripheral 0
4'd 0 :
if (rst_i == 1'b1)
begin
io_data_o = periph0_data_i;
io_data_o <= 32'b0;
io_ack_o <= 1'b0;
end
// Peripheral 1
4'd 1 :
else
begin
io_data_o = periph1_data_i;
end
// Peripheral 2
4'd 2 :
begin
io_data_o = periph2_data_i;
end
// Peripheral 3
4'd 3 :
begin
io_data_o = periph3_data_i;
end
// Peripheral 4
4'd 4 :
begin
io_data_o = periph4_data_i;
end
// Peripheral 5
4'd 5 :
begin
io_data_o = periph5_data_i;
end
// Peripheral 6
4'd 6 :
begin
io_data_o = periph6_data_i;
end
// Peripheral 7
4'd 7 :
begin
io_data_o = periph7_data_i;
end
if (io_stb_i)
begin
// Decode 4-bit peripheral select
case (io_addr_i[11:8])
// Peripheral 0
4'd 0 : io_data_o <= periph0_data_i;
// Peripheral 1
4'd 1 : io_data_o <= periph1_data_i;
// Peripheral 2
4'd 2 : io_data_o <= periph2_data_i;
// Peripheral 3
4'd 3 : io_data_o <= periph3_data_i;
// Peripheral 4
4'd 4 : io_data_o <= periph4_data_i;
// Peripheral 5
4'd 5 : io_data_o <= periph5_data_i;
// Peripheral 6
4'd 6 : io_data_o <= periph6_data_i;
// Peripheral 7
4'd 7 : io_data_o <= periph7_data_i;
 
default :
begin
io_data_o = 32'h00000000;
default : io_data_o <= 32'h00000000;
endcase
end
 
io_ack_o <= io_stb_i;
end
endcase
end
 
//-----------------------------------------------------------------
// Registered peripheral select
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i == 1'b1)
r_mem_sel <= 4'h0;
else
r_mem_sel <= io_addr_i[11:8];
end
 
endmodule
/rtl/cpu/altor32_dcache.v
49,9 → 49,10
input [31:0] address_i /*verilator public*/,
output [31:0] data_o /*verilator public*/,
input [31:0] data_i /*verilator public*/,
input rd_i /*verilator public*/,
input [3:0] wr_i /*verilator public*/,
output accept_o /*verilator public*/,
input we_i /*verilator public*/,
input stb_i /*verilator public*/,
input [3:0] sel_i /*verilator public*/,
output stall_o /*verilator public*/,
output ack_o /*verilator public*/,
 
// Output (Memory)
58,10 → 59,12
output [31:0] mem_addr_o /*verilator public*/,
input [31:0] mem_data_i /*verilator public*/,
output [31:0] mem_data_o /*verilator public*/,
output mem_burst_o /*verilator public*/,
output mem_rd_o /*verilator public*/,
output [3:0] mem_wr_o /*verilator public*/,
input mem_accept_i/*verilator public*/,
output [2:0] mem_cti_o /*verilator public*/,
output mem_cyc_o /*verilator public*/,
output mem_stb_o /*verilator public*/,
output mem_we_o /*verilator public*/,
output [3:0] mem_sel_o /*verilator public*/,
input mem_stall_i/*verilator public*/,
input mem_ack_i/*verilator public*/
);
 
119,15 → 122,15
reg evict;
wire done;
 
reg [31:0] data_w;
wire [31:0] data_r;
reg data_rd;
reg [3:0] data_wr;
reg rd_single;
reg [3:0] wr_single;
 
reg req_rd;
reg [3:0] req_wr;
reg req_ack;
reg [31:0] req_address;
reg [31:0] req_data;
 
reg req_flush;
reg flush_single;
157,9 → 160,8
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 accept_o = (state == STATE_IDLE);
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];
 
166,8 → 168,11
// Access is cacheable?
wire cacheable = ~muxed_address[ADDR_NO_CACHE_BIT] & ~muxed_address[ADDR_CACHE_BYPASS_BIT];
 
// Address matches cache tag
wire addr_hit = (req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]);
 
// Cache hit?
wire hit = cacheable & valid & (muxed_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]) & (state == STATE_CHECK);
wire hit = cacheable & valid & addr_hit & (state == STATE_CHECK);
 
assign ack_o = ack | hit;
 
175,43 → 180,514
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}};
 
 
//-----------------------------------------------------------------
// Control logic
// Next State Logic
//-----------------------------------------------------------------
reg [3:0] next_state_r;
always @ *
begin
next_state_r = state;
 
case (state)
//-----------------------------------------
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
// Cache flush request
if (flush_i | req_flush)
next_state_r = STATE_FLUSH2;
// Read (uncacheable)
else if (stb_i & ~we_i & ~cacheable)
next_state_r = STATE_SINGLE;
// Read (cacheable)
else if (stb_i & ~we_i)
next_state_r = STATE_CHECK;
// Write (uncacheable)
else if (stb_i & we_i & ~cacheable)
next_state_r = STATE_SINGLE;
// Write (cacheable)
else if (stb_i & we_i)
next_state_r = STATE_WRITE;
end
//-----------------------------------------
// WRITE - Wait for write-thru to complete
//-----------------------------------------
STATE_WRITE :
begin
// Cache hit
if (valid & addr_hit)
next_state_r = STATE_WAIT2;
// Cache dirty
else if (valid & dirty)
next_state_r = STATE_EVICTING;
// Cache miss
else
next_state_r = STATE_UPDATE;
end
//-----------------------------------------
// EVICTING - Evicting cache line
//-----------------------------------------
STATE_EVICTING:
begin
// Data ready from memory?
if (done)
begin
// Evict for read?
if (req_rd)
next_state_r = STATE_FETCH;
// Evict for write
else
next_state_r = STATE_UPDATE;
end
end
//-----------------------------------------
// UPDATE - Update fetched cache line
//-----------------------------------------
STATE_UPDATE:
begin
// Data ready from memory?
if (done)
next_state_r = STATE_WAIT2;
end
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache hit
if (valid & addr_hit)
next_state_r = STATE_IDLE;
// Cache dirty
else if (valid & dirty)
next_state_r = STATE_EVICTING;
// Cache miss
else
next_state_r = STATE_FETCH;
end
//-----------------------------------------
// FETCH_SINGLE - Single access to memory
//-----------------------------------------
STATE_SINGLE:
begin
// Data ready from memory?
if (done)
begin
// Single WRITE?
if (~req_rd)
next_state_r = STATE_SINGLE_READY;
// Dirty? Write back
else if (valid & dirty & addr_hit)
next_state_r = STATE_FLUSH4;
// Valid line, invalidate
else if (valid & addr_hit)
next_state_r = STATE_SINGLE_READY;
else
next_state_r = STATE_SINGLE_READY;
end
end
//-----------------------------------------
// FETCH - Fetch row from memory
//-----------------------------------------
STATE_FETCH :
begin
// Cache line filled?
if (done)
next_state_r = STATE_WAIT;
end
//-----------------------------------------
// WAIT - Wait cycle
//-----------------------------------------
STATE_WAIT :
begin
// Allow extra wait state to handle write & read collision
next_state_r = STATE_WAIT2;
end
//-----------------------------------------
// WAIT2 - Wait cycle
//-----------------------------------------
STATE_WAIT2 :
begin
next_state_r = STATE_IDLE;
end
//-----------------------------------------
// SINGLE_READY - Uncached access ready
//-----------------------------------------
STATE_SINGLE_READY :
begin
// Allow extra wait state to handle write & read collision
next_state_r = STATE_IDLE;
end
//-----------------------------------------
// FLUSHx - Flush dirty lines & invalidate
//-----------------------------------------
STATE_FLUSH1 :
begin
if (req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] == {CACHE_LINE_ADDR_WIDTH{1'b1}})
next_state_r = STATE_WAIT;
else
next_state_r = STATE_FLUSH2;
end
//-----------------------------------------
// FLUSH2 - Wait state
//-----------------------------------------
STATE_FLUSH2 :
begin
// Allow a cycle to read line state
next_state_r = STATE_FLUSH3;
end
//-----------------------------------------
// FLUSH3 - Check if line dirty & flush
//-----------------------------------------
STATE_FLUSH3 :
begin
// Dirty line? Evict line first
if (dirty)
next_state_r = STATE_FLUSH4;
// Not dirty? Just invalidate
else
begin
if (flush_single)
next_state_r = STATE_WAIT;
else
next_state_r = STATE_FLUSH1;
end
end
//-----------------------------------------
// FLUSH4 - Wait for line flush to complete
//-----------------------------------------
STATE_FLUSH4 :
begin
// Cache line filled?
if (done)
begin
if (flush_single)
next_state_r = STATE_SINGLE_READY;
else
next_state_r = STATE_FLUSH1;
end
end
 
default:
;
endcase
end
 
// Update state
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
state <= STATE_IDLE;
else
state <= next_state_r;
end
 
//-----------------------------------------------------------------
// Tag Write
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
data_w <= 32'h00000000;
data_wr <= 4'h0;
data_rd <= 1'b0;
tag_data_in <= 16'b0;
tag_wr <= 1'b0;
end
else
begin
tag_wr <= 1'b0;
 
case (state)
//-----------------------------------------
// WRITE - Wait for write-thru to complete
//-----------------------------------------
STATE_WRITE :
begin
// Cache hit
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;
end
// Cache miss / cache line doesn't require write back
else if (~valid | ~dirty)
begin
// Update tag memory with this line's details
tag_data_in <= {1'b1, 1'b1, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
end
end
//-----------------------------------------
// EVICTING - Evicting cache line
//-----------------------------------------
STATE_EVICTING:
begin
// Data ready from memory?
if (done)
begin
// Update tag memory with this new line's details
tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
end
end
//-----------------------------------------
// UPDATE - Update fetched cache line
//-----------------------------------------
STATE_UPDATE:
begin
// Data ready from memory?
if (done)
begin
// Mark line as dirty
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
tag_wr <= 1'b1;
end
end
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache hit
if (valid & addr_hit)
begin
 
end
// Cache miss / cache line doesn't require write back
else if (~valid | ~dirty)
begin
// Update tag memory with this line's details
tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
end
end
//-----------------------------------------
// FETCH_SINGLE - Single access to memory
//-----------------------------------------
STATE_SINGLE:
begin
// Data ready from memory?
if (done)
begin
// Single WRITE?
if (~req_rd)
begin
// Invalidate cached version
if (valid & addr_hit)
begin
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_wr <= 1'b1;
end
end
// Valid line (not dirty), just invalidate
else if (valid & ~dirty & addr_hit)
begin
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_wr <= 1'b1;
end
end
end
//-----------------------------------------
// FLUSH3 - Check if line dirty & flush
//-----------------------------------------
STATE_FLUSH3 :
begin
// Not dirty? Just invalidate
if (~dirty)
begin
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_wr <= 1'b1;
end
end
//-----------------------------------------
// FLUSH4 - Wait for line flush to complete
//-----------------------------------------
STATE_FLUSH4 :
begin
// Cache line filled?
if (done)
begin
// Invalidate line
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;
end
end
default:
;
endcase
end
end
 
//-----------------------------------------------------------------
// Register requests
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
req_address <= 32'h00000000;
req_data <= 32'h00000000;
req_ack <= 1'b0;
req_wr <= 4'h0;
req_rd <= 1'b0;
tag_wr <= 1'b0;
req_flush <= 1'b0;
end
else
begin
if (flush_i)
req_flush <= 1'b1;
 
case (state)
//-----------------------------------------
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
// Cache flush request
if (flush_i | req_flush)
begin
// Set to first line address
req_address <= 32'h00000000;
req_flush <= 1'b0;
req_ack <= 1'b0;
end
// Read (uncacheable)
else if (stb_i & ~we_i & ~cacheable)
begin
// Start read single from memory
req_address <= address_i;
req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
req_rd <= 1'b1;
req_wr <= 4'b0;
req_ack <= 1'b1;
end
// Read (cacheable)
else if (stb_i & ~we_i)
begin
req_address <= address_i;
req_rd <= 1'b1;
req_wr <= 4'b0;
req_ack <= 1'b1;
end
// Write (uncacheable)
else if (stb_i & we_i & ~cacheable)
begin
// Perform write single
req_address <= address_i;
req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
req_data <= data_i;
req_wr <= sel_i;
req_rd <= 1'b0;
req_ack <= 1'b1;
end
// Write (cacheable)
else if (stb_i & we_i)
begin
req_address <= address_i;
req_data <= data_i;
req_wr <= sel_i;
req_rd <= 1'b0;
req_ack <= 1'b0;
end
end
//-----------------------------------------
// FLUSHx - Flush dirty lines & invalidate
//-----------------------------------------
STATE_FLUSH1 :
begin
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;
end
else
begin
// Increment flush line address
req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] <=
req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] + 1;
end
end
default:
;
endcase
end
end
 
//-----------------------------------------------------------------
// Cache Data Write
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
cache_data_w <= 32'h00000000;
cache_wr <= 4'b0;
end
else
begin
cache_wr <= 4'b0;
 
case (state)
//-----------------------------------------
// WRITE - Wait for write-thru to complete
//-----------------------------------------
STATE_WRITE :
begin
// Cache hit
if (valid & addr_hit)
begin
// Update line already in cache
cache_data_w <= req_data;
cache_wr <= req_wr;
end
end
//-----------------------------------------
// UPDATE - Update fetched cache line
//-----------------------------------------
STATE_UPDATE:
begin
// Data ready from memory?
if (done)
begin
// Update line already in cache
cache_data_w <= req_data;
cache_wr <= req_wr;
end
end
default:
;
endcase
end
end
 
//-----------------------------------------------------------------
// Control
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
wr_single <= 4'h0;
rd_single <= 1'b0;
flush_single <= 1'b0;
fill <= 1'b0;
evict <= 1'b0;
cache_data_w <= 32'h00000000;
cache_wr <= 4'b0;
ack <= 1'b0;
state <= STATE_IDLE;
end
else
begin
ack <= 1'b0;
tag_wr <= 1'b0;
fill <= 1'b0;
evict <= 1'b0;
cache_wr <= 4'b0;
data_wr <= 4'b0;
data_rd <= 1'b0;
wr_single <= 4'b0;
rd_single <= 1'b0;
 
if (flush_i)
req_flush <= 1'b1;
 
case (state)
 
//-----------------------------------------
218,65 → 694,25
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
begin
// Cache flush request
if (flush_i | req_flush)
begin
// Set to first line address
flush_single<= 1'b0;
end
// Read (uncacheable)
if (rd_i & ~cacheable)
else if (stb_i & ~we_i & ~cacheable)
begin
// Start read single from memory
req_address <= address_i;
req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
data_rd <= 1'b1;
req_rd <= 1'b1;
req_wr <= 4'b0;
req_ack <= 1'b1;
state <= STATE_SINGLE;
end
// Read (cacheable)
else if (rd_i)
begin
req_address <= address_i;
req_rd <= 1'b1;
req_wr <= 4'b0;
req_ack <= 1'b1;
state <= STATE_CHECK;
end
rd_single <= 1'b1;
end
// Write (uncacheable)
else if (wr_i != 4'b0000 & ~cacheable)
else if (stb_i & we_i & ~cacheable)
begin
// Perform write single
req_address <= address_i;
req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
data_w <= data_i;
data_wr <= wr_i;
req_wr <= wr_i;
req_rd <= 1'b0;
req_ack <= 1'b1;
state <= STATE_SINGLE;
end
// Write (cacheable)
else if (wr_i != 4'b0000)
begin
req_address <= address_i;
data_w <= data_i;
req_wr <= wr_i;
req_rd <= 1'b0;
req_ack <= 1'b0;
 
// Early ACK
ack <= 1'b1;
 
state <= STATE_WRITE;
end
// Cache flush request
else if (flush_i | req_flush)
begin
// Set to first line address
req_address <= 32'h00000000;
req_flush <= 1'b0;
req_ack <= 1'b0;
flush_single<= 1'b0;
state <= STATE_FLUSH2;
end
wr_single <= sel_i;
end
end
//-----------------------------------------
// WRITE - Wait for write-thru to complete
284,19 → 720,9
STATE_WRITE :
begin
// Cache hit
if (valid &&
(req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]))
if (valid & addr_hit)
begin
// Update line already in cache
cache_data_w <= data_w;
cache_wr <= req_wr;
 
// Mark line as dirty
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
tag_wr <= 1'b1;
 
state <= STATE_WAIT2;
end
// Cache dirty
else if (valid & dirty)
303,18 → 729,12
begin
// Evict cache line
evict <= 1'b1;
state <= STATE_EVICTING;
end
// Cache miss
else
begin
// Update tag memory with this line's details
tag_data_in <= {1'b1, 1'b1, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
 
// Fill cache line
fill <= 1'b1;
state <= STATE_UPDATE;
end
end
//-----------------------------------------
325,51 → 745,19
// Data ready from memory?
if (done)
begin
// Update tag memory with this new line's details
tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
 
// Fill cache line
fill <= 1'b1;
 
// Evict for read?
if (req_rd)
state <= STATE_FETCH;
// Evict for write
else
state <= STATE_UPDATE;
end
end
end
//-----------------------------------------
// UPDATE - Update fetched cache line
//-----------------------------------------
STATE_UPDATE:
begin
// Data ready from memory?
if (done)
begin
// Update line already in cache
cache_data_w <= data_w;
cache_wr <= req_wr;
 
// Mark line as dirty
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
tag_wr <= 1'b1;
 
state <= STATE_WAIT2;
end
end
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache hit
if (valid &&
(req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]))
if (valid & addr_hit)
begin
state <= STATE_IDLE;
 
end
// Cache dirty
else if (valid & dirty)
376,18 → 764,12
begin
// Evict cache line
evict <= 1'b1;
state <= STATE_EVICTING;
end
// Cache miss
else
begin
// Update tag memory with this line's details
tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
 
// Fill cache line
fill <= 1'b1;
state <= STATE_FETCH;
end
end
//-----------------------------------------
401,95 → 783,18
// Single WRITE?
if (~req_rd)
begin
state <= STATE_SINGLE_READY;
ack <= req_ack;
end
// Dirty? Write back
else if (valid & dirty)
else if (valid & dirty & addr_hit)
begin
// Evict cache line
evict <= 1'b1;
flush_single<= 1'b1;
state <= STATE_FLUSH4;
end
// Valid line, invalidate
else if (valid)
begin
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_wr <= 1'b1;
 
state <= STATE_SINGLE_READY;
ack <= req_ack;
end
else
begin
state <= STATE_SINGLE_READY;
ack <= req_ack;
end
end
end
end
//-----------------------------------------
// FETCH - Fetch row from memory
//-----------------------------------------
STATE_FETCH :
begin
// Cache line filled?
if (done)
state <= STATE_WAIT;
end
//-----------------------------------------
// WAIT - Wait cycle
//-----------------------------------------
STATE_WAIT :
begin
// Allow extra wait state to handle write & read collision
state <= STATE_WAIT2;
end
//-----------------------------------------
// WAIT2 - Wait cycle
//-----------------------------------------
STATE_WAIT2 :
begin
state <= STATE_IDLE;
ack <= req_ack;
end
//-----------------------------------------
// SINGLE_READY - Uncached access ready
//-----------------------------------------
STATE_SINGLE_READY :
begin
// Allow extra wait state to handle write & read collision
state <= STATE_IDLE;
end
//-----------------------------------------
// FLUSHx - Flush dirty lines & invalidate
//-----------------------------------------
STATE_FLUSH1 :
begin
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;
state <= STATE_WAIT;
end
else
begin
// Increment flush line address
req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] <=
req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] + 1;
 
state <= STATE_FLUSH2;
end
end
//-----------------------------------------
// FLUSH2 - Wait state
//-----------------------------------------
STATE_FLUSH2 :
begin
// Allow a cycle to read line state
state <= STATE_FLUSH3;
end
//-----------------------------------------
// FLUSH3 - Check if line dirty & flush
//-----------------------------------------
STATE_FLUSH3 :
499,47 → 804,77
begin
// Evict cache line
evict <= 1'b1;
state <= STATE_FLUSH4;
end
// Not dirty? Just invalidate
else
begin
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_wr <= 1'b1;
end
default:
;
endcase
end
end
 
if (flush_single)
state <= STATE_WAIT;
else
state <= STATE_FLUSH1;
end
end
//-----------------------------------------
// FLUSH4 - Wait for line flush to complete
//-----------------------------------------
STATE_FLUSH4 :
//-----------------------------------------------------------------
// ACK
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
ack <= 1'b0;
else
begin
ack <= 1'b0;
 
case (state)
 
//-----------------------------------------
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
// Write (cacheable), early acknowledge
if (~(flush_i | req_flush) & stb_i & we_i & cacheable)
ack <= 1'b1;
end
//-----------------------------------------
// FETCH_SINGLE - Single access to memory
//-----------------------------------------
STATE_SINGLE:
begin
// Data ready from memory?
if (done)
begin
// Cache line filled?
if (done)
// Single WRITE?
if (~req_rd)
ack <= req_ack;
// Dirty? Write back
else if (valid & dirty & addr_hit)
begin
// Invalidate line
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;
 
if (flush_single)
begin
state <= STATE_SINGLE_READY;
ack <= req_ack;
end
else
state <= STATE_FLUSH1;
end
end
default:
;
endcase
// Valid line, invalidate
else if (valid & addr_hit)
ack <= req_ack;
else
ack <= req_ack;
end
end
//-----------------------------------------
// WAIT2 - Wait cycle
//-----------------------------------------
STATE_WAIT2 :
begin
ack <= req_ack;
end
//-----------------------------------------
// FLUSH4 - Wait for line flush to complete
//-----------------------------------------
STATE_FLUSH4 :
begin
if (done & flush_single)
ack <= req_ack;
end
default:
;
endcase
end
end
 
559,13 → 894,13
// Cache interface
.address_i(muxed_address),
.data_i(data_w),
.data_i(req_data),
.data_o(data_r),
.fill_i(fill),
.evict_i(evict),
.evict_addr_i(line_address),
.rd_single_i(data_rd),
.wr_single_i(data_wr),
.rd_single_i(rd_single),
.wr_single_i(wr_single),
.done_o(done),
 
// Cache memory (fill/evict)
578,10 → 913,12
.mem_addr_o(mem_addr_o),
.mem_data_i(mem_data_i),
.mem_data_o(mem_data_o),
.mem_burst_o(mem_burst_o),
.mem_rd_o(mem_rd_o),
.mem_wr_o(mem_wr_o),
.mem_accept_i(mem_accept_i),
.mem_cti_o(mem_cti_o),
.mem_cyc_o(mem_cyc_o),
.mem_stb_o(mem_stb_o),
.mem_we_o(mem_we_o),
.mem_sel_o(mem_sel_o),
.mem_stall_i(mem_stall_i),
.mem_ack_i(mem_ack_i)
);
/rtl/cpu/altor32_noicache.v
54,13 → 54,14
output [31:0] instruction_o /*verilator public*/,
output valid_o /*verilator public*/,
// Memory interface (slave)
output reg [31:0] mem_addr_o /*verilator public*/,
input [31:0] mem_data_i /*verilator public*/,
output reg mem_burst_o /*verilator public*/,
output reg mem_rd_o /*verilator public*/,
input mem_accept_i/*verilator public*/,
input mem_ack_i/*verilator public*/
// Memory interface
output reg [31:0] wbm_addr_o /*verilator public*/,
input [31:0] wbm_dat_i /*verilator public*/,
output [2:0] wbm_cti_o /*verilator public*/,
output reg wbm_cyc_o /*verilator public*/,
output reg wbm_stb_o /*verilator public*/,
input wbm_stall_i/*verilator public*/,
input wbm_ack_i/*verilator public*/
);
 
//-----------------------------------------------------------------
70,11 → 71,13
// Current state
parameter STATE_CHECK = 0;
parameter STATE_FETCH = 1;
reg [1:0] state;
reg state;
 
assign valid_o = mem_ack_i;
assign instruction_o = mem_data_i;
reg ignore_resp;
 
assign valid_o = wbm_ack_i & ~ignore_resp & ~rd_i;
assign instruction_o = wbm_dat_i;
 
//-----------------------------------------------------------------
// Control logic
//-----------------------------------------------------------------
82,16 → 85,17
begin
if (rst_i == 1'b1)
begin
mem_addr_o <= 32'h00000000;
mem_rd_o <= 1'b0;
mem_burst_o <= 1'b0;
wbm_addr_o <= 32'h00000000;
wbm_stb_o <= 1'b0;
wbm_cyc_o <= 1'b0;
ignore_resp <= 1'b0;
state <= STATE_CHECK;
end
else
begin
if (mem_accept_i)
mem_rd_o <= 1'b0;
if (~wbm_stall_i)
wbm_stb_o <= 1'b0;
case (state)
 
101,9 → 105,10
STATE_CHECK :
begin
// Start fetch from memory
mem_addr_o <= pc_i;
mem_rd_o <= 1'b1;
mem_burst_o <= 1'b0;
wbm_addr_o <= pc_i;
wbm_stb_o <= 1'b1;
wbm_cyc_o <= 1'b1;
ignore_resp <= 1'b0;
state <= STATE_FETCH;
end
//-----------------------------------------
111,9 → 116,16
//-----------------------------------------
STATE_FETCH :
begin
// Read whilst waiting for previous response?
if (rd_i)
ignore_resp <= 1'b1;
 
// Data ready from memory?
if (mem_ack_i)
state <= STATE_CHECK;
if (wbm_ack_i)
begin
wbm_cyc_o <= 1'b0;
state <= STATE_CHECK;
end
end
default:
122,5 → 134,7
end
end
 
assign wbm_cti_o = 3'b111;
 
endmodule
 
/rtl/cpu/altor32_icache.v
43,7 → 43,7
//-----------------------------------------------------------------
// Module - Instruction Cache
//-----------------------------------------------------------------
module altor32_icache
module altor32_icache
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
59,13 → 59,14
output miss_o /*verilator public*/,
output busy_o /*verilator public*/,
 
// Memory interface (slave)
output reg [31:0] mem_addr_o /*verilator public*/,
input [31:0] mem_data_i /*verilator public*/,
output reg mem_burst_o /*verilator public*/,
output reg mem_rd_o /*verilator public*/,
input mem_accept_i/*verilator public*/,
input mem_ack_i/*verilator public*/
// Memory interface
output reg [31:0] wbm_addr_o /*verilator public*/,
input [31:0] wbm_dat_i /*verilator public*/,
output reg [2:0] wbm_cti_o /*verilator public*/,
output reg wbm_cyc_o /*verilator public*/,
output reg wbm_stb_o /*verilator public*/,
input wbm_stall_i/*verilator public*/,
input wbm_ack_i/*verilator public*/
);
 
//-----------------------------------------------------------------
100,28 → 101,36
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
 
// Tag read / write data
wire [CACHE_TAG_WIDTH-1:0] tag_data_out;
reg [CACHE_TAG_WIDTH-1:0] tag_data_in;
reg tag_wr;
 
// Tag address
wire [CACHE_LINE_ADDR_WIDTH-1:0] tag_entry;
 
// Data memory read / write
wire [CACHE_DWIDTH-1:0] cache_address_rd;
 
reg [CACHE_DWIDTH-1:0] cache_address_wr;
reg [31:0] cache_data_w;
reg [31:0] cache_data_in;
reg cache_wr;
 
reg [CACHE_LINE_SIZE_WIDTH-3:0] fetch_word;
// Word currently being fetched within a line
reg [CACHE_LINE_SIZE_WIDTH-3:0] mem_fetch_word;
reg [CACHE_LINE_SIZE_WIDTH-3:0] mem_resp_idx;
 
// Current / Miss PC
reg [31:0] last_pc;
reg [31:0] miss_pc;
 
reg initial_fetch;
// Flush state
reg flush_req;
 
reg [CACHE_LINE_ADDR_WIDTH-1:0] flush_addr;
reg flush_wr;
 
// Other state
reg initial_fetch;
reg read_while_busy;
 
// Current state
130,38 → 139,259
parameter STATE_WAIT = 2;
parameter STATE_WAIT2 = 3;
parameter STATE_FLUSH = 4;
reg [3:0] state;
reg [3:0] state;
 
assign tag_entry = (state != STATE_CHECK) ? miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] : pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH];
assign cache_address_rd = pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:2];
// Tag address from input PC or flopped version of it
assign tag_entry = (state != STATE_CHECK) ?
miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] :
pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH];
 
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 read address
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] ||
(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!
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}});
 
// Flushing: Last line to flush
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
!initial_fetch && // NOT initial fetch after reset
!rd_i && // NOT new read request cycle
!read_while_busy && // NOT pending read whilst busy
!flush_req && // NOT flush request
!invalidate_i);
 
//-----------------------------------------------------------------
// Control logic
// Next State Logic
//-----------------------------------------------------------------
reg [CACHE_LINE_SIZE_WIDTH-3:0] v_line_word;
reg [3:0] next_state_r;
always @ *
begin
next_state_r = state;
 
case (state)
 
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache flush request pending?
if (flush_req || invalidate_i)
next_state_r = STATE_FLUSH;
// Cache miss (& new read request not pending)
else if (cache_miss)
next_state_r = STATE_FETCH;
// Cache hit (or new read request)
else
next_state_r = STATE_CHECK;
end
//-----------------------------------------
// FETCH - Fetch row from memory
//-----------------------------------------
STATE_FETCH :
begin
// Line fetch complete?
if (mem_resp_idx == {CACHE_LINE_SIZE_WIDTH-2{1'b1}} && wbm_ack_i)
next_state_r = STATE_WAIT;
end
//-----------------------------------------
// FLUSH - Invalidate tag memory
//-----------------------------------------
STATE_FLUSH :
begin
if (flush_final_line)
next_state_r = STATE_FETCH;
else
next_state_r = STATE_FLUSH;
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:
;
endcase
end
 
// Update state
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
state <= STATE_CHECK;
else
state <= next_state_r;
end
 
 
//-----------------------------------------------------------------
// Check for cache misses
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
mem_addr_o <= 32'h00000000;
mem_rd_o <= 1'b0;
mem_burst_o <= 1'b0;
tag_wr <= 1'b0;
cache_address_wr<= {CACHE_DWIDTH{1'b0}};
cache_data_w <= 32'h00000000;
cache_wr <= 1'b0;
miss_pc <= BOOT_VECTOR + `VECTOR_RESET;
last_pc <= 32'h00000000;
state <= STATE_CHECK;
last_pc <= 32'h00000000;
initial_fetch <= 1'b1;
read_while_busy <= 1'b0;
end
else
begin
initial_fetch <= 1'b0;
last_pc <= pc_i;
// New request whilst cache busy?
if (rd_i)
read_while_busy <= 1'b1;
 
case (state)
 
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache miss (& new read request not pending)
if (cache_miss)
begin
read_while_busy <= 1'b0;
 
`ifdef CONF_CORE_DEBUG
$display("Fetch: Cache miss at 0x%x (last=%x, current=%x)", miss_pc, last_pc, pc_i);
`endif
end
// Cache hit (or new read request)
else
begin
`ifdef CONF_CORE_DEBUG
$display("Fetch: Cache hit at PC=%x (current=%x)", last_pc, pc_i);
if (read_while_busy)
$display("Fetch: Read request whilst busy PC=%x (current=%x)", last_pc, pc_i);
`endif
// Store fetch PC
miss_pc <= pc_i;
read_while_busy <= 1'b0;
end
end
//-----------------------------------------
// FLUSH - Invalidate tag memory
//-----------------------------------------
STATE_FLUSH :
begin
// Last line, clear pending reads whilst busy
if (flush_final_line)
read_while_busy <= 1'b0;
end
default:
;
endcase
end
end
 
//-----------------------------------------------------------------
// Cache Tag Write
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
tag_data_in <= {CACHE_TAG_WIDTH{1'b0}};
tag_wr <= 1'b0;
end
else
begin
tag_wr <= 1'b0;
 
case (state)
 
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache miss (& new read request not pending)
if (cache_miss)
begin
// Update tag memory with this line's details
tag_data_in <= {1'b1, miss_pc[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
end
end
//-----------------------------------------
// FLUSH - Invalidate tag memory
//-----------------------------------------
STATE_FLUSH :
begin
if (flush_final_line)
begin
// Update tag memory with this line's details
tag_data_in <= {1'b1, pc_i[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
end
end
default:
;
endcase
end
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 )
begin
if (rst_i == 1'b1)
begin
flush_addr <= {CACHE_LINE_ADDR_WIDTH{1'b0}};
flush_wr <= 1'b0;
flush_req <= 1'b0;
168,176 → 398,236
end
else
begin
if (mem_accept_i)
mem_rd_o <= 1'b0;
tag_wr <= 1'b0;
cache_wr <= 1'b0;
initial_fetch <= 1'b0;
flush_wr <= 1'b0;
last_pc <= pc_i;
// Latch invalidate request even if can't be actioned now...
if (invalidate_i)
flush_req <= 1'b1;
 
// New request whilst cache busy?
if (rd_i)
read_while_busy <= 1'b1;
 
case (state)
 
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache flush request pending?
if (flush_req || invalidate_i)
begin
// Cache flush request pending?
if (flush_req || invalidate_i)
begin
flush_req <= 1'b0;
flush_addr <= {CACHE_LINE_ADDR_WIDTH{1'b1}};
flush_wr <= 1'b1;
state <= STATE_FLUSH;
flush_req <= 1'b0;
flush_addr <= {CACHE_LINE_ADDR_WIDTH{1'b1}};
flush_wr <= 1'b1;
 
`ifdef CONF_CORE_DEBUG
$display("Fetch: Cache flush request");
`endif
end
// Cache miss (& new read request not pending)
else if ((miss_o && !initial_fetch) && !rd_i && !read_while_busy)
begin
read_while_busy <= 1'b0;
$display("Fetch: Cache flush request");
`endif
end
end
//-----------------------------------------
// FLUSH - Invalidate tag memory
//-----------------------------------------
STATE_FLUSH :
begin
if (~flush_final_line)
begin
flush_addr <= flush_addr - 1;
flush_wr <= 1'b1;
end
end
default:
;
endcase
end
end
 
fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
//-----------------------------------------------------------------
// External Mem Access
//-----------------------------------------------------------------
 
`ifdef CONF_CORE_DEBUG
$display("Fetch: Cache miss at 0x%x (last=%x, current=%x)", miss_pc, last_pc, pc_i);
`endif
// Start fetch from memory
mem_addr_o <= {miss_pc[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
mem_rd_o <= 1'b1;
mem_burst_o <= 1'b1;
state <= STATE_FETCH;
// Update tag memory with this line's details
tag_data_in <= {1'b1, miss_pc[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
end
// Cache hit (or new read request)
else
begin
`ifdef CONF_CORE_DEBUG
$display("Fetch: Cache hit at PC=%x (current=%x)", last_pc, pc_i);
if (read_while_busy)
$display("Fetch: Read request whilst busy PC=%x (current=%x)", last_pc, pc_i);
`endif
// Next fetch address
wire [CACHE_LINE_SIZE_WIDTH-3:0] mem_next_word = mem_fetch_word + 1;
 
// Store fetch PC
miss_pc <= pc_i;
state <= STATE_CHECK;
read_while_busy <= 1'b0;
end
end
//-----------------------------------------
// FETCH - Fetch row from memory
//-----------------------------------------
STATE_FETCH :
// Last word to fetch
wire mem_resp_idx_word = (mem_fetch_word == ({CACHE_LINE_WORDS_IDX_MAX{1'b1}}-1));
 
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
wbm_addr_o <= 32'h00000000;
wbm_cti_o <= 3'b0;
wbm_stb_o <= 1'b0;
 
mem_fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
end
else
begin
if (~wbm_stall_i)
wbm_stb_o <= 1'b0;
 
case (state)
 
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache miss (& new read request not pending)
if (cache_miss)
begin
// Data ready from memory?
if (mem_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], fetch_word};
cache_data_w <= mem_data_i;
cache_wr <= 1'b1;
// Start fetch from memory
wbm_addr_o <= {miss_pc[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
// Line fetch complete?
if (fetch_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
begin
state <= STATE_WAIT;
end
// Fetch next word for line
else
begin
v_line_word = fetch_word + 1'b1;
fetch_word <= v_line_word;
mem_addr_o <= {mem_addr_o[31:CACHE_LINE_SIZE_WIDTH], v_line_word, 2'b00};
mem_rd_o <= 1'b1;
if (fetch_word == ({CACHE_LINE_WORDS_IDX_MAX{1'b1}}-1))
begin
mem_burst_o <= 1'b0;
end
end
end
// Incrementing linear burst
wbm_cti_o <= 3'b010;
 
// Start of cycle
wbm_stb_o <= 1'b1;
mem_fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
end
//-----------------------------------------
// FLUSH - Invalidate tag memory
//-----------------------------------------
STATE_FLUSH :
begin
if (flush_addr == {CACHE_LINE_ADDR_WIDTH{1'b0}})
end
//-----------------------------------------
// FETCH - Fetch row from memory
//-----------------------------------------
STATE_FETCH :
begin
// Command accepted
if (~wbm_stall_i)
begin
// Fetch next word for line
if (!mem_fetch_final_word)
begin
// Fetch current PC line again
mem_addr_o <= {pc_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
mem_rd_o <= 1'b1;
mem_burst_o <= 1'b1;
state <= STATE_FETCH;
// Update tag memory with this line's details
tag_data_in <= {1'b1, pc_i[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
wbm_addr_o <= {wbm_addr_o[31:CACHE_LINE_SIZE_WIDTH], mem_next_word, 2'b00};
// Final word to read?
if (mem_resp_idx_word)
wbm_cti_o <= 3'b111;
 
// Start of line
fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
mem_fetch_word <= mem_next_word;
 
// Clear pending reads whilst busy
read_while_busy <= 1'b0;
end
else
begin
flush_addr <= flush_addr - 1;
flush_wr <= 1'b1;
state <= STATE_FLUSH;
end
end
//-----------------------------------------
// WAIT - Wait cycle
//-----------------------------------------
STATE_WAIT :
begin
// Allow extra wait state to handle write & read collision
state <= STATE_WAIT2;
end
//-----------------------------------------
// WAIT2 - Wait cycle
//-----------------------------------------
STATE_WAIT2 :
begin
`ifdef CONF_CORE_DEBUG
$display("Fetch: Filled line containing PC=%x", miss_pc);
`endif
state <= STATE_CHECK;
end
default:
;
endcase
// Still fetching...
wbm_stb_o <= 1'b1;
end
end
end
//-----------------------------------------
// FLUSH - Invalidate tag memory
//-----------------------------------------
STATE_FLUSH :
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}}};
// Incrementing linear burst
wbm_cti_o <= 3'b010;
 
// Start of cycle
wbm_stb_o <= 1'b1;
 
// Start of line
mem_fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
end
end
default:
;
endcase
end
end
 
// Stall the CPU if cache state machine is not idle!
assign busy_o = (state == STATE_CHECK & ~read_while_busy) ? 1'b0 : 1'b1;
//-----------------------------------------------------------------
// CYC_O
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
wbm_cyc_o <= 1'b0;
else
begin
case (state)
 
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache miss (& new read request not pending)
if (cache_miss)
wbm_cyc_o <= 1'b1;
end
//-----------------------------------------
// FLUSH - Invalidate tag memory
//-----------------------------------------
STATE_FLUSH :
begin
// Fetch current PC line again
if (flush_final_line)
wbm_cyc_o <= 1'b1;
end
//-----------------------------------------
// FETCH - Fetch row from memory
//-----------------------------------------
STATE_FETCH :
begin
// Last response?
if (wbm_ack_i && (mem_resp_idx == {CACHE_LINE_SIZE_WIDTH-2{1'b1}}))
wbm_cyc_o <= 1'b0;
end
default:
;
endcase
end
end
 
//-----------------------------------------------------------------
// Instantiation
// Memory response counter
//-----------------------------------------------------------------
// Tag memory
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
mem_resp_idx <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
else
begin
case (state)
 
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache miss (& new read request not pending)
if (cache_miss)
mem_resp_idx <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
end
//-----------------------------------------
// FLUSH - Invalidate tag memory
//-----------------------------------------
STATE_FLUSH :
begin
// Fetch current PC line again
if (flush_final_line)
mem_resp_idx <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
end
//-----------------------------------------
// FETCH - Fetch row from memory
//-----------------------------------------
STATE_FETCH :
begin
// Response
if (wbm_ack_i)
mem_resp_idx <= mem_resp_idx + 1;
end
default:
;
endcase
end
end
 
//-----------------------------------------------------------------
// Tag memory
//-----------------------------------------------------------------
altor32_ram_dp
#(
.WIDTH(CACHE_TAG_WIDTH),
345,6 → 635,7
)
u1_tag_mem
(
// Tag read/write port
.aclk_i(clk_i),
.adat_o(tag_data_out),
.adat_i(tag_data_in),
351,6 → 642,7
.aadr_i(tag_entry),
.awr_i(tag_wr),
// Tag invalidate port
.bclk_i(clk_i),
.badr_i(flush_addr),
.bdat_o(/*open*/),
357,8 → 649,10
.bdat_i({CACHE_TAG_WIDTH{1'b0}}),
.bwr_i(flush_wr)
);
 
//-----------------------------------------------------------------
// Data memory
//-----------------------------------------------------------------
altor32_ram_dp
#(
.WIDTH(32),
366,6 → 660,7
)
u2_data_mem
(
// Data read port
.aclk_i(clk_i),
.aadr_i(cache_address_rd),
.adat_o(instruction_o),
372,10 → 667,11
.adat_i(32'h00),
.awr_i(1'b0),
// Data write port
.bclk_i(clk_i),
.badr_i(cache_address_wr),
.bdat_o(/*open*/),
.bdat_i(cache_data_w),
.bdat_i(cache_data_in),
.bwr_i(cache_wr)
);
 
/rtl/cpu/altor32.v
41,7 → 41,7
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - AltOR32 CPU
// Module - AltOR32 CPU (Pipelined Wishbone Interfaces)
//-----------------------------------------------------------------
module cpu
(
56,21 → 56,24
 
// Instruction memory
output [31:0] imem_addr_o /*verilator public*/,
output imem_rd_o /*verilator public*/,
output imem_burst_o /*verilator public*/,
input [31:0] imem_data_in_i /*verilator public*/,
input imem_accept_i /*verilator public*/,
input imem_ack_i /*verilator public*/,
input [31:0] imem_dat_i /*verilator public*/,
output [2:0] imem_cti_o /*verilator public*/,
output imem_cyc_o /*verilator public*/,
output imem_stb_o /*verilator public*/,
input imem_stall_i/*verilator public*/,
input imem_ack_i/*verilator public*/,
 
// Data memory
output [31:0] dmem_addr_o /*verilator public*/,
output [31:0] dmem_data_out_o /*verilator public*/,
input [31:0] dmem_data_in_i /*verilator public*/,
output [3:0] dmem_wr_o /*verilator public*/,
output dmem_rd_o /*verilator public*/,
output dmem_burst_o /*verilator public*/,
input dmem_accept_i /*verilator public*/,
input dmem_ack_i /*verilator public*/
output [31:0] dmem_dat_o /*verilator public*/,
input [31:0] dmem_dat_i /*verilator public*/,
output [3:0] dmem_sel_o /*verilator public*/,
output [2:0] dmem_cti_o /*verilator public*/,
output dmem_cyc_o /*verilator public*/,
output dmem_we_o /*verilator public*/,
output dmem_stb_o /*verilator public*/,
input dmem_stall_i/*verilator public*/,
input dmem_ack_i/*verilator public*/
);
 
//-----------------------------------------------------------------
140,10 → 143,12
wire [31:0] dcache_addr;
wire [31:0] dcache_data_o;
wire [31:0] dcache_data_i;
wire [3:0] dcache_wr;
wire dcache_rd;
wire [3:0] dcache_sel;
wire dcache_we;
wire dcache_stb;
wire dcache_cyc;
wire dcache_ack;
wire dcache_accept;
wire dcache_stall;
wire dcache_flush;
 
//-----------------------------------------------------------------
176,16 → 181,17
.busy_o(icache_busy),
// Instruction memory
.mem_addr_o(imem_addr_o),
.mem_data_i(imem_data_in_i),
.mem_burst_o(imem_burst_o),
.mem_rd_o(imem_rd_o),
.mem_accept_i(imem_accept_i),
.mem_ack_i(imem_ack_i)
.wbm_addr_o(imem_addr_o),
.wbm_dat_i(imem_dat_i),
.wbm_cti_o(imem_cti_o),
.wbm_cyc_o(imem_cyc_o),
.wbm_stb_o(imem_stb_o),
.wbm_stall_i(imem_stall_i),
.wbm_ack_i(imem_ack_i)
);
end
else
begin
begin : NO_ICACHE
// No instruction cache
altor32_noicache
u_icache
200,12 → 206,13
.valid_o(icache_valid),
// Instruction memory
.mem_addr_o(imem_addr_o),
.mem_data_i(imem_data_in_i),
.mem_burst_o(imem_burst_o),
.mem_rd_o(imem_rd_o),
.mem_accept_i(imem_accept_i),
.mem_ack_i(imem_ack_i)
.wbm_addr_o(imem_addr_o),
.wbm_dat_i(imem_dat_i),
.wbm_cti_o(imem_cti_o),
.wbm_cyc_o(imem_cyc_o),
.wbm_stb_o(imem_stb_o),
.wbm_stall_i(imem_stall_i),
.wbm_ack_i(imem_ack_i)
);
end
endgenerate
246,7 → 253,7
// Register file
generate
if (REGISTER_FILE_TYPE == "XILINX")
begin
begin : REGFILE_XIL
altor32_regfile_xil
#(
.SUPPORT_32REGS(SUPPORT_32REGS)
268,7 → 275,7
);
end
else if (REGISTER_FILE_TYPE == "ALTERA")
begin
begin : REGFILE_ALT
altor32_regfile_alt
#(
.SUPPORT_32REGS(SUPPORT_32REGS)
290,7 → 297,7
);
end
else
begin
begin : REGFILE_SIM
altor32_regfile_sim
#(
.SUPPORT_32REGS(SUPPORT_32REGS)
315,7 → 322,7
 
generate
if (ENABLE_DCACHE == "ENABLED")
begin
begin : DCACHE
// Data cache
altor32_dcache
u_dcache
329,34 → 336,39
.address_i({dcache_addr[31:2], 2'b00}),
.data_o(dcache_data_i),
.data_i(dcache_data_o),
.wr_i(dcache_wr),
.rd_i(dcache_rd),
.accept_o(dcache_accept),
.we_i(dcache_we),
.stb_i(dcache_stb),
.sel_i(dcache_sel),
.stall_o(dcache_stall),
.ack_o(dcache_ack),
// Memory interface (slave)
.mem_addr_o(dmem_addr_o),
.mem_data_i(dmem_data_in_i),
.mem_data_o(dmem_data_out_o),
.mem_burst_o(dmem_burst_o),
.mem_rd_o(dmem_rd_o),
.mem_wr_o(dmem_wr_o),
.mem_accept_i(dmem_accept_i),
.mem_data_i(dmem_dat_i),
.mem_data_o(dmem_dat_o),
.mem_sel_o(dmem_sel_o),
.mem_we_o(dmem_we_o),
.mem_stb_o(dmem_stb_o),
.mem_cyc_o(dmem_cyc_o),
.mem_cti_o(dmem_cti_o),
.mem_stall_i(dmem_stall_i),
.mem_ack_i(dmem_ack_i)
);
end
else
begin
begin: NO_DCACHE
 
// No data cache
assign dmem_addr_o = {dcache_addr[31:2], 2'b00};
assign dmem_data_out_o = dcache_data_o;
assign dcache_data_i = dmem_data_in_i;
assign dmem_rd_o = dcache_rd;
assign dmem_wr_o = dcache_wr;
assign dmem_burst_o = 1'b0;
assign dmem_dat_o = dcache_data_o;
assign dcache_data_i = dmem_dat_i;
assign dmem_sel_o = dcache_sel;
assign dmem_cyc_o = dcache_cyc;
assign dmem_we_o = dcache_we;
assign dmem_stb_o = dcache_stb;
assign dmem_cti_o = 3'b111;
assign dcache_ack = dmem_ack_i;
assign dcache_accept = dmem_accept_i;
assign dcache_stall = dmem_stall_i;
end
endgenerate
 
416,9 → 428,11
.dmem_addr_o(dcache_addr),
.dmem_data_out_o(dcache_data_o),
.dmem_data_in_i(dcache_data_i),
.dmem_wr_o(dcache_wr),
.dmem_rd_o(dcache_rd),
.dmem_accept_i(dcache_accept),
.dmem_sel_o(dcache_sel),
.dmem_we_o(dcache_we),
.dmem_stb_o(dcache_stb),
.dmem_cyc_o(dcache_cyc),
.dmem_stall_i(dcache_stall),
.dmem_ack_i(dcache_ack)
);
 
/rtl/cpu/altor32_dcache_mem_if.v
62,13 → 62,15
// Memory interface (slave)
output reg [31:0] mem_addr_o /*verilator public*/,
input [31:0] mem_data_i /*verilator public*/,
input [31:0] mem_data_i /*verilator public*/,
output reg [31:0] mem_data_o /*verilator public*/,
output reg mem_burst_o /*verilator public*/,
output reg mem_rd_o /*verilator public*/,
output reg [3:0] mem_wr_o /*verilator public*/,
input mem_accept_i/*verilator public*/,
input mem_ack_i/*verilator public*/
output reg [2:0] mem_cti_o /*verilator public*/,
output reg mem_cyc_o /*verilator public*/,
output reg mem_stb_o /*verilator public*/,
output reg mem_we_o /*verilator public*/,
output reg [3:0] mem_sel_o /*verilator public*/,
input mem_stall_i/*verilator public*/,
input mem_ack_i/*verilator public*/
);
 
//-----------------------------------------------------------------
82,53 → 84,195
//-----------------------------------------------------------------
 
reg [31:CACHE_LINE_SIZE_WIDTH] line_address;
reg [CACHE_LINE_SIZE_WIDTH-3:0] line_word;
 
reg [CACHE_LINE_WORDS_IDX_MAX-1:0] response_idx;
 
reg [CACHE_LINE_WORDS_IDX_MAX-1:0] request_idx;
wire [CACHE_LINE_WORDS_IDX_MAX-1:0] next_request_idx = request_idx + 1'b1;
 
reg [CACHE_LINE_WORDS_IDX_MAX-1:0] cache_idx;
wire [CACHE_LINE_WORDS_IDX_MAX-1:0] next_cache_idx = cache_idx + 1'b1;
 
 
// Current state
parameter STATE_IDLE = 0;
parameter STATE_FETCH = 1;
parameter STATE_READ_WAIT = 2;
parameter STATE_WRITE_SETUP = 2;
parameter STATE_WRITE = 3;
parameter STATE_WRITE_WAIT = 4;
parameter STATE_READ_SINGLE = 5;
parameter STATE_WRITE_SINGLE= 6;
parameter STATE_MEM_SINGLE = 5;
parameter STATE_FETCH_WAIT = 6;
 
reg [3:0] state;
 
//-----------------------------------------------------------------
// Control logic
// Next State Logic
//-----------------------------------------------------------------
reg [CACHE_LINE_SIZE_WIDTH-3:0] v_line_word;
reg [3:0] next_state_r;
always @ *
begin
next_state_r = state;
 
case (state)
//-----------------------------------------
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
// Perform cache evict (write)
if (evict_i)
next_state_r = STATE_WRITE_SETUP;
// Perform cache fill (read)
else if (fill_i)
next_state_r = STATE_FETCH;
// Read/Write single
else if (rd_single_i | (|wr_single_i))
next_state_r = STATE_MEM_SINGLE;
end
//-----------------------------------------
// FETCH - Fetch line from memory
//-----------------------------------------
STATE_FETCH :
begin
// Line fetch complete?
if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
next_state_r = STATE_FETCH_WAIT;
end
//-----------------------------------------
// FETCH_WAIT - Wait for read responses
//-----------------------------------------
STATE_FETCH_WAIT:
begin
// Read from memory complete
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
next_state_r = STATE_IDLE;
end
//-----------------------------------------
// WRITE_SETUP - Wait for data from cache
//-----------------------------------------
STATE_WRITE_SETUP :
next_state_r = STATE_WRITE;
//-----------------------------------------
// WRITE - Write word to memory
//-----------------------------------------
STATE_WRITE :
begin
// Line write complete?
if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
next_state_r = STATE_WRITE_WAIT;
// Fetch next word for line
else if (~mem_stall_i | ~mem_stb_o)
next_state_r = STATE_WRITE_SETUP;
end
//-----------------------------------------
// WRITE_WAIT - Wait for write to complete
//-----------------------------------------
STATE_WRITE_WAIT:
begin
// Write to memory complete
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
next_state_r = STATE_IDLE;
end
//-----------------------------------------
// MEM_SINGLE - Single access to memory
//-----------------------------------------
STATE_MEM_SINGLE:
begin
// Data ready from memory?
if (mem_ack_i)
next_state_r = STATE_IDLE;
end
default:
;
endcase
end
 
// Update state
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
state <= STATE_IDLE;
else
state <= next_state_r;
end
 
//-----------------------------------------------------------------
// Control logic
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
line_address <= {32-CACHE_LINE_SIZE_WIDTH{1'b0}};
line_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
mem_addr_o <= 32'h00000000;
mem_data_o <= 32'h00000000;
mem_wr_o <= 4'h0;
mem_rd_o <= 1'b0;
mem_burst_o <= 1'b0;
cache_addr_o <= 30'h00000000;
cache_data_o <= 32'h00000000;
cache_wr_o <= 1'b0;
done_o <= 1'b0;
data_o <= 32'h00000000;
state <= STATE_IDLE;
end
else
begin
if (mem_accept_i)
begin
mem_rd_o <= 1'b0;
mem_wr_o <= 4'h0;
end
done_o <= 1'b0;
case (state)
 
done_o <= 1'b0;
//-----------------------------------------
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
// Perform cache evict (write)
if (evict_i)
line_address <= evict_addr_i[31:CACHE_LINE_SIZE_WIDTH];
// Perform cache fill (read)
else if (fill_i)
line_address <= address_i[31:CACHE_LINE_SIZE_WIDTH];
end
//-----------------------------------------
// FETCH/WRITE_WAIT - Wait for oustanding responses
//-----------------------------------------
STATE_WRITE_WAIT,
STATE_FETCH_WAIT:
begin
// Write to memory complete
if (mem_ack_i)
begin
// Line write complete?
if (response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
done_o <= 1'b1;
end
end
//-----------------------------------------
// MEM_SINGLE - Single access to memory
//-----------------------------------------
STATE_MEM_SINGLE:
begin
// Data ready from memory?
if (mem_ack_i)
begin
data_o <= mem_data_i;
done_o <= 1'b1;
end
end
default:
;
endcase
end
end
 
//-----------------------------------------------------------------
// Cache Read / Write
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
cache_addr_o <= 30'h00000000;
cache_data_o <= 32'h00000000;
cache_wr_o <= 1'b0;
 
cache_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
end
else
begin
cache_wr_o <= 1'b0;
case (state)
 
137,27 → 281,114
//-----------------------------------------
STATE_IDLE :
begin
cache_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
 
// Perform cache evict (write)
if (evict_i)
begin
line_address <= evict_addr_i[31:CACHE_LINE_SIZE_WIDTH];
line_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
 
// Read data from cache
cache_addr_o <= {evict_addr_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH-2{1'b0}}};
state <= STATE_READ_WAIT;
cache_addr_o <= {evict_addr_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_WORDS_IDX_MAX{1'b0}}};
end
end
//-----------------------------------------
// FETCH - Fetch line from memory
//-----------------------------------------
STATE_FETCH,
STATE_FETCH_WAIT:
begin
// Data ready from memory?
if (mem_ack_i)
begin
// Write data into cache
cache_addr_o <= {line_address, cache_idx};
cache_data_o <= mem_data_i;
cache_wr_o <= 1'b1;
 
cache_idx <= next_cache_idx;
end
end
//-----------------------------------------
// WRITE - Write word to memory
//-----------------------------------------
STATE_WRITE_SETUP:
begin
 
end
STATE_WRITE,
STATE_WRITE_WAIT:
begin
if (~mem_stall_i | ~mem_stb_o)
begin
// Setup next word read from cache
cache_addr_o <= {line_address, next_cache_idx};
cache_idx <= next_cache_idx;
end
end
default:
;
endcase
end
end
 
//-----------------------------------------------------------------
// Request
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
mem_addr_o <= 32'h00000000;
mem_data_o <= 32'h00000000;
mem_sel_o <= 4'h0;
mem_cti_o <= 3'b0;
mem_stb_o <= 1'b0;
mem_we_o <= 1'b0;
request_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
end
else
begin
if (~mem_stall_i)
begin
mem_stb_o <= 1'b0;
 
// TMP
if (mem_cti_o == 3'b111)
begin
//mem_addr_o <= 32'h00000000;
mem_data_o <= 32'h00000000;
mem_sel_o <= 4'h0;
mem_cti_o <= 3'b0;
mem_stb_o <= 1'b0;
mem_we_o <= 1'b0;
end
end
case (state)
 
//-----------------------------------------
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
request_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
 
// Perform cache evict (write)
if (evict_i)
begin
 
end
// Perform cache fill (read)
else if (fill_i)
begin
line_address <= address_i[31:CACHE_LINE_SIZE_WIDTH];
line_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
// Start fetch from memory
mem_addr_o <= {address_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
mem_rd_o <= 1'b1;
mem_burst_o <= 1'b1;
state <= STATE_FETCH;
mem_data_o <= 32'h00000000;
mem_sel_o <= 4'b1111;
mem_cti_o <= 3'b010;
mem_stb_o <= 1'b1;
mem_we_o <= 1'b0;
 
request_idx <= next_request_idx;
end
// Read single
else if (rd_single_i)
164,10 → 395,11
begin
// Start fetch from memory
mem_addr_o <= address_i;
mem_data_o <= 32'b0;
mem_rd_o <= 1'b1;
mem_burst_o <= 1'b0;
state <= STATE_READ_SINGLE;
mem_data_o <= 32'h00000000;
mem_sel_o <= 4'b1111;
mem_cti_o <= 3'b111;
mem_stb_o <= 1'b1;
mem_we_o <= 1'b0;
end
// Write single
else if (|wr_single_i)
175,9 → 407,10
// Start fetch from memory
mem_addr_o <= address_i;
mem_data_o <= data_i;
mem_wr_o <= wr_single_i;
mem_burst_o <= 1'b0;
state <= STATE_WRITE_SINGLE;
mem_sel_o <= wr_single_i;
mem_cti_o <= 3'b111;
mem_stb_o <= 1'b1;
mem_we_o <= 1'b1;
end
end
//-----------------------------------------
185,110 → 418,160
//-----------------------------------------
STATE_FETCH :
begin
// Data ready from memory?
if (mem_ack_i && mem_rd_o == 1'b0)
// Previous request accepted?
if (~mem_stall_i)
begin
// Write data into cache
cache_addr_o <= {line_address, line_word};
cache_data_o <= mem_data_i;
cache_wr_o <= 1'b1;
// Line fetch complete?
if (line_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
begin
done_o <= 1'b1;
state <= STATE_IDLE;
end
// Fetch next word for line
else
begin
v_line_word = line_word + 1'b1;
line_word <= v_line_word;
mem_addr_o <= {line_address, v_line_word, 2'b00};
mem_rd_o <= 1'b1;
if (line_word == ({CACHE_LINE_WORDS_IDX_MAX{1'b1}}-1))
begin
mem_burst_o <= 1'b0;
end
end
mem_addr_o <= {line_address, request_idx, 2'b00};
mem_stb_o <= 1'b1;
if (request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
mem_cti_o <= 3'b111;
 
request_idx <= next_request_idx;
end
end
//-----------------------------------------
// READ_WAIT - Wait for data from cache
//-----------------------------------------
STATE_READ_WAIT :
begin
// Not used yet, but set for start of burst
mem_burst_o <= 1'b1;
state <= STATE_WRITE;
end
//-----------------------------------------
// WRITE - Write word to memory
//-----------------------------------------
STATE_WRITE :
begin
// Write data into memory from cache
mem_addr_o <= {line_address, line_word, 2'b00};
mem_data_o <= cache_data_i;
mem_wr_o <= 4'b1111;
// Memory interface can request command?
if (~mem_stall_i | ~mem_stb_o)
begin
// Write data into memory from cache
mem_addr_o <= {line_address, request_idx, 2'b00};
mem_data_o <= cache_data_i;
mem_sel_o <= 4'b1111;
mem_stb_o <= 1'b1;
mem_we_o <= 1'b1;
if (request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
mem_cti_o <= 3'b111;
else
mem_cti_o <= 3'b010;
 
// Setup next word read from cache
v_line_word = line_word + 1'b1;
cache_addr_o <= {line_address, v_line_word};
request_idx <= next_request_idx;
end
end
default:
;
endcase
end
end
 
state <= STATE_WRITE_WAIT;
end
//-----------------------------------------------------------------
// Memory Response Counter
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
response_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
else
begin
case (state)
 
//-----------------------------------------
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
response_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
end
//-----------------------------------------
// FETCH - Fetch line from memory
//-----------------------------------------
STATE_FETCH,
STATE_FETCH_WAIT :
begin
// Data ready from memory?
if (mem_ack_i)
response_idx <= response_idx + 1'b1;
end
//-----------------------------------------
// WRITE_WAIT - Wait for write to complete
//-----------------------------------------
STATE_WRITE,
STATE_WRITE_SETUP,
STATE_WRITE_WAIT:
begin
// Write to memory complete
if (mem_ack_i && mem_wr_o == 4'b0)
if (mem_ack_i)
response_idx <= response_idx + 1'b1;
end
default:
;
endcase
end
end
 
//-----------------------------------------------------------------
// CYC_O
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
mem_cyc_o <= 1'b0;
else
begin
case (state)
 
//-----------------------------------------
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
// Perform cache evict (write)
if (evict_i)
begin
// Line write complete?
if (line_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
begin
done_o <= 1'b1;
state <= STATE_IDLE;
end
// Fetch next word for line
else
begin
line_word <= line_word + 1'b1;
state <= STATE_WRITE;
if (line_word == ({CACHE_LINE_WORDS_IDX_MAX{1'b1}}-1))
mem_burst_o <= 1'b0;
end
 
end
end
// Perform cache fill (read)
else if (fill_i)
mem_cyc_o <= 1'b1;
// Read single
else if (rd_single_i)
mem_cyc_o <= 1'b1;
// Write single
else if (|wr_single_i)
mem_cyc_o <= 1'b1;
end
//-----------------------------------------
// READ_SINGLE - Single access to memory
// FETCH - Fetch line from memory
//-----------------------------------------
STATE_READ_SINGLE:
STATE_FETCH :
begin
// Data ready from memory?
if (mem_ack_i && mem_rd_o == 1'b0)
begin
data_o <= mem_data_i;
done_o <= 1'b1;
state <= STATE_IDLE;
end
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
mem_cyc_o <= 1'b0;
end
//-----------------------------------------
// WRITE_SINGLE - Single access to memory
// WRITE - Write word to memory
//-----------------------------------------
STATE_WRITE_SINGLE:
STATE_WRITE :
begin
if (mem_ack_i && mem_wr_o == 4'b0)
begin
done_o <= 1'b1;
state <= STATE_IDLE;
end
end
// Write data into memory from cache
mem_cyc_o <= 1'b1;
end
//-----------------------------------------
// FETCH/WRITE_WAIT - Wait for responses
//-----------------------------------------
STATE_WRITE_WAIT,
STATE_FETCH_WAIT:
begin
// Write to memory complete
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
mem_cyc_o <= 1'b0;
end
//-----------------------------------------
// MEM_SINGLE - Single access to memory
//-----------------------------------------
STATE_MEM_SINGLE:
begin
// Data ready from memory?
if (mem_ack_i)
mem_cyc_o <= 1'b0;
end
default:
;
endcase
/rtl/cpu/altor32_exec.v
36,9 → 36,7
//-----------------------------------------------------------------
 
//`define CONF_CORE_DEBUG
//`define CONF_CORE_DEBUG_BUBBLE
//`define CONF_CORE_TRACE
//`define CONF_CORE_FAULT_ON_OPCODE0
 
//-----------------------------------------------------------------
// Includes
106,9 → 104,11
output reg [31:0] dmem_addr_o /*verilator public*/,
output reg [31:0] dmem_data_out_o /*verilator public*/,
input [31:0] dmem_data_in_i /*verilator public*/,
output reg [3:0] dmem_wr_o /*verilator public*/,
output reg dmem_rd_o /*verilator public*/,
input dmem_accept_i /*verilator public*/,
output reg [3:0] dmem_sel_o /*verilator public*/,
output reg dmem_we_o /*verilator public*/,
output reg dmem_stb_o /*verilator public*/,
output reg dmem_cyc_o /*verilator public*/,
input dmem_stall_i /*verilator public*/,
input dmem_ack_i /*verilator public*/
);
 
749,170 → 749,106
//-----------------------------------------------------------------
// Comparisons
//-----------------------------------------------------------------
reg [31:0] compare_a_r;
reg [31:0] compare_b_r;
always @ *
begin
compare_a_r = reg_ra_r;
compare_b_r = reg_rb_r;
 
case (1'b1)
inst_sfeqi_w, // l.sfeqi
inst_sfgesi_w, // l.sfgesi
inst_sfgeui_w, // l.sfgeui
inst_sfgtsi_w, // l.sfgtsi
inst_sfgtui_w, // l.sfgtui
inst_sflesi_w, // l.sflesi
inst_sfleui_w, // l.sfleui
inst_sfltsi_w, // l.sfltsi
inst_sfltui_w, // l.sfltui
inst_sfnei_w: // l.sfnei
compare_b_r = int32_r;
default:
;
endcase
end
 
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;
 
compare_lts_r = less_than_signed(compare_a_r, compare_b_r);
 
if (compare_a_r < compare_b_r)
compare_lt_r = 1'b1;
else
compare_lt_r = 1'b0;
 
// Greater than (signed)
compare_gts_r = ~(compare_lts_r | compare_equal_r);
 
if (compare_a_r > compare_b_r)
compare_gt_r = 1'b1;
else
compare_gt_r = 1'b0;
end
 
always @ *
begin
compare_result_r = 1'b0;
 
case (1'b1)
inst_sfeq_w: // l.sfeq
begin
if (reg_ra_r == reg_rb_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
 
inst_sfeq_w, // l.sfeq
inst_sfeqi_w: // l.sfeqi
begin
if (reg_ra_r == int32_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
compare_result_r = compare_equal_r;
 
inst_sfges_w: // l.sfges
begin
if (greater_than_equal_signed(reg_ra_r, reg_rb_r) == 1'b1)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
 
inst_sfges_w, // l.sfges
inst_sfgesi_w: // l.sfgesi
begin
if (greater_than_equal_signed(reg_ra_r, int32_r) == 1'b1)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
compare_result_r = compare_gts_r | compare_equal_r;
 
inst_sfgeu_w: // l.sfgeu
begin
if (reg_ra_r >= reg_rb_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
 
inst_sfgeu_w, // l.sfgeu
inst_sfgeui_w: // l.sfgeui
begin
if (reg_ra_r >= int32_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
compare_result_r = compare_gt_r | compare_equal_r;
 
inst_sfgts_w: // l.sfgts
begin
if (greater_than_signed(reg_ra_r, reg_rb_r) == 1'b1)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
 
inst_sfgts_w, // l.sfgts
inst_sfgtsi_w: // l.sfgtsi
begin
if (greater_than_signed(reg_ra_r, int32_r) == 1'b1)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
compare_result_r = compare_gts_r;
 
inst_sfgtu_w: // l.sfgtu
begin
if (reg_ra_r > reg_rb_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
 
inst_sfgtu_w, // l.sfgtu
inst_sfgtui_w: // l.sfgtui
begin
if (reg_ra_r > int32_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
compare_result_r = compare_gt_r;
 
inst_sfles_w: // l.sfles
begin
if (less_than_equal_signed(reg_ra_r, reg_rb_r) == 1'b1)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
 
inst_sfles_w, // l.sfles
inst_sflesi_w: // l.sflesi
begin
if (less_than_equal_signed(reg_ra_r, int32_r) == 1'b1)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
compare_result_r = compare_lts_r | compare_equal_r;
 
inst_sfleu_w: // l.sfleu
begin
if (reg_ra_r <= reg_rb_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
inst_sfleu_w, // l.sfleu
 
inst_sfleui_w: // l.sfleui
begin
if (reg_ra_r <= int32_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
compare_result_r = compare_lt_r | compare_equal_r;
 
inst_sflts_w: // l.sflts
begin
if (less_than_signed(reg_ra_r, reg_rb_r) == 1'b1)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
inst_sflts_w, // l.sflts
 
inst_sfltsi_w: // l.sfltsi
begin
if (less_than_signed(reg_ra_r, int32_r) == 1'b1)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
compare_result_r = compare_lts_r;
 
inst_sfltu_w: // l.sfltu
begin
if (reg_ra_r < reg_rb_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
inst_sfltu_w, // l.sfltu
 
inst_sfltui_w: // l.sfltui
begin
if (reg_ra_r < int32_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
compare_result_r = compare_lt_r;
 
inst_sfne_w: // l.sfne
begin
if (reg_ra_r != reg_rb_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
inst_sfne_w, // l.sfne
 
inst_sfnei_w: // l.sfnei
begin
if (reg_ra_r != int32_r)
compare_result_r = 1'b1;
else
compare_result_r = 1'b0;
end
compare_result_r = ~compare_equal_r;
default:
;
endcase
1330,8 → 1266,10
// Data memory
dmem_addr_o <= 32'h00000000;
dmem_data_out_o <= 32'h00000000;
dmem_rd_o <= 1'b0;
dmem_wr_o <= 4'b0000;
dmem_we_o <= 1'b0;
dmem_sel_o <= 4'b0000;
dmem_stb_o <= 1'b0;
dmem_cyc_o <= 1'b0;
r_mem_load <= 1'b0;
r_mem_store <= 1'b0;
1347,12 → 1285,11
begin
 
// If memory access accepted by slave
if (dmem_accept_i)
begin
dmem_rd_o <= 1'b0;
dmem_wr_o <= 4'b0000;
end
if (~dmem_stall_i)
dmem_stb_o <= 1'b0;
 
if (dmem_ack_i)
dmem_cyc_o <= 1'b0;
r_mem_access <= 1'b0;
d_mem_load <= r_mem_access & r_mem_load;
 
1391,7 → 1328,10
begin
dmem_addr_o <= mem_addr_r;
dmem_data_out_o <= 32'h00000000;
dmem_rd_o <= 1'b1;
dmem_sel_o <= 4'b1111;
dmem_we_o <= 1'b0;
dmem_stb_o <= 1'b1;
dmem_cyc_o <= 1'b1;
 
// Mark load as pending
r_mem_load <= 1'b1;
1415,32 → 1355,41
2'b00 :
begin
dmem_data_out_o <= {reg_rb_r[7:0],24'h000000};
dmem_wr_o <= 4'b1000;
dmem_sel_o <= 4'b1000;
dmem_we_o <= 1'b1;
dmem_stb_o <= 1'b1;
dmem_cyc_o <= 1'b1;
r_mem_store <= 1'b1;
end
2'b01 :
begin
dmem_data_out_o <= {{8'h00,reg_rb_r[7:0]},16'h0000};
dmem_wr_o <= 4'b0100;
dmem_sel_o <= 4'b0100;
dmem_we_o <= 1'b1;
dmem_stb_o <= 1'b1;
dmem_cyc_o <= 1'b1;
r_mem_store <= 1'b1;
end
2'b10 :
begin
dmem_data_out_o <= {{16'h0000,reg_rb_r[7:0]},8'h00};
dmem_wr_o <= 4'b0010;
dmem_sel_o <= 4'b0010;
dmem_we_o <= 1'b1;
dmem_stb_o <= 1'b1;
dmem_cyc_o <= 1'b1;
r_mem_store <= 1'b1;
end
2'b11 :
begin
dmem_data_out_o <= {24'h000000,reg_rb_r[7:0]};
dmem_wr_o <= 4'b0001;
dmem_sel_o <= 4'b0001;
dmem_we_o <= 1'b1;
dmem_stb_o <= 1'b1;
dmem_cyc_o <= 1'b1;
r_mem_store <= 1'b1;
end
default :
begin
dmem_data_out_o <= 32'h00000000;
dmem_wr_o <= 4'b0000;
end
;
endcase
end
 
1452,20 → 1401,23
2'b00 :
begin
dmem_data_out_o <= {reg_rb_r[15:0],16'h0000};
dmem_wr_o <= 4'b1100;
dmem_sel_o <= 4'b1100;
dmem_we_o <= 1'b1;
dmem_stb_o <= 1'b1;
dmem_cyc_o <= 1'b1;
r_mem_store <= 1'b1;
end
2'b10 :
begin
dmem_data_out_o <= {16'h0000,reg_rb_r[15:0]};
dmem_wr_o <= 4'b0011;
dmem_sel_o <= 4'b0011;
dmem_we_o <= 1'b1;
dmem_stb_o <= 1'b1;
dmem_cyc_o <= 1'b1;
r_mem_store <= 1'b1;
end
default :
begin
dmem_data_out_o <= 32'h00000000;
dmem_wr_o <= 4'b0000;
end
;
endcase
end
 
1473,7 → 1425,10
begin
dmem_addr_o <= mem_addr_r;
dmem_data_out_o <= reg_rb_r;
dmem_wr_o <= 4'b1111;
dmem_sel_o <= 4'b1111;
dmem_we_o <= 1'b1;
dmem_stb_o <= 1'b1;
dmem_cyc_o <= 1'b1;
r_mem_access <= 1'b1;
r_mem_store <= 1'b1;
 
1619,6 → 1574,26
get_putc = 8'b0;
`endif
endfunction
function [0:0] get_reg_valid;
// verilator public
get_reg_valid = ~(resolve_failed | load_stall);
endfunction
function [4:0] get_reg_ra;
// verilator public
get_reg_ra = reg_ra_i;
endfunction
function [31:0] get_reg_ra_value;
// verilator public
get_reg_ra_value = ra_value_resolved;
endfunction
function [4:0] get_reg_rb;
// verilator public
get_reg_rb = reg_rb_i;
endfunction
function [31:0] get_reg_rb_value;
// verilator public
get_reg_rb_value = rb_value_resolved;
endfunction
`endif
 
endmodule
/rtl/cpu/altor32_regfile_sim.v
45,15 → 45,15
//-----------------------------------------------------------------
module altor32_regfile_sim
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
input wr_i /*verilator public*/,
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*/,
input [31:0] reg_rd_i /*verilator public*/
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
input wr_i /*verilator public*/,
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*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
//-----------------------------------------------------------------
98,9 → 98,6
reg [31:0] reg_r30;
reg [31:0] reg_r31;
 
reg [31:0] reg_rs_o;
reg [31:0] reg_rt_o;
 
//-----------------------------------------------------------------
// Register File (for simulation)
//-----------------------------------------------------------------
/rtl/sim/ram.v
1,4 → 1,41
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module: ram - dual port block RAM
//-----------------------------------------------------------------
module ram
5,19 → 42,25
(
// Port A
input clka_i /*verilator public*/,
input ena_i /*verilator public*/,
input [3:0] wea_i /*verilator public*/,
input rsta_i /*verilator public*/,
input stba_i /*verilator public*/,
input wea_i /*verilator public*/,
input [3:0] sela_i /*verilator public*/,
input [31:2] addra_i /*verilator public*/,
input [31:0] dataa_i /*verilator public*/,
output [31:0] dataa_o /*verilator public*/,
output reg acka_o /*verilator public*/,
 
// Port B
input clkb_i /*verilator public*/,
input enb_i /*verilator public*/,
input [3:0] web_i /*verilator public*/,
input rstb_i /*verilator public*/,
input stbb_i /*verilator public*/,
input web_i /*verilator public*/,
input [3:0] selb_i /*verilator public*/,
input [31:2] addrb_i /*verilator public*/,
input [31:0] datab_i /*verilator public*/,
output [31:0] datab_o /*verilator public*/
output [31:0] datab_o /*verilator public*/,
output reg ackb_o /*verilator public*/
);
 
//-----------------------------------------------------------------
30,6 → 73,9
// Instantiation
//-----------------------------------------------------------------
 
wire [3:0] wr_a = {4{stba_i}} & {4{wea_i}} & sela_i;
wire [3:0] wr_b = {4{stbb_i}} & {4{web_i}} & selb_i;
 
ram_dp8
#(
.WIDTH(8),
41,13 → 87,13
.aadr_i(addra_i[SIZE+2-1:2]),
.adat_o(dataa_o[7:0]),
.adat_i(dataa_i[7:0]),
.awr_i(wea_i[0]),
.awr_i(wr_a[0]),
.bclk_i(clkb_i),
.badr_i(addrb_i[SIZE+2-1:2]),
.bdat_o(datab_o[7:0]),
.bdat_i(datab_i[7:0]),
.bwr_i(web_i[0])
.bwr_i(wr_b[0])
);
 
ram_dp8
61,13 → 107,13
.aadr_i(addra_i[SIZE+2-1:2]),
.adat_o(dataa_o[15:8]),
.adat_i(dataa_i[15:8]),
.awr_i(wea_i[1]),
.awr_i(wr_a[1]),
.bclk_i(clkb_i),
.badr_i(addrb_i[SIZE+2-1:2]),
.bdat_o(datab_o[15:8]),
.bdat_i(datab_i[15:8]),
.bwr_i(web_i[1])
.bwr_i(wr_b[1])
);
 
ram_dp8
81,13 → 127,13
.aadr_i(addra_i[SIZE+2-1:2]),
.adat_o(dataa_o[23:16]),
.adat_i(dataa_i[23:16]),
.awr_i(wea_i[2]),
.awr_i(wr_a[2]),
.bclk_i(clkb_i),
.badr_i(addrb_i[SIZE+2-1:2]),
.bdat_o(datab_o[23:16]),
.bdat_i(datab_i[23:16]),
.bwr_i(web_i[2])
.bwr_i(wr_b[2])
);
 
ram_dp8
101,13 → 147,39
.aadr_i(addra_i[SIZE+2-1:2]),
.adat_o(dataa_o[31:24]),
.adat_i(dataa_i[31:24]),
.awr_i(wea_i[3]),
.awr_i(wr_a[3]),
.bclk_i(clkb_i),
.badr_i(addrb_i[SIZE+2-1:2]),
.bdat_o(datab_o[31:24]),
.bdat_i(datab_i[31:24]),
.bwr_i(web_i[3])
.bwr_i(wr_b[3])
);
 
// AckA
always @(posedge clka_i or posedge rsta_i)
begin
if (rsta_i == 1'b1)
begin
acka_o <= 1'b0;
end
else
begin
acka_o <= stba_i;
end
end
 
// AckB
always @(posedge clkb_i or posedge rstb_i)
begin
if (rstb_i == 1'b1)
begin
ackb_o <= 1'b0;
end
else
begin
ackb_o <= stbb_i;
end
end
 
endmodule
/rtl/sim/top.v
64,26 → 64,32
wire [31:0] soc_addr;
wire [31:0] soc_data_w;
wire [31:0] soc_data_r;
wire [3:0] soc_wr;
wire soc_rd;
wire soc_we;
wire soc_stb;
wire soc_ack;
wire soc_irq;
 
wire[31:0] dmem_address;
wire[31:0] dmem_data_w;
wire[31:0] dmem_data_r;
wire[3:0] dmem_wr;
wire dmem_rd;
wire dmem_burst;
wire[3:0] dmem_sel;
wire[2:0] dmem_cti;
wire dmem_we;
wire dmem_stb;
wire dmem_cyc;
wire dmem_stall;
wire dmem_ack;
reg dmem_req_r;
 
wire[31:0] imem_addr;
wire[31:0] imem_data;
wire imem_rd;
wire imem_burst;
wire[3:0] imem_sel;
wire imem_stb;
wire imem_cyc;
wire[2:0] imem_cti;
wire imem_stall;
wire imem_ack;
reg imem_req_r;
 
 
//-----------------------------------------------------------------
// Instantiation
//-----------------------------------------------------------------
96,21 → 102,26
u_ram
(
.clka_i(clk_i),
.ena_i(1'b1),
.wea_i(4'b0),
.rsta_i(rst_i),
.stba_i(imem_stb),
.wea_i(1'b0),
.sela_i(imem_sel),
.addra_i(imem_addr[31:2]),
.dataa_i(32'b0),
.dataa_o(imem_data),
.acka_o(imem_ack),
 
.clkb_i(clk_i),
.enb_i(1'b1),
.web_i(dmem_wr),
.rstb_i(rst_i),
.stbb_i(dmem_stb),
.web_i(dmem_we),
.selb_i(dmem_sel),
.addrb_i(dmem_address[31:2]),
.datab_i(dmem_data_w),
.datab_o(dmem_data_r)
.datab_o(dmem_data_r),
.ackb_o(dmem_ack)
);
 
 
// CPU
cpu_if
#(
133,10 → 144,12
 
// Instruction Memory 0 (0x10000000 - 0x10FFFFFF)
.imem0_addr_o(imem_addr),
.imem0_rd_o(imem_rd),
.imem0_burst_o(imem_burst),
.imem0_data_in_i(imem_data),
.imem0_accept_i(1'b1),
.imem0_data_i(imem_data),
.imem0_sel_o(imem_sel),
.imem0_cti_o(imem_cti),
.imem0_cyc_o(imem_cyc),
.imem0_stb_o(imem_stb),
.imem0_stall_i(1'b0),
.imem0_ack_i(imem_ack),
 
// Data Memory 0 (0x10000000 - 0x10FFFFFF)
143,20 → 156,24
.dmem0_addr_o(dmem_address),
.dmem0_data_o(dmem_data_w),
.dmem0_data_i(dmem_data_r),
.dmem0_wr_o(dmem_wr),
.dmem0_rd_o(dmem_rd),
.dmem0_accept_i(1'b1),
.dmem0_burst_o(dmem_burst),
.dmem0_sel_o(dmem_sel),
.dmem0_cti_o(dmem_cti),
.dmem0_cyc_o(dmem_cyc),
.dmem0_we_o(dmem_we),
.dmem0_stb_o(dmem_stb),
.dmem0_stall_i(1'b0),
.dmem0_ack_i(dmem_ack),
// Data Memory 1 (0x11000000 - 0x11FFFFFF)
.dmem1_addr_o(),
.dmem1_data_o(),
.dmem1_addr_o(/*open*/),
.dmem1_data_o(/*open*/),
.dmem1_data_i(32'b0),
.dmem1_wr_o(),
.dmem1_rd_o(),
.dmem1_accept_i(1'b1),
.dmem1_burst_o(/*open*/),
.dmem1_sel_o(/*open*/),
.dmem1_we_o(/*open*/),
.dmem1_stb_o(/*open*/),
.dmem1_cyc_o(/*open*/),
.dmem1_cti_o(/*open*/),
.dmem1_stall_i(1'b0),
.dmem1_ack_i(1'b1),
 
// Data Memory 2 (0x12000000 - 0x12FFFFFF)
163,11 → 180,13
.dmem2_addr_o(soc_addr),
.dmem2_data_o(soc_data_w),
.dmem2_data_i(soc_data_r),
.dmem2_wr_o(soc_wr),
.dmem2_rd_o(soc_rd),
.dmem2_accept_i(1'b1),
.dmem2_burst_o(/*open*/),
.dmem2_ack_i(1'b1)
.dmem2_sel_o(/*open*/),
.dmem2_we_o(soc_we),
.dmem2_stb_o(soc_stb),
.dmem2_cyc_o(/*open*/),
.dmem2_cti_o(/*open*/),
.dmem2_stall_i(1'b0),
.dmem2_ack_i(soc_ack)
);
 
// CPU SOC
190,38 → 209,9
.io_addr_i(soc_addr),
.io_data_i(soc_data_w),
.io_data_o(soc_data_r),
.io_wr_i(soc_wr),
.io_rd_i(soc_rd)
.io_we_i(soc_we),
.io_stb_i(soc_stb),
.io_ack_o(soc_ack)
);
 
// Ack
always @(posedge clk_i or posedge rst_i)
begin
if (rst_i == 1'b1)
begin
imem_req_r <= 1'b0;
end
else
begin
imem_req_r <= imem_rd;
end
end
 
assign imem_ack = imem_req_r;
 
// Ack
always @(posedge clk_i or posedge rst_i)
begin
if (rst_i == 1'b1)
begin
dmem_req_r <= 1'b0;
end
else
begin
dmem_req_r <= dmem_rd | (|dmem_wr);
end
end
 
assign dmem_ack = dmem_req_r;
endmodule
/rtl/sim/ram_dp8.v
1,3 → 1,39
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module: ram_dp8 - dual port block RAM
/rtl/peripheral/intr_periph.v
65,8 → 65,8
addr_i,
data_o,
data_i,
wr_i,
rd_i
we_i,
stb_i
);
 
//-----------------------------------------------------------------
94,8 → 94,8
input [7:0] addr_i /*verilator public*/;
output [31:0] data_o /*verilator public*/;
input [31:0] data_i /*verilator public*/;
input [3:0] wr_i /*verilator public*/;
input rd_i /*verilator public*/;
input we_i /*verilator public*/;
input stb_i /*verilator public*/;
 
//-----------------------------------------------------------------
// Registers / Wires
175,7 → 175,7
intr_o <= ((v_irq_status & irq_mask) != {(INTERRUPT_COUNT){1'b0}}) ? 1'b1 : 1'b0;
 
// Write Cycle
if (wr_i != 4'b0000)
if (we_i & stb_i)
begin
case (addr_i)
 
198,33 → 198,22
//-----------------------------------------------------------------
// Peripheral Register Read
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
always @ *
begin
if (rst_i == 1'b1)
begin
data_o <= 32'h00000000;
end
else
begin
// Read cycle?
if (rd_i == 1'b1)
begin
case (addr_i[7:0])
case (addr_i[7:0])
 
`IRQ_MASK_SET :
data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_mask};
`IRQ_MASK_SET :
data_o = {{(32-INTERRUPT_COUNT){1'b0}}, irq_mask};
 
`IRQ_MASK_CLR :
data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_mask};
`IRQ_MASK_CLR :
data_o = {{(32-INTERRUPT_COUNT){1'b0}}, irq_mask};
 
`IRQ_STATUS :
data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_status};
`IRQ_STATUS :
data_o = {{(32-INTERRUPT_COUNT){1'b0}}, irq_status};
 
default :
data_o <= 32'h00000000;
endcase
end
end
default :
data_o = 32'h00000000;
endcase
end
 
endmodule
/rtl/peripheral/timer_periph.v
57,8 → 57,8
addr_i,
data_o,
data_i,
wr_i,
rd_i
we_i,
stb_i
);
 
//-----------------------------------------------------------------
81,8 → 81,8
input [7:0] addr_i /*verilator public*/;
output [31:0] data_o /*verilator public*/;
input [31:0] data_i /*verilator public*/;
input [3:0] wr_i /*verilator public*/;
input rd_i /*verilator public*/;
input we_i /*verilator public*/;
input stb_i /*verilator public*/;
 
//-----------------------------------------------------------------
// Registers / Wires
231,7 → 231,7
else
begin
// Write Cycle
if (wr_i != 4'b0000)
if (we_i & stb_i)
begin
case (addr_i)
 
248,32 → 248,21
//-----------------------------------------------------------------
// Peripheral Register Read
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
always @ *
begin
if (rst_i == 1'b1)
begin
data_o <= 32'h00000000;
end
else
begin
// Read cycle?
if (rd_i == 1'b1)
begin
case (addr_i[7:0])
case (addr_i[7:0])
 
// 32-bit systick/1ms counter
`TIMER_SYSTICK_VAL :
data_o <= systick_count;
// 32-bit systick/1ms counter
`TIMER_SYSTICK_VAL :
data_o = systick_count;
 
// Hi res timer (clock rate)
`TIMER_HIRES :
data_o <= hr_timer_cnt;
// Hi res timer (clock rate)
`TIMER_HIRES :
data_o = hr_timer_cnt;
 
default :
data_o <= 32'h00000000;
endcase
end
end
default :
data_o = 32'h00000000;
endcase
end
 
endmodule

powered by: WebSVN 2.1.0

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