Skip to content

Instantly share code, notes, and snippets.

@hinzundcode

hinzundcode/fomu_vga.v

Last active Aug 20, 2020
Embed
What would you like to do?
// user_1 is R, G and B (VGA pins 1, 2 and 3)
// user_2 is Ground
// user_3 is HSYNC (VGA pin 13)
// user_4 is VSYNC (VGA pin 15)
// from https://8bitworkshop.com/v3.6.0/?file=hvsync_generator.v&platform=verilog-vga
module hvsync_generator(clk, reset, hsync, vsync, display_on, hpos, vpos);
input clk;
input reset;
output reg hsync, vsync;
output display_on;
output reg [9:0] hpos;
output reg [9:0] vpos;
// declarations for TV-simulator sync parameters
// horizontal constants
parameter H_DISPLAY = 640; // horizontal display width
parameter H_BACK = 48; // horizontal left border (back porch)
parameter H_FRONT = 16; // horizontal right border (front porch)
parameter H_SYNC = 96; // horizontal sync width
// vertical constants
parameter V_DISPLAY = 480; // vertical display height
parameter V_TOP = 33; // vertical top border
parameter V_BOTTOM = 10; // vertical bottom border
parameter V_SYNC = 2; // vertical sync # lines
// derived constants
parameter H_SYNC_START = H_DISPLAY + H_FRONT;
parameter H_SYNC_END = H_DISPLAY + H_FRONT + H_SYNC - 1;
parameter H_MAX = H_DISPLAY + H_BACK + H_FRONT + H_SYNC - 1;
parameter V_SYNC_START = V_DISPLAY + V_BOTTOM;
parameter V_SYNC_END = V_DISPLAY + V_BOTTOM + V_SYNC - 1;
parameter V_MAX = V_DISPLAY + V_TOP + V_BOTTOM + V_SYNC - 1;
wire hmaxxed = (hpos == H_MAX) || reset; // set when hpos is maximum
wire vmaxxed = (vpos == V_MAX) || reset; // set when vpos is maximum
// horizontal position counter
always @(posedge clk)
begin
hsync <= (hpos>=H_SYNC_START && hpos<=H_SYNC_END);
if(hmaxxed)
hpos <= 0;
else
hpos <= hpos + 1;
end
// vertical position counter
always @(posedge clk)
begin
vsync <= (vpos>=V_SYNC_START && vpos<=V_SYNC_END);
if(hmaxxed)
if (vmaxxed)
vpos <= 0;
else
vpos <= vpos + 1;
end
// display_on is set when beam is in "safe" visible frame
assign display_on = (hpos<H_DISPLAY) && (vpos<V_DISPLAY);
endmodule
module gpu(clk, hsync, vsync, color);
input clk;
output hsync, vsync;
output color;
wire pclk;
wire display_on;
wire [9:0] hpos;
wire [9:0] vpos;
// generates pixelclock, 640x480 @60Hz
// from 48MHz to 25.125MHz (icepll -i 48 -o 25.175)
SB_PLL40_CORE #(.FEEDBACK_PATH("SIMPLE"),
.PLLOUT_SELECT("GENCLK"),
.DIVR(4'b0011), // R = 3
.DIVF(7'b1000010), // F = 66
.DIVQ(3'b101), // Q = 5
.FILTER_RANGE(3'b001),
) uut (
.REFERENCECLK(clk),
.PLLOUTCORE(pclk),
//.LOCK(D5),
.RESETB(1'b1),
.BYPASS(1'b0)
);
hvsync_generator hvsync_gen (
.clk(pclk),
.reset(0),
.hsync(hsync),
.vsync(vsync),
.display_on(display_on),
.hpos(hpos),
.vpos(vpos),
);
// static square
wire inbox = hpos >= 100 && hpos < 200 && vpos >= 100 && vpos < 200;
assign color = display_on && inbox;
// moving square
/*reg [31:0] counter = 0;
reg signed [15:0] x0 = 0;
always @(posedge clk) begin
counter <= counter + 1;
// every second
if (counter >= 48000000) begin
counter <= 0;
x0 <= x0 + 10;
end
end
wire inbox = hpos >= x0 && hpos < 200 && vpos >= 100 && vpos < 200;
assign color = display_on && inbox;*/
endmodule
module top (
// 48MHz Clock input
// --------
input clki,
// LED outputs
// --------
output user_1,
output user_2,
output user_3,
output user_4,
// USB Pins (which should be statically driven if not being used).
// --------
output usb_dp,
output usb_dn,
output usb_dp_pu
);
// Assign USB pins to "0" so as to disconnect Fomu from
// the host system. Otherwise it would try to talk to
// us over USB, which wouldn't work since we have no stack.
assign usb_dp = 1'b0;
assign usb_dn = 1'b0;
assign usb_dp_pu = 1'b0;
// Connect to system clock (with buffering)
wire clk;
SB_GB clk_gb (
.USER_SIGNAL_TO_GLOBAL_BUFFER(clki),
.GLOBAL_BUFFER_OUTPUT(clk)
);
gpu g (
.clk(clk),
.hsync(user_3),
.vsync(user_4),
.color(user_1),
);
assign user_2 = 'b0;
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment