修改目录, 添加ch3的代码
parent
eaa3f793fd
commit
7926a80163
@ -0,0 +1,287 @@
|
||||
|
||||
module axi_mpeg2encoder_wrapper #(
|
||||
parameter AXI_IDWIDTH = 4
|
||||
) (
|
||||
input wire rstn,
|
||||
input wire clk,
|
||||
// AXI-MM AW interface ----------------------------------------------------
|
||||
output wire s_axi_awready,
|
||||
input wire s_axi_awvalid,
|
||||
input wire [ 63:0] s_axi_awaddr,
|
||||
input wire [ 7:0] s_axi_awlen,
|
||||
input wire [AXI_IDWIDTH-1:0] s_axi_awid,
|
||||
// AXI-MM W interface ----------------------------------------------------
|
||||
output wire s_axi_wready,
|
||||
input wire s_axi_wvalid,
|
||||
input wire s_axi_wlast,
|
||||
input wire [ 63:0] s_axi_wdata,
|
||||
// AXI-MM B interface ----------------------------------------------------
|
||||
input wire s_axi_bready,
|
||||
output wire s_axi_bvalid,
|
||||
output wire [AXI_IDWIDTH-1:0] s_axi_bid,
|
||||
output wire [ 1:0] s_axi_bresp,
|
||||
// AXI-MM AR interface ----------------------------------------------------
|
||||
output wire s_axi_arready,
|
||||
input wire s_axi_arvalid,
|
||||
input wire [ 63:0] s_axi_araddr,
|
||||
input wire [ 7:0] s_axi_arlen,
|
||||
input wire [AXI_IDWIDTH-1:0] s_axi_arid,
|
||||
// AXI-MM R interface ----------------------------------------------------
|
||||
input wire s_axi_rready,
|
||||
output wire s_axi_rvalid,
|
||||
output wire s_axi_rlast,
|
||||
output reg [ 63:0] s_axi_rdata,
|
||||
output wire [AXI_IDWIDTH-1:0] s_axi_rid,
|
||||
output wire [ 1:0] s_axi_rresp
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// AXI READ state machine
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
enum reg [0:0] {R_IDLE, R_BUSY} rstate = R_IDLE;
|
||||
|
||||
reg [AXI_IDWIDTH-1:0] rid = '0;
|
||||
reg [ 7:0] rcount = '0;
|
||||
reg [ 63-3:0] raddr_63_3, raddr_63_3_r;
|
||||
wire [ 63:0] raddr = {raddr_63_3 , 3'h0};
|
||||
wire [ 63:0] raddr_r = {raddr_63_3_r, 3'h0};
|
||||
|
||||
assign s_axi_arready = (rstate == R_IDLE);
|
||||
assign s_axi_rvalid = (rstate == R_BUSY);
|
||||
assign s_axi_rlast = (rstate == R_BUSY) && (rcount == 8'd0);
|
||||
assign s_axi_rid = rid;
|
||||
assign s_axi_rresp = '0;
|
||||
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if (~rstn) begin
|
||||
rstate <= R_IDLE;
|
||||
rid <= '0;
|
||||
rcount <= '0;
|
||||
end else begin
|
||||
case (rstate)
|
||||
R_IDLE :
|
||||
if (s_axi_arvalid) begin
|
||||
rstate <= R_BUSY;
|
||||
rid <= s_axi_arid;
|
||||
rcount <= s_axi_arlen;
|
||||
end
|
||||
R_BUSY :
|
||||
if (s_axi_rready) begin
|
||||
if (rcount == 8'd0) // the last data of read session
|
||||
rstate <= R_IDLE;
|
||||
rcount <= rcount - 8'd1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb
|
||||
if (rstate == R_IDLE && s_axi_arvalid)
|
||||
raddr_63_3 = s_axi_araddr[63:3];
|
||||
else if (rstate == R_BUSY && s_axi_rready)
|
||||
raddr_63_3 = raddr_63_3_r + 61'h1;
|
||||
else
|
||||
raddr_63_3 = raddr_63_3_r;
|
||||
|
||||
always @ (posedge clk)
|
||||
raddr_63_3_r <= raddr_63_3;
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// AXI WRITE state machine
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
enum reg [1:0] {W_IDLE, W_BUSY, W_RESP} wstate = W_IDLE;
|
||||
|
||||
reg [AXI_IDWIDTH-1:0] wid = '0;
|
||||
reg [ 7:0] wcount = '0;
|
||||
reg [ 63-3:0] waddr_63_3 = '0;
|
||||
wire [ 63:0] waddr = {waddr_63_3, 3'h0};
|
||||
|
||||
assign s_axi_awready = (wstate == W_IDLE);
|
||||
assign s_axi_wready = (wstate == W_BUSY);
|
||||
assign s_axi_bvalid = (wstate == W_RESP);
|
||||
assign s_axi_bid = wid;
|
||||
assign s_axi_bresp = '0;
|
||||
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if (~rstn) begin
|
||||
wstate <= W_IDLE;
|
||||
wid <= '0;
|
||||
wcount <= '0;
|
||||
waddr_63_3 <= '0;
|
||||
end else begin
|
||||
case (wstate)
|
||||
W_IDLE :
|
||||
if (s_axi_awvalid) begin
|
||||
wstate <= W_BUSY;
|
||||
wid <= s_axi_awid;
|
||||
wcount <= s_axi_awlen;
|
||||
waddr_63_3 <= s_axi_awaddr[63:3];
|
||||
end
|
||||
W_BUSY :
|
||||
if (s_axi_wvalid) begin
|
||||
if (wcount == 8'd0 || s_axi_wlast)
|
||||
wstate <= W_RESP;
|
||||
wcount <= wcount - 8'd1;
|
||||
waddr_63_3 <= waddr_63_3 + 61'h1;
|
||||
end
|
||||
W_RESP :
|
||||
if (s_axi_bready)
|
||||
wstate <= W_IDLE;
|
||||
default :
|
||||
wstate <= W_IDLE;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
|
||||
function automatic logic [255:0] big_endian_to_little_endian_32B (input logic [255:0] din);
|
||||
logic [255:0] dout;
|
||||
for (int i=0; i<32; i++)
|
||||
dout[i*8 +: 8] = din[(31-i)*8 +: 8];
|
||||
return dout;
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// signals of the MPEG2 encoder
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
reg mpeg2_rstn = '0;
|
||||
|
||||
wire mpeg2_sequence_busy;
|
||||
reg mpeg2_sequence_stop = '0;
|
||||
|
||||
reg [ 6:0] mpeg2_xsize16 = '0;
|
||||
reg [ 6:0] mpeg2_ysize16 = '0;
|
||||
|
||||
reg mpeg2_i_en = '0;
|
||||
reg [ 7:0] mpeg2_i_Y0, mpeg2_i_Y1, mpeg2_i_Y2, mpeg2_i_Y3;
|
||||
reg [ 7:0] mpeg2_i_U0, mpeg2_i_U2 ;
|
||||
reg [ 7:0] mpeg2_i_V0, mpeg2_i_V2 ;
|
||||
|
||||
wire mpeg2_o_en;
|
||||
wire mpeg2_o_last;
|
||||
wire [255:0] mpeg2_o_data;
|
||||
|
||||
reg [ 15:0] mpeg2_o_addr = '0;
|
||||
reg mpeg2_o_over = '0; // 1: overflow !
|
||||
|
||||
|
||||
reg [255:0] out_buf ['h10000]; // out buffer : a block RAM to save the MPEG2 IP's out data, 32B * 0x10000 = 2 MB
|
||||
|
||||
reg [255:0] out_buf_rdata;
|
||||
|
||||
always @ (posedge clk)
|
||||
out_buf_rdata <= out_buf[ (16)'(raddr>>5) ]; // read BRAM
|
||||
|
||||
always @ (posedge clk)
|
||||
if ( mpeg2_o_en & ~mpeg2_o_over )
|
||||
out_buf[mpeg2_o_addr] <= big_endian_to_little_endian_32B(mpeg2_o_data);
|
||||
|
||||
|
||||
always_comb
|
||||
if ( raddr_r == 64'h00000000 ) // address = 0x00000000 : read status register (reset status and sequence status)
|
||||
s_axi_rdata = {61'h0, mpeg2_sequence_busy, 1'b0, mpeg2_rstn};
|
||||
else if ( raddr_r == 64'h00000008 ) // address = 0x00000008 : read status register (video frame size)
|
||||
s_axi_rdata = {25'h0, mpeg2_ysize16,
|
||||
25'h0, mpeg2_xsize16 };
|
||||
else if ( raddr_r == 64'h00000010 ) // address = 0x00000010 : read status register (out buffer status)
|
||||
s_axi_rdata = { 31'h0, mpeg2_o_over,
|
||||
11'h0, mpeg2_o_addr, 5'h0};
|
||||
else if ( raddr_r >= 64'h01000000 ) // address >= 0x01000000 : read out buffer (i.e. MPEG2 output stream)
|
||||
case( raddr_r[4:3] )
|
||||
2'b00 : s_axi_rdata = out_buf_rdata[ 63: 0];
|
||||
2'b01 : s_axi_rdata = out_buf_rdata[127: 64];
|
||||
2'b10 : s_axi_rdata = out_buf_rdata[191:128];
|
||||
2'b11 : s_axi_rdata = out_buf_rdata[255:192];
|
||||
endcase
|
||||
else
|
||||
s_axi_rdata = '0;
|
||||
|
||||
|
||||
always @ (posedge clk) begin
|
||||
mpeg2_sequence_stop <= 1'b0;
|
||||
mpeg2_i_en <= 1'b0;
|
||||
|
||||
if ( mpeg2_o_en ) begin
|
||||
if ( mpeg2_o_addr == '1 )
|
||||
mpeg2_o_over <= 1'b1;
|
||||
else
|
||||
mpeg2_o_addr <= mpeg2_o_addr + 16'h1;
|
||||
end
|
||||
|
||||
if ( s_axi_wvalid & s_axi_wready ) begin
|
||||
if ( waddr == 64'h00000000 ) begin // address = 0x00000000 : write reset control register (reset control and sequence control)
|
||||
mpeg2_rstn <= s_axi_wdata[0];
|
||||
mpeg2_sequence_stop <= s_axi_wdata[1];
|
||||
|
||||
end else if ( waddr == 64'h00000008 ) begin // address = 0x00000008 : write control register (video frame size)
|
||||
mpeg2_xsize16 <= s_axi_wdata[ 6: 0];
|
||||
mpeg2_ysize16 <= s_axi_wdata[38:32];
|
||||
|
||||
end else if ( waddr == 64'h00000010 ) begin // address = 0x00000010 : write control register (out buffer control)
|
||||
mpeg2_o_addr <= '0;
|
||||
mpeg2_o_over <= '0;
|
||||
|
||||
end else if ( waddr >= 64'h01000000 ) begin // address >= 0x01000000 : write video input data (i.e. raw YUV pixels)
|
||||
mpeg2_i_en <= 1'b1;
|
||||
{ mpeg2_i_V2, mpeg2_i_Y3, mpeg2_i_U2, mpeg2_i_Y2,
|
||||
mpeg2_i_V0, mpeg2_i_Y1, mpeg2_i_U0, mpeg2_i_Y0 } <= s_axi_wdata;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MPEG2 encoder instance
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
mpeg2encoder #(
|
||||
.XL ( 6 ), // determine the max horizontal pixel count. 4->256 pixels 5->512 pixels 6->1024 pixels 7->2048 pixels .
|
||||
.YL ( 6 ), // determine the max vertical pixel count. 4->256 pixels 5->512 pixels 6->1024 pixels 7->2048 pixels .
|
||||
.VECTOR_LEVEL ( 3 ),
|
||||
.Q_LEVEL ( 2 )
|
||||
) mpeg2encoder_i (
|
||||
.rstn ( mpeg2_rstn ),
|
||||
.clk ( clk ),
|
||||
// Video sequence configuration interface.
|
||||
.i_xsize16 ( mpeg2_xsize16 ),
|
||||
.i_ysize16 ( mpeg2_ysize16 ),
|
||||
.i_pframes_count ( 8'd47 ),
|
||||
// Video sequence input pixel stream interface. In each clock cycle, this interface can input 4 adjacent pixels in a row. Pixel format is YUV 4:4:4, the module will convert it to YUV 4:2:0, then compress it to MPEG2 stream.
|
||||
.i_en ( mpeg2_i_en ),
|
||||
.i_Y0 ( mpeg2_i_Y0 ),
|
||||
.i_Y1 ( mpeg2_i_Y1 ),
|
||||
.i_Y2 ( mpeg2_i_Y2 ),
|
||||
.i_Y3 ( mpeg2_i_Y3 ),
|
||||
.i_U0 ( mpeg2_i_U0 ),
|
||||
.i_U1 ( mpeg2_i_U0 ),
|
||||
.i_U2 ( mpeg2_i_U2 ),
|
||||
.i_U3 ( mpeg2_i_U2 ),
|
||||
.i_V0 ( mpeg2_i_V0 ),
|
||||
.i_V1 ( mpeg2_i_V0 ),
|
||||
.i_V2 ( mpeg2_i_V2 ),
|
||||
.i_V3 ( mpeg2_i_V2 ),
|
||||
// Video sequence control interface.
|
||||
.i_sequence_stop ( mpeg2_sequence_stop ),
|
||||
.o_sequence_busy ( mpeg2_sequence_busy ),
|
||||
// Video sequence output MPEG2 stream interface.
|
||||
.o_en ( mpeg2_o_en ),
|
||||
.o_last ( mpeg2_o_last ),
|
||||
.o_data ( mpeg2_o_data )
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -0,0 +1,214 @@
|
||||
|
||||
module fpga_top (
|
||||
output wire o_led0,
|
||||
input wire i_pcie_rstn,
|
||||
input wire i_pcie_refclkp, i_pcie_refclkn,
|
||||
input wire [0:0] i_pcie_rxp, i_pcie_rxn,
|
||||
output wire [0:0] o_pcie_txp, o_pcie_txn
|
||||
);
|
||||
|
||||
|
||||
localparam AXI_IDWIDTH = 4;
|
||||
localparam AXI_AWIDTH = 64;
|
||||
localparam AXI_DWIDTH = 64;
|
||||
|
||||
|
||||
wire pcie_rstn;
|
||||
wire pcie_refclk;
|
||||
|
||||
wire rstn;
|
||||
wire clk;
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PCIe XDMA's AXI interface
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
wire axi_awready;
|
||||
wire axi_awvalid;
|
||||
wire [ AXI_AWIDTH-1:0] axi_awaddr;
|
||||
wire [ 7:0] axi_awlen;
|
||||
wire [ AXI_IDWIDTH-1:0] axi_awid;
|
||||
// AXI Master Write Data Channel
|
||||
wire axi_wready;
|
||||
wire axi_wvalid;
|
||||
wire axi_wlast;
|
||||
wire [ AXI_DWIDTH-1:0] axi_wdata;
|
||||
// AXI Master Write Response Channel
|
||||
wire axi_bready;
|
||||
wire axi_bvalid;
|
||||
wire [ AXI_IDWIDTH-1:0] axi_bid;
|
||||
wire [ 1:0] axi_bresp;
|
||||
// AXI Master Read Address Channel
|
||||
wire axi_arready;
|
||||
wire axi_arvalid;
|
||||
wire [ AXI_AWIDTH-1:0] axi_araddr;
|
||||
wire [ 7:0] axi_arlen;
|
||||
wire [ AXI_IDWIDTH-1:0] axi_arid;
|
||||
// AXI Master Read Data Channel
|
||||
wire axi_rready;
|
||||
wire axi_rvalid;
|
||||
wire axi_rlast;
|
||||
wire [ AXI_DWIDTH-1:0] axi_rdata;
|
||||
wire [ AXI_IDWIDTH-1:0] axi_rid;
|
||||
wire [ 1:0] axi_rresp;
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Ref clock input buffer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
IBUFDS_GTE2 refclk_ibuf (
|
||||
.CEB ( 1'b0 ),
|
||||
.I ( i_pcie_refclkp ),
|
||||
.IB ( i_pcie_refclkn ),
|
||||
.O ( pcie_refclk ),
|
||||
.ODIV2 ( )
|
||||
);
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Reset input buffer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
IBUF sys_reset_n_ibuf (
|
||||
.I ( i_pcie_rstn ),
|
||||
.O ( pcie_rstn )
|
||||
);
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PCIe XDMA core
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
xdma_0 xdma_0_i (
|
||||
// PCI Express (PCIe) Interface : connect to the pins of FPGA chip
|
||||
.sys_rst_n ( pcie_rstn ),
|
||||
.sys_clk ( pcie_refclk ),
|
||||
.pci_exp_txn ( o_pcie_txn ),
|
||||
.pci_exp_txp ( o_pcie_txp ),
|
||||
.pci_exp_rxn ( i_pcie_rxn ),
|
||||
.pci_exp_rxp ( i_pcie_rxp ),
|
||||
// PCIe link up
|
||||
.user_lnk_up ( o_led0 ),
|
||||
// interrupts
|
||||
.usr_irq_req ( 16'h0 ),
|
||||
.usr_irq_ack ( ),
|
||||
//
|
||||
.msix_enable ( ),
|
||||
// clock/reset for user (for AXI)
|
||||
.axi_aclk ( clk ),
|
||||
.axi_aresetn ( rstn ),
|
||||
// AXI Interface
|
||||
.m_axi_awready ( axi_awready ),
|
||||
.m_axi_awvalid ( axi_awvalid ),
|
||||
.m_axi_awaddr ( axi_awaddr ),
|
||||
.m_axi_awlen ( axi_awlen ),
|
||||
.m_axi_awid ( axi_awid ),
|
||||
.m_axi_awsize ( ),
|
||||
.m_axi_awburst ( ),
|
||||
.m_axi_awprot ( ),
|
||||
.m_axi_awlock ( ),
|
||||
.m_axi_awcache ( ),
|
||||
.m_axi_wready ( axi_wready ),
|
||||
.m_axi_wvalid ( axi_wvalid ),
|
||||
.m_axi_wlast ( axi_wlast ),
|
||||
.m_axi_wdata ( axi_wdata ),
|
||||
.m_axi_wstrb ( ),
|
||||
.m_axi_bready ( axi_bready ),
|
||||
.m_axi_bvalid ( axi_bvalid ),
|
||||
.m_axi_bid ( axi_bid ),
|
||||
.m_axi_bresp ( axi_bresp ),
|
||||
.m_axi_arready ( axi_arready ),
|
||||
.m_axi_arvalid ( axi_arvalid ),
|
||||
.m_axi_araddr ( axi_araddr ),
|
||||
.m_axi_arlen ( axi_arlen ),
|
||||
.m_axi_arid ( axi_arid ),
|
||||
.m_axi_arsize ( ),
|
||||
.m_axi_arburst ( ),
|
||||
.m_axi_arprot ( ),
|
||||
.m_axi_arlock ( ),
|
||||
.m_axi_arcache ( ),
|
||||
.m_axi_rready ( axi_rready ),
|
||||
.m_axi_rvalid ( axi_rvalid ),
|
||||
.m_axi_rlast ( axi_rlast ),
|
||||
.m_axi_rdata ( axi_rdata ),
|
||||
.m_axi_rid ( axi_rid ),
|
||||
.m_axi_rresp ( axi_rresp ),
|
||||
// AXI bypass interface
|
||||
.m_axib_awready ( '0 ),
|
||||
.m_axib_awvalid ( ),
|
||||
.m_axib_awaddr ( ),
|
||||
.m_axib_awlen ( ),
|
||||
.m_axib_awid ( ),
|
||||
.m_axib_awsize ( ),
|
||||
.m_axib_awburst ( ),
|
||||
.m_axib_awprot ( ),
|
||||
.m_axib_awlock ( ),
|
||||
.m_axib_awcache ( ),
|
||||
.m_axib_wready ( '0 ),
|
||||
.m_axib_wvalid ( ),
|
||||
.m_axib_wlast ( ),
|
||||
.m_axib_wdata ( ),
|
||||
.m_axib_wstrb ( ),
|
||||
.m_axib_bready ( ),
|
||||
.m_axib_bvalid ( '0 ),
|
||||
.m_axib_bid ( '0 ),
|
||||
.m_axib_bresp ( '0 ),
|
||||
.m_axib_arready ( '0 ),
|
||||
.m_axib_arvalid ( ),
|
||||
.m_axib_araddr ( ),
|
||||
.m_axib_arlen ( ),
|
||||
.m_axib_arid ( ),
|
||||
.m_axib_arsize ( ),
|
||||
.m_axib_arburst ( ),
|
||||
.m_axib_arprot ( ),
|
||||
.m_axib_arlock ( ),
|
||||
.m_axib_arcache ( ),
|
||||
.m_axib_rready ( ),
|
||||
.m_axib_rvalid ( '0 ),
|
||||
.m_axib_rlast ( '0 ),
|
||||
.m_axib_rdata ( '0 ),
|
||||
.m_axib_rid ( '0 ),
|
||||
.m_axib_rresp ( '0 )
|
||||
);
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// AXI BRAM connected to PCIe XDMA's AXI interface
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
axi_mpeg2encoder_wrapper #(
|
||||
.AXI_IDWIDTH ( AXI_IDWIDTH )
|
||||
) axi_axi_mpeg2encoder_wrapper_i (
|
||||
.rstn ( rstn ),
|
||||
.clk ( clk ),
|
||||
// AXI Memory Mapped interface
|
||||
.s_axi_awready ( axi_awready ),
|
||||
.s_axi_awvalid ( axi_awvalid ),
|
||||
.s_axi_awaddr ( axi_awaddr ),
|
||||
.s_axi_awlen ( axi_awlen ),
|
||||
.s_axi_awid ( axi_awid ),
|
||||
.s_axi_wready ( axi_wready ),
|
||||
.s_axi_wvalid ( axi_wvalid ),
|
||||
.s_axi_wlast ( axi_wlast ),
|
||||
.s_axi_wdata ( axi_wdata ),
|
||||
.s_axi_bready ( axi_bready ),
|
||||
.s_axi_bvalid ( axi_bvalid ),
|
||||
.s_axi_bid ( axi_bid ),
|
||||
.s_axi_bresp ( axi_bresp ),
|
||||
.s_axi_arready ( axi_arready ),
|
||||
.s_axi_arvalid ( axi_arvalid ),
|
||||
.s_axi_araddr ( axi_araddr ),
|
||||
.s_axi_arlen ( axi_arlen ),
|
||||
.s_axi_arid ( axi_arid ),
|
||||
.s_axi_rready ( axi_rready ),
|
||||
.s_axi_rvalid ( axi_rvalid ),
|
||||
.s_axi_rlast ( axi_rlast ),
|
||||
.s_axi_rdata ( axi_rdata ),
|
||||
.s_axi_rid ( axi_rid ),
|
||||
.s_axi_rresp ( axi_rresp )
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,372 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/timeb.h>
|
||||
|
||||
|
||||
|
||||
|
||||
// function : dev_read
|
||||
// description : read data from device to local memory (buffer), (i.e. device-to-host)
|
||||
// parameter :
|
||||
// dev_fd : device instance
|
||||
// addr : source address in the device
|
||||
// buffer : buffer base pointer
|
||||
// size : data size
|
||||
// return:
|
||||
// int : 0=success, -1=failed
|
||||
int dev_read (int dev_fd, uint64_t addr, void *buffer, uint64_t size) {
|
||||
if ( addr != lseek(dev_fd, addr, SEEK_SET) ) // seek
|
||||
return -1; // seek failed
|
||||
if ( size != read(dev_fd, buffer, size) ) // read device to buffer
|
||||
return -1; // read failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// function : dev_write
|
||||
// description : write data from local memory (buffer) to device, (i.e. host-to-device)
|
||||
// parameter :
|
||||
// dev_fd : device instance
|
||||
// addr : target address in the device
|
||||
// buffer : buffer base pointer
|
||||
// size : data size
|
||||
// return:
|
||||
// int : 0=success, -1=failed
|
||||
int dev_write (int dev_fd, uint64_t addr, void *buffer, uint64_t size) {
|
||||
if ( addr != lseek(dev_fd, addr, SEEK_SET) ) // seek
|
||||
return -1; // seek failed
|
||||
if ( size != write(dev_fd, buffer, size) ) // write device from buffer
|
||||
return -1; // write failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// function : dev_read_uint64
|
||||
// description : read a uint64 value (8 bytes) from device to local, (i.e. device-to-host)
|
||||
// parameter :
|
||||
// dev_fd : device instance
|
||||
// addr : source address in the device
|
||||
// p_value : uint64 value's pointer
|
||||
// return:
|
||||
// int : 0=success, -1=failed
|
||||
int dev_read_uint64 (int dev_fd, uint64_t addr, uint64_t *p_value) {
|
||||
return dev_read(dev_fd, addr, (void*)p_value, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
|
||||
// function : dev_write_uint64
|
||||
// description : write a uint64 value (8 bytes) from to device, (i.e. host-to-device)
|
||||
// parameter :
|
||||
// dev_fd : device instance
|
||||
// addr : target address in the device
|
||||
// value : uint64 value to write
|
||||
// return:
|
||||
// int : 0=success, -1=failed
|
||||
int dev_write_uint64 (int dev_fd, uint64_t addr, uint64_t value) {
|
||||
return dev_write(dev_fd, addr, (void*)&value, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// mpeg2encoder device's address map --------------------------------------------------------------------------------
|
||||
#define ADDR_RESET_AND_SEQUENCE_CONTROL 0x00000000UL
|
||||
#define ADDR_VIDEO_FRAME_SIZE 0x00000008UL
|
||||
#define ADDR_OUT_BUF_CONTROL 0x00000010UL
|
||||
#define ADDR_BASE_IN_PIXELS 0x01000000UL
|
||||
#define ADDR_BASE_OUT_BUF 0x01000000UL
|
||||
|
||||
|
||||
// function : mpeg2encoder_reset
|
||||
// description : reset the mpeg2encoder in the device
|
||||
// return:
|
||||
// int : 0=success, -1=failed
|
||||
int mpeg2encoder_reset (int dev_w_fd) {
|
||||
if ( dev_write_uint64(dev_w_fd, ADDR_RESET_AND_SEQUENCE_CONTROL, 0x0) ) // reset
|
||||
return -1;
|
||||
return dev_write_uint64(dev_w_fd, ADDR_RESET_AND_SEQUENCE_CONTROL, 0x1) ; // reset release
|
||||
}
|
||||
|
||||
|
||||
// function : mpeg2encoder_set_sequence_stop
|
||||
// description : send a "sequence stop" signal to the device, which indicate this is the end of a video sequence
|
||||
// return:
|
||||
// int : 0=success, -1=failed
|
||||
int mpeg2encoder_set_sequence_stop (int dev_w_fd) {
|
||||
return dev_write_uint64(dev_w_fd, ADDR_RESET_AND_SEQUENCE_CONTROL, 0x3) ; // sequence stop, note that the lowest bit is set to 1 to keep the reset released
|
||||
}
|
||||
|
||||
|
||||
// function : mpeg2encoder_set_video_frame_size
|
||||
// description : set the frame width and height of the video sequence to be encoded
|
||||
// parameter :
|
||||
// xsize16 : frame width / 16 . e.g. for width = 640, xsize16 = 40
|
||||
// ysize16 : frame height / 16 . e.g. for height = 480, ysize16 = 30
|
||||
// return:
|
||||
// int : 0=success, -1=failed
|
||||
int mpeg2encoder_set_video_frame_size (int dev_w_fd, int xsize16, int ysize16) {
|
||||
uint64_t reg_value;
|
||||
reg_value = ysize16;
|
||||
reg_value <<= 32;
|
||||
reg_value |= xsize16;
|
||||
return dev_write_uint64(dev_w_fd, ADDR_VIDEO_FRAME_SIZE, reg_value);
|
||||
}
|
||||
|
||||
|
||||
// function : mpeg2encoder_put_pixels
|
||||
// description : put raw YUV pixels to the device, which will be encoded to the MPEG2 stream
|
||||
// return:
|
||||
// int : 0=success, -1=failed
|
||||
int mpeg2encoder_put_pixels (int dev_w_fd, void *buffer, uint64_t size) {
|
||||
return dev_write(dev_w_fd, ADDR_BASE_IN_PIXELS, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
// function : mpeg2encoder_get_outbuf
|
||||
// description : get data (encoded MPEG2 stream) from the out buffer of the device
|
||||
// return:
|
||||
// int : 0=success, -1=failed
|
||||
int mpeg2encoder_get_outbuf (int dev_r_fd, int dev_w_fd, void *buffer, int *p_size, int *p_overflow) { // buffer must have 0x200000 (2MB) space at least
|
||||
int offset = 0;
|
||||
|
||||
for (;;) {
|
||||
do { // wait until outbuf not empty
|
||||
uint64_t reg_value;
|
||||
if ( dev_read_uint64(dev_r_fd, ADDR_OUT_BUF_CONTROL, ®_value) )
|
||||
return -1;
|
||||
*p_size = reg_value & 0x7ffffff;
|
||||
*p_overflow = ((reg_value >> 32) & 1);
|
||||
} while (*p_size <= 0) ;
|
||||
|
||||
if (offset >= *p_size) // no more available data in out buffer
|
||||
break;
|
||||
|
||||
if ( dev_read(dev_r_fd, ADDR_BASE_OUT_BUF+offset, (void*)((char*)buffer+offset), *p_size-offset ) )
|
||||
return -1;
|
||||
|
||||
offset = *p_size;
|
||||
}
|
||||
|
||||
return dev_write_uint64(dev_w_fd, ADDR_OUT_BUF_CONTROL, 0UL); // clear the out buffer
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// function : get_millisecond
|
||||
// description : get time in millisecond
|
||||
uint64_t get_millisecond () {
|
||||
struct timeb tb;
|
||||
ftime(&tb);
|
||||
return (uint64_t)tb.millitm + (uint64_t)tb.time * 1000UL;
|
||||
// tb.time is the number of seconds since 00:00:00 January 1, 1970 UTC time;
|
||||
// tb.millitm is the number of milliseconds in a second
|
||||
}
|
||||
|
||||
|
||||
|
||||
// function : parse_int
|
||||
// description : get a int value from string (support hexadecimal and decimal)
|
||||
int parse_int (char *string, int *pvalue) {
|
||||
if ( string[0] == '0' && string[1] == 'x' ) // HEX format "0xXXXXXXXX"
|
||||
return sscanf( &(string[2]), "%x", pvalue);
|
||||
else // DEC format
|
||||
return sscanf( string , "%d", pvalue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char USAGE [] =
|
||||
"Usage: \n"
|
||||
" %s <dev_r_name> <dev_w_name> <in_file_name> <out_file_name> <video_frame_width> <video_frame_height>\n"
|
||||
"\n"
|
||||
"Where:\n"
|
||||
" in_file_name : .yuv file which contains the raw YUV pixels of a video,\n"
|
||||
" must be in YUYV format (a type of YUV 4:2:2 packed format)\n"
|
||||
" out_file_name : .m2v file which contains the MPEG2 stream,\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
" %s /dev/xdma0_c2h_0 /dev/xdma0_h2c_0 in.yuv out.m2v 640 480\n"
|
||||
"\n" ;
|
||||
|
||||
|
||||
|
||||
// video frame size limitations (limited by the device) -----------------------------------------------------------------
|
||||
#define VIDEO_FRAME_XSIZE16_MIN 4 // min frame width = 4 * 16 = 64
|
||||
#define VIDEO_FRAME_XSIZE16_MAX 64 // max frame width = 4 * 64 = 1024
|
||||
#define VIDEO_FRAME_YSIZE16_MIN 4 // min frame height = 4 * 16 = 64
|
||||
#define VIDEO_FRAME_YSIZE16_MAX 64 // max frame height = 4 * 64 = 1024
|
||||
|
||||
|
||||
|
||||
#define IN_BUF_SIZE 0x200000
|
||||
#define OUT_BUF_SIZE 0x200000
|
||||
|
||||
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
|
||||
static char in_buffer [IN_BUF_SIZE]; // this buffer is for the RAW pixels which is to send to the device
|
||||
static char out_buffer [OUT_BUF_SIZE]; // this buffer is for the MPEG2 stream get from the device
|
||||
|
||||
int ret = -1;
|
||||
uint64_t millisecond;
|
||||
char usage_string [1024];
|
||||
|
||||
char *dev_r_name, *dev_w_name, *in_file_name, *out_file_name;
|
||||
int xsize, ysize;
|
||||
|
||||
int dev_r_fd = -1, dev_w_fd = -1;
|
||||
|
||||
FILE *in_fp = NULL, *out_fp = NULL;
|
||||
|
||||
|
||||
sprintf(usage_string, USAGE, argv[0], argv[0] );
|
||||
|
||||
if (argc < 7) { // not enough argument
|
||||
puts(usage_string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
dev_r_name = argv[1];
|
||||
dev_w_name = argv[2];
|
||||
in_file_name = argv[3];
|
||||
out_file_name = argv[4];
|
||||
|
||||
if ( 0 == parse_int(argv[5], &xsize) ) { // parse video width (xsize) from command line argument
|
||||
puts(usage_string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( 0 == parse_int(argv[6], &ysize) ) { // parse video height (ysize) from command line argument
|
||||
puts(usage_string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// print information -----------------------------------
|
||||
printf("device : %s %s\n" , dev_r_name, dev_w_name);
|
||||
printf("input yuv file : %s\n" , in_file_name);
|
||||
printf("output m2v file : %s\n" , out_file_name);
|
||||
printf("video size : %d x %d\n" , xsize, ysize );
|
||||
|
||||
// check video frame size -----------------------------------
|
||||
if ( xsize % 16 != 0 ) {
|
||||
printf("*** ERROR: xsize must be multiple of 16\n");
|
||||
return -1;
|
||||
}
|
||||
if ( ysize % 16 != 0 ) {
|
||||
printf("*** ERROR: ysize must be multiple of 16\n");
|
||||
return -1;
|
||||
}
|
||||
if ( xsize < 16*VIDEO_FRAME_XSIZE16_MIN || xsize > 16*VIDEO_FRAME_XSIZE16_MAX ) {
|
||||
printf("*** ERROR: xsize must not smaller than %d or larger than %d", 16*VIDEO_FRAME_XSIZE16_MIN, 16*VIDEO_FRAME_XSIZE16_MAX);
|
||||
return -1;
|
||||
}
|
||||
if ( ysize < 16*VIDEO_FRAME_YSIZE16_MIN || ysize > 16*VIDEO_FRAME_YSIZE16_MAX ) {
|
||||
printf("*** ERROR: ysize must not smaller than %d or larger than %d", 16*VIDEO_FRAME_YSIZE16_MIN, 16*VIDEO_FRAME_YSIZE16_MAX);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
dev_r_fd = open(dev_r_name, O_RDWR); // open device
|
||||
if (dev_r_fd < 0) {
|
||||
printf("*** ERROR: failed to open device %s\n", dev_r_name);
|
||||
goto close_and_clear;
|
||||
}
|
||||
|
||||
dev_w_fd = open(dev_w_name, O_RDWR); // open device
|
||||
if (dev_w_fd < 0) {
|
||||
printf("*** ERROR: failed to open device %s\n", dev_w_name);
|
||||
goto close_and_clear;
|
||||
}
|
||||
|
||||
in_fp = fopen(in_file_name, "rb"); // open file for read
|
||||
if (in_fp == NULL) {
|
||||
printf("*** ERROR: failed to open file %s for read\n", in_file_name);
|
||||
goto close_and_clear;
|
||||
}
|
||||
|
||||
out_fp = fopen(out_file_name, "wb"); // open file for write
|
||||
if (out_fp == NULL) {
|
||||
printf("*** ERROR: failed to open file %s for write\n", out_file_name);
|
||||
goto close_and_clear;
|
||||
}
|
||||
|
||||
|
||||
millisecond = get_millisecond(); // get start time
|
||||
|
||||
if ( mpeg2encoder_reset(dev_w_fd) ) { // reset the mpeg2encoder device
|
||||
printf("*** ERROR: failed to reset device\n");
|
||||
goto close_and_clear;
|
||||
}
|
||||
|
||||
if ( mpeg2encoder_set_video_frame_size(dev_w_fd, xsize/16, ysize/16) ) { // set video frame size
|
||||
printf("*** ERROR: failed to set video frame size\n");
|
||||
goto close_and_clear;
|
||||
}
|
||||
|
||||
do {
|
||||
int in_len, out_len, out_overflow;
|
||||
|
||||
in_len = fread((void*)in_buffer, 1, IN_BUF_SIZE, in_fp); // file -> in_buffer (raw YUV pixels)
|
||||
|
||||
if ( mpeg2encoder_put_pixels(dev_w_fd, (void*)in_buffer, in_len) ) { // in_buffer -> device (raw YUV pixels)
|
||||
printf("*** ERROR: failed to put pixels\n");
|
||||
goto close_and_clear;
|
||||
}
|
||||
|
||||
if ( feof(in_fp) ) // if input file is ended, send "video sequence stop" signal
|
||||
if ( mpeg2encoder_set_sequence_stop(dev_w_fd) ) {
|
||||
printf("*** ERROR: failed to set sequence stop\n");
|
||||
goto close_and_clear;
|
||||
}
|
||||
|
||||
if ( mpeg2encoder_get_outbuf (dev_r_fd, dev_w_fd, (void*)out_buffer, &out_len, &out_overflow) ) { // device -> out_buffer (MPEG2 stream)
|
||||
printf("*** ERROR: failed to get data from device\n");
|
||||
goto close_and_clear;
|
||||
}
|
||||
|
||||
if ( out_overflow )
|
||||
printf("*** WARNING: device's out buffer overflow, out data stream is partly corrupted\n");
|
||||
|
||||
if ( out_len != fwrite((void*)out_buffer, 1, out_len, out_fp) ) { // out_buffer -> file (MPEG2 stream)
|
||||
printf("*** ERROR: failed to write %s\n", out_file_name);
|
||||
goto close_and_clear;
|
||||
}
|
||||
|
||||
} while ( ! feof(in_fp) ) ;
|
||||
|
||||
millisecond = get_millisecond() - millisecond; // get time consumption
|
||||
millisecond = (millisecond > 0) ? millisecond : 1; // avoid divide-by-zero
|
||||
|
||||
printf("input size = %ld\n", ftell(in_fp) );
|
||||
printf("output size = %ld\n", ftell(out_fp) );
|
||||
printf("compression ratio = %.1lf\n", (double) ftell(in_fp) / (ftell(out_fp) + 1) );
|
||||
printf("time=%lu ms input throughput = %.1lf KBps\n", millisecond, (double) ftell(in_fp) / millisecond );
|
||||
|
||||
ret = 0;
|
||||
|
||||
close_and_clear:
|
||||
|
||||
if (dev_r_fd >= 0)
|
||||
close(dev_r_fd);
|
||||
|
||||
if (dev_w_fd >= 0)
|
||||
close(dev_r_fd);
|
||||
|
||||
if (in_fp)
|
||||
fclose(in_fp);
|
||||
|
||||
if (out_fp)
|
||||
fclose(out_fp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue