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

Subversion Repositories openarty

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

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 34 dgisselq
        parameter       CLKBITS=3, // = 3 for 200MHz source clock, 2 for 100 MHz
53
                        PHYADDR = 5'h01;
54 3 dgisselq
        input   i_clk, i_rst;
55
        input                   i_wb_cyc, i_wb_stb, i_wb_we;
56
        input           [4:0]    i_wb_addr;
57
        input           [15:0]   i_wb_data;
58
        output  reg             o_wb_ack, o_wb_stall;
59
        output  wire    [31:0]   o_wb_data;
60
        //
61
        input                   i_mdio;
62
        output  wire            o_mdclk;
63
        output  reg             o_mdio, o_mdwe;
64
        //
65 30 dgisselq
        output  wire    [31:0]   o_debug;
66
        //
67 3 dgisselq
 
68
        reg             read_pending, write_pending;
69
        reg     [4:0]    r_addr;
70
        reg     [15:0]   read_reg, write_reg, r_data;
71
        reg     [2:0]    ctrl_state;
72
        reg     [5:0]    reg_pos;
73
        reg             zreg_pos;
74
        reg     [15:0]   r_wb_data;
75
 
76
 
77
        // Step 1: Generate our clock
78
        reg     [(CLKBITS-1):0]  clk_counter;
79
        initial         clk_counter = 0;
80
        always @(posedge i_clk)
81
                clk_counter <= clk_counter + 1;
82
        assign  o_mdclk = clk_counter[(CLKBITS-1)];
83
 
84
        // Step 2: Generate strobes for when to move, given the clock
85
        reg     rclk, zclk;
86
        initial zclk = 0;
87
        always @(posedge i_clk)
88 30 dgisselq
                zclk <= (&clk_counter[(CLKBITS-1):1])&&(!clk_counter[0]);
89 3 dgisselq
        initial rclk = 0;
90
        always @(posedge i_clk)
91
                rclk <= (~clk_counter[(CLKBITS-1)])&&(&clk_counter[(CLKBITS-2):0]);
92
 
93
        // Step 3: Read from our input port
94
        //      Note: I read on the falling edge, he changes on the rising edge
95 30 dgisselq
        reg     in_idle;
96 3 dgisselq
        always @(posedge i_clk)
97
                if (zclk)
98
                        read_reg <= { read_reg[14:0], i_mdio };
99
        always @(posedge i_clk)
100
                zreg_pos <= (reg_pos == 0);
101
 
102
        always @(posedge i_clk)
103
                if (rclk)
104
                        r_wb_data <= read_reg;
105
        assign  o_wb_data = { 16'h00, r_wb_data };
106
 
107
        // Step 4: Write to our output port
108
        //      Note: I change on the falling edge,
109
        always @(posedge i_clk)
110
                if (zclk)
111
                        o_mdio <= write_reg[15];
112
 
113
        initial in_idle = 1'b0;
114
        always @(posedge i_clk)
115
                in_idle <= (ctrl_state == `ECTRL_IDLE);
116
        initial o_wb_stall = 1'b0;
117
        always @(posedge i_clk)
118
                if (ctrl_state != `ECTRL_IDLE)
119
                        o_wb_stall <= 1'b1;
120
                else if (o_wb_ack)
121
                        o_wb_stall <= 1'b0;
122
                else if (((i_wb_stb)&&(in_idle))||(read_pending)||(write_pending))
123
                        o_wb_stall <= 1'b1;
124
                else    o_wb_stall <= 1'b0;
125
 
126
        initial read_pending  = 1'b0;
127
        initial write_pending = 1'b0;
128
        always @(posedge i_clk)
129
        begin
130
                r_addr <= i_wb_addr;
131
                if ((i_wb_stb)&&(~o_wb_stall))
132
                        r_data <= i_wb_data;
133
                if ((i_rst)||(ctrl_state == `ECTRL_READ)||(ctrl_state == `ECTRL_WRITE))
134
                begin
135
                        read_pending  <= 1'b0;
136
                        write_pending <= 1'b0;
137
                end else if ((i_wb_stb)&&(~o_wb_stall))
138
                begin
139
                        read_pending <= (~i_wb_we);
140
                        write_pending <= (i_wb_we);
141
                end
142
        end
143
 
144
        initial reg_pos = 6'h3f;
145
        initial ctrl_state = `ECTRL_RESET;
146
        initial write_reg = 16'hffff;
147
        always @(posedge i_clk)
148
        begin
149
                o_wb_ack <= 1'b0;
150 30 dgisselq
                if ((zclk)&&(!zreg_pos))
151 3 dgisselq
                        reg_pos <= reg_pos - 1;
152
                if (zclk)
153
                        write_reg <= { write_reg[14:0], 1'b1 };
154
                if (i_rst)
155
                begin // Must go for 167 ms before our 32 clocks
156
                        ctrl_state <= `ECTRL_RESET;
157
                        reg_pos <= 6'h3f;
158
                        write_reg[15:0] <= 16'hffff;
159
                end else case(ctrl_state)
160
                `ECTRL_RESET: begin
161
                        o_mdwe <= 1'b1; // Write
162
                        write_reg[15:0] <= 16'hffff;
163
                        if ((zclk)&&(zreg_pos))
164
                                ctrl_state <= `ECTRL_IDLE;
165
                        end
166
                `ECTRL_IDLE: begin
167
                        o_mdwe <= 1'b1; // Write
168
                        write_reg <= { 4'he, PHYADDR, r_addr, 2'b11 };
169
                        if (write_pending)
170 30 dgisselq
                        begin
171 3 dgisselq
                                write_reg[15:12] <= { 4'h5 };
172 30 dgisselq
                                write_reg[0] <= 1'b0;
173
                        end else if (read_pending)
174 3 dgisselq
                                write_reg[15:12] <= { 4'h6 };
175 30 dgisselq
                        if (!zclk)
176
                                write_reg[15] <= 1'b1;
177
                        reg_pos <= 6'h0f;
178
                        if ((zclk)&&(read_pending || write_pending))
179 3 dgisselq
                        begin
180
                                ctrl_state <= `ECTRL_ADDRESS;
181
                        end end
182
                `ECTRL_ADDRESS: begin
183
                        o_mdwe <= 1'b1; // Write
184
                        if ((zreg_pos)&&(zclk))
185
                        begin
186
                                reg_pos <= 6'h10;
187
                                if (read_pending)
188
                                        ctrl_state <= `ECTRL_READ;
189
                                else
190
                                        ctrl_state <= `ECTRL_WRITE;
191
                                write_reg <= r_data;
192
                        end end
193
                `ECTRL_READ: begin
194
                        o_mdwe <= 1'b0; // Read
195
                        if ((zreg_pos)&&(zclk))
196
                        begin
197
                                ctrl_state <= `ECTRL_IDLE;
198
                                o_wb_ack <= 1'b1;
199
                        end end
200
                `ECTRL_WRITE: begin
201
                        o_mdwe <= 1'b1; // Write
202
                        if ((zreg_pos)&&(zclk))
203
                        begin
204
                                ctrl_state <= `ECTRL_IDLE;
205
                                o_wb_ack <= 1'b1;
206
                        end end
207
                default: begin
208
                        o_mdwe <= 1'b0; // Read
209
                        reg_pos <= 6'h3f;
210
                        ctrl_state <= `ECTRL_RESET;
211
                        end
212
                endcase
213
        end
214
 
215 30 dgisselq
        assign  o_debug = {
216
                        o_wb_stall,i_wb_stb,i_wb_we, i_wb_addr, // 8 bits
217
                        o_wb_ack, rclk, o_wb_data[5:0],          // 8 bits
218
                        zreg_pos, zclk, reg_pos,                // 8 bits
219
                        read_pending, ctrl_state,               // 4 bits
220
                        o_mdclk, o_mdwe, o_mdio, i_mdio         // 4 bits
221
                };
222
 
223 3 dgisselq
endmodule

powered by: WebSVN 2.1.0

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