微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 一个简单的fifo请大家帮忙简化一下

一个简单的fifo请大家帮忙简化一下

时间:10-02 整理:3721RD 点击:
初学vhdl,请大家帮忙简化仿真一些
请问接受端使用原始的时钟clk和fsyn是否能正确的采样串行输出数据?
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity fifo is
port(clk:in std_logic;--原始时钟
fsynut std_logic;--帧同步
datain:in std_logic_vector(7 downto 0);--并行输入数据
pcmoutut std_logic;--串行输出数据
n_clkut std_logic;--反向输出时钟
we:in std_logic;--写允许信号
oe:in std_logic;--片选信号
clearfifo:in std_logic;--清空fifo
address:in std_logic_vector(7 downto 0)--fifo地址
);
end fifo;
architecture a of fifo is
signal counter:std_logic_vector(3 downto 0);--用来产生帧同步
signal data:std_logic_vector(31 downto 0);--用来保存输入数据
signal interior_fsyn:std_logic;--内部使用的帧同步
signal write_signal:std_logic;--用来标示写地址和写数据
signal temp_address:std_logic_vector(7 downto 0);--保存地址
signal number:std_logic_vector(4 downto 0);--计数输出数据
signal interior_clk:std_logic;--内部移位输出使用的时钟为原始时钟反相
signal pcmout:std_logic;
begin
n_clk<=not clk;
interior_clk<=not clk;
---------------------------------------------------------------------------------
--------------------------------------------------------------------------------
write_signal<=we or oe;--产生写控制信号
---------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- 锁存地址
process(write_signal,clearfifo)
begin
if clearfifo='1'then
temp_address<="00000000";
elsif falling_edge(write_signal)then
temp_address<=address;
end if;
end process;
---------------------------------------------------------------------------------
--------------------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
counter<=counter+1;
end if;
end process;
-----------------------------------------------------------------------------------
------------------------------------------------------------------------------------
--产生帧同步
process(counter)
begin
if counter<"1000" then
fsyn<='1';
interior_fsyn<='1';
else
fsyn<='0';
interior_fsyn<='0';
end if;
end process;
---------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--存储输入数据
process(write_signal,clearfifo)
begin
if clearfifo='1' then
data<="00000000000000000000000000000000";
elsif rising_edge(write_signal) then
if temp_address="10000011" then--对应地址0x83
data(31 downto 24)<=datain;
elsif temp_address="10000010"then--对应地址0x82
data(23 downto 16)<=datain;
elsif temp_address="10000001"then--对应地址0x81
data(15 downto 8)<=datain;
elsif temp_address="10000000"then--对应地址0x80
data(7 downto 0)<=datain;
end if;
end if;
end process;
---------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--PCM输出先输出高位
--输出数据
process(interior_clk,clearfifo)
begin
if clearfifo='1' then
number<="11111";
elsif rising_edge(interior_clk)then
if interior_fsyn='1'then
number<=number-1;
case number is
when "11111"=>
pcmout<=data(31);
when "11110"=>
pcmout<=data(30);
when "11101"=>
pcmout<=data(29);
when "11100"=>
pcmout<=data(28);
when "11011"=>
pcmout<=data(27);
when "11010"=>
pcmout<=data(26);
when "11001"=>
pcmout<=data(25);
when "11000"=>
pcmout<=data(24);
when "10111"=>
pcmout<=data(23);
when "10110"=>
pcmout<=data(22);
when "10101"=>
pcmout<=data(21);
when "10100"=>
pcmout<=data(20);
when "10011"=>
pcmout<=data(19);
when "10010"=>
pcmout<=data(18);
when "10001"=>
pcmout<=data(17);
when "10000"=>
pcmout<=data(16);
when "01111"=>
pcmout<=data(15);
when "01110"=>
pcmout<=data(14);
when "01101"=>
pcmout<=data(13);
when "01100"=>
pcmout<=data(12);
when "01011"=>
pcmout<=data(11);
when "01010"=>
pcmout<=data(10);
when "01001"=>
pcmout<=data(9);
when "01000"=>
pcmout<=data(8);
when "00111"=>
pcmout<=data(7);
when "00110"=>
pcmout<=data(6);
when "00101"=>
pcmout<=data(5);
when "00100"=>
pcmout<=data(4);
when "00011"=>
pcmout<=data(3);
when "00010"=>
pcmout<=data(2);
when "00001"=>
pcmout<=data(1);
when "00000"=>
pcmout<=data(0);
when others=>
pcmout<='Z';
end case;
end if;
end if;
end process;
---------------------------------------------------------------------------------
--------------------------------------------------------------------------------
end a;

一个简单的fifo请大家帮忙简化一下
提几个小意见:
1。锁存地址和数据部分:
elsif falling_edge(write_signal)then
最好不要那write_signal当时钟来用,它应该是个控制信号。
2。PCM数据输出:
elsif rising_edge(interior_clk)then
最好不要在时钟上加反相再用,你可以直接用下降沿触发。
pcmout实际上是个并串转化的输出,不用这么复杂。
直接可以用:
datatmp(31 downto 0)<=datatmp(30 downto 0) & '0';
pcmout<=datatmp(31);
类似这样的写法,具体怎么做你可以根据你的实际情况考虑。
你原来的写法会产生一个32选1的MUX,对你的fmax影响很大。

一个简单的fifo请大家帮忙简化一下
谢谢小编大人啊

一个简单的fifo请大家帮忙简化一下
说明一下,首先0x83~0x80地址对应的空间相当于RAM,所以write_signal是使用RAM的片选信号ce和写信号we相或后产生的,在下降沿锁存地址,再上升沿锁存输入的数据,所以不是当作时钟用的。
datatmp(31 downto 0)<=datatmp(30 downto 0) & '0';
pcmout<=datatmp(31);
这样做的前提是要将pcm_out传给datatmp,可是在什么情况下传递啊
我开始也是用移位做的,可是没法把pcm_out传给datatmp,因为我要在四个连续的帧同步中
把RAM中的四个字节依次移位输出。

一个简单的fifo请大家帮忙简化一下
if falling_edge(write_signal)then
这种写法反映到硬件上就是将write_signal接到触发器的时钟端。这样做不好。
移位寄存器一般要一个load信号
比如:
process(clk)
if count=31 then
datatmp<=data;
else
datatmp(31 downto 0)<=datatmp(30 downto 0) & '0';
end if;
end process;
pcmout<=datatmp(31);

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top