Created
December 1, 2023 21:59
-
-
Save zoldar/20169bb40dc21bea41295f0dca4444f6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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