Skip to content

Instantly share code, notes, and snippets.

@hugoferreira
Created November 18, 2021 22:20
Show Gist options
  • Save hugoferreira/46608defe94215d36fafcad1bf6d4d69 to your computer and use it in GitHub Desktop.
Save hugoferreira/46608defe94215d36fafcad1bf6d4d69 to your computer and use it in GitHub Desktop.
Comparison of HVSync Generator in Chisel and Hand-written SystemVerilog
import chisel3._
def bits(x: Int) = Math.ceil((Math.log(x) / Math.log(2))).toInt
class hvsync_generator(
h_display: Int, h_back: Int, h_front: Int, h_sync: Int,
v_display: Int, v_top: Int, v_bottom: Int, v_sync: Int) extends Module {
val h_sync_start = h_display + h_front
val h_sync_end = h_display + h_front + h_sync - 1
val h_max = h_display + h_back + h_front + h_sync - 1
val v_sync_start = v_display + v_bottom
val v_sync_end = v_display + v_bottom + v_sync - 1
val v_max = v_display + v_top + v_bottom + v_sync - 1
val io = IO(new Bundle {
val hsync = Output(Bool())
val vsync = Output(Bool())
val hpos = Output(UInt(bits(h_max).W))
val vpos = Output(UInt(bits(v_max).W))
val display_on = Output(Bool())
})
val hpos = RegNext(io.hpos, 0.U)
val vpos = RegNext(io.vpos, 0.U)
val hsync = RegNext(io.hsync, false.B)
val vsync = RegNext(io.vsync, false.B)
when(hpos === h_max.U) {
hpos := 0.U
vpos := Mux(vpos === v_max.U, 0.U, vpos + 1.U)
}.otherwise {
hpos := hpos + 1.U
}
io.hpos := hpos
io.vpos := vpos
io.hsync := (hpos >= h_sync_start.U) && (hpos <= h_sync_end.U)
io.vsync := (vpos >= v_sync_start.U) && (vpos <= v_sync_end.U)
io.display_on := (hpos < h_display.U) && (vpos < v_display.U)
}
println(getVerilogString(new hvsync_generator(640, 48, 16, 96, 480, 33, 10, 2)))
module hvsync_generator(
input clock,
input reset,
output io_hsync,
output io_vsync,
output [9:0] io_hpos,
output [9:0] io_vpos,
output io_display_on
);
`ifdef RANDOMIZE_REG_INIT
reg [31:0] _RAND_0;
reg [31:0] _RAND_1;
`endif // RANDOMIZE_REG_INIT
reg [9:0] hpos; // @[hvsyncgenerator.worksheet.sc 33:21]
reg [9:0] vpos; // @[hvsyncgenerator.worksheet.sc 34:21]
wire [9:0] _T_3 = vpos + 10'h1; // @[hvsyncgenerator.worksheet.sc 40:45]
wire [9:0] _T_6 = hpos + 10'h1; // @[hvsyncgenerator.worksheet.sc 42:18]
assign io_hsync = hpos >= 10'h290 & hpos <= 10'h2ef; // @[hvsyncgenerator.worksheet.sc 47:40]
assign io_vsync = vpos >= 10'h1ea & vpos <= 10'h1eb; // @[hvsyncgenerator.worksheet.sc 48:40]
assign io_hpos = hpos; // @[hvsyncgenerator.worksheet.sc 45:11]
assign io_vpos = vpos; // @[hvsyncgenerator.worksheet.sc 46:11]
assign io_display_on = hpos < 10'h280 & vpos < 10'h1e0; // @[hvsyncgenerator.worksheet.sc 49:41]
always @(posedge clock) begin
if (reset) begin // @[hvsyncgenerator.worksheet.sc 33:21]
hpos <= 10'h0; // @[hvsyncgenerator.worksheet.sc 33:21]
end else if (hpos == 10'h31f) begin // @[hvsyncgenerator.worksheet.sc 38:26]
hpos <= 10'h0; // @[hvsyncgenerator.worksheet.sc 39:10]
end else begin
hpos <= _T_6; // @[hvsyncgenerator.worksheet.sc 42:10]
end
if (reset) begin // @[hvsyncgenerator.worksheet.sc 34:21]
vpos <= 10'h0; // @[hvsyncgenerator.worksheet.sc 34:21]
end else if (hpos == 10'h31f) begin // @[hvsyncgenerator.worksheet.sc 38:26]
if (vpos == 10'h20c) begin // @[hvsyncgenerator.worksheet.sc 40:16]
vpos <= 10'h0;
end else begin
vpos <= _T_3;
end
end else begin
vpos <= io_vpos; // @[hvsyncgenerator.worksheet.sc 34:21]
end
end
// Register and memory initialization
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifndef RANDOM
`define RANDOM $random
`endif
`ifdef RANDOMIZE_MEM_INIT
integer initvar;
`endif
`ifndef SYNTHESIS
`ifdef FIRRTL_BEFORE_INITIAL
`FIRRTL_BEFORE_INITIAL
`endif
initial begin
`ifdef RANDOMIZE
`ifdef INIT_RANDOM
`INIT_RANDOM
`endif
`ifndef VERILATOR
`ifdef RANDOMIZE_DELAY
#`RANDOMIZE_DELAY begin end
`else
#0.002 begin end
`endif
`endif
`ifdef RANDOMIZE_REG_INIT
_RAND_0 = {1{`RANDOM}};
hpos = _RAND_0[9:0];
_RAND_1 = {1{`RANDOM}};
vpos = _RAND_1[9:0];
`endif // RANDOMIZE_REG_INIT
`endif // RANDOMIZE
end // initial
`ifdef FIRRTL_AFTER_INITIAL
`FIRRTL_AFTER_INITIAL
`endif
`endif // SYNTHESIS
endmodule
module hvsync_generator(
input logic clk, input logic reset, output logic hsync, output logic vsync,
output logic display_on, output logic [7:0] hpos, output logic [6:0] vpos);
// horizontal constants
parameter H_DISPLAY = 480; // horizontal display width
parameter H_BACK = 16; // horizontal left border (back porch)
parameter H_FRONT = 48; // horizontal right border (front porch)
parameter H_SYNC = 96; // horizontal sync width
// vertical constants
parameter V_DISPLAY = 480; // vertical display height
parameter V_TOP = 33; // vertical top border
parameter V_BOTTOM = 10; // vertical bottom border
parameter V_SYNC = 2; // vertical sync # lines
// derived constants
parameter H_SYNC_START = H_DISPLAY + H_FRONT;
parameter H_SYNC_END = H_DISPLAY + H_FRONT + H_SYNC - 1;
parameter H_MAX = H_DISPLAY + H_BACK + H_FRONT + H_SYNC - 1;
parameter V_SYNC_START = V_DISPLAY + V_BOTTOM;
parameter V_SYNC_END = V_DISPLAY + V_BOTTOM + V_SYNC - 1;
parameter V_MAX = V_DISPLAY + V_TOP + V_BOTTOM + V_SYNC - 1;
wire hmaxxed = (hpos === H_MAX) | reset; // set when hpos is maximum
wire vmaxxed = (vpos === V_MAX) | reset; // set when vpos is maximum
// horizontal position counter
always_ff @(posedge clk)
begin
hsync <= (hpos >= H_SYNC_START && hpos <= H_SYNC_END);
if (hmaxxed) hpos <= 0;
else hpos <= hpos + 1;
end
// vertical position counter
always_ff @(posedge clk)
begin
vsync <= (vpos >= V_SYNC_START && vpos <= V_SYNC_END);
if (hmaxxed)
if (vmaxxed) vpos <= 0;
else vpos <= vpos + 1;
end
// display_on is set when beam is in "safe" visible frame
assign display_on = (hpos < H_DISPLAY) && (vpos < V_DISPLAY);
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment