This DAC(MCP4821) module was developed by the UPB students Jose Velandia & Henry Lizaro in the year 2012 to control the single channel 12-bit Digital-to-Analog converter (DAC) with internal voltage reference of Microchip MCP4821. You will find here the description of the module, plus a very useful application on digital modulations(ASK, FSK, BPSK, QPSK), that you could use to learn more about digital modulations and to visualize at the output of the MCP4821 DAC.

 


Verilog Module

 

Datasheet of the DAC MCP4821 

 

Instantiation

/*MCP4821*/												
MCP4821 Dac_FSM_inst
(
	.clk_40mhz(clk_40Mhz) ,	// input  CLOCK_IN_sig
	.START(start_signal) ,	// input  START_sig
	.TRAMA({~data[11],data[10:0]}) ,	// input [11:0] TRAMA_sig
	.ENABLE(1'd1) ,	// input  ENABLE_sig
	.GAINx2(1'd0) ,	// input  GAINx2_sig
	.SHDN(1'd0), 	// input  HZ_sig
	.CSn(GPIO[0]) ,	// output  CSn_sig
	.SCK(GPIO[1]) ,	// output  SCK_sig
	.SDI(GPIO[2]) ,	// output  SDI_sig
	.LDAC(GPIO[3])	// output  LDAC_sig
);			

 

Module Description:

  • This module operates at a clock frequency of 40 MHz.
  • It interfaces with an MCP4821 Digital-to-Analog Converter (DAC) and manages the SPI communication protocol.
  • The module accepts the following inputs:
    • START (1 bit): Initiates the Finite State Machine (FSM).
    • TRAMA (12 bits): Data input for the DAC.
    • ENABLE (1 bit): Enables the module.
    • GAINx2 (1 bit): Selects the gain of the DAC (0 for 1x, 1 for 2x).
    • SHDN (1 bit): Controls the shutdown mode of the DAC.
  • It has the following SPI interface signals:
    • CSn (1 bit): Chip Select.
    • SCK (1 bit): Serial Clock.
    • SDI (1 bit): Serial Data Input.
  • The module provides one output:
    • LDAC (1 bit): This signal is used to synchronize and transfer data from the input latch register to the DAC register (output latches, VOUT).

Finite State Machine (FSM) Operation: The module employs a Finite State Machine (FSM) to control the DAC MCP4821 and ensure proper timing and synchronization during the SPI communication. Here's how it works:

  1. Initialization (ESTADO_1):

    • The module waits for the START signal to initiate an operation.
  2. Data Transfer Setup (ESTADO_2 - ESTADO_4):

    • If START is high, the module proceeds to ESTADO_2, where it checks the other control signals.
    • It prepares for data transfer in ESTADO_3 by enabling SDI_ON.
    • In ESTADO_4, data transfer commences, and the module shifts the 12-bit data onto the SDI line according to the SPI protocol.
  3. LDAC Control (ESTADO_5 - ESTADO_6):

    • After data transfer, the module manages LDAC synchronization:
      • In ESTADO_5, it raises LDAC.
      • After a delay (controlled by LDAC_ON_H), it transitions to ESTADO_6, lowering LDAC.
  4. Idle Period (ESTADO_7):

    • In ESTADO_6, it waits for an idle period before starting a new operation.
    • This ensures that all signals are in the correct state before initiating another operation.
  5. Finish (ESTADO_1):

    • After the idle period, the module returns to ESTADO_1, ready for a new operation.

Operation Overview:

  • The module's operation is initiated by setting START.
  • It follows the SPI protocol, managing CSn, SCK, and SDI for data transfer.
  • LDAC synchronization ensures proper updates to the DAC output.
  • The LDAC signal is used for synchronization and is set as per the timing requirements of the MCP4821 DAC.
  • The FSM allows for proper timing and synchronization for DAC operations.

 

DAC output Calculation for MCP4821 

 

MCP4821 SPI Communication Frame 

 

Example on the board DE0-NANO.

 

In the following FPGA project example for the DE0-NANO, we have several key components(observe figure below):

  1. Random Signal Generator (LFSR_generator): This part creates random data that can be used for various purposes. It runs on a 50 MHz clock and produces 4 bits of random data.

  2. Modulation Modules: a. ASK Modulator (ask_modulation): This module takes the random data and uses it to perform Amplitude Shift Keying (ASK) modulation. The result is a 12-bit signal (Ask) that represents information encoded in the signal's amplitude. b. FSK Modulator (fsk_modulation): Similar to ASK, this module employs the clock and random data to carry out Frequency Shift Keying (FSK) modulation. It produces a 12-bit signal (Fsk) with information encoded in the signal's frequency. c. BPSK Modulator (bpsk_modulation): This module applies Binary Phase-Shift Keying (BPSK) modulation using the clock and random data. It generates a 12-bit signal (Bpsk) with information encoded in the signal's phase. d. QPSK Modulator (qpsk_modulation): Using the clock and a 2-bit random data input, this module performs Quadrature Phase-Shift Keying (QPSK) modulation. The output is a 12-bit signal (Qpsk) with information encoded in both amplitude and phase.

  3. Multiplexer (mux_comunica): Think of this as a switch. It selects one of the modulation signals (ASK, FSK, BPSK, or QPSK) based on the position of physical switches (SW[1:0]). The chosen modulation signal is then sent to the MCP4821 module.

  4. MCP4821 (Dac_FSM_inst): This module connects to the MCP4821 Digital-to-Analog Converter (DAC). It operates on a 40 MHz clock and receives the selected modulation signal. It appears to control the DAC chip and produce an analog signal.

  5. GPIO Signals: These signals are used for communication with the MCP4821 chip.

  6. LEDs and Switches: The LEDs display information or status, and the switches (SW[1:0]) allow you to select the type of modulation you want to work with. The switch combinations and their corresponding selected modulations are as follows:

    • SW[1:0] = 00: ASK Modulation
    • SW[1:0] = 01: FSK Modulation
    • SW[1:0] = 10: BPSK Modulation
    • SW[1:0] = 11: QPSK Modulation

In essence, this project generates various types of modulated signals (ASK, FSK, BPSK, QPSK) using random data. You can select one of these modulated signals using the switches, and the MCP4821 module helps convert this digital signal into analog, which can be used for various applications.



You can download the Quartus project to have a template or to test your MCP4821 DAC

 

If you synthesize this application example, you need to have a MCP4821 connected to the GPIOs of the FPGA, and then you will see.

 

  • SW[1:0] = 00: ASK Modulation


  • SW[1:0] = 01: FSK Modulation


  • SW[1:0] = 10: BPSK Modulation


  • SW[1:0] = 11: QPSK Modulation

 

 

 

 

 

 

Authors:

Full Paper for Citation: 

 

Verilog files for the core:

 

Video Example of the core working on a Real Vital Signs Monitor:



 

 

 

Introduction

 

Signal wave graphing is a common requirement in embedded instrumentation systems dedicated to the monitoring and logging of external variables. However, this functionality requires a lot more resources than the ones available in simple signal acquisition systems as expected in power and economic budgets, as they may require the use of external GPUs that integrate a variety of graphing resources unnecessary for logging-and-graphing dedicated applications, such as Digital Oscilloscopes, Industrial Monitoring, Vital Signs Monitors and others.

A Verilog HDL module for the acceleration of signal wave graphing using FPGAs has been developed as part of an ongoing process carried by the ADT(Advanced Digital Technologies) academic working-group at UPB(Universidad Pontificia Bolivariana) Bucaramanga. The ADT group develops resources related to its fields of study and leaves them available and open for other students and the engineering industry to use in embedded systems solutions. This paper describes this module's justification, specifications, development methodology, comparison test results, performance and future work.

An advantage provided by the use of FPGAs is the possibility of performing signal wave graphing using the same integrated circuit used for signal processing and peripheral interfaces, without the high cost related to custom ASICs (Application Specific Integrated Circuits). FPGAs are a fast way of getting to market with highly integrated devices before or without moving to ASICs. For instance, Global Information and Communication Technology service provider Huawei was known for being the single largest buyer of FPGAs before changing their commercial solutions to ASICs [*], and recent news stated that Intel will be manufacturing Altera's high-end FPGAs, giving them an edge in technology that should boost the use of their devices in faster design-to-market solutions.

The algorithms for signal wave graphing can be carried out by a processor with the use of graphing libraries and frame dedicated modules, but these systems result in slower processing speeds for any other task, as video processing is a very demanding task by itself due to the speeds required to perform stable and optimal frame rates. However, the iterative nature of rasterization and other wave related algorithms makes them highly translatable to efficient HWD modules, where the inputs are points X and Y, where X could be time and Y is the input data, while the output is the wave pixels setting to be plotted in the display. This project makes use of custom HWD for the acquisition and processing of incoming data from multiple signal waves, as well as rasterization algorithms and the graphing of pixels directly into the video frame.

 

Graph Module

A following step is to develop a set of modules that are capable of graphing any input data. For this purpose there is a peripheral device that delivers mutiple-wave continuous data through a UART (Universal Asynchronous Receiver Transmitter) transmission that has to be decoded and arranged. The graphing modules store a complete trace of the wave and create the graph to be displayed through VGA.

 


Figure 1. Block Diagram of video synchronization and frame drawing module

 

The first module required for this purpose takes the synchronization signals, that in the case of VGA are Horizontal and Vertical Sync, and counts them to obtain the location (X,Y) of the pixel being set in the frame. It resets in every frame and is configurable for any resolution. This count is then pipelined into the Graph Module, that is also given data from a UART receiver module, which stores every new data in RAM addressed by the X axis count. These two inputs are then used to create a wave graph according to the configuration inputs that allow the user to change any graph parameter: color, size, position, visibility, speed and mode (scroll or redraw). Figure 1 is a block diagram of the three mentioned modules, along with a VGA synchronization block that generates the corresponding H-Sync and V-Sync signals according to the resolution and frame rate to be displayed.

 

Every new data received in the Graph Module is the amplitude of a signal. They are cyclically written into a RAM which depth is equal to the width of the wave graphing area in the interface, i.e. 640 in a 640x480 screen where the wave graph takes the whole screen. Every row in RAM matches a pixel in the graphing area where pixel count X is the address of the data in RAM shifted by the X location of the wave graph area, and pixel count Y is compared to the amplitude of the data in that address, which is also shifted by the Y location of the wave graph area, when it is read. For Y the number is negated, taking into account that the pixel count starts at 0,0 that is the leftmost upper corner and the wave should increase towards that direction.

The X pixel count is then constantly reading this RAM, and the Graph Module determines whether the current pixel should display or not a wave dot when pixel count Y matches the data read. The outputs from the Graph Module are then the RGB colors configured by the user and a bit signal called “Graph ON” that is high when the pixel being displayed matches the data to be graphed. This results in a cyclical drawing of dots along the axes of the graph, like the ones pictured in image (a) of Figure 2, which does not represent a continuous graph. A rasterization algorithm is then required in order to obtain continuous lines joining the dots, so this process is also carried out by a logical HWD inside the Graph Module.

 

Figure 2. Data Rasterization. (a) Data as pixels. (b) Data as lines.

 

 

When a new amplitude data is read from RAM, the previous data is saved in a register and is used to determine if a line of pixels should be drawn above or under the new data pixel, to connect both dots. It is a simple rasterization algorithm that allows a continuous line to be drawn from a vector of data, these pixels are then going to generate a “Graph ON” signal when the following condition is true:

wire SlopeFX=
((CountY_in+line_width)>=((SDRAM_OUT_1[7:0]/Height)+ Pos_Y))?
((CountY_in<=((SDRAM_OUT[7:0]/Height)+ Pos_Y))&
((CountY_in+line_width)>=((SDRAM_OUT_1[7:0]/Height)+ Pos_Y))):

((CountY_in)<=((SDRAM_OUT_1[7:0]/Height)+ Pos_Y))?
(((CountY_in+line_width)>=((SDRAM_OUT[7:0]/Height)+ Pos_Y))&
(CountY_in<=((SDRAM_OUT_1[7:0]/Height)+ Pos_Y))):

1'b0;

 

Figure 2 (b) is a demonstration of how lines are drawn using this module, gray pixels are drawn by the rasterization conditions while black ones are read directly from RAM.

 

The configuration for a “scroll” display mode is done by incrementing the address register for RAM, giving the appearance that data is being shifted through RAM. When RAM is overflowed the address offset register resets and continues the process. The full I/O port list of the graph module is as follows:

module plot_graph(	
		//Inputs
		CountX_in,//X-position of current pixel
		CountY_in,//Y-position of current pixel
		data_graph,//Input data to store in RAM
		data_graph_rdy,//Input data ready
		display_clk,//Graph module clock = Video clock
		color_graph, //RGB format graph color
		scroll_en,//Painting mode: Scroll or Redraw
		Pos_X,//X-axis position for graph origin
		Pos_Y,//Y-axis position for graph origin
		Witdh,//Ammount of data to be graphed
		Height,//Maximum wave amplitude
		line_width,//Pixel width of the wave
		Graph_en,//View graph or make invisible
		reset_n,//Active-low reset
		pause_graph,//Stop graphing new data
		//Outputs
		Graph_on,//Graph is showed in current pixel
		R,//Red component
		G,//Green component
		B//Blue component
	);

 

First Test

 

The first testing stage of these modules involves a comparison with a wave graphing system based solely on software, for which the Nios II soft-processor from Altera was chosen, along with the DE0-Nano Development board with external RAM(Random Access Memory) and Altera’s VIP Cores. As shown in Figure 3, the processor takes the UART input, graphing libraries and control of the video cores to perform the graphing process, data is written to RAM with functions that form the waves according to the video frame format that the frame reader can use. However, when processing multiple signals, this system presents stuttering and lost values caused by the sequential processing, rasterization and graphing of data with insufficient clock speeds required to display an optimal frame rate. This design is then used as a base to create a second test by merging it with the previous HWD design.

Figure 3. Block Diagram of the First Test

 

 

Second Test

 

In order to broaden the applications of the first HWD modules there needs to be an additional processing system that creates a video source to work as a background and for user interaction, on top of which the waves will be graphed. Figure 4 is an example of the video output used for the system tests, in which only the graphs are implemented with SW(1st Test) or HWD(2nd and 3rd Tests), while the picture and the labels are always drawn using SW. This background, labels and pictures are set by a system similar to the one used in the first test: a Nios II processor, VIP Cores and a user input (Touch, Keyboard or Mouse). The system uses a Frame Reader module to acquire sprites and drawings from RAM to use as buttons, text boxes, lines and pictures; these form a GUI (Graphic User Interface) with a dedicated area for wave graphing.

Figure 4. Video Output Example

 

 

Frames are then sent through a video converter or CVO (Clocked Video Output) that turns them into VGA or Digital RGB format so they can be run through the previously designed HWD modules. This results in a processing system dedicated to the GUI that is going to be updated with every interaction of the user, at very low frequencies, and a HWD system for the signal graphing that requires higher frequencies related to data acquisition and visualization. Data acquired through a UART module attached to the Nios II processor is decoded and then sent  to the Graph Module where it rasterizes the data into waves to be blended with the background. The resulting system is pictured by the block diagram in Figure 5. Control signals for wave parameters like color and location are sent from the Nios II processor to the graphing module. This approach shows a performance upgrade from the previous system but the task for data acquisition and decoding is still demanding processor resources that can be outsourced.

 

Figure 5. Block Diagram of the Second Test

Third Test

 

For the final design, the UART data decoding and arranging is taken out of the processor and put into a custom HWD module, distributing the design and releasing more processing tasks out of the Nios II, as shown in Figure 6. Similar to the first HWD, this design shows a wave graph on the display if no other video has been set by the Nios II and VIP modules. It keeps the configuration ports attached to the Nios II allowing the customization of the graphs through interaction of the user, whether it is by using a touch display or through other input devices attached to the Nios II. The Nios II processor uses the VIP modules to lay a background and GUI (Graphical User Interface), resulting in a complete system for the visualization of signal graphs with the possibility for interaction and custom interface designs.

 

Additional development involved the use of LCDs instead of VGA monitors, which requires a different Video Frame Converter and connection of the video signals to the “Pixel Count” module, without regarding the other components of the design as RGB data is kept the same way. This serves as an example of the flexibility offered by this development, by performing equally in both Xilinx and Altera and with different display technologies with only a few modifications. These changes can be done due to a pure Verilog description of the modules without depending on device primitives or additional software.

 

Figure 6. Block Diagram of the Third Test

 

Results

Each of the three testing systems was run with different parameters, varying frequencies and all versions of the Nios II processor (Fast, Standard and Economic) that can achieve 170, 96 and 23 DMIPS (Dhrystone Million Instructions Per Second) correspondingly at 150 MHz. The results acquired from these tests can be divided in three main characteristics: Each Graph Module's implementation, Frames Per Second (FPS) and power dissipation.

Table 1 is a detailed description of how each Graph Module is implemented in the FPGA for every test. Although the resolution values and frequency are variable, the remaining values are exactly the same for every instance that is added to the design. Therefore, a system with 8 Graph modules will occupy 8 times 99 Logic Cells (LC) of combinational logic, 8 times 27 LC of register logic and 8 times 3840 bits of memory. This is the characteristic that allows for a better performance of the system, both in FPS as well as power.

 

Table 1. Characteristics of each graphing module

 

FPS are the most important unit of measure in these tests and the results shown in Figure 7 are the justification for this project. This graph shows the number of FPS that every test system can show using different parameters and with an increasing number of waves to be graphed. The first test system is run with the highest DMIPS processor, the second test is done with a Standard Nios II while the third test is run with the lowest performance processor. This however shows that while the first test is unable to keep a FPS rate of 60 Hz with more than one wave being graphed, the second test system is capable of graphing four, despite of having a lower performance Nios II and lower frequency. Furthermore, the third system is the only one capable of maintaining a stable 60 Hz FPS rate at the video output, while having the lowest performance Nios II, at 8 DMIPS (Nios II economic at 50 Hz). The same results can be achieved by the third test system using any other operational frequency for the Nios II processor, this is because the data acquisition and graphing is done independently.

 

Figure 7. FPS Comparison

 

 

The use of HWD modules dedicated to demanding tasks like data processing, decoding and video algorithms results in a direct power consumption reduction. These modules called “Accelerators” have the objective of releasing a task from a processor and they can be made by using tools such as C2H (C to Hardware) translators. However, the most accurate way of “Accelerating” any task is by creating a custom HWD module from scratch, although it is very time consuming for any project. The tasks chosen to be accelerated need to have a behavior that can be parallelized and successfully converted to HWD, video processing is a good example. 

 

An approximation of the power dissipation of every HWD module can be derived from the device and described system's characteristics, such as frequency, LC and operating temperature (25°C room temperature by default), the Quartus II software from Altera gives an approximate Total Thermal Power that is a sum of the Dynamic, Static and I/O power estimated in the design . This value is the one used in this project to compare each of the evaluated systems, by taking the minimum power at which the compared system is capable of graphing one wave at 60 Hz, the results are shown in Figure 8.

 

Figure 8. Minimum power at 60FPS

 

The decrease that can be seen between the first and second tests relates only to the Graph Module as it was shown in the previous block diagrams, however, when the third system is tested at 120 MHz the power reduction relates not only to the Graph Module but also to the UART receiver and decoder that is now a HWD and is not being done by SW, thereby the system is capable of displaying a 60 HZ FPS video output while having a lower performance Nios II that is also reducing power consumption. Further reduction of power in the latter examples can be expected due to the relation between frequency and power in digital circuits, the Nios II processor frequency can be reduced, whereas the Graph module’s frequency remains as 40 MHz.

 

Conclusion

 

The final design, used as the third testing system, shows a liable behavior under demanding conditions like multiple graphs and complex data frames, making it appropriate for FPGA-based embedded systems or SoC (System on-a Chip) implementations where a high level of reliability is required in the continuity and stability of real-time multiple wave graphing (i.e Digital Oscilloscopes, Spectrum Analyzers, Vital Signs Monitors or Audio players).

 

The system offers ease of scalability and real-time processing while keeping a lower memory usage due to the use of raw data vectors and the re-processing of it to obtain the wave graph on every frame read, instead of storing the processed matrices or graphical objects. This is also more energy efficient despite of having to put the data through the combinational logic that determines the waves to be graphed every single time.

 

In regard to power consumption the module showed a noticeable upgrade from a typical application using the Nios II to write the video frames in memory, this is even more relevant when the system requires the graphing of more than one wave. Although for this kind of values the tests were limited, taking into account that between the two systems (first and third), only the final system was capable of displaying eight wave graphs while still keeping a stable FPS rate. However, compared to the second system there was always a decrease in power related to the implementation of UART data reception and decoding with a custom HWD module instead of the Avalon interface used in the previous implementations (e.g 0.64 mW for the UART receiver and decoder).

 

Future work on this system aims towards the standardization of the system modules by using a more complex HWD for the rasterization algorithm (e.g. Bresenham's Algorithm). As a result the Graph Module should be able to still perform real-time processing of the data points with configurable width and extend its application to dynamic X axis data. This Graph Module's visualization could then be optimized by adding a function for lines and markers, and also upgraded to be used through Avalon or Wishbone bus standards, improving its applicability in commercial FPGA systems.

 

 

 

 

 

 

 

 

 

The PWM module varies the duration (time) of the high and low states of an output signal based on an internal count (modifiable Nbits) and a comparison (duty and period). This has various applications in the field of electronics, ranging from control to digital communications. PWM can be used to control the speed of a motor, among other applications.

Figure 1 – PWM Module.

 

Equations:

 

FRECpwm=output frequency of the module in Hz

CLKin= Input clock frequency in Hz

PERIODOpwm=Max value of the internal counter of the PWM.

Note: The maximum value of Duty[n:0] is determined by the value of the Period.

 

Example 1 (Modular instantiation):

If you want Frec_pwm = 20KHz and you have a period = 250, what should be the input clock frequency to the PWM module?

 

 

If we apply the formula given earlier:

 

Example 2:

Let's assume CLK_in = 50MHz, Nbits = 3, Period = 7, and a fixed duty = 3.

 

How would the output signal of the PWM module look and what is the period of the signal?

 

Figure 2 - Annotated simulation of the PWM module.

 

Figure 3 - Simulation of the PWM module

 

Applying the formula, it would be:

 

 

 

Verilog Module(PWM.v):

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    18:31:09 06/04/2009 
// Design Name:    Jose Pablo Pinilla & Holguer A Becerra
// Module Name:    PWM 
// Project Name:   
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision:  
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

module PWM #(parameter Bits_counter = 7, Periodo=3'd7)
	 (	input  clk, output motor, input  [Bits_counter-1:0] duty_cycle);	
   
   reg [Bits_counter-1:0] Timer1=0;
   reg PWM_OUTPUT;
	
	assign motor = PWM_OUTPUT; 
	
   always @(posedge clk)
	begin
		if (Timer1 >= Periodo)
			begin
					Timer1 <= 0;
					PWM_OUTPUT<=PWM_OUTPUT;
			end		
		else
		   begin
				  Timer1 <= Timer1+1; 
				  if (Timer1 >= duty_cycle)
						 PWM_OUTPUT<=1'b0;
				  else 
						PWM_OUTPUT <= 1'b1;		  
		   end
	end	
	
endmodule

 

 

 

 

 

 

 

 

 

 

 

 

 

Author: Jose Pinilla

Today, the use of UART serial communication in embedded systems and electronics projects is very common. UART communication is found in Bluetooth devices (SPP), WiFi, Ethernet, USB conversion, audio and video devices, and communication with a wide variety of OEM cards.

 

UART

 

Verilog code UART Full Duplex(UART_FullDuplex.v):

change parameter "baud_rate" to change speed rate

//=======================UART_FullDuplex=====================
//Engineer: Jose Pablo Pinilla
//Website:	semilleroadt.upbbga.edu.co


module UART_FullDuplex (
	input 	clk,
	//Transmitter
	input 	Tx_Start,
	input 	[7:0]Tx_Data,
	output 	Tx,
	output	TxD_Busy,
	//Receiver
	input 	Rx,
	output	[7:0]Rx_Data,
	output	RxD_Ready
	);

//========================Tx/Rx Control=====================

reg		Frame_Rx=0;						//Frame is being received
reg		Frame_Tx=0;						//Frame is being transmitted

assign	TxD_Busy = Frame_Tx;
assign 	RxD_Ready= ~Frame_Rx;

//=====================Baud Rate Generation==================
parameter clk_in_freq = 50000000;
parameter baud_rate = 4800;
localparam counter_limit = clk_in_freq/(2*baud_rate);

//Baud Rate
reg [15:0]div_clk_counter=0;
reg clk_count_reset=0;
reg baud_clk=0;

always @ (posedge clk or posedge clk_count_reset)
	if (clk_count_reset)
		div_clk_counter <= 0;
	else
		begin
			if (Frame_Tx|Frame_Rx)
				div_clk_counter <= div_clk_counter+1;
		end		

always @ (negedge clk)
	clk_count_reset <= (div_clk_counter==counter_limit-1);
	
always @ (posedge clk_count_reset)
	baud_clk <= ~baud_clk;
		
//======================Tx========================

//Tx Data Frame Counter

reg [3:0]Tx_counter=0;
	
always @ (negedge baud_clk or negedge Frame_Tx)
	if (~Frame_Tx)
		Tx_counter <= 0;
	else
		Tx_counter <= Tx_counter+4'd1;

wire Tx_Counter_Reset = (Tx_counter==10);

//Tx Detection

always@(posedge Tx_Start or posedge Tx_Counter_Reset)
	if (Tx_Counter_Reset)
		Frame_Tx <= 0;
	else
		Frame_Tx <= 1;

//Tx Shift Register

reg [9:0]OutBuffer = 10'b11111111_0_1;

always @ (posedge baud_clk or negedge Frame_Tx)
	if (~Frame_Tx)
		OutBuffer <= {Tx_Data,2'b01};
	else
		OutBuffer <= {1'b1,OutBuffer[9:1]};
				
//======================Rx=========================

//Rx Data Frame Counter

reg [3:0]Rx_counter=0;
	
always @ (negedge baud_clk or negedge Frame_Rx)
	if (~Frame_Rx)
		Rx_counter <= 0;
	else
		Rx_counter <= Rx_counter+4'd1;

wire Rx_Counter_Reset = (Rx_counter==10);
	
//Rx Detection
always@(negedge  Rx or posedge Rx_Counter_Reset)
	if (Rx_Counter_Reset)
		Frame_Rx <= 0;
	else
		Frame_Rx <= 1;
	
//Rx Shift Register

reg [9:0]InBuffer=0;

always @ (posedge baud_clk)
	if (Frame_Rx)
		InBuffer <= {Rx,InBuffer[9:1]};

//================Output Assignment==============
		
assign Tx = OutBuffer[0];

assign Rx_Data = InBuffer[8:1];

endmodule 

 

 

This Verilog HDL module is designed to meet the needs of many university students in their electronic instrumentation laboratories, where they often need to measure the angle, velocity, or position of a DC motor using an encoder.

 

Description of inputs and outputs of the HDL module:

 

Inputs:

- A: First input from the encoder.

- B: Second input from the encoder.

- Reset: Resets the pulse count and all outputs of the HDL module (active low).

 

Outputs:

- Encoder_pos: A 9-bit output that, depending on the number of pulses given by the encoder and its direction, marks a count from 0 to the maximum number of encoder pulses. Users can change the number of pulses by modifying the NUM_OF_PULSES parameter in the Verilog module. By default, the module was designed for use with encoders of 500 pulses.

- Dir_out: A 2-bit output that indicates the direction of rotation based on how the A and B inputs are connected. It will display '01' in one direction and '10' in the opposite direction. Upon system startup and after a reset, it is set to '00' (initialization condition).

- Zero: A 1-bit output that marks a pulse each time the encoder returns to the initial reference point of the internal count, indicating that it has reached the starting position

again after a reset.

 

Verilog instantiation:

encoder encoder_inst (
.A(A_sig) ,     // input A_sig .B(B_sig) ,     // input B_sig
.reset(reset_sig) , // input reset_sig
.encoder_pos(encoder_pos_sig) ,	// output [8:0] encoder_pos_sig .dir_out(dir_out_sig) ,	// output [1:0] dir_out_sig
.zero(zero_sig)	// output zero_sig 
);

 

Hardware connection:

 

 

 

Module(Motor_encoder.v):

//////////////////////////////////////////////////////////////////////////////////
// Company: Universidad Pontificia Bolivariana Seccional Bucaramanga, Semillero ADT
// Engineer: Holguer A Becerra
// 
// Create Date:    18:07:43 03/11/2010 
// Design Name:   
// Module Name:   Encoder 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////


module encoder(A,B,reset,encoder_pos,dir_out,zero);

// numero de pulsos del encoder
parameter NUM_OF_PULSES=9'd500;

input A;// Entrada A del Encoder
input B;// Entrada B del Encoder
input reset;

output [8:0]encoder_pos;// salida del encoder respecto al punto de iniciacion
output [1:0]dir_out;// direccion para donde va el rotor del encoder, dependiendo de la conexion A y B, cuando se inicia es 0, y 2 o 1 de acuerdo al sentido de giro
output zero;// Dependiendo del punto de iniciacion, esta salida marca un pulso si pasa nuevamente por la posicion inicial

reg [8:0]counter=9'd0;
reg [1:0]dir_out_temp=2'd0;

assign dir_out[1:0]=dir_out_temp[1:0];
assign encoder_pos[8:0]=counter[8:0];

// paso por zero
assign zero=(counter==9'd0);


// conteo de pulsos
always@(posedge A,negedge reset)	 
begin
	if(!reset)
		begin
			counter<=9'd0;
		end
	else
		begin
		  if(B)
			 begin
						if(counter==9'd0)counter<=NUM_OF_PULSES-1'b1;
						else counter<=counter-9'd1;
						
			 end	
		  else
			 begin  
						if(counter==(NUM_OF_PULSES-1'b1))counter<=9'd0;
						else counter<=counter+9'd1;
			 end
		end
end


// sentido de giro
always@(posedge A, negedge reset)	 
begin
	if(!reset)
		begin
			dir_out_temp<=2'd0;
		end
	else
		begin
		  if(B)
			 begin
						
						dir_out_temp<=2'b01;
			 end	
		  else
			 begin  
						dir_out_temp<=2'b10;
						
			 end
		end	 
end




endmodule