PART 6
Manual Controller Design
Controller.onehot
- Only one hot state at a given time
- Easier design,
- No need for encoding states
- No need for decoding control lines
Controller.hardware
- Encoded state machine
- Requires more output and input logic
- Requires fewer flip-flops
Controller.hardware
- We will use a one hot controller
- Hardware surrounding a control flip-flop
- A control flip-flop conditionally activates control signals
Controller.hardware
- Control signals are issued by various control flip-flops
- Use OR gate for oring same-name control signals
- All signals activating a control flip-flop are ored
Controller.hardware
- Three control states and corresponding logic
- csy conditionally issued by j
- csx conditionally issued by i also unconditionally issued by k
Controller.VHDL_style
- ARCHITECTURE multiple_state_machine OF detector IS
- SIGNAL s : ored_bit_vector (1 TO 4) REGISTER := "1000";
- BEGIN
- clocking : BLOCK (clk = '1' AND NOT clk'STABLE)
- BEGIN
- s1: BLOCK (s(1) = '1' AND GUARD)
- BEGIN
- s(1) <= GUARDED '1' WHEN x = '0' ELSE '0';
- s(2) <= GUARDED '1' WHEN x = '1' ELSE '0';
- END BLOCK s1;
- s2: BLOCK (s(2) = '1' AND GUARD)
- BEGIN
- s(3) <= GUARDED '1' WHEN x = '0' ELSE '0';
- s(2) <= GUARDED '1' WHEN x = '1' ELSE '0';
- END BLOCK s2;
- s3: BLOCK (s(3) = '1' AND GUARD)
- BEGIN
- s(1) <= GUARDED '1' WHEN x = '0' ELSE '0';
- s(4) <= GUARDED '1' WHEN x = '1' ELSE '0';
- END BLOCK s3;
- s4: BLOCK (s(4) = '1' AND GUARD)
- BEGIN
- s(3) <= GUARDED '1' WHEN x = '0' ELSE '0';
- s(2) <= GUARDED '1' WHEN x = '1' ELSE '0';
- z <= '1' WHEN (s(4) = '1' AND x = '1') ELSE '0';
- END BLOCK s4;
- s <= GUARDED "0000";
- END BLOCK clocking;
- END multiple_state_machine;
- State machine description style
- A guarded block for each state
Controller.VHDL_style
sn: Block (guard on state n)
BEGIN
issue control signals
.
.
.
ck: Block (guard on clock)
issue next state;
END Block ck;
END Block sn;
- Issue control signals in each state
- A guarded block guards next state assignment
Controller.signals_and_resolutions
- Controller issues signals used by data
- Decisions made based on ir_lines
Controller.signals_and_resolutions
- ARCHITECTURE dataflow OF par_control_unit IS
- -- oring is implied in the following signals (oi)
- SIGNAL load_ac_oi, zero_ac_oi,
- load_ir_oi,
- increment_pc_oi, load_page_pc_oi, load_offset_pc_oi, reset_pc_oi,
- load_page_mar_oi, load_offset_mar_oi,
- load_sr_oi, cm_carry_sr_oi,
- pc_on_mar_page_bus_oi, ir_on_mar_page_bus_oi,
- pc_on_mar_offset_bus_oi, dbus_on_mar_offset_bus_oi,
- pc_offset_on_dbus_oi, obus_on_dbus_oi, databus_on_dbus_oi,
- mar_on_adbus_oi,
- dbus_on_databus_oi,
- arith_shift_left_oi, arith_shift_right_oi,
- read_mem_oi, write_mem_oi : ored_qit BUS;
- SIGNAL alu_code_oi : ored_qit_vector (2 DOWNTO 0) BUS;
- SIGNAL s : ored_qit_vector (9 DOWNTO 1) REGISTER := "000000001";
- Use resolved signals to imply oring
- Multiple assignments to oi signals are ored
- Declare s as a register of 9 states
Controller.signals_and_resolutions
FUNCTION oring ( drivers : qit_vector) RETURN qit;
SUBTYPE ored_qit IS oring qit;
TYPE ored_qit_vector IS ARRAY (NATURAL RANGE <>) OF ored_qit;
(a)
FUNCTION oring ( drivers : qit_vector) RETURN qit IS
VARIABLE accumulate : qit := '0';
BEGIN
FOR i IN drivers'RANGE LOOP
accumulate := accumulate OR drivers(i);
END LOOP;
RETURN accumulate;
END oring;
(b)
- Use oring resolution function
- All assignments to same state are ored
- All assignments to same control lines are ored
Controller.signals_and_resolutions
- Ored signals control flow of data in the data section
- Ored signals make appropriate state transitions
- Data and control signals follow the same timing
- Control signals are active from one falling edge to another
- One period allows propagation through logic and buses
Controller.signals_and_resolutions
- BEGIN
- -- implied or assignments to output signals
- load_ac <= load_ac_oi;
- zero_ac <= zero_ac_oi;
- load_ir <= load_ir_oi;
- increment_pc <= increment_pc_oi;
- load_page_pc <= load_page_pc_oi;
- load_offset_pc <= load_offset_pc_oi;
- reset_pc <= reset_pc_oi;
- load_page_mar <= load_page_mar_oi;
- load_offset_mar <= load_offset_mar_oi;
- load_sr <= load_sr_oi;
- cm_carry_sr <= cm_carry_sr_oi;
- pc_on_mar_page_bus <= pc_on_mar_page_bus_oi;
- ir_on_mar_page_bus <= ir_on_mar_page_bus_oi;
- pc_on_mar_offset_bus <= pc_on_mar_offset_bus_oi;
- dbus_on_mar_offset_bus <= dbus_on_mar_offset_bus_oi;
- pc_offset_on_dbus <= pc_offset_on_dbus_oi;
- obus_on_dbus <= obus_on_dbus_oi;
- databus_on_dbus <= databus_on_dbus_oi;
- mar_on_adbus <= mar_on_adbus_oi;
- dbus_on_databus <= dbus_on_databus_oi;
- arith_shift_left <= arith_shift_left_oi;
- arith_shift_right <= arith_shift_right_oi;
- read_mem <= read_mem_oi;
- write_mem <= write_mem_oi;
- alu_code <= qit_vector (alu_code_oi);
- Make assignments to do type conversion
Controller.state_descriptions
- s1: BLOCK (s(1) = '1')
- BEGIN -- start of fetch
- -- pc to mar
- pc_on_mar_page_bus_oi <= GUARDED '1';
- pc_on_mar_offset_bus_oi <= GUARDED '1';
- load_page_mar_oi <= GUARDED '1';
- load_offset_mar_oi <= GUARDED '1';
- -- reset pc if interrupt
- reset_pc_oi <= GUARDED '1' WHEN interrupt = '1' ELSE '0';
- -- goto 2 if interrupt is off
- ck: BLOCK ( (clk = '0' AND NOT clk'STABLE) AND GUARD )
- BEGIN
- s(1) <= GUARDED '1' WHEN interrupt = '1' ELSE '0';
- s(2) <= GUARDED '1' WHEN interrupt /= '1' ELSE '0';
- END BLOCK ck;
- END BLOCK s1;
- Start to fetch in state 1
- Transfer pc to mar via mar_bus
- Stay in state 1 if interrupted
Controller.state_descriptions
- s2: BLOCK (s(2) = '1')
- BEGIN -- fetching continues
- -- read memory into ir
- mar_on_adbus_oi <= GUARDED '1';
- read_mem_oi <= GUARDED '1' AFTER read_delay;
- databus_on_dbus_oi <= GUARDED '1';
- alu_code_oi <= GUARDED ored_qit_vector (a_input);
- load_ir_oi <= GUARDED '1';
- -- increment pc
- increment_pc_oi <= GUARDED '1';
- -- goto 3
- ck: BLOCK ( (clk = '0' AND NOT clk'STABLE) AND GUARD )
- BEGIN
- s(3) <= GUARDED '1';
- END BLOCK ck;
- END BLOCK s2;
- Continue to fetch instruction
- Read memory into ir
Controller.state_descriptions
- s3: BLOCK (s(3) = '1')
- BEGIN
- -- pc to mar, for next read
- pc_on_mar_page_bus_oi <= GUARDED '1';
- pc_on_mar_offset_bus_oi <= GUARDED '1';
- load_page_mar_oi <= GUARDED '1';
- load_offset_mar_oi <= GUARDED '1';
- -- goto 4 if not single byte instruction
- ck: BLOCK ( (clk = '0' AND NOT clk'STABLE) AND GUARD )
- BEGIN
- s(4) <= GUARDED '1' WHEN ir_lines (7 DOWNTO 4) /= "1110" ELSE '0';
- END BLOCK ck;
- -- perform single byte instructions
- sb: BLOCK ( (ir_lines (7 DOWNTO 4) = "1110") AND GUARD)
- BEGIN
- alu_code_oi <= GUARDED
- ored_qit_vector (b_compl) WHEN ir_lines (1) = '1' ELSE
- ored_qit_vector (b_input);
- arith_shift_left_oi <= GUARDED
- '1' WHEN ir_lines (3 DOWNTO 0) = "1000" ELSE '0';
- arith_shift_right_oi <= GUARDED
- '1' WHEN ir_lines (3 DOWNTO 0) = "1001" ELSE '0';
- load_sr_oi <= GUARDED
- '1' WHEN ( ir_lines (3) = '1' OR ir_lines (1) = '1' ) ELSE '0';
- cm_carry_sr_oi <= GUARDED '1' WHEN ir_lines (2) = '1' ELSE '0';
- load_ac_oi <= GUARDED
- '1' WHEN ( ir_lines (3) = '1' OR ir_lines (1) = '1' ) ELSE '0';
- zero_ac_oi <= GUARDED
- '1' WHEN ( ir_lines (3) = '0' AND ir_lines (0) = '1' ) ELSE '0';
- ck: BLOCK ( (clk = '0' AND NOT clk'STABLE) AND GUARD )
- BEGIN
- s(2) <= GUARDED '1';
- END BLOCK ck;
- END BLOCK sb;
- END BLOCK s3;
- For two byte instructions:
Prepare for address fetch, goto state 4
- For single byte instructions:
Prepare for next instruction fetch, complete current instruction
Controller.state_descriptions
- Hardware for state3
- Logic block is enabled to do single_byte instructions
- pc to mar transfer takes place
Controller.state_descriptions
- s4: BLOCK (s(4) = '1')
- BEGIN -- page from ir, and offset from next memory makeup 12-bit address
- -- read memory into mar offset
- mar_on_adbus_oi <= GUARDED '1';
- read_mem_oi <= GUARDED '1' AFTER read_delay;
- databus_on_dbus_oi <= GUARDED '1';
- dbus_on_mar_offset_bus_oi <= GUARDED '1';
- load_offset_mar_oi <= GUARDED '1'; -- completed operand (dir/indir) address
- -- page from ir if not branch or jsr
- pg: BLOCK ( (ir_lines (7 DOWNTO 6) /= "11") AND GUARD)
- BEGIN
- ir_on_mar_page_bus_oi <= GUARDED '1';
- load_page_mar_oi <= GUARDED '1';
- -- goto 5 for indirect, 6 for direct
- ck: BLOCK ( (clk = '0' AND NOT clk'STABLE) AND GUARD )
- BEGIN
- s(5) <= GUARDED '1' WHEN ir_lines (4) = '1' ELSE '0'; -- indir
- s(6) <= GUARDED '1' WHEN ir_lines (4) = '0' ELSE '0'; -- direct
- END BLOCK ck;
- END BLOCK pg;
- -- keep page in mar_page if jms or bra (same-page instructions)
- sp: BLOCK ( (ir_lines (7 DOWNTO 6) = "11") AND GUARD)
- BEGIN
- -- fot 7 for jsr, 9 for bra
- ck: BLOCK ( (clk = '0' AND NOT clk'STABLE) AND GUARD )
- BEGIN
- s(7) <= GUARDED '1' WHEN ir_lines (5) = '0' ELSE '0'; -- jsr
- s(9) <= GUARDED '1' WHEN ir_lines (5) = '1' ELSE '0'; -- bra
- END BLOCK ck;
- END BLOCK sp;
- -- increment pc
- increment_pc_oi <= GUARDED '1';
- END BLOCK s4;
- Get operand for page and full instructions
- For full address : use page from ir, offset from mar
- For page address: keep mar page unchanged
Controller.state_descriptions
- Hardware for state 4
- ir to mar occurs only when ir(7:6)=11
Controller.state_descriptions
- s5: BLOCK (s(5) = '1')
- BEGIN -- indirect addressing
- -- read actual operand from memory into mar offset
- mar_on_adbus_oi <= GUARDED '1';
- read_mem_oi <= GUARDED '1' AFTER read_delay;
- databus_on_dbus_oi <= GUARDED '1';
- dbus_on_mar_offset_bus_oi <= GUARDED '1';
- load_offset_mar_oi <= GUARDED '1';
- -- goto 6
- ck: BLOCK ( (clk = '0' AND NOT clk'STABLE) AND GUARD )
- BEGIN
- s(6) <= GUARDED '1';
- END BLOCK ck;
- END BLOCK s5;
- Access memory with full address for indirect
- Load byte from memory to mar offset
Controller.state_descriptions
- s6: BLOCK (s(6) = '1')
- BEGIN
- jm : BLOCK ( (ir_lines (7 DOWNTO 5) = "100" ) AND GUARD
- BEGIN
- ... perform jmp
- END BLOCK jm;
- st: BLOCK ( (ir_lines (7 DOWNTO 5) = "101") AND GUARD)
- BEGIN
- ... perform sta
- END BLOCK st;
- rd: BLOCK ( (ir_lines (7) = '0') AND GUARD)
- BEGIN
- ... perform lda, and, add, sub
- END BLOCK rd;
- END BLOCK s6;
- Full address instructions are handled here
- Three separate blocks for
1) jmp
2) sta
3) lda, and, add, sub
Controller.state_descriptions
- s6: BLOCK (s(6) = '1') BEGIN
- jm: BLOCK ( (ir_lines (7 DOWNTO 5) = "100") AND GUARD)
- BEGIN
- load_page_pc_oi <= GUARDED '1';
- load_offset_pc_oi <= GUARDED '1';
- -- goto 2
- ck: BLOCK ( (clk = '0' AND NOT clk'STABLE) AND GUARD )
- BEGIN
- s(2) <= GUARDED '1';
- END BLOCK ck;
- END BLOCK jm;
- . . .
- . . .
Controller.state_descriptions
- s6: BLOCK (s(6) = '1') BEGIN
- . . .
- st: BLOCK ( (ir_lines (7 DOWNTO 5) = "101") AND GUARD)
- BEGIN
- -- mar on adbus, ac on databus, write to memory
- mar_on_adbus_oi <= GUARDED '1';
- alu_code_oi <= GUARDED ored_qit_vector (b_input);
- obus_on_dbus_oi <= GUARDED '1';
- dbus_on_databus_oi <= GUARDED '1';
- write_mem_oi <= GUARDED '1' AFTER write_delay;
- -- goto 1
- ck: BLOCK ( (clk = '0' AND NOT clk'STABLE) AND GUARD )
- BEGIN
- s(1) <= GUARDED '1';
- END BLOCK ck;
- END BLOCK st;
- . . .
- For sta, write ac to memory via alu
- Assume writing is completed in one clock
Controller.state_descriptions
s6: BLO