Реализация FIFO - VHDL
Я столкнулся с еще одной трудностью при создании экземпляра кода fifo в моем верхнем модуле. Я хочу сохранить некоторый набор данных, скажем "ДОБРО ПОЖАЛОВАТЬ В МИР ПЛИС", из моего последовательного порта (принимающей подсистемы), а затем я хочу получить его обратно, скажем, когда кнопка на плате fpga нажата или FIFO заполнен. У меня есть мой код fifo и код последовательной связи. Идея - данные, отправленные с клавиатуры -> принимающая подсистема -> FIFO -> передающая подсистема -> гипертерминал. В настоящее время я использую FIFO шириной 8 бит и говорю 28 глубиной только для хранения небольших данных. Пожалуйста, помогите мне в этом отношении, как я могу реализовать это. У меня есть байт, поступающий от получателя, сохраненный в register_save. код FIFO
inst_bit8_recieve_unit : entity work.byte_recieve_8N1
port map ( ck => ck,
reset => reset,
new_byte_in_buffer => new_byte_in_buffer,
byte_read_from_buffer => byte_read_from_buffer,
recieve_buffer => register_save,
JA_2 => JA(2));
---------------------FIFO instantiate-------------------------------
inst_of_fifo_Recieve_unit : entity work.fifo
generic map (B => data_bits, W => fifo_width)
port map ( ck => ck,
reset => reset,
rd => rd_rx,
wr => wr_rx,
write_data => num_recieved,
read_data => num_recieved_fifo,
empty => empty_rx,
full => full_rx );
inst_bit8_transmit_unit : entity work.byte_transmit_8N1
port map ( ck => ck,
reset => reset,
send_byte_ready => send_byte_ready,
send_byte_done => send_byte_done ,
send_buffer => num_send,
JAOUT_0 => JAOUT );
proc_send5byte: process(ck, reset, state_byte5, send_byte_done, num_send, state_button_0, num_recieved_fifo, rd_rx)
begin
if reset = '1' THEN
state_byte5 <= idle;
send_byte_ready <='0';
num_send <= "00000000" ;
else
if rising_edge(ck) then
case state_byte5 is
when idle => ---- in this, if btn(0) is high i.e pressed then only state_byte5 will go to next state
if state_button_0 = transit_pressed then
state_byte5 <= byte;
end if;
-----===============================================================
when byte =>
if (not empty_rx = '1') then
if send_byte_ready ='0' and send_byte_done = '0' then ----here if condition is satified the send_byte_ready will be set
send_byte_ready <='1'; --------- shows next byte is ready
num_send <= num_recieved_fifo;
rd_rx <='1';
end if;
end if;
if send_byte_ready = '1' and send_byte_done = '1' then --- during load state send_byte will be resets
send_byte_ready <='0';
rd_rx <= '0';
state_byte5 <= idle; ----------- go back to idle
end if;
--end if;
---===============================================================
when others =>
state_byte5 <= idle; ------------- for other cases state state _byte5 will be in idle
send_byte_ready <= '0';
rd_rx <= '0';
end case;
end if;
end if;
end process;
proc_recieving_byte : process (ck, reset, register_save, new_byte_in_buffer, full_rx, num_recieved, wr_rx)
begin
if reset = '1' then
byte_read_from_buffer <= '0';
else
if rising_edge(ck) then
if full_rx = '0' then
if new_byte_in_buffer = '1' and byte_read_from_buffer = '0' then
byte_read_from_buffer <= '1';
wr_rx <= '1';
num_recieved(7 downto 0 ) <= register_save( 7 downto 0);
end if;
end if;
if new_byte_in_buffer = '0' then
byte_read_from_buffer <= '0';
wr_rx <= '0';
end if;
--end if;
end if;
end if;
end process;
Просто добавил исправленный код, который сейчас работает. Проблема возникает при увеличении глубины fifo. Когда глубина>2, то каждый третий байт отсутствует. Пожалуйста, помогите, почему я теряю данные.
2 ответа
Принцип пятерки - "первым пришел - первым вышел". Вы не должны управлять этим.
- Вы размещаете свои данные на входе fifo
- Вы установили бит разрешения записи на "1"
- Вы ждете один такт
- Вы установили бит разрешения записи на "0"
затем данные сохраняются, вы делаете это снова, чтобы сохранить другое значение.
Когда вы хотите прочитать все данные (Fifo полный / любой случай, который вы хотите)
Вы устанавливаете бит разрешения чтения на "1", и каждый тактовый цикл вы будете получать данные.
--- process for recieving bytes and sent to fifo input with write enable signal------------
proc_recieving_byte : process (ck, reset, register_save, new_byte_in_buffer, full_rx, num_recieved, wr_rx)
begin
if reset = '1' then
byte_read_from_buffer <= '0';
else
if rising_edge(ck) then
if full_rx = '0' then
if new_byte_in_buffer = '1' and byte_read_from_buffer = '0' then
byte_read_from_buffer <= '1';
wr_rx <= '1';
num_recieved(7 downto 0 ) <= register_save( 7 downto 0);
else
wr_rx <= '0';
end if;
end if;
if new_byte_in_buffer = '0' then
byte_read_from_buffer <= '0';
wr_rx <= '0';
end if;
end if;
end if;
end process;
-------------------------------------------------------------------------------------------------------------------
---- this process checks first button state and then transmission occurs from fifo untill empty------
proc_send5byte: process(ck, reset, state_byte5, send_byte_done, num_send, state_button_0, num_recieved_fifo, rd_rx)
begin
if reset = '1' THEN
state_byte5 <= idle;
send_byte_ready <='0';
num_send <= "00000000" ;
else
if rising_edge(ck) then
case state_byte5 is
when idle => ---- in this, if btn(0) is high i.e pressed then only state_byte5 will go to next state
if state_button_0 = transit_pressed then
state_byte5 <= byte;
end if;
-----===============================================================
when byte =>
if (not empty_rx = '1') then
if send_byte_ready ='0' and send_byte_done = '0' then ----here if condition is satified the send_byte_ready will be set
send_byte_ready <='1'; --------- shows next byte is ready
num_send <= num_recieved_fifo;
rd_rx <='1';
else
rd_rx <='0';
end if;
end if;
if send_byte_ready = '1' and send_byte_done = '1' then --- during load state send_byte will be resets
send_byte_ready <='0';
rd_rx <= '0';
state_byte5 <= idle; ----------- go back to idle
end if;
---===============================================================
when others =>
state_byte5 <= idle;
send_byte_ready <= '0';
rd_rx <= '0';
end case;
end if;
end if;
end process;
Просто нашел ошибку и исправил, как указано выше, которая работает очень хорошо. Комментарии к улучшению приветствуются.