FPGA Beginners - write 9226 two-way acquisition code by yourself

This is a record of writing your own code
If the car overturns, ask a big guy to correct it
First, open quartus to create a new project
Then choose your own development board
During the epidemic, when I was at home and didn't have a board, I chose a kind of development board that was often used by my friends~
Choose Verilog hdl from modelsim

Creation complete.

Click new projectNow I need to think about what I want to do with the results

So I Baidu searched the data manual of ad9226

AD9226 links to English materials
It may be a picture that helps your understanding

This chip will record data at every rising edge of the clock

Here we mainly analyze what the 28 pins of that chip represent

Pin Name describe
1 CLK This is the clock of the chip
2 BIT 12 Least significant bit (for a given data string (integer), such as 1001 in binary or 351 in decimal, the least significant bit is the bit with the lowest unit value. For example, the rightmost bit of binary 1001 has the value 1, which represents the lowest bit in the integer. The value of this bit can determine whether the integer is odd (1) or even (0). The same is true for decimal numbers. Generally, lsb is the rightmost bit of an integer, so it seems that the concept is redundant. However, there are exceptions. Some data transmission or processors are on the contrary. The left most bit is lsb, so this least significant bit is defined in the computing field to specify the data format.)
3-12 BITS 11-2 After the analog signal collected by the chip is transformed into a digital signal, the output port of the signal
13 BIT 1 Most significant bit (the bit with the highest value in a binary system). In 16 bit digital audio, the first bit has the greatest impact on the value of 16 bit words. For example, in the decimal number of 15389, the number equivalent to one line (1) of tens of thousands has the greatest impact on the value. Compare the opposite LSB.)
14 OTR out of range
15 AVDD 5V analog supply
16 AVSS Analog grounding
17 SENSE Reference selection, I don't understand
18 VREF Reference IO
23 VINA Analog input+
24 VINB Analog input-

Well, after reading this, I still don't understand

However, I may have a lost understanding that I need a. v file to read module or chip pins
So I created an ad.v document

If there is a module, there must be an end module. This is a good habit we need to develop when we write code
What I want to do next is what should I input and output in this module. So I looked at the codes of my predecessors and thought they were reasonable, so I wrote them by myself

module ad
(
          input ad_clk,
			 input [11:0] ad1_in,
			 input [11:0] ad2_in,
			 output reg[11:0]ad_ch1,
			 output reg[11:0]ad_ch2
    );
	 
	 

Two channels of input AD1 in ad2 in, and two channels of recorded data

always @(posedge ad_clk)
begin
    ad_ch1[11] <= ad1_in[0];  
    ad_ch1[10] <= ad1_in[1];  
    ad_ch1[9] <= ad1_in[2];  
    ad_ch1[8] <= ad1_in[3];  
    ad_ch1[7] <= ad1_in[4];  
    ad_ch1[6] <= ad1_in[5];  
    ad_ch1[5] <= ad1_in[6];  
    ad_ch1[4] <= ad1_in[7];  
    ad_ch1[3] <= ad1_in[8];  
    ad_ch1[2] <= ad1_in[9];  
    ad_ch1[1] <= ad1_in[10];  
    ad_ch1[0] <= ad1_in[11];  	 
	 
	 
	 
	ad_ch2[11] <= ad2_in[0];  
    ad_ch2[10] <= ad2_in[1];  
    ad_ch2[9] <= ad2_in[2];  
    ad_ch2[8] <= ad2_in[3];  
    ad_ch2[7] <= ad2_in[4];  
    ad_ch2[6] <= ad2_in[5];  
    ad_ch2[5] <= ad2_in[6];  
    ad_ch2[4] <= ad2_in[7];  
    ad_ch2[3] <= ad2_in[8];  
    ad_ch2[2] <= ad2_in[9];  
    ad_ch2[1] <= ad2_in[10];  
    ad_ch2[0] <= ad2_in[11];  
end 




endmodule

Then, two channels of data of 9226 module are collected and recorded at the same time by non blocking assignment.
After this step, I want to see the test bench simulation
So I built a new ad TB. V
File creation complete
After the teacher wrote so many test bench files, I still can't hahaha when I do it myself
At this time, I silently open the test bench file of tlv1544 written by the teacher

`timescale 1ns/1ns

`define clk_period 20

module TLV1544_CTRL_tb;

	reg Clk;
	reg Rst_n;
	reg Do_Conv;	//Start converting enable signal

	reg [3:0]ADC_CHSEL;	//Channel selection
	
	wire[9:0]ADC_DATA;	//Sampling results
	wire AD_DONE;	//Conversion completion signal
	wire DATA_Valid;
	
	reg TLV1544_SDO;
	reg TLV1544_EOC;
	wire TLV1544_SDI;	
	wire TLV1544_SCLK;	
	wire TLV1544_NCS;
	wire TLV1544_FS;

	TLV1544_CTRL TLV1544_CTRL0(

		.Clk(Clk),
		.Rst_n(Rst_n),
		
		.Do_Conv(Do_Conv),	//Start converting enable signal
		.AD_DONE(AD_DONE),	//Conversion completion signal
		.ADC_CHSEL(ADC_CHSEL),	//Channel selection
		
		.ADC_DATA(ADC_DATA),	//Sampling results
		.DATA_Valid(DATA_Valid),
		
		.TLV1544_SDO(TLV1544_SDO),	
		.TLV1544_SDI(TLV1544_SDI),	
		.TLV1544_SCLK(TLV1544_SCLK),	
		.TLV1544_NCS(TLV1544_NCS),	
		.TLV1544_FS(TLV1544_FS),
		.TLV1544_EOC(TLV1544_EOC)
	);
	
	initial Clk = 1'b1;
	always #(`clk_period/2)Clk = ~Clk;
	
	initial begin
		Rst_n = 1'b0;
		Do_Conv = 1'b0;
		ADC_CHSEL = 4'b0;
		TLV1544_SDO = 1'b0;
		TLV1544_EOC = 1'b1;
		#(`clk_period * 10 +1);//The main purpose is to stagger the release of RST х N and our clk, so as to facilitate the observation of signal changes
		Rst_n = 1'b1;
		#(`clk_period * 10);
		ADC_CHSEL = 0;//Select channel 0
		Do_Conv = 1'b1;//Generate read enable signal
		#(`clk_period);
		Do_Conv = 1'b0;
		@(posedge (TLV1544_CTRL0.LSM_CNT == 8'd189))//At the rising edge of the 10th module clock, the analog EOC is equal to 0, which means the data conversion is completed
		TLV1544_EOC = 1'b0;
		#(`clk_period*10 +3);
		TLV1544_EOC = 1'b1;
		#(`clk_period*1000 );
		
		ADC_CHSEL = 1;
		Do_Conv = 1'b1;
		#(`clk_period);
		Do_Conv = 1'b0;
		@(posedge (TLV1544_CTRL0.LSM_CNT == 8'd189))
		#(`clk_period);
		TLV1544_EOC = 1'b0;
		#(`clk_period*10 +3);
		TLV1544_EOC = 1'b1;
		#(`clk_period*1000 );
		$stop;
	end
	
	initial begin
	forever begin//forever must be used in the initial block, not in the always block
			TLV1544_SDO = ~TLV1544_SDO;
			#350;		
		end	
	end
	
endmodule

Uh huh. First of all, I need to instantiate the file I want to simulate. This is the first step. In the process of instantiation, I want to name the instantiation ad0 by the way

 ad ad0
(
          	 .ad_clk,
			 .ad1_in,
			 .ad2_in,
			 .ad_ch1,
			 .ad_ch2
    );
	 

Then define reg and wire according to the input and output types of data in ad
Like this, by the way, I checked that there was no grammatical error.
After running, it was found that there was no number of digits given after reg and wire in tb file, so there was no result, so it was changed

`timescale 1ns/1ns
`define clock_period 20


module ad_tb;

		reg ad_clk;
		reg [11:0]ad1_in;
		reg [11:0]ad2_in;
		wire [11:0]ad_ch1;
		wire [11:0]ad_ch2;


			 ad ad0
			(
						 .ad_clk(ad_clk),
						 .ad1_in(ad1_in),
						 .ad2_in(ad2_in),
						 .ad_ch1(ad_ch1),
						 .ad_ch2(ad_ch2)
				 );

	initial begin 


		ad_clk = 1'b1;
		ad1_in=12'b0;
		ad2_in=12'b0;

	end 
	always #(`clock_period/2)ad_clk = ~ad_clk;//Simulate the clock of ad
	
	
	
	initial begin
    ad1_in[0]=0;  
    ad1_in[1]=0;  
    ad1_in[2]=1;  
    ad1_in[3]=1;  
    ad1_in[4]=1;  
    ad1_in[5]=1;  
    ad1_in[6]=1;  
    ad1_in[7]=1;  
    ad1_in[8]=1;  
    ad1_in[9]=1;  
    ad1_in[10]=1;  
    ad1_in[11]=0;  	 
	 #300;
	 
	 ad2_in[0]=0;  
    ad2_in[1]=0;  
    ad2_in[2]=0;  
    ad2_in[3]=0;  
    ad2_in[4]=0;  
    ad2_in[5]=1;  
    ad2_in[6]=1;  
    ad2_in[7]=1;  
    ad2_in[8]=1;  
    ad2_in[9]=1;  
    ad2_in[10]=1;  
    ad2_in[11]=0; 
	 #300
	 $stop;
	end
	
			
endmodule 

It turned out to be like this, let alone it.
Next, read the 9226 code of predecessors
I found out they wrote a binary to decimal code
Well, yeah, binary to decimal is easier to see
First of all, bcd.v. It's hard to paste the elder code directly!

`module bcd(clk,
          hex,
          dec);//BCD Code, I need a module to input hexadecimal and output decimal

input  clk;
input  [16:0] hex;
output [19:0] dec;

wire [15:0] rrhex;
reg [3:0] rhex[3:0];

reg [17:0] rhexd;
reg [13:0] rhexc;
reg [9:0] rhexb;
reg [3:0] rhexa;

reg [5:0] resa,resb,resc,resd;
reg [3:0] rese;

assign rrhex = hex[16] ? ~hex[15:0]+1'b1 : hex[15:0];         //De sign
assign dec = {rese,resd[3:0],resc[3:0],resb[3:0],resa[3:0]};

always@(posedge clk)                 //First level register
begin
    rhex[3] <= rrhex[15:12];
    rhex[2] <= rrhex[11:8];
    rhex[1] <= rrhex[7:4];
    rhex[0] <= rrhex[3:0];
end

always@(posedge clk)                  //High 4 bit decoding
begin
    case(rhex[3])
        4'h0: rhexd <= 18'h00000;
        4'h1: rhexd <= 18'h04096;
        4'h2: rhexd <= 18'h08192;
        4'h3: rhexd <= 18'h12288;
        4'h4: rhexd <= 18'h16384;
        4'h5: rhexd <= 18'h20480;
        4'h6: rhexd <= 18'h24576;
        4'h7: rhexd <= 18'h28672;
        default: rhexd <= 10'h00000;
    endcase
end

always@(posedge clk)                //Sub high 4 bit decoding
begin
    case(rhex[2]) 
        4'h0: rhexc <= 14'h0000;
        4'h1: rhexc <= 14'h0256;
        4'h2: rhexc <= 14'h0512;
        4'h3: rhexc <= 14'h0768;
        4'h4: rhexc <= 14'h1024;
        4'h5: rhexc <= 14'h1280;
        4'h6: rhexc <= 14'h1536;
        4'h7: rhexc <= 14'h1792;
        4'h8: rhexc <= 14'h2048;
        4'h9: rhexc <= 14'h2304;
        4'ha: rhexc <= 14'h2560;
        4'hb: rhexc <= 14'h2816;
        4'hc: rhexc <= 14'h3072;
        4'hd: rhexc <= 14'h3328;
        4'he: rhexc <= 14'h3584;
        4'hf: rhexc <= 14'h3840;
        default: rhexc <= 14'h0000;
    endcase
end 

always@(posedge clk)
begin
    case(rhex[1])
        4'h0: rhexb <= 10'h000;
        4'h1: rhexb <= 10'h016;
        4'h2: rhexb <= 10'h032;
        4'h3: rhexb <= 10'h048;
        4'h4: rhexb <= 10'h064;
        4'h5: rhexb <= 10'h080;
        4'h6: rhexb <= 10'h096;
        4'h7: rhexb <= 10'h112;
        4'h8: rhexb <= 10'h128;
        4'h9: rhexb <= 10'h144;
        4'ha: rhexb <= 10'h160;
        4'hb: rhexb <= 10'h176;
        4'hc: rhexb <= 10'h192;
        4'hd: rhexb <= 10'h208;
        4'he: rhexb <= 10'h224;
        4'hf: rhexb <= 10'h240;
        default: rhexb <= 10'h000;
    endcase
end 

always@(posedge clk)
begin
    rhexa <= rhex[0];
end

always@(posedge clk) //Each result is single by the same level bcd Code addition,High level bcd Code to add the carry of the lower level,That's higher than4Bit part
begin   
    resa = addbcd4(rhexa[3:0],rhexb[3:0],rhexc[3:0],  rhexd[3:0]);
    resb = addbcd4(resa[5:4], rhexb[7:4],rhexc[7:4],  rhexd[7:4]);
    resc = addbcd4(resb[5:4], rhexb[9:8],rhexc[11:8], rhexd[11:8]);
    resd = addbcd4(resc[5:4], 4'h0,      rhexc[13:12],rhexd[15:12]);
    rese = resd[5:4] + rhexd[17:16];
end

function [5:0] addbcd4; 
input [3:0] add1,add2,add3,add4;
begin
    addbcd4 = add1 + add2 + add3 + add4;
    if(addbcd4 > 6'h1d)               //>29 At least one possibility0xf,But the number from binary conversion will not be greater than40Situation
        addbcd4 = addbcd4 + 5'h12;
    else if(addbcd4 > 5'h13)          //>19Plus results12
        addbcd4 = addbcd4 + 4'hc;
    else if(addbcd4 > 4'h9)           //>9Plus results6
        addbcd4 = addbcd4 + 4'h6;
end
endfunction

endmodule`

Voltage conversion code

Insert a code slice here`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name:    volt_cal 
//////////////////////////////////////////////////////////////////////////////////
module volt_cal(
   input        ad_clk,                  //
	
	input [11:0] ad_ch1,              //AD The first1Channel data
	input [11:0] ad_ch2,              //AD The first2Channel data


	output [19:0] ch1_dec,            //AD The first1Channel data(Decimal system)
	output [19:0] ch2_dec,            //AD The first2Channel data(Decimal system)
   
	output reg [7:0] ch1_sig,         //AD The first1Data positive and negative characters of the channel
	output reg [7:0] ch2_sig          //AD The first2Data positive and negative characters of the channel	

    );

reg [31:0] ch1_data_reg;
reg [31:0] ch2_data_reg;


reg [12:0] ch1_reg;
reg [12:0] ch2_reg;

reg [31:0] ch1_vol;              //AD The first1Channel data(16Binary system)
reg [31:0] ch2_vol;              //AD The first2Channel data(16Binary system)

//AD Voltage conversion
always @(posedge ad_clk)
begin
    if(ad_ch1[11]==1'b1) begin                     //If CH1 It is negative voltage.
	    ch1_reg<=12'hfff - ad_ch1 + 1'b1;
		 ch1_sig <= 45;                              //'-' asic Code for45
	 end
	 else begin
       ch1_reg<=ad_ch1;
		 ch1_sig<=43;                                //'-' asic code
	 end	 
		 
    if(ad_ch2[11]==1'b1) begin                     //If CH2 It is negative voltage.
	    ch2_reg<=12'hfff-ad_ch2 + 1'b1;
		 ch2_sig<=45;                                //'-' asic Code for45	 
	 end	 
	 else begin
	    ch2_reg<=ad_ch2;
		 ch2_sig<=43;                                //'-' asic Code for45
	 end	
	 
 
end 		 


//AD Voltage conversion(1 LSB = 5V / 2048 = 2.44mV
always @(posedge ad_clk)
begin
	ch1_data_reg<=ch1_reg * 5000;			
	ch2_data_reg<=ch2_reg * 5000;
			
   ch1_vol<=ch1_data_reg >>11;
   ch2_vol<=ch2_data_reg >>11;

end	

//16Base to decimal  
bcd bcd1_ist(         
               .hex           (ch1_vol[15:0]),
					.dec           (ch1_dec),
					.clk           (ad_clk)
					);

//16Base to decimal  
bcd bcd2_ist(         
               .hex           (ch2_vol[15:0]),
					.dec           (ch2_dec),
					.clk           (ad_clk)
					);
  
  
endmodule


Unfinished...

Published 12 original articles, won praise 9, visited 2376
Private letter follow

Tags: Verilog

Posted on Sat, 01 Feb 2020 23:43:46 -0800 by acannings