[资料分享] 【我给xilinx资源中心做贡献】VHDL实现USB2.0控制器设计

wanghongyang   2011-6-23 21:43 楼主

VHDL实现USB2.0控制器设计

--控制器SSRAM
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity usbf_mem_arb is  --实体声明
generic(SSRAM_HADR:integer:=14);
port(phy_clk,wclk,rst:in std_logic;
   sram_adr:buffer std_logic_vector(SSRAM_HADR downto 0);
   sram_din:in std_logic_vector(31 downto 0);
   sram_dout:buffer std_logic_vector(31 downto 0);
   sram_re,sram_weut std_logic;
   --SSRAM接口
   madr:in std_logic_vector(SSRAM_HADR downto 0);
   mdoutut std_logic_vector(31 downto 0);
   mdin:in std_logic_vector(31 downto 0);
   mwe:in std_logic;
   mreq:in std_logic;
   mack:buffer stdlogic;
   --内部DMA操作接口
   wadr:in std_logic_vector(SSRAM_HADR downto 0);
   wdoutut std_logic_vector(31 downto 0);
   wdin:in std_logic_vector(31 downto 0);
   wwe:in std_logic;
   wreq:in std_logic;
   wack:buffer std_logic  --应用模块的wishbone接口
   );
   end entity
   
   architecture arch_of_mem_arb of usbf_mem_arb is
   signal wsel:std_logic;
   signal mcy:stdlogic;
   signal wack_r:std_logic;
   begin
   wsel<=(wreq or wack)and not(mreq);
   --对SRAM数据输出
   process(wsel,wdin,mdin)
   begin
   if(wsel=&#39;1&#39;)then
   sram_dout<=wdin;
   else sram_dout<=mdin;
   end if;
   end process;
   --sram地址线输出
   process(wsel,wadr,madr)
   begin
   if(wsel=&#39;1&#39;)then
    sram_adr<=wadr;
   else sram_adr<=madr;
   end if;
   end process;
  --sram写操作使能控制
   process(wsel,wwe,wreq,mwe,mcyc)begin
   if(wsel=&#39;1&#39;)then
    sram_we<=wreq and wwe;
   else sram_we<=mwe and mcc;
   end if;
   end process;

   sram_re<=&#39;1&#39;;
   mdout<=sram_din;
   mack<=mreq;
   mcyc<=mack;
   --应用模块之间的wishbone接口
   wdout<=sram_din;
   wack<=wack_r and not(mreq);
   
   process(rst,phy_clk)begin
      if(rst=&#39;0&#39;)then
        wack_r<=&#39;0&#39;;
      else if(ph_clk&#39; event and phy_clk=&#39;1&#39;)then
      wack_r<=wreq and not(mreq)and not(wack);
      end if;
   end process;
   end architecture;

QQ:1625345502

回复评论 (4)

--控制器WISHBONE
--file:usb_wishbone.vhd
  library ieee
  use ieee.std_logic_1164.all;
  use ieee.std_logic_arith.all;
  use ieee.std_logic_unsigned.all;

  entity usbf_wb is
  generic(USBF_UFC_HADR:integer:=17);
  port(wb_clk,phy_clk:in std_logic;
     rst:in std_logic;
     wb_addr_i:in std_logic_vector(USBF_UFC_HDR downto 0);
     wb_data_i:in std_logic_vector(31 downto 0);
     wb_data_o:buffer std_logic_vector(31 downto 0);
     wb_ack_o:buffer std_logic;
     wb_we_i:in std_logic;
     wb_stb_i:in std_logic;
     wb_cyc_i:in std_logic:
--应用程序的WISHBONE接口
         
   ma_adrut std_logic_vector(USBF_UFC_HADR downto 0);
   ma_doutut std_logic_vector(31 downto 0);
   ma_dinut std_logic_vector(31 downto 0);
   ma_we:buffer std_logic_vector(31 wownto 0);
   ma_req:buffer std_logic;
   ma_ack:in std_logic;
  --存储器仲裁器接口
   
   rf_re:buffer std_logic;
   rf_weut std_logic;
   rf_din:in std_logic_vector(31 downto 0);
   rf_doutut std_logic_vector(31 downto 0);
   );
   end entity;

   architecture arch_usbf_wb of usbf_wb is
   constant IDLE:std_logic_vector(5 downto 0):="000001";
   constant MA_WR:std_logic_vector(5 downto 0):="000010";
   constant MA_RD:Std_logic_vector(5 downto 0):="000100";
   constant WO:Std_logic_vector(5 downto 0):="001000";
   constant W1:Std_logic_vector(5 downto 0):="010000";
   constant W2:Std_logic_vector(5 downto 0):="100000";
   
   signal state,next_state:std_logic_vector(5 downto 0);
                             
   signal wb_req_sl:std_logic;
   signal wb_ack_d,wb_ack_sl,wb_ack_sla,wb_ack_s2:std_logic;
   signal rf_we_d:std_logic;
--状态机状态
   begin
   ma_adr<=wb_addr_i;
   ma_dout<=wb_data_i;
   rf_dout<=wb_data_i;
--数据,地址由应用模块驱动,输出至存储器或内部存储器
   process(wb_clk)begin
     if(wb_clk'evevt and wb_clk='1')then
     if(not(wb_addr_i(17)0='1')then
        wb_data_o<=rf_din;
     else wb_data_o<=ma_din;
     end if;
     end if;
   end process;
--数据通道,仲裁数据输入来源是寄存器或储存器
   process(phy_clk)begin
     if phy_clk'event and phy_clk='1'then
     wb_req_s1<=(wb_std_i nd wb_cyc_i);
     end if;
   end process;
--wishbone 请求
   process(wb_clk)begin
     if wb_clk'event and wb_clk='1' then
     wb_ack_sl<=wb_ack_d;
     end if;
   end process;

   process(wb_clk)begin
     if wb_clk'event and wb_clk='1' then
     wb_ack_o<=(wb_ack_s1 and not(wb_ack_s2)and not(wb_ack_0));
     end if;
   end process;
     
   process(wb_clk)begin
     if wb_clk'event and wb_clk='1' then
     wb_ack_s2<=wb_ack_s1a;
     end if;
   end process;

   process(wb_clk)begin
     if wb_clk'event and wb_clk='1' then
     wb_ck_s2<=wb_ack_s1a;
     end if;
   end process;
   --内部寄存器写使能驱动
   
   rf_we<=rf_we_d;
   
   process(phy_clk,rst)begin
     if(rst='0')then
         state<=IDLE;
     elsif wb_clk'event and wb_clk='1' then
         state<=next_state;
     end if;
   end process;

   process(state,wb_req_s1,wb_addr_i,ma_ack,wb_we_i)
     begin
      next_state<=state;
      ma_req<='0';
      ma_we<='0';
      wb_ack_d<='0';
      rf_re<='0';
      rf_we_d<='0';

   case state is --状态机状态转移
     when IDLE=>
      if(wb_req_s1='1' and wb_addr_i(17)='0'and wb_we_i='1')then
        ma_req<='1';
        ma_we<='1';
        next_state<=M_WR;  --存储器写状态
      end if;
      if(wb_req_s1='1' and wb_addr_i(17)='0'and wb_we_i='0')then
        ma_req<='1';
        next_state<=MA_WR;  --存储器读状态
      end if;
      if(wb_req_s1='1' and wb_addr_i(12)='0'and wb_we_i='1')then
        rf_we_d<='1';
        next_state<=W0;   --寄存器写状态
      end if;
      if(wb_req_s1='1' and wb_addr_i(12)='0'and wb_we_i='0')then
        rf_re<='1';
        next_state<=W0;   --寄存器读状态
      end if;
   
     when MA_WR=>
      if(ma_ack='0')then
         ma_req<='1';
         ma_we<='1';
      else
         wb_ack_d<='1';
         next_state<=W1;
      end if;
              
     when MA_RD=>
      if(ma_ack='0') then
         ma_req<='1';
      else
         wb_ack_d<='1';
         next_state<=W1;
      end if;

     when W0=>
       wb_ack_d<='1';
       next_state<=W1;      --W1

     when W1=>
       next_state<=W2;      --W2

     when W2=>
       next_state<=IDLE;     --IDLE

     when others=>
       null;
     end case;
   end process;
QQ:1625345502
点赞  2011-6-23 21:43
--控制器协议层
--file    :usbf_pd.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity usb_pd is  --实体声明
    generic(
    USBF_T_PID_OUT:std_logic_vector(3 downto 0):="0001";
    USBF_T_PID_IN:std_logic_vector(3 downto 0):="1001";
    USBF_T_PID_SOF:std_logic_vector(3 downto 0):="0101";
    USBF_T_PID_SETUP:std_logic_vector(3 downto 0):="1101";
    USBF_T_PID_DATA0:std_logic_vector(3 downto 0):="0011";
    USBF_T_PID_DATA1:std_logic_vector(3 downto 0):="1011";
    USBF_T_PID_DATA2:std_logic_vector(3 downto 0):="0111";
    USBF_T_PID_MDATA:std_logic_vector(3 downto 0):="1111";
    USBF_T_PID_ACK :std_logic_vector(3 downto 0):="0010";
    USBF_T_PID_NACK :std_logic_vector(3 downto 0):="1010";
    USBF_T_PID_STALL:std_logic_vector(3 downto 0):="1110";
    USBF_T_PID_NYET :std_logic_vector(3 downto 0):="0110";   
    USBF_T_PID_PRE :std_logic_vector(3 downto 0):="1100";
    USBF_T_PID_ERR :std_logic_vector(3 downto 0):="1100";      
    USBF_T_PID_SPLIT:std_logic_vector(3 downto 0):="1000";
    USBF_T_PID_PING :std_logic_vector(3 downto 0):="0100";   
    USBF_T_PID_RES :std_logic_vector(3 downto 0):="0000";
    );
   
    port(clk,rst:in std_logic;
      rx_data:in std_logic_vector(7 downto 0);
      rx_valid,rx_active,rx_err:in std_logic;
      --PID数据包标试符信息输出
      
    pid_OUT,pid_IN,pid_SOF,pid_SETUP:buffer std_logic;
    pid_DATA0,pid_DATA1,pid_DATA2,pid_MDATA:buffer std_logic;
    pid_ACK,pid_NACK,pid_STALL,pid_NYET:buffer std_logic;
    pid_PRE,pid_ERR,pid_SPLIT,pid_PING:buffer std_logic;
    pid_cks_err:buffer std_logic;    --pid出错标识
     
    --令牌包信息输出接口
    token_fadr:buffer std_logic_vector(6 downto 0);  --地址信息
    token_endp:buffer std_logic_vector(3 downto 0);  --端点信息
    token_valid:buffer std_logic;           --令牌包有效信息
    crc5_errut std_logic;              --令牌包的CRC5错误检查
    frame_nout std_logic_vector(10 downto 0);    --SOF信息包输出信息

    --数据包信息输出接口
    rx_data_stut std_logic_vector(7 downto 0);    --数据输出
    rx_data_validut std_logic;            --数据有效
    rx_data_doneut std_logic             --数据传输结束
    crc16_errut std_logic;              --数据包CRC6出错检测
    seq_err:buffer std_logic;             --状态机出错信息
    );
    end entity;

    architecture arch_usbf_pd of usbf_pd is
   

    compand usbf_crc5 port(
      crc_in:in std_logic_vector(15 downto 0);
      din:in std_logic_vector(7 downto 0);
      crc_outut std_logic_vector(15 downto 0);
      );
    end compand;

    --状态机状态定义
    constant IDLE:std_logic_vector(3 downto 0):="0001";
    constant ACTIVE:std_logic_vector(3 downto 0):="0010";
    constant TOKEN:std_logic_vector(3 downto 0):="0100";
    constant DATA:std_logic_vector(3 downto 0):="1000";
    signal state,next_state:std_logic_vector(3 downto 0);

    signal pid:std_logic_vector(7 downto 0);    --PDI
    signal pid_le_sm:std_logic;    --状态机pid有效
    signal pid_ld_en:std_logic;    --pid有效使能
   
    signal pid_RES:std_logic;
    signal pid_TOKEN:std_logic;    --所有的令牌包统一的信号
    signal pid_DATA:std_logic;     --所有的数据包统一信号
   
    signal token0,token1:std_logic_vector(7 downto 0);  --令牌包缓存
    signal token_le_1,token_le_2:std_logic;       --令牌包缓存有效使能
    signal token_crc5:std_logic_vector(4 downto 0);

    signal d0,d1,d2:std_logic_vector(7 downto 0);  --数据通道延迟线(计算CRC5)
    signal data_valid_d:std_logic;          --状态机输出数据有效信号
    signal data_done:std_logic;           --数据有效信号延迟
    signal rxv1:std_logic;
    signal rxv2:std_logic;

    signal got_pid_ack:std_logic;
    signal token_valid_r1:std_logic;
    signal token_valid_str1:std_logic;
   
    signal rx_active_r:std_logic;          --输出有效
   
    signal crc5_out:std_logic_vector(4 doento 0);
    signal crc5_out2:std_logic_vector(4 doento 0);
    signal crc16_clr:std_logic;
    signal crc16_sum:std_logic_vector(15 down 0);
    signal crc16_out:std_logic_vector(15 down 0);  --crc5 crc16校验
  
    signal rx_data_temp:std_logic_vector(7 downto 0);
    signal token_temp:std_logic_vector(10 downto 0);
   
    begin
   
    --PID逻辑分析
    pid_ld_en<=pid_le_sm and rx_active and rx_valid;
    --PID输入寄存
    process(clk,rst)begin
      if(rst='0')then
         pid<="11110000";
      elsif clk'event and clk='1'then
          if(pid_ld_en='1')then
             pdi<=rx_data;
          end if;

      end if;
    end process;

    --PID校验,识别
    process(pid)begin
      if pid(3 downto 0)/=not(pid(7 downto 4))then pid_cks_err<='1';
      else pid_cks_err<='0';
      end if;                --PID校验

      if pid(3 downto 0)=USBF_T_PID_OUT then pid_out<="1';
      else pid_OUT<='0';
      end if;
     
      if pid(3 downto 0)=USBF_T_PID_IN then pid_IN<='1';
      else PID_SETUP<='0';
      end if;

      if pid(3 downto 0)=USBF_T_PID_SOF then pid_SOF<='1';
      else PID_SOF<='0';
      end if;

      if pid(3 downto 0)=USBF_T_PID_SETUP then pid_setup<='1';
      else PID_SETUP<='0';
      end if;
  
      if pid(3 downto 0)=USBF_T_PID_DATA0 then pid_DATA0<='1';
      else PID_DATA0<='0';
      end if;
  
      if pid(3 downto 0)=USBF_T_PID_DATA1 then pid_DATA<='1';
      else PID_DATA1<='0';
      end if;

      if pid(3 downto 0)=USBF_T_PID_DATA2 then pid_DATA2<='1';
      else PID_DATA2<='0';
      end if;

      if pid(3 downto 0)=USBF_T_PID_MDATA then pid_MDATA<='1';
      else PID_MDATA<='0';
      end if;
      
      if pid(3 downto 0)=USBF_T_PID_ACK then pid_ACK<='1';
      else PID_ACK<='0';
      end if;
         
      if pid(3 downto 0)=USBF_T_PID_NACK then pid_NACK<='1';
      else PID_NACK<='0';
      end if;
      
      if pid(3 downto 0)=USBF_T_PID_STALL then pid_STALL<='1';
      else PID_STALL<='0';
      end if;
      
      if pid(3 downto 0)=USBF_T_PID_NYET then pid_NYET<='1';
      else PID_NYET<='0';
      end if;

      if pid(3 downto 0)=USBF_T_PID_PRE then pid_PRE<='1';
      else PID_PRE<='0';
      end if;

      if pid(3 downto 0)=USBF_T_PID_ERR then pid_ERR<='1';
      else PID_ERR<='0';
      end if;

      if pid(3 downto 0)=USBF_T_PID_SPLIT then pid_SPLIT<='1';
      else PID_SPLIT<='0';
      end if;

      if pid(3 downto 0)=USBF_T_PID_PING then pid_PING<='1';
      else PID_PING<='0';
      end if;

      if pid(3 downto 0)=USBF_T_PID_RES then pid_RES<='1';
      else PID_ACK<='0';
      end if;

    end process

    --令牌包数据包的统一识别
    pid_TOKEN<=pid_OUT or pid_SOF or pid_SRTUP or pid_PING;
    pid_DATA<=pid_DATA0 or pid_DATA1 or pid_DATA2 or pid_MDATA;

    --令牌包分析模块
    process(clk)begin
       if clk'event and clk='1'then
          if(token_le_1='1')then
             token0<=rx_data;
          end if;
       end if
    end process;

    process(clk)begin
       if clk'event and clk='1'then
          if(token_le_2='1')then
             token1<=rx_data;
          end if;
       end if
    end process;
  
    process(clk)begin
       if clk'event and clk='1'then
       token_valid_r1<=token_le_2;
       end if
    end process;

    ;
QQ:1625345502
点赞  2011-6-23 21:44
process(clk)begin
       if clk'event and clk='1'then
       token_valid_str1<=token_valid_r1 or got_pid_ack;   
       end if
    end process;

    token_valid<=token_valid_str1;
   
   --CRC5数据校验模块,时序需要一个时钟周期

    process(token_valid,crc5_out2,token_crc5)begin
      if(crc5_out2/=token_crc5)then
         crc5_err<=token_valid;
      else crc5_err<='0';
      end if;
    end process

    token_temp<=token_fadr(0)&token_fadr(1)&token_fadr(2)&token_fadr(3)&token_fadr(4)          &token_fadr(5)&token_fadr(6)&token_endp(0)&token_endp(1)&token_endp(2)
          &token_endp(03);
    usbf_crc5_u0:usbf_crc5 port map(
      "11111",
      token_temp,
      crc5_out
      );

    --CRC5校验输出
      crc5_out2<=not(crc5_out(0)&crc5_out(1)&crc5_out(2)&crc5_out(3)&crc5_out(4);

      frame_no<=token1(2 downto 0)&token0;
      token_fadr<=token0(6 downto 0);
      token_endp<=token1(2 downto 0)&token0(7);
      token_crc5<=token1(7 downto 3);

    --数据接收逻辑
    --rxv1 rxv2的作用是对数据有效信号做2个时钟的延迟
   process(clk,rst)begin
      if(rst='0') then
          rxv1<='0';
    elsif clk'event and clk='1'then
       if(data_valid_d='1')then
           rxv1<='1';
       elsif(data_done='1')then
           rxv1<='0';
       end if;
    end if;
   end process;
  
   process(clk,rst)begin
      if(rst='0') then
         rxv2<='0';
      elsif clk'event and clk='1'then
          if(rxv1='1' and data_valid_d='1')then
             rxv2<='1';
             elsif(data_done='1')then
                rxv2<='0';
             end if;
          end if;
      end process;

      process(clk)begin
        if clk'event and clk='1'then
            data_valid0<=rxv2 and data_valid_d;
        end if;
      end process;

      process(clk)begin
        if clk'event and clk='1'then
            if(data_valid_d='1')then d0<=rx_data;end if;
            if(data_valid_d='1')then d1<=d0;end if;
            if(data_valid_d='1')then d2<=d1;end if;    --数据2个时钟延迟
        end if;
      end process;

      rx_data_st<=d2;
      rx_data_valid<=data_vlid0;
      rx_data_done<=data_done;

      --crc16数据校验
      process(clk)begin
        if clk'event and clk='1'then
        rx_active_r<=rx_active;
        end if;
      end process;

      crc16_clr<=rx_active and not(rx_active_r);

      process(clk)begin
        if clk'event and clk='1'then
          if(crc16_clr='1')then
             crc16_sum<='1111111111111111";
          else
          if(data_valid_d='1')then crc16_sum<=crc16_out;
          end if;
          end if;
       end if;
      end process;

      rx_data_temp<=rx_data(0)&rx_data(1)&rx_data(2)&rx_data(3)
             &rx_data(4)&rx_data(5)&rx_data(6)&rx_data(7);
      usbf_crc16_u1:usb_crc16 port map(
        crc16_sum,
        rx_data_temp,
        crc16_out
        );
      
      process(data_done,crc16_sum)begin
        if crc16_sum/="1000000000001101"then
           crc16_err<=data_done;
        else crc16_err<='0';
        end if;
      end process;

      --状态机设计
      process(clk,rst)begin
        if(rst='0') then
            state<=IDLE;
        elseif clk'event and clk='1'then
            state<=next_state;
        end if;
      end process;

      process(state,rx_valid,rx_active,rx_err,pid_ACK,pid_TOKEN,pid_DATA)
       begin
        next_state<=state; --默认状态不改变状态机状态
        pid_le_sm<='0';
        token_le_1<='0';
        token_le_2<='0';
        data_valid_d<='0';
        data_done<='0';
        seq_err<='0';
        got_pid_ack<='0';
        case state is    ---状态机
          when IDLE=>
          pid_le_sm<='1';
          if(rx_valid='1' and rx_active='1')then
             next_state<=ACTIVE;
          end if;
        when ACTIVE=>
           --收到数据包标识符号
           if(pid_ACK='1' and rx_err='0')then
              got_pid_ack<='1';
              if(rx_active='0')then
                 next_atate<=IDLE;
              end if;
           --收到令牌token数据包标识符
           elsif(pid_TOKEN='1' and rx_valid='1' and rx_ctive='1' and            rx_err='0')then           
              token_le_1<='1';
              next_state<=TOKEN;
           --收到data数据包标识符
           elsif(pid_TOKEN='1' and rx_valid='1' and rx_ctive='1' and            rx_err='0')then  
              data_valid_d<='1';
              next_state<=DATA;
           elsif(rx_active='0' or rx_err='1'or
              (rx_valid='1' and not(pid_TOKEN='1' or pid_DATA='1')))then
              seq_err<==not(rx_err);
              if(rx_active='0')then next_state<=IDLE;
              end if;
            end if;
      --令牌token数据包处理
      when TOKEN=>
         if(rx_valid='1' and rx_active='1' and rx_err='0')then
            token_le_2<='1';
            next_state<=IDLE;
         elsif(rx_active='0' or rx_err='1')then
            seq_err<=not(rx_err);
            if(rx_active='0')then
               next_state<=IDLE;
            end if;
         end if;
       --DATA数据包处理
       when DATA=>
          if(rx_valid='1' and rx_active='1' and rx_err='0') then
             data_vlid_d<='1';
          end if;
      
          if(rx_active='0' or rx_err='1')then
             data_done<='1';
             if(rx_active='0')then
                next_state<=IDLE;
             end if;
          end if;
        when other=>
           null;
        end case;
       end process;
       end architecture;
QQ:1625345502
点赞  2011-6-23 21:44

验证过能用吗?

一个为理想不懈前进的人,一个永不言败人! http://shop57496282.taobao.com/ 欢迎光临网上店铺!
点赞  2011-6-25 20:28
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复