Loading util_modules/cmd_seq_mux.v 0 → 100644 +118 −0 Original line number Diff line number Diff line /******************************************************************************* * Module: cmd_seq_mux * Date:2015-06-29 * Author: andrey * Description: Command multiplexer from 4 channels of frame-based command * sequencers. * * Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> . * cmd_seq_mux.v is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * cmd_seq_mux.v is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ `timescale 1ns/1ps module cmd_seq_mux#( parameter AXI_WR_ADDR_BITS=14 )( input rst, // global system reset input mclk, // global system clock // Sensor channel 0 input [AXI_WR_ADDR_BITS-1:0] waddr0, // write address, valid with wr_en_out input wr_en0, // write enable input [31:0] wdata0, // write data, valid with waddr_out and wr_en_out output ackn0, // command sequencer address/data accepted // Sensor channel 1 input [AXI_WR_ADDR_BITS-1:0] waddr1, // write address, valid with wr_en_out input wr_en1, // write enable input [31:0] wdata1, // write data, valid with waddr_out and wr_en_out output ackn1, // command sequencer address/data accepted // Sensor channel 2 input [AXI_WR_ADDR_BITS-1:0] waddr2, // write address, valid with wr_en_out input wr_en2, // write enable input [31:0] wdata2, // write data, valid with waddr_out and wr_en_out output ackn2, // command sequencer address/data accepted // Sensor channel 3 input [AXI_WR_ADDR_BITS-1:0] waddr3, // write address, valid with wr_en_out input wr_en3, // write enable input [31:0] wdata3, // write data, valid with waddr_out and wr_en_out output ackn3, // command sequencer address/data accepted // mux output output reg [AXI_WR_ADDR_BITS-1:0] waddr_out, // write address, valid with wr_en_out output wr_en_out, // write enable output reg [31:0] wdata_out, // write data, valid with waddr_out and wr_en_out input ackn_out // command sequencer address/data accepted ); wire [3:0] wr_en = {wr_en3 & ~ackn3, wr_en2 & ~ackn2, wr_en1 & ~ackn1, wr_en0 & ~ackn0}; wire [3:0] pri_one_rr[0:3]; // round robin priority wire [3:0] pri_one; reg [1:0] chn_r; // last served channel wire rq_any; wire [1:0] pri_enc_w; reg full_r; wire ackn_w; //pre-acknowledge of one of the channels reg [3:0] ackn_r; assign pri_one_rr[0]={wr_en[3] & ~(|wr_en[2:1]), wr_en[2] & ~wr_en[1], wr_en[1], wr_en[0] & ~(|wr_en[3:1])}; assign pri_one_rr[1]={wr_en[3] & ~ wr_en[2], wr_en[2], wr_en[1] & ~(|wr_en[3:2]) & wr_en[0], wr_en[0] & ~(|wr_en[3:2])}; assign pri_one_rr[2]={wr_en[3], wr_en[2]&~(|wr_en[1:0])&wr_en[3], wr_en[1] & ~ wr_en[3] & wr_en[0], wr_en[0] & ~ wr_en[3] }; assign pri_one_rr[3]={wr_en[3] & ~(|wr_en[2:0]), wr_en[2]&~(|wr_en[1:0]), wr_en[1] & wr_en[0], wr_en[0] }; assign pri_one = pri_one_rr[chn_r]; assign rq_any= |wr_en; assign pri_enc_w ={pri_one[3] | pri_one[2], pri_one[3] | pri_one[1]}; assign wr_en_out = full_r; assign {ackn3, ackn2, ackn1, ackn0} = ackn_r; assign ackn_w = rq_any && (!full_r || ackn_out); always @(posedge rst or posedge mclk) begin if (rst) full_r <= 0; else if (rq_any) full_r <= 1; else if (ackn_out) full_r <= 0; if (rst) ackn_r <=0; else ackn_r <= {4{ackn_w}} & { pri_enc_w[1] & pri_enc_w[0], pri_enc_w[1] & ~pri_enc_w[0], ~pri_enc_w[1] & pri_enc_w[0], ~pri_enc_w[1] & ~pri_enc_w[0]}; end always @(posedge mclk) begin if (ackn_w) begin chn_r <= pri_enc_w; case (pri_enc_w) 2'h0:begin waddr_out <= waddr0; wdata_out <= wdata0; end 2'h1:begin waddr_out <= waddr1; wdata_out <= wdata1; end 2'h2:begin waddr_out <= waddr2; wdata_out <= wdata2; end 2'h3:begin waddr_out <= waddr3; wdata_out <= wdata3; end endcase end end endmodule x393.v +66 −8 Original line number Diff line number Diff line Loading @@ -158,10 +158,29 @@ module x393 #( wire axird_dev_busy; //TODO: The following is the interface to the frame-based command sequencer (not yet implemnted) wire [AXI_WR_ADDR_BITS-1:0] cseq_waddr; /// S uppressThisWarning VEditor ****** command sequencer write address (output to command multiplexer) wire cseq_wr_en; /// S uppressThisWarning VEditor ****** command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq_wdata; /// S uppressThisWarning VEditor ****** command sequencer write data (output to command multiplexer) wire cseq_ackn; /// SuppressThisWarning VEditor ****** ackn to command sequencer, command sequencer should de-assert cseq_wr_en wire [AXI_WR_ADDR_BITS-1:0] cseq_waddr; // command sequencer write address (output to command multiplexer) wire cseq_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq_wdata; // command sequencer write data (output to command multiplexer) wire cseq_ackn; // ackn to command sequencer, command sequencer should de-assert cseq_wr_en // per-sensor channel command sequencer signals wire [AXI_WR_ADDR_BITS-1:0] cseq0_waddr; // command sequencer write address (output to command multiplexer) wire cseq0_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq0_wdata; // command sequencer write data (output to command multiplexer) wire cseq0_ackn; /// SuppressThisWarning VEditor ****** ackn to command sequencer, command sequencer should de-assert cseq_wr_en wire [AXI_WR_ADDR_BITS-1:0] cseq1_waddr; // command sequencer write address (output to command multiplexer) wire cseq1_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq1_wdata; // command sequencer write data (output to command multiplexer) wire cseq1_ackn; /// SuppressThisWarning VEditor ****** ackn to command sequencer, command sequencer should de-assert cseq_wr_en wire [AXI_WR_ADDR_BITS-1:0] cseq2_waddr; // command sequencer write address (output to command multiplexer) wire cseq2_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq2_wdata; // command sequencer write data (output to command multiplexer) wire cseq2_ackn; /// SuppressThisWarning VEditor ****** ackn to command sequencer, command sequencer should de-assert cseq_wr_en wire [AXI_WR_ADDR_BITS-1:0] cseq3_waddr; // command sequencer write address (output to command multiplexer) wire cseq3_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq3_wdata; // command sequencer write data (output to command multiplexer) wire cseq3_ackn; /// SuppressThisWarning VEditor ****** ackn to command sequencer, command sequencer should de-assert cseq_wr_en // parallel address/data - where higher bandwidth (single-cycle) is needed wire [AXI_WR_ADDR_BITS-1:0] par_waddr; /// SuppressThisWarning VEditor ****** multiplexed address (full, parallel) to slave devices wire [31:0] par_data; /// SuppressThisWarning VEditor ****** multiplexed data (full, parallel) to slave devices Loading Loading @@ -290,10 +309,21 @@ module x393 #( // assign status_test01_start = status_other_start; // missing command sequencer: assign cseq_waddr='bx; // command sequencer write address (output to command multiplexer) assign cseq_wr_en= 0; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received assign cseq_wdata='bx; // command sequencer write data (output to command multiplexer) assign cseq0_waddr='bx; // command sequencer write address (output to command multiplexer) assign cseq0_wr_en= 0; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received assign cseq0_wdata='bx; // command sequencer write data (output to command multiplexer) assign cseq1_waddr='bx; // command sequencer write address (output to command multiplexer) assign cseq1_wr_en= 0; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received assign cseq1_wdata='bx; // command sequencer write data (output to command multiplexer) assign cseq2_waddr='bx; // command sequencer write address (output to command multiplexer) assign cseq2_wr_en= 0; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received assign cseq2_wdata='bx; // command sequencer write data (output to command multiplexer) assign cseq3_waddr='bx; // command sequencer write address (output to command multiplexer) assign cseq3_wr_en= 0; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received assign cseq3_wdata='bx; // command sequencer write data (output to command multiplexer) Loading Loading @@ -427,7 +457,7 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0])); ); // Interface to channels to read/write memory (including 4 page BRAM buffers) // TODO:increase depth, number of NUM_CYCLES - twice? cmd_mux #( .AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS), .CONTROL_ADDR (CONTROL_ADDR), Loading Loading @@ -473,6 +503,34 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0])); .ad_stb (cmd_root_stb) // output ); cmd_seq_mux #( .AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS) ) cmd_seq_mux_i ( .rst (axi_rst), // input .mclk (mclk), // input .waddr0 (cseq0_waddr), // input[13:0] .wr_en0 (cseq0_wr_en), // input .wdata0 (cseq0_wdata), // input[31:0] .ackn0 (cseq0_ackn), // output .waddr1 (cseq1_waddr), // input[13:0] .wr_en1 (cseq1_wr_en), // input .wdata1 (cseq1_wdata), // input[31:0] .ackn1 (cseq1_ackn), // output .waddr2 (cseq2_waddr), // input[13:0] .wr_en2 (cseq2_wr_en), // input .wdata2 (cseq2_wdata), // input[31:0] .ackn2 (cseq2_ackn), // output .waddr3 (cseq3_waddr), // input[13:0] .wr_en3 (cseq3_wr_en), // input .wdata3 (cseq3_wdata), // input[31:0] .ackn3 (cseq3_ackn), // output .waddr_out (cseq_waddr), // output[13:0] reg .wr_en_out (cseq_wr_en), // output .wdata_out (cseq_wdata), // output[31:0] reg .ackn_out (cseq_ackn) // input ); // Mirror control register data for readback (registers can be written both from the PS and from the command sequencer) cmd_readback #( .AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS), Loading Loading
util_modules/cmd_seq_mux.v 0 → 100644 +118 −0 Original line number Diff line number Diff line /******************************************************************************* * Module: cmd_seq_mux * Date:2015-06-29 * Author: andrey * Description: Command multiplexer from 4 channels of frame-based command * sequencers. * * Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> . * cmd_seq_mux.v is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * cmd_seq_mux.v is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ `timescale 1ns/1ps module cmd_seq_mux#( parameter AXI_WR_ADDR_BITS=14 )( input rst, // global system reset input mclk, // global system clock // Sensor channel 0 input [AXI_WR_ADDR_BITS-1:0] waddr0, // write address, valid with wr_en_out input wr_en0, // write enable input [31:0] wdata0, // write data, valid with waddr_out and wr_en_out output ackn0, // command sequencer address/data accepted // Sensor channel 1 input [AXI_WR_ADDR_BITS-1:0] waddr1, // write address, valid with wr_en_out input wr_en1, // write enable input [31:0] wdata1, // write data, valid with waddr_out and wr_en_out output ackn1, // command sequencer address/data accepted // Sensor channel 2 input [AXI_WR_ADDR_BITS-1:0] waddr2, // write address, valid with wr_en_out input wr_en2, // write enable input [31:0] wdata2, // write data, valid with waddr_out and wr_en_out output ackn2, // command sequencer address/data accepted // Sensor channel 3 input [AXI_WR_ADDR_BITS-1:0] waddr3, // write address, valid with wr_en_out input wr_en3, // write enable input [31:0] wdata3, // write data, valid with waddr_out and wr_en_out output ackn3, // command sequencer address/data accepted // mux output output reg [AXI_WR_ADDR_BITS-1:0] waddr_out, // write address, valid with wr_en_out output wr_en_out, // write enable output reg [31:0] wdata_out, // write data, valid with waddr_out and wr_en_out input ackn_out // command sequencer address/data accepted ); wire [3:0] wr_en = {wr_en3 & ~ackn3, wr_en2 & ~ackn2, wr_en1 & ~ackn1, wr_en0 & ~ackn0}; wire [3:0] pri_one_rr[0:3]; // round robin priority wire [3:0] pri_one; reg [1:0] chn_r; // last served channel wire rq_any; wire [1:0] pri_enc_w; reg full_r; wire ackn_w; //pre-acknowledge of one of the channels reg [3:0] ackn_r; assign pri_one_rr[0]={wr_en[3] & ~(|wr_en[2:1]), wr_en[2] & ~wr_en[1], wr_en[1], wr_en[0] & ~(|wr_en[3:1])}; assign pri_one_rr[1]={wr_en[3] & ~ wr_en[2], wr_en[2], wr_en[1] & ~(|wr_en[3:2]) & wr_en[0], wr_en[0] & ~(|wr_en[3:2])}; assign pri_one_rr[2]={wr_en[3], wr_en[2]&~(|wr_en[1:0])&wr_en[3], wr_en[1] & ~ wr_en[3] & wr_en[0], wr_en[0] & ~ wr_en[3] }; assign pri_one_rr[3]={wr_en[3] & ~(|wr_en[2:0]), wr_en[2]&~(|wr_en[1:0]), wr_en[1] & wr_en[0], wr_en[0] }; assign pri_one = pri_one_rr[chn_r]; assign rq_any= |wr_en; assign pri_enc_w ={pri_one[3] | pri_one[2], pri_one[3] | pri_one[1]}; assign wr_en_out = full_r; assign {ackn3, ackn2, ackn1, ackn0} = ackn_r; assign ackn_w = rq_any && (!full_r || ackn_out); always @(posedge rst or posedge mclk) begin if (rst) full_r <= 0; else if (rq_any) full_r <= 1; else if (ackn_out) full_r <= 0; if (rst) ackn_r <=0; else ackn_r <= {4{ackn_w}} & { pri_enc_w[1] & pri_enc_w[0], pri_enc_w[1] & ~pri_enc_w[0], ~pri_enc_w[1] & pri_enc_w[0], ~pri_enc_w[1] & ~pri_enc_w[0]}; end always @(posedge mclk) begin if (ackn_w) begin chn_r <= pri_enc_w; case (pri_enc_w) 2'h0:begin waddr_out <= waddr0; wdata_out <= wdata0; end 2'h1:begin waddr_out <= waddr1; wdata_out <= wdata1; end 2'h2:begin waddr_out <= waddr2; wdata_out <= wdata2; end 2'h3:begin waddr_out <= waddr3; wdata_out <= wdata3; end endcase end end endmodule
x393.v +66 −8 Original line number Diff line number Diff line Loading @@ -158,10 +158,29 @@ module x393 #( wire axird_dev_busy; //TODO: The following is the interface to the frame-based command sequencer (not yet implemnted) wire [AXI_WR_ADDR_BITS-1:0] cseq_waddr; /// S uppressThisWarning VEditor ****** command sequencer write address (output to command multiplexer) wire cseq_wr_en; /// S uppressThisWarning VEditor ****** command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq_wdata; /// S uppressThisWarning VEditor ****** command sequencer write data (output to command multiplexer) wire cseq_ackn; /// SuppressThisWarning VEditor ****** ackn to command sequencer, command sequencer should de-assert cseq_wr_en wire [AXI_WR_ADDR_BITS-1:0] cseq_waddr; // command sequencer write address (output to command multiplexer) wire cseq_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq_wdata; // command sequencer write data (output to command multiplexer) wire cseq_ackn; // ackn to command sequencer, command sequencer should de-assert cseq_wr_en // per-sensor channel command sequencer signals wire [AXI_WR_ADDR_BITS-1:0] cseq0_waddr; // command sequencer write address (output to command multiplexer) wire cseq0_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq0_wdata; // command sequencer write data (output to command multiplexer) wire cseq0_ackn; /// SuppressThisWarning VEditor ****** ackn to command sequencer, command sequencer should de-assert cseq_wr_en wire [AXI_WR_ADDR_BITS-1:0] cseq1_waddr; // command sequencer write address (output to command multiplexer) wire cseq1_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq1_wdata; // command sequencer write data (output to command multiplexer) wire cseq1_ackn; /// SuppressThisWarning VEditor ****** ackn to command sequencer, command sequencer should de-assert cseq_wr_en wire [AXI_WR_ADDR_BITS-1:0] cseq2_waddr; // command sequencer write address (output to command multiplexer) wire cseq2_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq2_wdata; // command sequencer write data (output to command multiplexer) wire cseq2_ackn; /// SuppressThisWarning VEditor ****** ackn to command sequencer, command sequencer should de-assert cseq_wr_en wire [AXI_WR_ADDR_BITS-1:0] cseq3_waddr; // command sequencer write address (output to command multiplexer) wire cseq3_wr_en; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received wire [31:0] cseq3_wdata; // command sequencer write data (output to command multiplexer) wire cseq3_ackn; /// SuppressThisWarning VEditor ****** ackn to command sequencer, command sequencer should de-assert cseq_wr_en // parallel address/data - where higher bandwidth (single-cycle) is needed wire [AXI_WR_ADDR_BITS-1:0] par_waddr; /// SuppressThisWarning VEditor ****** multiplexed address (full, parallel) to slave devices wire [31:0] par_data; /// SuppressThisWarning VEditor ****** multiplexed data (full, parallel) to slave devices Loading Loading @@ -290,10 +309,21 @@ module x393 #( // assign status_test01_start = status_other_start; // missing command sequencer: assign cseq_waddr='bx; // command sequencer write address (output to command multiplexer) assign cseq_wr_en= 0; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received assign cseq_wdata='bx; // command sequencer write data (output to command multiplexer) assign cseq0_waddr='bx; // command sequencer write address (output to command multiplexer) assign cseq0_wr_en= 0; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received assign cseq0_wdata='bx; // command sequencer write data (output to command multiplexer) assign cseq1_waddr='bx; // command sequencer write address (output to command multiplexer) assign cseq1_wr_en= 0; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received assign cseq1_wdata='bx; // command sequencer write data (output to command multiplexer) assign cseq2_waddr='bx; // command sequencer write address (output to command multiplexer) assign cseq2_wr_en= 0; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received assign cseq2_wdata='bx; // command sequencer write data (output to command multiplexer) assign cseq3_waddr='bx; // command sequencer write address (output to command multiplexer) assign cseq3_wr_en= 0; // command sequencer write enable (output to command multiplexer) - keep until cseq_ackn received assign cseq3_wdata='bx; // command sequencer write data (output to command multiplexer) Loading Loading @@ -427,7 +457,7 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0])); ); // Interface to channels to read/write memory (including 4 page BRAM buffers) // TODO:increase depth, number of NUM_CYCLES - twice? cmd_mux #( .AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS), .CONTROL_ADDR (CONTROL_ADDR), Loading Loading @@ -473,6 +503,34 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0])); .ad_stb (cmd_root_stb) // output ); cmd_seq_mux #( .AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS) ) cmd_seq_mux_i ( .rst (axi_rst), // input .mclk (mclk), // input .waddr0 (cseq0_waddr), // input[13:0] .wr_en0 (cseq0_wr_en), // input .wdata0 (cseq0_wdata), // input[31:0] .ackn0 (cseq0_ackn), // output .waddr1 (cseq1_waddr), // input[13:0] .wr_en1 (cseq1_wr_en), // input .wdata1 (cseq1_wdata), // input[31:0] .ackn1 (cseq1_ackn), // output .waddr2 (cseq2_waddr), // input[13:0] .wr_en2 (cseq2_wr_en), // input .wdata2 (cseq2_wdata), // input[31:0] .ackn2 (cseq2_ackn), // output .waddr3 (cseq3_waddr), // input[13:0] .wr_en3 (cseq3_wr_en), // input .wdata3 (cseq3_wdata), // input[31:0] .ackn3 (cseq3_ackn), // output .waddr_out (cseq_waddr), // output[13:0] reg .wr_en_out (cseq_wr_en), // output .wdata_out (cseq_wdata), // output[31:0] reg .ackn_out (cseq_ackn) // input ); // Mirror control register data for readback (registers can be written both from the PS and from the command sequencer) cmd_readback #( .AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS), Loading