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

Subversion Repositories openarty

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

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

powered by: WebSVN 2.1.0

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