OpenCores
URL https://opencores.org/ocsvn/tinycpu/tinycpu/trunk

Subversion Repositories tinycpu

[/] [tinycpu/] [trunk/] [src/] [core.vhd] - Blame information for rev 34

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 earlz
--Core module. 
2
--This module is basically connects everything and decodes the opcodes.
3
--The only thing above this is toplevel.vhd which actually sets the pinout for the FPGA
4
 
5
 
6
library IEEE;
7
use IEEE.STD_LOGIC_1164.ALL;
8
use IEEE.NUMERIC_STD.ALL;
9
use work.tinycpu.all;
10
 
11
entity core is
12
  port(
13
    --memory interface 
14
    MemAddr: out std_logic_vector(15 downto 0); --memory address (in bytes)
15
    MemWW: out std_logic; --memory writeword
16
    MemWE: out std_logic; --memory writeenable
17 20 earlz
    MemIn: in std_logic_vector(15 downto 0);
18
    MemOut: out std_logic_vector(15 downto 0);
19 19 earlz
    --general interface
20
    Clock: in std_logic;
21
    Reset: in std_logic; --When this is high, CPU will reset within 1 clock cycles. 
22
    --Enable: in std_logic; --When this is high, the CPU executes as normal, when low the CPU stops at the next clock cycle(maintaining all state)
23
    Hold: in std_logic; --when high, CPU pauses execution and places Memory interfaces into high impendance state so the memory can be used by other components
24
    HoldAck: out std_logic; --when high, CPU acknowledged hold and buses are in high Z
25
    --todo: port interface
26
 
27
    --debug ports:
28
    DebugIR: out std_logic_vector(15 downto 0); --current instruction
29 20 earlz
    DebugIP: out std_logic_vector(7 downto 0); --current IP
30
    DebugCS: out std_logic_vector(7 downto 0); --current code segment
31 19 earlz
    DebugTR: out std_logic; --current value of TR
32 20 earlz
    DebugR0: out std_logic_vector(7 downto 0)
33 19 earlz
   );
34
end core;
35
 
36
architecture Behavioral of core is
37
  component fetch is
38
    port(
39
      Enable: in std_logic;
40
      AddressIn: in std_logic_vector(15 downto 0);
41
      Clock: in std_logic;
42
      DataIn: in std_logic_vector(15 downto 0); --interface from memory
43
      IROut: out std_logic_vector(15 downto 0);
44
      AddressOut: out std_logic_vector(15 downto 0) --interface to memory
45
    );
46
  end component;
47
  component alu is
48
    port(
49
      Op: in std_logic_vector(4 downto 0);
50
      DataIn1: in std_logic_vector(7 downto 0);
51
      DataIn2: in std_logic_vector(7 downto 0);
52
      DataOut: out std_logic_vector(7 downto 0);
53
      TR: out std_logic
54
    );
55
  end component;
56
  component carryover is
57
    port(
58
      EnableCarry: in std_logic; --When disabled, SegmentIn goes to SegmentOut
59
      DataIn: in std_logic_vector(7 downto 0);
60
      SegmentIn: in std_logic_vector(7 downto 0);
61
      Addend: in std_logic_vector(7 downto 0); --How much to increase DataIn by (as a signed number). Believe it or not, that's the actual word for what we need.
62
      DataOut: out std_logic_vector(7 downto 0);
63 21 earlz
      SegmentOut: out std_logic_vector(7 downto 0);
64
      Clock: in std_logic
65 19 earlz
    );
66
  end component;
67
  component registerfile is
68
  port(
69
    WriteEnable: in regwritetype;
70
    DataIn: in regdatatype;
71
    Clock: in std_logic;
72
    DataOut: out regdatatype
73
  );
74
  end component;
75
 
76
  constant REGIP: integer := 7;
77
  constant REGSP: integer := 6;
78
  constant REGSS: integer := 15;
79
  constant REGES: integer := 14;
80
  constant REGDS: integer := 13;
81
  constant REGCS: integer := 12;
82
 
83
  type ProcessorState is (
84
    ResetProcessor,
85 21 earlz
    FirstFetch1, --the fetcher needs two clock cycles to catch up
86
    FirstFetch2,
87 23 earlz
    Firstfetch3,
88 19 earlz
    Execute,
89
    WaitForMemory,
90 30 earlz
    HoldMemory,
91
    WaitForAlu -- wait for settling is needed when using the ALU
92 19 earlz
  );
93 20 earlz
  signal state: ProcessorState;
94
  signal HeldState: ProcessorState; --state the processor was in when HOLD was activated
95 19 earlz
 
96
  --carryout signals
97
  signal CarryCS: std_logic;
98
  signal CarrySS: std_logic;
99
  signal IPAddend: std_logic_vector(7 downto 0);
100
  signal SPAddend: std_logic_vector(7 downto 0);
101
  signal IPCarryOut: std_logic_vector(7 downto 0);
102
  signal CSCarryOut: std_logic_vector(7 downto 0);
103 25 earlz
  signal SPCarryOut: std_logic_vector(7 downto 0);
104
  signal SSCarryOut: std_logic_vector(7 downto 0);
105
 
106 19 earlz
  --register signals
107
  signal regWE:regwritetype;
108
  signal regIn: regdatatype;
109
  signal regOut: regdatatype;
110
  --fetch signals
111
  signal fetchEN: std_logic;
112
  signal IR: std_logic_vector(15 downto 0);
113 25 earlz
  --alu signals
114
  signal AluOp: std_logic_vector(4 downto 0);
115
  signal AluIn1: std_logic_vector(7 downto 0);
116
  signal AluIn2: std_logic_vector(7 downto 0);
117
  signal AluOut: std_logic_vector(7 downto 0);
118 31 earlz
  signal AluTR: std_logic;
119 25 earlz
  signal TR: std_logic;
120 31 earlz
  signal TRData: std_logic;
121
  signal UseAluTR: std_logic;
122 19 earlz
 
123
  --control signals
124
  signal InReset: std_logic;
125 25 earlz
  signal OpAddress: std_logic_vector(15 downto 0); --memory address to use for operation of an instruction
126 32 earlz
  signal OpDataIn: std_logic_vector(15 downto 0);
127
  signal OpDataOut: std_logic_vector(15 downto 0);
128 25 earlz
  signal OpWW: std_logic;
129
  signal OpWE: std_logic;
130 32 earlz
  signal OpDestReg1: std_logic_vector(3 downto 0);
131
  signal OpUseReg2: std_logic;
132
  signal OpDestReg2: std_logic_vector(3 downto 0);
133 19 earlz
 
134
  --opcode shortcut signals
135
  signal opmain: std_logic_vector(3 downto 0);
136
  signal opimmd: std_logic_vector(7 downto 0);
137
  signal opcond1: std_logic; --first conditional bit
138
  signal opcond2: std_logic; --second conditional bit
139
  signal opreg1: std_logic_vector(2 downto 0);
140
  signal opreg2: std_logic_vector(2 downto 0);
141
  signal opreg3: std_logic_vector(2 downto 0);
142
  signal opseges: std_logic; --use ES segment
143 25 earlz
 
144
  signal regbank: std_logic;
145 19 earlz
 
146 20 earlz
  signal fetcheraddress: std_logic_vector(15 downto 0);
147 25 earlz
 
148 27 earlz
 
149
  signal bankreg1: std_logic_vector(3 downto 0); --these signals have register bank stuff baked in
150
  signal bankreg2: std_logic_vector(3 downto 0);
151
  signal bankreg3: std_logic_vector(3 downto 0);
152 25 earlz
  signal FetchMemAddr: std_logic_vector(15 downto 0);
153
 
154 29 earlz
  signal UsuallySS: std_logic_vector(3 downto 0);
155
  signal UsuallyDS: std_logic_vector(3 downto 0);
156 32 earlz
  signal AluRegOut: std_logic_vector(3 downto 0);
157 19 earlz
begin
158 20 earlz
  reg: registerfile port map(
159 19 earlz
    WriteEnable => regWE,
160
    DataIn => regIn,
161
    Clock => Clock,
162
    DataOut => regOut
163
  );
164 20 earlz
  carryovercs: carryover port map(
165 19 earlz
    EnableCarry => CarryCS,
166 28 earlz
    DataIn => regOut(REGIP),
167
    SegmentIn => regOut(REGCS),
168 20 earlz
    Addend => IPAddend,
169
    DataOut => IPCarryOut,
170 21 earlz
    SegmentOut => CSCarryOut,
171
    Clock => Clock
172 19 earlz
  );
173 25 earlz
  carryoverss: carryover port map(
174
    EnableCarry => CarrySS,
175 28 earlz
    DataIn => regOut(REGSP),
176
    SegmentIn => RegOut(REGSS),
177 25 earlz
    Addend => SPAddend,
178
    DataOut => SPCarryOut,
179
    SegmentOut => SSCarryOut,
180
    Clock => Clock
181
  );
182 20 earlz
  fetcher: fetch port map(
183 19 earlz
    Enable => fetchEN,
184 20 earlz
    AddressIn => fetcheraddress,
185 19 earlz
    Clock => Clock,
186
    DataIn => MemIn,
187
    IROut => IR,
188 25 earlz
    AddressOut => FetchMemAddr
189 19 earlz
  );
190 25 earlz
  cpualu: alu port map(
191
    Op => AluOp,
192
    DataIn1 => AluIn1,
193
    DataIn2 => AluIn2,
194
    DataOut => AluOut,
195 31 earlz
    TR => AluTR
196 25 earlz
  );
197 21 earlz
  fetcheraddress <= regIn(REGCS) & regIn(REGIP);
198 25 earlz
  MemAddr <= OpAddress when state=WaitForMemory else FetchMemAddr;
199 32 earlz
  MemOut <= OpDataOut when (state=WaitForMemory and OpWE='1') else "ZZZZZZZZZZZZZZZZ" when state=HoldMemory else x"0000";
200 28 earlz
  MemWE <= OpWE when state=WaitForMemory else 'Z' when state=HoldMemory else '0';
201
  MemWW <= OpWW when state=WaitForMemory else 'Z' when state=HoldMEmory else '0';
202 32 earlz
  OpDataIn <= MemIn;
203 20 earlz
  --opcode shortcuts
204 19 earlz
  opmain <= IR(15 downto 12);
205
  opimmd <= IR(7 downto 0);
206
  opcond1 <= IR(8);
207
  opcond2 <= IR(7);
208
  opreg1 <= IR(11 downto 9);
209
  opreg3 <= IR(2 downto 0);
210 27 earlz
  opreg2 <= IR(6 downto 4);
211
  opseges <= IR(3);
212 20 earlz
  --debug ports
213
  DebugCS <= regOut(REGCS);
214
  DebugIP <= regOut(REGIP);
215
  DebugR0 <= regOut(0);
216
  DebugIR <= IR;
217 25 earlz
  DebugTR <= TR;
218
  --register addresses with registerbank baked in
219 27 earlz
  bankreg1 <= ('1' & opreg1) when (regbank='1' and opreg1(2)='0') else '0' & opreg1;
220
  bankreg2 <= ('1' & opreg2) when (regbank='1' and opreg2(2)='0') else '0' & opreg2;
221
  bankreg3 <= ('1' & opreg3) when (regbank='1' and opreg3(2)='0') else '0' & opreg3;
222 29 earlz
  --UsuallySegment shortcuts (only used when not an immediate
223
  UsuallyDS <= "1101" when opseges='0' else "1110";
224
  UsuallySS <= "1111" when opseges='0' else "1110";
225 31 earlz
  TR <= TRData when UseAluTR='0' else AluTR;
226 19 earlz
 
227 29 earlz
  foo: process(Clock, Hold, state, IR, inreset, reset, regin, regout, IPCarryOut, CSCarryOut)
228 19 earlz
  begin
229
    if rising_edge(Clock) then
230 21 earlz
 
231
    --states
232 20 earlz
      if reset='1' and hold='0' then
233 19 earlz
        InReset <= '1';
234
        state <= ResetProcessor;
235 20 earlz
        HoldAck <= '0';
236 21 earlz
        CarryCS <= '1';
237
        CarrySS <= '0';
238
        regWE <= (others => '1');
239
        regIn <= (others => "00000000");
240
        regIn(REGCS) <= x"01";
241 32 earlz
        regIn(REGSS) <= x"02";
242 21 earlz
        IPAddend <= x"00";
243 25 earlz
        SPAddend <= x"00";
244
        AluOp <= "10001"; --reset TR in ALU
245
        regbank <= '0';
246 21 earlz
        fetchEN <= '1';
247 32 earlz
        OpDataOut <= "ZZZZZZZZZZZZZZZZ";
248 25 earlz
        OpAddress <= x"0000";
249
        OpWE <= '0';
250
        opWW <= '0';
251 31 earlz
        TRData <= '0';
252
        UseAluTR <= '0';
253 32 earlz
        OpDestReg1<= x"0";
254
        OpDestReg2 <= x"0";
255
        OpUseReg2 <= '0';
256 19 earlz
        --finish up
257
      elsif InReset='1' and reset='0' and Hold='0' then --reset is done, start executing
258
        InReset <= '0';
259 21 earlz
        fetchEN <= '1';
260
        state <= FirstFetch1;
261 19 earlz
      elsif Hold = '1' and (state=HoldMemory or state=Execute or state=ResetProcessor) then
262 20 earlz
        --do not hold immediately if waiting on memory or if waiting on the first fetch of an instruction after reset
263 19 earlz
        state <= HoldMemory;
264
        HoldAck <= '1';
265 21 earlz
        FetchEN <= '0';
266 19 earlz
      elsif Hold='0' and state=HoldMemory then
267 20 earlz
        if reset='1' or InReset='1' then
268
          state <= ResetProcessor;
269
        else
270
          state <= Execute;
271
        end if;
272 21 earlz
        FetchEN <= '1';
273
      elsif state=FirstFetch1 then --we have to let IR get loaded before we can execute.
274 20 earlz
        --regWE <= (others => '0');
275 21 earlz
        fetchEN <= '1'; --already enabled, but anyway
276 23 earlz
        --regWE <= (others => '0');
277 21 earlz
        IPAddend <= x"02";
278
        SPAddend <= x"00"; --no addend unless pushing or popping
279
        RegWE <= (others => '0');
280
        regIn(REGIP) <= IPCarryOut;
281
        regWE(REGIP) <= '1';
282
        regWE(REGCS) <= '1';
283
        regIn(REGCS) <= CSCarryOut;
284 23 earlz
        state <= Execute;
285
      elsif state=FirstFetch2 then
286
        state <= FirstFetch3;
287
 
288
      elsif state=FirstFetch3 then
289
        state <= Execute;
290 25 earlz
      elsif state=WaitForMemory then
291
        state <= Execute;
292
        FetchEn <= '1';
293
        IpAddend <= x"02";
294 33 earlz
        --SpAddend <= x"00";
295
        --SP can change here... really I don't *think* it can change from within Execute... so maybe that's redundant
296
        regIn(REGSP) <= SPCarryOut; --with addend being 0, it'll just write SP to SP so it won't change, but this makes code easier for me
297
        regIn(REGSS) <= SSCarryOut;
298
        regWE(REGSP) <= '1';
299
        regWE(REGSS) <= '1';
300 32 earlz
        if OpWE='0' then
301
          regIn(to_integer(unsigned(OpDestReg1))) <= OpDataIn(7 downto 0);
302
          regWE(to_integer(unsigned(OpDestReg1))) <= '1';
303
          if OpUseReg2='1' then
304
            regIn(to_integer(unsigned(OpDestReg2))) <= OpDataIn(15 downto 8);
305
            regWE(to_integer(unsigned(OpDestReg2))) <= '1';
306
          end if;
307
        end if;
308 30 earlz
      elsif state=WaitForAlu then
309
        state <= Execute;
310 32 earlz
        regIn(to_integer(unsigned(AluRegOut))) <= AluOut;
311
        regWE(to_integer(unsigned(AluRegOut))) <= '1';
312 30 earlz
        FetchEN <= '1';
313
        IPAddend <= x"02";
314
        SPAddend <= x"00";
315 19 earlz
      end if;
316 21 earlz
 
317
 
318 19 earlz
      if state=Execute then
319 20 earlz
        fetchEN <= '1';
320 19 earlz
        --reset to "usual"
321 20 earlz
        IPAddend <= x"02";
322
        SPAddend <= x"00"; --no addend unless pushing or popping
323 19 earlz
        RegWE <= (others => '0');
324 21 earlz
        regIn(REGIP) <= IPCarryOut;
325
        regWE(REGIP) <= '1';
326
        regWE(REGCS) <= '1';
327
        regIn(REGCS) <= CSCarryOut;
328 32 earlz
        OpUseReg2 <= '0';
329 25 earlz
        OpAddress <= "ZZZZZZZZZZZZZZZZ";
330 31 earlz
        if UseAluTR='1' then
331
          UseAluTR<='0';
332
        end if;
333 19 earlz
        --actual decoding
334 25 earlz
        if opcond1='0' or (opcond1='1' and TR='1') then
335
          case opmain is
336
            when "0000" => --mov reg,imm
337 27 earlz
              regIn(to_integer(unsigned(bankreg1))) <= opimmd;
338
              regWE(to_integer(unsigned(bankreg1))) <= '1';
339 25 earlz
            when "0001" => --mov [reg],imm
340 27 earlz
              OpAddress <= regOut(REGDS) & regOut(to_integer(unsigned(bankreg1)));
341 25 earlz
              OpWE <= '1';
342 32 earlz
              OpDataOut <= x"00" & opimmd;
343 25 earlz
              OpWW <= '0';
344
              state <= WaitForMemory;
345
              IPAddend <= x"00"; --disable all this because we have to wait a cycle to write memory
346
              FetchEN <= '0';
347 27 earlz
            when "0011" => --group 3 comparisons
348 31 earlz
              TRData <= AluTR;
349
              UseAluTR <= '1';
350 27 earlz
              AluOp <= "01" & opreg3; --nothing hard here, ALU does it all for us
351 29 earlz
              AluIn1 <= regOut(to_integer(unsigned(bankreg1)));
352
              AluIn2 <= regOut(to_integer(unsigned(bankreg2)));
353 27 earlz
            when "0100" => --group 4 bitwise operations
354 30 earlz
              --setup wait state
355
              State <= WaitForAlu;
356
              FetchEN <= '0';
357
              IPAddend <= x"00";
358 27 earlz
              AluOp <= "00" & opreg3; --nothing hard here, ALU does it all for us
359 29 earlz
              AluIn1 <= regOut(to_integer(unsigned(bankreg1)));
360
              AluIn2 <= regOut(to_integer(unsigned(bankreg2)));
361 32 earlz
              AluRegOut <= bankreg1;
362 30 earlz
              --regIn(to_integer(unsigned(bankreg1))) <= AluOut;
363
              --regWE(to_integer(unsigned(bankreg1))) <= '1';
364 29 earlz
           when "0101" => --group 5
365
              case opreg3 is
366
                when "000" => --subgroup 5-0
367
                  case opreg2 is
368
                    when "000" => --push reg
369
                      SpAddend <= x"02"; --set SP to increment
370
                      OpAddress <= regOut(to_integer(unsigned(UsuallySS))) & regOut(REGSP);
371
                      OpWE <= '1';
372 32 earlz
                      OpDataOut <= x"00" & regOut(to_integer(unsigned(bankreg1)));
373 29 earlz
                      OpWW <= '1';
374
                      state <= WaitForMemory;
375
                      IPAddend <= x"00";
376
                      FetchEN <= '0';
377
                    when "001" => --pop reg
378
                      SPAddend <= x"FE"; --set SP to decrement
379 33 earlz
                      --TODO account for carryover properties
380
                      OpAddress <= regOut(to_integer(unsigned(UsuallySS))) & std_logic_vector(unsigned(regOut(REGSP))-2); --decrement 2 here "early" 
381 29 earlz
                      OpWE <= '0';
382 32 earlz
                      OpDestReg1 <= bankreg1;
383
                      --regIn(to_integer(unsigned(bankreg1))) <= OpData(7 downto 0);
384 29 earlz
                      OpWW <= '0';
385
                      state <= WaitForMemory;
386
                      IPAddend <= x"00";
387
                      FetchEN <= '0';
388
                    when others =>
389
                      --synthesis off
390
                      report "Not implemented subgroup 5-0" severity error;
391
                      --synthesis on
392
                  end case;
393 33 earlz
                when "001" => --mov reg, reg
394
                  regIn(to_integer(unsigned(bankreg1))) <= regOut(to_integer(unsigned(bankreg2)));
395
                  regWE(to_integer(unsigned(bankreg1))) <= '1';
396 34 earlz
                when "010" => --mov reg, [reg] (load)
397
                  OpDestReg1 <= bankreg1;
398
                  OpWE <= '0';
399
                  OpAddress <= regOut(to_integer(unsigned(UsuallyDS))) & regOut(to_integer(unsigned(bankreg2)));
400
                  IpAddend <= x"00";
401
                  FetchEN <= '0';
402
                  state <= WaitForMemory;
403
                when "011" => --mov [reg], reg (store)
404
                  OpDataOut <= x"00" & regOut(to_integer(unsigned(bankreg2)));
405
                  OpWW <= '0';
406
                  OpWE <= '1';
407
                  OpAddress <= regOut(to_integer(unsigned(UsuallyDS))) & regOut(to_integer(unsigned(bankreg1)));
408
                  IpAddend <= x"00";
409
                  FetchEN <= '0';
410
                  state <= WaitForMemory;
411 29 earlz
                when others =>
412
                  --synthesis off
413
                  report "Not implemented group 5" severity error;
414
                  --synthesis on
415
              end case;
416 25 earlz
            when others =>
417
              --synthesis off
418
              report "Not implemented" severity error;
419
              --synthesis on
420
          end case;
421
        end if;
422 19 earlz
      end if;
423 21 earlz
 
424 29 earlz
    end if;
425 21 earlz
 
426
 
427 29 earlz
 
428 19 earlz
  end process;
429
 
430
 
431
 
432
 
433
 
434
 
435
 
436
 
437
 
438
end Behavioral;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.