URL
https://opencores.org/ocsvn/adv_debug_sys/adv_debug_sys/trunk
Subversion Repositories adv_debug_sys
Compare Revisions
- This comparison shows the changes necessary to convert path
/adv_debug_sys/trunk/Hardware/adv_dbg_if
- from Rev 51 to Rev 56
- ↔ Reverse comparison
Rev 51 → Rev 56
/bench/full_system/adv_dbg_tb.v
6,13 → 6,13
//// Testbench for the SoC Advanced Debug Interface. //// |
//// //// |
//// Author(s): //// |
//// Nathan Yawn (nathan.yawn@opencores.org) //// |
//// Nathan Yawn (nyawn@opencores.org) //// |
//// //// |
//// //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2008 Authors //// |
//// Copyright (C) 2008'2010 Authors //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
40,6 → 40,9
// CVS Revision History |
// |
// $Log: adv_dbg_tb.v,v $ |
// Revision 1.7 2011-02-14 04:16:25 natey |
// Major functionality enhancement - now duplicates the full OR1K self-test performed by adv_jtag_bridge. |
// |
// Revision 1.6 2010-01-16 02:15:22 Nathan |
// Updated to match changes in hardware. Added support for hi-speed mode. |
// |
121,6 → 124,8
|
reg [32:0] err_data; // holds the contents of the error register from the various modules |
|
reg [31:0] original_instruction; // holds instruction being replaced by TRAP in CPU functional test |
|
reg failed; |
integer i; |
|
269,9 → 274,11
`endif // WB module supported |
|
|
/////////////////////////////////////////////////////////////////// |
// Test CPU0 unit |
//////////////////////////////////////////////////////////////////// |
/////////////////////////////////////////////////////////////////// |
// Test CPU0 unit. This duplicates the CPU self-test originally |
// found in the jp2 JTAG proxy (which was carried over into |
// adv_jtag_bridge) |
//////////////////////////////////////////////////////////////////// |
`ifdef DBG_CPU0_SUPPORTED |
// Select the CPU0 unit in the debug module |
#1000; |
291,125 → 298,240
#1000; |
|
|
// Write some opcodes into the memory |
select_debug_module(`DBG_TOP_WISHBONE_DEBUG_MODULE); |
// Write some opcodes into the memory |
select_debug_module(`DBG_TOP_WISHBONE_DEBUG_MODULE); |
$display("Commencing CPU functional test - writing instructions at time %t", $time); |
static_data32[0] = 32'hE0000005;/* l.xor r0,r0,r0 */ |
static_data32[1] = 32'h9C200000; /* l.addi r1,r0,0x0 */ |
static_data32[2] = 32'h18400000;/* l.movhi r2,0x4000 */ |
static_data32[3] = 32'hA8420030;/* l.ori r2,r2,0x30 */ |
static_data32[4] = 32'h9C210001;/* l.addi r1,r1,1 */ |
static_data32[5] = 32'h9C210001; /* l.addi r1,r1,1 */ |
static_data32[6] = 32'hD4020800;/* l.sw 0(r2),r1 */ |
static_data32[7] = 32'h9C210001;/* l.addi r1,r1,1 */ |
static_data32[8] = 32'h84620000;/* l.lwz r3,0(r2) */ |
static_data32[9] = 32'h03FFFFFB;/* l.j loop2 */ |
static_data32[10] = 32'hE0211800;/* l.add r1,r1,r3 */ |
do_module_burst_write(3'h4, 16'd11, 32'h0); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
|
static_data32[0] = 32'hE0000005;/* l.xor r0,r0,r0 */ |
static_data32[1] = 32'h9C200000; /* l.addi r1,r0,0x0 */ |
static_data32[2] = 32'h18400000;/* l.movhi r2,0x4000 */ |
static_data32[3] = 32'hA8420030;/* l.ori r2,r2,0x30 */ |
static_data32[4] = 32'h9C210001;/* l.addi r1,r1,1 */ |
static_data32[5] = 32'h9C210001; /* l.addi r1,r1,1 */ |
static_data32[6] = 32'hD4020800;/* l.sw 0(r2),r1 */ |
static_data32[7] = 32'h9C210001;/* l.addi r1,r1,1 */ |
static_data32[8] = 32'h84620000;/* l.lwz r3,0(r2) */ |
static_data32[9] = 32'h03FFFFFB;/* l.j loop2 */ |
static_data32[10] = 32'hE0211800;/* l.add r1,r1,r3 */ |
#1000; |
select_debug_module(`DBG_TOP_CPU0_DEBUG_MODULE); |
|
do_module_burst_write(3'h4, 16'd11, 32'h0); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
|
// *** Test the step bit *** |
#1000; |
select_debug_module(`DBG_TOP_CPU0_DEBUG_MODULE); |
$display("Testing step bit at time %t", $time); |
static_data32[0] = 32'h1; // enable exceptions |
do_module_burst_write(3'h4, 16'd1, 32'd17); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
static_data32[0] = 32'h00002000; // Trap causes stall |
do_module_burst_write(3'h4, 16'd1, (6 << 11)+20); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
static_data32[0] = 32'h0; // Set PC to 0x00 |
do_module_burst_write(3'h4, 16'd1, 32'd16); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
static_data32[0] = (1 << 22); // set step bit |
do_module_burst_write(3'h4, 16'd1, (6<<11) + 16); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
|
#1000; |
$display("Enabling CPU exceptions at time %t", $time); |
static_data32[0] = 32'h1; // enable exceptions |
do_module_burst_write(3'h4, 16'd1, 32'd17); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
// Unstall x11 |
for(i = 0; i < 11; i = i + 1) |
begin |
#1000; |
$display("Unstall (%d/11) at time %t", i+1, $time); |
unstall(); |
wait_for_stall(); |
end |
|
#1000; |
$display("Set \'trap causes stall\' at time %t", $time); |
static_data32[0] = 32'h00002000; // Trap causes stall |
do_module_burst_write(3'h4, 16'd1, (6 << 11)+20); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
#1000; |
check_results(32'h10, 32'h28, 32'h5); |
|
static_data32[0] = 32'h0; |
do_module_burst_write(3'h4, 16'd1, (6 << 11)+16); // Un-set step bit |
|
// *** Put a TRAP instruction in the delay slot *** |
#1000; |
$display("Put TRAP instruction in the delay slot at time %t", $time); |
select_debug_module(`DBG_TOP_WISHBONE_DEBUG_MODULE); |
do_module_burst_read(3'h4, 16'd1, 32'h28); // Save old instr in input_data32[0] |
original_instruction = input_data32[0]; |
static_data32[0] = 32'h21000001; /* l.trap */ |
do_module_burst_write(3'h4, 16'd1, 32'h28); // put new instr |
select_debug_module(`DBG_TOP_CPU0_DEBUG_MODULE); |
// We don't set the PC here |
|
#1000; |
$display("Set PC at time %t", $time); |
static_data32[0] = 32'h0; // Set PC |
do_module_burst_write(3'h4, 16'd1, 32'd16); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
unstall(); |
wait_for_stall(); |
check_results(32'h10, 32'h28, 32'd8); // Expected NPC, PPC, R1 |
|
// Put back original instruction |
static_data32[0] = original_instruction; |
select_debug_module(`DBG_TOP_WISHBONE_DEBUG_MODULE); |
do_module_burst_write(3'h4, 16'd1, 32'h28); // put back old instr |
|
#1000; |
$display("Set step bit at time %t", $time); |
static_data32[0] = (1 << 22); // set step bit |
do_module_burst_write(3'h4, 16'd1, (6<<11) + 16); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
// *** Put TRAP instruction in place of BRANCH instruction *** |
#1000; |
$display("Put TRAP instruction in place of BRANCH instruction at time %t", $time); |
do_module_burst_read(3'h4, 16'd1, 32'h24); // Save old instr in input_data32[0] |
original_instruction = input_data32[0]; |
static_data32[0] = 32'h21000001; /* l.trap */ |
do_module_burst_write(3'h4, 16'd1, 32'h24); // put new instr |
select_debug_module(`DBG_TOP_CPU0_DEBUG_MODULE); |
static_data32[0] = 32'h10; |
do_module_burst_write(3'h4, 16'd1, 32'd16); // Set PC to 0x10 |
|
unstall(); |
wait_for_stall(); |
check_results(32'h28, 32'h24, 32'd11); // Expected NPC, PPC, R1 |
|
static_data32[0] = original_instruction; |
select_debug_module(`DBG_TOP_WISHBONE_DEBUG_MODULE); |
do_module_burst_write(3'h4, 16'd1, 32'h24); // put back old instr |
|
// Unstall x11 |
for(i = 0; i < 11; i = i + 1) |
begin |
// *** Set TRAP instruction before BRANCH instruction *** |
#1000; |
$display("Unstall (%d/11) at time %t", i, $time); |
write_module_internal_register(32'h0, 8'h1, 32'h0, 8'h2); // idx, idxlen, data, datalen |
end |
$display("Put TRAP instruction before BRANCH instruction at time %t", $time); |
do_module_burst_read(3'h4, 16'd1, 32'h20); // Save old instr in input_data32[0] |
original_instruction = input_data32[0]; |
static_data32[0] = 32'h21000001; /* l.trap */ |
do_module_burst_write(3'h4, 16'd1, 32'h20); // put new instr |
select_debug_module(`DBG_TOP_CPU0_DEBUG_MODULE); |
static_data32[0] = 32'h24; |
do_module_burst_write(3'h4, 16'd1, 32'd16); // Set PC to 0x24 |
|
unstall(); |
wait_for_stall(); |
check_results(32'h24, 32'h20, 32'd24); // Expected NPC, PPC, R1 |
|
static_data32[0] = original_instruction; |
select_debug_module(`DBG_TOP_WISHBONE_DEBUG_MODULE); |
do_module_burst_write(3'h4, 16'd1, 32'h20); // put back old instr |
|
#1000; |
#1000; |
#1000; |
// *** Set TRAP instruction behind LSU instruction *** |
#1000; |
$display("Put TRAP instruction behind LSU instruction at time %t", $time); |
do_module_burst_read(3'h4, 16'd1, 32'h1c); // Save old instr in input_data32[0] |
original_instruction = input_data32[0]; |
static_data32[0] = 32'h21000001; /* l.trap */ |
do_module_burst_write(3'h4, 16'd1, 32'h1c); // put new instr |
select_debug_module(`DBG_TOP_CPU0_DEBUG_MODULE); |
static_data32[0] = 32'h20; |
do_module_burst_write(3'h4, 16'd1, 32'd16); // Set PC to 0x20 |
|
unstall(); |
wait_for_stall(); |
check_results(32'h20, 32'h1c, 32'd49); // Expected NPC, PPC, R1 |
|
static_data32[0] = original_instruction; |
select_debug_module(`DBG_TOP_WISHBONE_DEBUG_MODULE); |
do_module_burst_write(3'h4, 16'd1, 32'h1c); // put back old instr |
|
$display("Getting NPC at time %t", $time); |
do_module_burst_read(3'h4, 16'd1, 32'd16); |
|
$display("NPC = %x, expected 0x00000010", input_data32[0]); |
|
$display("Getting PPC at time %t", $time); |
do_module_burst_read(3'h4, 16'd1, 32'd18); |
$display("PPC = %x, expected 0x00000028", input_data32[0]); |
|
#1000; |
$display("Getting R1 at time %t", $time); |
do_module_burst_read(3'h4, 16'd1, 32'h401); // Word size, count, addr; save old instr |
$display("R1 = %d, expected 5", input_data32[0]); |
|
#1000; |
$display("Un-set step bit at %t", $time); |
static_data32[0] = 32'h0; // Trap causes stall |
do_module_burst_write(3'h4, 16'd1, (6 << 11)+16); |
|
// Put a trap instr at 0x20 |
#1000; |
$display("Select WB at %t", $time); |
select_debug_module(`DBG_TOP_WISHBONE_DEBUG_MODULE); |
#1000; |
$display("Save old instr at %t", $time); |
do_module_burst_read(3'h4, 16'd1, 32'h20); // Save old instr |
#1000; |
$display("Put trap instr at %t", $time); |
static_data32[0] = 32'h21000001; /* l.trap */ |
do_module_burst_write(3'h4, 16'd1, 32'h20); // put new instr |
#1000; |
$display("Select CPU0 at %t", $time); |
select_debug_module(`DBG_TOP_CPU0_DEBUG_MODULE); |
#1000; |
$display("Set PC to 0x24 at %t", $time); |
static_data32[0] = 32'h24; |
do_module_burst_write(3'h4, 16'd1, 32'd16); // Set PC to 0x24 |
#1000; |
$display("Unstall at time %t", $time); |
write_module_internal_register(32'h0, 8'h1, 32'h0, 8'h2); // idx, idxlen, data, datalen |
// *** Set TRAP instruction very near previous one *** |
#1000; |
$display("Put TRAP instruction very near previous one at time %t", $time); |
do_module_burst_read(3'h4, 16'd1, 32'h20); // Save old instr in input_data32[0] |
original_instruction = input_data32[0]; |
static_data32[0] = 32'h21000001; /* l.trap */ |
do_module_burst_write(3'h4, 16'd1, 32'h20); // put new instr |
select_debug_module(`DBG_TOP_CPU0_DEBUG_MODULE); |
static_data32[0] = 32'h1c; |
do_module_burst_write(3'h4, 16'd1, 32'd16); // Set PC to 0x1c |
|
unstall(); |
wait_for_stall(); |
check_results(32'h24, 32'h20, 32'd50); // Expected NPC, PPC, R1 |
|
static_data32[0] = original_instruction; |
select_debug_module(`DBG_TOP_WISHBONE_DEBUG_MODULE); |
do_module_burst_write(3'h4, 16'd1, 32'h20); // put back old instr |
|
// We assume it stalls again here... |
#1000; |
// *** Set TRAP instruction at the start *** |
#1000; |
$display("Put TRAP at the start at time %t", $time); |
do_module_burst_read(3'h4, 16'd1, 32'h10); // Save old instr in input_data32[0] |
original_instruction = input_data32[0]; |
static_data32[0] = 32'h21000001; /* l.trap */ |
do_module_burst_write(3'h4, 16'd1, 32'h10); // put new instr |
select_debug_module(`DBG_TOP_CPU0_DEBUG_MODULE); |
static_data32[0] = 32'h20; |
do_module_burst_write(3'h4, 16'd1, 32'd16); // Set PC to 0x20 |
|
unstall(); |
wait_for_stall(); |
check_results(32'h14, 32'h10, 32'd99); // Expected NPC, PPC, R1 |
|
static_data32[0] = original_instruction; |
select_debug_module(`DBG_TOP_WISHBONE_DEBUG_MODULE); |
do_module_burst_write(3'h4, 16'd1, 32'h10); // put back old instr |
|
err_data = 1; |
while(err_data != 0) |
begin |
$display("Testing for stall at %t", $time); |
read_module_internal_register(8'd2, err_data); // We assume the register is already selected |
#1000; |
end |
// *** Test the STEP bit some more *** |
#1000; |
select_debug_module(`DBG_TOP_CPU0_DEBUG_MODULE); |
$display("Set step bit at time %t", $time); |
static_data32[0] = (1 << 22); // set step bit |
do_module_burst_write(3'h4, 16'd1, (6<<11) + 16); // 3-bit word size (bytes), 16-bit word count, 32-bit start address |
|
// Unstall x5 |
for(i = 0; i < 5; i = i + 1) |
begin |
#1000; |
$display("Unstall (%d/5) at time %t", i, $time); |
unstall(); |
wait_for_stall(); |
end |
|
// *** The software self-test does 2 separate reads here... |
$display("Getting NPC at time %t", $time); |
do_module_burst_read(3'h4, 16'd3, 32'd16); |
|
$display("NPC = %x, expected 0x00000024", input_data32[0]); |
$display("PPC = %x, expected 0x00000020", input_data32[2]); |
check_results(32'h28, 32'h24, 32'd101); // Expected NPC, PPC, R1 |
|
|
|
static_data32[0] = 32'h24; |
do_module_burst_write(3'h4, 16'd1, 32'd16); // Set PC to 0x24 |
|
// Unstall x2 |
for(i = 0; i < 2; i = i + 1) |
begin |
#1000; |
$display("Unstall (%d/2) at time %t", i, $time); |
unstall(); |
wait_for_stall(); |
end |
|
check_results(32'h10, 32'h28, 32'd201); // Expected NPC, PPC, R1 |
|
`endif |
|
|
end |
|
task check_results; |
input [31:0] expected_npc; |
input [31:0] expected_ppc; |
input [31:0] expected_r1; |
begin |
//$display("Getting NPC at time %t", $time); |
do_module_burst_read(3'h4, 16'd3, 32'd16);// The software self-test does 2 separate reads here |
|
$display("NPC = %x, expected %x", input_data32[0], expected_npc); |
$display("PPC = %x, expected %x", input_data32[2], expected_ppc); |
|
//$display("Getting R1 at time %t", $time); |
do_module_burst_read(3'h4, 16'd1, 32'h401); // Word size, count, addr |
$display("R1 = %x, expected %x", input_data32[0], expected_r1); |
end |
endtask |
|
task unstall; |
begin |
//$display("Unstall at time %t", $time); |
write_module_internal_register(32'h0, 8'h1, 32'h0, 8'h2); // idx, idxlen, data, datalen |
end |
endtask |
|
task wait_for_stall; |
reg[31:0] regstate; |
begin |
regstate = 0; |
while(regstate == 0) |
begin |
//$display("Testing for stall at %t", $time); |
read_module_internal_register(8'd2, regstate); // We assume the register is already selected |
#1000; |
end |
end |
endtask |
|
task initialize_memory; |
input [31:0] start_addr; |
input [31:0] length; |
482,7 → 604,7
write_bit(`JTAG_TMS_bit); // update_dr |
write_bit(3'h0); // idle |
|
$display("Selecting module (%0x)", moduleid); |
//$display("Selecting module (%0x)", moduleid); |
|
// Read back the status to make sure a valid chain is selected |
/* Pointless, the newly selected module would respond instead... |
592,7 → 714,7
reg [31:0] crc_read; |
reg [5:0] word_size_bits; |
begin |
$display("Doing burst read, word size %d, word count %d, start address 0x%x", word_size_bytes, word_count, start_address); |
//$display("Doing burst read, word size %d, word count %d, start address 0x%x", word_size_bytes, word_count, start_address); |
instream = 64'h0; |
word_size_bits = word_size_bytes << 3; |
crc_calc_i = 32'hffffffff; |
634,9 → 756,9
j = j + 1; |
end |
|
if(j > 1) begin |
$display("Took %0d tries before good status bit during burst read", j); |
end |
//if(j > 1) begin |
// $display("Took %0d tries before good status bit during burst read", j); |
//end |
`endif |
|
// Now, repeat... |
651,9 → 773,9
j = j + 1; |
end |
|
if(j > 1) begin |
$display("Took %0d tries before good status bit during burst read", j); |
end |
//if(j > 1) begin |
// $display("Took %0d tries before good status bit during burst read", j); |
//end |
`endif |
|
jtag_read_write_stream(64'h0, {2'h0,(word_size_bytes<<3)},0,instream); |
668,7 → 790,7
// Read the data CRC from the debug module. |
jtag_read_write_stream(64'h0, 6'd32, 1, crc_read); |
if(crc_calc_o != crc_read) $display("CRC ERROR! Computed 0x%x, read CRC 0x%x", crc_calc_o, crc_read); |
else $display("CRC OK!"); |
//else $display("CRC OK!"); |
|
// Finally, shift out 5 0's, to make the next command a NOP |
// Not necessary, debug unit won't latch a new opcode at the end of a burst |
693,7 → 815,7
reg crc_match; |
reg [5:0] word_size_bits; |
begin |
$display("Doing burst write, word size %d, word count %d, start address 0x%x", word_size_bytes, word_count, start_address); |
//$display("Doing burst write, word size %d, word count %d, start address 0x%x", word_size_bytes, word_count, start_address); |
word_size_bits = word_size_bytes << 3; |
crc_calc_i = 32'hffffffff; |
|
752,7 → 874,7
// Read the 'CRC match' bit, and go to exit1_dr |
read_write_bit(`JTAG_TMS_bit, crc_match); |
if(!crc_match) $display("CRC ERROR! match bit after write is %d (computed CRC 0x%x)", crc_match, crc_calc_o); |
else $display("CRC OK!"); |
//else $display("CRC OK!"); |
|
// Finally, shift out 5 0's, to make the next command a NOP |
// Not necessary, module will not latch new opcode during burst |
913,4 → 1035,6
end |
endtask |
|
endmodule |
endmodule // adv_debug_tb |
|
|
/bench/full_system/xsv_fpga_top.v
44,6 → 44,9
// CVS Revision History |
// |
// $Log: xsv_fpga_top.v,v $ |
// Revision 1.6 2011-02-14 04:16:25 natey |
// Major functionality enhancement - now duplicates the full OR1K self-test performed by adv_jtag_bridge. |
// |
// Revision 1.5 2010-01-16 02:15:22 Nathan |
// Updated to match changes in hardware. Added support for hi-speed mode. |
// |
146,7 → 149,6
wire wb_dm_we_o; |
wire wb_dm_stb_o; |
wire wb_dm_cyc_o; |
wire wb_dm_cab_o; |
wire wb_dm_ack_i; |
wire wb_dm_err_i; |
|
193,7 → 195,6
wire wb_rim_rty_i = 1'b0; |
wire wb_rim_we_o; |
wire wb_rim_stb_o; |
wire wb_rim_cab_o; |
//wire [31:0] wb_rif_adr; |
//reg prefix_flash; |
|
210,7 → 211,6
wire wb_rdm_rty_i = 1'b0; |
wire wb_rdm_we_o; |
wire wb_rdm_stb_o; |
wire wb_rdm_cab_o; |
|
// |
// RISC misc |
527,7 → 527,6
.iwb_rty_i ( wb_rim_rty_i ), |
.iwb_we_o ( wb_rim_we_o ), |
.iwb_stb_o ( wb_rim_stb_o ), |
.iwb_cab_o ( wb_rim_cab_o ), |
|
// WISHBONE Data Master |
.dwb_clk_i ( wb_clk ), |
542,7 → 541,6
.dwb_rty_i ( wb_rdm_rty_i ), |
.dwb_we_o ( wb_rdm_we_o ), |
.dwb_stb_o ( wb_rdm_stb_o ), |
.dwb_cab_o ( wb_rdm_cab_o ), |
|
// Debug |
.dbg_stall_i ( dbg_stall ), // Set to 1'b0 if debug is absent / broken |
733,7 → 731,7
// WISHBONE Initiator 3 |
.m3_cyc_i ( wb_dm_cyc_o ), |
.m3_stb_i ( wb_dm_stb_o ), |
.m3_cab_i ( wb_dm_cab_o ), |
.m3_cab_i ( 1'b0 ), |
.m3_adr_i ( wb_dm_adr_o ), |
.m3_sel_i ( wb_dm_sel_o ), |
.m3_we_i ( wb_dm_we_o ), |
745,7 → 743,7
// WISHBONE Initiator 4 |
.m4_cyc_i ( wb_rdm_cyc_o ), |
.m4_stb_i ( wb_rdm_stb_o ), |
.m4_cab_i ( wb_rdm_cab_o ), |
.m4_cab_i ( 1'b0 ), |
.m4_adr_i ( wb_rdm_adr_o ), |
.m4_sel_i ( wb_rdm_sel_o ), |
.m4_we_i ( wb_rdm_we_o ), |
757,7 → 755,7
// WISHBONE Initiator 5 |
.m5_cyc_i ( wb_rim_cyc_o ), |
.m5_stb_i ( wb_rim_stb_o ), |
.m5_cab_i ( wb_rim_cab_o ), |
.m5_cab_i ( 1'b0 ), |
.m5_adr_i ( wb_rim_adr_o ), |
.m5_sel_i ( wb_rim_sel_o ), |
.m5_we_i ( wb_rim_we_o ), |
/bench/full_system/onchip_ram_top.v
0,0 → 1,281
////////////////////////////////////////////////////////////////////// |
//// //// |
//// onchip_ram_top.v //// |
//// //// |
//// //// |
//// //// |
//// Author(s): //// |
//// De Nayer Instituut (emsys.denayer.wenk.be) //// |
//// Nathan Yawn (nathan.yawn@epfl.ch) //// |
//// //// |
//// //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2003-2008 Authors //// |
//// //// |
//// 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 //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
// // |
// This file is a simple wrapper for on-chip (FPGA) RAM blocks, // |
// coupled with a simple WISHBONE bus interface. It supports 2- // |
// cycle writes, and 1-cycle reads. Bursts using bus tags (for // |
// registered-feedback busses) are not supported at present. // |
// Altera ALTSYNCRAM blocks are instantiated directly. Xilinx // |
// BRAM blocks are not as easy to declare for a wide range of // |
// devices, they are implied instead of declared directly. // |
// // |
////////////////////////////////////////////////////////////////////// |
// |
// CVS Revision History |
// |
// $Log: onchip_ram_top.v,v $ |
// Revision 1.1 2010-03-29 19:34:52 Nathan |
// The onchip_ram memory unit is not distributed on the OpenCores website as of this checkin; this version of the core may be used with the advanced debug system testbench until it is. |
// |
// Revision 1.1 2008/07/18 20:13:48 Nathan |
// Changed directory structure to match existing projects. |
// |
// Revision 1.2 2008/05/22 19:56:36 Nathan |
// Added implied BRAM for Xilinx FPGAs. Also added copyright, CVS log, and brief description. |
// |
|
|
`define ALTERA |
|
|
module onchip_ram_top ( |
wb_clk_i, wb_rst_i, |
wb_dat_i, wb_dat_o, wb_adr_i, wb_sel_i, wb_we_i, wb_cyc_i, |
wb_stb_i, wb_ack_o, wb_err_o |
); |
|
// Function to calculate width of address signal. |
function integer log2; |
input [31:0] value; |
for (log2=0; value>0; log2=log2+1) |
value = value>>1; |
endfunction |
|
// |
// Parameters |
// |
parameter dwidth = 32; |
parameter size_bytes = 4096; |
parameter initfile = "NONE"; |
parameter words = (size_bytes / (dwidth/8)); // Don't override this. Really. |
parameter awidth = log2(size_bytes)-1; // Don't override this either. |
parameter bewidth = (dwidth/8); // Or this. |
|
// |
// I/O Ports |
// |
input wb_clk_i; |
input wb_rst_i; |
// |
// WB slave i/f |
// |
input [dwidth-1:0] wb_dat_i; |
output [dwidth-1:0] wb_dat_o; |
input [awidth-1:0] wb_adr_i; |
input [bewidth-1:0] wb_sel_i; |
input wb_we_i; |
input wb_cyc_i; |
input wb_stb_i; |
output wb_ack_o; |
output wb_err_o; |
// |
// Internal regs and wires |
// |
wire we; |
wire [bewidth-1:0] be_i; |
wire [dwidth-1:0] wb_dat_o; |
wire ack_we; |
reg ack_we1; |
reg ack_we2; |
reg ack_re; |
|
// |
// Aliases and simple assignments |
// |
assign wb_ack_o = ack_re | ack_we; |
assign wb_err_o = 1'b0; //wb_cyc_i & wb_stb_i & ???; |
assign we = wb_cyc_i & wb_stb_i & wb_we_i & (|wb_sel_i[bewidth-1:0]); |
assign be_i = (wb_cyc_i & wb_stb_i) * wb_sel_i; |
|
// |
// Write acknowledge |
// Little trick to keep the writes single-cycle: |
// set the write ack signal on the falling clk edge, so it will be set halfway through the |
// cycle and be registered at the end of the first clock cycle. To prevent contention for |
// the next half-cycle, latch the ack_we1 signal on the next rising edge, and force the |
// bus output low when that latched signal is high. |
always @ (negedge wb_clk_i or posedge wb_rst_i) |
begin |
if (wb_rst_i) |
ack_we1 <= 1'b0; |
else |
if (wb_cyc_i & wb_stb_i & wb_we_i & ~ack_we) |
ack_we1 <= #1 1'b1; |
else |
ack_we1 <= #1 1'b0; |
end |
|
always @ (posedge wb_clk_i or posedge wb_rst_i) |
begin |
if (wb_rst_i) |
ack_we2 <= 1'b0; |
else |
ack_we2 <= ack_we1; |
end |
|
assign ack_we = ack_we1 & ~ack_we2; |
|
|
// |
// read acknowledge |
// |
always @ (posedge wb_clk_i or posedge wb_rst_i) |
begin |
if (wb_rst_i) |
ack_re <= 1'b0; |
else |
if (wb_cyc_i & wb_stb_i & ~wb_err_o & ~wb_we_i & ~ack_re) |
ack_re <= 1'b1; |
else |
ack_re <= 1'b0; |
end |
|
|
`ifdef ALTERA |
// |
// change intended_device_family according to the FPGA device (Stratix or Cyclone) |
// |
altsyncram altsyncram_component ( |
.wren_a (we), |
.clock0 (wb_clk_i), |
.byteena_a (be_i), |
.address_a (wb_adr_i[awidth-1:2]), |
.data_a (wb_dat_i), |
.q_a (wb_dat_o)); |
defparam |
altsyncram_component.intended_device_family = "CycloneII", |
altsyncram_component.width_a = dwidth, |
altsyncram_component.widthad_a = (awidth-2), |
altsyncram_component.numwords_a = (words), |
altsyncram_component.operation_mode = "SINGLE_PORT", |
altsyncram_component.outdata_reg_a = "UNREGISTERED", |
altsyncram_component.indata_aclr_a = "NONE", |
altsyncram_component.wrcontrol_aclr_a = "NONE", |
altsyncram_component.address_aclr_a = "NONE", |
altsyncram_component.outdata_aclr_a = "NONE", |
altsyncram_component.width_byteena_a = bewidth, |
altsyncram_component.byte_size = 8, |
altsyncram_component.byteena_aclr_a = "NONE", |
altsyncram_component.ram_block_type = "AUTO", |
altsyncram_component.lpm_type = "altsyncram", |
altsyncram_component.init_file = initfile; |
|
|
`else |
// Xilinx does not have anything so neat as a resizable memory array. |
// We use generic code, which will imply a BRAM array. |
// This will also work for non-Xilinx architectures, but be warned that |
// it will not be recognized as an implied RAM block by the current Altera |
// tools. |
|
// The actual memory array...4 banks, for 4 separate byte lanes |
reg [7:0] mem_bank0 [0:(words-1)]; |
reg [7:0] mem_bank1 [0:(words-1)]; |
reg [7:0] mem_bank2 [0:(words-1)]; |
reg [7:0] mem_bank3 [0:(words-1)]; |
|
// Write enables, qualified with byte lane enables |
wire we_0, we_1, we_2, we_3; |
|
// Enable, indicates any read or write operation |
wire en; |
|
// Yes, separate address registers, which will hold identical data. This |
// is necessary to correctly imply a Xilinx BRAM. Because that's just |
// how they roll. |
reg [(awidth-3):0] addr_reg0; |
reg [(awidth-3):0] addr_reg1; |
reg [(awidth-3):0] addr_reg2; |
reg [(awidth-3):0] addr_reg3; |
|
assign we_0 = be_i[0] & wb_we_i; |
assign we_1 = be_i[1] & wb_we_i; |
assign we_2 = be_i[2] & wb_we_i; |
assign we_3 = be_i[3] & wb_we_i; |
|
assign en = (|be_i); |
|
// Sequential bits. Setting of the address registers, and memory array writes. |
always @ (posedge wb_clk_i) |
begin |
if (en) |
begin |
addr_reg0 <= wb_adr_i[(awidth-1):2]; |
if (we_0) |
begin |
mem_bank0[wb_adr_i[(awidth-1):2]] <= wb_dat_i[7:0]; |
end |
end |
|
if (en) |
begin |
addr_reg1 <= wb_adr_i[(awidth-1):2]; |
if (we_1) |
begin |
mem_bank1[wb_adr_i[(awidth-1):2]] <= wb_dat_i[15:8]; |
end |
end |
|
if (en) |
begin |
addr_reg2 <= wb_adr_i[(awidth-1):2]; |
if (we_2) |
begin |
mem_bank2[wb_adr_i[(awidth-1):2]] <= wb_dat_i[23:16]; |
end |
end |
|
if (en) |
begin |
addr_reg3 <= wb_adr_i[(awidth-1):2]; |
if (we_3) |
begin |
mem_bank3[wb_adr_i[(awidth-1):2]] <= wb_dat_i[31:24]; |
end |
end |
|
end |
|
|
// Data output. Combinatorial, no output register. |
assign wb_dat_o = {mem_bank3[addr_reg2], mem_bank2[addr_reg2], mem_bank1[addr_reg1], mem_bank0[addr_reg0]}; |
|
`endif |
|
endmodule |
bench/full_system/onchip_ram_top.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property