昨天在论坛上看到有人帖出了他写的并串转换VHDL代码,但是他自己说有问题,但是不知道怎么改。我大概看了一下,发现思路还是比较乱的。于是就写下了我自己的并串转换代码。这个并串转换代码是依靠同步状态机来实现其控制的。其实并串转换在实际的电路中使用还是比较多的,尤其在通信线路方面的复用和分解方面,原理上就是一个串并转换和并串转换的过程。举个简单的例子,计算机串口发送数据的过程,如果满足发送条件了,其实就是一个并串转换的过程了。好了,废话不说,看代码就是。
-------------------------------------------------------------------------------- -- Engineer: skycanny -- Module Name: p2s - Behavioral -- Tool versions: ISE7.1 -- Description: This module is designed to implement parallel to serial conversion -------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity p2s is port( reset : in std_logic; clk : in std_logic; start : in std_logic; --low active,data_in valid data_in : in std_logic_vector(7 downto 0); data_valid : out std_logic; --high active,output data valid ready : out std_logic; --low active,ready to recieve data q : out std_logic ); end p2s;
architecture Behavioral of p2s is
signal reg : std_logic_vector(7 downto 0); signal cnt : std_logic_vector(3 downto 0); signal reg_en : std_logic; signal shift_start : std_logic; type state is (idle,recieve,shift,finish); signal current_state, next_state : state;
begin counter: process(reset,clk,shift_start) begin if(reset = '0') then cnt <= (others => '0'); elsif(clk'event and clk = '1') then if(shift_start = '0') then cnt <= cnt + 1; else cnt <= (others => '0'); end if; end if; end process counter; fsm: block begin sync: process(reset,clk) begin if(reset= '0') then current_state <= idle; elsif(clk'event and clk = '1') then current_state <= next_state; end if; end process sync;
comb: process(current_state,cnt,start) begin case current_state is when idle => ready <= '0'; reg_en <= '1'; shift_start <= '1'; data_valid <= '1'; if(start = '0') then reg_en <= '0'; next_state <= recieve; else next_state <= idle; end if; when recieve => reg_en <= '1'; ready <= '1'; data_valid <= '0'; shift_start <= '0'; next_state <= shift; when shift => reg_en <= '1'; ready <= '1'; data_valid <= '0'; if(cnt = 8) then shift_start <= '1'; next_state <= finish; else shift_start <= '0'; next_state <= shift; end if; when finish => reg_en <= '1'; ready <= '0'; data_valid <= '1'; shift_start <= '1'; next_state <= idle; when others => next_state <= idle; end case; end process comb;
end block fsm; data_channel: process(reset,clk) begin if(reset = '0') then reg <= (others => '0'); q <= '0'; elsif(clk'event and clk = '1') then if(reg_en = '0') then reg <= data_in; elsif(shift_start = '0') then q <= reg(7); for i in 7 downto 1 loop --shift register reg(i) <= reg(i - 1); end loop; reg(0) <= '0'; else q <= '0'; end if; end if; end process data_channel;
end Behavioral;
写完一看,一个并串转换居然搞了这么大,有点失败。但是整个代码已经通过了后仿真,而且思路还是比较清楚的,可靠性和稳定性方面也应该没有问题滴,呵呵。不过说老实话,里面有些信号是确实可以去掉的,不过后来就懒得改了。如果谁想要实际的工程中用的话可以改一下。好了,收工,今天还要去未央湖。。。
欢迎访问skycanny的笔记(副站) |
用户43070 2008-4-18 21:44
用户60452 2008-4-9 22:52
用户139439 2008-4-8 08:52
用户9951 2006-12-28 09:00
不是很明白,如果能转换成Verilog HDL语言就好了。