diff options
Diffstat (limited to 'fpga/usrp3/lib/control/settings_bus_timed_2clk.v')
| -rw-r--r-- | fpga/usrp3/lib/control/settings_bus_timed_2clk.v | 170 | 
1 files changed, 170 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/control/settings_bus_timed_2clk.v b/fpga/usrp3/lib/control/settings_bus_timed_2clk.v new file mode 100644 index 000000000..2b62ffd26 --- /dev/null +++ b/fpga/usrp3/lib/control/settings_bus_timed_2clk.v @@ -0,0 +1,170 @@ +// +// Copyright 2018 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: settings_bus_timed_2clk +// Description: +// - Stores settings bus transaction in a FIFO and  +//   releases them based on VITA time input +// - Also moves the settings bus to the timebase +//   clock domain +// + +module settings_bus_timed_2clk #( +  parameter SR_AWIDTH     = 8, +  parameter SR_DWIDTH     = 32, +  parameter RB_AWIDTH     = 8, +  parameter RB_DWIDTH     = 64, +  parameter TIMED_CMDS_EN = 0 +) ( +  input                  sb_clk,          // Settings bus clock +  input                  sb_rst,          // Reset (sb_clk) +  input                  tb_clk,          // Timebase clock +  input                  tb_rst,          // Reset (tb_clk) + +  input  [63:0]          vita_time,       // Current timebase time +                          +  input                  s_set_stb,       // Settings bus strobe +  input  [SR_AWIDTH-1:0] s_set_addr,      // Settings address +  input  [SR_DWIDTH-1:0] s_set_data,      // Settings data +  input                  s_set_has_time,  // Is this a timed command? +  input  [63:0]          s_set_time,      // Command time +  output                 s_set_pending,   // Is settings transaction pending? +  input  [RB_AWIDTH-1:0] s_rb_addr,       // Readback address +  output                 s_rb_stb,        // Readback data strobe +  output [RB_DWIDTH-1:0] s_rb_data,       // Readback data value + +  output                 m_set_stb,       // Settings bus strobe +  output [SR_AWIDTH-1:0] m_set_addr,      // Settings address +  output [SR_DWIDTH-1:0] m_set_data,      // Settings data +  output                 m_set_has_time,  // Is this a timed command? +  output [63:0]          m_set_time,      // Command time +  input                  m_set_pending,   // Is settings transaction pending? +  output [RB_AWIDTH-1:0] m_rb_addr,       // Readback address +  input                  m_rb_stb,        // Readback data strobe +  input  [RB_DWIDTH-1:0] m_rb_data        // Readback data value +); + +  // States for input and output state machines +  localparam [2:0] ST_IDLE        = 3'd0; // Nothing is happening on the bus +  localparam [2:0] ST_SET_ISSUED  = 3'd1; // A settings transaction has been issued +  localparam [2:0] ST_SET_PENDING = 3'd2; // A settings transaction is pending +  localparam [2:0] ST_RB_PENDING  = 3'd3; // Waiting for readback data +  localparam [2:0] ST_RB_DONE     = 3'd4; // Readback data is valid +   +  wire rb_valid; + +  // Input state machine +  reg [2:0] in_state = ST_IDLE; +  always @(posedge sb_clk) begin +    if (sb_rst) begin +      in_state <= ST_IDLE; +    end else begin +      case (in_state) +        ST_IDLE: begin +          if (s_set_stb) begin +            in_state <= ST_SET_PENDING; +          end +        end +        ST_SET_PENDING: begin +          if (rb_valid) begin +            in_state <= ST_RB_DONE; +          end +        end +        ST_RB_DONE: begin +          in_state <= ST_IDLE; +        end +        default: begin +          in_state <= ST_IDLE; +        end +      endcase +    end +  end +  assign s_set_pending = (in_state == ST_SET_PENDING); +  assign s_rb_stb = (in_state == ST_RB_DONE); + +  // Clock crossing FIFO (settings) +  // TODO: Look into a more efficient implementation for a single element +  //       clock crossing FIFO. +  wire set_pending, set_finished; +  axi_fifo_2clk #( +    .WIDTH(SR_AWIDTH+SR_DWIDTH+1+64+RB_AWIDTH), .SIZE(0) +  ) sb_2clk_fifo_i ( +    .i_aclk(sb_clk), .reset(sb_rst), +    .i_tdata({s_set_addr, s_set_data, s_set_has_time, s_set_time, s_rb_addr}), +    .i_tvalid(s_set_stb), .i_tready(/* Ignored: FIFO may not have an exact size*/), +    .o_aclk(tb_clk), +    .o_tdata({m_set_addr, m_set_data, m_set_has_time, m_set_time, m_rb_addr}), +    .o_tvalid(set_pending), .o_tready(set_finished) +  ); + +  // Time compare logic +  // If ~has_time then pass the transaction through, otherwise wait for time +  // to tick up to command time +  wire now, late; +  wire go = ((TIMED_CMDS_EN == 1) && m_set_has_time) ? (now | late) : 1'b1; + +  // If this is a timed command then vita_time == m_set_time one cycle before +  // strobe is asserted i.e. timed strobe assertion has a one cycle latency +  time_compare time_compare ( +    .clk(tb_clk), .reset(tb_rst), +    .time_now(vita_time), .trigger_time(m_set_time), +    .now(now), .early(), .late(late), .too_early() +  ); + +  // Clock crossing FIFO (readback) +  reg [RB_DWIDTH-1:0] cached_rb_data; +  axi_fifo_2clk #( +    .WIDTH(RB_DWIDTH), .SIZE(0) +  ) rbdata_2clk_fifo_i ( +    .reset(tb_rst), +    .i_aclk(tb_clk), .i_tdata(cached_rb_data), .i_tvalid(set_finished), .i_tready(), +    .o_aclk(sb_clk), .o_tdata(s_rb_data), .o_tvalid(rb_valid), .o_tready(s_rb_stb) +  ); + +  // Output state machine +  reg [2:0] out_state = ST_IDLE; +  always @(posedge tb_clk) begin +    if (tb_rst) begin +      out_state <= ST_IDLE; +    end else begin +      case (out_state) +        ST_IDLE: begin +          if (go & set_pending) begin +            out_state <= ST_SET_ISSUED; +          end +        end +        ST_SET_ISSUED: begin +          out_state <= ST_SET_PENDING; +        end +        ST_SET_PENDING: begin +          if (~m_set_pending) begin +            if (m_rb_stb) begin +              out_state <= ST_RB_DONE; +              cached_rb_data <= m_rb_data; +            end else begin +              out_state <= ST_RB_PENDING; +            end +          end +        end +        ST_RB_PENDING: begin +          if (m_rb_stb) begin +            out_state <= ST_RB_DONE; +            cached_rb_data <= m_rb_data; +          end +        end +        ST_RB_DONE: begin +          out_state <= ST_IDLE; +        end +        default: begin +          out_state <= ST_IDLE; +        end +      endcase +    end +  end + +  assign m_set_stb = (out_state == ST_SET_ISSUED); +  assign set_finished = (out_state == ST_RB_DONE); + +endmodule  | 
