fpga: ram: Use Verilog model for synthesis and VHDL for simulation
This commit is contained in:
		
							parent
							
								
									7497f1f6bb
								
							
						
					
					
						commit
						cc4b088173
					
				
							
								
								
									
										94
									
								
								fpga/hdl/design/ram_vhdl.vhd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								fpga/hdl/design/ram_vhdl.vhd
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,94 @@ | ||||
| -- -------------------------------------------------------------------------- -- | ||||
| --              TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs              -- | ||||
| -- -------------------------------------------------------------------------- -- | ||||
| -- Servant-compatible RAM, rewritten in VHDL | ||||
| -- -------------------------------------------------------------------------- -- | ||||
| -- Author       : Markus Koch <markus@notsyncing.net> | ||||
| -- Contributors : None | ||||
| -- License      : Mozilla Public License (MPL) Version 2 | ||||
| -- -------------------------------------------------------------------------- -- | ||||
| 
 | ||||
| library ieee; | ||||
| use ieee.std_logic_1164.all; | ||||
| use ieee.numeric_std.all; | ||||
| use std.textio.all; | ||||
| 
 | ||||
| library generics; | ||||
| use generics.wishbone_pkg.all; | ||||
| 
 | ||||
| entity ram_vhdl is | ||||
| 	generic( | ||||
| 		memfile   : string  := "data/empty.hex"; | ||||
| 		read_only : boolean := false; | ||||
| 		adr_width : integer := 16 | ||||
| 	); | ||||
| 	port( | ||||
| 		clk  : in  std_logic;           -- CPU and bus clock | ||||
| 		clr  : in  std_logic;           -- Synchronous reset | ||||
| 
 | ||||
| 		wb_o : out wishbone_slave_out;  -- Wishbone bus (out) | ||||
| 		wb_i : in  wishbone_slave_in    -- Wishbone bus (in) | ||||
| 	); | ||||
| end entity ram_vhdl; | ||||
| 
 | ||||
| architecture rtl of ram_vhdl is | ||||
| 	type mem_t is array (0 to 2 ** adr_width - 1) of std_logic_vector(wb_i.dat'range); | ||||
| 
 | ||||
| 	impure function init_ram_hex return mem_t is | ||||
| 		file text_file       : text open read_mode is memfile; | ||||
| 		variable text_line   : line; | ||||
| 		variable ram_content : mem_t := (others => (others => '0')); | ||||
| 	begin | ||||
| 		for i in 0 to 2 ** adr_width - 1 loop | ||||
| 			exit when endfile(text_file); | ||||
| 			readline(text_file, text_line); | ||||
| 			hread(text_line, ram_content(i)); | ||||
| 		end loop; | ||||
| 
 | ||||
| 		return ram_content; | ||||
| 	end function; | ||||
| 
 | ||||
| 	signal mem         : mem_t := init_ram_hex; | ||||
| 	signal mem_address : integer range mem'range; | ||||
| begin | ||||
| 	wb_o.rty   <= '0'; | ||||
| 	wb_o.err   <= '0'; | ||||
| 	wb_o.stall <= '0'; | ||||
| 
 | ||||
| 	mem_address <= to_integer(unsigned(wb_i.adr(adr_width - 1 + 2 downto 2))); | ||||
| 
 | ||||
| 	rowarn : process(clk) is | ||||
| 	begin | ||||
| 		if rising_edge(clk) then | ||||
| 			if wb_i.cyc and wb_i.stb then | ||||
| 				if (unsigned(wb_i.adr) > 2 ** adr_width - 1) then | ||||
| 					report "ERROR: Out of bounds for " & ram_vhdl'path_name & " @0x" & to_hstring(wb_i.adr) severity error; | ||||
| 				end if; | ||||
| 				if (wb_i.we = '1' and read_only) then | ||||
| 					report "ERROR: Write access to ROM @0x" & to_hstring(wb_i.adr) severity warning; | ||||
| 				end if; | ||||
| 			end if; | ||||
| 		end if; | ||||
| 	end process rowarn; | ||||
| 
 | ||||
| 	mem_p : process(clk) is | ||||
| 	begin | ||||
| 		if rising_edge(clk) then | ||||
| 			wb_o.dat <= mem(mem_address); | ||||
| 			wb_o.ack <= wb_i.stb; | ||||
| 			if (wb_i.we) then | ||||
| 				wb_o.dat <= (others => '-'); | ||||
| 				for i in wb_i.sel'range loop | ||||
| 					if wb_i.sel(i) then | ||||
| 						mem(mem_address)((i + 1) * 8 - 1 downto (i * 8)) <= wb_i.dat((i + 1) * 8 - 1 downto (i * 8)); | ||||
| 					end if; | ||||
| 				end loop; | ||||
| 			end if; | ||||
| 
 | ||||
| 			if clr then | ||||
| 				wb_o.dat <= (others => '-'); | ||||
| 				wb_o.ack <= '0'; | ||||
| 			end if; | ||||
| 		end if; | ||||
| 	end process mem_p; | ||||
| end architecture rtl; | ||||
| @ -1,7 +1,7 @@ | ||||
| -- -------------------------------------------------------------------------- -- | ||||
| --              TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs              -- | ||||
| -- -------------------------------------------------------------------------- -- | ||||
| -- Servant-compatible RAM, rewritten in VHDL | ||||
| -- TODO | ||||
| -- -------------------------------------------------------------------------- -- | ||||
| -- Author       : Markus Koch <markus@notsyncing.net> | ||||
| -- Contributors : None | ||||
| @ -11,16 +11,16 @@ | ||||
| library ieee; | ||||
| use ieee.std_logic_1164.all; | ||||
| use ieee.numeric_std.all; | ||||
| use std.textio.all; | ||||
| 
 | ||||
| library generics; | ||||
| use generics.wishbone_pkg.all; | ||||
| 
 | ||||
| entity servant_ram_vhdl is | ||||
| 	generic( | ||||
| 		memfile   : string  := "data/empty.hex"; | ||||
| 		read_only : boolean := false; | ||||
| 		adr_width : integer := 16 | ||||
| 		memfile    : string  := "data/empty.hex"; | ||||
| 		read_only  : boolean := false; | ||||
| 		adr_width  : integer := 16; | ||||
| 		force_vlog : boolean := false | ||||
| 	); | ||||
| 	port( | ||||
| 		clk  : in  std_logic;           -- CPU and bus clock | ||||
| @ -32,63 +32,75 @@ entity servant_ram_vhdl is | ||||
| end entity servant_ram_vhdl; | ||||
| 
 | ||||
| architecture rtl of servant_ram_vhdl is | ||||
| 	type mem_t is array (0 to 2 ** adr_width - 1) of std_logic_vector(wb_i.dat'range); | ||||
| 	component servant_ram | ||||
| 		generic( | ||||
| 			depth   : integer; | ||||
| 			aw      : integer; | ||||
| 			memfile : string | ||||
| 		); | ||||
| 		port( | ||||
| 			i_wb_clk : in  std_logic; | ||||
| 			i_wb_rst : in  std_logic; | ||||
| 			i_wb_adr : in  std_logic_vector; | ||||
| 			i_wb_dat : in  std_logic_vector; | ||||
| 			i_wb_sel : in  std_logic_vector; | ||||
| 			i_wb_we  : in  std_logic; | ||||
| 			i_wb_cyc : in  std_logic; | ||||
| 			o_wb_rdt : out std_logic_vector; | ||||
| 			o_wb_ack : out std_logic | ||||
| 		); | ||||
| 	end component servant_ram; | ||||
| 
 | ||||
| 	impure function init_ram_hex return mem_t is | ||||
| 		file text_file       : text open read_mode is memfile; | ||||
| 		variable text_line   : line; | ||||
| 		variable ram_content : mem_t := (others => (others => '0')); | ||||
| 	begin | ||||
| 		for i in 0 to 2 ** adr_width - 1 loop | ||||
| 			exit when endfile(text_file); | ||||
| 			readline(text_file, text_line); | ||||
| 			hread(text_line, ram_content(i)); | ||||
| 		end loop; | ||||
| 
 | ||||
| 		return ram_content; | ||||
| 	end function; | ||||
| 
 | ||||
| 	signal mem         : mem_t := init_ram_hex; | ||||
| 	signal mem_address : integer range mem'range; | ||||
| begin | ||||
| 	wb_o.rty   <= '0'; | ||||
| 	wb_o.err   <= '0'; | ||||
| 	wb_o.stall <= '0'; | ||||
| 	vlogforce : if force_vlog generate | ||||
| 		servant_ram_inst : component servant_ram | ||||
| 			generic map( | ||||
| 				depth   => 2 ** adr_width, | ||||
| 				aw      => adr_width, | ||||
| 				memfile => memfile | ||||
| 			) | ||||
| 			port map( | ||||
| 				i_wb_clk => clk, | ||||
| 				i_wb_rst => clr, | ||||
| 				i_wb_adr => wb_i.adr(adr_width - 1 downto 2), | ||||
| 				i_wb_dat => wb_i.dat, | ||||
| 				i_wb_sel => wb_i.sel, | ||||
| 				i_wb_we  => wb_i.we, | ||||
| 				i_wb_cyc => wb_i.cyc and wb_i.stb, | ||||
| 				o_wb_rdt => wb_o.dat, | ||||
| 				o_wb_ack => wb_o.ack | ||||
| 			); | ||||
| 
 | ||||
| 	mem_address <= to_integer(unsigned(wb_i.adr(adr_width - 1 + 2 downto 2))); | ||||
| 		wb_o.rty   <= '0'; | ||||
| 		wb_o.err   <= '0'; | ||||
| 		wb_o.stall <= '0'; | ||||
| 
 | ||||
| 	rowarn : process(clk) is | ||||
| 	begin | ||||
| 		if rising_edge(clk) then | ||||
| 			if wb_i.cyc and wb_i.stb then | ||||
| 				if (unsigned(wb_i.adr) > 2 ** adr_width - 1) then | ||||
| 					report "ERROR: Out of bounds for " & servant_ram_vhdl'path_name & " @0x" & to_hstring(wb_i.adr) severity error; | ||||
| 				end if; | ||||
| 				if (wb_i.we = '1' and read_only) then | ||||
| 					report "ERROR: Write access to ROM @0x" & to_hstring(wb_i.adr) severity warning; | ||||
| 				end if; | ||||
| 			end if; | ||||
| 		end if; | ||||
| 	end process rowarn; | ||||
| 
 | ||||
| 	mem_p : process(clk) is | ||||
| 	begin | ||||
| 		if rising_edge(clk) then | ||||
| 			wb_o.dat <= mem(mem_address); | ||||
| 			wb_o.ack <= wb_i.stb; | ||||
| 			if (wb_i.we) then | ||||
| 				wb_o.dat <= (others => '-'); | ||||
| 				for i in wb_i.sel'range loop | ||||
| 					if wb_i.sel(i) then | ||||
| 						mem(mem_address)((i + 1) * 8 - 1 downto (i * 8)) <= wb_i.dat((i + 1) * 8 - 1 downto (i * 8)); | ||||
| 		rowarn : process(clk) is | ||||
| 		begin | ||||
| 			if rising_edge(clk) then | ||||
| 				if wb_i.cyc and wb_i.stb then | ||||
| 					if (unsigned(wb_i.adr) > 2 ** adr_width - 1) then | ||||
| 						report "ERROR: Out of bounds for " & servant_ram_vhdl'path_name & " @0x" & to_hstring(wb_i.adr) severity error; | ||||
| 					end if; | ||||
| 				end loop; | ||||
| 					if (wb_i.we = '1' and read_only) then | ||||
| 						report "ERROR: Write access to ROM @0x" & to_hstring(wb_i.adr) severity warning; | ||||
| 					end if; | ||||
| 				end if; | ||||
| 			end if; | ||||
| 		end process rowarn; | ||||
| 
 | ||||
| 			if clr then | ||||
| 				wb_o.dat <= (others => '-'); | ||||
| 				wb_o.ack <= '0'; | ||||
| 			end if; | ||||
| 		end if; | ||||
| 	end process mem_p; | ||||
| 	else generate | ||||
| 		ram_vhdl_inst : entity work.ram_vhdl | ||||
| 			generic map( | ||||
| 				memfile   => memfile, | ||||
| 				read_only => read_only, | ||||
| 				adr_width => adr_width | ||||
| 			) | ||||
| 			port map( | ||||
| 				clk  => clk, | ||||
| 				clr  => clr, | ||||
| 				wb_o => wb_o, | ||||
| 				wb_i => wb_i | ||||
| 			); | ||||
| 	end generate vlogforce; | ||||
| end architecture rtl; | ||||
|  | ||||
| @ -239,7 +239,8 @@ begin | ||||
| 		generic map( | ||||
| 			memfile   => "../sw/bootrom/bootrom.vhex", | ||||
| 			read_only => true, | ||||
| 			adr_width => 9 | ||||
| 			adr_width => 9, | ||||
| 			force_vlog  => not in_simulation -- GHDL + Yosys doesn't keep the memfile | ||||
| 		) | ||||
| 		port map( | ||||
| 			clk  => clk, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user