N
Nicholas Kinar
Guest
Hello--
I've designed a custom circuit board with a Cyclone II FPGA, and I am
now writing Verilog code to send a control word to a 16-bit DAC. The
DAC is a Texas Instruments/Burr-Brown part (DAC8580, datasheet available
at http://www.ti.com/lit/gpn/dac8580) which communicates via an
SPI-style interface with the chip-select line (FSYNC) active high. A
control word is latched into the DAC on the rising edge of the SPI bus
clock.
The system clock for the FPGA is 30MHz, and the maximum frequency of the
SPI clock for the DAC is also 30MHz.
I am using the i2cslave core from OpenCores.org to set up I2C
communications between a 32-bit DSP running Linux and the Cyclone II
FPGA. The i2cslave core (which is written in Verilog) works quite well.
I have written a Linux kernel module to read and write I2C registers
provided by the i2cslave core.
The FPGA serves as the I2C slave. I have defined three I2C registers,
each 8 bits in length.
(1) msb_data (Contains the MSB of the 16-bit control word)
(2) lsb_data (Contains the LSB of the 16-bit control word)
(3) load_word (Writing to this register will send the 16-bit control
word to the DAC)
The idea is for the user to use the I2C bus to load the msb_data
register and the lsb_data register with the MSB and LSB of the control
word. The user then writes a value to the load_word register. When a
value is written to the load_word register, the contents of the msb_data
and lsb_data registers are sent to the DAC. After the 16-bit control
word is sent to the DAC, the load_word register is reset to zero.
I've written Verilog code to send a control word to the DAC, but it
appears that the data is not latched into the device when I use I2C to
write a value to the load_word register. An LED is attached to one of
the port pins of the FPGA.
I have compiled the Verilog code with Quartus II Web Edition 9.1 Linux
Beta. (The Linux beta currently works quite well, but can crash when
some dialog boxes are open.)
What is happening with my code? What would I have to do to shift out a
control word to the DAC when the user writes a value to the load_word
register?
Here is the module that I have written to attempt to communicate with
the DAC:
module dac( clk,
load_word,
msb_data,
lsb_data,
sdin_dac,
sclk_dac,
fsync_dac,
led);
input clk;
inout load_word;
input [7:0] msb_data;
input [7:0] lsb_data;
output sdin_dac;
output sclk_dac;
output fsync_dac;
output led;
reg [15:0] data;
reg count;
// Clock to DAC is continuous
assign sclk_dac = clk;
// Data is the concatenation of two registers
assign data = {msb_data, lsb_data};
// The data is latched in on the rising edge of the clock
// so the setup needs to be done on the falling edge?
always @(negedge clk) begin
if(load_word == 1'b1) begin
led <= 1'b1; // why is the led on when load_word is low?
if(count == 1'b0) begin
fsync_dac <= 1'b1; // CS is set high
end
if(count < 16) begin
// clock the data out MSB first
sdin_dac = data[15 - count];
count = (count + 1'b1);
end
if(count == 16) begin
count <= 0;
fsync_dac <= 0; // lower CS
load_word <= 0; // reset load_word
end
end // load_word block
end // clk always
endmodule
I've designed a custom circuit board with a Cyclone II FPGA, and I am
now writing Verilog code to send a control word to a 16-bit DAC. The
DAC is a Texas Instruments/Burr-Brown part (DAC8580, datasheet available
at http://www.ti.com/lit/gpn/dac8580) which communicates via an
SPI-style interface with the chip-select line (FSYNC) active high. A
control word is latched into the DAC on the rising edge of the SPI bus
clock.
The system clock for the FPGA is 30MHz, and the maximum frequency of the
SPI clock for the DAC is also 30MHz.
I am using the i2cslave core from OpenCores.org to set up I2C
communications between a 32-bit DSP running Linux and the Cyclone II
FPGA. The i2cslave core (which is written in Verilog) works quite well.
I have written a Linux kernel module to read and write I2C registers
provided by the i2cslave core.
The FPGA serves as the I2C slave. I have defined three I2C registers,
each 8 bits in length.
(1) msb_data (Contains the MSB of the 16-bit control word)
(2) lsb_data (Contains the LSB of the 16-bit control word)
(3) load_word (Writing to this register will send the 16-bit control
word to the DAC)
The idea is for the user to use the I2C bus to load the msb_data
register and the lsb_data register with the MSB and LSB of the control
word. The user then writes a value to the load_word register. When a
value is written to the load_word register, the contents of the msb_data
and lsb_data registers are sent to the DAC. After the 16-bit control
word is sent to the DAC, the load_word register is reset to zero.
I've written Verilog code to send a control word to the DAC, but it
appears that the data is not latched into the device when I use I2C to
write a value to the load_word register. An LED is attached to one of
the port pins of the FPGA.
I have compiled the Verilog code with Quartus II Web Edition 9.1 Linux
Beta. (The Linux beta currently works quite well, but can crash when
some dialog boxes are open.)
What is happening with my code? What would I have to do to shift out a
control word to the DAC when the user writes a value to the load_word
register?
Here is the module that I have written to attempt to communicate with
the DAC:
module dac( clk,
load_word,
msb_data,
lsb_data,
sdin_dac,
sclk_dac,
fsync_dac,
led);
input clk;
inout load_word;
input [7:0] msb_data;
input [7:0] lsb_data;
output sdin_dac;
output sclk_dac;
output fsync_dac;
output led;
reg [15:0] data;
reg count;
// Clock to DAC is continuous
assign sclk_dac = clk;
// Data is the concatenation of two registers
assign data = {msb_data, lsb_data};
// The data is latched in on the rising edge of the clock
// so the setup needs to be done on the falling edge?
always @(negedge clk) begin
if(load_word == 1'b1) begin
led <= 1'b1; // why is the led on when load_word is low?
if(count == 1'b0) begin
fsync_dac <= 1'b1; // CS is set high
end
if(count < 16) begin
// clock the data out MSB first
sdin_dac = data[15 - count];
count = (count + 1'b1);
end
if(count == 16) begin
count <= 0;
fsync_dac <= 0; // lower CS
load_word <= 0; // reset load_word
end
end // load_word block
end // clk always
endmodule