[FPGA-Verilog] Move clock generator to generic stimuli and shift register clock period is auto tuned by programming clock period

This commit is contained in:
tangxifan 2021-10-02 21:48:10 -07:00
parent 54ec74d8d2
commit 76d58ebaa0
3 changed files with 128 additions and 65 deletions

View File

@ -1112,21 +1112,30 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp,
*******************************************************************/ *******************************************************************/
static static
void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp, void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp,
const e_config_protocol_type& config_protocol_type, const ConfigProtocol& config_protocol,
const ModuleManager& module_manager, const ModuleManager& module_manager,
const ModuleId& top_module, const ModuleId& top_module,
const bool& fast_configuration,
const bool& bit_value_to_skip,
const FabricBitstream& fabric_bitstream,
const float& prog_clock_period, const float& prog_clock_period,
const float& timescale) { const float& timescale) {
/* Validate the file stream */ /* Validate the file stream */
valid_file_stream(fp); valid_file_stream(fp);
/* Branch on the type of configuration protocol */ /* Branch on the type of configuration protocol */
switch (config_protocol_type) { switch (config_protocol.type()) {
case CONFIG_MEM_STANDALONE: case CONFIG_MEM_STANDALONE:
break; break;
case CONFIG_MEM_SCAN_CHAIN: case CONFIG_MEM_SCAN_CHAIN:
break; break;
case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_QL_MEMORY_BANK:
print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp,
config_protocol,
module_manager,top_module,
fast_configuration, bit_value_to_skip, fabric_bitstream,
prog_clock_period, timescale);
break;
case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK:
case CONFIG_MEM_FRAME_BASED: { case CONFIG_MEM_FRAME_BASED: {
ModulePortId en_port_id = module_manager.find_module_port(top_module, ModulePortId en_port_id = module_manager.find_module_port(top_module,
@ -1956,8 +1965,9 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
/* Generate stimuli for programming interface */ /* Generate stimuli for programming interface */
print_verilog_top_testbench_configuration_protocol_stimulus(fp, print_verilog_top_testbench_configuration_protocol_stimulus(fp,
config_protocol.type(), config_protocol,
module_manager, top_module, module_manager, top_module,
fast_configuration, bit_value_to_skip, fabric_bitstream,
prog_clock_period, prog_clock_period,
VERILOG_SIM_TIMESCALE); VERILOG_SIM_TIMESCALE);

View File

@ -87,9 +87,13 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp,
/* BL Shift register clock and registers */ /* BL Shift register clock and registers */
BasicPort sr_clock_port(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); BasicPort sr_clock_port(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1);
fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_clock_port) << ";" << std::endl; fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_port) << ";" << std::endl;
BasicPort sr_clock_register_port(std::string(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_register_port) << ";" << std::endl; /* Register to enable/disable bl/wl shift register clocks */
BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1);
fp << generate_verilog_port(VERILOG_PORT_REG, start_bl_sr_port) << ";" << std::endl;
/* Register to count bl/wl shift register clocks */
fp << "integer " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl;
} }
/* Print the address port for the Word-Line decoder here */ /* Print the address port for the Word-Line decoder here */
@ -125,9 +129,13 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp,
/* WL Shift register clock and registers */ /* WL Shift register clock and registers */
BasicPort sr_clock_port(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); BasicPort sr_clock_port(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1);
fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_clock_port) << ";" << std::endl; fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_port) << ";" << std::endl;
BasicPort sr_clock_register_port(std::string(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_register_port) << ";" << std::endl; /* Register to enable/disable bl/wl shift register clocks */
BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1);
fp << generate_verilog_port(VERILOG_PORT_REG, start_wl_sr_port) << ";" << std::endl;
/* Register to count bl/wl shift register clocks */
fp << "integer " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl;
} }
/* Print the data-input port: only available when BL has a decoder */ /* Print the data-input port: only available when BL has a decoder */
@ -191,6 +199,94 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp,
fp << ";" << std::endl; fp << ";" << std::endl;
} }
/**
* @brief Generate the Verilog codes for a shift register clocks that controls BL/WL protocols
*/
static
void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(std::fstream& fp,
const BasicPort& prog_clock_port,
const BasicPort& start_sr_port,
const BasicPort& sr_clock_port,
const float& sr_clock_period) {
/* Validate the file stream */
valid_file_stream(fp);
fp << "always";
fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")";
fp << " begin";
fp << std::endl;
fp << "\t";
fp << generate_verilog_port_constant_values(sr_clock_port, std::vector<size_t>(sr_clock_port.get_width(), 0), true);
fp << ";" << std::endl;
fp << "\t";
fp << "while (" << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ") begin";
fp << std::endl;
fp << "\t\t";
fp << "#" << sr_clock_period << " ";
print_verilog_register_connection(fp, sr_clock_port, sr_clock_port, true);
fp << "\t";
fp << "end";
fp << std::endl;
fp << "\t";
fp << generate_verilog_port_constant_values(sr_clock_port, std::vector<size_t>(sr_clock_port.get_width(), 0), true);
fp << ";" << std::endl;
}
void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp,
const ConfigProtocol& config_protocol,
const ModuleManager& module_manager,
const ModuleId& top_module,
const bool& fast_configuration,
const bool& bit_value_to_skip,
const FabricBitstream& fabric_bitstream,
const float& prog_clock_period,
const float& timescale) {
ModulePortId en_port_id = module_manager.find_module_port(top_module,
std::string(DECODER_ENABLE_PORT_NAME));
BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1);
if (en_port_id) {
en_port = module_manager.module_port(top_module, en_port_id);
}
BasicPort en_register_port(std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
print_verilog_comment(fp, std::string("---- Generate enable signal waveform -----"));
print_verilog_shifted_clock_stimuli(fp, en_register_port,
0.25 * prog_clock_period / timescale,
0.5 * prog_clock_period / timescale, 0);
/* Stimulus only for shift-register-based BL/WL protocols */
BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1);
BasicPort bl_sr_clock_port(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1);
BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1);
BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1);
BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1);
/* Reorganize the fabric bitstream by the same address across regions */
if (CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) {
MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream,
fast_configuration,
bit_value_to_skip);
/* TODO: Consider auto-tuned clock period for now */
float bl_sr_clock_period = prog_clock_period / fabric_bits_by_addr.bl_width() / timescale;
float wl_sr_clock_period = prog_clock_period / fabric_bits_by_addr.wl_width() / timescale;
if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) {
print_verilog_comment(fp, "----- BL Shift register clock generator -----");
print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_bl_sr_port, bl_sr_clock_port, 0.5 * bl_sr_clock_period);
}
if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) {
print_verilog_comment(fp, "----- WL Shift register clock generator -----");
print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_wl_sr_port, wl_sr_clock_port, 0.5 * wl_sr_clock_period);
}
}
}
/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ /* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */
static static
void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& fp, void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& fp,
@ -326,40 +422,6 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream&
print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----");
} }
/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */
void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(std::fstream& fp,
const BasicPort& prog_clock_port,
const BasicPort& start_sr_port,
const BasicPort& sr_clock_port) {
/* Validate the file stream */
valid_file_stream(fp);
fp << "always";
fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")";
fp << " begin";
fp << std::endl;
fp << "\t";
fp << generate_verilog_port_constant_values(sr_clock_port, std::vector<size_t>(sr_clock_port.get_width(), 0), true);
fp << ";" << std::endl;
fp << "\t";
fp << "while (" << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ") begin";
fp << std::endl;
fp << "\t\t";
fp << "#0.05 ";
print_verilog_register_connection(fp, sr_clock_port, sr_clock_port, true);
fp << "\t";
fp << "end";
fp << std::endl;
fp << "\t";
fp << generate_verilog_port_constant_values(sr_clock_port, std::vector<size_t>(sr_clock_port.get_width(), 0), true);
fp << ";" << std::endl;
}
/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ /* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */
static static
void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::fstream& fp, void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::fstream& fp,
@ -429,16 +491,6 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f
fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl;
/* Register to enable/disable bl/wl shift register clocks */
BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1);
fp << generate_verilog_port(VERILOG_PORT_REG, start_bl_sr_port) << ";" << std::endl;
BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1);
fp << generate_verilog_port(VERILOG_PORT_REG, start_wl_sr_port) << ";" << std::endl;
/* Register to count bl/wl shift register clocks */
fp << "integer " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl;
fp << "integer " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl;
print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----");
fp << "initial begin" << std::endl; fp << "initial begin" << std::endl;
fp << "\t"; fp << "\t";
@ -462,6 +514,9 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f
fp << ";"; fp << ";";
fp << std::endl; fp << std::endl;
BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1);
BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1);
fp << "\t"; fp << "\t";
fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector<size_t>(start_bl_sr_port.get_width(), 0), true); fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector<size_t>(start_bl_sr_port.get_width(), 0), true);
fp << ";"; fp << ";";
@ -480,12 +535,6 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f
BasicPort bl_sr_clock_port(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); BasicPort bl_sr_clock_port(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1);
BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1);
print_verilog_comment(fp, "----- BL Shift register clock generator -----");
print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_bl_sr_port, bl_sr_clock_port);
print_verilog_comment(fp, "----- WL Shift register clock generator -----");
print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_wl_sr_port, wl_sr_clock_port);
print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----");
fp << "always"; fp << "always";
fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")";

View File

@ -35,13 +35,17 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp,
const ConfigProtocol& config_protocol); const ConfigProtocol& config_protocol);
/** /**
* @brief Generate the Verilog codes for a shift register clocks that controls BL/WL protocols * @brief Generate the Verilog codes that generate stimuli waveforms for BL/WL protocols
*/ */
void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(std::fstream& fp, void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp,
const BasicPort& prog_clock_port, const ConfigProtocol& config_protocol,
const BasicPort& start_sr_port, const ModuleManager& module_manager,
const BasicPort& sr_clock_port); const ModuleId& top_module,
const bool& fast_configuration,
const bool& bit_value_to_skip,
const FabricBitstream& fabric_bitstream,
const float& prog_clock_period,
const float& timescale);
/** /**
* @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol * @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol