📄 control_logic.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 + -