Ok, you are curently telling the pixel writer the:
pixel_cmd[27:24] <= dest_bits_per_pixel[3:0];
This tells the pixel writer that a pixel is:
1 bit wide,
2 bits wide,
4 bits wide,
8 bits wide, or
16 bits wide.
Now, to work, the pixel writer needs a second bit of information. Remember when we set the video source or destination to 1 bit per pixel, the:
( y * dest_rast_width[15:0] + x ) << 1 ) >> LUT_bits_to_shift[dest_bits_per_pixel[3:0]]
is effectively divided by 16 (since we are eventually muting bit 0 in the address).
Now, since the address stays the same for every 16 pixels when in 1 bit pixel mode, we need to sub-shifts to the right bit position every 16 coordinates on the X/Y axis when in that 1 bit per pixel mode. The pixel writer still needs that sub-position location which shifts by 1 every 1 pixels while the provided address stays the same for every 16 pixels.
This is the:
pixel_cmd[23:20] <= target_bit; (You actually need 2 of them, a dest & srce target bit)
When in 1 bit mode, the pixel writer/reader will concentrate on the first 4 bits of the X coordinate which was lost from the address generator which was divided by 16 meaning:
dest_target_bit[3:0] = ( y * dest_rast_width[15:0] + x ) && 4'b1111;
srce_target_bit[3:0] = ( y * srce_rast_width[15:0] + x ) && 4'b1111;
Now, if x=0, the pixel writer knows to edit bits 15 in 1 bit mode.
Now, if x=1, the pixel writer knows to edit bits 14 in 1 bit mode.
Now, if x=2, the pixel writer knows to edit bits 13 in 1 bit mode.
Now, if x=3, the pixel writer knows to edit bits 12 in 1 bit mode.
Now, if x=4, the pixel writer knows to edit bits 11 in 1 bit mode.
In 2 bit mode, the pixel write knows to pay attention to the bottom 3 bits of the srce/dest_target_bit[3:0].
Now, if x=0, the pixel writer knows to edit bits 15..14 in 2 bit mode.
Now, if x=1, the pixel writer knows to edit bits 13..12 in 2 bit mode.
Now, if x=2, the pixel writer knows to edit bits 11..10 in 2 bit mode.
Now, if x=3, the pixel writer knows to edit bits 9..8 in 2 bit mode.
Now, if x=4, the pixel writer knows to edit bits 7..6 in 2 bit mode.
In 4 bit mode, the pixel write knows to pay attention to the bottom 2 bits of the srce/dest_target_bit[3:0].
Now, if x=0, the pixel writer knows to edit bits 15..12 in 4 bit mode.
Now, if x=1, the pixel writer knows to edit bits 11..8 in 4 bit mode.
Now, if x=2, the pixel writer knows to edit bits 7..4 in 4 bit mode.
Now, if x=3, the pixel writer knows to edit bits 3..0 in 4 bit mode.
Now, if x=4, the pixel writer knows to edit bits 15..12 in 4 bit mode. (remember, only the bottom 2 bits of x is used)
In 8 bit mode, the pixel write knows to pay attention to the bottom 1 bit of the srce/dest_target_bit[3:0].
Now, if x=0, the pixel writer knows to edit bits 15..8 in 8 bit mode.
Now, if x=1, the pixel writer knows to edit bits 7..0 in 8 bit mode.
Now, if x=2, the pixel writer knows to edit bits 15..8 in 8 bit mode.
Now, if x=3, the pixel writer knows to edit bits 7..0 in 8 bit mode.
Now, if x=4, the pixel writer knows to edit bits 15..8 in 8 bit mode.
In 16 bit mode, the pixel write knows to ignore the srce/dest_target_bit[3:0].
Now, if x=0, the pixel writer knows to edit all bits 15..0 in 16 bit mode.
Now, if x=1, the pixel writer knows to edit all bits 15..0 in 16 bit mode.
You've sort of done this before. Take a look at your 'bart.v' source code. It has:
colour_mode_in[2:0], similar to srce/dest_bits_per_pixel[3:0] with different values.
The difference is that it works using only the bottom 3 bits of the X coordinate, and in it works it's way toward bit x[2] as the bits per pixel increases.
With our pixel writer, we we work toward the bottom of the X coordinate bit, down to bit X[0] when we go up to 8 bit color and ignoring the srce/dest_target_bit all together when operating in 16 bit mode.
Like this: (beginning of lines 109, get rid of line 107)
dest_base_address_offset = ( ( y * dest_rast_width[15:0] + x ) << 1 ) >> LUT_bits_to_shift[dest_bits_per_pixel[3:0]] ;
srce_base_address_offset = ( ( y * srce_rast_width[15:0] + x ) << 1 ) >> LUT_bits_to_shift[srce_bits_per_pixel[3:0]] ;
dest_target_bit[3:0] = ( y * dest_rast_width[15:0] + x ) && 4'b1111;
srce_target_bit[3:0] = ( y * srce_rast_width[15:0] + x ) && 4'b1111;