Skip to content

Instantly share code, notes, and snippets.

@zoldar
Created December 1, 2023 21:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zoldar/20169bb40dc21bea41295f0dca4444f6 to your computer and use it in GitHub Desktop.
Save zoldar/20169bb40dc21bea41295f0dca4444f6 to your computer and use it in GitHub Desktop.
module top (
input CLK,
input BTN_N,
input BTN1,
output P1A1,
output P1A2,
output P1A3,
output P1A4,
output P1A7,
output P1A8,
output P1A9,
output P1A10
);
parameter MEMORY_INPUT = "input.hex";
SOC #(.MEMORY_INPUT(MEMORY_INPUT))SoC(
.CLK(CLK),
.RESET(!BTN_N),
.BUTTON(BTN1),
.segment_select(P1A10),
.segment_display({P1A9, P1A8, P1A7, P1A4, P1A3, P1A2, P1A1})
);
endmodule
module SOC (
input CLK,
input RESET,
input BUTTON,
output segment_select,
output [6:0] segment_display
);
parameter MEMORY_INPUT = "input.hex";
// Segment display
reg [7:0] segment_number = 8'b0;
// Main internal clock divider
wire disp_clk;
Clockworks #(
.SLOW(2)
)DispClk(
.CLK(CLK),
.clk(disp_clk)
);
SegmentDisplay SEGDISP(
.CLK(disp_clk),
.NUMBER(segment_number),
.digit_sel(segment_select),
.seg_pins_n(segment_display)
);
// Memory
reg [31:0] mem_addr = 32'b0;
wire [7:0] char;
Memory #(
.MEMORY_SIZE_KB(8),
.MEMORY_HEXFILE(MEMORY_INPUT)
)CharMem(
.CLK(CLK),
.ADDR(mem_addr),
.rdata(char)
);
wire lowDigitPrefix = char[7:3] == 5'b00110;
wire highDigitPrefix = char[7:3] == 5'b00111;
wire isCharDigit = lowDigitPrefix | (highDigitPrefix & (char[2:0] == 3'b000 | char[2:0] == 3'b001));
wire isCharNewLine = char == 10;
wire [3:0] digit = char[3:0];
reg [3:0] firstDigit = 'ha;
reg [3:0] lastDigit = 'ha;
reg [31:0] sum = 32'b0;
localparam WAIT_DATA = 0;
localparam EXECUTE = 1;
localparam FINISH = 2;
reg [2:0] state = WAIT_DATA;
always @(posedge CLK)
begin
if (RESET)
begin
state = WAIT_DATA;
segment_number = 8'b0;
mem_addr = 32'b0;
firstDigit <= 'ha;
lastDigit <= 'ha;
sum <= 0;
end
else
begin
case (state)
WAIT_DATA:
begin
state <= EXECUTE;
// $display($time,, "firstDigit = %h, lastDigit = %h", firstDigit, lastDigit);
// $display($time,, "sum = %h", sum);
end
EXECUTE:
begin
// $display($time,, "char = %b, isCharDigit = %b, isCharNewLine = %b", char, isCharDigit, isCharNewLine);
if (isCharNewLine | char == 8'b0)
begin
sum <= sum + ({28'b0, firstDigit} << 3) + ({28'b0, firstDigit} << 1) + {28'b0, lastDigit};
firstDigit <= 'ha;
lastDigit <= 'ha;
end
else if (isCharDigit)
begin
if (firstDigit == 'ha)
firstDigit <= digit;
lastDigit <= digit;
end
if (char != 8'b0)
begin
mem_addr <= mem_addr + 1;
state <= WAIT_DATA;
end
else
begin
state <= FINISH;
end
end
FINISH:
begin
// $display($time,, "final sum=%h", sum);
segment_number <= sum[7:0];
end
endcase
end
end
endmodule
module SegmentDisplay (
input CLK,
input [7:0] NUMBER,
output reg digit_sel,
output reg [6:0] seg_pins_n
);
wire [6:0] tens;
wire [6:0] ones;
initial
begin
digit_sel = 1'b0;
end
wire [3:0] digit = digit_sel ? NUMBER[3:0] : NUMBER[7:4];
wire [6:0] segments = digit_sel? ones : tens;
SevenSeg SegTens(
.CLK(CLK),
.DIGIT(digit),
.segments(tens)
);
SevenSeg SegOnes(
.CLK(CLK),
.DIGIT(digit),
.segments(ones)
);
always @(posedge CLK)
begin
seg_pins_n <= ~segments;
digit_sel <= !digit_sel;
end
endmodule
module SevenSeg(
input CLK,
input [3:0] DIGIT,
output reg [6:0] segments
);
initial
begin
segments = 7'b0111111;
end
always @(posedge CLK)
begin
case (DIGIT)
0:
segments <= 7'b0111111;
1:
segments <= 7'b0000110;
2:
segments <= 7'b1011011;
3:
segments <= 7'b1001111;
4:
segments <= 7'b1100110;
5:
segments <= 7'b1101101;
6:
segments <= 7'b1111101;
7:
segments <= 7'b0000111;
8:
segments <= 7'b1111111;
9:
segments <= 7'b1101111;
4'hA:
segments <= 7'b1110111;
4'hB:
segments <= 7'b1111100;
4'hC:
segments <= 7'b0111001;
4'hD:
segments <= 7'b1011110;
4'hE:
segments <= 7'b1111001;
4'hF:
segments <= 7'b1110001;
endcase
end
endmodule
module Clockworks (
input CLK,
output clk
);
parameter SLOW = 0;
reg [SLOW:0] slow_CLK = 0;
always @(posedge CLK)
begin
slow_CLK <= slow_CLK + 1;
end
assign clk = slow_CLK[SLOW];
endmodule
module Memory (
input CLK,
input [31:0] ADDR,
output reg [7:0] rdata
);
initial
begin
rdata = 'hff;
end
parameter MEMORY_SIZE_KB = 4;
parameter MEMORY_HEXFILE = "input.hex";
// Memory
reg [7:0] MEM [0:((MEMORY_SIZE_KB * 1024) - 1)];
initial
begin
$readmemh(MEMORY_HEXFILE, MEM);
end
always @(posedge CLK)
begin
rdata <= MEM[ADDR];
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment