Перейти к содержанию
    

можем вам только разрешить это сделать:)

 

можно описать память

 

reg [ADDR_S - 1 : 0] Addr;
reg [DATA_S - 1 : 0] Data [(2 ** ADDR_S) - 1 : 0];

always @(posedge clk)
   Addr <= addr_in;

always @(posedge clk)
   if(write_en)
      Data[addr_in] <= data_in;

assign data_out = Data[Addr];

 

это обычная память которая в 99% случаев автоматически укладывается синтезатором в специализированные блоки если они есть, или делается на регистрах если их нет. Можно явно использовать блоки

Можно использовать мего-функцию генератор. Как вам больше нравится. Можно найти шаблон описания памяти от производителя, в том числе и 2 портовой, если надо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

можем вам только разрешить это сделать:)

 

можно описать память

 

reg [ADDR_S - 1 : 0] Addr;
reg [DATA_S - 1 : 0] Data [(2 ** ADDR_S) - 1 : 0];

always @(posedge clk)
   Addr <= addr_in;

always @(posedge clk)
   if(write_en)
      Data[addr_in] <= data_in;

assign data_out = Data[Addr];

 

это обычная память которая в 99% случаев автоматически укладывается синтезатором в специализированные блоки если они есть, или делается на регистрах если их нет. Можно явно использовать блоки

Можно использовать мего-функцию генератор. Как вам больше нравится. Можно найти шаблон описания памяти от производителя, в том числе и 2 портовой, если надо.

 

Ого! Спасибо! :biggrin: А на каком языке этот код? :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

на английском:)

 

ну не на русском точно))

не сочтите за наглость, но можно ли такое написать на VHDL? Просто Verilog я вообще не знаю, а VHDL сейчас изучаю и прошивка на нём..

Изменено пользователем scorpein

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

process(all)
begin
  if (clk'event and clk = '1') then
    Addr <= addr_in;
    if(we) then
       Data[addr_in] <= data_in;
    end if;
  end if;
end process;

process(all)
   data_out <= Data[Addr];
end process;

 

вроде как то так, я давно на VHDL не писал

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

process(all)
begin
  if (clk'event and clk = '1') then
    Addr <= addr_in;
    if(we) then
       Data[addr_in] <= data_in;
    end if;
  end if;
end process;

process(all)
   data_out <= Data[Addr];
end process;

 

вроде как то так, я давно на VHDL не писал

 

Благодарю!!!!!! Шас буду смотреть, что получится...

Не могли бы вы дать краткое описание этого кода, потому как застрял на объекте "we", ну и остальное, чтобы не затормозить сильно.. :help:

Изменено пользователем scorpein

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если затруднения с ПЛИС, то может сделать этот простой интерфейс на микроконтроллере? Тайминги позволят?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

we - write enable внешний сигнал разрешения записи в память, если он один то то что на входе data_in попадает в ячейку с номером addr_in.

data_in - вход шины данных

addr_in - вход шины адреса

 

на data_out выдаются данные из ячейки с номером addr_in, но выдаются на следующем такте (так в памятях принято).

то есть выставляете addr_in, и на следующем такте можете забирать данные, а если хотите записать, то выставляете

addr_in, data_in, и we и данные будут записаны

 

как то так... на самом деле в книжке должно быть написано как память описывается. Если такой код вызывает затруднения, то надо сделать шаг назад и еще почитать основы, чуть сильнее

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если затруднения с ПЛИС, то может сделать этот простой интерфейс на микроконтроллере? Тайминги позволят?

Дело в том, что я получаю на ПЛИС данные с шины LPC, а далее мне необходимо их передать на МК. Так как частоты шины и МК не совпадают, появилась идея создания некой буферной памяти, откуда данные будут уже на частоте МК передаваться.

 

we - write enable внешний сигнал разрешения записи в память, если он один то то что на входе data_in попадает в ячейку с номером addr_in.

data_in - вход шины данных

addr_in - вход шины адреса

 

на data_out выдаются данные из ячейки с номером addr_in, но выдаются на следующем такте (так в памятях принято).

то есть выставляете addr_in, и на следующем такте можете забирать данные, а если хотите записать, то выставляете

addr_in, data_in, и we и данные будут записаны

 

как то так... на самом деле в книжке должно быть написано как память описывается. Если такой код вызывает затруднения, то надо сделать шаг назад и еще почитать основы, чуть сильнее

Спасибо большое за пояснения! Был бы рад сделать шаг назад, но время играет против меня.. :wacko:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я попробовал выделить память "штатными" средствами, которые предлагает сам Quartus. Пожалуйста посмотрите код...

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL;
--use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity LPC_IOW80 is

-- разрядность шин
generic 
(
	DATA_WIDTH : natural := 3;
	ADDR_WIDTH : natural := 5
);

Port 
(
lclk: in std_logic; -- LPC: 33MHz clock (rising edge)
lframe_n: in std_logic; -- LPC: frame, active low
lreset_n: in std_logic; -- LPC: reset, active low
lad: in std_logic_vector(3 downto 0); -- LPC: multiplexed bus

       --назначение портов для памяти
	addr	: in natural range 0 to 2**ADDR_WIDTH - 9;

	we		: in std_logic := '1';
	q		: out std_logic_vector((2**DATA_WIDTH -5) downto 0)

);
end LPC_IOW80;

architecture RTL of LPC_IOW80 is
type LPC_State_Type is 
(
IDLE, -- Waiting for a start condition
START, -- Start condition detected
WADDN3, -- I/O write address nibble 3 (A15..A12)
WADDN2, -- I/O write address nibble 2 (A11..A8 )
WADDN1, -- I/O write address nibble 1 (A7..A4)
WADDN0, -- I/O write address nibble 0 (A3-A0)
WDATN1, -- I/O write data nibble 0 (D7..D4)
WDATN0, -- I/O write data nibble 1 (D3..D0)
WHTAR0, -- I/O write host turn around phase 0
WHTAR1, -- I/O write host turn around phase 1
WSYNC, -- I/O write sync
WPTAR -- I/O write peripheral turn around
); 

signal LPC_State: LPC_State_Type;
signal lframe_nreg: std_logic; -- LPC frame register
signal lad_rin: std_logic_vector(lad'range); -- LPC input registers
signal W_Data: std_logic_vector(7 downto 0); -- LPC input Post Code

       -- создание массивов и объявление RAM
-- Build a 2-D array type for the RAM
subtype word_t is std_logic_vector((2**DATA_WIDTH-5) downto 0);
type memory_t is array(2**ADDR_WIDTH-9 downto 0) of word_t;

-- Declare the RAM signal.	
signal ram : memory_t;

-- Register to hold the address 
signal addr_reg : natural range 0 to 2**ADDR_WIDTH-9;


begin
---------------------------------------------------------------------------
-- LPC bidirectional pins definition.
---------------------------------------------------------------------------
-- Input register to get some timing margin
P_input_register: process(lclk)
begin
if (lclk'event and lclk='1') then
lad_rin <= lad;
lframe_nreg <= lframe_n;
end if;
end process;
---------------------------------------------------------------------------
-- LPC state machine
-- LPC_State value is actually one clock cycle late.
---------------------------------------------------------------------------
P_LPC_StatMachine: process(lclk)
begin
if (lclk'event and lclk='1') then
-- Synchronous reset
if (lreset_n = '0') then
LPC_State <= IDLE;
W_Data(7 downto 0) <= "00000000"; -- init. both displays to all on
else
case LPC_State is
-- Looking for a START condition
when IDLE =>
if (lframe_nreg = '0') and (lad_rin = "0000") then
LPC_State <= START; -- START condition detected
end if;
-- Skip extra cycles on START frame
-- (can be many clock cycles)
-- and then, check for I/O write transaction
when START =>
if (lframe_nreg = '0') then -- frame still asserted
if (lad_rin /= "0000") then
LPC_State <= IDLE; -- unsupported start code
end if;
else
if (lad_rin(3 downto 1) = "001") then
LPC_State <= WADDN3; -- I/O write detected
else
LPC_State <= IDLE; -- unsupported command
end if;
end if;
-- --------------------------------
-- I/O write transaction processing
-- --------------------------------
when WADDN3 => -- Write Data Address Nibble 3
-- Find next state
if (lframe_nreg = '0') or (lad_rin /= "0000") then
LPC_State <= IDLE; -- abort cycle, bad frame
-- or address mismatch
else
LPC_State <= WADDN2;
end if;
when WADDN2 => -- Write Data Address Nibble 2
-- Find next state
if (lframe_nreg = '0') or (lad_rin /= "0000") then
LPC_State <= IDLE; -- abort cycle, bad frame
-- or address mismatch
else
LPC_State <= WADDN1;
end if;
when WADDN1 => -- Write Data Address Nibble 1
-- Find next state
if (lframe_nreg = '0') or (lad_rin /= "1000") then
LPC_State <= IDLE; -- abort cycle, bad frame
-- or address mismatch
else
LPC_State <= WADDN0;
end if;
when WADDN0 => -- Write Data Address Nibble 0
-- Find next state
if (lframe_nreg = '0') or (lad_rin /= "0000") then
LPC_State <= IDLE; -- abort cycle, bad frame
-- or address mismatch
else
-- Write address valid. Subsequent Data displays.
LPC_State <= WDATN0; -- Next state will get
-- first data nibble
end if;
when WDATN0 => -- Data LSN (Least Significant Nibble)is
-- sent first
W_Data(3 downto 0) <= lad_rin; -- latch data (LSN)
if (lframe_nreg = '1') then
LPC_State <= WDATN1; -- Next state gets
-- 2nd data nibble
else
LPC_State <= IDLE;
end if;
when WDATN1 => -- Data MSN (Most Significant Nibble)
W_Data(7 downto 4) <= lad_rin; -- latch data (MSN)
if (lframe_nreg = '1') then
LPC_State <= WHTAR0;
else
LPC_State <= IDLE;
end if;
when WHTAR0 => -- Write Data Turn Around Cycle 0
if (lframe_nreg = '1') and (lad_rin = "1111") then
LPC_State <= WHTAR1;
else
LPC_State <= IDLE;
end if;
when WHTAR1 => -- Write Data Turn Around Cycle 1
if (lframe_nreg = '1') then
LPC_State <= WSYNC;
else
LPC_State <= IDLE;
end if;
when WSYNC => -- Write Data Sync Cycle
-- Note: No device to respond with a synch at I\O addr
-- 080h. Therefore bus should time out and abort.
-- State ==> to IDLE
if (lframe_nreg = '1') then
LPC_State <= WPTAR;
else
LPC_State <= IDLE;
end if;
when WPTAR => -- Write Data Final Turn Around Cycle
-- (not needed -- see WSYNC)
LPC_State <= IDLE; -- I/O write cycle end
when others =>
LPC_State <= IDLE; -- all other cases
end case;
end if;
end if;
end process;

       --данные с шины по тетраде помещаются в ram
process(lclk)
begin
if(rising_edge(lclk)) then
	if(we = '1') then
		ram(addr) <= W_data(7 downto 4);
	end if;

	-- Register the address for reading
	addr_reg <= addr;
end if;
	if(rising_edge(lclk)) then
	if(we = '1') then
		ram(addr) <= W_data(3 downto 0);
	end if;

	-- Register the address for reading
	addr_reg <= addr;
end if;
end process;

       --собственно вывод данных
       q <= ram(addr_reg);


end RTL;

Изменено пользователем scorpein

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только что предложили использовать внешнюю RAM-память. Модуль на 128 кб. Должны подвезти. Наверное, будет лучше использовать такой вариант...

 

Привезли память UM61256K-15 (аналог IS61C256AH). Теперь нужно передавать на неё байты данных с ПЛИС и считывать их МК. Подскажите по этой теме? :help:

Изменено пользователем scorpein

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Обожаю такие решения%)

Я бы предложил вам использовать профессиональных инженеров, их найти труднее чем СРАМ, но и выхлоп будет лучше.

 

Подсказываю по теме. Берет и используете.

Память однопортовая, поэтому доступ к ней будет иметь одновременно только 1 устройство. В вашем случае это будет ПЛИС. Поэтому в ПЛИС вам надо организовать механизм арбитража доступа к памяти. Чтобы плис могла писать в нее когда ей надо, и предоставлять процессору доступ на чтение когда ему надо. Внутри вы могли сделать 2 портовую память и лазить в нее без арбитража, а тут наслаждайтесь проектированием:)

 

Вы интерфейс проц - плис то наладили? Может с него начать, а не с памяти?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Обожаю такие решения%)

Я бы предложил вам использовать профессиональных инженеров, их найти труднее чем СРАМ, но и выхлоп будет лучше.

 

Подсказываю по теме. Берет и используете.

Память однопортовая, поэтому доступ к ней будет иметь одновременно только 1 устройство. В вашем случае это будет ПЛИС. Поэтому в ПЛИС вам надо организовать механизм арбитража доступа к памяти. Чтобы плис могла писать в нее когда ей надо, и предоставлять процессору доступ на чтение когда ему надо. Внутри вы могли сделать 2 портовую память и лазить в нее без арбитража, а тут наслаждайтесь проектированием:)

 

Вы интерфейс проц - плис то наладили? Может с него начать, а не с памяти?

 

Использовать внешнюю память приходится из-за малого числа вентилей в моём ПЛИС - всего 240. Та прошивка, которую выкладывал выше забила его на 95%.

Сейчас как раз обдумываю арбитраж.

С интерфейсом ещё ничего не решилось. :laughing: На просторах интернета в основном решения передачи от МК к ПЛИСу, не уверен, что это мне подойдёт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

так это CPLD что ли? Ну так можете бросать это дело... CPLD у вас может выполнять только функцию преобразования SPI в параллельную шину для памяти от проца, больше его ни на что не хватит... С другой стороны можно взять любой АРМ и FRAM к нему как внешнюю оперативку и всех делов...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

функцию преобразования SPI в параллельную шину для памяти от проца

Прошу прощения, но не я не совсем понял, в чём смысл этой функции, относительно задачи.. :wacko:

Менять устройство, к сожалению, уже невозможно. Нужно делать с этим. :laughing:

 

Почему Quartus ругается на

            io[addr] <= W_data(7 downto 0);

или

Data[addr_in] <= data_in;

 

Постоянно ошибка Error (10500): VHDL syntax error at LPC_IOW80.vhd(185) near text "<="; expecting "(", or "'", or "." :(

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...