Скачиваний:
29
Добавлен:
09.05.2014
Размер:
359.32 Кб
Скачать

Санкт-Петербургский Государственный Университет Информационнах Технологий, Механики и Оптики

Кафедра вычислительной техники

Лабораторная работа №3

«Разработка цифровых схем с использованием языка

VerilogHDL»

Выполнили

студенты группы 3100

Серженко Дмитрий

Серженко Екатерина

Санкт-Петербург, 2010

Цель работы:

Введение в технологии языкового проектирования цифровой аппаратуры.

Задачи:

  1. Изучение языка Verilog;

  2. Проектирование простейших цифровых устройств с использованием языка Verilog;

  3. Ознакомление со средой цифрового моделирования ModelSim, средствами САПР Quartus для синтеза и временного анализа цифровых схем.

Реализация:

/******************************************************************************

* HAM 7-4 *

******************************************************************************/

module ham74_encoder

(

input wire clk,

input wire rstn,

input wire[7:0] baseadr,

input wire[4:0] count,

input wire start,

input wire[7:0] din,

output wire[7:0] dout,

output wire[7:0] addr,

output reg write_enable

);

reg [3:0] state, next_state;

reg [3:0] mlen;

reg [7:0] maddr;

reg [7:0] read_maddr;

reg [7:0] write_maddr;

reg [7:0] out_reg;

assign addr = maddr;

assign dout = out_reg;

//states

localparam IDLE = 0, INIT = 1, RDMEM = 2, USE_DECODERS = 3,

SAVE1 = 4, SAVE2 = 5;

localparam SAVE_ADDRESS = 0;

//initial $monitor("state = %d, addr=%x, dout=%x\n",

// state, maddr, dout);

// state_machine state register

always @(posedge clk) begin

if (~rstn) state <= IDLE;

else state <= next_state;

end

// state machine next_state logic

always @* begin

write_enable = 0;

next_state = state;

case (state)

IDLE: begin

if (start) next_state = INIT;

end

INIT: begin

next_state = RDMEM;

end

RDMEM: begin

next_state = USE_DECODERS;

end

USE_DECODERS: begin

next_state = SAVE1;

end

SAVE1: begin

next_state = SAVE2;

write_enable = 1;

end

SAVE2: begin

if (mlen == 0) next_state = IDLE;

else next_state = RDMEM;

write_enable = 1;

end

endcase

end

// mlen - length of data array in memory

always @(posedge clk) begin

if (~rstn) mlen <= 0;

else if (start && (state == IDLE) ) mlen <= count;

else if (state == RDMEM) mlen <= mlen - 4'd1;

end

// maddr - current address in memory

always @(posedge clk) begin

if (~rstn) begin

read_maddr <= 0;

write_maddr <= 0;

maddr <= 0;

end else if (start && (state == IDLE) ) begin

read_maddr <= baseadr;

write_maddr <= SAVE_ADDRESS;

end else if (next_state == RDMEM) begin

maddr <= read_maddr;

read_maddr <= read_maddr + 8'd1;

end else if (next_state == SAVE1 || next_state == SAVE2) begin

maddr <= write_maddr;

write_maddr <= write_maddr + 8'd1;

end

end

// ham - encode data using Hammings codes (7-4)

always @(posedge clk) begin

if (next_state == SAVE1) begin

out_reg[3:0] <= din[3:0];

out_reg[4] <= (din[3] ^ din[2] ^ din[0]);

out_reg[5] <= (din[2] ^ din[1] ^ din[0]);

out_reg[6] <= (din[3] ^ din[2] ^ din[1]);

out_reg[7] <= din[4];

end else if (next_state == SAVE2) begin

out_reg[2:0] <= din[7:5];

out_reg[3] <= (din[7] ^ din[6] ^ din[4]);

out_reg[4] <= (din[6] ^ din[5] ^ din[4]);

out_reg[5] <= (din[7] ^ din[6] ^ din[5]);

out_reg[6] <= 0;

out_reg[7] <= 0;

end

end

endmodule

Тестовый модуль:

/******************************************************************************

* HAM_tb *

******************************************************************************/

module ham_tb;

reg clk;

reg rstn;

reg [7:0] baseaddr;

reg start;

reg [4:0] count;

wire [7:0] addr;

wire [7:0] din;

wire write_enable;

wire [7:0] dout;

mem my_mem(clk, addr, dout, write_enable, din);

ham74_encoder ham_enc(clk, rstn, baseaddr, count, start,

din, dout, addr, write_enable);

initial

begin

clk = 0;

forever #10 clk = ~clk;

end

initial

begin

rstn = 0;

start = 0;

baseaddr = 6;

count = 3;

#50 rstn = 1;

@(posedge clk);

@(posedge clk)

start = 1;

@(posedge clk)

start = 0;

end

always @(ham_enc.dout)

$display ("%t : %h",$time, ham_enc.dout);

always @(posedge clk)

if (ham_enc.write_enable) $display ("RESULT = %h", ham_enc.dout);

endmodule

/******************************************************************************

* Behavioral model of memory, for simulation purposes only

*******************************************************************************/

module mem

(

input wire clk,

input wire [7:0] addr,

input wire [7:0] din,

input wire we,

output reg [7:0] dout

);

reg [7:0] memory[15:0];

initial

$readmemh("mem.rom", memory, 0, 15);

always @(posedge clk) begin

dout <= memory [addr];

if ( we )

memory [addr] <= din;

end

endmodule

Эквивалентная программа на Си:

#include <stdio.h>

/* Кодирование Хемминга 7-4.

* На входе байт данных, на выходе 2 байта следующего формата:

* empty|hem2|data2|hem1|data1, где dataN 4 бита, hemN - 3 бита,

* empty - 2 бита.

*/

unsigned char get_hamming_codes(unsigned char data)

{

data = data & 0x0F; /* Очистить старший полубайт */

switch (data) {

case 0b0000:

return 0b000;

case 0b0001:

return 0b011;

case 0b0010:

return 0b110;

case 0b0011:

return 0b101;

case 0b0100:

return 0b111;

case 0b0101:

return 0b100;

case 0b0110:

return 0b001;

case 0b0111:

return 0b010;

case 0b1000:

return 0b101;

case 0b1001:

return 0b110;

case 0b1010:

return 0b011;

case 0b1011:

return 0b000;

case 0b1100:

return 0b010;

case 0b1101:

return 0b001;

case 0b1110:

return 0b100;

case 0b1111:

return 0b111;

default:

return 0; /* Не должно происходить! */

}

}

unsigned short encode_hem74(unsigned char word)

{

unsigned char h_word1, h_word2; /* Слова по 4 бита */

unsigned char ham1, ham2; /* коды хемминга */

unsigned short res; /* h_word1 (4бита)|коды хемминга (3бита)|h_word2... */

h_word1 = word & 0x0F; /* Нижний полубайт */

h_word2 = (word & 0xF0)>>4; /* Сдвинутый верхний */

ham1 = get_hamming_codes(h_word1);

ham2 = get_hamming_codes(h_word2);

res = h_word1;

res |= ham1 << 4;

res |= (unsigned short)h_word2 << 7;

res |= (unsigned short)ham2 << 11;

return res;

}

void encode_words(unsigned char* mem, int mem_len)

{

int i = 0;

for (; i < mem_len; i++)

printf("%x-%x\n", mem[i], encode_hem74(mem[i]));

}

int main()

{

unsigned char mem[4] = {0, 1, 0xAE, 0xF0};

encode_words(mem, 4);

return 0;

}

Временная диаграмма:

Критический путь 3.496 нс. Предельная допустимая частота $283.69 MHz при синтезе на FGPA Cyclone (для стенда SDK 6.1).

Соседние файлы в папке Лаб3