MAZZI 1 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба Интересен пример описания блочной памяти, где были бы два независимых конфигурируемых порта по записи и по чтению, с такой синтезируемой моделью можно легко будет делать преобразователи из последовательного в параллельный код, минуя сдвиговые регистры (сейчас я с ними делаю). Какие есть решения по данной реализации на Verilog (VHDL), чтобы ещё и понятно было :)? выкладывайте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба Интересен пример описания блочной памяти, где были бы два независимых конфигурируемых порта по записи и по чтению, с такой синтезируемой моделью можно легко будет делать преобразователи из последовательного в параллельный код, минуя сдвиговые регистры (сейчас я с ними делаю). Обсуждалось. Какие есть решения по данной реализации на Verilog (VHDL), чтобы ещё и понятно было :)? выкладывайте. Используйте поиск. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба Интересен пример описания блочной памяти, где были бы два независимых конфигурируемых порта по записи и по чтению, с такой синтезируемой моделью можно легко будет делать преобразователи из последовательного в параллельный код, минуя сдвиговые регистры (сейчас я с ними делаю). Какие есть решения по данной реализации на Verilog (VHDL), чтобы ещё и понятно было :)? выкладывайте. <{POST_SNAPBACK}> У ксайлинсков около 10 апнот на эту тему!!!!!!!! ищите по BLOCK RAM DATA WIDTH CONVERTION FIFO Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MAZZI 1 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба Если это обсуждалось (в чем я сильно сомневаюсь), дайте ссылочку, пожалуйста, то же и по appnotes, использовал для примера CORE Generator, он сослался на библиотечный элемент BLKMEMDP_V6_1.v, слишком все тяжело описано в нем, разобраться не могу, сам придумал реализацию, по крайней мере в моделе всё как и задумывалось: <================================================== /* ОБЪЯВЛЕНИЕ МОДУЛЯ */ module C_DPINDEP_RAM /*----------------------------------------------------------------------------- * Объявление параметров: */ #( parameter WIDTH_WR_DATA = 1, WIDTH_WR_ADDR = 12, DEPTH_WR = (1<<WIDTH_WR_ADDR), WIDTH_RD_DATA = 8, WIDTH_RD_ADDR = 9 ) /*----------------------------------------------------------------------------- * Объявление портов: */ ( // порт записи input i_WR_CLK, // тактовый импульс записи i_WR_EN, // строб разрешения записи input [(WIDTH_WR_DATA-1): 0] i_WR_DATA,// шина данных записи input [(WIDTH_WR_ADDR-1): 0] i_WR_ADDR,// адресная шина записи // порт чтения input i_RD_CLK, // тактовый импульс чтения input [(WIDTH_RD_ADDR-1): 0] i_RD_ADDR, // адресная шина чтения output reg [(WIDTH_RD_DATA-1): 0] o_RD_DATA // шина данных чтения ); /*----------------------------------------------------------------------------- * Объявление сигналов: */ reg R_tmp_mem [(WIDTH_WR_DATA*DEPTH_WR-1):0]; reg [(WIDTH_RD_ADDR-1): 0] R_rd_addr; integer j, k; /* synthesis translate_off */ integer i; initial begin for (i = 0; i < WIDTH_WR_DATA*DEPTH_WR; i= i + 1) R_tmp_mem <= 1'b0; R_rd_addr <= {WIDTH_RD_ADDR{1'b0}}; end /* synthesis translate_on */ /*----------------------------------------------------------------------------- * Основной код: */ always @(posedge i_WR_CLK) begin if (i_WR_EN) for (j = 0; j < WIDTH_WR_DATA; j = j + 1) R_tmp_mem[(i_WR_ADDR * WIDTH_WR_DATA) + j] <= i_WR_DATA[j]; end always @(posedge i_RD_CLK) begin R_rd_addr <= i_RD_ADDR; end always @*//(posedge i_RD_CLK) <=== пробовал и в комментарии и без for (k = 0; k < WIDTH_RD_DATA; k = k + 1) o_RD_DATA[k] = R_tmp_mem[(R_rd_addr * WIDTH_RD_DATA) + k]; endmodule <================================================== только вот беда, синтезатор (Symplify_pro8.1) не берет это описание как БЛОЧНУЮ ПАМЯТЬ, и пишет: Could not implement Block RAM. Is the read address registered using the same clock as the RAM? Как правильно описать такую модель для Блочной памяти? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба Если это обсуждалось (в чем я сильно сомневаюсь), дайте ссылочку, пожалуйста, то же и по appnotes, использовал для примера CORE Generator, он сослался на библиотечный элемент BLKMEMDP_V6_1.v, слишком все тяжело описано в нем, разобраться не могу, сам придумал реализацию, по крайней мере в моделе всё как и задумывалось: <================================================== /* ОБЪЯВЛЕНИЕ МОДУЛЯ */ module C_DPINDEP_RAM /*----------------------------------------------------------------------------- * Объявление параметров: */ #( parameter WIDTH_WR_DATA = 1, WIDTH_WR_ADDR = 12, DEPTH_WR = (1<<WIDTH_WR_ADDR), WIDTH_RD_DATA = 8, WIDTH_RD_ADDR = 9 ) /*----------------------------------------------------------------------------- * Объявление портов: */ ( // порт записи input i_WR_CLK, // тактовый импульс записи i_WR_EN, // строб разрешения записи input [(WIDTH_WR_DATA-1): 0] i_WR_DATA,// шина данных записи input [(WIDTH_WR_ADDR-1): 0] i_WR_ADDR,// адресная шина записи // порт чтения input i_RD_CLK, // тактовый импульс чтения input [(WIDTH_RD_ADDR-1): 0] i_RD_ADDR, // адресная шина чтения output reg [(WIDTH_RD_DATA-1): 0] o_RD_DATA // шина данных чтения ); /*----------------------------------------------------------------------------- * Объявление сигналов: */ reg R_tmp_mem [(WIDTH_WR_DATA*DEPTH_WR-1):0]; reg [(WIDTH_RD_ADDR-1): 0] R_rd_addr; integer j, k; /* synthesis translate_off */ integer i; initial begin for (i = 0; i < WIDTH_WR_DATA*DEPTH_WR; i= i + 1) R_tmp_mem <= 1'b0; R_rd_addr <= {WIDTH_RD_ADDR{1'b0}}; end /* synthesis translate_on */ /*----------------------------------------------------------------------------- * Основной код: */ always @(posedge i_WR_CLK) begin if (i_WR_EN) for (j = 0; j < WIDTH_WR_DATA; j = j + 1) R_tmp_mem[(i_WR_ADDR * WIDTH_WR_DATA) + j] <= i_WR_DATA[j]; end always @(posedge i_RD_CLK) begin R_rd_addr <= i_RD_ADDR; end always @*//(posedge i_RD_CLK) <=== пробовал и в комментарии и без for (k = 0; k < WIDTH_RD_DATA; k = k + 1) o_RD_DATA[k] = R_tmp_mem[(R_rd_addr * WIDTH_RD_DATA) + k]; endmodule <================================================== только вот беда, синтезатор (Symplify_pro8.1) не берет это описание как БЛОЧНУЮ ПАМЯТЬ, и пишет: Could not implement Block RAM. Is the read address registered using the same clock as the RAM? Как правильно описать такую модель для Блочной памяти? <{POST_SNAPBACK}> Зачем core generator !!!!!!! XAPP205 - Data-Width Conversion FIFOs Using the Virtex Block SelectRAM Memory XAPP261 - Data-Width Conversion FIFOs Using the Virtex-II Block RAM Memory XAPP258 - FIFOs Using Virtex-II Block RAM и т.д. просто берем компоненит RAMB_16 и конфигурим его ручками -- Component declaration of the "ramb16(ramb16_v)" unit defined in -- file: "./src/unisim_vital.vhd" component ramb16 generic( DOA_REG : INTEGER := 0; DOB_REG : INTEGER := 0; INVERT_CLK_DOA_REG : BOOLEAN := false; INVERT_CLK_DOB_REG : BOOLEAN := false; RAM_EXTENSION_A : STRING := "NONE"; RAM_EXTENSION_B : STRING := "NONE"; READ_WIDTH_A : INTEGER := 0; READ_WIDTH_B : INTEGER := 0; SIM_COLLISION_CHECK : STRING := "ALL"; SRVAL_A : BIT_VECTOR := X"000000000"; SRVAL_B : BIT_VECTOR := X"000000000"; WRITE_MODE_A : STRING := "WRITE_FIRST"; WRITE_MODE_B : STRING := "WRITE_FIRST"; WRITE_WIDTH_A : INTEGER := 0; WRITE_WIDTH_B : INTEGER := 0); port( CASCADEOUTA : out std_ulogic; CASCADEOUTB : out std_ulogic; DOA : out std_logic_vector(31 downto 0); DOB : out std_logic_vector(31 downto 0); DOPA : out std_logic_vector(3 downto 0); DOPB : out std_logic_vector(3 downto 0); ADDRA : in std_logic_vector(14 downto 0); ADDRB : in std_logic_vector(14 downto 0); CASCADEINA : in std_ulogic; CASCADEINB : in std_ulogic; CLKA : in std_ulogic; CLKB : in std_ulogic; DIA : in std_logic_vector(31 downto 0); DIB : in std_logic_vector(31 downto 0); DIPA : in std_logic_vector(3 downto 0); DIPB : in std_logic_vector(3 downto 0); ENA : in std_ulogic; ENB : in std_ulogic; REGCEA : in std_ulogic; REGCEB : in std_ulogic; SSRA : in std_ulogic; SSRB : in std_ulogic; WEA : in std_logic_vector(3 downto 0); WEB : in std_logic_vector(3 downto 0)); end component; for all: ramb16 use entity unisim.ramb16(ramb16_v); если уже совсем не в моготу то пользуем уже готовый компоненты библитеки унисим типа RAMB_X_X. Все это описанно в Lib Guide Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MAZZI 1 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба На харр дал ссылки это очень хорошо, спасибо, только вернемся к вопросу, необходимо не ручками брать "готовый компоненты библиотеки унисим типа RAMB_X_X" и конфигурить их, а было бы классно, чтобы синтезатор сам понимал, что из описания модели RAM сделать блочную память, к примеру, как есть описание из Language Templates ISE, которое он в дальнейщем понимает как Block Ram, так и здеcь хотелось бы тоже самое. Это делает код более мобильным и переносимым на другие ПЛИС, ASIC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба Это делает код более мобильным и переносимым на другие ПЛИС, ASIC. <{POST_SNAPBACK}> Ну во первых это боольшой вопрос, т.к. : 1. Вам "повезло" с семейством, т.к. разная ширина шин у кмпонента это "фишка" данного семества и на "другие" так просто не переноситься. 2. Если вы хотите универсальности в ручную мапте адреса и демультиплексируете потоки.(как и сделано в компоненте). Но вот мне не удалось сказать синтезатору ИСЕ и симплифай (даже с контрейнами) что то что я описал на языке должно быть не блоком памяти с мультеплексором, а одним компонентом. А так это описываеться элементарно, а вот синтезируеться ...... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MAZZI 1 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба Как мы все дружно решаем данную ситуацию, давайте, парни, поднапряжемся, кто-нибудь найдет решение :). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба Как мы все дружно решаем данную ситуацию, давайте, парни, поднапряжемся, кто-нибудь найдет решение :). <{POST_SNAPBACK}> Ты скажи русским/английским языком что тебе надо ?? :glare: Если память сконфигуровать то читай апноты или руками конфигури. Если описать на языке то принцип тебе расказали, или ты хочешь что бы тебе еще и код с коментариями запостили ?? ну ты ленивый :excl: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MAZZI 1 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба Возможно ты прав, возможно я и ленивый, если ты ставишь вопрос таким образом, то: 1) помоги найди некорректность в моем описании на Verilog выложенное выше. 2) расскажи ещё раз принцип описания на языке, я его что-то не увидел здесь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба Возможно ты прав, возможно я и ленивый, если ты ставишь вопрос таким образом, то: 1) помоги найди некорректность в моем описании на Verilog выложенное выше. 2) расскажи ещё раз принцип описания на языке, я его что-то не увидел здесь. <{POST_SNAPBACK}> мне бежать надо по этому вкратце 1. порт записи 32 бита, адрес 8 бит. порт чтения 16 бит адресс 9 бит пишем просто по входным адресам, когда читаем первые 8 бит это адрес памяти, младший бит на выходной мультиплексор. 2. если наоборотт, то мультиплексируем сигнал разрешения записи. младшим битом а старшие 8 бит на адресс. В твоем описании (подробно не смотрел) симплифай ругаеться, т.к. у тебя есть массив пр.32 по 32 бита а ты почему то решил из него сделать 64 на 16 бит, адреса не совпадають :) удачи Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MAZZI 1 1 июля, 2005 Опубликовано 1 июля, 2005 · Жалоба мне бежать надо по этому вкратце 1. порт записи 32 бита, адрес 8 бит. порт чтения 16 бит адресс 9 бит пишем просто по входным адресам, когда читаем первые 8 бит это адрес памяти, младший бит на выходной мультиплексор. 2. если наоборотт, то мультиплексируем сигнал разрешения записи. младшим битом а старшие 8 бит на адресс. В твоем описании (подробно не смотрел) симплифай ругаеться, т.к. у тебя есть массив пр.32 по 32 бита а ты почему то решил из него сделать 64 на 16 бит, адреса не совпадають :) удачи <{POST_SNAPBACK}> то что ты вкратце описал, не очень красивое решение, т.к. все равно обращаешься на компоненты памяти, или я не прав? Да и было бы интереснее если бы ты показал на примере <== что ты имеешь ввиду Моё описание корректно: parameter WIDTH_WR_DATA = 1, WIDTH_WR_ADDR = 12, DEPTH_WR = (1<<WIDTH_WR_ADDR), // это будет 2**12=4096 <== WIDTH_RD_DATA = 8, WIDTH_RD_ADDR = 9 reg R_tmp_mem [(WIDTH_WR_DATA*DEPTH_WR-1):0]; reg [(WIDTH_RD_ADDR-1): 0] R_rd_addr; отсюда: reg R_tmp_mem [(1*4096-1):0]; reg [(9-1): 0] R_rd_addr; // 9 разрядный счетчик (2**9=512) по WIDTH_RD_DATA = 8 получается, что бит я покрываю 512*8=4096 при чтении, всё корректно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 4 июля, 2005 Опубликовано 4 июля, 2005 · Жалоба то что ты вкратце описал, не очень красивое решение, т.к. все равно обращаешься на компоненты памяти, или я не прав? Да и было бы интереснее если бы ты показал на примере <== что ты имеешь ввиду правда на ВХДЛ но смысл бумаю будет понятен library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; library WORK; use WORK.define_pkg.all; entity RAM_16_DWC_Dev is generic (WIDTH : integer := 16); port ( in_clock : in std_logic; in_reset_b : in std_logic; in_wr_data : in std_logic_vector(4*WIDTH-1 downto 0); in_wr_strobe : in std_logic; in_wr_addr : in std_logic_vector(3 downto 0); in_rd_addr : in std_logic_vector(5 downto 0); out_rd_data : out std_logic_vector(WIDTH-1 downto 0) ); end entity RAM_16_DWC_Dev; architecture RAM_16_DWC_Dev of RAM_16_DWC_Dev is type RAM_16 is array (0 to 7) of std_logic_vector(4*WIDTH-1 downto 0); signal mem : RAM_16; attribute RAM_STYLE of mem : signal is "distributed"; attribute SYN_RAMSTYLE of mem : signal is "select_ram"; begin mem_read_proc : process(in_clock) is variable reg0, reg1, reg2, reg3 : std_logic_vector(WIDTH-1 downto 0); variable mem_data : std_logic_vector(4*WIDTH-1 downto 0); begin if (rising_edge(in_clock)) then if (in_reset_b = '0') then out_rd_data <= (others => '0'); else mem_data := mem(conv_integer(in_rd_addr(5 downto 2))); demux_data(mem_data, reg0, reg1, reg2, reg3); case (in_rd_addr(1 downto 0)) is when "00" => out_rd_data <= reg0; when "01" => out_rd_data <= reg1; when "10" => out_rd_data <= reg2; when "11" => out_rd_data <= reg3; when others => null; end case; end if; end if; end process mem_read_proc; mem_write_proc : process(in_clock) is begin if (rising_edge(in_clock)) then if (in_wr_strobe = '1') then mem(conv_integer(in_wr_addr)) <= in_wr_data; end if; end if; end process mem_write_proc; end architecture RAM_16_DWC_Dev; насчет корректности твоего описания reg R_tmp_mem [(WIDTH_WR_DATA*DEPTH_WR-1):0]; reg [(WIDTH_RD_ADDR-1): 0] R_rd_addr; вот здесь ты объявляешь не память а регистр. А тебе нужна именно память, а не набор регистров. reg R_tmp_mem [(1*4096-1):0]; reg [(9-1): 0] R_rd_addr; // 9 разрядный счетчик (2**9=512) по WIDTH_RD_DATA = 8 получается, что бит я покрываю 512*8=4096 при чтении, всё корректно. А теперь скажи как ты будешь адресовать 8 ми битные слова ? Мы разговариваем про разные вещи, память это двумерный массив. У памяти может быть 1-2 порта чтения записи, если же их больше, то это приведет к памяти на регистрах. Если у тебя их много то ...... а если нет ?? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MAZZI 1 4 июля, 2005 Опубликовано 4 июля, 2005 · Жалоба правда на ВХДЛ но смысл бумаю будет понятен entity RAM_16_DWC_Dev is generic (WIDTH : integer := 16); port ( in_clock : in std_logic; in_reset_b : in std_logic; in_wr_data : in std_logic_vector(4*WIDTH-1 downto 0); in_wr_strobe : in std_logic; in_wr_addr : in std_logic_vector(3 downto 0); in_rd_addr : in std_logic_vector(5 downto 0); out_rd_data : out std_logic_vector(WIDTH-1 downto 0) ); end entity RAM_16_DWC_Dev; Ты изначально заложил то, что у тебя не может быть вход данных in_wr_data однобитовым mem_read_proc : process(in_clock) is variable reg0, reg1, reg2, reg3 : std_logic_vector(WIDTH-1 downto 0); variable mem_data : std_logic_vector(4*WIDTH-1 downto 0); begin if (rising_edge(in_clock)) then if (in_reset_b = '0') then out_rd_data <= (others => '0'); else mem_data := mem(conv_integer(in_rd_addr(5 downto 2))); demux_data(mem_data, reg0, reg1, reg2, reg3); case (in_rd_addr(1 downto 0)) is when "00" => out_rd_data <= reg0; when "01" => out_rd_data <= reg1; when "10" => out_rd_data <= reg2; when "11" => out_rd_data <= reg3; when others => null; end case; end if; end if; end process mem_read_proc; Вот и мультиплексор вылез о котором ты и упоминал ранее насчет корректности твоего описания reg R_tmp_mem [(WIDTH_WR_DATA*DEPTH_WR-1):0]; reg [(WIDTH_RD_ADDR-1): 0] R_rd_addr; вот здесь ты объявляешь не память а регистр. А тебе нужна именно память, а не набор регистров. Поправь меня, если я не прав, память с разрядностью шины данных в один бит не существует? R_tmp_mem - длинная однобитовая память, с которой я и работаю в дальнейшем по записи и по чтению. А теперь скажи как ты будешь адресовать 8 ми битные слова ? для меня в этот момент важен перевод последовательный в параллельный, и ты прав для записи многоразрядных слов это описание некорректно Мы разговариваем про разные вещи, память это двумерный массив. У памяти может быть 1-2 порта чтения записи, если же их больше, то это приведет к памяти на регистрах. Если у тебя их много то ...... а если нет ?? <{POST_SNAPBACK}> Что то ты здесь перемудрил :) в моем случае R_tmp_mem - двумерный массив [1]x[4096]. Запись reg R_tmp_mem [(WIDTH_WR_DATA*DEPTH_WR-1):0]; как раз это отображает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 4 июля, 2005 Опубликовано 4 июля, 2005 · Жалоба понятно, мы говорим о разных вещах. У нас разные задачи и разные подходы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться