www.pudn.com > noc.rar > bram16k.cpp
/*
* TU Eindhoven
* Eindhoven, The Netherlands
*
* Name : bram16k.cpp
*
* Author : A.S.Slusarczyk@tue.nl
*
* Date :
*
* Function : RAM based on VirtexII 16kb BlockRAMs
*
*
*/
#include "bram16k.h"
#ifdef MEM_DBG
#include "dbg_mem.h"
#endif
void BRAM16K_WRAPPER::reg()
{
sc_bv<2> ar = addr.read().range(1,0);
#ifdef MEM_DBG
sc_uint<2> _r = r.read(), _w = w.read();
extern void hack_pc();
if( (_r == 1 || _w == 1) && ar != 0 ){
cout << "WARNING: Non-aligned word access address=" << addr.read().to_uint() << " r=" << _r << " w=" << _w << endl;
cout << "\t" << name() << " PCs:";
hack_pc();
}
if( dbg_mem_hit( addr.read().to_uint() ) ){
cout << "MEMORY ACCESS "
<< " addr=0x" << hex << addr.read().to_uint() << dec << " "
<< (_r==2 ? "read byte " : (_r==1 ? "read word " : "") )
<< (_w==2 ? "write byte " : (_w==1 ? "write word " : "") )
<< "data=0x" << hex << din.read().to_uint() << dec << endl;
cout << "\t" << name() << " PCs:";
hack_pc();
}
#endif
if( en.read()[0]!=0 )
{
// register r and w inputs
r_reg.write(r.read());
w_reg.write(w.read());
byte_reg.write(ar);
}
}
void BRAM16K_WRAPPER::in()
{
// read/write request
sc_uint<2> iw=w.read(), ir=r.read();
sc_bv a = addr.read();
// discard two least significant bits of the address
// they are only used in byte mode --
// for that purpose they are registered in byte_reg
sc_bv<12> a_13_2 = a.range(13,2);
sc_uint<12> addr12 = a_13_2;
ADDR.write(addr12);
sc_bv dwr = din.read();
// if w == 2, we're writing the LSByte of the input word to the appropriate address
sc_bv<2> byteb = a.range(1,0);
sc_uint<2> byteno = byteb;
sc_bv<4> b0 = dwr.range(7,4), b1 = dwr.range(3,0);
bool byte_to_0 = (iw==2 && byteno==0),
byte_to_1 = (iw==2 && byteno==1),
byte_to_2 = (iw==2 && byteno==2),
byte_to_3 = (iw==2 && byteno==3);
// split the input data between the two memory blocks
sc_bv<4> dwr0 = dwr.range(31,28), dwr1 = dwr.range(27,24), dwr2 = dwr.range(23,20), dwr3 = dwr.range(19,16),
dwr4 = dwr.range(15,12), dwr5 = dwr.range(11,8), dwr6 = dwr.range(7,4), dwr7 = dwr.range(3,0);
DI00.write(byte_to_0 ? b0 : dwr0);
DI01.write(byte_to_0 ? b1 : dwr1);
DI02.write(byte_to_1 ? b0 : dwr2);
DI03.write(byte_to_1 ? b1 : dwr3);
DI04.write(byte_to_2 ? b0 : dwr4);
DI05.write(byte_to_2 ? b1 : dwr5);
DI06.write(byte_to_3 ? b0 : dwr6);
DI07.write(byte_to_3 ? b1 : dwr7);
// BlockRAM enable needs to be active for both read and write
bool e = ((en.read()[0]!=0) && ((ir!=0)||(iw!=0)));
EN.write(e);
WE0.write(iw==1 || iw==2 && byte_to_0);
WE1.write(iw==1 || iw==2 && byte_to_1);
WE2.write(iw==1 || iw==2 && byte_to_2);
WE3.write(iw==1 || iw==2 && byte_to_3);
SSR.write(0);
CLK.write(clk.read());
}
void BRAM16K_WRAPPER::out()
{
sc_bv<24> data24;
sc_bv<4> d0, d1, d2, d3, d4, d5, d6, d7;
sc_bv<8> msbyte;
// gather bytes of the word from memory blocks
d0 = DO00.read();
d1 = DO01.read();
d2 = DO02.read();
d3 = DO03.read();
d4 = DO04.read();
d5 = DO05.read();
d6 = DO06.read();
d7 = DO07.read();
// check byte/word mode
sc_uint<2> iw=w_reg.read(), ir=r_reg.read();
bool byte_mode = (iw==2 || ir==2);
data24 = (d2, d3, d4, d5, d6, d7);
// depending on mode (byte/word) select the most significant byte
if( byte_mode )
{
// in byte mode take one of the bytes,
// depending on the last two bits of the address
sc_uint<2> byteno = byte_reg.read();
switch( byteno ){
case 0: msbyte = (d0,d1); break;
case 1: msbyte = (d2,d3); break;
case 2: msbyte = (d4,d5); break;
case 3: msbyte = (d6,d7); break;
}
}
else
{
// word mode
msbyte = (d0,d1);
}
dout.write( (msbyte, data24) );
memwait.write( false );
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void BRAM16K_DBGWRAPPER::in()
{
bool clk = CLK.read();
dCLK.write(clk);
// discard two least significant bits of the address
sc_uint<12> addr = ADDR.read().range(13,2);
dADDR.write(addr);
// split the input data between the memory blocks
sc_int<32> dwr = DI.read();
sc_int<4> dwr0 = dwr.range(31,28), dwr1 = dwr.range(28,24), dwr2 = dwr.range(23,20), dwr3 = dwr.range(19,16),
dwr4 = dwr.range(15,12), dwr5 = dwr.range(11,8), dwr6 = dwr.range(7,4), dwr7 = dwr.range(3,0);
dDI00.write(dwr0); dDI01.write(dwr1); dDI02.write(dwr2); dDI03.write(dwr3);
dDI04.write(dwr4); dDI05.write(dwr5); dDI06.write(dwr6); dDI07.write(dwr7);
bool en = EN.read(), we = WE.read();
dEN.write(en);
dWE.write(we);
dSSR.write(0);
}
void BRAM16K_DBGWRAPPER::out()
{
sc_int<32> data;
sc_int<4> d0, d1, d2, d3, d4, d5, d6, d7;
// gather bytes of the word from memory blocks
d0 = dDO00.read();
d1 = dDO01.read();
d2 = dDO02.read();
d3 = dDO03.read();
d4 = dDO04.read();
d5 = dDO05.read();
d6 = dDO06.read();
d7 = dDO07.read();
data = (d0, d1, d2, d3, d4, d5, d6, d7);
DO.write( data );
}
#ifndef VERILOG
void BRAM16K::mem_init(const char *filename, int size){
vector* > v;
v.push_back(bram00->memory);
v.push_back(bram01->memory);
v.push_back(bram02->memory);
v.push_back(bram03->memory);
v.push_back(bram04->memory);
v.push_back(bram05->memory);
v.push_back(bram06->memory);
v.push_back(bram07->memory);
init_memory(&v,size,filename);
}
void BRAM16K::mem_dump(const char *filename, int size){
vector* > v;
v.push_back(bram00->memory);
v.push_back(bram01->memory);
v.push_back(bram02->memory);
v.push_back(bram03->memory);
v.push_back(bram04->memory);
v.push_back(bram05->memory);
v.push_back(bram06->memory);
v.push_back(bram07->memory);
dump_memory(&v,size,filename);
}
#endif