forked from sorgelig/Amstrad_MiST
-
Notifications
You must be signed in to change notification settings - Fork 0
/
i8255.v
98 lines (86 loc) · 2.85 KB
/
i8255.v
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
//============================================================================
// Simple i82c55 implementation
// Copyright (C) 2018 Sorgelig
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module i8255
(
input reset,
input clk_sys,
input [1:0] addr,
input [7:0] idata,
output reg[7:0] odata,
input cs,
input we,
input oe,
input [7:0] ipa,
output [7:0] opa,
input [7:0] ipb,
output [7:0] opb,
input [7:0] ipc,
output [7:0] opc
);
reg [7:0] mode;
reg [7:0] opa_r;
reg [7:0] opb_r;
reg [7:0] opc_r;
assign opa =(~mode[4] | mode[6]) ? opa_r : 8'hFF;
assign opc[7:4] =(~mode[3]) ? opc_r[7:4] : 4'hF;
assign opb =(~mode[1]) ? opb_r : 8'hFF;
assign opc[3:0] =(~mode[0]) ? opc_r[3:0] : 4'hF;
reg [7:0] maskC;
always @(*) begin
casex({mode[6:4], mode[2]})
'b1xx0: maskC = 8'b00000111;
'b1xx1: maskC = 8'b00000000;
'b0110: maskC = 8'b00110111;
'b0111: maskC = 8'b00110000;
'b0100: maskC = 8'b11000111;
'b0101: maskC = 8'b11000000;
'b00x1: maskC = 8'b11111000;
default: maskC = 8'b11111111;
endcase
end
//cpc quirk to pass the ppi test
wire [3:0] tapemotor = (~mode[6] & mode[5] & ~mode[4] & ~mode[2]) ? 4'h2 : 4'h0;
always @* begin
casex({oe&cs,addr})
'b0XX: odata = 8'hFF;
'b100: odata =(mode[4] | mode[6]) ? ipa : opa_r;
'b101: odata = mode[1] ? ipb : opb_r;
'b110: odata ={mode[3] ? (ipc[7:4] & maskC[7:4]) | tapemotor : opc_r[7:4], mode[0] ? ipc[3:0] & maskC[3:0] : opc_r[3:0]};
'b111: odata = mode;
endcase
end
always @(posedge clk_sys) begin
reg old_we;
old_we <= we;
if (reset) {opa_r,opb_r,opc_r,mode} <= {8'h00,8'h00,8'h00,8'h9B};
else begin
if(~old_we & we & cs) begin
case(addr)
0: opa_r <= idata;
1: opb_r <= idata;
2: opc_r <= (idata & maskC) | (opc_r & ~maskC);
default: begin
if (~idata[7]) opc_r[idata[3:1]] <= idata[0];
else {opa_r,opb_r,opc_r,mode} <= {8'h00,8'h00,8'h00,idata};
end
endcase
end
end
end
endmodule