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
210
211
212
213
214
215
216
217
|
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.alu_types.all;
entity alu is
port (
a, b : in std_logic_vector(7 downto 0); -- inputs to ALU. In
-- general here 'a' is
-- a value from working
-- register W and 'b'
-- is from a file
-- register.
op : in alu_op; -- ALU operation which
-- one to use
bit_select : in std_logic_vector(2 downto 0); -- this is the 'b' signal in
-- the datasheet.
status_in : in std_logic_vector(2 downto 0); -- status before ALU operation.
status : out std_logic_vector(2 downto 0); -- status after ALU operation.
result : out std_logic_vector(7 downto 0); -- result of the ALU
-- operation. This is
-- then either stored
-- in file register f
-- or work register W.
skip : out std_logic -- SKIP signal.
-- the status register is of form:
-- IRP RP1 RP0 ~TO ~PD Z DC C
-- 7 6 5 4 3 2 1 0
-- ALU only operates on 3 least significant bits.
);
end entity alu;
architecture rtl of alu is
-- ternary op; returns x1 if cond is true, x2 otherwise.
pure function sel(cond : boolean; x1, x2 : std_logic) return std_logic is
begin
if cond then return x1; else return x2; end if;
end function;
-- return status with the given flag set to val, all other bits same
pure function set_flag(flag : alu_flag; val : std_logic; stat : std_logic_vector(2 downto 0)) return std_logic_vector is
variable s_out : std_logic_vector(2 downto 0) := stat;
begin
case flag is
when FLAG_Z => s_out(2) := val;
when FLAG_DC => s_out(1) := val;
when FLAG_C => s_out(0) := val;
end case;
return s_out;
end function;
-- Computes val +/- 1, drives result and either sets Z flag or skip signal.
procedure inc_dec(
val : in std_logic_vector(7 downto 0);
inc : in boolean; -- true = increment, false = decrement
do_skip : in boolean; -- true for *FSZ variants
signal res : out std_logic_vector(7 downto 0);
signal stat : out std_logic_vector(2 downto 0);
signal do_skip_out : out std_logic;
stat_in : in std_logic_vector(2 downto 0)
) is
variable t : std_logic_vector(7 downto 0);
begin
if inc then
t := std_logic_vector(unsigned(val) + 1);
else
t := std_logic_vector(unsigned(val) - 1);
end if;
res <= t;
if do_skip then
if unsigned(t) = 0 then
do_skip_out <= '1';
else
do_skip_out <= '0';
end if;
else
stat <= set_flag(FLAG_Z, sel(unsigned(t) = 0, '1', '0'), stat_in);
end if;
end procedure;
begin
process(a, b, op, bit_select, status_in)
variable tmp : std_logic_vector(7 downto 0);
variable tmp_extended : std_logic_vector(8 downto 0);
variable tmp_status : std_logic_vector(2 downto 0);
begin
-- DEFAULT case (NOP)
result <= (others => '0'); -- default: zero result
skip <= '0'; -- default: no skip
status <= status_in; -- default: pass status thru
case op is
when NOP => -- nothing
when ADDWF | ADDLW =>
-- addition
tmp_extended := std_logic_vector(unsigned('0' & a) + unsigned('0' & b));
-- DC
tmp(4 downto 0) := std_logic_vector(('0' & unsigned(a(3 downto 0))) + ('0' & unsigned(b(3 downto 0))));
-- flags
tmp_status := set_flag(FLAG_Z, sel(unsigned(tmp_extended(7 downto 0)) = 0, '1', '0'), status_in);
tmp_status := set_flag(FLAG_C, tmp_extended(8), tmp_status);
tmp_status := set_flag(FLAG_DC, tmp(4), tmp_status);
status <= tmp_status;
result <= tmp_extended(7 downto 0);
when SUBLW | SUBWF =>
-- PIC16F84A: SUBWF = f - W, SUBLW = k - W → dest = b - a
tmp_extended := std_logic_vector(unsigned('0' & b) - unsigned('0' & a));
-- DC: borrow out of lower nibble
tmp(4 downto 0) := std_logic_vector(('0' & unsigned(b(3 downto 0))) - ('0' & unsigned(a(3 downto 0))));
tmp_status := set_flag(FLAG_Z, sel(unsigned(tmp_extended(7 downto 0)) = 0, '1', '0'), status_in);
tmp_status := set_flag(FLAG_C, not tmp_extended(8), tmp_status);
tmp_status := set_flag(FLAG_DC, not tmp(4), tmp_status);
status <= tmp_status;
result <= tmp_extended(7 downto 0);
when IORLW | IORWF =>
tmp := a or b;
result <= tmp;
status <= set_flag(FLAG_Z, sel(unsigned(tmp) = 0, '1', '0'), status_in);
when ANDWF | ANDLW =>
tmp := a and b;
result <= tmp;
status <= set_flag(FLAG_Z, sel(unsigned(tmp) = 0, '1', '0'), status_in);
when XORLW | XORWF =>
tmp := a xor b;
result <= tmp;
status <= set_flag(FLAG_Z, sel(unsigned(tmp) = 0, '1', '0'), status_in);
when COMF =>
tmp := not b;
result <= tmp;
status <= set_flag(FLAG_Z, sel(unsigned(tmp) = 0, '1', '0'), status_in);
when DECF => inc_dec(b, false, false, result, status, skip, status_in);
when DECFSZ => inc_dec(b, false, true, result, status, skip, status_in);
when INCF => inc_dec(b, true, false, result, status, skip, status_in);
when INCFSZ => inc_dec(b, true, true, result, status, skip, status_in);
when RLF =>
tmp := std_logic_vector(shift_left(unsigned(b), 1));
tmp(0) := status_in(0);
status(0) <= b(7);
result <= tmp;
when RRF =>
tmp := std_logic_vector(shift_right(unsigned(b), 1));
tmp(7) := status_in(0);
status(0) <= b(0);
result <= tmp;
when BCF =>
result <= b;
result(to_integer(unsigned(bit_select))) <= '0';
when BTFSC =>
skip <= not b(to_integer(unsigned(bit_select)));
when BSF =>
result <= b;
result(to_integer(unsigned(bit_select))) <= '1';
when BTFSS =>
skip <= b(to_integer(unsigned(bit_select)));
when SWAPF =>
tmp(7 downto 4) := b(3 downto 0);
tmp(3 downto 0) := b(7 downto 4);
result <= tmp;
when CLRF | CLRW =>
result <= (others => '0');
status <= set_flag(FLAG_Z, '1', status_in);
when MOVF =>
result <= b;
status <= set_flag(FLAG_Z, sel(unsigned(b) = 0, '1', '0'), status_in);
when MOVWF => result <= a;
when MOVLW => result <= b;
when CALL => null;
when GOTO => null;
when RETLW => result <= b;
when RETUR => null;
when RETFIE => null;
end case;
end process;
end architecture rtl;
|