[FPGA-Verilog] Upgrade fpga-verilog to support decoders with WLR
This commit is contained in:
parent
36a4da863c
commit
c84c0d4a3f
|
@ -194,6 +194,7 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager,
|
||||||
if (true == decoder_lib.use_readback(decoder)) {
|
if (true == decoder_lib.use_readback(decoder)) {
|
||||||
BasicPort data_ren_port(std::string(DECODER_DATA_READ_ENABLE_PORT_NAME), data_size);
|
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.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;
|
return module_id;
|
||||||
|
|
|
@ -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);
|
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 */
|
/* dump module definition + ports */
|
||||||
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
|
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
|
||||||
/* Finish dumping ports */
|
/* Finish dumping ports */
|
||||||
|
@ -303,10 +317,18 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
|
||||||
* else data_out is driven by '0'
|
* else data_out is driven by '0'
|
||||||
*/
|
*/
|
||||||
if (1 == data_size) {
|
if (1 == data_size) {
|
||||||
|
/* Output logics for data output */
|
||||||
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
|
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
|
||||||
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_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 << ") begin" << std::endl;
|
||||||
fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && (";
|
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 << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))";
|
||||||
fp << " begin" << std::endl;
|
fp << " begin" << std::endl;
|
||||||
fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector<size_t>(1, 1)) << ";" << 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 << "\t" << "end" << std::endl;
|
||||||
fp << "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 */
|
/* Depend on if the inverted data output port is needed or not */
|
||||||
if (true == decoder_lib.use_data_inv_port(decoder)) {
|
if (true == decoder_lib.use_data_inv_port(decoder)) {
|
||||||
print_verilog_wire_connection(fp, data_inv_port, addr_port, true);
|
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;
|
* 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);
|
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 << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
|
||||||
fp << ") begin" << std::endl;
|
fp << ") 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 << "\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;
|
fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl;
|
||||||
/* Create a string for addr and data */
|
/* Create a string for addr and data */
|
||||||
for (size_t i = 0; i < data_size; ++i) {
|
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;
|
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)) {
|
if (true == decoder_lib.use_data_inv_port(decoder)) {
|
||||||
print_verilog_wire_connection(fp, data_inv_port, data_port, true);
|
print_verilog_wire_connection(fp, data_inv_port, data_port, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
BasicPort din_port = module_manager.module_port(top_module, din_port_id);
|
||||||
fp << generate_verilog_port(VERILOG_PORT_REG, din_port) << ";" << std::endl;
|
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:
|
/* Generate enable signal waveform here:
|
||||||
* which is a 90 degree phase shift than the programming clock
|
* which is a 90 degree phase shift than the programming clock
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue