Skip to content
Snippets Groups Projects
Commit a4a0fcf6 authored by Daniel Newbrook's avatar Daniel Newbrook
Browse files

Add ADC behavioural model

parent 18d16a70
Branches
No related tags found
No related merge requests found
$(SOCLABS_NANOSOC_TECH_DIR)/nanosoc/sl_ams_tech/SL_ADC_8bits/logical/soclabs_adc.v
$(SOCLABS_NANOSOC_TECH_DIR)/nanosoc/sl_ams_tech/SL_ADC_8bits/logical/soclabs_adc_8bits.vams
\ No newline at end of file
`include "constants.vams"
`include "disciplines.vams"
`default_discipline logic
module soclabs_adc (
input wire PCLK,
input wire PCLKG,
input wire PRESETn,
input wire PSEL,
input wire [9:0] PADDR,
input wire PENABLE,
input wire PWRITE,
input wire [31:0] PWDATA,
output wire [31:0] PRDATA,
output wire PREADY,
output wire PSLVERR,
input EXTIN,
output wire ADCINT
);
reg [31:0] DATA_reg;
reg [31:0] STATUS_reg;
reg [7:0] ENABLE_reg;
reg [31:0] CLK_DIV;
reg [63:0] ID_reg = 64'h534C_0061_6463_0008;
reg [31:0] PRDATA_reg;
reg [31:0] counter;
reg PSLVERR_reg;
reg adc_clk_reg;
wire adc_clk;
wire [7:0] data;
wire READY;
reg CLR_READY_reg;
assign PRDATA = PRDATA_reg;
assign PSLVERR = PSLVERR_reg;
// Clock divider
always @(posedge PCLK or negedge PRESETn) begin
if(~PRESETn) begin
CLK_DIV <= 32'd10;
ENABLE_reg <= 8'd0;
counter <= 32'd0;
adc_clk_reg <= 1'b0;
STATUS_reg<= 32'd0;
end else begin
STATUS_reg<={31'd0, READY};
DATA_reg <= {24'd0, data};
counter <= counter + 1;
if(counter == CLK_DIV) begin
adc_clk_reg <= ~adc_clk_reg;
counter <= 32'd0;
end
end
end
assign adc_clk = adc_clk_reg & ENABLE_reg[0];
// APB interface
localparam APB_IDLE = 2'd0,
APB_WRITE = 2'd1,
APB_READ = 2'd2;
reg [1:0] apb_current_state;
reg [1:0] apb_next_state;
always @(posedge PCLK or negedge PRESETn) begin
if(~PRESETn) begin
apb_current_state <= APB_IDLE;
PSLVERR_reg <= 1'b0;
end else begin
apb_current_state <= apb_next_state;
end
end
always @(*) begin
case(apb_current_state)
APB_IDLE: begin
CLR_READY_reg = 1'b0;
PSLVERR_reg = 1'b0;
if(PSEL) begin
if(PWRITE) begin
apb_next_state = APB_WRITE;
end else begin
apb_next_state = APB_READ;
end
end
else begin
apb_next_state = APB_IDLE;
end
end
APB_WRITE: begin
case(PADDR)
10'h000: PSLVERR_reg = 1'b1;
10'h001: PSLVERR_reg = 1'b1;
10'h002: CLK_DIV = PWDATA;
10'h003: ENABLE_reg = PWDATA[7:0];
10'h3F0: PSLVERR_reg = 1'b1;
10'h3F1: PSLVERR_reg = 1'b1;
10'h3F2: PSLVERR_reg = 1'b1;
10'h3F3: PSLVERR_reg = 1'b1;
10'h3F4: PSLVERR_reg = 1'b1;
10'h3F5: PSLVERR_reg = 1'b1;
10'h3F6: PSLVERR_reg = 1'b1;
10'h3F7: PSLVERR_reg = 1'b1;
endcase
apb_next_state = APB_IDLE;
end
APB_READ: begin
case(PADDR)
10'h000: begin
PRDATA_reg = DATA_reg;
CLR_READY_reg = 1'b1;
end
10'h001: PRDATA_reg = STATUS_reg;
10'h002: PRDATA_reg = CLK_DIV;
10'h003: PRDATA_reg = {24'd0, ENABLE_reg};
10'h3F0: PRDATA_reg = {24'd0, ID_reg[63:56]};
10'h3F1: PRDATA_reg = {24'd0, ID_reg[55:48]};
10'h3F2: PRDATA_reg = {24'd0, ID_reg[47:40]};
10'h3F3: PRDATA_reg = {24'd0, ID_reg[39:32]};
10'h3F4: PRDATA_reg = {24'd0, ID_reg[31:24]};
10'h3F5: PRDATA_reg = {24'd0, ID_reg[23:16]};
10'h3F6: PRDATA_reg = {24'd0, ID_reg[15:8]};
10'h3F7: PRDATA_reg = {24'd0, ID_reg[7:0]};
default: PRDATA_reg = 32'hDEADDEAD;
endcase
apb_next_state = APB_IDLE;
end
endcase
end
assign PREADY = (apb_current_state==APB_READ|apb_current_state==APB_WRITE)? 1'b1:1'b0;
soclabs_adc_8bits u_adc_8bits(
.adc_clk(adc_clk),
.resetn(PRESETn),
.READY(READY),
.CLR_READY(CLR_READY_reg),
.DATA(data)
);
endmodule
\ No newline at end of file
`include "constants.vams"
`include "disciplines.vams"
`default_discipline logic
module soclabs_adc_8bits (
input wire adc_clk,
input wire resetn,
output wire [7:0] DATA,
output wire READY,
input wire CLR_READY,
input EXTIN,
output wire ADCINT
);
parameter integer bits = 8;// from [1:24]; // resolution (bits)
parameter real fullscale = 1.2; // input range is from 0 to fullscale (V)
parameter real td = 0.01; // delay from clock to output (ns)
electrical EXTIN;
real sample, midpoint, cmp;
integer i;
reg [bits-1:0] buffer;
reg [bits-1:0] out;
reg READY_reg;
assign READY=READY_reg;
assign DATA=out;
assign midpoint = fullscale/2.0;
real int_in;
assign int_in = 0.6*sin(2*3.14159265358979323846*100*$abstime)+0.6;
electrical n1;
parameter real gain = 0.6, freq = 1000.0;
localparam real omegac = 2.0 * 3.14159 * freq;
analog V(n1) <+ gain * sin(idt(omegac,0.0))+0.6;
assign cmp = buffer[7]*(fullscale/2.0) + buffer[6]*(fullscale/4.0) + buffer[5]*(fullscale/8.0) + buffer[4]*(fullscale/16.0)
+ buffer[3]*(fullscale/32.0) + buffer[2]*(fullscale/64.0) + buffer[1]*(fullscale/128.0) + buffer[0]*(fullscale/256.0);
always @(posedge adc_clk or negedge resetn) begin
if(~resetn) begin
i <= 7;
buffer <= 8'h80;
out <= 8'h00;
READY_reg <= 0;
end else begin
if (CLR_READY)
READY_reg<=1'b0;
if(i==0) begin
if (sample>cmp)
out <= {buffer[7:1], 1'b1};
else
out <= {buffer[7:1], 1'b0};
buffer <= 8'h80;
i <= 7;
sample = V(n1);
READY_reg <= 1'b1;
end else begin
if (sample>cmp)
buffer[i]<=1'b1;
else
buffer[i]<=1'b0;
if(i!=0)
buffer[i-1]<=1'b1;
i <= i-1;
end
end
end
always @(posedge adc_clk or posedge CLR_READY) begin
if(CLR_READY)
READY_reg <= 1'b0;
else
if(i==0)
READY_reg <= 1'b1;
end
endmodule
\ No newline at end of file
compile_vcs:
vcs -ad -ams soclabs_adc_tb.vams soclabs_adc.vams -debug_access+all -kdb > compile.log
sim_vcs:
./simv -gui
compile_mti:
vlog -vams soclabs_adc_tb.vams
\ No newline at end of file
`timescale 10ns / 10ps
`include "disciplines.vams"
`default_discipline logic
module testbench ();
electrical gnd;
ground gnd;
reg clk;
wire [0:7] out;
integer ii;
reg [0:7] plot_out;
initial clk=0;
always #1 clk=~clk;
always @(out) for (ii=0; ii<8; ii=ii+1) plot_out[ii] <= out[7-ii];
soclabs_adc adc0 (
.PCLK(clk),
.EXTIN(in),
.PRDATA(out));
vsource #(.type("sine"), .ampl(0.5), .dc(0.5), .freq(0.5M)) v0 (in, gnd);
endmodule
choose xa;
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment