Work on DRV8353 SPI driver
This commit is contained in:
parent
bd108603e3
commit
5f85a3b99e
|
@ -17,7 +17,7 @@ module drv8353r_driver(
|
||||||
output drv_cs_n,
|
output drv_cs_n,
|
||||||
output drv_sck,
|
output drv_sck,
|
||||||
output drv_sdi,
|
output drv_sdi,
|
||||||
output drv_sdo,
|
input drv_sdo,
|
||||||
|
|
||||||
// assert stop with the coast_nbrake
|
// assert stop with the coast_nbrake
|
||||||
// bit to disable the gate drivers
|
// bit to disable the gate drivers
|
||||||
|
@ -28,9 +28,11 @@ module drv8353r_driver(
|
||||||
output rdy,
|
output rdy,
|
||||||
output fault_a,
|
output fault_a,
|
||||||
output fault_b,
|
output fault_b,
|
||||||
output fault_c,
|
output fault_c
|
||||||
);
|
);
|
||||||
|
|
||||||
|
parameter WAIT_TIME = 98;
|
||||||
|
|
||||||
wire [15:0] driver_control;
|
wire [15:0] driver_control;
|
||||||
wire [15:0] hs_control;
|
wire [15:0] hs_control;
|
||||||
wire [15:0] ls_control;
|
wire [15:0] ls_control;
|
||||||
|
@ -49,8 +51,9 @@ assign driver_control = {
|
||||||
1'b0, // 1PWM_DIR, default
|
1'b0, // 1PWM_DIR, default
|
||||||
1'b0, // COAST, disabled
|
1'b0, // COAST, disabled
|
||||||
1'b0, // BRAKE, disabled
|
1'b0, // BRAKE, disabled
|
||||||
1'b0, // CLR_FLT, no clear
|
1'b0 // CLR_FLT, no clear
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO actually calculate HS/LS gate drive
|
// TODO actually calculate HS/LS gate drive
|
||||||
// requirements
|
// requirements
|
||||||
assign hs_control = {
|
assign hs_control = {
|
||||||
|
@ -58,7 +61,7 @@ assign hs_control = {
|
||||||
1'b1, // write
|
1'b1, // write
|
||||||
3'b000, // LOCK, don't lock or unlock
|
3'b000, // LOCK, don't lock or unlock
|
||||||
4'b0100, // IDRIVEP_HS, 300 mA
|
4'b0100, // IDRIVEP_HS, 300 mA
|
||||||
4'b0010, // IDRIVEN_HS, 200 mA
|
4'b0010 // IDRIVEN_HS, 200 mA
|
||||||
};
|
};
|
||||||
assign ls_control = {
|
assign ls_control = {
|
||||||
4'b0100, // address = 0x04
|
4'b0100, // address = 0x04
|
||||||
|
@ -66,7 +69,7 @@ assign ls_control = {
|
||||||
1'b1, // CBC, OCP conditions reset when PWM is provided
|
1'b1, // CBC, OCP conditions reset when PWM is provided
|
||||||
2'b11, // TDRIVE = 4000 ns gate-current drive time
|
2'b11, // TDRIVE = 4000 ns gate-current drive time
|
||||||
4'b0100, // IDRIVEP_LS, 300 mA
|
4'b0100, // IDRIVEP_LS, 300 mA
|
||||||
4'b0010, // IDRIVEN_LS, 200 mA
|
4'b0010 // IDRIVEN_LS, 200 mA
|
||||||
};
|
};
|
||||||
assign ocp_control = {
|
assign ocp_control = {
|
||||||
4'b0101, // address = 0x05
|
4'b0101, // address = 0x05
|
||||||
|
@ -75,7 +78,7 @@ assign ocp_control = {
|
||||||
2'b01, // DEAD_TIME, 100 ns deadtime
|
2'b01, // DEAD_TIME, 100 ns deadtime
|
||||||
2'b01, // OCP_MODE, overcurrent causes automatic retry
|
2'b01, // OCP_MODE, overcurrent causes automatic retry
|
||||||
2'b10, // OCP_DEG, 4us overcurrent deglitch
|
2'b10, // OCP_DEG, 4us overcurrent deglitch
|
||||||
4'b1101, // VDS_LVL, 1V
|
4'b1101 // VDS_LVL, 1V
|
||||||
};
|
};
|
||||||
assign csa_control = {
|
assign csa_control = {
|
||||||
4'b0110, // address = 0x06
|
4'b0110, // address = 0x06
|
||||||
|
@ -88,12 +91,11 @@ assign csa_control = {
|
||||||
1'b0, // CSA_CAL_A, normal operation
|
1'b0, // CSA_CAL_A, normal operation
|
||||||
1'b0, // CSA_CAL_B, normal operation
|
1'b0, // CSA_CAL_B, normal operation
|
||||||
1'b0, // CSA_CAL_C, normal operation
|
1'b0, // CSA_CAL_C, normal operation
|
||||||
2'b11, // SEN_LVL, OCP 1 V
|
2'b11 // SEN_LVL, OCP 1 V
|
||||||
};
|
};
|
||||||
|
|
||||||
reg [3:0] cur_bit;
|
wire [3:0] cur_bit;
|
||||||
wire [4:0] config_bits;
|
wire [7:0] config_bits;
|
||||||
wire config_bit;
|
|
||||||
|
|
||||||
assign config_bits[0] = driver_control[cur_bit];
|
assign config_bits[0] = driver_control[cur_bit];
|
||||||
assign config_bits[1] = hs_control[cur_bit];
|
assign config_bits[1] = hs_control[cur_bit];
|
||||||
|
@ -102,5 +104,141 @@ assign config_bits[3] =
|
||||||
ocp_control[cur_bit];
|
ocp_control[cur_bit];
|
||||||
assign config_bits[4] =
|
assign config_bits[4] =
|
||||||
csa_control[cur_bit];
|
csa_control[cur_bit];
|
||||||
|
assign config_bits[7:5] = 3'b000;
|
||||||
|
|
||||||
|
localparam IDLE = 0,
|
||||||
|
INIT = 1,
|
||||||
|
CONFIG = 2,
|
||||||
|
READY = 3;
|
||||||
|
reg [2:0] state = IDLE;
|
||||||
|
reg [2:0] state_next;
|
||||||
|
|
||||||
|
assign rdy = (state == READY);
|
||||||
|
|
||||||
|
reg drv_en_ff = 0;
|
||||||
|
reg drv_cs_n_ff = 1;
|
||||||
|
reg drv_sck_ff = 1;
|
||||||
|
reg drv_sdi_ff = 0;
|
||||||
|
|
||||||
|
reg drv_en_next, drv_cs_n_next;
|
||||||
|
reg drv_sck_next, drv_sdi_next;
|
||||||
|
|
||||||
|
assign drv_en = drv_en_ff;
|
||||||
|
assign drv_cs_n = drv_cs_n_ff;
|
||||||
|
assign drv_sck = drv_sck_ff;
|
||||||
|
assign drv_sdi = drv_sdi_ff;
|
||||||
|
|
||||||
|
reg [7:0] count = 0;
|
||||||
|
reg [7:0] count_next;
|
||||||
|
reg [7:0] msb_count = 0;
|
||||||
|
reg [7:0] msb_count_next;
|
||||||
|
|
||||||
|
assign cur_bit = 15 - count[6:3];
|
||||||
|
|
||||||
|
reg [2:0] cur_reg = 0;
|
||||||
|
reg [2:0] cur_reg_next;
|
||||||
|
|
||||||
|
always @* begin
|
||||||
|
state_next = state;
|
||||||
|
|
||||||
|
drv_en_next = 0;
|
||||||
|
drv_cs_n_next = 1;
|
||||||
|
drv_sck_next = 0;
|
||||||
|
drv_sdi_next = 0;
|
||||||
|
cur_reg_next = 0;
|
||||||
|
|
||||||
|
count_next = count;
|
||||||
|
msb_count_next = msb_count;
|
||||||
|
|
||||||
|
case (state)
|
||||||
|
IDLE: begin
|
||||||
|
if (en) begin
|
||||||
|
state_next = INIT;
|
||||||
|
drv_en_next = 1;
|
||||||
|
count_next = 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
INIT: begin
|
||||||
|
drv_en_next = 1;
|
||||||
|
|
||||||
|
// wait 1 ms before trying to configure
|
||||||
|
count_next = count + 1;
|
||||||
|
if (&count_next) begin
|
||||||
|
msb_count_next = msb_count;
|
||||||
|
end
|
||||||
|
if (msb_count == WAIT_TIME) begin
|
||||||
|
cur_reg_next = 0;
|
||||||
|
state_next = CONFIG;
|
||||||
|
count_next = 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
CONFIG: begin
|
||||||
|
// write all the configuration bits
|
||||||
|
// to the DRV8353
|
||||||
|
|
||||||
|
drv_en_next = 1;
|
||||||
|
drv_cs_n_next = drv_cs_n_ff;
|
||||||
|
drv_sck_next = drv_sck_ff;
|
||||||
|
drv_sdi_next = drv_sdi_ff;
|
||||||
|
cur_reg_next = cur_reg;
|
||||||
|
|
||||||
|
count_next = count + 1;
|
||||||
|
if (&count[1:0]) begin
|
||||||
|
if (count[7:2] == 0) begin
|
||||||
|
drv_cs_n_next = 0;
|
||||||
|
end
|
||||||
|
drv_sck_next = count[2];
|
||||||
|
if (count[7:2] == 33) begin
|
||||||
|
drv_cs_n_next = 1;
|
||||||
|
count_next = 0;
|
||||||
|
cur_reg_next = cur_reg + 1;
|
||||||
|
drv_sck_next = 0;
|
||||||
|
if (cur_reg == 4) begin
|
||||||
|
state_next = READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
// write the next bit on high transitions
|
||||||
|
if (count[2]) begin
|
||||||
|
drv_sdi_next = config_bits[cur_reg];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
READY: begin
|
||||||
|
drv_en_next = 1;
|
||||||
|
// TODO if there are faults read
|
||||||
|
// the status register to output
|
||||||
|
// the appropriate info
|
||||||
|
// TODO if a stop is commanded
|
||||||
|
// write to the register
|
||||||
|
// to stop the motor driver
|
||||||
|
// TODO if a stop is deasserted
|
||||||
|
// write to the register to
|
||||||
|
// reenable the motor driver
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (rst) begin
|
||||||
|
state_next = IDLE;
|
||||||
|
|
||||||
|
drv_en_next = 0;
|
||||||
|
drv_cs_n_next = 1;
|
||||||
|
drv_sck_next = 1;
|
||||||
|
drv_sdi_next = 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
state <= state_next;
|
||||||
|
|
||||||
|
drv_en_ff <= drv_en_next;
|
||||||
|
drv_cs_n_ff <= drv_cs_n_next;
|
||||||
|
drv_sck_ff <= drv_sck_next;
|
||||||
|
drv_sdi_ff <= drv_sdi_next;
|
||||||
|
|
||||||
|
count <= count_next;
|
||||||
|
msb_count <= msb_count_next;
|
||||||
|
|
||||||
|
cur_reg <= cur_reg_next;
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
tests: test_adc
|
tests: test_adc test_drv8353
|
||||||
|
|
||||||
test_adc: vcd/adc_driver_tb.vcd
|
test_adc: vcd/adc_driver_tb.vcd
|
||||||
|
|
||||||
|
@ -7,3 +7,11 @@ vcd/adc_driver_tb.vcd: bin/adc_driver_tb
|
||||||
|
|
||||||
bin/adc_driver_tb: adc_driver_tb.v ../library/adc_driver.v
|
bin/adc_driver_tb: adc_driver_tb.v ../library/adc_driver.v
|
||||||
iverilog adc_driver_tb.v ../library/adc_driver.v -o bin/adc_driver_tb
|
iverilog adc_driver_tb.v ../library/adc_driver.v -o bin/adc_driver_tb
|
||||||
|
|
||||||
|
test_drv8353: vcd/drv8353_spi_tb.vcd
|
||||||
|
|
||||||
|
vcd/drv8353_spi_tb.vcd: bin/drv8353_spi_tb
|
||||||
|
./bin/drv8353_spi_tb
|
||||||
|
|
||||||
|
bin/drv8353_spi_tb: drv8353_spi_tb.v ../library/drv8353r_driver.v
|
||||||
|
iverilog $^ -o bin/drv8353_spi_tb
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
`timescale 10ns/10ns
|
||||||
|
|
||||||
|
module drv8353_spi_tb();
|
||||||
|
|
||||||
|
reg clk = 0;
|
||||||
|
reg rst = 1;
|
||||||
|
reg en = 0;
|
||||||
|
|
||||||
|
reg drv_fault_n = 1;
|
||||||
|
wire drv_en;
|
||||||
|
|
||||||
|
wire drv_cs_n;
|
||||||
|
wire drv_sck;
|
||||||
|
wire drv_sdi;
|
||||||
|
reg drv_sdo = 0;
|
||||||
|
|
||||||
|
// assert stop with the coast_nbrake
|
||||||
|
// bit to disable the gate drivers
|
||||||
|
reg stop = 0;
|
||||||
|
reg coast_nbrake = 0;
|
||||||
|
reg clear_fault = 0;
|
||||||
|
|
||||||
|
wire rdy;
|
||||||
|
wire fault_a;
|
||||||
|
wire fault_b;
|
||||||
|
wire fault_c;
|
||||||
|
|
||||||
|
drv8353r_driver #(0) dut(
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.en(en),
|
||||||
|
|
||||||
|
.drv_fault_n(drv_fault_n),
|
||||||
|
.drv_en(drv_en),
|
||||||
|
|
||||||
|
.drv_cs_n(drv_cs_n),
|
||||||
|
.drv_sck(drv_sck),
|
||||||
|
.drv_sdi(drv_sdi),
|
||||||
|
.drv_sdo(drv_sdo),
|
||||||
|
|
||||||
|
.stop(stop),
|
||||||
|
.coast_nbrake(coast_nbrake),
|
||||||
|
.clear_fault(clear_fault),
|
||||||
|
|
||||||
|
.rdy(rdy),
|
||||||
|
.fault_a(fault_a),
|
||||||
|
.fault_b(fault_b),
|
||||||
|
.fault_c(fault_c)
|
||||||
|
);
|
||||||
|
|
||||||
|
integer cfg_num = -1;
|
||||||
|
integer cfg[5:0];
|
||||||
|
integer i = 0;
|
||||||
|
integer bit_count = 0;
|
||||||
|
reg spi_active = 0;
|
||||||
|
|
||||||
|
wire [15:0] cfg0;
|
||||||
|
wire [15:0] cfg1;
|
||||||
|
wire [15:0] cfg2;
|
||||||
|
wire [15:0] cfg3;
|
||||||
|
wire [15:0] cfg4;
|
||||||
|
|
||||||
|
assign cfg0 = cfg[0];
|
||||||
|
assign cfg1 = cfg[1];
|
||||||
|
assign cfg2 = cfg[2];
|
||||||
|
assign cfg3 = cfg[3];
|
||||||
|
assign cfg4 = cfg[4];
|
||||||
|
|
||||||
|
always @(negedge drv_cs_n) begin
|
||||||
|
spi_active <= 1;
|
||||||
|
cfg_num <= cfg_num + 1;
|
||||||
|
if (drv_sck) begin
|
||||||
|
$display("sck not low on falling edge, clock %d", i);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge drv_cs_n) begin
|
||||||
|
spi_active <= 0;
|
||||||
|
bit_count <= 0;
|
||||||
|
if (drv_sck) begin
|
||||||
|
$display("sck not low on rising edge, clock %d", i);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(negedge drv_sck) begin
|
||||||
|
if (spi_active) begin
|
||||||
|
cfg[cfg_num] <= cfg[cfg_num] << 1 | drv_sdi;
|
||||||
|
bit_count <= bit_count + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
integer j = 0;
|
||||||
|
integer expected = 0;
|
||||||
|
always @*
|
||||||
|
case (j)
|
||||||
|
0: expected = 16'b0010100000100000;
|
||||||
|
1: expected = 16'b0011100001000010;
|
||||||
|
2: expected = 16'b0100111101000010;
|
||||||
|
3: expected = 16'b0101100101101101;
|
||||||
|
4: expected = 16'b0110100010000011;
|
||||||
|
endcase
|
||||||
|
|
||||||
|
|
||||||
|
always @(rdy) begin
|
||||||
|
if (rdy) begin
|
||||||
|
for (j = 0; j < 5; j += 1)
|
||||||
|
#1
|
||||||
|
if (cfg[j] != expected)
|
||||||
|
$display("cfg %d bad, %x != %x", j, cfg[j], expected);
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("vcd/drv8353_spi_tb.vcd");
|
||||||
|
$dumpvars;
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i += 1) cfg[i] = 0;
|
||||||
|
// TODO cycle the module long enough to get all the configuration bits
|
||||||
|
// written out, and check to see if it worked correctly
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
#2 clk = 0;
|
||||||
|
#2 clk = 1;
|
||||||
|
|
||||||
|
i = i + 1;
|
||||||
|
rst = 0;
|
||||||
|
en = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < 3000; i+= 1) begin
|
||||||
|
#2 clk = 0;
|
||||||
|
#2 clk = 1;
|
||||||
|
i = i + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
Loading…
Reference in New Issue