ide_dev.v
4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// ide_dev.v v1 Frank Berndt
// ide bus devices that support dv;
// :set tabstop=4
module ide_dev (
sysclk, reset_l,
io_rst, io_ad, io_ale, io_cs, io_ior, io_iow, io_intr, gpio,
);
input sysclk; // system clock;
input reset_l; // system reset;
// io bus;
input io_rst; // io reset;
inout [15:0] io_ad; // io ad bus;
input io_ale; // address latch enable;
input [3:0] io_cs; // chip selects;
input io_ior; // read pulse;
input io_iow; // write pulse;
input io_intr; // io interrupt;
inout [3:0] gpio; // gpio bus;
// latch io bus address;
reg [15:0] io_addr; // latched io address;
always @(negedge io_ale)
io_addr <= io_ad;
// io bus debug printf;
// io_cs[3] (debug port) and address `PI_PRINTF;
// io_ad[7:0] contains the character;
// write chars into line buffer, dump on \n;
// flush printf buffer on io reset;
reg [7:0] prf_buf [0:127]; // printf buffer;
integer prf_nc; // # of chars in printf buffer;
reg [7:0] prf_char; // current char;
always @(io_rst)
begin
if(io_rst !== 1'b1)
prf_nc = 0;
end
task printf;
reg [7:0] c;
integer n;
begin
$write("%t: %M: ", $time);
for(n = 0; n < prf_nc; n = n + 1)
$write("%0s", prf_buf[n]);
$display("");
end
endtask
// decode accesses to simulator debug space;
wire dbg_spc;
assign dbg_spc = (io_rst === 1'b1) & (io_cs[3] === 1'b0);
always @(posedge io_iow)
begin
if(dbg_spc & (io_addr === 16'hfff0)) begin
prf_char = io_ad[7:0];
if(prf_char === 8'h0a) begin
printf;
prf_nc = 0;
end else if(prf_nc < 127) begin
prf_buf[prf_nc] = prf_char;
prf_nc = prf_nc + 1;
end
end
end
// io bus dump control;
// io_cs[3] (debug port) and address `PI_DUMP;
// io_ad[0] turns dump on or off;
always @(posedge io_iow)
begin
if(dbg_spc & (io_addr === 16'hfff1))
vsim.dump.dump = io_ad[0];
end
// flash module presence
// io_cs[3] (debug port) and address `PI_MODULE;
// io_ad[0] controls module presence
always @(posedge io_iow)
begin
if(dbg_spc & (io_addr === 16'hfff2))
vsim.mm.fl_md = io_ad[0];
end
// flash module insertion/removal sequencer;
// io_cs[3] (debug port) and address;
// PI_MD_PTR sets list pointer to 0;
// PI_MD_VAL writes write data to list;
// PI_MD_TRIG triggers md sequence;
wire [2:0] md_addr;
wire md_rd;
assign md_addr[0] = (io_addr === 16'hfff4);
assign md_addr[1] = (io_addr === 16'hfff3);
assign md_addr[2] = (io_addr === 16'hfff5);
always @(posedge io_iow)
begin
if(dbg_spc & md_addr[0]) begin
vsim.mm.md_ioptr = 0;
vsim.mm.md_iolist[0] = 0;
end
if(dbg_spc & md_addr[1]) begin
vsim.mm.md_iolist[vsim.mm.md_ioptr] = io_ad[15:0];
vsim.mm.md_ioptr = vsim.mm.md_ioptr + 1;
end
if(dbg_spc & md_addr[2])
vsim.mm.md_busy = 1;
end
assign md_rd = dbg_spc & ~io_ior & |md_addr;
assign io_ad = md_rd? { 15'd0, vsim.mm.md_busy } : 16'bz;
// set board_id;
always @(posedge io_iow)
begin
if(dbg_spc & (io_addr === 16'hfff6))
vsim.board_id = io_ad[15:6];
end
// pin reset backdoor;
// io_cs[3] (debug port) and address `PI_PINRST;
// do full pin reset;
always @(posedge io_iow)
begin
if(dbg_spc & (io_addr === 16'hffff)) begin
vsim.rst_l = 0;
repeat(16) @(posedge sysclk);
vsim.rst_l = 1;
end
end
// pwr_gd button backdoor
// io_cs[3] (debug port) and address `PI_PINBTN
always @(posedge io_iow)
begin
if (dbg_spc & (io_addr == 16'hfffe))
begin
repeat (20)
@(posedge sysclk)
;
vsim.button = 1'b1 ;
repeat (20)
@(posedge sysclk)
;
vsim.button = 1'b0 ;
end
end
// backdoor to halt simulator
// io_cs[3] (debug port) and address `PI_SIMHLT
always @(posedge io_iow)
begin
if (dbg_spc & (io_addr == 16'hfffd))
begin
$display("%t: %M: simulator termination", $time);
repeat(32) @(posedge sysclk);
$finish;
end
end
// gpio backdoor;
// same as PI_GPIO;
wire gpio_spc; // gpio debug space;
wire gpio_rd; // read gpio bits;
reg [3:0] gpio_oe; // ide side output enables;
reg [3:0] gpio_out; // ide side gpio outputs;
assign gpio_spc = dbg_spc & (io_addr === 16'hfffc);
always @(posedge sysclk or io_rst)
begin
if(io_rst !== 1'b1)
{ gpio_oe, gpio_out } <= 8'd0;
end
always @(posedge io_iow)
begin
if(gpio_spc)
{ gpio_oe, gpio_out } <= io_ad[7:0];
end
assign gpio_rd = gpio_spc & ~io_ior;
assign io_ad = gpio_rd? { 8'd0, gpio_oe, gpio } : 16'bz;
assign gpio[3] = gpio_oe[3]? gpio_out[3] : 'bz;
assign gpio[2] = gpio_oe[2]? gpio_out[2] : 'bz;
assign gpio[1] = gpio_oe[1]? gpio_out[1] : 'bz;
assign gpio[0] = gpio_oe[0]? gpio_out[0] : 'bz;
endmodule