summaryrefslogtreecommitdiffhomepage
path: root/source/mdio_cont.v
diff options
context:
space:
mode:
Diffstat (limited to 'source/mdio_cont.v')
-rw-r--r--source/mdio_cont.v159
1 files changed, 159 insertions, 0 deletions
diff --git a/source/mdio_cont.v b/source/mdio_cont.v
new file mode 100644
index 0000000..ad595fd
--- /dev/null
+++ b/source/mdio_cont.v
@@ -0,0 +1,159 @@
+/*
+ * mdio_cont.v
+ *
+ * Copyright (C) 2018, 2019 Mind Chasers Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * function: MDIO controller / state machine
+ *
+ */
+
+`timescale 1ns /10ps
+
+module mdio_controller #(parameter ADDR_SZ = 6)
+(
+
+ // system interface
+ input rstn,
+ input clk, // mdio mdc clock
+
+ // worker interface
+ input work_start,
+ output reg work_run,
+ output reg work_done,
+ input [ADDR_SZ-1:0] routine_addr,
+
+ // arbitration
+ input buffer_full,
+
+ // memory interface
+ output reg [ADDR_SZ-1:0] addr, // controller address
+ input [7:0] di, // controller data bus
+
+ // mdio interface
+ output reg [4:0] reg_addr,
+ output reg [15:0] dout, // data output ( for writes )
+ output ld, // load control / address,
+ output reg rwn, // read / write not
+ input done
+);
+
+ localparam ST_SZ = 4;
+ reg [ST_SZ-1:0] cont_state;
+ wire ld_dl, ld_dh;
+
+
+ // state encoding
+ localparam S0= 4'h0, S1=4'h1, S2=4'h2, S3=4'h3,
+ S4= 4'h4, S5=4'h5, S6=4'h6, S7=4'h7,
+ S8 = 4'h8;
+
+
+ /*
+ * keep running until an eop is found
+ */
+ always @(posedge clk or negedge rstn)
+ begin
+ if (!rstn)
+ cont_state <= S0;
+ else
+ case (cont_state)
+ S0: if (work_start == 1'b1) cont_state <= S1;
+ S1: cont_state <= S2;
+ S2: if ( work_done == 1'b1 ) cont_state <= S0;
+ else if ( buffer_full ) cont_state <= S2; // wait for the fifo to empty out
+ else if ( ~rwn ) cont_state <= S3;
+ else cont_state <= S6;
+ S3: cont_state <= S4;
+ S4: cont_state <= S5;
+ S5: cont_state <= S6;
+ S6: cont_state <= S7;
+ S7: if ( done == 1'b1 ) cont_state <= S8;
+ S8: cont_state <= S1;
+ endcase
+ end
+
+ /* read the eop bit during S1 */
+ always @(posedge clk or negedge rstn)
+ begin
+ if ( !rstn )
+ work_done <= 1'b0;
+ else if ( cont_state == S1 && di[7] == 1'b1 )
+ work_done <= 1'b1;
+ else
+ work_done <= 1'b0;
+ end
+
+ /* work_run */
+ always @(posedge clk or negedge rstn)
+ begin
+ if ( !rstn )
+ work_run <= 1'b0;
+ else if ( work_start == 1'b1 )
+ work_run <= 1'b1;
+ else if ( work_done == 1'b1 )
+ work_run <= 1'b0;
+ end
+
+ /* set RWN for duration of cyle */
+ always @(posedge clk or negedge rstn)
+ begin
+ if ( rstn == 1'b0 || work_done ==1'b1 )
+ begin
+ rwn <= 1'b1;
+ end
+ else if ( cont_state == S1 )
+ begin
+ rwn <= di[5];
+ end
+ end
+
+ /* reg_addr is the mdio register address */
+ always @(posedge clk or negedge rstn)
+ begin
+ if ( rstn == 1'b0 || work_done ==1'b1 )
+ reg_addr <= 5'h0;
+ else if ( cont_state == S1 )
+ reg_addr <= di[4:0];
+ end
+
+ /* addr is the program address */
+ always @(posedge clk or negedge rstn)
+ begin
+ if (rstn == 1'b0 || work_done == 1'b1 )
+ addr <= 0;
+ else if ( work_start == 1'b1 )
+ addr <= routine_addr[ADDR_SZ-1:0];
+ else if ( cont_state == S3 || cont_state == S4 || cont_state == S8 )
+ addr <= addr + 1;
+ end
+
+ // latch the write data to mdio
+ always @(posedge clk or negedge rstn)
+ begin
+ if (rstn == 0)
+ dout <= 16'h0000;
+ else if ( ld_dl == 1'b1 )
+ dout[7:0] <= di;
+ else if ( ld_dh == 1'b1 )
+ dout[15:8] <= di;
+ end
+
+ // combinatorial logic here
+ assign ld_dl = ( cont_state == S4 ) ? 1'b1 : 1'b0;
+ assign ld_dh = ( cont_state == S5 ) ? 1'b1 : 1'b0;
+ assign ld = ( cont_state == S6 ) ? 1'b1 : 1'b0;
+
+
+endmodule