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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [rtl/] [fastio.v] - Blame information for rev 50

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    fastio.v
4
//
5
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
6
//
7 49 dgisselq
// Purpose:     This file is used to group all of the simple I/O registers
8
//              together.  These are the I/O registers whose values can be
9
//      read without requesting it of any submodules, and that are guaranteed
10
//      not to stall the bus.  In general, these are items that can be read
11
//      or written in one clock (two, if an extra delay is needed to match
12
//      timing requirements).
13 3 dgisselq
//
14
// Creator:     Dan Gisselquist, Ph.D.
15
//              Gisselquist Technology, LLC
16
//
17
////////////////////////////////////////////////////////////////////////////////
18
//
19
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
20
//
21
// This program is free software (firmware): you can redistribute it and/or
22
// modify it under the terms of  the GNU General Public License as published
23
// by the Free Software Foundation, either version 3 of the License, or (at
24
// your option) any later version.
25
//
26
// This program is distributed in the hope that it will be useful, but WITHOUT
27
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
28
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
29
// for more details.
30
//
31
// You should have received a copy of the GNU General Public License along
32
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
33
// target there if the PDF file isn't present.)  If not, see
34
// <http://www.gnu.org/licenses/> for a copy.
35
//
36
// License:     GPL, v3, as defined and found on www.gnu.org,
37
//              http://www.gnu.org/licenses/gpl.html
38
//
39
//
40
////////////////////////////////////////////////////////////////////////////////
41
//
42
//
43
`include "builddate.v"
44
//
45
module  fastio(i_clk,
46
                // Board level I/O
47
                i_sw, i_btn, o_led,
48
                o_clr_led0, o_clr_led1, o_clr_led2, o_clr_led3,
49
                // Board level PMod I/O
50 34 dgisselq
                i_gpio, o_gpio,
51 3 dgisselq
                // Wishbone control
52
                i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr,
53
                        i_wb_data, o_wb_ack, o_wb_stall, o_wb_data,
54
                // Cross-board I/O
55 36 dgisselq
                i_rtc_ppd, i_buserr, i_gps_sub, i_gps_step, i_other_ints, o_bus_int, o_board_ints);
56 17 dgisselq
        parameter       AUXUART_SETUP = 30'd1736, // 115200 baud from 200MHz clk
57 25 dgisselq
                        GPSUART_SETUP = 30'd20833, // 9600 baud from 200MHz clk
58 34 dgisselq
                        EXTRACLOCK = 1, // Do we need an extra clock to process?
59
                        NGPI=0, NGPO=0; // Number of GPIO in and out wires
60 3 dgisselq
        input                   i_clk;
61
        // Board level I/O
62
        input           [3:0]    i_sw;
63
        input           [3:0]    i_btn;
64
        output  wire    [3:0]    o_led;
65 50 dgisselq
        output  wire    [2:0]    o_clr_led0;
66
        output  wire    [2:0]    o_clr_led1;
67
        output  wire    [2:0]    o_clr_led2;
68
        output  wire    [2:0]    o_clr_led3;
69 3 dgisselq
        // Board level PMod I/O
70
        //
71
        // GPIO
72 34 dgisselq
        input           [(NGPI-1):0]     i_gpio;
73 50 dgisselq
        output wire     [(NGPO-1):0]     o_gpio;
74 3 dgisselq
        //
75
        // Wishbone inputs
76
        input                   i_wb_cyc, i_wb_stb, i_wb_we;
77
        input           [4:0]    i_wb_addr;
78
        input           [31:0]   i_wb_data;
79
        // Wishbone outputs
80
        output  reg             o_wb_ack;
81
        output  wire            o_wb_stall;
82
        output  reg     [31:0]   o_wb_data;
83
        // A strobe at midnight, to keep the calendar on "time"
84
        input                   i_rtc_ppd;
85
        // Address of the last bus error
86
        input           [31:0]   i_buserr;
87 34 dgisselq
        // The current time, as produced by the GPS tracking processor
88 36 dgisselq
        input           [31:0]   i_gps_sub, i_gps_step;
89 3 dgisselq
        //
90
        // Interrupts -- both the output bus interrupt, as well as those
91
        //      internally generated interrupts which may be used elsewhere
92
        //      in the design
93 50 dgisselq
        input   wire    [11:0]   i_other_ints;
94 3 dgisselq
        output  wire            o_bus_int;
95 50 dgisselq
        output  wire    [2:0]    o_board_ints; // Button and switch interrupts
96 3 dgisselq
 
97 25 dgisselq
        wire    [31:0]   w_wb_data;
98
        wire    [4:0]    w_wb_addr;
99
        wire            w_wb_stb;
100
 
101
        generate
102
        if (EXTRACLOCK == 0)
103 3 dgisselq
        begin
104 25 dgisselq
                assign  w_wb_data = i_wb_data;
105
                assign  w_wb_addr = i_wb_addr;
106
                assign  w_wb_stb = (i_wb_stb)&&(i_wb_we);
107
        end else begin
108
                reg             last_wb_stb;
109
                reg     [4:0]    last_wb_addr;
110
                reg     [31:0]   last_wb_data;
111
                initial last_wb_stb = 1'b0;
112
                always @(posedge i_clk)
113
                begin
114
                        last_wb_addr <= i_wb_addr;
115
                        last_wb_data <= i_wb_data;
116
                        last_wb_stb  <= (i_wb_stb)&&(i_wb_we);
117
                end
118 3 dgisselq
 
119 25 dgisselq
                assign  w_wb_data = last_wb_data;
120
                assign  w_wb_addr = last_wb_addr;
121
                assign  w_wb_stb  = last_wb_stb;
122
        end endgenerate
123
 
124 3 dgisselq
        wire    [31:0]   pic_data;
125
        reg     sw_int, btn_int;
126
        wire    pps_int, rtc_int, netrx_int, nettx_int,
127 50 dgisselq
                gpsrx_int, auxrx_int, auxtx_int,
128
                gpio_int, flash_int, scop_int,
129
                sdcard_int, oled_int, zip_int;
130
        assign { zip_int,
131
                        gpsrx_int, auxtx_int, auxrx_int,
132
                        oled_int, rtc_int, sdcard_int,
133 3 dgisselq
                        nettx_int, netrx_int, scop_int, flash_int,
134
                        pps_int } = i_other_ints;
135
 
136 17 dgisselq
        //
137
        // The BUS Interrupt controller
138
        //
139 3 dgisselq
        icontrol #(15)  buspic(i_clk, 1'b0,
140 25 dgisselq
                (w_wb_stb)&&(w_wb_addr==5'h1),
141 3 dgisselq
                        i_wb_data, pic_data,
142 50 dgisselq
                { zip_int, oled_int, sdcard_int,
143 3 dgisselq
                        gpsrx_int, scop_int, flash_int, gpio_int,
144
                        auxtx_int, auxrx_int, nettx_int, netrx_int,
145
                        rtc_int, pps_int, sw_int, btn_int },
146
                        o_bus_int);
147
 
148
        // 
149
        // PWR Count
150
        // 
151
        // A 32-bit counter that starts at power up and never resets.  It's a
152
        // read only counter if you will.
153
        reg     [31:0]   pwr_counter;
154
        initial pwr_counter = 32'h00;
155
        always @(posedge i_clk)
156 34 dgisselq
                if (pwr_counter[31])
157 49 dgisselq
                        pwr_counter[30:0] <= pwr_counter[30:0] + 1'b1;
158 34 dgisselq
                else
159 49 dgisselq
                        pwr_counter[31:0] <= pwr_counter[31:0] + 1'b1;
160 3 dgisselq
 
161
        //
162 49 dgisselq
        // These pwr_counter bits are used for generating a PWM modulated
163
        // color LED output--allowing us to create multiple different, varied,
164
        // color LED "colors".  Here, we reverse the bits, to make their
165
        // transitions and PWM that much *less* noticable.  (a 50%
166
        // value, thus, is now an on-off-on-off-etc sequence, vice a 
167
        // sequence of 256 ons followed by a sequence of 256 offs --- it
168
        // places the transitions into a higher frequency bracket, and costs
169
        // us no logic to do--only a touch more pain to understand on behalf
170
        // of the programmer.)
171
        wire    [8:0]    rev_pwr_counter;
172
        assign rev_pwr_counter[8:0] = { pwr_counter[0],
173
                        pwr_counter[1], pwr_counter[2],
174
                        pwr_counter[3], pwr_counter[4],
175
                        pwr_counter[5], pwr_counter[6],
176
                        pwr_counter[7], pwr_counter[8] };
177
 
178
        //
179 3 dgisselq
        // BTNSW
180
        //
181
        // The button and switch control register
182
        wire    [31:0]   w_btnsw;
183
        reg     [3:0]    r_sw,  swcfg,  swnow,  swlast;
184
        reg     [3:0]    r_btn, btncfg, btnnow, btnlast, btnstate;
185
        initial btn_int = 1'b0;
186
        initial sw_int  = 1'b0;
187
        always @(posedge i_clk)
188
        begin
189
                r_sw <= i_sw;
190
                swnow <= r_sw;
191
                swlast<= swnow;
192
                sw_int <= |((swnow^swlast)|swcfg);
193
 
194 25 dgisselq
                if ((w_wb_stb)&&(w_wb_addr == 5'h4))
195
                        swcfg <= ((w_wb_data[3:0])&(w_wb_data[11:8]))
196
                                        |((~w_wb_data[3:0])&(swcfg));
197 3 dgisselq
 
198
                r_btn <= i_btn;
199
                btnnow <= r_btn;
200
                btn_int <= |(btnnow&btncfg);
201 25 dgisselq
                if ((w_wb_stb)&&(w_wb_addr == 5'h4))
202 3 dgisselq
                begin
203 25 dgisselq
                        btncfg <= ((w_wb_data[7:4])&(w_wb_data[15:12]))
204
                                        |((~w_wb_data[7:4])&(btncfg));
205
                        btnstate<= (btnnow)|((btnstate)&(~w_wb_data[7:4]));
206 3 dgisselq
                end else
207
                        btnstate <= (btnstate)|(btnnow);
208
        end
209
        assign  w_btnsw = { 8'h00, btnnow, 4'h0, btncfg, swcfg, btnstate, swnow };
210
 
211
        //
212
        // LEDCTRL
213
        //
214
        reg     [3:0]    r_leds;
215
        wire    [31:0]   w_ledreg;
216
        initial r_leds = 4'h0;
217
        always @(posedge i_clk)
218 25 dgisselq
                if ((w_wb_stb)&&(w_wb_addr == 5'h5))
219
                        r_leds <= ((w_wb_data[7:4])&(w_wb_data[3:0]))
220
                                |((~w_wb_data[7:4])&(r_leds));
221 3 dgisselq
        assign  o_led = r_leds;
222
        assign  w_ledreg = { 28'h0, r_leds  };
223
 
224
        //
225
        // GPIO
226
        //
227
        // Not used (yet), but this interface should allow us to control up to
228
        // 16 GPIO inputs, and another 16 GPIO outputs.  The interrupt trips
229
        // when any of the inputs changes.  (Sorry, which input isn't (yet)
230
        // selectable.)
231
        //
232 34 dgisselq
        wire    [31:0]   gpio_data;
233 50 dgisselq
        wbgpio  #(NGPI, NGPO)
234
                gpioi(i_clk, 1'b1, (w_wb_stb)&&(w_wb_addr == 5'h6), 1'b1,
235 34 dgisselq
                        w_wb_data, gpio_data, i_gpio, o_gpio, gpio_int);
236 3 dgisselq
 
237
        //
238
        // The Calendar DATE
239
        //
240
        wire    [31:0]   date_data;
241
`define GET_DATE
242
`ifdef  GET_DATE
243
        wire    date_ack, date_stall;
244
        rtcdate thedate(i_clk, i_rtc_ppd,
245 50 dgisselq
                i_wb_cyc, w_wb_stb, (w_wb_addr==5'h7), w_wb_data,
246 3 dgisselq
                        date_ack, date_stall, date_data);
247
`else
248 50 dgisselq
        assign  date_data = 32'h20170000;
249 3 dgisselq
`endif
250
 
251
        //
252 50 dgisselq
        // CLR LEDs
253 3 dgisselq
        //
254 50 dgisselq
        wire    [31:0]   w_clr_led0, w_clr_led1, w_clr_led2, w_clr_led3;
255
        clrled  clrled0(i_clk, (w_wb_stb)&&(w_wb_addr==5'h8), w_wb_data,
256
                                pwr_counter[8:0], w_clr_led0, o_clr_led0);
257
        clrled  clrled1(i_clk, (w_wb_stb)&&(w_wb_addr==5'h9), w_wb_data,
258
                                pwr_counter[8:0], w_clr_led1, o_clr_led1);
259
        clrled  clrled2(i_clk, (w_wb_stb)&&(w_wb_addr==5'ha), w_wb_data,
260
                                pwr_counter[8:0], w_clr_led2, o_clr_led2);
261
        clrled  clrled3(i_clk, (w_wb_stb)&&(w_wb_addr==5'hb), w_wb_data,
262
                                pwr_counter[8:0], w_clr_led3, o_clr_led3);
263 3 dgisselq
 
264 49 dgisselq
        reg     [32:0]   sec_step;
265
        initial sec_step = 33'h1;
266 3 dgisselq
        always @(posedge i_clk)
267 50 dgisselq
                if ((w_wb_stb)&&(w_wb_addr == 5'h0c))
268 49 dgisselq
                        sec_step <= { 1'b1, w_wb_data };
269
                else if (!pps_int)
270
                        sec_step <= 33'h1;
271
 
272
        reg     [31:0]   time_now_secs;
273
        initial time_now_secs = 32'h00;
274
        always @(posedge i_clk)
275
                if (pps_int)
276
                        time_now_secs <= time_now_secs + sec_step[31:0];
277
                else if (sec_step[32])
278
                        time_now_secs <= time_now_secs + sec_step[31:0];
279
 
280
        always @(posedge i_clk)
281 3 dgisselq
                case(i_wb_addr)
282
                5'h00: o_wb_data <= `DATESTAMP;
283
                5'h01: o_wb_data <= pic_data;
284
                5'h02: o_wb_data <= i_buserr;
285
                5'h03: o_wb_data <= pwr_counter;
286
                5'h04: o_wb_data <= w_btnsw;
287
                5'h05: o_wb_data <= w_ledreg;
288 50 dgisselq
                5'h06: o_wb_data <= date_data;
289
                5'h07: o_wb_data <= gpio_data;
290 3 dgisselq
                5'h08: o_wb_data <= w_clr_led0;
291
                5'h09: o_wb_data <= w_clr_led1;
292
                5'h0a: o_wb_data <= w_clr_led2;
293
                5'h0b: o_wb_data <= w_clr_led3;
294 50 dgisselq
                5'h0c: o_wb_data <= time_now_secs;
295
                5'h0d: o_wb_data <= i_gps_sub;
296
                5'h0e: o_wb_data <= i_gps_step;
297 3 dgisselq
                default: o_wb_data <= 32'h00;
298
                endcase
299
 
300
        assign  o_wb_stall = 1'b0;
301
        always @(posedge i_clk)
302
                o_wb_ack <= (i_wb_stb);
303 50 dgisselq
        assign  o_board_ints = { gpio_int, sw_int, btn_int };
304 3 dgisselq
 
305
 
306
endmodule

powered by: WebSVN 2.1.0

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