diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/debounce_switch.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/debounce_switch.v index bb631cc35..8e93a50c4 100644 --- a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/debounce_switch.v +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/debounce_switch.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes switch and button inputs with a slow sampled shift register @@ -87,3 +89,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/fpga.v index 50adc0ec4..be6d5b4ba 100644 --- a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -414,3 +416,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/fpga_core.v index 8e604fe18..021017f7b 100644 --- a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1120,3 +1122,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/debounce_switch.v b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/debounce_switch.v index bb631cc35..8e93a50c4 100644 --- a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/debounce_switch.v +++ b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/debounce_switch.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes switch and button inputs with a slow sampled shift register @@ -87,3 +89,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/fpga.v index ce3e813f3..58b134791 100644 --- a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -422,3 +424,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/fpga_core.v index b1b0ddd49..7ce3ac2f9 100644 --- a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1117,3 +1119,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/AU200/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/AU200/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/debounce_switch.v b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/debounce_switch.v index bb631cc35..8e93a50c4 100644 --- a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/debounce_switch.v +++ b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/debounce_switch.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes switch and button inputs with a slow sampled shift register @@ -87,3 +89,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/fpga.v index ce3e813f3..58b134791 100644 --- a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -422,3 +424,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/fpga_core.v index b1b0ddd49..7ce3ac2f9 100644 --- a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1117,3 +1119,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/AU250/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/AU250/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/fpga.v index fed9982c2..a2d12e569 100644 --- a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -401,3 +403,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/fpga_core.v index 789630448..e027507c1 100644 --- a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1109,3 +1111,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/AU280/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/AU280/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/fpga.v index 5d220a50d..00e8fa2de 100644 --- a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -410,3 +412,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/fpga_core.v index 0d383bdfa..2ac1619f9 100644 --- a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1120,3 +1122,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/AU50/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/AU50/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/debounce_switch.v b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/debounce_switch.v index bb631cc35..8e93a50c4 100644 --- a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/debounce_switch.v +++ b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/debounce_switch.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes switch and button inputs with a slow sampled shift register @@ -87,3 +89,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/fpga.v index f327b6e8e..3ebeea1af 100644 --- a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -409,3 +411,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/fpga_core.v index f8708405a..bb9fada6f 100644 --- a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1122,3 +1124,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/ExaNIC_X10/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/debounce_switch.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/debounce_switch.v index bb631cc35..8e93a50c4 100644 --- a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/debounce_switch.v +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/debounce_switch.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes switch and button inputs with a slow sampled shift register @@ -87,3 +89,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/fpga.v index 0e6ec35a5..ce62af7c8 100644 --- a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -408,3 +410,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/fpga_core.v index 3c8908a94..2c26bec58 100644 --- a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1120,3 +1122,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/debounce_switch.v b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/debounce_switch.v index bb631cc35..8e93a50c4 100644 --- a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/debounce_switch.v +++ b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/debounce_switch.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes switch and button inputs with a slow sampled shift register @@ -87,3 +89,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/fpga.v index c9295be4d..93ddb1620 100644 --- a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -439,3 +441,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/fpga_core.v index 090a7952f..c5819b9d5 100644 --- a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1112,3 +1114,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/VCU108/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/debounce_switch.v b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/debounce_switch.v index bb631cc35..8e93a50c4 100644 --- a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/debounce_switch.v +++ b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/debounce_switch.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes switch and button inputs with a slow sampled shift register @@ -87,3 +89,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/fpga.v index 8e2da145c..c84007873 100644 --- a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -453,3 +455,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/fpga_core.v index 1a32d0710..0700f1f13 100644 --- a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1122,3 +1124,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/VCU118/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/debounce_switch.v b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/debounce_switch.v index bb631cc35..8e93a50c4 100644 --- a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/debounce_switch.v +++ b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/debounce_switch.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes switch and button inputs with a slow sampled shift register @@ -87,3 +89,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/fpga.v index ce3e813f3..58b134791 100644 --- a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -422,3 +424,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/fpga_core.v index b1b0ddd49..7ce3ac2f9 100644 --- a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1117,3 +1119,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/VCU1525/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/debounce_switch.v b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/debounce_switch.v index bb631cc35..8e93a50c4 100644 --- a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/debounce_switch.v +++ b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/debounce_switch.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes switch and button inputs with a slow sampled shift register @@ -87,3 +89,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/fpga.v index 4f3ebc411..5bd4bf931 100644 --- a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -444,3 +446,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/fpga_core.v index 3dccfb81d..5c033f2db 100644 --- a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1122,3 +1124,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/ZCU106/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/common/driver/example/example_driver.c b/fpga/lib/pcie/example/common/driver/example/example_driver.c index 86ade9105..dd4bcc7ba 100644 --- a/fpga/lib/pcie/example/common/driver/example/example_driver.c +++ b/fpga/lib/pcie/example/common/driver/example/example_driver.c @@ -1,6 +1,6 @@ /* -Copyright (c) 2018 Alex Forencich +Copyright (c) 2018-2021 Alex Forencich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -46,323 +46,317 @@ static int map_bars(struct example_dev *edev, struct pci_dev *pdev); static void free_bars(struct example_dev *edev, struct pci_dev *pdev); static const struct pci_device_id pci_ids[] = { - { PCI_DEVICE(0x1234, 0x0001) }, - { 0 /* end */ } + {PCI_DEVICE(0x1234, 0x0001)}, + {0 /* end */ } }; MODULE_DEVICE_TABLE(pci, pci_ids); static irqreturn_t edev_intr(int irq, void *data) { - struct example_dev *edev = data; - struct device *dev = &edev->pdev->dev; + struct example_dev *edev = data; + struct device *dev = &edev->pdev->dev; - edev->irqcount++; + edev->irqcount++; - dev_info(dev, "Interrupt"); + dev_info(dev, "Interrupt"); - return IRQ_HANDLED; + return IRQ_HANDLED; } static int edev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - int ret = 0; - struct example_dev *edev; - struct device *dev = &pdev->dev; + int ret = 0; + struct example_dev *edev; + struct device *dev = &pdev->dev; - int k; + int k; - dev_info(dev, DRIVER_NAME " probe"); - dev_info(dev, " Vendor: 0x%04x", pdev->vendor); - dev_info(dev, " Device: 0x%04x", pdev->device); - dev_info(dev, " Class: 0x%06x", pdev->class); - dev_info(dev, " PCI ID: %04x:%02x:%02x.%d", pci_domain_nr(pdev->bus), - pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - if (pdev->pcie_cap) { - u16 devctl; - u32 lnkcap; - u16 lnksta; - pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_DEVCTL, &devctl); - pci_read_config_dword(pdev, pdev->pcie_cap + PCI_EXP_LNKCAP, &lnkcap); - pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_LNKSTA, &lnksta); - dev_info(dev, " Max payload size: %d bytes", 128 << ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5)); - dev_info(dev, " Max read request size: %d bytes", 128 << ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12)); - dev_info(dev, " Link capability: gen %d x%d", lnkcap & PCI_EXP_LNKCAP_SLS, (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4); - dev_info(dev, " Link status: gen %d x%d", lnksta & PCI_EXP_LNKSTA_CLS, (lnksta & PCI_EXP_LNKSTA_NLW) >> 4); - dev_info(dev, " Relaxed ordering: %s", devctl & PCI_EXP_DEVCTL_RELAX_EN ? "enabled" : "disabled"); - dev_info(dev, " Phantom functions: %s", devctl & PCI_EXP_DEVCTL_PHANTOM ? "enabled" : "disabled"); - dev_info(dev, " Extended tags: %s", devctl & PCI_EXP_DEVCTL_EXT_TAG ? "enabled" : "disabled"); - dev_info(dev, " No snoop: %s", devctl & PCI_EXP_DEVCTL_NOSNOOP_EN ? "enabled" : "disabled"); - } + dev_info(dev, DRIVER_NAME " probe"); + dev_info(dev, " Vendor: 0x%04x", pdev->vendor); + dev_info(dev, " Device: 0x%04x", pdev->device); + dev_info(dev, " Class: 0x%06x", pdev->class); + dev_info(dev, " PCI ID: %04x:%02x:%02x.%d", pci_domain_nr(pdev->bus), + pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + if (pdev->pcie_cap) { + u16 devctl; + u32 lnkcap; + u16 lnksta; + pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_DEVCTL, &devctl); + pci_read_config_dword(pdev, pdev->pcie_cap + PCI_EXP_LNKCAP, &lnkcap); + pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_LNKSTA, &lnksta); + dev_info(dev, " Max payload size: %d bytes", + 128 << ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5)); + dev_info(dev, " Max read request size: %d bytes", + 128 << ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12)); + dev_info(dev, " Link capability: gen %d x%d", + lnkcap & PCI_EXP_LNKCAP_SLS, (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4); + dev_info(dev, " Link status: gen %d x%d", + lnksta & PCI_EXP_LNKSTA_CLS, (lnksta & PCI_EXP_LNKSTA_NLW) >> 4); + dev_info(dev, " Relaxed ordering: %s", + devctl & PCI_EXP_DEVCTL_RELAX_EN ? "enabled" : "disabled"); + dev_info(dev, " Phantom functions: %s", + devctl & PCI_EXP_DEVCTL_PHANTOM ? "enabled" : "disabled"); + dev_info(dev, " Extended tags: %s", + devctl & PCI_EXP_DEVCTL_EXT_TAG ? "enabled" : "disabled"); + dev_info(dev, " No snoop: %s", + devctl & PCI_EXP_DEVCTL_NOSNOOP_EN ? "enabled" : "disabled"); + } #ifdef CONFIG_NUMA - dev_info(dev, " NUMA node: %d", pdev->dev.numa_node); + dev_info(dev, " NUMA node: %d", pdev->dev.numa_node); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) - pcie_print_link_status(pdev); + pcie_print_link_status(pdev); #endif - if (!(edev = devm_kzalloc(dev, sizeof(struct example_dev), GFP_KERNEL))) { - return -ENOMEM; - } + edev = devm_kzalloc(dev, sizeof(struct example_dev), GFP_KERNEL); + if (!edev) { + dev_err(dev, "Failed to allocate memory"); + return -ENOMEM; + } - edev->pdev = pdev; - pci_set_drvdata(pdev, edev); + edev->pdev = pdev; + pci_set_drvdata(pdev, edev); - // Allocate DMA buffer - edev->dma_region_len = 16*1024; - edev->dma_region = dma_alloc_coherent(dev, edev->dma_region_len, &edev->dma_region_addr, GFP_KERNEL | __GFP_ZERO); - if (!edev->dma_region) - { - dev_err(dev, "Failed to allocate DMA buffer"); - ret = -ENOMEM; - goto fail_dma_alloc; - } + // Allocate DMA buffer + edev->dma_region_len = 16 * 1024; + edev->dma_region = dma_alloc_coherent(dev, edev->dma_region_len, + &edev->dma_region_addr, + GFP_KERNEL | __GFP_ZERO); + if (!edev->dma_region) { + dev_err(dev, "Failed to allocate DMA buffer"); + ret = -ENOMEM; + goto fail_dma_alloc; + } - dev_info(dev, "Allocated DMA region virt %p, phys %p", edev->dma_region, (void *)edev->dma_region_addr); + dev_info(dev, "Allocated DMA region virt %p, phys %p", + edev->dma_region, (void *)edev->dma_region_addr); - // Disable ASPM - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); + // Disable ASPM + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | + PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); - // Enable device - ret = pci_enable_device_mem(pdev); - if (ret) - { - dev_err(dev, "Failed to enable PCI device"); - //ret = -ENODEV; - goto fail_enable_device; - } + // Enable device + ret = pci_enable_device_mem(pdev); + if (ret) { + dev_err(dev, "Failed to enable PCI device"); + goto fail_enable_device; + } - // Enable bus mastering for DMA - pci_set_master(pdev); + // Enable bus mastering for DMA + pci_set_master(pdev); - // Reserve regions - ret = pci_request_regions(pdev, DRIVER_NAME); - if (ret) - { - dev_err(dev, "Failed to reserve regions"); - //ret = -EBUSY; - goto fail_regions; - } + // Reserve regions + ret = pci_request_regions(pdev, DRIVER_NAME); + if (ret) { + dev_err(dev, "Failed to reserve regions"); + goto fail_regions; + } - // Enumerate BARs - enumerate_bars(edev, pdev); + // Enumerate BARs + enumerate_bars(edev, pdev); - // Map BARs - ret = map_bars(edev, pdev); - if (ret) - { - dev_err(dev, "Failed to map BARs"); - goto fail_map_bars; - } + // Map BARs + ret = map_bars(edev, pdev); + if (ret) { + dev_err(dev, "Failed to map BARs"); + goto fail_map_bars; + } - // Allocate MSI IRQs - ret = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); - if (ret < 0) - { - dev_err(dev, "Failed to allocate IRQs"); - goto fail_map_bars; - } + // Allocate MSI IRQs + ret = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); + if (ret < 0) { + dev_err(dev, "Failed to allocate IRQs"); + goto fail_map_bars; + } - // Set up interrupt - ret = pci_request_irq(pdev, 0, edev_intr, 0, edev, DRIVER_NAME); - if (ret < 0) - { - dev_err(dev, "Failed to request IRQ"); - goto fail_irq; - } + // Set up interrupt + ret = pci_request_irq(pdev, 0, edev_intr, 0, edev, DRIVER_NAME); + if (ret < 0) { + dev_err(dev, "Failed to request IRQ"); + goto fail_irq; + } - // Read/write test - dev_info(dev, "write to BAR2"); - iowrite32(0x11223344, edev->bar[2]); + // Read/write test + dev_info(dev, "write to BAR2"); + iowrite32(0x11223344, edev->bar[2]); - dev_info(dev, "read from BAR2"); - dev_info(dev, "%08x", ioread32(edev->bar[2])); + dev_info(dev, "read from BAR2"); + dev_info(dev, "%08x", ioread32(edev->bar[2])); - // PCIe DMA test - dev_info(dev, "write test data"); - for (k = 0; k < 256; k++) - { - ((char *)edev->dma_region)[k] = k; - } + // PCIe DMA test + dev_info(dev, "write test data"); + for (k = 0; k < 256; k++) + ((char *)edev->dma_region)[k] = k; - dev_info(dev, "read test data"); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, edev->dma_region, 256, true); + dev_info(dev, "read test data"); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, + edev->dma_region, 256, true); - dev_info(dev, "check DMA enable"); - dev_info(dev, "%08x", ioread32(edev->bar[0]+0x000000)); + dev_info(dev, "check DMA enable"); + dev_info(dev, "%08x", ioread32(edev->bar[0] + 0x000000)); - dev_info(dev, "enable DMA"); - iowrite32(0x1, edev->bar[0]+0x000000); + dev_info(dev, "enable DMA"); + iowrite32(0x1, edev->bar[0] + 0x000000); - dev_info(dev, "check DMA enable"); - dev_info(dev, "%08x", ioread32(edev->bar[0]+0x000000)); + dev_info(dev, "check DMA enable"); + dev_info(dev, "%08x", ioread32(edev->bar[0] + 0x000000)); - dev_info(dev, "start copy to card"); - iowrite32((edev->dma_region_addr+0x0000)&0xffffffff, edev->bar[0]+0x000100); - iowrite32(((edev->dma_region_addr+0x0000) >> 32)&0xffffffff, edev->bar[0]+0x000104); - iowrite32(0x100, edev->bar[0]+0x000108); - iowrite32(0, edev->bar[0]+0x00010C); - iowrite32(0x100, edev->bar[0]+0x000110); - iowrite32(0xAA, edev->bar[0]+0x000114); + dev_info(dev, "start copy to card"); + iowrite32((edev->dma_region_addr + 0x0000) & 0xffffffff, edev->bar[0] + 0x000100); + iowrite32(((edev->dma_region_addr + 0x0000) >> 32) & 0xffffffff, edev->bar[0] + 0x000104); + iowrite32(0x100, edev->bar[0] + 0x000108); + iowrite32(0, edev->bar[0] + 0x00010C); + iowrite32(0x100, edev->bar[0] + 0x000110); + iowrite32(0xAA, edev->bar[0] + 0x000114); - msleep(1); + msleep(1); - dev_info(dev, "Read status"); - dev_info(dev, "%08x", ioread32(edev->bar[0]+0x000118)); + dev_info(dev, "Read status"); + dev_info(dev, "%08x", ioread32(edev->bar[0] + 0x000118)); - dev_info(dev, "start copy to host"); - iowrite32((edev->dma_region_addr+0x0200)&0xffffffff, edev->bar[0]+0x000200); - iowrite32(((edev->dma_region_addr+0x0200) >> 32)&0xffffffff, edev->bar[0]+0x000204); - iowrite32(0x100, edev->bar[0]+0x000208); - iowrite32(0, edev->bar[0]+0x00020C); - iowrite32(0x100, edev->bar[0]+0x000210); - iowrite32(0x55, edev->bar[0]+0x000214); + dev_info(dev, "start copy to host"); + iowrite32((edev->dma_region_addr + 0x0200) & 0xffffffff, edev->bar[0] + 0x000200); + iowrite32(((edev->dma_region_addr + 0x0200) >> 32) & 0xffffffff, edev->bar[0] + 0x000204); + iowrite32(0x100, edev->bar[0] + 0x000208); + iowrite32(0, edev->bar[0] + 0x00020C); + iowrite32(0x100, edev->bar[0] + 0x000210); + iowrite32(0x55, edev->bar[0] + 0x000214); - msleep(1); + msleep(1); - dev_info(dev, "Read status"); - dev_info(dev, "%08x", ioread32(edev->bar[0]+0x000218)); + dev_info(dev, "Read status"); + dev_info(dev, "%08x", ioread32(edev->bar[0] + 0x000218)); - dev_info(dev, "read test data"); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, edev->dma_region+0x0200, 256, true); + dev_info(dev, "read test data"); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, + edev->dma_region + 0x0200, 256, true); - // probe complete - return 0; + // probe complete + return 0; - // error handling + // error handling fail_irq: - pci_free_irq_vectors(pdev); + pci_free_irq_vectors(pdev); fail_map_bars: - free_bars(edev, pdev); - pci_release_regions(pdev); + free_bars(edev, pdev); + pci_release_regions(pdev); fail_regions: - pci_clear_master(pdev); - pci_disable_device(pdev); + pci_clear_master(pdev); + pci_disable_device(pdev); fail_enable_device: - dma_free_coherent(dev, edev->dma_region_len, edev->dma_region, edev->dma_region_addr); + dma_free_coherent(dev, edev->dma_region_len, edev->dma_region, edev->dma_region_addr); fail_dma_alloc: - return ret; + return ret; } static void edev_remove(struct pci_dev *pdev) { - struct example_dev *edev; - struct device *dev = &pdev->dev; + struct example_dev *edev = pci_get_drvdata(pdev); + struct device *dev = &pdev->dev; - dev_info(dev, DRIVER_NAME " remove"); + dev_info(dev, DRIVER_NAME " remove"); - if (!(edev = pci_get_drvdata(pdev))) { - return; - } - - pci_free_irq(pdev, 0, edev); - pci_free_irq_vectors(pdev); - free_bars(edev, pdev); - pci_release_regions(pdev); - pci_clear_master(pdev); - pci_disable_device(pdev); - dma_free_coherent(dev, edev->dma_region_len, edev->dma_region, edev->dma_region_addr); + pci_free_irq(pdev, 0, edev); + pci_free_irq_vectors(pdev); + free_bars(edev, pdev); + pci_release_regions(pdev); + pci_clear_master(pdev); + pci_disable_device(pdev); + dma_free_coherent(dev, edev->dma_region_len, edev->dma_region, edev->dma_region_addr); } static void edev_shutdown(struct pci_dev *pdev) { - dev_info(&pdev->dev, DRIVER_NAME " shutdown"); + dev_info(&pdev->dev, DRIVER_NAME " shutdown"); - edev_remove(pdev); + edev_remove(pdev); } static int enumerate_bars(struct example_dev *edev, struct pci_dev *pdev) { - struct device *dev = &pdev->dev; - int i; + struct device *dev = &pdev->dev; + int i; - for (i = 0; i < 6; i++) - { - resource_size_t bar_start = pci_resource_start(pdev, i); - if (bar_start) - { - resource_size_t bar_end = pci_resource_end(pdev, i); - unsigned long bar_flags = pci_resource_flags(pdev, i); - dev_info(dev, "BAR[%d] 0x%08llx-0x%08llx flags 0x%08lx", - i, bar_start, bar_end, bar_flags); - } - } + for (i = 0; i < 6; i++) { + resource_size_t bar_start = pci_resource_start(pdev, i); + if (bar_start) { + resource_size_t bar_end = pci_resource_end(pdev, i); + unsigned long bar_flags = pci_resource_flags(pdev, i); + dev_info(dev, "BAR[%d] 0x%08llx-0x%08llx flags 0x%08lx", + i, bar_start, bar_end, bar_flags); + } + } - return 0; + return 0; } static int map_bars(struct example_dev *edev, struct pci_dev *pdev) { - struct device *dev = &pdev->dev; - int i; + struct device *dev = &pdev->dev; + int i; - for (i = 0; i < 6; i++) - { - resource_size_t bar_start = pci_resource_start(pdev, i); - resource_size_t bar_end = pci_resource_end(pdev, i); - resource_size_t bar_len = bar_end - bar_start + 1; - edev->bar_len[i] = bar_len; + for (i = 0; i < 6; i++) { + resource_size_t bar_start = pci_resource_start(pdev, i); + resource_size_t bar_end = pci_resource_end(pdev, i); + resource_size_t bar_len = bar_end - bar_start + 1; + edev->bar_len[i] = bar_len; - if (!bar_start || !bar_end) - { - edev->bar_len[i] = 0; - continue; - } + if (!bar_start || !bar_end) { + edev->bar_len[i] = 0; + continue; + } - if (bar_len < 1) - { - dev_warn(dev, "BAR[%d] is less than 1 byte", i); - continue; - } + if (bar_len < 1) { + dev_warn(dev, "BAR[%d] is less than 1 byte", i); + continue; + } - edev->bar[i] = pci_ioremap_bar(pdev, i); + edev->bar[i] = pci_ioremap_bar(pdev, i); - if (!edev->bar[i]) - { - dev_err(dev, "Could not map BAR[%d]", i); - return -1; - } + if (!edev->bar[i]) { + dev_err(dev, "Could not map BAR[%d]", i); + return -1; + } - dev_info(dev, "BAR[%d] mapped at 0x%p with length %llu", i, edev->bar[i], bar_len); - } + dev_info(dev, "BAR[%d] mapped at 0x%p with length %llu", + i, edev->bar[i], bar_len); + } - return 0; + return 0; } static void free_bars(struct example_dev *edev, struct pci_dev *pdev) { - struct device *dev = &pdev->dev; - int i; + struct device *dev = &pdev->dev; + int i; - for (i = 0; i < 6; i++) - { - if (edev->bar[i]) - { - pci_iounmap(pdev, edev->bar[i]); - edev->bar[i] = NULL; - dev_info(dev, "Unmapped BAR[%d]", i); - } - } + for (i = 0; i < 6; i++) { + if (edev->bar[i]) { + pci_iounmap(pdev, edev->bar[i]); + edev->bar[i] = NULL; + dev_info(dev, "Unmapped BAR[%d]", i); + } + } } static struct pci_driver pci_driver = { - .name = DRIVER_NAME, - .id_table = pci_ids, - .probe = edev_probe, - .remove = edev_remove, - .shutdown = edev_shutdown + .name = DRIVER_NAME, + .id_table = pci_ids, + .probe = edev_probe, + .remove = edev_remove, + .shutdown = edev_shutdown }; static int __init edev_init(void) { - return pci_register_driver(&pci_driver); + return pci_register_driver(&pci_driver); } static void __exit edev_exit(void) { - pci_unregister_driver(&pci_driver); + pci_unregister_driver(&pci_driver); } module_init(edev_init); module_exit(edev_exit); - diff --git a/fpga/lib/pcie/example/common/driver/example/example_driver.h b/fpga/lib/pcie/example/common/driver/example/example_driver.h index a42838534..6ef2857a6 100644 --- a/fpga/lib/pcie/example/common/driver/example/example_driver.h +++ b/fpga/lib/pcie/example/common/driver/example/example_driver.h @@ -1,6 +1,6 @@ /* -Copyright (c) 2018 Alex Forencich +Copyright (c) 2018-2021 Alex Forencich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,18 +31,18 @@ THE SOFTWARE. #define DRIVER_VERSION "0.1" struct example_dev { - struct pci_dev *pdev; + struct pci_dev *pdev; - // BAR pointers - void * __iomem bar[6]; - resource_size_t bar_len[6]; + // BAR pointers + void __iomem *bar[6]; + resource_size_t bar_len[6]; - // DMA buffer - size_t dma_region_len; - void *dma_region; - dma_addr_t dma_region_addr; + // DMA buffer + size_t dma_region_len; + void *dma_region; + dma_addr_t dma_region_addr; - int irqcount; + int irqcount; }; #endif /* EXAMPLE_DRIVER_H */ diff --git a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/axi_ram.v b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/axi_ram.v index 2ec9d04ef..b733b3e40 100644 --- a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/axi_ram.v +++ b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/axi_ram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4 RAM @@ -363,3 +365,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/axis_register.v b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/axis_register.v index 251bcde20..276b71ec3 100644 --- a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/axis_register.v +++ b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/axis_register.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream register @@ -262,3 +264,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/fpga.v b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/fpga.v index 3ceaf2a03..50eab6ba8 100644 --- a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/fpga.v +++ b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/fpga.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA top-level module @@ -449,3 +451,5 @@ core_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/fpga_core.v b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/fpga_core.v index 8dae9bd03..72548963d 100644 --- a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/fpga_core.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * FPGA core logic @@ -1122,3 +1124,5 @@ pcie_us_msi_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/led_sreg_driver.v b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/led_sreg_driver.v index fa81ea1a7..be970e9b0 100644 --- a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/led_sreg_driver.v +++ b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/led_sreg_driver.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * LED shift register driver @@ -133,3 +135,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/sync_reset.v b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/sync_reset.v index acbcf1c6e..1fd24d361 100644 --- a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/sync_reset.v +++ b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/sync_reset.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an active-high asynchronous reset signal to a given clock by @@ -50,3 +52,5 @@ always @(posedge clk or posedge rst) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/sync_signal.v b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/sync_signal.v index b2a8ce3de..74b855fa1 100644 --- a/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/sync_signal.v +++ b/fpga/lib/pcie/example/fb2CG/fpga_axi/rtl/sync_signal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog-2001 +`resetall `timescale 1 ns / 1 ps +`default_nettype none /* * Synchronizes an asyncronous signal to a given clock by using a pipeline of @@ -56,3 +58,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/arbiter.v b/fpga/lib/pcie/rtl/arbiter.v index cd55dd3dc..cfac70d1c 100644 --- a/fpga/lib/pcie/rtl/arbiter.v +++ b/fpga/lib/pcie/rtl/arbiter.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Arbiter module @@ -153,3 +155,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/axis_arb_mux.v b/fpga/lib/pcie/rtl/axis_arb_mux.v index ba2618609..99f0a8016 100644 --- a/fpga/lib/pcie/rtl/axis_arb_mux.v +++ b/fpga/lib/pcie/rtl/axis_arb_mux.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI4-Stream arbitrated multiplexer @@ -248,3 +250,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_client_axis_sink.v b/fpga/lib/pcie/rtl/dma_client_axis_sink.v index a13807f07..c2d322686 100644 --- a/fpga/lib/pcie/rtl/dma_client_axis_sink.v +++ b/fpga/lib/pcie/rtl/dma_client_axis_sink.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI stream sink DMA client @@ -629,3 +631,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_client_axis_source.v b/fpga/lib/pcie/rtl/dma_client_axis_source.v index 2abba4c41..bae229e06 100644 --- a/fpga/lib/pcie/rtl/dma_client_axis_source.v +++ b/fpga/lib/pcie/rtl/dma_client_axis_source.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * AXI stream source DMA client @@ -562,3 +564,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_axi.v b/fpga/lib/pcie/rtl/dma_if_axi.v new file mode 100644 index 000000000..df208d26a --- /dev/null +++ b/fpga/lib/pcie/rtl/dma_if_axi.v @@ -0,0 +1,330 @@ +/* + +Copyright (c) 2021 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI DMA interface + */ +module dma_if_axi # +( + // Width of AXI data bus in bits + parameter AXI_DATA_WIDTH = 32, + // Width of AXI address bus in bits + parameter AXI_ADDR_WIDTH = 16, + // Width of AXI wstrb (width of data bus in words) + parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8), + // Width of AXI ID signal + parameter AXI_ID_WIDTH = 8, + // Maximum AXI burst length to generate + parameter AXI_MAX_BURST_LEN = 256, + // RAM segment count + parameter RAM_SEG_COUNT = 2, + // RAM segment data width + parameter RAM_SEG_DATA_WIDTH = AXI_DATA_WIDTH*2/RAM_SEG_COUNT, + // RAM segment address width + parameter RAM_SEG_ADDR_WIDTH = 8, + // RAM segment byte enable width + parameter RAM_SEG_BE_WIDTH = RAM_SEG_DATA_WIDTH/8, + // RAM select width + parameter RAM_SEL_WIDTH = 2, + // RAM address width + parameter RAM_ADDR_WIDTH = RAM_SEG_ADDR_WIDTH+$clog2(RAM_SEG_COUNT)+$clog2(RAM_SEG_BE_WIDTH), + // Length field width + parameter LEN_WIDTH = 16, + // Tag field width + parameter TAG_WIDTH = 8, + // Operation table size (read) + parameter READ_OP_TABLE_SIZE = 2**(AXI_ID_WIDTH), + // Operation table size (write) + parameter WRITE_OP_TABLE_SIZE = 2**(AXI_ID_WIDTH), + // Use AXI ID signals + parameter USE_AXI_ID = 1 +) +( + input wire clk, + input wire rst, + + /* + * AXI master interface + */ + output wire [AXI_ID_WIDTH-1:0] m_axi_awid, + output wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr, + output wire [7:0] m_axi_awlen, + output wire [2:0] m_axi_awsize, + output wire [1:0] m_axi_awburst, + output wire m_axi_awlock, + output wire [3:0] m_axi_awcache, + output wire [2:0] m_axi_awprot, + output wire m_axi_awvalid, + input wire m_axi_awready, + output wire [AXI_DATA_WIDTH-1:0] m_axi_wdata, + output wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb, + output wire m_axi_wlast, + output wire m_axi_wvalid, + input wire m_axi_wready, + input wire [AXI_ID_WIDTH-1:0] m_axi_bid, + input wire [1:0] m_axi_bresp, + input wire m_axi_bvalid, + output wire m_axi_bready, + output wire [AXI_ID_WIDTH-1:0] m_axi_arid, + output wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr, + output wire [7:0] m_axi_arlen, + output wire [2:0] m_axi_arsize, + output wire [1:0] m_axi_arburst, + output wire m_axi_arlock, + output wire [3:0] m_axi_arcache, + output wire [2:0] m_axi_arprot, + output wire m_axi_arvalid, + input wire m_axi_arready, + input wire [AXI_ID_WIDTH-1:0] m_axi_rid, + input wire [AXI_DATA_WIDTH-1:0] m_axi_rdata, + input wire [1:0] m_axi_rresp, + input wire m_axi_rlast, + input wire m_axi_rvalid, + output wire m_axi_rready, + + /* + * AXI read descriptor input + */ + input wire [AXI_ADDR_WIDTH-1:0] s_axis_read_desc_axi_addr, + input wire [RAM_SEL_WIDTH-1:0] s_axis_read_desc_ram_sel, + input wire [RAM_ADDR_WIDTH-1:0] s_axis_read_desc_ram_addr, + input wire [LEN_WIDTH-1:0] s_axis_read_desc_len, + input wire [TAG_WIDTH-1:0] s_axis_read_desc_tag, + input wire s_axis_read_desc_valid, + output wire s_axis_read_desc_ready, + + /* + * AXI read descriptor status output + */ + output wire [TAG_WIDTH-1:0] m_axis_read_desc_status_tag, + output wire [3:0] m_axis_read_desc_status_error, + output wire m_axis_read_desc_status_valid, + + /* + * AXI write descriptor input + */ + input wire [AXI_ADDR_WIDTH-1:0] s_axis_write_desc_axi_addr, + input wire [RAM_SEL_WIDTH-1:0] s_axis_write_desc_ram_sel, + input wire [RAM_ADDR_WIDTH-1:0] s_axis_write_desc_ram_addr, + input wire [LEN_WIDTH-1:0] s_axis_write_desc_len, + input wire [TAG_WIDTH-1:0] s_axis_write_desc_tag, + input wire s_axis_write_desc_valid, + output wire s_axis_write_desc_ready, + + /* + * AXI write descriptor status output + */ + output wire [TAG_WIDTH-1:0] m_axis_write_desc_status_tag, + output wire [3:0] m_axis_write_desc_status_error, + output wire m_axis_write_desc_status_valid, + + /* + * RAM interface + */ + output wire [RAM_SEG_COUNT*RAM_SEL_WIDTH-1:0] ram_wr_cmd_sel, + output wire [RAM_SEG_COUNT*RAM_SEG_BE_WIDTH-1:0] ram_wr_cmd_be, + output wire [RAM_SEG_COUNT*RAM_SEG_ADDR_WIDTH-1:0] ram_wr_cmd_addr, + output wire [RAM_SEG_COUNT*RAM_SEG_DATA_WIDTH-1:0] ram_wr_cmd_data, + output wire [RAM_SEG_COUNT-1:0] ram_wr_cmd_valid, + input wire [RAM_SEG_COUNT-1:0] ram_wr_cmd_ready, + input wire [RAM_SEG_COUNT-1:0] ram_wr_done, + output wire [RAM_SEG_COUNT*RAM_SEL_WIDTH-1:0] ram_rd_cmd_sel, + output wire [RAM_SEG_COUNT*RAM_SEG_ADDR_WIDTH-1:0] ram_rd_cmd_addr, + output wire [RAM_SEG_COUNT-1:0] ram_rd_cmd_valid, + input wire [RAM_SEG_COUNT-1:0] ram_rd_cmd_ready, + input wire [RAM_SEG_COUNT*RAM_SEG_DATA_WIDTH-1:0] ram_rd_resp_data, + input wire [RAM_SEG_COUNT-1:0] ram_rd_resp_valid, + output wire [RAM_SEG_COUNT-1:0] ram_rd_resp_ready, + + /* + * Configuration + */ + input wire read_enable, + input wire write_enable +); + +dma_if_axi_rd #( + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_ADDR_WIDTH(AXI_ADDR_WIDTH), + .AXI_STRB_WIDTH(AXI_STRB_WIDTH), + .AXI_ID_WIDTH(AXI_ID_WIDTH), + .AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN), + .RAM_SEG_COUNT(RAM_SEG_COUNT), + .RAM_SEG_DATA_WIDTH(RAM_SEG_DATA_WIDTH), + .RAM_SEG_ADDR_WIDTH(RAM_SEG_ADDR_WIDTH), + .RAM_SEG_BE_WIDTH(RAM_SEG_BE_WIDTH), + .RAM_SEL_WIDTH(RAM_SEL_WIDTH), + .RAM_ADDR_WIDTH(RAM_ADDR_WIDTH), + .LEN_WIDTH(LEN_WIDTH), + .TAG_WIDTH(TAG_WIDTH), + .OP_TABLE_SIZE(READ_OP_TABLE_SIZE), + .USE_AXI_ID(USE_AXI_ID) +) +dma_if_axi_rd_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI master interface + */ + .m_axi_arid(m_axi_arid), + .m_axi_araddr(m_axi_araddr), + .m_axi_arlen(m_axi_arlen), + .m_axi_arsize(m_axi_arsize), + .m_axi_arburst(m_axi_arburst), + .m_axi_arlock(m_axi_arlock), + .m_axi_arcache(m_axi_arcache), + .m_axi_arprot(m_axi_arprot), + .m_axi_arvalid(m_axi_arvalid), + .m_axi_arready(m_axi_arready), + .m_axi_rid(m_axi_rid), + .m_axi_rdata(m_axi_rdata), + .m_axi_rresp(m_axi_rresp), + .m_axi_rlast(m_axi_rlast), + .m_axi_rvalid(m_axi_rvalid), + .m_axi_rready(m_axi_rready), + + /* + * AXI read descriptor input + */ + .s_axis_read_desc_axi_addr(s_axis_read_desc_axi_addr), + .s_axis_read_desc_ram_sel(s_axis_read_desc_ram_sel), + .s_axis_read_desc_ram_addr(s_axis_read_desc_ram_addr), + .s_axis_read_desc_len(s_axis_read_desc_len), + .s_axis_read_desc_tag(s_axis_read_desc_tag), + .s_axis_read_desc_valid(s_axis_read_desc_valid), + .s_axis_read_desc_ready(s_axis_read_desc_ready), + + /* + * AXI read descriptor status output + */ + .m_axis_read_desc_status_tag(m_axis_read_desc_status_tag), + .m_axis_read_desc_status_error(m_axis_read_desc_status_error), + .m_axis_read_desc_status_valid(m_axis_read_desc_status_valid), + + /* + * RAM interface + */ + .ram_wr_cmd_sel(ram_wr_cmd_sel), + .ram_wr_cmd_be(ram_wr_cmd_be), + .ram_wr_cmd_addr(ram_wr_cmd_addr), + .ram_wr_cmd_data(ram_wr_cmd_data), + .ram_wr_cmd_valid(ram_wr_cmd_valid), + .ram_wr_cmd_ready(ram_wr_cmd_ready), + .ram_wr_done(ram_wr_done), + + /* + * Configuration + */ + .enable(read_enable) +); + +dma_if_axi_wr #( + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_ADDR_WIDTH(AXI_ADDR_WIDTH), + .AXI_STRB_WIDTH(AXI_STRB_WIDTH), + .AXI_ID_WIDTH(AXI_ID_WIDTH), + .AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN), + .RAM_SEG_COUNT(RAM_SEG_COUNT), + .RAM_SEG_DATA_WIDTH(RAM_SEG_DATA_WIDTH), + .RAM_SEG_ADDR_WIDTH(RAM_SEG_ADDR_WIDTH), + .RAM_SEG_BE_WIDTH(RAM_SEG_BE_WIDTH), + .RAM_SEL_WIDTH(RAM_SEL_WIDTH), + .RAM_ADDR_WIDTH(RAM_ADDR_WIDTH), + .LEN_WIDTH(LEN_WIDTH), + .TAG_WIDTH(TAG_WIDTH), + .OP_TABLE_SIZE(WRITE_OP_TABLE_SIZE), + .USE_AXI_ID(USE_AXI_ID) +) +dma_if_axi_wr_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI master interface + */ + .m_axi_awid(m_axi_awid), + .m_axi_awaddr(m_axi_awaddr), + .m_axi_awlen(m_axi_awlen), + .m_axi_awsize(m_axi_awsize), + .m_axi_awburst(m_axi_awburst), + .m_axi_awlock(m_axi_awlock), + .m_axi_awcache(m_axi_awcache), + .m_axi_awprot(m_axi_awprot), + .m_axi_awvalid(m_axi_awvalid), + .m_axi_awready(m_axi_awready), + .m_axi_wdata(m_axi_wdata), + .m_axi_wstrb(m_axi_wstrb), + .m_axi_wlast(m_axi_wlast), + .m_axi_wvalid(m_axi_wvalid), + .m_axi_wready(m_axi_wready), + .m_axi_bid(m_axi_bid), + .m_axi_bresp(m_axi_bresp), + .m_axi_bvalid(m_axi_bvalid), + .m_axi_bready(m_axi_bready), + + /* + * AXI write descriptor input + */ + .s_axis_write_desc_axi_addr(s_axis_write_desc_axi_addr), + .s_axis_write_desc_ram_sel(s_axis_write_desc_ram_sel), + .s_axis_write_desc_ram_addr(s_axis_write_desc_ram_addr), + .s_axis_write_desc_len(s_axis_write_desc_len), + .s_axis_write_desc_tag(s_axis_write_desc_tag), + .s_axis_write_desc_valid(s_axis_write_desc_valid), + .s_axis_write_desc_ready(s_axis_write_desc_ready), + + /* + * AXI write descriptor status output + */ + .m_axis_write_desc_status_tag(m_axis_write_desc_status_tag), + .m_axis_write_desc_status_error(m_axis_write_desc_status_error), + .m_axis_write_desc_status_valid(m_axis_write_desc_status_valid), + + /* + * RAM interface + */ + .ram_rd_cmd_sel(ram_rd_cmd_sel), + .ram_rd_cmd_addr(ram_rd_cmd_addr), + .ram_rd_cmd_valid(ram_rd_cmd_valid), + .ram_rd_cmd_ready(ram_rd_cmd_ready), + .ram_rd_resp_data(ram_rd_resp_data), + .ram_rd_resp_valid(ram_rd_resp_valid), + .ram_rd_resp_ready(ram_rd_resp_ready), + + /* + * Configuration + */ + .enable(write_enable) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_axi_rd.v b/fpga/lib/pcie/rtl/dma_if_axi_rd.v new file mode 100644 index 000000000..7d17cd677 --- /dev/null +++ b/fpga/lib/pcie/rtl/dma_if_axi_rd.v @@ -0,0 +1,859 @@ +/* + +Copyright (c) 2021 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI DMA read interface + */ +module dma_if_axi_rd # +( + // Width of AXI data bus in bits + parameter AXI_DATA_WIDTH = 32, + // Width of AXI address bus in bits + parameter AXI_ADDR_WIDTH = 16, + // Width of AXI wstrb (width of data bus in words) + parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8), + // Width of AXI ID signal + parameter AXI_ID_WIDTH = 8, + // Maximum AXI burst length to generate + parameter AXI_MAX_BURST_LEN = 256, + // RAM segment count + parameter RAM_SEG_COUNT = 2, + // RAM segment data width + parameter RAM_SEG_DATA_WIDTH = AXI_DATA_WIDTH*2/RAM_SEG_COUNT, + // RAM segment address width + parameter RAM_SEG_ADDR_WIDTH = 8, + // RAM segment byte enable width + parameter RAM_SEG_BE_WIDTH = RAM_SEG_DATA_WIDTH/8, + // RAM select width + parameter RAM_SEL_WIDTH = 2, + // RAM address width + parameter RAM_ADDR_WIDTH = RAM_SEG_ADDR_WIDTH+$clog2(RAM_SEG_COUNT)+$clog2(RAM_SEG_BE_WIDTH), + // Length field width + parameter LEN_WIDTH = 16, + // Tag field width + parameter TAG_WIDTH = 8, + // Operation table size + parameter OP_TABLE_SIZE = 2**(AXI_ID_WIDTH), + // Use AXI ID signals + parameter USE_AXI_ID = 1 +) +( + input wire clk, + input wire rst, + + /* + * AXI master interface + */ + output wire [AXI_ID_WIDTH-1:0] m_axi_arid, + output wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr, + output wire [7:0] m_axi_arlen, + output wire [2:0] m_axi_arsize, + output wire [1:0] m_axi_arburst, + output wire m_axi_arlock, + output wire [3:0] m_axi_arcache, + output wire [2:0] m_axi_arprot, + output wire m_axi_arvalid, + input wire m_axi_arready, + input wire [AXI_ID_WIDTH-1:0] m_axi_rid, + input wire [AXI_DATA_WIDTH-1:0] m_axi_rdata, + input wire [1:0] m_axi_rresp, + input wire m_axi_rlast, + input wire m_axi_rvalid, + output wire m_axi_rready, + + /* + * AXI read descriptor input + */ + input wire [AXI_ADDR_WIDTH-1:0] s_axis_read_desc_axi_addr, + input wire [RAM_SEL_WIDTH-1:0] s_axis_read_desc_ram_sel, + input wire [RAM_ADDR_WIDTH-1:0] s_axis_read_desc_ram_addr, + input wire [LEN_WIDTH-1:0] s_axis_read_desc_len, + input wire [TAG_WIDTH-1:0] s_axis_read_desc_tag, + input wire s_axis_read_desc_valid, + output wire s_axis_read_desc_ready, + + /* + * AXI read descriptor status output + */ + output wire [TAG_WIDTH-1:0] m_axis_read_desc_status_tag, + output wire [3:0] m_axis_read_desc_status_error, + output wire m_axis_read_desc_status_valid, + + /* + * RAM interface + */ + output wire [RAM_SEG_COUNT*RAM_SEL_WIDTH-1:0] ram_wr_cmd_sel, + output wire [RAM_SEG_COUNT*RAM_SEG_BE_WIDTH-1:0] ram_wr_cmd_be, + output wire [RAM_SEG_COUNT*RAM_SEG_ADDR_WIDTH-1:0] ram_wr_cmd_addr, + output wire [RAM_SEG_COUNT*RAM_SEG_DATA_WIDTH-1:0] ram_wr_cmd_data, + output wire [RAM_SEG_COUNT-1:0] ram_wr_cmd_valid, + input wire [RAM_SEG_COUNT-1:0] ram_wr_cmd_ready, + input wire [RAM_SEG_COUNT-1:0] ram_wr_done, + + /* + * Configuration + */ + input wire enable +); + +parameter RAM_WORD_WIDTH = RAM_SEG_BE_WIDTH; +parameter RAM_WORD_SIZE = RAM_SEG_DATA_WIDTH/RAM_WORD_WIDTH; + +parameter AXI_WORD_WIDTH = AXI_STRB_WIDTH; +parameter AXI_WORD_SIZE = AXI_DATA_WIDTH/AXI_WORD_WIDTH; +parameter AXI_BURST_SIZE = $clog2(AXI_STRB_WIDTH); +parameter AXI_MAX_BURST_SIZE = AXI_MAX_BURST_LEN << AXI_BURST_SIZE; + +parameter OFFSET_WIDTH = AXI_STRB_WIDTH > 1 ? $clog2(AXI_STRB_WIDTH) : 1; +parameter OFFSET_MASK = AXI_STRB_WIDTH > 1 ? {OFFSET_WIDTH{1'b1}} : 0; +parameter RAM_OFFSET_WIDTH = $clog2(RAM_SEG_COUNT*RAM_SEG_BE_WIDTH); +parameter ADDR_MASK = {AXI_ADDR_WIDTH{1'b1}} << $clog2(AXI_STRB_WIDTH); +parameter CYCLE_COUNT_WIDTH = LEN_WIDTH - AXI_BURST_SIZE + 1; + +parameter OP_TAG_WIDTH = $clog2(OP_TABLE_SIZE); +parameter OP_TABLE_READ_COUNT_WIDTH = AXI_ID_WIDTH+1; +parameter OP_TABLE_WRITE_COUNT_WIDTH = LEN_WIDTH; + +parameter STATUS_FIFO_ADDR_WIDTH = 5; +parameter OUTPUT_FIFO_ADDR_WIDTH = 5; + +// bus width assertions +initial begin + if (AXI_WORD_SIZE * AXI_STRB_WIDTH != AXI_DATA_WIDTH) begin + $error("Error: AXI data width not evenly divisble (instance %m)"); + $finish; + end + + if (AXI_WORD_SIZE != RAM_WORD_SIZE) begin + $error("Error: word size mismatch (instance %m)"); + $finish; + end + + if (2**$clog2(AXI_WORD_WIDTH) != AXI_WORD_WIDTH) begin + $error("Error: AXI word width must be even power of two (instance %m)"); + $finish; + end + + if (AXI_MAX_BURST_LEN < 1 || AXI_MAX_BURST_LEN > 256) begin + $error("Error: AXI_MAX_BURST_LEN must be between 1 and 256 (instance %m)"); + $finish; + end + + if (RAM_SEG_COUNT < 2) begin + $error("Error: RAM interface requires at least 2 segments (instance %m)"); + $finish; + end + + if (RAM_SEG_COUNT*RAM_SEG_DATA_WIDTH != AXI_DATA_WIDTH*2) begin + $error("Error: RAM interface width must be double the AXI interface width (instance %m)"); + $finish; + end + + if (2**$clog2(RAM_WORD_WIDTH) != RAM_WORD_WIDTH) begin + $error("Error: RAM word width must be even power of two (instance %m)"); + $finish; + end + + if (RAM_ADDR_WIDTH != RAM_SEG_ADDR_WIDTH+$clog2(RAM_SEG_COUNT)+$clog2(RAM_SEG_BE_WIDTH)) begin + $error("Error: RAM_ADDR_WIDTH does not match RAM configuration (instance %m)"); + $finish; + end +end + +localparam [1:0] + AXI_RESP_OKAY = 2'b00, + AXI_RESP_EXOKAY = 2'b01, + AXI_RESP_SLVERR = 2'b10, + AXI_RESP_DECERR = 2'b11; + +localparam [3:0] + DMA_ERROR_NONE = 4'd0, + DMA_ERROR_TIMEOUT = 4'd1, + DMA_ERROR_PARITY = 4'd2, + DMA_ERROR_AXI_RD_SLVERR = 4'd4, + DMA_ERROR_AXI_RD_DECERR = 4'd5, + DMA_ERROR_AXI_WR_SLVERR = 4'd6, + DMA_ERROR_AXI_WR_DECERR = 4'd7, + DMA_ERROR_PCIE_FLR = 4'd8, + DMA_ERROR_PCIE_CPL_POISONED = 4'd9, + DMA_ERROR_PCIE_CPL_STATUS_UR = 4'd10, + DMA_ERROR_PCIE_CPL_STATUS_CA = 4'd11; + +localparam [0:0] + REQ_STATE_IDLE = 1'd0, + REQ_STATE_START = 1'd1; + +reg [0:0] req_state_reg = REQ_STATE_IDLE, req_state_next; + +localparam [0:0] + AXI_STATE_IDLE = 1'd0, + AXI_STATE_WRITE = 1'd1; + +reg [0:0] axi_state_reg = AXI_STATE_IDLE, axi_state_next; + +reg [AXI_ADDR_WIDTH-1:0] req_axi_addr_reg = {AXI_ADDR_WIDTH{1'b0}}, req_axi_addr_next; +reg [RAM_SEL_WIDTH-1:0] req_ram_sel_reg = {RAM_SEL_WIDTH{1'b0}}, req_ram_sel_next; +reg [RAM_ADDR_WIDTH-1:0] req_ram_addr_reg = {RAM_ADDR_WIDTH{1'b0}}, req_ram_addr_next; +reg [LEN_WIDTH-1:0] req_op_count_reg = {LEN_WIDTH{1'b0}}, req_op_count_next; +reg [LEN_WIDTH-1:0] req_tr_count_reg = {LEN_WIDTH{1'b0}}, req_tr_count_next; +reg [TAG_WIDTH-1:0] req_tag_reg = {TAG_WIDTH{1'b0}}, req_tag_next; + +reg [RAM_SEL_WIDTH-1:0] ram_sel_reg = {RAM_SEL_WIDTH{1'b0}}, ram_sel_next; +reg [RAM_ADDR_WIDTH-1:0] addr_reg = {RAM_ADDR_WIDTH{1'b0}}, addr_next; +reg [RAM_ADDR_WIDTH-1:0] addr_delay_reg = {RAM_ADDR_WIDTH{1'b0}}, addr_delay_next; +reg [12:0] op_count_reg = 13'd0, op_count_next; +reg [RAM_SEG_COUNT-1:0] ram_mask_reg = {RAM_SEG_COUNT{1'b0}}, ram_mask_next; +reg [RAM_SEG_COUNT-1:0] ram_mask_0_reg = {RAM_SEG_COUNT{1'b0}}, ram_mask_0_next; +reg [RAM_SEG_COUNT-1:0] ram_mask_1_reg = {RAM_SEG_COUNT{1'b0}}, ram_mask_1_next; +reg ram_wrap_reg = 1'b0, ram_wrap_next; +reg [OFFSET_WIDTH+1-1:0] cycle_byte_count_reg = {OFFSET_WIDTH+1{1'b0}}, cycle_byte_count_next; +reg [RAM_OFFSET_WIDTH-1:0] start_offset_reg = {RAM_OFFSET_WIDTH{1'b0}}, start_offset_next; +reg [RAM_OFFSET_WIDTH-1:0] end_offset_reg = {RAM_OFFSET_WIDTH{1'b0}}, end_offset_next; +reg [OFFSET_WIDTH-1:0] offset_reg = {OFFSET_WIDTH{1'b0}}, offset_next; +reg [OP_TAG_WIDTH-1:0] op_tag_reg = {OP_TAG_WIDTH{1'b0}}, op_tag_next; + +reg [STATUS_FIFO_ADDR_WIDTH+1-1:0] status_fifo_wr_ptr_reg = 0; +reg [STATUS_FIFO_ADDR_WIDTH+1-1:0] status_fifo_rd_ptr_reg = 0, status_fifo_rd_ptr_next; +reg [OP_TAG_WIDTH-1:0] status_fifo_op_tag[(2**STATUS_FIFO_ADDR_WIDTH)-1:0]; +reg [RAM_SEG_COUNT-1:0] status_fifo_mask[(2**STATUS_FIFO_ADDR_WIDTH)-1:0]; +reg status_fifo_finish[(2**STATUS_FIFO_ADDR_WIDTH)-1:0]; +reg [OP_TAG_WIDTH-1:0] status_fifo_wr_op_tag; +reg [RAM_SEG_COUNT-1:0] status_fifo_wr_mask; +reg status_fifo_wr_finish; +reg status_fifo_we; +reg status_fifo_finish_reg = 1'b0, status_fifo_finish_next; +reg status_fifo_we_reg = 1'b0, status_fifo_we_next; +reg status_fifo_half_full_reg = 1'b0; +reg [OP_TAG_WIDTH-1:0] status_fifo_rd_op_tag_reg = 0, status_fifo_rd_op_tag_next; +reg [RAM_SEG_COUNT-1:0] status_fifo_rd_mask_reg = 0, status_fifo_rd_mask_next; +reg status_fifo_rd_finish_reg = 1'b0, status_fifo_rd_finish_next; +reg status_fifo_rd_valid_reg = 1'b0, status_fifo_rd_valid_next; + +reg [AXI_DATA_WIDTH-1:0] m_axi_rdata_int_reg = {AXI_DATA_WIDTH{1'b0}}, m_axi_rdata_int_next; +reg m_axi_rvalid_int_reg = 1'b0, m_axi_rvalid_int_next; + +reg [AXI_ID_WIDTH-1:0] m_axi_arid_reg = {AXI_ID_WIDTH{1'b0}}, m_axi_arid_next; +reg [AXI_ADDR_WIDTH-1:0] m_axi_araddr_reg = {AXI_ADDR_WIDTH{1'b0}}, m_axi_araddr_next; +reg [7:0] m_axi_arlen_reg = 8'd0, m_axi_arlen_next; +reg m_axi_arvalid_reg = 1'b0, m_axi_arvalid_next; +reg m_axi_rready_reg = 1'b0, m_axi_rready_next; + +reg s_axis_read_desc_ready_reg = 1'b0, s_axis_read_desc_ready_next; + +reg [TAG_WIDTH-1:0] m_axis_read_desc_status_tag_reg = {TAG_WIDTH{1'b0}}, m_axis_read_desc_status_tag_next; +reg [3:0] m_axis_read_desc_status_error_reg = 4'd0, m_axis_read_desc_status_error_next; +reg m_axis_read_desc_status_valid_reg = 1'b0, m_axis_read_desc_status_valid_next; + +// internal datapath +reg [RAM_SEG_COUNT*RAM_SEL_WIDTH-1:0] ram_wr_cmd_sel_int; +reg [RAM_SEG_COUNT*RAM_SEG_BE_WIDTH-1:0] ram_wr_cmd_be_int; +reg [RAM_SEG_COUNT*RAM_SEG_ADDR_WIDTH-1:0] ram_wr_cmd_addr_int; +reg [RAM_SEG_COUNT*RAM_SEG_DATA_WIDTH-1:0] ram_wr_cmd_data_int; +reg [RAM_SEG_COUNT-1:0] ram_wr_cmd_valid_int; +reg [RAM_SEG_COUNT-1:0] ram_wr_cmd_ready_int; + +wire [RAM_SEG_COUNT-1:0] out_done; +reg [RAM_SEG_COUNT-1:0] out_done_ack; + +assign m_axi_arid = m_axi_arid_reg; +assign m_axi_araddr = m_axi_araddr_reg; +assign m_axi_arlen = m_axi_arlen_reg; +assign m_axi_arsize = AXI_BURST_SIZE; +assign m_axi_arburst = 2'b01; +assign m_axi_arlock = 1'b0; +assign m_axi_arcache = 4'b0011; +assign m_axi_arprot = 3'b010; +assign m_axi_arvalid = m_axi_arvalid_reg; +assign m_axi_rready = m_axi_rready_reg; + +assign s_axis_read_desc_ready = s_axis_read_desc_ready_reg; + +assign m_axis_read_desc_status_tag = m_axis_read_desc_status_tag_reg; +assign m_axis_read_desc_status_error = m_axis_read_desc_status_error_reg; +assign m_axis_read_desc_status_valid = m_axis_read_desc_status_valid_reg; + +// operation tag management +reg [OP_TAG_WIDTH+1-1:0] op_table_start_ptr_reg = 0; +reg [AXI_ADDR_WIDTH-1:0] op_table_start_axi_addr; +reg [RAM_SEL_WIDTH-1:0] op_table_start_ram_sel; +reg [RAM_ADDR_WIDTH-1:0] op_table_start_ram_addr; +reg [11:0] op_table_start_len; +reg [CYCLE_COUNT_WIDTH-1:0] op_table_start_cycle_count; +reg [TAG_WIDTH-1:0] op_table_start_tag; +reg op_table_start_last; +reg op_table_start_en; +reg op_table_write_complete_en; +reg [OP_TAG_WIDTH-1:0] op_table_write_complete_ptr; +reg [OP_TAG_WIDTH+1-1:0] op_table_finish_ptr_reg = 0; +reg op_table_finish_en; + +reg [2**OP_TAG_WIDTH-1:0] op_table_active = 0; +reg [AXI_ADDR_WIDTH-1:0] op_table_axi_addr [2**OP_TAG_WIDTH-1:0]; +reg [RAM_SEL_WIDTH-1:0] op_table_ram_sel [2**OP_TAG_WIDTH-1:0]; +reg [RAM_ADDR_WIDTH-1:0] op_table_ram_addr [2**OP_TAG_WIDTH-1:0]; +reg [11:0] op_table_len[2**OP_TAG_WIDTH-1:0]; +reg [CYCLE_COUNT_WIDTH-1:0] op_table_cycle_count[2**OP_TAG_WIDTH-1:0]; +reg [TAG_WIDTH-1:0] op_table_tag[2**OP_TAG_WIDTH-1:0]; +reg op_table_last[2**OP_TAG_WIDTH-1:0]; +reg op_table_write_complete[2**OP_TAG_WIDTH-1:0]; + +integer i; + +initial begin + for (i = 0; i < 2**OP_TAG_WIDTH; i = i + 1) begin + op_table_axi_addr[i] = 0; + op_table_ram_sel[i] = 0; + op_table_ram_addr[i] = 0; + op_table_len[i] = 0; + op_table_cycle_count[i] = 0; + op_table_tag[i] = 0; + op_table_last[i] = 0; + op_table_write_complete[i] = 0; + end +end + +always @* begin + req_state_next = REQ_STATE_IDLE; + + s_axis_read_desc_ready_next = 1'b0; + + req_axi_addr_next = req_axi_addr_reg; + req_ram_sel_next = req_ram_sel_reg; + req_ram_addr_next = req_ram_addr_reg; + req_op_count_next = req_op_count_reg; + req_tr_count_next = req_tr_count_reg; + req_tag_next = req_tag_reg; + + m_axi_arid_next = m_axi_arid_reg; + m_axi_araddr_next = m_axi_araddr_reg; + m_axi_arlen_next = m_axi_arlen_reg; + m_axi_arvalid_next = m_axi_arvalid_reg && !m_axi_arready; + + op_table_start_axi_addr = req_axi_addr_reg; + op_table_start_ram_sel = req_ram_sel_reg; + op_table_start_ram_addr = req_ram_addr_reg; + op_table_start_len = 0; + op_table_start_tag = req_tag_reg; + op_table_start_cycle_count = 0; + op_table_start_last = 0; + op_table_start_en = 1'b0; + + // segmentation and request generation + case (req_state_reg) + REQ_STATE_IDLE: begin + s_axis_read_desc_ready_next = !op_table_active[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] && ($unsigned(op_table_start_ptr_reg - op_table_finish_ptr_reg) < 2**OP_TAG_WIDTH) && enable; + + req_axi_addr_next = s_axis_read_desc_axi_addr; + req_ram_sel_next = s_axis_read_desc_ram_sel; + req_ram_addr_next = s_axis_read_desc_ram_addr; + req_op_count_next = s_axis_read_desc_len; + req_tag_next = s_axis_read_desc_tag; + + if (req_op_count_next <= AXI_MAX_BURST_SIZE - (req_axi_addr_next & OFFSET_MASK) || AXI_MAX_BURST_SIZE >= 4096) begin + // packet smaller than max burst size + if (((req_axi_addr_next & 12'hfff) + (req_op_count_next & 12'hfff)) >> 12 != 0 || req_op_count_next >> 12 != 0) begin + // crosses 4k boundary + req_tr_count_next = 13'h1000 - req_axi_addr_next[11:0]; + end else begin + // does not cross 4k boundary + req_tr_count_next = req_op_count_next; + end + end else begin + // packet larger than max burst size + if (((req_axi_addr_next & 12'hfff) + AXI_MAX_BURST_SIZE) >> 12 != 0) begin + // crosses 4k boundary + req_tr_count_next = 13'h1000 - req_axi_addr_next[11:0]; + end else begin + // does not cross 4k boundary + req_tr_count_next = AXI_MAX_BURST_SIZE - (req_axi_addr_next & OFFSET_MASK); + end + end + + if (s_axis_read_desc_ready && s_axis_read_desc_valid) begin + $display("AXI DMA start read (AXI 0x%x, RAM 0x%x 0x%x, len %d, tag 0x%x)", s_axis_read_desc_axi_addr, s_axis_read_desc_ram_sel, s_axis_read_desc_ram_addr, s_axis_read_desc_len, s_axis_read_desc_tag); + s_axis_read_desc_ready_next = 1'b0; + req_state_next = REQ_STATE_START; + end else begin + req_state_next = REQ_STATE_IDLE; + end + end + REQ_STATE_START: begin + if (!op_table_active[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] && ($unsigned(op_table_start_ptr_reg - op_table_finish_ptr_reg) < 2**OP_TAG_WIDTH) && (!m_axi_arvalid || m_axi_arready)) begin + req_axi_addr_next = req_axi_addr_reg + req_tr_count_reg; + req_ram_addr_next = req_ram_addr_reg + req_tr_count_reg; + req_op_count_next = req_op_count_reg - req_tr_count_reg; + + op_table_start_axi_addr = req_axi_addr_reg; + op_table_start_ram_sel = req_ram_sel_reg; + op_table_start_ram_addr = req_ram_addr_reg; + op_table_start_len = req_tr_count_next; + op_table_start_tag = req_tag_reg; + op_table_start_cycle_count = (req_tr_count_next + (req_axi_addr_reg & OFFSET_MASK) - 1) >> AXI_BURST_SIZE; + op_table_start_last = req_op_count_reg == req_tr_count_next; + op_table_start_en = 1'b1; + + m_axi_arid_next = op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]; + m_axi_araddr_next = req_axi_addr_reg; + m_axi_arlen_next = op_table_start_cycle_count; + m_axi_arvalid_next = 1'b1; + + if (req_op_count_next <= AXI_MAX_BURST_SIZE - (req_axi_addr_next & OFFSET_MASK) || AXI_MAX_BURST_SIZE >= 4096) begin + // packet smaller than max burst size + if (((req_axi_addr_next & 12'hfff) + (req_op_count_next & 12'hfff)) >> 12 != 0 || req_op_count_next >> 12 != 0) begin + // crosses 4k boundary + req_tr_count_next = 13'h1000 - req_axi_addr_next[11:0]; + end else begin + // does not cross 4k boundary + req_tr_count_next = req_op_count_next; + end + end else begin + // packet larger than max burst size + if (((req_axi_addr_next & 12'hfff) + AXI_MAX_BURST_SIZE) >> 12 != 0) begin + // crosses 4k boundary + req_tr_count_next = 13'h1000 - req_axi_addr_next[11:0]; + end else begin + // does not cross 4k boundary + req_tr_count_next = AXI_MAX_BURST_SIZE - (req_axi_addr_next & OFFSET_MASK); + end + end + + if (!op_table_start_last) begin + req_state_next = REQ_STATE_START; + end else begin + s_axis_read_desc_ready_next = !op_table_active[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] && ($unsigned(op_table_start_ptr_reg - op_table_finish_ptr_reg) < 2**OP_TAG_WIDTH) && enable; + req_state_next = REQ_STATE_IDLE; + end + end else begin + req_state_next = REQ_STATE_START; + end + end + endcase +end + +always @* begin + axi_state_next = AXI_STATE_IDLE; + + m_axi_rready_next = 1'b0; + + ram_sel_next = ram_sel_reg; + addr_next = addr_reg; + addr_delay_next = addr_delay_reg; + op_count_next = op_count_reg; + ram_mask_next = ram_mask_reg; + ram_mask_0_next = ram_mask_0_reg; + ram_mask_1_next = ram_mask_1_reg; + ram_wrap_next = ram_wrap_reg; + cycle_byte_count_next = cycle_byte_count_reg; + start_offset_next = start_offset_reg; + end_offset_next = end_offset_reg; + offset_next = offset_reg; + op_tag_next = op_tag_reg; + + op_table_write_complete_en = 1'b0; + op_table_write_complete_ptr = m_axi_rid; + + m_axi_rdata_int_next = m_axi_rdata_int_reg; + m_axi_rvalid_int_next = 1'b0; + + status_fifo_finish_next = 1'b0; + status_fifo_we_next = 1'b0; + + out_done_ack = {RAM_SEG_COUNT{1'b0}}; + + // Write generation + ram_wr_cmd_sel_int = {RAM_SEG_COUNT{ram_sel_reg}}; + if (!ram_wrap_reg) begin + ram_wr_cmd_be_int = ({RAM_SEG_COUNT*RAM_SEG_BE_WIDTH{1'b1}} << start_offset_reg) & ({RAM_SEG_COUNT*RAM_SEG_BE_WIDTH{1'b1}} >> (RAM_SEG_COUNT*RAM_SEG_BE_WIDTH-1-end_offset_reg)); + end else begin + ram_wr_cmd_be_int = ({RAM_SEG_COUNT*RAM_SEG_BE_WIDTH{1'b1}} << start_offset_reg) | ({RAM_SEG_COUNT*RAM_SEG_BE_WIDTH{1'b1}} >> (RAM_SEG_COUNT*RAM_SEG_BE_WIDTH-1-end_offset_reg)); + end + for (i = 0; i < RAM_SEG_COUNT; i = i + 1) begin + ram_wr_cmd_addr_int[i*RAM_SEG_ADDR_WIDTH +: RAM_SEG_ADDR_WIDTH] = addr_delay_reg[RAM_ADDR_WIDTH-1:RAM_ADDR_WIDTH-RAM_SEG_ADDR_WIDTH]; + if (ram_mask_1_reg[i]) begin + ram_wr_cmd_addr_int[i*RAM_SEG_ADDR_WIDTH +: RAM_SEG_ADDR_WIDTH] = addr_delay_reg[RAM_ADDR_WIDTH-1:RAM_ADDR_WIDTH-RAM_SEG_ADDR_WIDTH]+1; + end + end + ram_wr_cmd_data_int = {3{m_axi_rdata_int_reg}} >> (AXI_DATA_WIDTH - offset_reg*AXI_WORD_SIZE); + ram_wr_cmd_valid_int = {RAM_SEG_COUNT{1'b0}}; + + if (m_axi_rvalid_int_reg) begin + ram_wr_cmd_valid_int = ram_mask_reg; + end + + // AXI read response handling + case (axi_state_reg) + AXI_STATE_IDLE: begin + // idle state, wait for read data + m_axi_rready_next = &ram_wr_cmd_ready_int && !status_fifo_half_full_reg; + + op_tag_next = m_axi_rid[OP_TAG_WIDTH-1:0]; + ram_sel_next = op_table_ram_sel[op_tag_next]; + addr_next = op_table_ram_addr[op_tag_next]; + op_count_next = op_table_len[op_tag_next]; + offset_next = op_table_ram_addr[op_tag_next][RAM_OFFSET_WIDTH-1:0]-(op_table_axi_addr[op_tag_next] & OFFSET_MASK); + + if (m_axi_rready && m_axi_rvalid) begin + if (op_count_next > AXI_WORD_WIDTH-(op_table_axi_addr[m_axi_rid[OP_TAG_WIDTH-1:0]] & OFFSET_MASK)) begin + cycle_byte_count_next = AXI_WORD_WIDTH-(op_table_axi_addr[m_axi_rid[OP_TAG_WIDTH-1:0]] & OFFSET_MASK); + end else begin + cycle_byte_count_next = op_count_next; + end + start_offset_next = addr_next; + {ram_wrap_next, end_offset_next} = start_offset_next+cycle_byte_count_next-1; + + ram_mask_0_next = {RAM_SEG_COUNT{1'b1}} << (start_offset_next >> $clog2(RAM_SEG_BE_WIDTH)); + ram_mask_1_next = {RAM_SEG_COUNT{1'b1}} >> (RAM_SEG_COUNT-1-(end_offset_next >> $clog2(RAM_SEG_BE_WIDTH))); + + if (!ram_wrap_next) begin + ram_mask_next = ram_mask_0_next & ram_mask_1_next; + ram_mask_0_next = ram_mask_0_next & ram_mask_1_next; + ram_mask_1_next = 0; + end else begin + ram_mask_next = ram_mask_0_next | ram_mask_1_next; + end + + addr_delay_next = addr_next; + addr_next = addr_next + cycle_byte_count_next; + op_count_next = op_count_next - cycle_byte_count_next; + + m_axi_rdata_int_next = m_axi_rdata; + m_axi_rvalid_int_next = 1'b1; + + status_fifo_finish_next = 1'b0; + status_fifo_we_next = 1'b1; + + if (m_axi_rlast) begin + status_fifo_finish_next = 1'b1; + axi_state_next = AXI_STATE_IDLE; + end else begin + axi_state_next = AXI_STATE_WRITE; + end + end else begin + axi_state_next = AXI_STATE_IDLE; + end + end + AXI_STATE_WRITE: begin + // write state - generate write operations + m_axi_rready_next = &ram_wr_cmd_ready_int && !status_fifo_half_full_reg; + + if (m_axi_rready && m_axi_rvalid) begin + + if (op_count_next > AXI_WORD_WIDTH) begin + cycle_byte_count_next = AXI_WORD_WIDTH; + end else begin + cycle_byte_count_next = op_count_next; + end + start_offset_next = addr_next; + {ram_wrap_next, end_offset_next} = start_offset_next+cycle_byte_count_next-1; + + ram_mask_0_next = {RAM_SEG_COUNT{1'b1}} << (start_offset_next >> $clog2(RAM_SEG_BE_WIDTH)); + ram_mask_1_next = {RAM_SEG_COUNT{1'b1}} >> (RAM_SEG_COUNT-1-(end_offset_next >> $clog2(RAM_SEG_BE_WIDTH))); + + if (!ram_wrap_next) begin + ram_mask_next = ram_mask_0_next & ram_mask_1_next; + ram_mask_0_next = ram_mask_0_next & ram_mask_1_next; + ram_mask_1_next = 0; + end else begin + ram_mask_next = ram_mask_0_next | ram_mask_1_next; + end + + addr_delay_next = addr_next; + addr_next = addr_next + cycle_byte_count_next; + op_count_next = op_count_next - cycle_byte_count_next; + + m_axi_rdata_int_next = m_axi_rdata; + m_axi_rvalid_int_next = 1'b1; + + status_fifo_finish_next = 1'b0; + status_fifo_we_next = 1'b1; + + if (m_axi_rlast) begin + status_fifo_finish_next = 1'b1; + axi_state_next = AXI_STATE_IDLE; + end else begin + axi_state_next = AXI_STATE_WRITE; + end + end else begin + axi_state_next = AXI_STATE_WRITE; + end + end + endcase + + status_fifo_rd_ptr_next = status_fifo_rd_ptr_reg; + + status_fifo_wr_op_tag = op_tag_reg; + status_fifo_wr_mask = ram_mask_reg; + status_fifo_wr_finish = status_fifo_finish_reg; + status_fifo_we = 1'b0; + + if (status_fifo_we_reg) begin + status_fifo_wr_op_tag = op_tag_reg; + status_fifo_wr_mask = ram_mask_reg; + status_fifo_wr_finish = status_fifo_finish_reg; + status_fifo_we = 1'b1; + end + + status_fifo_rd_op_tag_next = status_fifo_rd_op_tag_reg; + status_fifo_rd_mask_next = status_fifo_rd_mask_reg; + status_fifo_rd_finish_next = status_fifo_rd_finish_reg; + status_fifo_rd_valid_next = status_fifo_rd_valid_reg; + + op_table_write_complete_ptr = status_fifo_rd_op_tag_reg; + op_table_write_complete_en = 1'b0; + + if (status_fifo_rd_valid_reg && (status_fifo_rd_mask_reg & ~out_done) == 0) begin + // got write completion, pop and return status + status_fifo_rd_valid_next = 1'b0; + + out_done_ack = status_fifo_rd_mask_reg; + + if (status_fifo_rd_finish_reg) begin + // mark done + op_table_write_complete_ptr = status_fifo_rd_op_tag_reg; + op_table_write_complete_en = 1'b1; + end + end + + if (!status_fifo_rd_valid_next && status_fifo_rd_ptr_reg != status_fifo_wr_ptr_reg) begin + // status FIFO not empty + status_fifo_rd_op_tag_next = status_fifo_op_tag[status_fifo_rd_ptr_reg[STATUS_FIFO_ADDR_WIDTH-1:0]]; + status_fifo_rd_mask_next = status_fifo_mask[status_fifo_rd_ptr_reg[STATUS_FIFO_ADDR_WIDTH-1:0]]; + status_fifo_rd_finish_next = status_fifo_finish[status_fifo_rd_ptr_reg[STATUS_FIFO_ADDR_WIDTH-1:0]]; + status_fifo_rd_valid_next = 1'b1; + status_fifo_rd_ptr_next = status_fifo_rd_ptr_reg + 1; + end + + // commit operations in-order + op_table_finish_en = 1'b0; + + m_axis_read_desc_status_tag_next = op_table_tag[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]]; + m_axis_read_desc_status_error_next = 0; + m_axis_read_desc_status_valid_next = 1'b0; + + if (op_table_active[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]] && op_table_write_complete[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]] && op_table_finish_ptr_reg != op_table_start_ptr_reg) begin + op_table_finish_en = 1'b1; + + if (op_table_last[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]]) begin + m_axis_read_desc_status_tag_next = op_table_tag[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]]; + m_axis_read_desc_status_error_next = 0; + m_axis_read_desc_status_valid_next = 1'b1; + end + end +end + +always @(posedge clk) begin + req_state_reg <= req_state_next; + axi_state_reg <= axi_state_next; + + req_axi_addr_reg <= req_axi_addr_next; + req_ram_sel_reg <= req_ram_sel_next; + req_ram_addr_reg <= req_ram_addr_next; + req_op_count_reg <= req_op_count_next; + req_tr_count_reg <= req_tr_count_next; + req_tag_reg <= req_tag_next; + + ram_sel_reg <= ram_sel_next; + addr_reg <= addr_next; + addr_delay_reg <= addr_delay_next; + op_count_reg <= op_count_next; + ram_mask_reg <= ram_mask_next; + ram_mask_0_reg <= ram_mask_0_next; + ram_mask_1_reg <= ram_mask_1_next; + ram_wrap_reg <= ram_wrap_next; + cycle_byte_count_reg <= cycle_byte_count_next; + start_offset_reg <= start_offset_next; + end_offset_reg <= end_offset_next; + offset_reg <= offset_next; + op_tag_reg <= op_tag_next; + + m_axi_rdata_int_reg <= m_axi_rdata_int_next; + m_axi_rvalid_int_reg <= m_axi_rvalid_int_next; + + m_axi_arid_reg <= m_axi_arid_next; + m_axi_araddr_reg <= m_axi_araddr_next; + m_axi_arlen_reg <= m_axi_arlen_next; + m_axi_arvalid_reg <= m_axi_arvalid_next; + m_axi_rready_reg <= m_axi_rready_next; + + s_axis_read_desc_ready_reg <= s_axis_read_desc_ready_next; + + m_axis_read_desc_status_tag_reg <= m_axis_read_desc_status_tag_next; + m_axis_read_desc_status_error_reg <= m_axis_read_desc_status_error_next; + m_axis_read_desc_status_valid_reg <= m_axis_read_desc_status_valid_next; + + if (status_fifo_we) begin + status_fifo_op_tag[status_fifo_wr_ptr_reg[STATUS_FIFO_ADDR_WIDTH-1:0]] <= status_fifo_wr_op_tag; + status_fifo_mask[status_fifo_wr_ptr_reg[STATUS_FIFO_ADDR_WIDTH-1:0]] <= status_fifo_wr_mask; + status_fifo_finish[status_fifo_wr_ptr_reg[STATUS_FIFO_ADDR_WIDTH-1:0]] <= status_fifo_wr_finish; + status_fifo_wr_ptr_reg <= status_fifo_wr_ptr_reg + 1; + end + status_fifo_rd_ptr_reg <= status_fifo_rd_ptr_next; + + status_fifo_finish_reg <= status_fifo_finish_next; + status_fifo_we_reg <= status_fifo_we_next; + + status_fifo_rd_op_tag_reg <= status_fifo_rd_op_tag_next; + status_fifo_rd_mask_reg <= status_fifo_rd_mask_next; + status_fifo_rd_finish_reg <= status_fifo_rd_finish_next; + status_fifo_rd_valid_reg <= status_fifo_rd_valid_next; + + status_fifo_half_full_reg <= $unsigned(status_fifo_wr_ptr_reg - status_fifo_rd_ptr_reg) >= 2**(STATUS_FIFO_ADDR_WIDTH-1); + + if (op_table_start_en) begin + op_table_start_ptr_reg <= op_table_start_ptr_reg + 1; + op_table_active[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= 1'b1; + op_table_axi_addr[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_axi_addr; + op_table_ram_sel[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_ram_sel; + op_table_ram_addr[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_ram_addr; + op_table_len[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_len; + op_table_cycle_count[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_cycle_count; + op_table_tag[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_tag; + op_table_last[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_last; + op_table_write_complete[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= 1'b0; + end + + if (op_table_write_complete_en) begin + op_table_write_complete[op_table_write_complete_ptr] <= 1'b1; + end + + if (op_table_finish_en) begin + op_table_finish_ptr_reg <= op_table_finish_ptr_reg + 1; + op_table_active[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]] <= 1'b0; + end + + if (rst) begin + req_state_reg <= REQ_STATE_IDLE; + axi_state_reg <= AXI_STATE_IDLE; + + m_axi_rdata_int_reg <= 1'b0; + + m_axi_arvalid_reg <= 1'b0; + m_axi_rready_reg <= 1'b0; + + s_axis_read_desc_ready_reg <= 1'b0; + m_axis_read_desc_status_valid_reg <= 1'b0; + + status_fifo_wr_ptr_reg <= 0; + status_fifo_rd_ptr_reg <= 0; + status_fifo_we_reg <= 1'b0; + status_fifo_rd_valid_reg <= 1'b0; + + op_table_active <= 0; + end +end + +// output datapath logic (write data) +generate + +genvar n; + +for (n = 0; n < RAM_SEG_COUNT; n = n + 1) begin + + reg [RAM_SEL_WIDTH-1:0] ram_wr_cmd_sel_reg = {RAM_SEL_WIDTH{1'b0}}; + reg [RAM_SEG_BE_WIDTH-1:0] ram_wr_cmd_be_reg = {RAM_SEG_BE_WIDTH{1'b0}}; + reg [RAM_SEG_ADDR_WIDTH-1:0] ram_wr_cmd_addr_reg = {RAM_SEG_ADDR_WIDTH{1'b0}}; + reg [RAM_SEG_DATA_WIDTH-1:0] ram_wr_cmd_data_reg = {RAM_SEG_DATA_WIDTH{1'b0}}; + reg ram_wr_cmd_valid_reg = 1'b0; + + reg [OUTPUT_FIFO_ADDR_WIDTH-1:0] out_fifo_wr_ptr_reg = 0; + reg [OUTPUT_FIFO_ADDR_WIDTH-1:0] out_fifo_rd_ptr_reg = 0; + reg out_fifo_half_full_reg = 1'b0; + + wire out_fifo_full = out_fifo_wr_ptr_reg == (out_fifo_rd_ptr_reg ^ {1'b1, {OUTPUT_FIFO_ADDR_WIDTH{1'b0}}}); + wire out_fifo_empty = out_fifo_wr_ptr_reg == out_fifo_rd_ptr_reg; + + (* ram_style = "distributed" *) + reg [RAM_SEL_WIDTH-1:0] out_fifo_wr_cmd_sel[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + (* ram_style = "distributed" *) + reg [RAM_SEG_BE_WIDTH-1:0] out_fifo_wr_cmd_be[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + (* ram_style = "distributed" *) + reg [RAM_SEG_ADDR_WIDTH-1:0] out_fifo_wr_cmd_addr[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + (* ram_style = "distributed" *) + reg [RAM_SEG_DATA_WIDTH-1:0] out_fifo_wr_cmd_data[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + + reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] done_count_reg = 0; + reg done_reg = 1'b0; + + assign ram_wr_cmd_ready_int[n +: 1] = !out_fifo_half_full_reg; + + assign ram_wr_cmd_sel[n*RAM_SEL_WIDTH +: RAM_SEL_WIDTH] = ram_wr_cmd_sel_reg; + assign ram_wr_cmd_be[n*RAM_SEG_BE_WIDTH +: RAM_SEG_BE_WIDTH] = ram_wr_cmd_be_reg; + assign ram_wr_cmd_addr[n*RAM_SEG_ADDR_WIDTH +: RAM_SEG_ADDR_WIDTH] = ram_wr_cmd_addr_reg; + assign ram_wr_cmd_data[n*RAM_SEG_DATA_WIDTH +: RAM_SEG_DATA_WIDTH] = ram_wr_cmd_data_reg; + assign ram_wr_cmd_valid[n +: 1] = ram_wr_cmd_valid_reg; + + assign out_done[n] = done_reg; + + always @(posedge clk) begin + ram_wr_cmd_valid_reg <= ram_wr_cmd_valid_reg && !ram_wr_cmd_ready[n +: 1]; + + out_fifo_half_full_reg <= $unsigned(out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2**(OUTPUT_FIFO_ADDR_WIDTH-1); + + if (!out_fifo_full && ram_wr_cmd_valid_int[n +: 1]) begin + out_fifo_wr_cmd_sel[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= ram_wr_cmd_sel_int[n*RAM_SEL_WIDTH +: RAM_SEL_WIDTH]; + out_fifo_wr_cmd_be[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= ram_wr_cmd_be_int[n*RAM_SEG_BE_WIDTH +: RAM_SEG_BE_WIDTH]; + out_fifo_wr_cmd_addr[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= ram_wr_cmd_addr_int[n*RAM_SEG_ADDR_WIDTH +: RAM_SEG_ADDR_WIDTH]; + out_fifo_wr_cmd_data[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= ram_wr_cmd_data_int[n*RAM_SEG_DATA_WIDTH +: RAM_SEG_DATA_WIDTH]; + out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1; + end + + if (!out_fifo_empty && (!ram_wr_cmd_valid_reg || ram_wr_cmd_ready[n +: 1])) begin + ram_wr_cmd_sel_reg <= out_fifo_wr_cmd_sel[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + ram_wr_cmd_be_reg <= out_fifo_wr_cmd_be[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + ram_wr_cmd_addr_reg <= out_fifo_wr_cmd_addr[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + ram_wr_cmd_data_reg <= out_fifo_wr_cmd_data[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + ram_wr_cmd_valid_reg <= 1'b1; + out_fifo_rd_ptr_reg <= out_fifo_rd_ptr_reg + 1; + end + + if (done_count_reg < 2**OUTPUT_FIFO_ADDR_WIDTH && ram_wr_done[n] && !out_done_ack[n]) begin + done_count_reg <= done_count_reg + 1; + done_reg <= 1; + end else if (done_count_reg > 0 && !ram_wr_done[n] && out_done_ack[n]) begin + done_count_reg <= done_count_reg - 1; + done_reg <= done_count_reg > 1; + end + + if (rst) begin + out_fifo_wr_ptr_reg <= 0; + out_fifo_rd_ptr_reg <= 0; + ram_wr_cmd_valid_reg <= 1'b0; + done_count_reg <= 0; + done_reg <= 1'b0; + end + end + +end + +endgenerate + +endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_axi_wr.v b/fpga/lib/pcie/rtl/dma_if_axi_wr.v new file mode 100644 index 000000000..15534ba55 --- /dev/null +++ b/fpga/lib/pcie/rtl/dma_if_axi_wr.v @@ -0,0 +1,972 @@ +/* + +Copyright (c) 2021 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI DMA write interface + */ +module dma_if_axi_wr # +( + // Width of AXI data bus in bits + parameter AXI_DATA_WIDTH = 32, + // Width of AXI address bus in bits + parameter AXI_ADDR_WIDTH = 16, + // Width of AXI wstrb (width of data bus in words) + parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8), + // Width of AXI ID signal + parameter AXI_ID_WIDTH = 8, + // Maximum AXI burst length to generate + parameter AXI_MAX_BURST_LEN = 256, + // RAM segment countm_axis_read_desc_status_error + parameter RAM_SEG_COUNT = 2, + // RAM segment data width + parameter RAM_SEG_DATA_WIDTH = AXI_DATA_WIDTH*2/RAM_SEG_COUNT, + // RAM segment address width + parameter RAM_SEG_ADDR_WIDTH = 8, + // RAM segment byte enable width + parameter RAM_SEG_BE_WIDTH = RAM_SEG_DATA_WIDTH/8, + // RAM select width + parameter RAM_SEL_WIDTH = 2, + // RAM address width + parameter RAM_ADDR_WIDTH = RAM_SEG_ADDR_WIDTH+$clog2(RAM_SEG_COUNT)+$clog2(RAM_SEG_BE_WIDTH), + // Length field width + parameter LEN_WIDTH = 16, + // Tag field width + parameter TAG_WIDTH = 8, + // Operation table size + parameter OP_TABLE_SIZE = 2**(AXI_ID_WIDTH), + // Use AXI ID signals + parameter USE_AXI_ID = 1 +) +( + input wire clk, + input wire rst, + + /* + * AXI master interface + */ + output wire [AXI_ID_WIDTH-1:0] m_axi_awid, + output wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr, + output wire [7:0] m_axi_awlen, + output wire [2:0] m_axi_awsize, + output wire [1:0] m_axi_awburst, + output wire m_axi_awlock, + output wire [3:0] m_axi_awcache, + output wire [2:0] m_axi_awprot, + output wire m_axi_awvalid, + input wire m_axi_awready, + output wire [AXI_DATA_WIDTH-1:0] m_axi_wdata, + output wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb, + output wire m_axi_wlast, + output wire m_axi_wvalid, + input wire m_axi_wready, + input wire [AXI_ID_WIDTH-1:0] m_axi_bid, + input wire [1:0] m_axi_bresp, + input wire m_axi_bvalid, + output wire m_axi_bready, + + /* + * AXI write descriptor input + */ + input wire [AXI_ADDR_WIDTH-1:0] s_axis_write_desc_axi_addr, + input wire [RAM_SEL_WIDTH-1:0] s_axis_write_desc_ram_sel, + input wire [RAM_ADDR_WIDTH-1:0] s_axis_write_desc_ram_addr, + input wire [LEN_WIDTH-1:0] s_axis_write_desc_len, + input wire [TAG_WIDTH-1:0] s_axis_write_desc_tag, + input wire s_axis_write_desc_valid, + output wire s_axis_write_desc_ready, + + /* + * AXI write descriptor status output + */ + output wire [TAG_WIDTH-1:0] m_axis_write_desc_status_tag, + output wire [3:0] m_axis_write_desc_status_error, + output wire m_axis_write_desc_status_valid, + + /* + * RAM interface + */ + output wire [RAM_SEG_COUNT*RAM_SEL_WIDTH-1:0] ram_rd_cmd_sel, + output wire [RAM_SEG_COUNT*RAM_SEG_ADDR_WIDTH-1:0] ram_rd_cmd_addr, + output wire [RAM_SEG_COUNT-1:0] ram_rd_cmd_valid, + input wire [RAM_SEG_COUNT-1:0] ram_rd_cmd_ready, + input wire [RAM_SEG_COUNT*RAM_SEG_DATA_WIDTH-1:0] ram_rd_resp_data, + input wire [RAM_SEG_COUNT-1:0] ram_rd_resp_valid, + output wire [RAM_SEG_COUNT-1:0] ram_rd_resp_ready, + + /* + * Configuration + */ + input wire enable +); + +parameter RAM_WORD_WIDTH = RAM_SEG_BE_WIDTH; +parameter RAM_WORD_SIZE = RAM_SEG_DATA_WIDTH/RAM_WORD_WIDTH; + +parameter AXI_WORD_WIDTH = AXI_STRB_WIDTH; +parameter AXI_WORD_SIZE = AXI_DATA_WIDTH/AXI_WORD_WIDTH; +parameter AXI_BURST_SIZE = $clog2(AXI_STRB_WIDTH); +parameter AXI_MAX_BURST_SIZE = AXI_MAX_BURST_LEN << AXI_BURST_SIZE; + +parameter OFFSET_WIDTH = AXI_STRB_WIDTH > 1 ? $clog2(AXI_STRB_WIDTH) : 1; +parameter OFFSET_MASK = AXI_STRB_WIDTH > 1 ? {OFFSET_WIDTH{1'b1}} : 0; +parameter RAM_OFFSET_WIDTH = $clog2(RAM_SEG_COUNT*RAM_SEG_BE_WIDTH); +parameter ADDR_MASK = {AXI_ADDR_WIDTH{1'b1}} << $clog2(AXI_STRB_WIDTH); +parameter CYCLE_COUNT_WIDTH = LEN_WIDTH - AXI_BURST_SIZE + 1; + +parameter MASK_FIFO_ADDR_WIDTH = $clog2(OP_TABLE_SIZE)+1; + +parameter OP_TAG_WIDTH = $clog2(OP_TABLE_SIZE); + +parameter OUTPUT_FIFO_ADDR_WIDTH = 5; + +// bus width assertions +initial begin + if (AXI_WORD_SIZE * AXI_STRB_WIDTH != AXI_DATA_WIDTH) begin + $error("Error: AXI data width not evenly divisble (instance %m)"); + $finish; + end + + if (AXI_WORD_SIZE != RAM_WORD_SIZE) begin + $error("Error: word size mismatch (instance %m)"); + $finish; + end + + if (2**$clog2(AXI_WORD_WIDTH) != AXI_WORD_WIDTH) begin + $error("Error: AXI word width must be even power of two (instance %m)"); + $finish; + end + + if (AXI_MAX_BURST_LEN < 1 || AXI_MAX_BURST_LEN > 256) begin + $error("Error: AXI_MAX_BURST_LEN must be between 1 and 256 (instance %m)"); + $finish; + end + + if (RAM_SEG_COUNT < 2) begin + $error("Error: RAM interface requires at least 2 segments (instance %m)"); + $finish; + end + + if (RAM_SEG_COUNT*RAM_SEG_DATA_WIDTH != AXI_DATA_WIDTH*2) begin + $error("Error: RAM interface width must be double the AXI interface width (instance %m)"); + $finish; + end + + if (2**$clog2(RAM_WORD_WIDTH) != RAM_WORD_WIDTH) begin + $error("Error: RAM word width must be even power of two (instance %m)"); + $finish; + end + + if (RAM_ADDR_WIDTH != RAM_SEG_ADDR_WIDTH+$clog2(RAM_SEG_COUNT)+$clog2(RAM_SEG_BE_WIDTH)) begin + $error("Error: RAM_ADDR_WIDTH does not match RAM configuration (instance %m)"); + $finish; + end +end + +localparam [1:0] + AXI_RESP_OKAY = 2'b00, + AXI_RESP_EXOKAY = 2'b01, + AXI_RESP_SLVERR = 2'b10, + AXI_RESP_DECERR = 2'b11; + +localparam [3:0] + DMA_ERROR_NONE = 4'd0, + DMA_ERROR_TIMEOUT = 4'd1, + DMA_ERROR_PARITY = 4'd2, + DMA_ERROR_AXI_RD_SLVERR = 4'd4, + DMA_ERROR_AXI_RD_DECERR = 4'd5, + DMA_ERROR_AXI_WR_SLVERR = 4'd6, + DMA_ERROR_AXI_WR_DECERR = 4'd7, + DMA_ERROR_PCIE_FLR = 4'd8, + DMA_ERROR_PCIE_CPL_POISONED = 4'd9, + DMA_ERROR_PCIE_CPL_STATUS_UR = 4'd10, + DMA_ERROR_PCIE_CPL_STATUS_CA = 4'd11; + +localparam [0:0] + REQ_STATE_IDLE = 1'd0, + REQ_STATE_START = 1'd1; + +reg [0:0] req_state_reg = REQ_STATE_IDLE, req_state_next; + +localparam [0:0] + READ_STATE_IDLE = 1'd0, + READ_STATE_READ = 1'd1; + +reg [0:0] read_state_reg = READ_STATE_IDLE, read_state_next; + +localparam [0:0] + AXI_STATE_IDLE = 1'd0, + AXI_STATE_TRANSFER = 1'd1; + +reg [0:0] axi_state_reg = AXI_STATE_IDLE, axi_state_next; + +// datapath control signals +reg mask_fifo_we; + +reg read_cmd_ready; + +reg [AXI_ADDR_WIDTH-1:0] axi_addr_reg = {AXI_ADDR_WIDTH{1'b0}}, axi_addr_next; +reg [RAM_SEL_WIDTH-1:0] ram_sel_reg = {RAM_SEL_WIDTH{1'b0}}, ram_sel_next; +reg [RAM_ADDR_WIDTH-1:0] ram_addr_reg = {RAM_ADDR_WIDTH{1'b0}}, ram_addr_next; +reg [LEN_WIDTH-1:0] op_count_reg = {LEN_WIDTH{1'b0}}, op_count_next; +reg [LEN_WIDTH-1:0] tr_count_reg = {LEN_WIDTH{1'b0}}, tr_count_next; +reg [12:0] tr_word_count_reg = 13'd0, tr_word_count_next; +reg [TAG_WIDTH-1:0] tag_reg = {TAG_WIDTH{1'b0}}, tag_next; + +reg [AXI_ADDR_WIDTH-1:0] read_axi_addr_reg = {AXI_ADDR_WIDTH{1'b0}}, read_axi_addr_next; +reg [RAM_SEL_WIDTH-1:0] read_ram_sel_reg = {RAM_SEL_WIDTH{1'b0}}, read_ram_sel_next; +reg [RAM_ADDR_WIDTH-1:0] read_ram_addr_reg = {RAM_ADDR_WIDTH{1'b0}}, read_ram_addr_next; +reg [LEN_WIDTH-1:0] read_len_reg = {LEN_WIDTH{1'b0}}, read_len_next; +reg [RAM_SEG_COUNT-1:0] read_ram_mask_reg = {RAM_SEG_COUNT{1'b0}}, read_ram_mask_next; +reg [RAM_SEG_COUNT-1:0] read_ram_mask_0_reg = {RAM_SEG_COUNT{1'b0}}, read_ram_mask_0_next; +reg [RAM_SEG_COUNT-1:0] read_ram_mask_1_reg = {RAM_SEG_COUNT{1'b0}}, read_ram_mask_1_next; +reg ram_wrap_reg = 1'b0, ram_wrap_next; +reg [CYCLE_COUNT_WIDTH-1:0] read_cycle_count_reg = {CYCLE_COUNT_WIDTH{1'b0}}, read_cycle_count_next; +reg read_last_cycle_reg = 1'b0, read_last_cycle_next; +reg [OFFSET_WIDTH+1-1:0] cycle_byte_count_reg = {OFFSET_WIDTH+1{1'b0}}, cycle_byte_count_next; +reg [RAM_OFFSET_WIDTH-1:0] start_offset_reg = {RAM_OFFSET_WIDTH{1'b0}}, start_offset_next; +reg [RAM_OFFSET_WIDTH-1:0] end_offset_reg = {RAM_OFFSET_WIDTH{1'b0}}, end_offset_next; + +reg [AXI_ADDR_WIDTH-1:0] tlp_addr_reg = {AXI_ADDR_WIDTH{1'b0}}, tlp_addr_next; +reg [11:0] tlp_len_reg = 12'd0, tlp_len_next; +reg [RAM_OFFSET_WIDTH-1:0] offset_reg = {RAM_OFFSET_WIDTH{1'b0}}, offset_next; +reg [AXI_STRB_WIDTH-1:0] strb_offset_mask_reg = {AXI_STRB_WIDTH{1'b1}}, strb_offset_mask_next; +reg [OFFSET_WIDTH-1:0] last_cycle_offset_reg = {OFFSET_WIDTH{1'b0}}, last_cycle_offset_next; +reg [RAM_SEG_COUNT-1:0] ram_mask_reg = {RAM_SEG_COUNT{1'b0}}, ram_mask_next; +reg ram_mask_valid_reg = 1'b0, ram_mask_valid_next; +reg [CYCLE_COUNT_WIDTH-1:0] cycle_count_reg = {CYCLE_COUNT_WIDTH{1'b0}}, cycle_count_next; +reg last_cycle_reg = 1'b0, last_cycle_next; + +reg [AXI_ADDR_WIDTH-1:0] read_cmd_axi_addr_reg = {AXI_ADDR_WIDTH{1'b0}}, read_cmd_axi_addr_next; +reg [RAM_SEL_WIDTH-1:0] read_cmd_ram_sel_reg = {RAM_SEL_WIDTH{1'b0}}, read_cmd_ram_sel_next; +reg [RAM_ADDR_WIDTH-1:0] read_cmd_ram_addr_reg = {RAM_ADDR_WIDTH{1'b0}}, read_cmd_ram_addr_next; +reg [11:0] read_cmd_len_reg = 12'd0, read_cmd_len_next; +reg [CYCLE_COUNT_WIDTH-1:0] read_cmd_cycle_count_reg = {CYCLE_COUNT_WIDTH{1'b0}}, read_cmd_cycle_count_next; +reg read_cmd_last_cycle_reg = 1'b0, read_cmd_last_cycle_next; +reg read_cmd_valid_reg = 1'b0, read_cmd_valid_next; + +reg [MASK_FIFO_ADDR_WIDTH+1-1:0] mask_fifo_wr_ptr_reg = 0; +reg [MASK_FIFO_ADDR_WIDTH+1-1:0] mask_fifo_rd_ptr_reg = 0, mask_fifo_rd_ptr_next; +reg [RAM_SEG_COUNT-1:0] mask_fifo_mask[(2**MASK_FIFO_ADDR_WIDTH)-1:0]; +reg [RAM_SEG_COUNT-1:0] mask_fifo_wr_mask; + +wire mask_fifo_empty = mask_fifo_wr_ptr_reg == mask_fifo_rd_ptr_reg; +wire mask_fifo_full = mask_fifo_wr_ptr_reg == (mask_fifo_rd_ptr_reg ^ (1 << MASK_FIFO_ADDR_WIDTH)); + +reg [AXI_ID_WIDTH-1:0] m_axi_awid_reg = {AXI_ID_WIDTH{1'b0}}, m_axi_awid_next; +reg [AXI_ADDR_WIDTH-1:0] m_axi_awaddr_reg = {AXI_ADDR_WIDTH{1'b0}}, m_axi_awaddr_next; +reg [7:0] m_axi_awlen_reg = 8'd0, m_axi_awlen_next; +reg m_axi_awvalid_reg = 1'b0, m_axi_awvalid_next; +reg m_axi_bready_reg = 1'b0, m_axi_bready_next; + +reg s_axis_write_desc_ready_reg = 1'b0, s_axis_write_desc_ready_next; + +reg [TAG_WIDTH-1:0] m_axis_write_desc_status_tag_reg = {TAG_WIDTH{1'b0}}, m_axis_write_desc_status_tag_next; +reg [3:0] m_axis_write_desc_status_error_reg = 4'd0, m_axis_write_desc_status_error_next; +reg m_axis_write_desc_status_valid_reg = 1'b0, m_axis_write_desc_status_valid_next; + +reg [RAM_SEG_COUNT*RAM_SEL_WIDTH-1:0] ram_rd_cmd_sel_reg = 0, ram_rd_cmd_sel_next; +reg [RAM_SEG_COUNT*RAM_SEG_ADDR_WIDTH-1:0] ram_rd_cmd_addr_reg = 0, ram_rd_cmd_addr_next; +reg [RAM_SEG_COUNT-1:0] ram_rd_cmd_valid_reg = 0, ram_rd_cmd_valid_next; +reg [RAM_SEG_COUNT-1:0] ram_rd_resp_ready_cmb; + +// internal datapath +reg [AXI_DATA_WIDTH-1:0] m_axi_wdata_int; +reg [AXI_STRB_WIDTH-1:0] m_axi_wstrb_int; +reg m_axi_wlast_int; +reg m_axi_wvalid_int; +wire m_axi_wready_int; + +assign m_axi_awid = m_axi_awid_reg; +assign m_axi_awaddr = m_axi_awaddr_reg; +assign m_axi_awlen = m_axi_awlen_reg; +assign m_axi_awsize = AXI_BURST_SIZE; +assign m_axi_awburst = 2'b01; +assign m_axi_awlock = 1'b0; +assign m_axi_awcache = 4'b0011; +assign m_axi_awprot = 3'b010; +assign m_axi_awvalid = m_axi_awvalid_reg; +assign m_axi_bready = m_axi_bready_reg; + +assign s_axis_write_desc_ready = s_axis_write_desc_ready_reg; + +assign m_axis_write_desc_status_tag = m_axis_write_desc_status_tag_reg; +assign m_axis_write_desc_status_error = m_axis_write_desc_status_error_reg; +assign m_axis_write_desc_status_valid = m_axis_write_desc_status_valid_reg; + +assign ram_rd_cmd_sel = ram_rd_cmd_sel_reg; +assign ram_rd_cmd_addr = ram_rd_cmd_addr_reg; +assign ram_rd_cmd_valid = ram_rd_cmd_valid_reg; +assign ram_rd_resp_ready = ram_rd_resp_ready_cmb; + +// operation tag management +reg [OP_TAG_WIDTH+1-1:0] op_table_start_ptr_reg = 0; +reg [AXI_ADDR_WIDTH-1:0] op_table_start_axi_addr; +reg [11:0] op_table_start_len; +reg [CYCLE_COUNT_WIDTH-1:0] op_table_start_cycle_count; +reg [RAM_OFFSET_WIDTH-1:0] op_table_start_offset; +reg [TAG_WIDTH-1:0] op_table_start_tag; +reg op_table_start_last; +reg op_table_start_en; +reg [OP_TAG_WIDTH+1-1:0] op_table_tx_start_ptr_reg = 0; +reg op_table_tx_start_en; +reg [OP_TAG_WIDTH+1-1:0] op_table_tx_finish_ptr_reg = 0; +reg op_table_tx_finish_en; +reg op_table_write_complete_en; +reg [OP_TAG_WIDTH-1:0] op_table_write_complete_ptr; +reg [OP_TAG_WIDTH+1-1:0] op_table_finish_ptr_reg = 0; +reg op_table_finish_en; + +reg [2**OP_TAG_WIDTH-1:0] op_table_active = 0; +reg [2**OP_TAG_WIDTH-1:0] op_table_write_complete = 0; +reg [AXI_ADDR_WIDTH-1:0] op_table_axi_addr[2**OP_TAG_WIDTH-1:0]; +reg [11:0] op_table_len[2**OP_TAG_WIDTH-1:0]; +reg [CYCLE_COUNT_WIDTH-1:0] op_table_cycle_count[2**OP_TAG_WIDTH-1:0]; +reg [RAM_OFFSET_WIDTH-1:0] op_table_offset[2**OP_TAG_WIDTH-1:0]; +reg [TAG_WIDTH-1:0] op_table_tag[2**OP_TAG_WIDTH-1:0]; +reg op_table_last[2**OP_TAG_WIDTH-1:0]; + +integer i; + +initial begin + for (i = 0; i < 2**OP_TAG_WIDTH; i = i + 1) begin + op_table_axi_addr[i] = 0; + op_table_len[i] = 0; + op_table_cycle_count[i] = 0; + op_table_offset[i] = 0; + op_table_tag[i] = 0; + op_table_last[i] = 0; + end +end + +always @* begin + req_state_next = REQ_STATE_IDLE; + + s_axis_write_desc_ready_next = 1'b0; + + tag_next = tag_reg; + axi_addr_next = axi_addr_reg; + ram_sel_next = ram_sel_reg; + ram_addr_next = ram_addr_reg; + op_count_next = op_count_reg; + tr_count_next = tr_count_reg; + tr_word_count_next = tr_word_count_reg; + + read_cmd_axi_addr_next = read_cmd_axi_addr_reg; + read_cmd_ram_sel_next = read_cmd_ram_sel_reg; + read_cmd_ram_addr_next = read_cmd_ram_addr_reg; + read_cmd_len_next = read_cmd_len_reg; + read_cmd_cycle_count_next = read_cmd_cycle_count_reg; + read_cmd_last_cycle_next = read_cmd_last_cycle_reg; + read_cmd_valid_next = read_cmd_valid_reg && !read_cmd_ready; + + op_table_start_axi_addr = axi_addr_reg; + op_table_start_len = 0; + op_table_start_cycle_count = 0; + op_table_start_offset = (axi_addr_reg & OFFSET_MASK)-ram_addr_reg[RAM_OFFSET_WIDTH-1:0]; + op_table_start_tag = tag_reg; + op_table_start_last = 0; + op_table_start_en = 1'b0; + + // TLP segmentation + case (req_state_reg) + REQ_STATE_IDLE: begin + // idle state, wait for incoming descriptor + s_axis_write_desc_ready_next = !op_table_active[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] && ($unsigned(op_table_start_ptr_reg - op_table_finish_ptr_reg) < 2**OP_TAG_WIDTH) && enable; + + axi_addr_next = s_axis_write_desc_axi_addr; + ram_sel_next = s_axis_write_desc_ram_sel; + ram_addr_next = s_axis_write_desc_ram_addr; + op_count_next = s_axis_write_desc_len; + tag_next = s_axis_write_desc_tag; + + if (op_count_next <= AXI_MAX_BURST_SIZE - (axi_addr_next & OFFSET_MASK) || AXI_MAX_BURST_SIZE >= 4096) begin + // packet smaller than max burst size + if (((axi_addr_next & 12'hfff) + (op_count_next & 12'hfff)) >> 12 != 0 || op_count_next >> 12 != 0) begin + // crosses 4k boundary + tr_word_count_next = 13'h1000 - axi_addr_next[11:0]; + end else begin + // does not cross 4k boundary + tr_word_count_next = op_count_next; + end + end else begin + // packet larger than max burst size + if (((axi_addr_next & 12'hfff) + AXI_MAX_BURST_SIZE) >> 12 != 0) begin + // crosses 4k boundary + tr_word_count_next = 13'h1000 - axi_addr_next[11:0]; + end else begin + // does not cross 4k boundary + tr_word_count_next = AXI_MAX_BURST_SIZE - (axi_addr_next & OFFSET_MASK); + end + end + + if (s_axis_write_desc_ready & s_axis_write_desc_valid) begin + $display("AXI DMA start write (AXI 0x%x, RAM 0x%x 0x%x, len %d, tag 0x%x)", s_axis_write_desc_axi_addr, s_axis_write_desc_ram_sel, s_axis_write_desc_ram_addr, s_axis_write_desc_len, s_axis_write_desc_tag); + s_axis_write_desc_ready_next = 1'b0; + req_state_next = REQ_STATE_START; + end else begin + req_state_next = REQ_STATE_IDLE; + end + end + REQ_STATE_START: begin + // start state, compute length + if (!op_table_active[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] && ($unsigned(op_table_start_ptr_reg - op_table_finish_ptr_reg) < 2**OP_TAG_WIDTH) && (!ram_rd_cmd_valid_reg || ram_rd_cmd_ready) && (!read_cmd_valid_reg || read_cmd_ready)) begin + read_cmd_axi_addr_next = axi_addr_reg; + read_cmd_ram_sel_next = ram_sel_reg; + read_cmd_ram_addr_next = ram_addr_reg; + read_cmd_len_next = tr_word_count_next; + read_cmd_cycle_count_next = (tr_word_count_next + (axi_addr_reg & OFFSET_MASK) - 1) >> AXI_BURST_SIZE; + op_table_start_cycle_count = read_cmd_cycle_count_next; + read_cmd_last_cycle_next = read_cmd_cycle_count_next == 0; + read_cmd_valid_next = 1'b1; + + axi_addr_next = axi_addr_reg + tr_word_count_next; + ram_addr_next = ram_addr_reg + tr_word_count_next; + op_count_next = op_count_reg - tr_word_count_next; + + op_table_start_axi_addr = axi_addr_reg; + op_table_start_len = tr_word_count_next; + op_table_start_offset = (axi_addr_reg & OFFSET_MASK)-ram_addr_reg[RAM_OFFSET_WIDTH-1:0]; + op_table_start_tag = tag_reg; + op_table_start_last = op_count_reg == tr_word_count_next; + op_table_start_en = 1'b1; + + if (op_count_next <= AXI_MAX_BURST_SIZE - (axi_addr_next & OFFSET_MASK) || AXI_MAX_BURST_SIZE >= 4096) begin + // packet smaller than max burst size + if (((axi_addr_next & 12'hfff) + (op_count_next & 12'hfff)) >> 12 != 0 || op_count_next >> 12 != 0) begin + // crosses 4k boundary + tr_word_count_next = 13'h1000 - axi_addr_next[11:0]; + end else begin + // does not cross 4k boundary + tr_word_count_next = op_count_next; + end + end else begin + // packet larger than max burst size + if (((axi_addr_next & 12'hfff) + AXI_MAX_BURST_SIZE) >> 12 != 0) begin + // crosses 4k boundary + tr_word_count_next = 13'h1000 - axi_addr_next[11:0]; + end else begin + // does not cross 4k boundary + tr_word_count_next = AXI_MAX_BURST_SIZE - (axi_addr_next & OFFSET_MASK); + end + end + + if (!op_table_start_last) begin + req_state_next = REQ_STATE_START; + end else begin + s_axis_write_desc_ready_next = !op_table_active[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] && ($unsigned(op_table_start_ptr_reg - op_table_finish_ptr_reg) < 2**OP_TAG_WIDTH) && enable; + req_state_next = REQ_STATE_IDLE; + end + end else begin + req_state_next = REQ_STATE_START; + end + end + endcase +end + +always @* begin + read_state_next = READ_STATE_IDLE; + + read_cmd_ready = 1'b0; + + ram_rd_cmd_sel_next = ram_rd_cmd_sel_reg; + ram_rd_cmd_addr_next = ram_rd_cmd_addr_reg; + ram_rd_cmd_valid_next = ram_rd_cmd_valid_reg & ~ram_rd_cmd_ready; + + read_axi_addr_next = read_axi_addr_reg; + read_ram_sel_next = read_ram_sel_reg; + read_ram_addr_next = read_ram_addr_reg; + read_len_next = read_len_reg; + read_ram_mask_next = read_ram_mask_reg; + read_ram_mask_0_next = read_ram_mask_0_reg; + read_ram_mask_1_next = read_ram_mask_1_reg; + ram_wrap_next = ram_wrap_reg; + read_cycle_count_next = read_cycle_count_reg; + read_last_cycle_next = read_last_cycle_reg; + cycle_byte_count_next = cycle_byte_count_reg; + start_offset_next = start_offset_reg; + end_offset_next = end_offset_reg; + + mask_fifo_wr_mask = read_ram_mask_reg; + mask_fifo_we = 1'b0; + + // Read request generation + case (read_state_reg) + READ_STATE_IDLE: begin + // idle state, wait for read command + + read_axi_addr_next = read_cmd_axi_addr_reg; + read_ram_sel_next = read_cmd_ram_sel_reg; + read_ram_addr_next = read_cmd_ram_addr_reg; + read_len_next = read_cmd_len_reg; + read_cycle_count_next = read_cmd_cycle_count_reg; + read_last_cycle_next = read_cmd_last_cycle_reg; + + if (read_len_next > AXI_STRB_WIDTH-(read_axi_addr_next & OFFSET_MASK)) begin + cycle_byte_count_next = AXI_STRB_WIDTH-(read_axi_addr_next & OFFSET_MASK); + end else begin + cycle_byte_count_next = read_len_next; + end + start_offset_next = read_ram_addr_next; + {ram_wrap_next, end_offset_next} = start_offset_next+cycle_byte_count_next-1; + + read_ram_mask_0_next = {RAM_SEG_COUNT{1'b1}} << (start_offset_next >> $clog2(RAM_SEG_BE_WIDTH)); + read_ram_mask_1_next = {RAM_SEG_COUNT{1'b1}} >> (RAM_SEG_COUNT-1-(end_offset_next >> $clog2(RAM_SEG_BE_WIDTH))); + + if (!ram_wrap_next) begin + read_ram_mask_next = read_ram_mask_0_next & read_ram_mask_1_next; + read_ram_mask_0_next = read_ram_mask_0_next & read_ram_mask_1_next; + read_ram_mask_1_next = 0; + end else begin + read_ram_mask_next = read_ram_mask_0_next | read_ram_mask_1_next; + end + + if (read_cmd_valid_reg) begin + read_cmd_ready = 1'b1; + read_state_next = READ_STATE_READ; + end else begin + read_state_next = READ_STATE_IDLE; + end + end + READ_STATE_READ: begin + // read state - start new read operations + + if (!(ram_rd_cmd_valid & ~ram_rd_cmd_ready & read_ram_mask_reg) && !mask_fifo_full) begin + + // update counters + read_ram_addr_next = read_ram_addr_reg + cycle_byte_count_reg; + read_len_next = read_len_reg - cycle_byte_count_reg; + read_cycle_count_next = read_cycle_count_reg - 1; + read_last_cycle_next = read_cycle_count_next == 0; + + for (i = 0; i < RAM_SEG_COUNT; i = i + 1) begin + if (read_ram_mask_0_reg[i]) begin + ram_rd_cmd_sel_next[i*RAM_SEL_WIDTH +: RAM_SEL_WIDTH] = read_ram_sel_reg; + ram_rd_cmd_addr_next[i*RAM_SEG_ADDR_WIDTH +: RAM_SEG_ADDR_WIDTH] = read_ram_addr_reg[RAM_ADDR_WIDTH-1:RAM_ADDR_WIDTH-RAM_SEG_ADDR_WIDTH]; + ram_rd_cmd_valid_next[i] = 1'b1; + end + if (read_ram_mask_1_reg[i]) begin + ram_rd_cmd_sel_next[i*RAM_SEL_WIDTH +: RAM_SEL_WIDTH] = read_ram_sel_reg; + ram_rd_cmd_addr_next[i*RAM_SEG_ADDR_WIDTH +: RAM_SEG_ADDR_WIDTH] = read_ram_addr_reg[RAM_ADDR_WIDTH-1:RAM_ADDR_WIDTH-RAM_SEG_ADDR_WIDTH]+1; + ram_rd_cmd_valid_next[i] = 1'b1; + end + end + + mask_fifo_wr_mask = read_ram_mask_reg; + mask_fifo_we = 1'b1; + + if (read_len_next > AXI_STRB_WIDTH) begin + cycle_byte_count_next = AXI_STRB_WIDTH; + end else begin + cycle_byte_count_next = read_len_next; + end + start_offset_next = read_ram_addr_next; + {ram_wrap_next, end_offset_next} = start_offset_next+cycle_byte_count_next-1; + + read_ram_mask_0_next = {RAM_SEG_COUNT{1'b1}} << (start_offset_next >> $clog2(RAM_SEG_BE_WIDTH)); + read_ram_mask_1_next = {RAM_SEG_COUNT{1'b1}} >> (RAM_SEG_COUNT-1-(end_offset_next >> $clog2(RAM_SEG_BE_WIDTH))); + + if (!ram_wrap_next) begin + read_ram_mask_next = read_ram_mask_0_next & read_ram_mask_1_next; + read_ram_mask_0_next = read_ram_mask_0_next & read_ram_mask_1_next; + read_ram_mask_1_next = 0; + end else begin + read_ram_mask_next = read_ram_mask_0_next | read_ram_mask_1_next; + end + + if (!read_last_cycle_reg) begin + read_state_next = READ_STATE_READ; + end else if (read_cmd_valid_reg) begin + + read_axi_addr_next = read_cmd_axi_addr_reg; + read_ram_sel_next = read_cmd_ram_sel_reg; + read_ram_addr_next = read_cmd_ram_addr_reg; + read_len_next = read_cmd_len_reg; + read_cycle_count_next = read_cmd_cycle_count_reg; + read_last_cycle_next = read_cmd_last_cycle_reg; + + if (read_len_next > AXI_STRB_WIDTH-(read_axi_addr_next & OFFSET_MASK)) begin + cycle_byte_count_next = AXI_STRB_WIDTH-(read_axi_addr_next & OFFSET_MASK); + end else begin + cycle_byte_count_next = read_len_next; + end + start_offset_next = read_ram_addr_next; + {ram_wrap_next, end_offset_next} = start_offset_next+cycle_byte_count_next-1; + + read_ram_mask_0_next = {RAM_SEG_COUNT{1'b1}} << (start_offset_next >> $clog2(RAM_SEG_BE_WIDTH)); + read_ram_mask_1_next = {RAM_SEG_COUNT{1'b1}} >> (RAM_SEG_COUNT-1-(end_offset_next >> $clog2(RAM_SEG_BE_WIDTH))); + + if (!ram_wrap_next) begin + read_ram_mask_next = read_ram_mask_0_next & read_ram_mask_1_next; + read_ram_mask_0_next = read_ram_mask_0_next & read_ram_mask_1_next; + read_ram_mask_1_next = 0; + end else begin + read_ram_mask_next = read_ram_mask_0_next | read_ram_mask_1_next; + end + + read_cmd_ready = 1'b1; + + read_state_next = READ_STATE_READ; + end else begin + read_state_next = READ_STATE_IDLE; + end + end else begin + read_state_next = READ_STATE_READ; + end + end + endcase +end + +always @* begin + axi_state_next = AXI_STATE_IDLE; + + ram_rd_resp_ready_cmb = {RAM_SEG_COUNT{1'b0}}; + + tlp_addr_next = tlp_addr_reg; + tlp_len_next = tlp_len_reg; + offset_next = offset_reg; + strb_offset_mask_next = strb_offset_mask_reg; + last_cycle_offset_next = last_cycle_offset_reg; + ram_mask_next = ram_mask_reg; + ram_mask_valid_next = ram_mask_valid_reg; + cycle_count_next = cycle_count_reg; + last_cycle_next = last_cycle_reg; + + mask_fifo_rd_ptr_next = mask_fifo_rd_ptr_reg; + + op_table_tx_start_en = 1'b0; + op_table_tx_finish_en = 1'b0; + + op_table_write_complete_en = 1'b0; + op_table_write_complete_ptr = m_axi_bid; + + m_axi_awid_next = m_axi_awid_reg; + m_axi_awaddr_next = m_axi_awaddr_reg; + m_axi_awlen_next = m_axi_awlen_reg; + m_axi_awvalid_next = m_axi_awvalid_reg && !m_axi_awready; + m_axi_bready_next = 1'b0; + + m_axi_wdata_int = 0; + m_axi_wstrb_int = 0; + m_axi_wlast_int = 1'b0; + m_axi_wvalid_int = 1'b0; + + // read response processing and AXI write generation + case (axi_state_reg) + AXI_STATE_IDLE: begin + // idle state, wait for command + ram_rd_resp_ready_cmb = {RAM_SEG_COUNT{1'b0}}; + + tlp_addr_next = op_table_axi_addr[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]]; + tlp_len_next = op_table_len[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]]; + offset_next = op_table_offset[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]]; + strb_offset_mask_next = {AXI_STRB_WIDTH{1'b1}} << (tlp_addr_next & OFFSET_MASK); + last_cycle_offset_next = tlp_addr_next + (tlp_len_next & OFFSET_MASK); + cycle_count_next = op_table_cycle_count[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]]; + last_cycle_next = op_table_cycle_count[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]] == 0; + + if (op_table_active[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]] && op_table_tx_start_ptr_reg != op_table_start_ptr_reg && (!m_axi_awvalid_reg || m_axi_awready)) begin + m_axi_awid_next = op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]; + m_axi_awaddr_next = tlp_addr_next; + m_axi_awlen_next = cycle_count_next; + m_axi_awvalid_next = 1'b1; + op_table_tx_start_en = 1'b1; + axi_state_next = AXI_STATE_TRANSFER; + end else begin + axi_state_next = AXI_STATE_IDLE; + end + end + AXI_STATE_TRANSFER: begin + // transfer state, transfer data + ram_rd_resp_ready_cmb = {RAM_SEG_COUNT{1'b0}}; + + if (!(ram_mask_reg & ~ram_rd_resp_valid) && ram_mask_valid_reg && m_axi_wready_int) begin + // transfer in read data + ram_rd_resp_ready_cmb = ram_mask_reg; + ram_mask_valid_next = 1'b0; + + // update counters + cycle_count_next = cycle_count_reg - 1; + last_cycle_next = cycle_count_next == 0; + offset_next = offset_reg + AXI_STRB_WIDTH; + strb_offset_mask_next = {AXI_STRB_WIDTH{1'b1}}; + + m_axi_wdata_int = {2{ram_rd_resp_data}} >> (RAM_SEG_COUNT*RAM_SEG_DATA_WIDTH-offset_reg*AXI_WORD_SIZE); + m_axi_wstrb_int = strb_offset_mask_reg; + m_axi_wvalid_int = 1'b1; + + if (last_cycle_reg) begin + // no more data to transfer, finish operation + m_axi_wlast_int = 1'b1; + op_table_tx_finish_en = 1'b1; + + if (last_cycle_offset_reg) begin + m_axi_wstrb_int = strb_offset_mask_reg & {AXI_STRB_WIDTH{1'b1}} >> (AXI_STRB_WIDTH - last_cycle_offset_reg); + end + + // skip idle state if possible + tlp_addr_next = op_table_axi_addr[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]]; + tlp_len_next = op_table_len[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]]; + offset_next = op_table_offset[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]]; + strb_offset_mask_next = {AXI_STRB_WIDTH{1'b1}} << (tlp_addr_next & OFFSET_MASK); + last_cycle_offset_next = tlp_addr_next + (tlp_len_next & OFFSET_MASK); + cycle_count_next = op_table_cycle_count[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]]; + last_cycle_next = op_table_cycle_count[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]] == 0; + + if (op_table_active[op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]] && op_table_tx_start_ptr_reg != op_table_start_ptr_reg && (!m_axi_awvalid_reg || m_axi_awready)) begin + m_axi_awid_next = op_table_tx_start_ptr_reg[OP_TAG_WIDTH-1:0]; + m_axi_awaddr_next = tlp_addr_next; + m_axi_awlen_next = cycle_count_next; + m_axi_awvalid_next = 1'b1; + op_table_tx_start_en = 1'b1; + axi_state_next = AXI_STATE_TRANSFER; + end else begin + axi_state_next = AXI_STATE_IDLE; + end + end else begin + axi_state_next = AXI_STATE_TRANSFER; + end + end else begin + axi_state_next = AXI_STATE_TRANSFER; + end + end + endcase + + if (!ram_mask_valid_next && !mask_fifo_empty) begin + ram_mask_next = mask_fifo_mask[mask_fifo_rd_ptr_reg[MASK_FIFO_ADDR_WIDTH-1:0]]; + ram_mask_valid_next = 1'b1; + mask_fifo_rd_ptr_next = mask_fifo_rd_ptr_reg+1; + end + + // accept write completions + m_axi_bready_next = 1'b1; + if (m_axi_bready && m_axi_bvalid) begin + op_table_write_complete_en = 1'b1; + op_table_write_complete_ptr = m_axi_bid; + end + + // commit operations in-order + op_table_finish_en = 1'b0; + + m_axis_write_desc_status_tag_next = op_table_tag[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]]; + m_axis_write_desc_status_error_next = 0; + m_axis_write_desc_status_valid_next = 1'b0; + + if (op_table_active[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]] && op_table_write_complete[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]] && op_table_finish_ptr_reg != op_table_tx_finish_ptr_reg) begin + op_table_finish_en = 1'b1; + + if (op_table_last[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]]) begin + m_axis_write_desc_status_tag_next = op_table_tag[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]]; + m_axis_write_desc_status_error_next = 0; + m_axis_write_desc_status_valid_next = 1'b1; + end + end +end + +always @(posedge clk) begin + req_state_reg <= req_state_next; + read_state_reg <= read_state_next; + axi_state_reg <= axi_state_next; + + axi_addr_reg <= axi_addr_next; + ram_sel_reg <= ram_sel_next; + ram_addr_reg <= ram_addr_next; + op_count_reg <= op_count_next; + tr_count_reg <= tr_count_next; + tr_word_count_reg <= tr_word_count_next; + tag_reg <= tag_next; + + read_axi_addr_reg <= read_axi_addr_next; + read_ram_sel_reg <= read_ram_sel_next; + read_ram_addr_reg <= read_ram_addr_next; + read_len_reg <= read_len_next; + read_ram_mask_reg <= read_ram_mask_next; + read_ram_mask_0_reg <= read_ram_mask_0_next; + read_ram_mask_1_reg <= read_ram_mask_1_next; + ram_wrap_reg <= ram_wrap_next; + read_cycle_count_reg <= read_cycle_count_next; + read_last_cycle_reg <= read_last_cycle_next; + cycle_byte_count_reg <= cycle_byte_count_next; + start_offset_reg <= start_offset_next; + end_offset_reg <= end_offset_next; + + tlp_addr_reg <= tlp_addr_next; + tlp_len_reg <= tlp_len_next; + offset_reg <= offset_next; + strb_offset_mask_reg <= strb_offset_mask_next; + last_cycle_offset_reg <= last_cycle_offset_next; + ram_mask_reg <= ram_mask_next; + ram_mask_valid_reg <= ram_mask_valid_next; + cycle_count_reg <= cycle_count_next; + last_cycle_reg <= last_cycle_next; + + read_cmd_axi_addr_reg <= read_cmd_axi_addr_next; + read_cmd_ram_sel_reg <= read_cmd_ram_sel_next; + read_cmd_ram_addr_reg <= read_cmd_ram_addr_next; + read_cmd_len_reg <= read_cmd_len_next; + read_cmd_cycle_count_reg <= read_cmd_cycle_count_next; + read_cmd_last_cycle_reg <= read_cmd_last_cycle_next; + read_cmd_valid_reg <= read_cmd_valid_next; + + m_axi_awid_reg <= m_axi_awid_next; + m_axi_awaddr_reg <= m_axi_awaddr_next; + m_axi_awlen_reg <= m_axi_awlen_next; + m_axi_awvalid_reg <= m_axi_awvalid_next; + m_axi_bready_reg <= m_axi_bready_next; + + s_axis_write_desc_ready_reg <= s_axis_write_desc_ready_next; + + m_axis_write_desc_status_tag_reg <= m_axis_write_desc_status_tag_next; + m_axis_write_desc_status_error_reg <= m_axis_write_desc_status_error_next; + m_axis_write_desc_status_valid_reg <= m_axis_write_desc_status_valid_next; + + ram_rd_cmd_sel_reg <= ram_rd_cmd_sel_next; + ram_rd_cmd_addr_reg <= ram_rd_cmd_addr_next; + ram_rd_cmd_valid_reg <= ram_rd_cmd_valid_next; + + if (mask_fifo_we) begin + mask_fifo_mask[mask_fifo_wr_ptr_reg[MASK_FIFO_ADDR_WIDTH-1:0]] <= mask_fifo_wr_mask; + mask_fifo_wr_ptr_reg <= mask_fifo_wr_ptr_reg + 1; + end + mask_fifo_rd_ptr_reg <= mask_fifo_rd_ptr_next; + + if (op_table_start_en) begin + op_table_start_ptr_reg <= op_table_start_ptr_reg + 1; + op_table_active[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= 1'b1; + op_table_write_complete[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= 1'b0; + op_table_axi_addr[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_axi_addr; + op_table_len[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_len; + op_table_cycle_count[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_cycle_count; + op_table_offset[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_offset; + op_table_tag[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_tag; + op_table_last[op_table_start_ptr_reg[OP_TAG_WIDTH-1:0]] <= op_table_start_last; + end + + if (op_table_tx_start_en) begin + op_table_tx_start_ptr_reg <= op_table_tx_start_ptr_reg + 1; + end + + if (op_table_tx_finish_en) begin + op_table_tx_finish_ptr_reg <= op_table_tx_finish_ptr_reg + 1; + end + + if (op_table_write_complete_en) begin + op_table_write_complete[op_table_write_complete_ptr] <= 1'b1; + end + + if (op_table_finish_en) begin + op_table_finish_ptr_reg <= op_table_finish_ptr_reg + 1; + op_table_active[op_table_finish_ptr_reg[OP_TAG_WIDTH-1:0]] <= 1'b0; + end + + if (rst) begin + req_state_reg <= REQ_STATE_IDLE; + read_state_reg <= READ_STATE_IDLE; + axi_state_reg <= AXI_STATE_IDLE; + + read_cmd_valid_reg <= 1'b0; + + ram_mask_valid_reg <= 1'b0; + + m_axi_awvalid_reg <= 1'b0; + m_axi_bready_reg <= 1'b0; + + s_axis_write_desc_ready_reg <= 1'b0; + m_axis_write_desc_status_valid_reg <= 1'b0; + + ram_rd_cmd_valid_reg <= {RAM_SEG_COUNT{1'b0}}; + + mask_fifo_wr_ptr_reg <= 0; + mask_fifo_rd_ptr_reg <= 0; + + op_table_start_ptr_reg <= 0; + op_table_tx_start_ptr_reg <= 0; + op_table_tx_finish_ptr_reg <= 0; + op_table_finish_ptr_reg <= 0; + op_table_active <= 0; + end +end + +// output datapath logic +reg [AXI_DATA_WIDTH-1:0] m_axi_wdata_reg = {AXI_DATA_WIDTH{1'b0}}; +reg [AXI_STRB_WIDTH-1:0] m_axi_wstrb_reg = {AXI_STRB_WIDTH{1'b0}}; +reg m_axi_wlast_reg = 1'b0; +reg m_axi_wvalid_reg = 1'b0; + +reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_wr_ptr_reg = 0; +reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_rd_ptr_reg = 0; +reg out_fifo_half_full_reg = 1'b0; + +wire out_fifo_full = out_fifo_wr_ptr_reg == (out_fifo_rd_ptr_reg ^ {1'b1, {OUTPUT_FIFO_ADDR_WIDTH{1'b0}}}); +wire out_fifo_empty = out_fifo_wr_ptr_reg == out_fifo_rd_ptr_reg; + +(* ram_style = "distributed" *) +reg [AXI_DATA_WIDTH-1:0] out_fifo_wdata[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; +(* ram_style = "distributed" *) +reg [AXI_STRB_WIDTH-1:0] out_fifo_wstrb[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; +(* ram_style = "distributed" *) +reg out_fifo_wlast[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + +assign m_axi_wready_int = !out_fifo_half_full_reg; + +assign m_axi_wdata = m_axi_wdata_reg; +assign m_axi_wstrb = m_axi_wstrb_reg; +assign m_axi_wvalid = m_axi_wvalid_reg; +assign m_axi_wlast = m_axi_wlast_reg; + +always @(posedge clk) begin + m_axi_wvalid_reg <= m_axi_wvalid_reg && !m_axi_wready; + + out_fifo_half_full_reg <= $unsigned(out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2**(OUTPUT_FIFO_ADDR_WIDTH-1); + + if (!out_fifo_full && m_axi_wvalid_int) begin + out_fifo_wdata[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axi_wdata_int; + out_fifo_wstrb[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axi_wstrb_int; + out_fifo_wlast[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axi_wlast_int; + out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1; + end + + if (!out_fifo_empty && (!m_axi_wvalid_reg || m_axi_wready)) begin + m_axi_wdata_reg <= out_fifo_wdata[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + m_axi_wstrb_reg <= out_fifo_wstrb[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + m_axi_wlast_reg <= out_fifo_wlast[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + m_axi_wvalid_reg <= 1'b1; + out_fifo_rd_ptr_reg <= out_fifo_rd_ptr_reg + 1; + end + + if (rst) begin + out_fifo_wr_ptr_reg <= 0; + out_fifo_rd_ptr_reg <= 0; + m_axi_wvalid_reg <= 1'b0; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_desc_mux.v b/fpga/lib/pcie/rtl/dma_if_desc_mux.v index ebf456073..714d2dfe9 100644 --- a/fpga/lib/pcie/rtl/dma_if_desc_mux.v +++ b/fpga/lib/pcie/rtl/dma_if_desc_mux.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * DMA interface descriptor mux @@ -299,3 +301,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_mux.v b/fpga/lib/pcie/rtl/dma_if_mux.v index dca2f45cc..3df283628 100644 --- a/fpga/lib/pcie/rtl/dma_if_mux.v +++ b/fpga/lib/pcie/rtl/dma_if_mux.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * DMA interface mux @@ -334,3 +336,5 @@ dma_if_mux_wr_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_mux_rd.v b/fpga/lib/pcie/rtl/dma_if_mux_rd.v index ccfede880..5882e9c11 100644 --- a/fpga/lib/pcie/rtl/dma_if_mux_rd.v +++ b/fpga/lib/pcie/rtl/dma_if_mux_rd.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * DMA interface mux (read) @@ -216,3 +218,5 @@ dma_ram_demux_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_mux_wr.v b/fpga/lib/pcie/rtl/dma_if_mux_wr.v index b43995776..d8259c0a6 100644 --- a/fpga/lib/pcie/rtl/dma_if_mux_wr.v +++ b/fpga/lib/pcie/rtl/dma_if_mux_wr.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * DMA interface mux (write) @@ -215,3 +217,5 @@ dma_ram_demux_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_pcie.v b/fpga/lib/pcie/rtl/dma_if_pcie.v index 11a9e51ee..414ae663b 100644 --- a/fpga/lib/pcie/rtl/dma_if_pcie.v +++ b/fpga/lib/pcie/rtl/dma_if_pcie.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe DMA interface @@ -476,3 +478,5 @@ dma_if_pcie_wr_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_pcie_rd.v b/fpga/lib/pcie/rtl/dma_if_pcie_rd.v index c4e647c09..aaf1e00ea 100644 --- a/fpga/lib/pcie/rtl/dma_if_pcie_rd.v +++ b/fpga/lib/pcie/rtl/dma_if_pcie_rd.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe DMA read interface @@ -1606,3 +1608,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_pcie_us.v b/fpga/lib/pcie/rtl/dma_if_pcie_us.v index 945e8385c..f7b6c2cd7 100644 --- a/fpga/lib/pcie/rtl/dma_if_pcie_us.v +++ b/fpga/lib/pcie/rtl/dma_if_pcie_us.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe DMA interface @@ -406,3 +408,5 @@ dma_if_pcie_us_wr_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_pcie_us_rd.v b/fpga/lib/pcie/rtl/dma_if_pcie_us_rd.v index 333996c33..8e3f50ee3 100644 --- a/fpga/lib/pcie/rtl/dma_if_pcie_us_rd.v +++ b/fpga/lib/pcie/rtl/dma_if_pcie_us_rd.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe DMA read interface @@ -1827,3 +1829,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_pcie_us_wr.v b/fpga/lib/pcie/rtl/dma_if_pcie_us_wr.v index 379fcfc44..813943cf7 100644 --- a/fpga/lib/pcie/rtl/dma_if_pcie_us_wr.v +++ b/fpga/lib/pcie/rtl/dma_if_pcie_us_wr.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe DMA write interface @@ -1390,3 +1392,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_if_pcie_wr.v b/fpga/lib/pcie/rtl/dma_if_pcie_wr.v index 826ea9f0b..0846ff7a0 100644 --- a/fpga/lib/pcie/rtl/dma_if_pcie_wr.v +++ b/fpga/lib/pcie/rtl/dma_if_pcie_wr.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe DMA write interface @@ -1125,3 +1127,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_psdpram.v b/fpga/lib/pcie/rtl/dma_psdpram.v index 39a6216a4..c66cbc513 100644 --- a/fpga/lib/pcie/rtl/dma_psdpram.v +++ b/fpga/lib/pcie/rtl/dma_psdpram.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * DMA parallel simple dual port RAM @@ -158,3 +160,5 @@ generate endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_psdpram_async.v b/fpga/lib/pcie/rtl/dma_psdpram_async.v index 51436007d..61895304b 100644 --- a/fpga/lib/pcie/rtl/dma_psdpram_async.v +++ b/fpga/lib/pcie/rtl/dma_psdpram_async.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * DMA parallel simple dual port RAM (asynchronous) @@ -159,3 +161,5 @@ generate endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_ram_demux.v b/fpga/lib/pcie/rtl/dma_ram_demux.v index 53d3c9de6..9aabccdae 100644 --- a/fpga/lib/pcie/rtl/dma_ram_demux.v +++ b/fpga/lib/pcie/rtl/dma_ram_demux.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * DMA RAM demux @@ -160,3 +162,5 @@ dma_ram_demux_rd_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_ram_demux_rd.v b/fpga/lib/pcie/rtl/dma_ram_demux_rd.v index 021645341..b97472744 100644 --- a/fpga/lib/pcie/rtl/dma_ram_demux_rd.v +++ b/fpga/lib/pcie/rtl/dma_ram_demux_rd.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * DMA RAM demux (read) @@ -329,3 +331,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/dma_ram_demux_wr.v b/fpga/lib/pcie/rtl/dma_ram_demux_wr.v index 232230808..a0c65f67e 100644 --- a/fpga/lib/pcie/rtl/dma_ram_demux_wr.v +++ b/fpga/lib/pcie/rtl/dma_ram_demux_wr.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * DMA RAM demux (write) @@ -313,3 +315,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_axi_dma_desc_mux.v b/fpga/lib/pcie/rtl/pcie_axi_dma_desc_mux.v index c68be35bb..4957afce8 100644 --- a/fpga/lib/pcie/rtl/pcie_axi_dma_desc_mux.v +++ b/fpga/lib/pcie/rtl/pcie_axi_dma_desc_mux.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe AXI DMA descriptor mux @@ -268,3 +270,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_axi_master.v b/fpga/lib/pcie/rtl/pcie_axi_master.v index cc5b08631..acdc8e3c8 100644 --- a/fpga/lib/pcie/rtl/pcie_axi_master.v +++ b/fpga/lib/pcie/rtl/pcie_axi_master.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe AXI Master @@ -352,3 +354,5 @@ status_error_uncor_pm_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_axi_master_rd.v b/fpga/lib/pcie/rtl/pcie_axi_master_rd.v index dd4560ffc..bf5df02d7 100644 --- a/fpga/lib/pcie/rtl/pcie_axi_master_rd.v +++ b/fpga/lib/pcie/rtl/pcie_axi_master_rd.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe AXI Master (read) @@ -978,3 +980,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_axi_master_wr.v b/fpga/lib/pcie/rtl/pcie_axi_master_wr.v index 412341151..b2d69f134 100644 --- a/fpga/lib/pcie/rtl/pcie_axi_master_wr.v +++ b/fpga/lib/pcie/rtl/pcie_axi_master_wr.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe AXI Master (write) @@ -538,3 +540,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_axil_master.v b/fpga/lib/pcie/rtl/pcie_axil_master.v index ffdca7b97..656ba2a09 100644 --- a/fpga/lib/pcie/rtl/pcie_axil_master.v +++ b/fpga/lib/pcie/rtl/pcie_axil_master.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe AXI Lite Master @@ -1026,3 +1028,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_axil_master_minimal.v b/fpga/lib/pcie/rtl/pcie_axil_master_minimal.v index 126ccc9f9..27a2b153b 100644 --- a/fpga/lib/pcie/rtl/pcie_axil_master_minimal.v +++ b/fpga/lib/pcie/rtl/pcie_axil_master_minimal.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe AXI Lite Master (minimal version, supports only aligned, 1 DW operations) @@ -696,3 +698,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_tlp_demux.v b/fpga/lib/pcie/rtl/pcie_tlp_demux.v index 0d66cf5b4..341287d88 100644 --- a/fpga/lib/pcie/rtl/pcie_tlp_demux.v +++ b/fpga/lib/pcie/rtl/pcie_tlp_demux.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe TLP demultiplexer @@ -322,3 +324,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_tlp_demux_bar.v b/fpga/lib/pcie/rtl/pcie_tlp_demux_bar.v index 9084c2037..5830eb9b4 100644 --- a/fpga/lib/pcie/rtl/pcie_tlp_demux_bar.v +++ b/fpga/lib/pcie/rtl/pcie_tlp_demux_bar.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe TLP demultiplexer (BAR ID) @@ -199,3 +201,5 @@ pcie_tlp_demux_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_tlp_mux.v b/fpga/lib/pcie/rtl/pcie_tlp_mux.v index c706eaeab..4f6bf6a87 100644 --- a/fpga/lib/pcie/rtl/pcie_tlp_mux.v +++ b/fpga/lib/pcie/rtl/pcie_tlp_mux.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * PCIe TLP multiplexer @@ -278,3 +280,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_axi_dma.v b/fpga/lib/pcie/rtl/pcie_us_axi_dma.v index 7d171edfd..144724525 100644 --- a/fpga/lib/pcie/rtl/pcie_us_axi_dma.v +++ b/fpga/lib/pcie/rtl/pcie_us_axi_dma.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe AXI DMA @@ -440,3 +442,5 @@ pcie_us_axi_dma_wr_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_axi_dma_rd.v b/fpga/lib/pcie/rtl/pcie_us_axi_dma_rd.v index 297bbc3ad..d293bc994 100644 --- a/fpga/lib/pcie/rtl/pcie_us_axi_dma_rd.v +++ b/fpga/lib/pcie/rtl/pcie_us_axi_dma_rd.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe AXI DMA Read @@ -1846,3 +1848,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_axi_dma_wr.v b/fpga/lib/pcie/rtl/pcie_us_axi_dma_wr.v index 9dc2d7145..83eb7f3e2 100644 --- a/fpga/lib/pcie/rtl/pcie_us_axi_dma_wr.v +++ b/fpga/lib/pcie/rtl/pcie_us_axi_dma_wr.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe AXI DMA Write @@ -1270,3 +1272,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_axi_master.v b/fpga/lib/pcie/rtl/pcie_us_axi_master.v index 6f11d93ea..b159f8d17 100644 --- a/fpga/lib/pcie/rtl/pcie_us_axi_master.v +++ b/fpga/lib/pcie/rtl/pcie_us_axi_master.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe AXI Master @@ -320,3 +322,5 @@ status_error_uncor_pm_inst ( ); endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_axi_master_rd.v b/fpga/lib/pcie/rtl/pcie_us_axi_master_rd.v index 4f13db5d7..5d722452d 100644 --- a/fpga/lib/pcie/rtl/pcie_us_axi_master_rd.v +++ b/fpga/lib/pcie/rtl/pcie_us_axi_master_rd.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe AXI Master (read) @@ -1186,3 +1188,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_axi_master_wr.v b/fpga/lib/pcie/rtl/pcie_us_axi_master_wr.v index 2fbae9f02..a79423ff4 100644 --- a/fpga/lib/pcie/rtl/pcie_us_axi_master_wr.v +++ b/fpga/lib/pcie/rtl/pcie_us_axi_master_wr.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe AXI Master (write) @@ -674,3 +676,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_axil_master.v b/fpga/lib/pcie/rtl/pcie_us_axil_master.v index 92000c282..f13f26933 100644 --- a/fpga/lib/pcie/rtl/pcie_us_axil_master.v +++ b/fpga/lib/pcie/rtl/pcie_us_axil_master.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe AXI Lite Master @@ -927,3 +929,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_axis_cq_demux.v b/fpga/lib/pcie/rtl/pcie_us_axis_cq_demux.v index 07a782cd3..6b7ce7ee5 100644 --- a/fpga/lib/pcie/rtl/pcie_us_axis_cq_demux.v +++ b/fpga/lib/pcie/rtl/pcie_us_axis_cq_demux.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe CQ demultiplexer @@ -313,3 +315,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_axis_rc_demux.v b/fpga/lib/pcie/rtl/pcie_us_axis_rc_demux.v index 9dce06924..688594739 100644 --- a/fpga/lib/pcie/rtl/pcie_us_axis_rc_demux.v +++ b/fpga/lib/pcie/rtl/pcie_us_axis_rc_demux.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe RC demultiplexer @@ -261,3 +263,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_cfg.v b/fpga/lib/pcie/rtl/pcie_us_cfg.v index 9640a6825..083cb32c7 100644 --- a/fpga/lib/pcie/rtl/pcie_us_cfg.v +++ b/fpga/lib/pcie/rtl/pcie_us_cfg.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe configuration shim @@ -169,3 +171,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_if.v b/fpga/lib/pcie/rtl/pcie_us_if.v index 8bfb0074c..4ab17c656 100644 --- a/fpga/lib/pcie/rtl/pcie_us_if.v +++ b/fpga/lib/pcie/rtl/pcie_us_if.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Xilinx UltraScale PCIe interface adapter @@ -552,3 +554,5 @@ end endgenerate endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_if_cc.v b/fpga/lib/pcie/rtl/pcie_us_if_cc.v index ea798cda4..612003c53 100644 --- a/fpga/lib/pcie/rtl/pcie_us_if_cc.v +++ b/fpga/lib/pcie/rtl/pcie_us_if_cc.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Xilinx UltraScale PCIe interface adapter (Completer Completion) @@ -447,3 +449,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_if_cq.v b/fpga/lib/pcie/rtl/pcie_us_if_cq.v index 5898bf8e2..01d17d2b2 100644 --- a/fpga/lib/pcie/rtl/pcie_us_if_cq.v +++ b/fpga/lib/pcie/rtl/pcie_us_if_cq.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Xilinx UltraScale PCIe interface adapter (Completer reQuest) @@ -399,3 +401,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_if_rc.v b/fpga/lib/pcie/rtl/pcie_us_if_rc.v index 12e07b542..1c7bd5065 100644 --- a/fpga/lib/pcie/rtl/pcie_us_if_rc.v +++ b/fpga/lib/pcie/rtl/pcie_us_if_rc.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Xilinx UltraScale PCIe interface adapter (Requester Completion) @@ -357,3 +359,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_if_rq.v b/fpga/lib/pcie/rtl/pcie_us_if_rq.v index a92184272..986b44422 100644 --- a/fpga/lib/pcie/rtl/pcie_us_if_rq.v +++ b/fpga/lib/pcie/rtl/pcie_us_if_rq.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Xilinx UltraScale PCIe interface adapter (Requester reQuest) @@ -614,3 +616,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pcie_us_msi.v b/fpga/lib/pcie/rtl/pcie_us_msi.v index dd7ce88c9..c64259031 100644 --- a/fpga/lib/pcie/rtl/pcie_us_msi.v +++ b/fpga/lib/pcie/rtl/pcie_us_msi.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Ultrascale PCIe MSI shim @@ -155,3 +157,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/priority_encoder.v b/fpga/lib/pcie/rtl/priority_encoder.v index dd59fa455..cf82512ba 100644 --- a/fpga/lib/pcie/rtl/priority_encoder.v +++ b/fpga/lib/pcie/rtl/priority_encoder.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Priority encoder module @@ -86,3 +88,5 @@ assign output_encoded = stage_enc[LEVELS-1]; assign output_unencoded = 1 << output_encoded; endmodule + +`resetall diff --git a/fpga/lib/pcie/rtl/pulse_merge.v b/fpga/lib/pcie/rtl/pulse_merge.v index 0c79092f0..aafe38a8e 100644 --- a/fpga/lib/pcie/rtl/pulse_merge.v +++ b/fpga/lib/pcie/rtl/pulse_merge.v @@ -24,7 +24,9 @@ THE SOFTWARE. // Language: Verilog 2001 +`resetall `timescale 1ns / 1ps +`default_nettype none /* * Pulse merge module @@ -75,3 +77,5 @@ always @(posedge clk) begin end endmodule + +`resetall diff --git a/fpga/lib/pcie/tb/dma_if_axi/Makefile b/fpga/lib/pcie/tb/dma_if_axi/Makefile new file mode 100644 index 000000000..470e63296 --- /dev/null +++ b/fpga/lib/pcie/tb/dma_if_axi/Makefile @@ -0,0 +1,112 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = dma_if_axi +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/$(DUT)_rd.v +VERILOG_SOURCES += ../../rtl/$(DUT)_wr.v + +# module parameters +export PARAM_AXI_DATA_WIDTH ?= 64 +export PARAM_AXI_ADDR_WIDTH ?= 16 +export PARAM_AXI_STRB_WIDTH ?= $(shell expr $(PARAM_AXI_DATA_WIDTH) / 8 ) +export PARAM_AXI_ID_WIDTH ?= 8 +export PARAM_RAM_SEG_COUNT ?= 2 +export PARAM_RAM_SEG_DATA_WIDTH ?= $(shell expr $(PARAM_AXI_DATA_WIDTH) \* 2 / $(PARAM_RAM_SEG_COUNT) ) +export PARAM_RAM_SEG_ADDR_WIDTH ?= 12 +export PARAM_RAM_SEG_BE_WIDTH ?= $(shell expr $(PARAM_RAM_SEG_DATA_WIDTH) / 8 ) +export PARAM_RAM_SEL_WIDTH ?= 2 +export PARAM_RAM_ADDR_WIDTH ?= $(shell python -c "print($(PARAM_RAM_SEG_ADDR_WIDTH) + ($(PARAM_RAM_SEG_COUNT)*$(PARAM_RAM_SEG_BE_WIDTH)-1).bit_length())") +export PARAM_LEN_WIDTH ?= 16 +export PARAM_TAG_WIDTH ?= 8 +export PARAM_READ_OP_TABLE_SIZE ?= $(shell python -c "print(2**$(PARAM_AXI_ID_WIDTH))") +export PARAM_WRITE_OP_TABLE_SIZE ?= $(shell python -c "print(2**$(PARAM_AXI_ID_WIDTH))") +export PARAM_USE_AXI_ID ?= 1 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXI_DATA_WIDTH=$(PARAM_AXI_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXI_ADDR_WIDTH=$(PARAM_AXI_ADDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXI_STRB_WIDTH=$(PARAM_AXI_STRB_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXI_ID_WIDTH=$(PARAM_AXI_ID_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_COUNT=$(PARAM_RAM_SEG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_DATA_WIDTH=$(PARAM_RAM_SEG_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_ADDR_WIDTH=$(PARAM_RAM_SEG_ADDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_BE_WIDTH=$(PARAM_RAM_SEG_BE_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEL_WIDTH=$(PARAM_RAM_SEL_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_ADDR_WIDTH=$(PARAM_RAM_ADDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).LEN_WIDTH=$(PARAM_LEN_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).TAG_WIDTH=$(PARAM_TAG_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).READ_OP_TABLE_SIZE=$(PARAM_READ_OP_TABLE_SIZE) + COMPILE_ARGS += -P $(TOPLEVEL).WRITE_OP_TABLE_SIZE=$(PARAM_WRITE_OP_TABLE_SIZE) + COMPILE_ARGS += -P $(TOPLEVEL).USE_AXI_ID=$(PARAM_USE_AXI_ID) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXI_DATA_WIDTH=$(PARAM_AXI_DATA_WIDTH) + COMPILE_ARGS += -GAXI_ADDR_WIDTH=$(PARAM_AXI_ADDR_WIDTH) + COMPILE_ARGS += -GAXI_STRB_WIDTH=$(PARAM_AXI_STRB_WIDTH) + COMPILE_ARGS += -GAXI_ID_WIDTH=$(PARAM_AXI_ID_WIDTH) + COMPILE_ARGS += -GRAM_SEG_COUNT=$(PARAM_RAM_SEG_COUNT) + COMPILE_ARGS += -GRAM_SEG_DATA_WIDTH=$(PARAM_RAM_SEG_DATA_WIDTH) + COMPILE_ARGS += -GRAM_SEG_ADDR_WIDTH=$(PARAM_RAM_SEG_ADDR_WIDTH) + COMPILE_ARGS += -GRAM_SEG_BE_WIDTH=$(PARAM_RAM_SEG_BE_WIDTH) + COMPILE_ARGS += -GRAM_SEL_WIDTH=$(PARAM_RAM_SEL_WIDTH) + COMPILE_ARGS += -GRAM_ADDR_WIDTH=$(PARAM_RAM_ADDR_WIDTH) + COMPILE_ARGS += -GLEN_WIDTH=$(PARAM_LEN_WIDTH) + COMPILE_ARGS += -GTAG_WIDTH=$(PARAM_TAG_WIDTH) + COMPILE_ARGS += -GREAD_OP_TABLE_SIZE=$(PARAM_READ_OP_TABLE_SIZE) + COMPILE_ARGS += -GWRITE_OP_TABLE_SIZE=$(PARAM_WRITE_OP_TABLE_SIZE) + COMPILE_ARGS += -GUSE_AXI_ID=$(PARAM_USE_AXI_ID) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/tb/dma_if_axi/dma_psdp_ram.py b/fpga/lib/pcie/tb/dma_if_axi/dma_psdp_ram.py new file mode 120000 index 000000000..6613351ee --- /dev/null +++ b/fpga/lib/pcie/tb/dma_if_axi/dma_psdp_ram.py @@ -0,0 +1 @@ +../dma_psdp_ram.py \ No newline at end of file diff --git a/fpga/lib/pcie/tb/dma_if_axi/test_dma_if_axi.py b/fpga/lib/pcie/tb/dma_if_axi/test_dma_if_axi.py new file mode 100644 index 000000000..dbe335112 --- /dev/null +++ b/fpga/lib/pcie/tb/dma_if_axi/test_dma_if_axi.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2021 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os +import sys + +import cocotb_test.simulator +import pytest + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.axi import AxiBus, AxiRam +from cocotbext.axi.stream import define_stream + +try: + from dma_psdp_ram import PsdpRam, PsdpRamBus +except ImportError: + # attempt import from current directory + sys.path.insert(0, os.path.join(os.path.dirname(__file__))) + try: + from dma_psdp_ram import PsdpRam, PsdpRamBus + finally: + del sys.path[0] + +DescBus, DescTransaction, DescSource, DescSink, DescMonitor = define_stream("Desc", + signals=["axi_addr", "ram_addr", "ram_sel", "len", "tag", "valid", "ready"] +) + +DescStatusBus, DescStatusTransaction, DescStatusSource, DescStatusSink, DescStatusMonitor = define_stream("DescStatus", + signals=["tag", "error", "valid"] +) + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 10, units="ns").start()) + + # AXI RAM + self.axi_ram = AxiRam(AxiBus.from_prefix(dut, "m_axi"), dut.clk, dut.rst, size=2**16) + + # DMA RAM + self.dma_ram = PsdpRam(PsdpRamBus.from_prefix(dut, "ram"), dut.clk, dut.rst, size=2**16) + + # Control + self.read_desc_source = DescSource(DescBus.from_prefix(dut, "s_axis_read_desc"), dut.clk, dut.rst) + self.read_desc_status_sink = DescStatusSink(DescStatusBus.from_prefix(dut, "m_axis_read_desc_status"), dut.clk, dut.rst) + + self.write_desc_source = DescSource(DescBus.from_prefix(dut, "s_axis_write_desc"), dut.clk, dut.rst) + self.write_desc_status_sink = DescStatusSink(DescStatusBus.from_prefix(dut, "m_axis_write_desc_status"), dut.clk, dut.rst) + + dut.read_enable.setimmediatevalue(0) + dut.write_enable.setimmediatevalue(0) + + def set_idle_generator(self, generator=None): + if generator: + self.axi_ram.write_if.b_channel.set_pause_generator(generator()) + self.axi_ram.read_if.r_channel.set_pause_generator(generator()) + + def set_backpressure_generator(self, generator=None): + if generator: + self.axi_ram.write_if.aw_channel.set_pause_generator(generator()) + self.axi_ram.write_if.w_channel.set_pause_generator(generator()) + self.axi_ram.read_if.ar_channel.set_pause_generator(generator()) + self.dma_ram.write_if.set_pause_generator(generator()) + self.dma_ram.read_if.set_pause_generator(generator()) + + async def cycle_reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test_write(dut, idle_inserter=None, backpressure_inserter=None): + + tb = TB(dut) + + axi_byte_lanes = tb.axi_ram.write_if.byte_lanes + ram_byte_lanes = tb.dma_ram.write_if.byte_lanes + tag_count = 2**len(tb.write_desc_source.bus.tag) + + cur_tag = 1 + + tb.set_idle_generator(idle_inserter) + tb.set_backpressure_generator(backpressure_inserter) + + await tb.cycle_reset() + + tb.dut.write_enable <= 1 + + for length in list(range(1, ram_byte_lanes+3))+list(range(128-4, 128+4))+[1024]: + # for axi_offset in axi_offsets: + for axi_offset in list(range(axi_byte_lanes+1))+list(range(4096-axi_byte_lanes, 4096)): + for ram_offset in range(1): + tb.log.info("length %d, axi_offset %d, ram_offset %d", length, axi_offset, ram_offset) + axi_addr = axi_offset+0x1000 + ram_addr = ram_offset+0x1000 + test_data = bytearray([x % 256 for x in range(length)]) + + tb.dma_ram.write(ram_addr & 0xffff80, b'\x55'*(len(test_data)+256)) + tb.axi_ram.write(axi_addr-128, b'\xaa'*(len(test_data)+256)) + tb.dma_ram.write(ram_addr, test_data) + + tb.log.debug("%s", tb.dma_ram.hexdump_str((ram_addr & ~0xf)-16, (((ram_addr & 0xf)+length-1) & ~0xf)+48, prefix="RAM ")) + + desc = DescTransaction(axi_addr=axi_addr, ram_addr=ram_addr, ram_sel=0, len=len(test_data), tag=cur_tag) + await tb.write_desc_source.send(desc) + + status = await tb.write_desc_status_sink.recv() + + tb.log.info("status: %s", status) + + assert int(status.tag) == cur_tag + assert int(status.error) == 0 + + tb.log.debug("%s", tb.axi_ram.hexdump_str((axi_addr & ~0xf)-16, (((axi_addr & 0xf)+length-1) & ~0xf)+48, prefix="AXI ")) + + assert tb.axi_ram.read(axi_addr-1, len(test_data)+2) == b'\xaa'+test_data+b'\xaa' + + cur_tag = (cur_tag + 1) % tag_count + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +async def run_test_read(dut, idle_inserter=None, backpressure_inserter=None): + + tb = TB(dut) + + axi_byte_lanes = tb.axi_ram.write_if.byte_lanes + ram_byte_lanes = tb.dma_ram.write_if.byte_lanes + tag_count = 2**len(tb.read_desc_source.bus.tag) + + cur_tag = 1 + + tb.set_idle_generator(idle_inserter) + tb.set_backpressure_generator(backpressure_inserter) + + await tb.cycle_reset() + + tb.dut.read_enable <= 1 + + for length in list(range(1, ram_byte_lanes+3))+list(range(128-4, 128+4))+[1024]: + for axi_offset in list(range(axi_byte_lanes+1))+list(range(4096-axi_byte_lanes, 4096)): + for ram_offset in range(1): + tb.log.info("length %d, axi_offset %d, ram_offset %d", length, axi_offset, ram_offset) + axi_addr = axi_offset+0x1000 + ram_addr = ram_offset+0x1000 + test_data = bytearray([x % 256 for x in range(length)]) + + tb.axi_ram.write(axi_addr, test_data) + + tb.log.debug("%s", tb.axi_ram.hexdump_str((axi_addr & ~0xf)-16, (((axi_addr & 0xf)+length-1) & ~0xf)+48, prefix="AXI ")) + + tb.dma_ram.write(ram_addr-256, b'\xaa'*(len(test_data)+512)) + + desc = DescTransaction(axi_addr=axi_addr, ram_addr=ram_addr, ram_sel=0, len=len(test_data), tag=cur_tag) + await tb.read_desc_source.send(desc) + + status = await tb.read_desc_status_sink.recv() + + tb.log.info("status: %s", status) + + assert int(status.tag) == cur_tag + assert int(status.error) == 0 + + tb.log.debug("%s", tb.dma_ram.hexdump_str((ram_addr & ~0xf)-16, (((ram_addr & 0xf)+length-1) & ~0xf)+48, prefix="RAM ")) + + assert tb.dma_ram.read(ram_addr-8, len(test_data)+16) == b'\xaa'*8+test_data+b'\xaa'*8 + + cur_tag = (cur_tag + 1) % tag_count + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def cycle_pause(): + return itertools.cycle([1, 1, 1, 0]) + + +if cocotb.SIM_NAME: + + for test in [run_test_write, run_test_read]: + + factory = TestFactory(test) + factory.add_option("idle_inserter", [None, cycle_pause]) + factory.add_option("backpressure_inserter", [None, cycle_pause]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) + + +@pytest.mark.parametrize("axi_data_width", [64, 128]) +def test_dma_if_axi(request, axi_data_width): + dut = "dma_if_axi" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + os.path.join(rtl_dir, f"{dut}_rd.v"), + os.path.join(rtl_dir, f"{dut}_wr.v"), + ] + + parameters = {} + + # segmented interface parameters + ram_seg_count = 2 + ram_seg_data_width = axi_data_width*2 // ram_seg_count + ram_seg_addr_width = 12 + ram_seg_be_width = ram_seg_data_width // 8 + ram_sel_width = 2 + ram_addr_width = ram_seg_addr_width + (ram_seg_count*ram_seg_be_width-1).bit_length() + + parameters['AXI_DATA_WIDTH'] = axi_data_width + parameters['AXI_ADDR_WIDTH'] = 16 + parameters['AXI_STRB_WIDTH'] = parameters['AXI_DATA_WIDTH'] // 8 + parameters['AXI_ID_WIDTH'] = 8 + parameters['RAM_SEG_COUNT'] = ram_seg_count + parameters['RAM_SEG_DATA_WIDTH'] = ram_seg_data_width + parameters['RAM_SEG_ADDR_WIDTH'] = ram_seg_addr_width + parameters['RAM_SEG_BE_WIDTH'] = ram_seg_be_width + parameters['RAM_SEL_WIDTH'] = ram_sel_width + parameters['RAM_ADDR_WIDTH'] = ram_addr_width + parameters['LEN_WIDTH'] = 16 + parameters['TAG_WIDTH'] = 8 + parameters['READ_OP_TABLE_SIZE'] = 2**parameters['AXI_ID_WIDTH'] + parameters['WRITE_OP_TABLE_SIZE'] = 2**parameters['AXI_ID_WIDTH'] + parameters['USE_AXI_ID'] = 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/fpga/lib/pcie/tb/dma_if_axi_rd/Makefile b/fpga/lib/pcie/tb/dma_if_axi_rd/Makefile new file mode 100644 index 000000000..b0e6e6ad9 --- /dev/null +++ b/fpga/lib/pcie/tb/dma_if_axi_rd/Makefile @@ -0,0 +1,104 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = dma_if_axi_rd +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v + +# module parameters +export PARAM_AXI_DATA_WIDTH ?= 64 +export PARAM_AXI_ADDR_WIDTH ?= 16 +export PARAM_AXI_STRB_WIDTH ?= $(shell expr $(PARAM_AXI_DATA_WIDTH) / 8 ) +export PARAM_AXI_ID_WIDTH ?= 8 +export PARAM_RAM_SEG_COUNT ?= 2 +export PARAM_RAM_SEG_DATA_WIDTH ?= $(shell expr $(PARAM_AXI_DATA_WIDTH) \* 2 / $(PARAM_RAM_SEG_COUNT) ) +export PARAM_RAM_SEG_ADDR_WIDTH ?= 12 +export PARAM_RAM_SEG_BE_WIDTH ?= $(shell expr $(PARAM_RAM_SEG_DATA_WIDTH) / 8 ) +export PARAM_RAM_SEL_WIDTH ?= 2 +export PARAM_RAM_ADDR_WIDTH ?= $(shell python -c "print($(PARAM_RAM_SEG_ADDR_WIDTH) + ($(PARAM_RAM_SEG_COUNT)*$(PARAM_RAM_SEG_BE_WIDTH)-1).bit_length())") +export PARAM_LEN_WIDTH ?= 16 +export PARAM_TAG_WIDTH ?= 8 +export PARAM_OP_TABLE_SIZE ?= $(shell python -c "print(2**$(PARAM_AXI_ID_WIDTH))") + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXI_DATA_WIDTH=$(PARAM_AXI_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXI_ADDR_WIDTH=$(PARAM_AXI_ADDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXI_STRB_WIDTH=$(PARAM_AXI_STRB_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXI_ID_WIDTH=$(PARAM_AXI_ID_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_COUNT=$(PARAM_RAM_SEG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_DATA_WIDTH=$(PARAM_RAM_SEG_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_ADDR_WIDTH=$(PARAM_RAM_SEG_ADDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_BE_WIDTH=$(PARAM_RAM_SEG_BE_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEL_WIDTH=$(PARAM_RAM_SEL_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_ADDR_WIDTH=$(PARAM_RAM_ADDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).LEN_WIDTH=$(PARAM_LEN_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).TAG_WIDTH=$(PARAM_TAG_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).OP_TABLE_SIZE=$(PARAM_OP_TABLE_SIZE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXI_DATA_WIDTH=$(PARAM_AXI_DATA_WIDTH) + COMPILE_ARGS += -GAXI_ADDR_WIDTH=$(PARAM_AXI_ADDR_WIDTH) + COMPILE_ARGS += -GAXI_STRB_WIDTH=$(PARAM_AXI_STRB_WIDTH) + COMPILE_ARGS += -GAXI_ID_WIDTH=$(PARAM_AXI_ID_WIDTH) + COMPILE_ARGS += -GRAM_SEG_COUNT=$(PARAM_RAM_SEG_COUNT) + COMPILE_ARGS += -GRAM_SEG_DATA_WIDTH=$(PARAM_RAM_SEG_DATA_WIDTH) + COMPILE_ARGS += -GRAM_SEG_ADDR_WIDTH=$(PARAM_RAM_SEG_ADDR_WIDTH) + COMPILE_ARGS += -GRAM_SEG_BE_WIDTH=$(PARAM_RAM_SEG_BE_WIDTH) + COMPILE_ARGS += -GRAM_SEL_WIDTH=$(PARAM_RAM_SEL_WIDTH) + COMPILE_ARGS += -GRAM_ADDR_WIDTH=$(PARAM_RAM_ADDR_WIDTH) + COMPILE_ARGS += -GLEN_WIDTH=$(PARAM_LEN_WIDTH) + COMPILE_ARGS += -GTAG_WIDTH=$(PARAM_TAG_WIDTH) + COMPILE_ARGS += -GOP_TABLE_SIZE=$(PARAM_OP_TABLE_SIZE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/tb/dma_if_axi_rd/dma_psdp_ram.py b/fpga/lib/pcie/tb/dma_if_axi_rd/dma_psdp_ram.py new file mode 120000 index 000000000..6613351ee --- /dev/null +++ b/fpga/lib/pcie/tb/dma_if_axi_rd/dma_psdp_ram.py @@ -0,0 +1 @@ +../dma_psdp_ram.py \ No newline at end of file diff --git a/fpga/lib/pcie/tb/dma_if_axi_rd/test_dma_if_axi_rd.py b/fpga/lib/pcie/tb/dma_if_axi_rd/test_dma_if_axi_rd.py new file mode 100644 index 000000000..4499b2350 --- /dev/null +++ b/fpga/lib/pcie/tb/dma_if_axi_rd/test_dma_if_axi_rd.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2021 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os +import sys + +import cocotb_test.simulator +import pytest + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.axi import AxiReadBus, AxiRamRead +from cocotbext.axi.stream import define_stream + +try: + from dma_psdp_ram import PsdpRamWrite, PsdpRamWriteBus +except ImportError: + # attempt import from current directory + sys.path.insert(0, os.path.join(os.path.dirname(__file__))) + try: + from dma_psdp_ram import PsdpRamWrite, PsdpRamWriteBus + finally: + del sys.path[0] + +DescBus, DescTransaction, DescSource, DescSink, DescMonitor = define_stream("Desc", + signals=["axi_addr", "ram_addr", "ram_sel", "len", "tag", "valid", "ready"] +) + +DescStatusBus, DescStatusTransaction, DescStatusSource, DescStatusSink, DescStatusMonitor = define_stream("DescStatus", + signals=["tag", "error", "valid"] +) + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 10, units="ns").start()) + + # AXI RAM + self.axi_ram = AxiRamRead(AxiReadBus.from_prefix(dut, "m_axi"), dut.clk, dut.rst, size=2**16) + + # DMA RAM + self.dma_ram = PsdpRamWrite(PsdpRamWriteBus.from_prefix(dut, "ram"), dut.clk, dut.rst, size=2**16) + + # Control + self.read_desc_source = DescSource(DescBus.from_prefix(dut, "s_axis_read_desc"), dut.clk, dut.rst) + self.read_desc_status_sink = DescStatusSink(DescStatusBus.from_prefix(dut, "m_axis_read_desc_status"), dut.clk, dut.rst) + + dut.enable.setimmediatevalue(0) + + def set_idle_generator(self, generator=None): + if generator: + self.axi_ram.r_channel.set_pause_generator(generator()) + + def set_backpressure_generator(self, generator=None): + if generator: + self.axi_ram.ar_channel.set_pause_generator(generator()) + self.dma_ram.set_pause_generator(generator()) + + async def cycle_reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test_read(dut, idle_inserter=None, backpressure_inserter=None): + + tb = TB(dut) + + axi_byte_lanes = tb.axi_ram.byte_lanes + ram_byte_lanes = tb.dma_ram.byte_lanes + tag_count = 2**len(tb.read_desc_source.bus.tag) + + cur_tag = 1 + + tb.set_idle_generator(idle_inserter) + tb.set_backpressure_generator(backpressure_inserter) + + await tb.cycle_reset() + + tb.dut.enable <= 1 + + for length in list(range(1, ram_byte_lanes+3))+list(range(128-4, 128+4))+[1024]: + for axi_offset in list(range(axi_byte_lanes+1))+list(range(4096-axi_byte_lanes, 4096)): + for ram_offset in range(ram_byte_lanes+1): + tb.log.info("length %d, axi_offset %d, ram_offset %d", length, axi_offset, ram_offset) + axi_addr = axi_offset+0x1000 + ram_addr = ram_offset+0x1000 + test_data = bytearray([x % 256 for x in range(length)]) + + tb.axi_ram.write(axi_addr, test_data) + + tb.log.debug("%s", tb.axi_ram.hexdump_str((axi_addr & ~0xf)-16, (((axi_addr & 0xf)+length-1) & ~0xf)+48, prefix="AXI ")) + + tb.dma_ram.write(ram_addr-256, b'\xaa'*(len(test_data)+512)) + + desc = DescTransaction(axi_addr=axi_addr, ram_addr=ram_addr, ram_sel=0, len=len(test_data), tag=cur_tag) + await tb.read_desc_source.send(desc) + + status = await tb.read_desc_status_sink.recv() + + tb.log.info("status: %s", status) + + assert int(status.tag) == cur_tag + assert int(status.error) == 0 + + tb.log.debug("%s", tb.dma_ram.hexdump_str((ram_addr & ~0xf)-16, (((ram_addr & 0xf)+length-1) & ~0xf)+48, prefix="RAM ")) + + assert tb.dma_ram.read(ram_addr-8, len(test_data)+16) == b'\xaa'*8+test_data+b'\xaa'*8 + + cur_tag = (cur_tag + 1) % tag_count + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def cycle_pause(): + return itertools.cycle([1, 1, 1, 0]) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test_read) + factory.add_option("idle_inserter", [None, cycle_pause]) + factory.add_option("backpressure_inserter", [None, cycle_pause]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) + + +@pytest.mark.parametrize("axi_data_width", [64, 128]) +def test_dma_if_axi_rd(request, axi_data_width): + dut = "dma_if_axi_rd" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + ] + + parameters = {} + + # segmented interface parameters + ram_seg_count = 2 + ram_seg_data_width = axi_data_width*2 // ram_seg_count + ram_seg_addr_width = 12 + ram_seg_be_width = ram_seg_data_width // 8 + ram_sel_width = 2 + ram_addr_width = ram_seg_addr_width + (ram_seg_count*ram_seg_be_width-1).bit_length() + + parameters['AXI_DATA_WIDTH'] = axi_data_width + parameters['AXI_ADDR_WIDTH'] = 16 + parameters['AXI_STRB_WIDTH'] = parameters['AXI_DATA_WIDTH'] // 8 + parameters['AXI_ID_WIDTH'] = 8 + parameters['RAM_SEG_COUNT'] = ram_seg_count + parameters['RAM_SEG_DATA_WIDTH'] = ram_seg_data_width + parameters['RAM_SEG_ADDR_WIDTH'] = ram_seg_addr_width + parameters['RAM_SEG_BE_WIDTH'] = ram_seg_be_width + parameters['RAM_SEL_WIDTH'] = ram_sel_width + parameters['RAM_ADDR_WIDTH'] = ram_addr_width + parameters['LEN_WIDTH'] = 16 + parameters['TAG_WIDTH'] = 8 + parameters['OP_TABLE_SIZE'] = 2**parameters['AXI_ID_WIDTH'] + parameters['USE_AXI_ID'] = 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + ) diff --git a/fpga/lib/pcie/tb/dma_if_axi_wr/Makefile b/fpga/lib/pcie/tb/dma_if_axi_wr/Makefile new file mode 100644 index 000000000..4cf70b09c --- /dev/null +++ b/fpga/lib/pcie/tb/dma_if_axi_wr/Makefile @@ -0,0 +1,104 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = dma_if_axi_wr +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v + +# module parameters +export PARAM_AXI_DATA_WIDTH ?= 64 +export PARAM_AXI_ADDR_WIDTH ?= 16 +export PARAM_AXI_STRB_WIDTH ?= $(shell expr $(PARAM_AXI_DATA_WIDTH) / 8 ) +export PARAM_AXI_ID_WIDTH ?= 8 +export PARAM_RAM_SEG_COUNT ?= 2 +export PARAM_RAM_SEG_DATA_WIDTH ?= $(shell expr $(PARAM_AXI_DATA_WIDTH) \* 2 / $(PARAM_RAM_SEG_COUNT) ) +export PARAM_RAM_SEG_ADDR_WIDTH ?= 12 +export PARAM_RAM_SEG_BE_WIDTH ?= $(shell expr $(PARAM_RAM_SEG_DATA_WIDTH) / 8 ) +export PARAM_RAM_SEL_WIDTH ?= 2 +export PARAM_RAM_ADDR_WIDTH ?= $(shell python -c "print($(PARAM_RAM_SEG_ADDR_WIDTH) + ($(PARAM_RAM_SEG_COUNT)*$(PARAM_RAM_SEG_BE_WIDTH)-1).bit_length())") +export PARAM_LEN_WIDTH ?= 16 +export PARAM_TAG_WIDTH ?= 8 +export PARAM_OP_TABLE_SIZE ?= $(shell python -c "print(2**$(PARAM_AXI_ID_WIDTH))") + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXI_DATA_WIDTH=$(PARAM_AXI_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXI_ADDR_WIDTH=$(PARAM_AXI_ADDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXI_STRB_WIDTH=$(PARAM_AXI_STRB_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXI_ID_WIDTH=$(PARAM_AXI_ID_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_COUNT=$(PARAM_RAM_SEG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_DATA_WIDTH=$(PARAM_RAM_SEG_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_ADDR_WIDTH=$(PARAM_RAM_SEG_ADDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEG_BE_WIDTH=$(PARAM_RAM_SEG_BE_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_SEL_WIDTH=$(PARAM_RAM_SEL_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RAM_ADDR_WIDTH=$(PARAM_RAM_ADDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).LEN_WIDTH=$(PARAM_LEN_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).TAG_WIDTH=$(PARAM_TAG_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).OP_TABLE_SIZE=$(PARAM_OP_TABLE_SIZE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXI_DATA_WIDTH=$(PARAM_AXI_DATA_WIDTH) + COMPILE_ARGS += -GAXI_ADDR_WIDTH=$(PARAM_AXI_ADDR_WIDTH) + COMPILE_ARGS += -GAXI_STRB_WIDTH=$(PARAM_AXI_STRB_WIDTH) + COMPILE_ARGS += -GAXI_ID_WIDTH=$(PARAM_AXI_ID_WIDTH) + COMPILE_ARGS += -GRAM_SEG_COUNT=$(PARAM_RAM_SEG_COUNT) + COMPILE_ARGS += -GRAM_SEG_DATA_WIDTH=$(PARAM_RAM_SEG_DATA_WIDTH) + COMPILE_ARGS += -GRAM_SEG_ADDR_WIDTH=$(PARAM_RAM_SEG_ADDR_WIDTH) + COMPILE_ARGS += -GRAM_SEG_BE_WIDTH=$(PARAM_RAM_SEG_BE_WIDTH) + COMPILE_ARGS += -GRAM_SEL_WIDTH=$(PARAM_RAM_SEL_WIDTH) + COMPILE_ARGS += -GRAM_ADDR_WIDTH=$(PARAM_RAM_ADDR_WIDTH) + COMPILE_ARGS += -GLEN_WIDTH=$(PARAM_LEN_WIDTH) + COMPILE_ARGS += -GTAG_WIDTH=$(PARAM_TAG_WIDTH) + COMPILE_ARGS += -GOP_TABLE_SIZE=$(PARAM_OP_TABLE_SIZE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/tb/dma_if_axi_wr/dma_psdp_ram.py b/fpga/lib/pcie/tb/dma_if_axi_wr/dma_psdp_ram.py new file mode 120000 index 000000000..6613351ee --- /dev/null +++ b/fpga/lib/pcie/tb/dma_if_axi_wr/dma_psdp_ram.py @@ -0,0 +1 @@ +../dma_psdp_ram.py \ No newline at end of file diff --git a/fpga/lib/pcie/tb/dma_if_axi_wr/test_dma_if_axi_wr.py b/fpga/lib/pcie/tb/dma_if_axi_wr/test_dma_if_axi_wr.py new file mode 100644 index 000000000..6bea6c487 --- /dev/null +++ b/fpga/lib/pcie/tb/dma_if_axi_wr/test_dma_if_axi_wr.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2021 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +import itertools +import logging +import os +import sys + +import cocotb_test.simulator +import pytest + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.axi import AxiWriteBus, AxiRamWrite +from cocotbext.axi.stream import define_stream + +try: + from dma_psdp_ram import PsdpRamRead, PsdpRamReadBus +except ImportError: + # attempt import from current directory + sys.path.insert(0, os.path.join(os.path.dirname(__file__))) + try: + from dma_psdp_ram import PsdpRamRead, PsdpRamReadBus + finally: + del sys.path[0] + +DescBus, DescTransaction, DescSource, DescSink, DescMonitor = define_stream("Desc", + signals=["axi_addr", "ram_addr", "ram_sel", "len", "tag", "valid", "ready"] +) + +DescStatusBus, DescStatusTransaction, DescStatusSource, DescStatusSink, DescStatusMonitor = define_stream("DescStatus", + signals=["tag", "error", "valid"] +) + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + cocotb.fork(Clock(dut.clk, 10, units="ns").start()) + + # AXI RAM + self.axi_ram = AxiRamWrite(AxiWriteBus.from_prefix(dut, "m_axi"), dut.clk, dut.rst, size=2**16) + + # DMA RAM + self.dma_ram = PsdpRamRead(PsdpRamReadBus.from_prefix(dut, "ram"), dut.clk, dut.rst, size=2**16) + + # Control + self.write_desc_source = DescSource(DescBus.from_prefix(dut, "s_axis_write_desc"), dut.clk, dut.rst) + self.write_desc_status_sink = DescStatusSink(DescStatusBus.from_prefix(dut, "m_axis_write_desc_status"), dut.clk, dut.rst) + + dut.enable.setimmediatevalue(0) + + def set_idle_generator(self, generator=None): + if generator: + self.axi_ram.b_channel.set_pause_generator(generator()) + + def set_backpressure_generator(self, generator=None): + if generator: + self.axi_ram.aw_channel.set_pause_generator(generator()) + self.axi_ram.w_channel.set_pause_generator(generator()) + self.dma_ram.set_pause_generator(generator()) + + async def cycle_reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test_write(dut, idle_inserter=None, backpressure_inserter=None): + + tb = TB(dut) + + axi_byte_lanes = tb.axi_ram.byte_lanes + ram_byte_lanes = tb.dma_ram.byte_lanes + tag_count = 2**len(tb.write_desc_source.bus.tag) + + cur_tag = 1 + + tb.set_idle_generator(idle_inserter) + tb.set_backpressure_generator(backpressure_inserter) + + await tb.cycle_reset() + + tb.dut.enable <= 1 + + for length in list(range(1, ram_byte_lanes+3))+list(range(128-4, 128+4))+[1024]: + # for axi_offset in axi_offsets: + for axi_offset in list(range(axi_byte_lanes+1))+list(range(4096-axi_byte_lanes, 4096)): + for ram_offset in range(ram_byte_lanes+1): + tb.log.info("length %d, axi_offset %d, ram_offset %d", length, axi_offset, ram_offset) + axi_addr = axi_offset+0x1000 + ram_addr = ram_offset+0x1000 + test_data = bytearray([x % 256 for x in range(length)]) + + tb.dma_ram.write(ram_addr & 0xffff80, b'\x55'*(len(test_data)+256)) + tb.axi_ram.write(axi_addr-128, b'\xaa'*(len(test_data)+256)) + tb.dma_ram.write(ram_addr, test_data) + + tb.log.debug("%s", tb.dma_ram.hexdump_str((ram_addr & ~0xf)-16, (((ram_addr & 0xf)+length-1) & ~0xf)+48, prefix="RAM ")) + + desc = DescTransaction(axi_addr=axi_addr, ram_addr=ram_addr, ram_sel=0, len=len(test_data), tag=cur_tag) + await tb.write_desc_source.send(desc) + + status = await tb.write_desc_status_sink.recv() + + tb.log.info("status: %s", status) + + assert int(status.tag) == cur_tag + assert int(status.error) == 0 + + tb.log.debug("%s", tb.axi_ram.hexdump_str((axi_addr & ~0xf)-16, (((axi_addr & 0xf)+length-1) & ~0xf)+48, prefix="AXI ")) + + assert tb.axi_ram.read(axi_addr-1, len(test_data)+2) == b'\xaa'+test_data+b'\xaa' + + cur_tag = (cur_tag + 1) % tag_count + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def cycle_pause(): + return itertools.cycle([1, 1, 1, 0]) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test_write) + factory.add_option("idle_inserter", [None, cycle_pause]) + factory.add_option("backpressure_inserter", [None, cycle_pause]) + factory.generate_tests() + + +# cocotb-test + +tests_dir = os.path.dirname(__file__) +rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl')) + + +@pytest.mark.parametrize("axi_data_width", [64, 128]) +def test_dma_if_axi_wr(request, axi_data_width): + dut = "dma_if_axi_wr" + module = os.path.splitext(os.path.basename(__file__))[0] + toplevel = dut + + verilog_sources = [ + os.path.join(rtl_dir, f"{dut}.v"), + ] + + parameters = {} + + # segmented interface parameters + ram_seg_count = 2 + ram_seg_data_width = axi_data_width*2 // ram_seg_count + ram_seg_addr_width = 12 + ram_seg_be_width = ram_seg_data_width // 8 + ram_sel_width = 2 + ram_addr_width = ram_seg_addr_width + (ram_seg_count*ram_seg_be_width-1).bit_length() + + parameters['AXI_DATA_WIDTH'] = axi_data_width + parameters['AXI_ADDR_WIDTH'] = 16 + parameters['AXI_STRB_WIDTH'] = parameters['AXI_DATA_WIDTH'] // 8 + parameters['AXI_ID_WIDTH'] = 8 + parameters['RAM_SEG_COUNT'] = ram_seg_count + parameters['RAM_SEG_DATA_WIDTH'] = ram_seg_data_width + parameters['RAM_SEG_ADDR_WIDTH'] = ram_seg_addr_width + parameters['RAM_SEG_BE_WIDTH'] = ram_seg_be_width + parameters['RAM_SEL_WIDTH'] = ram_sel_width + parameters['RAM_ADDR_WIDTH'] = ram_addr_width + parameters['LEN_WIDTH'] = 16 + parameters['TAG_WIDTH'] = 8 + parameters['OP_TABLE_SIZE'] = 2**parameters['AXI_ID_WIDTH'] + parameters['USE_AXI_ID'] = 1 + + extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} + + sim_build = os.path.join(tests_dir, "sim_build", + request.node.name.replace('[', '-').replace(']', '')) + + cocotb_test.simulator.run( + python_search=[tests_dir], + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module, + parameters=parameters, + sim_build=sim_build, + extra_env=extra_env, + )