TREQRESP学习和分析
TREQRESP结构
- TREQRESP学习和分析
- TREQRESP定义
- TREQRESP代码(VHDL版本)
- TREQRESP状态图
- SReset 重启状态:此状态rst复位信号有效或者linkup未连接到系统中时进行复位。其余时刻自动进入Sidle 空闲状态。
- Sidle 空闲状态:自动进入SWaitHead 等待头帧状态。用于其他状态复位使用。
- SWaitHead 等待头帧状态:treq_tvalid请求端有效='1'和treq_tready_w请求端准备好='1'时,进入SGotHead收获头帧状态。
- SGotHead 收获头帧状态:对头帧进行分析,从而选择进入SNread模式\DB模式\NWrite或SWrite模式
- sNswrGetData NWrite\SWrite读取数据状态:在req请求端valid有效 ready准备好 last响应了时,进入NWirte\SWrite响应状态,除了treq_tready外都是输入信号(tready在SWaitHead置为有效)。不满足一直保持该状态。
- SNswrResp 响应状态:当tresp_tready响应 准备好时,进入SNswrWA2axi 读取状态,更改response相应端 信号。
- SNswrWA2axi AXI写到RAM状态:计数器cntsNswrWA2axi计数到6时,进入sNswrWAwaitdone 等待完成状态。
- sNswrAwaitdone 等待结束状态:WAidle为1时,进入SNswrFinish结束状态。
- sMswrFinish 结束状态:一个周期跳转SIdle 空闲状态。
- SDBWrInfo DB写入FIFO数据状态:
- SDBresp DB响应状态:收到DB需要回复
- SDBfinishDB结束状态:一个周期返回SIdle。
- sNrdRAaxi Nread AXI RAM 状态:计数到6时,等于7分频,延时到达sNswrWAwaitdone Nread 等待结束状态
- sNrdRAwaitdone Nread 等待结束状态:RAidle=1 AXI RAM 空闲(输入信号)时,进入sNrdRespHead Nread 响应第一个头帧状态。
- sNrdRespHead Nread 响应第一个头帧状态:tresp_tready=1时,进入sNrdRespHead2 Nread 响应第二个头帧状态。
- sNrdRespHead2 Nread 响应第二个头帧状态:一个周期进入sNrdRespData SNread 响应数据状态。
- sNrdRespData SNread 响应数据状态:回复的数据到达输入的SIZE、tresp_tready响应端准备好='1'和tresp_tvalid_w相应端有效='1',进入sNrdFinish结束状态
- sNrdFinish Nread结束状态:一个周期到SIdle 空闲状态。
- 源代码
TREQRESP定义
原有的程序是一个SRIO接口控制模块。用于连接SRIO接口IP核其中Target端的TREQ和TResp两个端口。
TReq是指Target端的请求端口;
TResp是至Target端的Response响应端口。
XILINX的SRIO IP核使用的数据帧结构:
NWRITE(Normal WRITE 常规写模式) NWRITE_R(Normal WRITE Response,带响应的常规写模式) SWRITE(Stream WRITE,数据流写模式,连续写) NRead(常规读模式)
TREQRESP代码(VHDL版本)
输入代码块
1.导入库文件
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
2.信号端口
entity TREQRESP is
Port (
--系统时钟、复位信号------
clk : in STD_LOGIC;
rst : in STD_LOGIC;
--Status input interface linkup表示是否连接入系统----------------
linkup : in std_logic;--linkup表示是否连接入系统
--Config interface配置接口 设备自己的id地址----------------------
self_id : in std_logic_vector(15 downto 0);-- 设备自己的id地址
--Target request input interface request端口---------
treq_tvalid : in std_logic;
treq_tready : out std_logic;
treq_tlast : in std_logic;
treq_tdata : in std_logic_vector(63 downto 0);
treq_tkeep : in std_logic_vector( 7 downto 0);
treq_tuser : in std_logic_vector(31 downto 0);
--Target response output interface response端口--------
tresp_tvalid : out std_logic;
tresp_tready : in std_logic;
tresp_tlast : out std_logic;
tresp_tdata : out std_logic_vector(63 downto 0);
tresp_tkeep : out std_logic_vector( 7 downto 0);
tresp_tuser : out std_logic_vector(31 downto 0);
--Addr Remap 地址重映射-------------------------------
maping1_base : in std_logic_vector(15 downto 0);
maping1_high : in std_logic_vector(15 downto 0);
maping1_target : in std_logic_vector(31 downto 0);
maping2_base : in std_logic_vector(15 downto 0);
maping2_high : in std_logic_vector(15 downto 0);
maping2_target : in std_logic_vector(31 downto 0);
--DoorBell buffer fifo interface DBFIFO-----------
db_fifo_wren : out std_logic;
db_fifo_data : out std_logic_vector(63 downto 0);
--NWriteR/NWrite/SWrite-buf interface ------
WA_addr : out std_logic_vector( 7 downto 0);--地址
WA_wren : out std_logic_vector( 0 downto 0);--写使能
WA_data_wr : out std_logic_vector(63 downto 0);--数据总线
--AxiRam Control interface AXI控制RAM--------------------
WAstart : out std_logic; --AXi写
WAidle : in std_logic;
WAcount : out std_logic_vector(31 downto 0);
WAaddr : out std_logic_vector(31 downto 0);
--NRead-buf interface RAM---------------------------
RA_addr : out std_logic_vector( 7 downto 0);--读地址
RA_data_rd : in std_logic_vector(63 downto 0);--读数据
--AxiRam Control interface AXI控制RAM--------------------
RAstart : out std_logic; --Axi读
RAidle : in std_logic;
RAcount : out std_logic_vector(31 downto 0);
RAaddr : out std_logic_vector(31 downto 0)
);
end TREQRESP;
3.TREQRESP状态机输出段
architecture Behavioral of TREQRESP is
signal treq_tready_w : std_logic:='0';
signal regReqHead : std_logic_vector(63 downto 0):=x"0000000000000000";
signal TID : std_logic_vector( 7 downto 0):=x"00";
signal FTYPE : std_logic_vector( 3 downto 0):=x"0";
signal TTYPE : std_logic_vector( 3 downto 0):=x"0";
signal SIZE : std_logic_vector( 7 downto 0):=x"00";
signal ADDR : std_logic_vector(33 downto 0):="00"&x"00000000";
signal DBINFO : std_logic_vector(15 downto 0):=x"0000";
signal TUSER : std_logic_vector(31 downto 0):=x"00000000";
signal regLast : std_logic:='0';
signal cntsNswrWA2axi : std_logic_vector( 3 downto 0):=x"0";
signal cntsNrdRAaxi : std_logic_vector( 3 downto 0):=x"0";
signal cntTrans : std_logic_vector( 7 downto 0):=x"00";
signal cntsNrdRespData : std_logic_vector( 7 downto 0):=x"00"; --回复数据包计数器,回复到了第几个数据包
signal tresp_tvalid_w : std_logic:='0';
type state_type is ( sReset, sIdle,
sWaitHead, sGotHead,
sNswrGetData, sNswrResp, sNswrWA2axi, sNswrWAwaitdone, sNswrFinish,
sNrdRAaxi, sNrdRAwaitdone, sNrdRespHead, sNrdRespHead2, sNrdRespData, sNrdFinish,
sDbWrInfo, sDbResp, sDbFinish,
sError );
---状态解释
--
signal state,next_state : state_type:=sReset;
begin
--output logic-------------------------------------------------------
tresp_logic: process( state, FTYPE, TTYPE, TID, self_id, TUSER, RA_data_rd, cntsNrdRespData, SIZE ) begin
case state is
when sNswrResp =>--NWRITE_R或者SWRITE
if (FTYPE=x"5" and TTYPE=x"5") then--NWRITE_R
tresp_tvalid_w <= '1'; --应该是对方(即IP,I端)要写,并且是需要回应的写,因此我们需要发一个包回应,包长为1所以直接tlat置高
tresp_tlast <= '1';
else--在此状态但不是NWRITE_R的处理,不回复数据
tresp_tvalid_w <= '0';
tresp_tlast <= '0';
end if;
tresp_tdata <= TID & x"d04000"&x"00000000";--NWRITE_R的回复指定格式
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);--将自己的id和接受到TUSER低16位拼接
when sDbResp =>--收到DB需要回复
tresp_tvalid_w <= '1';
tresp_tlast <= '1';
tresp_tdata <= TID & x"d04000"&x"00000000";
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);--逻辑与上述一致(所以上述的回复也是一个DB )
when sNrdRespHead =>--NREAD RESPOND的包头响应
tresp_tvalid_w <= '1';
tresp_tlast <= '0';--因为还要发送数据包,所以不last
tresp_tdata <= TID & x"d84000"&x"00000000";
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
when sNrdRespData =>--NREAD RESPOND的数据响应
tresp_tvalid_w <= '1';
tresp_tdata <= RA_data_rd;
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
if ( cntsNrdRespData>=(SIZE(7 downto 3)) ) then--数到最后一个就拉高
tresp_tlast <= '1';
else
tresp_tlast <= '0';
end if;
when others =>
tresp_tvalid_w <= '0';
tresp_tlast <= '0';
tresp_tdata <= x"0000000000000000";
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
end case;
end process;
tresp_tvalid <= tresp_tvalid_w;
--应该相当于assign,应该是这个值还要在其他地方使用,因为VHDL定义的out类型不能在构造体内部使用,除非定义为buffer
--这一点和verilog不同,详见【参考书《VHDL硬件描述语言与数字逻辑电路设计(第五版)》p30】
信号初始化,默认当前状态机state和下一个状态机next_state为sReset状态
signal treq_tready_w : std_logic:='0';
signal regReqHead : std_logic_vector(63 downto 0):=x"0000000000000000";
signal TID : std_logic_vector( 7 downto 0):=x"00";
signal FTYPE : std_logic_vector( 3 downto 0):=x"0";
signal TTYPE : std_logic_vector( 3 downto 0):=x"0";
signal SIZE : std_logic_vector( 7 downto 0):=x"00";
signal ADDR : std_logic_vector(33 downto 0):="00"&x"00000000";
signal DBINFO : std_logic_vector(15 downto 0):=x"0000";
signal TUSER : std_logic_vector(31 downto 0):=x"00000000";
signal regLast : std_logic:='0';
signal cntsNswrWA2axi : std_logic_vector( 3 downto 0):=x"0";
signal cntsNrdRAaxi : std_logic_vector( 3 downto 0):=x"0";
signal cntTrans : std_logic_vector( 7 downto 0):=x"00";
signal cntsNrdRespData : std_logic_vector( 7 downto 0):=x"00"; --回复数据包计数器,回复到了第几个数据包
signal tresp_tvalid_w : std_logic:='0';
type state_type is ( sReset, sIdle,
sWaitHead, sGotHead,
sNswrGetData, sNswrResp, sNswrWA2axi, sNswrWAwaitdone, sNswrFinish,
sNrdRAaxi, sNrdRAwaitdone, sNrdRespHead, sNrdRespHead2, sNrdRespData, sNrdFinish,
sDbWrInfo, sDbResp, sDbFinish,
sError );
---状态解释
--
signal state,next_state : state_type:=sReset;
状态机响应段
--output logic-------------------------------------------------------
tresp_logic: process( state, FTYPE, TTYPE, TID, self_id, TUSER, RA_data_rd, cntsNrdRespData, SIZE ) begin
case state is
when sNswrResp =>--NWRITE_R和SWRITE共同使用sNswrResq状态
if (FTYPE=x"5" and TTYPE=x"5") then --NWRITE_R响应
tresp_tvalid_w <= '1'; --应该是对方(即IP,I端)要写,并且是需要回应的写,因此我们需要发一个包回应,包长为1所以直接tlat置高
tresp_tlast <= '1'; --tlast是相应数据
else--在此状态但不是NWRITE_R的处理,不回复数据
tresp_tvalid_w <= '0';
tresp_tlast <= '0';
end if;
tresp_tdata <= TID & x"d04000"&x"00000000";--NWRITE_R的回复指定格式
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);--将自己的id和接受到TUSER低16位拼接
when sDbResp =>--收到DB需要回复
tresp_tvalid_w <= '1';
tresp_tlast <= '1';
tresp_tdata <= TID & x"d04000"&x"00000000";
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);--逻辑与上述一致(所以上述的回复也是一个DB )
when sNrdRespHead =>--NREAD RESPOND的包头响应
tresp_tvalid_w <= '1';
tresp_tlast <= '0';--因为还要发送数据包,所以不last
tresp_tdata <= TID & x"d84000"&x"00000000";
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
when sNrdRespData =>--NREAD RESPOND的数据响应
tresp_tvalid_w <= '1';
tresp_tdata <= RA_data_rd;
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
if ( cntsNrdRespData>=(SIZE(7 downto 3)) ) then--数到最后一个就拉高last,响应
tresp_tlast <= '1';
else
tresp_tlast <= '0';
end if;
when others =>
tresp_tvalid_w <= '0';
tresp_tlast <= '0';
tresp_tdata <= x"0000000000000000";
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
end case;
end process;
tresp_tvalid <= tresp_tvalid_w;
--应该相当于assign,应该是这个值还要在其他地方使用,因为VHDL定义的out类型不能在构造体内部使用,除非定义为buffer
--这一点和verilog不同,详见【参考书《VHDL硬件描述语言与数字逻辑电路设计(第五版)》p30】
4.AxiRam Control interface AXI控制RAM
RAstart_logic: process(clk) begin if rising_edge(clk) then
if ( state=sNrdRAaxi and cntsNrdRAaxi<x"3" ) then
RAstart<='1';
else
RAstart<='0';
end if;
end if; end process;
RAcount <= x"00000020";--输出恒定值
RAaddr_logic: process(clk) begin if rising_edge(clk) then
RAaddr <= ADDR(31 downto 0);
end if; end process;
RA_addr_logic: process( state, tresp_tvalid_w, tresp_tready, cntsNrdRespData ) begin
if ( state=sNrdRespHead or state=sNrdRespHead2 ) then
RA_addr <= x"00";--以上两个state置0
elsif ( tresp_tvalid_w='1' and tresp_tready='1' ) then
RA_addr <= cntsNrdRespData+1;--回送数据计数器和地址之间的映射关系
else
RA_addr <= cntsNrdRespData+1;
end if;
end process;
状态机转移段
FSM_StateChange_logic: process(clk) begin if rising_edge(clk) then
if ( rst='1' or linkup='0' ) then --复位信号有效 或者 没有接入系统
state <= sReset;
else
case state is
when sReset =>
state <= sIdle;
when sIdle =>
state <= sWaitHead;
when sWaitHead =>
if (treq_tvalid='1' and treq_tready_w='1') then --request请求模块数据有效并且准备好
state <= sGotHead;
else
state <= state;
end if;
when sGotHead =>
if ( regLast='1' ) then --reglast 读取了last信号,响应后开始进行RAM读
if ( FTYPE=x"2" ) then
state <= sNrdRAaxi; -- NRead AXI RAM状态
elsif ( FTYPE=x"a" ) then
state <= sDbWrInfo; -- 数据写入FIFO状态
else
state <= sIdle;
end if;
else
if ( FTYPE=x"5" or FTYPE=x"6" ) then
state <= sNswrGetData;-- NWrite\SWrite 模式得到数据
else
state <= sIdle;
end if;
end if;
when sNswrGetData =>
if (treq_tvalid='1' and treq_tready_w='1' and treq_tlast='1') then
state <= sNswrResp;
else
state <= state;
end if;
when sNswrResp =>
if ( tresp_tready='1' ) then
state <= sNswrWA2axi;
else
state <= state;
end if;
when sNswrWA2axi =>
if ( cntsNswrWA2axi>=x"6" ) then
state <= sNswrWAwaitdone;
else
state <= state;
end if;
when sNswrWAwaitdone =>
if ( WAidle='1' ) then
state <= sNswrFinish;
else
state <= state;
end if;
when sNswrFinish =>
state <= sIdle;
when sNrdRAaxi =>
if ( cntsNrdRAaxi>=x"6") then
state <= sNrdRAwaitdone;
else
state <= state;
end if;
when sNrdRAwaitdone =>
if ( RAidle='1' ) then
state <= sNrdRespHead;
else
state <= state;
end if;
when sNrdRespHead =>
if ( tresp_tready='1' ) then
state <= sNrdRespHead2;
else
state <= state;
end if;
when sNrdRespHead2 =>
state <= sNrdRespData;
when sNrdRespData =>
if ( cntsNrdRespData>=(SIZE(7 downto 3)) and tresp_tready='1' and tresp_tvalid_w='1') then
state <= sNrdFinish;
else
state <= state;
end if;
when sNrdFinish =>
state <= sIdle;
when sDbWrInfo =>
state <= sDbResp;
when sDbResp =>
if ( tresp_tready='1' ) then
state <= sDbFinish;
else
state <= state;
end if;
when sDbFinish =>
state <= sIdle;
when others =>
state <= sReset;
end case;
end if;
end if; end process;
TREQRESP状态图
SReset 重启状态:此状态rst复位信号有效或者linkup未连接到系统中时进行复位。其余时刻自动进入Sidle 空闲状态。
regReqHead模块
regReqHead_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sReset or state=sIdle ) then -- SReset状态接收regHead复位
regReqHead <= x"0000000000000000";
elsif ( state=sWaitHead and treq_tvalid='1' ) then
regReqHead <= treq_tdata;
else
regReqHead <= regReqHead;
end if;
end if; end process;
译码模块
TID_FTYPE_TTYPE_SIZE_ADDR_TUSER_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sReset or state=sIdle ) then --SReset状态复位TID等信号
TID <= x"00";
FTYPE <= x"0";
TTYPE <= x"0";
SIZE <= x"00";
ADDR <= "00"&x"00000000";
DBINFO <= x"0000";
TUSER <= x"00000000";
regLast <= '0';
Sidle 空闲状态:自动进入SWaitHead 等待头帧状态。用于其他状态复位使用。
regReqHead模块
regReqHead_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sReset or state=sIdle ) then -- Sidle状态接收regHead复位
regReqHead <= x"0000000000000000";
elsif ( state=sWaitHead and treq_tvalid='1' ) then
regReqHead <= treq_tdata;
else
regReqHead <= regReqHead;
end if;
end if; end process;
译码模块
TID_FTYPE_TTYPE_SIZE_ADDR_TUSER_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sReset or state=sIdle ) then --SIdle状态复位TID等信号
TID <= x"00";
FTYPE <= x"0";
TTYPE <= x"0";
SIZE <= x"00";
ADDR <= "00"&x"00000000";
DBINFO <= x"0000";
TUSER <= x"00000000";
regLast <= '0';
SWaitHead 等待头帧状态:treq_tvalid请求端有效='1’和treq_tready_w请求端准备好='1’时,进入SGotHead收获头帧状态。
when sWaitHead =>
if (treq_tvalid='1' and treq_tready_w='1') then --treq_tvalid请求端有效='1'和treq_tready_w请求端准备好='1'时
state <= sGotHead;
else
state <= state;
end if;
treq_tready_w控制模块
treq_tready_w_logic: process(state) begin
case state is
when sWaitHead | sNswrGetData => --在sWaitHead 等待头帧状态下request请求端准备好treq_tready_w <= '1';
treq_tready_w <= '1';
when others =>
treq_tready_w <= '0';
end case;
end process;
treq_tready <= treq_tready_w;
regReqHead模块
regReqHead不清楚用途,目前只有这一个模块有,后续仿真模块进一步验证。
regReqHead_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sReset or state=sIdle ) then
regReqHead <= x"0000000000000000";
elsif ( state=sWaitHead and treq_tvalid='1' ) then --在SWaitHead 等待头帧状态下request请求有效treq_tvalid='1' ,读取请求数据到regRegHead数据
regReqHead <= treq_tdata; -- treq_tdata外界请求数据,输入状态
else
regReqHead <= regReqHead;
end if;
end if; end process;
译码模块
TID_FTYPE_TTYPE_SIZE_ADDR_TUSER_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sReset or state=sIdle ) then
TID <= x"00";
FTYPE <= x"0";
TTYPE <= x"0";
SIZE <= x"00";
ADDR <= "00"&x"00000000";
DBINFO <= x"0000";
TUSER <= x"00000000";
regLast <= '0';
elsif ( state=sWaitHead and treq_tvalid='1' ) then --在SWaitHead 等待头帧状态下,treq_tvalid=1(为输入信号)request请求有效时,进行数据解析
TID <= treq_tdata(63 downto 56);
FTYPE <= treq_tdata(55 downto 52);--FTYPE译码
TTYPE <= treq_tdata(51 downto 48);
SIZE <= treq_tdata(43 downto 36);
--ADDR <= treq_tdata(33 downto 0);
ADDR(33 downto 32) <= treq_tdata(33 downto 32);--ADDR重定向
if (treq_tdata(31 downto 16)>=maping1_base and treq_tdata(31 downto 16)<=maping1_high) then
ADDR(31 downto 0) <= treq_tdata(31 downto 0)-(maping1_base&x"0000")+maping1_target;
elsif (treq_tdata(31 downto 16)>=maping2_base and treq_tdata(31 downto 16)<=maping2_high) then
ADDR(31 downto 0) <= treq_tdata(31 downto 0)-(maping2_base&x"0000")+maping2_target;
else
ADDR(31 downto 0) <= treq_tdata(31 downto 0);
end if;
DBINFO <= treq_tdata(31 downto 16);
TUSER <= treq_tuser;
regLast <= treq_tlast;
SGotHead 收获头帧状态:对头帧进行分析,从而选择进入SNread模式\DB模式\NWrite或SWrite模式
when sGotHead => --对收获数据进行判断进入对应命令模式
if ( regLast='1' ) then
if ( FTYPE=x"2" ) then
state <= sNrdRAaxi; --进入Nread模式
elsif ( FTYPE=x"a" ) then
state <= sDbWrInfo; --进入DB FIFO信息写入模式
else
state <= sIdle; --命令不符进入SIdle 空闲状态
end if;
else
if ( FTYPE=x"5" or FTYPE=x"6" ) then
state <= sNswrGetData; --进入NWrite\SWrite 读取数据模式
else
state <= sIdle;
end if;
end if;
接收头帧译码模块
regLast信号出现在接收头帧译码模块。
TID_FTYPE_TTYPE_SIZE_ADDR_TUSER_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sReset or state=sIdle ) then
TID <= x"00";
FTYPE <= x"0";
TTYPE <= x"0";
SIZE <= x"00";
ADDR <= "00"&x"00000000";
DBINFO <= x"0000";
TUSER <= x"00000000";
regLast <= '0';
elsif ( state=sWaitHead and treq_tvalid='1' ) then
TID <= treq_tdata(63 downto 56);
FTYPE <= treq_tdata(55 downto 52);--FTYPE译码
TTYPE <= treq_tdata(51 downto 48);
SIZE <= treq_tdata(43 downto 36);
--ADDR <= treq_tdata(33 downto 0);
ADDR(33 downto 32) <= treq_tdata(33 downto 32);--ADDR重定向
if (treq_tdata(31 downto 16)>=maping1_base and treq_tdata(31 downto 16)<=maping1_high) then
ADDR(31 downto 0) <= treq_tdata(31 downto 0)-(maping1_base&x"0000")+maping1_target;
elsif (treq_tdata(31 downto 16)>=maping2_base and treq_tdata(31 downto 16)<=maping2_high) then
ADDR(31 downto 0) <= treq_tdata(31 downto 0)-(maping2_base&x"0000")+maping2_target;
else
ADDR(31 downto 0) <= treq_tdata(31 downto 0);
end if;
DBINFO <= treq_tdata(31 downto 16); --treq_tdata是个输入信号
TUSER <= treq_tuser; --treq_luser是个输入信号
regLast <= treq_tlast; --regLast来自treq_tlast,treq_last是个输入信号
else
TID <= TID;
FTYPE <= FTYPE;
TTYPE <= TTYPE;
SIZE <= SIZE;
ADDR <= ADDR;
DBINFO <= DBINFO;
TUSER <= TUSER;
regLast <= regLast;
end if;
end if; end process;
sNswrGetData NWrite\SWrite读取数据状态:在req请求端valid有效 ready准备好 last响应了时,进入NWirte\SWrite响应状态,除了treq_tready外都是输入信号(tready在SWaitHead置为有效)。不满足一直保持该状态。
when sNswrGetData =>
if (treq_tvalid='1' and treq_tready_w='1' and treq_tlast='1') then --treq请求valid有效 ready准备好 last响应了时,进入NWirte\SWrite响应状态,除了treq_tready外都是输入信号
state <= sNswrResp;
else
state <= state;
end if;
treq_tready_w_logic模块:在sWaitHead等待头帧或SNswrGetData Nwrite\SWrite数据接受状态treq_tready_w为1,treq_tready信号来源于treq_tready_w_logic模块
treq_tready_w_logic: process(state) begin
case state is
when sWaitHead | sNswrGetData =>
treq_tready_w <= '1';
when others =>
treq_tready_w <= '0';
end case;
end process;
treq_tready <= treq_tready_w;
WA_ram_logic模块:Write AXI RAM 模块,进行wr_en写使能、addr地址,data_wr写数据。
WA_ram_logic: process(clk) begin
if rising_edge(clk) then
case state is
when sNswrGetData =>
if ( treq_tvalid='1' and treq_tready_w='1' ) then
WA_wren <= "1";
else
WA_wren <= "0";
end if;
WA_addr <= cntTrans;
WA_data_wr <= treq_tdata;
when others =>
WA_addr <= x"00";
WA_wren <= "0";
WA_data_wr <= x"0000000000000000";
end case;
end if;
end process;
SNswrResp 响应状态:当tresp_tready响应 准备好时,进入SNswrWA2axi 读取状态,更改response相应端 信号。
when sNswrResp =>
if ( tresp_tready='1' ) then
state <= sNswrWA2axi;
else
state <= state;
end if;
cntTrans_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sNswrGetData ) then
if (treq_tvalid='1' and treq_tready_w='1') then
cntTrans <= cntTrans + 1;
else
cntTrans <= cntTrans;
end if;
elsif ( state=sNswrResp or state=sNswrWA2axi or state=sNswrWAwaitdone or state=sNswrFinish ) then --状态在SWrite\NWrite响应状态,cntTrans<=cntTrans
cntTrans <= cntTrans;
else
cntTrans <= x"00";
end if;
end if;
end process;
回复数据包计数器模块:回复收到了第几个数据包
cntsNrdRespData_logic: process(clk) begin if rising_edge(clk) then
if ( state=sNrdRespData and tresp_tvalid_w='1' and tresp_tready='1') then
cntsNrdRespData <= cntsNrdRespData+1;
elsif ( state=sNrdRAaxi or state=sNrdRAwaitdone or state=sNrdRespHead ) then
cntsNrdRespData <= x"00";
else
cntsNrdRespData <= cntsNrdRespData;
end if;
end if; end process;
tresp response响应模块
tresp_logic: process( state, FTYPE, TTYPE, TID, self_id, TUSER, RA_data_rd, cntsNrdRespData, SIZE ) begin
case state is
when sNswrResp =>--NWRITE_R或SWRITE
if (FTYPE=x"5" and TTYPE=x"5") then--NWRITE_R
tresp_tvalid_w <= '1'; --应该是对方(即IP,I端)要写,并且是需要回应的写,因此我们需要发一个包回应,包长为1所以直接tlat置高
tresp_tlast <= '1';
else--在此状态但不是NWRITE_R的处理,不回复数据
tresp_tvalid_w <= '0';
tresp_tlast <= '0';
end if;
tresp_tdata <= TID & x"d04000"&x"00000000";--NWRITE_R的回复指定格式
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);--将自己的id和接受到TUSER低16位拼接
SNswrWA2axi AXI写到RAM状态:计数器cntsNswrWA2axi计数到6时,进入sNswrWAwaitdone 等待完成状态。
when sNswrWA2axi =>
if ( cntsNswrWA2axi>=x"6" ) then
state <= sNswrWAwaitdone;
else
state <= state;
end if;
sNswrWA2axi计数模块
7分频计数,拖延时间从而使状态SNswrWA2axi状态到SNswrAwaitdone 等待结束状态。
cntsNswrWA2axi_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sNswrWA2axi ) then
cntsNswrWA2axi <= cntsNswrWA2axi + 1;
else
cntsNswrWA2axi <= x"0";
end if;
end if; end process;
RAM 地址转换模块
cntTrans_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sNswrGetData ) then
if (treq_tvalid='1' and treq_tready_w='1') then
cntTrans <= cntTrans + 1;
else
cntTrans <= cntTrans;
end if;
elsif ( state=sNswrResp or state=sNswrWA2axi or state=sNswrWAwaitdone or state=sNswrFinish ) then
cntTrans <= cntTrans;
else
cntTrans <= x"00";
end if;
end if;
end process;
AXI RAM读起始模块
--AXI RAM读起始模块
RAstart_logic: process(clk) begin if rising_edge(clk) then
if ( state=sNrdRAaxi and cntsNrdRAaxi<x"3" ) then
RAstart<='1';
else
RAstart<='0';
end if;
end if; end process;
RAcount <= x"00000020";--输出恒定值
RAaddr_logic: process(clk) begin if rising_edge(clk) then
RAaddr <= ADDR(31 downto 0);
end if; end process;
AXI RAM写控制模块
--AXI RAM写控制模块
WA_ctrl_logic: process(clk) begin
if rising_edge(clk) then
case state is
when sNswrWA2axi =>
if ( cntsNswrWA2axi<=x"3") then
WAstart <= '0';
else
WAstart <= '1';
end if;
WAcount <= x"000000"&cntTrans;
WAaddr <= ADDR(31 downto 0);
when sNswrWAwaitdone =>
WAstart <= '0';
WAcount <= x"000000"&cntTrans;
WAaddr <= ADDR(31 downto 0);
when others =>
WAstart <= '0';
WAcount <= x"00000000";
WAaddr <= x"00000000";
end case;
end if;
end process;
sNswrAwaitdone 等待结束状态:WAidle为1时,进入SNswrFinish结束状态。
when sNswrWAwaitdone =>
if ( WAidle='1' ) then --写AXI 总线空闲
state <= sNswrFinish;
else
state <= state;
end if;
sMswrFinish 结束状态:一个周期跳转SIdle 空闲状态。
when sNswrFinish =>
state <= sIdle;
SDBWrInfo DB写入FIFO数据状态:
DB的FIFO控制逻辑
DB的FIFO控制逻辑
db_fifo_logic: process(clk) begin if rising_edge(clk) then
if ( state=sDbWrInfo ) then
db_fifo_wren <= '1';--使能FIFO写
--db_fifo_data <= x"00" & TID & ADDR(31 downto 16) & TUSER;
db_fifo_data <= x"00" & TID & DBINFO & TUSER;--FIFO写数据包装{补充的位宽8,TID位宽8,DBINFO位宽16,TUSER位宽32}=1个包
else
db_fifo_wren <= '0';
db_fifo_data <= x"0000000000000000";
end if;
end if; end process;
解析、地址重映射模块
--解析、地址重映射模块
TID_FTYPE_TTYPE_SIZE_ADDR_TUSER_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sReset or state=sIdle ) then
TID <= x"00";
FTYPE <= x"0";
TTYPE <= x"0";
SIZE <= x"00";
ADDR <= "00"&x"00000000";
DBINFO <= x"0000";
TUSER <= x"00000000";
regLast <= '0';
elsif ( state=sWaitHead and treq_tvalid='1' ) then
TID <= treq_tdata(63 downto 56);
FTYPE <= treq_tdata(55 downto 52);--FTYPE译码
TTYPE <= treq_tdata(51 downto 48);
SIZE <= treq_tdata(43 downto 36);
--ADDR <= treq_tdata(33 downto 0);
ADDR(33 downto 32) <= treq_tdata(33 downto 32);--ADDR重定向
if (treq_tdata(31 downto 16)>=maping1_base and treq_tdata(31 downto 16)<=maping1_high) then
ADDR(31 downto 0) <= treq_tdata(31 downto 0)-(maping1_base&x"0000")+maping1_target;
elsif (treq_tdata(31 downto 16)>=maping2_base and treq_tdata(31 downto 16)<=maping2_high) then
ADDR(31 downto 0) <= treq_tdata(31 downto 0)-(maping2_base&x"0000")+maping2_target;
else
ADDR(31 downto 0) <= treq_tdata(31 downto 0);
end if;
DBINFO <= treq_tdata(31 downto 16);
TUSER <= treq_tuser;
regLast <= treq_tlast;
else
TID <= TID;
FTYPE <= FTYPE;
TTYPE <= TTYPE;
SIZE <= SIZE;
ADDR <= ADDR;
DBINFO <= DBINFO;
TUSER <= TUSER;
regLast <= regLast;
end if;
end if; end process;
SDBresp DB响应状态:收到DB需要回复
when sDbResp =>
if ( tresp_tready='1' ) then
state <= sDbFinish;
else
state <= state;
end if;
when sDbResp =>--收到DB需要回复
tresp_tvalid_w <= '1';
tresp_tlast <= '1';
tresp_tdata <= TID & x"d04000"&x"00000000";
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);--逻辑与上述一致(所以上述的回复也是一个DB )
SDBfinishDB结束状态:一个周期返回SIdle。
when sDbFinish =>
state <= sIdle;
sNrdRAaxi Nread AXI RAM 状态:计数到6时,等于7分频,延时到达sNswrWAwaitdone Nread 等待结束状态
when sNswrWA2axi =>
if ( cntsNswrWA2axi>=x"6" ) then
state <= sNswrWAwaitdone;
else
state <= state;
end if;
sNrdRaxi延迟模块
--sNrdRaxi延迟模块
cntsNrdRAaxi_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sNrdRAaxi ) then
cntsNrdRAaxi <= cntsNrdRAaxi + 1;
else
cntsNrdRAaxi <= x"0";
end if;
end if; end process;
sNrdRAwaitdone Nread 等待结束状态:RAidle=1 AXI RAM 空闲(输入信号)时,进入sNrdRespHead Nread 响应第一个头帧状态。
when sNrdRAwaitdone =>
if ( RAidle='1' ) then
state <= sNrdRespHead;
else
state <= state;
end if;
AXI RAM写控制模块
--AXI RAM写控制模块
WA_ctrl_logic: process(clk) begin
if rising_edge(clk) then
case state is
when sNswrWA2axi =>
if ( cntsNswrWA2axi<=x"3") then
WAstart <= '0';
else
WAstart <= '1';
end if;
WAcount <= x"000000"&cntTrans;
WAaddr <= ADDR(31 downto 0);
when sNswrWAwaitdone =>
WAstart <= '0';
WAcount <= x"000000"&cntTrans;
WAaddr <= ADDR(31 downto 0);
when others =>
WAstart <= '0';
WAcount <= x"00000000";
WAaddr <= x"00000000";
end case;
end if;
end process;
sNrdRespHead Nread 响应第一个头帧状态:tresp_tready=1时,进入sNrdRespHead2 Nread 响应第二个头帧状态。
when sNrdRespHead =>
if ( tresp_tready='1' ) then
state <= sNrdRespHead2;
else
state <= state;
end if;
sNrdRespHead2 Nread 响应第二个头帧状态:一个周期进入sNrdRespData SNread 响应数据状态。
when sNrdRespHead2 =>
state <= sNrdRespData;
收到数据计数器模块
--回复数据包计数器模块:回复到了第几个数据包
cntsNrdRespData_logic: process(clk) begin if rising_edge(clk) then
if ( state=sNrdRespData and tresp_tvalid_w='1' and tresp_tready='1') then
cntsNrdRespData <= cntsNrdRespData+1;
elsif ( state=sNrdRAaxi or state=sNrdRAwaitdone or state=sNrdRespHead ) then
cntsNrdRespData <= x"00";
else
cntsNrdRespData <= cntsNrdRespData;
end if;
end if; end process;
when sNrdRespData =>--NREAD RESPOND的数据响应
tresp_tvalid_w <= '1';
tresp_tdata <= RA_data_rd;
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
if ( cntsNrdRespData>=(SIZE(7 downto 3)) ) then--数到最后一个就拉高
tresp_tlast <= '1';
else
tresp_tlast <= '0';
end if;
sNrdRespData SNread 响应数据状态:回复的数据到达输入的SIZE、tresp_tready响应端准备好='1’和tresp_tvalid_w相应端有效=‘1’,进入sNrdFinish结束状态
when sNrdRespData =>
if ( cntsNrdRespData>=(SIZE(7 downto 3)) and tresp_tready='1' and tresp_tvalid_w='1') then
state <= sNrdFinish;
else
state <= state;
end if;
when sNrdRespData =>--NREAD RESPOND的数据响应
tresp_tvalid_w <= '1';
tresp_tdata <= RA_data_rd;
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
if ( cntsNrdRespData>=(SIZE(7 downto 3)) ) then--数到最后一个就拉高
tresp_tlast <= '1';
else
tresp_tlast <= '0';
end if;
sNrdFinish Nread结束状态:一个周期到SIdle 空闲状态。
when sNrdFinish =>
state <= sIdle;
源代码
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 2020/11/15 14:54:16
-- Design Name:
-- Module Name: TREQRESP - Behavioral
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity TREQRESP is
Port (
clk : in STD_LOGIC;
rst : in STD_LOGIC;
--Status input interface-----------------
linkup : in std_logic;
--Config interface-----------------------
self_id : in std_logic_vector(15 downto 0);
--Target request input interface---------
treq_tvalid : in std_logic;
treq_tready : out std_logic;
treq_tlast : in std_logic;
treq_tdata : in std_logic_vector(63 downto 0);
treq_tkeep : in std_logic_vector( 7 downto 0);
treq_tuser : in std_logic_vector(31 downto 0);
--Target response output interface--------
tresp_tvalid : out std_logic;
tresp_tready : in std_logic;
tresp_tlast : out std_logic;
tresp_tdata : out std_logic_vector(63 downto 0);
tresp_tkeep : out std_logic_vector( 7 downto 0);
tresp_tuser : out std_logic_vector(31 downto 0);
--Addr Remap-------------------------------
maping1_base : in std_logic_vector(15 downto 0);
maping1_high : in std_logic_vector(15 downto 0);
maping1_target : in std_logic_vector(31 downto 0);
maping2_base : in std_logic_vector(15 downto 0);
maping2_high : in std_logic_vector(15 downto 0);
maping2_target : in std_logic_vector(31 downto 0);
--DoorBell buffer fifo interface-----------
db_fifo_wren : out std_logic;
db_fifo_data : out std_logic_vector(63 downto 0);
--NWriteR/NWrite/SWrite-buf interface------
WA_addr : out std_logic_vector( 7 downto 0);--地址
WA_wren : out std_logic_vector( 0 downto 0);--写使能
WA_data_wr : out std_logic_vector(63 downto 0);--数据总线
--AxiRam Control interface--------------------
WAstart : out std_logic; --AXi写
WAidle : in std_logic;
WAcount : out std_logic_vector(31 downto 0);
WAaddr : out std_logic_vector(31 downto 0);
--NRead-buf interface---------------------------
RA_addr : out std_logic_vector( 7 downto 0);--读地址
RA_data_rd : in std_logic_vector(63 downto 0);--读数据
--AxiRam Control interface--------------------
RAstart : out std_logic; --Axi读
RAidle : in std_logic;
RAcount : out std_logic_vector(31 downto 0);
RAaddr : out std_logic_vector(31 downto 0)
);
end TREQRESP;
architecture Behavioral of TREQRESP is
signal treq_tready_w : std_logic:='0';
signal regReqHead : std_logic_vector(63 downto 0):=x"0000000000000000";
signal TID : std_logic_vector( 7 downto 0):=x"00";
signal FTYPE : std_logic_vector( 3 downto 0):=x"0";
signal TTYPE : std_logic_vector( 3 downto 0):=x"0";
signal SIZE : std_logic_vector( 7 downto 0):=x"00";
signal ADDR : std_logic_vector(33 downto 0):="00"&x"00000000";
signal DBINFO : std_logic_vector(15 downto 0):=x"0000";
signal TUSER : std_logic_vector(31 downto 0):=x"00000000";
signal regLast : std_logic:='0';
signal cntsNswrWA2axi : std_logic_vector( 3 downto 0):=x"0";
signal cntsNrdRAaxi : std_logic_vector( 3 downto 0):=x"0";
signal cntTrans : std_logic_vector( 7 downto 0):=x"00";
signal cntsNrdRespData : std_logic_vector( 7 downto 0):=x"00"; --回复数据包计数器,回复到了第几个数据包
signal tresp_tvalid_w : std_logic:='0';
type state_type is ( sReset, sIdle,
sWaitHead, sGotHead,
sNswrGetData, sNswrResp, sNswrWA2axi, sNswrWAwaitdone, sNswrFinish,
sNrdRAaxi, sNrdRAwaitdone, sNrdRespHead, sNrdRespHead2, sNrdRespData, sNrdFinish,
sDbWrInfo, sDbResp, sDbFinish,
sError );
---状态解释
--
signal state,next_state : state_type:=sReset;
begin
--output logic-------------------------------------------------------
tresp_logic: process( state, FTYPE, TTYPE, TID, self_id, TUSER, RA_data_rd, cntsNrdRespData, SIZE ) begin
case state is
when sNswrResp =>--???这是什么状态捏NWRITE_R或者SWRITE?
if (FTYPE=x"5" and TTYPE=x"5") then--NWRITE_R
tresp_tvalid_w <= '1'; --应该是对方(即IP,I端)要写,并且是需要回应的写,因此我们需要发一个包回应,包长为1所以直接tlat置高
tresp_tlast <= '1';
else--在此状态但不是NWRITE_R的处理,不回复数据
tresp_tvalid_w <= '0';
tresp_tlast <= '0';
end if;
tresp_tdata <= TID & x"d04000"&x"00000000";--NWRITE_R的回复指定格式
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);--将自己的id和接受到TUSER低16位拼接
when sDbResp =>--收到DB需要回复
tresp_tvalid_w <= '1';
tresp_tlast <= '1';
tresp_tdata <= TID & x"d04000"&x"00000000";
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);--逻辑与上述一致(所以上述的回复也是一个DB )
when sNrdRespHead =>--NREAD RESPOND的包头响应
tresp_tvalid_w <= '1';
tresp_tlast <= '0';--因为还要发送数据包,所以不last
tresp_tdata <= TID & x"d84000"&x"00000000";
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
when sNrdRespData =>--NREAD RESPOND的数据响应
tresp_tvalid_w <= '1';
tresp_tdata <= RA_data_rd;
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
if ( cntsNrdRespData>=(SIZE(7 downto 3)) ) then--数到最后一个就拉高
tresp_tlast <= '1';
else
tresp_tlast <= '0';
end if;
when others =>
tresp_tvalid_w <= '0';
tresp_tlast <= '0';
tresp_tdata <= x"0000000000000000";
tresp_tkeep <= x"ff";
tresp_tuser <= self_id & TUSER(15 downto 0);
end case;
end process;
tresp_tvalid <= tresp_tvalid_w;
--应该相当于assign,应该是这个值还要在其他地方使用,因为VHDL定义的out类型不能在构造体内部使用,除非定义为buffer
--这一点和verilog不同,详见【参考书p30】
--AXI RAM读起始模块
RAstart_logic: process(clk) begin if rising_edge(clk) then
if ( state=sNrdRAaxi and cntsNrdRAaxi<x"3" ) then
RAstart<='1';
else
RAstart<='0';
end if;
end if; end process;
RAcount <= x"00000020";--输出恒定值
RAaddr_logic: process(clk) begin if rising_edge(clk) then
RAaddr <= ADDR(31 downto 0);
end if; end process;
--AXI RAM读地址模块
RA_addr_logic: process( state, tresp_tvalid_w, tresp_tready, cntsNrdRespData ) begin
if ( state=sNrdRespHead or state=sNrdRespHead2 ) then
RA_addr <= x"00";--以上两个state置0
elsif ( tresp_tvalid_w='1' and tresp_tready='1' ) then
RA_addr <= cntsNrdRespData+1;--回送数据计数器和地址之间的映射关系
else
RA_addr <= cntsNrdRespData+1;
end if;
end process;
--AXI RAM写控制模块
WA_ram_logic: process(clk) begin
if rising_edge(clk) then
case state is
when sNswrGetData =>
if ( treq_tvalid='1' and treq_tready_w='1' ) then
WA_wren <= "1";
else
WA_wren <= "0";
end if;
WA_addr <= cntTrans;
WA_data_wr <= treq_tdata;
when others =>
WA_addr <= x"00";
WA_wren <= "0";
WA_data_wr <= x"0000000000000000";
end case;
end if;
end process;
--AXI RAM写控制模块
WA_ctrl_logic: process(clk) begin
if rising_edge(clk) then
case state is
when sNswrWA2axi =>
if ( cntsNswrWA2axi<=x"3") then
WAstart <= '0';
else
WAstart <= '1';
end if;
WAcount <= x"000000"&cntTrans;
WAaddr <= ADDR(31 downto 0);
when sNswrWAwaitdone =>
WAstart <= '0';
WAcount <= x"000000"&cntTrans;
WAaddr <= ADDR(31 downto 0);
when others =>
WAstart <= '0';
WAcount <= x"00000000";
WAaddr <= x"00000000";
end case;
end if;
end process;
--!!!DB的FIFO控制逻辑
db_fifo_logic: process(clk) begin if rising_edge(clk) then
if ( state=sDbWrInfo ) then
db_fifo_wren <= '1';--使能FIFO写
--db_fifo_data <= x"00" & TID & ADDR(31 downto 16) & TUSER;
db_fifo_data <= x"00" & TID & DBINFO & TUSER;--FIFO写数据包装{补充的位宽8,TID位宽8,DBINFO位宽16,TUSER位宽32}=1个包
else
db_fifo_wren <= '0';
db_fifo_data <= x"0000000000000000";
end if;
end if; end process;
--状态转换逻辑
----------------------------------------------------------------------------
FSM_StateChange_logic: process(clk) begin if rising_edge(clk) then
if ( rst='1' or linkup='0' ) then
state <= sReset;
else
case state is
when sReset =>
state <= sIdle;
when sIdle =>
state <= sWaitHead;
when sWaitHead =>
if (treq_tvalid='1' and treq_tready_w='1') then
state <= sGotHead;
else
state <= state;
end if;
when sGotHead =>
if ( regLast='1' ) then
if ( FTYPE=x"2" ) then
state <= sNrdRAaxi;
elsif ( FTYPE=x"a" ) then
state <= sDbWrInfo;
else
state <= sIdle;
end if;
else
if ( FTYPE=x"5" or FTYPE=x"6" ) then
state <= sNswrGetData;
else
state <= sIdle;
end if;
end if;
when sNswrGetData =>
if (treq_tvalid='1' and treq_tready_w='1' and treq_tlast='1') then
state <= sNswrResp;
else
state <= state;
end if;
when sNswrResp =>
if ( tresp_tready='1' ) then
state <= sNswrWA2axi;
else
state <= state;
end if;
when sNswrWA2axi =>
if ( cntsNswrWA2axi>=x"6" ) then
state <= sNswrWAwaitdone;
else
state <= state;
end if;
when sNswrWAwaitdone =>
if ( WAidle='1' ) then
state <= sNswrFinish;
else
state <= state;
end if;
when sNswrFinish =>
state <= sIdle;
when sNrdRAaxi =>
if ( cntsNrdRAaxi>=x"6") then
state <= sNrdRAwaitdone;
else
state <= state;
end if;
when sNrdRAwaitdone =>
if ( RAidle='1' ) then
state <= sNrdRespHead;
else
state <= state;
end if;
when sNrdRespHead =>
if ( tresp_tready='1' ) then
state <= sNrdRespHead2;
else
state <= state;
end if;
when sNrdRespHead2 =>
state <= sNrdRespData;
when sNrdRespData =>
if ( cntsNrdRespData>=(SIZE(7 downto 3)) and tresp_tready='1' and tresp_tvalid_w='1') then
state <= sNrdFinish;
else
state <= state;
end if;
when sNrdFinish =>
state <= sIdle;
when sDbWrInfo =>
state <= sDbResp;
when sDbResp =>
if ( tresp_tready='1' ) then
state <= sDbFinish;
else
state <= state;
end if;
when sDbFinish =>
state <= sIdle;
when others =>
state <= sReset;
end case;
end if;
end if; end process;
-- treq_tready处理模块
--assist logic------------------------------------------------------
treq_tready_w_logic: process(state) begin
case state is
when sWaitHead | sNswrGetData =>
treq_tready_w <= '1';
when others =>
treq_tready_w <= '0';
end case;
end process;
treq_tready <= treq_tready_w;
--regReqHead模块
regReqHead_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sReset or state=sIdle ) then
regReqHead <= x"0000000000000000";
elsif ( state=sWaitHead and treq_tvalid='1' ) then
regReqHead <= treq_tdata;
else
regReqHead <= regReqHead;
end if;
end if; end process;
--解析、地址重映射模块
TID_FTYPE_TTYPE_SIZE_ADDR_TUSER_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sReset or state=sIdle ) then
TID <= x"00";
FTYPE <= x"0";
TTYPE <= x"0";
SIZE <= x"00";
ADDR <= "00"&x"00000000";
DBINFO <= x"0000";
TUSER <= x"00000000";
regLast <= '0';
elsif ( state=sWaitHead and treq_tvalid='1' ) then
TID <= treq_tdata(63 downto 56);
FTYPE <= treq_tdata(55 downto 52);--FTYPE译码
TTYPE <= treq_tdata(51 downto 48);
SIZE <= treq_tdata(43 downto 36);
--ADDR <= treq_tdata(33 downto 0);
ADDR(33 downto 32) <= treq_tdata(33 downto 32);--ADDR重定向
if (treq_tdata(31 downto 16)>=maping1_base and treq_tdata(31 downto 16)<=maping1_high) then
ADDR(31 downto 0) <= treq_tdata(31 downto 0)-(maping1_base&x"0000")+maping1_target;
elsif (treq_tdata(31 downto 16)>=maping2_base and treq_tdata(31 downto 16)<=maping2_high) then
ADDR(31 downto 0) <= treq_tdata(31 downto 0)-(maping2_base&x"0000")+maping2_target;
else
ADDR(31 downto 0) <= treq_tdata(31 downto 0);
end if;
DBINFO <= treq_tdata(31 downto 16);
TUSER <= treq_tuser;
regLast <= treq_tlast;
else
TID <= TID;
FTYPE <= FTYPE;
TTYPE <= TTYPE;
SIZE <= SIZE;
ADDR <= ADDR;
DBINFO <= DBINFO;
TUSER <= TUSER;
regLast <= regLast;
end if;
end if; end process;
--sNrdRaxi延迟模块
cntsNswrWA2axi_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sNswrWA2axi ) then
cntsNswrWA2axi <= cntsNswrWA2axi + 1;
else
cntsNswrWA2axi <= x"0";
end if;
end if; end process;
--sNrdRaxi延迟模块
cntsNrdRAaxi_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sNrdRAaxi ) then
cntsNrdRAaxi <= cntsNrdRAaxi + 1;
else
cntsNrdRAaxi <= x"0";
end if;
end if; end process;
--RAM写地址选择模块
cntTrans_logic: process(clk) begin
if rising_edge(clk) then
if ( state=sNswrGetData ) then
if (treq_tvalid='1' and treq_tready_w='1') then
cntTrans <= cntTrans + 1;
else
cntTrans <= cntTrans;
end if;
elsif ( state=sNswrResp or state=sNswrWA2axi or state=sNswrWAwaitdone or state=sNswrFinish ) then
cntTrans <= cntTrans;
else
cntTrans <= x"00";
end if;
end if;
end process;
--回复数据包计数器模块:回复到了第几个数据包
cntsNrdRespData_logic: process(clk) begin if rising_edge(clk) then
if ( state=sNrdRespData and tresp_tvalid_w='1' and tresp_tready='1') then
cntsNrdRespData <= cntsNrdRespData+1;
elsif ( state=sNrdRAaxi or state=sNrdRAwaitdone or state=sNrdRespHead ) then
cntsNrdRespData <= x"00";
else
cntsNrdRespData <= cntsNrdRespData;
end if;
end if; end process;
end Behavioral;