Иноформационно-образовательный портал для FPGA разработчиков
Главное меню
  • Страница 1 из 1
  • 1
Модератор форума: drakonof  
SPI протокол для ЦАП AD5541A
Aleksey
Рядовой
Группа: Проверенные
Сообщений: 2
Репутация: 0
Статус: Offline
 
Главный вопрос правильно ли выполнена загрузка данных в последовательный порт. Замечания и предложения приветствуются


Код
#SV
module dac_ad5541a

(
input               clk,
input               rst_n,
input     [15:0]    data,
output              cs,
output  reg         sck,
output              mosi,
output reg          ldac

);
localparam  S_IDLE       = 0,
S_PREFIX     = 1,
S_DATA       = 2,
S_POSTFIX    = 3;

localparam  IDLE_SIZE    = 3, // = 40 нс, так как счетчик начинает считать с 0
PREFIX_SIZE  = 0, // = 10 нс, так как счетчик начинает считать с 0
DATA_SIZE    = 31, // = 320 нс, так как счетчик начинает считать с 0
POSTFIX_SIZE = 0; // = 10 нс, так как счетчик начинает считать с 0

// делитель частоты sck
wire sck_edge;
sck_clk scd
(
.clk(clk),
.rst_n(rst_n),
.sck_edge(sck_edge)
);

// счетчик времени
wire [23:0] cnt;
reg  [23:0] cntNext;
register #(.SIZE(24)) r_cnt(clk, rst_n, cntNext, cnt);

// регистры состояний
wire [1:0] State;
reg  [1:0] Next;
register #(.SIZE(2)) r_state(clk, rst_n, Next, State);

// Определение следующего состояния
always @(*) begin
Next = State;
case(State)
S_IDLE    : if(cnt == IDLE_SIZE)    Next = S_PREFIX;
S_PREFIX  : if(cnt == PREFIX_SIZE)  Next = S_DATA;
S_DATA    : if(cnt == DATA_SIZE)    Next = S_POSTFIX;
S_POSTFIX : if(cnt == POSTFIX_SIZE) Next = S_IDLE;
endcase
end

always @(*) begin
cntNext = cnt + 1;
case(State)
S_IDLE    : if (cnt == IDLE_SIZE)    cntNext = 0;
S_PREFIX  : if (cnt == PREFIX_SIZE)  cntNext = 0;
S_DATA    : if (cnt == DATA_SIZE)    cntNext = 0;
S_POSTFIX : if (cnt == POSTFIX_SIZE) cntNext = 0;
endcase
end

// формирвоания cs
wire csNext = (Next == S_IDLE);
register #(.SIZE(1)) r_cs(clk, rst_n, csNext, cs);

// формирвоания sck
always @(*)
if (State == S_DATA)
sck <= sck_edge;
else
sck <= 1'b0;

// формирвоания ldac
always @(*)
if (State == S_IDLE) begin
if ( cnt == 1)
ldac <= 1'b0;
else if ( cnt == 2)
ldac <= 1'b0;
else
ldac <= 1'b1;
end
else
ldac <= 1'b1;

// отправка данных
wire [15:0] buffer;
register #(.SIZE(16)) r_buf (clk, rst_n, data, buffer);

reg [15:0] shift;

assign mosi = shift [15];

always @(*)
if (State == S_IDLE)
shift <= buffer;
else
shift <= shift;

always @ (posedge sck or negedge rst_n)
if(~rst_n)
shift <= 16'd0;
else
shift <= shift << 1;

endmodule

module register
#(
parameter SIZE = 32
)
(
input                       clk,
input                       rst,
input      [ SIZE - 1 : 0 ] d,
output reg [ SIZE - 1 : 0 ] q
);
always @ (posedge clk or negedge rst)
if(~rst)
q <= { SIZE { 1'b0}};
else
q <= d;
endmodule
Сообщение отредактировал Aleksey - Среда, 09.02.2022, 16:58
Amurak
Рядовой
Группа: Проверенные
Сообщений: 1
Репутация: 0
Статус: Offline
 
Не, ну так анализировать код, чтобы сказать правильно он работает или нет, это сложно. Хоть бы времянки из симулятора выложил.
Aleksey
Рядовой
Группа: Проверенные
Сообщений: 2
Репутация: 0
Статус: Offline
 
Должно быть информативно
Прикрепления: 0903184.png (55.1 Kb)
  • Страница 1 из 1
  • 1
Поиск:
ePN