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
AndreiGrozav 2018-05-11 18:00:15 +03:00 committed by AndreiGrozav
parent 6fb250ad89
commit e607471898
4 changed files with 77 additions and 40 deletions

View File

@ -71,8 +71,7 @@ module axi_hdmi_tx #(
// vdma interface
input vdma_clk,
output vdma_fs,
input vdma_fs_ret,
input vdma_end_of_frame,
input vdma_valid,
input [63:0] vdma_data,
output vdma_ready,
@ -237,11 +236,10 @@ module axi_hdmi_tx #(
.hdmi_raddr_g (hdmi_raddr_g_s),
.vdma_clk (vdma_clk),
.vdma_rst (vdma_rst),
.vdma_fs (vdma_fs),
.vdma_fs_ret (vdma_fs_ret),
.vdma_valid (vdma_valid),
.vdma_data (vdma_data),
.vdma_ready (vdma_ready),
.vdma_end_of_frame (vdma_end_of_frame),
.vdma_wr (vdma_wr_s),
.vdma_waddr (vdma_waddr_s),
.vdma_wdata (vdma_wdata_s),

View File

@ -244,21 +244,26 @@ module axi_hdmi_tx_core #(
// hdmi start of frame
always @(posedge hdmi_clk) begin
if (EMBEDDED_SYNC == 1) begin
if ((hdmi_hs_count == 1) && (hdmi_vs_count == hdmi_ve_width_s)) begin
hdmi_fs <= hdmi_enable;
end else begin
hdmi_fs <= 1'b0;
end
if (hdmi_rst == 1'b1) begin
hdmi_fs_toggle <= 1'b0;
hdmi_fs <= 1'b0;
end else begin
if ((hdmi_hs_count == 1) && (hdmi_vs_count == hdmi_vs_width)) begin
hdmi_fs <= hdmi_enable;
if (EMBEDDED_SYNC == 1) begin
if ((hdmi_hs_count == 1) && (hdmi_vs_count == hdmi_ve_width_s)) begin
hdmi_fs <= hdmi_enable;
end else begin
hdmi_fs <= 1'b0;
end
end else begin
hdmi_fs <= 1'b0;
if ((hdmi_hs_count == 1) && (hdmi_vs_count == hdmi_vs_width)) begin
hdmi_fs <= hdmi_enable;
end else begin
hdmi_fs <= 1'b0;
end
end
if (hdmi_fs == 1'b1) begin
hdmi_fs_toggle <= ~hdmi_fs_toggle;
end
end
if (hdmi_fs == 1'b1) begin
hdmi_fs_toggle <= ~hdmi_fs_toggle;
end
end
@ -279,10 +284,8 @@ module axi_hdmi_tx_core #(
end
always @(posedge hdmi_clk) begin
hdmi_fs_ret <= hdmi_fs_ret_s;
if (hdmi_fs_ret_s == 1'b1) begin
hdmi_fs_ret <= hdmi_fs_ret_s;
hdmi_fs_waddr <= vdma_fs_waddr;
end
end
// hdmi sync signals
@ -332,7 +335,7 @@ module axi_hdmi_tx_core #(
always @(posedge hdmi_clk) begin
if (hdmi_rst == 1'b1) begin
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};
end else if (hdmi_de_s == 1'b1) begin
hdmi_raddr <= hdmi_raddr + 1'b1;

View File

@ -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 *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_data* -of_objects [ipx::current_core]]
set_property driver_value 0 [ipx::get_ports *vdma_ready* -of_objects [ipx::current_core]]

View File

@ -45,8 +45,7 @@ module axi_hdmi_tx_vdma (
input vdma_clk,
input vdma_rst,
output reg vdma_fs,
input vdma_fs_ret,
input vdma_end_of_frame,
input vdma_valid,
input [63:0] vdma_data,
output reg vdma_ready,
@ -66,16 +65,20 @@ module axi_hdmi_tx_vdma (
// internal registers
reg vdma_fs_toggle_m1 = 'd0;
reg vdma_fs_toggle_m2 = 'd0;
reg vdma_fs_toggle_m3 = 'd0;
reg [22:0] vdma_tpm_data = 'd0;
reg [ 8:0] vdma_raddr_g_m1 = 'd0;
reg [ 8:0] vdma_raddr_g_m2 = 'd0;
reg [ 8:0] vdma_raddr = 'd0;
reg [ 8:0] vdma_addr_diff = 'd0;
reg vdma_almost_full = 'd0;
reg vdma_almost_empty = 'd0;
reg vdma_fs_toggle_m1 = 1'd0;
reg vdma_fs_toggle_m2 = 1'd0;
reg vdma_fs_toggle_m3 = 1'd0;
reg [22:0] vdma_tpm_data = 23'd0;
reg [ 8:0] vdma_raddr_g_m1 = 9'd0;
reg [ 8:0] vdma_raddr_g_m2 = 9'd0;
reg [ 8:0] vdma_raddr = 9'd0;
reg [ 8:0] vdma_addr_diff = 9'd0;
reg vdma_almost_full = 1'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
@ -104,7 +107,7 @@ module axi_hdmi_tx_vdma (
end
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
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_m3 <= vdma_fs_toggle_m2;
end
hdmi_fs <= vdma_fs_toggle_m2 ^ vdma_fs_toggle_m3;
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
vdma_fs <= vdma_fs_toggle_m2 ^ vdma_fs_toggle_m3;
if (vdma_fs_ret == 1'b1) begin
vdma_fs_waddr <= vdma_waddr;
vdma_fs_ret_toggle <= ~vdma_fs_ret_toggle;
if (vdma_rst == 1'b1) begin
vdma_fs_ret_toggle = 1'b0;
vdma_fs_waddr <= 9'b0;
end else begin
if (vdma_fs) begin
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
@ -144,7 +180,7 @@ module axi_hdmi_tx_vdma (
assign vdma_tpm_oos_s = (vdma_wdata == vdma_tpm_data_s) ? 1'b0 : vdma_wr;
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_oos <= 1'd0;
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
vdma_ready <= 1'b0;
end else if (vdma_addr_diff <= RDY_THRESHOLD_LO) begin
vdma_ready <= 1'b1;
vdma_ready <= vdma_active_frame;
end
if (vdma_addr_diff > BUF_THRESHOLD_HI) begin
vdma_almost_full <= 1'b1;