Commit 8236e82b authored by Andrey Filippov's avatar Andrey Filippov

removed unused/unmaintained files

parent 78539c1a
......@@ -52,87 +52,87 @@
<link>
<name>vivado_logs/VivadoBitstream.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoBitstream-20160308235749196.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoBitstream-20160311095400893.log</location>
</link>
<link>
<name>vivado_logs/VivadoOpt.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOpt-20160308235749196.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOpt-20160311095400893.log</location>
</link>
<link>
<name>vivado_logs/VivadoOptPhys.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPhys-20160308235749196.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPhys-20160311095400893.log</location>
</link>
<link>
<name>vivado_logs/VivadoOptPower.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPower-20160308235749196.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPower-20160311095400893.log</location>
</link>
<link>
<name>vivado_logs/VivadoPlace.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoPlace-20160308235749196.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoPlace-20160311095400893.log</location>
</link>
<link>
<name>vivado_logs/VivadoRoute.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoRoute-20160308235749196.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoRoute-20160311095400893.log</location>
</link>
<link>
<name>vivado_logs/VivadoSynthesis.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoSynthesis-20160308235632422.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoSynthesis-20160311095237675.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimimgSummaryReportImplemented.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportImplemented-20160308235749196.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportImplemented-20160311095400893.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimimgSummaryReportSynthesis.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportSynthesis-20160308235632422.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportSynthesis-20160311095237675.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimingReportImplemented.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportImplemented-20160308235749196.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportImplemented-20160311095400893.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimingReportSynthesis.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportSynthesis-20160308235632422.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportSynthesis-20160311095237675.log</location>
</link>
<link>
<name>vivado_state/x393_sata-opt-phys.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-phys-20160308235749196.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-phys-20160311095400893.dcp</location>
</link>
<link>
<name>vivado_state/x393_sata-opt-power.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-power-20160308235749196.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-power-20160311095400893.dcp</location>
</link>
<link>
<name>vivado_state/x393_sata-opt.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-20160308235749196.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-20160311095400893.dcp</location>
</link>
<link>
<name>vivado_state/x393_sata-place.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-place-20160308235749196.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-place-20160311095400893.dcp</location>
</link>
<link>
<name>vivado_state/x393_sata-route.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-route-20160308235749196.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-route-20160311095400893.dcp</location>
</link>
<link>
<name>vivado_state/x393_sata-synth.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-synth-20160308235632422.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-synth-20160311095237675.dcp</location>
</link>
</linkedResources>
</projectDescription>
FPGA_project_0_SimulationTopFile=tb/tb_top.v
FPGA_project_1_SimulationTopModule=tb
FPGA_project_2_ImplementationTopFile=dma/top.v
FPGA_project_2_ImplementationTopFile=top.v
FPGA_project_3_ImplementationTopModule=top
FPGA_project_4_part=xc7z030fbg484-1
FPGA_project_5_part=xc7z030fbg484-1
......
/*******************************************************************************
* Module: axi_regs
* Date: 2015-07-11
* Author: Alexey
* Description: slave axi interface buffer
*
* Copyright (c) 2015 Elphel, Inc.
* axi_regs.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* axi_regs.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
//`include "axibram_read.v"
//`include "axibram_write.v"
module axi_regs(
input wire ACLK, // AXI PS Master GP1 Clock , input
input wire ARESETN, // AXI PS Master GP1 Reset, output
// AXI PS Master GP1: Read Address
input wire [31:0] ARADDR, // AXI PS Master GP1 ARADDR[31:0], output
input wire ARVALID, // AXI PS Master GP1 ARVALID, output
output wire ARREADY, // AXI PS Master GP1 ARREADY, input
input wire [11:0] ARID, // AXI PS Master GP1 ARID[11:0], output
input wire [3:0] ARLEN, // AXI PS Master GP1 ARLEN[3:0], output
input wire [1:0] ARSIZE, // AXI PS Master GP1 ARSIZE[1:0], output
input wire [1:0] ARBURST, // AXI PS Master GP1 ARBURST[1:0], output
// AXI PS Master GP1: Read Data
output wire [31:0] RDATA, // AXI PS Master GP1 RDATA[31:0], input
output wire RVALID, // AXI PS Master GP1 RVALID, input
input wire RREADY, // AXI PS Master GP1 RREADY, output
output wire [11:0] RID, // AXI PS Master GP1 RID[11:0], input
output wire RLAST, // AXI PS Master GP1 RLAST, input
output wire [1:0] RRESP, // AXI PS Master GP1 RRESP[1:0], input
// AXI PS Master GP1: Write Address
input wire [31:0] AWADDR, // AXI PS Master GP1 AWADDR[31:0], output
input wire AWVALID, // AXI PS Master GP1 AWVALID, output
output wire AWREADY, // AXI PS Master GP1 AWREADY, input
input wire [11:0] AWID, // AXI PS Master GP1 AWID[11:0], output
input wire [3:0] AWLEN, // AXI PS Master GP1 AWLEN[3:0], outpu:t
input wire [1:0] AWSIZE, // AXI PS Master GP1 AWSIZE[1:0], output
input wire [1:0] AWBURST, // AXI PS Master GP1 AWBURST[1:0], output
// AXI PS Master GP1: Write Data
input wire [31:0] WDATA, // AXI PS Master GP1 WDATA[31:0], output
input wire WVALID, // AXI PS Master GP1 WVALID, output
output wire WREADY, // AXI PS Master GP1 WREADY, input
input wire [11:0] WID, // AXI PS Master GP1 WID[11:0], output
input wire WLAST, // AXI PS Master GP1 WLAST, output
input wire [3:0] WSTRB, // AXI PS Master GP1 WSTRB[3:0], output
// AXI PS Master GP1: Write response
output wire BVALID, // AXI PS Master GP1 BVALID, input
input wire BREADY, // AXI PS Master GP1 BREADY, output
output wire [11:0] BID, // AXI PS Master GP1 BID[11:0], input
output wire [1:0] BRESP, // AXI PS Master GP1 BRESP[1:0], input
// registers iface
input wire [31:0] bram_rdata,
output wire [31:0] bram_waddr,
output wire [31:0] bram_wdata,
output wire [31:0] bram_raddr,
output wire [3:0] bram_wstb,
output wire bram_wen,
output wire bram_ren,
output wire bram_regen
);
/*
* Converntional MAXI interface from x393 project
*/
// Interface's instantiation
axibram_write #(
.ADDRESS_BITS(16)
)
axibram_write(
.aclk (ACLK),
.arst (ARESETN),
.awaddr (AWADDR),
.awvalid (AWVALID),
.awready (AWREADY),
.awid (AWID),
.awlen (AWLEN),
.awsize (AWSIZE),
.awburst (AWBURST),
.wdata (WDATA),
.wvalid (WVALID),
.wready (WREADY),
.wid (WID),
.wlast (WLAST),
.wstb (WSTRB),
.bvalid (BVALID),
.bready (BREADY),
.bid (BID),
.bresp (BRESP),
.pre_awaddr (),
.start_burst (),
.dev_ready (1'b1),
.bram_wclk (),
.bram_waddr (bram_waddr[15:0]),
.pre_bram_wen (),
.bram_wen (bram_wen),
.bram_wstb (bram_wstb),
.bram_wdata (bram_wdata)
);
axibram_read #(
.ADDRESS_BITS(16)
)
axibram_read(
.aclk (ACLK),
.arst (ARESETN),
.araddr (ARADDR),
.arvalid (ARVALID),
.arready (ARREADY),
.arid (ARID),
.arlen (ARLEN),
.arsize (ARSIZE),
.arburst (ARBURST),
.rdata (RDATA),
.rvalid (RVALID),
.rready (RREADY),
.rid (RID),
.rlast (RLAST),
.rresp (RRESP),
.pre_araddr (),
.start_burst (),
.dev_ready (1'b1),
.bram_rclk (),
.bram_raddr (bram_raddr[15:0]),
.bram_ren (bram_ren),
.bram_regen (bram_regen),
.bram_rdata (bram_rdata)
);
endmodule
/*******************************************************************************
* Module: dma_adapter
* Date: 2015-07-11
* Author: Alexey
* Description: temporary interconnect to membridge testing purposes only
*
* Copyright (c) 2015 Elphel, Inc.
* dma_adapter.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dma_adapter.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
/*
* The module is temporary
* It could make transactions from DMA data buffer to membridge and vice versa.
* Processes 1 transaction of 16 x 64bit-words at a time.
* Waits until 1 read or 1 write is completely done.
* After that it deasserts busy and is ready to process a new transaction.
*
* The whole purpose of a module as a system block is to be a buffer between
* a big dma data storage and axi interface. So it shall recieve data and control
* for 1 burst and pass it to axi.
*/
module dma_adapter(
input wire clk,
input wire rst,
// cmd iface
input wire cmd_type, // 1 = wr, 0 = rd
input wire cmd_val, // issue a cmd
input wire [31:7] cmd_addr, // [2:0] - 64-bit (8-bytes) word offset, [6:3] - 16-words transfer offset
output wire cmd_busy, // no-pipelined cmd execution, 1 cmd at a time
// data iface
input wire [63:0] wr_data_in,
input wire wr_val_in,
output wire wr_ack_out,
output wire [63:0] rd_data_out,
output wire rd_val_out,
input wire rd_ack_in,
// membridge iface
output wire [7:0] cmd_ad,
output wire cmd_stb,
input wire [7:0] status_ad,
input wire status_rq,
output wire status_start,
input wire frame_start_chn,
input wire next_page_chn,
output wire cmd_wrmem,
output wire page_ready_chn,
output wire frame_done_chn,
output wire [15:0] line_unfinished_chn1,
input wire suspend_chn1,
output wire xfer_reset_page_rd,
output wire buf_wpage_nxt,
output wire buf_wr,
output wire [63:0] buf_wdata,
output wire xfer_reset_page_wr,
output wire buf_rpage_nxt,
output wire buf_rd,
input wire [63:0] buf_rdata,
// additinal wire to indicate if membridge recieved a packet
input wire rdata_done // = membridge.is_last_in_page & membridge.afi_rready;
);
reg [2:0] membr_state;
// cmd handling
// if not busy and got cmd with val => cmd recieved, assert busy, start a respective algorithm
wire wr_start;
wire rd_start;
wire dma_start;
reg wr_done;
reg rd_done;
reg cmd_type_r;
reg [31:7] cmd_addr_r;
reg cmd_busy_r;
wire set_busy;
wire clr_busy;
assign set_busy = ~cmd_busy_r & cmd_val;
assign clr_busy = cmd_busy_r & (wr_done | rd_done);
assign cmd_busy = cmd_busy_r;
assign wr_start = set_busy & cmd_type;
assign rd_start = set_busy & ~cmd_type;
always @ (posedge clk)
begin
cmd_type_r <= rst ? 1'b0 : set_busy ? cmd_type : cmd_type_r;
cmd_addr_r <= rst ? 25'b0 : set_busy ? cmd_addr[31:7] : cmd_addr_r[31:7];
cmd_busy_r <= (cmd_busy_r | set_busy) & ~rst & ~clr_busy;
end
/*
* Read/write data state machine
* For better readability the state machine is splitted to two pieces:
* the first one is responsible only for the CMD WRITE case handling,
* the second one, respectively, for CMD READ
*
* Simultaniously with each fsm starts a membridge fsm, which, if being 1st time launched,
* sets up membridge's registers, or, if have been launched before, just programs read/write
* address.
*
* Current implementation is extremely slow, but simple and reliable
* After all other parts are implemented and this place occurs to be a bottleneck
* then replace it (and may be membridge too) with something more ... pipelined
*/
// check if memberidge was already set up
reg membr_is_set;
always @ (posedge clk)
membr_is_set <= (membr_is_set | dma_start) & ~rst;
// common state register
reg [3:0] rdwr_state;
// Get data from buffer
localparam IDLE = 0;
//localparam READ_IDLE = 0;
localparam READ_WAIT_ADDR = 3;
localparam READ_DATA = 4;
wire rd_reset_page;
reg rd_next_page;
wire [63:0] rd_data;
reg [6:0] rd_data_count;
reg rd_en;
wire rd_stop;
wire [6:0] rd_cnt_to_pull;
assign rd_cnt_to_pull = 7'hf;
assign rd_stop = rd_ack_in & rd_data_count == rd_cnt_to_pull;
assign rd_reset_page = 1'b0;
assign rd_data = buf_rdata;
assign rd_val_out = rd_en;
assign rd_data_out = rd_data;
/*always @ (posedge clk)
if (rst)
begin
rdwr_state <= READ_IDLE;
rd_done <= 1'b0;
rd_data_count <= 7'h0;
rd_next_page <= 1'b0;
rd_en <= 1'b0;
end
else
case (rdwr_state)
READ_IDLE:
begin
rdwr_state <= rd_start ? READ_WAIT_ADDR : READ_IDLE;
rd_done <= 1'b0;
rd_data_count <= 7'h0;
rd_next_page <= 1'b0;
rd_en <= 1'b0;
end
READ_WAIT_ADDR: // wait until address information is sent to the bus and input buffer got data
begin
rdwr_state <= membr_state == READ_IDLE & rdata_done ? READ_DATA : READ_WAIT_ADDR;
rd_done <= 1'b0;
rd_data_count <= 7'h0;
rd_next_page <= 1'b0;
rd_en <= 1'b0;
end
READ_DATA:
begin
rdwr_state <= rd_stop ? READ_IDLE : READ_DATA;
rd_done <= rd_stop ? 1'b1 : 1'b0;
rd_data_count <= rd_ack_in ? rd_data_count + 1'b1 : rd_data_count;
rd_next_page <= rd_stop ? 1'b1 : 1'b0;
rd_en <= rd_ack_in ? 1'b1 : 1'b0;
end
default: // write is processing
begin
rdwr_state <= READ_IDLE;
rd_done <= 1'b0;
rd_data_count <= 7'h0;
rd_next_page <= 1'b0;
rd_en <= 1'b0;
end
endcase
*/
// Put data into buffer
//localparam WRITE_IDLE = 0;
localparam WRITE_DATA = 1;
localparam WRITE_WAIT_ADDR = 2;
reg wr_en;
reg wr_reset_page;
reg wr_next_page;
reg [63:0] wr_data;
reg [6:0] wr_data_count;
reg wr_page_ready;
reg wr_val;
wire [6:0] wr_cnt_to_push;
wire wr_stop;
assign wr_cnt_to_push = 7'hf;
assign wr_stop = wr_val_in & wr_data_count == wr_cnt_to_push;
assign wr_ack_out = wr_val_in & rdwr_state == WRITE_DATA;
//assign wr_data_in = wr_data;
// assuming for now we write only pre-defined 16 64-bit words
always @ (posedge clk)
if (rst)
begin
rdwr_state <= IDLE;
rd_done <= 1'b0;
rd_data_count <= 7'h0;
rd_next_page <= 1'b0;
rd_en <= 1'b0;
wr_done <= 1'b0;
wr_data_count <= 7'd0;
wr_val <= 1'b0;
wr_data <= 64'h0;
wr_next_page <= 1'b0;
wr_reset_page <= 1'b0;
wr_en <= 1'b0;
wr_page_ready <= 1'b0;
end
else
case (rdwr_state)
IDLE:
begin
rdwr_state <= rd_start ? READ_WAIT_ADDR : wr_start ? WRITE_DATA : IDLE;
rd_done <= 1'b0;
rd_data_count <= 7'h0;
rd_next_page <= 1'b0;
rd_en <= 1'b0;
wr_data_count <= 7'd0;
wr_done <= 1'b0;
wr_data <= 64'h0;
wr_next_page <= 1'b0;
wr_reset_page <= wr_start ? 1'b1 : 1'b0;
wr_en <= 1'b0;
wr_page_ready <= 1'b0;
end
WRITE_DATA:
begin
wr_done <= wr_stop & membr_state == IDLE ? 1'b1 : 1'b0;
wr_data_count <= wr_val_in ? wr_data_count + 1'b1 : wr_data_count;
wr_data <= wr_data_in;
wr_next_page <= wr_stop ? 1'b1 : 1'b0;
wr_reset_page <= 1'b0;
wr_en <= wr_val_in;
wr_page_ready <= wr_stop ? 1'b1 : 1'b0;
rdwr_state <= wr_stop & membr_state == IDLE ? IDLE :
wr_stop ? WRITE_WAIT_ADDR : WRITE_DATA;
rd_done <= 1'b0;
rd_data_count <= 7'h0;
rd_next_page <= 1'b0;
rd_en <= 1'b0;
end
WRITE_WAIT_ADDR: // in case all data is written into a buffer, but address is still being issued on axi bus
begin
wr_done <= membr_state == IDLE ? 1'b1 : 1'b0;
wr_data_count <= 7'd0;
wr_data <= 64'h0;
wr_next_page <= 1'b0;
wr_reset_page <= 1'b0;
wr_en <= 1'b0;
wr_page_ready <= 1'b0;
rdwr_state <= membr_state == IDLE ? IDLE : WRITE_WAIT_ADDR;
rd_done <= 1'b0;
rd_data_count <= 7'h0;
rd_next_page <= 1'b0;
rd_en <= 1'b0;
end
READ_WAIT_ADDR: // wait until address information is sent to the bus and input buffer got data
begin
rdwr_state <= membr_state == IDLE & rdata_done ? READ_DATA : READ_WAIT_ADDR;
rd_done <= 1'b0;
rd_data_count <= 7'h0;
rd_next_page <= 1'b0;
rd_en <= 1'b0;
wr_done <= 1'b0;
wr_data_count <= 7'd0;
wr_data <= 64'h0;
wr_next_page <= 1'b0;
wr_reset_page <= 1'b0;
wr_en <= 1'b0;
wr_page_ready <= 1'b0;
end
READ_DATA:
begin
rdwr_state <= rd_stop ? IDLE : READ_DATA;
rd_done <= rd_stop ? 1'b1 : 1'b0;
rd_data_count <= rd_ack_in ? rd_data_count + 1'b1 : rd_data_count;
rd_next_page <= rd_stop ? 1'b1 : 1'b0;
rd_en <= rd_ack_in ? 1'b1 : 1'b0;
wr_done <= 1'b0;
wr_data_count <= 7'd0;
wr_data <= 64'h0;
wr_next_page <= 1'b0;
wr_reset_page <= 1'b0;
wr_en <= 1'b0;
wr_page_ready <= 1'b0;
end
default: // read is executed
begin
wr_done <= 1'b0;
wr_data_count <= 7'd0;
wr_data <= 64'h0;
wr_next_page <= 1'b0;
wr_reset_page <= 1'b0;
wr_en <= 1'b0;
wr_page_ready <= 1'b0;
rdwr_state <= IDLE;
rd_done <= 1'b0;
rd_data_count <= 7'h0;
rd_next_page <= 1'b0;
rd_en <= 1'b0;
end
endcase
// membridge interface assigments
assign status_start = 1'b0; // no need until status is used
assign cmd_wrmem = ~cmd_type_r;
assign xfer_reset_page_wr = rd_reset_page;
assign buf_rpage_nxt = rd_next_page;
assign buf_rd = rd_en;
assign buf_wdata = wr_data;
assign buf_wr = wr_en;
assign buf_wpage_nxt = wr_next_page;
assign xfer_reset_page_rd = wr_reset_page;
assign page_ready_chn = cmd_wrmem ? 1'b0 : wr_page_ready;
assign frame_done_chn = 1'b1;
/*
* Transfer address and membridge set-ups state machine
*/
localparam MEMBR_IDLE = 0;
localparam MEMBR_MODE = 1;
localparam MEMBR_WIDTH = 2;
localparam MEMBR_LEN = 3;
localparam MEMBR_START = 4;
localparam MEMBR_SIZE = 5;
localparam MEMBR_LOADDR = 6;
localparam MEMBR_CTRL = 7;
reg [31:0] membr_data;
reg [15:0] membr_addr;
reg membr_start;
reg membr_done;
reg membr_setup; // indicates the first tick of the state
wire membr_inprocess;
assign dma_start = wr_start | rd_start;
always @ (posedge clk)
if (rst)
begin
membr_data <= 32'h0;
membr_addr <= 16'h0;
membr_start <= 1'b0;
membr_setup <= 1'b0;
membr_done <= 1'b0;
membr_state <= MEMBR_IDLE;
end
else
case (membr_state)
MEMBR_IDLE:
begin
membr_data <= 32'h0;
membr_addr <= 16'h200;
membr_start <= dma_start ? 1'b1 : 1'b0;
membr_setup <= dma_start ? 1'b1 : 1'b0;
membr_done <= 1'b0;
membr_state <= dma_start & membr_is_set ? MEMBR_LOADDR :
dma_start ? MEMBR_MODE : MEMBR_IDLE;
end
MEMBR_MODE:
begin
membr_data <= 32'h3;
membr_addr <= 16'h207;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_done <= 1'b0;
membr_state <= membr_inprocess | membr_setup ? MEMBR_MODE : MEMBR_WIDTH;
end
MEMBR_WIDTH:
begin
membr_data <= 32'h10;
membr_addr <= 16'h206;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_done <= 1'b0;
membr_state <= membr_inprocess | membr_setup ? MEMBR_WIDTH : MEMBR_LEN;
end
MEMBR_LEN:
begin
membr_data <= 32'h10;
membr_addr <= 16'h205;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_done <= 1'b0;
membr_state <= membr_inprocess | membr_setup ? MEMBR_LEN : MEMBR_START;
end
MEMBR_START:
begin
membr_data <= 32'h0;
membr_addr <= 16'h204;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_done <= 1'b0;
membr_state <= membr_inprocess | membr_setup ? MEMBR_START : MEMBR_SIZE;
end
MEMBR_SIZE:
begin
membr_data <= 32'h10;
membr_addr <= 16'h203;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_done <= 1'b0;
membr_state <= membr_inprocess | membr_setup ? MEMBR_SIZE : MEMBR_LOADDR;
end
MEMBR_LOADDR:
begin
membr_data <= {7'h0, cmd_addr_r[31:7]};
membr_addr <= 16'h202;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_done <= 1'b0;
membr_state <= membr_inprocess | membr_setup ? MEMBR_LOADDR : MEMBR_CTRL;
end
MEMBR_CTRL:
begin
membr_data <= {28'h0000000, 4'b0011};
membr_addr <= 16'h200;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= 1'b0;
membr_done <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_state <= membr_inprocess | membr_setup ? MEMBR_CTRL : MEMBR_IDLE;
end
default:
begin
membr_data <= 32'h0;
membr_addr <= 16'h0;
membr_start <= 1'b0;
membr_setup <= 1'b0;
membr_done <= 1'b0;
membr_state <= MEMBR_IDLE;
end
endcase
// write to memridge registers fsm
localparam STATE_IDLE = 3'h0;
localparam STATE_CMD_0 = 3'h1;
localparam STATE_CMD_1 = 3'h2;
localparam STATE_DATA_0 = 3'h3;
localparam STATE_DATA_1 = 3'h4;
localparam STATE_DATA_2 = 3'h5;
localparam STATE_DATA_3 = 3'h6;
reg [2:0] state;
reg [7:0] out_ad;
reg out_stb;
assign membr_inprocess = state != STATE_IDLE;
assign cmd_ad = out_ad;
assign cmd_stb = out_stb;
always @ (posedge clk)
if (rst)
begin
state <= STATE_IDLE;
out_ad <= 8'h0;
out_stb <= 1'b0;
end
else
case (state)
STATE_IDLE:
begin
out_ad <= 8'h0;
out_stb <= 1'b0;
state <= membr_setup ? STATE_CMD_0 : STATE_IDLE;
end
STATE_CMD_0:
begin
out_ad <= membr_addr[7:0];
out_stb <= 1'b1;
state <= STATE_CMD_1;
end
STATE_CMD_1:
begin
out_ad <= membr_addr[15:8];
out_stb <= 1'b0;
state <= STATE_DATA_0;
end
STATE_DATA_0:
begin
out_ad <= membr_data[7:0];
out_stb <= 1'b0;
state <= STATE_DATA_1;
end
STATE_DATA_1:
begin
out_ad <= membr_data[15:8];
out_stb <= 1'b0;
state <= STATE_DATA_2;
end
STATE_DATA_2:
begin
out_ad <= membr_data[23:16];
out_stb <= 1'b0;
state <= STATE_DATA_3;
end
STATE_DATA_3:
begin
out_ad <= membr_data[31:24];
out_stb <= 1'b0;
state <= STATE_IDLE;
end
default:
begin
out_ad <= 8'hff;
out_stb <= 1'b0;
state <= STATE_IDLE;
end
endcase
endmodule
/*******************************************************************************
* Module: dma_control
* Date: 2015-07-11
* Author: Alexey
* Description: temporary dma request control logic
*
* Copyright (c) 2015 Elphel, Inc.
* dma_control.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dma_control.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
/*
* Later on most of address evaluation logic could be divided into 2 parts, which
* could be presented as 2 instances of 1 parameterized module
* + split data and address parts. Didnt do that because not sure if
* virtual channels would be implemented in the future
*/
module dma_control(
input wire sclk, // sata clock
input wire hclk, // axi-hp clock
input wire rst,
// registers iface
input wire [31:7] mem_address,
input wire [31:0] lba,
input wire [31:0] sector_cnt,
input wire dma_type,
input wire dma_start,
output wire dma_done,
// adapter command iface
input wire adp_busy,
output wire [31:7] adp_addr,
output wire adp_type,
output wire adp_val,
// sata host command iface
input wire host_ready_for_cmd,
output wire host_new_cmd,
output wire [1:0] host_cmd_type,
output wire [31:0] host_sector_count,
output wire [31:0] host_sector_addr,
// adapter data iface
// to main memory
output wire [63:0] to_data,
output wire to_val,
input wire to_ack,
// from main memory
input wire [63:0] from_data,
input wire from_val,
output wire from_ack,
// sata host iface
// data from sata host
input wire [31:0] in_data,
output wire in_val,
input wire in_busy,
// data to sata host
output wire [31:0] out_data,
output wire out_val,
input wire out_busy
);
//////////////////////////////////////////////////////////////////////////////////////
//// ADDRESS
//////////////////////////////////////////////////////////////////////////////////////
wire dma_done_adp;
wire dma_done_host;
assign dma_done = dma_done_host & dma_done_adp;
reg adp_busy_sclk;
/*
* Commands to sata host fsm
*/
// for now only 2 states: idle and send a pulse
reg host_issued;
wire host_issued_set;
wire host_issued_clr;
assign dma_done_host = host_issued;
assign host_issued_set = ~adp_busy_sclk & host_ready_for_cmd & dma_start;
assign host_issued_clr = dma_done;
always @ (posedge sclk)
host_issued <= (host_issued | host_issued_set) & ~host_issued_clr & ~rst;
// drive iface signals
assign host_new_cmd = host_issued_set;
assign host_cmd_type = {1'b0, dma_type};
assign host_sector_count = sector_cnt;
assign host_sector_addr = lba;
/*
* Commands to adapter fsm
*/
reg [33:0] quarter_sector_cnt;
wire last_data; // last 128 bytes of data are transmitted now
wire adp_val_sclk;
reg [31:7] current_addr;
reg current_type;
// fsm itself
wire state_idle;
reg state_wait_busy;
reg state_wait_done;
wire set_wait_busy;
wire set_wait_done;
wire clr_wait_busy;
wire clr_wait_done;
assign set_wait_busy = state_idle & host_issued_set // same start pulse for both fsms
| state_wait_done & clr_wait_done & ~last_data; // still have some data to transmit within a current dma request
assign set_wait_done = state_wait_busy & clr_wait_busy;
assign clr_wait_busy = adp_busy_sclk;
assign clr_wait_done = ~adp_busy_sclk;
assign state_idle = ~state_wait_busy & ~state_wait_done;
always @ (posedge sclk)
begin
state_wait_busy <= (state_wait_busy | set_wait_busy) & ~clr_wait_busy & ~rst;
state_wait_done <= (state_wait_done | set_wait_done) & ~clr_wait_done & ~rst;
end
assign adp_val_sclk = set_wait_busy;
// conrol signals resync
reg adp_val_r;
reg adp_val_rr;
always @ (posedge hclk)
begin
adp_val_r <= adp_val_sclk;
adp_val_rr <= adp_val_r;
end
assign adp_addr = current_addr[31:7];
assign adp_type = current_type;
assign adp_val = adp_val_rr;
// Maintaining correct adp_busy level @ sclk
// assuming busy won't toggle rapidly, can afford not implementing handshakes
wire adp_busy_sclk_set;
wire adp_busy_sclk_clr;
wire adp_busy_set;
wire adp_busy_clr;
reg adp_busy_r;
assign adp_busy_set = adp_busy & ~adp_busy_r;
assign adp_busy_clr = ~adp_busy & adp_busy_r;
always @ (posedge sclk)
adp_busy_sclk <= (adp_busy_sclk | adp_busy_sclk_set) & ~rst & ~adp_busy_sclk_clr;
always @ (posedge hclk)
adp_busy_r <= adp_busy;
pulse_cross_clock adp_busy_set_pulse(
.rst (rst),
.src_clk (hclk),
.dst_clk (sclk),
.in_pulse (adp_busy_set),
.out_pulse (adp_busy_sclk_set),
.busy ()
);
pulse_cross_clock adp_busy_clr_pulse(
.rst (rst),
.src_clk (hclk),
.dst_clk (sclk),
.in_pulse (adp_busy_clr),
.out_pulse (adp_busy_sclk_clr),
.busy ()
);
// synchronize with host fsm
reg adp_done;
wire adp_done_clr;
wire adp_done_set;
assign dma_done_adp = adp_done;
assign adp_done_set = state_wait_done & clr_wait_done & ~set_wait_busy; // = state_wait_done & set_idle;
assign adp_done_clr = dma_done;
always @ (posedge sclk)
adp_done <= (adp_done | adp_done_set) & ~adp_done_clr & ~rst;
// calculate sent sector count
// 1 sector = 512 bytes for now => 1 quarter_sector = 128 bytes
always @ (posedge sclk)
quarter_sector_cnt <= ~set_wait_busy ? quarter_sector_cnt :
state_idle ? 34'h0 : // new dma request
quarter_sector_cnt + 1'b1; // same dma request, next 128 bytes
// flags if we're currently sending the last data piece of dma transaction
assign last_data = (sector_cnt == quarter_sector_cnt[33:2] + 1'b1) & (&quarter_sector_cnt[1:0]);
// calculate outgoing address
// increment every transaction to adapter
always @ (posedge sclk)
current_addr <= ~set_wait_busy ? current_addr[31:7] :
state_idle ? mem_address[31:7] : // new dma request
current_addr[31:7] + 1'b1; // same dma request, next 128 bytes
always @ (posedge sclk)
current_type <= ~set_wait_busy ? current_type :
state_idle ? dma_type : // new dma request
current_type; // same dma request, next 128 bytes
//////////////////////////////////////////////////////////////////////////////////////
//// DATA
//////////////////////////////////////////////////////////////////////////////////////
/*
* from main memory resyncronisation circuit
*/
reg [9:0] from_rd_addr;
reg [8:0] from_wr_addr;
// incremened addresses
wire [8:0] from_wr_next_addr;
wire [9:0] from_rd_next_addr;
// gray coded addresses
reg [9:0] from_rd_addr_gr;
reg [8:0] from_wr_addr_gr;
// anti-metastability shift registers for gray-coded addresses
reg [9:0] from_rd_addr_gr_r;
reg [8:0] from_wr_addr_gr_r;
reg [9:0] from_rd_addr_gr_rr;
reg [8:0] from_wr_addr_gr_rr;
// resynced to opposite clks addresses
wire [9:0] from_rd_addr_r;
wire [8:0] from_wr_addr_r;
// fifo states
wire from_full; // MAY BE full. ~full -> MUST NOT be full
wire from_empty; // MAY BE empty. ~empty -> MUST NOT be empty
wire from_re;
wire from_we;
assign from_wr_next_addr = from_wr_addr + 1'b1;
assign from_rd_next_addr = from_rd_addr + 1'b1;
// hclk domain counters
always @ (posedge hclk)
begin
from_wr_addr <= rst ? 9'h0 : from_we ? from_wr_next_addr : from_wr_addr;
from_wr_addr_gr <= rst ? 9'h0 : from_we ? from_wr_next_addr ^ {1'b0, from_wr_next_addr[8:1]} : from_wr_addr_gr;
end
// sclk domain counters
always @ (posedge sclk)
begin
from_rd_addr <= rst ? 10'h0 : from_re ? from_rd_next_addr : from_rd_addr;
from_rd_addr_gr <= rst ? 10'h0 : from_re ? from_rd_next_addr ^ {1'b0, from_rd_next_addr[9:1]} : from_rd_addr_gr;
end
// write address -> sclk (rd) domain to compare
always @ (posedge sclk)
begin
from_wr_addr_gr_r <= rst ? 9'h0 : from_wr_addr_gr;
from_wr_addr_gr_rr <= rst ? 9'h0 : from_wr_addr_gr_r;
end
// read address -> hclk (wr) domain to compare
always @ (posedge hclk)
begin
from_rd_addr_gr_r <= rst ? 10'h0 : from_rd_addr_gr;
from_rd_addr_gr_rr <= rst ? 10'h0 : from_rd_addr_gr_r;
end
// translate resynced write address into ordinary (non-gray) address
genvar ii;
generate
for (ii = 0; ii < 9; ii = ii + 1)
begin: from_wr_antigray
assign from_wr_addr_r[ii] = ^from_wr_addr_gr_rr[8:ii];
end
endgenerate
// translate resynced read address into ordinary (non-gray) address
generate
for (ii = 0; ii < 10; ii = ii + 1)
begin: from_rd_antigray
assign from_rd_addr_r[ii] = ^from_rd_addr_gr_rr[9:ii];
end
endgenerate
// so we've got the following:
// hclk domain: from_wr_addr - current write address
// from_rd_addr_r - read address some hclk ticks ago
// => we can say if the fifo have the possibility to be full
// since actual from_rd_addr could only be incremented
//
// sclk domain: from_rd_addr - current read address
// from_wr_addr_r - write address some sclk ticks ago
// => we can say if the fifo have the possibility to be empty
// since actual from_wr_addr could only be incremented
assign from_full = {from_wr_addr, 1'b0} == from_rd_addr_r + 1'b1;
assign from_empty = {from_wr_addr_r, 1'b0} == from_rd_addr; // overflows must never be achieved
// calculate bus responses in order to fifo status:
assign from_ack = from_val & ~from_full;
assign out_val = ~out_busy & ~from_empty;
assign from_re = out_val;
assign from_we = from_ack;
// data buffer, recieves 64-bit data from main memory, directs it to sata host
ram_512x64w_1kx32r #(
.REGISTERS (0)
)
dma_data_from_mem (
.rclk (sclk),
.raddr (from_rd_addr),
.ren (from_re),
.regen (1'b0),
.data_out (out_data),
.wclk (hclk),
.waddr (from_wr_addr),
.we (from_we),
.web (8'hff),
.data_in (from_data)
);
/////////////////////////////////////////////////////////////////////////////////
/*
* to main memory resyncronisation circuit
*/
reg [8:0] to_rd_addr;
reg [9:0] to_wr_addr;
// incremened addresses
wire [9:0] to_wr_next_addr;
wire [8:0] to_rd_next_addr;
// gray coded addresses
reg [8:0] to_rd_addr_gr;
reg [9:0] to_wr_addr_gr;
// anti-metastability shift registers for gray-coded addresses
reg [8:0] to_rd_addr_gr_r;
reg [9:0] to_wr_addr_gr_r;
reg [8:0] to_rd_addr_gr_rr;
reg [9:0] to_wr_addr_gr_rr;
// resynced to opposite clks addresses
wire [8:0] to_rd_addr_r;
wire [9:0] to_wr_addr_r;
// fifo states
wire to_full; // MAY BE full. ~full -> MUST NOT be full
wire to_empty; // MAY BE empty. ~empty -> MUST NOT be empty
wire to_re;
wire to_we;
assign to_wr_next_addr = to_wr_addr + 1'b1;
assign to_rd_next_addr = to_rd_addr + 1'b1;
// sclk domain counters
always @ (posedge sclk)
begin
to_wr_addr <= rst ? 10'h0 : to_we ? to_wr_next_addr : to_wr_addr;
to_wr_addr_gr <= rst ? 10'h0 : to_we ? to_wr_next_addr ^ {1'b0, to_wr_next_addr[9:1]} : to_wr_addr_gr;
end
// hclk domain counters
always @ (posedge hclk)
begin
to_rd_addr <= rst ? 9'h0 : to_re ? to_rd_next_addr : to_rd_addr;
to_rd_addr_gr <= rst ? 9'h0 : to_re ? to_rd_next_addr ^ {1'b0, to_rd_next_addr[8:1]} : to_rd_addr_gr;
end
// write address -> hclk (rd) domain to compare
always @ (posedge hclk)
begin
to_wr_addr_gr_r <= rst ? 10'h0 : to_wr_addr_gr;
to_wr_addr_gr_rr <= rst ? 10'h0 : to_wr_addr_gr_r;
end
// read address -> sclk (wr) domain to compare
always @ (posedge sclk)
begin
to_rd_addr_gr_r <= rst ? 9'h0 : to_rd_addr_gr;
to_rd_addr_gr_rr <= rst ? 9'h0 : to_rd_addr_gr_r;
end
// translate resynced write address into ordinary (non-gray) address
generate
for (ii = 0; ii < 10; ii = ii + 1)
begin: to_wr_antigray
assign to_wr_addr_r[ii] = ^to_wr_addr_gr_rr[9:ii];
end
endgenerate
// translate resynced read address into ordinary (non-gray) address
generate
for (ii = 0; ii < 9; ii = ii + 1)
begin: to_rd_antigray
assign to_rd_addr_r[ii] = ^to_rd_addr_gr_rr[8:ii];
end
endgenerate
// so we've got the following:
// sclk domain: to_wr_addr - current write address
// to_rd_addr_r - read address some sclk ticks ago
// => we can say if the fifo have the possibility to be full
// since actual to_rd_addr could only be incremented
//
// hclk domain: to_rd_addr - current read address
// to_wr_addr_r - write address some hclk ticks ago
// => we can say if the fifo have the possibility to be empty
// since actual to_wr_addr could only be incremented
assign to_full = to_wr_addr == {to_rd_addr_r, 1'b0} + 1'b1;
assign to_empty = to_wr_addr_r == {to_rd_addr, 1'b0}; // overflows must never be achieved
// calculate bus responses in order to fifo status:
assign to_val = ~to_empty;
assign in_val = ~in_busy & ~to_full;
assign to_re = to_ack;
assign to_we = in_val;
// data buffer, recieves 32-bit data from sata host, directs it to the main memory
ram_1kx32w_512x64r #(
.REGISTERS (0)
)
dma_data_to_mem (
.rclk (hclk),
.raddr (to_rd_addr),
.ren (to_re),
.regen (1'b0),
.data_out (to_data),
.wclk (sclk),
.waddr (to_wr_addr),
.we (to_we),
.web (4'hf),
.data_in (in_data)
);
endmodule
/*******************************************************************************
* Module: dma_regs
* Date: 2015-07-11
* Author: Alexey
* Description: temporary registers, connected to axi bus
*
* Copyright (c) 2015 Elphel, Inc.
* dma_regs.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dma_regs.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
module dma_regs(
input wire rst,
input wire ACLK,
input wire sclk,
// registers iface
output wire [31:7] mem_address,
output wire [31:0] lba,
output wire [31:0] sector_cnt,
output wire dma_type,
output wire dma_start,
input wire dma_done,
// axi buffer iface
output wire [31:0] bram_rdata,
input wire [31:0] bram_raddr,
input wire [31:0] bram_waddr,
input wire [31:0] bram_wdata,
input wire [3:0] bram_wstb,
input wire bram_wen,
input wire bram_ren,
input wire bram_regen,
// all registers sh_* outputs valid @ACLK
// tmp to cmd control
output wire cmd_val_out,
output wire [31:0] cmd_out,
// tmp to shadow registers
output wire [31:0] sh_data, // write data
output wire sh_data_val, // write strobe
output wire sh_data_strobe, // read strobe
output wire [15:0] sh_feature,
output wire sh_feature_val,
output wire [23:0] sh_lba_lo,
output wire sh_lba_lo_val,
output wire [23:0] sh_lba_hi,
output wire sh_lba_hi_val,
output wire [15:0] sh_count,
output wire sh_count_val,
output wire [7:0] sh_command,
output wire sh_command_val,
output wire [7:0] sh_dev,
output wire sh_dev_val,
output wire [7:0] sh_control,
output wire sh_control_val,
output wire [31:0] sh_dma_id_lo,
output wire sh_dma_id_lo_val,
output wire [31:0] sh_dma_id_hi,
output wire sh_dma_id_hi_val,
output wire [31:0] sh_buf_off,
output wire sh_buf_off_val,
output wire [31:0] sh_dma_cnt,
output wire sh_dma_cnt_val,
output wire [15:0] sh_tran_cnt,
output wire sh_tran_cnt_val,
output wire sh_autoact,
output wire sh_autoact_val,
output wire sh_inter,
output wire sh_inter_val,
output wire [3:0] sh_port,
output wire sh_port_val,
output wire sh_notif,
output wire sh_notif_val,
output wire sh_dir,
output wire sh_dir_val,
// inputs from sh registers
// No registers, just mux-ed (so @ACLK)
input wire sh_data_val_in,
input wire [31:0] sh_data_in,
input wire [7:0] sh_control_in,
input wire [15:0] sh_feature_in,
input wire [47:0] sh_lba_in,
input wire [15:0] sh_count_in,
input wire [7:0] sh_command_in,
input wire [7:0] sh_err_in,
input wire [7:0] sh_status_in,
input wire [7:0] sh_estatus_in, // E_Status
input wire [7:0] sh_dev_in,
input wire [3:0] sh_port_in,
input wire sh_inter_in,
input wire sh_dir_in,
input wire [63:0] sh_dma_id_in,
input wire [31:0] sh_dma_off_in,
input wire [31:0] sh_dma_cnt_in,
input wire [15:0] sh_tran_cnt_in, // Transfer Count
input wire sh_notif_in,
input wire sh_autoact_in,
// inputs from cmd control
input wire [31:0] cmd_in
);
//reg [32*REGISTERS_CNT - 1:0] mem;
/*
* Converntional MAXI interface from x393 project, uses fifos, writes to/reads from memory
*/
/*
* Temporary mapping:
* rw 0x00: dma address (will automatically align to 128-bytes boundary, i.e. [6:0] -> 0
* rw 0x04: lba
* rw 0x08: sector count
* rw 0x0c: dma type (any(0x0c) => write)
* r1c 0x10: writes: dma start (any(0x10) => start)
* reads: dma status of last issued transfer (0xffffffff => done)
* ro 0x14: dma last issued dma_address
*/
reg [31:0] reg00;
reg [31:0] reg04;
reg [31:0] reg08;
reg [31:0] reg0c;
reg [31:0] reg10;
reg [31:0] reg14;
wire dma_done_aclk;
wire dma_start_aclk;
reg dma_issued;
wire [31:0] wdata;
pulse_cross_clock dma_done_pulse(
.rst (rst),
.src_clk (sclk),
.dst_clk (ACLK),
.in_pulse (dma_done),
.out_pulse (dma_done_aclk),
.busy ()
);
pulse_cross_clock dma_start_pulse(
.rst (rst),
.src_clk (ACLK),
.dst_clk (sclk),
.in_pulse (dma_start_aclk & ~dma_issued),
.out_pulse (dma_start),
.busy ()
);
assign dma_start_aclk = bram_wen & (bram_waddr[7:0] == 8'hf4) & |wdata;
assign wdata = bram_wdata[31:0] & {{8{bram_wstb[3]}}, {8{bram_wstb[2]}}, {8{bram_wstb[1]}}, {8{bram_wstb[0]}}};
always @ (posedge ACLK)
dma_issued <= (dma_issued | dma_start_aclk) & ~rst & ~dma_done_aclk;
assign mem_address = reg00[31:7];
assign lba = reg04;
assign sector_cnt = reg08;
assign dma_type = |reg0c;
always @ (posedge ACLK)
begin
reg00 <= rst ? 32'h0 : bram_wen & (bram_waddr[7:0] == 8'hf0) ? wdata : reg00;
reg04 <= rst ? 32'h0 : bram_wen & (bram_waddr[7:0] == 8'hf1) ? wdata : reg04;
reg08 <= rst ? 32'h0 : bram_wen & (bram_waddr[7:0] == 8'hf2) ? wdata : reg08;
reg0c <= rst ? 32'h0 : bram_wen & (bram_waddr[7:0] == 8'hf3) ? wdata : reg0c;
reg10 <= rst ? 32'h0 : dma_start_aclk ? 32'h0 : {31'h0, dma_done_aclk} ? 32'hffffffff : reg10; // status reg
reg14 <= rst ? 32'h0 : dma_done_aclk ? reg00 : reg14;
end
// writes to shadow registers:
assign sh_data_val = bram_wen & (bram_waddr[7:0] == 8'h0);
assign sh_feature_val = bram_wen & (bram_waddr[7:0] == 8'h1);
assign sh_lba_lo_val = bram_wen & (bram_waddr[7:0] == 8'h2);
assign sh_lba_hi_val = bram_wen & (bram_waddr[7:0] == 8'h3);
assign sh_count_val = bram_wen & (bram_waddr[7:0] == 8'h4);
assign sh_command_val = bram_wen & (bram_waddr[7:0] == 8'h5);
assign sh_dev_val = bram_wen & (bram_waddr[7:0] == 8'h6);
assign sh_control_val = bram_wen & (bram_waddr[7:0] == 8'h7);
assign sh_dma_id_lo_val = bram_wen & (bram_waddr[7:0] == 8'h8);
assign sh_dma_id_hi_val = bram_wen & (bram_waddr[7:0] == 8'h9);
assign sh_buf_off_val = bram_wen & (bram_waddr[7:0] == 8'ha);
assign sh_tran_cnt_val = bram_wen & (bram_waddr[7:0] == 8'hb);
assign sh_autoact_val = bram_wen & (bram_waddr[7:0] == 8'hc);
assign sh_inter_val = bram_wen & (bram_waddr[7:0] == 8'hd);
assign sh_dir_val = bram_wen & (bram_waddr[7:0] == 8'he);
assign cmd_val_out = bram_wen & (bram_waddr[7:0] == 8'hf);
assign sh_port_val = bram_wen & (bram_waddr[7:0] == 8'h13);
assign sh_dma_cnt_val = bram_wen & (bram_waddr[7:0] == 8'h14);
assign sh_notif_val = bram_wen & (bram_waddr[7:0] == 8'h15);
assign sh_data = wdata;
assign sh_feature = wdata[15:0];
assign sh_lba_lo = wdata[23:0];
assign sh_lba_hi = wdata[23:0];
assign sh_count = wdata[15:0];
assign sh_command = wdata[7:0];
assign sh_dev = wdata[7:0];
assign sh_control = wdata[7:0];
assign sh_dma_id_lo = wdata;
assign sh_dma_id_hi = wdata;
assign sh_buf_off = wdata;
assign sh_tran_cnt = wdata[15:0];
assign sh_autoact = wdata[0];
assign sh_inter = wdata[0];
assign sh_dir = wdata[0];
assign sh_port = wdata[3:0];
assign sh_notif = wdata[0];
assign sh_dma_cnt = wdata;
assign cmd_out = wdata;
reg [7:0] bram_raddr_r;
assign sh_data_strobe = bram_ren & bram_raddr[7:0] == 8'h00;
// read from registers. Interface's protocol assumes returning data with a delay
reg [31:0] bram_rdata_r;
always @ (posedge ACLK) begin
bram_raddr_r <= bram_ren ? bram_raddr[7:0] : bram_raddr_r;
bram_rdata_r <= ~bram_regen ? bram_rdata_r :
bram_raddr_r == 8'hf0 ? reg00 :
bram_raddr_r == 8'hf1 ? reg04 :
bram_raddr_r == 8'hf2 ? reg08 :
bram_raddr_r == 8'hf3 ? reg0c :
bram_raddr_r == 8'hf4 ? reg10 :
bram_raddr_r == 8'hf5 ? reg14 :
bram_raddr_r == 8'h00 ? sh_data_in :
bram_raddr_r == 8'h01 ? {16'h0, sh_feature_in} :
bram_raddr_r == 8'h02 ? {8'h0, sh_lba_in[23:0]} :
bram_raddr_r == 8'h03 ? {8'h0, sh_lba_in[47:24]} :
bram_raddr_r == 8'h04 ? {16'h0, sh_count_in} :
bram_raddr_r == 8'h05 ? {24'h0, sh_command_in} :
bram_raddr_r == 8'h06 ? {24'h0, sh_dev_in} :
bram_raddr_r == 8'h07 ? {24'h0, sh_control_in} :
bram_raddr_r == 8'h08 ? sh_dma_id_in[31:0] :
bram_raddr_r == 8'h09 ? sh_dma_id_in[63:32] :
bram_raddr_r == 8'h0a ? sh_dma_off_in :
bram_raddr_r == 8'h0b ? {16'h0, sh_tran_cnt_in} : // Transfer Count
bram_raddr_r == 8'h0c ? {31'h0, sh_autoact_in} :
bram_raddr_r == 8'h0d ? {31'h0, sh_inter_in} :
bram_raddr_r == 8'h0e ? {31'h0, sh_dir_in} :
bram_raddr_r == 8'h0f ? cmd_in :
bram_raddr_r == 8'h10 ? {24'h0, sh_err_in} :
bram_raddr_r == 8'h11 ? {24'h0, sh_status_in} :
bram_raddr_r == 8'h12 ? {24'h0, sh_estatus_in} : // E_Status
bram_raddr_r == 8'h13 ? {28'h0, sh_port_in} :
bram_raddr_r == 8'h14 ? sh_dma_cnt_in :
bram_raddr_r == 8'h15 ? {31'h0, sh_notif_in} :
32'hd34db33f;
end
assign bram_rdata = bram_rdata_r;
/*
// for testing purposes the 'memory' is a set of registers for now
// later on will try to use them as an application level registers
genvar ii;
generate
for (ii = 0; ii < REGISTERS_CNT; ii = ii + 1)
begin: write_to_mem
always @ (posedge ACLK)
begin
mem[32*ii + 31-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[31-:8] & {8{bram_wstb[3]}}: mem[32*ii + 31-:8];
mem[32*ii + 23-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[23-:8] & {8{bram_wstb[2]}}: mem[32*ii + 23-:8];
mem[32*ii + 15-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[15-:8] & {8{bram_wstb[1]}}: mem[32*ii + 15-:8];
mem[32*ii + 7-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[ 7-:8] & {8{bram_wstb[0]}}: mem[32*ii + 7-:8];
end
end
endgenerate
// read from memory. Interface's protocol assumes returning data with a delay
reg [3:0] bram_raddr_r;
reg [31:0] bram_rdata_r;
always @ (posedge ACLK) begin
bram_raddr_r <= bram_ren ? bram_raddr[3:0] : bram_raddr_r;
bram_rdata_r <= bram_regen ? mem[32*bram_raddr_r + 31-:32] : bram_rdata_r;
end
assign bram_rdata = bram_rdata_r;
*/
endmodule
/*******************************************************************************
* Module: sata_top
* Date: 2015-07-11
* Author: Alexey
* Description: sata for z7nq top-level module
*
* Copyright (c) 2015 Elphel, Inc.
* sata_top.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sata_top.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
`timescale 1ns/1ps
//`include "axi_regs.v"
//`include "dma_regs.v"
//`include "sata_host.v"
//`include "dma_adapter.v"
//`include "dma_control.v"
//`include "membridge.v"
/*
* Takes commands from axi iface as a slave, transfers data with another axi iface as a master
*/
module sata_top(
output wire sata_clk,
output wire sata_rst,
// input wire extrst,
input wire arst,
// reliable clock to source drp and cpll lock det circuits
input wire reliable_clk,
input wire hclk,
/*
* Commands interface
*/
input wire ACLK, // AXI PS Master GP1 Clock , input
input wire ARESETN, // AXI PS Master GP1 Reset, output
// AXI PS Master GP1: Read Address
input wire [31:0] ARADDR, // AXI PS Master GP1 ARADDR[31:0], output
input wire ARVALID, // AXI PS Master GP1 ARVALID, output
output wire ARREADY, // AXI PS Master GP1 ARREADY, input
input wire [11:0] ARID, // AXI PS Master GP1 ARID[11:0], output
input wire [3:0] ARLEN, // AXI PS Master GP1 ARLEN[3:0], output
input wire [1:0] ARSIZE, // AXI PS Master GP1 ARSIZE[1:0], output
input wire [1:0] ARBURST, // AXI PS Master GP1 ARBURST[1:0], output
// AXI PS Master GP1: Read Data
output wire [31:0] RDATA, // AXI PS Master GP1 RDATA[31:0], input
output wire RVALID, // AXI PS Master GP1 RVALID, input
input wire RREADY, // AXI PS Master GP1 RREADY, output
output wire [11:0] RID, // AXI PS Master GP1 RID[11:0], input
output wire RLAST, // AXI PS Master GP1 RLAST, input
output wire [1:0] RRESP, // AXI PS Master GP1 RRESP[1:0], input
// AXI PS Master GP1: Write Address
input wire [31:0] AWADDR, // AXI PS Master GP1 AWADDR[31:0], output
input wire AWVALID, // AXI PS Master GP1 AWVALID, output
output wire AWREADY, // AXI PS Master GP1 AWREADY, input
input wire [11:0] AWID, // AXI PS Master GP1 AWID[11:0], output
input wire [3:0] AWLEN, // AXI PS Master GP1 AWLEN[3:0], outpu:t
input wire [1:0] AWSIZE, // AXI PS Master GP1 AWSIZE[1:0], output
input wire [1:0] AWBURST, // AXI PS Master GP1 AWBURST[1:0], output
// AXI PS Master GP1: Write Data
input wire [31:0] WDATA, // AXI PS Master GP1 WDATA[31:0], output
input wire WVALID, // AXI PS Master GP1 WVALID, output
output wire WREADY, // AXI PS Master GP1 WREADY, input
input wire [11:0] WID, // AXI PS Master GP1 WID[11:0], output
input wire WLAST, // AXI PS Master GP1 WLAST, output
input wire [3:0] WSTRB, // AXI PS Master GP1 WSTRB[3:0], output
// AXI PS Master GP1: Write response
output wire BVALID, // AXI PS Master GP1 BVALID, input
input wire BREADY, // AXI PS Master GP1 BREADY, output
output wire [11:0] BID, // AXI PS Master GP1 BID[11:0], input
output wire [1:0] BRESP, // AXI PS Master GP1 BRESP[1:0], input
/*
* Data interface
*/
output wire [31:0] afi_awaddr,
output wire afi_awvalid,
input wire afi_awready,
output wire [5:0] afi_awid,
output wire [1:0] afi_awlock,
output wire [3:0] afi_awcache,
output wire [2:0] afi_awprot,
output wire [3:0] afi_awlen,
output wire [1:0] afi_awsize,
output wire [1:0] afi_awburst,
output wire [3:0] afi_awqos,
// write data
output wire [63:0] afi_wdata,
output wire afi_wvalid,
input wire afi_wready,
output wire [5:0] afi_wid,
output wire afi_wlast,
output wire [7:0] afi_wstrb,
// write response
input wire afi_bvalid,
output wire afi_bready,
input wire [5:0] afi_bid,
input wire [1:0] afi_bresp,
// PL extra (non-AXI) signals
input wire [7:0] afi_wcount,
input wire [5:0] afi_wacount,
output wire afi_wrissuecap1en,
// AXI_HP signals - read channel
// read address
output wire [31:0] afi_araddr,
output wire afi_arvalid,
input wire afi_arready,
output wire [5:0] afi_arid,
output wire [1:0] afi_arlock,
output wire [3:0] afi_arcache,
output wire [2:0] afi_arprot,
output wire [3:0] afi_arlen,
output wire [1:0] afi_arsize,
output wire [1:0] afi_arburst,
output wire [3:0] afi_arqos,
// read data
input wire [63:0] afi_rdata,
input wire afi_rvalid,
output wire afi_rready,
input wire [5:0] afi_rid,
input wire afi_rlast,
input wire [1:0] afi_rresp,
// PL extra (non-AXI) signals
input wire [7:0] afi_rcount,
input wire [2:0] afi_racount,
output wire afi_rdissuecap1en,
output wire irq, // not used here, for compatibility with AHCI branch
/*
* PHY
*/
output wire TXN,
output wire TXP,
input wire RXN,
input wire RXP,
input wire EXTCLK_P,
input wire EXTCLK_N
);
assign irq = 0;
//wire sata_rst;
// dma_regs <-> sata host
// tmp to cmd control
wire cmd_val_out;
wire [31:0] cmd_out;
// tmp to shadow registers
wire [31:0] sh_data; // write data
wire sh_data_val; // write strobe
wire sh_data_strobe; // read strobe
wire [15:0] sh_feature;
wire sh_feature_val;
wire [23:0] sh_lba_lo;
wire sh_lba_lo_val;
wire [23:0] sh_lba_hi;
wire sh_lba_hi_val;
wire [15:0] sh_count;
wire sh_count_val;
wire [7:0] sh_command;
wire sh_command_val;
wire [7:0] sh_dev;
wire sh_dev_val;
wire [7:0] sh_control;
wire sh_control_val;
wire [31:0] sh_dma_id_lo;
wire sh_dma_id_lo_val;
wire [31:0] sh_dma_id_hi;
wire sh_dma_id_hi_val;
wire [31:0] sh_buf_off;
wire sh_buf_off_val;
wire [31:0] sh_dma_cnt;
wire sh_dma_cnt_val;
wire [15:0] sh_tran_cnt;
wire sh_tran_cnt_val;
wire sh_autoact;
wire sh_autoact_val;
wire sh_inter;
wire sh_inter_val;
wire [3:0] sh_port;
wire sh_port_val;
wire sh_notif;
wire sh_notif_val;
wire sh_dir;
wire sh_dir_val;
// inputs from sh registers
wire sh_data_val_in;
wire [31:0] sh_data_in;
wire [7:0] sh_control_in;
wire [15:0] sh_feature_in;
wire [47:0] sh_lba_in;
wire [15:0] sh_count_in;
wire [7:0] sh_command_in;
wire [7:0] sh_err_in;
wire [7:0] sh_status_in;
wire [7:0] sh_estatus_in; // E_Status
wire [7:0] sh_dev_in;
wire [3:0] sh_port_in;
wire sh_inter_in;
wire sh_dir_in;
wire [63:0] sh_dma_id_in;
wire [31:0] sh_dma_off_in;
wire [31:0] sh_dma_cnt_in;
wire [15:0] sh_tran_cnt_in; // Transfer Count
wire sh_notif_in;
wire sh_autoact_in;
// inputs from cmd control
wire [31:0] cmd_in;
// axi_regs <-> data regs
wire [31:0] bram_rdata;
wire [31:0] bram_waddr;
wire [31:0] bram_wdata;
wire [31:0] bram_raddr;
wire [3:0] bram_wstb;
wire bram_wen;
wire bram_ren;
wire bram_regen;
// sata logic reset
//wire rst;
// sata clk
//wire sata_clk;
// dma_regs <-> dma_control
wire [31:7] mem_address;
wire [31:0] lba;
wire [31:0] sector_cnt;
wire dma_type;
wire dma_start;
wire dma_done;
// axi-hp clock
//wire hclk;
// dma_control <-> dma_adapter command iface
wire adp_busy;
wire [31:7] adp_addr;
wire adp_type;
wire adp_val;
// dma_control <-> sata_host command iface
wire host_ready_for_cmd;
wire host_new_cmd;
wire [1:0] host_cmd_type;
wire [31:0] host_sector_count;
wire [31:0] host_sector_addr;
// dma_control <-> dma_adapter data iface
wire [63:0] to_data;
wire to_val;
wire to_ack;
wire [63:0] from_data;
wire from_val;
wire from_ack;
// dma_control <-> sata_host data iface
wire [31:0] in_data;
wire in_val;
wire in_busy;
wire [31:0] out_data;
wire out_val;
wire out_busy;
// adapter <-> membridge iface
wire [7:0] cmd_ad;
wire cmd_stb;
wire [7:0] status_ad;
wire status_rq;
wire status_start;
wire frame_start_chn;
wire next_page_chn;
wire cmd_wrmem;
wire page_ready_chn;
wire frame_done_chn;
wire [15:0] line_unfinished_chn1;
wire suspend_chn1;
wire xfer_reset_page_rd;
wire buf_wpage_nxt;
wire buf_wr;
wire [63:0] buf_wdata;
wire xfer_reset_page_wr;
wire buf_rpage_nxt;
wire buf_rd;
wire [63:0] buf_rdata;
// additional adapter <-> membridge wire
wire rdata_done; // = membridge.is_last_in_page & membridge.afi_rready;
//assign rst = ARESETN;
reg hrst;
always @ (posedge hclk)
hrst <= sata_rst;
axi_regs axi_regs(
// axi iface
.ACLK (ACLK), // input wire
.ARESETN (ARESETN), // input wire
.ARADDR (ARADDR), // input[31:0] wire
.ARVALID (ARVALID), // input wire
.ARREADY (ARREADY), // output wire
.ARID (ARID), // input[11:0] wire
.ARLEN (ARLEN), // input[3:0] wire
.ARSIZE (ARSIZE), // input[1:0] wire
.ARBURST (ARBURST), // input[1:0] wire
.RDATA (RDATA), // output[31:0] wire
.RVALID (RVALID), // output wire
.RREADY (RREADY), // input wire
.RID (RID), // output[11:0] wire
.RLAST (RLAST), // output wire
.RRESP (RRESP), // output[1:0] wire
.AWADDR (AWADDR), // input[31:0] wire
.AWVALID (AWVALID), // input wire
.AWREADY (AWREADY), // output wire
.AWID (AWID), // input[11:0] wire
.AWLEN (AWLEN), // input[3:0] wire
.AWSIZE (AWSIZE), // input[1:0] wire
.AWBURST (AWBURST), // input[1:0] wire
.WDATA (WDATA), // input[31:0] wire
.WVALID (WVALID), // input wire
.WREADY (WREADY), // output wire
.WID (WID), // input[11:0] wire
.WLAST (WLAST), // input wire
.WSTRB (WSTRB), // input wire
.BVALID (BVALID), // output wire
.BREADY (BREADY), // input wire
.BID (BID), // output[11:0] wire
.BRESP (BRESP), // output[1:0] wire
// registers iface
.bram_rdata (bram_rdata),// input[31:0] wire
.bram_waddr (bram_waddr),// output[31:0] wire
.bram_wdata (bram_wdata),// output[31:0] wire
.bram_raddr (bram_raddr),// output[31:0] wire
.bram_wstb (bram_wstb), // output[3:0] wire
.bram_wen (bram_wen), // output wire
.bram_ren (bram_ren), // output wire
.bram_regen (bram_regen) // output wire
);
/*
* Programmable sata controller registers
*/
dma_regs dma_regs(
.rst (ARESETN), // input wire
.ACLK (ACLK), // input wire
.sclk (sata_clk), // input wire
// control iface
.mem_address (mem_address[31:7]), // output[31:7] wire
.lba (lba), // output[31:0] wire
.sector_cnt (sector_cnt), // output[31:0] wire
.dma_type (dma_type), // output wire
.dma_start (dma_start), // output wire
.dma_done (dma_done), // input wire
// axi buffer iface
.bram_rdata (bram_rdata), // output[31:0] wire
.bram_raddr (bram_raddr), // input[31:0] wire
.bram_waddr (bram_waddr), // input[31:0] wire
.bram_wdata (bram_wdata), // input[31:0] wire
.bram_wstb (bram_wstb), // input[ 3:0] wire
.bram_wen (bram_wen), // input wire
.bram_ren (bram_ren), // input wire
.bram_regen (bram_regen), // input wire
// direct connections to the host
// tmp to cmd control
.cmd_val_out (cmd_val_out), // output wire
.cmd_out (cmd_out), // output[31:0] wire
// tmp to shadow registers
.sh_data (sh_data), // output[31:0] wire : write data
.sh_data_val (sh_data_val), // output wire: write strobe
.sh_data_strobe (sh_data_strobe), // output wire: read strobe
.sh_feature (sh_feature), // output[15:0] wire
.sh_feature_val (sh_feature_val), // output wire
.sh_lba_lo (sh_lba_lo), // output[23:0] wire
.sh_lba_lo_val (sh_lba_lo_val), // output wire
.sh_lba_hi (sh_lba_hi), // output[23:0] wire
.sh_lba_hi_val (sh_lba_hi_val), // output wire
.sh_count (sh_count), // output[15:0] wire
.sh_count_val (sh_count_val), // output wire
.sh_command (sh_command), // output[7:0] wire
.sh_command_val (sh_command_val), // output wire
.sh_dev (sh_dev), // output[7:0] wire
.sh_dev_val (sh_dev_val), // output wire
.sh_control (sh_control), // output[7:0] wire
.sh_control_val (sh_control_val), // output wire
.sh_dma_id_lo (sh_dma_id_lo), // output[31:0] wire
.sh_dma_id_lo_val (sh_dma_id_lo_val),// output wire
.sh_dma_id_hi (sh_dma_id_hi), // output[31:0] wire
.sh_dma_id_hi_val (sh_dma_id_hi_val),// output wire
.sh_buf_off (sh_buf_off), // output[31:0] wire
.sh_buf_off_val (sh_buf_off_val), // output wire
.sh_dma_cnt (sh_dma_cnt), // output[31:0] wire
.sh_dma_cnt_val (sh_dma_cnt_val), // output wire
.sh_tran_cnt (sh_tran_cnt), // output[15:0] wire
.sh_tran_cnt_val (sh_tran_cnt_val), // output wire
.sh_autoact (sh_autoact), // output wire
.sh_autoact_val (sh_autoact_val), // output wire
.sh_inter (sh_inter), // output wire
.sh_inter_val (sh_inter_val), // output wire
.sh_port (sh_port), // output[3:0] wire
.sh_port_val (sh_port_val), // output wire
.sh_notif (sh_notif), // output wire
.sh_notif_val (sh_notif_val), // output wire
.sh_dir (sh_dir), // output wire
.sh_dir_val (sh_dir_val), // output wire
// inputs from sh registers
.sh_data_val_in (sh_data_val_in), // input wire
.sh_data_in (sh_data_in), // input[31:0] wire
.sh_control_in (sh_control_in), // input[7:0] wire
.sh_feature_in (sh_feature_in), // input[15:0] wire
.sh_lba_in (sh_lba_in), // input[47:0] wire
.sh_count_in (sh_count_in), // input[15:0] wire
.sh_command_in (sh_command_in), // input[7:0] wire
.sh_err_in (sh_err_in), // input[7:0] wire
.sh_status_in (sh_status_in), // input[7:0] wire
.sh_estatus_in (sh_estatus_in), // input[7:0] wire : E_Status
.sh_dev_in (sh_dev_in), // input[7:0] wire
.sh_port_in (sh_port_in), // input[3:0] wire
.sh_inter_in (sh_inter_in), // input wire
.sh_dir_in (sh_dir_in), // input wire
.sh_dma_id_in (sh_dma_id_in), // input[63:0] wire
.sh_dma_off_in (sh_dma_off_in), // input[31:0] wire
.sh_dma_cnt_in (sh_dma_cnt_in), // input[31:0] wire
.sh_tran_cnt_in (sh_tran_cnt_in), // Transfer Count
.sh_notif_in (sh_notif_in), // input wire
.sh_autoact_in (sh_autoact_in), // input wire
// inputs from cmd control
.cmd_in (cmd_in) // input[31:0] wire
);
dma_control dma_control(
.sclk (sata_clk), // input wire
.hclk (hclk), // input wire
.rst (sata_rst), // input wire
// registers iface
.mem_address (mem_address[31:7]), // input[31:7] wire
.lba (lba), // input[31:0] wire
.sector_cnt (sector_cnt), // input[31:0] wire
.dma_type (dma_type), // input wire
.dma_start (dma_start), // input wire
.dma_done (dma_done), // output wire
// adapter command iface
.adp_busy (adp_busy), // input wire
.adp_addr (adp_addr[31:7]), // output[31:7] wire
.adp_type (adp_type), // output wire
.adp_val (adp_val), // output wire
// sata host command iface
.host_ready_for_cmd (host_ready_for_cmd), // input wire
.host_new_cmd (host_new_cmd), // output wire
.host_cmd_type (host_cmd_type), // output[1:0] wire
.host_sector_count (host_sector_count), // output[31:0] wire
.host_sector_addr (host_sector_addr), // output[31:0] wire
// adapter data iface
// to main memory
.to_data (to_data), // output[63:0] wire
.to_val (to_val), // output wire
.to_ack (to_ack), // input wire
// from main memory
.from_data (from_data), // input[63:0] wire
.from_val (from_val), // input wire
.from_ack (from_ack), // output wire
// sata host iface
// data from sata host
.in_data (in_data), // input[31:0] wire
.in_val (in_val), // output wire
.in_busy (in_busy), // input wire
// data to sata host
.out_data (out_data), // output[31:0] wire
.out_val (out_val), // output wire
.out_busy (out_busy) // input wire
);
//assign rdata_done = membridge.is_last_in_page & membridge.afi_rready;
dma_adapter dma_adapter(
.clk (hclk), // input wire
.rst (hrst), // input wire
// command iface
.cmd_type (adp_type), // input wire
.cmd_val (adp_val), // input wire
.cmd_addr (adp_addr[31:7]), // input[31:7] wire
.cmd_busy (adp_busy), // output wire
// data iface
.wr_data_in (to_data), // input[63:0] wire
.wr_val_in (to_val), // input wire
.wr_ack_out (to_ack), // output wire
.rd_data_out (from_data), // output[63:0] wire
.rd_val_out (from_val), // output wire
.rd_ack_in (from_ack), // input wire
// membridge iface
.cmd_ad (cmd_ad), // output[7:0] wire
.cmd_stb (cmd_stb), // output wire
.status_ad (status_ad), // input[7:0] wire Not used
.status_rq (status_rq), // input wire Not used
.status_start (status_start), // output wire
.frame_start_chn (frame_start_chn), // input wire Not used
.next_page_chn (next_page_chn), // input wire Not used
.cmd_wrmem (cmd_wrmem), // output wire
.page_ready_chn (page_ready_chn), // output wire
.frame_done_chn (frame_done_chn), // output wire
.line_unfinished_chn1 (line_unfinished_chn1),// output[15:0] wire Not used
.suspend_chn1 (suspend_chn1), // input wire Not used
.xfer_reset_page_rd (xfer_reset_page_rd), // output wire
.buf_wpage_nxt (buf_wpage_nxt), // output wire
.buf_wr (buf_wr), // output wire
.buf_wdata (buf_wdata), // output[63:0] wire
.xfer_reset_page_wr (xfer_reset_page_wr), // output wire
.buf_rpage_nxt (buf_rpage_nxt), // output wire
.buf_rd (buf_rd), // output wire
.buf_rdata (buf_rdata), // input[63:0] wire
.rdata_done (rdata_done) // input wire
);
membridge /*#(
V .MEMBRIDGE_ADDR (),
.MEMBRIDGE_MASK (),
.MEMBRIDGE_CTRL (),
.MEMBRIDGE_STATUS_CNTRL (),
.MEMBRIDGE_LO_ADDR64 (),
.MEMBRIDGE_SIZE64 (),
.MEMBRIDGE_START64 (),
.MEMBRIDGE_LEN64 (),
.MEMBRIDGE_WIDTH64 (),
.MEMBRIDGE_MODE (),
.MEMBRIDGE_STATUS_REG (),
.FRAME_HEIGHT_BITS (),
.FRAME_WIDTH_BITS ()
)*/ membridge(
.mrst (sata_rst), // hrst), // input Andrey: Wrong, should be @sata_clk
.hrst (hrst), // input
.mclk (sata_clk), // input
.hclk (hclk), // input
.cmd_ad (cmd_ad), // input[7:0]
.cmd_stb (cmd_stb), // input // Nothing here
.status_ad (status_ad), // output[7:0]
.status_rq (status_rq), // output
.status_start (status_start), // input
.frame_start_chn (frame_start_chn), // output
.next_page_chn (next_page_chn), // output
.cmd_wrmem (cmd_wrmem), // input
.page_ready_chn (page_ready_chn), // input
.frame_done_chn (frame_done_chn), // input
.line_unfinished_chn1 (line_unfinished_chn1), // input[15:0]
.suspend_chn1 (suspend_chn1), // output
.xfer_reset_page_rd (xfer_reset_page_rd), // input
.buf_wpage_nxt (buf_wpage_nxt), // input
.buf_wr (buf_wr), // input
.buf_wdata (buf_wdata), // input[63:0]
.xfer_reset_page_wr (xfer_reset_page_wr), // input
.buf_rpage_nxt (buf_rpage_nxt), // input
.buf_rd (buf_rd), // input
.buf_rdata (buf_rdata), // output[63:0]
.afi_awaddr (afi_awaddr), // output[31:0]
.afi_awvalid (afi_awvalid), // output
.afi_awready (afi_awready), // input
.afi_awid (afi_awid), // output[5:0]
.afi_awlock (afi_awlock), // output[1:0]
.afi_awcache (afi_awcache), // output[3:0]
.afi_awprot (afi_awprot), // output[2:0]
.afi_awlen (afi_awlen), // output[3:0]
.afi_awsize (afi_awsize), // output[2:0]
.afi_awburst (afi_awburst), // output[1:0]
.afi_awqos (afi_awqos), // output[3:0]
.afi_wdata (afi_wdata), // output[63:0]
.afi_wvalid (afi_wvalid), // output
.afi_wready (afi_wready), // input
.afi_wid (afi_wid), // output[5:0]
.afi_wlast (afi_wlast), // output
.afi_wstrb (afi_wstrb), // output[7:0]
.afi_bvalid (afi_bvalid), // input
.afi_bready (afi_bready), // output
.afi_bid (afi_bid), // input[5:0]
.afi_bresp (afi_bresp), // input[1:0]
.afi_wcount (afi_wcount), // input[7:0]
.afi_wacount (afi_wacount), // input[5:0]
.afi_wrissuecap1en (afi_wrissuecap1en), // output
.afi_araddr (afi_araddr), // output[31:0]
.afi_arvalid (afi_arvalid), // output
.afi_arready (afi_arready), // input
.afi_arid (afi_arid), // output[5:0]
.afi_arlock (afi_arlock), // output[1:0]
.afi_arcache (afi_arcache), // output[3:0]
.afi_arprot (afi_arprot), // output[2:0]
.afi_arlen (afi_arlen), // output[3:0]
.afi_arsize (afi_arsize), // output[2:0]
.afi_arburst (afi_arburst), // output[1:0]
.afi_arqos (afi_arqos), // output[3:0]
.afi_rdata (afi_rdata), // input[63:0]
.afi_rvalid (afi_rvalid), // input
.afi_rready (afi_rready), // output
.afi_rid (afi_rid), // input[5:0]
.afi_rlast (afi_rlast), // input
.afi_rresp (afi_rresp), // input[2:0]
.afi_rcount (afi_rcount), // input[7:0]
.afi_racount (afi_racount), // input[2:0]
.afi_rdissuecap1en (afi_rdissuecap1en)/*, // output
.rdata_done (rdata_done)*/
);
assign rdata_done = 1'b0;
sata_host sata_host(
.extrst (arst),
// sata rst
.rst (sata_rst),
// sata clk
.clk (sata_clk),
// reliable clock to source drp and cpll lock det circuits
.reliable_clk (reliable_clk),
// temporary
.al_cmd_in (cmd_out), // == {cmd_type, cmd_port, cmd_val, cmd_done_bad, cmd_done_good; cmd_busy}
.al_cmd_val_in (cmd_val_out),
.al_cmd_out (cmd_in), // same
// tmp inputs directly from registers for each and every shadow register and control bit
// from al
.al_sh_data_in (sh_data), // write data
.al_sh_data_val_in (sh_data_val), // write strobe
.al_sh_data_strobe_in (sh_data_strobe), // read strobe
.al_sh_feature_in (sh_feature),
.al_sh_feature_val_in (sh_feature_val),
.al_sh_lba_lo_in (sh_lba_lo),
.al_sh_lba_lo_val_in (sh_lba_lo_val),
.al_sh_lba_hi_in (sh_lba_hi),
.al_sh_lba_hi_val_in (sh_lba_hi_val),
.al_sh_count_in (sh_count),
.al_sh_count_val_in (sh_count_val),
.al_sh_command_in (sh_command),
.al_sh_command_val_in (sh_command_val),
.al_sh_dev_in (sh_dev),
.al_sh_dev_val_in (sh_dev_val),
.al_sh_control_in (sh_control),
.al_sh_control_val_in (sh_control_val),
.al_sh_dma_id_lo_in (sh_dma_id_lo),
.al_sh_dma_id_lo_val_in (sh_dma_id_lo_val),
.al_sh_dma_id_hi_in (sh_dma_id_hi),
.al_sh_dma_id_hi_val_in (sh_dma_id_hi_val),
.al_sh_buf_off_in (sh_buf_off),
.al_sh_buf_off_val_in (sh_buf_off_val),
.al_sh_tran_cnt_in (sh_tran_cnt),
.al_sh_tran_cnt_val_in (sh_tran_cnt_val),
.al_sh_autoact_in (sh_autoact),
.al_sh_autoact_val_in (sh_autoact_val),
.al_sh_inter_in (sh_inter),
.al_sh_inter_val_in (sh_inter_val),
.al_sh_dir_in (sh_dir),
.al_sh_dir_val_in (sh_dir_val),
.al_sh_dma_cnt_in (sh_dma_cnt),
.al_sh_dma_cnt_val_in (sh_dma_cnt_val),
.al_sh_notif_in (sh_notif),
.al_sh_notif_val_in (sh_notif_val),
.al_sh_port_in (sh_port),
.al_sh_port_val_in (sh_port_val),
// outputs from shadow registers - no registers, just MUX-ed and read @ACLK
.sh_data_val_out (sh_data_val_in),
.sh_data_out (sh_data_in),
.sh_control_out (sh_control_in),
.sh_feature_out (sh_feature_in),
.sh_lba_out (sh_lba_in),
.sh_count_out (sh_count_in),
.sh_command_out (sh_command_in),
.sh_err_out (sh_err_in),
.sh_status_out (sh_status_in),
.sh_estatus_out (sh_estatus_in), // E_Status
.sh_dev_out (sh_dev_in),
.sh_port_out (sh_port_in),
.sh_inter_out (sh_inter_in),
.sh_dir_out (sh_dir_in),
.sh_dma_id_out (sh_dma_id_in),
.sh_dma_off_out (sh_dma_off_in),
.sh_dma_cnt_out (sh_dma_cnt_in),
.sh_tran_cnt_out (sh_tran_cnt_in), // Transfer Count
.sh_notif_out (sh_notif_in),
.sh_autoact_out (sh_autoact_in),
// top-level ifaces
// ref clk from an external source, shall be connected to pads
.extclk_p (EXTCLK_P),
.extclk_n (EXTCLK_N),
// sata physical link data pins
.txp_out (TXP),
.txn_out (TXN),
.rxp_in (RXP),
.rxn_in (RXN)
);
endmodule
/*******************************************************************************
* Module: top
* Date: 2015-07-11
* Author: Alexey
* Description: top-level module, instantiates PS7 + sata host controller
*
* Copyright (c) 2015 Elphel, Inc.
* top.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* top.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
/*
* all signals' and modules' names and interconnections are taken from x393.v
* to make the final integration easier - just to make an instance of
* what is called now 'axi_regs' and connect it
*/
// Including system defines at the top level can distinguish between simulation and synthesis?
`include "system_defines.vh"
module top #(
`include "includes/x393_parameters.vh" // SuppressThisWarning VEditor - partially used
)
(
// sata serial data iface
input wire RXN,
input wire RXP,
output wire TXN,
output wire TXP,
// sata clocking iface
input wire EXTCLK_P,
input wire EXTCLK_N
);
wire axi_aclk0;
wire sclk ; // Just output from SATA subsystem SuppressThisWarning VEditor Not used
wire sata_rst; // Just output from SATA subsystem SuppressThisWarning VEditor Not used
wire extrst;
wire [3:0] fclk;
wire [3:0] frst;
//wire axi_aclk;
wire axi_rst;
wire hclk;
wire comb_rst;
wire [31:0] maxi1_araddr;
wire maxi1_arvalid;
wire maxi1_arready;
wire [11:0] maxi1_arid;
wire [3:0] maxi1_arlen;
wire [1:0] maxi1_arsize;
wire [1:0] maxi1_arburst;
wire [31:0] maxi1_rdata;
wire maxi1_rvalid;
wire maxi1_rready;
wire [11:0] maxi1_rid;
wire maxi1_rlast;
wire [1:0] maxi1_rresp;
wire [31:0] maxi1_awaddr;
wire maxi1_awvalid;
wire maxi1_awready;
wire [11:0] maxi1_awid;
wire [3:0] maxi1_awlen;
wire [1:0] maxi1_awsize;
wire [1:0] maxi1_awburst;
wire [31:0] maxi1_wdata;
wire maxi1_wvalid;
wire maxi1_wready;
wire [11:0] maxi1_wid;
wire maxi1_wlast;
wire [3:0] maxi1_wstb;
wire maxi1_bvalid;
wire maxi1_bready;
wire [11:0] maxi1_bid;
wire [1:0] maxi1_bresp;
reg axi_rst_pre;
// membridge
wire [31:0] afi3_awaddr; // output[31:0]
wire afi3_awvalid; // output
wire afi3_awready; // input
wire [ 5:0] afi3_awid; // output[5:0]
wire [ 1:0] afi3_awlock; // output[1:0]
wire [ 3:0] afi3_awcache; // output[3:0]
wire [ 2:0] afi3_awprot; // output[2:0]
wire [ 3:0] afi3_awlen; // output[3:0]
wire [ 1:0] afi3_awsize; // output[2:0]
wire [ 1:0] afi3_awburst; // output[1:0]
wire [ 3:0] afi3_awqos; // output[3:0]
wire [63:0] afi3_wdata; // output[63:0]
wire afi3_wvalid; // output
wire afi3_wready; // input
wire [ 5:0] afi3_wid; // output[5:0]
wire afi3_wlast; // output
wire [ 7:0] afi3_wstrb; // output[7:0]
wire afi3_bvalid; // input
wire afi3_bready; // output
wire [ 5:0] afi3_bid; // input[5:0]
wire [ 1:0] afi3_bresp; // input[1:0]
wire [ 7:0] afi3_wcount; // input[7:0]
wire [ 5:0] afi3_wacount; // input[5:0]
wire afi3_wrissuecap1en; // output
wire [31:0] afi3_araddr; // output[31:0]
wire afi3_arvalid; // output
wire afi3_arready; // input
wire [ 5:0] afi3_arid; // output[5:0]
wire [ 1:0] afi3_arlock; // output[1:0]
wire [ 3:0] afi3_arcache; // output[3:0]
wire [ 2:0] afi3_arprot; // output[2:0]
wire [ 3:0] afi3_arlen; // output[3:0]
wire [ 1:0] afi3_arsize; // output[2:0]
wire [ 1:0] afi3_arburst; // output[1:0]
wire [ 3:0] afi3_arqos; // output[3:0]
wire [63:0] afi3_rdata; // input[63:0]
wire afi3_rvalid; // input
wire afi3_rready; // output
wire [ 5:0] afi3_rid; // input[5:0]
wire afi3_rlast; // input
wire [ 1:0] afi3_rresp; // input[2:0]
wire [ 7:0] afi3_rcount; // input[7:0]
wire [ 2:0] afi3_racount; // input[2:0]
wire afi3_rdissuecap1en; // output
wire irq; // ps7 IRQ
assign comb_rst=~frst[0] | frst[1];
always @(posedge comb_rst or posedge axi_aclk0) begin
if (comb_rst) axi_rst_pre <= 1'b1;
else axi_rst_pre <= 1'b0;
end
//BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(/*fclk[0]*/ sclk));
//assign axi_aclk = sclk;
BUFG bufg_axi_aclk0_i (.O(axi_aclk0),.I(fclk[0]));
BUFG bufg_axi_rst_i (.O(axi_rst),.I(axi_rst_pre));
BUFG bufg_extrst_i (.O(extrst),.I(axi_rst_pre));
axi_hp_clk #(
.CLKIN_PERIOD(20.000),
.CLKFBOUT_MULT_AXIHP(18),
.CLKFBOUT_DIV_AXIHP(6)
) axi_hp_clk_i (
.rst (axi_rst), // input
.clk_in (axi_aclk0), // input
.clk_axihp (hclk), // output
.locked_axihp () // output // not controlled?
);
`ifdef AHCI_SATA
sata_ahci_top sata_top(
`else
sata_top sata_top(
`endif
.sata_clk (sclk),
// reliable clock to source drp and cpll lock det circuits
.reliable_clk (axi_aclk0),
.hclk (hclk),
.sata_rst (sata_rst),
.arst (extrst),
.ACLK (axi_aclk0),
.ARESETN (axi_rst/* | sata_rst*/),
// AXI PS Master GP1: Read Address
.ARADDR (maxi1_araddr),
.ARVALID (maxi1_arvalid),
.ARREADY (maxi1_arready),
.ARID (maxi1_arid),
.ARLEN (maxi1_arlen),
.ARSIZE (maxi1_arsize),
.ARBURST (maxi1_arburst),
// AXI PS Master GP1: Read Data
.RDATA (maxi1_rdata),
.RVALID (maxi1_rvalid),
.RREADY (maxi1_rready),
.RID (maxi1_rid),
.RLAST (maxi1_rlast),
.RRESP (maxi1_rresp),
// AXI PS Master GP1: Write Address
.AWADDR (maxi1_awaddr),
.AWVALID (maxi1_awvalid),
.AWREADY (maxi1_awready),
.AWID (maxi1_awid),
.AWLEN (maxi1_awlen),
.AWSIZE (maxi1_awsize),
.AWBURST (maxi1_awburst),
// AXI PS Master GP1: Write Data
.WDATA (maxi1_wdata),
.WVALID (maxi1_wvalid),
.WREADY (maxi1_wready),
.WID (maxi1_wid),
.WLAST (maxi1_wlast),
.WSTRB (maxi1_wstb),
// AXI PS Master GP1: Write response
.BVALID (maxi1_bvalid),
.BREADY (maxi1_bready),
.BID (maxi1_bid),
.BRESP (maxi1_bresp),
/*
* Data interface
*/
.afi_awaddr (afi3_awaddr),
.afi_awvalid (afi3_awvalid),
.afi_awready (afi3_awready),
.afi_awid (afi3_awid),
.afi_awlock (afi3_awlock),
.afi_awcache (afi3_awcache),
.afi_awprot (afi3_awprot),
.afi_awlen (afi3_awlen),
.afi_awsize (afi3_awsize),
.afi_awburst (afi3_awburst),
.afi_awqos (afi3_awqos),
// write data
.afi_wdata (afi3_wdata),
.afi_wvalid (afi3_wvalid),
.afi_wready (afi3_wready),
.afi_wid (afi3_wid),
.afi_wlast (afi3_wlast),
.afi_wstrb (afi3_wstrb),
// write response
.afi_bvalid (afi3_bvalid),
.afi_bready (afi3_bready),
.afi_bid (afi3_bid),
.afi_bresp (afi3_bresp),
// PL extra (non-AXI) signal
.afi_wcount (afi3_wcount),
.afi_wacount (afi3_wacount),
.afi_wrissuecap1en (afi3_wrissuecap1en),
// AXI_HP signals - read channel
// read address
.afi_araddr (afi3_araddr),
.afi_arvalid (afi3_arvalid),
.afi_arready (afi3_arready),
.afi_arid (afi3_arid),
.afi_arlock (afi3_arlock),
.afi_arcache (afi3_arcache),
.afi_arprot (afi3_arprot),
.afi_arlen (afi3_arlen),
.afi_arsize (afi3_arsize),
.afi_arburst (afi3_arburst),
.afi_arqos (afi3_arqos),
// read data
.afi_rdata (afi3_rdata),
.afi_rvalid (afi3_rvalid),
.afi_rready (afi3_rready),
.afi_rid (afi3_rid),
.afi_rlast (afi3_rlast),
.afi_rresp (afi3_rresp),
// PL extra (non-AXI) signal
.afi_rcount (afi3_rcount),
.afi_racount (afi3_racount),
.afi_rdissuecap1en (afi3_rdissuecap1en),
.irq (irq), // output wire
/*
* PHY
*/
.TXN (TXN),
.TXP (TXP),
.RXN (RXN),
.RXP (RXP),
.EXTCLK_P (EXTCLK_P),
.EXTCLK_N (EXTCLK_N)
);
PS7 ps7_i (
// EMIO interface
// CAN interface
.EMIOCAN0PHYTX(), // CAN 0 TX, output
.EMIOCAN0PHYRX(), // CAN 0 RX, input
.EMIOCAN1PHYTX(), // Can 1 TX, output
.EMIOCAN1PHYRX(), // CAN 1 RX, input
// GMII 0
.EMIOENET0GMIICRS(), // GMII 0 Carrier sense, input
.EMIOENET0GMIICOL(), // GMII 0 Collision detect, input
.EMIOENET0EXTINTIN(), // GMII 0 Controller Interrupt input, input
// GMII 0 TX signals
.EMIOENET0GMIITXCLK(), // GMII 0 TX clock, input
.EMIOENET0GMIITXD(), // GMII 0 Tx Data[7:0], output
.EMIOENET0GMIITXEN(), // GMII 0 Tx En, output
.EMIOENET0GMIITXER(), // GMII 0 Tx Err, output
// GMII 0 TX timestamp signals
.EMIOENET0SOFTX(), // GMII 0 Tx Tx Start-of-Frame, output
.EMIOENET0PTPDELAYREQTX(), // GMII 0 Tx PTP delay req frame detected, output
.EMIOENET0PTPPDELAYREQTX(), // GMII 0 Tx PTP peer delay frame detect, output
.EMIOENET0PTPPDELAYRESPTX(), // GMII 0 Tx PTP pear delay response frame detected, output
.EMIOENET0PTPSYNCFRAMETX(), // GMII 0 Tx PTP sync frame detected, output
// GMII 0 RX signals
.EMIOENET0GMIIRXCLK(), // GMII 0 Rx Clock, input
.EMIOENET0GMIIRXD(), // GMII 0 Rx Data (7:0), input
.EMIOENET0GMIIRXDV(), // GMII 0 Rx Data valid, input
.EMIOENET0GMIIRXER(), // GMII 0 Rx Error, input
// GMII 0 RX timestamp signals
.EMIOENET0SOFRX(), // GMII 0 Rx Start of Frame, output
.EMIOENET0PTPDELAYREQRX(), // GMII 0 Rx PTP delay req frame detected
.EMIOENET0PTPPDELAYREQRX(), // GMII 0 Rx PTP peer delay frame detected, output
.EMIOENET0PTPPDELAYRESPRX(), // GMII 0 Rx PTP peer delay response frame detected, output
.EMIOENET0PTPSYNCFRAMERX(), // GMII 0 Rx PTP sync frame detected, output
// MDIO 0
.EMIOENET0MDIOMDC(), // MDIO 0 MD clock output, output
.EMIOENET0MDIOO(), // MDIO 0 MD data output, output
.EMIOENET0MDIOTN(), // MDIO 0 MD data 3-state, output
.EMIOENET0MDIOI(), // MDIO 0 MD data input, input
// GMII 1
.EMIOENET1GMIICRS(), // GMII 1 Carrier sense, input
.EMIOENET1GMIICOL(), // GMII 1 Collision detect, input
.EMIOENET1EXTINTIN(), // GMII 1 Controller Interrupt input, input
// GMII 1 TX signals
.EMIOENET1GMIITXCLK(), // GMII 1 TX clock, input
.EMIOENET1GMIITXD(), // GMII 1 Tx Data[7:0], output
.EMIOENET1GMIITXEN(), // GMII 1 Tx En, output
.EMIOENET1GMIITXER(), // GMII 1 Tx Err, output
// GMII 1 TX timestamp signals
.EMIOENET1SOFTX(), // GMII 1 Tx Tx Start-of-Frame, output
.EMIOENET1PTPDELAYREQTX(), // GMII 1 Tx PTP delay req frame detected, output
.EMIOENET1PTPPDELAYREQTX(), // GMII 1 Tx PTP peer delay frame detect, output
.EMIOENET1PTPPDELAYRESPTX(), // GMII 1 Tx PTP pear delay response frame detected, output
.EMIOENET1PTPSYNCFRAMETX(), // GMII 1 Tx PTP sync frame detected, output
// GMII 1 RX signals
.EMIOENET1GMIIRXCLK(), // GMII 1 Rx Clock, input
.EMIOENET1GMIIRXD(), // GMII 1 Rx Data (7:0), input
.EMIOENET1GMIIRXDV(), // GMII 1 Rx Data valid, input
.EMIOENET1GMIIRXER(), // GMII 1 Rx Error, input
// GMII 1 RX timestamp signals
.EMIOENET1SOFRX(), // GMII 1 Rx Start of Frame, output
.EMIOENET1PTPDELAYREQRX(), // GMII 1 Rx PTP delay req frame detected
.EMIOENET1PTPPDELAYREQRX(), // GMII 1 Rx PTP peer delay frame detected, output
.EMIOENET1PTPPDELAYRESPRX(), // GMII 1 Rx PTP peer delay response frame detected, output
.EMIOENET1PTPSYNCFRAMERX(), // GMII 1 Rx PTP sync frame detected, output
// MDIO 1
.EMIOENET1MDIOMDC(), // MDIO 1 MD clock output, output
.EMIOENET1MDIOO(), // MDIO 1 MD data output, output
.EMIOENET1MDIOTN(), // MDIO 1 MD data 3-state, output
.EMIOENET1MDIOI(), // MDIO 1 MD data input, input
// EMIO GPIO
.EMIOGPIOO(), // EMIO GPIO Data out[63:0], output
.EMIOGPIOI(/*gpio_in[63:0]*/), // EMIO GPIO Data in[63:0], input
.EMIOGPIOTN(), // EMIO GPIO OutputEnable[63:0], output
// EMIO I2C 0
.EMIOI2C0SCLO(), // I2C 0 SCL OUT, output // manual says input
.EMIOI2C0SCLI(), // I2C 0 SCL IN, input // manual says output
.EMIOI2C0SCLTN(), // I2C 0 SCL EN, output // manual says input
.EMIOI2C0SDAO(), // I2C 0 SDA OUT, output // manual says input
.EMIOI2C0SDAI(), // I2C 0 SDA IN, input // manual says output
.EMIOI2C0SDATN(), // I2C 0 SDA EN, output // manual says input
// EMIO I2C 1
.EMIOI2C1SCLO(), // I2C 1 SCL OUT, output // manual says input
.EMIOI2C1SCLI(), // I2C 1 SCL IN, input // manual says output
.EMIOI2C1SCLTN(), // I2C 1 SCL EN, output // manual says input
.EMIOI2C1SDAO(), // I2C 1 SDA OUT, output // manual says input
.EMIOI2C1SDAI(), // I2C 1 SDA IN, input // manual says output
.EMIOI2C1SDATN(), // I2C 1 SDA EN, output // manual says input
// JTAG
.EMIOPJTAGTCK(), // JTAG TCK, input
.EMIOPJTAGTMS(), // JTAG TMS, input
.EMIOPJTAGTDI(), // JTAG TDI, input
.EMIOPJTAGTDO(), // JTAG TDO, output
.EMIOPJTAGTDTN(), // JTAG TDO OE, output
// SDIO 0
.EMIOSDIO0CLKFB(), // SDIO 0 Clock feedback, input
.EMIOSDIO0CLK(), // SDIO 0 Clock, output
.EMIOSDIO0CMDI(), // SDIO 0 Command in, input
.EMIOSDIO0CMDO(), // SDIO 0 Command out, output
.EMIOSDIO0CMDTN(), // SDIO 0 command OE, output
.EMIOSDIO0DATAI(), // SDIO 0 Data in [3:0], input
.EMIOSDIO0DATAO(), // SDIO 0 Data out [3:0], output
.EMIOSDIO0DATATN(), // SDIO 0 Data OE [3:0], output
.EMIOSDIO0CDN(), // SDIO 0 Card detect, input
.EMIOSDIO0WP(), // SDIO 0 Write protect, input
.EMIOSDIO0BUSPOW(), // SDIO 0 Power control, output
.EMIOSDIO0LED(), // SDIO 0 LED control, output
.EMIOSDIO0BUSVOLT(), // SDIO 0 Bus voltage [2:0], output
// SDIO 1
.EMIOSDIO1CLKFB(), // SDIO 1 Clock feedback, input
.EMIOSDIO1CLK(), // SDIO 1 Clock, output
.EMIOSDIO1CMDI(), // SDIO 1 Command in, input
.EMIOSDIO1CMDO(), // SDIO 1 Command out, output
.EMIOSDIO1CMDTN(), // SDIO 1 command OE, output
.EMIOSDIO1DATAI(), // SDIO 1 Data in [3:0], input
.EMIOSDIO1DATAO(), // SDIO 1 Data out [3:0], output
.EMIOSDIO1DATATN(), // SDIO 1 Data OE [3:0], output
.EMIOSDIO1CDN(), // SDIO 1 Card detect, input
.EMIOSDIO1WP(), // SDIO 1 Write protect, input
.EMIOSDIO1BUSPOW(), // SDIO 1 Power control, output
.EMIOSDIO1LED(), // SDIO 1 LED control, output
.EMIOSDIO1BUSVOLT(), // SDIO 1 Bus voltage [2:0], output
// SPI 0
.EMIOSPI0SCLKI(), // SPI 0 CLK in , input
.EMIOSPI0SCLKO(), // SPI 0 CLK out, output
.EMIOSPI0SCLKTN(), // SPI 0 CLK OE, output
.EMIOSPI0SI(), // SPI 0 MOSI in , input
.EMIOSPI0MO(), // SPI 0 MOSI out , output
.EMIOSPI0MOTN(), // SPI 0 MOSI OE, output
.EMIOSPI0MI(), // SPI 0 MISO in, input
.EMIOSPI0SO(), // SPI 0 MISO out, output
.EMIOSPI0STN(), // SPI 0 MISO OE, output
.EMIOSPI0SSIN(), // SPI 0 Slave select 0 in, input
.EMIOSPI0SSON(), // SPI 0 Slave select [2:0] out, output
.EMIOSPI0SSNTN(), // SPI 0 Slave select OE, output
// SPI 1
.EMIOSPI1SCLKI(), // SPI 1 CLK in , input
.EMIOSPI1SCLKO(), // SPI 1 CLK out, output
.EMIOSPI1SCLKTN(), // SPI 1 CLK OE, output
.EMIOSPI1SI(), // SPI 1 MOSI in , input
.EMIOSPI1MO(), // SPI 1 MOSI out , output
.EMIOSPI1MOTN(), // SPI 1 MOSI OE, output
.EMIOSPI1MI(), // SPI 1 MISO in, input
.EMIOSPI1SO(), // SPI 1 MISO out, output
.EMIOSPI1STN(), // SPI 1 MISO OE, output
.EMIOSPI1SSIN(), // SPI 1 Slave select 0 in, input
.EMIOSPI1SSON(), // SPI 1 Slave select [2:0] out, output
.EMIOSPI1SSNTN(), // SPI 1 Slave select OE, output
// TPIU signals (Trace)
.EMIOTRACECTL(), // Trace CTL, output
.EMIOTRACEDATA(), // Trace Data[31:0], output
.EMIOTRACECLK(), // Trace CLK, input
// Timers/counters
.EMIOTTC0CLKI(), // Counter/Timer 0 clock in [2:0], input
.EMIOTTC0WAVEO(), // Counter/Timer 0 wave out[2:0], output
.EMIOTTC1CLKI(), // Counter/Timer 1 clock in [2:0], input
.EMIOTTC1WAVEO(), // Counter/Timer 1 wave out[2:0], output
//UART 0
.EMIOUART0TX(), // UART 0 Transmit, output
.EMIOUART0RX(), // UART 0 Receive, input
.EMIOUART0CTSN(), // UART 0 Clear To Send, input
.EMIOUART0RTSN(), // UART 0 Ready to Send, output
.EMIOUART0DSRN(), // UART 0 Data Set Ready , input
.EMIOUART0DCDN(), // UART 0 Data Carrier Detect, input
.EMIOUART0RIN(), // UART 0 Ring Indicator, input
.EMIOUART0DTRN(), // UART 0 Data Terminal Ready, output
//UART 1
.EMIOUART1TX(), // UART 1 Transmit, output
.EMIOUART1RX(), // UART 1 Receive, input
.EMIOUART1CTSN(), // UART 1 Clear To Send, input
.EMIOUART1RTSN(), // UART 1 Ready to Send, output
.EMIOUART1DSRN(), // UART 1 Data Set Ready , input
.EMIOUART1DCDN(), // UART 1 Data Carrier Detect, input
.EMIOUART1RIN(), // UART 1 Ring Indicator, input
.EMIOUART1DTRN(), // UART 1 Data Terminal Ready, output
// USB 0
.EMIOUSB0PORTINDCTL(), // USB 0 Port Indicator [1:0], output
.EMIOUSB0VBUSPWRFAULT(), // USB 0 Power Fault, input
.EMIOUSB0VBUSPWRSELECT(), // USB 0 Power Select, output
// USB 1
.EMIOUSB1PORTINDCTL(), // USB 1 Port Indicator [1:0], output
.EMIOUSB1VBUSPWRFAULT(), // USB 1 Power Fault, input
.EMIOUSB1VBUSPWRSELECT(), // USB 1 Power Select, output
// Watchdog Timer
.EMIOWDTCLKI(), // Watchdog Timer Clock in, input
.EMIOWDTRSTO(), // Watchdog Timer Reset out, output
// DMAC 0
.DMA0ACLK(), // DMAC 0 Clock, input
.DMA0DRVALID(), // DMAC 0 DMA Request Valid, input
.DMA0DRLAST(), // DMAC 0 DMA Request Last, input
.DMA0DRTYPE(), // DMAC 0 DMA Request Type [1:0] ()single/burst/ackn flush/reserved), input
.DMA0DRREADY(), // DMAC 0 DMA Request Ready, output
.DMA0DAVALID(), // DMAC 0 DMA Acknowledge Valid (DA_TYPE[1:0] valid), output
.DMA0DAREADY(), // DMAC 0 DMA Acknowledge (peripheral can accept DA_TYPE[1:0]), input
.DMA0DATYPE(), // DMAC 0 DMA Ackbowledge TYpe (completed single AXI, completed burst AXI, flush request), output
.DMA0RSTN(), // DMAC 0 RESET output (reserved, do not use), output
// DMAC 1
.DMA1ACLK(), // DMAC 1 Clock, input
.DMA1DRVALID(), // DMAC 1 DMA Request Valid, input
.DMA1DRLAST(), // DMAC 1 DMA Request Last, input
.DMA1DRTYPE(), // DMAC 1 DMA Request Type [1:0] ()single/burst/ackn flush/reserved), input
.DMA1DRREADY(), // DMAC 1 DMA Request Ready, output
.DMA1DAVALID(), // DMAC 1 DMA Acknowledge Valid (DA_TYPE[1:0] valid), output
.DMA1DAREADY(), // DMAC 1 DMA Acknowledge (peripheral can accept DA_TYPE[1:0]), input
.DMA1DATYPE(), // DMAC 1 DMA Ackbowledge TYpe (completed single AXI, completed burst AXI, flush request), output
.DMA1RSTN(), // DMAC 1 RESET output (reserved, do not use), output
// DMAC 2
.DMA2ACLK(), // DMAC 2 Clock, input
.DMA2DRVALID(), // DMAC 2 DMA Request Valid, input
.DMA2DRLAST(), // DMAC 2 DMA Request Last, input
.DMA2DRTYPE(), // DMAC 2 DMA Request Type [1:0] ()single/burst/ackn flush/reserved), input
.DMA2DRREADY(), // DMAC 2 DMA Request Ready, output
.DMA2DAVALID(), // DMAC 2 DMA Acknowledge Valid (DA_TYPE[1:0] valid), output
.DMA2DAREADY(), // DMAC 2 DMA Acknowledge (peripheral can accept DA_TYPE[1:0]), input
.DMA2DATYPE(), // DMAC 2 DMA Ackbowledge TYpe (completed single AXI, completed burst AXI, flush request), output
.DMA2RSTN(), // DMAC 2 RESET output (reserved, do not use), output
// DMAC 3
.DMA3ACLK(), // DMAC 3 Clock, input
.DMA3DRVALID(), // DMAC 3 DMA Request Valid, input
.DMA3DRLAST(), // DMAC 3 DMA Request Last, input
.DMA3DRTYPE(), // DMAC 3 DMA Request Type [1:0] ()single/burst/ackn flush/reserved), input
.DMA3DRREADY(), // DMAC 3 DMA Request Ready, output
.DMA3DAVALID(), // DMAC 3 DMA Acknowledge Valid (DA_TYPE[1:0] valid), output
.DMA3DAREADY(), // DMAC 3 DMA Acknowledge (peripheral can accept DA_TYPE[1:0]), input
.DMA3DATYPE(), // DMAC 3 DMA Ackbowledge TYpe (completed single AXI, completed burst AXI, flush request), output
.DMA3RSTN(), // DMAC 3 RESET output (reserved, do not use), output
// Interrupt signals
.IRQF2P({19'b0,irq}), // Interrupts, PL to PS [19:0], input
.IRQP2F(), // Interrupts, PS to PL [28:0], output
// Event Signals
.EVENTEVENTI(), // EVENT Wake up one or both CPU from WFE state, input
.EVENTEVENTO(), // EVENT Asserted when one of the COUs executed SEV instruction, output
.EVENTSTANDBYWFE(), // EVENT CPU standby mode [1:0], asserted when CPU is waiting for an event, output
.EVENTSTANDBYWFI(), // EVENT CPU standby mode [1:0], asserted when CPU is waiting for an interrupt, output
// PL Resets and clocks
.FCLKCLK(fclk[3:0]), // PL Clocks [3:0], output
.FCLKCLKTRIGN(), // PL Clock Throttle Control [3:0], input
.FCLKRESETN(frst[3:0]), // PL General purpose user reset [3:0], output (active low)
// Debug signals
.FTMTP2FDEBUG(), // Debug General purpose debug output [31:0], output
.FTMTF2PDEBUG(), // Debug General purpose debug input [31:0], input
.FTMTP2FTRIG(), // Debug Trigger PS to PL [3:0], output
.FTMTP2FTRIGACK(), // Debug Trigger PS to PL acknowledge[3:0], input
.FTMTF2PTRIG(), // Debug Trigger PL to PS [3:0], input
.FTMTF2PTRIGACK(), // Debug Trigger PL to PS acknowledge[3:0], output
.FTMDTRACEINCLOCK(), // Debug Trace PL to PS Clock, input
.FTMDTRACEINVALID(), // Debug Trace PL to PS Clock, data&id valid, input
.FTMDTRACEINDATA(), // Debug Trace PL to PS data [31:0], input
.FTMDTRACEINATID(), // Debug Trace PL to PS ID [3:0], input
// DDR Urgent
.DDRARB(), // DDR Urgent[3:0], input
// SRAM interrupt (on rising edge)
.EMIOSRAMINTIN(), // SRAM interrupt #50 shared with NAND busy, input
// AXI interfaces
.FPGAIDLEN(1'b1), //Idle PL AXI interfaces (active low), input
// AXI PS Master GP0
// AXI PS Master GP0: Clock, Reset
.MAXIGP0ACLK(/*axi_aclk*/), // AXI PS Master GP0 Clock , input
// .MAXIGP0ACLK(/*fclk[0]*/), // AXI PS Master GP0 Clock , input
// .MAXIGP0ACLK(/*~fclk[0]*/), // AXI PS Master GP0 Clock , input
// .MAXIGP0ACLK(/*axi_naclk*/), // AXI PS Master GP0 Clock , input
//
.MAXIGP0ARESETN(), // AXI PS Master GP0 Reset, output
// AXI PS Master GP0: Read Address
.MAXIGP0ARADDR (/*axi_araddr[31:0]*/), // AXI PS Master GP0 ARADDR[31:0], output
.MAXIGP0ARVALID (/*axi_arvalid*/), // AXI PS Master GP0 ARVALID, output
.MAXIGP0ARREADY (/*axi_arready*/), // AXI PS Master GP0 ARREADY, input
.MAXIGP0ARID (/*axi_arid[11:0]*/), // AXI PS Master GP0 ARID[11:0], output
.MAXIGP0ARLOCK (), // AXI PS Master GP0 ARLOCK[1:0], output
.MAXIGP0ARCACHE (),// AXI PS Master GP0 ARCACHE[3:0], output
.MAXIGP0ARPROT(), // AXI PS Master GP0 ARPROT[2:0], output
.MAXIGP0ARLEN (/*axi_arlen[3:0]*/), // AXI PS Master GP0 ARLEN[3:0], output
.MAXIGP0ARSIZE (/*axi_arsize[1:0]*/), // AXI PS Master GP0 ARSIZE[1:0], output
.MAXIGP0ARBURST (/*axi_arburst[1:0]*/),// AXI PS Master GP0 ARBURST[1:0], output
.MAXIGP0ARQOS (), // AXI PS Master GP0 ARQOS[3:0], output
// AXI PS Master GP0: Read Data
.MAXIGP0RDATA (/*axi_rdata[31:0]*/), // AXI PS Master GP0 RDATA[31:0], input
.MAXIGP0RVALID (/*axi_rvalid*/), // AXI PS Master GP0 RVALID, input
.MAXIGP0RREADY (/*axi_rready*/), // AXI PS Master GP0 RREADY, output
.MAXIGP0RID (/*axi_rid[11:0]*/), // AXI PS Master GP0 RID[11:0], input
.MAXIGP0RLAST (/*axi_rlast*/), // AXI PS Master GP0 RLAST, input
.MAXIGP0RRESP (/*axi_rresp[1:0]*/), // AXI PS Master GP0 RRESP[1:0], input
// AXI PS Master GP0: Write Address
.MAXIGP0AWADDR (/*axi_awaddr[31:0]*/), // AXI PS Master GP0 AWADDR[31:0], output
.MAXIGP0AWVALID (/*axi_awvalid*/), // AXI PS Master GP0 AWVALID, output
.MAXIGP0AWREADY (/*axi_awready*/), // AXI PS Master GP0 AWREADY, input
.MAXIGP0AWID (/*axi_awid[11:0]*/), // AXI PS Master GP0 AWID[11:0], output
.MAXIGP0AWLOCK (), // AXI PS Master GP0 AWLOCK[1:0], output
.MAXIGP0AWCACHE (),// AXI PS Master GP0 AWCACHE[3:0], output
.MAXIGP0AWPROT (), // AXI PS Master GP0 AWPROT[2:0], output
.MAXIGP0AWLEN (/*axi_awlen[3:0]*/), // AXI PS Master GP0 AWLEN[3:0], output
.MAXIGP0AWSIZE (/*axi_awsize[1:0]*/), // AXI PS Master GP0 AWSIZE[1:0], output
.MAXIGP0AWBURST (/*axi_awburst[1:0]*/),// AXI PS Master GP0 AWBURST[1:0], output
.MAXIGP0AWQOS (), // AXI PS Master GP0 AWQOS[3:0], output
// AXI PS Master GP0: Write Data
.MAXIGP0WDATA (/*axi_wdata[31:0]*/), // AXI PS Master GP0 WDATA[31:0], output
.MAXIGP0WVALID (/*axi_wvalid*/), // AXI PS Master GP0 WVALID, output
.MAXIGP0WREADY (/*axi_wready*/), // AXI PS Master GP0 WREADY, input
.MAXIGP0WID (/*axi_wid[11:0]*/), // AXI PS Master GP0 WID[11:0], output
.MAXIGP0WLAST (/*axi_wlast*/), // AXI PS Master GP0 WLAST, output
.MAXIGP0WSTRB (/*axi_wstb[3:0]*/), // AXI PS Master GP0 WSTRB[3:0], output
// AXI PS Master GP0: Write response
.MAXIGP0BVALID (/*axi_bvalid*/), // AXI PS Master GP0 BVALID, input
.MAXIGP0BREADY (/*axi_bready*/), // AXI PS Master GP0 BREADY, output
.MAXIGP0BID (/*axi_bid[11:0]*/), // AXI PS Master GP0 BID[11:0], input
.MAXIGP0BRESP (/*axi_bresp[1:0]*/), // AXI PS Master GP0 BRESP[1:0], input
// AXI PS Master GP1
// AXI PS Master GP1: Clock, Reset
.MAXIGP1ACLK (axi_aclk0), // AXI PS Master GP1 Clock , input
.MAXIGP1ARESETN (), // AXI PS Master GP1 Reset, output
// AXI PS Master GP1: Read Address
.MAXIGP1ARADDR (maxi1_araddr), // AXI PS Master GP1 ARADDR[31:0], output
.MAXIGP1ARVALID (maxi1_arvalid), // AXI PS Master GP1 ARVALID, output
.MAXIGP1ARREADY (maxi1_arready), // AXI PS Master GP1 ARREADY, input
.MAXIGP1ARID (maxi1_arid), // AXI PS Master GP1 ARID[11:0], output
.MAXIGP1ARLOCK (), // AXI PS Master GP1 ARLOCK[1:0], output
.MAXIGP1ARCACHE (), // AXI PS Master GP1 ARCACHE[3:0], output
.MAXIGP1ARPROT (), // AXI PS Master GP1 ARPROT[2:0], output
.MAXIGP1ARLEN (maxi1_arlen), // AXI PS Master GP1 ARLEN[3:0], output
.MAXIGP1ARSIZE (maxi1_arsize), // AXI PS Master GP1 ARSIZE[1:0], output
.MAXIGP1ARBURST (maxi1_arburst), // AXI PS Master GP1 ARBURST[1:0], output
.MAXIGP1ARQOS (), // AXI PS Master GP1 ARQOS[3:0], output
// AXI PS Master GP1: Read Data
.MAXIGP1RDATA (maxi1_rdata), // AXI PS Master GP1 RDATA[31:0], input
.MAXIGP1RVALID (maxi1_rvalid), // AXI PS Master GP1 RVALID, input
.MAXIGP1RREADY (maxi1_rready), // AXI PS Master GP1 RREADY, output
.MAXIGP1RID (maxi1_rid), // AXI PS Master GP1 RID[11:0], input
.MAXIGP1RLAST (maxi1_rlast), // AXI PS Master GP1 RLAST, input
.MAXIGP1RRESP (maxi1_rresp), // AXI PS Master GP1 RRESP[1:0], input
// AXI PS Master GP1: Write Address
.MAXIGP1AWADDR (maxi1_awaddr), // AXI PS Master GP1 AWADDR[31:0], output
.MAXIGP1AWVALID (maxi1_awvalid), // AXI PS Master GP1 AWVALID, output
.MAXIGP1AWREADY (maxi1_awready), // AXI PS Master GP1 AWREADY, input
.MAXIGP1AWID (maxi1_awid), // AXI PS Master GP1 AWID[11:0], output
.MAXIGP1AWLOCK (), // AXI PS Master GP1 AWLOCK[1:0], output
.MAXIGP1AWCACHE (), // AXI PS Master GP1 AWCACHE[3:0], output
.MAXIGP1AWPROT (), // AXI PS Master GP1 AWPROT[2:0], output
.MAXIGP1AWLEN (maxi1_awlen), // AXI PS Master GP1 AWLEN[3:0], output
.MAXIGP1AWSIZE (maxi1_awsize), // AXI PS Master GP1 AWSIZE[1:0], output
.MAXIGP1AWBURST (maxi1_awburst), // AXI PS Master GP1 AWBURST[1:0], output
.MAXIGP1AWQOS (), // AXI PS Master GP1 AWQOS[3:0], output
// AXI PS Master GP1: Write Data
.MAXIGP1WDATA (maxi1_wdata), // AXI PS Master GP1 WDATA[31:0], output
.MAXIGP1WVALID (maxi1_wvalid), // AXI PS Master GP1 WVALID, output
.MAXIGP1WREADY (maxi1_wready), // AXI PS Master GP1 WREADY, input
.MAXIGP1WID (maxi1_wid), // AXI PS Master GP1 WID[11:0], output
.MAXIGP1WLAST (maxi1_wlast), // AXI PS Master GP1 WLAST, output
.MAXIGP1WSTRB (maxi1_wstb), // AXI PS Master GP1 maxi1_wstb[3:0], output
// AXI PS Master GP1: Write response
.MAXIGP1BVALID (maxi1_bvalid), // AXI PS Master GP1 BVALID, input
.MAXIGP1BREADY (maxi1_bready), // AXI PS Master GP1 BREADY, output
.MAXIGP1BID (maxi1_bid), // AXI PS Master GP1 BID[11:0], input
.MAXIGP1BRESP (maxi1_bresp), // AXI PS Master GP1 BRESP[1:0], input
// AXI PS Slave GP0
// AXI PS Slave GP0: Clock, Reset
.SAXIGP0ACLK(), // AXI PS Slave GP0 Clock , input
.SAXIGP0ARESETN(), // AXI PS Slave GP0 Reset, output
// AXI PS Slave GP0: Read Address
.SAXIGP0ARADDR(), // AXI PS Slave GP0 ARADDR[31:0], input
.SAXIGP0ARVALID(), // AXI PS Slave GP0 ARVALID, input
.SAXIGP0ARREADY(), // AXI PS Slave GP0 ARREADY, output
.SAXIGP0ARID(), // AXI PS Slave GP0 ARID[5:0], input
.SAXIGP0ARLOCK(), // AXI PS Slave GP0 ARLOCK[1:0], input
.SAXIGP0ARCACHE(), // AXI PS Slave GP0 ARCACHE[3:0], input
.SAXIGP0ARPROT(), // AXI PS Slave GP0 ARPROT[2:0], input
.SAXIGP0ARLEN(), // AXI PS Slave GP0 ARLEN[3:0], input
.SAXIGP0ARSIZE(), // AXI PS Slave GP0 ARSIZE[1:0], input
.SAXIGP0ARBURST(), // AXI PS Slave GP0 ARBURST[1:0], input
.SAXIGP0ARQOS(), // AXI PS Slave GP0 ARQOS[3:0], input
// AXI PS Slave GP0: Read Data
.SAXIGP0RDATA(), // AXI PS Slave GP0 RDATA[31:0], output
.SAXIGP0RVALID(), // AXI PS Slave GP0 RVALID, output
.SAXIGP0RREADY(), // AXI PS Slave GP0 RREADY, input
.SAXIGP0RID(), // AXI PS Slave GP0 RID[5:0], output
.SAXIGP0RLAST(), // AXI PS Slave GP0 RLAST, output
.SAXIGP0RRESP(), // AXI PS Slave GP0 RRESP[1:0], output
// AXI PS Slave GP0: Write Address
.SAXIGP0AWADDR(), // AXI PS Slave GP0 AWADDR[31:0], input
.SAXIGP0AWVALID(), // AXI PS Slave GP0 AWVALID, input
.SAXIGP0AWREADY(), // AXI PS Slave GP0 AWREADY, output
.SAXIGP0AWID(), // AXI PS Slave GP0 AWID[5:0], input
.SAXIGP0AWLOCK(), // AXI PS Slave GP0 AWLOCK[1:0], input
.SAXIGP0AWCACHE(), // AXI PS Slave GP0 AWCACHE[3:0], input
.SAXIGP0AWPROT(), // AXI PS Slave GP0 AWPROT[2:0], input
.SAXIGP0AWLEN(), // AXI PS Slave GP0 AWLEN[3:0], input
.SAXIGP0AWSIZE(), // AXI PS Slave GP0 AWSIZE[1:0], input
.SAXIGP0AWBURST(), // AXI PS Slave GP0 AWBURST[1:0], input
.SAXIGP0AWQOS(), // AXI PS Slave GP0 AWQOS[3:0], input
// AXI PS Slave GP0: Write Data
.SAXIGP0WDATA(), // AXI PS Slave GP0 WDATA[31:0], input
.SAXIGP0WVALID(), // AXI PS Slave GP0 WVALID, input
.SAXIGP0WREADY(), // AXI PS Slave GP0 WREADY, output
.SAXIGP0WID(), // AXI PS Slave GP0 WID[5:0], input
.SAXIGP0WLAST(), // AXI PS Slave GP0 WLAST, input
.SAXIGP0WSTRB(), // AXI PS Slave GP0 WSTRB[3:0], input
// AXI PS Slave GP0: Write response
.SAXIGP0BVALID(), // AXI PS Slave GP0 BVALID, output
.SAXIGP0BREADY(), // AXI PS Slave GP0 BREADY, input
.SAXIGP0BID(), // AXI PS Slave GP0 BID[5:0], output //TODO: Update range !!!
.SAXIGP0BRESP(), // AXI PS Slave GP0 BRESP[1:0], output
// AXI PS Slave GP1
// AXI PS Slave GP1: Clock, Reset
.SAXIGP1ACLK(), // AXI PS Slave GP1 Clock , input
.SAXIGP1ARESETN(), // AXI PS Slave GP1 Reset, output
// AXI PS Slave GP1: Read Address
.SAXIGP1ARADDR(), // AXI PS Slave GP1 ARADDR[31:0], input
.SAXIGP1ARVALID(), // AXI PS Slave GP1 ARVALID, input
.SAXIGP1ARREADY(), // AXI PS Slave GP1 ARREADY, output
.SAXIGP1ARID(), // AXI PS Slave GP1 ARID[5:0], input
.SAXIGP1ARLOCK(), // AXI PS Slave GP1 ARLOCK[1:0], input
.SAXIGP1ARCACHE(), // AXI PS Slave GP1 ARCACHE[3:0], input
.SAXIGP1ARPROT(), // AXI PS Slave GP1 ARPROT[2:0], input
.SAXIGP1ARLEN(), // AXI PS Slave GP1 ARLEN[3:0], input
.SAXIGP1ARSIZE(), // AXI PS Slave GP1 ARSIZE[1:0], input
.SAXIGP1ARBURST(), // AXI PS Slave GP1 ARBURST[1:0], input
.SAXIGP1ARQOS(), // AXI PS Slave GP1 ARQOS[3:0], input
// AXI PS Slave GP1: Read Data
.SAXIGP1RDATA(), // AXI PS Slave GP1 RDATA[31:0], output
.SAXIGP1RVALID(), // AXI PS Slave GP1 RVALID, output
.SAXIGP1RREADY(), // AXI PS Slave GP1 RREADY, input
.SAXIGP1RID(), // AXI PS Slave GP1 RID[5:0], output
.SAXIGP1RLAST(), // AXI PS Slave GP1 RLAST, output
.SAXIGP1RRESP(), // AXI PS Slave GP1 RRESP[1:0], output
// AXI PS Slave GP1: Write Address
.SAXIGP1AWADDR(), // AXI PS Slave GP1 AWADDR[31:0], input
.SAXIGP1AWVALID(), // AXI PS Slave GP1 AWVALID, input
.SAXIGP1AWREADY(), // AXI PS Slave GP1 AWREADY, output
.SAXIGP1AWID(), // AXI PS Slave GP1 AWID[5:0], input
.SAXIGP1AWLOCK(), // AXI PS Slave GP1 AWLOCK[1:0], input
.SAXIGP1AWCACHE(), // AXI PS Slave GP1 AWCACHE[3:0], input
.SAXIGP1AWPROT(), // AXI PS Slave GP1 AWPROT[2:0], input
.SAXIGP1AWLEN(), // AXI PS Slave GP1 AWLEN[3:0], input
.SAXIGP1AWSIZE(), // AXI PS Slave GP1 AWSIZE[1:0], input
.SAXIGP1AWBURST(), // AXI PS Slave GP1 AWBURST[1:0], input
.SAXIGP1AWQOS(), // AXI PS Slave GP1 AWQOS[3:0], input
// AXI PS Slave GP1: Write Data
.SAXIGP1WDATA(), // AXI PS Slave GP1 WDATA[31:0], input
.SAXIGP1WVALID(), // AXI PS Slave GP1 WVALID, input
.SAXIGP1WREADY(), // AXI PS Slave GP1 WREADY, output
.SAXIGP1WID(), // AXI PS Slave GP1 WID[5:0], input
.SAXIGP1WLAST(), // AXI PS Slave GP1 WLAST, input
.SAXIGP1WSTRB(), // AXI PS Slave GP1 WSTRB[3:0], input
// AXI PS Slave GP1: Write response
.SAXIGP1BVALID(), // AXI PS Slave GP1 BVALID, output
.SAXIGP1BREADY(), // AXI PS Slave GP1 BREADY, input
.SAXIGP1BID(), // AXI PS Slave GP1 BID[5:0], output
.SAXIGP1BRESP(), // AXI PS Slave GP1 BRESP[1:0], output
// AXI PS Slave HP0
// AXI PS Slave HP0: Clock, Reset
.SAXIHP0ACLK(), // AXI PS Slave HP0 Clock , input
.SAXIHP0ARESETN(), // AXI PS Slave HP0 Reset, output
// AXI PS Slave HP0: Read Address
.SAXIHP0ARADDR(), // AXI PS Slave HP0 ARADDR[31:0], input
.SAXIHP0ARVALID(), // AXI PS Slave HP0 ARVALID, input
.SAXIHP0ARREADY(), // AXI PS Slave HP0 ARREADY, output
.SAXIHP0ARID(), // AXI PS Slave HP0 ARID[5:0], input
.SAXIHP0ARLOCK(), // AXI PS Slave HP0 ARLOCK[1:0], input
.SAXIHP0ARCACHE(), // AXI PS Slave HP0 ARCACHE[3:0], input
.SAXIHP0ARPROT(), // AXI PS Slave HP0 ARPROT[2:0], input
.SAXIHP0ARLEN(), // AXI PS Slave HP0 ARLEN[3:0], input
.SAXIHP0ARSIZE(), // AXI PS Slave HP0 ARSIZE[2:0], input
.SAXIHP0ARBURST(), // AXI PS Slave HP0 ARBURST[1:0], input
.SAXIHP0ARQOS(), // AXI PS Slave HP0 ARQOS[3:0], input
// AXI PS Slave HP0: Read Data
.SAXIHP0RDATA(), // AXI PS Slave HP0 RDATA[63:0], output
.SAXIHP0RVALID(), // AXI PS Slave HP0 RVALID, output
.SAXIHP0RREADY(), // AXI PS Slave HP0 RREADY, input
.SAXIHP0RID(), // AXI PS Slave HP0 RID[5:0], output
.SAXIHP0RLAST(), // AXI PS Slave HP0 RLAST, output
.SAXIHP0RRESP(), // AXI PS Slave HP0 RRESP[1:0], output
.SAXIHP0RCOUNT(), // AXI PS Slave HP0 RCOUNT[7:0], output
.SAXIHP0RACOUNT(), // AXI PS Slave HP0 RACOUNT[2:0], output
.SAXIHP0RDISSUECAP1EN(), // AXI PS Slave HP0 RDISSUECAP1EN, input
// AXI PS Slave HP0: Write Address
.SAXIHP0AWADDR(), // AXI PS Slave HP0 AWADDR[31:0], input
.SAXIHP0AWVALID(), // AXI PS Slave HP0 AWVALID, input
.SAXIHP0AWREADY(), // AXI PS Slave HP0 AWREADY, output
.SAXIHP0AWID(), // AXI PS Slave HP0 AWID[5:0], input
.SAXIHP0AWLOCK(), // AXI PS Slave HP0 AWLOCK[1:0], input
.SAXIHP0AWCACHE(), // AXI PS Slave HP0 AWCACHE[3:0], input
.SAXIHP0AWPROT(), // AXI PS Slave HP0 AWPROT[2:0], input
.SAXIHP0AWLEN(), // AXI PS Slave HP0 AWLEN[3:0], input
.SAXIHP0AWSIZE(), // AXI PS Slave HP0 AWSIZE[1:0], input
.SAXIHP0AWBURST(), // AXI PS Slave HP0 AWBURST[1:0], input
.SAXIHP0AWQOS(), // AXI PS Slave HP0 AWQOS[3:0], input
// AXI PS Slave HP0: Write Data
.SAXIHP0WDATA(), // AXI PS Slave HP0 WDATA[63:0], input
.SAXIHP0WVALID(), // AXI PS Slave HP0 WVALID, input
.SAXIHP0WREADY(), // AXI PS Slave HP0 WREADY, output
.SAXIHP0WID(), // AXI PS Slave HP0 WID[5:0], input
.SAXIHP0WLAST(), // AXI PS Slave HP0 WLAST, input
.SAXIHP0WSTRB(), // AXI PS Slave HP0 WSTRB[7:0], input
.SAXIHP0WCOUNT(), // AXI PS Slave HP0 WCOUNT[7:0], output
.SAXIHP0WACOUNT(), // AXI PS Slave HP0 WACOUNT[5:0], output
.SAXIHP0WRISSUECAP1EN(), // AXI PS Slave HP0 WRISSUECAP1EN, input
// AXI PS Slave HP0: Write response
.SAXIHP0BVALID(), // AXI PS Slave HP0 BVALID, output
.SAXIHP0BREADY(), // AXI PS Slave HP0 BREADY, input
.SAXIHP0BID(), // AXI PS Slave HP0 BID[5:0], output
.SAXIHP0BRESP(), // AXI PS Slave HP0 BRESP[1:0], output
// AXI PS Slave HP1
// AXI PS Slave 1: Clock, Reset
.SAXIHP1ACLK(), // AXI PS Slave HP1 Clock , input
.SAXIHP1ARESETN(), // AXI PS Slave HP1 Reset, output
// AXI PS Slave HP1: Read Address
.SAXIHP1ARADDR(), // AXI PS Slave HP1 ARADDR[31:0], input
.SAXIHP1ARVALID(), // AXI PS Slave HP1 ARVALID, input
.SAXIHP1ARREADY(), // AXI PS Slave HP1 ARREADY, output
.SAXIHP1ARID(), // AXI PS Slave HP1 ARID[5:0], input
.SAXIHP1ARLOCK(), // AXI PS Slave HP1 ARLOCK[1:0], input
.SAXIHP1ARCACHE(), // AXI PS Slave HP1 ARCACHE[3:0], input
.SAXIHP1ARPROT(), // AXI PS Slave HP1 ARPROT[2:0], input
.SAXIHP1ARLEN(), // AXI PS Slave HP1 ARLEN[3:0], input
.SAXIHP1ARSIZE(), // AXI PS Slave HP1 ARSIZE[2:0], input
.SAXIHP1ARBURST(), // AXI PS Slave HP1 ARBURST[1:0], input
.SAXIHP1ARQOS(), // AXI PS Slave HP1 ARQOS[3:0], input
// AXI PS Slave HP1: Read Data
.SAXIHP1RDATA(), // AXI PS Slave HP1 RDATA[63:0], output
.SAXIHP1RVALID(), // AXI PS Slave HP1 RVALID, output
.SAXIHP1RREADY(), // AXI PS Slave HP1 RREADY, input
.SAXIHP1RID(), // AXI PS Slave HP1 RID[5:0], output
.SAXIHP1RLAST(), // AXI PS Slave HP1 RLAST, output
.SAXIHP1RRESP(), // AXI PS Slave HP1 RRESP[1:0], output
.SAXIHP1RCOUNT(), // AXI PS Slave HP1 RCOUNT[7:0], output
.SAXIHP1RACOUNT(), // AXI PS Slave HP1 RACOUNT[2:0], output
.SAXIHP1RDISSUECAP1EN(), // AXI PS Slave HP1 RDISSUECAP1EN, input
// AXI PS Slave HP1: Write Address
.SAXIHP1AWADDR(), // AXI PS Slave HP1 AWADDR[31:0], input
.SAXIHP1AWVALID(), // AXI PS Slave HP1 AWVALID, input
.SAXIHP1AWREADY(), // AXI PS Slave HP1 AWREADY, output
.SAXIHP1AWID(), // AXI PS Slave HP1 AWID[5:0], input
.SAXIHP1AWLOCK(), // AXI PS Slave HP1 AWLOCK[1:0], input
.SAXIHP1AWCACHE(), // AXI PS Slave HP1 AWCACHE[3:0], input
.SAXIHP1AWPROT(), // AXI PS Slave HP1 AWPROT[2:0], input
.SAXIHP1AWLEN(), // AXI PS Slave HP1 AWLEN[3:0], input
.SAXIHP1AWSIZE(), // AXI PS Slave HP1 AWSIZE[1:0], input
.SAXIHP1AWBURST(), // AXI PS Slave HP1 AWBURST[1:0], input
.SAXIHP1AWQOS(), // AXI PS Slave HP1 AWQOS[3:0], input
// AXI PS Slave HP1: Write Data
.SAXIHP1WDATA(), // AXI PS Slave HP1 WDATA[63:0], input
.SAXIHP1WVALID(), // AXI PS Slave HP1 WVALID, input
.SAXIHP1WREADY(), // AXI PS Slave HP1 WREADY, output
.SAXIHP1WID(), // AXI PS Slave HP1 WID[5:0], input
.SAXIHP1WLAST(), // AXI PS Slave HP1 WLAST, input
.SAXIHP1WSTRB(), // AXI PS Slave HP1 WSTRB[7:0], input
.SAXIHP1WCOUNT(), // AXI PS Slave HP1 WCOUNT[7:0], output
.SAXIHP1WACOUNT(), // AXI PS Slave HP1 WACOUNT[5:0], output
.SAXIHP1WRISSUECAP1EN(), // AXI PS Slave HP1 WRISSUECAP1EN, input
// AXI PS Slave HP1: Write response
.SAXIHP1BVALID(), // AXI PS Slave HP1 BVALID, output
.SAXIHP1BREADY(), // AXI PS Slave HP1 BREADY, input
.SAXIHP1BID(), // AXI PS Slave HP1 BID[5:0], output
.SAXIHP1BRESP(), // AXI PS Slave HP1 BRESP[1:0], output
// AXI PS Slave HP2
// AXI PS Slave HP2: Clock, Reset
.SAXIHP2ACLK(), // AXI PS Slave HP2 Clock , input
.SAXIHP2ARESETN(), // AXI PS Slave HP2 Reset, output
// AXI PS Slave HP2: Read Address
.SAXIHP2ARADDR(), // AXI PS Slave HP2 ARADDR[31:0], input
.SAXIHP2ARVALID(), // AXI PS Slave HP2 ARVALID, input
.SAXIHP2ARREADY(), // AXI PS Slave HP2 ARREADY, output
.SAXIHP2ARID(), // AXI PS Slave HP2 ARID[5:0], input
.SAXIHP2ARLOCK(), // AXI PS Slave HP2 ARLOCK[1:0], input
.SAXIHP2ARCACHE(), // AXI PS Slave HP2 ARCACHE[3:0], input
.SAXIHP2ARPROT(), // AXI PS Slave HP2 ARPROT[2:0], input
.SAXIHP2ARLEN(), // AXI PS Slave HP2 ARLEN[3:0], input
.SAXIHP2ARSIZE(), // AXI PS Slave HP2 ARSIZE[2:0], input
.SAXIHP2ARBURST(), // AXI PS Slave HP2 ARBURST[1:0], input
.SAXIHP2ARQOS(), // AXI PS Slave HP2 ARQOS[3:0], input
// AXI PS Slave HP2: Read Data
.SAXIHP2RDATA(), // AXI PS Slave HP2 RDATA[63:0], output
.SAXIHP2RVALID(), // AXI PS Slave HP2 RVALID, output
.SAXIHP2RREADY(), // AXI PS Slave HP2 RREADY, input
.SAXIHP2RID(), // AXI PS Slave HP2 RID[5:0], output
.SAXIHP2RLAST(), // AXI PS Slave HP2 RLAST, output
.SAXIHP2RRESP(), // AXI PS Slave HP2 RRESP[1:0], output
.SAXIHP2RCOUNT(), // AXI PS Slave HP2 RCOUNT[7:0], output
.SAXIHP2RACOUNT(), // AXI PS Slave HP2 RACOUNT[2:0], output
.SAXIHP2RDISSUECAP1EN(), // AXI PS Slave HP2 RDISSUECAP1EN, input
// AXI PS Slave HP2: Write Address
.SAXIHP2AWADDR(), // AXI PS Slave HP2 AWADDR[31:0], input
.SAXIHP2AWVALID(), // AXI PS Slave HP2 AWVALID, input
.SAXIHP2AWREADY(), // AXI PS Slave HP2 AWREADY, output
.SAXIHP2AWID(), // AXI PS Slave HP2 AWID[5:0], input
.SAXIHP2AWLOCK(), // AXI PS Slave HP2 AWLOCK[1:0], input
.SAXIHP2AWCACHE(), // AXI PS Slave HP2 AWCACHE[3:0], input
.SAXIHP2AWPROT(), // AXI PS Slave HP2 AWPROT[2:0], input
.SAXIHP2AWLEN(), // AXI PS Slave HP2 AWLEN[3:0], input
.SAXIHP2AWSIZE(), // AXI PS Slave HP2 AWSIZE[1:0], input
.SAXIHP2AWBURST(), // AXI PS Slave HP2 AWBURST[1:0], input
.SAXIHP2AWQOS(), // AXI PS Slave HP2 AWQOS[3:0], input
// AXI PS Slave HP2: Write Data
.SAXIHP2WDATA(), // AXI PS Slave HP2 WDATA[63:0], input
.SAXIHP2WVALID(), // AXI PS Slave HP2 WVALID, input
.SAXIHP2WREADY(), // AXI PS Slave HP2 WREADY, output
.SAXIHP2WID(), // AXI PS Slave HP2 WID[5:0], input
.SAXIHP2WLAST(), // AXI PS Slave HP2 WLAST, input
.SAXIHP2WSTRB(), // AXI PS Slave HP2 WSTRB[7:0], input
.SAXIHP2WCOUNT(), // AXI PS Slave HP2 WCOUNT[7:0], output
.SAXIHP2WACOUNT(), // AXI PS Slave HP2 WACOUNT[5:0], output
.SAXIHP2WRISSUECAP1EN(), // AXI PS Slave HP2 WRISSUECAP1EN, input
// AXI PS Slave HP2: Write response
.SAXIHP2BVALID(), // AXI PS Slave HP2 BVALID, output
.SAXIHP2BREADY(), // AXI PS Slave HP2 BREADY, input
.SAXIHP2BID(), // AXI PS Slave HP2 BID[5:0], output
.SAXIHP2BRESP(), // AXI PS Slave HP2 BRESP[1:0], output
// AXI PS Slave HP3
// AXI PS Slave HP3: Clock, Reset
.SAXIHP3ACLK (hclk), // AXI PS Slave HP3 Clock , input
.SAXIHP3ARESETN(), // AXI PS Slave HP3 Reset, output
// AXI PS Slave HP3: Read Address
.SAXIHP3ARADDR (afi3_araddr), // AXI PS Slave HP3 ARADDR[31:0], input
.SAXIHP3ARVALID (afi3_arvalid), // AXI PS Slave HP3 ARVALID, input
.SAXIHP3ARREADY (afi3_arready), // AXI PS Slave HP3 ARREADY, output
.SAXIHP3ARID (afi3_arid), // AXI PS Slave HP3 ARID[5:0], input
.SAXIHP3ARLOCK (afi3_arlock), // AXI PS Slave HP3 ARLOCK[1:0], input
.SAXIHP3ARCACHE (afi3_arcache), // AXI PS Slave HP3 ARCACHE[3:0], input
.SAXIHP3ARPROT (afi3_arprot), // AXI PS Slave HP3 ARPROT[2:0], input
.SAXIHP3ARLEN (afi3_arlen), // AXI PS Slave HP3 ARLEN[3:0], input
.SAXIHP3ARSIZE (afi3_arsize), // AXI PS Slave HP3 ARSIZE[2:0], input
.SAXIHP3ARBURST (afi3_arburst), // AXI PS Slave HP3 ARBURST[1:0], input
.SAXIHP3ARQOS (afi3_arqos), // AXI PS Slave HP3 ARQOS[3:0], input
// AXI PS Slave HP3: Read Data
.SAXIHP3RDATA (afi3_rdata), // AXI PS Slave HP3 RDATA[63:0], output
.SAXIHP3RVALID (afi3_rvalid), // AXI PS Slave HP3 RVALID, output
.SAXIHP3RREADY (afi3_rready), // AXI PS Slave HP3 RREADY, input
.SAXIHP3RID (afi3_rid), // AXI PS Slave HP3 RID[5:0], output
.SAXIHP3RLAST (afi3_rlast), // AXI PS Slave HP3 RLAST, output
.SAXIHP3RRESP (afi3_rresp), // AXI PS Slave HP3 RRESP[1:0], output
.SAXIHP3RCOUNT (afi3_rcount), // AXI PS Slave HP3 RCOUNT[7:0], output
.SAXIHP3RACOUNT (afi3_racount), // AXI PS Slave HP3 RACOUNT[2:0], output
.SAXIHP3RDISSUECAP1EN (afi3_rdissuecap1en), // AXI PS Slave HP3 RDISSUECAP1EN, input
// AXI PS Slave HP3: Write Address
.SAXIHP3AWADDR (afi3_awaddr), // AXI PS Slave HP3 AWADDR[31:0], input
.SAXIHP3AWVALID (afi3_awvalid), // AXI PS Slave HP3 AWVALID, input
.SAXIHP3AWREADY (afi3_awready), // AXI PS Slave HP3 AWREADY, output
.SAXIHP3AWID (afi3_awid), // AXI PS Slave HP3 AWID[5:0], input
.SAXIHP3AWLOCK (afi3_awlock), // AXI PS Slave HP3 AWLOCK[1:0], input
.SAXIHP3AWCACHE (afi3_awcache), // AXI PS Slave HP3 AWCACHE[3:0], input
.SAXIHP3AWPROT (afi3_awprot), // AXI PS Slave HP3 AWPROT[2:0], input
.SAXIHP3AWLEN (afi3_awlen), // AXI PS Slave HP3 AWLEN[3:0], input
.SAXIHP3AWSIZE (afi3_awsize), // AXI PS Slave HP3 AWSIZE[1:0], input
.SAXIHP3AWBURST (afi3_awburst), // AXI PS Slave HP3 AWBURST[1:0], input
.SAXIHP3AWQOS (afi3_awqos), // AXI PS Slave HP3 AWQOS[3:0], input
// AXI PS Slave HP3: Write Data
.SAXIHP3WDATA (afi3_wdata), // AXI PS Slave HP3 WDATA[63:0], input
.SAXIHP3WVALID (afi3_wvalid), // AXI PS Slave HP3 WVALID, input
.SAXIHP3WREADY (afi3_wready), // AXI PS Slave HP3 WREADY, output
.SAXIHP3WID (afi3_wid), // AXI PS Slave HP3 WID[5:0], input
.SAXIHP3WLAST (afi3_wlast), // AXI PS Slave HP3 WLAST, input
.SAXIHP3WSTRB (afi3_wstrb), // AXI PS Slave HP3 WSTRB[7:0], input
.SAXIHP3WCOUNT (afi3_wcount), // AXI PS Slave HP3 WCOUNT[7:0], output
.SAXIHP3WACOUNT (afi3_wacount), // AXI PS Slave HP3 WACOUNT[5:0], output
.SAXIHP3WRISSUECAP1EN (afi3_wrissuecap1en), // AXI PS Slave HP3 WRISSUECAP1EN, input
// AXI PS Slave HP3: Write response
.SAXIHP3BVALID (afi3_bvalid), // AXI PS Slave HP3 BVALID, output
.SAXIHP3BREADY (afi3_bready), // AXI PS Slave HP3 BREADY, input
.SAXIHP3BID (afi3_bid), // AXI PS Slave HP3 BID[5:0], output
.SAXIHP3BRESP (afi3_bresp), // AXI PS Slave HP3 BRESP[1:0], output
// AXI PS Slave ACP
// AXI PS Slave ACP: Clock, Reset
.SAXIACPACLK(), // AXI PS Slave ACP Clock, input
.SAXIACPARESETN(), // AXI PS Slave ACP Reset, output
// AXI PS Slave ACP: Read Address
.SAXIACPARADDR(), // AXI PS Slave ACP ARADDR[31:0], input
.SAXIACPARVALID(), // AXI PS Slave ACP ARVALID, input
.SAXIACPARREADY(), // AXI PS Slave ACP ARREADY, output
.SAXIACPARID(), // AXI PS Slave ACP ARID[2:0], input
.SAXIACPARLOCK(), // AXI PS Slave ACP ARLOCK[1:0], input
.SAXIACPARCACHE(), // AXI PS Slave ACP ARCACHE[3:0], input
.SAXIACPARPROT(), // AXI PS Slave ACP ARPROT[2:0], input
.SAXIACPARLEN(), // AXI PS Slave ACP ARLEN[3:0], input
.SAXIACPARSIZE(), // AXI PS Slave ACP ARSIZE[2:0], input
.SAXIACPARBURST(), // AXI PS Slave ACP ARBURST[1:0], input
.SAXIACPARQOS(), // AXI PS Slave ACP ARQOS[3:0], input
.SAXIACPARUSER(), // AXI PS Slave ACP ARUSER[4:0], input
// AXI PS Slave ACP: Read Data
.SAXIACPRDATA(), // AXI PS Slave ACP RDATA[63:0], output
.SAXIACPRVALID(), // AXI PS Slave ACP RVALID, output
.SAXIACPRREADY(), // AXI PS Slave ACP RREADY, input
.SAXIACPRID(), // AXI PS Slave ACP RID[2:0], output
.SAXIACPRLAST(), // AXI PS Slave ACP RLAST, output
.SAXIACPRRESP(), // AXI PS Slave ACP RRESP[1:0], output
// AXI PS Slave ACP: Write Address
.SAXIACPAWADDR(), // AXI PS Slave ACP AWADDR[31:0], input
.SAXIACPAWVALID(), // AXI PS Slave ACP AWVALID, input
.SAXIACPAWREADY(), // AXI PS Slave ACP AWREADY, output
.SAXIACPAWID(), // AXI PS Slave ACP AWID[2:0], input
.SAXIACPAWLOCK(), // AXI PS Slave ACP AWLOCK[1:0], input
.SAXIACPAWCACHE(), // AXI PS Slave ACP AWCACHE[3:0], input
.SAXIACPAWPROT(), // AXI PS Slave ACP AWPROT[2:0], input
.SAXIACPAWLEN(), // AXI PS Slave ACP AWLEN[3:0], input
.SAXIACPAWSIZE(), // AXI PS Slave ACP AWSIZE[1:0], input
.SAXIACPAWBURST(), // AXI PS Slave ACP AWBURST[1:0], input
.SAXIACPAWQOS(), // AXI PS Slave ACP AWQOS[3:0], input
.SAXIACPAWUSER(), // AXI PS Slave ACP AWUSER[4:0], input
// AXI PS Slave ACP: Write Data
.SAXIACPWDATA(), // AXI PS Slave ACP WDATA[63:0], input
.SAXIACPWVALID(), // AXI PS Slave ACP WVALID, input
.SAXIACPWREADY(), // AXI PS Slave ACP WREADY, output
.SAXIACPWID(), // AXI PS Slave ACP WID[2:0], input
.SAXIACPWLAST(), // AXI PS Slave ACP WLAST, input
.SAXIACPWSTRB(), // AXI PS Slave ACP WSTRB[7:0], input
// AXI PS Slave ACP: Write response
.SAXIACPBVALID(), // AXI PS Slave ACP BVALID, output
.SAXIACPBREADY(), // AXI PS Slave ACP BREADY, input
.SAXIACPBID(), // AXI PS Slave ACP BID[2:0], output
.SAXIACPBRESP(), // AXI PS Slave ACP BRESP[1:0], output
// Direct connection to PS package pads
.DDRA(), // PS DDRA[14:0], inout
.DDRBA(), // PS DDRBA[2:0], inout
.DDRCASB(), // PS DDRCASB, inout
.DDRCKE(), // PS DDRCKE, inout
.DDRCKP(), // PS DDRCKP, inout
.DDRCKN(), // PS DDRCKN, inout
.DDRCSB(), // PS DDRCSB, inout
.DDRDM(), // PS DDRDM[3:0], inout
.DDRDQ(), // PS DDRDQ[31:0], inout
.DDRDQSP(), // PS DDRDQSP[3:0], inout
.DDRDQSN(), // PS DDRDQSN[3:0], inout
.DDRDRSTB(), // PS DDRDRSTB, inout
.DDRODT(), // PS DDRODT, inout
.DDRRASB(), // PS DDRRASB, inout
.DDRVRN(), // PS DDRVRN, inout
.DDRVRP(), // PS DDRVRP, inout
.DDRWEB(), // PS DDRWEB, inout
.MIO(), // PS MIO[53:0], inout // clg225 has less
.PSCLK(), // PS PSCLK, inout
.PSPORB(), // PS PSPORB, inout
.PSSRSTB() // PS PSSRSTB, inout
);
endmodule
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import division
# Copyright (C) 2015, Elphel.inc.
# Helper module create AHCI registers type/default data
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2015, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
import sys
# All unspecified ranges/fields default to fT:RO, fC:0 (readonly, reset value = 0)
RID = 0x02 # Revision ID (use for bitstream version)
VID = 0xfffe # What to use for non-PCI "vendorID"?
DID = 0x0001
SSVID = 0xfffe
SSID = 0x0001
IPIN = 0x01 # TODO: Put a real number for "Interrupt pin"
ILINE = 0x00 # Interrupt line - software is supposed to fill it - maybe here we need to put some predefined value?
HBA_OFFS = 0x0 # All offsets are in bytes
CLB_OFFS = 0x800 # In the second half of the register space (0x800..0xbff - 1KB)
FB_OFFS = 0xc00 # Needs 0x100 bytes
#HBA_PORT0 = 0x100 Not needed, always HBA_OFFS + 0x100
PCIHEAD = 0x180
PMCAP = 0x1C0
AXI_BASEADDR = 0x80000000
reg_defaults_path= "../includes/ahci_defaults.vh"
reg_types_path= "../includes/ahci_types.vh"
localparams_path= "../includes/ahci_localparams.vh"
gN = "groupName"
gS = "groupStart"
gE = "groupEnd"
gD = "groupDescription"
gC = "groupContent"
rN = "rangeName" # byte/word/dword
rS = "rangeStart" # in bytes relative to the Group start
rE = "rangeEnd" # in bytes relative to the Group start
rD = "rangeDescription"
rC = "rangeContent"
fN = "fieldName"
fL = "fieldOffsetLow" # if any of fL, fH is absent, it is assumed to be equal to the other, if both - to the full range
fH = "fieldOffsetHigh"
fS = "fieldSize"
fE = "fieldEnd"
fD = "fieldDescription"
fC = "fieldContent"
fT = "fieldType"
RW = "RW"
RO= "RO"
RWC = "RWC"
RW1 = "RW1"
ABAR = AXI_BASEADDR + HBA_OFFS
# Second half of the 4KB register memory does not have RO/RW/RWC/RW1 capability (just RW), but has a single-cycle write access
#Keeping CLB and received FIS reduces number of required DMA transfer types - just reading PRDs and Read/Write DMA data
P0CLB = AXI_BASEADDR + CLB_OFFS # Port 0 CLB address - keep in HBA internal memory
P0FB = AXI_BASEADDR + FB_OFFS # Port 0 received FIS address - keep in HBA internal memory
#reg_defaults = [0]*4096 # array of bytes, default value = 0
#bit_types = [0]*2048 # array of words, default value = 0
src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation with no PCI",gC:
[{rN:"ID", rS:0x0, rE:0x3, rD:"Identifiers", rC:
[{fN:"DID", fS:16, fE:31, fT:RO, fC:DID, fD:"Device ID"},
{fN:"VID", fS:0, fE:15, fT:RO, fC:VID, fD:"Vendor ID"}]},
{rN:"CMD", rS:0x04, rE:0x5, rD:"Command Register", rC:
[{fS:11, fE:15, fT:RO, fC:0}, # reserved
{fN:"ID", fS:10, fT:RW, fC:0, fD:"HBA Interrupt Disable"},
{fN:"FBE", fS: 9, fT:RO, fC:0, fD:"Fast Back-to-Back Enable"},
{fN:"SEE", fS: 8, fT:RO, fC:0, fD:"SERR Enable"},
{fN:"WCC", fS: 7, fT:RO, fC:0, fD:"Reserved"},
{fN:"PEE", fS: 6, fT:RO, fC:0, fD:"Parity Error Response Enable"},
{fN:"VGA", fS: 5, fT:RO, fC:0, fD:"Reserved"},
{fN:"MWIE",fS: 4, fT:RO, fC:0, fD:"Reserved"},
{fN:"SCE", fS: 3, fT:RO, fC:0, fD:"Reserved"},
{fN:"BME", fS: 2, fT:RW, fC:0, fD:"Bus Master Enable (0 - stops any DMA)"},
{fN:"MSE", fS: 1, fT:RW, fC:0, fD:"Memory Space enable (here - always?)"},
{fN:"IOSE",fS: 0, fT:RO, fC:0, fD:"Enable IO space access (only for legacy IDE)"}]},
{rN:"STS", rS:0x06, rE:0x7, rD:"Device Status", rC:
[{fN:"DPE", fS:15, fT:RWC, fC:0, fD:"Detected Parity Error"},
{fN:"SSE", fS:14, fT:RWC, fC:0, fD:"Signaled System Error (HBA SERR)"},
{fN:"RMA", fS:13, fT:RWC, fC:0, fD:"Received Master Abort"},
{fN:"RTA", fS:12, fT:RWC, fC:0, fD:"Received Target Abort"},
{fN:"STA", fS:11, fT:RWC, fC:0, fD:"Signaled Target Abort"},
{fN:"DEVT",fS: 9, fE:10, fT:RO, fC:0, fD:"PCI DEVSEL Timing"},
{fN:"DPD", fS: 8, fT:RWC, fC:0, fD:"Master Data Parity Error Detected"},
{fN:"FBC", fS: 7, fT:RO, fC:0, fD:"Fast Back-To-Back Capable"},
{ fS: 6, fT:RO, fC:0, fD:"Reserved"},
{fN:"C66", fS: 5, fT:RO, fC:0, fD:"66 MHz Capable"},
{fN:"CL", fS: 4, fT:RO, fC:1, fD:"Capabilities List (PCI power management mandatory)"},
{fN:"IS", fS: 3, fT:RO, fC:0, fD:"Interrupt Status (1 - asserted)"},
{ fS: 0, fE:2, fT:RO, fC:0, fD:"Reserved"}]},
{rN:"RID", rS:0x08, rD:"HBA Revision ID", rC:
[{fN:"RID", fT:RO, fC:RID, fD:"HBA Revision ID"}]},
{rN:"CC", rS:0x09, rE:0x0b, rD:"Class Code", rC:
[{fN:"BCC", fS:16, fE:23, fT:RO, fC:1, fD:"Base Class Code: 1 - Mass Storage Device"},
{fN:"SCC", fS: 8, fE:15, fT:RO, fC:6, fD:"Sub Class Code: 0x06 - SATA Device"},
{fN:"PI", fS: 8, fE:15, fT:RO, fC:1, fD:"Programming Interface: 1 - AHCI HBA major rev 1"}]},
{rN:"CLS", rS:0x0c, rD:"Cache Line Size", rC:
[{fN:"CLS", fT:RW, fC:0, fD:"Cache Line Size"}]},
{rN:"MLT", rS:0x0d, rD:"Master Latency Timer", rC:
[{fN:"MLT", fT:RW, fC:0, fD:"Master Latency Timer"}]},
{rN:"HTYPE", rS:0x0d, rD:"Header Type", rC:
[{fN:"MFDT",fS:7, fT:RO, fC:0, fD:"Multi-Function Device"},
{fN:"HL", fS: 0, fE:6, fT:RO, fC:0, fD:"Header Layout 0 - HBA uses a target device layout"}]},
#Offsets 0x10..0x23 - other BARs (optional)
{rN:"ABAR", rS:0x24, rE:0x27, rD:"AHCI Base Address", rC:
[{fN:"BA", fS: 4, fE:31, fT:RO, fC:(ABAR >> 4), fD:"AHCI Base Address high bits, normally RW, but here RO to get to MAXIGP1 space"},
{fN:"PF", fS: 3, fT:RO, fC:0, fD:"Prefetchable (this is not)"},
{fN:"TP", fS: 1, fE:2, fT:RO, fC:0, fD:"Type (0 - any 32-bit address, here it is hard-mapped"},
{fN:"RTE", fS: 0, fT:RO, fC:0, fD:"Resource Type Indicator: 0 - memory address"}]},
# 0x28.0x2b skipped
{rN:"SS", rS:0x2c, rE:0x2f, rD:"Sub System identifiers", rC:
[{fN:"SSID", fS:16, fE:31, fT:RO, fC:SSID, fD:"SubSystem ID"},
{fN:"SSVID", fS:0, fE:15, fT:RO, fC:SSVID,fD:"SubSystem Vendor ID"}]},
{rN:"EROM", rS:0x30, rE:0x33, rD:"Extension ROM (optional)", rC:
[{fN:"RBA", fT:RO, fC:0, fD:"ROM Base Address"}]},
{rN:"CAP", rS:0x34, rD:"Capabilities Pointer", rC:
[{fN:"CAP", fT:RO, fC:(PMCAP-PCIHEAD), fD:"Capabilities pointer"}]},
#0x35-0x3b are reserved
{rN:"INTR", rS:0x3c, rE:0x3d, rD:"Interrupt Information", rC:
[{fN:"IPIN", fS: 8, fE:15, fT:RO, fC:IPIN, fD:"Interrupt pin"},
{fN:"ILINE", fS: 0, fE: 7, fT:RW, fC:ILINE,fD:"Interrupt Line"}]},
{rN:"MGNT", rS:0x3e, rD:"Minimal Grant (optional)", rC:
[{fN:"MGNT", fT:RO, fC:0, fD:"Minimal Grant"}]},
{rN:"MLAT", rS:0x3f, rD:"Maximal Latency (optional)", rC:
[{fN:"MLAT", fT:RO, fC:0, fD:"Maximal Latency"}]}
]}, # End of "PCI_Header" group
{gN:"PMCAP", gS: PMCAP, gE:PMCAP+0x7, gD:"Power Management Capability",gC:
[{rN:"PID", rS:0x0, rE:0x1, rD:"PCI Power Management Capability ID", rC:
[{fN:"NEXT", fS: 8, fE:15, fT:RO, fC:0, fD:"Next Capability pointer"},
{fN:"CID", fS: 0, fE: 7, fT:RO, fC:1, fD:"This is PCI Power Management Capability"}]},
{rN:"PC", rS:0x2, rE:0x3, rD:"Power Management Capabilities", rC:
[{fN:"PSUP", fS:11, fE:15, fT:RO, fC:8, fD:"PME_SUPPORT bits:'b01000"},
{fN:"D2S", fS:10, fT:RO, fC:0, fD:"D2 Support - no"},
{fN:"D1S", fS: 9, fT:RO, fC:0, fD:"D1 Support - no"},
{fN:"AUXC", fS: 6, fE: 8, fT:RO, fC:0, fD:"Maximal D3cold current"},
{fN:"DSI", fS: 5, fT:RO, fC:0, fD:"Device-specific initialization required"}, #Use it?
{ fS: 4, fT:RO, fC:0, fD:"Reserved"},
{fN:"PMEC", fS: 3, fT:RO, fC:0, fD:"PCI clock required to generate PME"},
{fN:"VS", fS: 0, fE: 2, fT:RO, fC:0, fD:"Revision of Power Management Specification support version"}]},
{rN:"PMCS", rS:0x4, rE:0x5, rD:"Power Management Control and Status", rC:
[{fN:"PMES", fS:15, fT:RWC,fC:0, fD:"PME Status, set by hardware when HBA generates PME"},
{ fS: 9, fE:14, fT:RO, fC:0, fD:"Reserved: AHCI HBA Does not implement data register"},
{fN:"PMEE", fS: 8, fT:RW, fC:0, fD:"PME Enable"},
{ fS: 2, fE: 7, fT:RO, fC:0, fD:"Reserved"},
{fN:"PS", fS: 0, fE: 1, fT:RW, fC:0, fD:"Power State"}]},
]},
{gN:"GHC", gS: HBA_OFFS, gE:HBA_OFFS + 0x2b, gD:"HBA Generic Host Control",gC:
[{rN:"CAP", rS:0x0, rE:0x03, rD:"HBA Capabilities", rC:
[{fN:"S64A", fS:31, fT:RO, fC:0, fD:"Supports 64-bit Addressing - no"},
{fN:"SNCQ", fS:30, fT:RO, fC:0, fD:"Supports Native Command Queuing - no"},
{fN:"SSNTF", fS:29, fT:RO, fC:0, fD:"Supports SNotification Register - no"},
{fN:"SMPS", fS:28, fT:RO, fC:0, fD:"Supports Mechanical Presence Switch - no"},
{fN:"SSS", fS:27, fT:RO, fC:0, fD:"Supports Staggered Spin-up - no"},
{fN:"SALP", fS:26, fT:RO, fC:0, fD:"Supports Aggressive Link Power Management - no"},
{fN:"SAL", fS:25, fT:RO, fC:0, fD:"Supports Activity LED - no"},
{fN:"SCLO", fS:24, fT:RO, fC:0, fD:"Supports Command List Override - no (not capable of clearing BSY and DRQ bits, needs soft reset"},
{fN:"ISS", fS:20, fE:23, fT:RO, fC:2, fD:"Interface Maximal speed: 2 - Gen2, 3 - Gen3"},
{ fS:19, fT:RO, fC:0, fD:"Reserved"},
{fN:"SAM", fS:18, fT:RO, fC:1, fD:"AHCI only (0 - legacy too)"},
{fN:"SPM", fS:17, fT:RO, fC:0, fD:"Supports Port Multiplier - no"},
{fN:"FBSS", fS:16, fT:RO, fC:0, fD:"Supports FIS-based switching of the Port Multiplier - no"},
{fN:"PMD", fS:15, fT:RO, fC:0, fD:"PIO Multiple DRQ block - no"},
{fN:"SSC", fS:14, fT:RO, fC:0, fD:"Slumber State Capable - no"},
{fN:"PSC", fS:13, fT:RO, fC:0, fD:"Partial State Capable - no"},
{fN:"NSC", fS: 8, fE:12, fT:RO, fC:0, fD:"Number of Command Slots, 0-based (0 means 1?)"},
{fN:"CCCS", fS: 7, fT:RO, fC:0, fD:"Command Completion Coalescing - no"},
{fN:"EMS", fS: 6, fT:RO, fC:0, fD:"Enclosure Management - no"},
{fN:"SXS", fS: 5, fT:RO, fC:1, fD:"External SATA connector - yes"},
{fN:"NP", fS: 0, fE: 4, fT:RO, fC:0, fD:"Number of Ports, 0-based (0 means 1?)"}]},
{rN:"GHC", rS:0x4, rE:0x07, rD:"Global HBA Control", rC:
[{fN:"AE", fS:31, fT:RO, fC:1, fD:"AHCI enable (0 - legacy)"},
{ fS: 3, fE:30, fT:RO, fC:0, fD:"Reserved"},
{fN:"MRSM", fS: 2, fT:RO, fC:0, fD:"MSI Revert to Single Message"},
{fN:"IE", fS: 1, fT:RW, fC:0, fD:"Interrupt Enable (all ports)"},
{fN:"HR", fS: 0, fT:RW1,fC:0, fD:"HBA reset (COMINIT, ...). Set by software, cleared by hardware, section 10.4.3"}]},
{rN:"IS", rS:0x08, rE:0x0b, rD:"Interrupt Status Register", rC:
[{fN:"IPS", fT:RWC,fC:0, fD:"Interrupt Pending Status (per port)"}]},
{rN:"PI", rS:0x0c, rE:0x0f, rD:"Interrupt Status Register", rC:
[{fN:"PI", fT:RO, fC:1, fD:"Ports Implemented"}]},
{rN:"VS", rS:0x10, rE:0x13, rD:"AHCI Version", rC:
[{fN:"MJR", fS:16, fE:31, fT:RO, fC:0x0001, fD:"AHCI Major Version 1."},
{fN:"MNR", fS: 0, fE:15, fT:RO, fC:0x0301, fD:"AHCI Minor Version 3.1"}]},
{rN:"CCC_CTL", rS:0x14, rE:0x17, rD:"Command Completion Coalescing Control", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"CCC_PORTS", rS:0x18, rE:0x1b, rD:"Command Completion Coalescing Ports", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"EM_LOC", rS:0x1c, rE:0x1f, rD:"Enclosure Management Location", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"EM_CTL", rS:0x20, rE:0x23, rD:"Enclosure Management Control", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"CAP2", rS:0x24, rE:0x27, rD:"HBA Capabilities Extended", rC:
[{ fS: 6, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"DESO", fS: 5, fT:RO, fC:0, fD:"DevSleep Entrance from Slumber Only"},
{fN:"SADM", fS: 4, fT:RO, fC:0, fD:"Supports Aggressive Device Sleep Management"},
{fN:"SDS", fS: 3, fT:RO, fC:0, fD:"Supports Device Sleep"},
{fN:"APST", fS: 2, fT:RO, fC:0, fD:"Automatic Partial to Slumber Transitions"},
{fN:"NVMP", fS: 1, fT:RO, fC:0, fD:"NVMHCI Present (section 10.15)"},
{fN:"BOH", fS: 0, fT:RO, fC:0, fD:"BIOS/OS Handoff - not supported"}]},
{rN:"BOHC", rS:0x28, rE:0x2b, rD:"BIOS/OS COntrol and status", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
]},
{gN:"HBA_PORT", gS: HBA_OFFS + 0x100, gE:HBA_OFFS + 0x17f, gD:"HBA Port registers",gC:
[{rN:"PxCLB", rS:0x0, rE:0x03, rD:"Port x Command List Base Address", rC:
[{fN:"CLB", fS:10, fE:31, fT:RW, fC:P0CLB>>10, fD:"Command List Base Address (1KB aligned)"},
{ fS: 0, fE: 9, fT:RO, fC:0, fD:"Reserved"}]},
{rN:"PxCLBU", rS:0x04, rE:0x07, rD:"Port x CLB address, upper 32 bits of 64", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"PxFB", rS:0x8, rE:0x0b, rD:"FIS Base Address", rC:
[{fN:"CLB", fS: 8, fE:31, fT:RW, fC:P0FB>> 8, fD:"Command List Base Address (1KB aligned)"},
{ fS: 0, fE: 7, fT:RO, fC:0, fD:"Reserved"}]},
{rN:"PxFBU", rS:0x0c, rE:0x0f, rD:"FIS address, upper 32 bits of 64", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"PxIS", rS:0x10, rE:0x13, rD:"Port x Interrupt Status", rC:
[{fN:"CPDS", fS:31, fT:RWC,fC:0, fD:"Cold Port Detect Status"},
{fN:"TFES", fS:30, fT:RWC,fC:0, fD:"Task File Error Status"},
{fN:"HBFS", fS:29, fT:RWC,fC:0, fD:"Host Bus (PCI) Fatal error"},
{fN:"HBDS", fS:28, fT:RWC,fC:0, fD:"ECC error R/W system memory"},
{fN:"IFS", fS:27, fT:RWC,fC:0, fD:"Interface Fatal Error Status (sect. 6.1.2)"},
{fN:"INFS", fS:26, fT:RWC,fC:0, fD:"Interface Non-Fatal Error Status (sect. 6.1.2)"},
{ fS:25, fT:RO, fC:0, fD:"Reserved"},
{fN:"OFS", fS:24, fT:RWC,fC:0, fD:"Overflow Status"},
{fN:"IPMS", fS:23, fT:RWC,fC:0, fD:"Incorrect Port Multiplier Status"},
{fN:"PRCS", fS:22, fT:RO, fC:0, fD:"PhyRdy changed Status"}, #Indirect clear
{ fS: 8, fE:21, fT:RO, fC:0, fD:"Reserved"},
{fN:"DMPS", fS: 7, fT:RO, fC:0, fD:"Device Mechanical Presence Status"}, #Indirect clear
{fN:"PCS", fS: 6, fT:RO, fC:0, fD:"Port Connect Change Status"}, #Indirect clear
{fN:"DPS", fS: 5, fT:RWC,fC:0, fD:"Descriptor Processed"},
{fN:"UFS", fS: 4, fT:RO, fC:0, fD:"Unknown FIS"}, #Indirect clear
{fN:"SDBS", fS: 3, fT:RWC,fC:0, fD:"Set Device Bits Interrupt - Set Device bits FIS with 'I' bit set"},
{fN:"DSS", fS: 2, fT:RWC,fC:0, fD:"DMA Setup FIS Interrupt - DMA Setup FIS received with 'I' bit set"},
{fN:"PSS", fS: 1, fT:RWC,fC:0, fD:"PIO Setup FIS Interrupt - PIO Setup FIS received with 'I' bit set"},
{fN:"DHRS", fS: 0, fT:RWC,fC:0, fD:"D2H Register FIS Interrupt - D2H Register FIS received with 'I' bit set"}]},
{rN:"PxIE", rS:0x14, rE:0x17, rD:"Port x Interrupt Enable", rC:
[{fN:"CPDE", fS:31, fT:RW, fC:0, fD:"Cold Port Detect Enable"},
{fN:"TFEE", fS:30, fT:RW, fC:0, fD:"Task File Error Enable"},
{fN:"HBFE", fS:29, fT:RW, fC:0, fD:"Host Bus (PCI) Fatal Error Enable"},
{fN:"HBDE", fS:28, fT:RW, fC:0, fD:"ECC Error R/W System Memory Enable"},
{fN:"IFE", fS:27, fT:RW, fC:0, fD:"Interface Fatal Error Enable (sect. 6.1.2)"},
{fN:"INFE", fS:26, fT:RW, fC:0, fD:"Interface Non-Fatal Error Enable (sect. 6.1.2)"},
{ fS:25, fT:RO, fC:0, fD:"Reserved"},
{fN:"OFE", fS:24, fT:RW, fC:0, fD:"Overflow Enable"},
{fN:"IPME", fS:23, fT:RW, fC:0, fD:"Incorrect Port Multiplier Enable"},
{fN:"PRCE", fS:22, fT:RW, fC:0, fD:"PhyRdy changed Enable"}, #Indirect clear
{ fS: 8, fE:21, fT:RO, fC:0, fD:"Reserved"},
{fN:"DMPE", fS: 7, fT:RO, fC:0, fD:"Device Mechanical Presence Interrupt Enable"}, #Indirect clear
{fN:"PCE", fS: 6, fT:RW, fC:0, fD:"Port Connect Change Interrupt Enable"}, #Indirect clear
{fN:"DPE", fS: 5, fT:RW, fC:0, fD:"Descriptor Processed Interrupt Enable"},
{fN:"UFE", fS: 4, fT:RW, fC:0, fD:"Unknown FIS"}, #Indirect clear
{fN:"SDBE", fS: 3, fT:RW, fC:0, fD:"Device Bits Interrupt Enable"},
{fN:"DSE", fS: 2, fT:RW, fC:0, fD:"DMA Setup FIS Interrupt Enable"},
{fN:"PSE", fS: 1, fT:RW, fC:0, fD:"PIO Setup FIS Interrupt Enable"},
{fN:"DHRE", fS: 0, fT:RW, fC:0, fD:"D2H Register FIS Interrupt Enable"}]},
{rN:"PxCMD", rS:0x18, rE:0x1b, rD:"Port x Command and Status", rC:
[{fN:"ICC", fS:28, fE:31, fT:RW, fC:0, fD:"Interface Communication Control"},
# Only act if Link Layer in L_IDLE or L_NoCommPower states
# 0x8 - DevSleep
# 0x6 - Slumber
# 0x2 - Partial
# 0x1 - Active
# 0x0 - No-Op/Idle
# All other commands reserved
{fN:"ASP", fS:27, fT:RO, fC:0, fD:"Aggressive Slumber/Partial - not implemented"},
{fN:"ALPE", fS:26, fT:RO, fC:0, fD:"Aggressive Link Power Management Enable - not implemented"},
{fN:"DLAE", fS:25, fT:RW, fC:0, fD:"Drive LED on ATAPI enable"},
{fN:"ATAPI", fS:24, fT:RW, fC:0, fD:"Device is ATAPI (for activity LED)"},
{fN:"APSTE", fS:23, fT:RW, fC:0, fD:"Automatic Partial to Slumber Transitions Enabled"},
{fN:"FBSCP", fS:22, fT:RO, fC:0, fD:"FIS-Based Switching Capable Port - not implemented"},
{fN:"ESP", fS:21, fT:RO, fC:1, fD:"External SATA port"},
{fN:"CPD", fS:20, fT:RO, fC:0, fD:"Cold Presence Detection"},
{fN:"MPSP", fS:19, fT:RO, fC:0, fD:"Mechanical Presence Switch Attached to Port"},
{fN:"HPCP", fS:18, fT:RO, fC:1, fD:"Hot Plug Capable Port"},
{fN:"PMA", fS:17, fT:RW, fC:0, fD:"Port Multiplier Attached - not implemented (software should write this bit)"},
{fN:"CPS", fS:16, fT:RO, fC:0, fD:"Cold Presence State"},
{fN:"CR", fS:15, fT:RO, fC:0, fD:"Command List Running (section 5.3.2)"},
{fN:"FR", fS:14, fT:RO, fC:0, fD:"FIS Receive Running (section 10.3.2)"},
{fN:"MPSS", fS:13, fT:RO, fC:0, fD:"Mechanical Presence Switch State"},
{fN:"CCS", fS: 8, fE:12, fT:RO, fC:0, fD:"Current Command Slot (when PxCMD.ST 1-> ) should be reset to 0, when 0->1 - highest priority is 0"},
{ fS: 5, fE: 7, fT:RO, fC:0, fD:"Reserved"},
{fN:"FRE", fS: 4, fT:RW, fC:0, fD:"FIS Receive Enable (enable after FIS memory is set)"},
{fN:"CLO", fS: 3, fT:RW1,fC:0, fD:"Command List Override"},
{fN:"POD", fS: 2, fT:RO, fC:1, fD:"Power On Device (RW with Cold Presence Detection)"},
{fN:"SUD", fS: 1, fT:RO, fC:1, fD:"Spin-Up Device (RW with Staggered Spin-Up Support)"},
{fN:"ST", fS: 0, fT:RW, fC:0, fD:"Start (HBA may process commands). See section 10.3.1"}]},
# 0x1c..0x1f - Reserved
{rN:"PxTFD", rS:0x20, rE:0x23, rD:"Port x Task File Data (copy of error/status from device)", rC:
[{ fS:16, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"ERR", fS: 8, fE:15, fT:RO, fC:0, fD:"Latest Copy of Task File Error Register"},
# {fN:"STS", fS: 0, fE: 7, fT:RO, fC:0, fD:"Latest Copy of Task File Status Register"},
# # bit 7 - BSY
# # bits 6..4 - command-specific
# # bit 3 - DRQ
# # bits 1..2 - command-specific
# # bit 0 - ERR
{fN:"STS.BSY", fS: 7, fE: 7, fT:RO, fC:0, fD:"Latest Copy of Task File Status Register: BSY"},
{fN:"STS.64", fS: 4, fE: 6, fT:RO, fC:0, fD:"Latest Copy of Task File Status Register: command-specific bits 4..6 "},
{fN:"STS.DRQ", fS: 3, fE: 3, fT:RO, fC:0, fD:"Latest Copy of Task File Status Register: DRQ"},
{fN:"STS.12", fS: 1, fE: 2, fT:RO, fC:0, fD:"Latest Copy of Task File Status Register: command-specific bits 1..2 "},
{fN:"STS.ERR", fS: 0, fE: 0, fT:RO, fC:0, fD:"Latest Copy of Task File Status Register: ERR"}
]},
{rN:"PxSIG", rS:0x24, rE:0x27, rD:"Port x Signature (first D2H data after reset)", rC:
[{fN:"SIG", fS: 0, fE:31, fT:RO, fC:0xffffffff, fD:"Data in the first D2H Register FIS"},
# bits 24..31 - LBA High Register
# bits 16..23 - LBA Mid Register
# bits 8..15 - LBA Low Register
# bits 0.. 7 - Sector Count Register
]},
{rN:"PxSSTS", rS:0x28, rE:0x2b, rD:"Port x SATA Status (SCR0:SStatus)", rC:
[{ fS:12, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"IPM", fS: 8, fE:11, fT:RO, fC:0, fD:"Interface Power Management"},
# 0 - Device not present or communication not established
# 1 - Interface in active state
# 2 - Partial power state
# 6 - Slumber
# 8 - DevSleep
{fN:"SPD", fS: 4, fE: 7, fT:RO, fC:0, fD:"Interface Speed"},
# 0 - Device not present or communication not established
# 1 - Gen 1 speed
# 2 - Gen 2 speed
# 3 - Gen 3 speed
{fN:"DET", fS: 0, fE: 3, fT:RO, fC:0, fD:"Device Detection (should be detected if COMINIT is received)"},
# 0 - no device detected and Phy communication not established
# 1 - device present and detected but Phy communication not established
# 3 - device present and detected and Phy communication established
# 4 - Phy in offline mode as a result of interface being disabled or
# or running in a BIST loopback mode
]},
{rN:"PxSCTL", rS:0x2c, rE:0x2f, rD:"Port x SATA Control (SCR2:SControl)", rC:
[{ fS:20, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"PMP", fS:16, fE:19, fT:RO, fC:0, fD:"Port Multiplier Port - not used by AHCI"},
{fN:"SPM", fS:12, fE:15, fT:RO, fC:0, fD:"Select Power Management - not used by AHCI"},
{fN:"IPM", fS: 8, fE:11, fT:RW, fC:0, fD:"Interface Power Management Transitions Allowed"},
# 0 - no interface restrictions
# 1 - Transitions to Partial are disabled
# 2 - Transitions to Slumber are disabled
# 4 - Transitions to DevSleep are disabled
# Other bit-ORed values are possible
{fN:"SPD", fS: 4, fE: 7, fT:RW, fC:0, fD:"Interface Highest Speed"},
# 0 - No Speed Limit
# 1 - Gen 1 speed only
# 2 - Gen 2 speed or less
# 3 - Gen 3 speed or less
{fN:"DET", fS: 0, fE: 3, fT:RW, fC:0, fD:"Device Detection Initialization"},
# 0 - no device detection/initialization requested
# 1 - Perform interface initialization (same as hard reset)
# 4 - Disable SATA and put PHY in offline mode
]},
{rN:"PxSERR", rS:0x30, rE:0x34, rD:"Port x SATA Error (SCR1:SError)", rC:
[{ fS:27, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"DIAG.X",fS:26, fT:RWC,fC:0, fD:"Exchanged (set on COMINIT), reflected in PxIS.PCS"},
{fN:"DIAG.F",fS:25, fT:RWC,fC:0, fD:"Unknown FIS"},
{fN:"DIAG.T",fS:24, fT:RWC,fC:0, fD:"Transport state transition error"},
{fN:"DIAG.S",fS:23, fT:RWC,fC:0, fD:"Link sequence error"},
{fN:"DIAG.H",fS:22, fT:RWC,fC:0, fD:"Handshake Error (i.e. Device got CRC error)"},
{fN:"DIAG.C",fS:21, fT:RWC,fC:0, fD:"CRC error in Link layer"},
{fN:"DIAG.D",fS:20, fT:RWC,fC:0, fD:"Disparity Error - not used by AHCI"},
{fN:"DIAG.B",fS:19, fT:RWC,fC:0, fD:"10B to 8B decode error"},
{fN:"DIAG.W",fS:18, fT:RWC,fC:0, fD:"COMMWAKE signal was detected"},
{fN:"DIAG.I",fS:17, fT:RWC,fC:0, fD:"PHY Internal Error"},
{fN:"DIAG.N",fS:16, fT:RWC,fC:0, fD:"PhyRdy changed. Reflected in PxIS.PRCS bit."},
{ fS:12, fE:15, fT:RO, fC:0, fD:"Reserved"},
{fN:"ERR.E", fS:11, fT:RWC,fC:0, fD:"Internal Error"},
{fN:"ERR.P", fS:10, fT:RWC,fC:0, fD:"Protocol Error - a violation of SATA protocol detected"},
{fN:"ERR.C", fS: 9, fT:RWC,fC:0, fD:"Persistent Communication or Data Integrity Error"},
{fN:"ERR.T", fS: 8, fT:RWC,fC:0, fD:"Transient Data Integrity Error (error not recovered by the interface)"},
{ fS: 2, fE: 7, fT:RO, fC:0, fD:"Reserved"},
{fN:"ERR.M", fS: 1, fT:RWC,fC:0, fD:"Communication between the device and host was lost but re-established"},
{fN:"ERR.I", fS: 0, fT:RWC,fC:0, fD:"Recovered Data integrity Error"}
]},
{rN:"PxSACT", rS:0x34, rE:0x37, rD:"Port x SATA Active (SCR3:SActive), only set when PxCMD.ST==1", rC:
[{fN:"DS", fT:RW1,fC:0, fD:"Device Status: bit per Port, for TAG in native queued command"}
]},
{rN:"PxCI", rS:0x38, rE:0x3b, rD:"Port x Command Issue", rC:
[{fN:"CI", fT:RW1,fC:0, fD:"Command Issued: bit per Port, only set when PxCMD.ST==1, also cleared by PxCMD.ST: 1->0 by soft"}
]},
{rN:"PxSNTF", rS:0x3c, rE:0x3f, rD:"Port x SATA Notification (SCR4:SNotification)", rC:
[{ fS:16, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"PMN", fS: 0, fE:15, fT:RWC,fC:0, fD:"PM Notify (bit per PM port)"}
]},
{rN:"PxFBS", rS:0x40, rE:0x43, rD:"Port x FIS-based switching control)", rC:
[{ fS:20, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"DWE", fS:16, fE:19, fT:RO, fC:0, fD:"Device with Error"},
{fN:"ADO", fS:12, fE:15, fT:RO, fC:0, fD:"Active Device Optimization"},
{fN:"DEV", fS: 8, fE:11, fT:RW, fC:0, fD:"Device To Issue"},
{ fS: 3, fE: 7, fT:RO, fC:0, fD:"Reserved"},
{fN:"SDE", fS: 2, fT:RO, fC:0, fD:"Single Device Error"},
{fN:"DEC", fS: 1, fT:RW1,fC:0, fD:"Device Error Clear"},
{fN:"EN", fS: 0, fT:RW, fC:0, fD:"Enable"}
]},
{rN:"PxDEVSLP",rS:0x44, rE:0x47, rD:"Port x Device Sleep", rC:
[{ fS:29, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"DM", fS:25, fE:28, fT:RO, fC:0, fD:"DITO Multiplier"},
{fN:"DITO", fS:15, fE:24, fT:RW, fC:0, fD:"Device Sleep Idle Timeout (section 8.5.1.1.1)"},
{fN:"MDAT", fS:10, fE:14, fT:RW, fC:0, fD:"Minimum Device Sleep Assertion Time"},
{fN:"DETO", fS: 2, fE: 9, fT:RW, fC:0, fD:"Device Sleep Exit Timeout"},
{fN:"DSP", fS: 1, fT:RO, fC:0, fD:"Device Sleep Present"},
{fN:"ADSE", fS: 0, fT:RO, fC:0, fD:"Aggressive Device Sleep Enable"}
]},
# 0x48..0x6f - reserved
{rN:"AFI_CACHE", rS:0x70, rE:0x73, rD:"Port x Vendor Specific, program AXI cache modes", rC:
[{ fS: 8, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"WR_CM", fS: 4, fE: 7, fT:RW, fC:3, fD:"SAXIHP write channel cache mode "},
{fN:"RD_CM", fS: 0, fE: 3, fT:RW, fC:3, fD:"SAXIHP read channel cache mode "},
]},
{rN:"PGM_AHCI_SM",rS:0x74, rE:0x77, rD:"Port x Vendor Specific, AHCI state machine", rC:
[{ fS:25, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"AnD", fS:24, fT:RW, fC:0, fD:"Address/not data for programming AHCI state machine"},
{ fS:18, fE:23, fT:RO, fC:0, fD:"Reserved"},
{fN:"PGM_AD",fS: 0, fE:17, fT:RW, fC:3, fD:"Program address/data for programming AHCI state machine"},
]},
{rN:"PxVS", rS:0x78, rE:0x7f, rD:"Other Port x Vendor Specific", rC:
[{ fT:RW, fC:0, fD:"Vendor-specific data - 96 bits"}
]},
]},
]
reg_defaults = [0]*4096 # array of bytes, default value = 0
bit_types = [0]*2048 # array of words, default value = 0
localparams =[]
for group in src:
groupName = group[gN]
groupStart = group[gS]
groupEnd = group[gE]
if groupStart > groupEnd:
groupEnd, groupStart = (groupStart, groupEnd)
try:
groupDescription= group[gD]
except:
groupDescription= ""
print ("Group %s (%s) 0x%x..0x%x:"%(groupName, groupDescription, groupStart, groupEnd))
for dataRange in group[gC]:
try:
rangeName = dataRange[rN]
except:
rangeName = ""
if (not rS in dataRange) and (not rE in dataRange):
rangeStart = 0
rangeEnd = groupEnd - groupStart -1
else:
try:
rangeStart = dataRange[rS]
except:
rangeStart = dataRange[rE]
try:
rangeEnd = dataRange[rE]
except:
rangeEnd = dataRange[rS]
if rangeStart > rangeEnd:
rangeEnd, rangeStart = (rangeStart, rangeEnd)
try:
rangeDescription= dataRange[rD]
except:
rangeDescription= ""
print (" Range %s (%s) 0x%x..0x%x:"%(rangeName, rangeDescription, rangeStart, rangeEnd))
for dataField in dataRange[rC]:
try:
fieldName = dataField[fN]
except:
fieldName = ""
if (not fS in dataField) and (not fE in dataField):
fieldStart = 0
fieldEnd = (rangeEnd - rangeStart) * 8 +7 # last bit in bytes
else:
try:
fieldStart = dataField[fS]
except:
fieldStart = dataField[fE]
try:
fieldEnd = dataField[fE]
except:
fieldEnd = dataField[fS]
if fieldStart > fieldEnd:
fieldEnd, fieldStart = (fieldStart, fieldEnd)
try:
fieldDescription= dataField[fD]
except:
fieldDescription= ""
try:
fieldValue = dataField[fC]
except:
fieldValue = 0
print (" Field %s %d..%d, value = 0x%x, type = %s (%s)"%(fieldName, fieldStart, fieldEnd, fieldValue, dataField[fT], fieldDescription))
# Split field in bytes
offs=groupStart+rangeStart
fv = fieldValue << fieldStart
if dataField[fT] == RO:
t = 0
elif dataField[fT] == RW:
t = 1
elif dataField[fT] == RWC:
t = 2
elif dataField[fT] == RW1:
t = 3
else:
raise("ERROR: Invalid field type %s, only RO, RW, RWC and RX1 are valid"%(dataField[fT]))
ft=0
for i in range(fieldEnd - fieldStart +1):
ft = (ft << 2) | t
ft <<= (2*fieldStart)
for b in range (fieldStart//8, fieldEnd//8 + 1):
if (b > 0):
bs=0
else:
bs = fieldStart % 8
if (b < fieldEnd//8):
be = 7
else:
be = fieldEnd%8
bm = 0;
for i in range (bs,be+1):
bm |= (1 << i)
bv = (fv >> (8*b)) & 0xff
bt = (ft >> (16*b)) & 0xffff
bm16 = 0;
for i in range (bs,be+1):
bm16 |= (3 << (2*i))
# print ("fS = 0x%x, fE=0x%x, fS//8 = 0x%x, fE//8 + 1 = 0x%x, b=%d, fieldValue=0x%x, bv=0x%x"%(fieldStart, fieldEnd, fieldStart//8,(fieldEnd//8) + 1,b, fieldValue, bv))
reg_defaults[offs+b] = ((reg_defaults[offs+b] ^ bv) & bm) ^ reg_defaults[offs+b]
print ("reg_defaults[0x%x] = 0x%x"%(offs+b,reg_defaults[offs+b]))
#bit_types
if (offs+b) < len(bit_types):
bit_types[offs+b] = ((bit_types[offs+b] ^ bt) & bm16) ^ bit_types[offs+b]
print ("bit_types[0x%x] = 0x%x"%(offs+b,bit_types[offs+b]))
fullName=("%s__%s__%s"%(groupName,rangeName,fieldName)).replace(".","__") # no dots in field names
comment= "%s: %s"%(dataField[fT], fieldDescription)
dwas = (offs*8 + fieldStart) // 32 # 32-bit address
dwae = (offs*8 + fieldEnd) // 32 # 32-bit address
fe=fieldEnd
if dwae > dwas:
print ("***** WARNING: Field %s spans several DWORDs, truncating to the first one"%(fullName))
fe = 32*dwas +31 - offs*8 # Later AND fieldValue with field mask
fieldMask = ((1 << (fe - fieldStart + 1)) -1) << ((offs % 4) * 8 + fieldStart)
fieldShiftedValue = fieldValue << ((offs % 4) * 8 + fieldStart)
fieldShiftedValue &= fieldMask
if fieldName: # Skip reserved fields
localparams.append("// %s"%(comment))
localparams.append(" localparam %s__ADDR = 'h%x;"%(fullName, dwas))
localparams.append(" localparam %s__MASK = 'h%x;"%(fullName, fieldMask))
localparams.append(" localparam %s__DFLT = 'h%x;"%(fullName, fieldShiftedValue))
localparams.append("")
localparams_txt="\n".join(localparams)
#print(localparams_txt)
def create_no_parity (init_data, # numeric data
num_bits, # number of bits in item
start_bit, # bit number to start filling from
full_bram): # true if ramb36, false - ramb18
bsize = (0x4000,0x8000)[full_bram]
bdata = [0 for i in range(bsize)]
for item in init_data:
for bt in range (num_bits):
bdata[start_bit+bt] = (item >> bt) & 1;
start_bit += num_bits
data = []
for i in range (len(bdata)//256):
d = 0;
for b in range(255, -1,-1):
d = (d<<1) + bdata[256*i+b]
data.append(d)
# print(bdata)
# print(data)
return {'data':data,'data_p':[]}
def print_params(data,out_file_name):
with open(out_file_name,"w") as out_file:
for i, v in enumerate(data['data']):
if v:
print (", .INIT_%02X (256'h%064X)"%(i,v), file=out_file)
# if (include_parity):
for i, v in enumerate(data['data_p']):
if v:
print (", .INITP_%02X (256'h%064X)"%(i,v), file=out_file)
import os
#print (os.path.abspath(__file__))
#print (os.path.dirname(__file__))
#print (os.path.join(os.path.dirname(__file__), reg_defaults_path))
#print (os.path.abspath(os.path.join(os.path.dirname(__file__), reg_defaults_path)))
#print(reg_defaults)
#print("\n-------------------------\n")
#print(create_no_parity(reg_defaults, 8, 0, True))
#print("\n-------------------------\n")
#print(bit_types)
#print("\n-------------------------\n")
#print(create_no_parity(bit_types, 16, 0, True))
print_params(create_no_parity(reg_defaults, 8, 0, True),os.path.abspath(os.path.join(os.path.dirname(__file__), reg_defaults_path)))
print ("AHCI register defaults are written to %s"%(os.path.abspath(os.path.join(os.path.dirname(__file__), reg_defaults_path))))
print_params(create_no_parity(bit_types, 16, 0, True),os.path.abspath(os.path.join(os.path.dirname(__file__), reg_types_path)))
print ("AHCI register bit field types are written to %s"%(os.path.abspath(os.path.join(os.path.dirname(__file__), reg_types_path))))
#print(localparams_txt)
with open(os.path.abspath(os.path.join(os.path.dirname(__file__), localparams_path)),"w") as out_file:
print(localparams_txt, file=out_file)
print ("AHCI localparam definitions are written to %s"%(os.path.abspath(os.path.join(os.path.dirname(__file__), localparams_path))))
/*******************************************************************************
* Module: command
* Date: 2015-07-11
* Author: Alexey
* Description: sata command layer temporary implementation
*
* Copyright (c) 2015 Elphel, Inc.
* command.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* command.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
/*
* For testing purposes almost neat, manually-controlled
*/
module command(
input rst,
input clk,
// temporary TODO
input wire gtx_ready,
input wire phy_ready,
input wire [11:0] debug_cnt,
// tl cmd iface
output wire [2:0] cmd_type,
output wire cmd_val,
output wire [3:0] cmd_port,
input wire cmd_busy,
input wire cmd_done_good,
input wire cmd_done_bad,
// temporary TODO
input wire [31:0] al_cmd_in, // == {cmd_type, cmd_port, cmd_val, cmd_done_bad, cmd_done_good, cmd_busy}
input wire al_cmd_val_in,
output wire [31:0] al_cmd_out, // same
// data from tl
input wire [31:0] tl_data_in,
input wire tl_data_val_in,
input wire tl_data_last_in,
output wire tl_data_busy_out,
// to tl
output wire [31:0] tl_data_out,
output wire tl_data_last_out,
output wire tl_data_val_out,
input wire tl_data_strobe_in,
// tmp inputs directly from registers for each and every shadow register and control bit
// from al
input wire [31:0] al_sh_data_in, // write data
input wire al_sh_data_val_in, // write strobe
input wire al_sh_data_strobe_in, // read strobe
input wire [15:0] al_sh_feature_in,
input wire al_sh_feature_val_in,
input wire [23:0] al_sh_lba_lo_in,
input wire al_sh_lba_lo_val_in,
input wire [23:0] al_sh_lba_hi_in,
input wire al_sh_lba_hi_val_in,
input wire [15:0] al_sh_count_in,
input wire al_sh_count_val_in,
input wire [7:0] al_sh_command_in,
input wire al_sh_command_val_in,
input wire [7:0] al_sh_dev_in,
input wire al_sh_dev_val_in,
input wire [7:0] al_sh_control_in,
input wire al_sh_control_val_in,
input wire [31:0] al_sh_dma_id_lo_in,
input wire al_sh_dma_id_lo_val_in,
input wire [31:0] al_sh_dma_id_hi_in,
input wire al_sh_dma_id_hi_val_in,
input wire [31:0] al_sh_buf_off_in,
input wire al_sh_buf_off_val_in,
input wire [15:0] al_sh_tran_cnt_in,
input wire al_sh_tran_cnt_val_in,
input wire al_sh_autoact_in,
input wire al_sh_autoact_val_in,
input wire al_sh_inter_in,
input wire al_sh_inter_val_in,
input wire al_sh_dir_in,
input wire al_sh_dir_val_in,
input wire [31:0] al_sh_dma_cnt_in,
input wire al_sh_dma_cnt_val_in,
input wire al_sh_notif_in,
input wire al_sh_notif_val_in,
input wire [3:0] al_sh_port_in,
input wire al_sh_port_val_in,
// from tl
input wire [47:0] tl_sh_lba_in,
input wire [15:0] tl_sh_count_in,
input wire [7:0] tl_sh_command_in,
input wire [7:0] tl_sh_err_in,
input wire [7:0] tl_sh_status_in,
input wire [7:0] tl_sh_estatus_in, // E_Status
input wire [7:0] tl_sh_dev_in,
input wire [3:0] tl_sh_port_in,
input wire tl_sh_inter_in,
input wire tl_sh_dir_in,
input wire [63:0] tl_sh_dma_id_in,
input wire [31:0] tl_sh_dma_off_in,
input wire [31:0] tl_sh_dma_cnt_in,
input wire [15:0] tl_sh_tran_cnt_in, // Transfer Count
input wire tl_sh_notif_in,
input wire tl_sh_autoact_in,
input wire tl_sh_lba_val_in,
input wire tl_sh_count_val_in,
input wire tl_sh_command_val_in,
input wire tl_sh_err_val_in,
input wire tl_sh_status_val_in,
input wire tl_sh_estatus_val_in, // E_Status
input wire tl_sh_dev_val_in,
input wire tl_sh_port_val_in,
input wire tl_sh_inter_val_in,
input wire tl_sh_dir_val_in,
input wire tl_sh_dma_id_val_in,
input wire tl_sh_dma_off_val_in,
input wire tl_sh_dma_cnt_val_in,
input wire tl_sh_tran_cnt_val_in, // Transfer Count
input wire tl_sh_notif_val_in,
input wire tl_sh_autoact_val_in,
// all regs to output
output wire sh_data_val_out,
output wire [31:0] sh_data_out,
output wire [7:0] sh_control_out,
output wire [15:0] sh_feature_out,
output wire [47:0] sh_lba_out,
output wire [15:0] sh_count_out,
output wire [7:0] sh_command_out,
output wire [7:0] sh_err_out,
output wire [7:0] sh_status_out,
output wire [7:0] sh_estatus_out, // E_Status
output wire [7:0] sh_dev_out,
output wire [3:0] sh_port_out,
output wire sh_inter_out,
output wire sh_dir_out,
output wire [63:0] sh_dma_id_out,
output wire [31:0] sh_dma_off_out,
output wire [31:0] sh_dma_cnt_out,
output wire [15:0] sh_tran_cnt_out, // Transfer Count
output wire sh_notif_out,
output wire sh_autoact_out
);
// shadow registers
wire [31:0] sh_data;
reg [7:0] sh_control;
reg [15:0] sh_feature;
reg [47:0] sh_lba;
reg [15:0] sh_count;
reg [7:0] sh_command;
reg [7:0] sh_err;
reg [7:0] sh_status;
reg [7:0] sh_estatus; // E_Status
reg [7:0] sh_dev;
reg [3:0] sh_port;
reg sh_inter;
reg sh_dir;
reg [63:0] sh_dma_id;
reg [31:0] sh_dma_off;
reg [31:0] sh_dma_cnt;
reg [15:0] sh_tran_cnt; // Transfer Count
reg sh_notif;
reg sh_autoact;
always @ (posedge clk)
begin
// sh_data <= rst ? 32'h0 : al_sh_data_val_in ? al_sh_data_in : /*tl_sh_data_val_in ? tl_sh_data_in :*/ sh_data;
sh_control <= rst ? 8'h0 : al_sh_control_val_in ? al_sh_control_in : /*tl_sh_control_val_in ? tl_sh_control_in :*/ sh_control;
sh_feature <= rst ? 16'h0 : al_sh_feature_val_in ? al_sh_feature_in : /*tl_sh_feature_val_in ? tl_sh_feature_in :*/ sh_feature;
sh_lba[23:0] <= rst ? 24'h0 : al_sh_lba_lo_val_in ? al_sh_lba_lo_in : tl_sh_lba_val_in ? tl_sh_lba_in[23:0] : sh_lba[23:0];
sh_lba[47:24] <= rst ? 24'h0 : al_sh_lba_hi_val_in ? al_sh_lba_hi_in : tl_sh_lba_val_in ? tl_sh_lba_in[47:24] : sh_lba[47:24];
sh_count <= rst ? 16'h0 : al_sh_count_val_in ? al_sh_count_in : tl_sh_count_val_in ? tl_sh_count_in : sh_count;
sh_command <= rst ? 8'h0 : al_sh_command_val_in ? al_sh_command_in : tl_sh_command_val_in ? tl_sh_command_in : sh_command;
sh_err <= rst ? 8'h0 :/* al_sh_err_val_in ? al_sh_err_in :*/ tl_sh_err_val_in ? tl_sh_err_in : sh_err;
sh_status <= rst ? 8'h0 :/* al_sh_status_val_in ? al_sh_status_in :*/ tl_sh_status_val_in ? tl_sh_status_in : sh_status;
sh_estatus <= rst ? 8'h0 :/* al_sh_estatus_val_in ? al_sh_estatus_in :*/ tl_sh_estatus_val_in ? tl_sh_estatus_in : sh_estatus;
sh_dev <= rst ? 8'h0 : al_sh_dev_val_in ? al_sh_dev_in : tl_sh_dev_val_in ? tl_sh_dev_in : sh_dev;
sh_port <= rst ? 4'h0 : al_sh_port_val_in ? al_sh_port_in : tl_sh_port_val_in ? tl_sh_port_in : sh_port;
sh_inter <= rst ? 1'h0 : al_sh_inter_val_in ? al_sh_inter_in : tl_sh_inter_val_in ? tl_sh_inter_in : sh_inter;
sh_dir <= rst ? 1'h0 : al_sh_dir_val_in ? al_sh_dir_in : tl_sh_dir_val_in ? tl_sh_dir_in : sh_dir;
sh_dma_id[31:0] <= rst ? 32'h0 : al_sh_dma_id_lo_val_in ? al_sh_dma_id_lo_in : tl_sh_dma_id_val_in ? tl_sh_dma_id_in[31:0] : sh_dma_id[31:0];
sh_dma_id[63:32] <= rst ? 32'h0 : al_sh_dma_id_hi_val_in ? al_sh_dma_id_hi_in : tl_sh_dma_id_val_in ? tl_sh_dma_id_in[63:32] : sh_dma_id[63:32];
sh_dma_off <= rst ? 32'h0 : al_sh_buf_off_val_in ? al_sh_buf_off_in : tl_sh_dma_off_val_in ? tl_sh_dma_off_in : sh_dma_off;
sh_dma_cnt <= rst ? 32'h0 : al_sh_dma_cnt_val_in ? al_sh_dma_cnt_in : tl_sh_dma_cnt_val_in ? tl_sh_dma_cnt_in : sh_dma_cnt;
sh_tran_cnt <= rst ? 16'h0 : al_sh_tran_cnt_val_in ? al_sh_tran_cnt_in : tl_sh_tran_cnt_val_in ? tl_sh_tran_cnt_in : sh_tran_cnt;
sh_notif <= rst ? 1'h0 : al_sh_notif_val_in ? al_sh_notif_in : tl_sh_notif_val_in ? tl_sh_notif_in : sh_notif;
sh_autoact <= rst ? 1'h0 : al_sh_autoact_val_in ? al_sh_autoact_in : tl_sh_autoact_val_in ? tl_sh_autoact_in : sh_autoact;
end
// outputs assignment
assign sh_data_out = sh_data;
assign sh_control_out = sh_control;
assign sh_feature_out = sh_feature;
assign sh_lba_out = sh_lba;
assign sh_count_out = sh_count;
assign sh_command_out = sh_command;
assign sh_err_out = sh_err;
assign sh_status_out = sh_status;
assign sh_estatus_out = sh_estatus;
assign sh_dev_out = sh_dev;
assign sh_port_out = sh_port;
assign sh_inter_out = sh_inter;
assign sh_dir_out = sh_dir;
assign sh_dma_id_out = sh_dma_id;
assign sh_dma_off_out = sh_dma_off;
assign sh_dma_cnt_out = sh_dma_cnt;
assign sh_tran_cnt_out = sh_tran_cnt;
assign sh_notif_out = sh_notif;
assign sh_autoact_out = sh_autoact;
// temporaty command register TODO
reg [31:0] cmd;
assign al_cmd_out[31:12] = cmd[31:12];
assign al_cmd_out[11:0] = debug_cnt;
always @ (posedge clk)
begin
cmd[27:4] <= rst ? 24'h0 : al_cmd_val_in ? al_cmd_in[27:4] : cmd[27:4];
cmd[31] <= rst ? 1'b1 : cmd[31];
cmd[30:28] <= rst ? 3'h0 : {1'b0, phy_ready, gtx_ready};
cmd[3] <= rst ? 1'b0 : al_cmd_val_in ? al_cmd_in[3] : cmd_val ? 1'b0 : cmd[3];
cmd[2] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_bad ? 1'b1 : cmd[2];
cmd[1] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_good ? 1'b1 : cmd[1];
cmd[0] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_busy;
end
assign cmd_val = ~cmd_busy & cmd[3];
assign cmd_type = cmd[10:8];
assign cmd_port = cmd[7:4];
// data read buffer, 2048 dwords
reg [9:0] raddr;
reg [9:0] waddr;
assign tl_data_busy_out = 1'b0;
assign tl_data_out = 32'h0;
assign tl_data_last_out = 1'b0;
assign tl_data_val_out = 1'b0;
always @ (posedge clk)
waddr <= rst ? 10'b0 : ~tl_data_val_in ? waddr : (raddr == waddr + 1'b1) ? waddr : waddr + 1'b1;
always @ (posedge clk)
raddr <= rst ? 10'b0 : al_sh_data_strobe_in ? raddr + 1'b1 : raddr;
// Application layer has different clock ?
ram_1kx32_1kx32 rbuf(
.rclk (clk), // clock for read port
.raddr (raddr), // read address
.ren (al_sh_data_strobe_in), // read port enable
.regen (1'b0), // output register enable
.data_out (sh_data), // data out
.wclk (clk), // clock for read port
.waddr (waddr), // write address
.we (tl_data_val_in), // write port enable
.web (4'hf),
.data_in (tl_data_in) // data out
);
endmodule
/*******************************************************************************
* Module: sata_host
* Date: 2015-07-11
* Author: Alexey
* Description: is a wrapper for command + transport + link + phy levels
*
* Copyright (c) 2015 Elphel, Inc.
* sata_host.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sata_host.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
//`include "sata_phy.v"
//`include "link.v"
//`include "transport.v"
//`include "command.v"
module sata_host(
input wire extrst,
// sata rst
output wire rst,
// sata clk
output wire clk,
// reliable clock to source drp and cpll lock det circuits
input wire reliable_clk,
// temporary
input wire [31:0] al_cmd_in, // == {cmd_type, cmd_port, cmd_val, cmd_done_bad, cmd_done_good; cmd_busy}
input wire al_cmd_val_in,
output wire [31:0] al_cmd_out, // same
// tmp inputs directly from registers for each and every shadow register and control bit
// from al
input wire [31:0] al_sh_data_in, // write data
input wire al_sh_data_val_in, // write strobe
input wire al_sh_data_strobe_in, // read strobe
input wire [15:0] al_sh_feature_in,
input wire al_sh_feature_val_in,
input wire [23:0] al_sh_lba_lo_in,
input wire al_sh_lba_lo_val_in,
input wire [23:0] al_sh_lba_hi_in,
input wire al_sh_lba_hi_val_in,
input wire [15:0] al_sh_count_in,
input wire al_sh_count_val_in,
input wire [7:0] al_sh_command_in,
input wire al_sh_command_val_in,
input wire [7:0] al_sh_dev_in,
input wire al_sh_dev_val_in,
input wire [7:0] al_sh_control_in,
input wire al_sh_control_val_in,
input wire [31:0] al_sh_dma_id_lo_in,
input wire al_sh_dma_id_lo_val_in,
input wire [31:0] al_sh_dma_id_hi_in,
input wire al_sh_dma_id_hi_val_in,
input wire [31:0] al_sh_buf_off_in,
input wire al_sh_buf_off_val_in,
input wire [15:0] al_sh_tran_cnt_in,
input wire al_sh_tran_cnt_val_in,
input wire al_sh_autoact_in,
input wire al_sh_autoact_val_in,
input wire al_sh_inter_in,
input wire al_sh_inter_val_in,
input wire al_sh_dir_in,
input wire al_sh_dir_val_in,
input wire [31:0] al_sh_dma_cnt_in,
input wire al_sh_dma_cnt_val_in,
input wire al_sh_notif_in,
input wire al_sh_notif_val_in,
input wire [3:0] al_sh_port_in,
input wire al_sh_port_val_in,
// outputs from shadow registers
output wire sh_data_val_out,
output wire [31:0] sh_data_out,
output wire [7:0] sh_control_out,
output wire [15:0] sh_feature_out,
output wire [47:0] sh_lba_out,
output wire [15:0] sh_count_out,
output wire [7:0] sh_command_out,
output wire [7:0] sh_err_out,
output wire [7:0] sh_status_out,
output wire [7:0] sh_estatus_out, // E_Status
output wire [7:0] sh_dev_out,
output wire [3:0] sh_port_out,
output wire sh_inter_out,
output wire sh_dir_out,
output wire [63:0] sh_dma_id_out,
output wire [31:0] sh_dma_off_out,
output wire [31:0] sh_dma_cnt_out,
output wire [15:0] sh_tran_cnt_out, // Transfer Count
output wire sh_notif_out,
output wire sh_autoact_out,
// top-level ifaces
// ref clk from an external source, shall be connected to pads
input wire extclk_p,
input wire extclk_n,
// sata physical link data pins
output wire txp_out,
output wire txn_out,
input wire rxp_in,
input wire rxn_in
);
/*
initial
begin
$dumpfile("dump.vcd");
$dumpvars(0, sata_host);
end
*/
parameter DATA_BYTE_WIDTH = 4;
// tl cmd iface
wire [2:0] cl2tl_cmd_type;
wire cl2tl_cmd_val;
wire [3:0] cl2tl_cmd_port;
wire cl2tl_cmd_busy;
wire cl2tl_cmd_done_good;
wire cl2tl_cmd_done_bad;
// data from tl
wire [31:0] tl2cl_data;
wire tl2cl_data_val;
wire tl2cl_data_last;
wire tl2cl_data_busy;
// to tl
wire [31:0] cl2tl_data;
wire cl2tl_data_last;
wire cl2tl_data_val;
wire cl2tl_data_strobe;
// from tl
wire [47:0] tl2cl_sh_lba;
wire [15:0] tl2cl_sh_count;
wire [7:0] tl2cl_sh_command;
wire [7:0] tl2cl_sh_err;
wire [7:0] tl2cl_sh_status;
wire [7:0] tl2cl_sh_estatus; // E_Status
wire [7:0] tl2cl_sh_dev;
wire [3:0] tl2cl_sh_port;
wire tl2cl_sh_dir;
wire tl2cl_sh_inter;
wire [63:0] tl2cl_sh_dma_id;
wire [31:0] tl2cl_sh_dma_off;
wire [31:0] tl2cl_sh_dma_cnt;
wire [15:0] tl2cl_sh_tran_cnt; // Transfer Count
wire tl2cl_sh_notif;
wire tl2cl_sh_autoact;
wire tl2cl_sh_lba_val;
wire tl2cl_sh_count_val;
wire tl2cl_sh_command_val;
wire tl2cl_sh_err_val;
wire tl2cl_sh_status_val;
wire tl2cl_sh_estatus_val; // E_Status
wire tl2cl_sh_dev_val;
wire tl2cl_sh_port_val;
wire tl2cl_sh_dir_val;
wire tl2cl_sh_inter_val;
wire tl2cl_sh_dma_id_val;
wire tl2cl_sh_dma_off_val;
wire tl2cl_sh_dma_cnt_val;
wire tl2cl_sh_tran_cnt_val; // Transfer Count
wire tl2cl_sh_notif_val;
wire tl2cl_sh_autoact_val;
// all regs to output
wire sh_data_val;
wire [31:0] sh_data;
wire [7:0] sh_control;
wire [15:0] sh_feature;
wire [47:0] sh_lba;
wire [15:0] sh_count;
wire [7:0] sh_command;
wire [7:0] sh_err;
wire [7:0] sh_status;
wire [7:0] sh_estatus; // E_Status
wire [7:0] sh_dev;
wire [3:0] sh_port;
wire sh_inter;
wire sh_dir;
wire [63:0] sh_dma_id;
wire [31:0] sh_dma_off;
wire [31:0] sh_dma_cnt;
wire [15:0] sh_tran_cnt; // Transfer Count
wire sh_notif;
wire sh_autoact;
// phy is ready - link is established
wire phy_ready;
// tmp TODO
wire gtx_ready;
wire [11:0] debug_cnt;
assign sh_data_val_out = sh_data_val;
assign sh_data_out = sh_data;
assign sh_control_out = sh_control;
assign sh_feature_out = sh_feature;
assign sh_lba_out = sh_lba;
assign sh_count_out = sh_count;
assign sh_command_out = sh_command;
assign sh_err_out = sh_err;
assign sh_status_out = sh_status;
assign sh_estatus_out = sh_estatus;
assign sh_dev_out = sh_dev;
assign sh_port_out = sh_port;
assign sh_inter_out = sh_inter;
assign sh_dir_out = sh_dir;
assign sh_dma_id_out = sh_dma_id;
assign sh_dma_off_out = sh_dma_off;
assign sh_dma_cnt_out = sh_dma_cnt;
assign sh_tran_cnt_out = sh_tran_cnt;
assign sh_notif_out = sh_notif;
assign sh_autoact_out = sh_autoact;
command command(
.rst (rst),
.clk (clk),
// temporary inputs TODO
.gtx_ready (gtx_ready),
.phy_ready (phy_ready),
.debug_cnt (debug_cnt),
// tl cmd iface
.cmd_type (cl2tl_cmd_type),
.cmd_val (cl2tl_cmd_val),
.cmd_port (cl2tl_cmd_port),
.cmd_busy (cl2tl_cmd_busy),
.cmd_done_good (cl2tl_cmd_done_good),
.cmd_done_bad (cl2tl_cmd_done_bad),
// temporary TODO
.al_cmd_in (al_cmd_in), // == {cmd_type, cmd_port, cmd_val, cmd_done_bad, cmd_done_good, cmd_busy}
.al_cmd_val_in (al_cmd_val_in),
.al_cmd_out (al_cmd_out), // same
// data from tl
.tl_data_in (tl2cl_data),
.tl_data_val_in (tl2cl_data_val),
.tl_data_last_in (tl2cl_data_last),
.tl_data_busy_out (tl2cl_data_busy),
// to tl
.tl_data_out (cl2tl_data),
.tl_data_last_out (cl2tl_data_last),
.tl_data_val_out (cl2tl_data_val),
.tl_data_strobe_in (cl2tl_data_strobe),
// tmp inputs directly from registers for each and every shadow register and control bit
// from al
.al_sh_data_in (al_sh_data_in), // write data
.al_sh_data_val_in (al_sh_data_val_in), // write strobe
.al_sh_data_strobe_in (al_sh_data_strobe_in), // read strobe
.al_sh_feature_in (al_sh_feature_in),
.al_sh_feature_val_in (al_sh_feature_val_in),
.al_sh_lba_lo_in (al_sh_lba_lo_in),
.al_sh_lba_lo_val_in (al_sh_lba_lo_val_in),
.al_sh_lba_hi_in (al_sh_lba_hi_in),
.al_sh_lba_hi_val_in (al_sh_lba_hi_val_in),
.al_sh_count_in (al_sh_count_in),
.al_sh_count_val_in (al_sh_count_val_in),
.al_sh_command_in (al_sh_command_in),
.al_sh_command_val_in (al_sh_command_val_in),
.al_sh_dev_in (al_sh_dev_in),
.al_sh_dev_val_in (al_sh_dev_val_in),
.al_sh_control_in (al_sh_control_in),
.al_sh_control_val_in (al_sh_control_val_in),
.al_sh_dma_id_lo_in (al_sh_dma_id_lo_in),
.al_sh_dma_id_lo_val_in (al_sh_dma_id_lo_val_in),
.al_sh_dma_id_hi_in (al_sh_dma_id_hi_in),
.al_sh_dma_id_hi_val_in (al_sh_dma_id_hi_val_in),
.al_sh_buf_off_in (al_sh_buf_off_in),
.al_sh_buf_off_val_in (al_sh_buf_off_val_in),
.al_sh_tran_cnt_in (al_sh_tran_cnt_in),
.al_sh_tran_cnt_val_in (al_sh_tran_cnt_val_in),
.al_sh_autoact_in (al_sh_autoact_in),
.al_sh_autoact_val_in (al_sh_autoact_val_in),
.al_sh_inter_in (al_sh_inter_in),
.al_sh_inter_val_in (al_sh_inter_val_in),
.al_sh_dir_in (al_sh_dir_in),
.al_sh_dir_val_in (al_sh_dir_val_in),
.al_sh_dma_cnt_in (al_sh_dma_cnt_in),
.al_sh_dma_cnt_val_in (al_sh_dma_cnt_val_in),
.al_sh_notif_in (al_sh_notif_in),
.al_sh_notif_val_in (al_sh_notif_val_in),
.al_sh_port_in (al_sh_port_in),
.al_sh_port_val_in (al_sh_port_val_in),
// from tl
.tl_sh_lba_in (tl2cl_sh_lba),
.tl_sh_count_in (tl2cl_sh_count),
.tl_sh_command_in (tl2cl_sh_command),
.tl_sh_err_in (tl2cl_sh_err),
.tl_sh_status_in (tl2cl_sh_status),
.tl_sh_estatus_in (tl2cl_sh_estatus), // E_Status
.tl_sh_dev_in (tl2cl_sh_dev),
.tl_sh_port_in (tl2cl_sh_port),
.tl_sh_inter_in (tl2cl_sh_inter),
.tl_sh_dir_in (tl2cl_sh_dir),
.tl_sh_dma_id_in (tl2cl_sh_dma_id),
.tl_sh_dma_off_in (tl2cl_sh_dma_off),
.tl_sh_dma_cnt_in (tl2cl_sh_dma_cnt),
.tl_sh_tran_cnt_in (tl2cl_sh_tran_cnt), // Transfer Count
.tl_sh_notif_in (tl2cl_sh_notif),
.tl_sh_autoact_in (tl2cl_sh_autoact),
.tl_sh_lba_val_in (tl2cl_sh_lba_val),
.tl_sh_count_val_in (tl2cl_sh_count_val),
.tl_sh_command_val_in (tl2cl_sh_command_val),
.tl_sh_err_val_in (tl2cl_sh_err_val),
.tl_sh_status_val_in (tl2cl_sh_status_val),
.tl_sh_estatus_val_in (tl2cl_sh_estatus_val), // E_Status
.tl_sh_dev_val_in (tl2cl_sh_dev_val),
.tl_sh_port_val_in (tl2cl_sh_port_val),
.tl_sh_inter_val_in (tl2cl_sh_inter_val),
.tl_sh_dir_val_in (tl2cl_sh_dir_val),
.tl_sh_dma_id_val_in (tl2cl_sh_dma_id_val),
.tl_sh_dma_off_val_in (tl2cl_sh_dma_off_val),
.tl_sh_dma_cnt_val_in (tl2cl_sh_dma_cnt_val),
.tl_sh_tran_cnt_val_in (tl2cl_sh_tran_cnt_val), // Transfer Count
.tl_sh_notif_val_in (tl2cl_sh_notif_val),
.tl_sh_autoact_val_in (tl2cl_sh_autoact_val),
// all regs to output
.sh_data_val_out (sh_data_val),
.sh_data_out (sh_data),
.sh_control_out (sh_control),
.sh_feature_out (sh_feature),
.sh_lba_out (sh_lba),
.sh_count_out (sh_count),
.sh_command_out (sh_command),
.sh_err_out (sh_err),
.sh_status_out (sh_status),
.sh_estatus_out (sh_estatus), // E_Status
.sh_dev_out (sh_dev),
.sh_port_out (sh_port),
.sh_inter_out (sh_inter),
.sh_dir_out (sh_dir),
.sh_dma_id_out (sh_dma_id),
.sh_dma_off_out (sh_dma_off),
.sh_dma_cnt_out (sh_dma_cnt),
.sh_tran_cnt_out (sh_tran_cnt), // Transfer Count
.sh_notif_out (sh_notif),
.sh_autoact_out (sh_autoact)
);
// issue a frame
wire tl2ll_frame_req;
// frame started to be transmitted
wire tl2ll_frame_ack;
// frame issue was rejected because of incoming frame with higher priority
wire tl2ll_frame_rej;
// LL is not ready to receive a frame request. frame_req shall be low if busy is asserted
wire tl2ll_frame_busy;
// frame was transmitted w/o probles and successfully received @ a device side
wire tl2ll_frame_done_good;
// frame was transmitted, but device messages of problems with receiving
wire tl2ll_frame_done_bad;
// LL reports of an incoming frame transmission. They're always allowed and have the highest priority
wire ll2tl_incom_start;
// LL reports of a completion of an incoming frame transmission.
wire ll2tl_incom_done;
// LL reports of errors in current FIS
wire ll2tl_incom_invalidate; // TODO
wire ll2tl_incom_sync_escape;
// TL analyzes FIS and returnes if FIS makes sense.
wire ll2tl_incom_ack_good;
// ... and if it doesn't
wire ll2tl_incom_ack_bad;
// transmission interrupts
// TL demands to brutally cancel current transaction TODO
wire tl2ll_sync_escape_req;
// acknowlegement of a successful reception TODO
wire tl2ll_sync_escape_ack;
// TL demands to stop current recieving session TODO
wire tl2ll_incom_stop_req;
// shows if dma activate was received (a pulse)
wire got_dma_activate;
wire [3:0] got_dma_activate_port;
// if CL made a mistake in controlling data FIS length
wire data_limit_exceeded;
// LL data
// data inputs from LL
wire [DATA_BYTE_WIDTH*8 - 1:0] ll2tl_data;
wire [DATA_BYTE_WIDTH/2 - 1:0] ll2tl_data_mask;
wire ll2tl_data_val;
wire ll2tl_data_last;
// transport layer tells if its inner buffer is almost full
wire ll2tl_data_busy;
// data outputs to LL
wire [DATA_BYTE_WIDTH*8 - 1:0] tl2ll_data;
// not implemented yet TODO
wire [DATA_BYTE_WIDTH/2 - 1:0] tl2ll_data_mask;
wire tl2ll_data_last;
wire tl2ll_data_val;
wire tl2ll_data_strobe;
// watchdog timers calls. They shall be handled in TL, but for debug purposes are wired to the upper level
// when eof acknowledgement is not received after sent FIS
wire watchdog_eof;
// when too many dwords is in current FIS
wire watchdog_dwords;
transport transport(
.clk (clk),
.rst (rst),
// link layer (LL) control
// issue a frame
.frame_req (tl2ll_frame_req),
// frame started to be transmitted
.frame_ack (tl2ll_frame_ack),
// frame issue was rejected because of incoming frame with higher priority
.frame_rej (tl2ll_frame_rej),
// LL is not ready to receive a frame request. frame_req shall be low if busy is asserted
.frame_busy (tl2ll_frame_busy),
// frame was transmitted w/o probles and successfully received @ a device side
.frame_done_good (tl2ll_frame_done_good),
// frame was transmitted, but device messages of problems with receiving
.frame_done_bad (tl2ll_frame_done_bad),
// LL reports of an incoming frame transmission. They're always allowed and have the highest priority
.incom_start (ll2tl_incom_start),
// LL reports of a completion of an incoming frame transmission.
.incom_done (ll2tl_incom_done),
// LL reports of errors in current FIS
.incom_invalidate (ll2tl_incom_invalidate || ll2tl_incom_sync_escape), // TODO
// TL analyzes FIS and returnes if FIS makes sense.
.incom_ack_good (ll2tl_incom_ack_good),
// ... and if it doesn't
.incom_ack_bad (ll2tl_incom_ack_bad),
// transmission interrupts
// TL demands to brutally cancel current transaction TODO
.sync_escape_req (tl2ll_sync_escape_req),
// acknowlegement of a successful reception TODO
.sync_escape_ack (tl2ll_sync_escape_ack),
// TL demands to stop current recieving session TODO
.incom_stop_req (tl2ll_incom_stop_req),
// controls from a command layer (CL)
// FIS type, ordered by CL
.cmd_type (cl2tl_cmd_type),
// request itself
.cmd_val (cl2tl_cmd_val),
// destination port
.cmd_port (cl2tl_cmd_port),
// if cmd got into processing, busy asserts, when TL is ready to receive a new cmd, busy deasserts
.cmd_busy (cl2tl_cmd_busy),
// indicates completion of a request
.cmd_done_good (cl2tl_cmd_done_good),
// request is completed, but device wasn't able to receive
.cmd_done_bad (cl2tl_cmd_done_bad),
// shadow registers TODO reduce outputs/inputs count. or not
// actual registers are stored in CL
.sh_data_in (sh_data),
.sh_feature_in (sh_feature),
.sh_lba_in (sh_lba),
.sh_count_in (sh_count),
.sh_command_in (sh_command),
.sh_dev_in (sh_dev),
.sh_control_in (sh_control),
.sh_autoact_in (sh_autoact),
.sh_inter_in (sh_inter),
.sh_dir_in (sh_dir),
.sh_dma_id_in (sh_dma_id),
.sh_buf_off_in (sh_dma_off),
.sh_dma_cnt_in (sh_dma_cnt),
.sh_notif_in (sh_notif),
.sh_tran_cnt_in (sh_tran_cnt),
.sh_port_in (sh_port),
// TL decodes register writes and sends corresponding issues to CL
.sh_lba_out (tl2cl_sh_lba),
.sh_count_out (tl2cl_sh_count),
.sh_command_out (tl2cl_sh_command),
.sh_err_out (tl2cl_sh_err),
.sh_status_out (tl2cl_sh_status),
.sh_estatus_out (tl2cl_sh_estatus), // E_Status
.sh_dev_out (tl2cl_sh_dev),
.sh_port_out (tl2cl_sh_port),
.sh_inter_out (tl2cl_sh_inter),
.sh_dir_out (tl2cl_sh_dir),
.sh_dma_id_out (tl2cl_sh_dma_id),
.sh_dma_off_out (tl2cl_sh_dma_off),
.sh_dma_cnt_out (tl2cl_sh_dma_cnt),
.sh_tran_cnt_out (tl2cl_sh_tran_cnt), // Transfer Count
.sh_notif_out (tl2cl_sh_notif),
.sh_autoact_out (tl2cl_sh_autoact),
.sh_lba_val_out (tl2cl_sh_lba_val),
.sh_count_val_out (tl2cl_sh_count_val),
.sh_command_val_out (tl2cl_sh_command_val),
.sh_err_val_out (tl2cl_sh_err_val),
.sh_status_val_out (tl2cl_sh_status_val),
.sh_estatus_val_out (tl2cl_sh_estatus_val), // E_Status
.sh_dev_val_out (tl2cl_sh_dev_val),
.sh_port_val_out (tl2cl_sh_port_val),
.sh_inter_val_out (tl2cl_sh_inter_val),
.sh_dir_val_out (tl2cl_sh_dir_val),
.sh_dma_id_val_out (tl2cl_sh_dma_id_val),
.sh_dma_off_val_out (tl2cl_sh_dma_off_val),
.sh_dma_cnt_val_out (tl2cl_sh_dma_cnt_val),
.sh_tran_cnt_val_out (tl2cl_sh_tran_cnt_val), // Transfer Count
.sh_notif_val_out (tl2cl_sh_notif_val),
.sh_autoact_val_out (tl2cl_sh_autoact_val),
// shows if dma activate was received (a pulse)
.got_dma_activate (got_dma_activate),
.got_dma_activate_port (got_dma_activate_port),
// if CL made a mistake in controlling data FIS length
.data_limit_exceeded (data_limit_exceeded),
// LL data
// data inputs from LL
.ll_data_in (ll2tl_data),
.ll_data_mask_in (ll2tl_data_mask),
.ll_data_val_in (ll2tl_data_val),
.ll_data_last_in (ll2tl_data_last),
// transport layer tells if its inner buffer is almost full
.ll_data_busy_out (ll2tl_data_busy),
// data outputs to LL
.ll_data_out (tl2ll_data),
// not implemented yet TODO
.ll_data_mask_out (tl2ll_data_mask),
.ll_data_last_out (tl2ll_data_last),
.ll_data_val_out (tl2ll_data_val),
.ll_data_strobe_in (tl2ll_data_strobe),
// CL data
// required content is bypassed from ll, other is trimmed
// only content of data FIS, starting from 1st dword. Max burst = 2048 dwords
// data outputs to CL
.cl_data_out (tl2cl_data),
.cl_data_mask_out (),
.cl_data_val_out (tl2cl_data_val),
.cl_data_last_out (tl2cl_data_last),
// transport layer tells if its inner buffer is almost full
.cl_data_busy_in (tl2cl_data_busy),
// data inputs from CL
.cl_data_in (cl2tl_data),
// not implemented yet TODO
.cl_data_mask_in (2'b11),//cl2tl_data_mask),
.cl_data_last_in (cl2tl_data_last),
.cl_data_val_in (cl2tl_data_val),
.cl_data_strobe_out (cl2tl_data_strobe),
// watchdog timers calls. They shall be handled in TL, but for debug purposes are wired to the upper level
// when eof acknowledgement is not received after sent FIS
.watchdog_eof (watchdog_eof),
// when too many dwords is in current FIS
.watchdog_dwords (watchdog_dwords)
);
// oob sequence is reinitiated and link now is not established or rxelecidle
//wire link_reset; // use ~phy_ready instead
// data-primitives stream from phy
wire [DATA_BYTE_WIDTH*8 - 1:0] phy2ll_data;
wire [DATA_BYTE_WIDTH - 1:0] phy2ll_isk; // charisk
wire [DATA_BYTE_WIDTH - 1:0] phy2ll_err; // disperr | notintable
// to phy
wire [DATA_BYTE_WIDTH*8 - 1:0] ll2phy_data;
wire [DATA_BYTE_WIDTH - 1:0] ll2phy_isk; // charisk
link link(
// TODO insert watchdogs
.rst (rst),
.clk (clk),
// data inputs from transport layer
// input data stream (if any data during OOB setting => ignored)
.data_in (tl2ll_data),
// in case of strange data aligments and size (1st mentioned @ doc, p.310, odd number of words case)
// Actually, only last data bundle shall be masked, others are always valid.
// Mask could be encoded into 3 bits instead of 4 for qword, but encoding+decoding aren't worth the bit
// TODO, for now not supported, all mask bits are assumed to be set
.data_mask_in (tl2ll_data_mask),
// buffer read strobe
.data_strobe_out (tl2ll_data_strobe),
// transaction's last data budle pulse
.data_last_in (tl2ll_data_last),
// read data is valid (if 0 while last pulse wasn't received => need to hold the line)
.data_val_in (tl2ll_data_val),
// data outputs to transport layer
// read data, same as related inputs
.data_out (ll2tl_data),
// same thing - all 1s for now. TODO
.data_mask_out (ll2tl_data_mask),
// count every data bundle read by transport layer, even if busy flag is set
// let the transport layer handle oveflows by himself
.data_val_out (ll2tl_data_val),
// transport layer tells if its inner buffer is almost full
.data_busy_in (ll2tl_data_busy),
.data_last_out (ll2tl_data_last),
// request for a new frame transition
.frame_req (tl2ll_frame_req),
// a little bit of overkill with the cound of response signals, think of throwing out 1 of them
// LL tells back if it cant handle the request for now
.frame_busy (tl2ll_frame_busy),
// LL tells if the request is transmitting
.frame_ack (tl2ll_frame_ack),
// or if it was cancelled because of simultanious incoming transmission
.frame_rej (tl2ll_frame_rej),
// TL tell if the outcoming transaction is done and how it was done
.frame_done_good (tl2ll_frame_done_good),
.frame_done_bad (tl2ll_frame_done_bad),
// if started an incoming transaction
.incom_start (ll2tl_incom_start),
// if incoming transition was completed
.incom_done (ll2tl_incom_done),
// if incoming transition had errors
.incom_invalidate (ll2tl_incom_invalidate),
// if incoming got sync escape
.incom_sync_escape (ll2tl_incom_sync_escape), // output wire
// transport layer responds on a completion of a FIS
.incom_ack_good (ll2tl_incom_ack_good),
.incom_ack_bad (ll2tl_incom_ack_bad),
// oob sequence is reinitiated and link now is not established or rxelecidle
.link_reset (~phy_ready), //TODO mb it shall be independent
// TL demands to brutally cancel current transaction
.sync_escape_req (tl2ll_sync_escape_req),
// acknowlegement of a successful reception
.sync_escape_ack (tl2ll_sync_escape_ack),
// TL demands to stop current recieving session
.incom_stop_req (tl2ll_incom_stop_req),
// inputs from phy
// phy is ready - link is established
.phy_ready (phy_ready),
// data-primitives stream from phy
.phy_data_in (phy2ll_data),
.phy_isk_in (phy2ll_isk), // charisk
.phy_err_in (phy2ll_err), // disperr | notintable
// to phy
.phy_data_out (ll2phy_data),
.phy_isk_out (ll2phy_isk)// charis
);
sata_phy phy(
// pll reset
.extrst (extrst),
// sata clk
.rst (rst),
// sata clk, generated in pll as usrclk2
.clk (clk),
// stable clock to source drp and cpll lock det circuits
.reliable_clk (reliable_clk),
// state
.phy_ready (phy_ready),
.gtx_ready (gtx_ready),
.debug_cnt (debug_cnt),
// top-level ifaces
// ref clk from an external source, shall be connected to pads
.extclk_p (extclk_p),
.extclk_n (extclk_n),
// sata link data pins
.txp_out (txp_out),
.txn_out (txn_out),
.rxp_in (rxp_in),
.rxn_in (rxn_in),
// to link layer
.ll_data_out (phy2ll_data),
.ll_charisk_out (phy2ll_isk),
.ll_err_out (phy2ll_err),
// from link layer
.ll_data_in (ll2phy_data),
.ll_charisk_in (ll2phy_isk),
// added for AHCI
.set_offline (1'b0), // input
.comreset_send (1'b0), // input
.cominit_got (), // output wire
.comwake_got () // output wire
);
endmodule
/*******************************************************************************
* Module: transport
* Date: 2015-07-11
* Author: Alexey
* Description: sata transport layer implementation
*
* Copyright (c) 2015 Elphel, Inc.
* transport.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* transport.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
module transport #(
parameter DATA_BYTE_WIDTH = 4
)
(
input wire clk,
input wire rst,
// link layer (LL) control
// issue a frame
output wire frame_req,
// frame started to be transmitted
input wire frame_ack,
// frame issue was rejected because of incoming frame with higher priority
input wire frame_rej,
// LL is not ready to receive a frame request. frame_req shall be low if busy is asserted
input wire frame_busy,
// frame was transmitted w/o probles and successfully received @ a device side
input wire frame_done_good,
// frame was transmitted, but device messages of problems with receiving
input wire frame_done_bad,
// LL reports of an incoming frame transmission. They're always allowed and have the highest priority
input wire incom_start,
// LL reports of a completion of an incoming frame transmission.
input wire incom_done,
// LL reports of errors in current FIS
input wire incom_invalidate, // TODO
// TL analyzes FIS and returnes if FIS makes sense.
output wire incom_ack_good,
// ... and if it doesn't
output wire incom_ack_bad,
// transmission interrupts
// TL demands to brutally cancel current transaction TODO
output wire sync_escape_req,
// acknowlegement of a successful reception TODO
input wire sync_escape_ack,
// TL demands to stop current recieving session TODO
output wire incom_stop_req,
// controls from a command layer (CL)
// FIS type, ordered by CL
input wire [2:0] cmd_type,
// request itself
input wire cmd_val,
// destination port
input wire [3:0] cmd_port,
// if cmd got into processing, busy asserts, when TL is ready to receive a new cmd, busy deasserts
output wire cmd_busy,
// indicates completion of a request
output wire cmd_done_good,
// request is completed, but device wasn't able to receive
output wire cmd_done_bad,
// shadow registers TODO reduce outputs/inputs count. or not
// actual registers are stored in CL
input wire [31:0] sh_data_in,
input wire [15:0] sh_feature_in,
input wire [47:0] sh_lba_in,
input wire [15:0] sh_count_in,
input wire [7:0] sh_command_in,
input wire [7:0] sh_dev_in,
input wire [7:0] sh_control_in,
input wire sh_autoact_in,
input wire sh_inter_in,
input wire sh_dir_in,
input wire [63:0] sh_dma_id_in,
input wire [31:0] sh_buf_off_in,
input wire [31:0] sh_dma_cnt_in,
input wire sh_notif_in,
input wire [15:0] sh_tran_cnt_in,
input wire [3:0] sh_port_in,
// TL decodes register writes and sends corresponding issues to CL
output wire [47:0] sh_lba_out,
output wire [15:0] sh_count_out,
output wire [7:0] sh_command_out,
output wire [7:0] sh_err_out,
output wire [7:0] sh_status_out,
output wire [7:0] sh_estatus_out, // E_Status
output wire [7:0] sh_dev_out,
output wire [3:0] sh_port_out,
output wire sh_inter_out,
output wire sh_dir_out,
output wire [63:0] sh_dma_id_out,
output wire [31:0] sh_dma_off_out,
output wire [31:0] sh_dma_cnt_out,
output wire [15:0] sh_tran_cnt_out, // Transfer Count
output wire sh_notif_out,
output wire sh_autoact_out,
output wire sh_lba_val_out,
output wire sh_count_val_out,
output wire sh_command_val_out,
output wire sh_err_val_out,
output wire sh_status_val_out,
output wire sh_estatus_val_out, // E_Status
output wire sh_dev_val_out,
output wire sh_port_val_out,
output wire sh_inter_val_out,
output wire sh_dir_val_out,
output wire sh_dma_id_val_out,
output wire sh_dma_off_val_out,
output wire sh_dma_cnt_val_out,
output wire sh_tran_cnt_val_out, // Transfer Count
output wire sh_notif_val_out,
output wire sh_autoact_val_out,
// shows if dma activate was received (a pulse)
output wire got_dma_activate,
output wire [3:0] got_dma_activate_port,
// if CL made a mistake in controlling data FIS length
output wire data_limit_exceeded,
// LL data
// data inputs from LL
input wire [DATA_BYTE_WIDTH*8 - 1:0] ll_data_in,
input wire [DATA_BYTE_WIDTH/2 - 1:0] ll_data_mask_in,
input wire ll_data_val_in,
input wire ll_data_last_in,
// transport layer tells if its inner buffer is almost full
output wire ll_data_busy_out,
// data outputs to LL
output wire [DATA_BYTE_WIDTH*8 - 1:0] ll_data_out,
// not implemented yet TODO
output wire [DATA_BYTE_WIDTH/2 - 1:0] ll_data_mask_out,
output wire ll_data_last_out,
output wire ll_data_val_out,
input wire ll_data_strobe_in,
// CL data
// required content is bypassed from ll, other is trimmed
// only content of data FIS, starting from 1st dword. Max burst = 2048 dwords
// data outputs to CL
output wire [DATA_BYTE_WIDTH*8 - 1:0] cl_data_out,
output wire [DATA_BYTE_WIDTH/2 - 1:0] cl_data_mask_out,
output wire cl_data_val_out,
output wire cl_data_last_out,
// transport layer tells if its inner buffer is almost full
input wire cl_data_busy_in,
// data inputs from CL
input wire [DATA_BYTE_WIDTH*8 - 1:0] cl_data_in,
// not implemented yet TODO
input wire [DATA_BYTE_WIDTH/2 - 1:0] cl_data_mask_in,
input wire cl_data_last_in,
input wire cl_data_val_in,
output wire cl_data_strobe_out,
// watchdog timers calls. They shall be handled in TL, but for debug purposes are wired to the upper level
// when eof acknowledgement is not received after sent FIS
output wire watchdog_eof,
// when too many dwords is in current FIS
output wire watchdog_dwords
);
reg [7:0] state;
//TODO
assign sync_escape_req = 1'b0;
assign incom_stop_req = 1'b0;
assign cl_data_strobe_out = 1'b0;
// How much time does device have to response on EOF
parameter [13:0] WATCHDOG_EOF_LIMIT = 14'd1000;
// must have a local reserve copy of shadow registers in case of
// a) received FIS with incorrect length (seems like an error, so no registers shall be written)
// b) incoming transmission overrides outcoming, so we have to latch outcoming values in real shadow registers
// while storing incoming ones in the local copy
reg [47:0] loc_lba;
reg [15:0] loc_count;
reg [7:0] loc_command;
reg [7:0] loc_err;
reg [7:0] loc_status;
reg [7:0] loc_estatus; // E_Status
reg [7:0] loc_dev;
reg [3:0] loc_port;
reg loc_inter;
reg loc_dir;
reg [63:0] loc_dma_id;
reg [31:0] loc_dma_off;
reg [31:0] loc_dma_cnt;
reg [15:0] loc_tran_cnt; // Transfer Count
reg loc_notif;
reg loc_autoact;
// latching cmd inputs
reg [3:0] cmd_port_r;
reg [2:0] cmd_type_r;
always @ (posedge clk)
cmd_type_r <= rst ? 3'h0 : cmd_val ? cmd_type : cmd_type_r;
always @ (posedge clk)
cmd_port_r <= rst ? 4'h0 : cmd_val ? cmd_port : cmd_port_r;
// incomming command type decode, shows which type of FIS shall be issued
localparam [2:0] CMD_TYPE_REG_DEV = 3'h0; // Reg H2D, bit C -> 0
localparam [2:0] CMD_TYPE_REG_CMD = 3'h1; // Reg H2D, bit C -> 1
localparam [2:0] CMD_TYPE_DMA_SETUP = 3'h2;
localparam [2:0] CMD_TYPE_DATA = 3'h3;
localparam [2:0] CMD_TYPE_BIST_ACT = 3'h4;
// current header dword
wire [31:0] ll_header_dword;
// current dword shall be header's
wire ll_header_val;
// if last data dword is header's
wire ll_header_last;
// incorrect size or unmatched type of a received FIS
reg bad_fis_received;
// if a FIS has wrong size, make sure it would stop, universal dword counter
reg [13:0] dword_cnt;
// FIS dword size exceeded condition
assign watchdog_dwords = dword_cnt == 14'd2049;
// ask for a receiving termination in case of errors
reg incom_stop_req_timeout;
// global TL fsm
/*
idle -----> outcoming FIS ----> outcoming ----non-data--> fill dwords -------------------------+
| |if rej | |
| | +-----data--> make header --> bypass data from CL -+
| V |
+-------> incoming FIS -------detect type---non-data--> parse dwords, write sh regs ---------+
| |
+-------------data--> get header ---> bypass data to CL -----> done
*/
localparam STATE_IDLE = 8'h0;
localparam STATE_INCOMING = 8'h1;
localparam STATE_OUTCOMING = 8'h2;
localparam STATE_IN_DATA = 8'h10; // Data FIS from device
localparam STATE_IN_REG_1 = 8'h20; // Register FIS Device to Host: 1st dword
localparam STATE_IN_REG_2 = 8'h21; // Register FIS Device to Host: 2nd dword
localparam STATE_IN_REG_3 = 8'h22; // Register FIS Device to Host: 3rd dword
localparam STATE_IN_REG_4 = 8'h23; // Register FIS Device to Host: 4th dword
localparam STATE_IN_REG_ERR = 8'h24; // Register FIS Device to Host: Error happened
localparam STATE_IN_DMAA_ERR = 8'h30; // DMA Activate: Error Happened
localparam STATE_IN_DMAS_1 = 8'h40; // DMA Setup FIS device to host: 1st dword
localparam STATE_IN_DMAS_2 = 8'h41; // DMA Setup FIS device to host: 2nd dword
localparam STATE_IN_DMAS_3 = 8'h42; // DMA Setup FIS device to host: 3rd dword
localparam STATE_IN_DMAS_4 = 8'h43; // DMA Setup FIS device to host: 4th dword
localparam STATE_IN_DMAS_5 = 8'h44; // DMA Setup FIS device to host: 5th dword
localparam STATE_IN_DMAS_6 = 8'h45; // DMA Setup FIS device to host: 6th dword
localparam STATE_IN_DMAS_ERR = 8'h46; // DMA Setup FIS device to host: Error happened
localparam STATE_IN_BIST_1 = 8'h50; // BIST Activate FIS Device to Host: 1st dword
localparam STATE_IN_BIST_2 = 8'h51; // BIST Activate FIS Device to Host: 2nd dword
localparam STATE_IN_BIST_ERR = 8'h52; // BIST Activate FIS Device to Host: Error happened
localparam STATE_IN_PIOS_1 = 8'h60; // PIO Setup FIS: 1st dword
localparam STATE_IN_PIOS_2 = 8'h61; // PIO Setup FIS: 2nd dword
localparam STATE_IN_PIOS_3 = 8'h62; // PIO Setup FIS: 3rd dword
localparam STATE_IN_PIOS_4 = 8'h63; // PIO Setup FIS: 4th dword
localparam STATE_IN_PIOS_ERR = 8'h64; // PIO Setup FIS: Error happened
localparam STATE_IN_SDB_1 = 8'h70; // Set Device Bits FIS: 1st dword
localparam STATE_IN_SDB_ERR = 8'h70; // Set Device Bits FIS: Error happened
localparam STATE_OUT_DATA_H = 8'h80; // Data FIS from host: header
localparam STATE_OUT_DATA_D = 8'h81; // Data FIS from host: payload
localparam STATE_OUT_REG = 8'h90; // Register FIS Host to Device
localparam STATE_OUT_DMAS = 8'ha0; // DMA Setup FIS Host to Device
localparam STATE_OUT_BIST = 8'hb0; // BIST Activate FIS Host to Device
localparam STATE_OUT_WAIT_RESP = 8'hc0; //
localparam STATE_IN_UNRECOG = 8'hf0; // Unrecognized FIS from Device
always @ (posedge clk)
if (rst)
begin
state <= STATE_IDLE;
dword_cnt <= 14'h0;
incom_stop_req_timeout <= 1'b0;
bad_fis_received <= 1'b0;
loc_lba <= 48'h0;
loc_count <= 32'h0;
loc_command <= 8'h0;
loc_err <= 8'h0;
loc_status <= 8'h0;
loc_estatus <= 8'h0;
loc_dev <= 8'h0;
loc_port <= 4'h0;
loc_inter <= 1'h0;
loc_dir <= 1'h0;
loc_dma_id <= 64'h0;
loc_dma_off <= 32'h0;
loc_dma_cnt <= 32'h0;
loc_tran_cnt <= 16'h0;
loc_notif <= 1'h0;
loc_autoact <= 1'h0;
end
else
case (state)
STATE_IDLE:
begin
dword_cnt <= 14'h0;
incom_stop_req_timeout <= 1'b0;
bad_fis_received <= 1'b0;
if (frame_req)
state <= STATE_OUTCOMING;
else
if (incom_start | frame_req)
state <= STATE_INCOMING;
else
state <= STATE_IDLE;
loc_lba <= sh_lba_in;
loc_count <= sh_count_in;
loc_command <= sh_command_in;
loc_err <= 8'h0;
loc_status <= 8'h0;
loc_estatus <= 8'h0;
loc_dev <= 8'h0;
loc_port <= sh_port_in;
loc_inter <= sh_inter_in;
loc_dir <= sh_dir_in;
loc_dma_id <= sh_dma_id_in;
loc_dma_off <= sh_buf_off_in;
loc_dma_cnt <= sh_dma_cnt_in;
loc_tran_cnt <= sh_tran_cnt_in;
loc_notif <= sh_notif_in;
loc_autoact <= sh_autoact_in;
end
STATE_INCOMING:
// enter state when we're starting to get a FIS, leave after 1st dword is received
begin
if (ll_data_val_in)
// if 0-th dword came
case (ll_data_in[7:0])
// act depending on packet type
8'h34:
// register
begin
if (~ll_data_last_in)
begin
loc_port <= ll_data_in[11:8];
loc_inter <= ll_data_in[14];
loc_status <= ll_data_in[23:16];
loc_err <= ll_data_in[31:24];
state <= STATE_IN_REG_1;
end
else
// an error state, too little dwords transfered
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
end
8'h39:
// DMA Activate
begin
if (~ll_data_last_in)
begin
state <= STATE_IN_DMAA_ERR;
dword_cnt <= 14'h1;
end
else
begin
// got_dma_activate - wire assigment
state <= STATE_IDLE;
end
end
8'h41:
// DMA Setup
begin
if (~ll_data_last_in)
begin
loc_port <= ll_data_in[11:8];
loc_dir <= ll_data_in[13];
loc_inter <= ll_data_in[14];
loc_autoact <= ll_data_in[15];
state <= STATE_IN_DMAS_1;
end
else
// an error state, too little dwords transfered
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
end
8'h46:
// Data FIS
begin
if (~ll_data_last_in)
begin
loc_port <= ll_data_in[11:8];
dword_cnt <= 14'h1;
state <= STATE_IN_DATA;
end
else
// an error state, too little dwords transfered
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
end
8'h58:
// BIST
begin
// for now skips payload, just controls length TODO
state <= STATE_IN_BIST_1;
end
8'h5f:
// PIO setup
begin
if (~ll_data_last_in)
begin
loc_port <= ll_data_in[11:8];
loc_dir <= ll_data_in[13];
loc_inter <= ll_data_in[14];
loc_status <= ll_data_in[23:16];
loc_err <= ll_data_in[31:24];
state <= STATE_IN_PIOS_1;
end
else
// an error state, too little dwords transfered
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
end
8'ha1:
// Set Device Bits
begin
if (~ll_data_last_in)
begin
loc_inter <= ll_data_in[14];
loc_notif <= ll_data_in[15];
loc_status[2:0] <= ll_data_in[19:17];
loc_status[6:4] <= ll_data_in[23:21];
loc_err <= ll_data_in[31:24];
state <= STATE_IN_SDB_1;
end
else
// an error state, too little dwords transfered
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
end
default:
// no known FIS type matched
begin
dword_cnt <= 14'h0;
state <= STATE_IN_UNRECOG;
end
endcase
end
STATE_OUTCOMING:
// enter state when we're issuing a FIS, leave when got an ack from ll (FIS started to transmit)
// or if FIS won't start because of incoming transmission. In such case outcoming request parameter shall be latched TODO or not?
begin
dword_cnt <= 14'h0;
state <= frame_rej ? STATE_INCOMING :
frame_ack & cmd_type_r == CMD_TYPE_REG_DEV ? STATE_OUT_REG :
frame_ack & cmd_type_r == CMD_TYPE_REG_CMD ? STATE_OUT_REG :
frame_ack & cmd_type_r == CMD_TYPE_DMA_SETUP ? STATE_OUT_DMAS :
frame_ack & cmd_type_r == CMD_TYPE_DATA ? STATE_OUT_DATA_H :
frame_ack & cmd_type_r == CMD_TYPE_BIST_ACT ? STATE_OUT_BIST :
STATE_OUTCOMING;
end
STATE_IN_DATA:
// receiving data from Data FIS, bypass it into buffer at upper level
begin
if (incom_done)
// EOF received, CRC good
begin
state <= STATE_IDLE;
end
else
if (ll_data_val_in)
begin
if (dword_cnt == 14'd2049)
// if too much data for a data FIS TODO handle this exception properly
state <= STATE_IDLE;
else
// continuing receiving data
begin
dword_cnt <= dword_cnt + 1'b1;
state <= STATE_IN_DATA;
end
end
end
STATE_IN_REG_1:
// receiving register FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {Device, LBA High, LBA Mid, LBA Low}
begin
loc_lba[7:0] <= ll_data_in[7:0];
loc_lba[23:16] <= ll_data_in[15:8];
loc_lba[39:32] <= ll_data_in[23:16];
loc_dev[7:0] <= ll_data_in[31:24];
state <= STATE_IN_REG_2;
end
end
STATE_IN_REG_2:
// receiving register FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {Reserved, LBA High (exp), LBA Mid (exp), LBA Low (exp)}
begin
loc_lba[15:8] <= ll_data_in[7:0];
loc_lba[31:24] <= ll_data_in[15:8];
loc_lba[47:40] <= ll_data_in[23:16];
state <= STATE_IN_REG_3;
end
end
STATE_IN_REG_3:
// receiving register FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {Reserved, Reserved, Sector Count (exp), Sector Count}
begin
loc_count[15:0] <= ll_data_in[15:0];
state <= STATE_IN_REG_4;
end
end
STATE_IN_REG_4:
// receiving register FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// correct frame size, finishing
begin
state <= STATE_IDLE;
end
else
// incorrect frame size
begin
state <= STATE_IN_REG_ERR;
dword_cnt <= 14'h4;
end
end
STATE_IN_REG_ERR:
// FIS was started as REG, but for some reason it has a size more than needed
// just wait until it's over and assert an error
begin
if (ll_data_val_in)
if (ll_data_last_in)
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
begin
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
dword_cnt <= dword_cnt + 1'b1;
end
end
STATE_IN_DMAA_ERR:
// FIS was started as DMA Activate, but for some reason it has a size more than needed
// just wait until it's over and assert an error
begin
if (ll_data_val_in)
if (ll_data_last_in)
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
begin
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
dword_cnt <= dword_cnt + 1'b1;
end
end
STATE_IN_DMAS_1:
// receiving DMA Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: DMA Buffer Id Low
begin
loc_dma_id[31:0] <= ll_data_in[31:0];
state <= STATE_IN_DMAS_2;
end
end
STATE_IN_DMAS_2:
// receiving DMA Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: DMA Buffer Id High
begin
loc_dma_id[63:32] <= ll_data_in[31:0];
state <= STATE_IN_DMAS_3;
end
end
STATE_IN_DMAS_3:
// receiving DMA Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: Reserved
begin
state <= STATE_IN_DMAS_4;
end
end
STATE_IN_DMAS_4:
// receiving DMA Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: DMA Buffer Offset
begin
loc_dma_off[31:0] <= ll_data_in[31:0];
state <= STATE_IN_DMAS_5;
end
end
STATE_IN_DMAS_5:
// receiving DMA Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: DMA Transfer Count
begin
loc_dma_cnt[31:0] <= ll_data_in[31:0];
state <= STATE_IN_DMAS_6;
end
end
STATE_IN_DMAS_6:
// receiving DMA Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// correct frame size, finishing, current dword: Reserved
begin
state <= STATE_IDLE;
end
else
// incorrect frame size
begin
state <= STATE_IN_DMAS_ERR;
dword_cnt <= 14'h6;
end
end
STATE_IN_DMAS_ERR:
// FIS was started as DMA Setup, but for some reason it has a size more than needed
// just wait until it's over and assert an error
begin
if (ll_data_val_in)
if (ll_data_last_in)
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
begin
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
dword_cnt <= dword_cnt + 1'b1;
end
end
STATE_IN_BIST_1:
// receiving BIST FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: TODO
begin
state <= STATE_IN_BIST_2;
end
end
STATE_IN_BIST_2:
// receiving BIST FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// correct frame size, finishing, current dword: Reserved
begin
state <= STATE_IDLE;
end
else
// incorrect frame size
begin
state <= STATE_IN_BIST_ERR;
dword_cnt <= 14'h2;
end
end
STATE_IN_BIST_ERR:
// FIS was started as BIST Activate, but for some reason it has a size more than needed
// just wait until it's over and assert an error
begin
if (ll_data_val_in)
if (ll_data_last_in)
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
begin
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
dword_cnt <= dword_cnt + 1'b1;
end
end
STATE_IN_PIOS_1:
// receiving PIO Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {Device, LBA High, LBA Mid, LBA Low}
begin
loc_lba[7:0] <= ll_data_in[7:0];
loc_lba[23:16] <= ll_data_in[15:8];
loc_lba[39:32] <= ll_data_in[23:16];
loc_dev <= ll_data_in[31:24];
state <= STATE_IN_PIOS_2;
end
end
STATE_IN_PIOS_2:
// receiving PIO Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {Reserved, LBA High (exp), LBA Mid (exp), LBA Low (exp)}
begin
loc_lba[15:8] <= ll_data_in[7:0];
loc_lba[31:24] <= ll_data_in[15:8];
loc_lba[47:40] <= ll_data_in[23:16];
state <= STATE_IN_PIOS_3;
end
end
STATE_IN_PIOS_3:
// receiving PIOS FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {E_Status, Reserved, Sector Count (exp), Sector Count}
begin
loc_count[15:0] <= ll_data_in[15:0];
loc_estatus <= ll_data_in[31:24];
state <= STATE_IN_PIOS_4;
end
end
STATE_IN_PIOS_4:
// receiving PIO Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// correct frame size, finishing, current dword: {Reserved, Transfer Count}
begin
loc_tran_cnt <= ll_data_in[15:0];
state <= STATE_IDLE;
end
else
// incorrect frame size
begin
state <= STATE_IN_BIST_ERR;
dword_cnt <= 14'h4;
end
end
STATE_IN_PIOS_ERR:
// FIS was started as PIO Setup Activate, but for some reason it has a size more than needed
// just wait until it's over and assert an error
begin
if (ll_data_val_in)
if (ll_data_last_in)
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
begin
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
dword_cnt <= dword_cnt + 1'b1;
end
end
STATE_IN_SDB_1:
// receiving Set Device Bits FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// correct frame size, finishing, current dword: Reserved
begin
state <= STATE_IDLE;
end
else
// incorrect frame size
begin
state <= STATE_IN_SDB_ERR;
dword_cnt <= 14'h1;
end
end
STATE_IN_SDB_ERR:
// FIS was started as Set Device Bits FIS, but for some reason it has a size more than needed
// just wait until it's over and assert an error
begin
if (ll_data_val_in)
if (ll_data_last_in)
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
begin
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
dword_cnt <= dword_cnt + 1'b1;
end
end
STATE_OUT_DATA_H:
// Send data FIS header
begin
if (ll_data_strobe_in)
begin
state <= STATE_OUT_DATA_D;
dword_cnt <= 14'h1;
end
end
STATE_OUT_DATA_D:
// Send data FIS data payload
begin
if (ll_data_strobe_in)
begin
if (cl_data_last_in)
begin
// All data is transmitted
dword_cnt <= 14'h0;
state <= STATE_OUT_WAIT_RESP;
end
else
if (dword_cnt == 2048)
// data_limit_exceed - wire assigned
state <= STATE_IDLE;
else
begin
state <= STATE_OUT_DATA_D;
dword_cnt <= dword_cnt + 1'b1;
end
end
end
STATE_OUT_REG:
// Register Host 2 Device FIS
begin
if (ll_data_strobe_in)
// 5 header dwords, then wait for a reception on a device side
if (dword_cnt[2:0] == 3'h4)
begin
dword_cnt <= 14'h0;
state <= STATE_OUT_WAIT_RESP;
end
else
begin
state <= STATE_OUT_REG;
dword_cnt <= dword_cnt + 1'b1;
end
end
STATE_OUT_DMAS:
// DMA Setup outcoming FIS
begin
if (ll_data_strobe_in)
// 7 header dwords, then wait for a reception on a device side
if (dword_cnt[2:0] == 3'h6)
begin
dword_cnt <= 14'h0;
state <= STATE_OUT_WAIT_RESP;
end
else
begin
state <= STATE_OUT_DMAS;
dword_cnt <= dword_cnt + 1'b1;
end
end
STATE_OUT_BIST:
begin
if (ll_data_strobe_in)
// 3 header dwords, then wait for a reception on a device side
if (dword_cnt[2:0] == 3'h2)
begin
dword_cnt <= 14'h0;
state <= STATE_OUT_WAIT_RESP;
end
else
begin
state <= STATE_OUT_BIST;
dword_cnt <= dword_cnt + 1'b1;
end
end
STATE_OUT_WAIT_RESP:
begin
if (frame_done_good)
// cmd_done_good wire assigned
state <= STATE_IDLE;
else
if (frame_done_bad)
// cmd_done_bad wire assigned
state <= STATE_IDLE;
else
if (dword_cnt == WATCHDOG_EOF_LIMIT)
// in here dword_cnt works as a watchdog timer
begin
state <= STATE_IDLE;
// watchdog_eof wire assigned
// for now while debugging let it be indicated on higher level TODO Choose exception. May be send incom stop req.
// Be aware of no response for that. In such case go for rst for ll. Or better make link_reset -> 1. And dont forget for oob
end
else
begin
dword_cnt <= dword_cnt + 1'b1;
state <= STATE_OUT_WAIT_RESP;
end
end
STATE_IN_UNRECOG:
begin
if (incom_done | incom_invalidate)
// transmission complete
// incom_ack_bad wire assigned
state <= STATE_IDLE;
else
if (watchdog_dwords)
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
begin
dword_cnt <= dword_cnt + 1'b1;
state <= STATE_IN_UNRECOG;
end
end
default:
begin
end
endcase
// buys circuit
assign cmd_busy = |state | frame_busy;
// respond if received FIS had any meaning in terms of TL
// actual response shall come next tick after done signal to fit LL fsm
reg incom_done_r;
reg incom_done_bad_r;
always @ (posedge clk)
incom_done_bad_r <= incom_done & state == STATE_IN_UNRECOG;
always @ (posedge clk)
incom_done_r <= incom_done;
assign incom_ack_bad = incom_done_bad_r | bad_fis_received;
assign incom_ack_good = incom_done_r & ~incom_ack_bad;
// after a device says it received the FIS, reveal the error code
assign cmd_done_good = state == STATE_OUT_WAIT_RESP & frame_done_good;
assign cmd_done_bad = state == STATE_OUT_WAIT_RESP & frame_done_bad;
// Reg H2D FIS header
wire [31:0] header_regfis;
assign header_regfis = dword_cnt[2:0] == 3'h0 ? {sh_feature_in[7:0], sh_command_in, cmd_type_r == CMD_TYPE_REG_CMD, 3'h0, cmd_port_r, 8'h27} : // features command C R R R PMPort FISType
dword_cnt[2:0] == 3'h1 ? {sh_dev_in, sh_lba_in[39:32], sh_lba_in[23:16], sh_lba_in[7:0]} : // Device LBAHigh LBAMid LBALow
dword_cnt[2:0] == 3'h2 ? {sh_feature_in[15:8], sh_lba_in[47:40], sh_lba_in[31:24], sh_lba_in[15:8]} : // Features (exp) LBAHigh (exp) LBAMid (exp) LBALow (exp)
dword_cnt[2:0] == 3'h3 ? {sh_control_in[7:0], 8'h00, sh_count_in[15:0]} : // Control Reserved SectorCount (exp) SectorCount
/*dword_cnt[2:0] == 3'h4 ?*/ {32'h0000}; // Reserved
// DMA Setup FIS header
wire [31:0] header_dmas;
assign header_dmas = dword_cnt[3:0] == 4'h0 ? {8'h0, 8'h0, sh_autoact_in, sh_inter_in, sh_dir_in, 1'b0, cmd_port_r, 8'h41} : // Reserved, Reserved, A I D R PMPort, FIS Type
dword_cnt[3:0] == 4'h1 ? {sh_dma_id_in[31:0]} : // DMA Buffer Identifier Low
dword_cnt[3:0] == 4'h2 ? {sh_dma_id_in[63:32]} : // DMA Buffer Identifier High
dword_cnt[3:0] == 4'h4 ? {sh_buf_off_in[31:0]} : // DMA Buffer Offset
dword_cnt[3:0] == 4'h5 ? {sh_dma_cnt_in[31:0]} : // DMA Transfer Count
/* 4'h3 | 4'h6 */ {32'h0000}; // Reserved
// BIST Activate FIS header
wire [31:0] header_bist; // TODO
assign header_bist = dword_cnt[2:0] == 3'h0 ? {8'h00, 8'h00, 4'h0, cmd_port_r, 8'h58} : // Reserved, T A S L F P R V, R R R R PMPort, FIS Type
dword_cnt[2:0] == 3'h1 ? {32'h00000000} : // Data1
dword_cnt[2:0] == 3'h2 ? {32'h00000000} : // Data2
{32'h00000000};
// Data FIS header
wire [31:0] header_data;
assign header_data = {8'h00, 8'h00, 4'h0, cmd_port_r, 8'h46}; // Reserved, Reserved, R R R R PMPort, FIS Type
assign ll_header_val = state == STATE_OUT_REG | state == STATE_OUT_DMAS | state == STATE_OUT_BIST | state == STATE_OUT_DATA_H;
assign ll_header_last = state == STATE_OUT_REG & dword_cnt[2:0] == 3'h4 |
state == STATE_OUT_DMAS & dword_cnt[2:0] == 3'h6 |
state == STATE_OUT_BIST & dword_cnt[2:0] == 3'h2;
assign ll_header_dword = {32{state == STATE_OUT_REG}} & header_regfis |
{32{state == STATE_OUT_DMAS}} & header_dmas |
{32{state == STATE_OUT_BIST}} & header_bist |
{32{state == STATE_OUT_DATA_H}} & header_data;
// bypass data from ll to cl if it's data stage in data FIS
assign cl_data_val_out = ll_data_val_in & state == STATE_IN_DATA;
assign cl_data_last_out = ll_data_val_in & ll_data_last_in & state == STATE_IN_DATA;
assign cl_data_mask_out = ll_data_mask_in;
assign cl_data_out = ll_data_in & {32{cl_data_val_out}};
assign ll_data_busy_out = cl_data_busy_in;
// set data to ll: bypass payload from cl or headers constructed in here
assign ll_data_val_out = ll_header_val | cl_data_val_in;
assign ll_data_last_out = ll_header_last & ll_header_val | cl_data_last_in & ~ll_header_val;
assign ll_data_out = ll_header_dword & {32{ll_header_val}} | cl_data_in & {32{~ll_header_val}};
assign ll_data_mask_out = {2{ll_header_val}} | cl_data_mask_in & {2{~ll_header_val}};
// limit was 2048 words + 1 headers
assign data_limit_exceeded = dword_cnt == 14'd2048 & ~cl_data_last_in;
// check if no data was obtained from buffer by ll when we're waiting for a response
wire chk_strobe_while_waitresp;
assign chk_strobe_while_waitresp = state == STATE_OUT_WAIT_RESP & ll_data_strobe_in;
// issue a FIS
assign frame_req = cmd_val & state == STATE_IDLE & ~frame_busy;
// update shadow registers as soon as transaction finishes TODO invalidate in case of errors
// TODO update only corresponding fields, which was updated during the transmission
assign sh_lba_out = loc_lba;
assign sh_count_out = loc_count;
assign sh_command_out = loc_command;
assign sh_err_out = loc_err;
assign sh_status_out = loc_status;
assign sh_estatus_out = loc_estatus;
assign sh_dev_out = loc_dev;
assign sh_port_out = loc_port;
assign sh_inter_out = loc_inter;
assign sh_dir_out = loc_dir;
assign sh_dma_id_out = loc_dma_id;
assign sh_dma_off_out = loc_dma_off;
assign sh_dma_cnt_out = loc_dma_cnt;
assign sh_tran_cnt_out = loc_tran_cnt;
assign sh_notif_out = loc_notif;
assign sh_autoact_out = loc_autoact;
assign sh_lba_val_out = ll_data_last_in;
assign sh_count_val_out = ll_data_last_in;
assign sh_command_val_out = ll_data_last_in;
assign sh_err_val_out = ll_data_last_in;
assign sh_status_val_out = ll_data_last_in;
assign sh_estatus_val_out = ll_data_last_in;
assign sh_dev_val_out = ll_data_last_in;
assign sh_port_val_out = ll_data_last_in;
assign sh_inter_val_out = ll_data_last_in;
assign sh_dir_val_out = ll_data_last_in;
assign sh_dma_id_val_out = ll_data_last_in;
assign sh_dma_off_val_out = ll_data_last_in;
assign sh_dma_cnt_val_out = ll_data_last_in;
assign sh_tran_cnt_val_out = ll_data_last_in;
assign sh_notif_val_out = ll_data_last_in;
assign sh_autoact_val_out = ll_data_last_in;
// dma activate is received when its type met and no errors occurs
assign got_dma_activate = state == STATE_INCOMING & cl_data_last_in & ll_data_val_in & ll_data_in[7:0] == 8'h39;
assign got_dma_activate_port = {4{got_dma_activate}} & ll_data_in[11:8];
`ifdef CHECKERS_ENABLED
always @ (posedge clk)
if (~rst)
if (chk_strobe_while_waitresp)
begin
$display("ERROR in %m: retrieving data while being in a STATE_OUT_WAIT_RESP state");
$finish;
end
`endif
// eof response watchdog
assign watchdog_eof = dword_cnt == WATCHDOG_EOF_LIMIT & state == STATE_OUT_WAIT_RESP;
`ifdef CHECKERS_ENABLED
always @ (posedge clk)
if (~rst)
if (watchdog_eof)
begin
$display("WARNING in %m: watchdog_eof asserted");
$stop;
end
`endif
`ifdef CHECKERS_ENABLED
always @ (posedge clk)
if (~rst)
if (watchdog_dwords)
begin
$display("ERROR in %m: state %h - current FIS contains more than 2048 dwords", state);
$finish;
end
`endif
wire chk_inc_dword_limit_exceeded;
assign chk_inc_dword_limit_exceeded = state == STATE_IN_DATA & dword_cnt == 14'd2049;
`ifdef CHECKERS_ENABLED
always @ (posedge clk)
if (~rst)
if (chk_inc_dword_limit_exceeded)
begin
$display("ERROR in %m: received more than 2048 words in one FIS");
$finish;
end
`endif
endmodule
/*******************************************************************************
* Module: tb
* Date: 2015-07-11
* Author: Alexey
* Description: testbench for top.v
*
* Copyright (c) 2015 Elphel, Inc.
* tb_top.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* tb_top.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
// global defines
`define IVERILOG
`define SIMULATION
`define OPEN_SOURCE_ONLY
`define PRELOAD_BRAMS
`define CHECKERS_ENABLED
/*
* using x393_testbench01.tf style, contains a lot of copy-pasted code from there
*/
`timescale 1ns/1ps
//`include "top.v"
//`include "sata_device.v"
module tb #(
`include "includes/x393_parameters.vh" // SuppressThisWarning VEditor - partially used
`include "includes/x393_simulation_parameters.vh" // SuppressThisWarning VEditor - partially used
)
(
);
`ifdef IVERILOG
`ifdef NON_VDT_ENVIROMENT
parameter fstname="x393.fst";
`else
`include "IVERILOG_INCLUDE.v"
`endif // NON_VDT_ENVIROMENT
`else // IVERILOG
`ifdef CVC
`ifdef NON_VDT_ENVIROMENT
parameter fstname = "x393.fst";
`else // NON_VDT_ENVIROMENT
`include "IVERILOG_INCLUDE.v"
`endif // NON_VDT_ENVIROMENT
`else
parameter fstname = "x393.fst";
`endif // CVC
`endif // IVERILOG
reg [639:0] TESTBENCH_TITLE; // to show human-readable state in the GTKWave
reg [31:0] TESTBENCH_DATA;
reg [11:0] TESTBENCH_ID;
initial #1 $display("HI THERE");
initial
begin
$dumpfile(fstname);
$dumpvars(0, tb); // SuppressThisWarning VEditor - no idea why here was a warning
end
reg EXTCLK_P = 1'b1;
reg EXTCLK_N = 1'b0;
//reg serial_clk = 1'b1;
reg [11:0] ARID_IN_r;
reg [31:0] ARADDR_IN_r;
reg [3:0] ARLEN_IN_r;
reg [1:0] ARSIZE_IN_r;
reg [1:0] ARBURST_IN_r;
reg [11:0] AWID_IN_r;
reg [31:0] AWADDR_IN_r;
reg [3:0] AWLEN_IN_r;
reg [1:0] AWSIZE_IN_r;
reg [1:0] AWBURST_IN_r;
reg [11:0] WID_IN_r;
reg [31:0] WDATA_IN_r;
reg [3:0] WSTRB_IN_r;
reg WLAST_IN_r;
reg DEBUG1, DEBUG2, DEBUG3;
reg [11:0] GLOBAL_WRITE_ID=0;
reg [11:0] GLOBAL_READ_ID=0;
reg [11:0] LAST_ARID; // last issued ARID
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [SIMUL_AXI_READ_WIDTH-1:0] SIMUL_AXI_ADDR_W;
// SuppressWarnings VEditor
wire SIMUL_AXI_MISMATCH;
// SuppressWarnings VEditor
reg [31:0] SIMUL_AXI_READ;
// SuppressWarnings VEditor
reg [SIMUL_AXI_READ_WIDTH-1:0] SIMUL_AXI_ADDR;
// SuppressWarnings VEditor
reg SIMUL_AXI_FULL; // some data available
wire SIMUL_AXI_EMPTY;
reg [31:0] registered_rdata; // here read data from task
reg CLK;
//wire CLK;
reg RST;
reg AR_SET_CMD_r;
wire AR_READY;
reg AW_SET_CMD_r;
wire AW_READY;
reg W_SET_CMD_r;
wire W_READY;
reg [3:0] RD_LAG; // ready signal lag in axi read channel (0 - RDY=1, 1..15 - RDY is asserted N cycles after valid)
reg [3:0] B_LAG; // ready signal lag in axi arete response channel (0 - RDY=1, 1..15 - RDY is asserted N cycles after valid)
// Simulation modules interconnection
wire [11:0] arid;
wire [31:0] araddr;
wire [3:0] arlen;
wire [1:0] arsize;
wire [1:0] arburst;
// SuppressWarnings VEditor : assigned in $readmem(14) system task
wire [3:0] arcache;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [2:0] arprot;
wire arvalid;
wire arready;
wire [11:0] awid;
wire [31:0] awaddr;
wire [3:0] awlen;
wire [1:0] awsize;
wire [1:0] awburst;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [3:0] awcache;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [2:0] awprot;
wire awvalid;
wire awready;
wire [11:0] wid;
wire [31:0] wdata;
wire [3:0] wstrb;
wire wlast;
wire wvalid;
wire wready;
wire [31:0] rdata;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [11:0] rid;
wire rlast;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [1:0] rresp;
wire rvalid;
wire rready;
wire rstb=rvalid && rready;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [1:0] bresp;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [11:0] bid;
wire bvalid;
wire bready;
integer NUM_WORDS_READ;
integer NUM_WORDS_EXPECTED;
reg [15:0] ENABLED_CHANNELS = 0; // currently enabled memory channels
// integer SCANLINE_CUR_X;
// integer SCANLINE_CUR_Y;
wire AXI_RD_EMPTY=NUM_WORDS_READ==NUM_WORDS_EXPECTED; //SuppressThisWarning VEditor : may be unused, just for simulation
assign SIMUL_AXI_EMPTY= ~rvalid && rready && (rid==LAST_ARID); //SuppressThisWarning VEditor : may be unused, just for simulation // use it to wait for?
wire [11:0] #(AXI_TASK_HOLD) ARID_IN = ARID_IN_r;
wire [31:0] #(AXI_TASK_HOLD) ARADDR_IN = ARADDR_IN_r;
wire [3:0] #(AXI_TASK_HOLD) ARLEN_IN = ARLEN_IN_r;
wire [1:0] #(AXI_TASK_HOLD) ARSIZE_IN = ARSIZE_IN_r;
wire [1:0] #(AXI_TASK_HOLD) ARBURST_IN = ARBURST_IN_r;
wire [11:0] #(AXI_TASK_HOLD) AWID_IN = AWID_IN_r;
wire [31:0] #(AXI_TASK_HOLD) AWADDR_IN = AWADDR_IN_r;
wire [3:0] #(AXI_TASK_HOLD) AWLEN_IN = AWLEN_IN_r;
wire [1:0] #(AXI_TASK_HOLD) AWSIZE_IN = AWSIZE_IN_r;
wire [1:0] #(AXI_TASK_HOLD) AWBURST_IN = AWBURST_IN_r;
wire [11:0] #(AXI_TASK_HOLD) WID_IN = WID_IN_r;
wire [31:0] #(AXI_TASK_HOLD) WDATA_IN = WDATA_IN_r;
wire [ 3:0] #(AXI_TASK_HOLD) WSTRB_IN = WSTRB_IN_r;
wire #(AXI_TASK_HOLD) WLAST_IN = WLAST_IN_r;
wire #(AXI_TASK_HOLD) AR_SET_CMD = AR_SET_CMD_r;
wire #(AXI_TASK_HOLD) AW_SET_CMD = AW_SET_CMD_r;
wire #(AXI_TASK_HOLD) W_SET_CMD = W_SET_CMD_r;
//always #(CLKIN_PERIOD/2) CLK = ~CLK;
//assign CLK = dut.axi_aclk;
/*
* connect axi ports to the dut
*/
assign dut.ps7_i.FCLKCLK= {4{CLK}};
assign dut.ps7_i.FCLKRESETN= {RST,~RST,RST,~RST};
// Read address
assign dut.ps7_i.MAXIGP1ARADDR= araddr;
assign dut.ps7_i.MAXIGP1ARVALID= arvalid;
assign arready= dut.ps7_i.MAXIGP1ARREADY;
assign dut.ps7_i.MAXIGP1ARID= arid;
assign dut.ps7_i.MAXIGP1ARLEN= arlen;
assign dut.ps7_i.MAXIGP1ARSIZE= arsize[1:0]; // arsize[2] is not used
assign dut.ps7_i.MAXIGP1ARBURST= arburst;
// Read data
assign rdata= dut.ps7_i.MAXIGP1RDATA;
assign rvalid= dut.ps7_i.MAXIGP1RVALID;
assign dut.ps7_i.MAXIGP1RREADY= rready;
assign rid= dut.ps7_i.MAXIGP1RID;
assign rlast= dut.ps7_i.MAXIGP1RLAST;
assign rresp= dut.ps7_i.MAXIGP1RRESP;
// Write address
assign dut.ps7_i.MAXIGP1AWADDR= awaddr;
assign dut.ps7_i.MAXIGP1AWVALID= awvalid;
assign awready= dut.ps7_i.MAXIGP1AWREADY;
//assign awready= AWREADY_AAAA;
assign dut.ps7_i.MAXIGP1AWID=awid;
// SuppressWarnings VEditor all
// wire [ 1:0] AWLOCK;
// SuppressWarnings VEditor all
// wire [ 3:0] AWCACHE;
// SuppressWarnings VEditor all
// wire [ 2:0] AWPROT;
assign dut.ps7_i.MAXIGP1AWLEN= awlen;
assign dut.ps7_i.MAXIGP1AWSIZE= awsize[1:0]; // awsize[2] is not used
assign dut.ps7_i.MAXIGP1AWBURST= awburst;
// SuppressWarnings VEditor all
// wire [ 3:0] AWQOS;
// Write data
assign dut.ps7_i.MAXIGP1WDATA= wdata;
assign dut.ps7_i.MAXIGP1WVALID= wvalid;
assign wready= dut.ps7_i.MAXIGP1WREADY;
assign dut.ps7_i.MAXIGP1WID= wid;
assign dut.ps7_i.MAXIGP1WLAST= wlast;
assign dut.ps7_i.MAXIGP1WSTRB= wstrb;
// Write response
assign bvalid= dut.ps7_i.MAXIGP1BVALID;
assign dut.ps7_i.MAXIGP1BREADY= bready;
assign bid= dut.ps7_i.MAXIGP1BID;
assign bresp= dut.ps7_i.MAXIGP1BRESP;
// Simulation modules
simul_axi_master_rdaddr
#(
.ID_WIDTH(12),
.ADDRESS_WIDTH(32),
.LATENCY(AXI_RDADDR_LATENCY), // minimal delay between inout and output ( 0 - next cycle)
.DEPTH(8), // maximal number of commands in FIFO
.DATA_DELAY(3.5),
.VALID_DELAY(4.0)
) simul_axi_master_rdaddr_i (
.clk(CLK),
.reset(RST),
.arid_in(ARID_IN[11:0]),
.araddr_in(ARADDR_IN[31:0]),
.arlen_in(ARLEN_IN[3:0]),
.arsize_in(ARSIZE_IN[1:0]),
.arburst_in(ARBURST_IN[1:0]),
.arcache_in(4'b0),
.arprot_in(3'b0), // .arprot_in(2'b0),
.arid(arid[11:0]),
.araddr(araddr[31:0]),
.arlen(arlen[3:0]),
.arsize(arsize[1:0]),
.arburst(arburst[1:0]),
.arcache(arcache[3:0]),
.arprot(arprot[2:0]),
.arvalid(arvalid),
.arready(arready),
.set_cmd(AR_SET_CMD), // latch all other input data at posedge of clock
.ready(AR_READY) // command/data FIFO can accept command
);
simul_axi_master_wraddr
#(
.ID_WIDTH(12),
.ADDRESS_WIDTH(32),
.LATENCY(AXI_WRADDR_LATENCY), // minimal delay between inout and output ( 0 - next cycle)
.DEPTH(8), // maximal number of commands in FIFO
.DATA_DELAY(3.5),
.VALID_DELAY(4.0)
) simul_axi_master_wraddr_i (
.clk(CLK),
.reset(RST),
.awid_in(AWID_IN[11:0]),
.awaddr_in(AWADDR_IN[31:0]),
.awlen_in(AWLEN_IN[3:0]),
.awsize_in(AWSIZE_IN[1:0]),
.awburst_in(AWBURST_IN[1:0]),
.awcache_in(4'b0),
.awprot_in(3'b0), //.awprot_in(2'b0),
.awid(awid[11:0]),
.awaddr(awaddr[31:0]),
.awlen(awlen[3:0]),
.awsize(awsize[1:0]),
.awburst(awburst[1:0]),
.awcache(awcache[3:0]),
.awprot(awprot[2:0]),
.awvalid(awvalid),
.awready(awready),
.set_cmd(AW_SET_CMD), // latch all other input data at posedge of clock
.ready(AW_READY) // command/data FIFO can accept command
);
simul_axi_master_wdata
#(
.ID_WIDTH(12),
.DATA_WIDTH(32),
.WSTB_WIDTH(4),
.LATENCY(AXI_WRDATA_LATENCY), // minimal delay between inout and output ( 0 - next cycle)
.DEPTH(8), // maximal number of commands in FIFO
.DATA_DELAY(3.2),
.VALID_DELAY(3.6)
) simul_axi_master_wdata_i (
.clk(CLK),
.reset(RST),
.wid_in(WID_IN[11:0]),
.wdata_in(WDATA_IN[31:0]),
.wstrb_in(WSTRB_IN[3:0]),
.wlast_in(WLAST_IN),
.wid(wid[11:0]),
.wdata(wdata[31:0]),
.wstrb(wstrb[3:0]),
.wlast(wlast),
.wvalid(wvalid),
.wready(wready),
.set_cmd(W_SET_CMD), // latch all other input data at posedge of clock
.ready(W_READY) // command/data FIFO can accept command
);
simul_axi_slow_ready simul_axi_slow_ready_read_i(
.clk(CLK),
.reset(RST), //input reset,
.delay(RD_LAG), //input [3:0] delay,
.valid(rvalid), // input valid,
.ready(rready) //output ready
);
simul_axi_slow_ready simul_axi_slow_ready_write_resp_i(
.clk(CLK),
.reset(RST), //input reset,
.delay(B_LAG), //input [3:0] delay,
.valid(bvalid), // input ADDRESS_NUMBER+2:0 valid,
.ready(bready) //output ready
);
simul_axi_read #(
.ADDRESS_WIDTH(SIMUL_AXI_READ_WIDTH)
) simul_axi_read_i(
.clk(CLK),
.reset(RST),
.last(rlast),
.data_stb(rstb),
.raddr(ARADDR_IN[SIMUL_AXI_READ_WIDTH+1:2]),
.rlen(ARLEN_IN),
.rcmd(AR_SET_CMD),
.addr_out(SIMUL_AXI_ADDR_W[SIMUL_AXI_READ_WIDTH-1:0]),
.burst(), // burst in progress - just debug
.err_out()); // data last does not match predicted or FIFO over/under run - just debug
// device-under-test instance
wire rxn;
wire rxp;
wire txn;
wire txp;
wire device_rst;
top dut(
.RXN (rxn),
.RXP (rxp),
.TXN (txn),
.TXP (txp),
.EXTCLK_P (EXTCLK_P),
.EXTCLK_N (EXTCLK_N)
);
assign device_rst = dut.axi_rst;
sata_device dev(
.rst (device_rst),
.RXN (txn),
.RXP (txp),
.TXN (rxn),
.TXP (rxp),
.EXTCLK_P (EXTCLK_P),
.EXTCLK_N (EXTCLK_N)
);
// SAXI HP interface
// axi_hp simulation signals
wire HCLK;
wire [31:0] afi_sim_rd_address; // output[31:0]
wire [ 5:0] afi_sim_rid; // output[5:0] SuppressThisWarning VEditor - not used - just view
// reg afi_sim_rd_valid; // input
wire afi_sim_rd_valid; // input
wire afi_sim_rd_ready; // output
// reg [63:0] afi_sim_rd_data; // input[63:0]
wire [63:0] afi_sim_rd_data; // input[63:0]
wire [ 2:0] afi_sim_rd_cap; // output[2:0] SuppressThisWarning VEditor - not used - just view
wire [ 3:0] afi_sim_rd_qos; // output[3:0] SuppressThisWarning VEditor - not used - just view
wire [ 1:0] afi_sim_rd_resp; // input[1:0]
// reg [ 1:0] afi_sim_rd_resp; // input[1:0]
wire [31:0] afi_sim_wr_address; // output[31:0] SuppressThisWarning VEditor - not used - just view
wire [ 5:0] afi_sim_wid; // output[5:0] SuppressThisWarning VEditor - not used - just view
wire afi_sim_wr_valid; // output
wire afi_sim_wr_ready; // input
// reg afi_sim_wr_ready; // input
wire [63:0] afi_sim_wr_data; // output[63:0] SuppressThisWarning VEditor - not used - just view
wire [ 7:0] afi_sim_wr_stb; // output[7:0] SuppressThisWarning VEditor - not used - just view
wire [ 3:0] afi_sim_bresp_latency; // input[3:0]
// reg [ 3:0] afi_sim_bresp_latency; // input[3:0]
wire [ 2:0] afi_sim_wr_cap; // output[2:0] SuppressThisWarning VEditor - not used - just view
wire [ 3:0] afi_sim_wr_qos; // output[3:0] SuppressThisWarning VEditor - not used - just view
assign HCLK = dut.ps7_i.SAXIHP3ACLK; // shortcut name
// afi loopback
assign #1 afi_sim_rd_data= afi_sim_rd_ready?{2'h0,afi_sim_rd_address[31:3],1'h1, 2'h0,afi_sim_rd_address[31:3],1'h0}:64'bx;
assign #1 afi_sim_rd_valid = afi_sim_rd_ready;
assign #1 afi_sim_rd_resp = afi_sim_rd_ready?2'b0:2'bx;
assign #1 afi_sim_wr_ready = afi_sim_wr_valid;
assign #1 afi_sim_bresp_latency=4'h5;
// axi_hp register access
// PS memory mapped registers to read/write over a separate simulation bus running at HCLK, no waits
reg [31:0] PS_REG_ADDR;
reg PS_REG_WR;
reg PS_REG_RD;
reg [31:0] PS_REG_DIN;
wire [31:0] PS_REG_DOUT;
reg [31:0] PS_RDATA; // SuppressThisWarning VEditor - not used - just view
/*
reg [31:0] afi_reg_addr;
reg afi_reg_wr;
reg afi_reg_rd;
reg [31:0] afi_reg_din;
wire [31:0] afi_reg_dout;
reg [31:0] AFI_REG_RD; // SuppressThisWarning VEditor - not used - just view
*/
initial begin
PS_REG_ADDR <= 'bx;
PS_REG_WR <= 0;
PS_REG_RD <= 0;
PS_REG_DIN <= 'bx;
PS_RDATA <= 'bx;
end
always @ (posedge HCLK) if (PS_REG_RD) PS_RDATA <= PS_REG_DOUT;
simul_axi_hp_rd #(
.HP_PORT(3)
) simul_axi_hp_rd_i (
.rst (RST), // input
.aclk (dut.ps7_i.SAXIHP3ACLK), // input
.aresetn (), // output
.araddr (dut.ps7_i.SAXIHP3ARADDR[31:0]), // input[31:0]
.arvalid (dut.ps7_i.SAXIHP3ARVALID), // input
.arready (dut.ps7_i.SAXIHP3ARREADY), // output
.arid (dut.ps7_i.SAXIHP3ARID), // input[5:0]
.arlock (dut.ps7_i.SAXIHP3ARLOCK), // input[1:0]
.arcache (dut.ps7_i.SAXIHP3ARCACHE), // input[3:0]
.arprot (dut.ps7_i.SAXIHP3ARPROT), // input[2:0]
.arlen (dut.ps7_i.SAXIHP3ARLEN), // input[3:0]
.arsize (dut.ps7_i.SAXIHP3ARSIZE), // input[2:0]
.arburst (dut.ps7_i.SAXIHP3ARBURST), // input[1:0]
.arqos (dut.ps7_i.SAXIHP3ARQOS), // input[3:0]
.rdata (dut.ps7_i.SAXIHP3RDATA), // output[63:0]
.rvalid (dut.ps7_i.SAXIHP3RVALID), // output
.rready (dut.ps7_i.SAXIHP3RREADY), // input
.rid (dut.ps7_i.SAXIHP3RID), // output[5:0]
.rlast (dut.ps7_i.SAXIHP3RLAST), // output
.rresp (dut.ps7_i.SAXIHP3RRESP), // output[1:0]
.rcount (dut.ps7_i.SAXIHP3RCOUNT), // output[7:0]
.racount (dut.ps7_i.SAXIHP3RACOUNT), // output[2:0]
.rdissuecap1en (dut.ps7_i.SAXIHP3RDISSUECAP1EN), // input
.sim_rd_address (afi_sim_rd_address), // output[31:0]
.sim_rid (afi_sim_rid), // output[5:0]
.sim_rd_valid (afi_sim_rd_valid), // input
.sim_rd_ready (afi_sim_rd_ready), // output
.sim_rd_data (afi_sim_rd_data), // input[63:0]
.sim_rd_cap (afi_sim_rd_cap), // output[2:0]
.sim_rd_qos (afi_sim_rd_qos), // output[3:0]
.sim_rd_resp (afi_sim_rd_resp), // input[1:0]
.reg_addr (PS_REG_ADDR), // input[31:0]
.reg_wr (PS_REG_WR), // input
.reg_rd (PS_REG_RD), // input
.reg_din (PS_REG_DIN), // input[31:0]
.reg_dout (PS_REG_DOUT) // output[31:0]
);
simul_axi_hp_wr #(
.HP_PORT(3)
) simul_axi_hp_wr_i (
.rst (RST), // input
.aclk (dut.ps7_i.SAXIHP3ACLK), // input
.aresetn (), // output
.awaddr (dut.ps7_i.SAXIHP3AWADDR), // input[31:0]
.awvalid (dut.ps7_i.SAXIHP3AWVALID), // input
.awready (dut.ps7_i.SAXIHP3AWREADY), // output
.awid (dut.ps7_i.SAXIHP3AWID), // input[5:0]
.awlock (dut.ps7_i.SAXIHP3AWLOCK), // input[1:0]
.awcache (dut.ps7_i.SAXIHP3AWCACHE), // input[3:0]
.awprot (dut.ps7_i.SAXIHP3AWPROT), // input[2:0]
.awlen (dut.ps7_i.SAXIHP3AWLEN), // input[3:0]
.awsize (dut.ps7_i.SAXIHP3AWSIZE), // input[2:0]
.awburst (dut.ps7_i.SAXIHP3AWBURST), // input[1:0]
.awqos (dut.ps7_i.SAXIHP3AWQOS), // input[3:0]
.wdata (dut.ps7_i.SAXIHP3WDATA), // input[63:0]
.wvalid (dut.ps7_i.SAXIHP3WVALID), // input
.wready (dut.ps7_i.SAXIHP3WREADY), // output
.wid (dut.ps7_i.SAXIHP3WID), // input[5:0]
.wlast (dut.ps7_i.SAXIHP3WLAST), // input
.wstrb (dut.ps7_i.SAXIHP3WSTRB), // input[7:0]
.bvalid (dut.ps7_i.SAXIHP3BVALID), // output
.bready (dut.ps7_i.SAXIHP3BREADY), // input
.bid (dut.ps7_i.SAXIHP3BID), // output[5:0]
.bresp (dut.ps7_i.SAXIHP3BRESP), // output[1:0]
.wcount (dut.ps7_i.SAXIHP3WCOUNT), // output[7:0]
.wacount (dut.ps7_i.SAXIHP3WACOUNT), // output[5:0]
.wrissuecap1en (dut.ps7_i.SAXIHP3WRISSUECAP1EN), // input
.sim_wr_address (afi_sim_wr_address), // output[31:0]
.sim_wid (afi_sim_wid), // output[5:0]
.sim_wr_valid (afi_sim_wr_valid), // output
.sim_wr_ready (afi_sim_wr_ready), // input
.sim_wr_data (afi_sim_wr_data), // output[63:0]
.sim_wr_stb (afi_sim_wr_stb), // output[7:0]
.sim_bresp_latency(afi_sim_bresp_latency), // input[3:0]
.sim_wr_cap (afi_sim_wr_cap), // output[2:0]
.sim_wr_qos (afi_sim_wr_qos), // output[3:0]
.reg_addr (PS_REG_ADDR), // input[31:0]
.reg_wr (PS_REG_WR), // input
.reg_rd (PS_REG_RD), // input
.reg_din (PS_REG_DIN), // input[31:0]
.reg_dout (PS_REG_DOUT) // output[31:0]
);
// wire [ 3:0] SIMUL_ADD_ADDR;
always @ (posedge CLK) begin
if (RST) SIMUL_AXI_FULL <=0;
else if (rstb) SIMUL_AXI_FULL <=1;
if (RST) begin
NUM_WORDS_READ <= 0;
end else if (rstb) begin
NUM_WORDS_READ <= NUM_WORDS_READ + 1;
end
if (rstb) begin
SIMUL_AXI_ADDR <= SIMUL_AXI_ADDR_W;
SIMUL_AXI_READ <= rdata;
`ifdef DEBUG_RD_DATA
$display (" Read data (addr:data): 0x%x:0x%x @%t",SIMUL_AXI_ADDR_W,rdata,$time);
`endif
end
end
//tasks
`include "includes/x393_tasks01.vh" // SuppressThisWarning VEditor - partially used
`include "includes/x393_tasks_afi.vh" // SuppressThisWarning VEditor - partially used
/*
* Monitor maxi bus read data.
* No burst assumed, so we're interested only in 3 signals to monitor on.
* Every time something is on a bus, data and id of a transaction are pushed into a fifo
* Fifo can be read by maxiMonitorPop function. Check if fifo is empty by calling maxiMonitorIsEmpty()
*/
// path to these signals
wire [31:0] maxi_monitor_rdata;
wire [11:0] maxi_monitor_rid;
wire maxi_monitor_rvalid;
assign maxi_monitor_rdata = dut.ps7_i.MAXIGP1RDATA;
assign maxi_monitor_rid = dut.ps7_i.MAXIGP1RID;
assign maxi_monitor_rvalid = dut.ps7_i.MAXIGP1RVALID;
localparam maxi_monitor_fifo_size = 2049;
reg [43:0] maxi_monitor_fifo [maxi_monitor_fifo_size - 1:0];
integer maxi_monitor_raddr = 0;
integer maxi_monitor_waddr = 0;
reg maxi_monitor_fifo_empty = 1;
function maxiMonitorIsEmpty( // SuppressThisWarning VEditor - it's ok
input dummy // SuppressThisWarning VEditor - it's ok
);
begin
maxiMonitorIsEmpty = maxi_monitor_fifo_empty;
end
endfunction
task maxiMonitorPop;
output reg [31:0] data;
output integer id;
begin
if ((maxi_monitor_waddr == maxi_monitor_raddr) && maxi_monitor_fifo_empty) begin
$display("[Testbench] maxiMonitorPop: Trying to pop from an empty fifo");
$finish;
end
data = maxi_monitor_fifo[maxi_monitor_raddr][31:0]; // RDATA
id = maxi_monitor_fifo[maxi_monitor_raddr][43:32]; // RID // SuppressThisWarning VEditor - it's ok
maxi_monitor_raddr = (maxi_monitor_raddr + 1) % maxi_monitor_fifo_size;
if (maxi_monitor_waddr == maxi_monitor_raddr) begin
maxi_monitor_fifo_empty = 1;
end
end
endtask
task maxiMonitorPush;
input [31:0] data;
input [11:0] id;
begin
if (maxi_monitor_raddr == (maxi_monitor_waddr + 1)) begin
$display("[Testbench] maxiMonitorPush: trying to push to a full fifo");
TESTBENCH_TITLE = "trying to push to a full fifo";
$display("[Testbench] maxiMonitorPush %s = %h, id = %h @%t", TESTBENCH_TITLE, $time);
$finish;
end
maxi_monitor_fifo[maxi_monitor_waddr][31:0] = data;
maxi_monitor_fifo[maxi_monitor_waddr][43:32] = id;
maxi_monitor_fifo_empty = 1'b0;
// $display("[Testbench] MAXI: Got data = %h, id = %h", data, id);
TESTBENCH_TITLE = "Got data";
TESTBENCH_DATA = data;
TESTBENCH_ID = id;
$display("[Testbench] MAXI %s = %h, id = %h @%t", TESTBENCH_TITLE, TESTBENCH_DATA, TESTBENCH_ID, $time);
//[Testbench] MAXI: %
maxi_monitor_waddr = (maxi_monitor_waddr + 1) % maxi_monitor_fifo_size;
end
endtask
initial forever @ (posedge CLK) begin
if (~RST) begin
if (maxi_monitor_rvalid) begin
maxiMonitorPush(maxi_monitor_rdata, maxi_monitor_rid);
end
end
end
// testing itself
`include "test_top.v" // S uppressThisWarning VEditor - to avoid strange warnings
endmodule
//`include "x393/glbl.v" // SuppressThisWarning VEditor - duplicate module
/*******************************************************************************
* Module: tb
* Date: 2015-07-11
* Author: Alexey
* Description: dut inputs control for for tb_top.v
*
* Copyright (c) 2015 Elphel, Inc.
* test_top.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* test_top.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
/*
* this file is included into tb_top.v due to the compatibility with x393 design testbench
*/
reg [639:0] TEST_TITLE; // to show human-readable state in the GTKWave
// external clock to gtx
always #3.333
begin
EXTCLK_P = ~EXTCLK_P;
EXTCLK_N = ~EXTCLK_N;
end
// MAXI clock
always #10
begin
CLK = ~CLK;
end
integer i;
integer status;
integer id;
reg [31:0] data;
// write registers
initial
begin
CLK =1'b0;
RST = 1'bx;
AR_SET_CMD_r = 1'b0;
AW_SET_CMD_r = 1'b0;
W_SET_CMD_r = 1'b0;
#500;
// $display ("x393_i.ddrc_sequencer_i.phy_cmd_i.phy_top_i.rst=%d",x393_i.ddrc_sequencer_i.phy_cmd_i.phy_top_i.rst);
#500;
RST = 1'b1;
NUM_WORDS_EXPECTED =0;
// #99000; // same as glbl
#900; // same as glbl
repeat (20) @(posedge EXTCLK_P) ;
RST =1'b0;
@ (negedge dut.sata_top.sata_rst);
repeat (20)
@ (posedge dev.clk);
// test MAXI1 inface
axi_set_rd_lag(0);
axi_write_single(32'h4, 32'hdeadbeef);
// axi_read_addr(12'h777, 32'h4, 4'h3, 2'b01);
repeat (7)
@ (posedge dev.clk);
axi_write_single(32'h8, 32'hd34db33f);
// axi_read_addr(12'h555, 32'h0, 4'h3, 2'b01);
for (i = 0; i < 2048; i = i + 1) begin
dev.receive_data_pause[i] = 32'h0;
end
dev.receive_wait_fifo = 0;
// issue Identify Device command
// ATAPI command id = EC
axi_write_single({30'h5, 2'b00}, 32'hEC);
// start!
axi_write_single({30'hf, 2'b00}, 32'h0108);
// $display("[Test]: H2D Reg with pio cmd issued");
TEST_TITLE = "H2D Reg with pio cmd issued";
$display("[Test]: %s @%t", TEST_TITLE, $time);
// wait until reception
while (dev.receive_id != 1) begin
repeat (100)
@ (posedge dev.clk);
end
if (dev.receive_status != 0) begin
// $display("[Test]: Failed 1");
TEST_TITLE = "Failed #1";
$display("[Test]: %s @%t", TEST_TITLE, $time);
$finish;
end
// $display("[Test]: H2D Reg with pio cmd received by dev");
TEST_TITLE = "H2D Reg with pio cmd received by dev";
$display("[Test]: %s @%t", TEST_TITLE, $time);
// send dev2host reg fis with BSY flag
repeat (100)
@ (posedge dev.clk);
for (i = 0; i < 2048; i = i + 1) begin
dev.transmit_data_pause[i] = 32'h0;
end
dev.transmit_data[0] = 32'h00800034; // BSY -> 1, type = dev2host reg
dev.transmit_data[1] = 32'hdeadbeef; // whatever
dev.transmit_data[2] = 32'hdeadbeef; // whatever
dev.transmit_data[3] = 32'hdeadbeef; // whatever
dev.transmit_data[4] = 32'hdeadbeef; // whatever
dev.linkTransmitFIS(66, 5, 0, status);
if (status != 0) begin
// $display("[Test]: Failed 2");
TEST_TITLE = "Failed #2";
$display("[Test]: %s @%t", TEST_TITLE, $time);
$finish;
end
// $display("[Test]: Dev sent BSY flag");
TEST_TITLE = "Dev sent BSY flag";
$display("[Test]: %s @%t", TEST_TITLE, $time);
// checks if BSY is set up // only on waves TODO
axi_read_addr(12'h555, {30'h11, 2'b00}, 4'h3, 2'b01);
repeat (50)
@ (posedge dev.clk);
// $display("[Test]: Device sends PIO Setup");
TEST_TITLE = "Device sends PIO Setup";
$display("[Test]: %s @%t", TEST_TITLE, $time);
dev.transmit_data[0] = 32'h0080205f; // direction d2h, type = 5f
dev.transmit_data[1] = 32'hdeadbeef; // whatever
dev.transmit_data[2] = 32'hdeadbeef; // whatever
dev.transmit_data[3] = 32'h00adbeef; // whatever
dev.transmit_data[4] = 32'h00000014; // let it be 20 bytes to be transfered
dev.linkTransmitFIS(11, 5, 0, status);
if (status != 0) begin
// $display("[Test]: Failed 3");
TEST_TITLE = "Failed #3";
$display("[Test]: %s @%t", TEST_TITLE, $time);
$finish;
end
// $display("[Test]: Device sends data FIS");
TEST_TITLE = "Device sends data FIS";
$display("[Test]: %s @%t", TEST_TITLE, $time);
dev.transmit_data[0] = 32'h00000046; // type = 46
dev.transmit_data[1] = 32'hfeeddeaf;
dev.transmit_data[2] = 32'ha114bea7;
dev.transmit_data[3] = 32'hca110911;
dev.transmit_data[4] = 32'hCA715F1E;
dev.transmit_data[5] = 32'hdeadbeef;
dev.linkTransmitFIS(22, 6, 0, status);
if (status != 0) begin
// $display("[Test]: Failed 4");
TEST_TITLE = "Failed #4";
$display("[Test]: %s @%t", TEST_TITLE, $time);
$finish;
end
repeat (20)
@ (posedge dev.clk);
// prepare monitor - clean it before actual usage
while (~maxiMonitorIsEmpty(0)) begin
maxiMonitorPop(data, id);
end
// imitating PIO reads
// $display("[Test]: Read data word 0");
TEST_TITLE = "Read data word 0";
$display("[Test]: %s @%t", TEST_TITLE, $time);
axi_read_addr(12'h660, {30'h00, 2'b00}, 4'h0, 2'b01);
// $display("[Test]: Read data word 1");
TEST_TITLE = "Read data word 1";
$display("[Test]: %s @%t", TEST_TITLE, $time);
axi_read_addr(12'h661, {30'h00, 2'b00}, 4'h0, 2'b01);
// $display("[Test]: Read data word 2");
TEST_TITLE = "Read data word 2";
$display("[Test]: %s @%t", TEST_TITLE, $time);
axi_read_addr(12'h662, {30'h00, 2'b00}, 4'h0, 2'b01);
// $display("[Test]: Read data word 3");
TEST_TITLE = "Read data word 3";
$display("[Test]: %s @%t", TEST_TITLE, $time);
axi_read_addr(12'h663, {30'h00, 2'b00}, 4'h0, 2'b01);
// $display("[Test]: Read data word 4");
TEST_TITLE = "Read data word 4";
$display("[Test]: %s @%t", TEST_TITLE, $time);
axi_read_addr(12'h664, {30'h00, 2'b00}, 4'h0, 2'b01);
// check if all ok
i = 0;
while (~maxiMonitorIsEmpty(0)) begin
maxiMonitorPop(data, id);
if (dev.transmit_data[i] != data) begin
// $display("[Test]: Data check failed");
TEST_TITLE = "Data check failed";
$display("[Test]: %s @%t", TEST_TITLE, $time);
$finish;
end
i = i + 1;
end
// $display("[Test]: Data check OK");
TEST_TITLE = "Data check OK";
$display("[Test]: %s @%t", TEST_TITLE, $time);
repeat (30)
@ (posedge dev.clk);
/* for (i = 0; i < 32; i = i + 1) begin
$display("data received : %h", dev.receive_data[i]);
end*/
$display("============= DONE =============");
TEST_TITLE = "DONE";
$finish;
// test SAXI3 iface
/* afi_setup(3);
axi_write_single(32'h10, 32'h0add9e55); // addr
axi_write_single(32'h14, 32'h12345678); // lba
axi_write_single(32'h18, 32'h00000020); // sector count
axi_write_single(32'h20, 32'h00100000); // dma type
axi_write_single(32'h24, 32'h00010000); // start
axi_write_single(32'h28, 32'hdeadbee2); // data
axi_write_single(32'h2c, 32'hdeadbee3); // data
axi_write_single(32'h1c, 32'hffffffff); // start */
end
/*
// control the device
reg [112:0] rprim;
integer status;
initial
begin
@ (posedge dev.phy_ready);
repeat (30)
@ (posedge dev.clk);
dev.linkSendPrim("XRDY");
rprim = dev.linkGetPrim(0);
while (rprim != "RRDY") begin
if (rprim != "SYNC") begin
$display("Expected SYNC primitive, got %8s", rprim);
$finish;
end
@ (posedge dev.clk)
rprim = dev.linkGetPrim(0);
end
dev.linkSendPrim("SYNC");
repeat (30)
@ (posedge dev.clk);
for (i = 0; i < 2048; i = i + 1) begin
dev.transmit_data[i] = 32'hdeadbeef;
dev.transmit_data_pause[i] = 32'h0;
end
// dev.transmit_crc = 32'hfd60f8a6;
dev.transmit_crc = 32'hfd60f8a5;
dev.linkTransmitFIS(66, 12, status);
$display("Fis %d transmitted, status %d", 66, status);
repeat (1000)
@ (posedge dev.clk);
$display("============= DONE =============");
$finish;
end
*/
initial begin
#150000;
// $display("[Test]: Failed");
TEST_TITLE = "Failed (timelimit)";
$display("[Test]: %s @%t", TEST_TITLE, $time);
$display("============= TIMELIMIT =============");
$finish;
end
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