从这篇就开始正式写自己的驱动代码。这个BLOG写一段将FIFO里面内容根据指令写到指定的PC内存地址的代码,调用的是pcie_ram_to_wr这个代码。
首先看一下pcie_ram_to_wr这个模块的接口:
module pcie_ram_to_wr #(
parameter BUFFER_SIZE_BITS = 17,
parameter BUFFER_BUS_ADDRESS = 32,
parameter MEM_TAG = 1,
parameter BUFFER_BURST_BITS = 5
)(
// UL
input s_ul_clk,
input s_ul_aresetn,
input ul_lm_rvalid,
output reg ul_lm_rready,
input [BUFFER_SIZE_BITS - 1:3] ul_lm_rlocaddr, //14
input [BUFFER_BUS_ADDRESS - 1:3] ul_lm_rbusaddr, //29
input [BUFFER_BURST_BITS - 1:0] ul_lm_rlength, //5
input [MEM_TAG-1:0] ul_lm_rtag, //1
// Bus data move confirmation
output reg ul_lm_tvalid,
input ul_lm_tready,
output reg [MEM_TAG-1:0] ul_lm_ttag, //1
input [1:0] cfg_pcie_attr,
input [15:0] cfg_pcie_reqid,
// AXIs PCIe TX
input m_axis_tx_tready,
output reg [63:0] m_axis_tx_tdata,
output reg [7:0] m_axis_tx_tkeep,
output reg m_axis_tx_tlast,
output reg m_axis_tx_tvalid,
// RAM interface
input [63:0] bram_data_rd,
output reg [BUFFER_SIZE_BITS-1:3]bram_addr, //14
output bram_en,
output reg [1:0] dma_state
);
这里看到逻辑还是很简单的,首先是请求,之后状态机运转允许开始写操作后,就读RAM将数据读走发出。这里按照64位为单位发送,最多发送 2^BUFFER_BURST_BITS -1 个 64 位(是不是64位还要继续确定一下)。
再后续的代码中我们看到:
这也就说明这个BUFFER_BURST_BITS最大可以设置位8.
我要做一个模块控制这个发送器,要有以下这些接口:
1,首先是有要发送的数据接口,我们这里不用RAM接口用FIFO接口。
2,要接收上面模块给的传输命令,上面模块给出要传输的开始地址和长度,这个控制模块将大的数据块分成小的一点点传输给PCIE。
3,要有控制这个pcie_ram_to_wr的接口。
这样分析下来就可以写了
module wr_to_ram_man #(
parameter BUFFER_SIZE_BITS = 17,
parameter BUFFER_BUS_ADDRESS = 32,
parameter MEM_TAG = 1,
parameter BUFFER_BURST_BITS = 7,
parameter BURST_LEN = 32 //liwei
)(
input s_ul_clk,
input s_ul_aresetn,
input ul_lm_done ,
output ul_lm_rvalid,
input ul_lm_rready,
output [BUFFER_SIZE_BITS - 1:3] ul_lm_rlocaddr, //14 no use
output [BUFFER_BUS_ADDRESS - 1:3] ul_lm_rbusaddr, //29
output [BUFFER_BURST_BITS - 1:0] ul_lm_rlength, //5
// output [MEM_TAG-1:0] ul_lm_rtag, //1 no use
// Bus data move confirmation
input ul_lm_tvalid,
output ul_lm_tready,
// input [MEM_TAG-1:0] ul_lm_ttag, //1 no use
input [31:3] up_wr_addr,
input [19:0] up_wr_len,
input wp_wr_start ,
output wr_wr_idle ,
input [15:0] wr_fifo_gap
);
parameter BURST_LEN = 32 ;
reg [31:3] s_up_wr_addr ;
reg [19:0] s_up_wr_len ;
always @ (posedge clk )case (st)
10: if (wp_wr_start) s_up_wr_addr <= up_wr_addr ;
22: s_up_wr_addr <= s_up_wr_addr + BURST_LEN ;
endcase
always @ (posedge clk )case (st)
10: if (wp_wr_start) s_up_wr_len <= up_wr_len ;
22: s_up_wr_len <= s_up_wr_len - BURST_LEN ;
endcase
wire clk = s_ul_clk ;
input rst = ~ s_ul_aresetn;
reg [7:0] st ;
assign ul_lm_tready = 1 ;
always @ (posedge clk)if (rst) st<=0; else case (st)
0 : st<=10;
10 : if (wp_wr_start) st<=10;
20 : if ( wr_fifo_gap >= BURST_LEN ) st<=21; //wait data ready
21 : if (ul_lm_rready) st<=22; // set command
22 : st<=23; // a delay
23 : if ( ul_lm_done ) st<=24;
24 : if ( s_up_wr_len >0 ) st<=20 ;else st<=30;
30 : st<=10;
endcase
assign ul_lm_rlocaddr = 0 ;
assign ul_lm_rbusaddr = s_up_wr_addr ;
assign ul_lm_rlength = BURST_LEN ;
assign ul_lm_rvalid = st == 21 ;
assign wr_wr_idle = (st==10)&&(wp_wr_start==0);
endmodule
这里没有引入FIFO接口,只是输入了FIFO的GAP判断是否有足够数据进行一次传输。
写一步要写一个单独的仿真模块进行测试,之后进行实际的硬件实验。明天完成这个模块的调试