# Migen ## Environment Activate the prepared environment every time you use Migen. ``` source ~/.venv/bin/activate ``` ## Creating project Create your own directory in a home directory i. e. **labs**. Create a new subdirectory and name it **lab2**, then create a file **lab2.py** in the subdirectory, after that copy a below text to the file. ``` #!/usr/bin/env python3 from migen import * from litex.build.generic_platform import * from litex.build.altera import AlteraPlatform from litex.build.altera.programmer import USBBlaster # IOs ---------------------------------------------------------------------------------------------- _io = [ # Clk / Rst ("clk10", 0, Pins("N5"), IOStandard("3.3-V LVTTL")), ("clk50", 0, Pins("P11"), IOStandard("3.3-V LVTTL")), ("clk50", 1, Pins("N14"), IOStandard("3.3-V LVTTL")), # Seven Segment ("seven_seg", 0, Pins("C14 E15 C15 C16 E16 D17 C17 D15"), IOStandard("3.3-V LVTTL")), ("seven_seg", 1, Pins("C18 D18 E18 B16 A17 A18 B17 A16"), IOStandard("3.3-V LVTTL")) ] # Platform ----------------------------------------------------------------------------------------- class Platform(AlteraPlatform): default_clk_name = "clk50" default_clk_period = 1e9/50e6 create_rbf = False def __init__(self, toolchain="quartus"): AlteraPlatform.__init__(self, "10M50DAF484C7G", _io, toolchain=toolchain) self.add_platform_command("set_global_assignment -name FAMILY \"MAX 10\"") self.add_platform_command("set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF") self.add_platform_command("set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE \"SINGLE IMAGE WITH ERAM\"") def create_programmer(self): return USBBlaster() def do_finalize(self, fragment): AlteraPlatform.do_finalize(self, fragment) self.add_period_constraint(self.lookup_request("clk10", loose=True), 1e9/10e6) self.add_period_constraint(self.lookup_request("clk50", 0, loose=True), 1e9/50e6) self.add_period_constraint(self.lookup_request("clk50", 1, loose=True), 1e9/50e6) # Design ------------------------------------------------------------------------------------------- class HexDisp(Module): def __init__(self, output_hex0, output_hex1): hex0 = Signal(8) hex1 = Signal(8) self.output_hex0 = output_hex0 self.output_hex1 = output_hex1 self.comb += hex0[0].eq(1) self.comb += hex0[1].eq(0) self.comb += hex0[2].eq(0) self.comb += hex0[3].eq(1) self.comb += hex0[4].eq(1) self.comb += hex0[5].eq(0) self.comb += hex0[6].eq(0) self.comb += hex0[7].eq(1) self.comb += hex1[0].eq(0) self.comb += hex1[1].eq(0) self.comb += hex1[2].eq(1) self.comb += hex1[3].eq(0) self.comb += hex1[4].eq(0) self.comb += hex1[5].eq(1) self.comb += hex1[6].eq(0) self.comb += hex1[7].eq(1) self.comb += self.output_hex0.eq(hex0) self.comb += self.output_hex1.eq(hex1) # Build -------------------------------------------------------------------------------------------- if __name__ == "__main__": # Create our platform (fpga interface) platform = Platform() hex0 = platform.request("seven_seg",0) hex1 = platform.request("seven_seg",1) # Create our module (fpga description) module=HexDisp(hex0, hex1) # Build -------------------------------------------------------------------------------------------- platform.build(module) prog = platform.create_programmer() prog.load_bitstream(os.path.join("build", "top.sof")) ``` ## Running projects Running project is quite simple. To run project add project name as paramter to python3 command, like it is written below. Remember to set directory with project as current directory in console using **cd** command. ``` python3 lab2.py ``` A result should look like below. ![image info](l2i.jpg) ## Comments The presented source code requires some comments, to understand the way how it works. ### Packages Listed packages are necessary for writing in **Migen**, synhtesizing project(**AlteraPlatform**) and programming a board(**USBBlaster**). ``` #!/usr/bin/env python3 from migen import * from litex.build.generic_platform import * from litex.build.altera import AlteraPlatform from litex.build.altera.programmer import USBBlaster ``` ### IOs IOs are used by project to connect design with physical componnents of the board. Pins and theirs connections are described in a board manual. For examples pins C14 E15 C15 C16 E16 D17 C17 D15 are connected with 7-seg LED display, C18 D18 E18 B16 A17 A18 B17 A16 are connected with another 7-seg LED display. ``` # IOs ---------------------------------------------------------------------------------------------- _io = [ # Clk / Rst ("clk10", 0, Pins("N5"), IOStandard("3.3-V LVTTL")), ("clk50", 0, Pins("P11"), IOStandard("3.3-V LVTTL")), ("clk50", 1, Pins("N14"), IOStandard("3.3-V LVTTL")), # Seven Segment ("seven_seg", 0, Pins("C14 E15 C15 C16 E16 D17 C17 D15"), IOStandard("3.3-V LVTTL")), ("seven_seg", 1, Pins("C18 D18 E18 B16 A17 A18 B17 A16"), IOStandard("3.3-V LVTTL")) ] ``` ### Platform Platform class defines basic informations about platform which will run the project. The project will be running on DE10 lite board, so **10M50DAF484C7G** is chosen, which is the id of the chip installed on the board. USBBlaster informs about the way the board will be programmed. In the source you can find also information about the clocks. ``` # Platform ----------------------------------------------------------------------------------------- class Platform(AlteraPlatform): default_clk_name = "clk50" default_clk_period = 1e9/50e6 create_rbf = False def __init__(self, toolchain="quartus"): AlteraPlatform.__init__(self, "10M50DAF484C7G", _io, toolchain=toolchain) self.add_platform_command("set_global_assignment -name FAMILY \"MAX 10\"") self.add_platform_command("set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF") self.add_platform_command("set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE \"SINGLE IMAGE WITH ERAM\"") def create_programmer(self): return USBBlaster() def do_finalize(self, fragment): AlteraPlatform.do_finalize(self, fragment) self.add_period_constraint(self.lookup_request("clk10", loose=True), 1e9/10e6) self.add_period_constraint(self.lookup_request("clk50", 0, loose=True), 1e9/50e6) self.add_period_constraint(self.lookup_request("clk50", 1, loose=True), 1e9/50e6) ``` ### Design This part is an independed part of the code. Describes how your project should work. Because this code will be connected with external devices the outpus are defined. Output_hex0 and output_hex are bridge between FPGA nad 7-seg LED displays. Hex0 and hex1 are internal signals of the class. Rest of code assigns values to variables. [] defines which bit of the signal should be changed. ``` # Design ------------------------------------------------------------------------------------------- class HexDisp(Module): def __init__(self, output_hex0, output_hex1): hex0 = Signal(8) hex1 = Signal(8) self.output_hex0 = output_hex0 self.output_hex1 = output_hex1 self.comb += hex0[0].eq(1) self.comb += hex0[1].eq(0) self.comb += hex0[2].eq(0) self.comb += hex0[3].eq(1) self.comb += hex0[4].eq(1) self.comb += hex0[5].eq(0) self.comb += hex0[6].eq(0) self.comb += hex0[7].eq(1) self.comb += hex1[0].eq(0) self.comb += hex1[1].eq(0) self.comb += hex1[2].eq(1) self.comb += hex1[3].eq(0) self.comb += hex1[4].eq(0) self.comb += hex1[5].eq(1) self.comb += hex1[6].eq(0) self.comb += hex1[7].eq(1) self.comb += self.output_hex0.eq(hex0) self.comb += self.output_hex1.eq(hex1) ``` ### Build This part describes connections between design and an "outside world". ``` # Build -------------------------------------------------------------------------------------------- if __name__ == "__main__": # Create our platform (fpga interface) platform = Platform() hex0 = platform.request("seven_seg",0) hex1 = platform.request("seven_seg",1) # Create our module (fpga description) module=HexDisp(hex0, hex1) # Build -------------------------------------------------------------------------------------------- platform.build(module) prog = platform.create_programmer() prog.load_bitstream(os.path.join("build", "top.sof")) ``` ## Tasks Connect rest of the 7-seg LED displays with the code. To do this add rest of the IOs to IO part, you can find information about connections in user manual. Add additional variables and signals in the design part, add hex3, add hex4…, add output_hex3, add output_hex4…. Extend the Build part, add hex3, add hex4… Set an actual date on the displays. A results should look like an example below. ![image info](l2o.jpg)