1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

概要

paiza.ioでelixirやってみた。
高位合成、やってみた。
練習問題やってみた。
実装編。

練習問題

俺言語で、serial送信を実現せよ。

サンプルコード



defmodule Asm do
	def start_link do
		Agent.start_link(fn ->
			%{u: ""}
		end, name: __MODULE__)
	end
    def a(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                a <= j[9 - b];\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def o(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                o <= " <> b <> ";\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def p(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                p <= " <> b <> ";\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def x(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                x <= " <> b <> ";\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def b(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                b <= " <> b <> ";\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def c(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                c <= " <> b <> ";\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def d(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                d <= " <> b <> ";\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def e(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                e <= " <> b <> ";\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def f(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                f <= " <> b <> ";\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def g(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                g <= " <> b <> ";\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def h(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                h <= " <> b <> ";\n" <>
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def i(a, b) do
		Agent.update(__MODULE__, fn v ->
		
		    vv = String.trim(b, "\"")
		        |> String.codepoints()
                |> Enum.with_index(fn (k, i) ->
	                "\t\tmem[#{i}] <= {1'b1, \"#{k}\", 1'b0};"
                end)
                |> Enum.join("\n")


		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    vv <>
			    "\n                mem[5] <= 0;\n" <>			    
			    "                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def j(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
				"                j <= mem[m];\n" <>
				"                m <= m + 1;\n" <>
				"                if (m > 5) m <= 0;\n" <>
				"                pc <= #{c};\n" <>
			    "            end\n"
			%{v | u: v.u <> str}
		end)
    end
    def print(a, b) do
		Agent.update(__MODULE__, fn v ->
            c = String.to_integer(a)
			if String.match?(b, ~r/\"/) do
			    b = String.replace(b, "\"", "")
		        s = String.split(b, "", trim: true)
                l = String.length(b)
			    str = Enum.reduce(s, ["", c], fn x, y ->
			        pc = Enum.at(y, 1)
			        str = Enum.at(y, 0) <> 
			            "            #{pc}:\n" <>
			            "            begin\n" <>
                        "                out <= \"#{x}\";\n" <>
                        "                pc <= #{pc + 1};\n" <>
                        "            end\n"
                    pc = pc + 1
                    [str, pc]
			    end)
			    str = Enum.at(str, 0) <>
    			    "            #{c + l}:\n" <>
		            "            begin\n" <>
                    "                out <= \" \";\n" <>
                    "                pc <= #{c + 10};\n" <>
                    "            end\n"
			    %{v | u: v.u <> str}
			else
			    str = "            #{c}:\n" <>
			    "            begin\n" <>
                "                out <= a / 10 + 48;\n" <>
                "                pc <= #{c + 1};\n" <>
                "            end\n" <>
                "            #{c + 1}:\n" <>
                "            begin\n" <>
                "                out <= a % 10 + 48;\n" <>
                "                pc <= #{c + 2};\n" <>
                "            end\n" <>
                "            #{c + 2}:\n" <>
                "            begin\n" <>
                "                out <= 32;\n" <>
                "                pc <= #{c + 10};\n" <>
                "            end\n"
                %{v | u: v.u <> str}
			end
		end)
    end
    def loop(a, b) do
		Agent.update(__MODULE__, fn v ->
		    c = String.to_integer(a) + 10
			if String.match?(b, ~r/\*/) do
			    b = String.replace(b, "@", "==")
		        s = String.split(b, "*")
			    str = "            " <> a <> ":\n" <>
			    "            begin\n" <>
			    "                if (" <> Enum.at(s, 0) <> ")\n" <>
			    "                    pc <= " <> Enum.at(s, 1) <> ";\n" <>
			    "                else\n" <>
                "                    pc <= #{c};\n" <>
			    "            end\n"
			    %{v | u: v.u <> str}
		    else
		        str = "            " <> a <> ":\n" <>
		        "            begin\n" <>
		        "                pc <= " <> b <> ";\n" <>
		        "            end\n"
		        %{v | u: v.u <> str}
		    end
		end)
    end
    def make() do
		Agent.get(__MODULE__, fn v ->
            IO.puts "`timescale 1ns/1ps\n" <>
            "module ore(input clk, input rst, input o, input p, input q, output x, output y, output z);\n" <>
	        "    reg [7:0] a;\n" <>
	        "    reg [7:0] b;\n" <>
	        "    reg [7:0] c;\n" <>
	        "    reg [7:0] d;\n" <>
	        "    reg [7:0] e;\n" <>
	        "    reg [7:0] f;\n" <>
	        "    reg [7:0] g;\n" <>
	        "    reg [7:0] h;\n" <>
	        "    reg [7:0] pc;\n" <>
	        "    reg [9:0] mem[31:0];\n" <>
	        "    reg [9:0] i;\n" <>
	        "    reg [7:0] j;\n" <>
	        "    reg [7:0] n;\n" <>
	        "    reg [7:0] m;\n" <>
	        "    reg x;\n" <>
	        "    reg y;\n" <>
	        "    reg z;\n" <>
	        "    wire o;\n" <>
	        "    wire p;\n" <>
	        "    wire q;\n" <>
	        "    always @(posedge clk)\n" <>
	        "    begin\n" <>
		    "        if (!rst)\n" <>
		    "        begin\n" <>
			"            a <= 0;\n" <>
			"            b <= 0;\n" <>
			"            c <= 0;\n" <>
			"            d <= 0;\n" <>
			"            e <= 0;\n" <>
			"            f <= 0;\n" <>
			"            g <= 0;\n" <>
			"            h <= 0;\n" <>
			"            pc <= 10;\n" <>
			"            i <= 0;\n" <>
			"            j <= 0;\n" <>
			"            n <= 0;\n" <>
			"            m <= 0;\n" <>
		    "        end\n" <>
		    "        else\n" <>
	        "        begin\n" <>
		    "            case(pc)\n" <>
		    v.u <>
		    "            endcase\n" <>
	        "        end\n" <>
	        "    end\n" <>
	        "    initial\n" <>
	        "    begin\n" <>
		    "        //$monitor(\" %d  %d\", pc, x);\n" <>
	        "    end\n" <>
		    "endmodule\n\n" <>
            "module test;\n" <>
	        "    reg clk,\n" <>
		    "        rst;\n" <>
	        "    wire [7:0] out;\n" <>
	        "    reg o;\n" <>
	        "    reg p;\n" <>
	        "    reg q;\n" <>
	        "    wire x;\n" <>
	        "    wire y;\n" <>
	        "    wire z;\n" <>
	        "    ore u(.clk(clk), .rst(rst), .o(o), .p(p), .q(q), .x(x), .y(y), .z(z));\n" <>
	        "    initial\n" <>
	        "    begin\n" <>
		    "        clk = 0;\n" <>
		    "        rst = 1;\n" <>	
		    "        o = 0;\n" <>
		    "    #2\n" <>
			"        rst = 0;\n" <>
		    "    #2\n" <>
		    "        rst = 1;\n" <>
		    "    #90000\n" <>
			"        $finish;\n" <>
	        "    end\n" <>
	        "    always\n" <>
		    "    #1\n" <>
			"        clk = ~clk;\n" <>
	        "    always\n" <>
		    "    #868\n" <>
			"        o = ~o;\n" <>
	        "    initial\n" <>
	        "    begin\n" <>
	        "		 $dumpfile(\"test.vcd\");\n" <>
		    "        $dumpvars(0, u);\n" <>
	        "        $display(\" o  p  x \");\n" <>
		    "        $monitor(\" %d %d  %d \", o, p, x);\n" <>
	        "    end\n" <>
            "endmodule\n"
		end)
	end
end

defmodule Main do
	def run(str) do
	    str = String.replace(str, "=", " ")
    	Enum.map(String.split(str, "\n"), fn l ->
		    s = String.split(l, " ")
		    cond do
			Enum.at(s, 1) == "?" ->
				Asm.print(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "#" ->
				Asm.loop(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "a" ->
				Asm.a(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "o" ->
				Asm.o(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "p" ->
				Asm.p(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "x" ->
				Asm.x(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "b" ->
				Asm.b(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "c" ->
				Asm.c(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "d" ->
				Asm.d(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "e" ->
				Asm.e(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "f" ->
				Asm.f(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "g" ->
				Asm.g(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "h" ->
				Asm.h(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "i" ->
				Asm.i(Enum.at(s, 0), Enum.at(s, 2))
			Enum.at(s, 1) == "j" ->
				Asm.j(Enum.at(s, 0), Enum.at(s, 2))
			true ->
				IO.puts l
			end
	    end)
	    Asm.make
	end
end

Asm.start_link

Main.run("""
10 x=1
20 i="hello"
30 j=i
40 #=j@0*200
50 #=b@9*150
60 #=o@1*80
70 #=60
80 a=j
90 #=a@1*120
100 x=1
110 #=130
120 x=0
130 #=o@0*170
140 #=130
150 b=0
160 #=30
170 b=b+1
180 #=50
200 #=200
""")




実行結果


`timescale 1ns/1ps
module ore(input clk, input rst, input o, input p, input q, output x, output y, output z);
    reg [7:0] a;
    reg [7:0] b;
    reg [7:0] c;
    reg [7:0] d;
    reg [7:0] e;
    reg [7:0] f;
    reg [7:0] g;
    reg [7:0] h;
    reg [7:0] pc;
    reg [9:0] mem[31:0];
    reg [9:0] i;
    reg [7:0] j;
    reg [7:0] n;
    reg [7:0] m;
    reg x;
    reg y;
    reg z;
    wire o;
    wire p;
    wire q;
    always @(posedge clk)
    begin
        if (!rst)
        begin
            a <= 0;
            b <= 0;
            c <= 0;
            d <= 0;
            e <= 0;
            f <= 0;
            g <= 0;
            h <= 0;
            pc <= 10;
            i <= 0;
            j <= 0;
            n <= 0;
            m <= 0;
        end
        else
        begin
            case(pc)
            10:
            begin
                x <= 1;
                pc <= 20;
            end
            20:
            begin
		mem[0] <= {1'b1, "h", 1'b0};
		mem[1] <= {1'b1, "e", 1'b0};
		mem[2] <= {1'b1, "l", 1'b0};
		mem[3] <= {1'b1, "l", 1'b0};
		mem[4] <= {1'b1, "o", 1'b0};
                mem[5] <= 0;
                pc <= 30;
            end
            30:
            begin
                j <= mem[m];
                m <= m + 1;
                if (m > 5) m <= 0;
                pc <= 40;
            end
            40:
            begin
                if (j==0)
                    pc <= 200;
                else
                    pc <= 50;
            end
            50:
            begin
                if (b==9)
                    pc <= 150;
                else
                    pc <= 60;
            end
            60:
            begin
                if (o==1)
                    pc <= 80;
                else
                    pc <= 70;
            end
            70:
            begin
                pc <= 60;
            end
            80:
            begin
                a <= j[9 - b];
                pc <= 90;
            end
            90:
            begin
                if (a==1)
                    pc <= 120;
                else
                    pc <= 100;
            end
            100:
            begin
                x <= 1;
                pc <= 110;
            end
            110:
            begin
                pc <= 130;
            end
            120:
            begin
                x <= 0;
                pc <= 130;
            end
            130:
            begin
                if (o==0)
                    pc <= 170;
                else
                    pc <= 140;
            end
            140:
            begin
                pc <= 130;
            end
            150:
            begin
                b <= 0;
                pc <= 160;
            end
            160:
            begin
                pc <= 30;
            end
            170:
            begin
                b <= b+1;
                pc <= 180;
            end
            180:
            begin
                pc <= 50;
            end
            200:
            begin
                pc <= 200;
            end
            endcase
        end
    end
    initial
    begin
        //$monitor(" %d  %d", pc, x);
    end
endmodule

module test;
    reg clk,
        rst;
    wire [7:0] out;
    reg o;
    reg p;
    reg q;
    wire x;
    wire y;
    wire z;
    ore u(.clk(clk), .rst(rst), .o(o), .p(p), .q(q), .x(x), .y(y), .z(z));
    initial
    begin
        clk = 0;
        rst = 1;
        o = 0;
    #2
        rst = 0;
    #2
        rst = 1;
    #90000
        $finish;
    end
    always
    #1
        clk = ~clk;
    always
    #868
        o = ~o;
    initial
    begin
		 $dumpfile("test.vcd");
        $dumpvars(0, u);
        $display(" o  p  x ");
        $monitor(" %d %d  %d ", o, p, x);
    end
endmodule

写真

image.png

成果物

以上。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?