MC14500B In VHDL

From Wiki
Jump to: navigation, search
-- VHDL description of Motorola MC14500B Industrial Control Unit
-- Copyright 2002, 2006 Eric Smith
-- $Id: mc14500b.vhdl,v 1.2 2006/10/29 03:04:47 eric Exp eric $

-- In the real MC14500B, there is an internal oscillator, which is stopped
-- when rst is asserted.  This model requires an externally supplied clock,
-- and treats rst as a synchronous input.

-- In the real MC14500B, the data pin is bidirectional.  In this model, for
-- ease of use in an FPGA, there are separate data_in and data_out signals.
-- These may be tied together externally to the model.

library ieee;
use ieee.std_logic_1164.all;

entity mc14500b is
  port (clk:      in std_logic;
        rst:      in std_logic;
        i:        in  std_logic_vector (3 downto 0);
        data_in:  in  std_logic;
        data_out: out std_logic;
        write:    out std_logic;
        jmp:      out std_logic;
        rtn:      out std_logic;
        flg0:     out std_logic;
        flgf:     out std_logic
       );
end mc14500b;

architecture behavioral of mc14500b is
  signal masked_data: std_logic;

  -- The MC14500B has an instruction register clocked on the falling
  -- edge of the clock input.
  signal ir: std_logic_vector (3 downto 0);

  
  -- The MC14500B has four internal state flip-flops, clocked on the
  -- rising edge of the clock input.
  signal ien: std_logic;
  signal oen: std_logic;
  signal skip: std_logic;
  signal rr: std_logic;
begin

  masked_data <= data_in and ien;

  flg0 <= '1' when ir = "0000" else '0';
  rtn  <= '1' when ir = "1101" else '0';
  jmp  <= '1' when ir = "1100" else '0';
  flgf <= '1' when ir = "1111" else '0';

  write <= '1' when skip = '0' and oen = '1' and (ir = "1000" or ir = "1001") else '0';

  -- It is not clear from the manual whether the MC14500B drives the data pin
  -- when there is a write instruction but OEN is zero.  I'm assuming that it
  -- does not, in order to avoid contention from the input selector.
  data_out <= rr     when skip = '0' and oen = '1' and ir = "1000" else
              not rr when skip = '0' and oen = '1' and ir = "1001" else
              'Z';

  process (clk) is
  begin
    if falling_edge (clk) then
      ir <= i;
    end if;
  end process;

  process (clk) is
  begin
    if rising_edge (clk) then

      if rst = '1' then
	   ien <= '0';
      elsif ir = "1010" and skip = '0' then
        ien <= data_in;
      end if;
      
      if rst = '1' then
        oen <= '0';
      elsif ir = "1011" and skip = '0' then
        oen <= data_in;
      end if;
							 
      if rst = '1' then
        skip <= '0';
      elsif skip = '1' then
        skip <= '0';
      elsif ir = "1101" then
        skip <= '1';
      elsif ir = "1110" and rr = '0' then
        skip <= '1';
      else
        skip <= '0';
      end if;
      
      if rst = '1' then
        rr <= '0';
      elsif ir = "0001" and skip = '0' then
        rr <= masked_data;
      elsif ir = "0010" and skip = '0' then
        rr <= not masked_data;
      elsif ir = "0011" and skip = '0' then
        rr <= rr and masked_data;
      elsif ir = "0100" and skip = '0' then
        rr <= rr and not masked_data;
      elsif ir = "0101" and skip = '0' then
        rr <= rr or masked_data;
      elsif ir = "0110" and skip = '0' then
        rr <= rr or not masked_data;
      elsif ir = "0111" and skip = '0' then
        rr <= rr xor not masked_data;
      end if;
      
    end if;
  end process;
end behavioral;