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