More stuff

This commit is contained in:
John Bintz 2024-07-14 20:34:18 -04:00
parent e47471826e
commit 11cea6b1cf
19 changed files with 5614 additions and 21 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/test
/test.vcd

View File

@ -1,19 +1,21 @@
CONSTRAINTS = ../Go_Board_Constraints.pcf
LED_TOGGLE = pong_runner.bin
LED_TOGGLE = double_dabble_counters.bin
install: $(LED_TOGGLE)
iceprog $(LED_TOGGLE)
.PHONY: test
test:
iverilog -o test uart_rx_test.v uart_rx.v
iverilog -o test image_index_to_color.v
vvp test
gtkwave test.vcd
.SUFFIXES: .v .json .bitstream .bin
.v.json:
yosys -q -p "hierarchy -top PongRunner; synth_ice40 -json $*.json" $*.v vga_sync_pulse_generator.v vga_current_beam_position.v vga_add_porches_to_output.v uart_rx.v uart_tx.v pong.v pong_ball.v pong_paddle.v debounce_filter.v
#yosys -q -p "hierarchy -top VGAImageRenderer_Top; synth_ice40 -json $*.json" $*.v vga_sync_pulse_generator.v vga_current_beam_position.v vga_add_porches_to_output.v image_index_to_color.v image_ram.v
#yosys -q -p "hierarchy -top VGAImageRenderer_Top; synth_ice40 -json $*.json" $*.v vga_image_renderer.v image_ram.v image_index_to_color.v vga_sync_pulse_generator.v vga_current_beam_position.v vga_add_porches_to_output.v
yosys -q -p "hierarchy -top DoubleDabbleCounter_Top; synth_ice40 -json $*.json" $*.v
.json.bitstream:
#nextpnr-ice40 --hx1k --freq 25 --pcf $(CONSTRAINTS) --json $*.json --package vq100 --asc $*.bitstream

101
build_image.rb Executable file
View File

@ -0,0 +1,101 @@
#!/usr/bin/env ruby
require 'rmagick'
class GoBoardPixel
GO_BOARD_CHANNEL_TO_RMAGICK_CHANNEL = 65_536 / 8
attr_reader :red, :green, :blue
def self.from_magick(red:, green:, blue:)
new(
red: red / GO_BOARD_CHANNEL_TO_RMAGICK_CHANNEL,
green: green / GO_BOARD_CHANNEL_TO_RMAGICK_CHANNEL,
blue: blue / GO_BOARD_CHANNEL_TO_RMAGICK_CHANNEL
)
end
def initialize(red:, green:, blue:)
@red = red
@green = green
@blue = blue
end
def distance_from_real_pixel(red:, green:, blue:)
(red - @red * GO_BOARD_CHANNEL_TO_RMAGICK_CHANNEL)**2 +
(green - @green * GO_BOARD_CHANNEL_TO_RMAGICK_CHANNEL)**2 +
(blue - @blue * GO_BOARD_CHANNEL_TO_RMAGICK_CHANNEL)**2
end
def distance_from_go_pixel(red:, green:, blue:)
(red - @red)**2 +
(green - @green)**2 +
(blue - @blue)**2
end
def eql?(other)
red == other.red && green == other.green && blue == other.blue
end
def hash
[red, green, blue].hash
end
end
ImagePixel = Data.define(:red, :green, :blue)
image = Magick::Image.read(ARGV[0]).first
image.change_geometry!('80x60^') do |cols, rows, img|
img.resize!(cols, rows)
end
image.crop!(Magick::CenterGravity, 80, 60, true)
possible_colors = {}
image.each_pixel do |px|
go_px = GoBoardPixel.from_magick(red: px.red, green: px.green, blue: px.blue)
possible_colors[go_px] ||= 0
possible_colors[go_px] += 1
end
pixels_by_usage = possible_colors.sort_by(&:last).reverse
go_board_palette = pixels_by_usage[0..31].map(&:first)
color_mapping = go_board_palette.each_with_index.each_with_object({}) do |(go_px, index), obj|
obj[go_px] = index
end
pixels_by_usage[32..].map(&:first).each do |go_px|
best_match = go_board_palette.each_with_index.map do |target_go_px, index|
[
target_go_px.distance_from_go_pixel(
red: go_px.red,
green: go_px.green,
blue: go_px.blue,
), index
]
end.sort_by(&:first).first
color_mapping[go_px] = best_match.last
end
File.open('image_data.txt', 'w') do |fh|
image.each_pixel do |px|
magick_px = GoBoardPixel.from_magick(
red: px.red, green: px.green, blue: px.blue
)
fh.puts format('%05b', color_mapping[magick_px])
end
end
File.open('palette_data.txt', 'w') do |fh|
go_board_palette.each do |color|
fh.puts format('%09b', ((color.red << 6) + (color.green << 3) + color.blue))
end
end
# [ ] load image
# [ ] downsample to 40x30
# [ ] change to indexed image with go board palette
# [ ] save out body data
# [ ] save out palette data

37
double_dabble.rb Executable file
View File

@ -0,0 +1,37 @@
#!/usr/bin/env ruby
# build double dabble in ruby so I can feel how it works
number = 999
puts "Binary: #{number.to_s(2)}"
binary_registers = number.to_s(2).split('').map(&:to_i)
scratch_size = 4 * (binary_registers.count / 3).ceil
scratch_space = Array.new(binary_registers.count + scratch_size) { 0 }
binary_registers.each_with_index do |reg, i|
scratch_space[-(binary_registers.count - i)] = reg
end
pp (scratch_space.count / 4).to_i
binary_registers.count.times do
(scratch_size / 4).to_i.times do |j|
value = scratch_space[j * 4..j * 4 + 3].join.to_i(2)
next unless value > 4
value += 3
scratch_space[j * 4..j * 4 + 3] = value.to_s(2).split('').map(&:to_i)
end
(scratch_space.count - 1).times do |j|
scratch_space[j] = scratch_space[j + 1]
end
scratch_space[-1] = 0
pp scratch_space
end

BIN
double_dabble_counters.bin Normal file

Binary file not shown.

136
double_dabble_counters.v Normal file
View File

@ -0,0 +1,136 @@
module DoubleDabbleCounter_Top(
input i_Clk,
output o_Segment1_A,
output o_Segment1_B,
output o_Segment1_C,
output o_Segment1_D,
output o_Segment1_E,
output o_Segment1_F,
output o_Segment1_G,
output o_Segment2_A,
output o_Segment2_B,
output o_Segment2_C,
output o_Segment2_D,
output o_Segment2_E,
output o_Segment2_F,
output o_Segment2_G
);
reg [6:0] r_currentNumber = 0;
reg [$clog2(10000000)-1:0] r_counter;
always @(posedge i_Clk) begin
if (r_counter == 10000000) begin
r_counter <= 0;
if (r_currentNumber == 99) begin
r_currentNumber <= 0;
end else begin
r_currentNumber <= r_currentNumber + 1;
end
end else begin
r_counter <= r_counter + 1;
end
end
wire [8:0] w_binaryCodedNumber;
wire [3:0] w_decimal1, w_decimal2;
wire [6:0] w_segment1, w_segment2;
IntegerToBCD integerToBCD (
.i_BinaryNumber(r_currentNumber),
.o_BinaryCodedDecimal(w_binaryCodedNumber)
);
assign w_decimal1 = w_binaryCodedNumber[7:4];
assign w_decimal2 = w_binaryCodedNumber[3:0];
BCDTo7Segment segment1 (
.i_Clk(i_Clk),
.i_BinaryCodedDecimal(w_decimal1),
.o_SegmentLights(w_segment1)
);
BCDTo7Segment segment2 (
.i_Clk(i_Clk),
.i_BinaryCodedDecimal(w_decimal2),
.o_SegmentLights(w_segment2)
);
assign o_Segment1_A = !w_segment1[6];
assign o_Segment1_B = !w_segment1[5];
assign o_Segment1_C = !w_segment1[4];
assign o_Segment1_D = !w_segment1[3];
assign o_Segment1_E = !w_segment1[2];
assign o_Segment1_F = !w_segment1[1];
assign o_Segment1_G = !w_segment1[0];
assign o_Segment2_A = !w_segment2[6];
assign o_Segment2_B = !w_segment2[5];
assign o_Segment2_C = !w_segment2[4];
assign o_Segment2_D = !w_segment2[3];
assign o_Segment2_E = !w_segment2[2];
assign o_Segment2_F = !w_segment2[1];
assign o_Segment2_G = !w_segment2[0];
// register that goes to 99
// debounce two input buttons
// button 1 increases
// button 2 decreases
endmodule
module BCDTo7Segment(
input i_Clk,
input [3:0] i_BinaryCodedDecimal,
output reg [6:0] o_SegmentLights
);
always @(posedge i_Clk) begin
case (i_BinaryCodedDecimal)
0: o_SegmentLights <= 7'b1111110;
1: o_SegmentLights <= 7'b0110000;
2: o_SegmentLights <= 7'b1101101;
3: o_SegmentLights <= 7'b1111001;
4: o_SegmentLights <= 7'b0110011;
5: o_SegmentLights <= 7'b1011011;
6: o_SegmentLights <= 7'b1011111;
7: o_SegmentLights <= 7'b1110000;
8: o_SegmentLights <= 7'b1111111;
9: o_SegmentLights <= 7'b1111011;
default: o_SegmentLights <= 7'b0000000;
endcase
end
endmodule
/**
* From https://github.com/AmeerAbdelhadi/Binary-to-BCD-Converter
* This halts until the conversion is done!
*/
module IntegerToBCD(
input [MAX_BIT_WIDTH-1:0] i_BinaryNumber,
output reg [SCRATCH_AREA_WIDTH:0] o_BinaryCodedDecimal
);
// this is all the go board will need for the 7 segment display to go to 99
parameter MAX_BIT_WIDTH = 7;
localparam SCRATCH_AREA_WIDTH = MAX_BIT_WIDTH+(MAX_BIT_WIDTH-4)/3;
integer i,j;
always @(i_BinaryNumber) begin
for (i = 0; i <= SCRATCH_AREA_WIDTH; i = i + 1) begin
o_BinaryCodedDecimal[i] = 0;
end
o_BinaryCodedDecimal[MAX_BIT_WIDTH-1:0] = i_BinaryNumber;
// this does the shift-and-add in small pieces
for (i = 0; i <= MAX_BIT_WIDTH - 4; i = i + 1) begin
for (j = 0; j <= i / 3; j = j + 1) begin
if (o_BinaryCodedDecimal[MAX_BIT_WIDTH-i+4*j -: 4] > 4) begin
o_BinaryCodedDecimal[MAX_BIT_WIDTH-i+4*j -: 4] = o_BinaryCodedDecimal[MAX_BIT_WIDTH-i+4*j -: 4] + 4'd3;
end
end
end
end
endmodule

4800
image_data.txt Normal file

File diff suppressed because it is too large Load Diff

94
image_index_to_color.v Normal file
View File

@ -0,0 +1,94 @@
module ImageIndexToColor(
input i_Clk,
input [4:0] i_ColorIndex,
input i_DoWrite,
input [3:0] i_WriteColorIndex,
input [2:0] i_WriteColor_Red,
input [2:0] i_WriteColor_Green,
input [2:0] i_WriteColor_Blue,
output [2:0] o_Red,
output [2:0] o_Green,
output [2:0] o_Blue,
output reg o_WriteComplete
);
reg [8:0] r_colors[0:31];
initial begin
$readmemb("palette_data.txt", r_colors);
end
always @(posedge i_Clk) begin
if (i_DoWrite) begin
r_colors[i_WriteColorIndex] <= {
i_WriteColor_Red, i_WriteColor_Green, i_WriteColor_Blue
};
o_WriteComplete <= i_DoWrite;
end
end
assign o_Red = r_colors[i_ColorIndex][8:6];
assign o_Green = r_colors[i_ColorIndex][5:3];
assign o_Blue = r_colors[i_ColorIndex][2:0];
endmodule
module TestImageIndexToColor();
reg i_Clk = 0;
always #2 i_Clk <= !i_Clk;
reg [3:0] r_colorIndex = 0;
wire [2:0] w_Red, w_Green, w_Blue;
wire w_writeComplete;
reg r_doWrite = 0;
reg [2:0] r_WriteColor_Red = 3'b111;
reg [2:0] r_WriteColor_Green = 3'b000;
reg [2:0] r_WriteColor_Blue = 3'b001;
reg [3:0] r_writeColorIndex = 0;
ImageIndexToColor ii2c (
.i_Clk(i_Clk),
.i_ColorIndex(r_colorIndex),
.i_DoWrite(r_doWrite),
.i_WriteColorIndex(r_writeColorIndex),
.i_WriteColor_Red(r_WriteColor_Red),
.i_WriteColor_Green(r_WriteColor_Green),
.i_WriteColor_Blue(r_WriteColor_Blue),
.o_Red(w_Red),
.o_Green(w_Green),
.o_Blue(w_Blue),
.o_WriteComplete(w_writeComplete)
);
initial begin
$dumpfile("test.vcd");
$dumpvars;
#2;
#2;
r_colorIndex = 1;
#2;
#2;
r_doWrite = 1;
#2;
#2;
r_colorIndex = 15;
#2;
#2;
$finish;
end
endmodule

92
image_ram.v Normal file
View File

@ -0,0 +1,92 @@
module ImageRAM(
input i_Clk,
input i_doRead,
input [$clog2(WIDTH)-1:0] i_ReadX,
input [$clog2(HEIGHT)-1:0] i_ReadY,
input [$clog2(WIDTH)-1:0] i_WriteX,
input [$clog2(HEIGHT)-1:0] i_WriteY,
input [$clog2(INDEXES)-1:0] i_WriteData,
input i_DoWrite,
output reg o_ReadDataReady,
output reg [4:0] o_ReadData,
output reg o_WriteComplete
);
parameter INDEXES = 8;
parameter WIDTH = 80;
parameter HEIGHT = 60;
reg [4:0] r_Memory[0:HEIGHT-1][0:WIDTH-1];
initial begin
$readmemb("image_data.txt", r_Memory);
end
// reading
always @(posedge i_Clk) begin
o_ReadData <= r_Memory[i_ReadY][i_ReadX];
o_ReadDataReady <= i_doRead;
end
// writing
always @(posedge i_Clk) begin
if (i_DoWrite) begin
r_Memory[i_WriteY][i_WriteX] <= i_WriteData;
o_WriteComplete <= i_DoWrite;
end
end
endmodule
module TestImageRAM();
reg r_Clk = 0;
always #2 r_Clk <= !r_Clk;
reg r_doRead = 0;
reg [5:0] r_readX = 0;
reg [4:0] r_readY = 0;
wire w_readDataReady;
wire [2:0] w_readData;
ImageRAM MyRam (
.i_Clk(r_Clk),
.i_doRead(r_doRead),
.i_ReadX(r_readX),
.i_ReadY(r_readY),
.o_ReadDataReady(w_readDataReady),
.o_ReadData(w_readData)
);
initial begin
$dumpfile("test.vcd");
$dumpvars;
#2;
#2;
r_doRead <= 1;
#2;
#2;
r_doRead <= 0;
r_readX <= 1;
r_readY <= 0;
#2;
#2;
r_doRead <= 1;
#2;
#2;
r_doRead <= 0;
$finish;
end
endmodule

2
image_ram_dat.txt Normal file
View File

@ -0,0 +1,2 @@
011
101

32
palette_data.txt Normal file
View File

@ -0,0 +1,32 @@
011110111
101111111
100110111
100111111
100011011
011010010
110011010
111100011
001011100
111100100
101011010
010101111
110011011
011101110
010001001
111101101
101011011
010100101
101100100
000010011
110101101
001100110
000011100
110100100
100010010
100100100
110100011
101010010
001100101
111101100
011011011
010110111

BIN
pong_runner.bin Normal file

Binary file not shown.

View File

@ -1,6 +1,9 @@
/**
* The output is buffered as the front/back porches are added, so watch your
* timing for other stuff.
*
* Side effects:
* * Blanks o_<color> if within HSync/VSync
*/
module VGA_Add_Porches_To_Output(
input i_Clk,
@ -55,21 +58,23 @@ module VGA_Add_Porches_To_Output(
.o_Y(w_Y)
);
wire w_withinHPorch, w_withinVPorch, w_withinSync;
assign w_withinHPorch = (w_X < FRONT_PORCH_COUNT_X + ACTIVE_COLUMNS) ||
(w_X > TOTAL_COLUMNS - BACK_PORCH_COUNT_X - 1);
assign w_withinVPorch = (w_Y < FRONT_PORCH_COUNT_Y + ACTIVE_ROWS) ||
(w_Y > TOTAL_ROWS - BACK_PORCH_COUNT_Y - 1);
assign w_withinSync = (w_X > ACTIVE_COLUMNS) || (w_Y > ACTIVE_COLUMNS);
// https://web.mit.edu/6.111/www/s2004/NEWKIT/vga.shtml
always @(posedge i_Clk) begin
if (
(w_X < FRONT_PORCH_COUNT_X + ACTIVE_COLUMNS) ||
(w_X > TOTAL_COLUMNS - BACK_PORCH_COUNT_X - 1)
) begin
if (w_withinHPorch) begin
o_HSync <= 1;
end else begin
o_HSync <= w_HSync;
end
if (
(w_Y < FRONT_PORCH_COUNT_Y + ACTIVE_ROWS) ||
(w_Y > TOTAL_ROWS - BACK_PORCH_COUNT_Y - 1)
) begin
if (w_withinVPorch) begin
o_VSync <= 1;
end else begin
o_VSync <= w_VSync;
@ -84,8 +89,15 @@ module VGA_Add_Porches_To_Output(
r_Green <= i_Green;
r_Blue <= i_Blue;
o_Red <= r_Red;
o_Green <= r_Green;
o_Blue <= r_Blue;
// Ensure we never deliver color data during hsync/vsync
if (w_withinSync) begin
o_Red <= 0;
o_Green <= 0;
o_Blue <= 0;
end else begin
o_Red <= r_Red;
o_Green <= r_Green;
o_Blue <= r_Blue;
end
end
endmodule

View File

@ -10,11 +10,16 @@ module VGA_Current_Beam_Position(
output reg o_VSync = 0,
output reg [$clog2(TOTAL_COLUMNS)-1:0] o_X,
output reg [$clog2(TOTAL_ROWS)-1:0] o_Y
output reg [$clog2(TOTAL_ROWS)-1:0] o_Y,
output o_IsActiveArea
);
parameter TOTAL_COLUMNS = 800;
parameter TOTAL_ROWS = 525;
parameter ACTIVE_COLUMNS = 640;
parameter ACTIVE_ROWS = 480;
wire w_frameStart;
// forward these flip-flop style. use these instead of what
@ -44,4 +49,5 @@ module VGA_Current_Beam_Position(
// rising vsync == new frame
assign w_frameStart = (~o_VSync & i_VSync);
assign o_IsActiveArea = (o_X < ACTIVE_COLUMNS && o_Y < ACTIVE_COLUMNS);
endmodule

BIN
vga_image_renderer.bin Normal file

Binary file not shown.

81
vga_image_renderer.v Normal file
View File

@ -0,0 +1,81 @@
module VGAImageRenderer(
input i_Clk,
input i_HSync,
input i_VSync,
output o_HSync,
output o_VSync,
output [2:0] o_Red,
output [2:0] o_Green,
output [2:0] o_Blue
);
// sync signals
wire w_HSync_FromCurrentPos, w_VSync_FromCurrentPos;
wire w_IsActiveArea;
// screen location
wire [9:0] w_X, w_Y;
wire [6:0] w_CellX;
wire [5:0] w_CellY;
// ram reading
reg r_doImageRAMRead = 1;
reg r_doImageRAMWrite = 0;
wire w_imageRAMReadDataReady;
wire [4:0] w_imageRAMReadData;
wire [2:0] w_Red, w_Green, w_Blue;
VGA_Current_Beam_Position currentPos (
.i_Clk(i_Clk),
.i_HSync(i_HSync),
.i_VSync(i_VSync),
.o_HSync(w_HSync_FromCurrentPos),
.o_VSync(w_VSync_FromCurrentPos),
.o_X(w_X),
.o_Y(w_Y),
.o_IsActiveArea(w_IsActiveArea)
);
assign w_CellX = w_X[9:3];
assign w_CellY = w_Y[9:3];
// takes a tick, so add one to HSync/VSync
ImageRAM imageRam (
.i_Clk(i_Clk),
.i_ReadX(w_CellX),
.i_ReadY(w_CellY),
.i_doRead(r_doImageRAMRead),
.o_ReadDataReady(w_imageRAMReadDataReady),
.o_ReadData(w_imageRAMReadData),
.i_WriteX(),
.i_WriteY(),
.i_WriteData(),
.i_DoWrite(r_doImageRAMWrite),
.o_WriteComplete()
);
ImageIndexToColor palette (
.i_Clk(i_Clk),
.i_ColorIndex(w_imageRAMReadData),
.o_Red(w_Red),
.o_Green(w_Green),
.o_Blue(w_Blue),
.i_DoWrite(r_doImageRAMWrite),
.i_WriteColorIndex(),
.i_WriteColor_Red(),
.i_WriteColor_Green(),
.i_WriteColor_Blue(),
.o_WriteComplete()
);
assign o_Red = w_IsActiveArea ? w_Red : 0;
assign o_Green = w_IsActiveArea ? w_Green : 0;
assign o_Blue = w_IsActiveArea ? w_Blue : 0;
assign o_HSync = w_HSync_FromCurrentPos;
assign o_VSync = w_VSync_FromCurrentPos;
endmodule

BIN
vga_image_renderer_top.bin Normal file

Binary file not shown.

202
vga_image_renderer_top.v Normal file
View File

@ -0,0 +1,202 @@
module VGAImageRenderer_Top(
input i_Clk,
output o_VGA_HSync,
output o_VGA_VSync,
output o_VGA_Red_0,
output o_VGA_Red_1,
output o_VGA_Red_2,
output o_VGA_Grn_0,
output o_VGA_Grn_1,
output o_VGA_Grn_2,
output o_VGA_Blu_0,
output o_VGA_Blu_1,
output o_VGA_Blu_2
);
localparam TOTAL_COLUMNS = 800;
localparam TOTAL_ROWS = 525;
localparam ACTIVE_COLUMNS = 640;
localparam ACTIVE_ROWS = 480;
localparam VIDEO_WIDTH = 3;
wire w_HSync_FromPulseGenerator, w_VSync_FromPulseGenerator;
wire w_HSync_FromImageRenderer, w_VSync_FromImageRenderer;
wire w_HSync_FromPorchSync, w_VSync_FromPorchSync;
wire [2:0] w_Red_FromImageRenderer, w_Green_FromImageRenderer, w_Blue_FromImageRenderer;
wire [2:0] w_Red_FromPorchSync, w_Green_FromPorchSync, w_Blue_FromPorchSync;
VGA_Sync_Pulse_Generator #(
.TOTAL_COLUMNS(TOTAL_COLUMNS),
.TOTAL_ROWS(TOTAL_ROWS),
.ACTIVE_COLUMNS(ACTIVE_COLUMNS),
.ACTIVE_ROWS(ACTIVE_ROWS)
) pulseGenerator (
.i_Clk(i_Clk),
.o_HSync(w_HSync_FromPulseGenerator),
.o_VSync(w_VSync_FromPulseGenerator),
.o_rawX(),
.o_rawX()
);
VGAImageRenderer imageRenderer (
.i_Clk(i_Clk),
.i_HSync(w_HSync_FromPulseGenerator),
.i_VSync(w_VSync_FromPulseGenerator),
.o_HSync(w_HSync_FromImageRenderer),
.o_VSync(w_VSync_FromImageRenderer),
.o_Red(w_Red_FromImageRenderer),
.o_Green(w_Green_FromImageRenderer),
.o_Blue(w_Blue_FromImageRenderer)
);
wire w_HSync_FromImageDimmer, w_VSync_FromImageDimmer;
wire [2:0] w_Red_FromImageDimmer, w_Green_FromImageDimmer, w_Blue_FromImageDimmer;
ImageMovingSpotlight imageDimmer (
.i_Clk(i_Clk),
.i_HSync(w_HSync_FromImageRenderer),
.i_VSync(w_VSync_FromImageRenderer),
.i_Red(w_Red_FromImageRenderer),
.i_Green(w_Green_FromImageRenderer),
.i_Blue(w_Blue_FromImageRenderer),
.o_HSync(w_HSync_FromImageDimmer),
.o_VSync(w_VSync_FromImageDimmer),
.o_Red(w_Red_FromImageDimmer),
.o_Green(w_Green_FromImageDimmer),
.o_Blue(w_Blue_FromImageDimmer)
);
VGA_Add_Porches_To_Output #(
.VIDEO_WIDTH(VIDEO_WIDTH),
.TOTAL_COLUMNS(TOTAL_COLUMNS),
.TOTAL_ROWS(TOTAL_ROWS),
.ACTIVE_COLUMNS(ACTIVE_COLUMNS),
.ACTIVE_ROWS(ACTIVE_ROWS)
) PorchOutput (
.i_Clk(i_Clk),
.i_HSync(w_HSync_FromImageDimmer),
.i_VSync(w_VSync_FromImageDimmer),
.i_Red(w_Red_FromImageDimmer),
.i_Green(w_Green_FromImageDimmer),
.i_Blue(w_Blue_FromImageDimmer),
.o_HSync(w_HSync_FromPorchSync),
.o_VSync(w_VSync_FromPorchSync),
.o_Red(w_Red_FromPorchSync),
.o_Green(w_Green_FromPorchSync),
.o_Blue(w_Blue_FromPorchSync)
);
assign o_VGA_HSync = w_HSync_FromPorchSync;
assign o_VGA_VSync = w_VSync_FromPorchSync;
assign o_VGA_Red_0 = w_Red_FromPorchSync[0];
assign o_VGA_Red_1 = w_Red_FromPorchSync[1];
assign o_VGA_Red_2 = w_Red_FromPorchSync[2];
assign o_VGA_Grn_0 = w_Green_FromPorchSync[0];
assign o_VGA_Grn_1 = w_Green_FromPorchSync[1];
assign o_VGA_Grn_2 = w_Green_FromPorchSync[2];
assign o_VGA_Blu_0 = w_Blue_FromPorchSync[0];
assign o_VGA_Blu_1 = w_Blue_FromPorchSync[1];
assign o_VGA_Blu_2 = w_Blue_FromPorchSync[2];
endmodule
module ImageMovingSpotlight(
input i_Clk,
input i_HSync,
input i_VSync,
input [2:0] i_Red,
input [2:0] i_Green,
input [2:0] i_Blue,
output reg o_HSync,
output reg o_VSync,
output reg [2:0] o_Red,
output reg [2:0] o_Green,
output reg [2:0] o_Blue
);
parameter VIDEO_WIDTH = 3;
parameter TOTAL_COLUMNS = 800;
parameter TOTAL_ROWS = 525;
wire w_HSync, w_VSync;
wire [$clog2(TOTAL_COLUMNS)-1:0] w_X;
wire [$clog2(TOTAL_ROWS)-1:0] w_Y;
reg [$clog2(12500000)-1:0] r_counter = 0;
reg [VIDEO_WIDTH-1:0] r_Red = 0;
reg [VIDEO_WIDTH-1:0] r_Green = 0;
reg [VIDEO_WIDTH-1:0] r_Blue = 0;
reg [$clog2(TOTAL_COLUMNS)-1:0] r_currentX = 4;
reg [$clog2(TOTAL_ROWS)-1:0] r_currentY = 3;
VGA_Current_Beam_Position #(
.TOTAL_COLUMNS(TOTAL_COLUMNS),
.TOTAL_ROWS(TOTAL_ROWS)
) CurrentPosition (
.i_Clk(i_Clk),
.i_HSync(i_HSync),
.i_VSync(i_VSync),
.o_HSync(w_HSync),
.o_VSync(w_VSync),
.o_X(w_X),
.o_Y(w_Y)
);
wire [6:0] w_CellX;
wire [5:0] w_CellY;
assign w_CellX = w_X[9:3];
assign w_CellY = w_Y[9:3];
always @(posedge i_Clk) begin
if (r_counter == 25000000/16) begin
r_counter <= 0;
if (r_currentX == 80 - 1) begin
r_currentX <= 0;
end else begin
r_currentX <= r_currentX + 1;
end
end else begin
r_counter <= r_counter + 1;
end
end
always @(posedge i_Clk) begin
o_HSync <= w_HSync;
o_VSync <= w_VSync;
// if the pointer is right on the square, white
// if the pointer is within a square, brighten by {[0, 1], 1}
// otherwise return the current red
o_Red <= r_Red;
o_Green <= r_Green;
o_Blue <= r_Blue;
r_Red <= (r_currentX == w_CellX && r_currentY == w_CellY) ? 7 : i_Red;
r_Green <= (r_currentX == w_CellX && r_currentY == w_CellY) ? 7 : i_Green;
r_Blue <= (r_currentX == w_CellX && r_currentY == w_CellY) ? 7 : i_Blue;
/*
(r_currentX > 0 && w_X == r_currentX - 1 && r_currentY == w_Y) ? {i_Red[0:1], 1} :
(r_currentX < TOTAL_COLUMNS - 2 && w_X == r_currentX + 1 && r_currentY == w_Y) ? {i_Red[0:1], 1} :
(r_currentY > 0 && w_Y == r_currentY - 1 && r_currentX == w_X) ? {i_Red[0:1], 1} :
(r_currentY < TOTAL_ROWS - 2 && w_Y == r_currentY + 1 && r_currentX == w_X) ? {i_Red[0:1], 1} : i_Red;
*/
end
endmodule

View File

@ -168,12 +168,6 @@ module VGA_Tester(
.i_HSync(w_HSync_Start),
.i_VSync(w_VSync_Start),
.o_HSync(w_HSync_FromTestPattern),
.i_Clk(i_Clk),
.i_Pattern(r_currentPattern),
.i_HSync(w_HSync_Start),
.i_VSync(w_VSync_Start),
.o_HSync(w_HSync_FromTestPattern),
.o_VSync(w_VSync_FromTestPattern),
.o_Red(w_Red_FromTestPattern),