отчеты по лабораторным работам / лабораторная работа №3 / Лаб3 / отчет
.odtСанкт-Петербургский Государственный Университет Информационнах Технологий, Механики и Оптики
Кафедра вычислительной техники
Лабораторная работа №3
«Разработка цифровых схем с использованием языка
VerilogHDL»
Выполнили
студенты группы 3100
Серженко Дмитрий
Серженко Екатерина
Санкт-Петербург, 2010
Цель работы:
Введение в технологии языкового проектирования цифровой аппаратуры.
Задачи:
-
Изучение языка Verilog;
-
Проектирование простейших цифровых устройств с использованием языка Verilog;
-
Ознакомление со средой цифрового моделирования 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).
