Gowin Vol.3 第3部第2章 リスト1

`timescale 1ns / 1ps
`default_nettype none

module linebuffer #(
parameter int DATA_WIDTH = 10,
parameter int MAX_DATA_LENGTH = 1024
)(
input wire clk,

input wire vsync_i,
input wire de_i,
input wire [DATA_WIDTH-1:0] data_i,

output logic de_o,
output logic [DATA_WIDTH-1:0] data0_o,
output logic [DATA_WIDTH-1:0] data1_o,
output logic [DATA_WIDTH-1:0] data2_o
);

localparam int MAX_DATA_WIDTH = $clog2(MAX_DATA_LENGTH);

logic [DATA_WIDTH-1:0] data0_buf[0:MAX_DATA_LENGTH-1];
logic [DATA_WIDTH-1:0] data1_buf[0:MAX_DATA_LENGTH-1];
logic data_buf_w;
logic de_d;
logic [MAX_DATA_WIDTH-1:0] hcount;
logic vcount;

logic negedge_de;

always_comb begin
negedge_de = ((de_d == 1’b1) & ( de_i == 1’b0 ));
end

always_ff @(posedge clk) begin
if ( vsync_i ) begin
data_buf_w <= #1 1’b0;
end else begin
if ( negedge_de ) begin
data_buf_w <= #1 ~data_buf_w;
end
end

de_d <= #1 de_i;
end

always_ff @(posedge clk) begin
if ( de_i ) begin
if ( data_buf_w == 1’b0 ) begin
data0_buf[hcount] <= #1 data_i;
end else begin
data1_buf[hcount] <= #1 data_i;
end
end
end

always_ff @(posedge clk) begin
if ( vsync_i ) begin
vcount <= #1 1’b0;
end else begin
if ( negedge_de ) begin
vcount <= #1 1’b1;
end
end
end

logic de_o_w;

always_comb begin
de_o_w = (vcount & de_i);
end

always_ff @(posedge clk) begin
de_o <= #1 de_o_w;
end

always_ff @(posedge clk) begin
if ( de_o_w ) begin
if ( data_buf_w == 1’b0 ) begin
data1_o <= #1 data1_buf[hcount];
data0_o <= #1 data0_buf[hcount];
end else begin
data1_o <= #1 data0_buf[hcount];
data0_o <= #1 data1_buf[hcount];
end
data2_o <= #1 data_i;
end
end

always_ff @(posedge clk) begin
if ( vsync_i ) begin
hcount <= #1 MAX_DATA_WIDTH'(0);
end else if ( de_i ) begin
hcount <= #1 hcount + MAX_DATA_WIDTH'(1);
end else begin
hcount <= #1 MAX_DATA_WIDTH'(0);
end
end

`ifdef DEBUG_MAX_DATA_WIDTH
initial
begin
$display(MAX_DATA_WIDTH);
end
`endif

endmodule

`default_nettype wire