dsi-shield/hdl/rtl/dsi_core/dsi_timing_gen.v

238 lines
6.3 KiB
Verilog

/*
* DSI Core
* Copyright (C) 2013 twl <twlostow@printf.cc>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
`timescale 1ns/1ps
`include "dsi_defs.vh"
/*
* dsi_timing_gen.v
*
* Image timing generator - produces the display refresh timing (hsync, vsync, blanking, etc.)
* The image is delivered by a simple FIFO interface, pixel-by-pixel. The output requests
* particular packets from the Packet Assembler.
*/
module dsi_timing_gen
(
clk_i,
rst_n_i,
fifo_empty_i,
fifo_rd_o,
fifo_pixels_i,
fifo_frame_i,
fifo_got_frame_i,
p_req_o,
p_islong_o,
p_type_o,
p_wcount_o,
p_command_o,
p_payload_o,
p_dreq_i,
p_last_o,
host_a_i,
host_d_i,
host_d_o,
host_wr_i
);
parameter g_pixels_per_clock = 1;
localparam g_pixel_width = g_pixels_per_clock * 24;
input clk_i;
input rst_n_i;
input fifo_empty_i;
input fifo_got_frame_i;
output fifo_rd_o;
input [g_pixel_width - 1: 0] fifo_pixels_i;
input fifo_frame_i;
output reg p_req_o, p_islong_o;
output reg [5:0] p_type_o;
output reg [15:0] p_wcount_o, p_command_o;
output [g_pixel_width-1:0] p_payload_o;
input p_dreq_i;
output reg p_last_o;
input [3:0] host_a_i;
input [31:0] host_d_i;
output reg [31:0] host_d_o;
input host_wr_i;
`define ST_BPORCH 0
`define ST_FPORCH 1
`define ST_HSYNC_START 2
`define ST_HSYNC_END 3
`define ST_HSYNC_ACTIVE 4
`define ST_LINE 6
`define ST_VSYNC_PACKET 7
`define ST_STOP 8
`define ST_LONG_PACKET 9
`define ST_LP 10
reg [3:0] state, next_state;
reg [11:0] h_count, v_count;
reg [11:0] h_front_porch, h_back_porch, h_active, h_total;
reg [11:0] v_front_porch, v_back_porch, v_active, v_total;
reg enable = 0;
reg disp_en_mask;
reg [11:0] pixel_counter;
// host registers
always@(posedge clk_i)
if(!rst_n_i)
begin
enable <= 0;
end else if(host_wr_i) begin
case (host_a_i)
0:h_front_porch <= host_d_i;
1:h_back_porch <= host_d_i;
2:h_active <= host_d_i;
3:h_total <= host_d_i;
4:v_front_porch <= host_d_i;
5:v_back_porch <= host_d_i;
6:v_active <= host_d_i;
7:v_total <= host_d_i;
8:enable<=host_d_i[0];
endcase // case (host_a_i)
end
task send(input long, input [5:0] ptype, input [15:0] count, input[3:0] _next_state, input is_last);
begin
if(p_dreq_i) begin
p_islong_o <= long;
p_type_o <= ptype;
p_wcount_o <= count;
p_command_o <= 0;
p_last_o <= is_last;
pixel_counter <= count;
if(long)
state <= `ST_LONG_PACKET;
else
state <= _next_state;
next_state <= _next_state;
end // if (p_dreq_i)
end
endtask // send
reg push_pixels, push_pixels_d0;
always@(posedge clk_i)
if(!rst_n_i || !enable) begin
v_count <= 0;
state <= `ST_LP;
pixel_counter <= h_total;
p_req_o <= 0;
p_last_o <= 0;
disp_en_mask <= 0;
push_pixels <= 0;
push_pixels_d0 <= 0;
end else begin
push_pixels_d0 <= push_pixels;
case (state)
`ST_FPORCH:
begin
push_pixels<=0;
push_pixels_d0<=0;
if(v_count == v_back_porch) begin
disp_en_mask <= 1;
end else if(v_count == v_front_porch) begin
disp_en_mask <= 0;
end
send(1, `PTYPE_BLANKING, h_front_porch, `ST_HSYNC_START, 0);
end // case: `ST_FPORCH
`ST_HSYNC_START: begin
p_req_o <= 1;
if(v_count == 0)
send(0, `PTYPE_VSYNC_START, h_total, `ST_BPORCH, 0);
else if (v_count == v_total)
send(0, `PTYPE_HSYNC_START, h_total, `ST_LP, 1);
else
send(0, `PTYPE_HSYNC_START, h_total, `ST_BPORCH, 0);
end
`ST_BPORCH:
send(1, `PTYPE_BLANKING, h_back_porch, `ST_LINE, 0);
`ST_LINE:
begin
send(1, disp_en_mask ? `PTYPE_RGB24: `PTYPE_BLANKING, h_active, `ST_FPORCH, 0);
if(p_dreq_i) begin
if(v_count == v_total)
v_count <= 0;
else
v_count <= v_count + 1;
push_pixels <= disp_en_mask;
end
end
`ST_LP: begin
p_req_o <= 0;
if(pixel_counter == 0) begin
if(!fifo_empty_i) begin
state <= `ST_HSYNC_START;
v_count <= 0;
end
end else
pixel_counter <= pixel_counter - 1;
end
`ST_LONG_PACKET:
begin
if(p_dreq_i)
pixel_counter <= pixel_counter - 3;
if(pixel_counter == 3)
begin
push_pixels <=0;
state <= next_state;
end
end
endcase // case (state)
end // else: !if(!rst_n_i || !enable)
assign fifo_rd_o = (push_pixels && p_dreq_i);
assign p_payload_o = (push_pixels || push_pixels_d0 ? fifo_pixels_i : 0);
endmodule // dsi_timing_gen