Using the Nexys-2 platform, Prawal Shrestha and I designed and implemented a digital system that utilizes the Xilinx Spartan 3E FPGA to allow users to create ASCII characters in an external RAM and then transmit them serially for display on the PC.
The writing process goes as follow: Setup the ASCII code for the first letter on the DIP switch (e.g. 0x4A for 'J') and press a button (the 'write' button) to store it in the bottom location of the RAM. Change the DIP switch to enter the second, third, and fourth characters, and press the button to load these one at a time into the next three RAM locations.
At any time we are able to verify the contents of the RAM by setting a RAM address on the DIP switches. The RAM contents at this address will then be displayed on two of the seven-segment displays.
When pressing another button (the 'transmit' button) the four stored ASCII characters will then be serially transmitted to the PC for display. After transmitting the four characters we would still be able to repeat the above exercise.
There are two main components: the Transmitter and the SRAM Controller (which consists of the memory state machine and the address state machine). The idea is that the SRAM controller alters the data in the SRAM and the Transmitter reads those data and transmits them serially over the RS232 to display on the PC.
These were used to store the constant values.
All these were used in intermediate processes. For example, counters were used so that the transmitter knew when it had completed reading from all four addresses.
The flip-flops were needed to implement the two state machines and the clock synchronous processes.
This was used to do the anode multiplexing in the driver for the seven-segment display.
We administered two consecutive writes and two consecutive reads. The two values we wrote are “x55” and “xAA”. In the “data” line above, we can see these values are repeated indicating writes and reads. Also the “writeb” and “readb” buttons show that the two writes were performed and then the two reads were executed.
The one problem we encountered was keeping track of what address the device is to write to next and what process (idle, read, or write) the device is currently doing. We first tried to do this using only one state machine but we discovered that our design may be better with two: one to keep track of the address and the other to keep track of the current process.
From this project, we learned how to work the SRAM hardware and how to transmit over the RS232 serial port. We also learned how to integrate more than one state machine into a single device.
We could extend this project by adding more features such as the ability to transmit data from the PC, through the RS232, and into the SRAM of our Nexys2 board.
Introduction
Using the serial port and the RAM on the Nexys 2 board, our goal is to enter the four ASCII characters into RAM and then transmit them serially for display on the PC. The external RAM is a 128Mbit Micron device connected to a 16-bit bus. We only used the bottom four 8-bit locations to store the ASCII characters.The writing process goes as follow: Setup the ASCII code for the first letter on the DIP switch (e.g. 0x4A for 'J') and press a button (the 'write' button) to store it in the bottom location of the RAM. Change the DIP switch to enter the second, third, and fourth characters, and press the button to load these one at a time into the next three RAM locations.
At any time we are able to verify the contents of the RAM by setting a RAM address on the DIP switches. The RAM contents at this address will then be displayed on two of the seven-segment displays.
When pressing another button (the 'transmit' button) the four stored ASCII characters will then be serially transmitted to the PC for display. After transmitting the four characters we would still be able to repeat the above exercise.
Design
A state machine with three states was used to control the overall operation of this device. The two states implemented are idle, read and write. The idle state is where the device does not do anything at the rising clock edge. The write state is where the device writes into the SRAM the 8-bit value that the user set using the DIP switches. The read state is where the device reads one of four addresses that could be accessed depending on the DIP switch configuration. The state machine transitions from state to state depending on either the read button or the write button. We call this state machine the Memory State Machine. Another state machine was used to keep track of which SRAM address the device will be writing to next. We call this state machine the Address State Machine.State Machines
The state diagrams (and their corresponding code snippet) below show the two state machines used in the device:Memory State Machine
This state machine is used so that the device knows what process it is currently doing.--============================= |
--memory state machine |
--============================= |
--state memory |
state_memory: process(clk_1hz,rst) |
begin |
if rst = '1' then |
curr_s <= idle_s; |
elsif clk_1hz'event and clk_1hz = '1' then |
curr_s <= next_s; |
end if; |
end process state_memory; |
--next state logic |
next_state: process(curr_s, writeb, readb) |
begin |
case curr_s is |
when idle_s => |
if writeb = '1' then |
next_s <= write_s; |
elsif readb = '1' then |
next_s <= read_s; |
else |
next_s <= idle_s; |
end if; |
when write_s => |
if writeb = '0' then |
next_s <= idle_s; |
else |
next_s <= write_s; |
end if; |
when read_s => |
if readb = '0' then |
next_s <= idle_s; |
else |
next_s <= read_s; |
end if; |
end case; |
end process next_state; |
Address State Machine
This state machine was implemented to keep track of which address location on the SRAM the device should write to next.--============================= |
--address state machine |
--============================= |
--state memory |
process(clk_1hz, rst) |
begin |
if rst = '1' then |
curr_a <= a0; |
elsif clk_1hz'event and clk_1hz = '1' then |
curr_a<= next_a; |
end if; |
end process; |
--next state logic |
process(curr_a,writeb) |
begin |
case curr_a is |
when a0 => |
if writeb = '1' then |
next_a <= a1; |
else |
next_a <= a0; |
end if; |
when a1 => |
if writeb = '1' then |
next_a <= a2; |
else |
next_a <= a1; |
end if; |
when a2 => |
if writeb = '1' then |
next_a <= a3; |
else |
next_a <= a2; |
end if; |
when a3 => |
if writeb = '1' then |
next_a <= a0; |
else |
next_a <= a3; |
end if; |
end case; |
end process; |
--output logic for the state machine |
cur_addr <= addr1 when curr_a = a0 else |
addr2 when curr_a = a1 else |
addr3 when curr_a = a2 else |
addr4 |
Block Diagram
This is the block diagram for the device:There are two main components: the Transmitter and the SRAM Controller (which consists of the memory state machine and the address state machine). The idea is that the SRAM controller alters the data in the SRAM and the Transmitter reads those data and transmits them serially over the RS232 to display on the PC.
Resource Usage
The list below shows the resources used:
2 ROMs:
1 16x7-bit ROM
1 4x2-bit ROM
4 Adders/Subtractors:
1 11-bit adder
3 25-bit adder
5 Counters:
1 11-bit up counter
3 25-bit up counter
1 4-bit down counter
1 Comparators:
1 4-bit comparator greater
59 Registers:
59 Flip-Flops
1 Multiplexers:
1 4-bit 4-to-1 multiplexer
Test Bench Waveform & Oscilloscope Display
Test Bench Waveform
After implementing the read and write process we tested our program using a VHDL test bench. The code for the test bench can be found in the appendix. This test was performed before we implemented the serial communication feature. As such, the entity port of the main unit in the test bench is less than it actually is in the completed program. The result of the test bench is shown below.We administered two consecutive writes and two consecutive reads. The two values we wrote are “x55” and “xAA”. In the “data” line above, we can see these values are repeated indicating writes and reads. Also the “writeb” and “readb” buttons show that the two writes were performed and then the two reads were executed.
Oscilloscope Display
We used an oscilloscope to capture the transmitted serial communication of one 8-bit data. The 8-bit data below corresponds to “10101010”. Below is the annotated oscilloscope waveform.Conclusion
Our project successfully achieved our design goals. We were able to write and read from the SRAM as well as transmit the data from the SRAM through a RS232 serial port.The one problem we encountered was keeping track of what address the device is to write to next and what process (idle, read, or write) the device is currently doing. We first tried to do this using only one state machine but we discovered that our design may be better with two: one to keep track of the address and the other to keep track of the current process.
From this project, we learned how to work the SRAM hardware and how to transmit over the RS232 serial port. We also learned how to integrate more than one state machine into a single device.
We could extend this project by adding more features such as the ability to transmit data from the PC, through the RS232, and into the SRAM of our Nexys2 board.
This article was first published in 2008.
Comments
Post a Comment