Commit 460a550b authored by Andrey Filippov's avatar Andrey Filippov
Browse files

adding multiplexer for 4-channels of command sequencers

parent 18addecb
Loading
Loading
Loading
Loading
+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
+66 −8
Original line number Diff line number Diff line
@@ -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 
@@ -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) 



@@ -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),
@@ -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),