概要
windowsでiverilogやってみた。
verilog見つけたので、やってみた。
参考にしたページ
サンプルコード
`timescale 1ns/1ps
`default_nettype none
module UART_RX #(parameter DIV_WID = 8, parameter DIV_CNT = 8'hAE)(input wire i_rst_n, input wire i_clk, input wire i_UART_RX, output wire[7:0] o_dat, output wire o_ena);
reg [2:0] rx;
reg busy;
reg [DIV_WID - 1:0] div;
reg [4:0] cnt;
reg [9:0] sp_ff;
reg chk_trg;
reg [7:0] dat;
reg ena;
wire dt_get;
wire start;
wire fin;
assign start = (rx[2:1] == 2'b10) & (busy == 1'b0) ? 1'b1 : 1'b0;
assign fin = (cnt == 5'd9) & (dt_get == 1'b1) ? 1'b1 : 1 'b0;
assign dt_get = (busy == 1'b1) & (div == 8'd0) ? 1'b1 : 1'b0;
assign o_dat = dat;
assign o_ena = ena;
always@(posedge i_clk or negedge i_rst_n)
begin
if (~i_rst_n)
rx <= 3'b111;
else
rx <= {rx[1:0], i_UART_RX};
end
always@(posedge i_clk or negedge i_rst_n)
begin
if (~i_rst_n)
busy <= 1'b0;
else if (start)
busy <= 1'b1;
else if (fin)
busy <= 1'b0;
end
always@(posedge i_clk or negedge i_rst_n)
begin
if (~i_rst_n)
div <= 8'd0;
else if (start)
div <= { 1'b0, DIV_CNT[DIV_WID - 1:1] };
else if (busy)
begin
if (div == 8'd0)
div <= DIV_CNT;
else
div <= div - 1;
end
else
div <= 8'd0;
end
always@(posedge i_clk or negedge i_rst_n)
begin
if (~i_rst_n)
cnt <= 5'd0;
else if (start)
cnt <= 5'd0;
else if (dt_get)
cnt <= cnt + 1;
end
always@(posedge i_clk or negedge i_rst_n)
begin
if (~i_rst_n)
sp_ff <= 10'h3FF;
else if (dt_get)
sp_ff <= { rx[2], sp_ff[9:1] };
end
always@(posedge i_clk or negedge i_rst_n)
begin
if (~i_rst_n)
chk_trg <= 1'b0;
else
chk_trg <= fin;
end
always@(posedge i_clk or negedge i_rst_n)
begin
if (~i_rst_n)
begin
dat <= 8'h00;
ena <= 1'b0;
end
else if ((chk_trg == 1'b1) & (sp_ff[0] == 1'b0) & (sp_ff[9] == 1'b1))
begin
dat <= sp_ff[8:1];
ena <= 1'b1;
end
else
begin
dat <= dat;
ena <= 1'b0;
end
end
endmodule
module test();
reg i_rst_n = 1'b0;
reg i_clk = 1'b0;
wire [7:0] o_dat;
wire o_ena;
reg uart_rx_in = 1'b1;
task T_UART_RX;
parameter RATE = 115200;
input [7:0] dat;
integer i;
time BIT_CYC;
begin
$display("UART input start : 0x%2X", dat);
BIT_CYC = 1000000000 / RATE;
uart_rx_in = 1'b0;
#BIT_CYC;
for(i = 0; i < 8; i = i + 1)
begin
uart_rx_in = dat[i];
#BIT_CYC;
end
uart_rx_in = 1'b1;
#BIT_CYC;
end
endtask
UART_RX DUT(.i_rst_n (i_rst_n), .i_clk(i_clk), .i_UART_RX(uart_rx_in), .o_dat(o_dat), .o_ena(o_ena));
always
#25
i_clk = ~i_clk;
initial
begin
$dumpfile("test.vcd");
$dumpvars(0, DUT);
#120
i_rst_n = 1'b1;
#5000;
T_UART_RX (8'h65);
#50000;
T_UART_RX (8'h39);
#120
$finish;
end
endmodule
写真
以上。