Q138FreeSystemVerilog
Rotate a tile in place with one memory port
Interview prompt
Question
Rotate a loaded square pixel tile 90 degrees clockwise in place when the local row-major memory permits only one synchronous read or one write per cycle. PIX_W is positive. Accept n from 1 through 8, then load exactly n*n row-major pixels and assert load_last only on the final accepted pixel. Pulse start after loading. After done, issue reads only for addresses below n*n.
Candidate starting point
Implementation scaffold
module inplace_tile_rotator #(
parameter int unsigned PIX_W = 8
) (
input logic clk,
input logic rst_n,
input logic cfg_valid,
input logic [3:0] n,
input logic load_valid,
input logic load_last,
input logic [PIX_W-1:0] load_pixel,
input logic start,
input logic read_req,
input logic [5:0] read_addr,
output logic cfg_ready,
output logic load_ready,
output logic busy,
output logic done,
output logic read_valid,
output logic [PIX_W-1:0] read_pixel
);
typedef enum logic [3:0] {
S_CONFIG, S_LOAD, S_WAIT,
S_READ_A, S_READ_B, S_READ_C, S_READ_D,
S_WRITE_A, S_WRITE_B, S_WRITE_C, S_WRITE_D,
S_ADVANCE, S_READY
} state_t;
state_t state_q;
logic [PIX_W-1:0] mem_q [0:63];
logic [PIX_W-1:0] a_q, b_q, c_q, d_q;
logic [3:0] n_q;
logic [6:0] pixel_total_q;
logic [5:0] load_index_q;
logic [2:0] layer_q, offset_q;
logic [2:0] first_pos, last_pos;
logic [6:0] top_addr_w, right_addr_w, bottom_addr_w, left_addr_w;
always_comb begin : generate_orbit_addresses
// TODO: Implement generate_orbit_addresses using the supplied state and interface.
end
assign cfg_ready = (state_q == S_CONFIG) || (state_q == S_READY);
assign load_ready = (state_q == S_LOAD);
assign busy = (state_q >= S_READ_A) && (state_q <= S_ADVANCE);
always_ff @(posedge clk) begin : load_rotate_and_read
// TODO: Implement load_rotate_and_read using the supplied state and interface.
end
endmoduleReviewed example
Trace one case
Input
N=2; row-major tile = [1, 2, 3, 4]Expected output
row-major tile after rotation = [3, 1, 4, 2]Saving the complete four-pixel cycle before any write prevents the single-port in-place update from destroying a later source pixel.
What to cover
Requirements
- Support N from 1 to 8 and exactly N times N pixels loaded in row-major order.
- Use the mapping (row, col) -> (col, N - 1 - row) without allocating a second tile.
- Save all four pixels of each four-cell orbit across separate read cycles before writing any destination in that orbit.
- Use only a constant number of pixel registers and block external reads during rotation.
- After done, provide one-cycle external reads of the rotated row-major tile.
