Описание схем с памятью на языке Verilog
Рассмотрим пример D-триггера (D flip-flop). // D-триггер с асинхронным сбросом module d_flipflop(q, d, clk, rst); output q; input d, clk, rst; reg q; // возможность присваивания always @(posedge clk or posedge rst) // список чувствительности if (rst) q = 1’b0; Else q = d; endmodule /* d_flipflop */ Моделирование памяти Для моделирования памяти обычно используется конструкция reg. Примеры reg mem; // один бит reg mem[0:15]; // 16-разрядный регистр reg [0:7] mem [0:31]; // 32 8-разрядных регистров Ключевое слово reg можно использовать как в отношении внутренних данных, так и выходных сигналов (см. пример D-триггера). Замечание. К регистрам нельзя применять непрерывное присваивание. Непрерывное присваивание можно применять только к проводам (net, в частности, wire). Для регистров следует использовать процедурное присваивание. Процедурное присваивание
Примеры // блокируемое присваивание a = 1; b = 2; Begin a = b; b = a; // a == 2, b == 2 End // неблокируемое присваивание a = 1; b = 2; Begin a <= b; b <= a; // a == 2, b == 1 End Always-блоки Примеры always // бесконечный цикл clk = #10 ~clk;
always @(posedge clk) // обработчик события ...
always @(posedge clk or posedge rst) // обработчик нескольких событий ... // Гонка: возможны разные порядки always @(posedge clk) a = b; always @(posedge clk) b = a; // Гонки нет always @(posedge clk) a <= b; always @(posedge clk) b <= a; Конструкция @(событие 1 or... событие n) называется списком чувствительности процесса. Управляющие конструкции Конструкция if if (<expression1>) <statement1>; else if (<expression2>) <statement2>; ... else <default_statement>; Конструкция case case (<expression>) <alternative1>: <statement1>; <alternative2>: <statement2>; ... default: <default_statement>; Endcase Пример. Мультиплексор 4-в-1. module mux4_1(out, i0, i1, i2, i3, s1, s0); output out; input i0, i1, i2, i3; input s1, s0; reg out; always @(s1 or s0 or i0 or i1 or i2 or i3) Begin case ({s1, s0}) 2'b00: out = i0; 2'b01: out = i1; 2'b10: out = i2; 2'b11: out = i3; default: out = 1'bx; Endcase End endmodule /* mux4_1 */ Задание. Описать на языке Verilog модуль управления пешеходным переходом. `timescale 1s/1ms
Домашнее задание. Модуль управления лифтом. Сформулировать требования. Продумать интерфейс. Описать на языке Verilog. Написать тест.
Лекция 3 «Примеры проектирования на языке Verilog» В данной лекции будет рассмотрено несколько примеров проектирования аппаратуры. Цель лекции – продемонстрировать (пусть и в несколько упрощенной форме) основные этапы процесса проектирования аппаратуры (поведенческое проектирование и проектирование на уровне регистровых передач). Пример 0. «Память прямого доступа на 4 слова» ` timescale 1ns/1ps
// RAM consisting of four 32-bit items module ram(clk, rst, val_rd, val_wr, addr_in, data_in, val_out, data_out, is_ready); input clk; input rst; input val_rd; input val_wr; input [1:0] addr_in; input [31:0] data_in; output val_out; output [31:0] data_out; output is_ready;
reg [31:0] mem0; reg [31:0] mem1; reg [31:0] mem2; reg [31:0] mem3;
reg [31:0] result; reg [1:0] state;
// State encoding parameter RAM_IDLE = 2'b00; parameter RAM_READ = 2'b01; parameter RAM_WRITE = 2'b10; parameter RAM_RESULT = 2'b11;
assign is_ready = (state == RAM_IDLE); assign val_out = (state == RAM_RESULT); assign data_out = (state == RAM_RESULT)? result: 32'h0000_0000;
always @(posedge rst) Begin mem0 <= 32'hXXXX_XXXX; mem1 <= 32'hXXXX_XXXX; mem2 <= 32'hXXXX_XXXX; mem3 <= 32'hXXXX_XXXX; result <= 32'hXXXX_XXXX; state <= 2'b00; End
always @(posedge clk) Begin if (state == RAM_IDLE) Begin // Read operation if (~rst & val_rd) Begin state <= RAM_READ;
// Multiplexor 4-to-1 case (addr_in) 2'b00: result <= mem0; 2'b01: result <= mem1; 2'b10: result <= mem2; 2'b11: result <= mem3; Endcase End // Write operation else if (~rst & val_wr) Begin state <= RAM_WRITE; result <= 32'hXXXX_XXXX;
// Demultiplexor 1-to-4 case (addr_in) 2'b00: mem0 <= data_in; 2'b01: mem1 <= data_in; 2'b10: mem2 <= data_in; 2'b11: mem3 <= data_in; Endcase End End Else Begin if (state == RAM_RESULT) Begin state <= RAM_IDLE; End Else Begin state <= RAM_RESULT; End End End endmodule /* ram */ Пример 1. «Очередь FIFO» ` timescale 1ns/1ps
// FIFO queue consisting of four 8-bit items module fifo(clk, rst, val_rd, val_wr, data_in, val_out, data_out, is_full, is_ready); input clk; input rst; input val_rd; input val_wr; input [31:0] data_in; output val_out; output [31:0] data_out; output is_full; output is_ready;
// RAM[i] is available reg val0, val1, val2, val3;
reg [1:0] addr0; reg [1:0] addr1; reg [1:0] addr2; reg [1:0] addr3;
reg [1:0] last;
wire [1:0] free_addr; wire [1:0] addr_in;
assign is_full = val0 & val1 & val2 & val3;
assign free_addr = (~val0? 2'h0: (~val1? 2'h1: (~val2? 2'h2: (~val3? 2'h3: 2'hX))));
assign addr_in = val_wr? free_addr: (val_rd? addr0: 2'h0);
ram memory ( .clk(clk), .rst(rst), .val_rd(val_rd), .val_wr(val_wr), .addr_in(addr_in), .data_in(data_in), .val_out(val_out), .data_out(data_out), .is_ready(is_ready) );
always @(posedge rst) Begin val0 <= 1'b0; val1 <= 1'b0; val2 <= 1'b0; val3 <= 1'b0; addr0 <= 2'hX; addr1 <= 2'hX; addr2 <= 2'hX; addr3 <= 2'hX; last <= 2'h0; End
always @(posedge clk) Begin if (~rst & val_wr) Begin @(val_out);
case (last) 2'h0: begin addr0 <= free_addr; val0 <= 1'b1; last <= 2'h1; End 2'h1: begin addr1 <= free_addr; val1 <= 1'b1; last <= 2'h2; End 2'h2: begin addr2 <= free_addr; val2 <= 1'b1; last <= 2'h3; End 2'h3: begin addr3 <= free_addr; val3 <= 1'b1; last <= 2'h3; End
|