I'm messing around with FPGAs and am running into some warnings that I sort of understand but don't know what's causing them. My understanding is there was a conflict of some kind and it is resolved but using a constant value. Though that will cause things to not work, which is what I'm seeing.
Warning: Driver-driver conflict for \controller.out_buff [1] between cell $flatten\alu.$procdff$1191.Q and constant 1'0 in cpu: Resolved using constant.
Warning: Driver-driver conflict for \controller.out_buff [1] between cell $auto$ff.cc:266:slice$1430.Q and constant 1'0 in cpu: Resolved using constant.
Warning: Driver-driver conflict for \controller.out_buff [1] between cell $flatten\pc.$procdff$1163.Q and constant 1'0 in cpu: Resolved using constant.
Warning: Driver-driver conflict for \controller.out_buff [1] between cell $flatten\register_a.$procdff$1161.Q and constant 1'0 in cpu: Resolved using constant.
Warning: Driver-driver conflict for \controller.out_buff [1] between cell $flatten\register_b.$procdff$1161.Q and constant 1'0 in cpu: Resolved using constant.
Warning: Driver-driver conflict for \controller.out_buff [1] between cell $flatten\register_instruction.$procdff$1161.Q and constant 1'0 in cpu: Resolved using constant.
Warning: Driver-driver conflict for \controller.out_buff [1] between cell $flatten\register_output.$procdff$1161.Q and constant 1'0 in cpu: Resolved using constant.
My issue is I don't know why there are the warnings, or how to fix them... I've included below my cpu.v, register.v and controller.v files below as four of the errors are related to the register and if I can figure that out I can figure the rest out, I hope.
What is causing the Driver-driver warnings? How do I fix it?
cpu.v
module cpu
(
input i_clk,
input i_reset,
output [5:0] led
);
wire [7:0] bus;
wire register_a_read_n;
wire register_a_write_n;
wire register_b_read_n;
wire register_b_write_n;
wire register_instruction_read_n;
wire register_instruction_write_n;
wire [7:0] regiter_instruction_internal;
wire register_out_write_n;
wire [7:0] regiter_out_internal;
wire register_mem_write_n;
wire [7:0] regiter_mem_internal;
wire programcounter_read_n;
wire programcounter_write_n;
wire programcounter_inc_n;
wire alu_read_n;
wire alu_subtract;
wire [7:0] alu_input_a;
wire [7:0] alu_input_b;
wire [3:0] mem_address;
wire mem_read_n;
wire mem_write_n;
wire [3:0] instruction;
wire [3:0] instruction_argument;
wire flag_c;
wire flag_z;
wire sys_clock;
wire control_halt;
assign led[5:0] = ~regiter_out_internal[5:0];
assign mem_address[3:0] = regiter_mem_internal[3:0];
assign instruction = regiter_instruction_internal[7:4];
assign instruction_argument = regiter_instruction_internal[3:0];
clock system_clock
(
.i_clk(i_clk),
.i_halt(control_halt),
.o_clk(sys_clock)
);
register register_a
(
.i_clk(sys_clock),
.i_reset(i_reset),
.i_read_n(register_a_read_n),
.i_write_n(register_a_write_n),
.io_bus(bus),
.internal_data(alu_input_a)
);
register register_b
(
.i_clk(sys_clock),
.i_reset(i_reset),
.i_read_n(register_b_read_n),
.i_write_n(register_b_write_n),
.io_bus(bus),
.internal_data(alu_input_b)
);
register register_instruction
(
.i_clk(sys_clock),
.i_reset(i_reset),
.i_read_n(register_instruction_read_n),
.i_write_n(register_instruction_write_n),
.io_bus(bus),
.internal_data(regiter_instruction_internal)
);
register register_output
(
.i_clk(sys_clock),
.i_reset(i_reset),
.i_read_n(1'b1),
.i_write_n(register_out_write_n),
.io_bus(bus),
.internal_data(regiter_out_internal)
);
register register_mem
(
.i_clk(sys_clock),
.i_reset(i_reset),
.i_read_n(1'b1),
.i_write_n(register_mem_write_n),
.io_bus(bus),
.internal_data(regiter_mem_internal)
);
programcounter pc
(
.i_clk(sys_clock),
.i_reset(i_reset),
.i_read_n(programcounter_read_n),
.i_write_n(programcounter_write_n),
.i_inc_n(programcounter_inc_n),
.io_bus(bus)
);
alu alu
(
.i_clk(sys_clock),
.i_reset(i_reset),
.i_read_n(alu_read_n),
.i_subtract(alu_subtract),
.i_data_a(alu_input_a),
.i_data_b(alu_input_b),
.o_flag_c(flag_c),
.o_flag_z(flag_z),
.o_bus(bus)
);
memory mem
(
.i_clk(sys_clock),
.i_address(mem_address),
.i_read_n(mem_read_n),
.i_write_n(mem_write_n),
.io_bus(bus)
);
controller controller
(
.i_clk(sys_clock),
.i_reset(i_reset),
.i_instruction(instruction),
.i_instruction_argument(instruction_argument),
.i_flag_c(flag_c),
.i_flag_z(flag_z),
.o_bus(bus),
.o_halt(control_halt),
.o_reg_mem_write_n(),
.o_mem_read_n(mem_read_n),
.o_mem_write_n(mem_write_n),
.o_reg_instruction_read_n(),
.o_reg_instruction_write_n(),
.o_reg_a_read_n(register_a_read_n),
.o_reg_a_write_n(register_a_write_n),
.o_alu_read_n(alu_read_n),
.o_alu_subtract(alu_subtract),
.o_reg_b_read_n(register_b_read_n),
.o_reg_b_write_n(register_b_write_n),
.o_reg_out_write_n(register_out_write_n),
.o_pc_read_n(programcounter_read_n),
.o_pc_write_n(programcounter_write_n),
.o_pc_inc_n(programcounter_inc_n)
);
endmodule
register.v
module register
(
i_clk,
i_reset,
i_read_n,
i_write_n,
io_bus,
internal_data
);
// Control signals
input wire i_clk;
input wire i_reset;
input wire i_read_n;
input wire i_write_n;
// Inputs & Outputs
inout wire [7:0] io_bus;
output reg [7:0] internal_data;
reg [7:0] bus_data;
assign io_bus = bus_data;
initial begin
internal_data <= 8'b00000000;
end
wire sen;
assign sen = i_clk || i_reset;
always @(posedge sen) begin
if (i_reset == 1'b1) begin
internal_data <= 8'b00000000;
bus_data <= 8'bZZZZZZZZ;
end else begin
if (i_write_n == 1'b0) begin
internal_data <= io_bus;
end
if (i_read_n == 1'b0) begin
bus_data <= internal_data;
end else begin
bus_data <= 8'bZZZZZZZZ;
end
end
end
endmodule
controller.v
module controller
(
i_clk,
i_reset,
i_instruction,
i_instruction_argument,
i_flag_c,
i_flag_z,
o_bus,
o_halt,
o_reg_mem_write_n,
o_mem_read_n,
o_mem_write_n,
o_reg_instruction_read_n,
o_reg_instruction_write_n,
o_reg_a_read_n,
o_reg_a_write_n,
o_alu_read_n,
o_alu_subtract,
o_reg_b_read_n,
o_reg_b_write_n,
o_reg_out_write_n,
o_pc_read_n,
o_pc_write_n,
o_pc_inc_n
);
// Control signals
input wire i_clk;
input wire i_reset;
// Inputs & Outputs
input wire [3:0] i_instruction;
input wire [3:0] i_instruction_argument;
input wire i_flag_c;
input wire i_flag_z;
inout wire [7:0] o_bus;
output reg o_halt;
output reg o_reg_mem_write_n;
output reg o_mem_read_n;
output reg o_mem_write_n;
output reg o_reg_instruction_read_n;
output reg o_reg_instruction_write_n;
output reg o_reg_a_read_n;
output reg o_reg_a_write_n;
output reg o_alu_read_n;
output reg o_alu_subtract;
output reg o_reg_b_read_n;
output reg o_reg_b_write_n;
output reg o_reg_out_write_n;
output reg o_pc_read_n;
output reg o_pc_write_n;
output reg o_pc_inc_n;
// Internal
reg [7:0] out_buff;
integer cycle_step;
integer instruction_step;
assign o_bus = out_buff;
initial begin
cycle_step = 0;
out_buff <= 8'bZZZZZZZZ;
o_halt <= 1'b0;
o_reg_mem_write_n <= 1'b1;
o_mem_read_n <= 1'b1;
o_mem_write_n <= 1'b1;
o_reg_instruction_read_n <= 1'b1;
o_reg_instruction_write_n <= 1'b1;
o_reg_a_read_n <= 1'b1;
o_reg_a_write_n <= 1'b1;
o_alu_read_n <= 1'b1;
o_alu_subtract <= 1'b0;
o_reg_b_read_n <= 1'b1;
o_reg_b_write_n <= 1'b1;
o_pc_read_n <= 1'b1;
o_pc_write_n <= 1'b1;
o_pc_inc_n <= 1'b1;
end
wire sen;
assign sen = i_clk || i_reset;
// Main controller loop
always @(posedge sen) begin
if (i_reset == 1'b1) begin
cycle_step = 0;
out_buff <= 8'bZZZZZZZZ;
o_halt <= 1'b0;
o_reg_mem_write_n <= 1'b1;
o_mem_read_n <= 1'b1;
o_mem_write_n <= 1'b1;
o_reg_instruction_read_n <= 1'b1;
o_reg_instruction_write_n <= 1'b1;
o_reg_a_read_n <= 1'b1;
o_reg_a_write_n <= 1'b1;
o_alu_read_n <= 1'b1;
o_alu_subtract <= 1'b0;
o_reg_b_read_n <= 1'b1;
o_reg_b_write_n <= 1'b1;
o_pc_read_n <= 1'b1;
o_pc_write_n <= 1'b1;
o_pc_inc_n <= 1'b1;
end else begin
if (cycle_step == 0) begin
// Load the PC contents into mem reg
o_pc_read_n <= 1'b0;
o_reg_mem_write_n <= 1'b0;
o_reg_out_write_n <= 1'b0;
cycle_step = 1;
end
if (cycle_step == 1) begin
o_pc_read_n <= 1'b1;
o_reg_mem_write_n <= 1'b1;
o_reg_out_write_n <= 1'b1;
// Load mem content into instruction reg
o_mem_read_n <= 1'b0;
o_reg_instruction_write_n <= 1'b0;
// Inc the PC register
o_pc_inc_n <= 1'b0;
cycle_step = 2;
end
if (cycle_step == 2) begin
o_mem_read_n <= 1'b1;
o_reg_instruction_write_n <= 1'b1;
o_pc_inc_n <= 1'b1;
instruction_step = 0;
cycle_step = 0;
end
// Instructions
if (cycle_step == 99) begin
if (i_instruction == 4'b0001) begin // LDA (Load A)
if (instruction_step == 0) begin
// set mem reg
out_buff <= 8'b00000000;
out_buff[3:0] <= i_instruction_argument;
o_reg_mem_write_n <= 1'b1;
instruction_step = 1;
end
if (instruction_step == 1) begin
o_reg_mem_write_n <= 1'b0;
out_buff <= 8'bZZZZZZZZ;
// Load mem into A reg
o_mem_read_n <= 1'b0;
o_reg_a_write_n <= 1'b0;
instruction_step = 2;
end
if (instruction_step == 2) begin
o_mem_read_n <= 1'b1;
o_reg_a_write_n <= 1'b1;
// Finish instruction
instruction_step = 0;
cycle_step = 0;
end
end else if (i_instruction == 4'b0010) begin // LDB (Load B)
if (instruction_step == 0) begin
// set mem reg
out_buff <= 8'b00000000;
out_buff[3:0] <= i_instruction_argument;
o_reg_mem_write_n <= 1'b1;
instruction_step = 1;
end
if (instruction_step == 1) begin
o_reg_mem_write_n <= 1'b0;
out_buff <= 8'bZZZZZZZZ;
// Load mem into B reg
o_mem_read_n <= 1'b0;
o_reg_b_write_n <= 1'b0;
instruction_step = 2;
end
if (instruction_step == 2) begin
o_mem_read_n <= 1'b1;
o_reg_b_write_n <= 1'b1;
// Finish instruction
instruction_step = 0;
cycle_step = 0;
end
end else if (i_instruction == 4'b0011) begin // LDO (Load Out)
if (instruction_step == 0) begin
// set mem reg
out_buff <= 8'b00000000;
out_buff[3:0] <= i_instruction_argument;
o_reg_mem_write_n <= 1'b1;
instruction_step = 1;
end
if (instruction_step == 1) begin
o_reg_mem_write_n <= 1'b0;
out_buff <= 8'bZZZZZZZZ;
// Load mem into B reg
o_mem_read_n <= 1'b0;
o_reg_out_write_n <= 1'b0;
instruction_step = 2;
end
if (instruction_step == 2) begin
o_mem_read_n <= 1'b1;
o_reg_out_write_n <= 1'b1;
// Finish instruction
instruction_step = 0;
cycle_step = 0;
end
end else if (i_instruction == 4'b1111) begin // HLT (Halt)
if (instruction_step == 0) begin
// set halt signal
o_halt <= 1'b1;
// Finish instruction
instruction_step = 0;
cycle_step = 0;
end
end else begin
// Finish instruction
instruction_step = 0;
cycle_step = 0;
end
end
end
end
endmodule
Synthesizable Verilog is a limited subset of the Verilog language. The Verilog language allows both synthesizable and non-synthesizable coding. The non-synthesizable coding is for behavior models, delays, test bench code, and to a limited extent analog behavior. Synthesis tools expect you to write your code within a certain style template. It is up the the synthesis tool to decide how to translate into logic cells, but they generally follow the same templates for flops, comb-logic, tri-state logic, etc.
All of your @(posedge sen)
should be @(posedge i_clk or posedge i_reset)
for asynchronous reset or @(posedge i_clk)
for synchronous reset. If you are targeting for FPGA, you should go for synchronous reset as most FPGA boards had limited (if any) flops with asynchronous that you are allowed to control. If you are targeting for ASIC, then typically either should work but depending on the standard cell library that you are mapping to.
assign io_bus = bus_data;
should be assign io_bus = (i_read_n == 1'b0) ? internal_data : 8'bZZZZZZZZ;
. You may or may not want to flop the i_read_n
depending on your design needs. Synthesis tools usually treat assigning X or Z to a register as don't care (ie: what ever is convenient or optimal for the synthesizer). This is different than driving high-impedance Z to a net/wire. This is an area where Verilog simulation and synthesis differ. The preferred approach is to use a tri-state operator in the net. Registers should generally be assigned to known states.
The same tri-state assignment criteria is true for assign o_bus = out_buff;
. I will let you figure out the signal to enable the driver.
Other issues:
You are mixing blocking (=
) and non-blocking (<=
) assignments. Generally blocking should be used to assign combination logic and non-blocking should be used to assign synchronous logic. Typically combination logic and synchronous logic should be in separate always blocks. There are save ways to mix blocking and non-blocking but most RTL designers and verification people are adamantly agents it has been the cause of simulation vs synthesis mismatch.
If you are targeting for ASIC, get ride of the initial blocks. Most ASIC synthesizers will ignore initial blocks.
Consideration:
In the cpu.v you are using the more modern ANSI style header (available since IEEE1364-2001; aka Verilog-2001). But it in the other module you are using the legacy non-ANSI style header (required in IEEE1364-1995; aka Verilog-95). The advantage of ANSI style header is fewer lines of code and less change missing port or additional port without a port connections. For example, the register module header could be written as:
module register
(
// Control signals
input wire i_clk,
input wire i_reset,
input wire i_read_n,
input wire i_write_n,
// Inputs & Outputs
inout wire [7:0] io_bus,
output reg [7:0] internal_data
);