CMPE691 : Reconfigurable System Design

Discussion 9

Dr Ryan Robucci

Nov 10,2020

Objective

Tools :

  1. Quartus Prime.
  2. ModelSim

Quartus IP creation and simulation

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 :

Create Project

  1. Open Quartus Prime. Create a empty project called pll_fifo

Generate PLL

  1. When you’re in the main Quartus Prime window, at the right portion you’ll see a tab named IP Catalog. We’ll choose our IP from here.
  2. From IP Cataloggo 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.
  1. Then the PLL IP parameter window like Figure 2 will appear. Edit these configurations as Figure 2 and hit 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

Generate FIFO

  1. Next add a FIFO as follows:
    We will add a FIFO now, go to Library -> On Chip Memory , double click on FIFO. Set the name as my_fifo and hit OK.
  1. When the IP parameter window appears, Set No for common clock for reading and writing. Then hit Next.
  1. In the next window chose the third option for metastability protection. Then hit Next.
  1. In the next window, put a tick on 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.

  1. In Quartus Prime window, at the top left there is 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

  1. Create a new top 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.

Contraints File

  1. Generate New Synopsys Design Contraints file using Menu File->New…
  1. Edit the contents to the following, then save the file astop.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 Project and Run Timing Analysis

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?

Additional Views/Reports


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.

Testbench

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
		

Simulation with Generated IP

Start Simulator

  1. After finishing the analysis and synthesis successfully, go to Tools -> Run Simulation Tool -> RTL Simulation . Then the ModelSim window will load up.

Compile Source

  1. From ModelSim window, you can use the 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

Start simulation

  1. In the ModelSim window, run the following command in the cosole:

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.

Add waves to viewer

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 the simulation

  1. Finally type in run -all to run the simulation.

You see results like the following: