1
0
mirror of git://projects.qi-hardware.com/nn-usb-fpga.git synced 2025-01-10 12:50:14 +02:00
nn-usb-fpga/Examples/ADC/logic/ADC_peripheral.v
2010-04-02 23:30:52 -05:00

189 lines
6.0 KiB
Verilog

`timescale 1ns / 1ps
module ADC_peripheral( clk, reset, cs, ADC_EOC, ADC_CS, ADC_CSTART,
ADC_SCLK, ADC_SDIN, ADC_SDOUT,
addr, rdBus, wrBus, we);
input clk, reset, ADC_EOC, cs, we;
input [8:0] addr;
input [7:0] wrBus;
output ADC_CS, ADC_CSTART, ADC_SCLK;
output [7:0] rdBus;
inout ADC_SDIN, ADC_SDOUT;
wire [7:0] rdBus2;
reg [7:0] wrBus2;
reg [8:0] addr2;
wire we1;
reg we2=0, nSample=0;
reg [7:0] auto_count=0;
reg [4:0] w_st2=0;
reg [3:0] SPI_in_data=0;
reg [9:0] SPI_out_data;
reg SPI_rd = 0;
reg SPI_wr = 0;
reg [7:0] buffer_rd1;
reg [3:0] ADC_cmd;
assign we1 = we & cs;
assign ADC_CSTART = 1'b1;
// Dual-port RAM instatiation
RAMB16_S9_S9 ba0(
.DOA(rdBus), // Port A 8-bit Data Output
.DOB(rdBus2), // Port B 8-bit Data Output
.DOPA(), // Port A 1-bit Parity Output
.DOPB(), // Port B 1-bit Parity Output
.ADDRA(addr[8:0]), // Port A 11-bit Address Input
.ADDRB(addr2[8:0]), // Port B 11-bit Address Input
.CLKA(~clk), // Port A Clock
.CLKB(~clk), // Port B Clock
.DIA(wrBus), // Port A 8-bit Data Input
.DIB(wrBus2), // Port B 8-bit Data Input
.DIPA(1'b0), // Port A 1-bit parity Input
.DIPB(1'b0), // Port-B 1-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.ENB(1'b1), // Port B RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEA(we1), // Port A Write Enable Input
.WEB(we2) ); // Port B Write Enable Input
// SPI comunication module instantiation
reg ADC_SCLK_buffer = 0;
reg ADC_SDIN_buffer = 0;
reg busy = 0;
reg [3:0] in_buffer=0;
reg [9:0] out_buffer;
reg [7:0] clkcount = 0;
reg [7:0] clkdiv = 255;
reg [4:0] count = 0;
assign ADC_CS = ~busy;
always@(SPI_rd or out_buffer or busy or clkdiv)
begin
SPI_out_data = 10'bx;
if(SPI_rd)
begin SPI_out_data = out_buffer; end
end
always@(negedge clk)
begin
if(!busy)
begin
if(SPI_wr)
begin in_buffer = SPI_in_data; busy = 1; end
end
else
begin
clkcount = clkcount + 1;
if(clkcount >= clkdiv)
begin
clkcount = 0;
// Send the ADC CMD on first 4 rising edge of SCLK
if((count % 2) == 0)
begin
ADC_SDIN_buffer = in_buffer[3];
in_buffer = in_buffer << 1;
end
// We generate 10 cicles of SCLK
if(count > 0 && count < 21)
begin
ADC_SCLK_buffer = ~ADC_SCLK_buffer;
end
count = count + 1;
if(count > 21)
begin
count = 0;
busy = 0;
end
end
end
end
always@(posedge ADC_SCLK_buffer)
begin
out_buffer = out_buffer << 1;
out_buffer[0] = ADC_SDOUT;
end
assign ADC_SCLK = ADC_SCLK_buffer;
assign ADC_SDIN = ADC_SDIN_buffer;
// State Machine for control ADC comunication
always @(posedge clk)
if(reset)
{we2, SPI_wr, SPI_rd, w_st2, auto_count, SPI_in_data} <= 0;
else begin
case (w_st2)
0: begin addr2 <= 0; w_st2 <= 1; end
1: begin
ADC_cmd <= rdBus2[3:0];
if (rdBus2[7:4] == 5)
// Send command without read samples
begin addr2<= 2; w_st2 <= 2; nSample <= 1; end
else if (rdBus2[7:4] == 6)
// Read: Stop when buffer full
begin addr2<= 2; w_st2 <= 2; nSample <= 0; end
else if (rdBus2[7:4] == 9)
// Set clkdiv on SPI controller
begin addr2<= 1; w_st2 <= 10; end
else
begin w_st2 <= 0; end
end
2: begin
if (rdBus2[7:0] == 0)
begin auto_count<=0; w_st2 <= 0; end
else begin
//Send data to ADC
buffer_rd1<=rdBus2;
auto_count<=auto_count+1;
SPI_in_data <= ADC_cmd[3:0];
SPI_wr <= 1; w_st2 <= 3;
end
end
3: begin
SPI_wr <= 0;
//Wait for complete convertion
if(!ADC_EOC || ADC_CS) begin
buffer_rd1<=buffer_rd1-1;
SPI_rd <=1;
if(nSample)
w_st2<= 8;
else
w_st2<= 4;
end
end
4: begin
//Write data on BRAM (LOW)
wrBus2 <= SPI_out_data[7:0];
addr2 <= 2+2*auto_count;
we2 <= 1; w_st2 <= 5;
end
5: begin we2 <= 0; w_st2 <= 6; end
6: begin
//Write data on BRAM (HI)
wrBus2 <= SPI_out_data[9:8];
addr2 <= 3+2*auto_count;
we2 <= 1; w_st2 <= 7;
end
7: begin we2 <= 0; w_st2 <= 8; end
8: begin
SPI_rd <=0;
//Update Buffer Size value
wrBus2 <= buffer_rd1;
addr2 <= 2;
we2 <= 1; w_st2 <= 9;
end
9: begin we2 <= 0; w_st2 <= 0; end
//Sent clock divider for speed on SPI comunication
10: begin clkdiv = rdBus2; w_st2 <= 0; end
endcase
end
endmodule