OpenCores
URL https://opencores.org/ocsvn/openarty/openarty/trunk

Subversion Repositories openarty

[/] [openarty/] [trunk/] [rtl/] [enetctrl.v] - Blame information for rev 30

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    enetctrl
4
//
5
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
6
//
7
// Purpose:     This module translates wishbone commands, whether they be read
8
//              or write commands, to MIO commands operating on an Ethernet
9
//      controller, such as the TI DP83848 controller on the Artix-7 Arty
10
//      development boarod (used by this project).  As designed, the bus
11
//      *will* stall until the command has been completed.
12
//
13
// Creator:     Dan Gisselquist, Ph.D.
14
//              Gisselquist Technology, LLC
15
//
16
////////////////////////////////////////////////////////////////////////////////
17
//
18
// Copyright (C) 2016, Gisselquist Technology, LLC
19
//
20
// This program is free software (firmware): you can redistribute it and/or
21
// modify it under the terms of  the GNU General Public License as published
22
// by the Free Software Foundation, either version 3 of the License, or (at
23
// your option) any later version.
24
//
25
// This program is distributed in the hope that it will be useful, but WITHOUT
26
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
27
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
28
// for more details.
29
//
30
// You should have received a copy of the GNU General Public License along
31
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
32
// target there if the PDF file isn't present.)  If not, see
33
// <http://www.gnu.org/licenses/> for a copy.
34
//
35
// License:     GPL, v3, as defined and found on www.gnu.org,
36
//              http://www.gnu.org/licenses/gpl.html
37
//
38
//
39
////////////////////////////////////////////////////////////////////////////////
40
//
41
//
42
`define ECTRL_RESET     3'h0
43
`define ECTRL_IDLE      3'h1
44
`define ECTRL_ADDRESS   3'h2
45
`define ECTRL_READ      3'h3
46
`define ECTRL_WRITE     3'h4
47
module  enetctrl(i_clk, i_rst,
48
                i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
49
                        o_wb_ack, o_wb_stall, o_wb_data,
50 30 dgisselq
                o_mdclk, o_mdio, i_mdio, o_mdwe,
51
                o_debug);
52 3 dgisselq
        parameter       CLKBITS=3; // = 3 for 200MHz source clock, 2 for 100 MHz
53
        input   i_clk, i_rst;
54
        input                   i_wb_cyc, i_wb_stb, i_wb_we;
55
        input           [4:0]    i_wb_addr;
56
        input           [15:0]   i_wb_data;
57
        output  reg             o_wb_ack, o_wb_stall;
58
        output  wire    [31:0]   o_wb_data;
59
        //
60
        input                   i_mdio;
61
        output  wire            o_mdclk;
62
        output  reg             o_mdio, o_mdwe;
63
        //
64 30 dgisselq
        output  wire    [31:0]   o_debug;
65
        //
66 3 dgisselq
        parameter       PHYADDR = 5'h01;
67
 
68
 
69
        reg             read_pending, write_pending;
70
        reg     [4:0]    r_addr;
71
        reg     [15:0]   read_reg, write_reg, r_data;
72
        reg     [2:0]    ctrl_state;
73
        reg     [5:0]    reg_pos;
74
        reg             zreg_pos;
75
        reg     [15:0]   r_wb_data;
76
 
77
 
78
        // Step 1: Generate our clock
79
        reg     [(CLKBITS-1):0]  clk_counter;
80
        initial         clk_counter = 0;
81
        always @(posedge i_clk)
82
                clk_counter <= clk_counter + 1;
83
        assign  o_mdclk = clk_counter[(CLKBITS-1)];
84
 
85
        // Step 2: Generate strobes for when to move, given the clock
86
        reg     rclk, zclk;
87
        initial zclk = 0;
88
        always @(posedge i_clk)
89 30 dgisselq
                zclk <= (&clk_counter[(CLKBITS-1):1])&&(!clk_counter[0]);
90 3 dgisselq
        initial rclk = 0;
91
        always @(posedge i_clk)
92
                rclk <= (~clk_counter[(CLKBITS-1)])&&(&clk_counter[(CLKBITS-2):0]);
93
 
94
        // Step 3: Read from our input port
95
        //      Note: I read on the falling edge, he changes on the rising edge
96 30 dgisselq
        reg     in_idle;
97 3 dgisselq
        always @(posedge i_clk)
98
                if (zclk)
99
                        read_reg <= { read_reg[14:0], i_mdio };
100
        always @(posedge i_clk)
101
                zreg_pos <= (reg_pos == 0);
102
 
103
        always @(posedge i_clk)
104
                if (rclk)
105
                        r_wb_data <= read_reg;
106
        assign  o_wb_data = { 16'h00, r_wb_data };
107
 
108
        // Step 4: Write to our output port
109
        //      Note: I change on the falling edge,
110
        always @(posedge i_clk)
111
                if (zclk)
112
                        o_mdio <= write_reg[15];
113
 
114
        initial in_idle = 1'b0;
115
        always @(posedge i_clk)
116
                in_idle <= (ctrl_state == `ECTRL_IDLE);
117
        initial o_wb_stall = 1'b0;
118
        always @(posedge i_clk)
119
                if (ctrl_state != `ECTRL_IDLE)
120
                        o_wb_stall <= 1'b1;
121
                else if (o_wb_ack)
122
                        o_wb_stall <= 1'b0;
123
                else if (((i_wb_stb)&&(in_idle))||(read_pending)||(write_pending))
124
                        o_wb_stall <= 1'b1;
125
                else    o_wb_stall <= 1'b0;
126
 
127
        initial read_pending  = 1'b0;
128
        initial write_pending = 1'b0;
129
        always @(posedge i_clk)
130
        begin
131
                r_addr <= i_wb_addr;
132
                if ((i_wb_stb)&&(~o_wb_stall))
133
                        r_data <= i_wb_data;
134
                if ((i_rst)||(ctrl_state == `ECTRL_READ)||(ctrl_state == `ECTRL_WRITE))
135
                begin
136
                        read_pending  <= 1'b0;
137
                        write_pending <= 1'b0;
138
                end else if ((i_wb_stb)&&(~o_wb_stall))
139
                begin
140
                        read_pending <= (~i_wb_we);
141
                        write_pending <= (i_wb_we);
142
                end
143
        end
144
 
145
        initial reg_pos = 6'h3f;
146
        initial ctrl_state = `ECTRL_RESET;
147
        initial write_reg = 16'hffff;
148
        always @(posedge i_clk)
149
        begin
150
                o_wb_ack <= 1'b0;
151 30 dgisselq
                if ((zclk)&&(!zreg_pos))
152 3 dgisselq
                        reg_pos <= reg_pos - 1;
153
                if (zclk)
154
                        write_reg <= { write_reg[14:0], 1'b1 };
155
                if (i_rst)
156
                begin // Must go for 167 ms before our 32 clocks
157
                        ctrl_state <= `ECTRL_RESET;
158
                        reg_pos <= 6'h3f;
159
                        write_reg[15:0] <= 16'hffff;
160
                end else case(ctrl_state)
161
                `ECTRL_RESET: begin
162
                        o_mdwe <= 1'b1; // Write
163
                        write_reg[15:0] <= 16'hffff;
164
                        if ((zclk)&&(zreg_pos))
165
                                ctrl_state <= `ECTRL_IDLE;
166
                        end
167
                `ECTRL_IDLE: begin
168
                        o_mdwe <= 1'b1; // Write
169
                        write_reg <= { 4'he, PHYADDR, r_addr, 2'b11 };
170
                        if (write_pending)
171 30 dgisselq
                        begin
172 3 dgisselq
                                write_reg[15:12] <= { 4'h5 };
173 30 dgisselq
                                write_reg[0] <= 1'b0;
174
                        end else if (read_pending)
175 3 dgisselq
                                write_reg[15:12] <= { 4'h6 };
176 30 dgisselq
                        if (!zclk)
177
                                write_reg[15] <= 1'b1;
178
                        reg_pos <= 6'h0f;
179
                        if ((zclk)&&(read_pending || write_pending))
180 3 dgisselq
                        begin
181
                                ctrl_state <= `ECTRL_ADDRESS;
182
                        end end
183
                `ECTRL_ADDRESS: begin
184
                        o_mdwe <= 1'b1; // Write
185
                        if ((zreg_pos)&&(zclk))
186
                        begin
187
                                reg_pos <= 6'h10;
188
                                if (read_pending)
189
                                        ctrl_state <= `ECTRL_READ;
190
                                else
191
                                        ctrl_state <= `ECTRL_WRITE;
192
                                write_reg <= r_data;
193
                        end end
194
                `ECTRL_READ: begin
195
                        o_mdwe <= 1'b0; // Read
196
                        if ((zreg_pos)&&(zclk))
197
                        begin
198
                                ctrl_state <= `ECTRL_IDLE;
199
                                o_wb_ack <= 1'b1;
200
                        end end
201
                `ECTRL_WRITE: begin
202
                        o_mdwe <= 1'b1; // Write
203
                        if ((zreg_pos)&&(zclk))
204
                        begin
205
                                ctrl_state <= `ECTRL_IDLE;
206
                                o_wb_ack <= 1'b1;
207
                        end end
208
                default: begin
209
                        o_mdwe <= 1'b0; // Read
210
                        reg_pos <= 6'h3f;
211
                        ctrl_state <= `ECTRL_RESET;
212
                        end
213
                endcase
214
        end
215
 
216 30 dgisselq
        assign  o_debug = {
217
                        o_wb_stall,i_wb_stb,i_wb_we, i_wb_addr, // 8 bits
218
                        o_wb_ack, rclk, o_wb_data[5:0],          // 8 bits
219
                        zreg_pos, zclk, reg_pos,                // 8 bits
220
                        read_pending, ctrl_state,               // 4 bits
221
                        o_mdclk, o_mdwe, o_mdio, i_mdio         // 4 bits
222
                };
223
 
224 3 dgisselq
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.