Procesador Utilizando la Metodología de Lenguaje VDHL
Código en Xilinx
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY procesador IS
PORT(clk,rst: IN std_logic;
r_w: OUT std_logic;
dir: OUT std_logic_vector(3 DOWNTO 0);
a_1: out std_logic_vector(3 DOWNTO 0);
dat_in1: IN std_logic_vector(3 DOWNTO 0);
dat_out1: OUT std_logic_vector(3 DOWNTO 0));
END procesador;
ARCHITECTURE descripcion OF procesador IS
TYPE estado IS (inicial,busqueda,ejec,ldxxa,ldaxx,anda,adda,suba);
SIGNAL a,pc,carga_a,carga_pc: std_logic_vector(3 DOWNTO 0);
SIGNAL rdat_in,dat_in,dat_out: std_logic_vector(3 DOWNTO 0);
SIGNAL rwaux: std_logic;
SIGNAL presente: estado:=inicial;
FUNCTION "+"(d1,d2: std_logic_vector(3 DOWNTO 0)) RETURN
std_logic_vector IS
VARIABLE sal: std_logic_vector(3 DOWNTO 0);
VARIABLE carry: std_logic:='0';
VARIABLE ind: INTEGER;
BEGIN
FOR ind IN 0 TO 3 LOOP
sal(ind):=d1(ind) XOR d2(ind) XOR carry;
carry:=(d1(ind) AND d2(ind)) OR (d1(ind) AND carry) OR (d2(ind) AND carry);
END LOOP;
RETURN sal;
END "+";
FUNCTION "-"(d1,d2: std_logic_vector(3 DOWNTO 0)) RETURN
std_logic_vector IS
BEGIN
RETURN d1+((NOT d2)+"0001");
END "-";
BEGIN
fsm:
PROCESS(clk,rst)
BEGIN
IF rst='1' THEN
presente<=inicial;
ELSIF clk='1' AND clk'event THEN
CASE presente IS
WHEN inicial =>
presente<=busqueda;
WHEN busqueda=>
IF dat_in(2 DOWNTO 0)="111" THEN presente<=busqueda;
ELSE presente<=ejec;
END IF;
WHEN ejec =>
CASE rdat_in(2 DOWNTO 0) IS
WHEN "010" =>
presente<=anda;
WHEN "000" =>
presente<=ldxxa;
WHEN "001" =>
presente<=ldaxx;
WHEN "011" =>
presente<=adda;
WHEN "100" =>
presente<=suba;
WHEN OTHERS => -- jz,jmp
presente<=busqueda;
END CASE;
WHEN OTHERS=>
presente<=busqueda;
END CASE;
END IF;
END PROCESS fsm;
salida:
PROCESS(presente,pc,a,rdat_in,dat_in)
BEGIN
CASE presente IS
WHEN inicial =>
carga_pc<="0000"; -- PC a 0
carga_a<="0000"; -- Acumulador a 0
dir<=pc; -- Dirección a 0;
rwaux<='1'; -- Lectura
WHEN busqueda=>
carga_pc<=pc+"0001"; -- Incrementa PC
carga_a<=a; -- Deja A como estaba
dir<=pc;
rwaux<='1';
WHEN ejec =>
CASE rdat_in(2 DOWNTO 0) IS
WHEN "101" => -- jz
dir<=pc;
IF a="0000" THEN
carga_pc<=dat_in; -- Salta si A=0
END IF;
rwaux<='1';
carga_a<=a;
WHEN "110" => --jmp
dir<=pc;
carga_pc<=dat_in; -- Salta siempre
rwaux<='1';
carga_a<=a;
WHEN OTHERS => -- Por defecto para el resto:
rwaux<='1'; -- Leer
dir<=pc; -- Dirección del operando
carga_pc<=pc;
carga_a<=a;
END CASE;
WHEN ldaxx =>
rwaux<='1';
carga_a<=dat_in;
carga_pc<=pc+"0001";
dir<=rdat_in;
WHEN ldxxa =>
rwaux<='0'; -- Único que escribe
carga_a<=a;
carga_pc<=pc+"0001";
dir<=rdat_in;
WHEN anda =>
rwaux<='1';
carga_a<=a AND dat_in;
carga_pc<=pc+"0001";
dir<=rdat_in;
WHEN adda =>
rwaux<='1';
carga_a<=a+dat_in;
carga_pc<=pc+"0001";
dir<=rdat_in;
WHEN suba =>
rwaux<='1';
carga_a<=a-dat_in;
carga_pc<=pc+"0001";
dir<=rdat_in;
END CASE;
END PROCESS salida;
registro_de_entrada:
PROCESS(clk,rst)
BEGIN
IF rst='1' THEN rdat_in<="0000";
ELSIF clk='1' AND clk'event THEN rdat_in<=dat_in;
END IF;
END PROCESS registro_de_entrada;
regs_con_carga:
PROCESS(clk,rst)
BEGIN
IF rst='1' THEN
a <="0000";
pc<="0000";
ELSIF clk='1' AND clk'event THEN
a <=carga_a;
pc<=carga_pc;
END IF;
END PROCESS regs_con_carga;
r_w<=rwaux; -- Para leer la salida.
-- Triestado de salida:
dat_in<=dat_in1;
dat_out<=a;
dat_out1<=dat_out WHEN rwaux='0' ELSE "ZZZZ";
a_1<=carga_a;
END descripcion;
No hay comentarios:
Publicar un comentario