display-timing.sv (4519B)
1 // Copyright 2020, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0. 3 4 `default_nettype none 5 6 module display_timing #( 7 // horizontal timing (all values -1) 8 parameter HZNT_FRONT = 15, 9 parameter HZNT_SYNC = 95, 10 parameter HZNT_BACK = 47, 11 parameter HZNT_ACTIVE = 639, 12 13 // vertical timing (all values -1) 14 parameter VERT_FRONT = 11, 15 parameter VERT_SYNC = 1, 16 parameter VERT_BACK = 29, 17 parameter VERT_ACTIVE = 479 18 )( 19 input wire clk, 20 21 output wire hsync, 22 output wire vsync, 23 output wire start_frame, 24 output wire start_line, 25 output wire pxl_accept, 26 output wire [9:0] pxl_x, 27 output wire [9:0] pxl_y 28 ); 29 30 localparam HS_FRONT = 2'd0; 31 localparam HS_SYNC = 2'd1; 32 localparam HS_BACK = 2'd2; 33 localparam HS_ACTIVE = 2'd3; 34 35 localparam VS_FRONT = 2'd0; 36 localparam VS_SYNC = 2'd1; 37 localparam VS_BACK = 2'd2; 38 localparam VS_ACTIVE = 2'd3; 39 40 reg [1:0] v_state = VS_FRONT; 41 reg [1:0] v_state_next; 42 reg v_sync = 1'b1; 43 reg v_sync_next; 44 reg v_active = 1'b0; 45 reg v_active_next; 46 reg [9:0] v_count = 10'b0; 47 reg [9:0] v_count_next; 48 wire [9:0] v_count_add1; 49 reg [7:0] v_countdown = VERT_FRONT; 50 reg [7:0] v_countdown_next; 51 wire [7:0] v_countdown_sub1; 52 wire v_countdown_done; 53 54 reg [1:0] h_state = HS_FRONT; 55 reg [1:0] h_state_next; 56 reg h_sync = 1'b1; 57 reg h_sync_next; 58 reg h_active = 1'b0; 59 reg h_active_next; 60 reg [9:0] h_count = 10'b0; 61 reg [9:0] h_count_next; 62 wire [9:0] h_count_add1; 63 reg [7:0] h_countdown = HZNT_FRONT; 64 reg [7:0] h_countdown_next; 65 wire [7:0] h_countdown_sub1; 66 wire h_countdown_done; 67 68 reg new_line = 1'b0; 69 reg new_frame = 1'b0; 70 reg new_line_next; 71 reg new_frame_next; 72 73 assign v_count_add1 = v_count + 9'd1; 74 assign h_count_add1 = h_count + 9'd1; 75 76 assign { h_countdown_done, h_countdown_sub1 } = { 1'b0, h_countdown } - 9'd1; 77 assign { v_countdown_done, v_countdown_sub1 } = { 1'b0, v_countdown } - 9'd1; 78 79 // outputs 80 assign hsync = h_sync; 81 assign vsync = v_sync; 82 assign start_frame = new_frame; 83 assign start_line = new_line & v_active; 84 assign pxl_accept = h_active & v_active; 85 assign pxl_x = h_count; 86 assign pxl_y = v_count; 87 88 always_comb begin 89 h_state_next = h_state; 90 h_count_next = h_count; 91 h_countdown_next = h_countdown; 92 h_active_next = h_active; 93 h_sync_next = h_sync; 94 new_line_next = 1'b0; 95 96 case (h_state) 97 HS_FRONT: begin 98 if (h_countdown_done) begin 99 h_state_next = HS_SYNC; 100 h_countdown_next = HZNT_SYNC; 101 h_sync_next = 1'b0; 102 end else begin 103 h_countdown_next = h_countdown_sub1; 104 end 105 end 106 HS_SYNC: begin 107 if (h_countdown_done) begin 108 h_state_next = HS_BACK; 109 h_countdown_next = HZNT_BACK; 110 h_sync_next = 1'b1; 111 end else begin 112 h_countdown_next = h_countdown_sub1; 113 end 114 end 115 HS_BACK: begin 116 if (h_countdown_done) begin 117 h_state_next = HS_ACTIVE; 118 h_countdown_next = HZNT_FRONT; 119 h_active_next = 1'b1; 120 end else begin 121 h_countdown_next = h_countdown_sub1; 122 end 123 end 124 HS_ACTIVE: begin 125 if (h_count == HZNT_ACTIVE) begin 126 h_state_next = HS_FRONT; 127 h_count_next = 0; 128 new_line_next = 1'b1; 129 h_active_next = 1'b0; 130 end else begin 131 h_count_next = h_count_add1; 132 end 133 end 134 endcase 135 end 136 137 always_comb begin 138 v_state_next = v_state; 139 v_count_next = v_count; 140 v_countdown_next = v_countdown; 141 v_active_next = v_active; 142 v_sync_next = v_sync; 143 new_frame_next = 1'b0; 144 145 case (v_state) 146 VS_FRONT: begin 147 if (v_countdown_done) begin 148 v_state_next = VS_SYNC; 149 v_countdown_next = VERT_SYNC; 150 v_sync_next = 1'b0; 151 end else begin 152 v_countdown_next = v_countdown_sub1; 153 end 154 end 155 VS_SYNC: begin 156 if (v_countdown_done) begin 157 v_state_next = VS_BACK; 158 v_countdown_next = VERT_BACK; 159 v_sync_next = 1'b1; 160 end else begin 161 v_countdown_next = v_countdown_sub1; 162 end 163 end 164 VS_BACK: begin 165 if (v_countdown_done) begin 166 v_state_next = VS_ACTIVE; 167 v_countdown_next = VERT_FRONT; 168 v_active_next = 1'b1; 169 end else begin 170 v_countdown_next = v_countdown_sub1; 171 end 172 end 173 VS_ACTIVE: begin 174 if (v_count == VERT_ACTIVE) begin 175 v_state_next = VS_FRONT; 176 v_count_next = 0; 177 v_active_next = 1'b0; 178 new_frame_next = 1'b1; 179 end else begin 180 v_count_next = v_count_add1; 181 end 182 end 183 endcase 184 end 185 186 always_ff @(posedge clk) begin 187 h_state <= h_state_next; 188 h_sync <= h_sync_next; 189 h_count <= h_count_next; 190 h_countdown <= h_countdown_next; 191 h_active <= h_active_next; 192 193 new_line <= new_line_next; 194 new_frame <= new_frame_next & new_line_next; 195 196 if (new_line_next) begin 197 v_state <= v_state_next; 198 v_sync <= v_sync_next; 199 v_count <= v_count_next; 200 v_countdown <= v_countdown_next; 201 v_active <= v_active_next; 202 end 203 end 204 205 endmodule