我正在编写代码以与this DAC接口以制作正弦波。我有一个正弦LUT可以很好地生成值,还有一个DAC控制器。控制器将CS置为低电平,逐位输入16位整数,并在16位计数后将CS脉冲调高。当它发出脉冲时,它还向sin LUT发送一个使能脉冲,以便再计数一个数。这段代码看起来效果不好,因为我的输出量有所增加。这是因为当它应该为高电平时,时钟将CS读为低电平(图1),导致DAC以17位读取(换句话说,读取当前数字的MSB作为前一个数字的LSB),这会导致尴尬尖峰(图2)。
我怎样才能更好地组织这些代码,以便最大限度地降低遇到此时间问题的风险?
module DAC_Control(
input [15:0]data_in,
input counter_enable,
input clk,
input rst,
output data_out,
output reg cs,
output reg enable
);
//bit counter
reg [3:0] bit_counter;
//to help with shifting
reg [15:0] shifter;
//shifter
always @(posedge (clk)) begin
if (rst) begin
bit_counter <= 4'b0;
shifter <= 0;
end
else if (counter_enable == 1) begin
shifter <= data_in;
bit_counter <= 4'b0;
end
else begin
shifter <= shifter << 1; // shifting
bit_counter <= bit_counter + 1'b1; // counter
end
end
reg cs_hold;
always @(posedge (clk)) begin
if (rst) begin
enable <= 1'b0;
cs <= 1'b1;
end
else if (bit_counter == 4'b1110) begin
enable <= 1'b1;
cs <= 1'b0;
end
else if (bit_counter == 4'b1111) begin
enable <= 1'b0;
cs <= 1'b1;
end
else if (cs_hold == 1) begin
enable <= 1'b0;
cs <= 1'b1;
end
else begin
enable <= 1'b0; // generate enable signals
cs <= 1'b0;
end
end
assign data_out = shifter[15];
endmodule
图1.黄色为DIN,蓝色为CS,绿色为时钟
图2. DAC的输出
答案 0 :(得分:2)
DAC正在使用上升沿对数据进行采样:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5541A.pdf
Serial Data Input. This device accepts 16-bit words. Data is clocked into the serial input register on the rising edge of SCLK.
您可能想尝试在clk的下降沿生成data_out和cs。
答案 1 :(得分:2)
我不知道您的FPGA来自哪个供应商,但是,大多数都有时序限制,允许您定义时钟和数据之间的关系。他们使用虚拟时钟的想法。可以想象它有一个外部时钟,你可以说出时钟之间的差异。如果时钟是直接从FPGA生成的,而不是来自某些外部源,我认为你可以将一些CLKs值设置为0.
通过设置这些约束,您可以使数据输出相对于clk移动,并且它将“一致并受控”。
+----------+ +--------+
| FPGA |----Data_out--->| DAC |
+----------+ +--------+
CLKs /\ CLKd /\
| |
+-------sys_clk--------+
以下是使用SDC对输出进行计时的Altera器件的解决方案。
#specify the maximum external clock delay to the FPGA
set CLKs_max 0.200
#specify the minimum external clock delay to the FPGA
set CLKs_min 0.100
#specify the maximum external clock delay to the external device
set CLKd_max 0.200
#specify the minimum external clock delay to the external device
set CLKd_min 0.100
#specify the maximum setup time of the external device
set tSU 0.125
#specify the minimum setup time of the external device
set tH 0.100
#specify the maximum board delay
set BD_max 0.180
#specify the minimum board delay
set BD_min 0.120
#create a clock 10ns
create_clock -period 10 -name sys_clk [get_ports sys_clk]
#create the associated virtual input clock
create_clock -period 10 -name virt_sys_clk
#create the output maximum delay for the data output from the FPGA that
#accounts for all delays specified
set_output_delay -clock virt_sys_clk \
-max [expr $CLKs_max + $BD_max + $tSU - $CLKd_min] \
[get_ports {data_out[*]}]
#create the output minimum delay for the data output from the FPGA that
#accounts for all delays specified
set_output_delay -clock virt_sys_clk \
-min [expr $CLKs_min + $BD_min - $tH - $CLKd_max] \
[get_ports {data_out[*]}]
或者,如果你不能用约束来控制数据和时钟之间的关系,这甚至建议看起来很俗气(如果是真的,请告诉我供应商这样我可以留下来)你可以通过以下方式改善情况通过将你的构成改为negedge来回答前一个答案的建议。请记住,从构建到构建,这可能是灵活的,因为输出可能不会以您想要的方式受到约束。