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

Subversion Repositories openrisc_me

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/orpsocv2/boards
    from Rev 482 to Rev 483
    Reverse comparison

Rev 482 → Rev 483

/actel/ordb1a3pe1500/sw/Makefile.inc
8,7 → 8,8
# Figure out actual path the common software directory
SW_ROOT=$(BOARD_SW_ROOT)/$(PROJ_ROOT)/sw
 
# Set the BOARD_PATH to point to the root of this board build
# Set the BOARD to be the path within the board/ path of the project that goes
# to this project.
BOARD=actel/ordb1a3pe1500
 
# Set RTL_VERILOG_INCLUDE_DIR so software
/actel/ordb1a3pe1500/sw/board/include/board.h
15,11 → 15,14
// Uncomment the appropriate bootloader define. This will effect the bootrom.S
// file, which is compiled and converted into Verilog for inclusion at
// synthesis time. See bootloader/bootloader.S for details on each option.
 
#ifndef PRELOAD_RAM
#define BOOTROM_SPI_FLASH
//#define BOOTROM_GOTO_RESET
//#define BOOTROM_LOOP_AT_ZERO
//#define BOOTROM_LOOP_IN_ROM
#else
#define BOOTROM_GOTO_RESET
#endif
 
//
// Defines for each core (memory map base, OR1200 interrupt line number, etc.)
/generic/ft/bench/verilog/include/timescale.v
0,0 → 1,41
//////////////////////////////////////////////////////////////////////
//// ////
//// ORPSoC Testbench Timescale ////
//// ////
//// Description ////
//// ORPSoC testbench timescale file ////
//// ////
//// To Do: ////
//// - ////
//// ////
//// Author(s): ////
//// - jb, jb@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG ////
//// ////
//// 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, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
`timescale 1ns/10ps
/generic/ft/bench/verilog/orpsoc_testbench.v
0,0 → 1,229
//////////////////////////////////////////////////////////////////////
/// ////
/// ORPSoC testbench ////
/// ////
/// Instantiate ORPSoC, monitors, provide stimulus ////
/// ////
/// Julius Baxter, julius@opencores.org ////
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// 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, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "orpsoc-defines.v"
`include "orpsoc-testbench-defines.v"
`include "test-defines.v"
 
`include "timescale.v"
 
module orpsoc_testbench;
 
reg clk = 0;
reg rst_n = 1; // Active LOW
always
#((`BOARD_CLOCK_PERIOD)/2) clk <= ~clk;
 
// Reset, ACTIVE LOW
initial
begin
#1;
repeat (32) @(negedge clk)
rst_n <= 1;
repeat (32) @(negedge clk)
rst_n <= 0;
repeat (32) @(negedge clk)
rst_n <= 1;
end
 
`include "orpsoc-params.v"
 
`ifdef JTAG_DEBUG
wire tdo_pad_o;
wire tck_pad_i;
wire tms_pad_i;
wire tdi_pad_i;
`endif
`ifdef UART0
wire uart0_stx_pad_o;
wire uart0_srx_pad_i;
`endif
orpsoc_top dut
(
.clk_pad_i (clk),
`ifdef JTAG_DEBUG
.tms_pad_i (tms_pad_i),
.tck_pad_i (tck_pad_i),
.tdi_pad_i (tdi_pad_i),
.tdo_pad_o (tdo_pad_o),
`endif
`ifdef UART0
.uart0_stx_pad_o (uart0_stx_pad_o),
.uart0_srx_pad_i (uart0_srx_pad_i),
`endif
.rst_n_pad_i (rst_n)
);
 
//
// Instantiate OR1200 monitor
//
or1200_monitor monitor();
 
or1200_ft_stim ft_stim();
 
`ifndef SIM_QUIET
`define CPU_ic_top or1200_ic_top
`define CPU_dc_top or1200_dc_top
wire ic_en = orpsoc_testbench.dut.or1200_top0.or1200_ic_top.ic_en;
always @(posedge ic_en)
$display("Or1200 IC enabled at %t", $time);
 
wire dc_en = orpsoc_testbench.dut.or1200_top0.or1200_dc_top.dc_en;
always @(posedge dc_en)
$display("Or1200 DC enabled at %t", $time);
`endif
 
 
`ifdef JTAG_DEBUG
`ifdef VPI_DEBUG
// Debugging interface
vpi_debug_module vpi_dbg
(
.tms(tms_pad_i),
.tck(tck_pad_i),
.tdi(tdi_pad_i),
.tdo(tdo_pad_o)
);
`else
// If no VPI debugging, tie off JTAG inputs
assign tdi_pad_i = 1;
assign tck_pad_i = 0;
assign tms_pad_i = 1;
`endif // !`ifdef VPI_DEBUG_ENABLE
`endif // `ifdef JTAG_DEBUG
 
initial
begin
`ifndef SIM_QUIET
$display("\n* Starting simulation of ORPSoC RTL.\n* Test: %s\n",
`TEST_NAME_STRING );
`endif
`ifdef VCD
`ifdef VCD_DELAY
#(`VCD_DELAY);
`endif
 
// Delay by x insns
`ifdef VCD_DELAY_INSNS
#10; // Delay until after the value becomes valid
while (monitor.insns < `VCD_DELAY_INSNS)
@(posedge clk);
`endif
 
`ifdef SIMULATOR_MODELSIM
// Modelsim can GZip VCDs on the fly if given in the suffix
`define VCD_SUFFIX ".vcd.gz"
`else
`define VCD_SUFFIX ".vcd"
`endif
`ifndef SIM_QUIET
$display("* VCD in %s\n", {"../out/",`TEST_NAME_STRING,`VCD_SUFFIX});
`endif
$dumpfile({"../out/",`TEST_NAME_STRING,`VCD_SUFFIX});
`ifndef VCD_DEPTH
`define VCD_DEPTH 0
`endif
$dumpvars(`VCD_DEPTH);
`endif
end // initial begin
`ifdef END_TIME
initial begin
#(`END_TIME);
`ifndef SIM_QUIET
$display("* Finish simulation due to END_TIME being set at %t", $time);
`endif
$finish;
end
`endif
 
`ifdef END_INSNS
initial begin
#10
while (monitor.insns < `END_INSNS)
@(posedge clk);
`ifndef SIM_QUIET
$display("* Finish simulation due to END_INSNS count (%d) reached at %t",
`END_INSNS, $time);
`endif
$finish;
end
`endif
`ifdef UART0
//
// UART0 decoder
//
uart_decoder
#(
.uart_baudrate_period_ns(8680) // 115200 baud = period 8.68uS
)
uart0_decoder
(
.clk(clk),
.uart_tx(uart0_stx_pad_o)
);
// UART0 stimulus
/*
uart_stim
#(
.uart_baudrate_period_ns(8680) // 115200 baud = period 8.68uS
)
uart0_stim
(
.clk(clk),
.uart_rx(uart0_srx_pad_i)
);
*/
// UART0 is looped back for now
assign uart0_srx_pad_i = uart0_stx_pad_o;
`endif // `ifdef UART0
endmodule // orpsoc_testbench
 
// Local Variables:
// verilog-library-directories:("." "../../rtl/verilog/orpsoc_top")
// verilog-library-files:()
// verilog-library-extensions:(".v" ".h")
// End:
 
/generic/ft/bench/verilog/or1200_ft_stim.v
0,0 → 1,391
 
 
`include "timescale.v"
`include "or1200_defines.v"
`include "orpsoc-testbench-defines.v"
`include "test-defines.v"
 
//
// Top of TB
//
`define TB_TOP orpsoc_testbench
 
//
// Top of DUT
//
`define DUT_TOP `TB_TOP.dut
 
//
// Top of OR1200 inside test bench
//
`define OR1200_TOP `DUT_TOP.or1200_top0
 
 
`define CPU or1200
`define CPU_cpu or1200_cpu
`define CPU_rf or1200_rf
`define CPU_except or1200_except
`define CPU_ctrl or1200_ctrl
`define CPU_sprs or1200_sprs
`define CPU_ic_top or1200_ic_top
`define CPU_ic_ram or1200_ic_ram
`define CPU_ic_tag or1200_ic_tag
`define CPU_dc_top or1200_dc_top
`define CPU_dc_ram or1200_dc_ram
`define CPU_dc_tag or1200_dc_tag
 
`define CPU_immu_top or1200_immu_top
`define CPU_immu_tlb or1200_immu_tlb
`define CPU_dmmu_top or1200_dmmu_top
`define CPU_dmmu_tlb or1200_dmmu_tlb
 
`define CPU_CORE_CLK `OR1200_TOP.`CPU_cpu.`CPU_ctrl.clk
 
`define FT_STIM_MEM_LOC 32'h00000004
`define FT_STIM_GO_WORD 32'h88000000
 
module or1200_ft_stim;
 
reg debug_on;
`ifdef OR1200_RAM_PARITY
 
`define RAM_WB_TOP `DUT_TOP.ram_wb0.ram_wb_b3_0
task get_ram_word;
input [31:0] addr;
output [31:0] insn;
begin
insn = `RAM_WB_TOP.get_mem32(addr[31:2]);
end
endtask // get_ram_word
 
task set_ram_word;
input [31:0] addr;
input [31:0] word;
reg dummy;
begin
dummy = `RAM_WB_TOP.set_mem32(addr[31:2], word);
end
endtask // set_ram_word
 
task wait_for_start;
reg [31:0] mem_word;
begin
get_ram_word(`FT_STIM_MEM_LOC, mem_word);
while(mem_word !== `FT_STIM_GO_WORD)
begin
 
// if (debug_on)
// $display("%m: Wait for start, read %h",mem_word);
#100000;
get_ram_word(`FT_STIM_MEM_LOC, mem_word);
end
end
endtask // wait_for_start
task get_command;
output [31:0] out_cmd;
reg [31:0] mem_word;
begin
get_ram_word(`FT_STIM_MEM_LOC, mem_word);
while(mem_word === 32'h0)
begin
#10000;
 
// if (debug_on)
// $display("%m: get_command %h",mem_word);
get_ram_word(`FT_STIM_MEM_LOC, mem_word);
end
out_cmd = mem_word;
end
endtask // get_command
 
task ack_command;
begin
// if (debug_on)
// $display("%m: Ack command");
set_ram_word(`FT_STIM_MEM_LOC, 0);
end
endtask // ack_command
 
task inject_ic_ram_fault;
input [31:0] cmd;
reg [23:0] word_number;
reg [7:0] bit_number;
begin
// Get line number from command
word_number = cmd[15:0];
bit_number = cmd[23:16];
if (debug_on)
$display("%m: inject error into IC RAM word 0x%h, data bit %02d",
word_number, bit_number);
`OR1200_TOP.`CPU_ic_top.`CPU_ic_ram.ic_ram0.gen_parity_err(word_number,
-1,
bit_number);
ack_command;
end
endtask // inject_ic_ram_fault
 
task inject_ic_tag_fault;
input [31:0] cmd;
reg [23:0] tag_word;
reg [7:0] bit_number;
begin
// Get line number from command
tag_word = cmd[15:0];
bit_number = cmd[23:16];
if (debug_on)
$display("%m: inject error into IC tag line 0x%h, data bit %02d",
tag_word, bit_number);
`OR1200_TOP.`CPU_ic_top.`CPU_ic_tag.ic_tag0.gen_parity_err(tag_word,
-1,
bit_number);
ack_command;
end
endtask
 
task inject_dc_ram_fault;
input [31:0] cmd;
reg [23:0] word_number;
reg [7:0] bit_number;
begin
// Get line number from command
word_number = cmd[15:0];
bit_number = cmd[23:16];
if (debug_on)
$display("%m: inject error into DC RAM word 0x%h, data bit %02d",
word_number, bit_number);
`OR1200_TOP.`CPU_dc_top.`CPU_dc_ram.dc_ram0.gen_parity_err(word_number,
bit_number);
ack_command;
end
endtask
 
task inject_dc_tag_fault;
input [31:0] cmd;
reg [23:0] tag_word;
reg [7:0] bit_number;
begin
// Get line number from command
tag_word = cmd[15:0];
bit_number =cmd[23:16];
if (debug_on)
$display("%m: inject error into DC tag line 0x%h, data bit %02d",
tag_word, bit_number);
`OR1200_TOP.`CPU_dc_top.`CPU_dc_tag.dc_tag0.gen_parity_err(tag_word,
-1,
bit_number);
ack_command;
end
endtask
 
task inject_immu_fault;
input tr;
input [31:0] cmd;
reg [23:0] mem_word;
reg [7:0] bit_number;
begin
// Get line number from command
mem_word = cmd[15:0];
bit_number =cmd[23:16];
if (tr)
begin
if (debug_on)
$display("%m: inject error into iTLB TR RAM, 0x%h, bit %02d",
mem_word, bit_number);
`OR1200_TOP.`CPU_immu_top.`CPU_immu_tlb.itlb_tr_ram.gen_parity_err(
mem_word,
-1,
bit_number);
end
else
begin
if (debug_on)
$display("%m: inject error into iTLB MR RAM, 0x%h, bit %02d",
mem_word, bit_number);
`OR1200_TOP.`CPU_immu_top.`CPU_immu_tlb.itlb_mr_ram.gen_parity_err(
mem_word,
-1,
bit_number);
end // else: !if(tr)
ack_command;
end
endtask // inject_immu_fault
 
task inject_dmmu_fault;
input tr;
input [31:0] cmd;
reg [23:0] mem_word;
reg [7:0] bit_number;
begin
// Get line number from command
mem_word = cmd[15:0];
bit_number =cmd[23:16];
if (tr)
begin
if (debug_on)
$display("%m: inject error into dtlb TR RAM, 0x%h, bit %02d",
mem_word, bit_number);
`OR1200_TOP.`CPU_dmmu_top.`CPU_dmmu_tlb.dtlb_tr_ram.gen_parity_err(
mem_word,
-1,
bit_number);
end
else
begin
if (debug_on)
$display("%m: inject error into dtlb MR RAM, 0x%h, bit %02d",
mem_word, bit_number);
`OR1200_TOP.`CPU_dmmu_top.`CPU_dmmu_tlb.dtlb_mr_ram.gen_parity_err(
mem_word,
-1,
bit_number);
end // else: !if(tr)
ack_command;
end
endtask
 
task inject_rf_fault;
input [31:0] cmd;
reg [23:0] gpr_no;
reg [7:0] bit_number;
begin
bit_number =cmd[23:16];
gpr_no = cmd[15:0];
if (debug_on)
$display("%m: inject error into register file, r%02d, bit %02d",
gpr_no, bit_number);
`OR1200_TOP.`CPU_cpu.`CPU_rf.rf_a.gen_parity_err( gpr_no,
-1,
bit_number);
`OR1200_TOP.`CPU_cpu.`CPU_rf.rf_b.gen_parity_err( gpr_no,
-1,
bit_number);
ack_command;
end
endtask
reg [31:0] cmd;
 
`define FT_STIM_CMD_WORD_CMD_POS 31:24
`define FT_STIM_CMD_WORD_CMD_WIDTH 8
`define FT_STIM_CMD_WORD_DATA_POS 23:0
`define FT_STIM_CMD_WORD_DATA_WIDTH 24
 
`define FT_STIM_CMD_IC_RAM_FAULT `FT_STIM_CMD_WORD_CMD_WIDTH'h1
`define FT_STIM_CMD_IC_TAG_FAULT `FT_STIM_CMD_WORD_CMD_WIDTH'h2
`define FT_STIM_CMD_DC_RAM_FAULT `FT_STIM_CMD_WORD_CMD_WIDTH'h3
`define FT_STIM_CMD_DC_TAG_FAULT `FT_STIM_CMD_WORD_CMD_WIDTH'h4
 
`define FT_STIM_CMD_DMMU_MR_FAULT `FT_STIM_CMD_WORD_CMD_WIDTH'h5
`define FT_STIM_CMD_DMMU_TR_FAULT `FT_STIM_CMD_WORD_CMD_WIDTH'h6
`define FT_STIM_CMD_IMMU_MR_FAULT `FT_STIM_CMD_WORD_CMD_WIDTH'h7
`define FT_STIM_CMD_IMMU_TR_FAULT `FT_STIM_CMD_WORD_CMD_WIDTH'h8
 
`define FT_STIM_CMD_RF_FAULT `FT_STIM_CMD_WORD_CMD_WIDTH'h9
 
`define FT_STIM_CMD_DEBUG_ON `FT_STIM_CMD_WORD_CMD_WIDTH'hff
`define FT_STIM_CMD_DEBUG_OFF `FT_STIM_CMD_WORD_CMD_WIDTH'hfe
 
initial
begin
#10;
 
// Disable to begin with
debug_on = 1;
// Wait for software to indicate the test is ready to run.
wait_for_start;
// Ack our receipt of start
ack_command;
while(1)
begin
cmd = 32'hdeaddead;
get_command(cmd);
 
case(cmd[`FT_STIM_CMD_WORD_CMD_POS])
`FT_STIM_CMD_IC_RAM_FAULT: begin
inject_ic_ram_fault(cmd);
end
`FT_STIM_CMD_IC_TAG_FAULT: begin
inject_ic_tag_fault(cmd);
end
`FT_STIM_CMD_DC_RAM_FAULT: begin
inject_dc_ram_fault(cmd);
end
`FT_STIM_CMD_DC_TAG_FAULT: begin
inject_dc_tag_fault(cmd);
end
`FT_STIM_CMD_DMMU_MR_FAULT: begin
inject_dmmu_fault(0, cmd);
end
`FT_STIM_CMD_DMMU_TR_FAULT: begin
inject_dmmu_fault(1, cmd);
end
`FT_STIM_CMD_IMMU_MR_FAULT: begin
inject_immu_fault(0, cmd);
end
`FT_STIM_CMD_IMMU_TR_FAULT: begin
inject_immu_fault(1, cmd);
end
`FT_STIM_CMD_RF_FAULT: begin
inject_rf_fault(cmd);
end
`FT_STIM_CMD_DEBUG_ON: begin
$display("%m: Debug on");
debug_on = 1;
ack_command;
end
`FT_STIM_CMD_DEBUG_OFF: begin
$display("%m: Debug off");
debug_on = 0;
ack_command;
end
default:
begin
$display("%m: Unknown command %h",
cmd[`FT_STIM_CMD_WORD_CMD_POS]);
#10000;
$finish;
end
endcase // case (cmd[`FT_STIM_CMD_WORD_CMD_POS])
end // while (1)
end // initial begin
`endif
endmodule // or1200_ft_stim
/generic/ft/bench/verilog/or1200_monitor.v
0,0 → 1,1890
//////////////////////////////////////////////////////////////////////
//// ////
//// or1200_monitor.v ////
//// ////
//// OR1200 processor monitor module ////
//// ////
//// Author(s): ////
//// - Damjan Lampret, lampret@opencores.org ////
//// - Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// 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, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "timescale.v"
`include "or1200_defines.v"
`include "orpsoc-testbench-defines.v"
`include "test-defines.v"
 
//
// Top of TB
//
`define TB_TOP orpsoc_testbench
 
//
// Top of DUT
//
`define DUT_TOP `TB_TOP.dut
 
//
// Top of OR1200 inside test bench
//
`define OR1200_TOP `DUT_TOP.or1200_top0
 
//
// Define to enable lookup file generation
//
//`define OR1200_MONITOR_LOOKUP
 
//
// Define to enable SPR access log file generation
//
//`define OR1200_MONITOR_SPRS
 
//
// Enable logging of state during execution
//
//`define OR1200_MONITOR_EXEC_STATE
 
//
// Enable disassembly of instructions in execution state log
//
//`define OR1200_MONITOR_EXEC_LOG_DISASSEMBLY
 
//
// Enable verbose report l.nops (to both general log file and stdout)
//
`define OR1200_MONITOR_VERBOSE_NOPS
 
//
// Enable monitoring of control and execution flow (experimental)
//
//`define OR1200_SYSTEM_CHECKER
 
// Can either individually enable things above, or usually have the scripts
// running the simulation pass the PROCESSOR_MONITOR_ENABLE_LOGS define to
// enable them all.
 
`ifdef PROCESSOR_MONITOR_ENABLE_LOGS
`define OR1200_MONITOR_EXEC_STATE
`define OR1200_MONITOR_SPRS
`define OR1200_MONITOR_LOOKUP
`endif
 
//
// Memory coherence checking (double check instruction in fetch stage against
// what is in memory.) Useful for cache controller development.
//
//`define MEM_COHERENCE_CHECK
 
//
// Top of OR1200 inside test bench
//
`define CPU or1200
`define CPU_cpu or1200_cpu
`define CPU_rf or1200_rf
`define CPU_except or1200_except
`define CPU_ctrl or1200_ctrl
`define CPU_sprs or1200_sprs
`define CPU_immu_top or1200_immu_top
`define CPU_immu_tlb or1200_immu_tlb
`define CPU_CORE_CLK `OR1200_TOP.`CPU_cpu.`CPU_ctrl.clk
 
 
`define OR1K_OPCODE_POS 31:26
`define OR1K_J_BR_IMM_POS 25:0
`define OR1K_RD_POS 25:21
`define OR1K_RA_POS 20:16
`define OR1K_RB_POS 15:11
`define OR1K_ALU_OP_POS 3:0
`define OR1K_SHROT_OP_POS 7:6
`define OR1K_SHROTI_IMM_POS 5:0
`define OR1K_SF_OP 25:21
`define OR1K_XSYNC_OP_POS 25:21
 
 
module or1200_monitor;
 
integer fexe;
integer finsn;
reg [23:0] ref;
`ifdef OR1200_MONITOR_SPRS
integer fspr;
`endif
integer fgeneral;
`ifdef OR1200_MONITOR_LOOKUP
integer flookup;
`endif
integer r3;
integer insns;
 
 
//
// Initialization
//
initial begin
ref = 0;
`ifdef OR1200_MONITOR_EXEC_STATE
fexe = $fopen({"../out/",`TEST_NAME_STRING,"-executed.log"});
`endif
`ifdef OR1200_MONITOR_EXEC_LOG_DISASSEMBLY
finsn = fexe;
`endif
$timeformat (-9, 2, " ns", 12);
`ifdef OR1200_MONITOR_SPRS
fspr = $fopen({"../out/",`TEST_NAME_STRING,"-sprs.log"});
`endif
fgeneral = $fopen({"../out/",`TEST_NAME_STRING,"-general.log"});
`ifdef OR1200_MONITOR_LOOKUP
flookup = $fopen({"../out/",`TEST_NAME_STRING,"-lookup.log"});
`endif
insns = 0;
 
end
 
//
// Get GPR
//
task get_gpr;
input [4:0] gpr_no;
output [31:0] gpr;
integer j;
begin
 
`ifdef OR1200_RFRAM_GENERIC
for(j = 0; j < 32; j = j + 1) begin
gpr[j] = `OR1200_TOP.`CPU_cpu.`CPU_rf.rf_a.mem[gpr_no*32+j];
end
`else
//gpr = `OR1200_TOP.`CPU_cpu.`CPU_rf.rf_a.mem[gpr_no];
gpr = `OR1200_TOP.`CPU_cpu.`CPU_rf.rf_a.get_gpr(gpr_no);
`endif
 
 
end
endtask
 
//
// Write state of the OR1200 registers into a file
//
// Limitation: only a small subset of register file RAMs
// are supported
//
task display_arch_state;
reg [5:0] i;
reg [31:0] r;
integer j;
begin
`ifdef OR1200_MONITOR_EXEC_STATE
ref = ref + 1;
`ifdef OR1200_MONITOR_LOOKUP
$fdisplay(flookup, "Instruction %d: %t", insns, $time);
`endif
$fwrite(fexe, "\nEXECUTED(%d): %h: %h", insns,
`OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc,
`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
`ifdef OR1200_MONITOR_EXEC_LOG_DISASSEMBLY
$fwrite(fexe,"\t");
// Decode the instruction, print it out
or1200_print_op(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
`endif
for(i = 0; i < 32; i = i + 1) begin
if (i % 4 == 0)
$fdisplay(fexe);
get_gpr(i, r);
$fwrite(fexe, "GPR%d: %h ", i, r);
end
$fdisplay(fexe);
r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.sr;
$fwrite(fexe, "SR : %h ", r);
r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.epcr;
$fwrite(fexe, "EPCR0: %h ", r);
r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.eear;
$fwrite(fexe, "EEAR0: %h ", r);
r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.esr;
$fdisplay(fexe, "ESR0 : %h", r);
`endif // `ifdef OR1200_MONITOR_EXEC_STATE
`ifdef OR1200_DISPLAY_EXECUTED
ref = ref + 1;
`ifdef OR1200_MONITOR_LOOKUP
$fdisplay(flookup, "Instruction %d: %t", insns, $time);
`endif
$fwrite(fexe, "\nEXECUTED(%d): %h: %h", insns, `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc, `OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
`endif
insns = insns + 1;
end
endtask // display_arch_state
 
/* Keep a trace buffer of the last lot of instructions and addresses
* "executed",as read from the writeback stage, and cause a $finish if we hit
* an instruction that is invalid, such as all zeros.
* Currently, only breaks on an all zero instruction, but should probably be
* made to break for anything with an X in it too. And of course ideally this
* shouldn't be needed - but is handy if someone changes something and stops
* the test continuing forever.
*/
integer num_nul_inst;
initial num_nul_inst = 0;
task monitor_for_crash;
`define OR1200_MONITOR_CRASH_TRACE_SIZE 32
//Trace buffer of 32 instructions
reg [31:0] insn_trace [0:`OR1200_MONITOR_CRASH_TRACE_SIZE-1];
//Trace buffer of the addresses of those instructions
reg [31:0] addr_trace [0:`OR1200_MONITOR_CRASH_TRACE_SIZE-1];
integer i;
begin
if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h00000000)
num_nul_inst = num_nul_inst + 1;
else
num_nul_inst = 0; // Reset it
 
if (num_nul_inst == 1000) // Sat a loop a bit too long...
begin
$fdisplay(fgeneral, "ERROR - no instruction at PC %h",
`OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc);
$fdisplay(fgeneral, "Crash trace: Last %d instructions: ",
`OR1200_MONITOR_CRASH_TRACE_SIZE);
 
$fdisplay(fgeneral, "PC\t\tINSTR");
for(i=`OR1200_MONITOR_CRASH_TRACE_SIZE-1;i>=0;i=i-1) begin
$fdisplay(fgeneral, "%h\t%h",addr_trace[i], insn_trace[i]);
end
#100 $finish;
end
else
begin
for(i=`OR1200_MONITOR_CRASH_TRACE_SIZE-1;i>0;i=i-1) begin
insn_trace[i] = insn_trace[i-1];
addr_trace[i] = addr_trace[i-1];
end
insn_trace[0] = `OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn;
addr_trace[0] = `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc;
end
end
endtask // monitor_for_crash
 
//
// Write state of the OR1200 registers into a file; version for exception
//
task display_arch_state_except;
reg [5:0] i;
reg [31:0] r;
integer j;
begin
`ifdef OR1200_MONITOR_EXEC_STATE
ref = ref + 1;
`ifdef OR1200_MONITOR_LOOKUP
$fdisplay(flookup, "Instruction %d: %t", insns, $time);
`endif
$fwrite(fexe, "\nEXECUTED(%d): %h: %h (exception)", insns, `OR1200_TOP.`CPU_cpu.`CPU_except.ex_pc, `OR1200_TOP.`CPU_cpu.`CPU_ctrl.ex_insn);
for(i = 0; i < 32; i = i + 1) begin
if (i % 4 == 0)
$fdisplay(fexe);
get_gpr(i, r);
$fwrite(fexe, "GPR%d: %h ", i, r);
end
$fdisplay(fexe);
r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.sr;
$fwrite(fexe, "SR : %h ", r);
r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.epcr;
$fwrite(fexe, "EPCR0: %h ", r);
r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.eear;
$fwrite(fexe, "EEAR0: %h ", r);
r = `OR1200_TOP.`CPU_cpu.`CPU_sprs.esr;
$fdisplay(fexe, "ESR0 : %h", r);
insns = insns + 1;
`endif // `ifdef OR1200_MONITOR_EXEC_STATE
`ifdef OR1200_DISPLAY_EXECUTED
ref = ref + 1;
`ifdef OR1200_MONITOR_LOOKUP
$fdisplay(flookup, "Instruction %d: %t", insns, $time);
`endif
$fwrite(fexe, "\nEXECUTED(%d): %h: %h (exception)", insns,
`OR1200_TOP.`CPU_cpu.`CPU_except.ex_pc,
`OR1200_TOP.`CPU_cpu.`CPU_ctrl.ex_insn);
insns = insns + 1;
`endif
end
endtask
 
integer iwb_progress;
reg [31:0] iwb_progress_addr;
//
// WISHBONE bus checker
//
always @(posedge `OR1200_TOP.iwb_clk_i)
if (`OR1200_TOP.iwb_rst_i) begin
iwb_progress = 0;
iwb_progress_addr = `OR1200_TOP.iwb_adr_o;
end
else begin
if (`OR1200_TOP.iwb_cyc_o && (iwb_progress != 2)) begin
iwb_progress = 1;
end
if (`OR1200_TOP.iwb_stb_o) begin
if (iwb_progress >= 1) begin
if (iwb_progress == 1)
iwb_progress_addr = `OR1200_TOP.iwb_adr_o;
iwb_progress = 2;
end
else begin
$fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_stb_o raised without `OR1200_TOP.iwb_cyc_o, at %t\n", $time);
#100 $finish;
end
end
if (`OR1200_TOP.iwb_ack_i & `OR1200_TOP.iwb_err_i) begin
$fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_ack_i and `OR1200_TOP.iwb_err_i raised at the same time, at %t\n", $time);
end
if ((iwb_progress == 2) && (iwb_progress_addr != `OR1200_TOP.iwb_adr_o)) begin
$fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_adr_o changed while waiting for `OR1200_TOP.iwb_err_i/`OR1200_TOP.iwb_ack_i, at %t\n", $time);
#10000;
$finish;
end
if (`OR1200_TOP.iwb_ack_i | `OR1200_TOP.iwb_err_i)
if (iwb_progress == 2) begin
iwb_progress = 0;
iwb_progress_addr = `OR1200_TOP.iwb_adr_o;
end
else begin
$fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_ack_i/`OR1200_TOP.iwb_err_i raised without `OR1200_TOP.iwb_cyc_i/`OR1200_TOP.iwb_stb_i, at %t\n", $time);
#100 $finish;
end
if ((iwb_progress == 2) && !`OR1200_TOP.iwb_stb_o) begin
$fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.iwb_stb_o lowered without `OR1200_TOP.iwb_err_i/`OR1200_TOP.iwb_ack_i, at %t\n", $time);
#100 $finish;
end
end
 
integer dwb_progress;
reg [31:0] dwb_progress_addr;
//
// WISHBONE bus checker
//
always @(posedge `OR1200_TOP.dwb_clk_i)
if (`OR1200_TOP.dwb_rst_i)
dwb_progress = 0;
else begin
if (`OR1200_TOP.dwb_cyc_o && (dwb_progress != 2))
dwb_progress = 1;
if (`OR1200_TOP.dwb_stb_o)
if (dwb_progress >= 1) begin
if (dwb_progress == 1)
dwb_progress_addr = `OR1200_TOP.dwb_adr_o;
dwb_progress = 2;
end
else begin
$fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_stb_o raised without `OR1200_TOP.dwb_cyc_o, at %t\n", $time);
#100 $finish;
end
if (`OR1200_TOP.dwb_ack_i & `OR1200_TOP.dwb_err_i) begin
$fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_ack_i and `OR1200_TOP.dwb_err_i raised at the same time, at %t\n", $time);
end
if ((dwb_progress == 2) && (dwb_progress_addr != `OR1200_TOP.dwb_adr_o)) begin
$fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_adr_o changed while waiting for `OR1200_TOP.dwb_err_i/`OR1200_TOP.dwb_ack_i, at %t\n", $time);
#100 $finish;
end
if (`OR1200_TOP.dwb_ack_i | `OR1200_TOP.dwb_err_i)
if (dwb_progress == 2) begin
dwb_progress = 0;
dwb_progress_addr = `OR1200_TOP.dwb_adr_o;
end
else begin
$fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_ack_i/`OR1200_TOP.dwb_err_i raised without `OR1200_TOP.dwb_cyc_i/`OR1200_TOP.dwb_stb_i, at %t\n", $time);
#100 $finish;
end
if ((dwb_progress == 2) && !`OR1200_TOP.dwb_stb_o) begin
$fdisplay(fgeneral, "WISHBONE protocol violation: `OR1200_TOP.dwb_stb_o lowered without `OR1200_TOP.dwb_err_i/`OR1200_TOP.dwb_ack_i, at %t\n", $time);
#100 $finish;
end
end
 
//
// Hooks for:
// - displaying registers
// - end of simulation
// - access to SPRs
//
always @(posedge `CPU_CORE_CLK)
if (!`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_freeze) begin
// #2;
if (((`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[31:26] != `OR1200_OR32_NOP)
| !`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[16])
& !(`OR1200_TOP.`CPU_cpu.`CPU_except.except_flushpipe &
`OR1200_TOP.`CPU_cpu.`CPU_except.ex_dslot))
begin
display_arch_state;
monitor_for_crash;
end
else
if (`OR1200_TOP.`CPU_cpu.`CPU_except.except_flushpipe)
display_arch_state_except;
// small hack to stop simulation (l.nop 1):
if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0001) begin
get_gpr(3, r3);
$fdisplay(fgeneral, "%t: l.nop exit (%h)", $time, r3);
`ifdef OR1200_MONITOR_VERBOSE_NOPS
$display("exit(%h)",r3);
`endif
$finish;
end
// debug if test (l.nop 10)
if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_000a) begin
$fdisplay(fgeneral, "%t: l.nop dbg_if_test", $time);
end
// simulation reports (l.nop 2)
if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0002) begin
get_gpr(3, r3);
$fdisplay(fgeneral, "%t: l.nop report (0x%h)", $time, r3);
`ifdef OR1200_MONITOR_VERBOSE_NOPS
$display("report (0x%h);", r3);
`endif
end
// simulation printfs (l.nop 3)
if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0003) begin
get_gpr(3, r3);
$fdisplay(fgeneral, "%t: l.nop printf (%h)", $time, r3);
end
if (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn == 32'h1500_0004) begin
// simulation putc (l.nop 4)
get_gpr(3, r3);
$write("%c", r3);
$fdisplay(fgeneral, "%t: l.nop putc (%c)", $time, r3);
end
`ifdef OR1200_MONITOR_SPRS
if (`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_we)
$fdisplay(fspr, "%t: Write to SPR : [%h] <- %h", $time,
`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_addr,
`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_dat_o);
if ((|`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_cs) &
!`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_we)
$fdisplay(fspr, "%t: Read from SPR: [%h] -> %h", $time,
`OR1200_TOP.`CPU_cpu.`CPU_sprs.spr_addr,
`OR1200_TOP.`CPU_cpu.`CPU_sprs.to_wbmux);
`endif
end
 
 
`ifdef RAM_WB
`define RAM_WB_TOP `DUT_TOP.ram_wb0.ram_wb_b3_0
task get_insn_from_wb_ram;
input [31:0] addr;
output [31:0] insn;
begin
insn = `RAM_WB_TOP.get_mem32(addr[31:2]);
end
endtask // get_insn_from_wb_ram
`endif
`ifdef VERSATILE_SDRAM
`define SDRAM_TOP `TB_TOP.sdram0
// Bit selects to define the bank
// 32 MB part with 4 banks
`define SDRAM_BANK_SEL_BITS 24:23
`define SDRAM_WORD_SEL_TOP_BIT 22
// Gets instruction word from correct bank
task get_insn_from_sdram;
input [31:0] addr;
output [31:0] insn;
reg [`SDRAM_WORD_SEL_TOP_BIT-1:0] word_addr;
begin
word_addr = addr[`SDRAM_WORD_SEL_TOP_BIT:2];
if (addr[`SDRAM_BANK_SEL_BITS] == 2'b00)
begin
//$display("%t: get_insn_from_sdram bank0, word 0x%h, (%h and %h in SDRAM)", $time, word_addr, `SDRAM_TOP.Bank0[{word_addr,1'b0}], `SDRAM_TOP.Bank0[{word_addr,1'b1}]);
insn[15:0] = `SDRAM_TOP.Bank0[{word_addr,1'b1}];
insn[31:16] = `SDRAM_TOP.Bank0[{word_addr,1'b0}];
end
end
endtask // get_insn_from_sdram
`endif // `ifdef VERSATILE_SDRAM
 
`ifdef XILINX_DDR2
`define DDR2_TOP `TB_TOP.gen_cs[0]
// Gets instruction word from correct bank
task get_insn_from_xilinx_ddr2;
input [31:0] addr;
output [31:0] insn;
reg [16*8-1:0] ddr2_array_line0,ddr2_array_line1,ddr2_array_line2,
ddr2_array_line3;
integer word_in_line_num;
begin
// Get our 4 128-bit chunks (8 half-words in each!! Confused yet?),
// 16 words total
`DDR2_TOP.gen[0].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line0);
`DDR2_TOP.gen[1].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line1);
`DDR2_TOP.gen[2].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line2);
`DDR2_TOP.gen[3].u_mem0.memory_read(addr[28:27],addr[26:13],{addr[12:6],3'd0},ddr2_array_line3);
case (addr[5:2])
4'h0:
begin
insn[15:0] = ddr2_array_line0[15:0];
insn[31:16] = ddr2_array_line1[15:0];
end
4'h1:
begin
insn[15:0] = ddr2_array_line2[15:0];
insn[31:16] = ddr2_array_line3[15:0];
end
4'h2:
begin
insn[15:0] = ddr2_array_line0[31:16];
insn[31:16] = ddr2_array_line1[31:16];
end
4'h3:
begin
insn[15:0] = ddr2_array_line2[31:16];
insn[31:16] = ddr2_array_line3[31:16];
end
4'h4:
begin
insn[15:0] = ddr2_array_line0[47:32];
insn[31:16] = ddr2_array_line1[47:32];
end
4'h5:
begin
insn[15:0] = ddr2_array_line2[47:32];
insn[31:16] = ddr2_array_line3[47:32];
end
4'h6:
begin
insn[15:0] = ddr2_array_line0[63:48];
insn[31:16] = ddr2_array_line1[63:48];
end
4'h7:
begin
insn[15:0] = ddr2_array_line2[63:48];
insn[31:16] = ddr2_array_line3[63:48];
end
4'h8:
begin
insn[15:0] = ddr2_array_line0[79:64];
insn[31:16] = ddr2_array_line1[79:64];
end
4'h9:
begin
insn[15:0] = ddr2_array_line2[79:64];
insn[31:16] = ddr2_array_line3[79:64];
end
4'ha:
begin
insn[15:0] = ddr2_array_line0[95:80];
insn[31:16] = ddr2_array_line1[95:80];
end
4'hb:
begin
insn[15:0] = ddr2_array_line2[95:80];
insn[31:16] = ddr2_array_line3[95:80];
end
4'hc:
begin
insn[15:0] = ddr2_array_line0[111:96];
insn[31:16] = ddr2_array_line1[111:96];
end
4'hd:
begin
insn[15:0] = ddr2_array_line2[111:96];
insn[31:16] = ddr2_array_line3[111:96];
end
4'he:
begin
insn[15:0] = ddr2_array_line0[127:112];
insn[31:16] = ddr2_array_line1[127:112];
end
4'hf:
begin
insn[15:0] = ddr2_array_line2[127:112];
insn[31:16] = ddr2_array_line3[127:112];
end
endcase // case (addr[5:2])
end
endtask // get_insn_from_xilinx_ddr2
`endif
task get_insn_from_memory;
input [31:0] id_pc;
output [31:0] insn;
begin
// do a decode of which server we should look in
case (id_pc[31:28])
`ifdef VERSATILE_SDRAM
4'h0:
get_insn_from_sdram(id_pc, insn);
`endif
`ifdef XILINX_DDR2
4'h0:
get_insn_from_xilinx_ddr2(id_pc, insn);
`endif
`ifdef RAM_WB
4'h0:
get_insn_from_wb_ram(id_pc, insn);
`endif
4'hf:
// Flash isn't stored in a memory, it's an FSM so just skip/ignore
insn = `OR1200_TOP.`CPU_cpu.`CPU_ctrl.id_insn;
default:
begin
$fdisplay(fgeneral, "%t: Unknown memory server for address 0x%h", $time,id_pc);
insn = 32'hxxxxxxxx; // Unknown server
end
endcase // case (id_pc[31:28])
end
endtask // get_insn_from_memory
 
//
// Look in the iMMU TLB MR for this address' page, if MMUs are on and enabled
//
task check_for_immu_entry;
input [31:0] pc;
output [31:0] physical_pc;
output mmu_tlb_miss;
integer w,x;
 
reg [31:`OR1200_IMMU_PS] pc_vpn;
reg [`OR1200_ITLBTRW-1:0] itlb_tr;
reg [`OR1200_ITLBMRW-1:0] itlb_mr;
 
integer tlb_index;
reg mmu_en;
begin
mmu_tlb_miss = 0;
`ifdef OR1200_NO_IMMU
physical_pc = pc;
`else
mmu_en = `OR1200_TOP.`CPU_immu_top.immu_en;
// If MMU is enabled
if (mmu_en)
begin
// Look in the iTLB for mapping - get virtual page number
pc_vpn = pc[31:`OR1200_IMMU_PS];
 
tlb_index = pc[`OR1200_ITLB_INDX];
// Look at the ITLB match register
itlb_mr = `OR1200_TOP.`CPU_immu_top.`CPU_immu_tlb.itlb_mr_ram.mem[tlb_index];
 
// Get the translate register here too, in case there's an error, we print it
itlb_tr = `OR1200_TOP.`CPU_immu_top.`CPU_immu_tlb.itlb_tr_ram.mem[tlb_index];
if ((itlb_mr[`OR1200_ITLBMR_V_BITS] === 1'b1) & (itlb_mr[`OR1200_ITLBMRW-1:1] === pc[`OR1200_ITLB_TAG]))
begin
// Page number in match register matches page number of virtual PC, so get the physical
// address from the translate memory
// Now pull the physical page number out of the tranlsate register (it's after bottom 3 bits)
physical_pc = {itlb_tr[`OR1200_ITLBTRW-1:`OR1200_ITLBTRW-(32-`OR1200_IMMU_PS)],pc[`OR1200_IMMU_PS-1:0]};
//$display("check_for_immu_entry: found match for virtual PC 0x%h in entry %d of iMMU, mr = 0x%x tr = 0x%x, phys. PC = 0x%h", pc, pc[`OR1200_ITLB_INDX], itlb_mr, itlb_tr, physical_pc);
end // if ((itlb_mr[`OR1200_ITLBMR_V_BITS]) & (itlb_mr[`OR1200_ITLBMRW-1:1] == pc[`OR1200_ITLB_TAG]))
else
begin
 
// Wait a couple of clocks, see if we're doing a miss
@(posedge `CPU_CORE_CLK);
@(posedge `CPU_CORE_CLK);
if (!(`OR1200_TOP.`CPU_immu_top.miss)) // MMU should indicate miss
begin
$display("%t: check_for_immu_entry - ERROR - no match found for virtual PC 0x%h in entry %d of iMMU, mr = 0x%x tr = 0x%x, and no miss generated",
$time, pc, pc[`OR1200_ITLB_INDX], itlb_mr, itlb_tr);
#100;
$finish;
end
else
begin
mmu_tlb_miss = 1; // Started a miss, so ignore this instruction
end
end // else: !if((itlb_mr[`OR1200_ITLBMR_V_BITS]) & (itlb_mr[`OR1200_ITLBMRW-1:1] == pc[`OR1200_ITLB_TAG]))
end // if (`OR1200_TOP.`CPU_immu_top.immu_en === 1'b1)
else
physical_pc = pc;
`endif // !`ifdef OR1200_NO_IMMU
end
endtask // check_for_immu_entry
 
/*
Instruction memory coherence checking.
For new instruction executed in the pipeline - ensure it matches
what is in the main program memory. Perform MMU translations if
it is enabled.
*/
reg [31:0] mem_word;
reg [31:0] last_addr = 0;
reg [31:0] last_mem_word;
reg [31:0] physical_pc;
reg tlb_miss;
 
`ifdef MEM_COHERENCE_CHECK
`define MEM_COHERENCE_TRIGGER (`OR1200_TOP.`CPU_cpu.`CPU_ctrl.id_void === 1'b0)
 
`define INSN_TO_CHECK `OR1200_TOP.`CPU_cpu.`CPU_ctrl.id_insn
`define PC_TO_CHECK `OR1200_TOP.`CPU_cpu.`CPU_except.id_pc
// Check instruction in decode stage is what is in the RAM
always @(posedge `CPU_CORE_CLK)
begin
if (`MEM_COHERENCE_TRIGGER)
begin
check_for_immu_entry(`PC_TO_CHECK, physical_pc, tlb_miss);
// Check if it's a new PC - will also get triggered if the
// instruction has changed since we last checked it
if (((physical_pc !== last_addr) ||
(last_mem_word != `INSN_TO_CHECK)) & !tlb_miss)
begin
// Decode stage not void, check instruction
// get PC
get_insn_from_memory(physical_pc, mem_word);
 
if (mem_word !== `INSN_TO_CHECK)
begin
$fdisplay(fgeneral, "%t: Instruction mismatch for PC 0x%h (phys. 0x%h) - memory had 0x%h, CPU had 0x%h",
$time, `PC_TO_CHECK, physical_pc, mem_word,
`INSN_TO_CHECK);
$display("%t: Instruction mismatch for PC 0x%h (phys. 0x%h) - memory had 0x%h, CPU had 0x%h",
$time, `PC_TO_CHECK, physical_pc, mem_word,
`INSN_TO_CHECK);
#200;
$finish;
end
last_addr = physical_pc;
last_mem_word = mem_word;
end // if (((physical_pc !== last_addr) || (last_mem_word != `INSN_TO_CHECK))...
end // if (`MEM_COHERENCE_TRIGGER)
end // always @ (posedge `CPU_CORE_CLK)
`endif // `ifdef MEM_COHERENCE_CHECK
// Trigger on each instruction that gets into writeback stage properly
reg exception_coming1, exception_coming2, exception_here;
reg will_jump, jumping, jump_dslot, jumped;
reg rfe, except_during_rfe;
reg dslot_expt;
 
// Maintain a copy of GPRS for previous instruction
reg [31:0] current_gprs [0:31];
reg [31:0] current_epcr, current_eear, current_esr, current_sr;
reg [31:0] previous_gprs [0:31];
reg [31:0] previous_epcr;
reg [31:0] previous_eear;
reg [31:0] previous_esr;
reg [31:0] previous_sr;
task update_current_gprs;
integer j;
begin
for(j=0;j<32;j=j+1)
begin
get_gpr(j,current_gprs[j]);
end
current_sr = `OR1200_TOP.`CPU_cpu.or1200_sprs.sr ;
current_esr = `OR1200_TOP.`CPU_cpu.or1200_sprs.epcr ;
current_epcr = `OR1200_TOP.`CPU_cpu.or1200_sprs.epcr ;
current_eear = `OR1200_TOP.`CPU_cpu.or1200_sprs.eear ;
end
endtask
task update_previous_gprs;
integer j;
begin
for(j=0;j<32;j=j+1)
begin
previous_gprs[j] = current_gprs[j];
end
previous_sr = current_sr;
previous_esr = current_esr;
previous_epcr = current_epcr;
previous_eear = current_eear;
end
endtask // update_previous_gprs
// Maintain a list of addresses we expect the processor to execute
// Whenever we hit a branch or jump or rfe we add to this list - when we
// execute it then we remove it from the list.
reg [31:0] expected_addresses [0:31];
reg expected_addresses_waiting [0:31]; // List indicating if address is waiting
reg duplicate_expected_addresses_waiting [0:31]; // List indicating if a waiting address will be cleared by the single return
integer expected_address_num;
// Initialise things on reset
always @(`OR1200_TOP.iwb_rst_i)
begin
for (expected_address_num=0;expected_address_num<32;expected_address_num=expected_address_num+1)
begin
expected_addresses_waiting[expected_address_num] = 0;
duplicate_expected_addresses_waiting[expected_address_num] = 0;
end
expected_address_num = 0;
end
task add_expected_address;
input [31:0] expected_pc;
begin
if (expected_address_num == 31)
begin
$display("%t: Too many branches not reached",$time);
#100;
$finish;
end
if (expected_addresses_waiting[expected_address_num])
begin
$display("%t: expected_addresses tracker bugged out. expected_address_num = %0d",$time,expected_address_num);
#100;
$finish;
end
else
begin
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
// Debugging output...
$display("%t: Adding address 0x%h to expected list index %0d",$time, expected_pc,expected_address_num);
`endif
// Put the expected PC in the list, increase the index
expected_addresses[expected_address_num] = expected_pc;
expected_addresses_waiting[expected_address_num] = 1;
expected_address_num = expected_address_num + 1;
end // else: !if(expected_addresses_waiting[expected_address_num])
end
endtask // add_address_to_expect
 
// Use this in the case that there's an execption after a jump, in which
// case we'll have two entries when we finally jump back (the one the
// original jump put in, and the one put in by the l.rfe or l.jr/ when
// returning outside of exception handler), so mark this one as OK for
// removing the duplicate of
task mark_duplicate_expected_address;
begin
// This will always be done on the first instruction of an exception
// that has occured after a delay slot instruction, so
// expected_address_num will be one past the entry for the one we will
// get a duplicate return call for
duplicate_expected_addresses_waiting[expected_address_num-1] = 1;
end
endtask // mark_duplicate_expected_address
 
task check_expected_address;
input [31:0] pc;
input expecting_hit;
integer i,j;
reg hit;
reg duplicates;
begin
hit = 0;
//$display("%t: check_expected_addr 0x%h, index %0d",
// $time,pc, expected_address_num);
if (expected_address_num > 0)
begin
// First check the last jump we did
if (expected_addresses[expected_address_num-1] == pc)
begin
// Jump address hit
// Debugging printout:
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
$display("%t: PC address 0x%h was in expected list, index %0d",$time, pc,expected_address_num-1);
`endif
expected_address_num = expected_address_num-1;
expected_addresses_waiting[expected_address_num] = 0;
hit = 1;
end
else
begin
// Check through the list
for(i=0;i<expected_address_num;i=i+1)
begin
if (expected_addresses[i] == pc)
begin
// Jump address hit
// Debugging printout:
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
$display("%t: PC address 0x%h was in expected list, index %0d",$time, pc,i);
`endif
for(j=i;j<expected_address_num;j=j+1)
begin
// Pull all of the ones above us down one
expected_addresses_waiting[j]
= expected_addresses_waiting[j+1];
expected_addresses[j]
= expected_addresses[j+1];
duplicate_expected_addresses_waiting[j]
= duplicate_expected_addresses_waiting[j+1];
end
expected_address_num = expected_address_num-1;
hit = 1;
// quit out. only allow 1 hit
i = expected_address_num;
end
end
end // else: !if(expected_addresses[expected_ad...
end // if (expected_address_num > 0)
 
// Check for duplicates this way because of the way we've declared
// the array...
duplicates=0;
for(i=0;i<32;i=i+1)
duplicates = duplicates | duplicate_expected_addresses_waiting[i];
if (hit & duplicates)
begin
// If we got a hit, check for duplicates we're also meant to clear
`ifdef OR1200_MONITOR_JUMPTRACK_DEBUG_OUTPUT
$display;
`endif
for(i=0;i<expected_address_num;i=i+1)
begin
if(duplicate_expected_addresses_waiting[i] &
expected_addresses_waiting[i] &
expected_addresses[i] == pc)
begin
// Found a duplicate call address, clear it
duplicate_expected_addresses_waiting[i] = 0;
expected_addresses_waiting[i] = 0;
 
// Now reorder the list - pull all the ones above us
// down by one
for(j=i;j<expected_address_num;j=j+1)
begin
expected_addresses_waiting[j] = expected_addresses_waiting[j+1];
expected_addresses[j] = expected_addresses[j+1];
duplicate_expected_addresses_waiting[j] = duplicate_expected_addresses_waiting[j+1];
end
expected_address_num = expected_address_num - 1;
end
end // for (i=0;i<expected_address_num;i=i+1)
end // if (hit & duplicates)
if (expecting_hit & !hit)
begin
// Expected this address to be one we're supposed to jump to, but it wasn't!
$display("%t: Failed to find current PC, 0x%h, in expected PCs for branches/jumps",$time,pc);
#100;
$finish;
end
end
endtask // check_expected_address
 
// Task to assert value of GPR
task assert_gpr_val;
input [5:0] regnum;
input [31:0] assert_value;
input [31:0] pc;
reg [31:0] reg_val;
begin
get_gpr(regnum, reg_val);
if (reg_val !== assert_value)
begin
$display("%t: Assert r%0d value (0x%h) = 0x%h failed. pc=0x%h",
$time, regnum, reg_val, assert_value,pc);
#100;
$finish;
end
end
endtask // assert_gpr_val
// Task to assert something is true
task assert_this;
input assert_result;
input [31:0] pc;
begin
if (!assert_result)
begin
$display("%t: Assert failed for instruction at pc=0x%h",
$time , pc);
#100;
$finish;
end
end
endtask // assert_gpr_val
 
// The jumping variable doesn't get updated until we do the proper check of
// the current instruction reaching the writeback stage. We need to know
// earlier, eg. in the exception checking part, if this instruction will
// jump. We do that with this task.
task check_for_jump;
input [31:0] insn;
reg [5:0] opcode;
reg flag;
begin
opcode = insn[`OR1K_OPCODE_POS];
// Use the flag from the previous instruction, as the decision
// is made in the execute stage not in te writeback stage,
// which is where we're getting our instructions.
flag = previous_sr[`OR1200_SR_F];
case (opcode)
`OR1200_OR32_J,
`OR1200_OR32_JR,
`OR1200_OR32_JAL,
`OR1200_OR32_JALR:
will_jump = 1;
`OR1200_OR32_BNF:
will_jump = !flag;
`OR1200_OR32_BF:
will_jump = flag;
default:
will_jump = 0;
endcase // case (opcode)
end
endtask // check_for_jump
 
 
// Detect exceptions from the processor here
reg [13:0] except_trig_r;
reg exception_coming;
always @(posedge `CPU_CORE_CLK)
if (`OR1200_TOP.iwb_rst_i)
begin
except_trig_r = 0;
exception_coming = 0;
except_during_rfe = 0;
end
else if ((|`OR1200_TOP.`CPU_cpu.`CPU_except.except_trig) && !exception_coming)
begin
exception_coming = 1;
except_trig_r = `OR1200_TOP.`CPU_cpu.`CPU_except.except_trig;
except_during_rfe = rfe;
end
 
task check_incoming_exceptions;
begin
// Exception timing - depends on the trigger.
// Appears to be:
// tick timer - dslot - 1 instruction delay, else 2
// tlb lookasides - 1 instruction for both
 
casex (except_trig_r)
13'b1_xxxx_xxxx_xxxx: begin
//except_type <= #1 `OR1200_EXCEPT_TICK;
exception_here = exception_coming2;
exception_coming2 = jump_dslot ? exception_coming: exception_coming1 ;
exception_coming1 = jump_dslot ? 0 : exception_coming;
end
13'b0_1xxx_xxxx_xxxx: begin
//except_type <= #1 `OR1200_EXCEPT_INT;
#1;
end
13'b0_01xx_xxxx_xxxx: begin
//except_type <= #1 `OR1200_EXCEPT_ITLBMISS;
exception_here = exception_coming2;
exception_coming2 = jump_dslot ? exception_coming : exception_coming1 ;
exception_coming1 = jump_dslot ? 0 : exception_coming;
end
13'b0_001x_xxxx_xxxx: begin
//except_type <= #1 `OR1200_EXCEPT_IPF;
exception_here = exception_coming2;
exception_coming2 = jump_dslot ? exception_coming : exception_coming1 ;
exception_coming1 = jump_dslot ? 0 : exception_coming;
end
13'b0_0001_xxxx_xxxx: begin
//except_type <= #1 `OR1200_EXCEPT_BUSERR;
exception_here = exception_coming;
exception_coming2 = 0;
exception_coming1 = 0;
end
13'b0_0000_1xxx_xxxx: begin
//except_type <= #1 `OR1200_EXCEPT_ILLEGAL;
if (will_jump)
begin
// Writeback stage instruction will jump, and we have an
// illegal instruction in the decode/execute stage, which is
// the delay slot, so indicate the exception is coming...
exception_here = exception_coming2;
exception_coming2 = exception_coming;
exception_coming1 = 0;
end
else
begin
exception_here = jump_dslot ?
exception_coming2 : exception_coming;
exception_coming2 = jump_dslot ? exception_coming : 0;
exception_coming1 = 0;
end
end
13'b0_0000_01xx_xxxx: begin
//except_type <= #1 `OR1200_EXCEPT_ALIGN;
if(will_jump)
begin
exception_here = exception_coming2;
exception_coming2 = exception_coming;
exception_coming1 = 0;
end
else
begin
exception_here = (rfe) ? exception_coming : exception_coming2;
exception_coming2 = (rfe) ? 0 : exception_coming;
exception_coming1 = 0;
end
end
13'b0_0000_001x_xxxx: begin
//except_type <= #1 `OR1200_EXCEPT_DTLBMISS;
// Looks like except_trig goes high here after we check the
// instruction before the itlb miss after a delay slot, so we
// miss the dslot variable (it gets propegated before we call
// this task) so we use the jumped variable here to see if we
// are an exception after a delay slot
//exception_here = (jumped | rfe) ? exception_coming : exception_coming2 ;
//exception_coming2 = (jumped | rfe) ? 0 : exception_coming;
exception_here = (jumped | rfe) ? exception_coming : exception_coming2 ;
exception_coming2 = (jumped | rfe) ? 0 : exception_coming;
 
exception_coming1 = 0;
end
13'b0_0000_0001_xxxx: begin
//except_type <= #1 `OR1200_EXCEPT_DPF;
if (jumped) begin // Jumped onto illegal instruction
exception_here = exception_coming ;
exception_coming2 = 0;
exception_coming1 = 0;
end
else begin
exception_here = exception_coming2;
exception_coming2 = exception_coming;
exception_coming1 = 0;
end
end
13'b0_0000_0000_1xxx: begin // Data Bus Error
//except_type <= #1 `OR1200_EXCEPT_BUSERR;
exception_here = exception_coming2 ;
exception_coming2 = exception_coming;
exception_coming1 = 0;
end
13'b0_0000_0000_01xx: begin
//except_type <= #1 `OR1200_EXCEPT_RANGE;
#1;
end
13'b0_0000_0000_001x: begin
// trap
#1;
end
13'b0_0000_0000_0001: begin
//except_type <= #1 `OR1200_EXCEPT_SYSCALL;
exception_here = exception_coming2;
exception_coming2 = jumped ? exception_coming: exception_coming1 ;
exception_coming1 = jumped ? 0 : exception_coming;
end
endcase // casex (except_trig_r)
 
exception_coming = 0;
except_during_rfe = 0;
end
endtask // check_incoming_exceptions
 
/////////////////////////////////////////////////////////////////////////
// Execution tracking task
/////////////////////////////////////////////////////////////////////////
 
`ifdef OR1200_SYSTEM_CHECKER
always @(posedge `CPU_CORE_CLK)
begin
if (`OR1200_TOP.iwb_rst_i)
begin
exception_coming1 = 0;exception_coming2 = 0;exception_here= 0;
jumping = 0; jump_dslot = 0; jumped = 0;
rfe = 0;
end
if (!`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_freeze) begin
//#2 ;
// If instruction isn't a l.nop with bit 16 set (implementation's
// filler instruction in pipeline), and do not have an exception
// signaled with a dslot instruction in the execute stage
if (((`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[`OR1K_OPCODE_POS] !=
`OR1200_OR32_NOP) || !`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn[16])
&& !(`OR1200_TOP.`CPU_cpu.`CPU_except.except_flushpipe &&
`OR1200_TOP.`CPU_cpu.`CPU_except.ex_dslot)) // and not except start
begin
 
// Propegate jump-tracking variables
// If was exception in delay slot, we didn't actually jump
// so don't set jumped in this case.
jumped = exception_here ? 0 : jump_dslot;
jump_dslot = jumping;
jumping = 0;
rfe = 0;
// Now, check if current instruction will jump/branch, this is
// needed by the exception checking code, sets will_jump=1
check_for_jump(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
 
// Now check if it's an exception this instruction
check_incoming_exceptions;
 
// Case where we just went to an exception after a jump, so we
// mark the address we were meant to jump to as a place which will
// have duplicate return entries in the expected address list
if (exception_here & (jumped | jump_dslot))
begin
$display("%t: marked as jump address with exception (dup)"
,$time);
mark_duplicate_expected_address;
end
or1200_check_execution(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn,
`OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc,
exception_here);
//$write("%t: pc:0x%h\t",$time,
// `OR1200_TOP.`CPU_cpu.`CPU_except.wb_pc);
// Decode the instruction, print it out
//or1200_print_op(`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_insn);
//$write("\t exc:%0h dsl:%0h\n",exception_here,jump_dslot);
 
end
end // if (!`OR1200_TOP.`CPU_cpu.`CPU_ctrl.wb_freeze)
end // always @ (posedge `CPU_CORE_CLK)
`endif
 
task or1200_check_execution;
input [31:0] insn;
input [31:0] pc;
input exception;
reg [5:0] opcode;
 
reg [25:0] j_imm;
reg [25:0] br_imm;
reg [4:0] rD_num, rA_num, rB_num;
reg [31:0] rD_val, rA_val, rB_val;
reg [15:0] imm_16bit;
reg [15:0] mtspr_imm;
reg [3:0] alu_op;
reg [1:0] shrot_op;
 
reg [5:0] shroti_imm;
reg [5:0] sf_op;
reg [5:0] xsync_op;
 
reg flag;
 
reg [31:0] br_j_ea; // Branch/jump effective address
begin
// Instruction opcode
opcode = insn[`OR1K_OPCODE_POS];
// Immediates for jump or branch instructions
j_imm = insn[`OR1K_J_BR_IMM_POS];
br_imm = insn[`OR1K_J_BR_IMM_POS];
// Register numbers (D, A and B)
rD_num = insn[`OR1K_RD_POS];
rA_num = insn[`OR1K_RA_POS];
rB_num = insn[`OR1K_RB_POS];
// Bottom 16 bits when used as immediates in various instructions
imm_16bit = insn[15:0];
// 16-bit immediate for mtspr instructions
mtspr_imm = {insn[25:21],insn[10:0]};
// ALU op for ALU instructions
alu_op = insn[`OR1K_ALU_OP_POS];
// Shift-rotate op for SHROT ALU instructions
shrot_op = insn[`OR1K_SHROT_OP_POS];
shroti_imm = insn[`OR1K_SHROTI_IMM_POS];
 
// Set flag op
sf_op = insn[`OR1K_SF_OP];
// Xsync/syscall/trap opcode
xsync_op = insn[`OR1K_XSYNC_OP_POS];
 
// Use the flag from the previous instruction, as the decision
// is made in the execute stage not in te writeback stage,
// which is where we're getting our instructions.
flag = previous_sr[`OR1200_SR_F];
 
update_current_gprs;
 
// Check MSbit of the immediate, sign extend if set
br_j_ea = j_imm[25] ? pc + {4'hf,j_imm,2'b00} :
pc + {4'h0,j_imm,2'b00};
 
if (exception)
begin
$display("%t: exception - at 0x%x",$time, pc);
// get epcr, put it in the addresses we expect to jump
// back to
// Maybe DON'T do this. Because maybe in linux things we
// interrupt out of, we don't want to execute them again?
//add_expected_address(current_epcr);
end
 
check_expected_address(pc, (jumped & !exception));
 
rfe = 0;
case (opcode)
`OR1200_OR32_J:
begin
//
// PC < - exts(Immediate < < 2) + JumpInsnAddr
//
//The immediate value is shifted left two bits, sign-extended
// to program counter width, and then added to the address of
// the jump instruction. The result is the effective address
// of the jump. The program unconditionally jumps to EA with
// a delay of one instruction.
add_expected_address(br_j_ea);
 
jumping = 1;
end
`OR1200_OR32_JAL:
begin
//
//PC < - exts(Immediate < < 2) + JumpInsnAddr
//LR < - DelayInsnAddr + 4
//
// Link reg is r9, check it is PC+8
//
add_expected_address(br_j_ea);
assert_gpr_val(9, pc+8, pc);
jumping = 1; //
end
`OR1200_OR32_BNF:
begin
//EA < - exts(Immediate < < 2) + BranchInsnAddr
//PC < - EA if SR[F] cleared
if (!flag)
begin
add_expected_address(br_j_ea);
jumping = 1;
end
end
`OR1200_OR32_BF:
begin
//EA < - exts(Immediate < < 2) + BranchInsnAddr
//PC < - EA if SR[F] set
if (flag)
begin
add_expected_address(br_j_ea);
jumping = 1;
end
end
`OR1200_OR32_RFE:
begin
add_expected_address(current_epcr);
// jumping variable keeps track of jumps/branches with delay
// slot - there is none for l.rfe
rfe = 1;
end
`OR1200_OR32_JR:
begin
//PC < - rB
get_gpr(rB_num, rB_val);
add_expected_address(rB_val);
jumping = 1;
end
`OR1200_OR32_JALR:
begin
//PC < - rB
//LR < - DelayInsnAddr + 4
get_gpr(rB_num, rB_val);
add_expected_address(rB_val);
assert_gpr_val(9, pc+8, pc);
jumping = 1;
end
/*
`OR1200_OR32_LWZ,
`OR1200_OR32_LBZ,
`OR1200_OR32_LBS,
`OR1200_OR32_LHZ,
`OR1200_OR32_LHS,
`OR1200_OR32_SW,
`OR1200_OR32_SB,
`OR1200_OR32_SH:
begin
// Should result in databus access if data cache disabled
$display("%t: lsu instruction",$time);
end
 
`OR1200_OR32_MFSPR,
`OR1200_OR32_MTSPR:
begin
// Confirm RF values end up in the correct SPR
$display("%t: mxspr",$time);
end
 
`OR1200_OR32_MOVHI,
`OR1200_OR32_ADDI,
`OR1200_OR32_ADDIC,
`OR1200_OR32_ANDI,
`OR1200_OR32_ORI,
`OR1200_OR32_XORI,
`OR1200_OR32_MULI,
`OR1200_OR32_ALU:
begin
// Double check operations done on RF and immediate values
$display("%t: ALU op",$time);
end
`OR1200_OR32_SH_ROTI:
begin
// Rotate according to immediate - maybe should be in ALU ops
$display("%t: rotate op",$time);
end
`OR1200_OR32_SFXXI,
`OR1200_OR32_SFXX:
begin
// Set flag - do the check oursevles, check flag
$display("%t: set flag op",$time);
end
`OR1200_OR32_MACI,
`OR1200_OR32_MACMSB:
begin
// Either, multiply signed and accumulate, l.mac
// or multiply signed and subtract, l.msb
$display("%t: MAC op",$time);
end
*/
/*default:
begin
$display("%t: Unknown opcode 0x%h at pc 0x%x\n",
$time,opcode, pc);
end
*/
endcase // case (opcode)
 
update_previous_gprs;
end
endtask // or1200_check_execution
/////////////////////////////////////////////////////////////////////////
// Instruction decode task
/////////////////////////////////////////////////////////////////////////
 
task or1200_print_op;
input [31:0] insn;
 
reg [5:0] opcode;
reg [25:0] j_imm;
reg [25:0] br_imm;
reg [4:0] rD_num, rA_num, rB_num;
reg [31:0] rA_val, rB_val;
reg [15:0] imm_16bit;
reg [10:0] imm_split16bit;
reg [3:0] alu_op;
reg [1:0] shrot_op;
 
reg [5:0] shroti_imm;
 
reg [5:0] sf_op;
reg [5:0] xsync_op;
begin
// Instruction opcode
opcode = insn[`OR1K_OPCODE_POS];
// Immediates for jump or branch instructions
j_imm = insn[`OR1K_J_BR_IMM_POS];
br_imm = insn[`OR1K_J_BR_IMM_POS];
// Register numbers (D, A and B)
rD_num = insn[`OR1K_RD_POS];
rA_num = insn[`OR1K_RA_POS];
rB_num = insn[`OR1K_RB_POS];
// Bottom 16 bits when used as immediates in various instructions
imm_16bit = insn[15:0];
// Bottom 11 bits used as immediates for l.sX instructions
 
// Split 16-bit immediate for l.mtspr/l.sX instructions
imm_split16bit = {insn[25:21],insn[10:0]};
// ALU op for ALU instructions
alu_op = insn[`OR1K_ALU_OP_POS];
// Shift-rotate op for SHROT ALU instructions
shrot_op = insn[`OR1K_SHROT_OP_POS];
shroti_imm = insn[`OR1K_SHROTI_IMM_POS];
 
// Set flag op
sf_op = insn[`OR1K_SF_OP];
// Xsync/syscall/trap opcode
xsync_op = insn[`OR1K_XSYNC_OP_POS];
case (opcode)
`OR1200_OR32_J:
begin
$fwrite(finsn,"l.j 0x%h", {j_imm,2'b00});
end
`OR1200_OR32_JAL:
begin
$fwrite(finsn,"l.jal 0x%h", {j_imm,2'b00});
end
 
`OR1200_OR32_BNF:
begin
$fwrite(finsn,"l.bnf 0x%h", {br_imm,2'b00});
end
`OR1200_OR32_BF:
begin
$fwrite(finsn,"l.bf 0x%h", {br_imm,2'b00});
end
`OR1200_OR32_RFE:
begin
$fwrite(finsn,"l.rfe");
end
`OR1200_OR32_JR:
begin
$fwrite(finsn,"l.jr r%0d",rB_num);
end
`OR1200_OR32_JALR:
begin
$fwrite(finsn,"l.jalr r%0d",rB_num);
end
`OR1200_OR32_LWZ:
begin
$fwrite(finsn,"l.lwz r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
end
`OR1200_OR32_LBZ:
begin
$fwrite(finsn,"l.lbz r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
end
`OR1200_OR32_LBS:
begin
$fwrite(finsn,"l.lbs r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
end
`OR1200_OR32_LHZ:
begin
$fwrite(finsn,"l.lhz r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
end
`OR1200_OR32_LHS:
begin
$fwrite(finsn,"l.lhs r%0d,0x%0h(r%0d)",rD_num,imm_16bit,rA_num);
end
`OR1200_OR32_SW:
begin
$fwrite(finsn,"l.sw 0x%0h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
end
`OR1200_OR32_SB:
begin
$fwrite(finsn,"l.sb 0x%0h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
end
`OR1200_OR32_SH:
begin
$fwrite(finsn,"l.sh 0x%0h(r%0d),r%0d",imm_split16bit,rA_num,rB_num);
end
`OR1200_OR32_MFSPR:
begin
$fwrite(finsn,"l.mfspr r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit,);
end
 
`OR1200_OR32_MTSPR:
begin
$fwrite(finsn,"l.mtspr r%0d,r%0d,0x%h",rA_num,rB_num,imm_split16bit);
end
`OR1200_OR32_MOVHI:
begin
if (!insn[16])
$fwrite(finsn,"l.movhi r%0d,0x%h",rD_num,imm_16bit);
else
$fwrite(finsn,"l.macrc r%0d",rD_num);
end
`OR1200_OR32_ADDI:
begin
$fwrite(finsn,"l.addi r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
end
`OR1200_OR32_ADDIC:
begin
$fwrite(finsn,"l.addic r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
end
`OR1200_OR32_ANDI:
begin
$fwrite(finsn,"l.andi r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
end
`OR1200_OR32_ORI:
begin
$fwrite(finsn,"l.ori r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
end
 
`OR1200_OR32_XORI:
begin
$fwrite(finsn,"l.xori r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
end
 
`OR1200_OR32_MULI:
begin
$fwrite(finsn,"l.muli r%0d,r%0d,0x%h",rD_num,rA_num,imm_16bit);
end
`OR1200_OR32_ALU:
begin
case(alu_op)
`OR1200_ALUOP_ADD:
$fwrite(finsn,"l.add ");
`OR1200_ALUOP_ADDC:
$fwrite(finsn,"l.addc ");
`OR1200_ALUOP_SUB:
$fwrite(finsn,"l.sub ");
`OR1200_ALUOP_AND:
$fwrite(finsn,"l.and ");
`OR1200_ALUOP_OR:
$fwrite(finsn,"l.or ");
`OR1200_ALUOP_XOR:
$fwrite(finsn,"l.xor ");
`OR1200_ALUOP_MUL:
$fwrite(finsn,"l.mul ");
`OR1200_ALUOP_SHROT:
begin
case(shrot_op)
`OR1200_SHROTOP_SLL:
$fwrite(finsn,"l.sll ");
`OR1200_SHROTOP_SRL:
$fwrite(finsn,"l.srl ");
`OR1200_SHROTOP_SRA:
$fwrite(finsn,"l.sra ");
`OR1200_SHROTOP_ROR:
$fwrite(finsn,"l.ror ");
endcase // case (shrot_op)
end
`OR1200_ALUOP_DIV:
$fwrite(finsn,"l.div ");
`OR1200_ALUOP_DIVU:
$fwrite(finsn,"l.divu ");
`OR1200_ALUOP_CMOV:
$fwrite(finsn,"l.cmov ");
endcase // case (alu_op)
$fwrite(finsn,"r%0d,r%0d,r%0d",rD_num,rA_num,rB_num);
end
`OR1200_OR32_SH_ROTI:
begin
case(shrot_op)
`OR1200_SHROTOP_SLL:
$fwrite(finsn,"l.slli ");
`OR1200_SHROTOP_SRL:
$fwrite(finsn,"l.srli ");
`OR1200_SHROTOP_SRA:
$fwrite(finsn,"l.srai ");
`OR1200_SHROTOP_ROR:
$fwrite(finsn,"l.rori ");
endcase // case (shrot_op)
$fwrite(finsn,"r%0d,r%0d,0x%h",rD_num,rA_num,shroti_imm);
end
`OR1200_OR32_SFXXI:
begin
case(sf_op[2:0])
`OR1200_COP_SFEQ:
$fwrite(finsn,"l.sfeqi ");
`OR1200_COP_SFNE:
$fwrite(finsn,"l.sfnei ");
`OR1200_COP_SFGT:
begin
if (sf_op[`OR1200_SIGNED_COMPARE])
$fwrite(finsn,"l.sfgtsi ");
else
$fwrite(finsn,"l.sfgtui ");
end
`OR1200_COP_SFGE:
begin
if (sf_op[`OR1200_SIGNED_COMPARE])
$fwrite(finsn,"l.sfgesi ");
else
$fwrite(finsn,"l.sfgeui ");
end
`OR1200_COP_SFLT:
begin
if (sf_op[`OR1200_SIGNED_COMPARE])
$fwrite(finsn,"l.sfltsi ");
else
$fwrite(finsn,"l.sfltui ");
end
`OR1200_COP_SFLE:
begin
if (sf_op[`OR1200_SIGNED_COMPARE])
$fwrite(finsn,"l.sflesi ");
else
$fwrite(finsn,"l.sfleui ");
end
endcase // case (sf_op[2:0])
$fwrite(finsn,"r%0d,0x%h",rA_num, imm_16bit);
end // case: `OR1200_OR32_SFXXI
 
`OR1200_OR32_SFXX:
begin
case(sf_op[2:0])
`OR1200_COP_SFEQ:
$fwrite(finsn,"l.sfeq ");
`OR1200_COP_SFNE:
$fwrite(finsn,"l.sfne ");
`OR1200_COP_SFGT:
begin
if (sf_op[`OR1200_SIGNED_COMPARE])
$fwrite(finsn,"l.sfgts ");
else
$fwrite(finsn,"l.sfgtu ");
end
`OR1200_COP_SFGE:
begin
if (sf_op[`OR1200_SIGNED_COMPARE])
$fwrite(finsn,"l.sfges ");
else
$fwrite(finsn,"l.sfgeu ");
end
`OR1200_COP_SFLT:
begin
if (sf_op[`OR1200_SIGNED_COMPARE])
$fwrite(finsn,"l.sflts ");
else
$fwrite(finsn,"l.sfltu ");
end
`OR1200_COP_SFLE:
begin
if (sf_op[`OR1200_SIGNED_COMPARE])
$fwrite(finsn,"l.sfles ");
else
$fwrite(finsn,"l.sfleu ");
end
endcase // case (sf_op[2:0])
$fwrite(finsn,"r%0d,r%0d",rA_num, rB_num);
end
`OR1200_OR32_MACI:
begin
$fwrite(finsn,"l.maci r%0d,0x%h",rA_num,imm_16bit);
end
 
`OR1200_OR32_MACMSB:
begin
if(insn[3:0] == 4'h1)
$fwrite(finsn,"l.mac ");
else if(insn[3:0] == 4'h2)
$fwrite(finsn,"l.msb ");
$fwrite(finsn,"r%0d,r%0d",rA_num,rB_num);
end
 
`OR1200_OR32_NOP:
begin
$fwrite(finsn,"l.nop 0x%0h",imm_16bit);
end
`OR1200_OR32_XSYNC:
begin
case (xsync_op)
5'd0:
$fwrite(finsn,"l.sys 0x%h",imm_16bit);
5'd8:
$fwrite(finsn,"l.trap 0x%h",imm_16bit);
5'd16:
$fwrite(finsn,"l.msync");
5'd20:
$fwrite(finsn,"l.psync");
5'd24:
$fwrite(finsn,"l.csync");
default:
begin
$display("%t: Instruction with opcode 0x%h has bad specific type information: 0x%h",$time,opcode,insn);
$fwrite(finsn,"%t: Instruction with opcode 0x%h has has bad specific type information: 0x%h",$time,opcode,insn);
end
endcase // case (xsync_op)
end
default:
begin
$display("%t: Unknown opcode 0x%h",$time,opcode);
$fwrite(finsn,"%t: Unknown opcode 0x%h",$time,opcode);
end
endcase // case (opcode)
end
endtask // or1200_print_op
 
 
endmodule
generic/ft/bench/verilog/or1200_monitor.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: generic/ft/rtl/verilog/clkgen/clkgen.v =================================================================== --- generic/ft/rtl/verilog/clkgen/clkgen.v (nonexistent) +++ generic/ft/rtl/verilog/clkgen/clkgen.v (revision 483) @@ -0,0 +1,118 @@ +////////////////////////////////////////////////////////////////////// +// +// clkgen +// +// Handles clock and reset generation for rest of design +// +// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG //// +//// //// +//// 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, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// A simple implementation for the main generic ORPSoC simulations +// + +`include "timescale.v" +`include "orpsoc-defines.v" + +module clkgen + ( + // Main clocks in, depending on board + clk_pad_i, + + // Input reset - through a buffer, asynchronous + async_rst_o, + // Wishbone clock and reset out + wb_clk_o, + wb_rst_o, + + // JTAG clock +`ifdef JTAG_DEBUG + tck_pad_i, + dbg_tck_o, +`endif + + // Asynchronous, active low reset in + rst_n_pad_i + + ); + + input clk_pad_i; + + output async_rst_o; + + output wb_rst_o; + output wb_clk_o; + +`ifdef JTAG_DEBUG + input tck_pad_i; + output dbg_tck_o; +`endif + + // Asynchronous, active low reset (pushbutton, typically) + input rst_n_pad_i; + + // First, deal with the asychronous reset + wire async_rst_n; + + // An input buffer is usually instantiated here + assign async_rst_n = rst_n_pad_i; + + // Everyone likes active-high reset signals... + assign async_rst_o = ~async_rst_n; + +`ifdef JTAG_DEBUG + assign dbg_tck_o = tck_pad_i; +`endif + + // + // Declare synchronous reset wires here + // + + // An active-low synchronous reset signal (usually a PLL lock signal) + wire sync_rst_n; + assign sync_rst_n = async_rst_n; // Pretend it's somehow synchronous now + + + // Here we just assign "board" clock (really test) to wishbone clock + assign wb_clk_o = clk_pad_i; + + // + // Reset generation + // + // + + // Reset generation for wishbone + reg [15:0] wb_rst_shr; + always @(posedge wb_clk_o or posedge async_rst_o) + if (async_rst_o) + wb_rst_shr <= 16'hffff; + else + wb_rst_shr <= {wb_rst_shr[14:0], ~(sync_rst_n)}; + + assign wb_rst_o = wb_rst_shr[15]; + +endmodule // clkgen Index: generic/ft/rtl/verilog/clkgen/README =================================================================== --- generic/ft/rtl/verilog/clkgen/README (nonexistent) +++ generic/ft/rtl/verilog/clkgen/README (revision 483) @@ -0,0 +1,20 @@ +Clock and reset generation module + +This module should be used as the main reset and clock generation module. It +should have the asynchronous resets and unbuffered clock lines coming in, and +depending on defines in the main design file, generate the appropriate clocks +and clock-synchronous resets. + +Currently Actel and Xilinx technlogies are supported. It is unclear if the way +it is handling clock-configurations depending on boards is ideal, potentially +it could become very cluttered if further board support is added and this would +need to be looked at. + +The technology-dependent modules (PLLs, buffers) instantiated here should be +located under the backend/vendor/rtl paths. + +As mentioned previously, it is unclear if this is the best way to manage the +task of clock and reset generation, particularly if further specialised clock +domains wish to be added, however there is some benefit in that it is all +managed in one place and with the strict rules that all clocks and resets come +to this module to be generated. \ No newline at end of file Index: generic/ft/rtl/verilog/include/or1200_defines.v =================================================================== --- generic/ft/rtl/verilog/include/or1200_defines.v (nonexistent) +++ generic/ft/rtl/verilog/include/or1200_defines.v (revision 483) @@ -0,0 +1,1791 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// OR1200's definitions //// +//// //// +//// This file is part of the OpenRISC 1200 project //// +//// http://opencores.org/project,or1k //// +//// //// +//// Description //// +//// Defines for the OR1200 core //// +//// //// +//// To Do: //// +//// - add parameters that are missing //// +//// //// +//// Author(s): //// +//// - Damjan Lampret, lampret@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// 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, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// $Log: or1200_defines.v,v $ +// Revision 2.0 2010/06/30 11:00:00 ORSoC +// Minor update: +// Defines added, bugs fixed. + +// +// Dump VCD +// +//`define OR1200_VCD_DUMP + +// +// Generate debug messages during simulation +// +//`define OR1200_VERBOSE + +// `define OR1200_ASIC +//////////////////////////////////////////////////////// +// +// Typical configuration for an ASIC +// +`ifdef OR1200_ASIC + +// +// Target ASIC memories +// +//`define OR1200_ARTISAN_SSP +//`define OR1200_ARTISAN_SDP +//`define OR1200_ARTISAN_STP +`define OR1200_VIRTUALSILICON_SSP +//`define OR1200_VIRTUALSILICON_STP_T1 +//`define OR1200_VIRTUALSILICON_STP_T2 + +// +// Do not implement Data cache +// +//`define OR1200_NO_DC + +// +// Do not implement Insn cache +// +//`define OR1200_NO_IC + +// +// Do not implement Data MMU +// +//`define OR1200_NO_DMMU + +// +// Do not implement Insn MMU +// +//`define OR1200_NO_IMMU + +// +// Select between ASIC optimized and generic multiplier +// +//`define OR1200_ASIC_MULTP2_32X32 +`define OR1200_GENERIC_MULTP2_32X32 + +// +// Size/type of insn/data cache if implemented +// +// `define OR1200_IC_1W_512B +// `define OR1200_IC_1W_4KB +`define OR1200_IC_1W_8KB +// `define OR1200_DC_1W_4KB +`define OR1200_DC_1W_8KB + +`else + + +///////////////////////////////////////////////////////// +// +// Typical configuration for an FPGA +// + +// +// Target FPGA memories +// +//`define OR1200_ALTERA_LPM +//`define OR1200_XILINX_RAMB16 +//`define OR1200_XILINX_RAMB4 +//`define OR1200_XILINX_RAM32X1D +//`define OR1200_USE_RAM16X1D_FOR_RAM32X1D +// Generic models should infer RAM blocks at synthesis time (not only effects +// single port ram.) +`define OR1200_GENERIC + +// +// Do not implement Data cache +// +//`define OR1200_NO_DC + +// +// Do not implement Insn cache +// +//`define OR1200_NO_IC + +// +// Do not implement Data MMU +// +//`define OR1200_NO_DMMU + +// +// Do not implement Insn MMU +// +//`define OR1200_NO_IMMU + +// +// Select between ASIC and generic multiplier +// +// (Generic seems to trigger a bug in the Cadence Ncsim simulator) +// +//`define OR1200_ASIC_MULTP2_32X32 +`define OR1200_GENERIC_MULTP2_32X32 + +// +// Size/type of insn/data cache if implemented +// (consider available FPGA memory resources) +// +//`define OR1200_IC_1W_512B +`define OR1200_IC_1W_4KB +//`define OR1200_IC_1W_8KB +//`define OR1200_IC_1W_16KB +//`define OR1200_IC_1W_32KB +`define OR1200_DC_1W_4KB +//`define OR1200_DC_1W_8KB +//`define OR1200_DC_1W_16KB +//`define OR1200_DC_1W_32KB + +`endif + + +////////////////////////////////////////////////////////// +// +// Do not change below unless you know what you are doing +// + +// +// Reset active low +// +//`define OR1200_RST_ACT_LOW + +// +// Enable RAM BIST +// +// At the moment this only works for Virtual Silicon +// single port RAMs. For other RAMs it has not effect. +// Special wrapper for VS RAMs needs to be provided +// with scan flops to facilitate bist scan. +// +//`define OR1200_BIST + +// +// Register OR1200 WISHBONE outputs +// (must be defined/enabled) +// +`define OR1200_REGISTERED_OUTPUTS + +// +// Register OR1200 WISHBONE inputs +// +// (must be undefined/disabled) +// +//`define OR1200_REGISTERED_INPUTS + +// +// Disable bursts if they are not supported by the +// memory subsystem (only affect cache line fill) +// +//`define OR1200_NO_BURSTS +// + +// +// WISHBONE retry counter range +// +// 2^value range for retry counter. Retry counter +// is activated whenever *wb_rty_i is asserted and +// until retry counter expires, corresponding +// WISHBONE interface is deactivated. +// +// To disable retry counters and *wb_rty_i all together, +// undefine this macro. +// +//`define OR1200_WB_RETRY 7 + +// +// WISHBONE Consecutive Address Burst +// +// This was used prior to WISHBONE B3 specification +// to identify bursts. It is no longer needed but +// remains enabled for compatibility with old designs. +// +// To remove *wb_cab_o ports undefine this macro. +// +//`define OR1200_WB_CAB + +// +// WISHBONE B3 compatible interface +// +// This follows the WISHBONE B3 specification. +// It is not enabled by default because most +// designs still don't use WB b3. +// +// To enable *wb_cti_o/*wb_bte_o ports, +// define this macro. +// +`define OR1200_WB_B3 + +// +// LOG all WISHBONE accesses +// +`define OR1200_LOG_WB_ACCESS + +// +// Enable additional synthesis directives if using +// _Synopsys_ synthesis tool +// +//`define OR1200_ADDITIONAL_SYNOPSYS_DIRECTIVES + +// +// Enables default statement in some case blocks +// and disables Synopsys synthesis directive full_case +// +// By default it is enabled. When disabled it +// can increase clock frequency. +// +`define OR1200_CASE_DEFAULT + +// +// Operand width / register file address width +// +// (DO NOT CHANGE) +// +`define OR1200_OPERAND_WIDTH 32 +`define OR1200_REGFILE_ADDR_WIDTH 5 + +// +// l.add/l.addi/l.and and optional l.addc/l.addic +// also set (compare) flag when result of their +// operation equals zero +// +// At the time of writing this, default or32 +// C/C++ compiler doesn't generate code that +// would benefit from this optimization. +// +// By default this optimization is disabled to +// save area. +// +//`define OR1200_ADDITIONAL_FLAG_MODIFIERS + +// +// Implement l.addc/l.addic instructions +// +// By default implementation of l.addc/l.addic +// instructions is enabled in case you need them. +// If you don't use them, then disable implementation +// to save area. +// +//`define OR1200_IMPL_ADDC + +// +// Implement l.sub instruction +// +// By default implementation of l.sub instructions +// is enabled to be compliant with the simulator. +// If you don't use carry bit, then disable +// implementation to save area. +// +`define OR1200_IMPL_SUB + +// +// Implement carry bit SR[CY] +// +// +// By default implementation of SR[CY] is enabled +// to be compliant with the simulator. However SR[CY] +// is explicitly only used by l.addc/l.addic/l.sub +// instructions and if these three insns are not +// implemented there is not much point having SR[CY]. +// +//`define OR1200_IMPL_CY + +// +// Implement rotate in the ALU +// +// At the time of writing this, or32 +// C/C++ compiler doesn't generate rotate +// instructions. However or32 assembler +// can assemble code that uses rotate insn. +// This means that rotate instructions +// must be used manually inserted. +// +// By default implementation of rotate +// is disabled to save area and increase +// clock frequency. +// +//`define OR1200_IMPL_ALU_ROTATE + +// +// Type of ALU compare to implement +// +// Try either one to find what yields +// higher clock frequencyin your case. +// +//`define OR1200_IMPL_ALU_COMP1 +`define OR1200_IMPL_ALU_COMP2 + +// +// Implement Find First/Last '1' +// +`define OR1200_IMPL_ALU_FFL1 + +// +// Implement multiplier +// +// By default multiplier is implemented +// +`define OR1200_MULT_IMPLEMENTED + +// +// Implement multiply-and-accumulate +// +// By default MAC is implemented. To +// implement MAC, multiplier (non-serial) needs to be +// implemented. +// +`define OR1200_MAC_IMPLEMENTED + +// +// Implement optional l.div/l.divu instructions +// +// By default divide instructions are not implemented +// to save area. +// +// +`define OR1200_DIV_IMPLEMENTED + +// +// Serial multiplier. +// +//`define OR1200_MULT_SERIAL + +// +// Serial divider. +// Uncomment to use a serial divider, otherwise will +// be a generic parallel implementation. +// +//`define OR1200_DIV_SERIAL + +// +// Implement HW Single Precision FPU +// +`define OR1200_FPU_IMPLEMENTED + + +// +// Clock ratio RISC clock versus WB clock +// +// If you plan to run WB:RISC clock fixed to 1:1, disable +// both defines +// +// For WB:RISC 1:2 or 1:1, enable OR1200_CLKDIV_2_SUPPORTED +// and use clmode to set ratio +// +// For WB:RISC 1:4, 1:2 or 1:1, enable both defines and use +// clmode to set ratio +// +//`define OR1200_CLKDIV_2_SUPPORTED +//`define OR1200_CLKDIV_4_SUPPORTED + +// +// Type of register file RAM +// +// Memory macro w/ two ports (see or1200_tpram_32x32.v) +//`define OR1200_RFRAM_TWOPORT +// +// Memory macro dual port (see or1200_dpram.v) +`define OR1200_RFRAM_DUALPORT + +// +// Generic (flip-flop based) register file (see or1200_rfram_generic.v) +//`define OR1200_RFRAM_GENERIC +// Generic register file supports - 16 registers +`ifdef OR1200_RFRAM_GENERIC +// `define OR1200_RFRAM_16REG +`endif + +// +// Type of mem2reg aligner to implement. +// +// Once OR1200_IMPL_MEM2REG2 yielded faster +// circuit, however with today tools it will +// most probably give you slower circuit. +// +`define OR1200_IMPL_MEM2REG1 +//`define OR1200_IMPL_MEM2REG2 + +// +// Parity error detection. +// +// Add a parity bit for each byte held in various memories around the OR1200 +// and signal externally in event of parity error. +`define OR1200_RAM_PARITY + + +// +// Reset value and event +// +`ifdef OR1200_RST_ACT_LOW + `define OR1200_RST_VALUE (1'b0) + `define OR1200_RST_EVENT negedge +`else + `define OR1200_RST_VALUE (1'b1) + `define OR1200_RST_EVENT posedge +`endif + +// +// ALUOPs +// +`define OR1200_ALUOP_WIDTH 4 +`define OR1200_ALUOP_NOP 4'd4 +/* Order defined by arith insns that have two source operands both in regs + (see binutils/include/opcode/or32.h) */ +`define OR1200_ALUOP_ADD 4'd0 +`define OR1200_ALUOP_ADDC 4'd1 +`define OR1200_ALUOP_SUB 4'd2 +`define OR1200_ALUOP_AND 4'd3 +`define OR1200_ALUOP_OR 4'd4 +`define OR1200_ALUOP_XOR 4'd5 +`define OR1200_ALUOP_MUL 4'd6 +`define OR1200_ALUOP_CUST5 4'd7 +`define OR1200_ALUOP_SHROT 4'd8 +`define OR1200_ALUOP_DIV 4'd9 +`define OR1200_ALUOP_DIVU 4'd10 +`define OR1200_ALUOP_MULU 4'd11 +/* Values sent to ALU from decode unit - not strictly defined by ISA */ +`define OR1200_ALUOP_MOVHI 4'd12 +`define OR1200_ALUOP_COMP 4'd13 +`define OR1200_ALUOP_MTSR 4'd14 +`define OR1200_ALUOP_MFSR 4'd15 +`define OR1200_ALUOP_CMOV 4'd14 +`define OR1200_ALUOP_FFL1 4'd15 + + +// ALU instructions second opcode field (previously multicycle field in +// machine word) +`define OR1200_ALUOP2_POS 9:8 +`define OR1200_ALUOP2_WIDTH 2 + + +// +// MACOPs +// +`define OR1200_MACOP_WIDTH 3 +`define OR1200_MACOP_NOP 3'b000 +`define OR1200_MACOP_MAC 3'b001 +`define OR1200_MACOP_MSB 3'b010 + +// +// Shift/rotate ops +// +`define OR1200_SHROTOP_WIDTH 2 +`define OR1200_SHROTOP_NOP 2'd0 +`define OR1200_SHROTOP_SLL 2'd0 +`define OR1200_SHROTOP_SRL 2'd1 +`define OR1200_SHROTOP_SRA 2'd2 +`define OR1200_SHROTOP_ROR 2'd3 + +// Execution cycles per instruction +`define OR1200_MULTICYCLE_WIDTH 3 +`define OR1200_ONE_CYCLE 3'd0 +`define OR1200_TWO_CYCLES 3'd1 + +// Execution control which will "wait on" a module to finish +`define OR1200_WAIT_ON_WIDTH 2 +`define OR1200_WAIT_ON_FPU `OR1200_WAIT_ON_WIDTH'd1 +`define OR1200_WAIT_ON_MTSPR `OR1200_WAIT_ON_WIDTH'd2 + +// Operand MUX selects +`define OR1200_SEL_WIDTH 2 +`define OR1200_SEL_RF 2'd0 +`define OR1200_SEL_IMM 2'd1 +`define OR1200_SEL_EX_FORW 2'd2 +`define OR1200_SEL_WB_FORW 2'd3 + +// +// BRANCHOPs +// +`define OR1200_BRANCHOP_WIDTH 3 +`define OR1200_BRANCHOP_NOP 3'd0 +`define OR1200_BRANCHOP_J 3'd1 +`define OR1200_BRANCHOP_JR 3'd2 +`define OR1200_BRANCHOP_BAL 3'd3 +`define OR1200_BRANCHOP_BF 3'd4 +`define OR1200_BRANCHOP_BNF 3'd5 +`define OR1200_BRANCHOP_RFE 3'd6 + +// +// LSUOPs +// +// Bit 0: sign extend +// Bits 1-2: 00 doubleword, 01 byte, 10 halfword, 11 singleword +// Bit 3: 0 load, 1 store +`define OR1200_LSUOP_WIDTH 4 +`define OR1200_LSUOP_NOP 4'b0000 +`define OR1200_LSUOP_LBZ 4'b0010 +`define OR1200_LSUOP_LBS 4'b0011 +`define OR1200_LSUOP_LHZ 4'b0100 +`define OR1200_LSUOP_LHS 4'b0101 +`define OR1200_LSUOP_LWZ 4'b0110 +`define OR1200_LSUOP_LWS 4'b0111 +`define OR1200_LSUOP_LD 4'b0001 +`define OR1200_LSUOP_SD 4'b1000 +`define OR1200_LSUOP_SB 4'b1010 +`define OR1200_LSUOP_SH 4'b1100 +`define OR1200_LSUOP_SW 4'b1110 + +// Number of bits of load/store EA precalculated in ID stage +// for balancing ID and EX stages. +// +// Valid range: 2,3,...,30,31 +`define OR1200_LSUEA_PRECALC 2 + +// FETCHOPs +`define OR1200_FETCHOP_WIDTH 1 +`define OR1200_FETCHOP_NOP 1'b0 +`define OR1200_FETCHOP_LW 1'b1 + +// +// Register File Write-Back OPs +// +// Bit 0: register file write enable +// Bits 3-1: write-back mux selects +// +`define OR1200_RFWBOP_WIDTH 4 +`define OR1200_RFWBOP_NOP 4'b0000 +`define OR1200_RFWBOP_ALU 3'b000 +`define OR1200_RFWBOP_LSU 3'b001 +`define OR1200_RFWBOP_SPRS 3'b010 +`define OR1200_RFWBOP_LR 3'b011 +`define OR1200_RFWBOP_FPU 3'b100 + +// Compare instructions +`define OR1200_COP_SFEQ 3'b000 +`define OR1200_COP_SFNE 3'b001 +`define OR1200_COP_SFGT 3'b010 +`define OR1200_COP_SFGE 3'b011 +`define OR1200_COP_SFLT 3'b100 +`define OR1200_COP_SFLE 3'b101 +`define OR1200_COP_X 3'b111 +`define OR1200_SIGNED_COMPARE 'd3 +`define OR1200_COMPOP_WIDTH 4 + +// +// FP OPs +// +// MSbit indicates FPU operation valid +// +`define OR1200_FPUOP_WIDTH 8 +// FPU unit from Usselman takes 5 cycles from decode, so 4 ex. cycles +`define OR1200_FPUOP_CYCLES 3'd4 +// FP instruction is double precision if bit 4 is set. We're a 32-bit +// implementation thus do not support double precision FP +`define OR1200_FPUOP_DOUBLE_BIT 4 +`define OR1200_FPUOP_ADD 8'b0000_0000 +`define OR1200_FPUOP_SUB 8'b0000_0001 +`define OR1200_FPUOP_MUL 8'b0000_0010 +`define OR1200_FPUOP_DIV 8'b0000_0011 +`define OR1200_FPUOP_ITOF 8'b0000_0100 +`define OR1200_FPUOP_FTOI 8'b0000_0101 +`define OR1200_FPUOP_REM 8'b0000_0110 +`define OR1200_FPUOP_RESERVED 8'b0000_0111 +// FP Compare instructions +`define OR1200_FPCOP_SFEQ 8'b0000_1000 +`define OR1200_FPCOP_SFNE 8'b0000_1001 +`define OR1200_FPCOP_SFGT 8'b0000_1010 +`define OR1200_FPCOP_SFGE 8'b0000_1011 +`define OR1200_FPCOP_SFLT 8'b0000_1100 +`define OR1200_FPCOP_SFLE 8'b0000_1101 + +// +// TAGs for instruction bus +// +`define OR1200_ITAG_IDLE 4'h0 // idle bus +`define OR1200_ITAG_NI 4'h1 // normal insn +`define OR1200_ITAG_BE 4'hb // Bus error exception +`define OR1200_ITAG_PE 4'hc // Page fault exception +`define OR1200_ITAG_TE 4'hd // TLB miss exception + +// +// TAGs for data bus +// +`define OR1200_DTAG_IDLE 4'h0 // idle bus +`define OR1200_DTAG_ND 4'h1 // normal data +`define OR1200_DTAG_AE 4'ha // Alignment exception +`define OR1200_DTAG_BE 4'hb // Bus error exception +`define OR1200_DTAG_PE 4'hc // Page fault exception +`define OR1200_DTAG_TE 4'hd // TLB miss exception + + +////////////////////////////////////////////// +// +// ORBIS32 ISA specifics +// + +// SHROT_OP position in machine word +`define OR1200_SHROTOP_POS 7:6 + +// +// Instruction opcode groups (basic) +// +`define OR1200_OR32_J 6'b000000 +`define OR1200_OR32_JAL 6'b000001 +`define OR1200_OR32_BNF 6'b000011 +`define OR1200_OR32_BF 6'b000100 +`define OR1200_OR32_NOP 6'b000101 +`define OR1200_OR32_MOVHI 6'b000110 +`define OR1200_OR32_XSYNC 6'b001000 +`define OR1200_OR32_RFE 6'b001001 +/* */ +`define OR1200_OR32_JR 6'b010001 +`define OR1200_OR32_JALR 6'b010010 +`define OR1200_OR32_MACI 6'b010011 +/* */ +`define OR1200_OR32_LWZ 6'b100001 +`define OR1200_OR32_LBZ 6'b100011 +`define OR1200_OR32_LBS 6'b100100 +`define OR1200_OR32_LHZ 6'b100101 +`define OR1200_OR32_LHS 6'b100110 +`define OR1200_OR32_ADDI 6'b100111 +`define OR1200_OR32_ADDIC 6'b101000 +`define OR1200_OR32_ANDI 6'b101001 +`define OR1200_OR32_ORI 6'b101010 +`define OR1200_OR32_XORI 6'b101011 +`define OR1200_OR32_MULI 6'b101100 +`define OR1200_OR32_MFSPR 6'b101101 +`define OR1200_OR32_SH_ROTI 6'b101110 +`define OR1200_OR32_SFXXI 6'b101111 +/* */ +`define OR1200_OR32_MTSPR 6'b110000 +`define OR1200_OR32_MACMSB 6'b110001 +`define OR1200_OR32_FLOAT 6'b110010 +/* */ +`define OR1200_OR32_SW 6'b110101 +`define OR1200_OR32_SB 6'b110110 +`define OR1200_OR32_SH 6'b110111 +`define OR1200_OR32_ALU 6'b111000 +`define OR1200_OR32_SFXX 6'b111001 +//`define OR1200_OR32_CUST5 6'b111100 + + +///////////////////////////////////////////////////// +// +// Exceptions +// + +// +// Exception vectors per OR1K architecture: +// 0xPPPPP100 - reset +// 0xPPPPP200 - bus error +// ... etc +// where P represents exception prefix. +// +// Exception vectors can be customized as per +// the following formula: +// 0xPPPPPNVV - exception N +// +// P represents exception prefix +// N represents exception N +// VV represents length of the individual vector space, +// usually it is 8 bits wide and starts with all bits zero +// + +// +// PPPPP and VV parts +// +// Sum of these two defines needs to be 28 +// +`define OR1200_EXCEPT_EPH0_P 20'h00000 +`define OR1200_EXCEPT_EPH1_P 20'hF0000 +`define OR1200_EXCEPT_V 8'h00 + +// +// N part width +// +`define OR1200_EXCEPT_WIDTH 4 + +// +// Definition of exception vectors +// +// To avoid implementation of a certain exception, +// simply comment out corresponding line +// +`define OR1200_EXCEPT_UNUSED `OR1200_EXCEPT_WIDTH'hf +`define OR1200_EXCEPT_TRAP `OR1200_EXCEPT_WIDTH'he +`define OR1200_EXCEPT_FLOAT `OR1200_EXCEPT_WIDTH'hd +`define OR1200_EXCEPT_SYSCALL `OR1200_EXCEPT_WIDTH'hc +`define OR1200_EXCEPT_RANGE `OR1200_EXCEPT_WIDTH'hb +`define OR1200_EXCEPT_ITLBMISS `OR1200_EXCEPT_WIDTH'ha +`define OR1200_EXCEPT_DTLBMISS `OR1200_EXCEPT_WIDTH'h9 +`define OR1200_EXCEPT_INT `OR1200_EXCEPT_WIDTH'h8 +`define OR1200_EXCEPT_ILLEGAL `OR1200_EXCEPT_WIDTH'h7 +`define OR1200_EXCEPT_ALIGN `OR1200_EXCEPT_WIDTH'h6 +`define OR1200_EXCEPT_TICK `OR1200_EXCEPT_WIDTH'h5 +`define OR1200_EXCEPT_IPF `OR1200_EXCEPT_WIDTH'h4 +`define OR1200_EXCEPT_DPF `OR1200_EXCEPT_WIDTH'h3 +`define OR1200_EXCEPT_BUSERR `OR1200_EXCEPT_WIDTH'h2 +`define OR1200_EXCEPT_RESET `OR1200_EXCEPT_WIDTH'h1 +`define OR1200_EXCEPT_NONE `OR1200_EXCEPT_WIDTH'h0 + + +///////////////////////////////////////////////////// +// +// SPR groups +// + +// Bits that define the group +`define OR1200_SPR_GROUP_BITS 15:11 + +// Width of the group bits +`define OR1200_SPR_GROUP_WIDTH 5 + +// Bits that define offset inside the group +`define OR1200_SPR_OFS_BITS 10:0 + +// List of groups +`define OR1200_SPR_GROUP_SYS 5'd00 +`define OR1200_SPR_GROUP_DMMU 5'd01 +`define OR1200_SPR_GROUP_IMMU 5'd02 +`define OR1200_SPR_GROUP_DC 5'd03 +`define OR1200_SPR_GROUP_IC 5'd04 +`define OR1200_SPR_GROUP_MAC 5'd05 +`define OR1200_SPR_GROUP_DU 5'd06 +`define OR1200_SPR_GROUP_PM 5'd08 +`define OR1200_SPR_GROUP_PIC 5'd09 +`define OR1200_SPR_GROUP_TT 5'd10 +`define OR1200_SPR_GROUP_FPU 5'd11 + +///////////////////////////////////////////////////// +// +// System group +// + +// +// System registers +// +`define OR1200_SPR_CFGR 7'd0 +`define OR1200_SPR_RF 6'd32 // 1024 >> 5 +`define OR1200_SPR_NPC 11'd16 +`define OR1200_SPR_SR 11'd17 +`define OR1200_SPR_PPC 11'd18 +`define OR1200_SPR_FPCSR 11'd20 +`define OR1200_SPR_EPCR 11'd32 +`define OR1200_SPR_EEAR 11'd48 +`define OR1200_SPR_ESR 11'd64 + +// +// SR bits +// +`define OR1200_SR_WIDTH 17 +`define OR1200_SR_SM 0 +`define OR1200_SR_TEE 1 +`define OR1200_SR_IEE 2 +`define OR1200_SR_DCE 3 +`define OR1200_SR_ICE 4 +`define OR1200_SR_DME 5 +`define OR1200_SR_IME 6 +`define OR1200_SR_LEE 7 +`define OR1200_SR_CE 8 +`define OR1200_SR_F 9 +`define OR1200_SR_CY 10 // Unused +`define OR1200_SR_OV 11 // Unused +`define OR1200_SR_OVE 12 // Unused +`define OR1200_SR_DSX 13 // Unused +`define OR1200_SR_EPH 14 +`define OR1200_SR_FO 15 +`define OR1200_SR_TED 16 +`define OR1200_SR_CID 31:28 // Unimplemented + +// +// Bits that define offset inside the group +// +`define OR1200_SPROFS_BITS 10:0 + +// +// Default Exception Prefix +// +// 1'b0 - OR1200_EXCEPT_EPH0_P (0x0000_0000) +// 1'b1 - OR1200_EXCEPT_EPH1_P (0xF000_0000) +// +`define OR1200_SR_EPH_DEF 1'b0 + + +// +// FPCSR bits +// +`define OR1200_FPCSR_WIDTH 12 +`define OR1200_FPCSR_FPEE 0 +`define OR1200_FPCSR_RM 2:1 +`define OR1200_FPCSR_OVF 3 +`define OR1200_FPCSR_UNF 4 +`define OR1200_FPCSR_SNF 5 +`define OR1200_FPCSR_QNF 6 +`define OR1200_FPCSR_ZF 7 +`define OR1200_FPCSR_IXF 8 +`define OR1200_FPCSR_IVF 9 +`define OR1200_FPCSR_INF 10 +`define OR1200_FPCSR_DZF 11 +`define OR1200_FPCSR_RES 31:12 + +///////////////////////////////////////////////////// +// +// Power Management (PM) +// + +// Define it if you want PM implemented +//`define OR1200_PM_IMPLEMENTED + +// Bit positions inside PMR (don't change) +`define OR1200_PM_PMR_SDF 3:0 +`define OR1200_PM_PMR_DME 4 +`define OR1200_PM_PMR_SME 5 +`define OR1200_PM_PMR_DCGE 6 +`define OR1200_PM_PMR_UNUSED 31:7 + +// PMR offset inside PM group of registers +`define OR1200_PM_OFS_PMR 11'b0 + +// PM group +`define OR1200_SPRGRP_PM 5'd8 + +// Define if PMR can be read/written at any address inside PM group +`define OR1200_PM_PARTIAL_DECODING + +// Define if reading PMR is allowed +`define OR1200_PM_READREGS + +// Define if unused PMR bits should be zero +`define OR1200_PM_UNUSED_ZERO + + +///////////////////////////////////////////////////// +// +// Debug Unit (DU) +// + +// Define it if you want DU implemented +`define OR1200_DU_IMPLEMENTED + +// +// Define if you want HW Breakpoints +// (if HW breakpoints are not implemented +// only default software trapping is +// possible with l.trap insn - this is +// however already enough for use +// with or32 gdb) +// +//`define OR1200_DU_HWBKPTS + +// Number of DVR/DCR pairs if HW breakpoints enabled +// Comment / uncomment DU_DVRn / DU_DCRn pairs bellow according to this number ! +// DU_DVR0..DU_DVR7 should be uncommented for 8 DU_DVRDCR_PAIRS +`define OR1200_DU_DVRDCR_PAIRS 8 + +// Define if you want trace buffer +// (for now only available for Xilinx Virtex FPGAs) +//`define OR1200_DU_TB_IMPLEMENTED + + +// +// Address offsets of DU registers inside DU group +// +// To not implement a register, doq not define its address +// +`ifdef OR1200_DU_HWBKPTS +`define OR1200_DU_DVR0 11'd0 +`define OR1200_DU_DVR1 11'd1 +`define OR1200_DU_DVR2 11'd2 +`define OR1200_DU_DVR3 11'd3 +`define OR1200_DU_DVR4 11'd4 +`define OR1200_DU_DVR5 11'd5 +`define OR1200_DU_DVR6 11'd6 +`define OR1200_DU_DVR7 11'd7 +`define OR1200_DU_DCR0 11'd8 +`define OR1200_DU_DCR1 11'd9 +`define OR1200_DU_DCR2 11'd10 +`define OR1200_DU_DCR3 11'd11 +`define OR1200_DU_DCR4 11'd12 +`define OR1200_DU_DCR5 11'd13 +`define OR1200_DU_DCR6 11'd14 +`define OR1200_DU_DCR7 11'd15 +`endif +`define OR1200_DU_DMR1 11'd16 +`ifdef OR1200_DU_HWBKPTS +`define OR1200_DU_DMR2 11'd17 +`define OR1200_DU_DWCR0 11'd18 +`define OR1200_DU_DWCR1 11'd19 +`endif +`define OR1200_DU_DSR 11'd20 +`define OR1200_DU_DRR 11'd21 +`ifdef OR1200_DU_TB_IMPLEMENTED +`define OR1200_DU_TBADR 11'h0ff +`define OR1200_DU_TBIA 11'h1?? +`define OR1200_DU_TBIM 11'h2?? +`define OR1200_DU_TBAR 11'h3?? +`define OR1200_DU_TBTS 11'h4?? +`endif + +// Position of offset bits inside SPR address +`define OR1200_DUOFS_BITS 10:0 + +// DCR bits +`define OR1200_DU_DCR_DP 0 +`define OR1200_DU_DCR_CC 3:1 +`define OR1200_DU_DCR_SC 4 +`define OR1200_DU_DCR_CT 7:5 + +// DMR1 bits +`define OR1200_DU_DMR1_CW0 1:0 +`define OR1200_DU_DMR1_CW1 3:2 +`define OR1200_DU_DMR1_CW2 5:4 +`define OR1200_DU_DMR1_CW3 7:6 +`define OR1200_DU_DMR1_CW4 9:8 +`define OR1200_DU_DMR1_CW5 11:10 +`define OR1200_DU_DMR1_CW6 13:12 +`define OR1200_DU_DMR1_CW7 15:14 +`define OR1200_DU_DMR1_CW8 17:16 +`define OR1200_DU_DMR1_CW9 19:18 +`define OR1200_DU_DMR1_CW10 21:20 +`define OR1200_DU_DMR1_ST 22 +`define OR1200_DU_DMR1_BT 23 +`define OR1200_DU_DMR1_DXFW 24 +`define OR1200_DU_DMR1_ETE 25 + +// DMR2 bits +`define OR1200_DU_DMR2_WCE0 0 +`define OR1200_DU_DMR2_WCE1 1 +`define OR1200_DU_DMR2_AWTC 12:2 +`define OR1200_DU_DMR2_WGB 23:13 + +// DWCR bits +`define OR1200_DU_DWCR_COUNT 15:0 +`define OR1200_DU_DWCR_MATCH 31:16 + +// DSR bits +`define OR1200_DU_DSR_WIDTH 14 +`define OR1200_DU_DSR_RSTE 0 +`define OR1200_DU_DSR_BUSEE 1 +`define OR1200_DU_DSR_DPFE 2 +`define OR1200_DU_DSR_IPFE 3 +`define OR1200_DU_DSR_TTE 4 +`define OR1200_DU_DSR_AE 5 +`define OR1200_DU_DSR_IIE 6 +`define OR1200_DU_DSR_IE 7 +`define OR1200_DU_DSR_DME 8 +`define OR1200_DU_DSR_IME 9 +`define OR1200_DU_DSR_RE 10 +`define OR1200_DU_DSR_SCE 11 +`define OR1200_DU_DSR_FPE 12 +`define OR1200_DU_DSR_TE 13 + +// DRR bits +`define OR1200_DU_DRR_RSTE 0 +`define OR1200_DU_DRR_BUSEE 1 +`define OR1200_DU_DRR_DPFE 2 +`define OR1200_DU_DRR_IPFE 3 +`define OR1200_DU_DRR_TTE 4 +`define OR1200_DU_DRR_AE 5 +`define OR1200_DU_DRR_IIE 6 +`define OR1200_DU_DRR_IE 7 +`define OR1200_DU_DRR_DME 8 +`define OR1200_DU_DRR_IME 9 +`define OR1200_DU_DRR_RE 10 +`define OR1200_DU_DRR_SCE 11 +`define OR1200_DU_DRR_FPE 12 +`define OR1200_DU_DRR_TE 13 + +// Define if reading DU regs is allowed +`define OR1200_DU_READREGS + +// Define if unused DU registers bits should be zero +`define OR1200_DU_UNUSED_ZERO + +// Define if IF/LSU status is not needed by devel i/f +`define OR1200_DU_STATUS_UNIMPLEMENTED + +///////////////////////////////////////////////////// +// +// Programmable Interrupt Controller (PIC) +// + +// Define it if you want PIC implemented +`define OR1200_PIC_IMPLEMENTED + +// Define number of interrupt inputs (2-31) +`define OR1200_PIC_INTS 20 + +// Address offsets of PIC registers inside PIC group +`define OR1200_PIC_OFS_PICMR 2'd0 +`define OR1200_PIC_OFS_PICSR 2'd2 + +// Position of offset bits inside SPR address +`define OR1200_PICOFS_BITS 1:0 + +// Define if you want these PIC registers to be implemented +`define OR1200_PIC_PICMR +`define OR1200_PIC_PICSR + +// Define if reading PIC registers is allowed +`define OR1200_PIC_READREGS + +// Define if unused PIC register bits should be zero +`define OR1200_PIC_UNUSED_ZERO + + +///////////////////////////////////////////////////// +// +// Tick Timer (TT) +// + +// Define it if you want TT implemented +`define OR1200_TT_IMPLEMENTED + +// Address offsets of TT registers inside TT group +`define OR1200_TT_OFS_TTMR 1'd0 +`define OR1200_TT_OFS_TTCR 1'd1 + +// Position of offset bits inside SPR group +`define OR1200_TTOFS_BITS 0 + +// Define if you want these TT registers to be implemented +`define OR1200_TT_TTMR +`define OR1200_TT_TTCR + +// TTMR bits +`define OR1200_TT_TTMR_TP 27:0 +`define OR1200_TT_TTMR_IP 28 +`define OR1200_TT_TTMR_IE 29 +`define OR1200_TT_TTMR_M 31:30 + +// Define if reading TT registers is allowed +`define OR1200_TT_READREGS + + +////////////////////////////////////////////// +// +// MAC +// +`define OR1200_MAC_ADDR 0 // MACLO 0xxxxxxxx1, MACHI 0xxxxxxxx0 +`define OR1200_MAC_SPR_WE // Define if MACLO/MACHI are SPR writable + +// +// Shift {MACHI,MACLO} into destination register when executing l.macrc +// +// According to architecture manual there is no shift, so default value is 0. +// However the implementation has deviated in this from the arch manual and had +// hard coded shift by 28 bits which is a useful optimization for MP3 decoding +// (if using libmad fixed point library). Shifts are no longer default setup, +// but if you need to remain backward compatible, define your shift bits, which +// were normally +// dest_GPR = {MACHI,MACLO}[59:28] +`define OR1200_MAC_SHIFTBY 0 // 0 = According to arch manual, 28 = obsolete backward compatibility + + +////////////////////////////////////////////// +// +// Data MMU (DMMU) +// + +// +// Address that selects between TLB TR and MR +// +`define OR1200_DTLB_TM_ADDR 7 + +// +// DTLBMR fields +// +`define OR1200_DTLBMR_V_BITS 0 +`define OR1200_DTLBMR_CID_BITS 4:1 +`define OR1200_DTLBMR_RES_BITS 11:5 +`define OR1200_DTLBMR_VPN_BITS 31:13 + +// +// DTLBTR fields +// +`define OR1200_DTLBTR_CC_BITS 0 +`define OR1200_DTLBTR_CI_BITS 1 +`define OR1200_DTLBTR_WBC_BITS 2 +`define OR1200_DTLBTR_WOM_BITS 3 +`define OR1200_DTLBTR_A_BITS 4 +`define OR1200_DTLBTR_D_BITS 5 +`define OR1200_DTLBTR_URE_BITS 6 +`define OR1200_DTLBTR_UWE_BITS 7 +`define OR1200_DTLBTR_SRE_BITS 8 +`define OR1200_DTLBTR_SWE_BITS 9 +`define OR1200_DTLBTR_RES_BITS 11:10 +`define OR1200_DTLBTR_PPN_BITS 31:13 + +// +// DTLB configuration +// +`define OR1200_DMMU_PS 13 // 13 for 8KB page size +`define OR1200_DTLB_INDXW 6 // 6 for 64 entry DTLB 7 for 128 entries +`define OR1200_DTLB_INDXL `OR1200_DMMU_PS // 13 13 +`define OR1200_DTLB_INDXH `OR1200_DMMU_PS+`OR1200_DTLB_INDXW-1 // 18 19 +`define OR1200_DTLB_INDX `OR1200_DTLB_INDXH:`OR1200_DTLB_INDXL // 18:13 19:13 +`define OR1200_DTLB_TAGW 32-`OR1200_DTLB_INDXW-`OR1200_DMMU_PS // 13 12 +`define OR1200_DTLB_TAGL `OR1200_DTLB_INDXH+1 // 19 20 +`define OR1200_DTLB_TAG 31:`OR1200_DTLB_TAGL // 31:19 31:20 +`define OR1200_DTLBMRW `OR1200_DTLB_TAGW+1 // +1 because of V bit +`define OR1200_DTLBTRW 32-`OR1200_DMMU_PS+5 // +5 because of protection bits and CI + +// +// Cache inhibit while DMMU is not enabled/implemented +// +// cache inhibited 0GB-4GB 1'b1 +// cache inhibited 0GB-2GB !dcpu_adr_i[31] +// cache inhibited 0GB-1GB 2GB-3GB !dcpu_adr_i[30] +// cache inhibited 1GB-2GB 3GB-4GB dcpu_adr_i[30] +// cache inhibited 2GB-4GB (default) dcpu_adr_i[31] +// cached 0GB-4GB 1'b0 +// +`define OR1200_DMMU_CI dcpu_adr_i[31] + + +////////////////////////////////////////////// +// +// Insn MMU (IMMU) +// + +// +// Address that selects between TLB TR and MR +// +`define OR1200_ITLB_TM_ADDR 7 + +// +// ITLBMR fields +// +`define OR1200_ITLBMR_V_BITS 0 +`define OR1200_ITLBMR_CID_BITS 4:1 +`define OR1200_ITLBMR_RES_BITS 11:5 +`define OR1200_ITLBMR_VPN_BITS 31:13 + +// +// ITLBTR fields +// +`define OR1200_ITLBTR_CC_BITS 0 +`define OR1200_ITLBTR_CI_BITS 1 +`define OR1200_ITLBTR_WBC_BITS 2 +`define OR1200_ITLBTR_WOM_BITS 3 +`define OR1200_ITLBTR_A_BITS 4 +`define OR1200_ITLBTR_D_BITS 5 +`define OR1200_ITLBTR_SXE_BITS 6 +`define OR1200_ITLBTR_UXE_BITS 7 +`define OR1200_ITLBTR_RES_BITS 11:8 +`define OR1200_ITLBTR_PPN_BITS 31:13 + +// +// ITLB configuration +// +`define OR1200_IMMU_PS 13 // 13 for 8KB page size +`define OR1200_ITLB_INDXW 6 // 6 for 64 entry ITLB 7 for 128 entries +`define OR1200_ITLB_INDXL `OR1200_IMMU_PS // 13 13 +`define OR1200_ITLB_INDXH `OR1200_IMMU_PS+`OR1200_ITLB_INDXW-1 // 18 19 +`define OR1200_ITLB_INDX `OR1200_ITLB_INDXH:`OR1200_ITLB_INDXL // 18:13 19:13 +`define OR1200_ITLB_TAGW 32-`OR1200_ITLB_INDXW-`OR1200_IMMU_PS // 13 12 +`define OR1200_ITLB_TAGL `OR1200_ITLB_INDXH+1 // 19 20 +`define OR1200_ITLB_TAG 31:`OR1200_ITLB_TAGL // 31:19 31:20 +`define OR1200_ITLBMRW `OR1200_ITLB_TAGW+1 // +1 because of V bit +`define OR1200_ITLBTRW 32-`OR1200_IMMU_PS+3 // +3 because of protection bits and CI + +// +// Cache inhibit while IMMU is not enabled/implemented +// Note: all combinations that use icpu_adr_i cause async loop +// +// cache inhibited 0GB-4GB 1'b1 +// cache inhibited 0GB-2GB !icpu_adr_i[31] +// cache inhibited 0GB-1GB 2GB-3GB !icpu_adr_i[30] +// cache inhibited 1GB-2GB 3GB-4GB icpu_adr_i[30] +// cache inhibited 2GB-4GB (default) icpu_adr_i[31] +// cached 0GB-4GB 1'b0 +// +`define OR1200_IMMU_CI 1'b0 + + +///////////////////////////////////////////////// +// +// Insn cache (IC) +// + +// 4 for 16 byte line, 5 for 32 byte lines. +`ifdef OR1200_IC_1W_32KB + `define OR1200_ICLS 5 +`else + `define OR1200_ICLS 4 +`endif + +// +// IC configurations +// +`ifdef OR1200_IC_1W_512B +`define OR1200_ICSIZE 9 // 512 +`define OR1200_ICINDX `OR1200_ICSIZE-2 // 7 +`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 8 +`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 9 +`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 5 +`define OR1200_ICTAG_W 24 +`endif +`ifdef OR1200_IC_1W_4KB +`define OR1200_ICSIZE 12 // 4096 +`define OR1200_ICINDX `OR1200_ICSIZE-2 // 10 +`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 11 +`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 12 +`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 8 +`define OR1200_ICTAG_W 21 +`endif +`ifdef OR1200_IC_1W_8KB +`define OR1200_ICSIZE 13 // 8192 +`define OR1200_ICINDX `OR1200_ICSIZE-2 // 11 +`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 12 +`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 13 +`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 9 +`define OR1200_ICTAG_W 20 +`endif +`ifdef OR1200_IC_1W_16KB +`define OR1200_ICSIZE 14 // 16384 +`define OR1200_ICINDX `OR1200_ICSIZE-2 // 12 +`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 13 +`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 14 +`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 10 +`define OR1200_ICTAG_W 19 +`endif +`ifdef OR1200_IC_1W_32KB +`define OR1200_ICSIZE 15 // 32768 +`define OR1200_ICINDX `OR1200_ICSIZE-2 // 13 +`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 14 +`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 14 +`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 10 +`define OR1200_ICTAG_W 18 +`endif + + +///////////////////////////////////////////////// +// +// Data cache (DC) +// + +// 4 for 16 bytes, 5 for 32 bytes +`ifdef OR1200_DC_1W_32KB + `define OR1200_DCLS 5 +`else + `define OR1200_DCLS 4 +`endif + +// Define to enable default behavior of cache as write through +// Turning this off enabled write back statergy +// +`define OR1200_DC_WRITETHROUGH + +// Define to enable stores from the stack not doing writethrough. +// EXPERIMENTAL +//`define OR1200_DC_NOSTACKWRITETHROUGH + +// Data cache SPR definitions +`define OR1200_SPRGRP_DC_ADR_WIDTH 3 +// Data cache group SPR addresses +`define OR1200_SPRGRP_DC_DCCR 3'd0 // Not implemented +`define OR1200_SPRGRP_DC_DCBPR 3'd1 // Not implemented +`define OR1200_SPRGRP_DC_DCBFR 3'd2 +`define OR1200_SPRGRP_DC_DCBIR 3'd3 +`define OR1200_SPRGRP_DC_DCBWR 3'd4 // Not implemented +`define OR1200_SPRGRP_DC_DCBLR 3'd5 // Not implemented + +// +// DC configurations +// +`ifdef OR1200_DC_1W_4KB +`define OR1200_DCSIZE 12 // 4096 +`define OR1200_DCINDX `OR1200_DCSIZE-2 // 10 +`define OR1200_DCINDXH `OR1200_DCSIZE-1 // 11 +`define OR1200_DCTAGL `OR1200_DCINDXH+1 // 12 +`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 8 +`define OR1200_DCTAG_W 21 +`endif +`ifdef OR1200_DC_1W_8KB +`define OR1200_DCSIZE 13 // 8192 +`define OR1200_DCINDX `OR1200_DCSIZE-2 // 11 +`define OR1200_DCINDXH `OR1200_DCSIZE-1 // 12 +`define OR1200_DCTAGL `OR1200_DCINDXH+1 // 13 +`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 9 +`define OR1200_DCTAG_W 20 +`endif +`ifdef OR1200_DC_1W_16KB +`define OR1200_DCSIZE 14 // 16384 +`define OR1200_DCINDX `OR1200_DCSIZE-2 // 12 +`define OR1200_DCINDXH `OR1200_DCSIZE-1 // 13 +`define OR1200_DCTAGL `OR1200_DCINDXH+1 // 14 +`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 10 +`define OR1200_DCTAG_W 19 +`endif +`ifdef OR1200_DC_1W_32KB +`define OR1200_DCSIZE 15 // 32768 +`define OR1200_DCINDX `OR1200_DCSIZE-2 // 13 +`define OR1200_DCINDXH `OR1200_DCSIZE-1 // 14 +`define OR1200_DCTAGL `OR1200_DCINDXH+1 // 15 +`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 10 +`define OR1200_DCTAG_W 18 +`endif + + +///////////////////////////////////////////////// +// +// Store buffer (SB) +// + +// +// Store buffer +// +// It will improve performance by "caching" CPU stores +// using store buffer. This is most important for function +// prologues because DC can only work in write though mode +// and all stores would have to complete external WB writes +// to memory. +// Store buffer is between DC and data BIU. +// All stores will be stored into store buffer and immediately +// completed by the CPU, even though actual external writes +// will be performed later. As a consequence store buffer masks +// all data bus errors related to stores (data bus errors +// related to loads are delivered normally). +// All pending CPU loads will wait until store buffer is empty to +// ensure strict memory model. Right now this is necessary because +// we don't make destinction between cached and cache inhibited +// address space, so we simply empty store buffer until loads +// can begin. +// +// It makes design a bit bigger, depending what is the number of +// entries in SB FIFO. Number of entries can be changed further +// down. +// +//`define OR1200_SB_IMPLEMENTED + +// +// Number of store buffer entries +// +// Verified number of entries are 4 and 8 entries +// (2 and 3 for OR1200_SB_LOG). OR1200_SB_ENTRIES must +// always match 2**OR1200_SB_LOG. +// To disable store buffer, undefine +// OR1200_SB_IMPLEMENTED. +// +`define OR1200_SB_LOG 2 // 2 or 3 +`define OR1200_SB_ENTRIES 4 // 4 or 8 + + +///////////////////////////////////////////////// +// +// Quick Embedded Memory (QMEM) +// + +// +// Quick Embedded Memory +// +// Instantiation of dedicated insn/data memory (RAM or ROM). +// Insn fetch has effective throughput 1insn / clock cycle. +// Data load takes two clock cycles / access, data store +// takes 1 clock cycle / access (if there is no insn fetch)). +// Memory instantiation is shared between insn and data, +// meaning if insn fetch are performed, data load/store +// performance will be lower. +// +// Main reason for QMEM is to put some time critical functions +// into this memory and to have predictable and fast access +// to these functions. (soft fpu, context switch, exception +// handlers, stack, etc) +// +// It makes design a bit bigger and slower. QMEM sits behind +// IMMU/DMMU so all addresses are physical (so the MMUs can be +// used with QMEM and QMEM is seen by the CPU just like any other +// memory in the system). IC/DC are sitting behind QMEM so the +// whole design timing might be worse with QMEM implemented. +// +//`define OR1200_QMEM_IMPLEMENTED + +// +// Base address and mask of QMEM +// +// Base address defines first address of QMEM. Mask defines +// QMEM range in address space. Actual size of QMEM is however +// determined with instantiated RAM/ROM. However bigger +// mask will reserve more address space for QMEM, but also +// make design faster, while more tight mask will take +// less address space but also make design slower. If +// instantiated RAM/ROM is smaller than space reserved with +// the mask, instatiated RAM/ROM will also be shadowed +// at higher addresses in reserved space. +// +`define OR1200_QMEM_IADDR 32'h0080_0000 +`define OR1200_QMEM_IMASK 32'hfff0_0000 // Max QMEM size 1MB +`define OR1200_QMEM_DADDR 32'h0080_0000 +`define OR1200_QMEM_DMASK 32'hfff0_0000 // Max QMEM size 1MB + +// +// QMEM interface byte-select capability +// +// To enable qmem_sel* ports, define this macro. +// +//`define OR1200_QMEM_BSEL + +// +// QMEM interface acknowledge +// +// To enable qmem_ack port, define this macro. +// +//`define OR1200_QMEM_ACK + +///////////////////////////////////////////////////// +// +// VR, UPR and Configuration Registers +// +// +// VR, UPR and configuration registers are optional. If +// implemented, operating system can automatically figure +// out how to use the processor because it knows +// what units are available in the processor and how they +// are configured. +// +// This section must be last in or1200_defines.v file so +// that all units are already configured and thus +// configuration registers are properly set. +// + +// Define if you want configuration registers implemented +`define OR1200_CFGR_IMPLEMENTED + +// Define if you want full address decode inside SYS group +`define OR1200_SYS_FULL_DECODE + +// Offsets of VR, UPR and CFGR registers +`define OR1200_SPRGRP_SYS_VR 4'h0 +`define OR1200_SPRGRP_SYS_UPR 4'h1 +`define OR1200_SPRGRP_SYS_CPUCFGR 4'h2 +`define OR1200_SPRGRP_SYS_DMMUCFGR 4'h3 +`define OR1200_SPRGRP_SYS_IMMUCFGR 4'h4 +`define OR1200_SPRGRP_SYS_DCCFGR 4'h5 +`define OR1200_SPRGRP_SYS_ICCFGR 4'h6 +`define OR1200_SPRGRP_SYS_DCFGR 4'h7 + +// VR fields +`define OR1200_VR_REV_BITS 5:0 +`define OR1200_VR_RES1_BITS 15:6 +`define OR1200_VR_CFG_BITS 23:16 +`define OR1200_VR_VER_BITS 31:24 + +// VR values +`define OR1200_VR_REV 6'h08 +`define OR1200_VR_RES1 10'h000 +`define OR1200_VR_CFG 8'h00 +`define OR1200_VR_VER 8'h12 + +// UPR fields +`define OR1200_UPR_UP_BITS 0 +`define OR1200_UPR_DCP_BITS 1 +`define OR1200_UPR_ICP_BITS 2 +`define OR1200_UPR_DMP_BITS 3 +`define OR1200_UPR_IMP_BITS 4 +`define OR1200_UPR_MP_BITS 5 +`define OR1200_UPR_DUP_BITS 6 +`define OR1200_UPR_PCUP_BITS 7 +`define OR1200_UPR_PMP_BITS 8 +`define OR1200_UPR_PICP_BITS 9 +`define OR1200_UPR_TTP_BITS 10 +`define OR1200_UPR_FPP_BITS 11 +`define OR1200_UPR_RES1_BITS 23:12 +`define OR1200_UPR_CUP_BITS 31:24 + +// UPR values +`define OR1200_UPR_UP 1'b1 +`ifdef OR1200_NO_DC +`define OR1200_UPR_DCP 1'b0 +`else +`define OR1200_UPR_DCP 1'b1 +`endif +`ifdef OR1200_NO_IC +`define OR1200_UPR_ICP 1'b0 +`else +`define OR1200_UPR_ICP 1'b1 +`endif +`ifdef OR1200_NO_DMMU +`define OR1200_UPR_DMP 1'b0 +`else +`define OR1200_UPR_DMP 1'b1 +`endif +`ifdef OR1200_NO_IMMU +`define OR1200_UPR_IMP 1'b0 +`else +`define OR1200_UPR_IMP 1'b1 +`endif +`ifdef OR1200_MAC_IMPLEMENTED +`define OR1200_UPR_MP 1'b1 +`else +`define OR1200_UPR_MP 1'b0 +`endif +`ifdef OR1200_DU_IMPLEMENTED +`define OR1200_UPR_DUP 1'b1 +`else +`define OR1200_UPR_DUP 1'b0 +`endif +`define OR1200_UPR_PCUP 1'b0 // Performance counters not present +`ifdef OR1200_PM_IMPLEMENTED +`define OR1200_UPR_PMP 1'b1 +`else +`define OR1200_UPR_PMP 1'b0 +`endif +`ifdef OR1200_PIC_IMPLEMENTED +`define OR1200_UPR_PICP 1'b1 +`else +`define OR1200_UPR_PICP 1'b0 +`endif +`ifdef OR1200_TT_IMPLEMENTED +`define OR1200_UPR_TTP 1'b1 +`else +`define OR1200_UPR_TTP 1'b0 +`endif +`ifdef OR1200_FPU_IMPLEMENTED +`define OR1200_UPR_FPP 1'b1 +`else +`define OR1200_UPR_FPP 1'b0 +`endif +`define OR1200_UPR_RES1 12'h000 +`define OR1200_UPR_CUP 8'h00 + +// CPUCFGR fields +`define OR1200_CPUCFGR_NSGF_BITS 3:0 +`define OR1200_CPUCFGR_HGF_BITS 4 +`define OR1200_CPUCFGR_OB32S_BITS 5 +`define OR1200_CPUCFGR_OB64S_BITS 6 +`define OR1200_CPUCFGR_OF32S_BITS 7 +`define OR1200_CPUCFGR_OF64S_BITS 8 +`define OR1200_CPUCFGR_OV64S_BITS 9 +`define OR1200_CPUCFGR_RES1_BITS 31:10 + +// CPUCFGR values +`define OR1200_CPUCFGR_NSGF 4'h0 +`ifdef OR1200_RFRAM_16REG + `define OR1200_CPUCFGR_HGF 1'b1 +`else + `define OR1200_CPUCFGR_HGF 1'b0 +`endif +`define OR1200_CPUCFGR_OB32S 1'b1 +`define OR1200_CPUCFGR_OB64S 1'b0 +`ifdef OR1200_FPU_IMPLEMENTED + `define OR1200_CPUCFGR_OF32S 1'b1 +`else + `define OR1200_CPUCFGR_OF32S 1'b0 +`endif + +`define OR1200_CPUCFGR_OF64S 1'b0 +`define OR1200_CPUCFGR_OV64S 1'b0 +`define OR1200_CPUCFGR_RES1 22'h000000 + +// DMMUCFGR fields +`define OR1200_DMMUCFGR_NTW_BITS 1:0 +`define OR1200_DMMUCFGR_NTS_BITS 4:2 +`define OR1200_DMMUCFGR_NAE_BITS 7:5 +`define OR1200_DMMUCFGR_CRI_BITS 8 +`define OR1200_DMMUCFGR_PRI_BITS 9 +`define OR1200_DMMUCFGR_TEIRI_BITS 10 +`define OR1200_DMMUCFGR_HTR_BITS 11 +`define OR1200_DMMUCFGR_RES1_BITS 31:12 + +// DMMUCFGR values +`ifdef OR1200_NO_DMMU +`define OR1200_DMMUCFGR_NTW 2'h0 // Irrelevant +`define OR1200_DMMUCFGR_NTS 3'h0 // Irrelevant +`define OR1200_DMMUCFGR_NAE 3'h0 // Irrelevant +`define OR1200_DMMUCFGR_CRI 1'b0 // Irrelevant +`define OR1200_DMMUCFGR_PRI 1'b0 // Irrelevant +`define OR1200_DMMUCFGR_TEIRI 1'b0 // Irrelevant +`define OR1200_DMMUCFGR_HTR 1'b0 // Irrelevant +`define OR1200_DMMUCFGR_RES1 20'h00000 +`else +`define OR1200_DMMUCFGR_NTW 2'h0 // 1 TLB way +`define OR1200_DMMUCFGR_NTS 3'h`OR1200_DTLB_INDXW // Num TLB sets +`define OR1200_DMMUCFGR_NAE 3'h0 // No ATB entries +`define OR1200_DMMUCFGR_CRI 1'b0 // No control register +`define OR1200_DMMUCFGR_PRI 1'b0 // No protection reg +`define OR1200_DMMUCFGR_TEIRI 1'b1 // TLB entry inv reg impl. +`define OR1200_DMMUCFGR_HTR 1'b0 // No HW TLB reload +`define OR1200_DMMUCFGR_RES1 20'h00000 +`endif + +// IMMUCFGR fields +`define OR1200_IMMUCFGR_NTW_BITS 1:0 +`define OR1200_IMMUCFGR_NTS_BITS 4:2 +`define OR1200_IMMUCFGR_NAE_BITS 7:5 +`define OR1200_IMMUCFGR_CRI_BITS 8 +`define OR1200_IMMUCFGR_PRI_BITS 9 +`define OR1200_IMMUCFGR_TEIRI_BITS 10 +`define OR1200_IMMUCFGR_HTR_BITS 11 +`define OR1200_IMMUCFGR_RES1_BITS 31:12 + +// IMMUCFGR values +`ifdef OR1200_NO_IMMU +`define OR1200_IMMUCFGR_NTW 2'h0 // Irrelevant +`define OR1200_IMMUCFGR_NTS 3'h0 // Irrelevant +`define OR1200_IMMUCFGR_NAE 3'h0 // Irrelevant +`define OR1200_IMMUCFGR_CRI 1'b0 // Irrelevant +`define OR1200_IMMUCFGR_PRI 1'b0 // Irrelevant +`define OR1200_IMMUCFGR_TEIRI 1'b0 // Irrelevant +`define OR1200_IMMUCFGR_HTR 1'b0 // Irrelevant +`define OR1200_IMMUCFGR_RES1 20'h00000 +`else +`define OR1200_IMMUCFGR_NTW 2'h0 // 1 TLB way +`define OR1200_IMMUCFGR_NTS 3'h`OR1200_ITLB_INDXW // Num TLB sets +`define OR1200_IMMUCFGR_NAE 3'h0 // No ATB entry +`define OR1200_IMMUCFGR_CRI 1'b0 // No control reg +`define OR1200_IMMUCFGR_PRI 1'b0 // No protection reg +`define OR1200_IMMUCFGR_TEIRI 1'b1 // TLB entry inv reg impl +`define OR1200_IMMUCFGR_HTR 1'b0 // No HW TLB reload +`define OR1200_IMMUCFGR_RES1 20'h00000 +`endif + +// DCCFGR fields +`define OR1200_DCCFGR_NCW_BITS 2:0 +`define OR1200_DCCFGR_NCS_BITS 6:3 +`define OR1200_DCCFGR_CBS_BITS 7 +`define OR1200_DCCFGR_CWS_BITS 8 +`define OR1200_DCCFGR_CCRI_BITS 9 +`define OR1200_DCCFGR_CBIRI_BITS 10 +`define OR1200_DCCFGR_CBPRI_BITS 11 +`define OR1200_DCCFGR_CBLRI_BITS 12 +`define OR1200_DCCFGR_CBFRI_BITS 13 +`define OR1200_DCCFGR_CBWBRI_BITS 14 +`define OR1200_DCCFGR_RES1_BITS 31:15 + +// DCCFGR values +`ifdef OR1200_NO_DC +`define OR1200_DCCFGR_NCW 3'h0 // Irrelevant +`define OR1200_DCCFGR_NCS 4'h0 // Irrelevant +`define OR1200_DCCFGR_CBS 1'b0 // Irrelevant +`define OR1200_DCCFGR_CWS 1'b0 // Irrelevant +`define OR1200_DCCFGR_CCRI 1'b0 // Irrelevant +`define OR1200_DCCFGR_CBIRI 1'b0 // Irrelevant +`define OR1200_DCCFGR_CBPRI 1'b0 // Irrelevant +`define OR1200_DCCFGR_CBLRI 1'b0 // Irrelevant +`define OR1200_DCCFGR_CBFRI 1'b0 // Irrelevant +`define OR1200_DCCFGR_CBWBRI 1'b0 // Irrelevant +`define OR1200_DCCFGR_RES1 17'h00000 +`else +`define OR1200_DCCFGR_NCW 3'h0 // 1 cache way +`define OR1200_DCCFGR_NCS (`OR1200_DCTAG) // Num cache sets +`define OR1200_DCCFGR_CBS `OR1200_DCLS==4 ? 1'b0 : 1'b1 // 16 byte cache block +`ifdef OR1200_DC_WRITETHROUGH + `define OR1200_DCCFGR_CWS 1'b0 // Write-through strategy +`else + `define OR1200_DCCFGR_CWS 1'b1 // Write-back strategy +`endif +`define OR1200_DCCFGR_CCRI 1'b1 // Cache control reg impl. +`define OR1200_DCCFGR_CBIRI 1'b1 // Cache block inv reg impl. +`define OR1200_DCCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl. +`define OR1200_DCCFGR_CBLRI 1'b0 // Cache block lock reg not impl. +`define OR1200_DCCFGR_CBFRI 1'b1 // Cache block flush reg impl. +`ifdef OR1200_DC_WRITETHROUGH + `define OR1200_DCCFGR_CBWBRI 1'b0 // Cache block WB reg not impl. +`else + `define OR1200_DCCFGR_CBWBRI 1'b1 // Cache block WB reg impl. +`endif +`define OR1200_DCCFGR_RES1 17'h00000 +`endif + +// ICCFGR fields +`define OR1200_ICCFGR_NCW_BITS 2:0 +`define OR1200_ICCFGR_NCS_BITS 6:3 +`define OR1200_ICCFGR_CBS_BITS 7 +`define OR1200_ICCFGR_CWS_BITS 8 +`define OR1200_ICCFGR_CCRI_BITS 9 +`define OR1200_ICCFGR_CBIRI_BITS 10 +`define OR1200_ICCFGR_CBPRI_BITS 11 +`define OR1200_ICCFGR_CBLRI_BITS 12 +`define OR1200_ICCFGR_CBFRI_BITS 13 +`define OR1200_ICCFGR_CBWBRI_BITS 14 +`define OR1200_ICCFGR_RES1_BITS 31:15 + +// ICCFGR values +`ifdef OR1200_NO_IC +`define OR1200_ICCFGR_NCW 3'h0 // Irrelevant +`define OR1200_ICCFGR_NCS 4'h0 // Irrelevant +`define OR1200_ICCFGR_CBS 1'b0 // Irrelevant +`define OR1200_ICCFGR_CWS 1'b0 // Irrelevant +`define OR1200_ICCFGR_CCRI 1'b0 // Irrelevant +`define OR1200_ICCFGR_CBIRI 1'b0 // Irrelevant +`define OR1200_ICCFGR_CBPRI 1'b0 // Irrelevant +`define OR1200_ICCFGR_CBLRI 1'b0 // Irrelevant +`define OR1200_ICCFGR_CBFRI 1'b0 // Irrelevant +`define OR1200_ICCFGR_CBWBRI 1'b0 // Irrelevant +`define OR1200_ICCFGR_RES1 17'h00000 +`else +`define OR1200_ICCFGR_NCW 3'h0 // 1 cache way +`define OR1200_ICCFGR_NCS (`OR1200_ICTAG) // Num cache sets +`define OR1200_ICCFGR_CBS `OR1200_ICLS==4 ? 1'b0: 1'b1 // 16 byte cache block +`define OR1200_ICCFGR_CWS 1'b0 // Irrelevant +`define OR1200_ICCFGR_CCRI 1'b1 // Cache control reg impl. +`define OR1200_ICCFGR_CBIRI 1'b1 // Cache block inv reg impl. +`define OR1200_ICCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl. +`define OR1200_ICCFGR_CBLRI 1'b0 // Cache block lock reg not impl. +`define OR1200_ICCFGR_CBFRI 1'b1 // Cache block flush reg impl. +`define OR1200_ICCFGR_CBWBRI 1'b0 // Irrelevant +`define OR1200_ICCFGR_RES1 17'h00000 +`endif + +// DCFGR fields +`define OR1200_DCFGR_NDP_BITS 3:0 +`define OR1200_DCFGR_WPCI_BITS 4 +`define OR1200_DCFGR_RES1_BITS 31:5 + +// DCFGR values +`ifdef OR1200_DU_HWBKPTS +`define OR1200_DCFGR_NDP 4'h`OR1200_DU_DVRDCR_PAIRS // # of DVR/DCR pairs +`ifdef OR1200_DU_DWCR0 +`define OR1200_DCFGR_WPCI 1'b1 +`else +`define OR1200_DCFGR_WPCI 1'b0 // WP counters not impl. +`endif +`else +`define OR1200_DCFGR_NDP 4'h0 // Zero DVR/DCR pairs +`define OR1200_DCFGR_WPCI 1'b0 // WP counters not impl. +`endif +`define OR1200_DCFGR_RES1 27'd0 + +/////////////////////////////////////////////////////////////////////////////// +// Boot Address Selection // +// // +// Allows a definable boot address, potentially different to the usual reset // +// vector to allow for power-on code to be run, if desired. // +// // +// OR1200_BOOT_ADR should be the 32-bit address of the boot location // +// OR1200_BOOT_PCREG_DEFAULT should be ((OR1200_BOOT_ADR-4)>>2) // +// // +// For default reset behavior uncomment the settings under the "Boot 0x100" // +// comment below. // +// // +/////////////////////////////////////////////////////////////////////////////// +// Boot from 0xf0000100 +//`define OR1200_BOOT_PCREG_DEFAULT 30'h3c00003f +//`define OR1200_BOOT_ADR 32'hf0000100 +// Boot from 0x100 + `define OR1200_BOOT_PCREG_DEFAULT 30'h0000003f + `define OR1200_BOOT_ADR 32'h00000100 Index: generic/ft/rtl/verilog/include/orpsoc-defines.v =================================================================== --- generic/ft/rtl/verilog/include/orpsoc-defines.v (nonexistent) +++ generic/ft/rtl/verilog/include/orpsoc-defines.v (revision 483) @@ -0,0 +1,70 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// orpsoc-defines //// +//// //// +//// Top level ORPSoC defines file //// +//// //// +//// Included in toplevel and testbench //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG //// +//// //// +//// 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, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +// Define board clock - main system clock period +// 20ns period = 50MHz freq. +`define BOARD_CLOCK_PERIOD 20 + +// Included modules: define to include +//`define JTAG_DEBUG +//`define UART0 +`define RAM_WB + +// end of included module defines - keep this comment line here + +// +// Arbiter defines +// + +// Uncomment to register things through arbiter (hopefully quicker design) +// Instruction bus arbiter +//`define ARBITER_IBUS_REGISTERING +`define ARBITER_IBUS_WATCHDOG +// Watchdog timeout: 2^(ARBITER_IBUS_WATCHDOG_TIMER_WIDTH+1) cycles +`define ARBITER_IBUS_WATCHDOG_TIMER_WIDTH 12 + +// Data bus arbiter + +//`define ARBITER_DBUS_REGISTERING +`define ARBITER_DBUS_WATCHDOG +// Watchdog timeout: 2^(ARBITER_DBUS_WATCHDOG_TIMER_WIDTH+1) cycles +`define ARBITER_DBUS_WATCHDOG_TIMER_WIDTH 12 + +// Byte bus (peripheral bus) arbiter +// Don't really need the watchdog here - the databus will pick it up +//`define ARBITER_BYTEBUS_WATCHDOG +// Watchdog timeout: 2^(ARBITER_BYTEBUS_WATCHDOG_TIMER_WIDTH+1) cycles +`define ARBITER_BYTEBUS_WATCHDOG_TIMER_WIDTH 9 + Index: generic/ft/rtl/verilog/include/orpsoc-params.v =================================================================== --- generic/ft/rtl/verilog/include/orpsoc-params.v (nonexistent) +++ generic/ft/rtl/verilog/include/orpsoc-params.v (revision 483) @@ -0,0 +1,124 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// orpsoc-params //// +//// //// +//// Top level ORPSoC parameters file //// +//// //// +//// Included in toplevel and testbench //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG //// +//// //// +//// 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, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +/////////////////////////// +// // +// Peripheral parameters // +// // +/////////////////////////// + +// UART 0 params +parameter wbs_d_uart0_data_width = 8; +parameter uart0_wb_adr = 8'h90; +parameter uart0_data_width = 8; +parameter uart0_addr_width = 3; + +// Parity error unit +parameter peh_wb_adr = 8'he0; + +// ROM +parameter wbs_i_rom0_data_width = 32; +parameter wbs_i_rom0_addr_width = 6; +parameter rom0_wb_adr = 4'hf; + +////////////////////////////////////////////////////// +// // +// Wishbone bus parameters // +// // +////////////////////////////////////////////////////// + +//////////////////////// +// // +// Arbiter parameters // +// // +//////////////////////// + +parameter wb_dw = 32; // Default Wishbone full word width +parameter wb_aw = 32; // Default Wishbone full address width + +/////////////////////////// +// // +// Instruction bus // +// // +/////////////////////////// +parameter ibus_arb_addr_match_width = 4; +// Slave addresses +parameter ibus_arb_slave0_adr = rom0_wb_adr; // ROM +parameter ibus_arb_slave1_adr = 4'h0; // Main memory + +/////////////////////////// +// // +// Data bus // +// // +/////////////////////////// +// Has auto foward to last slave when no address hits +parameter dbus_arb_wb_addr_match_width = 8; +parameter dbus_arb_wb_num_slaves = 2; +// Slave addresses +parameter dbus_arb_slave0_adr = 4'h0; // Main memory (SDRAM/FPGA SRAM) +parameter dbus_arb_slave1_adr = 8'hxx; // Default slave - address don't care (X) + +/////////////////////////////// +// // +// Byte-wide peripheral bus // +// // +/////////////////////////////// +parameter bbus_arb_wb_addr_match_width = 8; +parameter bbus_arb_wb_num_slaves = 1; // Update this when changing slaves! +// Slave addresses +parameter bbus_arb_slave0_adr = peh_wb_adr; +parameter bbus_arb_slave1_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave2_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave3_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave4_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave5_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave6_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave7_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave8_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave9_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave10_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave11_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave12_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave13_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave14_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave15_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave16_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave17_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave18_adr = 0 /* UNASSIGNED */; +parameter bbus_arb_slave19_adr = 0 /* UNASSIGNED */; + + + + Index: generic/ft/rtl/verilog/orpsoc_top/orpsoc_top.v =================================================================== --- generic/ft/rtl/verilog/orpsoc_top/orpsoc_top.v (nonexistent) +++ generic/ft/rtl/verilog/orpsoc_top/orpsoc_top.v (revision 483) @@ -0,0 +1,828 @@ +////////////////////////////////////////////////////////////////////// +/// //// +/// ORPSoC top level //// +/// //// +/// Define I/O ports, instantiate modules //// +/// //// +/// Julius Baxter, julius@opencores.org //// +/// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG //// +//// //// +//// 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, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "orpsoc-defines.v" +`include "or1200_defines.v" + +module orpsoc_top + ( +`ifdef JTAG_DEBUG + tdo_pad_o, tms_pad_i, tck_pad_i, tdi_pad_i, +`endif + clk_pad_i, + rst_n_pad_i + ); + +`include "orpsoc-params.v" + + input clk_pad_i; + input rst_n_pad_i; + +`ifdef JTAG_DEBUG + output tdo_pad_o; + input tms_pad_i; + input tck_pad_i; + input tdi_pad_i; +`endif + + + //////////////////////////////////////////////////////////////////////// + // + // Clock and reset generation module + // + //////////////////////////////////////////////////////////////////////// + + // + // Wires + // + wire async_rst; + wire wb_clk, wb_rst; + wire dbg_tck; + + + clkgen clkgen0 + ( + + .clk_pad_i (clk_pad_i), + + .async_rst_o (async_rst), + + .wb_clk_o (wb_clk), + .wb_rst_o (wb_rst), + +`ifdef JTAG_DEBUG + .tck_pad_i (tck_pad_i), + .dbg_tck_o (dbg_tck), +`endif + + // Asynchronous active low reset + .rst_n_pad_i (rst_n_pad_i) + ); + + + //////////////////////////////////////////////////////////////////////// + // + // Arbiter + // + //////////////////////////////////////////////////////////////////////// + + // Wire naming convention: + // First: wishbone master or slave (wbm/wbs) + // Second: Which bus it's on instruction or data (i/d) + // Third: Between which module and the arbiter the wires are + // Fourth: Signal name + // Fifth: Direction relative to module (not bus/arbiter!) + // ie. wbm_d_or12_adr_o is address OUT from the or1200 + + // OR1200 instruction bus wires + wire [wb_aw-1:0] wbm_i_or12_adr_o; + wire [wb_dw-1:0] wbm_i_or12_dat_o; + wire [3:0] wbm_i_or12_sel_o; + wire wbm_i_or12_we_o; + wire wbm_i_or12_cyc_o; + wire wbm_i_or12_stb_o; + wire [2:0] wbm_i_or12_cti_o; + wire [1:0] wbm_i_or12_bte_o; + + wire [wb_dw-1:0] wbm_i_or12_dat_i; + wire wbm_i_or12_ack_i; + wire wbm_i_or12_err_i; + wire wbm_i_or12_rty_i; + + // OR1200 data bus wires + wire [wb_aw-1:0] wbm_d_or12_adr_o; + wire [wb_dw-1:0] wbm_d_or12_dat_o; + wire [3:0] wbm_d_or12_sel_o; + wire wbm_d_or12_we_o; + wire wbm_d_or12_cyc_o; + wire wbm_d_or12_stb_o; + wire [2:0] wbm_d_or12_cti_o; + wire [1:0] wbm_d_or12_bte_o; + + wire [wb_dw-1:0] wbm_d_or12_dat_i; + wire wbm_d_or12_ack_i; + wire wbm_d_or12_err_i; + wire wbm_d_or12_rty_i; + + // Debug interface bus wires + wire [wb_aw-1:0] wbm_d_dbg_adr_o; + wire [wb_dw-1:0] wbm_d_dbg_dat_o; + wire [3:0] wbm_d_dbg_sel_o; + wire wbm_d_dbg_we_o; + wire wbm_d_dbg_cyc_o; + wire wbm_d_dbg_stb_o; + wire [2:0] wbm_d_dbg_cti_o; + wire [1:0] wbm_d_dbg_bte_o; + + wire [wb_dw-1:0] wbm_d_dbg_dat_i; + wire wbm_d_dbg_ack_i; + wire wbm_d_dbg_err_i; + wire wbm_d_dbg_rty_i; + + // Byte bus bridge master signals + wire [wb_aw-1:0] wbm_b_d_adr_o; + wire [wb_dw-1:0] wbm_b_d_dat_o; + wire [3:0] wbm_b_d_sel_o; + wire wbm_b_d_we_o; + wire wbm_b_d_cyc_o; + wire wbm_b_d_stb_o; + wire [2:0] wbm_b_d_cti_o; + wire [1:0] wbm_b_d_bte_o; + + wire [wb_dw-1:0] wbm_b_d_dat_i; + wire wbm_b_d_ack_i; + wire wbm_b_d_err_i; + wire wbm_b_d_rty_i; + + // Instruction bus slave wires // + + // rom0 instruction bus wires + wire [31:0] wbs_i_rom0_adr_i; + wire [wbs_i_rom0_data_width-1:0] wbs_i_rom0_dat_i; + wire [3:0] wbs_i_rom0_sel_i; + wire wbs_i_rom0_we_i; + wire wbs_i_rom0_cyc_i; + wire wbs_i_rom0_stb_i; + wire [2:0] wbs_i_rom0_cti_i; + wire [1:0] wbs_i_rom0_bte_i; + wire [wbs_i_rom0_data_width-1:0] wbs_i_rom0_dat_o; + wire wbs_i_rom0_ack_o; + wire wbs_i_rom0_err_o; + wire wbs_i_rom0_rty_o; + + // mc0 instruction bus wires + wire [31:0] wbs_i_mc0_adr_i; + wire [31:0] wbs_i_mc0_dat_i; + wire [3:0] wbs_i_mc0_sel_i; + wire wbs_i_mc0_we_i; + wire wbs_i_mc0_cyc_i; + wire wbs_i_mc0_stb_i; + wire [2:0] wbs_i_mc0_cti_i; + wire [1:0] wbs_i_mc0_bte_i; + wire [31:0] wbs_i_mc0_dat_o; + wire wbs_i_mc0_ack_o; + wire wbs_i_mc0_err_o; + wire wbs_i_mc0_rty_o; + + // Data bus slave wires // + + // mc0 data bus wires + wire [31:0] wbs_d_mc0_adr_i; + wire [31:0] wbs_d_mc0_dat_i; + wire [3:0] wbs_d_mc0_sel_i; + wire wbs_d_mc0_we_i; + wire wbs_d_mc0_cyc_i; + wire wbs_d_mc0_stb_i; + wire [2:0] wbs_d_mc0_cti_i; + wire [1:0] wbs_d_mc0_bte_i; + wire [31:0] wbs_d_mc0_dat_o; + wire wbs_d_mc0_ack_o; + wire wbs_d_mc0_err_o; + wire wbs_d_mc0_rty_o; + + // memory parity error handler wires + wire [31:0] wbs_d_peh_adr_i; + wire [7:0] wbs_d_peh_dat_i; + wire [3:0] wbs_d_peh_sel_i; + wire wbs_d_peh_we_i; + wire wbs_d_peh_cyc_i; + wire wbs_d_peh_stb_i; + wire [2:0] wbs_d_peh_cti_i; + wire [1:0] wbs_d_peh_bte_i; + wire [7:0] wbs_d_peh_dat_o; + wire wbs_d_peh_ack_o; + wire wbs_d_peh_err_o; + wire wbs_d_peh_rty_o; + + // + // Wishbone instruction bus arbiter + // + + arbiter_ibus arbiter_ibus0 + ( + // Instruction Bus Master + // Inputs to arbiter from master + .wbm_adr_o (wbm_i_or12_adr_o), + .wbm_dat_o (wbm_i_or12_dat_o), + .wbm_sel_o (wbm_i_or12_sel_o), + .wbm_we_o (wbm_i_or12_we_o), + .wbm_cyc_o (wbm_i_or12_cyc_o), + .wbm_stb_o (wbm_i_or12_stb_o), + .wbm_cti_o (wbm_i_or12_cti_o), + .wbm_bte_o (wbm_i_or12_bte_o), + // Outputs to master from arbiter + .wbm_dat_i (wbm_i_or12_dat_i), + .wbm_ack_i (wbm_i_or12_ack_i), + .wbm_err_i (wbm_i_or12_err_i), + .wbm_rty_i (wbm_i_or12_rty_i), + + // Slave 0 + // Inputs to slave from arbiter + .wbs0_adr_i (wbs_i_rom0_adr_i), + .wbs0_dat_i (wbs_i_rom0_dat_i), + .wbs0_sel_i (wbs_i_rom0_sel_i), + .wbs0_we_i (wbs_i_rom0_we_i), + .wbs0_cyc_i (wbs_i_rom0_cyc_i), + .wbs0_stb_i (wbs_i_rom0_stb_i), + .wbs0_cti_i (wbs_i_rom0_cti_i), + .wbs0_bte_i (wbs_i_rom0_bte_i), + // Outputs from slave to arbiter + .wbs0_dat_o (wbs_i_rom0_dat_o), + .wbs0_ack_o (wbs_i_rom0_ack_o), + .wbs0_err_o (wbs_i_rom0_err_o), + .wbs0_rty_o (wbs_i_rom0_rty_o), + + // Slave 1 + // Inputs to slave from arbiter + .wbs1_adr_i (wbs_i_mc0_adr_i), + .wbs1_dat_i (wbs_i_mc0_dat_i), + .wbs1_sel_i (wbs_i_mc0_sel_i), + .wbs1_we_i (wbs_i_mc0_we_i), + .wbs1_cyc_i (wbs_i_mc0_cyc_i), + .wbs1_stb_i (wbs_i_mc0_stb_i), + .wbs1_cti_i (wbs_i_mc0_cti_i), + .wbs1_bte_i (wbs_i_mc0_bte_i), + // Outputs from slave to arbiter + .wbs1_dat_o (wbs_i_mc0_dat_o), + .wbs1_ack_o (wbs_i_mc0_ack_o), + .wbs1_err_o (wbs_i_mc0_err_o), + .wbs1_rty_o (wbs_i_mc0_rty_o), + + // Clock, reset inputs + .wb_clk (wb_clk), + .wb_rst (wb_rst)); + + defparam arbiter_ibus0.wb_addr_match_width = ibus_arb_addr_match_width; + + defparam arbiter_ibus0.slave0_adr = ibus_arb_slave0_adr; // ROM + defparam arbiter_ibus0.slave1_adr = ibus_arb_slave1_adr; // Main memory + + // + // Wishbone data bus arbiter + // + + arbiter_dbus arbiter_dbus0 + ( + // Master 0 + // Inputs to arbiter from master + .wbm0_adr_o (wbm_d_or12_adr_o), + .wbm0_dat_o (wbm_d_or12_dat_o), + .wbm0_sel_o (wbm_d_or12_sel_o), + .wbm0_we_o (wbm_d_or12_we_o), + .wbm0_cyc_o (wbm_d_or12_cyc_o), + .wbm0_stb_o (wbm_d_or12_stb_o), + .wbm0_cti_o (wbm_d_or12_cti_o), + .wbm0_bte_o (wbm_d_or12_bte_o), + // Outputs to master from arbiter + .wbm0_dat_i (wbm_d_or12_dat_i), + .wbm0_ack_i (wbm_d_or12_ack_i), + .wbm0_err_i (wbm_d_or12_err_i), + .wbm0_rty_i (wbm_d_or12_rty_i), + + // Master 0 + // Inputs to arbiter from master + .wbm1_adr_o (wbm_d_dbg_adr_o), + .wbm1_dat_o (wbm_d_dbg_dat_o), + .wbm1_we_o (wbm_d_dbg_we_o), + .wbm1_cyc_o (wbm_d_dbg_cyc_o), + .wbm1_sel_o (wbm_d_dbg_sel_o), + .wbm1_stb_o (wbm_d_dbg_stb_o), + .wbm1_cti_o (wbm_d_dbg_cti_o), + .wbm1_bte_o (wbm_d_dbg_bte_o), + // Outputs to master from arbiter + .wbm1_dat_i (wbm_d_dbg_dat_i), + .wbm1_ack_i (wbm_d_dbg_ack_i), + .wbm1_err_i (wbm_d_dbg_err_i), + .wbm1_rty_i (wbm_d_dbg_rty_i), + + // Slaves + + .wbs0_adr_i (wbs_d_mc0_adr_i), + .wbs0_dat_i (wbs_d_mc0_dat_i), + .wbs0_sel_i (wbs_d_mc0_sel_i), + .wbs0_we_i (wbs_d_mc0_we_i), + .wbs0_cyc_i (wbs_d_mc0_cyc_i), + .wbs0_stb_i (wbs_d_mc0_stb_i), + .wbs0_cti_i (wbs_d_mc0_cti_i), + .wbs0_bte_i (wbs_d_mc0_bte_i), + .wbs0_dat_o (wbs_d_mc0_dat_o), + .wbs0_ack_o (wbs_d_mc0_ack_o), + .wbs0_err_o (wbs_d_mc0_err_o), + .wbs0_rty_o (wbs_d_mc0_rty_o), + + .wbs1_adr_i (wbm_b_d_adr_o), + .wbs1_dat_i (wbm_b_d_dat_o), + .wbs1_sel_i (wbm_b_d_sel_o), + .wbs1_we_i (wbm_b_d_we_o), + .wbs1_cyc_i (wbm_b_d_cyc_o), + .wbs1_stb_i (wbm_b_d_stb_o), + .wbs1_cti_i (wbm_b_d_cti_o), + .wbs1_bte_i (wbm_b_d_bte_o), + .wbs1_dat_o (wbm_b_d_dat_i), + .wbs1_ack_o (wbm_b_d_ack_i), + .wbs1_err_o (wbm_b_d_err_i), + .wbs1_rty_o (wbm_b_d_rty_i), + + // Clock, reset inputs + .wb_clk (wb_clk), + .wb_rst (wb_rst)); + + // These settings are from top level params file + defparam arbiter_dbus0.wb_addr_match_width = dbus_arb_wb_addr_match_width; + defparam arbiter_dbus0.wb_num_slaves = dbus_arb_wb_num_slaves; + defparam arbiter_dbus0.slave0_adr = dbus_arb_slave0_adr; + defparam arbiter_dbus0.slave1_adr = dbus_arb_slave1_adr; + + // + // Wishbone byte-wide bus arbiter + // + + arbiter_bytebus arbiter_bytebus0 + ( + + // Master 0 + // Inputs to arbiter from master + .wbm0_adr_o (wbm_b_d_adr_o), + .wbm0_dat_o (wbm_b_d_dat_o), + .wbm0_sel_o (wbm_b_d_sel_o), + .wbm0_we_o (wbm_b_d_we_o), + .wbm0_cyc_o (wbm_b_d_cyc_o), + .wbm0_stb_o (wbm_b_d_stb_o), + .wbm0_cti_o (wbm_b_d_cti_o), + .wbm0_bte_o (wbm_b_d_bte_o), + // Outputs to master from arbiter + .wbm0_dat_i (wbm_b_d_dat_i), + .wbm0_ack_i (wbm_b_d_ack_i), + .wbm0_err_i (wbm_b_d_err_i), + .wbm0_rty_i (wbm_b_d_rty_i), + + // Byte bus slaves + + .wbs0_adr_i (wbs_d_peh_adr_i), + .wbs0_dat_i (wbs_d_peh_dat_i), + .wbs0_we_i (wbs_d_peh_we_i), + .wbs0_cyc_i (wbs_d_peh_cyc_i), + .wbs0_stb_i (wbs_d_peh_stb_i), + .wbs0_cti_i (wbs_d_peh_cti_i), + .wbs0_bte_i (wbs_d_peh_bte_i), + .wbs0_dat_o (wbs_d_peh_dat_o), + .wbs0_ack_o (wbs_d_peh_ack_o), + .wbs0_err_o (wbs_d_peh_err_o), + .wbs0_rty_o (wbs_d_peh_rty_o), + + // Clock, reset inputs + .wb_clk (wb_clk), + .wb_rst (wb_rst)); + + defparam arbiter_bytebus0.wb_addr_match_width = bbus_arb_wb_addr_match_width; + defparam arbiter_bytebus0.wb_num_slaves = bbus_arb_wb_num_slaves; + + defparam arbiter_bytebus0.slave0_adr = bbus_arb_slave0_adr; + +`ifdef JTAG_DEBUG + //////////////////////////////////////////////////////////////////////// + // + // JTAG TAP + // + //////////////////////////////////////////////////////////////////////// + + // + // Wires + // + wire dbg_if_select; + wire dbg_if_tdo; + wire jtag_tap_tdo; + wire jtag_tap_shift_dr, jtag_tap_pause_dr, + jtag_tap_update_dr, jtag_tap_capture_dr; + // + // Instantiation + // + + jtag_tap jtag_tap0 + ( + // Ports to pads + .tdo_pad_o (tdo_pad_o), + .tms_pad_i (tms_pad_i), + .tck_pad_i (dbg_tck), + .trst_pad_i (async_rst), + .tdi_pad_i (tdi_pad_i), + + .tdo_padoe_o (), + + .tdo_o (jtag_tap_tdo), + + .shift_dr_o (jtag_tap_shift_dr), + .pause_dr_o (jtag_tap_pause_dr), + .update_dr_o (jtag_tap_update_dr), + .capture_dr_o (jtag_tap_capture_dr), + + .extest_select_o (), + .sample_preload_select_o (), + .mbist_select_o (), + .debug_select_o (dbg_if_select), + + + .bs_chain_tdi_i (1'b0), + .mbist_tdi_i (1'b0), + .debug_tdi_i (dbg_if_tdo) + + ); + + //////////////////////////////////////////////////////////////////////// +`endif // `ifdef JTAG_DEBUG + + //////////////////////////////////////////////////////////////////////// + // + // OpenRISC processor + // + //////////////////////////////////////////////////////////////////////// + + // + // Wires + // + + wire [19:0] or1200_pic_ints; + + wire [31:0] or1200_dbg_dat_i; + wire [31:0] or1200_dbg_adr_i; + wire or1200_dbg_we_i; + wire or1200_dbg_stb_i; + wire or1200_dbg_ack_o; + wire [31:0] or1200_dbg_dat_o; + + wire or1200_dbg_stall_i; + wire or1200_dbg_ewt_i; + wire [3:0] or1200_dbg_lss_o; + wire [1:0] or1200_dbg_is_o; + wire [10:0] or1200_dbg_wp_o; + wire or1200_dbg_bp_o; + wire or1200_dbg_rst; + + wire or1200_clk, or1200_rst; + wire sig_tick; + wire [8:0] or1200_mem_parity_err; + wire parity_err_reset; + + wire or1200_wb_rst; + + // + // Assigns + // + assign or1200_clk = wb_clk; + assign or1200_rst = wb_rst | or1200_dbg_rst | parity_err_reset; + assign or1200_wb_rst = wb_rst | or1200_dbg_rst | parity_err_reset; + + // + // Instantiation + // + or1200_top or1200_top0 + ( + // Instruction bus, clocks, reset + .iwb_clk_i (wb_clk), + .iwb_rst_i (or1200_wb_rst), + .iwb_ack_i (wbm_i_or12_ack_i), + .iwb_err_i (wbm_i_or12_err_i), + .iwb_rty_i (wbm_i_or12_rty_i), + .iwb_dat_i (wbm_i_or12_dat_i), + + .iwb_cyc_o (wbm_i_or12_cyc_o), + .iwb_adr_o (wbm_i_or12_adr_o), + .iwb_stb_o (wbm_i_or12_stb_o), + .iwb_we_o (wbm_i_or12_we_o), + .iwb_sel_o (wbm_i_or12_sel_o), + .iwb_dat_o (wbm_i_or12_dat_o), + .iwb_cti_o (wbm_i_or12_cti_o), + .iwb_bte_o (wbm_i_or12_bte_o), + + // Data bus, clocks, reset + .dwb_clk_i (wb_clk), + .dwb_rst_i (or1200_wb_rst), + .dwb_ack_i (wbm_d_or12_ack_i), + .dwb_err_i (wbm_d_or12_err_i), + .dwb_rty_i (wbm_d_or12_rty_i), + .dwb_dat_i (wbm_d_or12_dat_i), + + .dwb_cyc_o (wbm_d_or12_cyc_o), + .dwb_adr_o (wbm_d_or12_adr_o), + .dwb_stb_o (wbm_d_or12_stb_o), + .dwb_we_o (wbm_d_or12_we_o), + .dwb_sel_o (wbm_d_or12_sel_o), + .dwb_dat_o (wbm_d_or12_dat_o), + .dwb_cti_o (wbm_d_or12_cti_o), + .dwb_bte_o (wbm_d_or12_bte_o), + + // Debug interface ports + .dbg_stall_i (or1200_dbg_stall_i), + //.dbg_ewt_i (or1200_dbg_ewt_i), + .dbg_ewt_i (1'b0), + .dbg_lss_o (or1200_dbg_lss_o), + .dbg_is_o (or1200_dbg_is_o), + .dbg_wp_o (or1200_dbg_wp_o), + .dbg_bp_o (or1200_dbg_bp_o), + + .dbg_adr_i (or1200_dbg_adr_i), + .dbg_we_i (or1200_dbg_we_i ), + .dbg_stb_i (or1200_dbg_stb_i), + .dbg_dat_i (or1200_dbg_dat_i), + .dbg_dat_o (or1200_dbg_dat_o), + .dbg_ack_o (or1200_dbg_ack_o), + + .pm_clksd_o (), + .pm_dc_gate_o (), + .pm_ic_gate_o (), + .pm_dmmu_gate_o (), + .pm_immu_gate_o (), + .pm_tt_gate_o (), + .pm_cpu_gate_o (), + .pm_wakeup_o (), + .pm_lvolt_o (), + + // Core clocks, resets + .clk_i (or1200_clk), + .rst_i (or1200_rst), + + .clmode_i (2'b00), + // Interrupts + .pic_ints_i (or1200_pic_ints), + .sig_tick(sig_tick), + /* + .mbist_so_o (), + .mbist_si_i (0), + .mbist_ctrl_i (0), + */ + +`ifdef OR1200_RAM_PARITY + .mem_parity_err (or1200_mem_parity_err), +`endif + .pm_cpustall_i (1'b0) + + ); + + //////////////////////////////////////////////////////////////////////// + + +`ifdef JTAG_DEBUG + //////////////////////////////////////////////////////////////////////// + // + // OR1200 Debug Interface + // + //////////////////////////////////////////////////////////////////////// + + dbg_if dbg_if0 + ( + // OR1200 interface + .cpu0_clk_i (or1200_clk), + .cpu0_rst_o (or1200_dbg_rst), + .cpu0_addr_o (or1200_dbg_adr_i), + .cpu0_data_o (or1200_dbg_dat_i), + .cpu0_stb_o (or1200_dbg_stb_i), + .cpu0_we_o (or1200_dbg_we_i), + .cpu0_data_i (or1200_dbg_dat_o), + .cpu0_ack_i (or1200_dbg_ack_o), + + + .cpu0_stall_o (or1200_dbg_stall_i), + .cpu0_bp_i (or1200_dbg_bp_o), + + // TAP interface + .tck_i (dbg_tck), + .tdi_i (jtag_tap_tdo), + .tdo_o (dbg_if_tdo), + .rst_i (wb_rst), + .shift_dr_i (jtag_tap_shift_dr), + .pause_dr_i (jtag_tap_pause_dr), + .update_dr_i (jtag_tap_update_dr), + .debug_select_i (dbg_if_select), + + // Wishbone debug master + .wb_clk_i (wb_clk), + .wb_dat_i (wbm_d_dbg_dat_i), + .wb_ack_i (wbm_d_dbg_ack_i), + .wb_err_i (wbm_d_dbg_err_i), + .wb_adr_o (wbm_d_dbg_adr_o), + .wb_dat_o (wbm_d_dbg_dat_o), + .wb_cyc_o (wbm_d_dbg_cyc_o), + .wb_stb_o (wbm_d_dbg_stb_o), + .wb_sel_o (wbm_d_dbg_sel_o), + .wb_we_o (wbm_d_dbg_we_o ), + .wb_cti_o (wbm_d_dbg_cti_o), + .wb_cab_o (/* UNUSED */), + .wb_bte_o (wbm_d_dbg_bte_o) + ); + + //////////////////////////////////////////////////////////////////////// +`else // !`ifdef JTAG_DEBUG + + assign or1200_dbg_rst = 0; + + assign wbm_d_dbg_adr_o = 0; + assign wbm_d_dbg_dat_o = 0; + assign wbm_d_dbg_cyc_o = 0; + assign wbm_d_dbg_stb_o = 0; + assign wbm_d_dbg_sel_o = 0; + assign wbm_d_dbg_we_o = 0; + assign wbm_d_dbg_cti_o = 0; + assign wbm_d_dbg_bte_o = 0; + + assign or1200_dbg_adr_i = 0; + assign or1200_dbg_dat_i = 0; + assign or1200_dbg_stb_i = 0; + assign or1200_dbg_we_i = 0; + assign or1200_dbg_stall_i = 0; + + //////////////////////////////////////////////////////////////////////// +`endif // !`ifdef JTAG_DEBUG + +`ifdef OR1200_RAM_PARITY + //////////////////////////////////////////////////////////////////////// + // + // Parity error handler + // + //////////////////////////////////////////////////////////////////////// + wire parity_err_int; + + parity_err_handler perrhndler + ( + .clk(wb_clk), + .parity_err(or1200_mem_parity_err), + .wb_rst(wb_rst), + .reset(parity_err_reset), + .interrupt(parity_err_int), + .wb_dat_o(wbs_d_peh_dat_o), + .wb_ack_o(wbs_d_peh_ack_o), + .wb_stb_i(wbs_d_peh_stb_i) + ); + + assign wbs_d_peh_err_o = 0; + assign wbs_d_peh_rty_o = 0; + +`endif + //////////////////////////////////////////////////////////////////////// + // + // ROM + // + //////////////////////////////////////////////////////////////////////// +`ifdef BOOTROM + rom rom0 + ( + .wb_dat_o (wbs_i_rom0_dat_o), + .wb_ack_o (wbs_i_rom0_ack_o), + .wb_adr_i (wbs_i_rom0_adr_i[(wbs_i_rom0_addr_width+2)-1:2]), + .wb_stb_i (wbs_i_rom0_stb_i), + .wb_cyc_i (wbs_i_rom0_cyc_i), + .wb_cti_i (wbs_i_rom0_cti_i), + .wb_bte_i (wbs_i_rom0_bte_i), + .wb_clk (wb_clk), + .wb_rst (wb_rst)); + + defparam rom0.addr_width = wbs_i_rom0_addr_width; +`else // !`ifdef BOOTROM + assign wbs_i_rom0_dat_o = 0; + assign wbs_i_rom0_ack_o = 0; +`endif // !`ifdef BOOTROM + + + assign wbs_i_rom0_err_o = 0; + assign wbs_i_rom0_rty_o = 0; + + //////////////////////////////////////////////////////////////////////// + +`ifdef RAM_WB + //////////////////////////////////////////////////////////////////////// + // + // Generic main RAM + // + //////////////////////////////////////////////////////////////////////// + + + ram_wb ram_wb0 + ( + // Wishbone slave interface 0 + .wbm0_dat_i (wbs_i_mc0_dat_i), + .wbm0_adr_i (wbs_i_mc0_adr_i), + .wbm0_sel_i (wbs_i_mc0_sel_i), + .wbm0_cti_i (wbs_i_mc0_cti_i), + .wbm0_bte_i (wbs_i_mc0_bte_i), + .wbm0_we_i (wbs_i_mc0_we_i ), + .wbm0_cyc_i (wbs_i_mc0_cyc_i), + .wbm0_stb_i (wbs_i_mc0_stb_i), + .wbm0_dat_o (wbs_i_mc0_dat_o), + .wbm0_ack_o (wbs_i_mc0_ack_o), + .wbm0_err_o (wbs_i_mc0_err_o), + .wbm0_rty_o (wbs_i_mc0_rty_o), + // Wishbone slave interface 1 + .wbm1_dat_i (wbs_d_mc0_dat_i), + .wbm1_adr_i (wbs_d_mc0_adr_i), + .wbm1_sel_i (wbs_d_mc0_sel_i), + .wbm1_cti_i (wbs_d_mc0_cti_i), + .wbm1_bte_i (wbs_d_mc0_bte_i), + .wbm1_we_i (wbs_d_mc0_we_i ), + .wbm1_cyc_i (wbs_d_mc0_cyc_i), + .wbm1_stb_i (wbs_d_mc0_stb_i), + .wbm1_dat_o (wbs_d_mc0_dat_o), + .wbm1_ack_o (wbs_d_mc0_ack_o), + .wbm1_err_o (wbs_d_mc0_err_o), + .wbm1_rty_o (wbs_d_mc0_rty_o), + // Wishbone slave interface 2 + .wbm2_dat_i ('d0), + .wbm2_adr_i ('d0), + .wbm2_sel_i (4'd0), + .wbm2_cti_i (3'd0), + .wbm2_bte_i (2'd0), + .wbm2_we_i (1'd0), + .wbm2_cyc_i (1'd0), + .wbm2_stb_i (1'd0), + .wbm2_dat_o (), + .wbm2_ack_o (), + .wbm2_err_o (), + .wbm2_rty_o (), + // Clock, reset + .wb_clk_i (wb_clk), + .wb_rst_i (wb_rst)); + + defparam ram_wb0.aw = wb_aw; + defparam ram_wb0.dw = wb_dw; + + defparam ram_wb0.mem_size_bytes = (1024*1024); // 1024MB + defparam ram_wb0.mem_adr_width = 20; // log2(1024*1024) + + + //////////////////////////////////////////////////////////////////////// +`endif + + //////////////////////////////////////////////////////////////////////// + // + // OR1200 Interrupt assignment + // + //////////////////////////////////////////////////////////////////////// + + assign or1200_pic_ints[0] = 0; // Non-maskable inside OR1200 + assign or1200_pic_ints[1] = 0; // Non-maskable inside OR1200 + assign or1200_pic_ints[2] = 0; + assign or1200_pic_ints[3] = 0; + assign or1200_pic_ints[4] = 0; +`ifdef OR1200_RAM_PARITY + assign or1200_pic_ints[5] = parity_err_int; +`else + assign or1200_pic_ints[5] = 0; +`endif + +`ifdef SPI0 + assign or1200_pic_ints[6] = spi0_irq; +`else + assign or1200_pic_ints[6] = 0; +`endif + assign or1200_pic_ints[7] = 0; + assign or1200_pic_ints[8] = 0; + assign or1200_pic_ints[9] = 0; + assign or1200_pic_ints[10] = 0; + assign or1200_pic_ints[11] = 0; + assign or1200_pic_ints[12] = 0; + assign or1200_pic_ints[13] = 0; + assign or1200_pic_ints[14] = 0; + assign or1200_pic_ints[15] = 0; + assign or1200_pic_ints[16] = 0; + assign or1200_pic_ints[17] = 0; + assign or1200_pic_ints[18] = 0; + assign or1200_pic_ints[19] = 0; + +endmodule // top + +// Local Variables: +// verilog-library-directories:("." "../arbiter" "../or1200" "../dbg_if" "../jtag_tap" "../rom" "../simple_spi" ) +// verilog-library-files:() +// verilog-library-extensions:(".v" ".h") +// End: +
generic/ft/rtl/verilog/orpsoc_top/orpsoc_top.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: generic/ft/rtl/verilog/arbiter/arbiter_bytebus.v =================================================================== --- generic/ft/rtl/verilog/arbiter/arbiter_bytebus.v (nonexistent) +++ generic/ft/rtl/verilog/arbiter/arbiter_bytebus.v (revision 483) @@ -0,0 +1,1192 @@ +////////////////////////////////////////////////////////////////////// +/// //// +/// Wishbone arbiter, byte-wide data path, no bursting //// +/// //// +/// Simple arbiter, single master, multiple slave, for byte-wide //// +/// peripherals //// +/// //// +/// Julius Baxter, julius@opencores.org //// +/// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG //// +//// //// +//// 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, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +// +// Things to update when changing slave config: +// +// 1. Port list +// 2. Port specification +// 3. Slave addr select parameter +// 4. Slave addr selects +// 5. Slave input mux logic +// 6. The four different master out mux logics (dat_o mux, and ack, rty & err) +// +`include "orpsoc-defines.v" +module arbiter_bytebus + ( + + // Master in + wbm0_adr_o, + wbm0_dat_o, + wbm0_sel_o, + wbm0_we_o, + wbm0_cyc_o, + wbm0_stb_o, + wbm0_cti_o, + wbm0_bte_o, + wbm0_dat_i, + wbm0_ack_i, + wbm0_err_i, + wbm0_rty_i, + + // Slave one + // Wishbone Slave interface + wbs0_adr_i, + wbs0_dat_i, + wbs0_we_i, + wbs0_cyc_i, + wbs0_stb_i, + wbs0_cti_i, + wbs0_bte_i, + wbs0_dat_o, + wbs0_ack_o, + wbs0_err_o, + wbs0_rty_o, +/* + // Slave two + // Wishbone Slave interface + wbs1_adr_i, + wbs1_dat_i, + wbs1_we_i, + wbs1_cyc_i, + wbs1_stb_i, + wbs1_cti_i, + wbs1_bte_i, + wbs1_dat_o, + wbs1_ack_o, + wbs1_err_o, + wbs1_rty_o, + + // Slave three + // Wishbone Slave interface + wbs2_adr_i, + wbs2_dat_i, + wbs2_we_i, + wbs2_cyc_i, + wbs2_stb_i, + wbs2_cti_i, + wbs2_bte_i, + wbs2_dat_o, + wbs2_ack_o, + wbs2_err_o, + wbs2_rty_o, + + // Slave four + // Wishbone Slave interface + wbs3_adr_i, + wbs3_dat_i, + wbs3_we_i, + wbs3_cyc_i, + wbs3_stb_i, + wbs3_cti_i, + wbs3_bte_i, + wbs3_dat_o, + wbs3_ack_o, + wbs3_err_o, + wbs3_rty_o, + + // Slave five + // Wishbone Slave interface + wbs4_adr_i, + wbs4_dat_i, + wbs4_we_i, + wbs4_cyc_i, + wbs4_stb_i, + wbs4_cti_i, + wbs4_bte_i, + wbs4_dat_o, + wbs4_ack_o, + wbs4_err_o, + wbs4_rty_o, + + // Slave six + // Wishbone Slave interface + wbs5_adr_i, + wbs5_dat_i, + wbs5_we_i, + wbs5_cyc_i, + wbs5_stb_i, + wbs5_cti_i, + wbs5_bte_i, + wbs5_dat_o, + wbs5_ack_o, + wbs5_err_o, + wbs5_rty_o, + + // Slave seven + // Wishbone Slave interface + wbs6_adr_i, + wbs6_dat_i, + wbs6_we_i, + wbs6_cyc_i, + wbs6_stb_i, + wbs6_cti_i, + wbs6_bte_i, + wbs6_dat_o, + wbs6_ack_o, + wbs6_err_o, + wbs6_rty_o, + + // Slave eight + // Wishbone Slave interface + wbs7_adr_i, + wbs7_dat_i, + wbs7_we_i, + wbs7_cyc_i, + wbs7_stb_i, + wbs7_cti_i, + wbs7_bte_i, + wbs7_dat_o, + wbs7_ack_o, + wbs7_err_o, + wbs7_rty_o, + + // Slave nine + // Wishbone Slave interface + wbs8_adr_i, + wbs8_dat_i, + wbs8_we_i, + wbs8_cyc_i, + wbs8_stb_i, + wbs8_cti_i, + wbs8_bte_i, + wbs8_dat_o, + wbs8_ack_o, + wbs8_err_o, + wbs8_rty_o, + + // Slave ten + // Wishbone Slave interface + wbs9_adr_i, + wbs9_dat_i, + wbs9_we_i, + wbs9_cyc_i, + wbs9_stb_i, + wbs9_cti_i, + wbs9_bte_i, + wbs9_dat_o, + wbs9_ack_o, + wbs9_err_o, + wbs9_rty_o, + + // Slave eleven + // Wishbone Slave interface + wbs10_adr_i, + wbs10_dat_i, + wbs10_we_i, + wbs10_cyc_i, + wbs10_stb_i, + wbs10_cti_i, + wbs10_bte_i, + wbs10_dat_o, + wbs10_ack_o, + wbs10_err_o, + wbs10_rty_o, + + // Slave twelve + // Wishbone Slave interface + wbs11_adr_i, + wbs11_dat_i, + wbs11_we_i, + wbs11_cyc_i, + wbs11_stb_i, + wbs11_cti_i, + wbs11_bte_i, + wbs11_dat_o, + wbs11_ack_o, + wbs11_err_o, + wbs11_rty_o, + + // Slave thirteen + // Wishbone Slave interface + wbs12_adr_i, + wbs12_dat_i, + wbs12_we_i, + wbs12_cyc_i, + wbs12_stb_i, + wbs12_cti_i, + wbs12_bte_i, + wbs12_dat_o, + wbs12_ack_o, + wbs12_err_o, + wbs12_rty_o, + + // Slave fourteen + // Wishbone Slave interface + wbs13_adr_i, + wbs13_dat_i, + wbs13_we_i, + wbs13_cyc_i, + wbs13_stb_i, + wbs13_cti_i, + wbs13_bte_i, + wbs13_dat_o, + wbs13_ack_o, + wbs13_err_o, + wbs13_rty_o, + + // Slave fifteen + // Wishbone Slave interface + wbs14_adr_i, + wbs14_dat_i, + wbs14_we_i, + wbs14_cyc_i, + wbs14_stb_i, + wbs14_cti_i, + wbs14_bte_i, + wbs14_dat_o, + wbs14_ack_o, + wbs14_err_o, + wbs14_rty_o, + + // Slave sixteen + // Wishbone Slave interface + wbs15_adr_i, + wbs15_dat_i, + wbs15_we_i, + wbs15_cyc_i, + wbs15_stb_i, + wbs15_cti_i, + wbs15_bte_i, + + wbs15_dat_o, + wbs15_ack_o, + wbs15_err_o, + wbs15_rty_o, + + // Slave seventeen + // Wishbone Slave interface + wbs16_adr_i, + wbs16_dat_i, + wbs16_we_i, + wbs16_cyc_i, + wbs16_stb_i, + wbs16_cti_i, + wbs16_bte_i, + + wbs16_dat_o, + wbs16_ack_o, + wbs16_err_o, + wbs16_rty_o, + + + // Slave eighteen + // Wishbone Slave interface + wbs17_adr_i, + wbs17_dat_i, + wbs17_we_i, + wbs17_cyc_i, + wbs17_stb_i, + wbs17_cti_i, + wbs17_bte_i, + + wbs17_dat_o, + wbs17_ack_o, + wbs17_err_o, + wbs17_rty_o, + + // Slave nineteen + // Wishbone Slave interface + wbs18_adr_i, + wbs18_dat_i, + wbs18_we_i, + wbs18_cyc_i, + wbs18_stb_i, + wbs18_cti_i, + wbs18_bte_i, + + wbs18_dat_o, + wbs18_ack_o, + wbs18_err_o, + wbs18_rty_o, + + // Slave twenty + // Wishbone Slave interface + wbs19_adr_i, + wbs19_dat_i, + wbs19_we_i, + wbs19_cyc_i, + wbs19_stb_i, + wbs19_cti_i, + wbs19_bte_i, + + wbs19_dat_o, + wbs19_ack_o, + wbs19_err_o, + wbs19_rty_o, + + */ + + wb_clk, wb_rst + ); + + + parameter wb_dat_width = 32; + parameter wbs_dat_width = 8; + parameter wb_adr_width = 32; + + parameter wb_addr_match_width = 8; + + parameter wb_num_slaves = 20; // Currently can handle up to 20 + + // Slave addresses + + parameter slave0_adr = 8'h00; + parameter slave1_adr = 8'h00; + parameter slave2_adr = 8'h00; + parameter slave3_adr = 8'h00; + parameter slave4_adr = 8'h00; + parameter slave5_adr = 8'h00; + parameter slave6_adr = 8'h00; + parameter slave7_adr = 8'h00; + parameter slave8_adr = 8'h00; + parameter slave9_adr = 8'h00; + parameter slave10_adr = 8'h00; + parameter slave11_adr = 8'h00; + parameter slave12_adr = 8'h00; + parameter slave13_adr = 8'h00; + parameter slave14_adr = 8'h00; + parameter slave15_adr = 8'h00; + parameter slave16_adr = 8'h00; + parameter slave17_adr = 8'h00; + parameter slave18_adr = 8'h00; + parameter slave19_adr = 8'h00; + + +`define WB_ARB_ADDR_MATCH_SEL wb_adr_width-1:wb_adr_width-wb_addr_match_width + + input wb_clk; + input wb_rst; + + // WB Master one + input [wb_adr_width-1:0] wbm0_adr_o; + input [wb_dat_width-1:0] wbm0_dat_o; + input [3:0] wbm0_sel_o; + input wbm0_we_o; + input wbm0_cyc_o; + input wbm0_stb_o; + input [2:0] wbm0_cti_o; + input [1:0] wbm0_bte_o; + output [wb_dat_width-1:0] wbm0_dat_i; + output wbm0_ack_i; + output wbm0_err_i; + output wbm0_rty_i; + + + // Slave one + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs0_adr_i; + output [wbs_dat_width-1:0] wbs0_dat_i; + output wbs0_we_i; + output wbs0_cyc_i; + output wbs0_stb_i; + output [2:0] wbs0_cti_i; + output [1:0] wbs0_bte_i; + input [wbs_dat_width-1:0] wbs0_dat_o; + input wbs0_ack_o; + input wbs0_err_o; + input wbs0_rty_o; + +/* + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs1_adr_i; + output [wbs_dat_width-1:0] wbs1_dat_i; + output wbs1_we_i; + output wbs1_cyc_i; + output wbs1_stb_i; + output [2:0] wbs1_cti_i; + output [1:0] wbs1_bte_i; + input [wbs_dat_width-1:0] wbs1_dat_o; + input wbs1_ack_o; + input wbs1_err_o; + input wbs1_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs2_adr_i; + output [wbs_dat_width-1:0] wbs2_dat_i; + output wbs2_we_i; + output wbs2_cyc_i; + output wbs2_stb_i; + output [2:0] wbs2_cti_i; + output [1:0] wbs2_bte_i; + input [wbs_dat_width-1:0] wbs2_dat_o; + input wbs2_ack_o; + input wbs2_err_o; + input wbs2_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs3_adr_i; + output [wbs_dat_width-1:0] wbs3_dat_i; + output wbs3_we_i; + output wbs3_cyc_i; + output wbs3_stb_i; + output [2:0] wbs3_cti_i; + output [1:0] wbs3_bte_i; + input [wbs_dat_width-1:0] wbs3_dat_o; + input wbs3_ack_o; + input wbs3_err_o; + input wbs3_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs4_adr_i; + output [wbs_dat_width-1:0] wbs4_dat_i; + output wbs4_we_i; + output wbs4_cyc_i; + output wbs4_stb_i; + output [2:0] wbs4_cti_i; + output [1:0] wbs4_bte_i; + input [wbs_dat_width-1:0] wbs4_dat_o; + input wbs4_ack_o; + input wbs4_err_o; + input wbs4_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs5_adr_i; + output [wbs_dat_width-1:0] wbs5_dat_i; + output wbs5_we_i; + output wbs5_cyc_i; + output wbs5_stb_i; + output [2:0] wbs5_cti_i; + output [1:0] wbs5_bte_i; + input [wbs_dat_width-1:0] wbs5_dat_o; + input wbs5_ack_o; + input wbs5_err_o; + input wbs5_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs6_adr_i; + output [wbs_dat_width-1:0] wbs6_dat_i; + output wbs6_we_i; + output wbs6_cyc_i; + output wbs6_stb_i; + output [2:0] wbs6_cti_i; + output [1:0] wbs6_bte_i; + input [wbs_dat_width-1:0] wbs6_dat_o; + input wbs6_ack_o; + input wbs6_err_o; + input wbs6_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs7_adr_i; + output [wbs_dat_width-1:0] wbs7_dat_i; + output wbs7_we_i; + output wbs7_cyc_i; + output wbs7_stb_i; + output [2:0] wbs7_cti_i; + output [1:0] wbs7_bte_i; + input [wbs_dat_width-1:0] wbs7_dat_o; + input wbs7_ack_o; + input wbs7_err_o; + input wbs7_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs8_adr_i; + output [wbs_dat_width-1:0] wbs8_dat_i; + output wbs8_we_i; + output wbs8_cyc_i; + output wbs8_stb_i; + output [2:0] wbs8_cti_i; + output [1:0] wbs8_bte_i; + input [wbs_dat_width-1:0] wbs8_dat_o; + input wbs8_ack_o; + input wbs8_err_o; + input wbs8_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs9_adr_i; + output [wbs_dat_width-1:0] wbs9_dat_i; + output wbs9_we_i; + output wbs9_cyc_i; + output wbs9_stb_i; + output [2:0] wbs9_cti_i; + output [1:0] wbs9_bte_i; + input [wbs_dat_width-1:0] wbs9_dat_o; + input wbs9_ack_o; + input wbs9_err_o; + input wbs9_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs10_adr_i; + output [wbs_dat_width-1:0] wbs10_dat_i; + output wbs10_we_i; + output wbs10_cyc_i; + output wbs10_stb_i; + output [2:0] wbs10_cti_i; + output [1:0] wbs10_bte_i; + input [wbs_dat_width-1:0] wbs10_dat_o; + input wbs10_ack_o; + input wbs10_err_o; + input wbs10_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs11_adr_i; + output [wbs_dat_width-1:0] wbs11_dat_i; + output wbs11_we_i; + output wbs11_cyc_i; + output wbs11_stb_i; + output [2:0] wbs11_cti_i; + output [1:0] wbs11_bte_i; + input [wbs_dat_width-1:0] wbs11_dat_o; + input wbs11_ack_o; + input wbs11_err_o; + input wbs11_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs12_adr_i; + output [wbs_dat_width-1:0] wbs12_dat_i; + output wbs12_we_i; + output wbs12_cyc_i; + output wbs12_stb_i; + output [2:0] wbs12_cti_i; + output [1:0] wbs12_bte_i; + input [wbs_dat_width-1:0] wbs12_dat_o; + input wbs12_ack_o; + input wbs12_err_o; + input wbs12_rty_o; + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs13_adr_i; + output [wbs_dat_width-1:0] wbs13_dat_i; + output wbs13_we_i; + output wbs13_cyc_i; + output wbs13_stb_i; + output [2:0] wbs13_cti_i; + output [1:0] wbs13_bte_i; + input [wbs_dat_width-1:0] wbs13_dat_o; + input wbs13_ack_o; + input wbs13_err_o; + input wbs13_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs14_adr_i; + output [wbs_dat_width-1:0] wbs14_dat_i; + output wbs14_we_i; + output wbs14_cyc_i; + output wbs14_stb_i; + output [2:0] wbs14_cti_i; + output [1:0] wbs14_bte_i; + input [wbs_dat_width-1:0] wbs14_dat_o; + input wbs14_ack_o; + input wbs14_err_o; + input wbs14_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs15_adr_i; + output [wbs_dat_width-1:0] wbs15_dat_i; + output wbs15_we_i; + output wbs15_cyc_i; + output wbs15_stb_i; + output [2:0] wbs15_cti_i; + output [1:0] wbs15_bte_i; + input [wbs_dat_width-1:0] wbs15_dat_o; + input wbs15_ack_o; + input wbs15_err_o; + input wbs15_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs16_adr_i; + output [wbs_dat_width-1:0] wbs16_dat_i; + output wbs16_we_i; + output wbs16_cyc_i; + output wbs16_stb_i; + output [2:0] wbs16_cti_i; + output [1:0] wbs16_bte_i; + input [wbs_dat_width-1:0] wbs16_dat_o; + input wbs16_ack_o; + input wbs16_err_o; + input wbs16_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs17_adr_i; + output [wbs_dat_width-1:0] wbs17_dat_i; + output wbs17_we_i; + output wbs17_cyc_i; + output wbs17_stb_i; + output [2:0] wbs17_cti_i; + output [1:0] wbs17_bte_i; + input [wbs_dat_width-1:0] wbs17_dat_o; + input wbs17_ack_o; + input wbs17_err_o; + input wbs17_rty_o; + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs18_adr_i; + output [wbs_dat_width-1:0] wbs18_dat_i; + output wbs18_we_i; + output wbs18_cyc_i; + output wbs18_stb_i; + output [2:0] wbs18_cti_i; + output [1:0] wbs18_bte_i; + input [wbs_dat_width-1:0] wbs18_dat_o; + input wbs18_ack_o; + input wbs18_err_o; + input wbs18_rty_o; + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs19_adr_i; + output [wbs_dat_width-1:0] wbs19_dat_i; + output wbs19_we_i; + output wbs19_cyc_i; + output wbs19_stb_i; + output [2:0] wbs19_cti_i; + output [1:0] wbs19_bte_i; + input [wbs_dat_width-1:0] wbs19_dat_o; + input wbs19_ack_o; + input wbs19_err_o; + input wbs19_rty_o; + */ + + reg watchdog_err; + + // Master input mux output wires + wire [wb_adr_width-1:0] wbm_adr_o; + wire [wbs_dat_width-1:0] wbm_dat_o; + wire [3:0] wbm_sel_o; + wire wbm_we_o; + wire wbm_cyc_o; + wire wbm_stb_o; + wire [2:0] wbm_cti_o; + wire [1:0] wbm_bte_o; + + wire [wbs_dat_width-1:0] wbm_dat_byte_i; + wire wbm_ack_i; + wire wbm_err_i; + wire wbm_rty_i; + + + // Master input mux (not really used, only one master on this bus) + assign wbm_adr_o = wbm0_adr_o; + + // Select the right byte and put it on the data out line + // !BIG ENDIAN! + assign wbm_dat_o = wbm0_sel_o[3] ? wbm0_dat_o[31:24] : + wbm0_sel_o[2] ? wbm0_dat_o[23:16] : + wbm0_sel_o[1] ? wbm0_dat_o[15:8] : + wbm0_dat_o[7:0]; + + assign wbm_we_o = wbm0_we_o; + + assign wbm_cyc_o = wbm0_stb_o; + + assign wbm_stb_o = wbm0_stb_o; + + // Will we really need these for byte-peripherals + assign wbm_cti_o = wbm0_cti_o; + + assign wbm_bte_o = wbm0_bte_o; + + // Signals back to the master + assign wbm0_dat_i = (wbm0_sel_o[3]) ? {wbm_dat_byte_i, 24'd0} : + (wbm0_sel_o[2]) ? {8'd0, wbm_dat_byte_i, 16'd0} : + (wbm0_sel_o[1]) ? {16'd0, wbm_dat_byte_i, 8'd0} : + {24'd0, wbm_dat_byte_i}; + + assign wbm0_ack_i = wbm_ack_i; + assign wbm0_err_i = wbm_err_i; + assign wbm0_rty_i = wbm_rty_i; + +`ifdef ARBITER_BYTEBUS_WATCHDOG + reg [`ARBITER_BYTEBUS_WATCHDOG_TIMER_WIDTH:0] watchdog_timer; + reg wbm_stb_r; // Register strobe + wire wbm_stb_edge; // Detect its edge + + always @(posedge wb_clk) + wbm_stb_r <= wbm_stb_o; + + assign wbm_stb_edge = (wbm_stb_o & !wbm_stb_r); + + // Counter logic + always @(posedge wb_clk) + if (wb_rst) watchdog_timer <= 0; + else if (wbm_ack_i) // When we see an ack, turn off timer + watchdog_timer <= 0; + else if (wbm_stb_edge) // New access means start timer again + watchdog_timer <= 1; + else if (|watchdog_timer) // Continue counting if counter > 0 + watchdog_timer <= watchdog_timer + 1; + + always @(posedge wb_clk) + watchdog_err <= (&watchdog_timer); + +`else // !`ifdef ARBITER_BYTEBUS_WATCHDOG + always @(posedge wb_clk) + watchdog_err <= 0; + +`endif // !`ifdef ARBITER_BYTEBUS_WATCHDOG + + + // Wishbone slave mux out wires + wire [wb_adr_width-1:0] wbs_adr_i; + wire [wbs_dat_width-1:0] wbs_dat_i; + wire wbs_we_i; + wire wbs_cyc_i; + wire wbs_stb_i; + wire [2:0] wbs_cti_i; + wire [1:0] wbs_bte_i; + wire [wbs_dat_width-1:0] wbs_dat_o; + wire wbs_ack_o; + wire wbs_err_o; + wire wbs_rty_o; + + + // Slave select wire + wire [wb_num_slaves-1:0] wb_slave_sel; + + // Slave out mux in wires + wire [wbs_dat_width-1:0] wbs_dat_o_mux_i [0:wb_num_slaves-1]; + wire wbs_ack_o_mux_i [0:wb_num_slaves-1]; + wire wbs_err_o_mux_i [0:wb_num_slaves-1]; + wire wbs_rty_o_mux_i [0:wb_num_slaves-1]; + + // Slave selects + assign wb_slave_sel[0] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave0_adr; + /* + assign wb_slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave1_adr; + assign wb_slave_sel[2] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave2_adr; + assign wb_slave_sel[3] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave3_adr; + assign wb_slave_sel[4] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave4_adr; + assign wb_slave_sel[5] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave5_adr; + assign wb_slave_sel[6] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave6_adr; + assign wb_slave_sel[7] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave7_adr; + assign wb_slave_sel[8] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave8_adr; + assign wb_slave_sel[9] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave9_adr; + assign wb_slave_sel[10] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave10_adr; + assign wb_slave_sel[11] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave11_adr; + assign wb_slave_sel[12] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave12_adr; + assign wb_slave_sel[13] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave13_adr; + assign wb_slave_sel[14] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave14_adr; + assign wb_slave_sel[15] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave15_adr; + assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave16_adr; + assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave17_adr; + assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave18_adr; + assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave19_adr; + */ + + + // Assign master inputs to slaves and slave inputs for MUXing back to master + + // Slave 0 inputs + assign wbs0_adr_i = wbm_adr_o; + assign wbs0_dat_i = wbm_dat_o; + assign wbs0_cyc_i = wbm_cyc_o & wb_slave_sel[0]; + assign wbs0_stb_i = wbm_stb_o & wb_slave_sel[0]; + assign wbs0_we_i = wbm_we_o; + assign wbs0_cti_i = wbm_cti_o; + assign wbs0_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[0] = wbs0_dat_o; + assign wbs_ack_o_mux_i[0] = wbs0_ack_o & wb_slave_sel[0]; + assign wbs_err_o_mux_i[0] = wbs0_err_o & wb_slave_sel[0]; + assign wbs_rty_o_mux_i[0] = wbs0_rty_o & wb_slave_sel[0]; + + /* + // Slave 1 inputs + assign wbs1_adr_i = wbm_adr_o; + assign wbs1_dat_i = wbm_dat_o; + assign wbs1_cyc_i = wbm_cyc_o & wb_slave_sel[1]; + assign wbs1_stb_i = wbm_stb_o & wb_slave_sel[1]; + assign wbs1_we_i = wbm_we_o; + assign wbs1_cti_i = wbm_cti_o; + assign wbs1_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[1] = wbs1_dat_o; + assign wbs_ack_o_mux_i[1] = wbs1_ack_o & wb_slave_sel[1]; + assign wbs_err_o_mux_i[1] = wbs1_err_o & wb_slave_sel[1]; + assign wbs_rty_o_mux_i[1] = wbs1_rty_o & wb_slave_sel[1]; + + + // Slave 2 inputs + assign wbs2_adr_i = wbm_adr_o; + assign wbs2_dat_i = wbm_dat_o; + assign wbs2_cyc_i = wbm_cyc_o & wb_slave_sel[2]; + assign wbs2_stb_i = wbm_stb_o & wb_slave_sel[2]; + assign wbs2_we_i = wbm_we_o; + assign wbs2_cti_i = wbm_cti_o; + assign wbs2_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[2] = wbs2_dat_o; + assign wbs_ack_o_mux_i[2] = wbs2_ack_o & wb_slave_sel[2]; + assign wbs_err_o_mux_i[2] = wbs2_err_o & wb_slave_sel[2]; + assign wbs_rty_o_mux_i[2] = wbs2_rty_o & wb_slave_sel[2]; + + + // Slave 3 inputs + assign wbs3_adr_i = wbm_adr_o; + assign wbs3_dat_i = wbm_dat_o; + assign wbs3_cyc_i = wbm_cyc_o & wb_slave_sel[3]; + assign wbs3_stb_i = wbm_stb_o & wb_slave_sel[3]; + assign wbs3_we_i = wbm_we_o; + assign wbs3_cti_i = wbm_cti_o; + assign wbs3_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[3] = wbs3_dat_o; + assign wbs_ack_o_mux_i[3] = wbs3_ack_o & wb_slave_sel[3]; + assign wbs_err_o_mux_i[3] = wbs3_err_o & wb_slave_sel[3]; + assign wbs_rty_o_mux_i[3] = wbs3_rty_o & wb_slave_sel[3]; + + + // Slave 4 inputs + assign wbs4_adr_i = wbm_adr_o; + assign wbs4_dat_i = wbm_dat_o; + assign wbs4_cyc_i = wbm_cyc_o & wb_slave_sel[4]; + assign wbs4_stb_i = wbm_stb_o & wb_slave_sel[4]; + assign wbs4_we_i = wbm_we_o; + assign wbs4_cti_i = wbm_cti_o; + assign wbs4_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[4] = wbs4_dat_o; + assign wbs_ack_o_mux_i[4] = wbs4_ack_o & wb_slave_sel[4]; + assign wbs_err_o_mux_i[4] = wbs4_err_o & wb_slave_sel[4]; + assign wbs_rty_o_mux_i[4] = wbs4_rty_o & wb_slave_sel[4]; + + + // Slave 5 inputs + assign wbs5_adr_i = wbm_adr_o; + assign wbs5_dat_i = wbm_dat_o; + assign wbs5_cyc_i = wbm_cyc_o & wb_slave_sel[5]; + assign wbs5_stb_i = wbm_stb_o & wb_slave_sel[5]; + assign wbs5_we_i = wbm_we_o; + assign wbs5_cti_i = wbm_cti_o; + assign wbs5_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[5] = wbs5_dat_o; + assign wbs_ack_o_mux_i[5] = wbs5_ack_o & wb_slave_sel[5]; + assign wbs_err_o_mux_i[5] = wbs5_err_o & wb_slave_sel[5]; + assign wbs_rty_o_mux_i[5] = wbs5_rty_o & wb_slave_sel[5]; + + + // Slave 6 inputs + assign wbs6_adr_i = wbm_adr_o; + assign wbs6_dat_i = wbm_dat_o; + assign wbs6_cyc_i = wbm_cyc_o & wb_slave_sel[6]; + assign wbs6_stb_i = wbm_stb_o & wb_slave_sel[6]; + assign wbs6_we_i = wbm_we_o; + assign wbs6_cti_i = wbm_cti_o; + assign wbs6_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[6] = wbs6_dat_o; + assign wbs_ack_o_mux_i[6] = wbs6_ack_o & wb_slave_sel[6]; + assign wbs_err_o_mux_i[6] = wbs6_err_o & wb_slave_sel[6]; + assign wbs_rty_o_mux_i[6] = wbs6_rty_o & wb_slave_sel[6]; + + + // Slave 7 inputs + assign wbs7_adr_i = wbm_adr_o; + assign wbs7_dat_i = wbm_dat_o; + assign wbs7_cyc_i = wbm_cyc_o & wb_slave_sel[7]; + assign wbs7_stb_i = wbm_stb_o & wb_slave_sel[7]; + assign wbs7_we_i = wbm_we_o; + assign wbs7_cti_i = wbm_cti_o; + assign wbs7_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[7] = wbs7_dat_o; + assign wbs_ack_o_mux_i[7] = wbs7_ack_o & wb_slave_sel[7]; + assign wbs_err_o_mux_i[7] = wbs7_err_o & wb_slave_sel[7]; + assign wbs_rty_o_mux_i[7] = wbs7_rty_o & wb_slave_sel[7]; + + + // Slave 8 inputs + assign wbs8_adr_i = wbm_adr_o; + assign wbs8_dat_i = wbm_dat_o; + assign wbs8_cyc_i = wbm_cyc_o & wb_slave_sel[8]; + assign wbs8_stb_i = wbm_stb_o & wb_slave_sel[8]; + assign wbs8_we_i = wbm_we_o; + assign wbs8_cti_i = wbm_cti_o; + assign wbs8_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[8] = wbs8_dat_o; + assign wbs_ack_o_mux_i[8] = wbs8_ack_o & wb_slave_sel[8]; + assign wbs_err_o_mux_i[8] = wbs8_err_o & wb_slave_sel[8]; + assign wbs_rty_o_mux_i[8] = wbs8_rty_o & wb_slave_sel[8]; + + + // Slave 9 inputs + assign wbs9_adr_i = wbm_adr_o; + assign wbs9_dat_i = wbm_dat_o; + assign wbs9_cyc_i = wbm_cyc_o & wb_slave_sel[9]; + assign wbs9_stb_i = wbm_stb_o & wb_slave_sel[9]; + assign wbs9_we_i = wbm_we_o; + assign wbs9_cti_i = wbm_cti_o; + assign wbs9_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[9] = wbs9_dat_o; + assign wbs_ack_o_mux_i[9] = wbs9_ack_o & wb_slave_sel[9]; + assign wbs_err_o_mux_i[9] = wbs9_err_o & wb_slave_sel[9]; + assign wbs_rty_o_mux_i[9] = wbs9_rty_o & wb_slave_sel[9]; + + + // Slave 10 inputs + assign wbs10_adr_i = wbm_adr_o; + assign wbs10_dat_i = wbm_dat_o; + assign wbs10_cyc_i = wbm_cyc_o & wb_slave_sel[10]; + assign wbs10_stb_i = wbm_stb_o & wb_slave_sel[10]; + assign wbs10_we_i = wbm_we_o; + assign wbs10_cti_i = wbm_cti_o; + assign wbs10_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[10] = wbs10_dat_o; + assign wbs_ack_o_mux_i[10] = wbs10_ack_o & wb_slave_sel[10]; + assign wbs_err_o_mux_i[10] = wbs10_err_o & wb_slave_sel[10]; + assign wbs_rty_o_mux_i[10] = wbs10_rty_o & wb_slave_sel[10]; + + + // Slave 11 inputs + assign wbs11_adr_i = wbm_adr_o; + assign wbs11_dat_i = wbm_dat_o; + assign wbs11_cyc_i = wbm_cyc_o & wb_slave_sel[11]; + assign wbs11_stb_i = wbm_stb_o & wb_slave_sel[11]; + assign wbs11_we_i = wbm_we_o; + assign wbs11_cti_i = wbm_cti_o; + assign wbs11_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[11] = wbs11_dat_o; + assign wbs_ack_o_mux_i[11] = wbs11_ack_o & wb_slave_sel[11]; + assign wbs_err_o_mux_i[11] = wbs11_err_o & wb_slave_sel[11]; + assign wbs_rty_o_mux_i[11] = wbs11_rty_o & wb_slave_sel[11]; + + // Slave 12 inputs + assign wbs12_adr_i = wbm_adr_o; + assign wbs12_dat_i = wbm_dat_o; + assign wbs12_cyc_i = wbm_cyc_o & wb_slave_sel[12]; + assign wbs12_stb_i = wbm_stb_o & wb_slave_sel[12]; + assign wbs12_we_i = wbm_we_o; + assign wbs12_cti_i = wbm_cti_o; + assign wbs12_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[12] = wbs12_dat_o; + assign wbs_ack_o_mux_i[12] = wbs12_ack_o & wb_slave_sel[12]; + assign wbs_err_o_mux_i[12] = wbs12_err_o & wb_slave_sel[12]; + assign wbs_rty_o_mux_i[12] = wbs12_rty_o & wb_slave_sel[12]; + + + // Slave 13 inputs + assign wbs13_adr_i = wbm_adr_o; + assign wbs13_dat_i = wbm_dat_o; + assign wbs13_cyc_i = wbm_cyc_o & wb_slave_sel[13]; + assign wbs13_stb_i = wbm_stb_o & wb_slave_sel[13]; + assign wbs13_we_i = wbm_we_o; + assign wbs13_cti_i = wbm_cti_o; + assign wbs13_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[13] = wbs13_dat_o; + assign wbs_ack_o_mux_i[13] = wbs13_ack_o & wb_slave_sel[13]; + assign wbs_err_o_mux_i[13] = wbs13_err_o & wb_slave_sel[13]; + assign wbs_rty_o_mux_i[13] = wbs13_rty_o & wb_slave_sel[13]; + + + // Slave 14 inputs + assign wbs14_adr_i = wbm_adr_o; + assign wbs14_dat_i = wbm_dat_o; + assign wbs14_cyc_i = wbm_cyc_o & wb_slave_sel[14]; + assign wbs14_stb_i = wbm_stb_o & wb_slave_sel[14]; + assign wbs14_we_i = wbm_we_o; + assign wbs14_cti_i = wbm_cti_o; + assign wbs14_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[14] = wbs14_dat_o; + assign wbs_ack_o_mux_i[14] = wbs14_ack_o & wb_slave_sel[14]; + assign wbs_err_o_mux_i[14] = wbs14_err_o & wb_slave_sel[14]; + assign wbs_rty_o_mux_i[14] = wbs14_rty_o & wb_slave_sel[14]; + + + // Slave 15 inputs + assign wbs15_adr_i = wbm_adr_o; + assign wbs15_dat_i = wbm_dat_o; + assign wbs15_cyc_i = wbm_cyc_o & wb_slave_sel[15]; + assign wbs15_stb_i = wbm_stb_o & wb_slave_sel[15]; + assign wbs15_we_i = wbm_we_o; + assign wbs15_cti_i = wbm_cti_o; + assign wbs15_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[15] = wbs15_dat_o; + assign wbs_ack_o_mux_i[15] = wbs15_ack_o & wb_slave_sel[15]; + assign wbs_err_o_mux_i[15] = wbs15_err_o & wb_slave_sel[15]; + assign wbs_rty_o_mux_i[15] = wbs15_rty_o & wb_slave_sel[15]; + + + // Slave 16 inputs + assign wbs16_adr_i = wbm_adr_o; + assign wbs16_dat_i = wbm_dat_o; + assign wbs16_cyc_i = wbm_cyc_o & wb_slave_sel[16]; + assign wbs16_stb_i = wbm_stb_o & wb_slave_sel[16]; + assign wbs16_we_i = wbm_we_o; + assign wbs16_cti_i = wbm_cti_o; + assign wbs16_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[16] = wbs16_dat_o; + assign wbs_ack_o_mux_i[16] = wbs16_ack_o & wb_slave_sel[16]; + assign wbs_err_o_mux_i[16] = wbs16_err_o & wb_slave_sel[16]; + assign wbs_rty_o_mux_i[16] = wbs16_rty_o & wb_slave_sel[16]; + + + // Slave 17 inputs + assign wbs17_adr_i = wbm_adr_o; + assign wbs17_dat_i = wbm_dat_o; + assign wbs17_cyc_i = wbm_cyc_o & wb_slave_sel[17]; + assign wbs17_stb_i = wbm_stb_o & wb_slave_sel[17]; + assign wbs17_we_i = wbm_we_o; + assign wbs17_cti_i = wbm_cti_o; + assign wbs17_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[17] = wbs17_dat_o; + assign wbs_ack_o_mux_i[17] = wbs17_ack_o & wb_slave_sel[17]; + assign wbs_err_o_mux_i[17] = wbs17_err_o & wb_slave_sel[17]; + assign wbs_rty_o_mux_i[17] = wbs17_rty_o & wb_slave_sel[17]; + + // Slave 18 inputs + assign wbs18_adr_i = wbm_adr_o; + assign wbs18_dat_i = wbm_dat_o; + assign wbs18_cyc_i = wbm_cyc_o & wb_slave_sel[18]; + assign wbs18_stb_i = wbm_stb_o & wb_slave_sel[18]; + assign wbs18_we_i = wbm_we_o; + assign wbs18_cti_i = wbm_cti_o; + assign wbs18_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[18] = wbs18_dat_o; + assign wbs_ack_o_mux_i[18] = wbs18_ack_o & wb_slave_sel[18]; + assign wbs_err_o_mux_i[18] = wbs18_err_o & wb_slave_sel[18]; + assign wbs_rty_o_mux_i[18] = wbs18_rty_o & wb_slave_sel[18]; + + // Slave 19 inputs + assign wbs19_adr_i = wbm_adr_o; + assign wbs19_dat_i = wbm_dat_o; + assign wbs19_cyc_i = wbm_cyc_o & wb_slave_sel[19]; + assign wbs19_stb_i = wbm_stb_o & wb_slave_sel[19]; + assign wbs19_we_i = wbm_we_o; + assign wbs19_cti_i = wbm_cti_o; + assign wbs19_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[19] = wbs19_dat_o; + assign wbs_ack_o_mux_i[19] = wbs19_ack_o & wb_slave_sel[19]; + assign wbs_err_o_mux_i[19] = wbs19_err_o & wb_slave_sel[19]; + assign wbs_rty_o_mux_i[19] = wbs19_rty_o & wb_slave_sel[19]; + +*/ + + + + // Master out mux from slave in data + assign wbm_dat_byte_i = wb_slave_sel[0] ? wbs_dat_o_mux_i[0] : +/* + wb_slave_sel[1] ? wbs_dat_o_mux_i[1] : + wb_slave_sel[2] ? wbs_dat_o_mux_i[2] : + wb_slave_sel[3] ? wbs_dat_o_mux_i[3] : + wb_slave_sel[4] ? wbs_dat_o_mux_i[4] : + wb_slave_sel[5] ? wbs_dat_o_mux_i[5] : + wb_slave_sel[6] ? wbs_dat_o_mux_i[6] : + wb_slave_sel[7] ? wbs_dat_o_mux_i[7] : + wb_slave_sel[8] ? wbs_dat_o_mux_i[8] : + wb_slave_sel[9] ? wbs_dat_o_mux_i[9] : + wb_slave_sel[10] ? wbs_dat_o_mux_i[10] : + wb_slave_sel[11] ? wbs_dat_o_mux_i[11] : + wb_slave_sel[12] ? wbs_dat_o_mux_i[12] : + wb_slave_sel[13] ? wbs_dat_o_mux_i[13] : + wb_slave_sel[14] ? wbs_dat_o_mux_i[14] : + wb_slave_sel[15] ? wbs_dat_o_mux_i[15] : + wb_slave_sel[16] ? wbs_dat_o_mux_i[16] : + wb_slave_sel[17] ? wbs_dat_o_mux_i[17] : + wb_slave_sel[18] ? wbs_dat_o_mux_i[18] : + wb_slave_sel[19] ? wbs_dat_o_mux_i[19] : +*/ + wbs_dat_o_mux_i[0]; + // Master out acks, or together + assign wbm_ack_i = wbs_ack_o_mux_i[0] /* | + wbs_ack_o_mux_i[1] | + wbs_ack_o_mux_i[2] | + wbs_ack_o_mux_i[3] | + wbs_ack_o_mux_i[4] | + wbs_ack_o_mux_i[5] | + wbs_ack_o_mux_i[6] | + wbs_ack_o_mux_i[7] | + wbs_ack_o_mux_i[8] | + wbs_ack_o_mux_i[9] | + wbs_ack_o_mux_i[10] | + wbs_ack_o_mux_i[11] | + wbs_ack_o_mux_i[12] | + wbs_ack_o_mux_i[13] | + wbs_ack_o_mux_i[14] | + wbs_ack_o_mux_i[15] | + wbs_ack_o_mux_i[16] | + wbs_ack_o_mux_i[17] | + wbs_ack_o_mux_i[18] | + wbs_ack_o_mux_i[19] + */ + ; + + + assign wbm_err_i = wbs_err_o_mux_i[0] |/* + wbs_err_o_mux_i[1] | + wbs_err_o_mux_i[2] | + wbs_err_o_mux_i[3] | + wbs_err_o_mux_i[4] | + wbs_err_o_mux_i[5] | + wbs_err_o_mux_i[6] | + wbs_err_o_mux_i[7] | + wbs_err_o_mux_i[8] | + wbs_err_o_mux_i[9] | + wbs_err_o_mux_i[10] | + wbs_err_o_mux_i[11] | + wbs_err_o_mux_i[12] | + wbs_err_o_mux_i[13] | + wbs_err_o_mux_i[14] | + wbs_err_o_mux_i[15] | + wbs_err_o_mux_i[16] | + wbs_err_o_mux_i[17] | + wbs_err_o_mux_i[18] | + wbs_err_o_mux_i[19] | + */ + watchdog_err ; + + + assign wbm_rty_i = wbs_rty_o_mux_i[0] /*| + wbs_rty_o_mux_i[1] | + wbs_rty_o_mux_i[2] | + wbs_rty_o_mux_i[3] | + wbs_rty_o_mux_i[4] | + wbs_rty_o_mux_i[5] | + wbs_rty_o_mux_i[6] | + wbs_rty_o_mux_i[7] | + wbs_rty_o_mux_i[8] | + wbs_rty_o_mux_i[9] | + wbs_rty_o_mux_i[10] | + wbs_rty_o_mux_i[11] | + wbs_rty_o_mux_i[12] | + wbs_rty_o_mux_i[13] | + wbs_rty_o_mux_i[14] | + wbs_rty_o_mux_i[15] | + wbs_rty_o_mux_i[16] | + wbs_rty_o_mux_i[17] | + wbs_rty_o_mux_i[18] | + wbs_rty_o_mux_i[19] + */ + ; + +endmodule // arbiter_bytebus Index: generic/ft/rtl/verilog/arbiter/arbiter_dbus.v =================================================================== --- generic/ft/rtl/verilog/arbiter/arbiter_dbus.v (nonexistent) +++ generic/ft/rtl/verilog/arbiter/arbiter_dbus.v (revision 483) @@ -0,0 +1,1267 @@ +////////////////////////////////////////////////////////////////////// +/// //// +/// Wishbone arbiter, burst-compatible //// +/// //// +/// Simple arbiter, multi-master, multi-slave with default slave //// +/// for chaining with peripheral arbiter //// +/// //// +/// Julius Baxter, julius@opencores.org //// +/// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG //// +//// //// +//// 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, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +`include "orpsoc-defines.v" +// 2 Masters, a few slaves +module arbiter_dbus + ( + // or1200 data master + // Wishbone Master interface + wbm0_adr_o, + wbm0_dat_o, + wbm0_sel_o, + wbm0_we_o, + wbm0_cyc_o, + wbm0_stb_o, + wbm0_cti_o, + wbm0_bte_o, + + wbm0_dat_i, + wbm0_ack_i, + wbm0_err_i, + wbm0_rty_i, + + // or1200 debug master + // Wishbone Master interface + wbm1_adr_o, + wbm1_dat_o, + wbm1_sel_o, + wbm1_we_o, + wbm1_cyc_o, + wbm1_stb_o, + wbm1_cti_o, + wbm1_bte_o, + + wbm1_dat_i, + wbm1_ack_i, + wbm1_err_i, + wbm1_rty_i, + + // Slave one + // Wishbone Slave interface + wbs0_adr_i, + wbs0_dat_i, + wbs0_sel_i, + wbs0_we_i, + wbs0_cyc_i, + wbs0_stb_i, + wbs0_cti_i, + wbs0_bte_i, + + wbs0_dat_o, + wbs0_ack_o, + wbs0_err_o, + wbs0_rty_o, + + // Slave two + // Wishbone Slave interface + wbs1_adr_i, + wbs1_dat_i, + wbs1_sel_i, + wbs1_we_i, + wbs1_cyc_i, + wbs1_stb_i, + wbs1_cti_i, + wbs1_bte_i, + + wbs1_dat_o, + wbs1_ack_o, + wbs1_err_o, + wbs1_rty_o, + + /* + // Slave three + // Wishbone Slave interface + wbs2_adr_i, + wbs2_dat_i, + wbs2_sel_i, + wbs2_we_i, + wbs2_cyc_i, + wbs2_stb_i, + wbs2_cti_i, + wbs2_bte_i, + + wbs2_dat_o, + wbs2_ack_o, + wbs2_err_o, + wbs2_rty_o, + + // Slave four + // Wishbone Slave interface + wbs3_adr_i, + wbs3_dat_i, + wbs3_sel_i, + wbs3_we_i, + wbs3_cyc_i, + wbs3_stb_i, + wbs3_cti_i, + wbs3_bte_i, + + wbs3_dat_o, + wbs3_ack_o, + wbs3_err_o, + wbs3_rty_o, + + // Slave five + // Wishbone Slave interface + wbs4_adr_i, + wbs4_dat_i, + wbs4_sel_i, + wbs4_we_i, + wbs4_cyc_i, + wbs4_stb_i, + wbs4_cti_i, + wbs4_bte_i, + + wbs4_dat_o, + wbs4_ack_o, + wbs4_err_o, + wbs4_rty_o, + + // Slave six + // Wishbone Slave interface + wbs5_adr_i, + wbs5_dat_i, + wbs5_sel_i, + wbs5_we_i, + wbs5_cyc_i, + wbs5_stb_i, + wbs5_cti_i, + wbs5_bte_i, + + wbs5_dat_o, + wbs5_ack_o, + wbs5_err_o, + wbs5_rty_o, + + // Slave seven + // Wishbone Slave interface + wbs6_adr_i, + wbs6_dat_i, + wbs6_sel_i, + wbs6_we_i, + wbs6_cyc_i, + wbs6_stb_i, + wbs6_cti_i, + wbs6_bte_i, + + wbs6_dat_o, + wbs6_ack_o, + wbs6_err_o, + wbs6_rty_o, + + // Slave eight + // Wishbone Slave interface + wbs7_adr_i, + wbs7_dat_i, + wbs7_sel_i, + wbs7_we_i, + wbs7_cyc_i, + wbs7_stb_i, + wbs7_cti_i, + wbs7_bte_i, + + wbs7_dat_o, + wbs7_ack_o, + wbs7_err_o, + wbs7_rty_o, + + // Slave nine + // Wishbone Slave interface + wbs8_adr_i, + wbs8_dat_i, + wbs8_sel_i, + wbs8_we_i, + wbs8_cyc_i, + wbs8_stb_i, + wbs8_cti_i, + wbs8_bte_i, + + wbs8_dat_o, + wbs8_ack_o, + wbs8_err_o, + wbs8_rty_o, + + // Slave ten + // Wishbone Slave interface + wbs9_adr_i, + wbs9_dat_i, + wbs9_sel_i, + wbs9_we_i, + wbs9_cyc_i, + wbs9_stb_i, + wbs9_cti_i, + wbs9_bte_i, + + wbs9_dat_o, + wbs9_ack_o, + wbs9_err_o, + wbs9_rty_o, + + // Slave eleven + // Wishbone Slave interface + wbs10_adr_i, + wbs10_dat_i, + wbs10_sel_i, + wbs10_we_i, + wbs10_cyc_i, + wbs10_stb_i, + wbs10_cti_i, + wbs10_bte_i, + + wbs10_dat_o, + wbs10_ack_o, + wbs10_err_o, + wbs10_rty_o, + + // Slave twelve + // Wishbone Slave interface + wbs11_adr_i, + wbs11_dat_i, + wbs11_sel_i, + wbs11_we_i, + wbs11_cyc_i, + wbs11_stb_i, + wbs11_cti_i, + wbs11_bte_i, + + wbs11_dat_o, + wbs11_ack_o, + wbs11_err_o, + wbs11_rty_o, + + // Slave thirteen + // Wishbone Slave interface + wbs12_adr_i, + wbs12_dat_i, + wbs12_sel_i, + wbs12_we_i, + wbs12_cyc_i, + wbs12_stb_i, + wbs12_cti_i, + wbs12_bte_i, + + wbs12_dat_o, + wbs12_ack_o, + wbs12_err_o, + wbs12_rty_o, + + // Slave fourteen + // Wishbone Slave interface + wbs13_adr_i, + wbs13_dat_i, + wbs13_sel_i, + wbs13_we_i, + wbs13_cyc_i, + wbs13_stb_i, + wbs13_cti_i, + wbs13_bte_i, + + wbs13_dat_o, + wbs13_ack_o, + wbs13_err_o, + wbs13_rty_o, + + // Slave fifteen + // Wishbone Slave interface + wbs14_adr_i, + wbs14_dat_i, + wbs14_sel_i, + wbs14_we_i, + wbs14_cyc_i, + wbs14_stb_i, + wbs14_cti_i, + wbs14_bte_i, + + wbs14_dat_o, + wbs14_ack_o, + wbs14_err_o, + wbs14_rty_o, + + // Slave sixteen + // Wishbone Slave interface + wbs15_adr_i, + wbs15_dat_i, + wbs15_sel_i, + wbs15_we_i, + wbs15_cyc_i, + wbs15_stb_i, + wbs15_cti_i, + wbs15_bte_i, + + wbs15_dat_o, + wbs15_ack_o, + wbs15_err_o, + wbs15_rty_o, + + // Slave seventeen + // Wishbone Slave interface + wbs16_adr_i, + wbs16_dat_i, + wbs16_sel_i, + wbs16_we_i, + wbs16_cyc_i, + wbs16_stb_i, + wbs16_cti_i, + wbs16_bte_i, + + wbs16_dat_o, + wbs16_ack_o, + wbs16_err_o, + wbs16_rty_o, + */ + + wb_clk, + wb_rst + ); + + parameter wb_dat_width = 32; + parameter wb_adr_width = 32; + + parameter wb_addr_match_width = 8; + + parameter wb_num_slaves = 2; // must also (un)comment things if changing + + // Slave addresses - these should be defparam'd from top level + // Declare them as you need them + parameter slave0_adr = 0; + parameter slave1_adr = 0; + parameter slave2_adr = 0; + parameter slave3_adr = 0; + parameter slave4_adr = 0; + parameter slave5_adr = 0; + parameter slave6_adr = 0; + parameter slave7_adr = 0; + parameter slave8_adr = 0; + parameter slave9_adr = 0; + parameter slave10_adr = 0; + parameter slave11_adr = 0; + parameter slave12_adr = 0; + + // Select for slave 0 +`define WB_ARB_ADDR_MATCH_SEL_SLAVE0 wb_adr_width-1:wb_adr_width-4 +`define WB_ARB_ADDR_MATCH_SEL wb_adr_width-1:wb_adr_width-wb_addr_match_width + + input wb_clk; + input wb_rst; + + // WB Master one + input [wb_adr_width-1:0] wbm0_adr_o; + input [wb_dat_width-1:0] wbm0_dat_o; + input [3:0] wbm0_sel_o; + input wbm0_we_o; + input wbm0_cyc_o; + input wbm0_stb_o; + input [2:0] wbm0_cti_o; + input [1:0] wbm0_bte_o; + output [wb_dat_width-1:0] wbm0_dat_i; + output wbm0_ack_i; + output wbm0_err_i; + output wbm0_rty_i; + + + input [wb_adr_width-1:0] wbm1_adr_o; + input [wb_dat_width-1:0] wbm1_dat_o; + input [3:0] wbm1_sel_o; + input wbm1_we_o; + input wbm1_cyc_o; + input wbm1_stb_o; + input [2:0] wbm1_cti_o; + input [1:0] wbm1_bte_o; + output [wb_dat_width-1:0] wbm1_dat_i; + output wbm1_ack_i; + output wbm1_err_i; + output wbm1_rty_i; + + + // Slave one + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs0_adr_i; + output [wb_dat_width-1:0] wbs0_dat_i; + output [3:0] wbs0_sel_i; + output wbs0_we_i; + output wbs0_cyc_i; + output wbs0_stb_i; + output [2:0] wbs0_cti_i; + output [1:0] wbs0_bte_i; + input [wb_dat_width-1:0] wbs0_dat_o; + input wbs0_ack_o; + input wbs0_err_o; + input wbs0_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs1_adr_i; + output [wb_dat_width-1:0] wbs1_dat_i; + output [3:0] wbs1_sel_i; + output wbs1_we_i; + output wbs1_cyc_i; + output wbs1_stb_i; + output [2:0] wbs1_cti_i; + output [1:0] wbs1_bte_i; + input [wb_dat_width-1:0] wbs1_dat_o; + input wbs1_ack_o; + input wbs1_err_o; + input wbs1_rty_o; + +/* + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs2_adr_i; + output [wb_dat_width-1:0] wbs2_dat_i; + output [3:0] wbs2_sel_i; + output wbs2_we_i; + output wbs2_cyc_i; + output wbs2_stb_i; + output [2:0] wbs2_cti_i; + output [1:0] wbs2_bte_i; + input [wb_dat_width-1:0] wbs2_dat_o; + input wbs2_ack_o; + input wbs2_err_o; + input wbs2_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs3_adr_i; + output [wb_dat_width-1:0] wbs3_dat_i; + output [3:0] wbs3_sel_i; + output wbs3_we_i; + output wbs3_cyc_i; + output wbs3_stb_i; + output [2:0] wbs3_cti_i; + output [1:0] wbs3_bte_i; + input [wb_dat_width-1:0] wbs3_dat_o; + input wbs3_ack_o; + input wbs3_err_o; + input wbs3_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs4_adr_i; + output [wb_dat_width-1:0] wbs4_dat_i; + output [3:0] wbs4_sel_i; + output wbs4_we_i; + output wbs4_cyc_i; + output wbs4_stb_i; + output [2:0] wbs4_cti_i; + output [1:0] wbs4_bte_i; + input [wb_dat_width-1:0] wbs4_dat_o; + input wbs4_ack_o; + input wbs4_err_o; + input wbs4_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs5_adr_i; + output [wb_dat_width-1:0] wbs5_dat_i; + output [3:0] wbs5_sel_i; + output wbs5_we_i; + output wbs5_cyc_i; + output wbs5_stb_i; + output [2:0] wbs5_cti_i; + output [1:0] wbs5_bte_i; + input [wb_dat_width-1:0] wbs5_dat_o; + input wbs5_ack_o; + input wbs5_err_o; + input wbs5_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs6_adr_i; + output [wb_dat_width-1:0] wbs6_dat_i; + output [3:0] wbs6_sel_i; + output wbs6_we_i; + output wbs6_cyc_i; + output wbs6_stb_i; + output [2:0] wbs6_cti_i; + output [1:0] wbs6_bte_i; + input [wb_dat_width-1:0] wbs6_dat_o; + input wbs6_ack_o; + input wbs6_err_o; + input wbs6_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs7_adr_i; + output [wb_dat_width-1:0] wbs7_dat_i; + output [3:0] wbs7_sel_i; + output wbs7_we_i; + output wbs7_cyc_i; + output wbs7_stb_i; + output [2:0] wbs7_cti_i; + output [1:0] wbs7_bte_i; + input [wb_dat_width-1:0] wbs7_dat_o; + input wbs7_ack_o; + input wbs7_err_o; + input wbs7_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs8_adr_i; + output [wb_dat_width-1:0] wbs8_dat_i; + output [3:0] wbs8_sel_i; + output wbs8_we_i; + output wbs8_cyc_i; + output wbs8_stb_i; + output [2:0] wbs8_cti_i; + output [1:0] wbs8_bte_i; + input [wb_dat_width-1:0] wbs8_dat_o; + input wbs8_ack_o; + input wbs8_err_o; + input wbs8_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs9_adr_i; + output [wb_dat_width-1:0] wbs9_dat_i; + output [3:0] wbs9_sel_i; + output wbs9_we_i; + output wbs9_cyc_i; + output wbs9_stb_i; + output [2:0] wbs9_cti_i; + output [1:0] wbs9_bte_i; + input [wb_dat_width-1:0] wbs9_dat_o; + input wbs9_ack_o; + input wbs9_err_o; + input wbs9_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs10_adr_i; + output [wb_dat_width-1:0] wbs10_dat_i; + output [3:0] wbs10_sel_i; + output wbs10_we_i; + output wbs10_cyc_i; + output wbs10_stb_i; + output [2:0] wbs10_cti_i; + output [1:0] wbs10_bte_i; + input [wb_dat_width-1:0] wbs10_dat_o; + input wbs10_ack_o; + input wbs10_err_o; + input wbs10_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs11_adr_i; + output [wb_dat_width-1:0] wbs11_dat_i; + output [3:0] wbs11_sel_i; + output wbs11_we_i; + output wbs11_cyc_i; + output wbs11_stb_i; + output [2:0] wbs11_cti_i; + output [1:0] wbs11_bte_i; + input [wb_dat_width-1:0] wbs11_dat_o; + input wbs11_ack_o; + input wbs11_err_o; + input wbs11_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs12_adr_i; + output [wb_dat_width-1:0] wbs12_dat_i; + output [3:0] wbs12_sel_i; + output wbs12_we_i; + output wbs12_cyc_i; + output wbs12_stb_i; + output [2:0] wbs12_cti_i; + output [1:0] wbs12_bte_i; + input [wb_dat_width-1:0] wbs12_dat_o; + input wbs12_ack_o; + input wbs12_err_o; + input wbs12_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs13_adr_i; + output [wb_dat_width-1:0] wbs13_dat_i; + output [3:0] wbs13_sel_i; + output wbs13_we_i; + output wbs13_cyc_i; + output wbs13_stb_i; + output [2:0] wbs13_cti_i; + output [1:0] wbs13_bte_i; + input [wb_dat_width-1:0] wbs13_dat_o; + input wbs13_ack_o; + input wbs13_err_o; + input wbs13_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs14_adr_i; + output [wb_dat_width-1:0] wbs14_dat_i; + output [3:0] wbs14_sel_i; + output wbs14_we_i; + output wbs14_cyc_i; + output wbs14_stb_i; + output [2:0] wbs14_cti_i; + output [1:0] wbs14_bte_i; + input [wb_dat_width-1:0] wbs14_dat_o; + input wbs14_ack_o; + input wbs14_err_o; + input wbs14_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs15_adr_i; + output [wb_dat_width-1:0] wbs15_dat_i; + output [3:0] wbs15_sel_i; + output wbs15_we_i; + output wbs15_cyc_i; + output wbs15_stb_i; + output [2:0] wbs15_cti_i; + output [1:0] wbs15_bte_i; + input [wb_dat_width-1:0] wbs15_dat_o; + input wbs15_ack_o; + input wbs15_err_o; + input wbs15_rty_o; + + + // Wishbone Slave interface + output [wb_adr_width-1:0] wbs16_adr_i; + output [wb_dat_width-1:0] wbs16_dat_i; + output [3:0] wbs16_sel_i; + output wbs16_we_i; + output wbs16_cyc_i; + output wbs16_stb_i; + output [2:0] wbs16_cti_i; + output [1:0] wbs16_bte_i; + input [wb_dat_width-1:0] wbs16_dat_o; + input wbs16_ack_o; + input wbs16_err_o; + input wbs16_rty_o; + +*/ + + reg watchdog_err; + +`ifdef ARBITER_DBUS_REGISTERING + + + // Registering setup: + // Masters typically register their outputs, so do the master selection and + // muxing before registering in the arbiter. Keep the common parts outside + // for code brevity. + + // Master ins -> |MUX> -> these wires + wire [wb_adr_width-1:0] wbm_adr_o_w; + wire [wb_dat_width-1:0] wbm_dat_o_w; + wire [3:0] wbm_sel_o_w; + wire wbm_we_o_w; + wire wbm_cyc_o_w; + wire wbm_stb_o_w; + wire [2:0] wbm_cti_o_w; + wire [1:0] wbm_bte_o_w; + // Slave ins -> |MUX> -> these wires + wire [wb_dat_width-1:0] wbm_dat_i; + wire wbm_ack_i; + wire wbm_err_i; + wire wbm_rty_i; + + // Registers after masters input mux + reg [wb_adr_width-1:0] wbm_adr_o_r; + reg [wb_dat_width-1:0] wbm_dat_o_r; + reg [3:0] wbm_sel_o_r; + reg wbm_we_o_r; + reg wbm_cyc_o_r; + reg wbm_stb_o_r; + reg [2:0] wbm_cti_o_r; + reg [1:0] wbm_bte_o_r; + + // Master input mux register wires + wire [wb_adr_width-1:0] wbm_adr_o; + wire [wb_dat_width-1:0] wbm_dat_o; + wire [3:0] wbm_sel_o; + wire wbm_we_o; + wire wbm_cyc_o; + wire wbm_stb_o; + wire [2:0] wbm_cti_o; + wire [1:0] wbm_bte_o; + + // Registers after slaves input mux + reg [wb_dat_width-1:0] wbm_dat_i_r; + reg wbm_ack_i_r; + reg wbm_err_i_r; + reg wbm_rty_i_r; + + // Master select (MUX controls) + wire [1:0] master_sel; + // priority to wbm1, the debug master + assign master_sel[0] = wbm0_cyc_o & !wbm1_cyc_o; + assign master_sel[1] = wbm1_cyc_o; + + + // Master input mux, priority to debug master + assign wbm_adr_o_w = master_sel[1] ? wbm1_adr_o : + wbm0_adr_o; + + assign wbm_dat_o_w = master_sel[1] ? wbm1_dat_o : + wbm0_dat_o; + + assign wbm_sel_o_w = master_sel[1] ? wbm1_sel_o : + wbm0_sel_o; + + assign wbm_we_o_w = master_sel[1] ? wbm1_we_o : + wbm0_we_o; + + assign wbm_cyc_o_w = master_sel[1] ? wbm1_cyc_o : + wbm0_cyc_o; + + assign wbm_stb_o_w = master_sel[1] ? wbm1_stb_o : + wbm0_stb_o; + + assign wbm_cti_o_w = master_sel[1] ? wbm1_cti_o : + wbm0_cti_o; + + assign wbm_bte_o_w = master_sel[1] ? wbm1_bte_o : + wbm0_bte_o; + + + // Register muxed master signals + always @(posedge wb_clk) + begin + wbm_adr_o_r <= wbm_adr_o_w; + wbm_dat_o_r <= wbm_dat_o_w; + wbm_sel_o_r <= wbm_sel_o_w; + wbm_we_o_r <= wbm_we_o_w; + wbm_cyc_o_r <= wbm_cyc_o_w; + wbm_stb_o_r <= wbm_stb_o_w & !wbm_ack_i & !wbm_ack_i_r; + wbm_cti_o_r <= wbm_cti_o_w; + wbm_bte_o_r <= wbm_bte_o_w; + + wbm_dat_i_r <= wbm_dat_i; + wbm_ack_i_r <= wbm_ack_i; + wbm_err_i_r <= wbm_err_i; + wbm_rty_i_r <= wbm_rty_i; + end // always @ (posedge wb_clk) + + + assign wbm_adr_o = wbm_adr_o_r; + assign wbm_dat_o = wbm_dat_o_r; + assign wbm_sel_o = wbm_sel_o_r; + assign wbm_we_o = wbm_we_o_r; + assign wbm_cyc_o = wbm_cyc_o_r; + assign wbm_stb_o = wbm_stb_o_r; + assign wbm_cti_o = wbm_cti_o_r; + assign wbm_bte_o = wbm_bte_o_r; + + // Master input mux, priority to debug master + assign wbm0_dat_i = wbm_dat_i_r; + assign wbm0_ack_i = wbm_ack_i_r & master_sel[0]; + assign wbm0_err_i = wbm_err_i_r & master_sel[0]; + assign wbm0_rty_i = wbm_rty_i_r & master_sel[0]; + + assign wbm1_dat_i = wbm_dat_i_r; + assign wbm1_ack_i = wbm_ack_i_r & master_sel[1]; + assign wbm1_err_i = wbm_err_i_r & master_sel[1]; + assign wbm1_rty_i = wbm_rty_i_r & master_sel[1]; + +`else // !`ifdef ARBITER_DBUS_REGISTERING + + // Master input mux output wires + wire [wb_adr_width-1:0] wbm_adr_o; + wire [wb_dat_width-1:0] wbm_dat_o; + wire [3:0] wbm_sel_o; + wire wbm_we_o; + wire wbm_cyc_o; + wire wbm_stb_o; + wire [2:0] wbm_cti_o; + wire [1:0] wbm_bte_o; + + // Master select + wire [1:0] master_sel; + // priority to wbm1, the debug master + assign master_sel[0] = wbm0_cyc_o & !wbm1_cyc_o; + assign master_sel[1] = wbm1_cyc_o; + + + // Master input mux, priority to debug master + assign wbm_adr_o = master_sel[1] ? wbm1_adr_o : + wbm0_adr_o; + + assign wbm_dat_o = master_sel[1] ? wbm1_dat_o : + wbm0_dat_o; + + assign wbm_sel_o = master_sel[1] ? wbm1_sel_o : + wbm0_sel_o; + + assign wbm_we_o = master_sel[1] ? wbm1_we_o : + wbm0_we_o; + + assign wbm_cyc_o = master_sel[1] ? wbm1_cyc_o : + wbm0_cyc_o; + + assign wbm_stb_o = master_sel[1] ? wbm1_stb_o : + wbm0_stb_o; + + assign wbm_cti_o = master_sel[1] ? wbm1_cti_o : + wbm0_cti_o; + + assign wbm_bte_o = master_sel[1] ? wbm1_bte_o : + wbm0_bte_o; + + + wire [wb_dat_width-1:0] wbm_dat_i; + wire wbm_ack_i; + wire wbm_err_i; + wire wbm_rty_i; + + + assign wbm0_dat_i = wbm_dat_i; + assign wbm0_ack_i = wbm_ack_i & master_sel[0]; + assign wbm0_err_i = wbm_err_i & master_sel[0]; + assign wbm0_rty_i = wbm_rty_i & master_sel[0]; + + assign wbm1_dat_i = wbm_dat_i; + assign wbm1_ack_i = wbm_ack_i & master_sel[1]; + assign wbm1_err_i = wbm_err_i & master_sel[1]; + assign wbm1_rty_i = wbm_rty_i & master_sel[1]; + + + +`endif // !`ifdef ARBITER_DBUS_REGISTERING + + + // Slave select wire + wire [wb_num_slaves-1:0] wb_slave_sel; + reg [wb_num_slaves-1:0] wb_slave_sel_r; + + // Register wb_slave_sel_r to break combinatorial loop when selecting default + // slave + always @(posedge wb_clk) + wb_slave_sel_r <= wb_slave_sel; + + // Slave out mux in wires + wire [wb_dat_width-1:0] wbs_dat_o_mux_i [0:wb_num_slaves-1]; + wire wbs_ack_o_mux_i [0:wb_num_slaves-1]; + wire wbs_err_o_mux_i [0:wb_num_slaves-1]; + wire wbs_rty_o_mux_i [0:wb_num_slaves-1]; + + // + // Slave selects + // + assign wb_slave_sel[0] = wbm_adr_o[31:28] == slave0_adr | wbm_adr_o[31:28] == 4'hf; // Special case, point all reads to ROM address to here + + // Auto select last slave when others are not selected + assign wb_slave_sel[1] = !(wb_slave_sel_r[0]); + +/* + assign wb_slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave1_adr; + assign wb_slave_sel[2] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave2_adr; + assign wb_slave_sel[3] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave3_adr; + assign wb_slave_sel[4] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave4_adr; + assign wb_slave_sel[5] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave5_adr; + assign wb_slave_sel[6] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave6_adr; + assign wb_slave_sel[7] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave7_adr; + assign wb_slave_sel[8] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave8_adr; + assign wb_slave_sel[9] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave9_adr; + assign wb_slave_sel[10] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave10_adr; + assign wb_slave_sel[11] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave11_adr; + assign wb_slave_sel[12] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave12_adr; + assign wb_slave_sel[13] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave13_adr; + assign wb_slave_sel[14] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave14_adr; + assign wb_slave_sel[15] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave15_adr; + assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave16_adr; +*/ + +`ifdef ARBITER_DBUS_WATCHDOG + reg [`ARBITER_DBUS_WATCHDOG_TIMER_WIDTH:0] watchdog_timer; + reg wbm_stb_r; // Register strobe + wire wbm_stb_edge; // Detect its edge + + always @(posedge wb_clk) + wbm_stb_r <= wbm_stb_o; + + assign wbm_stb_edge = (wbm_stb_o & !wbm_stb_r); + + // Counter logic + always @(posedge wb_clk) + if (wb_rst) watchdog_timer <= 0; + else if (wbm_ack_i) // When we see an ack, turn off timer + watchdog_timer <= 0; + else if (wbm_stb_edge) // New access means start timer again + watchdog_timer <= 1; + else if (|watchdog_timer) // Continue counting if counter > 0 + watchdog_timer <= watchdog_timer + 1; + + always @(posedge wb_clk) + watchdog_err <= (&watchdog_timer); + + +`else // !`ifdef ARBITER_DBUS_WATCHDOG + + always @(posedge wb_clk) + watchdog_err <= 0; + +`endif // !`ifdef ARBITER_DBUS_WATCHDOG + + + + // Slave 0 inputs + assign wbs0_adr_i = wbm_adr_o; + assign wbs0_dat_i = wbm_dat_o; + assign wbs0_sel_i = wbm_sel_o; + assign wbs0_cyc_i = wbm_cyc_o & wb_slave_sel_r[0]; + assign wbs0_stb_i = wbm_stb_o & wb_slave_sel_r[0]; + assign wbs0_we_i = wbm_we_o; + assign wbs0_cti_i = wbm_cti_o; + assign wbs0_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[0] = wbs0_dat_o; + assign wbs_ack_o_mux_i[0] = wbs0_ack_o & wb_slave_sel_r[0]; + assign wbs_err_o_mux_i[0] = wbs0_err_o & wb_slave_sel_r[0]; + assign wbs_rty_o_mux_i[0] = wbs0_rty_o & wb_slave_sel_r[0]; + + + // Slave 1 inputs + assign wbs1_adr_i = wbm_adr_o; + assign wbs1_dat_i = wbm_dat_o; + assign wbs1_sel_i = wbm_sel_o; + assign wbs1_cyc_i = wbm_cyc_o & wb_slave_sel_r[1]; + assign wbs1_stb_i = wbm_stb_o & wb_slave_sel_r[1]; + assign wbs1_we_i = wbm_we_o; + assign wbs1_cti_i = wbm_cti_o; + assign wbs1_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[1] = wbs1_dat_o; + assign wbs_ack_o_mux_i[1] = wbs1_ack_o & wb_slave_sel_r[1]; + assign wbs_err_o_mux_i[1] = wbs1_err_o & wb_slave_sel_r[1]; + assign wbs_rty_o_mux_i[1] = wbs1_rty_o & wb_slave_sel_r[1]; + +/* + // Slave 2 inputs + assign wbs2_adr_i = wbm_adr_o; + assign wbs2_dat_i = wbm_dat_o; + assign wbs2_sel_i = wbm_sel_o; + assign wbs2_cyc_i = wbm_cyc_o & wb_slave_sel_r[2]; + assign wbs2_stb_i = wbm_stb_o & wb_slave_sel_r[2]; + assign wbs2_we_i = wbm_we_o; + assign wbs2_cti_i = wbm_cti_o; + assign wbs2_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[2] = wbs2_dat_o; + assign wbs_ack_o_mux_i[2] = wbs2_ack_o & wb_slave_sel_r[2]; + assign wbs_err_o_mux_i[2] = wbs2_err_o & wb_slave_sel_r[2]; + assign wbs_rty_o_mux_i[2] = wbs2_rty_o & wb_slave_sel_r[2]; + + + // Slave 3 inputs + assign wbs3_adr_i = wbm_adr_o; + assign wbs3_dat_i = wbm_dat_o; + assign wbs3_sel_i = wbm_sel_o; + assign wbs3_cyc_i = wbm_cyc_o & wb_slave_sel_r[3]; + assign wbs3_stb_i = wbm_stb_o & wb_slave_sel_r[3]; + assign wbs3_we_i = wbm_we_o; + assign wbs3_cti_i = wbm_cti_o; + assign wbs3_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[3] = wbs3_dat_o; + assign wbs_ack_o_mux_i[3] = wbs3_ack_o & wb_slave_sel_r[3]; + assign wbs_err_o_mux_i[3] = wbs3_err_o & wb_slave_sel_r[3]; + assign wbs_rty_o_mux_i[3] = wbs3_rty_o & wb_slave_sel_r[3]; + + // Slave 4 inputs + assign wbs4_adr_i = wbm_adr_o; + assign wbs4_dat_i = wbm_dat_o; + assign wbs4_sel_i = wbm_sel_o; + assign wbs4_cyc_i = wbm_cyc_o & wb_slave_sel_r[4]; + assign wbs4_stb_i = wbm_stb_o & wb_slave_sel_r[4]; + assign wbs4_we_i = wbm_we_o; + assign wbs4_cti_i = wbm_cti_o; + assign wbs4_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[4] = wbs4_dat_o; + assign wbs_ack_o_mux_i[4] = wbs4_ack_o & wb_slave_sel_r[4]; + assign wbs_err_o_mux_i[4] = wbs4_err_o & wb_slave_sel_r[4]; + assign wbs_rty_o_mux_i[4] = wbs4_rty_o & wb_slave_sel_r[4]; + + + // Slave 5 inputs + assign wbs5_adr_i = wbm_adr_o; + assign wbs5_dat_i = wbm_dat_o; + assign wbs5_sel_i = wbm_sel_o; + assign wbs5_cyc_i = wbm_cyc_o & wb_slave_sel_r[5]; + assign wbs5_stb_i = wbm_stb_o & wb_slave_sel_r[5]; + assign wbs5_we_i = wbm_we_o; + assign wbs5_cti_i = wbm_cti_o; + assign wbs5_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[5] = wbs5_dat_o; + assign wbs_ack_o_mux_i[5] = wbs5_ack_o & wb_slave_sel_r[5]; + assign wbs_err_o_mux_i[5] = wbs5_err_o & wb_slave_sel_r[5]; + assign wbs_rty_o_mux_i[5] = wbs5_rty_o & wb_slave_sel_r[5]; + + + // Slave 6 inputs + assign wbs6_adr_i = wbm_adr_o; + assign wbs6_dat_i = wbm_dat_o; + assign wbs6_sel_i = wbm_sel_o; + assign wbs6_cyc_i = wbm_cyc_o & wb_slave_sel_r[6]; + assign wbs6_stb_i = wbm_stb_o & wb_slave_sel_r[6]; + assign wbs6_we_i = wbm_we_o; + assign wbs6_cti_i = wbm_cti_o; + assign wbs6_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[6] = wbs6_dat_o; + assign wbs_ack_o_mux_i[6] = wbs6_ack_o & wb_slave_sel_r[6]; + assign wbs_err_o_mux_i[6] = wbs6_err_o & wb_slave_sel_r[6]; + assign wbs_rty_o_mux_i[6] = wbs6_rty_o & wb_slave_sel_r[6]; + + + // Slave 7 inputs + assign wbs7_adr_i = wbm_adr_o; + assign wbs7_dat_i = wbm_dat_o; + assign wbs7_sel_i = wbm_sel_o; + assign wbs7_cyc_i = wbm_cyc_o & wb_slave_sel_r[7]; + assign wbs7_stb_i = wbm_stb_o & wb_slave_sel_r[7]; + assign wbs7_we_i = wbm_we_o; + assign wbs7_cti_i = wbm_cti_o; + assign wbs7_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[7] = wbs7_dat_o; + assign wbs_ack_o_mux_i[7] = wbs7_ack_o & wb_slave_sel_r[7]; + assign wbs_err_o_mux_i[7] = wbs7_err_o & wb_slave_sel_r[7]; + assign wbs_rty_o_mux_i[7] = wbs7_rty_o & wb_slave_sel_r[7]; + + + // Slave 8 inputs + assign wbs8_adr_i = wbm_adr_o; + assign wbs8_dat_i = wbm_dat_o; + assign wbs8_sel_i = wbm_sel_o; + assign wbs8_cyc_i = wbm_cyc_o & wb_slave_sel_r[8]; + assign wbs8_stb_i = wbm_stb_o & wb_slave_sel_r[8]; + assign wbs8_we_i = wbm_we_o; + assign wbs8_cti_i = wbm_cti_o; + assign wbs8_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[8] = wbs8_dat_o; + assign wbs_ack_o_mux_i[8] = wbs8_ack_o & wb_slave_sel_r[8]; + assign wbs_err_o_mux_i[8] = wbs8_err_o & wb_slave_sel_r[8]; + assign wbs_rty_o_mux_i[8] = wbs8_rty_o & wb_slave_sel_r[8]; + + + // Slave 9 inputs + assign wbs9_adr_i = wbm_adr_o; + assign wbs9_dat_i = wbm_dat_o; + assign wbs9_sel_i = wbm_sel_o; + assign wbs9_cyc_i = wbm_cyc_o & wb_slave_sel_r[9]; + assign wbs9_stb_i = wbm_stb_o & wb_slave_sel_r[9]; + assign wbs9_we_i = wbm_we_o; + assign wbs9_cti_i = wbm_cti_o; + assign wbs9_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[9] = wbs9_dat_o; + assign wbs_ack_o_mux_i[9] = wbs9_ack_o & wb_slave_sel_r[9]; + assign wbs_err_o_mux_i[9] = wbs9_err_o & wb_slave_sel_r[9]; + assign wbs_rty_o_mux_i[9] = wbs9_rty_o & wb_slave_sel_r[9]; + + + // Slave 10 inputs + assign wbs10_adr_i = wbm_adr_o; + assign wbs10_dat_i = wbm_dat_o; + assign wbs10_sel_i = wbm_sel_o; + assign wbs10_cyc_i = wbm_cyc_o & wb_slave_sel_r[10]; + assign wbs10_stb_i = wbm_stb_o & wb_slave_sel_r[10]; + assign wbs10_we_i = wbm_we_o; + assign wbs10_cti_i = wbm_cti_o; + assign wbs10_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[10] = wbs10_dat_o; + assign wbs_ack_o_mux_i[10] = wbs10_ack_o & wb_slave_sel_r[10]; + assign wbs_err_o_mux_i[10] = wbs10_err_o & wb_slave_sel_r[10]; + assign wbs_rty_o_mux_i[10] = wbs10_rty_o & wb_slave_sel_r[10]; + + + // Slave 11 inputs + assign wbs11_adr_i = wbm_adr_o; + assign wbs11_dat_i = wbm_dat_o; + assign wbs11_sel_i = wbm_sel_o; + assign wbs11_cyc_i = wbm_cyc_o & wb_slave_sel_r[11]; + assign wbs11_stb_i = wbm_stb_o & wb_slave_sel_r[11]; + assign wbs11_we_i = wbm_we_o; + assign wbs11_cti_i = wbm_cti_o; + assign wbs11_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[11] = wbs11_dat_o; + assign wbs_ack_o_mux_i[11] = wbs11_ack_o & wb_slave_sel_r[11]; + assign wbs_err_o_mux_i[11] = wbs11_err_o & wb_slave_sel_r[11]; + assign wbs_rty_o_mux_i[11] = wbs11_rty_o & wb_slave_sel_r[11]; + + + // Slave 12 inputs + assign wbs12_adr_i = wbm_adr_o; + assign wbs12_dat_i = wbm_dat_o; + assign wbs12_sel_i = wbm_sel_o; + assign wbs12_cyc_i = wbm_cyc_o & wb_slave_sel_r[12]; + assign wbs12_stb_i = wbm_stb_o & wb_slave_sel_r[12]; + assign wbs12_we_i = wbm_we_o; + assign wbs12_cti_i = wbm_cti_o; + assign wbs12_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[12] = wbs12_dat_o; + assign wbs_ack_o_mux_i[12] = wbs12_ack_o & wb_slave_sel_r[12]; + assign wbs_err_o_mux_i[12] = wbs12_err_o & wb_slave_sel_r[12]; + assign wbs_rty_o_mux_i[12] = wbs12_rty_o & wb_slave_sel_r[12]; + + + // Slave 13 inputs + assign wbs13_adr_i = wbm_adr_o; + assign wbs13_dat_i = wbm_dat_o; + assign wbs13_sel_i = wbm_sel_o; + assign wbs13_cyc_i = wbm_cyc_o & wb_slave_sel_r[13]; + assign wbs13_stb_i = wbm_stb_o & wb_slave_sel_r[13]; + assign wbs13_we_i = wbm_we_o; + assign wbs13_cti_i = wbm_cti_o; + assign wbs13_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[13] = wbs13_dat_o; + assign wbs_ack_o_mux_i[13] = wbs13_ack_o & wb_slave_sel_r[13]; + assign wbs_err_o_mux_i[13] = wbs13_err_o & wb_slave_sel_r[13]; + assign wbs_rty_o_mux_i[13] = wbs13_rty_o & wb_slave_sel_r[13]; + + + // Slave 14 inputs + assign wbs14_adr_i = wbm_adr_o; + assign wbs14_dat_i = wbm_dat_o; + assign wbs14_sel_i = wbm_sel_o; + assign wbs14_cyc_i = wbm_cyc_o & wb_slave_sel_r[14]; + assign wbs14_stb_i = wbm_stb_o & wb_slave_sel_r[14]; + assign wbs14_we_i = wbm_we_o; + assign wbs14_cti_i = wbm_cti_o; + assign wbs14_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[14] = wbs14_dat_o; + assign wbs_ack_o_mux_i[14] = wbs14_ack_o & wb_slave_sel_r[14]; + assign wbs_err_o_mux_i[14] = wbs14_err_o & wb_slave_sel_r[14]; + assign wbs_rty_o_mux_i[14] = wbs14_rty_o & wb_slave_sel_r[14]; + + + // Slave 15 inputs + assign wbs15_adr_i = wbm_adr_o; + assign wbs15_dat_i = wbm_dat_o; + assign wbs15_sel_i = wbm_sel_o; + assign wbs15_cyc_i = wbm_cyc_o & wb_slave_sel_r[15]; + assign wbs15_stb_i = wbm_stb_o & wb_slave_sel_r[15]; + assign wbs15_we_i = wbm_we_o; + assign wbs15_cti_i = wbm_cti_o; + assign wbs15_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[15] = wbs15_dat_o; + assign wbs_ack_o_mux_i[15] = wbs15_ack_o & wb_slave_sel_r[15]; + assign wbs_err_o_mux_i[15] = wbs15_err_o & wb_slave_sel_r[15]; + assign wbs_rty_o_mux_i[15] = wbs15_rty_o & wb_slave_sel_r[15]; + + + // Slave 16 inputs + assign wbs16_adr_i = wbm_adr_o; + assign wbs16_dat_i = wbm_dat_o; + assign wbs16_sel_i = wbm_sel_o; + assign wbs16_cyc_i = wbm_cyc_o & wb_slave_sel_r[16]; + assign wbs16_stb_i = wbm_stb_o & wb_slave_sel_r[16]; + assign wbs16_we_i = wbm_we_o; + assign wbs16_cti_i = wbm_cti_o; + assign wbs16_bte_i = wbm_bte_o; + assign wbs_dat_o_mux_i[16] = wbs16_dat_o; + assign wbs_ack_o_mux_i[16] = wbs16_ack_o & wb_slave_sel_r[16]; + assign wbs_err_o_mux_i[16] = wbs16_err_o & wb_slave_sel_r[16]; + assign wbs_rty_o_mux_i[16] = wbs16_rty_o & wb_slave_sel_r[16]; + +*/ + + + + // Master out mux from slave in data + assign wbm_dat_i = wb_slave_sel_r[0] ? wbs_dat_o_mux_i[0] : + wb_slave_sel_r[1] ? wbs_dat_o_mux_i[1] : +/* wb_slave_sel_r[2] ? wbs_dat_o_mux_i[2] : + wb_slave_sel_r[3] ? wbs_dat_o_mux_i[3] : + wb_slave_sel_r[4] ? wbs_dat_o_mux_i[4] : + wb_slave_sel_r[5] ? wbs_dat_o_mux_i[5] : + wb_slave_sel_r[6] ? wbs_dat_o_mux_i[6] : + wb_slave_sel_r[7] ? wbs_dat_o_mux_i[7] : + wb_slave_sel_r[8] ? wbs_dat_o_mux_i[8] : + wb_slave_sel_r[9] ? wbs_dat_o_mux_i[9] : + wb_slave_sel_r[10] ? wbs_dat_o_mux_i[10] : + wb_slave_sel_r[11] ? wbs_dat_o_mux_i[11] : + wb_slave_sel_r[12] ? wbs_dat_o_mux_i[12] : + wb_slave_sel_r[13] ? wbs_dat_o_mux_i[13] : + wb_slave_sel_r[14] ? wbs_dat_o_mux_i[14] : + wb_slave_sel_r[15] ? wbs_dat_o_mux_i[15] : + wb_slave_sel_r[16] ? wbs_dat_o_mux_i[16] : +*/ + wbs_dat_o_mux_i[0]; + // Master out acks, or together + assign wbm_ack_i = wbs_ack_o_mux_i[0] | + wbs_ack_o_mux_i[1] /*| + wbs_ack_o_mux_i[2] | + wbs_ack_o_mux_i[3] | + wbs_ack_o_mux_i[4] | + wbs_ack_o_mux_i[5] | + wbs_ack_o_mux_i[6] | + wbs_ack_o_mux_i[7] | + wbs_ack_o_mux_i[8] | + wbs_ack_o_mux_i[9] | + wbs_ack_o_mux_i[10] | + wbs_ack_o_mux_i[11] | + wbs_ack_o_mux_i[12] | + wbs_ack_o_mux_i[13] | + wbs_ack_o_mux_i[14] | + wbs_ack_o_mux_i[15] | + wbs_ack_o_mux_i[16] */ + ; + + + assign wbm_err_i = wbs_err_o_mux_i[0] | + wbs_err_o_mux_i[1] |/* + wbs_err_o_mux_i[2] | + wbs_err_o_mux_i[3] | + wbs_err_o_mux_i[4] | + wbs_err_o_mux_i[5] | + wbs_err_o_mux_i[6] | + wbs_err_o_mux_i[7] | + wbs_err_o_mux_i[8] | + wbs_err_o_mux_i[9] | + wbs_err_o_mux_i[10] | + wbs_err_o_mux_i[11] | + wbs_err_o_mux_i[12] | + wbs_err_o_mux_i[13] | + wbs_err_o_mux_i[14] | + wbs_err_o_mux_i[15] | + wbs_err_o_mux_i[16] |*/ + watchdog_err ; + + + assign wbm_rty_i = wbs_rty_o_mux_i[0] | + wbs_rty_o_mux_i[1]/*| + wbs_rty_o_mux_i[2] | + wbs_rty_o_mux_i[3] | + wbs_rty_o_mux_i[4] | + wbs_rty_o_mux_i[5] | + wbs_rty_o_mux_i[6] | + wbs_rty_o_mux_i[7] | + wbs_rty_o_mux_i[8] | + wbs_rty_o_mux_i[9] | + wbs_rty_o_mux_i[10] | + wbs_rty_o_mux_i[11] | + wbs_rty_o_mux_i[12] | + wbs_rty_o_mux_i[13] | + wbs_rty_o_mux_i[14] | + wbs_rty_o_mux_i[15] | + wbs_rty_o_mux_i[16]*/; + +endmodule // arbiter_dbus + Index: generic/ft/rtl/verilog/arbiter/arbiter_ibus.v =================================================================== --- generic/ft/rtl/verilog/arbiter/arbiter_ibus.v (nonexistent) +++ generic/ft/rtl/verilog/arbiter/arbiter_ibus.v (revision 483) @@ -0,0 +1,337 @@ +////////////////////////////////////////////////////////////////////// +/// //// +/// Wishbone arbiter, burst-compatible //// +/// //// +/// Simple arbiter, single master, dual slave, primarily for //// +/// processor instruction bus, providing access to one main //// +/// memory server and one ROM //// +/// //// +/// Julius Baxter, julius@opencores.org //// +/// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG //// +//// //// +//// 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, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +`include "orpsoc-defines.v" +// One master, 2 slaves. +module arbiter_ibus + ( + // instruction bus in + // Wishbone Master interface + wbm_adr_o, + wbm_dat_o, + wbm_sel_o, + wbm_we_o, + wbm_cyc_o, + wbm_stb_o, + wbm_cti_o, + wbm_bte_o, + + wbm_dat_i, + wbm_ack_i, + wbm_err_i, + wbm_rty_i, + + + // Slave one + // Wishbone Slave interface + wbs0_adr_i, + wbs0_dat_i, + wbs0_sel_i, + wbs0_we_i, + wbs0_cyc_i, + wbs0_stb_i, + wbs0_cti_i, + wbs0_bte_i, + + wbs0_dat_o, + wbs0_ack_o, + wbs0_err_o, + wbs0_rty_o, + + // Slave two + // Wishbone Slave interface + wbs1_adr_i, + wbs1_dat_i, + wbs1_sel_i, + wbs1_we_i, + wbs1_cyc_i, + wbs1_stb_i, + wbs1_cti_i, + wbs1_bte_i, + + wbs1_dat_o, + wbs1_ack_o, + wbs1_err_o, + wbs1_rty_o, + + wb_clk, + wb_rst + ); + + + parameter wb_dat_width = 32; + parameter wb_adr_width = 32; + + parameter wb_addr_match_width = 8; + + parameter slave0_adr = 8'hf0; // FLASH ROM + parameter slave1_adr = 8'h00; // Main memory (SDRAM/FPGA SRAM) + +`define WB_ARB_ADDR_MATCH_SEL wb_adr_width-1:wb_adr_width-wb_addr_match_width + + input wb_clk; + input wb_rst; + + + // WB Master + input [wb_adr_width-1:0] wbm_adr_o; + input [wb_dat_width-1:0] wbm_dat_o; + input [3:0] wbm_sel_o; + input wbm_we_o; + input wbm_cyc_o; + input wbm_stb_o; + input [2:0] wbm_cti_o; + input [1:0] wbm_bte_o; + output [wb_dat_width-1:0] wbm_dat_i; + output wbm_ack_i; + output wbm_err_i; + output wbm_rty_i; + + // WB Slave 0 + output [wb_adr_width-1:0] wbs0_adr_i; + output [wb_dat_width-1:0] wbs0_dat_i; + output [3:0] wbs0_sel_i; + output wbs0_we_i; + output wbs0_cyc_i; + output wbs0_stb_i; + output [2:0] wbs0_cti_i; + output [1:0] wbs0_bte_i; + input [wb_dat_width-1:0] wbs0_dat_o; + input wbs0_ack_o; + input wbs0_err_o; + input wbs0_rty_o; + + // WB Slave 1 + output [wb_adr_width-1:0] wbs1_adr_i; + output [wb_dat_width-1:0] wbs1_dat_i; + output [3:0] wbs1_sel_i; + output wbs1_we_i; + output wbs1_cyc_i; + output wbs1_stb_i; + output [2:0] wbs1_cti_i; + output [1:0] wbs1_bte_i; + input [wb_dat_width-1:0] wbs1_dat_o; + input wbs1_ack_o; + input wbs1_err_o; + input wbs1_rty_o; + + wire [1:0] slave_sel; // One bit per slave + + reg watchdog_err; + +`ifdef ARBITER_IBUS_WATCHDOG + reg [`ARBITER_IBUS_WATCHDOG_TIMER_WIDTH:0] watchdog_timer; + reg wbm_stb_r; // Register strobe + wire wbm_stb_edge; // Detect its edge + reg wbm_stb_edge_r, wbm_ack_i_r; // Reg these, better timing + + always @(posedge wb_clk) + wbm_stb_r <= wbm_stb_o; + + assign wbm_stb_edge = (wbm_stb_o & !wbm_stb_r); + + always @(posedge wb_clk) + wbm_stb_edge_r <= wbm_stb_edge; + + always @(posedge wb_clk) + wbm_ack_i_r <= wbm_ack_i; + + + // Counter logic + always @(posedge wb_clk) + if (wb_rst) watchdog_timer <= 0; + else if (wbm_ack_i_r) // When we see an ack, turn off timer + watchdog_timer <= 0; + else if (wbm_stb_edge_r) // New access means start timer again + watchdog_timer <= 1; + else if (|watchdog_timer) // Continue counting if counter > 0 + watchdog_timer <= watchdog_timer + 1; + + always @(posedge wb_clk) + watchdog_err <= (&watchdog_timer); + +`else // !`ifdef ARBITER_IBUS_WATCHDOG + + always @(posedge wb_clk) + watchdog_err <= 0; + +`endif // !`ifdef ARBITER_IBUS_WATCHDOG + + + +`ifdef ARBITER_IBUS_REGISTERING + + // Master input registers + reg [wb_adr_width-1:0] wbm_adr_o_r; + reg [wb_dat_width-1:0] wbm_dat_o_r; + reg [3:0] wbm_sel_o_r; + reg wbm_we_o_r; + reg wbm_cyc_o_r; + reg wbm_stb_o_r; + reg [2:0] wbm_cti_o_r; + reg [1:0] wbm_bte_o_r; + // Slave output registers + reg [wb_dat_width-1:0] wbs0_dat_o_r; + reg wbs0_ack_o_r; + reg wbs0_err_o_r; + reg wbs0_rty_o_r; + reg [wb_dat_width-1:0] wbs1_dat_o_r; + reg wbs1_ack_o_r; + reg wbs1_err_o_r; + reg wbs1_rty_o_r; + + wire wbm_ack_i_pre_reg; + + + + // Register master input signals + always @(posedge wb_clk) + begin + wbm_adr_o_r <= wbm_adr_o; + wbm_dat_o_r <= wbm_dat_o; + wbm_sel_o_r <= wbm_sel_o; + wbm_we_o_r <= wbm_we_o; + wbm_cyc_o_r <= wbm_cyc_o; + wbm_stb_o_r <= wbm_stb_o & !wbm_ack_i_pre_reg & !wbm_ack_i;//classic + wbm_cti_o_r <= wbm_cti_o; + wbm_bte_o_r <= wbm_bte_o; + + // Slave signals + wbs0_dat_o_r <= wbs0_dat_o; + wbs0_ack_o_r <= wbs0_ack_o; + wbs0_err_o_r <= wbs0_err_o; + wbs0_rty_o_r <= wbs0_rty_o; + wbs1_dat_o_r <= wbs1_dat_o; + wbs1_ack_o_r <= wbs1_ack_o; + wbs1_err_o_r <= wbs1_err_o; + wbs1_rty_o_r <= wbs1_rty_o; + + end // always @ (posedge wb_clk) + + // Slave select + assign slave_sel[0] = wbm_adr_o_r[`WB_ARB_ADDR_MATCH_SEL] == + slave0_adr; + + assign slave_sel[1] = wbm_adr_o_r[`WB_ARB_ADDR_MATCH_SEL] == + slave1_adr; + + // Slave out assigns + assign wbs0_adr_i = wbm_adr_o_r; + assign wbs0_dat_i = wbm_dat_o_r; + assign wbs0_we_i = wbm_dat_o_r; + assign wbs0_sel_i = wbm_sel_o_r; + assign wbs0_cti_i = wbm_cti_o_r; + assign wbs0_bte_i = wbm_bte_o_r; + assign wbs0_cyc_i = wbm_cyc_o_r & slave_sel[0]; + assign wbs0_stb_i = wbm_stb_o_r & slave_sel[0]; + + assign wbs1_adr_i = wbm_adr_o_r; + assign wbs1_dat_i = wbm_dat_o_r; + assign wbs1_we_i = wbm_dat_o_r; + assign wbs1_sel_i = wbm_sel_o_r; + assign wbs1_cti_i = wbm_cti_o_r; + assign wbs1_bte_i = wbm_bte_o_r; + assign wbs1_cyc_i = wbm_cyc_o_r & slave_sel[1]; + assign wbs1_stb_i = wbm_stb_o_r & slave_sel[1]; + + // Master out assigns + // Don't care about none selected... + assign wbm_dat_i = slave_sel[1] ? wbs1_dat_o_r : + wbs0_dat_o_r ; + + assign wbm_ack_i = (slave_sel[0] & wbs0_ack_o_r) | + (slave_sel[1] & wbs1_ack_o_r) + ; + + assign wbm_err_i = (slave_sel[0] & wbs0_err_o_r) | + (slave_sel[1] & wbs1_err_o_r) | + watchdog_err; + + assign wbm_rty_i = (slave_sel[0] & wbs0_rty_o_r) | + (slave_sel[1] & wbs1_rty_o_r); + + // Non-registered ack + assign wbm_ack_i_pre_reg = (slave_sel[0] & wbs0_ack_o) | + (slave_sel[1] & wbs1_ack_o); + +`else // !`ifdef ARBITER_IBUS_REGISTERING + + // Slave select + assign slave_sel[0] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == + slave0_adr; + + assign slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == + slave1_adr; + + // Slave out assigns + assign wbs0_adr_i = wbm_adr_o; + assign wbs0_dat_i = wbm_dat_o; + assign wbs0_we_i = wbm_we_o; + assign wbs0_sel_i = wbm_sel_o; + assign wbs0_cti_i = wbm_cti_o; + assign wbs0_bte_i = wbm_bte_o; + assign wbs0_cyc_i = wbm_cyc_o & slave_sel[0]; + assign wbs0_stb_i = wbm_stb_o & slave_sel[0]; + + assign wbs1_adr_i = wbm_adr_o; + assign wbs1_dat_i = wbm_dat_o; + assign wbs1_we_i = wbm_we_o; + assign wbs1_sel_i = wbm_sel_o; + assign wbs1_cti_i = wbm_cti_o; + assign wbs1_bte_i = wbm_bte_o; + assign wbs1_cyc_i = wbm_cyc_o & slave_sel[1]; + assign wbs1_stb_i = wbm_stb_o & slave_sel[1]; + + // Master out assigns + // Don't care about none selected... + assign wbm_dat_i = slave_sel[1] ? wbs1_dat_o : + wbs0_dat_o ; + + assign wbm_ack_i = (slave_sel[0] & wbs0_ack_o) | + (slave_sel[1] & wbs1_ack_o); + + + assign wbm_err_i = (slave_sel[0] & wbs0_err_o) | + (slave_sel[1] & wbs1_err_o) | + watchdog_err; + + assign wbm_rty_i = (slave_sel[0] & wbs0_rty_o) | + (slave_sel[1] & wbs1_rty_o); + + +`endif +endmodule // arbiter_ibus + Index: generic/ft/rtl/verilog/parity_err_handler/parity_err_handler.v =================================================================== --- generic/ft/rtl/verilog/parity_err_handler/parity_err_handler.v (nonexistent) +++ generic/ft/rtl/verilog/parity_err_handler/parity_err_handler.v (revision 483) @@ -0,0 +1,91 @@ +/* + Parity error handler + + Vector of parity error indicating signals coming in. + + We issue reset if certain errors are spotted, and interrupt in the case of + others. + + This module is not intended to be synthesisable, rather to be used in + conjunction with the or1200_ft_stim testbench module. + + */ + +module parity_err_handler( + clk, + parity_err, + wb_rst, + reset, + interrupt, + wb_dat_o, + wb_ack_o, + wb_stb_i + ); + parameter parity_vector_width = 9; + parameter parity_vector_resets = 1; // Signals at or below this we reset on + + input clk; + input [parity_vector_width-1:0] parity_err; + input wb_rst; + output reset; + output reg interrupt; + output reg [7:0] wb_dat_o; + output wb_ack_o; + input wb_stb_i; + + reg reset_r; + + wire [parity_vector_width-1:0] parity_err_mask; + + assign parity_err_mask = 9'b111100000; + + // Signal a reset if signals up to the number indicated by + // parity_vector_resets go high. + always @(clk or wb_rst) + if (wb_rst) + reset_r <= 0; + else + casez(parity_err[parity_vector_width-1:0]) + //9'b????1????: reset_r <= 1; + //9'b?????1???: reset_r <= 1; + //9'b??????1??: reset_r <= 1; + //9'b???????1?: reset_r <= 1; + 9'b????????1: reset_r <= 1; + default: reset_r <= 0; + endcase // casex (parity_err[parity_vector_resets-1:0]) + + assign reset = reset_r; + + always @(posedge reset) + $display("%m: Reset due to parity error. Vect:%h",parity_err); + + + // Signal an interrupt if signals above number parity_vector_resets go high + always @(posedge clk) + begin + if (wb_rst) + interrupt <= 0; + // Simulate level sensitive interrupt - clear upon read + else if (parity_err[parity_vector_width-1:parity_vector_resets] + & ~parity_err_mask) + interrupt <= 1; + else if (wb_stb_i & wb_ack_o) + interrupt <= 0; + end + + assign wb_ack_o = wb_stb_i; + + // Data bus output to indicate which thing caused parity error + always @(posedge clk) + begin + if (wb_rst) + wb_dat_o <= 0; + else if (parity_err[parity_vector_width-1:parity_vector_resets]) + wb_dat_o <= parity_err[parity_vector_width-1:parity_vector_resets]; + else if (wb_ack_o) // Clear data after read + wb_dat_o <= 0; + end + + + +endmodule // parity_err_handler Index: generic/ft/doc/README =================================================================== --- generic/ft/doc/README (nonexistent) +++ generic/ft/doc/README (revision 483) @@ -0,0 +1,114 @@ + OR1200 with Fault Tolerance features + ==================================== + +This technology-independent build tests the OR1200's fault tolerance features, +primarily parity error detection and behavior on its various internal RAMs. + +OR1200 fault tolerance features +=============================== + +The OR1200's parity detection mechanisms are enabled by adding +"`define OR1200_RAM_PARITY" in the or1200_defines.v file. + +This enables parity detection logic on the generic technology memory +implementations (to be inerred as block RAMs by FPGA synthesis tools, ASIC flow +will have to provide custom solution) throughout the processor. + +The 5 places special control logic is added is in the instruction and data +cache modules, the instruction and data MMU TLB caches, and the register file. + +An output vector is added to the top level of the OR1200 to indicate when a +parity error is detected. + +The following behavior is exhibited when a parity error is detected in these +locations: + +Instruction cache instruction RAM: Cache line refill +Instruction cache tag RAM: Cache line refill +Data cache data RAM: Cache line refill +Data cache tag RAM: Cache line refill + +Instruction MMU TLB match register RAM: ITLB miss exception +Instruction MMU TLB translate register RAM: ITLB miss exception +Data MMU TLB match register RAM: DTLB miss exception +Data MMU TLB translate register RAM: DTLB miss exception + +Register file: Execution continues, however a parity error in the register + file is considered unrecoverable, and the OR1200 should be + reset. This is not done automatically and should be the job + of an external unit. + + +Testing System +============== + +A special test-bench set up is contained in this testbench. The software test, +or1200ft-parity, communicates with a verilog module via some memory locations +in the main RAM on the Wishbone bus, sending commands which will inject errors +into various RAMs throughout the OR1200. The software then exercises these +areas of the RAM to ensure the parity error is detected. + +ORPSoC Configuration +==================== + +ORPSoC is configured with no peripherals, just bus arbiters, and a 1MB RAM on +the Wishbone bus. + +The only additional module is the parity error handler. + +Parity Error Handler Module +=========================== + +This module is in rtl/verilog/parity_err_handler of this build's path. + +It takes the wishbone clock, a reset and the OR1200's parity error indicator +vector, and will issue a reset to the OR1200 on detection of a RF parity error, +and assert its interrupt line (to IRQ5 of OR1200's PIC) on detection of any +instruction cache parity errors. + +The interrupt is edge-triggered by the incoming parity error indicator vector +but behaves as a level-triggered interrupt source, and reading from it (it is +at address 0xe0000000 on the Wishbone data bus) will clear the pending +interrupt. + +It can be configured to reset or interrupt on any incoming parity error vector. + + +Verilog Testbench Stimulus +========================== + +The additional verilog testbench module, or1200_ft_stim, is used to inject +parity errors into specific bits and words of the various RAMs in the design, +to a simulate single event upset (SUE). + +The stimulus is controlled by the software test running on the processor. It +(the testbench) polls some unused memory locations in the RAM on the Wishbone +data bus, and communicates via very simple protocol with the processor. + +It can inject errors into all cache, MMU TLB and register file memories for +a generic technology configuration. + +See the file for more details. + +Software Test +============= + +The software test configures the various memories to contain useful data before +commanding the verilog or1200_ft_stim module to inject errors there and +accessing them again. See the file sw/tests/or1200ft/or1200ft-parity.c for +exact details. + +The software test checks every bit possible in an output word from the cache +and TLB memories,and checks every word and every bit of the register file +memories. + +Running The Test +================ + +To run the fault tolerance test, the Modelsim simulator is used by default, +but to switch back to using Icarus Verilog, run: + + boards/generic/ft/sim/run$ make rtl-test TEST=or1200ft-parity SIMULATOR=icarus + +Or to run with Modelsim, remove "SIMULATOR=icarus". + Index: generic/ft/backend/rtl/verilog/dummy.v =================================================================== Index: generic/ft/sim/run/Makefile =================================================================== --- generic/ft/sim/run/Makefile (nonexistent) +++ generic/ft/sim/run/Makefile (revision 483) @@ -0,0 +1 @@ +include ../bin/Makefile Index: generic/ft/sim/bin/Makefile =================================================================== --- generic/ft/sim/bin/Makefile (nonexistent) +++ generic/ft/sim/bin/Makefile (revision 483) @@ -0,0 +1,571 @@ +###################################################################### +#### #### +#### ORPSoCv2 Testbenches Makefile #### +#### #### +#### Description #### +#### ORPSoCv2 Testbenches Makefile, containing rules for #### +#### configuring and running different tests on the current #### +#### ORPSoC(v2) design. #### +#### #### +#### To do: #### +#### #### +#### Author(s): #### +#### - Julius Baxter, julius@opencores.org #### +#### #### +#### #### +###################################################################### +#### #### +#### Copyright (C) 2009,2010 Authors and OPENCORES.ORG #### +#### #### +#### 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, download it #### +#### from http://www.opencores.org/lgpl.shtml #### +#### #### +###################################################################### + +# Name of the directory we're currently in +CUR_DIR=$(shell pwd) + +# The root path of the whole project +PROJECT_ROOT ?=$(CUR_DIR)/../../../../.. + +DESIGN_NAME=orpsoc +RTL_TESTBENCH_TOP=$(DESIGN_NAME)_testbench + +# Hardset the board name, even though we could probably determine it +FPGA_VENDOR=generic +BOARD_NAME=ft +BOARD_DIR=$(PROJECT_ROOT)/boards/$(FPGA_VENDOR)/$(BOARD_NAME) + +# Export BOARD_PATH for the software makefiles +BOARD=$(FPGA_VENDOR)/$(BOARD_NAME) +export BOARD + +# Paths to other important parts of this test suite +COMMON_RTL_DIR = $(PROJECT_ROOT)/rtl +COMMON_RTL_VERILOG_DIR = $(COMMON_RTL_DIR)/verilog +#COMMON_RTL_VHDL_DIR = $(COMMON_RTL_DIR)/vhdl + +BOARD_RTL_DIR=$(BOARD_DIR)/rtl +BOARD_RTL_VERILOG_DIR=$(BOARD_RTL_DIR)/verilog +# Only 1 include path for board builds - their own! +BOARD_RTL_VERILOG_INCLUDE_DIR=$(BOARD_RTL_VERILOG_DIR)/include + +BOARD_BENCH_DIR=$(BOARD_DIR)/bench +BOARD_BENCH_VERILOG_DIR=$(BOARD_BENCH_DIR)/verilog +BOARD_BENCH_VERILOG_INCLUDE_DIR=$(BOARD_BENCH_VERILOG_DIR)/include + +COMMON_BENCH_DIR=$(PROJECT_ROOT) +COMMON_BENCH_VERILOG_DIR=$(COMMON_BENCH_DIR)/verilog +COMMON_BENCH_VERILOG_INCLUDE_DIR=$(COMMON_BENCH_VERILOG_DIR)/include + +# Top level files for DUT and testbench +DUT_TOP=$(BOARD_RTL_VERILOG_DIR)/$(DESIGN_NAME)_top/$(DESIGN_NAME)_top.v +BENCH_TOP=$(BOARD_BENCH_VERILOG_DIR)/$(DESIGN_NAME)_testbench.v + +# Software tests we'll run + +# Need this for individual test variables to not break +TEST ?= or1200-simple + +TESTS ?= or1200-simple or1200-cbasic or1200-dctest or1200-float or1200-mmu or1200-basic or1200-except or1200-tick or1200-ticksyscall or1200ft-parity + +# Gets turned into verilog `define +SIM_TYPE=RTL + +# Main defines file is from board include path +PROJECT_VERILOG_DEFINES=$(BOARD_RTL_VERILOG_INCLUDE_DIR)/$(DESIGN_NAME)-defines.v + +# Detect technology to use for the simulation +DESIGN_DEFINES=$(shell cat $(PROJECT_VERILOG_DEFINES) | sed s://.*::g | sed s:\`:\#:g | sed 's:^[ ]*::' | awk '{print};/^\#define/{printf "_%s=%s\n",$$2,$$2}' | grep -v PERIOD | cpp -P | sed s:^_::g | sed s:=$$::g ) + +# Rule to look at what defines are being extracted from main file +print-defines: + @echo echo; echo "\t### Design defines ###"; echo; + @echo "\tParsing "$(PROJECT_VERILOG_DEFINES)" and exporting:" + @echo $(DESIGN_DEFINES) + +print-tests: + @echo; echo; echo "\t### Software tests to be run ###"; echo; + @echo $(TESTS) + @echo + +# Simulation directories +SIM_DIR ?=$(BOARD_DIR)/sim +RTL_SIM_DIR=$(SIM_DIR) +RTL_SIM_RUN_DIR=$(RTL_SIM_DIR)/run +RTL_SIM_BIN_DIR=$(RTL_SIM_DIR)/bin +RTL_SIM_RESULTS_DIR=$(RTL_SIM_DIR)/out + +# Testbench paths +BOARD_BENCH_DIR=$(BOARD_DIR)/bench +BOARD_BENCH_VERILOG_DIR=$(BOARD_BENCH_DIR)/verilog +COMMON_BENCH_DIR=$(PROJECT_ROOT)/bench +COMMON_BENCH_VERILOG_DIR=$(COMMON_BENCH_DIR)/verilog + +#BENCH_VHDL_DIR=$(BENCH_DIR)/vhdl +# No SystemC or Verilator support for this build +#BENCH_SYSC_DIR=$(BENCH_DIR)/sysc +#BENCH_SYSC_SRC_DIR=$(BENCH_SYSC_DIR)/src +#BENCH_SYSC_INCLUDE_DIR=$(BENCH_SYSC_DIR)/include + +# Backend directories +# This one is the board build's backend dir. +BOARD_BACKEND_DIR=$(BOARD_DIR)/backend +BOARD_BACKEND_VERILOG_DIR=$(BOARD_BACKEND_DIR)/rtl/verilog +TECHNOLOGY_BACKEND_DIR=$(BOARD_DIR)/../backend +# This path is for the technology library +TECHNOLOGY_BACKEND_VERILOG_DIR=$(TECHNOLOGY_BACKEND_DIR)/rtl/verilog + +# Synthesis directory for board +BOARD_SYN_DIR=$(BOARD_DIR)/syn/synplify +BOARD_SYN_OUT_DIR=$(BOARD_SYN_DIR)/out + +# System software dir +COMMON_SW_DIR=$(PROJECT_ROOT)/sw +BOARD_SW_DIR=$(BOARD_DIR)/sw + + +# Suffix of file to check after each test for the string +TEST_OUT_FILE_SUFFIX=-general.log +TEST_OK_STRING=8000000d + +# Dynamically generated verilog file defining configuration for various things +# Rule actually generating this is found in definesgen.inc file. +TEST_DEFINES_VLG=test-defines.v +# Set V=1 when calling make to enable verbose output +# mainly for debugging purposes. +ifeq ($(V), 1) +Q= +QUIET= +else +Q ?=@ +QUIET=-quiet +endif + +# Modelsim variables +MGC_VSIM=vsim +MGC_VLOG_COMP=vlog +MGC_VHDL_COMP=vcom +MODELSIM=modelsim + +# Icarus variables +ICARUS_COMPILE=iverilog +ICARUS_RUN=vvp +ICARUS_SCRIPT=icarus.scr +ICARUS_SIM_EXE=vlogsim.elf +ICARUS=icarus + + +# Default simulator is Modelsim here as we're using the ProASIC3 +# libraries which are not compilable with Icarus. +# Set SIMULATOR=modelsim to use Modelsim (Default) +# Set SIMULATOR=ncverilog to use Cadence's NC-Verilog - TODO +# Set SIMULATOR=icarus to use Icarus Verilog (Not supported for this board) + +SIMULATOR ?= $(MODELSIM) + +# +# Modelsim-specific settings +# +VOPT_ARGS=$(QUIET) -suppress 2241 +# If VCD dump is desired, tell Modelsim not to optimise +# away everything. +ifeq ($(VCD), 1) +#VOPT_ARGS=-voptargs="+acc=rnp" +VOPT_ARGS=+acc=rnpqv +endif +# VSIM commands +# Suppressed warnings - 3009: Failed to open $readmemh() file +# Suppressed warnings - 3009: Module 'blah' does not have a `timescale directive in effect, but previous modules do. +# Suppressed warnings - 8598: Non-positive replication multiplier inside concat. Replication will be ignored +VSIM_ARGS= -suppress 7 -suppress 3009 -suppress 8598 -c $(QUIET) -do "set StdArithNoWarnings 1; run -all; exit" +# Modelsim VPI settings +ifeq ($(VPI), 1) +VPI_LIBS=$(VPI_SRC_C_DIR)/$(MODELTECH_VPILIB) +VSIM_ARGS += -pli $(VPI_SRC_C_DIR)/$(MODELTECH_VPILIB) +endif +# Rule to make the VPI library for modelsim +$(VPI_SRC_C_DIR)/$(MODELTECH_VPILIB): $(VPI_SRCS) + $(MAKE) -C $(VPI_SRC_C_DIR) $(MODELTECH_VPILIB) + +# +# Verilog DUT source variables +# + +# First consider any modules we'll use gatelevel descriptions of. +# These will have to be set on the command line +GATELEVEL_MODULES ?= + +# First we get a list of modules in the RTL path of the board's path. +# Next we check which modules not in the board's RTL path are in the root RTL +# path (modules which can be commonly instantiated, but over which board +# build-specific versions take precedence.) + +# Paths under board/***/rtl/verilog we wish to exclude when getting modules +BOARD_VERILOG_MODULES_EXCLUDE= include $(GATELEVEL_MODULES) +BOARD_VERILOG_MODULES_DIR_LIST=$(shell ls $(BOARD_RTL_VERILOG_DIR)) +# Apply exclude to list of modules +BOARD_RTL_VERILOG_MODULES=$(filter-out $(BOARD_VERILOG_MODULES_EXCLUDE),$(BOARD_VERILOG_MODULES_DIR_LIST)) + +# Rule for debugging this script +print-board-modules: + @echo echo; echo "\t### Board verilog modules ###"; echo + @echo $(BOARD_RTL_VERILOG_MODULES) + +# Now get list of modules that we don't have a version of in the board path +COMMON_VERILOG_MODULES_EXCLUDE= include +COMMON_VERILOG_MODULES_EXCLUDE += $(BOARD_RTL_VERILOG_MODULES) +COMMON_VERILOG_MODULES_EXCLUDE += $(GATELEVEL_MODULES) + +COMMON_RTL_VERILOG_MODULES_DIR_LIST=$(shell ls $(COMMON_RTL_VERILOG_DIR)) +COMMON_RTL_VERILOG_MODULES=$(filter-out $(COMMON_VERILOG_MODULES_EXCLUDE), $(COMMON_RTL_VERILOG_MODULES_DIR_LIST)) + + +# Add these to exclude their RTL directories from being included in scripts + + + +# Rule for debugging this script +print-common-modules-exclude: + @echo echo; echo "\t### Common verilog modules being excluded due to board versions ###"; echo + @echo "$(COMMON_VERILOG_MODULES_EXCLUDE)" + +print-common-modules: + @echo echo; echo "\t### Verilog modules from common RTL dir ###"; echo + @echo $(COMMON_RTL_VERILOG_MODULES) + +# List of verilog source files (only .v files!) +# Board RTL modules first +RTL_VERILOG_SRC=$(shell for module in $(BOARD_RTL_VERILOG_MODULES); do if [ -d $(BOARD_RTL_VERILOG_DIR)/$$module ]; then ls $(BOARD_RTL_VERILOG_DIR)/$$module/*.v; fi; done) +# Common RTL module source +RTL_VERILOG_SRC +=$(shell for module in $(COMMON_RTL_VERILOG_MODULES); do if [ -d $(COMMON_RTL_VERILOG_DIR)/$$module ]; then ls $(COMMON_RTL_VERILOG_DIR)/$$module/*.v; fi; done) + +# List of verilog includes from board RTL path - only for rule sensitivity +RTL_VERILOG_INCLUDES=$(shell ls $(BOARD_RTL_VERILOG_INCLUDE_DIR)/*.*) + +print-verilog-src: + @echo echo; echo "\t### Verilog source ###"; echo + @echo $(RTL_VERILOG_SRC) + +# Rules to make RTL we might need +# Expects modules, if they need making, to have their top verilog file to +# correspond to their module name, and the directory should have a make file +# and rule which works for this command. +# Add name of module to this list, currently only does verilog ones. +# Rule 'rtl' is called just before generating DUT modelsim compilation script +RTL_TO_CHECK= +rtl: + $(Q)for module in $(RTL_TO_CHECK); do \ + $(MAKE) -C $(RTL_VERILOG_DIR)/$$module $$module.v; \ + done + +# +# VHDL DUT source variables +# +# VHDL modules +#RTL_VHDL_MODULES=$(shell ls $(RTL_VHDL_DIR)) +# VHDL sources +#RTL_VHDL_SRC=$(shell for module in $(RTL_VHDL_MODULES); do if [ -d $(RTL_VHDL_DIR)/$$module ]; then ls $(RTL_VHDL_DIR)/$$module/*.vhd; fi; done) +#print-vhdl-src: +# @echo echo; echo "\t### VHDL modules and source ###"; echo +# @echo "modules: "; echo $(RTL_VHDL_MODULES); echo +# @echo "source: "$(RTL_VHDL_SRC) + +# +# Testbench source +# +BOARD_BENCH_VERILOG_SRC=$(shell ls $(BOARD_BENCH_VERILOG_DIR)/*.v | grep -v $(DESIGN_NAME)_testbench ) +BOARD_BENCH_VERILOG_SRC_FILES=$(notdir $(BOARD_BENCH_VERILOG_SRC)) + +# Now only take the source from the common path that we don't already have in +# our board's +COMMON_BENCH_VERILOG_DIR_LS=$(shell ls $(COMMON_BENCH_VERILOG_DIR)/*.v) +COMMON_BENCH_VERILOG_SRC_FILES=$(notdir $(COMMON_BENCH_VERILOG_DIR_LS)) +COMMON_BENCH_VERILOG_SRC_FILTERED=$(filter-out $(BOARD_BENCH_VERILOG_SRC_FILES) $(DESIGN_NAME)_testbench.v,$(COMMON_BENCH_VERILOG_SRC_FILES)) +COMMON_BENCH_VERILOG_SRC=$(addprefix $(COMMON_BENCH_VERILOG_DIR)/, $(COMMON_BENCH_VERILOG_SRC_FILTERED)) + +print-board-bench-src: + $(Q)echo "\tBoard bench verilog source"; \ + echo $(BOARD_BENCH_VERILOG_SRC) + +print-common-bench-src: + $(Q)echo "\Common bench verilog source"; \ + echo $(COMMON_BENCH_VERILOG_SRC) + +# Testbench source subdirectory detection (exclude include, we always use +# board bench include directory!) +BOARD_BENCH_VERILOG_SUBDIRS=$(shell cd $(BOARD_BENCH_VERILOG_DIR) && ls -d */ | grep -v include) +COMMON_BENCH_VERILOG_SUBDIRS=$(shell cd $(COMMON_BENCH_VERILOG_DIR) && ls -d */ | grep -v include) + +# Get rid of ones we have a copy of locally +COMMON_BENCH_VERILOG_SUBDIRS_EXCLUDE_BOARDS=$(filter-out $(BOARD_BENCH_VERILOG_SUBDIRS),$(COMMON_BENCH_VERILOG_SUBDIRS)) + +# Construct list of paths we will want to include +BENCH_VERILOG_SUBDIRS=$(addprefix $(COMMON_BENCH_VERILOG_DIR)/,$(COMMON_BENCH_VERILOG_SUBDIRS_EXCLUDE_BOARDS)) +BENCH_VERILOG_SUBDIRS += $(addprefix $(BOARD_BENCH_VERILOG_DIR)/,$(BOARD_BENCH_VERILOG_SUBDIRS)) + +# Finally, add include path from local bench path +BENCH_VERILOG_SUBDIRS += $(BOARD_BENCH_VERILOG_DIR)/include + +print-board-bench-subdirs: + $(Q)echo "\tBoard bench subdirectories"; \ + echo $(BOARD_BENCH_VERILOG_SUBDIRS) + +print-common-bench-subdirs: + $(Q)echo "\tCommon bench subdirectories"; \ + echo $(COMMON_BENCH_VERILOG_SUBDIRS) + +print-bench-subdirs: + $(Q)echo "\tBench subdirectories"; \ + echo $(BENCH_VERILOG_SUBDIRS) + + +# Backend technology library files +# We don't do this for the board backend stuff - that should all be properly +# named, and so we only need to pass the "-y" option for that path. +BACKEND_TECHNOLOGY_VERILOG_SRC=$(shell ls $(TECHNOLOGY_BACKEND_VERILOG_DIR)/*.v ) +BOARD_BACKEND_VERILOG_SRC=$(shell ls $(BOARD_BACKEND_VERILOG_DIR)/*.v ) + +# +# Compile script generation rules: +# + +# Modelsim library compilation rules + +# Backend script generation - make these rules sensitive to source and includes +modelsim_backend.scr: $(BOARD_BACKEND_VERILOG_SRC) + $(Q)echo "+incdir+"$(TECHNOLOGY_BACKEND_VERILOG_DIR) > $@; + $(Q)echo "-y " $(BOARD_BACKEND_VERILOG_DIR) >> $@ + $(Q)echo "+libext+.v" >> $@; + $(Q)for vsrc in $(BACKEND_TECHNOLOGY_VERILOG_SRC); do echo $$vsrc >> $@; done + $(Q)echo >> $@; + +# DUT compile script +modelsim_dut.scr: rtl $(RTL_VERILOG_SRC) $(RTL_VERILOG_INCLUDES) + $(Q)echo "+incdir+"$(BOARD_RTL_VERILOG_INCLUDE_DIR) > $@; + $(Q)echo "+incdir+"$(BOARD_BENCH_VERILOG_INCLUDE_DIR) >> $@; + $(Q)echo "+libext+.v" >> $@; + $(Q)for module in $(BOARD_RTL_VERILOG_MODULES); do if [ -d $(BOARD_RTL_VERILOG_DIR)/$$module ]; then echo "-y " $(BOARD_RTL_VERILOG_DIR)/$$module >> $@; fi; done + $(Q)for module in $(COMMON_RTL_VERILOG_MODULES); do if [ -d $(COMMON_RTL_VERILOG_DIR)/$$module ]; then echo "-y " $(COMMON_RTL_VERILOG_DIR)/$$module >> $@; fi; done + $(Q)echo "-y " $(BOARD_BACKEND_VERILOG_DIR) >> $@; + $(Q)if [ ! -z "$$GATELEVEL_MODULES" ]; \ + then echo "-y " $(BOARD_SYN_OUT_DIR) >> $@; \ + echo "+libext+.vm" >> $@; \ + fi + $(Q)echo >> $@ + +modelsim_bench.scr: $(BOARD_BENCH_VERILOG_SRC) $(COMMON_BENCH_VERILOG_SRC) + $(Q)echo "+incdir+"$(BOARD_BENCH_VERILOG_INCLUDE_DIR) > $@; + $(Q)echo "+incdir+"$(COMMON_BENCH_VERILOG_INCLUDE_DIR) >> $@; + $(Q)for path in $(BENCH_VERILOG_SUBDIRS); do echo "+incdir+"$$path >> $@; done + $(Q)for path in $(BENCH_VERILOG_SUBDIRS); do echo "-y "$$path >> $@; done + $(Q)echo "+incdir+"$(BOARD_RTL_VERILOG_INCLUDE_DIR) >> $@; + $(Q)echo "+libext+.v" >> $@; + $(Q)for vsrc in $(BOARD_BENCH_VERILOG_SRC); do echo $$vsrc >> $@; done + $(Q)for vsrc in $(COMMON_BENCH_VERILOG_SRC); do echo $$vsrc >> $@; done + $(Q)echo >> $@ + +# Modelsim library compilation rules +#BACKEND_LIB=lib_backend +BACKEND_LIB= +#$(BACKEND_LIB): modelsim_backend.scr +# $(Q)if [ ! -e $@ ]; then vlib $@; fi +# $(Q)echo; echo "\t### Compiling backend library ###"; echo +# $(Q)vlog -nologo $(QUIET) -work $@ -f $< + +# Compile DUT into "work" library +work: modelsim_dut.scr + $(Q)if [ ! -e $@ ]; then vlib $@; fi + $(Q)echo; echo "\t### Compiling Verilog design library ###"; echo + $(Q)vlog $(QUIET) -f $< $(DUT_TOP) + +# Single compile rule +.PHONY : $(MODELSIM) +$(MODELSIM): modelsim_bench.scr $(TEST_DEFINES_VLG) $(BACKEND_LIB) $(VPI_LIBS) \ + work + $(Q)echo; echo "\t### Compiling testbench ###"; echo + $(Q)vlog $(QUIET) -nologo -incr $(BENCH_TOP) -f $< +# $(Q)vopt $(QUIET) $(RTL_TESTBENCH_TOP) $(VOPT_ARGS) -L $(BACKEND_LIB) \ + -o tb + $(Q)vopt $(QUIET) $(RTL_TESTBENCH_TOP) $(VOPT_ARGS) -o tb + $(Q)echo; echo "\t### Launching simulation ###"; echo + $(Q)vsim $(VSIM_ARGS) tb + +# +# Icarus Verilog simulator build and run rules +# +.PHONY: $(ICARUS_SCRIPT) +$(ICARUS_SCRIPT): $(BOARD_BENCH_VERILOG_SRC) $(COMMON_BENCH_VERILOG_SRC) \ + $(RTL_VERILOG_SRC) $(RTL_VERILOG_INCLUDES) + $(Q)echo "# Icarus Verilog simulation script" > $@ + $(Q)echo "# Auto generated. Any alterations will be written over!" >> $@ + $(Q)echo "+incdir+"$(BOARD_RTL_VERILOG_INCLUDE_DIR) >> $@; + $(Q)echo "+libext+.v" >> $@; + $(Q)for module in $(BOARD_RTL_VERILOG_MODULES); do if [ -d $(BOARD_RTL_VERILOG_DIR)/$$module ]; then echo "-y " $(BOARD_RTL_VERILOG_DIR)/$$module >> $@; fi; done + $(Q)for module in $(COMMON_RTL_VERILOG_MODULES); do if [ -d $(COMMON_RTL_VERILOG_DIR)/$$module ]; then echo "-y " $(COMMON_RTL_VERILOG_DIR)/$$module >> $@; fi; done + $(Q)echo "-y " $(BOARD_BACKEND_VERILOG_DIR) >> $@; + $(Q)echo "+incdir+"$(BOARD_BENCH_VERILOG_INCLUDE_DIR) >> $@; + $(Q)echo "+incdir+"$(COMMON_BENCH_VERILOG_INCLUDE_DIR) >> $@; + $(Q)for path in $(BENCH_VERILOG_SUBDIRS); do echo "+incdir+"$$path >> $@; done + $(Q)for path in $(BENCH_VERILOG_SUBDIRS); do echo "-y "$$path >> $@; done + $(Q)for vsrc in $(BOARD_BENCH_VERILOG_SRC); do echo $$vsrc >> $@; done + $(Q)for vsrc in $(COMMON_BENCH_VERILOG_SRC); do echo $$vsrc >> $@; done + $(Q)echo $(BENCH_TOP) >> $@; + $(Q) echo >> $@ + +# Icarus design compilation rule +$(ICARUS_SIM_EXE): $(ICARUS_SCRIPT) $(TEST_DEFINES_VLG) + $(Q)echo; echo "\t### Compiling ###"; echo + $(Q) $(ICARUS_COMPILE) -s$(RTL_TESTBENCH_TOP) -c $< -o $@ + +# Icarus simulation run rule +$(ICARUS): $(ICARUS_SIM_EXE) $(ICARUS_VPI_LIB) + $(Q)echo; echo "\t### Launching simulation ###"; echo + $(Q) $(ICARUS_RUN) $(ICARUS_VPI_ARGS) -l ../out/$(ICARUS_RUN).log $< + + +.PHONY: rtl-test +rtl-test: clean-sim-test-sw sw clean-test-defines $(TEST_DEFINES_VLG) \ + $(SIMULATOR) + +# Run an RTL test followed by checking of generated results +rtl-test-with-check: rtl-test + $(Q)$(MAKE) check-test-log; \ + if [ $$? -ne 0 ]; then \ + echo; echo "\t### "$(TEST)" test FAIL ###"; echo; \ + else \ + echo; echo "\t### "$(TEST)" test OK ###"; echo; \ + fi + +# Do check, don't print anything out +rtl-test-with-check-no-print: rtl-test check-test-log + +# Main RTL test loop +rtl-tests: + $(Q)for test in $(TESTS); do \ + export TEST=$$test; \ + $(MAKE) rtl-test-with-check-no-print; \ + if [ $$? -ne 0 ]; then break; fi; \ + echo; echo "\t### $$test test OK ###"; echo; \ + done + + +.PHONY: check-test-log +check-test-log: + $(Q)echo "#!/bin/bash" > $@ + $(Q)echo "function check-test-log { if [ \`grep -c -i "$(TEST_OK_STRING)" "$(RTL_SIM_RESULTS_DIR)"/"$(TEST)$(TEST_OUT_FILE_SUFFIX)"\` -gt 0 ]; then return 0; else return 1; fi; }" >> $@ + $(Q)echo "check-test-log" >> $@ + $(Q)chmod +x $@ + $(Q) echo; echo "\t### Checking simulation results for "$(TEST)" test ###"; echo; + $(Q)./$@ + +# Include the test-defines.v generation rule +include $(PROJECT_ROOT)/sim/bin/definesgen.inc + +# +# Software make rules (called recursively) +# + +# Path for the current test +# First check for a local copy of the test. If it doesn't exist then we +# default to the software tests in the root directory +TEST_MODULE=$(shell echo $(TEST) | cut -d "-" -f 1) +BOARD_SW_TEST_DIR=$(BOARD_SW_DIR)/tests/$(TEST_MODULE)/sim +COMMON_SW_TEST_DIR=$(COMMON_SW_DIR)/tests/$(TEST_MODULE)/sim +# Do this by testing for the file's existence +SW_TEST_DIR=$(shell if [ -e $(BOARD_SW_TEST_DIR)/$(TEST).[cS] ]; then echo $(BOARD_SW_TEST_DIR); else echo $(COMMON_SW_TEST_DIR); fi) + +print-test-sw-dir: + @echo; echo "\tTest software is in the following path"; echo; + @echo $(BOARD_SW_DIR); echo; + @echo $(BOARD_SW_TEST_DIR); echo; + @echo $(SW_TEST_DIR); echo; + +print-sw-tests: + $(Q) $(MAKE) -C $(COMMON_SW_DIR)/lib print-sw-tests + $(Q) $(MAKE) -C $(COMMON_SW_DIR)/lib print-sw-tests-subdirs + + +# Name of the image the RAM model will attempt to load via Verilog $readmemh +# system function. + +SIM_SW_IMAGE ?=sram.vmem + +.PHONY : sw +sw: $(SIM_SW_IMAGE) + +sram.vmem: $(SW_TEST_DIR)/$(TEST).vmem + $(Q)if [ -L $@ ]; then unlink $@; fi + $(Q)ln -s $< $@ + +.PHONY: $(SW_TEST_DIR)/$(TEST).flashin +$(SW_TEST_DIR)/$(TEST).flashin: + $(Q) echo; echo "\t### Compiling software ###"; echo; + $(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).flashin + +.PHONY: $(SW_TEST_DIR)/$(TEST).vmem +$(SW_TEST_DIR)/$(TEST).vmem: + $(Q) echo; echo "\t### Compiling software ###"; echo; + $(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).vmem + +# Create test software disassembly + +sw-dis: $(SW_TEST_DIR)/$(TEST).dis + $(Q)cp -v $< . + +$(SW_TEST_DIR)/$(TEST).dis: + $(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).dis + +# +# Cleaning rules +# +clean: clean-sim clean-sim-test-sw clean-out clean-sw + +clean-sim: + $(Q) echo; echo "\t### Cleaning simulation run directory ###"; echo; + $(Q)rm -rf *.* lib_* work transcript check-test-log +# No VPI support for now. $(Q) if [ -e $(VPI_SRC_C_DIR) ]; then $(MAKE) -C $(VPI_SRC_C_DIR) clean; fi + +clean-out: + $(Q)rm -rf $(RTL_SIM_RESULTS_DIR)/*.* + +clean-test-defines: + $(Q)rm -f $(TEST_DEFINES_VLG) + +clean-sim-test-sw: + $(Q)if [ -e $(SIM_SW_IMAGE) ]; then unlink $(SIM_SW_IMAGE); fi + +clean-sw: + $(Q) echo; echo "\t### Cleaning simulation sw directories ###"; echo; + $(Q) $(MAKE) -C $(COMMON_SW_DIR)/lib distclean + +clean-rtl: + $(Q) echo; echo "\t### Cleaning generated verilog RTL ###"; echo; + for module in $(RTL_TO_CHECK); do \ + $(MAKE) -C $(RTL_VERILOG_DIR)/$$module clean; \ + done + +# Removes any checked out RTL +distclean: clean + $(Q) echo; echo "\t### Cleaning generated verilog RTL ###"; echo; + $(Q)for module in $(RTL_TO_CHECK); do \ + $(MAKE) -C $(RTL_VERILOG_DIR)/$$module distclean; \ + done Index: generic/ft/sw/tests/or1200ft/sim/or1200ft-parity.c =================================================================== --- generic/ft/sw/tests/or1200ft/sim/or1200ft-parity.c (nonexistent) +++ generic/ft/sw/tests/or1200ft/sim/or1200ft-parity.c (revision 483) @@ -0,0 +1,1035 @@ +/* + * + * Communicate with the verilog testbench via memory, send commands for it to + * inject errors to I/D cache content RAM and tag RAM, I/D MMU translate and + * match RAMs, and the register file RAM. + * + * On instruction/data cache parity error we should receive an interrupt. + * + * On I/MMU parity error we should get an TLB miss exception, causing a software + * flush before continuing. + * + * On register file parity error we reset via assertion of reset signal to + * OR1200. + * + * To allow some variables to maintain their values between resets, we store + * them in #defined memory locations. + * + * The interrupt and exception vector routines contain important code allowing + * the test to proceed, so if they don't fire (due to parity errors not being + * injected, exercised or detected properly) then the test will repeat itself + * over and over with the same values, and should be stopped by the user and + * investigated. + * + * The ft_state pointer points to the overall state of the test. + * + * Julius Baxter, julius@opencores.org + * + */ + + +#include "cpu-utils.h" +#include "spr-defs.h" +#include "printf.h" +#include "board.h" + +// define to jump to a certain test immediately +//#define JUMP_TO_TEST 3 + +#define FT_MEM 0x4 +#define FT_GO_COMMAND 0x88000000 + +#define FT_STIM_CMD_OFF 24 + +#define FT_STIM_CMD_IC_RAM_FAULT 0x1 +#define FT_STIM_CMD_IC_TAG_FAULT 0x2 +#define FT_STIM_CMD_DC_RAM_FAULT 0x3 +#define FT_STIM_CMD_DC_TAG_FAULT 0x4 + +#define FT_STIM_CMD_DMMU_MR_FAULT 0x5 +#define FT_STIM_CMD_DMMU_TR_FAULT 0x6 +#define FT_STIM_CMD_IMMU_MR_FAULT 0x7 +#define FT_STIM_CMD_IMMU_TR_FAULT 0x8 +#define FT_STIM_CMD_RF_FAULT 0x9 + +#define FT_STIM_CMD_DEBUG_ON (0xff<> SPR_DMMUCFGR_NTS_OFF); + + + + // Initialise all match/translate register pairs, set 1-1 mapping + for (i = 0; i < ways; i++) + for (j = 0; j < sets; j++){ + mtspr (SPR_DTLBMR_BASE(i) + j, (j*PAGE_SIZE) | + SPR_DTLBMR_V); + mtspr (SPR_DTLBTR_BASE(i) + j, (j*PAGE_SIZE) | + DTLB_PR_NOLIMIT); + } + + // Set cache inhibit for first page + mtspr (SPR_DTLBTR_BASE(0), 0 | DTLB_PR_NOLIMIT | SPR_DTLBTR_CI); + +} + + +// If DC is present, init DMMU to disable cache on first page, which we'll +// use to communicate to the fault injection testbench. +int +dmmu_init(void) +{ + + unsigned long upr; + + // Only do this if DMMU and DC are here + + // Get the unit present register + upr = mfspr(SPR_UPR); + if ((upr & SPR_UPR_DCP) && !(upr & SPR_UPR_DMP)) + // Cannot do the test + exit(1); + + if (!(upr & SPR_UPR_DCP)) + // No need to config MMU - no data cache + return 1; + + dmmu_tlb_one_to_one_reset(); + + /* Enable DMMU */ + lo_dmmu_en (); + + return 0; + +} + +// Initialise iMMU +void +immu_tlb_one_to_one_reset(void) +{ + + int i, j, sets, ways; + unsigned long immucfgr; + + // Determine number of TLB sets + immucfgr = mfspr(SPR_IMMUCFGR); + + ways = (immucfgr & SPR_IMMUCFGR_NTW) + 1; + sets = 1 << ((immucfgr & SPR_IMMUCFGR_NTS)>> SPR_IMMUCFGR_NTS_OFF); + + // Initialise all match/translate register pairs, set 1-1 mapping + for (i = 0; i < ways; i++) + for (j = 0; j < sets; j++){ + mtspr (SPR_ITLBMR_BASE(i) + j, (j*PAGE_SIZE) | + SPR_ITLBMR_V); + mtspr (SPR_ITLBTR_BASE(i) + j, (j*PAGE_SIZE) | + ITLB_PR_NOLIMIT); + } +} + +void +test_state_update(void) +{ + volatile int * test_state1 = (volatile int*)FT_STATE_TEST_STATE1_MEM; + volatile int * test_state2 = (volatile int*)FT_STATE_TEST_STATE2_MEM; + volatile int * test_state3 = (volatile int*)FT_STATE_TEST_STATE3_MEM; + volatile int * ft_state = (volatile int*)FT_STATE_RECORD_MEM; + + // Disable DC here + mtspr(SPR_SR, (mfspr(SPR_SR) & ~SPR_SR_DCE)); + // Flush line of test state + mtspr(SPR_DCBIR, (unsigned long) test_state1); + + (*test_state1)++; + + if (*test_state1 == *test_state2) + (*ft_state)++; + +} + +// Initialise TLB contents and enable iMMU +int +immu_init(void) +{ + + int i, j, sets, ways; + unsigned long upr; + unsigned long immucfgr; + + // Only do this if iMMU here + + // Get the unit present register + upr = mfspr(SPR_UPR); + if (!(upr & SPR_UPR_IMP)) + return 1; + + immu_tlb_one_to_one_reset(); + + /* Enable IMMU */ + lo_immu_en (); + + return 0; +} + +void +itlb_miss_handler (void) +{ + // This was probably cause by injection of parity error + // We just reset iTLB in event of miss + printf("iTLB miss handler resetting iTLB\n"); + + immu_tlb_one_to_one_reset(); + + test_state_update(); + +} + +void +dtlb_miss_handler (void) +{ + // This was probably cause by injection of parity error + // We just reset iTLB in event of miss + printf("dTLB miss handler resetting iTLB\n"); + + dmmu_tlb_one_to_one_reset(); + + test_state_update(); + +} + + +unsigned long +inline inline_mfspr(unsigned long spr) +{ + unsigned long value; + asm("l.mfspr\t\t%0,%1,0" : "=r" (value) : "r" (spr)); + return value; +} + +void +parity_error_interrupt(void) +{ + // Read parity error indicator. Reading also clears interrupt line. + char parerr = REG8(PARERR_BASE); + + printf("Parity error interrupt: 0x%02x\n",parerr); + + test_state_update(); + + // Clear iTLB + //immu_tlb_one_to_one_reset(); + + return; +} + + +void +dummy_function() +{ + volatile int i; + + report(0xdfdfdfdf); + + for(i=0;i<64;i++); + + return; +} + +void +copy_function(void *insn_area, void* dummy_function, int nwords) +{ + int i; + unsigned long *p1 = (unsigned long *)insn_area; + unsigned long *p2 = (unsigned long *)dummy_function; + for (i = 0; i < nwords; i++) + p1[i] = p2[i]; +} + + +void +ic_test_setup() +{ + //Initialise handler vector + int_init(); + int_add(PARERR_IRQ, parity_error_interrupt, 0); + + // Enable interrupts in supervisor register + cpu_enable_user_interrupts(); +} + + +void +dc_test_setup() +{ + //Initialise handler vector + int_init(); + int_add(PARERR_IRQ, parity_error_interrupt, 0); + + // Enable interrupts in supervisor register + cpu_enable_user_interrupts(); +} + + +int +dmmu_test_setup(unsigned long data_location) +{ + unsigned long mmucfgr; + int mmu_tlb_reg, mmusets; + + // Determine number of mmusets + mmucfgr = mfspr (SPR_DMMUCFGR); + mmusets = 1 << ((mmucfgr & SPR_DMMUCFGR_NTS)>> + SPR_DMMUCFGR_NTS_OFF); + // Now get TLB register that will be used when matching/translating + // VA for page dummy_function() is in. + + mmu_tlb_reg = (data_location / PAGE_SIZE) % mmusets; + report (data_location); + report (mmu_tlb_reg); + + // Enable interrupts and install handler. Error will trigger + // an interrupt. + + //Initialise handler vector + int_init(); + int_add(PARERR_IRQ, parity_error_interrupt, 0); + + // Add handler for dTLB miss (parity error may show up as + // miss.) + add_handler(0x9, dtlb_miss_handler); + + // Enable interrupts in supervisor register + cpu_enable_user_interrupts(); + + return mmu_tlb_reg; + +} + + + +int +immu_test_setup(void) +{ + unsigned long mmucfgr; + int mmu_tlb_reg, mmusets; + + // Determine number of mmusets + mmucfgr = mfspr(SPR_IMMUCFGR); + mmusets = 1 << ((mmucfgr & SPR_IMMUCFGR_NTS)>> + SPR_IMMUCFGR_NTS_OFF); + // Now get TLB register that will be used when matching/translating + // VA for page dummy_function() is in. + + mmu_tlb_reg = ((unsigned long)dummy_function / PAGE_SIZE) % mmusets; + + report(mmu_tlb_reg); + + // Enable interrupts and install handler. Error will trigger + // an interrupt. + + // iMMU parity errors trigger both a miss and the parity interrupt, but + // for now we'll just have the miss vector do the handling + + //Initialise handler vector + //int_init(); + //int_add(PARERR_IRQ, parity_error_interrupt, 0); + // Enable interrupts in supervisor register + //cpu_enable_user_interrupts(); + + // Add handler for iTLB miss (parity error may show up as + // miss.) + add_handler(0xa, itlb_miss_handler); + + + return mmu_tlb_reg; +} + + +void +gpr_test(int reg, int bit_number) +{ + + switch(reg) + { + case 0: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r0"); + + break; + + case 1: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r1"); + + break; + + case 2: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r2"); + + break; + + case 3: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r3"); + + break; + + case 4: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r4"); + + break; + + case 5: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r5"); + + break; + + case 6: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r6"); + + break; + + case 7: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r7"); + + break; + + case 8: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r8"); + + break; + + case 9: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r9"); + + break; + + case 10: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r10"); + + break; + + case 11: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r11"); + + break; + + case 12: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r12"); + + break; + + case 13: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r13"); + + break; + + case 14: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r14"); + + break; + + case 15: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r15"); + + break; + + case 16: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r16"); + + break; + + case 17: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r17"); + + break; + + case 18: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r18"); + + break; + + case 19: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r19"); + + break; + + case 20: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r20"); + + break; + + case 21: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r21"); + + break; + + case 22: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r22"); + + break; + + case 23: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r23"); + + break; + + case 24: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r24"); + + break; + + case 25: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r25"); + + break; + + case 26: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r26"); + + break; + + case 27: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r27"); + + break; + + case 28: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r28"); + + break; + + case 29: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r29"); + + break; + + case 30: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r30"); + + break; + + case 31: + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_RF_FAULT,bit_number, reg); + FT_STIM_WAIT_ACK; + __asm__ ("l.add r23, r24, r31"); + break; + } +} + + +int main(void) +{ + + unsigned long cachecfgr, mmucfgr; + int cachebs, cachesets, cachesize; + int mmusets; + unsigned long * stack_ptr; + unsigned long * data_area; + unsigned long * insn_area; + int mmu_mr, mmu_tr; + int bit_number, word_number; + + printf("\nParity Error Test Restart\n"); + + // Setup DMMU with cache disable on first page + dmmu_init(); + + // This ft_state variable should retain its value between resets, as + // we'll always store it back to its memory location when accessing it. + volatile int * ft_state = (volatile int*)FT_STATE_RECORD_MEM; + + volatile int * test_state1 = (volatile int*)FT_STATE_TEST_STATE1_MEM; + volatile int * test_state2 = (volatile int*)FT_STATE_TEST_STATE2_MEM; + + + printf("Test state %d\n",*ft_state); + +restart_tests: + + switch(*ft_state) + { + case 0: + printf("State %d: Test initialisation\n", *ft_state); + + // Kickoff - tell testbench stimulus to start + printf("Writing GO command\n"); + FT_STIM_WRITE(FT_GO_COMMAND); + (*ft_state)++; + FT_STIM_WAIT_ACK; + +#ifdef JUMP_TO_TEST + *ft_state = JUMP_TO_TEST; + goto restart_tests; +#endif + + // No break, fall through to case 1 + case 1: + printf("\nState %d: IC instruction memory test\n", *ft_state); + + // IC instruction RAM fault injection. + + ic_test_setup(); + + // Determine cache configuration + cachecfgr = inline_mfspr(SPR_ICCFGR); + // What is block size + cachebs = (cachecfgr & SPR_ICCFGR_CBS) ? 32 : 16; + + cachesets = (1 << ((cachecfgr & SPR_ICCFGR_NCS)>> + SPR_ICCFGR_NCS_OFF)); + + // *ft_state increments when *test_state1 == *test_state2 + *test_state1 = 0; + *test_state2 = 32; + + word_number = (((unsigned long)dummy_function >> 2) % + cachesets); + report((unsigned long) dummy_function); + report(word_number); + + // Call a function, so it's cached, inject an error into + // the cache instruction RAM location where the first + // instruction of that function is located, and call it again. + // This should trip the parity error, and the interrupt. + + while(*ft_state == 1) + { + dummy_function(); + + bit_number = *test_state1; + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_IC_RAM_FAULT, + bit_number, word_number); + + FT_STIM_WAIT_ACK; + + dummy_function(); + + } + case 2: + printf("\nState %d: IC tag memory test\n", *ft_state); + // IC tag RAM fault injection. + + ic_test_setup(); + + // Determine cache configuration + cachecfgr = inline_mfspr(SPR_ICCFGR); + // What is block size + cachebs = (cachecfgr & SPR_ICCFGR_CBS) ? 32 : 16; + + cachesets = (1 << ((cachecfgr & SPR_ICCFGR_NCS)>> + SPR_ICCFGR_NCS_OFF)); + + cachesize = cachebs * cachesets; + + // Same as above, but this time for the tag RAM. + + // *ft_state increments when *test_state1 == *test_state2 + *test_state1 = 0; + *test_state2 = 24; + + // Calculate word in tag RAM + word_number = (((unsigned long)dummy_function % + cachesize ) / cachebs) ; + + while(*ft_state == 2) + { + dummy_function(); + bit_number = *test_state1; + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_IC_TAG_FAULT, + bit_number, word_number); + + FT_STIM_WAIT_ACK; + + dummy_function(); + + } + case 3: + // DC data RAM fault injection + printf("\nState %d: DC data memory test\n", *ft_state); + + dc_test_setup(); + + // Read a far off data address (outside first MMU page, at + // least), determine it's cache line, inject a fault and read + // it again. + // Set up stack pointer variable, so we know where top of + // stack is. + stack_ptr = (unsigned long*)&_stack; + + // Put test area one page past it: + data_area = stack_ptr; + data_area += PAGE_SIZE; + + // Report address + report((unsigned long)data_area); + // Write a test variable there + *data_area = 0xea5ecafe; + + // Determine cache set up + cachecfgr = inline_mfspr(SPR_DCCFGR); + // What is block size + cachebs = (cachecfgr & SPR_DCCFGR_CBS) ? 32 : 16; + + cachesets = (1 << ((cachecfgr & SPR_DCCFGR_NCS)>> + SPR_DCCFGR_NCS_OFF)); + + cachesize = cachebs * cachesets; + + // Calculate address of word in DC RAM + word_number = (((unsigned long)data_area % cachesize) >> 2); + + // *ft_state increments when *test_state1 == *test_state2 + *test_state1 = 0; + *test_state2 = 32; + + while(*ft_state == 3) + { + + // Read the location, to cache it, or trigger read + // from cache + report(*data_area); + bit_number = *test_state1; + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_DC_RAM_FAULT, + bit_number, word_number); + + FT_STIM_WAIT_ACK; + + //report(*data_area); + + + } + case 4: + printf("\nState %d: DC tag memory test\n", *ft_state); + + dc_test_setup(); + + // Same set up as data cache RAM test. + stack_ptr = (unsigned long*)&_stack; + + // Put test area one page past it: + data_area = stack_ptr; + data_area += PAGE_SIZE; + + // Report address + report((unsigned long)data_area); + // Write a test variable there + *data_area = 0xea5ecafe; + + // Determine cache set up + cachecfgr = inline_mfspr(SPR_DCCFGR); + // What is block size + cachebs = (cachecfgr & SPR_DCCFGR_CBS) ? 32 : 16; + + cachesets = (1 << ((cachecfgr & SPR_DCCFGR_NCS)>> + SPR_DCCFGR_NCS_OFF)); + + cachesize = cachebs * cachesets; + + // Calculate address of word in DC RAM + word_number = (((unsigned long)data_area % cachesize)/cachebs); + + // *ft_state increments when *test_state1 == *test_state2 + *test_state1 = 0; + *test_state2 = 24; + + while(*ft_state == 4) + { + + // Read the location, to cache it, or trigger read + // from cache + report(*data_area); + bit_number = *test_state1; + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_DC_TAG_FAULT, + bit_number, word_number); + FT_STIM_WAIT_ACK; + + report(*data_area); + + } + case 5: + // Instruction MMU TLB match register corruption test + // Parity error should just trigger an interrupt, not + // reset the system + printf("\nState %d: IMMU match register memory test\n", + *ft_state); + + if (immu_init()) + { + + printf("\nSkipping test %d - no iMMU present\n", + *ft_state); + (*ft_state)++; + goto restart_tests; + } + + mmu_mr = immu_test_setup(); + + *test_state1 = 0; + *test_state2 = 16; + + while (*ft_state==5) + { + bit_number = *test_state1; + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_IMMU_MR_FAULT, + bit_number, mmu_mr); + FT_STIM_WAIT_ACK; + + dummy_function(); + } + + + + case 6: + // Instruction MMU TLB match register corruption test + // Should just trigger interrupt, not reset. + printf("\nState %d: IMMU translate register memory test\n", + *ft_state); + if (immu_init()) + { + + printf("\nSkipping test %d - no iMMU present\n", + *ft_state); + (*ft_state)++; + goto restart_tests; + } + + mmu_tr = immu_test_setup(); + + *test_state1 = 0; + *test_state2 = 24; + + while (*ft_state==6) + { + bit_number = *test_state1; + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_IMMU_TR_FAULT, + bit_number, mmu_mr ); + FT_STIM_WAIT_ACK; + + dummy_function(); + } + + case 7: + // Data MMU TLB match register corruption test + // Parity error should just trigger an interrupt, not + // reset the system + printf("\nState %d: DMMU match register memory test\n", + *ft_state); + + if (dmmu_init()) + { + + printf("\nSkipping test %d - no dMMU present\n", + *ft_state); + (*ft_state)++; + goto restart_tests; + } + + // Choose address for test + data_area = stack_ptr; + data_area += PAGE_SIZE; + + *data_area = 0xeaaaa51e; + + mmu_mr = dmmu_test_setup((unsigned long) data_area); + + *test_state1 = 0; + *test_state2 = 16; + + while (*ft_state==7) + { + bit_number = *test_state1; + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_DMMU_MR_FAULT, + bit_number, mmu_mr ); + FT_STIM_WAIT_ACK; + + report (*data_area); + } + + case 8: + // Data MMU TLB translate register corruption test + // Parity error should just trigger an interrupt, not + // reset the system + printf("\nState %d: DMMU translate register memory test\n", + *ft_state); + + if (dmmu_init()) + { + + printf("\nSkipping test %d - no dMMU present\n", + *ft_state); + (*ft_state)++; + goto restart_tests; + } + + // Choose address for test + data_area = stack_ptr; + data_area += (PAGE_SIZE<<2); + + *data_area = 0xdeadc0de; + + mmu_tr = dmmu_test_setup((unsigned long) data_area); + + *test_state1 = 0; + *test_state2 = 24; + + while (*ft_state==8) + { + bit_number = *test_state1; + FT_STIM_WRITE_FAULT_CMD(FT_STIM_CMD_DMMU_TR_FAULT, + bit_number, mmu_tr ); + FT_STIM_WAIT_ACK; + + report (*data_area); + } + + // Sometimes the interrupt triggers twice here, meaning + // ft_state was incremented twice. So manually put it back, + // just in case. + *ft_state = 9; + + case 9: + printf("\nState %d: Register file memory test\n", + *ft_state); + + // Inject an error into a reg, then schedule an instruction to + // read it. + (*ft_state)++; + + // initialise variables here + *test_state1 = -1; // Bit number + *test_state2 = 0; // GPR number + + case 10: + // Sit in this state to do the tests + (*test_state1)++; + + if (*test_state1 == 32) + { + (*test_state2)++; + *test_state1 = 0; + + if (*test_state2 == 32) + (*ft_state)++; + } + + bit_number = *test_state1; + + while (*ft_state==10) + { + gpr_test(*test_state2,bit_number); + } + + case 11: + printf("Tests done\n"); + report(0x8000000d); + return 0; + default: + // Shouldn't be here. ft_state somhow got corrupted. + exit(1); + break; + } + + return 0; +} Index: generic/ft/sw/tests/or1200ft/sim/Makefile =================================================================== --- generic/ft/sw/tests/or1200ft/sim/Makefile (nonexistent) +++ generic/ft/sw/tests/or1200ft/sim/Makefile (revision 483) @@ -0,0 +1,14 @@ + +BOARD_SW_ROOT=../../.. + +include $(BOARD_SW_ROOT)/Makefile.inc + +%.dis: %.elf + $(Q)$(OR32_OBJDUMP) -d $< > $@ + +%.bin: %.elf + $(Q)$(OR32_OBJCOPY) -O binary $< $@ + +clean: + $(Q)rm -f *.elf *.bin *.vmem *.flashin *.dis + Index: generic/ft/sw/Makefile.inc =================================================================== --- generic/ft/sw/Makefile.inc (nonexistent) +++ generic/ft/sw/Makefile.inc (revision 483) @@ -0,0 +1,24 @@ + +# Expecting BOARD_SW_ROOT already set to indicate how far below directory we're +# in the board's software root path is. + +# Root from the board's sw/ path +PROJ_ROOT=../../../.. + +# Figure out actual path the common software directory +SW_ROOT=$(BOARD_SW_ROOT)/$(PROJ_ROOT)/sw + +# Set the BOARD +BOARD=generic/ft + +# Set RTL_VERILOG_INCLUDE_DIR so software +RTL_VERILOG_INCLUDE_DIR=$(shell pwd)/$(BOARD_SW_ROOT)/../rtl/verilog/include + +# Set the processor capability flags +#MARCH_FLAGS =-mhard-mul -mhard-div -msoft-float +MARCH_FLAGS =-mhard-mul -msoft-div -msoft-float +export MARCH_FLAGS + +# Finally include the main software include file + +include $(SW_ROOT)/Makefile.inc Index: generic/ft/sw/board/include/board.h =================================================================== --- generic/ft/sw/board/include/board.h (nonexistent) +++ generic/ft/sw/board/include/board.h (revision 483) @@ -0,0 +1,26 @@ +#ifndef _BOARD_H_ +#define _BOARD_H_ + +#define IN_CLK 50000000 // Hz + + +// +// Defines for each core (memory map base, OR1200 interrupt line number, etc.) +// +#define RAM_BASE 0x00000000 +#define RAM_SIZE 0x00100000 + + +// Parity error indicator module. Simple one for this build +#define PARERR_BASE 0xe0000000 +// Parity error generator IRQ - just for this test design +#define PARERR_IRQ 5 + + + +// +// OR1200 tick timer period define +// +#define TICKS_PER_SEC 100 + +#endif

powered by: WebSVN 2.1.0

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