OpenCores
URL https://opencores.org/ocsvn/heap_sorter/heap_sorter/trunk

Subversion Repositories heap_sorter

[/] [heap_sorter/] [trunk/] [high_speed_pipelined_4clk_per_word/] [src/] [sort_dpram.vhd_synth] - Rev 5

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- Title      : Parametrized DP RAM for heap-sorter
-- Project    : heap-sorter
-------------------------------------------------------------------------------
-- File       : sort_dpram.vhd
-- Author     : Wojciech M. Zabolotny <wzab@ise.pw.edu.pl>
-- Company    : 
-- Created    : 2010-05-14
-- Last update: 2018-03-09
-- Platform   : 
-- Standard   : VHDL'93
-------------------------------------------------------------------------------
-- Description: 
-------------------------------------------------------------------------------
-- Copyright (c) 2010 Wojciech M. Zabolotny
-- This file is published under the BSD license, so you can freely adapt
-- it for your own purposes.
-- Additionally this design has been described in my article:
--    Wojciech M. Zabolotny, "Dual port memory based Heapsort implementation
--    for FPGA", Proc. SPIE 8008, 80080E (2011); doi:10.1117/12.905281
-- I'd be glad if you cite this article when you publish something based
-- on my design.
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 2010-05-14  1.0      wzab    Created
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;
library work;
use work.sorter_pkg.all;
use work.sys_config.all;

entity sort_dp_ram is

  generic
    (
      ADDR_WIDTH  : natural;
      NLEVELS     : natural;
      NAME        : string := "X";
      RAM_STYLE_G : string := "block"
      );

  port
    (
      clk    : in  std_logic;
      clk2   : in  std_logic;
      addr_a : in  std_logic_vector(NLEVELS-1 downto 0);
      addr_b : in  std_logic_vector(NLEVELS-1 downto 0);
      data_a : in  T_DATA_REC;
      data_b : in  T_DATA_REC;
      we_a   : in  std_logic;
      we_b   : in  std_logic;
      q_a    : out T_DATA_REC;
      q_b    : out T_DATA_REC
      );

end sort_dp_ram;

architecture rtl of sort_dp_ram is

  signal vq_a, vq_b, tdata_a, tdata_b : std_logic_vector(DATA_REC_WIDTH-1 downto 0);
  signal reg                          : T_DATA_REC := DATA_REC_INIT_DATA;
  signal det1, det2, det3             : std_logic  := '1';
  signal gwe_a, gwe_b                 : std_logic  := '1';

begin

  -- Convert our data records int std_logic_vector, so that
  -- standard DP RAM may handle it
  tdata_a <= tdrec2stlv(data_a);
  tdata_b <= tdrec2stlv(data_b);

  -- We need to ensure, that the memory is written only every second cycle (so
  -- that the external combinatorial net has two Clk2 cycles to settle)
  -- 
  rs1 : process (clk) is
  begin  -- process rs1
    if clk'event and clk = '1' then     -- rising clock edge
      det1 <= not det1;
    end if;
  end process rs1;

  rs2 : process (clk2) is
  begin  -- process rs1
    if clk2'event and clk2 = '1' then   -- rising clock edge
      det2 <= det1;
    end if;
  end process rs2;
  -- We should activate WE only when det1 and det2 are equal
  -- (i.e., after the clk2 pulse not associated with the clk pulse)

  gwe : process (det1, det2, we_a, we_b) is
  begin  -- process gwe
    gwe_a <= '0';
    gwe_b <= '0';
    if det2 = det1 then
      gwe_a <= we_a;
      gwe_b <= we_b;
    end if;
  end process gwe;

  i1 : if ADDR_WIDTH > 0 generate
    -- When ADDR_WIDTH is above 0 embed the real DP RAM
    -- (even though synthesis tool may still replace it with
    -- registers during optimization for low ADDR_WIDTH)

    q_a <= stlv2tdrec(vq_a);
    q_b <= stlv2tdrec(vq_b);
    blockgen : if RAM_STYLE_G = "block" generate
      dp_ram_1 : entity work.dp_ram_scl_sorter
        generic map (
          DATA_WIDTH => DATA_REC_WIDTH,
          ADDR_WIDTH => ADDR_WIDTH)
        port map (
          clk    => clk2,
          addr_a => addr_a(ADDR_WIDTH-1 downto 0),
          addr_b => addr_b(ADDR_WIDTH-1 downto 0),
          data_a => tdata_a,
          data_b => tdata_b,
          we_a   => gwe_a,
          we_b   => gwe_b,
          q_a    => vq_a,
          q_b    => vq_b);

    end generate;

    distribgen : if RAM_STYLE_G = "distributed" generate
      dp_ram_1 : entity work.dp_ram_scl_sorter_distributed
        generic map (
          DATA_WIDTH => DATA_REC_WIDTH,
          ADDR_WIDTH => ADDR_WIDTH)
        port map (
          clk    => clk2,
          addr_a => addr_a(ADDR_WIDTH-1 downto 0),
          addr_b => addr_b(ADDR_WIDTH-1 downto 0),
          data_a => tdata_a,
          data_b => tdata_b,
          we_a   => gwe_a,
          we_b   => gwe_b,
          q_a    => vq_a,
          q_b    => vq_b);

    end generate;


  end generate i1;

  i2 : if ADDR_WIDTH = 0 generate
    -- When ADDR_WIDTH is 0, DP RAM should be simply replaced
    -- with a register implemented below

    p1 : process (clk)
    begin  -- process p1
      if clk'event and clk = '1' then   -- rising clock edge
        if we_a = '1' then
          reg <= data_a;
          q_a <= data_a;
          q_b <= data_a;
        elsif we_b = '1' then
          reg <= data_b;
          q_a <= data_b;
          q_b <= data_b;
        else
          q_a <= reg;
          q_b <= reg;
        end if;
      end if;
    end process p1;

  end generate i2;

  --dbg1 : if SORT_DEBUG generate

  --  -- Process monitoring read/write accesses to the memory (only for debugging)
  --  p3 : process (clk)
  --    variable rline : line;
  --  begin  -- process p1
  --    if clk'event and clk = '1' then   -- rising clock edge
  --      if(we_a = '1' and we_b = '1') then
  --        write(rline, NAME);
  --        write(rline, ADDR_WIDTH);
  --        write(rline, string'(" Possible write collision!"));
  --        writeline(reports, rline);
  --      end if;

--      if we_a = '1' then
--        write(rline, NAME);
--        write(rline, ADDR_WIDTH);
--        write(rline, string'(" WR_A:"));
--        wrstlv(rline, addr_a(ADDR_WIDTH-1 downto 0));
--        write(rline, string'(" VAL:"));
--        wrstlv(rline, tdata_a);
--        writeline(reports, rline);
--      end if;
--      if we_b = '1' then
--        write(rline, NAME);
--        write(rline, ADDR_WIDTH);
--        write(rline, string'(" WR_B:"));
--        wrstlv(rline, addr_b(ADDR_WIDTH-1 downto 0));
--        write(rline, string'(" VAL:"));
--        wrstlv(rline, tdata_b);
--        writeline(reports, rline);
--      end if;
--    end if;
--  end process p3;
--end generate dbg1;
end rtl;

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.