[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:
parent
54ec74d8d2
commit
76d58ebaa0
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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) << ")";
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue