2009년 7월 17일 금요일

USB camera (verilog HDL)

`timescale 1ns / 1ps

module usb_camera(nReset, nStart, Pclk, Href, Vsync, Y,
nLB, nUB, nCS, nWE, nOE, Address, Data,
Uclk, nFlagB, nPktend, nSLWR, Udata,
TP);

input nReset;
input nStart;
input Pclk;
input Vsync;
input Href;
input [7:0] Y;

output nLB;
output nUB;
output nCS;
output nWE;
output nOE;
output [17:0] Address;
inout [15:0] Data;

output Uclk;
input nFlagB;
output nPktend;
output nSLWR;
output [15:0] Udata;
output [7:0] TP;

wire pclkdcm;
wire clkdcm;
DCM dcm2x(.CLKIN(Pclk), .RST(1'b0), .CLKFB(pclkdcm), .CLK0(pclkdcm), .CLK2X(clkdcm), .LOCKED());
defparam dcm2x.CLKIN_PERIOD = 37.0; // 37ns

// make Global buffered pclk_2x(27*2Mhz) and new_pclk(27Mhz)
//wire pclk_2x;
//BUFG buf2x(.I(clkdcm), .O(pclk_2x));
wire new_pclk;
BUFG bufpclk(.I(pclkdcm), .O(new_pclk));
//wire inv_pclk;
//BUFG bufinvpclk(.I(~new_pclk), .O(inv_pclk));
//wire new_uclk;
//BUFG bufuclk(.I(~Uclk), .O(new_uclk));

assign Uclk = ~pclkdcm;

// parameter declarations
parameter CAM_RCV_SIZE = 4;
parameter CAM_RCV_IDLE = 4'h0;
parameter CAM_RCV_WAIT_VSYNC = 4'h1;
parameter CAM_RCV_VSYNC = 4'h2;
parameter CAM_RCV_WAIT_HREF = 4'h3;
parameter CAM_RCV_HREF1 = 4'h4;
parameter CAM_RCV_HREF2 = 4'h5;
parameter CAM_RCV_END = 4'h6;
parameter CAM_RCV_WAIT_EXT_EMPTY = 4'h7;

// internal variables declaration section - register types (only assigned within always statements).
reg [CAM_RCV_SIZE-1:0] cam_rcv_state;
reg [10:0] pixel_count;
reg [8:0] href_count;
reg [7:0] low_byte;
reg [15:0] word_data;
reg frame_end_flag;
reg [1:0] frame_end_count; // write OV7620's data to the external memory

reg ext_write_flag;
reg ext_read_flag;
reg ext_full_flag;
reg ext_empty_flag;
reg [18:0] ext_write_addr; // note MSB is not really address
reg [18:0] ext_read_addr; // note MSB is not really address
wire ext_read_wire;
assign ext_read_wire = ((cam_rcv_state^CAM_RCV_HREF2))&(~ext_empty_flag)&nFlagB;

// external memory -> USB FIFO
parameter USB_CTRL_SIZE = 2;
parameter USB_CTRL_READ = 2'h0;
parameter USB_CTRL_WRITE = 2'h1;
reg [USB_CTRL_SIZE-1:0] usb_ctrl_state;
reg [15:0] usb_data;
reg slwr_flag;
reg [19:0] usb_count;

// write ov7620's data to the external memory
always @(posedge new_pclk) begin
if (~nReset) begin
cam_rcv_state <= CAM_RCV_IDLE;
pixel_count <= 11'h0;
href_count <= 9'h0;
low_byte <= 8'hz;
word_data <= 16'hz;
ext_write_flag <= 1'b0;
frame_end_flag <= 1'b0;
frame_end_count <= 2'h0;

ext_write_addr <= 19'h0;
ext_read_addr <= 19'h0;

ext_read_flag <= 1'b0;
usb_ctrl_state <= USB_CTRL_READ;
slwr_flag <= 1'b1;
usb_count <= 20'h0;
end
else begin
if (~nPktend) frame_end_flag <= 1'b0;
case (cam_rcv_state)
CAM_RCV_IDLE: begin
if (~nStart) cam_rcv_state <= CAM_RCV_WAIT_VSYNC;
end
CAM_RCV_WAIT_VSYNC: begin
if (Vsync) cam_rcv_state <= CAM_RCV_VSYNC;
end
CAM_RCV_VSYNC: begin
if (~Vsync) begin
frame_end_flag <= 1'b0;
href_count <= 9'h00;
usb_count <= 20'h0;
cam_rcv_state <= CAM_RCV_WAIT_HREF;
end
end
CAM_RCV_WAIT_HREF: begin
ext_write_flag <= 1'b0;
pixel_count <= 11'h0;
if (Href) begin
low_byte <= Y;
//pixel_count <= 11'h1;
pixel_count <= pixel_count+1;
href_count <= href_count+1;
cam_rcv_state <= CAM_RCV_HREF2;
end
//else if (Vsync) begin
// cam_rcv_state <= CAM_RCV_END;
//end
end
CAM_RCV_HREF1: begin
low_byte <= Y;
ext_write_flag <= 1'b0;
pixel_count <= pixel_count+1;
cam_rcv_state <= CAM_RCV_HREF2;
end
CAM_RCV_HREF2: begin
word_data <= {Y, low_byte};
ext_write_flag <= 1'b1;
pixel_count <= pixel_count+1;
if (~(pixel_count^11'h4ff)) begin
if (~(href_count^9'h1e0)) cam_rcv_state <= CAM_RCV_END;
else cam_rcv_state <= CAM_RCV_WAIT_HREF;
end
else cam_rcv_state <= CAM_RCV_HREF1;
//cam_rcv_state <= CAM_RCV_WAIT_HREF;
end
CAM_RCV_END: begin
ext_write_flag <= 1'b0;
if (Vsync) begin
cam_rcv_state <= CAM_RCV_WAIT_EXT_EMPTY; // one shot
//frame_end_flag <= 1'b1;
frame_end_count <= 2'b11; // start frame_end_count !!!!!!
end
//else if (Vsync) begin
// cam_rcv_state = CAM_RCV_VSYNC; // continuous
// frame_end_flag <= 1'b1;
//end
end
CAM_RCV_WAIT_EXT_EMPTY: begin
if (ext_empty_flag&slwr_flag) begin
if (~frame_end_count) begin
frame_end_flag <= 1'b1;
cam_rcv_state <= CAM_RCV_IDLE;
end
else frame_end_count <= frame_end_count-1;
end
else frame_end_count <= 2'b11;
end
endcase

if (ext_write_flag) begin
ext_write_addr <= ext_write_addr+1;
end
else if (ext_read_flag) begin
ext_read_addr <= ext_read_addr+1;
end

case (usb_ctrl_state)
USB_CTRL_READ: begin
slwr_flag <= 1'b1;
if (ext_read_wire) begin
ext_read_flag <= 1'b1;
usb_ctrl_state <= USB_CTRL_WRITE;
end
end
USB_CTRL_WRITE: begin
ext_read_flag <= 1'b0;
usb_data <= Data;
slwr_flag <= 1'b0;
usb_count <= usb_count+1;
usb_ctrl_state <= USB_CTRL_READ;
end
endcase
end
end

always @(ext_write_addr or ext_read_addr) begin
if (~(ext_write_addr[17:0]^ext_read_addr[17:0])) begin
if (~(ext_write_addr[18]^ext_read_addr[18])) begin
ext_empty_flag <= 1'b1;
ext_full_flag <= 1'b0;
end
else begin
ext_empty_flag <= 1'b0;
ext_full_flag <= 1'b1;
end
end
else begin
ext_empty_flag <= 1'b0;
ext_full_flag <= 1'b0;
end
end

assign nWE = ~(ext_write_flag);
assign nOE = ~(ext_read_flag);

wire common_wire = ~(ext_write_flagext_read_flag);
assign nCS = common_wire;
assign nLB = common_wire;
assign nUB = common_wire;
assign Address = ext_write_flag ? ext_write_addr[17:0] : ext_read_flag ? ext_read_addr[17:0] : 18'hz;
assign Data = ext_write_flag ? word_data : 16'hz;
assign nSLWR = slwr_flag;
assign Udata = usb_data;
assign nPktend = ~(ext_empty_flag&frame_end_flag);

assign TP[0] = (cam_rcv_state^CAM_RCV_HREF2);
assign TP[1] = ext_write_flag;
assign TP[2] = ext_read_flag;
assign TP[3] = ext_empty_flag;
assign TP[4] = ext_full_flag;
assign TP[5] = ~(usb_count^20'h4b000);
assign TP[6] = ~(usb_ctrl_state^USB_CTRL_READ);
assign TP[7] = ~(usb_ctrl_state^USB_CTRL_WRITE);

endmodule

댓글 없음:

댓글 쓰기