Tengo una pregunta sobre algo que no entiendo que está ocurriendo en mi proyecto FPGA. Necesito controlar dos dispositivos (AGC y ADC) a través de un bus SPI. Como el dispositivo maestro será el FPGA, estoy generando una señal de reloj, SCK , en código dividiendo el reloj del sistema. Luego dirijo esa señal a un cable de salida a través de un búfer de estado. A continuación se muestra mi bit de código relevante. No se muestra, pero la señal que controla el búfer de estado, en_SCK controlado por un FSM, cuando se establece bajo en estado inactivo y luego alta en el resto de los estados.
output wire SDI
//for SCK_clock
reg SCK_gen, SCK_hold;
integer i;
reg en_SCK;
wire neg_edge_SCK;
//SCK_generator
always @(posedge clk)
begin
i <= i+1;
SCK_hold <= SCK_gen;
if(i == 10)
begin
SCK_gen <= ~SCK_gen;
i <= 0;
end
end
assign SCK = (en_SCK) ? SCK_gen : 1'bz;
Cuando consigo implementar el diseño, recibo la siguiente advertencia:
ADVERTENCIA: PhysDesignRules: 372 - Reloj cerrado. La red de reloj en_SCK_not0001 se origina por un pin combinatorio. Esto no es una buena práctica de diseño. Use el pin CE para controlar la carga de datos en el flip-flop.
También me doy cuenta de que mi reloj parece muy distorsionado. Pero si no uso el dispositivo triple en mi código y asigno directamente la señal del reloj al cable de salida (como en el código a continuación) obtengo una buena señal de reloj limpia.
assign SCK = SCK_gen;
A continuación se muestra una al lado de la señal SCK sin el búfer triple (izquierda) y con el búfer triple (derecha). Soy bastante nuevo en FPGA y Verilog, pero tengo entendido que usar ese estilo de código de asignación implica un búfer de estadísticas, por lo que estoy confundido por lo que parece interpretarse como una fuente de reloj cerrada (el esquema generado por XST muestra que está implícito con una puerta y . También estoy confundido acerca de cómo está distorsionando la señal del reloj. El FSM debería forzar la señal de habilitación en_SCK alta durante muchas veces el período del reloj así que no estoy seguro de lo que está sucediendo. Además, de acuerdo con el manual de la placa de demostración, otros dispositivos comparten esta señal, así que tengo que configurarla a alta impedancia cuando no está en uso. Si alguien podría apuntarme en la dirección correcta o explicarlo para mi estaría muy bien lleno. Gracias
Aquí está el módulo completo si eso aclara las cosas. Antes solo he hecho un par de proyectos Verilog simples, así que estoy seguro de que mi código no es bueno. Pero intenté diseñarlo usando un FSM. Tal vez mi problema no sea lo que pensé. Gracias por tu paciencia.
module AGC_controller
(
input wire clk, reset, set_AGC, AMP_DO,
output wire SDI, SCK,
output reg inhibit_ADC, AMP_CS,
//spi disable signals ** all disabled for =1 except AD_CONV. When AD_CONV=0, disabled.
output wire DAC_CS, AD_CONV, SF_CEO, FPGA_INIT_B,
output reg [7:0] led
);
localparam [2:0]
idle = 3'b000,
set_up = 3'b001,
start_data = 3'b010,
wait_for_neg= 3'b011,
wait_4 = 3'b100,
next_bit = 3'b101;
// wait_last = 3'b110;
//signals
//for SCK_clock
reg SCK_gen, SCK_hold;
integer i;
reg en_SCK;
wire neg_edge_SCK;
initial
begin
SCK_gen = 0;
i=0;
end
//SCK_generator
always @(posedge clk)
begin
i <= i+1;
SCK_hold <= SCK_gen;
if(i == 10)
begin
SCK_gen <= ~SCK_gen;
i <= 0;
end
end
//detect neg edge of SCK
assign neg_edge_SCK = SCK_hold & ~SCK_gen;
//general signals
reg [2:0] state_reg, state_next;
integer bit_position;
reg [7:0] AGC_buf;
reg en_SDI;
//FSM control
always @(posedge clk, posedge reset)
begin
if (reset)
state_reg <= idle;
else
state_reg <= state_next;
end
//FSM next state logic
always @*
begin
state_next = state_reg;
case(state_reg)
idle:
begin
bit_position=7;
AGC_buf = 8'b10011001;
en_SCK = 1'b0;
en_SDI = 1'b0;
AMP_CS = 1'b1;
inhibit_ADC = 1'b0;
if(set_AGC)
begin
state_next = set_up;
end
end
set_up:
begin
AMP_CS = 1'b0;
inhibit_ADC = 1'b1;
if ((SCK_gen) && (i < 9))
state_next = start_data;
end
start_data:
begin
en_SDI = 1'b1;
if ((SCK_gen == 0) && (i==2))
begin
state_next = wait_for_neg;
en_SCK = 1'b1;
end
end
wait_for_neg:
begin
if (neg_edge_SCK)
begin
state_next = wait_4;
end
end
wait_4:
begin
if (i==4)
begin
//test code to light leds
led[bit_position] = SDI;
if (bit_position == 0)
begin
state_next = idle;
end
else
begin
state_next = next_bit;
end
end
end
next_bit:
begin
bit_position = bit_position - 1;
state_next = wait_for_neg;
end
endcase
end
assign SDI = (en_SDI) ? AGC_buf[bit_position] : 1'bz;
assign SCK = (en_SCK) ? SCK_gen : 1'bz;
//spi disable signals ** all disabled for =1 except AD_CONV. When AD_CONV=0, disabled.
assign DAC_CS = (state_reg != idle);
assign AD_CONV = (state_reg == idle);
assign SF_CEO = (state_reg != idle);
assign FPGA_INIT_B = (state_reg != idle);
endmodule