CSE 670: Spring 2002 Richard E. Haskell

Lab 5 – The T8X Microprocessor

A block diagram for the T8X microprocessor is shown in Figure 1. It is based on the single-cycle processor of Lab 4.

Figure 1 The T8X Microprocessor

Part A:

The module Tcount from Lab 4 has been replaced by the program counter, PC. This program counter behaves like Tcount with the added feature that it can be loaded with a value when pload = ‘1’. The value comes from M, the output of the TROM. Listing 1 shows the VHDL code for the PC program counter.

library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_unsigned.all;

entity PC is

port (

d: in STD_LOGIC_VECTOR (7 downto 0);

clr: in STD_LOGIC;

clk: in STD_LOGIC;

inc: in STD_LOGIC;

pload: in STD_LOGIC;

q: out STD_LOGIC_VECTOR (7 downto 0)

);

end PC;

architecture PC_arch of PC is

begin

process (clk, clr)

variable COUNT: STD_LOGIC_VECTOR (7 downto 0);

begin

if clr = '1' then

COUNT := "00000000";

q <= COUNT;

elsif clk'event and clk='1' then

if pload = '0' then

if inc = '1' then

COUNT := COUNT + 1;

end if;

else

COUNT := d;

end if;

q <= COUNT;

end if;

end process;

end PC_arch;

Listing 1 PC.vhd

Part B:

For convenience, we can create a VHDL package for the opcode constants. Notice that in this microcontroller, the opcodes are not microcoded. The listing for the package is shown in Listing 2.

package tcodes is

subtype opcode is std_logic_vector(7 downto 0);

-- Register instructions --WHYP WORDS

constant nop:opcode := X"00";-- NOP

constant dup: opcode := X"01";-- DUP

-- ALU instructions

constant plus: opcode := X"10"; -- +

constant plus1: opcode := X"11"; -- 1+

constant invert: opcode := X"12"; -- INVERT

constant twotimes: opcode := X"13"; -- 2*

-- Return Stack, Memory Access, and I/O instructions

constant swfetch: opcode := X"31"; -- SW@

constant digstore: opcode := X"32"; -- DIG!

-- Transfer instructions

constant jmp: opcode := X"40"; -- GOTO

constant jnbtn4: opcode := X"41";-- WAIT_BTN4

constant jbtn4: opcode := X"42"; -- WAIT_BTN4_UP

end tcodes;

Listing 2 Package for opcode constants

Part C:

Since the instructions are not microcoded, it is necessary to have a contoller. The controller contains the VHDL state machine for the T8X. This state machine uses three processes, one synchronous process and two asynchronous. The synchronous process changes the current state to the next state on the rising edge of the clock. Listing 3 shows the entity for tcontrol and the synchronous state machine process synch.

library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_arith.all;

use work.tcodes.all;

entity Tcontrol is

port (

instr: in STD_LOGIC_VECTOR (7 downto 0);

M: in STD_LOGIC_VECTOR (7 downto 0);

clr: in STD_LOGIC;

clk: in STD_LOGIC;

BTN: in STD_LOGIC_VECTOR(1 to 4);

alusel: out STD_LOGIC_VECTOR (1 downto 0);

msel: out STD_LOGIC_VECTOR (1 downto 0);

inc: out STD_LOGIC;

pload: out STD_LOGIC;

tload: out STD_LOGIC;

nload: out STD_LOGIC;

digload: out STD_LOGIC;

iload: out STD_LOGIC

);

end Tcontrol;

architecture Tcontrol_arch of Tcontrol is

type state_type is (fetch, exec, exec_fetch);

signal current_state, next_state: state_type;

synch: process(clk, clr)

begin

if clr = '1' then

current_state <= fetch;

elsif (clk'event and clk = '1') then

current_state <= next_state;

endif;

endprocess synch;

Listing 3 Entity and synchronous process for tcontrol

Process C1 controls the next-state signal based on the current state and the value from the TROM. Since the instructions with bit 6 set to ‘1’ signify a multi-clock-cycle instruction, the next state is set accordingly. Process C2 decodes the instruction and sets the appropriate control signals for the T8X microcontroller. This process is based on the current instruction, instr, and the current state. Listing 4 contains the VHDL code for processes C1 and C2 for the entity tcontrol.

C1: process(current_state, M)

begin

case current_state is

when fetch =>

if M(6) = ‘1’ then

next_state <= exec;

else

next_state <= exec_fetch;

end if;

when exec_fetch =>

if M(6) = ‘1’ then

next_state <= exec;

else

next_state <= exec_fetch;

end if;

when exec =>

next_state <= fetch;

end case;

end process C1;

C2: process(instr, current_state)

begin

alusel <= "00"; msel <= "00"; pload <= '0'; tload <= '0';

nload <= '0'; digload <= '0'; inc <= '1'; iload <= '0';

if (current_state = fetch) or

(current_state = exec_fetch) then

iload <= '1'; -- fetch next instruction

end if;

if (current_state = exec) or

(current_state = exec_fetch) then

case instr is

when nop =>

null;

when dup =>

nload <= '1';

when plus =>

tload <= '1';

when plus1 =>

tload <= '1'; alusel <= "01";

when invert =>

tload <= '1'; alusel <= "10";

when twotimes =>

tload <= '1'; alusel <= "11";

when swfetch =>

tload <= '1'; msel <= "01";

when digstore =>

digload <= '1';

when jmp =>

pload <= '1'; inc <= '0';

when jnbtn4 =>

pload <= not BTN(4); inc <= BTN(4);

when jbtn4 =>

pload <= BTN(4); inc <= not BTN(4);

when others =>

null;

end case;

end if;

end process C2;

Listing 4 Processes C1 and C2 for tcontrol

Part D:

To test the microcontroller, we will use a program that multiplies the switch setting by 10 and displays the results on the 7-segment display. This program is shown in the program ROM, Trom6, in Listing 5.

library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_unsigned.all;

use work.tcodes.all;

entity Trom6 is

port (

addr: in STD_LOGIC_VECTOR (7 downto 0);

M: out STD_LOGIC_VECTOR (7 downto 0)

);

end Trom6;

architecture Trom6_arch of Trom6 is

subtype tword is std_logic_vector(7 downto 0);

type rom_array is array (0 to 18) of tword;

constant rom: rom_array := (

JBTN4, X"00",-- X"00" wait for BTN4 up

JNBTN4, X"02",-- X"02" wait for BTN4

SWFETCH,-- X"04" push switches

digstore,-- X"05" display

JBTN4, X"06",-- X"06" wait for BTN4 up

JNBTN4, X"08",-- X"08" wait for BTN4

twotimes,-- X"0A" 2*

DUP,-- X"0B" DUP

twotimes,-- X"0C" 2*

twotimes,-- X"0D" 2*

plus,-- X"0E" +

digstore,-- X"0F" display

JMP, X"00",-- X"10" GOTO 0

X"00"-- X"12"

);

Listing 5 Trom6.vhd

Part E:

Finally, the top-level component, T6main, shown in Listing 6 provides the necessary port maps for connecting the mux4, reg, alu, digdisplay, PC, Trom6, Tcontrol, and osc_4k in the T8X.

library IEEE;

use IEEE.std_logic_1164.all;

use work.T6comp.all;

entity T6main is

port (

SW: in STD_LOGIC_VECTOR (1 to 8);

BTN: in STD_LOGIC_VECTOR (1 to 4);

LD: out STD_LOGIC_VECTOR (1 to 8);

AtoG: out STD_LOGIC_VECTOR (6 downto 0);

A: out STD_LOGIC_VECTOR (3 downto 0)

);

end T6main;

Listing 6 Entity for T6main

Listing 7 shows the architecture that contains the structural VHDL for the T6main top-level component.

architecture T6main_arch of T6main is

signal tin, T, N, y, P, M,

instr: std_logic_vector(7 downto 0);

signal clr, clk: std_logic;

signal pload, iload, tload, nload,

digload, inc: std_logic;

signal msel, alusel : std_logic_vector(1 downto 0);

signal GND: std_logic_vector(3 downto 0);

begin

GND <= "0000";

U0: mux4 port map

(a => y, b =>SW, c(3 downto 0) => BTN,

c(7 downto 4) => GND, d => M, sel => msel, y => tin);

Treg: reg port map

(d => tin, load =>tload, clr => clr, clk =>clk,

q => T);

Nreg: reg port map

(d => T, load => nload, clr => clr, clk =>clk,

q => N);

U1: alu port map

(a => T, b => N, sel => alusel, y => y);

U2: digdisplay port map

(T => T, N => N, digload => digload, clr => clr,

clk => clk, A => A, AtoG => AtoG);

U3: PC port map

(d => M, clr => clr, clk => clk, pload => pload,

inc => inc, q => P);

U4: Trom6 port map

(addr => P, M => M);

ireg: reg port map

(d => M, load => iload, clr => clr, clk =>clk,

q => instr);

U5: Tcontrol port map

(instr => instr, M => M, clr => clr, clk => clk,

BTN => BTN, alusel => alusel, msel => msel,

inc => inc, pload => pload, tload => tload,

nload => nload, digload => digload, iload => iload);

U6: osc_4k port map

(clk => clk);

LD <= SW;

clr <= BTN(1);

end T6main_arch;

Listing 7 Architecture for T6main.vhd

Synthesize and implement this program for the Spartan2 FPGA and download the program to the Spartan2-DIO1 board. First, press and release BTN1 to clear the single-cycle processor, then use BTN4 to single-step through the program. On a listing of the ROM indicate the values of T and N after each instruction is executed.

Part F:

Modify the circuit by making the data busses 16 bits wide and displaying the 16-bit hex value of T on the four 7-segment displays. The instruction SWFETCH should load the switch values into the lower 8 bits of Treg and push Treg to Nreg. Store a sequence of instructions in the Trom that will multiply the 8-bit hex value on the switches by 25 (decimal). Test the program by setting the switch value to X”35”, press and release the button (BTN4) to load the value into the T8X microntroller, then press and release the button (BTN4) a second time to perform the multiplication by 25 (decimal). The hex answer, X”52D”, should be displayed on the 7-segment displays. You can continue to test different switch settings.

Demonstrate the operation of your program to a lab instructor. Hand in a listing of your main program and the Trom6 program. Explain the operation of each instruction in your Trom program.

1