Vivado 中如何使用modelsim 仿真 ddr3

时间:2024-04-12 14:09:53

**

Vivado 中如何使用modelsim 仿真 ddr3

**

第一步 : 编译 vivado 的modelsim 的仿真库 。

1: 将 modelsim 安装目录的modelsim .ini 文件 只读 去掉 。

Vivado 中如何使用modelsim 仿真 ddr3
2:在modelsim 安装目录中新建一个 目录vivado_sim_lib,如 我的 电脑中的vivado 的仿真库的目录为 : C:\modeltech64_2019.2\vivado_sim_lib

3:在 vivado 中选择 tools/compile simulation libraries 来编译仿真库 。
Vivado 中如何使用modelsim 仿真 ddr3

4:如下图设置好 要编译的 支持的器件.编译库的路径 以及 仿真 执行路径 。 Vivado 中如何使用modelsim 仿真 ddr3

5:编译的 过程时间可能会 花半小时,要耐心等待 。

6:编译完毕后,仿真路径下会有 一下的 一些文件。(只截图了部分)。
Vivado 中如何使用modelsim 仿真 ddr3

7: 同时 modelsim.ini 文件中自动 加入了 仿真库及其 路径说明 。(只截图了部分)。
Vivado 中如何使用modelsim 仿真 ddr3

第二步:在vivado 中新建一个工程 。

1:新建一个 clk_wiz_0 的ip ,将外部的 25M晶振时钟 生成一个 本地 clk200M 时钟 。
Vivado 中如何使用modelsim 仿真 ddr3
Vivado 中如何使用modelsim 仿真 ddr3

2: 正常例化 生成一个 ddr3的ip.(如 在 xc7k325t 中例化一个 1600M 16bit的 ddr3).
Vivado 中如何使用modelsim 仿真 ddr3

这个地方 : clock period 选 800M表示 ddr3 的 工作时钟频率 是 : 800M,但是数据吞吐 是 : 1600M(双沿存取数据).
Vivado 中如何使用modelsim 仿真 ddr3

这里的 input clock period 是200M,表示我们操控ddr3 的 时钟是 200M,但是位宽 是 : 1642 = 128bit.
Vivado 中如何使用modelsim 仿真 ddr3

例化完毕。

3: 设置 vivado 中的modelsim 的仿真库以及 modelsim 工作路径。
点击: project manager / settings / simulator ,然后如下图 设置。
Vivado 中如何使用modelsim 仿真 ddr3

同时在 settings / 3 rd parity simulator 中如 下图 设置 。
Vivado 中如何使用modelsim 仿真 ddr3

4: ddr3 仿真的 核心 是加载 ddr3的 仿真 模块: ddr3_model
Vivado 中如何使用modelsim 仿真 ddr3

例化完毕后的 example_design /sim 中 会有 要用到的仿真模块 。
(为 方便, 可以 直接 将 ddr3_model.sv 打开 ,将 文件中的
`include “ddr3_model_parameters.vh” 直接屏蔽掉 ,同时 ,将 ddr3_model_parameters.vh 中的 内容 直接 复制到 其 下面 。
如 下图 : (只截图了部分 )。
Vivado 中如何使用modelsim 仿真 ddr3

实际就是 将 上面两个文件 合并 ,生成一个新的 文件 如 :ddr3_model.vh 文件 ,并将文件 添加到 项目 中 。

5: 最终生成的项目top 文件如下:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

– Uncomment the following library declaration if using
– arithmetic functions with Signed or Unsigned values
–use IEEE.NUMERIC_STD.ALL;
– Uncomment the following library declaration if instantiating
– any Xilinx leaf cells in this code.
–library UNISIM;
–use UNISIM.VComponents.all;
entity example_top is
generic (
G_FOR_SIM : integer := 1 – 1 : simulator ture --0 :
simulator false
);
Port (
ddr3_dq : inout std_logic_vector(15 downto 0);
ddr3_dqs_p : inout std_logic_vector(1 downto 0);
ddr3_dqs_n : inout std_logic_vector(1 downto 0);
ddr3_addr : out std_logic_vector(12 downto 0);
ddr3_ba : out std_logic_vector(2 downto 0);
ddr3_ras_n : out std_logic;
ddr3_cas_n : out std_logic;
ddr3_we_n : out std_logic;
ddr3_reset_n : out std_logic;
ddr3_ck_p : out std_logic_vector(0 downto 0);
ddr3_ck_n : out std_logic_vector(0 downto 0);
ddr3_cke : out std_logic_vector(0 downto 0);
ddr3_dm : out std_logic_vector(1 downto 0);
ddr3_odt : out std_logic_vector(0 downto 0);
clk_27m_i : in std_logic
);

end example_top;
architecture Behavioral of example_top is
component ddr3_model
port (
rst_n : in std_logic;
ck : in std_logic;
ck_n : in std_logic;
cke : in std_logic;
cs_n : in std_logic;
ras_n : in std_logic;
cas_n : in std_logic;
we_n : in std_logic;
dm_tdqs : inout std_logic_vector(1 downto 0);
ba : in std_logic_vector(2 downto 0);
addr : in std_logic_vector(12 downto 0);
dq : inout std_logic_vector(15 downto 0);
dqs : inout std_logic_vector(1 downto 0);
dqs_n : inout std_logic_vector(1 downto 0);
tdqs_n : out std_logic_vector(1 downto 0);
odt : in std_logic
);
end component;

signal ddr3_dq_sdram : std_logic_vector(15 downto 0);
signal ddr3_dqs_p_sdram : std_logic_vector(1 downto 0);
signal ddr3_dqs_n_sdram : std_logic_vector(13 downto 0);
signal ddr3_addr_sdram : std_logic_vector(15 downto 0);
signal ddr3_ba_sdram : std_logic_vector(2 downto 0);
signal ddr3_ras_n_sdram : std_logic;
signal ddr3_cas_n_sdram : std_logic;
signal ddr3_we_n_sdram : std_logic;
signal ddr3_reset_n_sdram : std_logic;
signal ddr3_ck_p_sdram : std_logic_vector(0 downto 0);
signal ddr3_ck_n_sdram : std_logic_vector(0 downto 0);
signal ddr3_cke_sdram : std_logic_vector(0 downto 0);
signal ddr3_dm_sdram : std_logic_vector(1 downto 0);
signal ddr3_odt_sdram: std_logic_vector(0 downto 0);

component WireDelay
GENERIC (
Delay_g : INTEGER := 0;
Delay_rd : INTEGER := 0;
ERR_INSERT : STRING :=“OFF” );
PORT (
A : INOUT STD_LOGIC;
B : INOUT STD_LOGIC;
reset : IN STD_LOGIC;
phy_init_done : IN STD_LOGIC
);
END component;

component mig_7series_0
port (
ddr3_dq : inout
std_logic_vector(15 downto 0);
ddr3_dqs_p : inout
std_logic_vector(1 downto 0);
ddr3_dqs_n : inout
std_logic_vector(1 downto 0);
ddr3_addr : out std_logic_vector(12 downto 0);
ddr3_ba : out std_logic_vector(2 downto 0);
ddr3_ras_n : out std_logic;
ddr3_cas_n : out std_logic;
ddr3_we_n : out std_logic;
ddr3_reset_n : out std_logic;
ddr3_ck_p : out std_logic_vector(0 downto 0);
ddr3_ck_n : out std_logic_vector(0 downto 0);
ddr3_cke : out std_logic_vector(0 downto 0);
ddr3_dm : out std_logic_vector(1 downto 0);
ddr3_odt : out std_logic_vector(0 downto 0);
app_addr :in std_logic_vector(26 downto 0);
app_cmd :in std_logic_vector(2 downto 0);
app_en :in std_logic;
app_wdf_data :in std_logic_vector(127 downto 0);
app_wdf_end :in std_logic;
app_wdf_mask : in std_logic_vector(15 downto 0); app_wdf_wren : in std_logic;
app_rd_data :out std_logic_vector(127 downto 0);
app_rd_data_end :out std_logic;
app_rd_data_valid :out std_logic;
app_rdy : out std_logic;
app_wdf_rdy :out std_logic;
app_sr_req :in std_logic;
app_ref_req :in std_logic;
app_zq_req :in std_logic;
app_sr_active : out std_logic;
app_ref_ack :out std_logic;
app_zq_ack :out std_logic;
ui_clk :out std_logic;
ui_clk_sync_rst :out std_logic;
init_calib_complete :out std_logic;
sys_clk_i :in std_logic;
clk_ref_i : in std_logic;
device_temp :out std_logic_vector(11 downto 0);
sys_rst :in std_logic
);
end component;

component clk_wiz_0
Port (
clk_out1 : out STD_LOGIC;
reset : in STD_LOGIC;
locked : out STD_LOGIC;
clk_in1 : in STD_LOGIC
);
end component;

signal app_addr : std_logic_vector(26 downto 0);
signal app_cmd : std_logic_vector(2 downto 0);
signal app_en : std_logic;
signal app_wdf_data : std_logic_vector(127 downto 0);
signal app_wdf_end : std_logic;
signal app_wdf_mask : std_logic_vector(15 downto 0);
signal app_wdf_wren : std_logic;
signal app_rd_data : std_logic_vector(127 downto 0);
signal app_rd_data_end : std_logic;
signal app_rd_data_valid : std_logic;
signal app_rdy : std_logic;
signal app_wdf_rdy : std_logic;
signal app_sr_req : std_logic;
signal app_ref_req : std_logic;
signal app_zq_req : std_logic;
signal app_sr_active : std_logic;
signal app_ref_ack : std_logic;
signal app_zq_ack : std_logic;
signal ui_clk : std_logic;
signal ui_clk_sync_rst : std_logic;
signal init_calib_complete : std_logic;
signal device_temp : std_logic_vector(11 downto 0);
signal sys_rst_n : std_logic;
signal clk200m:std_logic;
signal locked:std_logic;

signal size :integer;
signal state: std_logic_vector(3 downto 0);
signal app_addr_begin: std_logic_vector(26 downto 0);
signal WriteSign:std_logic;
signal ProsessIn:std_logic;
signal Count_64:std_logic_vector(63 downto 0);
signal state1: std_logic_vector(3 downto 0);
signal ProsessIn1:std_logic;
signal Count_64_1:std_logic_vector(63 downto 0);
signal app_rd_data_tem:std_logic_vector(127 downto 0);
signal error_rddata:std_logic;
signal CountWrite_tem:std_logic_vector(31 downto 0);
signal CountRead_tem:std_logic_vector(31 downto 0);
signal CountWrite:std_logic_vector(31 downto 0);
signal CountRead:std_logic_vector(31 downto 0);
constant TEST_DATA_RANGE:std_logic_vector(23 downto 0):=(others=> ‘1’);

begin

ddr3_model_for_sim: if G_FOR_SIM= 1 generate
ddr3_model_i0: ddr3_model
port map(
rst_n => ‘1’,
ck => ddr3_ck_p_sdram(0),
ck_n => ddr3_ck_n_sdram(0),
cke => ddr3_cke_sdram(0),
cs_n => ‘0’,
ras_n => ddr3_ras_n_sdram,
cas_n => ddr3_cas_n_sdram,
we_n => ddr3_we_n_sdram,
dm_tdqs => ddr3_dm_sdram(1 downto 0),
ba => ddr3_ba_sdram,
addr => ddr3_addr_sdram(12 downto 0),
dq => ddr3_dq_sdram(15 downto 0),
dqs => ddr3_dqs_p_sdram(1 downto 0),
dqs_n => ddr3_dqs_n_sdram(1 downto 0),
tdqs_n => open,
odt => ddr3_odt_sdram(0)
);

u_delay_dq_delay: for i in 0 to 15 generate
u_WireDelay_dq : WireDelay
GENERIC MAP (
delay_g => 0,
delay_rd => 0,
err_insert => “OFF”
)
PORT MAP (
a => ddr3_dq(i),
b => ddr3_dq_sdram(i),
reset => ddr3_reset_n_sdram,
phy_init_done => init_calib_complete
);
END GENERATE u_delay_dq_delay;

u_delay_dqs_delay: for i in 0 to 1 generate
u_delay_dqs_p : WireDelay
GENERIC MAP (
delay_g => 0,
delay_rd => 0,
err_insert => “OFF”
)
PORT MAP (
a =>ddr3_dqs_p(i),
b =>ddr3_dqs_p_sdram(i),
reset =>ddr3_reset_n_sdram,
phy_init_done =>init_calib_complete
);

u_delay_dqs_n : WireDelay
GENERIC MAP (
delay_g => 0,
delay_rd => 0,
err_insert => “OFF”
)
PORT MAP (
a =>ddr3_dqs_n(i),
b =>ddr3_dqs_n_sdram(i),
reset =>ddr3_reset_n_sdram,
phy_init_done => init_calib_complete
);
END GENERATE u_delay_dqs_delay;
end generate ddr3_model_for_sim;

ddr3_ck_p <= ddr3_ck_p_sdram;
ddr3_ck_n <= ddr3_ck_n_sdram;
ddr3_addr <= ddr3_addr_sdram(12 downto 0);
ddr3_ba <= ddr3_ba_sdram;
ddr3_cke <= ddr3_cke_sdram;
ddr3_dm <=ddr3_dm_sdram;
ddr3_odt <=ddr3_odt_sdram;

ddr3_ras_n <= ddr3_ras_n_sdram;
ddr3_cas_n <= ddr3_cas_n_sdram;
ddr3_we_n <= ddr3_we_n_sdram;
ddr3_reset_n <=ddr3_reset_n_sdram;

mig_7series_0_i0: mig_7series_0
port map(
ddr3_dq => ddr3_dq,
ddr3_dqs_p => ddr3_dqs_p ,
ddr3_dqs_n => ddr3_dqs_n,
ddr3_addr =>ddr3_addr_sdram(12 downto 0) ,
ddr3_ba => ddr3_ba_sdram ,
ddr3_ras_n => ddr3_ras_n_sdram,
ddr3_cas_n => ddr3_cas_n_sdram,
ddr3_we_n => ddr3_we_n_sdram,
ddr3_reset_n => ddr3_reset_n_sdram,
ddr3_ck_p => ddr3_ck_p_sdram ,
ddr3_ck_n => ddr3_ck_n_sdram ,
ddr3_cke => ddr3_cke_sdram ,
ddr3_dm => ddr3_dm_sdram,
ddr3_odt => ddr3_odt_sdram,
app_addr => app_addr,
app_cmd => app_cmd,
app_en => app_en,
app_wdf_data => app_wdf_data,
app_wdf_end => app_wdf_end,
app_wdf_mask => app_wdf_mask,
app_wdf_wren =>app_wdf_wren,
app_rd_data =>app_rd_data ,
app_rd_data_end =>app_rd_data_end,
app_rd_data_valid =>app_rd_data_valid ,
app_rdy => app_rdy,
app_wdf_rdy =>app_wdf_rdy,
app_sr_req =>app_sr_req ,
app_ref_req =>app_ref_req,
app_zq_req =>app_zq_req,
app_sr_active =>app_sr_active,
app_ref_ack =>app_ref_ack,

app_zq_ack =>app_zq_ack,
ui_clk => ui_clk,
ui_clk_sync_rst =>ui_clk_sync_rst ,

init_calib_complete =>init_calib_complete,
sys_clk_i =>clk200m,
clk_ref_i => clk200m,

device_temp =>device_temp,
sys_rst => sys_rst_n
);

clk_wiz_0_i: clk_wiz_0
Port map(
clk_out1 => clk200m,
reset => ‘0’,
locked => locked,
clk_in1 => clk_27m_i
);

sys_rst_n <= locked;
end Behavioral;

文中 增加了 一个 条件 编译 选项。 如果要仿真 就设置
G_FOR_SIM : integer := 1 而如果平时 正常 工作时 就 设置 G_FOR_SIM : integer := 0

下面 就 可以 开始 仿真了 。

1: 点击 : simulation/run simulation/ run behavioral simulation 开始行为仿真 。
Vivado 中如何使用modelsim 仿真 ddr3

2:建立一个仿真激励文件 m.do 如下图:
Vivado 中如何使用modelsim 仿真 ddr3

具体的 内容为 :
quit -sim
vsim -t 1ps -voptargs="+acc" -L xil_defaultlib -L unisims_ver -L unimacro_ver -L secureip -L xpm -lib xil_defaultlib xil_defaultlib.example_top xil_defaultlib.glbl

add wave -r /*
radix hex
force clk_27m_i 0 0 ,1 20000 -r 40000
run 70000000

------说明 虽然我们写的是 clk_27m_i ,但我们 的 输入晶振是 25M 的 ----
最后 在modelsim 中 输入 :
do m.do
就开始仿真了 。
具体仿真后的波形如下 :
Vivado 中如何使用modelsim 仿真 ddr3

我们看到最终 : init_calib_complete 信号变为了 高电平
,表明 ddr3 仿真 初始化已成功 。