MC14500B In VHDL
From Wiki
Jump to navigationJump to 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;