[Cryptech-Commits] [core/comm/fmc] 02/03: FMC arbiter overhaul.

git at cryptech.is git at cryptech.is
Thu Jul 5 21:21:40 UTC 2018


This is an automated email from the git hooks/post-receive script.

meisterpaul1 at yandex.ru pushed a commit to branch fmc_clk
in repository core/comm/fmc.

commit 1ab18ea4258a4e614422d66905776d8d8302b841
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Thu Jul 5 21:44:28 2018 +0300

    FMC arbiter overhaul.
---
 src/rtl/fmc_arbiter.v | 359 ++++++++++++++++++++++++--------------------------
 1 file changed, 171 insertions(+), 188 deletions(-)

diff --git a/src/rtl/fmc_arbiter.v b/src/rtl/fmc_arbiter.v
index d6fb950..037d640 100644
--- a/src/rtl/fmc_arbiter.v
+++ b/src/rtl/fmc_arbiter.v
@@ -7,7 +7,7 @@
 //
 //
 // Author: Pavel Shatov
-// Copyright (c) 2015, NORDUnet A/S All rights reserved.
+// 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
@@ -40,7 +40,6 @@
 module fmc_arbiter
   (
    // fmc bus
-   fmc_clk,
    fmc_a, fmc_d,
    fmc_ne1, fmc_nl, fmc_nwe, fmc_noe, fmc_nwait,
 
@@ -65,7 +64,6 @@ module fmc_arbiter
    //
    // Ports
    //
-   input        wire                     fmc_clk;
    input        wire [NUM_ADDR_BITS-1:0] fmc_a;
    inout        wire [             31:0] fmc_d;
    input        wire                     fmc_ne1;
@@ -89,8 +87,8 @@ module fmc_arbiter
 
    /* PHY is needed to control bi-directional data bus. */
 
-   wire [31: 0]                          d_ro;   // value read from pins (receiver output)
-   reg [31: 0]                           d_di;   // value drives onto pins (driver input)
+   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 #
      (
@@ -99,192 +97,177 @@ module fmc_arbiter
    d_phy
      (
       .buf_io(fmc_d),          // <-- connect directly to top-level bi-dir port
-      .buf_di(d_di),
-      .buf_ro(d_ro),
+      .buf_di(fmc_d_di),
+      .buf_ro(fmc_d_ro),
       .buf_t(fmc_noe)          // <-- bus direction is controlled by STM32
       );
 
-
-   //
-   // FSM
-   //
-   localparam   FMC_FSM_STATE_INIT              = 5'b0_0_000; // arbiter is idle
-
-   localparam   FMC_FSM_STATE_WRITE_START       = 5'b1_1_000; // got address to write at
-   localparam   FMC_FSM_STATE_WRITE_LATENCY_1   = 5'b1_1_001; // dummy state to compensate STM32's latency
-   localparam   FMC_FSM_STATE_WRITE_LATENCY_2   = 5'b1_1_010; // dummy state to compensate STM32's latency
-   localparam   FMC_FSM_STATE_WRITE_LATENCY_3   = 5'b1_1_011; // dummy state to compensate STM32's latency
-   localparam   FMC_FSM_STATE_WRITE_DATABEAT    = 5'b1_1_100; // got data to write
-   localparam   FMC_FSM_STATE_WRITE_WAIT        = 5'b1_1_101; // request to user-side logic sent
-   localparam   FMC_FSM_STATE_WRITE_DONE        = 5'b1_1_111; // user-side logic acknowledged transaction
-
-   localparam   FMC_FSM_STATE_READ_START        = 5'b1_0_000; // got address to read from
-   localparam   FMC_FSM_STATE_READ_LATENCY_1    = 5'b1_0_001; // dummy state to compensate STM32's latency
-   localparam   FMC_FSM_STATE_READ_LATENCY_2    = 5'b1_0_010; // dummy state to compensate STM32's latency
-   localparam   FMC_FSM_STATE_READ_LATENCY_3    = 5'b1_0_011; // dummy state to compensate STM32's latency
-   localparam   FMC_FSM_STATE_READ_WAIT         = 5'b1_0_101; // request to user-side logic sent
-   localparam   FMC_FSM_STATE_READ_READY        = 5'b1_0_110; // got acknowledge from user logic
-   localparam   FMC_FSM_STATE_READ_DATABEAT     = 5'b1_0_100; // returned data to master
-   localparam   FMC_FSM_STATE_READ_DONE         = 5'b1_0_111; // transaction complete
-
-   reg [              4:0]               fmc_fsm_state  = FMC_FSM_STATE_INIT;                   // fsm state
-   reg [NUM_ADDR_BITS-1:0]               fmc_addr_latch = {NUM_ADDR_BITS{1'bX}};                // transaction address
-   reg [             31:0]               fmc_data_latch = {32{1'bX}};                                           // write data latch
-
-   /* These flags are used to wake up from INIT state. */
-   wire                                  fmc_write_start_flag = (fmc_ne1 == 1'b0) && (fmc_nwe == 1'b0) && (fmc_nl == 1'b0);
-   wire                                  fmc_read_start_flag  = (fmc_ne1 == 1'b0) && (fmc_nwe == 1'b1) && (fmc_nl == 1'b0);
-
-   /* These are transaction response flag and data from user-side logic. */
-   wire                                  fmc_user_ack;
-   wire [31: 0]                          fmc_user_data;
-
-   //
-   // FSM Transition Logic
-   //
-   always @(posedge fmc_clk)
-     //
-     case (fmc_fsm_state)
-       //
-       // INIT -> WRITE, INIT -> READ
-       //
-       FMC_FSM_STATE_INIT: begin
-          //
-          if (fmc_write_start_flag)     fmc_fsm_state   <= FMC_FSM_STATE_WRITE_START;
-          if (fmc_read_start_flag)      fmc_fsm_state   <= FMC_FSM_STATE_READ_START;
-          //
-       end
-       //
-       // WRITE
-       //
-       FMC_FSM_STATE_WRITE_START:       fmc_fsm_state <= FMC_FSM_STATE_WRITE_LATENCY_1;
-       FMC_FSM_STATE_WRITE_LATENCY_1:   fmc_fsm_state <= FMC_FSM_STATE_WRITE_LATENCY_2;
-       FMC_FSM_STATE_WRITE_LATENCY_2:   fmc_fsm_state <= FMC_FSM_STATE_WRITE_LATENCY_3;
-       FMC_FSM_STATE_WRITE_LATENCY_3:   fmc_fsm_state <= FMC_FSM_STATE_WRITE_DATABEAT;
-       FMC_FSM_STATE_WRITE_DATABEAT:    fmc_fsm_state <= FMC_FSM_STATE_WRITE_WAIT;
-       FMC_FSM_STATE_WRITE_WAIT:        if (fmc_user_ack) fmc_fsm_state <= FMC_FSM_STATE_WRITE_DONE;
-       FMC_FSM_STATE_WRITE_DONE:        fmc_fsm_state <= FMC_FSM_STATE_INIT;
-       //
-       // READ
-       //
-       FMC_FSM_STATE_READ_START:        fmc_fsm_state <= FMC_FSM_STATE_READ_LATENCY_1;
-       FMC_FSM_STATE_READ_LATENCY_1:    fmc_fsm_state <= FMC_FSM_STATE_READ_LATENCY_2;
-       FMC_FSM_STATE_READ_LATENCY_2:    fmc_fsm_state <= FMC_FSM_STATE_READ_LATENCY_3;
-       FMC_FSM_STATE_READ_LATENCY_3:    fmc_fsm_state <= FMC_FSM_STATE_READ_WAIT;
-       FMC_FSM_STATE_READ_WAIT:         if (fmc_user_ack) fmc_fsm_state <= FMC_FSM_STATE_READ_READY;
-       FMC_FSM_STATE_READ_READY:        fmc_fsm_state <= FMC_FSM_STATE_READ_DATABEAT;
-       FMC_FSM_STATE_READ_DATABEAT:     fmc_fsm_state <= FMC_FSM_STATE_READ_DONE;
-       FMC_FSM_STATE_READ_DONE:         fmc_fsm_state <= FMC_FSM_STATE_INIT;
-       //
-       default:                                                                                                                 fmc_fsm_state   <= FMC_FSM_STATE_INIT;
-       //
-     endcase
-
-
-   //
-   // Address Latch
-   //
-   always @(posedge fmc_clk)
-     //
-     if ((fmc_fsm_state == FMC_FSM_STATE_INIT) && (fmc_write_start_flag || fmc_read_start_flag))
-       //
-       fmc_addr_latch <= fmc_a;
-
-
-   //
-   // Additional Write Logic (Data Latch)
-   //
-   always @(posedge fmc_clk)
-     //
-     if (fmc_fsm_state == FMC_FSM_STATE_WRITE_LATENCY_3)
-       //
-       fmc_data_latch <= d_ro;
-
-
-   //
-   // Additional Read Logic (Read Latch)
-   //
-
-   /* Note that this register is updated on the falling edge of FMC_CLK, because
-    * STM32 samples bi-directional data bus on the rising edge.
-    */
-
-   always @(negedge fmc_clk)
-     //
-     if (fmc_fsm_state == FMC_FSM_STATE_READ_DATABEAT)
-       //
-       d_di <= fmc_user_data;
-
-
-
-   //
-   // Wait Logic
-   //
-   reg  fmc_wait_reg    = 1'b0;
-
-   always @(posedge fmc_clk)
-     //
-     begin
-        //
-        if ( (fmc_fsm_state == FMC_FSM_STATE_WRITE_START) ||
-             (fmc_fsm_state == FMC_FSM_STATE_READ_START) )
-          fmc_wait_reg  <= 1'b1;                // start waiting for read/write to complete
-        /*
-         if ( (fmc_fsm_state == FMC_FSM_STATE_WRITE_DONE) ||
-         (fmc_fsm_state == FMC_FSM_STATE_READ_READY) )
-         fmc_wait_reg  <= 1'b0;
-         */
-        if (fmc_fsm_state == FMC_FSM_STATE_INIT)
-          fmc_wait_reg  <= 1'b0;                // fsm is idle, no need to wait any more
-        //
-     end
-
-   assign fmc_nwait = ~fmc_wait_reg;
-
-
-   /* These flags are used to generate 1-cycle pulses to trigger CDC
-    * transaction.  Note that FSM goes from WRITE_DATABEAT to WRITE_WAIT and from
-    * READ_LATENCY_3 to READ_WAIT unconditionally, so these flags will always be
-    * active for 1 cycle only, which is exactly what we need.
-    */
-
-   wire arbiter_write_req_pulse = (fmc_fsm_state == FMC_FSM_STATE_WRITE_DATABEAT)  ? 1'b1 : 1'b0;
-   wire arbiter_read_req_pulse  = (fmc_fsm_state == FMC_FSM_STATE_READ_LATENCY_3)  ? 1'b1 : 1'b0;
-
-   //
-   // CDC Block
-   //
-
-   /* This block is used to transfer request data from FMC_CLK clock domain to
-    * SYS_CLK clock domain and then transfer acknowledge from SYS_CLK to FMC_CLK
-    * clock domain in return. Af first 1+1+22+32 = 56 bits are transfered,
-    * these are: write flag, read flag, address, write data. During read transaction
-    * some bogus write data is passed, which is not used later anyway.
-    * During read requests 32 bits of data are returned, during write requests
-    * 32 bits of bogus data are returned, that are never used later.
-    */
-
-   fmc_arbiter_cdc #
-     (
-      .NUM_ADDR_BITS(NUM_ADDR_BITS)
-      )
-   fmc_cdc
-     (
-      .fmc_clk(fmc_clk),
-
-      .fmc_req(arbiter_write_req_pulse | arbiter_read_req_pulse),
-      .fmc_ack(fmc_user_ack),
-
-      .fmc_din({arbiter_write_req_pulse, arbiter_read_req_pulse, fmc_addr_latch, fmc_data_latch}),
-      .fmc_dout(fmc_user_data),
-
-      .sys_clk(sys_clk),
-      .sys_addr(sys_addr),
-      .sys_wren(sys_wr_en),
-      .sys_data_out(sys_data_out),
-      .sys_rden(sys_rd_en),
-      .sys_data_in(sys_data_in)
-      );
+    //
+    // 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



More information about the Commits mailing list