OpenCores
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

powered by: WebSVN 2.1.0

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