#include "tb_sdram_mem.h"
#include <queue>
#define SDRAM_COL_W 9
#define SDRAM_BANK_W 2
#define SDRAM_ROW_W 13
#define NUM_ROWS (1 << SDRAM_ROW_W)
// REF: https://www.micron.com/~/media/documents/products/data-sheet/dram/128mb_x4x8x16_ait-aat_sdram.pdf
#define MAX_ROW_OPEN_TIME sc_time(35, SC_US)
#define MIN_ACTIVE_TO_ACTIVE sc_time(60, SC_NS)
#define MIN_ACTIVE_TO_ACCESS sc_time(15, SC_NS)
#define MAX_ROW_REFRESH_TIME (sc_time((64000000 / NUM_ROWS), SC_NS) + sc_time(200, SC_NS)) // Add some slack (FIXME)
#define DPRINTF //printf
//-----------------------------------------------------------------
// process: Handle requests
//-----------------------------------------------------------------
void tb_sdram_mem::process(void)
{
typedef enum
{
SDRAM_CMD_INHIBIT = 0,
SDRAM_CMD_NOP,
SDRAM_CMD_ACTIVE,
SDRAM_CMD_READ,
SDRAM_CMD_WRITE,
SDRAM_CMD_BURST_TERM,
SDRAM_CMD_PRECHARGE,
SDRAM_CMD_REFRESH,
SDRAM_CMD_LOAD_MODE
} t_sdram_cmd;
sc_uint <SDRAM_COL_W> col = 0;
sc_uint <SDRAM_ROW_W> row = 0;
sc_uint <SDRAM_BANK_W> bank = 0;
sc_uint <32> addr = 0;
uint16_t resp_data[3];
// Clear response pipeline
for (int i=0;i<sizeof(resp_data)/sizeof(resp_data[0]);i++)
resp_data[i] = 0;
for (unsigned b=0;b<NUM_BANKS;b++)
m_activate_time[b] = sc_time_stamp();
m_refresh_cnt = 0;
while (1)
{
sdram_io_master sdram_i = sdram_in.read();
sdram_io_slave sdram_o = sdram_out.read();
t_sdram_cmd new_cmd;
// Command decoder
if (sdram_i.CS)
new_cmd = SDRAM_CMD_INHIBIT;
else
{
if (sdram_i.RAS && sdram_i.CAS && sdram_i.WE)
new_cmd = SDRAM_CMD_NOP;
else if (!sdram_i.RAS && sdram_i.CAS && sdram_i.WE)
new_cmd = SDRAM_CMD_ACTIVE;
else if (sdram_i.RAS && !sdram_i.CAS && sdram_i.WE)
new_cmd = SDRAM_CMD_READ;
else if (sdram_i.RAS && !sdram_i.CAS && !sdram_i.WE)
new_cmd = SDRAM_CMD_WRITE;
else if (sdram_i.RAS && sdram_i.CAS && !sdram_i.WE)
new_cmd = SDRAM_CMD_BURST_TERM;
else if (!sdram_i.RAS && sdram_i.CAS && !sdram_i.WE)
new_cmd = SDRAM_CMD_PRECHARGE;
else if (!sdram_i.RAS && !sdram_i.CAS && sdram_i.WE)
new_cmd = SDRAM_CMD_REFRESH;
else if (!sdram_i.RAS && !sdram_i.CAS && !sdram_i.WE)
new_cmd = SDRAM_CMD_LOAD_MODE;
else
sc_assert(0); // NOT SURE...
}
// Check row open time...
for (unsigned b = 0;b < NUM_BANKS;b++)
if (m_active_row[b] != -1 && (sc_time_stamp() - m_activate_time[b]) > MAX_ROW_OPEN_TIME)
{
sc_assert(!"Row open too long...");
}
// Configure SDRAM
if (new_cmd == SDRAM_CMD_LOAD_MODE)
{
m_configured = true;
m_burst_type = (tBurstType)(int)sdram_i.ADDR[3];
m_write_burst_en = (bool)!sdram_i.ADDR[9];
m_burst_length = (tBurstLength)(int)sdram_i.ADDR.range(2,0);
m_cas_latency = (int)sdram_i.ADDR.range(6,4);
DPRINTF("SDRAM: MODE - write burst %d, burst len %d, CAS latency %d\n", m_write_burst_en, m_burst_length, m_cas_latency);
sc_assert(m_burst_type == BURST_TYPE_SEQUENTIAL);
}
// Auto refresh
else if (new_cmd == SDRAM_CMD_REFRESH)
{
//cout << "SDRAM: REFRESH @ " << sc_time_stamp() << " - delta = " << (sc_time_stamp() - m_last_refresh) << " - allowed " << MAX_ROW_REFRESH_TIME <<endl;
// Check no rows open..
for (unsigned b = 0;b < NUM_BANKS;b++)
{
sc_assert(m_active_row[b] == -1);
}
// Once init sequence complete, check for auto-refresh period...
if (m_refresh_cnt > 2)
{
sc_assert((sc_time_stamp() - m_last_refresh) < MAX_ROW_REFRESH_TIME);
}
m_last_refresh = sc_time_stamp();
if (m_refresh_cnt < 0xFFFFFFFF)
m_refresh_cnt += 1;
}
// Row is activated and copied into the row buffer of the bank
else if (new_cmd == SDRAM_CMD_ACTIVE)
{
sc_assert(m_configured);
sc_assert(m_refresh_cnt >= 2);
bank = sdram_i.BA;
row = sdram_i.ADDR;
DPRINTF("SDRAM: ACTIVATE Row=%x, Bank=%x\n", (unsigned)row, (unsigned)bank);
// A row should not be open
sc_assert(m_active_row[bank] == -1);
// ACTIVATE periods long enough...
sc_assert((sc_time_stamp() - m_activate_time[bank]) > MIN_ACTIVE_TO_ACTIVE);
// Mark row as open
m_active_row[bank] = row;
m_activate_time[bank] = sc_time_stamp();
}
// Read command
else if (new_cmd == SDRAM_CMD_READ)
{
sc_assert(m_configured);
bool en_ap = sdram_i.ADDR[SDRAM_COL_W];
col = sdram_i.ADDR;
bank = sdram_i.BA;
row = m_active_row[bank];
// A row should be open
sc_assert(m_active_row[bank] != -1);
// DQM expected to be low
sc_assert(sdram_i.DQM == 0x0);
// Check row activate timing
sc_assert((sc_time_stamp() - m_activate_time[bank]) > MIN_ACTIVE_TO_ACCESS);
// Address = RBC
addr.range(SDRAM_COL_W, 2) = col.range(SDRAM_COL_W-1, 1);
addr.range(SDRAM_COL_W+SDRAM_BANK_W, SDRAM_COL_W+SDRAM_BANK_W-1) = bank;
addr.range(31, SDRAM_COL_W+SDRAM_BANK_W+1) = row;
m_burst_offset = 0;
uint32_t data = read32((uint32_t)addr);
DPRINTF("SDRAM: READ %08x = %08x [Row=%x, Bank=%x, Col=%x]\n", (uint32_t)addr, data, (unsigned)row, (unsigned)bank, (unsigned)col);
resp_data[m_cas_latency-2] = data >> (m_burst_offset * 8);
m_burst_offset += 2;
switch (m_burst_length)
{
default:
case BURST_LEN_1:
m_burst_read = 1-1;
break;
case BURST_LEN_2:
m_burst_read = 2-1;
break;
case BURST_LEN_4:
m_burst_read = 4-1;
break;
case BURST_LEN_8:
m_burst_read = 8-1;
break;
}
m_burst_close_row[bank] = en_ap;
}
// Write command
else if (new_cmd == SDRAM_CMD_WRITE)
{
sc_assert(m_configured);
bool en_ap = sdram_i.ADDR[SDRAM_COL_W];
col = sdram_i.ADDR;
bank = sdram_i.BA;
row = m_active_row[bank];
// A row should be open
sc_assert(m_active_row[bank] != -1);
// Check row activate timing
sc_assert((sc_time_stamp() - m_activate_time[bank]) > MIN_ACTIVE_TO_ACCESS);
// Address = RBC
addr.range(SDRAM_COL_W, 2) = col.range(SDRAM_COL_W-1, 1);
addr.range(SDRAM_COL_W+SDRAM_BANK_W, SDRAM_COL_W+SDRAM_BANK_W-1) = bank;
addr.range(31, SDRAM_COL_W+SDRAM_BANK_W+1) = row;
uint32_t data = (uint32_t)sdram_i.DATA_OUTPUT;
uint8_t mask = 0;
m_burst_offset = 0;
data <<= (m_burst_offset * 8);
mask = 0x3 << (m_burst_offset);
// Lower byte - disabled
if (sdram_i.DQM[0])
{
data &= ~(0xFF << ((m_burst_offset + 0) * 8));
mask &= ~(1 << (m_burst_offset + 0));
}
没有合适的资源?快使用搜索试试~ 我知道了~
基于Verilog与C++实现带AXI4接口的SDRAM控制器(源码+说明文档).rar
共26个文件
h:12个
cpp:5个
v:3个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
5星 · 超过95%的资源 2 下载量 155 浏览量
2023-04-10
17:18:55
上传
评论
收藏 31KB RAR 举报
温馨提示
1、资源内容:基于Verilog与C++实现带AXI4接口的SDRAM控制器(源码+说明文档).rar 2、适用人群:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业或毕业设计,作为“参考资料”使用。 3、更多仿真源码和数据集下载列表(自行寻找自己需要的):https://blog.csdn.net/m0_62143653?type=download 4、免责声明:本资源作为“参考资料”而不是“定制需求”不一定能够满足所有人的需求,需要有一定的基础能够看懂代码,能够自行调试,能够自行添加功能修改代码。由于作者大厂工作较忙,不提供答疑服务,如不存在资源缺失问题概不负责,谢谢理解。
资源推荐
资源详情
资源评论
收起资源包目录
基于Verilog与C++实现带AXI4接口的SDRAM控制器(源码+说明文档).rar (26个子文件)
基于Verilog与C++实现带AXI4接口的SDRAM控制器(源码+说明文档)
tb
makefile 801B
testbench_vbase.h 2KB
sdram_axi.cpp 6KB
testbench.h 2KB
tb_memory.h 5KB
makefile.generate_verilated 1KB
axi4.h 7KB
tb_axi4_driver.h 3KB
tb_mem_test.cpp 4KB
tb_sdram_mem.h 3KB
tb_axi4_driver.cpp 11KB
main.cpp 4KB
sdram_axi.h 4KB
sdram_io.h 4KB
axi4_defines.h 739B
makefile.build_verilated 2KB
tb_driver_api.h 561B
makefile.build_sysc_tb 2KB
sc_reset_gen.h 496B
tb_sdram_mem.cpp 13KB
tb_mem_test.h 2KB
gtksettings.sav 2KB
src_v
sdram_axi_core.v 21KB
sdram_axi_pmem.v 11KB
sdram_axi.v 5KB
说明文档.md 4KB
共 26 条
- 1
资源评论
- EMXlight5062023-12-18感谢大佬分享的资源,对我启发很大,给了我新的灵感。
- wangharry_822024-04-06这个资源内容超赞,对我来说很有价值,很实用,感谢大佬分享~
Matlab仿真实验室
- 粉丝: 2w+
- 资源: 2180
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功