⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s8250.vhd

📁 用VHDL编写的8250
💻 VHD
字号:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;       
ENTITY s8250 IS
	PORT(clk, rclk, reset, sin, rd, wr, cs, a2, a1, a0, dsr: IN STD_ULOGIC;
		 baudout, sout,  dtr, rts: OUT STD_ULOGIC;
         d: INOUT STD_ULOGIC_VECTOR(7 DOWNTO 0));
END s8250;

ARCHITECTURE rtl OF s8250 IS
	SIGNAL scir: STD_ULOGIC_VECTOR(7 DOWNTO 0);        
	SIGNAL scit: STD_ULOGIC_VECTOR(7 DOWNTO 0);
	SIGNAL sh_r: STD_ULOGIC_VECTOR(3 DOWNTO 0);
	SIGNAL sl_r: STD_ULOGIC_VECTOR(3 DOWNTO 0);
	SIGNAL sh_t: STD_ULOGIC_VECTOR(3 DOWNTO 0);
	SIGNAL sl_t: STD_ULOGIC_VECTOR(3 DOWNTO 0);
	SIGNAL shrecreg: STD_ULOGIC_VECTOR(7 DOWNTO 0);  --接收移位寄存器        
	SIGNAL shsendreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); --发送移位寄存器        
	SIGNAL recreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); --接收数据寄存器        
	SIGNAL soutF, sinF: STD_ULOGIC;
	SIGNAL shsendregEMPTY: STD_ULOGIC:='1';
	SIGNAL shrecregFULL: STD_ULOGIC:='0';
	SIGNAL ad: STD_ULOGIC_VECTOR(2 DOWNTO 0); 
	SIGNAL internal_bus_out: STD_ULOGIC_VECTOR(7 DOWNTO 0);  --内总线        
	SIGNAL internal_bus_in: STD_ULOGIC_VECTOR(7 DOWNTO 0); 	--内总线        
 	SIGNAL ccreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); 	--通信控制寄存器        
	SIGNAL divl: STD_ULOGIC_VECTOR(7 DOWNTO 0); 	--除数寄存器低8位        
	SIGNAL divh: STD_ULOGIC_VECTOR(7 DOWNTO 0); 	--除数寄存器高8位        
	SIGNAL sendreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); 	--发送数据寄存器        
	SIGNAL sendregF: STD_ULOGIC;
	SIGNAL csreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); 	--通信状态寄存器        
	SIGNAL divF: STD_ULOGIC;
	SIGNAL sendover: STD_ULOGIC:='1';	--发送结束标志        
 	SIGNAL dlength: STD_ULOGIC_VECTOR(3 DOWNTO 0); 
	SIGNAL dtrF: STD_ULOGIC;
 BEGIN
	dtr<=dtrF;                                            
	rts<=dtrF;
	dlength <= "11"&ccreg(1)&ccreg(0);  --通信控制寄存器低四位,用于控制数据位长度                                                            
	sh_r <= scir(7 DOWNTO 4);
	sl_r <= scir(3 DOWNTO 0);
	sh_t <= scit(7 DOWNTO 4);
	sl_t <= scit(3 DOWNTO 0);
	--p1:对接收移位寄存器空满标志进行操作,将               
	   --并将接收移位寄存器中的值放入接收数据寄存器中                             
	PROCESS(rclk, rd, cs)
		VARIABLE shrecreg_v:STD_ULOGIC_VECTOR(7 DOWNTO 0);  
	BEGIN
	 	IF(rd='0' AND cs='0' AND ccreg(7)='0' AND a2='0' AND a1='0' AND a0='0') THEN
			shrecregFULL<='0'; --接收移位寄存器空                                                    
		ELSIF(rclk'EVENT AND rclk='1') THEN
			IF((sinF='1') AND (sh_r=dlength) AND(sl_r="1111")) THEN
	 			shrecregFULL<='1'; --接收移位寄存器满                                                    
	 			shrecreg_v:=shrecreg;
    			CASE dlength IS --根据数据位数不同对接受到的数据进行处理                                                    
					WHEN "1100" => FOR i IN 0 TO 4 LOOP  --数据位数为5位        
										shrecreg_v(i):=shrecreg_v(i+3);
								   END LOOP;
								   shrecreg_v:=shrecreg_v AND "00011111";
 					WHEN "1101" => FOR i IN 0 TO 5 LOOP  --数据位数为6位        
										shrecreg_v(i):=shrecreg_v(i+2);
								   END LOOP;
								   shrecreg_v:=shrecreg_v AND "00111111";
  					WHEN "1110" => FOR i IN 0 TO 6 LOOP  --数据位数为7位        
										shrecreg_v(i):=shrecreg_v(i+1);
								   END LOOP;
								   shrecreg_v:=shrecreg_v AND "01111111";
  					WHEN "1111" => shrecreg_v:=shrecreg_v;  --数据位数为8位         
					WHEN OTHERS => shrecreg_v:=shrecreg_v;
				END CASE;
	 			recreg<=shrecreg_v; --将接收移位寄存器中的值放入接收数据寄存器中                                                    
 			END IF;
		END IF;
	END PROCESS;
	--p2 写进程        
	PROCESS(cs,wr,reset)
	BEGIN
		IF(wr'EVENT AND wr='0') THEN
			ad <= a2 & a1 & a0;
			internal_bus_out <= d; --将数据值写入内总线                                            
		END IF;
		IF(reset = '0') THEN
			ccreg <= "00000000";
	  	ELSIF(wr'EVENT AND wr='1') THEN
			IF(ad="011" AND cs='0') THEN                                            
				ccreg <= internal_bus_out; --写入通信控制寄存器                                            
			ELSIF(ccreg(7) = '1' AND ad = "000" AND cs = '0') THEN
				divl <= internal_bus_out;  --写入除数寄存器低8位                                            
			ELSIF(ccreg(7) = '1' AND ad = "001" AND cs = '0') THEN
	            divh <= internal_bus_out;  --写入除数寄存器高8位                                            
				divF <= '1'; --表示除数值已写入                                                           
			ELSIF(ccreg(7) = '0' AND ad = "000" AND cs = '0') THEN		
				sendreg <= internal_bus_out; --写入发送数据寄存器                                            
	 		END IF;
		END IF;
	END PROCESS;
	--p3 
	PROCESS(rclk)
	BEGIN
		IF(rclk'EVENT AND rclk='1') THEN
			IF(sin='0') THEN
				sinF<='1'; --表示数据开始接收                                            
			ELSIF((sinF='1') AND (sh_r=dlength) AND(sl_r="1111")) THEN
				sinF<='0'; --表示数据接收完毕                                            
			END IF;
		END IF;
	END PROCESS;
	--p4 对发送过程的各标志操作                                            
	PROCESS(clk)
	BEGIN
		IF(reset='0' OR dsr='0') THEN
			dtrF<='1';
		END IF;
	 	IF(sendover= '1' AND sendregF = '0') THEN
			soutF<='0'; --表示开始发送数据                                             
			shsendregEMPTY<='0'; --表示发送移位寄存器满                                            
			dtrF<='0';
		ELSIF(clk'EVENT AND clk='1') THEN
			IF(((soutF='0') AND (sh_t=dlength) AND (sl_t="1111")) OR reset='0') THEN
				soutF<='1';  --表示数据位发送完毕                                            
	 			shsendregEMPTY<='1'; --表示发送移位寄存器空                                            
	 		END IF;                                            
		END IF;
	END PROCESS;
	--p5 读进程                                            
	PROCESS(rd, cs)
	BEGIN
		IF(rd='0') THEN
			IF(cs='0') THEN
				IF(ccreg(7) = '0' AND a2='0' AND a1='0' AND a0='0') THEN
					internal_bus_in<=recreg; --读接收数据寄存器                                            
				ELSIF(ccreg(7) = '1' AND a2='0' AND a1='0' AND a0='0') THEN
					internal_bus_in<=divl;   --读除数寄存器低8位                                            
				ELSIF(ccreg(7) = '1' AND a2='0' AND a1='0' AND a0='1') THEN
					internal_bus_in<=divh;   --读除数寄存器高8位                                            
				ELSIF(a2='0' AND a1='1' AND a0='1') THEN
					internal_bus_in<=ccreg;  --读通信控制寄存器                                            
				ELSIF(a2='1' AND a1='0' AND a0='1') THEN
					internal_bus_in<=csreg;  --读通信状态寄存器                                            
				END IF;
			END IF;
		ELSE
			internal_bus_in<="ZZZZZZZZ";
		END IF;
		d<=internal_bus_in;
	 
	END PROCESS;
	--p6 接收控制进程                                            
	PROCESS(rclk, reset)
		VARIABLE scir_v:INTEGER RANGE 0 TO 255;
		VARIABLE scir_s:STD_LOGIC_VECTOR(7 DOWNTO 0);
		VARIABLE dlength_v:INTEGER RANGE 0 TO 255;
 	BEGIN
		CASE dlength IS
			WHEN "1100" => dlength_v:=208; --11001111+1 数据位数为5位                                             
			WHEN "1101" => dlength_v:=224; --11011111+1 数据位数为6位                                            
	 		WHEN "1110" => dlength_v:=240; --11101111+1 数据位数为7位                                            
	 		WHEN "1111" => dlength_v:=0;   --11111111+1 数据位数为8位                                            
			WHEN OTHERS => dlength_v:=0;   
		END CASE;
	
		IF(reset='0') THEN
			scir_v:=0;    --"00000000";
		ELSIF(rclk'EVENT AND rclk='1') THEN
			IF((scir_v<=111) AND (sin='0')) THEN   --sci_v="01101111" 启动位到,开始接受                                            
				scir_v:=112;    --scir_v="01110000";
			ELSIF((scir_v<=111) AND (sin='1')) THEN 
				scir_v:=0;
			ELSE
				scir_v:=scir_v + 1;
				IF(scir_v = dlength_v) THEN --当接收到所设定的数据长度时                                             
					scir_v := 0;
				END IF;
 			END IF;
		END IF;
		scir_s:=CONV_STD_LOGIC_VECTOR(scir_v,8);
		scir<=TO_STDULOGICVECTOR(scir_s);
	END PROCESS;
	--p7 产生停止位和BOUDOUT信号                                            
	PROCESS(clk)
		VARIABLE counter:INTEGER RANGE 0 TO 32767; --15 bits
		VARIABLE halfdiv_int:INTEGER RANGE 0 TO 32767;
		VARIABLE halfdiv:STD_LOGIC_VECTOR(15 DOWNTO 0);
		VARIABLE baudoutF:STD_ULOGIC;
		VARIABLE stop_counter:INTEGER RANGE 0 TO 64;
		VARIABLE stopF:STD_ULOGIC;
 	BEGIN	
		IF(clk'EVENT AND clk='1') THEN
			IF(divF = '1') THEN --当除数寄存器已被写入                                            
				halfdiv := TO_STDLOGICVECTOR(divh&divl);
				FOR i IN 0 TO 14 LOOP --将除数除以2                                            
					halfdiv(i):=halfdiv(i+1);
				END LOOP;
				halfdiv(15) := '0'; 
		 		halfdiv_int:= CONV_INTEGER(halfdiv);
		 	 	counter := counter+1; --计算来了多少个clk脉冲                                            
		  		IF(counter = halfdiv_int) THEN --当所来脉冲等于除数的一半时                                            
					counter := 0;
					stop_counter := stop_counter+1; 
					IF(baudoutF = '1') THEN
						baudoutF := '0';
					ELSE 
						baudoutF := '1'; 
					END IF;
				END IF;
			END IF;
			IF((soutF='0') AND (sh_t=dlength) AND (sl_t="1111")) THEN --当数据位发送完毕时,           

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -