Compare commits
2 Commits
d4611c0ea3
...
5f85a3b99e
Author | SHA1 | Date |
---|---|---|
|
5f85a3b99e | |
|
bd108603e3 |
|
@ -17,7 +17,7 @@ module drv8353r_driver(
|
|||
output drv_cs_n,
|
||||
output drv_sck,
|
||||
output drv_sdi,
|
||||
output drv_sdo,
|
||||
input drv_sdo,
|
||||
|
||||
// assert stop with the coast_nbrake
|
||||
// bit to disable the gate drivers
|
||||
|
@ -28,9 +28,11 @@ module drv8353r_driver(
|
|||
output rdy,
|
||||
output fault_a,
|
||||
output fault_b,
|
||||
output fault_c,
|
||||
output fault_c
|
||||
);
|
||||
|
||||
parameter WAIT_TIME = 98;
|
||||
|
||||
wire [15:0] driver_control;
|
||||
wire [15:0] hs_control;
|
||||
wire [15:0] ls_control;
|
||||
|
@ -49,8 +51,9 @@ assign driver_control = {
|
|||
1'b0, // 1PWM_DIR, default
|
||||
1'b0, // COAST, disabled
|
||||
1'b0, // BRAKE, disabled
|
||||
1'b0, // CLR_FLT, no clear
|
||||
1'b0 // CLR_FLT, no clear
|
||||
};
|
||||
|
||||
// TODO actually calculate HS/LS gate drive
|
||||
// requirements
|
||||
assign hs_control = {
|
||||
|
@ -58,7 +61,7 @@ assign hs_control = {
|
|||
1'b1, // write
|
||||
3'b000, // LOCK, don't lock or unlock
|
||||
4'b0100, // IDRIVEP_HS, 300 mA
|
||||
4'b0010, // IDRIVEN_HS, 200 mA
|
||||
4'b0010 // IDRIVEN_HS, 200 mA
|
||||
};
|
||||
assign ls_control = {
|
||||
4'b0100, // address = 0x04
|
||||
|
@ -66,7 +69,7 @@ assign ls_control = {
|
|||
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
|
||||
4'b0010 // IDRIVEN_LS, 200 mA
|
||||
};
|
||||
assign ocp_control = {
|
||||
4'b0101, // address = 0x05
|
||||
|
@ -75,7 +78,7 @@ assign ocp_control = {
|
|||
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
|
||||
4'b1101 // VDS_LVL, 1V
|
||||
};
|
||||
assign csa_control = {
|
||||
4'b0110, // address = 0x06
|
||||
|
@ -88,12 +91,11 @@ assign csa_control = {
|
|||
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
|
||||
2'b11 // SEN_LVL, OCP 1 V
|
||||
};
|
||||
|
||||
reg [3:0] cur_bit;
|
||||
wire [4:0] config_bits;
|
||||
wire config_bit;
|
||||
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];
|
||||
|
@ -102,5 +104,141 @@ 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;
|
||||
|
||||
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
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
tests: test_adc
|
||||
tests: test_adc test_drv8353
|
||||
|
||||
test_adc: adc_driver_tb.vcd
|
||||
test_adc: vcd/adc_driver_tb.vcd
|
||||
|
||||
adc_driver_tb.vcd: ./adc_driver_tb
|
||||
./adc_driver_tb
|
||||
vcd/adc_driver_tb.vcd: bin/adc_driver_tb
|
||||
./bin/adc_driver_tb
|
||||
|
||||
adc_driver_tb: adc_driver_tb.v ../library/adc_driver.v
|
||||
iverilog adc_driver_tb.v ../library/adc_driver.v -o adc_driver_tb
|
||||
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
|
||||
|
||||
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
|
||||
|
|
|
@ -45,7 +45,7 @@ initial begin
|
|||
configured = 0;
|
||||
out = 0;
|
||||
|
||||
$dumpfile("adc_driver_tb.vcd");
|
||||
$dumpfile("vcd/adc_driver_tb.vcd");
|
||||
$dumpvars;
|
||||
end
|
||||
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
#include "Vadc_driver.h"
|
||||
#include "verilated.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
int main(int argc, char** argv, char** env) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
auto driver = std::unique_ptr<Vadc_driver>();
|
||||
uint64_t tick = 0;
|
||||
bool done = false;
|
||||
|
||||
driver->clk = 0;
|
||||
driver->rstn = 1;
|
||||
driver->adc_so = 0;
|
||||
driver->ack = 0;
|
||||
|
||||
int sck_old = driver->sck;
|
||||
|
||||
while (!done) {
|
||||
if (tick > 5) {
|
||||
driver->rstn = 0;
|
||||
}
|
||||
if ((tick % 10) == 0) {
|
||||
driver->clk = 1;
|
||||
}
|
||||
if ((tick % 10) == 5) {
|
||||
driver->clk = 0;
|
||||
}
|
||||
driver->eval();
|
||||
if (driver->sck & !sck_old) {
|
||||
}
|
||||
sck_old = driver->sck;
|
||||
if (driver->vld) {
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -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