跨时钟域处理(CDC)

FPGA自创跨RAM时钟域:通过写地址拉回读地址,起到看门狗作用。在这里插入图片描述在这里插入图片描述


– CDC (32bits x 368.64MHz -> 64bit x 184.32MHz)
– write clock domain begin 368.64MHz

-- write valid for double RAM
process (CLK)
begin
    if rising_edge(CLK) then
        if IQ_TICK = '1' then
            wvld <= "1" ;
        else 
            wvld <= not wvld;
        end if;

        if wvld = "1" then
            wdata(0) <= cdc_zeros0 & cdc_rb_start & cdc_rb_last & cdc_rb_tick & cdc_rb_valid & cdc_rb_data_i & cdc_rb_data_q;
        else                     
            wdata(1) <= cdc_zeros1 & cdc_rb_start & cdc_rb_last & cdc_rb_tick & cdc_rb_valid & cdc_rb_data_i & cdc_rb_data_q;
        end if;
    end if;
end process;

-- write address generation
process (CLK)
begin
    if rising_edge(CLK) then
        if hovs_wcnt = W_HOVS-1 then
            hovs_wcnt <= (others => '0');
            if (waddr = 5) then
                waddr <= (others => '0');
            else      
                waddr <= waddr + 1;
            end if;  -- write address accumulation register
        else
            hovs_wcnt <= hovs_wcnt + '1';  -- write address hovs accumulation register
        end if;
    end if;
end process;

-- wsync for avoiding w/r address collision
process (CLK)
begin
    if rising_edge(CLK) then
        if waddr >= 0 and waddr <= 1 then
            wsync <= '1';
        else
            wsync <= '0';
        end if;
    end if;
end process;

– read clock domain begin 184.32MHz

-- write address sync signal shift register
process (CLK_CUPE)
begin
    if rising_edge(CLK_CUPE) then
         wsync_d <= wsync_d(2 downto 0) & wsync;
    end if;
end process;

-- resync control
process (CLK_CUPE)
begin
    if rising_edge(CLK_CUPE) then
        if wsync_d(1) = '1' then
            if raddr >= 3 and raddr <= 5 then
                resync <= '0';  --normal
            else
                resync <= '1';  --abnormal, resync
            end if;
        else
            resync <= '0';
        end if;
    end if;
end process;
    
-- read address generation
process (CLK_CUPE)
begin
    if rising_edge(CLK_CUPE) then
        if resync = '1' then
            hovs_rcnt <= (others => '0');
            raddr <= std_logic_vector(to_unsigned(0, log2(BUFFER_DEPTH)));
        elsif hovs_rcnt = R_HOVS-1 then
            hovs_rcnt <= (others => '0');
            if (raddr = 5) then
                raddr <= (others => '0');
            else      
                raddr <= raddr + 1;
            end if;  -- read address accumulation register
        else
            hovs_rcnt <= hovs_rcnt + '1';  -- read address hovs accumulation register
        end if;
    end if;
end process;

-- read valid generation
process (CLK_CUPE)
begin
    if rising_edge(CLK_CUPE) then
        if hovs_rcnt = R_HOVS-1 then
            rvld <= '1';  -- output valid register
        else
            rvld <= '0';
        end if;
    end if;
end process;

u_blk_mem_cdc_odd : blk_mem_cdc
port map(
    clka       => CLK               ,  --: in std_logic;
    ena        => '1'               ,  --: in std_logic;
    wea        => wvld              ,  --: in std_logic_vector(0 downto 0);
    addra      => waddr             ,  --: in std_logic_vector(3 downto 0);
    dina       => wdata(0)          ,  --: in std_logic_vector(127 downto 0);
                                       
    clkb       => CLK_CUPE          ,  --: in std_logic;
    enb        => '1'               ,  --: in std_logic;
    addrb      => raddr             ,  --: in std_logic_vector(3 downto 0);
    doutb      => rdata(0)             --: out std_logic_vector(127 downto 0)
);                                  
                                    
u_blk_mem_cdc_even : blk_mem_cdc    
port map(                           
    clka       => CLK               ,  --: in std_logic;
    ena        => '1'               ,  --: in std_logic;
    wea        => wvld              ,  --: in std_logic_vector(0 downto 0);
    addra      => waddr             ,  --: in std_logic_vector(3 downto 0);
    dina       => wdata(1)          ,  --: in std_logic_vector(127 downto 0);
                                       
    clkb       => CLK_CUPE          ,  --: in std_logic;
    enb        => '1'               ,  --: in std_logic;
    addrb      => raddr             ,  --: in std_logic_vector(3 downto 0);
    doutb      => rdata(1)             --: out std_logic_vector(127 downto 0)
);  

-- output singal
process (CLK_CUPE)
begin
    if rising_edge(CLK_CUPE) then
        RB_START       <= rdata(0)(27)             ;
        RB_LAST        <= rdata(1)(26)             ;
        RB_VALID       <= rdata(0)(25)             ;
        RB_TICK        <= rdata(0)(24)             ;
        RB_DATA_I      <= rdata(0)(23 downto 0)    ;
        RB_DATA_Q      <= rdata(1)(23 downto 0)    ;
    end if;
end process;
  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值