PART 5

Manual Data_path Design












Data_path.components













Data_path.bussing_structure













Data_path.instruction_execution

lda instruction:

Begin fetch: pc_on_mar_page_bus, pc_on_mar_offset_bus,
load_mar_page, load_mar_offset, increment_pc

mar_on_adbus, read_memory, databus_on_adbus,
alu_a_side_on_alu_output, no_shift, load_ir

Get address: pc_on_mar_page_bus, pc_on_mar_offset_bus,
load_mar_page, load_mar_offset, increment_pc

mar_on_adbus, read_memory, databus_on_dbus,
dbus_on_mar_offset_bus, page_from_ir_on_mar_page_bus
load_mar_page_bus, load_mar_offset_bus

Get operand: mar_on_adbus, read_memory,
load ac databus_on_adbus,
alu_a_side_on_alu_output, no_shift, load_ac

Next fetch : ...













Data_path.control_connection













Data_path.control_connection













Data_path.logic_units

LIBRARY cmos;
USE cmos.basic_utilities.ALL;
PACKAGE alu_operations IS
CONSTANT a_and_b : qit_vector (2 DOWNTO 0) := "000";
CONSTANT b_compl : qit_vector (2 DOWNTO 0) := "001";
CONSTANT a_input : qit_vector (2 DOWNTO 0) := "100";
CONSTANT a_add_b : qit_vector (2 DOWNTO 0) := "101";
CONSTANT b_input : qit_vector (2 DOWNTO 0) := "110";
CONSTANT a_sub_b : qit_vector (2 DOWNTO 0) := "111";
END alu_operations;













Data_path.logic_units













Data_path.logic_units

ENTITY arithmetic_logic_unit IS
PORT (a_side, b_side : IN byte; code : IN qit_vector (2 DOWNTO 0);
in_flags : IN nibble; z_out : OUT byte; out_flags : OUT nibble);
END arithmetic_logic_unit;
--
ARCHITECTURE behavioral OF arithmetic_logic_unit IS
BEGIN
coding: PROCESS (a_side, b_side, code)
VARIABLE t : qit_vector (9 DOWNTO 0);
VARIABLE v, c, z, n : qit;
ALIAS n_flag_in : qit IS in_flags(0); ALIAS z_flag_in : qit IS in_flags(1);
ALIAS c_flag_in : qit IS in_flags(2); ALIAS v_flag_in : qit IS in_flags(3);
BEGIN
CASE code IS
WHEN a_add_b => t := add_cv (b_side, a_side, c_flag_in);
c := t(8); v := t(9); -- other flags are set at the end
WHEN a_sub_b => t := sub_cv (b_side, a_side, c_flag_in);
c := t(8); v := t(9);
WHEN a_and_b => t (7 DOWNTO 0) := a_side AND b_side;
c := c_flag_in; v := v_flag_in;
WHEN a_input => t (7 DOWNTO 0) := a_side;
c := c_flag_in; v := v_flag_in;
WHEN b_input => t (7 DOWNTO 0) := b_side;
c := c_flag_in; v := v_flag_in;
WHEN b_compl => t (7 DOWNTO 0) := NOT b_side;
c := c_flag_in; v := v_flag_in;
WHEN OTHERS => NULL;
END CASE;
n := t(7); z := set_if_zero (t); z_out <= t (7 DOWNTO 0);
out_flags <= v & c & z & n;
END PROCESS coding;
END behavioral;













Data_path.logic_units













Data_path.logic_units

ENTITY shifter_unit IS
PORT (alu_side : IN byte; arith_shift_left, arith_shift_right : IN qit;
in_flags : IN nibble; obus_side : OUT byte; out_flags : OUT nibble);
END shifter_unit;
--
ARCHITECTURE behavioral OF shifter_unit IS
BEGIN
coding: PROCESS (alu_side, arith_shift_left, arith_shift_right)
VARIABLE t : qit_vector (7 DOWNTO 0);
VARIABLE v, c, z, n : qit;
ALIAS n_flag_in : qit IS in_flags(0); ALIAS z_flag_in : qit IS in_flags(1);
ALIAS c_flag_in : qit IS in_flags(2); ALIAS v_flag_in : qit IS in_flags(3);
BEGIN
IF arith_shift_right = '0' AND arith_shift_left = '0' THEN
t := alu_side (7 DOWNTO 0);
n := n_flag_in; z := z_flag_in;
c := c_flag_in; v := v_flag_in;
ELSIF arith_shift_left = '1' THEN
t := alu_side (6 DOWNTO 0) & '0';
n := t (7); z := set_if_zero (t);
c := alu_side (7); v := alu_side (6) XOR alu_side (7);
ELSIF arith_shift_right = '1' THEN
t := alu_side (7) & alu_side (7 DOWNTO 1);
n := t (7); z := set_if_zero (t);
c := c_flag_in; v := v_flag_in;
END IF;
obus_side <= t; out_flags <= v & c & z & n;
END PROCESS coding;
END behavioral;













Data_path.registers













Data_path.registers

ENTITY status_register_unit IS
PORT (in_flags : IN nibble; out_status : OUT nibble;
load, cm_carry, ck : IN qit );
END status_register_unit;
--
ARCHITECTURE behavioral OF status_register_unit IS
BEGIN
PROCESS (ck)
VARIABLE internal_state : nibble := "0000";
ALIAS internal_z : qit IS internal_state (1);
ALIAS internal_c : qit IS internal_state (2);
BEGIN
IF (ck = '0') THEN
IF (load = '1') THEN
internal_state := in_flags;
ELSIF (cm_carry = '1') THEN
internal_c := NOT internal_c;
END IF;
out_status <= internal_state;
END IF;
END PROCESS;
END behavioral;













Data_path.registers













Data_path.registers

ENTITY accumulator_unit IS
PORT (i8 : IN byte; o8 : OUT byte; load, zero, ck : IN qit);
END accumulator_unit;
--
ARCHITECTURE dataflow OF accumulator_unit IS
BEGIN
enable : BLOCK (load = '1')
BEGIN
clocking : BLOCK ( (ck = '0' AND NOT ck'STABLE) AND GUARD )
BEGIN
o8 <= GUARDED "00000000" WHEN zero = '1' ELSE i8;
END BLOCK clocking;
END BLOCK enable;
END dataflow;













Data_path.registers













Data_path.registers

ENTITY instruction_register_unit IS
PORT (i8 : IN byte; o8 : OUT byte; load, ck : IN qit);
END instruction_register_unit;
--
ARCHITECTURE dataflow OF instruction_register_unit IS
BEGIN
enable : BLOCK (load = '1')
BEGIN
clocking : BLOCK ( (ck = '0' AND NOT ck'STABLE) AND GUARD )
BEGIN
o8 <= GUARDED i8;
END BLOCK clocking;
END BLOCK enable;
END dataflow;













Data_path.registers













Data_path.registers

ENTITY program_counter_unit IS
PORT (i12 : IN twelve; o12 : OUT twelve;
increment, load_page, load_offset, reset, ck : IN qit);
END program_counter_unit;
--
ARCHITECTURE behavioral OF program_counter_unit IS
BEGIN
PROCESS (ck)
VARIABLE internal_state : twelve := zero_12;
BEGIN
IF (ck = '0' ) THEN
IF reset = '1' THEN
internal_state := zero_12;
ELSIF increment = '1' THEN
internal_state := inc (internal_state);
ELSE
IF load_page = '1' THEN
internal_state (11 DOWNTO 8) := i12 (11 DOWNTO 8);
END IF;
IF load_offset = '1' THEN
internal_state (7 DOWNTO 0) := i12 (7 DOWNTO 0);
END IF;
END IF;
o12 <= internal_state;
END IF;
END PROCESS;
END behavioral;













Data_path.registers













Data_path.registers

ENTITY memory_address_register_unit IS
PORT (i12 : IN twelve; o12 : OUT twelve;
load_page, load_offset, ck : IN qit);
END memory_address_register_unit;
--
ARCHITECTURE behavioral OF memory_address_register_unit IS
BEGIN
PROCESS (ck)
VARIABLE internal_state : twelve := zero_12;
BEGIN
IF (ck = '0' ) THEN
IF load_page = '1' THEN
internal_state (11 DOWNTO 8) := i12 (11 DOWNTO 8);
END IF;
IF load_offset = '1' THEN
internal_state (7 DOWNTO 0) := i12 (7 DOWNTO 0);
END IF;
o12 <= internal_state;
END IF;
END PROCESS;
END behavioral;













Data_path.data_unit













Data_path.data_unit

ENTITY par_data_path IS
PORT (databus : INOUT wired_byte BUS := "ZZZZZZZZ"; adbus : OUT twelve;
clk : IN qit;
-- register controls:
load_ac, zero_ac,
load_ir,
increment_pc, load_page_pc, load_offset_pc, reset_pc,
load_page_mar, load_offset_mar,
load_sr, cm_carry_sr,
-- bus connections:
pc_on_mar_page_bus, ir_on_mar_page_bus,
pc_on_mar_offset_bus, dbus_on_mar_offset_bus,
pc_offset_on_dbus, obus_on_dbus, databus_on_dbus,
mar_on_adbus,
dbus_on_databus,
-- logic unit function control inputs:
arith_shift_left, arith_shift_right : IN qit;
alu_code : IN qit_vector (2 DOWNTO 0);
-- outputs to the controller:
ir_lines : OUT byte; status : OUT nibble
);
END par_data_path;













Data_path.data_unit

ARCHITECTURE structural OF par_data_path IS
--
COMPONENT ac
PORT (i8: IN byte; o8: OUT byte; load, zero, ck: IN qit);
END COMPONENT;
FOR r1: ac USE ENTITY WORK.accumulator_unit (dataflow);
--
COMPONENT ir
PORT (i8: IN byte; o8: OUT byte; load, ck: IN qit);
END COMPONENT;
FOR r2: ir USE ENTITY WORK.instruction_register_unit (dataflow);
--
COMPONENT pc
PORT (i12 : IN twelve; o12 : OUT twelve;
increment, load_page, load_offset, reset, ck : IN qit);
END COMPONENT;
FOR r3: pc USE ENTITY WORK.program_counter_unit (behavioral);
--
COMPONENT mar
PORT (i12 : IN twelve; o12 : OUT twelve;
load_page, load_offset, ck : IN qit);
END COMPONENT;
FOR r4: mar USE ENTITY WORK.memory_address_register_unit (behavioral);
--
COMPONENT sr
PORT (in_flags : IN nibble; out_status : OUT nibble;
load, cm_carry, ck : IN qit );
END COMPONENT;
FOR r5 : sr USE ENTITY WORK.status_register_unit (behavioral);
COMPONENT alu PORT (a_side, b_side : IN byte; code : IN qit_vector; in_flags : IN nibble; z_out : OUT byte; out_flags : OUT nibble); END COMPONENT; FOR l1 : alu USE ENTITY WORK.arithmetic_logic_unit (behavioral); -- COMPONENT shu PORT (alu_side : IN byte; arith_shift_left, arith_shift_right : IN qit; in_flags : IN nibble; obus_side : OUT byte; out_flags : OUT nibble); END COMPONENT; FOR l2 : shu USE ENTITY WORK.shifter_unit (behavioral);













Data_path.bus_resolution

SIGNAL ac_out, ir_out, alu_out, obus : byte;
SIGNAL alu_a_inp : byte;
SIGNAL pc_out, mar_out : twelve;
SIGNAL dbus : wired_byte BUS;
SIGNAL alu_flags, shu_flags, sr_out : nibble;
SIGNAL mar_bus : wired_twelve BUS;
SIGNAL mar_inp : twelve;













Data_path.bus_resolution

FUNCTION wire (a, b : qit) RETURN qit IS
CONSTANT qit_and_table : qit_2d := (
('0','X','0','X'),
('X','1','1','X'),
('0','1','Z','X'),
('X','X','X','X'));
BEGIN
RETURN qit_and_table (a, b);
END wire;

FUNCTION wiring ( drivers : qit_vector) RETURN qit IS
VARIABLE accumulate : qit := 'Z';
BEGIN
FOR i IN drivers'RANGE LOOP
accumulate := wire (accumulate, drivers(i));
END LOOP;
RETURN accumulate;
END wiring;

FUNCTION wiring ( drivers : qit_vector) RETURN qit;
SUBTYPE wired_qit IS wiring qit;
TYPE wired_qit_vector IS ARRAY (NATURAL RANGE <>) OF wired_qit;













Data_path.component_wiring

ARCHITECTURE
...
BEGIN

Bus connections
Write destinations of each bus

Register connections
Instantiate register, wire to its destinations

Wire registers and logic units
Instantiate logic with register outputs

END Structural













Data_path.component_wiring

BEGIN
-- bus connections --
dbus1: alu_a_inp <= qit_vector (dbus);
dbus2: BLOCK (dbus_on_mar_offset_bus = '1')
BEGIN mar_bus (7 DOWNTO 0) <= GUARDED dbus;END BLOCK dbus2;
dbus3: BLOCK (dbus_on_databus = '1')
BEGIN databus <= GUARDED dbus; END BLOCK dbus3;
--
obus1: BLOCK (obus_on_dbus = '1')
BEGIN dbus <= GUARDED wired_qit_vector (obus); END BLOCK obus1;
--
databus1: BLOCK (databus_on_dbus = '1')
BEGIN dbus <= GUARDED databus; END BLOCK databus1;
--
databus1: BLOCK (databus_on_dbus = '1')
BEGIN dbus <= GUARDED databus; END BLOCK databus1;
--
mar_bus1: mar_inp <= qit_vector (mar_bus);













Data_path.component_wiring

-- register connections --
r1: ac PORT MAP (obus, ac_out, load_ac, zero_ac, clk);
--
r2: ir PORT MAP (obus, ir_out, load_ir, clk);
ir1: ir_lines <= ir_out;
ir2: BLOCK (ir_on_mar_page_bus = '1') BEGIN
mar_bus (11 DOWNTO 8) <= GUARDED wired_qit_vector (ir_out (3 DOWNTO 0));
END BLOCK ir2;
r3: pc PORT MAP (mar_out, pc_out, increment_pc, load_page_pc, load_offset_pc, reset_pc, clk);
pc1: BLOCK (pc_on_mar_page_bus = '1') BEGIN
mar_bus (11 DOWNTO 8) <= GUARDED wired_qit_vector (pc_out (11 DOWNTO 8));
END BLOCK pc1;
pc2: BLOCK (pc_on_mar_offset_bus = '1') BEGIN
mar_bus (7 DOWNTO 0) <= GUARDED wired_qit_vector (pc_out (7 DOWNTO 0));
END BLOCK pc2;
pc3: BLOCK (pc_offset_on_dbus = '1') BEGIN
dbus <= GUARDED wired_qit_vector (pc_out (7 DOWNTO 0));
END BLOCK pc3;
--
r4: mar PORT MAP (mar_inp, mar_out, load_page_mar, load_offset_mar, clk);
mar1: BLOCK (mar_on_adbus = '1') BEGIN
adbus <= GUARDED mar_out;
END BLOCK mar1;
--
r5: sr PORT MAP (shu_flags, sr_out, load_sr, cm_carry_sr, clk); status <= sr_out;
END structural;













Data_path.component_wiring

-- connection of logical and register structures --
--
l1: alu PORT MAP (alu_a_inp, ac_out, alu_code, sr_out, alu_out, alu_flags);
l2: shu PORT MAP (alu_out, arith_shift_left, arith_shift_right, alu_flags, obus, shu_flags);













Data_path.conclusion

1. Outline: Introduction, Organization, Outline

2. Review: Levels of abstraction, Entity and Architecture, Signal assignments, Guarded signal assignments, Three state bussing, Process statements, Combinational processes, Sequential processes, Multiplexing, Package

3. MSI Based Design: Use MSI parts of Part 2, Sequential multiplication, Designing the multiplier, Control and data parts, Testing the multiplier

4. General CPU Description: Will present a high level VHDL description of a small CPU. The CPU, Memory organization, Instructions, Addressing, Utilities for VHDL description, Interface, Behavioral description, Coding individual instructions

5. Manual Data_path Design: Will present VHDL description for manual design of data_path. Data components, Bussing structure, Description of logic, Description of registers, Bus resolutions, Component wiring

6. Manual Controller Design: Will present VHDL description for manual design of controller. Controller hardware, VHDL style, Signals and resolutions, State descriptions, Complete CPU, Testing CPU

7. Synthesis: Main concepts, Structural synthesis, Combinational circuits, Functional registers, State machines

8. Behavioral_Synthesis: Will present a high level synthesizable CPU description. Synthesis style, Necessary Package, Interface, General Layout, Registers, Clocking, Sequencing, Simulation and Synthesis

9. Dataflow_Synthesis: Will partition the CPU and synthesize each part separately. Synthesis style, Controller, Data components, Data path, Synthesized example, Conclusions





to the top of the document