// This module converts display addresses to memory addresses // The input is (hcnt, vcnt) which is the x and y display coordinates // The output is (memx, memy) which is the x and y coordinates in // memory. If there were a 1-1 correspondence, then (hcnt, vcnt) // would be passed straight through. This module allows panning, // with the origin of the image to be displayed kept in the // (xstart, ystart) register. // This register can be adjusted using the 3-bit pan input. See // the parameter statement below for the values this can take. The // pan value is used at the start of every frame to decide how to // change the origin register. // This module makes the assumption that hcnt is increased on every // clock cycle, a correct assumption. Thus we only look for when // hcnt == 0 (beginning of a line), and vcnt == 0 (beginning of a frame) // and assume we are displaying the next pixel on every clock // Note that there is a one-cycle delay from hcnt == 0 to memx == startx // There is another one-cycle delay from reading the pixel at memx to the // data output from memory. // We assert a read signal along with the address when we are in the part // of the display where we are actually displaying a pixel, ie. when we need // to read a pixel from memory. This will be used to blank the output when // we are not displaying a pixel. module pan (clk, reset, xdata, writePan, hcnt, vcnt, memx, memy, read) ; input clk ; input reset; input [2:0] xdata ; // 3-bit control that allows the origin to be moved input writePan ; // Write the pan register input [9:0] hcnt ; // Display x coordinate (input) input [9:0] vcnt ; // Display y coordinate output [7:0] memx ; // Memory x coordinate (output) output [6:0] memy ; // Memory y coordinate output read; // Read signal to memory reg [8:0] xstart; // x and y of image origin reg [7:0] ystart; reg [12:0] curx; // Current x and y location, integer plus 4 fraction bits reg [11:0] cury; reg [2:0] panReg; // Pan register written by the XBUS parameter PanRight = 1, PanLeft = 2, PanDown = 3, PanUp = 4; assign memx = curx[11:4]; // memory x address is the integer part of curx assign memy = cury[10:4]; // memory y address is the integer part of cury assign read = (hcnt<256 && vcnt<128); // Image size is 256x128 always @(posedge clk) begin if (reset) begin xstart <= 0; ystart <= 0; panReg <= 0; end else if (hcnt==0 && vcnt==0) begin // start of frame case (panReg) PanRight: xstart <= xstart + 1; PanLeft: xstart <= xstart - 1; PanDown: ystart <= ystart + 1; PanUp: ystart <= ystart - 1; endcase curx <= {xstart, 4'b0}; cury <= {ystart, 4'b0}; end else if (hcnt==0) begin // start of line curx <= {xstart, 4'b0}; cury <= cury + 5'b10000; end else // in middle of line curx <= curx + 5'b10000; if (writePan) panReg <= xdata; end endmodule