//====================================================================== // // fmc_arbiter.v // ------------- // Port arbiter for the FMC interface for the Cryptech // Novena FPGA + STM32 Bridge Board framework. // // // Author: Pavel Shatov // Copyright (c) 2015, 2018 NORDUnet A/S All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // - Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // - Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // - Neither the name of the NORDUnet nor the names of its contributors may // be used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //====================================================================== module fmc_arbiter ( // fmc bus fmc_a, fmc_d, fmc_ne1, fmc_nl, fmc_nwe, fmc_noe, fmc_nwait, // system clock sys_clk, // user bus sys_addr, sys_wr_en, sys_data_out, sys_rd_en, sys_data_in ); // // Parameters // parameter NUM_ADDR_BITS = 22; // // Ports // input wire [NUM_ADDR_BITS-1:0] fmc_a; inout wire [ 31:0] fmc_d; input wire fmc_ne1; input wire fmc_nl; input wire fmc_nwe; input wire fmc_noe; output wire fmc_nwait; input wire sys_clk; output wire [NUM_ADDR_BITS-1:0] sys_addr; output wire sys_wr_en; output wire [ 31:0] sys_data_out; output wire sys_rd_en; input wire [ 31:0] sys_data_in; // // Data Bus PHY // /* PHY is needed to control bi-directional data bus. */ wire [31: 0] fmc_d_ro; // value read from pins (receiver output) wire [31: 0] fmc_d_di; // value drives onto pins (driver input) fmc_d_phy # ( .BUS_WIDTH(32) ) d_phy ( .buf_io(fmc_d), // <-- connect directly to top-level bi-dir port .buf_di(fmc_d_di), .buf_ro(fmc_d_ro), .buf_t(fmc_noe) // <-- bus direction is controlled by STM32 ); // // Two-Stage Synchronizer // (* SHREG_EXTRACT="NO" *) (* IOB="FALSE" *) reg [23: 0] fmc_a_ff1; (* SHREG_EXTRACT="NO" *) reg [23: 0] fmc_a_ff2; (* SHREG_EXTRACT="NO" *) (* IOB="TRUE" *) reg [31: 0] fmc_d_ro_ff1; (* SHREG_EXTRACT="NO" *) reg [31: 0] fmc_d_ro_ff2; (* SHREG_EXTRACT="NO" *) (* IOB="FALSE" *) reg fmc_ne1_ff1; (* SHREG_EXTRACT="NO" *) reg fmc_ne1_ff2; (* SHREG_EXTRACT="NO" *) (* IOB="FALSE" *) reg fmc_nwe_ff1; (* SHREG_EXTRACT="NO" *) reg fmc_nwe_ff2; (* SHREG_EXTRACT="NO" *) (* IOB="FALSE" *) reg fmc_nl_ff1; (* SHREG_EXTRACT="NO" *) reg fmc_nl_ff2; wire [23: 0] fmc_a_sync = fmc_a_ff2; wire [31: 0] fmc_d_ro_sync = fmc_d_ro_ff2; wire fmc_ne1_sync = fmc_ne1_ff2; wire fmc_nwe_sync = fmc_nwe_ff2; wire fmc_nl_sync = fmc_nl_ff2; always @(posedge sys_clk) begin fmc_a_ff1 <= fmc_a; fmc_a_ff2 <= fmc_a_ff1; fmc_d_ro_ff1 <= fmc_d_ro; fmc_d_ro_ff2 <= fmc_d_ro_ff1; fmc_ne1_ff1 <= fmc_ne1; fmc_ne1_ff2 <= fmc_ne1_ff1; fmc_nwe_ff1 <= fmc_nwe; fmc_nwe_ff2 <= fmc_nwe_ff1; fmc_nl_ff1 <= fmc_nl; fmc_nl_ff2 <= fmc_nl_ff1; end // // FSM // localparam FSM_STATE_IDLE = 4'd0; localparam FSM_STATE_WRITE_START = 4'd1; localparam FSM_STATE_WRITE_LATENCY_1 = 4'd2; localparam FSM_STATE_WRITE_LATENCY_2 = 4'd3; localparam FSM_STATE_WRITE_LATENCY_3 = 4'd4; localparam FSM_STATE_WRITE_LATENCY_4 = 4'd5; localparam FSM_STATE_WRITE_STOP = 4'd6; localparam FSM_STATE_READ_START = 4'd7; localparam FSM_STATE_READ_LATENCY_1 = 4'd8; localparam FSM_STATE_READ_STOP = 4'd9; reg [ 3: 0] fsm_state = FSM_STATE_IDLE; reg [ 3: 0] fsm_state_next; always @(posedge sys_clk) // fsm_state <= fsm_state_next; // // FSM Transition Logic // always @* // if (fmc_ne1_sync) fsm_state_next = FSM_STATE_IDLE; else case (fsm_state) FSM_STATE_IDLE: fsm_state_next = !fmc_nwe_sync ? FSM_STATE_WRITE_START : FSM_STATE_READ_START; FSM_STATE_WRITE_START: fsm_state_next = FSM_STATE_WRITE_LATENCY_1; FSM_STATE_WRITE_LATENCY_1: fsm_state_next = FSM_STATE_WRITE_LATENCY_2; FSM_STATE_WRITE_LATENCY_2: fsm_state_next = FSM_STATE_WRITE_LATENCY_3; FSM_STATE_WRITE_LATENCY_3: fsm_state_next = FSM_STATE_WRITE_LATENCY_4; FSM_STATE_WRITE_LATENCY_4, FSM_STATE_WRITE_STOP: fsm_state_next = FSM_STATE_WRITE_STOP; FSM_STATE_READ_START: fsm_state_next = FSM_STATE_READ_LATENCY_1; FSM_STATE_READ_LATENCY_1, FSM_STATE_READ_STOP: fsm_state_next = FSM_STATE_READ_STOP; default: fsm_state_next = FSM_STATE_IDLE; endcase // // Output Data Latch // (* IOB="TRUE" *) reg [31:0] sys_data_in_latch; assign fmc_d_di = sys_data_in_latch; // // Address Latch // always @(posedge sys_clk) // if (!fmc_ne1_sync && !fmc_nl_sync) // sys_addr_reg <= fmc_a_sync; // // System Interface // reg [NUM_ADDR_BITS-1:0] sys_addr_reg; reg sys_wr_en_reg = 1'b0; reg [ 31:0] sys_data_out_reg; reg sys_rd_en_reg = 1'b0; assign sys_addr = sys_addr_reg; assign sys_wr_en = sys_wr_en_reg; assign sys_data_out = sys_data_out_reg; assign sys_rd_en = sys_rd_en_reg; // // Write Enable Logic // always @(posedge sys_clk) // case (fsm_state) FSM_STATE_WRITE_LATENCY_4: sys_wr_en_reg <= 1'b1; default: sys_wr_en_reg <= 1'b0; endcase // // Read Enable Logic // always @(posedge sys_clk) // case (fsm_state_next) FSM_STATE_READ_START: sys_rd_en_reg <= 1'b1; default: sys_rd_en_reg <= 1'b0; endcase // // Output Data Latch // always @(posedge sys_clk) // case (fsm_state) FSM_STATE_READ_LATENCY_1: sys_data_in_latch <= sys_data_in; endcase // // Input Data Latch // always @(posedge sys_clk) // case (fsm_state) FSM_STATE_WRITE_LATENCY_4: sys_data_out_reg <= fmc_d_ro_sync; endcase // // Unused NWAIT tieoff // assign fmc_nwait = 1'b0; endmodule //====================================================================== // EOF fmc_arbiter.v //======================================================================