Commit 9c004cf3 authored by Andrey Filippov's avatar Andrey Filippov

more code in ahci_dma.v

parent 0fd78dc6
...@@ -36,7 +36,7 @@ module ahci_dma ( ...@@ -36,7 +36,7 @@ module ahci_dma (
input cmd_abort, // try to abort a command input cmd_abort, // try to abort a command
// Some data from the command table will be used internally, data will be available on the general // Some data from the command table will be used internally, data will be available on the general
// sys_out[31:0] port and should be consumed // sys_out[31:0] port and should be consumed
output ct_busy, // cleared after 0x20 DWORDs are read out output reg ct_busy, // cleared after 0x20 DWORDs are read out
// reading out command table data // reading out command table data
input [ 4:0] ct_addr, // DWORD address input [ 4:0] ct_addr, // DWORD address
input ct_re, // input ct_re, //
...@@ -44,9 +44,10 @@ module ahci_dma ( ...@@ -44,9 +44,10 @@ module ahci_dma (
// After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs, // After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs,
// not forwarding them to the output // not forwarding them to the output
output prd_done, // prd done (regardless of the interrupt) output prd_done, // prd done (regardless of the interrupt) - data transfer of one PRD is finished (any direction)
output prd_irq, // prd interrupt, if enabled output prd_irq, // prd interrupt, if enabled
output cmd_busy, // all command output reg cmd_busy, // all commands
output cmd_done, output cmd_done,
// Data System memory -> HBA interface @ mclk // Data System memory -> HBA interface @ mclk
...@@ -90,7 +91,7 @@ module ahci_dma ( ...@@ -90,7 +91,7 @@ module ahci_dma (
output afi_wrissuecap1en, output afi_wrissuecap1en,
// AXI_HP signals - read channel // AXI_HP signals - read channel
// read address // read address
output reg [31:0] afi_araddr, output [31:0] afi_araddr,
output afi_arvalid, output afi_arvalid,
input afi_arready, // @SuppressThisWarning VEditor unused - used FIF0 level input afi_arready, // @SuppressThisWarning VEditor unused - used FIF0 level
output [ 5:0] afi_arid, output [ 5:0] afi_arid,
...@@ -126,14 +127,16 @@ module ahci_dma ( ...@@ -126,14 +127,16 @@ module ahci_dma (
wire cmd_start_hclk; wire cmd_start_hclk;
wire cmd_abort_hclk; wire cmd_abort_hclk;
reg [31:4] ct_maddr; // granularity matches PRDT entry - 4xDWORD, 2xQWORD reg [31:4] ct_maddr; // granularity matches PRDT entry - 4xDWORD, 2xQWORD
reg ct_done_r; wire ct_done;
reg prd_done_r; reg [31:0] afi_addr; // common for afi_araddr and afi_awaddr
wire axi_set_raddr_ready = !(|afi_racount[2:1]); // What is the size of ra fifo? wire axi_set_raddr_ready = !(|afi_racount[2:1]); // What is the size of ra fifo?
wire axi_set_raddr_w; wire axi_set_raddr_w;
wire axi_set_waddr_w;
wire axi_set_raddr_ct_w; // next will be setting address/len/... to read command table wire axi_set_raddr_ct_w; // next will be setting address/len/... to read command table
reg axi_set_raddr_prd; // next will be setting address/len/... to read PRD entry reg axi_set_raddr_prd; // next will be setting address/len/... to read PRD entry
wire axi_set_raddr_data_w; // next will be setting address/len/... to read DATA wire axi_set_raddr_data_w; // next will be setting address/len/... to read DATA
reg axi_set_raddr_r; // [0] - actual write address to fifo reg axi_set_raddr_r; // [0] - actual write address to fifo
reg axi_set_waddr_r; // [0] - actual write address to fifo
reg was_ct_addr; // AXI RD channel was set to read command table reg was_ct_addr; // AXI RD channel was set to read command table
reg was_prd_addr;// AXI RD channel was set to read prd table reg was_prd_addr;// AXI RD channel was set to read prd table
...@@ -153,40 +156,60 @@ module ahci_dma ( ...@@ -153,40 +156,60 @@ module ahci_dma (
reg [1:0] ct_busy_r; reg [1:0] ct_busy_r;
reg prd_rd_busy; // reading PRD reg prd_rd_busy; // reading PRD
wire prd_done; // data transfer of one PRD is finished (any direction)
reg dev_wr_mclk; reg dev_wr_mclk;
reg dev_wr_hclk; reg dev_wr_hclk;
reg prd_wr; // write PRD data to memory reg prd_wr; // write PRD data to memory
reg prd_rd; // read PRD data from memory reg prd_rd; // read PRD data from memory
wire [3:0] afi_wstb4; wire [3:0] afi_wstb4;
// reg [1:0] afi_rready_ctl_r;
wire done_dev_wr; // finished PRD mem -> device
wire done_dev_rd; // finished PRD device -> mem
wire done_flush; // done flushing last partial dword
wire cmd_done_hclk;
wire ct_done_mclk;
assign afi_arvalid = axi_set_raddr_r[0]; assign afi_arvalid = axi_set_raddr_r;
assign afi_awvalid = axi_set_waddr_r;
assign axi_set_raddr_w = (axi_set_raddr_ct_w || axi_set_raddr_prd || axi_set_raddr_data_w) && axi_set_raddr_ready ; assign axi_set_raddr_w = (axi_set_raddr_ct_w || axi_set_raddr_prd || axi_set_raddr_data_w) && axi_set_raddr_ready ;
assign afi_rready = afi_rd_ctl[0] || data_afi_re; assign afi_rready = afi_rd_ctl[0] || data_afi_re;
assign ct_busy = ct_busy_r[0]; // assign ct_busy = ct_busy_r[0];
assign afi_wstrb = {{2{afi_wstb4[3]}},{2{afi_wstb4[2]}},{2{afi_wstb4[1]}},{2{afi_wstb4[0]}}}; assign afi_wstrb = {{2{afi_wstb4[3]}},{2{afi_wstb4[2]}},{2{afi_wstb4[1]}},{2{afi_wstb4[0]}}};
assign prd_done = done_dev_wr || done_dev_rd;
// assign afi_rready = data_afi_re || ((was_ct_addr || was_prd_addr) && assign prd_irq = data_irq && prd_done;
// ((|afi_rcount[6:SAFE_RD_BITS]) || (afi_rvalid && !afi_rready &&!(|afi_rready_r)))); assign cmd_done_hclk = ((ct_busy_r==2'b10) && (prdtl_mclk == 0)) || done_flush || done_dev_rd;
assign ct_done = (ct_busy_r == 2'b10);
assign afi_awaddr = afi_addr;
assign afi_araddr = afi_addr;
always @ (posedge mclk) begin always @ (posedge mclk) begin
if (ct_re) ct_data <= ct_data_ram[ct_addr]; if (ct_re) ct_data <= ct_data_ram[ct_addr];
if (ctba_ld) ctba_r <= ctba[31:7]; if (ctba_ld) ctba_r <= ctba[31:7];
if (cmd_start) prdtl_mclk <= prdtl; if (cmd_start) prdtl_mclk <= prdtl;
if (cmd_start) dev_wr_mclk <= dev_wr; if (cmd_start) dev_wr_mclk <= dev_wr;
if (mrst) cmd_busy <= 0;
else if (cmd_start) cmd_busy <= 1;
else if (cmd_done) cmd_busy <= 0;
if (mrst) ct_busy <= 0;
else if (cmd_start) ct_busy <= 1;
else if (ct_done_mclk) ct_busy <= 0;
end end
always @ (posedge hclk) begin always @ (posedge hclk) begin
if (cmd_start_hclk) ct_maddr[31:4] <= {ctba_r[31:7],3'b0}; if (cmd_start_hclk) ct_maddr[31:4] <= {ctba_r[31:7],3'b0};
else if (ct_done_r) ct_maddr[31:4] <= ct_maddr[31:4] + 16; else if (ct_done) ct_maddr[31:4] <= ct_maddr[31:4] + 16;
else if (prd_done_r) ct_maddr[31:4] <= ct_maddr[31:4] + 1; else if (wcount_set) ct_maddr[31:4] <= ct_maddr[31:4] + 1;
if (hrst) axi_set_raddr_r <= 0; if (hrst) axi_set_raddr_r <= 0;
else axi_set_raddr_r <= axi_set_raddr_w; else axi_set_raddr_r <= axi_set_raddr_w;
if (hrst) axi_set_waddr_r <= 0;
else axi_set_waddr_r <= axi_set_waddr_w;
if (axi_set_raddr_w) begin if (axi_set_raddr_w) begin
was_ct_addr <= axi_set_raddr_ct_w; was_ct_addr <= axi_set_raddr_ct_w;
...@@ -198,12 +221,15 @@ module ahci_dma ( ...@@ -198,12 +221,15 @@ module ahci_dma (
if (axi_set_raddr_r && was_prd_addr) last_prd <= prds_left == 1; if (axi_set_raddr_r && was_prd_addr) last_prd <= prds_left == 1;
if (axi_set_raddr_r) begin if (axi_set_raddr_w || axi_set_waddr_w) begin
if (was_ct_addr || was_prd_addr) afi_araddr <= {ct_maddr[31:4],4'b0}; // if (was_ct_addr || was_prd_addr) afi_addr <= {ct_maddr[31:4],4'b0};
else afi_araddr <= {data_addr[31:3],3'b0}; if (axi_set_raddr_ct_w || axi_set_raddr_prd) afi_addr <= {ct_maddr[31:4],4'b0};
else afi_addr <= {data_addr[31:3],3'b0};
if (was_ct_addr) afi_arlen <= 4'hf; // 16 QWORDS // if (was_ct_addr) afi_arlen <= 4'hf; // 16 QWORDS
else if (was_prd_addr) afi_arlen <= 4'h1; // 2 QWORDS // else if (was_prd_addr) afi_arlen <= 4'h1; // 2 QWORDS
if (axi_set_raddr_ct_w) afi_arlen <= 4'hf; // 16 QWORDS
else if (axi_set_raddr_prd) afi_arlen <= 4'h1; // 2 QWORDS
else afi_arlen <= data_len; // TBD - all but last are 4'hf else afi_arlen <= data_len; // TBD - all but last are 4'hf
end end
...@@ -212,8 +238,8 @@ module ahci_dma ( ...@@ -212,8 +238,8 @@ module ahci_dma (
if (afi_rd_ctl[0] && was_ct_addr) {ct_data_ram[{int_data_addr,1'b1}],ct_data_ram[{int_data_addr,1'b0}]} <= afi_rdata; // make sure it is synthesized correctly if (afi_rd_ctl[0] && was_ct_addr) {ct_data_ram[{int_data_addr,1'b1}],ct_data_ram[{int_data_addr,1'b0}]} <= afi_rdata; // make sure it is synthesized correctly
if (hrst) ct_busy_r[0] <= 0; if (hrst) ct_busy_r[0] <= 0;
else if (cmd_start_hclk) ct_busy_r[0] <= 1; else if (cmd_start_hclk) ct_busy_r[0] <= 1;
else if (afi_rd_ctl[0] && was_ct_addr && (&int_data_addr)) ct_busy_r[0] <= 0; else if (afi_rd_ctl[0] && was_ct_addr && (&int_data_addr)) ct_busy_r[0] <= 0;
ct_busy_r[1] <= ct_busy_r[0]; // delayed version to detect end of command ct_busy_r[1] <= ct_busy_r[0]; // delayed version to detect end of command
...@@ -225,7 +251,7 @@ module ahci_dma ( ...@@ -225,7 +251,7 @@ module ahci_dma (
// start PRD read // start PRD read
if (hrst) axi_set_raddr_prd <= 0; if (hrst) axi_set_raddr_prd <= 0;
else axi_set_raddr_prd <= ((|prds_left) && ((ct_busy_r==2'b10) || prd_done)); else axi_set_raddr_prd <= ((|prds_left) && (ct_done || prd_done));
// store data address from PRD // store data address from PRD
if (afi_rd_ctl[0] && was_prd_addr && (!int_data_addr[0])) data_addr[31:1] <= afi_rdata[31:1]; if (afi_rd_ctl[0] && was_prd_addr && (!int_data_addr[0])) data_addr[31:1] <= afi_rdata[31:1];
...@@ -248,6 +274,12 @@ module ahci_dma ( ...@@ -248,6 +274,12 @@ module ahci_dma (
end end
// TODO: Push addresses for Data read/data Write (different address FIFO depth), use IDs
// - different for commands (increment for each next command) and data (increment for each PRD) - not really needed, just for debugging
// Generate afi_wlast - each 16-th and the very last QWORD
ahci_dma_rd_fifo #( // memory to device ahci_dma_rd_fifo #( // memory to device
.WCNT_BITS (21), .WCNT_BITS (21),
.ADDRESS_BITS (3) .ADDRESS_BITS (3)
...@@ -264,8 +296,8 @@ module ahci_dma ( ...@@ -264,8 +296,8 @@ module ahci_dma (
.din_av_many (|afi_rcount[7:SAFE_RD_BITS]), // input .din_av_many (|afi_rcount[7:SAFE_RD_BITS]), // input
.last_prd (last_prd), // input .last_prd (last_prd), // input
.din_re (data_afi_re), // output .din_re (data_afi_re), // output
.done (), // output reg .done (done_dev_wr), // output reg
.done_flush (), // output .done_flush (done_flush), // output
.dout (sys_out), // output[31:0] .dout (sys_out), // output[31:0]
.dout_vld (sys_dav), // output .dout_vld (sys_dav), // output
.dout_re (sys_re) // input .dout_re (sys_re) // input
...@@ -289,13 +321,14 @@ module ahci_dma ( ...@@ -289,13 +321,14 @@ module ahci_dma (
.last_prd (last_prd), // input .last_prd (last_prd), // input
.dout_we (afi_wvalid), // output .dout_we (afi_wvalid), // output
.dout_wstb (afi_wstb4), // output[3:0] reg .dout_wstb (afi_wstb4), // output[3:0] reg
.done (), // output reg .done (done_dev_rd), // output reg
.busy (), // output .busy (), // output
.din (sys_in), // input[31:0] .din (sys_in), // input[31:0]
.din_rdy (sys_nfull), // output .din_rdy (sys_nfull), // output
.din_avail (sys_we) // input .din_avail (sys_we) // input
); );
// mclk -> hclk cross-clock synchronization // mclk -> hclk cross-clock synchronization
pulse_cross_clock #( pulse_cross_clock #(
.EXTRA_DLY(0) .EXTRA_DLY(0)
...@@ -317,7 +350,29 @@ module ahci_dma ( ...@@ -317,7 +350,29 @@ module ahci_dma (
.out_pulse (cmd_abort_hclk), // output .out_pulse (cmd_abort_hclk), // output
.busy() // output .busy() // output
); );
// hclk -> mclk;
pulse_cross_clock #(
.EXTRA_DLY(0)
) cmd_done_i (
.rst (hrst), // input
.src_clk (hclk), // input
.dst_clk (mclk), // input
.in_pulse (cmd_done_hclk), // input
.out_pulse (cmd_done), // output
.busy() // output
);
pulse_cross_clock #(
.EXTRA_DLY(0)
) ct_done_mclk_i (
.rst (hrst), // input
.src_clk (hclk), // input
.dst_clk (mclk), // input
.in_pulse (ct_done), // input
.out_pulse (ct_done_mclk), // output
.busy() // output
);
endmodule endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment