浅析ip核—PLL&RAM&FIFO

前言

ip核 :知识产权核或知识产权模块;IP主要分为软IP、固IP和硬IP。软IP是用Verilog/VHDL等硬件描述语言描述的功能块,但是并不涉及用什么具体电路元件实现这些功能。固IP是完成了综合的功能块。
有关详情可以参考下例网址;
IP核.

一、PLL(锁相环)

1、PLL简介

  • PLL英文:Phase locked Loop;
  • PLL:是一种反馈控制电路,其特点是利用外部输入的参考信号控制环路内部震荡信号的频率和相位;
  • 可实现时钟的分频、倍频、相位控制功能。

在这里插入图片描述
锁相环PLL电路模块组成

  • 鉴相鉴频器PFD(Phase Frequency Detector):对输入的基准信号(来自频率稳定的晶振)和反馈回路的信号进行频率的比较,输出一个代表两者相位差异的信号;
  • 低通滤波器LPF(Low-Pass Filter):将PFD中生成的差异信号的高频成分滤除,保留直流部分;
  • 压控振荡器VCXO(Voltage Controlled Oscillator):根据输入电压,输出对应频率的周期信号。利用变容二极管(偏置电压的变化会改变耗尽层的厚度,从而影响电容大小)与电感构成的LC谐振电路构成,提高变容二极管的逆向偏压,二极管内耗尽层变大,电容变小,LC电路的谐振频率提高,反之,降低逆向偏压时,二极管内电容变大,频率降低;
  • 反馈回路FL(Feedback Loop):通常由一个分频器实现。将VCXO的输出降低到与基准信号相同级别的频率才能在PFD中比较。
    工作原理
    将压控振荡器的输出经过分频后与基准信号输入PFD,PFD通过比较这两个信号的频率差,输出一个代表两者差异的信号,再经过低通滤波器转变成一个直流脉冲电压去控制VXCO使它的频率改变。

quartus||软件提供了锁相环pll的ip核 对时钟网络进行系统级的时钟管理和偏移控制,具有时钟倍频、分频、相位偏移和可编程占空比的功能。
在这里插入图片描述

2、IP核的使用

1、PLL配置

新建工程,pll_test,然后用quartus打开
在这里插入图片描述
配置pll
在这里插入图片描述
将配置的pll保存在ip目录下
在这里插入图片描述
下面开始进行pll的ip核配置
界面认识
在这里插入图片描述
配置结果图
在这里插入图片描述
异步清零以及时钟
在这里插入图片描述
保持默认,点击next
在这里插入图片描述
时钟转化配置,保持默认 点击next
在这里插入图片描述
选择动态配置pll,开发板时钟固定,保持默认
在这里插入图片描述
输出时钟页面认识
在这里插入图片描述
配置图c0
在这里插入图片描述
配置图c1
在这里插入图片描述
配置图c2

配置图c3
在这里插入图片描述
添加仿真库文件
在这里插入图片描述
总结页面,点击finish
在这里插入图片描述
查看生成的ip文件
在这里插入图片描述
将生成的ip核添加进工程,查看生成的ip信息
在这里插入图片描述
查看pll端口信息
在这里插入图片描述

2、PLL例化

创建顶层文件,例化配置的pll_demo
顶层pll_test.v

module pll_test(

    input          sys_clk         ,
    input          sys_rst_n       ,

    output         clk_100m        ,//输出时钟100M
    output         clk_100m_180deg ,//输出时钟100M 相位偏移180°
    output         clk_50m         ,//输出时钟50M
    output         clk_25m          //输出时钟25M
);

    //信号定义
    wire           locked  ;
    wire           rst_n   ;

    assign rst_n = sys_rst_n & locked;//避免时钟未稳定而发生的错误数据采集

   //模块例化
   pll_demo u_pll_demo
   (
	.areset     (~sys_rst_n      ),//pll高电平复位
	.inclk0     (sys_clk         ),
	.c0         (clk_100m        ),
	.c1         (clk_100m_180deg ),
	.c2         (clk_50m         ),
	.c3         (clk_25m         ),
	.locked     (locked          )
    );

endmodule

引脚分配,回车保存
在这里插入图片描述
工程全编译以及资源占用
在这里插入图片描述

3、示波器验证

下载工程,示波器验证结果
在这里插入图片描述

3、IP核的仿真

编写testbench文件 pll_tb.v

//时间尺度定义
`timescale 1ns/1ns

module pll_tb();

//激励信号
reg             clk            ;
reg             rst_n          ;

//输出信号
wire           clk_100m        ;
wire           clk_100m_180deg ;
wire           clk_50m         ;  
wire           clk_25m         ;

//模块例化
pll_test u_pll_test
   (
	.sys_clk    (sys_clk         ),
	.sys_rst_n  (rst_n           ),
	.c0         (clk_100m        ),
	.c1         (clk_100m_180deg ),
	.c2         (clk_50m         ),
	.c3         (clk_25m         )
    );

    //定义时间参数
    parameter TIME_CYCLE = 20;
    //产生时钟
    always #(TIME_CYCLE/2) clk = ~clk;
    //产生激励
    initial begin
        clk   = 1'b0;
        rst_n = 1'b0;
        #(TIME_CYCLE*20);
        rst_n = 1'b1;
        
    end

endmodule

modelsim仿真
在这里插入图片描述

二、读写RAM(随机存储器)

1、RAM简介

1、RAM认识

  • RAM:(Random Access Memory)即随机存取存储器,它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址读出数据,其读写速度由时钟频率决定的
  • 特点:断电时将丢失所有保存数据,是与CPU直接交换数据的内部存储器,也叫主存(内存),它可以随时读写而且速度很快,通常作为操作系统或其他正在运行中程序的临时数据存储媒介;
  • 区别ROM(Read Only Memory):只读内存,是一种半导体内存,资料随着断电将会消失,其特性是一旦储存资料就无法将之改变或删除。
  • RAM是暂时性的存储,ROM是永久性的存储,RAM在断电后保存在上面的数据会自动消失,而ROM不会

2、RAM分类

FPGA片上存储器:SRAM

RAM类别 优点 缺点
SRAM (静态存储器) 存取速度快;操作简单 成本高,存储器容量小
DRAM(动态存储器) 成本低,存储器容量大 操作时序复杂;读写速度慢

RAM主要用来存放程序以及程序执行过程中产生的中间数据、运算结果等。

RAM端口

RAM端口 特点
单口 读写由同一根地址线控制;读写分开进行;对同一地址进行读写操作
双口 可对RAM进行不同地址的读写操作

2、程序设计

任务:调用IP核,生成一个单端口RAM,然后对RAM进行读写操作。并进行仿真

系统框图
在这里插入图片描述
时序图
在这里插入图片描述
ram_top.v

module ram_top(

    input                  sys_clk    ,//系统时钟
    input                  sys_rst_n   //系统复位,低电平有效
);

   //信号定义
   wire                       ram_wr_en    ;//写使能
   wire                       ram_rd_en    ;//读使能
   wire      [4:0]            ram_addr     ;//读写地址
   wire      [7:0]            ram_wr_data  ;//写数据
   wire      [7:0]            ram_rd_data  ;//读数据

   //模块例化
   //ram读写模块
   ram_rw   u_ram_rw
   (
       .clk              (sys_clk      ),
       .rst_n            (sys_rst_n    ),

       .ram_wr_en        (ram_wr_en    ),
       .ram_rd_en        (ram_rd_en    ),
       .ram_addr         (ram_addr     ),
       .ram_wr_data      (ram_wr_data  ),
       
       .ram_rd_data      (ram_rd_data  )
   );

   //ram的ip
   ram_1port	u_ram_1port
   (
	   .address         ( ram_addr     ),
	   .clock           ( sys_clk      ),
	   .data            ( ram_wr_data  ),
	   .rden            ( ram_rd_en    ), 
	   .wren            ( ram_wr_en    ),
	   .q               ( ram_rd_data  )
	);


endmodule

ram_rw.v

module ram_rw(

    input                clk         ,
    input                rst_n       ,

    input    [7:0]       ram_rd_data   ,

    output               ram_wr_en   ,//写使能 
    output               ram_rd_en   ,//读使能 
    output  reg[4:0]     ram_addr    ,//读写地址
    output  reg[7:0]     ram_wr_data
);

   //信号定义
   reg           [5:0]        rw_cnt  ;//读写控制计数器

   //ram读写信号控制
   assign ram_wr_en = ((rw_cnt >= 6'd0 ) && (rw_cnt <= 6'd31))?1'b1:1'b0;//写使能在0-31为高电平 32-63为低电平

   assign ram_rd_en = ((rw_cnt >= 6'd32) && (rw_cnt <= 6'd63))?1'b1:1'b0;//读使能在0-31为低电平 32-63为高电平

   //读写控制计数器  0-63
   always @(posedge clk or negedge rst_n) begin
       if(rst_n == 1'b0)
         rw_cnt <= 6'd0;
       else if(rw_cnt == 6'd63)
         rw_cnt <= 6'd0;
       else 
         rw_cnt <= rw_cnt + 6'd1;
   end

   //读写控制器计数范围 0-31产生写使能和写数据
   always @(posedge clk or negedge rst_n) begin
       if(rst_n == 1'b0)
         ram_wr_data <= 8'd0;
       else if(rw_cnt >= 6'd0 && rw_cnt <= 6'd31)
         ram_wr_data <= ram_wr_data + 8'd1;
       else 
         ram_wr_data <= 8'd0;
   end

   //读写地址信号
   always @(posedge clk or negedge rst_n) begin
       if(rst_n == 1'b0)
         ram_addr <= 5'd0;
       else if(ram_addr == 5'd31)
         ram_addr <= 5'd0;
       else 
         ram_addr <= ram_addr + 1'b1;
   end

endmodule

ram_tb.v

`timescale 1ns / 1ps

module ram_tb();

reg sys_clk;
reg sys_rst_n;

wire [2:0] y;

initial 
begin
	sys_clk = 1'b0;
	sys_rst_n = 1'b0;
	#200
	sys_rst_n = 1'b1;
end

always #10 sys_clk = ~sys_clk;

ram_top u_sp_ram_rw(
	.sys_clk (sys_clk ),
	.sys_rst_n (sys_rst_n)
);

 endmodule

3、ip核使用

1、RAM的IP核配置

单端口RAM
在这里插入图片描述
将创建的ip核保存到IP目录下
在这里插入图片描述
界面认识
在这里插入图片描述
界面配置
在这里插入图片描述
界面认识
在这里插入图片描述
界面配置
在这里插入图片描述
界面配置
在这里插入图片描述
界面认识
在这里插入图片描述
界面配置
在这里插入图片描述
界面配置
在这里插入图片描述
界面配置
在这里插入图片描述

2、modelsim仿真验证

将testbench文件添加到modelsim中,添加波形到wave
在这里插入图片描述
使用Ctrl+A 与 Crtl+G对信号进行分组,运行仿真
在这里插入图片描述
将计数器、读写数据值改为无符号型
在这里插入图片描述
仿真结果
在这里插入图片描述
在这里插入图片描述

3、signal tap抓取验证

【tools】→【signal tap logic anlyser】
![在这里插入图片描述](https://img-blog.csdnimg.cn/097b61eaf9c24d5f9ba3efa3b0f44c4b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5aSp5Lya5pm05bCx5Lya5pqX,size_20,color_FFFFFF,t_70,g_se,x_16
连接开发板,选择驱动,下载生成的.sof文件
在这里插入图片描述
详细操请看以前文章,点击全编译
在这里插入图片描述
结果查看
在这里插入图片描述

三、读写FIFO(先进先出)

1、FIFO简介

FIFO:first in first out
FIFO一般用于不同时钟域之间的数据传输,也常用于来实现不同位宽的接口的数据匹配。
在这里插入图片描述
不同位宽的接口之间数据匹配
在这里插入图片描述

先入先出队列,这是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令。分类为同步FIFO,读写时钟相同;异步FIFO读写时钟不同。

2、程序设计

系统框图
在这里插入图片描述
源码:
fifo_top.v

/***********************
FIFO读写实验
***********************/

module fifo_top(

    input               sys_clk     ,//系统时钟
    input               sys_rst_n    //系统复位 低电平有效
);

    //信号定义
    /*    写FIFO     */
    wire                     wr_req    ;//写请求
    wire       [7:0]         data      ;//写入FIFO的数据
    wire                     wr_empty  ;//写空
    wire                     wr_full   ;//写满
    wire                     wr_udw    ;//写FIFO的数据量

    /*    读FIFO       */
    wire                    rd_req    ;//读请求
    wire       [7:0]        q_out     ;//数据输出
    wire                    rd_empty  ;//读空
    wire                    rd_full   ;//读满
    wire                    rd_udw    ;//读FIFO的数据量

    //模块例化
    //例化FIFO
    ip_fifo	   u_ip_fifo 
    (
	   .data               ( data        ),
	   .rdclk              ( sys_clk     ),
	   .rdreq              ( rd_req      ),
	   .wrclk              ( sys_clk     ),
	   .wrreq              ( wr_req      ),
	   .q                  ( q_out       ),
	   .rdempty            ( rd_empty    ),
	   .rdfull             ( rd_full     ),
	   .rdusedw            ( rd_udw      ),
	   .wrempty            ( wr_empty    ),
	   .wrfull             ( wr_full     ),
	   .wrusedw            ( wr_udw      )
	);

    //例化写FIFO

    //例化读FIFO
    fifo_rd     u_fifo_rd
    (
        .clk           (sys_clk      ),
        .rst_n         (sys_rst_n    ),
        .rd_empty      (rd_empty     ),
        .rd_full       (rd_full      ),
        .data          (data         ),
        .rd_req        (rd_req       )
    );

    //例化写fifo
    fifo_wr     u_fifo_wr
    (
         .clk          ( sys_clk     ),
         .rst_n        ( sys_rst_n   ),
         .wr_empty     ( wr_empty    ),
         .wr_full      ( wr_full     ),
         .data         ( data        ),
         .wr_req       ( wr_req      )
    );


endmodule

fifo_wr.v

module fifo_wr(

    input                     clk      ,
    input                     rst_n    ,
    input                     wr_empty ,//写空
    input                     wr_full  ,//写满
    output    reg [7:0]       data     ,//写入FIFO数据
    output    reg             wr_req    //写请求
);

     //信号定义
     reg          [1:0]      flow_cnt   ;//状态流转计数

     //写数据到FIFO
     always @(posedge clk or negedge rst_n) begin
         if(!rst_n)begin
           wr_req <= 1'b0;
           data <= 8'd0;
           flow_cnt <= 2'd0;
         end
         else begin
             case(flow_cnt)
             2'd0:begin
                 if(wr_empty)begin//写空时 写请求拉高 跳到下一个状态
                     wr_req <= 1'b1;
                     flow_cnt <= flow_cnt + 1'b1;
                 end
                else 
                     flow_cnt <= flow_cnt;
             end
             2'd1:begin
                 if(wr_full)begin//写满时 写请求拉低 跳回上一个状态
                     wr_req <= 1'b0;
                     data <= 8'd0;
                     flow_cnt <= 2'd0;
                 end
                    else begin//没有写满时 写请求拉高 继续输入数据
                     wr_req <= 1'b1;
                     data <= data + 1'd1;
                     end
							end
                     default:flow_cnt <= 2'd0;
             endcase
         end
     end

endmodule

fifo_rd.v

module fifo_rd(

    input                clk     ,
    input                rst_n   ,
    input                rd_empty,//读空
    input                rd_full ,//读满
    input    [7:0]       data    ,//从FIFO输出的数据
    output  reg          rd_req   //读请求                   
);

    //信号定义
    reg          [7:0]       data_fifo  ;//读取fifo数据
    reg          [1:0]       flow_cnt   ;//状态流转计数器

    //读取fifo数据
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)begin
            rd_req <= 1'b0;
            data_fifo <= 8'd0;
            flow_cnt <= 2'd0;
        end
        else begin
            case(flow_cnt)
            2'd0:begin
                if(rd_full)begin//读满 拉高读请求信号 跳到下一个状态
                    rd_req <= 1'b1;
                    flow_cnt <= flow_cnt + 1'b1;
                end
                else 
                flow_cnt <= flow_cnt;
            end
            2'd1:begin
                if(rd_empty)begin
                    rd_req <= 1'b0;
                    data_fifo <= 8'd0;
                    flow_cnt <= 2'd0;
                end
                else begin//未读空 寄存读取的数据
                    rd_req <= 1'b1;
                    data_fifo <= data;
                end
            end
            default:flow_cnt <= 2'd0;
				endcase
        end
    end

endmodule

3、IP核使用

1、FIFO的ip核配置

搜索ip核
在这里插入图片描述
将配置的ip核保存在ip目录下
在这里插入图片描述
界面认识与配置
在这里插入图片描述
界面配置
在这里插入图片描述
界面配置
在这里插入图片描述
界面认识与配置
在这里插入图片描述
界面认识
在这里插入图片描述
正常模式与前显模式
在这里插入图片描述

区别:正常模式,输出数据与读请求信号差一个时钟周期;前显模式,将数据放于数据线上,在读请求信号拉高时,在下一个时钟周期,输出FIFO中的第二个数据。

界面配置
在这里插入图片描述
界面配置
在这里插入图片描述
配置完成
在这里插入图片描述

2、信号抽头抓取验证

选择驱动,时钟等
在这里插入图片描述
抓取采样信号
在这里插入图片描述
对工程进行编译,保存stp文件
在这里插入图片描述
工程编译结果
在这里插入图片描述
点击图标
在这里插入图片描述
可以看到抓取的信号
在这里插入图片描述
结果展示
在这里插入图片描述
这里就不进行modelsim的仿真了,效果一样的。

四、参考资料

FIFO阈值设置及深度计算原理

什么是FIFO? FIFO有什么特点?

猜你喜欢

转载自blog.csdn.net/QWERTYzxw/article/details/121295258