Skip to content

Instantly share code, notes, and snippets.

@yupferris
Created December 8, 2022 20:42
Show Gist options
  • Save yupferris/f50e270b4bdb398e2a1ce39d214755bc to your computer and use it in GitHub Desktop.
Save yupferris/f50e270b4bdb398e2a1ce39d214755bc to your computer and use it in GitHub Desktop.
video stuffz
// video generation
// ~12,288,000 hz pixel clock
//
// we want our video mode of 320x240 @ 60hz, this results in 204800 clocks per frame
// we need to add hblank and vblank times to this, so there will be a nondisplay area.
// it can be thought of as a border around the visible area.
// to make numbers simple, we can have 400 total clocks per line, and 320 visible.
// dividing 204800 by 400 results in 512 total lines per frame, and 240 visible.
// this pixel clock is fairly high for the relatively low resolution, but that's fine.
// PLL output has a minimum output frequency anyway.
assign video_rgb_clock = clk_core_12288;
assign video_rgb_clock_90 = clk_core_12288_90deg;
assign video_rgb = vidout_rgb;
assign video_de = vidout_de;
assign video_skip = vidout_skip;
assign video_vs = vidout_vs;
assign video_hs = vidout_hs;
localparam VID_V_BPORCH = 'd10;
localparam VID_V_ACTIVE = 'd240;
localparam VID_V_TOTAL = 'd512;
localparam VID_H_BPORCH = 'd10;
localparam VID_H_ACTIVE = 'd320;
localparam VID_H_TOTAL = 'd400;
reg [15:0] frame_count;
reg [9:0] x_count;
reg [9:0] y_count;
reg [23:0] vidout_rgb;
reg vidout_de;
reg vidout_skip;
reg vidout_vs;
reg vidout_hs;
always @(posedge clk_core_12288 or negedge reset_n) begin
if(~reset_n) begin
x_count <= 0;
y_count <= 0;
end else begin
vidout_de <= 0;
vidout_skip <= 0;
vidout_vs <= 0;
vidout_hs <= 0;
// x and y counters
x_count <= x_count + 1'b1;
if(x_count == VID_H_TOTAL-1) begin
x_count <= 0;
y_count <= y_count + 1'b1;
if(y_count == VID_V_TOTAL-1) begin
y_count <= 0;
end
end
// generate sync
if(x_count == 0 && y_count == 0) begin
// sync signal in back porch
// new frame
vidout_vs <= 1;
frame_count <= frame_count + 1'b1;
end
// we want HS to occur a bit after VS, not on the same cycle
if(x_count == 3) begin
// sync signal in back porch
// new line
vidout_hs <= 1;
end
// inactive screen areas are black
vidout_rgb <= 24'h0;
// generate active video
if(x_count >= VID_H_BPORCH && x_count < VID_H_ACTIVE+VID_H_BPORCH) begin
if(y_count >= VID_V_BPORCH && y_count < VID_V_ACTIVE+VID_V_BPORCH) begin
// data enable. this is the active region of the line
vidout_de <= 1;
vidout_rgb[23:16] <= test_pattern_r;
vidout_rgb[15:8] <= test_pattern_g;
vidout_rgb[7:0] <= test_pattern_b;
end
end
end
end
// video test pattern generator
// currently on the output pixel clock, but should ideally happen in another domain with line buffer fifo(s) in between
reg [8:0] test_pattern_x;
reg [7:0] test_pattern_y;
always @(posedge clk_core_12288 or negedge reset_n) begin
if (~reset_n) begin
test_pattern_x <= 9'd0;
test_pattern_y <= 8'd0;
end
else begin
if (vidout_vs) begin
test_pattern_x <= 9'd0;
test_pattern_y <= 8'd0;
end
else if (x_count >= VID_H_BPORCH && x_count < VID_H_ACTIVE + VID_H_BPORCH - 1) begin
test_pattern_x <= test_pattern_x + 9'd1;
end
else if (x_count == VID_H_ACTIVE + VID_H_BPORCH - 1) begin
test_pattern_x <= 9'd0;
test_pattern_y <= test_pattern_y + 8'd1;
end
end
end
wire [7:0] test_pattern_r = test_pattern_x[7:0];
wire [7:0] test_pattern_g = test_pattern_y;
wire [7:0] test_pattern_b = 8'd64;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment