📄 parallel.v
字号:
//duoduo
//2003-11-17,3:22 simulation is good
//note: if MCU write to parallel OUT register,PLD will produce right handshake when PC first read
// but the second read of PC will not produce handshake,so PC will find timeout
// it can think as this: after PC read first,no before next data is send by MCU,the second PC
// read is illegal,because MCU has no data to send.
module PARALLEL(
MAIN_CLK,
P0,
RD_PARA_ADD_REG,
RD_PARA_DATA_REG,
WR_PARA_ADD_REG,
WR_PARA_DATA_REG,
INNER_RST,
PARA_RST_REG_BIT,
PARA_INT_TO_MCU,
PARA_D,
PARA_DATA_STROBE,
PARA_ADD_STROBE,
PARA_WRITE,
PARA_WAIT,
PARA_RST,
PARA_INT,
PARA_USER1
//PARA_USER2,
//PARA_USER3
);
input MAIN_CLK;
inout P0;
input RD_PARA_ADD_REG;
input RD_PARA_DATA_REG;
input WR_PARA_ADD_REG;
input WR_PARA_DATA_REG;
input INNER_RST;
input PARA_RST_REG_BIT;
output PARA_INT_TO_MCU;
inout PARA_D;
input PARA_DATA_STROBE;
input PARA_ADD_STROBE;
input PARA_WRITE;
output PARA_WAIT;
input PARA_RST;
output PARA_INT;
output PARA_USER1;
//output PARA_USER2;
//output PARA_USER3;
wire [7:0] P0;
wire [7:0] PARA_D;
reg PARA_WAIT;
reg PARA_INT;
///////////////////
wire PARA_RST_CTR;
reg [7:0] PARA_DATA_IN_REG;
reg [7:0] PARA_ADD_IN_REG;
reg [7:0] PARA_DATA_OUT_REG;
reg [7:0] PARA_ADD_OUT_REG;
reg [2:0] PARA_STATE_MACHINE;
reg PARA_WR_ENABLE;
reg PARA_WR_REG_SELECT;
reg MCU_WR_ENABLE;
reg MCU_WR_REG_SELECT;
reg PARA_RD_ALREADY;
reg PARA_INT_TO_MCU;
reg PARA_USER1;
reg [7:0] P0_OUT;
reg [7:0] PARA_D_OUT;
wire DATA_STROBE;
assign PARA_RST_CTR = INNER_RST | ~PARA_RST | ~PARA_RST_REG_BIT ;
parameter [3:0]
PARA_STATE_S0 = 3'B000,
PARA_STATE_S1 = 3'B001,
PARA_STATE_S2 = 3'B011,
PARA_STATE_S3 = 3'B010,
PARA_STATE_S4 = 3'B110,
PARA_STATE_S5 = 3'B111,
PARA_STATE_S6 = 3'B101,
PARA_STATE_S7 = 3'B100;
always @(posedge PARA_RST_CTR or posedge MAIN_CLK)
begin
if (PARA_RST_CTR == 1'B1)
begin
PARA_STATE_MACHINE = PARA_STATE_S0;
PARA_INT_TO_MCU = 1'B1;
PARA_WAIT = 1'B0;
PARA_INT = 1'B0;
PARA_USER1 = 1'B0;
PARA_WR_REG_SELECT = 1'B0;
PARA_WR_ENABLE = 1'B0;
MCU_WR_REG_SELECT = 1'B0;
MCU_WR_ENABLE = 1'B0;
PARA_RD_ALREADY = 1'B1;
end
else
begin
case (PARA_STATE_MACHINE)
PARA_STATE_S0:
begin
if (PARA_WAIT == 1'B0)
begin
if ((~PARA_WRITE & (~PARA_DATA_STROBE | ~PARA_ADD_STROBE)) == 1'B1) //if PC write
begin //if PC can normal write
PARA_WAIT = 1'B1; //handshake
PARA_STATE_MACHINE = PARA_STATE_S1; //to wait parallel data strobe or address strobe is deassert
PARA_WR_ENABLE = 1'B1;
if (~PARA_DATA_STROBE == 1'B1) PARA_WR_REG_SELECT = 1'B0;
else PARA_WR_REG_SELECT = 1'B1;
end
else if ((~WR_PARA_DATA_REG | ~WR_PARA_ADD_REG )==1'b1) //if MCU write to parallel
begin
MCU_WR_ENABLE = 1'B1;
PARA_STATE_MACHINE = PARA_STATE_S4; //to wait MCU data write or address write is deasserted
if (WR_PARA_DATA_REG == 1'B0) MCU_WR_REG_SELECT = 1'B0;
else MCU_WR_REG_SELECT = 1'B1;
end
end
end
PARA_STATE_S1:
begin ////wait parallel data strobe or address strobe is deasserted
if ((PARA_DATA_STROBE & PARA_ADD_STROBE) == 1'b1)
begin
PARA_INT_TO_MCU = 1'B0; //produce interrupt to mcu
PARA_WR_ENABLE = 1'B0; //protect parallel IN register and prohibit it not to be write before mcu read it
PARA_STATE_MACHINE = PARA_STATE_S2; //to expect MCU to read parallel IN register
end
//else will wait at this state
end
PARA_STATE_S2:
begin ////wait MCU to read the right parallel IN register
//if MCU read the incorrect parallel IN register,state will stay at this state,
//and only PARA_RST_CTR can exit this state
if (~PARA_WR_REG_SELECT & ~RD_PARA_DATA_REG) PARA_STATE_MACHINE = PARA_STATE_S3;
else if (PARA_WR_REG_SELECT & ~RD_PARA_ADD_REG) PARA_STATE_MACHINE = PARA_STATE_S3;
end
PARA_STATE_S3:
begin ////MCU has already read the parallel IN register
if ((RD_PARA_DATA_REG & RD_PARA_ADD_REG) == 1'b1)
begin
PARA_INT_TO_MCU = 1'b1; //deassert the interrupt signal to mcu
PARA_WAIT = 1'B0; //instruct PC can start next cycle
PARA_STATE_MACHINE = PARA_STATE_S0;
end
end
PARA_STATE_S4:
begin //////to wait MCU data write or address write is deasserted
if ((WR_PARA_DATA_REG & WR_PARA_ADD_REG) == 1'b1)
begin
PARA_INT = 1'B1; //produce interrupt to PC
MCU_WR_ENABLE = 1'B0; //protect parallel OUT register and prohibit it not to be write before PC read it
PARA_USER1 = MCU_WR_REG_SELECT; //instruction to PC whether data register or address register that MCU write to
PARA_RD_ALREADY = 1'B0; //instruction to MCU that whether PC has already read the right parallel OUT register
PARA_STATE_MACHINE = PARA_STATE_S5; //to expect PC to read parallel OUT register
end
//else will wait at this state
end
PARA_STATE_S5:
begin ////wait PC to read the right parallel IN register
//if PC read the incorrect parallel OUT register,state will stay at this state,
//and PC will find it's read is timeout
////and only PARA_RST_CTR can exit this state
if ((~MCU_WR_REG_SELECT & ~PARA_DATA_STROBE & PARA_WRITE) == 1'B1)
begin
PARA_STATE_MACHINE = PARA_STATE_S6;
PARA_WAIT = 1'B1;
end
else if ((MCU_WR_REG_SELECT & ~PARA_ADD_STROBE & PARA_WRITE) == 1'B1)
begin
PARA_STATE_MACHINE = PARA_STATE_S6;
PARA_WAIT = 1'B1;
end
end
PARA_STATE_S6:
begin ////PC has already read the parallel OUT register
if ((PARA_DATA_STROBE & PARA_ADD_STROBE) == 1'b1)
begin
PARA_INT = 1'B0; //deassert the interrupt signal to PC
PARA_WAIT = 1'B0; //instruct PC can start next cycle
PARA_RD_ALREADY = 1'B1; //instruction to MCU thar PC has already read
PARA_STATE_MACHINE = PARA_STATE_S0;
end
end
PARA_STATE_S7: //redudancy state
begin
PARA_STATE_MACHINE = PARA_STATE_S0;
end
endcase
end
end
//parallel write to address register or data register
always @(posedge PARA_RST_CTR or posedge PARA_DATA_STROBE)
begin
if (PARA_RST_CTR == 1'B1) PARA_DATA_IN_REG = 8'H00;
else
begin
if (PARA_WR_ENABLE == 1'B1) PARA_DATA_IN_REG = PARA_D;
end
end
always @(posedge PARA_RST_CTR or posedge PARA_ADD_STROBE)
begin
if (PARA_RST_CTR == 1'B1) PARA_ADD_IN_REG = 8'H00;
else
begin
if (PARA_WR_ENABLE == 1'B1) PARA_ADD_IN_REG = PARA_D;
end
end
//parallel read
always @(PARA_WRITE or PARA_DATA_STROBE or PARA_ADD_STROBE)
begin
if (PARA_WRITE == 1'B1)
begin
if (PARA_DATA_STROBE == 1'B0) PARA_D_OUT = PARA_DATA_OUT_REG;
else if (PARA_ADD_STROBE == 1'B0) PARA_D_OUT = PARA_ADD_OUT_REG;
end
end
assign PARA_D = ((PARA_WRITE & (~PARA_DATA_STROBE | ~PARA_ADD_STROBE )) == 1'B1)? PARA_D_OUT : 8'HZZ;
//MCU write to address register or data register
always @(posedge PARA_RST_CTR or posedge WR_PARA_DATA_REG)
begin
if (PARA_RST_CTR == 1'B1) PARA_DATA_OUT_REG = 8'H00;
else
begin
if (MCU_WR_ENABLE == 1'B1) PARA_DATA_OUT_REG = P0;
end
end
always @(posedge PARA_RST_CTR or posedge WR_PARA_ADD_REG)
begin
if (PARA_RST_CTR == 1'B1) PARA_ADD_OUT_REG = 8'H00;
else
begin
if (MCU_WR_ENABLE == 1'B1) PARA_ADD_OUT_REG = P0;
end
end
//mcu read
always @(RD_PARA_ADD_REG or RD_PARA_DATA_REG)
begin
if (RD_PARA_DATA_REG == 1'B0) P0_OUT = PARA_DATA_IN_REG;
else if (RD_PARA_ADD_REG == 1'B0) P0_OUT = PARA_ADD_IN_REG;
end
assign P0 = ((~RD_PARA_ADD_REG | ~RD_PARA_DATA_REG) == 1'B1)? P0_OUT : 8'HZZ;
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -