Merge remote-tracking branch 'origin/spice_model_refactoring' into ganesh_dev

This commit is contained in:
Ganesh Gore 2019-08-16 22:00:41 -06:00
commit 125d7888df
11 changed files with 145 additions and 105 deletions

View File

@ -199,9 +199,9 @@ int count_num_sram_bits_one_mux_spice_model(t_spice_model* cur_spice_model,
if ( (TRUE == cur_spice_model->design_tech_info.mux_info->local_encoder)
&& (2 < num_input_size) ) {
if (SPICE_MODEL_STRUCTURE_ONELEVEL == cur_spice_model->design_tech_info.mux_info->structure) {
num_sram_bits = ceil(log(num_sram_bits + 1) / log(2));
num_sram_bits = determine_mux_local_encoder_num_inputs(num_sram_bits);
} else if (SPICE_MODEL_STRUCTURE_MULTILEVEL == cur_spice_model->design_tech_info.mux_info->structure) {
num_sram_bits = cur_spice_model->design_tech_info.mux_info->mux_num_level * ceil(log(num_sram_bits / cur_spice_model->design_tech_info.mux_info->mux_num_level + 1) / log(2));
num_sram_bits = cur_spice_model->design_tech_info.mux_info->mux_num_level * determine_mux_local_encoder_num_inputs(num_sram_bits / cur_spice_model->design_tech_info.mux_info->mux_num_level);
}
}
break;
@ -721,9 +721,9 @@ int count_num_conf_bits_one_mux_spice_model(t_spice_model* cur_spice_model,
if ( (TRUE == cur_spice_model->design_tech_info.mux_info->local_encoder)
&& (2 < num_input_size) ) {
if (SPICE_MODEL_STRUCTURE_ONELEVEL == cur_spice_model->design_tech_info.mux_info->structure) {
num_conf_bits = ceil(log(num_conf_bits + 1) / log(2));
num_conf_bits = determine_mux_local_encoder_num_inputs(num_conf_bits);
} else if (SPICE_MODEL_STRUCTURE_MULTILEVEL == cur_spice_model->design_tech_info.mux_info->structure) {
num_conf_bits = cur_spice_model->design_tech_info.mux_info->mux_num_level * ceil(log(num_conf_bits / cur_spice_model->design_tech_info.mux_info->mux_num_level + 1) / log(2));
num_conf_bits = cur_spice_model->design_tech_info.mux_info->mux_num_level * determine_mux_local_encoder_num_inputs(num_conf_bits / cur_spice_model->design_tech_info.mux_info->mux_num_level);
}
}
break;

View File

@ -204,7 +204,7 @@ int multilevel_mux_last_level_input_num(int num_level, int num_input_per_unit,
* We plus 1, which is all-zero condition for outputs
***************************************************************************************/
int determine_mux_local_encoder_num_inputs(int num_outputs) {
return ceil(log(num_outputs + 1) / log(2));
return ceil(log(num_outputs) / log(2));
}
/* Decoding a one-level MUX:
@ -233,8 +233,8 @@ int* decode_onelevel_mux_sram_bits(int fan_in,
if (TRUE == use_local_encoder) {
/* The encoder will convert the path_id to a binary number
* For example: when path_id=3, using a 4-input encoder
* the sram_bits will be the 4-digit binary number of 3: 0011
* For example: when path_id=3 (use the 4th input), using a 4-input encoder
* the sram_bits will be the 4-digit binary number of 3: 0100
*/
ret = my_itobin_int(path_id, num_sram_bits);
} else {
@ -325,20 +325,25 @@ int* decode_multilevel_mux_sram_bits(int fan_in,
/* Walk through each level and find the path_id and encode it */
for (int ilvl = 0; ilvl < mux_level; ++ilvl) {
int start_idx = num_input_basis * ilvl;
int end_idx = num_input_basis * (ilvl + 1) - 1;
int encoded_path_id = 0;
int end_idx = num_input_basis * (ilvl + 1);
int encoded_path_id = -1;
int checker = 0;
for (int idx = start_idx; idx < end_idx; ++idx) {
if ('1' == ret[idx]) {
if (1 == ret[idx]) {
checker++;
encoded_path_id = idx;
encoded_path_id = idx - start_idx;
}
}
/* There should be at most one '1' */
assert( (0 == checker) || (1 == checker));
/* If all-zero bits are found, it means that the stage is not used, assign to the last input by default */
if (0 == checker) {
encoded_path_id = num_input_basis - 1;
}
assert (-1 != encoded_path_id);
/* The encoder will convert the path_id to a binary number
* For example: when path_id=3, using a 4-input encoder
* the sram_bits will be the 4-digit binary number of 3: 0011
* For example: when path_id=3 (use the 4th input), using a 4-input encoder
* the sram_bits will be the 4-digit binary number of 3: 0100
*/
int* tmp_bits = my_itobin_int(encoded_path_id, num_bits_per_level);
/* Copy tmp_bits to encoded bits */

View File

@ -153,6 +153,7 @@ int create_dir_path(char* dir_path) {
exit(1);
return 0;
}
return 0;
}
/* Cat string2 to the end of string1 */
@ -169,8 +170,8 @@ char* my_strcat(const char* str1,
}
/* Split the path and program name*/
int split_path_prog_name(char* prog_path,
char split_token,
int split_path_prog_name(const char* prog_path,
const char split_token,
char** ret_path,
char** ret_prog_name) {
int i;
@ -576,6 +577,28 @@ t_spice_transistor_type* find_mosfet_tech_lib(t_spice_tech_lib tech_lib,
return ret;
}
/* Convert an integer to an one-hot encoding integer array */
char* my_ito1hot(int in_int, int bin_len) {
char* ret = (char*) my_calloc (bin_len + 1, sizeof(char));
/* Make sure we do not have any overflow! */
if (! ( (-1 < in_int) && (in_int <= bin_len) ) )
assert ( (-1 < in_int) && (in_int <= bin_len) );
/* Initialize */
for (int i = 0; i < bin_len - 1; i++) {
ret[i] = '0';
}
sprintf(ret + bin_len - 1, "%s", "0");
if (bin_len == in_int) {
return ret; /* all zero case */
}
ret[in_int] = '1'; /* Keep a good sequence of bits */
return ret;
}
/* Converter an integer to a binary string */
int* my_itobin_int(int in_int, int bin_len) {
int* ret = (int*) my_calloc (bin_len, sizeof(int));
@ -588,7 +611,7 @@ int* my_itobin_int(int in_int, int bin_len) {
temp = in_int;
for (i = 0; i < bin_len; i++) {
if (1 == temp % 2) {
ret[i] = 1;
ret[i] = 1; /* Keep a good sequence of bits */
}
temp = temp / 2;
}
@ -596,7 +619,6 @@ int* my_itobin_int(int in_int, int bin_len) {
return ret;
}
/* Converter an integer to a binary string */
char* my_itobin(int in_int, int bin_len) {
char* ret = (char*) my_calloc (bin_len + 1, sizeof(char));
@ -622,6 +644,7 @@ char* my_itobin(int in_int, int bin_len) {
return ret;
}
/* Convert a integer to a string*/
char* my_itoa(int input) {
char* ret = NULL;

View File

@ -17,8 +17,8 @@ int create_dir_path(char* dir_path);
char* my_strcat(const char* str1,
const char* str2);
int split_path_prog_name(char* prog_path,
char split_token,
int split_path_prog_name(const char* prog_path,
const char split_token,
char** ret_path,
char** ret_prog_name);
@ -58,6 +58,8 @@ t_spice_model_port** find_spice_model_config_done_ports(t_spice_model* spice_mod
t_spice_transistor_type* find_mosfet_tech_lib(t_spice_tech_lib tech_lib,
e_spice_trans_type trans_type);
char* my_ito1hot(int in_int, int bin_len);
char* my_itobin(int in_int, int bin_len);
int* my_itobin_int(int in_int, int bin_len);

View File

@ -53,8 +53,8 @@ void dump_conf_bits_to_bitstream_file(FILE* fp,
* In this file, the property of configuration bits will be shown as comments,
* which is easy for developers to debug
*/
void dump_fpga_spice_bitstream(char* bitstream_file_name,
char* circuit_name,
void dump_fpga_spice_bitstream(const char* bitstream_file_name,
const char* circuit_name,
t_sram_orgz_info* cur_sram_orgz_info) {
FILE* fp;
@ -288,8 +288,8 @@ void dump_conf_bits_to_bitstream_file(FILE* fp,
/* Top-level function*/
void vpr_fpga_generate_bitstream(t_vpr_setup vpr_setup,
t_arch Arch,
char* circuit_name,
char* bitstream_file_path,
const char* circuit_name,
const char* bitstream_file_path,
t_sram_orgz_info** cur_sram_orgz_info) {
/* Timer */
clock_t t_start;
@ -380,22 +380,20 @@ void vpr_fpga_generate_bitstream(t_vpr_setup vpr_setup,
* Prepare all the variables required by the core generator
*/
void vpr_fpga_bitstream_generator(t_vpr_setup vpr_setup,
t_arch Arch,
char* circuit_name,
t_sram_orgz_info** cur_sram_orgz_info) {
char* bitstream_file_path = NULL;
t_arch Arch,
char* circuit_name,
t_sram_orgz_info** cur_sram_orgz_info) {
std::string bitstream_file_path;
if (NULL == vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.bitstream_output_file) {
bitstream_file_path = my_strcat(circuit_name, fpga_spice_bitstream_output_file_postfix);
bitstream_file_path = circuit_name;
bitstream_file_path.append(fpga_spice_bitstream_output_file_postfix);
} else {
bitstream_file_path = my_strdup(vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.bitstream_output_file);
bitstream_file_path = vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.bitstream_output_file;
}
/* Run bitstream generation and dump output file */
vpr_fpga_generate_bitstream(vpr_setup, Arch, circuit_name, bitstream_file_path, cur_sram_orgz_info);
/* Free */
my_free(bitstream_file_path);
vpr_fpga_generate_bitstream(vpr_setup, Arch, circuit_name, bitstream_file_path.c_str(), cur_sram_orgz_info);
}

View File

@ -2,14 +2,14 @@
void encode_decoder_addr(int input,
int decoder_size, char* addr);
void dump_fpga_spice_bitstream(char* bitstream_file_name,
char* circuit_name,
void dump_fpga_spice_bitstream(const char* bitstream_file_name,
const char* circuit_name,
t_sram_orgz_info* cur_sram_orgz_info);
void vpr_fpga_generate_bitstream(t_vpr_setup vpr_setup,
t_arch Arch,
char* circuit_name,
char* bitstream_file_path,
const char* circuit_name,
const char* bitstream_file_path,
t_sram_orgz_info** cur_sram_orgz_info);
void vpr_fpga_bitstream_generator(t_vpr_setup vpr_setup,

View File

@ -38,6 +38,7 @@
/* Generate bitstream for a multiplexer of a switch block */
static
void fpga_spice_generate_bitstream_switch_box_mux(FILE* fp,
const t_arch& arch,
const RRGSB& rr_sb,
t_sram_orgz_info* cur_sram_orgz_info,
t_rr_node* cur_rr_node,
@ -65,6 +66,7 @@ void fpga_spice_generate_bitstream_switch_box_mux(FILE* fp,
assert((2 == mux_size)||(2 < mux_size));
/* Get verilog model*/
CircuitModelId circuit_model = switch_inf[switch_index].circuit_model;
verilog_model = switch_inf[switch_index].spice_model;
/* Configuration bits for this MUX*/
@ -80,7 +82,8 @@ void fpga_spice_generate_bitstream_switch_box_mux(FILE* fp,
((DEFAULT_PATH_ID < path_id) &&(path_id < mux_size)));
/* Depend on both technology and structure of this MUX*/
switch (verilog_model->design_tech) {
const CircuitLibrary& circuit_lib = arch.spice->circuit_lib;
switch (circuit_lib.design_tech_type(circuit_model)) {
case SPICE_MODEL_DESIGN_CMOS:
decode_cmos_mux_sram_bits(verilog_model, mux_size, path_id, &num_mux_sram_bits, &mux_sram_bits, &mux_level);
break;
@ -213,6 +216,7 @@ void fpga_spice_generate_bitstream_switch_box_mux(FILE* fp,
static
void fpga_spice_generate_bitstream_switch_box_interc(FILE* fp,
const t_arch& arch,
const RRGSB& rr_sb,
t_sram_orgz_info* cur_sram_orgz_info,
enum e_side chan_side,
@ -245,7 +249,7 @@ void fpga_spice_generate_bitstream_switch_box_interc(FILE* fp,
/* No bitstream generation required by a special direct connection*/
} else if (1 < num_drive_rr_nodes) {
/* Print the multiplexer, fan_in >= 2 */
fpga_spice_generate_bitstream_switch_box_mux(fp, rr_sb, cur_sram_orgz_info,
fpga_spice_generate_bitstream_switch_box_mux(fp, arch, rr_sb, cur_sram_orgz_info,
cur_rr_node,
num_drive_rr_nodes, drive_rr_nodes,
cur_rr_node->drive_switches[DEFAULT_SWITCH_ID]);
@ -344,6 +348,7 @@ void fpga_spice_generate_bitstream_switch_box_interc(FILE* fp,
*/
static
void fpga_spice_generate_bitstream_routing_switch_box_subckt(FILE* fp,
const t_arch& arch,
const RRGSB& rr_sb,
t_sram_orgz_info* cur_sram_orgz_info) {
/* Check */
@ -362,7 +367,7 @@ void fpga_spice_generate_bitstream_routing_switch_box_subckt(FILE* fp,
||(CHANY == rr_sb.get_chan_node(side_manager.get_side(), itrack)->type));
/* We care INC_DIRECTION tracks at this side*/
if (OUT_PORT == rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) {
fpga_spice_generate_bitstream_switch_box_interc(fp, rr_sb, cur_sram_orgz_info,
fpga_spice_generate_bitstream_switch_box_interc(fp, arch, rr_sb, cur_sram_orgz_info,
side_manager.get_side(),
itrack);
}
@ -797,7 +802,7 @@ void fpga_spice_generate_bitstream_routing_connection_box_subckt(FILE* fp,
/* Top Function*/
/* Build the routing resource SPICE sub-circuits*/
void fpga_spice_generate_bitstream_routing_resources(char* routing_bitstream_log_file_path,
t_arch arch,
const t_arch& arch,
t_det_routing_arch* routing_arch,
t_sram_orgz_info* cur_sram_orgz_info,
boolean compact_routing_hierarchy) {
@ -841,7 +846,7 @@ void fpga_spice_generate_bitstream_routing_resources(char* routing_bitstream_log
for (size_t ix = 0; ix < sb_range.get_x(); ++ix) {
for (size_t iy = 0; iy < sb_range.get_y(); ++iy) {
const RRGSB& rr_sb = device_rr_gsb.get_gsb(ix, iy);
fpga_spice_generate_bitstream_routing_switch_box_subckt(fp,
fpga_spice_generate_bitstream_routing_switch_box_subckt(fp, arch,
rr_sb, cur_sram_orgz_info);
}
}

View File

@ -1,7 +1,7 @@
void fpga_spice_generate_bitstream_routing_resources(char* routing_bitstream_log_file_path,
t_arch arch,
const t_arch& arch,
t_det_routing_arch* routing_arch,
t_sram_orgz_info* cur_sram_orgz_info,
boolean compact_routing_hierarchy);

View File

@ -231,16 +231,22 @@ void connect_one_rr_node_for_phy_pb_graph_node(INP t_pb_graph_pin* cur_pb_graph_
assert(rr_node_type == local_rr_graph->rr_node[cur_rr_node_index].type);
switch (rr_node_type) {
case INTRA_CLUSTER_EDGE:
case INTRA_CLUSTER_EDGE: {
/* Check out all the output_edges belonging to the same physical mode */
int cur_edge = 0;
for (iedge = 0; iedge < cur_pb_graph_pin->num_output_edges; iedge++) {
check_pb_graph_edge(*(cur_pb_graph_pin->output_edges[iedge]));
if (phy_mode_index == cur_pb_graph_pin->output_edges[iedge]->interconnect->parent_mode_index) {
local_rr_graph->rr_node[cur_rr_node_index].edges[iedge] = cur_pb_graph_pin->output_edges[iedge]->output_pins[0]->rr_node_index_physical_pb;
local_rr_graph->rr_node[cur_rr_node_index].switches[iedge] = local_rr_graph->delayless_switch_index;
/* Bypass fan-outs that are not in the physical mode */
if (phy_mode_index != cur_pb_graph_pin->output_edges[iedge]->interconnect->parent_mode_index) {
continue;
}
assert ( cur_edge < local_rr_graph->rr_node[cur_rr_node_index].num_edges);
local_rr_graph->rr_node[cur_rr_node_index].edges[cur_edge] = cur_pb_graph_pin->output_edges[iedge]->output_pins[0]->rr_node_index_physical_pb;
local_rr_graph->rr_node[cur_rr_node_index].switches[cur_edge] = local_rr_graph->delayless_switch_index;
cur_edge++;
}
break;
}
case SOURCE:
/* Connect the SOURCE nodes to the rr_node of cur_pb_graph_pin */
assert (0 == local_rr_graph->rr_node[cur_rr_node_index].fan_in);

View File

@ -310,7 +310,10 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
sram_verilog_orgz_info->type);
/* Force enable bitstream generator when we need to output Verilog top testbench*/
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_testbench) {
if ((TRUE == vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.gen_bitstream)
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_testbench)
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_autocheck_top_testbench)
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_formal_verification_top_netlist)) {
vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.gen_bitstream = TRUE;
}

View File

@ -1497,10 +1497,10 @@ void dump_verilog_cmos_mux_multilevel_structure(FILE* fp,
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
/* Print local wires for local encoders */
fprintf(fp, "wire [%d:0] %s_data;\n",
fprintf(fp, "wire [0:%d] %s_data;\n",
spice_mux_arch.num_level * spice_mux_arch.num_input_basis - 1,
sram_port[0]->prefix);
fprintf(fp, "wire [%d:0] %s_data_inv;\n",
fprintf(fp, "wire [0:%d] %s_data_inv;\n",
spice_mux_arch.num_level * spice_mux_arch.num_input_basis - 1,
sram_port[0]->prefix);
}
@ -1670,6 +1670,37 @@ void dump_verilog_cmos_mux_onelevel_structure(FILE* fp,
fprintf(fp, "wire [0:%d] mux2_l%d_in; \n", spice_mux_arch.num_input - 1, 1); /* input0 */
fprintf(fp, "wire [0:%d] mux2_l%d_in; \n", 0, 0); /* output */
/* Instanciate local encoder circuit here */
if ( (TRUE == spice_model.design_tech_info.mux_info->local_encoder)
&& ( 2 < spice_mux_arch.num_input) ) {
/* Get the number of inputs */
int num_outputs = spice_mux_arch.num_input;
int num_inputs = determine_mux_local_encoder_num_inputs(num_outputs);
/* Print local wires for local encoders */
fprintf(fp, "wire [0:%d] %s_data;\n",
spice_mux_arch.num_input - 1,
sram_port[0]->prefix);
fprintf(fp, "wire [0:%d] %s_data_inv;\n",
spice_mux_arch.num_input - 1,
sram_port[0]->prefix);
/* Find the decoder name */
fprintf(fp, "%s %s_0_ (",
generate_verilog_decoder_subckt_name(num_inputs, num_outputs),
generate_verilog_decoder_subckt_name(num_inputs, num_outputs));
if (true == is_explicit_mapping) {
fprintf(fp, ".addr(%s), .data(%s_data), .data_inv(%s_data_inv) );\n",
sram_port[0]->prefix,
sram_port[0]->prefix,
sram_port[0]->prefix);
} else {
fprintf(fp, "%s, %s_data, %s_data_inv);\n",
sram_port[0]->prefix,
sram_port[0]->prefix,
sram_port[0]->prefix);
}
}
fprintf(fp, "%s mux_basis (\n", mux_basis_subckt_name); /* given_name */
/* Dump global ports */
if (0 < rec_dump_verilog_spice_model_global_ports(fp, &spice_model, FALSE, FALSE,
@ -1740,38 +1771,6 @@ void dump_verilog_cmos_mux_onelevel_structure(FILE* fp,
}
fprintf(fp, "\n");
fprintf(fp, ");\n");
if (2 < spice_mux_arch.num_input) {
/* Instanciate local encoder circuit here */
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
/* Get the number of inputs */
int num_outputs = spice_mux_arch.num_input - 1;
int num_inputs = determine_mux_local_encoder_num_inputs(num_outputs);
/* Print local wires for local encoders */
fprintf(fp, "wire [%d:0] %s_data;\n",
spice_mux_arch.num_input - 1,
sram_port[0]->prefix);
fprintf(fp, "wire [%d:0] %s_data_inv;\n",
spice_mux_arch.num_input - 1,
sram_port[0]->prefix);
/* Find the decoder name */
fprintf(fp, "%s %s_0_ (",
generate_verilog_decoder_subckt_name(num_inputs, num_outputs),
generate_verilog_decoder_subckt_name(num_inputs, num_outputs));
if (true == is_explicit_mapping) {
fprintf(fp, ".addr(%s), .data(%s_data), .data_inv(%s_data_inv) );\n",
sram_port[0]->prefix,
sram_port[0]->prefix,
sram_port[0]->prefix);
} else {
fprintf(fp, "%s, %s_data, %s_data_inv);\n",
sram_port[0]->prefix,
sram_port[0]->prefix,
sram_port[0]->prefix);
}
}
}
return;
}
@ -2870,9 +2869,8 @@ void dump_verilog_submodule_muxes(t_sram_orgz_info* cur_sram_orgz_info,
* Outputs
*
* The outputs are assumes to be one-hot codes (at most only one '1' exist)
* Considering this fact, there are only num_of_outputs + 1 conditions to be encoded.
* Therefore, the number of inputs is ceil(log(num_of_outputs+1)/log(2))
* We plus 1, which is all-zero condition for outputs
* Considering this fact, there are only num_of_outputs conditions to be encoded.
* Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2))
***************************************************************************************/
static
void dump_verilog_mux_local_encoder_module(FILE* fp, int num_outputs) {
@ -2901,7 +2899,8 @@ void dump_verilog_mux_local_encoder_module(FILE* fp, int num_outputs) {
0, num_inputs - 1);
fprintf(fp, ",\n");
/* Outputs */
dump_verilog_generic_port(fp, VERILOG_PORT_OUTPUT,
fprintf(fp, "output ");
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
"data",
0, num_outputs - 1);
fprintf(fp, ",\n");
@ -2910,11 +2909,6 @@ void dump_verilog_mux_local_encoder_module(FILE* fp, int num_outputs) {
0, num_outputs - 1);
fprintf(fp, "\n);\n");
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
"data_reg",
0, num_outputs - 1);
fprintf(fp, ";\n");
/* Print the truth table of this encoder */
/* Internal logics */
/* We use a magic number -1 as the addr=1 should be mapped to ...1
@ -2925,23 +2919,27 @@ void dump_verilog_mux_local_encoder_module(FILE* fp, int num_outputs) {
* will give a all-zero code
* For example:
* data is 5-bit while addr is 3-bit
* data=8'b0_0000 is reserved by addr=3'b000;
* data=8'b0_0001 will be encoded to addr=3'b001;
* data=8'b0_0010 will be encoded to addr=3'b010;
* data=8'b0_0100 will be encoded to addr=3'b011;
* data=8'b0_1000 will be encoded to addr=3'b100;
* data=8'b1_0000 will be encoded to addr=3'b101;
* data=8'b0_0000 will be encoded to addr=3'b001;
* data=8'b0_0001 will be encoded to addr=3'b010;
* data=8'b0_0010 will be encoded to addr=3'b011;
* data=8'b0_0100 will be encoded to addr=3'b100;
* data=8'b0_1000 will be encoded to addr=3'b101;
* data=8'b1_0000 will be encoded to addr=3'b110;
* The rest of addr codes 3'b110, 3'b111 will be decoded to data=8'b0_0000;
*/
fprintf(fp, "always@(addr, data)\n");
fprintf(fp, "begin\n");
fprintf(fp, "\tdata_reg = %d'b0;\n", num_outputs);
fprintf(fp, "\tif ((0 < addr) && (addr < %d) ) begin\n", num_outputs);
fprintf(fp, "\t\tdata_reg = 1'b1 << (addr - 1);\n");
fprintf(fp, "\tend\n");
fprintf(fp, "end\n");
fprintf(fp, "assign data = data_reg;\n");
fprintf(fp, "always@(addr)\n");
fprintf(fp, "case (addr)\n");
/* Create a string for addr and data */
for (int i = 0; i < num_outputs; ++i) {
fprintf(fp, "\t%d'b%s : data = %d'b%s;\n",
num_inputs, my_itobin(i, num_inputs),
num_outputs, my_ito1hot(i, num_outputs));
}
fprintf(fp, "\tdefault : data = %d'b%s;\n",
num_outputs, my_ito1hot(num_outputs - 1, num_outputs));
fprintf(fp, "endcase\n");
fprintf(fp, "assign data_inv = ~data;\n");