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
    /
    from Rev 482 to Rev 483
    Reverse comparison

Rev 482 → Rev 483

/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_cpu.v
86,6 → 86,11
// SPR interface
supv, spr_addr, spr_dat_cpu, spr_dat_pic, spr_dat_tt, spr_dat_pm,
spr_dat_dmmu, spr_dat_immu, spr_dat_du, spr_cs, spr_we, mtspr_dc_done
 
`ifdef OR1200_RAM_PARITY
,p_err_rf
`endif
);
 
parameter dw = `OR1200_OPERAND_WIDTH;
207,6 → 212,14
input sig_tick;
 
//
// Register file parity error indicator
//
`ifdef OR1200_RAM_PARITY
output p_err_rf;
`endif
//
// Internal wires
//
wire [31:0] if_insn;
531,6 → 544,9
or1200_rf or1200_rf(
.clk(clk),
.rst(rst),
`ifdef OR1200_RAM_PARITY
.p_err(p_err_rf),
`endif
.cy_we_i(cy_we_alu),
.cy_we_o(cy_we_rf),
.supv(sr[`OR1200_SR_SM]),
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_immu_top.v
69,6 → 69,11
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
 
// QMEM i/f
qmemimmu_rty_i, qmemimmu_err_i, qmemimmu_tag_i, qmemimmu_adr_o, qmemimmu_cycstb_o, qmemimmu_ci_o
);
122,6 → 127,10
output mbist_so_o;
`endif
 
`ifdef OR1200_RAM_PARITY
output [1:0] p_err;
`endif
//
// IC I/F
//
158,7 → 167,8
reg dis_spr_access_frst_clk;
reg dis_spr_access_scnd_clk;
`endif
 
reg [31:0] spr_dat_reg;
//
// Implemented bits inside match and translate registers
//
172,6 → 182,9
// 2 bits for protection
// 1 bit for cache inhibit
 
 
assign icpu_adr_boot = `OR1200_BOOT_ADR;
//
// icpu_adr_o
//
180,7 → 193,7
// default value
if (rst == `OR1200_RST_VALUE) begin
// select async. value due to reset state
icpu_adr_default <= 32'h0000_0100;
icpu_adr_o <= 32'h0000_0100;
icpu_adr_select <= 1'b1;
end
// selected value (different from default) is written
187,27 → 200,13
// into FF after reset state
else if (icpu_adr_select) begin
// dynamic value can only be assigned to FF out of reset!
icpu_adr_default <= icpu_adr_boot;
icpu_adr_o <= icpu_adr_boot;
// select FF value
icpu_adr_select <= 1'b0;
end
else begin
icpu_adr_default <= icpu_adr_i;
icpu_adr_o <= icpu_adr_i;
end
 
// select async. value for boot address after reset - PC jumps to the address
// selected after boot!
//assign icpu_adr_boot = {(boot_adr_sel_i ? `OR1200_EXCEPT_EPH1_P :
// `OR1200_EXCEPT_EPH0_P), 12'h100} ;
assign icpu_adr_boot = `OR1200_BOOT_ADR; // jb
 
always @(icpu_adr_boot or icpu_adr_default or icpu_adr_select)
if (icpu_adr_select)
// async. value is selected due to reset state
icpu_adr_o = icpu_adr_boot ;
else
// FF value is selected 2nd clock after reset state
icpu_adr_o = icpu_adr_default ;
`else
Unsupported !!!
`endif
220,8 → 219,8
assign page_cross = icpu_adr_i[31:`OR1200_IMMU_PS] != icpu_vpn_r;
 
//
// Register icpu_adr_i's VPN for use when IMMU is not enabled but PPN is expected to come
// one clock cycle after offset part.
// Register icpu_adr_i's VPN for use when IMMU is not enabled but PPN is
// expected to come one clock cycle after offset part.
//
always @(posedge clk or `OR1200_RST_EVENT rst)
if (rst == `OR1200_RST_VALUE)
244,6 → 243,10
`ifdef OR1200_BIST
assign mbist_so_o = mbist_si_i;
`endif
`ifdef OR1200_RAM_PARITY
assign p_err = 0;
`endif
`else
 
//
292,7 → 295,8
// OR1200_ITAG_TE - TLB miss Exception
// OR1200_ITAG_PE - Page fault Exception
//
assign icpu_tag_o = miss ? `OR1200_ITAG_TE : fault ? `OR1200_ITAG_PE : qmemimmu_tag_i;
assign icpu_tag_o = miss ? `OR1200_ITAG_TE :
fault ? `OR1200_ITAG_PE : qmemimmu_tag_i;
 
//
// icpu_rty_o
304,7 → 308,11
//
// icpu_err_o
//
assign icpu_err_o = miss | fault | qmemimmu_err_i;
assign icpu_err_o = miss | fault | qmemimmu_err_i
`ifdef OR1200_RAM_PARITY
| (|p_err)
`endif
;
 
//
// Assert itlb_en_r after one clock cycle and when there is no
314,7 → 322,7
if (rst == `OR1200_RST_VALUE)
itlb_en_r <= 1'b0;
else
itlb_en_r <= itlb_en & ~itlb_spr_access;
itlb_en_r <= itlb_en & ~itlb_spr_access;
 
//
// ITLB lookup successful
322,12 → 330,13
assign itlb_done = itlb_en_r & ~page_cross;
 
//
// Cut transfer when access (mtspr/mfspr) to/from ITLB occure or if something goes
// wrong with translation. If IC is disabled, use delayed signals.
// Cut transfer when access (mtspr/mfspr) to/from ITLB occurs or if something
// goes wrong with translation. If IC is disabled, use delayed signals.
//
// assign qmemimmu_cycstb_o = (!ic_en & immu_en) ? ~(miss | fault) & icpu_cycstb_i & ~page_cross : (miss | fault) ? 1'b0 : icpu_cycstb_i & ~page_cross; // DL
//assign qmemimmu_cycstb_o = immu_en ? ~(miss | fault) & icpu_cycstb_i & ~page_cross & itlb_done : icpu_cycstb_i & ~page_cross;
assign qmemimmu_cycstb_o = immu_en ? ~(miss | fault) & icpu_cycstb_i & ~page_cross & itlb_done & ~itlb_spr_access : icpu_cycstb_i & ~page_cross;
assign qmemimmu_cycstb_o = immu_en ?
~(miss | fault) & icpu_cycstb_i & ~page_cross &
itlb_done & ~itlb_spr_access :
icpu_cycstb_i & ~page_cross;
 
//
// Cache Inhibit
337,8 → 346,6
// assign qmemimmu_ci_o = immu_en ? itlb_done & itlb_ci : `OR1200_IMMU_CI;
// However this causes an async combinatorial loop so we stick to
// no cache inhibit.
//assign qmemimmu_ci_o = `OR1200_IMMU_CI;
// Cache inhibit without an async combinatorial loop
assign qmemimmu_ci_o = immu_en ? itlb_ci : `OR1200_IMMU_CI;
 
 
346,10 → 353,10
// Physical address is either translated virtual address or
// simply equal when IMMU is disabled
//
//assign qmemimmu_adr_o = itlb_done ? {itlb_ppn, icpu_adr_i[`OR1200_IMMU_PS-1:0]} : {icpu_vpn_r, icpu_adr_i[`OR1200_IMMU_PS-1:0]}; // DL: immu_en
assign qmemimmu_adr_o = immu_en & itlb_done ? {itlb_ppn, icpu_adr_i[`OR1200_IMMU_PS-1:2], 2'h0} : {icpu_vpn_r, icpu_adr_i[`OR1200_IMMU_PS-1:2], 2'h0};
assign qmemimmu_adr_o = immu_en & itlb_done ?
{itlb_ppn, icpu_adr_i[`OR1200_IMMU_PS-1:2], 2'h0} :
{icpu_vpn_r, icpu_adr_i[`OR1200_IMMU_PS-1:2], 2'h0};
 
reg [31:0] spr_dat_reg;
//
// Output to SPRS unit
//
367,8 → 374,8
// Page fault exception logic
//
assign fault = itlb_done &
( (!supv & !itlb_uxe) // Execute in user mode not enabled
|| (supv & !itlb_sxe)); // Execute in supv mode not enabled
((!supv & !itlb_uxe) // Execute in user mode not enabled
|| (supv & !itlb_sxe));// Execute in supv mode not en.
 
//
// TLB Miss exception logic
404,6 → 411,10
.mbist_ctrl_i(mbist_ctrl_i),
`endif
 
`ifdef OR1200_RAM_PARITY
.p_err(p_err),
`endif
 
// SPR access
.spr_cs(itlb_spr_access),
.spr_write(spr_write),
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_ic_tag.v
63,6 → 63,11
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
// Internal i/f
addr, en, we, datain, tag_v, tag
);
89,6 → 94,15
output mbist_so_o;
`endif
 
`ifdef OR1200_RAM_PARITY
parameter tag_ram_extra_width = 24 - `OR1200_ICTAG_W;
output p_err;
wire [24-2:0] tag_wire;
`else
wire [dw-2:0] tag_wire;
`endif
//
// Internal i/f
//
97,8 → 111,9
input we;
input [dw-1:0] datain;
output tag_v;
output [dw-2:0] tag;
output [dw-2:0] tag;
 
`ifdef OR1200_NO_IC
 
//
109,9 → 124,15
`ifdef OR1200_BIST
assign mbist_so_o = mbist_si_i;
`endif
`ifdef OR1200_RAM_PARITY
assign p_err = 0;
`endif
 
`else
 
assign tag = tag_wire[dw-2:0];
//
// Instantiation of TAG RAM block
//
118,7 → 139,11
or1200_spram #
(
.aw(`OR1200_ICTAG),
`ifdef OR1200_RAM_PARITY
.dw(24)
`else
.dw(`OR1200_ICTAG_W)
`endif
)
ic_tag0
(
129,15 → 154,18
.mbist_ctrl_i(mbist_ctrl_i),
`endif
.clk(clk),
.rst(rst),
.ce(en),
.we(we),
//.oe(1'b1),
.addr(addr),
`ifdef OR1200_RAM_PARITY
.p_err(p_err),
.di({{tag_ram_extra_width{1'b0}},datain}),
`else
.di(datain),
.doq({tag, tag_v})
`ifdef OR1200_RAM_PARITY
, .p_err()
`endif
.doq({tag_wire, tag_v})
);
`endif
 
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_ic_ram.v
63,6 → 63,11
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
// Internal i/f
addr, en, we, datain, dataout
);
90,6 → 95,10
output mbist_so_o;
`endif
 
`ifdef OR1200_RAM_PARITY
output p_err;
`endif
`ifdef OR1200_NO_IC
 
//
100,6 → 109,10
assign mbist_so_o = mbist_si_i;
`endif
 
`ifdef OR1200_RAM_PARITY
assign p_err = 0;
`endif
 
`else
 
//
118,6 → 131,10
.mbist_so_o(mbist_so_o),
.mbist_ctrl_i(mbist_ctrl_i),
`endif
`ifdef OR1200_RAM_PARITY
.p_err(p_err),
`endif
.rst(rst),
.clk(clk),
.ce(en),
.we(we[0]),
125,9 → 142,6
.addr(addr),
.di(datain),
.doq(dataout)
`ifdef OR1200_RAM_PARITY
, .p_err()
`endif
);
`endif
 
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_parity_chk.v
61,8 → 61,10
input [dw-1:0] d_i; // Data word in
input p_i; // Parity bit in
output err_o; // Error indicator out
assign err_o = ((^d_i[dw-1:0]) != p_i);
 
// Is nice if X's don't propegate through here during simulation, so use
// !==
assign err_o = ((^d_i[dw-1:0]) !== p_i);
 
endmodule // or1200_parity_chk
 
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_dmmu_tlb.v
69,6 → 69,11
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
// SPR access
spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
);
108,6 → 113,10
output mbist_so_o;
`endif
 
`ifdef OR1200_RAM_PARITY
output [1:0] p_err;
`endif
//
// SPR access
//
126,7 → 135,11
wire tlb_mr_en;
wire tlb_mr_we;
wire [`OR1200_DTLBMRW-1:0] tlb_mr_ram_in;
`ifdef OR1200_RAM_PARITY
wire [`OR1200_DTLBMRW-1+2:0] tlb_mr_ram_out;
`else
wire [`OR1200_DTLBMRW-1:0] tlb_mr_ram_out;
`endif
wire tlb_tr_en;
wire tlb_tr_we;
wire [`OR1200_DTLBTRW-1:0] tlb_tr_ram_in;
142,6 → 155,11
assign mbist_so_o = mbist_tr_so;
`endif
 
`ifdef OR1200_RAM_PARITY
wire [1:0] p_err_wire;
reg p_err_en;
`endif
//
// Implemented bits inside match and translate registers
//
187,7 → 205,7
//
// Assign outputs from Match registers
//
assign {vpn, v} = tlb_mr_ram_out;
assign {vpn, v} = tlb_mr_ram_out[`OR1200_DTLBMRW-1:0];
 
//
// Assign to Match registers inputs
212,14 → 230,31
//
// Generate hit
//
assign hit = (vpn == vaddr[`OR1200_DTLB_TAG]) & v;
assign hit = (vpn == vaddr[`OR1200_DTLB_TAG]) & v
`ifdef OR1200_RAM_PARITY
& !p_err
`endif
;
 
//
// TLB index is normally vaddr[18:13]. If it is SPR access then index is
// spr_addr[5:0].
//
assign tlb_index = spr_cs ? spr_addr[`OR1200_DTLB_INDXW-1:0] : vaddr[`OR1200_DTLB_INDX];
assign tlb_index = spr_cs ? spr_addr[`OR1200_DTLB_INDXW-1:0] :
vaddr[`OR1200_DTLB_INDX];
 
`ifdef OR1200_RAM_PARITY
always @(posedge clk)
if (rst)
p_err_en <= 0;
else
p_err_en <= (tlb_mr_en & !tlb_mr_we) | (tlb_tr_en & !tlb_tr_we);
assign p_err = (p_err_en & (tlb_mr_en & !tlb_mr_we) |
(tlb_tr_en & !tlb_tr_we)) ? p_err_wire : 0;
`endif
 
//
// Instantiation of DTLB Match Registers
//
227,11 → 262,16
or1200_spram #
(
.aw(6),
`ifdef OR1200_RAM_PARITY
.dw(16)
`else
.dw(14)
`endif
)
dtlb_ram
dtlb_mr_ram
(
.clk(clk),
.rst(rst),
`ifdef OR1200_BIST
// RAM BIST
.mbist_si_i(mbist_mr_si),
241,17 → 281,18
.ce(tlb_mr_en),
.we(tlb_mr_we),
.addr(tlb_index),
`ifdef OR1200_RAM_PARITY
.p_err(p_err_wire[0]),
.di({2'b00,tlb_mr_ram_in}),
`else
.di(tlb_mr_ram_in),
`endif
.doq(tlb_mr_ram_out)
`ifdef OR1200_RAM_PARITY
, .p_err()
`endif
);
//
// Instantiation of DTLB Translate Registers
//
//or1200_spram_64x24 dtlb_tr_ram(
or1200_spram #
(
.aw(6),
260,6 → 301,7
dtlb_tr_ram
(
.clk(clk),
.rst(rst),
`ifdef OR1200_BIST
// RAM BIST
.mbist_si_i(mbist_tr_si),
266,14 → 308,14
.mbist_so_o(mbist_tr_so),
.mbist_ctrl_i(mbist_ctrl_i),
`endif
`ifdef OR1200_RAM_PARITY
.p_err(p_err_wire[1]),
`endif
.ce(tlb_tr_en),
.we(tlb_tr_we),
.addr(tlb_index),
.di(tlb_tr_ram_in),
.di(tlb_tr_ram_in),
.doq(tlb_tr_ram_out)
`ifdef OR1200_RAM_PARITY
, .p_err()
`endif
);
endmodule // or1200_dmmu_tlb
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_rf.v
56,6 → 56,11
// Clock and reset
clk, rst,
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
 
// Write i/f
cy_we_i, cy_we_o, supv, wb_freeze, addrw, dataw, we, flushpipe,
 
111,7 → 116,15
input [31:0] spr_dat_i;
output [31:0] spr_dat_o;
input du_read;
 
`ifdef OR1200_RAM_PARITY
output p_err;
wire [1:0] p_err_wire;
reg ena_r, enb_r;
`endif
 
//
// Internal wires and regs
//
149,7 → 162,6
spr_du_cs <= spr_cs & du_read;
 
assign spr_cs_fe = spr_du_cs & !(spr_cs & du_read);
 
//
// SPR access is valid when spr_cs is asserted and
181,12 → 193,12
//
// RF write address is either from SPRS or normal from CPU control
//
assign rf_addrw = (spr_valid & spr_write) ? spr_addr[4:0] : addrw;
assign rf_addrw = rst ? 0 : (spr_valid & spr_write) ? spr_addr[4:0] : addrw;
 
//
// RF write data is either from SPRS or normal from CPU datapath
//
assign rf_dataw = (spr_valid & spr_write) ? spr_dat_i : dataw;
assign rf_dataw = rst ? 0 : (spr_valid & spr_write) ? spr_dat_i : dataw;
 
//
// RF write enable is either from SPRS or normal from CPU control
197,30 → 209,43
else if (~wb_freeze)
rf_we_allow <= ~flushpipe;
 
//assign rf_we = ((spr_valid & spr_write) | (we & ~wb_freeze)) & rf_we_allow & (supv | (|rf_addrw));
assign rf_we = ((spr_valid & spr_write) | (we & ~wb_freeze)) & rf_we_allow;
//assign cy_we_o = cy_we_i && rf_we;
assign rf_we = rst ? 1 : ((spr_valid & spr_write) | (we & ~wb_freeze)) &
rf_we_allow;
 
assign cy_we_o = cy_we_i && ~wb_freeze && rf_we_allow;
//
// CS RF A asserted when instruction reads operand A and ID stage
// is not stalled
//
//assign rf_ena = rda & ~id_freeze | spr_valid; // probably works with fixed binutils
assign rf_ena = (rda & ~id_freeze) | (spr_valid & !spr_write) | spr_cs_fe; // probably works with fixed binutils
// assign rf_ena = 1'b1; // does not work with single-stepping
//assign rf_ena = ~id_freeze | spr_valid; // works with broken binutils
assign rf_ena = (rda & ~id_freeze) | (spr_valid & !spr_write) | spr_cs_fe;
 
//
// CS RF B asserted when instruction reads operand B and ID stage
// is not stalled
//
//assign rf_enb = rdb & ~id_freeze | spr_valid;
assign rf_enb = rdb & ~id_freeze;
// assign rf_enb = 1'b1;
//assign rf_enb = ~id_freeze | spr_valid; // works with broken binutils
 
`ifdef OR1200_RAM_PARITY
always @(posedge clk)
if (rst) begin
ena_r <= 0;
enb_r <= 0;
end
else if (p_err) begin
ena_r <= 0;
enb_r <= 0;
end
else begin
ena_r <= rf_ena;
enb_r <= rf_enb;
end
assign p_err = (p_err_wire[0] & ena_r) | (p_err_wire[1] & enb_r);
`endif
 
`ifdef OR1200_RFRAM_TWOPORT
 
//
273,13 → 298,18
.do_b()
);
 
`ifdef OR1200_RAM_PARITY
assign p_err_wire = 0;
`endif
 
`else
 
`ifdef OR1200_RFRAM_DUALPORT
 
//
// Instantiation of register file two-port RAM A
//
`ifdef OR1200_RFRAM_DUALPORT
//
// Instantiation of register file two-port RAM A
//
or1200_dpram #
(
.aw(5),
287,8 → 317,9
)
rf_a
(
.rst(rst),
// Port A
.clk_a(clk),
.clk_a(clk),
.ce_a(rf_ena),
.addr_a(rf_addra),
.do_a(from_rfa),
300,9 → 331,9
.addr_b(rf_addrw),
.di_b(rf_dataw)
`ifdef OR1200_RAM_PARITY
, .p_err()
`endif
`ifdef OR1200_RAM_PARITY
, .p_err(p_err_wire[0])
`endif
);
 
//
315,6 → 346,7
)
rf_b
(
.rst(rst),
// Port A
.clk_a(clk),
.ce_a(rf_enb),
327,12 → 359,13
.we_b(rf_we),
.addr_b(rf_addrw),
.di_b(rf_dataw)
`ifdef OR1200_RAM_PARITY
, .p_err()
`endif
 
);
`ifdef OR1200_RAM_PARITY
, .p_err(p_err_wire[1])
`endif
 
);
 
`else
 
`ifdef OR1200_RFRAM_GENERIC
362,6 → 395,10
.di_w(rf_dataw)
);
 
`ifdef OR1200_RAM_PARITY
assign p_err_wire = 0;
`endif
 
`else
 
//
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_ic_top.v
71,6 → 71,11
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
 
// SPRs
spr_cs, spr_write, spr_dat_i
);
125,6 → 130,10
output mbist_so_o;
`endif
 
`ifdef OR1200_RAM_PARITY
output [1:0] p_err;
`endif
//
// SPR access
//
144,9 → 153,10
wire ictag_we;
wire [31:0] ic_addr;
wire icfsm_biu_read;
/* verilator lint_off UNOPTFLAT */
reg tagcomp_miss;
/* verilator lint_on UNOPTFLAT */
 
//reg tagcomp_miss;
wire tagcomp_miss;
 
wire [`OR1200_ICINDXH:`OR1200_ICLS] ictag_addr;
wire ictag_en;
wire ictag_v;
169,6 → 179,20
assign mbist_so_o = mbist_tag_so;
`endif
 
`ifdef OR1200_RAM_PARITY
wire [1:0] p_err_wire;
// Indicate an error if we're reading from the RAM (hit)
// Additionally, mask with tag_v as tag ram is properly cleared during
// init, whereas the instruction RAM is not.
assign p_err[0] = (icqmem_ack_o & (!icfsm_first_miss_ack | ic_en)) &
(tag_v & !p_err[1]) ? p_err_wire[0] : 0;
// Whenever there's a tag parity error and we have an instruction fetch
assign p_err[1] = (ictag_en & !ictag_we) ? p_err_wire[1] : 0;
 
`else
`endif
//
// Simple assignments
//
233,13 → 257,12
// Tag comparison
//
// During line invalidate, ensure it stays the same
always @(tag or saved_addr or tag_v) begin
if ((tag != saved_addr[31:`OR1200_ICTAGL]) | !tag_v)
tagcomp_miss = 1'b1;
else
tagcomp_miss = 1'b0;
end
 
assign tagcomp_miss = ((tag != saved_addr[31:`OR1200_ICTAGL]) | !tag_v
`ifdef OR1200_RAM_PARITY
| (|p_err_wire)
`endif
);
//
// Instantiation of IC Finite State Machine
//
275,6 → 298,9
.mbist_so_o(mbist_ram_so),
.mbist_ctrl_i(mbist_ctrl_i),
`endif
`ifdef OR1200_RAM_PARITY
.p_err(p_err_wire[0]),
`endif
.addr(ic_addr[`OR1200_ICINDXH:2]),
.en(ic_en),
.we(icram_we),
294,6 → 320,9
.mbist_so_o(mbist_tag_so),
.mbist_ctrl_i(mbist_ctrl_i),
`endif
`ifdef OR1200_RAM_PARITY
.p_err(p_err_wire[1]),
`endif
.addr(ictag_addr),
.en(ictag_en),
.we(ictag_we),
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_dc_tag.v
61,6 → 61,11
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
 
// Internal i/f
addr, en, we, datain, tag_v, tag, dirty
);
90,6 → 95,13
input [`OR1200_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i;
output mbist_so_o;
`endif
`ifdef OR1200_RAM_PARITY
parameter tag_ram_extra_width = 24 - (`OR1200_DCTAG_W+1);
output p_err;
wire [24-3:0] tag_wire;
`else
wire [dw-3:0] tag_wire;
`endif
 
`ifdef OR1200_NO_DC
 
102,8 → 114,14
assign mbist_so_o = mbist_si_i;
`endif
 
`ifdef OR1200_RAM_PARITY
assign p_err = 0;
`endif
 
`else
 
assign tag = tag_wire[dw-3:0];
//
// Instantiation of TAG RAM block
//
111,7 → 129,11
or1200_spram #
(
.aw(`OR1200_DCTAG),
`ifdef OR1200_RAM_PARITY
.dw(24)
`else
.dw(`OR1200_DCTAG_W + 1)
`endif
)
dc_tag0
(
122,14 → 144,17
.mbist_ctrl_i(mbist_ctrl_i),
`endif
.clk(clk),
.rst(rst),
.ce(en),
.we(we),
.addr(addr),
`ifdef OR1200_RAM_PARITY
.p_err(p_err),
.di({{tag_ram_extra_width{1'b0}},datain}),
`else
.di(datain),
.doq({tag, tag_v, dirty})
`ifdef OR1200_RAM_PARITY
, .p_err()
`endif
.doq({tag_wire, tag_v, dirty})
);
`endif
 
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_spram.v
64,7 → 64,7
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
// Generic synchronous single-port RAM interface
clk, ce, we, addr, di, doq
clk, rst, ce, we, addr, di, doq
`ifdef OR1200_RAM_PARITY
, p_err
`endif
89,6 → 89,7
// Generic synchronous single-port RAM interface
//
input clk; // Clock
input rst; // Reset
input ce; // Chip enable input
input we; // Write enable input
input [aw-1:0] addr; // address bus inputs
110,18 → 111,20
// Generic RAM's registers and wires
//
`ifdef OR1200_RAM_PARITY
reg [(dw+(dw/8))-1:0] mem [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
parameter par_w = (dw/8);
reg [(dw+par_w)-1:0] mem [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
`else
reg [dw-1:0] mem [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [dw-1:0] mem [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
`endif
reg [aw-1:0] addr_reg; // RAM address register
reg [aw-1:0] addr_reg; // RAM address register
 
`ifdef OR1200_RAM_PARITY
wire [(dw+(dw/8))-1:0] doq_wire;
wire [(dw/8)-1:0] di_p;
wire [(dw/8)-1:0] do_p;
wire [(dw/8)-1:0] parity_err;
wire [(dw+par_w)-1:0] doq_wire;
wire [par_w-1:0] di_p;
wire [par_w-1:0] do_p;
wire [par_w-1:0] parity_err;
reg ce_r;
`else
wire [dw-1:0] doq_wire;
`endif
129,7 → 132,7
`ifdef OR1200_RAM_PARITY
genvar i;
generate
for (i=0;i<(dw/8);i=i+1) begin: paritygen
for (i=0;i<par_w;i=i+1) begin: paritygen
or1200_parity_gen pgen(.d_i(di[(i*8)+7:(i*8)]), .p_o(di_p[i]));
or1200_parity_chk pchk(.d_i(doq_wire[(i*8)+7:(i*8)]),
.p_i(do_p[i]), .err_o(parity_err[i]));
137,32 → 140,35
endgenerate
 
// Extract parity bits of data out
assign do_p = doq_wire[(dw+(dw/8))-1:dw];
assign do_p = doq_wire[(dw+par_w)-1:dw];
 
always @(posedge clk)
if (rst)
ce_r <= 0;
else
ce_r <= ce;
 
// Indicate error
assign p_err = (|parity_err) & ce_r;
// Indicate error
assign p_err = (|parity_err);
 
// Inject a parity error. Can specify GPR number to affect,
// and which parity or data bit to switch.
// Inject a parity error.
task gen_parity_err;
input [aw-1:0] gpr_no;
input [aw-1:0] addr;
input [31:0] parity_bit_no;
input [31:0] data_bit_no;
reg [(dw+(dw/8))-1:0] do_temp;
reg [(dw+par_w)-1:0] do_temp;
begin
do_temp = mem[gpr_no];
do_temp = mem[addr];
// Switch parity bit
if (parity_bit_no > 0 && parity_bit_no <= (dw/8))
do_temp[dw+(parity_bit_no-1)] = ~do_temp[dw+(parity_bit_no-1)];
if (parity_bit_no >= 0 && parity_bit_no < par_w)
do_temp[dw+parity_bit_no] = ~do_temp[dw+parity_bit_no];
// Switch data bit
if (data_bit_no > 0 && data_bit_no <= dw)
do_temp[data_bit_no-1] = ~do_temp[data_bit_no-1];
if (data_bit_no >= 0 && data_bit_no < dw)
do_temp[data_bit_no] = ~do_temp[data_bit_no];
// Write word back
mem[gpr_no] = do_temp;
mem[addr] = do_temp;
end
endtask // gen_parity_err
`endif
 
183,10 → 189,11
// RAM write
//
always @(posedge clk)
`ifdef OR1200_RAM_PARITY
if (we && ce)
`ifdef OR1200_RAM_PARITY
mem[addr] <= {di_p,di};
`else
`else
if (we && ce)
mem[addr] <= di;
`endif
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_dc_ram.v
61,9 → 61,13
// RAM BIST
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
// Internal i/f
addr, en, we, datain, dataout
 
);
 
parameter dw = `OR1200_OPERAND_WIDTH;
79,6 → 83,10
input [3:0] we;
input [dw-1:0] datain;
output [dw-1:0] dataout;
`ifdef OR1200_RAM_PARITY
output p_err;
`endif
 
`ifdef OR1200_BIST
//
98,6 → 106,9
`ifdef OR1200_BIST
assign mbist_so_o = mbist_si_i;
`endif
`ifdef OR1200_RAM_PARITY
assign p_err = 0;
`endif
 
`else
 
109,7 → 120,7
.aw(`OR1200_DCINDX),
.dw(dw)
)
dc_ram
dc_ram0
(
`ifdef OR1200_BIST
// RAM BIST
117,15 → 128,16
.mbist_so_o(mbist_so_o),
.mbist_ctrl_i(mbist_ctrl_i),
`endif
`ifdef OR1200_RAM_PARITY
.p_err(p_err),
`endif
.clk(clk),
.rst(rst),
.ce(en),
.we(we),
.addr(addr),
.di(datain),
.doq(dataout)
`ifdef OR1200_RAM_PARITY
, .p_err()
`endif
);
`endif
 
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_dc_top.v
77,7 → 77,12
// RAM BIST
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
// SPRs
spr_cs, spr_write, spr_dat_i, spr_addr, mtspr_dc_done
);
137,6 → 142,10
output mbist_so_o;
`endif
 
`ifdef OR1200_RAM_PARITY
output [1:0] p_err;
`endif
 
//
// SPR access
//
168,6 → 177,10
 
assign mtspr_dc_done = 1'b1;
 
`ifdef OR1200_RAM_PARITY
assign p_err = 0;
`endif
`else
//
185,7 → 198,7
wire dcfsm_biu_write;
wire dcfsm_dcram_di_sel;
wire dcfsm_biu_do_sel;
reg tagcomp_miss;
wire tagcomp_miss;
wire [`OR1200_DCINDXH:`OR1200_DCLS] dctag_addr;
wire dctag_en;
wire dctag_v;
213,6 → 226,21
assign mbist_so_o = mbist_tag_so;
`endif
 
`ifdef OR1200_RAM_PARITY
wire [1:0] p_err_wire;
 
// Indicate an error if we're reading from the RAM (hit)
// Additionally, mask with tag_v as tag ram is properly cleared during
// init, whereas the data RAM is not.
assign p_err[0] = (dcqmem_ack_o & (!dcfsm_first_miss_ack | dc_en) &
!dcqmem_we_i) &
(tag_v & !p_err[1]) ? p_err_wire[0] : 0;
// Whenever there's a tag parity error and we have an instruction fetch
assign p_err[1] = (dctag_en & !dctag_we) ? p_err_wire[1] : 0;
`endif
// Address out to external bus - always from FSM
assign dcsb_adr_o = dc_addr;
//
288,16 → 316,25
//
// Tag comparison
//
wire [31:`OR1200_DCTAGL] dcqmem_adr_i_tag;
assign dcqmem_adr_i_tag = dcqmem_adr_i[31:`OR1200_DCTAGL];
wire [31:`OR1200_DCTAGL] dcqmem_adr_i_tag;
assign dcqmem_adr_i_tag = dcqmem_adr_i[31:`OR1200_DCTAGL];
/*
always @(tag or dcqmem_adr_i_tag or tag_v) begin
if ((tag != dcqmem_adr_i_tag) || !tag_v)
if ((tag != dcqmem_adr_i_tag) || !tag_v
`ifdef OR1200_RAM_PARITY
| p_err
`endif
)
tagcomp_miss = 1'b1;
else
tagcomp_miss = 1'b0;
end
 
*/
assign tagcomp_miss = (tag != dcqmem_adr_i_tag) | !tag_v
`ifdef OR1200_RAM_PARITY
| (|p_err_wire)
`endif
;
//
// Instantiation of DC Finite State Machine
//
349,6 → 386,9
.mbist_so_o(mbist_ram_so),
.mbist_ctrl_i(mbist_ctrl_i),
`endif
`ifdef OR1200_RAM_PARITY
.p_err(p_err_wire[0]),
`endif
.addr(dc_addr[`OR1200_DCINDXH:2]),
.en(dc_en),
.we(dcram_we),
368,6 → 408,9
.mbist_so_o(mbist_tag_so),
.mbist_ctrl_i(mbist_ctrl_i),
`endif
`ifdef OR1200_RAM_PARITY
.p_err(p_err_wire[1]),
`endif
.addr(dctag_addr),
.en(dctag_en),
.we(dctag_we),
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_immu_tlb.v
69,6 → 69,11
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
// SPR access
spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
);
106,6 → 111,10
output mbist_so_o;
`endif
 
`ifdef OR1200_RAM_PARITY
output [1:0] p_err;
`endif
//
// SPR access
//
124,12 → 133,18
wire tlb_mr_en;
wire tlb_mr_we;
wire [`OR1200_ITLBMRW-1:0] tlb_mr_ram_in;
wire [`OR1200_ITLBMRW-1:0] tlb_mr_ram_out;
wire tlb_tr_en;
wire tlb_tr_we;
wire [`OR1200_ITLBTRW-1:0] tlb_tr_ram_in;
wire [`OR1200_ITLBTRW-1:0] tlb_tr_ram_out;
`ifdef OR1200_RAM_PARITY
wire [`OR1200_ITLBMRW-1+2:0] tlb_mr_ram_out;
wire [`OR1200_ITLBTRW-1+2:0] tlb_tr_ram_out;
`else
wire [`OR1200_ITLBMRW-1:0] tlb_mr_ram_out;
wire [`OR1200_ITLBTRW-1:0] tlb_tr_ram_out;
`endif
 
 
// BIST
`ifdef OR1200_BIST
wire itlb_mr_ram_si;
138,6 → 153,11
wire itlb_tr_ram_so;
`endif
 
`ifdef OR1200_RAM_PARITY
wire [1:0] p_err_wire;
reg p_err_en;
`endif
 
//
// Implemented bits inside match and translate registers
//
177,23 → 197,24
assign spr_dat_o = (!spr_write & !spr_addr[`OR1200_ITLB_TM_ADDR]) ?
{vpn, tlb_index, {`OR1200_ITLB_TAGW-7{1'b0}}, 1'b0, 5'b00000, v} :
(!spr_write & spr_addr[`OR1200_ITLB_TM_ADDR]) ?
{ppn, {`OR1200_IMMU_PS-8{1'b0}}, uxe, sxe, {4{1'b0}}, ci, 1'b0} :
{ppn, {`OR1200_IMMU_PS-8{1'b0}}, uxe, sxe, {4{1'b0}}, ci, 1'b0} :
32'h00000000;
 
//
// Assign outputs from Match registers
//
assign {vpn, v} = tlb_mr_ram_out;
assign {vpn, v} = tlb_mr_ram_out[`OR1200_ITLBMRW-1:0];
 
//
// Assign to Match registers inputs
//
assign tlb_mr_ram_in = {spr_dat_i[`OR1200_ITLB_TAG], spr_dat_i[`OR1200_ITLBMR_V_BITS]};
assign tlb_mr_ram_in = {spr_dat_i[`OR1200_ITLB_TAG],
spr_dat_i[`OR1200_ITLBMR_V_BITS]};
 
//
// Assign outputs from Translate registers
//
assign {ppn, uxe, sxe, ci} = tlb_tr_ram_out;
assign {ppn, uxe, sxe, ci} = tlb_tr_ram_out[`OR1200_ITLBTRW-1:0];
 
//
// Assign to Translate registers inputs
206,13 → 227,18
//
// Generate hit
//
assign hit = (vpn == vaddr[`OR1200_ITLB_TAG]) & v;
assign hit = (vpn == vaddr[`OR1200_ITLB_TAG]) & v
`ifdef OR1200_RAM_PARITY
& !p_err
`endif
;
 
//
// TLB index is normally vaddr[18:13]. If it is SPR access then index is
// spr_addr[5:0].
//
assign tlb_index = spr_cs ? spr_addr[`OR1200_ITLB_INDXW-1:0] : vaddr[`OR1200_ITLB_INDX];
assign tlb_index = spr_cs ? spr_addr[`OR1200_ITLB_INDXW-1:0] :
vaddr[`OR1200_ITLB_INDX];
 
 
`ifdef OR1200_BIST
221,7 → 247,18
assign mbist_so_o = itlb_tr_ram_so;
`endif
 
`ifdef OR1200_RAM_PARITY
always @(posedge clk)
if (rst)
p_err_en <= 0;
else
p_err_en <= (tlb_mr_en & !tlb_mr_we) | (tlb_tr_en & !tlb_tr_we);
 
assign p_err = (p_err_en & (tlb_mr_en & !tlb_mr_we) |
(tlb_tr_en & !tlb_tr_we)) ? p_err_wire : 0;
`endif
 
 
//
// Instantiation of ITLB Match Registers
//
228,11 → 265,16
or1200_spram #
(
.aw(6),
`ifdef OR1200_RAM_PARITY
.dw(16)
`else
.dw(14)
`endif
)
itlb_mr_ram
(
.clk(clk),
.rst(rst),
`ifdef OR1200_BIST
// RAM BIST
.mbist_si_i(itlb_mr_ram_si),
243,11 → 285,13
.we(tlb_mr_we),
//.oe(1'b1),
.addr(tlb_index),
`ifdef OR1200_RAM_PARITY
.p_err(p_err_wire[0]),
.di({2'b00,tlb_mr_ram_in}),
`else
.di(tlb_mr_ram_in),
`endif
.doq(tlb_mr_ram_out)
`ifdef OR1200_RAM_PARITY
, .p_err()
`endif
);
 
//
256,11 → 300,16
or1200_spram #
(
.aw(6),
`ifdef OR1200_RAM_PARITY
.dw(24)
`else
.dw(22)
`endif
)
itlb_tr_ram
(
.clk(clk),
.rst(rst),
`ifdef OR1200_BIST
// RAM BIST
.mbist_si_i(itlb_tr_ram_si),
271,11 → 320,13
.we(tlb_tr_we),
//.oe(1'b1),
.addr(tlb_index),
`ifdef OR1200_RAM_PARITY
.p_err(p_err_wire[1]),
.di({2'b00,tlb_tr_ram_in}),
`else
.di(tlb_tr_ram_in),
`endif
.doq(tlb_tr_ram_out)
`ifdef OR1200_RAM_PARITY
, .p_err()
`endif
);
endmodule
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_spram_32_bw.v
65,7 → 65,7
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
// Generic synchronous single-port RAM interface
clk, ce, we, addr, di, doq
clk, rst, ce, we, addr, di, doq
`ifdef OR1200_RAM_PARITY
, p_err
`endif
88,19 → 88,22
input [`OR1200_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i;
output mbist_so_o;
`endif
 
`ifdef OR1200_RAM_PARITY
output p_err; // parity error indicator
`endif
//
// Generic synchronous single-port RAM interface
// Generic synchronous single-port byte-writable RAM interface
//
input clk; // Clock
input rst; // Reset
input ce; // Chip enable input
input [3:0] we; // Write enable input
input [aw-1:0] addr; // address bus inputs
input [dw-1:0] di; // input data bus
output [dw-1:0] doq; // output data bus
`ifdef OR1200_RAM_PARITY
output p_err; // parity error indicator
`endif
 
//
// Internal wires and registers
114,17 → 117,17
// Generic RAM's registers and wires
//
`ifdef OR1200_RAM_PARITY
reg [bw:0] mem0 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw:0] mem1 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw:0] mem2 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw:0] mem3 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw:0] mem0 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw:0] mem1 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw:0] mem2 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw:0] mem3 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
`else
reg [bw-1:0] mem0 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw-1:0] mem1 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw-1:0] mem2 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw-1:0] mem3 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw-1:0] mem0 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw-1:0] mem1 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw-1:0] mem2 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
reg [bw-1:0] mem3 [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/;
`endif
reg [aw-1:0] addr_reg; // RAM address register
reg [aw-1:0] addr_reg; // RAM address register
 
`ifdef OR1200_RAM_PARITY
wire [(dw+(dw/8))-1:0] doq_wire;
135,6 → 138,7
wire [(dw/8)-1:0] di_p;
wire [(dw/8)-1:0] do_p;
wire [(dw/8)-1:0] parity_err;
reg ce_r;
`else
wire [dw-1:0] doq_wire;
`endif
151,30 → 155,56
 
// Extract parity bits of data out
assign do_p = doq_wire[(dw+(dw/8))-1:dw];
 
always @(posedge clk)
if (rst)
ce_r <= 0;
else
ce_r <= ce;
// Indicate error
assign p_err = (|parity_err);
assign p_err = (|parity_err) & ce_r;
 
// Inject a parity error. Can specify GPR number to affect,
// and which parity or data bit to switch.
task gen_parity_err;
input [aw-1:0] gpr_no;
input [31:0] parity_bit_no;
input [aw-1:0] word_no;
input [31:0] data_bit_no;
reg [(dw+(dw/8))-1:0] do_temp;
reg [bw:0] do_temp;
begin
// TODO
/*
do_temp = mem[gpr_no];
// Switch parity bit
if (parity_bit_no > 0 && parity_bit_no <= (dw/8))
do_temp[dw+(parity_bit_no-1)] = ~do_temp[dw+(parity_bit_no-1)];
// Switch data bit
if (data_bit_no > 0 && data_bit_no <= dw)
do_temp[data_bit_no-1] = ~do_temp[data_bit_no-1];
// Write word back
mem[gpr_no] = do_temp;
*/
// Fish word out
if (data_bit_no < 8) begin
do_temp = mem0[word_no];
end
else if (data_bit_no < 16) begin
do_temp = mem1[word_no];
data_bit_no = data_bit_no - 8;
end
else if (data_bit_no < 24) begin
do_temp = mem2[word_no];
data_bit_no = data_bit_no - 16;
end
else if (data_bit_no < 32) begin
do_temp = mem3[word_no];
data_bit_no = data_bit_no - 24;
end
else begin
do_temp = mem3[word_no];
data_bit_no = 8;
end
 
// Switch bit
do_temp[data_bit_no] = ~do_temp[data_bit_no] ;
 
// Replace word
if (data_bit_no < 8)
mem0[word_no] = do_temp;
else if (data_bit_no < 16)
mem1[word_no] = do_temp;
else if (data_bit_no < 24)
mem2[word_no] = do_temp;
else
mem3[word_no] = do_temp;
end
endtask // gen_parity_err
`endif
232,4 → 262,5
`endif
end
endmodule // or1200_spram
endmodule // or1200_spram_32_bw
 
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_dmmu_top.v
72,6 → 72,11
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
// Parity error indicator
p_err,
`endif
// DC i/f
qmemdmmu_err_i, qmemdmmu_tag_i, qmemdmmu_adr_o, qmemdmmu_cycstb_o, qmemdmmu_ci_o
);
119,6 → 124,10
output mbist_so_o;
`endif
 
`ifdef OR1200_RAM_PARITY
output [1:0] p_err;
`endif
//
// DC I/F
//
176,6 → 185,9
`ifdef OR1200_BIST
assign mbist_so_o = mbist_si_i;
`endif
`ifdef OR1200_RAM_PARITY
assign p_err = 0;
`endif
 
`else
 
294,6 → 306,10
.mbist_ctrl_i(mbist_ctrl_i),
`endif
 
`ifdef OR1200_RAM_PARITY
.p_err(p_err),
`endif
// SPR access
.spr_cs(dtlb_spr_access),
.spr_write(spr_write),
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_top.v
85,6 → 85,11
// RAM BIST
mbist_si_i, mbist_so_o, mbist_ctrl_i,
`endif
 
`ifdef OR1200_RAM_PARITY
mem_parity_err,
`endif
// Power Management
pm_cpustall_i,
pm_clksd_o, pm_dc_gate_o, pm_ic_gate_o, pm_dmmu_gate_o,
195,6 → 200,10
output pm_wakeup_o;
output pm_lvolt_o;
 
`ifdef OR1200_RAM_PARITY
output [8:0] mem_parity_err;
`endif
 
//
// Internal wires and regs
425,6 → 434,17
assign mbist_so_o = mbist_dc_so;
`endif
 
`ifdef OR1200_RAM_PARITY
wire [1:0] p_err_dc;
wire [1:0] p_err_ic;
wire [1:0] p_err_dmmu;
wire [1:0] p_err_immu;
wire p_err_rf;
 
assign mem_parity_err = {p_err_immu,p_err_dmmu,p_err_ic,p_err_dc,p_err_rf};
`endif
wire [3:0] icqmem_sel_qmem;
wire [3:0] icqmem_tag_qmem;
wire [3:0] dcqmem_tag_qmem;
535,6 → 555,10
.mbist_ctrl_i(mbist_ctrl_i),
`endif
 
`ifdef OR1200_RAM_PARITY
.p_err(p_err_immu),
`endif
 
// CPU and IMMU
.ic_en(ic_en),
.immu_en(immu_en),
578,7 → 602,9
.mbist_so_o(mbist_ic_so),
.mbist_ctrl_i(mbist_ctrl_i),
`endif
 
`ifdef OR1200_RAM_PARITY
.p_err(p_err_ic),
`endif
// IC and QMEM
.ic_en(ic_en),
.icqmem_adr_i(icqmem_adr_qmem),
706,6 → 732,11
.spr_cs(spr_cs),
.spr_we(spr_we),
.mtspr_dc_done(mtspr_dc_done)
`ifdef OR1200_RAM_PARITY
// Register file parity error indicator
, .p_err_rf(p_err_rf)
`endif
);
 
//
723,6 → 754,10
.mbist_ctrl_i(mbist_ctrl_i),
`endif
 
`ifdef OR1200_RAM_PARITY
.p_err(p_err_dmmu),
`endif
 
// CPU i/f
.dc_en(dc_en),
.dmmu_en(dmmu_en),
761,7 → 796,9
.mbist_so_o(mbist_dc_so),
.mbist_ctrl_i(mbist_ctrl_i),
`endif
 
`ifdef OR1200_RAM_PARITY
.p_err(p_err_dc),
`endif
// DC and QMEM
.dc_en(dc_en),
.dcqmem_adr_i(dcqmem_adr_qmem),
/openrisc/trunk/orpsocv2/rtl/verilog/or1200/or1200_dpram.v
59,6 → 59,7
 
module or1200_dpram
(
rst,
// Generic synchronous double-port RAM interface
clk_a, ce_a, addr_a, do_a,
clk_b, ce_b, we_b, addr_b, di_b
76,6 → 77,7
//
// Generic synchronous double-port RAM interface
//
input rst; // Reset
input clk_a; // Clock
input ce_a; // Chip enable input
input [aw-1:0] addr_a; // address bus inputs
100,8 → 102,10
//
// Generic RAM's registers and wires
//
`ifdef OR1200_RAM_PARITY
reg [(dw+(dw/8))-1:0] mem [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/; // RAM content
`ifdef OR1200_RAM_PARITY
parameter par_w = (dw/8);
reg [(dw+par_w)-1:0] mem [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/; // RAM content
`else
reg [dw-1:0] mem [(1<<aw)-1:0] /*synthesis syn_ramstyle = "no_rw_check"*/; // RAM content
`endif
108,10 → 112,10
reg [aw-1:0] addr_a_reg; // RAM address registered
 
`ifdef OR1200_RAM_PARITY
wire [(dw+(dw/8))-1:0] do_a_wire;
wire [(dw/8)-1:0] di_p;
wire [(dw/8)-1:0] do_p;
wire [(dw/8)-1:0] parity_err;
wire [(dw+par_w)-1:0] do_a_wire;
wire [par_w-1:0] di_p;
wire [par_w-1:0] do_p;
wire [par_w-1:0] parity_err;
`else
wire [dw-1:0] do_a_wire;
`endif
121,15 → 125,16
function [31:0] get_gpr;
// verilator public
input [aw-1:0] gpr_no;
reg [(dw+(dw/8))-1:0] gpr_temp;
`ifdef OR1200_RAM_PARITY
reg [(dw+par_w)-1:0] gpr_temp;
begin
`ifdef OR1200_RAM_PARITY
gpr_temp = mem[gpr_no];
get_gpr = gpr_temp[31:0];
end
`else
 
get_gpr = mem[gpr_no];
`endif
end
endfunction // get_gpr
 
task set_gpr;
151,7 → 156,7
`ifdef OR1200_RAM_PARITY
genvar i;
generate
for (i=0;i<(dw/8);i=i+1) begin: paritygen
for (i=0;i<par_w;i=i+1) begin: paritygen
or1200_parity_gen pgen(.d_i(di_b[(i*8)+7:(i*8)]), .p_o(di_p[i]));
or1200_parity_chk pchk(.d_i(do_a_wire[(i*8)+7:(i*8)]),
.p_i(do_p[i]), .err_o(parity_err[i]));
159,10 → 164,17
endgenerate
 
// Extract parity bits of data out
assign do_p = do_a_wire[(dw+(dw/8))-1:dw];
assign do_p = do_a_wire[(dw+par_w)-1:dw];
 
reg ce_a_r;
always @(posedge clk_a)
if (rst)
ce_a_r <= 0;
else
ce_a_r <= ce_a;
// Indicate error
assign p_err = (|parity_err);
assign p_err = (|parity_err) & ce_a_r;
 
// Inject a parity error. Can specify GPR number to affect,
// and which parity or data bit to switch.
170,21 → 182,19
input [aw-1:0] gpr_no;
input [31:0] parity_bit_no;
input [31:0] data_bit_no;
reg [(dw+(dw/8))-1:0] do_temp;
reg [(dw+par_w)-1:0] do_temp;
begin
do_temp = mem[gpr_no];
// Switch parity bit
if (parity_bit_no > 0)
do_temp[dw+(parity_bit_no-1)] = ~do_temp[dw+(parity_bit_no-1)];
if (parity_bit_no >= 0 && parity_bit_no < par_w)
do_temp[dw+parity_bit_no] = ~do_temp[dw+parity_bit_no];
// Switch data bit
if (data_bit_no > 0 && data_bit_no <= dw)
do_temp[data_bit_no-1] = ~do_temp[data_bit_no-1];
if (data_bit_no >= 0 && data_bit_no < dw)
do_temp[data_bit_no] = ~do_temp[data_bit_no];
// Write word back
mem[gpr_no] = do_temp;
end
endtask // gen_parity_err
`endif
 
//
/openrisc/trunk/orpsocv2/doc/orpsoc.texi
62,6 → 62,7
* Board Designs::
* ORDB1A3PE1500::
* ML501::
* Generic Designs::
* Software::
* GNU Free Documentation License:: The license for this documentation
* Index::
1353,7 → 1354,30
 
See the ML501 schematic (http://www.xilinx.com/support/documentation/boards_and_kits/ml501_20061010_bw.pdf) for more details on these headers, and refer to the pinouts in the ML501 UCF, in the board's @code{backend/par/bin/ml501.ucf} file.
 
 
@c ****************************************************************************
@c Generic Design build chapter
@c ****************************************************************************
 
@node Generic
@chapter Generic
@cindex Generic design information
 
@menu
* Overview::
@end menu
 
 
@node Generic Build Overview
@section Overview
 
The paths under @code{boards/generic} contain designs similar to the reference design, in that they are not technology specific, and used for development of certain features of the processor, or peripherals.
 
An example is the fault tolerance testing build, in @code{boards/generic/ft}, which implements some custom modules in the testbench and ORPSoC top level design, and is in general a very minimal system just for testing.
 
Additional builds, testing certain parts of the technology, can be developed here.
 
@c ****************************************************************************
@c Software section
@c ****************************************************************************
 
/openrisc/trunk/orpsocv2/sw/tests/or1200/sim/or1200-dctest.c
14,8 → 14,7
#define LOOPS 64
#define WORD_STRIDE 8
 
// Memory area to test at
#define TEST_BASE 0x600000 /* 6MB */
extern unsigned long _stack;
 
unsigned long int my_lfsr;
 
29,6 → 28,8
main()
{
 
unsigned long stack_top = (unsigned long) &_stack;
 
// Check data cache is present and enabled
if (!(mfspr(SPR_UPR)& SPR_UPR_DCP) | !(mfspr(SPR_SR) & SPR_SR_DCE))
{
37,7 → 38,7
return 0;
}
 
volatile char* ptr = (volatile char*) TEST_BASE;
volatile char* ptr = (volatile char*) (stack_top + 256);
int i;
 
ptr[0] = 0xab;
99,7 → 100,7
 
// init LFSR
my_lfsr = RAND_LFSR_SEED;
volatile unsigned long int *lptr = (volatile unsigned long int*) TEST_BASE;
volatile unsigned long int *lptr = (volatile unsigned long int*) (stack_top + 256);
for(i=0;i<LOOPS;i++)
{
lptr[(i*WORD_STRIDE)-1] = next_rand();
/openrisc/trunk/orpsocv2/sw/tests/or1200/sim/or1200-mmu.c
94,7 → 94,7
// Set this to 1 to enable the IMMU tests
#define DO_IMMU_TESTS 1
// Set this to 1 to enable the DMMU tests
#define DO_DMMU_TESTS 1
#define DO_DMMU_TESTS 0
 
// Symbols defined in linker script
extern unsigned long _endtext;
114,7 → 114,9
will be used for testing */
#define RAM_START 0x00000000
// Assume only 2MB memory
#define RAM_SIZE 0x00200000
#ifndef RAM_SIZE
# define RAM_SIZE 0x00200000
#endif
 
#define VM_BASE 0xc0000000
 
/openrisc/trunk/orpsocv2/sw/drivers/or1200/crt0.S
35,6 → 35,37
/* ---[ 0x100: RESET exception ]----------------------------------------- */
.org 0x100
l.movhi r0, 0
l.movhi r1, 0
l.movhi r2, 0
l.movhi r3, 0
l.movhi r4, 0
l.movhi r5, 0
l.movhi r6, 0
l.movhi r7, 0
l.movhi r8, 0
l.movhi r9, 0
l.movhi r10, 0
l.movhi r11, 0
l.movhi r12, 0
l.movhi r13, 0
l.movhi r14, 0
l.movhi r15, 0
l.movhi r16, 0
l.movhi r17, 0
l.movhi r18, 0
l.movhi r19, 0
l.movhi r20, 0
l.movhi r21, 0
l.movhi r22, 0
l.movhi r23, 0
l.movhi r24, 0
l.movhi r25, 0
l.movhi r26, 0
l.movhi r27, 0
l.movhi r28, 0
l.movhi r29, 0
l.movhi r30, 0
l.movhi r31, 0
/* Clear status register, set supervisor mode */
l.ori r1, r0, SPR_SR_SM
l.mtspr r0, r1, SPR_SR
290,11 → 321,6
 
.L10:
 
/* Initialise stack */
/* LOAD_SYMBOL_2_GPR(r1, _stack)
l.addi r2, r0, -3
l.and r1, r1, r2
*/
/* Clear BSS */
LOAD_SYMBOL_2_GPR(r28, _bss_start)
LOAD_SYMBOL_2_GPR(r30, _bss_end)
304,12 → 330,10
l.bf 1b
l.addi r28, r28, 4
 
 
/* Initialise UART in a C function */
/*l.jal _uart_init
l.nop*/
 
/* Jump to main program entry point (argc = argv = 0) */
CLEAR_GPR(r3)
CLEAR_GPR(r4)
/openrisc/trunk/orpsocv2/boards/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
/openrisc/trunk/orpsocv2/boards/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.)
/openrisc/trunk/orpsocv2/boards/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
/openrisc/trunk/orpsocv2/boards/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:
 
/openrisc/trunk/orpsocv2/boards/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
/openrisc/trunk/orpsocv2/boards/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
openrisc/trunk/orpsocv2/boards/generic/ft/bench/verilog/or1200_monitor.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/clkgen/clkgen.v =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/clkgen/clkgen.v (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/clkgen/README =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/clkgen/README (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/include/or1200_defines.v =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/include/or1200_defines.v (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/include/orpsoc-defines.v =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/include/orpsoc-defines.v (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/include/orpsoc-params.v =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/include/orpsoc-params.v (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/orpsoc_top/orpsoc_top.v =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/orpsoc_top/orpsoc_top.v (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: +
openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/orpsoc_top/orpsoc_top.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/arbiter/arbiter_bytebus.v =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/arbiter/arbiter_bytebus.v (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/arbiter/arbiter_dbus.v =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/arbiter/arbiter_dbus.v (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/arbiter/arbiter_ibus.v =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/arbiter/arbiter_ibus.v (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/parity_err_handler/parity_err_handler.v =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/rtl/verilog/parity_err_handler/parity_err_handler.v (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/doc/README =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/doc/README (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/backend/rtl/verilog/dummy.v =================================================================== Index: openrisc/trunk/orpsocv2/boards/generic/ft/sim/run/Makefile =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/sim/run/Makefile (nonexistent) +++ openrisc/trunk/orpsocv2/boards/generic/ft/sim/run/Makefile (revision 483) @@ -0,0 +1 @@ +include ../bin/Makefile Index: openrisc/trunk/orpsocv2/boards/generic/ft/sim/bin/Makefile =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/sim/bin/Makefile (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/sw/tests/or1200ft/sim/or1200ft-parity.c =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/sw/tests/or1200ft/sim/or1200ft-parity.c (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/sw/tests/or1200ft/sim/Makefile =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/sw/tests/or1200ft/sim/Makefile (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/sw/Makefile.inc =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/sw/Makefile.inc (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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: openrisc/trunk/orpsocv2/boards/generic/ft/sw/board/include/board.h =================================================================== --- openrisc/trunk/orpsocv2/boards/generic/ft/sw/board/include/board.h (nonexistent) +++ openrisc/trunk/orpsocv2/boards/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.