SDRAM_spinal/Top_Project.v

143 lines
6.4 KiB
Coq
Raw Permalink Normal View History

2026-04-09 10:44:54 +08:00
`timescale 1ns/1ps
module Top_Project (
// ==========================================
// 1. 系统全局时钟与复位输入
// ==========================================
input wire sys_clk_50m, // 开发板上的 50MHz 晶振输入
input wire sys_rst_n, // 开发板上的复位按键 (低电平有效按下为0)
// ==========================================
// 2. 外部 SDRAM 物理芯片接口 (匹配 W9825G6JH-6)
// ==========================================
output wire [12:0] sdram_ADDR, // 13位行地址 / 9位列地址复用
output wire [1:0] sdram_BA, // 2位 Bank 地址
inout wire [15:0] sdram_DQ, // 16位数据总线 (必须是 inout 双向类型)
output wire [1:0] sdram_DQM, // 数据掩码
output wire sdram_CASn, // 列选通 (低有效)
output wire sdram_CKE, // 时钟使能
output wire sdram_CSn, // 片选 (低有效)
output wire sdram_RASn, // 行选通 (低有效)
output wire sdram_WEn, // 写使能 (低有效)
output wire sdram_CLK, // 输出给 SDRAM 芯片的时钟引脚 (带相位偏移)
// ==========================================
// 3. 测试状态指示灯 (新增)
// ==========================================
output wire led_test_pass, // 测试通过指示灯 (建议接绿色 LED)
output wire led_test_fail // 测试失败指示灯 (建议接红色 LED)
);
// ==========================================
// 内部信号声明
// ==========================================
wire clk_100m; // PLL 输出的 100MHz (0度相位 FPGA 内部逻辑用)
wire clk_100m_shift; // PLL 输出的 100MHz (-90度相位 SDRAM 芯片用)
wire pll_locked; // PLL 锁定指示信号 (高电平表示时钟已稳定输出)
wire [15:0] sdram_DQ_read; // 从双向引脚分离出的读数据
wire [15:0] sdram_DQ_write; // 准备输出到双向引脚的写数据
wire [15:0] sdram_DQ_writeEnable; // 控制总线方向的写使能信号
// --- 新增用户逻辑交互总线连线 ---
wire user_cmd_valid;
wire user_cmd_ready;
wire user_is_write;
wire [23:0] user_address;
wire [15:0] user_write_data;
wire user_rsp_valid;
wire [15:0] user_rsp_data;
// ==========================================
// 模块 1例化系统 PLL IP (sys_pll)
// ==========================================
sys_pll u_sys_pll (
// ALTPLL areset 是高电平有效
// 因为板载按键 sys_rst_n 是低电平有效所以这里必须加非逻辑 '~'
.areset (~sys_rst_n),
.inclk0 (sys_clk_50m),
.c0 (clk_100m), // 内部 100MHz 时钟
.c1 (clk_100m_shift),// 偏移 100MHz 时钟
.locked (pll_locked)
);
// 将带有 -90 度相位偏移的时钟直接连到顶层输出引脚送给 SDRAM 物理芯片
assign sdram_CLK = clk_100m_shift;
// ==========================================
// 模块 2复位信号反相与同步处理
// ==========================================
// SpinalHDL 生成的 MyCustomSdramTop 高电平复位
// 我们在此生成一个全局的高电平有效复位信号 system_reset
wire system_reset;
assign system_reset = (~sys_rst_n) | (~pll_locked);
// ==========================================
// 模块 3处理 SDRAM 双向数据总线 (inout 三态门)
// ==========================================
// 读取通道直接将外部管脚状态输入给控制器
assign sdram_DQ_read = sdram_DQ;
// 写入通道通过三态门控制
// 当控制器拉高写使能 (16'hFFFF) 将写数据推送到总线上
assign sdram_DQ = (sdram_DQ_writeEnable == 16'hFFFF) ? sdram_DQ_write : 16'hZZZZ;
// ==========================================
// 模块 4例化由 SpinalHDL 生成的 SDRAM 控制器
// ==========================================
MyCustomSdramTop u_sdram_ctrl (
// --- 时钟与复位 ---
.clk (clk_100m), // 接入稳定的 100MHz 内部时钟
.reset (system_reset), // 接入经过处理的高有效复位信号
// --- 连接到底层的 SDRAM 物理接口信号 ---
.io_sdram_ADDR (sdram_ADDR),
.io_sdram_BA (sdram_BA),
.io_sdram_DQ_read (sdram_DQ_read),
.io_sdram_DQ_write (sdram_DQ_write),
.io_sdram_DQ_writeEnable (sdram_DQ_writeEnable),
.io_sdram_DQM (sdram_DQM),
.io_sdram_CASn (sdram_CASn),
.io_sdram_CKE (sdram_CKE),
.io_sdram_CSn (sdram_CSn),
.io_sdram_RASn (sdram_RASn),
.io_sdram_WEn (sdram_WEn),
// --- 连接到测试模块的用户逻辑接口 ---
.io_userCmdValid (user_cmd_valid),
.io_userCmdReady (user_cmd_ready),
.io_userIsWrite (user_is_write),
.io_userAddress (user_address),
.io_userWriteData (user_write_data),
.io_userWriteMask (2'b11), // 写数据掩码 (2'b00表示16位全部写入不屏蔽)
.io_userRspValid (user_rsp_valid),
.io_userRspData (user_rsp_data)
);
// ==========================================
// 模块 5例化读写校验测试模块 (新增)
// ==========================================
Sdram_Tester #(
.TEST_LENGTH(24'd4096) // 测试的地址长度这里设置为测试前 4096 个地址
) u_tester (
.clk (clk_100m),
// 注意Tester 内部是下降沿复位 (低有效)所以需要将高有效的 system_reset 取反
.rst_n (~system_reset),
// --- 挂载到 SDRAM 用户总线 ---
.cmd_valid (user_cmd_valid),
.cmd_ready (user_cmd_ready),
.is_write (user_is_write),
.address (user_address),
.write_data (user_write_data),
.rsp_valid (user_rsp_valid),
.rsp_data (user_rsp_data),
// --- 连接到顶层外部引脚 ---
.test_pass (led_test_pass),
.test_fail (led_test_fail)
);
endmodule