1 |
4 |
robfinch |
// ============================================================================
|
2 |
|
|
// __
|
3 |
|
|
// \\__/ o\ (C) 2023 Robert Finch, Waterloo
|
4 |
|
|
// \ __ / All rights reserved.
|
5 |
|
|
// \/_// robfinch@finitron.ca
|
6 |
|
|
// ||
|
7 |
|
|
//
|
8 |
|
|
//
|
9 |
|
|
// BSD 3-Clause License
|
10 |
|
|
// Redistribution and use in source and binary forms, with or without
|
11 |
|
|
// modification, are permitted provided that the following conditions are met:
|
12 |
|
|
//
|
13 |
|
|
// 1. Redistributions of source code must retain the above copyright notice, this
|
14 |
|
|
// list of conditions and the following disclaimer.
|
15 |
|
|
//
|
16 |
|
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
17 |
|
|
// this list of conditions and the following disclaimer in the documentation
|
18 |
|
|
// and/or other materials provided with the distribution.
|
19 |
|
|
//
|
20 |
|
|
// 3. Neither the name of the copyright holder nor the names of its
|
21 |
|
|
// contributors may be used to endorse or promote products derived from
|
22 |
|
|
// this software without specific prior written permission.
|
23 |
|
|
//
|
24 |
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
25 |
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
26 |
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
27 |
|
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
28 |
|
|
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
29 |
|
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
30 |
|
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
31 |
|
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
32 |
|
|
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
33 |
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34 |
|
|
//
|
35 |
|
|
// ============================================================================
|
36 |
|
|
//
|
37 |
|
|
|
38 |
|
|
module pci32_config(rst_i, clk_i, irq_i, irq_o, cs_config_i,
|
39 |
|
|
we_i, sel_i, adr_i, dat_i, dat_o, cs_bar0_o, cs_bar1_o, cs_bar2_o, irq_en_o);
|
40 |
|
|
input rst_i;
|
41 |
|
|
input clk_i;
|
42 |
|
|
input irq_i;
|
43 |
|
|
output reg [31:0] irq_o;
|
44 |
|
|
input cs_config_i;
|
45 |
|
|
input we_i;
|
46 |
|
|
input [3:0] sel_i;
|
47 |
|
|
input [31:0] adr_i;
|
48 |
|
|
input [31:0] dat_i;
|
49 |
|
|
output [31:0] dat_o;
|
50 |
|
|
output reg cs_bar0_o;
|
51 |
|
|
output reg cs_bar1_o;
|
52 |
|
|
output reg cs_bar2_o;
|
53 |
|
|
output reg irq_en_o;
|
54 |
|
|
|
55 |
|
|
parameter CFG_BUS = 8'd0;
|
56 |
|
|
parameter CFG_DEVICE = 5'd0;
|
57 |
|
|
parameter CFG_FUNC = 3'd0;
|
58 |
|
|
parameter CFG_VENDOR_ID = 16'h0;
|
59 |
|
|
parameter CFG_DEVICE_ID = 16'h0;
|
60 |
|
|
parameter CFG_SUBSYSTEM_VENDOR_ID = 16'h0;
|
61 |
|
|
parameter CFG_SUBSYSTEM_ID = 16'h0;
|
62 |
|
|
parameter CFG_BAR0 = 32'h1;
|
63 |
|
|
parameter CFG_BAR1 = 32'h1;
|
64 |
|
|
parameter CFG_BAR2 = 32'h1;
|
65 |
|
|
parameter CFG_BAR0_MASK = 32'h0;
|
66 |
|
|
parameter CFG_BAR1_MASK = 32'h0;
|
67 |
|
|
parameter CFG_BAR2_MASK = 32'h0;
|
68 |
|
|
parameter CFG_ROM_ADDR = 32'hFFFFFFF0;
|
69 |
|
|
|
70 |
|
|
parameter CFG_REVISION_ID = 8'd0;
|
71 |
|
|
parameter CFG_PROGIF = 8'd1;
|
72 |
|
|
parameter CFG_SUBCLASS = 8'h80; // 80 = Other
|
73 |
|
|
parameter CFG_CLASS = 8'h03; // 03 = display controller
|
74 |
|
|
parameter CFG_CACHE_LINE_SIZE = 8'd8; // 32-bit units
|
75 |
|
|
parameter CFG_MIN_GRANT = 8'h00;
|
76 |
|
|
parameter CFG_MAX_LATENCY = 8'h00;
|
77 |
|
|
parameter CFG_IRQ_LINE = 8'd16;
|
78 |
|
|
|
79 |
|
|
localparam CFG_HEADER_TYPE = 8'h00; // 00 = a general device
|
80 |
|
|
|
81 |
|
|
parameter MSIX = 1'b0;
|
82 |
|
|
|
83 |
|
|
integer n1;
|
84 |
|
|
reg [31:0] bar0;
|
85 |
|
|
reg [31:0] bar1;
|
86 |
|
|
reg [31:0] bar2;
|
87 |
|
|
reg [15:0] cmd_reg;
|
88 |
|
|
reg [15:0] cmdo_reg;
|
89 |
|
|
reg memory_space, io_space;
|
90 |
|
|
reg bus_master;
|
91 |
|
|
reg parity_err_resp;
|
92 |
|
|
reg serr_enable;
|
93 |
|
|
reg int_disable;
|
94 |
|
|
reg [7:0] latency_timer = 8'h00;
|
95 |
|
|
|
96 |
|
|
always_comb
|
97 |
|
|
begin
|
98 |
|
|
cmdo_reg = cmd_reg;
|
99 |
|
|
cmdo_reg[3] = 1'b0; // no special cycles
|
100 |
|
|
cmdo_reg[4] = 1'b0; // memory write and invalidate supported
|
101 |
|
|
cmdo_reg[5] = 1'b0; // VGA palette snoop
|
102 |
|
|
cmdo_reg[7] = 1'b0; // reserved bit
|
103 |
|
|
cmdo_reg[9] = 1'b1; // fast back-to-back enable
|
104 |
|
|
cmdo_reg[15:11] = 5'd0; // reserved
|
105 |
|
|
end
|
106 |
|
|
|
107 |
|
|
reg [15:0] stat_reg;
|
108 |
|
|
reg [15:0] stato_reg;
|
109 |
|
|
always_comb
|
110 |
|
|
begin
|
111 |
|
|
stato_reg = stat_reg;
|
112 |
|
|
stato_reg[2:0] = 3'b0; // reserved
|
113 |
|
|
stato_reg[3] = irq_i; // interrupt status
|
114 |
|
|
stato_reg[4] = 1'b0; // capabilities list
|
115 |
|
|
stato_reg[5] = 1'b1; // 66 MHz enable (N/A)
|
116 |
|
|
stato_reg[6] = 1'b0; // reserved
|
117 |
|
|
stato_reg[7] = 1'b1; // fast back-to-back capable
|
118 |
|
|
stato_reg[10:9] = 2'b01; // medium DEVSEL timing
|
119 |
|
|
end
|
120 |
|
|
|
121 |
|
|
reg [31:0] cfg_dat [0:63];
|
122 |
|
|
reg [31:0] cfg_out;
|
123 |
|
|
reg [7:0] irq_line;
|
124 |
|
|
|
125 |
|
|
initial begin
|
126 |
|
|
for (n1 = 0; n1 < 64; n1 = n1 + 1)
|
127 |
|
|
cfg_dat[n1] = 'd0;
|
128 |
|
|
end
|
129 |
|
|
|
130 |
|
|
wire cs = cs_config_i &&
|
131 |
|
|
adr_i[27:20]==CFG_BUS &&
|
132 |
|
|
adr_i[19:15]==CFG_DEVICE &&
|
133 |
|
|
adr_i[14:12]==CFG_FUNC;
|
134 |
|
|
|
135 |
|
|
always_ff @(posedge clk_i)
|
136 |
|
|
if (rst_i) begin
|
137 |
|
|
bar0 <= CFG_BAR0;
|
138 |
|
|
bar1 <= CFG_BAR1;
|
139 |
|
|
bar2 <= CFG_BAR2;
|
140 |
|
|
cmd_reg <= 16'h4003;
|
141 |
|
|
stat_reg <= 16'h0000;
|
142 |
|
|
irq_line <= CFG_IRQ_LINE;
|
143 |
|
|
end
|
144 |
|
|
else begin
|
145 |
|
|
io_space <= cmdo_reg[0];
|
146 |
|
|
memory_space <= cmdo_reg[1];
|
147 |
|
|
bus_master <= cmdo_reg[2];
|
148 |
|
|
parity_err_resp <= cmdo_reg[6];
|
149 |
|
|
serr_enable <= cmdo_reg[8];
|
150 |
|
|
int_disable <= cmdo_reg[10];
|
151 |
|
|
irq_en_o <= ~cmdo_reg[10];
|
152 |
|
|
|
153 |
|
|
if (cs) begin
|
154 |
|
|
if (we_i)
|
155 |
|
|
case(adr_i[7:2])
|
156 |
|
|
5'h02:
|
157 |
|
|
begin
|
158 |
|
|
if (sel_i[0]) cmd_reg[7:0] <= dat_i[7:0];
|
159 |
|
|
if (sel_i[1]) cmd_reg[15:8] <= dat_i[15:8];
|
160 |
|
|
if (sel_i[3]) begin
|
161 |
|
|
if (dat_i[8]) stat_reg[8] <= 1'b0;
|
162 |
|
|
if (dat_i[11]) stat_reg[11] <= 1'b0;
|
163 |
|
|
if (dat_i[12]) stat_reg[12] <= 1'b0;
|
164 |
|
|
if (dat_i[13]) stat_reg[13] <= 1'b0;
|
165 |
|
|
if (dat_i[14]) stat_reg[14] <= 1'b0;
|
166 |
|
|
if (dat_i[15]) stat_reg[15] <= 1'b0;
|
167 |
|
|
end
|
168 |
|
|
end
|
169 |
|
|
5'h04:
|
170 |
|
|
if (&sel_i[3:0] && dat_i[31:0]==32'hFFFFFFFF)
|
171 |
|
|
bar0 <= CFG_BAR0_MASK;
|
172 |
|
|
else begin
|
173 |
|
|
if (sel_i[0]) bar0[7:0] <= dat_i[7:0];
|
174 |
|
|
if (sel_i[1]) bar0[15:8] <= dat_i[15:8];
|
175 |
|
|
if (sel_i[2]) bar0[23:16] <= dat_i[23:16];
|
176 |
|
|
if (sel_i[3]) bar0[31:24] <= dat_i[31:24];
|
177 |
|
|
end
|
178 |
|
|
5'h05:
|
179 |
|
|
if (&sel_i[3:0] && dat_i[31:0]==32'hFFFFFFFF)
|
180 |
|
|
bar1 <= CFG_BAR1_MASK;
|
181 |
|
|
else begin
|
182 |
|
|
if (sel_i[0]) bar1[7:0] <= dat_i[7:0];
|
183 |
|
|
if (sel_i[1]) bar1[15:8] <= dat_i[15:8];
|
184 |
|
|
if (sel_i[2]) bar1[23:16] <= dat_i[23:16];
|
185 |
|
|
if (sel_i[3]) bar1[31:24] <= dat_i[31:24];
|
186 |
|
|
end
|
187 |
|
|
5'h06:
|
188 |
|
|
if (&sel_i[3:0] && dat_i[31:0]==32'hFFFFFFFF)
|
189 |
|
|
bar2 <= CFG_BAR2_MASK;
|
190 |
|
|
else begin
|
191 |
|
|
if (sel_i[0]) bar2[7:0] <= dat_i[7:0];
|
192 |
|
|
if (sel_i[1]) bar2[15:8] <= dat_i[15:8];
|
193 |
|
|
if (sel_i[2]) bar2[23:16] <= dat_i[23:16];
|
194 |
|
|
if (sel_i[3]) bar2[31:24] <= dat_i[31:24];
|
195 |
|
|
end
|
196 |
|
|
5'h0F:
|
197 |
|
|
if (sel_i[0]) irq_line <= dat_i[7:0];
|
198 |
|
|
default:
|
199 |
|
|
cfg_dat[adr_i[7:2]] <= dat_i;
|
200 |
|
|
endcase
|
201 |
|
|
else
|
202 |
|
|
case(adr_i[7:2])
|
203 |
|
|
5'h00: cfg_out <= {CFG_DEVICE_ID,CFG_VENDOR_ID};
|
204 |
|
|
5'h01: cfg_out <= {stato_reg,cmdo_reg};
|
205 |
|
|
5'h02: cfg_out <= {
|
206 |
|
|
CFG_CLASS,CFG_SUBCLASS,CFG_PROGIF,CFG_REVISION_ID};
|
207 |
|
|
5'h03: cfg_out <= {8'h00,
|
208 |
|
|
CFG_HEADER_TYPE,latency_timer,CFG_CACHE_LINE_SIZE};
|
209 |
|
|
5'h04: cfg_out <= bar0;
|
210 |
|
|
5'h05: cfg_out <= bar1;
|
211 |
|
|
5'h06: cfg_out <= bar2;
|
212 |
|
|
5'h07: cfg_out <= 32'hFFFFFFFF;
|
213 |
|
|
5'h08: cfg_out <= 32'hFFFFFFFF;
|
214 |
|
|
5'h09: cfg_out <= 32'hFFFFFFFF;
|
215 |
|
|
5'h0A: cfg_out <= 32'h0;
|
216 |
|
|
5'h0B: cfg_out <= {CFG_SUBSYSTEM_ID,CFG_SUBSYSTEM_VENDOR_ID};
|
217 |
|
|
5'h0C: cfg_out <= CFG_ROM_ADDR;
|
218 |
|
|
5'h0D: cfg_out <= 32'h0;
|
219 |
|
|
5'h0E: cfg_out <= 32'h0;
|
220 |
|
|
5'h0F: cfg_out <= {8'd8,8'd0,8'd0,irq_line};
|
221 |
|
|
default: cfg_out <= cfg_dat[adr_i[7:2]];
|
222 |
|
|
endcase
|
223 |
|
|
end
|
224 |
|
|
end
|
225 |
|
|
|
226 |
|
|
always_comb
|
227 |
|
|
irq_o = {31'd0,irq_i & ~int_disable} << irq_line;
|
228 |
|
|
|
229 |
|
|
always_comb
|
230 |
|
|
cs_bar0_o = ((adr_i ^ bar0) & CFG_BAR0_MASK) == 'd0;
|
231 |
|
|
always_comb
|
232 |
|
|
cs_bar1_o = ((adr_i ^ bar1) & CFG_BAR1_MASK) == 'd0;
|
233 |
|
|
always_comb
|
234 |
|
|
cs_bar2_o = ((adr_i ^ bar2) & CFG_BAR2_MASK) == 'd0;
|
235 |
|
|
|
236 |
|
|
endmodule
|