Reputation: 175
I am using an iceFUN FPGA board and have a working design that blinks an LED at 1 Hz. It is using the external 12 Mhz clock connected on GBIN5.
I want to instantiate a pll to increase the internal frequency to around 50Mhz. without further modifying the design I would expect the led to blink at ~4.166Hz
How do I configure/instantiate one of the two plls the ice40hx8k offers?
The VHDL code I am using to blink the LED is as follows:
-- top.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- iceFUN FPGA (ice40hx8k package 132)
-- the board has an external 12Mhz clock on GBIN5 (P7)
-- Led positions
-- .----------- C1
-- | .-------- C2
-- | | .------ C3
-- | | | .--- C4
-- | | | |
-- +---+ +---+ R1 R1 R1 R1
-- | | | | R2 R2 R2 R2
-- | | | | R3 R3 R3 R3 +====
-- +---+ +---+ R4 R4 R4 R4 | USB
-- +---+ +---+ R5 R5 R5 R5 | USB
-- | | | | R6 R6 R6 R6 +====
-- | | | | R7 R7 R7 R7
-- +---+ +---+ R8 R8 R8 R8
-- the led must be LOW and the corresponding column (row) be LOW to turn on the led
entity top is
port (
clk : in std_logic;
R1, R2, R3, R4, R5, R6, R7, R8, C1, C2, C3, C4 : out std_logic
);
end top;
architecture rtl of top is
signal blink : std_logic := '1';
begin
process (clk)
variable counter : unsigned (23 downto 0) := x"000000";
begin
if rising_edge(clk) then
if counter = 11_999_999 then
counter := x"000000";
blink <= not blink;
else
counter := counter + 1;
end if;
end if;
end process;
R1 <= blink;
R2 <= '1';
R3 <= '1';
R4 <= '1';
R5 <= '1';
R6 <= '1';
R7 <= '1';
R8 <= '1';
C1 <= '0';
C2 <= '1';
C3 <= '1';
C4 <= '1';
end rtl;
And I synthesize the design with:
yosys -m ghdl -p 'ghdl --std=08 top.vhd -e top; synth_ice40 -json top.json'
nextpnr-ice40 -r --hx8k --json top.json --package cb132 --asc top.asc --opt-timing --pcf iceFUN.pcf --report bin/usage.report.json
icepack top.asc top.bin
For completeness the pin config
#iceFUN.pcf
# For iceFUN board
set_io --warn-no-port clk P7
set_io --warn-no-port R1 C10
set_io --warn-no-port R2 A10
set_io --warn-no-port R3 D7
set_io --warn-no-port R4 D6
set_io --warn-no-port R5 A7
set_io --warn-no-port R6 C7
set_io --warn-no-port R7 A4
set_io --warn-no-port R8 C4
set_io --warn-no-port C1 A12
set_io --warn-no-port C2 D10
set_io --warn-no-port C3 A6
set_io --warn-no-port C4 C5
set_io --warn-no-port SPI_CS C3
set_io --warn-no-port SPI_SCK A1
set_io --warn-no-port SPI_MOSI A2
set_io --warn-no-port SPI_MISO A3
I can produce some verilog code to configure a pll with:
$ icepll -p -i 12 -o 50 -m
/**
* PLL configuration
*
* This Verilog module was generated automatically
* using the icepll tool from the IceStorm project.
* Use at your own risk.
*
* Given input frequency: 12.000 MHz
* Requested output frequency: 50.000 MHz
* Achieved output frequency: 50.250 MHz
*/
module pll(
input clock_in,
output clock_out,
output locked
);
SB_PLL40_PAD #(
.FEEDBACK_PATH("SIMPLE"),
.DIVR(4'b0000), // DIVR = 0
.DIVF(7'b1000010), // DIVF = 66
.DIVQ(3'b100), // DIVQ = 4
.FILTER_RANGE(3'b001) // FILTER_RANGE = 1
) uut (
.LOCK(locked),
.RESETB(1'b1),
.BYPASS(1'b0),
.PACKAGEPIN(clock_in),
.PLLOUTCORE(clock_out)
);
endmodule
I imagine the VHDL instance code to be something like:
pll_instance : entity work.pll
port map(
input => clk,
output => fast_clk,
locked => locked
);
where clk is the original 12Mhz clock and fask_clk is a new signal to carry the 50Mhz clock.
However, I do not know how to add the verilog code to my synthesis steps.
Upvotes: 0
Views: 86
Reputation: 175
After much searching I stumbled across a solution
A pull request that was never merged implemented the VHDL code generation I was missing to the icepll tool: https://github.com/YosysHQ/icestorm/pull/265
Something like this VHDL file would be created. When added to the sources and instantiated in the top it provides the desired pll.
I did not fund out why the pull request never got merged. Maybe the devs wanted to focus only on verilog?
-- pll.vhd
--
-- PLL configuration
--
-- This VHDL entity was generated automatically
-- using the icepll tool from the IceStorm project.
-- Use at your own risk.
--
-- F_PLLIN: 12.000 MHz (given)
-- F_PLLOUT: 50.000 MHz (requested)
-- F_PLLOUT: 50.250 MHz (achieved)
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity pll is
port (
clk_in : in std_logic;
clk_out : out std_logic;
locked : out std_logic
);
end pll;
architecture synth of pll is
component SB_PLL40_CORE is
generic (
FEEDBACK_PATH : String := "SIMPLE";
DIVR : unsigned(3 downto 0) := "0000";--\n", binstr(best_divr, 4));
DIVF : unsigned(6 downto 0) := "1000010";--\n", binstr(best_divf, 7));
DIVQ : unsigned(2 downto 0) := "100";--\n", binstr(best_divq, 3));
FILTER_RANGE : unsigned(2 downto 0) := "001"--\n", binstr(filter_range, 3));
);
port (
LOCK : out std_logic;
RESETB : in std_logic;
BYPASS : in std_logic;
REFERENCECLK : in std_logic;
PLLOUTGLOBAL : out std_logic
);
end component;
begin
PLL1 : SB_PLL40_CORE port map (
LOCK => locked,
RESETB => '1',
BYPASS => '0',
REFERENCECLK => clk_in,
PLLOUTGLOBAL => clk_out
);
end;
Upvotes: 0