*Note we are not affiliated with individual companies Temu or Zoom, nor are they associated with us in any way shape or form.
Following the COVID-19 pandemic, we witnessed virtual communication tools proliferate into the mainstream, reshaping our understanding of teamwork and collaboration in educational and professional settings. Digital tools designed to facilitate remote communication have been a defining element of our academic experience, and considering the asynchronous nature of the course this semester, it felt natural that we chose to explore implementing real-time video and audio communication between FPGAs in our final project. Using National Television Standard Committee (NSTC) cameras and stereo microphones for video and audio data collection, we designed and implemented a protocol that enables two boards to successfully and simultaneously exchange data, creating a video call system over GPIO.
Our project implements two-way audio and video communication between two DE-1 SoC FPGA boards. Our approach primarily uses Verilog to handle data collection and transmission through the reading from and writing to the video bus in a state machine. However, we also use the HPS to communicate with our NSTC Camera. Audio data is read from a microphone in port and played back using the line out port. We used an EBAB Bus Master to handle some of the complexities associated with audio sampling from the microphone and playback. An EBAB Bus Master is also used for video playback. Ostensibly, video and audio work in the same way. A bus master is used to handle reading and writing, respectively, and it's important to note that these two actions can't happen simultaneously.
The process is fairly trivial when audio or video playback is performed on one board. By the time you're ready to write data, you will be writing the data read in the previous states. The key complexity in this project was designing a multi-board synchronization scheme that ensures that during two-way communication, once one board has completed a read from its camera and microphone, the correct data will be available from the other board over GPIO during the time interval associated with data write. However, a few considerations make audio less complex than video. First, it doesn't necessarily need to be as reliable. Some data can be "missed," meaning it isn't successfully put on the receiver's output. Assuming it's not happening frequently, an occasional miss has no discernible effect on output audio quality. Secondly, no associated addressing is required in video to map pixel color to position on the VGA display.
Because of these key differences, we can use different approaches to create audio and video playback and handle their communication separately. The rationale behind this division is that if audio and video are being transferred in seemingly real time, any minor audio and video synchronization discrepancies would not be evident to users. This choice enabled us to create two unique state machines, one dedicated to audio and the other for video. This greatly simplified the design and minimized the complexity of the handshaking that needed to occur in the communication protocol.
We decided to use GPIO ports because of their simplicity. We are able to connect FPGAs using jumper cables. This approach does have limitations, the most obvious being the length constraints. The need for the two boards to be in relative proximity does, in principle, defeat the purpose of virtual communication. Still, the focus of our project was the protocol design, which can be easily translated to support data transmission over different mediums. Another key limitation of the GPIO approach was the non-negligible clock skew and signal distortion, especially at high frequencies. Due to the board's limitations in effectively writing and reading pins at high speeds, many of our preliminary approaches proved ineffective. Ultimately, these challenges enabled us to design a system resilient to hardware limitations and constraints.
The NTSC camera is connected directly to the FPGA, and we are able to communicate with it via the Hardware Protocol system(HPS). To display camera input on the VGA monitor, we used the eternal bus to avalon bridge interface to facilitate communication between the FPGA and the monitor. When we read from the NTSC camera, it defaults to a resolution of 320 x 240, which is different from the 640 x 480 of our VGA monitor. Instead of directly mapping the inputs of the NTSC camera to the VGA monitor and writing pixels one to one, we mapped one pixel to four to use the full display. Without this approach, the video would only populate one-quarter of the display. Increasing the video size with this mapping scheme does not improve the resolution, but we think it provides an improved user experience. In theory, our video playback process is read and then write, but in practice, to produce a scaled image, there are four consecutive writes after each read, one for each pixel.
Figure 1 : Mapping from Camera Read to VGA Pixels
We based our video state machine and edited code off of the Video Input with VGA output demo on the Quartus 18.1 page on the course website.
To perform a read, we set signals bus_read to one and bus_addr to the corresponding address from which we want to retrieve camera data. They are connected to the external bus to Avalon bridge, which upon seeing the bus_read signal and bus_addr will return an acknowledgement and make the requested data available by putting it on bus_read_data on the next clock cycle. After the read is completed, the bus_read signal is set to low. This process is completed in two states. A write is completed by putting data on bus_write_data the desired write address on bus_addr and setting the bus_write flag. A write is complete once an acknowledgement has been received, and this process also takes 2 states. It’s important to note that since for each camera pixel we are completing four writes to increase the scale of the image, the writing process in our state machine takes 8 clock cycles.
Figure 2 : Video Communication Flow Between FPGAs
Figure 3 : State Machine for Video on the FPGAs
Both FPGAs use the same reading and writing scheme explained above. To make them communicate with each other, we added 2 handshake states to one of the state machines to ensure that they both finish reading and will not move to writing until they agree that they have been finished reading for 3 clock cycles. We implemented similar logic for writing that does the same thing where both FPGAs will not read a new value until they have both agreed that they are done writing. Once an agreement has been reached which is performed by monitoring flag exchanged between boards, the state machine responsible for tracking the handshakes will move on to the next step, and communicate with the other FPGA to do the same. The primary motivation for this handshaking scheme is it takes an inconsistent number of clock cycles to complete the video state machine. A timer is implemented to prevent bus hogging which ultimately introduces a completion time variability of 32 clock cycles. In theory, if we could reasonably assume that the number of cycles for completion was the same and the clocks on the boards were the same frequency, the two state machines would be synchronized in some capacity by default. Because this is not the case we rely on handshaking to create synchronization.
Figure 4 : Audio Communication Flow Between FPGAs
Because of the ability of audio to tolerate some inconsistencies, the implementation is much simpler than that of video. Our audio state machine is a modified version of the Audio loop-back configuration found on the course website's Digital Signal Processing page. The audio communication protocol doesn't utilize any handshaking because, through experimentation, we learned that it is simply not necessary. It begins with a read from the microphone in port, followed by a write-to line out. Because it also uses an EBAB bus master, the mechanisms for reading and writing are very similar to the one explained above for video. The audio_bus_addr is set to the read FIFO address, and audio_bus_read is set high. It will then return an acknowledgment and make the data available on audio_bus_read_data on the next clock cycle. The desired data is put on audio_bus_write_data, and the audio_bus_write is set high enough for the write to line out. It then waits for an acknowledgment of a successful write before beginning a new read. The data exchange is very straightforward. Once a read is complete, the data is put on a set of GPIO pins, which makes it available to the other FPGA. When it is time to write, the write data is read from a different set of GPIO pins on which the other FPGA puts its read data. It is important to note that two reads and two writes are performed, one for the left channel and the other for the right channel. No additional coordination between the two state machines is necessary because they don't need to operate in sync. If data is missed, meaning that the data available on the GPIO pins changes before it gets written, or there is a duplicate write, meaning that a value is written to line out twice because it didn't change fast enough, there is no meaningful impact on audio clarity. In the project demonstration, it is evident that there is very obvious and audible distortion, but this is a symptom of the fact that we compressed audio from 32 bits to 6 bits to have enough GPIO pins available for video communication. We did this by keeping the 6 most significant bits and then concatenated 24 bits of 0s onto it after it was received, so it could maintain its 32 bit status.
Significant trial and error was involved in developing a working approach. In our first attempt, we tried to create synchronization by clocking one board of the other. In theory, this would ensure they would have identical state transitions, effectively eliminating the need for handshaking. We thought we could use a 50 MHz clock on one board, put that clock on a GPIO pin, and then use that pin as the clock on the other board. In practice, this was not an effective solution. Even if we were to ignore the clock skew and its likely negative effects, the signal distortion on the 50 mHz square wave over GPIO made it impossible for the receiving board to effectively and consistently detect rising edges. In another approach, we tried to implement state machines that moved on from the handshake at the same time. This seemed promising because it yielded good results until we tried two-way video data exchange. In our testing, we had issues with inconsistent camera functionality. To help identify when the issue was related to the camera versus our protocol, when testing, we often had the state machines performing two-way communication. However, one of the boards would be writing its own camera data instead of the data available on the GPIO pins. This enabled us to identify when the camera wasn’t working. When we were doing these tests, this approach seemed to work well, as the video receiver was able to output the video data being received over GPIO to its own VGA display. However, when we switched to both boards, outputting the data received over GPIO would begin to miss bus acknowledgments, resulting in the state machine getting stuck.
The cause of this is unclear as nothing had changed regarding actual state machine functionality in the two approaches. One guess is that data on the GPIO was not stable for a long enough duration to be written. Our experimentation with different FPGAs informed this assumption, which indicated that it was a board-related issue instead of a code issue. When trying different boards or switching the sender-receiver code between two boards, the missed acknowledgment usually occurs on the same board independent of the code being run on it. Once we moved to our current handshaking approach, it seemed to resolve the missed acknowledgment issue. However, there was an issue with mapping pixel color data to the correct address. In addition to the pixel color data, we also include the address data so the receiver understands where the pixel is supposed to go. We had thought critically about this issue when developing our initial scheme, and we were under the impression that our handshaking protocol should handle it; however, it did not. Because of our choice to send addresses in addition to color data, we needed to compress audio from 8 bits to 6 bits to have enough GPIO ports. We had conducted an experiment earlier where we input a 5 bit number using switches and used the value to select how many bits we wanted to send. From this experiment, we found that 6 bits interestingly enough was the smallest we could go without the quality dropping significantly. This worked out as we ended up needing to use 6 bit audio.
Here are a couple of pictures from when we were in the debug phase. The official demo video should be on the ECE 5760 page or youtube channel
Figure 5 : Former bug where video used to run and then stopped randomly after not missing a bus ack for some reason
Figure 6 : Former Bug with weird indexing
Figure 7 : Another former bug with weird indexing
Figure 8 : Former bug with partial render of video, but not complete
The ability to receive direct feedback relating to the functionality of our project made the design and verification process fairly straightforward. The ability to see or hear whether we were achieving the desired output made for quick evaluation. Although we cut audio from 8 bits to 6 bits, it still retained data integrity, and is clearly understood. The same can be said with video. Due to the low resolution of the camera as well as our scaling of the video feed, the video quality is far from exceptional but still easy to perceive. Due to the state machines depending on each other for signals and vulnerability to sensitivities and clock skews on the GPIO ports and that there are many states that involve waiting for acks, it does not render every frame with a consistent time.
In terms of usability, video call starts once we flash the .sof files to the FPGAs and run the C code on both. The audio needs to be enabled by pressing key 1. While it functions overall, certain factors can cause the state machine to desynchronize such as pressing reset (key 0) for the video state machines can desynchronize which requires us to flash again. Since there are no mute and camera off buttons yet, the person using the system also does not have a choice on what data to choose to send.
In conclusion, we created two-way video and audio communication between two FPGA boards. Using GPIO imposed obvious limitations regarding board proximity, speed, and data integrity. However, in developing a protocol to manage the last two effectively, we created a resilient framework that can be easily expanded to support other communication mediums. In the future, we can include features like a mute button and camera off. Furthermore, to expand the functionality and practicality, we could pivot away from GPIO to support communication over a wireless network, eliminating the need for the two boards to be tethered together.
We used the External Bus to Avalon Bridge interface from Intel in our project. We based our video state machine and edited code off the Video Input with VGA output demo on the Quartus 18.1 page on the course website. Our audio state machine is a modified version of the Audio loop-back configuration found on the course website's Digital Signal Processing page.
There is nothing to patent on our project; it was just a fun exercise and learning opportunity, but we did not create anything proprietary.
The group approves this report for inclusion on the course website. The group approves the video for inclusion on the course youtube channel
Both Nita and Sabian both put work into every part of this lab whether it was getting video or audio to work, or the communication side.
module DE1_SoC_Computer (
////////////////////////////////////
// FPGA Pins
////////////////////////////////////
// Clock pins
CLOCK_50,
CLOCK2_50,
CLOCK3_50,
CLOCK4_50,
// ADC
ADC_CS_N,
ADC_DIN,
ADC_DOUT,
ADC_SCLK,
// Audio
AUD_ADCDAT,
AUD_ADCLRCK,
AUD_BCLK,
AUD_DACDAT,
AUD_DACLRCK,
AUD_XCK,
// SDRAM
DRAM_ADDR,
DRAM_BA,
DRAM_CAS_N,
DRAM_CKE,
DRAM_CLK,
DRAM_CS_N,
DRAM_DQ,
DRAM_LDQM,
DRAM_RAS_N,
DRAM_UDQM,
DRAM_WE_N,
// I2C Bus for Configuration of the Audio and Video-In Chips
FPGA_I2C_SCLK,
FPGA_I2C_SDAT,
// 40-Pin Headers
GPIO_0,
GPIO_1,
// Seven Segment Displays
HEX0,
HEX1,
HEX2,
HEX3,
HEX4,
HEX5,
// IR
IRDA_RXD,
IRDA_TXD,
// Pushbuttons
KEY,
// LEDs
LEDR,
// PS2 Ports
PS2_CLK,
PS2_DAT,
PS2_CLK2,
PS2_DAT2,
// Slider Switches
SW,
// Video-In
TD_CLK27,
TD_DATA,
TD_HS,
TD_RESET_N,
TD_VS,
// VGA
VGA_B,
VGA_BLANK_N,
VGA_CLK,
VGA_G,
VGA_HS,
VGA_R,
VGA_SYNC_N,
VGA_VS,
////////////////////////////////////
// HPS Pins
////////////////////////////////////
// DDR3 SDRAM
HPS_DDR3_ADDR,
HPS_DDR3_BA,
HPS_DDR3_CAS_N,
HPS_DDR3_CKE,
HPS_DDR3_CK_N,
HPS_DDR3_CK_P,
HPS_DDR3_CS_N,
HPS_DDR3_DM,
HPS_DDR3_DQ,
HPS_DDR3_DQS_N,
HPS_DDR3_DQS_P,
HPS_DDR3_ODT,
HPS_DDR3_RAS_N,
HPS_DDR3_RESET_N,
HPS_DDR3_RZQ,
HPS_DDR3_WE_N,
// Ethernet
HPS_ENET_GTX_CLK,
HPS_ENET_INT_N,
HPS_ENET_MDC,
HPS_ENET_MDIO,
HPS_ENET_RX_CLK,
HPS_ENET_RX_DATA,
HPS_ENET_RX_DV,
HPS_ENET_TX_DATA,
HPS_ENET_TX_EN,
// Flash
HPS_FLASH_DATA,
HPS_FLASH_DCLK,
HPS_FLASH_NCSO,
// Accelerometer
HPS_GSENSOR_INT,
// General Purpose I/O
HPS_GPIO,
// I2C
HPS_I2C_CONTROL,
HPS_I2C1_SCLK,
HPS_I2C1_SDAT,
HPS_I2C2_SCLK,
HPS_I2C2_SDAT,
// Pushbutton
HPS_KEY,
// LED
HPS_LED,
// SD Card
HPS_SD_CLK,
HPS_SD_CMD,
HPS_SD_DATA,
// SPI
HPS_SPIM_CLK,
HPS_SPIM_MISO,
HPS_SPIM_MOSI,
HPS_SPIM_SS,
// UART
HPS_UART_RX,
HPS_UART_TX,
// USB
HPS_CONV_USB_N,
HPS_USB_CLKOUT,
HPS_USB_DATA,
HPS_USB_DIR,
HPS_USB_NXT,
HPS_USB_STP
);
//=======================================================
// PARAMETER declarations
//=======================================================
//=======================================================
// PORT declarations
//=======================================================
////////////////////////////////////
// FPGA Pins
////////////////////////////////////
// Clock pins
input CLOCK_50;
input CLOCK2_50;
input CLOCK3_50;
input CLOCK4_50;
// ADC
inout ADC_CS_N;
output ADC_DIN;
input ADC_DOUT;
output ADC_SCLK;
// Audio
input AUD_ADCDAT;
inout AUD_ADCLRCK;
inout AUD_BCLK;
output AUD_DACDAT;
inout AUD_DACLRCK;
output AUD_XCK;
// SDRAM
output [12: 0] DRAM_ADDR;
output [ 1: 0] DRAM_BA;
output DRAM_CAS_N;
output DRAM_CKE;
output DRAM_CLK;
output DRAM_CS_N;
inout [15: 0] DRAM_DQ;
output DRAM_LDQM;
output DRAM_RAS_N;
output DRAM_UDQM;
output DRAM_WE_N;
// I2C Bus for Configuration of the Audio and Video-In Chips
output FPGA_I2C_SCLK;
inout FPGA_I2C_SDAT;
// 40-pin headers
inout [35: 0] GPIO_0;
inout [35: 0] GPIO_1;
// Seven Segment Displays
output [ 6: 0] HEX0;
output [ 6: 0] HEX1;
output [ 6: 0] HEX2;
output [ 6: 0] HEX3;
output [ 6: 0] HEX4;
output [ 6: 0] HEX5;
// IR
input IRDA_RXD;
output IRDA_TXD;
// Pushbuttons
input [ 3: 0] KEY;
// LEDs
output [ 9: 0] LEDR;
// PS2 Ports
inout PS2_CLK;
inout PS2_DAT;
inout PS2_CLK2;
inout PS2_DAT2;
// Slider Switches
input [ 9: 0] SW;
// Video-In
input TD_CLK27;
input [ 7: 0] TD_DATA;
input TD_HS;
output TD_RESET_N;
input TD_VS;
// VGA
output [ 7: 0] VGA_B;
output VGA_BLANK_N;
output VGA_CLK;
output [ 7: 0] VGA_G;
output VGA_HS;
output [ 7: 0] VGA_R;
output VGA_SYNC_N;
output VGA_VS;
////////////////////////////////////
// HPS Pins
////////////////////////////////////
// DDR3 SDRAM
output [14: 0] HPS_DDR3_ADDR;
output [ 2: 0] HPS_DDR3_BA;
output HPS_DDR3_CAS_N;
output HPS_DDR3_CKE;
output HPS_DDR3_CK_N;
output HPS_DDR3_CK_P;
output HPS_DDR3_CS_N;
output [ 3: 0] HPS_DDR3_DM;
inout [31: 0] HPS_DDR3_DQ;
inout [ 3: 0] HPS_DDR3_DQS_N;
inout [ 3: 0] HPS_DDR3_DQS_P;
output HPS_DDR3_ODT;
output HPS_DDR3_RAS_N;
output HPS_DDR3_RESET_N;
input HPS_DDR3_RZQ;
output HPS_DDR3_WE_N;
// Ethernet
output HPS_ENET_GTX_CLK;
inout HPS_ENET_INT_N;
output HPS_ENET_MDC;
inout HPS_ENET_MDIO;
input HPS_ENET_RX_CLK;
input [ 3: 0] HPS_ENET_RX_DATA;
input HPS_ENET_RX_DV;
output [ 3: 0] HPS_ENET_TX_DATA;
output HPS_ENET_TX_EN;
// Flash
inout [ 3: 0] HPS_FLASH_DATA;
output HPS_FLASH_DCLK;
output HPS_FLASH_NCSO;
// Accelerometer
inout HPS_GSENSOR_INT;
// General Purpose I/O
inout [ 1: 0] HPS_GPIO;
// I2C
inout HPS_I2C_CONTROL;
inout HPS_I2C1_SCLK;
inout HPS_I2C1_SDAT;
inout HPS_I2C2_SCLK;
inout HPS_I2C2_SDAT;
// Pushbutton
inout HPS_KEY;
// LED
inout HPS_LED;
// SD Card
output HPS_SD_CLK;
inout HPS_SD_CMD;
inout [ 3: 0] HPS_SD_DATA;
// SPI
output HPS_SPIM_CLK;
input HPS_SPIM_MISO;
output HPS_SPIM_MOSI;
inout HPS_SPIM_SS;
// UART
input HPS_UART_RX;
output HPS_UART_TX;
// USB
inout HPS_CONV_USB_N;
input HPS_USB_CLKOUT;
inout [ 7: 0] HPS_USB_DATA;
input HPS_USB_DIR;
input HPS_USB_NXT;
output HPS_USB_STP;
//=======================================================
// REG/WIRE declarations
//=======================================================
wire [15: 0] hex3_hex0;
//wire [15: 0] hex5_hex4;
//assign HEX0 = ~hex3_hex0[ 6: 0]; // hex3_hex0[ 6: 0];
//assign HEX1 = ~hex3_hex0[14: 8];
//assign HEX2 = ~hex3_hex0[22:16];
//assign HEX3 = ~hex3_hex0[30:24];
//assign HEX4 = 7'b1111111;
//assign HEX5 = 7'b1111111;
//HexDigit Digit2(HEX2, hex3_hex0[11:8]);
//HexDigit Digit3(HEX3, hex3_hex0[15:12]);
// MAY need to cycle this switch on power-up to get video
assign TD_RESET_N = SW[1];
// get some signals exposed
// connect bus master signals to i/o for probes
/*assign GPIO_0[0] = TD_HS ;
assign GPIO_0[1] = TD_VS ;
assign GPIO_0[2] = TD_DATA[6] ;
assign GPIO_0[3] = TD_CLK27 ;
assign GPIO_0[4] = TD_RESET_N ;*/
//=======================================================
// Bus controller for AVALON bus-master
//=======================================================
wire [31:0] vga_bus_addr, video_in_bus_addr ; // Avalon addresses
reg [31:0] bus_addr ;
wire [31:0] vga_out_base_address = 32'h0000_0000 ; // Avalon address
wire [31:0] video_in_base_address = 32'h0800_0000 ; // Avalon address
reg [3:0] bus_byte_enable ; // four bit byte read/write mask
reg bus_read ; // high when requesting data
reg bus_write ; // high when writing data
reg [31:0] bus_write_data ; // data to send to Avalog bus
wire bus_ack ; // Avalon bus raises this when done
wire [31:0] bus_read_data ; // data from Avalon bus
reg [31:0] timer ;
reg [3:0] state ; //change here
reg last_vs, wait_one;
reg [19:0] vs_count ;
reg last_hs, wait_one_hs ;
reg [19:0] hs_count ;
wire [31:0] pix_1_addr ;
wire [31:0] pix_2_addr ;
wire [31:0] pix_3_addr ;
wire [31:0] pix_4_addr ;
// pixel address is
reg [9:0] vga_x_cood, vga_y_cood, video_in_x_cood, video_in_y_cood ;
reg [7:0] current_pixel_color1, current_pixel_color2 ;
// compute address
//assign vga_bus_addr = vga_out_base_address + {22'b0,video_in_x_cood + vga_x_cood} + ({22'b0,video_in_y_cood + vga_y_cood}<<10) ;
//assign vga_bus_addr = vga_out_base_address + {22'b0,vga_x_cood} + ({22'b0,vga_y_cood}<<10) ;
assign video_in_bus_addr = video_in_base_address + {22'b0,video_in_x_cood} + ({22'b0,video_in_y_cood}<<9) ;
wire [9:0] video_x_addr_in;
wire [9:0] video_y_addr_in;
assign video_x_addr_in = GPIO_0[15:6];
assign video_y_addr_in[9:4] = GPIO_0[5:0];
assign video_y_addr_in[3:2] = GPIO_1[29:28];
assign video_y_addr_in[1:0] = GPIO_1[13:12];
assign pix_1_addr = vga_out_base_address + {22'b0,video_x_addr_in << 1} + 0 + ({22'b0, (video_y_addr_in << 1) + 0} << 10);
assign pix_2_addr = vga_out_base_address + {22'b0,video_x_addr_in << 1} + 1 + ({22'b0, (video_y_addr_in << 1) + 0} << 10);
assign pix_3_addr = vga_out_base_address + {22'b0,video_x_addr_in << 1} + 1 + ({22'b0, (video_y_addr_in << 1) + 1} << 10);
assign pix_4_addr = vga_out_base_address + {22'b0,video_x_addr_in << 1} + 0 + ({22'b0, (video_y_addr_in << 1) + 1} << 10);
//assign pix_1_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 0 + ({22'b0, (video_in_y_cood << 1) + 0} << 10);
//assign pix_2_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 1 + ({22'b0, (video_in_y_cood << 1) + 0} << 10);
//assign pix_3_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 1 + ({22'b0, (video_in_y_cood << 1) + 1} << 10);
//assign pix_4_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 0 + ({22'b0, (video_in_y_cood << 1) + 1} << 10);
reg my_data_ready;
wire your_data_ready;
assign GPIO_1[0] = write_now;
assign GPIO_1[1] = read_now;
wire [7:0] curr_pix;
wire [7:0] get_pix = GPIO_1[27:20];
assign curr_pix = current_pixel_color1;
reg[4:0] delay_timer;
HexDigit Digit0(HEX0, state);
HexDigit Digit1(HEX1, {3'b0, your_data_ready});
HexDigit Digit2(HEX2, {3'b0, my_data_ready});
reg [1:0] cyc_handshake_write;
reg [1:0] cyc_handshake_read;
reg read_now;
reg write_now;
wire your_write_finish;
assign your_write_finish = GPIO_1[3];
assign your_data_ready = GPIO_1[2];
assign GPIO_1[11:4] = curr_pix;
reg [7:0] get_pix_reg;
wire other_rst;
assign GPIO_0[35:26] = video_in_x_cood;
assign GPIO_0[25:16] = video_in_y_cood;
always@(posedge CLOCK2_50) begin
if (~KEY[0]) begin
cyc_handshake_read <=2'b0;
end
else if (my_data_ready & your_data_ready) begin
cyc_handshake_read <= cyc_handshake_read +2'b1;
end
else cyc_handshake_read <= cyc_handshake_read;
end
reg my_write_finish;
always@(posedge CLOCK2_50) begin
if (~KEY[0]) begin
cyc_handshake_write <=2'b0;
end
else if (my_write_finish & your_write_finish) begin
cyc_handshake_write<= cyc_handshake_write +2'b1;
end
else cyc_handshake_write <= cyc_handshake_write;
end
always @(posedge CLOCK2_50) begin //CLOCK_50
if (SW[5]==0) begin
state<=0;
end
else begin
// reset state machine and read/write controls
if (~KEY[0]) begin
state <= 0 ;
bus_read <= 0 ; // set to one if a read opeation from bus
bus_write <= 0 ; // set to on if a write operation to bus
// base address of upper-left corner of the screen
vga_x_cood <= 0 ;
vga_y_cood <= 0 ;
video_in_x_cood <= 0 ;
video_in_y_cood <= 0 ;
bus_byte_enable <= 4'b0001;
my_data_ready <=0;
timer <= 0;
delay_timer <=0;
my_write_finish <=0;
my_data_ready <=0;
end
else begin
timer <= timer + 1;
end
// if (state==2) begin
// state <= read_done ? 0 :2;
// end
// write to the bus-master
// and put in a small delay to aviod bus hogging
// timer delay can be set to 2**n-1, so 3, 7, 15, 31
// bigger numbers mean slower frame update to VGA
if (state==0 && SW[0] && (timer & 31)==0 ) begin //
my_write_finish <=0;
my_data_ready <=0;
read_now <=1;
write_now <=0;
state <= 1;
// i_give_pixel <= 0;
// i_display_pixel <= 0;
// read all the pixels in the video input
video_in_x_cood <= video_in_x_cood + 10'd1 ;
if (video_in_x_cood > 10'd319) begin
video_in_x_cood <= 0 ;
video_in_y_cood <= video_in_y_cood + 10'd1 ;
if (video_in_y_cood > 10'd239) begin
video_in_y_cood <= 10'd0 ;
end
end
// one byte data
bus_byte_enable <= 4'b0001;
// read first pixel
bus_addr <= video_in_bus_addr ;
// signal the bus that a read is requested
bus_read <= 1'b1 ;
end
// finish the read
// You MUST do this check
if (state==1 && bus_ack==1) begin
state <= 2 ; //state <= 2 ;
bus_read <= 1'b0;
current_pixel_color1 <= bus_read_data ;
my_data_ready <= 1;
end
if (state ==3) begin
//state <= you_display_pixel ? 8 :3;delay_timer
state <= (delay_timer==4'd31) ? 0 :3;
delay_timer <= delay_timer + 4'b1;
get_pix_reg <= get_pix;
end
if (state==2) begin
state <= (cyc_handshake_read==2'b11) ? 8 : 2 ; //state <= 2 ;
get_pix_reg <= get_pix;
end
// write a pixel to VGA memory
// if (state==8 && you_display_pixel==1 && (SW[7]==1)) begin
if (state==8 /*&& my_data_ready == 1 && your_data_ready == 1*/) begin
state <= 9;
bus_write <= 1'b1;
bus_addr <= pix_1_addr ;
bus_write_data <= get_pix_reg; //curr_pix; //get_pix_reg; //curr_pix; //GPIO_1[9:2];//curr_pix;//current_pixel_color1 ;
bus_byte_enable <= 4'b0001;
delay_timer <=0;
my_data_ready <= 0;
write_now <=1;
read_now <=0;
end
// and finish write
if (state==9 && bus_ack==1) begin
state <= 10 ;
bus_write <= 1'b0;
end
// write a pixel to VGA memory
if (state==10) begin
state <= 11 ;
bus_write <= 1'b1;
bus_addr <= pix_2_addr ;
bus_write_data <= get_pix_reg; //curr_pix; //get_pix_reg; //curr_pix; //GPIO_1[9:2];//curr_pix;//current_pixel_color1
bus_byte_enable <= 4'b0001;
end
// and finish write
if (state==11 && bus_ack==1) begin
state <= 12 ;
bus_write <= 1'b0;
end
// write a pixel to VGA memory
if (state==12) begin
state <= 13 ;
bus_write <= 1'b1;
bus_addr <= pix_3_addr ;
bus_write_data <= get_pix_reg; //curr_pix; //get_pix_reg;//curr_pix; //GPIO_1[9:2];//curr_pix;//current_pixel_color1
bus_byte_enable <= 4'b0001;
my_data_ready <= 0;
end
// and finish write
if (state==13 && bus_ack==1) begin
state <= 14 ;
bus_write <= 1'b0;
end
// write a pixel to VGA memory
if (state==14) begin
state <= 15 ;
bus_write <= 1'b1;
bus_addr <= pix_4_addr ;
bus_write_data <= get_pix_reg; //curr_pix; //get_pix_reg;//curr_pix; //GPIO_1[9:2];//curr_pix;//current_pixel_color1
bus_byte_enable <= 4'b0001;
my_write_finish <=0;
end
// and finish write
if (state==15 && bus_ack==1) begin
state <= 4 ;
bus_write <= 1'b0;
// i_display_pixel <=1;
my_write_finish <=1;
end
if (state==4) begin
state <= (cyc_handshake_write==2'b11) ? 0 : 4 ; //state <= 2 ;
end
end
end // always @(posedge state_clock)
//=======================================================
// Bus controller for AVALON bus-master
//=======================================================
// computes DDS for sine wave and fills audio FIFO
// reads audio FIFO and loops it back
// MUST configure (in Qsys) Audio Config module
// -- Line in to ADC
// -- uncheck both bypass options
reg [31:0] audio_bus_addr ; // Avalon address
// see
// ftp://ftp.altera.com/up/pub/Altera_Material/15.1/University_Program_IP_Cores/Audio_Video/Audio.pdf
// for addresses
wire [31:0] audio_base_address = 32'h00003040 ; // Avalon address
wire [31:0] audio_fifo_address = 32'h00003044 ; // Avalon address +4 offset
wire [31:0] audio_data_left_address = 32'h00003048 ; // Avalon address +8
wire [31:0] audio_data_right_address = 32'h0000304c ; // Avalon address +12
reg [3:0] audio_bus_byte_enable ; // four bit byte read/write mask
reg audio_bus_read ; // high when requesting data
reg audio_bus_write ; // high when writing data
reg [31:0] audio_bus_write_data ; // data to send to Avalog bus
wire audio_bus_ack ; // Avalon bus raises this when done
wire [31:0] audio_bus_read_data ; // data from Avalon bus
reg [30:0] audio_timer ;
reg [3:0] audio_state ;
wire state_clock ;
// current free words in audio interface
reg [7:0] fifo_space ;
// debug check of space
assign LEDR = fifo_space ;
// use 4-byte-wide bus-master
//assign audio_bus_byte_enable = 4'b1111;
// DDS signals
reg [31:0] audio_dds_accum ;
// DDS LUT
wire [15:0] sine_out ;
sync_rom sineTable(CLOCK_50, audio_dds_accum[31:24], sine_out);
// audio input from audio module FIFO
reg [31:0] right_audio_input, left_audio_input ;
// get some signals exposed
// connect bus master signals to i/o for probes
/*assign GPIO_0[0] = audio_bus_write ;
assign GPIO_0[1] = audio_bus_read ;
assign GPIO_0[2] = audio_bus_ack ; */
//assign GPIO_0[3] = ??? ;
assign GPIO_1[19:14] = left_audio_input[31:26];
//assign = GPIO_1[19:12] ;
always @(posedge CLOCK_50) begin //CLOCK_50
// reset audio_state machine and read/write controls
if (~KEY[1]) begin
audio_state <= 0 ;
audio_bus_read <= 0 ; // set to one if a read opeation from bus
audio_bus_write <= 0 ; // set to one if a write operation to bus
audio_timer <= 0;
end
else begin
// timer just for deubgging
audio_timer <= audio_timer + 1;
end
// === writing stereo to the audio FIFO ==========
// set up read FIFO available space
if (audio_state==4'd0) begin
audio_bus_addr <= audio_fifo_address ;
audio_bus_read <= 1'b1 ;
audio_bus_byte_enable <= 4'b1111;
audio_state <= 4'd1 ; // wait for read ACK
end
// wait for read ACK and read the fifo available
// bus ACK is high when data is available
if (audio_state==4'd1 && audio_bus_ack==1) begin
audio_state <= 4'd2 ; //4'd2
// FIFO write space is in high byte
fifo_space <= (audio_bus_read_data>>24) ;
// end the read
audio_bus_read <= 1'b0 ;
end
// When there is room in the FIFO
// -- compute next DDS sine sample
// -- start write to fifo for each channel
// -- first the left channel
if (audio_state==4'd2 && fifo_space>8'd2) begin //
audio_state <= 4'd3;
// IF SW=10'h200
// and Fout = (sample_rate)/(2^32)*{SW[9:0], 16'b0}
// then Fout=48000/(2^32)*(2^25) = 375 Hz
audio_dds_accum <= audio_dds_accum + {SW[9:0], 16'b0} ;
// convert 16-bit table to 32-bit format
audio_bus_write_data <= SW[6]? (sine_out << 16) : {GPIO_1[35:30], 26'b0};
audio_bus_addr <= audio_data_left_address ;
audio_bus_byte_enable <= 4'b1111;
audio_bus_write <= 1'b1 ;
end
// if no space, try again later
else if (audio_state==4'd2 && fifo_space<=8'd2) begin
audio_state <= 4'b0 ;
end
// detect bus-transaction-complete ACK
// for left channel write
// You MUST do this check
if (audio_state==4'd3 && audio_bus_ack==1) begin
audio_state <= 4'd4 ; // include right channel
//audio_state <= 4'd0 ; // left channel only!
audio_bus_write <= 0;
end
// -- now the right channel
if (audio_state==4'd4) begin //
audio_state <= 4'd5;
// loop back audio input data
// audio_bus_write_data <= right_audio_input ;
audio_bus_write_data <= {GPIO_1[35:30], 26'b0};
audio_bus_addr <= audio_data_right_address ;
audio_bus_write <= 1'b1 ;
end
// detect bus-transaction-complete ACK
// for right channel write
// You MUST do this check
if (audio_state==4'd5 && audio_bus_ack==1) begin
// audio_state <= 4'd0 ; // for write only function
audio_state <= 4'd6 ; // for read/write function
audio_bus_write <= 0;
end
// === reading stereo from the audio FIFO ==========
// set up read FIFO for available read values
if (audio_state==4'd6 ) begin
audio_bus_addr <= audio_fifo_address ;
audio_bus_read <= 1'b1 ;
audio_bus_byte_enable <= 4'b1111;
audio_state <= 4'd7 ; // wait for read ACK
end
// wait for read ACK and read the fifo available
// bus ACK is high when data is available
if (audio_state==4'd7 && audio_bus_ack==1) begin
audio_state <= 4'd8 ; //4'dxx
// FIFO read space is in low byte
// which is zero when empty
fifo_space <= audio_bus_read_data & 8'hff ;
// end the read
audio_bus_read <= 1'b0 ;
end
// When there is data in the read FIFO
// -- read it from both channels
// -- first the left channel
if (audio_state==4'd8 && fifo_space>8'd0) begin //
audio_state <= 4'd9;
audio_bus_addr <= audio_data_left_address ;
audio_bus_byte_enable <= 4'b1111;
audio_bus_read <= 1'b1 ;
end
// if no space, try again later
else if (audio_state==4'd8 && fifo_space<=8'd0) begin
audio_state <= 4'b0 ;
end
// detect bus-transaction-complete ACK
// for left channel read
// You MUST do this check
if (audio_state==4'd9 && audio_bus_ack==1) begin
audio_state <= 4'd10 ; // include right channel
left_audio_input <= audio_bus_read_data ;
audio_bus_read <= 0;
end
// When there is data in the read FIFO
// -- read it from both channels
// -- now right channel
if (audio_state==4'd10) begin //
audio_state <= 4'd11;
audio_bus_addr <= audio_data_right_address ;
audio_bus_byte_enable <= 4'b1111;
audio_bus_read <= 1'b1 ;
end
// detect bus-transaction-complete ACK
// for left channel read
// You MUST do this check
if (audio_state==4'd11 && audio_bus_ack==1) begin
audio_state <= 4'd0 ; // back to beginning
right_audio_input <= audio_bus_read_data ;
audio_bus_read <= 0;
end
end // always @(posedge state_clock)
//=======================================================
// Structural coding
//=======================================================
Computer_System The_System (
////////////////////////////////////
// FPGA Side
////////////////////////////////////
// Global signals
.system_pll_ref_clk_clk (CLOCK_50),
.system_pll_ref_reset_reset (1'b0),
// AV Config
.av_config_SCLK (FPGA_I2C_SCLK),
.av_config_SDAT (FPGA_I2C_SDAT),
// VGA Subsystem
.vga_pll_ref_clk_clk (CLOCK2_50),
.vga_pll_ref_reset_reset (1'b0),
.vga_CLK (VGA_CLK),
.vga_BLANK (VGA_BLANK_N),
.vga_SYNC (VGA_SYNC_N),
.vga_HS (VGA_HS),
.vga_VS (VGA_VS),
.vga_R (VGA_R),
.vga_G (VGA_G),
.vga_B (VGA_B),
// Video In Subsystem
.video_in_TD_CLK27 (TD_CLK27),
.video_in_TD_DATA (TD_DATA),
.video_in_TD_HS (TD_HS),
.video_in_TD_VS (TD_VS),
.video_in_clk27_reset (),
.video_in_TD_RESET (),
.video_in_overflow_flag (),
.ebab_video_in_external_interface_address (bus_addr), //
.ebab_video_in_external_interface_byte_enable (bus_byte_enable), // .byte_enable
.ebab_video_in_external_interface_read (bus_read), // .read
.ebab_video_in_external_interface_write (bus_write), // .write
.ebab_video_in_external_interface_write_data (bus_write_data), //.write_data
.ebab_video_in_external_interface_acknowledge (bus_ack), // .acknowledge
.ebab_video_in_external_interface_read_data (bus_read_data),
// clock bridge for EBAb_video_in_external_interface_acknowledge
.clock_bridge_0_in_clk_clk (CLOCK_50),
// SDRAM
.sdram_clk_clk (DRAM_CLK),
.sdram_addr (DRAM_ADDR),
.sdram_ba (DRAM_BA),
.sdram_cas_n (DRAM_CAS_N),
.sdram_cke (DRAM_CKE),
.sdram_cs_n (DRAM_CS_N),
.sdram_dq (DRAM_DQ),
.sdram_dqm ({DRAM_UDQM,DRAM_LDQM}),
.sdram_ras_n (DRAM_RAS_N),
.sdram_we_n (DRAM_WE_N),
// Audio Subsystem
.audio_pll_ref_clk_clk (CLOCK3_50),
.audio_pll_ref_reset_reset (1'b0),
.audio_clk_clk (AUD_XCK),
.audio_ADCDAT (AUD_ADCDAT),
.audio_ADCLRCK (AUD_ADCLRCK),
.audio_BCLK (AUD_BCLK),
.audio_DACDAT (AUD_DACDAT),
.audio_DACLRCK (AUD_DACLRCK),
// bus-master state machine interface
.bus_master_audio_export_address (audio_bus_addr),
.bus_master_audio_export_byte_enable (audio_bus_byte_enable),
.bus_master_audio_export_read (audio_bus_read),
.bus_master_audio_export_write (audio_bus_write),
.bus_master_audio_export_write_data (audio_bus_write_data),
.bus_master_audio_export_acknowledge (audio_bus_ack),
.bus_master_audio_export_read_data (audio_bus_read_data),
////////////////////////////////////
// HPS Side
////////////////////////////////////
// DDR3 SDRAM
.memory_mem_a (HPS_DDR3_ADDR),
.memory_mem_ba (HPS_DDR3_BA),
.memory_mem_ck (HPS_DDR3_CK_P),
.memory_mem_ck_n (HPS_DDR3_CK_N),
.memory_mem_cke (HPS_DDR3_CKE),
.memory_mem_cs_n (HPS_DDR3_CS_N),
.memory_mem_ras_n (HPS_DDR3_RAS_N),
.memory_mem_cas_n (HPS_DDR3_CAS_N),
.memory_mem_we_n (HPS_DDR3_WE_N),
.memory_mem_reset_n (HPS_DDR3_RESET_N),
.memory_mem_dq (HPS_DDR3_DQ),
.memory_mem_dqs (HPS_DDR3_DQS_P),
.memory_mem_dqs_n (HPS_DDR3_DQS_N),
.memory_mem_odt (HPS_DDR3_ODT),
.memory_mem_dm (HPS_DDR3_DM),
.memory_oct_rzqin (HPS_DDR3_RZQ),
// Ethernet
.hps_io_hps_io_gpio_inst_GPIO35 (HPS_ENET_INT_N),
.hps_io_hps_io_emac1_inst_TX_CLK (HPS_ENET_GTX_CLK),
.hps_io_hps_io_emac1_inst_TXD0 (HPS_ENET_TX_DATA[0]),
.hps_io_hps_io_emac1_inst_TXD1 (HPS_ENET_TX_DATA[1]),
.hps_io_hps_io_emac1_inst_TXD2 (HPS_ENET_TX_DATA[2]),
.hps_io_hps_io_emac1_inst_TXD3 (HPS_ENET_TX_DATA[3]),
.hps_io_hps_io_emac1_inst_RXD0 (HPS_ENET_RX_DATA[0]),
.hps_io_hps_io_emac1_inst_MDIO (HPS_ENET_MDIO),
.hps_io_hps_io_emac1_inst_MDC (HPS_ENET_MDC),
.hps_io_hps_io_emac1_inst_RX_CTL (HPS_ENET_RX_DV),
.hps_io_hps_io_emac1_inst_TX_CTL (HPS_ENET_TX_EN),
.hps_io_hps_io_emac1_inst_RX_CLK (HPS_ENET_RX_CLK),
.hps_io_hps_io_emac1_inst_RXD1 (HPS_ENET_RX_DATA[1]),
.hps_io_hps_io_emac1_inst_RXD2 (HPS_ENET_RX_DATA[2]),
.hps_io_hps_io_emac1_inst_RXD3 (HPS_ENET_RX_DATA[3]),
// Flash
.hps_io_hps_io_qspi_inst_IO0 (HPS_FLASH_DATA[0]),
.hps_io_hps_io_qspi_inst_IO1 (HPS_FLASH_DATA[1]),
.hps_io_hps_io_qspi_inst_IO2 (HPS_FLASH_DATA[2]),
.hps_io_hps_io_qspi_inst_IO3 (HPS_FLASH_DATA[3]),
.hps_io_hps_io_qspi_inst_SS0 (HPS_FLASH_NCSO),
.hps_io_hps_io_qspi_inst_CLK (HPS_FLASH_DCLK),
// Accelerometer
.hps_io_hps_io_gpio_inst_GPIO61 (HPS_GSENSOR_INT),
//.adc_sclk (ADC_SCLK),
//.adc_cs_n (ADC_CS_N),
//.adc_dout (ADC_DOUT),
//.adc_din (ADC_DIN),
// General Purpose I/O
.hps_io_hps_io_gpio_inst_GPIO40 (HPS_GPIO[0]),
.hps_io_hps_io_gpio_inst_GPIO41 (HPS_GPIO[1]),
// I2C
.hps_io_hps_io_gpio_inst_GPIO48 (HPS_I2C_CONTROL),
.hps_io_hps_io_i2c0_inst_SDA (HPS_I2C1_SDAT),
.hps_io_hps_io_i2c0_inst_SCL (HPS_I2C1_SCLK),
.hps_io_hps_io_i2c1_inst_SDA (HPS_I2C2_SDAT),
.hps_io_hps_io_i2c1_inst_SCL (HPS_I2C2_SCLK),
// Pushbutton
.hps_io_hps_io_gpio_inst_GPIO54 (HPS_KEY),
// LED
.hps_io_hps_io_gpio_inst_GPIO53 (HPS_LED),
// SD Card
.hps_io_hps_io_sdio_inst_CMD (HPS_SD_CMD),
.hps_io_hps_io_sdio_inst_D0 (HPS_SD_DATA[0]),
.hps_io_hps_io_sdio_inst_D1 (HPS_SD_DATA[1]),
.hps_io_hps_io_sdio_inst_CLK (HPS_SD_CLK),
.hps_io_hps_io_sdio_inst_D2 (HPS_SD_DATA[2]),
.hps_io_hps_io_sdio_inst_D3 (HPS_SD_DATA[3]),
// SPI
.hps_io_hps_io_spim1_inst_CLK (HPS_SPIM_CLK),
.hps_io_hps_io_spim1_inst_MOSI (HPS_SPIM_MOSI),
.hps_io_hps_io_spim1_inst_MISO (HPS_SPIM_MISO),
.hps_io_hps_io_spim1_inst_SS0 (HPS_SPIM_SS),
// UART
.hps_io_hps_io_uart0_inst_RX (HPS_UART_RX),
.hps_io_hps_io_uart0_inst_TX (HPS_UART_TX),
// USB
.hps_io_hps_io_gpio_inst_GPIO09 (HPS_CONV_USB_N),
.hps_io_hps_io_usb1_inst_D0 (HPS_USB_DATA[0]),
.hps_io_hps_io_usb1_inst_D1 (HPS_USB_DATA[1]),
.hps_io_hps_io_usb1_inst_D2 (HPS_USB_DATA[2]),
.hps_io_hps_io_usb1_inst_D3 (HPS_USB_DATA[3]),
.hps_io_hps_io_usb1_inst_D4 (HPS_USB_DATA[4]),
.hps_io_hps_io_usb1_inst_D5 (HPS_USB_DATA[5]),
.hps_io_hps_io_usb1_inst_D6 (HPS_USB_DATA[6]),
.hps_io_hps_io_usb1_inst_D7 (HPS_USB_DATA[7]),
.hps_io_hps_io_usb1_inst_CLK (HPS_USB_CLKOUT),
.hps_io_hps_io_usb1_inst_STP (HPS_USB_STP),
.hps_io_hps_io_usb1_inst_DIR (HPS_USB_DIR),
.hps_io_hps_io_usb1_inst_NXT (HPS_USB_NXT)
);
endmodule
//////////////////////////////////////////////////
//////////// Sin Wave ROM Table //////////////
//////////////////////////////////////////////////
// produces a 2's comp, 16-bit, approximation
// of a sine wave, given an input phase (address)
module sync_rom (clock, address, sine);
input clock;
input [7:0] address;
output [15:0] sine;
reg signed [15:0] sine;
always@(posedge clock)
begin
case(address)
8'h00: sine = 16'h0000 ;
8'h01: sine = 16'h0192 ;
8'h02: sine = 16'h0323 ;
8'h03: sine = 16'h04b5 ;
8'h04: sine = 16'h0645 ;
8'h05: sine = 16'h07d5 ;
8'h06: sine = 16'h0963 ;
8'h07: sine = 16'h0af0 ;
8'h08: sine = 16'h0c7c ;
8'h09: sine = 16'h0e05 ;
8'h0a: sine = 16'h0f8c ;
8'h0b: sine = 16'h1111 ;
8'h0c: sine = 16'h1293 ;
8'h0d: sine = 16'h1413 ;
8'h0e: sine = 16'h158f ;
8'h0f: sine = 16'h1708 ;
8'h10: sine = 16'h187d ;
8'h11: sine = 16'h19ef ;
8'h12: sine = 16'h1b5c ;
8'h13: sine = 16'h1cc5 ;
8'h14: sine = 16'h1e2a ;
8'h15: sine = 16'h1f8b ;
8'h16: sine = 16'h20e6 ;
8'h17: sine = 16'h223c ;
8'h18: sine = 16'h238d ;
8'h19: sine = 16'h24d9 ;
8'h1a: sine = 16'h261f ;
8'h1b: sine = 16'h275f ;
8'h1c: sine = 16'h2899 ;
8'h1d: sine = 16'h29cc ;
8'h1e: sine = 16'h2afa ;
8'h1f: sine = 16'h2c20 ;
8'h20: sine = 16'h2d40 ;
8'h21: sine = 16'h2e59 ;
8'h22: sine = 16'h2f6b ;
8'h23: sine = 16'h3075 ;
8'h24: sine = 16'h3178 ;
8'h25: sine = 16'h3273 ;
8'h26: sine = 16'h3366 ;
8'h27: sine = 16'h3452 ;
8'h28: sine = 16'h3535 ;
8'h29: sine = 16'h3611 ;
8'h2a: sine = 16'h36e4 ;
8'h2b: sine = 16'h37ae ;
8'h2c: sine = 16'h3870 ;
8'h2d: sine = 16'h3929 ;
8'h2e: sine = 16'h39da ;
8'h2f: sine = 16'h3a81 ;
8'h30: sine = 16'h3b1f ;
8'h31: sine = 16'h3bb5 ;
8'h32: sine = 16'h3c41 ;
8'h33: sine = 16'h3cc4 ;
8'h34: sine = 16'h3d3d ;
8'h35: sine = 16'h3dad ;
8'h36: sine = 16'h3e14 ;
8'h37: sine = 16'h3e70 ;
8'h38: sine = 16'h3ec4 ;
8'h39: sine = 16'h3f0d ;
8'h3a: sine = 16'h3f4d ;
8'h3b: sine = 16'h3f83 ;
8'h3c: sine = 16'h3fb0 ;
8'h3d: sine = 16'h3fd2 ;
8'h3e: sine = 16'h3feb ;
8'h3f: sine = 16'h3ffa ;
8'h40: sine = 16'h3fff ;
8'h41: sine = 16'h3ffa ;
8'h42: sine = 16'h3feb ;
8'h43: sine = 16'h3fd2 ;
8'h44: sine = 16'h3fb0 ;
8'h45: sine = 16'h3f83 ;
8'h46: sine = 16'h3f4d ;
8'h47: sine = 16'h3f0d ;
8'h48: sine = 16'h3ec4 ;
8'h49: sine = 16'h3e70 ;
8'h4a: sine = 16'h3e14 ;
8'h4b: sine = 16'h3dad ;
8'h4c: sine = 16'h3d3d ;
8'h4d: sine = 16'h3cc4 ;
8'h4e: sine = 16'h3c41 ;
8'h4f: sine = 16'h3bb5 ;
8'h50: sine = 16'h3b1f ;
8'h51: sine = 16'h3a81 ;
8'h52: sine = 16'h39da ;
8'h53: sine = 16'h3929 ;
8'h54: sine = 16'h3870 ;
8'h55: sine = 16'h37ae ;
8'h56: sine = 16'h36e4 ;
8'h57: sine = 16'h3611 ;
8'h58: sine = 16'h3535 ;
8'h59: sine = 16'h3452 ;
8'h5a: sine = 16'h3366 ;
8'h5b: sine = 16'h3273 ;
8'h5c: sine = 16'h3178 ;
8'h5d: sine = 16'h3075 ;
8'h5e: sine = 16'h2f6b ;
8'h5f: sine = 16'h2e59 ;
8'h60: sine = 16'h2d40 ;
8'h61: sine = 16'h2c20 ;
8'h62: sine = 16'h2afa ;
8'h63: sine = 16'h29cc ;
8'h64: sine = 16'h2899 ;
8'h65: sine = 16'h275f ;
8'h66: sine = 16'h261f ;
8'h67: sine = 16'h24d9 ;
8'h68: sine = 16'h238d ;
8'h69: sine = 16'h223c ;
8'h6a: sine = 16'h20e6 ;
8'h6b: sine = 16'h1f8b ;
8'h6c: sine = 16'h1e2a ;
8'h6d: sine = 16'h1cc5 ;
8'h6e: sine = 16'h1b5c ;
8'h6f: sine = 16'h19ef ;
8'h70: sine = 16'h187d ;
8'h71: sine = 16'h1708 ;
8'h72: sine = 16'h158f ;
8'h73: sine = 16'h1413 ;
8'h74: sine = 16'h1293 ;
8'h75: sine = 16'h1111 ;
8'h76: sine = 16'h0f8c ;
8'h77: sine = 16'h0e05 ;
8'h78: sine = 16'h0c7c ;
8'h79: sine = 16'h0af0 ;
8'h7a: sine = 16'h0963 ;
8'h7b: sine = 16'h07d5 ;
8'h7c: sine = 16'h0645 ;
8'h7d: sine = 16'h04b5 ;
8'h7e: sine = 16'h0323 ;
8'h7f: sine = 16'h0192 ;
8'h80: sine = 16'h0000 ;
8'h81: sine = 16'hfe6e ;
8'h82: sine = 16'hfcdd ;
8'h83: sine = 16'hfb4b ;
8'h84: sine = 16'hf9bb ;
8'h85: sine = 16'hf82b ;
8'h86: sine = 16'hf69d ;
8'h87: sine = 16'hf510 ;
8'h88: sine = 16'hf384 ;
8'h89: sine = 16'hf1fb ;
8'h8a: sine = 16'hf074 ;
8'h8b: sine = 16'heeef ;
8'h8c: sine = 16'hed6d ;
8'h8d: sine = 16'hebed ;
8'h8e: sine = 16'hea71 ;
8'h8f: sine = 16'he8f8 ;
8'h90: sine = 16'he783 ;
8'h91: sine = 16'he611 ;
8'h92: sine = 16'he4a4 ;
8'h93: sine = 16'he33b ;
8'h94: sine = 16'he1d6 ;
8'h95: sine = 16'he075 ;
8'h96: sine = 16'hdf1a ;
8'h97: sine = 16'hddc4 ;
8'h98: sine = 16'hdc73 ;
8'h99: sine = 16'hdb27 ;
8'h9a: sine = 16'hd9e1 ;
8'h9b: sine = 16'hd8a1 ;
8'h9c: sine = 16'hd767 ;
8'h9d: sine = 16'hd634 ;
8'h9e: sine = 16'hd506 ;
8'h9f: sine = 16'hd3e0 ;
8'ha0: sine = 16'hd2c0 ;
8'ha1: sine = 16'hd1a7 ;
8'ha2: sine = 16'hd095 ;
8'ha3: sine = 16'hcf8b ;
8'ha4: sine = 16'hce88 ;
8'ha5: sine = 16'hcd8d ;
8'ha6: sine = 16'hcc9a ;
8'ha7: sine = 16'hcbae ;
8'ha8: sine = 16'hcacb ;
8'ha9: sine = 16'hc9ef ;
8'haa: sine = 16'hc91c ;
8'hab: sine = 16'hc852 ;
8'hac: sine = 16'hc790 ;
8'had: sine = 16'hc6d7 ;
8'hae: sine = 16'hc626 ;
8'haf: sine = 16'hc57f ;
8'hb0: sine = 16'hc4e1 ;
8'hb1: sine = 16'hc44b ;
8'hb2: sine = 16'hc3bf ;
8'hb3: sine = 16'hc33c ;
8'hb4: sine = 16'hc2c3 ;
8'hb5: sine = 16'hc253 ;
8'hb6: sine = 16'hc1ec ;
8'hb7: sine = 16'hc190 ;
8'hb8: sine = 16'hc13c ;
8'hb9: sine = 16'hc0f3 ;
8'hba: sine = 16'hc0b3 ;
8'hbb: sine = 16'hc07d ;
8'hbc: sine = 16'hc050 ;
8'hbd: sine = 16'hc02e ;
8'hbe: sine = 16'hc015 ;
8'hbf: sine = 16'hc006 ;
8'hc0: sine = 16'hc001 ;
8'hc1: sine = 16'hc006 ;
8'hc2: sine = 16'hc015 ;
8'hc3: sine = 16'hc02e ;
8'hc4: sine = 16'hc050 ;
8'hc5: sine = 16'hc07d ;
8'hc6: sine = 16'hc0b3 ;
8'hc7: sine = 16'hc0f3 ;
8'hc8: sine = 16'hc13c ;
8'hc9: sine = 16'hc190 ;
8'hca: sine = 16'hc1ec ;
8'hcb: sine = 16'hc253 ;
8'hcc: sine = 16'hc2c3 ;
8'hcd: sine = 16'hc33c ;
8'hce: sine = 16'hc3bf ;
8'hcf: sine = 16'hc44b ;
8'hd0: sine = 16'hc4e1 ;
8'hd1: sine = 16'hc57f ;
8'hd2: sine = 16'hc626 ;
8'hd3: sine = 16'hc6d7 ;
8'hd4: sine = 16'hc790 ;
8'hd5: sine = 16'hc852 ;
8'hd6: sine = 16'hc91c ;
8'hd7: sine = 16'hc9ef ;
8'hd8: sine = 16'hcacb ;
8'hd9: sine = 16'hcbae ;
8'hda: sine = 16'hcc9a ;
8'hdb: sine = 16'hcd8d ;
8'hdc: sine = 16'hce88 ;
8'hdd: sine = 16'hcf8b ;
8'hde: sine = 16'hd095 ;
8'hdf: sine = 16'hd1a7 ;
8'he0: sine = 16'hd2c0 ;
8'he1: sine = 16'hd3e0 ;
8'he2: sine = 16'hd506 ;
8'he3: sine = 16'hd634 ;
8'he4: sine = 16'hd767 ;
8'he5: sine = 16'hd8a1 ;
8'he6: sine = 16'hd9e1 ;
8'he7: sine = 16'hdb27 ;
8'he8: sine = 16'hdc73 ;
8'he9: sine = 16'hddc4 ;
8'hea: sine = 16'hdf1a ;
8'heb: sine = 16'he075 ;
8'hec: sine = 16'he1d6 ;
8'hed: sine = 16'he33b ;
8'hee: sine = 16'he4a4 ;
8'hef: sine = 16'he611 ;
8'hf0: sine = 16'he783 ;
8'hf1: sine = 16'he8f8 ;
8'hf2: sine = 16'hea71 ;
8'hf3: sine = 16'hebed ;
8'hf4: sine = 16'hed6d ;
8'hf5: sine = 16'heeef ;
8'hf6: sine = 16'hf074 ;
8'hf7: sine = 16'hf1fb ;
8'hf8: sine = 16'hf384 ;
8'hf9: sine = 16'hf510 ;
8'hfa: sine = 16'hf69d ;
8'hfb: sine = 16'hf82b ;
8'hfc: sine = 16'hf9bb ;
8'hfd: sine = 16'hfb4b ;
8'hfe: sine = 16'hfcdd ;
8'hff: sine = 16'hfe6e ;
endcase
end
endmodule
module DE1_SoC_Computer (
////////////////////////////////////
// FPGA Pins
////////////////////////////////////
// Clock pins
CLOCK_50,
CLOCK2_50,
CLOCK3_50,
CLOCK4_50,
// ADC
ADC_CS_N,
ADC_DIN,
ADC_DOUT,
ADC_SCLK,
// Audio
AUD_ADCDAT,
AUD_ADCLRCK,
AUD_BCLK,
AUD_DACDAT,
AUD_DACLRCK,
AUD_XCK,
// SDRAM
DRAM_ADDR,
DRAM_BA,
DRAM_CAS_N,
DRAM_CKE,
DRAM_CLK,
DRAM_CS_N,
DRAM_DQ,
DRAM_LDQM,
DRAM_RAS_N,
DRAM_UDQM,
DRAM_WE_N,
// I2C Bus for Configuration of the Audio and Video-In Chips
FPGA_I2C_SCLK,
FPGA_I2C_SDAT,
// 40-Pin Headers
GPIO_0,
GPIO_1,
// Seven Segment Displays
HEX0,
HEX1,
HEX2,
HEX3,
HEX4,
HEX5,
// IR
IRDA_RXD,
IRDA_TXD,
// Pushbuttons
KEY,
// LEDs
LEDR,
// PS2 Ports
PS2_CLK,
PS2_DAT,
PS2_CLK2,
PS2_DAT2,
// Slider Switches
SW,
// Video-In
TD_CLK27,
TD_DATA,
TD_HS,
TD_RESET_N,
TD_VS,
// VGA
VGA_B,
VGA_BLANK_N,
VGA_CLK,
VGA_G,
VGA_HS,
VGA_R,
VGA_SYNC_N,
VGA_VS,
////////////////////////////////////
// HPS Pins
////////////////////////////////////
// DDR3 SDRAM
HPS_DDR3_ADDR,
HPS_DDR3_BA,
HPS_DDR3_CAS_N,
HPS_DDR3_CKE,
HPS_DDR3_CK_N,
HPS_DDR3_CK_P,
HPS_DDR3_CS_N,
HPS_DDR3_DM,
HPS_DDR3_DQ,
HPS_DDR3_DQS_N,
HPS_DDR3_DQS_P,
HPS_DDR3_ODT,
HPS_DDR3_RAS_N,
HPS_DDR3_RESET_N,
HPS_DDR3_RZQ,
HPS_DDR3_WE_N,
// Ethernet
HPS_ENET_GTX_CLK,
HPS_ENET_INT_N,
HPS_ENET_MDC,
HPS_ENET_MDIO,
HPS_ENET_RX_CLK,
HPS_ENET_RX_DATA,
HPS_ENET_RX_DV,
HPS_ENET_TX_DATA,
HPS_ENET_TX_EN,
// Flash
HPS_FLASH_DATA,
HPS_FLASH_DCLK,
HPS_FLASH_NCSO,
// Accelerometer
HPS_GSENSOR_INT,
// General Purpose I/O
HPS_GPIO,
// I2C
HPS_I2C_CONTROL,
HPS_I2C1_SCLK,
HPS_I2C1_SDAT,
HPS_I2C2_SCLK,
HPS_I2C2_SDAT,
// Pushbutton
HPS_KEY,
// LED
HPS_LED,
// SD Card
HPS_SD_CLK,
HPS_SD_CMD,
HPS_SD_DATA,
// SPI
HPS_SPIM_CLK,
HPS_SPIM_MISO,
HPS_SPIM_MOSI,
HPS_SPIM_SS,
// UART
HPS_UART_RX,
HPS_UART_TX,
// USB
HPS_CONV_USB_N,
HPS_USB_CLKOUT,
HPS_USB_DATA,
HPS_USB_DIR,
HPS_USB_NXT,
HPS_USB_STP
);
//=======================================================
// PARAMETER declarations
//=======================================================
//=======================================================
// PORT declarations
//=======================================================
////////////////////////////////////
// FPGA Pins
////////////////////////////////////
// Clock pins
input CLOCK_50;
input CLOCK2_50;
input CLOCK3_50;
input CLOCK4_50;
// ADC
inout ADC_CS_N;
output ADC_DIN;
input ADC_DOUT;
output ADC_SCLK;
// Audio
input AUD_ADCDAT;
inout AUD_ADCLRCK;
inout AUD_BCLK;
output AUD_DACDAT;
inout AUD_DACLRCK;
output AUD_XCK;
// SDRAM
output [12: 0] DRAM_ADDR;
output [ 1: 0] DRAM_BA;
output DRAM_CAS_N;
output DRAM_CKE;
output DRAM_CLK;
output DRAM_CS_N;
inout [15: 0] DRAM_DQ;
output DRAM_LDQM;
output DRAM_RAS_N;
output DRAM_UDQM;
output DRAM_WE_N;
// I2C Bus for Configuration of the Audio and Video-In Chips
output FPGA_I2C_SCLK;
inout FPGA_I2C_SDAT;
// 40-pin headers
inout [35: 0] GPIO_0;
inout [35: 0] GPIO_1;
// Seven Segment Displays
output [ 6: 0] HEX0;
output [ 6: 0] HEX1;
output [ 6: 0] HEX2;
output [ 6: 0] HEX3;
output [ 6: 0] HEX4;
output [ 6: 0] HEX5;
// IR
input IRDA_RXD;
output IRDA_TXD;
// Pushbuttons
input [ 3: 0] KEY;
// LEDs
output [ 9: 0] LEDR;
// PS2 Ports
inout PS2_CLK;
inout PS2_DAT;
inout PS2_CLK2;
inout PS2_DAT2;
// Slider Switches
input [ 9: 0] SW;
// Video-In
input TD_CLK27;
input [ 7: 0] TD_DATA;
input TD_HS;
output TD_RESET_N;
input TD_VS;
// VGA
output [ 7: 0] VGA_B;
output VGA_BLANK_N;
output VGA_CLK;
output [ 7: 0] VGA_G;
output VGA_HS;
output [ 7: 0] VGA_R;
output VGA_SYNC_N;
output VGA_VS;
////////////////////////////////////
// HPS Pins
////////////////////////////////////
// DDR3 SDRAM
output [14: 0] HPS_DDR3_ADDR;
output [ 2: 0] HPS_DDR3_BA;
output HPS_DDR3_CAS_N;
output HPS_DDR3_CKE;
output HPS_DDR3_CK_N;
output HPS_DDR3_CK_P;
output HPS_DDR3_CS_N;
output [ 3: 0] HPS_DDR3_DM;
inout [31: 0] HPS_DDR3_DQ;
inout [ 3: 0] HPS_DDR3_DQS_N;
inout [ 3: 0] HPS_DDR3_DQS_P;
output HPS_DDR3_ODT;
output HPS_DDR3_RAS_N;
output HPS_DDR3_RESET_N;
input HPS_DDR3_RZQ;
output HPS_DDR3_WE_N;
// Ethernet
output HPS_ENET_GTX_CLK;
inout HPS_ENET_INT_N;
output HPS_ENET_MDC;
inout HPS_ENET_MDIO;
input HPS_ENET_RX_CLK;
input [ 3: 0] HPS_ENET_RX_DATA;
input HPS_ENET_RX_DV;
output [ 3: 0] HPS_ENET_TX_DATA;
output HPS_ENET_TX_EN;
// Flash
inout [ 3: 0] HPS_FLASH_DATA;
output HPS_FLASH_DCLK;
output HPS_FLASH_NCSO;
// Accelerometer
inout HPS_GSENSOR_INT;
// General Purpose I/O
inout [ 1: 0] HPS_GPIO;
// I2C
inout HPS_I2C_CONTROL;
inout HPS_I2C1_SCLK;
inout HPS_I2C1_SDAT;
inout HPS_I2C2_SCLK;
inout HPS_I2C2_SDAT;
// Pushbutton
inout HPS_KEY;
// LED
inout HPS_LED;
// SD Card
output HPS_SD_CLK;
inout HPS_SD_CMD;
inout [ 3: 0] HPS_SD_DATA;
// SPI
output HPS_SPIM_CLK;
input HPS_SPIM_MISO;
output HPS_SPIM_MOSI;
inout HPS_SPIM_SS;
// UART
input HPS_UART_RX;
output HPS_UART_TX;
// USB
inout HPS_CONV_USB_N;
input HPS_USB_CLKOUT;
inout [ 7: 0] HPS_USB_DATA;
input HPS_USB_DIR;
input HPS_USB_NXT;
output HPS_USB_STP;
//=======================================================
// REG/WIRE declarations
//=======================================================
wire [15: 0] hex3_hex0;
//wire [15: 0] hex5_hex4;
//assign HEX0 = ~hex3_hex0[ 6: 0]; // hex3_hex0[ 6: 0];
//assign HEX1 = ~hex3_hex0[14: 8];
//assign HEX2 = ~hex3_hex0[22:16];
//assign HEX3 = ~hex3_hex0[30:24];
//assign HEX4 = 7'b1111111;
//assign HEX5 = 7'b1111111;
//HexDigit Digit2(HEX2, hex3_hex0[11:8]);
//HexDigit Digit3(HEX3, hex3_hex0[15:12]);
// MAY need to cycle this switch on power-up to get video
assign TD_RESET_N = SW[1];
// get some signals exposed
// connect bus master signals to i/o for probes
/*assign GPIO_0[0] = TD_HS ;
assign GPIO_0[1] = TD_VS ;
assign GPIO_0[2] = TD_DATA[6] ;
assign GPIO_0[3] = TD_CLK27 ;
assign GPIO_0[4] = TD_RESET_N ;*/
////=======================================================
//// Bus controller for AVALON bus-master
////=======================================================
//wire [31:0] vga_bus_addr, video_in_bus_addr ; // Avalon addresses
//reg [31:0] bus_addr ;
//wire [31:0] vga_out_base_address = 32'h0000_0000 ; // Avalon address
//wire [31:0] video_in_base_address = 32'h0800_0000 ; // Avalon address
//reg [3:0] bus_byte_enable ; // four bit byte read/write mask
//reg bus_read ; // high when requesting data
//reg bus_write ; // high when writing data
//reg [31:0] bus_write_data ; // data to send to Avalog bus
//wire bus_ack ; // Avalon bus raises this when done
//wire [31:0] bus_read_data ; // data from Avalon bus
//reg [31:0] timer ;
//reg [3:0] state ;
//reg last_vs, wait_one;
//reg [19:0] vs_count ;
//reg last_hs, wait_one_hs ;
//reg [19:0] hs_count ;
//wire [31:0] pix_1_addr ;
//wire [31:0] pix_2_addr ;
//wire [31:0] pix_3_addr ;
//wire [31:0] pix_4_addr ;
//
//
//// pixel address is
//reg [9:0] vga_x_cood, vga_y_cood, video_in_x_cood, video_in_y_cood ;
//reg [7:0] current_pixel_color1, current_pixel_color2 ;
//// compute address
////assign vga_bus_addr = vga_out_base_address + {22'b0,video_in_x_cood + vga_x_cood} + ({22'b0,video_in_y_cood + vga_y_cood}<<10) ;
////assign vga_bus_addr = vga_out_base_address + {22'b0,vga_x_cood} + ({22'b0,vga_y_cood}<<10) ;
//assign video_in_bus_addr = video_in_base_address + {22'b0,video_in_x_cood} + ({22'b0,video_in_y_cood}<<9) ;
//
//assign pix_1_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 0 + ({22'b0, (video_in_y_cood << 1) + 0} << 10);
//assign pix_2_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 1 + ({22'b0, (video_in_y_cood << 1) + 0} << 10);
//assign pix_3_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 1 + ({22'b0, (video_in_y_cood << 1) + 1} << 10);
//assign pix_4_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 0 + ({22'b0, (video_in_y_cood << 1) + 1} << 10);
//
//reg my_data_ready;
//wire your_data_ready;
//
//assign your_data_ready = 1; //GPIO_1[23];
////assign your_data_ready = 1;
//
////
////assign you_give_pixel = 1;
////assign you_display_pixel = 1;
//
//
//wire [7:0] curr_pix;
//
////assign curr_pix = GPIO_1[9:2];
//
//assign GPIO_1[9:2] = curr_pix;
//
//assign curr_pix = current_pixel_color1;
//assign GPIO_1[24] = my_data_ready;
//
//reg [4:0] delay_timer;
//
//
//
//HexDigit Digit0(HEX0, state);
//HexDigit Digit1(HEX1, {3'b0, my_data_ready});
//HexDigit Digit2(HEX2, {3'b0, your_data_ready});
//
//
//always @(posedge CLOCK2_50) begin //CLOCK_50
//
// // reset state machine and read/write controls
// if (~KEY[0]) begin
// state <= 0 ;
// bus_read <= 0 ; // set to one if a read opeation from bus
// bus_write <= 0 ; // set to on if a write operation to bus
// // base address of upper-left corner of the screen
// vga_x_cood <= 0 ;
// vga_y_cood <= 0 ;
// video_in_x_cood <= 0 ;
// video_in_y_cood <= 0 ;
// bus_byte_enable <= 4'b0001;
// my_data_ready <=0;
// timer <= 0;
// delay_timer <=0;
// end
// else begin
// timer <= timer + 1;
// end
//// if (state==2) begin
//// state <= read_done ? 0 :2;
//
//// end
// // write to the bus-master
// // and put in a small delay to aviod bus hogging
// // timer delay can be set to 2**n-1, so 3, 7, 15, 31
// // bigger numbers mean slower frame update to VGA
// if (state==0 && SW[0] && (timer & 31)==0 ) begin //
// state <= 1;
//// i_give_pixel <= 0;
//// i_display_pixel <= 0;
//
// // read all the pixels in the video input
// video_in_x_cood <= video_in_x_cood + 10'd1 ;
// if (video_in_x_cood > 10'd319) begin
// video_in_x_cood <= 0 ;
// video_in_y_cood <= video_in_y_cood + 10'd1 ;
// if (video_in_y_cood > 10'd239) begin
// video_in_y_cood <= 10'd0 ;
// end
// end
//
// // one byte data
// bus_byte_enable <= 4'b0001;
// // read first pixel
// bus_addr <= video_in_bus_addr ;
// // signal the bus that a read is requested
// bus_read <= 1'b1 ;
// end
//
// // finish the read
// // You MUST do this check
// if (state==1 && bus_ack==1) begin
// state <= 2 ; //state <= 2 ;
// bus_read <= 1'b0;
// current_pixel_color1 <= bus_read_data ;
// end
//
// if (state ==3) begin
// //state <= you_display_pixel ? 8 :3;delay_timer
// state <= (delay_timer==4'd31) ? 0 :3;
// delay_timer <= delay_timer + 4'b1;
// end
//
// if (state==2) begin
// state <= 8 ; //state <= 2 ;
// my_data_ready <= 1;
// end
//
// // write a pixel to VGA memory
//// if (state==8 && you_display_pixel==1 && (SW[7]==1)) begin
// if (state==8 && my_data_ready == 1 && your_data_ready == 1) begin
// state <= 9;
// bus_write <= 1'b1;
// bus_addr <= pix_1_addr ;
// bus_write_data <= curr_pix;//current_pixel_color1 ;
// bus_byte_enable <= 4'b0001;
// delay_timer <=0;
// end
//
// // and finish write
// if (state==9 && bus_ack==1) begin
// state <= 10 ;
// bus_write <= 1'b0;
// end
//
// // write a pixel to VGA memory
// if (state==10) begin
// state <= 11 ;
// bus_write <= 1'b1;
// bus_addr <= pix_2_addr ;
// bus_write_data <= curr_pix;//current_pixel_color1
// bus_byte_enable <= 4'b0001;
// end
//
// // and finish write
// if (state==11 && bus_ack==1) begin
// state <= 12 ;
// bus_write <= 1'b0;
// end
//
// // write a pixel to VGA memory
// if (state==12) begin
// state <= 13 ;
// bus_write <= 1'b1;
// bus_addr <= pix_3_addr ;
// bus_write_data <= curr_pix;//current_pixel_color1
// bus_byte_enable <= 4'b0001;
//
// my_data_ready <= 0;
//
// end
//
// // and finish write
// if (state==13 && bus_ack==1) begin
// state <= 14 ;
// bus_write <= 1'b0;
// end
//
// // write a pixel to VGA memory
// if (state==14) begin
// state <= 15 ;
// bus_write <= 1'b1;
// bus_addr <= pix_4_addr ;
// bus_write_data <= curr_pix;//current_pixel_color1
// bus_byte_enable <= 4'b0001;
// end
//
// // and finish write
// if (state==15 && bus_ack==1) begin
// state <= 0 ;
// bus_write <= 1'b0;
//// i_display_pixel <=1;
//
// end
//
//end // always @(posedge state_clock)
//=======================================================
// Bus controller for AVALON bus-master
//=======================================================
// computes DDS for sine wave and fills audio FIFO
// reads audio FIFO and loops it back
// MUST configure (in Qsys) Audio Config module
// -- Line in to ADC
// -- uncheck both bypass options
reg [31:0] audio_bus_addr ; // Avalon address
// see
// ftp://ftp.altera.com/up/pub/Altera_Material/15.1/University_Program_IP_Cores/Audio_Video/Audio.pdf
// for addresses
wire [31:0] audio_base_address = 32'h00003040 ; // Avalon address
wire [31:0] audio_fifo_address = 32'h00003044 ; // Avalon address +4 offset
wire [31:0] audio_data_left_address = 32'h00003048 ; // Avalon address +8
wire [31:0] audio_data_right_address = 32'h0000304c ; // Avalon address +12
reg [3:0] audio_bus_byte_enable ; // four bit byte read/write mask
reg audio_bus_read ; // high when requesting data
reg audio_bus_write ; // high when writing data
reg [31:0] audio_bus_write_data ; // data to send to Avalog bus
wire audio_bus_ack ; // Avalon bus raises this when done
wire [31:0] audio_bus_read_data ; // data from Avalon bus
reg [30:0] audio_timer ;
reg [3:0] audio_state ;
wire state_clock ;
// current free words in audio interface
reg [7:0] fifo_space ;
// debug check of space
assign LEDR = fifo_space ;
// use 4-byte-wide bus-master
//assign audio_bus_byte_enable = 4'b1111;
// DDS signals
reg [31:0] audio_dds_accum ;
// DDS LUT
wire [15:0] sine_out ;
sync_rom sineTable(CLOCK_50, audio_dds_accum[31:24], sine_out);
// audio input from audio module FIFO
reg [31:0] right_audio_input, left_audio_input ;
// get some signals exposed
// connect bus master signals to i/o for probes
/*assign GPIO_0[0] = audio_bus_write ;
assign GPIO_0[1] = audio_bus_read ;
assign GPIO_0[2] = audio_bus_ack ; */
//assign GPIO_0[3] = ??? ;
assign GPIO_1[35:30] = left_audio_input[31:26];
//assign = GPIO_1[19:12] ;
always @(posedge CLOCK_50) begin //CLOCK_50
// reset audio_state machine and read/write controls
if (~KEY[1]) begin
audio_state <= 0 ;
audio_bus_read <= 0 ; // set to one if a read opeation from bus
audio_bus_write <= 0 ; // set to one if a write operation to bus
audio_timer <= 0;
end
else begin
// timer just for deubgging
audio_timer <= audio_timer + 1;
end
// === writing stereo to the audio FIFO ==========
// set up read FIFO available space
if (audio_state==4'd0) begin
audio_bus_addr <= audio_fifo_address ;
audio_bus_read <= 1'b1 ;
audio_bus_byte_enable <= 4'b1111;
audio_state <= 4'd1 ; // wait for read ACK
end
// wait for read ACK and read the fifo available
// bus ACK is high when data is available
if (audio_state==4'd1 && audio_bus_ack==1) begin
audio_state <= 4'd2 ; //4'd2
// FIFO write space is in high byte
fifo_space <= (audio_bus_read_data>>24) ;
// end the read
audio_bus_read <= 1'b0 ;
end
// When there is room in the FIFO
// -- compute next DDS sine sample
// -- start write to fifo for each channel
// -- first the left channel
if (audio_state==4'd2 && fifo_space>8'd2) begin //
audio_state <= 4'd3;
// IF SW=10'h200
// and Fout = (sample_rate)/(2^32)*{SW[9:0], 16'b0}
// then Fout=48000/(2^32)*(2^25) = 375 Hz
audio_dds_accum <= audio_dds_accum + {SW[9:0], 16'b0} ;
// convert 16-bit table to 32-bit format
audio_bus_write_data <= SW[6]? (sine_out << 16) : {GPIO_1[19:14], 26'b0};
audio_bus_addr <= audio_data_left_address ;
audio_bus_byte_enable <= 4'b1111;
audio_bus_write <= 1'b1 ;
end
// if no space, try again later
else if (audio_state==4'd2 && fifo_space<=8'd2) begin
audio_state <= 4'b0 ;
end
// detect bus-transaction-complete ACK
// for left channel write
// You MUST do this check
if (audio_state==4'd3 && audio_bus_ack==1) begin
audio_state <= 4'd4 ; // include right channel
//audio_state <= 4'd0 ; // left channel only!
audio_bus_write <= 0;
end
// -- now the right channel
if (audio_state==4'd4) begin //
audio_state <= 4'd5;
// loop back audio input data
// audio_bus_write_data <= right_audio_input ;
audio_bus_write_data <= {GPIO_1[19:14], 26'b0};
audio_bus_addr <= audio_data_right_address ;
audio_bus_write <= 1'b1 ;
end
// detect bus-transaction-complete ACK
// for right channel write
// You MUST do this check
if (audio_state==4'd5 && audio_bus_ack==1) begin
// audio_state <= 4'd0 ; // for write only function
audio_state <= 4'd6 ; // for read/write function
audio_bus_write <= 0;
end
// === reading stereo from the audio FIFO ==========
// set up read FIFO for available read values
if (audio_state==4'd6 ) begin
audio_bus_addr <= audio_fifo_address ;
audio_bus_read <= 1'b1 ;
audio_bus_byte_enable <= 4'b1111;
audio_state <= 4'd7 ; // wait for read ACK
end
// wait for read ACK and read the fifo available
// bus ACK is high when data is available
if (audio_state==4'd7 && audio_bus_ack==1) begin
audio_state <= 4'd8 ; //4'dxx
// FIFO read space is in low byte
// which is zero when empty
fifo_space <= audio_bus_read_data & 8'hff ;
// end the read
audio_bus_read <= 1'b0 ;
end
// When there is data in the read FIFO
// -- read it from both channels
// -- first the left channel
if (audio_state==4'd8 && fifo_space>8'd0) begin //
audio_state <= 4'd9;
audio_bus_addr <= audio_data_left_address ;
audio_bus_byte_enable <= 4'b1111;
audio_bus_read <= 1'b1 ;
end
// if no space, try again later
else if (audio_state==4'd8 && fifo_space<=8'd0) begin
audio_state <= 4'b0 ;
end
// detect bus-transaction-complete ACK
// for left channel read
// You MUST do this check
if (audio_state==4'd9 && audio_bus_ack==1) begin
audio_state <= 4'd10 ; // include right channel
left_audio_input <= audio_bus_read_data ;
audio_bus_read <= 0;
end
// When there is data in the read FIFO
// -- read it from both channels
// -- now right channel
if (audio_state==4'd10) begin //
audio_state <= 4'd11;
audio_bus_addr <= audio_data_right_address ;
audio_bus_byte_enable <= 4'b1111;
audio_bus_read <= 1'b1 ;
end
// detect bus-transaction-complete ACK
// for left channel read
// You MUST do this check
if (audio_state==4'd11 && audio_bus_ack==1) begin
audio_state <= 4'd0 ; // back to beginning
right_audio_input <= audio_bus_read_data ;
audio_bus_read <= 0;
end
end // always @(posedge state_clock)
//=======================================================
// Bus controller for AVALON bus-master
//=======================================================
wire [31:0] vga_bus_addr, video_in_bus_addr ; // Avalon addresses
reg [31:0] bus_addr ;
wire [31:0] vga_out_base_address = 32'h0000_0000 ; // Avalon address
wire [31:0] video_in_base_address = 32'h0800_0000 ; // Avalon address
reg [3:0] bus_byte_enable ; // four bit byte read/write mask
reg bus_read ; // high when requesting data
reg bus_write ; // high when writing data
reg [31:0] bus_write_data ; // data to send to Avalog bus
wire bus_ack ; // Avalon bus raises this when done
wire [31:0] bus_read_data ; // data from Avalon bus
reg [31:0] timer ;
reg [3:0] state ; //change here
reg last_vs, wait_one;
reg [19:0] vs_count ;
reg last_hs, wait_one_hs ;
reg [19:0] hs_count ;
wire [31:0] pix_1_addr ;
wire [31:0] pix_2_addr ;
wire [31:0] pix_3_addr ;
wire [31:0] pix_4_addr ;
// pixel address is
reg [9:0] vga_x_cood, vga_y_cood, video_in_x_cood, video_in_y_cood ;
reg [7:0] current_pixel_color1, current_pixel_color2 ;
// compute address
//assign vga_bus_addr = vga_out_base_address + {22'b0,video_in_x_cood + vga_x_cood} + ({22'b0,video_in_y_cood + vga_y_cood}<<10) ;
//assign vga_bus_addr = vga_out_base_address + {22'b0,vga_x_cood} + ({22'b0,vga_y_cood}<<10) ;
assign video_in_bus_addr = video_in_base_address + {22'b0,video_in_x_cood} + ({22'b0,video_in_y_cood}<<9) ;
//assign pix_1_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 0 + ({22'b0, (video_in_y_cood << 1) + 0} << 10);
//assign pix_2_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 1 + ({22'b0, (video_in_y_cood << 1) + 0} << 10);
//assign pix_3_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 1 + ({22'b0, (video_in_y_cood << 1) + 1} << 10);
//assign pix_4_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 0 + ({22'b0, (video_in_y_cood << 1) + 1} << 10);
wire [9:0] video_x_addr_in;
wire [9:0] video_y_addr_in;
assign video_x_addr_in = GPIO_0[35:26];
assign video_y_addr_in = GPIO_0[25:16];
assign pix_1_addr = vga_out_base_address + {22'b0,video_x_addr_in << 1} + 0 + ({22'b0, (video_y_addr_in << 1) + 0} << 10);
assign pix_2_addr = vga_out_base_address + {22'b0,video_x_addr_in << 1} + 1 + ({22'b0, (video_y_addr_in << 1) + 0} << 10);
assign pix_3_addr = vga_out_base_address + {22'b0,video_x_addr_in << 1} + 1 + ({22'b0, (video_y_addr_in << 1) + 1} << 10);
assign pix_4_addr = vga_out_base_address + {22'b0,video_x_addr_in << 1} + 0 + ({22'b0, (video_y_addr_in << 1) + 1} << 10);
//
//assign pix_1_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 0 + ({22'b0, (video_in_y_cood << 1) + 0} << 10);
//assign pix_2_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 1 + ({22'b0, (video_in_y_cood << 1) + 0} << 10);
//assign pix_3_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 1 + ({22'b0, (video_in_y_cood << 1) + 1} << 10);
//assign pix_4_addr = vga_out_base_address + {22'b0,video_in_x_cood << 1} + 0 + ({22'b0, (video_in_y_cood << 1) + 1} << 10);
reg my_data_ready;
wire your_data_ready;
assign your_data_ready = 1; // GPIO_1[24];
//assign your_data_ready = 1;
//assign you_give_pixel = 1;
//assign you_display_pixel = 1;
wire [7:0] curr_pix;
//assign curr_pix = GPIO_1[9:2];
//assign GPIO_1[9:2] = curr_pix;
assign curr_pix = current_pixel_color1;
//assign GPIO_1[23] = i_give_pixel;
//assign GPIO_1[23] = my_data_ready;
reg[4:0] delay_timer;
HexDigit Digit0(HEX0, state);
HexDigit Digit1(HEX1, {3'b0, your_data_ready});
HexDigit Digit2(HEX2, {3'b0, my_data_ready});
wire read_now;
wire write_now;
assign read_now = GPIO_1[1];
assign write_now = GPIO_1[0];
reg my_write_finish;
assign GPIO_1[27:20] = curr_pix;
assign GPIO_1[2] = my_data_ready;
assign GPIO_1[3] = my_write_finish;
wire [7:0] get_pix;
reg [7:0] get_pix_reg;
assign get_pix = GPIO_1[11:4];
//assign GPIO_0[0] = ~KEY[0];
wire other_rst;
//assign other_rst = GPIO_0[1];
assign GPIO_0[15:6] = video_in_x_cood;
assign GPIO_0[5:0] = video_in_y_cood[9:4];
assign GPIO_1[29:28] = video_in_y_cood[3:2];
assign GPIO_1[13:12] = video_in_y_cood[1:0];
always @(posedge CLOCK2_50) begin //CLOCK_50
// reset state machine and read/write controls
if (~KEY[0]) begin
state <= 0 ;
bus_read <= 0 ; // set to one if a read opeation from bus
bus_write <= 0 ; // set to on if a write operation to bus
// base address of upper-left corner of the screen
vga_x_cood <= 0 ;
vga_y_cood <= 0 ;
video_in_x_cood <= 0 ;
video_in_y_cood <= 0 ;
bus_byte_enable <= 4'b0001;
my_data_ready <=0;
my_write_finish <=0;
timer <= 0;
delay_timer <=0;
end
else begin
timer <= timer + 1;
end
// if (state==2) begin
// state <= read_done ? 0 :2;
// end
// write to the bus-master
// and put in a small delay to aviod bus hogging
// timer delay can be set to 2**n-1, so 3, 7, 15, 31
// bigger numbers mean slower frame update to VGA
if (state==0 && SW[0] && (timer & 31)==0 ) begin //
state <= 1;
my_data_ready <=0;
my_write_finish <=0;
// i_give_pixel <= 0;
// i_display_pixel <= 0;
// read all the pixels in the video input
video_in_x_cood <= video_in_x_cood + 10'd1 ;
if (video_in_x_cood > 10'd319) begin
video_in_x_cood <= 0 ;
video_in_y_cood <= video_in_y_cood + 10'd1 ;
if (video_in_y_cood > 10'd239) begin
video_in_y_cood <= 10'd0 ;
end
end
// one byte data
bus_byte_enable <= 4'b0001;
// read first pixel
bus_addr <= video_in_bus_addr ;
// signal the bus that a read is requested
bus_read <= 1'b1 ;
end
// finish the read
// You MUST do this check
if (state==1 && bus_ack==1) begin
state <= 2 ; //state <= 2 ;
bus_read <= 1'b0;
current_pixel_color1 <= bus_read_data ;
my_data_ready <= 1;
end
// if (state ==3) begin
// //state <= you_display_pixel ? 8 :3;delay_timer
// state <= (delay_timer==4'd31) ? 0 :3;
// delay_timer <= delay_timer + 4'b1;
// end
if (state==2) begin
state <= write_now? 8: 2; //state <= 2 ;
get_pix_reg <= get_pix;
my_data_ready <= 1;
end
// write a pixel to VGA memory
// if (state==8 && you_display_pixel==1 && (SW[7]==1)) begin
if (state==8) begin
state <= 9;
bus_write <= 1'b1;
bus_addr <= pix_1_addr ;
bus_write_data <= get_pix_reg; //curr_pix; //GPIO_1[9:2];//curr_pix;//current_pixel_color1 ;
bus_byte_enable <= 4'b0001;
delay_timer <=0;
my_data_ready <= 0;
end
// and finish write
if (state==9 && bus_ack==1) begin
state <= 10 ;
bus_write <= 1'b0;
end
// write a pixel to VGA memory
if (state==10) begin
state <= 11 ;
bus_write <= 1'b1;
bus_addr <= pix_2_addr ;
bus_write_data <= get_pix_reg; // curr_pix; //GPIO_1[9:2];//curr_pix;//current_pixel_color1
bus_byte_enable <= 4'b0001;
end
// and finish write
if (state==11 && bus_ack==1) begin
state <= 12 ;
bus_write <= 1'b0;
end
// write a pixel to VGA memory
if (state==12) begin
state <= 13 ;
bus_write <= 1'b1;
bus_addr <= pix_3_addr ;
bus_write_data <= get_pix_reg; // curr_pix; //GPIO_1[9:2];//curr_pix;//current_pixel_color1
bus_byte_enable <= 4'b0001;
my_data_ready <= 0;
end
// and finish write
if (state==13 && bus_ack==1) begin
state <= 14 ;
bus_write <= 1'b0;
end
// write a pixel to VGA memory
if (state==14) begin
state <= 15 ;
bus_write <= 1'b1;
bus_addr <= pix_4_addr ;
bus_write_data <= get_pix_reg; // curr_pix; //GPIO_1[9:2];//curr_pix;//current_pixel_color1
bus_byte_enable <= 4'b0001;
my_write_finish <=0;
end
// and finish write
if (state==15 && bus_ack==1) begin
state <= 0 ;
bus_write <= 1'b0;
my_write_finish <=1;
// i_display_pixel <=1;
end
if (state==4) begin
state <= read_now? 0: 4;
my_write_finish <=1;
// i_display_pixel <=1;
end
end // always @(posedge state_clock)
//=======================================================
// Structural coding
//=======================================================
Computer_System The_System (
////////////////////////////////////
// FPGA Side
////////////////////////////////////
// Global signals
.system_pll_ref_clk_clk (CLOCK_50),
.system_pll_ref_reset_reset (1'b0),
// AV Config
.av_config_SCLK (FPGA_I2C_SCLK),
.av_config_SDAT (FPGA_I2C_SDAT),
// VGA Subsystem
.vga_pll_ref_clk_clk (CLOCK2_50),
.vga_pll_ref_reset_reset (1'b0),
.vga_CLK (VGA_CLK),
.vga_BLANK (VGA_BLANK_N),
.vga_SYNC (VGA_SYNC_N),
.vga_HS (VGA_HS),
.vga_VS (VGA_VS),
.vga_R (VGA_R),
.vga_G (VGA_G),
.vga_B (VGA_B),
// Video In Subsystem
.video_in_TD_CLK27 (TD_CLK27),
.video_in_TD_DATA (TD_DATA),
.video_in_TD_HS (TD_HS),
.video_in_TD_VS (TD_VS),
.video_in_clk27_reset (),
.video_in_TD_RESET (),
.video_in_overflow_flag (),
.ebab_video_in_external_interface_address (bus_addr), //
.ebab_video_in_external_interface_byte_enable (bus_byte_enable), // .byte_enable
.ebab_video_in_external_interface_read (bus_read), // .read
.ebab_video_in_external_interface_write (bus_write), // .write
.ebab_video_in_external_interface_write_data (bus_write_data), //.write_data
.ebab_video_in_external_interface_acknowledge (bus_ack), // .acknowledge
.ebab_video_in_external_interface_read_data (bus_read_data),
// clock bridge for EBAb_video_in_external_interface_acknowledge
.clock_bridge_0_in_clk_clk (CLOCK_50),
// SDRAM
.sdram_clk_clk (DRAM_CLK),
.sdram_addr (DRAM_ADDR),
.sdram_ba (DRAM_BA),
.sdram_cas_n (DRAM_CAS_N),
.sdram_cke (DRAM_CKE),
.sdram_cs_n (DRAM_CS_N),
.sdram_dq (DRAM_DQ),
.sdram_dqm ({DRAM_UDQM,DRAM_LDQM}),
.sdram_ras_n (DRAM_RAS_N),
.sdram_we_n (DRAM_WE_N),
// Audio Subsystem
.audio_pll_ref_clk_clk (CLOCK3_50),
.audio_pll_ref_reset_reset (1'b0),
.audio_clk_clk (AUD_XCK),
.audio_ADCDAT (AUD_ADCDAT),
.audio_ADCLRCK (AUD_ADCLRCK),
.audio_BCLK (AUD_BCLK),
.audio_DACDAT (AUD_DACDAT),
.audio_DACLRCK (AUD_DACLRCK),
// bus-master state machine interface
.bus_master_audio_export_address (audio_bus_addr),
.bus_master_audio_export_byte_enable (audio_bus_byte_enable),
.bus_master_audio_export_read (audio_bus_read),
.bus_master_audio_export_write (audio_bus_write),
.bus_master_audio_export_write_data (audio_bus_write_data),
.bus_master_audio_export_acknowledge (audio_bus_ack),
.bus_master_audio_export_read_data (audio_bus_read_data),
////////////////////////////////////
// HPS Side
////////////////////////////////////
// DDR3 SDRAM
.memory_mem_a (HPS_DDR3_ADDR),
.memory_mem_ba (HPS_DDR3_BA),
.memory_mem_ck (HPS_DDR3_CK_P),
.memory_mem_ck_n (HPS_DDR3_CK_N),
.memory_mem_cke (HPS_DDR3_CKE),
.memory_mem_cs_n (HPS_DDR3_CS_N),
.memory_mem_ras_n (HPS_DDR3_RAS_N),
.memory_mem_cas_n (HPS_DDR3_CAS_N),
.memory_mem_we_n (HPS_DDR3_WE_N),
.memory_mem_reset_n (HPS_DDR3_RESET_N),
.memory_mem_dq (HPS_DDR3_DQ),
.memory_mem_dqs (HPS_DDR3_DQS_P),
.memory_mem_dqs_n (HPS_DDR3_DQS_N),
.memory_mem_odt (HPS_DDR3_ODT),
.memory_mem_dm (HPS_DDR3_DM),
.memory_oct_rzqin (HPS_DDR3_RZQ),
// Ethernet
.hps_io_hps_io_gpio_inst_GPIO35 (HPS_ENET_INT_N),
.hps_io_hps_io_emac1_inst_TX_CLK (HPS_ENET_GTX_CLK),
.hps_io_hps_io_emac1_inst_TXD0 (HPS_ENET_TX_DATA[0]),
.hps_io_hps_io_emac1_inst_TXD1 (HPS_ENET_TX_DATA[1]),
.hps_io_hps_io_emac1_inst_TXD2 (HPS_ENET_TX_DATA[2]),
.hps_io_hps_io_emac1_inst_TXD3 (HPS_ENET_TX_DATA[3]),
.hps_io_hps_io_emac1_inst_RXD0 (HPS_ENET_RX_DATA[0]),
.hps_io_hps_io_emac1_inst_MDIO (HPS_ENET_MDIO),
.hps_io_hps_io_emac1_inst_MDC (HPS_ENET_MDC),
.hps_io_hps_io_emac1_inst_RX_CTL (HPS_ENET_RX_DV),
.hps_io_hps_io_emac1_inst_TX_CTL (HPS_ENET_TX_EN),
.hps_io_hps_io_emac1_inst_RX_CLK (HPS_ENET_RX_CLK),
.hps_io_hps_io_emac1_inst_RXD1 (HPS_ENET_RX_DATA[1]),
.hps_io_hps_io_emac1_inst_RXD2 (HPS_ENET_RX_DATA[2]),
.hps_io_hps_io_emac1_inst_RXD3 (HPS_ENET_RX_DATA[3]),
// Flash
.hps_io_hps_io_qspi_inst_IO0 (HPS_FLASH_DATA[0]),
.hps_io_hps_io_qspi_inst_IO1 (HPS_FLASH_DATA[1]),
.hps_io_hps_io_qspi_inst_IO2 (HPS_FLASH_DATA[2]),
.hps_io_hps_io_qspi_inst_IO3 (HPS_FLASH_DATA[3]),
.hps_io_hps_io_qspi_inst_SS0 (HPS_FLASH_NCSO),
.hps_io_hps_io_qspi_inst_CLK (HPS_FLASH_DCLK),
// Accelerometer
.hps_io_hps_io_gpio_inst_GPIO61 (HPS_GSENSOR_INT),
//.adc_sclk (ADC_SCLK),
//.adc_cs_n (ADC_CS_N),
//.adc_dout (ADC_DOUT),
//.adc_din (ADC_DIN),
// General Purpose I/O
.hps_io_hps_io_gpio_inst_GPIO40 (HPS_GPIO[0]),
.hps_io_hps_io_gpio_inst_GPIO41 (HPS_GPIO[1]),
// I2C
.hps_io_hps_io_gpio_inst_GPIO48 (HPS_I2C_CONTROL),
.hps_io_hps_io_i2c0_inst_SDA (HPS_I2C1_SDAT),
.hps_io_hps_io_i2c0_inst_SCL (HPS_I2C1_SCLK),
.hps_io_hps_io_i2c1_inst_SDA (HPS_I2C2_SDAT),
.hps_io_hps_io_i2c1_inst_SCL (HPS_I2C2_SCLK),
// Pushbutton
.hps_io_hps_io_gpio_inst_GPIO54 (HPS_KEY),
// LED
.hps_io_hps_io_gpio_inst_GPIO53 (HPS_LED),
// SD Card
.hps_io_hps_io_sdio_inst_CMD (HPS_SD_CMD),
.hps_io_hps_io_sdio_inst_D0 (HPS_SD_DATA[0]),
.hps_io_hps_io_sdio_inst_D1 (HPS_SD_DATA[1]),
.hps_io_hps_io_sdio_inst_CLK (HPS_SD_CLK),
.hps_io_hps_io_sdio_inst_D2 (HPS_SD_DATA[2]),
.hps_io_hps_io_sdio_inst_D3 (HPS_SD_DATA[3]),
// SPI
.hps_io_hps_io_spim1_inst_CLK (HPS_SPIM_CLK),
.hps_io_hps_io_spim1_inst_MOSI (HPS_SPIM_MOSI),
.hps_io_hps_io_spim1_inst_MISO (HPS_SPIM_MISO),
.hps_io_hps_io_spim1_inst_SS0 (HPS_SPIM_SS),
// UART
.hps_io_hps_io_uart0_inst_RX (HPS_UART_RX),
.hps_io_hps_io_uart0_inst_TX (HPS_UART_TX),
// USB
.hps_io_hps_io_gpio_inst_GPIO09 (HPS_CONV_USB_N),
.hps_io_hps_io_usb1_inst_D0 (HPS_USB_DATA[0]),
.hps_io_hps_io_usb1_inst_D1 (HPS_USB_DATA[1]),
.hps_io_hps_io_usb1_inst_D2 (HPS_USB_DATA[2]),
.hps_io_hps_io_usb1_inst_D3 (HPS_USB_DATA[3]),
.hps_io_hps_io_usb1_inst_D4 (HPS_USB_DATA[4]),
.hps_io_hps_io_usb1_inst_D5 (HPS_USB_DATA[5]),
.hps_io_hps_io_usb1_inst_D6 (HPS_USB_DATA[6]),
.hps_io_hps_io_usb1_inst_D7 (HPS_USB_DATA[7]),
.hps_io_hps_io_usb1_inst_CLK (HPS_USB_CLKOUT),
.hps_io_hps_io_usb1_inst_STP (HPS_USB_STP),
.hps_io_hps_io_usb1_inst_DIR (HPS_USB_DIR),
.hps_io_hps_io_usb1_inst_NXT (HPS_USB_NXT)
);
endmodule
//////////////////////////////////////////////////
//////////// Sin Wave ROM Table //////////////
//////////////////////////////////////////////////
// produces a 2's comp, 16-bit, approximation
// of a sine wave, given an input phase (address)
module sync_rom (clock, address, sine);
input clock;
input [7:0] address;
output [15:0] sine;
reg signed [15:0] sine;
always@(posedge clock)
begin
case(address)
8'h00: sine = 16'h0000 ;
8'h01: sine = 16'h0192 ;
8'h02: sine = 16'h0323 ;
8'h03: sine = 16'h04b5 ;
8'h04: sine = 16'h0645 ;
8'h05: sine = 16'h07d5 ;
8'h06: sine = 16'h0963 ;
8'h07: sine = 16'h0af0 ;
8'h08: sine = 16'h0c7c ;
8'h09: sine = 16'h0e05 ;
8'h0a: sine = 16'h0f8c ;
8'h0b: sine = 16'h1111 ;
8'h0c: sine = 16'h1293 ;
8'h0d: sine = 16'h1413 ;
8'h0e: sine = 16'h158f ;
8'h0f: sine = 16'h1708 ;
8'h10: sine = 16'h187d ;
8'h11: sine = 16'h19ef ;
8'h12: sine = 16'h1b5c ;
8'h13: sine = 16'h1cc5 ;
8'h14: sine = 16'h1e2a ;
8'h15: sine = 16'h1f8b ;
8'h16: sine = 16'h20e6 ;
8'h17: sine = 16'h223c ;
8'h18: sine = 16'h238d ;
8'h19: sine = 16'h24d9 ;
8'h1a: sine = 16'h261f ;
8'h1b: sine = 16'h275f ;
8'h1c: sine = 16'h2899 ;
8'h1d: sine = 16'h29cc ;
8'h1e: sine = 16'h2afa ;
8'h1f: sine = 16'h2c20 ;
8'h20: sine = 16'h2d40 ;
8'h21: sine = 16'h2e59 ;
8'h22: sine = 16'h2f6b ;
8'h23: sine = 16'h3075 ;
8'h24: sine = 16'h3178 ;
8'h25: sine = 16'h3273 ;
8'h26: sine = 16'h3366 ;
8'h27: sine = 16'h3452 ;
8'h28: sine = 16'h3535 ;
8'h29: sine = 16'h3611 ;
8'h2a: sine = 16'h36e4 ;
8'h2b: sine = 16'h37ae ;
8'h2c: sine = 16'h3870 ;
8'h2d: sine = 16'h3929 ;
8'h2e: sine = 16'h39da ;
8'h2f: sine = 16'h3a81 ;
8'h30: sine = 16'h3b1f ;
8'h31: sine = 16'h3bb5 ;
8'h32: sine = 16'h3c41 ;
8'h33: sine = 16'h3cc4 ;
8'h34: sine = 16'h3d3d ;
8'h35: sine = 16'h3dad ;
8'h36: sine = 16'h3e14 ;
8'h37: sine = 16'h3e70 ;
8'h38: sine = 16'h3ec4 ;
8'h39: sine = 16'h3f0d ;
8'h3a: sine = 16'h3f4d ;
8'h3b: sine = 16'h3f83 ;
8'h3c: sine = 16'h3fb0 ;
8'h3d: sine = 16'h3fd2 ;
8'h3e: sine = 16'h3feb ;
8'h3f: sine = 16'h3ffa ;
8'h40: sine = 16'h3fff ;
8'h41: sine = 16'h3ffa ;
8'h42: sine = 16'h3feb ;
8'h43: sine = 16'h3fd2 ;
8'h44: sine = 16'h3fb0 ;
8'h45: sine = 16'h3f83 ;
8'h46: sine = 16'h3f4d ;
8'h47: sine = 16'h3f0d ;
8'h48: sine = 16'h3ec4 ;
8'h49: sine = 16'h3e70 ;
8'h4a: sine = 16'h3e14 ;
8'h4b: sine = 16'h3dad ;
8'h4c: sine = 16'h3d3d ;
8'h4d: sine = 16'h3cc4 ;
8'h4e: sine = 16'h3c41 ;
8'h4f: sine = 16'h3bb5 ;
8'h50: sine = 16'h3b1f ;
8'h51: sine = 16'h3a81 ;
8'h52: sine = 16'h39da ;
8'h53: sine = 16'h3929 ;
8'h54: sine = 16'h3870 ;
8'h55: sine = 16'h37ae ;
8'h56: sine = 16'h36e4 ;
8'h57: sine = 16'h3611 ;
8'h58: sine = 16'h3535 ;
8'h59: sine = 16'h3452 ;
8'h5a: sine = 16'h3366 ;
8'h5b: sine = 16'h3273 ;
8'h5c: sine = 16'h3178 ;
8'h5d: sine = 16'h3075 ;
8'h5e: sine = 16'h2f6b ;
8'h5f: sine = 16'h2e59 ;
8'h60: sine = 16'h2d40 ;
8'h61: sine = 16'h2c20 ;
8'h62: sine = 16'h2afa ;
8'h63: sine = 16'h29cc ;
8'h64: sine = 16'h2899 ;
8'h65: sine = 16'h275f ;
8'h66: sine = 16'h261f ;
8'h67: sine = 16'h24d9 ;
8'h68: sine = 16'h238d ;
8'h69: sine = 16'h223c ;
8'h6a: sine = 16'h20e6 ;
8'h6b: sine = 16'h1f8b ;
8'h6c: sine = 16'h1e2a ;
8'h6d: sine = 16'h1cc5 ;
8'h6e: sine = 16'h1b5c ;
8'h6f: sine = 16'h19ef ;
8'h70: sine = 16'h187d ;
8'h71: sine = 16'h1708 ;
8'h72: sine = 16'h158f ;
8'h73: sine = 16'h1413 ;
8'h74: sine = 16'h1293 ;
8'h75: sine = 16'h1111 ;
8'h76: sine = 16'h0f8c ;
8'h77: sine = 16'h0e05 ;
8'h78: sine = 16'h0c7c ;
8'h79: sine = 16'h0af0 ;
8'h7a: sine = 16'h0963 ;
8'h7b: sine = 16'h07d5 ;
8'h7c: sine = 16'h0645 ;
8'h7d: sine = 16'h04b5 ;
8'h7e: sine = 16'h0323 ;
8'h7f: sine = 16'h0192 ;
8'h80: sine = 16'h0000 ;
8'h81: sine = 16'hfe6e ;
8'h82: sine = 16'hfcdd ;
8'h83: sine = 16'hfb4b ;
8'h84: sine = 16'hf9bb ;
8'h85: sine = 16'hf82b ;
8'h86: sine = 16'hf69d ;
8'h87: sine = 16'hf510 ;
8'h88: sine = 16'hf384 ;
8'h89: sine = 16'hf1fb ;
8'h8a: sine = 16'hf074 ;
8'h8b: sine = 16'heeef ;
8'h8c: sine = 16'hed6d ;
8'h8d: sine = 16'hebed ;
8'h8e: sine = 16'hea71 ;
8'h8f: sine = 16'he8f8 ;
8'h90: sine = 16'he783 ;
8'h91: sine = 16'he611 ;
8'h92: sine = 16'he4a4 ;
8'h93: sine = 16'he33b ;
8'h94: sine = 16'he1d6 ;
8'h95: sine = 16'he075 ;
8'h96: sine = 16'hdf1a ;
8'h97: sine = 16'hddc4 ;
8'h98: sine = 16'hdc73 ;
8'h99: sine = 16'hdb27 ;
8'h9a: sine = 16'hd9e1 ;
8'h9b: sine = 16'hd8a1 ;
8'h9c: sine = 16'hd767 ;
8'h9d: sine = 16'hd634 ;
8'h9e: sine = 16'hd506 ;
8'h9f: sine = 16'hd3e0 ;
8'ha0: sine = 16'hd2c0 ;
8'ha1: sine = 16'hd1a7 ;
8'ha2: sine = 16'hd095 ;
8'ha3: sine = 16'hcf8b ;
8'ha4: sine = 16'hce88 ;
8'ha5: sine = 16'hcd8d ;
8'ha6: sine = 16'hcc9a ;
8'ha7: sine = 16'hcbae ;
8'ha8: sine = 16'hcacb ;
8'ha9: sine = 16'hc9ef ;
8'haa: sine = 16'hc91c ;
8'hab: sine = 16'hc852 ;
8'hac: sine = 16'hc790 ;
8'had: sine = 16'hc6d7 ;
8'hae: sine = 16'hc626 ;
8'haf: sine = 16'hc57f ;
8'hb0: sine = 16'hc4e1 ;
8'hb1: sine = 16'hc44b ;
8'hb2: sine = 16'hc3bf ;
8'hb3: sine = 16'hc33c ;
8'hb4: sine = 16'hc2c3 ;
8'hb5: sine = 16'hc253 ;
8'hb6: sine = 16'hc1ec ;
8'hb7: sine = 16'hc190 ;
8'hb8: sine = 16'hc13c ;
8'hb9: sine = 16'hc0f3 ;
8'hba: sine = 16'hc0b3 ;
8'hbb: sine = 16'hc07d ;
8'hbc: sine = 16'hc050 ;
8'hbd: sine = 16'hc02e ;
8'hbe: sine = 16'hc015 ;
8'hbf: sine = 16'hc006 ;
8'hc0: sine = 16'hc001 ;
8'hc1: sine = 16'hc006 ;
8'hc2: sine = 16'hc015 ;
8'hc3: sine = 16'hc02e ;
8'hc4: sine = 16'hc050 ;
8'hc5: sine = 16'hc07d ;
8'hc6: sine = 16'hc0b3 ;
8'hc7: sine = 16'hc0f3 ;
8'hc8: sine = 16'hc13c ;
8'hc9: sine = 16'hc190 ;
8'hca: sine = 16'hc1ec ;
8'hcb: sine = 16'hc253 ;
8'hcc: sine = 16'hc2c3 ;
8'hcd: sine = 16'hc33c ;
8'hce: sine = 16'hc3bf ;
8'hcf: sine = 16'hc44b ;
8'hd0: sine = 16'hc4e1 ;
8'hd1: sine = 16'hc57f ;
8'hd2: sine = 16'hc626 ;
8'hd3: sine = 16'hc6d7 ;
8'hd4: sine = 16'hc790 ;
8'hd5: sine = 16'hc852 ;
8'hd6: sine = 16'hc91c ;
8'hd7: sine = 16'hc9ef ;
8'hd8: sine = 16'hcacb ;
8'hd9: sine = 16'hcbae ;
8'hda: sine = 16'hcc9a ;
8'hdb: sine = 16'hcd8d ;
8'hdc: sine = 16'hce88 ;
8'hdd: sine = 16'hcf8b ;
8'hde: sine = 16'hd095 ;
8'hdf: sine = 16'hd1a7 ;
8'he0: sine = 16'hd2c0 ;
8'he1: sine = 16'hd3e0 ;
8'he2: sine = 16'hd506 ;
8'he3: sine = 16'hd634 ;
8'he4: sine = 16'hd767 ;
8'he5: sine = 16'hd8a1 ;
8'he6: sine = 16'hd9e1 ;
8'he7: sine = 16'hdb27 ;
8'he8: sine = 16'hdc73 ;
8'he9: sine = 16'hddc4 ;
8'hea: sine = 16'hdf1a ;
8'heb: sine = 16'he075 ;
8'hec: sine = 16'he1d6 ;
8'hed: sine = 16'he33b ;
8'hee: sine = 16'he4a4 ;
8'hef: sine = 16'he611 ;
8'hf0: sine = 16'he783 ;
8'hf1: sine = 16'he8f8 ;
8'hf2: sine = 16'hea71 ;
8'hf3: sine = 16'hebed ;
8'hf4: sine = 16'hed6d ;
8'hf5: sine = 16'heeef ;
8'hf6: sine = 16'hf074 ;
8'hf7: sine = 16'hf1fb ;
8'hf8: sine = 16'hf384 ;
8'hf9: sine = 16'hf510 ;
8'hfa: sine = 16'hf69d ;
8'hfb: sine = 16'hf82b ;
8'hfc: sine = 16'hf9bb ;
8'hfd: sine = 16'hfb4b ;
8'hfe: sine = 16'hfcdd ;
8'hff: sine = 16'hfe6e ;
endcase
end
endmodule
///////////////////////////////////////
/// 640x480 version!
/// test VGA with hardware video input copy to VGA
///////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/time.h>
#include "address_map_arm_brl4.h"
/* function prototypes */
void VGA_text (int, int, char *);
void VGA_text_clear();
void VGA_box (int, int, int, int, short);
void VGA_line(int, int, int, int, short) ;
void VGA_disc (int, int, int, short);
int VGA_read_pixel(int, int) ;
int video_in_read_pixel(int, int);
void draw_delay(void) ;
// the light weight buss base
void *h2p_lw_virtual_base;
volatile unsigned int *h2p_lw_video_in_control_addr=NULL;
volatile unsigned int *h2p_lw_video_in_resolution_addr=NULL;
//volatile unsigned int *h2p_lw_video_in_control_addr=NULL;
//volatile unsigned int *h2p_lw_video_in_control_addr=NULL;
volatile unsigned int *h2p_lw_video_edge_control_addr=NULL;
// pixel buffer
volatile unsigned int * vga_pixel_ptr = NULL ;
void *vga_pixel_virtual_base;
// video input buffer
volatile unsigned int * video_in_ptr = NULL ;
void *video_in_virtual_base;
// character buffer
volatile unsigned int * vga_char_ptr = NULL ;
void *vga_char_virtual_base;
// /dev/mem file id
int fd;
// shared memory
key_t mem_key=0xf0;
int shared_mem_id;
int *shared_ptr;
int shared_time;
int shared_note;
char shared_str[64];
// pixel macro
#define VGA_PIXEL(x,y,color) do{\
char *pixel_ptr ;\
pixel_ptr = (char *)vga_pixel_ptr + ((y)<<10) + (x) ;\
*(char *)pixel_ptr = (color);\
} while(0)
#define VIDEO_IN_PIXEL(x,y,color) do{\
char *pixel_ptr ;\
pixel_ptr = (char *)video_in_ptr + ((y)<<9) + (x) ;\
*(char *)pixel_ptr = (color);\
} while(0)
// measure time
struct timeval t1, t2;
double elapsedTime;
struct timespec delay_time ;
int main(void)
{
delay_time.tv_nsec = 10 ;
delay_time.tv_sec = 0 ;
// Declare volatile pointers to I/O registers (volatile // means that IO load and store instructions will be used // to access these pointer locations,
// instead of regular memory loads and stores)
// === need to mmap: =======================
// FPGA_CHAR_BASE
// FPGA_ONCHIP_BASE
// HW_REGS_BASE
// === get FPGA addresses ==================
// Open /dev/mem
if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
printf( "ERROR: could not open \"/dev/mem\"...\n" );
return( 1 );
}
// get virtual addr that maps to physical
h2p_lw_virtual_base = mmap( NULL, HW_REGS_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, HW_REGS_BASE );
if( h2p_lw_virtual_base == MAP_FAILED ) {
printf( "ERROR: mmap1() failed...\n" );
close( fd );
return(1);
}
h2p_lw_video_in_control_addr=(volatile unsigned int *)(h2p_lw_virtual_base+VIDEO_IN_BASE+0x0c);
h2p_lw_video_in_resolution_addr=(volatile unsigned int *)(h2p_lw_virtual_base+VIDEO_IN_BASE+0x08);
*(h2p_lw_video_in_control_addr) = 0x04 ; // turn on video capture
*(h2p_lw_video_in_resolution_addr) = 0x00f00140 ; // high 240 low 320
h2p_lw_video_edge_control_addr=(volatile unsigned int *)(h2p_lw_virtual_base+VIDEO_IN_BASE+0x10);
*h2p_lw_video_edge_control_addr = 0x01 ; // 1 means edges
*h2p_lw_video_edge_control_addr = 0x00 ; // 1 means edges
// === get VGA char addr =====================
// get virtual addr that maps to physical
vga_char_virtual_base = mmap( NULL, FPGA_CHAR_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, FPGA_CHAR_BASE );
if( vga_char_virtual_base == MAP_FAILED ) {
printf( "ERROR: mmap2() failed...\n" );
close( fd );
return(1);
}
// Get the address that maps to the character
vga_char_ptr =(unsigned int *)(vga_char_virtual_base);
// === get VGA pixel addr ====================
// get virtual addr that maps to physical
// SDRAM
vga_pixel_virtual_base = mmap( NULL, FPGA_ONCHIP_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, SDRAM_BASE); //SDRAM_BASE
if( vga_pixel_virtual_base == MAP_FAILED ) {
printf( "ERROR: mmap3() failed...\n" );
close( fd );
return(1);
}
// Get the address that maps to the FPGA pixel buffer
vga_pixel_ptr =(unsigned int *)(vga_pixel_virtual_base);
// === get video input =======================
// on-chip RAM
video_in_virtual_base = mmap( NULL, FPGA_ONCHIP_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, FPGA_ONCHIP_BASE);
if( video_in_virtual_base == MAP_FAILED ) {
printf( "ERROR: mmap3() failed...\n" );
close( fd );
return(1);
}
// format the pointer
video_in_ptr =(unsigned int *)(video_in_virtual_base);
// ===========================================
/* create a message to be displayed on the VGA
and LCD displays */
char text_top_row[40] = "DE1-SoC ARM/FPGA\0";
char text_bottom_row[40] = "Cornell ece5760\0";
char num_string[20], time_string[50] ;
// a pixel from the video
int pixel_color;
// video input index
int i,j;
// clear the screen
VGA_box (0, 0, 639, 479, 0x03);
// clear the text
VGA_text_clear();
VGA_text (1, 56, text_top_row);
VGA_text (1, 57, text_bottom_row);
// start timer
//gettimeofday(&t1, NULL);
while(1)
{
gettimeofday(&t1, NULL);
// note that this version of VGA_disk
// has THROTTLED pixel write
// VGA_disc((rand()&0x3ff), (rand()&0x1ff), rand()&0x3f, rand()&0xff) ;
// software copy test.
// in production, hardware does the copy
// put a few pixel in input buffer
//VIDEO_IN_PIXEL(160,120,0xff);
//VIDEO_IN_PIXEL(0,0,0xff);
//VIDEO_IN_PIXEL(319,239,0xff);
//VIDEO_IN_PIXEL(300,200,0xff);
// read/write video input -- copy to VGA display
// for (i=0; i<320; i++) {
// for (j=0; j<240; j++) {
// pixel_color = video_in_read_pixel(i,j);
// VGA_PIXEL(i+100,j+50,pixel_color);
// }
// }
// stop timer
gettimeofday(&t2, NULL);
elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; // sec to ms
elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; // us to ms
pixel_color = VGA_read_pixel(160,120);
sprintf(time_string, "T=%3.0fmS color=%x ", elapsedTime, pixel_color);
// VGA_text (10, 3, num_string);
VGA_text (1, 58, time_string);
} // end while(1)
} // end main
/****************************************************************************************
* Subroutine to read a pixel from the video input
****************************************************************************************/
int video_in_read_pixel(int x, int y){
char *pixel_ptr ;
pixel_ptr = (char *)video_in_ptr + ((y)<<9) + (x) ;
return *pixel_ptr ;
}
/****************************************************************************************
* Subroutine to read a pixel from the VGA monitor
****************************************************************************************/
int VGA_read_pixel(int x, int y){
char *pixel_ptr ;
pixel_ptr = (char *)vga_pixel_ptr + ((y)<<10) + (x) ;
return *pixel_ptr ;
}
/****************************************************************************************
* Subroutine to send a string of text to the VGA monitor
****************************************************************************************/
void VGA_text(int x, int y, char * text_ptr)
{
volatile char * character_buffer = (char *) vga_char_ptr ; // VGA character buffer
int offset;
/* assume that the text string fits on one line */
offset = (y << 7) + x;
while ( *(text_ptr) )
{
// write to the character buffer
*(character_buffer + offset) = *(text_ptr);
++text_ptr;
++offset;
}
}
/****************************************************************************************
* Subroutine to clear text to the VGA monitor
****************************************************************************************/
void VGA_text_clear()
{
volatile char * character_buffer = (char *) vga_char_ptr ; // VGA character buffer
int offset, x, y;
for (x=0; x<79; x++){
for (y=0; y<59; y++){
/* assume that the text string fits on one line */
offset = (y << 7) + x;
// write to the character buffer
*(character_buffer + offset) = ' ';
}
}
}
/****************************************************************************************
* Draw a filled rectangle on the VGA monitor
****************************************************************************************/
#define SWAP(X,Y) do{int temp=X; X=Y; Y=temp;}while(0)
void VGA_box(int x1, int y1, int x2, int y2, short pixel_color)
{
char *pixel_ptr ;
int row, col;
/* check and fix box coordinates to be valid */
if (x1>639) x1 = 639;
if (y1>479) y1 = 479;
if (x2>639) x2 = 639;
if (y2>479) y2 = 479;
if (x1<0) x1 = 0;
if (y1<0) y1 = 0;
if (x2<0) x2 = 0;
if (y2<0) y2 = 0;
if (x1>x2) SWAP(x1,x2);
if (y1>y2) SWAP(y1,y2);
for (row = y1; row <= y2; row++)
for (col = x1; col <= x2; ++col)
{
//640x480
pixel_ptr = (char *)vga_pixel_ptr + (row<<10) + col ;
// set pixel color
*(char *)pixel_ptr = pixel_color;
}
}
/****************************************************************************************
* Draw a filled circle on the VGA monitor
****************************************************************************************/
void VGA_disc(int x, int y, int r, short pixel_color)
{
char *pixel_ptr ;
int row, col, rsqr, xc, yc;
rsqr = r*r;
for (yc = -r; yc <= r; yc++)
for (xc = -r; xc <= r; xc++)
{
col = xc;
row = yc;
// add the r to make the edge smoother
if(col*col+row*row <= rsqr+r){
col += x; // add the center point
row += y; // add the center point
//check for valid 640x480
if (col>639) col = 639;
if (row>479) row = 479;
if (col<0) col = 0;
if (row<0) row = 0;
pixel_ptr = (char *)vga_pixel_ptr + (row<<10) + col ;
// set pixel color
//nanosleep(&delay_time, NULL);
draw_delay();
*(char *)pixel_ptr = pixel_color;
}
}
}
// =============================================
// === Draw a line
// =============================================
//plot a line
//at x1,y1 to x2,y2 with color
//Code is from David Rodgers,
//"Procedural Elements of Computer Graphics",1985
void VGA_line(int x1, int y1, int x2, int y2, short c) {
int e;
signed int dx,dy,j, temp;
signed int s1,s2, xchange;
signed int x,y;
char *pixel_ptr ;
/* check and fix line coordinates to be valid */
if (x1>639) x1 = 639;
if (y1>479) y1 = 479;
if (x2>639) x2 = 639;
if (y2>479) y2 = 479;
if (x1<0) x1 = 0;
if (y1<0) y1 = 0;
if (x2<0) x2 = 0;
if (y2<0) y2 = 0;
x = x1;
y = y1;
//take absolute value
if (x2 < x1) {
dx = x1 - x2;
s1 = -1;
}
else if (x2 == x1) {
dx = 0;
s1 = 0;
}
else {
dx = x2 - x1;
s1 = 1;
}
if (y2 < y1) {
dy = y1 - y2;
s2 = -1;
}
else if (y2 == y1) {
dy = 0;
s2 = 0;
}
else {
dy = y2 - y1;
s2 = 1;
}
xchange = 0;
if (dy>dx) {
temp = dx;
dx = dy;
dy = temp;
xchange = 1;
}
e = ((int)dy<<1) - dx;
for (j=0; j<=dx; j++) {
//video_pt(x,y,c); //640x480
pixel_ptr = (char *)vga_pixel_ptr + (y<<10)+ x;
// set pixel color
*(char *)pixel_ptr = c;
if (e>=0) {
if (xchange==1) x = x + s1;
else y = y + s2;
e = e - ((int)dx<<1);
}
if (xchange==1) y = y + s2;
else x = x + s1;
e = e + ((int)dy<<1);
}
}
/////////////////////////////////////////////
#define NOP10() asm("nop;nop;nop;nop;nop;nop;nop;nop;nop;nop")
void draw_delay(void){
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10(); //16
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10(); //32
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10(); //48
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10(); //64
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10(); //68
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10(); //80
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
// NOP10(); NOP10(); NOP10(); NOP10();
NOP10(); NOP10(); NOP10(); NOP10(); //96
}
/// /// /////////////////////////////////////
/// end /////////////////////////////////////
/* This files provides address values that exist in the system */
#define BOARD "DE1-SoC"
/* Memory */
#define DDR_BASE 0x00000000
#define DDR_END 0x3FFFFFFF
#define A9_ONCHIP_BASE 0xFFFF0000
#define A9_ONCHIP_END 0xFFFFFFFF
#define SDRAM_BASE 0xC0000000
#define SDRAM_END 0xC3FFFFFF
//
#define FPGA_ONCHIP_BASE 0xC8000000
#define FPGA_ONCHIP_END 0xC803FFFF
// modified for 640x480
// #define FPGA_ONCHIP_SPAN 0x00040000
#define FPGA_ONCHIP_SPAN 0x00080000
//
#define FPGA_CHAR_BASE 0xC9000000
#define FPGA_CHAR_END 0xC9001FFF
#define FPGA_CHAR_SPAN 0x00002000
/* Cyclone V FPGA devices */
#define HW_REGS_BASE 0xff200000
//#define HW_REGS_SPAN 0x00200000
#define HW_REGS_SPAN 0x00005000
// === now offsets from the BASE ===
#define LEDR_BASE 0x00000000
#define HEX3_HEX0_BASE 0x00000020
#define HEX5_HEX4_BASE 0x00000030
#define SW_BASE 0x00000040
#define KEY_BASE 0x00000050
#define JP1_BASE 0x00000060
#define JP2_BASE 0x00000070
#define PS2_BASE 0x00000100
#define PS2_DUAL_BASE 0x00000108
#define JTAG_UART_BASE 0x00001000
#define JTAG_UART_2_BASE 0x00001008
#define IrDA_BASE 0x00001020
#define TIMER_BASE 0x00002000
#define TIMER_2_BASE 0x00002020
#define AV_CONFIG_BASE 0x00003000
#define PIXEL_BUF_CTRL_BASE 0x00003020
#define CHAR_BUF_CTRL_BASE 0x00003030
#define AUDIO_BASE 0x00003040
#define VIDEO_IN_BASE 0x00003060
#define ADC_BASE 0x00004000
/* Cyclone V HPS devices */
#define HPS_GPIO1_BASE 0xFF709000
#define I2C0_BASE 0xFFC04000
#define I2C1_BASE 0xFFC05000
#define I2C2_BASE 0xFFC06000
#define I2C3_BASE 0xFFC07000
#define HPS_TIMER0_BASE 0xFFC08000
#define HPS_TIMER1_BASE 0xFFC09000
#define HPS_TIMER2_BASE 0xFFD00000
#define HPS_TIMER3_BASE 0xFFD01000
#define FPGA_BRIDGE 0xFFD0501C
/* ARM A9 MPCORE devices */
#define PERIPH_BASE 0xFFFEC000 // base address of peripheral devices
#define MPCORE_PRIV_TIMER 0xFFFEC600 // PERIPH_BASE + 0x0600
/* Interrupt controller (GIC) CPU interface(s) */
#define MPCORE_GIC_CPUIF 0xFFFEC100 // PERIPH_BASE + 0x100
#define ICCICR 0x00 // offset to CPU interface control reg
#define ICCPMR 0x04 // offset to interrupt priority mask reg
#define ICCIAR 0x0C // offset to interrupt acknowledge reg
#define ICCEOIR 0x10 // offset to end of interrupt reg
/* Interrupt controller (GIC) distributor interface(s) */
#define MPCORE_GIC_DIST 0xFFFED000 // PERIPH_BASE + 0x1000
#define ICDDCR 0x00 // offset to distributor control reg
#define ICDISER 0x100 // offset to interrupt set-enable regs
#define ICDICER 0x180 // offset to interrupt clear-enable regs
#define ICDIPTR 0x800 // offset to interrupt processor targets regs
#define ICDICFR 0xC00 // offset to interrupt configuration regs