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

📄 control_logic.v

📁 采用Verilog语言实现了8255A的功能
💻 V
字号:
/*
   //*************************************************************************
   // Project Name: 8255A的功能设计和分析
   // Module Name :	Control_Logic
   // Author:		    张文涛
   // Created:		  2006-10-25
   // Modified:     2006-10-29
   // Revision:		  3.0
   //
   //*************************************************************************
   // 需要注意的地方:1.Port_En在等于0时允许输入,等于1时允许输出;
   //                2.Port_Ld在等于0时有效,允许数据IO;
   //                3.PortA_IO=0时为输入,=1时为输出,与控制字中相反; 
   //*************************************************************************
*/

module  Control_Logic(//input
                      reset,
                      nRD,
                      nWR,
                      A,
                      Din,
                      nSTBA,
                      nSTBB,
                      nACKA,
                      nACKB,
                      
                      //output
                      Data_En,
                      PortA_IO_En,
                      PortB_IO_En,
                      PortC_IO_En,
                      PortA_In_Ld,
                      PortB_In_Ld,
                      PortA_Out_Ld,
                      PortB_Out_Ld,
                      PortC_Out_Ld,
                      Control_Data,
                      Dout_Select
                      );
  
  //-----端口声明-----                    
  input        reset;                                       //复位信号,高电平有效;
  input        nRD;                                         //读信号,低电平有效;
  input        nWR;                                         //写信号,低电平有效;
  input[1:0]   A;                                           //地址信号;
  input[7:0]   Din;                                         //数据口,与CPU通信;
  input        nSTBA;                                       //A口选通信号,由外设输入;
  input        nSTBB;                                       //B口选通信号,由外设输入;
  input        nACKA;                                       //A口应答信号,由外设输入;
  input        nACKB;                                       //B口应答信号,由外设输入;
  
  output       Data_En;                                     //Data总线选择信号;
  output       PortA_IO_En;                                 //A口总线选择信号;
  output       PortB_IO_En;                                 //B口总线选择信号;
  output[7:0]  PortC_IO_En;                                 //C口总线选择信号;
  output       PortA_In_Ld;                                 //A口输入允许信号;
  output       PortB_In_Ld;                                 //B口输入允许信号;
  output       PortA_Out_Ld;                                //A口输出允许信号;
  output       PortB_Out_Ld;                                //B口输出允许信号;
  output[7:0]  PortC_Out_Ld;                                //C口输出允许信号;
  output[6:0]  Control_Data;                                //给PC_IO的控制信号;
  output[1:0]  Dout_Select;                                 //给Dout_Mux的选择信号;
  
  //-----内部寄存器声明-----
  reg          Data_En;
  reg          PortA_IO_En;
  reg          PortB_IO_En;
  reg[7:0]     PortC_IO_En; 
  reg          PortA_In_Ld;
  reg          PortB_In_Ld;
  reg          PortA_Out_Ld;
  reg          PortB_Out_Ld;
  reg[7:0]     PortC_Out_Ld;
  reg[6:0]     Control_Data;
  reg[1:0]     Dout_Select;
  
  reg          Control_Flag;                                //方式选择控制字标志位;
  reg[1:0]     ModeA;                                       //A口方式;
  reg          PortA_IO;                                    //A口I/O;
  reg          PortC_Up_IO;                                 //C口高四位I/O;
  reg          ModeB;                                       //B口方式
  reg          PortB_IO;                                    //B口I/O;
  reg          PortC_Low_IO;                                //C口低四位I/O;
  reg[2:0]     BitSelect;                                   //置位/复位位选择;
  reg          PortC_RS;                                    //置位/复位;
  
  ////////////////////////////控制字寄存器赋值/////////////////////////////
  
  //-----控制字标志位-----
  always @ (reset or A or nWR or Din)
    if(reset)
        Control_Flag = 1'b0;
    else if(A==2'b11 && Din[7]==1'b0)
        Control_Flag = 1'b0;
    else
        Control_Flag = 1'b1;
        
   //-----A口方向-----      
   always @ (reset or A or nWR or Din)
    if(reset)
          PortA_IO = 1'b0;
    else if(A==2'b11 && nWR==1'b0 && Din[7]==1'b1 && ModeA!=2'b10)
          PortA_IO = ~Din[4];
    else if(ModeA==2'b10)
      begin
        if(nSTBA==1'b0)
          PortA_IO = 1'b0;
        else if(nACKA==1'b0)
          PortA_IO = 1'b1;
        else 
          PortA_IO = PortA_IO;
      end
    else
          PortA_IO = PortA_IO;
  
  //-----方式选择控制字-----    
  always @ (reset or A or nWR or Din)
    if(reset)
      begin	                                            
      	ModeA = 2'b00;                                      //复位,寄存器全部清零;
      	PortC_Up_IO = 1'b0;
      	ModeB = 1'b0;
      	PortB_IO =1'b0;
      	PortC_Low_IO =1'b0; 	
     end
    else if(A==2'b11 && nWR==1'b0 && Din[7]==1'b1)          //方式选择控制字;
      begin
      	PortC_Up_IO = ~Din[3];
      	ModeB = Din[2];
      	PortB_IO = ~Din[1];
      	PortC_Low_IO = ~Din[0];
      	ModeA = (Din[6])?2'b10:{Din[6:5]};    	
      end
    else                                                    //其它情况锁存原值;
      begin
      	ModeA = ModeA;
      	PortC_Up_IO = PortC_Up_IO;
      	ModeB = ModeB;
      	PortB_IO = PortB_IO;
      	PortC_Low_IO = PortC_Low_IO;
      end
  
  //-----置位/复位控制字-----   
  always @ (reset or A or nWR or Din)
    if(reset)
      begin
        BitSelect = 3'b000;
      	PortC_RS = 1'b0;
      end
    else if(A==2'b11 && nWR==1'b0 && Din[7]==1'b0) 
      begin
        BitSelect = Din[3:1];
      	PortC_RS = Din[0];
      end
    else
      begin
      	BitSelect = 3'b000;
      	PortC_RS = 1'b0;
      end
  
  ////////////////////////////输入输出选择Port_En/////////////////////////////////
  
  //-----Data_En-----
  always @ (reset or nRD or nWR)
    if(reset)
      Data_En = 1'b0;
    else if(!nWR)
      Data_En = 1'b0;
    else if(!nRD)
      Data_En = 1'b1;
    else
      Data_En = 1'b0;
  
  //-----PortA_IO_En-----
  always @ (reset or ModeA or PortA_IO or nACKA)
    if(reset)                                               //复位清0;
      PortA_IO_En = 1'b0;                                 
    else                                                    //由输入输出方向决定;
      PortA_IO_En = PortA_IO;                  
           
  //-----PortB_IO_En-----                                   
  always @ (reset or ModeB or PortB_IO)
    if(reset)                                               //复位清0;
      PortB_IO_En = 1'b0;
    else                                                    //由输入输出方向决定;
      PortB_IO_En = PortB_IO;
  
  //-----PortC_IO_En-----                                   
  always @ (reset or ModeB or PortC_Low_IO)
    if(reset)                                               //低三位,由B口决定;
      PortC_IO_En[2:0] = 3'b000;                             
    else if(ModeB==1'b1)                                    //B口方式1;
      PortC_IO_En[2:0] = {1'b0,1'b1,1'b1};
    else                                                    //B口方式0;
      PortC_IO_En[2:0] = {3{PortC_Low_IO}};                 
                                                              
     
  always @ (reset or ModeA or PortC_Up_IO or PortC_Low_IO or PortA_IO)
    if(reset)                                               //高5位,由A口决定;
          PortC_IO_En[7:3] = 5'b00000;                        
    else if(ModeA==2'b10)                                   //A口方式2;
          PortC_IO_En[7:3] = 5'b10101;          
    else if(ModeA==2'b01)                                   //A口方式1,与方向有关;                   
      begin
      	if(PortA_IO==1'b0)                                  //A口方式1输入;
      	  PortC_IO_En[7:3] = {{2{PortC_Up_IO}},1'b1,1'b0,1'b1};
      	else                                                //A口方式2输入;
      	  PortC_IO_En[7:3] = {1'b1,1'b0,{2{PortC_Up_IO}},1'b1};
      end   
    else                                                    //A口方式0;
          PortC_IO_En[7:3] = {{4{PortC_Up_IO}},PortC_Low_IO};

  ////////////////////////////锁存允许Port_Ld///////////////////////////
  
  //-----PortA_In_Ld-----
  always @ (reset or A or PortA_IO or nSTBA)
    if(reset)
      PortA_In_Ld = 1'b0;                                   //复位清0;
    else if(ModeA==2'b00 && A==2'b00 && PortA_IO==1'b0)     //A口选中,数据输入,方式0;
      PortA_In_Ld = 1'b0;
    else if(ModeA!=2'b00 && A==2'b00 && PortA_IO==1'b0 && nSTBA==1'b0)
      PortA_In_Ld = 1'b0;                                   //A口选中,数据输入,方式1/2,应答信号有效;
    else
      PortA_In_Ld = 1'b1;                                   //其它情况;
      
  //-----PortB_In_Ld-----
  always @ (reset or A or PortB_IO or nSTBB)                
    if(reset)                                               //复位清0;
      PortB_In_Ld = 1'b0;
    else if(ModeA==2'b00 && A==2'b01 && PortB_IO==1'b0)     //B口选中,数据输入;
      PortB_In_Ld = 1'b0;     
    else if(ModeA!=2'b00 && A==2'b01 && PortB_IO==1'b0 && nSTBB==1'b0)
      PortB_In_Ld = 1'b0;                                   //B口选中,数据输入,方式1/2,应答信号有效;
    else                                                    //其它情况;
      PortB_In_Ld = 1'b1;
                          
  
  //-----PortA_Out_Ld-----
  always @ (reset or A or PortA_IO)
    if(reset)                                               //复位清0;
      PortA_Out_Ld = 1'b0;
    else if(A==2'b00 && PortA_IO==1'b1)                     //A口选中,数据输出;
      PortA_Out_Ld = 1'b0;
    else                                                    //其它情况;
      PortA_Out_Ld = 1'b1;   
      
  //-----PortB_Out_Ld-----                           
  always @ (reset or A or PortB_IO)              
    if(reset)                                               //复位清0;
      PortB_Out_Ld = 1'b0;                      
    else if(A==2'b01 && PortB_IO==1'b1)                     //B口选中,数据输出;                 
      PortB_Out_Ld = 1'b0;     
    else                                                    //其它情况;
      PortB_Out_Ld = 1'b1;                   
         
  //-----PortC_Out_Ld-----
  always @ (reset or Control_Flag or ModeA or ModeB or Din[3:0] or PortA_IO)
    if(reset)
                    PortC_Out_Ld = 8'b00000_000;
    else if(Control_Flag==0)                                //置位复位选择控制字,相应位为0;
      begin
      	case(Din[3:1])
      	  3'b000:   PortC_Out_Ld = 8'b11111110 ;
      	  3'b001:   PortC_Out_Ld = 8'b11111101 ;
      	  3'b010:   PortC_Out_Ld = 8'b11111011 ;
      	  3'b011:   PortC_Out_Ld = 8'b11110111 ;
      	  3'b100:   PortC_Out_Ld = 8'b11101111 ;
      	  3'b101:   PortC_Out_Ld = 8'b11011111 ;
      	  3'b110:   PortC_Out_Ld = 8'b10111111 ;
      	  3'b111:   PortC_Out_Ld = 8'b01111111 ;
      	  default:  PortC_Out_Ld = 8'b11111111 ;
        endcase     
      end
    else                                                    //方式选择控制字,作数据IO的相应位为0;
      if(ModeA==2'b00 && ModeB==1'b0)                       //A口方式0,B口方式0;
                    PortC_Out_Ld = 8'b00000000;
      else if(ModeA==2'b00 && ModeB==1'b1)                  //A口方式0,B口方式1;
                    PortC_Out_Ld = 8'b00000111;
      else if(ModeA==2'b01 && PortA_IO==1'b0 && ModeB==1'b0)//A口方式1输入,B口方式0;
                    PortC_Out_Ld = 8'b00111000;
      else if(ModeA==2'b01 && PortA_IO==1'b0 && ModeB==1'b1)//A口方式1输入,B口方式1;
                    PortC_Out_Ld = 8'b00111111;
      else if(ModeA==2'b01 && PortA_IO==1'b1 && ModeB==1'b0)//A口方式1输出,B口方式0;
                    PortC_Out_Ld = 8'b11001000;
      else if(ModeA==2'b01 && PortA_IO==1'b1 && ModeB==1'b1)//A口方式1输出,B口方式1;
                    PortC_Out_Ld = 8'b11001111;
      else if(ModeA==2'b10 && ModeB==1'b0)                  //A口方式2,B口方式0;
                    PortC_Out_Ld = 8'b11111000;
      else if(ModeA==2'b10 && ModeB==1'b1)                  //A口方式2,B口方式1;
                    PortC_Out_Ld = 8'b11111111;
      else                                                  //其它情况;
                    PortC_Out_Ld = 8'b00000000;
  
  ////////////////////////////其它/////////////////////////////
  
  //-----Control_Data-----
  always @ (reset or Control_Flag or ModeA or ModeB or PortA_IO or PortB_IO)
    if(reset)                                               //输出给PC_IO的控制信号;
      Control_Data = 7'b0000000;                    
    else
      Control_Data = {PortC_RS,Control_Flag,ModeA,ModeB,PortA_IO,PortB_IO};
      
  //-----Dout_Select-----                                   //输出给Dout_Mux的选择信号;
  always @ (reset or A or nRD)
    if(reset)
                   Dout_Select = 2'b00;
    else if(nRD==1'b0)
      case(A)
        2'b00:     Dout_Select = 2'b00;
        2'b01:     Dout_Select = 2'b01;
        2'b10:     Dout_Select = 2'b10;
        default:   Dout_Select = 2'b00;
      endcase
    else
                   Dout_Select = Dout_Select;
endmodule 
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
 

⌨️ 快捷键说明

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