Skip to content

Instantly share code, notes, and snippets.

@tzechienchu
Created September 30, 2022 07:28
Show Gist options
  • Save tzechienchu/6eb5ebb8e237d7888ef13970bd675843 to your computer and use it in GitHub Desktop.
Save tzechienchu/6eb5ebb8e237d7888ef13970bd675843 to your computer and use it in GitHub Desktop.
Analog Device DAC Driver use Verilog
//Analog Device DAC Driver
module ad_dac(
clk,
rst,
send,
valid,
tx_value,
channel,
command,
rx_value,
rx_valid,
sclk,
sync,
to_sdi,
from_sdo
);
input wire clk;
input wire rst;
input wire valid;
input wire send;
input wire[15:0] tx_value;
output wire[23:0] rx_value;
input wire[3:0] channel;
input wire[3:0] command;
output wire sclk;
output wire sync;
output wire to_sdi;
input wire from_sdo;
output wire rx_valid;
localparam IDLE = 3'b000,
WAIT_START_0 = 3'b001,
WAIT_START_1 = 3'b011,
TRANSFER = 3'b111,
WAIT_END_0 = 3'b110,
WAIT_END_1 = 3'b100;
reg[2:0] state_reg, state_next;
reg[1:0] sck_counter, sck_counter_next;
reg[4:0] bit_counter, bit_counter_next;
reg[23:0] temp_reg, temp_next;
reg[23:0] channel_data, channel_data_next;
reg[23:0] rx_value_reg, rx_value_next;
reg to_sdi_q, to_sdi_d;
reg valid_q, valid_d;
wire busy;
assign to_sdi = to_sdi_q;
assign sclk = (sck_counter[1]) & (state_reg == TRANSFER);
assign rx_valid = valid_q;
assign busy = (state_reg != IDLE);
assign sync = !busy;
assign rx_value = rx_value_reg;
always @(valid) begin
temp_next = temp_reg;
if (valid) begin
temp_next <= {command[3:0], channel[3:0], tx_value[15:0]};
end
end
always @(*) begin
state_next = state_reg;
case(state_reg)
IDLE: begin
if (send == 1'b1) begin
state_next = WAIT_START_0;
end
end
WAIT_START_0: begin
state_next = WAIT_START_1;
end
WAIT_START_1: begin
state_next = TRANSFER;
end
TRANSFER: begin
if (sck_counter == {2'b11}) begin
if (bit_counter == 5'b1_0111) begin
state_next = WAIT_END_0;
end
end
end
WAIT_END_0: begin
state_next = WAIT_END_1;
end
WAIT_END_1: begin
state_next = IDLE;
end
endcase
end
always @(posedge clk) begin
if (rst) begin
state_next <= 0;
end else begin
state_reg <= state_next;
end
end
always @(*) begin
valid_d = valid_q;
sck_counter_next = sck_counter;
bit_counter_next = bit_counter;
channel_data_next = channel_data;
rx_value_next = rx_value_reg;
case(state_reg)
IDLE: begin
valid_d = 1'b0;
sck_counter_next = 4'b0;
bit_counter_next = 5'b0;
if (send == 1'b1) begin
channel_data_next = temp_reg;
end
end
TRANSFER: begin
sck_counter_next = sck_counter + 1'b1;
if (sck_counter == 2'b00) begin
to_sdi_d = channel_data[23];
end else if (sck_counter == 2'b01) begin
channel_data_next = {channel_data[22:0], from_sdo};
end else if (sck_counter == 2'b11) begin
bit_counter_next = bit_counter + 1'b1;
if (bit_counter == 5'b1_0111) begin
rx_value_next = channel_data;
valid_d = 1'b1;
end
end
end
WAIT_END_1: begin
valid_d = 1'b0;
end
endcase
end
always @(posedge clk) begin
if (rst) begin
temp_next <= 0;
sck_counter_next <= 0;
bit_counter_next <= 0;
rx_value_next <= 0;
channel_data_next <= 0;
to_sdi_d <= 0;
valid_d <= 0;
end else begin
temp_reg <= temp_next;
sck_counter <= sck_counter_next;
bit_counter <= bit_counter_next;
rx_value_reg <= rx_value_next;
channel_data <= channel_data_next;
to_sdi_q <= to_sdi_d;
valid_q <= valid_d;
end
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment