2021-02-28 18:59:56 +03:00

169 lines
4.3 KiB
Systemverilog

`timescale 1ns/100ps
`default_nettype none
`include "assert.vh"
module fig_ring #(parameter POINT_COUNT = 32,
parameter FADING = 1)
(input wire clock,
input wire reset,
input wire [7:0] pt_x,
input wire [7:0] pt_y,
input wire [7:0] pt_h,
input wire pt_req_i,
output reg pt_ack_o,
output reg [7:0] fig_x_o,
output reg [8:0] fig_y_o,
output reg [7:0] fig_h_o,
output reg [7:0] fig_s_o,
output reg [7:0] fig_v_o,
output reg fig_req_o,
input wire fig_ack_i);
initial begin
`assert(POINT_COUNT > 0);
`assert(POINT_COUNT == (1 << $clog2(POINT_COUNT)));
end
/* Points coordinate RAM */
localparam POINT_CW = $clog2(POINT_COUNT);
localparam [7:0] V_INC = FADING == 0 ? 8'd255 : 8'('h100 / POINT_COUNT);
logic [23:0] pt_ram[POINT_COUNT];
logic [POINT_CW-1:0] pt_raddr;
logic [POINT_CW-1:0] pt_waddr;
logic pt_wr;
logic [7:0] pt_xw, pt_xr;
logic [7:0] pt_yw, pt_yr;
logic [7:0] pt_hw, pt_hr;
always_ff @ (posedge clock) begin
if (pt_wr)
pt_ram[pt_waddr] <= {pt_hw, pt_xw, pt_yw};
{pt_hr, pt_xr, pt_yr} <= pt_ram[pt_raddr];
end
`ifdef TESTBENCH
integer i;
initial
for (i = 0; i < POINT_COUNT; i ++)
pt_ram[i] = {8'(i*5), 8'(i*5 + 20), 8'(i*5 + 30)};
`endif
/* FSM */
enum int unsigned {
ST_IDLE = 0, // 0
ST_READ_LAST_PT, // 1
ST_STORE_LAST_PT, // 2
ST_WRITE_NEW_PT, // 3
ST_DRAW_LAST, // 4
ST_FIG_DRAW, // 5
ST_NEXT_PT, // 6
ST_READ_PT, // 7
ST_STORE_PT, // 8
ST_ACK // 9
} state;
logic [POINT_CW-1:0] pt_last;
assign pt_xw = pt_x;
assign pt_yw = pt_y;
assign pt_hw = pt_h;
always_ff @ (posedge clock, posedge reset)
if (reset) begin
state <= ST_IDLE;
pt_wr <= 1'b0;
pt_last <= '0;
pt_ack_o <= 1'b0;
fig_req_o <= 1'b0;
end
else
case (state)
ST_IDLE: begin
if (pt_req_i) begin
pt_raddr <= pt_last;
pt_waddr <= pt_last;
pt_wr <= 1'b0;
fig_v_o <= '0;
state <= ST_READ_LAST_PT;
end
end
ST_READ_LAST_PT:
state <= ST_STORE_LAST_PT;
ST_STORE_LAST_PT: begin
fig_x_o <= pt_xr;
fig_y_o <= {1'b0, pt_yr};
fig_h_o <= pt_hr;
fig_s_o <= 8'hff; // TODO: add saturation to ring mem
pt_wr <= 1'b1;
state <= ST_WRITE_NEW_PT;
end
ST_WRITE_NEW_PT: begin
pt_wr <= 1'b0;
fig_req_o <= 1'b1;
pt_raddr <= pt_last + 1'b1;
state <= ST_DRAW_LAST;
end
ST_DRAW_LAST:
if (fig_ack_i) begin
fig_req_o <= 1'b0;
state <= ST_READ_PT;
end
ST_FIG_DRAW: begin
fig_req_o <= 1'b1;
state <= ST_NEXT_PT;
end
ST_NEXT_PT:
if (fig_ack_i) begin
fig_req_o <= 1'b0;
if (pt_raddr == pt_last) begin
pt_last <= pt_last + 1'b1;
pt_ack_o <= 1'b1;
state <= ST_ACK;
end
else begin
if (pt_raddr == POINT_CW'(POINT_COUNT-1))
pt_raddr <= '0;
else
pt_raddr <= pt_raddr + 1'b1;
state <= ST_READ_PT;
end
end
ST_READ_PT:
state <= ST_STORE_PT;
ST_STORE_PT: begin
fig_x_o <= pt_xr;
fig_y_o <= {1'b0, pt_yr};
fig_h_o <= pt_hr;
fig_s_o <= 8'hff; // TODO: add saturation to ring mem
if (fig_v_o > (255-V_INC))
fig_v_o <= 8'hff;
else
fig_v_o <= fig_v_o + V_INC;
state <= ST_FIG_DRAW;
end
ST_ACK: begin
pt_ack_o <= 1'b0;
state <= ST_IDLE;
end
endcase
endmodule // fig_ring