diff --git a/Makefile b/Makefile index 478f80f..6d7b9ed 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,6 @@ # Makefile for the different parts of the RISC-V COntroller # Project by # Yannick Reiß -# Carl Ries -# Alexander Graf # Variable section PARTS = ram regs alu decoder pc cpu @@ -10,14 +8,14 @@ CHDL = ghdl FLAGS = --std=08 REGSSRC = src/riscv_types.vhd src/registers.vhd tb/tb_reg.vhd ALUSRC = src/riscv_types.vhd src/alu.vhd tb/tb_alu.vhd -RAMSRC = src/riscv_types.vhd src/ram_block.vhd src/imem.vhd src/ram_entity_only.vhd tb/tb_ram.vhd +RAMSRC = src/riscv_types.vhd src/ram_block.vhd src/imem.vhd src/ram.vhd tb/tb_ram.vhd PCSRC = src/riscv_types.vhd src/pc.vhd tb/tb_pc.vhd DECSRC = src/riscv_types.vhd src/decoder.vhd tb/tb_decoder.vhd -CPUSRC = src/riscv_types.vhd src/ram_block.vhd src/branch.vhd src/imem.vhd src/ram_entity_only.vhd src/registers.vhd src/alu.vhd src/pc.vhd src/decoder.vhd src/imm.vhd src/cpu.vhd tb/tb_cpu.vhd +CPUSRC = src/riscv_types.vhd src/ram_block.vhd src/branch.vhd src/imem.vhd src/ram.vhd src/registers.vhd src/alu.vhd src/pc.vhd src/decoder.vhd src/imm.vhd src/cpu.vhd tb/tb_cpu.vhd ENTITY = regs_tb ALUENTITY = alu_tb PCENTITY = pc_tb -STOP = 9000ns +STOP = 100ns TBENCH = alu_tb regs_tb # Build all @@ -40,7 +38,7 @@ alu : $(ALUSRC) $(CHDL) -a $(FLAGS) $(ALUSRC) $(CHDL) -e $(FLAGS) $(ALUENTITY) $(CHDL) -r $(FLAGS) $(ALUENTITY) --wave=$(ALUENTITY).ghw --stop-time=$(STOP) - + # pc testbench pc : $(PCSRC) $(CHDL) -a $(FLAGS) $(PCSRC) diff --git a/constrainits.xdc b/constrainits.xdc index 2e4e7c6..e3ac891 100644 --- a/constrainits.xdc +++ b/constrainits.xdc @@ -718,4 +718,4 @@ set_property PACKAGE_PIN L16 [get_ports {RGB2[2]}] #set_property IOSTANDARD LVCMOS33 [get_ports {MemAdr[21]}] ##Bank = 14, Pin name = IO_L23N_T3_A02_D18_14, Sch name = CRAM_A22 #set_property PACKAGE_PIN U13 [get_ports {MemAdr[22]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {MemAdr[22]}] \ No newline at end of file + #set_property IOSTANDARD LVCMOS33 [get_ports {MemAdr[22]}] diff --git a/src/cpu.vhd b/src/cpu.vhd index db64967..8fe0c2d 100644 --- a/src/cpu.vhd +++ b/src/cpu.vhd @@ -1,6 +1,6 @@ -- cpu.vhd -- Created on: Mo 19. Dez 11:07:17 CET 2022 --- Author(s): Yannick Reiß, Carl Ries, Alexander Graf +-- Author(s): Yannick Reiss -- Content: Entity cpu library IEEE; use ieee.std_logic_1164.all; @@ -12,14 +12,14 @@ use work.riscv_types.all; -- Entity cpu: path implementation of RISC-V cpu entity cpu is port( - clk : in std_logic; -- clk to control the unit - - -- Led Output - led : out std_logic_vector(15 downto 0); -- output to 16 LEDS - - -- RGB Output - RGB1 : out std_logic_vector(2 downto 0); -- output to RGB 1 - RGB2 : out std_logic_vector(2 downto 0) -- output to RGB 2 + clk : in std_logic; -- clk to control the unit + rst : in std_logic; + instruction_read : in word; + ram_read_data : in word; + ram_enable_writing : out std_logic; + instruction_pointer : out ram_addr_t; + data_address : out ram_addr_t; + ram_write_data : out word ); end cpu; @@ -36,18 +36,6 @@ architecture implementation of cpu is ); end component; - component ram - port( - clk : in std_logic; -- Clock input for timing - instructionAdr : in ram_addr_t; -- Address instruction - dataAdr : in ram_addr_t; -- Address data - writeEnable : in one_bit; -- Read or write mode - dataIn : in word; -- Write data - instruction : out word; -- Get instruction - dataOut : out word -- Read data - ); - end component; - component alu port ( alu_opc : in aluOP; -- alu opcode. @@ -69,9 +57,9 @@ architecture implementation of cpu is component imm port ( - instruction : in instruction; - opcode : in uOP; - immediate : out word + instr : in instruction; + opcode : in uOP; + immediate : out word ); end component; @@ -85,8 +73,7 @@ architecture implementation of cpu is r2_idx : in reg_idx; -- second register to read from write_enable : in one_bit; -- enable writing to wr_idx r1_out : out word; -- data from first register - r2_out : out word; -- data from second register - led_out : out word -- output led + r2_out : out word -- data from second register ); end component; @@ -100,15 +87,12 @@ architecture implementation of cpu is end component; -- SIGNALS GLOBAL - signal s_clock : std_logic; - signal s_reg_wb_enable : one_bit; --enables: register writeback - signal s_reg_wr_enable : one_bit; --enables: register write to index - signal s_pc_enable : one_bit; --enables: pc - signal s_pc_jump_enable : one_bit; --enables: pc jump to address - signal s_ram_enable : one_bit; --enables: ram write enalbe - signal s_led_out : word := "10110011100001110111010110101110"; -- stores the exact output - - + signal s_clock : std_logic := '0'; + signal s_reg_wb_enable : one_bit := "0"; --enables: register writeback + signal s_reg_wr_enable : one_bit := "0"; --enables: register write to index + signal s_pc_enable : one_bit := "0"; --enables: pc + signal s_pc_jump_enable : one_bit := "0"; --enables: pc jump to address + signal s_ram_enable : std_logic := '0'; --enables: ram write enalbe -- decoder -> registers signal s_idx_1 : reg_idx; @@ -122,8 +106,8 @@ architecture implementation of cpu is signal s_reg_data1 : word; signal s_reg_data2 : word; - -- pc -> ram - signal s_instAdr : ram_addr_t; + -- pc -> ram + signal s_instAddr : ram_addr_t; signal s_cycle_cnt : cpuStates := stIF; signal s_branch_jump_enable : one_bit; @@ -133,12 +117,10 @@ architecture implementation of cpu is -- ram -> register signal s_ram_data : word; - --ram -> decoder + imm + --ram -> decoder + imm signal s_inst : instruction; signal s_data_in_addr : ram_addr_t; - - -- v dummy signals below v --imm -> ??? @@ -150,8 +132,8 @@ architecture implementation of cpu is -- ??? -> alu signal X_addr_calc : ram_addr_t; - -- Clock signals - signal reset : std_logic; + -- Clock signals + signal reset : std_logic; signal locked : std_logic; ------------------------- @@ -167,7 +149,14 @@ architecture implementation of cpu is begin - s_clock <= clk; + -- External assignments + s_clock <= clk; + ram_enable_writing <= s_ram_enable; + instruction_pointer <= s_instAddr; + data_address <= s_data_in_addr; + ram_write_data <= s_alu_data; + s_inst <= instruction_read; + s_ram_data <= ram_read_data; decoder_RISCV : decoder port map( @@ -188,15 +177,14 @@ begin r2_idx => s_idx_2, write_enable => s_reg_wr_enable, r1_out => s_reg_data1, - r2_out => s_reg_data2, - led_out => s_led_out + r2_out => s_reg_data2 ); imm_RISCV : imm port map( - instruction => s_inst, - opcode => s_opcode, - immediate => s_immediate + instr => s_inst, + opcode => s_opcode, + immediate => s_immediate ); pc_RISCV : pc @@ -205,7 +193,7 @@ begin en_pc => s_pc_enable, addr_calc => X_addr_calc, doJump => s_pc_jump_enable, - addr => s_instAdr + addr => s_instAddr ); alu_RISCV : alu @@ -216,17 +204,6 @@ begin result => s_alu_data ); - ram_RISCV : ram - port map( - clk => s_clock, -- - instructionAdr => s_instAdr, -- instruction from pc - dataAdr => s_data_in_addr, -- data address from alu - writeEnable => s_ram_enable, -- - dataIn => s_reg_data2, -- data from register - instruction => s_inst, -- - dataOut => s_ram_data - ); - branch_RISCV : Branch port map( op_code => s_opcode, @@ -243,8 +220,6 @@ begin ----------------------------------------- -- Output ----------------------------------------- - led <= s_led_out(15 downto 0); - RGB1 <= s_clock & s_clock & s_clock; alu_control : process (s_immediate, s_opcode, s_reg_data1, s_reg_data2) -- runs only, when item in list changed begin @@ -276,8 +251,8 @@ begin end case; end process; - -- Process register_data_input select which input is needed for register - register_data_input : process (s_cycle_cnt, s_opcode, s_ram_data, s_alu_data) -- runs only, when item in list changed + -- Process register_data_input select which input is needed for register + register_data_input : process (s_cycle_cnt, s_opcode, s_ram_data, s_alu_data) -- runs only, when item in list changed begin s_reg_wb_enable <= "0"; case s_opcode is @@ -297,43 +272,43 @@ begin end case; end process; - -- Process pc input - pc_addr_input : process(s_opcode, s_cycle_cnt, s_instAdr, s_immediate) + -- Process pc input + pc_addr_input : process(s_opcode, s_cycle_cnt, s_instAddr, s_immediate) begin if s_cycle_cnt = stWB then s_pc_enable <= "1"; else s_pc_enable <= "0"; - -- X_addr_calc <= s_instAdr; -- should not be necessary, every case option sets X_addr_calc + -- X_addr_calc <= s_instAddr; -- should not be necessary, every case option sets X_addr_calc end if; case s_opcode is when uJALR | uJAL => s_pc_jump_enable <= "1"; - X_addr_calc <= std_logic_vector(signed(s_immediate(11 downto 0)) + signed(s_instAdr)); + X_addr_calc <= std_logic_vector(signed(s_immediate(11 downto 0)) + signed(s_instAddr)); -- Branch op_codes when uBEQ | uBNE | uBLT | uBGE | uBLTU | uBGEU => -- always load address from immediate on B-Type - X_addr_calc <= std_logic_vector(signed(s_immediate(11 downto 0)) + signed(s_instAdr)); + X_addr_calc <= std_logic_vector(signed(s_immediate(11 downto 0)) + signed(s_instAddr)); -- check for opcodes and evaluate condition s_pc_jump_enable <= s_branch_jump_enable; when others => s_pc_jump_enable <= "0"; - X_addr_calc <= s_instAdr; + X_addr_calc <= s_instAddr; end case; end process; - -- process ram + -- process ram ram_input : process(s_opcode, s_cycle_cnt) begin - s_data_in_addr <= std_logic_vector(signed(s_immediate(11 downto 0)) + signed(s_reg_data1(11 downto 0))); + s_data_in_addr <= std_logic_vector(signed(s_immediate) + signed(s_reg_data1)); if s_cycle_cnt = stWB then case s_opcode is - when uSB | uSH | uSW => s_ram_enable <= "1"; - when others => s_ram_enable <= "0"; + when uSB | uSH | uSW => s_ram_enable <= '1'; + when others => s_ram_enable <= '0'; end case; else - s_ram_enable <= "0"; + s_ram_enable <= '0'; end if; end process; @@ -342,16 +317,11 @@ begin begin if rising_edge(s_clock) then case s_cycle_cnt is - when stIF => s_cycle_cnt <= stDEC; - RGB2 <= "001"; - when stDEC => s_cycle_cnt <= stOF; - RGB2 <= "010"; - when stOF => s_cycle_cnt <= stEXEC; - RGB2 <= "011"; + when stIF => s_cycle_cnt <= stDEC; + when stDEC => s_cycle_cnt <= stOF; + when stOF => s_cycle_cnt <= stEXEC; when stEXEC => s_cycle_cnt <= stWB; - RGB2 <= "100"; when others => s_cycle_cnt <= stIF; - RGB2 <= "101"; end case; end if; end process pc_cycle_control; diff --git a/src/imem.vhd b/src/imem.vhd index f1fb5b6..615c15b 100644 --- a/src/imem.vhd +++ b/src/imem.vhd @@ -13,12 +13,10 @@ entity instr_memory is generic (initMem : ram_t := (others => (others => '0'))); - port (clk : in std_logic; - - addr_a : in std_logic_vector(ram_addr_size - 3 downto 0); - data_read_a : out std_logic_vector(wordWidth - 1 downto 0); - - write_b : in one_bit; + port (clk : in std_logic; + addr_a : in std_logic_vector(ram_addr_size - 3 downto 0); + data_read_a : out std_logic_vector(wordWidth - 1 downto 0); + write_b : in std_logic; addr_b : in std_logic_vector(ram_addr_size - 3 downto 0); data_read_b : out std_logic_vector(wordWidth - 1 downto 0); data_write_b : in std_logic_vector(wordWidth - 1 downto 0) @@ -27,28 +25,18 @@ entity instr_memory is end instr_memory; --- START: --- addi x1 x0 1 --- add x2 x0 x0 --- add x3 x0 x0 --- addi x4 x0 2047 --- slli x4 x4 5 --- REG2UP: --- add x2 x2 x1 --- add x3 x0 x0 --- REG3UP: --- add x3 x3 x1 --- bgeu x3 x4 REG2UP --- jal REG3UP architecture behavioral of instr_memory is signal store : ram_t := ( - x"00100093", x"00000133", x"000001b3", x"7ff00213", x"00521213", x"00110133", x"000001b3", x"001181b3", x"fe41fae3", x"ff9ff0ef", others => (others => '0') + b"00000000000000000000001010010011", + b"00000000000100101000001010010011", + b"11111111110111111111000011101111", + others => (others => '0') ); begin - -- Two synchron read ports - data_read_a <= store(to_integer(unsigned(addr_a(9 downto 2)))); - data_read_b <= store(to_integer(unsigned(addr_b(9 downto 2)))); + -- Two synchron read ports + data_read_a <= store(to_integer(unsigned(addr_a(ram_addr_size - 3 downto 2)))); + data_read_b <= store(to_integer(unsigned(addr_b(ram_addr_size - 3 downto 2)))); end behavioral; diff --git a/src/imm.vhd b/src/imm.vhd index f690364..aab4b6b 100644 --- a/src/imm.vhd +++ b/src/imm.vhd @@ -7,9 +7,9 @@ use work.riscv_types.all; entity imm is port ( - instruction : in instruction; - opcode : in uOP; - immediate : out word + instr : in instruction; + opcode : in uOP; + immediate : out word ); end imm; @@ -18,23 +18,23 @@ architecture slicing of imm is begin -- Process immediate slice - process (opcode, instruction) + process (opcode, instr) begin case opcode is -- I-Type - when uLB | uLH | uLW | uLBU | uLHU | uADDI | uSLTI | uSLTIU | uXORI | uORI | uANDI => immediate <= std_logic_vector(to_unsigned(0, wordWidth - 12)) & instruction(31 downto 20); + when uLB | uLH | uLW | uLBU | uLHU | uADDI | uSLTI | uSLTIU | uXORI | uORI | uANDI => immediate <= std_logic_vector(to_unsigned(0, wordWidth - 12)) & instr(31 downto 20); -- S-Type - when uSB | uSH | uSW => immediate <= std_logic_vector(to_unsigned(0, wordWidth-12)) & instruction(31 downto 25) & instruction(11 downto 7); + when uSB | uSH | uSW => immediate <= std_logic_vector(to_unsigned(0, wordWidth-12)) & instr(31 downto 25) & instr(11 downto 7); -- B-Type - when uBEQ | uBNE | uBLT | uBGE | uBLTU | uBGEU => immediate <= std_logic_vector(to_unsigned(0, 19)) & instruction(31) & instruction(7) & instruction(30 downto 25) & instruction(11 downto 8) & "0"; + when uBEQ | uBNE | uBLT | uBGE | uBLTU | uBGEU => immediate <= std_logic_vector(to_unsigned(0, 19)) & instr(31) & instr(7) & instr(30 downto 25) & instr(11 downto 8) & "0"; -- U-Type - when uLUI | uAUIPC => immediate <= instruction(31 downto 12) & std_logic_vector(to_unsigned(0, 12)); + when uLUI | uAUIPC => immediate <= instr(31 downto 12) & std_logic_vector(to_unsigned(0, 12)); -- J-Type - when uJAL => immediate <= std_logic_vector(to_unsigned(0, wordWidth - 21)) & instruction(31) & instruction(19 downto 12) & instruction(20) & instruction(30 downto 21) & "0"; + when uJAL => immediate <= std_logic_vector(to_unsigned(0, wordWidth - 21)) & instr(31) & instr(19 downto 12) & instr(20) & instr(30 downto 21) & "0"; when others => immediate <= x"C000FFEE"; end case; diff --git a/src/ram_entity_only.vhd b/src/ram.vhd similarity index 60% rename from src/ram_entity_only.vhd rename to src/ram.vhd index 9963809..2a5f1cd 100644 --- a/src/ram_entity_only.vhd +++ b/src/ram.vhd @@ -13,25 +13,23 @@ entity ram is generic (zeros : ram_t := (others => (others => '0'))); port( - clk : in std_logic; -- Clock input for timing - instructionAdr : in ram_addr_t; -- Address instruction - dataAdr : in ram_addr_t; -- Address data - - writeEnable : in one_bit; -- Read or write mode - - dataIn : in word; -- Write data - instruction : out word; -- Get instruction - dataOut : out word -- Read data + clk : in std_logic; -- Clock input for timing + instructionAddr : in ram_addr_t; -- Address instruction + dataAddr : in ram_addr_t; -- Address data + writeEnable : in std_logic; -- Read or write mode + dataIn : in word; -- Write data + instruction : out word; -- Get instruction + dataOut : out word -- Read data ); end ram; -- Architecture behavioral of ram: control different ram blocks architecture behavioral of ram is -- write signals - signal wr1 : one_bit := "0"; - signal wr2 : one_bit := "0"; - signal wr3 : one_bit := "0"; - signal wr4 : one_bit := "0"; + signal wr1 : std_logic := '0'; + signal wr2 : std_logic := '0'; + signal wr3 : std_logic := '0'; + signal wr4 : std_logic := '0'; -- instruction signals signal inst1 : std_logic_vector(wordWidth - 1 downto 0); @@ -50,9 +48,9 @@ begin block1 : entity work.instr_memory(behavioral) port map ( clk => clk, - addr_a => instructionAdr(ram_addr_size - 3 downto 0), + addr_a => instructionAddr(ram_addr_size - 3 downto 0), write_b => wr1, - addr_b => dataAdr(ram_addr_size - 3 downto 0), + addr_b => dataAddr(ram_addr_size - 3 downto 0), data_write_b => dataIn, data_read_a => inst1, @@ -62,9 +60,9 @@ begin block2 : entity work.ram_block(behavioral) port map ( clk => clk, - addr_a => instructionAdr(9 downto 0), + addr_a => instructionAddr(ram_addr_size - 3 downto 0), write_b => wr2, - addr_b => dataAdr(9 downto 0), + addr_b => dataAddr(ram_addr_size - 3 downto 0), data_write_b => dataIn, data_read_a => inst2, @@ -74,9 +72,9 @@ begin block3 : entity work.ram_block(behavioral) port map ( clk => clk, - addr_a => instructionAdr(9 downto 0), + addr_a => instructionAddr(ram_addr_size - 3 downto 0), write_b => wr3, - addr_b => dataAdr(9 downto 0), + addr_b => dataAddr(ram_addr_size - 3 downto 0), data_write_b => dataIn, data_read_a => inst3, @@ -86,50 +84,50 @@ begin block4 : entity work.ram_block(behavioral) port map ( clk => clk, - addr_a => instructionAdr(9 downto 0), + addr_a => instructionAddr(ram_addr_size - 3 downto 0), write_b => wr4, - addr_b => dataAdr(9 downto 0), + addr_b => dataAddr(ram_addr_size - 3 downto 0), data_write_b => dataIn, data_read_a => inst4, data_read_b => data4 ); - addr_block : process (data1, data2, data3, data4, dataAdr(11 downto 10), + addr_block : process (data1, data2, data3, data4, dataAddr(11 downto 10), inst1, inst2, inst3, inst4, - instructionAdr(11 downto 10), writeEnable) -- run process addr_block when list changes + instructionAddr(11 downto 10), writeEnable) -- run process addr_block when list changes begin -- enable write - case dataAdr(11 downto 10) is + case dataAddr(11 downto 10) is when "00" => wr1 <= writeEnable; - wr2 <= "0"; - wr3 <= "0"; - wr4 <= "0"; + wr2 <= '0'; + wr3 <= '0'; + wr4 <= '0'; when "01" => - wr1 <= "0"; + wr1 <= '0'; wr2 <= writeEnable; - wr3 <= "0"; - wr4 <= "0"; + wr3 <= '0'; + wr4 <= '0'; when "10" => - wr1 <= "0"; - wr2 <= "0"; + wr1 <= '0'; + wr2 <= '0'; wr3 <= writeEnable; - wr4 <= "0"; + wr4 <= '0'; when "11" => - wr1 <= "0"; - wr2 <= "0"; - wr3 <= "0"; + wr1 <= '0'; + wr2 <= '0'; + wr3 <= '0'; wr4 <= writeEnable; when others => - wr1 <= "0"; - wr2 <= "0"; - wr3 <= "0"; - wr4 <= "0"; + wr1 <= '0'; + wr2 <= '0'; + wr3 <= '0'; + wr4 <= '0'; end case; -- instruction data - case instructionAdr(11 downto 10) is + case instructionAddr(11 downto 10) is when "00" => instruction <= inst1; when "01" => instruction <= inst2; when "10" => instruction <= inst3; @@ -137,7 +135,7 @@ begin end case; -- data data - case dataAdr(11 downto 10) is + case dataAddr(11 downto 10) is when "00" => dataOut <= data1; when "01" => dataOut <= data2; when "10" => dataOut <= data3; diff --git a/src/ram_block.vhd b/src/ram_block.vhd index 91e413d..f5f7581 100644 --- a/src/ram_block.vhd +++ b/src/ram_block.vhd @@ -13,16 +13,13 @@ entity ram_block is generic (initMem : ram_t := (others => (others => '0'))); - port (clk : in std_logic; - - addr_a : in std_logic_vector(ram_addr_size - 3 downto 0); - data_read_a : out std_logic_vector(wordWidth - 1 downto 0); - - write_b : in one_bit; + port (clk : in std_logic; + addr_a : in std_logic_vector(ram_addr_size - 3 downto 0); + data_read_a : out std_logic_vector(wordWidth - 1 downto 0); + write_b : in std_logic; addr_b : in std_logic_vector(ram_addr_size - 3 downto 0); data_read_b : out std_logic_vector(wordWidth - 1 downto 0); data_write_b : in std_logic_vector(wordWidth - 1 downto 0) - ); end ram_block; @@ -39,16 +36,15 @@ begin if rising_edge(clk) then -- One synchron write port - if write_b = "1" then + if write_b = '1' then store(to_integer(unsigned(addr_b(9 downto 2)))) <= data_write_b; end if; end if; end process; - -- Two synchron read ports + -- Two synchron read ports data_read_a <= store(to_integer(unsigned(addr_a(9 downto 2)))); - data_read_b <= store(to_integer(unsigned(addr_b(9 downto 2)))); + data_read_b <= store(to_integer(unsigned(addr_b(5 downto 2)))); end behavioral; - diff --git a/src/registers.vhd b/src/registers.vhd index da70df2..458db6a 100644 --- a/src/registers.vhd +++ b/src/registers.vhd @@ -29,8 +29,7 @@ entity registers is r2_idx : in reg_idx; -- second register to read from write_enable : in one_bit; -- enable writing to wr_idx r1_out : out word; -- data from first register - r2_out : out word; -- data from second register - led_out : out word -- output reg 2 to led + r2_out : out word -- data from second register ); end registers; @@ -54,6 +53,5 @@ begin -- read from both reading registers r1_out <= registerbench(to_integer(unsigned(r1_idx))); r2_out <= registerbench(to_integer(unsigned(r2_idx))); - led_out <= registerbench(2); end structure; diff --git a/src/riscv_types.vhd b/src/riscv_types.vhd index ce0f1f6..add3908 100644 --- a/src/riscv_types.vhd +++ b/src/riscv_types.vhd @@ -52,7 +52,7 @@ package riscv_types is -- constants for the 7bit opcode field in a normal 32bit instruction. - -- for 32bit size instructions the last 2 bits always have to be '1' + -- for 32bit size instructions the last 2 bits always have to be '1' -- xxxxx11 constant opc_LUI : opcode := "0110111"; -- load upper immediate constant opc_AUIPC : opcode := "0010111"; -- add upper immediate to pc @@ -109,13 +109,12 @@ package riscv_types is type regFile is array (reg_size - 1 downto 0) of word; -- ram constants and type - constant ram_size : natural := 4096; - constant ram_block_size : natural := 1024; - constant ram_addr_size : natural := 12; + constant ram_size : natural := 16384; + constant ram_block_size : natural := 4096; + constant ram_addr_size : natural := 32; subtype ram_addr_t is std_logic_vector(ram_addr_size -1 downto 0); - -- type ram_t is array(0 to ram_addr_size - 1) of word; - type ram_t is array(0 to 255) of word; + type ram_t is array(0 to ram_block_size) of word; -- const for multiplexer sources constant mul_wr_alures : two_bit := "00"; diff --git a/tb/tb_cpu.vhd b/tb/tb_cpu.vhd index 9d5a208..d6ab475 100644 --- a/tb/tb_cpu.vhd +++ b/tb/tb_cpu.vhd @@ -22,11 +22,43 @@ architecture Behavioral of cpu_tb is -- Clock period definitions constant clk_period : time := 10 ns; + -- CPU and RAM constraints + signal cpu_reset : std_logic := '0'; + signal cpu_instruction : word := (others => '0'); + signal cpu_data : word := (others => '0'); + signal ram_enable : std_logic := '0'; + signal instr_pointer : ram_addr_t := (others => '0'); + signal ram_address : ram_addr_t := (others => '0'); + signal ram_data : word := (others => '0'); + signal ram_cut_zeros : ram_addr_t := (others => '0'); + signal instr_pointer_zeros : ram_addr_t := (others => '0'); + begin + ram_cut_zeros <= "00000000000000000000" & ram_address(11 downto 0); + instr_pointer_zeros <= "00000000000000000000" & instr_pointer(11 downto 0); + -- Instantiate the Unit Under Test (UUT) uut : entity work.cpu(implementation) - port map (clk => clk); + port map (clk => clk, + rst => cpu_reset, + instruction_read => cpu_instruction, + ram_read_data => cpu_data, + ram_enable_writing => ram_enable, + instruction_pointer => instr_pointer, + data_address => ram_address, + ram_write_data => ram_data + ); + + rut : entity work.ram (behavioral) + port map(clk => clk, + instructionAddr => instr_pointer_zeros, + dataAddr => ram_cut_zeros, + writeEnable => ram_enable, + dataIn => ram_data, + instruction => cpu_instruction, + dataOut => cpu_data + ); -- Clock process definitions clk_process : process diff --git a/tb/tb_imm.vhd b/tb/tb_imm.vhd index 83dafbf..3c84bf5 100644 --- a/tb/tb_imm.vhd +++ b/tb/tb_imm.vhd @@ -13,8 +13,8 @@ library std; use std.textio.all; -- Entity imm_tb: dummy entity - entity imm_tb is - end imm_tb; +entity imm_tb is +end imm_tb; architecture testing of imm_tb is @@ -32,10 +32,10 @@ architecture testing of imm_tb is begin uut : entity work.imm port map( - - instruction => s_instruction, - opcode => s_opcode, - immediate => s_immediate + + instr => s_instruction, + opcode => s_opcode, + immediate => s_immediate ); -- Process clk_process operating the clock @@ -65,10 +65,10 @@ begin s_opcode <= uADDI; wait for 10 ns; - + -- addi x2, x0, 1 s_instruction <= x"00100113"; - s_opcode <= uADDI; + s_opcode <= uADDI; wait; diff --git a/tb/tb_ram.vhd b/tb/tb_ram.vhd index 4c2f410..a1b3a4c 100644 --- a/tb/tb_ram.vhd +++ b/tb/tb_ram.vhd @@ -14,39 +14,39 @@ end ram_tb; architecture Behavioral of ram_tb is -- Clock - signal clk : std_logic; + signal clk : std_logic := '0'; -- Inputs - signal addr_a : std_logic_vector(ram_addr_size - 1 downto 0); - signal write_b : std_logic_vector(1-1 downto 0); - signal addr_b : std_logic_vector(ram_addr_size - 1 downto 0); - signal data_write_b : std_logic_vector(wordWidth - 1 downto 0); + signal addr_a : std_logic_vector(ram_addr_size - 1 downto 0) := (others => '0'); + signal write_b : std_logic := '0'; + signal addr_b : std_logic_vector(ram_addr_size - 1 downto 0) := (others => '0'); + signal data_write_b : std_logic_vector(wordWidth - 1 downto 0) := (others => '0'); -- Outputs - signal data_read_a : std_logic_vector(wordWidth - 1 downto 0); - signal data_read_b : std_logic_vector(wordWidth - 1 downto 0); + signal data_read_a : std_logic_vector(wordWidth - 1 downto 0) := (others => '0'); + signal data_read_b : std_logic_vector(wordWidth - 1 downto 0) := (others => '0'); -- Clock period definitions constant clk_period : time := 10 ns; -- Unittest Signale - signal tb_addr_a : integer; - signal tb_addr_b : integer; - signal tb_test_v : std_logic_vector(wordWidth - 1 downto 0); - signal tb_check_v : std_logic_vector(wordWidth - 1 downto 0); - signal tb_validate : std_logic; + signal tb_addr_a : integer := 0; + signal tb_addr_b : integer := 0; + signal tb_test_v : std_logic_vector(wordWidth - 1 downto 0) := (others => '0'); + signal tb_check_v : std_logic_vector(wordWidth - 1 downto 0) := (others => '0'); + signal tb_validate : std_logic := '0'; begin -- Instantiate the Unit Under Test (UUT) uut : entity work.ram(Behavioral) - port map (clk => clk, - instructionAdr => addr_a, - dataAdr => addr_b, - writeEnable => write_b, - dataIn => data_write_b, - instruction => data_read_a, - dataOut => data_read_b); + port map (clk => clk, + instructionAddr => addr_a, + dataAddr => addr_b, + writeEnable => write_b, + dataIn => data_write_b, + instruction => data_read_a, + dataOut => data_read_b); -- Clock process definitions clk_process : process @@ -68,17 +68,17 @@ begin wait until rising_edge(clk); -- manual test - addr_a <= "001101001110"; - addr_b <= "011100110010"; - write_b <= "1"; + addr_a <= "00000000000000000000000000000110"; + addr_b <= "00000000000000000000000000000010"; + write_b <= '1'; wait for 10 ns; -- Testing Mem tb_validate <= '1'; - write_b <= std_logic_vector(to_unsigned(1, 1)); - for test_case in 0 to 1000 loop - for tb_addr in 0 to 4096 loop + write_b <= '1'; + for test_case in 0 to 12 loop + for tb_addr in 0 to 12 loop -- assign test values tb_test_v <= std_logic_vector(to_unsigned(tb_addr, wordWidth)); tb_check_v <= std_logic_vector(to_unsigned(tb_addr, wordWidth)); diff --git a/tb/tb_riscv.vhd b/tb/tb_riscv.vhd new file mode 100644 index 0000000..eec3382 --- /dev/null +++ b/tb/tb_riscv.vhd @@ -0,0 +1,49 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.riscv_types.all; + +library std; +use std.textio.all; + +entity cpu_tb is +end cpu_tb; + +architecture Behavioral of cpu_tb is + + -- Clock + signal clk : std_logic; + + -- Inputs + + -- Outputs + -- Clock period definitions + constant clk_period : time := 10 ns; + +begin + + -- Instantiate the Unit Under Test (UUT) + uut : entity work.cpu(implementation) + port map (clk => clk); + + -- Clock process definitions + clk_process : process + begin + clk <= '0'; + wait for clk_period/2; + clk <= '1'; + wait for clk_period/2; + end process; + + -- Process stim_proc stimulate uut + stim_proc : process -- runs only, when changed + variable lineBuffer : line; + begin + write(lineBuffer, string'("Start the simulator")); + writeline(output, lineBuffer); + + wait for 0 ns; + end process; +end architecture; diff --git a/test.S b/test.S new file mode 100644 index 0000000..e0ac0ab --- /dev/null +++ b/test.S @@ -0,0 +1,3 @@ +addi x5 x0 0 +addi x5 x5 1 +jal x1 -4