digital electronics
dffre1.txt
-- 8-bit register (D flip-flop) with synchronous enable and reset library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity dffre is generic (N : integer); port( clk : in STD_LOGIC; en : in STD_LOGIC; rst: in STD_LOGIC; d : in STD_LOGIC_VECTOR(N-1 downto 0); q : out STD_LOGIC_VECTOR(N-1 downto 0) ); end dffre; architecture Behavioral of dffre is begin process(clk) begin if rising_edge(clk) then if rst='1' then q<=(others=>'0'); else if en='1' then q<=d; end if; end if; end if; end process; end Behavioral;
edgedetect1.txt
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity edgedetect is port( clk : in STD_LOGIC; din : in STD_LOGIC; dout : out STD_LOGIC ); end edgedetect; architecture Behavioral of edgedetect is signal last : STD_LOGIC; begin process(clk) begin if rising_edge(clk) then last <= din; end if; end process; dout <= din and not last; end Behavioral;
hexto7seg1.txt
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.std_logic_unsigned.ALL; entity hexto7seg is port( clk: in std_logic; d7: in std_logic_vector(3 downto 0); d6: in std_logic_vector(3 downto 0); d5: in std_logic_vector(3 downto 0); d4: in std_logic_vector(3 downto 0); d3: in std_logic_vector(3 downto 0); d2: in std_logic_vector(3 downto 0); d1: in std_logic_vector(3 downto 0); d0: in std_logic_vector(3 downto 0); blink: in std_logic_vector(7 downto 0); q: out std_logic_vector(6 downto 0); active : out std_logic_vector(7 downto 0) ); end hexto7seg; architecture Behavioral of hexto7seg is signal a: std_logic; signal b: std_logic; signal c: std_logic; signal d: std_logic; signal qt: std_logic_vector(6 downto 0); signal ctr: std_logic_vector(2 downto 0); signal divider: std_logic_vector(25 downto 0); begin p1: process(clk) begin if rising_edge(clk) then divider<=divider+1; end if; end process; p2: process(clk) begin if rising_edge(clk) then if divider(9 downto 0)="0000000000" then ctr<=ctr+1; end if; end if; end process; -- input mux with ctr select a <= d0(3) when "000", d1(3) when "001", d2(3) when "010", d3(3) when "011", d4(3) when "100", d5(3) when "101", d6(3) when "110", d7(3) when others; with ctr select b <= d0(2) when "000", d1(2) when "001", d2(2) when "010", d3(2) when "011", d4(2) when "100", d5(2) when "101", d6(2) when "110", d7(2) when others; with ctr select c <= d0(1) when "000", d1(1) when "001", d2(1) when "010", d3(1) when "011", d4(1) when "100", d5(1) when "101", d6(1) when "110", d7(1) when others; with ctr select d <= d0(0) when "000", d1(0) when "001", d2(0) when "010", d3(0) when "011", d4(0) when "100", d5(0) when "101", d6(0) when "110", d7(0) when others; -- Output mux with ctr select active <= "11111110" when "000", "11111101" when "001", "11111011" when "010", "11110111" when "011", "11101111" when "100", "11011111" when "101", "10111111" when "110", "01111111" when others; -- Blinking q(0) <= (blink(to_integer(unsigned(ctr))) and divider(25)) or qt(0); q(1) <= (blink(to_integer(unsigned(ctr))) and divider(25)) or qt(1); q(2) <= (blink(to_integer(unsigned(ctr))) and divider(25)) or qt(2); q(3) <= (blink(to_integer(unsigned(ctr))) and divider(25)) or qt(3); q(4) <= (blink(to_integer(unsigned(ctr))) and divider(25)) or qt(4); q(5) <= (blink(to_integer(unsigned(ctr))) and divider(25)) or qt(5); q(6) <= (blink(to_integer(unsigned(ctr))) and divider(25)) or qt(6); qt(0) <= not ( (not a and not b and not c and not d ) or (not a and not b and c and not d) or (not a and not b and c and d) or (not a and b and not c and d) or (not a and b and c and not d) or (not a and b and c and d) or (a and not b and not c and not d) or (a and not b and not c and d) or (a and not b and c and not d) or (a and b and not c and not d) or (a and b and c and not d) or (a and b and c and d) ); qt(1) <= not ( (not a and not b and not c and not d) or (not a and not b and not c and d) or (not a and not b and c and not d) or (not a and not b and c and c) or (not a and b and not c and not d) or (not a and b and c and d) or (a and not b and not c and not d) or (a and not b and not c and d) or (a and not b and c and not d) or (a and b and not c and d) ); qt(2) <= not ( (not a and not b and not c and not d) or (not a and not b and not c and d) or (not a and not b and c and d) or (not a and b and not c and not d) or (not a and b and not c and d) or (not a and b and c and not d) or (not a and b and c and d) or (a and not b and not c and not d) or (a and not b and not c and d) or (a and not b and c and not d) or (a and not b and c and d) or (a and b and not c and d) ); qt(3) <= not ((not a and not b and not c and not d) or (not a and not b and c and not d) or (not a and not b and c and d) or (not a and b and not c and d) or (not a and b and c and not d) or (a and not b and not c and not d) or (a and not b and c and d) or (a and b and not c and not d) or (a and b and not c and d) or (a and b and c and not d) ); --qt(4) <= not ((not a and not b and not c and not d) -- or (not a and not b and c and not d) -- or (not a and b and c and not d) -- or (a and not b and not c and not d) -- or (a and not b and c and not d) -- or (a and not b and c and d) -- or (a and b and not c and not d) -- or (a and b and not c and d) -- or (a and b and c and not d) -- or (a and b and c and d) ); --qt(5) <= not ((not a and not b and not c and not d) -- or (not a and b and not c and not d) -- or (not a and b and not c and d) -- or (not a and b and c and not d) -- or (a and not b and not c and not d) -- or (a and not b and not c and d) -- or (a and not b and c and not d) -- or (a and not b and c and d) -- or (a and b and not c and not d) -- or (a and b and c and not d) -- or (a and b and c and d) ); --qt(6) <= not ((not a and not b and c and not d) -- or (not a and not b and c and d) -- or (not a and b and not c and not d) -- or (not a and b and not c and d) -- or (not a and b and c and not d) -- or (a and not b and not c and not d) -- or (a and not b and not c and d) -- or (a and not b and c and not d) -- or (a and not b and c and d) -- or (a and b and not c and d) -- or (a and b and c and not d) -- or (a and b and c and d) ); -- Minimized expression: qt(4) <= not( (a and b) or (a and c) or (c and not d) or (not b and not d) ); qt(5) <= not( (b and not d) or (not a and b and not c) or (a and not b) or (a and c) or (not c and not d) ); qt(6) <= not( (not a and b and not c) or (a and not b) or (a and d) or (not b and c and d) or (c and not d) ); end Behavioral;
labcpu1.txt
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity main is Port ( clk : in STD_LOGIC; btnU : in STD_LOGIC; btnD : in STD_LOGIC; btnL : in STD_LOGIC; btnC : in STD_LOGIC; btnR : in STD_LOGIC; btnCpuReset : in STD_LOGIC; sw : in STD_LOGIC_VECTOR (15 downto 0); led : out STD_LOGIC_VECTOR (15 downto 0); seg : out STD_LOGIC_VECTOR(6 downto 0); an : out STD_LOGIC_VECTOR(7 downto 0) ); end main; architecture Structural of main is signal reset : STD_LOGIC; -- clocks signal clkmain : STD_LOGIC; signal clkslow : STD_LOGIC; signal cpu_ram_we : STD_LOGIC; signal cpu_ram_address : STD_LOGIC_VECTOR(4 downto 0); signal cpu_ram_datawr : STD_LOGIC_VECTOR(7 downto 0); signal cpu_ram_datard : STD_LOGIC_VECTOR(7 downto 0); signal ramedit_address : STD_LOGIC_VECTOR(4 downto 0); signal ramedit_data : STD_LOGIC_VECTOR(7 downto 0); signal ramedit_enable : STD_LOGIC; signal ramedit_we : STD_LOGIC; -- Display signals signal display_d7 : STD_LOGIC_VECTOR(3 downto 0); signal display_d6 : STD_LOGIC_VECTOR(3 downto 0); signal display_d5 : STD_LOGIC_VECTOR(3 downto 0); signal display_d4 : STD_LOGIC_VECTOR(3 downto 0); signal display_d3 : STD_LOGIC_VECTOR(3 downto 0); signal display_d2 : STD_LOGIC_VECTOR(3 downto 0); signal display_d1 : STD_LOGIC_VECTOR(3 downto 0); signal display_d0 : STD_LOGIC_VECTOR(3 downto 0); signal display_blink : STD_LOGIC_VECTOR(7 downto 0); signal cpu_d0, cpu_d1, cpu_d2, cpu_d3, cpu_d4, cpu_d5, cpu_d6, cpu_d7 : STD_LOGIC_VECTOR(3 downto 0); -- RAM signals signal ramclk : STD_LOGIC; signal ram_address : STD_LOGIC_VECTOR(4 downto 0); signal ram_datain : STD_LOGIC_VECTOR(7 downto 0); signal ram_we : STD_LOGIC; signal ram_dataout : STD_LOGIC_VECTOR(7 downto 0); -- debouncing signal btnUd,btnDd,btnLd,btnCd,btnRd,btnCpuResetd : STD_LOGIC; signal sw15d,sw13d : STD_LOGIC; -- edge detect signal btnUde,btnDde,btnLde,btnRde : STD_LOGIC; -- Only for CPU debugging signal dbg_qa : STD_LOGIC_VECTOR(7 downto 0); signal dbg_qb : STD_LOGIC_VECTOR(7 downto 0); signal dbg_qc : STD_LOGIC_VECTOR(7 downto 0); signal dbg_qd : STD_LOGIC_VECTOR(7 downto 0); signal dbg_instr : STD_LOGIC_VECTOR(15 downto 0); signal dbg_seq : STD_LOGIC_VECTOR(1 downto 0); signal dbg_flags : STD_LOGIC_VECTOR(3 downto 0); begin -- Debouncing comp_deb1 : entity work.debounce port map(clk=>clk,button=>btnC,result=>btnCd); comp_deb2 : entity work.debounce port map(clk=>clk,button=>btnU,result=>btnUd); comp_deb3 : entity work.debounce port map(clk=>clk,button=>btnD,result=>btnDd); comp_deb4 : entity work.debounce port map(clk=>clk,button=>btnL,result=>btnLd); comp_deb5 : entity work.debounce port map(clk=>clk,button=>btnR,result=>btnRd); comp_deb6 : entity work.debounce port map(clk=>clk,button=>btnCpuReset,result=>btnCpuResetd); comp_deb7 : entity work.debounce port map(clk=>clk,button=>sw(15),result=>sw15d); comp_deb8 : entity work.debounce port map(clk=>clk,button=>sw(13),result=>sw13d); -- Edge detectors on some buttons (for RAM editor) comp_edg1 : entity work.edgedetect port map(clk=>clk,din=>btnLd,dout=>btnLde); comp_edg2 : entity work.edgedetect port map(clk=>clk,din=>btnRd,dout=>btnRde); comp_edg3 : entity work.edgedetect port map(clk=>clk,din=>btnUd,dout=>btnUde); comp_edg4 : entity work.edgedetect port map(clk=>clk,din=>btnDd,dout=>btnDde); -- slow clock -- comp_clk : entity work.clkdiv generic map(N=>25) port map(clkin=>clk,clkout=>clkslow); -- Reset -- reset <= not btnCpuResetd; -- Toggle the RAM edit mode according to sw15d -- ramedit_enable <= sw15d; -- Display debug status on LEDs -- led(15) <= ramedit_enable; led(14) <= clkmain; led(13 downto 12) <= dbg_seq; led(11 downto 8) <= dbg_flags; -- Display multiplexers: toggle between ram edit and cpu mode display_blink <= "00"&ramedit_enable&ramedit_enable&ramedit_enable&ramedit_enable&ramedit_enable&ramedit_enable; display_d7 <= "0000" when ramedit_enable='1' else cpu_d7; display_d6 <= "0000" when ramedit_enable='1' else cpu_d6; display_d5 <= "000"&ram_address(4 downto 4) when ramedit_enable='1' else cpu_d5; display_d4 <= ram_address(3 downto 0) when ramedit_enable='1' else cpu_d4; display_d3 <= sw(7 downto 4) when ramedit_enable='1' else cpu_d3; display_d2 <= sw(3 downto 0) when ramedit_enable='1' else cpu_d2; display_d1 <= ram_dataout(7 downto 4) when ramedit_enable='1' else cpu_d1; display_d0 <= ram_dataout(3 downto 0) when ramedit_enable='1' else cpu_d0; -- Display multiplexers: toggle cpu display modes cpu_d7 <= dbg_qa(7 downto 4); cpu_d6 <= dbg_qa(3 downto 0); cpu_d5 <= dbg_qb(7 downto 4) when sw(14)='1' else "000"&cpu_ram_address(4 downto 4); cpu_d4 <= dbg_qb(3 downto 0) when sw(14)='1' else cpu_ram_address(3 downto 0); cpu_d3 <= dbg_qc(7 downto 4) when sw(14)='1' else dbg_instr(15 downto 12); cpu_d2 <= dbg_qc(3 downto 0) when sw(14)='1' else dbg_instr(11 downto 8); cpu_d1 <= dbg_qd(7 downto 4) when sw(14)='1' else dbg_instr(7 downto 4); cpu_d0 <= dbg_qd(3 downto 0) when sw(14)='1' else dbg_instr(3 downto 0); -- Instantiate the 7-segment display -- comp1: entity work.hexto7seg port map( clk=>clk, d7=>display_d7, d6=>display_d6, d5=>display_d5, d4=>display_d4, d3=>display_d3, d2=>display_d2, d1=>display_d1, d0=>display_d0, blink=>display_blink, q=>seg, active=>an); --comp2: entity work.clkdiv generic map (N => 26) port map( clkin=>clk,clkout=>clkmain ); --led(15)<=clkmain; clkmain <= not ramedit_enable and( (btnCd and not sw13d) or (clkslow and sw13d)); -- Instantiate RAM -- RAM clock is either board clock in edit mode, or manual clock ramclk <= clk when sw15d='1' else clkmain; comp3: entity work.ram generic map(N=>5) port map(clk=>ramclk,address=>ram_address,data=>ram_datain,we=>ram_we,q=>ram_dataout); -- Instantiate the RAM editor comp_ramedit: entity work.ramedit generic map(N=>5) port map(clk=>clk,rst=>reset,btnU=>btnUde,btnD=>btnDde,btnL=>btnLde,btnR=>btnRde,din=>sw, we=>ramedit_we,address=>ramedit_address,data=>ramedit_data); -- Multiplex the editor and the CPU to the RAM -- ram_we <= ramedit_we when ramedit_enable='1' else cpu_ram_we; ram_address <= ramedit_address when ramedit_enable='1' else cpu_ram_address; ram_datain <= ramedit_data when ramedit_enable='1' else cpu_ram_datawr; -- Instantiate the CPU comp_cpu: entity work.CPU generic map(N=>5) port map(clk=>clkmain,rst=>reset,ext_in=>sw(7 downto 0),ext_out=>led(7 downto 0), ram_we=>cpu_ram_we,ram_address=>cpu_ram_address,ram_datawr=>cpu_ram_datawr,ram_datard=>ram_dataout, dbg_qa=>dbg_qa,dbg_qb=>dbg_qb,dbg_qc=>dbg_qc,dbg_qd=>dbg_qd, dbg_instr=>dbg_instr,dbg_seq=>dbg_seq,dbg_flags=>dbg_flags); end Structural;
ram1.txt
LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; ENTITY ram IS generic(N : integer); PORT ( clk: IN std_logic; address: IN STD_LOGIC_VECTOR(N-1 downto 0); data: IN STD_LOGIC_VECTOR(7 downto 0); we: IN std_logic; q: OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ); END ram; ARCHITECTURE rtl OF ram IS TYPE mem IS ARRAY(0 TO 2**N-1) OF std_logic_vector(7 DOWNTO 0); SIGNAL ram_block : mem := ( -- Put the initial content of the memory here. Note: provide exactly 32 bytes X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00" ); BEGIN PROCESS(clk) BEGIN IF rising_edge(clk) THEN IF we = '1' THEN ram_block(to_integer(unsigned(address))) <= data; END IF; END IF; END PROCESS; q <= ram_block(to_integer(unsigned(address))); END rtl;
ramedit1.txt
-- RAM editor -- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ramedit is generic(N : integer); port( clk : in STD_LOGIC; rst : in STD_LOGIC; btnU : in STD_LOGIC; btnD : in STD_LOGIC; btnL : in STD_LOGIC; btnR : in STD_LOGIC; din : in STD_LOGIC_VECTOR(15 downto 0); we : out STD_LOGIC; address : out STD_LOGIC_VECTOR(N-1 downto 0); data : out STD_LOGIC_VECTOR(7 downto 0) ); end ramedit; architecture Behavioral of ramedit is -- Register with the address we currently wish to edit signal address_edit : STD_LOGIC_VECTOR(N-1 downto 0); begin process(clk,rst) begin if rising_edge(clk) then if rst='1' then address_edit<=(others=>'0'); else if btnU='1' and btnD='0' then address_edit <= address_edit+1; elsif btnU='0' and btnD='1' then address_edit <= address_edit-1; elsif btnL='1' then address_edit <= din(8+N-1 downto 8); end if; end if; end if; end process; we <= btnR; address <= address_edit; data <= din(7 downto 0); end Behavioral;
clkdiv1.txt
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity clkdiv is generic(N : integer); port ( clkin : in STD_LOGIC; clkout : out STD_LOGIC ); end clkdiv; architecture Behavioral of clkdiv is signal divider : STD_LOGIC_VECTOR(N-1 downto 0); begin process(clkin) begin if rising_edge(clkin) then divider<=divider+1; end if; end process; clkout<=divider(N-1); end Behavioral;
cpu1.txt
---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity cpu is generic(N : integer); port( clk : in STD_LOGIC; rst : in STD_LOGIC; ext_in : in STD_LOGIC_VECTOR(7 downto 0); ext_out : out STD_LOGIC_VECTOR(7 downto 0); ram_we : out STD_LOGIC; ram_address : out STD_LOGIC_VECTOR(N-1 downto 0); ram_datawr : out STD_LOGIC_VECTOR(7 downto 0); ram_datard : in STD_LOGIC_VECTOR(7 downto 0); -- Only for debugging dbg_qa : out STD_LOGIC_VECTOR(7 downto 0); dbg_qb : out STD_LOGIC_VECTOR(7 downto 0); dbg_qc : out STD_LOGIC_VECTOR(7 downto 0); dbg_qd : out STD_LOGIC_VECTOR(7 downto 0); dbg_instr : out STD_LOGIC_VECTOR(15 downto 0); dbg_seq : out STD_LOGIC_VECTOR(1 downto 0); dbg_flags : out STD_LOGIC_VECTOR(3 downto 0) ); end cpu; architecture Behavioral of cpu is -- Instruction signal instruction : STD_LOGIC_VECTOR(15 downto 0); -- Helper signal source : STD_LOGIC_VECTOR(7 downto 0); signal wrdata : STD_LOGIC_VECTOR(7 downto 0); -- register bank signal regwren : STD_LOGIC; signal reg1out : STD_LOGIC_VECTOR(7 downto 0); signal reg2out : STD_LOGIC_VECTOR(7 downto 0); -- flags signal flagwren : STD_LOGIC; signal flags : STD_LOGIC_VECTOR(3 downto 0); -- zf, ovf, cf, sf signal zf,ovf,cf,sf : STD_LOGIC; -- fetch/execute signals signal seq : STD_LOGIC_VECTOR(1 downto 0); signal execute,fetch,fetchh,fetchl : STD_LOGIC; -- Instruction pointer signal ip: STD_LOGIC_VECTOR(N-1 downto 0); signal ipnext: STD_LOGIC_VECTOR(N-1 downto 0); -- ALU input and output signals signal aluqout: STD_LOGIC_VECTOR(7 downto 0); signal alufout : STD_LOGIC_VECTOR(3 downto 0); -- Jumps signal jump : STD_LOGIC; signal jumpip: STD_LOGIC_VECTOR(N-1 downto 0); signal jumpconditionvalid : STD_LOGIC; -- External interface signal ext_wren : STD_LOGIC; -- Debug signals --signal tdbg_qa,tdbg_qb,tdbg_qc,tdbg_qd : STD_LOGIC_VECTOR(7 downto 0); begin --------------------------------------------------------------------------------------- -- Fetch/Execute -- Fetch/Execute -- Fetch/Execute -- Fetch/Execute -- Fetch/Execute -- --------------------------------------------------------------------------------------- -- Instantiate a fetch/exec sequencer. Seq is 00 for load1, 01 for load2, 10 for execute comp_seq: entity work.cpusequencer port map(clk=>clk,rst=>rst,en=>'1',seq=>seq); -- Binary to one hot fetchh <= '1' when seq="00" else '0'; fetchl <= '1' when seq="01" else '0'; execute <= '1' when seq="10" else '0'; fetch <= fetchl or fetchh; -- Instantiate two 8-bit registers to store the 16-bit instruction during the fetchl and fetchh cycles. comp_instrh: entity work.dffre generic map(N=>8) port map(clk=>clk,rst=>rst,en=>fetchh,d=>ram_datard,q=>instruction(15 downto 8)); comp_instrl: entity work.dffre generic map(N=>8) port map(clk=>clk,rst=>rst,en=>fetchl,d=>ram_datard,q=>instruction(7 downto 0)); --------------------------------------------------------------------------------------- -- Instruction pointer --------------------------------------------------------------------------------------- comp_ip: entity work.dffre generic map(N=>N) port map(clk=>clk,rst=>rst,en=>'1',d=>ipnext,q=>ip); ipnext <= ip+1 when fetch='1' else ip when jump='0' else jumpip; --------------------------------------------------------------------------------------- -- Register bank -- Register bank -- Register bank -- Register bank -- Register bank -- --------------------------------------------------------------------------------------- -- Instantiate the register bank -- Always map the register 1 and register 2 to the source and destination registers in the instruction fields -- Always map the write register to destination register in instruction field. -- Always map the write input to wrdata comp_regs: entity work.cpuregbank port map(clk=>clk,rrd1=>instruction(9 downto 8),rrd2=>instruction(1 downto 0),rwr=>instruction(9 downto 8),rwren=>regwren,rst=>rst,d=>wrdata,q1=>reg1out,q2=>reg2out, dbg_qa=>dbg_qa,dbg_qb=>dbg_qb,dbg_qc=>dbg_qc,dbg_qd=>dbg_qd); -- Write to register for move instructions with direct destination, or ALU instructions except cmp. regwren <= '1' when execute='1' and instruction(15 downto 13) = "000" and instruction(11)='0' else -- opcode 000 (move) '1' when execute='1' and instruction(15 downto 13) = "001" else -- opcode 001 (add,sub,and,or) '1' when execute='1' and instruction(15 downto 13) = "010" and instruction(11 downto 10) /= "01" else -- opcode 010 (all except cmp) '1' when execute='1' and instruction(15 downto 13) = "011" else -- opcode 011 '1' when execute='1' and instruction(15 downto 13) = "110" and instruction(11 downto 10) = "01" else -- opcode 110 (io) '0'; -------------------------------------------------------------------------------------------- -- Helper -- Helper -- Helper -- Helper -- Helper -- Helper -- Helper -- Helper -- Helper -- -------------------------------------------------------------------------------------------- -- Almost all instructions using a source have register or immediate mode. We source <= reg2out when instruction(12)='0' else instruction(7 downto 0); ------------------------------------------------------------------------------- -- ALU -- ALU -- ALU -- ALU -- ALU -- ALU -- ALU -- ALU -- ALU -- ALU -- ALU -- ------------------------------------------------------------------------------- -- Instantiate ALU comp_alu: entity work.cpualu port map(clk=>clk,rst=>rst,op=>instruction(14 downto 10),a=>reg1out,b=>source,q=>aluqout,f=>alufout); ----------------------------------------------------------------------------------- -- Flags -- Flags -- Flags -- Flags -- Flags -- Flags -- Flags -- Flags -- Flags -- ----------------------------------------------------------------------------------- -- instantiate register to store the flags comp_flags: entity work.dffre generic map(N=>4) port map(clk=>clk,rst=>rst,en=>flagwren,d=>alufout,q=>flags); -- When to write the flags: execute phase and compare instruction flagwren <= '1' when execute='1' and instruction(15 downto 13)="010" and instruction(11 downto 10)="01" else '0'; -- Individual signals for each flag zf <= flags(3); ovf <= flags(2); cf <= flags(1); sf <= flags(0); ----------------------------------------------------------------------------------- -- Jump -- Jump -- Jump -- Jump -- Jump -- Jump -- Jump -- Jump -- Jump -- Jump -- ----------------------------------------------------------------------------------- -- Jump destinatinon is register or immediate jumpip <= source(N-1 downto 0); -- Do jump when the instruction is a jump and the jump condition is met jump <= '1' when instruction(15 downto 13) = "101" and jumpconditionvalid='1' else '0'; -- Jump condition jumpconditionvalid <= '1' when instruction(11 downto 8) = "0000" else -- Unconditional jump '1' when instruction(11 downto 8) = "0001" and zf='1' else -- je/jz '1' when instruction(11 downto 8) = "1001" and zf='0' else -- jne/jnz '1' when instruction(11 downto 8) = "0010" and zf='0' and cf='0' else -- ja '1' when instruction(11 downto 8) = "1011" and zf='0' and cf='1' else -- jb '0'; --------------------------------------------------------------------------------------- -- RAM interface -- RAM interface -- RAM interface -- RAM interface -- RAM interface -- --------------------------------------------------------------------------------------- -- ram address to read instruction and read or write data ram_address <= ip when fetch='1' else reg2out(N-1 downto 0) when instruction(15 downto 10)="000001" else instruction(N-1 downto 0) when instruction(15 downto 10)="000101" else reg1out(N-1 downto 0) when instruction(15 downto 10)="000010" else reg1out(N-1 downto 0) when instruction(15 downto 10)="000110" else (others=>'0'); --"00000"; -- Enable write ram_we <= '1' when execute='1' and instruction(15 downto 13)="000" and instruction(11 downto 10)="10" else '0'; -- Data to write ram_datawr <= wrdata; ------------------------------------------------------------------------------------------ -- External interface -- External interface -- External interface -- External interface -- ------------------------------------------------------------------------------------------ -- Instantiate a register to hold the output interface data comp_regextout : entity work.dffre generic map (N=>8) port map(clk=>clk,rst=>rst,en=>ext_wren,d=>source,q=>ext_out); ext_wren <= '1' when execute='1' and instruction(15 downto 13) = "110" and instruction(11 downto 10)="00" else '0'; -------------------------------------------------------------------------------------- -- Write data -- Write data -- Write data -- Write data -- Write data -- Write data -- -------------------------------------------------------------------------------------- -- Data may be written to ram or memory. The enable signals in the ram and register instances -- control whether the write occurs. -- Here we define what to write. wrdata <= source when instruction(15 downto 13) = "000" and instruction(11 downto 10)="00" else -- Move with register or immediate as source source when instruction(15 downto 13) = "000" and instruction(11 downto 10)="10" else -- Move with register or immediate as source ram_datard when instruction(15 downto 13) = "000" and instruction(11 downto 10)="01" else -- Move with memory as source aluqout when instruction(15 downto 13) = "001" else -- ALU aluqout when instruction(15 downto 13) = "010" else -- ALU aluqout when instruction(15 downto 13) = "011" else -- ALU ext_in when instruction(15 downto 13) = "110" and instruction(11 downto 10)="01" else -- Instruction in: read external input "00000000"; -- Only for debugging dbg_instr <= instruction; dbg_seq <= seq; dbg_flags <= flags; end Behavioral;
cpualu1.txt
-- ALU -- The ALU uses 1 or 2 operands -- The opcode are bits 14,13,12,11,10 of the instruction -- a: input A of ALU -- b: input B of ALU (not used for single operand instructions) -- q: result (except for compare which is not used) -- f: flag vectors with zero flag, overflow flag, carry flag and sign flag. library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity cpualu is port ( clk : in STD_LOGIC; rst : in STD_LOGIC; op : in STD_LOGIC_VECTOR(4 downto 0); a : in STD_LOGIC_VECTOR(7 downto 0); b : in STD_LOGIC_VECTOR(7 downto 0); q : out STD_LOGIC_VECTOR(7 downto 0); f : out STD_LOGIC_VECTOR(3 downto 0) ); end cpualu; architecture Behavioral of cpualu is signal sub : STD_LOGIC_VECTOR(8 downto 0); -- Do subtraction on 9 bits to obtain the carry signal r: STD_LOGIC_VECTOR(7 downto 0); -- ALU result signal zf,ovf,cf,sf : STD_LOGIC; begin --comp_rng: entity work.rng port map(clk=>clk,rst=>rst sub <= ('0'&a) - ('0'&b); r <= a+b when op(4 downto 3)="01" and op(1 downto 0)="00" else sub(7 downto 0) when op(4 downto 3)="01" and op(1 downto 0)="01" else a and b when op(4 downto 3)="01" and op(1 downto 0)="10" else a or b when op(4 downto 3)="01" and op(1 downto 0)="11" else a xor b when op(4 downto 3)="10" and op(1 downto 0)="00" else not a when op(4 downto 0)="11000" else '0'&a(7 downto 1) when op(4 downto 0)="11001" else a(0)&a(7 downto 1) when op(4 downto 0)="11010" else a(7)&a(7 downto 1) when op(4 downto 0)="11011" else a(6 downto 0)&a(7) when op(4 downto 0)="11100" else "00000000"; sf <= sub(7); zf <= not(sub(7) or sub(6) or sub(5) or sub(4) or sub(3) or sub(2) or sub(1) or sub(0)); cf <= sub(8); ovf <= (not a(7) and b(7) and sub(7)) or (a(7) and not b(7) and not sub(7)); f<=zf&ovf&cf&sf; q<=r; end Behavioral;
cpuregbank1.txt
-- CPU register banks holding the 4 CPU registers. -- This is used to simplify the reading and writing to registers -- by allowing to address them with a 2-bit address and enable signal. library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity cpuregbank is port( clk : in STD_LOGIC; rrd1 : in STD_LOGIC_VECTOR(1 downto 0); rrd2 : in STD_LOGIC_VECTOR(1 downto 0); rwr : in STD_LOGIC_VECTOR(1 downto 0); rwren : in STD_LOGIC; rst : in STD_LOGIC; d : in STD_LOGIC_VECTOR(7 downto 0); q1 : out STD_LOGIC_VECTOR(7 downto 0); q2 : out STD_LOGIC_VECTOR(7 downto 0); -- Only for debugging dbg_qa : out STD_LOGIC_VECTOR(7 downto 0); dbg_qb : out STD_LOGIC_VECTOR(7 downto 0); dbg_qc : out STD_LOGIC_VECTOR(7 downto 0); dbg_qd : out STD_LOGIC_VECTOR(7 downto 0) ); end cpuregbank; architecture Behavioral of cpuregbank is signal enables: STD_LOGIC_VECTOR(3 downto 0); signal qa,qb,qc,qd: STD_LOGIC_VECTOR(7 downto 0); begin ra: entity work.dffre generic map (N=>8) port map(clk=>clk,en=>enables(0),rst=>rst,d=>d,q=>qa); rb: entity work.dffre generic map (N=>8) port map(clk=>clk,en=>enables(1),rst=>rst,d=>d,q=>qb); rc: entity work.dffre generic map (N=>8) port map(clk=>clk,en=>enables(2),rst=>rst,d=>d,q=>qc); rd: entity work.dffre generic map (N=>8) port map(clk=>clk,en=>enables(3),rst=>rst,d=>d,q=>qd); with rwr select enables <= "0001" and rwren&rwren&rwren&rwren when "00", "0010" and rwren&rwren&rwren&rwren when "01", "0100" and rwren&rwren&rwren&rwren when "10", "1000" and rwren&rwren&rwren&rwren when others; with rrd1 select q1 <= qa when "00", qb when "01", qc when "10", qd when others; with rrd2 select q2 <= qa when "00", qb when "01", qc when "10", qd when others; -- Only for debugging dbg_qa <= qa; dbg_qb <= qb; dbg_qc <= qc; dbg_qd <= qd; end Behavioral;
cpusequencer1.txt
-- Generates the CPU state sequence seq: ld1 (00), ld2 (01), exec (10) -- Implementation with a D FF with synchronous reset and enable library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity cpusequencer is port( clk : in STD_LOGIC; rst : in STD_LOGIC; en : in STD_LOGIC; seq : out STD_LOGIC_VECTOR(1 downto 0) ); end cpusequencer; architecture Behavioral of cpusequencer is signal s : STD_LOGIC_VECTOR(1 downto 0); begin process(clk,rst) begin if rising_edge(clk) then if rst='1' then s<="00"; else if en='1' then if s="10" then s <= "00"; else s <= s+1; end if; end if; end if; end if; end process; seq <= s; end Behavioral;
debounce1.txt
-------------------------------------------------------------------------------- -- -- FileName: debounce.vhd -- Dependencies: none -- Design Software: Quartus II 32-bit Version 11.1 Build 173 SJ Full Version -- -- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY -- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY -- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL -- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF -- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS -- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), -- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. -- -- Version History -- Version 1.0 3/26/2012 Scott Larson -- Initial Public Release -- -------------------------------------------------------------------------------- LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; ENTITY debounce IS GENERIC( counter_size : INTEGER := 19); --counter size (19 bits gives 10.5ms with 50MHz clock) PORT( clk : IN STD_LOGIC; --input clock button : IN STD_LOGIC; --input signal to be debounced result : OUT STD_LOGIC); --debounced signal END debounce; ARCHITECTURE logic OF debounce IS SIGNAL flipflops : STD_LOGIC_VECTOR(1 DOWNTO 0); --input flip flops SIGNAL counter_set : STD_LOGIC; --sync reset to zero SIGNAL counter_out : STD_LOGIC_VECTOR(counter_size DOWNTO 0) := (OTHERS => '0'); --counter output BEGIN counter_set <= flipflops(0) xor flipflops(1); --determine when to start/reset counter PROCESS(clk) BEGIN IF(clk'EVENT and clk = '1') THEN flipflops(0) <= button; flipflops(1) <= flipflops(0); If(counter_set = '1') THEN --reset counter because input is changing counter_out <= (OTHERS => '0'); ELSIF(counter_out(counter_size) = '0') THEN --stable input time is not yet met counter_out <= counter_out + 1; ELSE --stable input time is met result <= flipflops(1); END IF; END IF; END PROCESS; END logic;