Rev 119 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
116 | lvd | 1 | // part of NeoGS flash programmer project (c) 2014 lvd^NedoPC |
2 | // |
||
3 | // zxbus controller |
||
4 | |||
5 | module zxbus |
||
6 | ( |
||
7 | input wire clk, |
||
8 | input wire rst_n, |
||
9 | |||
117 | lvd | 10 | inout wire [7:0] zxid, // zxbus DATA BUS in/out [7:0] |
11 | input wire [7:0] zxa, // zxbus ADDRESS 7-0 in [7:0] |
||
12 | input wire zxiorq_n, |
||
13 | input wire zxmreq_n, |
||
14 | input wire zxrd_n, |
||
15 | input wire zxwr_n, |
||
16 | output wire zxblkiorq_n, // active low - signal to generate IORQGE |
||
17 | output reg zxbusin, // controls 74hct245 buffer direction (1 - input from bus, 0 - output to zx) |
||
18 | output reg zxbusena_n, // 74hct245 buffer enable signal |
||
116 | lvd | 19 | |
117 | lvd | 20 | output reg init, // positive pulse to cause reset/init to all board |
21 | input wire init_in_progress, // 1 while init in progress |
||
116 | lvd | 22 | |
117 | lvd | 23 | output reg led, // LED state |
116 | lvd | 24 | |
121 | lvd | 25 | output reg autoinc_ena, // enable autoincrement |
26 | |||
117 | lvd | 27 | output reg wr_addr, // to ROM controller |
28 | output reg wr_data, // |
||
29 | output reg rd_data, // |
||
30 | output reg [7:0] wr_buffer, // |
||
31 | input wire [7:0] rd_buffer // |
||
116 | lvd | 32 | ); |
33 | |||
117 | lvd | 34 | wire iowr = ~(zxiorq_n | zxwr_n); |
35 | wire iord = ~(zxiorq_n | zxrd_n); |
||
116 | lvd | 36 | |
117 | lvd | 37 | reg [2:0] iowr_r; |
38 | reg [2:0] iord_r; |
||
39 | |||
40 | wire iowr_begin, iowr_end; |
||
41 | wire iord_begin, iord_end; |
||
42 | |||
43 | wire io_begin, io_end; |
||
44 | |||
45 | wire addr_ok; |
||
46 | |||
119 | lvd | 47 | reg wrr; |
117 | lvd | 48 | |
119 | lvd | 49 | |
117 | lvd | 50 | wire [1:0] regsel; |
51 | |||
52 | |||
53 | reg [7:0] read_data; |
||
54 | |||
55 | |||
56 | reg zxid_oe; |
||
57 | reg [7:0] zxid_out; |
||
58 | wire [7:0] zxid_in; |
||
59 | |||
60 | |||
61 | |||
62 | reg [8:0] test_reg; |
||
63 | reg [7:0] test_reg_pre; |
||
64 | reg test_reg_write; |
||
65 | |||
66 | |||
67 | |||
68 | |||
69 | |||
70 | // register select (one of 4) |
||
71 | assign regsel[1:0] = { zxa[7], zxa[3] }; |
||
72 | |||
73 | |||
74 | |||
75 | // addr decode |
||
76 | assign addr_ok = (zxa==8'h33) || (zxa==8'h3B) || (zxa==8'hB3) || (zxa==8'hBB); |
||
77 | |||
78 | // IORQGE |
||
79 | assign zxblkiorq_n = ~addr_ok; |
||
80 | |||
81 | |||
82 | // internal data bus control |
||
83 | assign zxid = zxid_oe ? zxid_out : 8'bZZZZ_ZZZZ; |
||
84 | // |
||
85 | assign zxid_in = zxid; |
||
86 | |||
87 | |||
88 | |||
89 | // resync strobes |
||
90 | always @(posedge clk) |
||
91 | begin |
||
92 | iowr_r[2:0] <= { iowr_r[1:0], iowr }; |
||
93 | iord_r[2:0] <= { iord_r[1:0], iord }; |
||
94 | end |
||
95 | // |
||
96 | assign iowr_begin = iowr_r[1] && !iowr_r[2]; |
||
118 | lvd | 97 | assign iord_begin = iord_r[1] && !iord_r[2]; |
117 | lvd | 98 | // |
99 | assign iowr_end = !iowr_r[1] && iowr_r[2]; |
||
100 | assign iord_end = !iord_r[1] && iord_r[2]; |
||
101 | // |
||
102 | assign io_begin = iowr_begin || iord_begin; |
||
103 | assign io_end = iowr_end || iord_end; |
||
104 | |||
105 | |||
106 | // control ext bus buffer |
||
107 | always @(posedge clk, negedge rst_n) |
||
108 | if( !rst_n ) |
||
109 | begin |
||
110 | zxbusin <= 1'b1; |
||
111 | zxbusena_n <= 1'b1; |
||
112 | end |
||
113 | else if( addr_ok && io_begin ) |
||
114 | begin |
||
115 | zxbusin <= ~iord_begin; |
||
116 | zxbusena_n <= 1'b0; |
||
117 | end |
||
118 | else if( io_end ) |
||
119 | begin |
||
120 | zxbusena_n <= 1'b1; |
||
121 | end |
||
122 | |||
123 | // control int bus buffer |
||
124 | always @(posedge clk, negedge rst_n) |
||
125 | if( !rst_n ) |
||
126 | begin |
||
127 | zxid_oe <= 1'b0; |
||
128 | end |
||
129 | else if( addr_ok && io_begin ) |
||
130 | begin |
||
131 | zxid_oe <= iord_begin; |
||
132 | end |
||
133 | else if( io_end ) |
||
134 | begin |
||
135 | zxid_oe <= 1'b0; |
||
136 | end |
||
137 | |||
119 | lvd | 138 | // internal write strobe |
139 | always @(posedge clk, negedge rst_n) |
||
140 | if( !rst_n ) |
||
141 | wrr <= 1'b0; |
||
142 | else |
||
143 | wrr <= addr_ok && iowr_begin; |
||
117 | lvd | 144 | |
145 | |||
119 | lvd | 146 | |
121 | lvd | 147 | // write to 33 (init/ctrl reg) |
118 | lvd | 148 | // |
117 | lvd | 149 | always @(posedge clk, negedge rst_n) |
150 | if( !rst_n ) |
||
118 | lvd | 151 | led <= 1'b0; |
152 | else if( init ) |
||
153 | led <= 1'b0; |
||
119 | lvd | 154 | else if( wrr && regsel==2'b00 && zxid[6] ) |
118 | lvd | 155 | led <= ~led; |
156 | // |
||
157 | always @(posedge clk, negedge rst_n) |
||
158 | if( !rst_n ) |
||
159 | init <= 1'b0; |
||
119 | lvd | 160 | else if( wrr && regsel==2'b00 && zxid[7] ) |
118 | lvd | 161 | init <= 1'b1; |
117 | lvd | 162 | else |
163 | init <= 1'b0; |
||
121 | lvd | 164 | // |
165 | always @(posedge clk, negedge rst_n) |
||
166 | if( !rst_n ) |
||
167 | autoinc_ena <= 1'b0; |
||
168 | else if( wrr && regsel==2'b00 ) |
||
169 | autoinc_ena <= zxid[5]; |
||
117 | lvd | 170 | |
171 | |||
172 | // write to 3B (test reg) |
||
173 | always @(posedge clk, negedge rst_n) |
||
174 | if( !rst_n ) |
||
175 | begin |
||
176 | test_reg <= 9'd0; |
||
177 | end |
||
118 | lvd | 178 | else if( init ) |
179 | begin |
||
180 | test_reg <= 9'd0; |
||
181 | end |
||
117 | lvd | 182 | else if( test_reg_write ) |
183 | begin |
||
184 | test_reg[8:0] <= { (~test_reg_pre[7:0]), test_reg[8] }; |
||
185 | end |
||
186 | // |
||
187 | always @(posedge clk) |
||
119 | lvd | 188 | if( wrr && regsel==2'b01 ) |
117 | lvd | 189 | begin |
190 | test_reg_pre <= zxid_in; |
||
191 | test_reg_write <= 1'b1; |
||
192 | end |
||
193 | else |
||
194 | begin |
||
195 | test_reg_write <= 1'b0; |
||
196 | end |
||
197 | |||
198 | |||
199 | // write to B3 (addr reg) |
||
200 | always @(posedge clk) |
||
119 | lvd | 201 | if( wrr && regsel==2'b10 ) |
117 | lvd | 202 | wr_addr <= 1'b1; |
203 | else |
||
204 | wr_addr <= 1'b0; |
||
205 | |||
206 | // write to BB (data reg) |
||
207 | always @(posedge clk) |
||
119 | lvd | 208 | if( wrr && regsel==2'b11 ) |
117 | lvd | 209 | wr_data <= 1'b1; |
210 | else |
||
211 | wr_data <= 1'b0; |
||
212 | |||
213 | // read from BB (data reg) |
||
214 | always @(posedge clk) |
||
215 | if( addr_ok && regsel==2'b11 && iord_begin ) |
||
216 | rd_data <= 1'b1; |
||
217 | else |
||
218 | rd_data <= 1'b0; |
||
219 | |||
220 | // write data for B3 and BB |
||
221 | always @(posedge clk) |
||
119 | lvd | 222 | if( wrr && regsel[1]==1'b1 ) |
117 | lvd | 223 | wr_buffer <= zxid_in; |
224 | |||
225 | |||
226 | // ports read |
||
227 | always @* |
||
228 | case( regsel ) |
||
118 | lvd | 229 | 2'b00: read_data = { init_in_progress, 7'd0 }; |
230 | 2'b01: read_data = test_reg[7:0]; |
||
117 | lvd | 231 | //2'b10: read_data <= рег адреса (НОЛЬ!) |
118 | lvd | 232 | 2'b11: read_data = rd_buffer; |
233 | default: read_data = 8'd0; |
||
117 | lvd | 234 | endcase |
235 | // |
||
236 | always @(posedge clk) |
||
237 | if( addr_ok && iord_begin ) |
||
238 | zxid_out <= read_data; |
||
239 | |||
240 | |||
241 | |||
116 | lvd | 242 | endmodule |
243 |