254 lines
5.7 KiB
Verilog
254 lines
5.7 KiB
Verilog
// this module configures the DRV8353,
|
|
// leaving the PWM for a different module
|
|
// if the fault pin is triggered
|
|
// it will read the fault status registers
|
|
// and assert the appropriate output wire
|
|
// it also allows disabling/enabling
|
|
// the MOSFETs using the coast/brake pins
|
|
// in the driver control register
|
|
module drv8353r_driver(
|
|
input clk,
|
|
input rst,
|
|
input en,
|
|
|
|
input drv_fault_n,
|
|
output drv_en,
|
|
|
|
output drv_cs_n,
|
|
output drv_sck,
|
|
output drv_sdi,
|
|
input drv_sdo,
|
|
|
|
// assert stop with the coast_nbrake
|
|
// bit to disable the gate drivers
|
|
input stop,
|
|
input coast_nbrake,
|
|
input clear_fault,
|
|
|
|
output rdy,
|
|
output fault_a,
|
|
output fault_b,
|
|
output fault_c
|
|
);
|
|
|
|
parameter WAIT_TIME = 98;
|
|
|
|
wire [15:0] driver_control;
|
|
wire [15:0] hs_control;
|
|
wire [15:0] ls_control;
|
|
wire [15:0] ocp_control;
|
|
wire [15:0] csa_control;
|
|
|
|
assign driver_control = {
|
|
4'b0010, // address = 0x02
|
|
1'b1, // write
|
|
1'b0, // OCP_ACT, shutdown affected half bridge on fault
|
|
1'b0, // DIS_GDUV, undervoltage enabled
|
|
1'b0, // DIS_GDF, gate drive fault enabled
|
|
1'b0, // OTW_REP, overtemp not reported
|
|
2'b01, // PWM_MODE, 3x PWM mode
|
|
1'b0, // 1PWM_COM, 1x PWM uses synchronous rectifier
|
|
1'b0, // 1PWM_DIR, default
|
|
1'b0, // COAST, disabled
|
|
1'b0, // BRAKE, disabled
|
|
1'b0 // CLR_FLT, no clear
|
|
};
|
|
|
|
// TODO actually calculate HS/LS gate drive
|
|
// requirements
|
|
assign hs_control = {
|
|
4'b0011, // address = 0x03
|
|
1'b1, // write
|
|
3'b000, // LOCK, don't lock or unlock
|
|
4'b0100, // IDRIVEP_HS, 300 mA
|
|
4'b0010 // IDRIVEN_HS, 200 mA
|
|
};
|
|
assign ls_control = {
|
|
4'b0100, // address = 0x04
|
|
1'b1, // write
|
|
1'b1, // CBC, OCP conditions reset when PWM is provided
|
|
2'b11, // TDRIVE = 4000 ns gate-current drive time
|
|
4'b0100, // IDRIVEP_LS, 300 mA
|
|
4'b0010 // IDRIVEN_LS, 200 mA
|
|
};
|
|
assign ocp_control = {
|
|
4'b0101, // address = 0x05
|
|
1'b1, // write
|
|
1'b0, // TRETRY, VDS_OCP/SEN_OCP retry time is 8ms
|
|
2'b01, // DEAD_TIME, 100 ns deadtime
|
|
2'b01, // OCP_MODE, overcurrent causes automatic retry
|
|
2'b10, // OCP_DEG, 4us overcurrent deglitch
|
|
4'b1101 // VDS_LVL, 1V
|
|
};
|
|
assign csa_control = {
|
|
4'b0110, // address = 0x06
|
|
1'b1, // write
|
|
1'b0, // CSA_FET = SPx
|
|
1'b0, // VREF_DIV, unidirectional
|
|
1'b0, // LS_REF, VDS_OCP is measured from SHx to SNx
|
|
2'b10, // CSA_GAIN, 20V/V
|
|
1'b0, // DIS_SEN overcurrent fault enabled
|
|
1'b0, // CSA_CAL_A, normal operation
|
|
1'b0, // CSA_CAL_B, normal operation
|
|
1'b0, // CSA_CAL_C, normal operation
|
|
2'b11 // SEN_LVL, OCP 1 V
|
|
};
|
|
|
|
wire [3:0] cur_bit;
|
|
wire [7:0] config_bits;
|
|
|
|
assign config_bits[0] = driver_control[cur_bit];
|
|
assign config_bits[1] = hs_control[cur_bit];
|
|
assign config_bits[2] = ls_control[cur_bit];
|
|
assign config_bits[3] =
|
|
ocp_control[cur_bit];
|
|
assign config_bits[4] =
|
|
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;
|
|
|
|
reg fault_a_ff = 0;
|
|
reg fault_b_ff = 0;
|
|
reg fault_c_ff = 0;
|
|
|
|
assign fault_a = fault_a_ff;
|
|
assign fault_b = fault_b_ff;
|
|
assign fault_c = fault_c_ff;
|
|
|
|
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;
|
|
// 8x downsample
|
|
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
|