plain CS/EE 5750/6750: Asynchronous Circuit Design

CS/EE 5750/6750: Asynchronous Circuit Design

Chris J. Myers
Lecture 2: Communication Channels
Chapter 2

Communication Channels

Libraries and Packages

-- wine_example.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all; 
use work.nondeterminism.all;
use work.channel.all;

Entities/Architectures

entity wine_example is          
end wine_example;

architecture behavior of wine_example is 
-- declarations
begin
-- concurrent statements
end behavior;

Signal Declarations

  type wine_type is (cabernet, merlot, zinfandel, 
       chardonnay, sauvignon_blanc, pinot_noir, 
       riesling, bubbly);
  signal wine_drunk : wine_type;
  signal winery_to_shop : channel := init_channel;
  signal shop_to_patron : channel := init_channel;
  signal bottle : std_logic_vector( 2 downto 0 ) := "000";
  signal shelf : std_logic_vector( 2 downto 0 );
  signal brown_bag : std_logic_vector( 2 downto 0);

Std_Logic Values

`U' Unitialized
`X' Forcing unknown
`0' Forcing 0
`1' Forcing 1
`Z' High impedance
`W' Weak unknown
`L' Weak 0
`H' Weak 1
`-' Don't care

Concurrent Processes: winery

winery : process
begin
     send(winery_to_shop,bottle);
     bottle <= bottle + 1;
     wait for 5 ns;
end process winery;

Concurrent Processes: shop

shop : process
begin
     receive(winery_to_shop,shelf);
     send(shop_to_patron,shelf);
end process shop;

Concurrent Processes: patron

patron : process
begin
     receive(shop_to_patron,brown_bag);
     wine_drunk <= wine_type'val(conv_integer(brown_bag));
end process patron;

Block Diagram for wine_shop

Figure

Structural Modeling: wineshop.vhd

entity wine_shop is
  port(wine_delivery : inout channel:=init_channel;
       wine_selling : inout channel:=init_channel );
end wine_shop;
architecture behavior of wine_shop is 
  signal shelf : std_logic_vector( 2 downto 0 );
begin
shop : process
begin
     receive(wine_delivery,shelf);
     send(wine_selling,shelf);
end process shop;
end behavior;

Structural Modeling: winery.vhd

entity winery is                
  port(wine_shipping : inout channel:=init_channel);
end winery;
architecture behavior of winery is 
  signal bottle : std_logic_vector( 2 downto 0 ) := "000";
begin
winery : process
begin
     send(wine_shipping,bottle);
     bottle <= bottle + 1;
     wait for 5 ns;
end process winery;
end behavior;

Structural Modeling: patron.vhd

architecture behavior of patron is 
  type wine_type is (cabernet, merlot, zinfandel, 
       chardonnay, sauvignon_blanc, pinot_noir, 
       riesling, bubbly);
  signal wine_drunk : wine_type;
  signal brown_bag : std_logic_vector( 2 downto 0 );
begin
patron : process
begin
     receive(wine_buying,brown_bag);
     wine_drunk <= wine_type'val(conv_integer(brown_bag));
end process patron;
end behavior;

Structural Modeling: wine_example2.vhd

-- same header
entity wine_example2 is                 
end wine_example2;

architecture structure of wine_example2 is 
  -- component and signal declarations
begin
  -- component instantiations
end structure;

Component Declarations

  component winery
    port(wine_shipping : inout channel);
  end component;
  component wine_shop
    port(wine_delivery : inout channel;
         wine_selling : inout channel);
  end component;
  component patron 
    port(wine_buying : inout channel);
  end component;
  signal winery_to_shop : channel := init_channel;
  signal shop_to_patron : channel := init_channel;

Component Instantiations

architecture structure of wine_example2 is 
  -- declarations
begin
  THE_WINERY : winery 
      port map(wine_shipping => winery_to_shop);
  THE_SHOP : wine_shop 
      port map(wine_delivery => winery_to_shop,
              wine_selling => shop_to_patron);
  THE_PATRON : patron 
      port map(wine_buying => shop_to_patron);
end structure;

Block Diagram Including New Wine Shop

Figure

VHDL with New Wine Shop

architecture new_structure of wine_example3 is 
  -- component declarations
  -- channel declarations
begin
  -- winery
  OLD_SHOP : wine_shop 
      port map(wine_delivery => winery_to_shop,
               wine_selling => shop1_to_shop2);
  NEW_SHOP : wine_shop 
      port map(wine_delivery => shop1_to_shop2,
               wine_selling => shop_to_patron);
  -- patron
end new_structure;

Deterministic Selection: if-then-else

winery : process
begin
  if (wine_type'val(conv_integer(bottle))=chardonnay) then
    send(wine_to_new_shop,bottle);
  else
    send(wine_to_old_shop,bottle);
  end if;
  bottle <= bottle + 1;
  wait for 5 ns;
end process winery;

Deterministic Selection: case

winery : process
begin
  case (wine_type'val(conv_integer(bottle))) is
  when chardonnay =>
    send(wine_to_new_shop,bottle);
  when others =>
    send(wine_to_old_shop,bottle);
  end case;
  bottle <= bottle + 1;
  wait for 5 ns;
end process winery;

Non-deterministic Selection: if-then-else

winery : process
variable z : integer;
begin
  z := selection(2);
  if (z = 1) then
    send(wine_to_new_shop,bottle);
  else
    send(wine_to_old_shop,bottle);
  end if;
  bottle <= bottle + 1;
  wait for 5 ns;
end process winery;

Non-deterministic Selection: case

winery : process
variable z : integer;
begin
  z := selection(2);
  case z is
  when 1 =>
    send(wine_to_new_shop,bottle);
  when others =>
    send(wine_to_old_shop,bottle);
  end case;
  bottle <= bottle + 1;
  wait for 5 ns;
end process winery;

Repetition: for loops

winery : process
begin
  for i in 1 to 4 loop
    send(wine_to_old_shop,bottle);
    bottle <= bottle + 1;
    wait for 5 ns;
  end loop;
  for i in 1 to 3 loop
    send(wine_to_new_shop,bottle);
    bottle <= bottle + 1;
    wait for 5 ns;
  end loop;
end process winery;

Repetition: while loops

winery : process
begin
  while (wine_type'val(conv_integer(bottle))/=chardonnay) 
  loop
    send(wine_to_old_shop,bottle);
    bottle <= bottle + 1;
    wait for 5 ns;
  end loop;
  send(wine_to_new_shop,bottle);
  bottle <= bottle + 1;
  wait for 5 ns;
end process winery;

Repetition: infinite loops

winery : process
begin
  send(wine_to_old_shop,bottle);
  bottle <= bottle + 1;
  wait for 5 ns;
  loop
    send(wine_to_new_shop,bottle);
    bottle <= bottle + 1;
    wait for 5 ns;
  end loop;
end process winery;

Block Diagram Including New Wine Shop

Figure

The Probe

patron : process
begin
  if (probe(old_shop_to_patron)) then 
    receive(old_shop_to_patron,brown_bag);
    wine_drunk <= wine_type'val(conv_integer(brown_bag));
  elsif (probe(new_shop_to_patron)) then
    receive(new_shop_to_patron,brown_bag);
    wine_drunk <= wine_type'val(conv_integer(brown_bag));
  end if;
  wait for 2 ns;
end process patron;

Parallel Send

winery : process
begin
  send(wine_to_old_shop,bottle1,
       wine_to_new_shop,bottle2);
  bottle1 <= bottle1 + 1;
  bottle2 <= bottle2 + 1;
  wait for 5 ns;
end process winery;

Parallel Receive

patron : process
begin
  receive(old_shop_to_patron,brown_bag1,
          new_shop_to_patron,brown_bag2);
  wine_drunk1 <= wine_type'val(conv_integer(brown_bag1));
  wine_drunk2 <= wine_type'val(conv_integer(brown_bag2));
end process patron;

MiniMIPS: ISA

Instruction Operation Example
add rd : = rs + rt add r1, r2, r3
sub rd : = rs - rt sub r1, r2, r3
and rd : = rs & rt and r1, r2, r3
or rd : = rs | rt or r1, r2, r3
lw rt : = mem[rs + offset] lw r1, (32)r2
sw mem[rs + offset] : = rt sw r1, (32)r2
beq if (rs = = rt) then beq r1, r2, Loop
PC : = PC + offset
j PC : = address j Loop

MiniMIPS: ISA

Instruction Opcode Func
add 0 32
sub 0 34
and 0 36
or 0 37
lw 35 n/a
sw 43 n/a
beq 4 n/a
j 6 n/a

MiniMIPS: Instruction Formats

Register instructions
opcode rs rt rd shamt func
6 5 5 5 5 6
Load/store/branch instructions
opcode rs rt offset
6 5 5 16
Jump instructions
opcode address
6 26

Block Diagram for MiniMIPS

Figure

Block Diagram for MiniMIPS

Figure

MiniMIPS: minimips.vhd

-- Entity/architecture declarations 
-- ieee stuff
use work.channel.all;
entity minimips is
end minimips;

architecture structure of minimips is
    -- Component declarations
    -- Signal declarations
begin
    -- Component instances
end structure;

MiniMIPS: imem.vhd

-- ieee stuff
use work.nondeterminism.all;
use work.channel.all;
entity imem is
  port(address : inout channel:=init_channel;
       data : inout channel:=init_channel); 		
end imem;
architecture behavior of imem is
  type mem_array is array (0 to 7) of 
    std_logic_vector(31 downto 0);
  signal addr : std_logic_vector(31 downto 0);
  signal instr: std_logic_vector(31 downto 0);
begin

MiniMIPS: imem.vhd

process
  variable imem : mem_array := (
    X"8c220000", -- L: lw $2,0($1)
    ...);
begin
  receive(address,addr);
  instr <= imem(conv_integer(addr(2 downto 0)));
  wait for 5 ns;
  send(data,instr);
end process;

MiniMIPS: fetch.vhd

entity fetch is
  port(imem_address : inout channel:=init_channel; 
       imem_data : inout channel:=init_channel;
       decode_instr : inout channel:=init_channel;
       branch_decision : inout channel:=init_channel); 		
end fetch;
architecture behavior of fetch is 
  signal PC:std_logic_vector(31 downto 0):=(others=>'0');
  signal instr : std_logic_vector( 31 downto 0);
  signal bd : std_logic_vector( 0 downto 0 );
  alias opcode is instr(31 downto 26);
  alias offset is instr(15 downto 0);
  alias address is instr(25 downto 0); 

MiniMIPS: fetch.vhd

process
  variable branch_offset : std_logic_vector(31 downto 0);
begin
  send(imem_address,PC);
  receive(imem_data,instr);
  PC <= PC + 1;
  wait for 5 ns;
  case opcode is
  when "000110" => -- j
    PC <= (PC(31 downto 26) & address);
    wait for 5 ns;

MiniMIPS: fetch.vhd

  when "000100" => -- beq
    send(decode_instr,instr);
    receive(branch_decision,bd);
    if (bd = "1") then
      branch_offset(31 downto 16):=(others => instr(15));
      branch_offset(15 downto 0):=offset;
      PC <= PC + branch_offset;
      wait for 5 ns;
    end if;
  when others => 
    send(decode_instr,instr);
  end case;
end process;

MiniMIPS: decode.vhd

entity decode is
  port(decode_instr : inout channel:=init_channel;
       execute_op : inout channel:=init_channel;
       execute_rs : inout channel:=init_channel;
       execute_rt : inout channel:=init_channel;
       execute_rd : inout channel:=init_channel;
       execute_func : inout channel:=init_channel;
       execute_offset : inout channel:=init_channel;
       dmem_datain : inout channel:=init_channel;
       dmem_dataout : inout channel:=init_channel); 		
end decode;

MiniMIPS: decode.vhd

  type reg_array is array (0 to 7) of 
       std_logic_vector(31 downto 0);
  signal instr : std_logic_vector( 31 downto 0);
  alias op is instr(31 downto 26);
  alias rs is instr(23 downto 21);
  alias rt is instr(18 downto 16);
  alias rd is instr(13 downto 11);
  alias func is instr(5 downto 0);
  alias offset is instr(15 downto 0);
  signal registers : reg_array := (X"00000000",...);
  signal reg_rs : std_logic_vector(31 downto 0);
  signal reg_rt : std_logic_vector(31 downto 0);
  signal reg_rd : std_logic_vector(31 downto 0);

MiniMIPS: decode.vhd

process
begin
  receive(decode_instr,instr);
  case op is
  when "000100" => -- beq
    send(execute_op,op);
    reg_rs <= registers(conv_integer(rs));
    reg_rt <= registers(conv_integer(rt));
    wait for 5 ns;
    send(execute_rs,reg_rs);
    send(execute_rt,reg_rt);

MiniMIPS: decode.vhd

  when "000000" => -- ALU op
    send(execute_op,op);
    send(execute_func,func);
    reg_rs <= registers(conv_integer(rs));
    reg_rt <= registers(conv_integer(rt));
    wait for 5 ns;
    send(execute_rs,reg_rs);   
    send(execute_rt,reg_rt);
    receive(execute_rd,reg_rd);
    registers(conv_integer(rd)) <= reg_rd;
    wait for 5 ns;

MiniMIPS: decode.vhd

  when "100011" => -- lw
    send(execute_op,op);
    reg_rs <= registers(conv_integer(rs));
    wait for 5 ns;
    send(execute_rs,reg_rs);
    send(execute_offset,offset);
    receive(dmem_dataout,reg_rt);
    registers(conv_integer(rt)) <= reg_rt;
    wait for 5 ns;

MiniMIPS: decode.vhd

  when "101011" => -- sw
    send(execute_op,op);
    reg_rs <= registers(conv_integer(rs));
    reg_rt <= registers(conv_integer(rt));
    wait for 5 ns;
    send(execute_rs,reg_rs);
    send(execute_offset,offset);
    send(dmem_datain,reg_rt);
  when others => -- undefined
    assert false
    report "Illegal instruction"
    severity error;
  end case;

MiniMIPS: execute.vhd

entity execute is
  port(execute_op : inout channel:=init_channel;
       execute_rs : inout channel:=init_channel;
       execute_rt : inout channel:=init_channel;
       execute_rd : inout channel:=init_channel;
       execute_func : inout channel:=init_channel;
       execute_offset : inout channel:=init_channel;
       dmem_addr : inout channel:=init_channel;
       dmem_rw : inout channel:=init_channel;
       branch_decision : inout channel:=init_channel); 		
end execute;

MiniMIPS: execute.vhd

architecture behavior of execute is 
  signal rs : std_logic_vector(31 downto 0);
  signal rt : std_logic_vector(31 downto 0);
  signal rd : std_logic_vector(31 downto 0);
  signal op : std_logic_vector(5 downto 0);
  signal func : std_logic_vector(5 downto 0);
  signal offset : std_logic_vector(15 downto 0);
  signal rw : std_logic_vector(0 downto 0);
  signal bd : std_logic_vector(0 downto 0);
begin

MiniMIPS: execute.vhd

process begin
  receive(execute_op,op);
  case op is
  when "000100" => -- beq
    receive(execute_rs,rs);
    receive(execute_rt,rt);
    if (rs = rt) then
      bd <= "1";
    else
      bd <= "0";
    end if;
    wait for 5 ns;
    send(branch_decision,bd);

MiniMIPS: execute.vhd

  when "000000" => -- ALU op
    receive(execute_func,func);
    receive(execute_rs,rs);
    receive(execute_rt,rt);
    case func is
    when "100000" => -- add
      rd <= rs + rt;
    when "100010" => -- sub
      rd <= rs - rt;
    when "100100" => -- and
      rd <= rs and rt;
    when "100101" => -- or
      rd <= rs or rt;

MiniMIPS: execute.vhd

    when others =>
      rd <= (others => 'X'); -- undefined
    end case;
    wait for 5 ns;
    send(execute_rd,rd);

MiniMIPS: execute.vhd

  when "100011" => -- lw
    receive(execute_rs,rs);
    receive(execute_offset,offset);
    rd <= rs + ("0000000000000000" & offset);
    rw <= "1";
    wait for 5 ns;
    send(dmem_addr,rd);
    send(dmem_rw,rw);

MiniMIPS: execute.vhd

  when "101011" => -- sw
    receive(execute_rs,rs);
    receive(execute_offset,offset);
    rd <= rs + ("0000000000000000" & offset);
    rw <= "0";
    wait for 5 ns;
    send(dmem_addr,rd);
    send(dmem_rw,rw);
  when others => -- undefined
    wait for 5 ns;
  end case;
  end process;
end behavior;

MiniMIPS: dmem.vhd

entity dmem is
  port(address : inout channel:=init_channel;
       data_in : inout channel:=init_channel;
       data_out : inout channel:=init_channel;
       read_write : inout channel:=init_channel); 		
end dmem;
architecture behavior of dmem is
  type mem_array is array (0 to 7) of 
    std_logic_vector(31 downto 0);
  signal addr : std_logic_vector(31 downto 0);
  signal d : std_logic_vector(31 downto 0);
  signal rw : std_logic_vector(0 downto 0);
  signal dmem : mem_array := (X"00000000", ...);

MiniMIPS: dmem.vhd

  receive(address,addr);
  receive(read_write,rw);
  case rw is
  when "1" => 
    d <= dmem(conv_integer(addr(2 downto 0)));
    wait for 5 ns;
    send(data_out,d);
  when "0" =>
    receive(data_in,d);
    dmem(conv_integer(addr(2 downto 0))) <= d;
    wait for 5 ns;
  when others => wait for 5 ns;

Deadlock

producer:process
begin
  send(X,x);
  send(Y,y);
end process producer;

consumer:process
begin
  receive(Y,a);
  receive(X,b);
end process consumer;

Optimized MiniMIPS: decode.vhd

  when "000000" => -- ALU op
    send(execute_func,func,execute_rs,reg_rs,
         execute_rt,reg_rt);   
    -- same
  when "000100" => -- beq
    send(execute_rs,reg_rs,execute_rt,reg_rt);
  when "100011" => -- lw
    send(execute_rs,reg_rs,execute_offset,offset);
    -- same
  when "101011" => -- sw
    send(execute_rs,reg_rs,execute_offset,offset,
         dmem_datain,reg_rt);

Optimized MiniMIPS: execute.vhd

  when "000000" => -- ALU op
    receive(execute_func,func,execute_rs,rs,
            execute_rt,rt);
    -- same
  when "000100" => -- beq
    receive(execute_rs,rs,execute_rt,rt);
    -- same
  when "100011" => -- lw
    receive(execute_rs,rs,execute_offset,offset);
    -- same
    send(dmem_addr,rd,dmem_rw,rw);
  when "101011" => -- sw
    -- same as lw

Optimized MiniMIPS: dmem.vhd

process
begin
  receive(address,addr,read_write,rw);
  -- same
end process;

RAW Hazards

  • r1 contains 1.
  • r2 contains 2.

add r1,r2,r2
add r4,r1,r1

Pipelined MiniMIPS: decode.vhd

  signal reg_locks : bool_array(0 to 7) 
         := (others => false);
  signal decode_to_wb : channel:=init_channel;
  signal wb_instr : std_logic_vector(31 downto 0);
  alias wb_op is wb_instr(31 downto 26);
  alias wb_rt is wb_instr(18 downto 16);
  alias wb_rd is wb_instr(13 downto 11);
  signal lock : channel:=init_channel;

Pipelined MiniMIPS: decode.vhd

  receive(decode_instr,instr);
  if ((reg_locks(conv_integer(rs))) or 
      (reg_locks(conv_integer(rt)))) then
    wait until ((not reg_locks(conv_integer(rs))) and 
                (not reg_locks(conv_integer(rt))));
  end if;
  reg_rs <= registers(conv_integer(rs));
  reg_rt <= registers(conv_integer(rt));
  send(execute_op,op);
  wait for 5 ns;

Pipelined MiniMIPS: decode.vhd

  when "000000" => -- ALU op
    if (reg_locks(conv_integer(rd))) then
      wait until not reg_locks(conv_integer(rd));
    end if;
    send(execute_func,func,execute_rs,reg_rs,
         execute_rt,reg_rt);
    send(decode_to_wb,instr);
    receive(lock);

Pipelined MiniMIPS: decode.vhd

  when "100011" => -- lw
    send(execute_rs,reg_rs,execute_offset,offset);
    send(decode_to_wb,instr);
    receive(lock);

Pipelined MiniMIPS: decode.vhd

writeback:process
begin
  receive(decode_to_wb,wb_instr);
  case wb_op is 
  when "000000" => -- ALU op
    reg_locks(conv_integer(wb_rd)) <= true;
    wait for 1 ns;
    send(lock);
    receive(execute_rd,reg_rd);
    registers(conv_integer(wb_rd)) <= reg_rd;
    wait for 5 ns;
    reg_locks(conv_integer(wb_rd)) <= false;
    wait for 5 ns;

Pipelined MiniMIPS: decode.vhd

  when "100011" => -- lw
    reg_locks(conv_integer(wb_rt)) <= true;
    wait for 1 ns;
    send(lock);
    receive(dmem_dataout,reg_rd);
    registers(conv_integer(wb_rt)) <= reg_rd;
    wait for 5 ns;
    reg_locks(conv_integer(wb_rt)) <= false;
    wait for 5 ns;
  when others => -- undefined
    wait for 5 ns;
  end case;
end process; 

Summary

  • Channel package
  • Send and receive procedures
  • Structural modeling
  • Selection and repetition
  • The probe
  • Parallel composition
  • MiniMIPS


File translated from TEX by TTH, version 2.22.
On 17 Jan 2000, 20:21.