mercredi 8 avril 2020

VHDL Best way to generate PRN with variable Frequency?

The problem of the following question is in the fixed point and how to use it in VHDL, knowledge of GPS is not essential.

ENTITY BLOCK DIAGRAM

I am making a GPS receiver in FPGA with VHDL and I am having problems with the PRN generator module. Attached here is the block diagram. The idea is that this entity should be able to adapt to different generation rates of each bit of the PRN.

My idea has been, to generate a sub-entity (ENABLER) that consists of "delaying" each bit generation by entering as Enable in the "PRN" sub-entity.

An example:

We assume Fs = 8e6

Each bit must be generated every
Tchip = 1e-6/1023 = 977.5 ns

So with a period Tclock
Tclock = 1 / 8e6 = 0.000000125
Tclock / Tchip = 0.127875

So every FPGA clock there is a division of exactly 0.127875 so after 8 clocks 0.127875 * 8 = 1.023 entity output is 1.

This 1 output goes as enable input in the "PRN" sub-entity.

  1. Is there a problem with the remaining 0.23 of the accumulator result in terms of GPS synchronization?
  2. Is this the best way?

The problem comes when I try to implement it with VHDL which I started learning a few months ago.

Here is the ENABLER code.

Library IEEE;
Use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all; 
use ieee.FIXED_PKG.all;


Entity prn_enabler is
--generic(
--Fs: integer      :=   8000000

--);

port( 
    clk,rst,en     :    in std_logic;
    en_out         :    out std_logic
);
end prn_enabler;

architecture rtl of prn_enabler is

--Local Signals

signal Tclk              :  ufixed(31 downto 0):=  "00000000000000000000000000000000";
constant Tchip           :  ufixed(0 downto -31):= "00000000000000000000100000110011"; --32 bit 977.5 ns approximation -- better to use constant or generic?
signal Tchip_converted   :  ufixed(31 downto 0);
signal count             :  integer range 0 to 31;

begin
process(clk,rst)
begin

if(rst='1') then
    --reset

elsif(clk'event and clk='1') then
    if(en = '1') then

    Tclk <= 1/unsigned(Fs); -- this should be 0.000000125
    Tclk <= Tclk sll 19; -- Tclk*2^32 or Tclk(32 downto 20) = 536
    Tchip_converted <= Tchip sll 19; -- or Tchip(32 downto 20) = 4198
    Div <= Tclk*Tchip_converted;
    Count <= Div + Div(32 downto 20); --or "Div sll 19" to shift 2^32 = 0.1220

    end if;
end if;
end process;

en_out <= Count;

end rtl;

This code does not allow me to do the division Tclk = 1 / Fs. The idea is to shift to the left to remove the point.

Tchip * 2 ^ 32 = 977.5ns * 2 ^ 32 = 4198 (low resolution)
Tclk * 2 ^ 32 = 1.25e-7 * 2 ^ 32 = 536
Solution = Tchip * Tclk / 2 ^ 32 = 0.1220

To get an exact result, a minimum of 54 bits are required to store the Tchip value with all the resolution. So the idea is to do it with 64 bits.

  1. Is there a problem doing this with 64 bit?

These calculations can be seen in the MATLAB code. In addition to a comparison with 32 and 64 bits. I attach the matlab file here to not extend this question.

MATLAB CODE

Thank you very much in advance, any questions or corrections to improve will be appreciated.




Aucun commentaire:

Enregistrer un commentaire