1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-01-28 07:02:55 +08:00
Konstantin Pavlov (pt) 40533743d7 Added altera cookbook
2015-12-15 22:44:58 +03:00

229 lines
6.0 KiB
Verilog

// Copyright 2009 Altera Corporation. All rights reserved.
// Altera products are protected under numerous U.S. and foreign patents,
// maskwork rights, copyrights and other intellectual property laws.
//
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design
// License Agreement (either as signed by you or found at www.altera.com). By
// using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation. In the event that you do
// not agree with such terms and conditions, you may not use the reference
// design file and please promptly destroy any copies you have made.
//
// This reference design file is being provided on an "as-is" basis and as an
// accommodation and therefore all warranties, representations or guarantees of
// any kind (whether express, implied or statutory) including, without
// limitation, warranties of merchantability, non-infringement, or fitness for
// a particular purpose, are specifically disclaimed. By making this reference
// design file available, Altera expressly does not recommend, suggest or
// require that this reference design file be used in combination with any
// other product not provided by Altera.
/////////////////////////////////////////////////////////////////////////////
// baeckler - 03-13-2009
// little state machine to scanout a binary
// font character to raster writes
module display_char #(
parameter RASTER_ADDR_WIDTH = 18,
parameter RASTER_LINE_WIDTH = 640,
parameter RASTER_DATA_WIDTH = 16,
parameter FONT_DATA_WIDTH = 24,
parameter FONT_HEIGHT = 27,
parameter FONT_ADDR_WIDTH = 11
)(
input clk,arst,
input [9:0] raster_x,
input [9:0] raster_y,
input [7:0] char_select,
input [RASTER_DATA_WIDTH-1:0] wdata,
output busy,
input start_write,
output reg [RASTER_ADDR_WIDTH-1:0] raster_addr,
output reg [RASTER_DATA_WIDTH-1:0] raster_data,
output reg raster_we
);
`include "log2.inc"
localparam PIXEL_CNT_WIDTH = log2(FONT_DATA_WIDTH);
localparam LINE_CNT_WIDTH = log2(FONT_HEIGHT);
function [FONT_DATA_WIDTH-1:0] reverse_font;
input [FONT_DATA_WIDTH-1:0] din;
integer n;
for (n=0; n<FONT_DATA_WIDTH; n=n+1) begin : foo
reverse_font[n] = din[FONT_DATA_WIDTH-1-n];
end
endfunction
/////////////////////////////////////////
// Convert user input to raw addr
/////////////////////////////////////////
reg [RASTER_ADDR_WIDTH-1:0] raster_start;
reg [FONT_ADDR_WIDTH-1:0] char_start;
reg start_write_d;
always @(posedge clk or posedge arst) begin
if (arst) begin
char_start <= 0;
raster_start <= 0;
start_write_d <= 0;
end
else begin
char_start <= char_select * FONT_HEIGHT;
raster_start <= raster_x + raster_y * RASTER_LINE_WIDTH;
start_write_d <= start_write;
end
end
/////////////////////////////////////////
// Font ROM
/////////////////////////////////////////
reg [FONT_ADDR_WIDTH-1:0] font_addr;
wire [FONT_DATA_WIDTH-1:0] font_data;
font_rom fr (
.clk(clk),
.addr(font_addr),
.out(font_data)
);
/////////////////////////////////////////
// Index into the font data
/////////////////////////////////////////
reg load_start_address;
reg [PIXEL_CNT_WIDTH-1:0] pixel_idx;
reg [LINE_CNT_WIDTH-1:0] char_line;
reg addr_valid, addr_valid_d, addr_valid_dd, char_complete;
// these are offset slightly to cancel the
// font ROM latency
wire pixel_idx_max = (pixel_idx == (FONT_DATA_WIDTH-1));
wire pixel_idx_short = (pixel_idx == (FONT_DATA_WIDTH-3));
always @(posedge clk or posedge arst) begin
if (arst) begin
font_addr <= 0;
pixel_idx <= 0;
char_line <= 0;
addr_valid <= 1'b0;
addr_valid_d <= 1'b0;
addr_valid_dd <= 1'b0;
char_complete <= 1'b1;
end
else begin
if (load_start_address) begin
font_addr <= char_start;
pixel_idx <= FONT_DATA_WIDTH-4'd2;
char_line <= 0;
addr_valid <= 1'b1;
addr_valid_d <= 1'b0;
addr_valid_dd <= 1'b0;
char_complete <= 1'b0;
end
else begin
addr_valid_d <= addr_valid;
addr_valid_dd <= addr_valid_d;
if (pixel_idx_max) pixel_idx <= 0;
else pixel_idx <= pixel_idx + 1'b1;
if (pixel_idx_short) begin
font_addr <= font_addr + 1'b1;
char_line <= char_line + 1'b1;
if (char_line == (FONT_HEIGHT-1)) begin
addr_valid <= 1'b0;
char_complete <= 1'b1;
end
end
end
end
end
/////////////////////////////////////////
// combine to font bit stream
/////////////////////////////////////////
reg font_bit, font_bit_valid, font_eol;
wire [FONT_DATA_WIDTH-1:0] rev_font_data = reverse_font (font_data);
always @(posedge clk or posedge arst) begin
if (arst) begin
font_bit <= 1'b0;
font_bit_valid <= 1'b0;
font_eol <= 1'b0;
end
else begin
font_bit <= rev_font_data [pixel_idx];
font_bit_valid <= addr_valid_dd;
font_eol <= pixel_idx_max;
end
end
/////////////////////////////////////////
// Translate font bitstream to raster
/////////////////////////////////////////
always @(posedge clk or posedge arst) begin
if (arst) begin
raster_addr <= 0;
raster_data <= 0;
raster_we <= 0;
end
else begin
if (load_start_address) begin
raster_addr <= raster_start;
end
else begin
if (font_bit_valid) begin
if (font_eol) begin
raster_addr <= raster_addr +
RASTER_LINE_WIDTH -
FONT_DATA_WIDTH + 1;
end
else begin
raster_addr <= raster_addr + 1'b1;
end
raster_data <= font_bit ? wdata : 0;
raster_we <= font_bit;
end
end
end
end
/////////////////////////////////////////
// Control state machine
/////////////////////////////////////////
localparam ST_WAIT = 1'b0, ST_WRITE = 1'b1;
reg state,next_state;
always @(*) begin
next_state = state;
load_start_address = 1'b0;
case (state)
ST_WAIT : begin
load_start_address = 1'b1;
if (start_write_d) next_state = ST_WRITE;
end
ST_WRITE : begin
if (char_complete) next_state = ST_WAIT;
end
endcase
end
assign busy = (state != ST_WAIT);
always @(posedge clk or posedge arst) begin
if (arst) state <= ST_WAIT;
else state <= next_state;
end
endmodule