axi_hdmi_tx: Update to use ADI DMA
The frame synchronization between axi_hdmi_tx and axi_dmac is based on the DMA(2D streaming) last signal. The last signal will be used as an end of frame signal marking the beginning of the future frame to be transferred by the DMA. Only after both HDMI and DMA are ready for a "new frame" data will be requested from the DMA. The datarate and CDC between the axi_dmac and axi_hdmi_tx cores will be handled by axi_hdmi_tx's DMA interface based on a backpressure mechanism.main
parent
6fb250ad89
commit
e607471898
|
@ -71,8 +71,7 @@ module axi_hdmi_tx #(
|
||||||
// vdma interface
|
// vdma interface
|
||||||
|
|
||||||
input vdma_clk,
|
input vdma_clk,
|
||||||
output vdma_fs,
|
input vdma_end_of_frame,
|
||||||
input vdma_fs_ret,
|
|
||||||
input vdma_valid,
|
input vdma_valid,
|
||||||
input [63:0] vdma_data,
|
input [63:0] vdma_data,
|
||||||
output vdma_ready,
|
output vdma_ready,
|
||||||
|
@ -237,11 +236,10 @@ module axi_hdmi_tx #(
|
||||||
.hdmi_raddr_g (hdmi_raddr_g_s),
|
.hdmi_raddr_g (hdmi_raddr_g_s),
|
||||||
.vdma_clk (vdma_clk),
|
.vdma_clk (vdma_clk),
|
||||||
.vdma_rst (vdma_rst),
|
.vdma_rst (vdma_rst),
|
||||||
.vdma_fs (vdma_fs),
|
|
||||||
.vdma_fs_ret (vdma_fs_ret),
|
|
||||||
.vdma_valid (vdma_valid),
|
.vdma_valid (vdma_valid),
|
||||||
.vdma_data (vdma_data),
|
.vdma_data (vdma_data),
|
||||||
.vdma_ready (vdma_ready),
|
.vdma_ready (vdma_ready),
|
||||||
|
.vdma_end_of_frame (vdma_end_of_frame),
|
||||||
.vdma_wr (vdma_wr_s),
|
.vdma_wr (vdma_wr_s),
|
||||||
.vdma_waddr (vdma_waddr_s),
|
.vdma_waddr (vdma_waddr_s),
|
||||||
.vdma_wdata (vdma_wdata_s),
|
.vdma_wdata (vdma_wdata_s),
|
||||||
|
|
|
@ -244,6 +244,10 @@ module axi_hdmi_tx_core #(
|
||||||
// hdmi start of frame
|
// hdmi start of frame
|
||||||
|
|
||||||
always @(posedge hdmi_clk) begin
|
always @(posedge hdmi_clk) begin
|
||||||
|
if (hdmi_rst == 1'b1) begin
|
||||||
|
hdmi_fs_toggle <= 1'b0;
|
||||||
|
hdmi_fs <= 1'b0;
|
||||||
|
end else begin
|
||||||
if (EMBEDDED_SYNC == 1) begin
|
if (EMBEDDED_SYNC == 1) begin
|
||||||
if ((hdmi_hs_count == 1) && (hdmi_vs_count == hdmi_ve_width_s)) begin
|
if ((hdmi_hs_count == 1) && (hdmi_vs_count == hdmi_ve_width_s)) begin
|
||||||
hdmi_fs <= hdmi_enable;
|
hdmi_fs <= hdmi_enable;
|
||||||
|
@ -261,6 +265,7 @@ module axi_hdmi_tx_core #(
|
||||||
hdmi_fs_toggle <= ~hdmi_fs_toggle;
|
hdmi_fs_toggle <= ~hdmi_fs_toggle;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
// hdmi sof write address
|
// hdmi sof write address
|
||||||
|
|
||||||
|
@ -280,10 +285,8 @@ module axi_hdmi_tx_core #(
|
||||||
|
|
||||||
always @(posedge hdmi_clk) begin
|
always @(posedge hdmi_clk) begin
|
||||||
hdmi_fs_ret <= hdmi_fs_ret_s;
|
hdmi_fs_ret <= hdmi_fs_ret_s;
|
||||||
if (hdmi_fs_ret_s == 1'b1) begin
|
|
||||||
hdmi_fs_waddr <= vdma_fs_waddr;
|
hdmi_fs_waddr <= vdma_fs_waddr;
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
// hdmi sync signals
|
// hdmi sync signals
|
||||||
|
|
||||||
|
@ -332,7 +335,7 @@ module axi_hdmi_tx_core #(
|
||||||
always @(posedge hdmi_clk) begin
|
always @(posedge hdmi_clk) begin
|
||||||
if (hdmi_rst == 1'b1) begin
|
if (hdmi_rst == 1'b1) begin
|
||||||
hdmi_raddr <= 10'd0;
|
hdmi_raddr <= 10'd0;
|
||||||
end else if (hdmi_fs_ret == 1'b1) begin
|
end else if (hdmi_fs == 1'b1) begin
|
||||||
hdmi_raddr <= {hdmi_fs_waddr, 1'b0};
|
hdmi_raddr <= {hdmi_fs_waddr, 1'b0};
|
||||||
end else if (hdmi_de_s == 1'b1) begin
|
end else if (hdmi_de_s == 1'b1) begin
|
||||||
hdmi_raddr <= hdmi_raddr + 1'b1;
|
hdmi_raddr <= hdmi_raddr + 1'b1;
|
||||||
|
|
|
@ -35,7 +35,7 @@ set_property driver_value 0 [ipx::get_ports *vsync* -of_objects [ipx::current_co
|
||||||
set_property driver_value 0 [ipx::get_ports *data* -of_objects [ipx::current_core]]
|
set_property driver_value 0 [ipx::get_ports *data* -of_objects [ipx::current_core]]
|
||||||
set_property driver_value 0 [ipx::get_ports *es_data* -of_objects [ipx::current_core]]
|
set_property driver_value 0 [ipx::get_ports *es_data* -of_objects [ipx::current_core]]
|
||||||
|
|
||||||
set_property driver_value 0 [ipx::get_ports *vdma_fs* -of_objects [ipx::current_core]]
|
set_property driver_value 0 [ipx::get_ports *vdma_end_of_frame* -of_objects [ipx::current_core]]
|
||||||
set_property driver_value 0 [ipx::get_ports *vdma_valid* -of_objects [ipx::current_core]]
|
set_property driver_value 0 [ipx::get_ports *vdma_valid* -of_objects [ipx::current_core]]
|
||||||
set_property driver_value 0 [ipx::get_ports *vdma_data* -of_objects [ipx::current_core]]
|
set_property driver_value 0 [ipx::get_ports *vdma_data* -of_objects [ipx::current_core]]
|
||||||
set_property driver_value 0 [ipx::get_ports *vdma_ready* -of_objects [ipx::current_core]]
|
set_property driver_value 0 [ipx::get_ports *vdma_ready* -of_objects [ipx::current_core]]
|
||||||
|
|
|
@ -45,8 +45,7 @@ module axi_hdmi_tx_vdma (
|
||||||
|
|
||||||
input vdma_clk,
|
input vdma_clk,
|
||||||
input vdma_rst,
|
input vdma_rst,
|
||||||
output reg vdma_fs,
|
input vdma_end_of_frame,
|
||||||
input vdma_fs_ret,
|
|
||||||
input vdma_valid,
|
input vdma_valid,
|
||||||
input [63:0] vdma_data,
|
input [63:0] vdma_data,
|
||||||
output reg vdma_ready,
|
output reg vdma_ready,
|
||||||
|
@ -66,16 +65,20 @@ module axi_hdmi_tx_vdma (
|
||||||
|
|
||||||
// internal registers
|
// internal registers
|
||||||
|
|
||||||
reg vdma_fs_toggle_m1 = 'd0;
|
reg vdma_fs_toggle_m1 = 1'd0;
|
||||||
reg vdma_fs_toggle_m2 = 'd0;
|
reg vdma_fs_toggle_m2 = 1'd0;
|
||||||
reg vdma_fs_toggle_m3 = 'd0;
|
reg vdma_fs_toggle_m3 = 1'd0;
|
||||||
reg [22:0] vdma_tpm_data = 'd0;
|
reg [22:0] vdma_tpm_data = 23'd0;
|
||||||
reg [ 8:0] vdma_raddr_g_m1 = 'd0;
|
reg [ 8:0] vdma_raddr_g_m1 = 9'd0;
|
||||||
reg [ 8:0] vdma_raddr_g_m2 = 'd0;
|
reg [ 8:0] vdma_raddr_g_m2 = 9'd0;
|
||||||
reg [ 8:0] vdma_raddr = 'd0;
|
reg [ 8:0] vdma_raddr = 9'd0;
|
||||||
reg [ 8:0] vdma_addr_diff = 'd0;
|
reg [ 8:0] vdma_addr_diff = 9'd0;
|
||||||
reg vdma_almost_full = 'd0;
|
reg vdma_almost_full = 1'd0;
|
||||||
reg vdma_almost_empty = 'd0;
|
reg vdma_almost_empty = 1'd0;
|
||||||
|
reg hdmi_fs = 1'd0;
|
||||||
|
reg vdma_fs = 1'd0;
|
||||||
|
reg vdma_end_of_frame_d = 1'd0;
|
||||||
|
reg vdma_active_frame = 1'd0;
|
||||||
|
|
||||||
// internal wires
|
// internal wires
|
||||||
|
|
||||||
|
@ -104,7 +107,7 @@ module axi_hdmi_tx_vdma (
|
||||||
end
|
end
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
// get fs from hdmi side, return fs and sof write address back
|
// hdmi frame sync
|
||||||
|
|
||||||
always @(posedge vdma_clk or posedge vdma_rst) begin
|
always @(posedge vdma_clk or posedge vdma_rst) begin
|
||||||
if (vdma_rst == 1'b1) begin
|
if (vdma_rst == 1'b1) begin
|
||||||
|
@ -116,13 +119,46 @@ module axi_hdmi_tx_vdma (
|
||||||
vdma_fs_toggle_m2 <= vdma_fs_toggle_m1;
|
vdma_fs_toggle_m2 <= vdma_fs_toggle_m1;
|
||||||
vdma_fs_toggle_m3 <= vdma_fs_toggle_m2;
|
vdma_fs_toggle_m3 <= vdma_fs_toggle_m2;
|
||||||
end
|
end
|
||||||
|
hdmi_fs <= vdma_fs_toggle_m2 ^ vdma_fs_toggle_m3;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// dma frame sync
|
||||||
|
|
||||||
|
always @(posedge vdma_clk or posedge vdma_rst) begin
|
||||||
|
if (vdma_rst == 1'b1) begin
|
||||||
|
vdma_end_of_frame_d <= 1'b0;
|
||||||
|
vdma_fs <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
vdma_end_of_frame_d <= vdma_end_of_frame;
|
||||||
|
vdma_fs <= vdma_end_of_frame_d;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// sync dma and hdmi frames
|
||||||
|
|
||||||
always @(posedge vdma_clk) begin
|
always @(posedge vdma_clk) begin
|
||||||
vdma_fs <= vdma_fs_toggle_m2 ^ vdma_fs_toggle_m3;
|
if (vdma_rst == 1'b1) begin
|
||||||
if (vdma_fs_ret == 1'b1) begin
|
vdma_fs_ret_toggle = 1'b0;
|
||||||
vdma_fs_waddr <= vdma_waddr;
|
vdma_fs_waddr <= 9'b0;
|
||||||
|
end else begin
|
||||||
|
if (vdma_fs) begin
|
||||||
vdma_fs_ret_toggle <= ~vdma_fs_ret_toggle;
|
vdma_fs_ret_toggle <= ~vdma_fs_ret_toggle;
|
||||||
|
vdma_fs_waddr <= vdma_waddr ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// accept new frame from dma
|
||||||
|
|
||||||
|
always @(posedge vdma_clk) begin
|
||||||
|
if (vdma_rst == 1'b1) begin
|
||||||
|
vdma_active_frame <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if ((vdma_active_frame == 1'b1) && (vdma_end_of_frame == 1'b1)) begin
|
||||||
|
vdma_active_frame <= 1'b0;
|
||||||
|
end else if ((vdma_active_frame == 1'b0) && (hdmi_fs == 1'b1)) begin
|
||||||
|
vdma_active_frame <= 1'b1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -144,7 +180,7 @@ module axi_hdmi_tx_vdma (
|
||||||
assign vdma_tpm_oos_s = (vdma_wdata == vdma_tpm_data_s) ? 1'b0 : vdma_wr;
|
assign vdma_tpm_oos_s = (vdma_wdata == vdma_tpm_data_s) ? 1'b0 : vdma_wr;
|
||||||
|
|
||||||
always @(posedge vdma_clk) begin
|
always @(posedge vdma_clk) begin
|
||||||
if ((vdma_rst == 1'b1) || (vdma_fs_ret == 1'b1)) begin
|
if ((vdma_rst == 1'b1) || (vdma_fs == 1'b1)) begin
|
||||||
vdma_tpm_data <= 23'd0;
|
vdma_tpm_data <= 23'd0;
|
||||||
vdma_tpm_oos <= 1'd0;
|
vdma_tpm_oos <= 1'd0;
|
||||||
end else if (vdma_wr == 1'b1) begin
|
end else if (vdma_wr == 1'b1) begin
|
||||||
|
@ -175,7 +211,7 @@ module axi_hdmi_tx_vdma (
|
||||||
if (vdma_addr_diff >= RDY_THRESHOLD_HI) begin
|
if (vdma_addr_diff >= RDY_THRESHOLD_HI) begin
|
||||||
vdma_ready <= 1'b0;
|
vdma_ready <= 1'b0;
|
||||||
end else if (vdma_addr_diff <= RDY_THRESHOLD_LO) begin
|
end else if (vdma_addr_diff <= RDY_THRESHOLD_LO) begin
|
||||||
vdma_ready <= 1'b1;
|
vdma_ready <= vdma_active_frame;
|
||||||
end
|
end
|
||||||
if (vdma_addr_diff > BUF_THRESHOLD_HI) begin
|
if (vdma_addr_diff > BUF_THRESHOLD_HI) begin
|
||||||
vdma_almost_full <= 1'b1;
|
vdma_almost_full <= 1'b1;
|
||||||
|
|
Loading…
Reference in New Issue