Главный вопрос правильно ли выполнена загрузка данных в последовательный порт. Замечания и предложения приветствуются
Код
#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
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