Week09 – Mojo V3 – Display 7_Segment and UART Tx








7 Segment

    7 Segment คือหน้าจอแสดงผลตัวเลข - ตัวอักษร ได้บางตัว ที่มีหน้าจอทำมาจากการจัดวางหลอด LED (แอล อี ดี) ในแนวยาว เมื่อทำให้หลอด LED แต่ละดวงติดพร้อมกัน ก็จะทำให้แสดงออกมาเป็นตัวเลขทรงเหลี่ยมได้


    จอแสดงผลแบบ 7 Segment นั้นประกอบไปด้วย 7 ส่วนซึ่งจะถูกทำการเปิดหรือปิดเพื่อแสดงรูปแบบของตัวเลขฐานสิบ 7 Segment จะถูกจัดเรียงเป็นรูปสี่เหลี่ยม โดยในแนวตั้งมีอยู่ด้านละ 2  แท่งและแนวนอนมีอยู่ 1 แท่ง 3 ชิ้น บน กลาง และล่าง แท่งแต่ละแท่งของ 7 Segment จะถูกอ้างอิงจากตัวอักษรตั้งแต่ A (เอ) ถึง G (จี) โดยที่ DP (ดี พี) จะเป็นแท่งที่ 8 ใช้สำหรับตัวเลขที่ไม่ใช่จำนวนเต็ม



Q01 – Ripple Adder 4 bit + 4 Bit = 1 + 4Bit


เป็นวงจรบวก (4bit  +  4bit)  แสดงออกทาง  7Segment

Create Schematic File

1.   Full Adder Logic
2.   Decode_7Seg Verilog File
Full Adder Logic

Decode_7Seg Verilog File


`timescale 1ns / 1ps 
module Decode_7Seg( D, C, B, A, ledt, leda, ledb, ledc, ledd, lede, ledf, ledg); 
input D, C, B, A; 
output ledt, leda, ledb, ledc, ledd, lede, ledf, ledg; 
reg [7:0] seg_data; 
reg [3:0] DataIn; 
always @* begin 
DataIn = { D, C, B, A }; 
end 
always @(DataIn) 
case (DataIn) 
4'b0000: seg_data = 8'b01111110; 
4'b0001: seg_data = 8'b00110000; 
4'b0010: seg_data = 8'b01101101; 
4'b0011: seg_data = 8'b01111001; 
4'b0100: seg_data = 8'b00110011; 
4'b0101: seg_data = 8'b01011011; 
4'b0110: seg_data = 8'b01011111; 
4'b0111: seg_data = 8'b01110000; 
4'b1000: seg_data = 8'b01111111; 
4'b1001: seg_data = 8'b01111011; 
4'b1010: seg_data = 8'b01110111; 
4'b1011: seg_data = 8'b00011111; 
4'b1100: seg_data = 8'b01001110; 
4'b1101: seg_data = 8'b00111101; 
4'b1110: seg_data = 8'b01001111; 
4'b1111: seg_data = 8'b01000111; 
Endcase 
assign ledt = ~seg_data[7]; // if Active Low(Using ~) 
assign leda = ~seg_data[6]; 
assign ledb = ~seg_data[5]; 
assign ledc = ~seg_data[4]; 
assign ledd = ~seg_data[3]; 
assign lede = ~seg_data[2]; 
assign ledf = ~seg_data[1]; 
assign ledg = ~seg_data[0]; 
endmodule 

Schematic 


Port Input/Output ucf File 

NET "A0" LOC = P2; 
NET "B0" LOC = P6; 
NET "A1" LOC = P8; 
NET "B1" LOC = P10; 
NET "A2" LOC = P12; 
NET "B2" LOC = P15; 
NET "A3" LOC = P17; 
NET "B3" LOC = P22; 
NET "S4" LOC = P11; 
NET "Seg_A"  LOC = P41 ; 
NET "Seg_B"  LOC = P27 ; 
NET "Seg_C"  LOC = P32 ; 
NET "Seg_D"  LOC = P40 ; 
NET "Seg_E"  LOC = P50 ; 
NET "Seg_F"  LOC = P35 ; 
NET "Seg_G"  LOC = P29 ; 
NET "Seg_T"  LOC = P34 ; 

การต่อวงจร 



Q02 – Carry Save Adder 4 number@3 bit 


เป็นวงจรบวก (3bit + 3bit + 3bit) แสดงออกทาง 7 segment 


Create Schematic File  

1.Full Adder Logic 
2. Decode_7Seg Verilog File 


Full Adder Logic

Decode_7Seg Verilog File

`timescale 1ns / 1ps 
module Decode_7Seg( D, C, B, A, ledt, leda, ledb, ledc, ledd, lede, ledf, ledg); 
input D, C, B, A; 
output ledt, leda, ledb, ledc, ledd, lede, ledf, ledg; 
reg [7:0] seg_data; 
reg [3:0] DataIn; 
always @* begin 
DataIn = { D, C, B, A }; 
end 
always @(DataIn) 
case (DataIn) 
4'b0000: seg_data = 8'b01111110; 
4'b0001: seg_data = 8'b00110000; 
4'b0010: seg_data = 8'b01101101; 
4'b0011: seg_data = 8'b01111001; 
4'b0100: seg_data = 8'b00110011; 
4'b0101: seg_data = 8'b01011011; 
4'b0110: seg_data = 8'b01011111; 
4'b0111: seg_data = 8'b01110000; 
4'b1000: seg_data = 8'b01111111; 
4'b1001: seg_data = 8'b01111011; 
4'b1010: seg_data = 8'b01110111; 
4'b1011: seg_data = 8'b00011111; 
4'b1100: seg_data = 8'b01001110; 
4'b1101: seg_data = 8'b00111101; 
4'b1110: seg_data = 8'b01001111; 
4'b1111: seg_data = 8'b01000111; 
Endcase 
assign ledt = ~seg_data[7]; // if Active Low(Using ~) 
assign leda = ~seg_data[6]; 
assign ledb = ~seg_data[5]; 
assign ledc = ~seg_data[4]; 
assign ledd = ~seg_data[3]; 
assign lede = ~seg_data[2]; 
assign ledf = ~seg_data[1]; 
assign ledg = ~seg_data[0]; 
endmodule 

Schematic 


Port Input/Output ucf File
NET "A0" LOC = P2; 
NET "A1" LOC = P6; 
NET "A2" LOC = P8; 
NET "B0" LOC = P10; 
NET "B1" LOC = P12; 
NET "B2" LOC = P15; 
NET "C0" LOC = P17; 
NET "C1" LOC = P22; 
NET "C2" LOC = P24; 
NET "D0" LOC = P27; 
NET "D1" LOC = P30; 
NET "D2" LOC = P33; 
NET "S4" LOC = P51; 
NET "ledt" LOC = P1; 
NET "leda" LOC = P5; 
NET "ledb" LOC = P7; 
NET "ledc" LOC = P9; 
NET "ledd" LOC = P11; 
NET "lede" LOC = P14; 
NET "ledf" LOC = P16; 
NET "ledg" LOC = P21; 

การต่อวงจร 



Q03 – Single Digit 7-Segment

Create Schematic File  

1. Gen_1Hz 
2. Decode_7Seg Verilog File 

Gen_1Hz 

`timescale 1ns / 1ps 
module Gen_1Hz( input Clk_In, output Clk_Out ); 
 reg rClk_Out; 
 reg [27:0] Counter; 
 always@(posedge Clk_In) begin 
  Counter <= Counter + 1'b1; 
  if ( Counter == 25_000_000) begin 
   Counter <= 0; 
   rClk_Out <= ~rClk_Out; 
  end 
 end 
 assign Clk_Out = rClk_Out; 
endmodule 

Decode_7Seg Verilog File

`timescale 1ns / 1ps 
module Decode_7Seg( D, C, B, A, ledt, leda, ledb, ledc, ledd, lede, ledf, ledg); 
input D, C, B, A; 
output ledt, leda, ledb, ledc, ledd, lede, ledf, ledg; 
reg [7:0] seg_data; 
reg [3:0] DataIn; 
always @* begin 
DataIn = { D, C, B, A }; 
end 
always @(DataIn) 
case (DataIn) 
4'b0000: seg_data = 8'b01111110; 
4'b0001: seg_data = 8'b00110000; 
4'b0010: seg_data = 8'b01101101; 
4'b0011: seg_data = 8'b01111001; 
4'b0100: seg_data = 8'b00110011; 
4'b0101: seg_data = 8'b01011011; 
4'b0110: seg_data = 8'b01011111; 
4'b0111: seg_data = 8'b01110000; 
4'b1000: seg_data = 8'b01111111; 
4'b1001: seg_data = 8'b01111011; 
4'b1010: seg_data = 8'b01110111; 
4'b1011: seg_data = 8'b00011111; 
4'b1100: seg_data = 8'b01001110; 
4'b1101: seg_data = 8'b00111101; 
4'b1110: seg_data = 8'b01001111; 
4'b1111: seg_data = 8'b01000111; 
Endcase 
assign ledt = ~seg_data[7]; // if Active Low(Using ~) 
assign leda = ~seg_data[6]; 
assign ledb = ~seg_data[5]; 
assign ledc = ~seg_data[4]; 
assign ledd = ~seg_data[3]; 
assign lede = ~seg_data[2]; 
assign ledf = ~seg_data[1]; 
assign ledg = ~seg_data[0]; 
endmodule 

Schematic


Port Input/Output ucf File

NET "Clk_50MHz" LOC = P56 | IOSTANDARD = LVTTL; 
NET "Reset_Onboard" LOC = P38 | IOSTANDARD = LVTTL ;  
  
NET "Seg_A"  LOC = P41 ; 
NET "Seg_B"  LOC = P27 ; 
NET "Seg_C"  LOC = P32 ; 
NET "Seg_D"  LOC = P40 ; 
NET "Seg_E"  LOC = P50 ; 
NET "Seg_F"  LOC = P35 ; 
NET "Seg_G"  LOC = P29 ; 
NET "Seg_T"  LOC = P34 ; 

การต่อวงจร


Q05 – MAX7219 Display Control

5.1/4 test Data 32bit Verilog File

`timescale 1ns / 1ps 
module Verilog(input Clk_50MHz, rstCount, output [31:0] oData); 
reg [31:0] cCounter; 
reg [31:0] roData; 
always@(posedge Clk_50MHz or negedge rstCount) begin 
if(rstCount==0) 
roData <= 0; 



else begin 
cCounter <= cCounter + 1'b1; 
if ( cCounter == 1_250_000) begin 
cCounter <= 0; 
roData <= roData + 1'b1; 
roData <= 32'b10110101100100000100100001000110; 
end 
end 
end 
assign oData = roData; 
endmodule 



5.2/4 Driver MAX7219 VHDL File



-- ########################################################### 
-- Driver for MAX7219 with 8 digit 7-segment display 
-- http://stevenmerrifield.com/max7219/M7219.vhdl 
-- sjm 15 May 2017 
-- ########################################################### 
library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
entity drv_MAX7219 is 
port ( 
clk : in std_logic; 
parallel : in std_logic_vector(31 downto 0); 
clk_out : out std_logic; 
data_out : out std_logic; 
load : out std_logic 
); 
end drv_MAX7219; 
-- ########################################################### 
architecture Behavioral of drv_MAX7219 is 
attribute syn_encoding : string; 
type state_machine is (init_1, init_2, init_3, init_4, read_data, dig_7, dig_6, dig_5, 
dig_4, dig_3, dig_2, dig_1, dig_0); 
attribute syn_encoding of state_machine : type is "safe"; 
signal state : state_machine := init_1; 
type driver_machine is (idle, start, clk_data, clk_high, clk_low, finished); 
attribute syn_encoding of driver_machine : type is "safe"; 
signal driver_state : driver_machine := idle; 
signal command : std_logic_vector(15 downto 0) := x"0000"; 
signal driver_start : std_logic := '0'; 
-- ----------------------------------------------------------- 
function hex2seg(num : std_logic_vector(3 downto 0)) return std_logic_vector is 
begin 
case num is 
when "0000" => return("01111110"); -- 0 
when "0001" => return("00110000"); -- 1 
when "0010" => return("01101101"); -- 2 
when "0011" => return("01111001"); -- 3 
when "0100" => return("00110011"); -- 4 
when "0101" => return("01011011"); -- 5 
when "0110" => return("01011111"); -- 6 
when "0111" => return("01110000"); -- 7 
when "1000" => return("01111111"); -- 8 
when "1001" => return("01111011"); -- 9 
when "1010" => return("01110111"); -- A 
when "1011" => return("00011111"); -- b 
when "1100" => return("00001101"); -- c 
when "1101" => return("00111101"); -- d 
when "1110" => return("01001111"); -- E 
when "1111" => return("01000111"); -- F 
when others => return("00000000"); 
end case; 
end hex2seg; 
-- ----------------------------------------------------------- 
-- ########################################################### 
begin -- of Behavioral 
process 
variable counter : integer := 0; 
variable clk_counter : integer := 0; 
variable latch_in : std_logic_vector(31 downto 0) := x"00000000"; 
variable dig0_data : std_logic_vector(7 downto 0) := x"00"; 
variable dig1_data : std_logic_vector(7 downto 0) := x"00"; 
variable dig2_data : std_logic_vector(7 downto 0) := x"00"; 
variable dig3_data : std_logic_vector(7 downto 0) := x"00"; 
variable dig4_data : std_logic_vector(7 downto 0) := x"00"; 
variable dig5_data : std_logic_vector(7 downto 0) := x"00"; 
variable dig6_data : std_logic_vector(7 downto 0) := x"00"; 
variable dig7_data : std_logic_vector(7 downto 0) := x"00"; 
-- =========================================================== 
begin -- of process 
-- ----------------------------------------------------------- 
wait until rising_edge(clk); 
-- ----------------------------------------------------------- 
case state is 
when init_1 => 
if (driver_state = idle) then 
command <= x"0c01"; -- shutdown / normal operation 
driver_state <= start; 
state <= init_2; 
end if; 
when init_2 => 
if (driver_state = idle) then 
command <= x"0900"; -- decode mode 
driver_state <= start; 
state <= init_3; 
end if; 
when init_3 => 
if (driver_state = idle) then 
command <= x"0A04"; -- intensity 
driver_state <= start; 
state <= init_4; 
end if; 
when init_4 => 
if (driver_state = idle) then 
command <= x"0B07"; -- scan limit 
driver_state <= start; 
state <= read_data; 
end if; 
when read_data => 
latch_in := parallel; 
dig7_data := hex2seg(latch_in(31 downto 28)); 
dig6_data := hex2seg(latch_in(27 downto 24)); 
dig5_data := hex2seg(latch_in(23 downto 20)); 
dig4_data := hex2seg(latch_in(19 downto 16)); 
dig3_data := hex2seg(latch_in(15 downto 12)); 
dig2_data := hex2seg(latch_in(11 downto 8)); 
dig1_data := hex2seg(latch_in(7 downto 4)); 
dig0_data := hex2seg(latch_in(3 downto 0)); 
state <= dig_7; 
when dig_7 => 
if (driver_state = idle) then 
command <= x"08" & dig7_data; 
driver_state <= start; 
state <= dig_6; 
end if; 
when dig_6 => 
if (driver_state = idle) then 
command <= x"07" & dig6_data; 
driver_state <= start; 
state <= dig_5; 
end if; 
when dig_5 => 
if (driver_state = idle) then 
command <= x"06" & dig5_data; 
driver_state <= start; 
state <= dig_4; 
end if; 
when dig_4 => 
if (driver_state = idle) then 
command <= x"05" & dig4_data; 
driver_state <= start; 
state <= dig_3; 
end if; 
when dig_3 => 
if (driver_state = idle) then 
command <= x"04" & dig3_data; 
driver_state <= start; 
state <= dig_2; 
end if; 
when dig_2 => 
if (driver_state = idle) then 
command <= x"03" & dig2_data; 
driver_state <= start; 
state <= dig_1; 
end if; 
when dig_1 => 
if (driver_state = idle) then 
command <= x"02" & dig1_data; 
driver_state <= start; 
state <= dig_0; 
end if; 
when dig_0 => 
if (driver_state = idle) then 
command <= x"01" & dig0_data; 
driver_state <= start; 
state <= read_data; 
end if; 
when others => null; 
end case; 
-- ----------------------------------------------------------- 
if (clk_counter < 100) then 
clk_counter := clk_counter + 1; 
else 
clk_counter := 0; 
case driver_state is 
when idle => 
load <= '1'; 
clk_out <= '0'; 
when start => 
load <= '0'; 
counter := 16; 
driver_state <= clk_data; 
when clk_data => 
counter := counter - 1; 
data_out <= command(counter); 
driver_state <= clk_high; 
when clk_high => 
clk_out <= '1'; 
driver_state <= clk_low; 
when clk_low => 
clk_out <= '0'; 
if (counter = 0) then 
load <= '1'; 
driver_state <= finished; 
else 
driver_state <= clk_data; 
end if; 
when finished => 
driver_state <= idle; 
when others => null; 
end case; 

end if; -- clk_counter 
-- ----------------------------------------------------------- 
end process; 
-- =========================================================== 
end Behavioral; 
-- ########################################################### 




5.3/4 Main Schematic File 



5.4/4 Port Input/output ucf File

NET "Clk_50MHz" LOC = P56 | IOSTANDARD = LVTTL ; 
NET "Onboard" LOC = P38 | IOSTANDARD = LVTTL ; 
NET "DIN" LOC = P51 ; 
NET "CLK" LOC = P41 ; 
NET "CS" LOC = P35 ;


ผลลัพธ์ 
 จะเป็นรหัสนักศึกษาเรียงกัน >> B 5 9 0 4 8 4 6

Q06 – Serial Communication – UART Tx

6.1/4 UART Sending Verilog File

module uart_send # ( parameter BAUD_RATE = 115200, 
 parameter CLOCK_SPEED_MHZ = 50) 
 ( input [7:0] data_byte, 
 input start_send, 
 input clk, 
 output tx, 
 output ready); 
 parameter integer CYCLES_WAIT = CLOCK_SPEED_MHZ * 1e6 / BAUD_RATE; 
 parameter IDLE = 0; 
 parameter START_BIT = 1; 
 parameter END_BIT = 2; 
 parameter DATA_BIT = 3; 
 reg [2:0] state = IDLE; 
 reg [15:0] cycle_count = 0; 
 reg [3:0] bit_index = 0; 
 reg [7:0] data; 
 assign tx = state == IDLE ? 1 : 
 state == START_BIT ? 0 : 
 state == END_BIT ? 1 : 
 data[bit_index]; 
 assign ready = state == IDLE; 
 always @(posedge clk) begin 
 if(state != IDLE) 
 data <= data_byte; 
 if(cycle_count == CYCLES_WAIT) cycle_count <= 0; 
 else cycle_count <= cycle_count + 1; 
 if(state == IDLE && start_send) begin 
 state <= START_BIT; 
 cycle_count <= 0; 
 end else if(state == START_BIT && cycle_count == CYCLES_WAIT) begin 
 state <= DATA_BIT; 
 bit_index <= 0; 
 end else if(state == DATA_BIT && cycle_count == CYCLES_WAIT) begin 
 if(bit_index == 7) state <= END_BIT; 
 else bit_index <= bit_index + 1; 
 end else if(state == END_BIT && cycle_count == CYCLES_WAIT) begin 
 state <= IDLE; 
 end 
 end 
endmodule 


6.2/4 UART Test Verilog File

module uart_test #(parameter DelayStep=10000000) 
 ( input clk, n_rst, output start, output [7:0] data ); 
 parameter ASCII_Start = "A"; 
 parameter ASCII_Stop = "Z"; 
 reg [31:0] count = 0; 
 reg [7:0] rData = ASCII_Start; 
 reg [7:0] cData = ASCII_Start; 
 reg rStart = 0; 
 always @(posedge clk or negedge n_rst) 
 if (n_rst==0) 
 begin 
 cData <= ASCII_Start; 
 rData <= ASCII_Start; 
 end 
 else 
 begin 
 if (count == DelayStep) 
 begin 
 count <= 0; 
 cData <= cData + 1'b1; 
 if(cData <= ASCII_Stop) rData <= cData; 
 else if(cData == (ASCII_Stop+1)) rData <= 8'b00001101; 
 else if(cData == (ASCII_Stop+2)) rData <= 8'b00001010; 
 else cData <= ASCII_Start; 
 end 
 else 
 begin 
 count <= count + 1'b1; 
 if (count == 100) rStart <= 1; else rStart <= 0; 
 end 
 end 
 assign data = rData; 
 assign start = rStart; 
endmodule


6.3/4 Main Schematic File



6.4/4 Port Input/Output ucf File

NET "clk" TNM_NET = clk; 
TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50%; 
NET "clk" LOC = P56 | IOSTANDARD = LVTTL; 
NET "rst_n" LOC = P38 | IOSTANDARD = LVTTL; 
NET "tx" LOC = P51 | IOSTANDARD = LVTTL;


6.5 ผลลัพธ์จะเป็นการส่งข้อมูล A-Z ไปเรื่อยๆ