External Wishbone bus and serial input/output registers
[AtosmChip.git] / pia.v
blob9f06bed723aed6793495e2089a3e8317c63d58c0
1 // Atosm Chip
2 // Copyright (C) 2008 Tomasz Malesinski <tmal@mimuw.edu.pl>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // TODO: interrupt input/outputs
20 module pia(rst_i, clk_i,
21 adr_i,
22 dat_i,
23 dat_o,
24 we_i,
25 stb_i,
26 ack_o,
27 pa_i,
28 pb_i,
29 pa_o,
30 pb_o,
31 ca2_o, cb2_o);
32 input rst_i;
33 input clk_i;
34 input adr_i;
35 input dat_i;
36 input we_i;
37 input stb_i;
38 input pa_i, pb_i;
40 output dat_o;
41 output ack_o;
42 output pa_o, pb_o;
43 output ca2_o, cb2_o;
45 wire rst_i, clk_i;
46 wire [1:0] adr_i;
47 wire [7:0] dat_i;
48 wire we_i;
49 wire stb_i;
51 wire ack_o;
53 reg [7:0] dat_o;
55 wire [7:0] pa_i, pb_i;
56 wire [7:0] pa_o, pb_o;
57 wire ca2_o, cb2_o;
59 reg [7:0] pa_out_reg, pb_out_reg;
60 reg [7:0] pa_dir_reg, pb_dir_reg;
61 reg [1:0] ca1ctl, cb1ctl;
62 reg ddir_a, ddir_b;
63 reg [2:0] ca2ctl, cb2ctl;
65 assign ack_o = stb_i;
67 assign pa_o = (pa_out_reg & pa_dir_reg) | ~pa_dir_reg;
68 assign pb_o = (pb_out_reg & pb_dir_reg) | ~pb_dir_reg;
70 // Only manual CA2/CB2 output modes are supported.
71 assign ca2_o = ca2ctl[0];
72 assign cb2_o = cb2ctl[0];
74 // Read registers.
75 always @ (adr_i or pa_i or pb_i)
76 case (adr_i)
77 0: dat_o = ddir_a ?
78 (pa_i & ~pa_dir_reg) | (pa_out_reg & pa_dir_reg) :
79 pa_dir_reg;
80 1: dat_o = ddir_b ?
81 (pb_i & ~pb_dir_reg) | (pb_out_reg & pb_dir_reg) :
82 pb_dir_reg;
83 2: dat_o = {2'b00, ca2ctl, ddir_a, ca1ctl};
84 3: dat_o = {2'b00, cb2ctl, ddir_b, cb1ctl};
85 endcase
87 // Port A output.
88 always @ (posedge clk_i)
89 if (rst_i)
90 pa_out_reg <= 0;
91 else if (stb_i && we_i && adr_i == 0 && ddir_a)
92 pa_out_reg <= dat_i;
94 // Port A direction.
95 always @ (posedge clk_i)
96 if (rst_i)
97 pa_dir_reg <= 0;
98 else if (stb_i && we_i && adr_i == 0 && !ddir_a)
99 pa_dir_reg <= dat_i;
101 // Port B output.
102 always @ (posedge clk_i)
103 if (rst_i)
104 pb_out_reg <= 0;
105 else if (stb_i && we_i && adr_i == 1 && ddir_b)
106 pb_out_reg <= dat_i;
108 // Port B direction.
109 always @ (posedge clk_i)
110 if (rst_i)
111 pb_dir_reg <= 0;
112 else if (stb_i && we_i && adr_i == 1 && !ddir_b)
113 pb_dir_reg <= dat_i;
115 // Port A control.
116 always @ (posedge clk_i)
117 if (rst_i) begin
118 ca2ctl <= 0;
119 ddir_a <= 0;
120 ca1ctl <= 0;
121 end else if (stb_i && we_i && adr_i == 2) begin
122 ca2ctl <= dat_i[5:3];
123 ddir_a <= dat_i[2];
124 ca1ctl <= dat_i[1:0];
127 // Port B control.
128 always @ (posedge clk_i)
129 if (rst_i) begin
130 cb2ctl <= 0;
131 ddir_b <= 0;
132 cb1ctl <= 0;
133 end else if (stb_i && we_i && adr_i == 3) begin
134 cb2ctl <= dat_i[5:3];
135 ddir_b <= dat_i[2];
136 cb1ctl <= dat_i[1:0];
139 endmodule