2010년 4월 7일 수요일

ADC2USB Verilog HDL

External - CPLD : Reset, Clk, Trigger, LED
CY7C68013 - CPLD : nSLWR, FD
AD7829 - CPLD : nCONVST, nEOC, A, nRD, DB

// 20Mhz OSC
// 19.53126 khz sampling
// sampling count 10bits

module adc2usb(Reset, Clk, Trigger, LED,
nCONVST, nEOC, A, /*nCS,*/ nRD, DB,
/*Ifclk,*/ /*nFlagB,*/ /*nPKTEND,*/ nSLWR, FD,);

input wire Reset;
input wire Clk;
input [7:0] Trigger;
output wire [4:0] LED;

/* interface to ADC (AD7829) */
output reg nCONVST;
input wire nEOC;
output wire [2:0] A;
//output reg [2:0] A;
//output reg nCS;
output reg nRD;
input [7:0] DB;

/* interface to USB FIFO (CY7C68013A) */
//output Ifclk;
//input wire nFlagB;
//output reg nPKTEND;
output reg nSLWR;
output reg [7:0] FD;

// FSM for adc
parameter STATE_BITS = 7;
parameter IDLE = 7'b0000001;
parameter SAVE_TRIGGER = 7'b0000010;
parameter TX_TRIGGER = 7'b0000100;
parameter START_ADC = 7'b0001000;
parameter WAIT_EOC = 7'b0010000;
parameter RD_ADC_MUX_ADDR = 7'b0100000;
parameter TX_ADC = 7'b1000000;

function [STATE_BITS-1:0] adc2usb_fsm;
input [STATE_BITS-1:0] state;
input count_zero;
input channel_zero;
input sample_zero;
input start;
input endofconv;
case (state)
IDLE:
if (count_zero) begin
if (channel_zero) begin
if (sample_zero) begin
if (start) begin
adc2usb_fsm = SAVE_TRIGGER;
end else begin
adc2usb_fsm = IDLE;
end
end else begin
adc2usb_fsm = TX_TRIGGER;
end
end else begin
adc2usb_fsm = START_ADC;
end
end else begin
adc2usb_fsm = IDLE;
end
SAVE_TRIGGER:
adc2usb_fsm = TX_TRIGGER;
TX_TRIGGER:
adc2usb_fsm = START_ADC;
START_ADC:
adc2usb_fsm = WAIT_EOC;
WAIT_EOC:
if (endofconv) adc2usb_fsm = WAIT_EOC;
else adc2usb_fsm = RD_ADC_MUX_ADDR;
RD_ADC_MUX_ADDR:
adc2usb_fsm = TX_ADC;
TX_ADC:
adc2usb_fsm = IDLE;
default:
adc2usb_fsm = IDLE;
endcase
endfunction

wire adc_start;
assign adc_start = |(Trigger);
assign LED[0] = |(Trigger);

reg [19:0] adc_count;

wire [9:0] sample_count;
assign sample_count = adc_count[19:10];

wire [2:0] channel_count;
assign channel_count = adc_count[9:7];

wire adc_started;
assign adc_started = |(adc_count);
assign LED[1] = |(adc_count);

wire sample_is_zero;
assign sample_is_zero = ~|(adc_count[19:10]);
assign LED[2] = ~|(adc_count[19:10]);

wire channel_is_zero;
assign channel_is_zero = ~|(adc_count[9:7]);
assign LED[3] = ~|(adc_count[9:7]);

wire other_is_zero;
assign other_is_zero = ~|(adc_count[6:0]);
assign LED[4] = ~|(adc_count[6:0]);

always @(posedge Clk) begin
// if (Reset) begin
// adc_count <= 0;
// end else begin
if (adc_started|adc_start) adc_count <= adc_count+1;
else adc_count <= 0;
// end
end

reg [STATE_BITS-1:0] state;
wire [STATE_BITS-1:0] next_state;

assign next_state = adc2usb_fsm(state, other_is_zero, channel_is_zero, sample_is_zero, adc_start, nEOC/* 1'b0 */);

always @(posedge Clk) begin
// if (Reset) begin
// state <= IDLE;
// end else begin
state <= next_state;
// end
end

assign A = channel_count+1;
//assign A = {~|(state^TX_ADC), ~|(state^WAIT_EOC), ~|(state^START_ADC)}; //adc_count[2:0];

always @(posedge Clk) begin
// if (Reset) begin
// nCONVST <= 1'b1;
// end else begin
if (~|(state^START_ADC)) nCONVST <= 1'b0;
else nCONVST <= 1'b1;
// end
end

always @(posedge Clk) begin
// if (Reset) begin
// nRD <= 1'b1;
// end else begin
if (~|(state^RD_ADC_MUX_ADDR)) nRD <= 1'b0;
else nRD <= 1'b1;
// end
end

reg [7:0] saved_trigger;
always @(posedge Clk) begin
if (~|(state^SAVE_TRIGGER)) saved_trigger = Trigger;
end

always @(posedge Clk) begin
if (~|(state^TX_TRIGGER)) FD <= saved_trigger;
else if (~|(state^TX_ADC)) FD <= DB;
end

always @(posedge Clk) begin
// if (Reset) begin
// nSLWR <= 1'b1;
// end else begin
if (~|(state^TX_TRIGGER)) nSLWR <= 1'b0;
else if ((~|(state^TX_ADC))&(saved_trigger[channel_count])) nSLWR <= 1'b0;
else nSLWR <= 1'b1;
// end
end

endmodule

댓글 없음:

댓글 쓰기