diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..48397b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,68 @@ +# Vivado project files +*.cache/ +*.data/ +*.hw/ +*.ip_user_files/ +*.runs/ +*.sim/ +*.srcs/ +*.sdk/ + +# Vivado settings and logs +*.jou +*.log +*.str +*.bak + +# Generated files +project_*.xpr +*.bit +*.bin +*.bmm +*.dcp +*.html +*.xdc +*.ltx +*.ngc +*.tcl +*.xgui +*.xise +*.xml +*_bd.tcl +*_top.xdc +*_wrapper.bmm +*_xmd.xdc +*_xmd.ini + +# Compiled files +webtalk.log +xgui/ +hdl/ +isim/ +project_*.cache/ +project_*.runs/ +project_*.srcs/ +project_*.xpr.user +*_vivado_* + +# IDE specific files +.DS_Store +*.suo +*.user +*.sln +*.ncb +*.aps +*.vsp +*.pidb +*.opensdf +*.VC.db + +# Ignore user-specific settings and configurations +*.xilinx +*.sws +*.cache +*.str +*.history + +# Ignore backup files created by text editors +*~ diff --git a/src/alu.vhd b/src/alu.vhd new file mode 100644 index 0000000..c1ffeac --- /dev/null +++ b/src/alu.vhd @@ -0,0 +1,86 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity alu is +port( + a: in STD_LOGIC_VECTOR(7 downto 0); + b: in STD_LOGIC_VECTOR(7 downto 0); + op: in STD_LOGIC_VECTOR(2 downto 0); + s: out STD_LOGIC_VECTOR(7 downto 0); + flags : out STD_LOGIC_VECTOR(3 downto 0) +); +end alu; + +-- Flags +-- C -> Carry (bit 0) +-- N -> Negative (bit 1) +-- Z -> Zero (bit 2) +-- O -> Overflow (when using MUL) (bit 3) + +-- Operation Bits (OP2, OP1, OP0) Operation +-- 000 ADD +-- 001 SUB +-- 010 AND +-- 011 OR +-- 100 XOR +-- 101 NOT (return 0x1 if true, else return 0x0) +-- 110 MUL + +architecture behavior_alu of alu is + -- Internal variables + shared variable buffer_s_16 : STD_LOGIC_VECTOR(15 downto 0); + shared variable buffer_s : STD_LOGIC_VECTOR(7 downto 0); + shared variable carry_s : STD_LOGIC_VECTOR(8 downto 0); + shared variable buffer_flags : STD_LOGIC_VECTOR(3 downto 0); + +begin + process(a, b, op) is + begin + buffer_flags := "0000"; + case op is + when "000" => + -- calculcating a + b by concatening 8 bits to 9 bits and checking the MSB + carry_s := ('0' & a) + ('0' & b); + buffer_s := carry_s(7 downto 0); + buffer_flags(0) := carry_s(8); + -- Checking negative + if (SIGNED(buffer_s) < (0)) then + buffer_flags(1) := '1'; + end if; + when "001" => + carry_s := ('0' & a) - ('0' & b); + buffer_s := carry_s(7 downto 0); + -- borrowing when negative + buffer_flags(1) := carry_s(8); + when "010" => + buffer_s := a AND b; + when "011" => + buffer_s := a OR b; + when "100" => + buffer_s := a XOR b; + when "101" => + buffer_s := NOT a; + when "110" => + buffer_s_16 := (a * b); + buffer_s := buffer_s_16(7 downto 0); + -- In the context of a multiplication overflow can be interpreted in two manners + -- A basic overflow for both signed/unsigned. A negative flag for signed. + if (buffer_s_16 > X"FF") then + buffer_flags(3) := '1'; + end if; + when others => + buffer_s := "00000000"; + end case; + + -- checking for 0 value + if (buffer_s = 0) then + buffer_flags(2) := '1'; + end if; + + -- Writing from the buffer to the output + s <= buffer_s; + flags <= buffer_flags; + end process; +end behavior_alu; diff --git a/src/alu_tb.vhd b/src/alu_tb.vhd new file mode 100644 index 0000000..cb14e05 --- /dev/null +++ b/src/alu_tb.vhd @@ -0,0 +1,54 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity test_alu is +end test_alu; + +architecture bench of test_alu is + component alu is + port( + a: in STD_LOGIC_VECTOR(7 downto 0); + b: in STD_LOGIC_VECTOR(7 downto 0); + op: in STD_LOGIC_VECTOR(2 downto 0); + s: out STD_LOGIC_VECTOR(7 downto 0); + flags : out STD_LOGIC_VECTOR(3 downto 0) + ); + end component; + + for all : alu use entity work.alu; + + signal in1, in2, out1 : STD_LOGIC_VECTOR(7 downto 0); + signal out2 : STD_LOGIC_VECTOR(3 downto 0); + signal operation : STD_LOGIC_VECTOR(2 downto 0); + +-- Test ADD -> 4+(-16)/4+240, then 128+156 -> C = 1 +-- Test SUB -> 32-6 then 4-10 -> N =1 +-- Test AND -> 0b00001111 & 0b11110000 then 0b01010000 & 0b11110001 +-- Test OR -> 0b00001111 | 0b11110000 then 0b01010000 | 0b11110001 +-- Test XOR -> 0b00001111 ^ 0b11110000 then 0b01010000 ^ 0b11110001 +-- Test NOT -> 0b00001111 +-- Test MUL -> 6*3 then 128*3 O = 1 + +begin + testeur: alu PORT MAP(in1, in2, operation, out1, out2); + in1 <= "00000100", "10000000" after 2 ns, + "00100000" after 4 ns, "00000100" after 6 ns, + "00001111" after 8 ns, "01010000" after 10 ns, + "00001111" after 12 ns, "01010000" after 14 ns, + "00001111" after 16 ns, "01010000" after 18 ns, + "00001111" after 20ns, + "00000110" after 24ns, "10000000" after 26ns; + + in2 <= "11110000", "10011100" after 2 ns, + "00000110" after 4 ns, "00001010" after 6 ns, + "11110000" after 8 ns, "11110001" after 10 ns, + "11110000" after 12 ns, "11110001" after 14 ns, + "11110000" after 16 ns, "11110001" after 18 ns, + -- in2 is not used for not + "00000011" after 24ns, "00000011" after 26ns; + + operation <= "000", "001" after 4ns, "010" after 8ns, "011" after 12ns, "100" after 16ns, "101" after 20ns, "110" after 24ns; +end bench; diff --git a/src/data_memory.vhd b/src/data_memory.vhd new file mode 100644 index 0000000..dfd2b5a --- /dev/null +++ b/src/data_memory.vhd @@ -0,0 +1,31 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity DataMemory is + Port ( CLK : in STD_LOGIC; + RST : in STD_LOGIC; + RW_ENABLE : in STD_LOGIC; + ADDR : in STD_LOGIC_VECTOR(7 downto 0); + DATA_IN : in STD_LOGIC_VECTOR(7 downto 0); + DATA_OUT : out STD_LOGIC_VECTOR(7 downto 0)); +end DataMemory; + +architecture Behavioral of DataMemory is + type MemoryArray is array (0 to 255) of STD_LOGIC_VECTOR(7 downto 0); + signal Memory : MemoryArray := (others => X"00"); +begin + process(CLK, RST) + begin + if RST = '1' then + Memory <= (others => X"00"); -- Reset the memory to 0x00 + elsif rising_edge(CLK) then + if RW_ENABLE = '1' then -- Read + DATA_OUT <= Memory(to_integer(unsigned(ADDR))); + else -- Write + Memory(to_integer(unsigned(ADDR))) <= DATA_IN; + end if; + end if; + end process; +end Behavioral; diff --git a/src/data_memory_tb.vhd b/src/data_memory_tb.vhd new file mode 100644 index 0000000..9d7d49f --- /dev/null +++ b/src/data_memory_tb.vhd @@ -0,0 +1,61 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity DataMemory_TB is +end DataMemory_TB; + +architecture Behavioral of DataMemory_TB is + signal CLK : STD_LOGIC := '0'; + signal RST : STD_LOGIC := '0'; + signal RW_ENABLE : STD_LOGIC := '0'; + signal ADDR : STD_LOGIC_VECTOR(7 downto 0) := (others => '0'); + signal DATA_IN : STD_LOGIC_VECTOR(7 downto 0) := (others => '0'); + signal DATA_OUT : STD_LOGIC_VECTOR(7 downto 0); + + constant CLOCK_PERIOD : time := 10 ns; -- Define your clock period here +begin + -- Instantiate the DataMemory component + UUT: entity work.DataMemory + port map ( + CLK => CLK, + RST => RST, + RW_ENABLE => RW_ENABLE, + ADDR => ADDR, + DATA_IN => DATA_IN, + DATA_OUT => DATA_OUT + ); + + -- Clock generation process + CLK_GEN: process + begin + while now < 1000 ns loop + CLK <= not CLK; + wait for CLOCK_PERIOD / 2; + end loop; + wait; + end process; + + -- Stimulus process + STIMULUS: process + begin + RST <= '1'; -- Reset the memory + wait for 20 ns; + RST <= '0'; + wait for 10 ns; + + -- Write to memory + RW_ENABLE <= '0'; + ADDR <= "00000001"; + DATA_IN <= "01010101"; + wait for 20 ns; + + -- Read from memory + RW_ENABLE <= '1'; + ADDR <= "00000001"; + wait for 20 ns; + + wait; + end process; +end Behavioral; diff --git a/src/instruction_memory.vhd b/src/instruction_memory.vhd new file mode 100644 index 0000000..1a0e6d8 --- /dev/null +++ b/src/instruction_memory.vhd @@ -0,0 +1,40 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity instruction is + port( + instruction: in STD_LOGIC_VECTOR(7 downto 0); + code: out STD_LOGIC_VECTOR(31 downto 0); + clk: in STD_LOGIC + ); + + -- Array of STD_LOGIC_VECTOR + type code_array is array(0 to 256) of + STD_LOGIC_VECTOR(31 downto 0); + + -- Initialize the code memory + function init return code_array is + variable init_result: code_array; + begin + --do something (e.g. read data from a file, perform some initialization calculation, ...) + -- Exemple : + for i in code_array'range loop + init_result(i) := std_logic_vector(conv_unsigned(i, 32)); + end loop; + return init_result; + end function init; +end instruction; + +architecture behavior_instr of instruction is + -- Memory variable + signal code_memory: code_array := init; +begin + process(instruction, clk) is + begin + if clk'event AND clk = '1' then + code <= code_memory(CONV_INTEGER(UNSIGNED(instruction))); + end if; + end process; +end behavior_instr; \ No newline at end of file diff --git a/src/instruction_memory_tb.vhd b/src/instruction_memory_tb.vhd new file mode 100644 index 0000000..db14e8d --- /dev/null +++ b/src/instruction_memory_tb.vhd @@ -0,0 +1,31 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity test_instr is +end test_instr; + +architecture bench of test_instr is + component instruction is + port( + instruction: in STD_LOGIC_VECTOR(7 downto 0); + code: out STD_LOGIC_VECTOR(31 downto 0); + clk: in STD_LOGIC + ); + end component; + + for all : instruction use entity work.instruction; + + signal inAddress : STD_LOGIC_VECTOR(7 downto 0); + signal outCode : STD_LOGIC_VECTOR(31 downto 0); + signal inClock : STD_LOGIC := '0'; + +begin + testeur: instruction PORT MAP(inAddress, outCode, inClock); + inClock <= not inClock after 1ns; + + inAddress <= X"00", X"0a" after 10ns; + +end bench; diff --git a/src/register.vhd b/src/register.vhd new file mode 100644 index 0000000..6a8cf54 --- /dev/null +++ b/src/register.vhd @@ -0,0 +1,52 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity reg is +port( + address_A: in STD_LOGIC_VECTOR(3 downto 0); + address_B: in STD_LOGIC_VECTOR(3 downto 0); + address_W: in STD_LOGIC_VECTOR(3 downto 0); + W_Enable: in STD_LOGIC; + W_Data: in STD_LOGIC_VECTOR(7 downto 0); + reset: in STD_LOGIC; + clk: in STD_LOGIC; + A_Data: out STD_LOGIC_VECTOR(7 downto 0); + B_Data: out STD_LOGIC_VECTOR(7 downto 0) +); +end reg; + +architecture behavior_reg of reg is + -- Array of STD_LOGIC_VECTOR + type memory_array is array(0 to 15) of + STD_LOGIC_VECTOR(7 downto 0); + -- Memory variable + signal memory: memory_array; +begin + + -- Convert address_A and address_B to integers + -- Using Bypass to avoid delay between Read Data and Write Data if they are at the same time called (WEnable = 1) + A_Data <= memory(CONV_INTEGER(unsigned(address_A))) when (W_Enable = '0' or address_A /= address_W) + else W_Data; + + B_Data <= memory(CONV_INTEGER(unsigned(address_B))) when (W_Enable = '0' or address_B /= address_W) + else W_Data; + + -- Write data synchronously + process(address_W, W_Enable, W_Data, reset, clk) is + begin + -- Reset the memory if shutdown + if reset = '0' then + memory <= (others => "00000000"); + end if; + -- Else Doing writing routine at each clock tick + if reset = '1' then + if clk'event and clk='1' then + if W_Enable = '1' then + memory(CONV_INTEGER(unsigned(address_W))) <= W_Data; + end if; + end if; + end if; + end process; +end behavior_reg; \ No newline at end of file diff --git a/src/register_tb.vhd b/src/register_tb.vhd new file mode 100644 index 0000000..0102c71 --- /dev/null +++ b/src/register_tb.vhd @@ -0,0 +1,42 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity test_reg is +end test_reg; + +architecture bench of test_reg is + component reg is + port( + address_A: in STD_LOGIC_VECTOR(3 downto 0); + address_B: in STD_LOGIC_VECTOR(3 downto 0); + address_W: in STD_LOGIC_VECTOR(3 downto 0); + W_Enable: in STD_LOGIC; + W_Data: in STD_LOGIC_VECTOR(7 downto 0); + reset: in STD_LOGIC; + clk: in STD_LOGIC; + A_Data: out STD_LOGIC_VECTOR(7 downto 0); + B_Data: out STD_LOGIC_VECTOR(7 downto 0) + ); + end component; + + for all : reg use entity work.reg; + + signal inA, inB, inW : STD_LOGIC_VECTOR(3 downto 0); + signal outA, outB, inDataW : STD_LOGIC_VECTOR(7 downto 0); + signal inWenabler, inReset, inClock : STD_LOGIC := '0'; + +begin + testeur: reg PORT MAP(inA, inB, inW, inWenabler, inDataW, inReset, inClock, outA, outB); + + inClock <= not inClock after 1ns; + inReset <= '0', '1' after 1ns, '0' after 200ns, '1' after 202ns; + + inA <= "0000", "0001" after 48ns, "0010" after 64ns, "0000" after 70ns, "0001" after 80ns; + inB <= "0000", "0010" after 48ns, "0001" after 64ns, "1111" after 70ns; + inW <= "0000", "0001" after 24ns, "0010" after 32ns, "0000" after 56ns; + inWenabler <= '0', '1' after 24ns, '0' after 56ns; + inDataW <= "00000000", "01010101" after 24ns, "10101010" after 32ns, "11111111" after 48ns, "00000000" after 56ns; +end bench;