Denormalizing an OrderedDict to CSV
tmp.update({k:v}) is an unusual way to perform tmp[k] = v
Take advantage of the max builtin:

max_len = max(len(v) for v in dic.values() if isinstance(v, list))

To make the code easier to follow, you could first transform the dictionary to give it a consistent structure like this

{'k1': ['v1', 'v1', 'v1', 'v1'],
 'k2': ['v2', 'v2', 'v2', 'v2'],
 'k3a': [21, 23],
 'k3b': [22, 24],
 'k4': [1, 2, 3, 4]}                


using code like this

mapped = collections.OrderedDict()
for key, value in dic.items():
    if key in mapping:
        for sublist in value:
            for subkey, subvalue in sublist:
                mapped.setdefault(subkey, []).append(subvalue)
    elif isinstance(value, list):
        mapped[key] = value
    else:
        mapped[key] = max_len * [value]

Then you can take advantage of itertools.zip_longest to produce the output:

with open("out.csv", "w", newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(list(mapped.keys()))
    writer.writerows(itertools.zip_longest(*mapped.values(), fillvalue=''))