A Serial-In-Parallel-Out shift register IC is very popular among micro-controller programmers. It's commonly use for I/O extending, LED driving, relay driving, etc. The SN75C595N or the SN74HC164 are commonly used with micro-controllers to expand their outputs.
Hardware test on bread-board with Arduino Uno SPI |
Using a CPLD/FPGA we can create any digital circuit including this type shift registers chip. In this example, I use the XC95108 CPLD to create a 16-bit serial in parallel out shift registers chip. The chosen language is VHDL.
The designed chip include reset(RST), serial clock(CLK), and serial data in (DIN). Its output is an 16-bit output port connects to LED.
---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 10:34:09 01/29/2024 -- Design Name: -- Module Name: shift_regs_16_LED - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity shift_regs_16_LED is Port ( CLK : in STD_LOGIC; RST : in STD_LOGIC; DIN : in STD_LOGIC; LEDS : out STD_LOGIC_VECTOR (15 downto 0)); end shift_regs_16_LED; architecture Behavioral of shift_regs_16_LED is SIGNAL REGS: STD_LOGIC_VECTOR(15 DOWNTO 0); begin PROCESS(CLK,RST) BEGIN IF(RST='0') THEN REGS<=x"0000"; ELSIF(CLK'EVENT AND CLK='1') THEN REGS(0)<=DIN; REGS(1)<=REGS(0); REGS(2)<=REGS(1); REGS(3)<=REGS(2); REGS(4)<=REGS(3); REGS(5)<=REGS(4); REGS(6)<=REGS(5); REGS(7)<=REGS(6); REGS(8)<=REGS(7); REGS(9)<=REGS(8); REGS(10)<=REGS(9); REGS(11)<=REGS(10); REGS(12)<=REGS(11); REGS(13)<=REGS(12); REGS(14)<=REGS(13); REGS(15)<=REGS(14); END IF; LEDS<=REGS; END PROCESS; end Behavioral;
Its internal circuit doesn't need additional clock input to synchronize input data. The data is synchronized with serial clock pin from external device.
Its I/O pins are assigned as follow using the Floorplan I/O tool.
#PACE: Start of Constraints generated by PACE #PACE: Start of PACE I/O Pin Assignments NET "CLK" LOC = "P48" ; NET "DIN" LOC = "P50" ; NET "LEDS<0>" LOC = "P63" ; NET "LEDS<10>" LOC = "P67" ; NET "LEDS<11>" LOC = "P68" ; NET "LEDS<12>" LOC = "P69" ; NET "LEDS<13>" LOC = "P70" ; NET "LEDS<14>" LOC = "P71" ; NET "LEDS<15>" LOC = "P72" ; NET "LEDS<1>" LOC = "P62" ; NET "LEDS<2>" LOC = "P61" ; NET "LEDS<3>" LOC = "P58" ; NET "LEDS<4>" LOC = "P57" ; NET "LEDS<5>" LOC = "P56" ; NET "LEDS<6>" LOC = "P55" ; NET "LEDS<7>" LOC = "P54" ; NET "LEDS<8>" LOC = "P65" ; NET "LEDS<9>" LOC = "P66" ; NET "RST" LOC = "P47" ; #PACE: Start of PACE Area Constraints #PACE: Start of PACE Prohibit Constraints #PACE: End of Constraints generated by PACE
After the design and programming process are completed, we can test this circuit manually with a few on-board input switches. For convenience we can use a popular Arduino Uno as an SPI master device transferring a 16-bit data to this shift registers chip.
#include<SPI.h> void setup() { SPI.begin(); } char data[2]; void loop() { data[0]=0xF0; data[1]=0x0F; SPI.transfer(data,2); delay(1000); data[0]=0x0F; data[1]=0xF0; SPI.transfer(data,2); delay(1000); }
The circuit connections between the Arduino Uno and the XC95108 CPLD are:
Arduino Uno XC95108 CPLD Prototype Board
GND GND
PIN11 (MOSI) P50
PIN13 (SCK) P48
I use the Arduino SPI module and library without bit-banging. Optionally we can use the on-board 7-Segment display instead of the LED.
Click here to download its source file.
No comments:
Post a Comment