// axis2video_out.v
// 2019/01/14 by marsee
// 2019/01/23 : Fixed IP start state machine bug
// 2019/07/25 : Added (* ASYNC_REG = "TRUE" *)
//
`default_nettype none
module axis2video_out
(
// Clock and Reset
input wire disp_clk,
input wire axi_clk,
input wire axi_rst_n,
input wire init_done,
// AXI4-Stream
input wire [31:0] axis_tdata,
input wire axis_tvalid,
output wire axis_tready,
input wire [3:0] axis_tkeep,
input wire [3:0] axis_tstrb,
input wire axis_tuser,
input wire axis_tlast,
input wire axis_tid,
input wire axis_tdest,
// IP
output reg ip_start,
input wire ip_done,
// video in
input wire de_in,
input wire vsync_in,
input wire hsync_in,
// video_out
output wire [35:0] disp_pixel,
output wire de_out,
output wire vsync_out,
output wire hsync_out
);
parameter IDLE_START = 1'b0,
IP_START_1 = 1'b1;
reg reset_disp_2b = 1'b1, reset_disp_1b = 1'b1;
wire reset_disp;
reg fifo_reset_axi_2b = 1'b0, fifo_reset_axi_1b = 1'b0;
wire fifo_reset_axi;
reg fifo_reset_disp_2b = 1'b0, fifo_reset_disp_1b = 1'b0;
wire fifo_reset_disp;
reg de_1d, vsync_1d, hsync_1d;
(* ASYNC_REG = "TRUE" *) reg vsync_axi_1b, vsync_axi_2b;
wire vsync_axi;
(* ASYNC_REG = "TRUE" *) reg vsync_axi_1d, vsync_axi_2d;
reg cs_start;
wire pfifo_empty, pfifo_full;
wire [33:0] pfifo_dout;
reg vsync_rising_edge_axi, vsync_falling_edge_axi;
(* ASYNC_REG = "TRUE" *) reg init_done_axi_1d, axi_rst_n_axi_1d;
(* ASYNC_REG = "TRUE" *) reg init_done_axi_2d, axi_rst_n_axi_2d;
(* ASYNC_REG = "TRUE" *) reg init_done_disp_1d, axi_rst_n_disp_1d;
(* ASYNC_REG = "TRUE" *) reg init_done_disp_2d, axi_rst_n_disp_2d;
always @(posedge disp_clk) begin
if(reset_disp) begin
de_1d <= 1'b0;
vsync_1d <= 1'b0;
hsync_1d <= 1'b0;
end else begin
de_1d <= de_in;
vsync_1d <= vsync_in;
hsync_1d <= hsync_in;
end
end
always @(posedge axi_clk) begin
init_done_axi_1d <= init_done;
init_done_axi_2d <= init_done_axi_1d;
axi_rst_n_axi_1d <= axi_rst_n;
axi_rst_n_axi_2d <= axi_rst_n_axi_1d;
end
always @(posedge disp_clk) begin
init_done_disp_1d <= init_done;
init_done_disp_2d <= init_done_disp_1d;
axi_rst_n_disp_1d <= axi_rst_n;
axi_rst_n_disp_2d <= axi_rst_n_disp_1d;
end
// reset signals
always @(posedge axi_clk) begin
fifo_reset_axi_2b <= ~init_done_axi_2d | ~axi_rst_n_axi_2d | vsync_axi;
fifo_reset_axi_1b <= fifo_reset_axi_2b;
end
assign fifo_reset_axi = fifo_reset_axi_1b;
always @(posedge disp_clk) begin
fifo_reset_disp_2b <= ~init_done_disp_2d | ~axi_rst_n_disp_2d | vsync_1d;
fifo_reset_disp_1b <= fifo_reset_disp_2b;
end
assign fifo_reset_disp = fifo_reset_disp_1b;
always @(posedge disp_clk) begin
reset_disp_2b <= ~init_done_disp_2d | ~axi_rst_n_disp_2d;
reset_disp_1b <= reset_disp_2b;
end
assign reset_disp = reset_disp_1b;
// vsync_rising_edge, vsync_falling_edge
always @(posedge axi_clk) begin
if (!axi_rst_n) begin
vsync_axi_2b <= 1'b1;
vsync_axi_1b <= 1'b1;
end else begin
vsync_axi_2b <= vsync_1d;
vsync_axi_1b <= vsync_axi_2b;
end
end
assign vsync_axi = vsync_axi_1b;
always @(posedge axi_clk) begin
if (!axi_rst_n) begin
vsync_axi_1d <= 1'b1;
vsync_axi_2d <= 1'b1;
end else begin
vsync_axi_1d <= vsync_axi;
vsync_axi_2d <= vsync_axi_1d;
end
end
always @(posedge axi_clk) begin
if (!axi_rst_n) begin
vsync_rising_edge_axi = 1'b0;
vsync_falling_edge_axi = 1'b0;
end else begin
vsync_rising_edge_axi <= ~vsync_axi_2d & vsync_axi_1d;
vsync_falling_edge_axi <= vsync_axi_2d & ~vsync_axi_1d;
end
end
// IP start State Machine
always @(posedge axi_clk) begin
if (!axi_rst_n) begin
cs_start <= IDLE_START;
ip_start <= 1'b0;
end else begin
case (cs_start)
IDLE_START : begin
ip_start <= 1'b0;
if (vsync_falling_edge_axi) begin
cs_start <= IP_START_1;
ip_start <= 1'b1;
end
end
IP_START_1 : begin
if (ip_done) begin
cs_start <= IDLE_START;
ip_start <= 1'b0;
end
end
endcase
end
end
// data width 34 bits, 512 depth
pixel_fifo pixel_fifo_i (
.wr_rst(fifo_reset_axi),
.wr_clk(axi_clk),
.rd_rst(fifo_reset_disp),
.rd_clk(disp_clk),
.din({axis_tuser, axis_tlast, axis_tdata}),
.dout(pfifo_dout),
.wr_en(~pfifo_full & axis_tvalid),
.full(pfifo_full),
.rd_en(de_1d),
.empty(pfifo_empty)
);
assign axis_tready = ~pfifo_full;
assign disp_pixel = {pfifo_dout[7:0], 4'd0, pfifo_dout[23:16], 4'd0, pfifo_dout[15:8], 4'd0}; //BRG
assign de_out = de_1d;
assign vsync_out = vsync_1d;
assign hsync_out = hsync_1d;
endmodule
`default_nettype wire
ASYNC_REG では、 タイミング違反が発生しても最後の既知の値を出力するようにレジスタが変更されます。
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | - | - | - |