реклама на сайте
подробности

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> FIFO (CPLD+SRAM)
EvgenyNik
сообщение Sep 7 2015, 06:06
Сообщение #31


Знающий
****

Группа: Свой
Сообщений: 597
Регистрация: 24-05-06
Из: г. Чебоксары
Пользователь №: 17 402



Цитата(Golikov A. @ Sep 7 2015, 08:36) *
и зачем это все?
Чтобы проц имел доступ к последним данным, а не к тем, которые были когда-то до тех пор, пока FIFO не забилось.
Цитата(Golikov A. @ Sep 7 2015, 08:36) *
ТС спросил можно ли сделать такое фифо, а вы уже все обсудили и интерфейсы, и АЦП, и прочее...
При таком подходе - согласен. Но, вообще говоря, из задачи не совсем ясна конечная цель ТС. Правильность того или иного подхода будет сильно зависеть от прочих условий.


--------------------
Почему разработчики систем повышенной надёжности плохо справляются с простыми проектами? :)
Go to the top of the page
 
+Quote Post
uragan90
сообщение Sep 7 2015, 06:57
Сообщение #32


Местный
***

Группа: Свой
Сообщений: 248
Регистрация: 2-02-09
Из: Тверь
Пользователь №: 44 309



Цитата(Maverick @ Sep 7 2015, 10:02) *
как я понял у ТС однопортовая память SRAM

Да! Одно портовая память срам! Хочу создать модуль контроллера срам, чтоб с ней работать как с фифо, но писать в неё по фронту сигнала WD который приходит из другого модуля, а по спаду WD сбрасывать в регистр и хранить там пока не перелью данные в мк и не произведу следующий запрос чтения.
Вот начал писать модуль сий. Затык с этим самым "автоматом состояний" который должен активировать регистр rdy когда посылаем запрос и ожидаем данные, вот тут за спотыкался.

CODE
module sram_control(
input clk_pld, //основной такт плис
input wd, //запись в sram, (высокий приоритет)
input request, //запрос данных
output reg ack, //подтверждение готовности данных
output empty, //sram пустая (читать нельзя)
output full, //sram полная (писать нельзя)
output [17:0] addr, //адрес sram
input [15:0] din, //вход данных для записи во внешнюю sram
output reg [15:0] dout, //выход данных для чтения из sram
inout [15:0] dinout //двунаправленный порт данных для подключения непосредственно к sram
);

reg rdy = 0;
reg [15:0] buff = 0; //буфер 3х состояний
reg [18:0] count_w = 0; //регистр счётчика записи
reg [18:0] count_r = 0; //регистр счётчика чтения

//счётчик адреса записи
always @(posedge clk)
begin
if(wd) count_w = count_w + 1;
end

//счётчик адреса чтения
always @(posedge clk)
begin
if(rdу) count_r = count_r + 1;
end

//процес управляющий логикой чтения данных
always @(posedge clk)
begin
if(request)
begin

//??????????????????????????????????
end
end


always @(posedge clk)
begin
if(wd) buff = din;
else
begin
buff = 16'bz;
if(rdу)
dout = dinout;
end
end

assign dinout = buff;
assign addr = (!wd && rdу)? count_r : count_w;

assign full = ((count_w[17:0] == count_r[17:0]) && (count_w[18] ^^ count_r[18]))? 1'b1 : 1'b0;
assign empty = ((count_w[17:0] == count_r[17:0]) && (!(count_w[18] ^^ count_r[18])))? 1'b1 : 1'b0;
endmodule

Go to the top of the page
 
+Quote Post
krux
сообщение Sep 7 2015, 07:22
Сообщение #33


Профессионал
*****

Группа: Свой
Сообщений: 1 700
Регистрация: 2-07-12
Из: дефолт-сити
Пользователь №: 72 596



при старте, если указатели чтения и записи равны (т.е. записей в озу нет), то первая запись должна идти напрямую в dout.
empty при этом падает в 0.
следующие записи если empty в нуле идут в sram, счетчик записей увеличивается.
если активны циклы записи, а микроконтроллер увидев не empty решил почитать, то он читает dout, и empty становится в 1 до момента, когда будет возможность прочитать данные из sram в dout.
в ближайший возможный момент когда записи нет, а empty в 1, и есть записи в озу - из sram вычитывается в dout, empty падает в 0.

идея понятна?


--------------------
провоцируем неудовлетворенных провокаторов с удовольствием.
Go to the top of the page
 
+Quote Post
uragan90
сообщение Sep 7 2015, 08:21
Сообщение #34


Местный
***

Группа: Свой
Сообщений: 248
Регистрация: 2-02-09
Из: Тверь
Пользователь №: 44 309



Цитата(krux @ Sep 7 2015, 11:22) *
при старте, если указатели чтения и записи равны (т.е. записей в озу нет), то первая запись должна идти напрямую в dout.
empty при этом падает в 0.
следующие записи если empty в нуле идут в sram, счетчик записей увеличивается.
если активны циклы записи, а микроконтроллер увидев не empty решил почитать, то он читает dout, и empty становится в 1 до момента, когда будет возможность прочитать данные из sram в dout.
в ближайший возможный момент когда записи нет, а empty в 1, из sram вычитывается в dout, empty падает в 0.

идея понятна?

Оооо.. Точно!!!! Спасибо!!! Действительно в начале должны данные на выход захлопнутся, а уж потом сливаться в sram. Ведь если первым зашёл то первым и выйти должен по принципу фифо

Вобщем суть такая данные у меня заливаются в плис по 8 бит шине, а sram 16бит это дало мне возможность написать модуль который забирает данные по 8 бит и складывает в регистр 16 бит для того чтоб залить их в sram и плюс время целых два такта на то чтоб можно было по одному из них записывать, а по другому считывать.
Вот текст этой прослойки типа

CODE
module translator(
input wire clk, //клок
input wire [7:0]sbyte, //вход 1байт
input wire rdy, //загрузка байта
output reg [15:0]word, //выход 2байта
output reg wr //данные готовы
);

reg cnt = 0;
reg [15:0]buff0 = 0;

always @(posedge rdy)
begin
if(!cnt)
begin
buff0[15:8] = sbyte[7:0];
end
else
begin
buff0[7:0] = sbyte[7:0];
word = buff0;
end
cnt = cnt + 1'b1;
end

always @(posedge clk)
begin
wr = ~cnt && rdy;
end

endmodule
Go to the top of the page
 
+Quote Post
uragan90
сообщение Sep 24 2015, 12:44
Сообщение #35


Местный
***

Группа: Свой
Сообщений: 248
Регистрация: 2-02-09
Из: Тверь
Пользователь №: 44 309



Удалось реализовать такой модуль FIFO на внешней SRAM, но работает он как то не стабильно и через раз!
Уважаемые спецы, помогите найти причины не стабильности.

CODE

module FIFO_SRAM(
input Reset,
input Wclk,
input Rclk,
input Rd,
input Wd,
output full,
output empty,
input [DATA-1:0] Din,
output reg [DATA-1:0] Dout,
output [ADDR-1:0] Addr_Sram,
inout [DATA-1:0] Data_Sram,
output nCS,
output nOE,
output nWE
);

parameter ADDR = 4; // Параметр разрядности Адреса SRAM
parameter DATA = 4; // Параметр разрядности Данных SRAM

//--- Счётчики адресов чтения и записи ------------------------------
assign Addr_Sram = (Wd) ? write_addr[ADDR-1 : 0] : read_addr[ADDR-1 : 0];
reg [ADDR:0] read_addr=0;
always @(posedge Rclk) //По такту чтения
begin
if(Reset)
begin
read_addr <= 0;
end
else
begin
if (Rd) read_addr <= read_addr + 1'b1;
else read_addr <= read_addr;
end
end
//---
reg [ADDR:0] write_addr=0;
always @(posedge Wclk) //По такту записи
begin
if(Reset)
begin
write_addr <= 0;
end
else
begin
if (Wd) write_addr <= write_addr + 1'b1;
else write_addr <= write_addr;
end
end
//--- Абработка флагов заполненности ФИФО ------------------------------
assign full = ((write_addr[ADDR-1:0] == read_addr[ADDR-1:0]) && (write_addr[ADDR] ^ read_addr[ADDR]))? 1'b1 : 1'b0; //Фифо полное
assign empty = ((write_addr[ADDR-1:0] == read_addr[ADDR-1:0]) && (!(write_addr[ADDR] ^ read_addr[ADDR])))? 1'b1 : 1'b0; //Фифо пустое

//--- Логика комутации данных ------------------------------
wire [DATA-1 : 0] bus_data_out;
always@(posedge Wd or posedge Rd)
begin
Dout <= bus_data_out; //При любом запросе пишим на выход
end

assign bus_data_out = (Wd & empty)? Din : 'bz ; //Если запись и фифо пустое то со входа пишем на прямую в выходной регистр
assign Data_Sram = (Wd & ~empty)? Din : 'bz ; //Если запись и в выходном регистре не пусто то заполняем SRAM
assign bus_data_out = (~Wd & Rd)? Data_Sram : 'bz ; //Если нет записи, но есть чтение то из SRAM в выходной регистр

assign nCS = ~(Wd | Rd); //Разрешение чипа SRAM
assign nOE = ~(Rd); //Чтение чипа SRAM
assign nWE = ~(Wd); //Запись чипа SRAM

endmodule
Go to the top of the page
 
+Quote Post
Gorby
сообщение Sep 24 2015, 13:04
Сообщение #36


Местный
***

Группа: Свой
Сообщений: 449
Регистрация: 28-10-04
Из: Украина
Пользователь №: 1 002



Цитата(krux @ Sep 5 2015, 20:10) *
я полагаю, никто до сих пор не понял какого конечного результата вы хотите добиться =)


Значит, у Вас такой задачи не стояло biggrin.gif

Автору топика: вполне заурядная задача, смелее делайте и будет всё работать.
Не забудьте про довольно большие счетчики адресов, их сравнение, и результат этого сравнения.

Тут правильно советуют - операция записи в ОЗУ имеет приоритет перед чтением.
Работу с ОЗУ разбиваем на циклы. Цикл состоит из записи и потом чтения.
Если есть запрос на запись - пишем. Если есть запрос на чтение - читаем, пока не появится запрос на запись или не кончится чтение.
Если одновременно присутствует и запрос на запись, и на чтение, то в каждом цикле одно слово должно записаться, и одно-вычитаться.
Тут надо кропотливо поработать с таймингами ОЗУ.
Очень помогает моделирование в Моделсиме или что там у Вас есть.


--------------------
Умею молчать на 37 языках...
Go to the top of the page
 
+Quote Post
uragan90
сообщение Sep 24 2015, 13:22
Сообщение #37


Местный
***

Группа: Свой
Сообщений: 248
Регистрация: 2-02-09
Из: Тверь
Пользователь №: 44 309



Цитата(Gorby @ Sep 24 2015, 17:04) *
Тут правильно советуют - операция записи в ОЗУ имеет приоритет перед чтением.
Работу с ОЗУ разбиваем на циклы. Цикл состоит из записи и потом чтения.
Если есть запрос на запись - пишем. Если есть запрос на чтение - читаем, пока не появится запрос на запись или не кончится чтение.
Если одновременно присутствует и запрос на запись, и на чтение, то в каждом цикле одно слово должно записаться, и одно-вычитаться.
Тут надо кропотливо поработать с таймингами ОЗУ.

Так получается тут нужно реализовывать конечный автомат состояний?
Проблема видимо в том что у меня два клоковых домина и я не соображу как мне преодалеть эту проблему. У меня есть основной клок в CPLD 100Mhz. Частота записи 50Mhz а частота чтения 10Mhz. Эти частоты я реализовал делителями.
Была идея:
Запись в абсолютном приоритете!! Если поступил запрос на чтение то мы ждём пока кончится запись и как только это произойдёт то мы прочитаем данные на выход и выставим флаг готовности данных, сбросив при этом флаги запроса. Но при таком раскладе у меня в RTL модели видны защёлки, а это явная ошибка проекта.
Как же быть?

Я просто чувствую что это вполне реализуемо, но нет идей и помощи более опытных товарищей. laughing.gif
Go to the top of the page
 
+Quote Post
Gorby
сообщение Sep 24 2015, 13:49
Сообщение #38


Местный
***

Группа: Свой
Сообщений: 449
Регистрация: 28-10-04
Из: Украина
Пользователь №: 1 002



Цитата(uragan90 @ Sep 24 2015, 17:22) *
Так получается тут нужно реализовывать конечный автомат состояний?
Я просто чувствую что это вполне реализуемо, но нет идей и помощи более опытных товарищей. laughing.gif

Да, конечный автомат нужен. Но он простой, один-два триггера.

Вы с частотами-то поосторожнее. Тщательно просчитайте, возможно ли в принипе добиться от Вашей памяти такой растактовки. Тут нужен в клеточку лист бумаги, карандаш и мозг. Оно само всё покажет. Если основной клок 100МГц и данные поступают на каждом втором такте - то у Вас просто нет шансов даже на запись - каким образом сформировать управляющие сигналы? Или делать асинхронщину на RC цепях. У Вас нету системного подхода. Сначала - растактовка памяти (управляющие сигналы формируются из виртуального клока, и это будет явно не 100МГц, а 180, 166 или рядом). Критерий - максимально выжать быстродействие ОЗУ при условии, что управление идет почти на макс скорости (половина системного клока).

Вижу сам, что сумбурно. Вы сами сразу всё увидите, как растактовку ОЗУ нарисуете.


--------------------
Умею молчать на 37 языках...
Go to the top of the page
 
+Quote Post
uragan90
сообщение Sep 24 2015, 13:58
Сообщение #39


Местный
***

Группа: Свой
Сообщений: 248
Регистрация: 2-02-09
Из: Тверь
Пользователь №: 44 309



Цитата(Gorby @ Sep 24 2015, 17:49) *
Да, конечный автомат нужен. Но он простой, один-два триггера.

Вы с частотами-то поосторожнее. Тщательно просчитайте, возможно ли в принипе добиться от Вашей памяти такой растактовки. Тут нужен в клеточку лист бумаги, карандаш и мозг. Оно само всё покажет. Если основной клок 100МГц и данные поступают на каждом втором такте - то у Вас просто нет шансов даже на запись - каким образом сформировать управляющие сигналы? Или делать асинхронщину на RC цепях. У Вас нету системного подхода. Сначала - растактовка памяти (управляющие сигналы формируются из виртуального клока, и это будет явно не 100МГц, а 180, 166 или рядом). Критерий - максимально выжать быстродействие ОЗУ при условии, что управление идет почти на макс скорости (половина системного клока).

Вижу сам, что сумбурно. Вы сами сразу всё увидите, как растактовку ОЗУ нарисуете.

Да вроде работает, но видно что что то не то. Сложность заключается в проблеме моделирования шин с 3мя состояниями. В железе видно что работает но не так как хотелось бы
Go to the top of the page
 
+Quote Post
EvgenyNik
сообщение Sep 24 2015, 14:04
Сообщение #40


Знающий
****

Группа: Свой
Сообщений: 597
Регистрация: 24-05-06
Из: г. Чебоксары
Пользователь №: 17 402



Цитата(Gorby @ Sep 24 2015, 16:49) *
Если основной клок 100МГц и данные поступают на каждом втором такте - то у Вас просто нет шансов даже на запись - каким образом сформировать управляющие сигналы?
Но данные приходят по 8 бит, а ширина шины данных ОЗУ 16 бит, что даёт ему возможность накопить слово и записать его одним махом. А пока оно копится - прочитать 16 бит для выдачи.


--------------------
Почему разработчики систем повышенной надёжности плохо справляются с простыми проектами? :)
Go to the top of the page
 
+Quote Post
uragan90
сообщение Sep 24 2015, 14:09
Сообщение #41


Местный
***

Группа: Свой
Сообщений: 248
Регистрация: 2-02-09
Из: Тверь
Пользователь №: 44 309



Цитата(EvgenyNik @ Sep 24 2015, 18:04) *
Но данные приходят по 8 бит, а ширина шины данных ОЗУ 16 бит, что даёт ему возможность накопить слово и записать его одним махом. А пока оно копится - прочитать 16 бит для выдачи.

Именно так я и делаю!!! На частоте 100 я собераю данные по 8 бит, в регистр 16 бит. И того частота делится надвое. получается 50 Mhz. Память у меня 16ти разрядная и тем самым частота записи снижается. Читать я буду на частоте 10Mhz вот такой расклад получается, но проблема то в том что у меня 2 клоковых домина пересекающийся между собой!
Go to the top of the page
 
+Quote Post
EvgenyNik
сообщение Sep 24 2015, 15:10
Сообщение #42


Знающий
****

Группа: Свой
Сообщений: 597
Регистрация: 24-05-06
Из: г. Чебоксары
Пользователь №: 17 402



Цитата(uragan90 @ Sep 24 2015, 17:09) *
Читать я буду на частоте 10Mhz вот такой расклад получается, но проблема то в том что у меня 2 клоковых домина пересекающийся между собой!
Ну тогда читать Вам надо по системе "запрос-ответ". Т.е. некий мастер выставляет запрос на чтение по определённому адресу, ваша ПЛИС "принимает" этот запрос и ожидает паузы между записями. Наступает пауза максимум через 4 такта, Вы читаете из ОЗУ и выставляете готовность - "забирай" sm.gif
Более того, учитывая, что читаете Вы на 10МГц, у Вас, как навскидку думается, есть все шансы - обработать "запрос на чтение" в этом же цикле чтения, не заставляя читающее устройство ждать.


--------------------
Почему разработчики систем повышенной надёжности плохо справляются с простыми проектами? :)
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Sep 24 2015, 19:32
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



задача проста как 2 копейки, вы мудрите...
первое: делаете 2 портовую память.
- это просто, она на частоте 100 МГц, то пишет в 1 адрес (если есть сигнал записи, или не пишите), то выставляет 2 адрес и читает. Получаете 50 МГц 2 портовую память.

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

Код
input addr1;
input addr2;
input we;
input data_in;
output data_out;
reg PortSel; //регистр для выбора порта
reg mem_data_in; //регистр для сохранения

always @(posedge clk)
begin
   if(PortSel == 0)
      begin
        mem_addr <= addr2; //готовимся читать со 2 адреса
        mem_we <= 1'b0; //снимаем сигнал записи, 2 адрес чтение
        data_out <= mem_data_out; //защелкиваем данные с памяти (с прошлого задания адреса)
        PortSel <= 1'b1;
      end
   else
      begin
        mem_addr <= addr1; //готовимся писать в 1 адрес если надо
        mem_we <= we; //ставим we если надо
        mem_data_in <= data_in; //защелкиваем данные для записи
        PortSel <= 1'b0;
      end
end



А после того как вы это сделали, у вас остается сделать правильный переход из домена 100 МГц в домен 10.
Это просто запрос на чтение через 2 триггера, из 10 в 100, там выставляете защелкиваете данные на выход, через 1 клок данные будут валидны и стоять на входе 10. То есть на след такте вы их легко считаете...
Go to the top of the page
 
+Quote Post
uragan90
сообщение Sep 25 2015, 07:45
Сообщение #44


Местный
***

Группа: Свой
Сообщений: 248
Регистрация: 2-02-09
Из: Тверь
Пользователь №: 44 309



Цитата(Golikov A. @ Sep 24 2015, 23:32) *
задача проста как 2 копейки, вы мудрите...
первое: делаете 2 портовую память.
- это просто, она на частоте 100 МГц, то пишет в 1 адрес (если есть сигнал записи, или не пишите), то выставляет 2 адрес и читает. Получаете 50 МГц 2 портовую память.

У меня не двух портовая память CY7C1041DV33
У неё нет такой возможности обращения к одним и тем же данным по разным портам
Go to the top of the page
 
+Quote Post
EvgenyNik
сообщение Sep 25 2015, 07:55
Сообщение #45


Знающий
****

Группа: Свой
Сообщений: 597
Регистрация: 24-05-06
Из: г. Чебоксары
Пользователь №: 17 402



Цитата(uragan90 @ Sep 25 2015, 10:45) *
У меня не двух портовая память...
Дык, Вам и пишут - как из обычного 100МГц ОЗУ сделать а-ля двухпортовое 50МГц ОЗУ. Только порты будут фактически на ПЛИСке.


--------------------
Почему разработчики систем повышенной надёжности плохо справляются с простыми проектами? :)
Go to the top of the page
 
+Quote Post

4 страниц V  < 1 2 3 4 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 09:48
Рейтинг@Mail.ru


Страница сгенерированна за 0.01507 секунд с 7
ELECTRONIX ©2004-2016