mirror of
https://github.com/Lemonochrme/vhdl_processor.git
synced 2025-06-08 08:50:49 +02:00
Boilerplate CPU. VHDL files only.
This commit is contained in:
parent
e6c33c07b5
commit
be238afa0a
9 changed files with 465 additions and 0 deletions
68
.gitignore
vendored
Normal file
68
.gitignore
vendored
Normal file
|
@ -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
|
||||
*~
|
86
src/alu.vhd
Normal file
86
src/alu.vhd
Normal file
|
@ -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;
|
54
src/alu_tb.vhd
Normal file
54
src/alu_tb.vhd
Normal file
|
@ -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;
|
31
src/data_memory.vhd
Normal file
31
src/data_memory.vhd
Normal file
|
@ -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;
|
61
src/data_memory_tb.vhd
Normal file
61
src/data_memory_tb.vhd
Normal file
|
@ -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;
|
40
src/instruction_memory.vhd
Normal file
40
src/instruction_memory.vhd
Normal file
|
@ -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;
|
31
src/instruction_memory_tb.vhd
Normal file
31
src/instruction_memory_tb.vhd
Normal file
|
@ -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;
|
52
src/register.vhd
Normal file
52
src/register.vhd
Normal file
|
@ -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;
|
42
src/register_tb.vhd
Normal file
42
src/register_tb.vhd
Normal file
|
@ -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;
|
Loading…
Add table
Reference in a new issue