ALTDDIO_OUT IP核的调用 ALTDDIO_OUT 是 Altera 提供的双数据速率 (DDR) IP 核的一部分,双数据速率 (DDR) IP 核可以用于在逻辑资源中实现 DDR 寄存器。其中 ALTDDIO_IN 可实现 DDR 输入接口, ALTDDIO_OUT 可实现 DDR 输出接口, ALTDDIO_BIDIR 可实现双向 DDR 输入输出接口。 本模块使用的是 ALTDDIO_OUT IP 核,用以实现 DDR 输出接口,将两路单沿信号,转换为双沿信号,在参考时钟的上升沿和下降沿发送数据。ALTDDIO_OUT IP 核框图和接口信号描述,具体见下图: 图3 ALTDDIO IP核框图 图4 ALTDDIO_OUT IP 核接口信号描述 图5 ALTDDIO_OUT IP 核时序图 了解了 ALTDDIO_OUT IP 核的相关知识后,我们开始进行 IP 核的配置。 图6 在图 6 IP 核搜索界面标注①处搜索 ALTDDIO ;选中标注②处的ALTDDIO_OUT;在标注③处选择 IP 核文件存储位置并命名 IP 核;点击标注④处的 “Next ”,进行后续配置。
图7
图 7 所示,在标注①处选择输入输出数据位宽,本模块中选择位宽为 1bit ;在标注②处选择“Not used ”,不使用“ aclr ”“ aset ”信号;点击标注③处“ Next ”,进行后续配置。 图8 本页面不进行任何参数设置,直接点击“Next ”进入下一步。 图9 标注①处为 IP 核仿真模型的相关描述;本页面同样不进行任何参数配置,点击标注②处“Next ”,进入后续配置。图10
如图 10 所示,标注①处为 IP 核生成后产生文件的文件列表,默认全部勾选,读者也可自定义选择;点击标注②处“Finish”完成 IP 核的生成。
这里我们只使用了 ALTDDIO_OUT IP 核的部分功能,有关其详细的配置资料读者可点击图 10 标注③,查找 IP 核的官方数据手册。
IP 核生成完毕后,打开 IP 核实例化文件,如图 11 所示。其中,信号 datain_h 为输入的时钟上升沿待输出数据,位宽为 1bit ,信号 datain_l 为输入的时钟下降沿待输出数据,位宽为 1bit , dataout 为输出的串行双沿采样数据,同步时钟为 outclock 。图11 IP核实例化文件
在这里模块输入的是位宽 10bit 的并行数据 par_data , clk_1x 时钟信号同步下的 par_data 数据是如何转换为 clk_5x 时钟信号下的 datain_h 、 datain_l 数据信号?下面我们进行讲解。 图12 并转串波形图 第一步:将输入的 10bit 并行数据 par_data 拆分为两个位宽 5bit 的数据信号。拆分规则 : 将 会 在 时 钟 上 升 沿 输 出 的 par_data[8] 、 par_data[6] 、 par_data[4] 、 par_data[2] 、par_data[0]赋值给变量 data_rise[4:0] ;将会在时钟下降沿输出的 par_data[9] 、 par_data[7] 、par_data[5]、 par_data[3] 、 par_data[1] 赋值给变量 data_fall[4:0] 。 第二步:声明计数器 cnt ,以 clk_5x 为计数时钟进行循环计数,计数范围 0-4 ,每个时钟周期自加 1 。当 cnt 计数值为最大值 4 时,将拆分得到的变量 data_rise 、 data_fall 分别赋值给 data_rise_s 、 data_fall_s ; 第三步:将 data_rise_s[0] 、 data_fall_s[0] 分别写入 ALTDDIO_OUT IP 核的 datain_h 、datain_l 接口;同时,每个时钟周期将 data_rise_s 、 data_fall_s 右移一位。经过上述三步操作后,位宽 10bit 的并行数据 par_data 转换为两路串行数据传入ALTDDIO_OUT IP 核的 datain_h 、 datain_l 接口,经过 IP 核处理后,输出以 clk_5x 为同步时钟的串行双沿采样信号。 同时再次调用 ALTDDIO_OUT IP 核,将 ~data_rise_s[0] 、 ~data_fall_s[0] 分别写入ALTDDIO_OUT IP 核的 datain_h 、 datain_l 接口,输出的串行双沿采样信号与之前生成的串行双沿采样信号,构成差分信号对。 到了这里,本模块已完成并行数据 par_data 向串行差分信号对 ser_data_p 、 der_data_n 的转化。
module par_to_ser
(
input wire clk_5x , //输入系统时钟
input wire [9:0] data_in , //输入并行数据
output wire ser_p , //输出串行差分数据
output wire ser_n //输出串行差分数据
);
//wire define
wire [4:0] data_rise = {data_in[8],data_in[6],
data_in[4],data_in[2],data_in[0]} ;
wire [4:0] data_fall = {data_in[9],data_in[7],
data_in[5],data_in[3],data_in[1]} ;
//reg define
reg [4:0] data_rise_s = 0 ;
reg [4:0] data_fall_s = 0 ;
reg [2:0] cnt = 0 ;
always@(posedge clk_5x)
begin
cnt <= (cnt[2]) ? 3'd0 : cnt + cnt ;
data_rise_s <= (cnt[2]) ? data_rise : data_rise_s[4:1] ;
data_fall_s <= (cnt[2]) ? data_fall : data_fall_s[4:1] ;
end
alt_ddio_out alt_ddio_out_inst_1
(
.datain_h (data_rise_s[0]) ,
.datain_l (data_fall_s[0]) ,
.outclock (~clk_5x) ,
.dataout (ser_p)
);
alt_ddio_out alt_ddio_out_inst_2
(
.datain_h (~data_rise_s[0]) ,
.datain_l (~data_fall_s[0]) ,
.outclock (~clk_5x) ,
.dataout (ser_n)
);
endmodule
具体代码如下: