[FPGA-Verilog] Upgrade fpga-verilog to support decoders with WLR

This commit is contained in:
tangxifan 2021-09-20 17:07:26 -07:00
parent 36a4da863c
commit c84c0d4a3f
3 changed files with 108 additions and 1 deletions

View File

@ -194,6 +194,7 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager,
if (true == decoder_lib.use_readback(decoder)) {
BasicPort data_ren_port(std::string(DECODER_DATA_READ_ENABLE_PORT_NAME), data_size);
module_manager.add_port(module_id, data_ren_port, ModuleManager::MODULE_OUTPUT_PORT);
module_manager.set_port_is_register(module_id, data_ren_port.get_name(), true);
}
return module_id;

View File

@ -289,6 +289,20 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
data_inv_port = module_manager.module_port(module_id, data_inv_port_id);
}
/* Find readback port */
ModulePortId readback_port_id = module_manager.find_module_port(module_id, std::string(DECODER_READBACK_PORT_NAME));
BasicPort readback_port;
if (readback_port_id) {
readback_port = module_manager.module_port(module_id, readback_port_id);
}
/* Find data read-enable port */
ModulePortId data_ren_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_READ_ENABLE_PORT_NAME));
BasicPort data_ren_port;
if (data_ren_port_id) {
data_ren_port = module_manager.module_port(module_id, data_ren_port_id);
}
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* Finish dumping ports */
@ -303,10 +317,18 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
* else data_out is driven by '0'
*/
if (1 == data_size) {
/* Output logics for data output */
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
/* If there is a readback port, the data output is only enabled when readback is disabled */
if (readback_port_id) {
fp << " or " << "~" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port);
}
fp << ") begin" << std::endl;
fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && (";
if (readback_port_id) {
fp << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b0) && (";
}
fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))";
fp << " begin" << std::endl;
fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector<size_t>(1, 1)) << ";" << std::endl;
@ -315,6 +337,26 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
fp << "\t" << "end" << std::endl;
fp << "end" << std::endl;
/* Output logics for data readback output */
if (data_ren_port_id) {
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
/* If there is a readback port, the data output is only enabled when readback is disabled */
if (readback_port_id) {
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, readback_port);
}
fp << ") begin" << std::endl;
fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && (";
fp << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b1) && (";
fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))";
fp << " begin" << std::endl;
fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, std::vector<size_t>(1, 1)) << ";" << std::endl;
fp << "\t" << "end else begin" << std::endl;
fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, std::vector<size_t>(1, 0)) << ";" << std::endl;
fp << "\t" << "end" << std::endl;
fp << "end" << std::endl;
}
/* Depend on if the inverted data output port is needed or not */
if (true == decoder_lib.use_data_inv_port(decoder)) {
print_verilog_wire_connection(fp, data_inv_port, addr_port, true);
@ -344,10 +386,23 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
* The rest of addr codes 3'b110, 3'b111 will be decoded to data=8'b0_0000;
*/
/* Output logics for data output */
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
/* If there is a readback port, the data output is only enabled when readback is disabled */
if (readback_port_id) {
fp << " or " << "~" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port);
}
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
fp << ") begin" << std::endl;
fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl;
if (readback_port_id) {
fp << "\tif (";
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) ";
fp << "&&";
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b0) ";
fp << ") begin" << std::endl;
} else {
fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl;
}
fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl;
/* Create a string for addr and data */
for (size_t i = 0; i < data_size; ++i) {
@ -373,6 +428,46 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
fp << "end" << std::endl;
/* Output logics for data readback output */
if (data_ren_port_id) {
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
/* If there is a readback port, the data output is only enabled when readback is disabled */
if (readback_port_id) {
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, readback_port);
}
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
fp << ") begin" << std::endl;
fp << "\tif (";
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) ";
fp << "&&";
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b1) ";
fp << ") begin" << std::endl;
fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl;
/* Create a string for addr and data */
for (size_t i = 0; i < data_size; ++i) {
fp << "\t\t\t" << generate_verilog_constant_values(itobin_vec(i, addr_size));
fp << " : ";
fp << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(i, data_size));
fp << ";" << std::endl;
}
/* Different from MUX decoder, we assign default values which is all zero */
fp << "\t\t\t" << "default";
fp << " : ";
fp << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(data_size, data_size));
fp << ";" << std::endl;
fp << "\t\t" << "endcase" << std::endl;
fp << "\t" << "end" << std::endl;
/* If enable is not active, we should give all zero */
fp << "\t" << "else begin" << std::endl;
fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(data_size, data_size));
fp << ";" << std::endl;
fp << "\t" << "end" << std::endl;
fp << "end" << std::endl;
}
if (true == decoder_lib.use_data_inv_port(decoder)) {
print_verilog_wire_connection(fp, data_inv_port, data_port, true);
}

View File

@ -128,6 +128,17 @@ void print_verilog_top_testbench_memory_bank_port(std::fstream& fp,
BasicPort din_port = module_manager.module_port(top_module, din_port_id);
fp << generate_verilog_port(VERILOG_PORT_REG, din_port) << ";" << std::endl;
/* Print the optional readback port for the decoder here */
print_verilog_comment(fp, std::string("---- Readback port for memory decoders -----"));
ModulePortId readback_port_id = module_manager.find_module_port(top_module,
std::string(DECODER_READBACK_PORT_NAME));
if (readback_port_id) {
BasicPort readback_port = module_manager.module_port(top_module, readback_port_id);
fp << generate_verilog_port(VERILOG_PORT_WIRE, readback_port) << ";" << std::endl;
/* Disable readback in full testbenches */
print_verilog_wire_constant_values(fp, readback_port, std::vector<size_t>(readback_port.get_width(), 0));
}
/* Generate enable signal waveform here:
* which is a 90 degree phase shift than the programming clock
*/