From 5723ec1a34181f1cfef9b8e870ab2e9a0362487c Mon Sep 17 00:00:00 2001 From: mindchasers Date: Wed, 1 May 2019 18:16:45 -0400 Subject: initial commit, all basic functions work on Darsena V02 --- source/mdio_cont.v | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 source/mdio_cont.v (limited to 'source/mdio_cont.v') 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 -- cgit v1.2.3-8-gadcc