166 lines
2.8 KiB
Verilog
166 lines
2.8 KiB
Verilog
`timescale 10ns/10ns
|
|
|
|
module top();
|
|
|
|
reg clk = 0;
|
|
reg rstn = 1;
|
|
reg adc_so = 1;
|
|
wire adc_si;
|
|
wire adc_sck;
|
|
wire adc_ss;
|
|
|
|
reg sck_old = 1;
|
|
reg ss_old = 1;
|
|
|
|
wire [1:0] channel;
|
|
wire [11:0] adc_val;
|
|
wire vld;
|
|
|
|
reg ack = 0;
|
|
|
|
adc_driver dut(
|
|
.clk(clk),
|
|
.rstn(rstn),
|
|
.so(adc_so),
|
|
.si(adc_si),
|
|
.ss(adc_ss),
|
|
.sck(adc_sck),
|
|
|
|
.channel(channel),
|
|
.val(adc_val),
|
|
.vld(vld),
|
|
.ack(ack)
|
|
);
|
|
|
|
reg configured;
|
|
|
|
reg [15:0] out;
|
|
|
|
initial begin
|
|
clk = 0;
|
|
rstn = 1;
|
|
adc_so = 1;
|
|
sck_old = 1;
|
|
|
|
configured = 0;
|
|
out = 0;
|
|
|
|
$dumpfile("adc_driver_tb.vcd");
|
|
$dumpvars;
|
|
end
|
|
|
|
always
|
|
#2 clk = !clk;
|
|
|
|
reg enabled;
|
|
integer bit_pos;
|
|
integer channel_num;
|
|
integer tosend;
|
|
integer configdata;
|
|
integer adc_pos;
|
|
|
|
integer adc_out[3:0];
|
|
integer expected[3:0];
|
|
|
|
integer i;
|
|
initial begin
|
|
bit_pos = 0;
|
|
channel_num = 0;
|
|
tosend = 0;
|
|
enabled = 0;
|
|
configdata = 0;
|
|
adc_pos = 0;
|
|
adc_so = 1;
|
|
|
|
for (i = 0; i < 4; i++) begin
|
|
#1 adc_pos = i;
|
|
#1 expected[i] = out;
|
|
end
|
|
adc_pos = 0;
|
|
for (i = 0; i < 4; i++)
|
|
adc_out[i] = 0;
|
|
end
|
|
|
|
always @* begin
|
|
case (adc_pos[1:0])
|
|
2'b00: out = 16'h01ff;
|
|
2'b01: out = 16'h1fff;
|
|
2'b10: out = 16'h2dea;
|
|
2'b11: out = 16'h3caf;
|
|
endcase
|
|
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (~adc_ss & ss_old) begin
|
|
enabled <= 1;
|
|
//bit_pos <= 0;
|
|
end
|
|
if (enabled) begin
|
|
if (!configured) begin
|
|
// load into configdata if it hasn't
|
|
// been configured yet
|
|
if (~sck_old & adc_sck) begin
|
|
configdata <= (configdata << 1) | adc_si;
|
|
if (bit_pos >= 15) begin
|
|
configured <= 1;
|
|
bit_pos <= 0;
|
|
end else
|
|
bit_pos <= bit_pos + 1;
|
|
end
|
|
end else begin
|
|
if (~sck_old & adc_sck) begin
|
|
// TODO make sure the input is zero
|
|
end
|
|
if (sck_old & ~adc_sck) begin
|
|
// otherwise start loading in adc data
|
|
if (bit_pos >= 15) begin
|
|
bit_pos <= 0;
|
|
end else
|
|
bit_pos <= bit_pos + 1;
|
|
|
|
adc_so <= out[15-bit_pos];
|
|
end
|
|
end
|
|
end
|
|
|
|
if (vld & configured & ~ack) begin
|
|
adc_pos <= adc_pos + 1;
|
|
adc_out[channel] = adc_val;
|
|
ack <= 1;
|
|
if (channel == 3) begin
|
|
// TODO check configdata
|
|
i = {
|
|
1'b0, // ADC Mode Control
|
|
4'b0100, // Standard_Ext
|
|
4'b0011, // Up to AIN3
|
|
2'b01, // reset FIFO
|
|
2'b00, // normal PM mode
|
|
1'b1, // include channel number in output
|
|
1'b0, // SWCNV enable, not used in external clock mode
|
|
1'b0 // reserved
|
|
};
|
|
|
|
if (configdata != i)
|
|
$display("config %d != %d", configdata, i);
|
|
for (i = 0; i < 4; i++) begin
|
|
if (adc_out[i] != (12'hfff & expected[i]) )
|
|
$display("adc %x %x != %x", i, adc_out[i], expected[i]);
|
|
end
|
|
$finish;
|
|
end
|
|
end else
|
|
ack <= 0;
|
|
|
|
ss_old <= adc_ss;
|
|
sck_old <= adc_sck;
|
|
end
|
|
|
|
initial begin
|
|
#50000
|
|
$finish;
|
|
end
|
|
|
|
|
|
endmodule
|