Tools :
In this discussion we will demonstrate multi-time domain read and write in FIFO (First In First Out) memory. We will use PLL also to generate two separate clocks. Both FIFO and PLL will be generated from Quartus IP.
Steps :
Quartus Prime
. Create a empty project called pll_fifoIP Catalog
. We’ll choose our IP from here.IP Catalog
go to Library
-> Basic Functions
-> Clocks,PLLs and Resets
-> PLL
. Double click on PLL Intel FPGA IP
. A new window like Figure 1 will appear. Give the name as my_pll
and press OK
.Finish
. As we are opting to use two clocks, we have to give the number of clocks as 2 and set the frequency of the first clock generated clock to 100 MHz second clock to 25 MHz.Note the information provided in the
Advanced Parameters Tab:
Names | Value |
---|---|
M-Counter Hi Divide | 3 |
M-Counter Low Divide | 3 |
N-Counter Hi Divide | 256 |
N-Counter Low Divide | 256 |
M-Counter Bypass Enable | false |
N-Counter Bypass Enable | true |
M-Counter Odd Divide Enable | false |
N-Counter Odd Divide Enable | false |
C-Counter-0 Hi Divide | 2 |
C-Counter-0 Low Divide | 1 |
C-Counter-0 Coarse Phase Shift | 1 |
C-Counter-0 VCO Phase Tap | 0 |
C-Counter-0 Input Source | ph_mux_clk |
C-Counter-0 Bypass Enable | false |
C-Counter-0 Odd Divide Enable | true |
C-Counter-1 Hi Divide | 6 |
C-Counter-1 Low Divide | 6 |
C-Counter-1 Coarse Phase Shift | 1 |
C-Counter-1 VCO Phase Tap | 0 |
C-Counter-1 Input Source | ph_mux_clk |
C-Counter-1 Bypass Enable | false |
C-Counter-1 Odd Divide Enable | false |
VCO Post Divide Counter Enable | 2 |
Charge Pump current (uA) | 30 |
Loop Filter Bandwidth Resistor (Ohms) | 2000 |
PLL Output VCO Frequency | 300.0 MHz |
K-Fractional Division Value (DSM) | 1 |
Feedback Clock Type | none |
Feedback Clock MUX 1 | glb |
Feedback Clock MUX 2 | m_cnt |
M Counter Source MUX | ph_mux_clk |
PLL Auto Reset | false |
Click Finish
to proceed.
A window appear reporting the generation status, you can click Exit
when it is complete to continue.
Answer yes in the following dialog to add the files to the project
Library
-> On Chip Memory
, double click on FIFO
. Set the name as my_fifo
and hit OK
.No
for common clock for reading and writing. Then hit Next
.Next
.Asynchronous clear
. Click next to proceed to option page 8. Choose to also generate an instantiation template file then click Finish
since we don’t need to change the other options. A summary window will/may appear,hit Finish
to create the IP. Then add the .qip
file when prompted by clicking yes
.The following is a generated example of instantiating a fifo. Generators will often provide the option to create an instantiation template.
Project Navigator
. From there change the box just beside it to Files
and take a look at the verilog files generated. Double click on ip_pll.v
and from the verilog file copy the input output declaration. We will need that for the instantiation. Do the same for ip_fifo.v
file.top.sv
with the following contents.module top (input clk,rst, output rdempty,wrfull, output [7:0] data_out); logic clk_25,clk_100; // Creating wire for 100 and 50 MHz clock logic flag_locked; logic fifo_aclr; assign fifo_aclr = !flag_locked; logic wrreq; logic [7:0] data_in; always_ff @(posedge clk_100,posedge fifo_aclr) begin if (fifo_aclr) begin data_in<='0; end else begin if (flag_locked) begin data_in <= data_in+8'b1; end end end always_ff @(posedge clk_100,posedge fifo_aclr) begin if (fifo_aclr) begin wrreq<='0; end else begin wrreq<=~wrreq; end end logic rdreq; always_ff @(posedge clk_25,posedge fifo_aclr) begin if (fifo_aclr) begin rdreq<='0; end else begin rdreq<=~rdreq; end end my_fifo my_fifo_inst ( .aclr ( fifo_aclr ), .data ( data_in ), .rdclk ( clk_25 ), .rdreq ( rdreq ), .wrclk ( clk_100 ), .wrreq ( wrreq ), .q ( data_out ), .rdempty ( rdempty ), .wrfull ( wrfull ) ); my_pll uut( // PLL instantiation .refclk(clk), .rst(rst), .outclk_0(clk_100), .outclk_1(clk_25), .locked(flag_locked) ); endmodule
Add file to the project and set top.sv
as the top entity by right clicking on the file.
top.sdc
and and it to the project.#File:top.sdc create_clock -period 20.000 -waveform {0.000 10.000} -name clk50 [get_ports {clk}] derive_pll_clocks #automatically creates constraints for PLL generated clocks
Compile the poject using Menu Processing->Start Compilation
When Finished run the timing analyzer Menu Processing -> Start Timing Analyzer
Verify your setup and hold time slack by examining the report.
Note the unconstrained paths. What are they and why are they unconstrained?
RTL:
This view helps you understand the logical interpreation of your HDL code.
Mapping:
This view helps you understand the logical implementation of your HDL code.
ChipPlanner:
This view helps you understand the physical implementation of your HDL code.
Next we will simulate the project.
First, create the top_tb.sv
with the following contents save and add to the project.
`timescale 1ns/1ps module top_tb; logic clk,rst,rdempty,wrfull; logic [7:0] data_out; top my_top(.*); initial begin clk=0; forever #10 clk=~clk; end initial begin $monitor(" empty:",rdempty," full:",wrfull," dout:",data_out); rst = 1; repeat (10) begin @ (negedge clk); end rst = 0; repeat (1000)begin @ (negedge clk); end $stop; //$finish tends to close the simulator end endmodule
Tools
-> Run Simulation Tool
-> RTL Simulation
. Then the ModelSim window will load up.Compile
-> Compile...
tool to select and Compile
files ip_test.v
,ip_pll.v
,ip_fifo.v
and from <your project directory>/ip_pll
ip_pl_002.v
then click on Done
to close the window.OR
enter the following commands in the Transcript/console (you’ll need to edit the paths):
vlog -reportprogress 300 -work work /home/robucci/IntelFPGAProjects/pll_fifo/my_pll/my_pll_0002.v vlog -reportprogress 300 -work work /home/robucci/IntelFPGAProjects/pll_fifo/my_pll.v vlog -reportprogress 300 -work work /home/robucci/IntelFPGAProjects/pll_fifo/my_fifo.v vlog -reportprogress 300 -work work /home/robucci/IntelFPGAProjects/pll_fifo/top.sv vlog -reportprogress 300 -work work /home/robucci/IntelFPGAProjects/pll_fifo/top_tb.sv
vsim rtl_work.top_tb -L altera_mf_ver -L altera_lnsim_ver
end hit Enter
to start the simulator. In the command -L
means load, we are loading the altera_mf_ver
and altera_lnsim_ver
because the FIFO and PLL IP uses this library respectively.
To add the signals in waveform window type in add wave -position insertpoint sim:/top_tb/*
OR use the follow more specific waveforms:
add wave -position insertpoint \ sim:/top_tb/clk \ sim:/top_tb/rst \ sim:/top_tb/rdempty \ sim:/top_tb/wrfull \
add wave -position insertpoint \ sim:/top_tb/my_top/my_fifo_inst/aclr \ sim:/top_tb/my_top/my_fifo_inst/data \ {sim:/top_tb/my_top/my_fifo_inst/data[7]} \ {sim:/top_tb/my_top/my_fifo_inst/data[6]} \ {sim:/top_tb/my_top/my_fifo_inst/data[5]} \ {sim:/top_tb/my_top/my_fifo_inst/data[4]} \ {sim:/top_tb/my_top/my_fifo_inst/data[3]} \ {sim:/top_tb/my_top/my_fifo_inst/data[2]} \ {sim:/top_tb/my_top/my_fifo_inst/data[1]} \ {sim:/top_tb/my_top/my_fifo_inst/data[0]} \ sim:/top_tb/my_top/my_fifo_inst/rdclk \ sim:/top_tb/my_top/my_fifo_inst/rdreq \ sim:/top_tb/my_top/my_fifo_inst/wrclk \ sim:/top_tb/my_top/my_fifo_inst/wrreq \ sim:/top_tb/my_top/my_fifo_inst/q \ sim:/top_tb/my_top/my_fifo_inst/rdempty \ sim:/top_tb/my_top/my_fifo_inst/wrfull \ sim:/top_tb/my_top/my_fifo_inst/sub_wire0 \ sim:/top_tb/my_top/my_fifo_inst/sub_wire1 \
run -all
to run the simulation.You see results like the following: