initial commit
This commit is contained in:
commit
59f7d5db2e
|
@ -0,0 +1,71 @@
|
||||||
|
# ##############################################################################
|
||||||
|
|
||||||
|
# iCEcube PCF
|
||||||
|
|
||||||
|
# Version: 2014.12.27052
|
||||||
|
|
||||||
|
# File Generated: Apr 27 2015 09:46:33
|
||||||
|
|
||||||
|
# Family & Device: iCE40HX1K
|
||||||
|
|
||||||
|
# Package: VQ100
|
||||||
|
|
||||||
|
# ##############################################################################
|
||||||
|
|
||||||
|
### Main FPGA Clock
|
||||||
|
set_io i_Clk 15
|
||||||
|
|
||||||
|
### LED Pins:
|
||||||
|
set_io o_LED_1 56
|
||||||
|
set_io o_LED_2 57
|
||||||
|
set_io o_LED_3 59
|
||||||
|
set_io o_LED_4 60
|
||||||
|
|
||||||
|
## Push-Button Switches
|
||||||
|
set_io i_Switch_1 53
|
||||||
|
set_io i_Switch_2 51
|
||||||
|
set_io i_Switch_3 54
|
||||||
|
set_io i_Switch_4 52
|
||||||
|
|
||||||
|
### 7 Segment Outputs
|
||||||
|
set_io o_Segment1_A 3
|
||||||
|
set_io o_Segment1_B 4
|
||||||
|
set_io o_Segment1_C 93
|
||||||
|
set_io o_Segment1_D 91
|
||||||
|
set_io o_Segment1_E 90
|
||||||
|
set_io o_Segment1_F 1
|
||||||
|
set_io o_Segment1_G 2
|
||||||
|
set_io o_Segment2_A 100
|
||||||
|
set_io o_Segment2_B 99
|
||||||
|
set_io o_Segment2_C 97
|
||||||
|
set_io o_Segment2_D 95
|
||||||
|
set_io o_Segment2_E 94
|
||||||
|
set_io o_Segment2_F 8
|
||||||
|
set_io o_Segment2_G 96
|
||||||
|
|
||||||
|
## UART Outputs
|
||||||
|
set_io i_UART_RX 73
|
||||||
|
set_io o_UART_TX 74
|
||||||
|
|
||||||
|
## VGA Outputs
|
||||||
|
set_io o_VGA_HSync 26
|
||||||
|
set_io o_VGA_VSync 27
|
||||||
|
set_io o_VGA_Red_0 36
|
||||||
|
set_io o_VGA_Red_1 37
|
||||||
|
set_io o_VGA_Red_2 40
|
||||||
|
set_io o_VGA_Grn_0 29
|
||||||
|
set_io o_VGA_Grn_1 30
|
||||||
|
set_io o_VGA_Grn_2 33
|
||||||
|
set_io o_VGA_Blu_0 28
|
||||||
|
set_io o_VGA_Blu_1 41
|
||||||
|
set_io o_VGA_Blu_2 42
|
||||||
|
|
||||||
|
## PMOD Signals
|
||||||
|
set_io io_PMOD_1 65
|
||||||
|
set_io io_PMOD_2 64
|
||||||
|
set_io io_PMOD_3 63
|
||||||
|
set_io io_PMOD_4 62
|
||||||
|
set_io io_PMOD_7 78
|
||||||
|
set_io io_PMOD_8 79
|
||||||
|
set_io io_PMOD_9 80
|
||||||
|
set_io io_PMOD_10 81
|
|
@ -0,0 +1,23 @@
|
||||||
|
CONSTRAINTS = ../Go_Board_Constraints.pcf
|
||||||
|
LED_TOGGLE = pong_runner.bin
|
||||||
|
|
||||||
|
install: $(LED_TOGGLE)
|
||||||
|
iceprog $(LED_TOGGLE)
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
iverilog -o test uart_rx_test.v uart_rx.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
|
||||||
|
|
||||||
|
.json.bitstream:
|
||||||
|
#nextpnr-ice40 --hx1k --freq 25 --pcf $(CONSTRAINTS) --json $*.json --package vq100 --asc $*.bitstream
|
||||||
|
nextpnr-ice40 --hx1k --freq 25 --pcf $(CONSTRAINTS) --json $*.json --package vq100 --asc $*.bitstream
|
||||||
|
|
||||||
|
.bitstream.bin:
|
||||||
|
icepack $*.bitstream $*.bin
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Go Board code reworking
|
||||||
|
|
||||||
|
This code is a reworking of the code for the [Go Board](https://nandland.com/the-go-board/)
|
||||||
|
FPGA beginner's board.
|
||||||
|
|
||||||
|
The original code comes from two sources:
|
||||||
|
|
||||||
|
* [Nandland Go Board tutorials](https://nandland.com/download-and-install-the-fpga-tools-and-drivers/)
|
||||||
|
* [Getting Started with FPGAs repo](https://github.com/nandland/getting-started-with-fpgas/)
|
||||||
|
|
||||||
|
Where possible I tried to:
|
||||||
|
|
||||||
|
* use more consistent variable and constant names
|
||||||
|
* fix missing inferred wires (the Pong project had a lot of these)
|
||||||
|
* avoid run-on lines of code
|
||||||
|
* avoid one-liner conditional bodies, opting for `begin...end` blocks everywhere
|
||||||
|
|
||||||
|
All of these can be built with [Yosys](https://github.com/YosysHQ/yosys)
|
||||||
|
and tested with [Icarus Verilog](https://github.com/steveicarus/iverilog). The `Makefile` is one I've been dragging along across all projects. It can fire off both a build-and-install to the Go Board, as well as run the test suite and open up [GTKWave](https://gtkwave.sourceforge.net/)
|
||||||
|
so you can inspect the signals. You do not need Lattive iCECube2 and you will have a hard time
|
||||||
|
getting it to run on modern Linux anyway!
|
||||||
|
|
||||||
|
`sipo_shift_register_test.sv` shows how to create your own `assert` for Icarus Verilog,
|
||||||
|
taken from an idea from here: https://stackoverflow.com/a/13906120
|
||||||
|
|
||||||
|
Have fun.
|
||||||
|
|
||||||
|
John
|
|
@ -0,0 +1,44 @@
|
||||||
|
module Binary_to_7_Segment(
|
||||||
|
input i_Clk,
|
||||||
|
input [$clog2(15)-1:0] i_Number,
|
||||||
|
output o_SegA,
|
||||||
|
output o_SegB,
|
||||||
|
output o_SegC,
|
||||||
|
output o_SegD,
|
||||||
|
output o_SegE,
|
||||||
|
output o_SegF,
|
||||||
|
output o_SegG
|
||||||
|
);
|
||||||
|
|
||||||
|
reg [6:0] r_HexEncoding;
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
case (i_Number)
|
||||||
|
0: r_HexEncoding <= 7'b1111110;
|
||||||
|
1: r_HexEncoding <= 7'b0110000;
|
||||||
|
2: r_HexEncoding <= 7'b1101101;
|
||||||
|
3: r_HexEncoding <= 7'b1111001;
|
||||||
|
4: r_HexEncoding <= 7'b0110011;
|
||||||
|
5: r_HexEncoding <= 7'b1011011;
|
||||||
|
6: r_HexEncoding <= 7'b1011111;
|
||||||
|
7: r_HexEncoding <= 7'b1110000;
|
||||||
|
8: r_HexEncoding <= 7'b1111111;
|
||||||
|
9: r_HexEncoding <= 7'b1111011;
|
||||||
|
10: r_HexEncoding <= 7'b1110111;
|
||||||
|
11: r_HexEncoding <= 7'b0011111;
|
||||||
|
12: r_HexEncoding <= 7'b1001110;
|
||||||
|
13: r_HexEncoding <= 7'b0111101;
|
||||||
|
14: r_HexEncoding <= 7'b1001111;
|
||||||
|
15: r_HexEncoding <= 7'b1000111;
|
||||||
|
default: r_HexEncoding <= 7'b0000000;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_SegA = r_HexEncoding[6];
|
||||||
|
assign o_SegB = r_HexEncoding[5];
|
||||||
|
assign o_SegC = r_HexEncoding[4];
|
||||||
|
assign o_SegD = r_HexEncoding[3];
|
||||||
|
assign o_SegE = r_HexEncoding[2];
|
||||||
|
assign o_SegF = r_HexEncoding[1];
|
||||||
|
assign o_SegG = r_HexEncoding[0];
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,22 @@
|
||||||
|
module Count_And_Toggle (
|
||||||
|
input i_Clk,
|
||||||
|
input i_Enable,
|
||||||
|
output reg o_Toggle
|
||||||
|
);
|
||||||
|
parameter COUNT_LIMIT = 10;
|
||||||
|
|
||||||
|
reg [$clog2(COUNT_LIMIT - 1):0] r_Counter;
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
if (i_Enable == 1) begin
|
||||||
|
if (r_Counter == COUNT_LIMIT - 1) begin
|
||||||
|
o_Toggle <= !o_Toggle;
|
||||||
|
r_Counter <= 0;
|
||||||
|
end else begin
|
||||||
|
r_Counter <= r_Counter + 1;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
o_Toggle <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -0,0 +1,30 @@
|
||||||
|
module Debounce_Filter
|
||||||
|
#(parameter DEBOUNCE_LIMIT = 20) (
|
||||||
|
input i_Clk,
|
||||||
|
input i_Bouncy,
|
||||||
|
output o_Debounced
|
||||||
|
);
|
||||||
|
|
||||||
|
reg [$clog2(DEBOUNCE_LIMIT)-1:0] r_Count = 0;
|
||||||
|
reg r_State = 1'b0;
|
||||||
|
|
||||||
|
always @(posedge i_Clk)
|
||||||
|
begin
|
||||||
|
if (i_Bouncy !== r_State && r_Count < DEBOUNCE_LIMIT - 1)
|
||||||
|
begin
|
||||||
|
r_Count <= r_Count + 1;
|
||||||
|
end
|
||||||
|
else if (r_Count == DEBOUNCE_LIMIT - 1)
|
||||||
|
begin
|
||||||
|
r_State <= i_Bouncy;
|
||||||
|
r_Count <= 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
r_Count <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_Debounced = r_State;
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,19 @@
|
||||||
|
module Debounce_Project_Top(
|
||||||
|
input i_Clk,
|
||||||
|
input i_Switch_1,
|
||||||
|
output o_LED_1
|
||||||
|
);
|
||||||
|
wire w_Debounced_Switch;
|
||||||
|
|
||||||
|
Debounce_Filter #(.DEBOUNCE_LIMIT(250000)) Debounce_Inst (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Bouncy(i_Switch_1),
|
||||||
|
.o_Debounced(w_Debounced_Switch)
|
||||||
|
);
|
||||||
|
|
||||||
|
LED_Toggle_Project LED_Toggle_Inst (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Switch_1(w_Debounced_Switch),
|
||||||
|
.o_LED_1(o_LED_1)
|
||||||
|
);
|
||||||
|
endmodule
|
|
@ -0,0 +1,14 @@
|
||||||
|
module Demux_1_to_4(
|
||||||
|
input i_Data,
|
||||||
|
input i_Sel0,
|
||||||
|
input i_Sel1,
|
||||||
|
output o_Data0,
|
||||||
|
output o_Data1,
|
||||||
|
output o_Data2,
|
||||||
|
output o_Data3
|
||||||
|
);
|
||||||
|
assign o_Data0 = i_Data & !i_Sel0 & !i_Sel1;
|
||||||
|
assign o_Data1 = i_Data & i_Sel0 & !i_Sel1;
|
||||||
|
assign o_Data2 = i_Data & !i_Sel0 & i_Sel1;
|
||||||
|
assign o_Data3 = i_Data & i_Sel0 & i_Sel1;
|
||||||
|
endmodule
|
|
@ -0,0 +1,180 @@
|
||||||
|
module FIFO(
|
||||||
|
input i_Clock,
|
||||||
|
|
||||||
|
input i_writeDataReady_Flash,
|
||||||
|
input [WIDTH_BITS-1:0] i_writeData,
|
||||||
|
input [$clog2(DEPTH_WORDS)-1:0] i_almostFullLevel,
|
||||||
|
output o_almostFull,
|
||||||
|
output o_Full,
|
||||||
|
|
||||||
|
input i_doRead_Flash,
|
||||||
|
output reg o_readDataReady,
|
||||||
|
output reg [WIDTH_BITS-1:0] o_readData,
|
||||||
|
input [$clog2(DEPTH_WORDS)-1:0] i_almostEmptyLevel,
|
||||||
|
output o_almostEmpty,
|
||||||
|
output o_Empty,
|
||||||
|
|
||||||
|
input i_Reset_Low
|
||||||
|
);
|
||||||
|
parameter WIDTH_BITS = 8;
|
||||||
|
parameter DEPTH_WORDS = 16;
|
||||||
|
|
||||||
|
reg [WIDTH_BITS-1:0] r_RAM [DEPTH_WORDS-1:0];
|
||||||
|
reg [$clog2(DEPTH_WORDS)-1:0] r_writeAddress;
|
||||||
|
reg [$clog2(DEPTH_WORDS)-1:0] r_readAddress;
|
||||||
|
reg [$clog2(DEPTH_WORDS)-1:0] r_Count;
|
||||||
|
|
||||||
|
always @(posedge i_Clock or negedge i_Reset_Low) begin
|
||||||
|
if (~i_Reset_Low) begin
|
||||||
|
r_writeAddress <= 0;
|
||||||
|
r_readAddress <= 0;
|
||||||
|
r_Count <= 0;
|
||||||
|
end else begin
|
||||||
|
if (i_writeDataReady_Flash) begin
|
||||||
|
r_RAM[r_writeAddress] <= i_writeData;
|
||||||
|
|
||||||
|
if (r_writeAddress == DEPTH_WORDS - 1) begin
|
||||||
|
r_writeAddress <= 0;
|
||||||
|
end else begin
|
||||||
|
r_writeAddress <= r_writeAddress + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i_doRead_Flash) begin
|
||||||
|
o_readData <= r_RAM[r_readAddress];
|
||||||
|
o_readDataReady <= i_doRead_Flash;
|
||||||
|
|
||||||
|
if (r_readAddress == DEPTH_WORDS - 1) begin
|
||||||
|
r_readAddress <= 0;
|
||||||
|
end else begin
|
||||||
|
r_readAddress <= r_readAddress + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i_doRead_Flash & ~i_writeDataReady_Flash) begin
|
||||||
|
if (r_Count != 0) begin
|
||||||
|
r_Count <= r_Count - 1;
|
||||||
|
end
|
||||||
|
end else if (i_writeDataReady_Flash & ~i_doRead_Flash) begin
|
||||||
|
if (r_Count != DEPTH_WORDS) begin
|
||||||
|
r_Count <= r_Count + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_Full = (
|
||||||
|
r_Count == DEPTH_WORDS
|
||||||
|
) || (
|
||||||
|
r_Count == DEPTH_WORDS-1 &&
|
||||||
|
i_writeDataReady_Flash &&
|
||||||
|
!i_doRead_Flash
|
||||||
|
);
|
||||||
|
assign o_Empty = (r_Count == 0);
|
||||||
|
|
||||||
|
assign o_almostFull = (r_Count > DEPTH_WORDS - i_almostFullLevel);
|
||||||
|
assign o_almostEmpty = (r_Count < i_almostEmptyLevel);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module TestFIFO();
|
||||||
|
reg r_Clk = 0;
|
||||||
|
|
||||||
|
always #1 r_Clk <= !r_Clk;
|
||||||
|
|
||||||
|
reg r_Reset_Low = 0;
|
||||||
|
|
||||||
|
reg r_writeDataReady_Flash = 0;
|
||||||
|
reg [7:0] r_writeData = 50;
|
||||||
|
reg [3:0] r_almostFullLevel = 4;
|
||||||
|
|
||||||
|
wire w_almostFull;
|
||||||
|
wire w_Full;
|
||||||
|
|
||||||
|
reg r_doReadFlash = 0;
|
||||||
|
wire w_readDataReady;
|
||||||
|
wire [7:0] w_readData;
|
||||||
|
reg [3:0] r_almostEmptyLevel = 4;
|
||||||
|
wire w_almostEmpty;
|
||||||
|
wire w_Empty;
|
||||||
|
|
||||||
|
FIFO myFifo(
|
||||||
|
.i_Clock(r_Clk),
|
||||||
|
.i_Reset_Low(r_Reset_Low),
|
||||||
|
|
||||||
|
.i_writeDataReady_Flash(r_writeDataReady_Flash),
|
||||||
|
.i_writeData(r_writeData),
|
||||||
|
.i_almostFullLevel(r_almostFullLevel),
|
||||||
|
.o_almostFull(w_almostFull),
|
||||||
|
.o_Full(w_Full),
|
||||||
|
|
||||||
|
.i_doRead_Flash(r_doReadFlash),
|
||||||
|
.o_readDataReady(w_readDataReady),
|
||||||
|
.o_readData(w_readData),
|
||||||
|
.i_almostEmptyLevel(r_almostEmptyLevel),
|
||||||
|
.o_almostEmpty(w_almostEmpty),
|
||||||
|
.o_Empty(w_Empty)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("test.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_Reset_Low <= 1;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_writeDataReady_Flash <= 1;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_writeDataReady_Flash <= 0;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_writeData = 69;
|
||||||
|
r_writeDataReady_Flash <= 1;
|
||||||
|
#2;
|
||||||
|
r_writeDataReady_Flash <= 0;
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_writeDataReady_Flash <= 1;
|
||||||
|
#2;
|
||||||
|
r_writeDataReady_Flash <= 0;
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_writeDataReady_Flash <= 1;
|
||||||
|
#2;
|
||||||
|
r_writeDataReady_Flash <= 0;
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_writeDataReady_Flash <= 1;
|
||||||
|
#2;
|
||||||
|
r_writeDataReady_Flash <= 0;
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_writeDataReady_Flash <= 1;
|
||||||
|
#2;
|
||||||
|
r_writeDataReady_Flash <= 0;
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_doReadFlash <= 1;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_doReadFlash <= 0;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_doReadFlash <= 1;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_doReadFlash <= 0;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -0,0 +1,20 @@
|
||||||
|
module LED_Toggle_Project(
|
||||||
|
input i_Clk,
|
||||||
|
input i_Switch_1,
|
||||||
|
output o_LED_1
|
||||||
|
);
|
||||||
|
reg r_LED_1 = 1'b0;
|
||||||
|
reg r_Switch_1 = 1'b0;
|
||||||
|
|
||||||
|
always @(posedge i_Clk)
|
||||||
|
begin
|
||||||
|
r_Switch_1 <= i_Switch_1;
|
||||||
|
|
||||||
|
if (i_Switch_1 == 1'b0 && r_Switch_1 == 1'b1)
|
||||||
|
begin
|
||||||
|
r_LED_1 <= ~r_LED_1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_LED_1 = r_LED_1;
|
||||||
|
endmodule
|
|
@ -0,0 +1,18 @@
|
||||||
|
module LFSR(
|
||||||
|
input i_Clk,
|
||||||
|
output [SIZE-1:0] o_LFSR_Data,
|
||||||
|
output o_LFSR_Done
|
||||||
|
);
|
||||||
|
parameter SIZE = 22;
|
||||||
|
|
||||||
|
reg [SIZE-1:0] r_LFSR;
|
||||||
|
wire w_XNOR;
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
r_LFSR <= {r_LFSR[SIZE-2:0], w_XNOR};
|
||||||
|
end
|
||||||
|
|
||||||
|
assign w_XNOR = r_LFSR[SIZE-1] ^~ r_LFSR[SIZE-2];
|
||||||
|
assign o_LFSR_Done = (r_LFSR == 0);
|
||||||
|
assign o_LFSR_Data = r_LFSR;
|
||||||
|
endmodule
|
|
@ -0,0 +1,181 @@
|
||||||
|
module Pong(
|
||||||
|
input i_Clk,
|
||||||
|
input i_HSync,
|
||||||
|
input i_VSync,
|
||||||
|
|
||||||
|
input i_GameStart,
|
||||||
|
|
||||||
|
input i_Player1_Up,
|
||||||
|
input i_Player1_Down,
|
||||||
|
input i_Player2_Up,
|
||||||
|
input i_Player2_Down,
|
||||||
|
|
||||||
|
output reg o_HSync,
|
||||||
|
output reg o_VSync,
|
||||||
|
output [2:0] o_Red,
|
||||||
|
output [2:0] o_Green,
|
||||||
|
output [2:0] o_Blue
|
||||||
|
);
|
||||||
|
parameter TOTAL_COLUMNS = 800;
|
||||||
|
parameter TOTAL_ROWS = 525;
|
||||||
|
|
||||||
|
parameter ACTIVE_COLUMNS = 640;
|
||||||
|
parameter ACTIVE_ROWS = 480;
|
||||||
|
|
||||||
|
localparam SCREEN_WIDTH_CELLS = 40;
|
||||||
|
localparam SCREEN_HEIGHT_CELLS = 30;
|
||||||
|
localparam SCORE_LIMIT = 9;
|
||||||
|
localparam PADDLE_HEIGHT = 6;
|
||||||
|
localparam PADDLE_PLAYER1_X = 0;
|
||||||
|
localparam PADDLE_PLAYER2_X = SCREEN_WIDTH_CELLS - 1;
|
||||||
|
|
||||||
|
localparam STATE_IDLE = 0;
|
||||||
|
localparam STATE_RUNNING = 1;
|
||||||
|
localparam STATE_P1_WINNER = 2;
|
||||||
|
localparam STATE_P2_WINNER = 3;
|
||||||
|
localparam STATE_CLEANUP = 4;
|
||||||
|
|
||||||
|
reg [2:0] r_currentState = STATE_IDLE;
|
||||||
|
|
||||||
|
wire w_HSync, w_VSync;
|
||||||
|
wire [9:0] w_X, w_Y;
|
||||||
|
|
||||||
|
wire w_P1_DoDrawPaddle, w_P2_DoDrawPaddle;
|
||||||
|
wire [5:0] w_P1_PaddleY, w_P2_PaddleY;
|
||||||
|
wire w_DoDrawBall, w_DrawAny;
|
||||||
|
wire [5:0] w_BallX, w_BallY;
|
||||||
|
wire w_IsGameActive;
|
||||||
|
|
||||||
|
reg [3:0] r_P1_Score = 0;
|
||||||
|
reg [3:0] r_P2_Score = 0;
|
||||||
|
|
||||||
|
wire [5:0] w_CellX, w_CellY;
|
||||||
|
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
o_HSync <= w_HSync;
|
||||||
|
o_VSync <= w_VSync;
|
||||||
|
end
|
||||||
|
|
||||||
|
// right shift 4
|
||||||
|
assign w_CellX = w_X[9:4];
|
||||||
|
assign w_CellY = w_Y[9:4];
|
||||||
|
|
||||||
|
// paddles
|
||||||
|
|
||||||
|
PongPaddle #(
|
||||||
|
.X_POS_CELLS(PADDLE_PLAYER1_X),
|
||||||
|
.SCREEN_HEIGHT_CELLS(SCREEN_HEIGHT_CELLS),
|
||||||
|
.PADDLE_HEIGHT_CELLS(PADDLE_HEIGHT)
|
||||||
|
) P1_Paddle (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_CellX(w_CellX),
|
||||||
|
.i_CellY(w_CellY),
|
||||||
|
.i_PaddleUp(i_Player1_Up),
|
||||||
|
.i_PaddleDown(i_Player1_Down),
|
||||||
|
.o_DoDrawPaddle(w_P1_DoDrawPaddle),
|
||||||
|
.o_PaddleY(w_P1_PaddleY)
|
||||||
|
);
|
||||||
|
|
||||||
|
PongPaddle #(
|
||||||
|
.X_POS_CELLS(PADDLE_PLAYER2_X),
|
||||||
|
.SCREEN_HEIGHT_CELLS(SCREEN_HEIGHT_CELLS),
|
||||||
|
.PADDLE_HEIGHT_CELLS(PADDLE_HEIGHT)
|
||||||
|
) P2_Paddle (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_CellX(w_CellX),
|
||||||
|
.i_CellY(w_CellY),
|
||||||
|
.i_PaddleUp(i_Player2_Up),
|
||||||
|
.i_PaddleDown(i_Player2_Down),
|
||||||
|
.o_DoDrawPaddle(w_P2_DoDrawPaddle),
|
||||||
|
.o_PaddleY(w_P2_PaddleY)
|
||||||
|
);
|
||||||
|
|
||||||
|
PongBall #(
|
||||||
|
.SCREEN_WIDTH_CELLS(SCREEN_WIDTH_CELLS),
|
||||||
|
.SCREEN_HEIGHT_CELLS(SCREEN_HEIGHT_CELLS)
|
||||||
|
) Ball (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_IsGameActive(w_IsGameActive),
|
||||||
|
.i_CellX(w_CellX),
|
||||||
|
.i_CellY(w_CellY),
|
||||||
|
.o_DoDrawBall(w_DoDrawBall),
|
||||||
|
.o_BallX(w_BallX),
|
||||||
|
.o_BallY(w_BallY)
|
||||||
|
);
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
case (r_currentState)
|
||||||
|
STATE_IDLE:
|
||||||
|
begin
|
||||||
|
if (i_GameStart) begin
|
||||||
|
r_currentState <= STATE_RUNNING;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_RUNNING:
|
||||||
|
begin
|
||||||
|
if (
|
||||||
|
w_BallX == 0 && (
|
||||||
|
w_BallY < w_P1_PaddleY ||
|
||||||
|
w_BallY > w_P1_PaddleY + PADDLE_HEIGHT
|
||||||
|
)
|
||||||
|
) begin
|
||||||
|
r_currentState <= STATE_P1_WINNER;
|
||||||
|
end else if (
|
||||||
|
w_BallX == SCREEN_WIDTH_CELLS - 1 && (
|
||||||
|
w_BallY < w_P2_PaddleY ||
|
||||||
|
w_BallY > w_P2_PaddleY + PADDLE_HEIGHT
|
||||||
|
)
|
||||||
|
) begin
|
||||||
|
r_currentState <= STATE_P2_WINNER;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_P1_WINNER:
|
||||||
|
begin
|
||||||
|
if (r_P1_Score == SCORE_LIMIT - 1) begin
|
||||||
|
r_P1_Score <= 0;
|
||||||
|
end else begin
|
||||||
|
r_P1_Score <= r_P1_Score + 1;
|
||||||
|
r_currentState <= STATE_CLEANUP;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_P2_WINNER:
|
||||||
|
begin
|
||||||
|
if (r_P2_Score == SCORE_LIMIT - 1) begin
|
||||||
|
r_P2_Score <= 0;
|
||||||
|
end else begin
|
||||||
|
r_P2_Score <= r_P2_Score + 1;
|
||||||
|
r_currentState <= STATE_CLEANUP;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_CLEANUP:
|
||||||
|
begin
|
||||||
|
r_currentState <= STATE_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign w_IsGameActive = (r_currentState == STATE_RUNNING) ? 1 : 0;
|
||||||
|
|
||||||
|
assign w_DrawAny = w_DoDrawBall | w_P1_DoDrawPaddle | w_P2_DoDrawPaddle;
|
||||||
|
|
||||||
|
assign o_Red = w_DrawAny ? 7 : 0;
|
||||||
|
assign o_Green = w_DrawAny ? 7 : 0;
|
||||||
|
assign o_Blue = w_DrawAny ? 7 : 0;
|
||||||
|
endmodule
|
|
@ -0,0 +1,70 @@
|
||||||
|
module PongBall (
|
||||||
|
input i_Clk,
|
||||||
|
input i_IsGameActive,
|
||||||
|
input [5:0] i_CellX,
|
||||||
|
input [5:0] i_CellY,
|
||||||
|
|
||||||
|
output reg o_DoDrawBall,
|
||||||
|
output reg [5:0] o_BallX,
|
||||||
|
output reg [5:0] o_BallY
|
||||||
|
);
|
||||||
|
parameter SCREEN_WIDTH_CELLS = 40;
|
||||||
|
parameter SCREEN_HEIGHT_CELLS = 30;
|
||||||
|
|
||||||
|
parameter CLOCKS_PER_SECOND = 25000000;
|
||||||
|
parameter BALL_MOVE_TIME_MS = 50;
|
||||||
|
parameter BALL_SPEED = 1250000;
|
||||||
|
|
||||||
|
reg [$clog2(BALL_SPEED)-1:0] r_ballMoveCount;
|
||||||
|
|
||||||
|
reg [5:0] r_PrevBallX;
|
||||||
|
reg [5:0] r_PrevBallY;
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
if (!i_IsGameActive) begin
|
||||||
|
o_BallX <= SCREEN_WIDTH_CELLS / 2;
|
||||||
|
o_BallY <= SCREEN_HEIGHT_CELLS / 2;
|
||||||
|
r_PrevBallX <= SCREEN_WIDTH_CELLS / 2 + 1;
|
||||||
|
r_PrevBallY <= SCREEN_HEIGHT_CELLS / 2 - 2;
|
||||||
|
end else begin
|
||||||
|
if (r_ballMoveCount < BALL_SPEED) begin
|
||||||
|
r_ballMoveCount <= r_ballMoveCount + 1;
|
||||||
|
end else begin
|
||||||
|
r_ballMoveCount <= 0;
|
||||||
|
|
||||||
|
r_PrevBallX <= o_BallX;
|
||||||
|
r_PrevBallY <= o_BallY;
|
||||||
|
|
||||||
|
if (
|
||||||
|
// at right edge, travelling right
|
||||||
|
(r_PrevBallX < o_BallX && o_BallX == SCREEN_WIDTH_CELLS - 1) ||
|
||||||
|
// not at left edge
|
||||||
|
(o_BallX < r_PrevBallX && o_BallX != 0)
|
||||||
|
) begin
|
||||||
|
o_BallX <= o_BallX - 1;
|
||||||
|
end else begin
|
||||||
|
o_BallX <= o_BallX + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (
|
||||||
|
// at bottom edge, travelling up
|
||||||
|
(r_PrevBallY < o_BallY && o_BallY == SCREEN_HEIGHT_CELLS - 1) ||
|
||||||
|
// not at left edge
|
||||||
|
(o_BallY < r_PrevBallY && o_BallY != 0)
|
||||||
|
) begin
|
||||||
|
o_BallY <= o_BallY - 1;
|
||||||
|
end else begin
|
||||||
|
o_BallY <= o_BallY + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
if (i_CellX == o_BallX && i_CellY == o_BallY) begin
|
||||||
|
o_DoDrawBall <= 1;
|
||||||
|
end else begin
|
||||||
|
o_DoDrawBall <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
* Paddles maintain their own location on the screen
|
||||||
|
*/
|
||||||
|
module PongPaddle (
|
||||||
|
input i_Clk,
|
||||||
|
input [5:0] i_CellX,
|
||||||
|
input [5:0] i_CellY,
|
||||||
|
input i_PaddleUp,
|
||||||
|
input i_PaddleDown,
|
||||||
|
|
||||||
|
output reg o_DoDrawPaddle,
|
||||||
|
output reg [5:0] o_PaddleY
|
||||||
|
);
|
||||||
|
parameter X_POS_CELLS = 0;
|
||||||
|
parameter PADDLE_HEIGHT_CELLS = 6;
|
||||||
|
parameter SCREEN_HEIGHT_CELLS = 30;
|
||||||
|
|
||||||
|
parameter CLOCKS_PER_SECOND = 25000000;
|
||||||
|
parameter PADDLE_MOVE_TIME_MS = 50;
|
||||||
|
// omg i can't get this
|
||||||
|
parameter integer PADDLE_SPEED = 1250000;
|
||||||
|
|
||||||
|
reg [$clog2(PADDLE_SPEED)-1:0] r_paddleMoveCount;
|
||||||
|
wire w_onlyOneButtonDown = i_PaddleUp ^ i_PaddleDown;
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
// handle end of move delay
|
||||||
|
if (w_onlyOneButtonDown) begin
|
||||||
|
if (r_paddleMoveCount == PADDLE_SPEED) begin
|
||||||
|
r_paddleMoveCount <= 0;
|
||||||
|
end else begin
|
||||||
|
r_paddleMoveCount <= r_paddleMoveCount + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (
|
||||||
|
i_PaddleUp &&
|
||||||
|
r_paddleMoveCount == PADDLE_SPEED &&
|
||||||
|
o_PaddleY > 0
|
||||||
|
) begin
|
||||||
|
o_PaddleY <= o_PaddleY - 1;
|
||||||
|
end else if (
|
||||||
|
i_PaddleDown &&
|
||||||
|
r_paddleMoveCount == PADDLE_SPEED &&
|
||||||
|
o_PaddleY < SCREEN_HEIGHT_CELLS - PADDLE_HEIGHT_CELLS - 1
|
||||||
|
) begin
|
||||||
|
o_PaddleY <= o_PaddleY + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (
|
||||||
|
i_CellX == X_POS_CELLS &&
|
||||||
|
i_CellY >= o_PaddleY &&
|
||||||
|
i_CellY <= o_PaddleY + PADDLE_HEIGHT_CELLS) begin
|
||||||
|
o_DoDrawPaddle <= 1;
|
||||||
|
end else begin
|
||||||
|
o_DoDrawPaddle <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -0,0 +1,142 @@
|
||||||
|
module PongRunner (
|
||||||
|
input i_Clk,
|
||||||
|
input i_UART_RX,
|
||||||
|
|
||||||
|
input i_Switch_1,
|
||||||
|
input i_Switch_2,
|
||||||
|
input i_Switch_3,
|
||||||
|
input i_Switch_4,
|
||||||
|
|
||||||
|
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 [VIDEO_WIDTH-1:0] w_Red_FromPong, w_Red_FromPorchSync;
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Green_FromPong, w_Green_FromPorchSync;
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Blue_FromPong, w_Blue_FromPorchSync;
|
||||||
|
|
||||||
|
wire w_dataReady;
|
||||||
|
wire w_HSync_Start, w_VSync_Start;
|
||||||
|
wire w_HSync_FromPong, w_VSync_FromPong;
|
||||||
|
wire w_HSync_FromPorchSync, w_VSync_FromPorchSync;
|
||||||
|
wire w_Switch_1_Debounced,
|
||||||
|
w_Switch_2_Debounced,
|
||||||
|
w_Switch_3_Debounced,
|
||||||
|
w_Switch_4_Debounced;
|
||||||
|
|
||||||
|
UART_RX #(
|
||||||
|
.CLOCKS_PER_SECOND(25000000),
|
||||||
|
.BAUD_RATE(115200)
|
||||||
|
) MyUART_RX (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_ReceiveBit(i_UART_RX),
|
||||||
|
.o_DataReady(w_dataReady),
|
||||||
|
.o_DataByte()
|
||||||
|
);
|
||||||
|
|
||||||
|
VGA_Sync_Pulse_Generator #(
|
||||||
|
.TOTAL_COLUMNS(TOTAL_COLUMNS),
|
||||||
|
.TOTAL_ROWS(TOTAL_ROWS),
|
||||||
|
.ACTIVE_COLUMNS(ACTIVE_COLUMNS),
|
||||||
|
.ACTIVE_ROWS(ACTIVE_ROWS)
|
||||||
|
) SyncGenerator (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.o_HSync(w_HSync_Start),
|
||||||
|
.o_VSync(w_VSync_Start),
|
||||||
|
.o_rawX(),
|
||||||
|
.o_rawY()
|
||||||
|
);
|
||||||
|
|
||||||
|
Debounce_Filter #(
|
||||||
|
.DEBOUNCE_LIMIT(25000000 / 25000)
|
||||||
|
) Debounce_Switch_1 (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Bouncy(i_Switch_1),
|
||||||
|
.o_Debounced(w_Switch_1_Debounced)
|
||||||
|
);
|
||||||
|
|
||||||
|
Debounce_Filter #(
|
||||||
|
.DEBOUNCE_LIMIT(25000000 / 25000)
|
||||||
|
) Debounce_Switch_2 (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Bouncy(i_Switch_2),
|
||||||
|
.o_Debounced(w_Switch_2_Debounced)
|
||||||
|
);
|
||||||
|
|
||||||
|
Debounce_Filter #(
|
||||||
|
.DEBOUNCE_LIMIT(25000000 / 25000)
|
||||||
|
) Debounce_Switch_3 (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Bouncy(i_Switch_3),
|
||||||
|
.o_Debounced(w_Switch_3_Debounced)
|
||||||
|
);
|
||||||
|
|
||||||
|
Debounce_Filter #(
|
||||||
|
.DEBOUNCE_LIMIT(25000000 / 25000)
|
||||||
|
) Debounce_Switch_4 (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Bouncy(i_Switch_4),
|
||||||
|
.o_Debounced(w_Switch_4_Debounced)
|
||||||
|
);
|
||||||
|
|
||||||
|
Pong #() MyPong (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_HSync(w_HSync_Start),
|
||||||
|
.i_VSync(w_VSync_Start),
|
||||||
|
.i_GameStart(w_dataReady),
|
||||||
|
.i_Player1_Up(w_Switch_1_Debounced),
|
||||||
|
.i_Player1_Down(w_Switch_2_Debounced),
|
||||||
|
.i_Player2_Up(w_Switch_3_Debounced),
|
||||||
|
.i_Player2_Down(w_Switch_4_Debounced),
|
||||||
|
.o_HSync(w_HSync_FromPong),
|
||||||
|
.o_VSync(w_VSync_FromPong),
|
||||||
|
.o_Red(w_Red_FromPong),
|
||||||
|
.o_Green(w_Green_FromPong),
|
||||||
|
.o_Blue(w_Blue_FromPong)
|
||||||
|
);
|
||||||
|
|
||||||
|
VGA_Add_Porches_To_Output #() PorchOutput (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_HSync(w_HSync_FromPong),
|
||||||
|
.i_VSync(w_VSync_FromPong),
|
||||||
|
.i_Red(w_Red_FromPong),
|
||||||
|
.i_Green(w_Green_FromPong),
|
||||||
|
.i_Blue(w_Blue_FromPong),
|
||||||
|
.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
|
|
@ -0,0 +1,77 @@
|
||||||
|
module RAM(
|
||||||
|
input i_writeClock,
|
||||||
|
input [$clog2(DEPTH_WORDS - 1):0] i_writeAddress,
|
||||||
|
input [WIDTH_BITS-1:0] i_writeData,
|
||||||
|
input i_writeDataValid,
|
||||||
|
|
||||||
|
input i_readClock,
|
||||||
|
input [$clog2(DEPTH_WORDS - 1):0] i_readAddress,
|
||||||
|
input i_doRead,
|
||||||
|
output reg o_dataValid,
|
||||||
|
output reg [WIDTH_BITS-1:0] o_readData
|
||||||
|
);
|
||||||
|
parameter WIDTH_BITS = 8;
|
||||||
|
parameter DEPTH_WORDS = 16;
|
||||||
|
|
||||||
|
reg [WIDTH_BITS-1:0] r_Memory[DEPTH_WORDS-1:0];
|
||||||
|
|
||||||
|
always @(posedge i_writeClock) begin
|
||||||
|
if (i_writeDataValid) begin
|
||||||
|
r_Memory[i_writeAddress] <= i_writeData;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge i_readClock) begin
|
||||||
|
o_readData <= r_Memory[i_readAddress];
|
||||||
|
o_dataValid <= i_doRead;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module TestRAM();
|
||||||
|
reg r_Clk = 0;
|
||||||
|
|
||||||
|
always #2 r_Clk <= !r_Clk;
|
||||||
|
|
||||||
|
reg [4:0] r_writeAddress = 1;
|
||||||
|
reg [7:0] r_writeData = 50;
|
||||||
|
reg r_writeDataValid = 0;
|
||||||
|
|
||||||
|
reg [4:0] r_readAddress = 1;
|
||||||
|
wire [7:0] w_readData;
|
||||||
|
reg r_doRead = 0;
|
||||||
|
wire w_dataValid;
|
||||||
|
|
||||||
|
RAM myRam (
|
||||||
|
.i_writeClock(r_Clk),
|
||||||
|
.i_writeAddress(r_writeAddress),
|
||||||
|
.i_writeData(r_writeData),
|
||||||
|
.i_writeDataValid(r_writeDataValid),
|
||||||
|
|
||||||
|
.i_readClock(r_Clk),
|
||||||
|
.i_readAddress(r_readAddress),
|
||||||
|
.i_doRead(r_doRead),
|
||||||
|
.o_dataValid(w_dataValid),
|
||||||
|
.o_readData(w_readData)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("test.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_writeDataValid <= 1;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_writeDataValid <= 0;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
r_doRead <= 1;
|
||||||
|
|
||||||
|
#2;
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -0,0 +1,103 @@
|
||||||
|
module Simon(
|
||||||
|
input i_Clk,
|
||||||
|
|
||||||
|
input i_Switch_1,
|
||||||
|
input i_Switch_2,
|
||||||
|
input i_Switch_3,
|
||||||
|
input i_Switch_4,
|
||||||
|
|
||||||
|
output o_LED_1,
|
||||||
|
output o_LED_2,
|
||||||
|
output o_LED_3,
|
||||||
|
output o_LED_4,
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
localparam GAME_LIMIT = 7;
|
||||||
|
localparam CLKS_PER_SECOND = 25000000;
|
||||||
|
localparam integer DEBOUNCE_LIMIT = CLKS_PER_SECOND * 0.001;
|
||||||
|
|
||||||
|
wire w_Switch_1, w_Switch_2, w_Switch_3, w_Switch_4;
|
||||||
|
wire [3:0] w_Score;
|
||||||
|
wire w_Segment2_A,
|
||||||
|
w_Segment2_B,
|
||||||
|
w_Segment2_C,
|
||||||
|
w_Segment2_D,
|
||||||
|
w_Segment2_E,
|
||||||
|
w_Segment2_F,
|
||||||
|
w_Segment2_G;
|
||||||
|
|
||||||
|
Debounce_Filter #(
|
||||||
|
.DEBOUNCE_LIMIT(DEBOUNCE_LIMIT)
|
||||||
|
) Debounce_Switch_1 (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Bouncy(i_Switch_1),
|
||||||
|
.o_Debounced(w_Switch_1)
|
||||||
|
);
|
||||||
|
|
||||||
|
Debounce_Filter #(
|
||||||
|
.DEBOUNCE_LIMIT(DEBOUNCE_LIMIT)
|
||||||
|
) Debounce_Switch_2 (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Bouncy(i_Switch_2),
|
||||||
|
.o_Debounced(w_Switch_2)
|
||||||
|
);
|
||||||
|
|
||||||
|
Debounce_Filter #(
|
||||||
|
.DEBOUNCE_LIMIT(DEBOUNCE_LIMIT)
|
||||||
|
) Debounce_Switch_3 (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Bouncy(i_Switch_3),
|
||||||
|
.o_Debounced(w_Switch_3)
|
||||||
|
);
|
||||||
|
|
||||||
|
Debounce_Filter #(
|
||||||
|
.DEBOUNCE_LIMIT(DEBOUNCE_LIMIT)
|
||||||
|
) Debounce_Switch_4 (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Bouncy(i_Switch_4),
|
||||||
|
.o_Debounced(w_Switch_4)
|
||||||
|
);
|
||||||
|
|
||||||
|
Simon_Game #(
|
||||||
|
.CLKS_PER_SECOND(CLKS_PER_SECOND),
|
||||||
|
.GAME_LIMIT(GAME_LIMIT)
|
||||||
|
) Simon_Game_Instance (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Switch_1(w_Switch_1),
|
||||||
|
.i_Switch_2(w_Switch_2),
|
||||||
|
.i_Switch_3(w_Switch_3),
|
||||||
|
.i_Switch_4(w_Switch_4),
|
||||||
|
.o_Score(w_Score),
|
||||||
|
.o_LED_1(o_LED_1),
|
||||||
|
.o_LED_2(o_LED_2),
|
||||||
|
.o_LED_3(o_LED_3),
|
||||||
|
.o_LED_4(o_LED_4)
|
||||||
|
);
|
||||||
|
|
||||||
|
Binary_to_7_Segment Scoreboard (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Number(w_Score),
|
||||||
|
.o_SegA(w_Segment2_A),
|
||||||
|
.o_SegB(w_Segment2_B),
|
||||||
|
.o_SegC(w_Segment2_C),
|
||||||
|
.o_SegD(w_Segment2_D),
|
||||||
|
.o_SegE(w_Segment2_E),
|
||||||
|
.o_SegF(w_Segment2_F),
|
||||||
|
.o_SegG(w_Segment2_G)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign o_Segment2_A = !w_Segment2_A;
|
||||||
|
assign o_Segment2_B = !w_Segment2_B;
|
||||||
|
assign o_Segment2_C = !w_Segment2_C;
|
||||||
|
assign o_Segment2_D = !w_Segment2_D;
|
||||||
|
assign o_Segment2_E = !w_Segment2_E;
|
||||||
|
assign o_Segment2_F = !w_Segment2_F;
|
||||||
|
assign o_Segment2_G = !w_Segment2_G;
|
||||||
|
endmodule
|
|
@ -0,0 +1,208 @@
|
||||||
|
module Simon_Game (
|
||||||
|
input i_Clk,
|
||||||
|
|
||||||
|
input i_Switch_1,
|
||||||
|
input i_Switch_2,
|
||||||
|
input i_Switch_3,
|
||||||
|
input i_Switch_4,
|
||||||
|
|
||||||
|
output reg [3:0] o_Score,
|
||||||
|
|
||||||
|
output o_LED_1,
|
||||||
|
output o_LED_2,
|
||||||
|
output o_LED_3,
|
||||||
|
output o_LED_4
|
||||||
|
);
|
||||||
|
parameter CLKS_PER_SECOND = 25000000;
|
||||||
|
parameter GAME_LIMIT = 6;
|
||||||
|
|
||||||
|
localparam START = 3'd0;
|
||||||
|
localparam PATTERN_OFF = 3'd1;
|
||||||
|
localparam PATTERN_SHOW = 3'd2;
|
||||||
|
localparam WAIT_PLAYER = 3'd3;
|
||||||
|
localparam INCREMENT_SCORE = 3'd4;
|
||||||
|
localparam PLAYER_LOST = 3'd5;
|
||||||
|
localparam PLAYER_WON = 3'd6;
|
||||||
|
|
||||||
|
reg [2:0] r_currentState;
|
||||||
|
|
||||||
|
// count and toggle results
|
||||||
|
wire w_IncomingDelay;
|
||||||
|
reg r_DelayCompleted;
|
||||||
|
wire w_EnableCounter;
|
||||||
|
|
||||||
|
// user input handling
|
||||||
|
reg r_Switch_1, r_Switch_2, r_Switch_3, r_Switch_4;
|
||||||
|
reg r_Button_notDown;
|
||||||
|
reg [1:0] r_currentButtonDown;
|
||||||
|
|
||||||
|
// game pattern & construction
|
||||||
|
reg [1:0] r_LEDPattern [0:10];
|
||||||
|
wire [21:0] w_LFSR_Data;
|
||||||
|
reg [$clog2(GAME_LIMIT)-1:0] r_currentLEDPattern;
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
if (i_Switch_1 & i_Switch_2) begin
|
||||||
|
r_currentState <= START;
|
||||||
|
end else begin
|
||||||
|
case (r_currentState)
|
||||||
|
START:
|
||||||
|
begin
|
||||||
|
if (!i_Switch_1 & !i_Switch_2 & r_Button_notDown) begin
|
||||||
|
o_Score <= 0;
|
||||||
|
r_currentLEDPattern <= 0;
|
||||||
|
r_currentState <= PATTERN_OFF;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
PATTERN_OFF:
|
||||||
|
begin
|
||||||
|
if (!w_IncomingDelay & r_DelayCompleted) begin
|
||||||
|
r_currentState <= PATTERN_SHOW;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
PATTERN_SHOW:
|
||||||
|
begin
|
||||||
|
if (!w_IncomingDelay & r_DelayCompleted) begin
|
||||||
|
// this limits the number of
|
||||||
|
if (o_Score == r_currentLEDPattern) begin
|
||||||
|
r_currentLEDPattern <= 0;
|
||||||
|
r_currentState <= WAIT_PLAYER;
|
||||||
|
end else begin
|
||||||
|
r_currentLEDPattern <= r_currentLEDPattern + 1;
|
||||||
|
r_currentState <= PATTERN_OFF;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
WAIT_PLAYER:
|
||||||
|
begin
|
||||||
|
if (r_Button_notDown) begin
|
||||||
|
if (
|
||||||
|
r_LEDPattern[r_currentLEDPattern] == r_currentButtonDown &&
|
||||||
|
o_Score == r_currentLEDPattern
|
||||||
|
) begin
|
||||||
|
r_currentLEDPattern <= 0;
|
||||||
|
r_currentState <= INCREMENT_SCORE;
|
||||||
|
end else if (
|
||||||
|
r_LEDPattern[r_currentLEDPattern] != r_currentButtonDown
|
||||||
|
) begin
|
||||||
|
r_currentState <= PLAYER_LOST;
|
||||||
|
end else begin
|
||||||
|
r_currentLEDPattern <= r_currentLEDPattern + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
INCREMENT_SCORE:
|
||||||
|
begin
|
||||||
|
o_Score <= o_Score + 1;
|
||||||
|
if (o_Score == GAME_LIMIT - 1) begin
|
||||||
|
r_currentState <= PLAYER_WON;
|
||||||
|
end else begin
|
||||||
|
r_currentState <= PATTERN_OFF;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
PLAYER_WON:
|
||||||
|
begin
|
||||||
|
o_Score <= 4'hA;
|
||||||
|
end
|
||||||
|
|
||||||
|
PLAYER_LOST:
|
||||||
|
begin
|
||||||
|
o_Score <= 4'hF;
|
||||||
|
end
|
||||||
|
|
||||||
|
default:
|
||||||
|
begin
|
||||||
|
r_currentState <= START;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
if (r_currentState == START) begin
|
||||||
|
r_LEDPattern[0] <= w_LFSR_Data[1:0];
|
||||||
|
r_LEDPattern[1] <= w_LFSR_Data[3:2];
|
||||||
|
r_LEDPattern[2] <= w_LFSR_Data[5:4];
|
||||||
|
r_LEDPattern[3] <= w_LFSR_Data[7:6];
|
||||||
|
r_LEDPattern[4] <= w_LFSR_Data[9:8];
|
||||||
|
r_LEDPattern[5] <= w_LFSR_Data[11:10];
|
||||||
|
r_LEDPattern[6] <= w_LFSR_Data[13:12];
|
||||||
|
r_LEDPattern[7] <= w_LFSR_Data[15:14];
|
||||||
|
r_LEDPattern[8] <= w_LFSR_Data[17:16];
|
||||||
|
r_LEDPattern[9] <= w_LFSR_Data[19:18];
|
||||||
|
r_LEDPattern[10] <= w_LFSR_Data[21:20];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_LED_1 = (
|
||||||
|
(r_currentState == PATTERN_SHOW && r_LEDPattern[r_currentLEDPattern] == 0) ?
|
||||||
|
1 :
|
||||||
|
i_Switch_1
|
||||||
|
);
|
||||||
|
|
||||||
|
assign o_LED_2 = (
|
||||||
|
(r_currentState == PATTERN_SHOW && r_LEDPattern[r_currentLEDPattern] == 1) ?
|
||||||
|
1 :
|
||||||
|
i_Switch_2
|
||||||
|
);
|
||||||
|
|
||||||
|
assign o_LED_3 = (
|
||||||
|
(r_currentState == PATTERN_SHOW && r_LEDPattern[r_currentLEDPattern] == 2) ?
|
||||||
|
1 :
|
||||||
|
i_Switch_3
|
||||||
|
);
|
||||||
|
|
||||||
|
assign o_LED_4 = (
|
||||||
|
(r_currentState == PATTERN_SHOW && r_LEDPattern[r_currentLEDPattern] == 3) ?
|
||||||
|
1 :
|
||||||
|
i_Switch_4
|
||||||
|
);
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
r_DelayCompleted <= w_IncomingDelay;
|
||||||
|
r_Switch_1 <= i_Switch_1;
|
||||||
|
r_Switch_2 <= i_Switch_2;
|
||||||
|
r_Switch_3 <= i_Switch_3;
|
||||||
|
r_Switch_4 <= i_Switch_4;
|
||||||
|
|
||||||
|
if (r_Switch_1 && !i_Switch_1) begin
|
||||||
|
r_Button_notDown <= 1;
|
||||||
|
r_currentButtonDown <= 0;
|
||||||
|
end else if (r_Switch_2 && !i_Switch_2) begin
|
||||||
|
r_Button_notDown <= 1;
|
||||||
|
r_currentButtonDown <= 1;
|
||||||
|
end else if (r_Switch_3 && !i_Switch_3) begin
|
||||||
|
r_Button_notDown <= 1;
|
||||||
|
r_currentButtonDown <= 2;
|
||||||
|
end else if (r_Switch_4 && !i_Switch_4) begin
|
||||||
|
r_Button_notDown <= 1;
|
||||||
|
r_currentButtonDown <= 3;
|
||||||
|
end else begin
|
||||||
|
r_Button_notDown <= 0;
|
||||||
|
r_currentButtonDown <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign w_EnableCounter = (r_currentState == PATTERN_SHOW || r_currentState == PATTERN_OFF);
|
||||||
|
|
||||||
|
Count_And_Toggle #(
|
||||||
|
.COUNT_LIMIT(CLKS_PER_SECOND/4)
|
||||||
|
) Counter (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Enable(w_EnableCounter),
|
||||||
|
.o_Toggle(w_IncomingDelay)
|
||||||
|
);
|
||||||
|
|
||||||
|
LFSR #(
|
||||||
|
.SIZE(22)
|
||||||
|
) MyLFSR (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.o_LFSR_Data(w_LFSR_Data),
|
||||||
|
.o_LFSR_Done()
|
||||||
|
);
|
||||||
|
endmodule
|
|
@ -0,0 +1,104 @@
|
||||||
|
module SiPo_ShiftRegister_4(
|
||||||
|
input i_Clk,
|
||||||
|
input i_Latch,
|
||||||
|
input i_Data,
|
||||||
|
input i_Reset,
|
||||||
|
output o_Data0,
|
||||||
|
output o_Data1,
|
||||||
|
output o_Data2,
|
||||||
|
output o_Data3
|
||||||
|
);
|
||||||
|
reg [3:0] r_Data;
|
||||||
|
reg [3:0] r_Incoming;
|
||||||
|
reg [2:0] r_Pos;
|
||||||
|
reg r_didLatch;
|
||||||
|
|
||||||
|
always @ (posedge i_Clk & i_Reset) begin
|
||||||
|
r_Data <= 0;
|
||||||
|
r_Incoming <= 0;
|
||||||
|
r_Pos <= 0;
|
||||||
|
r_didLatch <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge i_Clk) begin
|
||||||
|
if (i_Latch & !r_didLatch) begin
|
||||||
|
r_Incoming[0] <= i_Data;
|
||||||
|
r_Incoming[3:1] <= r_Incoming[2:0];
|
||||||
|
r_Pos <= r_Pos + 1;
|
||||||
|
r_didLatch <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (r_didLatch & !i_Latch) begin
|
||||||
|
r_didLatch <= 0;
|
||||||
|
|
||||||
|
if (r_Pos == 4) begin
|
||||||
|
r_Data[3:0] <= r_Incoming[3:0];
|
||||||
|
r_Incoming <= 0;
|
||||||
|
r_Pos <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_Data0 = r_Data[0];
|
||||||
|
assign o_Data1 = r_Data[1];
|
||||||
|
assign o_Data2 = r_Data[2];
|
||||||
|
assign o_Data3 = r_Data[3];
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module Test_SIPO();
|
||||||
|
task assert(input condition);
|
||||||
|
if (!condition) $error;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
reg r_Data = 1'b0, r_Clk = 1'b0, r_Latch = 1'b0, r_Reset = 1'b0;
|
||||||
|
wire w_Data0, w_Data1, w_Data2, w_Data3;
|
||||||
|
|
||||||
|
always #2 r_Clk <= !r_Clk;
|
||||||
|
|
||||||
|
SiPo_ShiftRegister_4 UUT(
|
||||||
|
.i_Clk(r_Clk),
|
||||||
|
.i_Data(r_Data),
|
||||||
|
.i_Latch(r_Latch),
|
||||||
|
.i_Reset(r_Reset),
|
||||||
|
.o_Data0(w_Data0),
|
||||||
|
.o_Data1(w_Data1),
|
||||||
|
.o_Data2(w_Data2),
|
||||||
|
.o_Data3(w_Data3)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("test.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
|
||||||
|
r_Data <= 1'b1;
|
||||||
|
r_Reset <= 1'b1;
|
||||||
|
@(posedge r_Clk);
|
||||||
|
|
||||||
|
r_Reset <= 1'b0;
|
||||||
|
@(posedge r_Clk);
|
||||||
|
|
||||||
|
r_Latch <= 1'b1;
|
||||||
|
@(posedge r_Clk);
|
||||||
|
r_Latch <= 1'b0;
|
||||||
|
@(posedge r_Clk);
|
||||||
|
|
||||||
|
r_Data <= 0;
|
||||||
|
r_Latch <= 1'b1;
|
||||||
|
@(posedge r_Clk);
|
||||||
|
r_Latch <= 1'b0;
|
||||||
|
@(posedge r_Clk);
|
||||||
|
r_Latch <= 1'b1;
|
||||||
|
@(posedge r_Clk);
|
||||||
|
r_Latch <= 1'b0;
|
||||||
|
@(posedge r_Clk);
|
||||||
|
r_Data <= 1;
|
||||||
|
r_Latch <= 1'b1;
|
||||||
|
@(posedge r_Clk);
|
||||||
|
r_Latch <= 1'b0;
|
||||||
|
@(posedge r_Clk);
|
||||||
|
|
||||||
|
#5;
|
||||||
|
|
||||||
|
$finish();
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -0,0 +1,100 @@
|
||||||
|
module UART_RX (
|
||||||
|
input i_Clk,
|
||||||
|
input i_ReceiveBit,
|
||||||
|
output o_DataReady,
|
||||||
|
output [7:0] o_DataByte
|
||||||
|
);
|
||||||
|
parameter CLOCKS_PER_SECOND = 25000000;
|
||||||
|
parameter BAUD_RATE = 115200;
|
||||||
|
localparam integer CLOCKS_PER_BIT = CLOCKS_PER_SECOND / BAUD_RATE;
|
||||||
|
localparam integer HALF_CLOCKS_PER_BIT = (CLOCKS_PER_BIT - 1) / 2;
|
||||||
|
|
||||||
|
localparam IDLE = 0;
|
||||||
|
localparam VERIFY_START_BIT = 1;
|
||||||
|
localparam READ_DATA_BITS = 2;
|
||||||
|
localparam WAIT_FOR_STOP_BIT = 3;
|
||||||
|
localparam CLEANUP = 4;
|
||||||
|
|
||||||
|
// golang-style: lowercase is private, uppercase is public
|
||||||
|
reg [$clog2(CLEANUP)-1:0] r_currentState = IDLE;
|
||||||
|
|
||||||
|
reg r_dataReady = 0;
|
||||||
|
reg [$clog2(CLOCKS_PER_BIT)-1:0] r_clockCount = 0;
|
||||||
|
reg [$clog2(8)-1:0] r_bitIndex = 0;
|
||||||
|
reg [7:0] r_receivedByte = 0;
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
case (r_currentState)
|
||||||
|
IDLE:
|
||||||
|
begin
|
||||||
|
r_dataReady <= 0;
|
||||||
|
r_clockCount <= 0;
|
||||||
|
r_bitIndex <= 0;
|
||||||
|
|
||||||
|
if (i_ReceiveBit == 0) begin
|
||||||
|
r_currentState <= VERIFY_START_BIT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Check the middle of the start bit to make sure it's still low
|
||||||
|
VERIFY_START_BIT:
|
||||||
|
begin
|
||||||
|
if (r_clockCount == HALF_CLOCKS_PER_BIT) begin
|
||||||
|
// still low, let's go
|
||||||
|
if (i_ReceiveBit == 0) begin
|
||||||
|
r_clockCount <= 0;
|
||||||
|
r_currentState <= READ_DATA_BITS;
|
||||||
|
end else begin
|
||||||
|
r_currentState <= IDLE;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
r_clockCount <= r_clockCount + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// note that we are still in the halfway points of the signal at this
|
||||||
|
// point. we are sampling the very middles.
|
||||||
|
READ_DATA_BITS:
|
||||||
|
begin
|
||||||
|
if (r_clockCount < CLOCKS_PER_BIT - 1) begin
|
||||||
|
r_clockCount <= r_clockCount + 1;
|
||||||
|
end else begin
|
||||||
|
r_clockCount <= 0;
|
||||||
|
r_receivedByte[r_bitIndex] <= i_ReceiveBit;
|
||||||
|
|
||||||
|
if (r_bitIndex == 7) begin
|
||||||
|
r_bitIndex <= 0;
|
||||||
|
r_currentState <= WAIT_FOR_STOP_BIT;
|
||||||
|
end else begin
|
||||||
|
r_bitIndex <= r_bitIndex + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
WAIT_FOR_STOP_BIT:
|
||||||
|
begin
|
||||||
|
if (r_clockCount < CLOCKS_PER_BIT - 1) begin
|
||||||
|
r_clockCount <= r_clockCount + 1;
|
||||||
|
end else begin
|
||||||
|
r_dataReady <= 1;
|
||||||
|
r_clockCount <= 0;
|
||||||
|
r_currentState <= CLEANUP;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
CLEANUP:
|
||||||
|
begin
|
||||||
|
r_currentState <= IDLE;
|
||||||
|
r_dataReady <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
default:
|
||||||
|
begin
|
||||||
|
r_currentState <= IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_DataByte = r_receivedByte;
|
||||||
|
assign o_DataReady = r_dataReady;
|
||||||
|
endmodule
|
|
@ -0,0 +1,98 @@
|
||||||
|
module UART_TX (
|
||||||
|
input i_Reset_Low,
|
||||||
|
input i_Clk,
|
||||||
|
input i_TransmitReady,
|
||||||
|
input [7:0] i_TransmitByte,
|
||||||
|
|
||||||
|
output reg o_Active,
|
||||||
|
output reg o_Output,
|
||||||
|
output reg o_Done
|
||||||
|
);
|
||||||
|
parameter CLOCKS_PER_SECOND = 25000000;
|
||||||
|
parameter BAUD_RATE = 115200;
|
||||||
|
localparam integer CLOCKS_PER_BIT = CLOCKS_PER_SECOND / BAUD_RATE;
|
||||||
|
|
||||||
|
localparam IDLE = 0;
|
||||||
|
localparam SEND_START_BIT = 1;
|
||||||
|
localparam SEND_DATA_BITS = 2;
|
||||||
|
localparam SEND_STOP_BIT = 3;
|
||||||
|
|
||||||
|
reg [$clog2(SEND_STOP_BIT)-1:0] r_currentState = IDLE;
|
||||||
|
reg [$clog2(CLOCKS_PER_BIT)-1:0] r_clockCount = 0;
|
||||||
|
reg [$clog2(8)-1:0] r_bitIndex = 0;
|
||||||
|
reg [7:0] r_transmitData;
|
||||||
|
|
||||||
|
always @(posedge i_Clk or negedge i_Reset_Low) begin
|
||||||
|
if (!i_Reset_Low) begin
|
||||||
|
r_currentState <= IDLE;
|
||||||
|
end else begin
|
||||||
|
o_Done <= 0;
|
||||||
|
|
||||||
|
case (r_currentState)
|
||||||
|
IDLE:
|
||||||
|
begin
|
||||||
|
// Drive line high for idle
|
||||||
|
o_Output <= 1;
|
||||||
|
r_clockCount <= 0;
|
||||||
|
r_bitIndex <= 0;
|
||||||
|
|
||||||
|
if (i_TransmitReady) begin
|
||||||
|
o_Active <= 1;
|
||||||
|
r_transmitData <= i_TransmitByte;
|
||||||
|
r_currentState <= SEND_START_BIT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
SEND_START_BIT:
|
||||||
|
begin
|
||||||
|
o_Output <= 0;
|
||||||
|
|
||||||
|
if (r_clockCount < CLOCKS_PER_BIT - 1) begin
|
||||||
|
r_clockCount <= r_clockCount + 1;
|
||||||
|
end else begin
|
||||||
|
r_clockCount <= 0;
|
||||||
|
r_currentState <= SEND_DATA_BITS;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
SEND_DATA_BITS:
|
||||||
|
begin
|
||||||
|
o_Output <= r_transmitData[r_bitIndex];
|
||||||
|
|
||||||
|
if (r_clockCount < CLOCKS_PER_BIT - 1) begin
|
||||||
|
r_clockCount <= r_clockCount + 1;
|
||||||
|
end else begin
|
||||||
|
r_clockCount <= 0;
|
||||||
|
|
||||||
|
if (r_bitIndex == 7) begin
|
||||||
|
r_bitIndex <= 0;
|
||||||
|
r_currentState <= SEND_STOP_BIT;
|
||||||
|
end else begin
|
||||||
|
r_bitIndex <= r_bitIndex + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
SEND_STOP_BIT:
|
||||||
|
begin
|
||||||
|
o_Output <= 1;
|
||||||
|
|
||||||
|
if (r_clockCount < CLOCKS_PER_BIT - 1) begin
|
||||||
|
r_clockCount <= r_clockCount + 1;
|
||||||
|
end else begin
|
||||||
|
o_Done <= 1;
|
||||||
|
r_clockCount <= 0;
|
||||||
|
r_currentState <= IDLE;
|
||||||
|
o_Output <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default:
|
||||||
|
begin
|
||||||
|
r_currentState <= IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
/**
|
||||||
|
* The output is buffered as the front/back porches are added, so watch your
|
||||||
|
* timing for other stuff.
|
||||||
|
*/
|
||||||
|
module VGA_Add_Porches_To_Output(
|
||||||
|
input i_Clk,
|
||||||
|
input i_HSync,
|
||||||
|
input i_VSync,
|
||||||
|
input [VIDEO_WIDTH-1:0] i_Red,
|
||||||
|
input [VIDEO_WIDTH-1:0] i_Green,
|
||||||
|
input [VIDEO_WIDTH-1:0] i_Blue,
|
||||||
|
|
||||||
|
output reg o_HSync,
|
||||||
|
output reg o_VSync,
|
||||||
|
output reg [VIDEO_WIDTH-1:0] o_Red,
|
||||||
|
output reg [VIDEO_WIDTH-1:0] o_Green,
|
||||||
|
output reg [VIDEO_WIDTH-1:0] o_Blue
|
||||||
|
);
|
||||||
|
parameter VIDEO_WIDTH = 3;
|
||||||
|
|
||||||
|
parameter TOTAL_COLUMNS = 800;
|
||||||
|
parameter TOTAL_ROWS = 525;
|
||||||
|
|
||||||
|
parameter ACTIVE_COLUMNS = 640;
|
||||||
|
parameter ACTIVE_ROWS = 480;
|
||||||
|
|
||||||
|
//parameter FRONT_PORCH_COUNT_X = 18;
|
||||||
|
parameter FRONT_PORCH_COUNT_X = 15;
|
||||||
|
//parameter FRONT_PORCH_COUNT_Y = 10;
|
||||||
|
parameter FRONT_PORCH_COUNT_Y = 10;
|
||||||
|
//parameter BACK_PORCH_COUNT_X = 50;
|
||||||
|
parameter BACK_PORCH_COUNT_X = 53;
|
||||||
|
//parameter BACK_PORCH_COUNT_Y = 33;
|
||||||
|
parameter BACK_PORCH_COUNT_Y = 33;
|
||||||
|
|
||||||
|
wire w_HSync, w_VSync;
|
||||||
|
|
||||||
|
wire [$clog2(TOTAL_COLUMNS)-1:0] w_X;
|
||||||
|
wire [$clog2(TOTAL_ROWS)-1:0] w_Y;
|
||||||
|
|
||||||
|
reg [VIDEO_WIDTH-1:0] r_Red = 0;
|
||||||
|
reg [VIDEO_WIDTH-1:0] r_Green = 0;
|
||||||
|
reg [VIDEO_WIDTH-1:0] r_Blue = 0;
|
||||||
|
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
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
|
||||||
|
o_VSync <= 1;
|
||||||
|
end else begin
|
||||||
|
o_VSync <= w_VSync;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// The process of going through Current Beam Position and then
|
||||||
|
// the porch alignment above delays the video signal by two clock ticks.
|
||||||
|
// Do the same input -> wire -> output as above.
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
r_Red <= i_Red;
|
||||||
|
r_Green <= i_Green;
|
||||||
|
r_Blue <= i_Blue;
|
||||||
|
|
||||||
|
o_Red <= r_Red;
|
||||||
|
o_Green <= r_Green;
|
||||||
|
o_Blue <= r_Blue;
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Keys off of HSync and VSync signals to get the actual electron
|
||||||
|
// beam position
|
||||||
|
|
||||||
|
module VGA_Current_Beam_Position(
|
||||||
|
input i_Clk,
|
||||||
|
input i_HSync,
|
||||||
|
input i_VSync,
|
||||||
|
|
||||||
|
output reg o_HSync = 0,
|
||||||
|
output reg o_VSync = 0,
|
||||||
|
|
||||||
|
output reg [$clog2(TOTAL_COLUMNS)-1:0] o_X,
|
||||||
|
output reg [$clog2(TOTAL_ROWS)-1:0] o_Y
|
||||||
|
);
|
||||||
|
parameter TOTAL_COLUMNS = 800;
|
||||||
|
parameter TOTAL_ROWS = 525;
|
||||||
|
|
||||||
|
wire w_frameStart;
|
||||||
|
|
||||||
|
// forward these flip-flop style. use these instead of what
|
||||||
|
// comes out of sync pulse generator!
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
o_VSync <= i_VSync;
|
||||||
|
o_HSync <= i_HSync;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
if (w_frameStart == 1) begin
|
||||||
|
o_X <= 0;
|
||||||
|
o_Y <= 0;
|
||||||
|
end else begin
|
||||||
|
if (o_X == TOTAL_COLUMNS - 1) begin
|
||||||
|
o_X <= 0;
|
||||||
|
if (o_Y == TOTAL_ROWS - 1) begin
|
||||||
|
o_Y <= 0;
|
||||||
|
end else begin
|
||||||
|
o_Y <= o_Y + 1;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
o_X <= o_X + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// rising vsync == new frame
|
||||||
|
assign w_frameStart = (~o_VSync & i_VSync);
|
||||||
|
endmodule
|
|
@ -0,0 +1,189 @@
|
||||||
|
module VGA_Pattern_Generator(
|
||||||
|
input i_Clk,
|
||||||
|
input [3:0] i_Pattern,
|
||||||
|
input i_HSync,
|
||||||
|
input i_VSync,
|
||||||
|
|
||||||
|
output reg o_HSync = 0,
|
||||||
|
output reg o_VSync = 0,
|
||||||
|
output reg [VIDEO_WIDTH-1:0] o_Red,
|
||||||
|
output reg [VIDEO_WIDTH-1:0] o_Green,
|
||||||
|
output reg [VIDEO_WIDTH-1:0] o_Blue
|
||||||
|
);
|
||||||
|
// Go Board only supports 3 bits per channel. That's even less than the
|
||||||
|
// Amiga!
|
||||||
|
parameter VIDEO_WIDTH = 3;
|
||||||
|
|
||||||
|
parameter TOTAL_COLUMNS = 800;
|
||||||
|
parameter TOTAL_ROWS = 525;
|
||||||
|
|
||||||
|
parameter ACTIVE_COLUMNS = 640;
|
||||||
|
parameter ACTIVE_ROWS = 480;
|
||||||
|
|
||||||
|
localparam COLOR_BAR_WIDTH = ACTIVE_COLUMNS / 8;
|
||||||
|
|
||||||
|
wire w_HSync, w_VSync;
|
||||||
|
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Red[0:15];
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Green[0:15];
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Blue[0:15];
|
||||||
|
|
||||||
|
wire [$clog2(TOTAL_COLUMNS)-1:0] w_X;
|
||||||
|
wire [$clog2(TOTAL_ROWS)-1:0] w_Y;
|
||||||
|
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
|
||||||
|
// all these pattern operations take one clock tick
|
||||||
|
// so delay sync signals by that much
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
o_HSync <= w_HSync;
|
||||||
|
o_VSync <= w_VSync;
|
||||||
|
end
|
||||||
|
|
||||||
|
// none more black
|
||||||
|
assign w_Red[0] = 0;
|
||||||
|
assign w_Green[0] = 0;
|
||||||
|
assign w_Blue[0] = 0;
|
||||||
|
|
||||||
|
// red
|
||||||
|
assign w_Red[1] = (
|
||||||
|
(w_X < ACTIVE_COLUMNS && w_Y < ACTIVE_ROWS) ?
|
||||||
|
{VIDEO_WIDTH{1'b1}} :
|
||||||
|
0
|
||||||
|
);
|
||||||
|
assign w_Green[1] = 0;
|
||||||
|
assign w_Blue[1] = 0;
|
||||||
|
|
||||||
|
// green
|
||||||
|
assign w_Red[2] = 0;
|
||||||
|
assign w_Green[2] = (
|
||||||
|
(w_X < ACTIVE_COLUMNS && w_Y < ACTIVE_ROWS) ?
|
||||||
|
{VIDEO_WIDTH{1'b1}} :
|
||||||
|
0
|
||||||
|
);
|
||||||
|
assign w_Blue[2] = 0;
|
||||||
|
|
||||||
|
// blue
|
||||||
|
assign w_Red[3] = 0;
|
||||||
|
assign w_Green[3] = 0;
|
||||||
|
assign w_Blue[3] = (
|
||||||
|
(w_X < ACTIVE_COLUMNS && w_Y < ACTIVE_ROWS) ?
|
||||||
|
{VIDEO_WIDTH{1'b1}} :
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
// checkerboard
|
||||||
|
// cell size is 32 pixels
|
||||||
|
assign w_Red[4] = (w_X[5] ^ w_Y[5]) ? {VIDEO_WIDTH{1'b1}} : 0;
|
||||||
|
assign w_Green[4] = w_Red[4];
|
||||||
|
assign w_Blue[4] = w_Red[4];
|
||||||
|
|
||||||
|
wire [2:0] w_colorBarSelect;
|
||||||
|
|
||||||
|
// color bars
|
||||||
|
// yes this is the hardware way to do this b/c multi/div
|
||||||
|
assign w_colorBarSelect =
|
||||||
|
w_X < COLOR_BAR_WIDTH ? 0 :
|
||||||
|
w_X < COLOR_BAR_WIDTH * 2 ? 1 :
|
||||||
|
w_X < COLOR_BAR_WIDTH * 3 ? 2 :
|
||||||
|
w_X < COLOR_BAR_WIDTH * 4 ? 3 :
|
||||||
|
w_X < COLOR_BAR_WIDTH * 5 ? 4 :
|
||||||
|
w_X < COLOR_BAR_WIDTH * 6 ? 5 :
|
||||||
|
w_X < COLOR_BAR_WIDTH * 7 ? 6 :7;
|
||||||
|
|
||||||
|
assign w_Red[5] = (
|
||||||
|
w_colorBarSelect == 4 ||
|
||||||
|
w_colorBarSelect == 5 ||
|
||||||
|
w_colorBarSelect == 6 ||
|
||||||
|
w_colorBarSelect == 7
|
||||||
|
) ? {VIDEO_WIDTH{1'b1}} : 0;
|
||||||
|
|
||||||
|
assign w_Green[5] = (
|
||||||
|
w_colorBarSelect == 2 ||
|
||||||
|
w_colorBarSelect == 3 ||
|
||||||
|
w_colorBarSelect == 6 ||
|
||||||
|
w_colorBarSelect == 7
|
||||||
|
) ? {VIDEO_WIDTH{1'b1}} : 0;
|
||||||
|
|
||||||
|
assign w_Blue[5] = (
|
||||||
|
w_colorBarSelect == 1 ||
|
||||||
|
w_colorBarSelect == 3 ||
|
||||||
|
w_colorBarSelect == 5 ||
|
||||||
|
w_colorBarSelect == 7
|
||||||
|
) ? {VIDEO_WIDTH{1'b1}} : 0;
|
||||||
|
|
||||||
|
// border
|
||||||
|
|
||||||
|
localparam BORDER_WIDTH = 2;
|
||||||
|
|
||||||
|
assign w_Red[6] = (
|
||||||
|
w_X < BORDER_WIDTH || w_X >= ACTIVE_COLUMNS - BORDER_WIDTH ||
|
||||||
|
w_Y < BORDER_WIDTH || w_Y >= ACTIVE_ROWS - BORDER_WIDTH
|
||||||
|
) ? {VIDEO_WIDTH{1'b1}} : 0;
|
||||||
|
assign w_Green[6] = 0;
|
||||||
|
assign w_Blue[6] = 0;
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
case (i_Pattern)
|
||||||
|
0:
|
||||||
|
begin
|
||||||
|
o_Red <= w_Red[0];
|
||||||
|
o_Green <= w_Green[0];
|
||||||
|
o_Blue <= w_Blue[0];
|
||||||
|
end
|
||||||
|
1:
|
||||||
|
begin
|
||||||
|
o_Red <= w_Red[1];
|
||||||
|
o_Green <= w_Green[1];
|
||||||
|
o_Blue <= w_Blue[1];
|
||||||
|
end
|
||||||
|
2:
|
||||||
|
begin
|
||||||
|
o_Red <= w_Red[2];
|
||||||
|
o_Green <= w_Green[2];
|
||||||
|
o_Blue <= w_Blue[2];
|
||||||
|
end
|
||||||
|
3:
|
||||||
|
begin
|
||||||
|
o_Red <= w_Red[3];
|
||||||
|
o_Green <= w_Green[3];
|
||||||
|
o_Blue <= w_Blue[3];
|
||||||
|
end
|
||||||
|
4:
|
||||||
|
begin
|
||||||
|
o_Red <= w_Red[4];
|
||||||
|
o_Green <= w_Green[4];
|
||||||
|
o_Blue <= w_Blue[4];
|
||||||
|
end
|
||||||
|
5:
|
||||||
|
begin
|
||||||
|
o_Red <= w_Red[5];
|
||||||
|
o_Green <= w_Green[5];
|
||||||
|
o_Blue <= w_Blue[5];
|
||||||
|
end
|
||||||
|
6:
|
||||||
|
begin
|
||||||
|
o_Red <= w_Red[6];
|
||||||
|
o_Green <= w_Green[6];
|
||||||
|
o_Blue <= w_Blue[6];
|
||||||
|
end
|
||||||
|
default:
|
||||||
|
begin
|
||||||
|
o_Red <= w_Red[0];
|
||||||
|
o_Green <= w_Green[0];
|
||||||
|
o_Blue <= w_Blue[0];
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Remember, this "magically works" on the Go Board.
|
||||||
|
// If you're using a different clock speed, you need to
|
||||||
|
// do a different thing here.
|
||||||
|
module VGA_Sync_Pulse_Generator (
|
||||||
|
input i_Clk,
|
||||||
|
output o_HSync,
|
||||||
|
output o_VSync,
|
||||||
|
|
||||||
|
output reg [$clog2(TOTAL_COLUMNS)-1:0] o_rawX,
|
||||||
|
output reg [$clog2(TOTAL_ROWS)-1:0] o_rawY
|
||||||
|
);
|
||||||
|
// remember overscan
|
||||||
|
parameter ACTIVE_COLUMNS = 640;
|
||||||
|
parameter ACTIVE_ROWS = 480;
|
||||||
|
|
||||||
|
parameter TOTAL_COLUMNS = 800;
|
||||||
|
parameter TOTAL_ROWS = 525;
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
if (o_rawX == TOTAL_COLUMNS - 1) begin
|
||||||
|
o_rawX <= 0;
|
||||||
|
if (o_rawY == TOTAL_ROWS - 1) begin
|
||||||
|
o_rawY <= 0;
|
||||||
|
end else begin
|
||||||
|
o_rawY <= o_rawY + 1;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
o_rawX <= o_rawX + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_HSync = (o_rawX < ACTIVE_COLUMNS) ? 1 : 0;
|
||||||
|
assign o_VSync = (o_rawY < ACTIVE_ROWS) ? 1 : 0;
|
||||||
|
endmodule
|
|
@ -0,0 +1,219 @@
|
||||||
|
module VGA_Tester(
|
||||||
|
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,
|
||||||
|
|
||||||
|
input i_UART_RX,
|
||||||
|
output o_UART_TX,
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
localparam TOTAL_COLUMNS = 800;
|
||||||
|
localparam TOTAL_ROWS = 525;
|
||||||
|
|
||||||
|
localparam ACTIVE_COLUMNS = 640;
|
||||||
|
localparam ACTIVE_ROWS = 480;
|
||||||
|
|
||||||
|
localparam VIDEO_WIDTH = 3;
|
||||||
|
|
||||||
|
// vga
|
||||||
|
wire w_HSync_Start, w_VSync_Start;
|
||||||
|
wire w_HSync_FromTestPattern, w_VSync_FromTestPattern;
|
||||||
|
wire w_HSync_FromPorchSync, w_VSync_FromPorchSync;
|
||||||
|
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Red_FromTestPattern;
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Red_FromPorchSync;
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Green_FromTestPattern;
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Green_FromPorchSync;
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Blue_FromTestPattern;
|
||||||
|
wire [VIDEO_WIDTH-1:0] w_Blue_FromPorchSync;
|
||||||
|
|
||||||
|
reg [3:0] r_currentPattern = 6;
|
||||||
|
|
||||||
|
// uart
|
||||||
|
wire w_dataReady;
|
||||||
|
wire [7:0] w_dataByte;
|
||||||
|
wire w_transmitActive, w_transmitSerial;
|
||||||
|
|
||||||
|
wire w_segment1_A, w_segment2_A;
|
||||||
|
wire w_segment1_B, w_segment2_B;
|
||||||
|
wire w_segment1_C, w_segment2_C;
|
||||||
|
wire w_segment1_D, w_segment2_D;
|
||||||
|
wire w_segment1_E, w_segment2_E;
|
||||||
|
wire w_segment1_F, w_segment2_F;
|
||||||
|
wire w_segment1_G, w_segment2_G;
|
||||||
|
|
||||||
|
reg r_resetTransmit = 1;
|
||||||
|
|
||||||
|
// accept incoming data
|
||||||
|
|
||||||
|
UART_RX #(
|
||||||
|
.CLOCKS_PER_SECOND(25000000),
|
||||||
|
.BAUD_RATE(115200)
|
||||||
|
) MyUART_RX (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_ReceiveBit(i_UART_RX),
|
||||||
|
.o_DataReady(w_dataReady),
|
||||||
|
.o_DataByte(w_dataByte)
|
||||||
|
);
|
||||||
|
|
||||||
|
UART_TX #(
|
||||||
|
.CLOCKS_PER_SECOND(25000000),
|
||||||
|
.BAUD_RATE(115200)
|
||||||
|
) MyUART_TX (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Reset_Low(r_resetTransmit),
|
||||||
|
.i_TransmitReady(w_dataReady),
|
||||||
|
.i_TransmitByte(w_dataByte),
|
||||||
|
.o_Active(w_transmitActive),
|
||||||
|
.o_Output(w_transmitSerial),
|
||||||
|
.o_Done()
|
||||||
|
);
|
||||||
|
|
||||||
|
assign o_UART_TX = w_transmitActive ? w_transmitSerial : 1;
|
||||||
|
|
||||||
|
Binary_to_7_Segment Segment_1 (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Number(w_dataByte[7:4]),
|
||||||
|
.o_SegA(w_segment1_A),
|
||||||
|
.o_SegB(w_segment1_B),
|
||||||
|
.o_SegC(w_segment1_C),
|
||||||
|
.o_SegD(w_segment1_D),
|
||||||
|
.o_SegE(w_segment1_E),
|
||||||
|
.o_SegF(w_segment1_F),
|
||||||
|
.o_SegG(w_segment1_G)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign o_Segment1_A = !w_segment1_A;
|
||||||
|
assign o_Segment1_B = !w_segment1_B;
|
||||||
|
assign o_Segment1_C = !w_segment1_C;
|
||||||
|
assign o_Segment1_D = !w_segment1_D;
|
||||||
|
assign o_Segment1_E = !w_segment1_E;
|
||||||
|
assign o_Segment1_F = !w_segment1_F;
|
||||||
|
assign o_Segment1_G = !w_segment1_G;
|
||||||
|
|
||||||
|
Binary_to_7_Segment Segment_2 (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Number(w_dataByte[3:0]),
|
||||||
|
.o_SegA(w_segment2_A),
|
||||||
|
.o_SegB(w_segment2_B),
|
||||||
|
.o_SegC(w_segment2_C),
|
||||||
|
.o_SegD(w_segment2_D),
|
||||||
|
.o_SegE(w_segment2_E),
|
||||||
|
.o_SegF(w_segment2_F),
|
||||||
|
.o_SegG(w_segment2_G)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign o_Segment2_A = !w_segment2_A;
|
||||||
|
assign o_Segment2_B = !w_segment2_B;
|
||||||
|
assign o_Segment2_C = !w_segment2_C;
|
||||||
|
assign o_Segment2_D = !w_segment2_D;
|
||||||
|
assign o_Segment2_E = !w_segment2_E;
|
||||||
|
assign o_Segment2_F = !w_segment2_F;
|
||||||
|
assign o_Segment2_G = !w_segment2_G;
|
||||||
|
|
||||||
|
always @(posedge i_Clk) begin
|
||||||
|
if (w_dataReady) begin
|
||||||
|
r_currentPattern <= w_dataByte[3:0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// show the video
|
||||||
|
|
||||||
|
VGA_Sync_Pulse_Generator #(
|
||||||
|
.TOTAL_COLUMNS(TOTAL_COLUMNS),
|
||||||
|
.TOTAL_ROWS(TOTAL_ROWS),
|
||||||
|
.ACTIVE_COLUMNS(ACTIVE_COLUMNS),
|
||||||
|
.ACTIVE_ROWS(ACTIVE_ROWS)
|
||||||
|
) SyncGenerator (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.o_HSync(w_HSync_Start),
|
||||||
|
.o_VSync(w_VSync_Start),
|
||||||
|
.o_rawX(),
|
||||||
|
.o_rawY()
|
||||||
|
);
|
||||||
|
|
||||||
|
VGA_Pattern_Generator #(
|
||||||
|
.VIDEO_WIDTH(VIDEO_WIDTH),
|
||||||
|
.TOTAL_COLUMNS(TOTAL_COLUMNS),
|
||||||
|
.TOTAL_ROWS(TOTAL_ROWS),
|
||||||
|
.ACTIVE_COLUMNS(ACTIVE_COLUMNS),
|
||||||
|
.ACTIVE_ROWS(ACTIVE_ROWS)
|
||||||
|
) PatternGenerator (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_Pattern(r_currentPattern),
|
||||||
|
.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),
|
||||||
|
.o_Green(w_Green_FromTestPattern),
|
||||||
|
.o_Blue(w_Blue_FromTestPattern)
|
||||||
|
);
|
||||||
|
|
||||||
|
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)
|
||||||
|
) PorchBuilder (
|
||||||
|
.i_Clk(i_Clk),
|
||||||
|
.i_HSync(w_HSync_FromTestPattern),
|
||||||
|
.i_VSync(w_VSync_FromTestPattern),
|
||||||
|
.i_Red(w_Red_FromTestPattern),
|
||||||
|
.i_Green(w_Green_FromTestPattern),
|
||||||
|
.i_Blue(w_Blue_FromTestPattern),
|
||||||
|
|
||||||
|
.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
|
Loading…
Reference in New Issue