1 |
2 |
dgisselq |
///////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// Filename: ioslave
|
4 |
|
|
//
|
5 |
|
|
// Project: XuLA2 board
|
6 |
|
|
//
|
7 |
|
|
// Purpose: This handles a bunch of small, simple I/O registers. To be
|
8 |
|
|
// included here, the I/O register must take exactly a single
|
9 |
|
|
// clock to access and never stall.
|
10 |
|
|
//
|
11 |
|
|
// Particular peripherals include:
|
12 |
|
|
// - the interrupt controller
|
13 |
|
|
// - Realtime Clock
|
14 |
|
|
// - Realtime clock Date
|
15 |
|
|
// - A bus error register--records the address of the last
|
16 |
|
|
// bus error. Cannot be written to, save by a bus error.
|
17 |
|
|
// Other peripherals have been removed due to a lack of bus address space.
|
18 |
|
|
//
|
19 |
|
|
//
|
20 |
|
|
// Creator: Dan Gisselquist, Ph.D.
|
21 |
|
|
// Gisselquist Technology, LLC
|
22 |
|
|
//
|
23 |
|
|
///////////////////////////////////////////////////////////////////////////
|
24 |
|
|
//
|
25 |
|
|
// Copyright (C) 2015, Gisselquist Technology, LLC
|
26 |
|
|
//
|
27 |
|
|
// This program is free software (firmware): you can redistribute it and/or
|
28 |
|
|
// modify it under the terms of the GNU General Public License as published
|
29 |
|
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
30 |
|
|
// your option) any later version.
|
31 |
|
|
//
|
32 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
33 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
34 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
35 |
|
|
// for more details.
|
36 |
|
|
//
|
37 |
|
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
38 |
|
|
// http://www.gnu.org/licenses/gpl.html
|
39 |
|
|
//
|
40 |
|
|
//
|
41 |
|
|
///////////////////////////////////////////////////////////////////////////
|
42 |
|
|
//
|
43 |
|
|
//
|
44 |
|
|
`include "builddate.v"
|
45 |
|
|
module ioslave(i_clk,
|
46 |
|
|
// Wishbone control
|
47 |
|
|
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
|
48 |
|
|
o_wb_ack, o_wb_stall, o_wb_data,
|
49 |
|
|
// GPIO wires
|
50 |
|
|
i_gpio,
|
51 |
|
|
o_gpio,
|
52 |
|
|
// Other registers
|
53 |
|
|
i_bus_err_addr,
|
54 |
|
|
brd_interrupts, o_ints_to_zip_cpu, o_interrupt);
|
55 |
|
|
parameter NGPO=15, NGPI=15;
|
56 |
|
|
input i_clk;
|
57 |
|
|
// Wishbone control
|
58 |
|
|
// inputs...
|
59 |
|
|
input i_wb_cyc, i_wb_stb, i_wb_we;
|
60 |
|
|
input [4:0] i_wb_addr;
|
61 |
|
|
input [31:0] i_wb_data;
|
62 |
|
|
// outputs...
|
63 |
|
|
output reg o_wb_ack;
|
64 |
|
|
output wire o_wb_stall;
|
65 |
|
|
output wire [31:0] o_wb_data;
|
66 |
|
|
// GPIO
|
67 |
|
|
input [(NGPI-1):0] i_gpio;
|
68 |
|
|
output wire [(NGPO-1):0] o_gpio;
|
69 |
|
|
// Other registers
|
70 |
|
|
input [31:0] i_bus_err_addr;
|
71 |
|
|
input [5:0] brd_interrupts;
|
72 |
|
|
output wire [7:0] o_ints_to_zip_cpu;
|
73 |
|
|
output wire o_interrupt;
|
74 |
|
|
|
75 |
|
|
|
76 |
|
|
wire i_uart_rx_int, i_uart_tx_int, i_scop_int, i_flash_int,i_pwm_int;
|
77 |
|
|
assign i_uart_tx_int = brd_interrupts[5];
|
78 |
|
|
assign i_uart_rx_int = brd_interrupts[4];
|
79 |
|
|
assign i_pwm_int = brd_interrupts[3];
|
80 |
|
|
assign i_scop_int = brd_interrupts[2];
|
81 |
|
|
assign i_flash_int = brd_interrupts[1];
|
82 |
|
|
|
83 |
|
|
// reg [31:0] pwrcount;
|
84 |
|
|
// reg [31:0] rtccount;
|
85 |
|
|
wire [31:0] ictrl_data, gpio_data, date_data;
|
86 |
|
|
|
87 |
|
|
reg [31:0] r_wb_data;
|
88 |
|
|
reg r_wb_addr;
|
89 |
|
|
always @(posedge i_clk)
|
90 |
|
|
begin
|
91 |
|
|
r_wb_addr <= i_wb_addr[4];
|
92 |
|
|
// if ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_we)&&(~i_wb_addr[4]))
|
93 |
|
|
// begin
|
94 |
|
|
// casez(i_wb_addr[3:0])
|
95 |
|
|
// // 4'h0: begin end // Reset register
|
96 |
|
|
// // 4'h1: begin end // Status/Control register
|
97 |
|
|
// // 4'h2: begin end // Reset register
|
98 |
|
|
// // 4'h3: begin end // Interrupt Control register
|
99 |
|
|
// // 4'h4: // R/O Power count
|
100 |
|
|
// // 4'h5: // RTC count
|
101 |
|
|
// default: begin end
|
102 |
|
|
// endcase
|
103 |
|
|
// end else
|
104 |
|
|
if ((i_wb_cyc)&&(i_wb_stb)&&(~i_wb_we))
|
105 |
|
|
begin
|
106 |
|
|
casez(i_wb_addr[3:0])
|
107 |
|
|
4'h02: r_wb_data <= `DATESTAMP;
|
108 |
|
|
4'h03: r_wb_data <= ictrl_data;
|
109 |
|
|
4'h04: r_wb_data <= i_bus_err_addr;
|
110 |
|
|
4'h05: r_wb_data <= date_data;
|
111 |
|
|
4'h06: r_wb_data <= gpio_data;
|
112 |
|
|
default: r_wb_data <= 32'h0000;
|
113 |
|
|
endcase
|
114 |
|
|
end
|
115 |
|
|
end
|
116 |
|
|
|
117 |
|
|
// The interrupt controller
|
118 |
|
|
wire ck_int;
|
119 |
|
|
wire [7:0] interrupt_vector;
|
120 |
|
|
assign interrupt_vector = {
|
121 |
|
|
i_uart_tx_int, i_uart_rx_int, i_pwm_int, gpio_int,
|
122 |
|
|
i_scop_int, i_flash_int, ck_int, brd_interrupts[0] };
|
123 |
|
|
icontrol #(8) intcontroller(i_clk, 1'b0,
|
124 |
|
|
((i_wb_cyc)&&(i_wb_stb)&&(i_wb_we)
|
125 |
|
|
&&(i_wb_addr==5'h3)), i_wb_data,
|
126 |
|
|
ictrl_data, interrupt_vector,
|
127 |
|
|
o_interrupt);
|
128 |
|
|
|
129 |
|
|
/*
|
130 |
|
|
// The ticks since power up register
|
131 |
|
|
initial pwrcount = 32'h00;
|
132 |
|
|
always @(posedge i_clk)
|
133 |
|
|
if (~ (&pwrcount))
|
134 |
|
|
pwrcount <= pwrcount+1;
|
135 |
|
|
|
136 |
|
|
// The time since power up register
|
137 |
|
|
reg [15:0] subrtc;
|
138 |
|
|
reg subpps;
|
139 |
|
|
initial rtccount = 32'h00;
|
140 |
|
|
initial subrtc = 16'h00;
|
141 |
|
|
always @(posedge i_clk)
|
142 |
|
|
{ subpps, subrtc } <= subrtc + 16'd43;
|
143 |
|
|
always @(posedge i_clk)
|
144 |
|
|
rtccount <= rtccount + ((subpps)? 32'h1 : 32'h0);
|
145 |
|
|
*/
|
146 |
|
|
|
147 |
|
|
//
|
148 |
|
|
// GPIO controller
|
149 |
|
|
//
|
150 |
|
|
wire gpio_int;
|
151 |
|
|
wbgpio #(NGPI, NGPO)
|
152 |
|
|
gpiodev(i_clk, i_wb_cyc, (i_wb_stb)&&(i_wb_addr[4:0]==5'h6),
|
153 |
|
|
i_wb_we, i_wb_data, gpio_data, i_gpio, o_gpio,gpio_int);
|
154 |
|
|
|
155 |
|
|
//
|
156 |
|
|
// 4'b1xxx
|
157 |
|
|
// BUS access to a real time clock (not calendar, just clock)
|
158 |
|
|
//
|
159 |
|
|
//
|
160 |
|
|
wire [31:0] ck_data;
|
161 |
|
|
wire ck_ppd;
|
162 |
9 |
dgisselq |
rtclight
|
163 |
|
|
#(32'h388342) // 76 MHz clock (2^48 / 76e6)
|
164 |
|
|
// #(32'h35afe5) // 80 MHz clock
|
165 |
|
|
// #(32'h2eaf36) // 92 MHz clock
|
166 |
|
|
// #(32'h2af31d) // 100 MHz clock
|
167 |
2 |
dgisselq |
theclock(i_clk, i_wb_cyc, (i_wb_stb)&&(i_wb_addr[4]),
|
168 |
|
|
i_wb_we, i_wb_addr[2:0], i_wb_data,
|
169 |
|
|
ck_data, ck_int, ck_ppd);
|
170 |
|
|
|
171 |
|
|
wire date_ack, date_stall;
|
172 |
|
|
rtcdate thedate(i_clk, ck_ppd,
|
173 |
|
|
i_wb_cyc, (i_wb_stb)&&(i_wb_addr[3:0]==4'h5),
|
174 |
|
|
i_wb_we, i_wb_data,
|
175 |
|
|
date_ack, date_stall, date_data);
|
176 |
|
|
|
177 |
|
|
always @(posedge i_clk)
|
178 |
|
|
o_wb_ack <= (i_wb_stb)&&(i_wb_cyc);
|
179 |
|
|
assign o_wb_stall = 1'b0;
|
180 |
|
|
|
181 |
|
|
assign o_wb_data = (r_wb_addr)? ck_data : r_wb_data;
|
182 |
|
|
|
183 |
|
|
//
|
184 |
|
|
//
|
185 |
|
|
assign o_ints_to_zip_cpu = { i_uart_tx_int, i_uart_rx_int,
|
186 |
|
|
i_pwm_int, gpio_int, i_scop_int, i_flash_int,
|
187 |
|
|
ck_int, o_interrupt };
|
188 |
|
|
endmodule
|