|
发表于 2012-4-19 22:36:02
|
显示全部楼层
本帖最后由 wye11083 于 2012-4-19 22:37 编辑
Hi,我已经实现了一个命令控制器模块,支持输入输出指令,8位数据,1位Probe。输入格式:
D15--Direction,0:Host->Device,1:Device->Host(Only valid when Probe=1),
D14-D8--Command,
D7-D0--Data.
所有操作都是同步操作。所有Probe信号均保持一个周期,或者仅在一个周期有效。
module CPUIO_CommandControl(
input int_in_GCLK,
input int_in_GRST,
inout [15:0] port_io_FIFOD,
input port_in_DIN,
output [15:0] int_out_FIFOD,
output int_out_Cmd_Valid,
output int_out_Cmd_Is_Read,
input [15:0] int_in_Data_Out,
input int_in_Data_Latch_Valid
);
// Use DIN (PA0) as input trigger. Whenever a rising transition occurs on DIN,
// Latch FIFO and send command.
// For the first cycle of DIN high, load command and data in. For the second cycle,
// if command is Read, then output data; else load as usual.
reg [15:0] r_port_io_FIFOD = 16'h0000;
wire w_CommandIsRead = r_port_io_FIFOD[15];
reg [15:0] r_port_io_FIFOD_Output = 16'h0000;
reg [1:0] r_port_in_DIN_delay;
wire w_port_in_DIN_Edge = ^r_port_in_DIN_delay;
reg [1:0] rs_FIFOD_Command;
reg r_FIFOD_Output_Enable;
assign port_io_FIFOD = (port_in_DIN & w_CommandIsRead & r_FIFOD_Output_Enable)?r_port_io_FIFOD_Output:'bz;
reg r_Command_Input_Ready;
assign int_out_FIFOD = r_port_io_FIFOD;
assign int_out_Cmd_Valid = r_Command_Input_Ready;
assign int_out_Cmd_Is_Read = w_CommandIsRead;
// r_Command_Input_Ready and r_port_io_FIFOD is INPUT.
// r_port_io_FIFOD_Output is OUTPUT.
// OUTPUT is valid only when previously command is READ command.
always @(posedge int_in_GCLK or negedge int_in_GRST)
begin
if(~int_in_GRST)
begin
r_port_io_FIFOD <= 16'h0000;
r_port_in_DIN_delay <= 0;
rs_FIFOD_Command <= 0;
r_Command_Input_Ready <= 0;
r_FIFOD_Output_Enable <= 0;
end
else
begin
r_port_in_DIN_delay <= {r_port_in_DIN_delay[0],port_in_DIN};
if(int_in_Data_Latch_Valid)
r_port_io_FIFOD_Output <= int_in_Data_Out;
else
r_port_io_FIFOD_Output <= r_port_io_FIFOD_Output;
case (rs_FIFOD_Command)
0:
begin
// State is input default.
if(w_port_in_DIN_Edge & r_port_in_DIN_delay[0])
begin
r_port_io_FIFOD <= port_io_FIFOD;
r_Command_Input_Ready <= 1;
rs_FIFOD_Command <= 1;
end
else
begin
r_Command_Input_Ready <= 0;
end
end
1:
begin
r_Command_Input_Ready <= 0;
// Jump on falling edge of DIN
if(w_port_in_DIN_Edge & ~r_port_in_DIN_delay[0] & w_CommandIsRead)
begin
rs_FIFOD_Command <= 2;
r_FIFOD_Output_Enable <= 1;
end
else if(w_port_in_DIN_Edge & ~r_port_in_DIN_delay[0])
rs_FIFOD_Command <= 0;
else
rs_FIFOD_Command <= rs_FIFOD_Command;
end
2:
begin
// Read operation.
if(w_port_in_DIN_Edge & ~r_port_in_DIN_delay[0])
begin
rs_FIFOD_Command <= 0;
r_port_io_FIFOD[15] <= 0;
r_FIFOD_Output_Enable <= 0;
end
else
begin
rs_FIFOD_Command <= rs_FIFOD_Command;
end
end
default:
rs_FIFOD_Command <= 0;
endcase
end
end
endmodule
这个模块是从顶模块中抠出来下放的,为了保持顶层模块简洁,所以没有单独的TestBench。就简单说下吧,DIN一般为低,当输入时,D15置0,后面命令等等置好,然后DIN拉高,再拉低,则命令/数据就载入了。如果要输出,D15置1,然后置命令和数据,然后DIN拉高,拉低(完成第一步,输入命令)。只要这个命令接收到(DIN上升沿有效),FPGA后面应该处理命令,并且置int_in_Data_Out数据,且置int_in_Data_Latch_Valid为1(1个周期)。当第二个周期时,DIN拉高,就可以从FPGA中读数据了,然后DIN拉低,一个读周期完成,FPGA自动进入写命令周期。
即写周期:D15置0,然后DIN拉高再拉低;
读周期:D15置1,然后DIN拉高再拉低,然后置单片机IO为输入,DIN拉高,读数据,DIN再拉低。目前上板正常工作,且顺利接驳I2C模块读写。
有一点要注意,这个port_开头的信号都是连FPGA管脚的信号,int_开头的都是连的内部信号。inout可以直接连内部模块,只要连的是port_io信号。 |
|